23 #include "BigNumberUtil.h"
24 #include "utility/EndianUtil.h"
25 #include "utility/LimbUtil.h"
56 const uint8_t *bytes,
size_t len)
58 #if BIGNUMBER_LIMB_8BIT
60 memcpy(limbs, bytes, len);
61 memset(limbs + len, 0, count - len);
63 memcpy(limbs, bytes, count);
65 #elif CRYPTO_LITTLE_ENDIAN
66 count *=
sizeof(limb_t);
68 memcpy(limbs, bytes, len);
69 memset(((uint8_t *)limbs) + len, 0, count - len);
71 memcpy(limbs, bytes, count);
73 #elif BIGNUMBER_LIMB_16BIT
74 while (count > 0 && len >= 2) {
75 *limbs++ = ((limb_t)(bytes[0])) |
76 (((limb_t)(bytes[1])) << 8);
81 if (count > 0 && len == 1) {
82 *limbs++ = ((limb_t)(bytes[0]));
89 #elif BIGNUMBER_LIMB_32BIT
90 while (count > 0 && len >= 4) {
91 *limbs++ = ((limb_t)(bytes[0])) |
92 (((limb_t)(bytes[1])) << 8) |
93 (((limb_t)(bytes[2])) << 16) |
94 (((limb_t)(bytes[3])) << 24);
99 if (count > 0 && len > 0) {
101 *limbs++ = ((limb_t)(bytes[0])) |
102 (((limb_t)(bytes[1])) << 8) |
103 (((limb_t)(bytes[2])) << 16);
104 }
else if (len == 2) {
105 *limbs++ = ((limb_t)(bytes[0])) |
106 (((limb_t)(bytes[1])) << 8);
108 *limbs++ = ((limb_t)(bytes[0]));
116 #elif BIGNUMBER_LIMB_64BIT
117 while (count > 0 && len >= 8) {
118 *limbs++ = ((limb_t)(bytes[0])) |
119 (((limb_t)(bytes[1])) << 8) |
120 (((limb_t)(bytes[2])) << 16) |
121 (((limb_t)(bytes[3])) << 24) |
122 (((limb_t)(bytes[4])) << 32) |
123 (((limb_t)(bytes[5])) << 40) |
124 (((limb_t)(bytes[6])) << 48) |
125 (((limb_t)(bytes[7])) << 56);
130 if (count > 0 && len > 0) {
133 while (len > 0 && shift < 64) {
134 word |= (((limb_t)(*bytes++)) << shift);
164 const uint8_t *bytes,
size_t len)
166 #if BIGNUMBER_LIMB_8BIT
167 while (count > 0 && len > 0) {
170 *limbs++ = bytes[len];
172 memset(limbs, 0, count);
173 #elif BIGNUMBER_LIMB_16BIT
175 while (count > 0 && len >= 2) {
179 *limbs++ = ((limb_t)(bytes[1])) |
180 (((limb_t)(bytes[0])) << 8);
182 if (count > 0 && len == 1) {
185 *limbs++ = (limb_t)(bytes[0]);
187 memset(limbs, 0, count *
sizeof(limb_t));
188 #elif BIGNUMBER_LIMB_32BIT
190 while (count > 0 && len >= 4) {
194 *limbs++ = ((limb_t)(bytes[3])) |
195 (((limb_t)(bytes[2])) << 8) |
196 (((limb_t)(bytes[1])) << 16) |
197 (((limb_t)(bytes[0])) << 24);
203 *limbs++ = ((limb_t)(bytes[2])) |
204 (((limb_t)(bytes[1])) << 8) |
205 (((limb_t)(bytes[0])) << 16);
206 }
else if (len == 2) {
209 *limbs++ = ((limb_t)(bytes[1])) |
210 (((limb_t)(bytes[0])) << 8);
211 }
else if (len == 1) {
214 *limbs++ = (limb_t)(bytes[0]);
217 memset(limbs, 0, count *
sizeof(limb_t));
218 #elif BIGNUMBER_LIMB_64BIT
220 while (count > 0 && len >= 8) {
224 *limbs++ = ((limb_t)(bytes[7])) |
225 (((limb_t)(bytes[6])) << 8) |
226 (((limb_t)(bytes[5])) << 16) |
227 (((limb_t)(bytes[4])) << 24) |
228 (((limb_t)(bytes[3])) << 32) |
229 (((limb_t)(bytes[2])) << 40) |
230 (((limb_t)(bytes[1])) << 48) |
231 (((limb_t)(bytes[0])) << 56);
233 if (count > 0 && len > 0) {
236 while (len > 0 && shift < 64) {
237 word |= (((limb_t)(*(--bytes))) << shift);
244 memset(limbs, 0, count *
sizeof(limb_t));
265 const limb_t *limbs,
size_t count)
267 #if BIGNUMBER_LIMB_8BIT
269 memcpy(bytes, limbs, len);
271 memcpy(bytes, limbs, count);
272 memset(bytes + count, 0, len - count);
274 #elif CRYPTO_LITTLE_ENDIAN
275 count *=
sizeof(limb_t);
277 memcpy(bytes, limbs, len);
279 memcpy(bytes, limbs, count);
280 memset(bytes + count, 0, len - count);
282 #elif BIGNUMBER_LIMB_16BIT
284 while (count > 0 && len >= 2) {
286 bytes[0] = (uint8_t)word;
287 bytes[1] = (uint8_t)(word >> 8);
292 if (count > 0 && len == 1) {
293 bytes[0] = (uint8_t)(*limbs);
297 memset(bytes, 0, len);
298 #elif BIGNUMBER_LIMB_32BIT
300 while (count > 0 && len >= 4) {
302 bytes[0] = (uint8_t)word;
303 bytes[1] = (uint8_t)(word >> 8);
304 bytes[2] = (uint8_t)(word >> 16);
305 bytes[3] = (uint8_t)(word >> 24);
313 bytes[0] = (uint8_t)word;
314 bytes[1] = (uint8_t)(word >> 8);
315 bytes[2] = (uint8_t)(word >> 16);
318 }
else if (len == 2) {
320 bytes[0] = (uint8_t)word;
321 bytes[1] = (uint8_t)(word >> 8);
324 }
else if (len == 1) {
325 bytes[0] = (uint8_t)(*limbs);
330 memset(bytes, 0, len);
331 #elif BIGNUMBER_LIMB_64BIT
333 while (count > 0 && len >= 8) {
335 bytes[0] = (uint8_t)word;
336 bytes[1] = (uint8_t)(word >> 8);
337 bytes[2] = (uint8_t)(word >> 16);
338 bytes[3] = (uint8_t)(word >> 24);
339 bytes[4] = (uint8_t)(word >> 32);
340 bytes[5] = (uint8_t)(word >> 40);
341 bytes[6] = (uint8_t)(word >> 48);
342 bytes[7] = (uint8_t)(word >> 56);
350 *bytes++ = (uint8_t)word;
355 memset(bytes, 0, len);
376 const limb_t *limbs,
size_t count)
378 #if BIGNUMBER_LIMB_8BIT
380 size_t size = len - count;
381 memset(bytes, 0, size);
384 }
else if (len < count) {
390 *bytes++ = *(--limbs);
392 #elif BIGNUMBER_LIMB_16BIT
393 size_t countBytes = count *
sizeof(limb_t);
395 if (len >= countBytes) {
396 size_t size = len - countBytes;
397 memset(bytes, 0, size);
402 count = len /
sizeof(limb_t);
405 *bytes++ = (uint8_t)(*limbs);
410 *bytes++ = (uint8_t)(word >> 8);
411 *bytes++ = (uint8_t)word;
413 #elif BIGNUMBER_LIMB_32BIT
414 size_t countBytes = count *
sizeof(limb_t);
416 if (len >= countBytes) {
417 size_t size = len - countBytes;
418 memset(bytes, 0, size);
423 count = len /
sizeof(limb_t);
425 if ((len & 3) == 3) {
427 *bytes++ = (uint8_t)(word >> 16);
428 *bytes++ = (uint8_t)(word >> 8);
429 *bytes++ = (uint8_t)word;
430 }
else if ((len & 3) == 2) {
432 *bytes++ = (uint8_t)(word >> 8);
433 *bytes++ = (uint8_t)word;
434 }
else if ((len & 3) == 1) {
435 *bytes++ = (uint8_t)(*limbs);
441 *bytes++ = (uint8_t)(word >> 24);
442 *bytes++ = (uint8_t)(word >> 16);
443 *bytes++ = (uint8_t)(word >> 8);
444 *bytes++ = (uint8_t)word;
446 #elif BIGNUMBER_LIMB_64BIT
447 size_t countBytes = count *
sizeof(limb_t);
449 if (len >= countBytes) {
450 size_t size = len - countBytes;
451 memset(bytes, 0, size);
456 count = len /
sizeof(limb_t);
458 uint8_t size = len & 7;
459 uint8_t shift = size * 8;
463 *bytes++ = (uint8_t)(word >> shift);
470 *bytes++ = (uint8_t)(word >> 56);
471 *bytes++ = (uint8_t)(word >> 48);
472 *bytes++ = (uint8_t)(word >> 40);
473 *bytes++ = (uint8_t)(word >> 32);
474 *bytes++ = (uint8_t)(word >> 24);
475 *bytes++ = (uint8_t)(word >> 16);
476 *bytes++ = (uint8_t)(word >> 8);
477 *bytes++ = (uint8_t)word;
496 const limb_t *y,
size_t size)
502 *result++ = (limb_t)carry;
506 return (limb_t)carry;
523 const limb_t *y,
size_t size)
527 borrow = ((dlimb_t)(*x++)) - (*y++) - ((borrow >> LIMB_BITS) & 0x01);
528 *result++ = (limb_t)borrow;
531 return ((limb_t)(borrow >> LIMB_BITS)) & 0x01;
547 const limb_t *y,
size_t ycount)
560 for (i = 0; i < xcount; ++i) {
561 carry += ((dlimb_t)(*xx++)) * word;
562 *rr++ = (limb_t)carry;
568 for (i = 1; i < ycount; ++i) {
573 for (j = 0; j < xcount; ++j) {
574 carry += ((dlimb_t)(*xx++)) * word;
576 *rr++ = (limb_t)carry;
599 const limb_t *y,
size_t size)
602 limb_t mask =
sub(result, x, y, size);
609 carry += (*y++ & mask);
610 *result++ = (limb_t)carry;
629 const limb_t *y,
size_t size)
634 carry += pgm_read_limb(y++);
635 *result++ = (limb_t)carry;
639 return (limb_t)carry;
656 const limb_t *y,
size_t size)
660 borrow = ((dlimb_t)(*x++)) - pgm_read_limb(y++) - ((borrow >> LIMB_BITS) & 0x01);
661 *result++ = (limb_t)borrow;
664 return ((limb_t)(borrow >> LIMB_BITS)) & 0x01;
681 const limb_t *y,
size_t ycount)
691 word = pgm_read_limb(&(y[0]));
694 for (i = 0; i < xcount; ++i) {
695 carry += ((dlimb_t)(*xx++)) * word;
696 *rr++ = (limb_t)carry;
702 for (i = 1; i < ycount; ++i) {
703 word = pgm_read_limb(&(y[i]));
707 for (j = 0; j < xcount; ++j) {
708 carry += ((dlimb_t)(*xx++)) * word;
710 *rr++ = (limb_t)carry;
735 const limb_t *y,
size_t size)
738 limb_t mask =
sub_P(result, x, y, size);
745 carry += (pgm_read_limb(y++) & mask);
746 *result++ = (limb_t)carry;
768 return (limb_t)(((((dlimb_t)1) << LIMB_BITS) - word) >> LIMB_BITS);
static void reduceQuick_P(limb_t *result, const limb_t *x, const limb_t *y, size_t size)
Reduces x modulo y using subtraction where y is in program memory.
static void mul(limb_t *result, const limb_t *x, size_t xcount, const limb_t *y, size_t ycount)
Multiplies two big numbers.
static void unpackLE(limb_t *limbs, size_t count, const uint8_t *bytes, size_t len)
Unpacks the little-endian byte representation of a big number into a limb array.
static void reduceQuick(limb_t *result, const limb_t *x, const limb_t *y, size_t size)
Reduces x modulo y using subtraction.
static void unpackBE(limb_t *limbs, size_t count, const uint8_t *bytes, size_t len)
Unpacks the big-endian byte representation of a big number into a limb array.
static limb_t sub(limb_t *result, const limb_t *x, const limb_t *y, size_t size)
Subtracts one big number from another.
static void packLE(uint8_t *bytes, size_t len, const limb_t *limbs, size_t count)
Packs the little-endian byte representation of a big number into a byte array.
static limb_t add(limb_t *result, const limb_t *x, const limb_t *y, size_t size)
Adds two big numbers.
static void mul_P(limb_t *result, const limb_t *x, size_t xcount, const limb_t *y, size_t ycount)
Multiplies two big numbers where one is in program memory.
static limb_t add_P(limb_t *result, const limb_t *x, const limb_t *y, size_t size)
Adds two big numbers where one of them is in program memory.
static limb_t isZero(const limb_t *x, size_t size)
Determine if a big number is zero.
static limb_t sub_P(limb_t *result, const limb_t *x, const limb_t *y, size_t size)
Subtracts one big number from another where one is in program memory.
static void packBE(uint8_t *bytes, size_t len, const limb_t *limbs, size_t count)
Packs the big-endian byte representation of a big number into a byte array.