summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/bn/bn_mont.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/bn/bn_mont.c')
-rw-r--r--src/lib/libcrypto/bn/bn_mont.c78
1 files changed, 46 insertions, 32 deletions
diff --git a/src/lib/libcrypto/bn/bn_mont.c b/src/lib/libcrypto/bn/bn_mont.c
index edd7bcd0c8..8280a8db27 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.66 2025/03/09 15:22:40 tb Exp $ */ 1/* $OpenBSD: bn_mont.c,v 1.69 2025/08/03 10:33:46 tb 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 *
@@ -116,6 +116,7 @@
116 * sections 3.8 and 4.2 in http://security.ece.orst.edu/koc/papers/r01rsasw.pdf 116 * sections 3.8 and 4.2 in http://security.ece.orst.edu/koc/papers/r01rsasw.pdf
117 */ 117 */
118 118
119#include <limits.h>
119#include <stdio.h> 120#include <stdio.h>
120#include <stdint.h> 121#include <stdint.h>
121#include <string.h> 122#include <string.h>
@@ -214,7 +215,7 @@ BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx)
214 goto err; 215 goto err;
215 mont->N.neg = 0; 216 mont->N.neg = 0;
216 mont->ri = ((BN_num_bits(mod) + BN_BITS2 - 1) / BN_BITS2) * BN_BITS2; 217 mont->ri = ((BN_num_bits(mod) + BN_BITS2 - 1) / BN_BITS2) * BN_BITS2;
217 if (mont->ri * 2 < mont->ri) 218 if (mont->ri > INT_MAX / 2)
218 goto err; 219 goto err;
219 220
220 /* 221 /*
@@ -316,6 +317,44 @@ BN_MONT_CTX_set_locked(BN_MONT_CTX **pmctx, int lock, const BIGNUM *mod,
316LCRYPTO_ALIAS(BN_MONT_CTX_set_locked); 317LCRYPTO_ALIAS(BN_MONT_CTX_set_locked);
317 318
318/* 319/*
320 * bn_montgomery_reduce_words() performs Montgomery reduction, reducing the input
321 * from its Montgomery form aR to a, returning the result in r. a must be twice
322 * the length of the modulus. Note that the input is mutated in the process of
323 * performing the reduction.
324 */
325void
326bn_montgomery_reduce_words(BN_ULONG *r, BN_ULONG *a, const BN_ULONG *n,
327 BN_ULONG n0, int n_len)
328{
329 BN_ULONG v, mask;
330 BN_ULONG carry = 0;
331 int i;
332
333 /* Add multiples of the modulus, so that it becomes divisible by R. */
334 for (i = 0; i < n_len; i++) {
335 v = bn_mul_add_words(&a[i], n, n_len, a[i] * n0);
336 bn_addw_addw(v, a[i + n_len], carry, &carry, &a[i + n_len]);
337 }
338
339 /* Divide by R (this is the equivalent of right shifting by n_len). */
340 a = &a[n_len];
341
342 /*
343 * The output is now in the range of [0, 2N). Attempt to reduce once by
344 * subtracting the modulus. If the reduction was necessary then the
345 * result is already in r, otherwise copy the value prior to reduction
346 * from the top half of a.
347 */
348 mask = carry - bn_sub_words(r, a, n, n_len);
349
350 for (i = 0; i < n_len; i++) {
351 *r = (*r & ~mask) | (*a & mask);
352 r++;
353 a++;
354 }
355}
356
357/*
319 * bn_montgomery_reduce() performs Montgomery reduction, reducing the input 358 * bn_montgomery_reduce() performs Montgomery reduction, reducing the input
320 * from its Montgomery form aR to a, returning the result in r. Note that the 359 * from its Montgomery form aR to a, returning the result in r. Note that the
321 * input is mutated in the process of performing the reduction, destroying its 360 * input is mutated in the process of performing the reduction, destroying its
@@ -325,7 +364,6 @@ static int
325bn_montgomery_reduce(BIGNUM *r, BIGNUM *a, BN_MONT_CTX *mctx) 364bn_montgomery_reduce(BIGNUM *r, BIGNUM *a, BN_MONT_CTX *mctx)
326{ 365{
327 BIGNUM *n; 366 BIGNUM *n;
328 BN_ULONG *ap, *rp, n0, v, carry, mask;
329 int i, max, n_len; 367 int i, max, n_len;
330 368
331 n = &mctx->N; 369 n = &mctx->N;
@@ -341,7 +379,8 @@ bn_montgomery_reduce(BIGNUM *r, BIGNUM *a, BN_MONT_CTX *mctx)
341 379
342 /* 380 /*
343 * Expand a to twice the length of the modulus, zero if necessary. 381 * Expand a to twice the length of the modulus, zero if necessary.
344 * XXX - make this a requirement of the caller. 382 * XXX - make this a requirement of the caller or use a temporary
383 * allocation.
345 */ 384 */
346 if ((max = 2 * n_len) < n_len) 385 if ((max = 2 * n_len) < n_len)
347 return 0; 386 return 0;
@@ -350,33 +389,8 @@ bn_montgomery_reduce(BIGNUM *r, BIGNUM *a, BN_MONT_CTX *mctx)
350 for (i = a->top; i < max; i++) 389 for (i = a->top; i < max; i++)
351 a->d[i] = 0; 390 a->d[i] = 0;
352 391
353 carry = 0; 392 bn_montgomery_reduce_words(r->d, a->d, n->d, mctx->n0[0], n_len);
354 n0 = mctx->n0[0];
355 393
356 /* Add multiples of the modulus, so that it becomes divisible by R. */
357 for (i = 0; i < n_len; i++) {
358 v = bn_mul_add_words(&a->d[i], n->d, n_len, a->d[i] * n0);
359 bn_addw_addw(v, a->d[i + n_len], carry, &carry,
360 &a->d[i + n_len]);
361 }
362
363 /* Divide by R (this is the equivalent of right shifting by n_len). */
364 ap = &a->d[n_len];
365
366 /*
367 * The output is now in the range of [0, 2N). Attempt to reduce once by
368 * subtracting the modulus. If the reduction was necessary then the
369 * result is already in r, otherwise copy the value prior to reduction
370 * from the top half of a.
371 */
372 mask = carry - bn_sub_words(r->d, ap, n->d, n_len);
373
374 rp = r->d;
375 for (i = 0; i < n_len; i++) {
376 *rp = (*rp & ~mask) | (*ap & mask);
377 rp++;
378 ap++;
379 }
380 r->top = n_len; 394 r->top = n_len;
381 395
382 bn_correct_top(r); 396 bn_correct_top(r);
@@ -417,7 +431,7 @@ bn_mod_mul_montgomery_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
417 return ret; 431 return ret;
418} 432}
419 433
420static void 434static inline void
421bn_montgomery_multiply_word(const BN_ULONG *ap, BN_ULONG b, const BN_ULONG *np, 435bn_montgomery_multiply_word(const BN_ULONG *ap, BN_ULONG b, const BN_ULONG *np,
422 BN_ULONG *tp, BN_ULONG w, BN_ULONG *carry_a, BN_ULONG *carry_n, int n_len) 436 BN_ULONG *tp, BN_ULONG w, BN_ULONG *carry_a, BN_ULONG *carry_n, int n_len)
423{ 437{
@@ -452,7 +466,7 @@ bn_montgomery_multiply_word(const BN_ULONG *ap, BN_ULONG b, const BN_ULONG *np,
452 * given word arrays. The caller must ensure that rp, ap, bp and np are all 466 * given word arrays. The caller must ensure that rp, ap, bp and np are all
453 * n_len words in length, while tp must be n_len * 2 + 2 words in length. 467 * n_len words in length, while tp must be n_len * 2 + 2 words in length.
454 */ 468 */
455static void 469void
456bn_montgomery_multiply_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, 470bn_montgomery_multiply_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
457 const BN_ULONG *np, BN_ULONG *tp, BN_ULONG n0, int n_len) 471 const BN_ULONG *np, BN_ULONG *tp, BN_ULONG n0, int n_len)
458{ 472{