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  av_free(key_tem);
232  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 (EC_KEY_set_group(*eckey, ecgroup) != 1) {
266  av_log(NULL, AV_LOG_ERROR, "TLS: Generate private key, EC_KEY_set_group failed, %s\n", ERR_error_string(ERR_get_error(), NULL));
267  goto einval_end;
268  }
269 
270  if (EC_KEY_generate_key(*eckey) != 1) {
271  av_log(NULL, AV_LOG_ERROR, "TLS: Generate private key, EC_KEY_generate_key failed, %s\n", ERR_error_string(ERR_get_error(), NULL));
272  goto einval_end;
273  }
274 
275  if (EVP_PKEY_set1_EC_KEY(*pkey, *eckey) != 1) {
276  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));
277  goto einval_end;
278  }
279 #else
280  *pkey = EVP_EC_gen(curve);
281  if (!*pkey) {
282  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));
283  goto einval_end;
284  }
285 #endif
286  goto end;
287 
288 einval_end:
289  ret = AVERROR(EINVAL);
290 end:
291 #if OPENSSL_VERSION_NUMBER < 0x30000000L /* OpenSSL 3.0 */
292  EC_GROUP_free(ecgroup);
293 #endif
294  return ret;
295 }
296 
297 static int openssl_gen_certificate(EVP_PKEY *pkey, X509 **cert, char **fingerprint)
298 {
299  int ret = 0, serial, expire_day;
300  const char *aor = "lavf";
301  X509_NAME* subject = NULL;
302 
303  *cert= X509_new();
304  if (!*cert) {
305  goto enomem_end;
306  }
307 
308  // TODO: Support non-self-signed certificate, for example, load from a file.
309  subject = X509_NAME_new();
310  if (!subject) {
311  goto enomem_end;
312  }
313 
314  serial = (int)av_get_random_seed();
315  if (ASN1_INTEGER_set(X509_get_serialNumber(*cert), serial) != 1) {
316  av_log(NULL, AV_LOG_ERROR, "TLS: Failed to set serial, %s\n", ERR_error_string(ERR_get_error(), NULL));
317  goto einval_end;
318  }
319 
320  if (X509_NAME_add_entry_by_txt(subject, "CN", MBSTRING_ASC, aor, strlen(aor), -1, 0) != 1) {
321  av_log(NULL, AV_LOG_ERROR, "TLS: Failed to set CN, %s\n", ERR_error_string(ERR_get_error(), NULL));
322  goto einval_end;
323  }
324 
325  if (X509_set_issuer_name(*cert, subject) != 1) {
326  av_log(NULL, AV_LOG_ERROR, "TLS: Failed to set issuer, %s\n", ERR_error_string(ERR_get_error(), NULL));
327  goto einval_end;
328  }
329  if (X509_set_subject_name(*cert, subject) != 1) {
330  av_log(NULL, AV_LOG_ERROR, "TLS: Failed to set subject name, %s\n", ERR_error_string(ERR_get_error(), NULL));
331  goto einval_end;
332  }
333 
334  expire_day = 365;
335  if (!X509_gmtime_adj(X509_get_notBefore(*cert), 0)) {
336  av_log(NULL, AV_LOG_ERROR, "TLS: Failed to set notBefore, %s\n", ERR_error_string(ERR_get_error(), NULL));
337  goto einval_end;
338  }
339  if (!X509_gmtime_adj(X509_get_notAfter(*cert), 60*60*24*expire_day)) {
340  av_log(NULL, AV_LOG_ERROR, "TLS: Failed to set notAfter, %s\n", ERR_error_string(ERR_get_error(), NULL));
341  goto einval_end;
342  }
343 
344  if (X509_set_version(*cert, 2) != 1) {
345  av_log(NULL, AV_LOG_ERROR, "TLS: Failed to set version, %s\n", ERR_error_string(ERR_get_error(), NULL));
346  goto einval_end;
347  }
348 
349  if (X509_set_pubkey(*cert, pkey) != 1) {
350  av_log(NULL, AV_LOG_ERROR, "TLS: Failed to set public key, %s\n", ERR_error_string(ERR_get_error(), NULL));
351  goto einval_end;
352  }
353 
354  if (!X509_sign(*cert, pkey, EVP_sha1())) {
355  av_log(NULL, AV_LOG_ERROR, "TLS: Failed to sign certificate, %s\n", ERR_error_string(ERR_get_error(), NULL));
356  goto einval_end;
357  }
358 
359  *fingerprint = generate_fingerprint(*cert);
360  if (!*fingerprint) {
361  goto enomem_end;
362  }
363 
364  goto end;
365 enomem_end:
366  ret = AVERROR(ENOMEM);
367  goto end;
368 einval_end:
369  ret = AVERROR(EINVAL);
370 end:
371  X509_NAME_free(subject);
372  return ret;
373 }
374 
375 int ff_ssl_gen_key_cert(char *key_buf, size_t key_sz, char *cert_buf, size_t cert_sz, char **fingerprint)
376 {
377  int ret = 0;
378  EVP_PKEY *pkey = NULL;
379  EC_KEY *ec_key = NULL;
380  X509 *cert = NULL;
381  char *key_tem = NULL, *cert_tem = NULL;
382 
383  ret = openssl_gen_private_key(&pkey, &ec_key);
384  if (ret < 0) goto error;
385 
386  ret = openssl_gen_certificate(pkey, &cert, fingerprint);
387  if (ret < 0) goto error;
388 
389  key_tem = pkey_to_pem_string(pkey);
390  cert_tem = cert_to_pem_string(cert);
391 
392  snprintf(key_buf, key_sz, "%s", key_tem);
393  snprintf(cert_buf, cert_sz, "%s", cert_tem);
394 
395  av_free(key_tem);
396  av_free(cert_tem);
397 error:
398  return ret;
399 }
400 
401 
402 /**
403  * Deserialize a PEM‐encoded private or public key from a NUL-terminated C string.
404  *
405  * @param pem_str The PEM text, e.g.
406  * "-----BEGIN PRIVATE KEY-----\n…\n-----END PRIVATE KEY-----\n"
407  * @param is_priv If non-zero, parse as a PRIVATE key; otherwise, parse as a PUBLIC key.
408  * @return EVP_PKEY* on success (must EVP_PKEY_free()), or NULL on error.
409  */
410 static EVP_PKEY *pkey_from_pem_string(const char *pem_str, int is_priv)
411 {
412  BIO *mem = BIO_new_mem_buf(pem_str, -1);
413  if (!mem) {
414  av_log(NULL, AV_LOG_ERROR, "BIO_new_mem_buf failed\n");
415  return NULL;
416  }
417 
418  EVP_PKEY *pkey = NULL;
419  if (is_priv) {
420  pkey = PEM_read_bio_PrivateKey(mem, NULL, NULL, NULL);
421  } else {
422  pkey = PEM_read_bio_PUBKEY(mem, NULL, NULL, NULL);
423  }
424 
425  if (!pkey)
426  av_log(NULL, AV_LOG_ERROR, "Failed to parse %s key from string\n",
427  is_priv ? "private" : "public");
428 
429  BIO_free(mem);
430  return pkey;
431 }
432 
433 /**
434  * Deserialize a PEM‐encoded certificate from a NUL-terminated C string.
435  *
436  * @param pem_str The PEM text, e.g.
437  * "-----BEGIN CERTIFICATE-----\n…\n-----END CERTIFICATE-----\n"
438  * @return X509* on success (must X509_free()), or NULL on error.
439  */
440 static X509 *cert_from_pem_string(const char *pem_str)
441 {
442  BIO *mem = BIO_new_mem_buf(pem_str, -1);
443  if (!mem) {
444  av_log(NULL, AV_LOG_ERROR, "BIO_new_mem_buf failed\n");
445  return NULL;
446  }
447 
448  X509 *cert = PEM_read_bio_X509(mem, NULL, NULL, NULL);
449  if (!cert) {
450  av_log(NULL, AV_LOG_ERROR, "Failed to parse certificate from string\n");
451  return NULL;
452  }
453 
454  BIO_free(mem);
455  return cert;
456 }
457 
458 
459 typedef struct TLSContext {
460  const AVClass *class;
462  SSL_CTX *ctx;
463  SSL *ssl;
464  EVP_PKEY *pkey;
465  BIO_METHOD* url_bio_method;
466  int io_err;
467  char error_message[256];
468 } TLSContext;
469 
470 /**
471  * Retrieves the error message for the latest OpenSSL error.
472  *
473  * This function retrieves the error code from the thread's error queue, converts it
474  * to a human-readable string, and stores it in the TLSContext's error_message field.
475  * The error queue is then cleared using ERR_clear_error().
476  */
477 static const char* openssl_get_error(TLSContext *ctx)
478 {
479  int r2 = ERR_get_error();
480  if (r2) {
481  ERR_error_string_n(r2, ctx->error_message, sizeof(ctx->error_message));
482  } else
483  ctx->error_message[0] = '\0';
484 
485  ERR_clear_error();
486  return ctx->error_message;
487 }
488 
490 {
491  TLSContext *c = h->priv_data;
492  TLSShared *s = &c->tls_shared;
493 
494  if (s->is_dtls)
495  c->tls_shared.udp = sock;
496  else
497  c->tls_shared.tcp = sock;
498 
499  return 0;
500 }
501 
502 int ff_dtls_export_materials(URLContext *h, char *dtls_srtp_materials, size_t materials_sz)
503 {
504  int ret = 0;
505  const char* dst = "EXTRACTOR-dtls_srtp";
506  TLSContext *c = h->priv_data;
507 
508  ret = SSL_export_keying_material(c->ssl, dtls_srtp_materials, materials_sz,
509  dst, strlen(dst), NULL, 0, 0);
510  if (!ret) {
511  av_log(c, AV_LOG_ERROR, "TLS: Failed to export SRTP material, %s\n", openssl_get_error(c));
512  return -1;
513  }
514  return 0;
515 }
516 
518 {
519  TLSContext *c = h->priv_data;
520  return c->tls_shared.state;
521 }
522 
523 static int print_ssl_error(URLContext *h, int ret)
524 {
525  TLSContext *c = h->priv_data;
526  int printed = 0, e, averr = AVERROR(EIO);
527  if (h->flags & AVIO_FLAG_NONBLOCK) {
528  int err = SSL_get_error(c->ssl, ret);
529  if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
530  return AVERROR(EAGAIN);
531  }
532  while ((e = ERR_get_error()) != 0) {
533  av_log(h, AV_LOG_ERROR, "%s\n", ERR_error_string(e, NULL));
534  printed = 1;
535  }
536  if (c->io_err) {
537  av_log(h, AV_LOG_ERROR, "IO error: %s\n", av_err2str(c->io_err));
538  printed = 1;
539  averr = c->io_err;
540  c->io_err = 0;
541  }
542  if (!printed)
543  av_log(h, AV_LOG_ERROR, "Unknown error\n");
544  return averr;
545 }
546 
547 static int tls_close(URLContext *h)
548 {
549  TLSContext *c = h->priv_data;
550  if (c->ssl) {
551  SSL_shutdown(c->ssl);
552  SSL_free(c->ssl);
553  }
554  if (c->ctx)
555  SSL_CTX_free(c->ctx);
556  ffurl_closep(&c->tls_shared.tcp);
557  if (c->url_bio_method)
558  BIO_meth_free(c->url_bio_method);
559  return 0;
560 }
561 
562 static int url_bio_create(BIO *b)
563 {
564  BIO_set_init(b, 1);
565  BIO_set_data(b, NULL);
566  BIO_set_flags(b, 0);
567  return 1;
568 }
569 
570 static int url_bio_destroy(BIO *b)
571 {
572  return 1;
573 }
574 
575 static int url_bio_bread(BIO *b, char *buf, int len)
576 {
577  TLSContext *c = BIO_get_data(b);
578  int ret = ffurl_read(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  return 0;
584  if (ret == AVERROR(EAGAIN))
585  BIO_set_retry_read(b);
586  else
587  c->io_err = ret;
588  return -1;
589 }
590 
591 static int url_bio_bwrite(BIO *b, const char *buf, int len)
592 {
593  TLSContext *c = BIO_get_data(b);
594  int ret = ffurl_write(c->tls_shared.is_dtls ? c->tls_shared.udp : c->tls_shared.tcp, buf, len);
595  if (ret >= 0)
596  return ret;
597  BIO_clear_retry_flags(b);
598  if (ret == AVERROR_EXIT)
599  return 0;
600  if (ret == AVERROR(EAGAIN))
601  BIO_set_retry_write(b);
602  else
603  c->io_err = ret;
604  return -1;
605 }
606 
607 static long url_bio_ctrl(BIO *b, int cmd, long num, void *ptr)
608 {
609  if (cmd == BIO_CTRL_FLUSH) {
610  BIO_clear_retry_flags(b);
611  return 1;
612  }
613  return 0;
614 }
615 
616 static int url_bio_bputs(BIO *b, const char *str)
617 {
618  return url_bio_bwrite(b, str, strlen(str));
619 }
620 
622 {
623  TLSContext *p = h->priv_data;
624  BIO *bio;
625  int bio_idx = BIO_get_new_index();
626  if (bio_idx == -1)
627  return AVERROR_EXTERNAL;
628  p->url_bio_method = BIO_meth_new(bio_idx | BIO_TYPE_SOURCE_SINK, "urlprotocol bio");
629  BIO_meth_set_write(p->url_bio_method, url_bio_bwrite);
630  BIO_meth_set_read(p->url_bio_method, url_bio_bread);
631  BIO_meth_set_puts(p->url_bio_method, url_bio_bputs);
632  BIO_meth_set_ctrl(p->url_bio_method, url_bio_ctrl);
633  BIO_meth_set_create(p->url_bio_method, url_bio_create);
634  BIO_meth_set_destroy(p->url_bio_method, url_bio_destroy);
635  bio = BIO_new(p->url_bio_method);
636  BIO_set_data(bio, p);
637 
638  SSL_set_bio(p->ssl, bio, bio);
639  return 0;
640 }
641 
642 static void openssl_info_callback(const SSL *ssl, int where, int ret) {
643  const char *method = "undefined";
644  TLSContext *ctx = (TLSContext*)SSL_get_ex_data(ssl, 0);
645 
646  if (where & SSL_ST_CONNECT) {
647  method = "SSL_connect";
648  } else if (where & SSL_ST_ACCEPT)
649  method = "SSL_accept";
650 
651  if (where & SSL_CB_LOOP) {
652  av_log(ctx, AV_LOG_DEBUG, "Info method=%s state=%s(%s), where=%d, ret=%d\n",
653  method, SSL_state_string(ssl), SSL_state_string_long(ssl), where, ret);
654  } else if (where & SSL_CB_ALERT) {
655  method = (where & SSL_CB_READ) ? "read":"write";
656  av_log(ctx, AV_LOG_DEBUG, "Alert method=%s state=%s(%s), where=%d, ret=%d\n",
657  method, SSL_state_string(ssl), SSL_state_string_long(ssl), where, ret);
658  }
659 }
660 
661 /**
662  * Always return 1 to accept any certificate. This is because we allow the peer to
663  * use a temporary self-signed certificate for DTLS.
664  */
665 static int openssl_dtls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
666 {
667  return 1;
668 }
669 
671 {
672  int ret = 0, r0, r1;
673  TLSContext *p = h->priv_data;
674 
675  r0 = SSL_do_handshake(p->ssl);
676  r1 = SSL_get_error(p->ssl, r0);
677  if (r0 <= 0) {
678  if (r1 != SSL_ERROR_WANT_READ && r1 != SSL_ERROR_WANT_WRITE && r1 != SSL_ERROR_ZERO_RETURN) {
679  av_log(p, AV_LOG_ERROR, "TLS: Read failed, r0=%d, r1=%d %s\n", r0, r1, openssl_get_error(p));
680  ret = AVERROR(EIO);
681  goto end;
682  }
683  } else {
684  av_log(p, AV_LOG_TRACE, "TLS: Read %d bytes, r0=%d, r1=%d\n", r0, r0, r1);
685  }
686 
687  /* Check whether the DTLS is completed. */
688  if (SSL_is_init_finished(p->ssl) != 1)
689  goto end;
690 
692 end:
693  return ret;
694 }
695 
697 {
698  int ret;
699  TLSContext *p = h->priv_data;
700  TLSShared *c = &p->tls_shared;
701  EVP_PKEY *pkey = NULL;
702  X509 *cert = NULL;
703  /* setup ca, private key, certificate */
704  if (c->ca_file) {
705  if (!SSL_CTX_load_verify_locations(p->ctx, c->ca_file, NULL))
706  av_log(h, AV_LOG_ERROR, "SSL_CTX_load_verify_locations %s\n", openssl_get_error(p));
707  }
708 
709  if (c->cert_file) {
710  ret = SSL_CTX_use_certificate_chain_file(p->ctx, c->cert_file);
711  if (ret <= 0) {
712  av_log(h, AV_LOG_ERROR, "Unable to load cert file %s: %s\n",
713  c->cert_file, openssl_get_error(p));
714  ret = AVERROR(EIO);
715  goto fail;
716  }
717  } else if (c->cert_buf) {
718  cert = cert_from_pem_string(c->cert_buf);
719  if (SSL_CTX_use_certificate(p->ctx, cert) != 1) {
720  av_log(p, AV_LOG_ERROR, "SSL: Init SSL_CTX_use_certificate failed, %s\n", openssl_get_error(p));
721  ret = AVERROR(EINVAL);
722  return ret;
723  }
724  } else if (c->is_dtls){
725  av_log(p, AV_LOG_ERROR, "TLS: Init cert failed, %s\n", openssl_get_error(p));
726  ret = AVERROR(EINVAL);
727  goto fail;
728  }
729 
730  if (c->key_file) {
731  ret = SSL_CTX_use_PrivateKey_file(p->ctx, c->key_file, SSL_FILETYPE_PEM);
732  if (ret <= 0) {
733  av_log(h, AV_LOG_ERROR, "Unable to load key file %s: %s\n",
734  c->key_file, openssl_get_error(p));
735  ret = AVERROR(EIO);
736  goto fail;
737  }
738  } else if (c->key_buf) {
739  p->pkey = pkey = pkey_from_pem_string(c->key_buf, 1);
740  if (SSL_CTX_use_PrivateKey(p->ctx, pkey) != 1) {
741  av_log(p, AV_LOG_ERROR, "TLS: Init SSL_CTX_use_PrivateKey failed, %s\n", openssl_get_error(p));
742  ret = AVERROR(EINVAL);
743  return ret;
744  }
745  } else if (c->is_dtls) {
746  av_log(p, AV_LOG_ERROR, "TLS: Init pkey failed, %s\n", openssl_get_error(p));
747  ret = AVERROR(EINVAL);
748  goto fail;
749  }
750  ret = 0;
751 fail:
752  return ret;
753 }
754 
755 /**
756  * Once the DTLS role has been negotiated - active for the DTLS client or passive for the
757  * DTLS server - we proceed to set up the DTLS state and initiate the handshake.
758  */
759 static int dtls_start(URLContext *h, const char *url, int flags, AVDictionary **options)
760 {
761  TLSContext *p = h->priv_data;
762  TLSShared *c = &p->tls_shared;
763  int ret = 0;
764  c->is_dtls = 1;
765  const char* ciphers = "ALL";
766 
767  /**
768  * The profile for OpenSSL's SRTP is SRTP_AES128_CM_SHA1_80, see ssl/d1_srtp.c.
769  * The profile for FFmpeg's SRTP is SRTP_AES128_CM_HMAC_SHA1_80, see libavformat/srtp.c.
770  */
771  const char* profiles = "SRTP_AES128_CM_SHA1_80";
772  /* Refer to the test cases regarding these curves in the WebRTC code. */
773  const char* curves = "X25519:P-256:P-384:P-521";
774 
775  p->ctx = SSL_CTX_new(DTLS_method());
776  if (!p->ctx) {
777  ret = AVERROR(ENOMEM);
778  goto fail;
779  }
780 
781  /* For ECDSA, we could set the curves list. */
782  if (SSL_CTX_set1_curves_list(p->ctx, curves) != 1) {
783  av_log(p, AV_LOG_ERROR, "TLS: Init SSL_CTX_set1_curves_list failed, curves=%s, %s\n",
785  ret = AVERROR(EINVAL);
786  return ret;
787  }
788 
789  /**
790  * We activate "ALL" cipher suites to align with the peer's capabilities,
791  * ensuring maximum compatibility.
792  */
793  if (SSL_CTX_set_cipher_list(p->ctx, ciphers) != 1) {
794  av_log(p, AV_LOG_ERROR, "TLS: Init SSL_CTX_set_cipher_list failed, ciphers=%s, %s\n",
795  ciphers, openssl_get_error(p));
796  ret = AVERROR(EINVAL);
797  return ret;
798  }
800  if (ret < 0) goto fail;
801 
802  /* Server will send Certificate Request. */
803  SSL_CTX_set_verify(p->ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, openssl_dtls_verify_callback);
804  /* The depth count is "level 0:peer certificate", "level 1: CA certificate",
805  * "level 2: higher level CA certificate", and so on. */
806  SSL_CTX_set_verify_depth(p->ctx, 4);
807  /* Whether we should read as many input bytes as possible (for non-blocking reads) or not. */
808  SSL_CTX_set_read_ahead(p->ctx, 1);
809  /* Setup the SRTP context */
810  if (SSL_CTX_set_tlsext_use_srtp(p->ctx, profiles)) {
811  av_log(p, AV_LOG_ERROR, "TLS: Init SSL_CTX_set_tlsext_use_srtp failed, profiles=%s, %s\n",
813  ret = AVERROR(EINVAL);
814  return ret;
815  }
816 
817  /* The ssl should not be created unless the ctx has been initialized. */
818  p->ssl = SSL_new(p->ctx);
819  if (!p->ssl) {
820  ret = AVERROR(ENOMEM);
821  goto fail;
822  }
823 
824  /* Setup the callback for logging. */
825  SSL_set_ex_data(p->ssl, 0, p);
826  SSL_set_info_callback(p->ssl, openssl_info_callback);
827  /**
828  * We have set the MTU to fragment the DTLS packet. It is important to note that the
829  * packet is split to ensure that each handshake packet is smaller than the MTU.
830  */
831  SSL_set_options(p->ssl, SSL_OP_NO_QUERY_MTU);
832  SSL_set_mtu(p->ssl, p->tls_shared.mtu);
833  DTLS_set_link_mtu(p->ssl, p->tls_shared.mtu);
834  ret = init_bio_method(h);
835  if (ret < 0)
836  goto fail;
837 
838  if (p->tls_shared.external_sock != 1) {
839  if ((ret = ff_tls_open_underlying(&p->tls_shared, h, url, options)) < 0) {
840  av_log(p, AV_LOG_ERROR, "Failed to connect %s\n", url);
841  return ret;
842  }
843  }
844 
845  /* Setup DTLS as passive, which is server role. */
846  c->listen ? SSL_set_accept_state(p->ssl) : SSL_set_connect_state(p->ssl);
847 
848  /**
849  * During initialization, we only need to call SSL_do_handshake once because SSL_read consumes
850  * the handshake message if the handshake is incomplete.
851  * To simplify maintenance, we initiate the handshake for both the DTLS server and client after
852  * sending out the ICE response in the start_active_handshake function. It's worth noting that
853  * although the DTLS server may receive the ClientHello immediately after sending out the ICE
854  * response, this shouldn't be an issue as the handshake function is called before any DTLS
855  * packets are received.
856  *
857  * The SSL_do_handshake can't be called if DTLS hasn't prepare for udp.
858  */
859  if (p->tls_shared.external_sock != 1) {
860  ret = dtls_handshake(h);
861  // Fatal SSL error, for example, no available suite when peer is DTLS 1.0 while we are DTLS 1.2.
862  if (ret < 0) {
863  av_log(p, AV_LOG_ERROR, "TLS: Failed to drive SSL context, ret=%d\n", ret);
864  return AVERROR(EIO);
865  }
866  }
867 
868  av_log(p, AV_LOG_VERBOSE, "TLS: Setup ok, MTU=%d\n", p->tls_shared.mtu);
869 
870  ret = 0;
871 fail:
872  return ret;
873 }
874 
875 /**
876  * Cleanup the DTLS context.
877  */
879 {
880  TLSContext *ctx = h->priv_data;
881  SSL_free(ctx->ssl);
882  SSL_CTX_free(ctx->ctx);
883  av_freep(&ctx->tls_shared.cert_buf);
884  av_freep(&ctx->tls_shared.key_buf);
885  EVP_PKEY_free(ctx->pkey);
886  return 0;
887 }
888 
889 static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
890 {
891  TLSContext *p = h->priv_data;
892  TLSShared *c = &p->tls_shared;
893  int ret;
894 
895  if ((ret = ff_tls_open_underlying(c, h, uri, options)) < 0)
896  goto fail;
897 
898  // We want to support all versions of TLS >= 1.0, but not the deprecated
899  // and insecure SSLv2 and SSLv3. Despite the name, TLS_*_method()
900  // enables support for all versions of SSL and TLS, and we then disable
901  // support for the old protocols immediately after creating the context.
902  p->ctx = SSL_CTX_new(c->listen ? TLS_server_method() : TLS_client_method());
903  if (!p->ctx) {
904  av_log(h, AV_LOG_ERROR, "%s\n", openssl_get_error(p));
905  ret = AVERROR(EIO);
906  goto fail;
907  }
908  if (!SSL_CTX_set_min_proto_version(p->ctx, TLS1_VERSION)) {
909  av_log(h, AV_LOG_ERROR, "Failed to set minimum TLS version to TLSv1\n");
911  goto fail;
912  }
914  if (ret < 0) goto fail;
915  // Note, this doesn't check that the peer certificate actually matches
916  // the requested hostname.
917  if (c->verify)
918  SSL_CTX_set_verify(p->ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
919  p->ssl = SSL_new(p->ctx);
920  if (!p->ssl) {
921  av_log(h, AV_LOG_ERROR, "%s\n", openssl_get_error(p));
922  ret = AVERROR(EIO);
923  goto fail;
924  }
925  SSL_set_ex_data(p->ssl, 0, p);
926  SSL_CTX_set_info_callback(p->ctx, openssl_info_callback);
927  ret = init_bio_method(h);
928  if (ret < 0)
929  goto fail;
930  if (!c->listen && !c->numerichost)
931  SSL_set_tlsext_host_name(p->ssl, c->host);
932  ret = c->listen ? SSL_accept(p->ssl) : SSL_connect(p->ssl);
933  if (ret == 0) {
934  av_log(h, AV_LOG_ERROR, "Unable to negotiate TLS/SSL session\n");
935  ret = AVERROR(EIO);
936  goto fail;
937  } else if (ret < 0) {
938  ret = print_ssl_error(h, ret);
939  goto fail;
940  }
941 
942  return 0;
943 fail:
944  tls_close(h);
945  return ret;
946 }
947 
948 static int tls_read(URLContext *h, uint8_t *buf, int size)
949 {
950  TLSContext *c = h->priv_data;
951  URLContext *uc = c->tls_shared.is_dtls ? c->tls_shared.udp
952  : c->tls_shared.tcp;
953  int ret;
954  // Set or clear the AVIO_FLAG_NONBLOCK on c->tls_shared.tcp
955  uc->flags &= ~AVIO_FLAG_NONBLOCK;
956  uc->flags |= h->flags & AVIO_FLAG_NONBLOCK;
957  ret = SSL_read(c->ssl, buf, size);
958  if (ret > 0)
959  return ret;
960  if (ret == 0)
961  return AVERROR_EOF;
962  return print_ssl_error(h, ret);
963 }
964 
965 static int tls_write(URLContext *h, const uint8_t *buf, int size)
966 {
967  TLSContext *c = h->priv_data;
968  URLContext *uc = c->tls_shared.is_dtls ? c->tls_shared.udp
969  : c->tls_shared.tcp;
970  int ret;
971  // Set or clear the AVIO_FLAG_NONBLOCK on c->tls_shared.tcp
972  uc->flags &= ~AVIO_FLAG_NONBLOCK;
973  uc->flags |= h->flags & AVIO_FLAG_NONBLOCK;
974  ret = SSL_write(c->ssl, buf, size);
975  if (ret > 0)
976  return ret;
977  if (ret == 0)
978  return AVERROR_EOF;
979  return print_ssl_error(h, ret);
980 }
981 
983 {
984  TLSContext *p = h->priv_data;
985  TLSShared *c = &p->tls_shared;
986  return ffurl_get_file_handle(c->is_dtls ? c->udp : c->tcp);
987 }
988 
990 {
991  TLSContext *p = h->priv_data;
992  TLSShared *c = &p->tls_shared;
993  return ffurl_get_short_seek(c->is_dtls ? c->udp : c->tcp);
994 }
995 
996 static const AVOption options[] = {
997  TLS_COMMON_OPTIONS(TLSContext, tls_shared),
998  { NULL }
999 };
1000 
1001 static const AVClass tls_class = {
1002  .class_name = "tls",
1003  .item_name = av_default_item_name,
1004  .option = options,
1005  .version = LIBAVUTIL_VERSION_INT,
1006 };
1007 
1009  .name = "tls",
1010  .url_open2 = tls_open,
1011  .url_read = tls_read,
1012  .url_write = tls_write,
1013  .url_close = tls_close,
1014  .url_get_file_handle = tls_get_file_handle,
1015  .url_get_short_seek = tls_get_short_seek,
1016  .priv_data_size = sizeof(TLSContext),
1018  .priv_data_class = &tls_class,
1019 };
1020 
1021 static const AVClass dtls_class = {
1022  .class_name = "dtls",
1023  .item_name = av_default_item_name,
1024  .option = options,
1025  .version = LIBAVUTIL_VERSION_INT,
1026 };
1027 
1029  .name = "dtls",
1030  .url_open2 = dtls_start,
1031  .url_handshake = dtls_handshake,
1032  .url_close = dtls_close,
1033  .url_read = tls_read,
1034  .url_write = tls_write,
1035  .url_get_file_handle = tls_get_file_handle,
1036  .url_get_short_seek = tls_get_short_seek,
1037  .priv_data_size = sizeof(TLSContext),
1039  .priv_data_class = &dtls_class,
1040 };
error
static void error(const char *err)
Definition: target_bsf_fuzzer.c:32
flags
const SwsFlags flags[]
Definition: swscale.c:61
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:440
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
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:57
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:878
cleanup
static av_cold void cleanup(FlashSV2Context *s)
Definition: flashsv2enc.c:130
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:66
URLProtocol
Definition: url.h:51
os_support.h
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_dtls_export_materials
int ff_dtls_export_materials(URLContext *h, char *dtls_srtp_materials, size_t materials_sz)
Definition: tls_openssl.c:502
TLS_COMMON_OPTIONS
#define TLS_COMMON_OPTIONS(pstruct, options_field)
Definition: tls.h:89
tls_class
static const AVClass tls_class
Definition: tls_openssl.c:1001
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:562
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:665
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:517
s
#define s(width, name)
Definition: cbs_vp9.c:198
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:965
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:1008
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
dtls_handshake
static int dtls_handshake(URLContext *h)
Definition: tls_openssl.c:670
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
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:375
url_bio_ctrl
static long url_bio_ctrl(BIO *b, int cmd, long num, void *ptr)
Definition: tls_openssl.c:607
url_bio_destroy
static int url_bio_destroy(BIO *b)
Definition: tls_openssl.c:570
ff_tls_set_external_socket
int ff_tls_set_external_socket(URLContext *h, URLContext *sock)
Definition: tls_openssl.c:489
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:591
tls_open
static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
Definition: tls_openssl.c:889
TLSContext::error_message
char error_message[256]
Definition: tls_openssl.c:467
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:150
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:575
init_bio_method
static av_cold int init_bio_method(URLContext *h)
Definition: tls_openssl.c:621
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:87
TLSShared::external_sock
int external_sock
Definition: tls.h:60
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:462
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:996
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:642
AVERROR_EXTERNAL
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:59
tls_get_file_handle
static int tls_get_file_handle(URLContext *h)
Definition: tls_openssl.c:982
TLSContext::ssl
SSL * ssl
Definition: tls_openssl.c:463
URLContext
Definition: url.h:35
print_ssl_error
static int print_ssl_error(URLContext *h, int ret)
Definition: tls_openssl.c:523
openssl_get_error
static const char * openssl_get_error(TLSContext *ctx)
Retrieves the error message for the latest OpenSSL error.
Definition: tls_openssl.c:477
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
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
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:135
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:989
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:948
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:76
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:696
TLSContext::pkey
EVP_PKEY * pkey
Definition: tls_openssl.c:464
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:759
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:410
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:1021
DTLS_STATE_FINISHED
@ DTLS_STATE_FINISHED
Definition: tls.h:40
tls_close
static int tls_close(URLContext *h)
Definition: tls_openssl.c:547
snprintf
#define snprintf
Definition: snprintf.h:34
ff_dtls_protocol
const URLProtocol ff_dtls_protocol
Definition: tls_openssl.c:1028
openssl_gen_certificate
static int openssl_gen_certificate(EVP_PKEY *pkey, X509 **cert, char **fingerprint)
Definition: tls_openssl.c:297
TLSContext::url_bio_method
BIO_METHOD * url_bio_method
Definition: tls_openssl.c:465
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:616
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