3 * Copyright (c) 2018 Thomas Volkert
5 * This file is part of FFmpeg.
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #include <mbedtls/version.h>
23 #include <mbedtls/ctr_drbg.h>
24 #include <mbedtls/entropy.h>
25 #include <mbedtls/net_sockets.h>
26 #include <mbedtls/platform.h>
27 #include <mbedtls/ssl.h>
28 #include <mbedtls/x509_crt.h>
29 #include <mbedtls/debug.h>
30 #ifdef MBEDTLS_PSA_CRYPTO_C
31 #include <psa/crypto.h>
38 #include "libavutil/mem.h"
39 #include "libavutil/parseutils.h"
40 #include "libavutil/avstring.h"
42 typedef struct TLSContext
{
44 mbedtls_ssl_context ssl_context
;
45 mbedtls_ssl_config ssl_config
;
46 mbedtls_entropy_context entropy_context
;
47 mbedtls_ctr_drbg_context ctr_drbg_context
;
48 mbedtls_x509_crt ca_cert
;
49 mbedtls_x509_crt own_cert
;
50 mbedtls_pk_context priv_key
;
54 #define OFFSET(x) offsetof(TLSContext, x)
56 static int tls_close(URLContext
*h
)
58 TLSContext
*tls_ctx
= h
->priv_data
;
60 mbedtls_ssl_close_notify(&tls_ctx
->ssl_context
);
61 mbedtls_pk_free(&tls_ctx
->priv_key
);
62 mbedtls_x509_crt_free(&tls_ctx
->ca_cert
);
63 mbedtls_x509_crt_free(&tls_ctx
->own_cert
);
64 mbedtls_ssl_free(&tls_ctx
->ssl_context
);
65 mbedtls_ssl_config_free(&tls_ctx
->ssl_config
);
66 mbedtls_ctr_drbg_free(&tls_ctx
->ctr_drbg_context
);
67 mbedtls_entropy_free(&tls_ctx
->entropy_context
);
69 ffurl_closep(&tls_ctx
->tls_shared
.tcp
);
73 static int handle_transport_error(URLContext
*h
, const char* func_name
, int react_on_eagain
, int ret
)
77 return react_on_eagain
;
81 case AVERROR(ECONNRESET
):
82 return MBEDTLS_ERR_NET_CONN_RESET
;
84 av_log(h
, AV_LOG_ERROR
, "%s returned 0x%x\n", func_name
, ret
);
86 return MBEDTLS_ERR_NET_SEND_FAILED
;
90 static int mbedtls_send(void *ctx
, const unsigned char *buf
, size_t len
)
92 URLContext
*h
= (URLContext
*) ctx
;
93 int ret
= ffurl_write(h
, buf
, len
);
97 if (h
->max_packet_size
&& len
> h
->max_packet_size
)
98 return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL
;
100 return handle_transport_error(h
, "ffurl_write", MBEDTLS_ERR_SSL_WANT_WRITE
, ret
);
103 static int mbedtls_recv(void *ctx
, unsigned char *buf
, size_t len
)
105 URLContext
*h
= (URLContext
*) ctx
;
106 int ret
= ffurl_read(h
, buf
, len
);
110 if (h
->max_packet_size
&& len
> h
->max_packet_size
)
111 return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL
;
113 return handle_transport_error(h
, "ffurl_read", MBEDTLS_ERR_SSL_WANT_READ
, ret
);
116 static void mbedtls_debug(void *ctx
, int lvl
, const char *file
, int line
, const char *msg
)
118 URLContext
*h
= (URLContext
*) ctx
;
119 int av_lvl
= lvl
>= 4 ? AV_LOG_TRACE
: AV_LOG_DEBUG
;
120 av_log(h
, av_lvl
, "%s:%d: %s", av_basename(file
), line
, msg
);
123 static void handle_pk_parse_error(URLContext
*h
, int ret
)
126 case MBEDTLS_ERR_PK_FILE_IO_ERROR
:
127 av_log(h
, AV_LOG_ERROR
, "Read of key file failed. Is it actually there, are the access permissions correct?\n");
129 case MBEDTLS_ERR_PK_PASSWORD_REQUIRED
:
130 av_log(h
, AV_LOG_ERROR
, "A password for the private key is missing.\n");
132 case MBEDTLS_ERR_PK_PASSWORD_MISMATCH
:
133 av_log(h
, AV_LOG_ERROR
, "The given password for the private key is wrong.\n");
136 av_log(h
, AV_LOG_ERROR
, "mbedtls_pk_parse_key returned -0x%x\n", -ret
);
141 static void handle_handshake_error(URLContext
*h
, int ret
)
144 #if MBEDTLS_VERSION_MAJOR < 3
145 case MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE
:
146 av_log(h
, AV_LOG_ERROR
, "None of the common ciphersuites is usable. Was the local certificate correctly set?\n");
149 case MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE
:
150 av_log(h
, AV_LOG_ERROR
, "TLS handshake failed.\n");
152 case MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION
:
153 av_log(h
, AV_LOG_ERROR
, "TLS protocol version mismatch.\n");
156 case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE
:
157 av_log(h
, AV_LOG_ERROR
, "A fatal alert message was received from the peer, has the peer a correct certificate?\n");
159 case MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED
:
160 av_log(h
, AV_LOG_ERROR
, "No CA chain is set, but required to operate. Was the CA correctly set?\n");
162 case MBEDTLS_ERR_SSL_INTERNAL_ERROR
:
163 av_log(h
, AV_LOG_ERROR
, "Internal error encountered.\n");
165 case MBEDTLS_ERR_NET_CONN_RESET
:
166 av_log(h
, AV_LOG_ERROR
, "TLS handshake was aborted by peer.\n");
168 case MBEDTLS_ERR_X509_CERT_VERIFY_FAILED
:
169 av_log(h
, AV_LOG_ERROR
, "Certificate verification failed.\n");
172 av_log(h
, AV_LOG_ERROR
, "mbedtls_ssl_handshake returned -0x%x\n", -ret
);
177 static int tls_open(URLContext
*h
, const char *uri
, int flags
, AVDictionary
**options
)
179 TLSContext
*tls_ctx
= h
->priv_data
;
180 TLSShared
*shr
= &tls_ctx
->tls_shared
;
181 uint32_t verify_res_flags
;
184 if ((ret
= ff_tls_open_underlying(shr
, h
, uri
, options
)) < 0)
187 #ifdef MBEDTLS_PSA_CRYPTO_C
188 if ((ret
= psa_crypto_init()) != PSA_SUCCESS
) {
189 av_log(h
, AV_LOG_ERROR
, "psa_crypto_init returned %d\n", ret
);
194 mbedtls_ssl_init(&tls_ctx
->ssl_context
);
195 mbedtls_ssl_config_init(&tls_ctx
->ssl_config
);
196 mbedtls_entropy_init(&tls_ctx
->entropy_context
);
197 mbedtls_ctr_drbg_init(&tls_ctx
->ctr_drbg_context
);
198 mbedtls_x509_crt_init(&tls_ctx
->ca_cert
);
199 mbedtls_pk_init(&tls_ctx
->priv_key
);
201 if (av_log_get_level() >= AV_LOG_DEBUG
) {
202 mbedtls_ssl_conf_dbg(&tls_ctx
->ssl_config
, mbedtls_debug
, shr
->tcp
);
204 * Note: we can't call mbedtls_debug_set_threshold() here because
205 * it's global state. The user is thus expected to manage this.
211 if ((ret
= mbedtls_x509_crt_parse_file(&tls_ctx
->ca_cert
, shr
->ca_file
)) != 0) {
212 av_log(h
, AV_LOG_ERROR
, "mbedtls_x509_crt_parse_file for CA cert returned %d\n", ret
);
217 // load own certificate
218 if (shr
->cert_file
) {
219 if ((ret
= mbedtls_x509_crt_parse_file(&tls_ctx
->own_cert
, shr
->cert_file
)) != 0) {
220 av_log(h
, AV_LOG_ERROR
, "mbedtls_x509_crt_parse_file for own cert returned %d\n", ret
);
225 // seed the random number generator
226 if ((ret
= mbedtls_ctr_drbg_seed(&tls_ctx
->ctr_drbg_context
,
227 mbedtls_entropy_func
,
228 &tls_ctx
->entropy_context
,
230 av_log(h
, AV_LOG_ERROR
, "mbedtls_ctr_drbg_seed returned %d\n", ret
);
236 if ((ret
= mbedtls_pk_parse_keyfile(&tls_ctx
->priv_key
,
239 #if MBEDTLS_VERSION_MAJOR >= 3
240 , mbedtls_ctr_drbg_random
,
241 &tls_ctx
->ctr_drbg_context
244 handle_pk_parse_error(h
, ret
);
249 if ((ret
= mbedtls_ssl_config_defaults(&tls_ctx
->ssl_config
,
250 shr
->listen
? MBEDTLS_SSL_IS_SERVER
: MBEDTLS_SSL_IS_CLIENT
,
251 MBEDTLS_SSL_TRANSPORT_STREAM
,
252 MBEDTLS_SSL_PRESET_DEFAULT
)) != 0) {
253 av_log(h
, AV_LOG_ERROR
, "mbedtls_ssl_config_defaults returned %d\n", ret
);
257 #ifdef MBEDTLS_SSL_PROTO_TLS1_3
258 // this version does not allow disabling certificate verification with TLSv1.3 (yes, really).
259 if (mbedtls_version_get_number() == 0x03060000 && !shr
->verify
) {
260 av_log(h
, AV_LOG_INFO
, "Forcing TLSv1.2 because certificate verification is disabled\n");
261 mbedtls_ssl_conf_max_tls_version(&tls_ctx
->ssl_config
, MBEDTLS_SSL_VERSION_TLS1_2
);
265 // not VERIFY_REQUIRED because we manually check after handshake
266 mbedtls_ssl_conf_authmode(&tls_ctx
->ssl_config
,
267 shr
->verify
? MBEDTLS_SSL_VERIFY_OPTIONAL
: MBEDTLS_SSL_VERIFY_NONE
);
268 mbedtls_ssl_conf_rng(&tls_ctx
->ssl_config
, mbedtls_ctr_drbg_random
, &tls_ctx
->ctr_drbg_context
);
269 mbedtls_ssl_conf_ca_chain(&tls_ctx
->ssl_config
, &tls_ctx
->ca_cert
, NULL
);
271 // set own certificate and private key
272 if ((ret
= mbedtls_ssl_conf_own_cert(&tls_ctx
->ssl_config
, &tls_ctx
->own_cert
, &tls_ctx
->priv_key
)) != 0) {
273 av_log(h
, AV_LOG_ERROR
, "mbedtls_ssl_conf_own_cert returned %d\n", ret
);
277 if ((ret
= mbedtls_ssl_setup(&tls_ctx
->ssl_context
, &tls_ctx
->ssl_config
)) != 0) {
278 av_log(h
, AV_LOG_ERROR
, "mbedtls_ssl_setup returned %d\n", ret
);
282 if (!shr
->listen
&& !shr
->numerichost
) {
283 if ((ret
= mbedtls_ssl_set_hostname(&tls_ctx
->ssl_context
, shr
->host
)) != 0) {
284 av_log(h
, AV_LOG_ERROR
, "mbedtls_ssl_set_hostname returned %d\n", ret
);
289 // set I/O functions to use FFmpeg internal code for transport layer
290 mbedtls_ssl_set_bio(&tls_ctx
->ssl_context
, shr
->tcp
, mbedtls_send
, mbedtls_recv
, NULL
);
293 while ((ret
= mbedtls_ssl_handshake(&tls_ctx
->ssl_context
)) != 0) {
294 if (ret
!= MBEDTLS_ERR_SSL_WANT_READ
&& ret
!= MBEDTLS_ERR_SSL_WANT_WRITE
) {
295 handle_handshake_error(h
, ret
);
301 // check the result of the certificate verification
302 if ((verify_res_flags
= mbedtls_ssl_get_verify_result(&tls_ctx
->ssl_context
)) != 0) {
303 av_log(h
, AV_LOG_ERROR
, "mbedtls_ssl_get_verify_result reported problems "\
304 "with the certificate verification, returned flags: %u\n",
306 if (verify_res_flags
& MBEDTLS_X509_BADCERT_NOT_TRUSTED
)
307 av_log(h
, AV_LOG_ERROR
, "The certificate is not correctly signed by the trusted CA.\n");
319 static int handle_tls_error(URLContext
*h
, const char* func_name
, int ret
)
322 case MBEDTLS_ERR_SSL_WANT_READ
:
323 case MBEDTLS_ERR_SSL_WANT_WRITE
:
324 #ifdef MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET
325 case MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET
:
327 return AVERROR(EAGAIN
);
328 case MBEDTLS_ERR_NET_SEND_FAILED
:
329 case MBEDTLS_ERR_NET_RECV_FAILED
:
331 case MBEDTLS_ERR_NET_CONN_RESET
:
332 case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY
:
333 av_log(h
, AV_LOG_WARNING
, "%s reported connection reset by peer\n", func_name
);
336 av_log(h
, AV_LOG_ERROR
, "%s returned -0x%x\n", func_name
, -ret
);
341 static int tls_read(URLContext
*h
, uint8_t *buf
, int size
)
343 TLSContext
*tls_ctx
= h
->priv_data
;
346 tls_ctx
->tls_shared
.tcp
->flags
&= ~AVIO_FLAG_NONBLOCK
;
347 tls_ctx
->tls_shared
.tcp
->flags
|= h
->flags
& AVIO_FLAG_NONBLOCK
;
348 if ((ret
= mbedtls_ssl_read(&tls_ctx
->ssl_context
, buf
, size
)) > 0) {
349 // return read length
353 return handle_tls_error(h
, "mbedtls_ssl_read", ret
);
356 static int tls_write(URLContext
*h
, const uint8_t *buf
, int size
)
358 TLSContext
*tls_ctx
= h
->priv_data
;
361 tls_ctx
->tls_shared
.tcp
->flags
&= ~AVIO_FLAG_NONBLOCK
;
362 tls_ctx
->tls_shared
.tcp
->flags
|= h
->flags
& AVIO_FLAG_NONBLOCK
;
363 if ((ret
= mbedtls_ssl_write(&tls_ctx
->ssl_context
, buf
, size
)) > 0) {
364 // return written length
368 return handle_tls_error(h
, "mbedtls_ssl_write", ret
);
371 static int tls_get_file_handle(URLContext
*h
)
373 TLSContext
*c
= h
->priv_data
;
374 return ffurl_get_file_handle(c
->tls_shared
.tcp
);
377 static int tls_get_short_seek(URLContext
*h
)
379 TLSContext
*s
= h
->priv_data
;
380 return ffurl_get_short_seek(s
->tls_shared
.tcp
);
383 static const AVOption options
[] = {
384 TLS_COMMON_OPTIONS(TLSContext
, tls_shared
), \
385 {"key_password", "Password for the private key file", OFFSET(priv_key_pw
), AV_OPT_TYPE_STRING
, .flags
= TLS_OPTFL
}, \
389 static const AVClass tls_class
= {
391 .item_name
= av_default_item_name
,
393 .version
= LIBAVUTIL_VERSION_INT
,
396 const URLProtocol ff_tls_protocol
= {
398 .url_open2
= tls_open
,
399 .url_read
= tls_read
,
400 .url_write
= tls_write
,
401 .url_close
= tls_close
,
402 .url_get_file_handle
= tls_get_file_handle
,
403 .url_get_short_seek
= tls_get_short_seek
,
404 .priv_data_size
= sizeof(TLSContext
),
405 .flags
= URL_PROTOCOL_FLAG_NETWORK
,
406 .priv_data_class
= &tls_class
,