27 #include "utility/LimbUtil.h"
50 #define NUM_LIMBS_521BIT NUM_LIMBS_BITS(521)
57 #define NUM_LIMBS_1042BIT (NUM_LIMBS_BITS(521) * 2)
61 #if defined(P521_STRICT_CLEAN)
62 #define strict_clean(x) clean(x)
64 #define strict_clean(x) do { ; } while (0)
68 #if BIGNUMBER_LIMB_8BIT
69 #define LIMB_PARTIAL(value) ((uint8_t)(value)), \
70 ((uint8_t)((value) >> 8))
72 #define LIMB_PARTIAL(value) (value)
79 static limb_t
const P521_q[NUM_LIMBS_521BIT] PROGMEM = {
80 LIMB(0x91386409), LIMB(0xbb6fb71e), LIMB(0x899c47ae), LIMB(0x3bb5c9b8),
81 LIMB(0xf709a5d0), LIMB(0x7fcc0148), LIMB(0xbf2f966b), LIMB(0x51868783),
82 LIMB(0xfffffffa), LIMB(0xffffffff), LIMB(0xffffffff), LIMB(0xffffffff),
83 LIMB(0xffffffff), LIMB(0xffffffff), LIMB(0xffffffff), LIMB(0xffffffff),
88 static limb_t
const P521_b[NUM_LIMBS_521BIT] PROGMEM = {
89 LIMB(0x6b503f00), LIMB(0xef451fd4), LIMB(0x3d2c34f1), LIMB(0x3573df88),
90 LIMB(0x3bb1bf07), LIMB(0x1652c0bd), LIMB(0xec7e937b), LIMB(0x56193951),
91 LIMB(0x8ef109e1), LIMB(0xb8b48991), LIMB(0x99b315f3), LIMB(0xa2da725b),
92 LIMB(0xb68540ee), LIMB(0x929a21a0), LIMB(0x8e1c9a1f), LIMB(0x953eb961),
97 static limb_t
const P521_Gx[NUM_LIMBS_521BIT] PROGMEM = {
98 LIMB(0xc2e5bd66), LIMB(0xf97e7e31), LIMB(0x856a429b), LIMB(0x3348b3c1),
99 LIMB(0xa2ffa8de), LIMB(0xfe1dc127), LIMB(0xefe75928), LIMB(0xa14b5e77),
100 LIMB(0x6b4d3dba), LIMB(0xf828af60), LIMB(0x053fb521), LIMB(0x9c648139),
101 LIMB(0x2395b442), LIMB(0x9e3ecb66), LIMB(0x0404e9cd), LIMB(0x858e06b7),
106 static limb_t
const P521_Gy[NUM_LIMBS_521BIT] PROGMEM = {
107 LIMB(0x9fd16650), LIMB(0x88be9476), LIMB(0xa272c240), LIMB(0x353c7086),
108 LIMB(0x3fad0761), LIMB(0xc550b901), LIMB(0x5ef42640), LIMB(0x97ee7299),
109 LIMB(0x273e662c), LIMB(0x17afbd17), LIMB(0x579b4468), LIMB(0x98f54449),
110 LIMB(0x2c7d1bd9), LIMB(0x5c8a5fb4), LIMB(0x9a3bc004), LIMB(0x39296a78),
136 bool P521::eval(uint8_t result[132],
const uint8_t f[66],
const uint8_t point[132])
138 limb_t x[NUM_LIMBS_521BIT];
139 limb_t y[NUM_LIMBS_521BIT];
148 memcpy_P(x, P521_Gx,
sizeof(x));
149 memcpy_P(y, P521_Gy,
sizeof(y));
233 limb_t x[NUM_LIMBS_521BIT];
234 limb_t y[NUM_LIMBS_521BIT];
239 bool ok = validate(x, y);
277 void P521::sign(uint8_t signature[132],
const uint8_t privateKey[66],
278 const void *message,
size_t len,
Hash *hash)
282 limb_t x[NUM_LIMBS_521BIT];
283 limb_t y[NUM_LIMBS_521BIT];
284 limb_t t[NUM_LIMBS_521BIT];
291 hash->
update(message, len);
295 memset(hm, 0, 66 - len);
301 memset(hm, 0, 66 - len);
302 memcpy(hm + 66 - len, message, len);
309 generateK(k, hm, privateKey, hash, count);
311 generateK(k, hm, privateKey, count);
314 memcpy_P(x, P521_Gx,
sizeof(x));
315 memcpy_P(y, P521_Gy,
sizeof(y));
375 const uint8_t publicKey[132],
376 const void *message,
size_t len,
Hash *hash)
378 limb_t x[NUM_LIMBS_521BIT];
379 limb_t y[NUM_LIMBS_521BIT];
380 limb_t r[NUM_LIMBS_521BIT];
381 limb_t s[NUM_LIMBS_521BIT];
382 limb_t u1[NUM_LIMBS_521BIT];
383 limb_t u2[NUM_LIMBS_521BIT];
404 if (!validate(x, y)) {
412 hash->
update(message, len);
433 memcpy_P(u2, P521_Gx,
sizeof(x));
434 memcpy_P(s, P521_Gy,
sizeof(y));
437 addAffine(u2, s, x, y);
441 ok = secure_compare(u1, r, NUM_LIMBS_521BIT *
sizeof(limb_t));
474 limb_t x[NUM_LIMBS_521BIT];
476 RNG.
rand((uint8_t *)x,
sizeof(x));
477 #if BIGNUMBER_LIMB_8BIT
478 x[NUM_LIMBS_521BIT - 1] &= 0x01;
480 x[NUM_LIMBS_521BIT - 1] &= 0x1FF;
501 limb_t x[NUM_LIMBS_521BIT];
502 limb_t y[NUM_LIMBS_521BIT];
503 memcpy_P(x, P521_Gx,
sizeof(x));
504 memcpy_P(y, P521_Gy,
sizeof(y));
505 evaluate(x, y, privateKey);
528 static uint8_t
const P521_q_bytes[66] PROGMEM = {
529 0x01, 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, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
533 0xFF, 0xFA, 0x51, 0x86, 0x87, 0x83, 0xBF, 0x2F,
534 0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09,
535 0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C,
536 0x47, 0xAE, 0xBB, 0x6F, 0xB7, 0x1E, 0x91, 0x38,
539 uint8_t zeroTest = 0;
546 zeroTest |= privateKey[posn];
550 borrow = ((uint16_t)(privateKey[posn])) -
551 pgm_read_byte(&(P521_q_bytes[posn])) -
552 ((borrow >> 8) & 0x01);
554 return zeroTest != 0 && borrow != 0;
567 limb_t x[NUM_LIMBS_521BIT];
568 limb_t y[NUM_LIMBS_521BIT];
571 bool ok = validate(x, y);
598 void P521::evaluate(limb_t *x, limb_t *y,
const uint8_t f[66])
600 limb_t x1[NUM_LIMBS_521BIT];
601 limb_t y1[NUM_LIMBS_521BIT];
602 limb_t z1[NUM_LIMBS_521BIT];
603 limb_t x2[NUM_LIMBS_521BIT];
604 limb_t y2[NUM_LIMBS_521BIT];
605 limb_t z2[NUM_LIMBS_521BIT];
613 memset(x1, 0,
sizeof(x1));
614 memset(y1, 0,
sizeof(y1));
615 memset(z1, 0,
sizeof(z1));
619 uint8_t select = (f[0] & 0x01);
620 cmove(select, x1, x);
621 cmove(select, y1, y);
627 for (uint16_t t = 520; t > 0; --t) {
629 dblPoint(x1, y1, z1, x1, y1, z1);
634 addPoint(x2, y2, z2, x1, y1, z1, x, y);
637 select = (f[fposn] & mask);
638 cmove(select, x1, x2);
639 cmove(select, y1, y2);
640 cmove(select, z1, z2);
677 void P521::addAffine(limb_t *x1, limb_t *y1,
const limb_t *x2,
const limb_t *y2)
679 limb_t xout[NUM_LIMBS_521BIT];
680 limb_t yout[NUM_LIMBS_521BIT];
681 limb_t zout[NUM_LIMBS_521BIT];
682 limb_t z1[NUM_LIMBS_521BIT];
686 memset(z1 + 1, 0, (NUM_LIMBS_521BIT - 1) *
sizeof(limb_t));
689 addPoint(xout, yout, zout, x1, y1, z1, x2, y2);
715 bool P521::validate(
const limb_t *x,
const limb_t *y)
723 result &= inRange(y);
726 limb_t t1[NUM_LIMBS_521BIT];
727 limb_t t2[NUM_LIMBS_521BIT];
730 mulLiteral(t2, x, 3);
732 memcpy_P(t2, P521_b,
sizeof(t2));
735 result &= secure_compare(t1, t2,
sizeof(t1));
749 bool P521::inRange(
const limb_t *x)
755 for (uint8_t index = 0; index < NUM_LIMBS_521BIT; ++index) {
757 word = (limb_t)carry;
762 #if BIGNUMBER_LIMB_8BIT
763 carry = (carry << 7) + (word >> 1);
765 carry = (carry << (LIMB_BITS - 9)) + (word >> 9);
770 word = (limb_t)(carry | (carry >> LIMB_BITS));
771 word = (limb_t)(((((dlimb_t)1) << LIMB_BITS) - word) >> LIMB_BITS);
784 void P521::reduce(limb_t *result,
const limb_t *x)
786 #if BIGNUMBER_LIMB_16BIT || BIGNUMBER_LIMB_32BIT
792 const limb_t *xl = x;
793 const limb_t *xh = x + NUM_LIMBS_521BIT;
796 limb_t word = x[NUM_LIMBS_521BIT - 1];
797 carry = (word >> 9) + 1;
799 for (index = 0; index < (NUM_LIMBS_521BIT - 1); ++index) {
801 carry += ((dlimb_t)(*xh++)) << (LIMB_BITS - 9);
802 *rr++ = (limb_t)carry;
806 carry += ((dlimb_t)(x[NUM_LIMBS_1042BIT - 1])) << (LIMB_BITS - 9);
807 word = (limb_t)carry;
814 carry = ((word >> 9) ^ 0x01) & 0x01;
816 for (index = 0; index < NUM_LIMBS_521BIT; ++index) {
817 carry = ((dlimb_t)(*rr)) - carry;
818 *rr++ = (limb_t)carry;
819 carry = (carry >> LIMB_BITS) & 0x01;
822 #elif BIGNUMBER_LIMB_8BIT
825 const limb_t *xl = x;
826 const limb_t *xh = x + NUM_LIMBS_521BIT;
829 limb_t word = x[NUM_LIMBS_521BIT - 1];
830 carry = (word >> 1) + 1;
832 for (index = 0; index < (NUM_LIMBS_521BIT - 1); ++index) {
834 carry += ((dlimb_t)(*xh++)) << 7;
835 *rr++ = (limb_t)carry;
839 carry += ((dlimb_t)(x[NUM_LIMBS_1042BIT - 1])) << 1;
840 word = (limb_t)carry;
842 carry = ((word >> 1) ^ 0x01) & 0x01;
844 for (index = 0; index < NUM_LIMBS_521BIT; ++index) {
845 carry = ((dlimb_t)(*rr)) - carry;
846 *rr++ = (limb_t)carry;
847 carry = (carry >> LIMB_BITS) & 0x01;
851 #error "Don't know how to reduce values mod 2^521 - 1"
867 void P521::reduceQuick(limb_t *x)
874 for (index = 0; index < NUM_LIMBS_521BIT; ++index) {
876 *xx++ = (limb_t)carry;
884 #if BIGNUMBER_LIMB_16BIT || BIGNUMBER_LIMB_32BIT
885 carry = ((x[NUM_LIMBS_521BIT - 1] >> 9) ^ 0x01) & 0x01;
887 for (index = 0; index < NUM_LIMBS_521BIT; ++index) {
888 carry = ((dlimb_t)(*xx)) - carry;
889 *xx++ = (limb_t)carry;
890 carry = (carry >> LIMB_BITS) & 0x01;
893 #elif BIGNUMBER_LIMB_8BIT
894 carry = ((x[NUM_LIMBS_521BIT - 1] >> 1) ^ 0x01) & 0x01;
896 for (index = 0; index < NUM_LIMBS_521BIT; ++index) {
897 carry = ((dlimb_t)(*xx)) - carry;
898 *xx++ = (limb_t)carry;
899 carry = (carry >> LIMB_BITS) & 0x01;
917 void P521::mulNoReduce(limb_t *result,
const limb_t *x,
const limb_t *y)
930 for (i = 0; i < NUM_LIMBS_521BIT; ++i) {
931 carry += ((dlimb_t)(*yy++)) * word;
932 *rr++ = (limb_t)carry;
938 for (i = 1; i < NUM_LIMBS_521BIT; ++i) {
943 for (j = 0; j < NUM_LIMBS_521BIT; ++j) {
944 carry += ((dlimb_t)(*yy++)) * word;
946 *rr++ = (limb_t)carry;
963 void P521::mul(limb_t *result,
const limb_t *x,
const limb_t *y)
965 limb_t temp[NUM_LIMBS_1042BIT];
966 mulNoReduce(temp, x, y);
967 reduce(result, temp);
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
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(0x6EC79BF7), LIMB(0x449048E1), LIMB(0x7663B851), LIMB(0xC44A3647),
1396 LIMB(0x08F65A2F), LIMB(0x8033FEB7), LIMB(0x40D06994), LIMB(0xAE79787C),
1397 LIMB(0x00000005), LIMB(0x00000000), LIMB(0x00000000), LIMB(0x00000000),
1398 LIMB(0x00000000), LIMB(0x00000000), LIMB(0x00000000), LIMB(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
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])) << 14;
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(0x91386407), LIMB(0xbb6fb71e), LIMB(0x899c47ae), LIMB(0x3bb5c9b8),
1470 LIMB(0xf709a5d0), LIMB(0x7fcc0148), LIMB(0xbf2f966b), LIMB(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 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.