summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/libcrypto/bn/bn_local.h15
-rw-r--r--src/lib/libcrypto/bn/bn_mont.c159
2 files changed, 76 insertions, 98 deletions
diff --git a/src/lib/libcrypto/bn/bn_local.h b/src/lib/libcrypto/bn/bn_local.h
index c763890695..35e9073e2d 100644
--- a/src/lib/libcrypto/bn/bn_local.h
+++ b/src/lib/libcrypto/bn/bn_local.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: bn_local.h,v 1.14 2023/02/21 05:58:08 jsing Exp $ */ 1/* $OpenBSD: bn_local.h,v 1.15 2023/02/22 05:25:47 jsing Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -127,13 +127,14 @@ struct bignum_st {
127 int flags; 127 int flags;
128}; 128};
129 129
130/* Used for montgomery multiplication */
131struct bn_mont_ctx_st { 130struct bn_mont_ctx_st {
132 int ri; /* number of bits in R */ 131 int ri; /* Number of bits in R */
133 BIGNUM RR; /* used to convert to montgomery form */ 132 BIGNUM RR; /* Used to convert to Montgomery form */
134 BIGNUM N; /* The modulus */ 133 BIGNUM N; /* Modulus */
135 BN_ULONG n0[2];/* least significant word(s) of Ni; R*(1/R mod N) - N*Ni = 1 134
136 (type changed with 0.9.9, was "BN_ULONG n0;" before) */ 135 /* Least significant word(s) of Ni; R*(1/R mod N) - N*Ni = 1 */
136 BN_ULONG n0[2];
137
137 int flags; 138 int flags;
138}; 139};
139 140
diff --git a/src/lib/libcrypto/bn/bn_mont.c b/src/lib/libcrypto/bn/bn_mont.c
index a54355ca37..559811b975 100644
--- a/src/lib/libcrypto/bn/bn_mont.c
+++ b/src/lib/libcrypto/bn/bn_mont.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: bn_mont.c,v 1.44 2023/02/21 12:20:22 bcook Exp $ */ 1/* $OpenBSD: bn_mont.c,v 1.45 2023/02/22 05:25:47 jsing Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -120,6 +120,7 @@
120#include <stdint.h> 120#include <stdint.h>
121#include <string.h> 121#include <string.h>
122 122
123#include "bn_internal.h"
123#include "bn_local.h" 124#include "bn_local.h"
124 125
125BN_MONT_CTX * 126BN_MONT_CTX *
@@ -180,114 +181,89 @@ BN_MONT_CTX_copy(BN_MONT_CTX *dst, BN_MONT_CTX *src)
180int 181int
181BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) 182BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx)
182{ 183{
184 BIGNUM *N, *Ninv, *Rinv, *R;
183 int ret = 0; 185 int ret = 0;
184 BIGNUM *Ri, *R;
185
186 if (BN_is_zero(mod))
187 return 0;
188 186
189 BN_CTX_start(ctx); 187 BN_CTX_start(ctx);
190 if ((Ri = BN_CTX_get(ctx)) == NULL) 188
189 if ((N = BN_CTX_get(ctx)) == NULL)
190 goto err;
191 if ((Ninv = BN_CTX_get(ctx)) == NULL)
192 goto err;
193 if ((R = BN_CTX_get(ctx)) == NULL)
194 goto err;
195 if ((Rinv = BN_CTX_get(ctx)) == NULL)
191 goto err; 196 goto err;
192 R = &(mont->RR); /* grab RR as a temp */
193 if (!BN_copy(&(mont->N), mod))
194 goto err; /* Set N */
195 mont->N.neg = 0;
196 197
197 { 198 /* Save modulus and determine length of R. */
198 BIGNUM tmod; 199 if (BN_is_zero(mod))
199 BN_ULONG buf[2]; 200 goto err;
201 if (!BN_copy(&mont->N, mod))
202 goto err;
203 mont->N.neg = 0;
204 mont->ri = (BN_num_bits(mod) + (BN_BITS2 - 1)) / BN_BITS2 * BN_BITS2;
205 if (mont->ri * 2 < mont->ri)
206 goto err;
200 207
201 BN_init(&tmod); 208 /*
202 tmod.d = buf; 209 * Compute Ninv = (R * Rinv - 1)/N mod R, for R = 2^64. This provides
203 tmod.dmax = 2; 210 * a single or double word result (dependent on BN word size), that is
204 tmod.neg = 0; 211 * later used to implement Montgomery reduction.
212 */
213 BN_zero(R);
214 if (!BN_set_bit(R, 64))
215 goto err;
205 216
206 mont->ri = (BN_num_bits(mod) + 217 /* N = N mod R. */
207 (BN_BITS2 - 1)) / BN_BITS2 * BN_BITS2; 218 if (!bn_wexpand(N, 2))
219 goto err;
220 if (!BN_set_word(N, mod->d[0]))
221 goto err;
222#if BN_BITS2 == 32
223 if (mod->top > 1) {
224 N->d[1] = mod->d[1];
225 N->top += bn_ct_ne_zero(N->d[1]);
226 }
227#endif
208 228
209#if defined(OPENSSL_BN_ASM_MONT) && (BN_BITS2<=32) 229 /* Rinv = R^-1 mod N */
210 /* Only certain BN_BITS2<=32 platforms actually make use of 230 if ((BN_mod_inverse_ct(Rinv, R, N, ctx)) == NULL)
211 * n0[1], and we could use the #else case (with a shorter R 231 goto err;
212 * value) for the others. However, currently only the assembler
213 * files do know which is which. */
214 232
215 BN_zero(R); 233 /* Ninv = (R * Rinv - 1) / N */
216 if (!(BN_set_bit(R, 2 * BN_BITS2))) 234 if (!BN_lshift(Ninv, Rinv, 64))
235 goto err;
236 if (BN_is_zero(Ninv)) {
237 /* R * Rinv == 0, set to R so that R * Rinv - 1 is mod R. */
238 if (!BN_set_bit(Ninv, 64))
217 goto err; 239 goto err;
240 }
241 if (!BN_sub_word(Ninv, 1))
242 goto err;
243 if (!BN_div_ct(Ninv, NULL, Ninv, N, ctx))
244 goto err;
218 245
219 tmod.top = 0; 246 /* Store least significant word(s) of Ninv. */
220 if ((buf[0] = mod->d[0])) 247 mont->n0[0] = mont->n0[1] = 0;
221 tmod.top = 1; 248 if (Ninv->top > 0)
222 if ((buf[1] = mod->top > 1 ? mod->d[1] : 0)) 249 mont->n0[0] = Ninv->d[0];
223 tmod.top = 2; 250#if BN_BITS2 == 32
224 251 /* Some BN_BITS2 == 32 platforms (namely parisc) use two words of Ninv. */
225 if ((BN_mod_inverse_ct(Ri, R, &tmod, ctx)) == NULL) 252 if (Ninv->top > 1)
226 goto err; 253 mont->n0[1] = Ninv->d[1];
227 if (!BN_lshift(Ri, Ri, 2 * BN_BITS2))
228 goto err; /* R*Ri */
229 if (!BN_is_zero(Ri)) {
230 if (!BN_sub_word(Ri, 1))
231 goto err;
232 }
233 else /* if N mod word size == 1 */
234 {
235 if (!bn_wexpand(Ri, 2))
236 goto err;
237 /* Ri-- (mod double word size) */
238 Ri->neg = 0;
239 Ri->d[0] = BN_MASK2;
240 Ri->d[1] = BN_MASK2;
241 Ri->top = 2;
242 }
243 if (!BN_div_ct(Ri, NULL, Ri, &tmod, ctx))
244 goto err;
245 /* Ni = (R*Ri-1)/N,
246 * keep only couple of least significant words: */
247 mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0;
248 mont->n0[1] = (Ri->top > 1) ? Ri->d[1] : 0;
249#else
250 BN_zero(R);
251 if (!(BN_set_bit(R, BN_BITS2)))
252 goto err; /* R */
253
254 buf[0] = mod->d[0]; /* tmod = N mod word size */
255 buf[1] = 0;
256 tmod.top = buf[0] != 0 ? 1 : 0;
257 /* Ri = R^-1 mod N*/
258 if ((BN_mod_inverse_ct(Ri, R, &tmod, ctx)) == NULL)
259 goto err;
260 if (!BN_lshift(Ri, Ri, BN_BITS2))
261 goto err; /* R*Ri */
262 if (!BN_is_zero(Ri)) {
263 if (!BN_sub_word(Ri, 1))
264 goto err;
265 }
266 else /* if N mod word size == 1 */
267 {
268 if (!BN_set_word(Ri, BN_MASK2))
269 goto err; /* Ri-- (mod word size) */
270 }
271 if (!BN_div_ct(Ri, NULL, Ri, &tmod, ctx))
272 goto err;
273 /* Ni = (R*Ri-1)/N,
274 * keep only least significant word: */
275 mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0;
276 mont->n0[1] = 0;
277#endif 254#endif
278 }
279 255
280 /* setup RR for conversions */ 256 /* Compute RR = R * R mod N, for use when converting to Montgomery form. */
281 BN_zero(&(mont->RR)); 257 BN_zero(&mont->RR);
282 if (!BN_set_bit(&(mont->RR), mont->ri*2)) 258 if (!BN_set_bit(&mont->RR, mont->ri * 2))
283 goto err; 259 goto err;
284 if (!BN_mod_ct(&(mont->RR), &(mont->RR), &(mont->N), ctx)) 260 if (!BN_mod_ct(&mont->RR, &mont->RR, &mont->N, ctx))
285 goto err; 261 goto err;
286 262
287 ret = 1; 263 ret = 1;
288 264 err:
289err:
290 BN_CTX_end(ctx); 265 BN_CTX_end(ctx);
266
291 return ret; 267 return ret;
292} 268}
293 269
@@ -427,6 +403,7 @@ err:
427int 403int
428BN_to_montgomery(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont, BN_CTX *ctx) 404BN_to_montgomery(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont, BN_CTX *ctx)
429{ 405{
406 /* Compute r = a * R * R * R^-1 mod N = aR mod N */
430 return BN_mod_mul_montgomery(r, a, &mont->RR, mont, ctx); 407 return BN_mod_mul_montgomery(r, a, &mont->RR, mont, ctx);
431} 408}
432 409