27 #include "utility/LimbUtil.h"
49 #define NUM_LIMBS_521BIT NUM_LIMBS_BITS(521)
56 #define NUM_LIMBS_1042BIT (NUM_LIMBS_BITS(521) * 2)
60 #if defined(P521_STRICT_CLEAN)
61 #define strict_clean(x) clean(x)
63 #define strict_clean(x) do { ; } while (0)
67 #if BIGNUMBER_LIMB_8BIT
68 #define LIMB_PARTIAL(value) ((uint8_t)(value)), \
69 ((uint8_t)((value) >> 8))
71 #define LIMB_PARTIAL(value) (value)
78 static limb_t
const P521_q[NUM_LIMBS_521BIT] PROGMEM = {
79 LIMB_PAIR(0x91386409, 0xbb6fb71e), LIMB_PAIR(0x899c47ae, 0x3bb5c9b8),
80 LIMB_PAIR(0xf709a5d0, 0x7fcc0148), LIMB_PAIR(0xbf2f966b, 0x51868783),
81 LIMB_PAIR(0xfffffffa, 0xffffffff), LIMB_PAIR(0xffffffff, 0xffffffff),
82 LIMB_PAIR(0xffffffff, 0xffffffff), LIMB_PAIR(0xffffffff, 0xffffffff),
87 static limb_t
const P521_b[NUM_LIMBS_521BIT] PROGMEM = {
88 LIMB_PAIR(0x6b503f00, 0xef451fd4), LIMB_PAIR(0x3d2c34f1, 0x3573df88),
89 LIMB_PAIR(0x3bb1bf07, 0x1652c0bd), LIMB_PAIR(0xec7e937b, 0x56193951),
90 LIMB_PAIR(0x8ef109e1, 0xb8b48991), LIMB_PAIR(0x99b315f3, 0xa2da725b),
91 LIMB_PAIR(0xb68540ee, 0x929a21a0), LIMB_PAIR(0x8e1c9a1f, 0x953eb961),
96 static limb_t
const P521_Gx[NUM_LIMBS_521BIT] PROGMEM = {
97 LIMB_PAIR(0xc2e5bd66, 0xf97e7e31), LIMB_PAIR(0x856a429b, 0x3348b3c1),
98 LIMB_PAIR(0xa2ffa8de, 0xfe1dc127), LIMB_PAIR(0xefe75928, 0xa14b5e77),
99 LIMB_PAIR(0x6b4d3dba, 0xf828af60), LIMB_PAIR(0x053fb521, 0x9c648139),
100 LIMB_PAIR(0x2395b442, 0x9e3ecb66), LIMB_PAIR(0x0404e9cd, 0x858e06b7),
105 static limb_t
const P521_Gy[NUM_LIMBS_521BIT] PROGMEM = {
106 LIMB_PAIR(0x9fd16650, 0x88be9476), LIMB_PAIR(0xa272c240, 0x353c7086),
107 LIMB_PAIR(0x3fad0761, 0xc550b901), LIMB_PAIR(0x5ef42640, 0x97ee7299),
108 LIMB_PAIR(0x273e662c, 0x17afbd17), LIMB_PAIR(0x579b4468, 0x98f54449),
109 LIMB_PAIR(0x2c7d1bd9, 0x5c8a5fb4), LIMB_PAIR(0x9a3bc004, 0x39296a78),
135 bool P521::eval(uint8_t result[132],
const uint8_t f[66],
const uint8_t point[132])
137 limb_t x[NUM_LIMBS_521BIT];
138 limb_t y[NUM_LIMBS_521BIT];
147 memcpy_P(x, P521_Gx,
sizeof(x));
148 memcpy_P(y, P521_Gy,
sizeof(y));
232 limb_t x[NUM_LIMBS_521BIT];
233 limb_t y[NUM_LIMBS_521BIT];
238 bool ok = validate(x, y);
276 void P521::sign(uint8_t signature[132],
const uint8_t privateKey[66],
277 const void *message,
size_t len,
Hash *hash)
281 limb_t x[NUM_LIMBS_521BIT];
282 limb_t y[NUM_LIMBS_521BIT];
283 limb_t t[NUM_LIMBS_521BIT];
290 hash->
update(message, len);
294 memset(hm, 0, 66 - len);
300 memset(hm, 0, 66 - len);
301 memcpy(hm + 66 - len, message, len);
308 generateK(k, hm, privateKey, hash, count);
310 generateK(k, hm, privateKey, count);
313 memcpy_P(x, P521_Gx,
sizeof(x));
314 memcpy_P(y, P521_Gy,
sizeof(y));
374 const uint8_t publicKey[132],
375 const void *message,
size_t len,
Hash *hash)
377 limb_t x[NUM_LIMBS_521BIT];
378 limb_t y[NUM_LIMBS_521BIT];
379 limb_t r[NUM_LIMBS_521BIT];
380 limb_t s[NUM_LIMBS_521BIT];
381 limb_t u1[NUM_LIMBS_521BIT];
382 limb_t u2[NUM_LIMBS_521BIT];
403 if (!validate(x, y)) {
411 hash->
update(message, len);
432 memcpy_P(u2, P521_Gx,
sizeof(x));
433 memcpy_P(s, P521_Gy,
sizeof(y));
436 addAffine(u2, s, x, y);
440 ok = secure_compare(u1, r, NUM_LIMBS_521BIT *
sizeof(limb_t));
473 limb_t x[NUM_LIMBS_521BIT];
475 RNG.
rand((uint8_t *)x,
sizeof(x));
476 #if BIGNUMBER_LIMB_8BIT
477 x[NUM_LIMBS_521BIT - 1] &= 0x01;
479 x[NUM_LIMBS_521BIT - 1] &= 0x1FF;
500 limb_t x[NUM_LIMBS_521BIT];
501 limb_t y[NUM_LIMBS_521BIT];
502 memcpy_P(x, P521_Gx,
sizeof(x));
503 memcpy_P(y, P521_Gy,
sizeof(y));
504 evaluate(x, y, privateKey);
527 static uint8_t
const P521_q_bytes[66] PROGMEM = {
528 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
529 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
530 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
531 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
532 0xFF, 0xFA, 0x51, 0x86, 0x87, 0x83, 0xBF, 0x2F,
533 0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09,
534 0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C,
535 0x47, 0xAE, 0xBB, 0x6F, 0xB7, 0x1E, 0x91, 0x38,
538 uint8_t zeroTest = 0;
545 zeroTest |= privateKey[posn];
549 borrow = ((uint16_t)(privateKey[posn])) -
550 pgm_read_byte(&(P521_q_bytes[posn])) -
551 ((borrow >> 8) & 0x01);
553 return zeroTest != 0 && borrow != 0;
566 limb_t x[NUM_LIMBS_521BIT];
567 limb_t y[NUM_LIMBS_521BIT];
570 bool ok = validate(x, y);
597 void P521::evaluate(limb_t *x, limb_t *y,
const uint8_t f[66])
599 limb_t x1[NUM_LIMBS_521BIT];
600 limb_t y1[NUM_LIMBS_521BIT];
601 limb_t z1[NUM_LIMBS_521BIT];
602 limb_t x2[NUM_LIMBS_521BIT];
603 limb_t y2[NUM_LIMBS_521BIT];
604 limb_t z2[NUM_LIMBS_521BIT];
612 memset(x1, 0,
sizeof(x1));
613 memset(y1, 0,
sizeof(y1));
614 memset(z1, 0,
sizeof(z1));
618 uint8_t select = (f[0] & 0x01);
619 cmove(select, x1, x);
620 cmove(select, y1, y);
626 for (uint16_t t = 520; t > 0; --t) {
628 dblPoint(x1, y1, z1, x1, y1, z1);
633 addPoint(x2, y2, z2, x1, y1, z1, x, y);
636 select = (f[fposn] & mask);
637 cmove(select, x1, x2);
638 cmove(select, y1, y2);
639 cmove(select, z1, z2);
676 void P521::addAffine(limb_t *x1, limb_t *y1,
const limb_t *x2,
const limb_t *y2)
678 limb_t xout[NUM_LIMBS_521BIT];
679 limb_t yout[NUM_LIMBS_521BIT];
680 limb_t zout[NUM_LIMBS_521BIT];
681 limb_t z1[NUM_LIMBS_521BIT];
685 memset(z1 + 1, 0, (NUM_LIMBS_521BIT - 1) *
sizeof(limb_t));
688 addPoint(xout, yout, zout, x1, y1, z1, x2, y2);
714 bool P521::validate(
const limb_t *x,
const limb_t *y)
722 result &= inRange(y);
725 limb_t t1[NUM_LIMBS_521BIT];
726 limb_t t2[NUM_LIMBS_521BIT];
729 mulLiteral(t2, x, 3);
731 memcpy_P(t2, P521_b,
sizeof(t2));
734 result &= secure_compare(t1, t2,
sizeof(t1));
748 bool P521::inRange(
const limb_t *x)
754 for (uint8_t index = 0; index < NUM_LIMBS_521BIT; ++index) {
756 word = (limb_t)carry;
761 #if BIGNUMBER_LIMB_8BIT
762 carry = (carry << 7) + (word >> 1);
764 carry = (carry << (LIMB_BITS - 9)) + (word >> 9);
769 word = (limb_t)(carry | (carry >> LIMB_BITS));
770 word = (limb_t)(((((dlimb_t)1) << LIMB_BITS) - word) >> LIMB_BITS);
783 void P521::reduce(limb_t *result,
const limb_t *x)
785 #if BIGNUMBER_LIMB_16BIT || BIGNUMBER_LIMB_32BIT || BIGNUMBER_LIMB_64BIT
791 const limb_t *xl = x;
792 const limb_t *xh = x + NUM_LIMBS_521BIT;
795 limb_t word = x[NUM_LIMBS_521BIT - 1];
796 carry = (word >> 9) + 1;
798 for (index = 0; index < (NUM_LIMBS_521BIT - 1); ++index) {
800 carry += ((dlimb_t)(*xh++)) << (LIMB_BITS - 9);
801 *rr++ = (limb_t)carry;
805 carry += ((dlimb_t)(x[NUM_LIMBS_1042BIT - 1])) << (LIMB_BITS - 9);
806 word = (limb_t)carry;
813 carry = ((word >> 9) ^ 0x01) & 0x01;
815 for (index = 0; index < NUM_LIMBS_521BIT; ++index) {
816 carry = ((dlimb_t)(*rr)) - carry;
817 *rr++ = (limb_t)carry;
818 carry = (carry >> LIMB_BITS) & 0x01;
821 #elif BIGNUMBER_LIMB_8BIT
824 const limb_t *xl = x;
825 const limb_t *xh = x + NUM_LIMBS_521BIT;
828 limb_t word = x[NUM_LIMBS_521BIT - 1];
829 carry = (word >> 1) + 1;
831 for (index = 0; index < (NUM_LIMBS_521BIT - 1); ++index) {
833 carry += ((dlimb_t)(*xh++)) << 7;
834 *rr++ = (limb_t)carry;
838 carry += ((dlimb_t)(x[NUM_LIMBS_1042BIT - 1])) << 1;
839 word = (limb_t)carry;
841 carry = ((word >> 1) ^ 0x01) & 0x01;
843 for (index = 0; index < NUM_LIMBS_521BIT; ++index) {
844 carry = ((dlimb_t)(*rr)) - carry;
845 *rr++ = (limb_t)carry;
846 carry = (carry >> LIMB_BITS) & 0x01;
850 #error "Don't know how to reduce values mod 2^521 - 1"
866 void P521::reduceQuick(limb_t *x)
873 for (index = 0; index < NUM_LIMBS_521BIT; ++index) {
875 *xx++ = (limb_t)carry;
883 #if BIGNUMBER_LIMB_16BIT || BIGNUMBER_LIMB_32BIT || BIGNUMBER_LIMB_64BIT
884 carry = ((x[NUM_LIMBS_521BIT - 1] >> 9) ^ 0x01) & 0x01;
886 for (index = 0; index < NUM_LIMBS_521BIT; ++index) {
887 carry = ((dlimb_t)(*xx)) - carry;
888 *xx++ = (limb_t)carry;
889 carry = (carry >> LIMB_BITS) & 0x01;
892 #elif BIGNUMBER_LIMB_8BIT
893 carry = ((x[NUM_LIMBS_521BIT - 1] >> 1) ^ 0x01) & 0x01;
895 for (index = 0; index < NUM_LIMBS_521BIT; ++index) {
896 carry = ((dlimb_t)(*xx)) - carry;
897 *xx++ = (limb_t)carry;
898 carry = (carry >> LIMB_BITS) & 0x01;
916 void P521::mulNoReduce(limb_t *result,
const limb_t *x,
const limb_t *y)
929 for (i = 0; i < NUM_LIMBS_521BIT; ++i) {
930 carry += ((dlimb_t)(*yy++)) * word;
931 *rr++ = (limb_t)carry;
937 for (i = 1; i < NUM_LIMBS_521BIT; ++i) {
942 for (j = 0; j < NUM_LIMBS_521BIT; ++j) {
943 carry += ((dlimb_t)(*yy++)) * word;
945 *rr++ = (limb_t)carry;
962 void P521::mul(limb_t *result,
const limb_t *x,
const limb_t *y)
964 limb_t temp[NUM_LIMBS_1042BIT];
965 mulNoReduce(temp, x, y);
966 reduce(result, temp);
968 crypto_feed_watchdog();
990 void P521::mulLiteral(limb_t *result,
const limb_t *x, limb_t y)
994 const limb_t *xx = x;
1000 for (index = 0; index < NUM_LIMBS_521BIT; ++index) {
1001 carry += ((dlimb_t)(*xx++)) * y;
1002 *rr++ = (limb_t)carry;
1003 carry >>= LIMB_BITS;
1008 #if BIGNUMBER_LIMB_16BIT || BIGNUMBER_LIMB_32BIT || BIGNUMBER_LIMB_64BIT
1009 limb_t word = result[NUM_LIMBS_521BIT - 1];
1010 carry = (word >> 9) + 1;
1013 for (index = 0; index < (NUM_LIMBS_521BIT - 1); ++index) {
1015 *rr++ = (limb_t)carry;
1016 carry >>= LIMB_BITS;
1019 word = (limb_t)carry;
1026 carry = ((word >> 9) ^ 0x01) & 0x01;
1028 for (index = 0; index < NUM_LIMBS_521BIT; ++index) {
1029 carry = ((dlimb_t)(*rr)) - carry;
1030 *rr++ = (limb_t)carry;
1031 carry = (carry >> LIMB_BITS) & 0x01;
1034 #elif BIGNUMBER_LIMB_8BIT
1036 limb_t word = result[NUM_LIMBS_521BIT - 1];
1037 carry = (word >> 1) + 1;
1040 for (index = 0; index < (NUM_LIMBS_521BIT - 1); ++index) {
1042 *rr++ = (limb_t)carry;
1043 carry >>= LIMB_BITS;
1046 word = (limb_t)carry;
1048 carry = ((word >> 1) ^ 0x01) & 0x01;
1050 for (index = 0; index < NUM_LIMBS_521BIT; ++index) {
1051 carry = ((dlimb_t)(*rr)) - carry;
1052 *rr++ = (limb_t)carry;
1053 carry = (carry >> LIMB_BITS) & 0x01;
1069 void P521::add(limb_t *result,
const limb_t *x,
const limb_t *y)
1072 limb_t *rr = result;
1073 for (uint8_t posn = 0; posn < NUM_LIMBS_521BIT; ++posn) {
1076 *rr++ = (limb_t)carry;
1077 carry >>= LIMB_BITS;
1079 reduceQuick(result);
1092 void P521::sub(limb_t *result,
const limb_t *x,
const limb_t *y)
1096 limb_t *rr = result;
1100 for (posn = 0; posn < NUM_LIMBS_521BIT; ++posn) {
1101 borrow = ((dlimb_t)(*x++)) - (*y++) - ((borrow >> LIMB_BITS) & 0x01);
1102 *rr++ = (limb_t)borrow;
1111 borrow = (borrow >> LIMB_BITS) & 1U;
1112 borrow = ((dlimb_t)(*rr)) - borrow;
1113 *rr++ = (limb_t)borrow;
1114 for (posn = 1; posn < NUM_LIMBS_521BIT; ++posn) {
1115 borrow = ((dlimb_t)(*rr)) - ((borrow >> LIMB_BITS) & 0x01);
1116 *rr++ = (limb_t)borrow;
1118 #if BIGNUMBER_LIMB_8BIT
1140 void P521::dblPoint(limb_t *xout, limb_t *yout, limb_t *zout,
1141 const limb_t *xin,
const limb_t *yin,
1144 limb_t alpha[NUM_LIMBS_521BIT];
1145 limb_t beta[NUM_LIMBS_521BIT];
1146 limb_t gamma[NUM_LIMBS_521BIT];
1147 limb_t delta[NUM_LIMBS_521BIT];
1148 limb_t tmp[NUM_LIMBS_521BIT];
1155 mul(beta, xin, gamma);
1156 sub(tmp, xin, delta);
1157 mulLiteral(alpha, tmp, 3);
1158 add(tmp, xin, delta);
1159 mul(alpha, alpha, tmp);
1160 square(xout, alpha);
1161 mulLiteral(tmp, beta, 8);
1162 sub(xout, xout, tmp);
1163 add(zout, yin, zin);
1165 sub(zout, zout, gamma);
1166 sub(zout, zout, delta);
1167 mulLiteral(yout, beta, 4);
1168 sub(yout, yout, xout);
1169 mul(yout, alpha, yout);
1170 square(gamma, gamma);
1171 mulLiteral(gamma, gamma, 8);
1172 sub(yout, yout, gamma);
1175 strict_clean(alpha);
1177 strict_clean(gamma);
1178 strict_clean(delta);
1201 void P521::addPoint(limb_t *xout, limb_t *yout, limb_t *zout,
1202 const limb_t *x1,
const limb_t *y1,
1203 const limb_t *z1,
const limb_t *x2,
1206 limb_t z1z1[NUM_LIMBS_521BIT];
1207 limb_t u2[NUM_LIMBS_521BIT];
1208 limb_t s2[NUM_LIMBS_521BIT];
1209 limb_t h[NUM_LIMBS_521BIT];
1210 limb_t i[NUM_LIMBS_521BIT];
1211 limb_t j[NUM_LIMBS_521BIT];
1212 limb_t r[NUM_LIMBS_521BIT];
1213 limb_t v[NUM_LIMBS_521BIT];
1225 mulLiteral(i, h, 2);
1241 add(zout, zout, zout);
1246 cmove(p1IsIdentity, xout, x2);
1247 cmove(p1IsIdentity, yout, y2);
1248 cmove1(p1IsIdentity, zout);
1273 void P521::cmove(limb_t select, limb_t *x,
const limb_t *y)
1281 sel = (limb_t)(((((dlimb_t)1) << LIMB_BITS) - select) >> LIMB_BITS);
1285 for (posn = 0; posn < NUM_LIMBS_521BIT; ++posn) {
1286 dummy = sel & (*x ^ *y++);
1302 void P521::cmove1(limb_t select, limb_t *x)
1310 sel = (limb_t)(((((dlimb_t)1) << LIMB_BITS) - select) >> LIMB_BITS);
1314 dummy = sel & (*x ^ 1);
1316 for (posn = 1; posn < NUM_LIMBS_521BIT; ++posn) {
1330 void P521::recip(limb_t *result,
const limb_t *x)
1332 limb_t t1[NUM_LIMBS_521BIT];
1345 mul(result, result, x);
1346 square(result, result);
1347 mul(result, result, x);
1348 square(result, result);
1349 mul(result, result, x);
1353 for (
size_t power = 4; power <= 256; power <<= 1) {
1355 for (
size_t temp = 1; temp < power; ++temp)
1357 mul(result, result, t1);
1361 for (uint8_t index = 0; index < 7; ++index) {
1362 square(result, result);
1363 mul(result, result, x);
1365 square(result, result);
1366 square(result, result);
1367 mul(result, result, x);
1381 void P521::reduceQ(limb_t *result,
const limb_t *r)
1394 static limb_t
const numM[NUM_LIMBS_521BIT] PROGMEM = {
1395 LIMB_PAIR(0x6EC79BF7, 0x449048E1), LIMB_PAIR(0x7663B851, 0xC44A3647),
1396 LIMB_PAIR(0x08F65A2F, 0x8033FEB7), LIMB_PAIR(0x40D06994, 0xAE79787C),
1397 LIMB_PAIR(0x00000005, 0x00000000), LIMB_PAIR(0x00000000, 0x00000000),
1398 LIMB_PAIR(0x00000000, 0x00000000), LIMB_PAIR(0x00000000, 0x00000000),
1401 limb_t temp[NUM_LIMBS_1042BIT + NUM_LIMBS_521BIT];
1402 limb_t temp2[NUM_LIMBS_521BIT];
1408 #if BIGNUMBER_LIMB_8BIT || BIGNUMBER_LIMB_16BIT
1409 dlimb_t carry = temp[NUM_LIMBS_BITS(1040)] >> 2;
1410 for (uint8_t index = 0; index < NUM_LIMBS_521BIT; ++index) {
1411 carry += ((dlimb_t)(temp[NUM_LIMBS_BITS(1040) + index + 1])) << (LIMB_BITS - 2);
1412 temp2[index] = (limb_t)carry;
1413 carry >>= LIMB_BITS;
1415 #elif BIGNUMBER_LIMB_32BIT || BIGNUMBER_LIMB_64BIT
1416 dlimb_t carry = temp[NUM_LIMBS_BITS(1024)] >> 18;
1417 for (uint8_t index = 0; index < NUM_LIMBS_521BIT; ++index) {
1418 carry += ((dlimb_t)(temp[NUM_LIMBS_BITS(1024) + index + 1])) << (LIMB_BITS - 18);
1419 temp2[index] = (limb_t)carry;
1420 carry >>= LIMB_BITS;
1428 P521_q, NUM_LIMBS_521BIT);
1449 void P521::mulQ(limb_t *result,
const limb_t *x,
const limb_t *y)
1451 limb_t temp[NUM_LIMBS_1042BIT];
1452 mulNoReduce(temp, x, y);
1453 reduceQ(result, temp);
1465 void P521::recipQ(limb_t *result,
const limb_t *x)
1468 static limb_t
const P521_q_m2[] PROGMEM = {
1469 LIMB_PAIR(0x91386407, 0xbb6fb71e), LIMB_PAIR(0x899c47ae, 0x3bb5c9b8),
1470 LIMB_PAIR(0xf709a5d0, 0x7fcc0148), LIMB_PAIR(0xbf2f966b, 0x51868783),
1476 limb_t t1[NUM_LIMBS_521BIT];
1478 mulQ(result, result, x);
1479 mulQ(result, result, result);
1480 mulQ(result, result, x);
1481 mulQ(result, result, result);
1482 mulQ(result, result, x);
1483 for (
size_t power = 4; power <= 128; power <<= 1) {
1484 mulQ(t1, result, result);
1485 for (
size_t temp = 1; temp < power; ++temp)
1487 mulQ(result, result, t1);
1497 mulQ(result, result, result);
1498 if (pgm_read_limb(&(P521_q_m2[bit / LIMB_BITS])) &
1499 (((limb_t)1) << (bit % LIMB_BITS))) {
1500 mulQ(result, result, x);
1515 void P521::generateK(uint8_t k[66],
const uint8_t hm[66],
1516 const uint8_t x[66],
Hash *hash, uint64_t count)
1535 memset(V, 0x01, hlen);
1536 memset(K, 0x00, hlen);
1550 hash->
update(&marker, 1);
1554 hash->
update(&count,
sizeof(count));
1566 hash->
update(&marker, 1);
1570 hash->
update(&count,
sizeof(count));
1587 size_t temp = 66 - posn;
1593 memcpy(k + posn, V, temp);
1601 for (posn = 65; posn > 0; --posn)
1602 k[posn] = (k[posn - 1] << 1) | (k[posn] >> 7);
1613 hash->
update(&marker, 1);
1637 void P521::generateK(uint8_t k[66],
const uint8_t hm[66],
1638 const uint8_t x[66], uint64_t count)
1641 generateK(k, hm, x, &hash, count);
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 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 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 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.
Abstract base class for cryptographic hash algorithms.
virtual void finalize(void *hash, size_t len)=0
Finalizes the hashing process and returns the hash.
virtual void reset()=0
Resets the hash ready for a new hashing process.
virtual void finalizeHMAC(const void *key, size_t keyLen, void *hash, size_t hashLen)=0
Finalizes the HMAC hashing process and returns the hash.
virtual size_t hashSize() const =0
Size of the hash result from finalize().
virtual void resetHMAC(const void *key, size_t keyLen)=0
Resets the hash ready for a new HMAC hashing process.
virtual void update(const void *data, size_t len)=0
Updates the hash with more data.
static void derivePublicKey(uint8_t publicKey[132], const uint8_t privateKey[66])
Derives the public key from a private key for P-521 signing operations.
static bool isValidPrivateKey(const uint8_t privateKey[66])
Validates a private key value to ensure that it is between 1 and q - 1.
static bool dh2(const uint8_t k[132], uint8_t f[66])
Performs phase 2 of an ECDH key exchange using P-521.
static void sign(uint8_t signature[132], const uint8_t privateKey[66], const void *message, size_t len, Hash *hash=0)
Signs a message using a specific P-521 private key.
static bool verify(const uint8_t signature[132], const uint8_t publicKey[132], const void *message, size_t len, Hash *hash=0)
Verifies a signature using a specific P-521 public key.
static bool eval(uint8_t result[132], const uint8_t f[66], const uint8_t point[132])
Evaluates the curve function.
static void dh1(uint8_t k[132], uint8_t f[66])
Performs phase 1 of an ECDH key exchange using P-521.
static void generatePrivateKey(uint8_t privateKey[66])
Generates a private key for P-521 signing operations.
static bool isValidPublicKey(const uint8_t publicKey[132])
Validates a public key to ensure that it is a valid curve point.
void rand(uint8_t *data, size_t len)
Generates random bytes into a caller-supplied buffer.