diff mbox

[FFmpeg-devel] libavformat: add mbedTLS based TLS

Message ID 1524319295-29428-1-git-send-email-silvo@gmx.net
State Superseded
Headers show

Commit Message

Thomas Volkert April 21, 2018, 2:01 p.m. UTC
From: Thomas Volkert <thomas.volkert@net-zeal.com>

---
 Changelog                 |   1 +
 configure                 |  31 ++--
 libavformat/Makefile      |   1 +
 libavformat/rtmpdh.c      |  55 ++++++++
 libavformat/rtmpdh.h      |   5 +
 libavformat/tls_mbedtls.c | 351 ++++++++++++++++++++++++++++++++++++++++++++++
 libavformat/version.h     |   2 +-
 7 files changed, 436 insertions(+), 10 deletions(-)
 create mode 100644 libavformat/tls_mbedtls.c

Comments

Nicolas George April 21, 2018, 2:05 p.m. UTC | #1
Thomas Volkert (2018-04-21):
> +- support mbedTLS based TLS

What is the benefit?

Regards,
Thomas Volkert April 21, 2018, 2:09 p.m. UTC | #2
On 21.04.2018 16:05, Nicolas George wrote:
> Thomas Volkert (2018-04-21):
>> +- support mbedTLS based TLS
> What is the benefit?

It needs less memory than other TLS implementations.
This is especially interesting for embedded systems.
(There is at least one real project which demands for this.)

Best regards,
Thomas.
Nicolas George April 21, 2018, 2:13 p.m. UTC | #3
Thomas Volkert (2018-04-21):
> It needs less memory than other TLS implementations.
> This is especially interesting for embedded systems.
> (There is at least one real project which demands for this.)

Thanks. Do you know how it compares in terms of speed?

Also, did you check bearssl? It has similar goals and benefits, and I
think it is a very trustworthy project.

Anyway, I think this should be stated somewhere, because users will not
be able to decide which library is better for their needs. Not blocking
for this patch, but to keep in mind.

Regards,
Carl Eugen Hoyos April 21, 2018, 4:18 p.m. UTC | #4
2018-04-21 16:01 GMT+02:00, Thomas Volkert <silvo@gmx.net>:

> +++ b/Changelog
> @@ -3,6 +3,7 @@ releases are sorted from youngest to oldest.
>
>  version <next>:
>  - deblock filter
> +- support mbedTLS based TLS

From a quick look, I believe this library is not license-compatible,
please solve this before committing.

Thank you, Carl Eugen
Hendrik Leppkes April 21, 2018, 7:37 p.m. UTC | #5
On Sat, Apr 21, 2018 at 6:18 PM, Carl Eugen Hoyos <ceffmpeg@gmail.com> wrote:
> 2018-04-21 16:01 GMT+02:00, Thomas Volkert <silvo@gmx.net>:
>
>> +++ b/Changelog
>> @@ -3,6 +3,7 @@ releases are sorted from youngest to oldest.
>>
>>  version <next>:
>>  - deblock filter
>> +- support mbedTLS based TLS
>
> From a quick look, I believe this library is not license-compatible,
> please solve this before committing.
>

mbedTLS is available both under Apache 2.0 and GPL 2.0 - and the patch
even adds it as nonfree only. Can you elaborate what you think the
problem is?

- Hendrik
Carl Eugen Hoyos April 21, 2018, 7:46 p.m. UTC | #6
2018-04-21 21:37 GMT+02:00, Hendrik Leppkes <h.leppkes@gmail.com>:
> On Sat, Apr 21, 2018 at 6:18 PM, Carl Eugen Hoyos <ceffmpeg@gmail.com>
> wrote:
>> 2018-04-21 16:01 GMT+02:00, Thomas Volkert <silvo@gmx.net>:
>>
>>> +++ b/Changelog
>>> @@ -3,6 +3,7 @@ releases are sorted from youngest to oldest.
>>>
>>>  version <next>:
>>>  - deblock filter
>>> +- support mbedTLS based TLS
>>
>> From a quick look, I believe this library is not license-compatible,
>> please solve this before committing.
>>
>
> mbedTLS is available both under Apache 2.0 and GPL 2.0 -
> and the patch even adds it as nonfree only.

I missed the nonfree part of the patch (and it surprises me now).

> Can you elaborate what you think the problem is?

Given that we allow muxing against gpl and Apache, I believe
the patch can be improved.

Carl Eugen
Thomas Volkert April 21, 2018, 7:59 p.m. UTC | #7
On 21.04.2018 21:46, Carl Eugen Hoyos wrote:

