23 #include "Curve25519.h"
26 #include "utility/ProgMemUtil.h"
44 #define NUM_LIMBS (32 / sizeof(limb_t))
47 #define LIMB_BITS (8 * sizeof(limb_t))
70 limb_t x_1[NUM_LIMBS];
71 limb_t x_2[NUM_LIMBS];
72 limb_t x_3[NUM_LIMBS];
73 limb_t z_2[NUM_LIMBS];
74 limb_t z_3[NUM_LIMBS];
95 memset(x_1, 0,
sizeof(x_1));
106 retval = (bool)(reduceQuick(x_1) & 0x01);
109 memset(x_2, 0,
sizeof(x_2));
111 memset(z_2, 0,
sizeof(z_2));
112 memcpy(x_3, x_1,
sizeof(x_1));
113 memcpy(z_3, x_2,
sizeof(x_2));
120 for (uint8_t t = 255; t > 0; --t) {
123 select = s[sposn] & mask;
125 cswap(swap, x_2, x_3);
126 cswap(swap, z_2, z_3);
160 cswap(swap, x_2, x_3);
161 cswap(swap, z_2, z_3);
240 f[31] = (f[31] & 0x7F) | 0x40;
251 }
while (isWeakPoint(k));
279 weak = isWeakPoint(k);
280 weak |= ((
eval(k, f, k) ^ 0x01) & 0x01);
281 weak |= isWeakPoint(k);
283 return (
bool)((weak ^ 0x01) & 0x01);
293 uint8_t Curve25519::isWeakPoint(
const uint8_t k[32])
299 static const uint8_t points[5][32] PROGMEM = {
300 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
301 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
302 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
303 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
304 {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
305 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
306 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
307 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
308 {0xE0, 0xEB, 0x7A, 0x7C, 0x3B, 0x41, 0xB8, 0xAE,
309 0x16, 0x56, 0xE3, 0xFA, 0xF1, 0x9F, 0xC4, 0x6A,
310 0xDA, 0x09, 0x8D, 0xEB, 0x9C, 0x32, 0xB1, 0xFD,
311 0x86, 0x62, 0x05, 0x16, 0x5F, 0x49, 0xB8, 0x00},
312 {0x5F, 0x9C, 0x95, 0xBC, 0xA3, 0x50, 0x8C, 0x24,
313 0xB1, 0xD0, 0xB1, 0x55, 0x9C, 0x83, 0xEF, 0x5B,
314 0x04, 0x44, 0x5C, 0xC4, 0x58, 0x1C, 0x8E, 0x86,
315 0xD8, 0x22, 0x4E, 0xDD, 0xD0, 0x9F, 0x11, 0x57},
316 {0xEC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
317 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
318 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
319 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F}
328 for (uint8_t posn = 0; posn < 5; ++posn) {
329 const uint8_t *point = points[posn];
330 uint8_t check = (pgm_read_byte(point + 31) ^ k[31]) & 0x7F;
331 for (uint8_t index = 31; index > 0; --index)
332 check |= (pgm_read_byte(point + index - 1) ^ k[index - 1]);
333 result |= (uint8_t)((((uint16_t)0x0100) - check) >> 8);
352 void Curve25519::reduce(limb_t *result, limb_t *x, uint8_t size)
401 carry = ((dlimb_t)(x[NUM_LIMBS - 1] >> (LIMB_BITS - 1))) * 19U;
402 x[NUM_LIMBS - 1] &= ((((limb_t)1) << (LIMB_BITS - 1)) - 1);
403 for (posn = 0; posn < size; ++posn) {
404 carry += ((dlimb_t)(x[posn + NUM_LIMBS])) * 38U;
406 x[posn] = (limb_t)carry;
409 if (size < NUM_LIMBS) {
412 for (posn = size; posn < NUM_LIMBS; ++posn) {
414 x[posn] = (limb_t)carry;
424 carry += ((dlimb_t)(x[NUM_LIMBS - 1] >> (LIMB_BITS - 1))) * 19U;
425 x[NUM_LIMBS - 1] &= ((((limb_t)1) << (LIMB_BITS - 1)) - 1);
426 for (posn = 0; posn < NUM_LIMBS; ++posn) {
428 x[posn] = (limb_t)carry;
438 for (posn = 0; posn < NUM_LIMBS; ++posn) {
440 x[posn + NUM_LIMBS] = (limb_t)carry;
450 limb_t mask = (limb_t)(((slimb_t)(x[NUM_LIMBS * 2 - 1])) >> (LIMB_BITS - 1));
451 limb_t nmask = ~mask;
452 x[NUM_LIMBS * 2 - 1] &= ((((limb_t)1) << (LIMB_BITS - 1)) - 1);
453 for (posn = 0; posn < NUM_LIMBS; ++posn) {
454 result[posn] = (x[posn] & nmask) | (x[posn + NUM_LIMBS] & mask);
471 limb_t Curve25519::reduceQuick(limb_t *x)
473 limb_t temp[NUM_LIMBS];
481 for (posn = 0; posn < NUM_LIMBS; ++posn) {
483 temp[posn] = (limb_t)carry;
492 limb_t mask = (limb_t)(((slimb_t)(temp[NUM_LIMBS - 1])) >> (LIMB_BITS - 1));
493 limb_t nmask = ~mask;
494 temp[NUM_LIMBS - 1] &= ((((limb_t)1) << (LIMB_BITS - 1)) - 1);
495 for (posn = 0; posn < NUM_LIMBS; ++posn) {
496 x[posn] = (x[posn] & nmask) | (temp[posn] & mask);
516 void Curve25519::mul(limb_t *result,
const limb_t *x,
const limb_t *y)
518 limb_t temp[NUM_LIMBS * 2];
526 for (i = 0; i < NUM_LIMBS; ++i) {
527 carry += ((dlimb_t)(y[i])) * word;
528 temp[i] = (limb_t)carry;
531 temp[NUM_LIMBS] = (limb_t)carry;
534 for (i = 1; i < NUM_LIMBS; ++i) {
537 for (j = 0; j < NUM_LIMBS; ++j) {
538 carry += ((dlimb_t)(y[j])) * word;
539 carry += temp[i + j];
540 temp[i + j] = (limb_t)carry;
543 temp[i + NUM_LIMBS] = (limb_t)carry;
547 reduce(result, temp, NUM_LIMBS);
570 void Curve25519::mulA24(limb_t *result,
const limb_t *x)
573 #if BIGNUMBER_LIMB_8BIT
574 static limb_t
const a24[3] PROGMEM = {0x41, 0xDB, 0x01};
575 #define pgm_read_a24(index) (pgm_read_byte(&(a24[(index)])))
576 #elif BIGNUMBER_LIMB_16BIT
577 static limb_t
const a24[2] PROGMEM = {0xDB41, 0x0001};
578 #define pgm_read_a24(index) (pgm_read_word(&(a24[(index)])))
579 #elif BIGNUMBER_LIMB_32BIT
580 static limb_t
const a24[1] PROGMEM = {0x0001DB41};
581 #define pgm_read_a24(index) (pgm_read_dword(&(a24[(index)])))
583 #error "limb_t must be 8, 16, or 32 bits in size"
585 #define NUM_A24_LIMBS (sizeof(a24) / sizeof(limb_t))
588 limb_t temp[NUM_LIMBS * 2];
591 limb_t word = pgm_read_a24(0);
592 for (i = 0; i < NUM_LIMBS; ++i) {
593 carry += ((dlimb_t)(x[i])) * word;
594 temp[i] = (limb_t)carry;
597 temp[NUM_LIMBS] = (limb_t)carry;
600 for (i = 1; i < NUM_A24_LIMBS; ++i) {
601 word = pgm_read_a24(i);
603 for (j = 0; j < NUM_LIMBS; ++j) {
604 carry += ((dlimb_t)(x[j])) * word;
605 carry += temp[i + j];
606 temp[i + j] = (limb_t)carry;
609 temp[i + NUM_LIMBS] = (limb_t)carry;
613 reduce(result, temp, NUM_A24_LIMBS);
627 void Curve25519::add(limb_t *result,
const limb_t *x,
const limb_t *y)
633 for (posn = 0; posn < NUM_LIMBS; ++posn) {
636 result[posn] = (limb_t)carry;
654 void Curve25519::sub(limb_t *result,
const limb_t *x,
const limb_t *y)
661 for (posn = 0; posn < NUM_LIMBS; ++posn) {
662 borrow = ((dlimb_t)x[posn]) - y[posn] - ((borrow >> LIMB_BITS) & 0x01);
663 result[posn] = (limb_t)borrow;
671 borrow = (borrow >> LIMB_BITS) & 19U;
672 borrow = ((dlimb_t)result[0]) - borrow;
673 result[0] = (limb_t)borrow;
674 for (posn = 1; posn < NUM_LIMBS; ++posn) {
675 borrow = ((dlimb_t)result[posn]) - ((borrow >> LIMB_BITS) & 0x01);
676 result[posn] = (limb_t)borrow;
678 result[NUM_LIMBS - 1] &= ((((limb_t)1) << (LIMB_BITS - 1)) - 1);
691 void Curve25519::cswap(uint8_t select, limb_t *x, limb_t *y)
699 sel = (limb_t)(((((dlimb_t)1) << LIMB_BITS) - select) >> LIMB_BITS);
704 for (posn = 0; posn < NUM_LIMBS; ++posn) {
705 dummy = sel & (x[posn] ^ y[posn]);
718 void Curve25519::recip(limb_t *result,
const limb_t *x)
720 limb_t t1[NUM_LIMBS];
735 #define RECIP_GROUP_SIZE 10
736 #define RECIP_GROUP_BITS 250 // Must be a multiple of RECIP_GROUP_SIZE.
738 for (j = 0; j < (RECIP_GROUP_SIZE - 1); ++j)
741 for (i = 0; i < ((RECIP_GROUP_BITS / RECIP_GROUP_SIZE) - 2); ++i) {
742 for (j = 0; j < RECIP_GROUP_SIZE; ++j)
744 mul(result, result, t1);
750 mul(result, result, t1);
751 for (j = 0; j < (RECIP_GROUP_SIZE - 2); ++j) {
753 mul(result, result, t1);
757 square(result, result);
758 square(result, result);
759 mul(result, result, x);
760 square(result, result);
761 square(result, result);
762 mul(result, result, x);
763 square(result, result);
764 mul(result, result, x);
782 void Curve25519::unpack(limb_t *result,
const uint8_t *x)
784 #if BIGNUMBER_LIMB_8BIT
785 memcpy(result, x, 32);
787 #elif BIGNUMBER_LIMB_16BIT
788 for (uint8_t posn = 0; posn < 16; ++posn) {
789 result[posn] = ((limb_t)x[posn * 2]) | (((limb_t)x[posn * 2 + 1]) << 8);
791 result[15] &= 0x7FFF;
792 #elif BIGNUMBER_LIMB_32BIT
793 for (uint8_t posn = 0; posn < 8; ++posn) {
794 result[posn] = ((limb_t)x[posn * 4]) |
795 (((limb_t)x[posn * 4 + 1]) << 8) |
796 (((limb_t)x[posn * 4 + 2]) << 16) |
797 (((limb_t)x[posn * 4 + 3]) << 24);
799 result[7] &= 0x7FFFFFFF;
812 void Curve25519::pack(uint8_t *result,
const limb_t *x)
814 #if BIGNUMBER_LIMB_8BIT
815 memcpy(result, x, 32);
816 #elif BIGNUMBER_LIMB_16BIT
817 for (uint8_t posn = 0; posn < 16; ++posn) {
818 limb_t value = x[posn];
819 result[posn * 2] = (uint8_t)value;
820 result[posn * 2 + 1] = (uint8_t)(value >> 8);
822 #elif BIGNUMBER_LIMB_32BIT
823 for (uint8_t posn = 0; posn < 8; ++posn) {
824 limb_t value = x[posn];
825 result[posn * 4] = (uint8_t)value;
826 result[posn * 4 + 1] = (uint8_t)(value >> 8);
827 result[posn * 4 + 2] = (uint8_t)(value >> 16);
828 result[posn * 4 + 3] = (uint8_t)(value >> 24);
void rand(uint8_t *data, size_t len)
Generates random bytes into a caller-supplied buffer.
static bool eval(uint8_t result[32], const uint8_t s[32], const uint8_t x[32])
Evaluates the raw Curve25519 function.
static void dh1(uint8_t k[32], uint8_t f[32])
Performs phase 1 of a Diffie-Hellman key exchange using Curve25519.
static bool dh2(uint8_t k[32], uint8_t f[32])
Performs phase 2 of a Diffie-Hellman key exchange using Curve25519.