Botan 3.0.0-alpha0
Crypto and TLS for C&
nistp_redc.cpp
Go to the documentation of this file.
1/*
2* NIST prime reductions
3* (C) 2014,2015,2018 Jack Lloyd
4*
5* Botan is released under the Simplified BSD License (see license.txt)
6*/
7
8#include <botan/internal/curve_nistp.h>
9#include <botan/internal/mp_core.h>
10#include <botan/internal/ct_utils.h>
11
12namespace Botan {
13
15 {
16 static const BigInt p521("0x1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
17 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
18
19 return p521;
20 }
21
23 {
25
26 const size_t p_full_words = 521 / BOTAN_MP_WORD_BITS;
27 const size_t p_top_bits = 521 % BOTAN_MP_WORD_BITS;
28 const size_t p_words = p_full_words + 1;
29
30#if (BOTAN_MP_WORD_BITS == 64)
31 static const word p521_words[p_words] = {
32 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF,
33 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF,
34 0x1FF };
35#else
36 static const word p521_words[p_words] = {
37 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
38 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
39 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
40 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
41 0x1FF };
42#endif
43
44 if(ws.size() < p_words + 1)
45 ws.resize(p_words + 1);
46
47 clear_mem(ws.data(), ws.size());
48 bigint_shr2(ws.data(), x.data(), std::min(x.size(), 2*p_words), p_full_words, p_top_bits);
49
50 x.mask_bits(521);
51 x.grow_to(p_words);
52
53 // Word-level carry will be zero
54 word carry = bigint_add3_nc(x.mutable_data(), x.data(), p_words, ws.data(), p_words);
55 BOTAN_ASSERT_EQUAL(carry, 0, "Final carry in P-521 reduction");
56
57 const word top_word = x.word_at(p_full_words);
58
59 /*
60 * Check if we need to reduce modulo P
61 * There are two possible cases:
62 * - The result overflowed past 521 bits, in which case bit 522 will be set
63 * - The result is exactly 2**521 - 1
64 */
65 const auto bit_522_set = CT::Mask<word>::expand(top_word >> p_top_bits);
66
67 word and_512 = MP_WORD_MAX;
68 for(size_t i = 0; i != p_full_words; ++i)
69 and_512 &= x.word_at(i);
70 const auto all_512_low_bits_set = CT::Mask<word>::is_equal(and_512, MP_WORD_MAX);
71 const auto has_p521_top_word = CT::Mask<word>::is_equal(top_word, 0x1FF);
72 const auto is_p521 = all_512_low_bits_set & has_p521_top_word;
73
74 const auto needs_reduction = is_p521 | bit_522_set;
75
76 bigint_cnd_sub(needs_reduction.value(), x.mutable_data(), p521_words, p_words);
77 }
78
79namespace {
80
81/**
82* Treating this MPI as a sequence of 32-bit words in big-endian
83* order, return word i. The array is assumed to be large enough.
84*/
85inline uint32_t get_uint32(const word xw[], size_t i)
86 {
87#if (BOTAN_MP_WORD_BITS == 32)
88 return xw[i];
89#else
90 return static_cast<uint32_t>(xw[i/2] >> ((i % 2)*32));
91#endif
92 }
93
94inline void set_words(word x[], size_t i, uint32_t R0, uint32_t R1)
95 {
96#if (BOTAN_MP_WORD_BITS == 32)
97 x[i] = R0;
98 x[i+1] = R1;
99#else
100 x[i/2] = (static_cast<uint64_t>(R1) << 32) | R0;
101#endif
102 }
103
104}
105
107 {
108 static const BigInt p192("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF");
109 return p192;
110 }
111
113 {
115
116 BOTAN_UNUSED(ws);
117
118 static const size_t p192_limbs = 192 / BOTAN_MP_WORD_BITS;
119
120 x.grow_to(2*p192_limbs);
121 word* xw = x.mutable_data();
122
123 const uint64_t X00 = get_uint32(xw, 0);
124 const uint64_t X01 = get_uint32(xw, 1);
125 const uint64_t X02 = get_uint32(xw, 2);
126 const uint64_t X03 = get_uint32(xw, 3);
127 const uint64_t X04 = get_uint32(xw, 4);
128 const uint64_t X05 = get_uint32(xw, 5);
129 const uint64_t X06 = get_uint32(xw, 6);
130 const uint64_t X07 = get_uint32(xw, 7);
131 const uint64_t X08 = get_uint32(xw, 8);
132 const uint64_t X09 = get_uint32(xw, 9);
133 const uint64_t X10 = get_uint32(xw, 10);
134 const uint64_t X11 = get_uint32(xw, 11);
135
136 const uint64_t S0 = X00 + X06 + X10;
137 const uint64_t S1 = X01 + X07 + X11;
138 const uint64_t S2 = X02 + X06 + X08 + X10;
139 const uint64_t S3 = X03 + X07 + X09 + X11;
140 const uint64_t S4 = X04 + X08 + X10;
141 const uint64_t S5 = X05 + X09 + X11;
142
143 uint64_t S = 0;
144 uint32_t R0 = 0, R1 = 0;
145
146 S += S0;
147 R0 = static_cast<uint32_t>(S);
148 S >>= 32;
149
150 S += S1;
151 R1 = static_cast<uint32_t>(S);
152 S >>= 32;
153
154 set_words(xw, 0, R0, R1);
155
156 S += S2;
157 R0 = static_cast<uint32_t>(S);
158 S >>= 32;
159
160 S += S3;
161 R1 = static_cast<uint32_t>(S);
162 S >>= 32;
163
164 set_words(xw, 2, R0, R1);
165
166 S += S4;
167 R0 = static_cast<uint32_t>(S);
168 S >>= 32;
169
170 S += S5;
171 R1 = static_cast<uint32_t>(S);
172 S >>= 32;
173
174 set_words(xw, 4, R0, R1);
175
176 // No underflow possible
177
178 /*
179 This is a table of (i*P-192) % 2**192 for i in 1...3
180 */
181 static const word p192_mults[3][p192_limbs] = {
182#if (BOTAN_MP_WORD_BITS == 64)
183 {0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFE, 0xFFFFFFFFFFFFFFFF},
184 {0xFFFFFFFFFFFFFFFE, 0xFFFFFFFFFFFFFFFD, 0xFFFFFFFFFFFFFFFF},
185 {0xFFFFFFFFFFFFFFFD, 0xFFFFFFFFFFFFFFFC, 0xFFFFFFFFFFFFFFFF},
186#else
187 {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
188 {0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
189 {0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFC, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
190#endif
191 };
192
193 CT::unpoison(S);
194 BOTAN_ASSERT(S <= 2, "Expected overflow");
195
196 BOTAN_ASSERT_NOMSG(x.size() >= p192_limbs + 1);
197 x.mask_bits(192);
198 word borrow = bigint_sub2(x.mutable_data(), p192_limbs + 1, p192_mults[S], p192_limbs);
199 BOTAN_DEBUG_ASSERT(borrow == 0 || borrow == 1);
200 bigint_cnd_add(borrow, x.mutable_data(), p192_limbs + 1, p192_mults[0], p192_limbs);
201 }
202
204 {
205 static const BigInt p224("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001");
206 return p224;
207 }
208
210 {
212
213 static const size_t p224_limbs = (BOTAN_MP_WORD_BITS == 32) ? 7 : 4;
214
215 BOTAN_UNUSED(ws);
216
217 x.grow_to(2*p224_limbs);
218 word* xw = x.mutable_data();
219
220 const int64_t X00 = get_uint32(xw, 0);
221 const int64_t X01 = get_uint32(xw, 1);
222 const int64_t X02 = get_uint32(xw, 2);
223 const int64_t X03 = get_uint32(xw, 3);
224 const int64_t X04 = get_uint32(xw, 4);
225 const int64_t X05 = get_uint32(xw, 5);
226 const int64_t X06 = get_uint32(xw, 6);
227 const int64_t X07 = get_uint32(xw, 7);
228 const int64_t X08 = get_uint32(xw, 8);
229 const int64_t X09 = get_uint32(xw, 9);
230 const int64_t X10 = get_uint32(xw, 10);
231 const int64_t X11 = get_uint32(xw, 11);
232 const int64_t X12 = get_uint32(xw, 12);
233 const int64_t X13 = get_uint32(xw, 13);
234
235 // One full copy of P224 is added, so the result is always positive
236
237 const int64_t S0 = 0x00000001 + X00 - X07 - X11;
238 const int64_t S1 = 0x00000000 + X01 - X08 - X12;
239 const int64_t S2 = 0x00000000 + X02 - X09 - X13;
240 const int64_t S3 = 0xFFFFFFFF + X03 + X07 + X11 - X10;
241 const int64_t S4 = 0xFFFFFFFF + X04 + X08 + X12 - X11;
242 const int64_t S5 = 0xFFFFFFFF + X05 + X09 + X13 - X12;
243 const int64_t S6 = 0xFFFFFFFF + X06 + X10 - X13;
244
245 int64_t S = 0;
246 uint32_t R0 = 0, R1 = 0;
247
248 S += S0;
249 R0 = static_cast<uint32_t>(S);
250 S >>= 32;
251
252 S += S1;
253 R1 = static_cast<uint32_t>(S);
254 S >>= 32;
255
256 set_words(xw, 0, R0, R1);
257
258 S += S2;
259 R0 = static_cast<uint32_t>(S);
260 S >>= 32;
261
262 S += S3;
263 R1 = static_cast<uint32_t>(S);
264 S >>= 32;
265
266 set_words(xw, 2, R0, R1);
267
268 S += S4;
269 R0 = static_cast<uint32_t>(S);
270 S >>= 32;
271
272 S += S5;
273 R1 = static_cast<uint32_t>(S);
274 S >>= 32;
275
276 set_words(xw, 4, R0, R1);
277
278 S += S6;
279 R0 = static_cast<uint32_t>(S);
280 S >>= 32;
281
282 set_words(xw, 6, R0, 0);
283
284 static const word p224_mults[3][p224_limbs] = {
285#if (BOTAN_MP_WORD_BITS == 64)
286 {0x0000000000000001, 0xFFFFFFFF00000000, 0xFFFFFFFFFFFFFFFF, 0x00000000FFFFFFFF},
287 {0x0000000000000002, 0xFFFFFFFE00000000, 0xFFFFFFFFFFFFFFFF, 0x00000000FFFFFFFF},
288 {0x0000000000000003, 0xFFFFFFFD00000000, 0xFFFFFFFFFFFFFFFF, 0x00000000FFFFFFFF},
289#else
290 {0x00000001, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
291 {0x00000002, 0x00000000, 0x00000000, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
292 {0x00000003, 0x00000000, 0x00000000, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}
293#endif
294
295 };
296
297 CT::unpoison(S);
298 BOTAN_ASSERT(S >= 0 && S <= 2, "Expected overflow");
299
300 BOTAN_ASSERT_NOMSG(x.size() >= p224_limbs + 1);
301 x.mask_bits(224);
302 word borrow = bigint_sub2(x.mutable_data(), p224_limbs + 1, p224_mults[S], p224_limbs);
303 BOTAN_DEBUG_ASSERT(borrow == 0 || borrow == 1);
304 bigint_cnd_add(borrow, x.mutable_data(), p224_limbs + 1, p224_mults[0], p224_limbs);
305 }
306
308 {
309 static const BigInt p256("0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF");
310 return p256;
311 }
312
314 {
316
317 static const size_t p256_limbs = (BOTAN_MP_WORD_BITS == 32) ? 8 : 4;
318
319 BOTAN_UNUSED(ws);
320
321 x.grow_to(2*p256_limbs);
322 word* xw = x.mutable_data();
323
324 const int64_t X00 = get_uint32(xw, 0);
325 const int64_t X01 = get_uint32(xw, 1);
326 const int64_t X02 = get_uint32(xw, 2);
327 const int64_t X03 = get_uint32(xw, 3);
328 const int64_t X04 = get_uint32(xw, 4);
329 const int64_t X05 = get_uint32(xw, 5);
330 const int64_t X06 = get_uint32(xw, 6);
331 const int64_t X07 = get_uint32(xw, 7);
332 const int64_t X08 = get_uint32(xw, 8);
333 const int64_t X09 = get_uint32(xw, 9);
334 const int64_t X10 = get_uint32(xw, 10);
335 const int64_t X11 = get_uint32(xw, 11);
336 const int64_t X12 = get_uint32(xw, 12);
337 const int64_t X13 = get_uint32(xw, 13);
338 const int64_t X14 = get_uint32(xw, 14);
339 const int64_t X15 = get_uint32(xw, 15);
340
341 // Adds 6 * P-256 to prevent underflow
342 const int64_t S0 = 0xFFFFFFFA + X00 + X08 + X09 - (X11 + X12 + X13) - X14;
343 const int64_t S1 = 0xFFFFFFFF + X01 + X09 + X10 - X12 - (X13 + X14 + X15);
344 const int64_t S2 = 0xFFFFFFFF + X02 + X10 + X11 - (X13 + X14 + X15);
345 const int64_t S3 = 0x00000005 + X03 + (X11 + X12)*2 + X13 - X15 - X08 - X09;
346 const int64_t S4 = 0x00000000 + X04 + (X12 + X13)*2 + X14 - X09 - X10;
347 const int64_t S5 = 0x00000000 + X05 + (X13 + X14)*2 + X15 - X10 - X11;
348 const int64_t S6 = 0x00000006 + X06 + X13 + X14*3 + X15*2 - X08 - X09;
349 const int64_t S7 = 0xFFFFFFFA + X07 + X15*3 + X08 - X10 - (X11 + X12 + X13);
350
351 int64_t S = 0;
352
353 uint32_t R0 = 0, R1 = 0;
354
355 S += S0;
356 R0 = static_cast<uint32_t>(S);
357 S >>= 32;
358
359 S += S1;
360 R1 = static_cast<uint32_t>(S);
361 S >>= 32;
362
363 set_words(xw, 0, R0, R1);
364
365 S += S2;
366 R0 = static_cast<uint32_t>(S);
367 S >>= 32;
368
369 S += S3;
370 R1 = static_cast<uint32_t>(S);
371 S >>= 32;
372
373 set_words(xw, 2, R0, R1);
374
375 S += S4;
376 R0 = static_cast<uint32_t>(S);
377 S >>= 32;
378
379 S += S5;
380 R1 = static_cast<uint32_t>(S);
381 S >>= 32;
382
383 set_words(xw, 4, R0, R1);
384
385 S += S6;
386 R0 = static_cast<uint32_t>(S);
387 S >>= 32;
388
389 S += S7;
390 R1 = static_cast<uint32_t>(S);
391 S >>= 32;
392 set_words(xw, 6, R0, R1);
393
394 S += 5; // the top digits of 6*P-256
395
396 /*
397 This is a table of (i*P-256) % 2**256 for i in 1...10
398 */
399 static const word p256_mults[11][p256_limbs] = {
400#if (BOTAN_MP_WORD_BITS == 64)
401 {0xFFFFFFFFFFFFFFFF, 0x00000000FFFFFFFF, 0x0000000000000000, 0xFFFFFFFF00000001},
402 {0xFFFFFFFFFFFFFFFE, 0x00000001FFFFFFFF, 0x0000000000000000, 0xFFFFFFFE00000002},
403 {0xFFFFFFFFFFFFFFFD, 0x00000002FFFFFFFF, 0x0000000000000000, 0xFFFFFFFD00000003},
404 {0xFFFFFFFFFFFFFFFC, 0x00000003FFFFFFFF, 0x0000000000000000, 0xFFFFFFFC00000004},
405 {0xFFFFFFFFFFFFFFFB, 0x00000004FFFFFFFF, 0x0000000000000000, 0xFFFFFFFB00000005},
406 {0xFFFFFFFFFFFFFFFA, 0x00000005FFFFFFFF, 0x0000000000000000, 0xFFFFFFFA00000006},
407 {0xFFFFFFFFFFFFFFF9, 0x00000006FFFFFFFF, 0x0000000000000000, 0xFFFFFFF900000007},
408 {0xFFFFFFFFFFFFFFF8, 0x00000007FFFFFFFF, 0x0000000000000000, 0xFFFFFFF800000008},
409 {0xFFFFFFFFFFFFFFF7, 0x00000008FFFFFFFF, 0x0000000000000000, 0xFFFFFFF700000009},
410 {0xFFFFFFFFFFFFFFF6, 0x00000009FFFFFFFF, 0x0000000000000000, 0xFFFFFFF60000000A},
411 {0xFFFFFFFFFFFFFFF5, 0x0000000AFFFFFFFF, 0x0000000000000000, 0xFFFFFFF50000000B},
412#else
413 {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0xFFFFFFFF},
414 {0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000001, 0x00000000, 0x00000000, 0x00000002, 0xFFFFFFFE},
415 {0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000002, 0x00000000, 0x00000000, 0x00000003, 0xFFFFFFFD},
416 {0xFFFFFFFC, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000003, 0x00000000, 0x00000000, 0x00000004, 0xFFFFFFFC},
417 {0xFFFFFFFB, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000004, 0x00000000, 0x00000000, 0x00000005, 0xFFFFFFFB},
418 {0xFFFFFFFA, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000005, 0x00000000, 0x00000000, 0x00000006, 0xFFFFFFFA},
419 {0xFFFFFFF9, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000006, 0x00000000, 0x00000000, 0x00000007, 0xFFFFFFF9},
420 {0xFFFFFFF8, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000007, 0x00000000, 0x00000000, 0x00000008, 0xFFFFFFF8},
421 {0xFFFFFFF7, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000008, 0x00000000, 0x00000000, 0x00000009, 0xFFFFFFF7},
422 {0xFFFFFFF6, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000009, 0x00000000, 0x00000000, 0x0000000A, 0xFFFFFFF6},
423 {0xFFFFFFF5, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000000A, 0x00000000, 0x00000000, 0x0000000B, 0xFFFFFFF5},
424#endif
425 };
426
427 CT::unpoison(S);
428 BOTAN_ASSERT(S >= 0 && S <= 10, "Expected overflow");
429
430 BOTAN_ASSERT_NOMSG(x.size() >= p256_limbs + 1);
431 x.mask_bits(256);
432 word borrow = bigint_sub2(x.mutable_data(), p256_limbs + 1, p256_mults[S], p256_limbs);
433 BOTAN_DEBUG_ASSERT(borrow == 0 || borrow == 1);
434 bigint_cnd_add(borrow, x.mutable_data(), p256_limbs + 1, p256_mults[0], p256_limbs);
435 }
436
438 {
439 static const BigInt p384("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF");
440 return p384;
441 }
442
444 {
446
447 BOTAN_UNUSED(ws);
448
449 static const size_t p384_limbs = (BOTAN_MP_WORD_BITS == 32) ? 12 : 6;
450
451 x.grow_to(2*p384_limbs);
452 word* xw = x.mutable_data();
453
454 const int64_t X00 = get_uint32(xw, 0);
455 const int64_t X01 = get_uint32(xw, 1);
456 const int64_t X02 = get_uint32(xw, 2);
457 const int64_t X03 = get_uint32(xw, 3);
458 const int64_t X04 = get_uint32(xw, 4);
459 const int64_t X05 = get_uint32(xw, 5);
460 const int64_t X06 = get_uint32(xw, 6);
461 const int64_t X07 = get_uint32(xw, 7);
462 const int64_t X08 = get_uint32(xw, 8);
463 const int64_t X09 = get_uint32(xw, 9);
464 const int64_t X10 = get_uint32(xw, 10);
465 const int64_t X11 = get_uint32(xw, 11);
466 const int64_t X12 = get_uint32(xw, 12);
467 const int64_t X13 = get_uint32(xw, 13);
468 const int64_t X14 = get_uint32(xw, 14);
469 const int64_t X15 = get_uint32(xw, 15);
470 const int64_t X16 = get_uint32(xw, 16);
471 const int64_t X17 = get_uint32(xw, 17);
472 const int64_t X18 = get_uint32(xw, 18);
473 const int64_t X19 = get_uint32(xw, 19);
474 const int64_t X20 = get_uint32(xw, 20);
475 const int64_t X21 = get_uint32(xw, 21);
476 const int64_t X22 = get_uint32(xw, 22);
477 const int64_t X23 = get_uint32(xw, 23);
478
479 // One copy of P-384 is added to prevent underflow
480 const int64_t S0 = 0xFFFFFFFF + X00 + X12 + X20 + X21 - X23;
481 const int64_t S1 = 0x00000000 + X01 + X13 + X22 + X23 - X12 - X20;
482 const int64_t S2 = 0x00000000 + X02 + X14 + X23 - X13 - X21;
483 const int64_t S3 = 0xFFFFFFFF + X03 + X12 + X15 + X20 + X21 - X14 - X22 - X23;
484 const int64_t S4 = 0xFFFFFFFE + X04 + X12 + X13 + X16 + X20 + X21*2 + X22 - X15 - X23*2;
485 const int64_t S5 = 0xFFFFFFFF + X05 + X13 + X14 + X17 + X21 + X22*2 + X23 - X16;
486 const int64_t S6 = 0xFFFFFFFF + X06 + X14 + X15 + X18 + X22 + X23*2 - X17;
487 const int64_t S7 = 0xFFFFFFFF + X07 + X15 + X16 + X19 + X23 - X18;
488 const int64_t S8 = 0xFFFFFFFF + X08 + X16 + X17 + X20 - X19;
489 const int64_t S9 = 0xFFFFFFFF + X09 + X17 + X18 + X21 - X20;
490 const int64_t SA = 0xFFFFFFFF + X10 + X18 + X19 + X22 - X21;
491 const int64_t SB = 0xFFFFFFFF + X11 + X19 + X20 + X23 - X22;
492
493 int64_t S = 0;
494
495 uint32_t R0 = 0, R1 = 0;
496
497 S += S0;
498 R0 = static_cast<uint32_t>(S);
499 S >>= 32;
500
501 S += S1;
502 R1 = static_cast<uint32_t>(S);
503 S >>= 32;
504
505 set_words(xw, 0, R0, R1);
506
507 S += S2;
508 R0 = static_cast<uint32_t>(S);
509 S >>= 32;
510
511 S += S3;
512 R1 = static_cast<uint32_t>(S);
513 S >>= 32;
514
515 set_words(xw, 2, R0, R1);
516
517 S += S4;
518 R0 = static_cast<uint32_t>(S);
519 S >>= 32;
520
521 S += S5;
522 R1 = static_cast<uint32_t>(S);
523 S >>= 32;
524
525 set_words(xw, 4, R0, R1);
526
527 S += S6;
528 R0 = static_cast<uint32_t>(S);
529 S >>= 32;
530
531 S += S7;
532 R1 = static_cast<uint32_t>(S);
533 S >>= 32;
534
535 set_words(xw, 6, R0, R1);
536
537 S += S8;
538 R0 = static_cast<uint32_t>(S);
539 S >>= 32;
540
541 S += S9;
542 R1 = static_cast<uint32_t>(S);
543 S >>= 32;
544
545 set_words(xw, 8, R0, R1);
546
547 S += SA;
548 R0 = static_cast<uint32_t>(S);
549 S >>= 32;
550
551 S += SB;
552 R1 = static_cast<uint32_t>(S);
553 S >>= 32;
554
555 set_words(xw, 10, R0, R1);
556
557 /*
558 This is a table of (i*P-384) % 2**384 for i in 1...4
559 */
560 static const word p384_mults[5][p384_limbs] = {
561#if (BOTAN_MP_WORD_BITS == 64)
562 {0x00000000FFFFFFFF, 0xFFFFFFFF00000000, 0xFFFFFFFFFFFFFFFE, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF},
563 {0x00000001FFFFFFFE, 0xFFFFFFFE00000000, 0xFFFFFFFFFFFFFFFD, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF},
564 {0x00000002FFFFFFFD, 0xFFFFFFFD00000000, 0xFFFFFFFFFFFFFFFC, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF},
565 {0x00000003FFFFFFFC, 0xFFFFFFFC00000000, 0xFFFFFFFFFFFFFFFB, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF},
566 {0x00000004FFFFFFFB, 0xFFFFFFFB00000000, 0xFFFFFFFFFFFFFFFA, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF},
567
568#else
569 {0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF,
570 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
571 {0xFFFFFFFE, 0x00000001, 0x00000000, 0xFFFFFFFE, 0xFFFFFFFD, 0xFFFFFFFF,
572 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
573 {0xFFFFFFFD, 0x00000002, 0x00000000, 0xFFFFFFFD, 0xFFFFFFFC, 0xFFFFFFFF,
574 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
575 {0xFFFFFFFC, 0x00000003, 0x00000000, 0xFFFFFFFC, 0xFFFFFFFB, 0xFFFFFFFF,
576 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
577 {0xFFFFFFFB, 0x00000004, 0x00000000, 0xFFFFFFFB, 0xFFFFFFFA, 0xFFFFFFFF,
578 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
579#endif
580 };
581
582 CT::unpoison(S);
583 BOTAN_ASSERT(S >= 0 && S <= 4, "Expected overflow");
584
585 BOTAN_ASSERT_NOMSG(x.size() >= p384_limbs + 1);
586 x.mask_bits(384);
587 word borrow = bigint_sub2(x.mutable_data(), p384_limbs + 1, p384_mults[S], p384_limbs);
588 BOTAN_DEBUG_ASSERT(borrow == 0 || borrow == 1);
589 bigint_cnd_add(borrow, x.mutable_data(), p384_limbs + 1, p384_mults[0], p384_limbs);
590 }
591
592}
#define BOTAN_ASSERT_NOMSG(expr)
Definition: assert.h:67
#define BOTAN_DEBUG_ASSERT(expr)
Definition: assert.h:122
#define BOTAN_UNUSED(...)
Definition: assert.h:141
#define BOTAN_ASSERT_EQUAL(expr1, expr2, assertion_made)
Definition: assert.h:80
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:54
word * mutable_data()
Definition: bigint.h:628
size_t size() const
Definition: bigint.h:594
void grow_to(size_t n) const
Definition: bigint.h:650
const word * data() const
Definition: bigint.h:634
word word_at(size_t n) const
Definition: bigint.h:522
void mask_bits(size_t n)
Definition: bigint.h:469
bool is_positive() const
Definition: bigint.h:547
static Mask< T > is_equal(T x, T y)
Definition: ct_utils.h:147
static Mask< T > expand(T v)
Definition: ct_utils.h:121
#define BOTAN_MP_WORD_BITS
Definition: build.h:52
void unpoison(const T *p, size_t n)
Definition: ct_utils.h:58
Definition: alg_id.cpp:13
BOTAN_TEST_API void redc_p521(BigInt &x, secure_vector< word > &ws)
Definition: nistp_redc.cpp:22
const word MP_WORD_MAX
Definition: mp_core.h:22
word bigint_sub2(word x[], size_t x_size, const word y[], size_t y_size)
Definition: mp_core.h:300
BOTAN_TEST_API void redc_p192(BigInt &x, secure_vector< word > &ws)
Definition: nistp_redc.cpp:112
BOTAN_TEST_API void redc_p256(BigInt &x, secure_vector< word > &ws)
Definition: nistp_redc.cpp:313
word bigint_cnd_add(word cnd, word x[], word x_size, const word y[], size_t y_size)
Definition: mp_core.h:42
word bigint_cnd_sub(word cnd, word x[], size_t x_size, const word y[], size_t y_size)
Definition: mp_core.h:88
BOTAN_TEST_API void redc_p224(BigInt &x, secure_vector< word > &ws)
Definition: nistp_redc.cpp:209
BOTAN_TEST_API const BigInt & prime_p384()
Definition: nistp_redc.cpp:437
void carry(int64_t &h0, int64_t &h1)
BOTAN_TEST_API const BigInt & prime_p224()
Definition: nistp_redc.cpp:203
BOTAN_TEST_API void redc_p384(BigInt &x, secure_vector< word > &ws)
Definition: nistp_redc.cpp:443
void bigint_shr2(word y[], const word x[], size_t x_size, size_t word_shift, size_t bit_shift)
Definition: mp_core.h:466
BOTAN_TEST_API const BigInt & prime_p256()
Definition: nistp_redc.cpp:307
word bigint_add3_nc(word z[], const word x[], size_t x_size, const word y[], size_t y_size)
Definition: mp_core.h:250
BOTAN_TEST_API const BigInt & prime_p192()
Definition: nistp_redc.cpp:106
BOTAN_TEST_API const BigInt & prime_p521()
Definition: nistp_redc.cpp:14
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:65
constexpr void clear_mem(T *ptr, size_t n)
Definition: mem_ops.h:115