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