mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-24 01:00:37 +00:00
hlsdemux: Prefer to use nettle for decryption but fall-back to libgcrypt
nettle is used by newer versions of gnutls, while older versions of gnutls used libgcrypt. Support both for now as not every distro has nettle yet. nettle is preferred as it is more efficient to use and much smaller.
This commit is contained in:
parent
6abed8da20
commit
6799e3b879
3 changed files with 78 additions and 26 deletions
14
configure.ac
14
configure.ac
|
@ -2211,7 +2211,19 @@ 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, [
|
||||
AM_PATH_LIBGCRYPT([1.2.0], [ HAVE_HLS="yes" ], [ HAVE_HLS="no" ])
|
||||
PKG_CHECK_MODULES(NETTLE, nettle,
|
||||
[
|
||||
AC_DEFINE(HAVE_NETTLE, 1, [Define if nettle is available])
|
||||
HAVE_HLS="yes"
|
||||
], [
|
||||
AM_PATH_LIBGCRYPT([1.2.0],
|
||||
[
|
||||
AC_DEFINE(HAVE_LIBGCRYPT, 1, [Define if libgcrypt is available])
|
||||
HAVE_HLS="yes"
|
||||
], [
|
||||
HAVE_HLS="no"
|
||||
])
|
||||
])
|
||||
])
|
||||
|
||||
else
|
||||
|
|
|
@ -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) $(LIBGCRYPT_CFLAGS)
|
||||
libgstfragmented_la_CFLAGS = $(GST_PLUGINS_BAD_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(GIO_CFLAGS) $(LIBGCRYPT_CFLAGS) $(NETTLE_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) $(LIBGCRYPT_LIBS)
|
||||
$(GST_BASE_LIBS) $(GST_LIBS) $(GIO_LIBS) $(LIBM) $(LIBGCRYPT_LIBS) $(NETTLE_LIBS)
|
||||
libgstfragmented_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -no-undefined
|
||||
libgstfragmented_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS)
|
||||
|
||||
|
|
|
@ -42,7 +42,12 @@
|
|||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#ifdef HAVE_NETTLE
|
||||
#include <nettle/aes.h>
|
||||
#include <nettle/cbc.h>
|
||||
#else
|
||||
#include <gcrypt.h>
|
||||
#endif
|
||||
#include "gsthlsdemux.h"
|
||||
|
||||
static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src_%u",
|
||||
|
@ -1231,6 +1236,59 @@ gst_hls_demux_switch_playlist (GstHLSDemux * demux)
|
|||
return gst_hls_demux_change_playlist (demux, bitrate * demux->bitrate_limit);
|
||||
}
|
||||
|
||||
#ifdef HAVE_NETTLE
|
||||
static gboolean
|
||||
decrypt_fragment (GstHLSDemux * demux, gsize length,
|
||||
const guint8 * encrypted_data, guint8 * decrypted_data,
|
||||
const guint8 * key_data, const guint8 * iv_data)
|
||||
{
|
||||
struct CBC_CTX (struct aes_ctx, AES_BLOCK_SIZE) aes_ctx;
|
||||
|
||||
if (length % 16 != 0)
|
||||
return FALSE;
|
||||
|
||||
aes_set_decrypt_key (&aes_ctx.ctx, 16, key_data);
|
||||
CBC_SET_IV (&aes_ctx, iv_data);
|
||||
|
||||
CBC_DECRYPT (&aes_ctx, aes_decrypt, length, decrypted_data, encrypted_data);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#else
|
||||
static gboolean
|
||||
decrypt_fragment (GstHLSDemux * demux, gsize length,
|
||||
const guint8 * encrypted_data, guint8 * decrypted_data,
|
||||
const guint8 * key_data, const guint8 * iv_data)
|
||||
{
|
||||
gcry_cipher_hd_t aes_ctx = NULL;
|
||||
gcry_error_t err = 0;
|
||||
gboolean ret = FALSE;
|
||||
|
||||
err =
|
||||
gcry_cipher_open (&aes_ctx, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC, 0);
|
||||
if (err)
|
||||
goto out;
|
||||
err = gcry_cipher_setkey (aes_ctx, key_data, 16);
|
||||
if (err)
|
||||
goto out;
|
||||
err = gcry_cipher_setiv (aes_ctx, iv_data, 16);
|
||||
if (err)
|
||||
goto out;
|
||||
err = gcry_cipher_decrypt (aes_ctx, decrypted_data, length,
|
||||
encrypted_data, length);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
out:
|
||||
if (aes_ctx)
|
||||
gcry_cipher_close (aes_ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static GstFragment *
|
||||
gst_hls_demux_decrypt_fragment (GstHLSDemux * demux,
|
||||
GstFragment * encrypted_fragment, const gchar * key, const guint8 * iv)
|
||||
|
@ -1238,8 +1296,6 @@ 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;
|
||||
gcry_cipher_hd_t aes_ctx = NULL;
|
||||
gcry_error_t err = 0;
|
||||
gsize unpadded_size;
|
||||
|
||||
GST_INFO_OBJECT (demux, "Fetching key %s", key);
|
||||
|
@ -1257,21 +1313,9 @@ 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);
|
||||
|
||||
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);
|
||||
if (!decrypt_fragment (demux, encrypted_info.size,
|
||||
encrypted_info.data, decrypted_info.data, key_info.data, iv))
|
||||
goto decrypt_error;
|
||||
|
||||
/* Handle pkcs7 unpadding here */
|
||||
unpadded_size =
|
||||
|
@ -1294,12 +1338,8 @@ 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);
|
||||
decrypt_error:
|
||||
GST_ERROR_OBJECT (demux, "Failed to decrypt fragment");
|
||||
|
||||
gst_buffer_unref (key_buffer);
|
||||
gst_buffer_unref (encrypted_buffer);
|
||||
|
|
Loading…
Reference in a new issue