dh_sys.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  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 dh_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. dh_key *key)
  15. {
  16. unsigned char *pub_expt, *dh_shared, *skey;
  17. dh_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/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. /* allocate memory */
  35. pub_expt = XMALLOC(DH_BUF_SIZE);
  36. dh_shared = XMALLOC(DH_BUF_SIZE);
  37. skey = XMALLOC(MAXBLOCKSIZE);
  38. if (pub_expt == NULL || dh_shared == NULL || skey == NULL) {
  39. if (pub_expt != NULL) {
  40. XFREE(pub_expt);
  41. }
  42. if (dh_shared != NULL) {
  43. XFREE(dh_shared);
  44. }
  45. if (skey != NULL) {
  46. XFREE(skey);
  47. }
  48. return CRYPT_MEM;
  49. }
  50. /* make a random key and export the public copy */
  51. if ((err = dh_make_key(prng, wprng, dh_get_size(key), &pubkey)) != CRYPT_OK) {
  52. goto __ERR;
  53. }
  54. pubkeysize = DH_BUF_SIZE;
  55. if ((err = dh_export(pub_expt, &pubkeysize, PK_PUBLIC, &pubkey)) != CRYPT_OK) {
  56. dh_free(&pubkey);
  57. goto __ERR;
  58. }
  59. /* now check if the out buffer is big enough */
  60. if (*len < (1 + 4 + 4 + PACKET_SIZE + pubkeysize + keylen)) {
  61. dh_free(&pubkey);
  62. err = CRYPT_BUFFER_OVERFLOW;
  63. goto __ERR;
  64. }
  65. /* make random key */
  66. hashsize = hash_descriptor[hash].hashsize;
  67. x = DH_BUF_SIZE;
  68. if ((err = dh_shared_secret(&pubkey, key, dh_shared, &x)) != CRYPT_OK) {
  69. dh_free(&pubkey);
  70. goto __ERR;
  71. }
  72. dh_free(&pubkey);
  73. z = MAXBLOCKSIZE;
  74. if ((err = hash_memory(hash, dh_shared, x, skey, &z)) != CRYPT_OK) {
  75. goto __ERR;
  76. }
  77. /* store header */
  78. packet_store_header(out, PACKET_SECT_DH, 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 DH 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. /* Store the encrypted key */
  90. STORE32L(keylen, out+y);
  91. y += 4;
  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, DH_BUF_SIZE);
  101. zeromem(dh_shared, DH_BUF_SIZE);
  102. zeromem(skey, MAXBLOCKSIZE);
  103. #endif
  104. XFREE(skey);
  105. XFREE(dh_shared);
  106. XFREE(pub_expt);
  107. return err;
  108. }
  109. int dh_decrypt_key(const unsigned char *in, unsigned long inlen,
  110. unsigned char *outkey, unsigned long *keylen,
  111. dh_key *key)
  112. {
  113. unsigned char *shared_secret, *skey;
  114. unsigned long x, y, z,hashsize, keysize;
  115. int hash, err;
  116. dh_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. /* allocate ram */
  126. shared_secret = XMALLOC(DH_BUF_SIZE);
  127. skey = XMALLOC(MAXBLOCKSIZE);
  128. if (shared_secret == NULL || skey == NULL) {
  129. if (shared_secret != NULL) {
  130. XFREE(shared_secret);
  131. }
  132. if (skey != NULL) {
  133. XFREE(skey);
  134. }
  135. return CRYPT_MEM;
  136. }
  137. /* check if initial header should fit */
  138. if (inlen < PACKET_SIZE+1+4+4) {
  139. err = CRYPT_INVALID_PACKET;
  140. goto __ERR;
  141. } else {
  142. inlen -= PACKET_SIZE+1+4+4;
  143. }
  144. /* is header correct? */
  145. if ((err = packet_valid_header((unsigned char *)in, PACKET_SECT_DH, PACKET_SUB_ENC_KEY)) != CRYPT_OK) {
  146. goto __ERR;
  147. }
  148. /* now lets get the hash name */
  149. y = PACKET_SIZE;
  150. hash = find_hash_id(in[y++]);
  151. if (hash == -1) {
  152. err = CRYPT_INVALID_HASH;
  153. goto __ERR;
  154. }
  155. /* common values */
  156. hashsize = hash_descriptor[hash].hashsize;
  157. /* get public key */
  158. LOAD32L(x, in+y);
  159. /* now check if the imported key will fit */
  160. if (inlen < x) {
  161. err = CRYPT_INVALID_PACKET;
  162. goto __ERR;
  163. } else {
  164. inlen -= x;
  165. }
  166. y += 4;
  167. if ((err = dh_import(in+y, x, &pubkey)) != CRYPT_OK) {
  168. goto __ERR;
  169. }
  170. y += x;
  171. /* make shared key */
  172. x = DH_BUF_SIZE;
  173. if ((err = dh_shared_secret(key, &pubkey, shared_secret, &x)) != CRYPT_OK) {
  174. dh_free(&pubkey);
  175. goto __ERR;
  176. }
  177. dh_free(&pubkey);
  178. z = MAXBLOCKSIZE;
  179. if ((err = hash_memory(hash, shared_secret, x, skey, &z)) != CRYPT_OK) {
  180. goto __ERR;
  181. }
  182. /* load in the encrypted key */
  183. LOAD32L(keysize, in+y);
  184. /* will the outkey fit as part of the input */
  185. if (inlen < keysize) {
  186. err = CRYPT_INVALID_PACKET;
  187. goto __ERR;
  188. } else {
  189. inlen -= keysize;
  190. }
  191. if (keysize > *keylen) {
  192. err = CRYPT_BUFFER_OVERFLOW;
  193. goto __ERR;
  194. }
  195. y += 4;
  196. *keylen = keysize;
  197. for (x = 0; x < keysize; x++, y++) {
  198. outkey[x] = skey[x] ^ in[y];
  199. }
  200. err = CRYPT_OK;
  201. __ERR:
  202. #ifdef CLEAN_STACK
  203. zeromem(shared_secret, DH_BUF_SIZE);
  204. zeromem(skey, MAXBLOCKSIZE);
  205. #endif
  206. XFREE(skey);
  207. XFREE(shared_secret);
  208. return err;
  209. }
  210. /* perform an ElGamal Signature of a hash
  211. *
  212. * The math works as follows. x is the private key, M is the message to sign
  213. 1. pick a random k
  214. 2. compute a = g^k mod p
  215. 3. compute b = (M - xa)/k mod p
  216. 4. Send (a,b)
  217. Now to verify with y=g^x mod p, a and b
  218. 1. compute y^a * a^b = g^(xa) * g^(k*(M-xa)/k)
  219. = g^(xa + (M - xa))
  220. = g^M [all mod p]
  221. 2. Compare against g^M mod p [based on input hash].
  222. 3. If result of #2 == result of #1 then signature valid
  223. */
  224. int dh_sign_hash(const unsigned char *in, unsigned long inlen,
  225. unsigned char *out, unsigned long *outlen,
  226. prng_state *prng, int wprng, dh_key *key)
  227. {
  228. mp_int a, b, k, m, g, p, p1, tmp;
  229. unsigned char *buf;
  230. unsigned long x, y;
  231. int err;
  232. _ARGCHK(in != NULL);
  233. _ARGCHK(out != NULL);
  234. _ARGCHK(outlen != NULL);
  235. _ARGCHK(key != NULL);
  236. /* check parameters */
  237. if (key->type != PK_PRIVATE) {
  238. return CRYPT_PK_NOT_PRIVATE;
  239. }
  240. if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
  241. return err;
  242. }
  243. /* is the IDX valid ? */
  244. if (is_valid_idx(key->idx) != 1) {
  245. return CRYPT_PK_INVALID_TYPE;
  246. }
  247. /* allocate ram for buf */
  248. buf = XMALLOC(520);
  249. /* make up a random value k,
  250. * since the order of the group is prime
  251. * we need not check if gcd(k, r) is 1
  252. */
  253. if (prng_descriptor[wprng].read(buf, sets[key->idx].size, prng) !=
  254. (unsigned long)(sets[key->idx].size)) {
  255. err = CRYPT_ERROR_READPRNG;
  256. goto __ERR;
  257. }
  258. /* init bignums */
  259. if ((err = mp_init_multi(&a, &b, &k, &m, &p, &g, &p1, &tmp, NULL)) != MP_OKAY) {
  260. err = mpi_to_ltc_error(err);
  261. goto __ERR;
  262. }
  263. /* load k and m */
  264. if ((err = mp_read_unsigned_bin(&m, (unsigned char *)in, inlen)) != MP_OKAY) { goto error; }
  265. #ifdef FAST_PK
  266. if ((err = mp_read_unsigned_bin(&k, buf, MIN(32,sets[key->idx].size))) != MP_OKAY) { goto error; }
  267. #else
  268. if ((err = mp_read_unsigned_bin(&k, buf, sets[key->idx].size)) != MP_OKAY) { goto error; }
  269. #endif
  270. /* load g, p and p1 */
  271. if ((err = mp_read_radix(&g, sets[key->idx].base, 64)) != MP_OKAY) { goto error; }
  272. if ((err = mp_read_radix(&p, sets[key->idx].prime, 64)) != MP_OKAY) { goto error; }
  273. if ((err = mp_sub_d(&p, 1, &p1)) != MP_OKAY) { goto error; }
  274. if ((err = mp_div_2(&p1, &p1)) != MP_OKAY) { goto error; } /* p1 = (p-1)/2 */
  275. /* now get a = g^k mod p */
  276. if ((err = mp_exptmod(&g, &k, &p, &a)) != MP_OKAY) { goto error; }
  277. /* now find M = xa + kb mod p1 or just b = (M - xa)/k mod p1 */
  278. if ((err = mp_invmod(&k, &p1, &k)) != MP_OKAY) { goto error; } /* k = 1/k mod p1 */
  279. if ((err = mp_mulmod(&a, &key->x, &p1, &tmp)) != MP_OKAY) { goto error; } /* tmp = xa */
  280. if ((err = mp_submod(&m, &tmp, &p1, &tmp)) != MP_OKAY) { goto error; } /* tmp = M - xa */
  281. if ((err = mp_mulmod(&k, &tmp, &p1, &b)) != MP_OKAY) { goto error; } /* b = (M - xa)/k */
  282. /* check for overflow */
  283. if ((unsigned long)(PACKET_SIZE + 4 + 4 + mp_unsigned_bin_size(&a) + mp_unsigned_bin_size(&b)) > *outlen) {
  284. err = CRYPT_BUFFER_OVERFLOW;
  285. goto __ERR;
  286. }
  287. /* store header */
  288. y = PACKET_SIZE;
  289. /* now store them both (a,b) */
  290. x = (unsigned long)mp_unsigned_bin_size(&a);
  291. STORE32L(x, out+y); y += 4;
  292. if ((err = mp_to_unsigned_bin(&a, out+y)) != MP_OKAY) { goto error; }
  293. y += x;
  294. x = (unsigned long)mp_unsigned_bin_size(&b);
  295. STORE32L(x, out+y); y += 4;
  296. if ((err = mp_to_unsigned_bin(&b, out+y)) != MP_OKAY) { goto error; }
  297. y += x;
  298. /* check if size too big */
  299. if (*outlen < y) {
  300. err = CRYPT_BUFFER_OVERFLOW;
  301. goto __ERR;
  302. }
  303. /* store header */
  304. packet_store_header(out, PACKET_SECT_DH, PACKET_SUB_SIGNED);
  305. *outlen = y;
  306. err = CRYPT_OK;
  307. goto __ERR;
  308. error:
  309. err = mpi_to_ltc_error(err);
  310. __ERR:
  311. mp_clear_multi(&tmp, &p1, &g, &p, &m, &k, &b, &a, NULL);
  312. XFREE(buf);
  313. return err;
  314. }
  315. /* verify the signature in sig of the given hash */
  316. int dh_verify_hash(const unsigned char *sig, unsigned long siglen,
  317. const unsigned char *hash, unsigned long hashlen,
  318. int *stat, dh_key *key)
  319. {
  320. mp_int a, b, p, g, m, tmp;
  321. unsigned long x, y;
  322. int err;
  323. _ARGCHK(sig != NULL);
  324. _ARGCHK(hash != NULL);
  325. _ARGCHK(stat != NULL);
  326. _ARGCHK(key != NULL);
  327. /* default to invalid */
  328. *stat = 0;
  329. /* check initial input length */
  330. if (siglen < PACKET_SIZE+4+4) {
  331. return CRYPT_INVALID_PACKET;
  332. }
  333. /* header ok? */
  334. if ((err = packet_valid_header((unsigned char *)sig, PACKET_SECT_DH, PACKET_SUB_SIGNED)) != CRYPT_OK) {
  335. return err;
  336. }
  337. /* get hash out of packet */
  338. y = PACKET_SIZE;
  339. /* init all bignums */
  340. if ((err = mp_init_multi(&a, &p, &b, &g, &m, &tmp, NULL)) != MP_OKAY) {
  341. return mpi_to_ltc_error(err);
  342. }
  343. /* load a and b */
  344. INPUT_BIGNUM(&a, sig, x, y, siglen);
  345. INPUT_BIGNUM(&b, sig, x, y, siglen);
  346. /* load p and g */
  347. if ((err = mp_read_radix(&p, sets[key->idx].prime, 64)) != MP_OKAY) { goto error1; }
  348. if ((err = mp_read_radix(&g, sets[key->idx].base, 64)) != MP_OKAY) { goto error1; }
  349. /* load m */
  350. if ((err = mp_read_unsigned_bin(&m, (unsigned char *)hash, hashlen)) != MP_OKAY) { goto error1; }
  351. /* find g^m mod p */
  352. if ((err = mp_exptmod(&g, &m, &p, &m)) != MP_OKAY) { goto error1; } /* m = g^m mod p */
  353. /* find y^a * a^b */
  354. if ((err = mp_exptmod(&key->y, &a, &p, &tmp)) != MP_OKAY) { goto error1; } /* tmp = y^a mod p */
  355. if ((err = mp_exptmod(&a, &b, &p, &a)) != MP_OKAY) { goto error1; } /* a = a^b mod p */
  356. if ((err = mp_mulmod(&a, &tmp, &p, &a)) != MP_OKAY) { goto error1; } /* a = y^a * a^b mod p */
  357. /* y^a * a^b == g^m ??? */
  358. if (mp_cmp(&a, &m) == 0) {
  359. *stat = 1;
  360. }
  361. /* clean up */
  362. err = CRYPT_OK;
  363. goto done;
  364. error1:
  365. err = mpi_to_ltc_error(err);
  366. error:
  367. done:
  368. mp_clear_multi(&tmp, &m, &g, &p, &b, &a, NULL);
  369. return err;
  370. }