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