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.