blob: 5343bc650d1621d2f6fe4ace70ae69d5a9dc1145 [file] [log] [blame]
Janos Follath0ded6312022-08-09 13:34:54 +01001/*
Janos Follatha95f2042022-08-19 12:09:17 +01002 * Low-level modular bignum functions
Janos Follath0ded6312022-08-09 13:34:54 +01003 *
4 * Copyright The Mbed TLS Contributors
Dave Rodgman16799db2023-11-02 19:47:20 +00005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Janos Follath0ded6312022-08-09 13:34:54 +01006 */
7
8#include "common.h"
9
Janos Follathf2334b72023-08-17 12:24:46 +000010#if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_ECP_WITH_MPI_UINT)
Janos Follath0ded6312022-08-09 13:34:54 +010011
12#include <string.h>
13
14#include "mbedtls/error.h"
15#include "mbedtls/platform_util.h"
16
Janos Follath0ded6312022-08-09 13:34:54 +010017#include "mbedtls/platform.h"
Janos Follath0ded6312022-08-09 13:34:54 +010018
19#include "bignum_core.h"
20#include "bignum_mod_raw.h"
21#include "bignum_mod.h"
22#include "constant_time_internal.h"
23
Gabor Mezei9a66ab12023-01-25 13:23:38 +010024#include "bignum_mod_raw_invasive.h"
25
Gilles Peskine449bd832023-01-11 14:50:10 +010026void mbedtls_mpi_mod_raw_cond_assign(mbedtls_mpi_uint *X,
27 const mbedtls_mpi_uint *A,
28 const mbedtls_mpi_mod_modulus *N,
29 unsigned char assign)
Gabor Mezei12071d42022-09-12 16:35:58 +020030{
Dave Rodgmancd2e38b2023-05-17 13:31:55 +010031 mbedtls_mpi_core_cond_assign(X, A, N->limbs, mbedtls_ct_bool(assign));
Gabor Mezei12071d42022-09-12 16:35:58 +020032}
33
Gilles Peskine449bd832023-01-11 14:50:10 +010034void mbedtls_mpi_mod_raw_cond_swap(mbedtls_mpi_uint *X,
35 mbedtls_mpi_uint *Y,
36 const mbedtls_mpi_mod_modulus *N,
37 unsigned char swap)
Gabor Mezei12071d42022-09-12 16:35:58 +020038{
Dave Rodgmancd2e38b2023-05-17 13:31:55 +010039 mbedtls_mpi_core_cond_swap(X, Y, N->limbs, mbedtls_ct_bool(swap));
Gabor Mezei12071d42022-09-12 16:35:58 +020040}
41
Mihir Raj Singh432cacf2023-01-11 21:12:46 +053042int mbedtls_mpi_mod_raw_read(mbedtls_mpi_uint *X,
43 const mbedtls_mpi_mod_modulus *N,
44 const unsigned char *input,
45 size_t input_length,
46 mbedtls_mpi_mod_ext_rep ext_rep)
Janos Follath0ded6312022-08-09 13:34:54 +010047{
48 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
49
Gilles Peskine449bd832023-01-11 14:50:10 +010050 switch (ext_rep) {
Janos Follath296ea662022-08-11 14:58:29 +010051 case MBEDTLS_MPI_MOD_EXT_REP_LE:
Mihir Raj Singh432cacf2023-01-11 21:12:46 +053052 ret = mbedtls_mpi_core_read_le(X, N->limbs,
53 input, input_length);
Janos Follath296ea662022-08-11 14:58:29 +010054 break;
55 case MBEDTLS_MPI_MOD_EXT_REP_BE:
Mihir Raj Singh432cacf2023-01-11 21:12:46 +053056 ret = mbedtls_mpi_core_read_be(X, N->limbs,
57 input, input_length);
Janos Follath296ea662022-08-11 14:58:29 +010058 break;
59 default:
Gilles Peskine449bd832023-01-11 14:50:10 +010060 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Janos Follath296ea662022-08-11 14:58:29 +010061 }
Janos Follath0ded6312022-08-09 13:34:54 +010062
Gilles Peskine449bd832023-01-11 14:50:10 +010063 if (ret != 0) {
Janos Follath0ded6312022-08-09 13:34:54 +010064 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +010065 }
Janos Follath0ded6312022-08-09 13:34:54 +010066
Mihir Raj Singh432cacf2023-01-11 21:12:46 +053067 if (!mbedtls_mpi_core_lt_ct(X, N->p, N->limbs)) {
Janos Follath0ded6312022-08-09 13:34:54 +010068 ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
69 goto cleanup;
70 }
71
72cleanup:
73
Gilles Peskine449bd832023-01-11 14:50:10 +010074 return ret;
Janos Follath0ded6312022-08-09 13:34:54 +010075}
76
Mihir Raj Singh432cacf2023-01-11 21:12:46 +053077int mbedtls_mpi_mod_raw_write(const mbedtls_mpi_uint *A,
78 const mbedtls_mpi_mod_modulus *N,
79 unsigned char *output,
80 size_t output_length,
81 mbedtls_mpi_mod_ext_rep ext_rep)
Janos Follath0ded6312022-08-09 13:34:54 +010082{
Gilles Peskine449bd832023-01-11 14:50:10 +010083 switch (ext_rep) {
Janos Follath296ea662022-08-11 14:58:29 +010084 case MBEDTLS_MPI_MOD_EXT_REP_LE:
Mihir Raj Singh432cacf2023-01-11 21:12:46 +053085 return mbedtls_mpi_core_write_le(A, N->limbs,
86 output, output_length);
Janos Follath296ea662022-08-11 14:58:29 +010087 case MBEDTLS_MPI_MOD_EXT_REP_BE:
Mihir Raj Singh432cacf2023-01-11 21:12:46 +053088 return mbedtls_mpi_core_write_be(A, N->limbs,
89 output, output_length);
Janos Follath296ea662022-08-11 14:58:29 +010090 default:
Gilles Peskine449bd832023-01-11 14:50:10 +010091 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Janos Follath296ea662022-08-11 14:58:29 +010092 }
Janos Follath0ded6312022-08-09 13:34:54 +010093}
94
Gilles Peskine449bd832023-01-11 14:50:10 +010095void mbedtls_mpi_mod_raw_sub(mbedtls_mpi_uint *X,
96 const mbedtls_mpi_uint *A,
97 const mbedtls_mpi_uint *B,
98 const mbedtls_mpi_mod_modulus *N)
Gabor Mezei4c7cf7d2022-11-09 14:07:43 +010099{
Gilles Peskine449bd832023-01-11 14:50:10 +0100100 mbedtls_mpi_uint c = mbedtls_mpi_core_sub(X, A, B, N->limbs);
Gabor Mezei4c7cf7d2022-11-09 14:07:43 +0100101
Gilles Peskine449bd832023-01-11 14:50:10 +0100102 (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) c);
Gabor Mezei4c7cf7d2022-11-09 14:07:43 +0100103}
104
Gabor Mezeiaaa1d2a2023-01-23 16:13:43 +0100105MBEDTLS_STATIC_TESTABLE
Gabor Mezei9073f7d2023-01-23 19:05:37 +0100106void mbedtls_mpi_mod_raw_fix_quasi_reduction(mbedtls_mpi_uint *X,
107 const mbedtls_mpi_mod_modulus *N)
Gabor Mezeiaaa1d2a2023-01-23 16:13:43 +0100108{
Gabor Mezeiaaa1d2a2023-01-23 16:13:43 +0100109 mbedtls_mpi_uint c = mbedtls_mpi_core_sub(X, X, N->p, N->limbs);
110
111 (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) c);
Gabor Mezeiaaa1d2a2023-01-23 16:13:43 +0100112}
113
Gabor Mezei627e5b12023-01-24 18:13:24 +0100114
Gilles Peskine449bd832023-01-11 14:50:10 +0100115void mbedtls_mpi_mod_raw_mul(mbedtls_mpi_uint *X,
116 const mbedtls_mpi_uint *A,
117 const mbedtls_mpi_uint *B,
118 const mbedtls_mpi_mod_modulus *N,
119 mbedtls_mpi_uint *T)
Gabor Mezei979d34c2022-12-07 16:02:33 +0100120{
Minos Galanakisc7408a42023-06-25 20:56:59 +0100121 /* Standard (A * B) multiplication stored into pre-allocated T
Minos Galanakisc4e49582023-06-27 14:03:35 +0100122 * buffer of fixed limb size of (2N + 1).
Minos Galanakis53a16b32023-06-26 17:05:53 +0100123 *
Minos Galanakisc4e49582023-06-27 14:03:35 +0100124 * The space may not not fully filled by when
125 * MBEDTLS_MPI_MOD_REP_OPT_RED is used. */
126 const size_t T_limbs = BITS_TO_LIMBS(N->bits) * 2;
Minos Galanakis2ed8fb72023-06-14 16:01:47 +0100127 switch (N->int_rep) {
128 case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
129 mbedtls_mpi_core_montmul(X, A, B, N->limbs, N->p, N->limbs,
130 N->rep.mont.mm, T);
131 break;
132 case MBEDTLS_MPI_MOD_REP_OPT_RED:
133 mbedtls_mpi_core_mul(T, A, N->limbs, B, N->limbs);
Minos Galanakis7b109322023-06-16 14:28:36 +0100134
135 /* Optimised Reduction */
Minos Galanakis2ed8fb72023-06-14 16:01:47 +0100136 (*N->rep.ored.modp)(T, T_limbs);
Minos Galanakis7b109322023-06-16 14:28:36 +0100137
Minos Galanakis8eb61042023-06-26 10:03:19 +0100138 /* Convert back to canonical representation */
Minos Galanakis2ed8fb72023-06-14 16:01:47 +0100139 mbedtls_mpi_mod_raw_fix_quasi_reduction(T, N);
140 memcpy(X, T, N->limbs * sizeof(mbedtls_mpi_uint));
141 break;
142 default:
143 break;
144 }
145
Gabor Mezei979d34c2022-12-07 16:02:33 +0100146}
147
Gilles Peskine449bd832023-01-11 14:50:10 +0100148size_t mbedtls_mpi_mod_raw_inv_prime_working_limbs(size_t AN_limbs)
Tom Cosgrove61292682022-12-08 09:44:10 +0000149{
150 /* mbedtls_mpi_mod_raw_inv_prime() needs a temporary for the exponent,
151 * which will be the same size as the modulus and input (AN_limbs),
152 * and additional space to pass to mbedtls_mpi_core_exp_mod(). */
Gilles Peskine449bd832023-01-11 14:50:10 +0100153 return AN_limbs +
154 mbedtls_mpi_core_exp_mod_working_limbs(AN_limbs, AN_limbs);
Tom Cosgrove61292682022-12-08 09:44:10 +0000155}
156
Gilles Peskine449bd832023-01-11 14:50:10 +0100157void mbedtls_mpi_mod_raw_inv_prime(mbedtls_mpi_uint *X,
158 const mbedtls_mpi_uint *A,
159 const mbedtls_mpi_uint *N,
160 size_t AN_limbs,
161 const mbedtls_mpi_uint *RR,
162 mbedtls_mpi_uint *T)
Tom Cosgrove61292682022-12-08 09:44:10 +0000163{
164 /* Inversion by power: g^|G| = 1 => g^(-1) = g^(|G|-1), and
165 * |G| = N - 1, so we want
166 * g^(|G|-1) = g^(N - 2)
167 */
Tom Cosgrove5f099302022-12-09 10:58:15 +0000168
169 /* Use the first AN_limbs of T to hold N - 2 */
Tom Cosgrove61292682022-12-08 09:44:10 +0000170 mbedtls_mpi_uint *Nminus2 = T;
Gilles Peskine449bd832023-01-11 14:50:10 +0100171 (void) mbedtls_mpi_core_sub_int(Nminus2, N, 2, AN_limbs);
Tom Cosgrove61292682022-12-08 09:44:10 +0000172
Tom Cosgrove5f099302022-12-09 10:58:15 +0000173 /* Rest of T is given to exp_mod for its working space */
Gilles Peskine449bd832023-01-11 14:50:10 +0100174 mbedtls_mpi_core_exp_mod(X,
175 A, N, AN_limbs, Nminus2, AN_limbs,
176 RR, T + AN_limbs);
Tom Cosgrove61292682022-12-08 09:44:10 +0000177}
178
Gilles Peskine449bd832023-01-11 14:50:10 +0100179void mbedtls_mpi_mod_raw_add(mbedtls_mpi_uint *X,
180 const mbedtls_mpi_uint *A,
181 const mbedtls_mpi_uint *B,
182 const mbedtls_mpi_mod_modulus *N)
Hanno Beckera45b6fe2022-11-01 13:14:28 +0000183{
Werner Lewisd391b8c2022-11-08 15:53:47 +0000184 mbedtls_mpi_uint carry, borrow;
Gilles Peskine449bd832023-01-11 14:50:10 +0100185 carry = mbedtls_mpi_core_add(X, A, B, N->limbs);
186 borrow = mbedtls_mpi_core_sub(X, X, N->p, N->limbs);
187 (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) (carry ^ borrow));
Hanno Beckera45b6fe2022-11-01 13:14:28 +0000188}
Janos Follath5933f692022-11-02 14:35:17 +0000189
Gilles Peskine1e2a4d42022-12-20 19:21:17 +0100190int mbedtls_mpi_mod_raw_canonical_to_modulus_rep(
191 mbedtls_mpi_uint *X,
Gilles Peskine449bd832023-01-11 14:50:10 +0100192 const mbedtls_mpi_mod_modulus *N)
Gilles Peskine1e2a4d42022-12-20 19:21:17 +0100193{
Gilles Peskine449bd832023-01-11 14:50:10 +0100194 switch (N->int_rep) {
Gilles Peskine1e2a4d42022-12-20 19:21:17 +0100195 case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
Gilles Peskine449bd832023-01-11 14:50:10 +0100196 return mbedtls_mpi_mod_raw_to_mont_rep(X, N);
Gilles Peskine1e2a4d42022-12-20 19:21:17 +0100197 case MBEDTLS_MPI_MOD_REP_OPT_RED:
Gilles Peskine449bd832023-01-11 14:50:10 +0100198 return 0;
Gilles Peskine1e2a4d42022-12-20 19:21:17 +0100199 default:
Gilles Peskine449bd832023-01-11 14:50:10 +0100200 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Gilles Peskine1e2a4d42022-12-20 19:21:17 +0100201 }
202}
203
204int mbedtls_mpi_mod_raw_modulus_to_canonical_rep(
205 mbedtls_mpi_uint *X,
Gilles Peskine449bd832023-01-11 14:50:10 +0100206 const mbedtls_mpi_mod_modulus *N)
Gilles Peskine1e2a4d42022-12-20 19:21:17 +0100207{
Gilles Peskine449bd832023-01-11 14:50:10 +0100208 switch (N->int_rep) {
Gilles Peskine1e2a4d42022-12-20 19:21:17 +0100209 case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
Gilles Peskine449bd832023-01-11 14:50:10 +0100210 return mbedtls_mpi_mod_raw_from_mont_rep(X, N);
Gilles Peskine1e2a4d42022-12-20 19:21:17 +0100211 case MBEDTLS_MPI_MOD_REP_OPT_RED:
Gilles Peskine449bd832023-01-11 14:50:10 +0100212 return 0;
Gilles Peskine1e2a4d42022-12-20 19:21:17 +0100213 default:
Gilles Peskine449bd832023-01-11 14:50:10 +0100214 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Gilles Peskine1e2a4d42022-12-20 19:21:17 +0100215 }
216}
217
Gilles Peskine449bd832023-01-11 14:50:10 +0100218int mbedtls_mpi_mod_raw_random(mbedtls_mpi_uint *X,
219 mbedtls_mpi_uint min,
220 const mbedtls_mpi_mod_modulus *N,
221 int (*f_rng)(void *, unsigned char *, size_t),
222 void *p_rng)
Gilles Peskinea57cf982022-12-06 22:54:09 +0100223{
Gilles Peskine449bd832023-01-11 14:50:10 +0100224 int ret = mbedtls_mpi_core_random(X, min, N->p, N->limbs, f_rng, p_rng);
225 if (ret != 0) {
226 return ret;
227 }
228 return mbedtls_mpi_mod_raw_canonical_to_modulus_rep(X, N);
Gilles Peskinea57cf982022-12-06 22:54:09 +0100229}
230
Mihir Raj Singh432cacf2023-01-11 21:12:46 +0530231int mbedtls_mpi_mod_raw_to_mont_rep(mbedtls_mpi_uint *X,
232 const mbedtls_mpi_mod_modulus *N)
Hanno Becker5ad4a932022-08-09 14:45:53 +0100233{
Minos Galanakisd9299c32022-11-01 16:19:07 +0000234 mbedtls_mpi_uint *T;
Mihir Raj Singh432cacf2023-01-11 21:12:46 +0530235 const size_t t_limbs = mbedtls_mpi_core_montmul_working_limbs(N->limbs);
Minos Galanakisd9299c32022-11-01 16:19:07 +0000236
Gilles Peskine449bd832023-01-11 14:50:10 +0100237 if ((T = (mbedtls_mpi_uint *) mbedtls_calloc(t_limbs, ciL)) == NULL) {
238 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
239 }
Minos Galanakisd9299c32022-11-01 16:19:07 +0000240
Mihir Raj Singh432cacf2023-01-11 21:12:46 +0530241 mbedtls_mpi_core_to_mont_rep(X, X, N->p, N->limbs,
242 N->rep.mont.mm, N->rep.mont.rr, T);
Minos Galanakisd9299c32022-11-01 16:19:07 +0000243
Tom Cosgroveca8c61b2023-07-17 15:17:40 +0100244 mbedtls_zeroize_and_free(T, t_limbs * ciL);
Gilles Peskine449bd832023-01-11 14:50:10 +0100245 return 0;
Hanno Becker5ad4a932022-08-09 14:45:53 +0100246}
Janos Follath5933f692022-11-02 14:35:17 +0000247
Mihir Raj Singh432cacf2023-01-11 21:12:46 +0530248int mbedtls_mpi_mod_raw_from_mont_rep(mbedtls_mpi_uint *X,
249 const mbedtls_mpi_mod_modulus *N)
Hanno Becker5ad4a932022-08-09 14:45:53 +0100250{
Mihir Raj Singh432cacf2023-01-11 21:12:46 +0530251 const size_t t_limbs = mbedtls_mpi_core_montmul_working_limbs(N->limbs);
Minos Galanakisd9299c32022-11-01 16:19:07 +0000252 mbedtls_mpi_uint *T;
253
Gilles Peskine449bd832023-01-11 14:50:10 +0100254 if ((T = (mbedtls_mpi_uint *) mbedtls_calloc(t_limbs, ciL)) == NULL) {
255 return MBEDTLS_ERR_MPI_ALLOC_FAILED;
256 }
Minos Galanakisd9299c32022-11-01 16:19:07 +0000257
Mihir Raj Singh432cacf2023-01-11 21:12:46 +0530258 mbedtls_mpi_core_from_mont_rep(X, X, N->p, N->limbs, N->rep.mont.mm, T);
Minos Galanakisd9299c32022-11-01 16:19:07 +0000259
Tom Cosgroveca8c61b2023-07-17 15:17:40 +0100260 mbedtls_zeroize_and_free(T, t_limbs * ciL);
Gilles Peskine449bd832023-01-11 14:50:10 +0100261 return 0;
Hanno Becker5ad4a932022-08-09 14:45:53 +0100262}
Minos Galanakis21fe8bd2022-12-07 18:06:05 +0000263
Gilles Peskine449bd832023-01-11 14:50:10 +0100264void mbedtls_mpi_mod_raw_neg(mbedtls_mpi_uint *X,
265 const mbedtls_mpi_uint *A,
Mihir Raj Singh432cacf2023-01-11 21:12:46 +0530266 const mbedtls_mpi_mod_modulus *N)
Minos Galanakis21fe8bd2022-12-07 18:06:05 +0000267{
Mihir Raj Singh432cacf2023-01-11 21:12:46 +0530268 mbedtls_mpi_core_sub(X, N->p, A, N->limbs);
Minos Galanakis21fe8bd2022-12-07 18:06:05 +0000269
270 /* If A=0 initially, then X=N now. Detect this by
271 * subtracting N and catching the carry. */
Mihir Raj Singh432cacf2023-01-11 21:12:46 +0530272 mbedtls_mpi_uint borrow = mbedtls_mpi_core_sub(X, X, N->p, N->limbs);
273 (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) borrow);
Minos Galanakis21fe8bd2022-12-07 18:06:05 +0000274}
Janos Follath5933f692022-11-02 14:35:17 +0000275
Janos Follathf2334b72023-08-17 12:24:46 +0000276#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ECP_WITH_MPI_UINT */