dh.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  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. #if defined(USE_MBEDTLS)
  24. #include <mbedtls/dhm.h>
  25. #include <mbedtls/bignum.h>
  26. typedef mbedtls_mpi* MP_t;
  27. #define MP_new(m) m = malloc(sizeof(mbedtls_mpi)); mbedtls_mpi_init(m)
  28. #define MP_set_w(mpi, w) mbedtls_mpi_lset(mpi, w)
  29. #define MP_cmp(u, v) mbedtls_mpi_cmp_mpi(u, v)
  30. #define MP_set(u, v) mbedtls_mpi_copy(u, v)
  31. #define MP_sub_w(mpi, w) mbedtls_mpi_sub_int(mpi, mpi, w)
  32. #define MP_cmp_1(mpi) mbedtls_mpi_cmp_int(mpi, 1)
  33. #define MP_modexp(r, y, q, p) mbedtls_mpi_exp_mod(r, y, q, p, NULL)
  34. #define MP_free(mpi) mbedtls_mpi_free(mpi); free(mpi)
  35. #define MP_gethex(u, hex, res) MP_new(u); res = mbedtls_mpi_read_string(u, 16, hex) == 0
  36. #define MP_bytes(u) mbedtls_mpi_size(u)
  37. #define MP_setbin(u,buf,len) mbedtls_mpi_write_binary(u,buf,len)
  38. #define MP_getbin(u,buf,len) MP_new(u); mbedtls_mpi_read_binary(u,buf,len)
  39. typedef struct MDH
  40. {
  41. MP_t p;
  42. MP_t g;
  43. MP_t pub_key;
  44. MP_t priv_key;
  45. long length;
  46. mbedtls_dhm_context ctx;
  47. } MDH;
  48. #define MDH_new() calloc(1,sizeof(MDH))
  49. #define MDH_free(vp) {MDH *_dh = vp; mbedtls_dhm_free(&_dh->ctx); MP_free(_dh->p); MP_free(_dh->g); MP_free(_dh->pub_key); MP_free(_dh->priv_key); free(_dh);}
  50. static int MDH_generate_key(MDH *dh)
  51. {
  52. unsigned char out[2];
  53. MP_set(&dh->ctx.P, dh->p);
  54. MP_set(&dh->ctx.G, dh->g);
  55. dh->ctx.len = 128;
  56. mbedtls_dhm_make_public(&dh->ctx, 1024, out, 1, mbedtls_ctr_drbg_random, &RTMP_TLS_ctx->ctr_drbg);
  57. MP_new(dh->pub_key);
  58. MP_new(dh->priv_key);
  59. MP_set(dh->pub_key, &dh->ctx.GX);
  60. MP_set(dh->priv_key, &dh->ctx.X);
  61. return 1;
  62. }
  63. static int MDH_compute_key(uint8_t *secret, size_t len, MP_t pub, MDH *dh)
  64. {
  65. MP_set(&dh->ctx.GY, pub);
  66. size_t olen;
  67. mbedtls_dhm_calc_secret(&dh->ctx, secret, len, &olen, NULL, NULL);
  68. return 0;
  69. }
  70. #elif defined(USE_POLARSSL)
  71. #include <polarssl/dhm.h>
  72. typedef mpi * MP_t;
  73. #define MP_new(m) m = malloc(sizeof(mpi)); mpi_init(m)
  74. #define MP_set_w(mpi, w) mpi_lset(mpi, w)
  75. #define MP_cmp(u, v) mpi_cmp_mpi(u, v)
  76. #define MP_set(u, v) mpi_copy(u, v)
  77. #define MP_sub_w(mpi, w) mpi_sub_int(mpi, mpi, w)
  78. #define MP_cmp_1(mpi) mpi_cmp_int(mpi, 1)
  79. #define MP_modexp(r, y, q, p) mpi_exp_mod(r, y, q, p, NULL)
  80. #define MP_free(mpi) mpi_free(mpi); free(mpi)
  81. #define MP_gethex(u, hex, res) MP_new(u); res = mpi_read_string(u, 16, hex) == 0
  82. #define MP_bytes(u) mpi_size(u)
  83. #define MP_setbin(u,buf,len) mpi_write_binary(u,buf,len)
  84. #define MP_getbin(u,buf,len) MP_new(u); mpi_read_binary(u,buf,len)
  85. typedef struct MDH
  86. {
  87. MP_t p;
  88. MP_t g;
  89. MP_t pub_key;
  90. MP_t priv_key;
  91. long length;
  92. dhm_context ctx;
  93. } MDH;
  94. #define MDH_new() calloc(1,sizeof(MDH))
  95. #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);}
  96. static int MDH_generate_key(MDH *dh)
  97. {
  98. unsigned char out[2];
  99. MP_set(&dh->ctx.P, dh->p);
  100. MP_set(&dh->ctx.G, dh->g);
  101. dh->ctx.len = 128;
  102. dhm_make_public(&dh->ctx, 1024, out, 1, havege_random, &RTMP_TLS_ctx->hs);
  103. MP_new(dh->pub_key);
  104. MP_new(dh->priv_key);
  105. MP_set(dh->pub_key, &dh->ctx.GX);
  106. MP_set(dh->priv_key, &dh->ctx.X);
  107. return 1;
  108. }
  109. static int MDH_compute_key(uint8_t *secret, size_t len, MP_t pub, MDH *dh)
  110. {
  111. MP_set(&dh->ctx.GY, pub);
  112. dhm_calc_secret(&dh->ctx, secret, &len);
  113. return 0;
  114. }
  115. #elif defined(USE_GNUTLS)
  116. #include <gmp.h>
  117. #include <nettle/bignum.h>
  118. typedef mpz_ptr MP_t;
  119. #define MP_new(m) m = malloc(sizeof(*m)); mpz_init2(m, 1)
  120. #define MP_set_w(mpi, w) mpz_set_ui(mpi, w)
  121. #define MP_cmp(u, v) mpz_cmp(u, v)
  122. #define MP_set(u, v) mpz_set(u, v)
  123. #define MP_sub_w(mpi, w) mpz_sub_ui(mpi, mpi, w)
  124. #define MP_cmp_1(mpi) mpz_cmp_ui(mpi, 1)
  125. #define MP_modexp(r, y, q, p) mpz_powm(r, y, q, p)
  126. #define MP_free(mpi) mpz_clear(mpi); free(mpi)
  127. #define MP_gethex(u, hex, res) u = malloc(sizeof(*u)); mpz_init2(u, 1); res = (mpz_set_str(u, hex, 16) == 0)
  128. #define MP_bytes(u) (mpz_sizeinbase(u, 2) + 7) / 8
  129. #define MP_setbin(u,buf,len) nettle_mpz_get_str_256(len,buf,u)
  130. #define MP_getbin(u,buf,len) u = malloc(sizeof(*u)); mpz_init2(u, 1); nettle_mpz_set_str_256_u(u,len,buf)
  131. typedef struct MDH
  132. {
  133. MP_t p;
  134. MP_t g;
  135. MP_t pub_key;
  136. MP_t priv_key;
  137. long length;
  138. } MDH;
  139. #define MDH_new() calloc(1,sizeof(MDH))
  140. #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)
  141. extern MP_t gnutls_calc_dh_secret(MP_t *priv, MP_t g, MP_t p);
  142. extern MP_t gnutls_calc_dh_key(MP_t y, MP_t x, MP_t p);
  143. #define MDH_generate_key(dh) (dh->pub_key = gnutls_calc_dh_secret(&dh->priv_key, dh->g, dh->p))
  144. static int MDH_compute_key(uint8_t *secret, size_t len, MP_t pub, MDH *dh)
  145. {
  146. MP_t sec = gnutls_calc_dh_key(pub, dh->priv_key, dh->p);
  147. if (sec)
  148. {
  149. MP_setbin(sec, secret, len);
  150. MP_free(sec);
  151. return 0;
  152. }
  153. else
  154. return -1;
  155. }
  156. #else /* USE_OPENSSL */
  157. #include <openssl/bn.h>
  158. #include <openssl/dh.h>
  159. typedef BIGNUM * MP_t;
  160. #define MP_new(m) m = BN_new()
  161. #define MP_set_w(mpi, w) BN_set_word(mpi, w)
  162. #define MP_cmp(u, v) BN_cmp(u, v)
  163. #define MP_set(u, v) BN_copy(u, v)
  164. #define MP_sub_w(mpi, w) BN_sub_word(mpi, w)
  165. #define MP_cmp_1(mpi) BN_cmp(mpi, BN_value_one())
  166. #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)
  167. #define MP_free(mpi) BN_free(mpi)
  168. #define MP_gethex(u, hex, res) res = BN_hex2bn(&u, hex)
  169. #define MP_bytes(u) BN_num_bytes(u)
  170. #define MP_setbin(u,buf,len) BN_bn2bin(u,buf)
  171. #define MP_getbin(u,buf,len) u = BN_bin2bn(buf,len,0)
  172. #define MDH DH
  173. #define MDH_new() DH_new()
  174. #define MDH_free(dh) DH_free(dh)
  175. #define MDH_generate_key(dh) DH_generate_key(dh)
  176. #define MDH_compute_key(secret, seclen, pub, dh) DH_compute_key(secret, pub, dh)
  177. #endif
  178. #include "log.h"
  179. #include "dhgroups.h"
  180. /* RFC 2631, Section 2.1.5, http://www.ietf.org/rfc/rfc2631.txt */
  181. static int
  182. isValidPublicKey(MP_t y, MP_t p, MP_t q)
  183. {
  184. int ret = TRUE;
  185. MP_t bn;
  186. assert(y);
  187. MP_new(bn);
  188. assert(bn);
  189. /* y must lie in [2,p-1] */
  190. MP_set_w(bn, 1);
  191. if (MP_cmp(y, bn) < 0)
  192. {
  193. RTMP_Log(RTMP_LOGERROR, "DH public key must be at least 2");
  194. ret = FALSE;
  195. goto failed;
  196. }
  197. /* bn = p-2 */
  198. MP_set(bn, p);
  199. MP_sub_w(bn, 1);
  200. if (MP_cmp(y, bn) > 0)
  201. {
  202. RTMP_Log(RTMP_LOGERROR, "DH public key must be at most p-2");
  203. ret = FALSE;
  204. goto failed;
  205. }
  206. /* Verify with Sophie-Germain prime
  207. *
  208. * This is a nice test to make sure the public key position is calculated
  209. * correctly. This test will fail in about 50% of the cases if applied to
  210. * random data.
  211. */
  212. if (q)
  213. {
  214. /* y must fulfill y^q mod p = 1 */
  215. MP_modexp(bn, y, q, p);
  216. if (MP_cmp_1(bn) != 0)
  217. {
  218. RTMP_Log(RTMP_LOGWARNING, "DH public key does not fulfill y^q mod p = 1");
  219. }
  220. }
  221. failed:
  222. MP_free(bn);
  223. return ret;
  224. }
  225. static MDH *
  226. DHInit(int nKeyBits)
  227. {
  228. size_t res;
  229. MDH *dh = MDH_new();
  230. if (!dh)
  231. goto failed;
  232. MP_new(dh->g);
  233. if (!dh->g)
  234. goto failed;
  235. MP_gethex(dh->p, P1024, res); /* prime P1024, see dhgroups.h */
  236. if (!res)
  237. {
  238. goto failed;
  239. }
  240. MP_set_w(dh->g, 2); /* base 2 */
  241. dh->length = nKeyBits;
  242. return dh;
  243. failed:
  244. if (dh)
  245. MDH_free(dh);
  246. return 0;
  247. }
  248. static int
  249. DHGenerateKey(MDH *dh)
  250. {
  251. size_t res = 0;
  252. if (!dh)
  253. return 0;
  254. while (!res)
  255. {
  256. MP_t q1 = NULL;
  257. if (!MDH_generate_key(dh))
  258. return 0;
  259. MP_gethex(q1, Q1024, res);
  260. assert(res);
  261. res = isValidPublicKey(dh->pub_key, dh->p, q1);
  262. if (!res)
  263. {
  264. MP_free(dh->pub_key);
  265. MP_free(dh->priv_key);
  266. dh->pub_key = dh->priv_key = 0;
  267. }
  268. MP_free(q1);
  269. }
  270. return 1;
  271. }
  272. /* fill pubkey with the public key in BIG ENDIAN order
  273. * 00 00 00 00 00 x1 x2 x3 .....
  274. */
  275. static int
  276. DHGetPublicKey(MDH *dh, uint8_t *pubkey, size_t nPubkeyLen)
  277. {
  278. int len;
  279. if (!dh || !dh->pub_key)
  280. return 0;
  281. len = (int)MP_bytes(dh->pub_key);
  282. if (len <= 0 || len > (int) nPubkeyLen)
  283. return 0;
  284. memset(pubkey, 0, nPubkeyLen);
  285. MP_setbin(dh->pub_key, pubkey + (nPubkeyLen - len), len);
  286. return 1;
  287. }
  288. #if 0 /* unused */
  289. static int
  290. DHGetPrivateKey(MDH *dh, uint8_t *privkey, size_t nPrivkeyLen)
  291. {
  292. if (!dh || !dh->priv_key)
  293. return 0;
  294. int len = MP_bytes(dh->priv_key);
  295. if (len <= 0 || len > (int) nPrivkeyLen)
  296. return 0;
  297. memset(privkey, 0, nPrivkeyLen);
  298. MP_setbin(dh->priv_key, privkey + (nPrivkeyLen - len), len);
  299. return 1;
  300. }
  301. #endif
  302. /* computes the shared secret key from the private MDH value and the
  303. * other party's public key (pubkey)
  304. */
  305. static int
  306. DHComputeSharedSecretKey(MDH *dh, uint8_t *pubkey, size_t nPubkeyLen,
  307. uint8_t *secret)
  308. {
  309. MP_t q1 = NULL, pubkeyBn = NULL;
  310. size_t len;
  311. int res;
  312. if (!dh || !secret || nPubkeyLen >= INT_MAX)
  313. return -1;
  314. MP_getbin(pubkeyBn, pubkey, nPubkeyLen);
  315. if (!pubkeyBn)
  316. return -1;
  317. MP_gethex(q1, Q1024, len);
  318. assert(len);
  319. if (isValidPublicKey(pubkeyBn, dh->p, q1))
  320. res = MDH_compute_key(secret, nPubkeyLen, pubkeyBn, dh);
  321. else
  322. res = -1;
  323. MP_free(q1);
  324. MP_free(pubkeyBn);
  325. return res;
  326. }