On Mon, 16 Jul 2012, Samuel Pitoiset wrote:

This adds two protocols, but one of them is an internal implementation
detail just used as an abstraction layer/generalization in the code. The
RTMPE protocol implementation uses rtmpenc:// as an alternative to the

This should be updated with the new protocol name

tcp:// protocol. This allows moving most of the lower level logic out
from the higher level generic rtmp code.
---
configure                |  11 ++
doc/general.texi         |   2 +-
doc/protocols.texi       |   9 ++
libavformat/Makefile     |   2 +
libavformat/allformats.c |   2 +
libavformat/rtmpdh.c     | 291 ++++++++++++++++++++++++++++++++++++++++++++
libavformat/rtmpdh.h     | 105 ++++++++++++++++
libavformat/rtmpenc.c    | 309 +++++++++++++++++++++++++++++++++++++++++++++++
libavformat/rtmpenc.h    |  69 +++++++++++
libavformat/rtmpproto.c  | 106 ++++++++++++++--
libavformat/version.h    |   2 +-
11 files changed, 899 insertions(+), 9 deletions(-)
create mode 100644 libavformat/rtmpdh.c
create mode 100644 libavformat/rtmpdh.h
create mode 100644 libavformat/rtmpenc.c
create mode 100644 libavformat/rtmpenc.h

diff --git a/configure b/configure
index 6b46ee4..3e3f2ce 100755
--- a/configure
+++ b/configure
@@ -937,6 +937,7 @@ CONFIG_LIST="
    fastdiv
    fft
    frei0r
+    gcrypt
    gnutls
    gpl
    gray
@@ -969,6 +970,7 @@ CONFIG_LIST="
    mdct
    memalign_hack
    mpegaudiodsp
+    nettle
    network
    nonfree
    openssl
@@ -1526,6 +1528,9 @@ vfwcap_indev_extralibs="-lavicap32"
x11_grab_device_indev_deps="x11grab XShmCreateImage"

# protocols
+ffrtmpenc_protocol_deps="!librtmp_protocol"
+ffrtmpenc_protocol_deps_any="gcrypt nettle openssl"
+ffrtmpenc_protocol_select="tcp_protocol"
gopher_protocol_deps="network"
httpproxy_protocol_deps="network"
httpproxy_protocol_select="tcp_protocol"
@@ -1541,6 +1546,7 @@ mmsh_protocol_select="http_protocol"
mmst_protocol_deps="network"
rtmp_protocol_deps="!librtmp_protocol"
rtmp_protocol_select="tcp_protocol"
+rtmpe_protocol_select="ffrtmpenc_protocol"

Since the others (rtmp and rtmpt) both have the _deps="!librtmp_protocol", this one should as well, I think. In principle it's not needed since we get the same dep via ffrtmpenc though, but it's perhaps better to keep it for consistency.

rtmphttp_protocol_deps="!librtmp_protocol"
rtmphttp_protocol_select="http_protocol"
rtmpt_protocol_deps="!librtmp_protocol"
@@ -3004,6 +3010,11 @@ enabled openssl    && { check_lib openssl/ssl.h 
SSL_library_init -lssl -lcrypto
                        check_lib openssl/ssl.h SSL_library_init -lssl -lcrypto 
-lws2_32 -lgdi32 ||
                        die "ERROR: openssl not found"; }

