FFmpeg
Loading...
Searching...
No Matches
tls_openssl.c
Go to the documentation of this file.
1/*
2 * TLS/DTLS/SSL Protocol
3 * Copyright (c) 2011 Martin Storsjo
4 * Copyright (c) 2025 Jack Lau
5 *
6 * This file is part of FFmpeg.
7 *
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23#include "config_components.h"
24
25#include "network.h"
26#include "os_support.h"
27#include "libavutil/time.h"
29#include "url.h"
30#include "tls.h"
31#include "libavutil/opt.h"
32
33#include <openssl/bio.h>
34#include <openssl/ssl.h>
35#include <openssl/err.h>
36#include <openssl/x509v3.h>
37#if HAVE_SYS_TIME_H
38#include <sys/time.h>
39#endif
40#include <string.h>
41
42#define DTLS_HANDSHAKE_TIMEOUT_US 30000000
43/**
44 * Convert an EVP_PKEY to a PEM string.
45 */
46static int pkey_to_pem_string(EVP_PKEY *pkey, char *out, size_t out_sz)
47{
48 BIO *mem = NULL;
49 size_t read_bytes = 0;
50
51 if (!pkey || !out || !out_sz)
52 goto done;
53
54 if (!(mem = BIO_new(BIO_s_mem())))
55 goto done;
56
57 if (!PEM_write_bio_PrivateKey(mem, pkey, NULL, NULL, 0, NULL, NULL))
58 goto done;
59
60 if (!BIO_read_ex(mem, out, out_sz - 1, &read_bytes))
61 goto done;
62
63done:
64 BIO_free(mem);
65 if (out && out_sz)
66 out[read_bytes] = '\0';
67 return read_bytes;
68}
69
70/**
71 * Convert an X509 certificate to a PEM string.
72 */
73static int cert_to_pem_string(X509 *cert, char *out, size_t out_sz)
74{
75 BIO *mem = NULL;
76 size_t read_bytes = 0;
77
78 if (!cert || !out || !out_sz)
79 goto done;
80
81 if (!(mem = BIO_new(BIO_s_mem())))
82 goto done;
83
84 if (!PEM_write_bio_X509(mem, cert))
85 goto done;
86
87 if (!BIO_read_ex(mem, out, out_sz - 1, &read_bytes))
88 goto done;
89
90done:
91 BIO_free(mem);
92 if (out && out_sz)
93 out[read_bytes] = '\0';
94 return read_bytes;
95}
96
97
98/**
99 * Generate a SHA-256 fingerprint of an X.509 certificate.
100 */
101static int x509_fingerprint(X509 *cert, char **fingerprint)
102{
103 unsigned char md[EVP_MAX_MD_SIZE];
104 int n = 0;
105 AVBPrint buf;
106
107 if (X509_digest(cert, EVP_sha256(), md, &n) != 1) {
108 av_log(NULL, AV_LOG_ERROR, "TLS: Failed to generate fingerprint, %s\n",
109 ERR_error_string(ERR_get_error(), NULL));
110 return AVERROR(EINVAL);
111 }
112
113 av_bprint_init(&buf, n*3, n*3);
114
115 for (int i = 0; i < n - 1; i++)
116 av_bprintf(&buf, "%02X:", md[i]);
117 av_bprintf(&buf, "%02X", md[n - 1]);
118
119 return av_bprint_finalize(&buf, fingerprint);
120}
121
122int ff_ssl_read_key_cert(char *key_url, char *cert_url, char *key_buf, size_t key_sz, char *cert_buf, size_t cert_sz, char **fingerprint)
123{
124 int ret = 0;
125 BIO *key_b = NULL, *cert_b = NULL;
126 AVBPrint key_bp, cert_bp;
127 EVP_PKEY *pkey = NULL;
128 X509 *cert = NULL;
129
130 /* To prevent a crash during cleanup, always initialize it. */
133
134 /* Read key file. */
135 ret = ff_url_read_all(key_url, &key_bp);
136 if (ret < 0) {
137 av_log(NULL, AV_LOG_ERROR, "TLS: Failed to open key file %s\n", key_url);
138 goto end;
139 }
140
141 if (!(key_b = BIO_new(BIO_s_mem()))) {
142 ret = AVERROR(ENOMEM);
143 goto end;
144 }
145
146 BIO_write(key_b, key_bp.str, key_bp.len);
147 pkey = PEM_read_bio_PrivateKey(key_b, NULL, NULL, NULL);
148 if (!pkey) {
149 av_log(NULL, AV_LOG_ERROR, "TLS: Failed to read private key from %s\n", key_url);
150 ret = AVERROR(EIO);
151 goto end;
152 }
153
154 /* Read certificate. */
155 ret = ff_url_read_all(cert_url, &cert_bp);
156 if (ret < 0) {
157 av_log(NULL, AV_LOG_ERROR, "TLS: Failed to open cert file %s\n", cert_url);
158 goto end;
159 }
160
161 if (!(cert_b = BIO_new(BIO_s_mem()))) {
162 ret = AVERROR(ENOMEM);
163 goto end;
164 }
165
166 BIO_write(cert_b, cert_bp.str, cert_bp.len);
167 cert = PEM_read_bio_X509(cert_b, NULL, NULL, NULL);
168 if (!cert) {
169 av_log(NULL, AV_LOG_ERROR, "TLS: Failed to read certificate from %s\n", cert_url);
170 ret = AVERROR(EIO);
171 goto end;
172 }
173
174 pkey_to_pem_string(pkey, key_buf, key_sz);
175 cert_to_pem_string(cert, cert_buf, cert_sz);
176
177 ret = x509_fingerprint(cert, fingerprint);
178 if (ret < 0)
179 av_log(NULL, AV_LOG_ERROR, "TLS: Failed to generate fingerprint from %s\n", cert_url);
180
181end:
182 BIO_free(key_b);
183 av_bprint_finalize(&key_bp, NULL);
184 BIO_free(cert_b);
185 av_bprint_finalize(&cert_bp, NULL);
186 EVP_PKEY_free(pkey);
187 X509_free(cert);
188 return ret;
189}
190
191static int openssl_gen_private_key(EVP_PKEY **pkey)
192{
193 int ret = 0;
194
195 /**
196 * Note that secp256r1 in openssl is called NID_X9_62_prime256v1 or prime256v1 in string,
197 * not NID_secp256k1 or secp256k1 in string.
198 *
199 * TODO: Should choose the curves in ClientHello.supported_groups, for example:
200 * Supported Group: x25519 (0x001d)
201 * Supported Group: secp256r1 (0x0017)
202 * Supported Group: secp384r1 (0x0018)
203 */
204#if OPENSSL_VERSION_NUMBER < 0x30000000L /* OpenSSL 3.0 */
205 EC_GROUP *ecgroup = NULL;
206 EC_KEY *eckey = NULL;
207 int curve = NID_X9_62_prime256v1;
208#else
209 const char *curve = SN_X9_62_prime256v1;
210#endif
211
212#if OPENSSL_VERSION_NUMBER < 0x30000000L /* OpenSSL 3.0 */
213 *pkey = EVP_PKEY_new();
214 if (!*pkey)
215 return AVERROR(ENOMEM);
216
217 eckey = EC_KEY_new();
218 if (!eckey) {
219 EVP_PKEY_free(*pkey);
220 *pkey = NULL;
221 return AVERROR(ENOMEM);
222 }
223
224 ecgroup = EC_GROUP_new_by_curve_name(curve);
225 if (!ecgroup) {
226 av_log(NULL, AV_LOG_ERROR, "TLS: Create EC group by curve=%d failed, %s", curve, ERR_error_string(ERR_get_error(), NULL));
227 goto einval_end;
228 }
229
230 if (EC_KEY_set_group(eckey, ecgroup) != 1) {
231 av_log(NULL, AV_LOG_ERROR, "TLS: Generate private key, EC_KEY_set_group failed, %s\n", ERR_error_string(ERR_get_error(), NULL));
232 goto einval_end;
233 }
234
235 if (EC_KEY_generate_key(eckey) != 1) {
236 av_log(NULL, AV_LOG_ERROR, "TLS: Generate private key, EC_KEY_generate_key failed, %s\n", ERR_error_string(ERR_get_error(), NULL));
237 goto einval_end;
238 }
239
240 if (EVP_PKEY_set1_EC_KEY(*pkey, eckey) != 1) {
241 av_log(NULL, AV_LOG_ERROR, "TLS: Generate private key, EVP_PKEY_set1_EC_KEY failed, %s\n", ERR_error_string(ERR_get_error(), NULL));
242 goto einval_end;
243 }
244#else
245 *pkey = EVP_EC_gen(curve);
246 if (!*pkey) {
247 av_log(NULL, AV_LOG_ERROR, "TLS: Generate private key, EVP_EC_gen curve=%s failed, %s\n", curve, ERR_error_string(ERR_get_error(), NULL));
248 goto einval_end;
249 }
250#endif
251 goto end;
252
253einval_end:
254 ret = AVERROR(EINVAL);
255 EVP_PKEY_free(*pkey);
256 *pkey = NULL;
257end:
258#if OPENSSL_VERSION_NUMBER < 0x30000000L /* OpenSSL 3.0 */
259 EC_GROUP_free(ecgroup);
260 EC_KEY_free(eckey);
261#endif
262 return ret;
263}
264
265static int openssl_gen_certificate(EVP_PKEY *pkey, X509 **cert, char **fingerprint)
266{
267 int ret = 0, expire_day;
268 uint64_t serial;
269 const char *aor = "lavf";
270 X509_NAME* subject = NULL;
271
272 *cert= X509_new();
273 if (!*cert) {
274 goto enomem_end;
275 }
276
277 subject = X509_NAME_new();
278 if (!subject) {
279 goto enomem_end;
280 }
281
282 serial = av_get_random_seed();
283 if (ASN1_INTEGER_set_uint64(X509_get_serialNumber(*cert), serial) != 1) {
284 av_log(NULL, AV_LOG_ERROR, "TLS: Failed to set serial, %s\n", ERR_error_string(ERR_get_error(), NULL));
285 goto einval_end;
286 }
287
288 if (X509_NAME_add_entry_by_txt(subject, "CN", MBSTRING_ASC, aor, strlen(aor), -1, 0) != 1) {
289 av_log(NULL, AV_LOG_ERROR, "TLS: Failed to set CN, %s\n", ERR_error_string(ERR_get_error(), NULL));
290 goto einval_end;
291 }
292
293 if (X509_set_issuer_name(*cert, subject) != 1) {
294 av_log(NULL, AV_LOG_ERROR, "TLS: Failed to set issuer, %s\n", ERR_error_string(ERR_get_error(), NULL));
295 goto einval_end;
296 }
297 if (X509_set_subject_name(*cert, subject) != 1) {
298 av_log(NULL, AV_LOG_ERROR, "TLS: Failed to set subject name, %s\n", ERR_error_string(ERR_get_error(), NULL));
299 goto einval_end;
300 }
301
302 expire_day = 365;
303 if (!X509_gmtime_adj(X509_get_notBefore(*cert), 0)) {
304 av_log(NULL, AV_LOG_ERROR, "TLS: Failed to set notBefore, %s\n", ERR_error_string(ERR_get_error(), NULL));
305 goto einval_end;
306 }
307 if (!X509_gmtime_adj(X509_get_notAfter(*cert), 60*60*24*expire_day)) {
308 av_log(NULL, AV_LOG_ERROR, "TLS: Failed to set notAfter, %s\n", ERR_error_string(ERR_get_error(), NULL));
309 goto einval_end;
310 }
311
312 if (X509_set_version(*cert, 2) != 1) {
313 av_log(NULL, AV_LOG_ERROR, "TLS: Failed to set version, %s\n", ERR_error_string(ERR_get_error(), NULL));
314 goto einval_end;
315 }
316
317 if (X509_set_pubkey(*cert, pkey) != 1) {
318 av_log(NULL, AV_LOG_ERROR, "TLS: Failed to set public key, %s\n", ERR_error_string(ERR_get_error(), NULL));
319 goto einval_end;
320 }
321
322 if (!X509_sign(*cert, pkey, EVP_sha256())) {
323 av_log(NULL, AV_LOG_ERROR, "TLS: Failed to sign certificate, %s\n", ERR_error_string(ERR_get_error(), NULL));
324 goto einval_end;
325 }
326
327 ret = x509_fingerprint(*cert, fingerprint);
328 if (ret < 0)
329 goto end;
330
331 goto end;
332enomem_end:
333 ret = AVERROR(ENOMEM);
334 goto end;
335einval_end:
336 ret = AVERROR(EINVAL);
337end:
338 if (ret) {
339 X509_free(*cert);
340 *cert = NULL;
341 }
342 X509_NAME_free(subject);
343 return ret;
344}
345
346int ff_ssl_gen_key_cert(char *key_buf, size_t key_sz, char *cert_buf, size_t cert_sz, char **fingerprint)
347{
348 int ret = 0;
349 EVP_PKEY *pkey = NULL;
350 X509 *cert = NULL;
351
352 ret = openssl_gen_private_key(&pkey);
353 if (ret < 0) goto error;
354
355 ret = openssl_gen_certificate(pkey, &cert, fingerprint);
356 if (ret < 0) goto error;
357
358 pkey_to_pem_string(pkey, key_buf, key_sz);
359 cert_to_pem_string(cert, cert_buf, cert_sz);
360
361error:
362 X509_free(cert);
363 EVP_PKEY_free(pkey);
364 return ret;
365}
366
367
368/**
369 * Deserialize a PEM-encoded private or public key from a NUL-terminated C string.
370 *
371 * @param pem_str The PEM text, e.g.
372 * "-----BEGIN PRIVATE KEY-----\n…\n-----END PRIVATE KEY-----\n"
373 * @param is_priv If non-zero, parse as a PRIVATE key; otherwise, parse as a PUBLIC key.
374 * @return EVP_PKEY* on success (must EVP_PKEY_free()), or NULL on error.
375 */
376static EVP_PKEY *pkey_from_pem_string(const char *pem_str, int is_priv)
377{
378 BIO *mem = BIO_new_mem_buf(pem_str, -1);
379 if (!mem) {
380 av_log(NULL, AV_LOG_ERROR, "BIO_new_mem_buf failed\n");
381 return NULL;
382 }
383
384 EVP_PKEY *pkey = NULL;
385 if (is_priv) {
386 pkey = PEM_read_bio_PrivateKey(mem, NULL, NULL, NULL);
387 } else {
388 pkey = PEM_read_bio_PUBKEY(mem, NULL, NULL, NULL);
389 }
390
391 if (!pkey)
392 av_log(NULL, AV_LOG_ERROR, "Failed to parse %s key from string\n",
393 is_priv ? "private" : "public");
394
395 BIO_free(mem);
396 return pkey;
397}
398
399/**
400 * Deserialize a PEM-encoded certificate from a NUL-terminated C string.
401 *
402 * @param pem_str The PEM text, e.g.
403 * "-----BEGIN CERTIFICATE-----\n…\n-----END CERTIFICATE-----\n"
404 * @return X509* on success (must X509_free()), or NULL on error.
405 */
406static X509 *cert_from_pem_string(const char *pem_str)
407{
408 X509 *cert = NULL;
409 BIO *mem = BIO_new_mem_buf(pem_str, -1);
410 if (!mem) {
411 av_log(NULL, AV_LOG_ERROR, "BIO_new_mem_buf failed\n");
412 return NULL;
413 }
414
415 cert = PEM_read_bio_X509(mem, NULL, NULL, NULL);
416 if (!cert)
417 av_log(NULL, AV_LOG_ERROR, "Failed to parse certificate from string\n");
418
419 BIO_free(mem);
420 return cert;
421}
422
423
424typedef struct TLSContext {
425 TLSShared tls_shared;
426 SSL_CTX *ctx;
427 SSL *ssl;
429 BIO_METHOD* url_bio_method;
430 int io_err;
431 char error_message[256];
433 socklen_t dest_addr_len;
434} TLSContext;
435
436/**
437 * Retrieves the error message for the latest OpenSSL error.
438 *
439 * This function retrieves the error code from the thread's error queue, converts it
440 * to a human-readable string, and stores it in the TLSContext's error_message field.
441 * The error queue is then cleared using ERR_clear_error().
442 */
443static const char* openssl_get_error(TLSContext *c)
444{
445 int r2 = ERR_get_error();
446 if (r2) {
447 ERR_error_string_n(r2, c->error_message, sizeof(c->error_message));
448 } else
449 c->error_message[0] = '\0';
450
451 ERR_clear_error();
452 return c->error_message;
453}
454
456{
457 TLSContext *c = h->priv_data;
458 TLSShared *s = &c->tls_shared;
459
460 if (s->is_dtls)
461 c->tls_shared.udp = sock;
462 else
463 c->tls_shared.tcp = sock;
464
465 return 0;
466}
467
468int ff_dtls_export_materials(URLContext *h, char *dtls_srtp_materials, size_t materials_sz)
469{
470 int ret = 0;
471 const char* dst = "EXTRACTOR-dtls_srtp";
472 TLSContext *c = h->priv_data;
473
474 ret = SSL_export_keying_material(c->ssl, dtls_srtp_materials, materials_sz,
475 dst, strlen(dst), NULL, 0, 0);
476 if (!ret) {
477 av_log(c, AV_LOG_ERROR, "Failed to export SRTP material, %s\n", openssl_get_error(c));
478 return -1;
479 }
480 return 0;
481}
482
483static int print_ssl_error(URLContext *h, int ret)
484{
485 TLSContext *c = h->priv_data;
486 int printed = 0, e, averr = AVERROR(EIO);
487 int err = SSL_get_error(c->ssl, ret);
488 if (h->flags & AVIO_FLAG_NONBLOCK) {
489 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
490 return AVERROR(EAGAIN);
491 }
492 switch (err) {
493 case SSL_ERROR_SSL:
494 case SSL_ERROR_SYSCALL:
495 c->do_shutdown = 0;
496 break;
497 }
498 while ((e = ERR_get_error()) != 0) {
499 av_log(h, AV_LOG_ERROR, "%s\n", ERR_error_string(e, NULL));
500 printed = 1;
501 }
502 if (c->io_err) {
503 av_log(h, AV_LOG_ERROR, "IO error: %s\n", av_err2str(c->io_err));
504 printed = 1;
505 averr = c->io_err;
506 c->io_err = 0;
507 }
508 if (!printed)
509 av_log(h, AV_LOG_ERROR, "Unknown error\n");
510 return averr;
511}
512
514{
515 TLSContext *c = h->priv_data;
516 if (c->ssl) {
517 if (c->do_shutdown)
518 SSL_shutdown(c->ssl);
519 SSL_free(c->ssl);
520 }
521 if (c->ctx)
522 SSL_CTX_free(c->ctx);
523 if (!c->tls_shared.external_sock)
524 ffurl_closep(c->tls_shared.is_dtls ? &c->tls_shared.udp : &c->tls_shared.tcp);
525 if (c->url_bio_method)
526 BIO_meth_free(c->url_bio_method);
527 return 0;
528}
529
530static int url_bio_create(BIO *b)
531{
532 BIO_set_init(b, 1);
533 BIO_set_data(b, NULL);
534 BIO_set_flags(b, 0);
535 return 1;
536}
537
538static int url_bio_destroy(BIO *b)
539{
540 return 1;
541}
542
543static int url_bio_bread(BIO *b, char *buf, int len)
544{
545 TLSContext *c = BIO_get_data(b);
546 TLSShared *s = &c->tls_shared;
547 int ret = ffurl_read(s->is_dtls ? s->udp : s->tcp, buf, len);
548 if (ret >= 0) {
549#if CONFIG_UDP_PROTOCOL
550 if (s->is_dtls && s->listen && !c->dest_addr_len) {
551 int err_ret;
552
553 ff_udp_get_last_recv_addr(s->udp, &c->dest_addr, &c->dest_addr_len);
554 err_ret = ff_udp_set_remote_addr(s->udp, (struct sockaddr *)&c->dest_addr, c->dest_addr_len, 1);
555 if (err_ret < 0) {
556 av_log(c, AV_LOG_ERROR, "Failed connecting udp context\n");
557 return err_ret;
558 }
559 av_log(c, AV_LOG_TRACE, "Set UDP remote addr on UDP socket, now 'connected'\n");
560 }
561#endif
562
563 return ret;
564 }
565 BIO_clear_retry_flags(b);
566 if (ret == AVERROR_EXIT)
567 return 0;
568 if (ret == AVERROR(EAGAIN))
569 BIO_set_retry_read(b);
570 else
571 c->io_err = ret;
572 return -1;
573}
574
575static int url_bio_bwrite(BIO *b, const char *buf, int len)
576{
577 TLSContext *c = BIO_get_data(b);
578 int ret = ffurl_write(c->tls_shared.is_dtls ? c->tls_shared.udp : c->tls_shared.tcp, buf, len);
579 if (ret >= 0)
580 return ret;
581 BIO_clear_retry_flags(b);
582 if (ret == AVERROR_EXIT)
583 /* Don't return 0: that signals success and silently drops the data. */
584 c->io_err = ret;
585 else if (ret == AVERROR(EAGAIN))
586 BIO_set_retry_write(b);
587 else
588 c->io_err = ret;
589 return -1;
590}
591
592static long url_bio_ctrl(BIO *b, int cmd, long num, void *ptr)
593{
594 if (cmd == BIO_CTRL_FLUSH) {
595 BIO_clear_retry_flags(b);
596 return 1;
597 }
598 return 0;
599}
600
601static int url_bio_bputs(BIO *b, const char *str)
602{
603 return url_bio_bwrite(b, str, strlen(str));
604}
605
607{
608 TLSContext *c = h->priv_data;
609 BIO *bio;
610 c->url_bio_method = BIO_meth_new(BIO_TYPE_SOURCE_SINK, "urlprotocol bio");
611 BIO_meth_set_write(c->url_bio_method, url_bio_bwrite);
612 BIO_meth_set_read(c->url_bio_method, url_bio_bread);
613 BIO_meth_set_puts(c->url_bio_method, url_bio_bputs);
614 BIO_meth_set_ctrl(c->url_bio_method, url_bio_ctrl);
615 BIO_meth_set_create(c->url_bio_method, url_bio_create);
616 BIO_meth_set_destroy(c->url_bio_method, url_bio_destroy);
617 bio = BIO_new(c->url_bio_method);
618 BIO_set_data(bio, c);
619
620 SSL_set_bio(c->ssl, bio, bio);
621}
622
623static void openssl_info_callback(const SSL *ssl, int where, int ret) {
624 const char *method = "undefined";
625 TLSContext *c = (TLSContext*)SSL_get_ex_data(ssl, 0);
626
627 if (where & SSL_ST_CONNECT) {
628 method = "SSL_connect";
629 } else if (where & SSL_ST_ACCEPT)
630 method = "SSL_accept";
631
632 if (where & SSL_CB_LOOP) {
633 av_log(c, AV_LOG_DEBUG, "Info method=%s state=%s(%s), where=%d, ret=%d\n",
634 method, SSL_state_string(ssl), SSL_state_string_long(ssl), where, ret);
635 } else if (where & SSL_CB_ALERT) {
636 method = (where & SSL_CB_READ) ? "read":"write";
637 av_log(c, AV_LOG_DEBUG, "Alert method=%s state=%s(%s), where=%d, ret=%d\n",
638 method, SSL_state_string(ssl), SSL_state_string_long(ssl), where, ret);
639 }
640}
641
643{
644 TLSContext *c = h->priv_data;
645 int ret, err;
646 int timeout_ms;
647 struct timeval timeout;
648 int64_t timeout_start = av_gettime_relative();
649 int sockfd = ffurl_get_file_handle(c->tls_shared.udp);
650 struct pollfd pfd = { .fd = sockfd, .events = POLLIN, .revents = 0 };
651
652 /* Force NONBLOCK mode to handle DTLS retransmissions */
653 c->tls_shared.udp->flags |= AVIO_FLAG_NONBLOCK;
654
655 for (;;) {
656 if (av_gettime_relative() - timeout_start > DTLS_HANDSHAKE_TIMEOUT_US) {
657 ret = AVERROR(ETIMEDOUT);
658 goto end;
659 }
660
661 ERR_clear_error();
662 ret = SSL_do_handshake(c->ssl);
663 if (ret == 1) {
664 av_log(c, AV_LOG_TRACE, "Handshake success\n");
665 c->do_shutdown = 1;
666 break;
667 }
668 err = SSL_get_error(c->ssl, ret);
669 if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE && err != SSL_ERROR_ZERO_RETURN) {
670 av_log(c, AV_LOG_ERROR, "Handshake failed, ret=%d, err=%d\n", ret, err);
671 ret = print_ssl_error(h, ret);
672 goto end;
673 }
674
675 timeout_ms = 1000;
676 if (DTLSv1_get_timeout(c->ssl, &timeout))
677 timeout_ms = timeout.tv_sec * 1000 + timeout.tv_usec / 1000;
678
679 ret = poll(&pfd, 1, timeout_ms);
680 if (ret > 0 && (pfd.revents & POLLIN))
681 continue;
682 if (!ret) {
683 if (DTLSv1_handle_timeout(c->ssl) < 0) {
684 ret = AVERROR(EIO);
685 goto end;
686 }
687 continue;
688 }
689 if (ret < 0) {
690 ret = ff_neterrno();
691 goto end;
692 }
693 }
694 /* Check whether the handshake is completed. */
695 if (SSL_is_init_finished(c->ssl) != TLS_ST_OK)
696 goto end;
697
698 ret = 0;
699end:
700 if (!(h->flags & AVIO_FLAG_NONBLOCK))
701 c->tls_shared.udp->flags &= ~AVIO_FLAG_NONBLOCK;
702 return ret;
703}
704
706{
707 int ret;
708 TLSContext *c = h->priv_data;
709 TLSShared *s = &c->tls_shared;
710 EVP_PKEY *pkey = NULL;
711 X509 *cert = NULL;
712 /* setup ca, private key, certificate */
713 if (s->ca_file) {
714 if (!SSL_CTX_load_verify_locations(c->ctx, s->ca_file, NULL))
715 av_log(h, AV_LOG_ERROR, "SSL_CTX_load_verify_locations %s\n", openssl_get_error(c));
716 } else {
717 if (!SSL_CTX_set_default_verify_paths(c->ctx)) {
718 // Only log the failure but do not error out, as this is not fatal
719 av_log(h, AV_LOG_WARNING, "Failure setting default verify locations: %s\n",
721 }
722 }
723
724 if (s->cert_file) {
725 ret = SSL_CTX_use_certificate_chain_file(c->ctx, s->cert_file);
726 if (ret <= 0) {
727 av_log(h, AV_LOG_ERROR, "Unable to load cert file %s: %s\n",
728 s->cert_file, openssl_get_error(c));
729 ret = AVERROR(EIO);
730 goto fail;
731 }
732 } else if (s->cert_buf) {
733 cert = cert_from_pem_string(s->cert_buf);
734 if (SSL_CTX_use_certificate(c->ctx, cert) != 1) {
735 av_log(c, AV_LOG_ERROR, "SSL: Init SSL_CTX_use_certificate failed, %s\n", openssl_get_error(c));
736 ret = AVERROR(EINVAL);
737 goto fail;
738 }
739 }
740
741 if (s->key_file) {
742 ret = SSL_CTX_use_PrivateKey_file(c->ctx, s->key_file, SSL_FILETYPE_PEM);
743 if (ret <= 0) {
744 av_log(h, AV_LOG_ERROR, "Unable to load key file %s: %s\n",
745 s->key_file, openssl_get_error(c));
746 ret = AVERROR(EIO);
747 goto fail;
748 }
749 } else if (s->key_buf) {
750 pkey = pkey_from_pem_string(s->key_buf, 1);
751 if (SSL_CTX_use_PrivateKey(c->ctx, pkey) != 1) {
752 av_log(c, AV_LOG_ERROR, "Init SSL_CTX_use_PrivateKey failed, %s\n", openssl_get_error(c));
753 ret = AVERROR(EINVAL);
754 goto fail;
755 }
756 }
757
758 if (s->listen && !s->cert_file && !s->cert_buf && !s->key_file && !s->key_buf) {
759 av_log(h, AV_LOG_VERBOSE, "No server certificate provided, using self-signed\n");
760
761 ret = openssl_gen_private_key(&pkey);
762 if (ret < 0)
763 goto fail;
764
765 ret = openssl_gen_certificate(pkey, &cert, NULL);
766 if (ret < 0)
767 goto fail;
768
769 if (SSL_CTX_use_certificate(c->ctx, cert) != 1) {
770 av_log(c, AV_LOG_ERROR, "SSL_CTX_use_certificate failed for self-signed cert, %s\n", openssl_get_error(c));
771 ret = AVERROR(EINVAL);
772 goto fail;
773 }
774
775 if (SSL_CTX_use_PrivateKey(c->ctx, pkey) != 1) {
776 av_log(c, AV_LOG_ERROR, "SSL_CTX_use_PrivateKey failed for self-signed cert, %s\n", openssl_get_error(c));
777 ret = AVERROR(EINVAL);
778 goto fail;
779 }
780 }
781
782 ret = 0;
783fail:
784 X509_free(cert);
785 EVP_PKEY_free(pkey);
786 return ret;
787}
788
789static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
790{
791 TLSContext *c = h->priv_data;
792 TLSShared *s = &c->tls_shared;
793 int ret;
794
795 if (!c->tls_shared.external_sock) {
796 if ((ret = ff_tls_open_underlying(&c->tls_shared, h, uri, options)) < 0)
797 goto fail;
798 } else if (!s->host) {
799 if ((ret = ff_tls_parse_host(s, s->underlying_host, sizeof(s->underlying_host), NULL, uri)) < 0)
800 goto fail;
801 }
802
803 // We want to support all versions of TLS >= 1.0, but not the deprecated
804 // and insecure SSLv2 and SSLv3. Despite the name, TLS_*_method()
805 // enables support for all versions of SSL and TLS, and we then disable
806 // support for the old protocols immediately after creating the context.
807 if (s->is_dtls)
808 c->ctx = SSL_CTX_new(s->listen ? DTLS_server_method() : DTLS_client_method());
809 else
810 c->ctx = SSL_CTX_new(s->listen ? TLS_server_method() : TLS_client_method());
811 if (!c->ctx) {
813 ret = AVERROR(EIO);
814 goto fail;
815 }
816 if (!s->is_dtls) {
817 if (!SSL_CTX_set_min_proto_version(c->ctx, TLS1_VERSION)) {
818 av_log(h, AV_LOG_ERROR, "Failed to set minimum TLS version to TLSv1\n");
819 ret = AVERROR_EXTERNAL;
820 goto fail;
821 }
822 }
824 if (ret < 0) goto fail;
825
826 if (s->verify)
827 SSL_CTX_set_verify(c->ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
828
829 if (s->is_dtls && s->use_srtp) {
830 /**
831 * The profile for OpenSSL's SRTP is SRTP_AES128_CM_SHA1_80, see ssl/d1_srtp.c.
832 * The profile for FFmpeg's SRTP is SRTP_AES128_CM_HMAC_SHA1_80, see libavformat/srtp.c.
833 */
834 const char *profiles = "SRTP_AES128_CM_SHA1_80";
835 if (SSL_CTX_set_tlsext_use_srtp(c->ctx, profiles)) {
836 av_log(c, AV_LOG_ERROR, "Init SSL_CTX_set_tlsext_use_srtp failed, profiles=%s, %s\n",
838 ret = AVERROR(EINVAL);
839 goto fail;
840 }
841 }
842
843 c->ssl = SSL_new(c->ctx);
844 if (!c->ssl) {
846 ret = AVERROR(EIO);
847 goto fail;
848 }
849 SSL_set_ex_data(c->ssl, 0, c);
850 SSL_CTX_set_info_callback(c->ctx, openssl_info_callback);
851
852 if (s->is_dtls) {
853 /**
854 * We have set the MTU to fragment the DTLS packet. It is important to note that the
855 * packet is split to ensure that each handshake packet is smaller than the MTU.
856 */
857 if (s->mtu <= 0)
858 s->mtu = 1096;
859 SSL_set_options(c->ssl, SSL_OP_NO_QUERY_MTU);
860 SSL_set_mtu(c->ssl, s->mtu);
861 DTLS_set_link_mtu(c->ssl, s->mtu);
862 }
863
865 if (!s->listen) {
866 // Pin a numeric host to the certificate's iPAddress SAN and everything else
867 // to the hostname. Classify s->host with the same AI_NUMERICHOST rule tls.c
868 // uses and hand OpenSSL the binary address, so legacy numeric forms (e.g.
869 // 2130706433) are pinned as IPs instead of falling back to hostname matching.
870 // A verifyhost=<name> override leaves s->host non-numeric and binds by name.
871 struct addrinfo hints = { .ai_flags = AI_NUMERICHOST }, *ai = NULL;
872 int is_numeric_host = !getaddrinfo(s->host, NULL, &hints, &ai);
873 int ok;
874
875 // By default OpenSSL does too lax wildcard matching
876 SSL_set_hostflags(c->ssl, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
877 if (is_numeric_host) {
878 void *addr = ai->ai_family == AF_INET6 ?
879 (void *)&((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr :
880 (void *)&((struct sockaddr_in *)ai->ai_addr)->sin_addr;
881 ok = X509_VERIFY_PARAM_set1_ip(SSL_get0_param(c->ssl), addr,
882 ai->ai_family == AF_INET6 ? 16 : 4);
883 } else {
884 ok = SSL_set1_host(c->ssl, s->host);
885 }
886 if (ai)
887 freeaddrinfo(ai);
888 if (!ok) {
889 av_log(h, AV_LOG_ERROR, "Failed to set %s for TLS/SSL verification: %s\n",
890 is_numeric_host ? "IP" : "hostname", openssl_get_error(c));
891 ret = AVERROR_EXTERNAL;
892 goto fail;
893 }
894 // SNI MUST NOT carry a literal IP address (RFC 6066 sec. 3); suppress it for
895 // numeric transport hosts, matching the GnuTLS backend.
896 if (!s->numerichost && !SSL_set_tlsext_host_name(c->ssl, s->host)) {
897 av_log(h, AV_LOG_ERROR, "Failed to set hostname for SNI: %s\n", openssl_get_error(c));
898 ret = AVERROR_EXTERNAL;
899 goto fail;
900 }
901 }
902
903 if (s->is_dtls) {
904 /* This seems to be necessary despite explicitly setting client/server method above. */
905 if (s->listen)
906 SSL_set_accept_state(c->ssl);
907 else
908 SSL_set_connect_state(c->ssl);
909
910 /* The SSL_do_handshake can't be called if DTLS hasn't prepared for udp. */
911 if (!c->tls_shared.external_sock) {
912 ret = dtls_handshake(h);
913 // Fatal SSL error, for example, no available suite when peer is DTLS 1.0 while we are DTLS 1.2.
914 if (ret < 0) {
915 av_log(c, AV_LOG_ERROR, "Failed to drive SSL context, ret=%d\n", ret);
916 return AVERROR(EIO);
917 }
918 }
919 av_log(c, AV_LOG_VERBOSE, "Setup ok, MTU=%d\n", c->tls_shared.mtu);
920 } else {
921 ERR_clear_error();
922 ret = s->listen ? SSL_accept(c->ssl) : SSL_connect(c->ssl);
923 if (ret == 0) {
924 av_log(h, AV_LOG_ERROR, "Unable to negotiate TLS/SSL session\n");
925 ret = AVERROR(EIO);
926 goto fail;
927 } else if (ret < 0) {
928 ret = print_ssl_error(h, ret);
929 goto fail;
930 }
931 c->do_shutdown = 1;
932 }
933
934 return 0;
935fail:
936 tls_close(h);
937 return ret;
938}
939
940static int dtls_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
941{
942 TLSContext *c = h->priv_data;
943 TLSShared *s = &c->tls_shared;
944 s->is_dtls = 1;
945 return tls_open(h, uri, flags, options);
946}
947
948static int tls_read(URLContext *h, uint8_t *buf, int size)
949{
950 TLSContext *c = h->priv_data;
951 TLSShared *s = &c->tls_shared;
952 URLContext *uc = s->is_dtls ? s->udp : s->tcp;
953 int ret;
954 // Set or clear the AVIO_FLAG_NONBLOCK on the underlying socket
956 uc->flags |= h->flags & AVIO_FLAG_NONBLOCK;
957 ERR_clear_error();
958 ret = SSL_read(c->ssl, buf, size);
959 if (ret > 0)
960 return ret;
961 if (ret == 0)
962 return AVERROR_EOF;
963 return print_ssl_error(h, ret);
964}
965
966static int tls_write(URLContext *h, const uint8_t *buf, int size)
967{
968 TLSContext *c = h->priv_data;
969 TLSShared *s = &c->tls_shared;
970 URLContext *uc = s->is_dtls ? s->udp : s->tcp;
971 int ret;
972
973 // Set or clear the AVIO_FLAG_NONBLOCK on the underlying socket
975 uc->flags |= h->flags & AVIO_FLAG_NONBLOCK;
976
977 if (s->is_dtls) {
978 const size_t mtu_size = DTLS_get_data_mtu(c->ssl);
979 size = FFMIN(size, mtu_size);
980 }
981
982 ERR_clear_error();
983 ret = SSL_write(c->ssl, buf, size);
984 if (ret > 0)
985 return ret;
986 if (ret == 0)
987 return AVERROR_EOF;
988 return print_ssl_error(h, ret);
989}
990
992{
993 TLSContext *c = h->priv_data;
994 TLSShared *s = &c->tls_shared;
995 return ffurl_get_file_handle(s->is_dtls ? s->udp : s->tcp);
996}
997
999{
1000 TLSContext *c = h->priv_data;
1001 TLSShared *s = &c->tls_shared;
1002 return ffurl_get_short_seek(s->is_dtls ? s->udp : s->tcp);
1003}
1004
1005static const AVOption options[] = {
1006 TLS_COMMON_OPTIONS(TLSContext, tls_shared),
1007 { NULL }
1008};
1009
1010static const AVClass tls_class = {
1011 .class_name = "tls",
1012 .item_name = av_default_item_name,
1013 .option = options,
1014 .version = LIBAVUTIL_VERSION_INT,
1015};
1016
1018 .name = "tls",
1019 .url_open2 = tls_open,
1020 .url_read = tls_read,
1021 .url_write = tls_write,
1022 .url_close = tls_close,
1023 .url_get_file_handle = tls_get_file_handle,
1024 .url_get_short_seek = tls_get_short_seek,
1025 .priv_data_size = sizeof(TLSContext),
1027 .priv_data_class = &tls_class,
1028};
1029
1030static const AVClass dtls_class = {
1031 .class_name = "dtls",
1032 .item_name = av_default_item_name,
1033 .option = options,
1034 .version = LIBAVUTIL_VERSION_INT,
1035};
1036
1038 .name = "dtls",
1039 .url_open2 = dtls_open,
1040 .url_handshake = dtls_handshake,
1041 .url_close = tls_close,
1042 .url_read = tls_read,
1043 .url_write = tls_write,
1044 .url_get_file_handle = tls_get_file_handle,
1045 .url_get_short_seek = tls_get_short_seek,
1046 .priv_data_size = sizeof(TLSContext),
1048 .priv_data_class = &dtls_class,
1049};
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition dsp.h:97
static FILE * out
int ffurl_closep(URLContext **hh)
Close the resource accessed by the URLContext h, and free the memory used by it.
Definition avio.c:663
int ffurl_get_short_seek(void *urlcontext)
Return the current short seek threshold value for this URL.
Definition avio.c:913
int ffurl_get_file_handle(URLContext *h)
Return the file descriptor associated with this URL.
Definition avio.c:889
#define AVIO_FLAG_NONBLOCK
Use non-blocking mode.
Definition avio.h:636
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition bprint.c:121
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition bprint.c:68
#define flags(name, subs,...)
Definition cbs_h264.c:74
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define s(width, name)
Definition cbs_vp9.c:198
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
#define fail
Definition test.h:479
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition bprint.c:234
uint32_t av_get_random_seed(void)
Get a seed to use in conjunction with random functions.
#define AVERROR_EXIT
Immediate exit was requested; the called function should not be restarted.
Definition error.h:58
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition error.h:59
#define AVERROR_EOF
End of file.
Definition error.h:57
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition error.h:122
#define AVERROR(e)
Definition error.h:45
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
Definition log.h:236
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition log.h:231
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition log.h:216
#define AV_LOG_VERBOSE
Detailed information.
Definition log.h:226
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
const char * av_default_item_name(void *ptr)
Return the context name.
Definition log.c:241
#define LIBAVUTIL_VERSION_INT
Definition version.h:85
#define b
Definition input.c:43
#define av_cold
Definition attributes.h:117
static const AVProfile profiles[]
#define FFMIN(a, b)
Definition macros.h:49
#define AI_NUMERICHOST
Definition network.h:187
#define getaddrinfo
Definition network.h:217
int ff_udp_set_remote_addr(URLContext *h, const struct sockaddr *dest_addr, socklen_t dest_addr_len, int do_connect)
This function is identical to ff_udp_set_remote_url, except that it takes a sockaddr directly.
Definition udp.c:472
void ff_udp_get_last_recv_addr(URLContext *h, struct sockaddr_storage *addr, socklen_t *addr_len)
Definition udp.c:510
#define ff_neterrno()
Definition network.h:68
#define freeaddrinfo
Definition network.h:218
int averr
Definition nvenc.c:157
AVOptions.
miscellaneous OS support macros and functions.
const URLProtocol ff_dtls_protocol
Definition tls_gnutls.c:792
const URLProtocol ff_tls_protocol
Definition tls_gnutls.c:772
Describe the class of an AVClass context structure.
Definition log.h:76
AVOption.
Definition opt.h:428
socklen_t dest_addr_len
Definition tls_gnutls.c:343
struct tls * ctx
Definition tls_libtls.c:37
struct sockaddr_storage dest_addr
Definition tls_gnutls.c:342
char error_message[256]
TLSShared tls_shared
Definition tls_gnutls.c:337
BIO_METHOD * url_bio_method
int flags
Definition url.h:40
#define av_log(a,...)
static void error(const char *err)
int num
Definition error.c:23
int64_t av_gettime_relative(void)
Get the current time in microseconds since some unspecified starting point.
Definition time.c:57
int ff_url_read_all(const char *url, AVBPrint *bp)
Read all data from the given URL url and store it in the given buffer bp.
Definition tls.c:128
int ff_tls_open_underlying(TLSShared *c, URLContext *parent, const char *uri, AVDictionary **options)
Definition tls.c:54
int ff_tls_parse_host(TLSShared *s, char *hostname, int hostname_size, int *port_ptr, const char *uri)
Definition tls.c:35
#define MAX_CERTIFICATE_SIZE
Maximum size limit of a certificate and private key size.
Definition tls.h:34
#define TLS_COMMON_OPTIONS(pstruct, options_field)
Definition tls.h:101
static int tls_close(URLContext *h)
Definition tls_gnutls.c:419
static const AVClass tls_class
Definition tls_gnutls.c:765
static int tls_read(URLContext *h, uint8_t *buf, int size)
Definition tls_gnutls.c:708
static int dtls_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
Definition tls_gnutls.c:700
static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
Definition tls_gnutls.c:533
static int tls_get_short_seek(URLContext *h)
Definition tls_gnutls.c:754
static int tls_write(URLContext *h, const uint8_t *buf, int size)
Definition tls_gnutls.c:725
static const AVClass dtls_class
Definition tls_gnutls.c:785
static int tls_get_file_handle(URLContext *h)
Definition tls_gnutls.c:748
static int dtls_handshake(URLContext *h)
static const char * openssl_get_error(TLSContext *c)
Retrieves the error message for the latest OpenSSL error.
#define DTLS_HANDSHAKE_TIMEOUT_US
Definition tls_openssl.c:42
static int pkey_to_pem_string(EVP_PKEY *pkey, char *out, size_t out_sz)
Convert an EVP_PKEY to a PEM string.
Definition tls_openssl.c:46
static av_cold void init_bio_method(URLContext *h)
static int tls_close(URLContext *h)
int ff_ssl_gen_key_cert(char *key_buf, size_t key_sz, char *cert_buf, size_t cert_sz, char **fingerprint)
int ff_ssl_read_key_cert(char *key_url, char *cert_url, char *key_buf, size_t key_sz, char *cert_buf, size_t cert_sz, char **fingerprint)
static int tls_read(URLContext *h, uint8_t *buf, int size)
static int dtls_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
static long url_bio_ctrl(BIO *b, int cmd, long num, void *ptr)
static int url_bio_bread(BIO *b, char *buf, int len)
int ff_dtls_export_materials(URLContext *h, char *dtls_srtp_materials, size_t materials_sz)
static int url_bio_bputs(BIO *b, const char *str)
static int openssl_gen_certificate(EVP_PKEY *pkey, X509 **cert, char **fingerprint)
static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
static int x509_fingerprint(X509 *cert, char **fingerprint)
Generate a SHA-256 fingerprint of an X.509 certificate.
static void openssl_info_callback(const SSL *ssl, int where, int ret)
static EVP_PKEY * pkey_from_pem_string(const char *pem_str, int is_priv)
Deserialize a PEM-encoded private or public key from a NUL-terminated C string.
static int url_bio_destroy(BIO *b)
static X509 * cert_from_pem_string(const char *pem_str)
Deserialize a PEM-encoded certificate from a NUL-terminated C string.
static int url_bio_bwrite(BIO *b, const char *buf, int len)
static int print_ssl_error(URLContext *h, int ret)
static int tls_get_short_seek(URLContext *h)
static int tls_write(URLContext *h, const uint8_t *buf, int size)
static av_cold int openssl_init_ca_key_cert(URLContext *h)
static int cert_to_pem_string(X509 *cert, char *out, size_t out_sz)
Convert an X509 certificate to a PEM string.
Definition tls_openssl.c:73
static int openssl_gen_private_key(EVP_PKEY **pkey)
static int tls_get_file_handle(URLContext *h)
int ff_tls_set_external_socket(URLContext *h, URLContext *sock)
static int url_bio_create(BIO *b)
int size
unbuffered private I/O API
static int ffurl_write(URLContext *h, const uint8_t *buf, int size)
Write size bytes from buf to the resource accessed by h.
Definition url.h:205
static int ffurl_read(URLContext *h, uint8_t *buf, int size)
Read up to size bytes from the resource accessed by h, and store the read bytes in buf.
Definition url.h:184
#define URL_PROTOCOL_FLAG_NETWORK
Definition url.h:33
#define md
static void read_bytes(const uint8_t *src, float *dst, int src_stride, int dst_stride, int width, int height, float scale)
Definition vf_nnedi.c:442
int len
static double c[64]