> 2018-04-21 21:37 GMT+02:00, Hendrik Leppkes <h.leppkes@gmail.com>:
>> On Sat, Apr 21, 2018 at 6:18 PM, Carl Eugen Hoyos <ceffmpeg@gmail.com>
>> wrote:
>>> 2018-04-21 16:01 GMT+02:00, Thomas Volkert <silvo@gmx.net>:
>>>
>>>> +++ b/Changelog
>>>> @@ -3,6 +3,7 @@ releases are sorted from youngest to oldest.
>>>>
>>>>  version <next>:
>>>>  - deblock filter
>>>> +- support mbedTLS based TLS
>>> From a quick look, I believe this library is not license-compatible,
>>> please solve this before committing.
>>>
>> mbedTLS is available both under Apache 2.0 and GPL 2.0 -

Confirmed.

>> and the patch even adds it as nonfree only.
> I missed the nonfree part of the patch (and it surprises me now).

Yes, the patch is quite restrictive related to the license.

>> Can you elaborate what you think the problem is?
> Given that we allow muxing against gpl and Apache, I believe
> the patch can be improved.

Okay, what do you suggest  in detail?

Best regards,
Thomas.
Carl Eugen Hoyos April 21, 2018, 8:15 p.m. UTC | #8
2018-04-21 21:59 GMT+02:00, Thomas Volkert <silvo@gmx.net>:
> On 21.04.2018 21:46, Carl Eugen Hoyos wrote:
>
>> 2018-04-21 21:37 GMT+02:00, Hendrik Leppkes <h.leppkes@gmail.com>:

>>> Can you elaborate what you think the problem is?
>> Given that we allow muxing against gpl and Apache, I believe
>> the patch can be improved.
>
> Okay, what do you suggest  in detail?

I believe the easiest solution is to "require version 3"
as we do for other Apache libraries (libvmaf and
libopencore).

Thank you, Carl Eugen
Hendrik Leppkes April 21, 2018, 11:30 p.m. UTC | #9
On Sat, Apr 21, 2018 at 10:15 PM, Carl Eugen Hoyos <ceffmpeg@gmail.com> wrote:
> 2018-04-21 21:59 GMT+02:00, Thomas Volkert <silvo@gmx.net>:
>> On 21.04.2018 21:46, Carl Eugen Hoyos wrote:
>>
>>> 2018-04-21 21:37 GMT+02:00, Hendrik Leppkes <h.leppkes@gmail.com>:
>
>>>> Can you elaborate what you think the problem is?
>>> Given that we allow muxing against gpl and Apache, I believe
>>> the patch can be improved.
>>
>> Okay, what do you suggest  in detail?
>
> I believe the easiest solution is to "require version 3"
> as we do for other Apache libraries (libvmaf and
> libopencore).
>

mbedTLS is dual-licensed under GPLv2 as well, so why not allow it with
GPL version 2 as well?

- Hendrik
Carl Eugen Hoyos April 21, 2018, 11:48 p.m. UTC | #10
2018-04-22 1:30 GMT+02:00, Hendrik Leppkes <h.leppkes@gmail.com>:
> On Sat, Apr 21, 2018 at 10:15 PM, Carl Eugen Hoyos <ceffmpeg@gmail.com>
> wrote:
>> 2018-04-21 21:59 GMT+02:00, Thomas Volkert <silvo@gmx.net>:
>>> On 21.04.2018 21:46, Carl Eugen Hoyos wrote:
>>>
>>>> 2018-04-21 21:37 GMT+02:00, Hendrik Leppkes <h.leppkes@gmail.com>:
>>
>>>>> Can you elaborate what you think the problem is?
>>>> Given that we allow muxing against gpl and Apache, I believe
>>>> the patch can be improved.
>>>
>>> Okay, what do you suggest  in detail?
>>
>> I believe the easiest solution is to "require version 3"
>> as we do for other Apache libraries (libvmaf and
>> libopencore).
>>
>
> mbedTLS is dual-licensed under GPLv2 as well, so why
> not allow it with GPL version 2 as well?

Because - iiuc - only releases are GPL, not the "current versions".