+if enabled gnutls; then
+    { check_lib nettle/bignum.h nettle_mpz_get_str_256 -lnettle -lhogweed -lgmp 
&& enable nettle; } ||
+    { check_lib gcrypt.h gcry_mpi_new -lgcrypt && enable gcrypt; }
+fi
+
# libdc1394 check
if enabled libdc1394; then
    { check_lib dc1394/dc1394.h dc1394_new -ldc1394 -lraw1394 &&
diff --git a/libavformat/rtmpdh.c b/libavformat/rtmpdh.c
new file mode 100644
index 0000000..44ac742
--- /dev/null
+++ b/libavformat/rtmpdh.c
@@ -0,0 +1,291 @@
+/*
+ * RTMP Diffie-Hellmann utilities
+ * Copyright (c) 2012 Samuel Pitoiset
+ *
+ * This file is part of Libav.
+ *
+ * Libav is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * Libav is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * RTMP Diffie-Hellmann utilities
+ */
+
+#include "config.h"
+#include "rtmpdh.h"
+
+#define P1024                                          \
+    "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
+    "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
+    "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \
+    "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
+    "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" \
+    "FFFFFFFFFFFFFFFF"
+
+#define Q1024                                          \
+    "7FFFFFFFFFFFFFFFE487ED5110B4611A62633145C06E0E68" \
+    "948127044533E63A0105DF531D89CD9128A5043CC71A026E" \
+    "F7CA8CD9E69D218D98158536F92F8A1BA7F09AB6B6A8E122" \
+    "F242DABB312F3F637A262174D31BF6B585FFAE5B7A035BF6" \
+    "F71C35FDAD44CFD2D74F9208BE258FF324943328F67329C0" \
+    "FFFFFFFFFFFFFFFF"
+
+#if CONFIG_NETTLE || CONFIG_GCRYPT
+#if CONFIG_NETTLE
+#define bn_new(bn)                      \
+    do {                                \

If you want to save one line, you could move the do { to the previous line. But this is way more compact than before now, so it's pretty good as is.

+        bn = av_malloc(sizeof(*bn));    \
+        if (bn)                         \
+            mpz_init2(bn, 1);           \
+    } while (0)
+#define bn_free(bn)                 mpz_clear(bn); av_free(bn)

Please enclose this one in do { } while (0) as well

+#define bn_set_word(bn, w)          mpz_set_ui(bn, w)
+#define bn_cmp(a, b)                mpz_cmp(a, b)
+#define bn_copy(to, from)           mpz_set(to, from)
+#define bn_sub_word(bn, w)          mpz_sub_ui(bn, bn, w)
+#define bn_cmp_1(bn)                mpz_cmp_ui(bn, 1)
+#define bn_num_bytes(bn)            (mpz_sizeinbase(bn, 2) + 7) / 8
+#define bn_bn2bin(bn, buf, len)     nettle_mpz_get_str_256(len, buf, bn)
+#define bn_bin2bn(bn, buf, len)                     \
+    do {                                            \
+        bn_new(bn);                                 \
+        if (bn)                                     \
+            nettle_mpz_set_str_256_u(bn, len, buf); \
+    } while (0)
+#define bn_hex2bn(bn, buf, ret)                     \
+    do {                                            \
+        bn_new(bn);                                 \
+        if (bn)                                     \
+            ret = (mpz_set_str(bn, buf, 16) == 0);  \
+    } while (0)
+#define bn_modexp(bn, y, q, p)      mpz_powm(bn, y, q, p)
+#elif CONFIG_GCRYPT
+#define bn_new(bn)                  bn = gcry_mpi_new(1)
+#define bn_free(bn)                 gcry_mpi_release(bn)
+#define bn_set_word(bn, w)          gcry_mpi_set_ui(bn, w)
+#define bn_cmp(a, b)                gcry_mpi_cmp(a, b)
+#define bn_copy(to, from)           gcry_mpi_set(to, from)
+#define bn_sub_word(bn, w)          gcry_mpi_sub_ui(bn, bn, w)
+#define bn_cmp_1(bn)                gcry_mpi_cmp_ui(bn, 1)
+#define bn_num_bytes(bn)            (gcry_mpi_get_nbits(bn) + 7) / 8
+#define bn_bn2bin(bn, buf, len)     gcry_mpi_print(GCRYMPI_FMT_USG, buf, len, 
NULL, bn)
+#define bn_bin2bn(bn, buf, len)     gcry_mpi_scan(&bn, GCRYMPI_FMT_USG, buf, 
len, NULL)
+#define bn_hex2bn(bn, buf, ret)     ret = (gcry_mpi_scan(&bn, GCRYMPI_FMT_HEX, 
buf, 0, 0) == 0)
+#define bn_modexp(bn, y, q, p)      gcry_mpi_powm(bn, y, q, p)
+#endif
+
+#define dh_new()                    av_malloc(sizeof(FF_DH))
+#define dh_generate_key(dh)         (dh->pub_key = 
gnutls_calc_dh_secret(&dh->priv_key, dh->g, dh->p))

I didn't realize we actually call functions from gnutls as well, not only from the crypto libraries - this changes how we should handle things a little.

I think the most straightforward way would be to change the _deps_any into

ffrtmpenc_protocol_deps_any="gnutls openssl"

and then make the check for nettle/gcrypt fail if none of them is found. Then we can safely change the "CONFIG_NETTLE || CONFIG_GCRYPT" back into CONFIG_GNUTLS. The way the code is written now, if we would happen to change configure so that you could enable nettle/gcrypt without gnutls, this code would fail, since it expects gnutls as well. (If we don't make configure fail if none of the crypto libraries are found, this code could fail if configure finds gnutls, but for some strange reason can't find either of the crypto libs.)


I see that the two functions aren't even proper public functions in gnutls - this means that gnutls is free to change them at any point. Ideally, we could ask gnutls to make them public, but that wouldn't help much for the versions currently out there.

On a quick look in the gnutls source, it seems that they're pretty simple, so we could just implement the same thing as they do with direct gcrypt/nettle/gmp calls instead. The you can ignore all that I said about modifying things above - then none of this code needs to know about gnutls at all, only gcrypt/nettle.


Also, as j-b pointed out on irc, rtmpenc might sound a bit misleading. Not sure what would be better though, rtmpcrypt?

// Martin
_______________________________________________
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to