blob: 70081de097220ab3b045106cfaab7359dd5edaec [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"
Janos Follath4614b9a2022-07-21 15:34:47 +010041#include "bignum_core.h"
Chris Jones4c5819c2021-03-03 17:45:34 +000042#include "bn_mul.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050043#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000044#include "mbedtls/error.h"
Gabor Mezei22c9a6f2021-10-20 12:09:35 +020045#include "constant_time_internal.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000046
Dave Rodgman351c71b2021-12-06 17:50:53 +000047#include <limits.h>
Rich Evans00ab4702015-02-06 13:43:58 +000048#include <string.h>
49
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000050#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020051
Gilles Peskine449bd832023-01-11 14:50:10 +010052#define MPI_VALIDATE_RET(cond) \
53 MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA)
54#define MPI_VALIDATE(cond) \
55 MBEDTLS_INTERNAL_VALIDATE(cond)
Gabor Mezei66669142022-08-03 12:52:26 +020056
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050057/* Implementation that should never be optimized out by the compiler */
Tom Cosgrove46259f62023-07-18 16:44:14 +010058static void mbedtls_mpi_zeroize_and_free(mbedtls_mpi_uint *v, size_t n)
Andres Amaya Garcia6698d2f2018-04-24 08:39:07 -050059{
Tom Cosgrove46259f62023-07-18 16:44:14 +010060 mbedtls_zeroize_and_free(v, ciL * n);
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050061}
62
Paul Bakker5121ce52009-01-03 21:22:43 +000063/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000064 * Initialize one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000065 */
Gilles Peskine449bd832023-01-11 14:50:10 +010066void mbedtls_mpi_init(mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +000067{
Gilles Peskine449bd832023-01-11 14:50:10 +010068 MPI_VALIDATE(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +000069
Paul Bakker6c591fa2011-05-05 11:49:20 +000070 X->s = 1;
71 X->n = 0;
72 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000073}
74
75/*
Paul Bakker6c591fa2011-05-05 11:49:20 +000076 * Unallocate one MPI
Paul Bakker5121ce52009-01-03 21:22:43 +000077 */
Gilles Peskine449bd832023-01-11 14:50:10 +010078void mbedtls_mpi_free(mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +000079{
Gilles Peskine449bd832023-01-11 14:50:10 +010080 if (X == NULL) {
Paul Bakker6c591fa2011-05-05 11:49:20 +000081 return;
Gilles Peskine449bd832023-01-11 14:50:10 +010082 }
Paul Bakker5121ce52009-01-03 21:22:43 +000083
Gilles Peskine449bd832023-01-11 14:50:10 +010084 if (X->p != NULL) {
Tom Cosgrove46259f62023-07-18 16:44:14 +010085 mbedtls_mpi_zeroize_and_free(X->p, X->n);
Paul Bakker5121ce52009-01-03 21:22:43 +000086 }
87
Paul Bakker6c591fa2011-05-05 11:49:20 +000088 X->s = 1;
89 X->n = 0;
90 X->p = NULL;
Paul Bakker5121ce52009-01-03 21:22:43 +000091}
92
93/*
94 * Enlarge to the specified number of limbs
95 */
Gilles Peskine449bd832023-01-11 14:50:10 +010096int mbedtls_mpi_grow(mbedtls_mpi *X, size_t nblimbs)
Paul Bakker5121ce52009-01-03 21:22:43 +000097{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020098 mbedtls_mpi_uint *p;
Gilles Peskine449bd832023-01-11 14:50:10 +010099 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000100
Gilles Peskine449bd832023-01-11 14:50:10 +0100101 if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
102 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
103 }
Paul Bakkerf9688572011-05-05 10:00:45 +0000104
Gilles Peskine449bd832023-01-11 14:50:10 +0100105 if (X->n < nblimbs) {
106 if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(nblimbs, ciL)) == NULL) {
107 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
108 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000109
Gilles Peskine449bd832023-01-11 14:50:10 +0100110 if (X->p != NULL) {
111 memcpy(p, X->p, X->n * ciL);
Tom Cosgrove46259f62023-07-18 16:44:14 +0100112 mbedtls_mpi_zeroize_and_free(X->p, X->n);
Paul Bakker5121ce52009-01-03 21:22:43 +0000113 }
114
115 X->n = nblimbs;
116 X->p = p;
117 }
118
Gilles Peskine449bd832023-01-11 14:50:10 +0100119 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000120}
121
122/*
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100123 * Resize down as much as possible,
124 * while keeping at least the specified number of limbs
125 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100126int mbedtls_mpi_shrink(mbedtls_mpi *X, size_t nblimbs)
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100127{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200128 mbedtls_mpi_uint *p;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100129 size_t i;
Gilles Peskine449bd832023-01-11 14:50:10 +0100130 MPI_VALIDATE_RET(X != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000131
Gilles Peskine449bd832023-01-11 14:50:10 +0100132 if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
133 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
134 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100135
Gilles Peskinee2f563e2020-01-20 21:17:43 +0100136 /* Actually resize up if there are currently fewer than nblimbs limbs. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100137 if (X->n <= nblimbs) {
138 return mbedtls_mpi_grow(X, nblimbs);
139 }
Gilles Peskine322752b2020-01-21 13:59:51 +0100140 /* After this point, then X->n > nblimbs and in particular X->n > 0. */
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100141
Gilles Peskine449bd832023-01-11 14:50:10 +0100142 for (i = X->n - 1; i > 0; i--) {
143 if (X->p[i] != 0) {
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100144 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100145 }
146 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100147 i++;
148
Gilles Peskine449bd832023-01-11 14:50:10 +0100149 if (i < nblimbs) {
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100150 i = nblimbs;
Gilles Peskine449bd832023-01-11 14:50:10 +0100151 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100152
Gilles Peskine449bd832023-01-11 14:50:10 +0100153 if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(i, ciL)) == NULL) {
154 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
155 }
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100156
Gilles Peskine449bd832023-01-11 14:50:10 +0100157 if (X->p != NULL) {
158 memcpy(p, X->p, i * ciL);
Tom Cosgrove46259f62023-07-18 16:44:14 +0100159 mbedtls_mpi_zeroize_and_free(X->p, X->n);
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100160 }
161
162 X->n = i;
163 X->p = p;
164
Gilles Peskine449bd832023-01-11 14:50:10 +0100165 return 0;
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100166}
167
Gilles Peskineed32b572021-06-02 22:17:52 +0200168/* Resize X to have exactly n limbs and set it to 0. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100169static int mbedtls_mpi_resize_clear(mbedtls_mpi *X, size_t limbs)
Gilles Peskineed32b572021-06-02 22:17:52 +0200170{
Gilles Peskine449bd832023-01-11 14:50:10 +0100171 if (limbs == 0) {
172 mbedtls_mpi_free(X);
173 return 0;
174 } else if (X->n == limbs) {
175 memset(X->p, 0, limbs * ciL);
Gilles Peskineed32b572021-06-02 22:17:52 +0200176 X->s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100177 return 0;
178 } else {
179 mbedtls_mpi_free(X);
180 return mbedtls_mpi_grow(X, limbs);
Gilles Peskineed32b572021-06-02 22:17:52 +0200181 }
182}
183
Manuel Pégourié-Gonnard58681632013-11-21 10:39:37 +0100184/*
Gilles Peskine3da1a8f2021-06-08 23:17:42 +0200185 * Copy the contents of Y into X.
186 *
187 * This function is not constant-time. Leading zeros in Y may be removed.
188 *
189 * Ensure that X does not shrink. This is not guaranteed by the public API,
190 * but some code in the bignum module relies on this property, for example
191 * in mbedtls_mpi_exp_mod().
Paul Bakker5121ce52009-01-03 21:22:43 +0000192 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100193int mbedtls_mpi_copy(mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000194{
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100195 int ret = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000196 size_t i;
Gilles Peskine449bd832023-01-11 14:50:10 +0100197 MPI_VALIDATE_RET(X != NULL);
198 MPI_VALIDATE_RET(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000199
Gilles Peskine449bd832023-01-11 14:50:10 +0100200 if (X == Y) {
201 return 0;
Manuel Pégourié-Gonnardf4999932013-08-12 17:02:59 +0200202 }
203
Gilles Peskine449bd832023-01-11 14:50:10 +0100204 if (Y->n == 0) {
205 if (X->n != 0) {
206 X->s = 1;
207 memset(X->p, 0, X->n * ciL);
208 }
209 return 0;
210 }
211
212 for (i = Y->n - 1; i > 0; i--) {
213 if (Y->p[i] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000214 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100215 }
216 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000217 i++;
218
219 X->s = Y->s;
220
Gilles Peskine449bd832023-01-11 14:50:10 +0100221 if (X->n < i) {
222 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i));
223 } else {
224 memset(X->p + i, 0, (X->n - i) * ciL);
Gilles Peskine4e4be7c2018-03-21 16:29:03 +0100225 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000226
Gilles Peskine449bd832023-01-11 14:50:10 +0100227 memcpy(X->p, Y->p, i * ciL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000228
229cleanup:
230
Gilles Peskine449bd832023-01-11 14:50:10 +0100231 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000232}
233
234/*
235 * Swap the contents of X and Y
236 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100237void mbedtls_mpi_swap(mbedtls_mpi *X, mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000238{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200239 mbedtls_mpi T;
Gilles Peskine449bd832023-01-11 14:50:10 +0100240 MPI_VALIDATE(X != NULL);
241 MPI_VALIDATE(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000242
Gilles Peskine449bd832023-01-11 14:50:10 +0100243 memcpy(&T, X, sizeof(mbedtls_mpi));
244 memcpy(X, Y, sizeof(mbedtls_mpi));
245 memcpy(Y, &T, sizeof(mbedtls_mpi));
Paul Bakker5121ce52009-01-03 21:22:43 +0000246}
247
Gilles Peskine449bd832023-01-11 14:50:10 +0100248static inline mbedtls_mpi_uint mpi_sint_abs(mbedtls_mpi_sint z)
Gilles Peskineef7f4e42022-11-15 23:25:27 +0100249{
Gilles Peskine449bd832023-01-11 14:50:10 +0100250 if (z >= 0) {
251 return z;
252 }
Gilles Peskineef7f4e42022-11-15 23:25:27 +0100253 /* Take care to handle the most negative value (-2^(biL-1)) correctly.
254 * A naive -z would have undefined behavior.
255 * Write this in a way that makes popular compilers happy (GCC, Clang,
256 * MSVC). */
Gilles Peskine449bd832023-01-11 14:50:10 +0100257 return (mbedtls_mpi_uint) 0 - (mbedtls_mpi_uint) z;
Gilles Peskineef7f4e42022-11-15 23:25:27 +0100258}
259
Paul Bakker5121ce52009-01-03 21:22:43 +0000260/*
261 * Set value from integer
262 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100263int mbedtls_mpi_lset(mbedtls_mpi *X, mbedtls_mpi_sint z)
Paul Bakker5121ce52009-01-03 21:22:43 +0000264{
Janos Follath24eed8d2019-11-22 13:21:35 +0000265 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +0100266 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000267
Gilles Peskine449bd832023-01-11 14:50:10 +0100268 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, 1));
269 memset(X->p, 0, X->n * ciL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000270
Gilles Peskine449bd832023-01-11 14:50:10 +0100271 X->p[0] = mpi_sint_abs(z);
272 X->s = (z < 0) ? -1 : 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000273
274cleanup:
275
Gilles Peskine449bd832023-01-11 14:50:10 +0100276 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000277}
278
279/*
Paul Bakker2f5947e2011-05-18 15:47:11 +0000280 * Get a specific bit
281 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100282int mbedtls_mpi_get_bit(const mbedtls_mpi *X, size_t pos)
Paul Bakker2f5947e2011-05-18 15:47:11 +0000283{
Gilles Peskine449bd832023-01-11 14:50:10 +0100284 MPI_VALIDATE_RET(X != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000285
Gilles Peskine449bd832023-01-11 14:50:10 +0100286 if (X->n * biL <= pos) {
287 return 0;
288 }
Paul Bakker2f5947e2011-05-18 15:47:11 +0000289
Gilles Peskine449bd832023-01-11 14:50:10 +0100290 return (X->p[pos / biL] >> (pos % biL)) & 0x01;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000291}
292
293/*
294 * Set a bit to a specific value of 0 or 1
295 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100296int mbedtls_mpi_set_bit(mbedtls_mpi *X, size_t pos, unsigned char val)
Paul Bakker2f5947e2011-05-18 15:47:11 +0000297{
298 int ret = 0;
299 size_t off = pos / biL;
300 size_t idx = pos % biL;
Gilles Peskine449bd832023-01-11 14:50:10 +0100301 MPI_VALIDATE_RET(X != NULL);
Paul Bakker2f5947e2011-05-18 15:47:11 +0000302
Gilles Peskine449bd832023-01-11 14:50:10 +0100303 if (val != 0 && val != 1) {
304 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000305 }
306
Gilles Peskine449bd832023-01-11 14:50:10 +0100307 if (X->n * biL <= pos) {
308 if (val == 0) {
309 return 0;
310 }
311
312 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, off + 1));
313 }
314
315 X->p[off] &= ~((mbedtls_mpi_uint) 0x01 << idx);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200316 X->p[off] |= (mbedtls_mpi_uint) val << idx;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000317
318cleanup:
Paul Bakker9af723c2014-05-01 13:03:14 +0200319
Gilles Peskine449bd832023-01-11 14:50:10 +0100320 return ret;
Paul Bakker2f5947e2011-05-18 15:47:11 +0000321}
322
323/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200324 * Return the number of less significant zero-bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000325 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100326size_t mbedtls_mpi_lsb(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000327{
Paul Bakker23986e52011-04-24 08:57:21 +0000328 size_t i, j, count = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100329 MBEDTLS_INTERNAL_VALIDATE_RET(X != NULL, 0);
Paul Bakker5121ce52009-01-03 21:22:43 +0000330
Gilles Peskine449bd832023-01-11 14:50:10 +0100331 for (i = 0; i < X->n; i++) {
332 for (j = 0; j < biL; j++, count++) {
333 if (((X->p[i] >> j) & 1) != 0) {
334 return count;
335 }
336 }
337 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000338
Gilles Peskine449bd832023-01-11 14:50:10 +0100339 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000340}
341
342/*
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200343 * Return the number of bits
Paul Bakker5121ce52009-01-03 21:22:43 +0000344 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100345size_t mbedtls_mpi_bitlen(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000346{
Gilles Peskine449bd832023-01-11 14:50:10 +0100347 return mbedtls_mpi_core_bitlen(X->p, X->n);
Paul Bakker5121ce52009-01-03 21:22:43 +0000348}
349
350/*
351 * Return the total size in bytes
352 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100353size_t mbedtls_mpi_size(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +0000354{
Gilles Peskine449bd832023-01-11 14:50:10 +0100355 return (mbedtls_mpi_bitlen(X) + 7) >> 3;
Paul Bakker5121ce52009-01-03 21:22:43 +0000356}
357
358/*
359 * Convert an ASCII character to digit value
360 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100361static int mpi_get_digit(mbedtls_mpi_uint *d, int radix, char c)
Paul Bakker5121ce52009-01-03 21:22:43 +0000362{
363 *d = 255;
364
Gilles Peskine449bd832023-01-11 14:50:10 +0100365 if (c >= 0x30 && c <= 0x39) {
366 *d = c - 0x30;
367 }
368 if (c >= 0x41 && c <= 0x46) {
369 *d = c - 0x37;
370 }
371 if (c >= 0x61 && c <= 0x66) {
372 *d = c - 0x57;
373 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000374
Gilles Peskine449bd832023-01-11 14:50:10 +0100375 if (*d >= (mbedtls_mpi_uint) radix) {
376 return MBEDTLS_ERR_MPI_INVALID_CHARACTER;
377 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000378
Gilles Peskine449bd832023-01-11 14:50:10 +0100379 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000380}
381
382/*
383 * Import from an ASCII string
384 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100385int mbedtls_mpi_read_string(mbedtls_mpi *X, int radix, const char *s)
Paul Bakker5121ce52009-01-03 21:22:43 +0000386{
Janos Follath24eed8d2019-11-22 13:21:35 +0000387 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000388 size_t i, j, slen, n;
Gilles Peskine80f56732021-04-03 18:26:13 +0200389 int sign = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200390 mbedtls_mpi_uint d;
391 mbedtls_mpi T;
Gilles Peskine449bd832023-01-11 14:50:10 +0100392 MPI_VALIDATE_RET(X != NULL);
393 MPI_VALIDATE_RET(s != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000394
Gilles Peskine449bd832023-01-11 14:50:10 +0100395 if (radix < 2 || radix > 16) {
396 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Gilles Peskine7cba8592021-06-08 18:32:34 +0200397 }
398
Gilles Peskine449bd832023-01-11 14:50:10 +0100399 mbedtls_mpi_init(&T);
400
401 if (s[0] == 0) {
402 mbedtls_mpi_free(X);
403 return 0;
404 }
405
406 if (s[0] == '-') {
Gilles Peskine80f56732021-04-03 18:26:13 +0200407 ++s;
408 sign = -1;
409 }
410
Gilles Peskine449bd832023-01-11 14:50:10 +0100411 slen = strlen(s);
Paul Bakkerff60ee62010-03-16 21:09:09 +0000412
Gilles Peskine449bd832023-01-11 14:50:10 +0100413 if (radix == 16) {
Dave Rodgman68ef1d62023-05-18 20:49:03 +0100414 if (slen > SIZE_MAX >> 2) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100415 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Paul Bakker5121ce52009-01-03 21:22:43 +0000416 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000417
Gilles Peskine449bd832023-01-11 14:50:10 +0100418 n = BITS_TO_LIMBS(slen << 2);
419
420 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n));
421 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
422
423 for (i = slen, j = 0; i > 0; i--, j++) {
424 MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i - 1]));
425 X->p[j / (2 * ciL)] |= d << ((j % (2 * ciL)) << 2);
426 }
427 } else {
428 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
429
430 for (i = 0; i < slen; i++) {
431 MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i]));
432 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T, X, radix));
433 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, &T, d));
Paul Bakker5121ce52009-01-03 21:22:43 +0000434 }
435 }
436
Gilles Peskine449bd832023-01-11 14:50:10 +0100437 if (sign < 0 && mbedtls_mpi_bitlen(X) != 0) {
Gilles Peskine80f56732021-04-03 18:26:13 +0200438 X->s = -1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100439 }
Gilles Peskine80f56732021-04-03 18:26:13 +0200440
Paul Bakker5121ce52009-01-03 21:22:43 +0000441cleanup:
442
Gilles Peskine449bd832023-01-11 14:50:10 +0100443 mbedtls_mpi_free(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000444
Gilles Peskine449bd832023-01-11 14:50:10 +0100445 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000446}
447
448/*
Ron Eldora16fa292018-11-20 14:07:01 +0200449 * Helper to write the digits high-order first.
Paul Bakker5121ce52009-01-03 21:22:43 +0000450 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100451static int mpi_write_hlp(mbedtls_mpi *X, int radix,
452 char **p, const size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000453{
Janos Follath24eed8d2019-11-22 13:21:35 +0000454 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200455 mbedtls_mpi_uint r;
Ron Eldora16fa292018-11-20 14:07:01 +0200456 size_t length = 0;
457 char *p_end = *p + buflen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000458
Gilles Peskine449bd832023-01-11 14:50:10 +0100459 do {
460 if (length >= buflen) {
461 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
Ron Eldora16fa292018-11-20 14:07:01 +0200462 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000463
Gilles Peskine449bd832023-01-11 14:50:10 +0100464 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, radix));
465 MBEDTLS_MPI_CHK(mbedtls_mpi_div_int(X, NULL, X, radix));
Ron Eldora16fa292018-11-20 14:07:01 +0200466 /*
467 * Write the residue in the current position, as an ASCII character.
468 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100469 if (r < 0xA) {
470 *(--p_end) = (char) ('0' + r);
471 } else {
472 *(--p_end) = (char) ('A' + (r - 0xA));
473 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000474
Ron Eldora16fa292018-11-20 14:07:01 +0200475 length++;
Gilles Peskine449bd832023-01-11 14:50:10 +0100476 } while (mbedtls_mpi_cmp_int(X, 0) != 0);
Paul Bakker5121ce52009-01-03 21:22:43 +0000477
Gilles Peskine449bd832023-01-11 14:50:10 +0100478 memmove(*p, p_end, length);
Ron Eldora16fa292018-11-20 14:07:01 +0200479 *p += length;
Paul Bakker5121ce52009-01-03 21:22:43 +0000480
481cleanup:
482
Gilles Peskine449bd832023-01-11 14:50:10 +0100483 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000484}
485
486/*
487 * Export into an ASCII string
488 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100489int mbedtls_mpi_write_string(const mbedtls_mpi *X, int radix,
490 char *buf, size_t buflen, size_t *olen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000491{
Paul Bakker23986e52011-04-24 08:57:21 +0000492 int ret = 0;
493 size_t n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000494 char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200495 mbedtls_mpi T;
Gilles Peskine449bd832023-01-11 14:50:10 +0100496 MPI_VALIDATE_RET(X != NULL);
497 MPI_VALIDATE_RET(olen != NULL);
498 MPI_VALIDATE_RET(buflen == 0 || buf != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000499
Gilles Peskine449bd832023-01-11 14:50:10 +0100500 if (radix < 2 || radix > 16) {
501 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
502 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000503
Gilles Peskine449bd832023-01-11 14:50:10 +0100504 n = mbedtls_mpi_bitlen(X); /* Number of bits necessary to present `n`. */
505 if (radix >= 4) {
506 n >>= 1; /* Number of 4-adic digits necessary to present
Hanno Becker23cfea02019-02-04 09:45:07 +0000507 * `n`. If radix > 4, this might be a strict
508 * overapproximation of the number of
509 * radix-adic digits needed to present `n`. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100510 }
511 if (radix >= 16) {
512 n >>= 1; /* Number of hexadecimal digits necessary to
Hanno Becker23cfea02019-02-04 09:45:07 +0000513 * present `n`. */
514
Gilles Peskine449bd832023-01-11 14:50:10 +0100515 }
Janos Follath80470622019-03-06 13:43:02 +0000516 n += 1; /* Terminating null byte */
Hanno Becker23cfea02019-02-04 09:45:07 +0000517 n += 1; /* Compensate for the divisions above, which round down `n`
518 * in case it's not even. */
519 n += 1; /* Potential '-'-sign. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100520 n += (n & 1); /* Make n even to have enough space for hexadecimal writing,
Hanno Becker23cfea02019-02-04 09:45:07 +0000521 * which always uses an even number of hex-digits. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000522
Gilles Peskine449bd832023-01-11 14:50:10 +0100523 if (buflen < n) {
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100524 *olen = n;
Gilles Peskine449bd832023-01-11 14:50:10 +0100525 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
Paul Bakker5121ce52009-01-03 21:22:43 +0000526 }
527
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100528 p = buf;
Gilles Peskine449bd832023-01-11 14:50:10 +0100529 mbedtls_mpi_init(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000530
Gilles Peskine449bd832023-01-11 14:50:10 +0100531 if (X->s == -1) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000532 *p++ = '-';
Hanno Beckerc983c812019-02-01 16:41:30 +0000533 buflen--;
534 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000535
Gilles Peskine449bd832023-01-11 14:50:10 +0100536 if (radix == 16) {
Paul Bakker23986e52011-04-24 08:57:21 +0000537 int c;
538 size_t i, j, k;
Paul Bakker5121ce52009-01-03 21:22:43 +0000539
Gilles Peskine449bd832023-01-11 14:50:10 +0100540 for (i = X->n, k = 0; i > 0; i--) {
541 for (j = ciL; j > 0; j--) {
542 c = (X->p[i - 1] >> ((j - 1) << 3)) & 0xFF;
Paul Bakker5121ce52009-01-03 21:22:43 +0000543
Gilles Peskine449bd832023-01-11 14:50:10 +0100544 if (c == 0 && k == 0 && (i + j) != 2) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000545 continue;
Gilles Peskine449bd832023-01-11 14:50:10 +0100546 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000547
Paul Bakker98fe5ea2012-10-24 11:17:48 +0000548 *(p++) = "0123456789ABCDEF" [c / 16];
Paul Bakkerd2c167e2012-10-30 07:49:19 +0000549 *(p++) = "0123456789ABCDEF" [c % 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000550 k = 1;
551 }
552 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100553 } else {
554 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T, X));
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000555
Gilles Peskine449bd832023-01-11 14:50:10 +0100556 if (T.s == -1) {
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000557 T.s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100558 }
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000559
Gilles Peskine449bd832023-01-11 14:50:10 +0100560 MBEDTLS_MPI_CHK(mpi_write_hlp(&T, radix, &p, buflen));
Paul Bakker5121ce52009-01-03 21:22:43 +0000561 }
562
563 *p++ = '\0';
Manuel Pégourié-Gonnardf79b4252015-06-02 15:41:48 +0100564 *olen = p - buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000565
566cleanup:
567
Gilles Peskine449bd832023-01-11 14:50:10 +0100568 mbedtls_mpi_free(&T);
Paul Bakker5121ce52009-01-03 21:22:43 +0000569
Gilles Peskine449bd832023-01-11 14:50:10 +0100570 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000571}
572
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200573#if defined(MBEDTLS_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000574/*
575 * Read X from an opened file
576 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100577int mbedtls_mpi_read_file(mbedtls_mpi *X, int radix, FILE *fin)
Paul Bakker5121ce52009-01-03 21:22:43 +0000578{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200579 mbedtls_mpi_uint d;
Paul Bakker23986e52011-04-24 08:57:21 +0000580 size_t slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000581 char *p;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000582 /*
Paul Bakkercb37aa52011-11-30 16:00:20 +0000583 * Buffer should have space for (short) label and decimal formatted MPI,
584 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000585 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100586 char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
Paul Bakker5121ce52009-01-03 21:22:43 +0000587
Gilles Peskine449bd832023-01-11 14:50:10 +0100588 MPI_VALIDATE_RET(X != NULL);
589 MPI_VALIDATE_RET(fin != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000590
Gilles Peskine449bd832023-01-11 14:50:10 +0100591 if (radix < 2 || radix > 16) {
592 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
593 }
Hanno Becker73d7d792018-12-11 10:35:51 +0000594
Gilles Peskine449bd832023-01-11 14:50:10 +0100595 memset(s, 0, sizeof(s));
596 if (fgets(s, sizeof(s) - 1, fin) == NULL) {
597 return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
598 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000599
Gilles Peskine449bd832023-01-11 14:50:10 +0100600 slen = strlen(s);
601 if (slen == sizeof(s) - 2) {
602 return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
603 }
Paul Bakkercb37aa52011-11-30 16:00:20 +0000604
Gilles Peskine449bd832023-01-11 14:50:10 +0100605 if (slen > 0 && s[slen - 1] == '\n') {
606 slen--; s[slen] = '\0';
607 }
608 if (slen > 0 && s[slen - 1] == '\r') {
609 slen--; s[slen] = '\0';
610 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000611
612 p = s + slen;
Gilles Peskine449bd832023-01-11 14:50:10 +0100613 while (p-- > s) {
614 if (mpi_get_digit(&d, radix, *p) != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000615 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100616 }
617 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000618
Gilles Peskine449bd832023-01-11 14:50:10 +0100619 return mbedtls_mpi_read_string(X, radix, p + 1);
Paul Bakker5121ce52009-01-03 21:22:43 +0000620}
621
622/*
623 * Write X into an opened file (or stdout if fout == NULL)
624 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100625int mbedtls_mpi_write_file(const char *p, const mbedtls_mpi *X, int radix, FILE *fout)
Paul Bakker5121ce52009-01-03 21:22:43 +0000626{
Janos Follath24eed8d2019-11-22 13:21:35 +0000627 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000628 size_t n, slen, plen;
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000629 /*
Paul Bakker5531c6d2012-09-26 19:20:46 +0000630 * Buffer should have space for (short) label and decimal formatted MPI,
631 * newline characters and '\0'
Paul Bakkerfe3256e2011-11-25 12:11:43 +0000632 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100633 char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
634 MPI_VALIDATE_RET(X != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000635
Gilles Peskine449bd832023-01-11 14:50:10 +0100636 if (radix < 2 || radix > 16) {
637 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
638 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000639
Gilles Peskine449bd832023-01-11 14:50:10 +0100640 memset(s, 0, sizeof(s));
Paul Bakker5121ce52009-01-03 21:22:43 +0000641
Gilles Peskine449bd832023-01-11 14:50:10 +0100642 MBEDTLS_MPI_CHK(mbedtls_mpi_write_string(X, radix, s, sizeof(s) - 2, &n));
Paul Bakker5121ce52009-01-03 21:22:43 +0000643
Gilles Peskine449bd832023-01-11 14:50:10 +0100644 if (p == NULL) {
645 p = "";
646 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000647
Gilles Peskine449bd832023-01-11 14:50:10 +0100648 plen = strlen(p);
649 slen = strlen(s);
Paul Bakker5121ce52009-01-03 21:22:43 +0000650 s[slen++] = '\r';
651 s[slen++] = '\n';
652
Gilles Peskine449bd832023-01-11 14:50:10 +0100653 if (fout != NULL) {
654 if (fwrite(p, 1, plen, fout) != plen ||
655 fwrite(s, 1, slen, fout) != slen) {
656 return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
657 }
658 } else {
659 mbedtls_printf("%s%s", p, s);
Paul Bakker5121ce52009-01-03 21:22:43 +0000660 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000661
662cleanup:
663
Gilles Peskine449bd832023-01-11 14:50:10 +0100664 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000665}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200666#endif /* MBEDTLS_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000667
668/*
Janos Follatha778a942019-02-13 10:28:28 +0000669 * Import X from unsigned binary data, little endian
Przemyslaw Stekiel76960a72022-02-21 13:42:09 +0100670 *
671 * This function is guaranteed to return an MPI with exactly the necessary
672 * number of limbs (in particular, it does not skip 0s in the input).
Janos Follatha778a942019-02-13 10:28:28 +0000673 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100674int mbedtls_mpi_read_binary_le(mbedtls_mpi *X,
675 const unsigned char *buf, size_t buflen)
Janos Follatha778a942019-02-13 10:28:28 +0000676{
Janos Follath24eed8d2019-11-22 13:21:35 +0000677 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +0100678 const size_t limbs = CHARS_TO_LIMBS(buflen);
Janos Follatha778a942019-02-13 10:28:28 +0000679
680 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine449bd832023-01-11 14:50:10 +0100681 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
Janos Follatha778a942019-02-13 10:28:28 +0000682
Gilles Peskine449bd832023-01-11 14:50:10 +0100683 MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_le(X->p, X->n, buf, buflen));
Janos Follatha778a942019-02-13 10:28:28 +0000684
685cleanup:
686
Janos Follath171a7ef2019-02-15 16:17:45 +0000687 /*
688 * This function is also used to import keys. However, wiping the buffers
689 * upon failure is not necessary because failure only can happen before any
690 * input is copied.
691 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100692 return ret;
Janos Follatha778a942019-02-13 10:28:28 +0000693}
694
695/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000696 * Import X from unsigned binary data, big endian
Przemyslaw Stekiel76960a72022-02-21 13:42:09 +0100697 *
698 * This function is guaranteed to return an MPI with exactly the necessary
699 * number of limbs (in particular, it does not skip 0s in the input).
Paul Bakker5121ce52009-01-03 21:22:43 +0000700 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100701int mbedtls_mpi_read_binary(mbedtls_mpi *X, const unsigned char *buf, size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000702{
Janos Follath24eed8d2019-11-22 13:21:35 +0000703 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +0100704 const size_t limbs = CHARS_TO_LIMBS(buflen);
Paul Bakker5121ce52009-01-03 21:22:43 +0000705
Gilles Peskine449bd832023-01-11 14:50:10 +0100706 MPI_VALIDATE_RET(X != NULL);
707 MPI_VALIDATE_RET(buflen == 0 || buf != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +0000708
Hanno Becker073c1992017-10-17 15:17:27 +0100709 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine449bd832023-01-11 14:50:10 +0100710 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
Paul Bakker5121ce52009-01-03 21:22:43 +0000711
Gilles Peskine449bd832023-01-11 14:50:10 +0100712 MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_be(X->p, X->n, buf, buflen));
Paul Bakker5121ce52009-01-03 21:22:43 +0000713
714cleanup:
715
Janos Follath171a7ef2019-02-15 16:17:45 +0000716 /*
717 * This function is also used to import keys. However, wiping the buffers
718 * upon failure is not necessary because failure only can happen before any
719 * input is copied.
720 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100721 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000722}
723
724/*
Janos Follathe344d0f2019-02-19 16:17:40 +0000725 * Export X into unsigned binary data, little endian
726 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100727int mbedtls_mpi_write_binary_le(const mbedtls_mpi *X,
728 unsigned char *buf, size_t buflen)
Janos Follathe344d0f2019-02-19 16:17:40 +0000729{
Gilles Peskine449bd832023-01-11 14:50:10 +0100730 return mbedtls_mpi_core_write_le(X->p, X->n, buf, buflen);
Janos Follathe344d0f2019-02-19 16:17:40 +0000731}
732
733/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000734 * Export X into unsigned binary data, big endian
735 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100736int mbedtls_mpi_write_binary(const mbedtls_mpi *X,
737 unsigned char *buf, size_t buflen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000738{
Gilles Peskine449bd832023-01-11 14:50:10 +0100739 return mbedtls_mpi_core_write_be(X->p, X->n, buf, buflen);
Paul Bakker5121ce52009-01-03 21:22:43 +0000740}
741
742/*
743 * Left-shift: X <<= count
744 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100745int mbedtls_mpi_shift_l(mbedtls_mpi *X, size_t count)
Paul Bakker5121ce52009-01-03 21:22:43 +0000746{
Janos Follath24eed8d2019-11-22 13:21:35 +0000747 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Minos Galanakis0144b352023-05-02 14:02:32 +0100748 size_t i;
Gilles Peskine449bd832023-01-11 14:50:10 +0100749 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000750
Gilles Peskine449bd832023-01-11 14:50:10 +0100751 i = mbedtls_mpi_bitlen(X) + count;
Paul Bakker5121ce52009-01-03 21:22:43 +0000752
Gilles Peskine449bd832023-01-11 14:50:10 +0100753 if (X->n * biL < i) {
754 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, BITS_TO_LIMBS(i)));
755 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000756
757 ret = 0;
758
Minos Galanakis0144b352023-05-02 14:02:32 +0100759 mbedtls_mpi_core_shift_l(X->p, X->n, count);
Paul Bakker5121ce52009-01-03 21:22:43 +0000760cleanup:
761
Gilles Peskine449bd832023-01-11 14:50:10 +0100762 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000763}
764
765/*
766 * Right-shift: X >>= count
767 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100768int mbedtls_mpi_shift_r(mbedtls_mpi *X, size_t count)
Paul Bakker5121ce52009-01-03 21:22:43 +0000769{
Gilles Peskine449bd832023-01-11 14:50:10 +0100770 MPI_VALIDATE_RET(X != NULL);
771 if (X->n != 0) {
772 mbedtls_mpi_core_shift_r(X->p, X->n, count);
773 }
774 return 0;
Gilles Peskine66414202022-09-21 15:36:16 +0200775}
776
Paul Bakker5121ce52009-01-03 21:22:43 +0000777/*
778 * Compare unsigned values
779 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100780int mbedtls_mpi_cmp_abs(const mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000781{
Paul Bakker23986e52011-04-24 08:57:21 +0000782 size_t i, j;
Gilles Peskine449bd832023-01-11 14:50:10 +0100783 MPI_VALIDATE_RET(X != NULL);
784 MPI_VALIDATE_RET(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000785
Gilles Peskine449bd832023-01-11 14:50:10 +0100786 for (i = X->n; i > 0; i--) {
787 if (X->p[i - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000788 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100789 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000790 }
791
Gilles Peskine449bd832023-01-11 14:50:10 +0100792 for (j = Y->n; j > 0; j--) {
793 if (Y->p[j - 1] != 0) {
794 break;
795 }
796 }
797
798 if (i == 0 && j == 0) {
799 return 0;
800 }
801
802 if (i > j) {
803 return 1;
804 }
805 if (j > i) {
806 return -1;
807 }
808
809 for (; i > 0; i--) {
810 if (X->p[i - 1] > Y->p[i - 1]) {
811 return 1;
812 }
813 if (X->p[i - 1] < Y->p[i - 1]) {
814 return -1;
815 }
816 }
817
818 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000819}
820
821/*
822 * Compare signed values
823 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100824int mbedtls_mpi_cmp_mpi(const mbedtls_mpi *X, const mbedtls_mpi *Y)
Paul Bakker5121ce52009-01-03 21:22:43 +0000825{
Paul Bakker23986e52011-04-24 08:57:21 +0000826 size_t i, j;
Gilles Peskine449bd832023-01-11 14:50:10 +0100827 MPI_VALIDATE_RET(X != NULL);
828 MPI_VALIDATE_RET(Y != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000829
Gilles Peskine449bd832023-01-11 14:50:10 +0100830 for (i = X->n; i > 0; i--) {
831 if (X->p[i - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000832 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100833 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000834 }
835
Gilles Peskine449bd832023-01-11 14:50:10 +0100836 for (j = Y->n; j > 0; j--) {
837 if (Y->p[j - 1] != 0) {
838 break;
839 }
840 }
841
842 if (i == 0 && j == 0) {
843 return 0;
844 }
845
846 if (i > j) {
847 return X->s;
848 }
849 if (j > i) {
850 return -Y->s;
851 }
852
853 if (X->s > 0 && Y->s < 0) {
854 return 1;
855 }
856 if (Y->s > 0 && X->s < 0) {
857 return -1;
858 }
859
860 for (; i > 0; i--) {
861 if (X->p[i - 1] > Y->p[i - 1]) {
862 return X->s;
863 }
864 if (X->p[i - 1] < Y->p[i - 1]) {
865 return -X->s;
866 }
867 }
868
869 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000870}
871
Janos Follathee6abce2019-09-05 14:47:19 +0100872/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000873 * Compare signed values
874 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100875int mbedtls_mpi_cmp_int(const mbedtls_mpi *X, mbedtls_mpi_sint z)
Paul Bakker5121ce52009-01-03 21:22:43 +0000876{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200877 mbedtls_mpi Y;
878 mbedtls_mpi_uint p[1];
Gilles Peskine449bd832023-01-11 14:50:10 +0100879 MPI_VALIDATE_RET(X != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000880
Gilles Peskine449bd832023-01-11 14:50:10 +0100881 *p = mpi_sint_abs(z);
882 Y.s = (z < 0) ? -1 : 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000883 Y.n = 1;
884 Y.p = p;
885
Gilles Peskine449bd832023-01-11 14:50:10 +0100886 return mbedtls_mpi_cmp_mpi(X, &Y);
Paul Bakker5121ce52009-01-03 21:22:43 +0000887}
888
889/*
890 * Unsigned addition: X = |A| + |B| (HAC 14.7)
891 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100892int mbedtls_mpi_add_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +0000893{
Janos Follath24eed8d2019-11-22 13:21:35 +0000894 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +0100895 size_t j;
Gilles Peskine449bd832023-01-11 14:50:10 +0100896 MPI_VALIDATE_RET(X != NULL);
897 MPI_VALIDATE_RET(A != NULL);
898 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000899
Gilles Peskine449bd832023-01-11 14:50:10 +0100900 if (X == B) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200901 const mbedtls_mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000902 }
903
Gilles Peskine449bd832023-01-11 14:50:10 +0100904 if (X != A) {
905 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
906 }
Paul Bakker9af723c2014-05-01 13:03:14 +0200907
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000908 /*
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +0100909 * X must always be positive as a result of unsigned additions.
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000910 */
911 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000912
Gilles Peskine449bd832023-01-11 14:50:10 +0100913 for (j = B->n; j > 0; j--) {
914 if (B->p[j - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000915 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100916 }
917 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000918
Gilles Peskinedb14a9d2022-11-15 22:59:00 +0100919 /* Exit early to avoid undefined behavior on NULL+0 when X->n == 0
920 * and B is 0 (of any size). */
Gilles Peskine449bd832023-01-11 14:50:10 +0100921 if (j == 0) {
922 return 0;
923 }
Gilles Peskinedb14a9d2022-11-15 22:59:00 +0100924
Gilles Peskine449bd832023-01-11 14:50:10 +0100925 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j));
Paul Bakker5121ce52009-01-03 21:22:43 +0000926
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +0100927 /* j is the number of non-zero limbs of B. Add those to X. */
Paul Bakker5121ce52009-01-03 21:22:43 +0000928
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +0100929 mbedtls_mpi_uint *p = X->p;
930
Gilles Peskine449bd832023-01-11 14:50:10 +0100931 mbedtls_mpi_uint c = mbedtls_mpi_core_add(p, p, B->p, j);
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +0100932
933 p += j;
934
935 /* Now propagate any carry */
Paul Bakker5121ce52009-01-03 21:22:43 +0000936
Gilles Peskine449bd832023-01-11 14:50:10 +0100937 while (c != 0) {
938 if (j >= X->n) {
939 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j + 1));
Tom Cosgroveaf7d44b2022-08-24 14:05:26 +0100940 p = X->p + j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000941 }
942
Gilles Peskine449bd832023-01-11 14:50:10 +0100943 *p += c; c = (*p < c); j++; p++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000944 }
945
946cleanup:
947
Gilles Peskine449bd832023-01-11 14:50:10 +0100948 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000949}
950
Paul Bakker5121ce52009-01-03 21:22:43 +0000951/*
Gilles Peskine0e5faf62020-06-08 22:50:35 +0200952 * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
Paul Bakker5121ce52009-01-03 21:22:43 +0000953 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100954int mbedtls_mpi_sub_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
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 n;
Gilles Peskine0e5faf62020-06-08 22:50:35 +0200958 mbedtls_mpi_uint carry;
Gilles Peskine449bd832023-01-11 14:50:10 +0100959 MPI_VALIDATE_RET(X != NULL);
960 MPI_VALIDATE_RET(A != NULL);
961 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000962
Gilles Peskine449bd832023-01-11 14:50:10 +0100963 for (n = B->n; n > 0; n--) {
964 if (B->p[n - 1] != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000965 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100966 }
967 }
968 if (n > A->n) {
Gilles Peskinec8a91772021-01-27 22:30:43 +0100969 /* B >= (2^ciL)^n > A */
970 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
971 goto cleanup;
972 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000973
Gilles Peskine449bd832023-01-11 14:50:10 +0100974 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, A->n));
Gilles Peskine1acf7cb2020-07-23 01:03:22 +0200975
976 /* Set the high limbs of X to match A. Don't touch the lower limbs
977 * because X might be aliased to B, and we must not overwrite the
978 * significant digits of B. */
Aaron M. Uckoaf67d2c2023-01-17 11:52:22 -0500979 if (A->n > n && A != X) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100980 memcpy(X->p + n, A->p + n, (A->n - n) * ciL);
981 }
982 if (X->n > A->n) {
983 memset(X->p + A->n, 0, (X->n - A->n) * ciL);
984 }
Gilles Peskine1acf7cb2020-07-23 01:03:22 +0200985
Gilles Peskine449bd832023-01-11 14:50:10 +0100986 carry = mbedtls_mpi_core_sub(X->p, A->p, B->p, n);
987 if (carry != 0) {
Tom Cosgrove452c99c2022-08-25 10:07:07 +0100988 /* Propagate the carry through the rest of X. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100989 carry = mbedtls_mpi_core_sub_int(X->p + n, X->p + n, carry, X->n - n);
Tom Cosgrove452c99c2022-08-25 10:07:07 +0100990
991 /* If we have further carry/borrow, the result is negative. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100992 if (carry != 0) {
Gilles Peskine89b41302020-07-23 01:16:46 +0200993 ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
994 goto cleanup;
995 }
Gilles Peskinec097e9e2020-06-08 21:58:22 +0200996 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000997
Gilles Peskine1acf7cb2020-07-23 01:03:22 +0200998 /* X should always be positive as a result of unsigned subtractions. */
999 X->s = 1;
1000
Paul Bakker5121ce52009-01-03 21:22:43 +00001001cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01001002 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001003}
1004
Gilles Peskine72ee1e32022-11-09 21:34:09 +01001005/* Common function for signed addition and subtraction.
1006 * Calculate A + B * flip_B where flip_B is 1 or -1.
Paul Bakker5121ce52009-01-03 21:22:43 +00001007 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001008static int add_sub_mpi(mbedtls_mpi *X,
1009 const mbedtls_mpi *A, const mbedtls_mpi *B,
1010 int flip_B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001011{
Hanno Becker73d7d792018-12-11 10:35:51 +00001012 int ret, s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001013 MPI_VALIDATE_RET(X != NULL);
1014 MPI_VALIDATE_RET(A != NULL);
1015 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001016
Hanno Becker73d7d792018-12-11 10:35:51 +00001017 s = A->s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001018 if (A->s * B->s * flip_B < 0) {
1019 int cmp = mbedtls_mpi_cmp_abs(A, B);
1020 if (cmp >= 0) {
1021 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, A, B));
Gilles Peskine4a768dd2022-11-09 22:02:16 +01001022 /* If |A| = |B|, the result is 0 and we must set the sign bit
1023 * to +1 regardless of which of A or B was negative. Otherwise,
1024 * since |A| > |B|, the sign is the sign of A. */
1025 X->s = cmp == 0 ? 1 : s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001026 } else {
1027 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, B, A));
Gilles Peskine4a768dd2022-11-09 22:02:16 +01001028 /* Since |A| < |B|, the sign is the opposite of A. */
Paul Bakker5121ce52009-01-03 21:22:43 +00001029 X->s = -s;
1030 }
Gilles Peskine449bd832023-01-11 14:50:10 +01001031 } else {
1032 MBEDTLS_MPI_CHK(mbedtls_mpi_add_abs(X, A, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001033 X->s = s;
1034 }
1035
1036cleanup:
1037
Gilles Peskine449bd832023-01-11 14:50:10 +01001038 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001039}
1040
1041/*
Gilles Peskine72ee1e32022-11-09 21:34:09 +01001042 * Signed addition: X = A + B
1043 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001044int mbedtls_mpi_add_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Gilles Peskine72ee1e32022-11-09 21:34:09 +01001045{
Gilles Peskine449bd832023-01-11 14:50:10 +01001046 return add_sub_mpi(X, A, B, 1);
Gilles Peskine72ee1e32022-11-09 21:34:09 +01001047}
1048
1049/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001050 * Signed subtraction: X = A - B
Paul Bakker5121ce52009-01-03 21:22:43 +00001051 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001052int mbedtls_mpi_sub_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001053{
Gilles Peskine449bd832023-01-11 14:50:10 +01001054 return add_sub_mpi(X, A, B, -1);
Paul Bakker5121ce52009-01-03 21:22:43 +00001055}
1056
1057/*
1058 * Signed addition: X = A + b
1059 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001060int mbedtls_mpi_add_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001061{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001062 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001063 mbedtls_mpi_uint p[1];
Gilles Peskine449bd832023-01-11 14:50:10 +01001064 MPI_VALIDATE_RET(X != NULL);
1065 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001066
Gilles Peskine449bd832023-01-11 14:50:10 +01001067 p[0] = mpi_sint_abs(b);
1068 B.s = (b < 0) ? -1 : 1;
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001069 B.n = 1;
1070 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001071
Gilles Peskine449bd832023-01-11 14:50:10 +01001072 return mbedtls_mpi_add_mpi(X, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00001073}
1074
1075/*
Paul Bakker60b1d102013-10-29 10:02:51 +01001076 * Signed subtraction: X = A - b
Paul Bakker5121ce52009-01-03 21:22:43 +00001077 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001078int mbedtls_mpi_sub_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001079{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001080 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001081 mbedtls_mpi_uint p[1];
Gilles Peskine449bd832023-01-11 14:50:10 +01001082 MPI_VALIDATE_RET(X != NULL);
1083 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001084
Gilles Peskine449bd832023-01-11 14:50:10 +01001085 p[0] = mpi_sint_abs(b);
1086 B.s = (b < 0) ? -1 : 1;
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001087 B.n = 1;
1088 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001089
Gilles Peskine449bd832023-01-11 14:50:10 +01001090 return mbedtls_mpi_sub_mpi(X, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00001091}
1092
Paul Bakker5121ce52009-01-03 21:22:43 +00001093/*
1094 * Baseline multiplication: X = A * B (HAC 14.12)
1095 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001096int mbedtls_mpi_mul_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001097{
Janos Follath24eed8d2019-11-22 13:21:35 +00001098 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker1772e052022-04-13 06:51:40 +01001099 size_t i, j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001100 mbedtls_mpi TA, TB;
Hanno Beckerda763de2022-04-13 06:50:02 +01001101 int result_is_zero = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +01001102 MPI_VALIDATE_RET(X != NULL);
1103 MPI_VALIDATE_RET(A != NULL);
1104 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001105
Tom Cosgrove6af26f32022-08-24 16:40:55 +01001106 mbedtls_mpi_init(&TA);
1107 mbedtls_mpi_init(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00001108
Gilles Peskine449bd832023-01-11 14:50:10 +01001109 if (X == A) {
1110 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A)); A = &TA;
1111 }
1112 if (X == B) {
1113 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B)); B = &TB;
1114 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001115
Gilles Peskine449bd832023-01-11 14:50:10 +01001116 for (i = A->n; i > 0; i--) {
1117 if (A->p[i - 1] != 0) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001118 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001119 }
1120 }
1121 if (i == 0) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001122 result_is_zero = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001123 }
Hanno Beckerda763de2022-04-13 06:50:02 +01001124
Gilles Peskine449bd832023-01-11 14:50:10 +01001125 for (j = B->n; j > 0; j--) {
1126 if (B->p[j - 1] != 0) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001127 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001128 }
1129 }
1130 if (j == 0) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001131 result_is_zero = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001132 }
Hanno Beckerda763de2022-04-13 06:50:02 +01001133
Gilles Peskine449bd832023-01-11 14:50:10 +01001134 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i + j));
1135 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
Paul Bakker5121ce52009-01-03 21:22:43 +00001136
Tom Cosgrove6af26f32022-08-24 16:40:55 +01001137 mbedtls_mpi_core_mul(X->p, A->p, i, B->p, j);
Paul Bakker5121ce52009-01-03 21:22:43 +00001138
Hanno Beckerda763de2022-04-13 06:50:02 +01001139 /* If the result is 0, we don't shortcut the operation, which reduces
1140 * but does not eliminate side channels leaking the zero-ness. We do
1141 * need to take care to set the sign bit properly since the library does
1142 * not fully support an MPI object with a value of 0 and s == -1. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001143 if (result_is_zero) {
Hanno Beckerda763de2022-04-13 06:50:02 +01001144 X->s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001145 } else {
Hanno Beckerda763de2022-04-13 06:50:02 +01001146 X->s = A->s * B->s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001147 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001148
1149cleanup:
1150
Gilles Peskine449bd832023-01-11 14:50:10 +01001151 mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TA);
Paul Bakker5121ce52009-01-03 21:22:43 +00001152
Gilles Peskine449bd832023-01-11 14:50:10 +01001153 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001154}
1155
1156/*
1157 * Baseline multiplication: X = A * b
1158 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001159int mbedtls_mpi_mul_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001160{
Gilles Peskine449bd832023-01-11 14:50:10 +01001161 MPI_VALIDATE_RET(X != NULL);
1162 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001163
Hanno Becker35771312022-04-14 11:52:11 +01001164 size_t n = A->n;
Gilles Peskine449bd832023-01-11 14:50:10 +01001165 while (n > 0 && A->p[n - 1] == 0) {
Hanno Becker35771312022-04-14 11:52:11 +01001166 --n;
Gilles Peskine449bd832023-01-11 14:50:10 +01001167 }
Hanno Becker35771312022-04-14 11:52:11 +01001168
Hanno Becker74a11a32022-04-06 06:27:00 +01001169 /* The general method below doesn't work if b==0. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001170 if (b == 0 || n == 0) {
1171 return mbedtls_mpi_lset(X, 0);
1172 }
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001173
Hanno Beckeraef9cc42022-04-11 06:36:29 +01001174 /* Calculate A*b as A + A*(b-1) to take advantage of mbedtls_mpi_core_mla */
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001175 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001176 /* In general, A * b requires 1 limb more than b. If
1177 * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same
1178 * number of limbs as A and the call to grow() is not required since
Gilles Peskinee1bba7c2021-03-10 23:44:10 +01001179 * copy() will take care of the growth if needed. However, experimentally,
1180 * making the call to grow() unconditional causes slightly fewer
Gilles Peskinecd0dbf32020-07-24 00:09:04 +02001181 * calls to calloc() in ECP code, presumably because it reuses the
1182 * same mpi for a while and this way the mpi is more likely to directly
Hanno Becker9137b9c2022-04-12 10:51:54 +01001183 * grow to its final size.
1184 *
1185 * Note that calculating A*b as 0 + A*b doesn't work as-is because
1186 * A,X can be the same. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001187 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n + 1));
1188 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
1189 mbedtls_mpi_core_mla(X->p, X->n, A->p, n, b - 1);
Gilles Peskine8fd95c62020-07-23 21:58:50 +02001190
1191cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01001192 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001193}
1194
1195/*
Simon Butcherf5ba0452015-12-27 23:01:55 +00001196 * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1197 * mbedtls_mpi_uint divisor, d
Simon Butcher15b15d12015-11-26 19:35:03 +00001198 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001199static mbedtls_mpi_uint mbedtls_int_div_int(mbedtls_mpi_uint u1,
1200 mbedtls_mpi_uint u0,
1201 mbedtls_mpi_uint d,
1202 mbedtls_mpi_uint *r)
Simon Butcher15b15d12015-11-26 19:35:03 +00001203{
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001204#if defined(MBEDTLS_HAVE_UDBL)
1205 mbedtls_t_udbl dividend, quotient;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001206#else
Simon Butcher9803d072016-01-03 00:24:34 +00001207 const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
Gilles Peskine449bd832023-01-11 14:50:10 +01001208 const mbedtls_mpi_uint uint_halfword_mask = ((mbedtls_mpi_uint) 1 << biH) - 1;
Simon Butcherf5ba0452015-12-27 23:01:55 +00001209 mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1210 mbedtls_mpi_uint u0_msw, u0_lsw;
Simon Butcher9803d072016-01-03 00:24:34 +00001211 size_t s;
Manuel Pégourié-Gonnard16308882015-12-01 10:27:00 +01001212#endif
1213
Simon Butcher15b15d12015-11-26 19:35:03 +00001214 /*
1215 * Check for overflow
1216 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001217 if (0 == d || u1 >= d) {
1218 if (r != NULL) {
1219 *r = ~(mbedtls_mpi_uint) 0u;
1220 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001221
Gilles Peskine449bd832023-01-11 14:50:10 +01001222 return ~(mbedtls_mpi_uint) 0u;
Simon Butcher15b15d12015-11-26 19:35:03 +00001223 }
1224
1225#if defined(MBEDTLS_HAVE_UDBL)
Simon Butcher15b15d12015-11-26 19:35:03 +00001226 dividend = (mbedtls_t_udbl) u1 << biL;
1227 dividend |= (mbedtls_t_udbl) u0;
1228 quotient = dividend / d;
Gilles Peskine449bd832023-01-11 14:50:10 +01001229 if (quotient > ((mbedtls_t_udbl) 1 << biL) - 1) {
1230 quotient = ((mbedtls_t_udbl) 1 << biL) - 1;
1231 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001232
Gilles Peskine449bd832023-01-11 14:50:10 +01001233 if (r != NULL) {
1234 *r = (mbedtls_mpi_uint) (dividend - (quotient * d));
1235 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001236
1237 return (mbedtls_mpi_uint) quotient;
1238#else
Simon Butcher15b15d12015-11-26 19:35:03 +00001239
1240 /*
1241 * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1242 * Vol. 2 - Seminumerical Algorithms, Knuth
1243 */
1244
1245 /*
1246 * Normalize the divisor, d, and dividend, u0, u1
1247 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001248 s = mbedtls_mpi_core_clz(d);
Simon Butcher15b15d12015-11-26 19:35:03 +00001249 d = d << s;
1250
1251 u1 = u1 << s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001252 u1 |= (u0 >> (biL - s)) & (-(mbedtls_mpi_sint) s >> (biL - 1));
Simon Butcher15b15d12015-11-26 19:35:03 +00001253 u0 = u0 << s;
1254
1255 d1 = d >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001256 d0 = d & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001257
1258 u0_msw = u0 >> biH;
Simon Butcher9803d072016-01-03 00:24:34 +00001259 u0_lsw = u0 & uint_halfword_mask;
Simon Butcher15b15d12015-11-26 19:35:03 +00001260
1261 /*
1262 * Find the first quotient and remainder
1263 */
1264 q1 = u1 / d1;
1265 r0 = u1 - d1 * q1;
1266
Gilles Peskine449bd832023-01-11 14:50:10 +01001267 while (q1 >= radix || (q1 * d0 > radix * r0 + u0_msw)) {
Simon Butcher15b15d12015-11-26 19:35:03 +00001268 q1 -= 1;
1269 r0 += d1;
1270
Gilles Peskine449bd832023-01-11 14:50:10 +01001271 if (r0 >= radix) {
1272 break;
1273 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001274 }
1275
Gilles Peskine449bd832023-01-11 14:50:10 +01001276 rAX = (u1 * radix) + (u0_msw - q1 * d);
Simon Butcher15b15d12015-11-26 19:35:03 +00001277 q0 = rAX / d1;
1278 r0 = rAX - q0 * d1;
1279
Gilles Peskine449bd832023-01-11 14:50:10 +01001280 while (q0 >= radix || (q0 * d0 > radix * r0 + u0_lsw)) {
Simon Butcher15b15d12015-11-26 19:35:03 +00001281 q0 -= 1;
1282 r0 += d1;
1283
Gilles Peskine449bd832023-01-11 14:50:10 +01001284 if (r0 >= radix) {
1285 break;
1286 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001287 }
1288
Gilles Peskine449bd832023-01-11 14:50:10 +01001289 if (r != NULL) {
1290 *r = (rAX * radix + u0_lsw - q0 * d) >> s;
1291 }
Simon Butcher15b15d12015-11-26 19:35:03 +00001292
1293 quotient = q1 * radix + q0;
1294
1295 return quotient;
1296#endif
1297}
1298
1299/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001300 * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20)
Paul Bakker5121ce52009-01-03 21:22:43 +00001301 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001302int mbedtls_mpi_div_mpi(mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
1303 const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001304{
Janos Follath24eed8d2019-11-22 13:21:35 +00001305 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001306 size_t i, n, t, k;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001307 mbedtls_mpi X, Y, Z, T1, T2;
Alexander Kd19a1932019-11-01 18:20:42 +03001308 mbedtls_mpi_uint TP2[3];
Gilles Peskine449bd832023-01-11 14:50:10 +01001309 MPI_VALIDATE_RET(A != NULL);
1310 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001311
Gilles Peskine449bd832023-01-11 14:50:10 +01001312 if (mbedtls_mpi_cmp_int(B, 0) == 0) {
1313 return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
1314 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001315
Gilles Peskine449bd832023-01-11 14:50:10 +01001316 mbedtls_mpi_init(&X); mbedtls_mpi_init(&Y); mbedtls_mpi_init(&Z);
1317 mbedtls_mpi_init(&T1);
Alexander Kd19a1932019-11-01 18:20:42 +03001318 /*
1319 * Avoid dynamic memory allocations for constant-size T2.
1320 *
1321 * T2 is used for comparison only and the 3 limbs are assigned explicitly,
1322 * so nobody increase the size of the MPI and we're safe to use an on-stack
1323 * buffer.
1324 */
Alexander K35d6d462019-10-31 14:46:45 +03001325 T2.s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001326 T2.n = sizeof(TP2) / sizeof(*TP2);
Alexander Kd19a1932019-11-01 18:20:42 +03001327 T2.p = TP2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001328
Gilles Peskine449bd832023-01-11 14:50:10 +01001329 if (mbedtls_mpi_cmp_abs(A, B) < 0) {
1330 if (Q != NULL) {
1331 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(Q, 0));
1332 }
1333 if (R != NULL) {
1334 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, A));
1335 }
1336 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001337 }
1338
Gilles Peskine449bd832023-01-11 14:50:10 +01001339 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&X, A));
1340 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001341 X.s = Y.s = 1;
1342
Gilles Peskine449bd832023-01-11 14:50:10 +01001343 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&Z, A->n + 2));
1344 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Z, 0));
1345 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T1, A->n + 2));
Paul Bakker5121ce52009-01-03 21:22:43 +00001346
Gilles Peskine449bd832023-01-11 14:50:10 +01001347 k = mbedtls_mpi_bitlen(&Y) % biL;
1348 if (k < biL - 1) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001349 k = biL - 1 - k;
Gilles Peskine449bd832023-01-11 14:50:10 +01001350 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&X, k));
1351 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, k));
1352 } else {
1353 k = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001354 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001355
1356 n = X.n - 1;
1357 t = Y.n - 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001358 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, biL * (n - t)));
Paul Bakker5121ce52009-01-03 21:22:43 +00001359
Gilles Peskine449bd832023-01-11 14:50:10 +01001360 while (mbedtls_mpi_cmp_mpi(&X, &Y) >= 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001361 Z.p[n - t]++;
Gilles Peskine449bd832023-01-11 14:50:10 +01001362 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &Y));
Paul Bakker5121ce52009-01-03 21:22:43 +00001363 }
Gilles Peskine449bd832023-01-11 14:50:10 +01001364 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, biL * (n - t)));
Paul Bakker5121ce52009-01-03 21:22:43 +00001365
Gilles Peskine449bd832023-01-11 14:50:10 +01001366 for (i = n; i > t; i--) {
1367 if (X.p[i] >= Y.p[t]) {
1368 Z.p[i - t - 1] = ~(mbedtls_mpi_uint) 0u;
1369 } else {
1370 Z.p[i - t - 1] = mbedtls_int_div_int(X.p[i], X.p[i - 1],
1371 Y.p[t], NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001372 }
1373
Gilles Peskine449bd832023-01-11 14:50:10 +01001374 T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
1375 T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
Alexander K35d6d462019-10-31 14:46:45 +03001376 T2.p[2] = X.p[i];
1377
Paul Bakker5121ce52009-01-03 21:22:43 +00001378 Z.p[i - t - 1]++;
Gilles Peskine449bd832023-01-11 14:50:10 +01001379 do {
Paul Bakker5121ce52009-01-03 21:22:43 +00001380 Z.p[i - t - 1]--;
1381
Gilles Peskine449bd832023-01-11 14:50:10 +01001382 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&T1, 0));
1383 T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
Paul Bakker5121ce52009-01-03 21:22:43 +00001384 T1.p[1] = Y.p[t];
Gilles Peskine449bd832023-01-11 14:50:10 +01001385 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &T1, Z.p[i - t - 1]));
1386 } while (mbedtls_mpi_cmp_mpi(&T1, &T2) > 0);
Paul Bakker5121ce52009-01-03 21:22:43 +00001387
Gilles Peskine449bd832023-01-11 14:50:10 +01001388 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &Y, Z.p[i - t - 1]));
1389 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1)));
1390 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &T1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001391
Gilles Peskine449bd832023-01-11 14:50:10 +01001392 if (mbedtls_mpi_cmp_int(&X, 0) < 0) {
1393 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T1, &Y));
1394 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1)));
1395 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&X, &X, &T1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001396 Z.p[i - t - 1]--;
1397 }
1398 }
1399
Gilles Peskine449bd832023-01-11 14:50:10 +01001400 if (Q != NULL) {
1401 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(Q, &Z));
Paul Bakker5121ce52009-01-03 21:22:43 +00001402 Q->s = A->s * B->s;
1403 }
1404
Gilles Peskine449bd832023-01-11 14:50:10 +01001405 if (R != NULL) {
1406 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&X, k));
Paul Bakkerf02c5642012-11-13 10:25:21 +00001407 X.s = A->s;
Gilles Peskine449bd832023-01-11 14:50:10 +01001408 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, &X));
Paul Bakker5121ce52009-01-03 21:22:43 +00001409
Gilles Peskine449bd832023-01-11 14:50:10 +01001410 if (mbedtls_mpi_cmp_int(R, 0) == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001411 R->s = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001412 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001413 }
1414
1415cleanup:
1416
Gilles Peskine449bd832023-01-11 14:50:10 +01001417 mbedtls_mpi_free(&X); mbedtls_mpi_free(&Y); mbedtls_mpi_free(&Z);
1418 mbedtls_mpi_free(&T1);
1419 mbedtls_platform_zeroize(TP2, sizeof(TP2));
Paul Bakker5121ce52009-01-03 21:22:43 +00001420
Gilles Peskine449bd832023-01-11 14:50:10 +01001421 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001422}
1423
1424/*
1425 * Division by int: A = Q * b + R
Paul Bakker5121ce52009-01-03 21:22:43 +00001426 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001427int mbedtls_mpi_div_int(mbedtls_mpi *Q, mbedtls_mpi *R,
1428 const mbedtls_mpi *A,
1429 mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001430{
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001431 mbedtls_mpi B;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001432 mbedtls_mpi_uint p[1];
Gilles Peskine449bd832023-01-11 14:50:10 +01001433 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001434
Gilles Peskine449bd832023-01-11 14:50:10 +01001435 p[0] = mpi_sint_abs(b);
1436 B.s = (b < 0) ? -1 : 1;
Yuto Takano36c8ddc2021-07-05 09:10:52 +01001437 B.n = 1;
1438 B.p = p;
Paul Bakker5121ce52009-01-03 21:22:43 +00001439
Gilles Peskine449bd832023-01-11 14:50:10 +01001440 return mbedtls_mpi_div_mpi(Q, R, A, &B);
Paul Bakker5121ce52009-01-03 21:22:43 +00001441}
1442
1443/*
1444 * Modulo: R = A mod B
1445 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001446int mbedtls_mpi_mod_mpi(mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001447{
Janos Follath24eed8d2019-11-22 13:21:35 +00001448 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +01001449 MPI_VALIDATE_RET(R != NULL);
1450 MPI_VALIDATE_RET(A != NULL);
1451 MPI_VALIDATE_RET(B != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001452
Gilles Peskine449bd832023-01-11 14:50:10 +01001453 if (mbedtls_mpi_cmp_int(B, 0) < 0) {
1454 return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1455 }
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001456
Gilles Peskine449bd832023-01-11 14:50:10 +01001457 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(NULL, R, A, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001458
Gilles Peskine449bd832023-01-11 14:50:10 +01001459 while (mbedtls_mpi_cmp_int(R, 0) < 0) {
1460 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(R, R, B));
1461 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001462
Gilles Peskine449bd832023-01-11 14:50:10 +01001463 while (mbedtls_mpi_cmp_mpi(R, B) >= 0) {
1464 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(R, R, B));
1465 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001466
1467cleanup:
1468
Gilles Peskine449bd832023-01-11 14:50:10 +01001469 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001470}
1471
1472/*
1473 * Modulo: r = A mod b
1474 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001475int mbedtls_mpi_mod_int(mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b)
Paul Bakker5121ce52009-01-03 21:22:43 +00001476{
Paul Bakker23986e52011-04-24 08:57:21 +00001477 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001478 mbedtls_mpi_uint x, y, z;
Gilles Peskine449bd832023-01-11 14:50:10 +01001479 MPI_VALIDATE_RET(r != NULL);
1480 MPI_VALIDATE_RET(A != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00001481
Gilles Peskine449bd832023-01-11 14:50:10 +01001482 if (b == 0) {
1483 return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
1484 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001485
Gilles Peskine449bd832023-01-11 14:50:10 +01001486 if (b < 0) {
1487 return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1488 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001489
1490 /*
1491 * handle trivial cases
1492 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001493 if (b == 1 || A->n == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001494 *r = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +01001495 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001496 }
1497
Gilles Peskine449bd832023-01-11 14:50:10 +01001498 if (b == 2) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001499 *r = A->p[0] & 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001500 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001501 }
1502
1503 /*
1504 * general case
1505 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001506 for (i = A->n, y = 0; i > 0; i--) {
Paul Bakker23986e52011-04-24 08:57:21 +00001507 x = A->p[i - 1];
Gilles Peskine449bd832023-01-11 14:50:10 +01001508 y = (y << biH) | (x >> biH);
Paul Bakker5121ce52009-01-03 21:22:43 +00001509 z = y / b;
1510 y -= z * b;
1511
1512 x <<= biH;
Gilles Peskine449bd832023-01-11 14:50:10 +01001513 y = (y << biH) | (x >> biH);
Paul Bakker5121ce52009-01-03 21:22:43 +00001514 z = y / b;
1515 y -= z * b;
1516 }
1517
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001518 /*
1519 * If A is negative, then the current y represents a negative value.
1520 * Flipping it to the positive side.
1521 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001522 if (A->s < 0 && y != 0) {
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001523 y = b - y;
Gilles Peskine449bd832023-01-11 14:50:10 +01001524 }
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001525
Paul Bakker5121ce52009-01-03 21:22:43 +00001526 *r = y;
1527
Gilles Peskine449bd832023-01-11 14:50:10 +01001528 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001529}
1530
Gilles Peskine449bd832023-01-11 14:50:10 +01001531static void mpi_montg_init(mbedtls_mpi_uint *mm, const mbedtls_mpi *N)
Paul Bakker5121ce52009-01-03 21:22:43 +00001532{
Gilles Peskine449bd832023-01-11 14:50:10 +01001533 *mm = mbedtls_mpi_core_montmul_init(N->p);
Paul Bakker5121ce52009-01-03 21:22:43 +00001534}
1535
Tom Cosgrove93842842022-08-05 16:59:43 +01001536/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1537 *
1538 * \param[in,out] A One of the numbers to multiply.
1539 * It must have at least as many limbs as N
1540 * (A->n >= N->n), and any limbs beyond n are ignored.
1541 * On successful completion, A contains the result of
1542 * the multiplication A * B * R^-1 mod N where
1543 * R = (2^ciL)^n.
1544 * \param[in] B One of the numbers to multiply.
1545 * It must be nonzero and must not have more limbs than N
1546 * (B->n <= N->n).
Tom Cosgrove40d22942022-08-17 06:42:44 +01001547 * \param[in] N The modulus. \p N must be odd.
Tom Cosgrove93842842022-08-05 16:59:43 +01001548 * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
1549 * This is -N^-1 mod 2^ciL.
1550 * \param[in,out] T A bignum for temporary storage.
1551 * It must be at least twice the limb size of N plus 1
1552 * (T->n >= 2 * N->n + 1).
1553 * Its initial content is unused and
1554 * its final content is indeterminate.
Tom Cosgrove5dd97e62022-08-30 14:31:49 +01001555 * It does not get reallocated.
Tom Cosgrove93842842022-08-05 16:59:43 +01001556 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001557static void mpi_montmul(mbedtls_mpi *A, const mbedtls_mpi *B,
1558 const mbedtls_mpi *N, mbedtls_mpi_uint mm,
1559 mbedtls_mpi *T)
Paul Bakker5121ce52009-01-03 21:22:43 +00001560{
Gilles Peskine449bd832023-01-11 14:50:10 +01001561 mbedtls_mpi_core_montmul(A->p, A->p, B->p, B->n, N->p, N->n, mm, T->p);
Paul Bakker5121ce52009-01-03 21:22:43 +00001562}
1563
1564/*
1565 * Montgomery reduction: A = A * R^-1 mod N
Gilles Peskine2a82f722020-06-04 15:00:49 +02001566 *
Tom Cosgrove93842842022-08-05 16:59:43 +01001567 * See mpi_montmul() regarding constraints and guarantees on the parameters.
Paul Bakker5121ce52009-01-03 21:22:43 +00001568 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001569static void mpi_montred(mbedtls_mpi *A, const mbedtls_mpi *N,
1570 mbedtls_mpi_uint mm, mbedtls_mpi *T)
Paul Bakker5121ce52009-01-03 21:22:43 +00001571{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001572 mbedtls_mpi_uint z = 1;
1573 mbedtls_mpi U;
Paul Bakker5121ce52009-01-03 21:22:43 +00001574
Paul Bakker8ddb6452013-02-27 14:56:33 +01001575 U.n = U.s = (int) z;
Paul Bakker5121ce52009-01-03 21:22:43 +00001576 U.p = &z;
1577
Gilles Peskine449bd832023-01-11 14:50:10 +01001578 mpi_montmul(A, &U, N, mm, T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001579}
1580
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001581/**
1582 * Select an MPI from a table without leaking the index.
1583 *
1584 * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it
1585 * reads the entire table in order to avoid leaking the value of idx to an
1586 * attacker able to observe memory access patterns.
1587 *
1588 * \param[out] R Where to write the selected MPI.
1589 * \param[in] T The table to read from.
1590 * \param[in] T_size The number of elements in the table.
1591 * \param[in] idx The index of the element to select;
1592 * this must satisfy 0 <= idx < T_size.
1593 *
1594 * \return \c 0 on success, or a negative error code.
1595 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001596static int mpi_select(mbedtls_mpi *R, const mbedtls_mpi *T, size_t T_size, size_t idx)
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001597{
1598 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1599
Gilles Peskine449bd832023-01-11 14:50:10 +01001600 for (size_t i = 0; i < T_size; i++) {
1601 MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign(R, &T[i],
1602 (unsigned char) mbedtls_ct_size_bool_eq(i,
1603 idx)));
Manuel Pégourié-Gonnard92413ef2021-06-03 10:42:46 +02001604 }
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001605
1606cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01001607 return ret;
Manuel Pégourié-Gonnard1297ef32021-03-09 11:22:20 +01001608}
1609
Paul Bakker5121ce52009-01-03 21:22:43 +00001610/*
1611 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1612 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001613int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A,
1614 const mbedtls_mpi *E, const mbedtls_mpi *N,
1615 mbedtls_mpi *prec_RR)
Paul Bakker5121ce52009-01-03 21:22:43 +00001616{
Janos Follath24eed8d2019-11-22 13:21:35 +00001617 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follath74601202022-11-21 15:54:20 +00001618 size_t window_bitsize;
Paul Bakker23986e52011-04-24 08:57:21 +00001619 size_t i, j, nblimbs;
1620 size_t bufsize, nbits;
Paul Elliott1748de12023-02-13 15:35:35 +00001621 size_t exponent_bits_in_window = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001622 mbedtls_mpi_uint ei, mm, state;
Gilles Peskine449bd832023-01-11 14:50:10 +01001623 mbedtls_mpi RR, T, W[(size_t) 1 << MBEDTLS_MPI_WINDOW_SIZE], WW, Apos;
Paul Bakkerf6198c12012-05-16 08:02:29 +00001624 int neg;
Paul Bakker5121ce52009-01-03 21:22:43 +00001625
Gilles Peskine449bd832023-01-11 14:50:10 +01001626 MPI_VALIDATE_RET(X != NULL);
1627 MPI_VALIDATE_RET(A != NULL);
1628 MPI_VALIDATE_RET(E != NULL);
1629 MPI_VALIDATE_RET(N != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00001630
Gilles Peskine449bd832023-01-11 14:50:10 +01001631 if (mbedtls_mpi_cmp_int(N, 0) <= 0 || (N->p[0] & 1) == 0) {
1632 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1633 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001634
Gilles Peskine449bd832023-01-11 14:50:10 +01001635 if (mbedtls_mpi_cmp_int(E, 0) < 0) {
1636 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1637 }
Paul Bakkerf6198c12012-05-16 08:02:29 +00001638
Gilles Peskine449bd832023-01-11 14:50:10 +01001639 if (mbedtls_mpi_bitlen(E) > MBEDTLS_MPI_MAX_BITS ||
1640 mbedtls_mpi_bitlen(N) > MBEDTLS_MPI_MAX_BITS) {
1641 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
1642 }
Chris Jones9246d042020-11-25 15:12:39 +00001643
Paul Bakkerf6198c12012-05-16 08:02:29 +00001644 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001645 * Init temps and window size
1646 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001647 mpi_montg_init(&mm, N);
1648 mbedtls_mpi_init(&RR); mbedtls_mpi_init(&T);
1649 mbedtls_mpi_init(&Apos);
1650 mbedtls_mpi_init(&WW);
1651 memset(W, 0, sizeof(W));
Paul Bakker5121ce52009-01-03 21:22:43 +00001652
Gilles Peskine449bd832023-01-11 14:50:10 +01001653 i = mbedtls_mpi_bitlen(E);
Paul Bakker5121ce52009-01-03 21:22:43 +00001654
Gilles Peskine449bd832023-01-11 14:50:10 +01001655 window_bitsize = (i > 671) ? 6 : (i > 239) ? 5 :
1656 (i > 79) ? 4 : (i > 23) ? 3 : 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001657
Gilles Peskine449bd832023-01-11 14:50:10 +01001658#if (MBEDTLS_MPI_WINDOW_SIZE < 6)
1659 if (window_bitsize > MBEDTLS_MPI_WINDOW_SIZE) {
Janos Follath7fa11b82022-11-21 14:48:02 +00001660 window_bitsize = MBEDTLS_MPI_WINDOW_SIZE;
Gilles Peskine449bd832023-01-11 14:50:10 +01001661 }
Peter Kolbuse6bcad32018-12-11 14:01:44 -06001662#endif
Paul Bakkerb6d5f082011-11-25 11:52:11 +00001663
Janos Follathc8d66d52022-11-22 10:47:10 +00001664 const size_t w_table_used_size = (size_t) 1 << window_bitsize;
Janos Follath06000952022-11-22 10:18:06 +00001665
Paul Bakker5121ce52009-01-03 21:22:43 +00001666 /*
Janos Follathbe54ca72022-11-21 16:14:54 +00001667 * This function is not constant-trace: its memory accesses depend on the
1668 * exponent value. To defend against timing attacks, callers (such as RSA
1669 * and DHM) should use exponent blinding. However this is not enough if the
1670 * adversary can find the exponent in a single trace, so this function
1671 * takes extra precautions against adversaries who can observe memory
1672 * access patterns.
Janos Follathf08b40e2022-11-11 15:56:38 +00001673 *
Janos Follathbe54ca72022-11-21 16:14:54 +00001674 * This function performs a series of multiplications by table elements and
1675 * squarings, and we want the prevent the adversary from finding out which
1676 * table element was used, and from distinguishing between multiplications
1677 * and squarings. Firstly, when multiplying by an element of the window
1678 * W[i], we do a constant-trace table lookup to obfuscate i. This leaves
1679 * squarings as having a different memory access patterns from other
1680 * multiplications. So secondly, we put the accumulator X in the table as
1681 * well, and also do a constant-trace table lookup to multiply by X.
1682 *
1683 * This way, all multiplications take the form of a lookup-and-multiply.
1684 * The number of lookup-and-multiply operations inside each iteration of
1685 * the main loop still depends on the bits of the exponent, but since the
1686 * other operations in the loop don't have an easily recognizable memory
1687 * trace, an adversary is unlikely to be able to observe the exact
1688 * patterns.
1689 *
1690 * An adversary may still be able to recover the exponent if they can
1691 * observe both memory accesses and branches. However, branch prediction
1692 * exploitation typically requires many traces of execution over the same
1693 * data, which is defeated by randomized blinding.
Janos Follath84461482022-11-21 14:31:22 +00001694 *
1695 * To achieve this, we make a copy of X and we use the table entry in each
1696 * calculation from this point on.
Janos Follath8e7d6a02022-10-04 13:27:40 +01001697 */
Janos Follathc8d66d52022-11-22 10:47:10 +00001698 const size_t x_index = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +01001699 mbedtls_mpi_init(&W[x_index]);
1700 mbedtls_mpi_copy(&W[x_index], X);
Janos Follath84461482022-11-21 14:31:22 +00001701
Paul Bakker5121ce52009-01-03 21:22:43 +00001702 j = N->n + 1;
Tom Cosgrove93842842022-08-05 16:59:43 +01001703 /* All W[i] and X must have at least N->n limbs for the mpi_montmul()
Paul Bakker5121ce52009-01-03 21:22:43 +00001704 * and mpi_montred() calls later. Here we ensure that W[1] and X are
1705 * large enough, and later we'll grow other W[i] to the same length.
1706 * They must not be shrunk midway through this function!
1707 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001708 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[x_index], j));
1709 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1], j));
1710 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T, j * 2));
Paul Bakker5121ce52009-01-03 21:22:43 +00001711
1712 /*
Paul Bakker50546922012-05-19 08:40:49 +00001713 * Compensate for negative A (and correct at the end)
1714 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001715 neg = (A->s == -1);
1716 if (neg) {
1717 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Apos, A));
Paul Bakker50546922012-05-19 08:40:49 +00001718 Apos.s = 1;
1719 A = &Apos;
1720 }
1721
1722 /*
Paul Bakker5121ce52009-01-03 21:22:43 +00001723 * If 1st call, pre-compute R^2 mod N
1724 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001725 if (prec_RR == NULL || prec_RR->p == NULL) {
1726 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&RR, 1));
1727 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&RR, N->n * 2 * biL));
1728 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&RR, &RR, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00001729
Gilles Peskine449bd832023-01-11 14:50:10 +01001730 if (prec_RR != NULL) {
1731 memcpy(prec_RR, &RR, sizeof(mbedtls_mpi));
1732 }
1733 } else {
1734 memcpy(&RR, prec_RR, sizeof(mbedtls_mpi));
Paul Bakker5121ce52009-01-03 21:22:43 +00001735 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001736
1737 /*
1738 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1739 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001740 if (mbedtls_mpi_cmp_mpi(A, N) >= 0) {
1741 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&W[1], A, N));
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02001742 /* This should be a no-op because W[1] is already that large before
1743 * mbedtls_mpi_mod_mpi(), but it's necessary to avoid an overflow
Tom Cosgrove93842842022-08-05 16:59:43 +01001744 * in mpi_montmul() below, so let's make sure. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001745 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1], N->n + 1));
1746 } else {
1747 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[1], A));
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02001748 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001749
Gilles Peskine3da1a8f2021-06-08 23:17:42 +02001750 /* Note that this is safe because W[1] always has at least N->n limbs
1751 * (it grew above and was preserved by mbedtls_mpi_copy()). */
Gilles Peskine449bd832023-01-11 14:50:10 +01001752 mpi_montmul(&W[1], &RR, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001753
1754 /*
Janos Follath8e7d6a02022-10-04 13:27:40 +01001755 * W[x_index] = R^2 * R^-1 mod N = R mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00001756 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001757 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[x_index], &RR));
1758 mpi_montred(&W[x_index], N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001759
Janos Follathc8d66d52022-11-22 10:47:10 +00001760
Gilles Peskine449bd832023-01-11 14:50:10 +01001761 if (window_bitsize > 1) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001762 /*
Janos Follath74601202022-11-21 15:54:20 +00001763 * W[i] = W[1] ^ i
1764 *
1765 * The first bit of the sliding window is always 1 and therefore we
1766 * only need to store the second half of the table.
Janos Follathc8d66d52022-11-22 10:47:10 +00001767 *
1768 * (There are two special elements in the table: W[0] for the
1769 * accumulator/result and W[1] for A in Montgomery form. Both of these
1770 * are already set at this point.)
Paul Bakker5121ce52009-01-03 21:22:43 +00001771 */
Janos Follath74601202022-11-21 15:54:20 +00001772 j = w_table_used_size / 2;
Paul Bakker5121ce52009-01-03 21:22:43 +00001773
Gilles Peskine449bd832023-01-11 14:50:10 +01001774 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[j], N->n + 1));
1775 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[j], &W[1]));
Paul Bakker5121ce52009-01-03 21:22:43 +00001776
Gilles Peskine449bd832023-01-11 14:50:10 +01001777 for (i = 0; i < window_bitsize - 1; i++) {
1778 mpi_montmul(&W[j], &W[j], N, mm, &T);
1779 }
Paul Bakker0d7702c2013-10-29 16:18:35 +01001780
Paul Bakker5121ce52009-01-03 21:22:43 +00001781 /*
1782 * W[i] = W[i - 1] * W[1]
1783 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001784 for (i = j + 1; i < w_table_used_size; i++) {
1785 MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[i], N->n + 1));
1786 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[i], &W[i - 1]));
Paul Bakker5121ce52009-01-03 21:22:43 +00001787
Gilles Peskine449bd832023-01-11 14:50:10 +01001788 mpi_montmul(&W[i], &W[1], N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001789 }
1790 }
1791
1792 nblimbs = E->n;
1793 bufsize = 0;
1794 nbits = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001795 state = 0;
1796
Gilles Peskine449bd832023-01-11 14:50:10 +01001797 while (1) {
1798 if (bufsize == 0) {
1799 if (nblimbs == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001800 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01001801 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001802
Paul Bakker0d7702c2013-10-29 16:18:35 +01001803 nblimbs--;
1804
Gilles Peskine449bd832023-01-11 14:50:10 +01001805 bufsize = sizeof(mbedtls_mpi_uint) << 3;
Paul Bakker5121ce52009-01-03 21:22:43 +00001806 }
1807
1808 bufsize--;
1809
1810 ei = (E->p[nblimbs] >> bufsize) & 1;
1811
1812 /*
1813 * skip leading 0s
1814 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001815 if (ei == 0 && state == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001816 continue;
Gilles Peskine449bd832023-01-11 14:50:10 +01001817 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001818
Gilles Peskine449bd832023-01-11 14:50:10 +01001819 if (ei == 0 && state == 1) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001820 /*
Janos Follath8e7d6a02022-10-04 13:27:40 +01001821 * out of window, square W[x_index]
Paul Bakker5121ce52009-01-03 21:22:43 +00001822 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001823 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index));
1824 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001825 continue;
1826 }
1827
1828 /*
1829 * add ei to current window
1830 */
1831 state = 2;
1832
1833 nbits++;
Gilles Peskine449bd832023-01-11 14:50:10 +01001834 exponent_bits_in_window |= (ei << (window_bitsize - nbits));
Paul Bakker5121ce52009-01-03 21:22:43 +00001835
Gilles Peskine449bd832023-01-11 14:50:10 +01001836 if (nbits == window_bitsize) {
Paul Bakker5121ce52009-01-03 21:22:43 +00001837 /*
Janos Follath7fa11b82022-11-21 14:48:02 +00001838 * W[x_index] = W[x_index]^window_bitsize R^-1 mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00001839 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001840 for (i = 0; i < window_bitsize; i++) {
1841 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size,
1842 x_index));
1843 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Janos Follathb764ee12022-10-04 14:00:09 +01001844 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001845
1846 /*
Janos Follath7fa11b82022-11-21 14:48:02 +00001847 * W[x_index] = W[x_index] * W[exponent_bits_in_window] R^-1 mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00001848 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001849 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size,
1850 exponent_bits_in_window));
1851 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001852
1853 state--;
1854 nbits = 0;
Janos Follath7fa11b82022-11-21 14:48:02 +00001855 exponent_bits_in_window = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +00001856 }
1857 }
1858
1859 /*
1860 * process the remaining bits
1861 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001862 for (i = 0; i < nbits; i++) {
1863 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index));
1864 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001865
Janos Follath7fa11b82022-11-21 14:48:02 +00001866 exponent_bits_in_window <<= 1;
Paul Bakker5121ce52009-01-03 21:22:43 +00001867
Gilles Peskine449bd832023-01-11 14:50:10 +01001868 if ((exponent_bits_in_window & ((size_t) 1 << window_bitsize)) != 0) {
1869 MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, 1));
1870 mpi_montmul(&W[x_index], &WW, N, mm, &T);
Janos Follathb764ee12022-10-04 14:00:09 +01001871 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001872 }
1873
1874 /*
Janos Follath8e7d6a02022-10-04 13:27:40 +01001875 * W[x_index] = A^E * R * R^-1 mod N = A^E mod N
Paul Bakker5121ce52009-01-03 21:22:43 +00001876 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001877 mpi_montred(&W[x_index], N, mm, &T);
Paul Bakker5121ce52009-01-03 21:22:43 +00001878
Gilles Peskine449bd832023-01-11 14:50:10 +01001879 if (neg && E->n != 0 && (E->p[0] & 1) != 0) {
Janos Follath8e7d6a02022-10-04 13:27:40 +01001880 W[x_index].s = -1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001881 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&W[x_index], N, &W[x_index]));
Paul Bakkerf6198c12012-05-16 08:02:29 +00001882 }
1883
Janos Follath8e7d6a02022-10-04 13:27:40 +01001884 /*
1885 * Load the result in the output variable.
1886 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001887 mbedtls_mpi_copy(X, &W[x_index]);
Janos Follath8e7d6a02022-10-04 13:27:40 +01001888
Paul Bakker5121ce52009-01-03 21:22:43 +00001889cleanup:
1890
Janos Follathb2c2fca2022-11-21 15:05:31 +00001891 /* The first bit of the sliding window is always 1 and therefore the first
1892 * half of the table was unused. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001893 for (i = w_table_used_size/2; i < w_table_used_size; i++) {
1894 mbedtls_mpi_free(&W[i]);
1895 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001896
Gilles Peskine449bd832023-01-11 14:50:10 +01001897 mbedtls_mpi_free(&W[x_index]);
1898 mbedtls_mpi_free(&W[1]);
1899 mbedtls_mpi_free(&T);
1900 mbedtls_mpi_free(&Apos);
1901 mbedtls_mpi_free(&WW);
Paul Bakker6c591fa2011-05-05 11:49:20 +00001902
Gilles Peskine449bd832023-01-11 14:50:10 +01001903 if (prec_RR == NULL || prec_RR->p == NULL) {
1904 mbedtls_mpi_free(&RR);
1905 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001906
Gilles Peskine449bd832023-01-11 14:50:10 +01001907 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00001908}
1909
Paul Bakker5121ce52009-01-03 21:22:43 +00001910/*
1911 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1912 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001913int mbedtls_mpi_gcd(mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B)
Paul Bakker5121ce52009-01-03 21:22:43 +00001914{
Janos Follath24eed8d2019-11-22 13:21:35 +00001915 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +00001916 size_t lz, lzt;
Alexander Ke8ad49f2019-08-16 16:16:07 +03001917 mbedtls_mpi TA, TB;
Paul Bakker5121ce52009-01-03 21:22:43 +00001918
Gilles Peskine449bd832023-01-11 14:50:10 +01001919 MPI_VALIDATE_RET(G != NULL);
1920 MPI_VALIDATE_RET(A != NULL);
1921 MPI_VALIDATE_RET(B != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00001922
Gilles Peskine449bd832023-01-11 14:50:10 +01001923 mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00001924
Gilles Peskine449bd832023-01-11 14:50:10 +01001925 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A));
1926 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B));
Paul Bakker5121ce52009-01-03 21:22:43 +00001927
Gilles Peskine449bd832023-01-11 14:50:10 +01001928 lz = mbedtls_mpi_lsb(&TA);
1929 lzt = mbedtls_mpi_lsb(&TB);
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001930
Gilles Peskine27253bc2021-06-09 13:26:43 +02001931 /* The loop below gives the correct result when A==0 but not when B==0.
1932 * So have a special case for B==0. Leverage the fact that we just
1933 * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test
1934 * slightly more efficient than cmp_int(). */
Gilles Peskine449bd832023-01-11 14:50:10 +01001935 if (lzt == 0 && mbedtls_mpi_get_bit(&TB, 0) == 0) {
1936 ret = mbedtls_mpi_copy(G, A);
Gilles Peskine27253bc2021-06-09 13:26:43 +02001937 goto cleanup;
1938 }
1939
Gilles Peskine449bd832023-01-11 14:50:10 +01001940 if (lzt < lz) {
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001941 lz = lzt;
Gilles Peskine449bd832023-01-11 14:50:10 +01001942 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001943
Paul Bakker5121ce52009-01-03 21:22:43 +00001944 TA.s = TB.s = 1;
1945
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02001946 /* We mostly follow the procedure described in HAC 14.54, but with some
1947 * minor differences:
1948 * - Sequences of multiplications or divisions by 2 are grouped into a
1949 * single shift operation.
Gilles Peskineb09c7ee2021-06-21 18:58:39 +02001950 * - The procedure in HAC assumes that 0 < TB <= TA.
1951 * - The condition TB <= TA is not actually necessary for correctness.
1952 * TA and TB have symmetric roles except for the loop termination
1953 * condition, and the shifts at the beginning of the loop body
1954 * remove any significance from the ordering of TA vs TB before
1955 * the shifts.
1956 * - If TA = 0, the loop goes through 0 iterations and the result is
1957 * correctly TB.
1958 * - The case TB = 0 was short-circuited above.
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02001959 *
1960 * For the correctness proof below, decompose the original values of
1961 * A and B as
1962 * A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1
1963 * B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1
1964 * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'),
1965 * and gcd(A',B') is odd or 0.
1966 *
1967 * At the beginning, we have TA = |A| and TB = |B| so gcd(A,B) = gcd(TA,TB).
1968 * The code maintains the following invariant:
1969 * gcd(A,B) = 2^k * gcd(TA,TB) for some k (I)
Gilles Peskine4df3f1f2021-06-15 22:09:39 +02001970 */
1971
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02001972 /* Proof that the loop terminates:
1973 * At each iteration, either the right-shift by 1 is made on a nonzero
1974 * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases
1975 * by at least 1, or the right-shift by 1 is made on zero and then
1976 * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted
1977 * since in that case TB is calculated from TB-TA with the condition TB>TA).
1978 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001979 while (mbedtls_mpi_cmp_int(&TA, 0) != 0) {
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02001980 /* Divisions by 2 preserve the invariant (I). */
Gilles Peskine449bd832023-01-11 14:50:10 +01001981 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, mbedtls_mpi_lsb(&TA)));
1982 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, mbedtls_mpi_lsb(&TB)));
Paul Bakker5121ce52009-01-03 21:22:43 +00001983
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02001984 /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd,
1985 * TA-TB is even so the division by 2 has an integer result.
1986 * Invariant (I) is preserved since any odd divisor of both TA and TB
1987 * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2
Shaun Case8b0ecbc2021-12-20 21:14:10 -08001988 * also divides TB, and any odd divisor of both TB and |TA-TB|/2 also
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02001989 * divides TA.
1990 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001991 if (mbedtls_mpi_cmp_mpi(&TA, &TB) >= 0) {
1992 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TA, &TA, &TB));
1993 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, 1));
1994 } else {
1995 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TB, &TB, &TA));
1996 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00001997 }
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02001998 /* Note that one of TA or TB is still odd. */
Paul Bakker5121ce52009-01-03 21:22:43 +00001999 }
2000
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002001 /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k.
2002 * At the loop exit, TA = 0, so gcd(TA,TB) = TB.
2003 * - If there was at least one loop iteration, then one of TA or TB is odd,
2004 * and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case,
2005 * lz = min(a,b) so gcd(A,B) = 2^lz * TB.
2006 * - If there was no loop iteration, then A was 0, and gcd(A,B) = B.
Gilles Peskine4d3fd362021-06-21 11:40:38 +02002007 * In this case, lz = 0 and B = TB so gcd(A,B) = B = 2^lz * TB as well.
Gilles Peskine2a63c5b2021-06-16 13:42:04 +02002008 */
2009
Gilles Peskine449bd832023-01-11 14:50:10 +01002010 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&TB, lz));
2011 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(G, &TB));
Paul Bakker5121ce52009-01-03 21:22:43 +00002012
2013cleanup:
2014
Gilles Peskine449bd832023-01-11 14:50:10 +01002015 mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TB);
Paul Bakker5121ce52009-01-03 21:22:43 +00002016
Gilles Peskine449bd832023-01-11 14:50:10 +01002017 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002018}
2019
Paul Bakker33dc46b2014-04-30 16:11:39 +02002020/*
2021 * Fill X with size bytes of random.
Gilles Peskine22cdd0c2022-10-27 20:15:13 +02002022 * The bytes returned from the RNG are used in a specific order which
2023 * is suitable for deterministic ECDSA (see the specification of
2024 * mbedtls_mpi_random() and the implementation in mbedtls_mpi_fill_random()).
Paul Bakker33dc46b2014-04-30 16:11:39 +02002025 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002026int mbedtls_mpi_fill_random(mbedtls_mpi *X, size_t size,
2027 int (*f_rng)(void *, unsigned char *, size_t),
2028 void *p_rng)
Paul Bakker287781a2011-03-26 13:18:49 +00002029{
Janos Follath24eed8d2019-11-22 13:21:35 +00002030 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +01002031 const size_t limbs = CHARS_TO_LIMBS(size);
Hanno Beckerda1655a2017-10-18 14:21:44 +01002032
Gilles Peskine449bd832023-01-11 14:50:10 +01002033 MPI_VALIDATE_RET(X != NULL);
2034 MPI_VALIDATE_RET(f_rng != NULL);
Paul Bakker33dc46b2014-04-30 16:11:39 +02002035
Hanno Beckerda1655a2017-10-18 14:21:44 +01002036 /* Ensure that target MPI has exactly the necessary number of limbs */
Gilles Peskine449bd832023-01-11 14:50:10 +01002037 MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
2038 if (size == 0) {
2039 return 0;
2040 }
Paul Bakker287781a2011-03-26 13:18:49 +00002041
Gilles Peskine449bd832023-01-11 14:50:10 +01002042 ret = mbedtls_mpi_core_fill_random(X->p, X->n, size, f_rng, p_rng);
Paul Bakker287781a2011-03-26 13:18:49 +00002043
2044cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01002045 return ret;
Paul Bakker287781a2011-03-26 13:18:49 +00002046}
2047
Gilles Peskine449bd832023-01-11 14:50:10 +01002048int mbedtls_mpi_random(mbedtls_mpi *X,
2049 mbedtls_mpi_sint min,
2050 const mbedtls_mpi *N,
2051 int (*f_rng)(void *, unsigned char *, size_t),
2052 void *p_rng)
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002053{
Gilles Peskine449bd832023-01-11 14:50:10 +01002054 if (min < 0) {
2055 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2056 }
2057 if (mbedtls_mpi_cmp_int(N, min) <= 0) {
2058 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2059 }
Gilles Peskine1e918f42021-03-29 22:14:51 +02002060
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002061 /* Ensure that target MPI has exactly the same number of limbs
2062 * as the upper bound, even if the upper bound has leading zeros.
Gilles Peskine6b7ce962022-12-15 15:04:33 +01002063 * This is necessary for mbedtls_mpi_core_random. */
Gilles Peskine449bd832023-01-11 14:50:10 +01002064 int ret = mbedtls_mpi_resize_clear(X, N->n);
2065 if (ret != 0) {
2066 return ret;
2067 }
Gilles Peskine1a7df4e2021-04-01 15:57:18 +02002068
Gilles Peskine449bd832023-01-11 14:50:10 +01002069 return mbedtls_mpi_core_random(X->p, min, N->p, X->n, f_rng, p_rng);
Gilles Peskine02ac93a2021-03-29 22:02:55 +02002070}
2071
Paul Bakker5121ce52009-01-03 21:22:43 +00002072/*
2073 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
2074 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002075int mbedtls_mpi_inv_mod(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N)
Paul Bakker5121ce52009-01-03 21:22:43 +00002076{
Janos Follath24eed8d2019-11-22 13:21:35 +00002077 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002078 mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
Gilles Peskine449bd832023-01-11 14:50:10 +01002079 MPI_VALIDATE_RET(X != NULL);
2080 MPI_VALIDATE_RET(A != NULL);
2081 MPI_VALIDATE_RET(N != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +00002082
Gilles Peskine449bd832023-01-11 14:50:10 +01002083 if (mbedtls_mpi_cmp_int(N, 1) <= 0) {
2084 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2085 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002086
Gilles Peskine449bd832023-01-11 14:50:10 +01002087 mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TU); mbedtls_mpi_init(&U1); mbedtls_mpi_init(&U2);
2088 mbedtls_mpi_init(&G); mbedtls_mpi_init(&TB); mbedtls_mpi_init(&TV);
2089 mbedtls_mpi_init(&V1); mbedtls_mpi_init(&V2);
Paul Bakker5121ce52009-01-03 21:22:43 +00002090
Gilles Peskine449bd832023-01-11 14:50:10 +01002091 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&G, A, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002092
Gilles Peskine449bd832023-01-11 14:50:10 +01002093 if (mbedtls_mpi_cmp_int(&G, 1) != 0) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002094 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002095 goto cleanup;
2096 }
2097
Gilles Peskine449bd832023-01-11 14:50:10 +01002098 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&TA, A, N));
2099 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TU, &TA));
2100 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, N));
2101 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TV, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002102
Gilles Peskine449bd832023-01-11 14:50:10 +01002103 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U1, 1));
2104 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U2, 0));
2105 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V1, 0));
2106 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002107
Gilles Peskine449bd832023-01-11 14:50:10 +01002108 do {
2109 while ((TU.p[0] & 1) == 0) {
2110 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TU, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002111
Gilles Peskine449bd832023-01-11 14:50:10 +01002112 if ((U1.p[0] & 1) != 0 || (U2.p[0] & 1) != 0) {
2113 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&U1, &U1, &TB));
2114 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &TA));
Paul Bakker5121ce52009-01-03 21:22:43 +00002115 }
2116
Gilles Peskine449bd832023-01-11 14:50:10 +01002117 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U1, 1));
2118 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002119 }
2120
Gilles Peskine449bd832023-01-11 14:50:10 +01002121 while ((TV.p[0] & 1) == 0) {
2122 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TV, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002123
Gilles Peskine449bd832023-01-11 14:50:10 +01002124 if ((V1.p[0] & 1) != 0 || (V2.p[0] & 1) != 0) {
2125 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, &TB));
2126 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &TA));
Paul Bakker5121ce52009-01-03 21:22:43 +00002127 }
2128
Gilles Peskine449bd832023-01-11 14:50:10 +01002129 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V1, 1));
2130 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V2, 1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002131 }
2132
Gilles Peskine449bd832023-01-11 14:50:10 +01002133 if (mbedtls_mpi_cmp_mpi(&TU, &TV) >= 0) {
2134 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TU, &TU, &TV));
2135 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U1, &U1, &V1));
2136 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &V2));
2137 } else {
2138 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TV, &TV, &TU));
2139 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, &U1));
2140 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &U2));
Paul Bakker5121ce52009-01-03 21:22:43 +00002141 }
Gilles Peskine449bd832023-01-11 14:50:10 +01002142 } while (mbedtls_mpi_cmp_int(&TU, 0) != 0);
2143
2144 while (mbedtls_mpi_cmp_int(&V1, 0) < 0) {
2145 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002146 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002147
Gilles Peskine449bd832023-01-11 14:50:10 +01002148 while (mbedtls_mpi_cmp_mpi(&V1, N) >= 0) {
2149 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, N));
2150 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002151
Gilles Peskine449bd832023-01-11 14:50:10 +01002152 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &V1));
Paul Bakker5121ce52009-01-03 21:22:43 +00002153
2154cleanup:
2155
Gilles Peskine449bd832023-01-11 14:50:10 +01002156 mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TU); mbedtls_mpi_free(&U1); mbedtls_mpi_free(&U2);
2157 mbedtls_mpi_free(&G); mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TV);
2158 mbedtls_mpi_free(&V1); mbedtls_mpi_free(&V2);
Paul Bakker5121ce52009-01-03 21:22:43 +00002159
Gilles Peskine449bd832023-01-11 14:50:10 +01002160 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002161}
2162
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002163#if defined(MBEDTLS_GENPRIME)
Paul Bakkerd9374b02012-11-02 11:02:58 +00002164
Paul Bakker5121ce52009-01-03 21:22:43 +00002165static const int small_prime[] =
2166{
Gilles Peskine449bd832023-01-11 14:50:10 +01002167 3, 5, 7, 11, 13, 17, 19, 23,
2168 29, 31, 37, 41, 43, 47, 53, 59,
2169 61, 67, 71, 73, 79, 83, 89, 97,
2170 101, 103, 107, 109, 113, 127, 131, 137,
2171 139, 149, 151, 157, 163, 167, 173, 179,
2172 181, 191, 193, 197, 199, 211, 223, 227,
2173 229, 233, 239, 241, 251, 257, 263, 269,
2174 271, 277, 281, 283, 293, 307, 311, 313,
2175 317, 331, 337, 347, 349, 353, 359, 367,
2176 373, 379, 383, 389, 397, 401, 409, 419,
2177 421, 431, 433, 439, 443, 449, 457, 461,
2178 463, 467, 479, 487, 491, 499, 503, 509,
2179 521, 523, 541, 547, 557, 563, 569, 571,
2180 577, 587, 593, 599, 601, 607, 613, 617,
2181 619, 631, 641, 643, 647, 653, 659, 661,
2182 673, 677, 683, 691, 701, 709, 719, 727,
2183 733, 739, 743, 751, 757, 761, 769, 773,
2184 787, 797, 809, 811, 821, 823, 827, 829,
2185 839, 853, 857, 859, 863, 877, 881, 883,
2186 887, 907, 911, 919, 929, 937, 941, 947,
2187 953, 967, 971, 977, 983, 991, 997, -103
Paul Bakker5121ce52009-01-03 21:22:43 +00002188};
2189
2190/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002191 * Small divisors test (X must be positive)
2192 *
2193 * Return values:
2194 * 0: no small factor (possible prime, more tests needed)
2195 * 1: certain prime
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002196 * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002197 * other negative: error
Paul Bakker5121ce52009-01-03 21:22:43 +00002198 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002199static int mpi_check_small_factors(const mbedtls_mpi *X)
Paul Bakker5121ce52009-01-03 21:22:43 +00002200{
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002201 int ret = 0;
2202 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002203 mbedtls_mpi_uint r;
Paul Bakker5121ce52009-01-03 21:22:43 +00002204
Gilles Peskine449bd832023-01-11 14:50:10 +01002205 if ((X->p[0] & 1) == 0) {
2206 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2207 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002208
Gilles Peskine449bd832023-01-11 14:50:10 +01002209 for (i = 0; small_prime[i] > 0; i++) {
2210 if (mbedtls_mpi_cmp_int(X, small_prime[i]) <= 0) {
2211 return 1;
2212 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002213
Gilles Peskine449bd832023-01-11 14:50:10 +01002214 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, small_prime[i]));
Paul Bakker5121ce52009-01-03 21:22:43 +00002215
Gilles Peskine449bd832023-01-11 14:50:10 +01002216 if (r == 0) {
2217 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2218 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002219 }
2220
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002221cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01002222 return ret;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002223}
2224
2225/*
2226 * Miller-Rabin pseudo-primality test (HAC 4.24)
2227 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002228static int mpi_miller_rabin(const mbedtls_mpi *X, size_t rounds,
2229 int (*f_rng)(void *, unsigned char *, size_t),
2230 void *p_rng)
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002231{
Pascal Junodb99183d2015-03-11 16:49:45 +01002232 int ret, count;
Janos Follathda31fa12018-09-03 14:45:23 +01002233 size_t i, j, k, s;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002234 mbedtls_mpi W, R, T, A, RR;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002235
Gilles Peskine449bd832023-01-11 14:50:10 +01002236 MPI_VALIDATE_RET(X != NULL);
2237 MPI_VALIDATE_RET(f_rng != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00002238
Gilles Peskine449bd832023-01-11 14:50:10 +01002239 mbedtls_mpi_init(&W); mbedtls_mpi_init(&R);
2240 mbedtls_mpi_init(&T); mbedtls_mpi_init(&A);
2241 mbedtls_mpi_init(&RR);
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002242
Paul Bakker5121ce52009-01-03 21:22:43 +00002243 /*
2244 * W = |X| - 1
2245 * R = W >> lsb( W )
2246 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002247 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&W, X, 1));
2248 s = mbedtls_mpi_lsb(&W);
2249 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&R, &W));
2250 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&R, s));
Paul Bakker5121ce52009-01-03 21:22:43 +00002251
Gilles Peskine449bd832023-01-11 14:50:10 +01002252 for (i = 0; i < rounds; i++) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002253 /*
2254 * pick a random A, 1 < A < |X| - 1
2255 */
Pascal Junodb99183d2015-03-11 16:49:45 +01002256 count = 0;
2257 do {
Gilles Peskine449bd832023-01-11 14:50:10 +01002258 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&A, X->n * ciL, f_rng, p_rng));
Pascal Junodb99183d2015-03-11 16:49:45 +01002259
Gilles Peskine449bd832023-01-11 14:50:10 +01002260 j = mbedtls_mpi_bitlen(&A);
2261 k = mbedtls_mpi_bitlen(&W);
Pascal Junodb99183d2015-03-11 16:49:45 +01002262 if (j > k) {
Gilles Peskine449bd832023-01-11 14:50:10 +01002263 A.p[A.n - 1] &= ((mbedtls_mpi_uint) 1 << (k - (A.n - 1) * biL - 1)) - 1;
Pascal Junodb99183d2015-03-11 16:49:45 +01002264 }
2265
2266 if (count++ > 30) {
Jens Wiklanderf08aa3e2019-01-17 13:30:57 +01002267 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2268 goto cleanup;
Pascal Junodb99183d2015-03-11 16:49:45 +01002269 }
2270
Gilles Peskine449bd832023-01-11 14:50:10 +01002271 } while (mbedtls_mpi_cmp_mpi(&A, &W) >= 0 ||
2272 mbedtls_mpi_cmp_int(&A, 1) <= 0);
Paul Bakker5121ce52009-01-03 21:22:43 +00002273
2274 /*
2275 * A = A^R mod |X|
2276 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002277 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&A, &A, &R, X, &RR));
Paul Bakker5121ce52009-01-03 21:22:43 +00002278
Gilles Peskine449bd832023-01-11 14:50:10 +01002279 if (mbedtls_mpi_cmp_mpi(&A, &W) == 0 ||
2280 mbedtls_mpi_cmp_int(&A, 1) == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002281 continue;
Gilles Peskine449bd832023-01-11 14:50:10 +01002282 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002283
2284 j = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01002285 while (j < s && mbedtls_mpi_cmp_mpi(&A, &W) != 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002286 /*
2287 * A = A * A mod |X|
2288 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002289 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &A, &A));
2290 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&A, &T, X));
Paul Bakker5121ce52009-01-03 21:22:43 +00002291
Gilles Peskine449bd832023-01-11 14:50:10 +01002292 if (mbedtls_mpi_cmp_int(&A, 1) == 0) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002293 break;
Gilles Peskine449bd832023-01-11 14:50:10 +01002294 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002295
2296 j++;
2297 }
2298
2299 /*
2300 * not prime if A != |X| - 1 or A == 1
2301 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002302 if (mbedtls_mpi_cmp_mpi(&A, &W) != 0 ||
2303 mbedtls_mpi_cmp_int(&A, 1) == 0) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002304 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00002305 break;
2306 }
2307 }
2308
2309cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01002310 mbedtls_mpi_free(&W); mbedtls_mpi_free(&R);
2311 mbedtls_mpi_free(&T); mbedtls_mpi_free(&A);
2312 mbedtls_mpi_free(&RR);
Paul Bakker5121ce52009-01-03 21:22:43 +00002313
Gilles Peskine449bd832023-01-11 14:50:10 +01002314 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002315}
2316
2317/*
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002318 * Pseudo-primality test: small factors, then Miller-Rabin
2319 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002320int mbedtls_mpi_is_prime_ext(const mbedtls_mpi *X, int rounds,
2321 int (*f_rng)(void *, unsigned char *, size_t),
2322 void *p_rng)
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002323{
Janos Follath24eed8d2019-11-22 13:21:35 +00002324 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002325 mbedtls_mpi XX;
Gilles Peskine449bd832023-01-11 14:50:10 +01002326 MPI_VALIDATE_RET(X != NULL);
2327 MPI_VALIDATE_RET(f_rng != NULL);
Manuel Pégourié-Gonnard7f4ed672014-10-14 20:56:02 +02002328
2329 XX.s = 1;
2330 XX.n = X->n;
2331 XX.p = X->p;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002332
Gilles Peskine449bd832023-01-11 14:50:10 +01002333 if (mbedtls_mpi_cmp_int(&XX, 0) == 0 ||
2334 mbedtls_mpi_cmp_int(&XX, 1) == 0) {
2335 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002336 }
2337
Gilles Peskine449bd832023-01-11 14:50:10 +01002338 if (mbedtls_mpi_cmp_int(&XX, 2) == 0) {
2339 return 0;
2340 }
2341
2342 if ((ret = mpi_check_small_factors(&XX)) != 0) {
2343 if (ret == 1) {
2344 return 0;
2345 }
2346
2347 return ret;
2348 }
2349
2350 return mpi_miller_rabin(&XX, rounds, f_rng, p_rng);
Janos Follathf301d232018-08-14 13:34:01 +01002351}
2352
Manuel Pégourié-Gonnard378fb4b2013-11-22 18:39:18 +01002353/*
Paul Bakker5121ce52009-01-03 21:22:43 +00002354 * Prime number generation
Jethro Beekman66689272018-02-14 19:24:10 -08002355 *
Janos Follathf301d232018-08-14 13:34:01 +01002356 * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
2357 * be either 1024 bits or 1536 bits long, and flags must contain
2358 * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
Paul Bakker5121ce52009-01-03 21:22:43 +00002359 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002360int mbedtls_mpi_gen_prime(mbedtls_mpi *X, size_t nbits, int flags,
2361 int (*f_rng)(void *, unsigned char *, size_t),
2362 void *p_rng)
Paul Bakker5121ce52009-01-03 21:22:43 +00002363{
Jethro Beekman66689272018-02-14 19:24:10 -08002364#ifdef MBEDTLS_HAVE_INT64
2365// ceil(2^63.5)
2366#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
2367#else
2368// ceil(2^31.5)
2369#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
2370#endif
2371 int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker23986e52011-04-24 08:57:21 +00002372 size_t k, n;
Janos Follathda31fa12018-09-03 14:45:23 +01002373 int rounds;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002374 mbedtls_mpi_uint r;
2375 mbedtls_mpi Y;
Paul Bakker5121ce52009-01-03 21:22:43 +00002376
Gilles Peskine449bd832023-01-11 14:50:10 +01002377 MPI_VALIDATE_RET(X != NULL);
2378 MPI_VALIDATE_RET(f_rng != NULL);
Hanno Becker73d7d792018-12-11 10:35:51 +00002379
Gilles Peskine449bd832023-01-11 14:50:10 +01002380 if (nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS) {
2381 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2382 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002383
Gilles Peskine449bd832023-01-11 14:50:10 +01002384 mbedtls_mpi_init(&Y);
Paul Bakker5121ce52009-01-03 21:22:43 +00002385
Gilles Peskine449bd832023-01-11 14:50:10 +01002386 n = BITS_TO_LIMBS(nbits);
Paul Bakker5121ce52009-01-03 21:22:43 +00002387
Gilles Peskine449bd832023-01-11 14:50:10 +01002388 if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR) == 0) {
Janos Follathda31fa12018-09-03 14:45:23 +01002389 /*
2390 * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
2391 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002392 rounds = ((nbits >= 1300) ? 2 : (nbits >= 850) ? 3 :
2393 (nbits >= 650) ? 4 : (nbits >= 350) ? 8 :
2394 (nbits >= 250) ? 12 : (nbits >= 150) ? 18 : 27);
2395 } else {
Janos Follathda31fa12018-09-03 14:45:23 +01002396 /*
2397 * 2^-100 error probability, number of rounds computed based on HAC,
2398 * fact 4.48
2399 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002400 rounds = ((nbits >= 1450) ? 4 : (nbits >= 1150) ? 5 :
2401 (nbits >= 1000) ? 6 : (nbits >= 850) ? 7 :
2402 (nbits >= 750) ? 8 : (nbits >= 500) ? 13 :
2403 (nbits >= 250) ? 28 : (nbits >= 150) ? 40 : 51);
Janos Follathda31fa12018-09-03 14:45:23 +01002404 }
2405
Gilles Peskine449bd832023-01-11 14:50:10 +01002406 while (1) {
2407 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(X, n * ciL, f_rng, p_rng));
Jethro Beekman66689272018-02-14 19:24:10 -08002408 /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
Gilles Peskine449bd832023-01-11 14:50:10 +01002409 if (X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2) {
2410 continue;
2411 }
Jethro Beekman66689272018-02-14 19:24:10 -08002412
2413 k = n * biL;
Gilles Peskine449bd832023-01-11 14:50:10 +01002414 if (k > nbits) {
2415 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(X, k - nbits));
2416 }
Jethro Beekman66689272018-02-14 19:24:10 -08002417 X->p[0] |= 1;
2418
Gilles Peskine449bd832023-01-11 14:50:10 +01002419 if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH) == 0) {
2420 ret = mbedtls_mpi_is_prime_ext(X, rounds, f_rng, p_rng);
Jethro Beekman66689272018-02-14 19:24:10 -08002421
Gilles Peskine449bd832023-01-11 14:50:10 +01002422 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
Paul Bakker5121ce52009-01-03 21:22:43 +00002423 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +01002424 }
2425 } else {
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002426 /*
Tom Cosgrovece7f18c2022-07-28 05:50:56 +01002427 * A necessary condition for Y and X = 2Y + 1 to be prime
Jethro Beekman66689272018-02-14 19:24:10 -08002428 * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2429 * Make sure it is satisfied, while keeping X = 3 mod 4
Manuel Pégourié-Gonnardddf76152013-11-22 19:58:22 +01002430 */
Jethro Beekman66689272018-02-14 19:24:10 -08002431
2432 X->p[0] |= 2;
2433
Gilles Peskine449bd832023-01-11 14:50:10 +01002434 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, 3));
2435 if (r == 0) {
2436 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 8));
2437 } else if (r == 1) {
2438 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 4));
2439 }
Jethro Beekman66689272018-02-14 19:24:10 -08002440
2441 /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
Gilles Peskine449bd832023-01-11 14:50:10 +01002442 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, X));
2443 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, 1));
Jethro Beekman66689272018-02-14 19:24:10 -08002444
Gilles Peskine449bd832023-01-11 14:50:10 +01002445 while (1) {
Jethro Beekman66689272018-02-14 19:24:10 -08002446 /*
2447 * First, check small factors for X and Y
2448 * before doing Miller-Rabin on any of them
2449 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002450 if ((ret = mpi_check_small_factors(X)) == 0 &&
2451 (ret = mpi_check_small_factors(&Y)) == 0 &&
2452 (ret = mpi_miller_rabin(X, rounds, f_rng, p_rng))
2453 == 0 &&
2454 (ret = mpi_miller_rabin(&Y, rounds, f_rng, p_rng))
2455 == 0) {
Jethro Beekman66689272018-02-14 19:24:10 -08002456 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +01002457 }
Jethro Beekman66689272018-02-14 19:24:10 -08002458
Gilles Peskine449bd832023-01-11 14:50:10 +01002459 if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
Jethro Beekman66689272018-02-14 19:24:10 -08002460 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +01002461 }
Jethro Beekman66689272018-02-14 19:24:10 -08002462
2463 /*
2464 * Next candidates. We want to preserve Y = (X-1) / 2 and
2465 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2466 * so up Y by 6 and X by 12.
2467 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002468 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 12));
2469 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&Y, &Y, 6));
Paul Bakker5121ce52009-01-03 21:22:43 +00002470 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002471 }
2472 }
2473
2474cleanup:
2475
Gilles Peskine449bd832023-01-11 14:50:10 +01002476 mbedtls_mpi_free(&Y);
Paul Bakker5121ce52009-01-03 21:22:43 +00002477
Gilles Peskine449bd832023-01-11 14:50:10 +01002478 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002479}
2480
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002481#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +00002482
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002483#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00002484
Paul Bakker23986e52011-04-24 08:57:21 +00002485#define GCD_PAIR_COUNT 3
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002486
2487static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2488{
2489 { 693, 609, 21 },
2490 { 1764, 868, 28 },
2491 { 768454923, 542167814, 1 }
2492};
2493
Paul Bakker5121ce52009-01-03 21:22:43 +00002494/*
2495 * Checkup routine
2496 */
Gilles Peskine449bd832023-01-11 14:50:10 +01002497int mbedtls_mpi_self_test(int verbose)
Paul Bakker5121ce52009-01-03 21:22:43 +00002498{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002499 int ret, i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002500 mbedtls_mpi A, E, N, X, Y, U, V;
Paul Bakker5121ce52009-01-03 21:22:43 +00002501
Gilles Peskine449bd832023-01-11 14:50:10 +01002502 mbedtls_mpi_init(&A); mbedtls_mpi_init(&E); mbedtls_mpi_init(&N); mbedtls_mpi_init(&X);
2503 mbedtls_mpi_init(&Y); mbedtls_mpi_init(&U); mbedtls_mpi_init(&V);
Paul Bakker5121ce52009-01-03 21:22:43 +00002504
Gilles Peskine449bd832023-01-11 14:50:10 +01002505 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&A, 16,
2506 "EFE021C2645FD1DC586E69184AF4A31E" \
2507 "D5F53E93B5F123FA41680867BA110131" \
2508 "944FE7952E2517337780CB0DB80E61AA" \
2509 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002510
Gilles Peskine449bd832023-01-11 14:50:10 +01002511 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&E, 16,
2512 "B2E7EFD37075B9F03FF989C7C5051C20" \
2513 "34D2A323810251127E7BF8625A4F49A5" \
2514 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2515 "5B5C25763222FEFCCFC38B832366C29E"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002516
Gilles Peskine449bd832023-01-11 14:50:10 +01002517 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&N, 16,
2518 "0066A198186C18C10B2F5ED9B522752A" \
2519 "9830B69916E535C8F047518A889A43A5" \
2520 "94B6BED27A168D31D4A52F88925AA8F5"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002521
Gilles Peskine449bd832023-01-11 14:50:10 +01002522 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&X, &A, &N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002523
Gilles Peskine449bd832023-01-11 14:50:10 +01002524 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2525 "602AB7ECA597A3D6B56FF9829A5E8B85" \
2526 "9E857EA95A03512E2BAE7391688D264A" \
2527 "A5663B0341DB9CCFD2C4C5F421FEC814" \
2528 "8001B72E848A38CAE1C65F78E56ABDEF" \
2529 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2530 "ECF677152EF804370C1A305CAF3B5BF1" \
2531 "30879B56C61DE584A0F53A2447A51E"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002532
Gilles Peskine449bd832023-01-11 14:50:10 +01002533 if (verbose != 0) {
2534 mbedtls_printf(" MPI test #1 (mul_mpi): ");
2535 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002536
Gilles Peskine449bd832023-01-11 14:50:10 +01002537 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2538 if (verbose != 0) {
2539 mbedtls_printf("failed\n");
2540 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002541
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002542 ret = 1;
2543 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002544 }
2545
Gilles Peskine449bd832023-01-11 14:50:10 +01002546 if (verbose != 0) {
2547 mbedtls_printf("passed\n");
2548 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002549
Gilles Peskine449bd832023-01-11 14:50:10 +01002550 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&X, &Y, &A, &N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002551
Gilles Peskine449bd832023-01-11 14:50:10 +01002552 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2553 "256567336059E52CAE22925474705F39A94"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002554
Gilles Peskine449bd832023-01-11 14:50:10 +01002555 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&V, 16,
2556 "6613F26162223DF488E9CD48CC132C7A" \
2557 "0AC93C701B001B092E4E5B9F73BCD27B" \
2558 "9EE50D0657C77F374E903CDFA4C642"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002559
Gilles Peskine449bd832023-01-11 14:50:10 +01002560 if (verbose != 0) {
2561 mbedtls_printf(" MPI test #2 (div_mpi): ");
2562 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002563
Gilles Peskine449bd832023-01-11 14:50:10 +01002564 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0 ||
2565 mbedtls_mpi_cmp_mpi(&Y, &V) != 0) {
2566 if (verbose != 0) {
2567 mbedtls_printf("failed\n");
2568 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002569
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002570 ret = 1;
2571 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002572 }
2573
Gilles Peskine449bd832023-01-11 14:50:10 +01002574 if (verbose != 0) {
2575 mbedtls_printf("passed\n");
2576 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002577
Gilles Peskine449bd832023-01-11 14:50:10 +01002578 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&X, &A, &E, &N, NULL));
Paul Bakker5121ce52009-01-03 21:22:43 +00002579
Gilles Peskine449bd832023-01-11 14:50:10 +01002580 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2581 "36E139AEA55215609D2816998ED020BB" \
2582 "BD96C37890F65171D948E9BC7CBAA4D9" \
2583 "325D24D6A3C12710F10A09FA08AB87"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002584
Gilles Peskine449bd832023-01-11 14:50:10 +01002585 if (verbose != 0) {
2586 mbedtls_printf(" MPI test #3 (exp_mod): ");
2587 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002588
Gilles Peskine449bd832023-01-11 14:50:10 +01002589 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2590 if (verbose != 0) {
2591 mbedtls_printf("failed\n");
2592 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002593
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002594 ret = 1;
2595 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002596 }
2597
Gilles Peskine449bd832023-01-11 14:50:10 +01002598 if (verbose != 0) {
2599 mbedtls_printf("passed\n");
2600 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002601
Gilles Peskine449bd832023-01-11 14:50:10 +01002602 MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&X, &A, &N));
Paul Bakker5121ce52009-01-03 21:22:43 +00002603
Gilles Peskine449bd832023-01-11 14:50:10 +01002604 MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
2605 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2606 "C3DBA76456363A10869622EAC2DD84EC" \
2607 "C5B8A74DAC4D09E03B5E0BE779F2DF61"));
Paul Bakker5121ce52009-01-03 21:22:43 +00002608
Gilles Peskine449bd832023-01-11 14:50:10 +01002609 if (verbose != 0) {
2610 mbedtls_printf(" MPI test #4 (inv_mod): ");
2611 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002612
Gilles Peskine449bd832023-01-11 14:50:10 +01002613 if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
2614 if (verbose != 0) {
2615 mbedtls_printf("failed\n");
2616 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002617
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002618 ret = 1;
2619 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +00002620 }
2621
Gilles Peskine449bd832023-01-11 14:50:10 +01002622 if (verbose != 0) {
2623 mbedtls_printf("passed\n");
2624 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002625
Gilles Peskine449bd832023-01-11 14:50:10 +01002626 if (verbose != 0) {
2627 mbedtls_printf(" MPI test #5 (simple gcd): ");
2628 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002629
Gilles Peskine449bd832023-01-11 14:50:10 +01002630 for (i = 0; i < GCD_PAIR_COUNT; i++) {
2631 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&X, gcd_pairs[i][0]));
2632 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Y, gcd_pairs[i][1]));
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002633
Gilles Peskine449bd832023-01-11 14:50:10 +01002634 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&A, &X, &Y));
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002635
Gilles Peskine449bd832023-01-11 14:50:10 +01002636 if (mbedtls_mpi_cmp_int(&A, gcd_pairs[i][2]) != 0) {
2637 if (verbose != 0) {
2638 mbedtls_printf("failed at %d\n", i);
2639 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002640
Manuel Pégourié-Gonnard9e987ed2014-01-20 10:03:15 +01002641 ret = 1;
2642 goto cleanup;
2643 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002644 }
2645
Gilles Peskine449bd832023-01-11 14:50:10 +01002646 if (verbose != 0) {
2647 mbedtls_printf("passed\n");
2648 }
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00002649
Paul Bakker5121ce52009-01-03 21:22:43 +00002650cleanup:
2651
Gilles Peskine449bd832023-01-11 14:50:10 +01002652 if (ret != 0 && verbose != 0) {
2653 mbedtls_printf("Unexpected error, return code = %08X\n", (unsigned int) ret);
2654 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002655
Gilles Peskine449bd832023-01-11 14:50:10 +01002656 mbedtls_mpi_free(&A); mbedtls_mpi_free(&E); mbedtls_mpi_free(&N); mbedtls_mpi_free(&X);
2657 mbedtls_mpi_free(&Y); mbedtls_mpi_free(&U); mbedtls_mpi_free(&V);
Paul Bakker5121ce52009-01-03 21:22:43 +00002658
Gilles Peskine449bd832023-01-11 14:50:10 +01002659 if (verbose != 0) {
2660 mbedtls_printf("\n");
2661 }
Paul Bakker5121ce52009-01-03 21:22:43 +00002662
Gilles Peskine449bd832023-01-11 14:50:10 +01002663 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +00002664}
2665
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002666#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00002667
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002668#endif /* MBEDTLS_BIGNUM_C */