1
0

modm-donna-32bit.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. /*
  2. Public domain by Andrew M. <liquidsun@gmail.com>
  3. */
  4. /* separate uint128 check for 64 bit sse2 */
  5. #if !defined(HAVE_UINT128) || defined(ED25519_FORCE_32BIT)
  6. /*
  7. Arithmetic modulo the group order n = 2^252 + 27742317777372353535851937790883648493 = 7237005577332262213973186563042994240857116359379907606001950938285454250989
  8. k = 32
  9. b = 1 << 8 = 256
  10. m = 2^252 + 27742317777372353535851937790883648493 = 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed
  11. mu = floor( b^(k*2) / m ) = 0xfffffffffffffffffffffffffffffffeb2106215d086329a7ed9ce5a30a2c131b
  12. */
  13. #define bignum256modm_bits_per_limb 30
  14. #define bignum256modm_limb_size 9
  15. typedef uint32_t bignum256modm_element_t;
  16. typedef bignum256modm_element_t bignum256modm[9];
  17. static const bignum256modm modm_m = {
  18. 0x1cf5d3ed, 0x20498c69, 0x2f79cd65, 0x37be77a8,
  19. 0x00000014, 0x00000000, 0x00000000, 0x00000000,
  20. 0x00001000
  21. };
  22. static const bignum256modm modm_mu = {
  23. 0x0a2c131b, 0x3673968c, 0x06329a7e, 0x01885742,
  24. 0x3fffeb21, 0x3fffffff, 0x3fffffff, 0x3fffffff,
  25. 0x000fffff
  26. };
  27. static bignum256modm_element_t
  28. lt_modm(bignum256modm_element_t a, bignum256modm_element_t b) {
  29. return (a - b) >> 31;
  30. }
  31. /* see HAC, Alg. 14.42 Step 4 */
  32. static void
  33. reduce256_modm(bignum256modm r) {
  34. bignum256modm t;
  35. bignum256modm_element_t b = 0, pb, mask;
  36. /* t = r - m */
  37. pb = 0;
  38. pb += modm_m[0]; b = lt_modm(r[0], pb); t[0] = (r[0] - pb + (b << 30)); pb = b;
  39. pb += modm_m[1]; b = lt_modm(r[1], pb); t[1] = (r[1] - pb + (b << 30)); pb = b;
  40. pb += modm_m[2]; b = lt_modm(r[2], pb); t[2] = (r[2] - pb + (b << 30)); pb = b;
  41. pb += modm_m[3]; b = lt_modm(r[3], pb); t[3] = (r[3] - pb + (b << 30)); pb = b;
  42. pb += modm_m[4]; b = lt_modm(r[4], pb); t[4] = (r[4] - pb + (b << 30)); pb = b;
  43. pb += modm_m[5]; b = lt_modm(r[5], pb); t[5] = (r[5] - pb + (b << 30)); pb = b;
  44. pb += modm_m[6]; b = lt_modm(r[6], pb); t[6] = (r[6] - pb + (b << 30)); pb = b;
  45. pb += modm_m[7]; b = lt_modm(r[7], pb); t[7] = (r[7] - pb + (b << 30)); pb = b;
  46. pb += modm_m[8]; b = lt_modm(r[8], pb); t[8] = (r[8] - pb + (b << 16));
  47. /* keep r if r was smaller than m */
  48. mask = b - 1;
  49. r[0] ^= mask & (r[0] ^ t[0]);
  50. r[1] ^= mask & (r[1] ^ t[1]);
  51. r[2] ^= mask & (r[2] ^ t[2]);
  52. r[3] ^= mask & (r[3] ^ t[3]);
  53. r[4] ^= mask & (r[4] ^ t[4]);
  54. r[5] ^= mask & (r[5] ^ t[5]);
  55. r[6] ^= mask & (r[6] ^ t[6]);
  56. r[7] ^= mask & (r[7] ^ t[7]);
  57. r[8] ^= mask & (r[8] ^ t[8]);
  58. }
  59. /*
  60. Barrett reduction, see HAC, Alg. 14.42
  61. Instead of passing in x, pre-process in to q1 and r1 for efficiency
  62. */
  63. static void
  64. barrett_reduce256_modm(bignum256modm r, const bignum256modm q1, const bignum256modm r1) {
  65. bignum256modm q3, r2;
  66. uint64_t c;
  67. bignum256modm_element_t f, b, pb;
  68. /* q1 = x >> 248 = 264 bits = 9 30 bit elements
  69. q2 = mu * q1
  70. q3 = (q2 / 256(32+1)) = q2 / (2^8)^(32+1) = q2 >> 264 */
  71. c = mul32x32_64(modm_mu[0], q1[7]) + mul32x32_64(modm_mu[1], q1[6]) + mul32x32_64(modm_mu[2], q1[5]) + mul32x32_64(modm_mu[3], q1[4]) + mul32x32_64(modm_mu[4], q1[3]) + mul32x32_64(modm_mu[5], q1[2]) + mul32x32_64(modm_mu[6], q1[1]) + mul32x32_64(modm_mu[7], q1[0]);
  72. c >>= 30;
  73. c += mul32x32_64(modm_mu[0], q1[8]) + mul32x32_64(modm_mu[1], q1[7]) + mul32x32_64(modm_mu[2], q1[6]) + mul32x32_64(modm_mu[3], q1[5]) + mul32x32_64(modm_mu[4], q1[4]) + mul32x32_64(modm_mu[5], q1[3]) + mul32x32_64(modm_mu[6], q1[2]) + mul32x32_64(modm_mu[7], q1[1]) + mul32x32_64(modm_mu[8], q1[0]);
  74. f = (bignum256modm_element_t)c; q3[0] = (f >> 24) & 0x3f; c >>= 30;
  75. c += mul32x32_64(modm_mu[1], q1[8]) + mul32x32_64(modm_mu[2], q1[7]) + mul32x32_64(modm_mu[3], q1[6]) + mul32x32_64(modm_mu[4], q1[5]) + mul32x32_64(modm_mu[5], q1[4]) + mul32x32_64(modm_mu[6], q1[3]) + mul32x32_64(modm_mu[7], q1[2]) + mul32x32_64(modm_mu[8], q1[1]);
  76. f = (bignum256modm_element_t)c; q3[0] |= (f << 6) & 0x3fffffff; q3[1] = (f >> 24) & 0x3f; c >>= 30;
  77. c += mul32x32_64(modm_mu[2], q1[8]) + mul32x32_64(modm_mu[3], q1[7]) + mul32x32_64(modm_mu[4], q1[6]) + mul32x32_64(modm_mu[5], q1[5]) + mul32x32_64(modm_mu[6], q1[4]) + mul32x32_64(modm_mu[7], q1[3]) + mul32x32_64(modm_mu[8], q1[2]);
  78. f = (bignum256modm_element_t)c; q3[1] |= (f << 6) & 0x3fffffff; q3[2] = (f >> 24) & 0x3f; c >>= 30;
  79. c += mul32x32_64(modm_mu[3], q1[8]) + mul32x32_64(modm_mu[4], q1[7]) + mul32x32_64(modm_mu[5], q1[6]) + mul32x32_64(modm_mu[6], q1[5]) + mul32x32_64(modm_mu[7], q1[4]) + mul32x32_64(modm_mu[8], q1[3]);
  80. f = (bignum256modm_element_t)c; q3[2] |= (f << 6) & 0x3fffffff; q3[3] = (f >> 24) & 0x3f; c >>= 30;
  81. c += mul32x32_64(modm_mu[4], q1[8]) + mul32x32_64(modm_mu[5], q1[7]) + mul32x32_64(modm_mu[6], q1[6]) + mul32x32_64(modm_mu[7], q1[5]) + mul32x32_64(modm_mu[8], q1[4]);
  82. f = (bignum256modm_element_t)c; q3[3] |= (f << 6) & 0x3fffffff; q3[4] = (f >> 24) & 0x3f; c >>= 30;
  83. c += mul32x32_64(modm_mu[5], q1[8]) + mul32x32_64(modm_mu[6], q1[7]) + mul32x32_64(modm_mu[7], q1[6]) + mul32x32_64(modm_mu[8], q1[5]);
  84. f = (bignum256modm_element_t)c; q3[4] |= (f << 6) & 0x3fffffff; q3[5] = (f >> 24) & 0x3f; c >>= 30;
  85. c += mul32x32_64(modm_mu[6], q1[8]) + mul32x32_64(modm_mu[7], q1[7]) + mul32x32_64(modm_mu[8], q1[6]);
  86. f = (bignum256modm_element_t)c; q3[5] |= (f << 6) & 0x3fffffff; q3[6] = (f >> 24) & 0x3f; c >>= 30;
  87. c += mul32x32_64(modm_mu[7], q1[8]) + mul32x32_64(modm_mu[8], q1[7]);
  88. f = (bignum256modm_element_t)c; q3[6] |= (f << 6) & 0x3fffffff; q3[7] = (f >> 24) & 0x3f; c >>= 30;
  89. c += mul32x32_64(modm_mu[8], q1[8]);
  90. f = (bignum256modm_element_t)c; q3[7] |= (f << 6) & 0x3fffffff; q3[8] = (bignum256modm_element_t)(c >> 24);
  91. /* r1 = (x mod 256^(32+1)) = x mod (2^8)(31+1) = x & ((1 << 264) - 1)
  92. r2 = (q3 * m) mod (256^(32+1)) = (q3 * m) & ((1 << 264) - 1) */
  93. c = mul32x32_64(modm_m[0], q3[0]);
  94. r2[0] = (bignum256modm_element_t)(c & 0x3fffffff); c >>= 30;
  95. c += mul32x32_64(modm_m[0], q3[1]) + mul32x32_64(modm_m[1], q3[0]);
  96. r2[1] = (bignum256modm_element_t)(c & 0x3fffffff); c >>= 30;
  97. c += mul32x32_64(modm_m[0], q3[2]) + mul32x32_64(modm_m[1], q3[1]) + mul32x32_64(modm_m[2], q3[0]);
  98. r2[2] = (bignum256modm_element_t)(c & 0x3fffffff); c >>= 30;
  99. c += mul32x32_64(modm_m[0], q3[3]) + mul32x32_64(modm_m[1], q3[2]) + mul32x32_64(modm_m[2], q3[1]) + mul32x32_64(modm_m[3], q3[0]);
  100. r2[3] = (bignum256modm_element_t)(c & 0x3fffffff); c >>= 30;
  101. c += mul32x32_64(modm_m[0], q3[4]) + mul32x32_64(modm_m[1], q3[3]) + mul32x32_64(modm_m[2], q3[2]) + mul32x32_64(modm_m[3], q3[1]) + mul32x32_64(modm_m[4], q3[0]);
  102. r2[4] = (bignum256modm_element_t)(c & 0x3fffffff); c >>= 30;
  103. c += mul32x32_64(modm_m[0], q3[5]) + mul32x32_64(modm_m[1], q3[4]) + mul32x32_64(modm_m[2], q3[3]) + mul32x32_64(modm_m[3], q3[2]) + mul32x32_64(modm_m[4], q3[1]) + mul32x32_64(modm_m[5], q3[0]);
  104. r2[5] = (bignum256modm_element_t)(c & 0x3fffffff); c >>= 30;
  105. c += mul32x32_64(modm_m[0], q3[6]) + mul32x32_64(modm_m[1], q3[5]) + mul32x32_64(modm_m[2], q3[4]) + mul32x32_64(modm_m[3], q3[3]) + mul32x32_64(modm_m[4], q3[2]) + mul32x32_64(modm_m[5], q3[1]) + mul32x32_64(modm_m[6], q3[0]);
  106. r2[6] = (bignum256modm_element_t)(c & 0x3fffffff); c >>= 30;
  107. c += mul32x32_64(modm_m[0], q3[7]) + mul32x32_64(modm_m[1], q3[6]) + mul32x32_64(modm_m[2], q3[5]) + mul32x32_64(modm_m[3], q3[4]) + mul32x32_64(modm_m[4], q3[3]) + mul32x32_64(modm_m[5], q3[2]) + mul32x32_64(modm_m[6], q3[1]) + mul32x32_64(modm_m[7], q3[0]);
  108. r2[7] = (bignum256modm_element_t)(c & 0x3fffffff); c >>= 30;
  109. c += mul32x32_64(modm_m[0], q3[8]) + mul32x32_64(modm_m[1], q3[7]) + mul32x32_64(modm_m[2], q3[6]) + mul32x32_64(modm_m[3], q3[5]) + mul32x32_64(modm_m[4], q3[4]) + mul32x32_64(modm_m[5], q3[3]) + mul32x32_64(modm_m[6], q3[2]) + mul32x32_64(modm_m[7], q3[1]) + mul32x32_64(modm_m[8], q3[0]);
  110. r2[8] = (bignum256modm_element_t)(c & 0xffffff);
  111. /* r = r1 - r2
  112. if (r < 0) r += (1 << 264) */
  113. pb = 0;
  114. pb += r2[0]; b = lt_modm(r1[0], pb); r[0] = (r1[0] - pb + (b << 30)); pb = b;
  115. pb += r2[1]; b = lt_modm(r1[1], pb); r[1] = (r1[1] - pb + (b << 30)); pb = b;
  116. pb += r2[2]; b = lt_modm(r1[2], pb); r[2] = (r1[2] - pb + (b << 30)); pb = b;
  117. pb += r2[3]; b = lt_modm(r1[3], pb); r[3] = (r1[3] - pb + (b << 30)); pb = b;
  118. pb += r2[4]; b = lt_modm(r1[4], pb); r[4] = (r1[4] - pb + (b << 30)); pb = b;
  119. pb += r2[5]; b = lt_modm(r1[5], pb); r[5] = (r1[5] - pb + (b << 30)); pb = b;
  120. pb += r2[6]; b = lt_modm(r1[6], pb); r[6] = (r1[6] - pb + (b << 30)); pb = b;
  121. pb += r2[7]; b = lt_modm(r1[7], pb); r[7] = (r1[7] - pb + (b << 30)); pb = b;
  122. pb += r2[8]; b = lt_modm(r1[8], pb); r[8] = (r1[8] - pb + (b << 24));
  123. reduce256_modm(r);
  124. reduce256_modm(r);
  125. }
  126. /* addition modulo m */
  127. static void
  128. add256_modm(bignum256modm r, const bignum256modm x, const bignum256modm y) {
  129. bignum256modm_element_t c;
  130. c = x[0] + y[0]; r[0] = c & 0x3fffffff; c >>= 30;
  131. c += x[1] + y[1]; r[1] = c & 0x3fffffff; c >>= 30;
  132. c += x[2] + y[2]; r[2] = c & 0x3fffffff; c >>= 30;
  133. c += x[3] + y[3]; r[3] = c & 0x3fffffff; c >>= 30;
  134. c += x[4] + y[4]; r[4] = c & 0x3fffffff; c >>= 30;
  135. c += x[5] + y[5]; r[5] = c & 0x3fffffff; c >>= 30;
  136. c += x[6] + y[6]; r[6] = c & 0x3fffffff; c >>= 30;
  137. c += x[7] + y[7]; r[7] = c & 0x3fffffff; c >>= 30;
  138. c += x[8] + y[8]; r[8] = c;
  139. reduce256_modm(r);
  140. }
  141. /* multiplication modulo m */
  142. static void
  143. mul256_modm(bignum256modm r, const bignum256modm x, const bignum256modm y) {
  144. bignum256modm r1, q1;
  145. uint64_t c;
  146. bignum256modm_element_t f;
  147. /* r1 = (x mod 256^(32+1)) = x mod (2^8)(31+1) = x & ((1 << 264) - 1)
  148. q1 = x >> 248 = 264 bits = 9 30 bit elements */
  149. c = mul32x32_64(x[0], y[0]);
  150. f = (bignum256modm_element_t)c; r1[0] = (f & 0x3fffffff); c >>= 30;
  151. c += mul32x32_64(x[0], y[1]) + mul32x32_64(x[1], y[0]);
  152. f = (bignum256modm_element_t)c; r1[1] = (f & 0x3fffffff); c >>= 30;
  153. c += mul32x32_64(x[0], y[2]) + mul32x32_64(x[1], y[1]) + mul32x32_64(x[2], y[0]);
  154. f = (bignum256modm_element_t)c; r1[2] = (f & 0x3fffffff); c >>= 30;
  155. c += mul32x32_64(x[0], y[3]) + mul32x32_64(x[1], y[2]) + mul32x32_64(x[2], y[1]) + mul32x32_64(x[3], y[0]);
  156. f = (bignum256modm_element_t)c; r1[3] = (f & 0x3fffffff); c >>= 30;
  157. c += mul32x32_64(x[0], y[4]) + mul32x32_64(x[1], y[3]) + mul32x32_64(x[2], y[2]) + mul32x32_64(x[3], y[1]) + mul32x32_64(x[4], y[0]);
  158. f = (bignum256modm_element_t)c; r1[4] = (f & 0x3fffffff); c >>= 30;
  159. c += mul32x32_64(x[0], y[5]) + mul32x32_64(x[1], y[4]) + mul32x32_64(x[2], y[3]) + mul32x32_64(x[3], y[2]) + mul32x32_64(x[4], y[1]) + mul32x32_64(x[5], y[0]);
  160. f = (bignum256modm_element_t)c; r1[5] = (f & 0x3fffffff); c >>= 30;
  161. c += mul32x32_64(x[0], y[6]) + mul32x32_64(x[1], y[5]) + mul32x32_64(x[2], y[4]) + mul32x32_64(x[3], y[3]) + mul32x32_64(x[4], y[2]) + mul32x32_64(x[5], y[1]) + mul32x32_64(x[6], y[0]);
  162. f = (bignum256modm_element_t)c; r1[6] = (f & 0x3fffffff); c >>= 30;
  163. c += mul32x32_64(x[0], y[7]) + mul32x32_64(x[1], y[6]) + mul32x32_64(x[2], y[5]) + mul32x32_64(x[3], y[4]) + mul32x32_64(x[4], y[3]) + mul32x32_64(x[5], y[2]) + mul32x32_64(x[6], y[1]) + mul32x32_64(x[7], y[0]);
  164. f = (bignum256modm_element_t)c; r1[7] = (f & 0x3fffffff); c >>= 30;
  165. c += mul32x32_64(x[0], y[8]) + mul32x32_64(x[1], y[7]) + mul32x32_64(x[2], y[6]) + mul32x32_64(x[3], y[5]) + mul32x32_64(x[4], y[4]) + mul32x32_64(x[5], y[3]) + mul32x32_64(x[6], y[2]) + mul32x32_64(x[7], y[1]) + mul32x32_64(x[8], y[0]);
  166. f = (bignum256modm_element_t)c; r1[8] = (f & 0x00ffffff); q1[0] = (f >> 8) & 0x3fffff; c >>= 30;
  167. c += mul32x32_64(x[1], y[8]) + mul32x32_64(x[2], y[7]) + mul32x32_64(x[3], y[6]) + mul32x32_64(x[4], y[5]) + mul32x32_64(x[5], y[4]) + mul32x32_64(x[6], y[3]) + mul32x32_64(x[7], y[2]) + mul32x32_64(x[8], y[1]);
  168. f = (bignum256modm_element_t)c; q1[0] = (q1[0] | (f << 22)) & 0x3fffffff; q1[1] = (f >> 8) & 0x3fffff; c >>= 30;
  169. c += mul32x32_64(x[2], y[8]) + mul32x32_64(x[3], y[7]) + mul32x32_64(x[4], y[6]) + mul32x32_64(x[5], y[5]) + mul32x32_64(x[6], y[4]) + mul32x32_64(x[7], y[3]) + mul32x32_64(x[8], y[2]);
  170. f = (bignum256modm_element_t)c; q1[1] = (q1[1] | (f << 22)) & 0x3fffffff; q1[2] = (f >> 8) & 0x3fffff; c >>= 30;
  171. c += mul32x32_64(x[3], y[8]) + mul32x32_64(x[4], y[7]) + mul32x32_64(x[5], y[6]) + mul32x32_64(x[6], y[5]) + mul32x32_64(x[7], y[4]) + mul32x32_64(x[8], y[3]);
  172. f = (bignum256modm_element_t)c; q1[2] = (q1[2] | (f << 22)) & 0x3fffffff; q1[3] = (f >> 8) & 0x3fffff; c >>= 30;
  173. c += mul32x32_64(x[4], y[8]) + mul32x32_64(x[5], y[7]) + mul32x32_64(x[6], y[6]) + mul32x32_64(x[7], y[5]) + mul32x32_64(x[8], y[4]);
  174. f = (bignum256modm_element_t)c; q1[3] = (q1[3] | (f << 22)) & 0x3fffffff; q1[4] = (f >> 8) & 0x3fffff; c >>= 30;
  175. c += mul32x32_64(x[5], y[8]) + mul32x32_64(x[6], y[7]) + mul32x32_64(x[7], y[6]) + mul32x32_64(x[8], y[5]);
  176. f = (bignum256modm_element_t)c; q1[4] = (q1[4] | (f << 22)) & 0x3fffffff; q1[5] = (f >> 8) & 0x3fffff; c >>= 30;
  177. c += mul32x32_64(x[6], y[8]) + mul32x32_64(x[7], y[7]) + mul32x32_64(x[8], y[6]);
  178. f = (bignum256modm_element_t)c; q1[5] = (q1[5] | (f << 22)) & 0x3fffffff; q1[6] = (f >> 8) & 0x3fffff; c >>= 30;
  179. c += mul32x32_64(x[7], y[8]) + mul32x32_64(x[8], y[7]);
  180. f = (bignum256modm_element_t)c; q1[6] = (q1[6] | (f << 22)) & 0x3fffffff; q1[7] = (f >> 8) & 0x3fffff; c >>= 30;
  181. c += mul32x32_64(x[8], y[8]);
  182. f = (bignum256modm_element_t)c; q1[7] = (q1[7] | (f << 22)) & 0x3fffffff; q1[8] = (f >> 8) & 0x3fffff;
  183. barrett_reduce256_modm(r, q1, r1);
  184. }
  185. static void
  186. expand256_modm(bignum256modm out, const unsigned char *in, size_t len) {
  187. unsigned char work[64] = {0};
  188. bignum256modm_element_t x[16];
  189. bignum256modm q1;
  190. memcpy(work, in, len);
  191. x[0] = U8TO32_LE(work + 0);
  192. x[1] = U8TO32_LE(work + 4);
  193. x[2] = U8TO32_LE(work + 8);
  194. x[3] = U8TO32_LE(work + 12);
  195. x[4] = U8TO32_LE(work + 16);
  196. x[5] = U8TO32_LE(work + 20);
  197. x[6] = U8TO32_LE(work + 24);
  198. x[7] = U8TO32_LE(work + 28);
  199. x[8] = U8TO32_LE(work + 32);
  200. x[9] = U8TO32_LE(work + 36);
  201. x[10] = U8TO32_LE(work + 40);
  202. x[11] = U8TO32_LE(work + 44);
  203. x[12] = U8TO32_LE(work + 48);
  204. x[13] = U8TO32_LE(work + 52);
  205. x[14] = U8TO32_LE(work + 56);
  206. x[15] = U8TO32_LE(work + 60);
  207. /* r1 = (x mod 256^(32+1)) = x mod (2^8)(31+1) = x & ((1 << 264) - 1) */
  208. out[0] = ( x[0]) & 0x3fffffff;
  209. out[1] = ((x[ 0] >> 30) | (x[ 1] << 2)) & 0x3fffffff;
  210. out[2] = ((x[ 1] >> 28) | (x[ 2] << 4)) & 0x3fffffff;
  211. out[3] = ((x[ 2] >> 26) | (x[ 3] << 6)) & 0x3fffffff;
  212. out[4] = ((x[ 3] >> 24) | (x[ 4] << 8)) & 0x3fffffff;
  213. out[5] = ((x[ 4] >> 22) | (x[ 5] << 10)) & 0x3fffffff;
  214. out[6] = ((x[ 5] >> 20) | (x[ 6] << 12)) & 0x3fffffff;
  215. out[7] = ((x[ 6] >> 18) | (x[ 7] << 14)) & 0x3fffffff;
  216. out[8] = ((x[ 7] >> 16) | (x[ 8] << 16)) & 0x00ffffff;
  217. /* 8*31 = 248 bits, no need to reduce */
  218. if (len < 32)
  219. return;
  220. /* q1 = x >> 248 = 264 bits = 9 30 bit elements */
  221. q1[0] = ((x[ 7] >> 24) | (x[ 8] << 8)) & 0x3fffffff;
  222. q1[1] = ((x[ 8] >> 22) | (x[ 9] << 10)) & 0x3fffffff;
  223. q1[2] = ((x[ 9] >> 20) | (x[10] << 12)) & 0x3fffffff;
  224. q1[3] = ((x[10] >> 18) | (x[11] << 14)) & 0x3fffffff;
  225. q1[4] = ((x[11] >> 16) | (x[12] << 16)) & 0x3fffffff;
  226. q1[5] = ((x[12] >> 14) | (x[13] << 18)) & 0x3fffffff;
  227. q1[6] = ((x[13] >> 12) | (x[14] << 20)) & 0x3fffffff;
  228. q1[7] = ((x[14] >> 10) | (x[15] << 22)) & 0x3fffffff;
  229. q1[8] = ((x[15] >> 8) );
  230. barrett_reduce256_modm(out, q1, out);
  231. }
  232. static void
  233. expand_raw256_modm(bignum256modm out, const unsigned char in[32]) {
  234. bignum256modm_element_t x[8];
  235. x[0] = U8TO32_LE(in + 0);
  236. x[1] = U8TO32_LE(in + 4);
  237. x[2] = U8TO32_LE(in + 8);
  238. x[3] = U8TO32_LE(in + 12);
  239. x[4] = U8TO32_LE(in + 16);
  240. x[5] = U8TO32_LE(in + 20);
  241. x[6] = U8TO32_LE(in + 24);
  242. x[7] = U8TO32_LE(in + 28);
  243. out[0] = ( x[0]) & 0x3fffffff;
  244. out[1] = ((x[ 0] >> 30) | (x[ 1] << 2)) & 0x3fffffff;
  245. out[2] = ((x[ 1] >> 28) | (x[ 2] << 4)) & 0x3fffffff;
  246. out[3] = ((x[ 2] >> 26) | (x[ 3] << 6)) & 0x3fffffff;
  247. out[4] = ((x[ 3] >> 24) | (x[ 4] << 8)) & 0x3fffffff;
  248. out[5] = ((x[ 4] >> 22) | (x[ 5] << 10)) & 0x3fffffff;
  249. out[6] = ((x[ 5] >> 20) | (x[ 6] << 12)) & 0x3fffffff;
  250. out[7] = ((x[ 6] >> 18) | (x[ 7] << 14)) & 0x3fffffff;
  251. out[8] = ((x[ 7] >> 16) ) & 0x0000ffff;
  252. }
  253. static void
  254. contract256_modm(unsigned char out[32], const bignum256modm in) {
  255. U32TO8_LE(out + 0, (in[0] ) | (in[1] << 30));
  256. U32TO8_LE(out + 4, (in[1] >> 2) | (in[2] << 28));
  257. U32TO8_LE(out + 8, (in[2] >> 4) | (in[3] << 26));
  258. U32TO8_LE(out + 12, (in[3] >> 6) | (in[4] << 24));
  259. U32TO8_LE(out + 16, (in[4] >> 8) | (in[5] << 22));
  260. U32TO8_LE(out + 20, (in[5] >> 10) | (in[6] << 20));
  261. U32TO8_LE(out + 24, (in[6] >> 12) | (in[7] << 18));
  262. U32TO8_LE(out + 28, (in[7] >> 14) | (in[8] << 16));
  263. }
  264. static void
  265. contract256_window4_modm(signed char r[64], const bignum256modm in) {
  266. char carry;
  267. signed char *quads = r;
  268. bignum256modm_element_t i, j, v;
  269. for (i = 0; i < 8; i += 2) {
  270. v = in[i];
  271. for (j = 0; j < 7; j++) {
  272. *quads++ = (v & 15);
  273. v >>= 4;
  274. }
  275. v |= (in[i+1] << 2);
  276. for (j = 0; j < 8; j++) {
  277. *quads++ = (v & 15);
  278. v >>= 4;
  279. }
  280. }
  281. v = in[8];
  282. *quads++ = (v & 15); v >>= 4;
  283. *quads++ = (v & 15); v >>= 4;
  284. *quads++ = (v & 15); v >>= 4;
  285. *quads++ = (v & 15); v >>= 4;
  286. /* making it signed */
  287. carry = 0;
  288. for(i = 0; i < 63; i++) {
  289. r[i] += carry;
  290. r[i+1] += (r[i] >> 4);
  291. r[i] &= 15;
  292. carry = (r[i] >> 3);
  293. r[i] -= (carry << 4);
  294. }
  295. r[63] += carry;
  296. }
  297. static void
  298. contract256_slidingwindow_modm(signed char r[256], const bignum256modm s, int windowsize) {
  299. int i,j,k,b;
  300. int m = (1 << (windowsize - 1)) - 1, soplen = 256;
  301. signed char *bits = r;
  302. bignum256modm_element_t v;
  303. /* first put the binary expansion into r */
  304. for (i = 0; i < 8; i++) {
  305. v = s[i];
  306. for (j = 0; j < 30; j++, v >>= 1)
  307. *bits++ = (v & 1);
  308. }
  309. v = s[8];
  310. for (j = 0; j < 16; j++, v >>= 1)
  311. *bits++ = (v & 1);
  312. /* Making it sliding window */
  313. for (j = 0; j < soplen; j++) {
  314. if (!r[j])
  315. continue;
  316. for (b = 1; (b < (soplen - j)) && (b <= 6); b++) {
  317. if ((r[j] + (r[j + b] << b)) <= m) {
  318. r[j] += r[j + b] << b;
  319. r[j + b] = 0;
  320. } else if ((r[j] - (r[j + b] << b)) >= -m) {
  321. r[j] -= r[j + b] << b;
  322. for (k = j + b; k < soplen; k++) {
  323. if (!r[k]) {
  324. r[k] = 1;
  325. break;
  326. }
  327. r[k] = 0;
  328. }
  329. } else if (r[j + b]) {
  330. break;
  331. }
  332. }
  333. }
  334. }
  335. /*
  336. helpers for batch verifcation, are allowed to be vartime
  337. */
  338. /* out = a - b, a must be larger than b */
  339. static void
  340. sub256_modm_batch(bignum256modm out, const bignum256modm a, const bignum256modm b, size_t limbsize) {
  341. size_t i = 0;
  342. bignum256modm_element_t carry = 0;
  343. switch (limbsize) {
  344. case 8: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 31); out[i] &= 0x3fffffff; i++;
  345. case 7: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 31); out[i] &= 0x3fffffff; i++;
  346. case 6: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 31); out[i] &= 0x3fffffff; i++;
  347. case 5: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 31); out[i] &= 0x3fffffff; i++;
  348. case 4: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 31); out[i] &= 0x3fffffff; i++;
  349. case 3: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 31); out[i] &= 0x3fffffff; i++;
  350. case 2: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 31); out[i] &= 0x3fffffff; i++;
  351. case 1: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 31); out[i] &= 0x3fffffff; i++;
  352. case 0:
  353. default: out[i] = (a[i] - b[i]) - carry;
  354. }
  355. }
  356. /* is a < b */
  357. static int
  358. lt256_modm_batch(const bignum256modm a, const bignum256modm b, size_t limbsize) {
  359. switch (limbsize) {
  360. case 8: if (a[8] > b[8]) return 0; if (a[8] < b[8]) return 1;
  361. case 7: if (a[7] > b[7]) return 0; if (a[7] < b[7]) return 1;
  362. case 6: if (a[6] > b[6]) return 0; if (a[6] < b[6]) return 1;
  363. case 5: if (a[5] > b[5]) return 0; if (a[5] < b[5]) return 1;
  364. case 4: if (a[4] > b[4]) return 0; if (a[4] < b[4]) return 1;
  365. case 3: if (a[3] > b[3]) return 0; if (a[3] < b[3]) return 1;
  366. case 2: if (a[2] > b[2]) return 0; if (a[2] < b[2]) return 1;
  367. case 1: if (a[1] > b[1]) return 0; if (a[1] < b[1]) return 1;
  368. case 0: if (a[0] > b[0]) return 0; if (a[0] < b[0]) return 1;
  369. }
  370. return 0;
  371. }
  372. /* is a <= b */
  373. static int
  374. lte256_modm_batch(const bignum256modm a, const bignum256modm b, size_t limbsize) {
  375. switch (limbsize) {
  376. case 8: if (a[8] > b[8]) return 0; if (a[8] < b[8]) return 1;
  377. case 7: if (a[7] > b[7]) return 0; if (a[7] < b[7]) return 1;
  378. case 6: if (a[6] > b[6]) return 0; if (a[6] < b[6]) return 1;
  379. case 5: if (a[5] > b[5]) return 0; if (a[5] < b[5]) return 1;
  380. case 4: if (a[4] > b[4]) return 0; if (a[4] < b[4]) return 1;
  381. case 3: if (a[3] > b[3]) return 0; if (a[3] < b[3]) return 1;
  382. case 2: if (a[2] > b[2]) return 0; if (a[2] < b[2]) return 1;
  383. case 1: if (a[1] > b[1]) return 0; if (a[1] < b[1]) return 1;
  384. case 0: if (a[0] > b[0]) return 0; if (a[0] < b[0]) return 1;
  385. }
  386. return 1;
  387. }
  388. /* is a == 0 */
  389. static int
  390. iszero256_modm_batch(const bignum256modm a) {
  391. size_t i;
  392. for (i = 0; i < 9; i++)
  393. if (a[i])
  394. return 0;
  395. return 1;
  396. }
  397. /* is a == 1 */
  398. static int
  399. isone256_modm_batch(const bignum256modm a) {
  400. size_t i;
  401. if (a[0] != 1)
  402. return 0;
  403. for (i = 1; i < 9; i++)
  404. if (a[i])
  405. return 0;
  406. return 1;
  407. }
  408. /* can a fit in to (at most) 128 bits */
  409. static int
  410. isatmost128bits256_modm_batch(const bignum256modm a) {
  411. uint32_t mask =
  412. ((a[8] ) | /* 16 */
  413. (a[7] ) | /* 46 */
  414. (a[6] ) | /* 76 */
  415. (a[5] ) | /* 106 */
  416. (a[4] & 0x3fffff00)); /* 128 */
  417. return (mask == 0);
  418. }
  419. #endif /* !defined(HAVE_UINT128) || defined(ED25519_FORCE_32BIT) */