diff options
| author | djm <> | 2008-09-06 12:17:54 +0000 |
|---|---|---|
| committer | djm <> | 2008-09-06 12:17:54 +0000 |
| commit | 6b62d1fdd8a4fd35acfcc0c4bb1bf8b757fa8cda (patch) | |
| tree | 7ccc28afe1789ea3dbedf72365f955d5b8e105b5 /src/lib/libcrypto/bn/bn_gcd.c | |
| parent | 89181603212b41e95cde36b1be5a146ce8fb2935 (diff) | |
| download | openbsd-6b62d1fdd8a4fd35acfcc0c4bb1bf8b757fa8cda.tar.gz openbsd-6b62d1fdd8a4fd35acfcc0c4bb1bf8b757fa8cda.tar.bz2 openbsd-6b62d1fdd8a4fd35acfcc0c4bb1bf8b757fa8cda.zip | |
resolve conflicts
Diffstat (limited to 'src/lib/libcrypto/bn/bn_gcd.c')
| -rw-r--r-- | src/lib/libcrypto/bn/bn_gcd.c | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/src/lib/libcrypto/bn/bn_gcd.c b/src/lib/libcrypto/bn/bn_gcd.c index 7649f63fd2..4a352119ba 100644 --- a/src/lib/libcrypto/bn/bn_gcd.c +++ b/src/lib/libcrypto/bn/bn_gcd.c | |||
| @@ -140,6 +140,7 @@ int BN_gcd(BIGNUM *r, const BIGNUM *in_a, const BIGNUM *in_b, BN_CTX *ctx) | |||
| 140 | ret=1; | 140 | ret=1; |
| 141 | err: | 141 | err: |
| 142 | BN_CTX_end(ctx); | 142 | BN_CTX_end(ctx); |
| 143 | bn_check_top(r); | ||
| 143 | return(ret); | 144 | return(ret); |
| 144 | } | 145 | } |
| 145 | 146 | ||
| @@ -194,6 +195,7 @@ static BIGNUM *euclid(BIGNUM *a, BIGNUM *b) | |||
| 194 | { | 195 | { |
| 195 | if (!BN_lshift(a,a,shifts)) goto err; | 196 | if (!BN_lshift(a,a,shifts)) goto err; |
| 196 | } | 197 | } |
| 198 | bn_check_top(a); | ||
| 197 | return(a); | 199 | return(a); |
| 198 | err: | 200 | err: |
| 199 | return(NULL); | 201 | return(NULL); |
| @@ -201,6 +203,8 @@ err: | |||
| 201 | 203 | ||
| 202 | 204 | ||
| 203 | /* solves ax == 1 (mod n) */ | 205 | /* solves ax == 1 (mod n) */ |
| 206 | static BIGNUM *BN_mod_inverse_no_branch(BIGNUM *in, | ||
| 207 | const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx); | ||
| 204 | BIGNUM *BN_mod_inverse(BIGNUM *in, | 208 | BIGNUM *BN_mod_inverse(BIGNUM *in, |
| 205 | const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx) | 209 | const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx) |
| 206 | { | 210 | { |
| @@ -208,6 +212,11 @@ BIGNUM *BN_mod_inverse(BIGNUM *in, | |||
| 208 | BIGNUM *ret=NULL; | 212 | BIGNUM *ret=NULL; |
| 209 | int sign; | 213 | int sign; |
| 210 | 214 | ||
| 215 | if ((BN_get_flags(a, BN_FLG_CONSTTIME) != 0) || (BN_get_flags(n, BN_FLG_CONSTTIME) != 0)) | ||
| 216 | { | ||
| 217 | return BN_mod_inverse_no_branch(in, a, n, ctx); | ||
| 218 | } | ||
| 219 | |||
| 211 | bn_check_top(a); | 220 | bn_check_top(a); |
| 212 | bn_check_top(n); | 221 | bn_check_top(n); |
| 213 | 222 | ||
| @@ -486,5 +495,160 @@ BIGNUM *BN_mod_inverse(BIGNUM *in, | |||
| 486 | err: | 495 | err: |
| 487 | if ((ret == NULL) && (in == NULL)) BN_free(R); | 496 | if ((ret == NULL) && (in == NULL)) BN_free(R); |
| 488 | BN_CTX_end(ctx); | 497 | BN_CTX_end(ctx); |
| 498 | bn_check_top(ret); | ||
| 499 | return(ret); | ||
| 500 | } | ||
| 501 | |||
| 502 | |||
| 503 | /* BN_mod_inverse_no_branch is a special version of BN_mod_inverse. | ||
| 504 | * It does not contain branches that may leak sensitive information. | ||
| 505 | */ | ||
| 506 | static BIGNUM *BN_mod_inverse_no_branch(BIGNUM *in, | ||
| 507 | const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx) | ||
| 508 | { | ||
| 509 | BIGNUM *A,*B,*X,*Y,*M,*D,*T,*R=NULL; | ||
| 510 | BIGNUM local_A, local_B; | ||
| 511 | BIGNUM *pA, *pB; | ||
| 512 | BIGNUM *ret=NULL; | ||
| 513 | int sign; | ||
| 514 | |||
| 515 | bn_check_top(a); | ||
| 516 | bn_check_top(n); | ||
| 517 | |||
| 518 | BN_CTX_start(ctx); | ||
| 519 | A = BN_CTX_get(ctx); | ||
| 520 | B = BN_CTX_get(ctx); | ||
| 521 | X = BN_CTX_get(ctx); | ||
| 522 | D = BN_CTX_get(ctx); | ||
| 523 | M = BN_CTX_get(ctx); | ||
| 524 | Y = BN_CTX_get(ctx); | ||
| 525 | T = BN_CTX_get(ctx); | ||
| 526 | if (T == NULL) goto err; | ||
| 527 | |||
| 528 | if (in == NULL) | ||
| 529 | R=BN_new(); | ||
| 530 | else | ||
| 531 | R=in; | ||
| 532 | if (R == NULL) goto err; | ||
| 533 | |||
| 534 | BN_one(X); | ||
| 535 | BN_zero(Y); | ||
| 536 | if (BN_copy(B,a) == NULL) goto err; | ||
| 537 | if (BN_copy(A,n) == NULL) goto err; | ||
| 538 | A->neg = 0; | ||
| 539 | |||
| 540 | if (B->neg || (BN_ucmp(B, A) >= 0)) | ||
| 541 | { | ||
| 542 | /* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked, | ||
| 543 | * BN_div_no_branch will be called eventually. | ||
| 544 | */ | ||
| 545 | pB = &local_B; | ||
| 546 | BN_with_flags(pB, B, BN_FLG_CONSTTIME); | ||
| 547 | if (!BN_nnmod(B, pB, A, ctx)) goto err; | ||
| 548 | } | ||
| 549 | sign = -1; | ||
| 550 | /* From B = a mod |n|, A = |n| it follows that | ||
| 551 | * | ||
| 552 | * 0 <= B < A, | ||
| 553 | * -sign*X*a == B (mod |n|), | ||
| 554 | * sign*Y*a == A (mod |n|). | ||
| 555 | */ | ||
| 556 | |||
| 557 | while (!BN_is_zero(B)) | ||
| 558 | { | ||
| 559 | BIGNUM *tmp; | ||
| 560 | |||
| 561 | /* | ||
| 562 | * 0 < B < A, | ||
| 563 | * (*) -sign*X*a == B (mod |n|), | ||
| 564 | * sign*Y*a == A (mod |n|) | ||
| 565 | */ | ||
| 566 | |||
| 567 | /* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked, | ||
| 568 | * BN_div_no_branch will be called eventually. | ||
| 569 | */ | ||
| 570 | pA = &local_A; | ||
| 571 | BN_with_flags(pA, A, BN_FLG_CONSTTIME); | ||
| 572 | |||
| 573 | /* (D, M) := (A/B, A%B) ... */ | ||
| 574 | if (!BN_div(D,M,pA,B,ctx)) goto err; | ||
| 575 | |||
| 576 | /* Now | ||
| 577 | * A = D*B + M; | ||
| 578 | * thus we have | ||
| 579 | * (**) sign*Y*a == D*B + M (mod |n|). | ||
| 580 | */ | ||
| 581 | |||
| 582 | tmp=A; /* keep the BIGNUM object, the value does not matter */ | ||
| 583 | |||
| 584 | /* (A, B) := (B, A mod B) ... */ | ||
| 585 | A=B; | ||
| 586 | B=M; | ||
| 587 | /* ... so we have 0 <= B < A again */ | ||
| 588 | |||
| 589 | /* Since the former M is now B and the former B is now A, | ||
| 590 | * (**) translates into | ||
| 591 | * sign*Y*a == D*A + B (mod |n|), | ||
| 592 | * i.e. | ||
| 593 | * sign*Y*a - D*A == B (mod |n|). | ||
| 594 | * Similarly, (*) translates into | ||
| 595 | * -sign*X*a == A (mod |n|). | ||
| 596 | * | ||
| 597 | * Thus, | ||
| 598 | * sign*Y*a + D*sign*X*a == B (mod |n|), | ||
| 599 | * i.e. | ||
| 600 | * sign*(Y + D*X)*a == B (mod |n|). | ||
| 601 | * | ||
| 602 | * So if we set (X, Y, sign) := (Y + D*X, X, -sign), we arrive back at | ||
| 603 | * -sign*X*a == B (mod |n|), | ||
| 604 | * sign*Y*a == A (mod |n|). | ||
| 605 | * Note that X and Y stay non-negative all the time. | ||
| 606 | */ | ||
| 607 | |||
| 608 | if (!BN_mul(tmp,D,X,ctx)) goto err; | ||
| 609 | if (!BN_add(tmp,tmp,Y)) goto err; | ||
| 610 | |||
| 611 | M=Y; /* keep the BIGNUM object, the value does not matter */ | ||
| 612 | Y=X; | ||
| 613 | X=tmp; | ||
| 614 | sign = -sign; | ||
| 615 | } | ||
| 616 | |||
| 617 | /* | ||
| 618 | * The while loop (Euclid's algorithm) ends when | ||
| 619 | * A == gcd(a,n); | ||
| 620 | * we have | ||
| 621 | * sign*Y*a == A (mod |n|), | ||
| 622 | * where Y is non-negative. | ||
| 623 | */ | ||
| 624 | |||
| 625 | if (sign < 0) | ||
| 626 | { | ||
| 627 | if (!BN_sub(Y,n,Y)) goto err; | ||
| 628 | } | ||
| 629 | /* Now Y*a == A (mod |n|). */ | ||
| 630 | |||
| 631 | if (BN_is_one(A)) | ||
| 632 | { | ||
| 633 | /* Y*a == 1 (mod |n|) */ | ||
| 634 | if (!Y->neg && BN_ucmp(Y,n) < 0) | ||
| 635 | { | ||
| 636 | if (!BN_copy(R,Y)) goto err; | ||
| 637 | } | ||
| 638 | else | ||
| 639 | { | ||
| 640 | if (!BN_nnmod(R,Y,n,ctx)) goto err; | ||
| 641 | } | ||
| 642 | } | ||
| 643 | else | ||
| 644 | { | ||
| 645 | BNerr(BN_F_BN_MOD_INVERSE_NO_BRANCH,BN_R_NO_INVERSE); | ||
| 646 | goto err; | ||
| 647 | } | ||
| 648 | ret=R; | ||
| 649 | err: | ||
| 650 | if ((ret == NULL) && (in == NULL)) BN_free(R); | ||
| 651 | BN_CTX_end(ctx); | ||
| 652 | bn_check_top(ret); | ||
| 489 | return(ret); | 653 | return(ret); |
| 490 | } | 654 | } |
