xref: /aosp_15_r20/external/mbedtls/library/bignum_mod.c (revision 62c56f9862f102b96d72393aff6076c951fb8148)
1*62c56f98SSadaf Ebrahimi /**
2*62c56f98SSadaf Ebrahimi  *  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/platform_util.h"
15*62c56f98SSadaf Ebrahimi #include "mbedtls/error.h"
16*62c56f98SSadaf Ebrahimi #include "mbedtls/bignum.h"
17*62c56f98SSadaf Ebrahimi 
18*62c56f98SSadaf Ebrahimi #include "mbedtls/platform.h"
19*62c56f98SSadaf Ebrahimi 
20*62c56f98SSadaf Ebrahimi #include "bignum_core.h"
21*62c56f98SSadaf Ebrahimi #include "bignum_mod.h"
22*62c56f98SSadaf Ebrahimi #include "bignum_mod_raw.h"
23*62c56f98SSadaf Ebrahimi #include "constant_time_internal.h"
24*62c56f98SSadaf Ebrahimi 
mbedtls_mpi_mod_residue_setup(mbedtls_mpi_mod_residue * r,const mbedtls_mpi_mod_modulus * N,mbedtls_mpi_uint * p,size_t p_limbs)25*62c56f98SSadaf Ebrahimi int mbedtls_mpi_mod_residue_setup(mbedtls_mpi_mod_residue *r,
26*62c56f98SSadaf Ebrahimi                                   const mbedtls_mpi_mod_modulus *N,
27*62c56f98SSadaf Ebrahimi                                   mbedtls_mpi_uint *p,
28*62c56f98SSadaf Ebrahimi                                   size_t p_limbs)
29*62c56f98SSadaf Ebrahimi {
30*62c56f98SSadaf Ebrahimi     if (p_limbs != N->limbs || !mbedtls_mpi_core_lt_ct(p, N->p, N->limbs)) {
31*62c56f98SSadaf Ebrahimi         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
32*62c56f98SSadaf Ebrahimi     }
33*62c56f98SSadaf Ebrahimi 
34*62c56f98SSadaf Ebrahimi     r->limbs = N->limbs;
35*62c56f98SSadaf Ebrahimi     r->p = p;
36*62c56f98SSadaf Ebrahimi 
37*62c56f98SSadaf Ebrahimi     return 0;
38*62c56f98SSadaf Ebrahimi }
39*62c56f98SSadaf Ebrahimi 
mbedtls_mpi_mod_residue_release(mbedtls_mpi_mod_residue * r)40*62c56f98SSadaf Ebrahimi void mbedtls_mpi_mod_residue_release(mbedtls_mpi_mod_residue *r)
41*62c56f98SSadaf Ebrahimi {
42*62c56f98SSadaf Ebrahimi     if (r == NULL) {
43*62c56f98SSadaf Ebrahimi         return;
44*62c56f98SSadaf Ebrahimi     }
45*62c56f98SSadaf Ebrahimi 
46*62c56f98SSadaf Ebrahimi     r->limbs = 0;
47*62c56f98SSadaf Ebrahimi     r->p = NULL;
48*62c56f98SSadaf Ebrahimi }
49*62c56f98SSadaf Ebrahimi 
mbedtls_mpi_mod_modulus_init(mbedtls_mpi_mod_modulus * N)50*62c56f98SSadaf Ebrahimi void mbedtls_mpi_mod_modulus_init(mbedtls_mpi_mod_modulus *N)
51*62c56f98SSadaf Ebrahimi {
52*62c56f98SSadaf Ebrahimi     if (N == NULL) {
53*62c56f98SSadaf Ebrahimi         return;
54*62c56f98SSadaf Ebrahimi     }
55*62c56f98SSadaf Ebrahimi 
56*62c56f98SSadaf Ebrahimi     N->p = NULL;
57*62c56f98SSadaf Ebrahimi     N->limbs = 0;
58*62c56f98SSadaf Ebrahimi     N->bits = 0;
59*62c56f98SSadaf Ebrahimi     N->int_rep = MBEDTLS_MPI_MOD_REP_INVALID;
60*62c56f98SSadaf Ebrahimi }
61*62c56f98SSadaf Ebrahimi 
mbedtls_mpi_mod_modulus_free(mbedtls_mpi_mod_modulus * N)62*62c56f98SSadaf Ebrahimi void mbedtls_mpi_mod_modulus_free(mbedtls_mpi_mod_modulus *N)
63*62c56f98SSadaf Ebrahimi {
64*62c56f98SSadaf Ebrahimi     if (N == NULL) {
65*62c56f98SSadaf Ebrahimi         return;
66*62c56f98SSadaf Ebrahimi     }
67*62c56f98SSadaf Ebrahimi 
68*62c56f98SSadaf Ebrahimi     switch (N->int_rep) {
69*62c56f98SSadaf Ebrahimi         case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
70*62c56f98SSadaf Ebrahimi             if (N->rep.mont.rr != NULL) {
71*62c56f98SSadaf Ebrahimi                 mbedtls_zeroize_and_free((mbedtls_mpi_uint *) N->rep.mont.rr,
72*62c56f98SSadaf Ebrahimi                                          N->limbs * sizeof(mbedtls_mpi_uint));
73*62c56f98SSadaf Ebrahimi                 N->rep.mont.rr = NULL;
74*62c56f98SSadaf Ebrahimi             }
75*62c56f98SSadaf Ebrahimi             N->rep.mont.mm = 0;
76*62c56f98SSadaf Ebrahimi             break;
77*62c56f98SSadaf Ebrahimi         case MBEDTLS_MPI_MOD_REP_OPT_RED:
78*62c56f98SSadaf Ebrahimi             N->rep.ored.modp = NULL;
79*62c56f98SSadaf Ebrahimi             break;
80*62c56f98SSadaf Ebrahimi         case MBEDTLS_MPI_MOD_REP_INVALID:
81*62c56f98SSadaf Ebrahimi             break;
82*62c56f98SSadaf Ebrahimi     }
83*62c56f98SSadaf Ebrahimi 
84*62c56f98SSadaf Ebrahimi     N->p = NULL;
85*62c56f98SSadaf Ebrahimi     N->limbs = 0;
86*62c56f98SSadaf Ebrahimi     N->bits = 0;
87*62c56f98SSadaf Ebrahimi     N->int_rep = MBEDTLS_MPI_MOD_REP_INVALID;
88*62c56f98SSadaf Ebrahimi }
89*62c56f98SSadaf Ebrahimi 
set_mont_const_square(const mbedtls_mpi_uint ** X,const mbedtls_mpi_uint * A,size_t limbs)90*62c56f98SSadaf Ebrahimi static int set_mont_const_square(const mbedtls_mpi_uint **X,
91*62c56f98SSadaf Ebrahimi                                  const mbedtls_mpi_uint *A,
92*62c56f98SSadaf Ebrahimi                                  size_t limbs)
93*62c56f98SSadaf Ebrahimi {
94*62c56f98SSadaf Ebrahimi     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
95*62c56f98SSadaf Ebrahimi     mbedtls_mpi N;
96*62c56f98SSadaf Ebrahimi     mbedtls_mpi RR;
97*62c56f98SSadaf Ebrahimi     *X = NULL;
98*62c56f98SSadaf Ebrahimi 
99*62c56f98SSadaf Ebrahimi     mbedtls_mpi_init(&N);
100*62c56f98SSadaf Ebrahimi     mbedtls_mpi_init(&RR);
101*62c56f98SSadaf Ebrahimi 
102*62c56f98SSadaf Ebrahimi     if (A == NULL || limbs == 0 || limbs >= (MBEDTLS_MPI_MAX_LIMBS / 2) - 2) {
103*62c56f98SSadaf Ebrahimi         goto cleanup;
104*62c56f98SSadaf Ebrahimi     }
105*62c56f98SSadaf Ebrahimi 
106*62c56f98SSadaf Ebrahimi     if (mbedtls_mpi_grow(&N, limbs)) {
107*62c56f98SSadaf Ebrahimi         goto cleanup;
108*62c56f98SSadaf Ebrahimi     }
109*62c56f98SSadaf Ebrahimi 
110*62c56f98SSadaf Ebrahimi     memcpy(N.p, A, sizeof(mbedtls_mpi_uint) * limbs);
111*62c56f98SSadaf Ebrahimi 
112*62c56f98SSadaf Ebrahimi     ret = mbedtls_mpi_core_get_mont_r2_unsafe(&RR, &N);
113*62c56f98SSadaf Ebrahimi 
114*62c56f98SSadaf Ebrahimi     if (ret == 0) {
115*62c56f98SSadaf Ebrahimi         *X = RR.p;
116*62c56f98SSadaf Ebrahimi         RR.p = NULL;
117*62c56f98SSadaf Ebrahimi     }
118*62c56f98SSadaf Ebrahimi 
119*62c56f98SSadaf Ebrahimi cleanup:
120*62c56f98SSadaf Ebrahimi     mbedtls_mpi_free(&N);
121*62c56f98SSadaf Ebrahimi     mbedtls_mpi_free(&RR);
122*62c56f98SSadaf Ebrahimi     ret = (ret != 0) ? MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED : 0;
123*62c56f98SSadaf Ebrahimi     return ret;
124*62c56f98SSadaf Ebrahimi }
125*62c56f98SSadaf Ebrahimi 
standard_modulus_setup(mbedtls_mpi_mod_modulus * N,const mbedtls_mpi_uint * p,size_t p_limbs,mbedtls_mpi_mod_rep_selector int_rep)126*62c56f98SSadaf Ebrahimi static inline void standard_modulus_setup(mbedtls_mpi_mod_modulus *N,
127*62c56f98SSadaf Ebrahimi                                           const mbedtls_mpi_uint *p,
128*62c56f98SSadaf Ebrahimi                                           size_t p_limbs,
129*62c56f98SSadaf Ebrahimi                                           mbedtls_mpi_mod_rep_selector int_rep)
130*62c56f98SSadaf Ebrahimi {
131*62c56f98SSadaf Ebrahimi     N->p = p;
132*62c56f98SSadaf Ebrahimi     N->limbs = p_limbs;
133*62c56f98SSadaf Ebrahimi     N->bits = mbedtls_mpi_core_bitlen(p, p_limbs);
134*62c56f98SSadaf Ebrahimi     N->int_rep = int_rep;
135*62c56f98SSadaf Ebrahimi }
136*62c56f98SSadaf Ebrahimi 
mbedtls_mpi_mod_modulus_setup(mbedtls_mpi_mod_modulus * N,const mbedtls_mpi_uint * p,size_t p_limbs)137*62c56f98SSadaf Ebrahimi int mbedtls_mpi_mod_modulus_setup(mbedtls_mpi_mod_modulus *N,
138*62c56f98SSadaf Ebrahimi                                   const mbedtls_mpi_uint *p,
139*62c56f98SSadaf Ebrahimi                                   size_t p_limbs)
140*62c56f98SSadaf Ebrahimi {
141*62c56f98SSadaf Ebrahimi     int ret = 0;
142*62c56f98SSadaf Ebrahimi     standard_modulus_setup(N, p, p_limbs, MBEDTLS_MPI_MOD_REP_MONTGOMERY);
143*62c56f98SSadaf Ebrahimi     N->rep.mont.mm = mbedtls_mpi_core_montmul_init(N->p);
144*62c56f98SSadaf Ebrahimi     ret = set_mont_const_square(&N->rep.mont.rr, N->p, N->limbs);
145*62c56f98SSadaf Ebrahimi 
146*62c56f98SSadaf Ebrahimi     if (ret != 0) {
147*62c56f98SSadaf Ebrahimi         mbedtls_mpi_mod_modulus_free(N);
148*62c56f98SSadaf Ebrahimi     }
149*62c56f98SSadaf Ebrahimi 
150*62c56f98SSadaf Ebrahimi     return ret;
151*62c56f98SSadaf Ebrahimi }
152*62c56f98SSadaf Ebrahimi 
mbedtls_mpi_mod_optred_modulus_setup(mbedtls_mpi_mod_modulus * N,const mbedtls_mpi_uint * p,size_t p_limbs,mbedtls_mpi_modp_fn modp)153*62c56f98SSadaf Ebrahimi int mbedtls_mpi_mod_optred_modulus_setup(mbedtls_mpi_mod_modulus *N,
154*62c56f98SSadaf Ebrahimi                                          const mbedtls_mpi_uint *p,
155*62c56f98SSadaf Ebrahimi                                          size_t p_limbs,
156*62c56f98SSadaf Ebrahimi                                          mbedtls_mpi_modp_fn modp)
157*62c56f98SSadaf Ebrahimi {
158*62c56f98SSadaf Ebrahimi     standard_modulus_setup(N, p, p_limbs, MBEDTLS_MPI_MOD_REP_OPT_RED);
159*62c56f98SSadaf Ebrahimi     N->rep.ored.modp = modp;
160*62c56f98SSadaf Ebrahimi     return 0;
161*62c56f98SSadaf Ebrahimi }
162*62c56f98SSadaf Ebrahimi 
mbedtls_mpi_mod_mul(mbedtls_mpi_mod_residue * X,const mbedtls_mpi_mod_residue * A,const mbedtls_mpi_mod_residue * B,const mbedtls_mpi_mod_modulus * N)163*62c56f98SSadaf Ebrahimi int mbedtls_mpi_mod_mul(mbedtls_mpi_mod_residue *X,
164*62c56f98SSadaf Ebrahimi                         const mbedtls_mpi_mod_residue *A,
165*62c56f98SSadaf Ebrahimi                         const mbedtls_mpi_mod_residue *B,
166*62c56f98SSadaf Ebrahimi                         const mbedtls_mpi_mod_modulus *N)
167*62c56f98SSadaf Ebrahimi {
168*62c56f98SSadaf Ebrahimi     if (N->limbs == 0) {
169*62c56f98SSadaf Ebrahimi         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
170*62c56f98SSadaf Ebrahimi     }
171*62c56f98SSadaf Ebrahimi 
172*62c56f98SSadaf Ebrahimi     if (X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs) {
173*62c56f98SSadaf Ebrahimi         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
174*62c56f98SSadaf Ebrahimi     }
175*62c56f98SSadaf Ebrahimi 
176*62c56f98SSadaf Ebrahimi     mbedtls_mpi_uint *T = mbedtls_calloc(N->limbs * 2 + 1, ciL);
177*62c56f98SSadaf Ebrahimi     if (T == NULL) {
178*62c56f98SSadaf Ebrahimi         return MBEDTLS_ERR_MPI_ALLOC_FAILED;
179*62c56f98SSadaf Ebrahimi     }
180*62c56f98SSadaf Ebrahimi 
181*62c56f98SSadaf Ebrahimi     mbedtls_mpi_mod_raw_mul(X->p, A->p, B->p, N, T);
182*62c56f98SSadaf Ebrahimi 
183*62c56f98SSadaf Ebrahimi     mbedtls_free(T);
184*62c56f98SSadaf Ebrahimi 
185*62c56f98SSadaf Ebrahimi     return 0;
186*62c56f98SSadaf Ebrahimi }
187*62c56f98SSadaf Ebrahimi 
mbedtls_mpi_mod_sub(mbedtls_mpi_mod_residue * X,const mbedtls_mpi_mod_residue * A,const mbedtls_mpi_mod_residue * B,const mbedtls_mpi_mod_modulus * N)188*62c56f98SSadaf Ebrahimi int mbedtls_mpi_mod_sub(mbedtls_mpi_mod_residue *X,
189*62c56f98SSadaf Ebrahimi                         const mbedtls_mpi_mod_residue *A,
190*62c56f98SSadaf Ebrahimi                         const mbedtls_mpi_mod_residue *B,
191*62c56f98SSadaf Ebrahimi                         const mbedtls_mpi_mod_modulus *N)
192*62c56f98SSadaf Ebrahimi {
193*62c56f98SSadaf Ebrahimi     if (X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs) {
194*62c56f98SSadaf Ebrahimi         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
195*62c56f98SSadaf Ebrahimi     }
196*62c56f98SSadaf Ebrahimi 
197*62c56f98SSadaf Ebrahimi     mbedtls_mpi_mod_raw_sub(X->p, A->p, B->p, N);
198*62c56f98SSadaf Ebrahimi 
199*62c56f98SSadaf Ebrahimi     return 0;
200*62c56f98SSadaf Ebrahimi }
201*62c56f98SSadaf Ebrahimi 
mbedtls_mpi_mod_inv_mont(mbedtls_mpi_mod_residue * X,const mbedtls_mpi_mod_residue * A,const mbedtls_mpi_mod_modulus * N,mbedtls_mpi_uint * working_memory)202*62c56f98SSadaf Ebrahimi static int mbedtls_mpi_mod_inv_mont(mbedtls_mpi_mod_residue *X,
203*62c56f98SSadaf Ebrahimi                                     const mbedtls_mpi_mod_residue *A,
204*62c56f98SSadaf Ebrahimi                                     const mbedtls_mpi_mod_modulus *N,
205*62c56f98SSadaf Ebrahimi                                     mbedtls_mpi_uint *working_memory)
206*62c56f98SSadaf Ebrahimi {
207*62c56f98SSadaf Ebrahimi     /* Input already in Montgomery form, so there's little to do */
208*62c56f98SSadaf Ebrahimi     mbedtls_mpi_mod_raw_inv_prime(X->p, A->p,
209*62c56f98SSadaf Ebrahimi                                   N->p, N->limbs,
210*62c56f98SSadaf Ebrahimi                                   N->rep.mont.rr,
211*62c56f98SSadaf Ebrahimi                                   working_memory);
212*62c56f98SSadaf Ebrahimi     return 0;
213*62c56f98SSadaf Ebrahimi }
214*62c56f98SSadaf Ebrahimi 
mbedtls_mpi_mod_inv_non_mont(mbedtls_mpi_mod_residue * X,const mbedtls_mpi_mod_residue * A,const mbedtls_mpi_mod_modulus * N,mbedtls_mpi_uint * working_memory)215*62c56f98SSadaf Ebrahimi static int mbedtls_mpi_mod_inv_non_mont(mbedtls_mpi_mod_residue *X,
216*62c56f98SSadaf Ebrahimi                                         const mbedtls_mpi_mod_residue *A,
217*62c56f98SSadaf Ebrahimi                                         const mbedtls_mpi_mod_modulus *N,
218*62c56f98SSadaf Ebrahimi                                         mbedtls_mpi_uint *working_memory)
219*62c56f98SSadaf Ebrahimi {
220*62c56f98SSadaf Ebrahimi     /* Need to convert input into Montgomery form */
221*62c56f98SSadaf Ebrahimi 
222*62c56f98SSadaf Ebrahimi     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
223*62c56f98SSadaf Ebrahimi 
224*62c56f98SSadaf Ebrahimi     mbedtls_mpi_mod_modulus Nmont;
225*62c56f98SSadaf Ebrahimi     mbedtls_mpi_mod_modulus_init(&Nmont);
226*62c56f98SSadaf Ebrahimi 
227*62c56f98SSadaf Ebrahimi     MBEDTLS_MPI_CHK(mbedtls_mpi_mod_modulus_setup(&Nmont, N->p, N->limbs));
228*62c56f98SSadaf Ebrahimi 
229*62c56f98SSadaf Ebrahimi     /* We'll use X->p to hold the Montgomery form of the input A->p */
230*62c56f98SSadaf Ebrahimi     mbedtls_mpi_core_to_mont_rep(X->p, A->p, Nmont.p, Nmont.limbs,
231*62c56f98SSadaf Ebrahimi                                  Nmont.rep.mont.mm, Nmont.rep.mont.rr,
232*62c56f98SSadaf Ebrahimi                                  working_memory);
233*62c56f98SSadaf Ebrahimi 
234*62c56f98SSadaf Ebrahimi     mbedtls_mpi_mod_raw_inv_prime(X->p, X->p,
235*62c56f98SSadaf Ebrahimi                                   Nmont.p, Nmont.limbs,
236*62c56f98SSadaf Ebrahimi                                   Nmont.rep.mont.rr,
237*62c56f98SSadaf Ebrahimi                                   working_memory);
238*62c56f98SSadaf Ebrahimi 
239*62c56f98SSadaf Ebrahimi     /* And convert back from Montgomery form */
240*62c56f98SSadaf Ebrahimi 
241*62c56f98SSadaf Ebrahimi     mbedtls_mpi_core_from_mont_rep(X->p, X->p, Nmont.p, Nmont.limbs,
242*62c56f98SSadaf Ebrahimi                                    Nmont.rep.mont.mm, working_memory);
243*62c56f98SSadaf Ebrahimi 
244*62c56f98SSadaf Ebrahimi cleanup:
245*62c56f98SSadaf Ebrahimi     mbedtls_mpi_mod_modulus_free(&Nmont);
246*62c56f98SSadaf Ebrahimi     return ret;
247*62c56f98SSadaf Ebrahimi }
248*62c56f98SSadaf Ebrahimi 
mbedtls_mpi_mod_inv(mbedtls_mpi_mod_residue * X,const mbedtls_mpi_mod_residue * A,const mbedtls_mpi_mod_modulus * N)249*62c56f98SSadaf Ebrahimi int mbedtls_mpi_mod_inv(mbedtls_mpi_mod_residue *X,
250*62c56f98SSadaf Ebrahimi                         const mbedtls_mpi_mod_residue *A,
251*62c56f98SSadaf Ebrahimi                         const mbedtls_mpi_mod_modulus *N)
252*62c56f98SSadaf Ebrahimi {
253*62c56f98SSadaf Ebrahimi     if (X->limbs != N->limbs || A->limbs != N->limbs) {
254*62c56f98SSadaf Ebrahimi         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
255*62c56f98SSadaf Ebrahimi     }
256*62c56f98SSadaf Ebrahimi 
257*62c56f98SSadaf Ebrahimi     /* Zero has the same value regardless of Montgomery form or not */
258*62c56f98SSadaf Ebrahimi     if (mbedtls_mpi_core_check_zero_ct(A->p, A->limbs) == 0) {
259*62c56f98SSadaf Ebrahimi         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
260*62c56f98SSadaf Ebrahimi     }
261*62c56f98SSadaf Ebrahimi 
262*62c56f98SSadaf Ebrahimi     size_t working_limbs =
263*62c56f98SSadaf Ebrahimi         mbedtls_mpi_mod_raw_inv_prime_working_limbs(N->limbs);
264*62c56f98SSadaf Ebrahimi 
265*62c56f98SSadaf Ebrahimi     mbedtls_mpi_uint *working_memory = mbedtls_calloc(working_limbs,
266*62c56f98SSadaf Ebrahimi                                                       sizeof(mbedtls_mpi_uint));
267*62c56f98SSadaf Ebrahimi     if (working_memory == NULL) {
268*62c56f98SSadaf Ebrahimi         return MBEDTLS_ERR_MPI_ALLOC_FAILED;
269*62c56f98SSadaf Ebrahimi     }
270*62c56f98SSadaf Ebrahimi 
271*62c56f98SSadaf Ebrahimi     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
272*62c56f98SSadaf Ebrahimi 
273*62c56f98SSadaf Ebrahimi     switch (N->int_rep) {
274*62c56f98SSadaf Ebrahimi         case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
275*62c56f98SSadaf Ebrahimi             ret = mbedtls_mpi_mod_inv_mont(X, A, N, working_memory);
276*62c56f98SSadaf Ebrahimi             break;
277*62c56f98SSadaf Ebrahimi         case MBEDTLS_MPI_MOD_REP_OPT_RED:
278*62c56f98SSadaf Ebrahimi             ret = mbedtls_mpi_mod_inv_non_mont(X, A, N, working_memory);
279*62c56f98SSadaf Ebrahimi             break;
280*62c56f98SSadaf Ebrahimi         default:
281*62c56f98SSadaf Ebrahimi             ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
282*62c56f98SSadaf Ebrahimi             break;
283*62c56f98SSadaf Ebrahimi     }
284*62c56f98SSadaf Ebrahimi 
285*62c56f98SSadaf Ebrahimi     mbedtls_zeroize_and_free(working_memory,
286*62c56f98SSadaf Ebrahimi                              working_limbs * sizeof(mbedtls_mpi_uint));
287*62c56f98SSadaf Ebrahimi 
288*62c56f98SSadaf Ebrahimi     return ret;
289*62c56f98SSadaf Ebrahimi }
290*62c56f98SSadaf Ebrahimi 
mbedtls_mpi_mod_add(mbedtls_mpi_mod_residue * X,const mbedtls_mpi_mod_residue * A,const mbedtls_mpi_mod_residue * B,const mbedtls_mpi_mod_modulus * N)291*62c56f98SSadaf Ebrahimi int mbedtls_mpi_mod_add(mbedtls_mpi_mod_residue *X,
292*62c56f98SSadaf Ebrahimi                         const mbedtls_mpi_mod_residue *A,
293*62c56f98SSadaf Ebrahimi                         const mbedtls_mpi_mod_residue *B,
294*62c56f98SSadaf Ebrahimi                         const mbedtls_mpi_mod_modulus *N)
295*62c56f98SSadaf Ebrahimi {
296*62c56f98SSadaf Ebrahimi     if (X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs) {
297*62c56f98SSadaf Ebrahimi         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
298*62c56f98SSadaf Ebrahimi     }
299*62c56f98SSadaf Ebrahimi 
300*62c56f98SSadaf Ebrahimi     mbedtls_mpi_mod_raw_add(X->p, A->p, B->p, N);
301*62c56f98SSadaf Ebrahimi 
302*62c56f98SSadaf Ebrahimi     return 0;
303*62c56f98SSadaf Ebrahimi }
304*62c56f98SSadaf Ebrahimi 
mbedtls_mpi_mod_random(mbedtls_mpi_mod_residue * X,mbedtls_mpi_uint min,const mbedtls_mpi_mod_modulus * N,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)305*62c56f98SSadaf Ebrahimi int mbedtls_mpi_mod_random(mbedtls_mpi_mod_residue *X,
306*62c56f98SSadaf Ebrahimi                            mbedtls_mpi_uint min,
307*62c56f98SSadaf Ebrahimi                            const mbedtls_mpi_mod_modulus *N,
308*62c56f98SSadaf Ebrahimi                            int (*f_rng)(void *, unsigned char *, size_t),
309*62c56f98SSadaf Ebrahimi                            void *p_rng)
310*62c56f98SSadaf Ebrahimi {
311*62c56f98SSadaf Ebrahimi     if (X->limbs != N->limbs) {
312*62c56f98SSadaf Ebrahimi         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
313*62c56f98SSadaf Ebrahimi     }
314*62c56f98SSadaf Ebrahimi     return mbedtls_mpi_mod_raw_random(X->p, min, N, f_rng, p_rng);
315*62c56f98SSadaf Ebrahimi }
316*62c56f98SSadaf Ebrahimi 
mbedtls_mpi_mod_read(mbedtls_mpi_mod_residue * r,const mbedtls_mpi_mod_modulus * N,const unsigned char * buf,size_t buflen,mbedtls_mpi_mod_ext_rep ext_rep)317*62c56f98SSadaf Ebrahimi int mbedtls_mpi_mod_read(mbedtls_mpi_mod_residue *r,
318*62c56f98SSadaf Ebrahimi                          const mbedtls_mpi_mod_modulus *N,
319*62c56f98SSadaf Ebrahimi                          const unsigned char *buf,
320*62c56f98SSadaf Ebrahimi                          size_t buflen,
321*62c56f98SSadaf Ebrahimi                          mbedtls_mpi_mod_ext_rep ext_rep)
322*62c56f98SSadaf Ebrahimi {
323*62c56f98SSadaf Ebrahimi     int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
324*62c56f98SSadaf Ebrahimi 
325*62c56f98SSadaf Ebrahimi     /* Do our best to check if r and m have been set up */
326*62c56f98SSadaf Ebrahimi     if (r->limbs == 0 || N->limbs == 0) {
327*62c56f98SSadaf Ebrahimi         goto cleanup;
328*62c56f98SSadaf Ebrahimi     }
329*62c56f98SSadaf Ebrahimi     if (r->limbs != N->limbs) {
330*62c56f98SSadaf Ebrahimi         goto cleanup;
331*62c56f98SSadaf Ebrahimi     }
332*62c56f98SSadaf Ebrahimi 
333*62c56f98SSadaf Ebrahimi     ret = mbedtls_mpi_mod_raw_read(r->p, N, buf, buflen, ext_rep);
334*62c56f98SSadaf Ebrahimi     if (ret != 0) {
335*62c56f98SSadaf Ebrahimi         goto cleanup;
336*62c56f98SSadaf Ebrahimi     }
337*62c56f98SSadaf Ebrahimi 
338*62c56f98SSadaf Ebrahimi     r->limbs = N->limbs;
339*62c56f98SSadaf Ebrahimi 
340*62c56f98SSadaf Ebrahimi     ret = mbedtls_mpi_mod_raw_canonical_to_modulus_rep(r->p, N);
341*62c56f98SSadaf Ebrahimi 
342*62c56f98SSadaf Ebrahimi cleanup:
343*62c56f98SSadaf Ebrahimi     return ret;
344*62c56f98SSadaf Ebrahimi }
345*62c56f98SSadaf Ebrahimi 
mbedtls_mpi_mod_write(const mbedtls_mpi_mod_residue * r,const mbedtls_mpi_mod_modulus * N,unsigned char * buf,size_t buflen,mbedtls_mpi_mod_ext_rep ext_rep)346*62c56f98SSadaf Ebrahimi int mbedtls_mpi_mod_write(const mbedtls_mpi_mod_residue *r,
347*62c56f98SSadaf Ebrahimi                           const mbedtls_mpi_mod_modulus *N,
348*62c56f98SSadaf Ebrahimi                           unsigned char *buf,
349*62c56f98SSadaf Ebrahimi                           size_t buflen,
350*62c56f98SSadaf Ebrahimi                           mbedtls_mpi_mod_ext_rep ext_rep)
351*62c56f98SSadaf Ebrahimi {
352*62c56f98SSadaf Ebrahimi     /* Do our best to check if r and m have been set up */
353*62c56f98SSadaf Ebrahimi     if (r->limbs == 0 || N->limbs == 0) {
354*62c56f98SSadaf Ebrahimi         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
355*62c56f98SSadaf Ebrahimi     }
356*62c56f98SSadaf Ebrahimi     if (r->limbs != N->limbs) {
357*62c56f98SSadaf Ebrahimi         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
358*62c56f98SSadaf Ebrahimi     }
359*62c56f98SSadaf Ebrahimi 
360*62c56f98SSadaf Ebrahimi     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
361*62c56f98SSadaf Ebrahimi     mbedtls_mpi_uint *working_memory = r->p;
362*62c56f98SSadaf Ebrahimi     size_t working_memory_len = sizeof(mbedtls_mpi_uint) * r->limbs;
363*62c56f98SSadaf Ebrahimi 
364*62c56f98SSadaf Ebrahimi     if (N->int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY) {
365*62c56f98SSadaf Ebrahimi 
366*62c56f98SSadaf Ebrahimi         working_memory = mbedtls_calloc(r->limbs, sizeof(mbedtls_mpi_uint));
367*62c56f98SSadaf Ebrahimi 
368*62c56f98SSadaf Ebrahimi         if (working_memory == NULL) {
369*62c56f98SSadaf Ebrahimi             ret = MBEDTLS_ERR_MPI_ALLOC_FAILED;
370*62c56f98SSadaf Ebrahimi             goto cleanup;
371*62c56f98SSadaf Ebrahimi         }
372*62c56f98SSadaf Ebrahimi 
373*62c56f98SSadaf Ebrahimi         memcpy(working_memory, r->p, working_memory_len);
374*62c56f98SSadaf Ebrahimi 
375*62c56f98SSadaf Ebrahimi         ret = mbedtls_mpi_mod_raw_from_mont_rep(working_memory, N);
376*62c56f98SSadaf Ebrahimi         if (ret != 0) {
377*62c56f98SSadaf Ebrahimi             goto cleanup;
378*62c56f98SSadaf Ebrahimi         }
379*62c56f98SSadaf Ebrahimi     }
380*62c56f98SSadaf Ebrahimi 
381*62c56f98SSadaf Ebrahimi     ret = mbedtls_mpi_mod_raw_write(working_memory, N, buf, buflen, ext_rep);
382*62c56f98SSadaf Ebrahimi 
383*62c56f98SSadaf Ebrahimi cleanup:
384*62c56f98SSadaf Ebrahimi 
385*62c56f98SSadaf Ebrahimi     if (N->int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY &&
386*62c56f98SSadaf Ebrahimi         working_memory != NULL) {
387*62c56f98SSadaf Ebrahimi 
388*62c56f98SSadaf Ebrahimi         mbedtls_zeroize_and_free(working_memory, working_memory_len);
389*62c56f98SSadaf Ebrahimi     }
390*62c56f98SSadaf Ebrahimi 
391*62c56f98SSadaf Ebrahimi     return ret;
392*62c56f98SSadaf Ebrahimi }
393*62c56f98SSadaf Ebrahimi 
394*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ECP_WITH_MPI_UINT */
395