/src/boringssl/crypto/fipsmodule/bn/shift.cc.inc
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright 1995-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 <assert.h> |
18 | | #include <string.h> |
19 | | |
20 | | #include <openssl/err.h> |
21 | | |
22 | | #include "internal.h" |
23 | | |
24 | | |
25 | 12.8M | int BN_lshift(BIGNUM *r, const BIGNUM *a, int n) { |
26 | 12.8M | int i, nw, lb, rb; |
27 | 12.8M | BN_ULONG *t, *f; |
28 | 12.8M | BN_ULONG l; |
29 | | |
30 | 12.8M | if (n < 0) { |
31 | 0 | OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER); |
32 | 0 | return 0; |
33 | 0 | } |
34 | | |
35 | 12.8M | r->neg = a->neg; |
36 | 12.8M | nw = n / BN_BITS2; |
37 | 12.8M | if (!bn_wexpand(r, a->width + nw + 1)) { |
38 | 0 | return 0; |
39 | 0 | } |
40 | 12.8M | lb = n % BN_BITS2; |
41 | 12.8M | rb = BN_BITS2 - lb; |
42 | 12.8M | f = a->d; |
43 | 12.8M | t = r->d; |
44 | 12.8M | t[a->width + nw] = 0; |
45 | 12.8M | if (lb == 0) { |
46 | 1.61M | for (i = a->width - 1; i >= 0; i--) { |
47 | 1.55M | t[nw + i] = f[i]; |
48 | 1.55M | } |
49 | 12.8M | } else { |
50 | 83.4M | for (i = a->width - 1; i >= 0; i--) { |
51 | 70.6M | l = f[i]; |
52 | 70.6M | t[nw + i + 1] |= l >> rb; |
53 | 70.6M | t[nw + i] = l << lb; |
54 | 70.6M | } |
55 | 12.8M | } |
56 | 12.8M | OPENSSL_memset(t, 0, nw * sizeof(t[0])); |
57 | 12.8M | r->width = a->width + nw + 1; |
58 | 12.8M | bn_set_minimal_width(r); |
59 | | |
60 | 12.8M | return 1; |
61 | 12.8M | } |
62 | | |
63 | 0 | int BN_lshift1(BIGNUM *r, const BIGNUM *a) { |
64 | 0 | BN_ULONG *ap, *rp, t, c; |
65 | 0 | int i; |
66 | |
|
67 | 0 | if (r != a) { |
68 | 0 | r->neg = a->neg; |
69 | 0 | if (!bn_wexpand(r, a->width + 1)) { |
70 | 0 | return 0; |
71 | 0 | } |
72 | 0 | r->width = a->width; |
73 | 0 | } else { |
74 | 0 | if (!bn_wexpand(r, a->width + 1)) { |
75 | 0 | return 0; |
76 | 0 | } |
77 | 0 | } |
78 | 0 | ap = a->d; |
79 | 0 | rp = r->d; |
80 | 0 | c = 0; |
81 | 0 | for (i = 0; i < a->width; i++) { |
82 | 0 | t = *(ap++); |
83 | 0 | *(rp++) = (t << 1) | c; |
84 | 0 | c = t >> (BN_BITS2 - 1); |
85 | 0 | } |
86 | 0 | if (c) { |
87 | 0 | *rp = 1; |
88 | 0 | r->width++; |
89 | 0 | } |
90 | |
|
91 | 0 | return 1; |
92 | 0 | } |
93 | | |
94 | | void bn_rshift_words(BN_ULONG *r, const BN_ULONG *a, unsigned shift, |
95 | 8.18M | size_t num) { |
96 | 8.18M | unsigned shift_bits = shift % BN_BITS2; |
97 | 8.18M | size_t shift_words = shift / BN_BITS2; |
98 | 8.18M | if (shift_words >= num) { |
99 | 87.2k | OPENSSL_memset(r, 0, num * sizeof(BN_ULONG)); |
100 | 87.2k | return; |
101 | 87.2k | } |
102 | 8.10M | if (shift_bits == 0) { |
103 | 51.2k | OPENSSL_memmove(r, a + shift_words, (num - shift_words) * sizeof(BN_ULONG)); |
104 | 8.04M | } else { |
105 | 53.0M | for (size_t i = shift_words; i < num - 1; i++) { |
106 | 45.0M | r[i - shift_words] = |
107 | 45.0M | (a[i] >> shift_bits) | (a[i + 1] << (BN_BITS2 - shift_bits)); |
108 | 45.0M | } |
109 | 8.04M | r[num - 1 - shift_words] = a[num - 1] >> shift_bits; |
110 | 8.04M | } |
111 | 8.10M | OPENSSL_memset(r + num - shift_words, 0, shift_words * sizeof(BN_ULONG)); |
112 | 8.10M | } |
113 | | |
114 | 8.18M | int BN_rshift(BIGNUM *r, const BIGNUM *a, int n) { |
115 | 8.18M | if (n < 0) { |
116 | 0 | OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER); |
117 | 0 | return 0; |
118 | 0 | } |
119 | | |
120 | 8.18M | if (!bn_wexpand(r, a->width)) { |
121 | 0 | return 0; |
122 | 0 | } |
123 | 8.18M | bn_rshift_words(r->d, a->d, n, a->width); |
124 | 8.18M | r->neg = a->neg; |
125 | 8.18M | r->width = a->width; |
126 | 8.18M | bn_set_minimal_width(r); |
127 | 8.18M | return 1; |
128 | 8.18M | } |
129 | | |
130 | | int bn_rshift_secret_shift(BIGNUM *r, const BIGNUM *a, unsigned n, |
131 | 0 | BN_CTX *ctx) { |
132 | 0 | bssl::BN_CTXScope scope(ctx); |
133 | 0 | BIGNUM *tmp = BN_CTX_get(ctx); |
134 | 0 | unsigned max_bits; |
135 | 0 | if (tmp == NULL || !BN_copy(r, a) || !bn_wexpand(tmp, r->width)) { |
136 | 0 | return 0; |
137 | 0 | } |
138 | | |
139 | | // Shift conditionally by powers of two. |
140 | 0 | max_bits = BN_BITS2 * r->width; |
141 | 0 | for (unsigned i = 0; (max_bits >> i) != 0; i++) { |
142 | 0 | BN_ULONG mask = (n >> i) & 1; |
143 | 0 | mask = 0 - mask; |
144 | 0 | bn_rshift_words(tmp->d, r->d, 1u << i, r->width); |
145 | 0 | bn_select_words(r->d, mask, tmp->d /* apply shift */, |
146 | 0 | r->d /* ignore shift */, r->width); |
147 | 0 | } |
148 | |
|
149 | 0 | return 1; |
150 | 0 | } |
151 | | |
152 | 3.58M | void bn_rshift1_words(BN_ULONG *r, const BN_ULONG *a, size_t num) { |
153 | 3.58M | if (num == 0) { |
154 | 0 | return; |
155 | 0 | } |
156 | 113M | for (size_t i = 0; i < num - 1; i++) { |
157 | 109M | r[i] = (a[i] >> 1) | (a[i + 1] << (BN_BITS2 - 1)); |
158 | 109M | } |
159 | 3.58M | r[num - 1] = a[num - 1] >> 1; |
160 | 3.58M | } |
161 | | |
162 | 3.58M | int BN_rshift1(BIGNUM *r, const BIGNUM *a) { |
163 | 3.58M | if (!bn_wexpand(r, a->width)) { |
164 | 0 | return 0; |
165 | 0 | } |
166 | 3.58M | bn_rshift1_words(r->d, a->d, a->width); |
167 | 3.58M | r->width = a->width; |
168 | 3.58M | r->neg = a->neg; |
169 | 3.58M | bn_set_minimal_width(r); |
170 | 3.58M | return 1; |
171 | 3.58M | } |
172 | | |
173 | 22.7k | int BN_set_bit(BIGNUM *a, int n) { |
174 | 22.7k | if (n < 0) { |
175 | 0 | return 0; |
176 | 0 | } |
177 | | |
178 | 22.7k | int i = n / BN_BITS2; |
179 | 22.7k | int j = n % BN_BITS2; |
180 | 22.7k | if (a->width <= i) { |
181 | 22.7k | if (!bn_wexpand(a, i + 1)) { |
182 | 0 | return 0; |
183 | 0 | } |
184 | 694k | for (int k = a->width; k < i + 1; k++) { |
185 | 672k | a->d[k] = 0; |
186 | 672k | } |
187 | 22.7k | a->width = i + 1; |
188 | 22.7k | } |
189 | | |
190 | 22.7k | a->d[i] |= (((BN_ULONG)1) << j); |
191 | | |
192 | 22.7k | return 1; |
193 | 22.7k | } |
194 | | |
195 | 0 | int BN_clear_bit(BIGNUM *a, int n) { |
196 | 0 | int i, j; |
197 | |
|
198 | 0 | if (n < 0) { |
199 | 0 | return 0; |
200 | 0 | } |
201 | | |
202 | 0 | i = n / BN_BITS2; |
203 | 0 | j = n % BN_BITS2; |
204 | 0 | if (a->width <= i) { |
205 | 0 | return 0; |
206 | 0 | } |
207 | | |
208 | 0 | a->d[i] &= (~(((BN_ULONG)1) << j)); |
209 | 0 | bn_set_minimal_width(a); |
210 | 0 | return 1; |
211 | 0 | } |
212 | | |
213 | 58.4M | int bn_is_bit_set_words(const BN_ULONG *a, size_t num, size_t bit) { |
214 | 58.4M | size_t i = bit / BN_BITS2; |
215 | 58.4M | size_t j = bit % BN_BITS2; |
216 | 58.4M | if (i >= num) { |
217 | 70.1k | return 0; |
218 | 70.1k | } |
219 | 58.3M | return (a[i] >> j) & 1; |
220 | 58.4M | } |
221 | | |
222 | 10.2M | int BN_is_bit_set(const BIGNUM *a, int n) { |
223 | 10.2M | if (n < 0) { |
224 | 0 | return 0; |
225 | 0 | } |
226 | 10.2M | return bn_is_bit_set_words(a->d, a->width, n); |
227 | 10.2M | } |
228 | | |
229 | 0 | int BN_mask_bits(BIGNUM *a, int n) { |
230 | 0 | if (n < 0) { |
231 | 0 | return 0; |
232 | 0 | } |
233 | | |
234 | 0 | int w = n / BN_BITS2; |
235 | 0 | int b = n % BN_BITS2; |
236 | 0 | if (w >= a->width) { |
237 | 0 | return 1; |
238 | 0 | } |
239 | 0 | if (b == 0) { |
240 | 0 | a->width = w; |
241 | 0 | } else { |
242 | 0 | a->width = w + 1; |
243 | 0 | a->d[w] &= ~(BN_MASK2 << b); |
244 | 0 | } |
245 | |
|
246 | 0 | bn_set_minimal_width(a); |
247 | 0 | return 1; |
248 | 0 | } |
249 | | |
250 | 0 | static int bn_count_low_zero_bits_word(BN_ULONG l) { |
251 | 0 | static_assert(sizeof(BN_ULONG) <= sizeof(crypto_word_t), |
252 | 0 | "crypto_word_t is too small"); |
253 | 0 | static_assert(sizeof(int) <= sizeof(crypto_word_t), |
254 | 0 | "crypto_word_t is too small"); |
255 | 0 | static_assert(BN_BITS2 == sizeof(BN_ULONG) * 8, "BN_ULONG has padding bits"); |
256 | | // C has very bizarre rules for types smaller than an int. |
257 | 0 | static_assert(sizeof(BN_ULONG) >= sizeof(int), |
258 | 0 | "BN_ULONG gets promoted to int"); |
259 | |
|
260 | 0 | crypto_word_t mask; |
261 | 0 | int bits = 0; |
262 | |
|
263 | 0 | #if BN_BITS2 > 32 |
264 | | // Check if the lower half of |x| are all zero. |
265 | 0 | mask = constant_time_is_zero_w(l << (BN_BITS2 - 32)); |
266 | | // If the lower half is all zeros, it is included in the bit count and we |
267 | | // count the upper half. Otherwise, we count the lower half. |
268 | 0 | bits += 32 & mask; |
269 | 0 | l = constant_time_select_w(mask, l >> 32, l); |
270 | 0 | #endif |
271 | | |
272 | | // The remaining blocks are analogous iterations at lower powers of two. |
273 | 0 | mask = constant_time_is_zero_w(l << (BN_BITS2 - 16)); |
274 | 0 | bits += 16 & mask; |
275 | 0 | l = constant_time_select_w(mask, l >> 16, l); |
276 | |
|
277 | 0 | mask = constant_time_is_zero_w(l << (BN_BITS2 - 8)); |
278 | 0 | bits += 8 & mask; |
279 | 0 | l = constant_time_select_w(mask, l >> 8, l); |
280 | |
|
281 | 0 | mask = constant_time_is_zero_w(l << (BN_BITS2 - 4)); |
282 | 0 | bits += 4 & mask; |
283 | 0 | l = constant_time_select_w(mask, l >> 4, l); |
284 | |
|
285 | 0 | mask = constant_time_is_zero_w(l << (BN_BITS2 - 2)); |
286 | 0 | bits += 2 & mask; |
287 | 0 | l = constant_time_select_w(mask, l >> 2, l); |
288 | |
|
289 | 0 | mask = constant_time_is_zero_w(l << (BN_BITS2 - 1)); |
290 | 0 | bits += 1 & mask; |
291 | |
|
292 | 0 | return bits; |
293 | 0 | } |
294 | | |
295 | 0 | int BN_count_low_zero_bits(const BIGNUM *bn) { |
296 | 0 | static_assert(sizeof(BN_ULONG) <= sizeof(crypto_word_t), |
297 | 0 | "crypto_word_t is too small"); |
298 | 0 | static_assert(sizeof(int) <= sizeof(crypto_word_t), |
299 | 0 | "crypto_word_t is too small"); |
300 | |
|
301 | 0 | int ret = 0; |
302 | 0 | crypto_word_t saw_nonzero = 0; |
303 | 0 | for (int i = 0; i < bn->width; i++) { |
304 | 0 | crypto_word_t nonzero = ~constant_time_is_zero_w(bn->d[i]); |
305 | 0 | crypto_word_t first_nonzero = ~saw_nonzero & nonzero; |
306 | 0 | saw_nonzero |= nonzero; |
307 | |
|
308 | 0 | int bits = bn_count_low_zero_bits_word(bn->d[i]); |
309 | 0 | ret |= first_nonzero & (i * BN_BITS2 + bits); |
310 | 0 | } |
311 | | |
312 | | // If got to the end of |bn| and saw no non-zero words, |bn| is zero. |ret| |
313 | | // will then remain zero. |
314 | 0 | return ret; |
315 | 0 | } |