ecc.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954
  1. /* LibTomCrypt, modular cryptographic library -- Tom St Denis
  2. *
  3. * LibTomCrypt is a library that provides various cryptographic
  4. * algorithms in a highly modular and flexible manner.
  5. *
  6. * The library is free for all purposes without any express
  7. * guarantee it works.
  8. *
  9. * Tom St Denis, [email protected], http://libtomcrypt.org
  10. */
  11. /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
  12. *
  13. * All curves taken from NIST recommendation paper of July 1999
  14. * Available at http://csrc.nist.gov/cryptval/dss.htm
  15. */
  16. #include "mycrypt.h"
  17. #ifdef MECC
  18. /* size of our temp buffers for exported keys */
  19. #define ECC_BUF_SIZE 160
  20. /* This holds the key settings. ***MUST*** be organized by size from smallest to largest. */
  21. static const struct {
  22. int size;
  23. char *name, *prime, *B, *order, *Gx, *Gy;
  24. } sets[] = {
  25. #ifdef ECC160
  26. {
  27. 20,
  28. "ECC-160",
  29. /* prime */
  30. "G00000000000000000000000007",
  31. /* B */
  32. "1oUV2vOaSlWbxr6",
  33. /* order */
  34. "G0000000000004sCQUtDxaqDUN5",
  35. /* Gx */
  36. "jpqOf1BHus6Yd/pyhyVpP",
  37. /* Gy */
  38. "D/wykuuIFfr+vPyx7kQEPu8MixO",
  39. },
  40. #endif
  41. #ifdef ECC192
  42. {
  43. 24,
  44. "ECC-192",
  45. /* prime */
  46. "/////////////////////l//////////",
  47. /* B */
  48. "P2456UMSWESFf+chSYGmIVwutkp1Hhcn",
  49. /* order */
  50. "////////////////cTxuDXHhoR6qqYWn",
  51. /* Gx */
  52. "68se3h0maFPylo3hGw680FJ/2ls2/n0I",
  53. /* Gy */
  54. "1nahbV/8sdXZ417jQoJDrNFvTw4UUKWH"
  55. },
  56. #endif
  57. #ifdef ECC224
  58. {
  59. 28,
  60. "ECC-224",
  61. /* prime */
  62. "400000000000000000000000000000000000BV",
  63. /* B */
  64. "21HkWGL2CxJIp",
  65. /* order */
  66. "4000000000000000000Kxnixk9t8MLzMiV264/",
  67. /* Gx */
  68. "jpqOf1BHus6Yd/pyhyVpP",
  69. /* Gy */
  70. "3FCtyo2yHA5SFjkCGbYxbOvNeChwS+j6wSIwck",
  71. },
  72. #endif
  73. #ifdef ECC256
  74. {
  75. 32,
  76. "ECC-256",
  77. /* Prime */
  78. "F////y000010000000000000000////////////////",
  79. /* B */
  80. "5h6DTYgEfFdi+kzLNQOXhnb7GQmp5EmzZlEF3udqc1B",
  81. /* Order */
  82. "F////y00000//////////+yvlgjfnUUXFEvoiByOoLH",
  83. /* Gx */
  84. "6iNqVBXB497+BpcvMEaGF9t0ts1BUipeFIXEKNOcCAM",
  85. /* Gy */
  86. "4/ZGkB+6d+RZkVhIdmFdXOhpZDNQp5UpiksG6Wtlr7r"
  87. },
  88. #endif
  89. #ifdef ECC384
  90. {
  91. 48,
  92. "ECC-384",
  93. /* prime */
  94. "//////////////////////////////////////////x/////00000000003/"
  95. "////",
  96. /* B */
  97. "ip4lf+8+v+IOZWLhu/Wj6HWTd6x+WK4I0nG8Zr0JXrh6LZcDYYxHdIg5oEtJ"
  98. "x2hl",
  99. /* Order */
  100. "////////////////////////////////nsDDWVGtBTzO6WsoIB2dUkpi6MhC"
  101. "nIbp",
  102. /* Gx and Gy */
  103. "geVA8hwB1JUEiSSUyo2jT6uTEsABfvkOMVT1u89KAZXL0l9TlrKfR3fKNZXo"
  104. "TWgt",
  105. "DXVUIfOcB6zTdfY/afBSAVZq7RqecXHywTen4xNmkC0AOB7E7Nw1dNf37NoG"
  106. "wWvV"
  107. },
  108. #endif
  109. #ifdef ECC521
  110. {
  111. 65,
  112. "ECC-521",
  113. /* prime */
  114. "V///////////////////////////////////////////////////////////"
  115. "///////////////////////////",
  116. /* B */
  117. "56LFhbXZXoQ7vAQ8Q2sXK3kejfoMvcp5VEuj8cHZl49uLOPEL7iVfDx5bB0l"
  118. "JknlmSrSz+8FImqyUz57zHhK3y0",
  119. /* Order */
  120. "V//////////////////////////////////////////+b66XuE/BvPhVym1I"
  121. "FS9fT0xjScuYPn7hhjljnwHE6G9",
  122. /* Gx and Gy */
  123. "CQ5ZWQt10JfpPu+osOZbRH2d6I1EGK/jI7uAAzWQqqzkg5BNdVlvrae/Xt19"
  124. "wB/gDupIBF1XMf2c/b+VZ72vRrc",
  125. "HWvAMfucZl015oANxGiVHlPcFL4ILURH6WNhxqN9pvcB9VkSfbUz2P0nL2v0"
  126. "J+j1s4rF726edB2G8Y+b7QVqMPG",
  127. },
  128. #endif
  129. {
  130. 0,
  131. NULL, NULL, NULL, NULL, NULL, NULL
  132. }
  133. };
  134. #if 0
  135. /* you plug in a prime and B value and it finds a pseudo-random base point */
  136. void ecc_find_base(void)
  137. {
  138. static char *prime = "26959946667150639794667015087019630673637144422540572481103610249951";
  139. static char *order = "26959946667150639794667015087019637467111563745054605861463538557247";
  140. static char *b = "9538957348957353489587";
  141. mp_int pp, p, r, B, tmp1, tmp2, tx, ty, x, y;
  142. char buf[4096];
  143. int i;
  144. mp_init_multi(&tx, &ty, &x, &y, &p, &pp, &r, &B, &tmp1, &tmp2, NULL);
  145. mp_read_radix(&p, prime, 10);
  146. mp_read_radix(&r, order, 10);
  147. mp_read_radix(&B, b, 10);
  148. /* get (p+1)/4 */
  149. mp_add_d(&p, 1, &pp);
  150. mp_div_2(&pp, &pp);
  151. mp_div_2(&pp, &pp);
  152. buf[0] = 0;
  153. do {
  154. printf("."); fflush(stdout);
  155. /* make a random value of x */
  156. for (i = 0; i < 16; i++) buf[i+1] = rand() & 255;
  157. mp_read_raw(&x, buf, 17);
  158. mp_copy(&x, &tx);
  159. /* now compute x^3 - 3x + b */
  160. mp_expt_d(&x, 3, &tmp1);
  161. mp_mul_d(&x, 3, &tmp2);
  162. mp_sub(&tmp1, &tmp2, &tmp1);
  163. mp_add(&tmp1, &B, &tmp1);
  164. mp_mod(&tmp1, &p, &tmp1);
  165. /* now compute sqrt via x^((p+1)/4) */
  166. mp_exptmod(&tmp1, &pp, &p, &tmp2);
  167. mp_copy(&tmp2, &ty);
  168. /* now square it */
  169. mp_sqrmod(&tmp2, &p, &tmp2);
  170. /* tmp2 should equal tmp1 */
  171. } while (mp_cmp(&tmp1, &tmp2));
  172. /* now output values in way that libtomcrypt wants */
  173. mp_todecimal(&p, buf);
  174. printf("\n\np==%s\n", buf);
  175. mp_tohex(&B, buf);
  176. printf("b==%s\n", buf);
  177. mp_todecimal(&r, buf);
  178. printf("r==%s\n", buf);
  179. mp_tohex(&tx, buf);
  180. printf("Gx==%s\n", buf);
  181. mp_tohex(&ty, buf);
  182. printf("Gy==%s\n", buf);
  183. mp_clear_multi(&tx, &ty, &x, &y, &p, &pp, &r, &B, &tmp1, &tmp2, NULL);
  184. }
  185. #endif
  186. static int is_valid_idx(int n)
  187. {
  188. int x;
  189. for (x = 0; sets[x].size != 0; x++);
  190. if ((n < 0) || (n >= x)) {
  191. return 0;
  192. }
  193. return 1;
  194. }
  195. static ecc_point *new_point(void)
  196. {
  197. ecc_point *p;
  198. p = XMALLOC(sizeof(ecc_point));
  199. if (p == NULL) {
  200. return NULL;
  201. }
  202. if (mp_init_multi(&p->x, &p->y, NULL) != MP_OKAY) {
  203. XFREE(p);
  204. return NULL;
  205. }
  206. return p;
  207. }
  208. static void del_point(ecc_point *p)
  209. {
  210. /* prevents free'ing null arguments */
  211. if (p != NULL) {
  212. mp_clear_multi(&p->x, &p->y, NULL);
  213. XFREE(p);
  214. }
  215. }
  216. /* double a point R = 2P, R can be P*/
  217. static int dbl_point(ecc_point *P, ecc_point *R, mp_int *modulus, mp_int *mu)
  218. {
  219. mp_int s, tmp, tmpx;
  220. int err;
  221. if ((err = mp_init_multi(&s, &tmp, &tmpx, NULL)) != MP_OKAY) {
  222. return mpi_to_ltc_error(err);
  223. }
  224. /* s = (3Xp^2 + a) / (2Yp) */
  225. if ((err = mp_mul_2(&P->y, &tmp)) != MP_OKAY) { goto error; } /* tmp = 2*y */
  226. if ((err = mp_invmod(&tmp, modulus, &tmp)) != MP_OKAY) { goto error; } /* tmp = 1/tmp mod modulus */
  227. if ((err = mp_sqr(&P->x, &s)) != MP_OKAY) { goto error; } /* s = x^2 */
  228. if ((err = mp_reduce(&s, modulus, mu)) != MP_OKAY) { goto error; }
  229. if ((err = mp_mul_d(&s,(mp_digit)3, &s)) != MP_OKAY) { goto error; } /* s = 3*(x^2) */
  230. if ((err = mp_sub_d(&s,(mp_digit)3, &s)) != MP_OKAY) { goto error; } /* s = 3*(x^2) - 3 */
  231. if (mp_cmp_d(&s, 0) == MP_LT) { /* if s < 0 add modulus */
  232. if ((err = mp_add(&s, modulus, &s)) != MP_OKAY) { goto error; }
  233. }
  234. if ((err = mp_mul(&s, &tmp, &s)) != MP_OKAY) { goto error; } /* s = tmp * s mod modulus */
  235. if ((err = mp_reduce(&s, modulus, mu)) != MP_OKAY) { goto error; }
  236. /* Xr = s^2 - 2Xp */
  237. if ((err = mp_sqr(&s, &tmpx)) != MP_OKAY) { goto error; } /* tmpx = s^2 */
  238. if ((err = mp_reduce(&tmpx, modulus, mu)) != MP_OKAY) { goto error; } /* tmpx = tmpx mod modulus */
  239. if ((err = mp_sub(&tmpx, &P->x, &tmpx)) != MP_OKAY) { goto error; } /* tmpx = tmpx - x */
  240. if ((err = mp_submod(&tmpx, &P->x, modulus, &tmpx)) != MP_OKAY) { goto error; } /* tmpx = tmpx - x mod modulus */
  241. /* Yr = -Yp + s(Xp - Xr) */
  242. if ((err = mp_sub(&P->x, &tmpx, &tmp)) != MP_OKAY) { goto error; } /* tmp = x - tmpx */
  243. if ((err = mp_mul(&tmp, &s, &tmp)) != MP_OKAY) { goto error; } /* tmp = tmp * s */
  244. if ((err = mp_submod(&tmp, &P->y, modulus, &R->y)) != MP_OKAY) { goto error; } /* y = tmp - y mod modulus */
  245. if ((err = mp_copy(&tmpx, &R->x)) != MP_OKAY) { goto error; } /* x = tmpx */
  246. err = CRYPT_OK;
  247. goto done;
  248. error:
  249. err = mpi_to_ltc_error(err);
  250. done:
  251. mp_clear_multi(&tmpx, &tmp, &s, NULL);
  252. return err;
  253. }
  254. /* add two different points over Z/pZ, R = P + Q, note R can equal either P or Q */
  255. static int add_point(ecc_point *P, ecc_point *Q, ecc_point *R, mp_int *modulus, mp_int *mu)
  256. {
  257. mp_int s, tmp, tmpx;
  258. int err;
  259. if ((err = mp_init(&tmp)) != MP_OKAY) {
  260. return mpi_to_ltc_error(err);
  261. }
  262. /* is P==Q or P==-Q? */
  263. if (((err = mp_neg(&Q->y, &tmp)) != MP_OKAY) || ((err = mp_mod(&tmp, modulus, &tmp)) != MP_OKAY)) {
  264. mp_clear(&tmp);
  265. return mpi_to_ltc_error(err);
  266. }
  267. if (mp_cmp(&P->x, &Q->x) == MP_EQ)
  268. if (mp_cmp(&P->y, &Q->y) == MP_EQ || mp_cmp(&P->y, &tmp) == MP_EQ) {
  269. mp_clear(&tmp);
  270. return dbl_point(P, R, modulus, mu);
  271. }
  272. if ((err = mp_init_multi(&tmpx, &s, NULL)) != MP_OKAY) {
  273. mp_clear(&tmp);
  274. return mpi_to_ltc_error(err);
  275. }
  276. /* get s = (Yp - Yq)/(Xp-Xq) mod p */
  277. if ((err = mp_sub(&P->x, &Q->x, &tmp)) != MP_OKAY) { goto error; } /* tmp = Px - Qx mod modulus */
  278. if (mp_cmp_d(&tmp, 0) == MP_LT) { /* if tmp<0 add modulus */
  279. if ((err = mp_add(&tmp, modulus, &tmp)) != MP_OKAY) { goto error; }
  280. }
  281. if ((err = mp_invmod(&tmp, modulus, &tmp)) != MP_OKAY) { goto error; } /* tmp = 1/tmp mod modulus */
  282. if ((err = mp_sub(&P->y, &Q->y, &s)) != MP_OKAY) { goto error; } /* s = Py - Qy mod modulus */
  283. if (mp_cmp_d(&s, 0) == MP_LT) { /* if s<0 add modulus */
  284. if ((err = mp_add(&s, modulus, &s)) != MP_OKAY) { goto error; }
  285. }
  286. if ((err = mp_mul(&s, &tmp, &s)) != MP_OKAY) { goto error; } /* s = s * tmp mod modulus */
  287. if ((err = mp_reduce(&s, modulus, mu)) != MP_OKAY) { goto error; }
  288. /* Xr = s^2 - Xp - Xq */
  289. if ((err = mp_sqr(&s, &tmp)) != MP_OKAY) { goto error; } /* tmp = s^2 mod modulus */
  290. if ((err = mp_reduce(&tmp, modulus, mu)) != MP_OKAY) { goto error; }
  291. if ((err = mp_sub(&tmp, &P->x, &tmp)) != MP_OKAY) { goto error; } /* tmp = tmp - Px */
  292. if ((err = mp_sub(&tmp, &Q->x, &tmpx)) != MP_OKAY) { goto error; } /* tmpx = tmp - Qx */
  293. /* Yr = -Yp + s(Xp - Xr) */
  294. if ((err = mp_sub(&P->x, &tmpx, &tmp)) != MP_OKAY) { goto error; } /* tmp = Px - tmpx */
  295. if ((err = mp_mul(&tmp, &s, &tmp)) != MP_OKAY) { goto error; } /* tmp = tmp * s */
  296. if ((err = mp_submod(&tmp, &P->y, modulus, &R->y)) != MP_OKAY) { goto error; } /* Ry = tmp - Py mod modulus */
  297. if ((err = mp_mod(&tmpx, modulus, &R->x)) != MP_OKAY) { goto error; } /* Rx = tmpx mod modulus */
  298. err = CRYPT_OK;
  299. goto done;
  300. error:
  301. err = mpi_to_ltc_error(err);
  302. done:
  303. mp_clear_multi(&s, &tmpx, &tmp, NULL);
  304. return err;
  305. }
  306. /* size of sliding window, don't change this! */
  307. #define WINSIZE 4
  308. /* perform R = kG where k == integer and G == ecc_point */
  309. static int ecc_mulmod(mp_int *k, ecc_point *G, ecc_point *R, mp_int *modulus)
  310. {
  311. ecc_point *tG, *M[8];
  312. int i, j, err;
  313. mp_int mu;
  314. mp_digit buf;
  315. int first, bitbuf, bitcpy, bitcnt, mode, digidx;
  316. /* init barrett reduction */
  317. if ((err = mp_init(&mu)) != MP_OKAY) {
  318. return mpi_to_ltc_error(err);
  319. }
  320. if ((err = mp_reduce_setup(&mu, modulus)) != MP_OKAY) {
  321. mp_clear(&mu);
  322. return mpi_to_ltc_error(err);
  323. }
  324. /* alloc ram for window temps */
  325. for (i = 0; i < 8; i++) {
  326. M[i] = new_point();
  327. if (M[i] == NULL) {
  328. for (j = 0; j < i; j++) {
  329. del_point(M[j]);
  330. }
  331. mp_clear(&mu);
  332. return CRYPT_MEM;
  333. }
  334. }
  335. /* make a copy of G incase R==G */
  336. tG = new_point();
  337. if (tG == NULL) { err = CRYPT_MEM; goto done; }
  338. /* tG = G */
  339. if ((err = mp_copy(&G->x, &tG->x)) != MP_OKAY) { goto error; }
  340. if ((err = mp_copy(&G->y, &tG->y)) != MP_OKAY) { goto error; }
  341. /* calc the M tab, which holds kG for k==8..15 */
  342. /* M[0] == 8G */
  343. if ((err = dbl_point(G, M[0], modulus, &mu)) != CRYPT_OK) { goto done; }
  344. if ((err = dbl_point(M[0], M[0], modulus, &mu)) != CRYPT_OK) { goto done; }
  345. if ((err = dbl_point(M[0], M[0], modulus, &mu)) != CRYPT_OK) { goto done; }
  346. /* now find (8+k)G for k=1..7 */
  347. for (j = 9; j < 16; j++) {
  348. if ((err = add_point(M[j-9], G, M[j-8], modulus, &mu)) != CRYPT_OK) { goto done; }
  349. }
  350. /* setup sliding window */
  351. mode = 0;
  352. bitcnt = 1;
  353. buf = 0;
  354. digidx = k->used - 1;
  355. bitcpy = bitbuf = 0;
  356. first = 1;
  357. /* perform ops */
  358. for (;;) {
  359. /* grab next digit as required */
  360. if (--bitcnt == 0) {
  361. if (digidx == -1) {
  362. break;
  363. }
  364. buf = k->dp[digidx--];
  365. bitcnt = (int) DIGIT_BIT;
  366. }
  367. /* grab the next msb from the multiplicand */
  368. i = (buf >> (DIGIT_BIT - 1)) & 1;
  369. buf <<= 1;
  370. /* skip leading zero bits */
  371. if (mode == 0 && i == 0) {
  372. continue;
  373. }
  374. /* if the bit is zero and mode == 1 then we double */
  375. if (mode == 1 && i == 0) {
  376. if ((err = dbl_point(R, R, modulus, &mu)) != CRYPT_OK) { goto done; }
  377. continue;
  378. }
  379. /* else we add it to the window */
  380. bitbuf |= (i << (WINSIZE - ++bitcpy));
  381. mode = 2;
  382. if (bitcpy == WINSIZE) {
  383. /* if this is the first window we do a simple copy */
  384. if (first == 1) {
  385. /* R = kG [k = first window] */
  386. if ((err = mp_copy(&M[bitbuf-8]->x, &R->x)) != MP_OKAY) { goto error; }
  387. if ((err = mp_copy(&M[bitbuf-8]->y, &R->y)) != MP_OKAY) { goto error; }
  388. first = 0;
  389. } else {
  390. /* normal window */
  391. /* ok window is filled so double as required and add */
  392. /* double first */
  393. for (j = 0; j < WINSIZE; j++) {
  394. if ((err = dbl_point(R, R, modulus, &mu)) != CRYPT_OK) { goto done; }
  395. }
  396. /* then add, bitbuf will be 8..15 [8..2^WINSIZE] guaranteed */
  397. if ((err = add_point(R, M[bitbuf-8], R, modulus, &mu)) != CRYPT_OK) { goto done; }
  398. }
  399. /* empty window and reset */
  400. bitcpy = bitbuf = 0;
  401. mode = 1;
  402. }
  403. }
  404. /* if bits remain then double/add */
  405. if (mode == 2 && bitcpy > 0) {
  406. /* double then add */
  407. for (j = 0; j < bitcpy; j++) {
  408. /* only double if we have had at least one add first */
  409. if (first == 0) {
  410. if ((err = dbl_point(R, R, modulus, &mu)) != CRYPT_OK) { goto done; }
  411. }
  412. bitbuf <<= 1;
  413. if ((bitbuf & (1 << WINSIZE)) != 0) {
  414. if (first == 1){
  415. /* first add, so copy */
  416. if ((err = mp_copy(&tG->x, &R->x)) != MP_OKAY) { goto error; }
  417. if ((err = mp_copy(&tG->y, &R->y)) != MP_OKAY) { goto error; }
  418. first = 0;
  419. } else {
  420. /* then add */
  421. if ((err = add_point(R, tG, R, modulus, &mu)) != CRYPT_OK) { goto done; }
  422. }
  423. }
  424. }
  425. }
  426. err = CRYPT_OK;
  427. goto done;
  428. error:
  429. err = mpi_to_ltc_error(err);
  430. done:
  431. del_point(tG);
  432. for (i = 0; i < 8; i++) {
  433. del_point(M[i]);
  434. }
  435. mp_clear(&mu);
  436. return err;
  437. }
  438. #undef WINSIZE
  439. int ecc_test(void)
  440. {
  441. mp_int modulus, order;
  442. ecc_point *G, *GG;
  443. int i, err, primality;
  444. if ((err = mp_init_multi(&modulus, &order, NULL)) != MP_OKAY) {
  445. return mpi_to_ltc_error(err);
  446. }
  447. G = new_point();
  448. GG = new_point();
  449. if (G == NULL || GG == NULL) {
  450. mp_clear_multi(&modulus, &order, NULL);
  451. del_point(G);
  452. del_point(GG);
  453. return CRYPT_MEM;
  454. }
  455. for (i = 0; sets[i].size; i++) {
  456. #if 0
  457. printf("Testing %d\n", sets[i].size);
  458. #endif
  459. if ((err = mp_read_radix(&modulus, (char *)sets[i].prime, 64)) != MP_OKAY) { goto error; }
  460. if ((err = mp_read_radix(&order, (char *)sets[i].order, 64)) != MP_OKAY) { goto error; }
  461. /* is prime actually prime? */
  462. if ((err = is_prime(&modulus, &primality)) != CRYPT_OK) { goto done; }
  463. if (primality == 0) {
  464. err = CRYPT_FAIL_TESTVECTOR;
  465. goto done;
  466. }
  467. /* is order prime ? */
  468. if ((err = is_prime(&order, &primality)) != CRYPT_OK) { goto done; }
  469. if (primality == 0) {
  470. err = CRYPT_FAIL_TESTVECTOR;
  471. goto done;
  472. }
  473. if ((err = mp_read_radix(&G->x, (char *)sets[i].Gx, 64)) != MP_OKAY) { goto error; }
  474. if ((err = mp_read_radix(&G->y, (char *)sets[i].Gy, 64)) != MP_OKAY) { goto error; }
  475. /* then we should have G == (order + 1)G */
  476. if ((err = mp_add_d(&order, 1, &order)) != MP_OKAY) { goto error; }
  477. if ((err = ecc_mulmod(&order, G, GG, &modulus)) != CRYPT_OK) { goto done; }
  478. if (mp_cmp(&G->x, &GG->x) != 0 || mp_cmp(&G->y, &GG->y) != 0) {
  479. err = CRYPT_FAIL_TESTVECTOR;
  480. goto done;
  481. }
  482. }
  483. err = CRYPT_OK;
  484. goto done;
  485. error:
  486. err = mpi_to_ltc_error(err);
  487. done:
  488. del_point(GG);
  489. del_point(G);
  490. mp_clear_multi(&order, &modulus, NULL);
  491. return err;
  492. }
  493. void ecc_sizes(int *low, int *high)
  494. {
  495. int i;
  496. _ARGCHK(low != NULL);
  497. _ARGCHK(high != NULL);
  498. *low = INT_MAX;
  499. *high = 0;
  500. for (i = 0; sets[i].size != 0; i++) {
  501. if (sets[i].size < *low) {
  502. *low = sets[i].size;
  503. }
  504. if (sets[i].size > *high) {
  505. *high = sets[i].size;
  506. }
  507. }
  508. }
  509. int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key)
  510. {
  511. int x, err;
  512. ecc_point *base;
  513. mp_int prime;
  514. unsigned char *buf;
  515. _ARGCHK(key != NULL);
  516. /* good prng? */
  517. if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
  518. return err;
  519. }
  520. /* find key size */
  521. for (x = 0; (keysize > sets[x].size) && (sets[x].size != 0); x++);
  522. keysize = sets[x].size;
  523. if (sets[x].size == 0) {
  524. return CRYPT_INVALID_KEYSIZE;
  525. }
  526. key->idx = x;
  527. /* allocate ram */
  528. base = NULL;
  529. buf = XMALLOC(128);
  530. if (buf == NULL) {
  531. return CRYPT_MEM;
  532. }
  533. /* make up random string */
  534. if (prng_descriptor[wprng].read(buf, (unsigned long)keysize, prng) != (unsigned long)keysize) {
  535. err = CRYPT_ERROR_READPRNG;
  536. goto __ERR2;
  537. }
  538. /* setup the key variables */
  539. if ((err = mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->k, &prime, NULL)) != MP_OKAY) {
  540. err = mpi_to_ltc_error(err);
  541. goto __ERR;
  542. }
  543. base = new_point();
  544. if (base == NULL) {
  545. mp_clear_multi(&key->pubkey.x, &key->pubkey.y, &key->k, &prime, NULL);
  546. err = CRYPT_MEM;
  547. goto __ERR;
  548. }
  549. /* read in the specs for this key */
  550. if ((err = mp_read_radix(&prime, (char *)sets[key->idx].prime, 64)) != MP_OKAY) { goto error; }
  551. if ((err = mp_read_radix(&base->x, (char *)sets[key->idx].Gx, 64)) != MP_OKAY) { goto error; }
  552. if ((err = mp_read_radix(&base->y, (char *)sets[key->idx].Gy, 64)) != MP_OKAY) { goto error; }
  553. if ((err = mp_read_unsigned_bin(&key->k, (unsigned char *)buf, keysize)) != MP_OKAY) { goto error; }
  554. /* make the public key */
  555. if ((err = ecc_mulmod(&key->k, base, &key->pubkey, &prime)) != CRYPT_OK) { goto __ERR; }
  556. key->type = PK_PRIVATE;
  557. /* shrink key */
  558. if ((err = mp_shrink(&key->k)) != MP_OKAY) { goto error; }
  559. if ((err = mp_shrink(&key->pubkey.x)) != MP_OKAY) { goto error; }
  560. if ((err = mp_shrink(&key->pubkey.y)) != MP_OKAY) { goto error; }
  561. /* free up ram */
  562. err = CRYPT_OK;
  563. goto __ERR;
  564. error:
  565. err = mpi_to_ltc_error(err);
  566. __ERR:
  567. del_point(base);
  568. mp_clear(&prime);
  569. __ERR2:
  570. #ifdef CLEAN_STACK
  571. zeromem(buf, 128);
  572. #endif
  573. XFREE(buf);
  574. return err;
  575. }
  576. void ecc_free(ecc_key *key)
  577. {
  578. _ARGCHK(key != NULL);
  579. mp_clear_multi(&key->pubkey.x, &key->pubkey.y, &key->k, NULL);
  580. }
  581. static int compress_y_point(ecc_point *pt, int idx, int *result)
  582. {
  583. mp_int tmp, tmp2, p;
  584. int err;
  585. _ARGCHK(pt != NULL);
  586. _ARGCHK(result != NULL);
  587. if ((err = mp_init_multi(&tmp, &tmp2, &p, NULL)) != MP_OKAY) {
  588. return mpi_to_ltc_error(err);
  589. }
  590. /* get x^3 - 3x + b */
  591. if ((err = mp_read_radix(&p, (char *)sets[idx].B, 64)) != MP_OKAY) { goto error; } /* p = B */
  592. if ((err = mp_expt_d(&pt->x, 3, &tmp)) != MP_OKAY) { goto error; } /* tmp = pX^3 */
  593. if ((err = mp_mul_d(&pt->x, 3, &tmp2)) != MP_OKAY) { goto error; } /* tmp2 = 3*pX^3 */
  594. if ((err = mp_sub(&tmp, &tmp2, &tmp)) != MP_OKAY) { goto error; } /* tmp = tmp - tmp2 */
  595. if ((err = mp_add(&tmp, &p, &tmp)) != MP_OKAY) { goto error; } /* tmp = tmp + p */
  596. if ((err = mp_read_radix(&p, (char *)sets[idx].prime, 64)) != MP_OKAY) { goto error; } /* p = prime */
  597. if ((err = mp_mod(&tmp, &p, &tmp)) != MP_OKAY) { goto error; } /* tmp = tmp mod p */
  598. /* now find square root */
  599. if ((err = mp_add_d(&p, 1, &tmp2)) != MP_OKAY) { goto error; } /* tmp2 = p + 1 */
  600. if ((err = mp_div_2d(&tmp2, 2, &tmp2, NULL)) != MP_OKAY) { goto error; } /* tmp2 = (p+1)/4 */
  601. if ((err = mp_exptmod(&tmp, &tmp2, &p, &tmp)) != MP_OKAY) { goto error; } /* tmp = (x^3 - 3x + b)^((p+1)/4) mod p */
  602. /* if tmp equals the y point give a 0, otherwise 1 */
  603. if (mp_cmp(&tmp, &pt->y) == 0) {
  604. *result = 0;
  605. } else {
  606. *result = 1;
  607. }
  608. err = CRYPT_OK;
  609. goto done;
  610. error:
  611. err = mpi_to_ltc_error(err);
  612. done:
  613. mp_clear_multi(&p, &tmp, &tmp2, NULL);
  614. return err;
  615. }
  616. static int expand_y_point(ecc_point *pt, int idx, int result)
  617. {
  618. mp_int tmp, tmp2, p;
  619. int err;
  620. _ARGCHK(pt != NULL);
  621. if ((err = mp_init_multi(&tmp, &tmp2, &p, NULL)) != MP_OKAY) {
  622. return CRYPT_MEM;
  623. }
  624. /* get x^3 - 3x + b */
  625. if ((err = mp_read_radix(&p, (char *)sets[idx].B, 64)) != MP_OKAY) { goto error; } /* p = B */
  626. if ((err = mp_expt_d(&pt->x, 3, &tmp)) != MP_OKAY) { goto error; } /* tmp = pX^3 */
  627. if ((err = mp_mul_d(&pt->x, 3, &tmp2)) != MP_OKAY) { goto error; } /* tmp2 = 3*pX^3 */
  628. if ((err = mp_sub(&tmp, &tmp2, &tmp)) != MP_OKAY) { goto error; } /* tmp = tmp - tmp2 */
  629. if ((err = mp_add(&tmp, &p, &tmp)) != MP_OKAY) { goto error; } /* tmp = tmp + p */
  630. if ((err = mp_read_radix(&p, (char *)sets[idx].prime, 64)) != MP_OKAY) { goto error; } /* p = prime */
  631. if ((err = mp_mod(&tmp, &p, &tmp)) != MP_OKAY) { goto error; } /* tmp = tmp mod p */
  632. /* now find square root */
  633. if ((err = mp_add_d(&p, 1, &tmp2)) != MP_OKAY) { goto error; } /* tmp2 = p + 1 */
  634. if ((err = mp_div_2d(&tmp2, 2, &tmp2, NULL)) != MP_OKAY) { goto error; } /* tmp2 = (p+1)/4 */
  635. if ((err = mp_exptmod(&tmp, &tmp2, &p, &tmp)) != MP_OKAY) { goto error; } /* tmp = (x^3 - 3x + b)^((p+1)/4) mod p */
  636. /* if result==0, then y==tmp, otherwise y==p-tmp */
  637. if (result == 0) {
  638. if ((err = mp_copy(&tmp, &pt->y) != MP_OKAY)) { goto error; }
  639. } else {
  640. if ((err = mp_sub(&p, &tmp, &pt->y) != MP_OKAY)) { goto error; }
  641. }
  642. err = CRYPT_OK;
  643. goto done;
  644. error:
  645. err = mpi_to_ltc_error(err);
  646. done:
  647. mp_clear_multi(&p, &tmp, &tmp2, NULL);
  648. return err;
  649. }
  650. int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key)
  651. {
  652. unsigned long y, z;
  653. int cp, err;
  654. _ARGCHK(out != NULL);
  655. _ARGCHK(outlen != NULL);
  656. _ARGCHK(key != NULL);
  657. /* can we store the static header? */
  658. if (*outlen < (PACKET_SIZE + 3)) {
  659. return CRYPT_BUFFER_OVERFLOW;
  660. }
  661. /* type valid? */
  662. if (key->type != PK_PRIVATE && type == PK_PRIVATE) {
  663. return CRYPT_PK_TYPE_MISMATCH;
  664. }
  665. /* output type and magic byte */
  666. y = PACKET_SIZE;
  667. out[y++] = (unsigned char)type;
  668. out[y++] = (unsigned char)sets[key->idx].size;
  669. /* output x coordinate */
  670. OUTPUT_BIGNUM(&(key->pubkey.x), out, y, z);
  671. /* compress y and output it */
  672. if ((err = compress_y_point(&key->pubkey, key->idx, &cp)) != CRYPT_OK) {
  673. return err;
  674. }
  675. out[y++] = (unsigned char)cp;
  676. if (type == PK_PRIVATE) {
  677. OUTPUT_BIGNUM(&key->k, out, y, z);
  678. }
  679. /* store header */
  680. packet_store_header(out, PACKET_SECT_ECC, PACKET_SUB_KEY);
  681. *outlen = y;
  682. return CRYPT_OK;
  683. }
  684. int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key)
  685. {
  686. unsigned long x, y, s;
  687. int err;
  688. _ARGCHK(in != NULL);
  689. _ARGCHK(key != NULL);
  690. /* check length */
  691. if ((3+PACKET_SIZE) > inlen) {
  692. return CRYPT_INVALID_PACKET;
  693. }
  694. /* check type */
  695. if ((err = packet_valid_header((unsigned char *)in, PACKET_SECT_ECC, PACKET_SUB_KEY)) != CRYPT_OK) {
  696. return err;
  697. }
  698. /* init key */
  699. if (mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->k, NULL) != MP_OKAY) {
  700. return CRYPT_MEM;
  701. }
  702. y = PACKET_SIZE;
  703. key->type = (int)in[y++];
  704. s = (unsigned long)in[y++];
  705. for (x = 0; (s > (unsigned long)sets[x].size) && (sets[x].size != 0); x++);
  706. if (sets[x].size == 0) {
  707. err = CRYPT_INVALID_KEYSIZE;
  708. goto error;
  709. }
  710. key->idx = (int)x;
  711. /* type check both values */
  712. if ((key->type != PK_PUBLIC) && (key->type != PK_PRIVATE)) {
  713. err = CRYPT_INVALID_PACKET;
  714. goto error;
  715. }
  716. /* is the key idx valid? */
  717. if (is_valid_idx(key->idx) != 1) {
  718. err = CRYPT_INVALID_PACKET;
  719. goto error;
  720. }
  721. /* load x coordinate */
  722. INPUT_BIGNUM(&key->pubkey.x, in, x, y, inlen);
  723. /* load y */
  724. x = (unsigned long)in[y++];
  725. if ((err = expand_y_point(&key->pubkey, key->idx, (int)x)) != CRYPT_OK) {
  726. goto error;
  727. }
  728. if (key->type == PK_PRIVATE) {
  729. /* load private key */
  730. INPUT_BIGNUM(&key->k, in, x, y, inlen);
  731. }
  732. /* eliminate private key if public */
  733. if (key->type == PK_PUBLIC) {
  734. mp_clear(&key->k);
  735. }
  736. return CRYPT_OK;
  737. error:
  738. mp_clear_multi(&key->pubkey.x, &key->pubkey.y, &key->k, NULL);
  739. return err;
  740. }
  741. int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key,
  742. unsigned char *out, unsigned long *outlen)
  743. {
  744. unsigned long x, y;
  745. ecc_point *result;
  746. mp_int prime;
  747. int err;
  748. _ARGCHK(private_key != NULL);
  749. _ARGCHK(public_key != NULL);
  750. _ARGCHK(out != NULL);
  751. _ARGCHK(outlen != NULL);
  752. /* type valid? */
  753. if (private_key->type != PK_PRIVATE) {
  754. return CRYPT_PK_NOT_PRIVATE;
  755. }
  756. if (private_key->idx != public_key->idx) {
  757. return CRYPT_PK_TYPE_MISMATCH;
  758. }
  759. /* make new point */
  760. result = new_point();
  761. if (result == NULL) {
  762. return CRYPT_MEM;
  763. }
  764. if ((err = mp_init(&prime)) != MP_OKAY) {
  765. del_point(result);
  766. return mpi_to_ltc_error(err);
  767. }
  768. if ((err = mp_read_radix(&prime, (char *)sets[private_key->idx].prime, 64)) != MP_OKAY) { goto error; }
  769. if ((err = ecc_mulmod(&private_key->k, &public_key->pubkey, result, &prime)) != CRYPT_OK) { goto done1; }
  770. x = (unsigned long)mp_unsigned_bin_size(&result->x);
  771. y = (unsigned long)mp_unsigned_bin_size(&result->y);
  772. if (*outlen < (x+y)) {
  773. err = CRYPT_BUFFER_OVERFLOW;
  774. goto done1;
  775. }
  776. *outlen = x+y;
  777. if ((err = mp_to_unsigned_bin(&result->x, out)) != MP_OKAY) { goto error; }
  778. if ((err = mp_to_unsigned_bin(&result->y, out+x)) != MP_OKAY) { goto error; }
  779. err = CRYPT_OK;
  780. goto done1;
  781. error:
  782. err = mpi_to_ltc_error(err);
  783. done1:
  784. mp_clear(&prime);
  785. del_point(result);
  786. return err;
  787. }
  788. int ecc_get_size(ecc_key *key)
  789. {
  790. _ARGCHK(key != NULL);
  791. if (is_valid_idx(key->idx))
  792. return sets[key->idx].size;
  793. else
  794. return INT_MAX; /* large value known to cause it to fail when passed to ecc_make_key() */
  795. }
  796. #include "ecc_sys.c"
  797. #endif