f25519.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. /* Arithmetic mod p = 2^255-19
  2. * Daniel Beer <dlbeer@gmail.com>, 5 Jan 2014
  3. *
  4. * This file is in the public domain.
  5. */
  6. #include "f25519.h"
  7. const uint8_t f25519_one[F25519_SIZE] = {1};
  8. void f25519_load(uint8_t *x, uint32_t c)
  9. {
  10. int i;
  11. for (i = 0; i < sizeof(c); i++) {
  12. x[i] = c;
  13. c >>= 8;
  14. }
  15. for (; i < F25519_SIZE; i++)
  16. x[i] = 0;
  17. }
  18. void f25519_normalize(uint8_t *x)
  19. {
  20. uint8_t minusp[F25519_SIZE];
  21. uint16_t c;
  22. int i;
  23. /* Reduce using 2^255 = 19 mod p */
  24. c = (x[31] >> 7) * 19;
  25. x[31] &= 127;
  26. for (i = 0; i < F25519_SIZE; i++) {
  27. c += x[i];
  28. x[i] = c;
  29. c >>= 8;
  30. }
  31. /* The number is now less than 2^255 + 18, and therefore less than
  32. * 2p. Try subtracting p, and conditionally load the subtracted
  33. * value if underflow did not occur.
  34. */
  35. c = 19;
  36. for (i = 0; i + 1 < F25519_SIZE; i++) {
  37. c += x[i];
  38. minusp[i] = c;
  39. c >>= 8;
  40. }
  41. c += ((uint16_t)x[i]) - 128;
  42. minusp[31] = c;
  43. /* Load x-p if no underflow */
  44. f25519_select(x, minusp, x, (c >> 15) & 1);
  45. }
  46. uint8_t f25519_eq(const uint8_t *x, const uint8_t *y)
  47. {
  48. uint8_t sum = 0;
  49. int i;
  50. for (i = 0; i < F25519_SIZE; i++)
  51. sum |= x[i] ^ y[i];
  52. sum |= (sum >> 4);
  53. sum |= (sum >> 2);
  54. sum |= (sum >> 1);
  55. return (sum ^ 1) & 1;
  56. }
  57. void f25519_select(uint8_t *dst,
  58. const uint8_t *zero, const uint8_t *one,
  59. uint8_t condition)
  60. {
  61. const uint8_t mask = -condition;
  62. int i;
  63. for (i = 0; i < F25519_SIZE; i++)
  64. dst[i] = zero[i] ^ (mask & (one[i] ^ zero[i]));
  65. }
  66. void f25519_add(uint8_t *r, const uint8_t *a, const uint8_t *b)
  67. {
  68. uint16_t c = 0;
  69. int i;
  70. /* Add */
  71. for (i = 0; i < F25519_SIZE; i++) {
  72. c >>= 8;
  73. c += ((uint16_t)a[i]) + ((uint16_t)b[i]);
  74. r[i] = c;
  75. }
  76. /* Reduce with 2^255 = 19 mod p */
  77. r[31] &= 127;
  78. c = (c >> 7) * 19;
  79. for (i = 0; i < F25519_SIZE; i++) {
  80. c += r[i];
  81. r[i] = c;
  82. c >>= 8;
  83. }
  84. }
  85. void f25519_sub(uint8_t *r, const uint8_t *a, const uint8_t *b)
  86. {
  87. uint32_t c = 0;
  88. int i;
  89. /* Calculate a + 2p - b, to avoid underflow */
  90. c = 218;
  91. for (i = 0; i + 1 < F25519_SIZE; i++) {
  92. c += 65280 + ((uint32_t)a[i]) - ((uint32_t)b[i]);
  93. r[i] = c;
  94. c >>= 8;
  95. }
  96. c += ((uint32_t)a[31]) - ((uint32_t)b[31]);
  97. r[31] = c & 127;
  98. c = (c >> 7) * 19;
  99. for (i = 0; i < F25519_SIZE; i++) {
  100. c += r[i];
  101. r[i] = c;
  102. c >>= 8;
  103. }
  104. }
  105. void f25519_neg(uint8_t *r, const uint8_t *a)
  106. {
  107. uint32_t c = 0;
  108. int i;
  109. /* Calculate 2p - a, to avoid underflow */
  110. c = 218;
  111. for (i = 0; i + 1 < F25519_SIZE; i++) {
  112. c += 65280 - ((uint32_t)a[i]);
  113. r[i] = c;
  114. c >>= 8;
  115. }
  116. c -= ((uint32_t)a[31]);
  117. r[31] = c & 127;
  118. c = (c >> 7) * 19;
  119. for (i = 0; i < F25519_SIZE; i++) {
  120. c += r[i];
  121. r[i] = c;
  122. c >>= 8;
  123. }
  124. }
  125. void f25519_mul__distinct(uint8_t *r, const uint8_t *a, const uint8_t *b)
  126. {
  127. uint32_t c = 0;
  128. int i;
  129. for (i = 0; i < F25519_SIZE; i++) {
  130. int j;
  131. c >>= 8;
  132. for (j = 0; j <= i; j++)
  133. c += ((uint32_t)a[j]) * ((uint32_t)b[i - j]);
  134. for (; j < F25519_SIZE; j++)
  135. c += ((uint32_t)a[j]) *
  136. ((uint32_t)b[i + F25519_SIZE - j]) * 38;
  137. r[i] = c;
  138. }
  139. r[31] &= 127;
  140. c = (c >> 7) * 19;
  141. for (i = 0; i < F25519_SIZE; i++) {
  142. c += r[i];
  143. r[i] = c;
  144. c >>= 8;
  145. }
  146. }
  147. static void f25519_mul_c(uint8_t *r, const uint8_t *a, uint32_t b)
  148. {
  149. uint32_t c = 0;
  150. int i;
  151. for (i = 0; i < F25519_SIZE; i++) {
  152. c >>= 8;
  153. c += b * ((uint32_t)a[i]);
  154. r[i] = c;
  155. }
  156. r[31] &= 127;
  157. c >>= 7;
  158. c *= 19;
  159. for (i = 0; i < F25519_SIZE; i++) {
  160. c += r[i];
  161. r[i] = c;
  162. c >>= 8;
  163. }
  164. }
  165. void f25519_inv__distinct(uint8_t *r, const uint8_t *x)
  166. {
  167. uint8_t s[F25519_SIZE];
  168. int i;
  169. /* This is a prime field, so by Fermat's little theorem:
  170. *
  171. * x^(p-1) = 1 mod p
  172. *
  173. * Therefore, raise to (p-2) = 2^255-21 to get a multiplicative
  174. * inverse.
  175. *
  176. * This is a 255-bit binary number with the digits:
  177. *
  178. * 11111111... 01011
  179. *
  180. * We compute the result by the usual binary chain, but
  181. * alternate between keeping the accumulator in r and s, so as
  182. * to avoid copying temporaries.
  183. */
  184. /* 1 1 */
  185. f25519_mul__distinct(s, x, x);
  186. f25519_mul__distinct(r, s, x);
  187. /* 1 x 248 */
  188. for (i = 0; i < 248; i++) {
  189. f25519_mul__distinct(s, r, r);
  190. f25519_mul__distinct(r, s, x);
  191. }
  192. /* 0 */
  193. f25519_mul__distinct(s, r, r);
  194. /* 1 */
  195. f25519_mul__distinct(r, s, s);
  196. f25519_mul__distinct(s, r, x);
  197. /* 0 */
  198. f25519_mul__distinct(r, s, s);
  199. /* 1 */
  200. f25519_mul__distinct(s, r, r);
  201. f25519_mul__distinct(r, s, x);
  202. /* 1 */
  203. f25519_mul__distinct(s, r, r);
  204. f25519_mul__distinct(r, s, x);
  205. }
  206. /* Raise x to the power of (p-5)/8 = 2^252-3, using s for temporary
  207. * storage.
  208. */
  209. static void exp2523(uint8_t *r, const uint8_t *x, uint8_t *s)
  210. {
  211. int i;
  212. /* This number is a 252-bit number with the binary expansion:
  213. *
  214. * 111111... 01
  215. */
  216. /* 1 1 */
  217. f25519_mul__distinct(r, x, x);
  218. f25519_mul__distinct(s, r, x);
  219. /* 1 x 248 */
  220. for (i = 0; i < 248; i++) {
  221. f25519_mul__distinct(r, s, s);
  222. f25519_mul__distinct(s, r, x);
  223. }
  224. /* 0 */
  225. f25519_mul__distinct(r, s, s);
  226. /* 1 */
  227. f25519_mul__distinct(s, r, r);
  228. f25519_mul__distinct(r, s, x);
  229. }
  230. void f25519_sqrt(uint8_t *r, const uint8_t *a)
  231. {
  232. uint8_t v[F25519_SIZE];
  233. uint8_t i[F25519_SIZE];
  234. uint8_t x[F25519_SIZE];
  235. uint8_t y[F25519_SIZE];
  236. /* v = (2a)^((p-5)/8) [x = 2a] */
  237. f25519_mul_c(x, a, 2);
  238. exp2523(v, x, y);
  239. /* i = 2av^2 - 1 */
  240. f25519_mul__distinct(y, v, v);
  241. f25519_mul__distinct(i, x, y);
  242. f25519_load(y, 1);
  243. f25519_sub(i, i, y);
  244. /* r = avi */
  245. f25519_mul__distinct(x, v, a);
  246. f25519_mul__distinct(r, x, i);
  247. }