[rtmpdump] r363 - in trunk/librtmp: dh.h rtmp.c
hyc
subversion at mplayerhq.hu
Wed Mar 17 08:09:29 CET 2010
Author: hyc
Date: Wed Mar 17 08:09:28 2010
New Revision: 363
Log:
Add GnuTLS/Gcrypt support for DH key exchange
Modified:
trunk/librtmp/dh.h
trunk/librtmp/rtmp.c
Modified: trunk/librtmp/dh.h
==============================================================================
--- trunk/librtmp/dh.h Tue Mar 16 10:21:27 2010 (r362)
+++ trunk/librtmp/dh.h Wed Mar 17 08:09:28 2010 (r363)
@@ -26,6 +26,52 @@
#include <assert.h>
#include <limits.h>
+#ifdef USE_GNUTLS
+#include <gcrypt.h>
+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 <openssl/bn.h>
#include <openssl/dh.h>
@@ -33,43 +79,65 @@
#include <openssl/hmac.h>
#include <openssl/rc4.h>
+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,
}
// 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,
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;
}
Modified: trunk/librtmp/rtmp.c
==============================================================================
--- trunk/librtmp/rtmp.c Tue Mar 16 10:21:27 2010 (r362)
+++ trunk/librtmp/rtmp.c Wed Mar 17 08:09:28 2010 (r363)
@@ -30,11 +30,14 @@
#include "rtmp_sys.h"
#include "log.h"
-#include <openssl/ssl.h>
-
#ifdef CRYPTO
+#ifdef USE_GNUTLS
+#include <gnutls/gnutls.h>
+#else
+#include <openssl/ssl.h>
#include <openssl/rc4.h>
#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)
More information about the rtmpdump
mailing list