dh.h 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. /* RTMPDump - Diffie-Hellmann Key Exchange
  2. * Copyright (C) 2009 Andrej Stepanchuk
  3. * Copyright (C) 2009-2010 Howard Chu
  4. *
  5. * This file is part of librtmp.
  6. *
  7. * librtmp is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU Lesser General Public License as
  9. * published by the Free Software Foundation; either version 2.1,
  10. * or (at your option) any later version.
  11. *
  12. * librtmp is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public License
  18. * along with librtmp see the file COPYING. If not, write to
  19. * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  20. * Boston, MA 02110-1301, USA.
  21. * http://www.gnu.org/copyleft/lgpl.html
  22. */
  23. #include <stdint.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <assert.h>
  27. #include <limits.h>
  28. #ifdef USE_POLARSSL
  29. #include <polarssl/dhm.h>
  30. typedef mpi * MP_t;
  31. #define MP_new(m) m = malloc(sizeof(mpi)); mpi_init(m)
  32. #define MP_set_w(mpi, w) mpi_lset(mpi, w)
  33. #define MP_cmp(u, v) mpi_cmp_mpi(u, v)
  34. #define MP_set(u, v) mpi_copy(u, v)
  35. #define MP_sub_w(mpi, w) mpi_sub_int(mpi, mpi, w)
  36. #define MP_cmp_1(mpi) mpi_cmp_int(mpi, 1)
  37. #define MP_modexp(r, y, q, p) mpi_exp_mod(r, y, q, p, NULL)
  38. #define MP_free(mpi) mpi_free(mpi); free(mpi)
  39. #define MP_gethex(u, hex, res) MP_new(u); res = mpi_read_string(u, 16, hex) == 0
  40. #define MP_bytes(u) mpi_size(u)
  41. #define MP_setbin(u,buf,len) mpi_write_binary(u,buf,len)
  42. #define MP_getbin(u,buf,len) MP_new(u); mpi_read_binary(u,buf,len)
  43. typedef struct MDH {
  44. MP_t p;
  45. MP_t g;
  46. MP_t pub_key;
  47. MP_t priv_key;
  48. long length;
  49. dhm_context ctx;
  50. } MDH;
  51. #define MDH_new() calloc(1,sizeof(MDH))
  52. #define MDH_free(vp) {MDH *_dh = vp; dhm_free(&_dh->ctx); MP_free(_dh->p); MP_free(_dh->g); MP_free(_dh->pub_key); MP_free(_dh->priv_key); free(_dh);}
  53. static int MDH_generate_key(MDH *dh)
  54. {
  55. unsigned char out[2];
  56. MP_set(&dh->ctx.P, dh->p);
  57. MP_set(&dh->ctx.G, dh->g);
  58. dh->ctx.len = 128;
  59. dhm_make_public(&dh->ctx, 1024, out, 1, havege_random, &RTMP_TLS_ctx->hs);
  60. MP_new(dh->pub_key);
  61. MP_new(dh->priv_key);
  62. MP_set(dh->pub_key, &dh->ctx.GX);
  63. MP_set(dh->priv_key, &dh->ctx.X);
  64. return 1;
  65. }
  66. static int MDH_compute_key(uint8_t *secret, size_t len, MP_t pub, MDH *dh)
  67. {
  68. MP_set(&dh->ctx.GY, pub);
  69. dhm_calc_secret(&dh->ctx, secret, &len);
  70. return 0;
  71. }
  72. #elif defined(USE_GNUTLS)
  73. #include <gmp.h>
  74. #include <nettle/bignum.h>
  75. #include <gnutls/crypto.h>
  76. typedef mpz_ptr MP_t;
  77. #define MP_new(m) m = malloc(sizeof(*m)); mpz_init2(m, 1)
  78. #define MP_set_w(mpi, w) mpz_set_ui(mpi, w)
  79. #define MP_cmp(u, v) mpz_cmp(u, v)
  80. #define MP_set(u, v) mpz_set(u, v)
  81. #define MP_sub_w(mpi, w) mpz_sub_ui(mpi, mpi, w)
  82. #define MP_cmp_1(mpi) mpz_cmp_ui(mpi, 1)
  83. #define MP_modexp(r, y, q, p) mpz_powm(r, y, q, p)
  84. #define MP_free(mpi) mpz_clear(mpi); free(mpi)
  85. #define MP_gethex(u, hex, res) u = malloc(sizeof(*u)); mpz_init2(u, 1); res = (mpz_set_str(u, hex, 16) == 0)
  86. #define MP_bytes(u) (mpz_sizeinbase(u, 2) + 7) / 8
  87. #define MP_setbin(u,buf,len) nettle_mpz_get_str_256(len,buf,u)
  88. #define MP_getbin(u,buf,len) u = malloc(sizeof(*u)); mpz_init2(u, 1); nettle_mpz_set_str_256_u(u,len,buf)
  89. typedef struct MDH {
  90. MP_t p;
  91. MP_t g;
  92. MP_t pub_key;
  93. MP_t priv_key;
  94. long length;
  95. } MDH;
  96. #define MDH_new() calloc(1,sizeof(MDH))
  97. #define MDH_free(dh) do {MP_free(((MDH*)(dh))->p); MP_free(((MDH*)(dh))->g); MP_free(((MDH*)(dh))->pub_key); MP_free(((MDH*)(dh))->priv_key); free(dh);} while(0)
  98. static int MDH_generate_key(MDH *dh)
  99. {
  100. int num_bytes;
  101. uint32_t seed;
  102. gmp_randstate_t rs;
  103. num_bytes = (mpz_sizeinbase(dh->p, 2) + 7) / 8 - 1;
  104. if (num_bytes <= 0 || num_bytes > 18000)
  105. return 0;
  106. dh->priv_key = calloc(1, sizeof(*dh->priv_key));
  107. if (!dh->priv_key)
  108. return 0;
  109. mpz_init2(dh->priv_key, 1);
  110. gnutls_rnd(GNUTLS_RND_RANDOM, &seed, sizeof(seed));
  111. gmp_randinit_mt(rs);
  112. gmp_randseed_ui(rs, seed);
  113. mpz_urandomb(dh->priv_key, rs, num_bytes);
  114. gmp_randclear(rs);
  115. dh->pub_key = calloc(1, sizeof(*dh->pub_key));
  116. if (!dh->pub_key)
  117. return 0;
  118. mpz_init2(dh->pub_key, 1);
  119. if (!dh->pub_key) {
  120. mpz_clear(dh->priv_key);
  121. free(dh->priv_key);
  122. return 0;
  123. }
  124. mpz_powm(dh->pub_key, dh->g, dh->priv_key, dh->p);
  125. return 1;
  126. }
  127. static int MDH_compute_key(uint8_t *secret, size_t len, MP_t pub, MDH *dh)
  128. {
  129. mpz_ptr k;
  130. int num_bytes;
  131. num_bytes = (mpz_sizeinbase(dh->p, 2) + 7) / 8;
  132. if (num_bytes <= 0 || num_bytes > 18000)
  133. return -1;
  134. k = calloc(1, sizeof(*k));
  135. if (!k)
  136. return -1;
  137. mpz_init2(k, 1);
  138. mpz_powm(k, pub, dh->priv_key, dh->p);
  139. nettle_mpz_get_str_256(len, secret, k);
  140. mpz_clear(k);
  141. free(k);
  142. /* return the length of the shared secret key like DH_compute_key */
  143. return len;
  144. }
  145. #else /* USE_OPENSSL */
  146. #include <openssl/bn.h>
  147. #include <openssl/dh.h>
  148. typedef BIGNUM * MP_t;
  149. #define MP_new(m) m = BN_new()
  150. #define MP_set_w(mpi, w) BN_set_word(mpi, w)
  151. #define MP_cmp(u, v) BN_cmp(u, v)
  152. #define MP_set(u, v) BN_copy(u, v)
  153. #define MP_sub_w(mpi, w) BN_sub_word(mpi, w)
  154. #define MP_cmp_1(mpi) BN_cmp(mpi, BN_value_one())
  155. #define MP_modexp(r, y, q, p) do {BN_CTX *ctx = BN_CTX_new(); BN_mod_exp(r, y, q, p, ctx); BN_CTX_free(ctx);} while(0)
  156. #define MP_free(mpi) BN_free(mpi)
  157. #define MP_gethex(u, hex, res) res = BN_hex2bn(&u, hex)
  158. #define MP_bytes(u) BN_num_bytes(u)
  159. #define MP_setbin(u,buf,len) BN_bn2bin(u,buf)
  160. #define MP_getbin(u,buf,len) u = BN_bin2bn(buf,len,0)
  161. #define MDH DH
  162. #define MDH_new() DH_new()
  163. #define MDH_free(dh) DH_free(dh)
  164. #define MDH_generate_key(dh) DH_generate_key(dh)
  165. #define MDH_compute_key(secret, seclen, pub, dh) DH_compute_key(secret, pub, dh)
  166. #endif
  167. #include "log.h"
  168. #include "dhgroups.h"
  169. /* RFC 2631, Section 2.1.5, http://www.ietf.org/rfc/rfc2631.txt */
  170. static int
  171. isValidPublicKey(MP_t y, MP_t p, MP_t q)
  172. {
  173. int ret = TRUE;
  174. MP_t bn;
  175. assert(y);
  176. MP_new(bn);
  177. assert(bn);
  178. /* y must lie in [2,p-1] */
  179. MP_set_w(bn, 1);
  180. if (MP_cmp(y, bn) < 0)
  181. {
  182. RTMP_Log(RTMP_LOGERROR, "DH public key must be at least 2");
  183. ret = FALSE;
  184. goto failed;
  185. }
  186. /* bn = p-2 */
  187. MP_set(bn, p);
  188. MP_sub_w(bn, 1);
  189. if (MP_cmp(y, bn) > 0)
  190. {
  191. RTMP_Log(RTMP_LOGERROR, "DH public key must be at most p-2");
  192. ret = FALSE;
  193. goto failed;
  194. }
  195. /* Verify with Sophie-Germain prime
  196. *
  197. * This is a nice test to make sure the public key position is calculated
  198. * correctly. This test will fail in about 50% of the cases if applied to
  199. * random data.
  200. */
  201. if (q)
  202. {
  203. /* y must fulfill y^q mod p = 1 */
  204. MP_modexp(bn, y, q, p);
  205. if (MP_cmp_1(bn) != 0)
  206. {
  207. RTMP_Log(RTMP_LOGWARNING, "DH public key does not fulfill y^q mod p = 1");
  208. }
  209. }
  210. failed:
  211. MP_free(bn);
  212. return ret;
  213. }
  214. static MDH *
  215. DHInit(int nKeyBits)
  216. {
  217. size_t res;
  218. MDH *dh = MDH_new();
  219. if (!dh)
  220. goto failed;
  221. MP_new(dh->g);
  222. if (!dh->g)
  223. goto failed;
  224. MP_gethex(dh->p, P1024, res); /* prime P1024, see dhgroups.h */
  225. if (!res)
  226. {
  227. goto failed;
  228. }
  229. MP_set_w(dh->g, 2); /* base 2 */
  230. dh->length = nKeyBits;
  231. return dh;
  232. failed:
  233. if (dh)
  234. MDH_free(dh);
  235. return 0;
  236. }
  237. static int
  238. DHGenerateKey(MDH *dh)
  239. {
  240. size_t res = 0;
  241. if (!dh)
  242. return 0;
  243. while (!res)
  244. {
  245. MP_t q1 = NULL;
  246. if (!MDH_generate_key(dh))
  247. return 0;
  248. MP_gethex(q1, Q1024, res);
  249. assert(res);
  250. res = isValidPublicKey(dh->pub_key, dh->p, q1);
  251. if (!res)
  252. {
  253. MP_free(dh->pub_key);
  254. MP_free(dh->priv_key);
  255. dh->pub_key = dh->priv_key = 0;
  256. }
  257. MP_free(q1);
  258. }
  259. return 1;
  260. }
  261. /* fill pubkey with the public key in BIG ENDIAN order
  262. * 00 00 00 00 00 x1 x2 x3 .....
  263. */
  264. static int
  265. DHGetPublicKey(MDH *dh, uint8_t *pubkey, size_t nPubkeyLen)
  266. {
  267. int len;
  268. if (!dh || !dh->pub_key)
  269. return 0;
  270. len = MP_bytes(dh->pub_key);
  271. if (len <= 0 || len > (int) nPubkeyLen)
  272. return 0;
  273. memset(pubkey, 0, nPubkeyLen);
  274. MP_setbin(dh->pub_key, pubkey + (nPubkeyLen - len), len);
  275. return 1;
  276. }
  277. #if 0 /* unused */
  278. static int
  279. DHGetPrivateKey(MDH *dh, uint8_t *privkey, size_t nPrivkeyLen)
  280. {
  281. if (!dh || !dh->priv_key)
  282. return 0;
  283. int len = MP_bytes(dh->priv_key);
  284. if (len <= 0 || len > (int) nPrivkeyLen)
  285. return 0;
  286. memset(privkey, 0, nPrivkeyLen);
  287. MP_setbin(dh->priv_key, privkey + (nPrivkeyLen - len), len);
  288. return 1;
  289. }
  290. #endif
  291. /* computes the shared secret key from the private MDH value and the
  292. * other party's public key (pubkey)
  293. */
  294. static int
  295. DHComputeSharedSecretKey(MDH *dh, uint8_t *pubkey, size_t nPubkeyLen,
  296. uint8_t *secret)
  297. {
  298. MP_t q1 = NULL, pubkeyBn = NULL;
  299. size_t len;
  300. int res;
  301. if (!dh || !secret || nPubkeyLen >= INT_MAX)
  302. return -1;
  303. MP_getbin(pubkeyBn, pubkey, nPubkeyLen);
  304. if (!pubkeyBn)
  305. return -1;
  306. MP_gethex(q1, Q1024, len);
  307. assert(len);
  308. if (isValidPublicKey(pubkeyBn, dh->p, q1))
  309. res = MDH_compute_key(secret, nPubkeyLen, pubkeyBn, dh);
  310. else
  311. res = -1;
  312. MP_free(q1);
  313. MP_free(pubkeyBn);
  314. return res;
  315. }