1
0

dh.h 8.4 KB

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