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