/src/openssl30/crypto/bn/bn_kron.c
| Line | Count | Source (jump to first uncovered line) | 
| 1 |  | /* | 
| 2 |  |  * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. | 
| 3 |  |  * | 
| 4 |  |  * Licensed under the Apache License 2.0 (the "License").  You may not use | 
| 5 |  |  * this file except in compliance with the License.  You can obtain a copy | 
| 6 |  |  * in the file LICENSE in the source distribution or at | 
| 7 |  |  * https://www.openssl.org/source/license.html | 
| 8 |  |  */ | 
| 9 |  |  | 
| 10 |  | #include "internal/cryptlib.h" | 
| 11 |  | #include "bn_local.h" | 
| 12 |  |  | 
| 13 |  | /* least significant word */ | 
| 14 | 2.36M | #define BN_lsw(n) (((n)->top == 0) ? (BN_ULONG) 0 : (n)->d[0]) | 
| 15 |  |  | 
| 16 |  | /* Returns -2 for errors because both -1 and 0 are valid results. */ | 
| 17 |  | int BN_kronecker(const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) | 
| 18 | 261k | { | 
| 19 | 261k |     int i; | 
| 20 | 261k |     int ret = -2;               /* avoid 'uninitialized' warning */ | 
| 21 | 261k |     int err = 0; | 
| 22 | 261k |     BIGNUM *A, *B, *tmp; | 
| 23 |  |     /*- | 
| 24 |  |      * In 'tab', only odd-indexed entries are relevant: | 
| 25 |  |      * For any odd BIGNUM n, | 
| 26 |  |      *     tab[BN_lsw(n) & 7] | 
| 27 |  |      * is $(-1)^{(n^2-1)/8}$ (using TeX notation). | 
| 28 |  |      * Note that the sign of n does not matter. | 
| 29 |  |      */ | 
| 30 | 261k |     static const int tab[8] = { 0, 1, 0, -1, 0, -1, 0, 1 }; | 
| 31 |  |  | 
| 32 | 261k |     bn_check_top(a); | 
| 33 | 261k |     bn_check_top(b); | 
| 34 |  |  | 
| 35 | 261k |     BN_CTX_start(ctx); | 
| 36 | 261k |     A = BN_CTX_get(ctx); | 
| 37 | 261k |     B = BN_CTX_get(ctx); | 
| 38 | 261k |     if (B == NULL) | 
| 39 | 0 |         goto end; | 
| 40 |  |  | 
| 41 | 261k |     err = !BN_copy(A, a); | 
| 42 | 261k |     if (err) | 
| 43 | 0 |         goto end; | 
| 44 | 261k |     err = !BN_copy(B, b); | 
| 45 | 261k |     if (err) | 
| 46 | 0 |         goto end; | 
| 47 |  |  | 
| 48 |  |     /* | 
| 49 |  |      * Kronecker symbol, implemented according to Henri Cohen, | 
| 50 |  |      * "A Course in Computational Algebraic Number Theory" | 
| 51 |  |      * (algorithm 1.4.10). | 
| 52 |  |      */ | 
| 53 |  |  | 
| 54 |  |     /* Cohen's step 1: */ | 
| 55 |  |  | 
| 56 | 261k |     if (BN_is_zero(B)) { | 
| 57 | 0 |         ret = BN_abs_is_word(A, 1); | 
| 58 | 0 |         goto end; | 
| 59 | 0 |     } | 
| 60 |  |  | 
| 61 |  |     /* Cohen's step 2: */ | 
| 62 |  |  | 
| 63 | 261k |     if (!BN_is_odd(A) && !BN_is_odd(B)) { | 
| 64 | 0 |         ret = 0; | 
| 65 | 0 |         goto end; | 
| 66 | 0 |     } | 
| 67 |  |  | 
| 68 |  |     /* now  B  is non-zero */ | 
| 69 | 261k |     i = 0; | 
| 70 | 261k |     while (!BN_is_bit_set(B, i)) | 
| 71 | 0 |         i++; | 
| 72 | 261k |     err = !BN_rshift(B, B, i); | 
| 73 | 261k |     if (err) | 
| 74 | 0 |         goto end; | 
| 75 | 261k |     if (i & 1) { | 
| 76 |  |         /* i is odd */ | 
| 77 |  |         /* (thus  B  was even, thus  A  must be odd!)  */ | 
| 78 |  |  | 
| 79 |  |         /* set 'ret' to $(-1)^{(A^2-1)/8}$ */ | 
| 80 | 0 |         ret = tab[BN_lsw(A) & 7]; | 
| 81 | 261k |     } else { | 
| 82 |  |         /* i is even */ | 
| 83 | 261k |         ret = 1; | 
| 84 | 261k |     } | 
| 85 |  |  | 
| 86 | 261k |     if (B->neg) { | 
| 87 | 0 |         B->neg = 0; | 
| 88 | 0 |         if (A->neg) | 
| 89 | 0 |             ret = -ret; | 
| 90 | 0 |     } | 
| 91 |  |  | 
| 92 |  |     /* | 
| 93 |  |      * now B is positive and odd, so what remains to be done is to compute | 
| 94 |  |      * the Jacobi symbol (A/B) and multiply it by 'ret' | 
| 95 |  |      */ | 
| 96 |  |  | 
| 97 | 1.27M |     while (1) { | 
| 98 |  |         /* Cohen's step 3: */ | 
| 99 |  |  | 
| 100 |  |         /*  B  is positive and odd */ | 
| 101 |  |  | 
| 102 | 1.27M |         if (BN_is_zero(A)) { | 
| 103 | 261k |             ret = BN_is_one(B) ? ret : 0; | 
| 104 | 261k |             goto end; | 
| 105 | 261k |         } | 
| 106 |  |  | 
| 107 |  |         /* now  A  is non-zero */ | 
| 108 | 1.01M |         i = 0; | 
| 109 | 2.03M |         while (!BN_is_bit_set(A, i)) | 
| 110 | 1.02M |             i++; | 
| 111 | 1.01M |         err = !BN_rshift(A, A, i); | 
| 112 | 1.01M |         if (err) | 
| 113 | 0 |             goto end; | 
| 114 | 1.01M |         if (i & 1) { | 
| 115 |  |             /* i is odd */ | 
| 116 |  |             /* multiply 'ret' by  $(-1)^{(B^2-1)/8}$ */ | 
| 117 | 335k |             ret = ret * tab[BN_lsw(B) & 7]; | 
| 118 | 335k |         } | 
| 119 |  |  | 
| 120 |  |         /* Cohen's step 4: */ | 
| 121 |  |         /* multiply 'ret' by  $(-1)^{(A-1)(B-1)/4}$ */ | 
| 122 | 1.01M |         if ((A->neg ? ~BN_lsw(A) : BN_lsw(A)) & BN_lsw(B) & 2) | 
| 123 | 147k |             ret = -ret; | 
| 124 |  |  | 
| 125 |  |         /* (A, B) := (B mod |A|, |A|) */ | 
| 126 | 1.01M |         err = !BN_nnmod(B, B, A, ctx); | 
| 127 | 1.01M |         if (err) | 
| 128 | 0 |             goto end; | 
| 129 | 1.01M |         tmp = A; | 
| 130 | 1.01M |         A = B; | 
| 131 | 1.01M |         B = tmp; | 
| 132 | 1.01M |         tmp->neg = 0; | 
| 133 | 1.01M |     } | 
| 134 | 261k |  end: | 
| 135 | 261k |     BN_CTX_end(ctx); | 
| 136 | 261k |     if (err) | 
| 137 | 0 |         return -2; | 
| 138 | 261k |     else | 
| 139 | 261k |         return ret; | 
| 140 | 261k | } |