diff options
author | Joel Sing <jsing@cvs.openbsd.org> | 2023-01-21 09:21:12 +0000 |
---|---|---|
committer | Joel Sing <jsing@cvs.openbsd.org> | 2023-01-21 09:21:12 +0000 |
commit | 35975edb5c0b7835aabccd3cfc4cca172cd264cf (patch) | |
tree | 7eec2725f86ab34cd516106e8bd4f356eb5c4710 | |
parent | 23959297239bbe36ffcc5cba59d0755ee699a727 (diff) |
Reorder functions and drop unnessary static prototypes.
No functional change.
-rw-r--r-- | lib/libcrypto/bn/bn_gcd.c | 735 |
1 files changed, 363 insertions, 372 deletions
diff --git a/lib/libcrypto/bn/bn_gcd.c b/lib/libcrypto/bn/bn_gcd.c index 0d8bdf07ebd..84c3d858500 100644 --- a/lib/libcrypto/bn/bn_gcd.c +++ b/lib/libcrypto/bn/bn_gcd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bn_gcd.c,v 1.20 2022/12/26 07:18:51 jmc Exp $ */ +/* $OpenBSD: bn_gcd.c,v 1.21 2023/01/21 09:21:11 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -113,63 +113,6 @@ #include "bn_local.h" -static BIGNUM *euclid(BIGNUM *a, BIGNUM *b); -static BIGNUM *BN_gcd_no_branch(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, - BN_CTX *ctx); - -int -BN_gcd(BIGNUM *r, const BIGNUM *in_a, const BIGNUM *in_b, BN_CTX *ctx) -{ - BIGNUM *a, *b, *t; - int ret = 0; - - - BN_CTX_start(ctx); - if ((a = BN_CTX_get(ctx)) == NULL) - goto err; - if ((b = BN_CTX_get(ctx)) == NULL) - goto err; - - if (BN_copy(a, in_a) == NULL) - goto err; - if (BN_copy(b, in_b) == NULL) - goto err; - a->neg = 0; - b->neg = 0; - - if (BN_cmp(a, b) < 0) { - t = a; - a = b; - b = t; - } - t = euclid(a, b); - if (t == NULL) - goto err; - - if (BN_copy(r, t) == NULL) - goto err; - ret = 1; - -err: - BN_CTX_end(ctx); - return (ret); -} - -int -BN_gcd_ct(BIGNUM *r, const BIGNUM *in_a, const BIGNUM *in_b, BN_CTX *ctx) -{ - if (BN_gcd_no_branch(r, in_a, in_b, ctx) == NULL) - return 0; - return 1; -} - -int -BN_gcd_nonct(BIGNUM *r, const BIGNUM *in_a, const BIGNUM *in_b, BN_CTX *ctx) -{ - return BN_gcd(r, in_a, in_b, ctx); -} - - static BIGNUM * euclid(BIGNUM *a, BIGNUM *b) { @@ -237,11 +180,370 @@ err: return (NULL); } +/* + * BN_gcd_no_branch is a special version of BN_mod_inverse_no_branch. + * that returns the GCD. + */ +static BIGNUM * +BN_gcd_no_branch(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, + BN_CTX *ctx) +{ + BIGNUM *A, *B, *X, *Y, *M, *D, *T, *R = NULL; + BIGNUM local_A, local_B; + BIGNUM *pA, *pB; + BIGNUM *ret = NULL; + int sign; -/* solves ax == 1 (mod n) */ -static BIGNUM *BN_mod_inverse_no_branch(BIGNUM *in, const BIGNUM *a, - const BIGNUM *n, BN_CTX *ctx); + if (in == NULL) + goto err; + R = in; + + BN_init(&local_A); + BN_init(&local_B); + + + BN_CTX_start(ctx); + if ((A = BN_CTX_get(ctx)) == NULL) + goto err; + if ((B = BN_CTX_get(ctx)) == NULL) + goto err; + if ((X = BN_CTX_get(ctx)) == NULL) + goto err; + if ((D = BN_CTX_get(ctx)) == NULL) + goto err; + if ((M = BN_CTX_get(ctx)) == NULL) + goto err; + if ((Y = BN_CTX_get(ctx)) == NULL) + goto err; + if ((T = BN_CTX_get(ctx)) == NULL) + goto err; + + if (!BN_one(X)) + goto err; + BN_zero(Y); + if (BN_copy(B, a) == NULL) + goto err; + if (BN_copy(A, n) == NULL) + goto err; + A->neg = 0; + + if (B->neg || (BN_ucmp(B, A) >= 0)) { + /* + * Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked, + * BN_div_no_branch will be called eventually. + */ + pB = &local_B; + /* BN_init() done at the top of the function. */ + BN_with_flags(pB, B, BN_FLG_CONSTTIME); + if (!BN_nnmod(B, pB, A, ctx)) + goto err; + } + sign = -1; + /* From B = a mod |n|, A = |n| it follows that + * + * 0 <= B < A, + * -sign*X*a == B (mod |n|), + * sign*Y*a == A (mod |n|). + */ + + while (!BN_is_zero(B)) { + BIGNUM *tmp; + + /* + * 0 < B < A, + * (*) -sign*X*a == B (mod |n|), + * sign*Y*a == A (mod |n|) + */ + + /* + * Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked, + * BN_div_no_branch will be called eventually. + */ + pA = &local_A; + /* BN_init() done at the top of the function. */ + BN_with_flags(pA, A, BN_FLG_CONSTTIME); + + /* (D, M) := (A/B, A%B) ... */ + if (!BN_div_ct(D, M, pA, B, ctx)) + goto err; + + /* Now + * A = D*B + M; + * thus we have + * (**) sign*Y*a == D*B + M (mod |n|). + */ + tmp = A; /* keep the BIGNUM object, the value does not matter */ + + /* (A, B) := (B, A mod B) ... */ + A = B; + B = M; + /* ... so we have 0 <= B < A again */ + + /* Since the former M is now B and the former B is now A, + * (**) translates into + * sign*Y*a == D*A + B (mod |n|), + * i.e. + * sign*Y*a - D*A == B (mod |n|). + * Similarly, (*) translates into + * -sign*X*a == A (mod |n|). + * + * Thus, + * sign*Y*a + D*sign*X*a == B (mod |n|), + * i.e. + * sign*(Y + D*X)*a == B (mod |n|). + * + * So if we set (X, Y, sign) := (Y + D*X, X, -sign), we arrive back at + * -sign*X*a == B (mod |n|), + * sign*Y*a == A (mod |n|). + * Note that X and Y stay non-negative all the time. + */ + + if (!BN_mul(tmp, D, X, ctx)) + goto err; + if (!BN_add(tmp, tmp, Y)) + goto err; + + M = Y; /* keep the BIGNUM object, the value does not matter */ + Y = X; + X = tmp; + sign = -sign; + } + + /* + * The while loop (Euclid's algorithm) ends when + * A == gcd(a,n); + */ + + if (!BN_copy(R, A)) + goto err; + ret = R; +err: + if ((ret == NULL) && (in == NULL)) + BN_free(R); + BN_CTX_end(ctx); + return (ret); +} + +int +BN_gcd(BIGNUM *r, const BIGNUM *in_a, const BIGNUM *in_b, BN_CTX *ctx) +{ + BIGNUM *a, *b, *t; + int ret = 0; + + + BN_CTX_start(ctx); + if ((a = BN_CTX_get(ctx)) == NULL) + goto err; + if ((b = BN_CTX_get(ctx)) == NULL) + goto err; + + if (BN_copy(a, in_a) == NULL) + goto err; + if (BN_copy(b, in_b) == NULL) + goto err; + a->neg = 0; + b->neg = 0; + + if (BN_cmp(a, b) < 0) { + t = a; + a = b; + b = t; + } + t = euclid(a, b); + if (t == NULL) + goto err; + + if (BN_copy(r, t) == NULL) + goto err; + ret = 1; + +err: + BN_CTX_end(ctx); + return (ret); +} + +int +BN_gcd_ct(BIGNUM *r, const BIGNUM *in_a, const BIGNUM *in_b, BN_CTX *ctx) +{ + if (BN_gcd_no_branch(r, in_a, in_b, ctx) == NULL) + return 0; + return 1; +} + +int +BN_gcd_nonct(BIGNUM *r, const BIGNUM *in_a, const BIGNUM *in_b, BN_CTX *ctx) +{ + return BN_gcd(r, in_a, in_b, ctx); +} + +/* BN_mod_inverse_no_branch is a special version of BN_mod_inverse. + * It does not contain branches that may leak sensitive information. + */ +static BIGNUM * +BN_mod_inverse_no_branch(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, + BN_CTX *ctx) +{ + BIGNUM *A, *B, *X, *Y, *M, *D, *T, *R = NULL; + BIGNUM local_A, local_B; + BIGNUM *pA, *pB; + BIGNUM *ret = NULL; + int sign; + + + BN_init(&local_A); + BN_init(&local_B); + + BN_CTX_start(ctx); + if ((A = BN_CTX_get(ctx)) == NULL) + goto err; + if ((B = BN_CTX_get(ctx)) == NULL) + goto err; + if ((X = BN_CTX_get(ctx)) == NULL) + goto err; + if ((D = BN_CTX_get(ctx)) == NULL) + goto err; + if ((M = BN_CTX_get(ctx)) == NULL) + goto err; + if ((Y = BN_CTX_get(ctx)) == NULL) + goto err; + if ((T = BN_CTX_get(ctx)) == NULL) + goto err; + + if (in == NULL) + R = BN_new(); + else + R = in; + if (R == NULL) + goto err; + + if (!BN_one(X)) + goto err; + BN_zero(Y); + if (BN_copy(B, a) == NULL) + goto err; + if (BN_copy(A, n) == NULL) + goto err; + A->neg = 0; + + if (B->neg || (BN_ucmp(B, A) >= 0)) { + /* + * Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked, + * BN_div_no_branch will be called eventually. + */ + pB = &local_B; + /* BN_init() done at the top of the function. */ + BN_with_flags(pB, B, BN_FLG_CONSTTIME); + if (!BN_nnmod(B, pB, A, ctx)) + goto err; + } + sign = -1; + /* From B = a mod |n|, A = |n| it follows that + * + * 0 <= B < A, + * -sign*X*a == B (mod |n|), + * sign*Y*a == A (mod |n|). + */ + + while (!BN_is_zero(B)) { + BIGNUM *tmp; + + /* + * 0 < B < A, + * (*) -sign*X*a == B (mod |n|), + * sign*Y*a == A (mod |n|) + */ + + /* + * Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked, + * BN_div_no_branch will be called eventually. + */ + pA = &local_A; + /* BN_init() done at the top of the function. */ + BN_with_flags(pA, A, BN_FLG_CONSTTIME); + + /* (D, M) := (A/B, A%B) ... */ + if (!BN_div_ct(D, M, pA, B, ctx)) + goto err; + + /* Now + * A = D*B + M; + * thus we have + * (**) sign*Y*a == D*B + M (mod |n|). + */ + tmp = A; /* keep the BIGNUM object, the value does not matter */ + + /* (A, B) := (B, A mod B) ... */ + A = B; + B = M; + /* ... so we have 0 <= B < A again */ + + /* Since the former M is now B and the former B is now A, + * (**) translates into + * sign*Y*a == D*A + B (mod |n|), + * i.e. + * sign*Y*a - D*A == B (mod |n|). + * Similarly, (*) translates into + * -sign*X*a == A (mod |n|). + * + * Thus, + * sign*Y*a + D*sign*X*a == B (mod |n|), + * i.e. + * sign*(Y + D*X)*a == B (mod |n|). + * + * So if we set (X, Y, sign) := (Y + D*X, X, -sign), we arrive back at + * -sign*X*a == B (mod |n|), + * sign*Y*a == A (mod |n|). + * Note that X and Y stay non-negative all the time. + */ + + if (!BN_mul(tmp, D, X, ctx)) + goto err; + if (!BN_add(tmp, tmp, Y)) + goto err; + + M = Y; /* keep the BIGNUM object, the value does not matter */ + Y = X; + X = tmp; + sign = -sign; + } + + /* + * The while loop (Euclid's algorithm) ends when + * A == gcd(a,n); + * we have + * sign*Y*a == A (mod |n|), + * where Y is non-negative. + */ + + if (sign < 0) { + if (!BN_sub(Y, n, Y)) + goto err; + } + /* Now Y*a == A (mod |n|). */ + if (BN_is_one(A)) { + /* Y*a == 1 (mod |n|) */ + if (!Y->neg && BN_ucmp(Y, n) < 0) { + if (!BN_copy(R, Y)) + goto err; + } else { + if (!BN_nnmod(R, Y, n, ctx)) + goto err; + } + } else { + BNerror(BN_R_NO_INVERSE); + goto err; + } + ret = R; + +err: + if ((ret == NULL) && (in == NULL)) + BN_free(R); + BN_CTX_end(ctx); + return (ret); +} + +/* solves ax == 1 (mod n) */ static BIGNUM * BN_mod_inverse_internal(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx, int ct) @@ -551,314 +853,3 @@ BN_mod_inverse_ct(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx) { return BN_mod_inverse_internal(in, a, n, ctx, 1); } - -/* BN_mod_inverse_no_branch is a special version of BN_mod_inverse. - * It does not contain branches that may leak sensitive information. - */ -static BIGNUM * -BN_mod_inverse_no_branch(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, - BN_CTX *ctx) -{ - BIGNUM *A, *B, *X, *Y, *M, *D, *T, *R = NULL; - BIGNUM local_A, local_B; - BIGNUM *pA, *pB; - BIGNUM *ret = NULL; - int sign; - - - BN_init(&local_A); - BN_init(&local_B); - - BN_CTX_start(ctx); - if ((A = BN_CTX_get(ctx)) == NULL) - goto err; - if ((B = BN_CTX_get(ctx)) == NULL) - goto err; - if ((X = BN_CTX_get(ctx)) == NULL) - goto err; - if ((D = BN_CTX_get(ctx)) == NULL) - goto err; - if ((M = BN_CTX_get(ctx)) == NULL) - goto err; - if ((Y = BN_CTX_get(ctx)) == NULL) - goto err; - if ((T = BN_CTX_get(ctx)) == NULL) - goto err; - - if (in == NULL) - R = BN_new(); - else - R = in; - if (R == NULL) - goto err; - - if (!BN_one(X)) - goto err; - BN_zero(Y); - if (BN_copy(B, a) == NULL) - goto err; - if (BN_copy(A, n) == NULL) - goto err; - A->neg = 0; - - if (B->neg || (BN_ucmp(B, A) >= 0)) { - /* - * Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked, - * BN_div_no_branch will be called eventually. - */ - pB = &local_B; - /* BN_init() done at the top of the function. */ - BN_with_flags(pB, B, BN_FLG_CONSTTIME); - if (!BN_nnmod(B, pB, A, ctx)) - goto err; - } - sign = -1; - /* From B = a mod |n|, A = |n| it follows that - * - * 0 <= B < A, - * -sign*X*a == B (mod |n|), - * sign*Y*a == A (mod |n|). - */ - - while (!BN_is_zero(B)) { - BIGNUM *tmp; - - /* - * 0 < B < A, - * (*) -sign*X*a == B (mod |n|), - * sign*Y*a == A (mod |n|) - */ - - /* - * Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked, - * BN_div_no_branch will be called eventually. - */ - pA = &local_A; - /* BN_init() done at the top of the function. */ - BN_with_flags(pA, A, BN_FLG_CONSTTIME); - - /* (D, M) := (A/B, A%B) ... */ - if (!BN_div_ct(D, M, pA, B, ctx)) - goto err; - - /* Now - * A = D*B + M; - * thus we have - * (**) sign*Y*a == D*B + M (mod |n|). - */ - tmp = A; /* keep the BIGNUM object, the value does not matter */ - - /* (A, B) := (B, A mod B) ... */ - A = B; - B = M; - /* ... so we have 0 <= B < A again */ - - /* Since the former M is now B and the former B is now A, - * (**) translates into - * sign*Y*a == D*A + B (mod |n|), - * i.e. - * sign*Y*a - D*A == B (mod |n|). - * Similarly, (*) translates into - * -sign*X*a == A (mod |n|). - * - * Thus, - * sign*Y*a + D*sign*X*a == B (mod |n|), - * i.e. - * sign*(Y + D*X)*a == B (mod |n|). - * - * So if we set (X, Y, sign) := (Y + D*X, X, -sign), we arrive back at - * -sign*X*a == B (mod |n|), - * sign*Y*a == A (mod |n|). - * Note that X and Y stay non-negative all the time. - */ - - if (!BN_mul(tmp, D, X, ctx)) - goto err; - if (!BN_add(tmp, tmp, Y)) - goto err; - - M = Y; /* keep the BIGNUM object, the value does not matter */ - Y = X; - X = tmp; - sign = -sign; - } - - /* - * The while loop (Euclid's algorithm) ends when - * A == gcd(a,n); - * we have - * sign*Y*a == A (mod |n|), - * where Y is non-negative. - */ - - if (sign < 0) { - if (!BN_sub(Y, n, Y)) - goto err; - } - /* Now Y*a == A (mod |n|). */ - - if (BN_is_one(A)) { - /* Y*a == 1 (mod |n|) */ - if (!Y->neg && BN_ucmp(Y, n) < 0) { - if (!BN_copy(R, Y)) - goto err; - } else { - if (!BN_nnmod(R, Y, n, ctx)) - goto err; - } - } else { - BNerror(BN_R_NO_INVERSE); - goto err; - } - ret = R; - -err: - if ((ret == NULL) && (in == NULL)) - BN_free(R); - BN_CTX_end(ctx); - return (ret); -} - -/* - * BN_gcd_no_branch is a special version of BN_mod_inverse_no_branch. - * that returns the GCD. - */ -static BIGNUM * -BN_gcd_no_branch(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, - BN_CTX *ctx) -{ - BIGNUM *A, *B, *X, *Y, *M, *D, *T, *R = NULL; - BIGNUM local_A, local_B; - BIGNUM *pA, *pB; - BIGNUM *ret = NULL; - int sign; - - if (in == NULL) - goto err; - R = in; - - BN_init(&local_A); - BN_init(&local_B); - - - BN_CTX_start(ctx); - if ((A = BN_CTX_get(ctx)) == NULL) - goto err; - if ((B = BN_CTX_get(ctx)) == NULL) - goto err; - if ((X = BN_CTX_get(ctx)) == NULL) - goto err; - if ((D = BN_CTX_get(ctx)) == NULL) - goto err; - if ((M = BN_CTX_get(ctx)) == NULL) - goto err; - if ((Y = BN_CTX_get(ctx)) == NULL) - goto err; - if ((T = BN_CTX_get(ctx)) == NULL) - goto err; - - if (!BN_one(X)) - goto err; - BN_zero(Y); - if (BN_copy(B, a) == NULL) - goto err; - if (BN_copy(A, n) == NULL) - goto err; - A->neg = 0; - - if (B->neg || (BN_ucmp(B, A) >= 0)) { - /* - * Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked, - * BN_div_no_branch will be called eventually. - */ - pB = &local_B; - /* BN_init() done at the top of the function. */ - BN_with_flags(pB, B, BN_FLG_CONSTTIME); - if (!BN_nnmod(B, pB, A, ctx)) - goto err; - } - sign = -1; - /* From B = a mod |n|, A = |n| it follows that - * - * 0 <= B < A, - * -sign*X*a == B (mod |n|), - * sign*Y*a == A (mod |n|). - */ - - while (!BN_is_zero(B)) { - BIGNUM *tmp; - - /* - * 0 < B < A, - * (*) -sign*X*a == B (mod |n|), - * sign*Y*a == A (mod |n|) - */ - - /* - * Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked, - * BN_div_no_branch will be called eventually. - */ - pA = &local_A; - /* BN_init() done at the top of the function. */ - BN_with_flags(pA, A, BN_FLG_CONSTTIME); - - /* (D, M) := (A/B, A%B) ... */ - if (!BN_div_ct(D, M, pA, B, ctx)) - goto err; - - /* Now - * A = D*B + M; - * thus we have - * (**) sign*Y*a == D*B + M (mod |n|). - */ - tmp = A; /* keep the BIGNUM object, the value does not matter */ - - /* (A, B) := (B, A mod B) ... */ - A = B; - B = M; - /* ... so we have 0 <= B < A again */ - - /* Since the former M is now B and the former B is now A, - * (**) translates into - * sign*Y*a == D*A + B (mod |n|), - * i.e. - * sign*Y*a - D*A == B (mod |n|). - * Similarly, (*) translates into - * -sign*X*a == A (mod |n|). - * - * Thus, - * sign*Y*a + D*sign*X*a == B (mod |n|), - * i.e. - * sign*(Y + D*X)*a == B (mod |n|). - * - * So if we set (X, Y, sign) := (Y + D*X, X, -sign), we arrive back at - * -sign*X*a == B (mod |n|), - * sign*Y*a == A (mod |n|). - * Note that X and Y stay non-negative all the time. - */ - - if (!BN_mul(tmp, D, X, ctx)) - goto err; - if (!BN_add(tmp, tmp, Y)) - goto err; - - M = Y; /* keep the BIGNUM object, the value does not matter */ - Y = X; - X = tmp; - sign = -sign; - } - - /* - * The while loop (Euclid's algorithm) ends when - * A == gcd(a,n); - */ - - if (!BN_copy(R, A)) - goto err; - ret = R; -err: - if ((ret == NULL) && (in == NULL)) - BN_free(R); - BN_CTX_end(ctx); - return (ret); -} |