1817466cbSJens Wiklander /* 2817466cbSJens Wiklander * Multi-precision integer library 3817466cbSJens Wiklander * 47901324dSJerome Forissier * Copyright The Mbed TLS Contributors 5b0563631STom Van Eyck * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 6817466cbSJens Wiklander */ 7817466cbSJens Wiklander 8817466cbSJens Wiklander /* 9817466cbSJens Wiklander * The following sources were referenced in the design of this Multi-precision 10817466cbSJens Wiklander * Integer library: 11817466cbSJens Wiklander * 12817466cbSJens Wiklander * [1] Handbook of Applied Cryptography - 1997 13817466cbSJens Wiklander * Menezes, van Oorschot and Vanstone 14817466cbSJens Wiklander * 15817466cbSJens Wiklander * [2] Multi-Precision Math 16817466cbSJens Wiklander * Tom St Denis 17817466cbSJens Wiklander * https://github.com/libtom/libtommath/blob/develop/tommath.pdf 18817466cbSJens Wiklander * 19817466cbSJens Wiklander * [3] GNU Multi-Precision Arithmetic Library 20817466cbSJens Wiklander * https://gmplib.org/manual/index.html 21817466cbSJens Wiklander * 22817466cbSJens Wiklander */ 23817466cbSJens Wiklander 247901324dSJerome Forissier #include "common.h" 25817466cbSJens Wiklander 26817466cbSJens Wiklander #if defined(MBEDTLS_BIGNUM_C) 27817466cbSJens Wiklander 28817466cbSJens Wiklander #include "mbedtls/bignum.h" 2932b31808SJens Wiklander #include "bignum_core.h" 30*cb034002SJerome Forissier #include "bignum_internal.h" 3132b31808SJens Wiklander #include "bn_mul.h" 323d3b0591SJens Wiklander #include "mbedtls/platform_util.h" 3311fa71b9SJerome Forissier #include "mbedtls/error.h" 34039e02dfSJerome Forissier #include "constant_time_internal.h" 35817466cbSJens Wiklander 36039e02dfSJerome Forissier #include <limits.h> 37817466cbSJens Wiklander #include <string.h> 38817466cbSJens Wiklander 39817466cbSJens Wiklander #include "mbedtls/platform.h" 40817466cbSJens Wiklander 4198bd5fe3SJens Wiklander #include <mempool.h> 42817466cbSJens Wiklander 4398bd5fe3SJens Wiklander void *mbedtls_mpi_mempool; 4498bd5fe3SJens Wiklander 45b0563631STom Van Eyck 46b0563631STom Van Eyck /* 47b0563631STom Van Eyck * Conditionally select an MPI sign in constant time. 48b0563631STom Van Eyck * (MPI sign is the field s in mbedtls_mpi. It is unsigned short and only 1 and -1 are valid 49b0563631STom Van Eyck * values.) 50b0563631STom Van Eyck */ 51b0563631STom Van Eyck static inline signed short mbedtls_ct_mpi_sign_if(mbedtls_ct_condition_t cond, 52b0563631STom Van Eyck signed short sign1, signed short sign2) 533d3b0591SJens Wiklander { 54b0563631STom Van Eyck return (signed short) mbedtls_ct_uint_if(cond, sign1 + 1, sign2 + 1) - 1; 553d3b0591SJens Wiklander } 563d3b0591SJens Wiklander 57817466cbSJens Wiklander /* 58b0563631STom Van Eyck * Compare signed values in constant time 59b0563631STom Van Eyck */ 60b0563631STom Van Eyck int mbedtls_mpi_lt_mpi_ct(const mbedtls_mpi *X, 61b0563631STom Van Eyck const mbedtls_mpi *Y, 62b0563631STom Van Eyck unsigned *ret) 63b0563631STom Van Eyck { 64b0563631STom Van Eyck mbedtls_ct_condition_t different_sign, X_is_negative, Y_is_negative, result; 65b0563631STom Van Eyck 66b0563631STom Van Eyck if (X->n != Y->n) { 67b0563631STom Van Eyck return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 68b0563631STom Van Eyck } 69b0563631STom Van Eyck 70b0563631STom Van Eyck /* 71b0563631STom Van Eyck * Set N_is_negative to MBEDTLS_CT_FALSE if N >= 0, MBEDTLS_CT_TRUE if N < 0. 72b0563631STom Van Eyck * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0. 73b0563631STom Van Eyck */ 74b0563631STom Van Eyck X_is_negative = mbedtls_ct_bool((X->s & 2) >> 1); 75b0563631STom Van Eyck Y_is_negative = mbedtls_ct_bool((Y->s & 2) >> 1); 76b0563631STom Van Eyck 77b0563631STom Van Eyck /* 78b0563631STom Van Eyck * If the signs are different, then the positive operand is the bigger. 79b0563631STom Van Eyck * That is if X is negative (X_is_negative == 1), then X < Y is true and it 80b0563631STom Van Eyck * is false if X is positive (X_is_negative == 0). 81b0563631STom Van Eyck */ 82b0563631STom Van Eyck different_sign = mbedtls_ct_bool_ne(X_is_negative, Y_is_negative); // true if different sign 83b0563631STom Van Eyck result = mbedtls_ct_bool_and(different_sign, X_is_negative); 84b0563631STom Van Eyck 85b0563631STom Van Eyck /* 86b0563631STom Van Eyck * Assuming signs are the same, compare X and Y. We switch the comparison 87b0563631STom Van Eyck * order if they are negative so that we get the right result, regardles of 88b0563631STom Van Eyck * sign. 89b0563631STom Van Eyck */ 90b0563631STom Van Eyck 91b0563631STom Van Eyck /* This array is used to conditionally swap the pointers in const time */ 92b0563631STom Van Eyck void * const p[2] = { X->p, Y->p }; 93b0563631STom Van Eyck size_t i = mbedtls_ct_size_if_else_0(X_is_negative, 1); 94b0563631STom Van Eyck mbedtls_ct_condition_t lt = mbedtls_mpi_core_lt_ct(p[i], p[i ^ 1], X->n); 95b0563631STom Van Eyck 96b0563631STom Van Eyck /* 97b0563631STom Van Eyck * Store in result iff the signs are the same (i.e., iff different_sign == false). If 98b0563631STom Van Eyck * the signs differ, result has already been set, so we don't change it. 99b0563631STom Van Eyck */ 100b0563631STom Van Eyck result = mbedtls_ct_bool_or(result, 101b0563631STom Van Eyck mbedtls_ct_bool_and(mbedtls_ct_bool_not(different_sign), lt)); 102b0563631STom Van Eyck 103b0563631STom Van Eyck *ret = mbedtls_ct_uint_if_else_0(result, 1); 104b0563631STom Van Eyck 105b0563631STom Van Eyck return 0; 106b0563631STom Van Eyck } 107b0563631STom Van Eyck 108b0563631STom Van Eyck /* 109b0563631STom Van Eyck * Conditionally assign X = Y, without leaking information 110b0563631STom Van Eyck * about whether the assignment was made or not. 111b0563631STom Van Eyck * (Leaking information about the respective sizes of X and Y is ok however.) 112b0563631STom Van Eyck */ 113b0563631STom Van Eyck #if defined(_MSC_VER) && defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) && \ 114b0563631STom Van Eyck (_MSC_FULL_VER < 193131103) 115b0563631STom Van Eyck /* 116b0563631STom Van Eyck * MSVC miscompiles this function if it's inlined prior to Visual Studio 2022 version 17.1. See: 117b0563631STom Van Eyck * https://developercommunity.visualstudio.com/t/c-compiler-miscompiles-part-of-mbedtls-library-on/1646989 118b0563631STom Van Eyck */ 119b0563631STom Van Eyck __declspec(noinline) 120b0563631STom Van Eyck #endif 121b0563631STom Van Eyck int mbedtls_mpi_safe_cond_assign(mbedtls_mpi *X, 122b0563631STom Van Eyck const mbedtls_mpi *Y, 123b0563631STom Van Eyck unsigned char assign) 124b0563631STom Van Eyck { 125b0563631STom Van Eyck int ret = 0; 126b0563631STom Van Eyck 127b0563631STom Van Eyck MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n)); 128b0563631STom Van Eyck 129b0563631STom Van Eyck { 130b0563631STom Van Eyck mbedtls_ct_condition_t do_assign = mbedtls_ct_bool(assign); 131b0563631STom Van Eyck 132b0563631STom Van Eyck X->s = mbedtls_ct_mpi_sign_if(do_assign, Y->s, X->s); 133b0563631STom Van Eyck 134b0563631STom Van Eyck mbedtls_mpi_core_cond_assign(X->p, Y->p, Y->n, do_assign); 135b0563631STom Van Eyck 136b0563631STom Van Eyck mbedtls_ct_condition_t do_not_assign = mbedtls_ct_bool_not(do_assign); 137b0563631STom Van Eyck for (size_t i = Y->n; i < X->n; i++) { 138b0563631STom Van Eyck X->p[i] = mbedtls_ct_mpi_uint_if_else_0(do_not_assign, X->p[i]); 139b0563631STom Van Eyck } 140b0563631STom Van Eyck } 141b0563631STom Van Eyck 142b0563631STom Van Eyck cleanup: 143b0563631STom Van Eyck return ret; 144b0563631STom Van Eyck } 145b0563631STom Van Eyck 146b0563631STom Van Eyck /* 147b0563631STom Van Eyck * Conditionally swap X and Y, without leaking information 148b0563631STom Van Eyck * about whether the swap was made or not. 149b0563631STom Van Eyck * Here it is not ok to simply swap the pointers, which would lead to 150b0563631STom Van Eyck * different memory access patterns when X and Y are used afterwards. 151b0563631STom Van Eyck */ 152b0563631STom Van Eyck int mbedtls_mpi_safe_cond_swap(mbedtls_mpi *X, 153b0563631STom Van Eyck mbedtls_mpi *Y, 154b0563631STom Van Eyck unsigned char swap) 155b0563631STom Van Eyck { 156b0563631STom Van Eyck int ret = 0; 157b0563631STom Van Eyck int s; 158b0563631STom Van Eyck 159b0563631STom Van Eyck if (X == Y) { 160b0563631STom Van Eyck return 0; 161b0563631STom Van Eyck } 162b0563631STom Van Eyck 163b0563631STom Van Eyck mbedtls_ct_condition_t do_swap = mbedtls_ct_bool(swap); 164b0563631STom Van Eyck 165b0563631STom Van Eyck MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n)); 166b0563631STom Van Eyck MBEDTLS_MPI_CHK(mbedtls_mpi_grow(Y, X->n)); 167b0563631STom Van Eyck 168b0563631STom Van Eyck s = X->s; 169b0563631STom Van Eyck X->s = mbedtls_ct_mpi_sign_if(do_swap, Y->s, X->s); 170b0563631STom Van Eyck Y->s = mbedtls_ct_mpi_sign_if(do_swap, s, Y->s); 171b0563631STom Van Eyck 172b0563631STom Van Eyck mbedtls_mpi_core_cond_swap(X->p, Y->p, X->n, do_swap); 173b0563631STom Van Eyck 174b0563631STom Van Eyck cleanup: 175b0563631STom Van Eyck return ret; 176b0563631STom Van Eyck } 177b0563631STom Van Eyck 178b0563631STom Van Eyck /* Implementation that should never be optimized out by the compiler */ 179b0563631STom Van Eyck #define mbedtls_mpi_zeroize_and_free(v, n) mbedtls_zeroize_and_free(v, ciL * (n)) 180b0563631STom Van Eyck 181b0563631STom Van Eyck /* 182b0563631STom Van Eyck * Implementation that should never be optimized out by the compiler. 183b0563631STom Van Eyck * Reintroduced to allow use of mempool. 184b0563631STom Van Eyck */ 185b0563631STom Van Eyck #define mbedtls_mpi_zeroize(v, n) mbedtls_platform_zeroize(v, ciL * (n)) 186b0563631STom Van Eyck 187b0563631STom Van Eyck /* 188817466cbSJens Wiklander * Initialize one MPI 189817466cbSJens Wiklander */ 1903d3b0591SJens Wiklander static void mpi_init(mbedtls_mpi *X, short use_mempool) 191817466cbSJens Wiklander { 1923d3b0591SJens Wiklander X->s = 1; 1933d3b0591SJens Wiklander X->use_mempool = use_mempool; 1943d3b0591SJens Wiklander X->n = 0; 1953d3b0591SJens Wiklander X->p = NULL; 196817466cbSJens Wiklander } 197817466cbSJens Wiklander 19898bd5fe3SJens Wiklander void mbedtls_mpi_init(mbedtls_mpi *X) 19998bd5fe3SJens Wiklander { 2003d3b0591SJens Wiklander mpi_init(X, 0 /*use_mempool*/); 20198bd5fe3SJens Wiklander } 20298bd5fe3SJens Wiklander 20398bd5fe3SJens Wiklander void mbedtls_mpi_init_mempool(mbedtls_mpi *X) 20498bd5fe3SJens Wiklander { 2053d3b0591SJens Wiklander mpi_init(X, !!mbedtls_mpi_mempool /*use_mempool*/); 20698bd5fe3SJens Wiklander } 20798bd5fe3SJens Wiklander 208817466cbSJens Wiklander /* 209817466cbSJens Wiklander * Unallocate one MPI 210817466cbSJens Wiklander */ 211817466cbSJens Wiklander void mbedtls_mpi_free(mbedtls_mpi *X) 212817466cbSJens Wiklander { 21332b31808SJens Wiklander if (X == NULL) { 214817466cbSJens Wiklander return; 21532b31808SJens Wiklander } 216817466cbSJens Wiklander 21732b31808SJens Wiklander if (X->p != NULL) { 218b0563631STom Van Eyck if(X->use_mempool) { 219817466cbSJens Wiklander mbedtls_mpi_zeroize(X->p, X->n); 22018c5148dSJens Wiklander mempool_free(mbedtls_mpi_mempool, X->p); 221b0563631STom Van Eyck } else { 222b0563631STom Van Eyck mbedtls_mpi_zeroize_and_free(X->p, X->n); 223b0563631STom Van Eyck } 224817466cbSJens Wiklander } 225817466cbSJens Wiklander 226817466cbSJens Wiklander X->s = 1; 227817466cbSJens Wiklander X->n = 0; 2283d3b0591SJens Wiklander X->p = NULL; 229817466cbSJens Wiklander } 230817466cbSJens Wiklander 231817466cbSJens Wiklander /* 232817466cbSJens Wiklander * Enlarge to the specified number of limbs 233817466cbSJens Wiklander */ 234817466cbSJens Wiklander int mbedtls_mpi_grow(mbedtls_mpi *X, size_t nblimbs) 235817466cbSJens Wiklander { 236817466cbSJens Wiklander mbedtls_mpi_uint *p; 237817466cbSJens Wiklander 23832b31808SJens Wiklander if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) { 23932b31808SJens Wiklander return MBEDTLS_ERR_MPI_ALLOC_FAILED; 24032b31808SJens Wiklander } 241817466cbSJens Wiklander 24232b31808SJens Wiklander if (X->n < nblimbs) { 24332b31808SJens Wiklander if(X->use_mempool) { 2443d3b0591SJens Wiklander p = mempool_alloc(mbedtls_mpi_mempool, nblimbs * ciL); 24518c5148dSJens Wiklander if(p == NULL) 24632b31808SJens Wiklander return MBEDTLS_ERR_MPI_ALLOC_FAILED; 2473d3b0591SJens Wiklander memset(p, 0, nblimbs * ciL); 24832b31808SJens Wiklander } else { 2493d3b0591SJens Wiklander p = (mbedtls_mpi_uint *) mbedtls_calloc(nblimbs, ciL); 2503d3b0591SJens Wiklander if (p == NULL) 25132b31808SJens Wiklander return MBEDTLS_ERR_MPI_ALLOC_FAILED; 252817466cbSJens Wiklander } 253817466cbSJens Wiklander 25432b31808SJens Wiklander if (X->p != NULL) { 2553d3b0591SJens Wiklander memcpy(p, X->p, X->n * ciL); 256b0563631STom Van Eyck 257b0563631STom Van Eyck if (X->use_mempool) { 2583d3b0591SJens Wiklander mbedtls_mpi_zeroize(X->p, X->n); 25918c5148dSJens Wiklander mempool_free(mbedtls_mpi_mempool, X->p); 260b0563631STom Van Eyck } else { 261b0563631STom Van Eyck mbedtls_mpi_zeroize_and_free(X->p, X->n); 262b0563631STom Van Eyck } 2633d3b0591SJens Wiklander } 26418c5148dSJens Wiklander 265b0563631STom Van Eyck /* nblimbs fits in n because we ensure that MBEDTLS_MPI_MAX_LIMBS 266b0563631STom Van Eyck * fits, and we've checked that nblimbs <= MBEDTLS_MPI_MAX_LIMBS. */ 267b0563631STom Van Eyck X->n = (unsigned short) nblimbs; 2683d3b0591SJens Wiklander X->p = p; 2693d3b0591SJens Wiklander } 270817466cbSJens Wiklander 27132b31808SJens Wiklander return 0; 272817466cbSJens Wiklander } 273817466cbSJens Wiklander 274817466cbSJens Wiklander /* 275817466cbSJens Wiklander * Resize down as much as possible, 276817466cbSJens Wiklander * while keeping at least the specified number of limbs 277817466cbSJens Wiklander */ 278817466cbSJens Wiklander int mbedtls_mpi_shrink(mbedtls_mpi *X, size_t nblimbs) 279817466cbSJens Wiklander { 280817466cbSJens Wiklander mbedtls_mpi_uint *p; 281817466cbSJens Wiklander size_t i; 2823d3b0591SJens Wiklander 28332b31808SJens Wiklander if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) { 28432b31808SJens Wiklander return MBEDTLS_ERR_MPI_ALLOC_FAILED; 28532b31808SJens Wiklander } 286817466cbSJens Wiklander 2875b25c76aSJerome Forissier /* Actually resize up if there are currently fewer than nblimbs limbs. */ 28832b31808SJens Wiklander if (X->n <= nblimbs) { 28932b31808SJens Wiklander return mbedtls_mpi_grow(X, nblimbs); 29032b31808SJens Wiklander } 2915b25c76aSJerome Forissier /* After this point, then X->n > nblimbs and in particular X->n > 0. */ 292817466cbSJens Wiklander 29332b31808SJens Wiklander for (i = X->n - 1; i > 0; i--) { 29432b31808SJens Wiklander if (X->p[i] != 0) { 295817466cbSJens Wiklander break; 29632b31808SJens Wiklander } 29732b31808SJens Wiklander } 298817466cbSJens Wiklander i++; 299817466cbSJens Wiklander 30032b31808SJens Wiklander if (i < nblimbs) { 301817466cbSJens Wiklander i = nblimbs; 30232b31808SJens Wiklander } 303817466cbSJens Wiklander 30432b31808SJens Wiklander if (X->use_mempool) { 305ed3fa831SJerome Forissier p = mempool_alloc(mbedtls_mpi_mempool, i * ciL); 3063d3b0591SJens Wiklander if (p == NULL) 30732b31808SJens Wiklander return MBEDTLS_ERR_MPI_ALLOC_FAILED; 308ed3fa831SJerome Forissier memset(p, 0, i * ciL); 30932b31808SJens Wiklander } else { 31032b31808SJens Wiklander if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(i, ciL)) == NULL) 31132b31808SJens Wiklander return MBEDTLS_ERR_MPI_ALLOC_FAILED; 3123d3b0591SJens Wiklander } 31318c5148dSJens Wiklander 31432b31808SJens Wiklander if (X->p != NULL) { 315817466cbSJens Wiklander memcpy(p, X->p, i * ciL); 316b0563631STom Van Eyck 317b0563631STom Van Eyck if (X->use_mempool) { 318817466cbSJens Wiklander mbedtls_mpi_zeroize(X->p, X->n); 31918c5148dSJens Wiklander mempool_free(mbedtls_mpi_mempool, X->p); 320b0563631STom Van Eyck } 321b0563631STom Van Eyck else { 322b0563631STom Van Eyck mbedtls_mpi_zeroize_and_free(X->p, X->n); 323b0563631STom Van Eyck } 324817466cbSJens Wiklander } 325817466cbSJens Wiklander 326b0563631STom Van Eyck /* i fits in n because we ensure that MBEDTLS_MPI_MAX_LIMBS 327b0563631STom Van Eyck * fits, and we've checked that i <= nblimbs <= MBEDTLS_MPI_MAX_LIMBS. */ 328b0563631STom Van Eyck X->n = (unsigned short) i; 3293d3b0591SJens Wiklander X->p = p; 330817466cbSJens Wiklander 33132b31808SJens Wiklander return 0; 332817466cbSJens Wiklander } 333817466cbSJens Wiklander 3347901324dSJerome Forissier /* Resize X to have exactly n limbs and set it to 0. */ 3357901324dSJerome Forissier static int mbedtls_mpi_resize_clear(mbedtls_mpi *X, size_t limbs) 3367901324dSJerome Forissier { 33732b31808SJens Wiklander if (limbs == 0) { 3387901324dSJerome Forissier mbedtls_mpi_free(X); 33932b31808SJens Wiklander return 0; 34032b31808SJens Wiklander } else if (X->n == limbs) { 3417901324dSJerome Forissier memset(X->p, 0, limbs * ciL); 3427901324dSJerome Forissier X->s = 1; 34332b31808SJens Wiklander return 0; 34432b31808SJens Wiklander } else { 3457901324dSJerome Forissier mbedtls_mpi_free(X); 34632b31808SJens Wiklander return mbedtls_mpi_grow(X, limbs); 3477901324dSJerome Forissier } 3487901324dSJerome Forissier } 3497901324dSJerome Forissier 350817466cbSJens Wiklander /* 3517901324dSJerome Forissier * Copy the contents of Y into X. 3527901324dSJerome Forissier * 3537901324dSJerome Forissier * This function is not constant-time. Leading zeros in Y may be removed. 3547901324dSJerome Forissier * 3557901324dSJerome Forissier * Ensure that X does not shrink. This is not guaranteed by the public API, 356b0563631STom Van Eyck * but some code in the bignum module might still rely on this property. 357817466cbSJens Wiklander */ 358817466cbSJens Wiklander int mbedtls_mpi_copy(mbedtls_mpi *X, const mbedtls_mpi *Y) 359817466cbSJens Wiklander { 3603d3b0591SJens Wiklander int ret = 0; 361817466cbSJens Wiklander size_t i; 362817466cbSJens Wiklander 36332b31808SJens Wiklander if (X == Y) { 36432b31808SJens Wiklander return 0; 36532b31808SJens Wiklander } 366817466cbSJens Wiklander 36732b31808SJens Wiklander if (Y->n == 0) { 36832b31808SJens Wiklander if (X->n != 0) { 3697901324dSJerome Forissier X->s = 1; 3707901324dSJerome Forissier memset(X->p, 0, X->n * ciL); 3717901324dSJerome Forissier } 37232b31808SJens Wiklander return 0; 373817466cbSJens Wiklander } 374817466cbSJens Wiklander 37532b31808SJens Wiklander for (i = Y->n - 1; i > 0; i--) { 37632b31808SJens Wiklander if (Y->p[i] != 0) { 377817466cbSJens Wiklander break; 37832b31808SJens Wiklander } 37932b31808SJens Wiklander } 380817466cbSJens Wiklander i++; 381817466cbSJens Wiklander 382817466cbSJens Wiklander X->s = Y->s; 383817466cbSJens Wiklander 38432b31808SJens Wiklander if (X->n < i) { 385817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i)); 38632b31808SJens Wiklander } else { 3873d3b0591SJens Wiklander memset(X->p + i, 0, (X->n - i) * ciL); 3883d3b0591SJens Wiklander } 389817466cbSJens Wiklander 390817466cbSJens Wiklander memcpy(X->p, Y->p, i * ciL); 391817466cbSJens Wiklander 392817466cbSJens Wiklander cleanup: 393817466cbSJens Wiklander 39432b31808SJens Wiklander return ret; 395817466cbSJens Wiklander } 396817466cbSJens Wiklander 397817466cbSJens Wiklander /* 398817466cbSJens Wiklander * Swap the contents of X and Y 399817466cbSJens Wiklander */ 400817466cbSJens Wiklander void mbedtls_mpi_swap(mbedtls_mpi *X, mbedtls_mpi *Y) 401817466cbSJens Wiklander { 402817466cbSJens Wiklander mbedtls_mpi T; 403817466cbSJens Wiklander 404817466cbSJens Wiklander memcpy(&T, X, sizeof(mbedtls_mpi)); 405817466cbSJens Wiklander memcpy(X, Y, sizeof(mbedtls_mpi)); 406817466cbSJens Wiklander memcpy(Y, &T, sizeof(mbedtls_mpi)); 407817466cbSJens Wiklander } 408817466cbSJens Wiklander 40932b31808SJens Wiklander static inline mbedtls_mpi_uint mpi_sint_abs(mbedtls_mpi_sint z) 41032b31808SJens Wiklander { 41132b31808SJens Wiklander if (z >= 0) { 41232b31808SJens Wiklander return z; 41332b31808SJens Wiklander } 41432b31808SJens Wiklander /* Take care to handle the most negative value (-2^(biL-1)) correctly. 41532b31808SJens Wiklander * A naive -z would have undefined behavior. 41632b31808SJens Wiklander * Write this in a way that makes popular compilers happy (GCC, Clang, 41732b31808SJens Wiklander * MSVC). */ 41832b31808SJens Wiklander return (mbedtls_mpi_uint) 0 - (mbedtls_mpi_uint) z; 41932b31808SJens Wiklander } 42032b31808SJens Wiklander 421b0563631STom Van Eyck /* Convert x to a sign, i.e. to 1, if x is positive, or -1, if x is negative. 422b0563631STom Van Eyck * This looks awkward but generates smaller code than (x < 0 ? -1 : 1) */ 423b0563631STom Van Eyck #define TO_SIGN(x) ((mbedtls_mpi_sint) (((mbedtls_mpi_uint) x) >> (biL - 1)) * -2 + 1) 424b0563631STom Van Eyck 425817466cbSJens Wiklander /* 426817466cbSJens Wiklander * Set value from integer 427817466cbSJens Wiklander */ 428817466cbSJens Wiklander int mbedtls_mpi_lset(mbedtls_mpi *X, mbedtls_mpi_sint z) 429817466cbSJens Wiklander { 43011fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 431817466cbSJens Wiklander 432817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, 1)); 433817466cbSJens Wiklander memset(X->p, 0, X->n * ciL); 434817466cbSJens Wiklander 43532b31808SJens Wiklander X->p[0] = mpi_sint_abs(z); 436b0563631STom Van Eyck X->s = TO_SIGN(z); 437817466cbSJens Wiklander 438817466cbSJens Wiklander cleanup: 439817466cbSJens Wiklander 44032b31808SJens Wiklander return ret; 441817466cbSJens Wiklander } 442817466cbSJens Wiklander 443817466cbSJens Wiklander /* 444817466cbSJens Wiklander * Get a specific bit 445817466cbSJens Wiklander */ 446817466cbSJens Wiklander int mbedtls_mpi_get_bit(const mbedtls_mpi *X, size_t pos) 447817466cbSJens Wiklander { 44832b31808SJens Wiklander if (X->n * biL <= pos) { 44932b31808SJens Wiklander return 0; 450817466cbSJens Wiklander } 451817466cbSJens Wiklander 45232b31808SJens Wiklander return (X->p[pos / biL] >> (pos % biL)) & 0x01; 45332b31808SJens Wiklander } 4543d3b0591SJens Wiklander 455817466cbSJens Wiklander /* 456817466cbSJens Wiklander * Set a bit to a specific value of 0 or 1 457817466cbSJens Wiklander */ 458817466cbSJens Wiklander int mbedtls_mpi_set_bit(mbedtls_mpi *X, size_t pos, unsigned char val) 459817466cbSJens Wiklander { 460817466cbSJens Wiklander int ret = 0; 461817466cbSJens Wiklander size_t off = pos / biL; 462817466cbSJens Wiklander size_t idx = pos % biL; 463817466cbSJens Wiklander 46432b31808SJens Wiklander if (val != 0 && val != 1) { 46532b31808SJens Wiklander return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 46632b31808SJens Wiklander } 467817466cbSJens Wiklander 46832b31808SJens Wiklander if (X->n * biL <= pos) { 46932b31808SJens Wiklander if (val == 0) { 47032b31808SJens Wiklander return 0; 47132b31808SJens Wiklander } 472817466cbSJens Wiklander 473817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, off + 1)); 474817466cbSJens Wiklander } 475817466cbSJens Wiklander 476817466cbSJens Wiklander X->p[off] &= ~((mbedtls_mpi_uint) 0x01 << idx); 477817466cbSJens Wiklander X->p[off] |= (mbedtls_mpi_uint) val << idx; 478817466cbSJens Wiklander 479817466cbSJens Wiklander cleanup: 480817466cbSJens Wiklander 48132b31808SJens Wiklander return ret; 482817466cbSJens Wiklander } 483817466cbSJens Wiklander 484817466cbSJens Wiklander /* 485817466cbSJens Wiklander * Return the number of less significant zero-bits 486817466cbSJens Wiklander */ 487817466cbSJens Wiklander size_t mbedtls_mpi_lsb(const mbedtls_mpi *X) 488817466cbSJens Wiklander { 489b0563631STom Van Eyck size_t i; 490817466cbSJens Wiklander 491b0563631STom Van Eyck #if defined(__has_builtin) 492b0563631STom Van Eyck #if (MBEDTLS_MPI_UINT_MAX == UINT_MAX) && __has_builtin(__builtin_ctz) 493b0563631STom Van Eyck #define mbedtls_mpi_uint_ctz __builtin_ctz 494b0563631STom Van Eyck #elif (MBEDTLS_MPI_UINT_MAX == ULONG_MAX) && __has_builtin(__builtin_ctzl) 495b0563631STom Van Eyck #define mbedtls_mpi_uint_ctz __builtin_ctzl 496b0563631STom Van Eyck #elif (MBEDTLS_MPI_UINT_MAX == ULLONG_MAX) && __has_builtin(__builtin_ctzll) 497b0563631STom Van Eyck #define mbedtls_mpi_uint_ctz __builtin_ctzll 498b0563631STom Van Eyck #endif 499b0563631STom Van Eyck #endif 500b0563631STom Van Eyck 501b0563631STom Van Eyck #if defined(mbedtls_mpi_uint_ctz) 50232b31808SJens Wiklander for (i = 0; i < X->n; i++) { 503b0563631STom Van Eyck if (X->p[i] != 0) { 504b0563631STom Van Eyck return i * biL + mbedtls_mpi_uint_ctz(X->p[i]); 505b0563631STom Van Eyck } 506b0563631STom Van Eyck } 507b0563631STom Van Eyck #else 508b0563631STom Van Eyck size_t count = 0; 509b0563631STom Van Eyck for (i = 0; i < X->n; i++) { 510b0563631STom Van Eyck for (size_t j = 0; j < biL; j++, count++) { 51132b31808SJens Wiklander if (((X->p[i] >> j) & 1) != 0) { 51232b31808SJens Wiklander return count; 51332b31808SJens Wiklander } 51432b31808SJens Wiklander } 515817466cbSJens Wiklander } 516b0563631STom Van Eyck #endif 517817466cbSJens Wiklander 51832b31808SJens Wiklander return 0; 519817466cbSJens Wiklander } 520817466cbSJens Wiklander 521817466cbSJens Wiklander /* 522817466cbSJens Wiklander * Return the number of bits 523817466cbSJens Wiklander */ 524817466cbSJens Wiklander size_t mbedtls_mpi_bitlen(const mbedtls_mpi *X) 525817466cbSJens Wiklander { 52632b31808SJens Wiklander return mbedtls_mpi_core_bitlen(X->p, X->n); 527817466cbSJens Wiklander } 528817466cbSJens Wiklander 529817466cbSJens Wiklander /* 530817466cbSJens Wiklander * Return the total size in bytes 531817466cbSJens Wiklander */ 532817466cbSJens Wiklander size_t mbedtls_mpi_size(const mbedtls_mpi *X) 533817466cbSJens Wiklander { 53432b31808SJens Wiklander return (mbedtls_mpi_bitlen(X) + 7) >> 3; 535817466cbSJens Wiklander } 536817466cbSJens Wiklander 537817466cbSJens Wiklander /* 538817466cbSJens Wiklander * Convert an ASCII character to digit value 539817466cbSJens Wiklander */ 540817466cbSJens Wiklander static int mpi_get_digit(mbedtls_mpi_uint *d, int radix, char c) 541817466cbSJens Wiklander { 542817466cbSJens Wiklander *d = 255; 543817466cbSJens Wiklander 54432b31808SJens Wiklander if (c >= 0x30 && c <= 0x39) { 54532b31808SJens Wiklander *d = c - 0x30; 54632b31808SJens Wiklander } 54732b31808SJens Wiklander if (c >= 0x41 && c <= 0x46) { 54832b31808SJens Wiklander *d = c - 0x37; 54932b31808SJens Wiklander } 55032b31808SJens Wiklander if (c >= 0x61 && c <= 0x66) { 55132b31808SJens Wiklander *d = c - 0x57; 55232b31808SJens Wiklander } 553817466cbSJens Wiklander 55432b31808SJens Wiklander if (*d >= (mbedtls_mpi_uint) radix) { 55532b31808SJens Wiklander return MBEDTLS_ERR_MPI_INVALID_CHARACTER; 55632b31808SJens Wiklander } 557817466cbSJens Wiklander 55832b31808SJens Wiklander return 0; 559817466cbSJens Wiklander } 560817466cbSJens Wiklander 561817466cbSJens Wiklander /* 562817466cbSJens Wiklander * Import from an ASCII string 563817466cbSJens Wiklander */ 564817466cbSJens Wiklander int mbedtls_mpi_read_string(mbedtls_mpi *X, int radix, const char *s) 565817466cbSJens Wiklander { 56611fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 567817466cbSJens Wiklander size_t i, j, slen, n; 5687901324dSJerome Forissier int sign = 1; 569817466cbSJens Wiklander mbedtls_mpi_uint d; 570817466cbSJens Wiklander mbedtls_mpi T; 571817466cbSJens Wiklander 57232b31808SJens Wiklander if (radix < 2 || radix > 16) { 57332b31808SJens Wiklander return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 57432b31808SJens Wiklander } 575817466cbSJens Wiklander 57698bd5fe3SJens Wiklander mbedtls_mpi_init_mempool(&T); 577817466cbSJens Wiklander 57832b31808SJens Wiklander if (s[0] == 0) { 5797901324dSJerome Forissier mbedtls_mpi_free(X); 58032b31808SJens Wiklander return 0; 5817901324dSJerome Forissier } 5827901324dSJerome Forissier 58332b31808SJens Wiklander if (s[0] == '-') { 5847901324dSJerome Forissier ++s; 5857901324dSJerome Forissier sign = -1; 5867901324dSJerome Forissier } 5877901324dSJerome Forissier 588817466cbSJens Wiklander slen = strlen(s); 589817466cbSJens Wiklander 59032b31808SJens Wiklander if (radix == 16) { 591b0563631STom Van Eyck if (slen > SIZE_MAX >> 2) { 59232b31808SJens Wiklander return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 59332b31808SJens Wiklander } 594817466cbSJens Wiklander 595817466cbSJens Wiklander n = BITS_TO_LIMBS(slen << 2); 596817466cbSJens Wiklander 597817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n)); 598817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0)); 599817466cbSJens Wiklander 60032b31808SJens Wiklander for (i = slen, j = 0; i > 0; i--, j++) { 601817466cbSJens Wiklander MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i - 1])); 602817466cbSJens Wiklander X->p[j / (2 * ciL)] |= d << ((j % (2 * ciL)) << 2); 603817466cbSJens Wiklander } 60432b31808SJens Wiklander } else { 605817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0)); 606817466cbSJens Wiklander 60732b31808SJens Wiklander for (i = 0; i < slen; i++) { 608817466cbSJens Wiklander MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i])); 609817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T, X, radix)); 610817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, &T, d)); 611817466cbSJens Wiklander } 612817466cbSJens Wiklander } 6137901324dSJerome Forissier 61432b31808SJens Wiklander if (sign < 0 && mbedtls_mpi_bitlen(X) != 0) { 6157901324dSJerome Forissier X->s = -1; 61632b31808SJens Wiklander } 617817466cbSJens Wiklander 618817466cbSJens Wiklander cleanup: 619817466cbSJens Wiklander 620817466cbSJens Wiklander mbedtls_mpi_free(&T); 621817466cbSJens Wiklander 62232b31808SJens Wiklander return ret; 623817466cbSJens Wiklander } 624817466cbSJens Wiklander 625817466cbSJens Wiklander /* 6265b25c76aSJerome Forissier * Helper to write the digits high-order first. 627817466cbSJens Wiklander */ 6285b25c76aSJerome Forissier static int mpi_write_hlp(mbedtls_mpi *X, int radix, 6295b25c76aSJerome Forissier char **p, const size_t buflen) 630817466cbSJens Wiklander { 63111fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 632817466cbSJens Wiklander mbedtls_mpi_uint r; 6335b25c76aSJerome Forissier size_t length = 0; 6345b25c76aSJerome Forissier char *p_end = *p + buflen; 635817466cbSJens Wiklander 63632b31808SJens Wiklander do { 63732b31808SJens Wiklander if (length >= buflen) { 63832b31808SJens Wiklander return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL; 6395b25c76aSJerome Forissier } 640817466cbSJens Wiklander 641817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, radix)); 642817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_div_int(X, NULL, X, radix)); 6435b25c76aSJerome Forissier /* 6445b25c76aSJerome Forissier * Write the residue in the current position, as an ASCII character. 6455b25c76aSJerome Forissier */ 64632b31808SJens Wiklander if (r < 0xA) { 6475b25c76aSJerome Forissier *(--p_end) = (char) ('0' + r); 64832b31808SJens Wiklander } else { 6495b25c76aSJerome Forissier *(--p_end) = (char) ('A' + (r - 0xA)); 65032b31808SJens Wiklander } 6515b25c76aSJerome Forissier 6525b25c76aSJerome Forissier length++; 6535b25c76aSJerome Forissier } while (mbedtls_mpi_cmp_int(X, 0) != 0); 6545b25c76aSJerome Forissier 6555b25c76aSJerome Forissier memmove(*p, p_end, length); 6565b25c76aSJerome Forissier *p += length; 657817466cbSJens Wiklander 658817466cbSJens Wiklander cleanup: 659817466cbSJens Wiklander 66032b31808SJens Wiklander return ret; 661817466cbSJens Wiklander } 662817466cbSJens Wiklander 663817466cbSJens Wiklander /* 664817466cbSJens Wiklander * Export into an ASCII string 665817466cbSJens Wiklander */ 666817466cbSJens Wiklander int mbedtls_mpi_write_string(const mbedtls_mpi *X, int radix, 667817466cbSJens Wiklander char *buf, size_t buflen, size_t *olen) 668817466cbSJens Wiklander { 669817466cbSJens Wiklander int ret = 0; 670817466cbSJens Wiklander size_t n; 671817466cbSJens Wiklander char *p; 672817466cbSJens Wiklander mbedtls_mpi T; 673817466cbSJens Wiklander 67432b31808SJens Wiklander if (radix < 2 || radix > 16) { 67532b31808SJens Wiklander return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 67632b31808SJens Wiklander } 677817466cbSJens Wiklander 6785b25c76aSJerome Forissier n = mbedtls_mpi_bitlen(X); /* Number of bits necessary to present `n`. */ 67932b31808SJens Wiklander if (radix >= 4) { 68032b31808SJens Wiklander n >>= 1; /* Number of 4-adic digits necessary to present 6815b25c76aSJerome Forissier * `n`. If radix > 4, this might be a strict 6825b25c76aSJerome Forissier * overapproximation of the number of 6835b25c76aSJerome Forissier * radix-adic digits needed to present `n`. */ 68432b31808SJens Wiklander } 68532b31808SJens Wiklander if (radix >= 16) { 68632b31808SJens Wiklander n >>= 1; /* Number of hexadecimal digits necessary to 6875b25c76aSJerome Forissier * present `n`. */ 6885b25c76aSJerome Forissier 68932b31808SJens Wiklander } 6905b25c76aSJerome Forissier n += 1; /* Terminating null byte */ 6915b25c76aSJerome Forissier n += 1; /* Compensate for the divisions above, which round down `n` 6925b25c76aSJerome Forissier * in case it's not even. */ 6935b25c76aSJerome Forissier n += 1; /* Potential '-'-sign. */ 6945b25c76aSJerome Forissier n += (n & 1); /* Make n even to have enough space for hexadecimal writing, 6955b25c76aSJerome Forissier * which always uses an even number of hex-digits. */ 696817466cbSJens Wiklander 69732b31808SJens Wiklander if (buflen < n) { 698817466cbSJens Wiklander *olen = n; 69932b31808SJens Wiklander return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL; 700817466cbSJens Wiklander } 701817466cbSJens Wiklander 702817466cbSJens Wiklander p = buf; 70398bd5fe3SJens Wiklander mbedtls_mpi_init_mempool(&T); 704817466cbSJens Wiklander 70532b31808SJens Wiklander if (X->s == -1) { 706817466cbSJens Wiklander *p++ = '-'; 7075b25c76aSJerome Forissier buflen--; 7085b25c76aSJerome Forissier } 709817466cbSJens Wiklander 71032b31808SJens Wiklander if (radix == 16) { 711817466cbSJens Wiklander int c; 712817466cbSJens Wiklander size_t i, j, k; 713817466cbSJens Wiklander 71432b31808SJens Wiklander for (i = X->n, k = 0; i > 0; i--) { 71532b31808SJens Wiklander for (j = ciL; j > 0; j--) { 716817466cbSJens Wiklander c = (X->p[i - 1] >> ((j - 1) << 3)) & 0xFF; 717817466cbSJens Wiklander 71832b31808SJens Wiklander if (c == 0 && k == 0 && (i + j) != 2) { 719817466cbSJens Wiklander continue; 72032b31808SJens Wiklander } 721817466cbSJens Wiklander 722817466cbSJens Wiklander *(p++) = "0123456789ABCDEF" [c / 16]; 723817466cbSJens Wiklander *(p++) = "0123456789ABCDEF" [c % 16]; 724817466cbSJens Wiklander k = 1; 725817466cbSJens Wiklander } 726817466cbSJens Wiklander } 72732b31808SJens Wiklander } else { 728817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T, X)); 729817466cbSJens Wiklander 73032b31808SJens Wiklander if (T.s == -1) { 731817466cbSJens Wiklander T.s = 1; 73232b31808SJens Wiklander } 733817466cbSJens Wiklander 7345b25c76aSJerome Forissier MBEDTLS_MPI_CHK(mpi_write_hlp(&T, radix, &p, buflen)); 735817466cbSJens Wiklander } 736817466cbSJens Wiklander 737817466cbSJens Wiklander *p++ = '\0'; 738b0563631STom Van Eyck *olen = (size_t) (p - buf); 739817466cbSJens Wiklander 740817466cbSJens Wiklander cleanup: 741817466cbSJens Wiklander 742817466cbSJens Wiklander mbedtls_mpi_free(&T); 743817466cbSJens Wiklander 74432b31808SJens Wiklander return ret; 745817466cbSJens Wiklander } 746817466cbSJens Wiklander 747817466cbSJens Wiklander #if defined(MBEDTLS_FS_IO) 748817466cbSJens Wiklander /* 749817466cbSJens Wiklander * Read X from an opened file 750817466cbSJens Wiklander */ 751817466cbSJens Wiklander int mbedtls_mpi_read_file(mbedtls_mpi *X, int radix, FILE *fin) 752817466cbSJens Wiklander { 753817466cbSJens Wiklander mbedtls_mpi_uint d; 754817466cbSJens Wiklander size_t slen; 755817466cbSJens Wiklander char *p; 756817466cbSJens Wiklander /* 757817466cbSJens Wiklander * Buffer should have space for (short) label and decimal formatted MPI, 758817466cbSJens Wiklander * newline characters and '\0' 759817466cbSJens Wiklander */ 760817466cbSJens Wiklander char s[MBEDTLS_MPI_RW_BUFFER_SIZE]; 761817466cbSJens Wiklander 76232b31808SJens Wiklander if (radix < 2 || radix > 16) { 76332b31808SJens Wiklander return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 76432b31808SJens Wiklander } 7653d3b0591SJens Wiklander 766817466cbSJens Wiklander memset(s, 0, sizeof(s)); 76732b31808SJens Wiklander if (fgets(s, sizeof(s) - 1, fin) == NULL) { 76832b31808SJens Wiklander return MBEDTLS_ERR_MPI_FILE_IO_ERROR; 76932b31808SJens Wiklander } 770817466cbSJens Wiklander 771817466cbSJens Wiklander slen = strlen(s); 77232b31808SJens Wiklander if (slen == sizeof(s) - 2) { 77332b31808SJens Wiklander return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL; 77432b31808SJens Wiklander } 775817466cbSJens Wiklander 77632b31808SJens Wiklander if (slen > 0 && s[slen - 1] == '\n') { 77732b31808SJens Wiklander slen--; s[slen] = '\0'; 77832b31808SJens Wiklander } 77932b31808SJens Wiklander if (slen > 0 && s[slen - 1] == '\r') { 78032b31808SJens Wiklander slen--; s[slen] = '\0'; 78132b31808SJens Wiklander } 782817466cbSJens Wiklander 783817466cbSJens Wiklander p = s + slen; 78432b31808SJens Wiklander while (p-- > s) { 78532b31808SJens Wiklander if (mpi_get_digit(&d, radix, *p) != 0) { 786817466cbSJens Wiklander break; 78732b31808SJens Wiklander } 78832b31808SJens Wiklander } 789817466cbSJens Wiklander 79032b31808SJens Wiklander return mbedtls_mpi_read_string(X, radix, p + 1); 791817466cbSJens Wiklander } 792817466cbSJens Wiklander 793817466cbSJens Wiklander /* 794817466cbSJens Wiklander * Write X into an opened file (or stdout if fout == NULL) 795817466cbSJens Wiklander */ 796817466cbSJens Wiklander int mbedtls_mpi_write_file(const char *p, const mbedtls_mpi *X, int radix, FILE *fout) 797817466cbSJens Wiklander { 79811fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 799817466cbSJens Wiklander size_t n, slen, plen; 800817466cbSJens Wiklander /* 801817466cbSJens Wiklander * Buffer should have space for (short) label and decimal formatted MPI, 802817466cbSJens Wiklander * newline characters and '\0' 803817466cbSJens Wiklander */ 804817466cbSJens Wiklander char s[MBEDTLS_MPI_RW_BUFFER_SIZE]; 8053d3b0591SJens Wiklander 80632b31808SJens Wiklander if (radix < 2 || radix > 16) { 80732b31808SJens Wiklander return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 80832b31808SJens Wiklander } 809817466cbSJens Wiklander 810817466cbSJens Wiklander memset(s, 0, sizeof(s)); 811817466cbSJens Wiklander 812817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_write_string(X, radix, s, sizeof(s) - 2, &n)); 813817466cbSJens Wiklander 81432b31808SJens Wiklander if (p == NULL) { 81532b31808SJens Wiklander p = ""; 81632b31808SJens Wiklander } 817817466cbSJens Wiklander 818817466cbSJens Wiklander plen = strlen(p); 819817466cbSJens Wiklander slen = strlen(s); 820817466cbSJens Wiklander s[slen++] = '\r'; 821817466cbSJens Wiklander s[slen++] = '\n'; 822817466cbSJens Wiklander 82332b31808SJens Wiklander if (fout != NULL) { 824817466cbSJens Wiklander if (fwrite(p, 1, plen, fout) != plen || 82532b31808SJens Wiklander fwrite(s, 1, slen, fout) != slen) { 82632b31808SJens Wiklander return MBEDTLS_ERR_MPI_FILE_IO_ERROR; 827817466cbSJens Wiklander } 82832b31808SJens Wiklander } else { 829817466cbSJens Wiklander mbedtls_printf("%s%s", p, s); 83032b31808SJens Wiklander } 831817466cbSJens Wiklander 832817466cbSJens Wiklander cleanup: 833817466cbSJens Wiklander 83432b31808SJens Wiklander return ret; 835817466cbSJens Wiklander } 836817466cbSJens Wiklander #endif /* MBEDTLS_FS_IO */ 837817466cbSJens Wiklander 838817466cbSJens Wiklander /* 83911fa71b9SJerome Forissier * Import X from unsigned binary data, little endian 84032b31808SJens Wiklander * 84132b31808SJens Wiklander * This function is guaranteed to return an MPI with exactly the necessary 84232b31808SJens Wiklander * number of limbs (in particular, it does not skip 0s in the input). 84311fa71b9SJerome Forissier */ 84411fa71b9SJerome Forissier int mbedtls_mpi_read_binary_le(mbedtls_mpi *X, 84511fa71b9SJerome Forissier const unsigned char *buf, size_t buflen) 84611fa71b9SJerome Forissier { 84711fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 84832b31808SJens Wiklander const size_t limbs = CHARS_TO_LIMBS(buflen); 84911fa71b9SJerome Forissier 85011fa71b9SJerome Forissier /* Ensure that target MPI has exactly the necessary number of limbs */ 8517901324dSJerome Forissier MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs)); 85211fa71b9SJerome Forissier 85332b31808SJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_le(X->p, X->n, buf, buflen)); 85411fa71b9SJerome Forissier 85511fa71b9SJerome Forissier cleanup: 85611fa71b9SJerome Forissier 85711fa71b9SJerome Forissier /* 85811fa71b9SJerome Forissier * This function is also used to import keys. However, wiping the buffers 85911fa71b9SJerome Forissier * upon failure is not necessary because failure only can happen before any 86011fa71b9SJerome Forissier * input is copied. 86111fa71b9SJerome Forissier */ 86232b31808SJens Wiklander return ret; 86311fa71b9SJerome Forissier } 86411fa71b9SJerome Forissier 86511fa71b9SJerome Forissier /* 866817466cbSJens Wiklander * Import X from unsigned binary data, big endian 86732b31808SJens Wiklander * 86832b31808SJens Wiklander * This function is guaranteed to return an MPI with exactly the necessary 86932b31808SJens Wiklander * number of limbs (in particular, it does not skip 0s in the input). 870817466cbSJens Wiklander */ 871817466cbSJens Wiklander int mbedtls_mpi_read_binary(mbedtls_mpi *X, const unsigned char *buf, size_t buflen) 872817466cbSJens Wiklander { 87311fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 87432b31808SJens Wiklander const size_t limbs = CHARS_TO_LIMBS(buflen); 875817466cbSJens Wiklander 8763d3b0591SJens Wiklander /* Ensure that target MPI has exactly the necessary number of limbs */ 8777901324dSJerome Forissier MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs)); 8782976273fSJens Wiklander 87932b31808SJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_be(X->p, X->n, buf, buflen)); 880817466cbSJens Wiklander 881817466cbSJens Wiklander cleanup: 882817466cbSJens Wiklander 88311fa71b9SJerome Forissier /* 88411fa71b9SJerome Forissier * This function is also used to import keys. However, wiping the buffers 88511fa71b9SJerome Forissier * upon failure is not necessary because failure only can happen before any 88611fa71b9SJerome Forissier * input is copied. 88711fa71b9SJerome Forissier */ 88832b31808SJens Wiklander return ret; 889817466cbSJens Wiklander } 890817466cbSJens Wiklander 891817466cbSJens Wiklander /* 89211fa71b9SJerome Forissier * Export X into unsigned binary data, little endian 89311fa71b9SJerome Forissier */ 89411fa71b9SJerome Forissier int mbedtls_mpi_write_binary_le(const mbedtls_mpi *X, 89511fa71b9SJerome Forissier unsigned char *buf, size_t buflen) 89611fa71b9SJerome Forissier { 89732b31808SJens Wiklander return mbedtls_mpi_core_write_le(X->p, X->n, buf, buflen); 89811fa71b9SJerome Forissier } 89911fa71b9SJerome Forissier 90011fa71b9SJerome Forissier /* 901817466cbSJens Wiklander * Export X into unsigned binary data, big endian 902817466cbSJens Wiklander */ 9033d3b0591SJens Wiklander int mbedtls_mpi_write_binary(const mbedtls_mpi *X, 9043d3b0591SJens Wiklander unsigned char *buf, size_t buflen) 905817466cbSJens Wiklander { 90632b31808SJens Wiklander return mbedtls_mpi_core_write_be(X->p, X->n, buf, buflen); 907817466cbSJens Wiklander } 908817466cbSJens Wiklander 909817466cbSJens Wiklander /* 910817466cbSJens Wiklander * Left-shift: X <<= count 911817466cbSJens Wiklander */ 912817466cbSJens Wiklander int mbedtls_mpi_shift_l(mbedtls_mpi *X, size_t count) 913817466cbSJens Wiklander { 91411fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 915b0563631STom Van Eyck size_t i; 916817466cbSJens Wiklander 917817466cbSJens Wiklander i = mbedtls_mpi_bitlen(X) + count; 918817466cbSJens Wiklander 91932b31808SJens Wiklander if (X->n * biL < i) { 920817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, BITS_TO_LIMBS(i))); 92132b31808SJens Wiklander } 922817466cbSJens Wiklander 923817466cbSJens Wiklander ret = 0; 924817466cbSJens Wiklander 925b0563631STom Van Eyck mbedtls_mpi_core_shift_l(X->p, X->n, count); 926817466cbSJens Wiklander cleanup: 927817466cbSJens Wiklander 92832b31808SJens Wiklander return ret; 929817466cbSJens Wiklander } 930817466cbSJens Wiklander 931817466cbSJens Wiklander /* 932817466cbSJens Wiklander * Right-shift: X >>= count 933817466cbSJens Wiklander */ 934817466cbSJens Wiklander int mbedtls_mpi_shift_r(mbedtls_mpi *X, size_t count) 935817466cbSJens Wiklander { 93632b31808SJens Wiklander if (X->n != 0) { 93732b31808SJens Wiklander mbedtls_mpi_core_shift_r(X->p, X->n, count); 938817466cbSJens Wiklander } 93932b31808SJens Wiklander return 0; 940817466cbSJens Wiklander } 941817466cbSJens Wiklander 942817466cbSJens Wiklander /* 943817466cbSJens Wiklander * Compare unsigned values 944817466cbSJens Wiklander */ 945817466cbSJens Wiklander int mbedtls_mpi_cmp_abs(const mbedtls_mpi *X, const mbedtls_mpi *Y) 946817466cbSJens Wiklander { 947817466cbSJens Wiklander size_t i, j; 948817466cbSJens Wiklander 94932b31808SJens Wiklander for (i = X->n; i > 0; i--) { 95032b31808SJens Wiklander if (X->p[i - 1] != 0) { 951817466cbSJens Wiklander break; 95232b31808SJens Wiklander } 953817466cbSJens Wiklander } 954817466cbSJens Wiklander 95532b31808SJens Wiklander for (j = Y->n; j > 0; j--) { 95632b31808SJens Wiklander if (Y->p[j - 1] != 0) { 95732b31808SJens Wiklander break; 95832b31808SJens Wiklander } 95932b31808SJens Wiklander } 96032b31808SJens Wiklander 961b0563631STom Van Eyck /* If i == j == 0, i.e. abs(X) == abs(Y), 962b0563631STom Van Eyck * we end up returning 0 at the end of the function. */ 96332b31808SJens Wiklander 96432b31808SJens Wiklander if (i > j) { 96532b31808SJens Wiklander return 1; 96632b31808SJens Wiklander } 96732b31808SJens Wiklander if (j > i) { 96832b31808SJens Wiklander return -1; 96932b31808SJens Wiklander } 97032b31808SJens Wiklander 97132b31808SJens Wiklander for (; i > 0; i--) { 97232b31808SJens Wiklander if (X->p[i - 1] > Y->p[i - 1]) { 97332b31808SJens Wiklander return 1; 97432b31808SJens Wiklander } 97532b31808SJens Wiklander if (X->p[i - 1] < Y->p[i - 1]) { 97632b31808SJens Wiklander return -1; 97732b31808SJens Wiklander } 97832b31808SJens Wiklander } 97932b31808SJens Wiklander 98032b31808SJens Wiklander return 0; 981817466cbSJens Wiklander } 982817466cbSJens Wiklander 983817466cbSJens Wiklander /* 984817466cbSJens Wiklander * Compare signed values 985817466cbSJens Wiklander */ 986817466cbSJens Wiklander int mbedtls_mpi_cmp_mpi(const mbedtls_mpi *X, const mbedtls_mpi *Y) 987817466cbSJens Wiklander { 988817466cbSJens Wiklander size_t i, j; 989817466cbSJens Wiklander 99032b31808SJens Wiklander for (i = X->n; i > 0; i--) { 99132b31808SJens Wiklander if (X->p[i - 1] != 0) { 992817466cbSJens Wiklander break; 99332b31808SJens Wiklander } 994817466cbSJens Wiklander } 995817466cbSJens Wiklander 99632b31808SJens Wiklander for (j = Y->n; j > 0; j--) { 99732b31808SJens Wiklander if (Y->p[j - 1] != 0) { 99832b31808SJens Wiklander break; 99932b31808SJens Wiklander } 100032b31808SJens Wiklander } 100132b31808SJens Wiklander 100232b31808SJens Wiklander if (i == 0 && j == 0) { 100332b31808SJens Wiklander return 0; 100432b31808SJens Wiklander } 100532b31808SJens Wiklander 100632b31808SJens Wiklander if (i > j) { 100732b31808SJens Wiklander return X->s; 100832b31808SJens Wiklander } 100932b31808SJens Wiklander if (j > i) { 101032b31808SJens Wiklander return -Y->s; 101132b31808SJens Wiklander } 101232b31808SJens Wiklander 101332b31808SJens Wiklander if (X->s > 0 && Y->s < 0) { 101432b31808SJens Wiklander return 1; 101532b31808SJens Wiklander } 101632b31808SJens Wiklander if (Y->s > 0 && X->s < 0) { 101732b31808SJens Wiklander return -1; 101832b31808SJens Wiklander } 101932b31808SJens Wiklander 102032b31808SJens Wiklander for (; i > 0; i--) { 102132b31808SJens Wiklander if (X->p[i - 1] > Y->p[i - 1]) { 102232b31808SJens Wiklander return X->s; 102332b31808SJens Wiklander } 102432b31808SJens Wiklander if (X->p[i - 1] < Y->p[i - 1]) { 102532b31808SJens Wiklander return -X->s; 102632b31808SJens Wiklander } 102732b31808SJens Wiklander } 102832b31808SJens Wiklander 102932b31808SJens Wiklander return 0; 1030817466cbSJens Wiklander } 1031817466cbSJens Wiklander 1032817466cbSJens Wiklander /* 1033817466cbSJens Wiklander * Compare signed values 1034817466cbSJens Wiklander */ 1035817466cbSJens Wiklander int mbedtls_mpi_cmp_int(const mbedtls_mpi *X, mbedtls_mpi_sint z) 1036817466cbSJens Wiklander { 1037817466cbSJens Wiklander mbedtls_mpi Y; 1038817466cbSJens Wiklander mbedtls_mpi_uint p[1]; 1039817466cbSJens Wiklander 104032b31808SJens Wiklander *p = mpi_sint_abs(z); 1041b0563631STom Van Eyck Y.s = TO_SIGN(z); 1042817466cbSJens Wiklander Y.n = 1; 1043817466cbSJens Wiklander Y.p = p; 1044817466cbSJens Wiklander 104532b31808SJens Wiklander return mbedtls_mpi_cmp_mpi(X, &Y); 1046817466cbSJens Wiklander } 1047817466cbSJens Wiklander 1048817466cbSJens Wiklander /* 1049817466cbSJens Wiklander * Unsigned addition: X = |A| + |B| (HAC 14.7) 1050817466cbSJens Wiklander */ 1051817466cbSJens Wiklander int mbedtls_mpi_add_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B) 1052817466cbSJens Wiklander { 105311fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 105432b31808SJens Wiklander size_t j; 1055b0563631STom Van Eyck mbedtls_mpi_uint *p; 1056b0563631STom Van Eyck mbedtls_mpi_uint c; 1057817466cbSJens Wiklander 105832b31808SJens Wiklander if (X == B) { 1059817466cbSJens Wiklander const mbedtls_mpi *T = A; A = X; B = T; 1060817466cbSJens Wiklander } 1061817466cbSJens Wiklander 106232b31808SJens Wiklander if (X != A) { 1063817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A)); 106432b31808SJens Wiklander } 1065817466cbSJens Wiklander 1066817466cbSJens Wiklander /* 106732b31808SJens Wiklander * X must always be positive as a result of unsigned additions. 1068817466cbSJens Wiklander */ 1069817466cbSJens Wiklander X->s = 1; 1070817466cbSJens Wiklander 107132b31808SJens Wiklander for (j = B->n; j > 0; j--) { 107232b31808SJens Wiklander if (B->p[j - 1] != 0) { 1073817466cbSJens Wiklander break; 107432b31808SJens Wiklander } 107532b31808SJens Wiklander } 107632b31808SJens Wiklander 107732b31808SJens Wiklander /* Exit early to avoid undefined behavior on NULL+0 when X->n == 0 107832b31808SJens Wiklander * and B is 0 (of any size). */ 107932b31808SJens Wiklander if (j == 0) { 108032b31808SJens Wiklander return 0; 108132b31808SJens Wiklander } 1082817466cbSJens Wiklander 1083817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j)); 1084817466cbSJens Wiklander 108532b31808SJens Wiklander /* j is the number of non-zero limbs of B. Add those to X. */ 1086817466cbSJens Wiklander 1087b0563631STom Van Eyck p = X->p; 108832b31808SJens Wiklander 1089b0563631STom Van Eyck c = mbedtls_mpi_core_add(p, p, B->p, j); 109032b31808SJens Wiklander 109132b31808SJens Wiklander p += j; 109232b31808SJens Wiklander 109332b31808SJens Wiklander /* Now propagate any carry */ 109432b31808SJens Wiklander 109532b31808SJens Wiklander while (c != 0) { 109632b31808SJens Wiklander if (j >= X->n) { 109732b31808SJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j + 1)); 109832b31808SJens Wiklander p = X->p + j; 1099817466cbSJens Wiklander } 1100817466cbSJens Wiklander 110132b31808SJens Wiklander *p += c; c = (*p < c); j++; p++; 1102817466cbSJens Wiklander } 1103817466cbSJens Wiklander 1104817466cbSJens Wiklander cleanup: 1105817466cbSJens Wiklander 110632b31808SJens Wiklander return ret; 1107817466cbSJens Wiklander } 1108817466cbSJens Wiklander 1109817466cbSJens Wiklander /* 11107901324dSJerome Forissier * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10) 1111817466cbSJens Wiklander */ 1112817466cbSJens Wiklander int mbedtls_mpi_sub_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B) 1113817466cbSJens Wiklander { 111411fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1115817466cbSJens Wiklander size_t n; 11167901324dSJerome Forissier mbedtls_mpi_uint carry; 1117817466cbSJens Wiklander 111832b31808SJens Wiklander for (n = B->n; n > 0; n--) { 111932b31808SJens Wiklander if (B->p[n - 1] != 0) { 1120817466cbSJens Wiklander break; 112132b31808SJens Wiklander } 112232b31808SJens Wiklander } 112332b31808SJens Wiklander if (n > A->n) { 11247901324dSJerome Forissier /* B >= (2^ciL)^n > A */ 11257901324dSJerome Forissier ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE; 11267901324dSJerome Forissier goto cleanup; 11277901324dSJerome Forissier } 1128817466cbSJens Wiklander 11297901324dSJerome Forissier MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, A->n)); 11307901324dSJerome Forissier 11317901324dSJerome Forissier /* Set the high limbs of X to match A. Don't touch the lower limbs 11327901324dSJerome Forissier * because X might be aliased to B, and we must not overwrite the 11337901324dSJerome Forissier * significant digits of B. */ 113432b31808SJens Wiklander if (A->n > n && A != X) { 11357901324dSJerome Forissier memcpy(X->p + n, A->p + n, (A->n - n) * ciL); 113632b31808SJens Wiklander } 113732b31808SJens Wiklander if (X->n > A->n) { 11387901324dSJerome Forissier memset(X->p + A->n, 0, (X->n - A->n) * ciL); 113932b31808SJens Wiklander } 11407901324dSJerome Forissier 114132b31808SJens Wiklander carry = mbedtls_mpi_core_sub(X->p, A->p, B->p, n); 114232b31808SJens Wiklander if (carry != 0) { 114332b31808SJens Wiklander /* Propagate the carry through the rest of X. */ 114432b31808SJens Wiklander carry = mbedtls_mpi_core_sub_int(X->p + n, X->p + n, carry, X->n - n); 114532b31808SJens Wiklander 114632b31808SJens Wiklander /* If we have further carry/borrow, the result is negative. */ 114732b31808SJens Wiklander if (carry != 0) { 11487901324dSJerome Forissier ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE; 11497901324dSJerome Forissier goto cleanup; 11507901324dSJerome Forissier } 11517901324dSJerome Forissier } 11527901324dSJerome Forissier 11537901324dSJerome Forissier /* X should always be positive as a result of unsigned subtractions. */ 11547901324dSJerome Forissier X->s = 1; 1155817466cbSJens Wiklander 1156817466cbSJens Wiklander cleanup: 115732b31808SJens Wiklander return ret; 115832b31808SJens Wiklander } 115932b31808SJens Wiklander 116032b31808SJens Wiklander /* Common function for signed addition and subtraction. 116132b31808SJens Wiklander * Calculate A + B * flip_B where flip_B is 1 or -1. 116232b31808SJens Wiklander */ 116332b31808SJens Wiklander static int add_sub_mpi(mbedtls_mpi *X, 116432b31808SJens Wiklander const mbedtls_mpi *A, const mbedtls_mpi *B, 116532b31808SJens Wiklander int flip_B) 116632b31808SJens Wiklander { 116732b31808SJens Wiklander int ret, s; 116832b31808SJens Wiklander 116932b31808SJens Wiklander s = A->s; 117032b31808SJens Wiklander if (A->s * B->s * flip_B < 0) { 117132b31808SJens Wiklander int cmp = mbedtls_mpi_cmp_abs(A, B); 117232b31808SJens Wiklander if (cmp >= 0) { 117332b31808SJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, A, B)); 117432b31808SJens Wiklander /* If |A| = |B|, the result is 0 and we must set the sign bit 117532b31808SJens Wiklander * to +1 regardless of which of A or B was negative. Otherwise, 117632b31808SJens Wiklander * since |A| > |B|, the sign is the sign of A. */ 117732b31808SJens Wiklander X->s = cmp == 0 ? 1 : s; 117832b31808SJens Wiklander } else { 117932b31808SJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, B, A)); 118032b31808SJens Wiklander /* Since |A| < |B|, the sign is the opposite of A. */ 118132b31808SJens Wiklander X->s = -s; 118232b31808SJens Wiklander } 118332b31808SJens Wiklander } else { 118432b31808SJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_add_abs(X, A, B)); 118532b31808SJens Wiklander X->s = s; 118632b31808SJens Wiklander } 118732b31808SJens Wiklander 118832b31808SJens Wiklander cleanup: 118932b31808SJens Wiklander 119032b31808SJens Wiklander return ret; 1191817466cbSJens Wiklander } 1192817466cbSJens Wiklander 1193817466cbSJens Wiklander /* 1194817466cbSJens Wiklander * Signed addition: X = A + B 1195817466cbSJens Wiklander */ 1196817466cbSJens Wiklander int mbedtls_mpi_add_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B) 1197817466cbSJens Wiklander { 119832b31808SJens Wiklander return add_sub_mpi(X, A, B, 1); 1199817466cbSJens Wiklander } 1200817466cbSJens Wiklander 1201817466cbSJens Wiklander /* 1202817466cbSJens Wiklander * Signed subtraction: X = A - B 1203817466cbSJens Wiklander */ 1204817466cbSJens Wiklander int mbedtls_mpi_sub_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B) 1205817466cbSJens Wiklander { 120632b31808SJens Wiklander return add_sub_mpi(X, A, B, -1); 1207817466cbSJens Wiklander } 1208817466cbSJens Wiklander 1209817466cbSJens Wiklander /* 1210817466cbSJens Wiklander * Signed addition: X = A + b 1211817466cbSJens Wiklander */ 1212817466cbSJens Wiklander int mbedtls_mpi_add_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b) 1213817466cbSJens Wiklander { 1214039e02dfSJerome Forissier mbedtls_mpi B; 1215817466cbSJens Wiklander mbedtls_mpi_uint p[1]; 1216817466cbSJens Wiklander 121732b31808SJens Wiklander p[0] = mpi_sint_abs(b); 1218b0563631STom Van Eyck B.s = TO_SIGN(b); 1219039e02dfSJerome Forissier B.n = 1; 1220039e02dfSJerome Forissier B.p = p; 1221817466cbSJens Wiklander 122232b31808SJens Wiklander return mbedtls_mpi_add_mpi(X, A, &B); 1223817466cbSJens Wiklander } 1224817466cbSJens Wiklander 1225817466cbSJens Wiklander /* 1226817466cbSJens Wiklander * Signed subtraction: X = A - b 1227817466cbSJens Wiklander */ 1228817466cbSJens Wiklander int mbedtls_mpi_sub_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b) 1229817466cbSJens Wiklander { 1230039e02dfSJerome Forissier mbedtls_mpi B; 1231817466cbSJens Wiklander mbedtls_mpi_uint p[1]; 1232817466cbSJens Wiklander 123332b31808SJens Wiklander p[0] = mpi_sint_abs(b); 1234b0563631STom Van Eyck B.s = TO_SIGN(b); 1235039e02dfSJerome Forissier B.n = 1; 1236039e02dfSJerome Forissier B.p = p; 1237817466cbSJens Wiklander 123832b31808SJens Wiklander return mbedtls_mpi_sub_mpi(X, A, &B); 1239817466cbSJens Wiklander } 1240817466cbSJens Wiklander 1241817466cbSJens Wiklander /* 1242817466cbSJens Wiklander * Baseline multiplication: X = A * B (HAC 14.12) 1243817466cbSJens Wiklander */ 1244817466cbSJens Wiklander int mbedtls_mpi_mul_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B) 1245817466cbSJens Wiklander { 124611fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1247817466cbSJens Wiklander size_t i, j; 1248817466cbSJens Wiklander mbedtls_mpi TA, TB; 12497901324dSJerome Forissier int result_is_zero = 0; 1250817466cbSJens Wiklander 1251b0563631STom Van Eyck mbedtls_mpi_init_mempool(&TA); 1252b0563631STom Van Eyck mbedtls_mpi_init_mempool(&TB); 1253817466cbSJens Wiklander 125432b31808SJens Wiklander if (X == A) { 125532b31808SJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A)); A = &TA; 125632b31808SJens Wiklander } 125732b31808SJens Wiklander if (X == B) { 125832b31808SJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B)); B = &TB; 125932b31808SJens Wiklander } 1260817466cbSJens Wiklander 126132b31808SJens Wiklander for (i = A->n; i > 0; i--) { 126232b31808SJens Wiklander if (A->p[i - 1] != 0) { 1263817466cbSJens Wiklander break; 126432b31808SJens Wiklander } 126532b31808SJens Wiklander } 126632b31808SJens Wiklander if (i == 0) { 12677901324dSJerome Forissier result_is_zero = 1; 126832b31808SJens Wiklander } 1269817466cbSJens Wiklander 127032b31808SJens Wiklander for (j = B->n; j > 0; j--) { 127132b31808SJens Wiklander if (B->p[j - 1] != 0) { 1272817466cbSJens Wiklander break; 127332b31808SJens Wiklander } 127432b31808SJens Wiklander } 127532b31808SJens Wiklander if (j == 0) { 12767901324dSJerome Forissier result_is_zero = 1; 127732b31808SJens Wiklander } 1278817466cbSJens Wiklander 1279817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i + j)); 1280817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0)); 1281817466cbSJens Wiklander 1282b0563631STom Van Eyck mbedtls_mpi_core_mul(X->p, A->p, i, B->p, j); 1283817466cbSJens Wiklander 12847901324dSJerome Forissier /* If the result is 0, we don't shortcut the operation, which reduces 12857901324dSJerome Forissier * but does not eliminate side channels leaking the zero-ness. We do 12867901324dSJerome Forissier * need to take care to set the sign bit properly since the library does 12877901324dSJerome Forissier * not fully support an MPI object with a value of 0 and s == -1. */ 128832b31808SJens Wiklander if (result_is_zero) { 12897901324dSJerome Forissier X->s = 1; 129032b31808SJens Wiklander } else { 1291817466cbSJens Wiklander X->s = A->s * B->s; 129232b31808SJens Wiklander } 1293817466cbSJens Wiklander 1294817466cbSJens Wiklander cleanup: 1295817466cbSJens Wiklander 1296817466cbSJens Wiklander mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TA); 1297817466cbSJens Wiklander 129832b31808SJens Wiklander return ret; 1299817466cbSJens Wiklander } 1300817466cbSJens Wiklander 1301817466cbSJens Wiklander /* 1302817466cbSJens Wiklander * Baseline multiplication: X = A * b 1303817466cbSJens Wiklander */ 1304817466cbSJens Wiklander int mbedtls_mpi_mul_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b) 1305817466cbSJens Wiklander { 13067901324dSJerome Forissier size_t n = A->n; 130732b31808SJens Wiklander while (n > 0 && A->p[n - 1] == 0) { 13087901324dSJerome Forissier --n; 13097901324dSJerome Forissier } 13107901324dSJerome Forissier 131132b31808SJens Wiklander /* The general method below doesn't work if b==0. */ 131232b31808SJens Wiklander if (b == 0 || n == 0) { 131332b31808SJens Wiklander return mbedtls_mpi_lset(X, 0); 131432b31808SJens Wiklander } 131532b31808SJens Wiklander 131632b31808SJens Wiklander /* Calculate A*b as A + A*(b-1) to take advantage of mbedtls_mpi_core_mla */ 13177901324dSJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 13187901324dSJerome Forissier /* In general, A * b requires 1 limb more than b. If 13197901324dSJerome Forissier * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same 13207901324dSJerome Forissier * number of limbs as A and the call to grow() is not required since 13217901324dSJerome Forissier * copy() will take care of the growth if needed. However, experimentally, 13227901324dSJerome Forissier * making the call to grow() unconditional causes slightly fewer 13237901324dSJerome Forissier * calls to calloc() in ECP code, presumably because it reuses the 13247901324dSJerome Forissier * same mpi for a while and this way the mpi is more likely to directly 132532b31808SJens Wiklander * grow to its final size. 132632b31808SJens Wiklander * 132732b31808SJens Wiklander * Note that calculating A*b as 0 + A*b doesn't work as-is because 132832b31808SJens Wiklander * A,X can be the same. */ 13297901324dSJerome Forissier MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n + 1)); 13307901324dSJerome Forissier MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A)); 133132b31808SJens Wiklander mbedtls_mpi_core_mla(X->p, X->n, A->p, n, b - 1); 13327901324dSJerome Forissier 13337901324dSJerome Forissier cleanup: 133432b31808SJens Wiklander return ret; 1335817466cbSJens Wiklander } 1336817466cbSJens Wiklander 1337817466cbSJens Wiklander /* 1338817466cbSJens Wiklander * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and 1339817466cbSJens Wiklander * mbedtls_mpi_uint divisor, d 1340817466cbSJens Wiklander */ 1341817466cbSJens Wiklander static mbedtls_mpi_uint mbedtls_int_div_int(mbedtls_mpi_uint u1, 134232b31808SJens Wiklander mbedtls_mpi_uint u0, 134332b31808SJens Wiklander mbedtls_mpi_uint d, 134432b31808SJens Wiklander mbedtls_mpi_uint *r) 1345817466cbSJens Wiklander { 1346817466cbSJens Wiklander #if defined(MBEDTLS_HAVE_UDBL) 1347817466cbSJens Wiklander mbedtls_t_udbl dividend, quotient; 1348817466cbSJens Wiklander #else 1349817466cbSJens Wiklander const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH; 1350817466cbSJens Wiklander const mbedtls_mpi_uint uint_halfword_mask = ((mbedtls_mpi_uint) 1 << biH) - 1; 1351817466cbSJens Wiklander mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient; 1352817466cbSJens Wiklander mbedtls_mpi_uint u0_msw, u0_lsw; 1353817466cbSJens Wiklander size_t s; 1354817466cbSJens Wiklander #endif 1355817466cbSJens Wiklander 1356817466cbSJens Wiklander /* 1357817466cbSJens Wiklander * Check for overflow 1358817466cbSJens Wiklander */ 135932b31808SJens Wiklander if (0 == d || u1 >= d) { 136032b31808SJens Wiklander if (r != NULL) { 136132b31808SJens Wiklander *r = ~(mbedtls_mpi_uint) 0u; 136232b31808SJens Wiklander } 1363817466cbSJens Wiklander 136432b31808SJens Wiklander return ~(mbedtls_mpi_uint) 0u; 1365817466cbSJens Wiklander } 1366817466cbSJens Wiklander 1367817466cbSJens Wiklander #if defined(MBEDTLS_HAVE_UDBL) 1368817466cbSJens Wiklander dividend = (mbedtls_t_udbl) u1 << biL; 1369817466cbSJens Wiklander dividend |= (mbedtls_t_udbl) u0; 1370817466cbSJens Wiklander quotient = dividend / d; 137132b31808SJens Wiklander if (quotient > ((mbedtls_t_udbl) 1 << biL) - 1) { 1372817466cbSJens Wiklander quotient = ((mbedtls_t_udbl) 1 << biL) - 1; 137332b31808SJens Wiklander } 1374817466cbSJens Wiklander 137532b31808SJens Wiklander if (r != NULL) { 1376817466cbSJens Wiklander *r = (mbedtls_mpi_uint) (dividend - (quotient * d)); 137732b31808SJens Wiklander } 1378817466cbSJens Wiklander 1379817466cbSJens Wiklander return (mbedtls_mpi_uint) quotient; 1380817466cbSJens Wiklander #else 1381817466cbSJens Wiklander 1382817466cbSJens Wiklander /* 1383817466cbSJens Wiklander * Algorithm D, Section 4.3.1 - The Art of Computer Programming 1384817466cbSJens Wiklander * Vol. 2 - Seminumerical Algorithms, Knuth 1385817466cbSJens Wiklander */ 1386817466cbSJens Wiklander 1387817466cbSJens Wiklander /* 1388817466cbSJens Wiklander * Normalize the divisor, d, and dividend, u0, u1 1389817466cbSJens Wiklander */ 139032b31808SJens Wiklander s = mbedtls_mpi_core_clz(d); 1391817466cbSJens Wiklander d = d << s; 1392817466cbSJens Wiklander 1393817466cbSJens Wiklander u1 = u1 << s; 1394817466cbSJens Wiklander u1 |= (u0 >> (biL - s)) & (-(mbedtls_mpi_sint) s >> (biL - 1)); 1395817466cbSJens Wiklander u0 = u0 << s; 1396817466cbSJens Wiklander 1397817466cbSJens Wiklander d1 = d >> biH; 1398817466cbSJens Wiklander d0 = d & uint_halfword_mask; 1399817466cbSJens Wiklander 1400817466cbSJens Wiklander u0_msw = u0 >> biH; 1401817466cbSJens Wiklander u0_lsw = u0 & uint_halfword_mask; 1402817466cbSJens Wiklander 1403817466cbSJens Wiklander /* 1404817466cbSJens Wiklander * Find the first quotient and remainder 1405817466cbSJens Wiklander */ 1406817466cbSJens Wiklander q1 = u1 / d1; 1407817466cbSJens Wiklander r0 = u1 - d1 * q1; 1408817466cbSJens Wiklander 140932b31808SJens Wiklander while (q1 >= radix || (q1 * d0 > radix * r0 + u0_msw)) { 1410817466cbSJens Wiklander q1 -= 1; 1411817466cbSJens Wiklander r0 += d1; 1412817466cbSJens Wiklander 141332b31808SJens Wiklander if (r0 >= radix) { 141432b31808SJens Wiklander break; 141532b31808SJens Wiklander } 1416817466cbSJens Wiklander } 1417817466cbSJens Wiklander 1418817466cbSJens Wiklander rAX = (u1 * radix) + (u0_msw - q1 * d); 1419817466cbSJens Wiklander q0 = rAX / d1; 1420817466cbSJens Wiklander r0 = rAX - q0 * d1; 1421817466cbSJens Wiklander 142232b31808SJens Wiklander while (q0 >= radix || (q0 * d0 > radix * r0 + u0_lsw)) { 1423817466cbSJens Wiklander q0 -= 1; 1424817466cbSJens Wiklander r0 += d1; 1425817466cbSJens Wiklander 142632b31808SJens Wiklander if (r0 >= radix) { 142732b31808SJens Wiklander break; 142832b31808SJens Wiklander } 1429817466cbSJens Wiklander } 1430817466cbSJens Wiklander 143132b31808SJens Wiklander if (r != NULL) { 1432817466cbSJens Wiklander *r = (rAX * radix + u0_lsw - q0 * d) >> s; 143332b31808SJens Wiklander } 1434817466cbSJens Wiklander 1435817466cbSJens Wiklander quotient = q1 * radix + q0; 1436817466cbSJens Wiklander 1437817466cbSJens Wiklander return quotient; 1438817466cbSJens Wiklander #endif 1439817466cbSJens Wiklander } 1440817466cbSJens Wiklander 1441817466cbSJens Wiklander /* 1442817466cbSJens Wiklander * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20) 1443817466cbSJens Wiklander */ 14443d3b0591SJens Wiklander int mbedtls_mpi_div_mpi(mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, 14453d3b0591SJens Wiklander const mbedtls_mpi *B) 1446817466cbSJens Wiklander { 144711fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1448817466cbSJens Wiklander size_t i, n, t, k; 1449817466cbSJens Wiklander mbedtls_mpi X, Y, Z, T1, T2; 145011fa71b9SJerome Forissier mbedtls_mpi_uint TP2[3]; 1451817466cbSJens Wiklander 145232b31808SJens Wiklander if (mbedtls_mpi_cmp_int(B, 0) == 0) { 145332b31808SJens Wiklander return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO; 145432b31808SJens Wiklander } 1455817466cbSJens Wiklander 145698bd5fe3SJens Wiklander mbedtls_mpi_init_mempool(&X); mbedtls_mpi_init_mempool(&Y); 145798bd5fe3SJens Wiklander mbedtls_mpi_init_mempool(&Z); mbedtls_mpi_init_mempool(&T1); 145811fa71b9SJerome Forissier /* 145911fa71b9SJerome Forissier * Avoid dynamic memory allocations for constant-size T2. 146011fa71b9SJerome Forissier * 146111fa71b9SJerome Forissier * T2 is used for comparison only and the 3 limbs are assigned explicitly, 146211fa71b9SJerome Forissier * so nobody increase the size of the MPI and we're safe to use an on-stack 146311fa71b9SJerome Forissier * buffer. 146411fa71b9SJerome Forissier */ 146511fa71b9SJerome Forissier T2.s = 1; 146611fa71b9SJerome Forissier T2.n = sizeof(TP2) / sizeof(*TP2); 146711fa71b9SJerome Forissier T2.p = TP2; 1468817466cbSJens Wiklander 146932b31808SJens Wiklander if (mbedtls_mpi_cmp_abs(A, B) < 0) { 147032b31808SJens Wiklander if (Q != NULL) { 147132b31808SJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_lset(Q, 0)); 147232b31808SJens Wiklander } 147332b31808SJens Wiklander if (R != NULL) { 147432b31808SJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, A)); 147532b31808SJens Wiklander } 147632b31808SJens Wiklander return 0; 1477817466cbSJens Wiklander } 1478817466cbSJens Wiklander 1479817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&X, A)); 1480817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, B)); 1481817466cbSJens Wiklander X.s = Y.s = 1; 1482817466cbSJens Wiklander 1483817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&Z, A->n + 2)); 1484817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Z, 0)); 14857901324dSJerome Forissier MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T1, A->n + 2)); 1486817466cbSJens Wiklander 1487817466cbSJens Wiklander k = mbedtls_mpi_bitlen(&Y) % biL; 148832b31808SJens Wiklander if (k < biL - 1) { 1489817466cbSJens Wiklander k = biL - 1 - k; 1490817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&X, k)); 1491817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, k)); 149232b31808SJens Wiklander } else { 149332b31808SJens Wiklander k = 0; 1494817466cbSJens Wiklander } 1495817466cbSJens Wiklander 1496817466cbSJens Wiklander n = X.n - 1; 1497817466cbSJens Wiklander t = Y.n - 1; 1498817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, biL * (n - t))); 1499817466cbSJens Wiklander 150032b31808SJens Wiklander while (mbedtls_mpi_cmp_mpi(&X, &Y) >= 0) { 1501817466cbSJens Wiklander Z.p[n - t]++; 1502817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &Y)); 1503817466cbSJens Wiklander } 1504817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, biL * (n - t))); 1505817466cbSJens Wiklander 150632b31808SJens Wiklander for (i = n; i > t; i--) { 150732b31808SJens Wiklander if (X.p[i] >= Y.p[t]) { 150832b31808SJens Wiklander Z.p[i - t - 1] = ~(mbedtls_mpi_uint) 0u; 150932b31808SJens Wiklander } else { 1510817466cbSJens Wiklander Z.p[i - t - 1] = mbedtls_int_div_int(X.p[i], X.p[i - 1], 1511817466cbSJens Wiklander Y.p[t], NULL); 1512817466cbSJens Wiklander } 1513817466cbSJens Wiklander 151411fa71b9SJerome Forissier T2.p[0] = (i < 2) ? 0 : X.p[i - 2]; 151511fa71b9SJerome Forissier T2.p[1] = (i < 1) ? 0 : X.p[i - 1]; 151611fa71b9SJerome Forissier T2.p[2] = X.p[i]; 151711fa71b9SJerome Forissier 1518817466cbSJens Wiklander Z.p[i - t - 1]++; 151932b31808SJens Wiklander do { 1520817466cbSJens Wiklander Z.p[i - t - 1]--; 1521817466cbSJens Wiklander 1522817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&T1, 0)); 1523817466cbSJens Wiklander T1.p[0] = (t < 1) ? 0 : Y.p[t - 1]; 1524817466cbSJens Wiklander T1.p[1] = Y.p[t]; 1525817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &T1, Z.p[i - t - 1])); 152632b31808SJens Wiklander } while (mbedtls_mpi_cmp_mpi(&T1, &T2) > 0); 1527817466cbSJens Wiklander 1528817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &Y, Z.p[i - t - 1])); 1529817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1))); 1530817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &T1)); 1531817466cbSJens Wiklander 153232b31808SJens Wiklander if (mbedtls_mpi_cmp_int(&X, 0) < 0) { 1533817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T1, &Y)); 1534817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1))); 1535817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&X, &X, &T1)); 1536817466cbSJens Wiklander Z.p[i - t - 1]--; 1537817466cbSJens Wiklander } 1538817466cbSJens Wiklander } 1539817466cbSJens Wiklander 154032b31808SJens Wiklander if (Q != NULL) { 1541817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_copy(Q, &Z)); 1542817466cbSJens Wiklander Q->s = A->s * B->s; 1543817466cbSJens Wiklander } 1544817466cbSJens Wiklander 154532b31808SJens Wiklander if (R != NULL) { 1546817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&X, k)); 1547817466cbSJens Wiklander X.s = A->s; 1548817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, &X)); 1549817466cbSJens Wiklander 155032b31808SJens Wiklander if (mbedtls_mpi_cmp_int(R, 0) == 0) { 1551817466cbSJens Wiklander R->s = 1; 1552817466cbSJens Wiklander } 155332b31808SJens Wiklander } 1554817466cbSJens Wiklander 1555817466cbSJens Wiklander cleanup: 1556817466cbSJens Wiklander 1557817466cbSJens Wiklander mbedtls_mpi_free(&X); mbedtls_mpi_free(&Y); mbedtls_mpi_free(&Z); 155811fa71b9SJerome Forissier mbedtls_mpi_free(&T1); 155911fa71b9SJerome Forissier mbedtls_platform_zeroize(TP2, sizeof(TP2)); 1560817466cbSJens Wiklander 156132b31808SJens Wiklander return ret; 1562817466cbSJens Wiklander } 1563817466cbSJens Wiklander 1564817466cbSJens Wiklander /* 1565817466cbSJens Wiklander * Division by int: A = Q * b + R 1566817466cbSJens Wiklander */ 15673d3b0591SJens Wiklander int mbedtls_mpi_div_int(mbedtls_mpi *Q, mbedtls_mpi *R, 15683d3b0591SJens Wiklander const mbedtls_mpi *A, 15693d3b0591SJens Wiklander mbedtls_mpi_sint b) 1570817466cbSJens Wiklander { 1571039e02dfSJerome Forissier mbedtls_mpi B; 1572817466cbSJens Wiklander mbedtls_mpi_uint p[1]; 1573817466cbSJens Wiklander 157432b31808SJens Wiklander p[0] = mpi_sint_abs(b); 1575b0563631STom Van Eyck B.s = TO_SIGN(b); 1576039e02dfSJerome Forissier B.n = 1; 1577039e02dfSJerome Forissier B.p = p; 1578817466cbSJens Wiklander 157932b31808SJens Wiklander return mbedtls_mpi_div_mpi(Q, R, A, &B); 1580817466cbSJens Wiklander } 1581817466cbSJens Wiklander 1582817466cbSJens Wiklander /* 1583817466cbSJens Wiklander * Modulo: R = A mod B 1584817466cbSJens Wiklander */ 1585817466cbSJens Wiklander int mbedtls_mpi_mod_mpi(mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B) 1586817466cbSJens Wiklander { 158711fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1588817466cbSJens Wiklander 158932b31808SJens Wiklander if (mbedtls_mpi_cmp_int(B, 0) < 0) { 159032b31808SJens Wiklander return MBEDTLS_ERR_MPI_NEGATIVE_VALUE; 159132b31808SJens Wiklander } 1592817466cbSJens Wiklander 1593817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(NULL, R, A, B)); 1594817466cbSJens Wiklander 159532b31808SJens Wiklander while (mbedtls_mpi_cmp_int(R, 0) < 0) { 1596817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(R, R, B)); 159732b31808SJens Wiklander } 1598817466cbSJens Wiklander 159932b31808SJens Wiklander while (mbedtls_mpi_cmp_mpi(R, B) >= 0) { 1600817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(R, R, B)); 160132b31808SJens Wiklander } 1602817466cbSJens Wiklander 1603817466cbSJens Wiklander cleanup: 1604817466cbSJens Wiklander 160532b31808SJens Wiklander return ret; 1606817466cbSJens Wiklander } 1607817466cbSJens Wiklander 1608817466cbSJens Wiklander /* 1609817466cbSJens Wiklander * Modulo: r = A mod b 1610817466cbSJens Wiklander */ 1611817466cbSJens Wiklander int mbedtls_mpi_mod_int(mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b) 1612817466cbSJens Wiklander { 1613817466cbSJens Wiklander size_t i; 1614817466cbSJens Wiklander mbedtls_mpi_uint x, y, z; 1615817466cbSJens Wiklander 161632b31808SJens Wiklander if (b == 0) { 161732b31808SJens Wiklander return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO; 161832b31808SJens Wiklander } 1619817466cbSJens Wiklander 162032b31808SJens Wiklander if (b < 0) { 162132b31808SJens Wiklander return MBEDTLS_ERR_MPI_NEGATIVE_VALUE; 162232b31808SJens Wiklander } 1623817466cbSJens Wiklander 1624817466cbSJens Wiklander /* 1625817466cbSJens Wiklander * handle trivial cases 1626817466cbSJens Wiklander */ 162732b31808SJens Wiklander if (b == 1 || A->n == 0) { 1628817466cbSJens Wiklander *r = 0; 162932b31808SJens Wiklander return 0; 1630817466cbSJens Wiklander } 1631817466cbSJens Wiklander 163232b31808SJens Wiklander if (b == 2) { 1633817466cbSJens Wiklander *r = A->p[0] & 1; 163432b31808SJens Wiklander return 0; 1635817466cbSJens Wiklander } 1636817466cbSJens Wiklander 1637817466cbSJens Wiklander /* 1638817466cbSJens Wiklander * general case 1639817466cbSJens Wiklander */ 164032b31808SJens Wiklander for (i = A->n, y = 0; i > 0; i--) { 1641817466cbSJens Wiklander x = A->p[i - 1]; 1642817466cbSJens Wiklander y = (y << biH) | (x >> biH); 1643817466cbSJens Wiklander z = y / b; 1644817466cbSJens Wiklander y -= z * b; 1645817466cbSJens Wiklander 1646817466cbSJens Wiklander x <<= biH; 1647817466cbSJens Wiklander y = (y << biH) | (x >> biH); 1648817466cbSJens Wiklander z = y / b; 1649817466cbSJens Wiklander y -= z * b; 1650817466cbSJens Wiklander } 1651817466cbSJens Wiklander 1652817466cbSJens Wiklander /* 1653817466cbSJens Wiklander * If A is negative, then the current y represents a negative value. 1654817466cbSJens Wiklander * Flipping it to the positive side. 1655817466cbSJens Wiklander */ 165632b31808SJens Wiklander if (A->s < 0 && y != 0) { 1657817466cbSJens Wiklander y = b - y; 165832b31808SJens Wiklander } 1659817466cbSJens Wiklander 1660817466cbSJens Wiklander *r = y; 1661817466cbSJens Wiklander 166232b31808SJens Wiklander return 0; 1663817466cbSJens Wiklander } 1664817466cbSJens Wiklander 1665b0563631STom Van Eyck /** 1666b0563631STom Van Eyck * \remark Replaced by our own because the original has been removed since 1667b0563631STom Van Eyck * mbedtls v3.6.0. 1668b0563631STom Van Eyck */ 16697901324dSJerome Forissier void mbedtls_mpi_montg_init(mbedtls_mpi_uint *mm, const mbedtls_mpi *N) 16707901324dSJerome Forissier { 1671b0563631STom Van Eyck *mm = mbedtls_mpi_core_montmul_init(N->p); 16727901324dSJerome Forissier } 16737901324dSJerome Forissier 16747901324dSJerome Forissier /** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36) 16757901324dSJerome Forissier * 16767901324dSJerome Forissier * \param[in,out] A One of the numbers to multiply. 16777901324dSJerome Forissier * It must have at least as many limbs as N 16787901324dSJerome Forissier * (A->n >= N->n), and any limbs beyond n are ignored. 16797901324dSJerome Forissier * On successful completion, A contains the result of 16807901324dSJerome Forissier * the multiplication A * B * R^-1 mod N where 16817901324dSJerome Forissier * R = (2^ciL)^n. 16827901324dSJerome Forissier * \param[in] B One of the numbers to multiply. 16837901324dSJerome Forissier * It must be nonzero and must not have more limbs than N 16847901324dSJerome Forissier * (B->n <= N->n). 168532b31808SJens Wiklander * \param[in] N The modulus. \p N must be odd. 16867901324dSJerome Forissier * \param mm The value calculated by `mpi_montg_init(&mm, N)`. 16877901324dSJerome Forissier * This is -N^-1 mod 2^ciL. 16887901324dSJerome Forissier * \param[in,out] T A bignum for temporary storage. 168932b31808SJens Wiklander * It must be at least twice the limb size of N plus 1 169032b31808SJens Wiklander * (T->n >= 2 * N->n + 1). 16917901324dSJerome Forissier * Its initial content is unused and 16927901324dSJerome Forissier * its final content is indeterminate. 169332b31808SJens Wiklander * It does not get reallocated. 1694b0563631STom Van Eyck * \remark Replaced by our own because the original has been removed since 1695b0563631STom Van Eyck * mbedtls v3.6.0. 1696817466cbSJens Wiklander */ 1697b0563631STom Van Eyck void mbedtls_mpi_montmul(mbedtls_mpi *A, const mbedtls_mpi *B, 169832b31808SJens Wiklander const mbedtls_mpi *N, mbedtls_mpi_uint mm, 169932b31808SJens Wiklander mbedtls_mpi *T) 1700817466cbSJens Wiklander { 170132b31808SJens Wiklander mbedtls_mpi_core_montmul(A->p, A->p, B->p, B->n, N->p, N->n, mm, T->p); 1702817466cbSJens Wiklander } 1703817466cbSJens Wiklander 1704b0563631STom Van Eyck /** 1705817466cbSJens Wiklander * Montgomery reduction: A = A * R^-1 mod N 17067901324dSJerome Forissier * 1707b0563631STom Van Eyck * See mbedtls_mpi_montmul() regarding constraints and guarantees on the parameters. 1708b0563631STom Van Eyck * 1709b0563631STom Van Eyck * \remark Replaced by our own because the original has been removed since 1710b0563631STom Van Eyck * mbedtls v3.6.0. 1711817466cbSJens Wiklander */ 1712b0563631STom Van Eyck void mbedtls_mpi_montred(mbedtls_mpi *A, const mbedtls_mpi *N, 171332b31808SJens Wiklander mbedtls_mpi_uint mm, mbedtls_mpi *T) 1714817466cbSJens Wiklander { 1715817466cbSJens Wiklander mbedtls_mpi_uint z = 1; 1716817466cbSJens Wiklander mbedtls_mpi U; 1717817466cbSJens Wiklander 1718817466cbSJens Wiklander U.n = U.s = (int) z; 1719817466cbSJens Wiklander U.p = &z; 1720817466cbSJens Wiklander 1721b0563631STom Van Eyck mbedtls_mpi_montmul(A, &U, N, mm, T); 17227901324dSJerome Forissier } 17237901324dSJerome Forissier 1724817466cbSJens Wiklander /* 1725*cb034002SJerome Forissier * Warning! If the parameter E_public has MBEDTLS_MPI_IS_PUBLIC as its value, 1726*cb034002SJerome Forissier * this function is not constant time with respect to the exponent (parameter E). 1727817466cbSJens Wiklander */ 1728*cb034002SJerome Forissier static int mbedtls_mpi_exp_mod_optionally_safe(mbedtls_mpi *X, const mbedtls_mpi *A, 1729*cb034002SJerome Forissier const mbedtls_mpi *E, int E_public, 1730*cb034002SJerome Forissier const mbedtls_mpi *N, mbedtls_mpi *prec_RR) 1731817466cbSJens Wiklander { 173211fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1733817466cbSJens Wiklander 173432b31808SJens Wiklander if (mbedtls_mpi_cmp_int(N, 0) <= 0 || (N->p[0] & 1) == 0) { 173532b31808SJens Wiklander return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 173632b31808SJens Wiklander } 1737817466cbSJens Wiklander 173832b31808SJens Wiklander if (mbedtls_mpi_cmp_int(E, 0) < 0) { 173932b31808SJens Wiklander return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 174032b31808SJens Wiklander } 1741817466cbSJens Wiklander 17427901324dSJerome Forissier if (mbedtls_mpi_bitlen(E) > MBEDTLS_MPI_MAX_BITS || 174332b31808SJens Wiklander mbedtls_mpi_bitlen(N) > MBEDTLS_MPI_MAX_BITS) { 174432b31808SJens Wiklander return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 174532b31808SJens Wiklander } 17467901324dSJerome Forissier 1747817466cbSJens Wiklander /* 1748*cb034002SJerome Forissier * Ensure that the exponent that we are passing to the core is not NULL. 1749817466cbSJens Wiklander */ 1750*cb034002SJerome Forissier if (E->n == 0) { 1751*cb034002SJerome Forissier ret = mbedtls_mpi_lset(X, 1); 1752*cb034002SJerome Forissier return ret; 175332b31808SJens Wiklander } 1754817466cbSJens Wiklander 175532b31808SJens Wiklander /* 1756*cb034002SJerome Forissier * Allocate working memory for mbedtls_mpi_core_exp_mod() 175732b31808SJens Wiklander */ 1758*cb034002SJerome Forissier size_t T_limbs = mbedtls_mpi_core_exp_mod_working_limbs(N->n, E->n); 1759*cb034002SJerome Forissier mbedtls_mpi_uint *T = (mbedtls_mpi_uint *) mbedtls_calloc(T_limbs, sizeof(mbedtls_mpi_uint)); 1760*cb034002SJerome Forissier if (T == NULL) { 1761*cb034002SJerome Forissier return MBEDTLS_ERR_MPI_ALLOC_FAILED; 176232b31808SJens Wiklander } 176332b31808SJens Wiklander 1764*cb034002SJerome Forissier mbedtls_mpi RR; 1765*cb034002SJerome Forissier mbedtls_mpi_init_mempool(&RR); 1766*cb034002SJerome Forissier 176732b31808SJens Wiklander /* 176832b31808SJens Wiklander * If 1st call, pre-compute R^2 mod N 176932b31808SJens Wiklander */ 177032b31808SJens Wiklander if (prec_RR == NULL || prec_RR->p == NULL) { 1771*cb034002SJerome Forissier MBEDTLS_MPI_CHK(mbedtls_mpi_core_get_mont_r2_unsafe(&RR, N)); 177232b31808SJens Wiklander 177332b31808SJens Wiklander if (prec_RR != NULL) { 1774*cb034002SJerome Forissier *prec_RR = RR; 177532b31808SJens Wiklander } 177632b31808SJens Wiklander } else { 1777*cb034002SJerome Forissier MBEDTLS_MPI_CHK(mbedtls_mpi_grow(prec_RR, N->n)); 1778*cb034002SJerome Forissier RR = *prec_RR; 177932b31808SJens Wiklander } 178032b31808SJens Wiklander 1781817466cbSJens Wiklander /* 1782*cb034002SJerome Forissier * To preserve constness we need to make a copy of A. Using X for this to 1783*cb034002SJerome Forissier * save memory. 1784817466cbSJens Wiklander */ 1785*cb034002SJerome Forissier MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A)); 1786*cb034002SJerome Forissier 1787*cb034002SJerome Forissier /* 1788*cb034002SJerome Forissier * Compensate for negative A (and correct at the end). 1789*cb034002SJerome Forissier */ 1790*cb034002SJerome Forissier X->s = 1; 1791*cb034002SJerome Forissier 1792*cb034002SJerome Forissier /* 1793*cb034002SJerome Forissier * Make sure that X is in a form that is safe for consumption by 1794*cb034002SJerome Forissier * the core functions. 1795*cb034002SJerome Forissier * 1796*cb034002SJerome Forissier * - The core functions will not touch the limbs of X above N->n. The 1797*cb034002SJerome Forissier * result will be correct if those limbs are 0, which the mod call 1798*cb034002SJerome Forissier * ensures. 1799*cb034002SJerome Forissier * - Also, X must have at least as many limbs as N for the calls to the 1800*cb034002SJerome Forissier * core functions. 1801*cb034002SJerome Forissier */ 1802*cb034002SJerome Forissier if (mbedtls_mpi_cmp_mpi(X, N) >= 0) { 1803*cb034002SJerome Forissier MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(X, X, N)); 1804*cb034002SJerome Forissier } 1805*cb034002SJerome Forissier MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, N->n)); 1806*cb034002SJerome Forissier 1807*cb034002SJerome Forissier /* 1808*cb034002SJerome Forissier * Convert to and from Montgomery around mbedtls_mpi_core_exp_mod(). 1809*cb034002SJerome Forissier */ 1810*cb034002SJerome Forissier { 1811*cb034002SJerome Forissier mbedtls_mpi_uint mm = mbedtls_mpi_core_montmul_init(N->p); 1812*cb034002SJerome Forissier mbedtls_mpi_core_to_mont_rep(X->p, X->p, N->p, N->n, mm, RR.p, T); 1813*cb034002SJerome Forissier if (E_public == MBEDTLS_MPI_IS_PUBLIC) { 1814*cb034002SJerome Forissier mbedtls_mpi_core_exp_mod_unsafe(X->p, X->p, N->p, N->n, E->p, E->n, RR.p, T); 181532b31808SJens Wiklander } else { 1816*cb034002SJerome Forissier mbedtls_mpi_core_exp_mod(X->p, X->p, N->p, N->n, E->p, E->n, RR.p, T); 181732b31808SJens Wiklander } 1818*cb034002SJerome Forissier mbedtls_mpi_core_from_mont_rep(X->p, X->p, N->p, N->n, mm, T); 181932b31808SJens Wiklander } 1820817466cbSJens Wiklander 1821817466cbSJens Wiklander /* 1822*cb034002SJerome Forissier * Correct for negative A. 1823817466cbSJens Wiklander */ 1824*cb034002SJerome Forissier if (A->s == -1 && (E->p[0] & 1) != 0) { 1825*cb034002SJerome Forissier mbedtls_ct_condition_t is_x_non_zero = mbedtls_mpi_core_check_zero_ct(X->p, X->n); 1826*cb034002SJerome Forissier X->s = mbedtls_ct_mpi_sign_if(is_x_non_zero, -1, 1); 1827817466cbSJens Wiklander 1828*cb034002SJerome Forissier MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(X, N, X)); 1829817466cbSJens Wiklander } 183032b31808SJens Wiklander 1831817466cbSJens Wiklander cleanup: 1832817466cbSJens Wiklander 1833*cb034002SJerome Forissier mbedtls_mpi_zeroize_and_free(T, T_limbs); 1834817466cbSJens Wiklander 183532b31808SJens Wiklander if (prec_RR == NULL || prec_RR->p == NULL) { 1836817466cbSJens Wiklander mbedtls_mpi_free(&RR); 183732b31808SJens Wiklander } 1838817466cbSJens Wiklander 183932b31808SJens Wiklander return ret; 1840817466cbSJens Wiklander } 1841817466cbSJens Wiklander 1842*cb034002SJerome Forissier int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A, 1843*cb034002SJerome Forissier const mbedtls_mpi *E, const mbedtls_mpi *N, 1844*cb034002SJerome Forissier mbedtls_mpi *prec_RR) 1845*cb034002SJerome Forissier { 1846*cb034002SJerome Forissier #if (defined(__KERNEL__) && defined(CFG_CORE_UNSAFE_MODEXP)) || \ 1847*cb034002SJerome Forissier (!defined(__KERNEL__) && defined(CFG_TA_MEBDTLS_UNSAFE_MODEXP)) 1848*cb034002SJerome Forissier return mbedtls_mpi_exp_mod_unsafe(X, A, E, N, prec_RR); 1849*cb034002SJerome Forissier #else 1850*cb034002SJerome Forissier return mbedtls_mpi_exp_mod_optionally_safe(X, A, E, MBEDTLS_MPI_IS_SECRET, N, prec_RR); 1851*cb034002SJerome Forissier #endif 1852*cb034002SJerome Forissier } 1853*cb034002SJerome Forissier 1854*cb034002SJerome Forissier 1855*cb034002SJerome Forissier /* 1856*cb034002SJerome Forissier * Sliding-window exponentiation: X = A^E mod N (HAC 14.85) 1857*cb034002SJerome Forissier */ 1858*cb034002SJerome Forissier int mbedtls_mpi_exp_mod_unsafe(mbedtls_mpi *X, const mbedtls_mpi *A, 1859*cb034002SJerome Forissier const mbedtls_mpi *E, const mbedtls_mpi *N, 1860*cb034002SJerome Forissier mbedtls_mpi *prec_RR) 1861*cb034002SJerome Forissier { 1862*cb034002SJerome Forissier return mbedtls_mpi_exp_mod_optionally_safe(X, A, E, MBEDTLS_MPI_IS_PUBLIC, N, prec_RR); 1863*cb034002SJerome Forissier } 1864*cb034002SJerome Forissier 1865817466cbSJens Wiklander /* 1866817466cbSJens Wiklander * Greatest common divisor: G = gcd(A, B) (HAC 14.54) 1867817466cbSJens Wiklander */ 1868817466cbSJens Wiklander int mbedtls_mpi_gcd(mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B) 1869817466cbSJens Wiklander { 187011fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1871817466cbSJens Wiklander size_t lz, lzt; 187211fa71b9SJerome Forissier mbedtls_mpi TA, TB; 1873817466cbSJens Wiklander 187411fa71b9SJerome Forissier mbedtls_mpi_init_mempool(&TA); mbedtls_mpi_init_mempool(&TB); 1875817466cbSJens Wiklander 1876817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A)); 1877817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B)); 1878817466cbSJens Wiklander 1879817466cbSJens Wiklander lz = mbedtls_mpi_lsb(&TA); 1880817466cbSJens Wiklander lzt = mbedtls_mpi_lsb(&TB); 1881817466cbSJens Wiklander 18827901324dSJerome Forissier /* The loop below gives the correct result when A==0 but not when B==0. 18837901324dSJerome Forissier * So have a special case for B==0. Leverage the fact that we just 18847901324dSJerome Forissier * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test 18857901324dSJerome Forissier * slightly more efficient than cmp_int(). */ 188632b31808SJens Wiklander if (lzt == 0 && mbedtls_mpi_get_bit(&TB, 0) == 0) { 18877901324dSJerome Forissier ret = mbedtls_mpi_copy(G, A); 18887901324dSJerome Forissier goto cleanup; 18897901324dSJerome Forissier } 18907901324dSJerome Forissier 189132b31808SJens Wiklander if (lzt < lz) { 1892817466cbSJens Wiklander lz = lzt; 189332b31808SJens Wiklander } 1894817466cbSJens Wiklander 1895817466cbSJens Wiklander TA.s = TB.s = 1; 1896817466cbSJens Wiklander 18977901324dSJerome Forissier /* We mostly follow the procedure described in HAC 14.54, but with some 18987901324dSJerome Forissier * minor differences: 18997901324dSJerome Forissier * - Sequences of multiplications or divisions by 2 are grouped into a 19007901324dSJerome Forissier * single shift operation. 19017901324dSJerome Forissier * - The procedure in HAC assumes that 0 < TB <= TA. 19027901324dSJerome Forissier * - The condition TB <= TA is not actually necessary for correctness. 19037901324dSJerome Forissier * TA and TB have symmetric roles except for the loop termination 19047901324dSJerome Forissier * condition, and the shifts at the beginning of the loop body 19057901324dSJerome Forissier * remove any significance from the ordering of TA vs TB before 19067901324dSJerome Forissier * the shifts. 19077901324dSJerome Forissier * - If TA = 0, the loop goes through 0 iterations and the result is 19087901324dSJerome Forissier * correctly TB. 19097901324dSJerome Forissier * - The case TB = 0 was short-circuited above. 19107901324dSJerome Forissier * 19117901324dSJerome Forissier * For the correctness proof below, decompose the original values of 19127901324dSJerome Forissier * A and B as 19137901324dSJerome Forissier * A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1 19147901324dSJerome Forissier * B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1 19157901324dSJerome Forissier * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'), 19167901324dSJerome Forissier * and gcd(A',B') is odd or 0. 19177901324dSJerome Forissier * 19187901324dSJerome Forissier * At the beginning, we have TA = |A| and TB = |B| so gcd(A,B) = gcd(TA,TB). 19197901324dSJerome Forissier * The code maintains the following invariant: 19207901324dSJerome Forissier * gcd(A,B) = 2^k * gcd(TA,TB) for some k (I) 19217901324dSJerome Forissier */ 19227901324dSJerome Forissier 19237901324dSJerome Forissier /* Proof that the loop terminates: 19247901324dSJerome Forissier * At each iteration, either the right-shift by 1 is made on a nonzero 19257901324dSJerome Forissier * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases 19267901324dSJerome Forissier * by at least 1, or the right-shift by 1 is made on zero and then 19277901324dSJerome Forissier * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted 19287901324dSJerome Forissier * since in that case TB is calculated from TB-TA with the condition TB>TA). 19297901324dSJerome Forissier */ 193032b31808SJens Wiklander while (mbedtls_mpi_cmp_int(&TA, 0) != 0) { 19317901324dSJerome Forissier /* Divisions by 2 preserve the invariant (I). */ 1932817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, mbedtls_mpi_lsb(&TA))); 1933817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, mbedtls_mpi_lsb(&TB))); 1934817466cbSJens Wiklander 19357901324dSJerome Forissier /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd, 19367901324dSJerome Forissier * TA-TB is even so the division by 2 has an integer result. 19377901324dSJerome Forissier * Invariant (I) is preserved since any odd divisor of both TA and TB 19387901324dSJerome Forissier * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2 1939039e02dfSJerome Forissier * also divides TB, and any odd divisor of both TB and |TA-TB|/2 also 19407901324dSJerome Forissier * divides TA. 19417901324dSJerome Forissier */ 194232b31808SJens Wiklander if (mbedtls_mpi_cmp_mpi(&TA, &TB) >= 0) { 1943817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TA, &TA, &TB)); 1944817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, 1)); 194532b31808SJens Wiklander } else { 1946817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TB, &TB, &TA)); 1947817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, 1)); 1948817466cbSJens Wiklander } 19497901324dSJerome Forissier /* Note that one of TA or TB is still odd. */ 1950817466cbSJens Wiklander } 1951817466cbSJens Wiklander 19527901324dSJerome Forissier /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k. 19537901324dSJerome Forissier * At the loop exit, TA = 0, so gcd(TA,TB) = TB. 19547901324dSJerome Forissier * - If there was at least one loop iteration, then one of TA or TB is odd, 19557901324dSJerome Forissier * and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case, 19567901324dSJerome Forissier * lz = min(a,b) so gcd(A,B) = 2^lz * TB. 19577901324dSJerome Forissier * - If there was no loop iteration, then A was 0, and gcd(A,B) = B. 19587901324dSJerome Forissier * In this case, lz = 0 and B = TB so gcd(A,B) = B = 2^lz * TB as well. 19597901324dSJerome Forissier */ 19607901324dSJerome Forissier 1961817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&TB, lz)); 1962817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_copy(G, &TB)); 1963817466cbSJens Wiklander 1964817466cbSJens Wiklander cleanup: 1965817466cbSJens Wiklander 196611fa71b9SJerome Forissier mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TB); 1967817466cbSJens Wiklander 196832b31808SJens Wiklander return ret; 19697901324dSJerome Forissier } 19707901324dSJerome Forissier 1971817466cbSJens Wiklander /* 1972817466cbSJens Wiklander * Fill X with size bytes of random. 197332b31808SJens Wiklander * The bytes returned from the RNG are used in a specific order which 197432b31808SJens Wiklander * is suitable for deterministic ECDSA (see the specification of 197532b31808SJens Wiklander * mbedtls_mpi_random() and the implementation in mbedtls_mpi_fill_random()). 1976817466cbSJens Wiklander */ 1977817466cbSJens Wiklander int mbedtls_mpi_fill_random(mbedtls_mpi *X, size_t size, 1978817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 1979817466cbSJens Wiklander void *p_rng) 1980817466cbSJens Wiklander { 198111fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 198232b31808SJens Wiklander const size_t limbs = CHARS_TO_LIMBS(size); 19835b25c76aSJerome Forissier 19845b25c76aSJerome Forissier /* Ensure that target MPI has exactly the necessary number of limbs */ 19857901324dSJerome Forissier MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs)); 198632b31808SJens Wiklander if (size == 0) { 198732b31808SJens Wiklander return 0; 198832b31808SJens Wiklander } 1989817466cbSJens Wiklander 199032b31808SJens Wiklander ret = mbedtls_mpi_core_fill_random(X->p, X->n, size, f_rng, p_rng); 1991817466cbSJens Wiklander 1992817466cbSJens Wiklander cleanup: 199332b31808SJens Wiklander return ret; 1994817466cbSJens Wiklander } 1995817466cbSJens Wiklander 19967901324dSJerome Forissier int mbedtls_mpi_random(mbedtls_mpi *X, 19977901324dSJerome Forissier mbedtls_mpi_sint min, 19987901324dSJerome Forissier const mbedtls_mpi *N, 19997901324dSJerome Forissier int (*f_rng)(void *, unsigned char *, size_t), 20007901324dSJerome Forissier void *p_rng) 20017901324dSJerome Forissier { 200232b31808SJens Wiklander if (min < 0) { 200332b31808SJens Wiklander return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 200432b31808SJens Wiklander } 200532b31808SJens Wiklander if (mbedtls_mpi_cmp_int(N, min) <= 0) { 200632b31808SJens Wiklander return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 200732b31808SJens Wiklander } 20087901324dSJerome Forissier 20097901324dSJerome Forissier /* Ensure that target MPI has exactly the same number of limbs 20107901324dSJerome Forissier * as the upper bound, even if the upper bound has leading zeros. 201132b31808SJens Wiklander * This is necessary for mbedtls_mpi_core_random. */ 201232b31808SJens Wiklander int ret = mbedtls_mpi_resize_clear(X, N->n); 201332b31808SJens Wiklander if (ret != 0) { 201432b31808SJens Wiklander return ret; 20157901324dSJerome Forissier } 20167901324dSJerome Forissier 201732b31808SJens Wiklander return mbedtls_mpi_core_random(X->p, min, N->p, X->n, f_rng, p_rng); 20187901324dSJerome Forissier } 20197901324dSJerome Forissier 2020817466cbSJens Wiklander /* 2021817466cbSJens Wiklander * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64) 2022817466cbSJens Wiklander */ 2023817466cbSJens Wiklander int mbedtls_mpi_inv_mod(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N) 2024817466cbSJens Wiklander { 202511fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 2026817466cbSJens Wiklander mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2; 2027817466cbSJens Wiklander 202832b31808SJens Wiklander if (mbedtls_mpi_cmp_int(N, 1) <= 0) { 202932b31808SJens Wiklander return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 203032b31808SJens Wiklander } 2031817466cbSJens Wiklander 203298bd5fe3SJens Wiklander mbedtls_mpi_init_mempool(&TA); mbedtls_mpi_init_mempool(&TU); 203398bd5fe3SJens Wiklander mbedtls_mpi_init_mempool(&U1); mbedtls_mpi_init_mempool(&U2); 203498bd5fe3SJens Wiklander mbedtls_mpi_init_mempool(&G); mbedtls_mpi_init_mempool(&TB); 203598bd5fe3SJens Wiklander mbedtls_mpi_init_mempool(&TV); mbedtls_mpi_init_mempool(&V1); 203698bd5fe3SJens Wiklander mbedtls_mpi_init_mempool(&V2); 2037817466cbSJens Wiklander 2038817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&G, A, N)); 2039817466cbSJens Wiklander 204032b31808SJens Wiklander if (mbedtls_mpi_cmp_int(&G, 1) != 0) { 2041817466cbSJens Wiklander ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; 2042817466cbSJens Wiklander goto cleanup; 2043817466cbSJens Wiklander } 2044817466cbSJens Wiklander 2045817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&TA, A, N)); 2046817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TU, &TA)); 2047817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, N)); 2048817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TV, N)); 2049817466cbSJens Wiklander 2050817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U1, 1)); 2051817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U2, 0)); 2052817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V1, 0)); 2053817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V2, 1)); 2054817466cbSJens Wiklander 205532b31808SJens Wiklander do { 205632b31808SJens Wiklander while ((TU.p[0] & 1) == 0) { 2057817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TU, 1)); 2058817466cbSJens Wiklander 205932b31808SJens Wiklander if ((U1.p[0] & 1) != 0 || (U2.p[0] & 1) != 0) { 2060817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&U1, &U1, &TB)); 2061817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &TA)); 2062817466cbSJens Wiklander } 2063817466cbSJens Wiklander 2064817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U1, 1)); 2065817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U2, 1)); 2066817466cbSJens Wiklander } 2067817466cbSJens Wiklander 206832b31808SJens Wiklander while ((TV.p[0] & 1) == 0) { 2069817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TV, 1)); 2070817466cbSJens Wiklander 207132b31808SJens Wiklander if ((V1.p[0] & 1) != 0 || (V2.p[0] & 1) != 0) { 2072817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, &TB)); 2073817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &TA)); 2074817466cbSJens Wiklander } 2075817466cbSJens Wiklander 2076817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V1, 1)); 2077817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V2, 1)); 2078817466cbSJens Wiklander } 2079817466cbSJens Wiklander 208032b31808SJens Wiklander if (mbedtls_mpi_cmp_mpi(&TU, &TV) >= 0) { 2081817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TU, &TU, &TV)); 2082817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U1, &U1, &V1)); 2083817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &V2)); 208432b31808SJens Wiklander } else { 2085817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TV, &TV, &TU)); 2086817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, &U1)); 2087817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &U2)); 2088817466cbSJens Wiklander } 208932b31808SJens Wiklander } while (mbedtls_mpi_cmp_int(&TU, 0) != 0); 2090817466cbSJens Wiklander 209132b31808SJens Wiklander while (mbedtls_mpi_cmp_int(&V1, 0) < 0) { 2092817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, N)); 209332b31808SJens Wiklander } 2094817466cbSJens Wiklander 209532b31808SJens Wiklander while (mbedtls_mpi_cmp_mpi(&V1, N) >= 0) { 2096817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, N)); 209732b31808SJens Wiklander } 2098817466cbSJens Wiklander 2099817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &V1)); 2100817466cbSJens Wiklander 2101817466cbSJens Wiklander cleanup: 2102817466cbSJens Wiklander 2103817466cbSJens Wiklander mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TU); mbedtls_mpi_free(&U1); mbedtls_mpi_free(&U2); 2104817466cbSJens Wiklander mbedtls_mpi_free(&G); mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TV); 2105817466cbSJens Wiklander mbedtls_mpi_free(&V1); mbedtls_mpi_free(&V2); 2106817466cbSJens Wiklander 210732b31808SJens Wiklander return ret; 2108817466cbSJens Wiklander } 2109817466cbSJens Wiklander 2110817466cbSJens Wiklander #if defined(MBEDTLS_GENPRIME) 2111817466cbSJens Wiklander 2112b0563631STom Van Eyck /* Gaps between primes, starting at 3. https://oeis.org/A001223 */ 2113b0563631STom Van Eyck static const unsigned char small_prime_gaps[] = { 2114b0563631STom Van Eyck 2, 2, 4, 2, 4, 2, 4, 6, 2115b0563631STom Van Eyck 2, 6, 4, 2, 4, 6, 6, 2, 2116b0563631STom Van Eyck 6, 4, 2, 6, 4, 6, 8, 4, 2117b0563631STom Van Eyck 2, 4, 2, 4, 14, 4, 6, 2, 2118b0563631STom Van Eyck 10, 2, 6, 6, 4, 6, 6, 2, 2119b0563631STom Van Eyck 10, 2, 4, 2, 12, 12, 4, 2, 2120b0563631STom Van Eyck 4, 6, 2, 10, 6, 6, 6, 2, 2121b0563631STom Van Eyck 6, 4, 2, 10, 14, 4, 2, 4, 2122b0563631STom Van Eyck 14, 6, 10, 2, 4, 6, 8, 6, 2123b0563631STom Van Eyck 6, 4, 6, 8, 4, 8, 10, 2, 2124b0563631STom Van Eyck 10, 2, 6, 4, 6, 8, 4, 2, 2125b0563631STom Van Eyck 4, 12, 8, 4, 8, 4, 6, 12, 2126b0563631STom Van Eyck 2, 18, 6, 10, 6, 6, 2, 6, 2127b0563631STom Van Eyck 10, 6, 6, 2, 6, 6, 4, 2, 2128b0563631STom Van Eyck 12, 10, 2, 4, 6, 6, 2, 12, 2129b0563631STom Van Eyck 4, 6, 8, 10, 8, 10, 8, 6, 2130b0563631STom Van Eyck 6, 4, 8, 6, 4, 8, 4, 14, 2131b0563631STom Van Eyck 10, 12, 2, 10, 2, 4, 2, 10, 2132b0563631STom Van Eyck 14, 4, 2, 4, 14, 4, 2, 4, 2133b0563631STom Van Eyck 20, 4, 8, 10, 8, 4, 6, 6, 2134b0563631STom Van Eyck 14, 4, 6, 6, 8, 6, /*reaches 997*/ 2135b0563631STom Van Eyck 0 /* the last entry is effectively unused */ 2136817466cbSJens Wiklander }; 2137817466cbSJens Wiklander 2138817466cbSJens Wiklander /* 2139817466cbSJens Wiklander * Small divisors test (X must be positive) 2140817466cbSJens Wiklander * 2141817466cbSJens Wiklander * Return values: 2142817466cbSJens Wiklander * 0: no small factor (possible prime, more tests needed) 2143817466cbSJens Wiklander * 1: certain prime 2144817466cbSJens Wiklander * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime 2145817466cbSJens Wiklander * other negative: error 2146817466cbSJens Wiklander */ 2147817466cbSJens Wiklander static int mpi_check_small_factors(const mbedtls_mpi *X) 2148817466cbSJens Wiklander { 2149817466cbSJens Wiklander int ret = 0; 2150817466cbSJens Wiklander size_t i; 2151817466cbSJens Wiklander mbedtls_mpi_uint r; 2152b0563631STom Van Eyck unsigned p = 3; /* The first odd prime */ 2153817466cbSJens Wiklander 215432b31808SJens Wiklander if ((X->p[0] & 1) == 0) { 215532b31808SJens Wiklander return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; 215632b31808SJens Wiklander } 2157817466cbSJens Wiklander 2158b0563631STom Van Eyck for (i = 0; i < sizeof(small_prime_gaps); p += small_prime_gaps[i], i++) { 2159b0563631STom Van Eyck MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, p)); 216032b31808SJens Wiklander if (r == 0) { 2161b0563631STom Van Eyck if (mbedtls_mpi_cmp_int(X, p) == 0) { 2162b0563631STom Van Eyck return 1; 2163b0563631STom Van Eyck } else { 216432b31808SJens Wiklander return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; 216532b31808SJens Wiklander } 2166817466cbSJens Wiklander } 2167b0563631STom Van Eyck } 2168817466cbSJens Wiklander 2169817466cbSJens Wiklander cleanup: 217032b31808SJens Wiklander return ret; 2171817466cbSJens Wiklander } 2172817466cbSJens Wiklander 2173817466cbSJens Wiklander /* 2174817466cbSJens Wiklander * Miller-Rabin pseudo-primality test (HAC 4.24) 2175817466cbSJens Wiklander */ 21763d3b0591SJens Wiklander static int mpi_miller_rabin(const mbedtls_mpi *X, size_t rounds, 2177817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 2178817466cbSJens Wiklander void *p_rng) 2179817466cbSJens Wiklander { 2180817466cbSJens Wiklander int ret, count; 21813d3b0591SJens Wiklander size_t i, j, k, s; 2182817466cbSJens Wiklander mbedtls_mpi W, R, T, A, RR; 2183817466cbSJens Wiklander 218498bd5fe3SJens Wiklander mbedtls_mpi_init_mempool(&W); mbedtls_mpi_init_mempool(&R); 218598bd5fe3SJens Wiklander mbedtls_mpi_init_mempool(&T); mbedtls_mpi_init_mempool(&A); 218698bd5fe3SJens Wiklander mbedtls_mpi_init_mempool(&RR); 2187817466cbSJens Wiklander 2188817466cbSJens Wiklander /* 2189817466cbSJens Wiklander * W = |X| - 1 2190817466cbSJens Wiklander * R = W >> lsb( W ) 2191817466cbSJens Wiklander */ 2192817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&W, X, 1)); 2193817466cbSJens Wiklander s = mbedtls_mpi_lsb(&W); 2194817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&R, &W)); 2195817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&R, s)); 2196817466cbSJens Wiklander 219732b31808SJens Wiklander for (i = 0; i < rounds; i++) { 2198817466cbSJens Wiklander /* 2199817466cbSJens Wiklander * pick a random A, 1 < A < |X| - 1 2200817466cbSJens Wiklander */ 2201817466cbSJens Wiklander count = 0; 2202817466cbSJens Wiklander do { 2203817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&A, X->n * ciL, f_rng, p_rng)); 2204817466cbSJens Wiklander 2205817466cbSJens Wiklander j = mbedtls_mpi_bitlen(&A); 2206817466cbSJens Wiklander k = mbedtls_mpi_bitlen(&W); 2207817466cbSJens Wiklander if (j > k) { 22083d3b0591SJens Wiklander A.p[A.n - 1] &= ((mbedtls_mpi_uint) 1 << (k - (A.n - 1) * biL - 1)) - 1; 2209817466cbSJens Wiklander } 2210817466cbSJens Wiklander 2211117cce93SJens Wiklander if (count++ > 300) { 2212336e3299SJens Wiklander ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; 2213336e3299SJens Wiklander goto cleanup; 2214817466cbSJens Wiklander } 2215817466cbSJens Wiklander 2216817466cbSJens Wiklander } while (mbedtls_mpi_cmp_mpi(&A, &W) >= 0 || 2217817466cbSJens Wiklander mbedtls_mpi_cmp_int(&A, 1) <= 0); 2218817466cbSJens Wiklander 2219817466cbSJens Wiklander /* 2220817466cbSJens Wiklander * A = A^R mod |X| 2221817466cbSJens Wiklander */ 2222817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&A, &A, &R, X, &RR)); 2223817466cbSJens Wiklander 2224817466cbSJens Wiklander if (mbedtls_mpi_cmp_mpi(&A, &W) == 0 || 222532b31808SJens Wiklander mbedtls_mpi_cmp_int(&A, 1) == 0) { 2226817466cbSJens Wiklander continue; 222732b31808SJens Wiklander } 2228817466cbSJens Wiklander 2229817466cbSJens Wiklander j = 1; 223032b31808SJens Wiklander while (j < s && mbedtls_mpi_cmp_mpi(&A, &W) != 0) { 2231817466cbSJens Wiklander /* 2232817466cbSJens Wiklander * A = A * A mod |X| 2233817466cbSJens Wiklander */ 2234817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &A, &A)); 2235817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&A, &T, X)); 2236817466cbSJens Wiklander 223732b31808SJens Wiklander if (mbedtls_mpi_cmp_int(&A, 1) == 0) { 2238817466cbSJens Wiklander break; 223932b31808SJens Wiklander } 2240817466cbSJens Wiklander 2241817466cbSJens Wiklander j++; 2242817466cbSJens Wiklander } 2243817466cbSJens Wiklander 2244817466cbSJens Wiklander /* 2245817466cbSJens Wiklander * not prime if A != |X| - 1 or A == 1 2246817466cbSJens Wiklander */ 2247817466cbSJens Wiklander if (mbedtls_mpi_cmp_mpi(&A, &W) != 0 || 224832b31808SJens Wiklander mbedtls_mpi_cmp_int(&A, 1) == 0) { 2249817466cbSJens Wiklander ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; 2250817466cbSJens Wiklander break; 2251817466cbSJens Wiklander } 2252817466cbSJens Wiklander } 2253817466cbSJens Wiklander 2254817466cbSJens Wiklander cleanup: 22553d3b0591SJens Wiklander mbedtls_mpi_free(&W); mbedtls_mpi_free(&R); 22563d3b0591SJens Wiklander mbedtls_mpi_free(&T); mbedtls_mpi_free(&A); 2257817466cbSJens Wiklander mbedtls_mpi_free(&RR); 2258817466cbSJens Wiklander 225932b31808SJens Wiklander return ret; 2260817466cbSJens Wiklander } 2261817466cbSJens Wiklander 2262817466cbSJens Wiklander /* 2263817466cbSJens Wiklander * Pseudo-primality test: small factors, then Miller-Rabin 2264817466cbSJens Wiklander */ 22653d3b0591SJens Wiklander int mbedtls_mpi_is_prime_ext(const mbedtls_mpi *X, int rounds, 2266817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 2267817466cbSJens Wiklander void *p_rng) 2268817466cbSJens Wiklander { 226911fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 2270817466cbSJens Wiklander mbedtls_mpi XX; 2271817466cbSJens Wiklander 2272817466cbSJens Wiklander XX.s = 1; 2273817466cbSJens Wiklander XX.n = X->n; 2274817466cbSJens Wiklander XX.p = X->p; 2275817466cbSJens Wiklander 2276817466cbSJens Wiklander if (mbedtls_mpi_cmp_int(&XX, 0) == 0 || 227732b31808SJens Wiklander mbedtls_mpi_cmp_int(&XX, 1) == 0) { 227832b31808SJens Wiklander return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; 2279817466cbSJens Wiklander } 2280817466cbSJens Wiklander 228132b31808SJens Wiklander if (mbedtls_mpi_cmp_int(&XX, 2) == 0) { 228232b31808SJens Wiklander return 0; 2283817466cbSJens Wiklander } 2284817466cbSJens Wiklander 228532b31808SJens Wiklander if ((ret = mpi_check_small_factors(&XX)) != 0) { 228632b31808SJens Wiklander if (ret == 1) { 228732b31808SJens Wiklander return 0; 22883d3b0591SJens Wiklander } 228932b31808SJens Wiklander 229032b31808SJens Wiklander return ret; 229132b31808SJens Wiklander } 229232b31808SJens Wiklander 229332b31808SJens Wiklander return mpi_miller_rabin(&XX, rounds, f_rng, p_rng); 229432b31808SJens Wiklander } 22953d3b0591SJens Wiklander 22963d3b0591SJens Wiklander /* 22973d3b0591SJens Wiklander * Prime number generation 22983d3b0591SJens Wiklander * 22993d3b0591SJens Wiklander * To generate an RSA key in a way recommended by FIPS 186-4, both primes must 23003d3b0591SJens Wiklander * be either 1024 bits or 1536 bits long, and flags must contain 23013d3b0591SJens Wiklander * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR. 23023d3b0591SJens Wiklander */ 23033d3b0591SJens Wiklander int mbedtls_mpi_gen_prime(mbedtls_mpi *X, size_t nbits, int flags, 23043d3b0591SJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 23053d3b0591SJens Wiklander void *p_rng) 23063d3b0591SJens Wiklander { 23073d3b0591SJens Wiklander #ifdef MBEDTLS_HAVE_INT64 23083d3b0591SJens Wiklander // ceil(2^63.5) 23093d3b0591SJens Wiklander #define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL 23103d3b0591SJens Wiklander #else 23113d3b0591SJens Wiklander // ceil(2^31.5) 23123d3b0591SJens Wiklander #define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U 23133d3b0591SJens Wiklander #endif 23143d3b0591SJens Wiklander int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; 2315817466cbSJens Wiklander size_t k, n; 23163d3b0591SJens Wiklander int rounds; 2317817466cbSJens Wiklander mbedtls_mpi_uint r; 2318817466cbSJens Wiklander mbedtls_mpi Y; 2319817466cbSJens Wiklander 232032b31808SJens Wiklander if (nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS) { 232132b31808SJens Wiklander return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 232232b31808SJens Wiklander } 2323817466cbSJens Wiklander 232498bd5fe3SJens Wiklander mbedtls_mpi_init_mempool(&Y); 2325817466cbSJens Wiklander 2326817466cbSJens Wiklander n = BITS_TO_LIMBS(nbits); 2327817466cbSJens Wiklander 232832b31808SJens Wiklander if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR) == 0) { 23293d3b0591SJens Wiklander /* 23303d3b0591SJens Wiklander * 2^-80 error probability, number of rounds chosen per HAC, table 4.4 23313d3b0591SJens Wiklander */ 23323d3b0591SJens Wiklander rounds = ((nbits >= 1300) ? 2 : (nbits >= 850) ? 3 : 23333d3b0591SJens Wiklander (nbits >= 650) ? 4 : (nbits >= 350) ? 8 : 23343d3b0591SJens Wiklander (nbits >= 250) ? 12 : (nbits >= 150) ? 18 : 27); 233532b31808SJens Wiklander } else { 23363d3b0591SJens Wiklander /* 23373d3b0591SJens Wiklander * 2^-100 error probability, number of rounds computed based on HAC, 23383d3b0591SJens Wiklander * fact 4.48 23393d3b0591SJens Wiklander */ 23403d3b0591SJens Wiklander rounds = ((nbits >= 1450) ? 4 : (nbits >= 1150) ? 5 : 23413d3b0591SJens Wiklander (nbits >= 1000) ? 6 : (nbits >= 850) ? 7 : 23423d3b0591SJens Wiklander (nbits >= 750) ? 8 : (nbits >= 500) ? 13 : 23433d3b0591SJens Wiklander (nbits >= 250) ? 28 : (nbits >= 150) ? 40 : 51); 23443d3b0591SJens Wiklander } 23453d3b0591SJens Wiklander 234632b31808SJens Wiklander while (1) { 2347817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(X, n * ciL, f_rng, p_rng)); 23483d3b0591SJens Wiklander /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */ 234932b31808SJens Wiklander if (X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2) { 235032b31808SJens Wiklander continue; 235132b31808SJens Wiklander } 2352817466cbSJens Wiklander 23533d3b0591SJens Wiklander k = n * biL; 235432b31808SJens Wiklander if (k > nbits) { 235532b31808SJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(X, k - nbits)); 235632b31808SJens Wiklander } 2357817466cbSJens Wiklander X->p[0] |= 1; 2358817466cbSJens Wiklander 235932b31808SJens Wiklander if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH) == 0) { 23603d3b0591SJens Wiklander ret = mbedtls_mpi_is_prime_ext(X, rounds, f_rng, p_rng); 23613d3b0591SJens Wiklander 236232b31808SJens Wiklander if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) { 2363817466cbSJens Wiklander goto cleanup; 2364817466cbSJens Wiklander } 236532b31808SJens Wiklander } else { 2366817466cbSJens Wiklander /* 236732b31808SJens Wiklander * A necessary condition for Y and X = 2Y + 1 to be prime 2368817466cbSJens Wiklander * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3). 2369817466cbSJens Wiklander * Make sure it is satisfied, while keeping X = 3 mod 4 2370817466cbSJens Wiklander */ 2371817466cbSJens Wiklander 2372817466cbSJens Wiklander X->p[0] |= 2; 2373817466cbSJens Wiklander 2374817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, 3)); 237532b31808SJens Wiklander if (r == 0) { 2376817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 8)); 237732b31808SJens Wiklander } else if (r == 1) { 2378817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 4)); 237932b31808SJens Wiklander } 2380817466cbSJens Wiklander 2381817466cbSJens Wiklander /* Set Y = (X-1) / 2, which is X / 2 because X is odd */ 2382817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, X)); 2383817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, 1)); 2384817466cbSJens Wiklander 238532b31808SJens Wiklander while (1) { 2386817466cbSJens Wiklander /* 2387817466cbSJens Wiklander * First, check small factors for X and Y 2388817466cbSJens Wiklander * before doing Miller-Rabin on any of them 2389817466cbSJens Wiklander */ 2390817466cbSJens Wiklander if ((ret = mpi_check_small_factors(X)) == 0 && 2391817466cbSJens Wiklander (ret = mpi_check_small_factors(&Y)) == 0 && 23923d3b0591SJens Wiklander (ret = mpi_miller_rabin(X, rounds, f_rng, p_rng)) 23933d3b0591SJens Wiklander == 0 && 23943d3b0591SJens Wiklander (ret = mpi_miller_rabin(&Y, rounds, f_rng, p_rng)) 239532b31808SJens Wiklander == 0) { 23963d3b0591SJens Wiklander goto cleanup; 239732b31808SJens Wiklander } 2398817466cbSJens Wiklander 239932b31808SJens Wiklander if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) { 2400817466cbSJens Wiklander goto cleanup; 240132b31808SJens Wiklander } 2402817466cbSJens Wiklander 2403817466cbSJens Wiklander /* 2404817466cbSJens Wiklander * Next candidates. We want to preserve Y = (X-1) / 2 and 2405817466cbSJens Wiklander * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3) 2406817466cbSJens Wiklander * so up Y by 6 and X by 12. 2407817466cbSJens Wiklander */ 2408817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 12)); 2409817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&Y, &Y, 6)); 2410817466cbSJens Wiklander } 2411817466cbSJens Wiklander } 24123d3b0591SJens Wiklander } 2413817466cbSJens Wiklander 2414817466cbSJens Wiklander cleanup: 2415817466cbSJens Wiklander 2416817466cbSJens Wiklander mbedtls_mpi_free(&Y); 2417817466cbSJens Wiklander 241832b31808SJens Wiklander return ret; 2419817466cbSJens Wiklander } 2420817466cbSJens Wiklander 2421817466cbSJens Wiklander #endif /* MBEDTLS_GENPRIME */ 2422817466cbSJens Wiklander 2423817466cbSJens Wiklander #if defined(MBEDTLS_SELF_TEST) 2424817466cbSJens Wiklander 2425817466cbSJens Wiklander #define GCD_PAIR_COUNT 3 2426817466cbSJens Wiklander 2427817466cbSJens Wiklander static const int gcd_pairs[GCD_PAIR_COUNT][3] = 2428817466cbSJens Wiklander { 2429817466cbSJens Wiklander { 693, 609, 21 }, 2430817466cbSJens Wiklander { 1764, 868, 28 }, 2431817466cbSJens Wiklander { 768454923, 542167814, 1 } 2432817466cbSJens Wiklander }; 2433817466cbSJens Wiklander 2434817466cbSJens Wiklander /* 2435817466cbSJens Wiklander * Checkup routine 2436817466cbSJens Wiklander */ 2437817466cbSJens Wiklander int mbedtls_mpi_self_test(int verbose) 2438817466cbSJens Wiklander { 2439817466cbSJens Wiklander int ret, i; 2440817466cbSJens Wiklander mbedtls_mpi A, E, N, X, Y, U, V; 2441817466cbSJens Wiklander 244298bd5fe3SJens Wiklander mbedtls_mpi_init_mempool(&A); mbedtls_mpi_init_mempool(&E); 244398bd5fe3SJens Wiklander mbedtls_mpi_init_mempool(&N); mbedtls_mpi_init_mempool(&X); 244498bd5fe3SJens Wiklander mbedtls_mpi_init_mempool(&Y); mbedtls_mpi_init_mempool(&U); 244598bd5fe3SJens Wiklander mbedtls_mpi_init_mempool(&V); 2446817466cbSJens Wiklander 2447817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&A, 16, 2448817466cbSJens Wiklander "EFE021C2645FD1DC586E69184AF4A31E" \ 2449817466cbSJens Wiklander "D5F53E93B5F123FA41680867BA110131" \ 2450817466cbSJens Wiklander "944FE7952E2517337780CB0DB80E61AA" \ 2451817466cbSJens Wiklander "E7C8DDC6C5C6AADEB34EB38A2F40D5E6")); 2452817466cbSJens Wiklander 2453817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&E, 16, 2454817466cbSJens Wiklander "B2E7EFD37075B9F03FF989C7C5051C20" \ 2455817466cbSJens Wiklander "34D2A323810251127E7BF8625A4F49A5" \ 2456817466cbSJens Wiklander "F3E27F4DA8BD59C47D6DAABA4C8127BD" \ 2457817466cbSJens Wiklander "5B5C25763222FEFCCFC38B832366C29E")); 2458817466cbSJens Wiklander 2459817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&N, 16, 2460817466cbSJens Wiklander "0066A198186C18C10B2F5ED9B522752A" \ 2461817466cbSJens Wiklander "9830B69916E535C8F047518A889A43A5" \ 2462817466cbSJens Wiklander "94B6BED27A168D31D4A52F88925AA8F5")); 2463817466cbSJens Wiklander 2464817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&X, &A, &N)); 2465817466cbSJens Wiklander 2466817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16, 2467817466cbSJens Wiklander "602AB7ECA597A3D6B56FF9829A5E8B85" \ 2468817466cbSJens Wiklander "9E857EA95A03512E2BAE7391688D264A" \ 2469817466cbSJens Wiklander "A5663B0341DB9CCFD2C4C5F421FEC814" \ 2470817466cbSJens Wiklander "8001B72E848A38CAE1C65F78E56ABDEF" \ 2471817466cbSJens Wiklander "E12D3C039B8A02D6BE593F0BBBDA56F1" \ 2472817466cbSJens Wiklander "ECF677152EF804370C1A305CAF3B5BF1" \ 2473817466cbSJens Wiklander "30879B56C61DE584A0F53A2447A51E")); 2474817466cbSJens Wiklander 247532b31808SJens Wiklander if (verbose != 0) { 2476817466cbSJens Wiklander mbedtls_printf(" MPI test #1 (mul_mpi): "); 247732b31808SJens Wiklander } 2478817466cbSJens Wiklander 247932b31808SJens Wiklander if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) { 248032b31808SJens Wiklander if (verbose != 0) { 2481817466cbSJens Wiklander mbedtls_printf("failed\n"); 248232b31808SJens Wiklander } 2483817466cbSJens Wiklander 2484817466cbSJens Wiklander ret = 1; 2485817466cbSJens Wiklander goto cleanup; 2486817466cbSJens Wiklander } 2487817466cbSJens Wiklander 248832b31808SJens Wiklander if (verbose != 0) { 2489817466cbSJens Wiklander mbedtls_printf("passed\n"); 249032b31808SJens Wiklander } 2491817466cbSJens Wiklander 2492817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&X, &Y, &A, &N)); 2493817466cbSJens Wiklander 2494817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16, 2495817466cbSJens Wiklander "256567336059E52CAE22925474705F39A94")); 2496817466cbSJens Wiklander 2497817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&V, 16, 2498817466cbSJens Wiklander "6613F26162223DF488E9CD48CC132C7A" \ 2499817466cbSJens Wiklander "0AC93C701B001B092E4E5B9F73BCD27B" \ 2500817466cbSJens Wiklander "9EE50D0657C77F374E903CDFA4C642")); 2501817466cbSJens Wiklander 250232b31808SJens Wiklander if (verbose != 0) { 2503817466cbSJens Wiklander mbedtls_printf(" MPI test #2 (div_mpi): "); 250432b31808SJens Wiklander } 2505817466cbSJens Wiklander 2506817466cbSJens Wiklander if (mbedtls_mpi_cmp_mpi(&X, &U) != 0 || 250732b31808SJens Wiklander mbedtls_mpi_cmp_mpi(&Y, &V) != 0) { 250832b31808SJens Wiklander if (verbose != 0) { 2509817466cbSJens Wiklander mbedtls_printf("failed\n"); 251032b31808SJens Wiklander } 2511817466cbSJens Wiklander 2512817466cbSJens Wiklander ret = 1; 2513817466cbSJens Wiklander goto cleanup; 2514817466cbSJens Wiklander } 2515817466cbSJens Wiklander 251632b31808SJens Wiklander if (verbose != 0) { 2517817466cbSJens Wiklander mbedtls_printf("passed\n"); 251832b31808SJens Wiklander } 2519817466cbSJens Wiklander 2520817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&X, &A, &E, &N, NULL)); 2521817466cbSJens Wiklander 2522817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16, 2523817466cbSJens Wiklander "36E139AEA55215609D2816998ED020BB" \ 2524817466cbSJens Wiklander "BD96C37890F65171D948E9BC7CBAA4D9" \ 2525817466cbSJens Wiklander "325D24D6A3C12710F10A09FA08AB87")); 2526817466cbSJens Wiklander 252732b31808SJens Wiklander if (verbose != 0) { 2528817466cbSJens Wiklander mbedtls_printf(" MPI test #3 (exp_mod): "); 252932b31808SJens Wiklander } 2530817466cbSJens Wiklander 253132b31808SJens Wiklander if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) { 253232b31808SJens Wiklander if (verbose != 0) { 2533817466cbSJens Wiklander mbedtls_printf("failed\n"); 253432b31808SJens Wiklander } 2535817466cbSJens Wiklander 2536817466cbSJens Wiklander ret = 1; 2537817466cbSJens Wiklander goto cleanup; 2538817466cbSJens Wiklander } 2539817466cbSJens Wiklander 254032b31808SJens Wiklander if (verbose != 0) { 2541817466cbSJens Wiklander mbedtls_printf("passed\n"); 254232b31808SJens Wiklander } 2543817466cbSJens Wiklander 2544817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&X, &A, &N)); 2545817466cbSJens Wiklander 2546817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16, 2547817466cbSJens Wiklander "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \ 2548817466cbSJens Wiklander "C3DBA76456363A10869622EAC2DD84EC" \ 2549817466cbSJens Wiklander "C5B8A74DAC4D09E03B5E0BE779F2DF61")); 2550817466cbSJens Wiklander 255132b31808SJens Wiklander if (verbose != 0) { 2552817466cbSJens Wiklander mbedtls_printf(" MPI test #4 (inv_mod): "); 255332b31808SJens Wiklander } 2554817466cbSJens Wiklander 255532b31808SJens Wiklander if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) { 255632b31808SJens Wiklander if (verbose != 0) { 2557817466cbSJens Wiklander mbedtls_printf("failed\n"); 255832b31808SJens Wiklander } 2559817466cbSJens Wiklander 2560817466cbSJens Wiklander ret = 1; 2561817466cbSJens Wiklander goto cleanup; 2562817466cbSJens Wiklander } 2563817466cbSJens Wiklander 256432b31808SJens Wiklander if (verbose != 0) { 2565817466cbSJens Wiklander mbedtls_printf("passed\n"); 256632b31808SJens Wiklander } 2567817466cbSJens Wiklander 256832b31808SJens Wiklander if (verbose != 0) { 2569817466cbSJens Wiklander mbedtls_printf(" MPI test #5 (simple gcd): "); 257032b31808SJens Wiklander } 2571817466cbSJens Wiklander 257232b31808SJens Wiklander for (i = 0; i < GCD_PAIR_COUNT; i++) { 2573817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&X, gcd_pairs[i][0])); 2574817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Y, gcd_pairs[i][1])); 2575817466cbSJens Wiklander 2576817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&A, &X, &Y)); 2577817466cbSJens Wiklander 257832b31808SJens Wiklander if (mbedtls_mpi_cmp_int(&A, gcd_pairs[i][2]) != 0) { 257932b31808SJens Wiklander if (verbose != 0) { 2580817466cbSJens Wiklander mbedtls_printf("failed at %d\n", i); 258132b31808SJens Wiklander } 2582817466cbSJens Wiklander 2583817466cbSJens Wiklander ret = 1; 2584817466cbSJens Wiklander goto cleanup; 2585817466cbSJens Wiklander } 2586817466cbSJens Wiklander } 2587817466cbSJens Wiklander 258832b31808SJens Wiklander if (verbose != 0) { 2589817466cbSJens Wiklander mbedtls_printf("passed\n"); 259032b31808SJens Wiklander } 2591817466cbSJens Wiklander 2592817466cbSJens Wiklander cleanup: 2593817466cbSJens Wiklander 259432b31808SJens Wiklander if (ret != 0 && verbose != 0) { 25957901324dSJerome Forissier mbedtls_printf("Unexpected error, return code = %08X\n", (unsigned int) ret); 259632b31808SJens Wiklander } 2597817466cbSJens Wiklander 2598817466cbSJens Wiklander mbedtls_mpi_free(&A); mbedtls_mpi_free(&E); mbedtls_mpi_free(&N); mbedtls_mpi_free(&X); 2599817466cbSJens Wiklander mbedtls_mpi_free(&Y); mbedtls_mpi_free(&U); mbedtls_mpi_free(&V); 2600817466cbSJens Wiklander 260132b31808SJens Wiklander if (verbose != 0) { 2602817466cbSJens Wiklander mbedtls_printf("\n"); 260332b31808SJens Wiklander } 2604817466cbSJens Wiklander 260532b31808SJens Wiklander return ret; 2606817466cbSJens Wiklander } 2607817466cbSJens Wiklander 2608817466cbSJens Wiklander #endif /* MBEDTLS_SELF_TEST */ 2609817466cbSJens Wiklander 2610817466cbSJens Wiklander #endif /* MBEDTLS_BIGNUM_C */ 2611