1// Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// https://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15#include <openssl/bn.h> 16 17#include <openssl/err.h> 18 19#include "internal.h" 20 21 22// least significant word 23#define BN_lsw(n) (((n)->width == 0) ? (BN_ULONG) 0 : (n)->d[0]) 24 25int bn_jacobi(const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { 26 // In 'tab', only odd-indexed entries are relevant: 27 // For any odd BIGNUM n, 28 // tab[BN_lsw(n) & 7] 29 // is $(-1)^{(n^2-1)/8}$ (using TeX notation). 30 // Note that the sign of n does not matter. 31 static const int tab[8] = {0, 1, 0, -1, 0, -1, 0, 1}; 32 33 // The Jacobi symbol is only defined for odd modulus. 34 if (!BN_is_odd(b)) { 35 OPENSSL_PUT_ERROR(BN, BN_R_CALLED_WITH_EVEN_MODULUS); 36 return -2; 37 } 38 39 // Require b be positive. 40 if (BN_is_negative(b)) { 41 OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER); 42 return -2; 43 } 44 45 bssl::BN_CTXScope scope(ctx); 46 BIGNUM *A = BN_CTX_get(ctx); 47 BIGNUM *B = BN_CTX_get(ctx); 48 if (B == NULL) { 49 return -2; 50 } 51 52 if (!BN_copy(A, a) || 53 !BN_copy(B, b)) { 54 return -2; 55 } 56 57 // Adapted from logic to compute the Kronecker symbol, originally implemented 58 // according to Henri Cohen, "A Course in Computational Algebraic Number 59 // Theory" (algorithm 1.4.10). 60 61 int ret = 1; 62 while (1) { 63 // Cohen's step 3: 64 65 // B is positive and odd 66 if (BN_is_zero(A)) { 67 return BN_is_one(B) ? ret : 0; 68 } 69 70 // now A is non-zero 71 int i = 0; 72 while (!BN_is_bit_set(A, i)) { 73 i++; 74 } 75 if (!BN_rshift(A, A, i)) { 76 return -2; 77 } 78 if (i & 1) { 79 // i is odd 80 // multiply 'ret' by $(-1)^{(B^2-1)/8}$ 81 ret = ret * tab[BN_lsw(B) & 7]; 82 } 83 84 // Cohen's step 4: 85 // multiply 'ret' by $(-1)^{(A-1)(B-1)/4}$ 86 if ((A->neg ? ~BN_lsw(A) : BN_lsw(A)) & BN_lsw(B) & 2) { 87 ret = -ret; 88 } 89 90 // (A, B) := (B mod |A|, |A|) 91 if (!BN_nnmod(B, B, A, ctx)) { 92 return -2; 93 } 94 BIGNUM *tmp = A; 95 A = B; 96 B = tmp; 97 tmp->neg = 0; 98 } 99} 100