Carl Eugen
Thomas Volkert April 22, 2018, 9:30 a.m. UTC | #11
On 22.04.2018 01:48, Carl Eugen Hoyos wrote:
> 2018-04-22 1:30 GMT+02:00, Hendrik Leppkes <h.leppkes@gmail.com>:
>> On Sat, Apr 21, 2018 at 10:15 PM, Carl Eugen Hoyos <ceffmpeg@gmail.com>
>> wrote:
>>> 2018-04-21 21:59 GMT+02:00, Thomas Volkert <silvo@gmx.net>:
>>>> On 21.04.2018 21:46, Carl Eugen Hoyos wrote:
>>>>
>>>>> 2018-04-21 21:37 GMT+02:00, Hendrik Leppkes <h.leppkes@gmail.com>:
>>>>>> Can you elaborate what you think the problem is?
>>>>> Given that we allow muxing against gpl and Apache, I believe
>>>>> the patch can be improved.
>>>> Okay, what do you suggest  in detail?
>>> I believe the easiest solution is to "require version 3"
>>> as we do for other Apache libraries (libvmaf and
>>> libopencore).
>>>
>> mbedTLS is dual-licensed under GPLv2 as well, so why
>> not allow it with GPL version 2 as well?
I had the same thoughts today (put mbedtls in the
EXTERNAL_LIBRARY_GPL_LIST list).
Maybe I will wait for other opinions for about 2 hours and then resend
the patch.

Best regards,
Thomas.
diff mbox

Patch

diff --git a/Changelog b/Changelog
index 3ed4874..0a344f3 100644
--- a/Changelog
+++ b/Changelog
@@ -3,6 +3,7 @@  releases are sorted from youngest to oldest.
 
 version <next>:
 - deblock filter
+- support mbedTLS based TLS
 
 
 version 4.0:
diff --git a/configure b/configure
index dee507c..4dda466 100755
--- a/configure
+++ b/configure
@@ -213,7 +213,7 @@  External library support:
   --enable-gmp             enable gmp, needed for rtmp(t)e support
                            if openssl or librtmp is not used [no]
   --enable-gnutls          enable gnutls, needed for https support
-                           if openssl or libtls is not used [no]
+                           if openssl, libtls or mbedtls is not used [no]
   --disable-iconv          disable iconv [autodetect]
   --enable-jni             enable JNI support [no]
   --enable-ladspa          enable LADSPA audio filtering [no]
@@ -262,7 +262,7 @@  External library support:
   --enable-libtesseract    enable Tesseract, needed for ocr filter [no]
   --enable-libtheora       enable Theora encoding via libtheora [no]
   --enable-libtls          enable LibreSSL (via libtls), needed for https support
-                           if openssl or gnutls is not used [no]
+                           if openssl, gnutls or mbedtls is not used [no]
   --enable-libtwolame      enable MP2 encoding via libtwolame [no]
   --enable-libv4l2         enable libv4l2/v4l-utils [no]
   --enable-libvidstab      enable video stabilization using vid.stab [no]
@@ -290,13 +290,15 @@  External library support:
   --disable-lzma           disable lzma [autodetect]
   --enable-decklink        enable Blackmagic DeckLink I/O support [no]
   --enable-libndi_newtek   enable Newteck NDI I/O support [no]
+  --enable-mbedtls         enable mbedTLS, needed for https support
+                           if openssl, gnutls or libtls is not used [no]
   --enable-mediacodec      enable Android MediaCodec support [no]
   --enable-libmysofa       enable libmysofa, needed for sofalizer filter [no]
   --enable-openal          enable OpenAL 1.1 capture support [no]
   --enable-opencl          enable OpenCL processing [no]
   --enable-opengl          enable OpenGL rendering [no]
   --enable-openssl         enable openssl, needed for https support
-                           if gnutls or libtls is not used [no]
+                           if gnutls, libtls or mbedtls is not used [no]
   --disable-sndio          disable sndio support [autodetect]
   --disable-schannel       disable SChannel SSP, needed for TLS support on
                            Windows if openssl and gnutls are not used [autodetect]
@@ -1646,6 +1648,7 @@  EXTERNAL_LIBRARY_NONFREE_LIST="
     libfdk_aac
     openssl
     libtls
+    mbedtls
 "
 
 EXTERNAL_LIBRARY_VERSION3_LIST="
@@ -3117,7 +3120,7 @@  fifo_muxer_deps="threads"
 flac_demuxer_select="flac_parser"
 hds_muxer_select="flv_muxer"
 hls_muxer_select="mpegts_muxer"
-hls_muxer_suggest="gcrypt openssl"
+hls_muxer_suggest="gcrypt openssl mbedtls"
 image2_alias_pix_demuxer_select="image2_demuxer"
 image2_brender_pix_demuxer_select="image2_demuxer"
 ipod_muxer_select="mov_muxer"
@@ -3229,7 +3232,7 @@  xv_outdev_extralibs="-lXv -lX11 -lXext"
 async_protocol_deps="threads"
 bluray_protocol_deps="libbluray"
 ffrtmpcrypt_protocol_conflict="librtmp_protocol"
-ffrtmpcrypt_protocol_deps_any="gcrypt gmp openssl"
+ffrtmpcrypt_protocol_deps_any="gcrypt gmp openssl mbedtls"
 ffrtmpcrypt_protocol_select="tcp_protocol"
 ffrtmphttp_protocol_conflict="librtmp_protocol"
 ffrtmphttp_protocol_select="http_protocol"
