From: hyc Date: Wed, 17 Mar 2010 07:09:28 +0000 (+0000) Subject: Add GnuTLS/Gcrypt support for DH key exchange X-Git-Tag: v2.4~175 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=00ae52c74f9e8ca781a8dbb12b5b0bfd5a8a89d1;p=rtmpdump Add GnuTLS/Gcrypt support for DH key exchange git-svn-id: svn://svn.mplayerhq.hu/rtmpdump/trunk@363 400ebc74-4327-4243-bc38-086b20814532 --- diff --git a/librtmp/dh.h b/librtmp/dh.h index 84f8ed5..0ffd9a7 100644 --- a/librtmp/dh.h +++ b/librtmp/dh.h @@ -26,6 +26,52 @@ #include #include +#ifdef USE_GNUTLS +#include +typedef gcry_mpi_t MP_t; +#define MP_new() gcry_mpi_new(1) +#define MP_set_w(mpi, w) gcry_mpi_set_ui(mpi, w) +#define MP_cmp(u, v) gcry_mpi_cmp(u, v) +#define MP_set(u, v) gcry_mpi_set(u, v) +#define MP_sub_w(mpi, w) gcry_mpi_sub_ui(mpi, mpi, w) +#define MP_cmp_1(mpi) gcry_mpi_cmp_ui(mpi, 1) +#define MP_modexp(r, y, q, p) gcry_mpi_powm(r, y, q, p) +#define MP_free(mpi) gcry_mpi_release(mpi) +#define MP_gethex(u, hex, res) res = (gcry_mpi_scan(u, GCRYMPI_FMT_HEX, hex, 0, 0) == 0) +#define MP_bytes(u) (gcry_mpi_get_nbits(u) + 7) / 8 +#define MP_setbin(u,buf,len) gcry_mpi_print(GCRYMPI_FMT_USG,buf,len,NULL,u) +#define MP_getbin(u,buf,len) gcry_mpi_scan(&u,GCRYMPI_FMT_USG,buf,len,NULL) + +typedef struct MDH { + MP_t p; + MP_t g; + MP_t pub_key; + MP_t priv_key; + long length; +} MDH; + +#define MDH_new() calloc(1,sizeof(MDH)) +#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) + +extern MP_t gnutls_calc_dh_secret(MP_t *priv, MP_t g, MP_t p); +extern MP_t gnutls_calc_dh_key(MP_t y, MP_t x, MP_t p); + + +#define MDH_generate_key(dh) (dh->pub_key = gnutls_calc_dh_secret(&dh->priv_key, dh->g, dh->p)) +static int MDH_compute_key(uint8_t *secret, size_t len, MP_t pub, MDH *dh) +{ + MP_t sec = gnutls_calc_dh_key(pub, dh->priv_key, dh->p); + if (sec) + { + MP_setbin(sec, secret, len); + MP_free(sec); + return 0; + } + else + return -1; +} + +#else #include #include @@ -33,43 +79,65 @@ #include #include +typedef BIGNUM * MP_t; +#define MP_new() BN_new() +#define MP_set_w(mpi, w) BN_set_word(mpi, w) +#define MP_cmp(u, v) BN_cmp(u, v) +#define MP_set(u, v) BN_copy(u, v) +#define MP_sub_w(mpi, w) BN_sub_word(mpi, w) +#define MP_cmp_1(mpi) BN_cmp(mpi, BN_value_one()) +#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) +#define MP_free(mpi) BN_free(mpi) +#define MP_gethex(u, hex, res) res = BN_hex2bn(u, hex) +#define MP_bytes(u) BN_num_bytes(u) +#define MP_setbin(u,buf,len) BN_bn2bin(u,buf) +#define MP_getbin(u,buf,len) u = BN_bin2bn(buf,len,0) + +#define MDH DH +#define MDH_new() DH_new() +#define MDH_free(dh) DH_free(dh) +#define MDH_generate_key(dh) DH_generate_key(dh) +#define MDH_compute_key(secret, seclen, pub, dh) DH_compute_key(secret, pub, dh) + +#endif + #include "log.h" #include "dhgroups.h" /* -BIGNUM *dh_shared_p = 0; // shared prime -BIGNUM *dh_shared_g = 0; // shared base +MP_t dh_shared_p = 0; // shared prime +MP_t dh_shared_g = 0; // shared base void dh_pg_init() { + int res; if(dh_shared_p || dh_shared_g) return; - dh_shared_p = BN_new(); - dh_shared_g = BN_new(); + dh_shared_p = MP_new(); + dh_shared_g = MP_new(); assert(dh_shared_p && dh_shared_g); - int res = BN_hex2bn(&dh_shared_p, P1024); // prime P1024, see dhgroups.h + MP_gethex(&dh_shared_p, P1024, res); // prime P1024, see dhgroups.h assert(res); - res = BN_set_word(dh_shared_g, 2); // base 2 - assert(res); + assert(MP_set_w(dh_shared_g, 2)); // base 2 } */ // RFC 2631, Section 2.1.5, http://www.ietf.org/rfc/rfc2631.txt static bool -isValidPublicKey(BIGNUM * y, BIGNUM * p, BIGNUM * q) +isValidPublicKey(MP_t y, MP_t p, MP_t q) { int ret = true; assert(y); - BIGNUM *bn = BN_new(); + MP_t bn = MP_new(); assert(bn); // y must lie in [2,p-1] - BN_set_word(bn, 1); - if (BN_cmp(y, bn) < 0) + MP_set_w(bn, 1); + if (MP_cmp(y, bn) < 0) { Log(LOGWARNING, "DH public key must be at least 2"); ret = false; @@ -77,9 +145,9 @@ isValidPublicKey(BIGNUM * y, BIGNUM * p, BIGNUM * q) } // bn = p-2 - BN_copy(bn, p); - BN_sub_word(bn, 1); - if (BN_cmp(y, bn) > 0) + MP_set(bn, p); + MP_sub_w(bn, 1); + if (MP_cmp(y, bn) > 0) { Log(LOGWARNING, "DH public key must be at most p-2"); ret = false; @@ -95,44 +163,40 @@ isValidPublicKey(BIGNUM * y, BIGNUM * p, BIGNUM * q) if (q) { // y must fulfill y^q mod p = 1 - BN_CTX *ctx = BN_CTX_new(); - BN_mod_exp(bn, y, q, p, ctx); + MP_modexp(bn, y, q, p); - if (BN_cmp(bn, BN_value_one()) != 0) + if (MP_cmp_1(bn) != 0) { Log(LOGWARNING, "DH public key does not fulfill y^q mod p = 1"); } - BN_CTX_free(ctx); } failed: - BN_free(bn); + MP_free(bn); return ret; } -static DH * +static MDH * DHInit(int nKeyBits) { - int res; - DH *dh = DH_new(); + size_t res; + MDH *dh = MDH_new(); if (!dh) goto failed; - dh->p = BN_new(); - dh->g = BN_new(); + dh->g = MP_new(); - if (!dh->p || !dh->g) + if (!dh->g) goto failed; - res = BN_hex2bn(&dh->p, P1024); // prime P1024, see dhgroups.h + MP_gethex(&dh->p, P1024, res); // prime P1024, see dhgroups.h if (!res) { goto failed; } - res = BN_set_word(dh->g, 2); // base 2 - if (!res) + if (!MP_set_w(dh->g, 2)) // base 2 { goto failed; } @@ -142,35 +206,36 @@ DHInit(int nKeyBits) failed: if (dh) - DH_free(dh); + MDH_free(dh); return 0; } static int -DHGenerateKey(DH * dh) +DHGenerateKey(MDH *dh) { if (!dh) return 0; - int res = 0; + size_t res = 0; while (!res) { - if (!DH_generate_key(dh)) + if (!MDH_generate_key(dh)) return 0; - BIGNUM *q1 = BN_new(); - assert(BN_hex2bn(&q1, Q1024)); + MP_t q1; + MP_gethex(&q1, Q1024, res); + assert(res); res = isValidPublicKey(dh->pub_key, dh->p, q1); if (!res) { - BN_free(dh->pub_key); - BN_free(dh->priv_key); + MP_free(dh->pub_key); + MP_free(dh->priv_key); dh->pub_key = dh->priv_key = 0; } - BN_free(q1); + MP_free(q1); } return 1; } @@ -179,63 +244,63 @@ DHGenerateKey(DH * dh) // 00 00 00 00 00 x1 x2 x3 ..... static int -DHGetPublicKey(DH * dh, uint8_t * pubkey, size_t nPubkeyLen) +DHGetPublicKey(MDH *dh, uint8_t *pubkey, size_t nPubkeyLen) { if (!dh || !dh->pub_key) return 0; - int len = BN_num_bytes(dh->pub_key); + int len = MP_bytes(dh->pub_key); if (len <= 0 || len > (int) nPubkeyLen) return 0; memset(pubkey, 0, nPubkeyLen); - BN_bn2bin(dh->pub_key, pubkey + (nPubkeyLen - len)); + MP_setbin(dh->pub_key, pubkey + (nPubkeyLen - len), len); return 1; } #if 0 /* unused */ static int -DHGetPrivateKey(DH * dh, uint8_t * privkey, size_t nPrivkeyLen) +DHGetPrivateKey(MDH *dh, uint8_t *privkey, size_t nPrivkeyLen) { if (!dh || !dh->priv_key) return 0; - int len = BN_num_bytes(dh->priv_key); + int len = MP_bytes(dh->priv_key); if (len <= 0 || len > (int) nPrivkeyLen) return 0; memset(privkey, 0, nPrivkeyLen); - BN_bn2bin(dh->priv_key, privkey + (nPrivkeyLen - len)); + MP_setbin(dh->priv_key, privkey + (nPrivkeyLen - len), len); return 1; } #endif -// computes the shared secret key from the private DH value and the othe parties public key (pubkey) +// computes the shared secret key from the private MDH value and the othe parties public key (pubkey) static int -DHComputeSharedSecretKey(DH * dh, uint8_t * pubkey, size_t nPubkeyLen, - uint8_t * secret) +DHComputeSharedSecretKey(MDH *dh, uint8_t *pubkey, size_t nPubkeyLen, + uint8_t *secret) { + MP_t q1, pubkeyBn = NULL; + size_t len; + int res; + if (!dh || !secret || nPubkeyLen >= INT_MAX) return -1; - BIGNUM *pubkeyBn = BN_bin2bn(pubkey, nPubkeyLen, 0); + MP_getbin(pubkeyBn, pubkey, nPubkeyLen); if (!pubkeyBn) return -1; - BIGNUM *q1 = BN_new(); - assert(BN_hex2bn(&q1, Q1024)); - - if (!isValidPublicKey(pubkeyBn, dh->p, q1)) - { - BN_free(pubkeyBn); - BN_free(q1); - return -1; - } + MP_gethex(&q1, Q1024, len); + assert(len); - BN_free(q1); + if (isValidPublicKey(pubkeyBn, dh->p, q1)) + res = MDH_compute_key(secret, nPubkeyLen, pubkeyBn, dh); + else + res = -1; - size_t len = DH_compute_key(secret, pubkeyBn, dh); - BN_free(pubkeyBn); + MP_free(q1); + MP_free(pubkeyBn); - return len; + return res; } diff --git a/librtmp/rtmp.c b/librtmp/rtmp.c index 9632314..f817c5c 100644 --- a/librtmp/rtmp.c +++ b/librtmp/rtmp.c @@ -30,11 +30,14 @@ #include "rtmp_sys.h" #include "log.h" -#include - #ifdef CRYPTO +#ifdef USE_GNUTLS +#include +#else +#include #include #endif +#endif #define RTMP_SIG_SIZE 1536 #define RTMP_LARGE_HEADER_SIZE 12 @@ -176,12 +179,16 @@ RTMPPacket_Dump(RTMPPacket *p) void RTMP_SSL_Init() { +#ifdef USE_GNUTLS + gnutls_global_init(); +#else SSL_load_error_strings(); SSL_library_init(); OpenSSL_add_all_digests(); RTMP_ssl_ctx = SSL_CTX_new(SSLv23_method()); SSL_CTX_set_options(RTMP_ssl_ctx, SSL_OP_ALL); SSL_CTX_set_default_verify_paths(RTMP_ssl_ctx); +#endif } void @@ -2798,7 +2805,7 @@ RTMP_Close(RTMP *r) #ifdef CRYPTO if (r->Link.dh) { - DH_free(r->Link.dh); + MDH_free(r->Link.dh); r->Link.dh = NULL; } if (r->Link.rc4keyIn)