[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