diff --git a/configure.ac b/configure.ac index 2f7e1e80c4..23992fcc44 100644 --- a/configure.ac +++ b/configure.ac @@ -2211,7 +2211,7 @@ AG_GST_CHECK_FEATURE(SNDIO, [sndio audio], sndio, [ dnl *** hls *** translit(dnm, m, l) AM_CONDITIONAL(USE_HLS, true) AG_GST_CHECK_FEATURE(HLS, [http live streaming plugin], hls, [ - PKG_CHECK_MODULES(GNUTLS, gnutls >= 2.11.3, [ HAVE_HLS="yes" ], [ HAVE_HLS="no" ]) + AM_PATH_LIBGCRYPT([1.2.0], [ HAVE_HLS="yes" ], [ HAVE_HLS="no" ]) ]) else diff --git a/ext/hls/Makefile.am b/ext/hls/Makefile.am index 508c775514..853944b323 100644 --- a/ext/hls/Makefile.am +++ b/ext/hls/Makefile.am @@ -8,11 +8,11 @@ libgstfragmented_la_SOURCES = \ gsthlssink.c \ gstm3u8playlist.c -libgstfragmented_la_CFLAGS = $(GST_PLUGINS_BAD_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(GIO_CFLAGS) $(GNUTLS_CFLAGS) +libgstfragmented_la_CFLAGS = $(GST_PLUGINS_BAD_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(GIO_CFLAGS) $(LIBGCRYPT_CFLAGS) libgstfragmented_la_LIBADD = \ $(top_builddir)/gst-libs/gst/uridownloader/libgsturidownloader-@GST_API_VERSION@.la \ $(GST_PLUGINS_BASE_LIBS) -lgstpbutils-$(GST_API_VERSION) -lgstvideo-$(GST_API_VERSION) \ - $(GST_BASE_LIBS) $(GST_LIBS) $(GIO_LIBS) $(LIBM) $(GNUTLS_LIBS) + $(GST_BASE_LIBS) $(GST_LIBS) $(GIO_LIBS) $(LIBM) $(LIBGCRYPT_LIBS) libgstfragmented_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -no-undefined libgstfragmented_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS) diff --git a/ext/hls/gsthlsdemux.c b/ext/hls/gsthlsdemux.c index 6854263bbd..32e1b7b69f 100644 --- a/ext/hls/gsthlsdemux.c +++ b/ext/hls/gsthlsdemux.c @@ -47,8 +47,7 @@ #include #include -#include -#include +#include #include "gsthlsdemux.h" static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src_%u", @@ -1247,8 +1246,8 @@ gst_hls_demux_decrypt_fragment (GstHLSDemux * demux, GstFragment *key_fragment, *ret = NULL; GstBuffer *key_buffer, *encrypted_buffer, *decrypted_buffer; GstMapInfo key_info, encrypted_info, decrypted_info; - gnutls_cipher_hd_t aes_ctx; - gnutls_datum_t key_d, iv_d; + gcry_cipher_hd_t aes_ctx = NULL; + gcry_error_t err = 0; gsize unpadded_size; GST_INFO_OBJECT (demux, "Fetching key %s", key); @@ -1266,15 +1265,21 @@ gst_hls_demux_decrypt_fragment (GstHLSDemux * demux, gst_buffer_map (encrypted_buffer, &encrypted_info, GST_MAP_READ); gst_buffer_map (decrypted_buffer, &decrypted_info, GST_MAP_WRITE); - key_d.data = key_info.data; - key_d.size = 16; - iv_d.data = (unsigned char *) iv; - iv_d.size = 16; - gnutls_cipher_init (&aes_ctx, gnutls_cipher_get_id ("AES-128-CBC"), &key_d, - &iv_d); - gnutls_cipher_decrypt2 (aes_ctx, encrypted_info.data, encrypted_info.size, - decrypted_info.data, decrypted_info.size); - gnutls_cipher_deinit (aes_ctx); + err = + gcry_cipher_open (&aes_ctx, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC, 0); + if (err) + goto gcry_error; + err = gcry_cipher_setkey (aes_ctx, key_info.data, 16); + if (err) + goto gcry_error; + err = gcry_cipher_setiv (aes_ctx, iv, 16); + if (err) + goto gcry_error; + err = gcry_cipher_decrypt (aes_ctx, decrypted_info.data, decrypted_info.size, + encrypted_info.data, encrypted_info.size); + if (err) + goto gcry_error; + gcry_cipher_close (aes_ctx); /* Handle pkcs7 unpadding here */ unpadded_size = @@ -1296,6 +1301,24 @@ gst_hls_demux_decrypt_fragment (GstHLSDemux * demux, key_failed: g_object_unref (encrypted_fragment); return ret; + +gcry_error: + GST_ERROR_OBJECT (demux, "Failed to decrypt fragment: %s", + gpg_strerror (err)); + + if (aes_ctx) + gcry_cipher_close (aes_ctx); + + gst_buffer_unref (key_buffer); + gst_buffer_unref (encrypted_buffer); + gst_buffer_unref (decrypted_buffer); + + gst_buffer_unmap (decrypted_buffer, &decrypted_info); + gst_buffer_unmap (encrypted_buffer, &encrypted_info); + gst_buffer_unmap (key_buffer, &key_info); + + g_object_unref (encrypted_fragment); + return ret; } static gboolean diff --git a/m4/libgcrypt.m4 b/m4/libgcrypt.m4 new file mode 100644 index 0000000000..6cf482fcba --- /dev/null +++ b/m4/libgcrypt.m4 @@ -0,0 +1,122 @@ +dnl Autoconf macros for libgcrypt +dnl Copyright (C) 2002, 2004, 2011 Free Software Foundation, Inc. +dnl +dnl This file is free software; as a special exception the author gives +dnl unlimited permission to copy and/or distribute it, with or without +dnl modifications, as long as this notice is preserved. +dnl +dnl This file is distributed in the hope that it will be useful, but +dnl WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +dnl implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + +dnl AM_PATH_LIBGCRYPT([MINIMUM-VERSION, +dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) +dnl Test for libgcrypt and define LIBGCRYPT_CFLAGS and LIBGCRYPT_LIBS. +dnl MINIMUN-VERSION is a string with the version number optionalliy prefixed +dnl with the API version to also check the API compatibility. Example: +dnl a MINIMUN-VERSION of 1:1.2.5 won't pass the test unless the installed +dnl version of libgcrypt is at least 1.2.5 *and* the API number is 1. Using +dnl this features allows to prevent build against newer versions of libgcrypt +dnl with a changed API. +dnl +AC_DEFUN([AM_PATH_LIBGCRYPT], +[ AC_REQUIRE([AC_CANONICAL_HOST]) + AC_ARG_WITH(libgcrypt-prefix, + AC_HELP_STRING([--with-libgcrypt-prefix=PFX], + [prefix where LIBGCRYPT is installed (optional)]), + libgcrypt_config_prefix="$withval", libgcrypt_config_prefix="") + if test x$libgcrypt_config_prefix != x ; then + if test x${LIBGCRYPT_CONFIG+set} != xset ; then + LIBGCRYPT_CONFIG=$libgcrypt_config_prefix/bin/libgcrypt-config + fi + fi + + AC_PATH_TOOL(LIBGCRYPT_CONFIG, libgcrypt-config, no) + tmp=ifelse([$1], ,1:1.2.0,$1) + if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then + req_libgcrypt_api=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\1/'` + min_libgcrypt_version=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\2/'` + else + req_libgcrypt_api=0 + min_libgcrypt_version="$tmp" + fi + + AC_MSG_CHECKING(for LIBGCRYPT - version >= $min_libgcrypt_version) + ok=no + if test "$LIBGCRYPT_CONFIG" != "no" ; then + req_major=`echo $min_libgcrypt_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` + req_minor=`echo $min_libgcrypt_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` + req_micro=`echo $min_libgcrypt_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'` + libgcrypt_config_version=`$LIBGCRYPT_CONFIG --version` + major=`echo $libgcrypt_config_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'` + minor=`echo $libgcrypt_config_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'` + micro=`echo $libgcrypt_config_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\3/'` + if test "$major" -gt "$req_major"; then + ok=yes + else + if test "$major" -eq "$req_major"; then + if test "$minor" -gt "$req_minor"; then + ok=yes + else + if test "$minor" -eq "$req_minor"; then + if test "$micro" -ge "$req_micro"; then + ok=yes + fi + fi + fi + fi + fi + fi + if test $ok = yes; then + AC_MSG_RESULT([yes ($libgcrypt_config_version)]) + else + AC_MSG_RESULT(no) + fi + if test $ok = yes; then + # If we have a recent libgcrypt, we should also check that the + # API is compatible + if test "$req_libgcrypt_api" -gt 0 ; then + tmp=`$LIBGCRYPT_CONFIG --api-version 2>/dev/null || echo 0` + if test "$tmp" -gt 0 ; then + AC_MSG_CHECKING([LIBGCRYPT API version]) + if test "$req_libgcrypt_api" -eq "$tmp" ; then + AC_MSG_RESULT([okay]) + else + ok=no + AC_MSG_RESULT([does not match. want=$req_libgcrypt_api got=$tmp]) + fi + fi + fi + fi + if test $ok = yes; then + LIBGCRYPT_CFLAGS=`$LIBGCRYPT_CONFIG --cflags` + LIBGCRYPT_LIBS=`$LIBGCRYPT_CONFIG --libs` + ifelse([$2], , :, [$2]) + libgcrypt_config_host=`$LIBGCRYPT_CONFIG --host 2>/dev/null || echo none` + if test x"$libgcrypt_config_host" != xnone ; then + if test x"$libgcrypt_config_host" != x"$host" ; then + AC_MSG_WARN([[ +*** +*** The config script $LIBGCRYPT_CONFIG was +*** built for $libgcrypt_config_host and thus may not match the +*** used host $host. +*** You may want to use the configure option --with-libgcrypt-prefix +*** to specify a matching config script. +***]]) + fi + fi + else + LIBGCRYPT_CFLAGS="" + LIBGCRYPT_LIBS="" + ifelse([$3], , :, [$3]) + fi + AC_SUBST(LIBGCRYPT_CFLAGS) + AC_SUBST(LIBGCRYPT_LIBS) +])