123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307 |
- /* Arithmetic mod p = 2^255-19
- * Daniel Beer <dlbeer@gmail.com>, 5 Jan 2014
- *
- * This file is in the public domain.
- */
- #include "f25519.h"
- const uint8_t f25519_one[F25519_SIZE] = {1};
- void f25519_load(uint8_t *x, uint32_t c)
- {
- int i;
- for (i = 0; i < sizeof(c); i++) {
- x[i] = c;
- c >>= 8;
- }
- for (; i < F25519_SIZE; i++)
- x[i] = 0;
- }
- void f25519_normalize(uint8_t *x)
- {
- uint8_t minusp[F25519_SIZE];
- uint16_t c;
- int i;
- /* Reduce using 2^255 = 19 mod p */
- c = (x[31] >> 7) * 19;
- x[31] &= 127;
- for (i = 0; i < F25519_SIZE; i++) {
- c += x[i];
- x[i] = c;
- c >>= 8;
- }
- /* The number is now less than 2^255 + 18, and therefore less than
- * 2p. Try subtracting p, and conditionally load the subtracted
- * value if underflow did not occur.
- */
- c = 19;
- for (i = 0; i + 1 < F25519_SIZE; i++) {
- c += x[i];
- minusp[i] = c;
- c >>= 8;
- }
- c += ((uint16_t)x[i]) - 128;
- minusp[31] = c;
- /* Load x-p if no underflow */
- f25519_select(x, minusp, x, (c >> 15) & 1);
- }
- uint8_t f25519_eq(const uint8_t *x, const uint8_t *y)
- {
- uint8_t sum = 0;
- int i;
- for (i = 0; i < F25519_SIZE; i++)
- sum |= x[i] ^ y[i];
- sum |= (sum >> 4);
- sum |= (sum >> 2);
- sum |= (sum >> 1);
- return (sum ^ 1) & 1;
- }
- void f25519_select(uint8_t *dst,
- const uint8_t *zero, const uint8_t *one,
- uint8_t condition)
- {
- const uint8_t mask = -condition;
- int i;
- for (i = 0; i < F25519_SIZE; i++)
- dst[i] = zero[i] ^ (mask & (one[i] ^ zero[i]));
- }
- void f25519_add(uint8_t *r, const uint8_t *a, const uint8_t *b)
- {
- uint16_t c = 0;
- int i;
- /* Add */
- for (i = 0; i < F25519_SIZE; i++) {
- c >>= 8;
- c += ((uint16_t)a[i]) + ((uint16_t)b[i]);
- r[i] = c;
- }
- /* Reduce with 2^255 = 19 mod p */
- r[31] &= 127;
- c = (c >> 7) * 19;
- for (i = 0; i < F25519_SIZE; i++) {
- c += r[i];
- r[i] = c;
- c >>= 8;
- }
- }
- void f25519_sub(uint8_t *r, const uint8_t *a, const uint8_t *b)
- {
- uint32_t c = 0;
- int i;
- /* Calculate a + 2p - b, to avoid underflow */
- c = 218;
- for (i = 0; i + 1 < F25519_SIZE; i++) {
- c += 65280 + ((uint32_t)a[i]) - ((uint32_t)b[i]);
- r[i] = c;
- c >>= 8;
- }
- c += ((uint32_t)a[31]) - ((uint32_t)b[31]);
- r[31] = c & 127;
- c = (c >> 7) * 19;
- for (i = 0; i < F25519_SIZE; i++) {
- c += r[i];
- r[i] = c;
- c >>= 8;
- }
- }
- void f25519_neg(uint8_t *r, const uint8_t *a)
- {
- uint32_t c = 0;
- int i;
- /* Calculate 2p - a, to avoid underflow */
- c = 218;
- for (i = 0; i + 1 < F25519_SIZE; i++) {
- c += 65280 - ((uint32_t)a[i]);
- r[i] = c;
- c >>= 8;
- }
- c -= ((uint32_t)a[31]);
- r[31] = c & 127;
- c = (c >> 7) * 19;
- for (i = 0; i < F25519_SIZE; i++) {
- c += r[i];
- r[i] = c;
- c >>= 8;
- }
- }
- void f25519_mul__distinct(uint8_t *r, const uint8_t *a, const uint8_t *b)
- {
- uint32_t c = 0;
- int i;
- for (i = 0; i < F25519_SIZE; i++) {
- int j;
- c >>= 8;
- for (j = 0; j <= i; j++)
- c += ((uint32_t)a[j]) * ((uint32_t)b[i - j]);
- for (; j < F25519_SIZE; j++)
- c += ((uint32_t)a[j]) *
- ((uint32_t)b[i + F25519_SIZE - j]) * 38;
- r[i] = c;
- }
- r[31] &= 127;
- c = (c >> 7) * 19;
- for (i = 0; i < F25519_SIZE; i++) {
- c += r[i];
- r[i] = c;
- c >>= 8;
- }
- }
- static void f25519_mul_c(uint8_t *r, const uint8_t *a, uint32_t b)
- {
- uint32_t c = 0;
- int i;
- for (i = 0; i < F25519_SIZE; i++) {
- c >>= 8;
- c += b * ((uint32_t)a[i]);
- r[i] = c;
- }
- r[31] &= 127;
- c >>= 7;
- c *= 19;
- for (i = 0; i < F25519_SIZE; i++) {
- c += r[i];
- r[i] = c;
- c >>= 8;
- }
- }
- void f25519_inv__distinct(uint8_t *r, const uint8_t *x)
- {
- uint8_t s[F25519_SIZE];
- int i;
- /* This is a prime field, so by Fermat's little theorem:
- *
- * x^(p-1) = 1 mod p
- *
- * Therefore, raise to (p-2) = 2^255-21 to get a multiplicative
- * inverse.
- *
- * This is a 255-bit binary number with the digits:
- *
- * 11111111... 01011
- *
- * We compute the result by the usual binary chain, but
- * alternate between keeping the accumulator in r and s, so as
- * to avoid copying temporaries.
- */
- /* 1 1 */
- f25519_mul__distinct(s, x, x);
- f25519_mul__distinct(r, s, x);
- /* 1 x 248 */
- for (i = 0; i < 248; i++) {
- f25519_mul__distinct(s, r, r);
- f25519_mul__distinct(r, s, x);
- }
- /* 0 */
- f25519_mul__distinct(s, r, r);
- /* 1 */
- f25519_mul__distinct(r, s, s);
- f25519_mul__distinct(s, r, x);
- /* 0 */
- f25519_mul__distinct(r, s, s);
- /* 1 */
- f25519_mul__distinct(s, r, r);
- f25519_mul__distinct(r, s, x);
- /* 1 */
- f25519_mul__distinct(s, r, r);
- f25519_mul__distinct(r, s, x);
- }
- /* Raise x to the power of (p-5)/8 = 2^252-3, using s for temporary
- * storage.
- */
- static void exp2523(uint8_t *r, const uint8_t *x, uint8_t *s)
- {
- int i;
- /* This number is a 252-bit number with the binary expansion:
- *
- * 111111... 01
- */
- /* 1 1 */
- f25519_mul__distinct(r, x, x);
- f25519_mul__distinct(s, r, x);
- /* 1 x 248 */
- for (i = 0; i < 248; i++) {
- f25519_mul__distinct(r, s, s);
- f25519_mul__distinct(s, r, x);
- }
- /* 0 */
- f25519_mul__distinct(r, s, s);
- /* 1 */
- f25519_mul__distinct(s, r, r);
- f25519_mul__distinct(r, s, x);
- }
- void f25519_sqrt(uint8_t *r, const uint8_t *a)
- {
- uint8_t v[F25519_SIZE];
- uint8_t i[F25519_SIZE];
- uint8_t x[F25519_SIZE];
- uint8_t y[F25519_SIZE];
- /* v = (2a)^((p-5)/8) [x = 2a] */
- f25519_mul_c(x, a, 2);
- exp2523(v, x, y);
- /* i = 2av^2 - 1 */
- f25519_mul__distinct(y, v, v);
- f25519_mul__distinct(i, x, y);
- f25519_load(y, 1);
- f25519_sub(i, i, y);
- /* r = avi */
- f25519_mul__distinct(x, v, a);
- f25519_mul__distinct(r, x, i);
- }
|