1a8e1175bSopenharmony_ci/* 2a8e1175bSopenharmony_ci * Multi-precision integer library 3a8e1175bSopenharmony_ci * 4a8e1175bSopenharmony_ci * Copyright The Mbed TLS Contributors 5a8e1175bSopenharmony_ci * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 6a8e1175bSopenharmony_ci */ 7a8e1175bSopenharmony_ci 8a8e1175bSopenharmony_ci/* 9a8e1175bSopenharmony_ci * The following sources were referenced in the design of this Multi-precision 10a8e1175bSopenharmony_ci * Integer library: 11a8e1175bSopenharmony_ci * 12a8e1175bSopenharmony_ci * [1] Handbook of Applied Cryptography - 1997 13a8e1175bSopenharmony_ci * Menezes, van Oorschot and Vanstone 14a8e1175bSopenharmony_ci * 15a8e1175bSopenharmony_ci * [2] Multi-Precision Math 16a8e1175bSopenharmony_ci * Tom St Denis 17a8e1175bSopenharmony_ci * https://github.com/libtom/libtommath/blob/develop/tommath.pdf 18a8e1175bSopenharmony_ci * 19a8e1175bSopenharmony_ci * [3] GNU Multi-Precision Arithmetic Library 20a8e1175bSopenharmony_ci * https://gmplib.org/manual/index.html 21a8e1175bSopenharmony_ci * 22a8e1175bSopenharmony_ci */ 23a8e1175bSopenharmony_ci 24a8e1175bSopenharmony_ci#include "common.h" 25a8e1175bSopenharmony_ci 26a8e1175bSopenharmony_ci#if defined(MBEDTLS_BIGNUM_C) 27a8e1175bSopenharmony_ci 28a8e1175bSopenharmony_ci#include "mbedtls/bignum.h" 29a8e1175bSopenharmony_ci#include "bignum_core.h" 30a8e1175bSopenharmony_ci#include "bn_mul.h" 31a8e1175bSopenharmony_ci#include "mbedtls/platform_util.h" 32a8e1175bSopenharmony_ci#include "mbedtls/error.h" 33a8e1175bSopenharmony_ci#include "constant_time_internal.h" 34a8e1175bSopenharmony_ci 35a8e1175bSopenharmony_ci#include <limits.h> 36a8e1175bSopenharmony_ci#include <string.h> 37a8e1175bSopenharmony_ci 38a8e1175bSopenharmony_ci#include "mbedtls/platform.h" 39a8e1175bSopenharmony_ci 40a8e1175bSopenharmony_ci 41a8e1175bSopenharmony_ci 42a8e1175bSopenharmony_ci/* 43a8e1175bSopenharmony_ci * Conditionally select an MPI sign in constant time. 44a8e1175bSopenharmony_ci * (MPI sign is the field s in mbedtls_mpi. It is unsigned short and only 1 and -1 are valid 45a8e1175bSopenharmony_ci * values.) 46a8e1175bSopenharmony_ci */ 47a8e1175bSopenharmony_cistatic inline signed short mbedtls_ct_mpi_sign_if(mbedtls_ct_condition_t cond, 48a8e1175bSopenharmony_ci signed short sign1, signed short sign2) 49a8e1175bSopenharmony_ci{ 50a8e1175bSopenharmony_ci return (signed short) mbedtls_ct_uint_if(cond, sign1 + 1, sign2 + 1) - 1; 51a8e1175bSopenharmony_ci} 52a8e1175bSopenharmony_ci 53a8e1175bSopenharmony_ci/* 54a8e1175bSopenharmony_ci * Compare signed values in constant time 55a8e1175bSopenharmony_ci */ 56a8e1175bSopenharmony_ciint mbedtls_mpi_lt_mpi_ct(const mbedtls_mpi *X, 57a8e1175bSopenharmony_ci const mbedtls_mpi *Y, 58a8e1175bSopenharmony_ci unsigned *ret) 59a8e1175bSopenharmony_ci{ 60a8e1175bSopenharmony_ci mbedtls_ct_condition_t different_sign, X_is_negative, Y_is_negative, result; 61a8e1175bSopenharmony_ci 62a8e1175bSopenharmony_ci if (X->n != Y->n) { 63a8e1175bSopenharmony_ci return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 64a8e1175bSopenharmony_ci } 65a8e1175bSopenharmony_ci 66a8e1175bSopenharmony_ci /* 67a8e1175bSopenharmony_ci * Set N_is_negative to MBEDTLS_CT_FALSE if N >= 0, MBEDTLS_CT_TRUE if N < 0. 68a8e1175bSopenharmony_ci * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0. 69a8e1175bSopenharmony_ci */ 70a8e1175bSopenharmony_ci X_is_negative = mbedtls_ct_bool((X->s & 2) >> 1); 71a8e1175bSopenharmony_ci Y_is_negative = mbedtls_ct_bool((Y->s & 2) >> 1); 72a8e1175bSopenharmony_ci 73a8e1175bSopenharmony_ci /* 74a8e1175bSopenharmony_ci * If the signs are different, then the positive operand is the bigger. 75a8e1175bSopenharmony_ci * That is if X is negative (X_is_negative == 1), then X < Y is true and it 76a8e1175bSopenharmony_ci * is false if X is positive (X_is_negative == 0). 77a8e1175bSopenharmony_ci */ 78a8e1175bSopenharmony_ci different_sign = mbedtls_ct_bool_ne(X_is_negative, Y_is_negative); // true if different sign 79a8e1175bSopenharmony_ci result = mbedtls_ct_bool_and(different_sign, X_is_negative); 80a8e1175bSopenharmony_ci 81a8e1175bSopenharmony_ci /* 82a8e1175bSopenharmony_ci * Assuming signs are the same, compare X and Y. We switch the comparison 83a8e1175bSopenharmony_ci * order if they are negative so that we get the right result, regardles of 84a8e1175bSopenharmony_ci * sign. 85a8e1175bSopenharmony_ci */ 86a8e1175bSopenharmony_ci 87a8e1175bSopenharmony_ci /* This array is used to conditionally swap the pointers in const time */ 88a8e1175bSopenharmony_ci void * const p[2] = { X->p, Y->p }; 89a8e1175bSopenharmony_ci size_t i = mbedtls_ct_size_if_else_0(X_is_negative, 1); 90a8e1175bSopenharmony_ci mbedtls_ct_condition_t lt = mbedtls_mpi_core_lt_ct(p[i], p[i ^ 1], X->n); 91a8e1175bSopenharmony_ci 92a8e1175bSopenharmony_ci /* 93a8e1175bSopenharmony_ci * Store in result iff the signs are the same (i.e., iff different_sign == false). If 94a8e1175bSopenharmony_ci * the signs differ, result has already been set, so we don't change it. 95a8e1175bSopenharmony_ci */ 96a8e1175bSopenharmony_ci result = mbedtls_ct_bool_or(result, 97a8e1175bSopenharmony_ci mbedtls_ct_bool_and(mbedtls_ct_bool_not(different_sign), lt)); 98a8e1175bSopenharmony_ci 99a8e1175bSopenharmony_ci *ret = mbedtls_ct_uint_if_else_0(result, 1); 100a8e1175bSopenharmony_ci 101a8e1175bSopenharmony_ci return 0; 102a8e1175bSopenharmony_ci} 103a8e1175bSopenharmony_ci 104a8e1175bSopenharmony_ci/* 105a8e1175bSopenharmony_ci * Conditionally assign X = Y, without leaking information 106a8e1175bSopenharmony_ci * about whether the assignment was made or not. 107a8e1175bSopenharmony_ci * (Leaking information about the respective sizes of X and Y is ok however.) 108a8e1175bSopenharmony_ci */ 109a8e1175bSopenharmony_ci#if defined(_MSC_VER) && defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) && \ 110a8e1175bSopenharmony_ci (_MSC_FULL_VER < 193131103) 111a8e1175bSopenharmony_ci/* 112a8e1175bSopenharmony_ci * MSVC miscompiles this function if it's inlined prior to Visual Studio 2022 version 17.1. See: 113a8e1175bSopenharmony_ci * https://developercommunity.visualstudio.com/t/c-compiler-miscompiles-part-of-mbedtls-library-on/1646989 114a8e1175bSopenharmony_ci */ 115a8e1175bSopenharmony_ci__declspec(noinline) 116a8e1175bSopenharmony_ci#endif 117a8e1175bSopenharmony_ciint mbedtls_mpi_safe_cond_assign(mbedtls_mpi *X, 118a8e1175bSopenharmony_ci const mbedtls_mpi *Y, 119a8e1175bSopenharmony_ci unsigned char assign) 120a8e1175bSopenharmony_ci{ 121a8e1175bSopenharmony_ci int ret = 0; 122a8e1175bSopenharmony_ci 123a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n)); 124a8e1175bSopenharmony_ci 125a8e1175bSopenharmony_ci { 126a8e1175bSopenharmony_ci mbedtls_ct_condition_t do_assign = mbedtls_ct_bool(assign); 127a8e1175bSopenharmony_ci 128a8e1175bSopenharmony_ci X->s = mbedtls_ct_mpi_sign_if(do_assign, Y->s, X->s); 129a8e1175bSopenharmony_ci 130a8e1175bSopenharmony_ci mbedtls_mpi_core_cond_assign(X->p, Y->p, Y->n, do_assign); 131a8e1175bSopenharmony_ci 132a8e1175bSopenharmony_ci mbedtls_ct_condition_t do_not_assign = mbedtls_ct_bool_not(do_assign); 133a8e1175bSopenharmony_ci for (size_t i = Y->n; i < X->n; i++) { 134a8e1175bSopenharmony_ci X->p[i] = mbedtls_ct_mpi_uint_if_else_0(do_not_assign, X->p[i]); 135a8e1175bSopenharmony_ci } 136a8e1175bSopenharmony_ci } 137a8e1175bSopenharmony_ci 138a8e1175bSopenharmony_cicleanup: 139a8e1175bSopenharmony_ci return ret; 140a8e1175bSopenharmony_ci} 141a8e1175bSopenharmony_ci 142a8e1175bSopenharmony_ci/* 143a8e1175bSopenharmony_ci * Conditionally swap X and Y, without leaking information 144a8e1175bSopenharmony_ci * about whether the swap was made or not. 145a8e1175bSopenharmony_ci * Here it is not ok to simply swap the pointers, which would lead to 146a8e1175bSopenharmony_ci * different memory access patterns when X and Y are used afterwards. 147a8e1175bSopenharmony_ci */ 148a8e1175bSopenharmony_ciint mbedtls_mpi_safe_cond_swap(mbedtls_mpi *X, 149a8e1175bSopenharmony_ci mbedtls_mpi *Y, 150a8e1175bSopenharmony_ci unsigned char swap) 151a8e1175bSopenharmony_ci{ 152a8e1175bSopenharmony_ci int ret = 0; 153a8e1175bSopenharmony_ci int s; 154a8e1175bSopenharmony_ci 155a8e1175bSopenharmony_ci if (X == Y) { 156a8e1175bSopenharmony_ci return 0; 157a8e1175bSopenharmony_ci } 158a8e1175bSopenharmony_ci 159a8e1175bSopenharmony_ci mbedtls_ct_condition_t do_swap = mbedtls_ct_bool(swap); 160a8e1175bSopenharmony_ci 161a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n)); 162a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_grow(Y, X->n)); 163a8e1175bSopenharmony_ci 164a8e1175bSopenharmony_ci s = X->s; 165a8e1175bSopenharmony_ci X->s = mbedtls_ct_mpi_sign_if(do_swap, Y->s, X->s); 166a8e1175bSopenharmony_ci Y->s = mbedtls_ct_mpi_sign_if(do_swap, s, Y->s); 167a8e1175bSopenharmony_ci 168a8e1175bSopenharmony_ci mbedtls_mpi_core_cond_swap(X->p, Y->p, X->n, do_swap); 169a8e1175bSopenharmony_ci 170a8e1175bSopenharmony_cicleanup: 171a8e1175bSopenharmony_ci return ret; 172a8e1175bSopenharmony_ci} 173a8e1175bSopenharmony_ci 174a8e1175bSopenharmony_ci/* Implementation that should never be optimized out by the compiler */ 175a8e1175bSopenharmony_ci#define mbedtls_mpi_zeroize_and_free(v, n) mbedtls_zeroize_and_free(v, ciL * (n)) 176a8e1175bSopenharmony_ci 177a8e1175bSopenharmony_ci/* 178a8e1175bSopenharmony_ci * Initialize one MPI 179a8e1175bSopenharmony_ci */ 180a8e1175bSopenharmony_civoid mbedtls_mpi_init(mbedtls_mpi *X) 181a8e1175bSopenharmony_ci{ 182a8e1175bSopenharmony_ci X->s = 1; 183a8e1175bSopenharmony_ci X->n = 0; 184a8e1175bSopenharmony_ci X->p = NULL; 185a8e1175bSopenharmony_ci} 186a8e1175bSopenharmony_ci 187a8e1175bSopenharmony_ci/* 188a8e1175bSopenharmony_ci * Unallocate one MPI 189a8e1175bSopenharmony_ci */ 190a8e1175bSopenharmony_civoid mbedtls_mpi_free(mbedtls_mpi *X) 191a8e1175bSopenharmony_ci{ 192a8e1175bSopenharmony_ci if (X == NULL) { 193a8e1175bSopenharmony_ci return; 194a8e1175bSopenharmony_ci } 195a8e1175bSopenharmony_ci 196a8e1175bSopenharmony_ci if (X->p != NULL) { 197a8e1175bSopenharmony_ci mbedtls_mpi_zeroize_and_free(X->p, X->n); 198a8e1175bSopenharmony_ci } 199a8e1175bSopenharmony_ci 200a8e1175bSopenharmony_ci X->s = 1; 201a8e1175bSopenharmony_ci X->n = 0; 202a8e1175bSopenharmony_ci X->p = NULL; 203a8e1175bSopenharmony_ci} 204a8e1175bSopenharmony_ci 205a8e1175bSopenharmony_ci/* 206a8e1175bSopenharmony_ci * Enlarge to the specified number of limbs 207a8e1175bSopenharmony_ci */ 208a8e1175bSopenharmony_ciint mbedtls_mpi_grow(mbedtls_mpi *X, size_t nblimbs) 209a8e1175bSopenharmony_ci{ 210a8e1175bSopenharmony_ci mbedtls_mpi_uint *p; 211a8e1175bSopenharmony_ci 212a8e1175bSopenharmony_ci if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) { 213a8e1175bSopenharmony_ci return MBEDTLS_ERR_MPI_ALLOC_FAILED; 214a8e1175bSopenharmony_ci } 215a8e1175bSopenharmony_ci 216a8e1175bSopenharmony_ci if (X->n < nblimbs) { 217a8e1175bSopenharmony_ci if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(nblimbs, ciL)) == NULL) { 218a8e1175bSopenharmony_ci return MBEDTLS_ERR_MPI_ALLOC_FAILED; 219a8e1175bSopenharmony_ci } 220a8e1175bSopenharmony_ci 221a8e1175bSopenharmony_ci if (X->p != NULL) { 222a8e1175bSopenharmony_ci memcpy(p, X->p, X->n * ciL); 223a8e1175bSopenharmony_ci mbedtls_mpi_zeroize_and_free(X->p, X->n); 224a8e1175bSopenharmony_ci } 225a8e1175bSopenharmony_ci 226a8e1175bSopenharmony_ci /* nblimbs fits in n because we ensure that MBEDTLS_MPI_MAX_LIMBS 227a8e1175bSopenharmony_ci * fits, and we've checked that nblimbs <= MBEDTLS_MPI_MAX_LIMBS. */ 228a8e1175bSopenharmony_ci X->n = (unsigned short) nblimbs; 229a8e1175bSopenharmony_ci X->p = p; 230a8e1175bSopenharmony_ci } 231a8e1175bSopenharmony_ci 232a8e1175bSopenharmony_ci return 0; 233a8e1175bSopenharmony_ci} 234a8e1175bSopenharmony_ci 235a8e1175bSopenharmony_ci/* 236a8e1175bSopenharmony_ci * Resize down as much as possible, 237a8e1175bSopenharmony_ci * while keeping at least the specified number of limbs 238a8e1175bSopenharmony_ci */ 239a8e1175bSopenharmony_ciint mbedtls_mpi_shrink(mbedtls_mpi *X, size_t nblimbs) 240a8e1175bSopenharmony_ci{ 241a8e1175bSopenharmony_ci mbedtls_mpi_uint *p; 242a8e1175bSopenharmony_ci size_t i; 243a8e1175bSopenharmony_ci 244a8e1175bSopenharmony_ci if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) { 245a8e1175bSopenharmony_ci return MBEDTLS_ERR_MPI_ALLOC_FAILED; 246a8e1175bSopenharmony_ci } 247a8e1175bSopenharmony_ci 248a8e1175bSopenharmony_ci /* Actually resize up if there are currently fewer than nblimbs limbs. */ 249a8e1175bSopenharmony_ci if (X->n <= nblimbs) { 250a8e1175bSopenharmony_ci return mbedtls_mpi_grow(X, nblimbs); 251a8e1175bSopenharmony_ci } 252a8e1175bSopenharmony_ci /* After this point, then X->n > nblimbs and in particular X->n > 0. */ 253a8e1175bSopenharmony_ci 254a8e1175bSopenharmony_ci for (i = X->n - 1; i > 0; i--) { 255a8e1175bSopenharmony_ci if (X->p[i] != 0) { 256a8e1175bSopenharmony_ci break; 257a8e1175bSopenharmony_ci } 258a8e1175bSopenharmony_ci } 259a8e1175bSopenharmony_ci i++; 260a8e1175bSopenharmony_ci 261a8e1175bSopenharmony_ci if (i < nblimbs) { 262a8e1175bSopenharmony_ci i = nblimbs; 263a8e1175bSopenharmony_ci } 264a8e1175bSopenharmony_ci 265a8e1175bSopenharmony_ci if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(i, ciL)) == NULL) { 266a8e1175bSopenharmony_ci return MBEDTLS_ERR_MPI_ALLOC_FAILED; 267a8e1175bSopenharmony_ci } 268a8e1175bSopenharmony_ci 269a8e1175bSopenharmony_ci if (X->p != NULL) { 270a8e1175bSopenharmony_ci memcpy(p, X->p, i * ciL); 271a8e1175bSopenharmony_ci mbedtls_mpi_zeroize_and_free(X->p, X->n); 272a8e1175bSopenharmony_ci } 273a8e1175bSopenharmony_ci 274a8e1175bSopenharmony_ci /* i fits in n because we ensure that MBEDTLS_MPI_MAX_LIMBS 275a8e1175bSopenharmony_ci * fits, and we've checked that i <= nblimbs <= MBEDTLS_MPI_MAX_LIMBS. */ 276a8e1175bSopenharmony_ci X->n = (unsigned short) i; 277a8e1175bSopenharmony_ci X->p = p; 278a8e1175bSopenharmony_ci 279a8e1175bSopenharmony_ci return 0; 280a8e1175bSopenharmony_ci} 281a8e1175bSopenharmony_ci 282a8e1175bSopenharmony_ci/* Resize X to have exactly n limbs and set it to 0. */ 283a8e1175bSopenharmony_cistatic int mbedtls_mpi_resize_clear(mbedtls_mpi *X, size_t limbs) 284a8e1175bSopenharmony_ci{ 285a8e1175bSopenharmony_ci if (limbs == 0) { 286a8e1175bSopenharmony_ci mbedtls_mpi_free(X); 287a8e1175bSopenharmony_ci return 0; 288a8e1175bSopenharmony_ci } else if (X->n == limbs) { 289a8e1175bSopenharmony_ci memset(X->p, 0, limbs * ciL); 290a8e1175bSopenharmony_ci X->s = 1; 291a8e1175bSopenharmony_ci return 0; 292a8e1175bSopenharmony_ci } else { 293a8e1175bSopenharmony_ci mbedtls_mpi_free(X); 294a8e1175bSopenharmony_ci return mbedtls_mpi_grow(X, limbs); 295a8e1175bSopenharmony_ci } 296a8e1175bSopenharmony_ci} 297a8e1175bSopenharmony_ci 298a8e1175bSopenharmony_ci/* 299a8e1175bSopenharmony_ci * Copy the contents of Y into X. 300a8e1175bSopenharmony_ci * 301a8e1175bSopenharmony_ci * This function is not constant-time. Leading zeros in Y may be removed. 302a8e1175bSopenharmony_ci * 303a8e1175bSopenharmony_ci * Ensure that X does not shrink. This is not guaranteed by the public API, 304a8e1175bSopenharmony_ci * but some code in the bignum module might still rely on this property. 305a8e1175bSopenharmony_ci */ 306a8e1175bSopenharmony_ciint mbedtls_mpi_copy(mbedtls_mpi *X, const mbedtls_mpi *Y) 307a8e1175bSopenharmony_ci{ 308a8e1175bSopenharmony_ci int ret = 0; 309a8e1175bSopenharmony_ci size_t i; 310a8e1175bSopenharmony_ci 311a8e1175bSopenharmony_ci if (X == Y) { 312a8e1175bSopenharmony_ci return 0; 313a8e1175bSopenharmony_ci } 314a8e1175bSopenharmony_ci 315a8e1175bSopenharmony_ci if (Y->n == 0) { 316a8e1175bSopenharmony_ci if (X->n != 0) { 317a8e1175bSopenharmony_ci X->s = 1; 318a8e1175bSopenharmony_ci memset(X->p, 0, X->n * ciL); 319a8e1175bSopenharmony_ci } 320a8e1175bSopenharmony_ci return 0; 321a8e1175bSopenharmony_ci } 322a8e1175bSopenharmony_ci 323a8e1175bSopenharmony_ci for (i = Y->n - 1; i > 0; i--) { 324a8e1175bSopenharmony_ci if (Y->p[i] != 0) { 325a8e1175bSopenharmony_ci break; 326a8e1175bSopenharmony_ci } 327a8e1175bSopenharmony_ci } 328a8e1175bSopenharmony_ci i++; 329a8e1175bSopenharmony_ci 330a8e1175bSopenharmony_ci X->s = Y->s; 331a8e1175bSopenharmony_ci 332a8e1175bSopenharmony_ci if (X->n < i) { 333a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i)); 334a8e1175bSopenharmony_ci } else { 335a8e1175bSopenharmony_ci memset(X->p + i, 0, (X->n - i) * ciL); 336a8e1175bSopenharmony_ci } 337a8e1175bSopenharmony_ci 338a8e1175bSopenharmony_ci memcpy(X->p, Y->p, i * ciL); 339a8e1175bSopenharmony_ci 340a8e1175bSopenharmony_cicleanup: 341a8e1175bSopenharmony_ci 342a8e1175bSopenharmony_ci return ret; 343a8e1175bSopenharmony_ci} 344a8e1175bSopenharmony_ci 345a8e1175bSopenharmony_ci/* 346a8e1175bSopenharmony_ci * Swap the contents of X and Y 347a8e1175bSopenharmony_ci */ 348a8e1175bSopenharmony_civoid mbedtls_mpi_swap(mbedtls_mpi *X, mbedtls_mpi *Y) 349a8e1175bSopenharmony_ci{ 350a8e1175bSopenharmony_ci mbedtls_mpi T; 351a8e1175bSopenharmony_ci 352a8e1175bSopenharmony_ci memcpy(&T, X, sizeof(mbedtls_mpi)); 353a8e1175bSopenharmony_ci memcpy(X, Y, sizeof(mbedtls_mpi)); 354a8e1175bSopenharmony_ci memcpy(Y, &T, sizeof(mbedtls_mpi)); 355a8e1175bSopenharmony_ci} 356a8e1175bSopenharmony_ci 357a8e1175bSopenharmony_cistatic inline mbedtls_mpi_uint mpi_sint_abs(mbedtls_mpi_sint z) 358a8e1175bSopenharmony_ci{ 359a8e1175bSopenharmony_ci if (z >= 0) { 360a8e1175bSopenharmony_ci return z; 361a8e1175bSopenharmony_ci } 362a8e1175bSopenharmony_ci /* Take care to handle the most negative value (-2^(biL-1)) correctly. 363a8e1175bSopenharmony_ci * A naive -z would have undefined behavior. 364a8e1175bSopenharmony_ci * Write this in a way that makes popular compilers happy (GCC, Clang, 365a8e1175bSopenharmony_ci * MSVC). */ 366a8e1175bSopenharmony_ci return (mbedtls_mpi_uint) 0 - (mbedtls_mpi_uint) z; 367a8e1175bSopenharmony_ci} 368a8e1175bSopenharmony_ci 369a8e1175bSopenharmony_ci/* Convert x to a sign, i.e. to 1, if x is positive, or -1, if x is negative. 370a8e1175bSopenharmony_ci * This looks awkward but generates smaller code than (x < 0 ? -1 : 1) */ 371a8e1175bSopenharmony_ci#define TO_SIGN(x) ((mbedtls_mpi_sint) (((mbedtls_mpi_uint) x) >> (biL - 1)) * -2 + 1) 372a8e1175bSopenharmony_ci 373a8e1175bSopenharmony_ci/* 374a8e1175bSopenharmony_ci * Set value from integer 375a8e1175bSopenharmony_ci */ 376a8e1175bSopenharmony_ciint mbedtls_mpi_lset(mbedtls_mpi *X, mbedtls_mpi_sint z) 377a8e1175bSopenharmony_ci{ 378a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 379a8e1175bSopenharmony_ci 380a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, 1)); 381a8e1175bSopenharmony_ci memset(X->p, 0, X->n * ciL); 382a8e1175bSopenharmony_ci 383a8e1175bSopenharmony_ci X->p[0] = mpi_sint_abs(z); 384a8e1175bSopenharmony_ci X->s = TO_SIGN(z); 385a8e1175bSopenharmony_ci 386a8e1175bSopenharmony_cicleanup: 387a8e1175bSopenharmony_ci 388a8e1175bSopenharmony_ci return ret; 389a8e1175bSopenharmony_ci} 390a8e1175bSopenharmony_ci 391a8e1175bSopenharmony_ci/* 392a8e1175bSopenharmony_ci * Get a specific bit 393a8e1175bSopenharmony_ci */ 394a8e1175bSopenharmony_ciint mbedtls_mpi_get_bit(const mbedtls_mpi *X, size_t pos) 395a8e1175bSopenharmony_ci{ 396a8e1175bSopenharmony_ci if (X->n * biL <= pos) { 397a8e1175bSopenharmony_ci return 0; 398a8e1175bSopenharmony_ci } 399a8e1175bSopenharmony_ci 400a8e1175bSopenharmony_ci return (X->p[pos / biL] >> (pos % biL)) & 0x01; 401a8e1175bSopenharmony_ci} 402a8e1175bSopenharmony_ci 403a8e1175bSopenharmony_ci/* 404a8e1175bSopenharmony_ci * Set a bit to a specific value of 0 or 1 405a8e1175bSopenharmony_ci */ 406a8e1175bSopenharmony_ciint mbedtls_mpi_set_bit(mbedtls_mpi *X, size_t pos, unsigned char val) 407a8e1175bSopenharmony_ci{ 408a8e1175bSopenharmony_ci int ret = 0; 409a8e1175bSopenharmony_ci size_t off = pos / biL; 410a8e1175bSopenharmony_ci size_t idx = pos % biL; 411a8e1175bSopenharmony_ci 412a8e1175bSopenharmony_ci if (val != 0 && val != 1) { 413a8e1175bSopenharmony_ci return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 414a8e1175bSopenharmony_ci } 415a8e1175bSopenharmony_ci 416a8e1175bSopenharmony_ci if (X->n * biL <= pos) { 417a8e1175bSopenharmony_ci if (val == 0) { 418a8e1175bSopenharmony_ci return 0; 419a8e1175bSopenharmony_ci } 420a8e1175bSopenharmony_ci 421a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, off + 1)); 422a8e1175bSopenharmony_ci } 423a8e1175bSopenharmony_ci 424a8e1175bSopenharmony_ci X->p[off] &= ~((mbedtls_mpi_uint) 0x01 << idx); 425a8e1175bSopenharmony_ci X->p[off] |= (mbedtls_mpi_uint) val << idx; 426a8e1175bSopenharmony_ci 427a8e1175bSopenharmony_cicleanup: 428a8e1175bSopenharmony_ci 429a8e1175bSopenharmony_ci return ret; 430a8e1175bSopenharmony_ci} 431a8e1175bSopenharmony_ci 432a8e1175bSopenharmony_ci/* 433a8e1175bSopenharmony_ci * Return the number of less significant zero-bits 434a8e1175bSopenharmony_ci */ 435a8e1175bSopenharmony_cisize_t mbedtls_mpi_lsb(const mbedtls_mpi *X) 436a8e1175bSopenharmony_ci{ 437a8e1175bSopenharmony_ci size_t i; 438a8e1175bSopenharmony_ci 439a8e1175bSopenharmony_ci#if defined(__has_builtin) 440a8e1175bSopenharmony_ci#if (MBEDTLS_MPI_UINT_MAX == UINT_MAX) && __has_builtin(__builtin_ctz) 441a8e1175bSopenharmony_ci #define mbedtls_mpi_uint_ctz __builtin_ctz 442a8e1175bSopenharmony_ci#elif (MBEDTLS_MPI_UINT_MAX == ULONG_MAX) && __has_builtin(__builtin_ctzl) 443a8e1175bSopenharmony_ci #define mbedtls_mpi_uint_ctz __builtin_ctzl 444a8e1175bSopenharmony_ci#elif (MBEDTLS_MPI_UINT_MAX == ULLONG_MAX) && __has_builtin(__builtin_ctzll) 445a8e1175bSopenharmony_ci #define mbedtls_mpi_uint_ctz __builtin_ctzll 446a8e1175bSopenharmony_ci#endif 447a8e1175bSopenharmony_ci#endif 448a8e1175bSopenharmony_ci 449a8e1175bSopenharmony_ci#if defined(mbedtls_mpi_uint_ctz) 450a8e1175bSopenharmony_ci for (i = 0; i < X->n; i++) { 451a8e1175bSopenharmony_ci if (X->p[i] != 0) { 452a8e1175bSopenharmony_ci return i * biL + mbedtls_mpi_uint_ctz(X->p[i]); 453a8e1175bSopenharmony_ci } 454a8e1175bSopenharmony_ci } 455a8e1175bSopenharmony_ci#else 456a8e1175bSopenharmony_ci size_t count = 0; 457a8e1175bSopenharmony_ci for (i = 0; i < X->n; i++) { 458a8e1175bSopenharmony_ci for (size_t j = 0; j < biL; j++, count++) { 459a8e1175bSopenharmony_ci if (((X->p[i] >> j) & 1) != 0) { 460a8e1175bSopenharmony_ci return count; 461a8e1175bSopenharmony_ci } 462a8e1175bSopenharmony_ci } 463a8e1175bSopenharmony_ci } 464a8e1175bSopenharmony_ci#endif 465a8e1175bSopenharmony_ci 466a8e1175bSopenharmony_ci return 0; 467a8e1175bSopenharmony_ci} 468a8e1175bSopenharmony_ci 469a8e1175bSopenharmony_ci/* 470a8e1175bSopenharmony_ci * Return the number of bits 471a8e1175bSopenharmony_ci */ 472a8e1175bSopenharmony_cisize_t mbedtls_mpi_bitlen(const mbedtls_mpi *X) 473a8e1175bSopenharmony_ci{ 474a8e1175bSopenharmony_ci return mbedtls_mpi_core_bitlen(X->p, X->n); 475a8e1175bSopenharmony_ci} 476a8e1175bSopenharmony_ci 477a8e1175bSopenharmony_ci/* 478a8e1175bSopenharmony_ci * Return the total size in bytes 479a8e1175bSopenharmony_ci */ 480a8e1175bSopenharmony_cisize_t mbedtls_mpi_size(const mbedtls_mpi *X) 481a8e1175bSopenharmony_ci{ 482a8e1175bSopenharmony_ci return (mbedtls_mpi_bitlen(X) + 7) >> 3; 483a8e1175bSopenharmony_ci} 484a8e1175bSopenharmony_ci 485a8e1175bSopenharmony_ci/* 486a8e1175bSopenharmony_ci * Convert an ASCII character to digit value 487a8e1175bSopenharmony_ci */ 488a8e1175bSopenharmony_cistatic int mpi_get_digit(mbedtls_mpi_uint *d, int radix, char c) 489a8e1175bSopenharmony_ci{ 490a8e1175bSopenharmony_ci *d = 255; 491a8e1175bSopenharmony_ci 492a8e1175bSopenharmony_ci if (c >= 0x30 && c <= 0x39) { 493a8e1175bSopenharmony_ci *d = c - 0x30; 494a8e1175bSopenharmony_ci } 495a8e1175bSopenharmony_ci if (c >= 0x41 && c <= 0x46) { 496a8e1175bSopenharmony_ci *d = c - 0x37; 497a8e1175bSopenharmony_ci } 498a8e1175bSopenharmony_ci if (c >= 0x61 && c <= 0x66) { 499a8e1175bSopenharmony_ci *d = c - 0x57; 500a8e1175bSopenharmony_ci } 501a8e1175bSopenharmony_ci 502a8e1175bSopenharmony_ci if (*d >= (mbedtls_mpi_uint) radix) { 503a8e1175bSopenharmony_ci return MBEDTLS_ERR_MPI_INVALID_CHARACTER; 504a8e1175bSopenharmony_ci } 505a8e1175bSopenharmony_ci 506a8e1175bSopenharmony_ci return 0; 507a8e1175bSopenharmony_ci} 508a8e1175bSopenharmony_ci 509a8e1175bSopenharmony_ci/* 510a8e1175bSopenharmony_ci * Import from an ASCII string 511a8e1175bSopenharmony_ci */ 512a8e1175bSopenharmony_ciint mbedtls_mpi_read_string(mbedtls_mpi *X, int radix, const char *s) 513a8e1175bSopenharmony_ci{ 514a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 515a8e1175bSopenharmony_ci size_t i, j, slen, n; 516a8e1175bSopenharmony_ci int sign = 1; 517a8e1175bSopenharmony_ci mbedtls_mpi_uint d; 518a8e1175bSopenharmony_ci mbedtls_mpi T; 519a8e1175bSopenharmony_ci 520a8e1175bSopenharmony_ci if (radix < 2 || radix > 16) { 521a8e1175bSopenharmony_ci return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 522a8e1175bSopenharmony_ci } 523a8e1175bSopenharmony_ci 524a8e1175bSopenharmony_ci mbedtls_mpi_init(&T); 525a8e1175bSopenharmony_ci 526a8e1175bSopenharmony_ci if (s[0] == 0) { 527a8e1175bSopenharmony_ci mbedtls_mpi_free(X); 528a8e1175bSopenharmony_ci return 0; 529a8e1175bSopenharmony_ci } 530a8e1175bSopenharmony_ci 531a8e1175bSopenharmony_ci if (s[0] == '-') { 532a8e1175bSopenharmony_ci ++s; 533a8e1175bSopenharmony_ci sign = -1; 534a8e1175bSopenharmony_ci } 535a8e1175bSopenharmony_ci 536a8e1175bSopenharmony_ci slen = strlen(s); 537a8e1175bSopenharmony_ci 538a8e1175bSopenharmony_ci if (radix == 16) { 539a8e1175bSopenharmony_ci if (slen > SIZE_MAX >> 2) { 540a8e1175bSopenharmony_ci return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 541a8e1175bSopenharmony_ci } 542a8e1175bSopenharmony_ci 543a8e1175bSopenharmony_ci n = BITS_TO_LIMBS(slen << 2); 544a8e1175bSopenharmony_ci 545a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n)); 546a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0)); 547a8e1175bSopenharmony_ci 548a8e1175bSopenharmony_ci for (i = slen, j = 0; i > 0; i--, j++) { 549a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i - 1])); 550a8e1175bSopenharmony_ci X->p[j / (2 * ciL)] |= d << ((j % (2 * ciL)) << 2); 551a8e1175bSopenharmony_ci } 552a8e1175bSopenharmony_ci } else { 553a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0)); 554a8e1175bSopenharmony_ci 555a8e1175bSopenharmony_ci for (i = 0; i < slen; i++) { 556a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i])); 557a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T, X, radix)); 558a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, &T, d)); 559a8e1175bSopenharmony_ci } 560a8e1175bSopenharmony_ci } 561a8e1175bSopenharmony_ci 562a8e1175bSopenharmony_ci if (sign < 0 && mbedtls_mpi_bitlen(X) != 0) { 563a8e1175bSopenharmony_ci X->s = -1; 564a8e1175bSopenharmony_ci } 565a8e1175bSopenharmony_ci 566a8e1175bSopenharmony_cicleanup: 567a8e1175bSopenharmony_ci 568a8e1175bSopenharmony_ci mbedtls_mpi_free(&T); 569a8e1175bSopenharmony_ci 570a8e1175bSopenharmony_ci return ret; 571a8e1175bSopenharmony_ci} 572a8e1175bSopenharmony_ci 573a8e1175bSopenharmony_ci/* 574a8e1175bSopenharmony_ci * Helper to write the digits high-order first. 575a8e1175bSopenharmony_ci */ 576a8e1175bSopenharmony_cistatic int mpi_write_hlp(mbedtls_mpi *X, int radix, 577a8e1175bSopenharmony_ci char **p, const size_t buflen) 578a8e1175bSopenharmony_ci{ 579a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 580a8e1175bSopenharmony_ci mbedtls_mpi_uint r; 581a8e1175bSopenharmony_ci size_t length = 0; 582a8e1175bSopenharmony_ci char *p_end = *p + buflen; 583a8e1175bSopenharmony_ci 584a8e1175bSopenharmony_ci do { 585a8e1175bSopenharmony_ci if (length >= buflen) { 586a8e1175bSopenharmony_ci return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL; 587a8e1175bSopenharmony_ci } 588a8e1175bSopenharmony_ci 589a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, radix)); 590a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_div_int(X, NULL, X, radix)); 591a8e1175bSopenharmony_ci /* 592a8e1175bSopenharmony_ci * Write the residue in the current position, as an ASCII character. 593a8e1175bSopenharmony_ci */ 594a8e1175bSopenharmony_ci if (r < 0xA) { 595a8e1175bSopenharmony_ci *(--p_end) = (char) ('0' + r); 596a8e1175bSopenharmony_ci } else { 597a8e1175bSopenharmony_ci *(--p_end) = (char) ('A' + (r - 0xA)); 598a8e1175bSopenharmony_ci } 599a8e1175bSopenharmony_ci 600a8e1175bSopenharmony_ci length++; 601a8e1175bSopenharmony_ci } while (mbedtls_mpi_cmp_int(X, 0) != 0); 602a8e1175bSopenharmony_ci 603a8e1175bSopenharmony_ci memmove(*p, p_end, length); 604a8e1175bSopenharmony_ci *p += length; 605a8e1175bSopenharmony_ci 606a8e1175bSopenharmony_cicleanup: 607a8e1175bSopenharmony_ci 608a8e1175bSopenharmony_ci return ret; 609a8e1175bSopenharmony_ci} 610a8e1175bSopenharmony_ci 611a8e1175bSopenharmony_ci/* 612a8e1175bSopenharmony_ci * Export into an ASCII string 613a8e1175bSopenharmony_ci */ 614a8e1175bSopenharmony_ciint mbedtls_mpi_write_string(const mbedtls_mpi *X, int radix, 615a8e1175bSopenharmony_ci char *buf, size_t buflen, size_t *olen) 616a8e1175bSopenharmony_ci{ 617a8e1175bSopenharmony_ci int ret = 0; 618a8e1175bSopenharmony_ci size_t n; 619a8e1175bSopenharmony_ci char *p; 620a8e1175bSopenharmony_ci mbedtls_mpi T; 621a8e1175bSopenharmony_ci 622a8e1175bSopenharmony_ci if (radix < 2 || radix > 16) { 623a8e1175bSopenharmony_ci return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 624a8e1175bSopenharmony_ci } 625a8e1175bSopenharmony_ci 626a8e1175bSopenharmony_ci n = mbedtls_mpi_bitlen(X); /* Number of bits necessary to present `n`. */ 627a8e1175bSopenharmony_ci if (radix >= 4) { 628a8e1175bSopenharmony_ci n >>= 1; /* Number of 4-adic digits necessary to present 629a8e1175bSopenharmony_ci * `n`. If radix > 4, this might be a strict 630a8e1175bSopenharmony_ci * overapproximation of the number of 631a8e1175bSopenharmony_ci * radix-adic digits needed to present `n`. */ 632a8e1175bSopenharmony_ci } 633a8e1175bSopenharmony_ci if (radix >= 16) { 634a8e1175bSopenharmony_ci n >>= 1; /* Number of hexadecimal digits necessary to 635a8e1175bSopenharmony_ci * present `n`. */ 636a8e1175bSopenharmony_ci 637a8e1175bSopenharmony_ci } 638a8e1175bSopenharmony_ci n += 1; /* Terminating null byte */ 639a8e1175bSopenharmony_ci n += 1; /* Compensate for the divisions above, which round down `n` 640a8e1175bSopenharmony_ci * in case it's not even. */ 641a8e1175bSopenharmony_ci n += 1; /* Potential '-'-sign. */ 642a8e1175bSopenharmony_ci n += (n & 1); /* Make n even to have enough space for hexadecimal writing, 643a8e1175bSopenharmony_ci * which always uses an even number of hex-digits. */ 644a8e1175bSopenharmony_ci 645a8e1175bSopenharmony_ci if (buflen < n) { 646a8e1175bSopenharmony_ci *olen = n; 647a8e1175bSopenharmony_ci return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL; 648a8e1175bSopenharmony_ci } 649a8e1175bSopenharmony_ci 650a8e1175bSopenharmony_ci p = buf; 651a8e1175bSopenharmony_ci mbedtls_mpi_init(&T); 652a8e1175bSopenharmony_ci 653a8e1175bSopenharmony_ci if (X->s == -1) { 654a8e1175bSopenharmony_ci *p++ = '-'; 655a8e1175bSopenharmony_ci buflen--; 656a8e1175bSopenharmony_ci } 657a8e1175bSopenharmony_ci 658a8e1175bSopenharmony_ci if (radix == 16) { 659a8e1175bSopenharmony_ci int c; 660a8e1175bSopenharmony_ci size_t i, j, k; 661a8e1175bSopenharmony_ci 662a8e1175bSopenharmony_ci for (i = X->n, k = 0; i > 0; i--) { 663a8e1175bSopenharmony_ci for (j = ciL; j > 0; j--) { 664a8e1175bSopenharmony_ci c = (X->p[i - 1] >> ((j - 1) << 3)) & 0xFF; 665a8e1175bSopenharmony_ci 666a8e1175bSopenharmony_ci if (c == 0 && k == 0 && (i + j) != 2) { 667a8e1175bSopenharmony_ci continue; 668a8e1175bSopenharmony_ci } 669a8e1175bSopenharmony_ci 670a8e1175bSopenharmony_ci *(p++) = "0123456789ABCDEF" [c / 16]; 671a8e1175bSopenharmony_ci *(p++) = "0123456789ABCDEF" [c % 16]; 672a8e1175bSopenharmony_ci k = 1; 673a8e1175bSopenharmony_ci } 674a8e1175bSopenharmony_ci } 675a8e1175bSopenharmony_ci } else { 676a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T, X)); 677a8e1175bSopenharmony_ci 678a8e1175bSopenharmony_ci if (T.s == -1) { 679a8e1175bSopenharmony_ci T.s = 1; 680a8e1175bSopenharmony_ci } 681a8e1175bSopenharmony_ci 682a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mpi_write_hlp(&T, radix, &p, buflen)); 683a8e1175bSopenharmony_ci } 684a8e1175bSopenharmony_ci 685a8e1175bSopenharmony_ci *p++ = '\0'; 686a8e1175bSopenharmony_ci *olen = (size_t) (p - buf); 687a8e1175bSopenharmony_ci 688a8e1175bSopenharmony_cicleanup: 689a8e1175bSopenharmony_ci 690a8e1175bSopenharmony_ci mbedtls_mpi_free(&T); 691a8e1175bSopenharmony_ci 692a8e1175bSopenharmony_ci return ret; 693a8e1175bSopenharmony_ci} 694a8e1175bSopenharmony_ci 695a8e1175bSopenharmony_ci#if defined(MBEDTLS_FS_IO) 696a8e1175bSopenharmony_ci/* 697a8e1175bSopenharmony_ci * Read X from an opened file 698a8e1175bSopenharmony_ci */ 699a8e1175bSopenharmony_ciint mbedtls_mpi_read_file(mbedtls_mpi *X, int radix, FILE *fin) 700a8e1175bSopenharmony_ci{ 701a8e1175bSopenharmony_ci mbedtls_mpi_uint d; 702a8e1175bSopenharmony_ci size_t slen; 703a8e1175bSopenharmony_ci char *p; 704a8e1175bSopenharmony_ci /* 705a8e1175bSopenharmony_ci * Buffer should have space for (short) label and decimal formatted MPI, 706a8e1175bSopenharmony_ci * newline characters and '\0' 707a8e1175bSopenharmony_ci */ 708a8e1175bSopenharmony_ci char s[MBEDTLS_MPI_RW_BUFFER_SIZE]; 709a8e1175bSopenharmony_ci 710a8e1175bSopenharmony_ci if (radix < 2 || radix > 16) { 711a8e1175bSopenharmony_ci return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 712a8e1175bSopenharmony_ci } 713a8e1175bSopenharmony_ci 714a8e1175bSopenharmony_ci memset(s, 0, sizeof(s)); 715a8e1175bSopenharmony_ci if (fgets(s, sizeof(s) - 1, fin) == NULL) { 716a8e1175bSopenharmony_ci return MBEDTLS_ERR_MPI_FILE_IO_ERROR; 717a8e1175bSopenharmony_ci } 718a8e1175bSopenharmony_ci 719a8e1175bSopenharmony_ci slen = strlen(s); 720a8e1175bSopenharmony_ci if (slen == sizeof(s) - 2) { 721a8e1175bSopenharmony_ci return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL; 722a8e1175bSopenharmony_ci } 723a8e1175bSopenharmony_ci 724a8e1175bSopenharmony_ci if (slen > 0 && s[slen - 1] == '\n') { 725a8e1175bSopenharmony_ci slen--; s[slen] = '\0'; 726a8e1175bSopenharmony_ci } 727a8e1175bSopenharmony_ci if (slen > 0 && s[slen - 1] == '\r') { 728a8e1175bSopenharmony_ci slen--; s[slen] = '\0'; 729a8e1175bSopenharmony_ci } 730a8e1175bSopenharmony_ci 731a8e1175bSopenharmony_ci p = s + slen; 732a8e1175bSopenharmony_ci while (p-- > s) { 733a8e1175bSopenharmony_ci if (mpi_get_digit(&d, radix, *p) != 0) { 734a8e1175bSopenharmony_ci break; 735a8e1175bSopenharmony_ci } 736a8e1175bSopenharmony_ci } 737a8e1175bSopenharmony_ci 738a8e1175bSopenharmony_ci return mbedtls_mpi_read_string(X, radix, p + 1); 739a8e1175bSopenharmony_ci} 740a8e1175bSopenharmony_ci 741a8e1175bSopenharmony_ci/* 742a8e1175bSopenharmony_ci * Write X into an opened file (or stdout if fout == NULL) 743a8e1175bSopenharmony_ci */ 744a8e1175bSopenharmony_ciint mbedtls_mpi_write_file(const char *p, const mbedtls_mpi *X, int radix, FILE *fout) 745a8e1175bSopenharmony_ci{ 746a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 747a8e1175bSopenharmony_ci size_t n, slen, plen; 748a8e1175bSopenharmony_ci /* 749a8e1175bSopenharmony_ci * Buffer should have space for (short) label and decimal formatted MPI, 750a8e1175bSopenharmony_ci * newline characters and '\0' 751a8e1175bSopenharmony_ci */ 752a8e1175bSopenharmony_ci char s[MBEDTLS_MPI_RW_BUFFER_SIZE]; 753a8e1175bSopenharmony_ci 754a8e1175bSopenharmony_ci if (radix < 2 || radix > 16) { 755a8e1175bSopenharmony_ci return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 756a8e1175bSopenharmony_ci } 757a8e1175bSopenharmony_ci 758a8e1175bSopenharmony_ci memset(s, 0, sizeof(s)); 759a8e1175bSopenharmony_ci 760a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_write_string(X, radix, s, sizeof(s) - 2, &n)); 761a8e1175bSopenharmony_ci 762a8e1175bSopenharmony_ci if (p == NULL) { 763a8e1175bSopenharmony_ci p = ""; 764a8e1175bSopenharmony_ci } 765a8e1175bSopenharmony_ci 766a8e1175bSopenharmony_ci plen = strlen(p); 767a8e1175bSopenharmony_ci slen = strlen(s); 768a8e1175bSopenharmony_ci s[slen++] = '\r'; 769a8e1175bSopenharmony_ci s[slen++] = '\n'; 770a8e1175bSopenharmony_ci 771a8e1175bSopenharmony_ci if (fout != NULL) { 772a8e1175bSopenharmony_ci if (fwrite(p, 1, plen, fout) != plen || 773a8e1175bSopenharmony_ci fwrite(s, 1, slen, fout) != slen) { 774a8e1175bSopenharmony_ci return MBEDTLS_ERR_MPI_FILE_IO_ERROR; 775a8e1175bSopenharmony_ci } 776a8e1175bSopenharmony_ci } else { 777a8e1175bSopenharmony_ci mbedtls_printf("%s%s", p, s); 778a8e1175bSopenharmony_ci } 779a8e1175bSopenharmony_ci 780a8e1175bSopenharmony_cicleanup: 781a8e1175bSopenharmony_ci 782a8e1175bSopenharmony_ci return ret; 783a8e1175bSopenharmony_ci} 784a8e1175bSopenharmony_ci#endif /* MBEDTLS_FS_IO */ 785a8e1175bSopenharmony_ci 786a8e1175bSopenharmony_ci/* 787a8e1175bSopenharmony_ci * Import X from unsigned binary data, little endian 788a8e1175bSopenharmony_ci * 789a8e1175bSopenharmony_ci * This function is guaranteed to return an MPI with exactly the necessary 790a8e1175bSopenharmony_ci * number of limbs (in particular, it does not skip 0s in the input). 791a8e1175bSopenharmony_ci */ 792a8e1175bSopenharmony_ciint mbedtls_mpi_read_binary_le(mbedtls_mpi *X, 793a8e1175bSopenharmony_ci const unsigned char *buf, size_t buflen) 794a8e1175bSopenharmony_ci{ 795a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 796a8e1175bSopenharmony_ci const size_t limbs = CHARS_TO_LIMBS(buflen); 797a8e1175bSopenharmony_ci 798a8e1175bSopenharmony_ci /* Ensure that target MPI has exactly the necessary number of limbs */ 799a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs)); 800a8e1175bSopenharmony_ci 801a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_le(X->p, X->n, buf, buflen)); 802a8e1175bSopenharmony_ci 803a8e1175bSopenharmony_cicleanup: 804a8e1175bSopenharmony_ci 805a8e1175bSopenharmony_ci /* 806a8e1175bSopenharmony_ci * This function is also used to import keys. However, wiping the buffers 807a8e1175bSopenharmony_ci * upon failure is not necessary because failure only can happen before any 808a8e1175bSopenharmony_ci * input is copied. 809a8e1175bSopenharmony_ci */ 810a8e1175bSopenharmony_ci return ret; 811a8e1175bSopenharmony_ci} 812a8e1175bSopenharmony_ci 813a8e1175bSopenharmony_ci/* 814a8e1175bSopenharmony_ci * Import X from unsigned binary data, big endian 815a8e1175bSopenharmony_ci * 816a8e1175bSopenharmony_ci * This function is guaranteed to return an MPI with exactly the necessary 817a8e1175bSopenharmony_ci * number of limbs (in particular, it does not skip 0s in the input). 818a8e1175bSopenharmony_ci */ 819a8e1175bSopenharmony_ciint mbedtls_mpi_read_binary(mbedtls_mpi *X, const unsigned char *buf, size_t buflen) 820a8e1175bSopenharmony_ci{ 821a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 822a8e1175bSopenharmony_ci const size_t limbs = CHARS_TO_LIMBS(buflen); 823a8e1175bSopenharmony_ci 824a8e1175bSopenharmony_ci /* Ensure that target MPI has exactly the necessary number of limbs */ 825a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs)); 826a8e1175bSopenharmony_ci 827a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_be(X->p, X->n, buf, buflen)); 828a8e1175bSopenharmony_ci 829a8e1175bSopenharmony_cicleanup: 830a8e1175bSopenharmony_ci 831a8e1175bSopenharmony_ci /* 832a8e1175bSopenharmony_ci * This function is also used to import keys. However, wiping the buffers 833a8e1175bSopenharmony_ci * upon failure is not necessary because failure only can happen before any 834a8e1175bSopenharmony_ci * input is copied. 835a8e1175bSopenharmony_ci */ 836a8e1175bSopenharmony_ci return ret; 837a8e1175bSopenharmony_ci} 838a8e1175bSopenharmony_ci 839a8e1175bSopenharmony_ci/* 840a8e1175bSopenharmony_ci * Export X into unsigned binary data, little endian 841a8e1175bSopenharmony_ci */ 842a8e1175bSopenharmony_ciint mbedtls_mpi_write_binary_le(const mbedtls_mpi *X, 843a8e1175bSopenharmony_ci unsigned char *buf, size_t buflen) 844a8e1175bSopenharmony_ci{ 845a8e1175bSopenharmony_ci return mbedtls_mpi_core_write_le(X->p, X->n, buf, buflen); 846a8e1175bSopenharmony_ci} 847a8e1175bSopenharmony_ci 848a8e1175bSopenharmony_ci/* 849a8e1175bSopenharmony_ci * Export X into unsigned binary data, big endian 850a8e1175bSopenharmony_ci */ 851a8e1175bSopenharmony_ciint mbedtls_mpi_write_binary(const mbedtls_mpi *X, 852a8e1175bSopenharmony_ci unsigned char *buf, size_t buflen) 853a8e1175bSopenharmony_ci{ 854a8e1175bSopenharmony_ci return mbedtls_mpi_core_write_be(X->p, X->n, buf, buflen); 855a8e1175bSopenharmony_ci} 856a8e1175bSopenharmony_ci 857a8e1175bSopenharmony_ci/* 858a8e1175bSopenharmony_ci * Left-shift: X <<= count 859a8e1175bSopenharmony_ci */ 860a8e1175bSopenharmony_ciint mbedtls_mpi_shift_l(mbedtls_mpi *X, size_t count) 861a8e1175bSopenharmony_ci{ 862a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 863a8e1175bSopenharmony_ci size_t i; 864a8e1175bSopenharmony_ci 865a8e1175bSopenharmony_ci i = mbedtls_mpi_bitlen(X) + count; 866a8e1175bSopenharmony_ci 867a8e1175bSopenharmony_ci if (X->n * biL < i) { 868a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, BITS_TO_LIMBS(i))); 869a8e1175bSopenharmony_ci } 870a8e1175bSopenharmony_ci 871a8e1175bSopenharmony_ci ret = 0; 872a8e1175bSopenharmony_ci 873a8e1175bSopenharmony_ci mbedtls_mpi_core_shift_l(X->p, X->n, count); 874a8e1175bSopenharmony_cicleanup: 875a8e1175bSopenharmony_ci 876a8e1175bSopenharmony_ci return ret; 877a8e1175bSopenharmony_ci} 878a8e1175bSopenharmony_ci 879a8e1175bSopenharmony_ci/* 880a8e1175bSopenharmony_ci * Right-shift: X >>= count 881a8e1175bSopenharmony_ci */ 882a8e1175bSopenharmony_ciint mbedtls_mpi_shift_r(mbedtls_mpi *X, size_t count) 883a8e1175bSopenharmony_ci{ 884a8e1175bSopenharmony_ci if (X->n != 0) { 885a8e1175bSopenharmony_ci mbedtls_mpi_core_shift_r(X->p, X->n, count); 886a8e1175bSopenharmony_ci } 887a8e1175bSopenharmony_ci return 0; 888a8e1175bSopenharmony_ci} 889a8e1175bSopenharmony_ci 890a8e1175bSopenharmony_ci/* 891a8e1175bSopenharmony_ci * Compare unsigned values 892a8e1175bSopenharmony_ci */ 893a8e1175bSopenharmony_ciint mbedtls_mpi_cmp_abs(const mbedtls_mpi *X, const mbedtls_mpi *Y) 894a8e1175bSopenharmony_ci{ 895a8e1175bSopenharmony_ci size_t i, j; 896a8e1175bSopenharmony_ci 897a8e1175bSopenharmony_ci for (i = X->n; i > 0; i--) { 898a8e1175bSopenharmony_ci if (X->p[i - 1] != 0) { 899a8e1175bSopenharmony_ci break; 900a8e1175bSopenharmony_ci } 901a8e1175bSopenharmony_ci } 902a8e1175bSopenharmony_ci 903a8e1175bSopenharmony_ci for (j = Y->n; j > 0; j--) { 904a8e1175bSopenharmony_ci if (Y->p[j - 1] != 0) { 905a8e1175bSopenharmony_ci break; 906a8e1175bSopenharmony_ci } 907a8e1175bSopenharmony_ci } 908a8e1175bSopenharmony_ci 909a8e1175bSopenharmony_ci /* If i == j == 0, i.e. abs(X) == abs(Y), 910a8e1175bSopenharmony_ci * we end up returning 0 at the end of the function. */ 911a8e1175bSopenharmony_ci 912a8e1175bSopenharmony_ci if (i > j) { 913a8e1175bSopenharmony_ci return 1; 914a8e1175bSopenharmony_ci } 915a8e1175bSopenharmony_ci if (j > i) { 916a8e1175bSopenharmony_ci return -1; 917a8e1175bSopenharmony_ci } 918a8e1175bSopenharmony_ci 919a8e1175bSopenharmony_ci for (; i > 0; i--) { 920a8e1175bSopenharmony_ci if (X->p[i - 1] > Y->p[i - 1]) { 921a8e1175bSopenharmony_ci return 1; 922a8e1175bSopenharmony_ci } 923a8e1175bSopenharmony_ci if (X->p[i - 1] < Y->p[i - 1]) { 924a8e1175bSopenharmony_ci return -1; 925a8e1175bSopenharmony_ci } 926a8e1175bSopenharmony_ci } 927a8e1175bSopenharmony_ci 928a8e1175bSopenharmony_ci return 0; 929a8e1175bSopenharmony_ci} 930a8e1175bSopenharmony_ci 931a8e1175bSopenharmony_ci/* 932a8e1175bSopenharmony_ci * Compare signed values 933a8e1175bSopenharmony_ci */ 934a8e1175bSopenharmony_ciint mbedtls_mpi_cmp_mpi(const mbedtls_mpi *X, const mbedtls_mpi *Y) 935a8e1175bSopenharmony_ci{ 936a8e1175bSopenharmony_ci size_t i, j; 937a8e1175bSopenharmony_ci 938a8e1175bSopenharmony_ci for (i = X->n; i > 0; i--) { 939a8e1175bSopenharmony_ci if (X->p[i - 1] != 0) { 940a8e1175bSopenharmony_ci break; 941a8e1175bSopenharmony_ci } 942a8e1175bSopenharmony_ci } 943a8e1175bSopenharmony_ci 944a8e1175bSopenharmony_ci for (j = Y->n; j > 0; j--) { 945a8e1175bSopenharmony_ci if (Y->p[j - 1] != 0) { 946a8e1175bSopenharmony_ci break; 947a8e1175bSopenharmony_ci } 948a8e1175bSopenharmony_ci } 949a8e1175bSopenharmony_ci 950a8e1175bSopenharmony_ci if (i == 0 && j == 0) { 951a8e1175bSopenharmony_ci return 0; 952a8e1175bSopenharmony_ci } 953a8e1175bSopenharmony_ci 954a8e1175bSopenharmony_ci if (i > j) { 955a8e1175bSopenharmony_ci return X->s; 956a8e1175bSopenharmony_ci } 957a8e1175bSopenharmony_ci if (j > i) { 958a8e1175bSopenharmony_ci return -Y->s; 959a8e1175bSopenharmony_ci } 960a8e1175bSopenharmony_ci 961a8e1175bSopenharmony_ci if (X->s > 0 && Y->s < 0) { 962a8e1175bSopenharmony_ci return 1; 963a8e1175bSopenharmony_ci } 964a8e1175bSopenharmony_ci if (Y->s > 0 && X->s < 0) { 965a8e1175bSopenharmony_ci return -1; 966a8e1175bSopenharmony_ci } 967a8e1175bSopenharmony_ci 968a8e1175bSopenharmony_ci for (; i > 0; i--) { 969a8e1175bSopenharmony_ci if (X->p[i - 1] > Y->p[i - 1]) { 970a8e1175bSopenharmony_ci return X->s; 971a8e1175bSopenharmony_ci } 972a8e1175bSopenharmony_ci if (X->p[i - 1] < Y->p[i - 1]) { 973a8e1175bSopenharmony_ci return -X->s; 974a8e1175bSopenharmony_ci } 975a8e1175bSopenharmony_ci } 976a8e1175bSopenharmony_ci 977a8e1175bSopenharmony_ci return 0; 978a8e1175bSopenharmony_ci} 979a8e1175bSopenharmony_ci 980a8e1175bSopenharmony_ci/* 981a8e1175bSopenharmony_ci * Compare signed values 982a8e1175bSopenharmony_ci */ 983a8e1175bSopenharmony_ciint mbedtls_mpi_cmp_int(const mbedtls_mpi *X, mbedtls_mpi_sint z) 984a8e1175bSopenharmony_ci{ 985a8e1175bSopenharmony_ci mbedtls_mpi Y; 986a8e1175bSopenharmony_ci mbedtls_mpi_uint p[1]; 987a8e1175bSopenharmony_ci 988a8e1175bSopenharmony_ci *p = mpi_sint_abs(z); 989a8e1175bSopenharmony_ci Y.s = TO_SIGN(z); 990a8e1175bSopenharmony_ci Y.n = 1; 991a8e1175bSopenharmony_ci Y.p = p; 992a8e1175bSopenharmony_ci 993a8e1175bSopenharmony_ci return mbedtls_mpi_cmp_mpi(X, &Y); 994a8e1175bSopenharmony_ci} 995a8e1175bSopenharmony_ci 996a8e1175bSopenharmony_ci/* 997a8e1175bSopenharmony_ci * Unsigned addition: X = |A| + |B| (HAC 14.7) 998a8e1175bSopenharmony_ci */ 999a8e1175bSopenharmony_ciint mbedtls_mpi_add_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B) 1000a8e1175bSopenharmony_ci{ 1001a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1002a8e1175bSopenharmony_ci size_t j; 1003a8e1175bSopenharmony_ci mbedtls_mpi_uint *p; 1004a8e1175bSopenharmony_ci mbedtls_mpi_uint c; 1005a8e1175bSopenharmony_ci 1006a8e1175bSopenharmony_ci if (X == B) { 1007a8e1175bSopenharmony_ci const mbedtls_mpi *T = A; A = X; B = T; 1008a8e1175bSopenharmony_ci } 1009a8e1175bSopenharmony_ci 1010a8e1175bSopenharmony_ci if (X != A) { 1011a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A)); 1012a8e1175bSopenharmony_ci } 1013a8e1175bSopenharmony_ci 1014a8e1175bSopenharmony_ci /* 1015a8e1175bSopenharmony_ci * X must always be positive as a result of unsigned additions. 1016a8e1175bSopenharmony_ci */ 1017a8e1175bSopenharmony_ci X->s = 1; 1018a8e1175bSopenharmony_ci 1019a8e1175bSopenharmony_ci for (j = B->n; j > 0; j--) { 1020a8e1175bSopenharmony_ci if (B->p[j - 1] != 0) { 1021a8e1175bSopenharmony_ci break; 1022a8e1175bSopenharmony_ci } 1023a8e1175bSopenharmony_ci } 1024a8e1175bSopenharmony_ci 1025a8e1175bSopenharmony_ci /* Exit early to avoid undefined behavior on NULL+0 when X->n == 0 1026a8e1175bSopenharmony_ci * and B is 0 (of any size). */ 1027a8e1175bSopenharmony_ci if (j == 0) { 1028a8e1175bSopenharmony_ci return 0; 1029a8e1175bSopenharmony_ci } 1030a8e1175bSopenharmony_ci 1031a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j)); 1032a8e1175bSopenharmony_ci 1033a8e1175bSopenharmony_ci /* j is the number of non-zero limbs of B. Add those to X. */ 1034a8e1175bSopenharmony_ci 1035a8e1175bSopenharmony_ci p = X->p; 1036a8e1175bSopenharmony_ci 1037a8e1175bSopenharmony_ci c = mbedtls_mpi_core_add(p, p, B->p, j); 1038a8e1175bSopenharmony_ci 1039a8e1175bSopenharmony_ci p += j; 1040a8e1175bSopenharmony_ci 1041a8e1175bSopenharmony_ci /* Now propagate any carry */ 1042a8e1175bSopenharmony_ci 1043a8e1175bSopenharmony_ci while (c != 0) { 1044a8e1175bSopenharmony_ci if (j >= X->n) { 1045a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j + 1)); 1046a8e1175bSopenharmony_ci p = X->p + j; 1047a8e1175bSopenharmony_ci } 1048a8e1175bSopenharmony_ci 1049a8e1175bSopenharmony_ci *p += c; c = (*p < c); j++; p++; 1050a8e1175bSopenharmony_ci } 1051a8e1175bSopenharmony_ci 1052a8e1175bSopenharmony_cicleanup: 1053a8e1175bSopenharmony_ci 1054a8e1175bSopenharmony_ci return ret; 1055a8e1175bSopenharmony_ci} 1056a8e1175bSopenharmony_ci 1057a8e1175bSopenharmony_ci/* 1058a8e1175bSopenharmony_ci * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10) 1059a8e1175bSopenharmony_ci */ 1060a8e1175bSopenharmony_ciint mbedtls_mpi_sub_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B) 1061a8e1175bSopenharmony_ci{ 1062a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1063a8e1175bSopenharmony_ci size_t n; 1064a8e1175bSopenharmony_ci mbedtls_mpi_uint carry; 1065a8e1175bSopenharmony_ci 1066a8e1175bSopenharmony_ci for (n = B->n; n > 0; n--) { 1067a8e1175bSopenharmony_ci if (B->p[n - 1] != 0) { 1068a8e1175bSopenharmony_ci break; 1069a8e1175bSopenharmony_ci } 1070a8e1175bSopenharmony_ci } 1071a8e1175bSopenharmony_ci if (n > A->n) { 1072a8e1175bSopenharmony_ci /* B >= (2^ciL)^n > A */ 1073a8e1175bSopenharmony_ci ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE; 1074a8e1175bSopenharmony_ci goto cleanup; 1075a8e1175bSopenharmony_ci } 1076a8e1175bSopenharmony_ci 1077a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, A->n)); 1078a8e1175bSopenharmony_ci 1079a8e1175bSopenharmony_ci /* Set the high limbs of X to match A. Don't touch the lower limbs 1080a8e1175bSopenharmony_ci * because X might be aliased to B, and we must not overwrite the 1081a8e1175bSopenharmony_ci * significant digits of B. */ 1082a8e1175bSopenharmony_ci if (A->n > n && A != X) { 1083a8e1175bSopenharmony_ci memcpy(X->p + n, A->p + n, (A->n - n) * ciL); 1084a8e1175bSopenharmony_ci } 1085a8e1175bSopenharmony_ci if (X->n > A->n) { 1086a8e1175bSopenharmony_ci memset(X->p + A->n, 0, (X->n - A->n) * ciL); 1087a8e1175bSopenharmony_ci } 1088a8e1175bSopenharmony_ci 1089a8e1175bSopenharmony_ci carry = mbedtls_mpi_core_sub(X->p, A->p, B->p, n); 1090a8e1175bSopenharmony_ci if (carry != 0) { 1091a8e1175bSopenharmony_ci /* Propagate the carry through the rest of X. */ 1092a8e1175bSopenharmony_ci carry = mbedtls_mpi_core_sub_int(X->p + n, X->p + n, carry, X->n - n); 1093a8e1175bSopenharmony_ci 1094a8e1175bSopenharmony_ci /* If we have further carry/borrow, the result is negative. */ 1095a8e1175bSopenharmony_ci if (carry != 0) { 1096a8e1175bSopenharmony_ci ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE; 1097a8e1175bSopenharmony_ci goto cleanup; 1098a8e1175bSopenharmony_ci } 1099a8e1175bSopenharmony_ci } 1100a8e1175bSopenharmony_ci 1101a8e1175bSopenharmony_ci /* X should always be positive as a result of unsigned subtractions. */ 1102a8e1175bSopenharmony_ci X->s = 1; 1103a8e1175bSopenharmony_ci 1104a8e1175bSopenharmony_cicleanup: 1105a8e1175bSopenharmony_ci return ret; 1106a8e1175bSopenharmony_ci} 1107a8e1175bSopenharmony_ci 1108a8e1175bSopenharmony_ci/* Common function for signed addition and subtraction. 1109a8e1175bSopenharmony_ci * Calculate A + B * flip_B where flip_B is 1 or -1. 1110a8e1175bSopenharmony_ci */ 1111a8e1175bSopenharmony_cistatic int add_sub_mpi(mbedtls_mpi *X, 1112a8e1175bSopenharmony_ci const mbedtls_mpi *A, const mbedtls_mpi *B, 1113a8e1175bSopenharmony_ci int flip_B) 1114a8e1175bSopenharmony_ci{ 1115a8e1175bSopenharmony_ci int ret, s; 1116a8e1175bSopenharmony_ci 1117a8e1175bSopenharmony_ci s = A->s; 1118a8e1175bSopenharmony_ci if (A->s * B->s * flip_B < 0) { 1119a8e1175bSopenharmony_ci int cmp = mbedtls_mpi_cmp_abs(A, B); 1120a8e1175bSopenharmony_ci if (cmp >= 0) { 1121a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, A, B)); 1122a8e1175bSopenharmony_ci /* If |A| = |B|, the result is 0 and we must set the sign bit 1123a8e1175bSopenharmony_ci * to +1 regardless of which of A or B was negative. Otherwise, 1124a8e1175bSopenharmony_ci * since |A| > |B|, the sign is the sign of A. */ 1125a8e1175bSopenharmony_ci X->s = cmp == 0 ? 1 : s; 1126a8e1175bSopenharmony_ci } else { 1127a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, B, A)); 1128a8e1175bSopenharmony_ci /* Since |A| < |B|, the sign is the opposite of A. */ 1129a8e1175bSopenharmony_ci X->s = -s; 1130a8e1175bSopenharmony_ci } 1131a8e1175bSopenharmony_ci } else { 1132a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_add_abs(X, A, B)); 1133a8e1175bSopenharmony_ci X->s = s; 1134a8e1175bSopenharmony_ci } 1135a8e1175bSopenharmony_ci 1136a8e1175bSopenharmony_cicleanup: 1137a8e1175bSopenharmony_ci 1138a8e1175bSopenharmony_ci return ret; 1139a8e1175bSopenharmony_ci} 1140a8e1175bSopenharmony_ci 1141a8e1175bSopenharmony_ci/* 1142a8e1175bSopenharmony_ci * Signed addition: X = A + B 1143a8e1175bSopenharmony_ci */ 1144a8e1175bSopenharmony_ciint mbedtls_mpi_add_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B) 1145a8e1175bSopenharmony_ci{ 1146a8e1175bSopenharmony_ci return add_sub_mpi(X, A, B, 1); 1147a8e1175bSopenharmony_ci} 1148a8e1175bSopenharmony_ci 1149a8e1175bSopenharmony_ci/* 1150a8e1175bSopenharmony_ci * Signed subtraction: X = A - B 1151a8e1175bSopenharmony_ci */ 1152a8e1175bSopenharmony_ciint mbedtls_mpi_sub_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B) 1153a8e1175bSopenharmony_ci{ 1154a8e1175bSopenharmony_ci return add_sub_mpi(X, A, B, -1); 1155a8e1175bSopenharmony_ci} 1156a8e1175bSopenharmony_ci 1157a8e1175bSopenharmony_ci/* 1158a8e1175bSopenharmony_ci * Signed addition: X = A + b 1159a8e1175bSopenharmony_ci */ 1160a8e1175bSopenharmony_ciint mbedtls_mpi_add_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b) 1161a8e1175bSopenharmony_ci{ 1162a8e1175bSopenharmony_ci mbedtls_mpi B; 1163a8e1175bSopenharmony_ci mbedtls_mpi_uint p[1]; 1164a8e1175bSopenharmony_ci 1165a8e1175bSopenharmony_ci p[0] = mpi_sint_abs(b); 1166a8e1175bSopenharmony_ci B.s = TO_SIGN(b); 1167a8e1175bSopenharmony_ci B.n = 1; 1168a8e1175bSopenharmony_ci B.p = p; 1169a8e1175bSopenharmony_ci 1170a8e1175bSopenharmony_ci return mbedtls_mpi_add_mpi(X, A, &B); 1171a8e1175bSopenharmony_ci} 1172a8e1175bSopenharmony_ci 1173a8e1175bSopenharmony_ci/* 1174a8e1175bSopenharmony_ci * Signed subtraction: X = A - b 1175a8e1175bSopenharmony_ci */ 1176a8e1175bSopenharmony_ciint mbedtls_mpi_sub_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b) 1177a8e1175bSopenharmony_ci{ 1178a8e1175bSopenharmony_ci mbedtls_mpi B; 1179a8e1175bSopenharmony_ci mbedtls_mpi_uint p[1]; 1180a8e1175bSopenharmony_ci 1181a8e1175bSopenharmony_ci p[0] = mpi_sint_abs(b); 1182a8e1175bSopenharmony_ci B.s = TO_SIGN(b); 1183a8e1175bSopenharmony_ci B.n = 1; 1184a8e1175bSopenharmony_ci B.p = p; 1185a8e1175bSopenharmony_ci 1186a8e1175bSopenharmony_ci return mbedtls_mpi_sub_mpi(X, A, &B); 1187a8e1175bSopenharmony_ci} 1188a8e1175bSopenharmony_ci 1189a8e1175bSopenharmony_ci/* 1190a8e1175bSopenharmony_ci * Baseline multiplication: X = A * B (HAC 14.12) 1191a8e1175bSopenharmony_ci */ 1192a8e1175bSopenharmony_ciint mbedtls_mpi_mul_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B) 1193a8e1175bSopenharmony_ci{ 1194a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1195a8e1175bSopenharmony_ci size_t i, j; 1196a8e1175bSopenharmony_ci mbedtls_mpi TA, TB; 1197a8e1175bSopenharmony_ci int result_is_zero = 0; 1198a8e1175bSopenharmony_ci 1199a8e1175bSopenharmony_ci mbedtls_mpi_init(&TA); 1200a8e1175bSopenharmony_ci mbedtls_mpi_init(&TB); 1201a8e1175bSopenharmony_ci 1202a8e1175bSopenharmony_ci if (X == A) { 1203a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A)); A = &TA; 1204a8e1175bSopenharmony_ci } 1205a8e1175bSopenharmony_ci if (X == B) { 1206a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B)); B = &TB; 1207a8e1175bSopenharmony_ci } 1208a8e1175bSopenharmony_ci 1209a8e1175bSopenharmony_ci for (i = A->n; i > 0; i--) { 1210a8e1175bSopenharmony_ci if (A->p[i - 1] != 0) { 1211a8e1175bSopenharmony_ci break; 1212a8e1175bSopenharmony_ci } 1213a8e1175bSopenharmony_ci } 1214a8e1175bSopenharmony_ci if (i == 0) { 1215a8e1175bSopenharmony_ci result_is_zero = 1; 1216a8e1175bSopenharmony_ci } 1217a8e1175bSopenharmony_ci 1218a8e1175bSopenharmony_ci for (j = B->n; j > 0; j--) { 1219a8e1175bSopenharmony_ci if (B->p[j - 1] != 0) { 1220a8e1175bSopenharmony_ci break; 1221a8e1175bSopenharmony_ci } 1222a8e1175bSopenharmony_ci } 1223a8e1175bSopenharmony_ci if (j == 0) { 1224a8e1175bSopenharmony_ci result_is_zero = 1; 1225a8e1175bSopenharmony_ci } 1226a8e1175bSopenharmony_ci 1227a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i + j)); 1228a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0)); 1229a8e1175bSopenharmony_ci 1230a8e1175bSopenharmony_ci mbedtls_mpi_core_mul(X->p, A->p, i, B->p, j); 1231a8e1175bSopenharmony_ci 1232a8e1175bSopenharmony_ci /* If the result is 0, we don't shortcut the operation, which reduces 1233a8e1175bSopenharmony_ci * but does not eliminate side channels leaking the zero-ness. We do 1234a8e1175bSopenharmony_ci * need to take care to set the sign bit properly since the library does 1235a8e1175bSopenharmony_ci * not fully support an MPI object with a value of 0 and s == -1. */ 1236a8e1175bSopenharmony_ci if (result_is_zero) { 1237a8e1175bSopenharmony_ci X->s = 1; 1238a8e1175bSopenharmony_ci } else { 1239a8e1175bSopenharmony_ci X->s = A->s * B->s; 1240a8e1175bSopenharmony_ci } 1241a8e1175bSopenharmony_ci 1242a8e1175bSopenharmony_cicleanup: 1243a8e1175bSopenharmony_ci 1244a8e1175bSopenharmony_ci mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TA); 1245a8e1175bSopenharmony_ci 1246a8e1175bSopenharmony_ci return ret; 1247a8e1175bSopenharmony_ci} 1248a8e1175bSopenharmony_ci 1249a8e1175bSopenharmony_ci/* 1250a8e1175bSopenharmony_ci * Baseline multiplication: X = A * b 1251a8e1175bSopenharmony_ci */ 1252a8e1175bSopenharmony_ciint mbedtls_mpi_mul_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b) 1253a8e1175bSopenharmony_ci{ 1254a8e1175bSopenharmony_ci size_t n = A->n; 1255a8e1175bSopenharmony_ci while (n > 0 && A->p[n - 1] == 0) { 1256a8e1175bSopenharmony_ci --n; 1257a8e1175bSopenharmony_ci } 1258a8e1175bSopenharmony_ci 1259a8e1175bSopenharmony_ci /* The general method below doesn't work if b==0. */ 1260a8e1175bSopenharmony_ci if (b == 0 || n == 0) { 1261a8e1175bSopenharmony_ci return mbedtls_mpi_lset(X, 0); 1262a8e1175bSopenharmony_ci } 1263a8e1175bSopenharmony_ci 1264a8e1175bSopenharmony_ci /* Calculate A*b as A + A*(b-1) to take advantage of mbedtls_mpi_core_mla */ 1265a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1266a8e1175bSopenharmony_ci /* In general, A * b requires 1 limb more than b. If 1267a8e1175bSopenharmony_ci * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same 1268a8e1175bSopenharmony_ci * number of limbs as A and the call to grow() is not required since 1269a8e1175bSopenharmony_ci * copy() will take care of the growth if needed. However, experimentally, 1270a8e1175bSopenharmony_ci * making the call to grow() unconditional causes slightly fewer 1271a8e1175bSopenharmony_ci * calls to calloc() in ECP code, presumably because it reuses the 1272a8e1175bSopenharmony_ci * same mpi for a while and this way the mpi is more likely to directly 1273a8e1175bSopenharmony_ci * grow to its final size. 1274a8e1175bSopenharmony_ci * 1275a8e1175bSopenharmony_ci * Note that calculating A*b as 0 + A*b doesn't work as-is because 1276a8e1175bSopenharmony_ci * A,X can be the same. */ 1277a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n + 1)); 1278a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A)); 1279a8e1175bSopenharmony_ci mbedtls_mpi_core_mla(X->p, X->n, A->p, n, b - 1); 1280a8e1175bSopenharmony_ci 1281a8e1175bSopenharmony_cicleanup: 1282a8e1175bSopenharmony_ci return ret; 1283a8e1175bSopenharmony_ci} 1284a8e1175bSopenharmony_ci 1285a8e1175bSopenharmony_ci/* 1286a8e1175bSopenharmony_ci * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and 1287a8e1175bSopenharmony_ci * mbedtls_mpi_uint divisor, d 1288a8e1175bSopenharmony_ci */ 1289a8e1175bSopenharmony_cistatic mbedtls_mpi_uint mbedtls_int_div_int(mbedtls_mpi_uint u1, 1290a8e1175bSopenharmony_ci mbedtls_mpi_uint u0, 1291a8e1175bSopenharmony_ci mbedtls_mpi_uint d, 1292a8e1175bSopenharmony_ci mbedtls_mpi_uint *r) 1293a8e1175bSopenharmony_ci{ 1294a8e1175bSopenharmony_ci#if defined(MBEDTLS_HAVE_UDBL) 1295a8e1175bSopenharmony_ci mbedtls_t_udbl dividend, quotient; 1296a8e1175bSopenharmony_ci#else 1297a8e1175bSopenharmony_ci const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH; 1298a8e1175bSopenharmony_ci const mbedtls_mpi_uint uint_halfword_mask = ((mbedtls_mpi_uint) 1 << biH) - 1; 1299a8e1175bSopenharmony_ci mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient; 1300a8e1175bSopenharmony_ci mbedtls_mpi_uint u0_msw, u0_lsw; 1301a8e1175bSopenharmony_ci size_t s; 1302a8e1175bSopenharmony_ci#endif 1303a8e1175bSopenharmony_ci 1304a8e1175bSopenharmony_ci /* 1305a8e1175bSopenharmony_ci * Check for overflow 1306a8e1175bSopenharmony_ci */ 1307a8e1175bSopenharmony_ci if (0 == d || u1 >= d) { 1308a8e1175bSopenharmony_ci if (r != NULL) { 1309a8e1175bSopenharmony_ci *r = ~(mbedtls_mpi_uint) 0u; 1310a8e1175bSopenharmony_ci } 1311a8e1175bSopenharmony_ci 1312a8e1175bSopenharmony_ci return ~(mbedtls_mpi_uint) 0u; 1313a8e1175bSopenharmony_ci } 1314a8e1175bSopenharmony_ci 1315a8e1175bSopenharmony_ci#if defined(MBEDTLS_HAVE_UDBL) 1316a8e1175bSopenharmony_ci dividend = (mbedtls_t_udbl) u1 << biL; 1317a8e1175bSopenharmony_ci dividend |= (mbedtls_t_udbl) u0; 1318a8e1175bSopenharmony_ci quotient = dividend / d; 1319a8e1175bSopenharmony_ci if (quotient > ((mbedtls_t_udbl) 1 << biL) - 1) { 1320a8e1175bSopenharmony_ci quotient = ((mbedtls_t_udbl) 1 << biL) - 1; 1321a8e1175bSopenharmony_ci } 1322a8e1175bSopenharmony_ci 1323a8e1175bSopenharmony_ci if (r != NULL) { 1324a8e1175bSopenharmony_ci *r = (mbedtls_mpi_uint) (dividend - (quotient * d)); 1325a8e1175bSopenharmony_ci } 1326a8e1175bSopenharmony_ci 1327a8e1175bSopenharmony_ci return (mbedtls_mpi_uint) quotient; 1328a8e1175bSopenharmony_ci#else 1329a8e1175bSopenharmony_ci 1330a8e1175bSopenharmony_ci /* 1331a8e1175bSopenharmony_ci * Algorithm D, Section 4.3.1 - The Art of Computer Programming 1332a8e1175bSopenharmony_ci * Vol. 2 - Seminumerical Algorithms, Knuth 1333a8e1175bSopenharmony_ci */ 1334a8e1175bSopenharmony_ci 1335a8e1175bSopenharmony_ci /* 1336a8e1175bSopenharmony_ci * Normalize the divisor, d, and dividend, u0, u1 1337a8e1175bSopenharmony_ci */ 1338a8e1175bSopenharmony_ci s = mbedtls_mpi_core_clz(d); 1339a8e1175bSopenharmony_ci d = d << s; 1340a8e1175bSopenharmony_ci 1341a8e1175bSopenharmony_ci u1 = u1 << s; 1342a8e1175bSopenharmony_ci u1 |= (u0 >> (biL - s)) & (-(mbedtls_mpi_sint) s >> (biL - 1)); 1343a8e1175bSopenharmony_ci u0 = u0 << s; 1344a8e1175bSopenharmony_ci 1345a8e1175bSopenharmony_ci d1 = d >> biH; 1346a8e1175bSopenharmony_ci d0 = d & uint_halfword_mask; 1347a8e1175bSopenharmony_ci 1348a8e1175bSopenharmony_ci u0_msw = u0 >> biH; 1349a8e1175bSopenharmony_ci u0_lsw = u0 & uint_halfword_mask; 1350a8e1175bSopenharmony_ci 1351a8e1175bSopenharmony_ci /* 1352a8e1175bSopenharmony_ci * Find the first quotient and remainder 1353a8e1175bSopenharmony_ci */ 1354a8e1175bSopenharmony_ci q1 = u1 / d1; 1355a8e1175bSopenharmony_ci r0 = u1 - d1 * q1; 1356a8e1175bSopenharmony_ci 1357a8e1175bSopenharmony_ci while (q1 >= radix || (q1 * d0 > radix * r0 + u0_msw)) { 1358a8e1175bSopenharmony_ci q1 -= 1; 1359a8e1175bSopenharmony_ci r0 += d1; 1360a8e1175bSopenharmony_ci 1361a8e1175bSopenharmony_ci if (r0 >= radix) { 1362a8e1175bSopenharmony_ci break; 1363a8e1175bSopenharmony_ci } 1364a8e1175bSopenharmony_ci } 1365a8e1175bSopenharmony_ci 1366a8e1175bSopenharmony_ci rAX = (u1 * radix) + (u0_msw - q1 * d); 1367a8e1175bSopenharmony_ci q0 = rAX / d1; 1368a8e1175bSopenharmony_ci r0 = rAX - q0 * d1; 1369a8e1175bSopenharmony_ci 1370a8e1175bSopenharmony_ci while (q0 >= radix || (q0 * d0 > radix * r0 + u0_lsw)) { 1371a8e1175bSopenharmony_ci q0 -= 1; 1372a8e1175bSopenharmony_ci r0 += d1; 1373a8e1175bSopenharmony_ci 1374a8e1175bSopenharmony_ci if (r0 >= radix) { 1375a8e1175bSopenharmony_ci break; 1376a8e1175bSopenharmony_ci } 1377a8e1175bSopenharmony_ci } 1378a8e1175bSopenharmony_ci 1379a8e1175bSopenharmony_ci if (r != NULL) { 1380a8e1175bSopenharmony_ci *r = (rAX * radix + u0_lsw - q0 * d) >> s; 1381a8e1175bSopenharmony_ci } 1382a8e1175bSopenharmony_ci 1383a8e1175bSopenharmony_ci quotient = q1 * radix + q0; 1384a8e1175bSopenharmony_ci 1385a8e1175bSopenharmony_ci return quotient; 1386a8e1175bSopenharmony_ci#endif 1387a8e1175bSopenharmony_ci} 1388a8e1175bSopenharmony_ci 1389a8e1175bSopenharmony_ci/* 1390a8e1175bSopenharmony_ci * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20) 1391a8e1175bSopenharmony_ci */ 1392a8e1175bSopenharmony_ciint mbedtls_mpi_div_mpi(mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, 1393a8e1175bSopenharmony_ci const mbedtls_mpi *B) 1394a8e1175bSopenharmony_ci{ 1395a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1396a8e1175bSopenharmony_ci size_t i, n, t, k; 1397a8e1175bSopenharmony_ci mbedtls_mpi X, Y, Z, T1, T2; 1398a8e1175bSopenharmony_ci mbedtls_mpi_uint TP2[3]; 1399a8e1175bSopenharmony_ci 1400a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_int(B, 0) == 0) { 1401a8e1175bSopenharmony_ci return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO; 1402a8e1175bSopenharmony_ci } 1403a8e1175bSopenharmony_ci 1404a8e1175bSopenharmony_ci mbedtls_mpi_init(&X); mbedtls_mpi_init(&Y); mbedtls_mpi_init(&Z); 1405a8e1175bSopenharmony_ci mbedtls_mpi_init(&T1); 1406a8e1175bSopenharmony_ci /* 1407a8e1175bSopenharmony_ci * Avoid dynamic memory allocations for constant-size T2. 1408a8e1175bSopenharmony_ci * 1409a8e1175bSopenharmony_ci * T2 is used for comparison only and the 3 limbs are assigned explicitly, 1410a8e1175bSopenharmony_ci * so nobody increase the size of the MPI and we're safe to use an on-stack 1411a8e1175bSopenharmony_ci * buffer. 1412a8e1175bSopenharmony_ci */ 1413a8e1175bSopenharmony_ci T2.s = 1; 1414a8e1175bSopenharmony_ci T2.n = sizeof(TP2) / sizeof(*TP2); 1415a8e1175bSopenharmony_ci T2.p = TP2; 1416a8e1175bSopenharmony_ci 1417a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_abs(A, B) < 0) { 1418a8e1175bSopenharmony_ci if (Q != NULL) { 1419a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_lset(Q, 0)); 1420a8e1175bSopenharmony_ci } 1421a8e1175bSopenharmony_ci if (R != NULL) { 1422a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, A)); 1423a8e1175bSopenharmony_ci } 1424a8e1175bSopenharmony_ci return 0; 1425a8e1175bSopenharmony_ci } 1426a8e1175bSopenharmony_ci 1427a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&X, A)); 1428a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, B)); 1429a8e1175bSopenharmony_ci X.s = Y.s = 1; 1430a8e1175bSopenharmony_ci 1431a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&Z, A->n + 2)); 1432a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Z, 0)); 1433a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T1, A->n + 2)); 1434a8e1175bSopenharmony_ci 1435a8e1175bSopenharmony_ci k = mbedtls_mpi_bitlen(&Y) % biL; 1436a8e1175bSopenharmony_ci if (k < biL - 1) { 1437a8e1175bSopenharmony_ci k = biL - 1 - k; 1438a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&X, k)); 1439a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, k)); 1440a8e1175bSopenharmony_ci } else { 1441a8e1175bSopenharmony_ci k = 0; 1442a8e1175bSopenharmony_ci } 1443a8e1175bSopenharmony_ci 1444a8e1175bSopenharmony_ci n = X.n - 1; 1445a8e1175bSopenharmony_ci t = Y.n - 1; 1446a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, biL * (n - t))); 1447a8e1175bSopenharmony_ci 1448a8e1175bSopenharmony_ci while (mbedtls_mpi_cmp_mpi(&X, &Y) >= 0) { 1449a8e1175bSopenharmony_ci Z.p[n - t]++; 1450a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &Y)); 1451a8e1175bSopenharmony_ci } 1452a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, biL * (n - t))); 1453a8e1175bSopenharmony_ci 1454a8e1175bSopenharmony_ci for (i = n; i > t; i--) { 1455a8e1175bSopenharmony_ci if (X.p[i] >= Y.p[t]) { 1456a8e1175bSopenharmony_ci Z.p[i - t - 1] = ~(mbedtls_mpi_uint) 0u; 1457a8e1175bSopenharmony_ci } else { 1458a8e1175bSopenharmony_ci Z.p[i - t - 1] = mbedtls_int_div_int(X.p[i], X.p[i - 1], 1459a8e1175bSopenharmony_ci Y.p[t], NULL); 1460a8e1175bSopenharmony_ci } 1461a8e1175bSopenharmony_ci 1462a8e1175bSopenharmony_ci T2.p[0] = (i < 2) ? 0 : X.p[i - 2]; 1463a8e1175bSopenharmony_ci T2.p[1] = (i < 1) ? 0 : X.p[i - 1]; 1464a8e1175bSopenharmony_ci T2.p[2] = X.p[i]; 1465a8e1175bSopenharmony_ci 1466a8e1175bSopenharmony_ci Z.p[i - t - 1]++; 1467a8e1175bSopenharmony_ci do { 1468a8e1175bSopenharmony_ci Z.p[i - t - 1]--; 1469a8e1175bSopenharmony_ci 1470a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&T1, 0)); 1471a8e1175bSopenharmony_ci T1.p[0] = (t < 1) ? 0 : Y.p[t - 1]; 1472a8e1175bSopenharmony_ci T1.p[1] = Y.p[t]; 1473a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &T1, Z.p[i - t - 1])); 1474a8e1175bSopenharmony_ci } while (mbedtls_mpi_cmp_mpi(&T1, &T2) > 0); 1475a8e1175bSopenharmony_ci 1476a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &Y, Z.p[i - t - 1])); 1477a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1))); 1478a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &T1)); 1479a8e1175bSopenharmony_ci 1480a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_int(&X, 0) < 0) { 1481a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T1, &Y)); 1482a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1))); 1483a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&X, &X, &T1)); 1484a8e1175bSopenharmony_ci Z.p[i - t - 1]--; 1485a8e1175bSopenharmony_ci } 1486a8e1175bSopenharmony_ci } 1487a8e1175bSopenharmony_ci 1488a8e1175bSopenharmony_ci if (Q != NULL) { 1489a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_copy(Q, &Z)); 1490a8e1175bSopenharmony_ci Q->s = A->s * B->s; 1491a8e1175bSopenharmony_ci } 1492a8e1175bSopenharmony_ci 1493a8e1175bSopenharmony_ci if (R != NULL) { 1494a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&X, k)); 1495a8e1175bSopenharmony_ci X.s = A->s; 1496a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, &X)); 1497a8e1175bSopenharmony_ci 1498a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_int(R, 0) == 0) { 1499a8e1175bSopenharmony_ci R->s = 1; 1500a8e1175bSopenharmony_ci } 1501a8e1175bSopenharmony_ci } 1502a8e1175bSopenharmony_ci 1503a8e1175bSopenharmony_cicleanup: 1504a8e1175bSopenharmony_ci 1505a8e1175bSopenharmony_ci mbedtls_mpi_free(&X); mbedtls_mpi_free(&Y); mbedtls_mpi_free(&Z); 1506a8e1175bSopenharmony_ci mbedtls_mpi_free(&T1); 1507a8e1175bSopenharmony_ci mbedtls_platform_zeroize(TP2, sizeof(TP2)); 1508a8e1175bSopenharmony_ci 1509a8e1175bSopenharmony_ci return ret; 1510a8e1175bSopenharmony_ci} 1511a8e1175bSopenharmony_ci 1512a8e1175bSopenharmony_ci/* 1513a8e1175bSopenharmony_ci * Division by int: A = Q * b + R 1514a8e1175bSopenharmony_ci */ 1515a8e1175bSopenharmony_ciint mbedtls_mpi_div_int(mbedtls_mpi *Q, mbedtls_mpi *R, 1516a8e1175bSopenharmony_ci const mbedtls_mpi *A, 1517a8e1175bSopenharmony_ci mbedtls_mpi_sint b) 1518a8e1175bSopenharmony_ci{ 1519a8e1175bSopenharmony_ci mbedtls_mpi B; 1520a8e1175bSopenharmony_ci mbedtls_mpi_uint p[1]; 1521a8e1175bSopenharmony_ci 1522a8e1175bSopenharmony_ci p[0] = mpi_sint_abs(b); 1523a8e1175bSopenharmony_ci B.s = TO_SIGN(b); 1524a8e1175bSopenharmony_ci B.n = 1; 1525a8e1175bSopenharmony_ci B.p = p; 1526a8e1175bSopenharmony_ci 1527a8e1175bSopenharmony_ci return mbedtls_mpi_div_mpi(Q, R, A, &B); 1528a8e1175bSopenharmony_ci} 1529a8e1175bSopenharmony_ci 1530a8e1175bSopenharmony_ci/* 1531a8e1175bSopenharmony_ci * Modulo: R = A mod B 1532a8e1175bSopenharmony_ci */ 1533a8e1175bSopenharmony_ciint mbedtls_mpi_mod_mpi(mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B) 1534a8e1175bSopenharmony_ci{ 1535a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1536a8e1175bSopenharmony_ci 1537a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_int(B, 0) < 0) { 1538a8e1175bSopenharmony_ci return MBEDTLS_ERR_MPI_NEGATIVE_VALUE; 1539a8e1175bSopenharmony_ci } 1540a8e1175bSopenharmony_ci 1541a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(NULL, R, A, B)); 1542a8e1175bSopenharmony_ci 1543a8e1175bSopenharmony_ci while (mbedtls_mpi_cmp_int(R, 0) < 0) { 1544a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(R, R, B)); 1545a8e1175bSopenharmony_ci } 1546a8e1175bSopenharmony_ci 1547a8e1175bSopenharmony_ci while (mbedtls_mpi_cmp_mpi(R, B) >= 0) { 1548a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(R, R, B)); 1549a8e1175bSopenharmony_ci } 1550a8e1175bSopenharmony_ci 1551a8e1175bSopenharmony_cicleanup: 1552a8e1175bSopenharmony_ci 1553a8e1175bSopenharmony_ci return ret; 1554a8e1175bSopenharmony_ci} 1555a8e1175bSopenharmony_ci 1556a8e1175bSopenharmony_ci/* 1557a8e1175bSopenharmony_ci * Modulo: r = A mod b 1558a8e1175bSopenharmony_ci */ 1559a8e1175bSopenharmony_ciint mbedtls_mpi_mod_int(mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b) 1560a8e1175bSopenharmony_ci{ 1561a8e1175bSopenharmony_ci size_t i; 1562a8e1175bSopenharmony_ci mbedtls_mpi_uint x, y, z; 1563a8e1175bSopenharmony_ci 1564a8e1175bSopenharmony_ci if (b == 0) { 1565a8e1175bSopenharmony_ci return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO; 1566a8e1175bSopenharmony_ci } 1567a8e1175bSopenharmony_ci 1568a8e1175bSopenharmony_ci if (b < 0) { 1569a8e1175bSopenharmony_ci return MBEDTLS_ERR_MPI_NEGATIVE_VALUE; 1570a8e1175bSopenharmony_ci } 1571a8e1175bSopenharmony_ci 1572a8e1175bSopenharmony_ci /* 1573a8e1175bSopenharmony_ci * handle trivial cases 1574a8e1175bSopenharmony_ci */ 1575a8e1175bSopenharmony_ci if (b == 1 || A->n == 0) { 1576a8e1175bSopenharmony_ci *r = 0; 1577a8e1175bSopenharmony_ci return 0; 1578a8e1175bSopenharmony_ci } 1579a8e1175bSopenharmony_ci 1580a8e1175bSopenharmony_ci if (b == 2) { 1581a8e1175bSopenharmony_ci *r = A->p[0] & 1; 1582a8e1175bSopenharmony_ci return 0; 1583a8e1175bSopenharmony_ci } 1584a8e1175bSopenharmony_ci 1585a8e1175bSopenharmony_ci /* 1586a8e1175bSopenharmony_ci * general case 1587a8e1175bSopenharmony_ci */ 1588a8e1175bSopenharmony_ci for (i = A->n, y = 0; i > 0; i--) { 1589a8e1175bSopenharmony_ci x = A->p[i - 1]; 1590a8e1175bSopenharmony_ci y = (y << biH) | (x >> biH); 1591a8e1175bSopenharmony_ci z = y / b; 1592a8e1175bSopenharmony_ci y -= z * b; 1593a8e1175bSopenharmony_ci 1594a8e1175bSopenharmony_ci x <<= biH; 1595a8e1175bSopenharmony_ci y = (y << biH) | (x >> biH); 1596a8e1175bSopenharmony_ci z = y / b; 1597a8e1175bSopenharmony_ci y -= z * b; 1598a8e1175bSopenharmony_ci } 1599a8e1175bSopenharmony_ci 1600a8e1175bSopenharmony_ci /* 1601a8e1175bSopenharmony_ci * If A is negative, then the current y represents a negative value. 1602a8e1175bSopenharmony_ci * Flipping it to the positive side. 1603a8e1175bSopenharmony_ci */ 1604a8e1175bSopenharmony_ci if (A->s < 0 && y != 0) { 1605a8e1175bSopenharmony_ci y = b - y; 1606a8e1175bSopenharmony_ci } 1607a8e1175bSopenharmony_ci 1608a8e1175bSopenharmony_ci *r = y; 1609a8e1175bSopenharmony_ci 1610a8e1175bSopenharmony_ci return 0; 1611a8e1175bSopenharmony_ci} 1612a8e1175bSopenharmony_ci 1613a8e1175bSopenharmony_ciint mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A, 1614a8e1175bSopenharmony_ci const mbedtls_mpi *E, const mbedtls_mpi *N, 1615a8e1175bSopenharmony_ci mbedtls_mpi *prec_RR) 1616a8e1175bSopenharmony_ci{ 1617a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1618a8e1175bSopenharmony_ci 1619a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_int(N, 0) <= 0 || (N->p[0] & 1) == 0) { 1620a8e1175bSopenharmony_ci return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 1621a8e1175bSopenharmony_ci } 1622a8e1175bSopenharmony_ci 1623a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_int(E, 0) < 0) { 1624a8e1175bSopenharmony_ci return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 1625a8e1175bSopenharmony_ci } 1626a8e1175bSopenharmony_ci 1627a8e1175bSopenharmony_ci if (mbedtls_mpi_bitlen(E) > MBEDTLS_MPI_MAX_BITS || 1628a8e1175bSopenharmony_ci mbedtls_mpi_bitlen(N) > MBEDTLS_MPI_MAX_BITS) { 1629a8e1175bSopenharmony_ci return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 1630a8e1175bSopenharmony_ci } 1631a8e1175bSopenharmony_ci 1632a8e1175bSopenharmony_ci /* 1633a8e1175bSopenharmony_ci * Ensure that the exponent that we are passing to the core is not NULL. 1634a8e1175bSopenharmony_ci */ 1635a8e1175bSopenharmony_ci if (E->n == 0) { 1636a8e1175bSopenharmony_ci ret = mbedtls_mpi_lset(X, 1); 1637a8e1175bSopenharmony_ci return ret; 1638a8e1175bSopenharmony_ci } 1639a8e1175bSopenharmony_ci 1640a8e1175bSopenharmony_ci /* 1641a8e1175bSopenharmony_ci * Allocate working memory for mbedtls_mpi_core_exp_mod() 1642a8e1175bSopenharmony_ci */ 1643a8e1175bSopenharmony_ci size_t T_limbs = mbedtls_mpi_core_exp_mod_working_limbs(N->n, E->n); 1644a8e1175bSopenharmony_ci mbedtls_mpi_uint *T = (mbedtls_mpi_uint *) mbedtls_calloc(T_limbs, sizeof(mbedtls_mpi_uint)); 1645a8e1175bSopenharmony_ci if (T == NULL) { 1646a8e1175bSopenharmony_ci return MBEDTLS_ERR_MPI_ALLOC_FAILED; 1647a8e1175bSopenharmony_ci } 1648a8e1175bSopenharmony_ci 1649a8e1175bSopenharmony_ci mbedtls_mpi RR; 1650a8e1175bSopenharmony_ci mbedtls_mpi_init(&RR); 1651a8e1175bSopenharmony_ci 1652a8e1175bSopenharmony_ci /* 1653a8e1175bSopenharmony_ci * If 1st call, pre-compute R^2 mod N 1654a8e1175bSopenharmony_ci */ 1655a8e1175bSopenharmony_ci if (prec_RR == NULL || prec_RR->p == NULL) { 1656a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_core_get_mont_r2_unsafe(&RR, N)); 1657a8e1175bSopenharmony_ci 1658a8e1175bSopenharmony_ci if (prec_RR != NULL) { 1659a8e1175bSopenharmony_ci *prec_RR = RR; 1660a8e1175bSopenharmony_ci } 1661a8e1175bSopenharmony_ci } else { 1662a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_grow(prec_RR, N->n)); 1663a8e1175bSopenharmony_ci RR = *prec_RR; 1664a8e1175bSopenharmony_ci } 1665a8e1175bSopenharmony_ci 1666a8e1175bSopenharmony_ci /* 1667a8e1175bSopenharmony_ci * To preserve constness we need to make a copy of A. Using X for this to 1668a8e1175bSopenharmony_ci * save memory. 1669a8e1175bSopenharmony_ci */ 1670a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A)); 1671a8e1175bSopenharmony_ci 1672a8e1175bSopenharmony_ci /* 1673a8e1175bSopenharmony_ci * Compensate for negative A (and correct at the end). 1674a8e1175bSopenharmony_ci */ 1675a8e1175bSopenharmony_ci X->s = 1; 1676a8e1175bSopenharmony_ci 1677a8e1175bSopenharmony_ci /* 1678a8e1175bSopenharmony_ci * Make sure that X is in a form that is safe for consumption by 1679a8e1175bSopenharmony_ci * the core functions. 1680a8e1175bSopenharmony_ci * 1681a8e1175bSopenharmony_ci * - The core functions will not touch the limbs of X above N->n. The 1682a8e1175bSopenharmony_ci * result will be correct if those limbs are 0, which the mod call 1683a8e1175bSopenharmony_ci * ensures. 1684a8e1175bSopenharmony_ci * - Also, X must have at least as many limbs as N for the calls to the 1685a8e1175bSopenharmony_ci * core functions. 1686a8e1175bSopenharmony_ci */ 1687a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_mpi(X, N) >= 0) { 1688a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(X, X, N)); 1689a8e1175bSopenharmony_ci } 1690a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, N->n)); 1691a8e1175bSopenharmony_ci 1692a8e1175bSopenharmony_ci /* 1693a8e1175bSopenharmony_ci * Convert to and from Montgomery around mbedtls_mpi_core_exp_mod(). 1694a8e1175bSopenharmony_ci */ 1695a8e1175bSopenharmony_ci { 1696a8e1175bSopenharmony_ci mbedtls_mpi_uint mm = mbedtls_mpi_core_montmul_init(N->p); 1697a8e1175bSopenharmony_ci mbedtls_mpi_core_to_mont_rep(X->p, X->p, N->p, N->n, mm, RR.p, T); 1698a8e1175bSopenharmony_ci mbedtls_mpi_core_exp_mod(X->p, X->p, N->p, N->n, E->p, E->n, RR.p, T); 1699a8e1175bSopenharmony_ci mbedtls_mpi_core_from_mont_rep(X->p, X->p, N->p, N->n, mm, T); 1700a8e1175bSopenharmony_ci } 1701a8e1175bSopenharmony_ci 1702a8e1175bSopenharmony_ci /* 1703a8e1175bSopenharmony_ci * Correct for negative A. 1704a8e1175bSopenharmony_ci */ 1705a8e1175bSopenharmony_ci if (A->s == -1 && (E->p[0] & 1) != 0) { 1706a8e1175bSopenharmony_ci mbedtls_ct_condition_t is_x_non_zero = mbedtls_mpi_core_check_zero_ct(X->p, X->n); 1707a8e1175bSopenharmony_ci X->s = mbedtls_ct_mpi_sign_if(is_x_non_zero, -1, 1); 1708a8e1175bSopenharmony_ci 1709a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(X, N, X)); 1710a8e1175bSopenharmony_ci } 1711a8e1175bSopenharmony_ci 1712a8e1175bSopenharmony_cicleanup: 1713a8e1175bSopenharmony_ci 1714a8e1175bSopenharmony_ci mbedtls_mpi_zeroize_and_free(T, T_limbs); 1715a8e1175bSopenharmony_ci 1716a8e1175bSopenharmony_ci if (prec_RR == NULL || prec_RR->p == NULL) { 1717a8e1175bSopenharmony_ci mbedtls_mpi_free(&RR); 1718a8e1175bSopenharmony_ci } 1719a8e1175bSopenharmony_ci 1720a8e1175bSopenharmony_ci return ret; 1721a8e1175bSopenharmony_ci} 1722a8e1175bSopenharmony_ci 1723a8e1175bSopenharmony_ci/* 1724a8e1175bSopenharmony_ci * Greatest common divisor: G = gcd(A, B) (HAC 14.54) 1725a8e1175bSopenharmony_ci */ 1726a8e1175bSopenharmony_ciint mbedtls_mpi_gcd(mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B) 1727a8e1175bSopenharmony_ci{ 1728a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1729a8e1175bSopenharmony_ci size_t lz, lzt; 1730a8e1175bSopenharmony_ci mbedtls_mpi TA, TB; 1731a8e1175bSopenharmony_ci 1732a8e1175bSopenharmony_ci mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TB); 1733a8e1175bSopenharmony_ci 1734a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A)); 1735a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B)); 1736a8e1175bSopenharmony_ci 1737a8e1175bSopenharmony_ci lz = mbedtls_mpi_lsb(&TA); 1738a8e1175bSopenharmony_ci lzt = mbedtls_mpi_lsb(&TB); 1739a8e1175bSopenharmony_ci 1740a8e1175bSopenharmony_ci /* The loop below gives the correct result when A==0 but not when B==0. 1741a8e1175bSopenharmony_ci * So have a special case for B==0. Leverage the fact that we just 1742a8e1175bSopenharmony_ci * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test 1743a8e1175bSopenharmony_ci * slightly more efficient than cmp_int(). */ 1744a8e1175bSopenharmony_ci if (lzt == 0 && mbedtls_mpi_get_bit(&TB, 0) == 0) { 1745a8e1175bSopenharmony_ci ret = mbedtls_mpi_copy(G, A); 1746a8e1175bSopenharmony_ci goto cleanup; 1747a8e1175bSopenharmony_ci } 1748a8e1175bSopenharmony_ci 1749a8e1175bSopenharmony_ci if (lzt < lz) { 1750a8e1175bSopenharmony_ci lz = lzt; 1751a8e1175bSopenharmony_ci } 1752a8e1175bSopenharmony_ci 1753a8e1175bSopenharmony_ci TA.s = TB.s = 1; 1754a8e1175bSopenharmony_ci 1755a8e1175bSopenharmony_ci /* We mostly follow the procedure described in HAC 14.54, but with some 1756a8e1175bSopenharmony_ci * minor differences: 1757a8e1175bSopenharmony_ci * - Sequences of multiplications or divisions by 2 are grouped into a 1758a8e1175bSopenharmony_ci * single shift operation. 1759a8e1175bSopenharmony_ci * - The procedure in HAC assumes that 0 < TB <= TA. 1760a8e1175bSopenharmony_ci * - The condition TB <= TA is not actually necessary for correctness. 1761a8e1175bSopenharmony_ci * TA and TB have symmetric roles except for the loop termination 1762a8e1175bSopenharmony_ci * condition, and the shifts at the beginning of the loop body 1763a8e1175bSopenharmony_ci * remove any significance from the ordering of TA vs TB before 1764a8e1175bSopenharmony_ci * the shifts. 1765a8e1175bSopenharmony_ci * - If TA = 0, the loop goes through 0 iterations and the result is 1766a8e1175bSopenharmony_ci * correctly TB. 1767a8e1175bSopenharmony_ci * - The case TB = 0 was short-circuited above. 1768a8e1175bSopenharmony_ci * 1769a8e1175bSopenharmony_ci * For the correctness proof below, decompose the original values of 1770a8e1175bSopenharmony_ci * A and B as 1771a8e1175bSopenharmony_ci * A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1 1772a8e1175bSopenharmony_ci * B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1 1773a8e1175bSopenharmony_ci * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'), 1774a8e1175bSopenharmony_ci * and gcd(A',B') is odd or 0. 1775a8e1175bSopenharmony_ci * 1776a8e1175bSopenharmony_ci * At the beginning, we have TA = |A| and TB = |B| so gcd(A,B) = gcd(TA,TB). 1777a8e1175bSopenharmony_ci * The code maintains the following invariant: 1778a8e1175bSopenharmony_ci * gcd(A,B) = 2^k * gcd(TA,TB) for some k (I) 1779a8e1175bSopenharmony_ci */ 1780a8e1175bSopenharmony_ci 1781a8e1175bSopenharmony_ci /* Proof that the loop terminates: 1782a8e1175bSopenharmony_ci * At each iteration, either the right-shift by 1 is made on a nonzero 1783a8e1175bSopenharmony_ci * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases 1784a8e1175bSopenharmony_ci * by at least 1, or the right-shift by 1 is made on zero and then 1785a8e1175bSopenharmony_ci * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted 1786a8e1175bSopenharmony_ci * since in that case TB is calculated from TB-TA with the condition TB>TA). 1787a8e1175bSopenharmony_ci */ 1788a8e1175bSopenharmony_ci while (mbedtls_mpi_cmp_int(&TA, 0) != 0) { 1789a8e1175bSopenharmony_ci /* Divisions by 2 preserve the invariant (I). */ 1790a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, mbedtls_mpi_lsb(&TA))); 1791a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, mbedtls_mpi_lsb(&TB))); 1792a8e1175bSopenharmony_ci 1793a8e1175bSopenharmony_ci /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd, 1794a8e1175bSopenharmony_ci * TA-TB is even so the division by 2 has an integer result. 1795a8e1175bSopenharmony_ci * Invariant (I) is preserved since any odd divisor of both TA and TB 1796a8e1175bSopenharmony_ci * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2 1797a8e1175bSopenharmony_ci * also divides TB, and any odd divisor of both TB and |TA-TB|/2 also 1798a8e1175bSopenharmony_ci * divides TA. 1799a8e1175bSopenharmony_ci */ 1800a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_mpi(&TA, &TB) >= 0) { 1801a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TA, &TA, &TB)); 1802a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, 1)); 1803a8e1175bSopenharmony_ci } else { 1804a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TB, &TB, &TA)); 1805a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, 1)); 1806a8e1175bSopenharmony_ci } 1807a8e1175bSopenharmony_ci /* Note that one of TA or TB is still odd. */ 1808a8e1175bSopenharmony_ci } 1809a8e1175bSopenharmony_ci 1810a8e1175bSopenharmony_ci /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k. 1811a8e1175bSopenharmony_ci * At the loop exit, TA = 0, so gcd(TA,TB) = TB. 1812a8e1175bSopenharmony_ci * - If there was at least one loop iteration, then one of TA or TB is odd, 1813a8e1175bSopenharmony_ci * and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case, 1814a8e1175bSopenharmony_ci * lz = min(a,b) so gcd(A,B) = 2^lz * TB. 1815a8e1175bSopenharmony_ci * - If there was no loop iteration, then A was 0, and gcd(A,B) = B. 1816a8e1175bSopenharmony_ci * In this case, lz = 0 and B = TB so gcd(A,B) = B = 2^lz * TB as well. 1817a8e1175bSopenharmony_ci */ 1818a8e1175bSopenharmony_ci 1819a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&TB, lz)); 1820a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_copy(G, &TB)); 1821a8e1175bSopenharmony_ci 1822a8e1175bSopenharmony_cicleanup: 1823a8e1175bSopenharmony_ci 1824a8e1175bSopenharmony_ci mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TB); 1825a8e1175bSopenharmony_ci 1826a8e1175bSopenharmony_ci return ret; 1827a8e1175bSopenharmony_ci} 1828a8e1175bSopenharmony_ci 1829a8e1175bSopenharmony_ci/* 1830a8e1175bSopenharmony_ci * Fill X with size bytes of random. 1831a8e1175bSopenharmony_ci * The bytes returned from the RNG are used in a specific order which 1832a8e1175bSopenharmony_ci * is suitable for deterministic ECDSA (see the specification of 1833a8e1175bSopenharmony_ci * mbedtls_mpi_random() and the implementation in mbedtls_mpi_fill_random()). 1834a8e1175bSopenharmony_ci */ 1835a8e1175bSopenharmony_ciint mbedtls_mpi_fill_random(mbedtls_mpi *X, size_t size, 1836a8e1175bSopenharmony_ci int (*f_rng)(void *, unsigned char *, size_t), 1837a8e1175bSopenharmony_ci void *p_rng) 1838a8e1175bSopenharmony_ci{ 1839a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1840a8e1175bSopenharmony_ci const size_t limbs = CHARS_TO_LIMBS(size); 1841a8e1175bSopenharmony_ci 1842a8e1175bSopenharmony_ci /* Ensure that target MPI has exactly the necessary number of limbs */ 1843a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs)); 1844a8e1175bSopenharmony_ci if (size == 0) { 1845a8e1175bSopenharmony_ci return 0; 1846a8e1175bSopenharmony_ci } 1847a8e1175bSopenharmony_ci 1848a8e1175bSopenharmony_ci ret = mbedtls_mpi_core_fill_random(X->p, X->n, size, f_rng, p_rng); 1849a8e1175bSopenharmony_ci 1850a8e1175bSopenharmony_cicleanup: 1851a8e1175bSopenharmony_ci return ret; 1852a8e1175bSopenharmony_ci} 1853a8e1175bSopenharmony_ci 1854a8e1175bSopenharmony_ciint mbedtls_mpi_random(mbedtls_mpi *X, 1855a8e1175bSopenharmony_ci mbedtls_mpi_sint min, 1856a8e1175bSopenharmony_ci const mbedtls_mpi *N, 1857a8e1175bSopenharmony_ci int (*f_rng)(void *, unsigned char *, size_t), 1858a8e1175bSopenharmony_ci void *p_rng) 1859a8e1175bSopenharmony_ci{ 1860a8e1175bSopenharmony_ci if (min < 0) { 1861a8e1175bSopenharmony_ci return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 1862a8e1175bSopenharmony_ci } 1863a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_int(N, min) <= 0) { 1864a8e1175bSopenharmony_ci return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 1865a8e1175bSopenharmony_ci } 1866a8e1175bSopenharmony_ci 1867a8e1175bSopenharmony_ci /* Ensure that target MPI has exactly the same number of limbs 1868a8e1175bSopenharmony_ci * as the upper bound, even if the upper bound has leading zeros. 1869a8e1175bSopenharmony_ci * This is necessary for mbedtls_mpi_core_random. */ 1870a8e1175bSopenharmony_ci int ret = mbedtls_mpi_resize_clear(X, N->n); 1871a8e1175bSopenharmony_ci if (ret != 0) { 1872a8e1175bSopenharmony_ci return ret; 1873a8e1175bSopenharmony_ci } 1874a8e1175bSopenharmony_ci 1875a8e1175bSopenharmony_ci return mbedtls_mpi_core_random(X->p, min, N->p, X->n, f_rng, p_rng); 1876a8e1175bSopenharmony_ci} 1877a8e1175bSopenharmony_ci 1878a8e1175bSopenharmony_ci/* 1879a8e1175bSopenharmony_ci * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64) 1880a8e1175bSopenharmony_ci */ 1881a8e1175bSopenharmony_ciint mbedtls_mpi_inv_mod(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N) 1882a8e1175bSopenharmony_ci{ 1883a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1884a8e1175bSopenharmony_ci mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2; 1885a8e1175bSopenharmony_ci 1886a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_int(N, 1) <= 0) { 1887a8e1175bSopenharmony_ci return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 1888a8e1175bSopenharmony_ci } 1889a8e1175bSopenharmony_ci 1890a8e1175bSopenharmony_ci mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TU); mbedtls_mpi_init(&U1); mbedtls_mpi_init(&U2); 1891a8e1175bSopenharmony_ci mbedtls_mpi_init(&G); mbedtls_mpi_init(&TB); mbedtls_mpi_init(&TV); 1892a8e1175bSopenharmony_ci mbedtls_mpi_init(&V1); mbedtls_mpi_init(&V2); 1893a8e1175bSopenharmony_ci 1894a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&G, A, N)); 1895a8e1175bSopenharmony_ci 1896a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_int(&G, 1) != 0) { 1897a8e1175bSopenharmony_ci ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; 1898a8e1175bSopenharmony_ci goto cleanup; 1899a8e1175bSopenharmony_ci } 1900a8e1175bSopenharmony_ci 1901a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&TA, A, N)); 1902a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TU, &TA)); 1903a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, N)); 1904a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TV, N)); 1905a8e1175bSopenharmony_ci 1906a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U1, 1)); 1907a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U2, 0)); 1908a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V1, 0)); 1909a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V2, 1)); 1910a8e1175bSopenharmony_ci 1911a8e1175bSopenharmony_ci do { 1912a8e1175bSopenharmony_ci while ((TU.p[0] & 1) == 0) { 1913a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TU, 1)); 1914a8e1175bSopenharmony_ci 1915a8e1175bSopenharmony_ci if ((U1.p[0] & 1) != 0 || (U2.p[0] & 1) != 0) { 1916a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&U1, &U1, &TB)); 1917a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &TA)); 1918a8e1175bSopenharmony_ci } 1919a8e1175bSopenharmony_ci 1920a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U1, 1)); 1921a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U2, 1)); 1922a8e1175bSopenharmony_ci } 1923a8e1175bSopenharmony_ci 1924a8e1175bSopenharmony_ci while ((TV.p[0] & 1) == 0) { 1925a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TV, 1)); 1926a8e1175bSopenharmony_ci 1927a8e1175bSopenharmony_ci if ((V1.p[0] & 1) != 0 || (V2.p[0] & 1) != 0) { 1928a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, &TB)); 1929a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &TA)); 1930a8e1175bSopenharmony_ci } 1931a8e1175bSopenharmony_ci 1932a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V1, 1)); 1933a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V2, 1)); 1934a8e1175bSopenharmony_ci } 1935a8e1175bSopenharmony_ci 1936a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_mpi(&TU, &TV) >= 0) { 1937a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TU, &TU, &TV)); 1938a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U1, &U1, &V1)); 1939a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &V2)); 1940a8e1175bSopenharmony_ci } else { 1941a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TV, &TV, &TU)); 1942a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, &U1)); 1943a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &U2)); 1944a8e1175bSopenharmony_ci } 1945a8e1175bSopenharmony_ci } while (mbedtls_mpi_cmp_int(&TU, 0) != 0); 1946a8e1175bSopenharmony_ci 1947a8e1175bSopenharmony_ci while (mbedtls_mpi_cmp_int(&V1, 0) < 0) { 1948a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, N)); 1949a8e1175bSopenharmony_ci } 1950a8e1175bSopenharmony_ci 1951a8e1175bSopenharmony_ci while (mbedtls_mpi_cmp_mpi(&V1, N) >= 0) { 1952a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, N)); 1953a8e1175bSopenharmony_ci } 1954a8e1175bSopenharmony_ci 1955a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &V1)); 1956a8e1175bSopenharmony_ci 1957a8e1175bSopenharmony_cicleanup: 1958a8e1175bSopenharmony_ci 1959a8e1175bSopenharmony_ci mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TU); mbedtls_mpi_free(&U1); mbedtls_mpi_free(&U2); 1960a8e1175bSopenharmony_ci mbedtls_mpi_free(&G); mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TV); 1961a8e1175bSopenharmony_ci mbedtls_mpi_free(&V1); mbedtls_mpi_free(&V2); 1962a8e1175bSopenharmony_ci 1963a8e1175bSopenharmony_ci return ret; 1964a8e1175bSopenharmony_ci} 1965a8e1175bSopenharmony_ci 1966a8e1175bSopenharmony_ci#if defined(MBEDTLS_GENPRIME) 1967a8e1175bSopenharmony_ci 1968a8e1175bSopenharmony_ci/* Gaps between primes, starting at 3. https://oeis.org/A001223 */ 1969a8e1175bSopenharmony_cistatic const unsigned char small_prime_gaps[] = { 1970a8e1175bSopenharmony_ci 2, 2, 4, 2, 4, 2, 4, 6, 1971a8e1175bSopenharmony_ci 2, 6, 4, 2, 4, 6, 6, 2, 1972a8e1175bSopenharmony_ci 6, 4, 2, 6, 4, 6, 8, 4, 1973a8e1175bSopenharmony_ci 2, 4, 2, 4, 14, 4, 6, 2, 1974a8e1175bSopenharmony_ci 10, 2, 6, 6, 4, 6, 6, 2, 1975a8e1175bSopenharmony_ci 10, 2, 4, 2, 12, 12, 4, 2, 1976a8e1175bSopenharmony_ci 4, 6, 2, 10, 6, 6, 6, 2, 1977a8e1175bSopenharmony_ci 6, 4, 2, 10, 14, 4, 2, 4, 1978a8e1175bSopenharmony_ci 14, 6, 10, 2, 4, 6, 8, 6, 1979a8e1175bSopenharmony_ci 6, 4, 6, 8, 4, 8, 10, 2, 1980a8e1175bSopenharmony_ci 10, 2, 6, 4, 6, 8, 4, 2, 1981a8e1175bSopenharmony_ci 4, 12, 8, 4, 8, 4, 6, 12, 1982a8e1175bSopenharmony_ci 2, 18, 6, 10, 6, 6, 2, 6, 1983a8e1175bSopenharmony_ci 10, 6, 6, 2, 6, 6, 4, 2, 1984a8e1175bSopenharmony_ci 12, 10, 2, 4, 6, 6, 2, 12, 1985a8e1175bSopenharmony_ci 4, 6, 8, 10, 8, 10, 8, 6, 1986a8e1175bSopenharmony_ci 6, 4, 8, 6, 4, 8, 4, 14, 1987a8e1175bSopenharmony_ci 10, 12, 2, 10, 2, 4, 2, 10, 1988a8e1175bSopenharmony_ci 14, 4, 2, 4, 14, 4, 2, 4, 1989a8e1175bSopenharmony_ci 20, 4, 8, 10, 8, 4, 6, 6, 1990a8e1175bSopenharmony_ci 14, 4, 6, 6, 8, 6, /*reaches 997*/ 1991a8e1175bSopenharmony_ci 0 /* the last entry is effectively unused */ 1992a8e1175bSopenharmony_ci}; 1993a8e1175bSopenharmony_ci 1994a8e1175bSopenharmony_ci/* 1995a8e1175bSopenharmony_ci * Small divisors test (X must be positive) 1996a8e1175bSopenharmony_ci * 1997a8e1175bSopenharmony_ci * Return values: 1998a8e1175bSopenharmony_ci * 0: no small factor (possible prime, more tests needed) 1999a8e1175bSopenharmony_ci * 1: certain prime 2000a8e1175bSopenharmony_ci * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime 2001a8e1175bSopenharmony_ci * other negative: error 2002a8e1175bSopenharmony_ci */ 2003a8e1175bSopenharmony_cistatic int mpi_check_small_factors(const mbedtls_mpi *X) 2004a8e1175bSopenharmony_ci{ 2005a8e1175bSopenharmony_ci int ret = 0; 2006a8e1175bSopenharmony_ci size_t i; 2007a8e1175bSopenharmony_ci mbedtls_mpi_uint r; 2008a8e1175bSopenharmony_ci unsigned p = 3; /* The first odd prime */ 2009a8e1175bSopenharmony_ci 2010a8e1175bSopenharmony_ci if ((X->p[0] & 1) == 0) { 2011a8e1175bSopenharmony_ci return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; 2012a8e1175bSopenharmony_ci } 2013a8e1175bSopenharmony_ci 2014a8e1175bSopenharmony_ci for (i = 0; i < sizeof(small_prime_gaps); p += small_prime_gaps[i], i++) { 2015a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, p)); 2016a8e1175bSopenharmony_ci if (r == 0) { 2017a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_int(X, p) == 0) { 2018a8e1175bSopenharmony_ci return 1; 2019a8e1175bSopenharmony_ci } else { 2020a8e1175bSopenharmony_ci return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; 2021a8e1175bSopenharmony_ci } 2022a8e1175bSopenharmony_ci } 2023a8e1175bSopenharmony_ci } 2024a8e1175bSopenharmony_ci 2025a8e1175bSopenharmony_cicleanup: 2026a8e1175bSopenharmony_ci return ret; 2027a8e1175bSopenharmony_ci} 2028a8e1175bSopenharmony_ci 2029a8e1175bSopenharmony_ci/* 2030a8e1175bSopenharmony_ci * Miller-Rabin pseudo-primality test (HAC 4.24) 2031a8e1175bSopenharmony_ci */ 2032a8e1175bSopenharmony_cistatic int mpi_miller_rabin(const mbedtls_mpi *X, size_t rounds, 2033a8e1175bSopenharmony_ci int (*f_rng)(void *, unsigned char *, size_t), 2034a8e1175bSopenharmony_ci void *p_rng) 2035a8e1175bSopenharmony_ci{ 2036a8e1175bSopenharmony_ci int ret, count; 2037a8e1175bSopenharmony_ci size_t i, j, k, s; 2038a8e1175bSopenharmony_ci mbedtls_mpi W, R, T, A, RR; 2039a8e1175bSopenharmony_ci 2040a8e1175bSopenharmony_ci mbedtls_mpi_init(&W); mbedtls_mpi_init(&R); 2041a8e1175bSopenharmony_ci mbedtls_mpi_init(&T); mbedtls_mpi_init(&A); 2042a8e1175bSopenharmony_ci mbedtls_mpi_init(&RR); 2043a8e1175bSopenharmony_ci 2044a8e1175bSopenharmony_ci /* 2045a8e1175bSopenharmony_ci * W = |X| - 1 2046a8e1175bSopenharmony_ci * R = W >> lsb( W ) 2047a8e1175bSopenharmony_ci */ 2048a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&W, X, 1)); 2049a8e1175bSopenharmony_ci s = mbedtls_mpi_lsb(&W); 2050a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&R, &W)); 2051a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&R, s)); 2052a8e1175bSopenharmony_ci 2053a8e1175bSopenharmony_ci for (i = 0; i < rounds; i++) { 2054a8e1175bSopenharmony_ci /* 2055a8e1175bSopenharmony_ci * pick a random A, 1 < A < |X| - 1 2056a8e1175bSopenharmony_ci */ 2057a8e1175bSopenharmony_ci count = 0; 2058a8e1175bSopenharmony_ci do { 2059a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&A, X->n * ciL, f_rng, p_rng)); 2060a8e1175bSopenharmony_ci 2061a8e1175bSopenharmony_ci j = mbedtls_mpi_bitlen(&A); 2062a8e1175bSopenharmony_ci k = mbedtls_mpi_bitlen(&W); 2063a8e1175bSopenharmony_ci if (j > k) { 2064a8e1175bSopenharmony_ci A.p[A.n - 1] &= ((mbedtls_mpi_uint) 1 << (k - (A.n - 1) * biL - 1)) - 1; 2065a8e1175bSopenharmony_ci } 2066a8e1175bSopenharmony_ci 2067a8e1175bSopenharmony_ci if (count++ > 30) { 2068a8e1175bSopenharmony_ci ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; 2069a8e1175bSopenharmony_ci goto cleanup; 2070a8e1175bSopenharmony_ci } 2071a8e1175bSopenharmony_ci 2072a8e1175bSopenharmony_ci } while (mbedtls_mpi_cmp_mpi(&A, &W) >= 0 || 2073a8e1175bSopenharmony_ci mbedtls_mpi_cmp_int(&A, 1) <= 0); 2074a8e1175bSopenharmony_ci 2075a8e1175bSopenharmony_ci /* 2076a8e1175bSopenharmony_ci * A = A^R mod |X| 2077a8e1175bSopenharmony_ci */ 2078a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&A, &A, &R, X, &RR)); 2079a8e1175bSopenharmony_ci 2080a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_mpi(&A, &W) == 0 || 2081a8e1175bSopenharmony_ci mbedtls_mpi_cmp_int(&A, 1) == 0) { 2082a8e1175bSopenharmony_ci continue; 2083a8e1175bSopenharmony_ci } 2084a8e1175bSopenharmony_ci 2085a8e1175bSopenharmony_ci j = 1; 2086a8e1175bSopenharmony_ci while (j < s && mbedtls_mpi_cmp_mpi(&A, &W) != 0) { 2087a8e1175bSopenharmony_ci /* 2088a8e1175bSopenharmony_ci * A = A * A mod |X| 2089a8e1175bSopenharmony_ci */ 2090a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &A, &A)); 2091a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&A, &T, X)); 2092a8e1175bSopenharmony_ci 2093a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_int(&A, 1) == 0) { 2094a8e1175bSopenharmony_ci break; 2095a8e1175bSopenharmony_ci } 2096a8e1175bSopenharmony_ci 2097a8e1175bSopenharmony_ci j++; 2098a8e1175bSopenharmony_ci } 2099a8e1175bSopenharmony_ci 2100a8e1175bSopenharmony_ci /* 2101a8e1175bSopenharmony_ci * not prime if A != |X| - 1 or A == 1 2102a8e1175bSopenharmony_ci */ 2103a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_mpi(&A, &W) != 0 || 2104a8e1175bSopenharmony_ci mbedtls_mpi_cmp_int(&A, 1) == 0) { 2105a8e1175bSopenharmony_ci ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; 2106a8e1175bSopenharmony_ci break; 2107a8e1175bSopenharmony_ci } 2108a8e1175bSopenharmony_ci } 2109a8e1175bSopenharmony_ci 2110a8e1175bSopenharmony_cicleanup: 2111a8e1175bSopenharmony_ci mbedtls_mpi_free(&W); mbedtls_mpi_free(&R); 2112a8e1175bSopenharmony_ci mbedtls_mpi_free(&T); mbedtls_mpi_free(&A); 2113a8e1175bSopenharmony_ci mbedtls_mpi_free(&RR); 2114a8e1175bSopenharmony_ci 2115a8e1175bSopenharmony_ci return ret; 2116a8e1175bSopenharmony_ci} 2117a8e1175bSopenharmony_ci 2118a8e1175bSopenharmony_ci/* 2119a8e1175bSopenharmony_ci * Pseudo-primality test: small factors, then Miller-Rabin 2120a8e1175bSopenharmony_ci */ 2121a8e1175bSopenharmony_ciint mbedtls_mpi_is_prime_ext(const mbedtls_mpi *X, int rounds, 2122a8e1175bSopenharmony_ci int (*f_rng)(void *, unsigned char *, size_t), 2123a8e1175bSopenharmony_ci void *p_rng) 2124a8e1175bSopenharmony_ci{ 2125a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 2126a8e1175bSopenharmony_ci mbedtls_mpi XX; 2127a8e1175bSopenharmony_ci 2128a8e1175bSopenharmony_ci XX.s = 1; 2129a8e1175bSopenharmony_ci XX.n = X->n; 2130a8e1175bSopenharmony_ci XX.p = X->p; 2131a8e1175bSopenharmony_ci 2132a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_int(&XX, 0) == 0 || 2133a8e1175bSopenharmony_ci mbedtls_mpi_cmp_int(&XX, 1) == 0) { 2134a8e1175bSopenharmony_ci return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; 2135a8e1175bSopenharmony_ci } 2136a8e1175bSopenharmony_ci 2137a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_int(&XX, 2) == 0) { 2138a8e1175bSopenharmony_ci return 0; 2139a8e1175bSopenharmony_ci } 2140a8e1175bSopenharmony_ci 2141a8e1175bSopenharmony_ci if ((ret = mpi_check_small_factors(&XX)) != 0) { 2142a8e1175bSopenharmony_ci if (ret == 1) { 2143a8e1175bSopenharmony_ci return 0; 2144a8e1175bSopenharmony_ci } 2145a8e1175bSopenharmony_ci 2146a8e1175bSopenharmony_ci return ret; 2147a8e1175bSopenharmony_ci } 2148a8e1175bSopenharmony_ci 2149a8e1175bSopenharmony_ci return mpi_miller_rabin(&XX, rounds, f_rng, p_rng); 2150a8e1175bSopenharmony_ci} 2151a8e1175bSopenharmony_ci 2152a8e1175bSopenharmony_ci/* 2153a8e1175bSopenharmony_ci * Prime number generation 2154a8e1175bSopenharmony_ci * 2155a8e1175bSopenharmony_ci * To generate an RSA key in a way recommended by FIPS 186-4, both primes must 2156a8e1175bSopenharmony_ci * be either 1024 bits or 1536 bits long, and flags must contain 2157a8e1175bSopenharmony_ci * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR. 2158a8e1175bSopenharmony_ci */ 2159a8e1175bSopenharmony_ciint mbedtls_mpi_gen_prime(mbedtls_mpi *X, size_t nbits, int flags, 2160a8e1175bSopenharmony_ci int (*f_rng)(void *, unsigned char *, size_t), 2161a8e1175bSopenharmony_ci void *p_rng) 2162a8e1175bSopenharmony_ci{ 2163a8e1175bSopenharmony_ci#ifdef MBEDTLS_HAVE_INT64 2164a8e1175bSopenharmony_ci// ceil(2^63.5) 2165a8e1175bSopenharmony_ci#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL 2166a8e1175bSopenharmony_ci#else 2167a8e1175bSopenharmony_ci// ceil(2^31.5) 2168a8e1175bSopenharmony_ci#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U 2169a8e1175bSopenharmony_ci#endif 2170a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; 2171a8e1175bSopenharmony_ci size_t k, n; 2172a8e1175bSopenharmony_ci int rounds; 2173a8e1175bSopenharmony_ci mbedtls_mpi_uint r; 2174a8e1175bSopenharmony_ci mbedtls_mpi Y; 2175a8e1175bSopenharmony_ci 2176a8e1175bSopenharmony_ci if (nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS) { 2177a8e1175bSopenharmony_ci return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 2178a8e1175bSopenharmony_ci } 2179a8e1175bSopenharmony_ci 2180a8e1175bSopenharmony_ci mbedtls_mpi_init(&Y); 2181a8e1175bSopenharmony_ci 2182a8e1175bSopenharmony_ci n = BITS_TO_LIMBS(nbits); 2183a8e1175bSopenharmony_ci 2184a8e1175bSopenharmony_ci if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR) == 0) { 2185a8e1175bSopenharmony_ci /* 2186a8e1175bSopenharmony_ci * 2^-80 error probability, number of rounds chosen per HAC, table 4.4 2187a8e1175bSopenharmony_ci */ 2188a8e1175bSopenharmony_ci rounds = ((nbits >= 1300) ? 2 : (nbits >= 850) ? 3 : 2189a8e1175bSopenharmony_ci (nbits >= 650) ? 4 : (nbits >= 350) ? 8 : 2190a8e1175bSopenharmony_ci (nbits >= 250) ? 12 : (nbits >= 150) ? 18 : 27); 2191a8e1175bSopenharmony_ci } else { 2192a8e1175bSopenharmony_ci /* 2193a8e1175bSopenharmony_ci * 2^-100 error probability, number of rounds computed based on HAC, 2194a8e1175bSopenharmony_ci * fact 4.48 2195a8e1175bSopenharmony_ci */ 2196a8e1175bSopenharmony_ci rounds = ((nbits >= 1450) ? 4 : (nbits >= 1150) ? 5 : 2197a8e1175bSopenharmony_ci (nbits >= 1000) ? 6 : (nbits >= 850) ? 7 : 2198a8e1175bSopenharmony_ci (nbits >= 750) ? 8 : (nbits >= 500) ? 13 : 2199a8e1175bSopenharmony_ci (nbits >= 250) ? 28 : (nbits >= 150) ? 40 : 51); 2200a8e1175bSopenharmony_ci } 2201a8e1175bSopenharmony_ci 2202a8e1175bSopenharmony_ci while (1) { 2203a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(X, n * ciL, f_rng, p_rng)); 2204a8e1175bSopenharmony_ci /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 �B.3.3 steps 4.4, 5.5) */ 2205a8e1175bSopenharmony_ci if (X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2) { 2206a8e1175bSopenharmony_ci continue; 2207a8e1175bSopenharmony_ci } 2208a8e1175bSopenharmony_ci 2209a8e1175bSopenharmony_ci k = n * biL; 2210a8e1175bSopenharmony_ci if (k > nbits) { 2211a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(X, k - nbits)); 2212a8e1175bSopenharmony_ci } 2213a8e1175bSopenharmony_ci X->p[0] |= 1; 2214a8e1175bSopenharmony_ci 2215a8e1175bSopenharmony_ci if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH) == 0) { 2216a8e1175bSopenharmony_ci ret = mbedtls_mpi_is_prime_ext(X, rounds, f_rng, p_rng); 2217a8e1175bSopenharmony_ci 2218a8e1175bSopenharmony_ci if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) { 2219a8e1175bSopenharmony_ci goto cleanup; 2220a8e1175bSopenharmony_ci } 2221a8e1175bSopenharmony_ci } else { 2222a8e1175bSopenharmony_ci /* 2223a8e1175bSopenharmony_ci * A necessary condition for Y and X = 2Y + 1 to be prime 2224a8e1175bSopenharmony_ci * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3). 2225a8e1175bSopenharmony_ci * Make sure it is satisfied, while keeping X = 3 mod 4 2226a8e1175bSopenharmony_ci */ 2227a8e1175bSopenharmony_ci 2228a8e1175bSopenharmony_ci X->p[0] |= 2; 2229a8e1175bSopenharmony_ci 2230a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, 3)); 2231a8e1175bSopenharmony_ci if (r == 0) { 2232a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 8)); 2233a8e1175bSopenharmony_ci } else if (r == 1) { 2234a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 4)); 2235a8e1175bSopenharmony_ci } 2236a8e1175bSopenharmony_ci 2237a8e1175bSopenharmony_ci /* Set Y = (X-1) / 2, which is X / 2 because X is odd */ 2238a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, X)); 2239a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, 1)); 2240a8e1175bSopenharmony_ci 2241a8e1175bSopenharmony_ci while (1) { 2242a8e1175bSopenharmony_ci /* 2243a8e1175bSopenharmony_ci * First, check small factors for X and Y 2244a8e1175bSopenharmony_ci * before doing Miller-Rabin on any of them 2245a8e1175bSopenharmony_ci */ 2246a8e1175bSopenharmony_ci if ((ret = mpi_check_small_factors(X)) == 0 && 2247a8e1175bSopenharmony_ci (ret = mpi_check_small_factors(&Y)) == 0 && 2248a8e1175bSopenharmony_ci (ret = mpi_miller_rabin(X, rounds, f_rng, p_rng)) 2249a8e1175bSopenharmony_ci == 0 && 2250a8e1175bSopenharmony_ci (ret = mpi_miller_rabin(&Y, rounds, f_rng, p_rng)) 2251a8e1175bSopenharmony_ci == 0) { 2252a8e1175bSopenharmony_ci goto cleanup; 2253a8e1175bSopenharmony_ci } 2254a8e1175bSopenharmony_ci 2255a8e1175bSopenharmony_ci if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) { 2256a8e1175bSopenharmony_ci goto cleanup; 2257a8e1175bSopenharmony_ci } 2258a8e1175bSopenharmony_ci 2259a8e1175bSopenharmony_ci /* 2260a8e1175bSopenharmony_ci * Next candidates. We want to preserve Y = (X-1) / 2 and 2261a8e1175bSopenharmony_ci * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3) 2262a8e1175bSopenharmony_ci * so up Y by 6 and X by 12. 2263a8e1175bSopenharmony_ci */ 2264a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 12)); 2265a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&Y, &Y, 6)); 2266a8e1175bSopenharmony_ci } 2267a8e1175bSopenharmony_ci } 2268a8e1175bSopenharmony_ci } 2269a8e1175bSopenharmony_ci 2270a8e1175bSopenharmony_cicleanup: 2271a8e1175bSopenharmony_ci 2272a8e1175bSopenharmony_ci mbedtls_mpi_free(&Y); 2273a8e1175bSopenharmony_ci 2274a8e1175bSopenharmony_ci return ret; 2275a8e1175bSopenharmony_ci} 2276a8e1175bSopenharmony_ci 2277a8e1175bSopenharmony_ci#endif /* MBEDTLS_GENPRIME */ 2278a8e1175bSopenharmony_ci 2279a8e1175bSopenharmony_ci#if defined(MBEDTLS_SELF_TEST) 2280a8e1175bSopenharmony_ci 2281a8e1175bSopenharmony_ci#define GCD_PAIR_COUNT 3 2282a8e1175bSopenharmony_ci 2283a8e1175bSopenharmony_cistatic const int gcd_pairs[GCD_PAIR_COUNT][3] = 2284a8e1175bSopenharmony_ci{ 2285a8e1175bSopenharmony_ci { 693, 609, 21 }, 2286a8e1175bSopenharmony_ci { 1764, 868, 28 }, 2287a8e1175bSopenharmony_ci { 768454923, 542167814, 1 } 2288a8e1175bSopenharmony_ci}; 2289a8e1175bSopenharmony_ci 2290a8e1175bSopenharmony_ci/* 2291a8e1175bSopenharmony_ci * Checkup routine 2292a8e1175bSopenharmony_ci */ 2293a8e1175bSopenharmony_ciint mbedtls_mpi_self_test(int verbose) 2294a8e1175bSopenharmony_ci{ 2295a8e1175bSopenharmony_ci int ret, i; 2296a8e1175bSopenharmony_ci mbedtls_mpi A, E, N, X, Y, U, V; 2297a8e1175bSopenharmony_ci 2298a8e1175bSopenharmony_ci mbedtls_mpi_init(&A); mbedtls_mpi_init(&E); mbedtls_mpi_init(&N); mbedtls_mpi_init(&X); 2299a8e1175bSopenharmony_ci mbedtls_mpi_init(&Y); mbedtls_mpi_init(&U); mbedtls_mpi_init(&V); 2300a8e1175bSopenharmony_ci 2301a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&A, 16, 2302a8e1175bSopenharmony_ci "EFE021C2645FD1DC586E69184AF4A31E" \ 2303a8e1175bSopenharmony_ci "D5F53E93B5F123FA41680867BA110131" \ 2304a8e1175bSopenharmony_ci "944FE7952E2517337780CB0DB80E61AA" \ 2305a8e1175bSopenharmony_ci "E7C8DDC6C5C6AADEB34EB38A2F40D5E6")); 2306a8e1175bSopenharmony_ci 2307a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&E, 16, 2308a8e1175bSopenharmony_ci "B2E7EFD37075B9F03FF989C7C5051C20" \ 2309a8e1175bSopenharmony_ci "34D2A323810251127E7BF8625A4F49A5" \ 2310a8e1175bSopenharmony_ci "F3E27F4DA8BD59C47D6DAABA4C8127BD" \ 2311a8e1175bSopenharmony_ci "5B5C25763222FEFCCFC38B832366C29E")); 2312a8e1175bSopenharmony_ci 2313a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&N, 16, 2314a8e1175bSopenharmony_ci "0066A198186C18C10B2F5ED9B522752A" \ 2315a8e1175bSopenharmony_ci "9830B69916E535C8F047518A889A43A5" \ 2316a8e1175bSopenharmony_ci "94B6BED27A168D31D4A52F88925AA8F5")); 2317a8e1175bSopenharmony_ci 2318a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&X, &A, &N)); 2319a8e1175bSopenharmony_ci 2320a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16, 2321a8e1175bSopenharmony_ci "602AB7ECA597A3D6B56FF9829A5E8B85" \ 2322a8e1175bSopenharmony_ci "9E857EA95A03512E2BAE7391688D264A" \ 2323a8e1175bSopenharmony_ci "A5663B0341DB9CCFD2C4C5F421FEC814" \ 2324a8e1175bSopenharmony_ci "8001B72E848A38CAE1C65F78E56ABDEF" \ 2325a8e1175bSopenharmony_ci "E12D3C039B8A02D6BE593F0BBBDA56F1" \ 2326a8e1175bSopenharmony_ci "ECF677152EF804370C1A305CAF3B5BF1" \ 2327a8e1175bSopenharmony_ci "30879B56C61DE584A0F53A2447A51E")); 2328a8e1175bSopenharmony_ci 2329a8e1175bSopenharmony_ci if (verbose != 0) { 2330a8e1175bSopenharmony_ci mbedtls_printf(" MPI test #1 (mul_mpi): "); 2331a8e1175bSopenharmony_ci } 2332a8e1175bSopenharmony_ci 2333a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) { 2334a8e1175bSopenharmony_ci if (verbose != 0) { 2335a8e1175bSopenharmony_ci mbedtls_printf("failed\n"); 2336a8e1175bSopenharmony_ci } 2337a8e1175bSopenharmony_ci 2338a8e1175bSopenharmony_ci ret = 1; 2339a8e1175bSopenharmony_ci goto cleanup; 2340a8e1175bSopenharmony_ci } 2341a8e1175bSopenharmony_ci 2342a8e1175bSopenharmony_ci if (verbose != 0) { 2343a8e1175bSopenharmony_ci mbedtls_printf("passed\n"); 2344a8e1175bSopenharmony_ci } 2345a8e1175bSopenharmony_ci 2346a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&X, &Y, &A, &N)); 2347a8e1175bSopenharmony_ci 2348a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16, 2349a8e1175bSopenharmony_ci "256567336059E52CAE22925474705F39A94")); 2350a8e1175bSopenharmony_ci 2351a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&V, 16, 2352a8e1175bSopenharmony_ci "6613F26162223DF488E9CD48CC132C7A" \ 2353a8e1175bSopenharmony_ci "0AC93C701B001B092E4E5B9F73BCD27B" \ 2354a8e1175bSopenharmony_ci "9EE50D0657C77F374E903CDFA4C642")); 2355a8e1175bSopenharmony_ci 2356a8e1175bSopenharmony_ci if (verbose != 0) { 2357a8e1175bSopenharmony_ci mbedtls_printf(" MPI test #2 (div_mpi): "); 2358a8e1175bSopenharmony_ci } 2359a8e1175bSopenharmony_ci 2360a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_mpi(&X, &U) != 0 || 2361a8e1175bSopenharmony_ci mbedtls_mpi_cmp_mpi(&Y, &V) != 0) { 2362a8e1175bSopenharmony_ci if (verbose != 0) { 2363a8e1175bSopenharmony_ci mbedtls_printf("failed\n"); 2364a8e1175bSopenharmony_ci } 2365a8e1175bSopenharmony_ci 2366a8e1175bSopenharmony_ci ret = 1; 2367a8e1175bSopenharmony_ci goto cleanup; 2368a8e1175bSopenharmony_ci } 2369a8e1175bSopenharmony_ci 2370a8e1175bSopenharmony_ci if (verbose != 0) { 2371a8e1175bSopenharmony_ci mbedtls_printf("passed\n"); 2372a8e1175bSopenharmony_ci } 2373a8e1175bSopenharmony_ci 2374a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&X, &A, &E, &N, NULL)); 2375a8e1175bSopenharmony_ci 2376a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16, 2377a8e1175bSopenharmony_ci "36E139AEA55215609D2816998ED020BB" \ 2378a8e1175bSopenharmony_ci "BD96C37890F65171D948E9BC7CBAA4D9" \ 2379a8e1175bSopenharmony_ci "325D24D6A3C12710F10A09FA08AB87")); 2380a8e1175bSopenharmony_ci 2381a8e1175bSopenharmony_ci if (verbose != 0) { 2382a8e1175bSopenharmony_ci mbedtls_printf(" MPI test #3 (exp_mod): "); 2383a8e1175bSopenharmony_ci } 2384a8e1175bSopenharmony_ci 2385a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) { 2386a8e1175bSopenharmony_ci if (verbose != 0) { 2387a8e1175bSopenharmony_ci mbedtls_printf("failed\n"); 2388a8e1175bSopenharmony_ci } 2389a8e1175bSopenharmony_ci 2390a8e1175bSopenharmony_ci ret = 1; 2391a8e1175bSopenharmony_ci goto cleanup; 2392a8e1175bSopenharmony_ci } 2393a8e1175bSopenharmony_ci 2394a8e1175bSopenharmony_ci if (verbose != 0) { 2395a8e1175bSopenharmony_ci mbedtls_printf("passed\n"); 2396a8e1175bSopenharmony_ci } 2397a8e1175bSopenharmony_ci 2398a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&X, &A, &N)); 2399a8e1175bSopenharmony_ci 2400a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16, 2401a8e1175bSopenharmony_ci "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \ 2402a8e1175bSopenharmony_ci "C3DBA76456363A10869622EAC2DD84EC" \ 2403a8e1175bSopenharmony_ci "C5B8A74DAC4D09E03B5E0BE779F2DF61")); 2404a8e1175bSopenharmony_ci 2405a8e1175bSopenharmony_ci if (verbose != 0) { 2406a8e1175bSopenharmony_ci mbedtls_printf(" MPI test #4 (inv_mod): "); 2407a8e1175bSopenharmony_ci } 2408a8e1175bSopenharmony_ci 2409a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) { 2410a8e1175bSopenharmony_ci if (verbose != 0) { 2411a8e1175bSopenharmony_ci mbedtls_printf("failed\n"); 2412a8e1175bSopenharmony_ci } 2413a8e1175bSopenharmony_ci 2414a8e1175bSopenharmony_ci ret = 1; 2415a8e1175bSopenharmony_ci goto cleanup; 2416a8e1175bSopenharmony_ci } 2417a8e1175bSopenharmony_ci 2418a8e1175bSopenharmony_ci if (verbose != 0) { 2419a8e1175bSopenharmony_ci mbedtls_printf("passed\n"); 2420a8e1175bSopenharmony_ci } 2421a8e1175bSopenharmony_ci 2422a8e1175bSopenharmony_ci if (verbose != 0) { 2423a8e1175bSopenharmony_ci mbedtls_printf(" MPI test #5 (simple gcd): "); 2424a8e1175bSopenharmony_ci } 2425a8e1175bSopenharmony_ci 2426a8e1175bSopenharmony_ci for (i = 0; i < GCD_PAIR_COUNT; i++) { 2427a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&X, gcd_pairs[i][0])); 2428a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Y, gcd_pairs[i][1])); 2429a8e1175bSopenharmony_ci 2430a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&A, &X, &Y)); 2431a8e1175bSopenharmony_ci 2432a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_int(&A, gcd_pairs[i][2]) != 0) { 2433a8e1175bSopenharmony_ci if (verbose != 0) { 2434a8e1175bSopenharmony_ci mbedtls_printf("failed at %d\n", i); 2435a8e1175bSopenharmony_ci } 2436a8e1175bSopenharmony_ci 2437a8e1175bSopenharmony_ci ret = 1; 2438a8e1175bSopenharmony_ci goto cleanup; 2439a8e1175bSopenharmony_ci } 2440a8e1175bSopenharmony_ci } 2441a8e1175bSopenharmony_ci 2442a8e1175bSopenharmony_ci if (verbose != 0) { 2443a8e1175bSopenharmony_ci mbedtls_printf("passed\n"); 2444a8e1175bSopenharmony_ci } 2445a8e1175bSopenharmony_ci 2446a8e1175bSopenharmony_cicleanup: 2447a8e1175bSopenharmony_ci 2448a8e1175bSopenharmony_ci if (ret != 0 && verbose != 0) { 2449a8e1175bSopenharmony_ci mbedtls_printf("Unexpected error, return code = %08X\n", (unsigned int) ret); 2450a8e1175bSopenharmony_ci } 2451a8e1175bSopenharmony_ci 2452a8e1175bSopenharmony_ci mbedtls_mpi_free(&A); mbedtls_mpi_free(&E); mbedtls_mpi_free(&N); mbedtls_mpi_free(&X); 2453a8e1175bSopenharmony_ci mbedtls_mpi_free(&Y); mbedtls_mpi_free(&U); mbedtls_mpi_free(&V); 2454a8e1175bSopenharmony_ci 2455a8e1175bSopenharmony_ci if (verbose != 0) { 2456a8e1175bSopenharmony_ci mbedtls_printf("\n"); 2457a8e1175bSopenharmony_ci } 2458a8e1175bSopenharmony_ci 2459a8e1175bSopenharmony_ci return ret; 2460a8e1175bSopenharmony_ci} 2461a8e1175bSopenharmony_ci 2462a8e1175bSopenharmony_ci#endif /* MBEDTLS_SELF_TEST */ 2463a8e1175bSopenharmony_ci 2464a8e1175bSopenharmony_ci#endif /* MBEDTLS_BIGNUM_C */ 2465