xref: /optee_os/lib/libmbedtls/mbedtls/library/bignum_mod.c (revision b0563631928755fe864b97785160fb3088e9efdc)
132b31808SJens Wiklander /**
232b31808SJens Wiklander  *  Modular bignum functions
332b31808SJens Wiklander  *
432b31808SJens Wiklander  *  Copyright The Mbed TLS Contributors
5*b0563631STom Van Eyck  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
632b31808SJens Wiklander  */
732b31808SJens Wiklander 
832b31808SJens Wiklander #include "common.h"
932b31808SJens Wiklander 
10*b0563631STom Van Eyck #if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_ECP_WITH_MPI_UINT)
1132b31808SJens Wiklander 
1232b31808SJens Wiklander #include <string.h>
1332b31808SJens Wiklander 
1432b31808SJens Wiklander #include "mbedtls/platform_util.h"
1532b31808SJens Wiklander #include "mbedtls/error.h"
1632b31808SJens Wiklander #include "mbedtls/bignum.h"
1732b31808SJens Wiklander 
1832b31808SJens Wiklander #include "mbedtls/platform.h"
1932b31808SJens Wiklander 
2032b31808SJens Wiklander #include "bignum_core.h"
2132b31808SJens Wiklander #include "bignum_mod.h"
2232b31808SJens Wiklander #include "bignum_mod_raw.h"
2332b31808SJens Wiklander #include "constant_time_internal.h"
2432b31808SJens Wiklander 
mbedtls_mpi_mod_residue_setup(mbedtls_mpi_mod_residue * r,const mbedtls_mpi_mod_modulus * N,mbedtls_mpi_uint * p,size_t p_limbs)2532b31808SJens Wiklander int mbedtls_mpi_mod_residue_setup(mbedtls_mpi_mod_residue *r,
2632b31808SJens Wiklander                                   const mbedtls_mpi_mod_modulus *N,
2732b31808SJens Wiklander                                   mbedtls_mpi_uint *p,
2832b31808SJens Wiklander                                   size_t p_limbs)
2932b31808SJens Wiklander {
3032b31808SJens Wiklander     if (p_limbs != N->limbs || !mbedtls_mpi_core_lt_ct(p, N->p, N->limbs)) {
3132b31808SJens Wiklander         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
3232b31808SJens Wiklander     }
3332b31808SJens Wiklander 
3432b31808SJens Wiklander     r->limbs = N->limbs;
3532b31808SJens Wiklander     r->p = p;
3632b31808SJens Wiklander 
3732b31808SJens Wiklander     return 0;
3832b31808SJens Wiklander }
3932b31808SJens Wiklander 
mbedtls_mpi_mod_residue_release(mbedtls_mpi_mod_residue * r)4032b31808SJens Wiklander void mbedtls_mpi_mod_residue_release(mbedtls_mpi_mod_residue *r)
4132b31808SJens Wiklander {
4232b31808SJens Wiklander     if (r == NULL) {
4332b31808SJens Wiklander         return;
4432b31808SJens Wiklander     }
4532b31808SJens Wiklander 
4632b31808SJens Wiklander     r->limbs = 0;
4732b31808SJens Wiklander     r->p = NULL;
4832b31808SJens Wiklander }
4932b31808SJens Wiklander 
mbedtls_mpi_mod_modulus_init(mbedtls_mpi_mod_modulus * N)5032b31808SJens Wiklander void mbedtls_mpi_mod_modulus_init(mbedtls_mpi_mod_modulus *N)
5132b31808SJens Wiklander {
5232b31808SJens Wiklander     if (N == NULL) {
5332b31808SJens Wiklander         return;
5432b31808SJens Wiklander     }
5532b31808SJens Wiklander 
5632b31808SJens Wiklander     N->p = NULL;
5732b31808SJens Wiklander     N->limbs = 0;
5832b31808SJens Wiklander     N->bits = 0;
5932b31808SJens Wiklander     N->int_rep = MBEDTLS_MPI_MOD_REP_INVALID;
6032b31808SJens Wiklander }
6132b31808SJens Wiklander 
mbedtls_mpi_mod_modulus_free(mbedtls_mpi_mod_modulus * N)6232b31808SJens Wiklander void mbedtls_mpi_mod_modulus_free(mbedtls_mpi_mod_modulus *N)
6332b31808SJens Wiklander {
6432b31808SJens Wiklander     if (N == NULL) {
6532b31808SJens Wiklander         return;
6632b31808SJens Wiklander     }
6732b31808SJens Wiklander 
6832b31808SJens Wiklander     switch (N->int_rep) {
6932b31808SJens Wiklander         case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
7032b31808SJens Wiklander             if (N->rep.mont.rr != NULL) {
71*b0563631STom Van Eyck                 mbedtls_zeroize_and_free((mbedtls_mpi_uint *) N->rep.mont.rr,
7232b31808SJens Wiklander                                          N->limbs * sizeof(mbedtls_mpi_uint));
7332b31808SJens Wiklander                 N->rep.mont.rr = NULL;
7432b31808SJens Wiklander             }
7532b31808SJens Wiklander             N->rep.mont.mm = 0;
7632b31808SJens Wiklander             break;
7732b31808SJens Wiklander         case MBEDTLS_MPI_MOD_REP_OPT_RED:
78*b0563631STom Van Eyck             N->rep.ored.modp = NULL;
7932b31808SJens Wiklander             break;
8032b31808SJens Wiklander         case MBEDTLS_MPI_MOD_REP_INVALID:
8132b31808SJens Wiklander             break;
8232b31808SJens Wiklander     }
8332b31808SJens Wiklander 
8432b31808SJens Wiklander     N->p = NULL;
8532b31808SJens Wiklander     N->limbs = 0;
8632b31808SJens Wiklander     N->bits = 0;
8732b31808SJens Wiklander     N->int_rep = MBEDTLS_MPI_MOD_REP_INVALID;
8832b31808SJens Wiklander }
8932b31808SJens Wiklander 
set_mont_const_square(const mbedtls_mpi_uint ** X,const mbedtls_mpi_uint * A,size_t limbs)9032b31808SJens Wiklander static int set_mont_const_square(const mbedtls_mpi_uint **X,
9132b31808SJens Wiklander                                  const mbedtls_mpi_uint *A,
9232b31808SJens Wiklander                                  size_t limbs)
9332b31808SJens Wiklander {
9432b31808SJens Wiklander     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
9532b31808SJens Wiklander     mbedtls_mpi N;
9632b31808SJens Wiklander     mbedtls_mpi RR;
9732b31808SJens Wiklander     *X = NULL;
9832b31808SJens Wiklander 
9932b31808SJens Wiklander     mbedtls_mpi_init(&N);
10032b31808SJens Wiklander     mbedtls_mpi_init(&RR);
10132b31808SJens Wiklander 
10232b31808SJens Wiklander     if (A == NULL || limbs == 0 || limbs >= (MBEDTLS_MPI_MAX_LIMBS / 2) - 2) {
10332b31808SJens Wiklander         goto cleanup;
10432b31808SJens Wiklander     }
10532b31808SJens Wiklander 
10632b31808SJens Wiklander     if (mbedtls_mpi_grow(&N, limbs)) {
10732b31808SJens Wiklander         goto cleanup;
10832b31808SJens Wiklander     }
10932b31808SJens Wiklander 
11032b31808SJens Wiklander     memcpy(N.p, A, sizeof(mbedtls_mpi_uint) * limbs);
11132b31808SJens Wiklander 
11232b31808SJens Wiklander     ret = mbedtls_mpi_core_get_mont_r2_unsafe(&RR, &N);
11332b31808SJens Wiklander 
11432b31808SJens Wiklander     if (ret == 0) {
11532b31808SJens Wiklander         *X = RR.p;
11632b31808SJens Wiklander         RR.p = NULL;
11732b31808SJens Wiklander     }
11832b31808SJens Wiklander 
11932b31808SJens Wiklander cleanup:
12032b31808SJens Wiklander     mbedtls_mpi_free(&N);
12132b31808SJens Wiklander     mbedtls_mpi_free(&RR);
12232b31808SJens Wiklander     ret = (ret != 0) ? MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED : 0;
12332b31808SJens Wiklander     return ret;
12432b31808SJens Wiklander }
12532b31808SJens Wiklander 
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*b0563631STom Van Eyck static inline void standard_modulus_setup(mbedtls_mpi_mod_modulus *N,
12732b31808SJens Wiklander                                           const mbedtls_mpi_uint *p,
12832b31808SJens Wiklander                                           size_t p_limbs,
12932b31808SJens Wiklander                                           mbedtls_mpi_mod_rep_selector int_rep)
13032b31808SJens Wiklander {
13132b31808SJens Wiklander     N->p = p;
13232b31808SJens Wiklander     N->limbs = p_limbs;
13332b31808SJens Wiklander     N->bits = mbedtls_mpi_core_bitlen(p, p_limbs);
13432b31808SJens Wiklander     N->int_rep = int_rep;
13532b31808SJens Wiklander }
13632b31808SJens Wiklander 
mbedtls_mpi_mod_modulus_setup(mbedtls_mpi_mod_modulus * N,const mbedtls_mpi_uint * p,size_t p_limbs)137*b0563631STom Van Eyck int mbedtls_mpi_mod_modulus_setup(mbedtls_mpi_mod_modulus *N,
138*b0563631STom Van Eyck                                   const mbedtls_mpi_uint *p,
139*b0563631STom Van Eyck                                   size_t p_limbs)
140*b0563631STom Van Eyck {
141*b0563631STom Van Eyck     int ret = 0;
142*b0563631STom Van Eyck     standard_modulus_setup(N, p, p_limbs, MBEDTLS_MPI_MOD_REP_MONTGOMERY);
143*b0563631STom Van Eyck     N->rep.mont.mm = mbedtls_mpi_core_montmul_init(N->p);
144*b0563631STom Van Eyck     ret = set_mont_const_square(&N->rep.mont.rr, N->p, N->limbs);
14532b31808SJens Wiklander 
14632b31808SJens Wiklander     if (ret != 0) {
14732b31808SJens Wiklander         mbedtls_mpi_mod_modulus_free(N);
14832b31808SJens Wiklander     }
14932b31808SJens Wiklander 
15032b31808SJens Wiklander     return ret;
15132b31808SJens Wiklander }
15232b31808SJens Wiklander 
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*b0563631STom Van Eyck int mbedtls_mpi_mod_optred_modulus_setup(mbedtls_mpi_mod_modulus *N,
154*b0563631STom Van Eyck                                          const mbedtls_mpi_uint *p,
155*b0563631STom Van Eyck                                          size_t p_limbs,
156*b0563631STom Van Eyck                                          mbedtls_mpi_modp_fn modp)
157*b0563631STom Van Eyck {
158*b0563631STom Van Eyck     standard_modulus_setup(N, p, p_limbs, MBEDTLS_MPI_MOD_REP_OPT_RED);
159*b0563631STom Van Eyck     N->rep.ored.modp = modp;
160*b0563631STom Van Eyck     return 0;
161*b0563631STom Van Eyck }
16232b31808SJens Wiklander 
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)16332b31808SJens Wiklander int mbedtls_mpi_mod_mul(mbedtls_mpi_mod_residue *X,
16432b31808SJens Wiklander                         const mbedtls_mpi_mod_residue *A,
16532b31808SJens Wiklander                         const mbedtls_mpi_mod_residue *B,
16632b31808SJens Wiklander                         const mbedtls_mpi_mod_modulus *N)
16732b31808SJens Wiklander {
16832b31808SJens Wiklander     if (N->limbs == 0) {
16932b31808SJens Wiklander         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
17032b31808SJens Wiklander     }
17132b31808SJens Wiklander 
17232b31808SJens Wiklander     if (X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs) {
17332b31808SJens Wiklander         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
17432b31808SJens Wiklander     }
17532b31808SJens Wiklander 
17632b31808SJens Wiklander     mbedtls_mpi_uint *T = mbedtls_calloc(N->limbs * 2 + 1, ciL);
17732b31808SJens Wiklander     if (T == NULL) {
17832b31808SJens Wiklander         return MBEDTLS_ERR_MPI_ALLOC_FAILED;
17932b31808SJens Wiklander     }
18032b31808SJens Wiklander 
18132b31808SJens Wiklander     mbedtls_mpi_mod_raw_mul(X->p, A->p, B->p, N, T);
18232b31808SJens Wiklander 
18332b31808SJens Wiklander     mbedtls_free(T);
18432b31808SJens Wiklander 
18532b31808SJens Wiklander     return 0;
18632b31808SJens Wiklander }
18732b31808SJens Wiklander 
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)18832b31808SJens Wiklander int mbedtls_mpi_mod_sub(mbedtls_mpi_mod_residue *X,
18932b31808SJens Wiklander                         const mbedtls_mpi_mod_residue *A,
19032b31808SJens Wiklander                         const mbedtls_mpi_mod_residue *B,
19132b31808SJens Wiklander                         const mbedtls_mpi_mod_modulus *N)
19232b31808SJens Wiklander {
19332b31808SJens Wiklander     if (X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs) {
19432b31808SJens Wiklander         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
19532b31808SJens Wiklander     }
19632b31808SJens Wiklander 
19732b31808SJens Wiklander     mbedtls_mpi_mod_raw_sub(X->p, A->p, B->p, N);
19832b31808SJens Wiklander 
19932b31808SJens Wiklander     return 0;
20032b31808SJens Wiklander }
20132b31808SJens Wiklander 
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)20232b31808SJens Wiklander static int mbedtls_mpi_mod_inv_mont(mbedtls_mpi_mod_residue *X,
20332b31808SJens Wiklander                                     const mbedtls_mpi_mod_residue *A,
20432b31808SJens Wiklander                                     const mbedtls_mpi_mod_modulus *N,
20532b31808SJens Wiklander                                     mbedtls_mpi_uint *working_memory)
20632b31808SJens Wiklander {
20732b31808SJens Wiklander     /* Input already in Montgomery form, so there's little to do */
20832b31808SJens Wiklander     mbedtls_mpi_mod_raw_inv_prime(X->p, A->p,
20932b31808SJens Wiklander                                   N->p, N->limbs,
21032b31808SJens Wiklander                                   N->rep.mont.rr,
21132b31808SJens Wiklander                                   working_memory);
21232b31808SJens Wiklander     return 0;
21332b31808SJens Wiklander }
21432b31808SJens Wiklander 
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)21532b31808SJens Wiklander static int mbedtls_mpi_mod_inv_non_mont(mbedtls_mpi_mod_residue *X,
21632b31808SJens Wiklander                                         const mbedtls_mpi_mod_residue *A,
21732b31808SJens Wiklander                                         const mbedtls_mpi_mod_modulus *N,
21832b31808SJens Wiklander                                         mbedtls_mpi_uint *working_memory)
21932b31808SJens Wiklander {
22032b31808SJens Wiklander     /* Need to convert input into Montgomery form */
22132b31808SJens Wiklander 
22232b31808SJens Wiklander     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
22332b31808SJens Wiklander 
22432b31808SJens Wiklander     mbedtls_mpi_mod_modulus Nmont;
22532b31808SJens Wiklander     mbedtls_mpi_mod_modulus_init(&Nmont);
22632b31808SJens Wiklander 
227*b0563631STom Van Eyck     MBEDTLS_MPI_CHK(mbedtls_mpi_mod_modulus_setup(&Nmont, N->p, N->limbs));
22832b31808SJens Wiklander 
22932b31808SJens Wiklander     /* We'll use X->p to hold the Montgomery form of the input A->p */
23032b31808SJens Wiklander     mbedtls_mpi_core_to_mont_rep(X->p, A->p, Nmont.p, Nmont.limbs,
23132b31808SJens Wiklander                                  Nmont.rep.mont.mm, Nmont.rep.mont.rr,
23232b31808SJens Wiklander                                  working_memory);
23332b31808SJens Wiklander 
23432b31808SJens Wiklander     mbedtls_mpi_mod_raw_inv_prime(X->p, X->p,
23532b31808SJens Wiklander                                   Nmont.p, Nmont.limbs,
23632b31808SJens Wiklander                                   Nmont.rep.mont.rr,
23732b31808SJens Wiklander                                   working_memory);
23832b31808SJens Wiklander 
23932b31808SJens Wiklander     /* And convert back from Montgomery form */
24032b31808SJens Wiklander 
24132b31808SJens Wiklander     mbedtls_mpi_core_from_mont_rep(X->p, X->p, Nmont.p, Nmont.limbs,
24232b31808SJens Wiklander                                    Nmont.rep.mont.mm, working_memory);
24332b31808SJens Wiklander 
24432b31808SJens Wiklander cleanup:
24532b31808SJens Wiklander     mbedtls_mpi_mod_modulus_free(&Nmont);
24632b31808SJens Wiklander     return ret;
24732b31808SJens Wiklander }
24832b31808SJens Wiklander 
mbedtls_mpi_mod_inv(mbedtls_mpi_mod_residue * X,const mbedtls_mpi_mod_residue * A,const mbedtls_mpi_mod_modulus * N)24932b31808SJens Wiklander int mbedtls_mpi_mod_inv(mbedtls_mpi_mod_residue *X,
25032b31808SJens Wiklander                         const mbedtls_mpi_mod_residue *A,
25132b31808SJens Wiklander                         const mbedtls_mpi_mod_modulus *N)
25232b31808SJens Wiklander {
25332b31808SJens Wiklander     if (X->limbs != N->limbs || A->limbs != N->limbs) {
25432b31808SJens Wiklander         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
25532b31808SJens Wiklander     }
25632b31808SJens Wiklander 
25732b31808SJens Wiklander     /* Zero has the same value regardless of Montgomery form or not */
25832b31808SJens Wiklander     if (mbedtls_mpi_core_check_zero_ct(A->p, A->limbs) == 0) {
25932b31808SJens Wiklander         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
26032b31808SJens Wiklander     }
26132b31808SJens Wiklander 
26232b31808SJens Wiklander     size_t working_limbs =
26332b31808SJens Wiklander         mbedtls_mpi_mod_raw_inv_prime_working_limbs(N->limbs);
26432b31808SJens Wiklander 
26532b31808SJens Wiklander     mbedtls_mpi_uint *working_memory = mbedtls_calloc(working_limbs,
26632b31808SJens Wiklander                                                       sizeof(mbedtls_mpi_uint));
26732b31808SJens Wiklander     if (working_memory == NULL) {
26832b31808SJens Wiklander         return MBEDTLS_ERR_MPI_ALLOC_FAILED;
26932b31808SJens Wiklander     }
27032b31808SJens Wiklander 
27132b31808SJens Wiklander     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
27232b31808SJens Wiklander 
27332b31808SJens Wiklander     switch (N->int_rep) {
27432b31808SJens Wiklander         case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
27532b31808SJens Wiklander             ret = mbedtls_mpi_mod_inv_mont(X, A, N, working_memory);
27632b31808SJens Wiklander             break;
27732b31808SJens Wiklander         case MBEDTLS_MPI_MOD_REP_OPT_RED:
27832b31808SJens Wiklander             ret = mbedtls_mpi_mod_inv_non_mont(X, A, N, working_memory);
27932b31808SJens Wiklander             break;
28032b31808SJens Wiklander         default:
28132b31808SJens Wiklander             ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
28232b31808SJens Wiklander             break;
28332b31808SJens Wiklander     }
28432b31808SJens Wiklander 
285*b0563631STom Van Eyck     mbedtls_zeroize_and_free(working_memory,
28632b31808SJens Wiklander                              working_limbs * sizeof(mbedtls_mpi_uint));
28732b31808SJens Wiklander 
28832b31808SJens Wiklander     return ret;
28932b31808SJens Wiklander }
29032b31808SJens Wiklander 
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)29132b31808SJens Wiklander int mbedtls_mpi_mod_add(mbedtls_mpi_mod_residue *X,
29232b31808SJens Wiklander                         const mbedtls_mpi_mod_residue *A,
29332b31808SJens Wiklander                         const mbedtls_mpi_mod_residue *B,
29432b31808SJens Wiklander                         const mbedtls_mpi_mod_modulus *N)
29532b31808SJens Wiklander {
29632b31808SJens Wiklander     if (X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs) {
29732b31808SJens Wiklander         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
29832b31808SJens Wiklander     }
29932b31808SJens Wiklander 
30032b31808SJens Wiklander     mbedtls_mpi_mod_raw_add(X->p, A->p, B->p, N);
30132b31808SJens Wiklander 
30232b31808SJens Wiklander     return 0;
30332b31808SJens Wiklander }
30432b31808SJens Wiklander 
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)30532b31808SJens Wiklander int mbedtls_mpi_mod_random(mbedtls_mpi_mod_residue *X,
30632b31808SJens Wiklander                            mbedtls_mpi_uint min,
30732b31808SJens Wiklander                            const mbedtls_mpi_mod_modulus *N,
30832b31808SJens Wiklander                            int (*f_rng)(void *, unsigned char *, size_t),
30932b31808SJens Wiklander                            void *p_rng)
31032b31808SJens Wiklander {
31132b31808SJens Wiklander     if (X->limbs != N->limbs) {
31232b31808SJens Wiklander         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
31332b31808SJens Wiklander     }
31432b31808SJens Wiklander     return mbedtls_mpi_mod_raw_random(X->p, min, N, f_rng, p_rng);
31532b31808SJens Wiklander }
31632b31808SJens Wiklander 
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)31732b31808SJens Wiklander int mbedtls_mpi_mod_read(mbedtls_mpi_mod_residue *r,
31832b31808SJens Wiklander                          const mbedtls_mpi_mod_modulus *N,
31932b31808SJens Wiklander                          const unsigned char *buf,
32032b31808SJens Wiklander                          size_t buflen,
32132b31808SJens Wiklander                          mbedtls_mpi_mod_ext_rep ext_rep)
32232b31808SJens Wiklander {
32332b31808SJens Wiklander     int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
32432b31808SJens Wiklander 
32532b31808SJens Wiklander     /* Do our best to check if r and m have been set up */
32632b31808SJens Wiklander     if (r->limbs == 0 || N->limbs == 0) {
32732b31808SJens Wiklander         goto cleanup;
32832b31808SJens Wiklander     }
32932b31808SJens Wiklander     if (r->limbs != N->limbs) {
33032b31808SJens Wiklander         goto cleanup;
33132b31808SJens Wiklander     }
33232b31808SJens Wiklander 
33332b31808SJens Wiklander     ret = mbedtls_mpi_mod_raw_read(r->p, N, buf, buflen, ext_rep);
33432b31808SJens Wiklander     if (ret != 0) {
33532b31808SJens Wiklander         goto cleanup;
33632b31808SJens Wiklander     }
33732b31808SJens Wiklander 
33832b31808SJens Wiklander     r->limbs = N->limbs;
33932b31808SJens Wiklander 
34032b31808SJens Wiklander     ret = mbedtls_mpi_mod_raw_canonical_to_modulus_rep(r->p, N);
34132b31808SJens Wiklander 
34232b31808SJens Wiklander cleanup:
34332b31808SJens Wiklander     return ret;
34432b31808SJens Wiklander }
34532b31808SJens Wiklander 
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)34632b31808SJens Wiklander int mbedtls_mpi_mod_write(const mbedtls_mpi_mod_residue *r,
34732b31808SJens Wiklander                           const mbedtls_mpi_mod_modulus *N,
34832b31808SJens Wiklander                           unsigned char *buf,
34932b31808SJens Wiklander                           size_t buflen,
35032b31808SJens Wiklander                           mbedtls_mpi_mod_ext_rep ext_rep)
35132b31808SJens Wiklander {
35232b31808SJens Wiklander     /* Do our best to check if r and m have been set up */
35332b31808SJens Wiklander     if (r->limbs == 0 || N->limbs == 0) {
354*b0563631STom Van Eyck         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
35532b31808SJens Wiklander     }
35632b31808SJens Wiklander     if (r->limbs != N->limbs) {
357*b0563631STom Van Eyck         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
358*b0563631STom Van Eyck     }
359*b0563631STom Van Eyck 
360*b0563631STom Van Eyck     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
361*b0563631STom Van Eyck     mbedtls_mpi_uint *working_memory = r->p;
362*b0563631STom Van Eyck     size_t working_memory_len = sizeof(mbedtls_mpi_uint) * r->limbs;
363*b0563631STom Van Eyck 
364*b0563631STom Van Eyck     if (N->int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY) {
365*b0563631STom Van Eyck 
366*b0563631STom Van Eyck         working_memory = mbedtls_calloc(r->limbs, sizeof(mbedtls_mpi_uint));
367*b0563631STom Van Eyck 
368*b0563631STom Van Eyck         if (working_memory == NULL) {
369*b0563631STom Van Eyck             ret = MBEDTLS_ERR_MPI_ALLOC_FAILED;
37032b31808SJens Wiklander             goto cleanup;
37132b31808SJens Wiklander         }
37232b31808SJens Wiklander 
373*b0563631STom Van Eyck         memcpy(working_memory, r->p, working_memory_len);
374*b0563631STom Van Eyck 
375*b0563631STom Van Eyck         ret = mbedtls_mpi_mod_raw_from_mont_rep(working_memory, N);
37632b31808SJens Wiklander         if (ret != 0) {
37732b31808SJens Wiklander             goto cleanup;
37832b31808SJens Wiklander         }
37932b31808SJens Wiklander     }
38032b31808SJens Wiklander 
381*b0563631STom Van Eyck     ret = mbedtls_mpi_mod_raw_write(working_memory, N, buf, buflen, ext_rep);
38232b31808SJens Wiklander 
38332b31808SJens Wiklander cleanup:
38432b31808SJens Wiklander 
385*b0563631STom Van Eyck     if (N->int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY &&
386*b0563631STom Van Eyck         working_memory != NULL) {
387*b0563631STom Van Eyck 
388*b0563631STom Van Eyck         mbedtls_zeroize_and_free(working_memory, working_memory_len);
389*b0563631STom Van Eyck     }
390*b0563631STom Van Eyck 
39132b31808SJens Wiklander     return ret;
39232b31808SJens Wiklander }
39332b31808SJens Wiklander 
394*b0563631STom Van Eyck #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ECP_WITH_MPI_UINT */
395