Coverage Report

Created: 2026-03-19 06:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/boringssl/crypto/fipsmodule/bn/jacobi.cc.inc
Line
Count
Source
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
using namespace bssl;
23
24
// least significant word
25
112k
#define BN_lsw(n) (((n)->width == 0) ? (BN_ULONG)0 : (n)->d[0])
26
27
28.9k
int bssl::bn_jacobi(const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) {
28
  // In 'tab', only odd-indexed entries are relevant:
29
  // For any odd BIGNUM n,
30
  //     tab[BN_lsw(n) & 7]
31
  // is $(-1)^{(n^2-1)/8}$ (using TeX notation).
32
  // Note that the sign of n does not matter.
33
28.9k
  static const int tab[8] = {0, 1, 0, -1, 0, -1, 0, 1};
34
35
  // The Jacobi symbol is only defined for odd modulus.
36
28.9k
  if (!BN_is_odd(b)) {
37
0
    OPENSSL_PUT_ERROR(BN, BN_R_CALLED_WITH_EVEN_MODULUS);
38
0
    return -2;
39
0
  }
40
41
  // Require b be positive.
42
28.9k
  if (BN_is_negative(b)) {
43
0
    OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER);
44
0
    return -2;
45
0
  }
46
47
28.9k
  BN_CTXScope scope(ctx);
48
28.9k
  BIGNUM *A = BN_CTX_get(ctx);
49
28.9k
  BIGNUM *B = BN_CTX_get(ctx);
50
28.9k
  if (B == nullptr) {
51
0
    return -2;
52
0
  }
53
54
28.9k
  if (!BN_copy(A, a) ||
55
28.9k
      !BN_copy(B, b)) {
56
0
    return -2;
57
0
  }
58
59
  // Adapted from logic to compute the Kronecker symbol, originally implemented
60
  // according to Henri Cohen, "A Course in Computational Algebraic Number
61
  // Theory" (algorithm 1.4.10).
62
63
28.9k
  int ret = 1;
64
78.1k
  while (1) {
65
    // Cohen's step 3:
66
67
    // B is positive and odd
68
78.1k
    if (BN_is_zero(A)) {
69
28.9k
      return BN_is_one(B) ? ret : 0;
70
28.9k
    }
71
72
    // now A is non-zero
73
49.1k
    int i = 0;
74
92.5k
    while (!BN_is_bit_set(A, i)) {
75
43.3k
      i++;
76
43.3k
    }
77
49.1k
    if (!BN_rshift(A, A, i)) {
78
0
      return -2;
79
0
    }
80
49.1k
    if (i & 1) {
81
      // i is odd
82
      // multiply 'ret' by  $(-1)^{(B^2-1)/8}$
83
14.4k
      ret = ret * tab[BN_lsw(B) & 7];
84
14.4k
    }
85
86
    // Cohen's step 4:
87
    // multiply 'ret' by  $(-1)^{(A-1)(B-1)/4}$
88
49.1k
    if ((A->neg ? ~BN_lsw(A) : BN_lsw(A)) & BN_lsw(B) & 2) {
89
0
      ret = -ret;
90
0
    }
91
92
    // (A, B) := (B mod |A|, |A|)
93
49.1k
    if (!BN_nnmod(B, B, A, ctx)) {
94
0
      return -2;
95
0
    }
96
49.1k
    BIGNUM *tmp = A;
97
49.1k
    A = B;
98
49.1k
    B = tmp;
99
49.1k
    tmp->neg = 0;
100
49.1k
  }
101
28.9k
}