FFmpeg
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 "libavutil/mem.h"
24 #include "network.h"
25 #include "os_support.h"
26 #include "libavutil/random_seed.h"
27 #include "url.h"
28 #include "tls.h"
29 #include "libavutil/opt.h"
30 
31 #include <openssl/bio.h>
32 #include <openssl/ssl.h>
33 #include <openssl/err.h>
34 
35 /**
36  * Returns a heap‐allocated null‐terminated string containing
37  * the PEM‐encoded public key. Caller must free.
38  */
39 static char *pkey_to_pem_string(EVP_PKEY *pkey) {
40  BIO *mem = NULL;
41  BUF_MEM *bptr = NULL;
42  char *pem_str = NULL;
43 
44  // Create a memory BIO
45  if (!(mem = BIO_new(BIO_s_mem())))
46  goto err;
47 
48  // Write public key in PEM form
49  if (!PEM_write_bio_PrivateKey(mem, pkey, NULL, NULL, 0, NULL, NULL))
50  goto err;
51 
52  // Extract pointer/length
53  BIO_get_mem_ptr(mem, &bptr);
54  if (!bptr || !bptr->length)
55  goto err;
56 
57  // Allocate string (+1 for NUL)
58  pem_str = av_malloc(bptr->length + 1);
59  if (!pem_str)
60  goto err;
61 
62  // Copy data & NUL‐terminate
63  memcpy(pem_str, bptr->data, bptr->length);
64  pem_str[bptr->length] = '\0';
65 
66 cleanup:
67  BIO_free(mem);
68  return pem_str;
69 
70 err:
71  // error path: free and return NULL
72  free(pem_str);
73  pem_str = NULL;
74  goto cleanup;
75 }
76 
77 /**
78  * Serialize an X509 certificate to a av_malloc’d PEM string.
79  * Caller must free the returned pointer.
80  */
81 static char *cert_to_pem_string(X509 *cert)
82 {
83  BIO *mem = BIO_new(BIO_s_mem());
84  BUF_MEM *bptr = NULL;
85  char *out = NULL;
86 
87  if (!mem) goto err;
88 
89  /* Write the PEM certificate */
90  if (!PEM_write_bio_X509(mem, cert))
91  goto err;
92 
93  BIO_get_mem_ptr(mem, &bptr);
94  if (!bptr || !bptr->length) goto err;
95 
96  out = av_malloc(bptr->length + 1);
97  if (!out) goto err;
98 
99  memcpy(out, bptr->data, bptr->length);
100  out[bptr->length] = '\0';
101 
102 cleanup:
103  BIO_free(mem);
104  return out;
105 
106 err:
107  free(out);
108  out = NULL;
109  goto cleanup;
110 }
111 
112 
113 /**
114  * Generate a SHA-256 fingerprint of an X.509 certificate.
115  *
116  * @param ctx AVFormatContext for logging (can be NULL)
117  * @param cert X509 certificate to fingerprint
118  * @return Newly allocated fingerprint string in "AA:BB:CC:…" format,
119  * or NULL on error (logs via av_log if ctx is not NULL).
120  * Caller must free() the returned string.
121  */
122 static char *generate_fingerprint(X509 *cert)
123 {
124  unsigned char md[EVP_MAX_MD_SIZE];
125  int n = 0;
126  AVBPrint fingerprint;
127  char *result = NULL;
128  int i;
129 
130  /* To prevent a crash during cleanup, always initialize it. */
131  av_bprint_init(&fingerprint, 0, AV_BPRINT_SIZE_UNLIMITED);
132 
133  if (X509_digest(cert, EVP_sha256(), md, &n) != 1) {
134  av_log(NULL, AV_LOG_ERROR, "TLS: Failed to generate fingerprint, %s\n", ERR_error_string(ERR_get_error(), NULL));
135  goto end;
136  }
137 
138  for (i = 0; i < n; i++) {
139  av_bprintf(&fingerprint, "%02X", md[i]);
140  if (i + 1 < n)
141  av_bprintf(&fingerprint, ":");
142  }
143 
144  if (!fingerprint.str || !strlen(fingerprint.str)) {
145  av_log(NULL, AV_LOG_ERROR, "TLS: Fingerprint is empty\n");
146  goto end;
147  }
148 
149  result = av_strdup(fingerprint.str);
150  if (!result) {
151  av_log(NULL, AV_LOG_ERROR, "TLS: Out of memory generating fingerprint\n");
152  }
153 
154 end:
155  av_bprint_finalize(&fingerprint, NULL);
156  return result;
157 }
158 
159 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)
160 {
161  int ret = 0;
162  BIO *key_b = NULL, *cert_b = NULL;
163  AVBPrint key_bp, cert_bp;
164  EVP_PKEY *pkey;
165  X509 *cert;
166  char *key_tem = NULL, *cert_tem = NULL;
167 
168  /* To prevent a crash during cleanup, always initialize it. */
170  av_bprint_init(&cert_bp, 1, MAX_CERTIFICATE_SIZE);
171 
172  /* Read key file. */
173  ret = ff_url_read_all(key_url, &key_bp);
174  if (ret < 0) {
175  av_log(NULL, AV_LOG_ERROR, "TLS: Failed to open key file %s\n", key_url);
176  goto end;
177  }
178 
179  if (!(key_b = BIO_new(BIO_s_mem()))) {
180  ret = AVERROR(ENOMEM);
181  goto end;
182  }
183 
184  BIO_write(key_b, key_bp.str, key_bp.len);
185  pkey = PEM_read_bio_PrivateKey(key_b, NULL, NULL, NULL);
186  if (!pkey) {
187  av_log(NULL, AV_LOG_ERROR, "TLS: Failed to read private key from %s\n", key_url);
188  ret = AVERROR(EIO);
189  goto end;
190  }
191 
192  /* Read certificate. */
193  ret = ff_url_read_all(cert_url, &cert_bp);
194  if (ret < 0) {
195  av_log(NULL, AV_LOG_ERROR, "TLS: Failed to open cert file %s\n", cert_url);
196  goto end;
197  }
198 
199  if (!(cert_b = BIO_new(BIO_s_mem()))) {
200  ret = AVERROR(ENOMEM);
201  goto end;
202  }
203 
204  BIO_write(cert_b, cert_bp.str, cert_bp.len);
205  cert = PEM_read_bio_X509(cert_b, NULL, NULL, NULL);
206  if (!cert) {
207  av_log(NULL, AV_LOG_ERROR, "TLS: Failed to read certificate from %s\n", cert_url);
208  ret = AVERROR(EIO);
209  goto end;
210  }
211 
212  key_tem = pkey_to_pem_string(pkey);
213  cert_tem = cert_to_pem_string(cert);
214 
215  snprintf(key_buf, key_sz, "%s", key_tem);
216  snprintf(cert_buf, cert_sz, "%s", cert_tem);
217 
218  /* Generate fingerprint. */
219  *fingerprint = generate_fingerprint(cert);
220  if (!*fingerprint) {
221  av_log(NULL, AV_LOG_ERROR, "TLS: Failed to generate fingerprint from %s\n", cert_url);
222  ret = AVERROR(EIO);
223  goto end;
224  }
225 
226 end:
227  BIO_free(key_b);
228  av_bprint_finalize(&key_bp, NULL);
229  BIO_free(cert_b);
230  av_bprint_finalize(&cert_bp, NULL);
231  if (key_tem) av_free(key_tem);
232  if (cert_tem) av_free(cert_tem);
233  return ret;
234 }
235 
236 static int openssl_gen_private_key(EVP_PKEY **pkey, EC_KEY **eckey)
237 {
238  int ret = 0;
239 
240  /**
241  * Note that secp256r1 in openssl is called NID_X9_62_prime256v1 or prime256v1 in string,
242  * not NID_secp256k1 or secp256k1 in string.
243  *
244  * TODO: Should choose the curves in ClientHello.supported_groups, for example:
245  * Supported Group: x25519 (0x001d)
246  * Supported Group: secp256r1 (0x0017)
247  * Supported Group: secp384r1 (0x0018)
248  */
249 #if OPENSSL_VERSION_NUMBER < 0x30000000L /* OpenSSL 3.0 */
250  EC_GROUP *ecgroup = NULL;
251  int curve = NID_X9_62_prime256v1;
252 #else
253  const char *curve = SN_X9_62_prime256v1;
254 #endif
255 
256 #if OPENSSL_VERSION_NUMBER < 0x30000000L /* OpenSSL 3.0 */
257  *pkey = EVP_PKEY_new();
258  *eckey = EC_KEY_new();
259  ecgroup = EC_GROUP_new_by_curve_name(curve);
260  if (!ecgroup) {
261  av_log(NULL, AV_LOG_ERROR, "TLS: Create EC group by curve=%d failed, %s", curve, ERR_error_string(ERR_get_error(), NULL));
262  goto einval_end;
263  }
264 
265 #if OPENSSL_VERSION_NUMBER < 0x10100000L // v1.1.x
266  /* For openssl 1.0, we must set the group parameters, so that cert is ok. */
267  EC_GROUP_set_asn1_flag(ecgroup, OPENSSL_EC_NAMED_CURVE);
268 #endif
269 
270  if (EC_KEY_set_group(*eckey, ecgroup) != 1) {
271  av_log(NULL, AV_LOG_ERROR, "TLS: Generate private key, EC_KEY_set_group failed, %s\n", ERR_error_string(ERR_get_error(), NULL));
272  goto einval_end;
273  }
274 
275  if (EC_KEY_generate_key(*eckey) != 1) {
276  av_log(NULL, AV_LOG_ERROR, "TLS: Generate private key, EC_KEY_generate_key failed, %s\n", ERR_error_string(ERR_get_error(), NULL));
277  goto einval_end;
278  }
279 
280  if (EVP_PKEY_set1_EC_KEY(*pkey, *eckey) != 1) {
281  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));
282  goto einval_end;
283  }
284 #else
285  *pkey = EVP_EC_gen(curve);
286  if (!*pkey) {
287  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));
288  goto einval_end;
289  }
290 #endif
291  goto end;
292 
293 einval_end:
294  ret = AVERROR(EINVAL);
295 end:
296 #if OPENSSL_VERSION_NUMBER < 0x30000000L /* OpenSSL 3.0 */
297  EC_GROUP_free(ecgroup);
298 #endif
299  return ret;
300 }
301 
302 static int openssl_gen_certificate(EVP_PKEY *pkey, X509 **cert, char **fingerprint)
303 {
304  int ret = 0, serial, expire_day;
305  const char *aor = "lavf";
306  X509_NAME* subject = NULL;
307 
308  *cert= X509_new();
309  if (!*cert) {
310  goto enomem_end;
311  }
312 
313  // TODO: Support non-self-signed certificate, for example, load from a file.
314  subject = X509_NAME_new();
315  if (!subject) {
316  goto enomem_end;
317  }
318 
319  serial = (int)av_get_random_seed();
320  if (ASN1_INTEGER_set(X509_get_serialNumber(*cert), serial) != 1) {
321  av_log(NULL, AV_LOG_ERROR, "TLS: Failed to set serial, %s\n", ERR_error_string(ERR_get_error(), NULL));
322  goto einval_end;
323  }
324 
325  if (X509_NAME_add_entry_by_txt(subject, "CN", MBSTRING_ASC, aor, strlen(aor), -1, 0) != 1) {
326  av_log(NULL, AV_LOG_ERROR, "TLS: Failed to set CN, %s\n", ERR_error_string(ERR_get_error(), NULL));
327  goto einval_end;
328  }
329 
330  if (X509_set_issuer_name(*cert, subject) != 1) {
331  av_log(NULL, AV_LOG_ERROR, "TLS: Failed to set issuer, %s\n", ERR_error_string(ERR_get_error(), NULL));
332  goto einval_end;
333  }
334  if (X509_set_subject_name(*cert, subject) != 1) {
335  av_log(NULL, AV_LOG_ERROR, "TLS: Failed to set subject name, %s\n", ERR_error_string(ERR_get_error(), NULL));
336  goto einval_end;
337  }
338 
339  expire_day = 365;
340  if (!X509_gmtime_adj(X509_get_notBefore(*cert), 0)) {
341  av_log(NULL, AV_LOG_ERROR, "TLS: Failed to set notBefore, %s\n", ERR_error_string(ERR_get_error(), NULL));
342  goto einval_end;
343  }
344  if (!X509_gmtime_adj(X509_get_notAfter(*cert), 60*60*24*expire_day)) {
345  av_log(NULL, AV_LOG_ERROR, "TLS: Failed to set notAfter, %s\n", ERR_error_string(ERR_get_error(), NULL));
346  goto einval_end;
347  }
348 
349  if (X509_set_version(*cert, 2) != 1) {
350  av_log(NULL, AV_LOG_ERROR, "TLS: Failed to set version, %s\n", ERR_error_string(ERR_get_error(), NULL));
351  goto einval_end;
352  }
353 
354  if (X509_set_pubkey(*cert, pkey) != 1) {
355  av_log(NULL, AV_LOG_ERROR, "TLS: Failed to set public key, %s\n", ERR_error_string(ERR_get_error(), NULL));
356  goto einval_end;
357  }
358 
359  if (!X509_sign(*cert, pkey, EVP_sha1())) {
360  av_log(NULL, AV_LOG_ERROR, "TLS: Failed to sign certificate, %s\n", ERR_error_string(ERR_get_error(), NULL));
361  goto einval_end;
362  }
363 
364  *fingerprint = generate_fingerprint(*cert);
365  if (!*fingerprint) {
366  goto enomem_end;
367  }
368 
369  goto end;
370 enomem_end:
371  ret = AVERROR(ENOMEM);
372  goto end;
373 einval_end:
374  ret = AVERROR(EINVAL);
375 end:
376  X509_NAME_free(subject);
377  //av_bprint_finalize(&fingerprint, NULL);
378  return ret;
379 }
380 
381 int ff_ssl_gen_key_cert(char *key_buf, size_t key_sz, char *cert_buf, size_t cert_sz, char **fingerprint)
382 {
383  int ret = 0;
384  EVP_PKEY *pkey = NULL;
385  EC_KEY *ec_key = NULL;
386  X509 *cert = NULL;
387  char *key_tem = NULL, *cert_tem = NULL;
388 
389  ret = openssl_gen_private_key(&pkey, &ec_key);
390  if (ret < 0) goto error;
391 
392  ret = openssl_gen_certificate(pkey, &cert, fingerprint);
393  if (ret < 0) goto error;
394 
395  key_tem = pkey_to_pem_string(pkey);
396  cert_tem = cert_to_pem_string(cert);
397 
398  snprintf(key_buf, key_sz, "%s", key_tem);
399  snprintf(cert_buf, cert_sz, "%s", cert_tem);
400 
401  if (key_tem) av_free(key_tem);
402  if (cert_tem) av_free(cert_tem);
403 error:
404  return ret;
405 }
406 
407 
408 /**
409  * Deserialize a PEM‐encoded private or public key from a NUL-terminated C string.
410  *
411  * @param pem_str The PEM text, e.g.
412  * "-----BEGIN PRIVATE KEY-----\n…\n-----END PRIVATE KEY-----\n"
413  * @param is_priv If non-zero, parse as a PRIVATE key; otherwise, parse as a PUBLIC key.
414  * @return EVP_PKEY* on success (must EVP_PKEY_free()), or NULL on error.
415  */
416 static EVP_PKEY *pkey_from_pem_string(const char *pem_str, int is_priv)
417 {
418  BIO *mem = BIO_new_mem_buf(pem_str, -1);
419  if (!mem) {
420  av_log(NULL, AV_LOG_ERROR, "BIO_new_mem_buf failed\n");
421  return NULL;
422  }
423 
424  EVP_PKEY *pkey = NULL;
425  if (is_priv) {
426  pkey = PEM_read_bio_PrivateKey(mem, NULL, NULL, NULL);
427  } else {
428  pkey = PEM_read_bio_PUBKEY(mem, NULL, NULL, NULL);
429  }
430 
431  if (!pkey)
432  av_log(NULL, AV_LOG_ERROR, "Failed to parse %s key from string\n",
433  is_priv ? "private" : "public");
434 
435  BIO_free(mem);
436  return pkey;
437 }
438 
439 /**
440  * Deserialize a PEM‐encoded certificate from a NUL-terminated C string.
441  *
442  * @param pem_str The PEM text, e.g.
443  * "-----BEGIN CERTIFICATE-----\n…\n-----END CERTIFICATE-----\n"
444  * @return X509* on success (must X509_free()), or NULL on error.
445  */
446 static X509 *cert_from_pem_string(const char *pem_str)
447 {
448  BIO *mem = BIO_new_mem_buf(pem_str, -1);
449  if (!mem) {
450  av_log(NULL, AV_LOG_ERROR, "BIO_new_mem_buf failed\n");
451  return NULL;
452  }
453 
454  X509 *cert = PEM_read_bio_X509(mem, NULL, NULL, NULL);
455  if (!cert) {
456  av_log(NULL, AV_LOG_ERROR, "Failed to parse certificate from string\n");
457  return NULL;
458  }
459 
460  BIO_free(mem);
461  return cert;
462 }
463 
464 
465 typedef struct TLSContext {
466  const AVClass *class;
468  SSL_CTX *ctx;
469  SSL *ssl;
470  EVP_PKEY *pkey;
471 #if OPENSSL_VERSION_NUMBER >= 0x1010000fL
472  BIO_METHOD* url_bio_method;
473 #endif
474  int io_err;
475  char error_message[256];
476 } TLSContext;
477 
478 /**
479  * Retrieves the error message for the latest OpenSSL error.
480  *
481  * This function retrieves the error code from the thread's error queue, converts it
482  * to a human-readable string, and stores it in the TLSContext's error_message field.
483  * The error queue is then cleared using ERR_clear_error().
484  */
485 static const char* openssl_get_error(TLSContext *ctx)
486 {
487  int r2 = ERR_get_error();
488  if (r2) {
489  ERR_error_string_n(r2, ctx->error_message, sizeof(ctx->error_message));
490  } else
491  ctx->error_message[0] = '\0';
492 
493  ERR_clear_error();
494  return ctx->error_message;
495 }
496 
498 {
499  TLSContext *c = h->priv_data;
500  c->tls_shared.udp = udp;
501  return 0;
502 }
503 
504 int ff_dtls_export_materials(URLContext *h, char *dtls_srtp_materials, size_t materials_sz)
505 {
506  int ret = 0;
507  const char* dst = "EXTRACTOR-dtls_srtp";
508  TLSContext *c = h->priv_data;
509 
510  ret = SSL_export_keying_material(c->ssl, dtls_srtp_materials, materials_sz,
511  dst, strlen(dst), NULL, 0, 0);
512  if (!ret) {
513  av_log(c, AV_LOG_ERROR, "TLS: Failed to export SRTP material, %s\n", openssl_get_error(c));
514  return -1;
515  }
516  return 0;
517 }
518 
520 {
521  TLSContext *c = h->priv_data;
522  return c->tls_shared.state;
523 }
524 
525 /* OpenSSL 1.0.2 or below, then you would use SSL_library_init. If you are
526  * using OpenSSL 1.1.0 or above, then the library will initialize
527  * itself automatically.
528  * https://wiki.openssl.org/index.php/Library_Initialization
529  */
530 #if OPENSSL_VERSION_NUMBER < 0x10100000L
531 #include "libavutil/thread.h"
532 
534 
535 static int openssl_init;
536 
537 #if HAVE_THREADS
538 #include <openssl/crypto.h>
539 #include "libavutil/mem.h"
540 
541 pthread_mutex_t *openssl_mutexes;
542 static void openssl_lock(int mode, int type, const char *file, int line)
543 {
544  if (mode & CRYPTO_LOCK)
545  pthread_mutex_lock(&openssl_mutexes[type]);
546  else
547  pthread_mutex_unlock(&openssl_mutexes[type]);
548 }
549 #if !defined(WIN32) && OPENSSL_VERSION_NUMBER < 0x10000000
550 static unsigned long openssl_thread_id(void)
551 {
552  return (intptr_t) pthread_self();
553 }
554 #endif
555 #endif
556 
558 {
560  if (!openssl_init) {
561  SSL_library_init();
562  SSL_load_error_strings();
563 #if HAVE_THREADS
564  if (!CRYPTO_get_locking_callback()) {
565  int i;
566  openssl_mutexes = av_malloc_array(sizeof(pthread_mutex_t), CRYPTO_num_locks());
567  if (!openssl_mutexes) {
569  return AVERROR(ENOMEM);
570  }
571 
572  for (i = 0; i < CRYPTO_num_locks(); i++)
573  pthread_mutex_init(&openssl_mutexes[i], NULL);
574  CRYPTO_set_locking_callback(openssl_lock);
575 #if !defined(WIN32) && OPENSSL_VERSION_NUMBER < 0x10000000
576  CRYPTO_set_id_callback(openssl_thread_id);
577 #endif
578  }
579 #endif
580  }
581  openssl_init++;
583 
584  return 0;
585 }
586 
588 {
590  openssl_init--;
591  if (!openssl_init) {
592 #if HAVE_THREADS
593  if (CRYPTO_get_locking_callback() == openssl_lock) {
594  int i;
595  CRYPTO_set_locking_callback(NULL);
596  for (i = 0; i < CRYPTO_num_locks(); i++)
597  pthread_mutex_destroy(&openssl_mutexes[i]);
598  av_free(openssl_mutexes);
599  }
600 #endif
601  }
603 }
604 #endif
605 
606 static int print_ssl_error(URLContext *h, int ret)
607 {
608  TLSContext *c = h->priv_data;
609  int printed = 0, e, averr = AVERROR(EIO);
610  if (h->flags & AVIO_FLAG_NONBLOCK) {
611  int err = SSL_get_error(c->ssl, ret);
612  if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
613  return AVERROR(EAGAIN);
614  }
615  while ((e = ERR_get_error()) != 0) {
616  av_log(h, AV_LOG_ERROR, "%s\n", ERR_error_string(e, NULL));
617  printed = 1;
618  }
619  if (c->io_err) {
620  av_log(h, AV_LOG_ERROR, "IO error: %s\n", av_err2str(c->io_err));
621  printed = 1;
622  averr = c->io_err;
623  c->io_err = 0;
624  }
625  if (!printed)
626  av_log(h, AV_LOG_ERROR, "Unknown error\n");
627  return averr;
628 }
629 
630 static int tls_close(URLContext *h)
631 {
632  TLSContext *c = h->priv_data;
633  if (c->ssl) {
634  SSL_shutdown(c->ssl);
635  SSL_free(c->ssl);
636  }
637  if (c->ctx)
638  SSL_CTX_free(c->ctx);
639  ffurl_closep(&c->tls_shared.tcp);
640 #if OPENSSL_VERSION_NUMBER >= 0x1010000fL
641  if (c->url_bio_method)
642  BIO_meth_free(c->url_bio_method);
643 #endif
644 #if OPENSSL_VERSION_NUMBER < 0x10100000L
646 #endif
647  return 0;
648 }
649 
650 static int url_bio_create(BIO *b)
651 {
652 #if OPENSSL_VERSION_NUMBER >= 0x1010000fL
653  BIO_set_init(b, 1);
654  BIO_set_data(b, NULL);
655  BIO_set_flags(b, 0);
656 #else
657  b->init = 1;
658  b->ptr = NULL;
659  b->flags = 0;
660 #endif
661  return 1;
662 }
663 
664 static int url_bio_destroy(BIO *b)
665 {
666  return 1;
667 }
668 
669 #if OPENSSL_VERSION_NUMBER >= 0x1010000fL
670 #define GET_BIO_DATA(x) BIO_get_data(x)
671 #else
672 #define GET_BIO_DATA(x) (x)->ptr
673 #endif
674 
675 static int url_bio_bread(BIO *b, char *buf, int len)
676 {
678  int ret = ffurl_read(c->tls_shared.is_dtls ? c->tls_shared.udp : c->tls_shared.tcp, buf, len);
679  if (ret >= 0)
680  return ret;
681  BIO_clear_retry_flags(b);
682  if (ret == AVERROR_EXIT)
683  return 0;
684  if (ret == AVERROR(EAGAIN))
685  BIO_set_retry_read(b);
686  else
687  c->io_err = ret;
688  return -1;
689 }
690 
691 static int url_bio_bwrite(BIO *b, const char *buf, int len)
692 {
694  int ret = ffurl_write(c->tls_shared.is_dtls ? c->tls_shared.udp : c->tls_shared.tcp, buf, len);
695  if (ret >= 0)
696  return ret;
697  BIO_clear_retry_flags(b);
698  if (ret == AVERROR_EXIT)
699  return 0;
700  if (ret == AVERROR(EAGAIN))
701  BIO_set_retry_write(b);
702  else
703  c->io_err = ret;
704  return -1;
705 }
706 
707 static long url_bio_ctrl(BIO *b, int cmd, long num, void *ptr)
708 {
709  if (cmd == BIO_CTRL_FLUSH) {
710  BIO_clear_retry_flags(b);
711  return 1;
712  }
713  return 0;
714 }
715 
716 static int url_bio_bputs(BIO *b, const char *str)
717 {
718  return url_bio_bwrite(b, str, strlen(str));
719 }
720 
721 #if OPENSSL_VERSION_NUMBER < 0x1010000fL
722 static BIO_METHOD url_bio_method = {
723  .type = BIO_TYPE_SOURCE_SINK,
724  .name = "urlprotocol bio",
725  .bwrite = url_bio_bwrite,
726  .bread = url_bio_bread,
727  .bputs = url_bio_bputs,
728  .bgets = NULL,
729  .ctrl = url_bio_ctrl,
730  .create = url_bio_create,
731  .destroy = url_bio_destroy,
732 };
733 #endif
734 
736 {
737  TLSContext *p = h->priv_data;
738  BIO *bio;
739 #if OPENSSL_VERSION_NUMBER >= 0x1010000fL
740  p->url_bio_method = BIO_meth_new(BIO_TYPE_SOURCE_SINK, "urlprotocol bio");
741  BIO_meth_set_write(p->url_bio_method, url_bio_bwrite);
742  BIO_meth_set_read(p->url_bio_method, url_bio_bread);
743  BIO_meth_set_puts(p->url_bio_method, url_bio_bputs);
744  BIO_meth_set_ctrl(p->url_bio_method, url_bio_ctrl);
745  BIO_meth_set_create(p->url_bio_method, url_bio_create);
746  BIO_meth_set_destroy(p->url_bio_method, url_bio_destroy);
747  bio = BIO_new(p->url_bio_method);
748  BIO_set_data(bio, p);
749 #else
750  bio = BIO_new(&url_bio_method);
751  bio->ptr = p;
752 #endif
753  SSL_set_bio(p->ssl, bio, bio);
754 }
755 
756 static void openssl_info_callback(const SSL *ssl, int where, int ret) {
757  const char *method = "undefined";
758  TLSContext *ctx = (TLSContext*)SSL_get_ex_data(ssl, 0);
759 
760  if (where & SSL_ST_CONNECT) {
761  method = "SSL_connect";
762  } else if (where & SSL_ST_ACCEPT)
763  method = "SSL_accept";
764 
765  if (where & SSL_CB_LOOP) {
766  av_log(ctx, AV_LOG_DEBUG, "Info method=%s state=%s(%s), where=%d, ret=%d\n",
767  method, SSL_state_string(ssl), SSL_state_string_long(ssl), where, ret);
768  } else if (where & SSL_CB_ALERT) {
769  method = (where & SSL_CB_READ) ? "read":"write";
770  av_log(ctx, AV_LOG_DEBUG, "Alert method=%s state=%s(%s), where=%d, ret=%d\n",
771  method, SSL_state_string(ssl), SSL_state_string_long(ssl), where, ret);
772  }
773 }
774 
775 /**
776  * Always return 1 to accept any certificate. This is because we allow the peer to
777  * use a temporary self-signed certificate for DTLS.
778  */
779 static int openssl_dtls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
780 {
781  return 1;
782 }
783 
785 {
786  int ret = 0, r0, r1;
787  TLSContext *p = h->priv_data;
788 
789  r0 = SSL_do_handshake(p->ssl);
790  r1 = SSL_get_error(p->ssl, r0);
791  if (r0 <= 0) {
792  if (r1 != SSL_ERROR_WANT_READ && r1 != SSL_ERROR_WANT_WRITE && r1 != SSL_ERROR_ZERO_RETURN) {
793  av_log(p, AV_LOG_ERROR, "TLS: Read failed, r0=%d, r1=%d %s\n", r0, r1, openssl_get_error(p));
794  ret = AVERROR(EIO);
795  goto end;
796  }
797  } else {
798  av_log(p, AV_LOG_TRACE, "TLS: Read %d bytes, r0=%d, r1=%d\n", r0, r0, r1);
799  }
800 
801  /* Check whether the DTLS is completed. */
802  if (SSL_is_init_finished(p->ssl) != 1)
803  goto end;
804 
806 end:
807  return ret;
808 }
809 
811 {
812  int ret;
813  TLSContext *p = h->priv_data;
814  TLSShared *c = &p->tls_shared;
815  EVP_PKEY *pkey = NULL;
816  X509 *cert = NULL;
817  /* setup ca, private key, certificate */
818  if (c->ca_file) {
819  if (!SSL_CTX_load_verify_locations(p->ctx, c->ca_file, NULL))
820  av_log(h, AV_LOG_ERROR, "SSL_CTX_load_verify_locations %s\n", openssl_get_error(p));
821  }
822 
823  if (c->cert_file) {
824  ret = SSL_CTX_use_certificate_chain_file(p->ctx, c->cert_file);
825  if (ret <= 0) {
826  av_log(h, AV_LOG_ERROR, "Unable to load cert file %s: %s\n",
827  c->cert_file, openssl_get_error(p));
828  ret = AVERROR(EIO);
829  goto fail;
830  }
831  } else if (p->tls_shared.cert_buf) {
833  if (SSL_CTX_use_certificate(p->ctx, cert) != 1) {
834  av_log(p, AV_LOG_ERROR, "SSL: Init SSL_CTX_use_certificate failed, %s\n", openssl_get_error(p));
835  ret = AVERROR(EINVAL);
836  return ret;
837  }
838  } else if (p->tls_shared.is_dtls){
839  av_log(p, AV_LOG_ERROR, "TLS: Init cert failed, %s\n", openssl_get_error(p));
840  ret = AVERROR(EINVAL);
841  goto fail;
842  }
843 
844  if (c->key_file) {
845  ret = SSL_CTX_use_PrivateKey_file(p->ctx, c->key_file, SSL_FILETYPE_PEM);
846  if (ret <= 0) {
847  av_log(h, AV_LOG_ERROR, "Unable to load key file %s: %s\n",
848  c->key_file, openssl_get_error(p));
849  ret = AVERROR(EIO);
850  goto fail;
851  }
852  } else if (p->tls_shared.key_buf) {
853  p->pkey = pkey = pkey_from_pem_string(p->tls_shared.key_buf, 1);
854  if (SSL_CTX_use_PrivateKey(p->ctx, pkey) != 1) {
855  av_log(p, AV_LOG_ERROR, "TLS: Init SSL_CTX_use_PrivateKey failed, %s\n", openssl_get_error(p));
856  ret = AVERROR(EINVAL);
857  return ret;
858  }
859  } else if (p->tls_shared.is_dtls){
860  av_log(p, AV_LOG_ERROR, "TLS: Init pkey failed, %s\n", openssl_get_error(p));
861  ret = AVERROR(EINVAL);
862  goto fail;
863  }
864  ret = 0;
865 fail:
866  return ret;
867 }
868 
869 /**
870  * Once the DTLS role has been negotiated - active for the DTLS client or passive for the
871  * DTLS server - we proceed to set up the DTLS state and initiate the handshake.
872  */
873 static int dtls_start(URLContext *h, const char *url, int flags, AVDictionary **options)
874 {
875  TLSContext *p = h->priv_data;
876  TLSShared *c = &p->tls_shared;
877  int ret = 0;
878  c->is_dtls = 1;
879  const char* ciphers = "ALL";
880 #if OPENSSL_VERSION_NUMBER < 0x10002000L // v1.0.2
881  EC_KEY *ec_key = NULL;
882 #endif
883  /**
884  * The profile for OpenSSL's SRTP is SRTP_AES128_CM_SHA1_80, see ssl/d1_srtp.c.
885  * The profile for FFmpeg's SRTP is SRTP_AES128_CM_HMAC_SHA1_80, see libavformat/srtp.c.
886  */
887  const char* profiles = "SRTP_AES128_CM_SHA1_80";
888  /* Refer to the test cases regarding these curves in the WebRTC code. */
889 #if OPENSSL_VERSION_NUMBER >= 0x10100000L /* OpenSSL 1.1.0 */
890  const char* curves = "X25519:P-256:P-384:P-521";
891 #elif OPENSSL_VERSION_NUMBER >= 0x10002000L /* OpenSSL 1.0.2 */
892  const char* curves = "P-256:P-384:P-521";
893 #endif
894 
895 #if OPENSSL_VERSION_NUMBER < 0x10002000L /* OpenSSL v1.0.2 */
896  p->ctx = SSL_CTX_new(DTLSv1_method());
897 #else
898  p->ctx = SSL_CTX_new(DTLS_method());
899 #endif
900  if (!p->ctx) {
901  ret = AVERROR(ENOMEM);
902  goto fail;
903  }
904 
905 #if OPENSSL_VERSION_NUMBER >= 0x10002000L /* OpenSSL 1.0.2 */
906  /* For ECDSA, we could set the curves list. */
907  if (SSL_CTX_set1_curves_list(p->ctx, curves) != 1) {
908  av_log(p, AV_LOG_ERROR, "TLS: Init SSL_CTX_set1_curves_list failed, curves=%s, %s\n",
910  ret = AVERROR(EINVAL);
911  return ret;
912  }
913 #endif
914 
915  /**
916  * We activate "ALL" cipher suites to align with the peer's capabilities,
917  * ensuring maximum compatibility.
918  */
919  if (SSL_CTX_set_cipher_list(p->ctx, ciphers) != 1) {
920  av_log(p, AV_LOG_ERROR, "TLS: Init SSL_CTX_set_cipher_list failed, ciphers=%s, %s\n",
921  ciphers, openssl_get_error(p));
922  ret = AVERROR(EINVAL);
923  return ret;
924  }
926  if (ret < 0) goto fail;
927 
928 #if OPENSSL_VERSION_NUMBER < 0x10100000L // v1.1.x
929 #if OPENSSL_VERSION_NUMBER < 0x10002000L // v1.0.2
930  if (p->pkey)
931  ec_key = EVP_PKEY_get1_EC_KEY(p->pkey);
932  if (ec_key)
933  SSL_CTX_set_tmp_ecdh(p->ctx, ec_key);
934 #else
935  SSL_CTX_set_ecdh_auto(p->ctx, 1);
936 #endif
937 #endif
938 
939  /* Server will send Certificate Request. */
940  SSL_CTX_set_verify(p->ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, openssl_dtls_verify_callback);
941  /* The depth count is "level 0:peer certificate", "level 1: CA certificate",
942  * "level 2: higher level CA certificate", and so on. */
943  SSL_CTX_set_verify_depth(p->ctx, 4);
944  /* Whether we should read as many input bytes as possible (for non-blocking reads) or not. */
945  SSL_CTX_set_read_ahead(p->ctx, 1);
946  /* Setup the SRTP context */
947  if (SSL_CTX_set_tlsext_use_srtp(p->ctx, profiles)) {
948  av_log(p, AV_LOG_ERROR, "TLS: Init SSL_CTX_set_tlsext_use_srtp failed, profiles=%s, %s\n",
950  ret = AVERROR(EINVAL);
951  return ret;
952  }
953 
954  /* The ssl should not be created unless the ctx has been initialized. */
955  p->ssl = SSL_new(p->ctx);
956  if (!p->ssl) {
957  ret = AVERROR(ENOMEM);
958  goto fail;
959  }
960 
961  /* Setup the callback for logging. */
962  SSL_set_ex_data(p->ssl, 0, p);
963  SSL_set_info_callback(p->ssl, openssl_info_callback);
964  /**
965  * We have set the MTU to fragment the DTLS packet. It is important to note that the
966  * packet is split to ensure that each handshake packet is smaller than the MTU.
967  */
968  SSL_set_options(p->ssl, SSL_OP_NO_QUERY_MTU);
969  SSL_set_mtu(p->ssl, p->tls_shared.mtu);
970 #if OPENSSL_VERSION_NUMBER >= 0x100010b0L /* OpenSSL 1.0.1k */
971  DTLS_set_link_mtu(p->ssl, p->tls_shared.mtu);
972 #endif
974 
975  if (p->tls_shared.use_external_udp != 1) {
976  if ((ret = ff_tls_open_underlying(&p->tls_shared, h, url, options)) < 0) {
977  av_log(p, AV_LOG_ERROR, "Failed to connect %s\n", url);
978  return ret;
979  }
980  }
981 
982  /* Setup DTLS as passive, which is server role. */
983  c->listen ? SSL_set_accept_state(p->ssl) : SSL_set_connect_state(p->ssl);
984 
985  /**
986  * During initialization, we only need to call SSL_do_handshake once because SSL_read consumes
987  * the handshake message if the handshake is incomplete.
988  * To simplify maintenance, we initiate the handshake for both the DTLS server and client after
989  * sending out the ICE response in the start_active_handshake function. It's worth noting that
990  * although the DTLS server may receive the ClientHello immediately after sending out the ICE
991  * response, this shouldn't be an issue as the handshake function is called before any DTLS
992  * packets are received.
993  *
994  * The SSL_do_handshake can't be called if DTLS hasn't prepare for udp.
995  */
996  if (p->tls_shared.use_external_udp != 1) {
997  ret = dtls_handshake(h);
998  // Fatal SSL error, for example, no available suite when peer is DTLS 1.0 while we are DTLS 1.2.
999  if (ret < 0) {
1000  av_log(p, AV_LOG_ERROR, "TLS: Failed to drive SSL context, ret=%d\n", ret);
1001  return AVERROR(EIO);
1002  }
1003  }
1004 
1005  av_log(p, AV_LOG_VERBOSE, "TLS: Setup ok, MTU=%d, fingerprint %s\n",
1007 
1008  ret = 0;
1009 fail:
1010 #if OPENSSL_VERSION_NUMBER < 0x10002000L // v1.0.2
1011  EC_KEY_free(ec_key);
1012 #endif
1013  return ret;
1014 }
1015 
1016 /**
1017  * Cleanup the DTLS context.
1018  */
1020 {
1021  TLSContext *ctx = h->priv_data;
1022  SSL_free(ctx->ssl);
1023  SSL_CTX_free(ctx->ctx);
1024  av_freep(&ctx->tls_shared.fingerprint);
1025  av_freep(&ctx->tls_shared.cert_buf);
1026  av_freep(&ctx->tls_shared.key_buf);
1027  EVP_PKEY_free(ctx->pkey);
1028  return 0;
1029 }
1030 
1031 static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
1032 {
1033  TLSContext *p = h->priv_data;
1034  TLSShared *c = &p->tls_shared;
1035  int ret;
1036 
1037 #if OPENSSL_VERSION_NUMBER < 0x10100000L
1038  if ((ret = ff_openssl_init()) < 0)
1039  return ret;
1040 #endif
1041 
1042  if ((ret = ff_tls_open_underlying(c, h, uri, options)) < 0)
1043  goto fail;
1044 
1045  // We want to support all versions of TLS >= 1.0, but not the deprecated
1046  // and insecure SSLv2 and SSLv3. Despite the name, SSLv23_*_method()
1047  // enables support for all versions of SSL and TLS, and we then disable
1048  // support for the old protocols immediately after creating the context.
1049  p->ctx = SSL_CTX_new(c->listen ? SSLv23_server_method() : SSLv23_client_method());
1050  if (!p->ctx) {
1051  av_log(h, AV_LOG_ERROR, "%s\n", openssl_get_error(p));
1052  ret = AVERROR(EIO);
1053  goto fail;
1054  }
1055  SSL_CTX_set_options(p->ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
1057  if (ret < 0) goto fail;
1058  // Note, this doesn't check that the peer certificate actually matches
1059  // the requested hostname.
1060  if (c->verify)
1061  SSL_CTX_set_verify(p->ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
1062  p->ssl = SSL_new(p->ctx);
1063  if (!p->ssl) {
1064  av_log(h, AV_LOG_ERROR, "%s\n", openssl_get_error(p));
1065  ret = AVERROR(EIO);
1066  goto fail;
1067  }
1068  SSL_set_ex_data(p->ssl, 0, p);
1069  SSL_CTX_set_info_callback(p->ctx, openssl_info_callback);
1070  init_bio_method(h);
1071  if (!c->listen && !c->numerichost)
1072  SSL_set_tlsext_host_name(p->ssl, c->host);
1073  ret = c->listen ? SSL_accept(p->ssl) : SSL_connect(p->ssl);
1074  if (ret == 0) {
1075  av_log(h, AV_LOG_ERROR, "Unable to negotiate TLS/SSL session\n");
1076  ret = AVERROR(EIO);
1077  goto fail;
1078  } else if (ret < 0) {
1079  ret = print_ssl_error(h, ret);
1080  goto fail;
1081  }
1082 
1083  return 0;
1084 fail:
1085  tls_close(h);
1086  return ret;
1087 }
1088 
1089 static int tls_read(URLContext *h, uint8_t *buf, int size)
1090 {
1091  TLSContext *c = h->priv_data;
1092  URLContext *uc = c->tls_shared.is_dtls ? c->tls_shared.udp
1093  : c->tls_shared.tcp;
1094  int ret;
1095  // Set or clear the AVIO_FLAG_NONBLOCK on c->tls_shared.tcp
1096  uc->flags &= ~AVIO_FLAG_NONBLOCK;
1097  uc->flags |= h->flags & AVIO_FLAG_NONBLOCK;
1098  ret = SSL_read(c->ssl, buf, size);
1099  if (ret > 0)
1100  return ret;
1101  if (ret == 0)
1102  return AVERROR_EOF;
1103  return print_ssl_error(h, ret);
1104 }
1105 
1106 static int tls_write(URLContext *h, const uint8_t *buf, int size)
1107 {
1108  TLSContext *c = h->priv_data;
1109  URLContext *uc = c->tls_shared.is_dtls ? c->tls_shared.udp
1110  : c->tls_shared.tcp;
1111  int ret;
1112  // Set or clear the AVIO_FLAG_NONBLOCK on c->tls_shared.tcp
1113  uc->flags &= ~AVIO_FLAG_NONBLOCK;
1114  uc->flags |= h->flags & AVIO_FLAG_NONBLOCK;
1115  ret = SSL_write(c->ssl, buf, size);
1116  if (ret > 0)
1117  return ret;
1118  if (ret == 0)
1119  return AVERROR_EOF;
1120  return print_ssl_error(h, ret);
1121 }
1122 
1124 {
1125  TLSContext *c = h->priv_data;
1126  return ffurl_get_file_handle(c->tls_shared.tcp);
1127 }
1128 
1130 {
1131  TLSContext *s = h->priv_data;
1132  return ffurl_get_short_seek(s->tls_shared.tcp);
1133 }
1134 
1135 static const AVOption options[] = {
1136  TLS_COMMON_OPTIONS(TLSContext, tls_shared),
1137  { NULL }
1138 };
1139 
1140 static const AVClass tls_class = {
1141  .class_name = "tls",
1142  .item_name = av_default_item_name,
1143  .option = options,
1144  .version = LIBAVUTIL_VERSION_INT,
1145 };
1146 
1148  .name = "tls",
1149  .url_open2 = tls_open,
1150  .url_read = tls_read,
1151  .url_write = tls_write,
1152  .url_close = tls_close,
1153  .url_get_file_handle = tls_get_file_handle,
1154  .url_get_short_seek = tls_get_short_seek,
1155  .priv_data_size = sizeof(TLSContext),
1157  .priv_data_class = &tls_class,
1158 };
1159 
1160 static const AVClass dtls_class = {
1161  .class_name = "dtls",
1162  .item_name = av_default_item_name,
1163  .option = options,
1164  .version = LIBAVUTIL_VERSION_INT,
1165 };
1166 
1168  .name = "dtls",
1169  .url_open2 = dtls_start,
1170  .url_handshake = dtls_handshake,
1171  .url_close = dtls_close,
1172  .url_read = tls_read,
1173  .url_write = tls_write,
1174  .priv_data_size = sizeof(TLSContext),
1176  .priv_data_class = &dtls_class,
1177 };
error
static void error(const char *err)
Definition: target_bsf_fuzzer.c:32
flags
const SwsFlags flags[]
Definition: swscale.c:61
pthread_mutex_t
_fmutex pthread_mutex_t
Definition: os2threads.h:53
cert_from_pem_string
static X509 * cert_from_pem_string(const char *pem_str)
Deserialize a PEM‐encoded certificate from a NUL-terminated C string.
Definition: tls_openssl.c:446
AV_BPRINT_SIZE_UNLIMITED
#define AV_BPRINT_SIZE_UNLIMITED
TLSContext
Definition: tls_gnutls.c:44
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
opt.h
URL_PROTOCOL_FLAG_NETWORK
#define URL_PROTOCOL_FLAG_NETWORK
Definition: url.h:33
out
FILE * out
Definition: movenc.c:55
curves
static const Curve curves[]
Definition: vf_pseudocolor.c:192
av_bprint_init
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition: bprint.c:69
thread.h
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:57
pthread_mutex_init
static av_always_inline int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
Definition: os2threads.h:104
openssl_gen_private_key
static int openssl_gen_private_key(EVP_PKEY **pkey, EC_KEY **eckey)
Definition: tls_openssl.c:236
ffurl_write
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:202
md
#define md
Definition: vf_colormatrix.c:101
dtls_close
static av_cold int dtls_close(URLContext *h)
Cleanup the DTLS context.
Definition: tls_openssl.c:1019
mode
Definition: swscale.c:56
cleanup
static av_cold void cleanup(FlashSV2Context *s)
Definition: flashsv2enc.c:130
pthread_mutex_lock
static av_always_inline int pthread_mutex_lock(pthread_mutex_t *mutex)
Definition: os2threads.h:119
AVOption
AVOption.
Definition: opt.h:429
b
#define b
Definition: input.c:42
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:226
AVDictionary
Definition: dict.c:32
TLSShared::state
enum DTLSState state
Definition: tls.h:64
URLProtocol
Definition: url.h:51
os_support.h
ff_openssl_deinit
void ff_openssl_deinit(void)
Definition: tls_openssl.c:587
TLSShared::fingerprint
char * fingerprint
Definition: tls.h:70
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:31
av_get_random_seed
uint32_t av_get_random_seed(void)
Get a seed to use in conjunction with random functions.
Definition: random_seed.c:196
ff_mutex_unlock
static int ff_mutex_unlock(AVMutex *mutex)
Definition: thread.h:189
ff_dtls_export_materials
int ff_dtls_export_materials(URLContext *h, char *dtls_srtp_materials, size_t materials_sz)
Definition: tls_openssl.c:504
TLS_COMMON_OPTIONS
#define TLS_COMMON_OPTIONS(pstruct, options_field)
Definition: tls.h:83
tls_class
static const AVClass tls_class
Definition: tls_openssl.c:1140
fail
#define fail()
Definition: checkasm.h:196
ffurl_get_short_seek
int ffurl_get_short_seek(void *urlcontext)
Return the current short seek threshold value for this URL.
Definition: avio.c:839
url_bio_create
static int url_bio_create(BIO *b)
Definition: tls_openssl.c:650
type
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf type
Definition: writing_filters.txt:86
GET_BIO_DATA
#define GET_BIO_DATA(x)
Definition: tls_openssl.c:672
openssl_dtls_verify_callback
static int openssl_dtls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
Always return 1 to accept any certificate.
Definition: tls_openssl.c:779
openssl_init
static int openssl_init
Definition: tls_openssl.c:535
ff_ssl_read_key_cert
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)
Definition: tls_openssl.c:159
AV_LOG_TRACE
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
Definition: log.h:236
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:210
av_cold
#define av_cold
Definition: attributes.h:90
ff_dtls_state
int ff_dtls_state(URLContext *h)
Definition: tls_openssl.c:519
AVMutex
#define AVMutex
Definition: thread.h:184
s
#define s(width, name)
Definition: cbs_vp9.c:198
pthread_mutex_unlock
static av_always_inline int pthread_mutex_unlock(pthread_mutex_t *mutex)
Definition: os2threads.h:126
URLContext::flags
int flags
Definition: url.h:40
tls_write
static int tls_write(URLContext *h, const uint8_t *buf, int size)
Definition: tls_openssl.c:1106
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:231
ctx
AVFormatContext * ctx
Definition: movenc.c:49
ff_tls_protocol
const URLProtocol ff_tls_protocol
Definition: tls_openssl.c:1147
ff_dtls_set_udp
int ff_dtls_set_udp(URLContext *h, URLContext *udp)
Definition: tls_openssl.c:497
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
dtls_handshake
static int dtls_handshake(URLContext *h)
Definition: tls_openssl.c:784
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:76
result
and forward the result(frame or status change) to the corresponding input. If nothing is possible
NULL
#define NULL
Definition: coverity.c:32
openssl_mutex
static AVMutex openssl_mutex
Definition: tls_openssl.c:533
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:240
options
Definition: swscale.c:43
ff_ssl_gen_key_cert
int ff_ssl_gen_key_cert(char *key_buf, size_t key_sz, char *cert_buf, size_t cert_sz, char **fingerprint)
Definition: tls_openssl.c:381
url_bio_ctrl
static long url_bio_ctrl(BIO *b, int cmd, long num, void *ptr)
Definition: tls_openssl.c:707
ff_openssl_init
int ff_openssl_init(void)
Definition: tls_openssl.c:557
url_bio_destroy
static int url_bio_destroy(BIO *b)
Definition: tls_openssl.c:664
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
url_bio_bwrite
static int url_bio_bwrite(BIO *b, const char *buf, int len)
Definition: tls_openssl.c:691
tls_open
static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
Definition: tls_openssl.c:1031
TLSContext::error_message
char error_message[256]
Definition: tls_openssl.c:475
TLSShared::cert_buf
char * cert_buf
Definition: tls.h:73
ff_url_read_all
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:153
av_bprint_finalize
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition: bprint.c:240
url_bio_bread
static int url_bio_bread(BIO *b, char *buf, int len)
Definition: tls_openssl.c:675
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:87
av_err2str
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition: error.h:122
TLSContext::ctx
SSL_CTX * ctx
Definition: tls_openssl.c:468
AV_MUTEX_INITIALIZER
#define AV_MUTEX_INITIALIZER
Definition: thread.h:185
pkey_to_pem_string
static char * pkey_to_pem_string(EVP_PKEY *pkey)
Returns a heap‐allocated null‐terminated string containing the PEM‐encoded public key.
Definition: tls_openssl.c:39
size
int size
Definition: twinvq_data.h:10344
TLSContext::tls_shared
TLSShared tls_shared
Definition: tls_gnutls.c:46
URLProtocol::name
const char * name
Definition: url.h:52
options
static const AVOption options[]
Definition: tls_openssl.c:1135
TLSContext::io_err
int io_err
Definition: tls_gnutls.c:50
openssl_info_callback
static void openssl_info_callback(const SSL *ssl, int where, int ret)
Definition: tls_openssl.c:756
line
Definition: graph2dot.c:48
ff_mutex_lock
static int ff_mutex_lock(AVMutex *mutex)
Definition: thread.h:188
tls_get_file_handle
static int tls_get_file_handle(URLContext *h)
Definition: tls_openssl.c:1123
TLSShared::key_buf
char * key_buf
Definition: tls.h:74
TLSShared::use_external_udp
int use_external_udp
Definition: tls.h:66
init_bio_method
static av_cold void init_bio_method(URLContext *h)
Definition: tls_openssl.c:735
pthread_mutex_destroy
static av_always_inline int pthread_mutex_destroy(pthread_mutex_t *mutex)
Definition: os2threads.h:112
TLSContext::ssl
SSL * ssl
Definition: tls_openssl.c:469
URLContext
Definition: url.h:35
print_ssl_error
static int print_ssl_error(URLContext *h, int ret)
Definition: tls_openssl.c:606
openssl_get_error
static const char * openssl_get_error(TLSContext *ctx)
Retrieves the error message for the latest OpenSSL error.
Definition: tls_openssl.c:485
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
generate_fingerprint
static char * generate_fingerprint(X509 *cert)
Generate a SHA-256 fingerprint of an X.509 certificate.
Definition: tls_openssl.c:122
av_malloc_array
#define av_malloc_array(a, b)
Definition: tableprint_vlc.h:32
url.h
len
int len
Definition: vorbis_enc_data.h:426
cert_to_pem_string
static char * cert_to_pem_string(X509 *cert)
Serialize an X509 certificate to a av_malloc’d PEM string.
Definition: tls_openssl.c:81
ffurl_closep
int ffurl_closep(URLContext **hh)
Close the resource accessed by the URLContext h, and free the memory used by it.
Definition: avio.c:589
ff_tls_open_underlying
int ff_tls_open_underlying(TLSShared *c, URLContext *parent, const char *uri, AVDictionary **options)
Definition: tls.c:69
ret
ret
Definition: filter_design.txt:187
TLSShared::is_dtls
int is_dtls
Definition: tls.h:62
AVClass::class_name
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:81
averr
int averr
Definition: nvenc.c:126
av_bprintf
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition: bprint.c:99
network.h
tls.h
random_seed.h
tls_get_short_seek
static int tls_get_short_seek(URLContext *h)
Definition: tls_openssl.c:1129
profiles
static const AVProfile profiles[]
Definition: libfdk-aacenc.c:557
tls_read
static int tls_read(URLContext *h, uint8_t *buf, int size)
Definition: tls_openssl.c:1089
av_strdup
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:272
mem.h
MAX_CERTIFICATE_SIZE
#define MAX_CERTIFICATE_SIZE
Maximum size limit of a certificate and private key size.
Definition: tls.h:34
TLSShared::mtu
int mtu
The size of RTP packet, should generally be set to MTU.
Definition: tls.h:79
url_bio_method
static BIO_METHOD url_bio_method
Definition: tls_openssl.c:722
TLSShared
Definition: tls.h:47
openssl_init_ca_key_cert
static av_cold int openssl_init_ca_key_cert(URLContext *h)
Definition: tls_openssl.c:810
TLSContext::pkey
EVP_PKEY * pkey
Definition: tls_openssl.c:470
av_free
#define av_free(p)
Definition: tableprint_vlc.h:34
dtls_start
static int dtls_start(URLContext *h, const char *url, int flags, AVDictionary **options)
Once the DTLS role has been negotiated - active for the DTLS client or passive for the DTLS server - ...
Definition: tls_openssl.c:873
AVIO_FLAG_NONBLOCK
#define AVIO_FLAG_NONBLOCK
Use non-blocking mode.
Definition: avio.h:636
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
TLSContext::ctx
struct tls * ctx
Definition: tls_libtls.c:37
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
pkey_from_pem_string
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.
Definition: tls_openssl.c:416
h
h
Definition: vp9dsp_template.c:2070
AVERROR_EXIT
#define AVERROR_EXIT
Immediate exit was requested; the called function should not be restarted.
Definition: error.h:58
dtls_class
static const AVClass dtls_class
Definition: tls_openssl.c:1160
DTLS_STATE_FINISHED
@ DTLS_STATE_FINISHED
Definition: tls.h:40
tls_close
static int tls_close(URLContext *h)
Definition: tls_openssl.c:630
snprintf
#define snprintf
Definition: snprintf.h:34
ff_dtls_protocol
const URLProtocol ff_dtls_protocol
Definition: tls_openssl.c:1167
openssl_gen_certificate
static int openssl_gen_certificate(EVP_PKEY *pkey, X509 **cert, char **fingerprint)
Definition: tls_openssl.c:302
ffurl_get_file_handle
int ffurl_get_file_handle(URLContext *h)
Return the file descriptor associated with this URL.
Definition: avio.c:815
url_bio_bputs
static int url_bio_bputs(BIO *b, const char *str)
Definition: tls_openssl.c:716
ffurl_read
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:181