dh.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  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. #include "mycrypt.h"
  12. #ifdef MDH
  13. /* max export size we'll encounter (smaller than this but lets round up a bit */
  14. #define DH_BUF_SIZE 1200
  15. /* This holds the key settings. ***MUST*** be organized by size from smallest to largest. */
  16. static const struct {
  17. int size;
  18. char *name, *base, *prime;
  19. } sets[] = {
  20. #ifdef DH768
  21. {
  22. 96,
  23. "DH-768",
  24. "4",
  25. "F///////////////////////////////////////////////////////////"
  26. "////////////////////////////////////////////////////////////"
  27. "//////m3wvV"
  28. },
  29. #endif
  30. #ifdef DH1024
  31. {
  32. 128,
  33. "DH-1024",
  34. "4",
  35. "F///////////////////////////////////////////////////////////"
  36. "////////////////////////////////////////////////////////////"
  37. "////////////////////////////////////////////////m3C47"
  38. },
  39. #endif
  40. #ifdef DH1280
  41. {
  42. 160,
  43. "DH-1280",
  44. "4",
  45. "F///////////////////////////////////////////////////////////"
  46. "////////////////////////////////////////////////////////////"
  47. "////////////////////////////////////////////////////////////"
  48. "//////////////////////////////m4kSN"
  49. },
  50. #endif
  51. #ifdef DH1536
  52. {
  53. 192,
  54. "DH-1536",
  55. "4",
  56. "F///////////////////////////////////////////////////////////"
  57. "////////////////////////////////////////////////////////////"
  58. "////////////////////////////////////////////////////////////"
  59. "////////////////////////////////////////////////////////////"
  60. "////////////m5uqd"
  61. },
  62. #endif
  63. #ifdef DH1792
  64. {
  65. 224,
  66. "DH-1792",
  67. "4",
  68. "F///////////////////////////////////////////////////////////"
  69. "////////////////////////////////////////////////////////////"
  70. "////////////////////////////////////////////////////////////"
  71. "////////////////////////////////////////////////////////////"
  72. "//////////////////////////////////////////////////////mT/sd"
  73. },
  74. #endif
  75. #ifdef DH2048
  76. {
  77. 256,
  78. "DH-2048",
  79. "4",
  80. "3///////////////////////////////////////////////////////////"
  81. "////////////////////////////////////////////////////////////"
  82. "////////////////////////////////////////////////////////////"
  83. "////////////////////////////////////////////////////////////"
  84. "////////////////////////////////////////////////////////////"
  85. "/////////////////////////////////////////m8MPh"
  86. },
  87. #endif
  88. #ifdef DH2560
  89. {
  90. 320,
  91. "DH-2560",
  92. "4",
  93. "3///////////////////////////////////////////////////////////"
  94. "////////////////////////////////////////////////////////////"
  95. "////////////////////////////////////////////////////////////"
  96. "////////////////////////////////////////////////////////////"
  97. "////////////////////////////////////////////////////////////"
  98. "////////////////////////////////////////////////////////////"
  99. "////////////////////////////////////////////////////////////"
  100. "/////mKFpF"
  101. },
  102. #endif
  103. #ifdef DH3072
  104. {
  105. 384,
  106. "DH-3072",
  107. "4",
  108. "3///////////////////////////////////////////////////////////"
  109. "////////////////////////////////////////////////////////////"
  110. "////////////////////////////////////////////////////////////"
  111. "////////////////////////////////////////////////////////////"
  112. "////////////////////////////////////////////////////////////"
  113. "////////////////////////////////////////////////////////////"
  114. "////////////////////////////////////////////////////////////"
  115. "////////////////////////////////////////////////////////////"
  116. "/////////////////////////////m32nN"
  117. },
  118. #endif
  119. #ifdef DH4096
  120. {
  121. 512,
  122. "DH-4096",
  123. "4",
  124. "////////////////////////////////////////////////////////////"
  125. "////////////////////////////////////////////////////////////"
  126. "////////////////////////////////////////////////////////////"
  127. "////////////////////////////////////////////////////////////"
  128. "////////////////////////////////////////////////////////////"
  129. "////////////////////////////////////////////////////////////"
  130. "////////////////////////////////////////////////////////////"
  131. "////////////////////////////////////////////////////////////"
  132. "////////////////////////////////////////////////////////////"
  133. "////////////////////////////////////////////////////////////"
  134. "////////////////////////////////////////////////////////////"
  135. "/////////////////////m8pOF"
  136. },
  137. #endif
  138. {
  139. 0,
  140. NULL,
  141. NULL,
  142. NULL
  143. }
  144. };
  145. static int is_valid_idx(int n)
  146. {
  147. int x;
  148. for (x = 0; sets[x].size; x++);
  149. if ((n < 0) || (n >= x)) {
  150. return 0;
  151. }
  152. return 1;
  153. }
  154. int dh_test(void)
  155. {
  156. mp_int p, g, tmp;
  157. int x, err, primality;
  158. if ((err = mp_init_multi(&p, &g, &tmp, NULL)) != MP_OKAY) { goto error; }
  159. for (x = 0; sets[x].size != 0; x++) {
  160. #if 0
  161. printf("dh_test():testing size %d-bits\n", sets[x].size * 8);
  162. #endif
  163. if ((err = mp_read_radix(&g,(char *)sets[x].base, 64)) != MP_OKAY) { goto error; }
  164. if ((err = mp_read_radix(&p,(char *)sets[x].prime, 64)) != MP_OKAY) { goto error; }
  165. /* ensure p is prime */
  166. if ((err = is_prime(&p, &primality)) != CRYPT_OK) { goto done; }
  167. if (primality == 0) {
  168. err = CRYPT_FAIL_TESTVECTOR;
  169. goto done;
  170. }
  171. if ((err = mp_sub_d(&p, 1, &tmp)) != MP_OKAY) { goto error; }
  172. if ((err = mp_div_2(&tmp, &tmp)) != MP_OKAY) { goto error; }
  173. /* ensure (p-1)/2 is prime */
  174. if ((err = is_prime(&tmp, &primality)) != CRYPT_OK) { goto done; }
  175. if (primality == 0) {
  176. err = CRYPT_FAIL_TESTVECTOR;
  177. goto done;
  178. }
  179. /* now see if g^((p-1)/2) mod p is in fact 1 */
  180. if ((err = mp_exptmod(&g, &tmp, &p, &tmp)) != MP_OKAY) { goto error; }
  181. if (mp_cmp_d(&tmp, 1)) {
  182. err = CRYPT_FAIL_TESTVECTOR;
  183. goto done;
  184. }
  185. }
  186. err = CRYPT_OK;
  187. goto done;
  188. error:
  189. err = mpi_to_ltc_error(err);
  190. done:
  191. mp_clear_multi(&tmp, &g, &p, NULL);
  192. return err;
  193. }
  194. void dh_sizes(int *low, int *high)
  195. {
  196. int x;
  197. _ARGCHK(low != NULL);
  198. _ARGCHK(high != NULL);
  199. *low = INT_MAX;
  200. *high = 0;
  201. for (x = 0; sets[x].size != 0; x++) {
  202. if (*low > sets[x].size) *low = sets[x].size;
  203. if (*high < sets[x].size) *high = sets[x].size;
  204. }
  205. }
  206. int dh_get_size(dh_key *key)
  207. {
  208. _ARGCHK(key != NULL);
  209. if (is_valid_idx(key->idx) == 1) {
  210. return sets[key->idx].size;
  211. } else {
  212. return INT_MAX; /* large value that would cause dh_make_key() to fail */
  213. }
  214. }
  215. int dh_make_key(prng_state *prng, int wprng, int keysize, dh_key *key)
  216. {
  217. unsigned char *buf;
  218. unsigned long x;
  219. mp_int p, g;
  220. int err;
  221. _ARGCHK(key != NULL);
  222. /* good prng? */
  223. if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
  224. return err;
  225. }
  226. /* find key size */
  227. for (x = 0; (keysize > sets[x].size) && (sets[x].size != 0); x++);
  228. #ifdef FAST_PK
  229. keysize = MIN(sets[x].size, 32);
  230. #else
  231. keysize = sets[x].size;
  232. #endif
  233. if (sets[x].size == 0) {
  234. return CRYPT_INVALID_KEYSIZE;
  235. }
  236. key->idx = x;
  237. /* allocate buffer */
  238. buf = XMALLOC(keysize);
  239. if (buf == NULL) {
  240. return CRYPT_MEM;
  241. }
  242. /* make up random string */
  243. if (prng_descriptor[wprng].read(buf, keysize, prng) != (unsigned long)keysize) {
  244. err = CRYPT_ERROR_READPRNG;
  245. goto error2;
  246. }
  247. /* init parameters */
  248. if ((err = mp_init_multi(&g, &p, &key->x, &key->y, NULL)) != MP_OKAY) {
  249. goto error;
  250. }
  251. if ((err = mp_read_radix(&g, sets[key->idx].base, 64)) != MP_OKAY) { goto error; }
  252. if ((err = mp_read_radix(&p, sets[key->idx].prime, 64)) != MP_OKAY) { goto error; }
  253. /* load the x value */
  254. if ((err = mp_read_unsigned_bin(&key->x, buf, keysize)) != MP_OKAY) { goto error; }
  255. if ((err = mp_exptmod(&g, &key->x, &p, &key->y)) != MP_OKAY) { goto error; }
  256. key->type = PK_PRIVATE;
  257. if ((err = mp_shrink(&key->x)) != MP_OKAY) { goto error; }
  258. if ((err = mp_shrink(&key->y)) != MP_OKAY) { goto error; }
  259. /* free up ram */
  260. err = CRYPT_OK;
  261. goto done;
  262. error:
  263. err = mpi_to_ltc_error(err);
  264. error2:
  265. mp_clear_multi(&key->x, &key->y, NULL);
  266. done:
  267. #ifdef CLEAN_STACK
  268. zeromem(buf, keysize);
  269. #endif
  270. mp_clear_multi(&p, &g, NULL);
  271. XFREE(buf);
  272. return err;
  273. }
  274. void dh_free(dh_key *key)
  275. {
  276. _ARGCHK(key != NULL);
  277. mp_clear_multi(&key->x, &key->y, NULL);
  278. }
  279. int dh_export(unsigned char *out, unsigned long *outlen, int type, dh_key *key)
  280. {
  281. unsigned long y, z;
  282. int err;
  283. _ARGCHK(out != NULL);
  284. _ARGCHK(outlen != NULL);
  285. _ARGCHK(key != NULL);
  286. /* can we store the static header? */
  287. if (*outlen < (PACKET_SIZE + 2)) {
  288. return CRYPT_BUFFER_OVERFLOW;
  289. }
  290. if (type == PK_PRIVATE && key->type != PK_PRIVATE) {
  291. return CRYPT_PK_NOT_PRIVATE;
  292. }
  293. /* header */
  294. y = PACKET_SIZE;
  295. /* header */
  296. out[y++] = type;
  297. out[y++] = (unsigned char)(sets[key->idx].size / 8);
  298. /* export y */
  299. OUTPUT_BIGNUM(&key->y, out, y, z);
  300. if (type == PK_PRIVATE) {
  301. /* export x */
  302. OUTPUT_BIGNUM(&key->x, out, y, z);
  303. }
  304. /* store header */
  305. packet_store_header(out, PACKET_SECT_DH, PACKET_SUB_KEY);
  306. /* store len */
  307. *outlen = y;
  308. return CRYPT_OK;
  309. }
  310. int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key)
  311. {
  312. unsigned long x, y, s;
  313. int err;
  314. _ARGCHK(in != NULL);
  315. _ARGCHK(key != NULL);
  316. /* make sure valid length */
  317. if ((2+PACKET_SIZE) > inlen) {
  318. return CRYPT_INVALID_PACKET;
  319. }
  320. /* check type byte */
  321. if ((err = packet_valid_header((unsigned char *)in, PACKET_SECT_DH, PACKET_SUB_KEY)) != CRYPT_OK) {
  322. return err;
  323. }
  324. /* init */
  325. if ((err = mp_init_multi(&key->x, &key->y, NULL)) != MP_OKAY) {
  326. return mpi_to_ltc_error(err);
  327. }
  328. /* advance past packet header */
  329. y = PACKET_SIZE;
  330. /* key type, e.g. private, public */
  331. key->type = (int)in[y++];
  332. /* key size in bytes */
  333. s = (unsigned long)in[y++] * 8;
  334. for (x = 0; (s > (unsigned long)sets[x].size) && (sets[x].size != 0); x++);
  335. if (sets[x].size == 0) {
  336. err = CRYPT_INVALID_KEYSIZE;
  337. goto error;
  338. }
  339. key->idx = (int)x;
  340. /* type check both values */
  341. if ((key->type != PK_PUBLIC) && (key->type != PK_PRIVATE)) {
  342. err = CRYPT_PK_TYPE_MISMATCH;
  343. goto error;
  344. }
  345. /* is the key idx valid? */
  346. if (is_valid_idx(key->idx) != 1) {
  347. err = CRYPT_PK_TYPE_MISMATCH;
  348. goto error;
  349. }
  350. /* load public value g^x mod p*/
  351. INPUT_BIGNUM(&key->y, in, x, y, inlen);
  352. if (key->type == PK_PRIVATE) {
  353. INPUT_BIGNUM(&key->x, in, x, y, inlen);
  354. }
  355. /* eliminate private key if public */
  356. if (key->type == PK_PUBLIC) {
  357. mp_clear(&key->x);
  358. }
  359. return CRYPT_OK;
  360. error:
  361. mp_clear_multi(&key->y, &key->x, NULL);
  362. return err;
  363. }
  364. int dh_shared_secret(dh_key *private_key, dh_key *public_key,
  365. unsigned char *out, unsigned long *outlen)
  366. {
  367. mp_int tmp, p;
  368. unsigned long x;
  369. int err;
  370. _ARGCHK(private_key != NULL);
  371. _ARGCHK(public_key != NULL);
  372. _ARGCHK(out != NULL);
  373. _ARGCHK(outlen != NULL);
  374. /* types valid? */
  375. if (private_key->type != PK_PRIVATE) {
  376. return CRYPT_PK_NOT_PRIVATE;
  377. }
  378. /* same idx? */
  379. if (private_key->idx != public_key->idx) {
  380. return CRYPT_PK_TYPE_MISMATCH;
  381. }
  382. /* compute y^x mod p */
  383. if ((err = mp_init_multi(&tmp, &p, NULL)) != MP_OKAY) {
  384. return mpi_to_ltc_error(err);
  385. }
  386. if ((err = mp_read_radix(&p, (char *)sets[private_key->idx].prime, 64)) != MP_OKAY) { goto error; }
  387. if ((err = mp_exptmod(&public_key->y, &private_key->x, &p, &tmp)) != MP_OKAY) { goto error; }
  388. /* enough space for output? */
  389. x = (unsigned long)mp_unsigned_bin_size(&tmp);
  390. if (*outlen < x) {
  391. err = CRYPT_BUFFER_OVERFLOW;
  392. goto done;
  393. }
  394. if ((err = mp_to_unsigned_bin(&tmp, out)) != MP_OKAY) { goto error; }
  395. *outlen = x;
  396. err = CRYPT_OK;
  397. goto done;
  398. error:
  399. err = mpi_to_ltc_error(err);
  400. done:
  401. mp_clear_multi(&p, &tmp, NULL);
  402. return err;
  403. }
  404. #include "dh_sys.c"
  405. #endif