1*32b31808SJens Wiklander /* 2*32b31808SJens Wiklander * Low-level modular bignum functions 3*32b31808SJens Wiklander * 4*32b31808SJens Wiklander * Copyright The Mbed TLS Contributors 5*32b31808SJens Wiklander * SPDX-License-Identifier: Apache-2.0 6*32b31808SJens Wiklander * 7*32b31808SJens Wiklander * Licensed under the Apache License, Version 2.0 (the "License"); you may 8*32b31808SJens Wiklander * not use this file except in compliance with the License. 9*32b31808SJens Wiklander * You may obtain a copy of the License at 10*32b31808SJens Wiklander * 11*32b31808SJens Wiklander * http://www.apache.org/licenses/LICENSE-2.0 12*32b31808SJens Wiklander * 13*32b31808SJens Wiklander * Unless required by applicable law or agreed to in writing, software 14*32b31808SJens Wiklander * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15*32b31808SJens Wiklander * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16*32b31808SJens Wiklander * See the License for the specific language governing permissions and 17*32b31808SJens Wiklander * limitations under the License. 18*32b31808SJens Wiklander */ 19*32b31808SJens Wiklander 20*32b31808SJens Wiklander #include "common.h" 21*32b31808SJens Wiklander 22*32b31808SJens Wiklander #if defined(MBEDTLS_BIGNUM_C) 23*32b31808SJens Wiklander 24*32b31808SJens Wiklander #include <string.h> 25*32b31808SJens Wiklander 26*32b31808SJens Wiklander #include "mbedtls/error.h" 27*32b31808SJens Wiklander #include "mbedtls/platform_util.h" 28*32b31808SJens Wiklander 29*32b31808SJens Wiklander #include "mbedtls/platform.h" 30*32b31808SJens Wiklander 31*32b31808SJens Wiklander #include "bignum_core.h" 32*32b31808SJens Wiklander #include "bignum_mod_raw.h" 33*32b31808SJens Wiklander #include "bignum_mod.h" 34*32b31808SJens Wiklander #include "constant_time_internal.h" 35*32b31808SJens Wiklander 36*32b31808SJens Wiklander #include "bignum_mod_raw_invasive.h" 37*32b31808SJens Wiklander 38*32b31808SJens Wiklander void mbedtls_mpi_mod_raw_cond_assign(mbedtls_mpi_uint *X, 39*32b31808SJens Wiklander const mbedtls_mpi_uint *A, 40*32b31808SJens Wiklander const mbedtls_mpi_mod_modulus *N, 41*32b31808SJens Wiklander unsigned char assign) 42*32b31808SJens Wiklander { 43*32b31808SJens Wiklander mbedtls_mpi_core_cond_assign(X, A, N->limbs, assign); 44*32b31808SJens Wiklander } 45*32b31808SJens Wiklander 46*32b31808SJens Wiklander void mbedtls_mpi_mod_raw_cond_swap(mbedtls_mpi_uint *X, 47*32b31808SJens Wiklander mbedtls_mpi_uint *Y, 48*32b31808SJens Wiklander const mbedtls_mpi_mod_modulus *N, 49*32b31808SJens Wiklander unsigned char swap) 50*32b31808SJens Wiklander { 51*32b31808SJens Wiklander mbedtls_mpi_core_cond_swap(X, Y, N->limbs, swap); 52*32b31808SJens Wiklander } 53*32b31808SJens Wiklander 54*32b31808SJens Wiklander int mbedtls_mpi_mod_raw_read(mbedtls_mpi_uint *X, 55*32b31808SJens Wiklander const mbedtls_mpi_mod_modulus *N, 56*32b31808SJens Wiklander const unsigned char *input, 57*32b31808SJens Wiklander size_t input_length, 58*32b31808SJens Wiklander mbedtls_mpi_mod_ext_rep ext_rep) 59*32b31808SJens Wiklander { 60*32b31808SJens Wiklander int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 61*32b31808SJens Wiklander 62*32b31808SJens Wiklander switch (ext_rep) { 63*32b31808SJens Wiklander case MBEDTLS_MPI_MOD_EXT_REP_LE: 64*32b31808SJens Wiklander ret = mbedtls_mpi_core_read_le(X, N->limbs, 65*32b31808SJens Wiklander input, input_length); 66*32b31808SJens Wiklander break; 67*32b31808SJens Wiklander case MBEDTLS_MPI_MOD_EXT_REP_BE: 68*32b31808SJens Wiklander ret = mbedtls_mpi_core_read_be(X, N->limbs, 69*32b31808SJens Wiklander input, input_length); 70*32b31808SJens Wiklander break; 71*32b31808SJens Wiklander default: 72*32b31808SJens Wiklander return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 73*32b31808SJens Wiklander } 74*32b31808SJens Wiklander 75*32b31808SJens Wiklander if (ret != 0) { 76*32b31808SJens Wiklander goto cleanup; 77*32b31808SJens Wiklander } 78*32b31808SJens Wiklander 79*32b31808SJens Wiklander if (!mbedtls_mpi_core_lt_ct(X, N->p, N->limbs)) { 80*32b31808SJens Wiklander ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 81*32b31808SJens Wiklander goto cleanup; 82*32b31808SJens Wiklander } 83*32b31808SJens Wiklander 84*32b31808SJens Wiklander cleanup: 85*32b31808SJens Wiklander 86*32b31808SJens Wiklander return ret; 87*32b31808SJens Wiklander } 88*32b31808SJens Wiklander 89*32b31808SJens Wiklander int mbedtls_mpi_mod_raw_write(const mbedtls_mpi_uint *A, 90*32b31808SJens Wiklander const mbedtls_mpi_mod_modulus *N, 91*32b31808SJens Wiklander unsigned char *output, 92*32b31808SJens Wiklander size_t output_length, 93*32b31808SJens Wiklander mbedtls_mpi_mod_ext_rep ext_rep) 94*32b31808SJens Wiklander { 95*32b31808SJens Wiklander switch (ext_rep) { 96*32b31808SJens Wiklander case MBEDTLS_MPI_MOD_EXT_REP_LE: 97*32b31808SJens Wiklander return mbedtls_mpi_core_write_le(A, N->limbs, 98*32b31808SJens Wiklander output, output_length); 99*32b31808SJens Wiklander case MBEDTLS_MPI_MOD_EXT_REP_BE: 100*32b31808SJens Wiklander return mbedtls_mpi_core_write_be(A, N->limbs, 101*32b31808SJens Wiklander output, output_length); 102*32b31808SJens Wiklander default: 103*32b31808SJens Wiklander return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 104*32b31808SJens Wiklander } 105*32b31808SJens Wiklander } 106*32b31808SJens Wiklander 107*32b31808SJens Wiklander /* BEGIN MERGE SLOT 1 */ 108*32b31808SJens Wiklander 109*32b31808SJens Wiklander /* END MERGE SLOT 1 */ 110*32b31808SJens Wiklander 111*32b31808SJens Wiklander /* BEGIN MERGE SLOT 2 */ 112*32b31808SJens Wiklander 113*32b31808SJens Wiklander void mbedtls_mpi_mod_raw_sub(mbedtls_mpi_uint *X, 114*32b31808SJens Wiklander const mbedtls_mpi_uint *A, 115*32b31808SJens Wiklander const mbedtls_mpi_uint *B, 116*32b31808SJens Wiklander const mbedtls_mpi_mod_modulus *N) 117*32b31808SJens Wiklander { 118*32b31808SJens Wiklander mbedtls_mpi_uint c = mbedtls_mpi_core_sub(X, A, B, N->limbs); 119*32b31808SJens Wiklander 120*32b31808SJens Wiklander (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) c); 121*32b31808SJens Wiklander } 122*32b31808SJens Wiklander 123*32b31808SJens Wiklander #if defined(MBEDTLS_TEST_HOOKS) 124*32b31808SJens Wiklander 125*32b31808SJens Wiklander MBEDTLS_STATIC_TESTABLE 126*32b31808SJens Wiklander void mbedtls_mpi_mod_raw_fix_quasi_reduction(mbedtls_mpi_uint *X, 127*32b31808SJens Wiklander const mbedtls_mpi_mod_modulus *N) 128*32b31808SJens Wiklander { 129*32b31808SJens Wiklander mbedtls_mpi_uint c = mbedtls_mpi_core_sub(X, X, N->p, N->limbs); 130*32b31808SJens Wiklander 131*32b31808SJens Wiklander (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) c); 132*32b31808SJens Wiklander } 133*32b31808SJens Wiklander 134*32b31808SJens Wiklander #endif /* MBEDTLS_TEST_HOOKS */ 135*32b31808SJens Wiklander 136*32b31808SJens Wiklander void mbedtls_mpi_mod_raw_mul(mbedtls_mpi_uint *X, 137*32b31808SJens Wiklander const mbedtls_mpi_uint *A, 138*32b31808SJens Wiklander const mbedtls_mpi_uint *B, 139*32b31808SJens Wiklander const mbedtls_mpi_mod_modulus *N, 140*32b31808SJens Wiklander mbedtls_mpi_uint *T) 141*32b31808SJens Wiklander { 142*32b31808SJens Wiklander mbedtls_mpi_core_montmul(X, A, B, N->limbs, N->p, N->limbs, 143*32b31808SJens Wiklander N->rep.mont.mm, T); 144*32b31808SJens Wiklander } 145*32b31808SJens Wiklander 146*32b31808SJens Wiklander /* END MERGE SLOT 2 */ 147*32b31808SJens Wiklander 148*32b31808SJens Wiklander /* BEGIN MERGE SLOT 3 */ 149*32b31808SJens Wiklander 150*32b31808SJens Wiklander size_t mbedtls_mpi_mod_raw_inv_prime_working_limbs(size_t AN_limbs) 151*32b31808SJens Wiklander { 152*32b31808SJens Wiklander /* mbedtls_mpi_mod_raw_inv_prime() needs a temporary for the exponent, 153*32b31808SJens Wiklander * which will be the same size as the modulus and input (AN_limbs), 154*32b31808SJens Wiklander * and additional space to pass to mbedtls_mpi_core_exp_mod(). */ 155*32b31808SJens Wiklander return AN_limbs + 156*32b31808SJens Wiklander mbedtls_mpi_core_exp_mod_working_limbs(AN_limbs, AN_limbs); 157*32b31808SJens Wiklander } 158*32b31808SJens Wiklander 159*32b31808SJens Wiklander void mbedtls_mpi_mod_raw_inv_prime(mbedtls_mpi_uint *X, 160*32b31808SJens Wiklander const mbedtls_mpi_uint *A, 161*32b31808SJens Wiklander const mbedtls_mpi_uint *N, 162*32b31808SJens Wiklander size_t AN_limbs, 163*32b31808SJens Wiklander const mbedtls_mpi_uint *RR, 164*32b31808SJens Wiklander mbedtls_mpi_uint *T) 165*32b31808SJens Wiklander { 166*32b31808SJens Wiklander /* Inversion by power: g^|G| = 1 => g^(-1) = g^(|G|-1), and 167*32b31808SJens Wiklander * |G| = N - 1, so we want 168*32b31808SJens Wiklander * g^(|G|-1) = g^(N - 2) 169*32b31808SJens Wiklander */ 170*32b31808SJens Wiklander 171*32b31808SJens Wiklander /* Use the first AN_limbs of T to hold N - 2 */ 172*32b31808SJens Wiklander mbedtls_mpi_uint *Nminus2 = T; 173*32b31808SJens Wiklander (void) mbedtls_mpi_core_sub_int(Nminus2, N, 2, AN_limbs); 174*32b31808SJens Wiklander 175*32b31808SJens Wiklander /* Rest of T is given to exp_mod for its working space */ 176*32b31808SJens Wiklander mbedtls_mpi_core_exp_mod(X, 177*32b31808SJens Wiklander A, N, AN_limbs, Nminus2, AN_limbs, 178*32b31808SJens Wiklander RR, T + AN_limbs); 179*32b31808SJens Wiklander } 180*32b31808SJens Wiklander 181*32b31808SJens Wiklander /* END MERGE SLOT 3 */ 182*32b31808SJens Wiklander 183*32b31808SJens Wiklander /* BEGIN MERGE SLOT 4 */ 184*32b31808SJens Wiklander 185*32b31808SJens Wiklander /* END MERGE SLOT 4 */ 186*32b31808SJens Wiklander 187*32b31808SJens Wiklander /* BEGIN MERGE SLOT 5 */ 188*32b31808SJens Wiklander void mbedtls_mpi_mod_raw_add(mbedtls_mpi_uint *X, 189*32b31808SJens Wiklander const mbedtls_mpi_uint *A, 190*32b31808SJens Wiklander const mbedtls_mpi_uint *B, 191*32b31808SJens Wiklander const mbedtls_mpi_mod_modulus *N) 192*32b31808SJens Wiklander { 193*32b31808SJens Wiklander mbedtls_mpi_uint carry, borrow; 194*32b31808SJens Wiklander carry = mbedtls_mpi_core_add(X, A, B, N->limbs); 195*32b31808SJens Wiklander borrow = mbedtls_mpi_core_sub(X, X, N->p, N->limbs); 196*32b31808SJens Wiklander (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) (carry ^ borrow)); 197*32b31808SJens Wiklander } 198*32b31808SJens Wiklander /* END MERGE SLOT 5 */ 199*32b31808SJens Wiklander 200*32b31808SJens Wiklander /* BEGIN MERGE SLOT 6 */ 201*32b31808SJens Wiklander 202*32b31808SJens Wiklander int mbedtls_mpi_mod_raw_canonical_to_modulus_rep( 203*32b31808SJens Wiklander mbedtls_mpi_uint *X, 204*32b31808SJens Wiklander const mbedtls_mpi_mod_modulus *N) 205*32b31808SJens Wiklander { 206*32b31808SJens Wiklander switch (N->int_rep) { 207*32b31808SJens Wiklander case MBEDTLS_MPI_MOD_REP_MONTGOMERY: 208*32b31808SJens Wiklander return mbedtls_mpi_mod_raw_to_mont_rep(X, N); 209*32b31808SJens Wiklander case MBEDTLS_MPI_MOD_REP_OPT_RED: 210*32b31808SJens Wiklander return 0; 211*32b31808SJens Wiklander default: 212*32b31808SJens Wiklander return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 213*32b31808SJens Wiklander } 214*32b31808SJens Wiklander } 215*32b31808SJens Wiklander 216*32b31808SJens Wiklander int mbedtls_mpi_mod_raw_modulus_to_canonical_rep( 217*32b31808SJens Wiklander mbedtls_mpi_uint *X, 218*32b31808SJens Wiklander const mbedtls_mpi_mod_modulus *N) 219*32b31808SJens Wiklander { 220*32b31808SJens Wiklander switch (N->int_rep) { 221*32b31808SJens Wiklander case MBEDTLS_MPI_MOD_REP_MONTGOMERY: 222*32b31808SJens Wiklander return mbedtls_mpi_mod_raw_from_mont_rep(X, N); 223*32b31808SJens Wiklander case MBEDTLS_MPI_MOD_REP_OPT_RED: 224*32b31808SJens Wiklander return 0; 225*32b31808SJens Wiklander default: 226*32b31808SJens Wiklander return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 227*32b31808SJens Wiklander } 228*32b31808SJens Wiklander } 229*32b31808SJens Wiklander 230*32b31808SJens Wiklander int mbedtls_mpi_mod_raw_random(mbedtls_mpi_uint *X, 231*32b31808SJens Wiklander mbedtls_mpi_uint min, 232*32b31808SJens Wiklander const mbedtls_mpi_mod_modulus *N, 233*32b31808SJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 234*32b31808SJens Wiklander void *p_rng) 235*32b31808SJens Wiklander { 236*32b31808SJens Wiklander int ret = mbedtls_mpi_core_random(X, min, N->p, N->limbs, f_rng, p_rng); 237*32b31808SJens Wiklander if (ret != 0) { 238*32b31808SJens Wiklander return ret; 239*32b31808SJens Wiklander } 240*32b31808SJens Wiklander return mbedtls_mpi_mod_raw_canonical_to_modulus_rep(X, N); 241*32b31808SJens Wiklander } 242*32b31808SJens Wiklander 243*32b31808SJens Wiklander /* END MERGE SLOT 6 */ 244*32b31808SJens Wiklander 245*32b31808SJens Wiklander /* BEGIN MERGE SLOT 7 */ 246*32b31808SJens Wiklander int mbedtls_mpi_mod_raw_to_mont_rep(mbedtls_mpi_uint *X, 247*32b31808SJens Wiklander const mbedtls_mpi_mod_modulus *N) 248*32b31808SJens Wiklander { 249*32b31808SJens Wiklander mbedtls_mpi_uint *T; 250*32b31808SJens Wiklander const size_t t_limbs = mbedtls_mpi_core_montmul_working_limbs(N->limbs); 251*32b31808SJens Wiklander 252*32b31808SJens Wiklander if ((T = (mbedtls_mpi_uint *) mbedtls_calloc(t_limbs, ciL)) == NULL) { 253*32b31808SJens Wiklander return MBEDTLS_ERR_MPI_ALLOC_FAILED; 254*32b31808SJens Wiklander } 255*32b31808SJens Wiklander 256*32b31808SJens Wiklander mbedtls_mpi_core_to_mont_rep(X, X, N->p, N->limbs, 257*32b31808SJens Wiklander N->rep.mont.mm, N->rep.mont.rr, T); 258*32b31808SJens Wiklander 259*32b31808SJens Wiklander mbedtls_platform_zeroize(T, t_limbs * ciL); 260*32b31808SJens Wiklander mbedtls_free(T); 261*32b31808SJens Wiklander return 0; 262*32b31808SJens Wiklander } 263*32b31808SJens Wiklander 264*32b31808SJens Wiklander int mbedtls_mpi_mod_raw_from_mont_rep(mbedtls_mpi_uint *X, 265*32b31808SJens Wiklander const mbedtls_mpi_mod_modulus *N) 266*32b31808SJens Wiklander { 267*32b31808SJens Wiklander const size_t t_limbs = mbedtls_mpi_core_montmul_working_limbs(N->limbs); 268*32b31808SJens Wiklander mbedtls_mpi_uint *T; 269*32b31808SJens Wiklander 270*32b31808SJens Wiklander if ((T = (mbedtls_mpi_uint *) mbedtls_calloc(t_limbs, ciL)) == NULL) { 271*32b31808SJens Wiklander return MBEDTLS_ERR_MPI_ALLOC_FAILED; 272*32b31808SJens Wiklander } 273*32b31808SJens Wiklander 274*32b31808SJens Wiklander mbedtls_mpi_core_from_mont_rep(X, X, N->p, N->limbs, N->rep.mont.mm, T); 275*32b31808SJens Wiklander 276*32b31808SJens Wiklander mbedtls_platform_zeroize(T, t_limbs * ciL); 277*32b31808SJens Wiklander mbedtls_free(T); 278*32b31808SJens Wiklander return 0; 279*32b31808SJens Wiklander } 280*32b31808SJens Wiklander 281*32b31808SJens Wiklander void mbedtls_mpi_mod_raw_neg(mbedtls_mpi_uint *X, 282*32b31808SJens Wiklander const mbedtls_mpi_uint *A, 283*32b31808SJens Wiklander const mbedtls_mpi_mod_modulus *N) 284*32b31808SJens Wiklander { 285*32b31808SJens Wiklander mbedtls_mpi_core_sub(X, N->p, A, N->limbs); 286*32b31808SJens Wiklander 287*32b31808SJens Wiklander /* If A=0 initially, then X=N now. Detect this by 288*32b31808SJens Wiklander * subtracting N and catching the carry. */ 289*32b31808SJens Wiklander mbedtls_mpi_uint borrow = mbedtls_mpi_core_sub(X, X, N->p, N->limbs); 290*32b31808SJens Wiklander (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) borrow); 291*32b31808SJens Wiklander } 292*32b31808SJens Wiklander /* END MERGE SLOT 7 */ 293*32b31808SJens Wiklander 294*32b31808SJens Wiklander /* BEGIN MERGE SLOT 8 */ 295*32b31808SJens Wiklander 296*32b31808SJens Wiklander /* END MERGE SLOT 8 */ 297*32b31808SJens Wiklander 298*32b31808SJens Wiklander /* BEGIN MERGE SLOT 9 */ 299*32b31808SJens Wiklander 300*32b31808SJens Wiklander /* END MERGE SLOT 9 */ 301*32b31808SJens Wiklander 302*32b31808SJens Wiklander /* BEGIN MERGE SLOT 10 */ 303*32b31808SJens Wiklander 304*32b31808SJens Wiklander /* END MERGE SLOT 10 */ 305*32b31808SJens Wiklander 306*32b31808SJens Wiklander #endif /* MBEDTLS_BIGNUM_C */ 307