curve-specific.inc 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249
  1. /* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */
  2. #ifndef _UECC_CURVE_SPECIFIC_H_
  3. #define _UECC_CURVE_SPECIFIC_H_
  4. #define num_bytes_secp160r1 20
  5. #define num_bytes_secp192r1 24
  6. #define num_bytes_secp224r1 28
  7. #define num_bytes_secp256r1 32
  8. #define num_bytes_secp256k1 32
  9. #if (uECC_WORD_SIZE == 1)
  10. #define num_words_secp160r1 20
  11. #define num_words_secp192r1 24
  12. #define num_words_secp224r1 28
  13. #define num_words_secp256r1 32
  14. #define num_words_secp256k1 32
  15. #define BYTES_TO_WORDS_8(a, b, c, d, e, f, g, h) \
  16. 0x##a, 0x##b, 0x##c, 0x##d, 0x##e, 0x##f, 0x##g, 0x##h
  17. #define BYTES_TO_WORDS_4(a, b, c, d) 0x##a, 0x##b, 0x##c, 0x##d
  18. #elif (uECC_WORD_SIZE == 4)
  19. #define num_words_secp160r1 5
  20. #define num_words_secp192r1 6
  21. #define num_words_secp224r1 7
  22. #define num_words_secp256r1 8
  23. #define num_words_secp256k1 8
  24. #define BYTES_TO_WORDS_8(a, b, c, d, e, f, g, h) 0x##d##c##b##a, 0x##h##g##f##e
  25. #define BYTES_TO_WORDS_4(a, b, c, d) 0x##d##c##b##a
  26. #elif (uECC_WORD_SIZE == 8)
  27. #define num_words_secp160r1 3
  28. #define num_words_secp192r1 3
  29. #define num_words_secp224r1 4
  30. #define num_words_secp256r1 4
  31. #define num_words_secp256k1 4
  32. #define BYTES_TO_WORDS_8(a, b, c, d, e, f, g, h) 0x##h##g##f##e##d##c##b##a##ull
  33. #define BYTES_TO_WORDS_4(a, b, c, d) 0x##d##c##b##a##ull
  34. #endif /* uECC_WORD_SIZE */
  35. #if uECC_SUPPORTS_secp160r1 || uECC_SUPPORTS_secp192r1 || \
  36. uECC_SUPPORTS_secp224r1 || uECC_SUPPORTS_secp256r1
  37. static void double_jacobian_default(uECC_word_t * X1,
  38. uECC_word_t * Y1,
  39. uECC_word_t * Z1,
  40. uECC_Curve curve) {
  41. /* t1 = X, t2 = Y, t3 = Z */
  42. uECC_word_t t4[uECC_MAX_WORDS];
  43. uECC_word_t t5[uECC_MAX_WORDS];
  44. wordcount_t num_words = curve->num_words;
  45. if (uECC_vli_isZero(Z1, num_words)) {
  46. return;
  47. }
  48. uECC_vli_modSquare_fast(t4, Y1, curve); /* t4 = y1^2 */
  49. uECC_vli_modMult_fast(t5, X1, t4, curve); /* t5 = x1*y1^2 = A */
  50. uECC_vli_modSquare_fast(t4, t4, curve); /* t4 = y1^4 */
  51. uECC_vli_modMult_fast(Y1, Y1, Z1, curve); /* t2 = y1*z1 = z3 */
  52. uECC_vli_modSquare_fast(Z1, Z1, curve); /* t3 = z1^2 */
  53. uECC_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = x1 + z1^2 */
  54. uECC_vli_modAdd(Z1, Z1, Z1, curve->p, num_words); /* t3 = 2*z1^2 */
  55. uECC_vli_modSub(Z1, X1, Z1, curve->p, num_words); /* t3 = x1 - z1^2 */
  56. uECC_vli_modMult_fast(X1, X1, Z1, curve); /* t1 = x1^2 - z1^4 */
  57. uECC_vli_modAdd(Z1, X1, X1, curve->p, num_words); /* t3 = 2*(x1^2 - z1^4) */
  58. uECC_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = 3*(x1^2 - z1^4) */
  59. if (uECC_vli_testBit(X1, 0)) {
  60. uECC_word_t l_carry = uECC_vli_add(X1, X1, curve->p, num_words);
  61. uECC_vli_rshift1(X1, num_words);
  62. X1[num_words - 1] |= l_carry << (uECC_WORD_BITS - 1);
  63. } else {
  64. uECC_vli_rshift1(X1, num_words);
  65. }
  66. /* t1 = 3/2*(x1^2 - z1^4) = B */
  67. uECC_vli_modSquare_fast(Z1, X1, curve); /* t3 = B^2 */
  68. uECC_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - A */
  69. uECC_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - 2A = x3 */
  70. uECC_vli_modSub(t5, t5, Z1, curve->p, num_words); /* t5 = A - x3 */
  71. uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = B * (A - x3) */
  72. uECC_vli_modSub(t4, X1, t4, curve->p, num_words); /* t4 = B * (A - x3) - y1^4 = y3 */
  73. uECC_vli_set(X1, Z1, num_words);
  74. uECC_vli_set(Z1, Y1, num_words);
  75. uECC_vli_set(Y1, t4, num_words);
  76. }
  77. /* Computes result = x^3 + ax + b. result must not overlap x. */
  78. static void x_side_default(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve) {
  79. uECC_word_t _3[uECC_MAX_WORDS] = {3}; /* -a = 3 */
  80. wordcount_t num_words = curve->num_words;
  81. uECC_vli_modSquare_fast(result, x, curve); /* r = x^2 */
  82. uECC_vli_modSub(result, result, _3, curve->p, num_words); /* r = x^2 - 3 */
  83. uECC_vli_modMult_fast(result, result, x, curve); /* r = x^3 - 3x */
  84. uECC_vli_modAdd(result, result, curve->b, curve->p, num_words); /* r = x^3 - 3x + b */
  85. }
  86. #endif /* uECC_SUPPORTS_secp... */
  87. #if uECC_SUPPORT_COMPRESSED_POINT
  88. #if uECC_SUPPORTS_secp160r1 || uECC_SUPPORTS_secp192r1 || \
  89. uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1
  90. /* Compute a = sqrt(a) (mod curve_p). */
  91. static void mod_sqrt_default(uECC_word_t *a, uECC_Curve curve) {
  92. bitcount_t i;
  93. uECC_word_t p1[uECC_MAX_WORDS] = {1};
  94. uECC_word_t l_result[uECC_MAX_WORDS] = {1};
  95. wordcount_t num_words = curve->num_words;
  96. /* When curve->p == 3 (mod 4), we can compute
  97. sqrt(a) = a^((curve->p + 1) / 4) (mod curve->p). */
  98. uECC_vli_add(p1, curve->p, p1, num_words); /* p1 = curve_p + 1 */
  99. for (i = uECC_vli_numBits(p1, num_words) - 1; i > 1; --i) {
  100. uECC_vli_modSquare_fast(l_result, l_result, curve);
  101. if (uECC_vli_testBit(p1, i)) {
  102. uECC_vli_modMult_fast(l_result, l_result, a, curve);
  103. }
  104. }
  105. uECC_vli_set(a, l_result, num_words);
  106. }
  107. #endif /* uECC_SUPPORTS_secp... */
  108. #endif /* uECC_SUPPORT_COMPRESSED_POINT */
  109. #if uECC_SUPPORTS_secp160r1
  110. #if (uECC_OPTIMIZATION_LEVEL > 0)
  111. static void vli_mmod_fast_secp160r1(uECC_word_t *result, uECC_word_t *product);
  112. #endif
  113. static const struct uECC_Curve_t curve_secp160r1 = {
  114. num_words_secp160r1,
  115. num_bytes_secp160r1,
  116. 161, /* num_n_bits */
  117. { BYTES_TO_WORDS_8(FF, FF, FF, 7F, FF, FF, FF, FF),
  118. BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
  119. BYTES_TO_WORDS_4(FF, FF, FF, FF) },
  120. { BYTES_TO_WORDS_8(57, 22, 75, CA, D3, AE, 27, F9),
  121. BYTES_TO_WORDS_8(C8, F4, 01, 00, 00, 00, 00, 00),
  122. BYTES_TO_WORDS_8(00, 00, 00, 00, 01, 00, 00, 00) },
  123. { BYTES_TO_WORDS_8(82, FC, CB, 13, B9, 8B, C3, 68),
  124. BYTES_TO_WORDS_8(89, 69, 64, 46, 28, 73, F5, 8E),
  125. BYTES_TO_WORDS_4(68, B5, 96, 4A),
  126. BYTES_TO_WORDS_8(32, FB, C5, 7A, 37, 51, 23, 04),
  127. BYTES_TO_WORDS_8(12, C9, DC, 59, 7D, 94, 68, 31),
  128. BYTES_TO_WORDS_4(55, 28, A6, 23) },
  129. { BYTES_TO_WORDS_8(45, FA, 65, C5, AD, D4, D4, 81),
  130. BYTES_TO_WORDS_8(9F, F8, AC, 65, 8B, 7A, BD, 54),
  131. BYTES_TO_WORDS_4(FC, BE, 97, 1C) },
  132. &double_jacobian_default,
  133. #if uECC_SUPPORT_COMPRESSED_POINT
  134. &mod_sqrt_default,
  135. #endif
  136. &x_side_default,
  137. #if (uECC_OPTIMIZATION_LEVEL > 0)
  138. &vli_mmod_fast_secp160r1
  139. #endif
  140. };
  141. uECC_Curve uECC_secp160r1(void) { return &curve_secp160r1; }
  142. #if (uECC_OPTIMIZATION_LEVEL > 0 && !asm_mmod_fast_secp160r1)
  143. /* Computes result = product % curve_p
  144. see http://www.isys.uni-klu.ac.at/PDF/2001-0126-MT.pdf page 354
  145. Note that this only works if log2(omega) < log2(p) / 2 */
  146. static void omega_mult_secp160r1(uECC_word_t *result, const uECC_word_t *right);
  147. #if uECC_WORD_SIZE == 8
  148. static void vli_mmod_fast_secp160r1(uECC_word_t *result, uECC_word_t *product) {
  149. uECC_word_t tmp[2 * num_words_secp160r1];
  150. uECC_word_t copy;
  151. uECC_vli_clear(tmp, num_words_secp160r1);
  152. uECC_vli_clear(tmp + num_words_secp160r1, num_words_secp160r1);
  153. omega_mult_secp160r1(tmp, product + num_words_secp160r1 - 1); /* (Rq, q) = q * c */
  154. product[num_words_secp160r1 - 1] &= 0xffffffff;
  155. copy = tmp[num_words_secp160r1 - 1];
  156. tmp[num_words_secp160r1 - 1] &= 0xffffffff;
  157. uECC_vli_add(result, product, tmp, num_words_secp160r1); /* (C, r) = r + q */
  158. uECC_vli_clear(product, num_words_secp160r1);
  159. tmp[num_words_secp160r1 - 1] = copy;
  160. omega_mult_secp160r1(product, tmp + num_words_secp160r1 - 1); /* Rq*c */
  161. uECC_vli_add(result, result, product, num_words_secp160r1); /* (C1, r) = r + Rq*c */
  162. while (uECC_vli_cmp_unsafe(result, curve_secp160r1.p, num_words_secp160r1) > 0) {
  163. uECC_vli_sub(result, result, curve_secp160r1.p, num_words_secp160r1);
  164. }
  165. }
  166. static void omega_mult_secp160r1(uint64_t *result, const uint64_t *right) {
  167. uint32_t carry;
  168. unsigned i;
  169. /* Multiply by (2^31 + 1). */
  170. carry = 0;
  171. for (i = 0; i < num_words_secp160r1; ++i) {
  172. uint64_t tmp = (right[i] >> 32) | (right[i + 1] << 32);
  173. result[i] = (tmp << 31) + tmp + carry;
  174. carry = (tmp >> 33) + (result[i] < tmp || (carry && result[i] == tmp));
  175. }
  176. result[i] = carry;
  177. }
  178. #else
  179. static void vli_mmod_fast_secp160r1(uECC_word_t *result, uECC_word_t *product) {
  180. uECC_word_t tmp[2 * num_words_secp160r1];
  181. uECC_word_t carry;
  182. uECC_vli_clear(tmp, num_words_secp160r1);
  183. uECC_vli_clear(tmp + num_words_secp160r1, num_words_secp160r1);
  184. omega_mult_secp160r1(tmp, product + num_words_secp160r1); /* (Rq, q) = q * c */
  185. carry = uECC_vli_add(result, product, tmp, num_words_secp160r1); /* (C, r) = r + q */
  186. uECC_vli_clear(product, num_words_secp160r1);
  187. omega_mult_secp160r1(product, tmp + num_words_secp160r1); /* Rq*c */
  188. carry += uECC_vli_add(result, result, product, num_words_secp160r1); /* (C1, r) = r + Rq*c */
  189. while (carry > 0) {
  190. --carry;
  191. uECC_vli_sub(result, result, curve_secp160r1.p, num_words_secp160r1);
  192. }
  193. if (uECC_vli_cmp_unsafe(result, curve_secp160r1.p, num_words_secp160r1) > 0) {
  194. uECC_vli_sub(result, result, curve_secp160r1.p, num_words_secp160r1);
  195. }
  196. }
  197. #endif
  198. #if uECC_WORD_SIZE == 1
  199. static void omega_mult_secp160r1(uint8_t *result, const uint8_t *right) {
  200. uint8_t carry;
  201. uint8_t i;
  202. /* Multiply by (2^31 + 1). */
  203. uECC_vli_set(result + 4, right, num_words_secp160r1); /* 2^32 */
  204. uECC_vli_rshift1(result + 4, num_words_secp160r1); /* 2^31 */
  205. result[3] = right[0] << 7; /* get last bit from shift */
  206. carry = uECC_vli_add(result, result, right, num_words_secp160r1); /* 2^31 + 1 */
  207. for (i = num_words_secp160r1; carry; ++i) {
  208. uint16_t sum = (uint16_t)result[i] + carry;
  209. result[i] = (uint8_t)sum;
  210. carry = sum >> 8;
  211. }
  212. }
  213. #elif uECC_WORD_SIZE == 4
  214. static void omega_mult_secp160r1(uint32_t *result, const uint32_t *right) {
  215. uint32_t carry;
  216. unsigned i;
  217. /* Multiply by (2^31 + 1). */
  218. uECC_vli_set(result + 1, right, num_words_secp160r1); /* 2^32 */
  219. uECC_vli_rshift1(result + 1, num_words_secp160r1); /* 2^31 */
  220. result[0] = right[0] << 31; /* get last bit from shift */
  221. carry = uECC_vli_add(result, result, right, num_words_secp160r1); /* 2^31 + 1 */
  222. for (i = num_words_secp160r1; carry; ++i) {
  223. uint64_t sum = (uint64_t)result[i] + carry;
  224. result[i] = (uint32_t)sum;
  225. carry = sum >> 32;
  226. }
  227. }
  228. #endif /* uECC_WORD_SIZE */
  229. #endif /* (uECC_OPTIMIZATION_LEVEL > 0 && !asm_mmod_fast_secp160r1) */
  230. #endif /* uECC_SUPPORTS_secp160r1 */
  231. #if uECC_SUPPORTS_secp192r1
  232. #if (uECC_OPTIMIZATION_LEVEL > 0)
  233. static void vli_mmod_fast_secp192r1(uECC_word_t *result, uECC_word_t *product);
  234. #endif
  235. static const struct uECC_Curve_t curve_secp192r1 = {
  236. num_words_secp192r1,
  237. num_bytes_secp192r1,
  238. 192, /* num_n_bits */
  239. { BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
  240. BYTES_TO_WORDS_8(FE, FF, FF, FF, FF, FF, FF, FF),
  241. BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF) },
  242. { BYTES_TO_WORDS_8(31, 28, D2, B4, B1, C9, 6B, 14),
  243. BYTES_TO_WORDS_8(36, F8, DE, 99, FF, FF, FF, FF),
  244. BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF) },
  245. { BYTES_TO_WORDS_8(12, 10, FF, 82, FD, 0A, FF, F4),
  246. BYTES_TO_WORDS_8(00, 88, A1, 43, EB, 20, BF, 7C),
  247. BYTES_TO_WORDS_8(F6, 90, 30, B0, 0E, A8, 8D, 18),
  248. BYTES_TO_WORDS_8(11, 48, 79, 1E, A1, 77, F9, 73),
  249. BYTES_TO_WORDS_8(D5, CD, 24, 6B, ED, 11, 10, 63),
  250. BYTES_TO_WORDS_8(78, DA, C8, FF, 95, 2B, 19, 07) },
  251. { BYTES_TO_WORDS_8(B1, B9, 46, C1, EC, DE, B8, FE),
  252. BYTES_TO_WORDS_8(49, 30, 24, 72, AB, E9, A7, 0F),
  253. BYTES_TO_WORDS_8(E7, 80, 9C, E5, 19, 05, 21, 64) },
  254. &double_jacobian_default,
  255. #if uECC_SUPPORT_COMPRESSED_POINT
  256. &mod_sqrt_default,
  257. #endif
  258. &x_side_default,
  259. #if (uECC_OPTIMIZATION_LEVEL > 0)
  260. &vli_mmod_fast_secp192r1
  261. #endif
  262. };
  263. uECC_Curve uECC_secp192r1(void) { return &curve_secp192r1; }
  264. #if (uECC_OPTIMIZATION_LEVEL > 0)
  265. /* Computes result = product % curve_p.
  266. See algorithm 5 and 6 from http://www.isys.uni-klu.ac.at/PDF/2001-0126-MT.pdf */
  267. #if uECC_WORD_SIZE == 1
  268. static void vli_mmod_fast_secp192r1(uint8_t *result, uint8_t *product) {
  269. uint8_t tmp[num_words_secp192r1];
  270. uint8_t carry;
  271. uECC_vli_set(result, product, num_words_secp192r1);
  272. uECC_vli_set(tmp, &product[24], num_words_secp192r1);
  273. carry = uECC_vli_add(result, result, tmp, num_words_secp192r1);
  274. tmp[0] = tmp[1] = tmp[2] = tmp[3] = tmp[4] = tmp[5] = tmp[6] = tmp[7] = 0;
  275. tmp[8] = product[24]; tmp[9] = product[25]; tmp[10] = product[26]; tmp[11] = product[27];
  276. tmp[12] = product[28]; tmp[13] = product[29]; tmp[14] = product[30]; tmp[15] = product[31];
  277. tmp[16] = product[32]; tmp[17] = product[33]; tmp[18] = product[34]; tmp[19] = product[35];
  278. tmp[20] = product[36]; tmp[21] = product[37]; tmp[22] = product[38]; tmp[23] = product[39];
  279. carry += uECC_vli_add(result, result, tmp, num_words_secp192r1);
  280. tmp[0] = tmp[8] = product[40];
  281. tmp[1] = tmp[9] = product[41];
  282. tmp[2] = tmp[10] = product[42];
  283. tmp[3] = tmp[11] = product[43];
  284. tmp[4] = tmp[12] = product[44];
  285. tmp[5] = tmp[13] = product[45];
  286. tmp[6] = tmp[14] = product[46];
  287. tmp[7] = tmp[15] = product[47];
  288. tmp[16] = tmp[17] = tmp[18] = tmp[19] = tmp[20] = tmp[21] = tmp[22] = tmp[23] = 0;
  289. carry += uECC_vli_add(result, result, tmp, num_words_secp192r1);
  290. while (carry || uECC_vli_cmp_unsafe(curve_secp192r1.p, result, num_words_secp192r1) != 1) {
  291. carry -= uECC_vli_sub(result, result, curve_secp192r1.p, num_words_secp192r1);
  292. }
  293. }
  294. #elif uECC_WORD_SIZE == 4
  295. static void vli_mmod_fast_secp192r1(uint32_t *result, uint32_t *product) {
  296. uint32_t tmp[num_words_secp192r1];
  297. int carry;
  298. uECC_vli_set(result, product, num_words_secp192r1);
  299. uECC_vli_set(tmp, &product[6], num_words_secp192r1);
  300. carry = uECC_vli_add(result, result, tmp, num_words_secp192r1);
  301. tmp[0] = tmp[1] = 0;
  302. tmp[2] = product[6];
  303. tmp[3] = product[7];
  304. tmp[4] = product[8];
  305. tmp[5] = product[9];
  306. carry += uECC_vli_add(result, result, tmp, num_words_secp192r1);
  307. tmp[0] = tmp[2] = product[10];
  308. tmp[1] = tmp[3] = product[11];
  309. tmp[4] = tmp[5] = 0;
  310. carry += uECC_vli_add(result, result, tmp, num_words_secp192r1);
  311. while (carry || uECC_vli_cmp_unsafe(curve_secp192r1.p, result, num_words_secp192r1) != 1) {
  312. carry -= uECC_vli_sub(result, result, curve_secp192r1.p, num_words_secp192r1);
  313. }
  314. }
  315. #else
  316. static void vli_mmod_fast_secp192r1(uint64_t *result, uint64_t *product) {
  317. uint64_t tmp[num_words_secp192r1];
  318. int carry;
  319. uECC_vli_set(result, product, num_words_secp192r1);
  320. uECC_vli_set(tmp, &product[3], num_words_secp192r1);
  321. carry = (int)uECC_vli_add(result, result, tmp, num_words_secp192r1);
  322. tmp[0] = 0;
  323. tmp[1] = product[3];
  324. tmp[2] = product[4];
  325. carry += uECC_vli_add(result, result, tmp, num_words_secp192r1);
  326. tmp[0] = tmp[1] = product[5];
  327. tmp[2] = 0;
  328. carry += uECC_vli_add(result, result, tmp, num_words_secp192r1);
  329. while (carry || uECC_vli_cmp_unsafe(curve_secp192r1.p, result, num_words_secp192r1) != 1) {
  330. carry -= uECC_vli_sub(result, result, curve_secp192r1.p, num_words_secp192r1);
  331. }
  332. }
  333. #endif /* uECC_WORD_SIZE */
  334. #endif /* (uECC_OPTIMIZATION_LEVEL > 0) */
  335. #endif /* uECC_SUPPORTS_secp192r1 */
  336. #if uECC_SUPPORTS_secp224r1
  337. #if uECC_SUPPORT_COMPRESSED_POINT
  338. static void mod_sqrt_secp224r1(uECC_word_t *a, uECC_Curve curve);
  339. #endif
  340. #if (uECC_OPTIMIZATION_LEVEL > 0)
  341. static void vli_mmod_fast_secp224r1(uECC_word_t *result, uECC_word_t *product);
  342. #endif
  343. static const struct uECC_Curve_t curve_secp224r1 = {
  344. num_words_secp224r1,
  345. num_bytes_secp224r1,
  346. 224, /* num_n_bits */
  347. { BYTES_TO_WORDS_8(01, 00, 00, 00, 00, 00, 00, 00),
  348. BYTES_TO_WORDS_8(00, 00, 00, 00, FF, FF, FF, FF),
  349. BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
  350. BYTES_TO_WORDS_4(FF, FF, FF, FF) },
  351. { BYTES_TO_WORDS_8(3D, 2A, 5C, 5C, 45, 29, DD, 13),
  352. BYTES_TO_WORDS_8(3E, F0, B8, E0, A2, 16, FF, FF),
  353. BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
  354. BYTES_TO_WORDS_4(FF, FF, FF, FF) },
  355. { BYTES_TO_WORDS_8(21, 1D, 5C, 11, D6, 80, 32, 34),
  356. BYTES_TO_WORDS_8(22, 11, C2, 56, D3, C1, 03, 4A),
  357. BYTES_TO_WORDS_8(B9, 90, 13, 32, 7F, BF, B4, 6B),
  358. BYTES_TO_WORDS_4(BD, 0C, 0E, B7),
  359. BYTES_TO_WORDS_8(34, 7E, 00, 85, 99, 81, D5, 44),
  360. BYTES_TO_WORDS_8(64, 47, 07, 5A, A0, 75, 43, CD),
  361. BYTES_TO_WORDS_8(E6, DF, 22, 4C, FB, 23, F7, B5),
  362. BYTES_TO_WORDS_4(88, 63, 37, BD) },
  363. { BYTES_TO_WORDS_8(B4, FF, 55, 23, 43, 39, 0B, 27),
  364. BYTES_TO_WORDS_8(BA, D8, BF, D7, B7, B0, 44, 50),
  365. BYTES_TO_WORDS_8(56, 32, 41, F5, AB, B3, 04, 0C),
  366. BYTES_TO_WORDS_4(85, 0A, 05, B4) },
  367. &double_jacobian_default,
  368. #if uECC_SUPPORT_COMPRESSED_POINT
  369. &mod_sqrt_secp224r1,
  370. #endif
  371. &x_side_default,
  372. #if (uECC_OPTIMIZATION_LEVEL > 0)
  373. &vli_mmod_fast_secp224r1
  374. #endif
  375. };
  376. uECC_Curve uECC_secp224r1(void) { return &curve_secp224r1; }
  377. #if uECC_SUPPORT_COMPRESSED_POINT
  378. /* Routine 3.2.4 RS; from http://www.nsa.gov/ia/_files/nist-routines.pdf */
  379. static void mod_sqrt_secp224r1_rs(uECC_word_t *d1,
  380. uECC_word_t *e1,
  381. uECC_word_t *f1,
  382. const uECC_word_t *d0,
  383. const uECC_word_t *e0,
  384. const uECC_word_t *f0) {
  385. uECC_word_t t[num_words_secp224r1];
  386. uECC_vli_modSquare_fast(t, d0, &curve_secp224r1); /* t <-- d0 ^ 2 */
  387. uECC_vli_modMult_fast(e1, d0, e0, &curve_secp224r1); /* e1 <-- d0 * e0 */
  388. uECC_vli_modAdd(d1, t, f0, curve_secp224r1.p, num_words_secp224r1); /* d1 <-- t + f0 */
  389. uECC_vli_modAdd(e1, e1, e1, curve_secp224r1.p, num_words_secp224r1); /* e1 <-- e1 + e1 */
  390. uECC_vli_modMult_fast(f1, t, f0, &curve_secp224r1); /* f1 <-- t * f0 */
  391. uECC_vli_modAdd(f1, f1, f1, curve_secp224r1.p, num_words_secp224r1); /* f1 <-- f1 + f1 */
  392. uECC_vli_modAdd(f1, f1, f1, curve_secp224r1.p, num_words_secp224r1); /* f1 <-- f1 + f1 */
  393. }
  394. /* Routine 3.2.5 RSS; from http://www.nsa.gov/ia/_files/nist-routines.pdf */
  395. static void mod_sqrt_secp224r1_rss(uECC_word_t *d1,
  396. uECC_word_t *e1,
  397. uECC_word_t *f1,
  398. const uECC_word_t *d0,
  399. const uECC_word_t *e0,
  400. const uECC_word_t *f0,
  401. const bitcount_t j) {
  402. bitcount_t i;
  403. uECC_vli_set(d1, d0, num_words_secp224r1); /* d1 <-- d0 */
  404. uECC_vli_set(e1, e0, num_words_secp224r1); /* e1 <-- e0 */
  405. uECC_vli_set(f1, f0, num_words_secp224r1); /* f1 <-- f0 */
  406. for (i = 1; i <= j; i++) {
  407. mod_sqrt_secp224r1_rs(d1, e1, f1, d1, e1, f1); /* RS (d1,e1,f1,d1,e1,f1) */
  408. }
  409. }
  410. /* Routine 3.2.6 RM; from http://www.nsa.gov/ia/_files/nist-routines.pdf */
  411. static void mod_sqrt_secp224r1_rm(uECC_word_t *d2,
  412. uECC_word_t *e2,
  413. uECC_word_t *f2,
  414. const uECC_word_t *c,
  415. const uECC_word_t *d0,
  416. const uECC_word_t *e0,
  417. const uECC_word_t *d1,
  418. const uECC_word_t *e1) {
  419. uECC_word_t t1[num_words_secp224r1];
  420. uECC_word_t t2[num_words_secp224r1];
  421. uECC_vli_modMult_fast(t1, e0, e1, &curve_secp224r1); /* t1 <-- e0 * e1 */
  422. uECC_vli_modMult_fast(t1, t1, c, &curve_secp224r1); /* t1 <-- t1 * c */
  423. /* t1 <-- p - t1 */
  424. uECC_vli_modSub(t1, curve_secp224r1.p, t1, curve_secp224r1.p, num_words_secp224r1);
  425. uECC_vli_modMult_fast(t2, d0, d1, &curve_secp224r1); /* t2 <-- d0 * d1 */
  426. uECC_vli_modAdd(t2, t2, t1, curve_secp224r1.p, num_words_secp224r1); /* t2 <-- t2 + t1 */
  427. uECC_vli_modMult_fast(t1, d0, e1, &curve_secp224r1); /* t1 <-- d0 * e1 */
  428. uECC_vli_modMult_fast(e2, d1, e0, &curve_secp224r1); /* e2 <-- d1 * e0 */
  429. uECC_vli_modAdd(e2, e2, t1, curve_secp224r1.p, num_words_secp224r1); /* e2 <-- e2 + t1 */
  430. uECC_vli_modSquare_fast(f2, e2, &curve_secp224r1); /* f2 <-- e2^2 */
  431. uECC_vli_modMult_fast(f2, f2, c, &curve_secp224r1); /* f2 <-- f2 * c */
  432. /* f2 <-- p - f2 */
  433. uECC_vli_modSub(f2, curve_secp224r1.p, f2, curve_secp224r1.p, num_words_secp224r1);
  434. uECC_vli_set(d2, t2, num_words_secp224r1); /* d2 <-- t2 */
  435. }
  436. /* Routine 3.2.7 RP; from http://www.nsa.gov/ia/_files/nist-routines.pdf */
  437. static void mod_sqrt_secp224r1_rp(uECC_word_t *d1,
  438. uECC_word_t *e1,
  439. uECC_word_t *f1,
  440. const uECC_word_t *c,
  441. const uECC_word_t *r) {
  442. wordcount_t i;
  443. wordcount_t pow2i = 1;
  444. uECC_word_t d0[num_words_secp224r1];
  445. uECC_word_t e0[num_words_secp224r1] = {1}; /* e0 <-- 1 */
  446. uECC_word_t f0[num_words_secp224r1];
  447. uECC_vli_set(d0, r, num_words_secp224r1); /* d0 <-- r */
  448. /* f0 <-- p - c */
  449. uECC_vli_modSub(f0, curve_secp224r1.p, c, curve_secp224r1.p, num_words_secp224r1);
  450. for (i = 0; i <= 6; i++) {
  451. mod_sqrt_secp224r1_rss(d1, e1, f1, d0, e0, f0, pow2i); /* RSS (d1,e1,f1,d0,e0,f0,2^i) */
  452. mod_sqrt_secp224r1_rm(d1, e1, f1, c, d1, e1, d0, e0); /* RM (d1,e1,f1,c,d1,e1,d0,e0) */
  453. uECC_vli_set(d0, d1, num_words_secp224r1); /* d0 <-- d1 */
  454. uECC_vli_set(e0, e1, num_words_secp224r1); /* e0 <-- e1 */
  455. uECC_vli_set(f0, f1, num_words_secp224r1); /* f0 <-- f1 */
  456. pow2i *= 2;
  457. }
  458. }
  459. /* Compute a = sqrt(a) (mod curve_p). */
  460. /* Routine 3.2.8 mp_mod_sqrt_224; from http://www.nsa.gov/ia/_files/nist-routines.pdf */
  461. static void mod_sqrt_secp224r1(uECC_word_t *a, uECC_Curve curve) {
  462. (void)curve;
  463. bitcount_t i;
  464. uECC_word_t e1[num_words_secp224r1];
  465. uECC_word_t f1[num_words_secp224r1];
  466. uECC_word_t d0[num_words_secp224r1];
  467. uECC_word_t e0[num_words_secp224r1];
  468. uECC_word_t f0[num_words_secp224r1];
  469. uECC_word_t d1[num_words_secp224r1];
  470. /* s = a; using constant instead of random value */
  471. mod_sqrt_secp224r1_rp(d0, e0, f0, a, a); /* RP (d0, e0, f0, c, s) */
  472. mod_sqrt_secp224r1_rs(d1, e1, f1, d0, e0, f0); /* RS (d1, e1, f1, d0, e0, f0) */
  473. for (i = 1; i <= 95; i++) {
  474. uECC_vli_set(d0, d1, num_words_secp224r1); /* d0 <-- d1 */
  475. uECC_vli_set(e0, e1, num_words_secp224r1); /* e0 <-- e1 */
  476. uECC_vli_set(f0, f1, num_words_secp224r1); /* f0 <-- f1 */
  477. mod_sqrt_secp224r1_rs(d1, e1, f1, d0, e0, f0); /* RS (d1, e1, f1, d0, e0, f0) */
  478. if (uECC_vli_isZero(d1, num_words_secp224r1)) { /* if d1 == 0 */
  479. break;
  480. }
  481. }
  482. uECC_vli_modInv(f1, e0, curve_secp224r1.p, num_words_secp224r1); /* f1 <-- 1 / e0 */
  483. uECC_vli_modMult_fast(a, d0, f1, &curve_secp224r1); /* a <-- d0 / e0 */
  484. }
  485. #endif /* uECC_SUPPORT_COMPRESSED_POINT */
  486. #if (uECC_OPTIMIZATION_LEVEL > 0)
  487. /* Computes result = product % curve_p
  488. from http://www.nsa.gov/ia/_files/nist-routines.pdf */
  489. #if uECC_WORD_SIZE == 1
  490. static void vli_mmod_fast_secp224r1(uint8_t *result, uint8_t *product) {
  491. uint8_t tmp[num_words_secp224r1];
  492. int8_t carry;
  493. /* t */
  494. uECC_vli_set(result, product, num_words_secp224r1);
  495. /* s1 */
  496. tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
  497. tmp[4] = tmp[5] = tmp[6] = tmp[7] = 0;
  498. tmp[8] = tmp[9] = tmp[10] = tmp[11] = 0;
  499. tmp[12] = product[28]; tmp[13] = product[29]; tmp[14] = product[30]; tmp[15] = product[31];
  500. tmp[16] = product[32]; tmp[17] = product[33]; tmp[18] = product[34]; tmp[19] = product[35];
  501. tmp[20] = product[36]; tmp[21] = product[37]; tmp[22] = product[38]; tmp[23] = product[39];
  502. tmp[24] = product[40]; tmp[25] = product[41]; tmp[26] = product[42]; tmp[27] = product[43];
  503. carry = uECC_vli_add(result, result, tmp, num_words_secp224r1);
  504. /* s2 */
  505. tmp[12] = product[44]; tmp[13] = product[45]; tmp[14] = product[46]; tmp[15] = product[47];
  506. tmp[16] = product[48]; tmp[17] = product[49]; tmp[18] = product[50]; tmp[19] = product[51];
  507. tmp[20] = product[52]; tmp[21] = product[53]; tmp[22] = product[54]; tmp[23] = product[55];
  508. tmp[24] = tmp[25] = tmp[26] = tmp[27] = 0;
  509. carry += uECC_vli_add(result, result, tmp, num_words_secp224r1);
  510. /* d1 */
  511. tmp[0] = product[28]; tmp[1] = product[29]; tmp[2] = product[30]; tmp[3] = product[31];
  512. tmp[4] = product[32]; tmp[5] = product[33]; tmp[6] = product[34]; tmp[7] = product[35];
  513. tmp[8] = product[36]; tmp[9] = product[37]; tmp[10] = product[38]; tmp[11] = product[39];
  514. tmp[12] = product[40]; tmp[13] = product[41]; tmp[14] = product[42]; tmp[15] = product[43];
  515. tmp[16] = product[44]; tmp[17] = product[45]; tmp[18] = product[46]; tmp[19] = product[47];
  516. tmp[20] = product[48]; tmp[21] = product[49]; tmp[22] = product[50]; tmp[23] = product[51];
  517. tmp[24] = product[52]; tmp[25] = product[53]; tmp[26] = product[54]; tmp[27] = product[55];
  518. carry -= uECC_vli_sub(result, result, tmp, num_words_secp224r1);
  519. /* d2 */
  520. tmp[0] = product[44]; tmp[1] = product[45]; tmp[2] = product[46]; tmp[3] = product[47];
  521. tmp[4] = product[48]; tmp[5] = product[49]; tmp[6] = product[50]; tmp[7] = product[51];
  522. tmp[8] = product[52]; tmp[9] = product[53]; tmp[10] = product[54]; tmp[11] = product[55];
  523. tmp[12] = tmp[13] = tmp[14] = tmp[15] = 0;
  524. tmp[16] = tmp[17] = tmp[18] = tmp[19] = 0;
  525. tmp[20] = tmp[21] = tmp[22] = tmp[23] = 0;
  526. tmp[24] = tmp[25] = tmp[26] = tmp[27] = 0;
  527. carry -= uECC_vli_sub(result, result, tmp, num_words_secp224r1);
  528. if (carry < 0) {
  529. do {
  530. carry += uECC_vli_add(result, result, curve_secp224r1.p, num_words_secp224r1);
  531. } while (carry < 0);
  532. } else {
  533. while (carry || uECC_vli_cmp_unsafe(curve_secp224r1.p, result, num_words_secp224r1) != 1) {
  534. carry -= uECC_vli_sub(result, result, curve_secp224r1.p, num_words_secp224r1);
  535. }
  536. }
  537. }
  538. #elif uECC_WORD_SIZE == 4
  539. static void vli_mmod_fast_secp224r1(uint32_t *result, uint32_t *product)
  540. {
  541. uint32_t tmp[num_words_secp224r1];
  542. int carry;
  543. /* t */
  544. uECC_vli_set(result, product, num_words_secp224r1);
  545. /* s1 */
  546. tmp[0] = tmp[1] = tmp[2] = 0;
  547. tmp[3] = product[7];
  548. tmp[4] = product[8];
  549. tmp[5] = product[9];
  550. tmp[6] = product[10];
  551. carry = uECC_vli_add(result, result, tmp, num_words_secp224r1);
  552. /* s2 */
  553. tmp[3] = product[11];
  554. tmp[4] = product[12];
  555. tmp[5] = product[13];
  556. tmp[6] = 0;
  557. carry += uECC_vli_add(result, result, tmp, num_words_secp224r1);
  558. /* d1 */
  559. tmp[0] = product[7];
  560. tmp[1] = product[8];
  561. tmp[2] = product[9];
  562. tmp[3] = product[10];
  563. tmp[4] = product[11];
  564. tmp[5] = product[12];
  565. tmp[6] = product[13];
  566. carry -= uECC_vli_sub(result, result, tmp, num_words_secp224r1);
  567. /* d2 */
  568. tmp[0] = product[11];
  569. tmp[1] = product[12];
  570. tmp[2] = product[13];
  571. tmp[3] = tmp[4] = tmp[5] = tmp[6] = 0;
  572. carry -= uECC_vli_sub(result, result, tmp, num_words_secp224r1);
  573. if (carry < 0) {
  574. do {
  575. carry += uECC_vli_add(result, result, curve_secp224r1.p, num_words_secp224r1);
  576. } while (carry < 0);
  577. } else {
  578. while (carry || uECC_vli_cmp_unsafe(curve_secp224r1.p, result, num_words_secp224r1) != 1) {
  579. carry -= uECC_vli_sub(result, result, curve_secp224r1.p, num_words_secp224r1);
  580. }
  581. }
  582. }
  583. #else
  584. static void vli_mmod_fast_secp224r1(uint64_t *result, uint64_t *product)
  585. {
  586. uint64_t tmp[num_words_secp224r1];
  587. int carry = 0;
  588. /* t */
  589. uECC_vli_set(result, product, num_words_secp224r1);
  590. result[num_words_secp224r1 - 1] &= 0xffffffff;
  591. /* s1 */
  592. tmp[0] = 0;
  593. tmp[1] = product[3] & 0xffffffff00000000ull;
  594. tmp[2] = product[4];
  595. tmp[3] = product[5] & 0xffffffff;
  596. uECC_vli_add(result, result, tmp, num_words_secp224r1);
  597. /* s2 */
  598. tmp[1] = product[5] & 0xffffffff00000000ull;
  599. tmp[2] = product[6];
  600. tmp[3] = 0;
  601. uECC_vli_add(result, result, tmp, num_words_secp224r1);
  602. /* d1 */
  603. tmp[0] = (product[3] >> 32) | (product[4] << 32);
  604. tmp[1] = (product[4] >> 32) | (product[5] << 32);
  605. tmp[2] = (product[5] >> 32) | (product[6] << 32);
  606. tmp[3] = product[6] >> 32;
  607. carry -= uECC_vli_sub(result, result, tmp, num_words_secp224r1);
  608. /* d2 */
  609. tmp[0] = (product[5] >> 32) | (product[6] << 32);
  610. tmp[1] = product[6] >> 32;
  611. tmp[2] = tmp[3] = 0;
  612. carry -= uECC_vli_sub(result, result, tmp, num_words_secp224r1);
  613. if (carry < 0) {
  614. do {
  615. carry += uECC_vli_add(result, result, curve_secp224r1.p, num_words_secp224r1);
  616. } while (carry < 0);
  617. } else {
  618. while (uECC_vli_cmp_unsafe(curve_secp224r1.p, result, num_words_secp224r1) != 1) {
  619. uECC_vli_sub(result, result, curve_secp224r1.p, num_words_secp224r1);
  620. }
  621. }
  622. }
  623. #endif /* uECC_WORD_SIZE */
  624. #endif /* (uECC_OPTIMIZATION_LEVEL > 0) */
  625. #endif /* uECC_SUPPORTS_secp224r1 */
  626. #if uECC_SUPPORTS_secp256r1
  627. #if (uECC_OPTIMIZATION_LEVEL > 0)
  628. static void vli_mmod_fast_secp256r1(uECC_word_t *result, uECC_word_t *product);
  629. #endif
  630. static const struct uECC_Curve_t curve_secp256r1 = {
  631. num_words_secp256r1,
  632. num_bytes_secp256r1,
  633. 256, /* num_n_bits */
  634. { BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
  635. BYTES_TO_WORDS_8(FF, FF, FF, FF, 00, 00, 00, 00),
  636. BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00),
  637. BYTES_TO_WORDS_8(01, 00, 00, 00, FF, FF, FF, FF) },
  638. { BYTES_TO_WORDS_8(51, 25, 63, FC, C2, CA, B9, F3),
  639. BYTES_TO_WORDS_8(84, 9E, 17, A7, AD, FA, E6, BC),
  640. BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
  641. BYTES_TO_WORDS_8(00, 00, 00, 00, FF, FF, FF, FF) },
  642. { BYTES_TO_WORDS_8(96, C2, 98, D8, 45, 39, A1, F4),
  643. BYTES_TO_WORDS_8(A0, 33, EB, 2D, 81, 7D, 03, 77),
  644. BYTES_TO_WORDS_8(F2, 40, A4, 63, E5, E6, BC, F8),
  645. BYTES_TO_WORDS_8(47, 42, 2C, E1, F2, D1, 17, 6B),
  646. BYTES_TO_WORDS_8(F5, 51, BF, 37, 68, 40, B6, CB),
  647. BYTES_TO_WORDS_8(CE, 5E, 31, 6B, 57, 33, CE, 2B),
  648. BYTES_TO_WORDS_8(16, 9E, 0F, 7C, 4A, EB, E7, 8E),
  649. BYTES_TO_WORDS_8(9B, 7F, 1A, FE, E2, 42, E3, 4F) },
  650. { BYTES_TO_WORDS_8(4B, 60, D2, 27, 3E, 3C, CE, 3B),
  651. BYTES_TO_WORDS_8(F6, B0, 53, CC, B0, 06, 1D, 65),
  652. BYTES_TO_WORDS_8(BC, 86, 98, 76, 55, BD, EB, B3),
  653. BYTES_TO_WORDS_8(E7, 93, 3A, AA, D8, 35, C6, 5A) },
  654. &double_jacobian_default,
  655. #if uECC_SUPPORT_COMPRESSED_POINT
  656. &mod_sqrt_default,
  657. #endif
  658. &x_side_default,
  659. #if (uECC_OPTIMIZATION_LEVEL > 0)
  660. &vli_mmod_fast_secp256r1
  661. #endif
  662. };
  663. uECC_Curve uECC_secp256r1(void) { return &curve_secp256r1; }
  664. #if (uECC_OPTIMIZATION_LEVEL > 0 && !asm_mmod_fast_secp256r1)
  665. /* Computes result = product % curve_p
  666. from http://www.nsa.gov/ia/_files/nist-routines.pdf */
  667. #if uECC_WORD_SIZE == 1
  668. static void vli_mmod_fast_secp256r1(uint8_t *result, uint8_t *product) {
  669. uint8_t tmp[num_words_secp256r1];
  670. int8_t carry;
  671. /* t */
  672. uECC_vli_set(result, product, num_words_secp256r1);
  673. /* s1 */
  674. tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
  675. tmp[4] = tmp[5] = tmp[6] = tmp[7] = 0;
  676. tmp[8] = tmp[9] = tmp[10] = tmp[11] = 0;
  677. tmp[12] = product[44]; tmp[13] = product[45]; tmp[14] = product[46]; tmp[15] = product[47];
  678. tmp[16] = product[48]; tmp[17] = product[49]; tmp[18] = product[50]; tmp[19] = product[51];
  679. tmp[20] = product[52]; tmp[21] = product[53]; tmp[22] = product[54]; tmp[23] = product[55];
  680. tmp[24] = product[56]; tmp[25] = product[57]; tmp[26] = product[58]; tmp[27] = product[59];
  681. tmp[28] = product[60]; tmp[29] = product[61]; tmp[30] = product[62]; tmp[31] = product[63];
  682. carry = uECC_vli_add(tmp, tmp, tmp, num_words_secp256r1);
  683. carry += uECC_vli_add(result, result, tmp, num_words_secp256r1);
  684. /* s2 */
  685. tmp[12] = product[48]; tmp[13] = product[49]; tmp[14] = product[50]; tmp[15] = product[51];
  686. tmp[16] = product[52]; tmp[17] = product[53]; tmp[18] = product[54]; tmp[19] = product[55];
  687. tmp[20] = product[56]; tmp[21] = product[57]; tmp[22] = product[58]; tmp[23] = product[59];
  688. tmp[24] = product[60]; tmp[25] = product[61]; tmp[26] = product[62]; tmp[27] = product[63];
  689. tmp[28] = tmp[29] = tmp[30] = tmp[31] = 0;
  690. carry += uECC_vli_add(tmp, tmp, tmp, num_words_secp256r1);
  691. carry += uECC_vli_add(result, result, tmp, num_words_secp256r1);
  692. /* s3 */
  693. tmp[0] = product[32]; tmp[1] = product[33]; tmp[2] = product[34]; tmp[3] = product[35];
  694. tmp[4] = product[36]; tmp[5] = product[37]; tmp[6] = product[38]; tmp[7] = product[39];
  695. tmp[8] = product[40]; tmp[9] = product[41]; tmp[10] = product[42]; tmp[11] = product[43];
  696. tmp[12] = tmp[13] = tmp[14] = tmp[15] = 0;
  697. tmp[16] = tmp[17] = tmp[18] = tmp[19] = 0;
  698. tmp[20] = tmp[21] = tmp[22] = tmp[23] = 0;
  699. tmp[24] = product[56]; tmp[25] = product[57]; tmp[26] = product[58]; tmp[27] = product[59];
  700. tmp[28] = product[60]; tmp[29] = product[61]; tmp[30] = product[62]; tmp[31] = product[63];
  701. carry += uECC_vli_add(result, result, tmp, num_words_secp256r1);
  702. /* s4 */
  703. tmp[0] = product[36]; tmp[1] = product[37]; tmp[2] = product[38]; tmp[3] = product[39];
  704. tmp[4] = product[40]; tmp[5] = product[41]; tmp[6] = product[42]; tmp[7] = product[43];
  705. tmp[8] = product[44]; tmp[9] = product[45]; tmp[10] = product[46]; tmp[11] = product[47];
  706. tmp[12] = product[52]; tmp[13] = product[53]; tmp[14] = product[54]; tmp[15] = product[55];
  707. tmp[16] = product[56]; tmp[17] = product[57]; tmp[18] = product[58]; tmp[19] = product[59];
  708. tmp[20] = product[60]; tmp[21] = product[61]; tmp[22] = product[62]; tmp[23] = product[63];
  709. tmp[24] = product[52]; tmp[25] = product[53]; tmp[26] = product[54]; tmp[27] = product[55];
  710. tmp[28] = product[32]; tmp[29] = product[33]; tmp[30] = product[34]; tmp[31] = product[35];
  711. carry += uECC_vli_add(result, result, tmp, num_words_secp256r1);
  712. /* d1 */
  713. tmp[0] = product[44]; tmp[1] = product[45]; tmp[2] = product[46]; tmp[3] = product[47];
  714. tmp[4] = product[48]; tmp[5] = product[49]; tmp[6] = product[50]; tmp[7] = product[51];
  715. tmp[8] = product[52]; tmp[9] = product[53]; tmp[10] = product[54]; tmp[11] = product[55];
  716. tmp[12] = tmp[13] = tmp[14] = tmp[15] = 0;
  717. tmp[16] = tmp[17] = tmp[18] = tmp[19] = 0;
  718. tmp[20] = tmp[21] = tmp[22] = tmp[23] = 0;
  719. tmp[24] = product[32]; tmp[25] = product[33]; tmp[26] = product[34]; tmp[27] = product[35];
  720. tmp[28] = product[40]; tmp[29] = product[41]; tmp[30] = product[42]; tmp[31] = product[43];
  721. carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1);
  722. /* d2 */
  723. tmp[0] = product[48]; tmp[1] = product[49]; tmp[2] = product[50]; tmp[3] = product[51];
  724. tmp[4] = product[52]; tmp[5] = product[53]; tmp[6] = product[54]; tmp[7] = product[55];
  725. tmp[8] = product[56]; tmp[9] = product[57]; tmp[10] = product[58]; tmp[11] = product[59];
  726. tmp[12] = product[60]; tmp[13] = product[61]; tmp[14] = product[62]; tmp[15] = product[63];
  727. tmp[16] = tmp[17] = tmp[18] = tmp[19] = 0;
  728. tmp[20] = tmp[21] = tmp[22] = tmp[23] = 0;
  729. tmp[24] = product[36]; tmp[25] = product[37]; tmp[26] = product[38]; tmp[27] = product[39];
  730. tmp[28] = product[44]; tmp[29] = product[45]; tmp[30] = product[46]; tmp[31] = product[47];
  731. carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1);
  732. /* d3 */
  733. tmp[0] = product[52]; tmp[1] = product[53]; tmp[2] = product[54]; tmp[3] = product[55];
  734. tmp[4] = product[56]; tmp[5] = product[57]; tmp[6] = product[58]; tmp[7] = product[59];
  735. tmp[8] = product[60]; tmp[9] = product[61]; tmp[10] = product[62]; tmp[11] = product[63];
  736. tmp[12] = product[32]; tmp[13] = product[33]; tmp[14] = product[34]; tmp[15] = product[35];
  737. tmp[16] = product[36]; tmp[17] = product[37]; tmp[18] = product[38]; tmp[19] = product[39];
  738. tmp[20] = product[40]; tmp[21] = product[41]; tmp[22] = product[42]; tmp[23] = product[43];
  739. tmp[24] = tmp[25] = tmp[26] = tmp[27] = 0;
  740. tmp[28] = product[48]; tmp[29] = product[49]; tmp[30] = product[50]; tmp[31] = product[51];
  741. carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1);
  742. /* d4 */
  743. tmp[0] = product[56]; tmp[1] = product[57]; tmp[2] = product[58]; tmp[3] = product[59];
  744. tmp[4] = product[60]; tmp[5] = product[61]; tmp[6] = product[62]; tmp[7] = product[63];
  745. tmp[8] = tmp[9] = tmp[10] = tmp[11] = 0;
  746. tmp[12] = product[36]; tmp[13] = product[37]; tmp[14] = product[38]; tmp[15] = product[39];
  747. tmp[16] = product[40]; tmp[17] = product[41]; tmp[18] = product[42]; tmp[19] = product[43];
  748. tmp[20] = product[44]; tmp[21] = product[45]; tmp[22] = product[46]; tmp[23] = product[47];
  749. tmp[24] = tmp[25] = tmp[26] = tmp[27] = 0;
  750. tmp[28] = product[52]; tmp[29] = product[53]; tmp[30] = product[54]; tmp[31] = product[55];
  751. carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1);
  752. if (carry < 0) {
  753. do {
  754. carry += uECC_vli_add(result, result, curve_secp256r1.p, num_words_secp256r1);
  755. } while (carry < 0);
  756. } else {
  757. while (carry || uECC_vli_cmp_unsafe(curve_secp256r1.p, result, num_words_secp256r1) != 1) {
  758. carry -= uECC_vli_sub(result, result, curve_secp256r1.p, num_words_secp256r1);
  759. }
  760. }
  761. }
  762. #elif uECC_WORD_SIZE == 4
  763. static void vli_mmod_fast_secp256r1(uint32_t *result, uint32_t *product) {
  764. uint32_t tmp[num_words_secp256r1];
  765. int carry;
  766. /* t */
  767. uECC_vli_set(result, product, num_words_secp256r1);
  768. /* s1 */
  769. tmp[0] = tmp[1] = tmp[2] = 0;
  770. tmp[3] = product[11];
  771. tmp[4] = product[12];
  772. tmp[5] = product[13];
  773. tmp[6] = product[14];
  774. tmp[7] = product[15];
  775. carry = uECC_vli_add(tmp, tmp, tmp, num_words_secp256r1);
  776. carry += uECC_vli_add(result, result, tmp, num_words_secp256r1);
  777. /* s2 */
  778. tmp[3] = product[12];
  779. tmp[4] = product[13];
  780. tmp[5] = product[14];
  781. tmp[6] = product[15];
  782. tmp[7] = 0;
  783. carry += uECC_vli_add(tmp, tmp, tmp, num_words_secp256r1);
  784. carry += uECC_vli_add(result, result, tmp, num_words_secp256r1);
  785. /* s3 */
  786. tmp[0] = product[8];
  787. tmp[1] = product[9];
  788. tmp[2] = product[10];
  789. tmp[3] = tmp[4] = tmp[5] = 0;
  790. tmp[6] = product[14];
  791. tmp[7] = product[15];
  792. carry += uECC_vli_add(result, result, tmp, num_words_secp256r1);
  793. /* s4 */
  794. tmp[0] = product[9];
  795. tmp[1] = product[10];
  796. tmp[2] = product[11];
  797. tmp[3] = product[13];
  798. tmp[4] = product[14];
  799. tmp[5] = product[15];
  800. tmp[6] = product[13];
  801. tmp[7] = product[8];
  802. carry += uECC_vli_add(result, result, tmp, num_words_secp256r1);
  803. /* d1 */
  804. tmp[0] = product[11];
  805. tmp[1] = product[12];
  806. tmp[2] = product[13];
  807. tmp[3] = tmp[4] = tmp[5] = 0;
  808. tmp[6] = product[8];
  809. tmp[7] = product[10];
  810. carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1);
  811. /* d2 */
  812. tmp[0] = product[12];
  813. tmp[1] = product[13];
  814. tmp[2] = product[14];
  815. tmp[3] = product[15];
  816. tmp[4] = tmp[5] = 0;
  817. tmp[6] = product[9];
  818. tmp[7] = product[11];
  819. carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1);
  820. /* d3 */
  821. tmp[0] = product[13];
  822. tmp[1] = product[14];
  823. tmp[2] = product[15];
  824. tmp[3] = product[8];
  825. tmp[4] = product[9];
  826. tmp[5] = product[10];
  827. tmp[6] = 0;
  828. tmp[7] = product[12];
  829. carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1);
  830. /* d4 */
  831. tmp[0] = product[14];
  832. tmp[1] = product[15];
  833. tmp[2] = 0;
  834. tmp[3] = product[9];
  835. tmp[4] = product[10];
  836. tmp[5] = product[11];
  837. tmp[6] = 0;
  838. tmp[7] = product[13];
  839. carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1);
  840. if (carry < 0) {
  841. do {
  842. carry += uECC_vli_add(result, result, curve_secp256r1.p, num_words_secp256r1);
  843. } while (carry < 0);
  844. } else {
  845. while (carry || uECC_vli_cmp_unsafe(curve_secp256r1.p, result, num_words_secp256r1) != 1) {
  846. carry -= uECC_vli_sub(result, result, curve_secp256r1.p, num_words_secp256r1);
  847. }
  848. }
  849. }
  850. #else
  851. static void vli_mmod_fast_secp256r1(uint64_t *result, uint64_t *product) {
  852. uint64_t tmp[num_words_secp256r1];
  853. int carry;
  854. /* t */
  855. uECC_vli_set(result, product, num_words_secp256r1);
  856. /* s1 */
  857. tmp[0] = 0;
  858. tmp[1] = product[5] & 0xffffffff00000000ull;
  859. tmp[2] = product[6];
  860. tmp[3] = product[7];
  861. carry = (int)uECC_vli_add(tmp, tmp, tmp, num_words_secp256r1);
  862. carry += uECC_vli_add(result, result, tmp, num_words_secp256r1);
  863. /* s2 */
  864. tmp[1] = product[6] << 32;
  865. tmp[2] = (product[6] >> 32) | (product[7] << 32);
  866. tmp[3] = product[7] >> 32;
  867. carry += uECC_vli_add(tmp, tmp, tmp, num_words_secp256r1);
  868. carry += uECC_vli_add(result, result, tmp, num_words_secp256r1);
  869. /* s3 */
  870. tmp[0] = product[4];
  871. tmp[1] = product[5] & 0xffffffff;
  872. tmp[2] = 0;
  873. tmp[3] = product[7];
  874. carry += uECC_vli_add(result, result, tmp, num_words_secp256r1);
  875. /* s4 */
  876. tmp[0] = (product[4] >> 32) | (product[5] << 32);
  877. tmp[1] = (product[5] >> 32) | (product[6] & 0xffffffff00000000ull);
  878. tmp[2] = product[7];
  879. tmp[3] = (product[6] >> 32) | (product[4] << 32);
  880. carry += uECC_vli_add(result, result, tmp, num_words_secp256r1);
  881. /* d1 */
  882. tmp[0] = (product[5] >> 32) | (product[6] << 32);
  883. tmp[1] = (product[6] >> 32);
  884. tmp[2] = 0;
  885. tmp[3] = (product[4] & 0xffffffff) | (product[5] << 32);
  886. carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1);
  887. /* d2 */
  888. tmp[0] = product[6];
  889. tmp[1] = product[7];
  890. tmp[2] = 0;
  891. tmp[3] = (product[4] >> 32) | (product[5] & 0xffffffff00000000ull);
  892. carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1);
  893. /* d3 */
  894. tmp[0] = (product[6] >> 32) | (product[7] << 32);
  895. tmp[1] = (product[7] >> 32) | (product[4] << 32);
  896. tmp[2] = (product[4] >> 32) | (product[5] << 32);
  897. tmp[3] = (product[6] << 32);
  898. carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1);
  899. /* d4 */
  900. tmp[0] = product[7];
  901. tmp[1] = product[4] & 0xffffffff00000000ull;
  902. tmp[2] = product[5];
  903. tmp[3] = product[6] & 0xffffffff00000000ull;
  904. carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1);
  905. if (carry < 0) {
  906. do {
  907. carry += uECC_vli_add(result, result, curve_secp256r1.p, num_words_secp256r1);
  908. } while (carry < 0);
  909. } else {
  910. while (carry || uECC_vli_cmp_unsafe(curve_secp256r1.p, result, num_words_secp256r1) != 1) {
  911. carry -= uECC_vli_sub(result, result, curve_secp256r1.p, num_words_secp256r1);
  912. }
  913. }
  914. }
  915. #endif /* uECC_WORD_SIZE */
  916. #endif /* (uECC_OPTIMIZATION_LEVEL > 0 && !asm_mmod_fast_secp256r1) */
  917. #endif /* uECC_SUPPORTS_secp256r1 */
  918. #if uECC_SUPPORTS_secp256k1
  919. static void double_jacobian_secp256k1(uECC_word_t * X1,
  920. uECC_word_t * Y1,
  921. uECC_word_t * Z1,
  922. uECC_Curve curve);
  923. static void x_side_secp256k1(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve);
  924. #if (uECC_OPTIMIZATION_LEVEL > 0)
  925. static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product);
  926. #endif
  927. static const struct uECC_Curve_t curve_secp256k1 = {
  928. num_words_secp256k1,
  929. num_bytes_secp256k1,
  930. 256, /* num_n_bits */
  931. { BYTES_TO_WORDS_8(2F, FC, FF, FF, FE, FF, FF, FF),
  932. BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
  933. BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
  934. BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF) },
  935. { BYTES_TO_WORDS_8(41, 41, 36, D0, 8C, 5E, D2, BF),
  936. BYTES_TO_WORDS_8(3B, A0, 48, AF, E6, DC, AE, BA),
  937. BYTES_TO_WORDS_8(FE, FF, FF, FF, FF, FF, FF, FF),
  938. BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF) },
  939. { BYTES_TO_WORDS_8(98, 17, F8, 16, 5B, 81, F2, 59),
  940. BYTES_TO_WORDS_8(D9, 28, CE, 2D, DB, FC, 9B, 02),
  941. BYTES_TO_WORDS_8(07, 0B, 87, CE, 95, 62, A0, 55),
  942. BYTES_TO_WORDS_8(AC, BB, DC, F9, 7E, 66, BE, 79),
  943. BYTES_TO_WORDS_8(B8, D4, 10, FB, 8F, D0, 47, 9C),
  944. BYTES_TO_WORDS_8(19, 54, 85, A6, 48, B4, 17, FD),
  945. BYTES_TO_WORDS_8(A8, 08, 11, 0E, FC, FB, A4, 5D),
  946. BYTES_TO_WORDS_8(65, C4, A3, 26, 77, DA, 3A, 48) },
  947. { BYTES_TO_WORDS_8(07, 00, 00, 00, 00, 00, 00, 00),
  948. BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00),
  949. BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00),
  950. BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00) },
  951. &double_jacobian_secp256k1,
  952. #if uECC_SUPPORT_COMPRESSED_POINT
  953. &mod_sqrt_default,
  954. #endif
  955. &x_side_secp256k1,
  956. #if (uECC_OPTIMIZATION_LEVEL > 0)
  957. &vli_mmod_fast_secp256k1
  958. #endif
  959. };
  960. uECC_Curve uECC_secp256k1(void) { return &curve_secp256k1; }
  961. /* Double in place */
  962. static void double_jacobian_secp256k1(uECC_word_t * X1,
  963. uECC_word_t * Y1,
  964. uECC_word_t * Z1,
  965. uECC_Curve curve) {
  966. /* t1 = X, t2 = Y, t3 = Z */
  967. uECC_word_t t4[num_words_secp256k1];
  968. uECC_word_t t5[num_words_secp256k1];
  969. if (uECC_vli_isZero(Z1, num_words_secp256k1)) {
  970. return;
  971. }
  972. uECC_vli_modSquare_fast(t5, Y1, curve); /* t5 = y1^2 */
  973. uECC_vli_modMult_fast(t4, X1, t5, curve); /* t4 = x1*y1^2 = A */
  974. uECC_vli_modSquare_fast(X1, X1, curve); /* t1 = x1^2 */
  975. uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = y1^4 */
  976. uECC_vli_modMult_fast(Z1, Y1, Z1, curve); /* t3 = y1*z1 = z3 */
  977. uECC_vli_modAdd(Y1, X1, X1, curve->p, num_words_secp256k1); /* t2 = 2*x1^2 */
  978. uECC_vli_modAdd(Y1, Y1, X1, curve->p, num_words_secp256k1); /* t2 = 3*x1^2 */
  979. if (uECC_vli_testBit(Y1, 0)) {
  980. uECC_word_t carry = uECC_vli_add(Y1, Y1, curve->p, num_words_secp256k1);
  981. uECC_vli_rshift1(Y1, num_words_secp256k1);
  982. Y1[num_words_secp256k1 - 1] |= carry << (uECC_WORD_BITS - 1);
  983. } else {
  984. uECC_vli_rshift1(Y1, num_words_secp256k1);
  985. }
  986. /* t2 = 3/2*(x1^2) = B */
  987. uECC_vli_modSquare_fast(X1, Y1, curve); /* t1 = B^2 */
  988. uECC_vli_modSub(X1, X1, t4, curve->p, num_words_secp256k1); /* t1 = B^2 - A */
  989. uECC_vli_modSub(X1, X1, t4, curve->p, num_words_secp256k1); /* t1 = B^2 - 2A = x3 */
  990. uECC_vli_modSub(t4, t4, X1, curve->p, num_words_secp256k1); /* t4 = A - x3 */
  991. uECC_vli_modMult_fast(Y1, Y1, t4, curve); /* t2 = B * (A - x3) */
  992. uECC_vli_modSub(Y1, Y1, t5, curve->p, num_words_secp256k1); /* t2 = B * (A - x3) - y1^4 = y3 */
  993. }
  994. /* Computes result = x^3 + b. result must not overlap x. */
  995. static void x_side_secp256k1(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve) {
  996. uECC_vli_modSquare_fast(result, x, curve); /* r = x^2 */
  997. uECC_vli_modMult_fast(result, result, x, curve); /* r = x^3 */
  998. uECC_vli_modAdd(result, result, curve->b, curve->p, num_words_secp256k1); /* r = x^3 + b */
  999. }
  1000. #if (uECC_OPTIMIZATION_LEVEL > 0 && !asm_mmod_fast_secp256k1)
  1001. static void omega_mult_secp256k1(uECC_word_t *result, const uECC_word_t *right);
  1002. static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) {
  1003. uECC_word_t tmp[2 * num_words_secp256k1];
  1004. uECC_word_t carry;
  1005. uECC_vli_clear(tmp, num_words_secp256k1);
  1006. uECC_vli_clear(tmp + num_words_secp256k1, num_words_secp256k1);
  1007. omega_mult_secp256k1(tmp, product + num_words_secp256k1); /* (Rq, q) = q * c */
  1008. carry = uECC_vli_add(result, product, tmp, num_words_secp256k1); /* (C, r) = r + q */
  1009. uECC_vli_clear(product, num_words_secp256k1);
  1010. omega_mult_secp256k1(product, tmp + num_words_secp256k1); /* Rq*c */
  1011. carry += uECC_vli_add(result, result, product, num_words_secp256k1); /* (C1, r) = r + Rq*c */
  1012. while (carry > 0) {
  1013. --carry;
  1014. uECC_vli_sub(result, result, curve_secp256k1.p, num_words_secp256k1);
  1015. }
  1016. if (uECC_vli_cmp_unsafe(result, curve_secp256k1.p, num_words_secp256k1) > 0) {
  1017. uECC_vli_sub(result, result, curve_secp256k1.p, num_words_secp256k1);
  1018. }
  1019. }
  1020. #if uECC_WORD_SIZE == 1
  1021. static void omega_mult_secp256k1(uint8_t * result, const uint8_t * right) {
  1022. /* Multiply by (2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1). */
  1023. uECC_word_t r0 = 0;
  1024. uECC_word_t r1 = 0;
  1025. uECC_word_t r2 = 0;
  1026. wordcount_t k;
  1027. /* Multiply by (2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1). */
  1028. muladd(0xD1, right[0], &r0, &r1, &r2);
  1029. result[0] = r0;
  1030. r0 = r1;
  1031. r1 = r2;
  1032. /* r2 is still 0 */
  1033. for (k = 1; k < num_words_secp256k1; ++k) {
  1034. muladd(0x03, right[k - 1], &r0, &r1, &r2);
  1035. muladd(0xD1, right[k], &r0, &r1, &r2);
  1036. result[k] = r0;
  1037. r0 = r1;
  1038. r1 = r2;
  1039. r2 = 0;
  1040. }
  1041. muladd(0x03, right[num_words_secp256k1 - 1], &r0, &r1, &r2);
  1042. result[num_words_secp256k1] = r0;
  1043. result[num_words_secp256k1 + 1] = r1;
  1044. /* add the 2^32 multiple */
  1045. result[4 + num_words_secp256k1] =
  1046. uECC_vli_add(result + 4, result + 4, right, num_words_secp256k1);
  1047. }
  1048. #elif uECC_WORD_SIZE == 4
  1049. static void omega_mult_secp256k1(uint32_t * result, const uint32_t * right) {
  1050. /* Multiply by (2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1). */
  1051. uint32_t carry = 0;
  1052. wordcount_t k;
  1053. for (k = 0; k < num_words_secp256k1; ++k) {
  1054. uint64_t p = (uint64_t)0x3D1 * right[k] + carry;
  1055. result[k] = (uint32_t) p;
  1056. carry = p >> 32;
  1057. }
  1058. result[num_words_secp256k1] = carry;
  1059. /* add the 2^32 multiple */
  1060. result[1 + num_words_secp256k1] =
  1061. uECC_vli_add(result + 1, result + 1, right, num_words_secp256k1);
  1062. }
  1063. #else
  1064. static void omega_mult_secp256k1(uint64_t * result, const uint64_t * right) {
  1065. uECC_word_t r0 = 0;
  1066. uECC_word_t r1 = 0;
  1067. uECC_word_t r2 = 0;
  1068. wordcount_t k;
  1069. /* Multiply by (2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1). */
  1070. for (k = 0; k < num_words_secp256k1; ++k) {
  1071. muladd(0x1000003D1ull, right[k], &r0, &r1, &r2);
  1072. result[k] = r0;
  1073. r0 = r1;
  1074. r1 = r2;
  1075. r2 = 0;
  1076. }
  1077. result[num_words_secp256k1] = r0;
  1078. }
  1079. #endif /* uECC_WORD_SIZE */
  1080. #endif /* (uECC_OPTIMIZATION_LEVEL > 0 && && !asm_mmod_fast_secp256k1) */
  1081. #endif /* uECC_SUPPORTS_secp256k1 */
  1082. #endif /* _UECC_CURVE_SPECIFIC_H_ */