diff options
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 | } |