diff options
Diffstat (limited to 'src/lib/libcrypto/bn/bn_gcd.c')
-rw-r--r-- | src/lib/libcrypto/bn/bn_gcd.c | 158 |
1 files changed, 157 insertions, 1 deletions
diff --git a/src/lib/libcrypto/bn/bn_gcd.c b/src/lib/libcrypto/bn/bn_gcd.c index 30896e4763..e2574c3304 100644 --- a/src/lib/libcrypto/bn/bn_gcd.c +++ b/src/lib/libcrypto/bn/bn_gcd.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: bn_gcd.c,v 1.13 2017/01/21 23:02:53 beck Exp $ */ | 1 | /* $OpenBSD: bn_gcd.c,v 1.14 2017/01/25 06:15:44 beck 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 | * |
@@ -114,6 +114,8 @@ | |||
114 | #include "bn_lcl.h" | 114 | #include "bn_lcl.h" |
115 | 115 | ||
116 | static BIGNUM *euclid(BIGNUM *a, BIGNUM *b); | 116 | static BIGNUM *euclid(BIGNUM *a, BIGNUM *b); |
117 | static BIGNUM *BN_gcd_no_branch(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, | ||
118 | BN_CTX *ctx); | ||
117 | 119 | ||
118 | int | 120 | int |
119 | BN_gcd(BIGNUM *r, const BIGNUM *in_a, const BIGNUM *in_b, BN_CTX *ctx) | 121 | BN_gcd(BIGNUM *r, const BIGNUM *in_a, const BIGNUM *in_b, BN_CTX *ctx) |
@@ -156,6 +158,21 @@ err: | |||
156 | return (ret); | 158 | return (ret); |
157 | } | 159 | } |
158 | 160 | ||
161 | int | ||
162 | BN_gcd_ct(BIGNUM *r, const BIGNUM *in_a, const BIGNUM *in_b, BN_CTX *ctx) | ||
163 | { | ||
164 | if (BN_gcd_no_branch(r, in_a, in_b, ctx) == NULL) | ||
165 | return 0; | ||
166 | return 1; | ||
167 | } | ||
168 | |||
169 | int | ||
170 | BN_gcd_nonct(BIGNUM *r, const BIGNUM *in_a, const BIGNUM *in_b, BN_CTX *ctx) | ||
171 | { | ||
172 | return BN_gcd(r, in_a, in_b, ctx); | ||
173 | } | ||
174 | |||
175 | |||
159 | static BIGNUM * | 176 | static BIGNUM * |
160 | euclid(BIGNUM *a, BIGNUM *b) | 177 | euclid(BIGNUM *a, BIGNUM *b) |
161 | { | 178 | { |
@@ -704,3 +721,142 @@ err: | |||
704 | bn_check_top(ret); | 721 | bn_check_top(ret); |
705 | return (ret); | 722 | return (ret); |
706 | } | 723 | } |
724 | |||
725 | /* | ||
726 | * BN_gcd_no_branch is a special version of BN_mod_inverse_no_branch. | ||
727 | * that returns the GCD. | ||
728 | */ | ||
729 | static BIGNUM * | ||
730 | BN_gcd_no_branch(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, | ||
731 | BN_CTX *ctx) | ||
732 | { | ||
733 | BIGNUM *A, *B, *X, *Y, *M, *D, *T, *R = NULL; | ||
734 | BIGNUM local_A, local_B; | ||
735 | BIGNUM *pA, *pB; | ||
736 | BIGNUM *ret = NULL; | ||
737 | int sign; | ||
738 | |||
739 | if (in == NULL) | ||
740 | goto err; | ||
741 | R = in; | ||
742 | |||
743 | bn_check_top(a); | ||
744 | bn_check_top(n); | ||
745 | |||
746 | BN_CTX_start(ctx); | ||
747 | if ((A = BN_CTX_get(ctx)) == NULL) | ||
748 | goto err; | ||
749 | if ((B = BN_CTX_get(ctx)) == NULL) | ||
750 | goto err; | ||
751 | if ((X = BN_CTX_get(ctx)) == NULL) | ||
752 | goto err; | ||
753 | if ((D = BN_CTX_get(ctx)) == NULL) | ||
754 | goto err; | ||
755 | if ((M = BN_CTX_get(ctx)) == NULL) | ||
756 | goto err; | ||
757 | if ((Y = BN_CTX_get(ctx)) == NULL) | ||
758 | goto err; | ||
759 | if ((T = BN_CTX_get(ctx)) == NULL) | ||
760 | goto err; | ||
761 | |||
762 | BN_one(X); | ||
763 | BN_zero(Y); | ||
764 | if (BN_copy(B, a) == NULL) | ||
765 | goto err; | ||
766 | if (BN_copy(A, n) == NULL) | ||
767 | goto err; | ||
768 | A->neg = 0; | ||
769 | |||
770 | if (B->neg || (BN_ucmp(B, A) >= 0)) { | ||
771 | /* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked, | ||
772 | * BN_div_no_branch will be called eventually. | ||
773 | */ | ||
774 | pB = &local_B; | ||
775 | BN_with_flags(pB, B, BN_FLG_CONSTTIME); | ||
776 | if (!BN_nnmod(B, pB, A, ctx)) | ||
777 | goto err; | ||
778 | } | ||
779 | sign = -1; | ||
780 | /* From B = a mod |n|, A = |n| it follows that | ||
781 | * | ||
782 | * 0 <= B < A, | ||
783 | * -sign*X*a == B (mod |n|), | ||
784 | * sign*Y*a == A (mod |n|). | ||
785 | */ | ||
786 | |||
787 | while (!BN_is_zero(B)) { | ||
788 | BIGNUM *tmp; | ||
789 | |||
790 | /* | ||
791 | * 0 < B < A, | ||
792 | * (*) -sign*X*a == B (mod |n|), | ||
793 | * sign*Y*a == A (mod |n|) | ||
794 | */ | ||
795 | |||
796 | /* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked, | ||
797 | * BN_div_no_branch will be called eventually. | ||
798 | */ | ||
799 | pA = &local_A; | ||
800 | BN_with_flags(pA, A, BN_FLG_CONSTTIME); | ||
801 | |||
802 | /* (D, M) := (A/B, A%B) ... */ | ||
803 | if (!BN_div_ct(D, M, pA, B, ctx)) | ||
804 | goto err; | ||
805 | |||
806 | /* Now | ||
807 | * A = D*B + M; | ||
808 | * thus we have | ||
809 | * (**) sign*Y*a == D*B + M (mod |n|). | ||
810 | */ | ||
811 | tmp = A; /* keep the BIGNUM object, the value does not matter */ | ||
812 | |||
813 | /* (A, B) := (B, A mod B) ... */ | ||
814 | A = B; | ||
815 | B = M; | ||
816 | /* ... so we have 0 <= B < A again */ | ||
817 | |||
818 | /* Since the former M is now B and the former B is now A, | ||
819 | * (**) translates into | ||
820 | * sign*Y*a == D*A + B (mod |n|), | ||
821 | * i.e. | ||
822 | * sign*Y*a - D*A == B (mod |n|). | ||
823 | * Similarly, (*) translates into | ||
824 | * -sign*X*a == A (mod |n|). | ||
825 | * | ||
826 | * Thus, | ||
827 | * sign*Y*a + D*sign*X*a == B (mod |n|), | ||
828 | * i.e. | ||
829 | * sign*(Y + D*X)*a == B (mod |n|). | ||
830 | * | ||
831 | * So if we set (X, Y, sign) := (Y + D*X, X, -sign), we arrive back at | ||
832 | * -sign*X*a == B (mod |n|), | ||
833 | * sign*Y*a == A (mod |n|). | ||
834 | * Note that X and Y stay non-negative all the time. | ||
835 | */ | ||
836 | |||
837 | if (!BN_mul(tmp, D, X, ctx)) | ||
838 | goto err; | ||
839 | if (!BN_add(tmp, tmp, Y)) | ||
840 | goto err; | ||
841 | |||
842 | M = Y; /* keep the BIGNUM object, the value does not matter */ | ||
843 | Y = X; | ||
844 | X = tmp; | ||
845 | sign = -sign; | ||
846 | } | ||
847 | |||
848 | /* | ||
849 | * The while loop (Euclid's algorithm) ends when | ||
850 | * A == gcd(a,n); | ||
851 | */ | ||
852 | |||
853 | if (!BN_copy(R, A)) | ||
854 | goto err; | ||
855 | ret = R; | ||
856 | err: | ||
857 | if ((ret == NULL) && (in == NULL)) | ||
858 | BN_free(R); | ||
859 | BN_CTX_end(ctx); | ||
860 | bn_check_top(ret); | ||
861 | return (ret); | ||
862 | } | ||