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