Downgrade BN_kronecker to bn_jacobi and unexport.
We only ever compute it for odd (actually, prime) modulus as part of
BN_mod_sqrt.
If we cared, we could probably drop this from most binaries. This is
used to when modular square root needs Tonelli-Shanks. Modular square
root is only used for compressed coordinates. Of our supported curves
(I'm handwaiving away EC_GROUP_new_curve_GFp here[*]), only P-224 needs
the full Tonelli-Shanks algorithm (p is 1 mod 8). That computes the
Legendre symbol a bunch to find a non-square mod p. But p is known at
compile-time, so we can just hard-code a sample non-square.
Sadly, BN_mod_sqrt has some callers outside of crypto/ec, so there's
also that. Anyway, it's also not that large of a function.
[*] Glancing through SEC 2 and Brainpool, secp224r1 is the only curve
listed in either document whose prime is not either 3 mod 4 or 5 mod 8.
Even 5 mod 8 is rare: only secp224k1. It's unlikely anyone would notice
if we broke annoying primes. Though OpenSSL does support "WTLS" curves
which has an additional 1 mod 8 case.
Change-Id: If36aa78c0d41253ec024f2d90692949515356cd1
Reviewed-on: https://boringssl-review.googlesource.com/15425
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/bn/CMakeLists.txt b/crypto/bn/CMakeLists.txt
index 9dd24b4..5da72e9 100644
--- a/crypto/bn/CMakeLists.txt
+++ b/crypto/bn/CMakeLists.txt
@@ -54,7 +54,7 @@
exponentiation.c
generic.c
gcd.c
- kronecker.c
+ jacobi.c
montgomery.c
montgomery_inv.c
mul.c
diff --git a/crypto/bn/internal.h b/crypto/bn/internal.h
index 7a3903b..e90b435 100644
--- a/crypto/bn/internal.h
+++ b/crypto/bn/internal.h
@@ -259,6 +259,10 @@
int bn_mod_inverse_secret_prime(BIGNUM *out, const BIGNUM *a, const BIGNUM *p,
BN_CTX *ctx, const BN_MONT_CTX *mont_p);
+/* bn_jacobi returns the Jacobi symbol of |a| and |b| (which is -1, 0 or 1), or
+ * -2 on error. */
+int bn_jacobi(const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
+
#if defined(__cplusplus)
} /* extern C */
diff --git a/crypto/bn/kronecker.c b/crypto/bn/jacobi.c
similarity index 78%
rename from crypto/bn/kronecker.c
rename to crypto/bn/jacobi.c
index 2089851..93e8fd9 100644
--- a/crypto/bn/kronecker.c
+++ b/crypto/bn/jacobi.c
@@ -52,17 +52,15 @@
#include <openssl/bn.h>
+#include <openssl/err.h>
+
#include "internal.h"
/* least significant word */
#define BN_lsw(n) (((n)->top == 0) ? (BN_ULONG) 0 : (n)->d[0])
-/* Returns -2 for errors because both -1 and 0 are valid results. */
-int BN_kronecker(const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) {
- int i;
- int ret = -2;
- BIGNUM *A, *B, *tmp;
+int bn_jacobi(const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) {
/* In 'tab', only odd-indexed entries are relevant:
* For any odd BIGNUM n,
* tab[BN_lsw(n) & 7]
@@ -70,9 +68,22 @@
* Note that the sign of n does not matter. */
static const int tab[8] = {0, 1, 0, -1, 0, -1, 0, 1};
+ /* The Jacobi symbol is only defined for odd modulus. */
+ if (!BN_is_odd(b)) {
+ OPENSSL_PUT_ERROR(BN, BN_R_CALLED_WITH_EVEN_MODULUS);
+ return -2;
+ }
+
+ /* Require b be positive. */
+ if (BN_is_negative(b)) {
+ OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER);
+ return -2;
+ }
+
+ int ret = -2;
BN_CTX_start(ctx);
- A = BN_CTX_get(ctx);
- B = BN_CTX_get(ctx);
+ BIGNUM *A = BN_CTX_get(ctx);
+ BIGNUM *B = BN_CTX_get(ctx);
if (B == NULL) {
goto end;
}
@@ -82,52 +93,11 @@
goto end;
}
- /* Kronecker symbol, imlemented according to Henri Cohen,
- * "A Course in Computational Algebraic Number Theory"
- * (algorithm 1.4.10). */
+ /* Adapted from logic to compute the Kronecker symbol, originally implemented
+ * according to Henri Cohen, "A Course in Computational Algebraic Number
+ * Theory" (algorithm 1.4.10). */
- /* Cohen's step 1: */
-
- if (BN_is_zero(B)) {
- ret = BN_abs_is_word(A, 1);
- goto end;
- }
-
- /* Cohen's step 2: */
-
- if (!BN_is_odd(A) && !BN_is_odd(B)) {
- ret = 0;
- goto end;
- }
-
- /* now B is non-zero */
- i = 0;
- while (!BN_is_bit_set(B, i)) {
- i++;
- }
- if (!BN_rshift(B, B, i)) {
- goto end;
- }
- if (i & 1) {
- /* i is odd */
- /* (thus B was even, thus A must be odd!) */
-
- /* set 'ret' to $(-1)^{(A^2-1)/8}$ */
- ret = tab[BN_lsw(A) & 7];
- } else {
- /* i is even */
- ret = 1;
- }
-
- if (B->neg) {
- B->neg = 0;
- if (A->neg) {
- ret = -ret;
- }
- }
-
- /* now B is positive and odd, so what remains to be done is to compute the
- * Jacobi symbol (A/B) and multiply it by 'ret' */
+ ret = 1;
while (1) {
/* Cohen's step 3: */
@@ -139,7 +109,7 @@
}
/* now A is non-zero */
- i = 0;
+ int i = 0;
while (!BN_is_bit_set(A, i)) {
i++;
}
@@ -164,7 +134,7 @@
ret = -2;
goto end;
}
- tmp = A;
+ BIGNUM *tmp = A;
A = B;
B = tmp;
tmp->neg = 0;
diff --git a/crypto/bn/sqrt.c b/crypto/bn/sqrt.c
index f806ea2..0342bc0 100644
--- a/crypto/bn/sqrt.c
+++ b/crypto/bn/sqrt.c
@@ -56,6 +56,8 @@
#include <openssl/err.h>
+#include "internal.h"
+
BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) {
/* Compute a square root of |a| mod |p| using the Tonelli/Shanks algorithm
@@ -253,7 +255,7 @@
}
}
- r = BN_kronecker(y, q, ctx); /* here 'q' is |p| */
+ r = bn_jacobi(y, q, ctx); /* here 'q' is |p| */
if (r < -1) {
goto end;
}
diff --git a/include/openssl/bn.h b/include/openssl/bn.h
index 49d4495..5ebdade 100644
--- a/include/openssl/bn.h
+++ b/include/openssl/bn.h
@@ -797,10 +797,6 @@
int BN_mod_inverse_odd(BIGNUM *out, int *out_no_inverse, const BIGNUM *a,
const BIGNUM *n, BN_CTX *ctx);
-/* BN_kronecker returns the Kronecker symbol of |a| and |b| (which is -1, 0 or
- * 1), or -2 on error. */
-OPENSSL_EXPORT int BN_kronecker(const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
-
/* Montgomery arithmetic. */