@@ -3249,7 +3252,7 @@  librtmpt_protocol_deps="librtmp"
 librtmpte_protocol_deps="librtmp"
 libsmbclient_protocol_deps="libsmbclient gplv3"
 libssh_protocol_deps="libssh"
-libtls_conflict="openssl gnutls"
+libtls_conflict="openssl gnutls mbedtls"
 mmsh_protocol_select="http_protocol"
 mmst_protocol_select="network"
 libsrt_protocol_deps="libsrt"
@@ -3269,13 +3272,13 @@  rtmpte_protocol_suggest="zlib"
 rtmpts_protocol_select="ffrtmphttp_protocol https_protocol"
 rtmpts_protocol_suggest="zlib"
 rtp_protocol_select="udp_protocol"
-schannel_conflict="openssl gnutls libtls"
+schannel_conflict="openssl gnutls libtls mbedtls"
 sctp_protocol_deps="struct_sctp_event_subscribe struct_msghdr_msg_flags"
 sctp_protocol_select="network"
-securetransport_conflict="openssl gnutls libtls"
+securetransport_conflict="openssl gnutls libtls mbedtls"
 srtp_protocol_select="rtp_protocol srtp"
 tcp_protocol_select="network"
-tls_protocol_deps_any="gnutls openssl schannel securetransport libtls"
+tls_protocol_deps_any="gnutls openssl schannel securetransport libtls mbedtls"
 tls_protocol_select="tcp_protocol"
 udp_protocol_select="network"
 udplite_protocol_select="network"
@@ -3907,6 +3910,12 @@  fi
 enabled_all gnutls openssl &&
     die "GnuTLS and OpenSSL must not be enabled at the same time."
 
+enabled_all gnutls mbedtls &&
+    die "GnuTLS and mbedTLS must not be enabled at the same time."
+
+enabled_all openssl mbedtls &&
+    die "OpenSSL and mbedTLS must not be enabled at the same time."
+
 # Disable all the library-specific components if the library itself
 # is disabled, see AVCODEC_LIST and following _LIST variables.
 
@@ -6090,6 +6099,10 @@  enabled libzvbi           && require_pkg_config libzvbi zvbi-0.2 libzvbi.h vbi_d
                              { test_cpp_condition libzvbi.h "VBI_VERSION_MAJOR > 0 || VBI_VERSION_MINOR > 2 || VBI_VERSION_MINOR == 2 && VBI_VERSION_MICRO >= 28" ||
                                enabled gpl || die "ERROR: libzvbi requires version 0.2.28 or --enable-gpl."; }
 enabled libxml2           && require_pkg_config libxml2 libxml-2.0 libxml2/libxml/xmlversion.h xmlCheckVersion
