blob: 384b9246b8bb2402d7f757a05cf00caeef991e4d [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakker5121ce52009-01-03 21:22:43 +000018 */
Simon Butcher15b15d12015-11-26 19:35:03 +000019
Paul Bakker5121ce52009-01-03 21:22:43 +000020/*
Simon Butcher15b15d12015-11-26 19:35:03 +000021 * The following sources were referenced in the design of this Multi-precision
22 * Integer library:
Paul Bakker5121ce52009-01-03 21:22:43 +000023 *
Simon Butcher15b15d12015-11-26 19:35:03 +000024 * [1] Handbook of Applied Cryptography - 1997
25 * Menezes, van Oorschot and Vanstone
26 *
27 * [2] Multi-Precision Math
28 * Tom St Denis
29 * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
30 *
31 * [3] GNU Multi-Precision Arithmetic Library
32 * https://gmplib.org/manual/index.html
33 *
Simon Butcherf5ba0452015-12-27 23:01:55 +000034 */
Paul Bakker5121ce52009-01-03 21:22:43 +000035
Gilles Peskinedb09ef62020-06-03 01:43:33 +020036#include "common.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if defined(MBEDTLS_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000039
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000040#include "mbedtls/bignum.h"
41#include "mbedtls/bn_mul.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050042#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000043#include "mbedtls/error.h"
Gabor Mezeic0ae1cf2021-10-20 12:09:35 +020044#include "constant_time_internal.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000045
Tom Cosgrove58efe612021-11-15 09:59:53 +000046#include <limits.h>
Rich Evans00ab4702015-02-06 13:43:58 +000047#include <string.h>
48
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000049#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020050
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010051#define MPI_VALIDATE_RET(cond) \
52 MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA)
53#define MPI_VALIDATE(cond) \
54 MBEDTLS_INTERNAL_VALIDATE(cond)
Hanno Becker73d7d792018-12-11 10:35:51 +000055
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020056#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
Paul Bakker5121ce52009-01-03 21:22:43 +000057#define biL (ciL << 3) /* bits in limb */
58#define biH (ciL << 2) /* half limb size */
59
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010060#define MPI_SIZE_T_MAX ((size_t) -1) /* SIZE_T_MAX is not standard */
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010061
Paul Bakker5121ce52009-01-03 21:22:43 +000062/*
63 * Convert between bits/chars and number of limbs
Manuel Pégourié-Gonnard58fb4952015-09-28 13:48:04 +020064 * Divide first in order to avoid potential overflows
Paul Bakker5121ce52009-01-03 21:22:43 +000065 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010066#define BITS_TO_LIMBS(i) ((i) / biL + ((i) % biL != 0))
67#define CHARS_TO_LIMBS(i) ((i) / ciL + ((i) % ciL != 0))
Paul Bakker5121ce52009-01-03 21:22:43 +000068
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050069/* Implementation that should never be optimized out by the compiler */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010070static void mbedtls_mpi_zeroize(mbedtls_mpi_uint *v, size_t n)
Andres Amaya Garcia6698d2f2018-04-24 08:39:07 -050071{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010072 mbedtls_platform_zeroize(v, ciL * n);
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050073}
74
Paul Bakker5121ce52009-01-03 21:22:43 +000075/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000076 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000077 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010078void mbedtls_mpi_init(mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +000079{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010080 MPI_VALIDATE(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +000081
Paul Bakker6c591fa2011-05-05 11:49:20 +000082 X->s = 1;
83 X->n = 0;
84 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000085}
86
87/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000088 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000089 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010090void mbedtls_mpi_free(mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +000091{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010092 if (X == NULL) {
Paul Bakker6c591fa2011-05-05 11:49:20 +000093 return;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010094 }
Paul Bakker5121ce52009-01-03 21:22:43 +000095
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010096 if (X->p != NULL) {
97 mbedtls_mpi_zeroize(X->p, X->n);
98 mbedtls_free(X->p);
Paul Bakker5121ce52009-01-03 21:22:43 +000099 }
100
Paul Bakker6c591fa2011-05-05 11:49:20 +0000101 X->s = 1;
102 X->n = 0;
103 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000104}
105
106/*
107 * Enlarge to the specified number of limbs
108 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100109int mbedtls_mpi_grow(mbedtls_mpi *X, size_t nblimbs)
Paul Bakker5121ce52009-01-03 21:22:43 +0000110{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200111 mbedtls_mpi_uint *p;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100112 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000113
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100114 if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
115 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
116 }
Paul Bakkerf9688572011-05-05 10:00:45 +0000117
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100118 if (X->n < nblimbs) {
119 if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(nblimbs, ciL)) == NULL) {
120 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
121 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000122
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100123 if (X->p != NULL) {
124 memcpy(p, X->p, X->n * ciL);
125 mbedtls_mpi_zeroize(X->p, X->n);
126 mbedtls_free(X->p);
Paul Bakker5121ce52009-01-03 21:22:43 +0000127 }
128
129 X->n = nblimbs;
130 X->p = p;
131 }
132
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100133 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000134}
135
136/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100137 * Resize down as much as possible,
138 * while keeping at least the specified number of limbs
139 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100140int mbedtls_mpi_shrink(mbedtls_mpi *X, size_t nblimbs)
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100141{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200142 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100143 size_t i;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100144 MPI_VALIDATE_RET(X != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000145
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100146 if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
147 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
148 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100149
Gilles Peskinee2f563e2020-01-20 21:17:43 +0100150 /* Actually resize up if there are currently fewer than nblimbs limbs. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100151 if (X->n <= nblimbs) {
152 return mbedtls_mpi_grow(X, nblimbs);
153 }
Gilles Peskine322752b2020-01-21 13:59:51 +0100154 /* After this point, then X->n > nblimbs and in particular X->n > 0. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100155
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100156 for (i = X->n - 1; i > 0; i--) {
157 if (X->p[i] != 0) {
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100158 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100159 }
160 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100161 i++;
162
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100163 if (i < nblimbs) {
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100164 i = nblimbs;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100165 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100166
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100167 if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(i, ciL)) == NULL) {
168 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
169 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100170
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100171 if (X->p != NULL) {
172 memcpy(p, X->p, i * ciL);
173 mbedtls_mpi_zeroize(X->p, X->n);
174 mbedtls_free(X->p);
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100175 }
176
177 X->n = i;
178 X->p = p;
179
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100180 return 0;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100181}
182
Gilles Peskine3130ce22021-06-02 22:17:52 +0200183/* Resize X to have exactly n limbs and set it to 0. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100184static int mbedtls_mpi_resize_clear(mbedtls_mpi *X, size_t limbs)
Gilles Peskine3130ce22021-06-02 22:17:52 +0200185{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100186 if (limbs == 0) {
187 mbedtls_mpi_free(X);
188 return 0;
189 } else if (X->n == limbs) {
190 memset(X->p, 0, limbs * ciL);
Gilles Peskine3130ce22021-06-02 22:17:52 +0200191 X->s = 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100192 return 0;
193 } else {
194 mbedtls_mpi_free(X);
195 return mbedtls_mpi_grow(X, limbs);
Gilles Peskine3130ce22021-06-02 22:17:52 +0200196 }
197}
198
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100199/*
Gilles Peskinef643e8e2021-06-08 23:17:42 +0200200 * Copy the contents of Y into X.
201 *
202 * This function is not constant-time. Leading zeros in Y may be removed.
203 *
204 * Ensure that X does not shrink. This is not guaranteed by the public API,
205 * but some code in the bignum module relies on this property, for example
206 * in mbedtls_mpi_exp_mod().
Paul Bakker5121ce52009-01-03 21:22:43 +0000207 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100208int mbedtls_mpi_copy(mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000209{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100210 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000211 size_t i;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100212 MPI_VALIDATE_RET(X != NULL);
213 MPI_VALIDATE_RET(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000214
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100215 if (X == Y) {
216 return 0;
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200217 }
218
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100219 if (Y->n == 0) {
220 if (X->n != 0) {
221 X->s = 1;
222 memset(X->p, 0, X->n * ciL);
223 }
224 return 0;
225 }
226
227 for (i = Y->n - 1; i > 0; i--) {
228 if (Y->p[i] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000229 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100230 }
231 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000232 i++;
233
234 X->s = Y->s;
235
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100236 if (X->n < i) {
237 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i));
238 } else {
239 memset(X->p + i, 0, (X->n - i) * ciL);
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100240 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000241
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100242 memcpy(X->p, Y->p, i * ciL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000243
244cleanup:
245
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100246 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000247}
248
249/*
250 * Swap the contents of X and Y
251 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100252void mbedtls_mpi_swap(mbedtls_mpi *X, mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000253{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200254 mbedtls_mpi T;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100255 MPI_VALIDATE(X != NULL);
256 MPI_VALIDATE(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000257
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100258 memcpy(&T, X, sizeof(mbedtls_mpi));
259 memcpy(X, Y, sizeof(mbedtls_mpi));
260 memcpy(Y, &T, sizeof(mbedtls_mpi));
Paul Bakker5121ce52009-01-03 21:22:43 +0000261}
262
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100263static inline mbedtls_mpi_uint mpi_sint_abs(mbedtls_mpi_sint z)
Gilles Peskineae7cbd72022-11-15 23:25:27 +0100264{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100265 if (z >= 0) {
266 return z;
267 }
Gilles Peskineae7cbd72022-11-15 23:25:27 +0100268 /* Take care to handle the most negative value (-2^(biL-1)) correctly.
269 * A naive -z would have undefined behavior.
270 * Write this in a way that makes popular compilers happy (GCC, Clang,
271 * MSVC). */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100272 return (mbedtls_mpi_uint) 0 - (mbedtls_mpi_uint) z;
Gilles Peskineae7cbd72022-11-15 23:25:27 +0100273}
274
Paul Bakker5121ce52009-01-03 21:22:43 +0000275/*
276 * Set value from integer
277 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100278int mbedtls_mpi_lset(mbedtls_mpi *X, mbedtls_mpi_sint z)
Paul Bakker5121ce52009-01-03 21:22:43 +0000279{
Janos Follath24eed8d2019-11-22 13:21:35 +0000280 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100281 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000282
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100283 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, 1));
284 memset(X->p, 0, X->n * ciL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000285
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100286 X->p[0] = mpi_sint_abs(z);
287 X->s = (z < 0) ? -1 : 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000288
289cleanup:
290
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100291 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000292}
293
294/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000295 * Get a specific bit
296 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100297int mbedtls_mpi_get_bit(const mbedtls_mpi *X, size_t pos)
Paul Bakker2f5947e2011-05-18 15:47:11 +0000298{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100299 MPI_VALIDATE_RET(X != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000300
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100301 if (X->n * biL <= pos) {
302 return 0;
303 }
Paul Bakker2f5947e2011-05-18 15:47:11 +0000304
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100305 return (X->p[pos / biL] >> (pos % biL)) & 0x01;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000306}
307
Gilles Peskine11cdb052018-11-20 16:47:47 +0100308/* Get a specific byte, without range checks. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100309#define GET_BYTE(X, i) \
310 (((X)->p[(i) / ciL] >> (((i) % ciL) * 8)) & 0xff)
Gilles Peskine11cdb052018-11-20 16:47:47 +0100311
Paul Bakker2f5947e2011-05-18 15:47:11 +0000312/*
313 * Set a bit to a specific value of 0 or 1
314 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100315int mbedtls_mpi_set_bit(mbedtls_mpi *X, size_t pos, unsigned char val)
Paul Bakker2f5947e2011-05-18 15:47:11 +0000316{
317 int ret = 0;
318 size_t off = pos / biL;
319 size_t idx = pos % biL;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100320 MPI_VALIDATE_RET(X != NULL);
Paul Bakker2f5947e2011-05-18 15:47:11 +0000321
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100322 if (val != 0 && val != 1) {
323 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000324 }
325
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100326 if (X->n * biL <= pos) {
327 if (val == 0) {
328 return 0;
329 }
330
331 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, off + 1));
332 }
333
334 X->p[off] &= ~((mbedtls_mpi_uint) 0x01 << idx);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200335 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000336
337cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200338
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100339 return ret;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000340}
341
342/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200343 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000344 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100345size_t mbedtls_mpi_lsb(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000346{
Paul Bakker23986e52011-04-24 08:57:21 +0000347 size_t i, j, count = 0;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100348 MBEDTLS_INTERNAL_VALIDATE_RET(X != NULL, 0);
Paul Bakker5121ce52009-01-03 21:22:43 +0000349
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100350 for (i = 0; i < X->n; i++) {
351 for (j = 0; j < biL; j++, count++) {
352 if (((X->p[i] >> j) & 1) != 0) {
353 return count;
354 }
355 }
356 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000357
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100358 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000359}
360
361/*
Simon Butcher15b15d12015-11-26 19:35:03 +0000362 * Count leading zero bits in a given integer
363 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100364static size_t mbedtls_clz(const mbedtls_mpi_uint x)
Simon Butcher15b15d12015-11-26 19:35:03 +0000365{
366 size_t j;
Manuel Pégourié-Gonnarde3e8edf2015-12-01 09:31:52 +0100367 mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
Simon Butcher15b15d12015-11-26 19:35:03 +0000368
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100369 for (j = 0; j < biL; j++) {
370 if (x & mask) {
371 break;
372 }
Simon Butcher15b15d12015-11-26 19:35:03 +0000373
374 mask >>= 1;
375 }
376
377 return j;
378}
379
380/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200381 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000382 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100383size_t mbedtls_mpi_bitlen(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000384{
Paul Bakker23986e52011-04-24 08:57:21 +0000385 size_t i, j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000386
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100387 if (X->n == 0) {
388 return 0;
389 }
Manuel Pégourié-Gonnard770b5e12015-04-29 17:02:01 +0200390
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100391 for (i = X->n - 1; i > 0; i--) {
392 if (X->p[i] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000393 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100394 }
395 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000396
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100397 j = biL - mbedtls_clz(X->p[i]);
Paul Bakker5121ce52009-01-03 21:22:43 +0000398
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100399 return (i * biL) + j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000400}
401
402/*
403 * Return the total size in bytes
404 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100405size_t mbedtls_mpi_size(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000406{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100407 return (mbedtls_mpi_bitlen(X) + 7) >> 3;
Paul Bakker5121ce52009-01-03 21:22:43 +0000408}
409
410/*
411 * Convert an ASCII character to digit value
412 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100413static int mpi_get_digit(mbedtls_mpi_uint *d, int radix, char c)
Paul Bakker5121ce52009-01-03 21:22:43 +0000414{
415 *d = 255;
416
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100417 if (c >= 0x30 && c <= 0x39) {
418 *d = c - 0x30;
419 }
420 if (c >= 0x41 && c <= 0x46) {
421 *d = c - 0x37;
422 }
423 if (c >= 0x61 && c <= 0x66) {
424 *d = c - 0x57;
425 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000426
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100427 if (*d >= (mbedtls_mpi_uint) radix) {
428 return MBEDTLS_ERR_MPI_INVALID_CHARACTER;
429 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000430
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100431 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000432}
433
434/*
435 * Import from an ASCII string
436 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100437int mbedtls_mpi_read_string(mbedtls_mpi *X, int radix, const char *s)
Paul Bakker5121ce52009-01-03 21:22:43 +0000438{
Janos Follath24eed8d2019-11-22 13:21:35 +0000439 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000440 size_t i, j, slen, n;
Gilles Peskine80f56732021-04-03 18:26:13 +0200441 int sign = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200442 mbedtls_mpi_uint d;
443 mbedtls_mpi T;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100444 MPI_VALIDATE_RET(X != NULL);
445 MPI_VALIDATE_RET(s != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000446
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100447 if (radix < 2 || radix > 16) {
448 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Gilles Peskined4876132021-06-08 18:32:34 +0200449 }
450
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100451 mbedtls_mpi_init(&T);
452
453 if (s[0] == 0) {
454 mbedtls_mpi_free(X);
455 return 0;
456 }
457
458 if (s[0] == '-') {
Gilles Peskine80f56732021-04-03 18:26:13 +0200459 ++s;
460 sign = -1;
461 }
462
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100463 slen = strlen(s);
Paul Bakkerff60ee62010-03-16 21:09:09 +0000464
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100465 if (radix == 16) {
466 if (slen > MPI_SIZE_T_MAX >> 2) {
467 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Paul Bakker5121ce52009-01-03 21:22:43 +0000468 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000469
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100470 n = BITS_TO_LIMBS(slen << 2);
471
472 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n));
473 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
474
475 for (i = slen, j = 0; i > 0; i--, j++) {
476 MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i - 1]));
477 X->p[j / (2 * ciL)] |= d << ((j % (2 * ciL)) << 2);
478 }
479 } else {
480 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
481
482 for (i = 0; i < slen; i++) {
483 MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i]));
484 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T, X, radix));
485 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, &T, d));
Paul Bakker5121ce52009-01-03 21:22:43 +0000486 }
487 }
488
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100489 if (sign < 0 && mbedtls_mpi_bitlen(X) != 0) {
Gilles Peskine80f56732021-04-03 18:26:13 +0200490 X->s = -1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100491 }
Gilles Peskine80f56732021-04-03 18:26:13 +0200492
Paul Bakker5121ce52009-01-03 21:22:43 +0000493cleanup:
494
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100495 mbedtls_mpi_free(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000496
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100497 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000498}
499
500/*
Ron Eldora16fa292018-11-20 14:07:01 +0200501 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000502 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100503static int mpi_write_hlp(mbedtls_mpi *X, int radix,
504 char **p, const size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000505{
Janos Follath24eed8d2019-11-22 13:21:35 +0000506 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200507 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200508 size_t length = 0;
509 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000510
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100511 do {
512 if (length >= buflen) {
513 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
Ron Eldora16fa292018-11-20 14:07:01 +0200514 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000515
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100516 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, radix));
517 MBEDTLS_MPI_CHK(mbedtls_mpi_div_int(X, NULL, X, radix));
Ron Eldora16fa292018-11-20 14:07:01 +0200518 /*
519 * Write the residue in the current position, as an ASCII character.
520 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100521 if (r < 0xA) {
522 *(--p_end) = (char) ('0' + r);
523 } else {
524 *(--p_end) = (char) ('A' + (r - 0xA));
525 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000526
Ron Eldora16fa292018-11-20 14:07:01 +0200527 length++;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100528 } while (mbedtls_mpi_cmp_int(X, 0) != 0);
Paul Bakker5121ce52009-01-03 21:22:43 +0000529
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100530 memmove(*p, p_end, length);
Ron Eldora16fa292018-11-20 14:07:01 +0200531 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000532
533cleanup:
534
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100535 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000536}
537
538/*
539 * Export into an ASCII string
540 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100541int mbedtls_mpi_write_string(const mbedtls_mpi *X, int radix,
542 char *buf, size_t buflen, size_t *olen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000543{
Paul Bakker23986e52011-04-24 08:57:21 +0000544 int ret = 0;
545 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000546 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200547 mbedtls_mpi T;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100548 MPI_VALIDATE_RET(X != NULL);
549 MPI_VALIDATE_RET(olen != NULL);
550 MPI_VALIDATE_RET(buflen == 0 || buf != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000551
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100552 if (radix < 2 || radix > 16) {
553 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
554 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000555
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100556 n = mbedtls_mpi_bitlen(X); /* Number of bits necessary to present `n`. */
557 if (radix >= 4) {
558 n >>= 1; /* Number of 4-adic digits necessary to present
Hanno Becker23cfea02019-02-04 09:45:07 +0000559 * `n`. If radix > 4, this might be a strict
560 * overapproximation of the number of
561 * radix-adic digits needed to present `n`. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100562 }
563 if (radix >= 16) {
564 n >>= 1; /* Number of hexadecimal digits necessary to
Hanno Becker23cfea02019-02-04 09:45:07 +0000565 * present `n`. */
566
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100567 }
Janos Follath80470622019-03-06 13:43:02 +0000568 n += 1; /* Terminating null byte */
Hanno Becker23cfea02019-02-04 09:45:07 +0000569 n += 1; /* Compensate for the divisions above, which round down `n`
570 * in case it's not even. */
571 n += 1; /* Potential '-'-sign. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100572 n += (n & 1); /* Make n even to have enough space for hexadecimal writing,
Hanno Becker23cfea02019-02-04 09:45:07 +0000573 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000574
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100575 if (buflen < n) {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100576 *olen = n;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100577 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000578 }
579
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100580 p = buf;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100581 mbedtls_mpi_init(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000582
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100583 if (X->s == -1) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000584 *p++ = '-';
Hanno Beckerc983c812019-02-01 16:41:30 +0000585 buflen--;
586 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000587
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100588 if (radix == 16) {
Paul Bakker23986e52011-04-24 08:57:21 +0000589 int c;
590 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000591
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100592 for (i = X->n, k = 0; i > 0; i--) {
593 for (j = ciL; j > 0; j--) {
594 c = (X->p[i - 1] >> ((j - 1) << 3)) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000595
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100596 if (c == 0 && k == 0 && (i + j) != 2) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000597 continue;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100598 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000599
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000600 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000601 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000602 k = 1;
603 }
604 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100605 } else {
606 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T, X));
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000607
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100608 if (T.s == -1) {
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000609 T.s = 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100610 }
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000611
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100612 MBEDTLS_MPI_CHK(mpi_write_hlp(&T, radix, &p, buflen));
Paul Bakker5121ce52009-01-03 21:22:43 +0000613 }
614
615 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100616 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000617
618cleanup:
619
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100620 mbedtls_mpi_free(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000621
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100622 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000623}
624
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200625#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000626/*
627 * Read X from an opened file
628 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100629int mbedtls_mpi_read_file(mbedtls_mpi *X, int radix, FILE *fin)
Paul Bakker5121ce52009-01-03 21:22:43 +0000630{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200631 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000632 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000633 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000634 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000635 * Buffer should have space for (short) label and decimal formatted MPI,
636 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000637 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100638 char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
Paul Bakker5121ce52009-01-03 21:22:43 +0000639
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100640 MPI_VALIDATE_RET(X != NULL);
641 MPI_VALIDATE_RET(fin != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000642
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100643 if (radix < 2 || radix > 16) {
644 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
645 }
Hanno Becker73d7d792018-12-11 10:35:51 +0000646
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100647 memset(s, 0, sizeof(s));
648 if (fgets(s, sizeof(s) - 1, fin) == NULL) {
649 return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
650 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000651
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100652 slen = strlen(s);
653 if (slen == sizeof(s) - 2) {
654 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
655 }
Paul Bakkercb37aa52011-11-30 16:00:20 +0000656
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100657 if (slen > 0 && s[slen - 1] == '\n') {
658 slen--; s[slen] = '\0';
659 }
660 if (slen > 0 && s[slen - 1] == '\r') {
661 slen--; s[slen] = '\0';
662 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000663
664 p = s + slen;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100665 while (p-- > s) {
666 if (mpi_get_digit(&d, radix, *p) != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000667 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100668 }
669 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000670
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100671 return mbedtls_mpi_read_string(X, radix, p + 1);
Paul Bakker5121ce52009-01-03 21:22:43 +0000672}
673
674/*
675 * Write X into an opened file (or stdout if fout == NULL)
676 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100677int mbedtls_mpi_write_file(const char *p, const mbedtls_mpi *X, int radix, FILE *fout)
Paul Bakker5121ce52009-01-03 21:22:43 +0000678{
Janos Follath24eed8d2019-11-22 13:21:35 +0000679 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000680 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000681 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000682 * Buffer should have space for (short) label and decimal formatted MPI,
683 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000684 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100685 char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
686 MPI_VALIDATE_RET(X != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000687
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100688 if (radix < 2 || radix > 16) {
689 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
690 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000691
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100692 memset(s, 0, sizeof(s));
Paul Bakker5121ce52009-01-03 21:22:43 +0000693
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100694 MBEDTLS_MPI_CHK(mbedtls_mpi_write_string(X, radix, s, sizeof(s) - 2, &n));
Paul Bakker5121ce52009-01-03 21:22:43 +0000695
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100696 if (p == NULL) {
697 p = "";
698 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000699
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100700 plen = strlen(p);
701 slen = strlen(s);
Paul Bakker5121ce52009-01-03 21:22:43 +0000702 s[slen++] = '\r';
703 s[slen++] = '\n';
704
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100705 if (fout != NULL) {
706 if (fwrite(p, 1, plen, fout) != plen ||
707 fwrite(s, 1, slen, fout) != slen) {
708 return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
709 }
710 } else {
711 mbedtls_printf("%s%s", p, s);
Paul Bakker5121ce52009-01-03 21:22:43 +0000712 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000713
714cleanup:
715
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100716 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000717}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200718#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000719
Hanno Beckerda1655a2017-10-18 14:21:44 +0100720
721/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
722 * into the storage form used by mbedtls_mpi. */
Hanno Beckerf8720072018-11-08 11:53:49 +0000723
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100724static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c(mbedtls_mpi_uint x)
Hanno Beckerf8720072018-11-08 11:53:49 +0000725{
726 uint8_t i;
Hanno Becker031d6332019-05-01 17:09:11 +0100727 unsigned char *x_ptr;
Hanno Beckerf8720072018-11-08 11:53:49 +0000728 mbedtls_mpi_uint tmp = 0;
Hanno Becker031d6332019-05-01 17:09:11 +0100729
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100730 for (i = 0, x_ptr = (unsigned char *) &x; i < ciL; i++, x_ptr++) {
Hanno Becker031d6332019-05-01 17:09:11 +0100731 tmp <<= CHAR_BIT;
732 tmp |= (mbedtls_mpi_uint) *x_ptr;
733 }
734
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100735 return tmp;
Hanno Beckerf8720072018-11-08 11:53:49 +0000736}
737
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100738static mbedtls_mpi_uint mpi_uint_bigendian_to_host(mbedtls_mpi_uint x)
Hanno Beckerf8720072018-11-08 11:53:49 +0000739{
740#if defined(__BYTE_ORDER__)
741
742/* Nothing to do on bigendian systems. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100743#if (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
744 return x;
Hanno Beckerf8720072018-11-08 11:53:49 +0000745#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
746
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100747#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
Hanno Beckerf8720072018-11-08 11:53:49 +0000748
749/* For GCC and Clang, have builtins for byte swapping. */
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000750#if defined(__GNUC__) && defined(__GNUC_PREREQ)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100751#if __GNUC_PREREQ(4, 3)
Hanno Beckerf8720072018-11-08 11:53:49 +0000752#define have_bswap
753#endif
Hanno Becker9f6d16a2019-01-02 17:15:06 +0000754#endif
755
756#if defined(__clang__) && defined(__has_builtin)
757#if __has_builtin(__builtin_bswap32) && \
758 __has_builtin(__builtin_bswap64)
759#define have_bswap
760#endif
761#endif
762
Hanno Beckerf8720072018-11-08 11:53:49 +0000763#if defined(have_bswap)
764 /* The compiler is hopefully able to statically evaluate this! */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100765 switch (sizeof(mbedtls_mpi_uint)) {
Hanno Beckerf8720072018-11-08 11:53:49 +0000766 case 4:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100767 return __builtin_bswap32(x);
Hanno Beckerf8720072018-11-08 11:53:49 +0000768 case 8:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100769 return __builtin_bswap64(x);
Hanno Beckerf8720072018-11-08 11:53:49 +0000770 }
771#endif
772#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
773#endif /* __BYTE_ORDER__ */
774
775 /* Fall back to C-based reordering if we don't know the byte order
776 * or we couldn't use a compiler-specific builtin. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100777 return mpi_uint_bigendian_to_host_c(x);
Hanno Beckerf8720072018-11-08 11:53:49 +0000778}
779
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100780static void mpi_bigendian_to_host(mbedtls_mpi_uint * const p, size_t limbs)
Hanno Beckerda1655a2017-10-18 14:21:44 +0100781{
Hanno Beckerda1655a2017-10-18 14:21:44 +0100782 mbedtls_mpi_uint *cur_limb_left;
783 mbedtls_mpi_uint *cur_limb_right;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100784 if (limbs == 0) {
Hanno Becker2be8a552018-10-25 12:40:09 +0100785 return;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100786 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100787
788 /*
789 * Traverse limbs and
790 * - adapt byte-order in each limb
791 * - swap the limbs themselves.
792 * For that, simultaneously traverse the limbs from left to right
793 * and from right to left, as long as the left index is not bigger
794 * than the right index (it's not a problem if limbs is odd and the
795 * indices coincide in the last iteration).
796 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100797 for (cur_limb_left = p, cur_limb_right = p + (limbs - 1);
Hanno Beckerda1655a2017-10-18 14:21:44 +0100798 cur_limb_left <= cur_limb_right;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100799 cur_limb_left++, cur_limb_right--) {
Hanno Beckerf8720072018-11-08 11:53:49 +0000800 mbedtls_mpi_uint tmp;
801 /* Note that if cur_limb_left == cur_limb_right,
802 * this code effectively swaps the bytes only once. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100803 tmp = mpi_uint_bigendian_to_host(*cur_limb_left);
804 *cur_limb_left = mpi_uint_bigendian_to_host(*cur_limb_right);
Hanno Beckerf8720072018-11-08 11:53:49 +0000805 *cur_limb_right = tmp;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100806 }
Hanno Beckerda1655a2017-10-18 14:21:44 +0100807}
808
Paul Bakker5121ce52009-01-03 21:22:43 +0000809/*
Janos Follatha778a942019-02-13 10:28:28 +0000810 * Import X from unsigned binary data, little endian
811 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100812int mbedtls_mpi_read_binary_le(mbedtls_mpi *X,
813 const unsigned char *buf, size_t buflen)
Janos Follatha778a942019-02-13 10:28:28 +0000814{
Janos Follath24eed8d2019-11-22 13:21:35 +0000815 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follatha778a942019-02-13 10:28:28 +0000816 size_t i;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100817 size_t const limbs = CHARS_TO_LIMBS(buflen);
Janos Follatha778a942019-02-13 10:28:28 +0000818
819 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100820 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
Janos Follatha778a942019-02-13 10:28:28 +0000821
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100822 for (i = 0; i < buflen; i++) {
Janos Follatha778a942019-02-13 10:28:28 +0000823 X->p[i / ciL] |= ((mbedtls_mpi_uint) buf[i]) << ((i % ciL) << 3);
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100824 }
Janos Follatha778a942019-02-13 10:28:28 +0000825
826cleanup:
827
Janos Follath171a7ef2019-02-15 16:17:45 +0000828 /*
829 * This function is also used to import keys. However, wiping the buffers
830 * upon failure is not necessary because failure only can happen before any
831 * input is copied.
832 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100833 return ret;
Janos Follatha778a942019-02-13 10:28:28 +0000834}
835
836/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000837 * Import X from unsigned binary data, big endian
838 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100839int mbedtls_mpi_read_binary(mbedtls_mpi *X, const unsigned char *buf, size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000840{
Janos Follath24eed8d2019-11-22 13:21:35 +0000841 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100842 size_t const limbs = CHARS_TO_LIMBS(buflen);
843 size_t const overhead = (limbs * ciL) - buflen;
Hanno Beckerda1655a2017-10-18 14:21:44 +0100844 unsigned char *Xp;
Paul Bakker5121ce52009-01-03 21:22:43 +0000845
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100846 MPI_VALIDATE_RET(X != NULL);
847 MPI_VALIDATE_RET(buflen == 0 || buf != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000848
Hanno Becker073c1992017-10-17 15:17:27 +0100849 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100850 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
Paul Bakker5121ce52009-01-03 21:22:43 +0000851
Gilles Peskine3130ce22021-06-02 22:17:52 +0200852 /* Avoid calling `memcpy` with NULL source or destination argument,
Hanno Becker0e810b92019-01-03 17:13:11 +0000853 * even if buflen is 0. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100854 if (buflen != 0) {
855 Xp = (unsigned char *) X->p;
856 memcpy(Xp + overhead, buf, buflen);
Hanno Beckerda1655a2017-10-18 14:21:44 +0100857
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100858 mpi_bigendian_to_host(X->p, limbs);
Hanno Becker0e810b92019-01-03 17:13:11 +0000859 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000860
861cleanup:
862
Janos Follath171a7ef2019-02-15 16:17:45 +0000863 /*
864 * This function is also used to import keys. However, wiping the buffers
865 * upon failure is not necessary because failure only can happen before any
866 * input is copied.
867 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100868 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000869}
870
871/*
Janos Follathe344d0f2019-02-19 16:17:40 +0000872 * Export X into unsigned binary data, little endian
873 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100874int mbedtls_mpi_write_binary_le(const mbedtls_mpi *X,
875 unsigned char *buf, size_t buflen)
Janos Follathe344d0f2019-02-19 16:17:40 +0000876{
877 size_t stored_bytes = X->n * ciL;
878 size_t bytes_to_copy;
879 size_t i;
880
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100881 if (stored_bytes < buflen) {
Janos Follathe344d0f2019-02-19 16:17:40 +0000882 bytes_to_copy = stored_bytes;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100883 } else {
Janos Follathe344d0f2019-02-19 16:17:40 +0000884 bytes_to_copy = buflen;
885
886 /* The output buffer is smaller than the allocated size of X.
887 * However X may fit if its leading bytes are zero. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100888 for (i = bytes_to_copy; i < stored_bytes; i++) {
889 if (GET_BYTE(X, i) != 0) {
890 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
891 }
Janos Follathe344d0f2019-02-19 16:17:40 +0000892 }
893 }
894
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100895 for (i = 0; i < bytes_to_copy; i++) {
896 buf[i] = GET_BYTE(X, i);
Janos Follathe344d0f2019-02-19 16:17:40 +0000897 }
898
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100899 if (stored_bytes < buflen) {
900 /* Write trailing 0 bytes */
901 memset(buf + stored_bytes, 0, buflen - stored_bytes);
902 }
903
904 return 0;
Janos Follathe344d0f2019-02-19 16:17:40 +0000905}
906
907/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000908 * Export X into unsigned binary data, big endian
909 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100910int mbedtls_mpi_write_binary(const mbedtls_mpi *X,
911 unsigned char *buf, size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000912{
Hanno Becker73d7d792018-12-11 10:35:51 +0000913 size_t stored_bytes;
Gilles Peskine11cdb052018-11-20 16:47:47 +0100914 size_t bytes_to_copy;
915 unsigned char *p;
916 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000917
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100918 MPI_VALIDATE_RET(X != NULL);
919 MPI_VALIDATE_RET(buflen == 0 || buf != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000920
921 stored_bytes = X->n * ciL;
922
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100923 if (stored_bytes < buflen) {
Gilles Peskine11cdb052018-11-20 16:47:47 +0100924 /* There is enough space in the output buffer. Write initial
925 * null bytes and record the position at which to start
926 * writing the significant bytes. In this case, the execution
927 * trace of this function does not depend on the value of the
928 * number. */
929 bytes_to_copy = stored_bytes;
930 p = buf + buflen - stored_bytes;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100931 memset(buf, 0, buflen - stored_bytes);
932 } else {
Gilles Peskine11cdb052018-11-20 16:47:47 +0100933 /* The output buffer is smaller than the allocated size of X.
934 * However X may fit if its leading bytes are zero. */
935 bytes_to_copy = buflen;
936 p = buf;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100937 for (i = bytes_to_copy; i < stored_bytes; i++) {
938 if (GET_BYTE(X, i) != 0) {
939 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
940 }
Gilles Peskine11cdb052018-11-20 16:47:47 +0100941 }
942 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000943
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100944 for (i = 0; i < bytes_to_copy; i++) {
945 p[bytes_to_copy - i - 1] = GET_BYTE(X, i);
946 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000947
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100948 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000949}
950
951/*
952 * Left-shift: X <<= count
953 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100954int mbedtls_mpi_shift_l(mbedtls_mpi *X, size_t count)
Paul Bakker5121ce52009-01-03 21:22:43 +0000955{
Janos Follath24eed8d2019-11-22 13:21:35 +0000956 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000957 size_t i, v0, t1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200958 mbedtls_mpi_uint r0 = 0, r1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100959 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000960
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100961 v0 = count / (biL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000962 t1 = count & (biL - 1);
963
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100964 i = mbedtls_mpi_bitlen(X) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000965
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100966 if (X->n * biL < i) {
967 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, BITS_TO_LIMBS(i)));
968 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000969
970 ret = 0;
971
972 /*
973 * shift by count / limb_size
974 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100975 if (v0 > 0) {
976 for (i = X->n; i > v0; i--) {
Paul Bakker23986e52011-04-24 08:57:21 +0000977 X->p[i - 1] = X->p[i - v0 - 1];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100978 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000979
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100980 for (; i > 0; i--) {
Paul Bakker23986e52011-04-24 08:57:21 +0000981 X->p[i - 1] = 0;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100982 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000983 }
984
985 /*
986 * shift by count % limb_size
987 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100988 if (t1 > 0) {
989 for (i = v0; i < X->n; i++) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000990 r1 = X->p[i] >> (biL - t1);
991 X->p[i] <<= t1;
992 X->p[i] |= r0;
993 r0 = r1;
994 }
995 }
996
997cleanup:
998
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100999 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001000}
1001
1002/*
1003 * Right-shift: X >>= count
1004 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001005int mbedtls_mpi_shift_r(mbedtls_mpi *X, size_t count)
Paul Bakker5121ce52009-01-03 21:22:43 +00001006{
Paul Bakker23986e52011-04-24 08:57:21 +00001007 size_t i, v0, v1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001008 mbedtls_mpi_uint r0 = 0, r1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001009 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001010
1011 v0 = count / biL;
1012 v1 = count & (biL - 1);
1013
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001014 if (v0 > X->n || (v0 == X->n && v1 > 0)) {
1015 return mbedtls_mpi_lset(X, 0);
1016 }
Manuel Pégourié-Gonnarde44ec102012-11-17 12:42:51 +01001017
Paul Bakker5121ce52009-01-03 21:22:43 +00001018 /*
1019 * shift by count / limb_size
1020 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001021 if (v0 > 0) {
1022 for (i = 0; i < X->n - v0; i++) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001023 X->p[i] = X->p[i + v0];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001024 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001025
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001026 for (; i < X->n; i++) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001027 X->p[i] = 0;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001028 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001029 }
1030
1031 /*
1032 * shift by count % limb_size
1033 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001034 if (v1 > 0) {
1035 for (i = X->n; i > 0; i--) {
Paul Bakker23986e52011-04-24 08:57:21 +00001036 r1 = X->p[i - 1] << (biL - v1);
1037 X->p[i - 1] >>= v1;
1038 X->p[i - 1] |= r0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001039 r0 = r1;
1040 }
1041 }
1042
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001043 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001044}
1045
1046/*
1047 * Compare unsigned values
1048 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001049int mbedtls_mpi_cmp_abs(const mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +00001050{
Paul Bakker23986e52011-04-24 08:57:21 +00001051 size_t i, j;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001052 MPI_VALIDATE_RET(X != NULL);
1053 MPI_VALIDATE_RET(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001054
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001055 for (i = X->n; i > 0; i--) {
1056 if (X->p[i - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001057 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001058 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001059 }
1060
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001061 for (j = Y->n; j > 0; j--) {
1062 if (Y->p[j - 1] != 0) {
1063 break;
1064 }
1065 }
1066
1067 if (i == 0 && j == 0) {
1068 return 0;
1069 }
1070
1071 if (i > j) {
1072 return 1;
1073 }
1074 if (j > i) {
1075 return -1;
1076 }
1077
1078 for (; i > 0; i--) {
1079 if (X->p[i - 1] > Y->p[i - 1]) {
1080 return 1;
1081 }
1082 if (X->p[i - 1] < Y->p[i - 1]) {
1083 return -1;
1084 }
1085 }
1086
1087 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001088}
1089
1090/*
1091 * Compare signed values
1092 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001093int mbedtls_mpi_cmp_mpi(const mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +00001094{
Paul Bakker23986e52011-04-24 08:57:21 +00001095 size_t i, j;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001096 MPI_VALIDATE_RET(X != NULL);
1097 MPI_VALIDATE_RET(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001098
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001099 for (i = X->n; i > 0; i--) {
1100 if (X->p[i - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001101 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001102 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001103 }
1104
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001105 for (j = Y->n; j > 0; j--) {
1106 if (Y->p[j - 1] != 0) {
1107 break;
1108 }
1109 }
1110
1111 if (i == 0 && j == 0) {
1112 return 0;
1113 }
1114
1115 if (i > j) {
1116 return X->s;
1117 }
1118 if (j > i) {
1119 return -Y->s;
1120 }
1121
1122 if (X->s > 0 && Y->s < 0) {
1123 return 1;
1124 }
1125 if (Y->s > 0 && X->s < 0) {
1126 return -1;
1127 }
1128
1129 for (; i > 0; i--) {
1130 if (X->p[i - 1] > Y->p[i - 1]) {
1131 return X->s;
1132 }
1133 if (X->p[i - 1] < Y->p[i - 1]) {
1134 return -X->s;
1135 }
1136 }
1137
1138 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001139}
1140
Janos Follathee6abce2019-09-05 14:47:19 +01001141/*
Paul Bakker5121ce52009-01-03 21:22:43 +00001142 * Compare signed values
1143 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001144int mbedtls_mpi_cmp_int(const mbedtls_mpi *X, mbedtls_mpi_sint z)
Paul Bakker5121ce52009-01-03 21:22:43 +00001145{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001146 mbedtls_mpi Y;
1147 mbedtls_mpi_uint p[1];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001148 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001149
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001150 *p = mpi_sint_abs(z);
1151 Y.s = (z < 0) ? -1 : 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001152 Y.n = 1;
1153 Y.p = p;
1154
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001155 return mbedtls_mpi_cmp_mpi(X, &Y);
Paul Bakker5121ce52009-01-03 21:22:43 +00001156}
1157
1158/*
1159 * Unsigned addition: X = |A| + |B| (HAC 14.7)
1160 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001161int mbedtls_mpi_add_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001162{
Janos Follath24eed8d2019-11-22 13:21:35 +00001163 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001164 size_t i, j;
Janos Follath6c922682015-10-30 17:43:11 +01001165 mbedtls_mpi_uint *o, *p, c, tmp;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001166 MPI_VALIDATE_RET(X != NULL);
1167 MPI_VALIDATE_RET(A != NULL);
1168 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001169
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001170 if (X == B) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001171 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +00001172 }
1173
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001174 if (X != A) {
1175 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
1176 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001177
Paul Bakkerf7ca7b92009-06-20 10:31:06 +00001178 /*
1179 * X should always be positive as a result of unsigned additions.
1180 */
1181 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001182
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001183 for (j = B->n; j > 0; j--) {
1184 if (B->p[j - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001185 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001186 }
1187 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001188
Gilles Peskine103cf592022-11-15 22:59:00 +01001189 /* Exit early to avoid undefined behavior on NULL+0 when X->n == 0
1190 * and B is 0 (of any size). */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001191 if (j == 0) {
1192 return 0;
1193 }
Gilles Peskine103cf592022-11-15 22:59:00 +01001194
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001195 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j));
Paul Bakker5121ce52009-01-03 21:22:43 +00001196
1197 o = B->p; p = X->p; c = 0;
1198
Janos Follath6c922682015-10-30 17:43:11 +01001199 /*
1200 * tmp is used because it might happen that p == o
1201 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001202 for (i = 0; i < j; i++, o++, p++) {
1203 tmp = *o;
1204 *p += c; c = (*p < c);
1205 *p += tmp; c += (*p < tmp);
Paul Bakker5121ce52009-01-03 21:22:43 +00001206 }
1207
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001208 while (c != 0) {
1209 if (i >= X->n) {
1210 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i + 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001211 p = X->p + i;
1212 }
1213
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001214 *p += c; c = (*p < c); i++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001215 }
1216
1217cleanup:
1218
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001219 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001220}
1221
Gilles Peskine09ec10a2020-06-09 10:39:38 +02001222/**
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001223 * Helper for mbedtls_mpi subtraction.
1224 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001225 * Calculate l - r where l and r have the same size.
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001226 * This function operates modulo (2^ciL)^n and returns the carry
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001227 * (1 if there was a wraparound, i.e. if `l < r`, and 0 otherwise).
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001228 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001229 * d may be aliased to l or r.
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001230 *
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001231 * \param n Number of limbs of \p d, \p l and \p r.
1232 * \param[out] d The result of the subtraction.
1233 * \param[in] l The left operand.
1234 * \param[in] r The right operand.
1235 *
1236 * \return 1 if `l < r`.
1237 * 0 if `l >= r`.
Paul Bakker5121ce52009-01-03 21:22:43 +00001238 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001239static mbedtls_mpi_uint mpi_sub_hlp(size_t n,
1240 mbedtls_mpi_uint *d,
1241 const mbedtls_mpi_uint *l,
1242 const mbedtls_mpi_uint *r)
Paul Bakker5121ce52009-01-03 21:22:43 +00001243{
Paul Bakker23986e52011-04-24 08:57:21 +00001244 size_t i;
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001245 mbedtls_mpi_uint c = 0, t, z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001246
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001247 for (i = 0; i < n; i++) {
1248 z = (l[i] < c); t = l[i] - c;
1249 c = (t < r[i]) + z; d[i] = t - r[i];
Paul Bakker5121ce52009-01-03 21:22:43 +00001250 }
1251
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001252 return c;
Paul Bakker5121ce52009-01-03 21:22:43 +00001253}
1254
1255/*
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001256 * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
Paul Bakker5121ce52009-01-03 21:22:43 +00001257 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001258int mbedtls_mpi_sub_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001259{
Janos Follath24eed8d2019-11-22 13:21:35 +00001260 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001261 size_t n;
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001262 mbedtls_mpi_uint carry;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001263 MPI_VALIDATE_RET(X != NULL);
1264 MPI_VALIDATE_RET(A != NULL);
1265 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001266
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001267 for (n = B->n; n > 0; n--) {
1268 if (B->p[n - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001269 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001270 }
1271 }
1272 if (n > A->n) {
Gilles Peskinec8a91772021-01-27 22:30:43 +01001273 /* B >= (2^ciL)^n > A */
1274 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1275 goto cleanup;
1276 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001277
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001278 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, A->n));
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001279
1280 /* Set the high limbs of X to match A. Don't touch the lower limbs
1281 * because X might be aliased to B, and we must not overwrite the
1282 * significant digits of B. */
Aaron M. Ucko78b823a2023-01-31 15:45:44 -05001283 if (A->n > n && A != X) {
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001284 memcpy(X->p + n, A->p + n, (A->n - n) * ciL);
1285 }
1286 if (X->n > A->n) {
1287 memset(X->p + A->n, 0, (X->n - A->n) * ciL);
1288 }
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001289
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001290 carry = mpi_sub_hlp(n, X->p, A->p, B->p);
1291 if (carry != 0) {
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001292 /* Propagate the carry to the first nonzero limb of X. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001293 for (; n < X->n && X->p[n] == 0; n++) {
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001294 --X->p[n];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001295 }
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001296 /* If we ran out of space for the carry, it means that the result
1297 * is negative. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001298 if (n == X->n) {
Gilles Peskine89b41302020-07-23 01:16:46 +02001299 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1300 goto cleanup;
1301 }
Gilles Peskine0e5faf62020-06-08 22:50:35 +02001302 --X->p[n];
Gilles Peskinec097e9e2020-06-08 21:58:22 +02001303 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001304
Gilles Peskine1acf7cb2020-07-23 01:03:22 +02001305 /* X should always be positive as a result of unsigned subtractions. */
1306 X->s = 1;
1307
Paul Bakker5121ce52009-01-03 21:22:43 +00001308cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001309 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001310}
1311
Gilles Peskine4e47bdc2022-11-09 21:34:09 +01001312/* Common function for signed addition and subtraction.
1313 * Calculate A + B * flip_B where flip_B is 1 or -1.
Paul Bakker5121ce52009-01-03 21:22:43 +00001314 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001315static int add_sub_mpi(mbedtls_mpi *X,
1316 const mbedtls_mpi *A, const mbedtls_mpi *B,
1317 int flip_B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001318{
Hanno Becker73d7d792018-12-11 10:35:51 +00001319 int ret, s;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001320 MPI_VALIDATE_RET(X != NULL);
1321 MPI_VALIDATE_RET(A != NULL);
1322 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001323
Hanno Becker73d7d792018-12-11 10:35:51 +00001324 s = A->s;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001325 if (A->s * B->s * flip_B < 0) {
1326 int cmp = mbedtls_mpi_cmp_abs(A, B);
1327 if (cmp >= 0) {
1328 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, A, B));
Gilles Peskine581c4602022-11-09 22:02:16 +01001329 /* If |A| = |B|, the result is 0 and we must set the sign bit
1330 * to +1 regardless of which of A or B was negative. Otherwise,
1331 * since |A| > |B|, the sign is the sign of A. */
1332 X->s = cmp == 0 ? 1 : s;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001333 } else {
1334 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, B, A));
Gilles Peskine581c4602022-11-09 22:02:16 +01001335 /* Since |A| < |B|, the sign is the opposite of A. */
Paul Bakker5121ce52009-01-03 21:22:43 +00001336 X->s = -s;
1337 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001338 } else {
1339 MBEDTLS_MPI_CHK(mbedtls_mpi_add_abs(X, A, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001340 X->s = s;
1341 }
1342
1343cleanup:
1344
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001345 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001346}
1347
1348/*
Gilles Peskine4e47bdc2022-11-09 21:34:09 +01001349 * Signed addition: X = A + B
1350 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001351int mbedtls_mpi_add_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Gilles Peskine4e47bdc2022-11-09 21:34:09 +01001352{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001353 return add_sub_mpi(X, A, B, 1);
Gilles Peskine4e47bdc2022-11-09 21:34:09 +01001354}
1355
1356/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001357 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001358 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001359int mbedtls_mpi_sub_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001360{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001361 return add_sub_mpi(X, A, B, -1);
Paul Bakker5121ce52009-01-03 21:22:43 +00001362}
1363
1364/*
1365 * Signed addition: X = A + b
1366 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001367int mbedtls_mpi_add_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001368{
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001369 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001370 mbedtls_mpi_uint p[1];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001371 MPI_VALIDATE_RET(X != NULL);
1372 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001373
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001374 p[0] = mpi_sint_abs(b);
1375 B.s = (b < 0) ? -1 : 1;
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001376 B.n = 1;
1377 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001378
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001379 return mbedtls_mpi_add_mpi(X, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00001380}
1381
1382/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001383 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001384 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001385int mbedtls_mpi_sub_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001386{
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001387 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001388 mbedtls_mpi_uint p[1];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001389 MPI_VALIDATE_RET(X != NULL);
1390 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001391
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001392 p[0] = mpi_sint_abs(b);
1393 B.s = (b < 0) ? -1 : 1;
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001394 B.n = 1;
1395 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001396
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001397 return mbedtls_mpi_sub_mpi(X, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00001398}
1399
Gilles Peskinea5d8d892020-07-23 21:27:15 +02001400/** Helper for mbedtls_mpi multiplication.
1401 *
1402 * Add \p b * \p s to \p d.
1403 *
1404 * \param i The number of limbs of \p s.
1405 * \param[in] s A bignum to multiply, of size \p i.
1406 * It may overlap with \p d, but only if
1407 * \p d <= \p s.
1408 * Its leading limb must not be \c 0.
1409 * \param[in,out] d The bignum to add to.
1410 * It must be sufficiently large to store the
1411 * result of the multiplication. This means
1412 * \p i + 1 limbs if \p d[\p i - 1] started as 0 and \p b
1413 * is not known a priori.
1414 * \param b A scalar to multiply.
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001415 */
1416static
1417#if defined(__APPLE__) && defined(__arm__)
1418/*
1419 * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1420 * appears to need this to prevent bad ARM code generation at -O3.
1421 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001422__attribute__((noinline))
Paul Bakkerfc4f46f2013-06-24 19:23:56 +02001423#endif
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001424void mpi_mul_hlp(size_t i,
1425 const mbedtls_mpi_uint *s,
1426 mbedtls_mpi_uint *d,
1427 mbedtls_mpi_uint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001428{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001429 mbedtls_mpi_uint c = 0, t = 0;
Gilles Peskined7848332023-02-24 12:08:01 +01001430 (void) t; /* Unused in some architectures */
Paul Bakker5121ce52009-01-03 21:22:43 +00001431
1432#if defined(MULADDC_HUIT)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001433 for (; i >= 8; i -= 8) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001434 MULADDC_INIT
1435 MULADDC_HUIT
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001436 MULADDC_STOP
Paul Bakker5121ce52009-01-03 21:22:43 +00001437 }
1438
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001439 for (; i > 0; i--) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001440 MULADDC_INIT
1441 MULADDC_CORE
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001442 MULADDC_STOP
Paul Bakker5121ce52009-01-03 21:22:43 +00001443 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001444#else /* MULADDC_HUIT */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001445 for (; i >= 16; i -= 16) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001446 MULADDC_INIT
1447 MULADDC_CORE MULADDC_CORE
1448 MULADDC_CORE MULADDC_CORE
1449 MULADDC_CORE MULADDC_CORE
1450 MULADDC_CORE MULADDC_CORE
1451
1452 MULADDC_CORE MULADDC_CORE
1453 MULADDC_CORE MULADDC_CORE
1454 MULADDC_CORE MULADDC_CORE
1455 MULADDC_CORE MULADDC_CORE
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001456 MULADDC_STOP
Paul Bakker5121ce52009-01-03 21:22:43 +00001457 }
1458
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001459 for (; i >= 8; i -= 8) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001460 MULADDC_INIT
1461 MULADDC_CORE MULADDC_CORE
1462 MULADDC_CORE MULADDC_CORE
1463
1464 MULADDC_CORE MULADDC_CORE
1465 MULADDC_CORE MULADDC_CORE
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001466 MULADDC_STOP
Paul Bakker5121ce52009-01-03 21:22:43 +00001467 }
1468
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001469 for (; i > 0; i--) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001470 MULADDC_INIT
1471 MULADDC_CORE
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001472 MULADDC_STOP
Paul Bakker5121ce52009-01-03 21:22:43 +00001473 }
Paul Bakker9af723c2014-05-01 13:03:14 +02001474#endif /* MULADDC_HUIT */
Paul Bakker5121ce52009-01-03 21:22:43 +00001475
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001476 while (c != 0) {
1477 *d += c; c = (*d < c); d++;
Paul Bakker5121ce52009-01-03 21:22:43 +00001478 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001479}
1480
1481/*
1482 * Baseline multiplication: X = A * B (HAC 14.12)
1483 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001484int mbedtls_mpi_mul_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001485{
Janos Follath24eed8d2019-11-22 13:21:35 +00001486 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001487 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001488 mbedtls_mpi TA, TB;
Gilles Peskined65b5002021-06-15 21:44:32 +02001489 int result_is_zero = 0;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001490 MPI_VALIDATE_RET(X != NULL);
1491 MPI_VALIDATE_RET(A != NULL);
1492 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001493
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001494 mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00001495
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001496 if (X == A) {
1497 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A)); A = &TA;
1498 }
1499 if (X == B) {
1500 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B)); B = &TB;
1501 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001502
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001503 for (i = A->n; i > 0; i--) {
1504 if (A->p[i - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001505 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001506 }
1507 }
1508 if (i == 0) {
Gilles Peskined65b5002021-06-15 21:44:32 +02001509 result_is_zero = 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001510 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001511
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001512 for (j = B->n; j > 0; j--) {
1513 if (B->p[j - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001514 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001515 }
1516 }
1517 if (j == 0) {
Gilles Peskined65b5002021-06-15 21:44:32 +02001518 result_is_zero = 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001519 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001520
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001521 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i + j));
1522 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
Paul Bakker5121ce52009-01-03 21:22:43 +00001523
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001524 for (; j > 0; j--) {
1525 mpi_mul_hlp(i, A->p, X->p + j - 1, B->p[j - 1]);
1526 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001527
Gilles Peskine70a7dcd2021-06-10 15:51:54 +02001528 /* If the result is 0, we don't shortcut the operation, which reduces
1529 * but does not eliminate side channels leaking the zero-ness. We do
1530 * need to take care to set the sign bit properly since the library does
1531 * not fully support an MPI object with a value of 0 and s == -1. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001532 if (result_is_zero) {
Gilles Peskine70a7dcd2021-06-10 15:51:54 +02001533 X->s = 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001534 } else {
Gilles Peskine70a7dcd2021-06-10 15:51:54 +02001535 X->s = A->s * B->s;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001536 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001537
1538cleanup:
1539
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001540 mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TA);
Paul Bakker5121ce52009-01-03 21:22:43 +00001541
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001542 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001543}
1544
1545/*
1546 * Baseline multiplication: X = A * b
1547 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001548int mbedtls_mpi_mul_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001549{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001550 MPI_VALIDATE_RET(X != NULL);
1551 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001552
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001553 /* mpi_mul_hlp can't deal with a leading 0. */
1554 size_t n = A->n;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001555 while (n > 0 && A->p[n - 1] == 0) {
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001556 --n;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001557 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001558
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001559 /* The general method below doesn't work if n==0 or b==0. By chance
1560 * calculating the result is trivial in those cases. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001561 if (b == 0 || n == 0) {
1562 return mbedtls_mpi_lset(X, 0);
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001563 }
1564
Gilles Peskinee1bba7c2021-03-10 23:44:10 +01001565 /* Calculate A*b as A + A*(b-1) to take advantage of mpi_mul_hlp */
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001566 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001567 /* In general, A * b requires 1 limb more than b. If
1568 * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same
1569 * number of limbs as A and the call to grow() is not required since
Gilles Peskinee1bba7c2021-03-10 23:44:10 +01001570 * copy() will take care of the growth if needed. However, experimentally,
1571 * making the call to grow() unconditional causes slightly fewer
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001572 * calls to calloc() in ECP code, presumably because it reuses the
1573 * same mpi for a while and this way the mpi is more likely to directly
1574 * grow to its final size. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001575 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n + 1));
1576 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
1577 mpi_mul_hlp(n, A->p, X->p, b - 1);
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001578
1579cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001580 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001581}
1582
1583/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001584 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1585 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001586 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001587static mbedtls_mpi_uint mbedtls_int_div_int(mbedtls_mpi_uint u1,
1588 mbedtls_mpi_uint u0,
1589 mbedtls_mpi_uint d,
1590 mbedtls_mpi_uint *r)
Simon Butcher15b15d12015-11-26 19:35:03 +00001591{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001592#if defined(MBEDTLS_HAVE_UDBL)
1593 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001594#else
Simon Butcher9803d072016-01-03 00:24:34 +00001595 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001596 const mbedtls_mpi_uint uint_halfword_mask = ((mbedtls_mpi_uint) 1 << biH) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001597 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1598 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001599 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001600#endif
1601
Simon Butcher15b15d12015-11-26 19:35:03 +00001602 /*
1603 * Check for overflow
1604 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001605 if (0 == d || u1 >= d) {
1606 if (r != NULL) {
1607 *r = ~(mbedtls_mpi_uint) 0u;
1608 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001609
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001610 return ~(mbedtls_mpi_uint) 0u;
Simon Butcher15b15d12015-11-26 19:35:03 +00001611 }
1612
1613#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001614 dividend = (mbedtls_t_udbl) u1 << biL;
1615 dividend |= (mbedtls_t_udbl) u0;
1616 quotient = dividend / d;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001617 if (quotient > ((mbedtls_t_udbl) 1 << biL) - 1) {
1618 quotient = ((mbedtls_t_udbl) 1 << biL) - 1;
1619 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001620
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001621 if (r != NULL) {
1622 *r = (mbedtls_mpi_uint) (dividend - (quotient * d));
1623 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001624
1625 return (mbedtls_mpi_uint) quotient;
1626#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001627
1628 /*
1629 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1630 * Vol. 2 - Seminumerical Algorithms, Knuth
1631 */
1632
1633 /*
1634 * Normalize the divisor, d, and dividend, u0, u1
1635 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001636 s = mbedtls_clz(d);
Simon Butcher15b15d12015-11-26 19:35:03 +00001637 d = d << s;
1638
1639 u1 = u1 << s;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001640 u1 |= (u0 >> (biL - s)) & (-(mbedtls_mpi_sint) s >> (biL - 1));
Simon Butcher15b15d12015-11-26 19:35:03 +00001641 u0 = u0 << s;
1642
1643 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001644 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001645
1646 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001647 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001648
1649 /*
1650 * Find the first quotient and remainder
1651 */
1652 q1 = u1 / d1;
1653 r0 = u1 - d1 * q1;
1654
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001655 while (q1 >= radix || (q1 * d0 > radix * r0 + u0_msw)) {
Simon Butcher15b15d12015-11-26 19:35:03 +00001656 q1 -= 1;
1657 r0 += d1;
1658
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001659 if (r0 >= radix) {
1660 break;
1661 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001662 }
1663
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001664 rAX = (u1 * radix) + (u0_msw - q1 * d);
Simon Butcher15b15d12015-11-26 19:35:03 +00001665 q0 = rAX / d1;
1666 r0 = rAX - q0 * d1;
1667
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001668 while (q0 >= radix || (q0 * d0 > radix * r0 + u0_lsw)) {
Simon Butcher15b15d12015-11-26 19:35:03 +00001669 q0 -= 1;
1670 r0 += d1;
1671
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001672 if (r0 >= radix) {
1673 break;
1674 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001675 }
1676
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001677 if (r != NULL) {
1678 *r = (rAX * radix + u0_lsw - q0 * d) >> s;
1679 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001680
1681 quotient = q1 * radix + q0;
1682
1683 return quotient;
1684#endif
1685}
1686
1687/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001688 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001689 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001690int mbedtls_mpi_div_mpi(mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1691 const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001692{
Janos Follath24eed8d2019-11-22 13:21:35 +00001693 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001694 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001695 mbedtls_mpi X, Y, Z, T1, T2;
Alexander Kd19a1932019-11-01 18:20:42 +03001696 mbedtls_mpi_uint TP2[3];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001697 MPI_VALIDATE_RET(A != NULL);
1698 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001699
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001700 if (mbedtls_mpi_cmp_int(B, 0) == 0) {
1701 return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
1702 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001703
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001704 mbedtls_mpi_init(&X); mbedtls_mpi_init(&Y); mbedtls_mpi_init(&Z);
1705 mbedtls_mpi_init(&T1);
Alexander Kd19a1932019-11-01 18:20:42 +03001706 /*
1707 * Avoid dynamic memory allocations for constant-size T2.
1708 *
1709 * T2 is used for comparison only and the 3 limbs are assigned explicitly,
1710 * so nobody increase the size of the MPI and we're safe to use an on-stack
1711 * buffer.
1712 */
Alexander K35d6d462019-10-31 14:46:45 +03001713 T2.s = 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001714 T2.n = sizeof(TP2) / sizeof(*TP2);
Alexander Kd19a1932019-11-01 18:20:42 +03001715 T2.p = TP2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001716
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001717 if (mbedtls_mpi_cmp_abs(A, B) < 0) {
1718 if (Q != NULL) {
1719 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(Q, 0));
1720 }
1721 if (R != NULL) {
1722 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, A));
1723 }
1724 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001725 }
1726
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001727 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&X, A));
1728 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001729 X.s = Y.s = 1;
1730
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001731 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&Z, A->n + 2));
1732 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Z, 0));
1733 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T1, A->n + 2));
Paul Bakker5121ce52009-01-03 21:22:43 +00001734
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001735 k = mbedtls_mpi_bitlen(&Y) % biL;
1736 if (k < biL - 1) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001737 k = biL - 1 - k;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001738 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&X, k));
1739 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, k));
1740 } else {
1741 k = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001742 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001743
1744 n = X.n - 1;
1745 t = Y.n - 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001746 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, biL * (n - t)));
Paul Bakker5121ce52009-01-03 21:22:43 +00001747
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001748 while (mbedtls_mpi_cmp_mpi(&X, &Y) >= 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001749 Z.p[n - t]++;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001750 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &Y));
Paul Bakker5121ce52009-01-03 21:22:43 +00001751 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001752 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, biL * (n - t)));
Paul Bakker5121ce52009-01-03 21:22:43 +00001753
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001754 for (i = n; i > t; i--) {
1755 if (X.p[i] >= Y.p[t]) {
1756 Z.p[i - t - 1] = ~(mbedtls_mpi_uint) 0u;
1757 } else {
1758 Z.p[i - t - 1] = mbedtls_int_div_int(X.p[i], X.p[i - 1],
1759 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001760 }
1761
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001762 T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
1763 T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
Alexander K35d6d462019-10-31 14:46:45 +03001764 T2.p[2] = X.p[i];
1765
Paul Bakker5121ce52009-01-03 21:22:43 +00001766 Z.p[i - t - 1]++;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001767 do {
Paul Bakker5121ce52009-01-03 21:22:43 +00001768 Z.p[i - t - 1]--;
1769
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001770 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&T1, 0));
1771 T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001772 T1.p[1] = Y.p[t];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001773 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &T1, Z.p[i - t - 1]));
1774 } while (mbedtls_mpi_cmp_mpi(&T1, &T2) > 0);
Paul Bakker5121ce52009-01-03 21:22:43 +00001775
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001776 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &Y, Z.p[i - t - 1]));
1777 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1)));
1778 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &T1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001779
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001780 if (mbedtls_mpi_cmp_int(&X, 0) < 0) {
1781 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T1, &Y));
1782 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1)));
1783 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&X, &X, &T1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001784 Z.p[i - t - 1]--;
1785 }
1786 }
1787
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001788 if (Q != NULL) {
1789 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(Q, &Z));
Paul Bakker5121ce52009-01-03 21:22:43 +00001790 Q->s = A->s * B->s;
1791 }
1792
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001793 if (R != NULL) {
1794 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&X, k));
Paul Bakkerf02c5642012-11-13 10:25:21 +00001795 X.s = A->s;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001796 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, &X));
Paul Bakker5121ce52009-01-03 21:22:43 +00001797
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001798 if (mbedtls_mpi_cmp_int(R, 0) == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001799 R->s = 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001800 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001801 }
1802
1803cleanup:
1804
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001805 mbedtls_mpi_free(&X); mbedtls_mpi_free(&Y); mbedtls_mpi_free(&Z);
1806 mbedtls_mpi_free(&T1);
1807 mbedtls_platform_zeroize(TP2, sizeof(TP2));
Paul Bakker5121ce52009-01-03 21:22:43 +00001808
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001809 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001810}
1811
1812/*
1813 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001814 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001815int mbedtls_mpi_div_int(mbedtls_mpi *Q, mbedtls_mpi *R,
1816 const mbedtls_mpi *A,
1817 mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001818{
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001819 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001820 mbedtls_mpi_uint p[1];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001821 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001822
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001823 p[0] = mpi_sint_abs(b);
1824 B.s = (b < 0) ? -1 : 1;
Yuto Takanobc6eaf72021-07-05 09:10:52 +01001825 B.n = 1;
1826 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001827
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001828 return mbedtls_mpi_div_mpi(Q, R, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00001829}
1830
1831/*
1832 * Modulo: R = A mod B
1833 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001834int mbedtls_mpi_mod_mpi(mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001835{
Janos Follath24eed8d2019-11-22 13:21:35 +00001836 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001837 MPI_VALIDATE_RET(R != NULL);
1838 MPI_VALIDATE_RET(A != NULL);
1839 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001840
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001841 if (mbedtls_mpi_cmp_int(B, 0) < 0) {
1842 return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1843 }
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001844
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001845 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(NULL, R, A, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001846
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001847 while (mbedtls_mpi_cmp_int(R, 0) < 0) {
1848 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(R, R, B));
1849 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001850
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001851 while (mbedtls_mpi_cmp_mpi(R, B) >= 0) {
1852 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(R, R, B));
1853 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001854
1855cleanup:
1856
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001857 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001858}
1859
1860/*
1861 * Modulo: r = A mod b
1862 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001863int mbedtls_mpi_mod_int(mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001864{
Paul Bakker23986e52011-04-24 08:57:21 +00001865 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001866 mbedtls_mpi_uint x, y, z;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001867 MPI_VALIDATE_RET(r != NULL);
1868 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001869
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001870 if (b == 0) {
1871 return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
1872 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001873
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001874 if (b < 0) {
1875 return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1876 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001877
1878 /*
1879 * handle trivial cases
1880 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001881 if (b == 1 || A->n == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001882 *r = 0;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001883 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001884 }
1885
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001886 if (b == 2) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001887 *r = A->p[0] & 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001888 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001889 }
1890
1891 /*
1892 * general case
1893 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001894 for (i = A->n, y = 0; i > 0; i--) {
Paul Bakker23986e52011-04-24 08:57:21 +00001895 x = A->p[i - 1];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001896 y = (y << biH) | (x >> biH);
Paul Bakker5121ce52009-01-03 21:22:43 +00001897 z = y / b;
1898 y -= z * b;
1899
1900 x <<= biH;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001901 y = (y << biH) | (x >> biH);
Paul Bakker5121ce52009-01-03 21:22:43 +00001902 z = y / b;
1903 y -= z * b;
1904 }
1905
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001906 /*
1907 * If A is negative, then the current y represents a negative value.
1908 * Flipping it to the positive side.
1909 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001910 if (A->s < 0 && y != 0) {
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001911 y = b - y;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001912 }
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001913
Paul Bakker5121ce52009-01-03 21:22:43 +00001914 *r = y;
1915
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001916 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001917}
1918
1919/*
1920 * Fast Montgomery initialization (thanks to Tom St Denis)
1921 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001922static void mpi_montg_init(mbedtls_mpi_uint *mm, const mbedtls_mpi *N)
Paul Bakker5121ce52009-01-03 21:22:43 +00001923{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001924 mbedtls_mpi_uint x, m0 = N->p[0];
Manuel Pégourié-Gonnardfdf3f0e2014-03-11 13:47:05 +01001925 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001926
1927 x = m0;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001928 x += ((m0 + 2) & 4) << 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001929
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001930 for (i = biL; i >= 8; i /= 2) {
1931 x *= (2 - (m0 * x));
1932 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001933
1934 *mm = ~x + 1;
1935}
1936
Gilles Peskine2a82f722020-06-04 15:00:49 +02001937/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1938 *
1939 * \param[in,out] A One of the numbers to multiply.
Gilles Peskine221626f2020-06-08 22:37:50 +02001940 * It must have at least as many limbs as N
1941 * (A->n >= N->n), and any limbs beyond n are ignored.
Gilles Peskine2a82f722020-06-04 15:00:49 +02001942 * On successful completion, A contains the result of
1943 * the multiplication A * B * R^-1 mod N where
1944 * R = (2^ciL)^n.
1945 * \param[in] B One of the numbers to multiply.
1946 * It must be nonzero and must not have more limbs than N
1947 * (B->n <= N->n).
1948 * \param[in] N The modulo. N must be odd.
1949 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
1950 * This is -N^-1 mod 2^ciL.
1951 * \param[in,out] T A bignum for temporary storage.
1952 * It must be at least twice the limb size of N plus 2
1953 * (T->n >= 2 * (N->n + 1)).
1954 * Its initial content is unused and
1955 * its final content is indeterminate.
1956 * Note that unlike the usual convention in the library
1957 * for `const mbedtls_mpi*`, the content of T can change.
Paul Bakker5121ce52009-01-03 21:22:43 +00001958 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001959static void mpi_montmul(mbedtls_mpi *A,
1960 const mbedtls_mpi *B,
1961 const mbedtls_mpi *N,
1962 mbedtls_mpi_uint mm,
1963 const mbedtls_mpi *T)
Paul Bakker5121ce52009-01-03 21:22:43 +00001964{
Paul Bakker23986e52011-04-24 08:57:21 +00001965 size_t i, n, m;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001966 mbedtls_mpi_uint u0, u1, *d;
Paul Bakker5121ce52009-01-03 21:22:43 +00001967
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001968 memset(T->p, 0, T->n * ciL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001969
1970 d = T->p;
1971 n = N->n;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001972 m = (B->n < n) ? B->n : n;
Paul Bakker5121ce52009-01-03 21:22:43 +00001973
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001974 for (i = 0; i < n; i++) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001975 /*
1976 * T = (T + u0*B + u1*N) / 2^biL
1977 */
1978 u0 = A->p[i];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001979 u1 = (d[0] + u0 * B->p[0]) * mm;
Paul Bakker5121ce52009-01-03 21:22:43 +00001980
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001981 mpi_mul_hlp(m, B->p, d, u0);
1982 mpi_mul_hlp(n, N->p, d, u1);
Paul Bakker5121ce52009-01-03 21:22:43 +00001983
1984 *d++ = u0; d[n + 1] = 0;
1985 }
1986
Gilles Peskine221626f2020-06-08 22:37:50 +02001987 /* At this point, d is either the desired result or the desired result
1988 * plus N. We now potentially subtract N, avoiding leaking whether the
1989 * subtraction is performed through side channels. */
Paul Bakker5121ce52009-01-03 21:22:43 +00001990
Gilles Peskine221626f2020-06-08 22:37:50 +02001991 /* Copy the n least significant limbs of d to A, so that
1992 * A = d if d < N (recall that N has n limbs). */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001993 memcpy(A->p, d, n * ciL);
Gilles Peskine09ec10a2020-06-09 10:39:38 +02001994 /* If d >= N then we want to set A to d - N. To prevent timing attacks,
Gilles Peskine221626f2020-06-08 22:37:50 +02001995 * do the calculation without using conditional tests. */
1996 /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */
Gilles Peskine132c0972020-06-04 21:05:24 +02001997 d[n] += 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001998 d[n] -= mpi_sub_hlp(n, d, d, N->p);
Gilles Peskine221626f2020-06-08 22:37:50 +02001999 /* If d0 < N then d < (2^biL)^n
2000 * so d[n] == 0 and we want to keep A as it is.
2001 * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n
2002 * so d[n] == 1 and we want to set A to the result of the subtraction
2003 * which is d - (2^biL)^n, i.e. the n least significant limbs of d.
2004 * This exactly corresponds to a conditional assignment. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002005 mbedtls_ct_mpi_uint_cond_assign(n, A->p, d, (unsigned char) d[n]);
Paul Bakker5121ce52009-01-03 21:22:43 +00002006}
2007
2008/*
2009 * Montgomery reduction: A = A * R^-1 mod N
Gilles Peskine2a82f722020-06-04 15:00:49 +02002010 *
2011 * See mpi_montmul() regarding constraints and guarantees on the parameters.
Paul Bakker5121ce52009-01-03 21:22:43 +00002012 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002013static void mpi_montred(mbedtls_mpi *A, const mbedtls_mpi *N,
2014 mbedtls_mpi_uint mm, const mbedtls_mpi *T)
Paul Bakker5121ce52009-01-03 21:22:43 +00002015{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002016 mbedtls_mpi_uint z = 1;
2017 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00002018
Paul Bakker8ddb6452013-02-27 14:56:33 +01002019 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00002020 U.p = &z;
2021
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002022 mpi_montmul(A, &U, N, mm, T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002023}
2024
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002025/**
2026 * Select an MPI from a table without leaking the index.
2027 *
2028 * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it
2029 * reads the entire table in order to avoid leaking the value of idx to an
2030 * attacker able to observe memory access patterns.
2031 *
2032 * \param[out] R Where to write the selected MPI.
2033 * \param[in] T The table to read from.
2034 * \param[in] T_size The number of elements in the table.
2035 * \param[in] idx The index of the element to select;
2036 * this must satisfy 0 <= idx < T_size.
2037 *
2038 * \return \c 0 on success, or a negative error code.
2039 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002040static int mpi_select(mbedtls_mpi *R, const mbedtls_mpi *T, size_t T_size, size_t idx)
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002041{
2042 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2043
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002044 for (size_t i = 0; i < T_size; i++) {
2045 MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign(R, &T[i],
2046 (unsigned char) mbedtls_ct_size_bool_eq(i,
2047 idx)));
Manuel Pégourié-Gonnardeaafa492021-06-03 10:42:46 +02002048 }
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002049
2050cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002051 return ret;
Manuel Pégourié-Gonnarde10e8db2021-03-09 11:22:20 +01002052}
2053
Paul Bakker5121ce52009-01-03 21:22:43 +00002054/*
2055 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
2056 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002057int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A,
2058 const mbedtls_mpi *E, const mbedtls_mpi *N,
2059 mbedtls_mpi *prec_RR)
Paul Bakker5121ce52009-01-03 21:22:43 +00002060{
Janos Follath24eed8d2019-11-22 13:21:35 +00002061 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follathd88e2192022-11-21 15:54:20 +00002062 size_t window_bitsize;
Paul Bakker23986e52011-04-24 08:57:21 +00002063 size_t i, j, nblimbs;
2064 size_t bufsize, nbits;
Paul Elliottfc820d92023-01-13 16:29:30 +00002065 size_t exponent_bits_in_window = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002066 mbedtls_mpi_uint ei, mm, state;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002067 mbedtls_mpi RR, T, W[(size_t) 1 << MBEDTLS_MPI_WINDOW_SIZE], WW, Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00002068 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00002069
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002070 MPI_VALIDATE_RET(X != NULL);
2071 MPI_VALIDATE_RET(A != NULL);
2072 MPI_VALIDATE_RET(E != NULL);
2073 MPI_VALIDATE_RET(N != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00002074
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002075 if (mbedtls_mpi_cmp_int(N, 0) <= 0 || (N->p[0] & 1) == 0) {
2076 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2077 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002078
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002079 if (mbedtls_mpi_cmp_int(E, 0) < 0) {
2080 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2081 }
Paul Bakkerf6198c12012-05-16 08:02:29 +00002082
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002083 if (mbedtls_mpi_bitlen(E) > MBEDTLS_MPI_MAX_BITS ||
2084 mbedtls_mpi_bitlen(N) > MBEDTLS_MPI_MAX_BITS) {
2085 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2086 }
Chris Jones9246d042020-11-25 15:12:39 +00002087
Paul Bakkerf6198c12012-05-16 08:02:29 +00002088 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002089 * Init temps and window size
2090 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002091 mpi_montg_init(&mm, N);
2092 mbedtls_mpi_init(&RR); mbedtls_mpi_init(&T);
2093 mbedtls_mpi_init(&Apos);
2094 mbedtls_mpi_init(&WW);
2095 memset(W, 0, sizeof(W));
Paul Bakker5121ce52009-01-03 21:22:43 +00002096
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002097 i = mbedtls_mpi_bitlen(E);
Paul Bakker5121ce52009-01-03 21:22:43 +00002098
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002099 window_bitsize = (i > 671) ? 6 : (i > 239) ? 5 :
2100 (i > 79) ? 4 : (i > 23) ? 3 : 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002101
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002102#if (MBEDTLS_MPI_WINDOW_SIZE < 6)
2103 if (window_bitsize > MBEDTLS_MPI_WINDOW_SIZE) {
Janos Follath66323832022-11-21 14:48:02 +00002104 window_bitsize = MBEDTLS_MPI_WINDOW_SIZE;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002105 }
Peter Kolbuse6bcad32018-12-11 14:01:44 -06002106#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00002107
Janos Follath6c5b5ad2022-11-22 10:47:10 +00002108 const size_t w_table_used_size = (size_t) 1 << window_bitsize;
Janos Follath6fa7a762022-11-22 10:18:06 +00002109
Paul Bakker5121ce52009-01-03 21:22:43 +00002110 /*
Janos Follath6e2d8e32022-11-21 16:14:54 +00002111 * This function is not constant-trace: its memory accesses depend on the
2112 * exponent value. To defend against timing attacks, callers (such as RSA
2113 * and DHM) should use exponent blinding. However this is not enough if the
2114 * adversary can find the exponent in a single trace, so this function
2115 * takes extra precautions against adversaries who can observe memory
2116 * access patterns.
Janos Follath3a3c50c2022-11-11 15:56:38 +00002117 *
Janos Follath6e2d8e32022-11-21 16:14:54 +00002118 * This function performs a series of multiplications by table elements and
2119 * squarings, and we want the prevent the adversary from finding out which
2120 * table element was used, and from distinguishing between multiplications
2121 * and squarings. Firstly, when multiplying by an element of the window
2122 * W[i], we do a constant-trace table lookup to obfuscate i. This leaves
2123 * squarings as having a different memory access patterns from other
Gilles Peskine20d54e32023-08-10 15:59:28 +02002124 * multiplications. So secondly, we put the accumulator in the table as
2125 * well, and also do a constant-trace table lookup to multiply by the
2126 * accumulator which is W[x_index].
Janos Follath6e2d8e32022-11-21 16:14:54 +00002127 *
2128 * This way, all multiplications take the form of a lookup-and-multiply.
2129 * The number of lookup-and-multiply operations inside each iteration of
2130 * the main loop still depends on the bits of the exponent, but since the
2131 * other operations in the loop don't have an easily recognizable memory
2132 * trace, an adversary is unlikely to be able to observe the exact
2133 * patterns.
2134 *
2135 * An adversary may still be able to recover the exponent if they can
2136 * observe both memory accesses and branches. However, branch prediction
2137 * exploitation typically requires many traces of execution over the same
2138 * data, which is defeated by randomized blinding.
Janos Follath91c02862022-10-04 13:27:40 +01002139 */
Janos Follath6c5b5ad2022-11-22 10:47:10 +00002140 const size_t x_index = 0;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002141 mbedtls_mpi_init(&W[x_index]);
Janos Follathf0ceb1c2022-11-21 14:31:22 +00002142
2143 j = N->n + 1;
Gilles Peskine20d54e32023-08-10 15:59:28 +02002144 /* All W[i] including the accumulator must have at least N->n limbs for
2145 * the mpi_montmul() and mpi_montred() calls later. Here we ensure that
2146 * W[1] and the accumulator W[x_index] are large enough. later we'll grow
2147 * other W[i] to the same length. They must not be shrunk midway through
2148 * this function!
Janos Follath3a3c50c2022-11-11 15:56:38 +00002149 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002150 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[x_index], j));
2151 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1], j));
2152 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T, j * 2));
Janos Follath91c02862022-10-04 13:27:40 +01002153
2154 /*
Paul Bakker50546922012-05-19 08:40:49 +00002155 * Compensate for negative A (and correct at the end)
2156 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002157 neg = (A->s == -1);
2158 if (neg) {
2159 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Apos, A));
Paul Bakker50546922012-05-19 08:40:49 +00002160 Apos.s = 1;
2161 A = &Apos;
2162 }
2163
2164 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00002165 * If 1st call, pre-compute R^2 mod N
2166 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002167 if (prec_RR == NULL || prec_RR->p == NULL) {
2168 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&RR, 1));
2169 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&RR, N->n * 2 * biL));
2170 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&RR, &RR, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002171
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002172 if (prec_RR != NULL) {
2173 memcpy(prec_RR, &RR, sizeof(mbedtls_mpi));
2174 }
2175 } else {
2176 memcpy(&RR, prec_RR, sizeof(mbedtls_mpi));
Paul Bakker5121ce52009-01-03 21:22:43 +00002177 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002178
2179 /*
2180 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
2181 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002182 if (mbedtls_mpi_cmp_mpi(A, N) >= 0) {
2183 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&W[1], A, N));
Gilles Peskinef643e8e2021-06-08 23:17:42 +02002184 /* This should be a no-op because W[1] is already that large before
2185 * mbedtls_mpi_mod_mpi(), but it's necessary to avoid an overflow
2186 * in mpi_montmul() below, so let's make sure. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002187 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1], N->n + 1));
2188 } else {
2189 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[1], A));
Gilles Peskinef643e8e2021-06-08 23:17:42 +02002190 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002191
Gilles Peskinef643e8e2021-06-08 23:17:42 +02002192 /* Note that this is safe because W[1] always has at least N->n limbs
2193 * (it grew above and was preserved by mbedtls_mpi_copy()). */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002194 mpi_montmul(&W[1], &RR, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002195
2196 /*
Janos Follath91c02862022-10-04 13:27:40 +01002197 * W[x_index] = R^2 * R^-1 mod N = R mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00002198 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002199 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[x_index], &RR));
2200 mpi_montred(&W[x_index], N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002201
Janos Follath6c5b5ad2022-11-22 10:47:10 +00002202
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002203 if (window_bitsize > 1) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002204 /*
Janos Follathd88e2192022-11-21 15:54:20 +00002205 * W[i] = W[1] ^ i
2206 *
2207 * The first bit of the sliding window is always 1 and therefore we
2208 * only need to store the second half of the table.
Janos Follath6c5b5ad2022-11-22 10:47:10 +00002209 *
2210 * (There are two special elements in the table: W[0] for the
2211 * accumulator/result and W[1] for A in Montgomery form. Both of these
2212 * are already set at this point.)
Paul Bakker5121ce52009-01-03 21:22:43 +00002213 */
Janos Follathd88e2192022-11-21 15:54:20 +00002214 j = w_table_used_size / 2;
Paul Bakker5121ce52009-01-03 21:22:43 +00002215
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002216 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[j], N->n + 1));
2217 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[j], &W[1]));
Paul Bakker5121ce52009-01-03 21:22:43 +00002218
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002219 for (i = 0; i < window_bitsize - 1; i++) {
2220 mpi_montmul(&W[j], &W[j], N, mm, &T);
2221 }
Paul Bakker0d7702c2013-10-29 16:18:35 +01002222
Paul Bakker5121ce52009-01-03 21:22:43 +00002223 /*
2224 * W[i] = W[i - 1] * W[1]
2225 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002226 for (i = j + 1; i < w_table_used_size; i++) {
2227 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[i], N->n + 1));
2228 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[i], &W[i - 1]));
Paul Bakker5121ce52009-01-03 21:22:43 +00002229
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002230 mpi_montmul(&W[i], &W[1], N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002231 }
2232 }
2233
2234 nblimbs = E->n;
2235 bufsize = 0;
2236 nbits = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00002237 state = 0;
2238
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002239 while (1) {
2240 if (bufsize == 0) {
2241 if (nblimbs == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002242 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002243 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002244
Paul Bakker0d7702c2013-10-29 16:18:35 +01002245 nblimbs--;
2246
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002247 bufsize = sizeof(mbedtls_mpi_uint) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00002248 }
2249
2250 bufsize--;
2251
2252 ei = (E->p[nblimbs] >> bufsize) & 1;
2253
2254 /*
2255 * skip leading 0s
2256 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002257 if (ei == 0 && state == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002258 continue;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002259 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002260
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002261 if (ei == 0 && state == 1) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002262 /*
Janos Follath91c02862022-10-04 13:27:40 +01002263 * out of window, square W[x_index]
Paul Bakker5121ce52009-01-03 21:22:43 +00002264 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002265 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index));
2266 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002267 continue;
2268 }
2269
2270 /*
2271 * add ei to current window
2272 */
2273 state = 2;
2274
2275 nbits++;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002276 exponent_bits_in_window |= (ei << (window_bitsize - nbits));
Paul Bakker5121ce52009-01-03 21:22:43 +00002277
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002278 if (nbits == window_bitsize) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002279 /*
Janos Follath66323832022-11-21 14:48:02 +00002280 * W[x_index] = W[x_index]^window_bitsize R^-1 mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00002281 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002282 for (i = 0; i < window_bitsize; i++) {
2283 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size,
2284 x_index));
2285 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Janos Follath95655a22022-10-04 14:00:09 +01002286 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002287
2288 /*
Janos Follath66323832022-11-21 14:48:02 +00002289 * W[x_index] = W[x_index] * W[exponent_bits_in_window] R^-1 mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00002290 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002291 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size,
2292 exponent_bits_in_window));
2293 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002294
2295 state--;
2296 nbits = 0;
Janos Follath66323832022-11-21 14:48:02 +00002297 exponent_bits_in_window = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00002298 }
2299 }
2300
2301 /*
2302 * process the remaining bits
2303 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002304 for (i = 0; i < nbits; i++) {
2305 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index));
2306 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002307
Janos Follath66323832022-11-21 14:48:02 +00002308 exponent_bits_in_window <<= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00002309
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002310 if ((exponent_bits_in_window & ((size_t) 1 << window_bitsize)) != 0) {
2311 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, 1));
2312 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Janos Follath95655a22022-10-04 14:00:09 +01002313 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002314 }
2315
2316 /*
Janos Follath91c02862022-10-04 13:27:40 +01002317 * W[x_index] = A^E * R * R^-1 mod N = A^E mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00002318 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002319 mpi_montred(&W[x_index], N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00002320
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002321 if (neg && E->n != 0 && (E->p[0] & 1) != 0) {
Janos Follath91c02862022-10-04 13:27:40 +01002322 W[x_index].s = -1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002323 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&W[x_index], N, &W[x_index]));
Paul Bakkerf6198c12012-05-16 08:02:29 +00002324 }
2325
Janos Follath91c02862022-10-04 13:27:40 +01002326 /*
2327 * Load the result in the output variable.
2328 */
Chien Wong0118a1d2023-08-01 21:38:46 +08002329 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &W[x_index]));
Janos Follath91c02862022-10-04 13:27:40 +01002330
Paul Bakker5121ce52009-01-03 21:22:43 +00002331cleanup:
2332
Janos Follatha92f9152022-11-21 15:05:31 +00002333 /* The first bit of the sliding window is always 1 and therefore the first
2334 * half of the table was unused. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002335 for (i = w_table_used_size/2; i < w_table_used_size; i++) {
2336 mbedtls_mpi_free(&W[i]);
2337 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002338
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002339 mbedtls_mpi_free(&W[x_index]);
2340 mbedtls_mpi_free(&W[1]);
2341 mbedtls_mpi_free(&T);
2342 mbedtls_mpi_free(&Apos);
2343 mbedtls_mpi_free(&WW);
Paul Bakker6c591fa2011-05-05 11:49:20 +00002344
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002345 if (prec_RR == NULL || prec_RR->p == NULL) {
2346 mbedtls_mpi_free(&RR);
2347 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002348
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002349 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002350}
2351
Paul Bakker5121ce52009-01-03 21:22:43 +00002352/*
2353 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
2354 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002355int mbedtls_mpi_gcd(mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00002356{
Janos Follath24eed8d2019-11-22 13:21:35 +00002357 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00002358 size_t lz, lzt;
Alexander Ke8ad49f2019-08-16 16:16:07 +03002359 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00002360
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002361 MPI_VALIDATE_RET(G != NULL);
2362 MPI_VALIDATE_RET(A != NULL);
2363 MPI_VALIDATE_RET(B != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00002364
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002365 mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00002366
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002367 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A));
2368 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00002369
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002370 lz = mbedtls_mpi_lsb(&TA);
2371 lzt = mbedtls_mpi_lsb(&TB);
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002372
Gilles Peskineb5e56ec2021-06-09 13:26:43 +02002373 /* The loop below gives the correct result when A==0 but not when B==0.
2374 * So have a special case for B==0. Leverage the fact that we just
2375 * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test
2376 * slightly more efficient than cmp_int(). */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002377 if (lzt == 0 && mbedtls_mpi_get_bit(&TB, 0) == 0) {
2378 ret = mbedtls_mpi_copy(G, A);
Gilles Peskineb5e56ec2021-06-09 13:26:43 +02002379 goto cleanup;
2380 }
2381
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002382 if (lzt < lz) {
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002383 lz = lzt;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002384 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002385
Paul Bakker5121ce52009-01-03 21:22:43 +00002386 TA.s = TB.s = 1;
2387
Gilles Peskineea9aa142021-06-16 13:42:04 +02002388 /* We mostly follow the procedure described in HAC 14.54, but with some
2389 * minor differences:
2390 * - Sequences of multiplications or divisions by 2 are grouped into a
2391 * single shift operation.
Gilles Peskine37d690c2021-06-21 18:58:39 +02002392 * - The procedure in HAC assumes that 0 < TB <= TA.
2393 * - The condition TB <= TA is not actually necessary for correctness.
2394 * TA and TB have symmetric roles except for the loop termination
2395 * condition, and the shifts at the beginning of the loop body
2396 * remove any significance from the ordering of TA vs TB before
2397 * the shifts.
2398 * - If TA = 0, the loop goes through 0 iterations and the result is
2399 * correctly TB.
2400 * - The case TB = 0 was short-circuited above.
Gilles Peskineea9aa142021-06-16 13:42:04 +02002401 *
2402 * For the correctness proof below, decompose the original values of
2403 * A and B as
2404 * A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1
2405 * B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1
2406 * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'),
2407 * and gcd(A',B') is odd or 0.
2408 *
2409 * At the beginning, we have TA = |A| and TB = |B| so gcd(A,B) = gcd(TA,TB).
2410 * The code maintains the following invariant:
2411 * gcd(A,B) = 2^k * gcd(TA,TB) for some k (I)
Gilles Peskine6537bdb2021-06-15 22:09:39 +02002412 */
2413
Gilles Peskineea9aa142021-06-16 13:42:04 +02002414 /* Proof that the loop terminates:
2415 * At each iteration, either the right-shift by 1 is made on a nonzero
2416 * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases
2417 * by at least 1, or the right-shift by 1 is made on zero and then
2418 * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted
2419 * since in that case TB is calculated from TB-TA with the condition TB>TA).
2420 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002421 while (mbedtls_mpi_cmp_int(&TA, 0) != 0) {
Gilles Peskineea9aa142021-06-16 13:42:04 +02002422 /* Divisions by 2 preserve the invariant (I). */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002423 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, mbedtls_mpi_lsb(&TA)));
2424 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, mbedtls_mpi_lsb(&TB)));
Paul Bakker5121ce52009-01-03 21:22:43 +00002425
Gilles Peskineea9aa142021-06-16 13:42:04 +02002426 /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd,
2427 * TA-TB is even so the division by 2 has an integer result.
2428 * Invariant (I) is preserved since any odd divisor of both TA and TB
2429 * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2
Shaun Case0e7791f2021-12-20 21:14:10 -08002430 * also divides TB, and any odd divisor of both TB and |TA-TB|/2 also
Gilles Peskineea9aa142021-06-16 13:42:04 +02002431 * divides TA.
2432 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002433 if (mbedtls_mpi_cmp_mpi(&TA, &TB) >= 0) {
2434 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TA, &TA, &TB));
2435 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, 1));
2436 } else {
2437 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TB, &TB, &TA));
2438 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002439 }
Gilles Peskineea9aa142021-06-16 13:42:04 +02002440 /* Note that one of TA or TB is still odd. */
Paul Bakker5121ce52009-01-03 21:22:43 +00002441 }
2442
Gilles Peskineea9aa142021-06-16 13:42:04 +02002443 /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k.
2444 * At the loop exit, TA = 0, so gcd(TA,TB) = TB.
2445 * - If there was at least one loop iteration, then one of TA or TB is odd,
2446 * and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case,
2447 * lz = min(a,b) so gcd(A,B) = 2^lz * TB.
2448 * - If there was no loop iteration, then A was 0, and gcd(A,B) = B.
Gilles Peskineb798b352021-06-21 11:40:38 +02002449 * In this case, lz = 0 and B = TB so gcd(A,B) = B = 2^lz * TB as well.
Gilles Peskineea9aa142021-06-16 13:42:04 +02002450 */
2451
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002452 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&TB, lz));
2453 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(G, &TB));
Paul Bakker5121ce52009-01-03 21:22:43 +00002454
2455cleanup:
2456
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002457 mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00002458
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002459 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002460}
2461
Gilles Peskine8f454702021-04-01 15:57:18 +02002462/* Fill X with n_bytes random bytes.
2463 * X must already have room for those bytes.
Gilles Peskine23422e42021-06-03 11:51:09 +02002464 * The ordering of the bytes returned from the RNG is suitable for
2465 * deterministic ECDSA (see RFC 6979 §3.3 and mbedtls_mpi_random()).
Gilles Peskinea16001e2021-04-13 21:55:35 +02002466 * The size and sign of X are unchanged.
Gilles Peskine8f454702021-04-01 15:57:18 +02002467 * n_bytes must not be 0.
2468 */
2469static int mpi_fill_random_internal(
2470 mbedtls_mpi *X, size_t n_bytes,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002471 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
Gilles Peskine8f454702021-04-01 15:57:18 +02002472{
2473 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002474 const size_t limbs = CHARS_TO_LIMBS(n_bytes);
2475 const size_t overhead = (limbs * ciL) - n_bytes;
Gilles Peskine8f454702021-04-01 15:57:18 +02002476
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002477 if (X->n < limbs) {
2478 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2479 }
Gilles Peskine8f454702021-04-01 15:57:18 +02002480
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002481 memset(X->p, 0, overhead);
2482 memset((unsigned char *) X->p + limbs * ciL, 0, (X->n - limbs) * ciL);
2483 MBEDTLS_MPI_CHK(f_rng(p_rng, (unsigned char *) X->p + overhead, n_bytes));
2484 mpi_bigendian_to_host(X->p, limbs);
Gilles Peskine8f454702021-04-01 15:57:18 +02002485
2486cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002487 return ret;
Gilles Peskine8f454702021-04-01 15:57:18 +02002488}
2489
Paul Bakker33dc46b2014-04-30 16:11:39 +02002490/*
2491 * Fill X with size bytes of random.
2492 *
2493 * Use a temporary bytes representation to make sure the result is the same
Paul Bakkerc37b0ac2014-05-01 14:19:23 +02002494 * regardless of the platform endianness (useful when f_rng is actually
Paul Bakker33dc46b2014-04-30 16:11:39 +02002495 * deterministic, eg for tests).
2496 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002497int mbedtls_mpi_fill_random(mbedtls_mpi *X, size_t size,
2498 int (*f_rng)(void *, unsigned char *, size_t),
2499 void *p_rng)
Paul Bakker287781a2011-03-26 13:18:49 +00002500{
Janos Follath24eed8d2019-11-22 13:21:35 +00002501 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002502 size_t const limbs = CHARS_TO_LIMBS(size);
Hanno Beckerda1655a2017-10-18 14:21:44 +01002503
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002504 MPI_VALIDATE_RET(X != NULL);
2505 MPI_VALIDATE_RET(f_rng != NULL);
Paul Bakker33dc46b2014-04-30 16:11:39 +02002506
Hanno Beckerda1655a2017-10-18 14:21:44 +01002507 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002508 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
2509 if (size == 0) {
2510 return 0;
2511 }
Paul Bakker287781a2011-03-26 13:18:49 +00002512
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002513 ret = mpi_fill_random_internal(X, size, f_rng, p_rng);
Paul Bakker287781a2011-03-26 13:18:49 +00002514
2515cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002516 return ret;
Paul Bakker287781a2011-03-26 13:18:49 +00002517}
2518
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002519int mbedtls_mpi_random(mbedtls_mpi *X,
2520 mbedtls_mpi_sint min,
2521 const mbedtls_mpi *N,
2522 int (*f_rng)(void *, unsigned char *, size_t),
2523 void *p_rng)
Gilles Peskine4699fa42021-03-29 22:02:55 +02002524{
Gilles Peskine4699fa42021-03-29 22:02:55 +02002525 int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002526 int count;
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002527 unsigned lt_lower = 1, lt_upper = 0;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002528 size_t n_bits = mbedtls_mpi_bitlen(N);
2529 size_t n_bytes = (n_bits + 7) / 8;
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002530 mbedtls_mpi lower_bound;
Gilles Peskine4699fa42021-03-29 22:02:55 +02002531
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002532 if (min < 0) {
2533 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2534 }
2535 if (mbedtls_mpi_cmp_int(N, min) <= 0) {
2536 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2537 }
Gilles Peskine9312ba52021-03-29 22:14:51 +02002538
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002539 /*
2540 * When min == 0, each try has at worst a probability 1/2 of failing
2541 * (the msb has a probability 1/2 of being 0, and then the result will
2542 * be < N), so after 30 tries failure probability is a most 2**(-30).
2543 *
2544 * When N is just below a power of 2, as is the case when generating
Gilles Peskine3f613632021-04-15 11:45:19 +02002545 * a random scalar on most elliptic curves, 1 try is enough with
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002546 * overwhelming probability. When N is just above a power of 2,
Gilles Peskine3f613632021-04-15 11:45:19 +02002547 * as when generating a random scalar on secp224k1, each try has
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002548 * a probability of failing that is almost 1/2.
2549 *
2550 * The probabilities are almost the same if min is nonzero but negligible
2551 * compared to N. This is always the case when N is crypto-sized, but
2552 * it's convenient to support small N for testing purposes. When N
2553 * is small, use a higher repeat count, otherwise the probability of
2554 * failure is macroscopic.
2555 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002556 count = (n_bytes > 4 ? 30 : 250);
Gilles Peskinee39ee8e2021-04-13 21:23:25 +02002557
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002558 mbedtls_mpi_init(&lower_bound);
Gilles Peskine74f66bb2021-04-13 21:09:10 +02002559
Gilles Peskine8f454702021-04-01 15:57:18 +02002560 /* Ensure that target MPI has exactly the same number of limbs
2561 * as the upper bound, even if the upper bound has leading zeros.
2562 * This is necessary for the mbedtls_mpi_lt_mpi_ct() check. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002563 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, N->n));
2564 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&lower_bound, N->n));
2565 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&lower_bound, min));
Gilles Peskine8f454702021-04-01 15:57:18 +02002566
Gilles Peskine4699fa42021-03-29 22:02:55 +02002567 /*
2568 * Match the procedure given in RFC 6979 §3.3 (deterministic ECDSA)
2569 * when f_rng is a suitably parametrized instance of HMAC_DRBG:
2570 * - use the same byte ordering;
2571 * - keep the leftmost n_bits bits of the generated octet string;
2572 * - try until result is in the desired range.
2573 * This also avoids any bias, which is especially important for ECDSA.
2574 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002575 do {
2576 MBEDTLS_MPI_CHK(mpi_fill_random_internal(X, n_bytes, f_rng, p_rng));
2577 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(X, 8 * n_bytes - n_bits));
Gilles Peskine4699fa42021-03-29 22:02:55 +02002578
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002579 if (--count == 0) {
Gilles Peskine4699fa42021-03-29 22:02:55 +02002580 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2581 goto cleanup;
2582 }
2583
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002584 MBEDTLS_MPI_CHK(mbedtls_mpi_lt_mpi_ct(X, &lower_bound, &lt_lower));
2585 MBEDTLS_MPI_CHK(mbedtls_mpi_lt_mpi_ct(X, N, &lt_upper));
2586 } while (lt_lower != 0 || lt_upper == 0);
Gilles Peskine4699fa42021-03-29 22:02:55 +02002587
2588cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002589 mbedtls_mpi_free(&lower_bound);
2590 return ret;
Gilles Peskine4699fa42021-03-29 22:02:55 +02002591}
2592
Paul Bakker5121ce52009-01-03 21:22:43 +00002593/*
2594 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2595 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002596int mbedtls_mpi_inv_mod(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N)
Paul Bakker5121ce52009-01-03 21:22:43 +00002597{
Janos Follath24eed8d2019-11-22 13:21:35 +00002598 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002599 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002600 MPI_VALIDATE_RET(X != NULL);
2601 MPI_VALIDATE_RET(A != NULL);
2602 MPI_VALIDATE_RET(N != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00002603
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002604 if (mbedtls_mpi_cmp_int(N, 1) <= 0) {
2605 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2606 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002607
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002608 mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TU); mbedtls_mpi_init(&U1); mbedtls_mpi_init(&U2);
2609 mbedtls_mpi_init(&G); mbedtls_mpi_init(&TB); mbedtls_mpi_init(&TV);
2610 mbedtls_mpi_init(&V1); mbedtls_mpi_init(&V2);
Paul Bakker5121ce52009-01-03 21:22:43 +00002611
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002612 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&G, A, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002613
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002614 if (mbedtls_mpi_cmp_int(&G, 1) != 0) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002615 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002616 goto cleanup;
2617 }
2618
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002619 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&TA, A, N));
2620 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TU, &TA));
2621 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, N));
2622 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TV, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002623
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002624 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U1, 1));
2625 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U2, 0));
2626 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V1, 0));
2627 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002628
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002629 do {
2630 while ((TU.p[0] & 1) == 0) {
2631 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TU, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002632
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002633 if ((U1.p[0] & 1) != 0 || (U2.p[0] & 1) != 0) {
2634 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&U1, &U1, &TB));
2635 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &TA));
Paul Bakker5121ce52009-01-03 21:22:43 +00002636 }
2637
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002638 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U1, 1));
2639 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002640 }
2641
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002642 while ((TV.p[0] & 1) == 0) {
2643 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TV, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002644
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002645 if ((V1.p[0] & 1) != 0 || (V2.p[0] & 1) != 0) {
2646 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, &TB));
2647 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &TA));
Paul Bakker5121ce52009-01-03 21:22:43 +00002648 }
2649
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002650 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V1, 1));
2651 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002652 }
2653
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002654 if (mbedtls_mpi_cmp_mpi(&TU, &TV) >= 0) {
2655 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TU, &TU, &TV));
2656 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U1, &U1, &V1));
2657 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &V2));
2658 } else {
2659 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TV, &TV, &TU));
2660 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, &U1));
2661 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &U2));
Paul Bakker5121ce52009-01-03 21:22:43 +00002662 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002663 } while (mbedtls_mpi_cmp_int(&TU, 0) != 0);
2664
2665 while (mbedtls_mpi_cmp_int(&V1, 0) < 0) {
2666 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002667 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002668
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002669 while (mbedtls_mpi_cmp_mpi(&V1, N) >= 0) {
2670 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, N));
2671 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002672
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002673 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &V1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002674
2675cleanup:
2676
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002677 mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TU); mbedtls_mpi_free(&U1); mbedtls_mpi_free(&U2);
2678 mbedtls_mpi_free(&G); mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TV);
2679 mbedtls_mpi_free(&V1); mbedtls_mpi_free(&V2);
Paul Bakker5121ce52009-01-03 21:22:43 +00002680
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002681 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002682}
2683
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002684#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002685
Paul Bakker5121ce52009-01-03 21:22:43 +00002686static const int small_prime[] =
2687{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002688 3, 5, 7, 11, 13, 17, 19, 23,
2689 29, 31, 37, 41, 43, 47, 53, 59,
2690 61, 67, 71, 73, 79, 83, 89, 97,
2691 101, 103, 107, 109, 113, 127, 131, 137,
2692 139, 149, 151, 157, 163, 167, 173, 179,
2693 181, 191, 193, 197, 199, 211, 223, 227,
2694 229, 233, 239, 241, 251, 257, 263, 269,
2695 271, 277, 281, 283, 293, 307, 311, 313,
2696 317, 331, 337, 347, 349, 353, 359, 367,
2697 373, 379, 383, 389, 397, 401, 409, 419,
2698 421, 431, 433, 439, 443, 449, 457, 461,
2699 463, 467, 479, 487, 491, 499, 503, 509,
2700 521, 523, 541, 547, 557, 563, 569, 571,
2701 577, 587, 593, 599, 601, 607, 613, 617,
2702 619, 631, 641, 643, 647, 653, 659, 661,
2703 673, 677, 683, 691, 701, 709, 719, 727,
2704 733, 739, 743, 751, 757, 761, 769, 773,
2705 787, 797, 809, 811, 821, 823, 827, 829,
2706 839, 853, 857, 859, 863, 877, 881, 883,
2707 887, 907, 911, 919, 929, 937, 941, 947,
2708 953, 967, 971, 977, 983, 991, 997, -103
Paul Bakker5121ce52009-01-03 21:22:43 +00002709};
2710
2711/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002712 * Small divisors test (X must be positive)
2713 *
2714 * Return values:
2715 * 0: no small factor (possible prime, more tests needed)
2716 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002717 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002718 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002719 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002720static int mpi_check_small_factors(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +00002721{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002722 int ret = 0;
2723 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002724 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002725
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002726 if ((X->p[0] & 1) == 0) {
2727 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2728 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002729
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002730 for (i = 0; small_prime[i] > 0; i++) {
2731 if (mbedtls_mpi_cmp_int(X, small_prime[i]) <= 0) {
2732 return 1;
2733 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002734
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002735 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, small_prime[i]));
Paul Bakker5121ce52009-01-03 21:22:43 +00002736
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002737 if (r == 0) {
2738 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2739 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002740 }
2741
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002742cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002743 return ret;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002744}
2745
2746/*
2747 * Miller-Rabin pseudo-primality test (HAC 4.24)
2748 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002749static int mpi_miller_rabin(const mbedtls_mpi *X, size_t rounds,
2750 int (*f_rng)(void *, unsigned char *, size_t),
2751 void *p_rng)
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002752{
Pascal Junodb99183d2015-03-11 16:49:45 +01002753 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002754 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002755 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002756
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002757 MPI_VALIDATE_RET(X != NULL);
2758 MPI_VALIDATE_RET(f_rng != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00002759
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002760 mbedtls_mpi_init(&W); mbedtls_mpi_init(&R);
2761 mbedtls_mpi_init(&T); mbedtls_mpi_init(&A);
2762 mbedtls_mpi_init(&RR);
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002763
Paul Bakker5121ce52009-01-03 21:22:43 +00002764 /*
2765 * W = |X| - 1
2766 * R = W >> lsb( W )
2767 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002768 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&W, X, 1));
2769 s = mbedtls_mpi_lsb(&W);
2770 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&R, &W));
2771 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&R, s));
Paul Bakker5121ce52009-01-03 21:22:43 +00002772
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002773 for (i = 0; i < rounds; i++) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002774 /*
2775 * pick a random A, 1 < A < |X| - 1
2776 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002777 count = 0;
2778 do {
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002779 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&A, X->n * ciL, f_rng, p_rng));
Pascal Junodb99183d2015-03-11 16:49:45 +01002780
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002781 j = mbedtls_mpi_bitlen(&A);
2782 k = mbedtls_mpi_bitlen(&W);
Pascal Junodb99183d2015-03-11 16:49:45 +01002783 if (j > k) {
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002784 A.p[A.n - 1] &= ((mbedtls_mpi_uint) 1 << (k - (A.n - 1) * biL - 1)) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002785 }
2786
2787 if (count++ > 30) {
Jens Wiklanderf08aa3e2019-01-17 13:30:57 +01002788 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2789 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002790 }
2791
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002792 } while (mbedtls_mpi_cmp_mpi(&A, &W) >= 0 ||
2793 mbedtls_mpi_cmp_int(&A, 1) <= 0);
Paul Bakker5121ce52009-01-03 21:22:43 +00002794
2795 /*
2796 * A = A^R mod |X|
2797 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002798 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&A, &A, &R, X, &RR));
Paul Bakker5121ce52009-01-03 21:22:43 +00002799
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002800 if (mbedtls_mpi_cmp_mpi(&A, &W) == 0 ||
2801 mbedtls_mpi_cmp_int(&A, 1) == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002802 continue;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002803 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002804
2805 j = 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002806 while (j < s && mbedtls_mpi_cmp_mpi(&A, &W) != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002807 /*
2808 * A = A * A mod |X|
2809 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002810 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &A, &A));
2811 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&A, &T, X));
Paul Bakker5121ce52009-01-03 21:22:43 +00002812
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002813 if (mbedtls_mpi_cmp_int(&A, 1) == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002814 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002815 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002816
2817 j++;
2818 }
2819
2820 /*
2821 * not prime if A != |X| - 1 or A == 1
2822 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002823 if (mbedtls_mpi_cmp_mpi(&A, &W) != 0 ||
2824 mbedtls_mpi_cmp_int(&A, 1) == 0) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002825 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002826 break;
2827 }
2828 }
2829
2830cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002831 mbedtls_mpi_free(&W); mbedtls_mpi_free(&R);
2832 mbedtls_mpi_free(&T); mbedtls_mpi_free(&A);
2833 mbedtls_mpi_free(&RR);
Paul Bakker5121ce52009-01-03 21:22:43 +00002834
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002835 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002836}
2837
2838/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002839 * Pseudo-primality test: small factors, then Miller-Rabin
2840 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002841int mbedtls_mpi_is_prime_ext(const mbedtls_mpi *X, int rounds,
2842 int (*f_rng)(void *, unsigned char *, size_t),
2843 void *p_rng)
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002844{
Janos Follath24eed8d2019-11-22 13:21:35 +00002845 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002846 mbedtls_mpi XX;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002847 MPI_VALIDATE_RET(X != NULL);
2848 MPI_VALIDATE_RET(f_rng != NULL);
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002849
2850 XX.s = 1;
2851 XX.n = X->n;
2852 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002853
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002854 if (mbedtls_mpi_cmp_int(&XX, 0) == 0 ||
2855 mbedtls_mpi_cmp_int(&XX, 1) == 0) {
2856 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002857 }
2858
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002859 if (mbedtls_mpi_cmp_int(&XX, 2) == 0) {
2860 return 0;
2861 }
2862
2863 if ((ret = mpi_check_small_factors(&XX)) != 0) {
2864 if (ret == 1) {
2865 return 0;
2866 }
2867
2868 return ret;
2869 }
2870
2871 return mpi_miller_rabin(&XX, rounds, f_rng, p_rng);
Janos Follathf301d232018-08-14 13:34:01 +01002872}
2873
Janos Follatha0b67c22018-09-18 14:48:23 +01002874#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Janos Follathf301d232018-08-14 13:34:01 +01002875/*
2876 * Pseudo-primality test, error probability 2^-80
2877 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002878int mbedtls_mpi_is_prime(const mbedtls_mpi *X,
2879 int (*f_rng)(void *, unsigned char *, size_t),
2880 void *p_rng)
Janos Follathf301d232018-08-14 13:34:01 +01002881{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002882 MPI_VALIDATE_RET(X != NULL);
2883 MPI_VALIDATE_RET(f_rng != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00002884
Janos Follatha0b67c22018-09-18 14:48:23 +01002885 /*
2886 * In the past our key generation aimed for an error rate of at most
2887 * 2^-80. Since this function is deprecated, aim for the same certainty
2888 * here as well.
2889 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002890 return mbedtls_mpi_is_prime_ext(X, 40, f_rng, p_rng);
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002891}
Janos Follatha0b67c22018-09-18 14:48:23 +01002892#endif
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002893
2894/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002895 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002896 *
Janos Follathf301d232018-08-14 13:34:01 +01002897 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2898 * be either 1024 bits or 1536 bits long, and flags must contain
2899 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002900 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002901int mbedtls_mpi_gen_prime(mbedtls_mpi *X, size_t nbits, int flags,
2902 int (*f_rng)(void *, unsigned char *, size_t),
2903 void *p_rng)
Paul Bakker5121ce52009-01-03 21:22:43 +00002904{
Jethro Beekman66689272018-02-14 19:24:10 -08002905#ifdef MBEDTLS_HAVE_INT64
2906// ceil(2^63.5)
2907#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2908#else
2909// ceil(2^31.5)
2910#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2911#endif
2912 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002913 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002914 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002915 mbedtls_mpi_uint r;
2916 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002917
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002918 MPI_VALIDATE_RET(X != NULL);
2919 MPI_VALIDATE_RET(f_rng != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00002920
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002921 if (nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS) {
2922 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2923 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002924
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002925 mbedtls_mpi_init(&Y);
Paul Bakker5121ce52009-01-03 21:22:43 +00002926
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002927 n = BITS_TO_LIMBS(nbits);
Paul Bakker5121ce52009-01-03 21:22:43 +00002928
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002929 if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR) == 0) {
Janos Follathda31fa12018-09-03 14:45:23 +01002930 /*
2931 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2932 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002933 rounds = ((nbits >= 1300) ? 2 : (nbits >= 850) ? 3 :
2934 (nbits >= 650) ? 4 : (nbits >= 350) ? 8 :
2935 (nbits >= 250) ? 12 : (nbits >= 150) ? 18 : 27);
2936 } else {
Janos Follathda31fa12018-09-03 14:45:23 +01002937 /*
2938 * 2^-100 error probability, number of rounds computed based on HAC,
2939 * fact 4.48
2940 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002941 rounds = ((nbits >= 1450) ? 4 : (nbits >= 1150) ? 5 :
2942 (nbits >= 1000) ? 6 : (nbits >= 850) ? 7 :
2943 (nbits >= 750) ? 8 : (nbits >= 500) ? 13 :
2944 (nbits >= 250) ? 28 : (nbits >= 150) ? 40 : 51);
Janos Follathda31fa12018-09-03 14:45:23 +01002945 }
2946
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002947 while (1) {
2948 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(X, n * ciL, f_rng, p_rng));
Jethro Beekman66689272018-02-14 19:24:10 -08002949 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002950 if (X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2) {
2951 continue;
2952 }
Jethro Beekman66689272018-02-14 19:24:10 -08002953
2954 k = n * biL;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002955 if (k > nbits) {
2956 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(X, k - nbits));
2957 }
Jethro Beekman66689272018-02-14 19:24:10 -08002958 X->p[0] |= 1;
2959
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002960 if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH) == 0) {
2961 ret = mbedtls_mpi_is_prime_ext(X, rounds, f_rng, p_rng);
Jethro Beekman66689272018-02-14 19:24:10 -08002962
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002963 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002964 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002965 }
2966 } else {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002967 /*
Tom Cosgrove5205c972022-07-28 06:12:08 +01002968 * A necessary condition for Y and X = 2Y + 1 to be prime
Jethro Beekman66689272018-02-14 19:24:10 -08002969 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2970 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002971 */
Jethro Beekman66689272018-02-14 19:24:10 -08002972
2973 X->p[0] |= 2;
2974
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002975 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, 3));
2976 if (r == 0) {
2977 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 8));
2978 } else if (r == 1) {
2979 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 4));
2980 }
Jethro Beekman66689272018-02-14 19:24:10 -08002981
2982 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002983 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, X));
2984 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, 1));
Jethro Beekman66689272018-02-14 19:24:10 -08002985
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002986 while (1) {
Jethro Beekman66689272018-02-14 19:24:10 -08002987 /*
2988 * First, check small factors for X and Y
2989 * before doing Miller-Rabin on any of them
2990 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002991 if ((ret = mpi_check_small_factors(X)) == 0 &&
2992 (ret = mpi_check_small_factors(&Y)) == 0 &&
2993 (ret = mpi_miller_rabin(X, rounds, f_rng, p_rng))
2994 == 0 &&
2995 (ret = mpi_miller_rabin(&Y, rounds, f_rng, p_rng))
2996 == 0) {
Jethro Beekman66689272018-02-14 19:24:10 -08002997 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01002998 }
Jethro Beekman66689272018-02-14 19:24:10 -08002999
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003000 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
Jethro Beekman66689272018-02-14 19:24:10 -08003001 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003002 }
Jethro Beekman66689272018-02-14 19:24:10 -08003003
3004 /*
3005 * Next candidates. We want to preserve Y = (X-1) / 2 and
3006 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
3007 * so up Y by 6 and X by 12.
3008 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003009 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 12));
3010 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&Y, &Y, 6));
Paul Bakker5121ce52009-01-03 21:22:43 +00003011 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003012 }
3013 }
3014
3015cleanup:
3016
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003017 mbedtls_mpi_free(&Y);
Paul Bakker5121ce52009-01-03 21:22:43 +00003018
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003019 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00003020}
3021
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003022#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00003023
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003024#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00003025
Paul Bakker23986e52011-04-24 08:57:21 +00003026#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003027
3028static const int gcd_pairs[GCD_PAIR_COUNT][3] =
3029{
3030 { 693, 609, 21 },
3031 { 1764, 868, 28 },
3032 { 768454923, 542167814, 1 }
3033};
3034
Paul Bakker5121ce52009-01-03 21:22:43 +00003035/*
3036 * Checkup routine
3037 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003038int mbedtls_mpi_self_test(int verbose)
Paul Bakker5121ce52009-01-03 21:22:43 +00003039{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003040 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003041 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00003042
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003043 mbedtls_mpi_init(&A); mbedtls_mpi_init(&E); mbedtls_mpi_init(&N); mbedtls_mpi_init(&X);
3044 mbedtls_mpi_init(&Y); mbedtls_mpi_init(&U); mbedtls_mpi_init(&V);
Paul Bakker5121ce52009-01-03 21:22:43 +00003045
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003046 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&A, 16,
3047 "EFE021C2645FD1DC586E69184AF4A31E" \
3048 "D5F53E93B5F123FA41680867BA110131" \
3049 "944FE7952E2517337780CB0DB80E61AA" \
3050 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6"));
Paul Bakker5121ce52009-01-03 21:22:43 +00003051
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003052 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&E, 16,
3053 "B2E7EFD37075B9F03FF989C7C5051C20" \
3054 "34D2A323810251127E7BF8625A4F49A5" \
3055 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
3056 "5B5C25763222FEFCCFC38B832366C29E"));
Paul Bakker5121ce52009-01-03 21:22:43 +00003057
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003058 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&N, 16,
3059 "0066A198186C18C10B2F5ED9B522752A" \
3060 "9830B69916E535C8F047518A889A43A5" \
3061 "94B6BED27A168D31D4A52F88925AA8F5"));
Paul Bakker5121ce52009-01-03 21:22:43 +00003062
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003063 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&X, &A, &N));
Paul Bakker5121ce52009-01-03 21:22:43 +00003064
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003065 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
3066 "602AB7ECA597A3D6B56FF9829A5E8B85" \
3067 "9E857EA95A03512E2BAE7391688D264A" \
3068 "A5663B0341DB9CCFD2C4C5F421FEC814" \
3069 "8001B72E848A38CAE1C65F78E56ABDEF" \
3070 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
3071 "ECF677152EF804370C1A305CAF3B5BF1" \
3072 "30879B56C61DE584A0F53A2447A51E"));
Paul Bakker5121ce52009-01-03 21:22:43 +00003073
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003074 if (verbose != 0) {
3075 mbedtls_printf(" MPI test #1 (mul_mpi): ");
3076 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003077
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003078 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
3079 if (verbose != 0) {
3080 mbedtls_printf("failed\n");
3081 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003082
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003083 ret = 1;
3084 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003085 }
3086
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003087 if (verbose != 0) {
3088 mbedtls_printf("passed\n");
3089 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003090
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003091 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&X, &Y, &A, &N));
Paul Bakker5121ce52009-01-03 21:22:43 +00003092
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003093 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
3094 "256567336059E52CAE22925474705F39A94"));
Paul Bakker5121ce52009-01-03 21:22:43 +00003095
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003096 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&V, 16,
3097 "6613F26162223DF488E9CD48CC132C7A" \
3098 "0AC93C701B001B092E4E5B9F73BCD27B" \
3099 "9EE50D0657C77F374E903CDFA4C642"));
Paul Bakker5121ce52009-01-03 21:22:43 +00003100
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003101 if (verbose != 0) {
3102 mbedtls_printf(" MPI test #2 (div_mpi): ");
3103 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003104
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003105 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0 ||
3106 mbedtls_mpi_cmp_mpi(&Y, &V) != 0) {
3107 if (verbose != 0) {
3108 mbedtls_printf("failed\n");
3109 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003110
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003111 ret = 1;
3112 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003113 }
3114
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003115 if (verbose != 0) {
3116 mbedtls_printf("passed\n");
3117 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003118
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003119 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&X, &A, &E, &N, NULL));
Paul Bakker5121ce52009-01-03 21:22:43 +00003120
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003121 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
3122 "36E139AEA55215609D2816998ED020BB" \
3123 "BD96C37890F65171D948E9BC7CBAA4D9" \
3124 "325D24D6A3C12710F10A09FA08AB87"));
Paul Bakker5121ce52009-01-03 21:22:43 +00003125
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003126 if (verbose != 0) {
3127 mbedtls_printf(" MPI test #3 (exp_mod): ");
3128 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003129
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003130 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
3131 if (verbose != 0) {
3132 mbedtls_printf("failed\n");
3133 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003134
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003135 ret = 1;
3136 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003137 }
3138
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003139 if (verbose != 0) {
3140 mbedtls_printf("passed\n");
3141 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003142
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003143 MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&X, &A, &N));
Paul Bakker5121ce52009-01-03 21:22:43 +00003144
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003145 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
3146 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
3147 "C3DBA76456363A10869622EAC2DD84EC" \
3148 "C5B8A74DAC4D09E03B5E0BE779F2DF61"));
Paul Bakker5121ce52009-01-03 21:22:43 +00003149
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003150 if (verbose != 0) {
3151 mbedtls_printf(" MPI test #4 (inv_mod): ");
3152 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003153
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003154 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
3155 if (verbose != 0) {
3156 mbedtls_printf("failed\n");
3157 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003158
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003159 ret = 1;
3160 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00003161 }
3162
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003163 if (verbose != 0) {
3164 mbedtls_printf("passed\n");
3165 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003166
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003167 if (verbose != 0) {
3168 mbedtls_printf(" MPI test #5 (simple gcd): ");
3169 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003170
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003171 for (i = 0; i < GCD_PAIR_COUNT; i++) {
3172 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&X, gcd_pairs[i][0]));
3173 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Y, gcd_pairs[i][1]));
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003174
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003175 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&A, &X, &Y));
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003176
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003177 if (mbedtls_mpi_cmp_int(&A, gcd_pairs[i][2]) != 0) {
3178 if (verbose != 0) {
3179 mbedtls_printf("failed at %d\n", i);
3180 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003181
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01003182 ret = 1;
3183 goto cleanup;
3184 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003185 }
3186
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003187 if (verbose != 0) {
3188 mbedtls_printf("passed\n");
3189 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00003190
Paul Bakker5121ce52009-01-03 21:22:43 +00003191cleanup:
3192
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003193 if (ret != 0 && verbose != 0) {
3194 mbedtls_printf("Unexpected error, return code = %08X\n", (unsigned int) ret);
3195 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003196
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003197 mbedtls_mpi_free(&A); mbedtls_mpi_free(&E); mbedtls_mpi_free(&N); mbedtls_mpi_free(&X);
3198 mbedtls_mpi_free(&Y); mbedtls_mpi_free(&U); mbedtls_mpi_free(&V);
Paul Bakker5121ce52009-01-03 21:22:43 +00003199
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003200 if (verbose != 0) {
3201 mbedtls_printf("\n");
3202 }
Paul Bakker5121ce52009-01-03 21:22:43 +00003203
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01003204 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00003205}
3206
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003207#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00003208
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003209#endif /* MBEDTLS_BIGNUM_C */