summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/libcrypto/bn/bn_mont.c177
1 files changed, 85 insertions, 92 deletions
diff --git a/src/lib/libcrypto/bn/bn_mont.c b/src/lib/libcrypto/bn/bn_mont.c
index c368e07e22..15c9c4a00e 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.46 2023/02/22 06:00:24 jsing Exp $ */ 1/* $OpenBSD: bn_mont.c,v 1.47 2023/02/28 12:29:57 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 *
@@ -356,22 +356,22 @@ bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
356#endif /* !OPENSSL_BN_ASM_MONT */ 356#endif /* !OPENSSL_BN_ASM_MONT */
357#endif /* OPENSSL_NO_ASM */ 357#endif /* OPENSSL_NO_ASM */
358 358
359static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont); 359static int bn_montgomery_reduce(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mctx);
360 360
361int 361int
362BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, 362BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
363 BN_MONT_CTX *mont, BN_CTX *ctx) 363 BN_MONT_CTX *mctx, BN_CTX *ctx)
364{ 364{
365 BIGNUM *tmp; 365 BIGNUM *tmp;
366 int ret = 0; 366 int ret = 0;
367 367
368#if defined(OPENSSL_BN_ASM_MONT) 368#if defined(OPENSSL_BN_ASM_MONT)
369 int num = mont->N.top; 369 int num = mctx->N.top;
370 370
371 if (num > 1 && a->top == num && b->top == num) { 371 if (num > 1 && a->top == num && b->top == num) {
372 if (!bn_wexpand(r, num)) 372 if (!bn_wexpand(r, num))
373 return (0); 373 return (0);
374 if (bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num)) { 374 if (bn_mul_mont(r->d, a->d, b->d, mctx->N.d, mctx->n0, num)) {
375 r->top = num; 375 r->top = num;
376 bn_correct_top(r); 376 bn_correct_top(r);
377 BN_set_negative(r, a->neg ^ b->neg); 377 BN_set_negative(r, a->neg ^ b->neg);
@@ -381,6 +381,7 @@ BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
381#endif 381#endif
382 382
383 BN_CTX_start(ctx); 383 BN_CTX_start(ctx);
384
384 if ((tmp = BN_CTX_get(ctx)) == NULL) 385 if ((tmp = BN_CTX_get(ctx)) == NULL)
385 goto err; 386 goto err;
386 387
@@ -388,16 +389,19 @@ BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
388 if (!BN_sqr(tmp, a, ctx)) 389 if (!BN_sqr(tmp, a, ctx))
389 goto err; 390 goto err;
390 } else { 391 } else {
391 if (!BN_mul(tmp, a,b, ctx)) 392 if (!BN_mul(tmp, a, b, ctx))
392 goto err; 393 goto err;
393 } 394 }
394 /* reduce from aRR to aR */ 395
395 if (!BN_from_montgomery_word(r, tmp, mont)) 396 /* Reduce from aRR to aR. */
397 if (!bn_montgomery_reduce(r, tmp, mctx))
396 goto err; 398 goto err;
399
397 ret = 1; 400 ret = 1;
398err: 401 err:
399 BN_CTX_end(ctx); 402 BN_CTX_end(ctx);
400 return (ret); 403
404 return ret;
401} 405}
402 406
403int 407int
@@ -407,106 +411,95 @@ BN_to_montgomery(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont, BN_CTX *ctx)
407 return BN_mod_mul_montgomery(r, a, &mont->RR, mont, ctx); 411 return BN_mod_mul_montgomery(r, a, &mont->RR, mont, ctx);
408} 412}
409 413
414/*
415 * bn_montgomery_reduce() performs Montgomery reduction, reducing the input
416 * from its Montgomery form aR to a, returning the result in r. Note that the
417 * input is mutated in the process of performing the reduction, destroying its
418 * original value.
419 */
410static int 420static int
411BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont) 421bn_montgomery_reduce(BIGNUM *r, BIGNUM *a, BN_MONT_CTX *mctx)
412{ 422{
413 BIGNUM *n; 423 BIGNUM *n;
414 BN_ULONG *ap, *np, *rp, n0, v, carry; 424 BN_ULONG *ap, *rp, n0, v, carry, mask;
415 int nl, max, i; 425 int i, max, n_len;
416
417 n = &(mont->N);
418 nl = n->top;
419 if (nl == 0) {
420 ret->top = 0;
421 return (1);
422 }
423 426
424 max = (2 * nl); /* carry is stored separately */ 427 n = &mctx->N;
425 if (!bn_wexpand(r, max)) 428 n_len = mctx->N.top;
426 return (0);
427 429
428 BN_set_negative(r, r->neg ^ n->neg); 430 if (n_len == 0) {
429 np = n->d; 431 BN_zero(r);
430 rp = r->d; 432 return 1;
433 }
431 434
432 /* clear the top words of T */ 435 if (!bn_wexpand(r, n_len))
433#if 1 436 return 0;
434 for (i=r->top; i<max; i++) /* memset? XXX */ 437
435 rp[i] = 0; 438 /*
436#else 439 * Expand a to twice the length of the modulus, zero if necessary.
437 memset(&(rp[r->top]), 0, (max - r->top) * sizeof(BN_ULONG)); 440 * XXX - make this a requirement of the caller.
438#endif 441 */
442 if ((max = 2 * n_len) < n_len)
443 return 0;
444 if (!bn_wexpand(a, max))
445 return 0;
446 for (i = a->top; i < max; i++)
447 a->d[i] = 0;
439 448
440 r->top = max; 449 carry = 0;
441 n0 = mont->n0[0]; 450 n0 = mctx->n0[0];
442 451
443 for (carry = 0, i = 0; i < nl; i++, rp++) { 452 /* Add multiples of the modulus, so that it becomes divisable by R. */
444 v = bn_mul_add_words(rp, np, nl, (rp[0] * n0) & BN_MASK2); 453 for (i = 0; i < n_len; i++) {
445 v = (v + carry + rp[nl]) & BN_MASK2; 454 v = bn_mul_add_words(&a->d[i], n->d, n_len, a->d[i] * n0);
446 carry |= (v != rp[nl]); 455 bn_addw_addw(v, a->d[i + n_len], carry, &carry,
447 carry &= (v <= rp[nl]); 456 &a->d[i + n_len]);
448 rp[nl] = v;
449 } 457 }
450 458
451 if (!bn_wexpand(ret, nl)) 459 /* Divide by R (this is the equivalent of right shifting by n_len). */
452 return (0); 460 ap = &a->d[n_len];
453 ret->top = nl; 461
454 BN_set_negative(ret, r->neg); 462 /*
455 463 * The output is now in the range of [0, 2N). Attempt to reduce once by
456 rp = ret->d; 464 * subtracting the modulus. If the reduction was necessary then the
457 ap = &(r->d[nl]); 465 * result is already in r, otherwise copy the value prior to reduction
458 466 * from the top half of a.
459#define BRANCH_FREE 1 467 */
460#if BRANCH_FREE 468 mask = carry - bn_sub_words(r->d, ap, n->d, n_len);
461 { 469
462 BN_ULONG *nrp; 470 rp = r->d;
463 size_t m; 471 for (i = 0; i < n_len; i++) {
464 472 *rp = (*rp & ~mask) | (*ap & mask);
465 v = bn_sub_words(rp, ap, np, nl) - carry; 473 rp++;
466 /* if subtraction result is real, then 474 ap++;
467 * trick unconditional memcpy below to perform in-place
468 * "refresh" instead of actual copy. */
469 m = (0 - (size_t)v);
470 nrp = (BN_ULONG *)(((uintptr_t)rp & ~m)|((uintptr_t)ap & m));
471
472 for (i = 0, nl -= 4; i < nl; i += 4) {
473 BN_ULONG t1, t2, t3, t4;
474
475 t1 = nrp[i + 0];
476 t2 = nrp[i + 1];
477 t3 = nrp[i + 2];
478 ap[i + 0] = 0;
479 t4 = nrp[i + 3];
480 ap[i + 1] = 0;
481 rp[i + 0] = t1;
482 ap[i + 2] = 0;
483 rp[i + 1] = t2;
484 ap[i + 3] = 0;
485 rp[i + 2] = t3;
486 rp[i + 3] = t4;
487 }
488 for (nl += 4; i < nl; i++)
489 rp[i] = nrp[i], ap[i] = 0;
490 } 475 }
491#else 476 r->top = n_len;
492 if (bn_sub_words (rp, ap, np, nl) - carry) 477
493 memcpy(rp, ap, nl*sizeof(BN_ULONG));
494#endif
495 bn_correct_top(r); 478 bn_correct_top(r);
496 bn_correct_top(ret);
497 479
498 return (1); 480 BN_set_negative(r, a->neg ^ n->neg);
481
482 return 1;
499} 483}
500 484
501int 485int
502BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont, BN_CTX *ctx) 486BN_from_montgomery(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mctx, BN_CTX *ctx)
503{ 487{
504 int retn = 0; 488 BIGNUM *tmp;
505 BIGNUM *t; 489 int ret = 0;
506 490
507 BN_CTX_start(ctx); 491 BN_CTX_start(ctx);
508 if ((t = BN_CTX_get(ctx)) && BN_copy(t, a)) 492
509 retn = BN_from_montgomery_word(ret, t, mont); 493 if ((tmp = BN_CTX_get(ctx)) == NULL)
494 goto err;
495 if (BN_copy(tmp, a) == NULL)
496 goto err;
497 if (!bn_montgomery_reduce(r, tmp, mctx))
498 goto err;
499
500 ret = 1;
501 err:
510 BN_CTX_end(ctx); 502 BN_CTX_end(ctx);
511 return (retn); 503
504 return ret;
512} 505}