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))
54 #if defined(CURVE25519_STRICT_CLEAN)
55 #define strict_clean(x) clean(x)
57 #define strict_clean(x) do { ; } while (0)
81 limb_t x_1[NUM_LIMBS];
82 limb_t x_2[NUM_LIMBS];
83 limb_t x_3[NUM_LIMBS];
84 limb_t z_2[NUM_LIMBS];
85 limb_t z_3[NUM_LIMBS];
106 x_1[NUM_LIMBS - 1] &= ((((limb_t)1) << (LIMB_BITS - 1)) - 1);
108 memset(x_1, 0,
sizeof(x_1));
119 retval = (bool)(reduceQuick(x_1) & 0x01);
122 memset(x_2, 0,
sizeof(x_2));
124 memset(z_2, 0,
sizeof(z_2));
125 memcpy(x_3, x_1,
sizeof(x_1));
126 memcpy(z_3, x_2,
sizeof(x_2));
133 for (uint8_t t = 255; t > 0; --t) {
136 select = s[sposn] & mask;
138 cswap(swap, x_2, x_3);
139 cswap(swap, z_2, z_3);
173 cswap(swap, x_2, x_3);
174 cswap(swap, z_2, z_3);
253 f[31] = (f[31] & 0x7F) | 0x40;
264 }
while (isWeakPoint(k));
292 weak = isWeakPoint(k);
293 weak |= ((
eval(k, f, k) ^ 0x01) & 0x01);
294 weak |= isWeakPoint(k);
296 return (
bool)((weak ^ 0x01) & 0x01);
306 uint8_t Curve25519::isWeakPoint(
const uint8_t k[32])
312 static const uint8_t points[5][32] PROGMEM = {
313 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
314 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
315 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
316 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
317 {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
318 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
319 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
320 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
321 {0xE0, 0xEB, 0x7A, 0x7C, 0x3B, 0x41, 0xB8, 0xAE,
322 0x16, 0x56, 0xE3, 0xFA, 0xF1, 0x9F, 0xC4, 0x6A,
323 0xDA, 0x09, 0x8D, 0xEB, 0x9C, 0x32, 0xB1, 0xFD,
324 0x86, 0x62, 0x05, 0x16, 0x5F, 0x49, 0xB8, 0x00},
325 {0x5F, 0x9C, 0x95, 0xBC, 0xA3, 0x50, 0x8C, 0x24,
326 0xB1, 0xD0, 0xB1, 0x55, 0x9C, 0x83, 0xEF, 0x5B,
327 0x04, 0x44, 0x5C, 0xC4, 0x58, 0x1C, 0x8E, 0x86,
328 0xD8, 0x22, 0x4E, 0xDD, 0xD0, 0x9F, 0x11, 0x57},
329 {0xEC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
330 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
331 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
332 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F}
341 for (uint8_t posn = 0; posn < 5; ++posn) {
342 const uint8_t *point = points[posn];
343 uint8_t check = (pgm_read_byte(point + 31) ^ k[31]) & 0x7F;
344 for (uint8_t index = 31; index > 0; --index)
345 check |= (pgm_read_byte(point + index - 1) ^ k[index - 1]);
346 result |= (uint8_t)((((uint16_t)0x0100) - check) >> 8);
365 void Curve25519::reduce(limb_t *result, limb_t *x, uint8_t size)
414 carry = ((dlimb_t)(x[NUM_LIMBS - 1] >> (LIMB_BITS - 1))) * 19U;
415 x[NUM_LIMBS - 1] &= ((((limb_t)1) << (LIMB_BITS - 1)) - 1);
416 for (posn = 0; posn < size; ++posn) {
417 carry += ((dlimb_t)(x[posn + NUM_LIMBS])) * 38U;
419 x[posn] = (limb_t)carry;
422 if (size < NUM_LIMBS) {
425 for (posn = size; posn < NUM_LIMBS; ++posn) {
427 x[posn] = (limb_t)carry;
437 carry += ((dlimb_t)(x[NUM_LIMBS - 1] >> (LIMB_BITS - 1))) * 19U;
438 x[NUM_LIMBS - 1] &= ((((limb_t)1) << (LIMB_BITS - 1)) - 1);
439 for (posn = 0; posn < NUM_LIMBS; ++posn) {
441 x[posn] = (limb_t)carry;
451 for (posn = 0; posn < NUM_LIMBS; ++posn) {
453 x[posn + NUM_LIMBS] = (limb_t)carry;
463 limb_t mask = (limb_t)(((slimb_t)(x[NUM_LIMBS * 2 - 1])) >> (LIMB_BITS - 1));
464 limb_t nmask = ~mask;
465 x[NUM_LIMBS * 2 - 1] &= ((((limb_t)1) << (LIMB_BITS - 1)) - 1);
466 for (posn = 0; posn < NUM_LIMBS; ++posn) {
467 result[posn] = (x[posn] & nmask) | (x[posn + NUM_LIMBS] & mask);
484 limb_t Curve25519::reduceQuick(limb_t *x)
486 limb_t temp[NUM_LIMBS];
498 for (posn = 0; posn < NUM_LIMBS; ++posn) {
500 *tt++ = (limb_t)carry;
509 limb_t mask = (limb_t)(((slimb_t)(temp[NUM_LIMBS - 1])) >> (LIMB_BITS - 1));
510 limb_t nmask = ~mask;
511 temp[NUM_LIMBS - 1] &= ((((limb_t)1) << (LIMB_BITS - 1)) - 1);
514 for (posn = 0; posn < NUM_LIMBS; ++posn) {
515 *xx = ((*xx) & nmask) | ((*tt++) & mask);
536 void Curve25519::mul(limb_t *result,
const limb_t *x,
const limb_t *y)
538 limb_t temp[NUM_LIMBS * 2];
550 for (i = 0; i < NUM_LIMBS; ++i) {
551 carry += ((dlimb_t)(*yy++)) * word;
552 *tt++ = (limb_t)carry;
558 for (i = 1; i < NUM_LIMBS; ++i) {
563 for (j = 0; j < NUM_LIMBS; ++j) {
564 carry += ((dlimb_t)(*yy++)) * word;
566 *tt++ = (limb_t)carry;
573 reduce(result, temp, NUM_LIMBS);
596 void Curve25519::mulA24(limb_t *result,
const limb_t *x)
599 #if BIGNUMBER_LIMB_8BIT
600 static limb_t
const a24[3] PROGMEM = {0x41, 0xDB, 0x01};
601 #define pgm_read_a24(index) (pgm_read_byte(&(a24[(index)])))
602 #elif BIGNUMBER_LIMB_16BIT
603 static limb_t
const a24[2] PROGMEM = {0xDB41, 0x0001};
604 #define pgm_read_a24(index) (pgm_read_word(&(a24[(index)])))
605 #elif BIGNUMBER_LIMB_32BIT
606 static limb_t
const a24[1] PROGMEM = {0x0001DB41};
607 #define pgm_read_a24(index) (pgm_read_dword(&(a24[(index)])))
609 #error "limb_t must be 8, 16, or 32 bits in size"
611 #define NUM_A24_LIMBS (sizeof(a24) / sizeof(limb_t))
614 limb_t temp[NUM_LIMBS * 2];
617 limb_t word = pgm_read_a24(0);
618 const limb_t *xx = x;
620 for (i = 0; i < NUM_LIMBS; ++i) {
621 carry += ((dlimb_t)(*xx++)) * word;
622 *tt++ = (limb_t)carry;
628 for (i = 1; i < NUM_A24_LIMBS; ++i) {
629 word = pgm_read_a24(i);
633 for (j = 0; j < NUM_LIMBS; ++j) {
634 carry += ((dlimb_t)(*xx++)) * word;
636 *tt++ = (limb_t)carry;
643 reduce(result, temp, NUM_A24_LIMBS);
657 void Curve25519::add(limb_t *result,
const limb_t *x,
const limb_t *y)
664 for (posn = 0; posn < NUM_LIMBS; ++posn) {
667 *rr++ = (limb_t)carry;
685 void Curve25519::sub(limb_t *result,
const limb_t *x,
const limb_t *y)
693 for (posn = 0; posn < NUM_LIMBS; ++posn) {
694 borrow = ((dlimb_t)(*x++)) - (*y++) - ((borrow >> LIMB_BITS) & 0x01);
695 *rr++ = (limb_t)borrow;
704 borrow = (borrow >> LIMB_BITS) & 19U;
705 borrow = ((dlimb_t)(*rr)) - borrow;
706 *rr++ = (limb_t)borrow;
707 for (posn = 1; posn < NUM_LIMBS; ++posn) {
708 borrow = ((dlimb_t)(*rr)) - ((borrow >> LIMB_BITS) & 0x01);
709 *rr++ = (limb_t)borrow;
711 *(--rr) &= ((((limb_t)1) << (LIMB_BITS - 1)) - 1);
724 void Curve25519::cswap(uint8_t select, limb_t *x, limb_t *y)
732 sel = (limb_t)(((((dlimb_t)1) << LIMB_BITS) - select) >> LIMB_BITS);
737 for (posn = 0; posn < NUM_LIMBS; ++posn) {
738 dummy = sel & (x[posn] ^ y[posn]);
751 void Curve25519::recip(limb_t *result,
const limb_t *x)
753 limb_t t1[NUM_LIMBS];
768 #define RECIP_GROUP_SIZE 10
769 #define RECIP_GROUP_BITS 250 // Must be a multiple of RECIP_GROUP_SIZE.
771 for (j = 0; j < (RECIP_GROUP_SIZE - 1); ++j)
774 for (i = 0; i < ((RECIP_GROUP_BITS / RECIP_GROUP_SIZE) - 2); ++i) {
775 for (j = 0; j < RECIP_GROUP_SIZE; ++j)
777 mul(result, result, t1);
783 mul(result, result, t1);
784 for (j = 0; j < (RECIP_GROUP_SIZE - 2); ++j) {
786 mul(result, result, t1);
790 square(result, result);
791 square(result, result);
792 mul(result, result, x);
793 square(result, result);
794 square(result, result);
795 mul(result, result, x);
796 square(result, result);
797 mul(result, result, x);
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 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 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 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.