diff options
| -rw-r--r-- | src/lib/libcrypto/bn/bn_kron.c | 161 |
1 files changed, 88 insertions, 73 deletions
diff --git a/src/lib/libcrypto/bn/bn_kron.c b/src/lib/libcrypto/bn/bn_kron.c index 274da5d186..c7bc53535e 100644 --- a/src/lib/libcrypto/bn/bn_kron.c +++ b/src/lib/libcrypto/bn/bn_kron.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: bn_kron.c,v 1.6 2015/02/09 15:49:22 jsing Exp $ */ | 1 | /* $OpenBSD: bn_kron.c,v 1.7 2022/06/20 19:32:35 tb Exp $ */ |
| 2 | /* ==================================================================== | 2 | /* ==================================================================== |
| 3 | * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved. | 3 | * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved. |
| 4 | * | 4 | * |
| @@ -58,128 +58,143 @@ | |||
| 58 | /* least significant word */ | 58 | /* least significant word */ |
| 59 | #define BN_lsw(n) (((n)->top == 0) ? (BN_ULONG) 0 : (n)->d[0]) | 59 | #define BN_lsw(n) (((n)->top == 0) ? (BN_ULONG) 0 : (n)->d[0]) |
| 60 | 60 | ||
| 61 | /* Returns -2 for errors because both -1 and 0 are valid results. */ | 61 | /* |
| 62 | * Kronecker symbol, implemented according to Henri Cohen, "A Course in | ||
| 63 | * Computational Algebraic Number Theory", Algorithm 1.4.10. | ||
| 64 | * | ||
| 65 | * Returns -1, 0, or 1 on success and -2 on error. | ||
| 66 | */ | ||
| 67 | |||
| 62 | int | 68 | int |
| 63 | BN_kronecker(const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) | 69 | BN_kronecker(const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) |
| 64 | { | 70 | { |
| 65 | int i; | 71 | /* tab[BN_lsw(n) & 7] = (-1)^((n^2 - 1)) / 8) for odd values of n. */ |
| 66 | int ret = -2; /* avoid 'uninitialized' warning */ | ||
| 67 | int err = 0; | ||
| 68 | BIGNUM *A, *B, *tmp; | ||
| 69 | |||
| 70 | /* In 'tab', only odd-indexed entries are relevant: | ||
| 71 | * For any odd BIGNUM n, | ||
| 72 | * tab[BN_lsw(n) & 7] | ||
| 73 | * is $(-1)^{(n^2-1)/8}$ (using TeX notation). | ||
| 74 | * Note that the sign of n does not matter. | ||
| 75 | */ | ||
| 76 | static const int tab[8] = {0, 1, 0, -1, 0, -1, 0, 1}; | 72 | static const int tab[8] = {0, 1, 0, -1, 0, -1, 0, 1}; |
| 73 | BIGNUM *A, *B, *tmp; | ||
| 74 | int k, v; | ||
| 75 | int ret = -2; | ||
| 77 | 76 | ||
| 78 | bn_check_top(a); | 77 | bn_check_top(a); |
| 79 | bn_check_top(b); | 78 | bn_check_top(b); |
| 80 | 79 | ||
| 81 | BN_CTX_start(ctx); | 80 | BN_CTX_start(ctx); |
| 81 | |||
| 82 | if ((A = BN_CTX_get(ctx)) == NULL) | 82 | if ((A = BN_CTX_get(ctx)) == NULL) |
| 83 | goto end; | 83 | goto end; |
| 84 | if ((B = BN_CTX_get(ctx)) == NULL) | 84 | if ((B = BN_CTX_get(ctx)) == NULL) |
| 85 | goto end; | 85 | goto end; |
| 86 | 86 | ||
| 87 | err = !BN_copy(A, a); | 87 | if (BN_copy(A, a) == NULL) |
| 88 | if (err) | ||
| 89 | goto end; | 88 | goto end; |
| 90 | err = !BN_copy(B, b); | 89 | if (BN_copy(B, b) == NULL) |
| 91 | if (err) | ||
| 92 | goto end; | 90 | goto end; |
| 93 | 91 | ||
| 94 | /* | 92 | /* |
| 95 | * Kronecker symbol, imlemented according to Henri Cohen, | 93 | * Cohen's step 1: |
| 96 | * "A Course in Computational Algebraic Number Theory" | ||
| 97 | * (algorithm 1.4.10). | ||
| 98 | */ | 94 | */ |
| 99 | 95 | ||
| 100 | /* Cohen's step 1: */ | 96 | /* If B is zero, output 1 if |A| is 1, otherwise output 0. */ |
| 101 | |||
| 102 | if (BN_is_zero(B)) { | 97 | if (BN_is_zero(B)) { |
| 103 | ret = BN_abs_is_word(A, 1); | 98 | ret = BN_abs_is_word(A, 1); |
| 104 | goto end; | 99 | goto end; |
| 105 | } | 100 | } |
| 106 | 101 | ||
| 107 | /* Cohen's step 2: */ | 102 | /* |
| 103 | * Cohen's step 2: | ||
| 104 | */ | ||
| 108 | 105 | ||
| 106 | /* If both are even, they have a factor in common, so output 0. */ | ||
| 109 | if (!BN_is_odd(A) && !BN_is_odd(B)) { | 107 | if (!BN_is_odd(A) && !BN_is_odd(B)) { |
| 110 | ret = 0; | 108 | ret = 0; |
| 111 | goto end; | 109 | goto end; |
| 112 | } | 110 | } |
| 113 | 111 | ||
| 114 | /* now B is non-zero */ | 112 | /* Factorize B = 2^v * u with odd u and replace B with u. */ |
| 115 | i = 0; | 113 | v = 0; |
| 116 | while (!BN_is_bit_set(B, i)) | 114 | while (!BN_is_bit_set(B, v)) |
| 117 | i++; | 115 | v++; |
| 118 | err = !BN_rshift(B, B, i); | 116 | if (!BN_rshift(B, B, v)) |
| 119 | if (err) | ||
| 120 | goto end; | 117 | goto end; |
| 121 | if (i & 1) { | ||
| 122 | /* i is odd */ | ||
| 123 | /* (thus B was even, thus A must be odd!) */ | ||
| 124 | |||
| 125 | /* set 'ret' to $(-1)^{(A^2-1)/8}$ */ | ||
| 126 | ret = tab[BN_lsw(A) & 7]; | ||
| 127 | } else { | ||
| 128 | /* i is even */ | ||
| 129 | ret = 1; | ||
| 130 | } | ||
| 131 | 118 | ||
| 132 | if (B->neg) { | 119 | /* If v is even set k = 1, otherwise set it to (-1)^((A^2 - 1) / 8). */ |
| 133 | B->neg = 0; | 120 | k = 1; |
| 134 | if (A->neg) | 121 | if (v % 2 != 0) |
| 135 | ret = -ret; | 122 | k = tab[BN_lsw(A) & 7]; |
| 123 | |||
| 124 | /* | ||
| 125 | * If B is negative, replace it with -B and if A is also negative | ||
| 126 | * replace k with -k. | ||
| 127 | */ | ||
| 128 | if (BN_is_negative(B)) { | ||
| 129 | BN_set_negative(B, 0); | ||
| 130 | |||
| 131 | if (BN_is_negative(A)) | ||
| 132 | k = -k; | ||
| 136 | } | 133 | } |
| 137 | 134 | ||
| 138 | /* now B is positive and odd, so what remains to be done is | 135 | /* |
| 139 | * to compute the Jacobi symbol (A/B) and multiply it by 'ret' */ | 136 | * Now B is positive and odd, so compute the Jacobi symbol (A/B) |
| 137 | * and multiply it by k. | ||
| 138 | */ | ||
| 140 | 139 | ||
| 141 | while (1) { | 140 | while (1) { |
| 142 | /* Cohen's step 3: */ | 141 | /* |
| 142 | * Cohen's step 3: | ||
| 143 | */ | ||
| 143 | 144 | ||
| 144 | /* B is positive and odd */ | 145 | /* B is positive and odd. */ |
| 145 | 146 | ||
| 147 | /* If A is zero output k if B is one, otherwise output 0. */ | ||
| 146 | if (BN_is_zero(A)) { | 148 | if (BN_is_zero(A)) { |
| 147 | ret = BN_is_one(B) ? ret : 0; | 149 | ret = BN_is_one(B) ? k : 0; |
| 148 | goto end; | 150 | goto end; |
| 149 | } | 151 | } |
| 150 | 152 | ||
| 151 | /* now A is non-zero */ | 153 | /* Factorize A = 2^v * u with odd u and replace A with u. */ |
| 152 | i = 0; | 154 | v = 0; |
| 153 | while (!BN_is_bit_set(A, i)) | 155 | while (!BN_is_bit_set(A, v)) |
| 154 | i++; | 156 | v++; |
| 155 | err = !BN_rshift(A, A, i); | 157 | if (!BN_rshift(A, A, v)) |
| 156 | if (err) | ||
| 157 | goto end; | 158 | goto end; |
| 158 | if (i & 1) { | ||
| 159 | /* i is odd */ | ||
| 160 | /* multiply 'ret' by $(-1)^{(B^2-1)/8}$ */ | ||
| 161 | ret = ret * tab[BN_lsw(B) & 7]; | ||
| 162 | } | ||
| 163 | |||
| 164 | /* Cohen's step 4: */ | ||
| 165 | /* multiply 'ret' by $(-1)^{(A-1)(B-1)/4}$ */ | ||
| 166 | if ((A->neg ? ~BN_lsw(A) : BN_lsw(A)) & BN_lsw(B) & 2) | ||
| 167 | ret = -ret; | ||
| 168 | 159 | ||
| 169 | /* (A, B) := (B mod |A|, |A|) */ | 160 | /* If v is odd, multiply k with (-1)^((B^2 - 1) / 8). */ |
| 170 | err = !BN_nnmod(B, B, A, ctx); | 161 | if (v % 2 != 0) |
| 171 | if (err) | 162 | k *= tab[BN_lsw(B) & 7]; |
| 163 | |||
| 164 | /* | ||
| 165 | * Cohen's step 4: | ||
| 166 | */ | ||
| 167 | |||
| 168 | /* | ||
| 169 | * Apply the reciprocity law: multiply k by (-1)^((A-1)(B-1)/4). | ||
| 170 | * | ||
| 171 | * This expression is -1 if and only if A and B are 3 (mod 4). | ||
| 172 | * In turn, this is the case if and only if their two's | ||
| 173 | * complement representations have the second bit set. | ||
| 174 | * A could be negative in the first iteration, B is positive. | ||
| 175 | */ | ||
| 176 | if ((BN_is_negative(A) ? ~BN_lsw(A) : BN_lsw(A)) & BN_lsw(B) & 2) | ||
| 177 | k = -k; | ||
| 178 | |||
| 179 | /* | ||
| 180 | * (A, B) := (B mod |A|, |A|) | ||
| 181 | * | ||
| 182 | * Once this is done, we know that 0 < A < B at the start of the | ||
| 183 | * loop. Since B is strictly decreasing, the loop terminates. | ||
| 184 | */ | ||
| 185 | |||
| 186 | if (!BN_nnmod(B, B, A, ctx)) | ||
| 172 | goto end; | 187 | goto end; |
| 188 | |||
| 173 | tmp = A; | 189 | tmp = A; |
| 174 | A = B; | 190 | A = B; |
| 175 | B = tmp; | 191 | B = tmp; |
| 176 | tmp->neg = 0; | 192 | |
| 193 | BN_set_negative(B, 0); | ||
| 177 | } | 194 | } |
| 178 | 195 | ||
| 179 | end: | 196 | end: |
| 180 | BN_CTX_end(ctx); | 197 | BN_CTX_end(ctx); |
| 181 | if (err) | 198 | |
| 182 | return -2; | 199 | return ret; |
| 183 | else | ||
| 184 | return ret; | ||
| 185 | } | 200 | } |
