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);
989 void P521::mulLiteral(limb_t *result,
const limb_t *x, limb_t y)
993 const limb_t *xx = x;
999 for (index = 0; index < NUM_LIMBS_521BIT; ++index) {
1000 carry += ((dlimb_t)(*xx++)) * y;
1001 *rr++ = (limb_t)carry;
1002 carry >>= LIMB_BITS;
1007 #if BIGNUMBER_LIMB_16BIT || BIGNUMBER_LIMB_32BIT || BIGNUMBER_LIMB_64BIT
1008 limb_t word = result[NUM_LIMBS_521BIT - 1];
1009 carry = (word >> 9) + 1;
1012 for (index = 0; index < (NUM_LIMBS_521BIT - 1); ++index) {
1014 *rr++ = (limb_t)carry;
1015 carry >>= LIMB_BITS;
1018 word = (limb_t)carry;
1025 carry = ((word >> 9) ^ 0x01) & 0x01;
1027 for (index = 0; index < NUM_LIMBS_521BIT; ++index) {
1028 carry = ((dlimb_t)(*rr)) - carry;
1029 *rr++ = (limb_t)carry;
1030 carry = (carry >> LIMB_BITS) & 0x01;
1033 #elif BIGNUMBER_LIMB_8BIT
1035 limb_t word = result[NUM_LIMBS_521BIT - 1];
1036 carry = (word >> 1) + 1;
1039 for (index = 0; index < (NUM_LIMBS_521BIT - 1); ++index) {
1041 *rr++ = (limb_t)carry;
1042 carry >>= LIMB_BITS;
1045 word = (limb_t)carry;
1047 carry = ((word >> 1) ^ 0x01) & 0x01;
1049 for (index = 0; index < NUM_LIMBS_521BIT; ++index) {
1050 carry = ((dlimb_t)(*rr)) - carry;
1051 *rr++ = (limb_t)carry;
1052 carry = (carry >> LIMB_BITS) & 0x01;
1068 void P521::add(limb_t *result,
const limb_t *x,
const limb_t *y)
1071 limb_t *rr = result;
1072 for (uint8_t posn = 0; posn < NUM_LIMBS_521BIT; ++posn) {
1075 *rr++ = (limb_t)carry;
1076 carry >>= LIMB_BITS;
1078 reduceQuick(result);
1091 void P521::sub(limb_t *result,
const limb_t *x,
const limb_t *y)
1095 limb_t *rr = result;
1099 for (posn = 0; posn < NUM_LIMBS_521BIT; ++posn) {
1100 borrow = ((dlimb_t)(*x++)) - (*y++) - ((borrow >> LIMB_BITS) & 0x01);
1101 *rr++ = (limb_t)borrow;
1110 borrow = (borrow >> LIMB_BITS) & 1U;
1111 borrow = ((dlimb_t)(*rr)) - borrow;
1112 *rr++ = (limb_t)borrow;
1113 for (posn = 1; posn < NUM_LIMBS_521BIT; ++posn) {
1114 borrow = ((dlimb_t)(*rr)) - ((borrow >> LIMB_BITS) & 0x01);
1115 *rr++ = (limb_t)borrow;
1117 #if BIGNUMBER_LIMB_8BIT
1139 void P521::dblPoint(limb_t *xout, limb_t *yout, limb_t *zout,
1140 const limb_t *xin,
const limb_t *yin,
1143 limb_t alpha[NUM_LIMBS_521BIT];
1144 limb_t beta[NUM_LIMBS_521BIT];
1145 limb_t gamma[NUM_LIMBS_521BIT];
1146 limb_t delta[NUM_LIMBS_521BIT];
1147 limb_t tmp[NUM_LIMBS_521BIT];
1154 mul(beta, xin, gamma);
1155 sub(tmp, xin, delta);
1156 mulLiteral(alpha, tmp, 3);
1157 add(tmp, xin, delta);
1158 mul(alpha, alpha, tmp);
1159 square(xout, alpha);
1160 mulLiteral(tmp, beta, 8);
1161 sub(xout, xout, tmp);
1162 add(zout, yin, zin);
1164 sub(zout, zout, gamma);
1165 sub(zout, zout, delta);
1166 mulLiteral(yout, beta, 4);
1167 sub(yout, yout, xout);
1168 mul(yout, alpha, yout);
1169 square(gamma, gamma);
1170 mulLiteral(gamma, gamma, 8);
1171 sub(yout, yout, gamma);
1174 strict_clean(alpha);
1176 strict_clean(gamma);
1177 strict_clean(delta);
1200 void P521::addPoint(limb_t *xout, limb_t *yout, limb_t *zout,
1201 const limb_t *x1,
const limb_t *y1,
1202 const limb_t *z1,
const limb_t *x2,
1205 limb_t z1z1[NUM_LIMBS_521BIT];
1206 limb_t u2[NUM_LIMBS_521BIT];
1207 limb_t s2[NUM_LIMBS_521BIT];
1208 limb_t h[NUM_LIMBS_521BIT];
1209 limb_t i[NUM_LIMBS_521BIT];
1210 limb_t j[NUM_LIMBS_521BIT];
1211 limb_t r[NUM_LIMBS_521BIT];
1212 limb_t v[NUM_LIMBS_521BIT];
1224 mulLiteral(i, h, 2);
1240 add(zout, zout, zout);
1245 cmove(p1IsIdentity, xout, x2);
1246 cmove(p1IsIdentity, yout, y2);
1247 cmove1(p1IsIdentity, zout);
1272 void P521::cmove(limb_t select, limb_t *x,
const limb_t *y)
1280 sel = (limb_t)(((((dlimb_t)1) << LIMB_BITS) - select) >> LIMB_BITS);
1284 for (posn = 0; posn < NUM_LIMBS_521BIT; ++posn) {
1285 dummy = sel & (*x ^ *y++);
1301 void P521::cmove1(limb_t select, limb_t *x)
1309 sel = (limb_t)(((((dlimb_t)1) << LIMB_BITS) - select) >> LIMB_BITS);
1313 dummy = sel & (*x ^ 1);
1315 for (posn = 1; posn < NUM_LIMBS_521BIT; ++posn) {
1329 void P521::recip(limb_t *result,
const limb_t *x)
1331 limb_t t1[NUM_LIMBS_521BIT];
1344 mul(result, result, x);
1345 square(result, result);
1346 mul(result, result, x);
1347 square(result, result);
1348 mul(result, result, x);
1352 for (
size_t power = 4; power <= 256; power <<= 1) {
1354 for (
size_t temp = 1; temp < power; ++temp)
1356 mul(result, result, t1);
1360 for (uint8_t index = 0; index < 7; ++index) {
1361 square(result, result);
1362 mul(result, result, x);
1364 square(result, result);
1365 square(result, result);
1366 mul(result, result, x);
1380 void P521::reduceQ(limb_t *result,
const limb_t *r)
1393 static limb_t
const numM[NUM_LIMBS_521BIT] PROGMEM = {
1394 LIMB_PAIR(0x6EC79BF7, 0x449048E1), LIMB_PAIR(0x7663B851, 0xC44A3647),
1395 LIMB_PAIR(0x08F65A2F, 0x8033FEB7), LIMB_PAIR(0x40D06994, 0xAE79787C),
1396 LIMB_PAIR(0x00000005, 0x00000000), LIMB_PAIR(0x00000000, 0x00000000),
1397 LIMB_PAIR(0x00000000, 0x00000000), LIMB_PAIR(0x00000000, 0x00000000),
1400 limb_t temp[NUM_LIMBS_1042BIT + NUM_LIMBS_521BIT];
1401 limb_t temp2[NUM_LIMBS_521BIT];
1407 #if BIGNUMBER_LIMB_8BIT || BIGNUMBER_LIMB_16BIT
1408 dlimb_t carry = temp[NUM_LIMBS_BITS(1040)] >> 2;
1409 for (uint8_t index = 0; index < NUM_LIMBS_521BIT; ++index) {
1410 carry += ((dlimb_t)(temp[NUM_LIMBS_BITS(1040) + index + 1])) << (LIMB_BITS - 2);
1411 temp2[index] = (limb_t)carry;
1412 carry >>= LIMB_BITS;
1414 #elif BIGNUMBER_LIMB_32BIT || BIGNUMBER_LIMB_64BIT
1415 dlimb_t carry = temp[NUM_LIMBS_BITS(1024)] >> 18;
1416 for (uint8_t index = 0; index < NUM_LIMBS_521BIT; ++index) {
1417 carry += ((dlimb_t)(temp[NUM_LIMBS_BITS(1024) + index + 1])) << (LIMB_BITS - 18);
1418 temp2[index] = (limb_t)carry;
1419 carry >>= LIMB_BITS;
1427 P521_q, NUM_LIMBS_521BIT);
1448 void P521::mulQ(limb_t *result,
const limb_t *x,
const limb_t *y)
1450 limb_t temp[NUM_LIMBS_1042BIT];
1451 mulNoReduce(temp, x, y);
1452 reduceQ(result, temp);
1464 void P521::recipQ(limb_t *result,
const limb_t *x)
1467 static limb_t
const P521_q_m2[] PROGMEM = {
1468 LIMB_PAIR(0x91386407, 0xbb6fb71e), LIMB_PAIR(0x899c47ae, 0x3bb5c9b8),
1469 LIMB_PAIR(0xf709a5d0, 0x7fcc0148), LIMB_PAIR(0xbf2f966b, 0x51868783),
1475 limb_t t1[NUM_LIMBS_521BIT];
1477 mulQ(result, result, x);
1478 mulQ(result, result, result);
1479 mulQ(result, result, x);
1480 mulQ(result, result, result);
1481 mulQ(result, result, x);
1482 for (
size_t power = 4; power <= 128; power <<= 1) {
1483 mulQ(t1, result, result);
1484 for (
size_t temp = 1; temp < power; ++temp)
1486 mulQ(result, result, t1);
1496 mulQ(result, result, result);
1497 if (pgm_read_limb(&(P521_q_m2[bit / LIMB_BITS])) &
1498 (((limb_t)1) << (bit % LIMB_BITS))) {
1499 mulQ(result, result, x);
1514 void P521::generateK(uint8_t k[66],
const uint8_t hm[66],
1515 const uint8_t x[66],
Hash *hash, uint64_t count)
1534 memset(V, 0x01, hlen);
1535 memset(K, 0x00, hlen);
1549 hash->
update(&marker, 1);
1553 hash->
update(&count,
sizeof(count));
1565 hash->
update(&marker, 1);
1569 hash->
update(&count,
sizeof(count));
1586 size_t temp = 66 - posn;
1592 memcpy(k + posn, V, temp);
1600 for (posn = 65; posn > 0; --posn)
1601 k[posn] = (k[posn - 1] << 1) | (k[posn] >> 7);
1612 hash->
update(&marker, 1);
1636 void P521::generateK(uint8_t k[66],
const uint8_t hm[66],
1637 const uint8_t x[66], uint64_t count)
1640 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 bool eval(uint8_t result[132], const uint8_t f[66], const uint8_t point[132])
Evaluates the curve function.
static limb_t add(limb_t *result, const limb_t *x, const limb_t *y, size_t size)
Adds two big numbers.
static void generatePrivateKey(uint8_t privateKey[66])
Generates a private key for P-521 signing operations.
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.
void rand(uint8_t *data, size_t len)
Generates random bytes into a caller-supplied buffer.
static bool dh2(const uint8_t k[132], uint8_t f[66])
Performs phase 2 of an ECDH key exchange using P-521.
Abstract base class for cryptographic hash algorithms.
virtual void finalizeHMAC(const void *key, size_t keyLen, void *hash, size_t hashLen)=0
Finalizes the HMAC hashing process and returns the hash.
static bool isValidPrivateKey(const uint8_t privateKey[66])
Validates a private key value to ensure that it is between 1 and q - 1.
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 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 limb_t sub(limb_t *result, const limb_t *x, const limb_t *y, size_t size)
Subtracts one big number from another.
virtual void reset()=0
Resets the hash ready for a new hashing process.
static void dh1(uint8_t k[132], uint8_t f[66])
Performs phase 1 of an ECDH key exchange using P-521.
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 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.
virtual void resetHMAC(const void *key, size_t keyLen)=0
Resets the hash ready for a new HMAC hashing process.
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 isValidPublicKey(const uint8_t publicKey[132])
Validates a public key to ensure that it is a valid curve point.
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.
virtual size_t hashSize() const =0
Size of the hash result from finalize().
virtual void update(const void *data, size_t len)=0
Updates the hash with more data.
virtual void finalize(void *hash, size_t len)=0
Finalizes the hashing process and returns the hash.
static limb_t isZero(const limb_t *x, size_t size)
Determine if a big number is zero.