+enabled mbedtls           && { check_pkg_config mbedtls mbedtls mbedtls/x509_crt.h mbedtls_x509_crt_init ||
+                               check_pkg_config mbedtls mbedtls mbedtls/ssl.h mbedtls_ssl_init ||
+                               check_lib mbedtls mbedtls/ssl.h mbedtls_ssl_init -lmbedtls ||
+                               die "ERROR: mbedTLS not found"; }
 enabled mediacodec        && { enabled jni || die "ERROR: mediacodec requires --enable-jni"; }
 enabled mmal              && { check_lib mmal interface/mmal/mmal.h mmal_port_connect -lmmal_core -lmmal_util -lmmal_vc_client -lbcm_host ||
                                { ! enabled cross_compile &&
diff --git a/libavformat/Makefile b/libavformat/Makefile
index 3eeca50..1f6b42a 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -608,6 +608,7 @@  OBJS-$(CONFIG_TEE_PROTOCOL)              += teeproto.o tee_common.o
 OBJS-$(CONFIG_TCP_PROTOCOL)              += tcp.o
 TLS-OBJS-$(CONFIG_GNUTLS)                += tls_gnutls.o
 TLS-OBJS-$(CONFIG_LIBTLS)                += tls_libtls.o
+TLS-OBJS-$(CONFIG_MBEDTLS)               += tls_mbedtls.o
 TLS-OBJS-$(CONFIG_OPENSSL)               += tls_openssl.o
 TLS-OBJS-$(CONFIG_SECURETRANSPORT)       += tls_securetransport.o
 TLS-OBJS-$(CONFIG_SCHANNEL)              += tls_schannel.o
diff --git a/libavformat/rtmpdh.c b/libavformat/rtmpdh.c
index 8eb0882..5ddae53 100644
--- a/libavformat/rtmpdh.c
+++ b/libavformat/rtmpdh.c
@@ -38,6 +38,11 @@ 
 
 #include "rtmpdh.h"
 
+#if CONFIG_MBEDTLS
+#include <mbedtls/ctr_drbg.h>
+#include <mbedtls/entropy.h>
+#endif
+
 #define P1024                                          \
     "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
     "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
@@ -159,6 +164,56 @@  static int bn_modexp(FFBigNum bn, FFBigNum y, FFBigNum q, FFBigNum p)
     BN_CTX_free(ctx);
     return 0;
 }
+#elif CONFIG_MBEDTLS
+#define bn_new(bn)                      \
+    do {                                \
+        bn = av_malloc(sizeof(*bn));    \
+        if (bn)                         \
+            mbedtls_mpi_init(bn);       \
+    } while (0)
+#define bn_free(bn)                     \
+    do {                                \
+        mbedtls_mpi_free(bn);           \
+        av_free(bn);                    \
+    } while (0)
+#define bn_set_word(bn, w)          mbedtls_mpi_lset(bn, w)
+#define bn_cmp(a, b)                mbedtls_mpi_cmp_mpi(a, b)
+#define bn_copy(to, from)           mbedtls_mpi_copy(to, from)
+#define bn_sub_word(bn, w)          mbedtls_mpi_sub_int(bn, bn, w)
+#define bn_cmp_1(bn)                mbedtls_mpi_cmp_int(bn, 1)
+#define bn_num_bytes(bn)            (mbedtls_mpi_bitlen(bn) + 7) / 8
+#define bn_bn2bin(bn, buf, len)     mbedtls_mpi_write_binary(bn, buf, len)
+#define bn_bin2bn(bn, buf, len)                     \
+    do {                                            \
+        bn_new(bn);                                 \
+        if (bn)                                     \
+            mbedtls_mpi_read_binary(bn, buf, len);  \
+    } while (0)
+#define bn_hex2bn(bn, buf, ret)                     \
+    do {                                            \
+        bn_new(bn);                                 \
+        if (bn)                                     \
+            ret = (mbedtls_mpi_read_string(bn, 16, buf) == 0);  \
+        else                                        \
+            ret = 1;                                \
+    } while (0)
+#define bn_random(bn, num_bits)                     \
+    do {                                            \
+        mbedtls_entropy_context entropy_ctx;        \
+        mbedtls_ctr_drbg_context ctr_drbg_ctx;      \
+                                                    \
+        mbedtls_entropy_init(&entropy_ctx);         \
+        mbedtls_ctr_drbg_init(&ctr_drbg_ctx);       \
+        mbedtls_ctr_drbg_seed(&ctr_drbg_ctx,        \
+                              mbedtls_entropy_func, \
+                              &entropy_ctx,         \
+                              NULL, 0);             \
+        mbedtls_mpi_fill_random(bn, (num_bits + 7) / 8, mbedtls_ctr_drbg_random, &ctr_drbg_ctx); \
+        mbedtls_ctr_drbg_free(&ctr_drbg_ctx);       \
+        mbedtls_entropy_free(&entropy_ctx);         \
+    } while (0)
+#define bn_modexp(bn, y, q, p)      mbedtls_mpi_exp_mod(bn, y, q, p, 0)
+
 #endif
 
 #define MAX_BYTES 18000
diff --git a/libavformat/rtmpdh.h b/libavformat/rtmpdh.h
index 188aad7..8cc1a42 100644
--- a/libavformat/rtmpdh.h
+++ b/libavformat/rtmpdh.h
@@ -40,6 +40,11 @@  typedef gcry_mpi_t FFBigNum;
 #include <openssl/dh.h>
 
 typedef BIGNUM *FFBigNum;
+#elif CONFIG_MBEDTLS
+#include <mbedtls/bignum.h>
+
+typedef mbedtls_mpi *FFBigNum;
+
 #endif
 
 typedef struct FF_DH {
diff --git a/libavformat/tls_mbedtls.c b/libavformat/tls_mbedtls.c
new file mode 100644
index 0000000..b42b76f
--- /dev/null
+++ b/libavformat/tls_mbedtls.c
@@ -0,0 +1,351 @@ 
+/*
+ * TLS/SSL Protocol
+ * Copyright (c) 2018 Thomas Volkert
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg 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.
+ *
+ * FFmpeg 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 FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <mbedtls/certs.h>
+#include <mbedtls/config.h>
+#include <mbedtls/ctr_drbg.h>
+#include <mbedtls/entropy.h>
+#include <mbedtls/net.h>
+#include <mbedtls/platform.h>
+#include <mbedtls/ssl.h>
+#include <mbedtls/x509_crt.h>
+
+#include "avformat.h"
+#include "internal.h"
+#include "url.h"
+#include "tls.h"
+#include "libavutil/parseutils.h"
+
+typedef struct TLSContext {
+    const AVClass *class;
+    TLSShared tls_shared;
+    mbedtls_ssl_context ssl_context;
+    mbedtls_ssl_config ssl_config;
+    mbedtls_entropy_context entropy_context;
+    mbedtls_ctr_drbg_context ctr_drbg_context;
+    mbedtls_x509_crt ca_cert;
+    mbedtls_x509_crt own_cert;
+    mbedtls_pk_context priv_key;
+    char *priv_key_pw;
+} TLSContext;
+
+#define OFFSET(x) offsetof(TLSContext, x)
+
+static int tls_close(URLContext *h)
+{
+    TLSContext *tls_ctx = h->priv_data;
+
+    mbedtls_ssl_close_notify(&tls_ctx->ssl_context);
+    mbedtls_pk_free(&tls_ctx->priv_key);
+    mbedtls_x509_crt_free(&tls_ctx->ca_cert);
+    mbedtls_x509_crt_free(&tls_ctx->own_cert);
+    mbedtls_ssl_free(&tls_ctx->ssl_context);
+    mbedtls_ssl_config_free(&tls_ctx->ssl_config);
+    mbedtls_ctr_drbg_free(&tls_ctx->ctr_drbg_context);
+    mbedtls_entropy_free(&tls_ctx->entropy_context);
+
+    return 0;
+}
+
+static int handle_transport_error(URLContext *h, const char* func_name, int react_on_eagain, int ret)
+{
+    switch (ret) {
+    case AVERROR(EAGAIN):
+        return react_on_eagain;
+    case AVERROR_EXIT:
+        return 0;
+    case AVERROR(EPIPE):
+    case AVERROR(ECONNRESET):
+        return MBEDTLS_ERR_NET_CONN_RESET;
+    default:
+        av_log(h, AV_LOG_ERROR, "%s returned 0x%x\n", func_name, ret);
+        errno = EIO;
+        return MBEDTLS_ERR_NET_SEND_FAILED;
+    }
+}
+
+static int mbedtls_send(void *ctx, const unsigned char *buf, size_t len)
+{
+    URLContext *h = (URLContext*) ctx;
+    int ret = ffurl_write(h, buf, len);
+    if (ret >= 0)
+        return ret;
+
+    if (h->max_packet_size && len > h->max_packet_size)
+        return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
+
+    return handle_transport_error(h, "ffurl_write", MBEDTLS_ERR_SSL_WANT_WRITE, ret);
+}
+
+static int mbedtls_recv(void *ctx, unsigned char *buf, size_t len)
+{
+    URLContext *h = (URLContext*) ctx;
+    int ret = ffurl_read(h, buf, len);
+    if (ret >= 0)
+        return ret;
+
+    if (h->max_packet_size && len > h->max_packet_size)
+        return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
+
+    return handle_transport_error(h, "ffurl_read", MBEDTLS_ERR_SSL_WANT_READ, ret);
+}
+
+static void handle_pk_parse_error(URLContext *h, int ret)
+{
+    switch (ret) {
+    case MBEDTLS_ERR_PK_FILE_IO_ERROR:
+        av_log(h, AV_LOG_ERROR, "Read of key file failed. Is it actually there, are the access permissions correct?\n");
+        break;
+    case MBEDTLS_ERR_PK_PASSWORD_REQUIRED:
+        av_log(h, AV_LOG_ERROR, "A password for the private key is missing.\n");
+        break;
+    case MBEDTLS_ERR_PK_PASSWORD_MISMATCH:
+        av_log(h, AV_LOG_ERROR, "The given password for the private key is wrong.\n");
+        break;
+    default:
+        av_log(h, AV_LOG_ERROR, "mbedtls_pk_parse_key returned -0x%x\n", -ret);
+        break;
+    }
+}
+
+static void handle_handshake_error(URLContext *h, int ret)
+{
+    switch (ret) {
+    case MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE:
+        av_log(h, AV_LOG_ERROR, "None of the common ciphersuites is usable. Was the local certificate correctly set?\n");
+        break;
+    case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE:
+        av_log(h, AV_LOG_ERROR, "A fatal alert message was received from the peer, has the peer a correct certificate?\n");
+        break;
+    case MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED:
+        av_log(h, AV_LOG_ERROR, "No CA chain is set, but required to operate. Was the CA correctly set?\n");
+        break;
+    case MBEDTLS_ERR_NET_CONN_RESET:
+        av_log(h, AV_LOG_ERROR, "TLS handshake was aborted by peer.\n");
+        break;
+    default:
+        av_log(h, AV_LOG_ERROR, "mbedtls_ssl_handshake returned -0x%x\n", -ret);
+        break;
+    }
+}
+
+static void parse_options(TLSContext *tls_ctxc, const char *uri)
+{
+    char buf[1024];
+    const char *p = strchr(uri, '?');
+    if (!p)
+        return;
+
+    if (!tls_ctxc->priv_key_pw && av_find_info_tag(buf, sizeof(buf), "key_password", p))
+        tls_ctxc->priv_key_pw = av_strdup(buf);
+}
+
+static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
+{
+    TLSContext *tls_ctx = h->priv_data;
+    TLSShared *shr = &tls_ctx->tls_shared;
+    uint32_t verify_res_flags;
+    int ret;
+
+    // parse additional options
+    parse_options(tls_ctx, uri);
+
+    if ((ret = ff_tls_open_underlying(shr, h, uri, options)) < 0)
+        goto fail;
+
+    mbedtls_ssl_init(&tls_ctx->ssl_context);
+    mbedtls_ssl_config_init(&tls_ctx->ssl_config);
+    mbedtls_entropy_init(&tls_ctx->entropy_context);
+    mbedtls_ctr_drbg_init(&tls_ctx->ctr_drbg_context);
+    mbedtls_x509_crt_init(&tls_ctx->ca_cert);
+    mbedtls_pk_init(&tls_ctx->priv_key);
+
+    // load trusted CA
+    if (shr->ca_file) {
+        if ((ret = mbedtls_x509_crt_parse_file(&tls_ctx->ca_cert, shr->ca_file)) != 0) {
+            av_log(h, AV_LOG_ERROR, "mbedtls_x509_crt_parse_file for CA cert returned %d\n", ret);
+            goto fail;
+        }
+    }
+
+    // load own certificate
+    if (shr->cert_file) {
+        if ((ret = mbedtls_x509_crt_parse_file(&tls_ctx->own_cert, shr->cert_file)) != 0) {
+            av_log(h, AV_LOG_ERROR, "mbedtls_x509_crt_parse_file for own cert returned %d\n", ret);
+            goto fail;
+        }
+    }
+
+    // load key file
+    if (shr->key_file) {
+        if ((ret = mbedtls_pk_parse_keyfile(&tls_ctx->priv_key,
+                                            shr->key_file,
+                                            tls_ctx->priv_key_pw)) != 0) {
+            handle_pk_parse_error(h, ret);
+            goto fail;
+        }
+    }
+
+    // seed the random number generator
+    if ((ret = mbedtls_ctr_drbg_seed(&tls_ctx->ctr_drbg_context,
+                                     mbedtls_entropy_func,
+                                     &tls_ctx->entropy_context,
+                                     NULL, 0)) != 0) {
+        av_log(h, AV_LOG_ERROR, "mbedtls_ctr_drbg_seed returned %d\n", ret);
+        goto fail;
+    }
+
+    if ((ret = mbedtls_ssl_config_defaults(&tls_ctx->ssl_config,
+                                           shr->listen ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT,
+                                           MBEDTLS_SSL_TRANSPORT_STREAM,
+                                           MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
+        av_log(h, AV_LOG_ERROR, "mbedtls_ssl_config_defaults returned %d\n", ret);
+        goto fail;
+    }
+
+    mbedtls_ssl_conf_authmode(&tls_ctx->ssl_config,
+                              shr->ca_file ? MBEDTLS_SSL_VERIFY_REQUIRED : MBEDTLS_SSL_VERIFY_NONE);
+    mbedtls_ssl_conf_rng(&tls_ctx->ssl_config, mbedtls_ctr_drbg_random, &tls_ctx->ctr_drbg_context);
+    mbedtls_ssl_conf_ca_chain(&tls_ctx->ssl_config, &tls_ctx->ca_cert, NULL);
+
+    // set own certificate and private key
+    if ((ret = mbedtls_ssl_conf_own_cert(&tls_ctx->ssl_config, &tls_ctx->own_cert, &tls_ctx->priv_key)) != 0) {
+        av_log(h, AV_LOG_ERROR, "mbedtls_ssl_conf_own_cert returned %d\n", ret);
+        goto fail;
+    }
+
+    if ((ret = mbedtls_ssl_setup(&tls_ctx->ssl_context, &tls_ctx->ssl_config)) != 0) {
+        av_log(h, AV_LOG_ERROR, "mbedtls_ssl_setup returned %d\n", ret);
+        goto fail;
+    }
+
+    if (!shr->listen && !shr->numerichost) {
+        if ((ret = mbedtls_ssl_set_hostname(&tls_ctx->ssl_context, shr->host)) != 0) {
+            av_log(h, AV_LOG_ERROR, "mbedtls_ssl_set_hostname returned %d\n", ret);
+            goto fail;
+        }
+    }
+
+    // set I/O functions to use FFmpeg internal code for transport layer
+    mbedtls_ssl_set_bio(&tls_ctx->ssl_context, shr->tcp, mbedtls_send, mbedtls_recv, NULL);
+
+    // ssl handshake
+    while ((ret = mbedtls_ssl_handshake(&tls_ctx->ssl_context)) != 0) {
+        if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
+            handle_handshake_error(h, ret);
+            goto fail;
+        }
+    }
+
+    if (shr->verify) {
+        // check the result of the certificate verification
+        if ((verify_res_flags = mbedtls_ssl_get_verify_result(&tls_ctx->ssl_context)) != 0) {
+            av_log(h, AV_LOG_ERROR, "mbedtls_ssl_get_verify_result reported problems "\
+                                    "with the certificate verification, returned flags: %u\n",
+                                    verify_res_flags);
+            if (verify_res_flags & MBEDTLS_X509_BADCERT_NOT_TRUSTED)
+                av_log(h, AV_LOG_ERROR, "The certificate is not correctly signed by the trusted CA.\n");
+            goto fail;
+        }
+    }
+
+    return 0;
+
+fail:
+    tls_close(h);
+    return AVERROR(EIO);
+}
+
+static int handle_tls_error(URLContext *h, const char* func_name, int ret)
+{
+    switch (ret) {
+    case MBEDTLS_ERR_SSL_WANT_READ:
+    case MBEDTLS_ERR_SSL_WANT_WRITE:
+        return AVERROR(EAGAIN);
+    case MBEDTLS_ERR_NET_SEND_FAILED:
+    case MBEDTLS_ERR_NET_RECV_FAILED:
+        return AVERROR(EIO);
+    case MBEDTLS_ERR_NET_CONN_RESET:
+    case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
+        av_log(h, AV_LOG_WARNING, "%s reported connection reset by peer\n", func_name);
+        return AVERROR_EOF;
+    default:
+        av_log(h, AV_LOG_ERROR, "%s returned -0x%x\n", func_name, -ret);
+        return AVERROR(EIO);
+    }
+}
+
+static int tls_read(URLContext *h, uint8_t *buf, int size)
+{
+    TLSContext *tls_ctx = h->priv_data;
+    int ret;
+
+    if ((ret = mbedtls_ssl_read(&tls_ctx->ssl_context, buf, size)) > 0) {
+        // return read length
+        return ret;
+    }
+
+    return handle_tls_error(h, "mbedtls_ssl_read", ret);
+}
+
+static int tls_write(URLContext *h, const uint8_t *buf, int size)
+{
+    TLSContext *tls_ctx = h->priv_data;
+    int ret;
+
+    if ((ret = mbedtls_ssl_write(&tls_ctx->ssl_context, buf, size)) > 0) {
+        // return written length
+        return ret;
+    }
+
+    return handle_tls_error(h, "mbedtls_ssl_write", ret);
+}
+
+static int tls_get_file_handle(URLContext *h)
+{
+    TLSContext *c = h->priv_data;
+    return ffurl_get_file_handle(c->tls_shared.tcp);
+}
+
+static const AVOption options[] = {
+    TLS_COMMON_OPTIONS(TLSContext, tls_shared), \
+    {"key_password", "Password for the private key file", OFFSET(priv_key_pw),  AV_OPT_TYPE_STRING, .flags = TLS_OPTFL }, \
+    { NULL }
+};
+
+static const AVClass tls_class = {
+    .class_name = "tls",
+    .item_name  = av_default_item_name,
+    .option     = options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+const URLProtocol ff_tls_protocol = {
+    .name           = "tls",
+    .url_open2      = tls_open,
+    .url_read       = tls_read,
+    .url_write      = tls_write,
+    .url_close      = tls_close,
+    .url_get_file_handle = tls_get_file_handle,
+    .priv_data_size = sizeof(TLSContext),
+    .flags          = URL_PROTOCOL_FLAG_NETWORK,
+    .priv_data_class = &tls_class,
+};
diff --git a/libavformat/version.h b/libavformat/version.h
index dced716..e9b94cc 100644
--- a/libavformat/version.h
+++ b/libavformat/version.h
@@ -32,7 +32,7 @@ 
 // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium)
 // Also please add any ticket numbers that you believe might be affected here
 #define LIBAVFORMAT_VERSION_MAJOR  58
-#define LIBAVFORMAT_VERSION_MINOR  13
+#define LIBAVFORMAT_VERSION_MINOR  14
 #define LIBAVFORMAT_VERSION_MICRO 100
 
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \