ecc_sys.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495
  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. int ecc_encrypt_key(const unsigned char *inkey, unsigned long keylen,
  12. unsigned char *out, unsigned long *len,
  13. prng_state *prng, int wprng, int hash,
  14. ecc_key *key)
  15. {
  16. unsigned char *pub_expt, *ecc_shared, *skey;
  17. ecc_key pubkey;
  18. unsigned long x, y, z, hashsize, pubkeysize;
  19. int err;
  20. _ARGCHK(inkey != NULL);
  21. _ARGCHK(out != NULL);
  22. _ARGCHK(len != NULL);
  23. _ARGCHK(key != NULL);
  24. /* check that wprng/cipher/hash are not invalid */
  25. if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
  26. return err;
  27. }
  28. if ((err = hash_is_valid(hash)) != CRYPT_OK) {
  29. return err;
  30. }
  31. if (keylen > hash_descriptor[hash].hashsize) {
  32. return CRYPT_INVALID_HASH;
  33. }
  34. /* make a random key and export the public copy */
  35. if ((err = ecc_make_key(prng, wprng, ecc_get_size(key), &pubkey)) != CRYPT_OK) {
  36. return err;
  37. }
  38. pub_expt = XMALLOC(ECC_BUF_SIZE);
  39. ecc_shared = XMALLOC(ECC_BUF_SIZE);
  40. skey = XMALLOC(MAXBLOCKSIZE);
  41. if (pub_expt == NULL || ecc_shared == NULL || skey == NULL) {
  42. if (pub_expt != NULL) {
  43. XFREE(pub_expt);
  44. }
  45. if (ecc_shared != NULL) {
  46. XFREE(ecc_shared);
  47. }
  48. if (skey != NULL) {
  49. XFREE(skey);
  50. }
  51. ecc_free(&pubkey);
  52. return CRYPT_MEM;
  53. }
  54. pubkeysize = ECC_BUF_SIZE;
  55. if ((err = ecc_export(pub_expt, &pubkeysize, PK_PUBLIC, &pubkey)) != CRYPT_OK) {
  56. ecc_free(&pubkey);
  57. goto __ERR;
  58. }
  59. /* now check if the out buffer is big enough */
  60. if (*len < (9 + PACKET_SIZE + pubkeysize + hash_descriptor[hash].hashsize)) {
  61. ecc_free(&pubkey);
  62. err = CRYPT_BUFFER_OVERFLOW;
  63. goto __ERR;
  64. }
  65. /* make random key */
  66. hashsize = hash_descriptor[hash].hashsize;
  67. x = ECC_BUF_SIZE;
  68. if ((err = ecc_shared_secret(&pubkey, key, ecc_shared, &x)) != CRYPT_OK) {
  69. ecc_free(&pubkey);
  70. goto __ERR;
  71. }
  72. ecc_free(&pubkey);
  73. z = MAXBLOCKSIZE;
  74. if ((err = hash_memory(hash, ecc_shared, x, skey, &z)) != CRYPT_OK) {
  75. goto __ERR;
  76. }
  77. /* store header */
  78. packet_store_header(out, PACKET_SECT_ECC, PACKET_SUB_ENC_KEY);
  79. /* output header */
  80. y = PACKET_SIZE;
  81. /* size of hash name and the name itself */
  82. out[y++] = hash_descriptor[hash].ID;
  83. /* length of ECC pubkey and the key itself */
  84. STORE32L(pubkeysize, out+y);
  85. y += 4;
  86. for (x = 0; x < pubkeysize; x++, y++) {
  87. out[y] = pub_expt[x];
  88. }
  89. STORE32L(keylen, out+y);
  90. y += 4;
  91. /* Encrypt/Store the encrypted key */
  92. for (x = 0; x < keylen; x++, y++) {
  93. out[y] = skey[x] ^ inkey[x];
  94. }
  95. *len = y;
  96. err = CRYPT_OK;
  97. __ERR:
  98. #ifdef CLEAN_STACK
  99. /* clean up */
  100. zeromem(pub_expt, ECC_BUF_SIZE);
  101. zeromem(ecc_shared, ECC_BUF_SIZE);
  102. zeromem(skey, MAXBLOCKSIZE);
  103. #endif
  104. XFREE(skey);
  105. XFREE(ecc_shared);
  106. XFREE(pub_expt);
  107. return err;
  108. }
  109. int ecc_decrypt_key(const unsigned char *in, unsigned long inlen,
  110. unsigned char *outkey, unsigned long *keylen,
  111. ecc_key *key)
  112. {
  113. unsigned char *shared_secret, *skey;
  114. unsigned long x, y, z, hashsize, keysize;
  115. int hash, err;
  116. ecc_key pubkey;
  117. _ARGCHK(in != NULL);
  118. _ARGCHK(outkey != NULL);
  119. _ARGCHK(keylen != NULL);
  120. _ARGCHK(key != NULL);
  121. /* right key type? */
  122. if (key->type != PK_PRIVATE) {
  123. return CRYPT_PK_NOT_PRIVATE;
  124. }
  125. /* correct length ? */
  126. if (inlen < PACKET_SIZE+1+4+4) {
  127. return CRYPT_INVALID_PACKET;
  128. } else {
  129. inlen -= PACKET_SIZE+1+4+4;
  130. }
  131. /* is header correct? */
  132. if ((err = packet_valid_header((unsigned char *)in, PACKET_SECT_ECC, PACKET_SUB_ENC_KEY)) != CRYPT_OK) {
  133. return err;
  134. }
  135. /* now lets get the hash name */
  136. y = PACKET_SIZE;
  137. hash = find_hash_id(in[y++]);
  138. if (hash == -1) {
  139. return CRYPT_INVALID_HASH;
  140. }
  141. /* common values */
  142. hashsize = hash_descriptor[hash].hashsize;
  143. /* get public key */
  144. LOAD32L(x, in+y);
  145. if (inlen < x) {
  146. return CRYPT_INVALID_PACKET;
  147. } else {
  148. inlen -= x;
  149. }
  150. y += 4;
  151. if ((err = ecc_import(in+y, x, &pubkey)) != CRYPT_OK) {
  152. return err;
  153. }
  154. y += x;
  155. /* allocate memory */
  156. shared_secret = XMALLOC(ECC_BUF_SIZE);
  157. skey = XMALLOC(MAXBLOCKSIZE);
  158. if (shared_secret == NULL || skey == NULL) {
  159. if (shared_secret != NULL) {
  160. XFREE(shared_secret);
  161. }
  162. if (skey != NULL) {
  163. XFREE(skey);
  164. }
  165. ecc_free(&pubkey);
  166. return CRYPT_MEM;
  167. }
  168. /* make shared key */
  169. x = ECC_BUF_SIZE;
  170. if ((err = ecc_shared_secret(key, &pubkey, shared_secret, &x)) != CRYPT_OK) {
  171. ecc_free(&pubkey);
  172. goto __ERR;
  173. }
  174. ecc_free(&pubkey);
  175. z = MAXBLOCKSIZE;
  176. if ((err = hash_memory(hash, shared_secret, x, skey, &z)) != CRYPT_OK) {
  177. goto __ERR;
  178. }
  179. LOAD32L(keysize, in+y);
  180. if (inlen < keysize) {
  181. err = CRYPT_INVALID_PACKET;
  182. goto __ERR;
  183. } else {
  184. inlen -= keysize;
  185. }
  186. y += 4;
  187. if (*keylen < keysize) {
  188. err = CRYPT_BUFFER_OVERFLOW;
  189. goto __ERR;
  190. }
  191. /* Decrypt the key */
  192. for (x = 0; x < keysize; x++, y++) {
  193. outkey[x] = skey[x] ^ in[y];
  194. }
  195. *keylen = keysize;
  196. err = CRYPT_OK;
  197. __ERR:
  198. #ifdef CLEAN_STACK
  199. zeromem(shared_secret, ECC_BUF_SIZE);
  200. zeromem(skey, MAXBLOCKSIZE);
  201. #endif
  202. XFREE(skey);
  203. XFREE(shared_secret);
  204. return err;
  205. }
  206. int ecc_sign_hash(const unsigned char *in, unsigned long inlen,
  207. unsigned char *out, unsigned long *outlen,
  208. prng_state *prng, int wprng, ecc_key *key)
  209. {
  210. ecc_key pubkey;
  211. mp_int b, p;
  212. unsigned char *epubkey, *er;
  213. unsigned long x, y, pubkeysize, rsize;
  214. int err;
  215. _ARGCHK(in != NULL);
  216. _ARGCHK(out != NULL);
  217. _ARGCHK(outlen != NULL);
  218. _ARGCHK(key != NULL);
  219. /* is this a private key? */
  220. if (key->type != PK_PRIVATE) {
  221. return CRYPT_PK_NOT_PRIVATE;
  222. }
  223. /* is the IDX valid ? */
  224. if (is_valid_idx(key->idx) != 1) {
  225. return CRYPT_PK_INVALID_TYPE;
  226. }
  227. if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
  228. return err;
  229. }
  230. /* make up a key and export the public copy */
  231. if ((err = ecc_make_key(prng, wprng, ecc_get_size(key), &pubkey)) != CRYPT_OK) {
  232. return err;
  233. }
  234. /* allocate ram */
  235. epubkey = XMALLOC(ECC_BUF_SIZE);
  236. er = XMALLOC(ECC_BUF_SIZE);
  237. if (epubkey == NULL || er == NULL) {
  238. if (epubkey != NULL) {
  239. XFREE(epubkey);
  240. }
  241. if (er != NULL) {
  242. XFREE(er);
  243. }
  244. ecc_free(&pubkey);
  245. return CRYPT_MEM;
  246. }
  247. pubkeysize = ECC_BUF_SIZE;
  248. if ((err = ecc_export(epubkey, &pubkeysize, PK_PUBLIC, &pubkey)) != CRYPT_OK) {
  249. ecc_free(&pubkey);
  250. goto __ERR;
  251. }
  252. /* get the hash and load it as a bignum into 'b' */
  253. /* init the bignums */
  254. if ((err = mp_init_multi(&b, &p, NULL)) != MP_OKAY) {
  255. ecc_free(&pubkey);
  256. err = mpi_to_ltc_error(err);
  257. goto __ERR;
  258. }
  259. if ((err = mp_read_radix(&p, (char *)sets[key->idx].order, 64)) != MP_OKAY) { goto error; }
  260. if ((err = mp_read_unsigned_bin(&b, (unsigned char *)in, (int)inlen)) != MP_OKAY) { goto error; }
  261. /* find b = (m - x)/k */
  262. if ((err = mp_invmod(&pubkey.k, &p, &pubkey.k)) != MP_OKAY) { goto error; } /* k = 1/k */
  263. if ((err = mp_submod(&b, &key->k, &p, &b)) != MP_OKAY) { goto error; } /* b = m - x */
  264. if ((err = mp_mulmod(&b, &pubkey.k, &p, &b)) != MP_OKAY) { goto error; } /* b = (m - x)/k */
  265. /* export it */
  266. rsize = (unsigned long)mp_unsigned_bin_size(&b);
  267. if (rsize > ECC_BUF_SIZE) {
  268. err = CRYPT_BUFFER_OVERFLOW;
  269. goto error;
  270. }
  271. if ((err = mp_to_unsigned_bin(&b, er)) != MP_OKAY) { goto error; }
  272. /* now lets check the outlen before we write */
  273. if (*outlen < (12 + rsize + pubkeysize)) {
  274. err = CRYPT_BUFFER_OVERFLOW;
  275. goto __ERR;
  276. }
  277. /* lets output */
  278. y = PACKET_SIZE;
  279. /* size of public key */
  280. STORE32L(pubkeysize, out+y);
  281. y += 4;
  282. /* copy the public key */
  283. for (x = 0; x < pubkeysize; x++, y++) {
  284. out[y] = epubkey[x];
  285. }
  286. /* size of 'r' */
  287. STORE32L(rsize, out+y);
  288. y += 4;
  289. /* copy r */
  290. for (x = 0; x < rsize; x++, y++) {
  291. out[y] = er[x];
  292. }
  293. /* store header */
  294. packet_store_header(out, PACKET_SECT_ECC, PACKET_SUB_SIGNED);
  295. *outlen = y;
  296. /* all ok */
  297. err = CRYPT_OK;
  298. goto __ERR;
  299. error:
  300. err = mpi_to_ltc_error(err);
  301. __ERR:
  302. mp_clear_multi(&b, &p, NULL);
  303. ecc_free(&pubkey);
  304. #ifdef CLEAN_STACK
  305. zeromem(er, ECC_BUF_SIZE);
  306. zeromem(epubkey, ECC_BUF_SIZE);
  307. #endif
  308. XFREE(epubkey);
  309. XFREE(er);
  310. return err;
  311. }
  312. /* verify that mG = (bA + Y)
  313. *
  314. * The signatures work by making up a fresh key "a" with a public key "A". Now we want to sign so the
  315. * public key Y = xG can verify it.
  316. *
  317. * b = (m - x)/k, A is the public key embedded and Y is the users public key [who signed it]
  318. * A = kG therefore bA == ((m-x)/k)kG == (m-x)G
  319. *
  320. * Adding Y = xG to the bA gives us (m-x)G + xG == mG
  321. *
  322. * The user given only xG, kG and b cannot determine k or x which means they can't find the private key.
  323. *
  324. */
  325. int ecc_verify_hash(const unsigned char *sig, unsigned long siglen,
  326. const unsigned char *hash, unsigned long inlen,
  327. int *stat, ecc_key *key)
  328. {
  329. ecc_point *mG;
  330. ecc_key pubkey;
  331. mp_int b, p, m, mu;
  332. unsigned long x, y;
  333. int err;
  334. _ARGCHK(sig != NULL);
  335. _ARGCHK(hash != NULL);
  336. _ARGCHK(stat != NULL);
  337. _ARGCHK(key != NULL);
  338. /* default to invalid signature */
  339. *stat = 0;
  340. if (siglen < PACKET_SIZE+4+4) {
  341. return CRYPT_INVALID_PACKET;
  342. } else {
  343. siglen -= PACKET_SIZE+4+4;
  344. }
  345. /* is the message format correct? */
  346. if ((err = packet_valid_header((unsigned char *)sig, PACKET_SECT_ECC, PACKET_SUB_SIGNED)) != CRYPT_OK) {
  347. return err;
  348. }
  349. /* get hash name */
  350. y = PACKET_SIZE;
  351. /* get size of public key */
  352. LOAD32L(x, sig+y);
  353. if (siglen < x) {
  354. return CRYPT_INVALID_PACKET;
  355. } else {
  356. siglen -= x;
  357. }
  358. y += 4;
  359. /* load the public key */
  360. if ((err = ecc_import((unsigned char*)sig+y, x, &pubkey)) != CRYPT_OK) {
  361. return err;
  362. }
  363. y += x;
  364. /* load size of 'b' */
  365. LOAD32L(x, sig+y);
  366. if (siglen < x) {
  367. return CRYPT_INVALID_PACKET;
  368. } else {
  369. siglen -= x;
  370. }
  371. y += 4;
  372. /* init values */
  373. if ((err = mp_init_multi(&b, &m, &p, &mu, NULL)) != MP_OKAY) {
  374. ecc_free(&pubkey);
  375. return mpi_to_ltc_error(err);
  376. }
  377. mG = new_point();
  378. if (mG == NULL) {
  379. mp_clear_multi(&b, &m, &p, &mu, NULL);
  380. ecc_free(&pubkey);
  381. return CRYPT_MEM;
  382. }
  383. /* load b */
  384. if ((err = mp_read_unsigned_bin(&b, (unsigned char *)sig+y, (int)x)) != MP_OKAY) { goto error; }
  385. y += x;
  386. /* get m in binary a bignum */
  387. if ((err = mp_read_unsigned_bin(&m, (unsigned char *)hash, (int)inlen)) != MP_OKAY) { goto error; }
  388. /* load prime */
  389. if ((err = mp_read_radix(&p, (char *)sets[key->idx].prime, 64)) != MP_OKAY) { goto error; }
  390. /* calculate barrett stuff */
  391. mp_set(&mu, 1);
  392. mp_lshd(&mu, 2 * USED(&p));
  393. if ((err = mp_div(&mu, &p, &mu, NULL)) != MP_OKAY) { goto error; }
  394. /* get bA */
  395. if ((err = ecc_mulmod(&b, &pubkey.pubkey, &pubkey.pubkey, &p)) != CRYPT_OK) { goto done; }
  396. /* get bA + Y */
  397. if ((err = add_point(&pubkey.pubkey, &key->pubkey, &pubkey.pubkey, &p, &mu)) != CRYPT_OK) { goto done; }
  398. /* get mG */
  399. if ((err = mp_read_radix(&mG->x, (char *)sets[key->idx].Gx, 64)) != MP_OKAY) { goto error; }
  400. if ((err = mp_read_radix(&mG->y, (char *)sets[key->idx].Gy, 64)) != MP_OKAY) { goto error; }
  401. if ((err = ecc_mulmod(&m, mG, mG, &p)) != CRYPT_OK) { goto done; }
  402. /* compare mG to bA + Y */
  403. if (mp_cmp(&mG->x, &pubkey.pubkey.x) == MP_EQ && mp_cmp(&mG->y, &pubkey.pubkey.y) == MP_EQ) {
  404. *stat = 1;
  405. }
  406. /* clear up and return */
  407. err = CRYPT_OK;
  408. goto done;
  409. error:
  410. err = mpi_to_ltc_error(err);
  411. done:
  412. del_point(mG);
  413. ecc_free(&pubkey);
  414. mp_clear_multi(&p, &m, &b, &mu, NULL);
  415. return err;
  416. }