1*62c56f98SSadaf Ebrahimi /*
2*62c56f98SSadaf Ebrahimi * Low-level modular bignum functions
3*62c56f98SSadaf Ebrahimi *
4*62c56f98SSadaf Ebrahimi * Copyright The Mbed TLS Contributors
5*62c56f98SSadaf Ebrahimi * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6*62c56f98SSadaf Ebrahimi */
7*62c56f98SSadaf Ebrahimi
8*62c56f98SSadaf Ebrahimi #include "common.h"
9*62c56f98SSadaf Ebrahimi
10*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_ECP_WITH_MPI_UINT)
11*62c56f98SSadaf Ebrahimi
12*62c56f98SSadaf Ebrahimi #include <string.h>
13*62c56f98SSadaf Ebrahimi
14*62c56f98SSadaf Ebrahimi #include "mbedtls/error.h"
15*62c56f98SSadaf Ebrahimi #include "mbedtls/platform_util.h"
16*62c56f98SSadaf Ebrahimi
17*62c56f98SSadaf Ebrahimi #include "mbedtls/platform.h"
18*62c56f98SSadaf Ebrahimi
19*62c56f98SSadaf Ebrahimi #include "bignum_core.h"
20*62c56f98SSadaf Ebrahimi #include "bignum_mod_raw.h"
21*62c56f98SSadaf Ebrahimi #include "bignum_mod.h"
22*62c56f98SSadaf Ebrahimi #include "constant_time_internal.h"
23*62c56f98SSadaf Ebrahimi
24*62c56f98SSadaf Ebrahimi #include "bignum_mod_raw_invasive.h"
25*62c56f98SSadaf Ebrahimi
mbedtls_mpi_mod_raw_cond_assign(mbedtls_mpi_uint * X,const mbedtls_mpi_uint * A,const mbedtls_mpi_mod_modulus * N,unsigned char assign)26*62c56f98SSadaf Ebrahimi void mbedtls_mpi_mod_raw_cond_assign(mbedtls_mpi_uint *X,
27*62c56f98SSadaf Ebrahimi const mbedtls_mpi_uint *A,
28*62c56f98SSadaf Ebrahimi const mbedtls_mpi_mod_modulus *N,
29*62c56f98SSadaf Ebrahimi unsigned char assign)
30*62c56f98SSadaf Ebrahimi {
31*62c56f98SSadaf Ebrahimi mbedtls_mpi_core_cond_assign(X, A, N->limbs, mbedtls_ct_bool(assign));
32*62c56f98SSadaf Ebrahimi }
33*62c56f98SSadaf Ebrahimi
mbedtls_mpi_mod_raw_cond_swap(mbedtls_mpi_uint * X,mbedtls_mpi_uint * Y,const mbedtls_mpi_mod_modulus * N,unsigned char swap)34*62c56f98SSadaf Ebrahimi void mbedtls_mpi_mod_raw_cond_swap(mbedtls_mpi_uint *X,
35*62c56f98SSadaf Ebrahimi mbedtls_mpi_uint *Y,
36*62c56f98SSadaf Ebrahimi const mbedtls_mpi_mod_modulus *N,
37*62c56f98SSadaf Ebrahimi unsigned char swap)
38*62c56f98SSadaf Ebrahimi {
39*62c56f98SSadaf Ebrahimi mbedtls_mpi_core_cond_swap(X, Y, N->limbs, mbedtls_ct_bool(swap));
40*62c56f98SSadaf Ebrahimi }
41*62c56f98SSadaf Ebrahimi
mbedtls_mpi_mod_raw_read(mbedtls_mpi_uint * X,const mbedtls_mpi_mod_modulus * N,const unsigned char * input,size_t input_length,mbedtls_mpi_mod_ext_rep ext_rep)42*62c56f98SSadaf Ebrahimi int mbedtls_mpi_mod_raw_read(mbedtls_mpi_uint *X,
43*62c56f98SSadaf Ebrahimi const mbedtls_mpi_mod_modulus *N,
44*62c56f98SSadaf Ebrahimi const unsigned char *input,
45*62c56f98SSadaf Ebrahimi size_t input_length,
46*62c56f98SSadaf Ebrahimi mbedtls_mpi_mod_ext_rep ext_rep)
47*62c56f98SSadaf Ebrahimi {
48*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
49*62c56f98SSadaf Ebrahimi
50*62c56f98SSadaf Ebrahimi switch (ext_rep) {
51*62c56f98SSadaf Ebrahimi case MBEDTLS_MPI_MOD_EXT_REP_LE:
52*62c56f98SSadaf Ebrahimi ret = mbedtls_mpi_core_read_le(X, N->limbs,
53*62c56f98SSadaf Ebrahimi input, input_length);
54*62c56f98SSadaf Ebrahimi break;
55*62c56f98SSadaf Ebrahimi case MBEDTLS_MPI_MOD_EXT_REP_BE:
56*62c56f98SSadaf Ebrahimi ret = mbedtls_mpi_core_read_be(X, N->limbs,
57*62c56f98SSadaf Ebrahimi input, input_length);
58*62c56f98SSadaf Ebrahimi break;
59*62c56f98SSadaf Ebrahimi default:
60*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
61*62c56f98SSadaf Ebrahimi }
62*62c56f98SSadaf Ebrahimi
63*62c56f98SSadaf Ebrahimi if (ret != 0) {
64*62c56f98SSadaf Ebrahimi goto cleanup;
65*62c56f98SSadaf Ebrahimi }
66*62c56f98SSadaf Ebrahimi
67*62c56f98SSadaf Ebrahimi if (!mbedtls_mpi_core_lt_ct(X, N->p, N->limbs)) {
68*62c56f98SSadaf Ebrahimi ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
69*62c56f98SSadaf Ebrahimi goto cleanup;
70*62c56f98SSadaf Ebrahimi }
71*62c56f98SSadaf Ebrahimi
72*62c56f98SSadaf Ebrahimi cleanup:
73*62c56f98SSadaf Ebrahimi
74*62c56f98SSadaf Ebrahimi return ret;
75*62c56f98SSadaf Ebrahimi }
76*62c56f98SSadaf Ebrahimi
mbedtls_mpi_mod_raw_write(const mbedtls_mpi_uint * A,const mbedtls_mpi_mod_modulus * N,unsigned char * output,size_t output_length,mbedtls_mpi_mod_ext_rep ext_rep)77*62c56f98SSadaf Ebrahimi int mbedtls_mpi_mod_raw_write(const mbedtls_mpi_uint *A,
78*62c56f98SSadaf Ebrahimi const mbedtls_mpi_mod_modulus *N,
79*62c56f98SSadaf Ebrahimi unsigned char *output,
80*62c56f98SSadaf Ebrahimi size_t output_length,
81*62c56f98SSadaf Ebrahimi mbedtls_mpi_mod_ext_rep ext_rep)
82*62c56f98SSadaf Ebrahimi {
83*62c56f98SSadaf Ebrahimi switch (ext_rep) {
84*62c56f98SSadaf Ebrahimi case MBEDTLS_MPI_MOD_EXT_REP_LE:
85*62c56f98SSadaf Ebrahimi return mbedtls_mpi_core_write_le(A, N->limbs,
86*62c56f98SSadaf Ebrahimi output, output_length);
87*62c56f98SSadaf Ebrahimi case MBEDTLS_MPI_MOD_EXT_REP_BE:
88*62c56f98SSadaf Ebrahimi return mbedtls_mpi_core_write_be(A, N->limbs,
89*62c56f98SSadaf Ebrahimi output, output_length);
90*62c56f98SSadaf Ebrahimi default:
91*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
92*62c56f98SSadaf Ebrahimi }
93*62c56f98SSadaf Ebrahimi }
94*62c56f98SSadaf Ebrahimi
mbedtls_mpi_mod_raw_sub(mbedtls_mpi_uint * X,const mbedtls_mpi_uint * A,const mbedtls_mpi_uint * B,const mbedtls_mpi_mod_modulus * N)95*62c56f98SSadaf Ebrahimi void mbedtls_mpi_mod_raw_sub(mbedtls_mpi_uint *X,
96*62c56f98SSadaf Ebrahimi const mbedtls_mpi_uint *A,
97*62c56f98SSadaf Ebrahimi const mbedtls_mpi_uint *B,
98*62c56f98SSadaf Ebrahimi const mbedtls_mpi_mod_modulus *N)
99*62c56f98SSadaf Ebrahimi {
100*62c56f98SSadaf Ebrahimi mbedtls_mpi_uint c = mbedtls_mpi_core_sub(X, A, B, N->limbs);
101*62c56f98SSadaf Ebrahimi
102*62c56f98SSadaf Ebrahimi (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) c);
103*62c56f98SSadaf Ebrahimi }
104*62c56f98SSadaf Ebrahimi
105*62c56f98SSadaf Ebrahimi MBEDTLS_STATIC_TESTABLE
mbedtls_mpi_mod_raw_fix_quasi_reduction(mbedtls_mpi_uint * X,const mbedtls_mpi_mod_modulus * N)106*62c56f98SSadaf Ebrahimi void mbedtls_mpi_mod_raw_fix_quasi_reduction(mbedtls_mpi_uint *X,
107*62c56f98SSadaf Ebrahimi const mbedtls_mpi_mod_modulus *N)
108*62c56f98SSadaf Ebrahimi {
109*62c56f98SSadaf Ebrahimi mbedtls_mpi_uint c = mbedtls_mpi_core_sub(X, X, N->p, N->limbs);
110*62c56f98SSadaf Ebrahimi
111*62c56f98SSadaf Ebrahimi (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) c);
112*62c56f98SSadaf Ebrahimi }
113*62c56f98SSadaf Ebrahimi
114*62c56f98SSadaf Ebrahimi
mbedtls_mpi_mod_raw_mul(mbedtls_mpi_uint * X,const mbedtls_mpi_uint * A,const mbedtls_mpi_uint * B,const mbedtls_mpi_mod_modulus * N,mbedtls_mpi_uint * T)115*62c56f98SSadaf Ebrahimi void mbedtls_mpi_mod_raw_mul(mbedtls_mpi_uint *X,
116*62c56f98SSadaf Ebrahimi const mbedtls_mpi_uint *A,
117*62c56f98SSadaf Ebrahimi const mbedtls_mpi_uint *B,
118*62c56f98SSadaf Ebrahimi const mbedtls_mpi_mod_modulus *N,
119*62c56f98SSadaf Ebrahimi mbedtls_mpi_uint *T)
120*62c56f98SSadaf Ebrahimi {
121*62c56f98SSadaf Ebrahimi /* Standard (A * B) multiplication stored into pre-allocated T
122*62c56f98SSadaf Ebrahimi * buffer of fixed limb size of (2N + 1).
123*62c56f98SSadaf Ebrahimi *
124*62c56f98SSadaf Ebrahimi * The space may not not fully filled by when
125*62c56f98SSadaf Ebrahimi * MBEDTLS_MPI_MOD_REP_OPT_RED is used. */
126*62c56f98SSadaf Ebrahimi const size_t T_limbs = BITS_TO_LIMBS(N->bits) * 2;
127*62c56f98SSadaf Ebrahimi switch (N->int_rep) {
128*62c56f98SSadaf Ebrahimi case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
129*62c56f98SSadaf Ebrahimi mbedtls_mpi_core_montmul(X, A, B, N->limbs, N->p, N->limbs,
130*62c56f98SSadaf Ebrahimi N->rep.mont.mm, T);
131*62c56f98SSadaf Ebrahimi break;
132*62c56f98SSadaf Ebrahimi case MBEDTLS_MPI_MOD_REP_OPT_RED:
133*62c56f98SSadaf Ebrahimi mbedtls_mpi_core_mul(T, A, N->limbs, B, N->limbs);
134*62c56f98SSadaf Ebrahimi
135*62c56f98SSadaf Ebrahimi /* Optimised Reduction */
136*62c56f98SSadaf Ebrahimi (*N->rep.ored.modp)(T, T_limbs);
137*62c56f98SSadaf Ebrahimi
138*62c56f98SSadaf Ebrahimi /* Convert back to canonical representation */
139*62c56f98SSadaf Ebrahimi mbedtls_mpi_mod_raw_fix_quasi_reduction(T, N);
140*62c56f98SSadaf Ebrahimi memcpy(X, T, N->limbs * sizeof(mbedtls_mpi_uint));
141*62c56f98SSadaf Ebrahimi break;
142*62c56f98SSadaf Ebrahimi default:
143*62c56f98SSadaf Ebrahimi break;
144*62c56f98SSadaf Ebrahimi }
145*62c56f98SSadaf Ebrahimi
146*62c56f98SSadaf Ebrahimi }
147*62c56f98SSadaf Ebrahimi
mbedtls_mpi_mod_raw_inv_prime_working_limbs(size_t AN_limbs)148*62c56f98SSadaf Ebrahimi size_t mbedtls_mpi_mod_raw_inv_prime_working_limbs(size_t AN_limbs)
149*62c56f98SSadaf Ebrahimi {
150*62c56f98SSadaf Ebrahimi /* mbedtls_mpi_mod_raw_inv_prime() needs a temporary for the exponent,
151*62c56f98SSadaf Ebrahimi * which will be the same size as the modulus and input (AN_limbs),
152*62c56f98SSadaf Ebrahimi * and additional space to pass to mbedtls_mpi_core_exp_mod(). */
153*62c56f98SSadaf Ebrahimi return AN_limbs +
154*62c56f98SSadaf Ebrahimi mbedtls_mpi_core_exp_mod_working_limbs(AN_limbs, AN_limbs);
155*62c56f98SSadaf Ebrahimi }
156*62c56f98SSadaf Ebrahimi
mbedtls_mpi_mod_raw_inv_prime(mbedtls_mpi_uint * X,const mbedtls_mpi_uint * A,const mbedtls_mpi_uint * N,size_t AN_limbs,const mbedtls_mpi_uint * RR,mbedtls_mpi_uint * T)157*62c56f98SSadaf Ebrahimi void mbedtls_mpi_mod_raw_inv_prime(mbedtls_mpi_uint *X,
158*62c56f98SSadaf Ebrahimi const mbedtls_mpi_uint *A,
159*62c56f98SSadaf Ebrahimi const mbedtls_mpi_uint *N,
160*62c56f98SSadaf Ebrahimi size_t AN_limbs,
161*62c56f98SSadaf Ebrahimi const mbedtls_mpi_uint *RR,
162*62c56f98SSadaf Ebrahimi mbedtls_mpi_uint *T)
163*62c56f98SSadaf Ebrahimi {
164*62c56f98SSadaf Ebrahimi /* Inversion by power: g^|G| = 1 => g^(-1) = g^(|G|-1), and
165*62c56f98SSadaf Ebrahimi * |G| = N - 1, so we want
166*62c56f98SSadaf Ebrahimi * g^(|G|-1) = g^(N - 2)
167*62c56f98SSadaf Ebrahimi */
168*62c56f98SSadaf Ebrahimi
169*62c56f98SSadaf Ebrahimi /* Use the first AN_limbs of T to hold N - 2 */
170*62c56f98SSadaf Ebrahimi mbedtls_mpi_uint *Nminus2 = T;
171*62c56f98SSadaf Ebrahimi (void) mbedtls_mpi_core_sub_int(Nminus2, N, 2, AN_limbs);
172*62c56f98SSadaf Ebrahimi
173*62c56f98SSadaf Ebrahimi /* Rest of T is given to exp_mod for its working space */
174*62c56f98SSadaf Ebrahimi mbedtls_mpi_core_exp_mod(X,
175*62c56f98SSadaf Ebrahimi A, N, AN_limbs, Nminus2, AN_limbs,
176*62c56f98SSadaf Ebrahimi RR, T + AN_limbs);
177*62c56f98SSadaf Ebrahimi }
178*62c56f98SSadaf Ebrahimi
mbedtls_mpi_mod_raw_add(mbedtls_mpi_uint * X,const mbedtls_mpi_uint * A,const mbedtls_mpi_uint * B,const mbedtls_mpi_mod_modulus * N)179*62c56f98SSadaf Ebrahimi void mbedtls_mpi_mod_raw_add(mbedtls_mpi_uint *X,
180*62c56f98SSadaf Ebrahimi const mbedtls_mpi_uint *A,
181*62c56f98SSadaf Ebrahimi const mbedtls_mpi_uint *B,
182*62c56f98SSadaf Ebrahimi const mbedtls_mpi_mod_modulus *N)
183*62c56f98SSadaf Ebrahimi {
184*62c56f98SSadaf Ebrahimi mbedtls_mpi_uint carry, borrow;
185*62c56f98SSadaf Ebrahimi carry = mbedtls_mpi_core_add(X, A, B, N->limbs);
186*62c56f98SSadaf Ebrahimi borrow = mbedtls_mpi_core_sub(X, X, N->p, N->limbs);
187*62c56f98SSadaf Ebrahimi (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) (carry ^ borrow));
188*62c56f98SSadaf Ebrahimi }
189*62c56f98SSadaf Ebrahimi
mbedtls_mpi_mod_raw_canonical_to_modulus_rep(mbedtls_mpi_uint * X,const mbedtls_mpi_mod_modulus * N)190*62c56f98SSadaf Ebrahimi int mbedtls_mpi_mod_raw_canonical_to_modulus_rep(
191*62c56f98SSadaf Ebrahimi mbedtls_mpi_uint *X,
192*62c56f98SSadaf Ebrahimi const mbedtls_mpi_mod_modulus *N)
193*62c56f98SSadaf Ebrahimi {
194*62c56f98SSadaf Ebrahimi switch (N->int_rep) {
195*62c56f98SSadaf Ebrahimi case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
196*62c56f98SSadaf Ebrahimi return mbedtls_mpi_mod_raw_to_mont_rep(X, N);
197*62c56f98SSadaf Ebrahimi case MBEDTLS_MPI_MOD_REP_OPT_RED:
198*62c56f98SSadaf Ebrahimi return 0;
199*62c56f98SSadaf Ebrahimi default:
200*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
201*62c56f98SSadaf Ebrahimi }
202*62c56f98SSadaf Ebrahimi }
203*62c56f98SSadaf Ebrahimi
mbedtls_mpi_mod_raw_modulus_to_canonical_rep(mbedtls_mpi_uint * X,const mbedtls_mpi_mod_modulus * N)204*62c56f98SSadaf Ebrahimi int mbedtls_mpi_mod_raw_modulus_to_canonical_rep(
205*62c56f98SSadaf Ebrahimi mbedtls_mpi_uint *X,
206*62c56f98SSadaf Ebrahimi const mbedtls_mpi_mod_modulus *N)
207*62c56f98SSadaf Ebrahimi {
208*62c56f98SSadaf Ebrahimi switch (N->int_rep) {
209*62c56f98SSadaf Ebrahimi case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
210*62c56f98SSadaf Ebrahimi return mbedtls_mpi_mod_raw_from_mont_rep(X, N);
211*62c56f98SSadaf Ebrahimi case MBEDTLS_MPI_MOD_REP_OPT_RED:
212*62c56f98SSadaf Ebrahimi return 0;
213*62c56f98SSadaf Ebrahimi default:
214*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
215*62c56f98SSadaf Ebrahimi }
216*62c56f98SSadaf Ebrahimi }
217*62c56f98SSadaf Ebrahimi
mbedtls_mpi_mod_raw_random(mbedtls_mpi_uint * X,mbedtls_mpi_uint min,const mbedtls_mpi_mod_modulus * N,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)218*62c56f98SSadaf Ebrahimi int mbedtls_mpi_mod_raw_random(mbedtls_mpi_uint *X,
219*62c56f98SSadaf Ebrahimi mbedtls_mpi_uint min,
220*62c56f98SSadaf Ebrahimi const mbedtls_mpi_mod_modulus *N,
221*62c56f98SSadaf Ebrahimi int (*f_rng)(void *, unsigned char *, size_t),
222*62c56f98SSadaf Ebrahimi void *p_rng)
223*62c56f98SSadaf Ebrahimi {
224*62c56f98SSadaf Ebrahimi int ret = mbedtls_mpi_core_random(X, min, N->p, N->limbs, f_rng, p_rng);
225*62c56f98SSadaf Ebrahimi if (ret != 0) {
226*62c56f98SSadaf Ebrahimi return ret;
227*62c56f98SSadaf Ebrahimi }
228*62c56f98SSadaf Ebrahimi return mbedtls_mpi_mod_raw_canonical_to_modulus_rep(X, N);
229*62c56f98SSadaf Ebrahimi }
230*62c56f98SSadaf Ebrahimi
mbedtls_mpi_mod_raw_to_mont_rep(mbedtls_mpi_uint * X,const mbedtls_mpi_mod_modulus * N)231*62c56f98SSadaf Ebrahimi int mbedtls_mpi_mod_raw_to_mont_rep(mbedtls_mpi_uint *X,
232*62c56f98SSadaf Ebrahimi const mbedtls_mpi_mod_modulus *N)
233*62c56f98SSadaf Ebrahimi {
234*62c56f98SSadaf Ebrahimi mbedtls_mpi_uint *T;
235*62c56f98SSadaf Ebrahimi const size_t t_limbs = mbedtls_mpi_core_montmul_working_limbs(N->limbs);
236*62c56f98SSadaf Ebrahimi
237*62c56f98SSadaf Ebrahimi if ((T = (mbedtls_mpi_uint *) mbedtls_calloc(t_limbs, ciL)) == NULL) {
238*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_MPI_ALLOC_FAILED;
239*62c56f98SSadaf Ebrahimi }
240*62c56f98SSadaf Ebrahimi
241*62c56f98SSadaf Ebrahimi mbedtls_mpi_core_to_mont_rep(X, X, N->p, N->limbs,
242*62c56f98SSadaf Ebrahimi N->rep.mont.mm, N->rep.mont.rr, T);
243*62c56f98SSadaf Ebrahimi
244*62c56f98SSadaf Ebrahimi mbedtls_zeroize_and_free(T, t_limbs * ciL);
245*62c56f98SSadaf Ebrahimi return 0;
246*62c56f98SSadaf Ebrahimi }
247*62c56f98SSadaf Ebrahimi
mbedtls_mpi_mod_raw_from_mont_rep(mbedtls_mpi_uint * X,const mbedtls_mpi_mod_modulus * N)248*62c56f98SSadaf Ebrahimi int mbedtls_mpi_mod_raw_from_mont_rep(mbedtls_mpi_uint *X,
249*62c56f98SSadaf Ebrahimi const mbedtls_mpi_mod_modulus *N)
250*62c56f98SSadaf Ebrahimi {
251*62c56f98SSadaf Ebrahimi const size_t t_limbs = mbedtls_mpi_core_montmul_working_limbs(N->limbs);
252*62c56f98SSadaf Ebrahimi mbedtls_mpi_uint *T;
253*62c56f98SSadaf Ebrahimi
254*62c56f98SSadaf Ebrahimi if ((T = (mbedtls_mpi_uint *) mbedtls_calloc(t_limbs, ciL)) == NULL) {
255*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_MPI_ALLOC_FAILED;
256*62c56f98SSadaf Ebrahimi }
257*62c56f98SSadaf Ebrahimi
258*62c56f98SSadaf Ebrahimi mbedtls_mpi_core_from_mont_rep(X, X, N->p, N->limbs, N->rep.mont.mm, T);
259*62c56f98SSadaf Ebrahimi
260*62c56f98SSadaf Ebrahimi mbedtls_zeroize_and_free(T, t_limbs * ciL);
261*62c56f98SSadaf Ebrahimi return 0;
262*62c56f98SSadaf Ebrahimi }
263*62c56f98SSadaf Ebrahimi
mbedtls_mpi_mod_raw_neg(mbedtls_mpi_uint * X,const mbedtls_mpi_uint * A,const mbedtls_mpi_mod_modulus * N)264*62c56f98SSadaf Ebrahimi void mbedtls_mpi_mod_raw_neg(mbedtls_mpi_uint *X,
265*62c56f98SSadaf Ebrahimi const mbedtls_mpi_uint *A,
266*62c56f98SSadaf Ebrahimi const mbedtls_mpi_mod_modulus *N)
267*62c56f98SSadaf Ebrahimi {
268*62c56f98SSadaf Ebrahimi mbedtls_mpi_core_sub(X, N->p, A, N->limbs);
269*62c56f98SSadaf Ebrahimi
270*62c56f98SSadaf Ebrahimi /* If A=0 initially, then X=N now. Detect this by
271*62c56f98SSadaf Ebrahimi * subtracting N and catching the carry. */
272*62c56f98SSadaf Ebrahimi mbedtls_mpi_uint borrow = mbedtls_mpi_core_sub(X, X, N->p, N->limbs);
273*62c56f98SSadaf Ebrahimi (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) borrow);
274*62c56f98SSadaf Ebrahimi }
275*62c56f98SSadaf Ebrahimi
276*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ECP_WITH_MPI_UINT */
277