/src/openssl30/crypto/bn/bn_exp2.c
| Line | Count | Source (jump to first uncovered line) | 
| 1 |  | /* | 
| 2 |  |  * Copyright 1995-2022 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 <stdio.h> | 
| 11 |  | #include "internal/cryptlib.h" | 
| 12 |  | #include "bn_local.h" | 
| 13 |  |  | 
| 14 |  | #define TABLE_SIZE      32 | 
| 15 |  |  | 
| 16 |  | int BN_mod_exp2_mont(BIGNUM *rr, const BIGNUM *a1, const BIGNUM *p1, | 
| 17 |  |                      const BIGNUM *a2, const BIGNUM *p2, const BIGNUM *m, | 
| 18 |  |                      BN_CTX *ctx, BN_MONT_CTX *in_mont) | 
| 19 | 1.13k | { | 
| 20 | 1.13k |     int i, j, bits, b, bits1, bits2, ret = | 
| 21 | 1.13k |         0, wpos1, wpos2, window1, window2, wvalue1, wvalue2; | 
| 22 | 1.13k |     int r_is_one = 1; | 
| 23 | 1.13k |     BIGNUM *d, *r; | 
| 24 | 1.13k |     const BIGNUM *a_mod_m; | 
| 25 |  |     /* Tables of variables obtained from 'ctx' */ | 
| 26 | 1.13k |     BIGNUM *val1[TABLE_SIZE], *val2[TABLE_SIZE]; | 
| 27 | 1.13k |     BN_MONT_CTX *mont = NULL; | 
| 28 |  |  | 
| 29 | 1.13k |     bn_check_top(a1); | 
| 30 | 1.13k |     bn_check_top(p1); | 
| 31 | 1.13k |     bn_check_top(a2); | 
| 32 | 1.13k |     bn_check_top(p2); | 
| 33 | 1.13k |     bn_check_top(m); | 
| 34 |  |  | 
| 35 | 1.13k |     if (!BN_is_odd(m)) { | 
| 36 | 0 |         ERR_raise(ERR_LIB_BN, BN_R_CALLED_WITH_EVEN_MODULUS); | 
| 37 | 0 |         return 0; | 
| 38 | 0 |     } | 
| 39 | 1.13k |     bits1 = BN_num_bits(p1); | 
| 40 | 1.13k |     bits2 = BN_num_bits(p2); | 
| 41 | 1.13k |     if ((bits1 == 0) && (bits2 == 0)) { | 
| 42 | 0 |         ret = BN_one(rr); | 
| 43 | 0 |         return ret; | 
| 44 | 0 |     } | 
| 45 |  |  | 
| 46 | 1.13k |     bits = (bits1 > bits2) ? bits1 : bits2; | 
| 47 |  |  | 
| 48 | 1.13k |     BN_CTX_start(ctx); | 
| 49 | 1.13k |     d = BN_CTX_get(ctx); | 
| 50 | 1.13k |     r = BN_CTX_get(ctx); | 
| 51 | 1.13k |     val1[0] = BN_CTX_get(ctx); | 
| 52 | 1.13k |     val2[0] = BN_CTX_get(ctx); | 
| 53 | 1.13k |     if (val2[0] == NULL) | 
| 54 | 0 |         goto err; | 
| 55 |  |  | 
| 56 | 1.13k |     if (in_mont != NULL) | 
| 57 | 1.13k |         mont = in_mont; | 
| 58 | 0 |     else { | 
| 59 | 0 |         if ((mont = BN_MONT_CTX_new()) == NULL) | 
| 60 | 0 |             goto err; | 
| 61 | 0 |         if (!BN_MONT_CTX_set(mont, m, ctx)) | 
| 62 | 0 |             goto err; | 
| 63 | 0 |     } | 
| 64 |  |  | 
| 65 | 1.13k |     window1 = BN_window_bits_for_exponent_size(bits1); | 
| 66 | 1.13k |     window2 = BN_window_bits_for_exponent_size(bits2); | 
| 67 |  |  | 
| 68 |  |     /* | 
| 69 |  |      * Build table for a1:   val1[i] := a1^(2*i + 1) mod m  for i = 0 .. 2^(window1-1) | 
| 70 |  |      */ | 
| 71 | 1.13k |     if (a1->neg || BN_ucmp(a1, m) >= 0) { | 
| 72 | 430 |         if (!BN_mod(val1[0], a1, m, ctx)) | 
| 73 | 0 |             goto err; | 
| 74 | 430 |         a_mod_m = val1[0]; | 
| 75 | 430 |     } else | 
| 76 | 705 |         a_mod_m = a1; | 
| 77 | 1.13k |     if (BN_is_zero(a_mod_m)) { | 
| 78 | 4 |         BN_zero(rr); | 
| 79 | 4 |         ret = 1; | 
| 80 | 4 |         goto err; | 
| 81 | 4 |     } | 
| 82 |  |  | 
| 83 | 1.13k |     if (!BN_to_montgomery(val1[0], a_mod_m, mont, ctx)) | 
| 84 | 0 |         goto err; | 
| 85 | 1.13k |     if (window1 > 1) { | 
| 86 | 1.13k |         if (!BN_mod_mul_montgomery(d, val1[0], val1[0], mont, ctx)) | 
| 87 | 0 |             goto err; | 
| 88 |  |  | 
| 89 | 1.13k |         j = 1 << (window1 - 1); | 
| 90 | 9.04k |         for (i = 1; i < j; i++) { | 
| 91 | 7.91k |             if (((val1[i] = BN_CTX_get(ctx)) == NULL) || | 
| 92 | 7.91k |                 !BN_mod_mul_montgomery(val1[i], val1[i - 1], d, mont, ctx)) | 
| 93 | 0 |                 goto err; | 
| 94 | 7.91k |         } | 
| 95 | 1.13k |     } | 
| 96 |  |  | 
| 97 |  |     /* | 
| 98 |  |      * Build table for a2:   val2[i] := a2^(2*i + 1) mod m  for i = 0 .. 2^(window2-1) | 
| 99 |  |      */ | 
| 100 | 1.13k |     if (a2->neg || BN_ucmp(a2, m) >= 0) { | 
| 101 | 316 |         if (!BN_mod(val2[0], a2, m, ctx)) | 
| 102 | 0 |             goto err; | 
| 103 | 316 |         a_mod_m = val2[0]; | 
| 104 | 316 |     } else | 
| 105 | 815 |         a_mod_m = a2; | 
| 106 | 1.13k |     if (BN_is_zero(a_mod_m)) { | 
| 107 | 13 |         BN_zero(rr); | 
| 108 | 13 |         ret = 1; | 
| 109 | 13 |         goto err; | 
| 110 | 13 |     } | 
| 111 | 1.11k |     if (!BN_to_montgomery(val2[0], a_mod_m, mont, ctx)) | 
| 112 | 0 |         goto err; | 
| 113 | 1.11k |     if (window2 > 1) { | 
| 114 | 1.10k |         if (!BN_mod_mul_montgomery(d, val2[0], val2[0], mont, ctx)) | 
| 115 | 0 |             goto err; | 
| 116 |  |  | 
| 117 | 1.10k |         j = 1 << (window2 - 1); | 
| 118 | 8.84k |         for (i = 1; i < j; i++) { | 
| 119 | 7.73k |             if (((val2[i] = BN_CTX_get(ctx)) == NULL) || | 
| 120 | 7.73k |                 !BN_mod_mul_montgomery(val2[i], val2[i - 1], d, mont, ctx)) | 
| 121 | 0 |                 goto err; | 
| 122 | 7.73k |         } | 
| 123 | 1.10k |     } | 
| 124 |  |  | 
| 125 |  |     /* Now compute the power product, using independent windows. */ | 
| 126 | 1.11k |     r_is_one = 1; | 
| 127 | 1.11k |     wvalue1 = 0;                /* The 'value' of the first window */ | 
| 128 | 1.11k |     wvalue2 = 0;                /* The 'value' of the second window */ | 
| 129 | 1.11k |     wpos1 = 0;                  /* If wvalue1 > 0, the bottom bit of the | 
| 130 |  |                                  * first window */ | 
| 131 | 1.11k |     wpos2 = 0;                  /* If wvalue2 > 0, the bottom bit of the | 
| 132 |  |                                  * second window */ | 
| 133 |  |  | 
| 134 | 1.11k |     if (!BN_to_montgomery(r, BN_value_one(), mont, ctx)) | 
| 135 | 0 |         goto err; | 
| 136 | 212k |     for (b = bits - 1; b >= 0; b--) { | 
| 137 | 211k |         if (!r_is_one) { | 
| 138 | 208k |             if (!BN_mod_mul_montgomery(r, r, r, mont, ctx)) | 
| 139 | 0 |                 goto err; | 
| 140 | 208k |         } | 
| 141 |  |  | 
| 142 | 211k |         if (!wvalue1) | 
| 143 | 122k |             if (BN_is_bit_set(p1, b)) { | 
| 144 |  |                 /* | 
| 145 |  |                  * consider bits b-window1+1 .. b for this window | 
| 146 |  |                  */ | 
| 147 | 42.3k |                 i = b - window1 + 1; | 
| 148 | 80.5k |                 while (!BN_is_bit_set(p1, i)) /* works for i<0 */ | 
| 149 | 38.2k |                     i++; | 
| 150 | 42.3k |                 wpos1 = i; | 
| 151 | 42.3k |                 wvalue1 = 1; | 
| 152 | 131k |                 for (i = b - 1; i >= wpos1; i--) { | 
| 153 | 88.7k |                     wvalue1 <<= 1; | 
| 154 | 88.7k |                     if (BN_is_bit_set(p1, i)) | 
| 155 | 62.8k |                         wvalue1++; | 
| 156 | 88.7k |                 } | 
| 157 | 42.3k |             } | 
| 158 |  |  | 
| 159 | 211k |         if (!wvalue2) | 
| 160 | 125k |             if (BN_is_bit_set(p2, b)) { | 
| 161 |  |                 /* | 
| 162 |  |                  * consider bits b-window2+1 .. b for this window | 
| 163 |  |                  */ | 
| 164 | 41.1k |                 i = b - window2 + 1; | 
| 165 | 78.4k |                 while (!BN_is_bit_set(p2, i)) | 
| 166 | 37.3k |                     i++; | 
| 167 | 41.1k |                 wpos2 = i; | 
| 168 | 41.1k |                 wvalue2 = 1; | 
| 169 | 127k |                 for (i = b - 1; i >= wpos2; i--) { | 
| 170 | 85.9k |                     wvalue2 <<= 1; | 
| 171 | 85.9k |                     if (BN_is_bit_set(p2, i)) | 
| 172 | 60.4k |                         wvalue2++; | 
| 173 | 85.9k |                 } | 
| 174 | 41.1k |             } | 
| 175 |  |  | 
| 176 | 211k |         if (wvalue1 && b == wpos1) { | 
| 177 |  |             /* wvalue1 is odd and < 2^window1 */ | 
| 178 | 42.3k |             if (!BN_mod_mul_montgomery(r, r, val1[wvalue1 >> 1], mont, ctx)) | 
| 179 | 0 |                 goto err; | 
| 180 | 42.3k |             wvalue1 = 0; | 
| 181 | 42.3k |             r_is_one = 0; | 
| 182 | 42.3k |         } | 
| 183 |  |  | 
| 184 | 211k |         if (wvalue2 && b == wpos2) { | 
| 185 |  |             /* wvalue2 is odd and < 2^window2 */ | 
| 186 | 41.1k |             if (!BN_mod_mul_montgomery(r, r, val2[wvalue2 >> 1], mont, ctx)) | 
| 187 | 0 |                 goto err; | 
| 188 | 41.1k |             wvalue2 = 0; | 
| 189 | 41.1k |             r_is_one = 0; | 
| 190 | 41.1k |         } | 
| 191 | 211k |     } | 
| 192 | 1.11k |     if (!BN_from_montgomery(rr, r, mont, ctx)) | 
| 193 | 0 |         goto err; | 
| 194 | 1.11k |     ret = 1; | 
| 195 | 1.13k |  err: | 
| 196 | 1.13k |     if (in_mont == NULL) | 
| 197 | 0 |         BN_MONT_CTX_free(mont); | 
| 198 | 1.13k |     BN_CTX_end(ctx); | 
| 199 | 1.13k |     bn_check_top(rr); | 
| 200 | 1.13k |     return ret; | 
| 201 | 1.11k | } |