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 #include <openssl/x509v3.h>
35 
36 /**
37  * Convert an EVP_PKEY to a PEM string.
38  */
39 static int pkey_to_pem_string(EVP_PKEY *pkey, char *out, size_t out_sz)
40 {
41  BIO *mem = NULL;
42  size_t read_bytes = 0;
43 
44  if (!pkey || !out || !out_sz)
45  goto done;
46 
47  if (!(mem = BIO_new(BIO_s_mem())))
48  goto done;
49 
50  if (!PEM_write_bio_PrivateKey(mem, pkey, NULL, NULL, 0, NULL, NULL))
51  goto done;
52 
53  if (!BIO_read_ex(mem, out, out_sz - 1, &read_bytes))
54  goto done;
55 
56 done:
57  BIO_free(mem);
58  if (out && out_sz)
59  out[read_bytes] = '\0';
60  return read_bytes;
61 }
62 
63 /**
64  * Convert an X509 certificate to a PEM string.
65  */
66 static int cert_to_pem_string(X509 *cert, char *out, size_t out_sz)
67 {
68  BIO *mem = NULL;
69  size_t read_bytes = 0;
70 
71  if (!cert || !out || !out_sz)
72  goto done;
73 
74  if (!(mem = BIO_new(BIO_s_mem())))
75  goto done;
76 
77  if (!PEM_write_bio_X509(mem, cert))
78  goto done;
79 
80  if (!BIO_read_ex(mem, out, out_sz - 1, &read_bytes))
81  goto done;
82 
83 done:
84  BIO_free(mem);
85  if (out && out_sz)
86  out[read_bytes] = '\0';
87  return read_bytes;
88 }
89 
90 
91 /**
92  * Generate a SHA-256 fingerprint of an X.509 certificate.
93  */
94 static int x509_fingerprint(X509 *cert, char **fingerprint)
95 {
96  unsigned char md[EVP_MAX_MD_SIZE];
97  int n = 0;
98  AVBPrint buf;
99 
100  if (X509_digest(cert, EVP_sha256(), md, &n) != 1) {
101  av_log(NULL, AV_LOG_ERROR, "TLS: Failed to generate fingerprint, %s\n",
102  ERR_error_string(ERR_get_error(), NULL));
103  return AVERROR(ENOMEM);
104  }
105 
106  av_bprint_init(&buf, n*3, n*3);
107 
108  for (int i = 0; i < n - 1; i++)
109  av_bprintf(&buf, "%02X:", md[i]);
110  av_bprintf(&buf, "%02X", md[n - 1]);
111 
112  return av_bprint_finalize(&buf, fingerprint);
113 }
114 
115 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)
116 {
117  int ret = 0;
118  BIO *key_b = NULL, *cert_b = NULL;
119  AVBPrint key_bp, cert_bp;
120  EVP_PKEY *pkey = NULL;
121  X509 *cert = NULL;
122 
123  /* To prevent a crash during cleanup, always initialize it. */
125  av_bprint_init(&cert_bp, 1, MAX_CERTIFICATE_SIZE);
126 
127  /* Read key file. */
128  ret = ff_url_read_all(key_url, &key_bp);
129  if (ret < 0) {
130  av_log(NULL, AV_LOG_ERROR, "TLS: Failed to open key file %s\n", key_url);
131  goto end;
132  }
133 
134  if (!(key_b = BIO_new(BIO_s_mem()))) {
135  ret = AVERROR(ENOMEM);
136  goto end;
137  }
138 
139  BIO_write(key_b, key_bp.str, key_bp.len);
140  pkey = PEM_read_bio_PrivateKey(key_b, NULL, NULL, NULL);
141  if (!pkey) {
142  av_log(NULL, AV_LOG_ERROR, "TLS: Failed to read private key from %s\n", key_url);
143  ret = AVERROR(EIO);
144  goto end;
145  }
146 
147  /* Read certificate. */
148  ret = ff_url_read_all(cert_url, &cert_bp);
149  if (ret < 0) {
150  av_log(NULL, AV_LOG_ERROR, "TLS: Failed to open cert file %s\n", cert_url);
151  goto end;
152  }
153 
154  if (!(cert_b = BIO_new(BIO_s_mem()))) {
155  ret = AVERROR(ENOMEM);
156  goto end;
157  }
158 
159  BIO_write(cert_b, cert_bp.str, cert_bp.len);
160  cert = PEM_read_bio_X509(cert_b, NULL, NULL, NULL);
161  if (!cert) {
162  av_log(NULL, AV_LOG_ERROR, "TLS: Failed to read certificate from %s\n", cert_url);
163  ret = AVERROR(EIO);
164  goto end;
165  }
166 
167  pkey_to_pem_string(pkey, key_buf, key_sz);
168  cert_to_pem_string(cert, cert_buf, cert_sz);
169 
170  ret = x509_fingerprint(cert, fingerprint);
171  if (ret < 0)
172  av_log(NULL, AV_LOG_ERROR, "TLS: Failed to generate fingerprint from %s\n", cert_url);
173 
174 end:
175  BIO_free(key_b);
176  av_bprint_finalize(&key_bp, NULL);
177  BIO_free(cert_b);
178  av_bprint_finalize(&cert_bp, NULL);
179  EVP_PKEY_free(pkey);
180  X509_free(cert);
181  return ret;
182 }
183 
184 static int openssl_gen_private_key(EVP_PKEY **pkey)
185 {
186  int ret = 0;
187 
188  /**
189  * Note that secp256r1 in openssl is called NID_X9_62_prime256v1 or prime256v1 in string,
190  * not NID_secp256k1 or secp256k1 in string.
191  *
192  * TODO: Should choose the curves in ClientHello.supported_groups, for example:
193  * Supported Group: x25519 (0x001d)
194  * Supported Group: secp256r1 (0x0017)
195  * Supported Group: secp384r1 (0x0018)
196  */
197 #if OPENSSL_VERSION_NUMBER < 0x30000000L /* OpenSSL 3.0 */
198  EC_GROUP *ecgroup = NULL;
199  EC_KEY *eckey = NULL;
200  int curve = NID_X9_62_prime256v1;
201 #else
202  const char *curve = SN_X9_62_prime256v1;
203 #endif
204 
205 #if OPENSSL_VERSION_NUMBER < 0x30000000L /* OpenSSL 3.0 */
206  *pkey = EVP_PKEY_new();
207  if (!*pkey)
208  return AVERROR(ENOMEM);
209 
210  eckey = EC_KEY_new();
211  if (!eckey) {
212  EVP_PKEY_free(*pkey);
213  *pkey = NULL;
214  return AVERROR(ENOMEM);
215  }
216 
217  ecgroup = EC_GROUP_new_by_curve_name(curve);
218  if (!ecgroup) {
219  av_log(NULL, AV_LOG_ERROR, "TLS: Create EC group by curve=%d failed, %s", curve, ERR_error_string(ERR_get_error(), NULL));
220  goto einval_end;
221  }
222 
223  if (EC_KEY_set_group(eckey, ecgroup) != 1) {
224  av_log(NULL, AV_LOG_ERROR, "TLS: Generate private key, EC_KEY_set_group failed, %s\n", ERR_error_string(ERR_get_error(), NULL));
225  goto einval_end;
226  }
227 
228  if (EC_KEY_generate_key(eckey) != 1) {
229  av_log(NULL, AV_LOG_ERROR, "TLS: Generate private key, EC_KEY_generate_key failed, %s\n", ERR_error_string(ERR_get_error(), NULL));
230  goto einval_end;
231  }
232 
233  if (EVP_PKEY_set1_EC_KEY(*pkey, eckey) != 1) {
234  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));
235  goto einval_end;
236  }
237 #else
238  *pkey = EVP_EC_gen(curve);
239  if (!*pkey) {
240  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));
241  goto einval_end;
242  }
243 #endif
244  goto end;
245 
246 einval_end:
247  ret = AVERROR(EINVAL);
248  EVP_PKEY_free(*pkey);
249  *pkey = NULL;
250 end:
251 #if OPENSSL_VERSION_NUMBER < 0x30000000L /* OpenSSL 3.0 */
252  EC_GROUP_free(ecgroup);
253  EC_KEY_free(eckey);
254 #endif
255  return ret;
256 }
257 
258 static int openssl_gen_certificate(EVP_PKEY *pkey, X509 **cert, char **fingerprint)
259 {
260  int ret = 0, expire_day;
261  uint64_t serial;
262  const char *aor = "lavf";
263  X509_NAME* subject = NULL;
264 
265  *cert= X509_new();
266  if (!*cert) {
267  goto enomem_end;
268  }
269 
270  // TODO: Support non-self-signed certificate, for example, load from a file.
271  subject = X509_NAME_new();
272  if (!subject) {
273  goto enomem_end;
274  }
275 
276  serial = av_get_random_seed();
277  if (ASN1_INTEGER_set_uint64(X509_get_serialNumber(*cert), serial) != 1) {
278  av_log(NULL, AV_LOG_ERROR, "TLS: Failed to set serial, %s\n", ERR_error_string(ERR_get_error(), NULL));
279  goto einval_end;
280  }
281 
282  if (X509_NAME_add_entry_by_txt(subject, "CN", MBSTRING_ASC, aor, strlen(aor), -1, 0) != 1) {
283  av_log(NULL, AV_LOG_ERROR, "TLS: Failed to set CN, %s\n", ERR_error_string(ERR_get_error(), NULL));
284  goto einval_end;
285  }
286 
287  if (X509_set_issuer_name(*cert, subject) != 1) {
288  av_log(NULL, AV_LOG_ERROR, "TLS: Failed to set issuer, %s\n", ERR_error_string(ERR_get_error(), NULL));
289  goto einval_end;
290  }
291  if (X509_set_subject_name(*cert, subject) != 1) {
292  av_log(NULL, AV_LOG_ERROR, "TLS: Failed to set subject name, %s\n", ERR_error_string(ERR_get_error(), NULL));
293  goto einval_end;
294  }
295 
296  expire_day = 365;
297  if (!X509_gmtime_adj(X509_get_notBefore(*cert), 0)) {
298  av_log(NULL, AV_LOG_ERROR, "TLS: Failed to set notBefore, %s\n", ERR_error_string(ERR_get_error(), NULL));
299  goto einval_end;
300  }
301  if (!X509_gmtime_adj(X509_get_notAfter(*cert), 60*60*24*expire_day)) {
302  av_log(NULL, AV_LOG_ERROR, "TLS: Failed to set notAfter, %s\n", ERR_error_string(ERR_get_error(), NULL));
303  goto einval_end;
304  }
305 
306  if (X509_set_version(*cert, 2) != 1) {
307  av_log(NULL, AV_LOG_ERROR, "TLS: Failed to set version, %s\n", ERR_error_string(ERR_get_error(), NULL));
308  goto einval_end;
309  }
310 
311  if (X509_set_pubkey(*cert, pkey) != 1) {
312  av_log(NULL, AV_LOG_ERROR, "TLS: Failed to set public key, %s\n", ERR_error_string(ERR_get_error(), NULL));
313  goto einval_end;
314  }
315 
316  if (!X509_sign(*cert, pkey, EVP_sha1())) {
317  av_log(NULL, AV_LOG_ERROR, "TLS: Failed to sign certificate, %s\n", ERR_error_string(ERR_get_error(), NULL));
318  goto einval_end;
319  }
320 
321  ret = x509_fingerprint(*cert, fingerprint);
322  if (ret < 0)
323  goto end;
324 
325  goto end;
326 enomem_end:
327  ret = AVERROR(ENOMEM);
328  goto end;
329 einval_end:
330  ret = AVERROR(EINVAL);
331 end:
332  if (ret) {
333  X509_free(*cert);
334  *cert = NULL;
335  }
336  X509_NAME_free(subject);
337  return ret;
338 }
339 
340 int ff_ssl_gen_key_cert(char *key_buf, size_t key_sz, char *cert_buf, size_t cert_sz, char **fingerprint)
341 {
342  int ret = 0;
343  EVP_PKEY *pkey = NULL;
344  X509 *cert = NULL;
345 
346  ret = openssl_gen_private_key(&pkey);
347  if (ret < 0) goto error;
348 
349  ret = openssl_gen_certificate(pkey, &cert, fingerprint);
350  if (ret < 0) goto error;
351 
352  pkey_to_pem_string(pkey, key_buf, key_sz);
353  cert_to_pem_string(cert, cert_buf, cert_sz);
354 
355 error:
356  X509_free(cert);
357  EVP_PKEY_free(pkey);
358  return ret;
359 }
360 
361 
362 /**
363  * Deserialize a PEM-encoded private or public key from a NUL-terminated C string.
364  *
365  * @param pem_str The PEM text, e.g.
366  * "-----BEGIN PRIVATE KEY-----\n…\n-----END PRIVATE KEY-----\n"
367  * @param is_priv If non-zero, parse as a PRIVATE key; otherwise, parse as a PUBLIC key.
368  * @return EVP_PKEY* on success (must EVP_PKEY_free()), or NULL on error.
369  */
370 static EVP_PKEY *pkey_from_pem_string(const char *pem_str, int is_priv)
371 {
372  BIO *mem = BIO_new_mem_buf(pem_str, -1);
373  if (!mem) {
374  av_log(NULL, AV_LOG_ERROR, "BIO_new_mem_buf failed\n");
375  return NULL;
376  }
377 
378  EVP_PKEY *pkey = NULL;
379  if (is_priv) {
380  pkey = PEM_read_bio_PrivateKey(mem, NULL, NULL, NULL);
381  } else {
382  pkey = PEM_read_bio_PUBKEY(mem, NULL, NULL, NULL);
383  }
384 
385  if (!pkey)
386  av_log(NULL, AV_LOG_ERROR, "Failed to parse %s key from string\n",
387  is_priv ? "private" : "public");
388 
389  BIO_free(mem);
390  return pkey;
391 }
392 
393 /**
394  * Deserialize a PEM-encoded certificate from a NUL-terminated C string.
395  *
396  * @param pem_str The PEM text, e.g.
397  * "-----BEGIN CERTIFICATE-----\n…\n-----END CERTIFICATE-----\n"
398  * @return X509* on success (must X509_free()), or NULL on error.
399  */
400 static X509 *cert_from_pem_string(const char *pem_str)
401 {
402  BIO *mem = BIO_new_mem_buf(pem_str, -1);
403  if (!mem) {
404  av_log(NULL, AV_LOG_ERROR, "BIO_new_mem_buf failed\n");
405  return NULL;
406  }
407 
408  X509 *cert = PEM_read_bio_X509(mem, NULL, NULL, NULL);
409  if (!cert) {
410  av_log(NULL, AV_LOG_ERROR, "Failed to parse certificate from string\n");
411  return NULL;
412  }
413 
414  BIO_free(mem);
415  return cert;
416 }
417 
418 
419 typedef struct TLSContext {
421  SSL_CTX *ctx;
422  SSL *ssl;
423  BIO_METHOD* url_bio_method;
424  int io_err;
425  char error_message[256];
427  socklen_t dest_addr_len;
428 } TLSContext;
429 
430 /**
431  * Retrieves the error message for the latest OpenSSL error.
432  *
433  * This function retrieves the error code from the thread's error queue, converts it
434  * to a human-readable string, and stores it in the TLSContext's error_message field.
435  * The error queue is then cleared using ERR_clear_error().
436  */
437 static const char* openssl_get_error(TLSContext *c)
438 {
439  int r2 = ERR_get_error();
440  if (r2) {
441  ERR_error_string_n(r2, c->error_message, sizeof(c->error_message));
442  } else
443  c->error_message[0] = '\0';
444 
445  ERR_clear_error();
446  return c->error_message;
447 }
448 
450 {
451  TLSContext *c = h->priv_data;
452  TLSShared *s = &c->tls_shared;
453 
454  if (s->is_dtls)
455  c->tls_shared.udp = sock;
456  else
457  c->tls_shared.tcp = sock;
458 
459  return 0;
460 }
461 
462 int ff_dtls_export_materials(URLContext *h, char *dtls_srtp_materials, size_t materials_sz)
463 {
464  int ret = 0;
465  const char* dst = "EXTRACTOR-dtls_srtp";
466  TLSContext *c = h->priv_data;
467 
468  ret = SSL_export_keying_material(c->ssl, dtls_srtp_materials, materials_sz,
469  dst, strlen(dst), NULL, 0, 0);
470  if (!ret) {
471  av_log(c, AV_LOG_ERROR, "Failed to export SRTP material, %s\n", openssl_get_error(c));
472  return -1;
473  }
474  return 0;
475 }
476 
477 static int print_ssl_error(URLContext *h, int ret)
478 {
479  TLSContext *c = h->priv_data;
480  int printed = 0, e, averr = AVERROR(EIO);
481  if (h->flags & AVIO_FLAG_NONBLOCK) {
482  int err = SSL_get_error(c->ssl, ret);
483  if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
484  return AVERROR(EAGAIN);
485  }
486  while ((e = ERR_get_error()) != 0) {
487  av_log(h, AV_LOG_ERROR, "%s\n", ERR_error_string(e, NULL));
488  printed = 1;
489  }
490  if (c->io_err) {
491  av_log(h, AV_LOG_ERROR, "IO error: %s\n", av_err2str(c->io_err));
492  printed = 1;
493  averr = c->io_err;
494  c->io_err = 0;
495  }
496  if (!printed)
497  av_log(h, AV_LOG_ERROR, "Unknown error\n");
498  return averr;
499 }
500 
501 static int tls_close(URLContext *h)
502 {
503  TLSContext *c = h->priv_data;
504  if (c->ssl) {
505  SSL_shutdown(c->ssl);
506  SSL_free(c->ssl);
507  }
508  if (c->ctx)
509  SSL_CTX_free(c->ctx);
510  if (!c->tls_shared.external_sock)
511  ffurl_closep(c->tls_shared.is_dtls ? &c->tls_shared.udp : &c->tls_shared.tcp);
512  if (c->url_bio_method)
513  BIO_meth_free(c->url_bio_method);
514  return 0;
515 }
516 
517 static int url_bio_create(BIO *b)
518 {
519  BIO_set_init(b, 1);
520  BIO_set_data(b, NULL);
521  BIO_set_flags(b, 0);
522  return 1;
523 }
524 
525 static int url_bio_destroy(BIO *b)
526 {
527  return 1;
528 }
529 
530 static int url_bio_bread(BIO *b, char *buf, int len)
531 {
532  TLSContext *c = BIO_get_data(b);
533  TLSShared *s = &c->tls_shared;
534  int ret = ffurl_read(c->tls_shared.is_dtls ? c->tls_shared.udp : c->tls_shared.tcp, buf, len);
535  if (ret >= 0) {
536  if (s->is_dtls && s->listen && !c->dest_addr_len) {
537  int err_ret;
538 
539  ff_udp_get_last_recv_addr(s->udp, &c->dest_addr, &c->dest_addr_len);
540  err_ret = ff_udp_set_remote_addr(s->udp, (struct sockaddr *)&c->dest_addr, c->dest_addr_len, 1);
541  if (err_ret < 0) {
542  av_log(c, AV_LOG_ERROR, "Failed connecting udp context\n");
543  return err_ret;
544  }
545  av_log(c, AV_LOG_TRACE, "Set UDP remote addr on UDP socket, now 'connected'\n");
546  }
547 
548  return ret;
549  }
550  BIO_clear_retry_flags(b);
551  if (ret == AVERROR_EXIT)
552  return 0;
553  if (ret == AVERROR(EAGAIN))
554  BIO_set_retry_read(b);
555  else
556  c->io_err = ret;
557  return -1;
558 }
559 
560 static int url_bio_bwrite(BIO *b, const char *buf, int len)
561 {
562  TLSContext *c = BIO_get_data(b);
563  int ret = ffurl_write(c->tls_shared.is_dtls ? c->tls_shared.udp : c->tls_shared.tcp, buf, len);
564  if (ret >= 0)
565  return ret;
566  BIO_clear_retry_flags(b);
567  if (ret == AVERROR_EXIT)
568  return 0;
569  if (ret == AVERROR(EAGAIN))
570  BIO_set_retry_write(b);
571  else
572  c->io_err = ret;
573  return -1;
574 }
575 
576 static long url_bio_ctrl(BIO *b, int cmd, long num, void *ptr)
577 {
578  if (cmd == BIO_CTRL_FLUSH) {
579  BIO_clear_retry_flags(b);
580  return 1;
581  }
582  return 0;
583 }
584 
585 static int url_bio_bputs(BIO *b, const char *str)
586 {
587  return url_bio_bwrite(b, str, strlen(str));
588 }
589 
591 {
592  TLSContext *c = h->priv_data;
593  BIO *bio;
594  c->url_bio_method = BIO_meth_new(BIO_TYPE_SOURCE_SINK, "urlprotocol bio");
595  BIO_meth_set_write(c->url_bio_method, url_bio_bwrite);
596  BIO_meth_set_read(c->url_bio_method, url_bio_bread);
597  BIO_meth_set_puts(c->url_bio_method, url_bio_bputs);
598  BIO_meth_set_ctrl(c->url_bio_method, url_bio_ctrl);
599  BIO_meth_set_create(c->url_bio_method, url_bio_create);
600  BIO_meth_set_destroy(c->url_bio_method, url_bio_destroy);
601  bio = BIO_new(c->url_bio_method);
602  BIO_set_data(bio, c);
603 
604  SSL_set_bio(c->ssl, bio, bio);
605 }
606 
607 static void openssl_info_callback(const SSL *ssl, int where, int ret) {
608  const char *method = "undefined";
609  TLSContext *c = (TLSContext*)SSL_get_ex_data(ssl, 0);
610 
611  if (where & SSL_ST_CONNECT) {
612  method = "SSL_connect";
613  } else if (where & SSL_ST_ACCEPT)
614  method = "SSL_accept";
615 
616  if (where & SSL_CB_LOOP) {
617  av_log(c, AV_LOG_DEBUG, "Info method=%s state=%s(%s), where=%d, ret=%d\n",
618  method, SSL_state_string(ssl), SSL_state_string_long(ssl), where, ret);
619  } else if (where & SSL_CB_ALERT) {
620  method = (where & SSL_CB_READ) ? "read":"write";
621  av_log(c, AV_LOG_DEBUG, "Alert method=%s state=%s(%s), where=%d, ret=%d\n",
622  method, SSL_state_string(ssl), SSL_state_string_long(ssl), where, ret);
623  }
624 }
625 
627 {
628  int ret = 1, r0, r1;
629  TLSContext *c = h->priv_data;
630 
631  c->tls_shared.udp->flags &= ~AVIO_FLAG_NONBLOCK;
632 
633  r0 = SSL_do_handshake(c->ssl);
634  if (r0 <= 0) {
635  r1 = SSL_get_error(c->ssl, r0);
636 
637  if (r1 != SSL_ERROR_WANT_READ && r1 != SSL_ERROR_WANT_WRITE && r1 != SSL_ERROR_ZERO_RETURN) {
638  av_log(c, AV_LOG_ERROR, "Handshake failed, r0=%d, r1=%d\n", r0, r1);
639  ret = print_ssl_error(h, r0);
640  goto end;
641  }
642  } else {
643  av_log(c, AV_LOG_TRACE, "Handshake success, r0=%d\n", r0);
644  }
645 
646  /* Check whether the handshake is completed. */
647  if (SSL_is_init_finished(c->ssl) != TLS_ST_OK)
648  goto end;
649 
650  ret = 0;
651 end:
652  return ret;
653 }
654 
656 {
657  int ret;
658  TLSContext *c = h->priv_data;
659  TLSShared *s = &c->tls_shared;
660  EVP_PKEY *pkey = NULL;
661  X509 *cert = NULL;
662  /* setup ca, private key, certificate */
663  if (s->ca_file) {
664  if (!SSL_CTX_load_verify_locations(c->ctx, s->ca_file, NULL))
665  av_log(h, AV_LOG_ERROR, "SSL_CTX_load_verify_locations %s\n", openssl_get_error(c));
666  } else {
667  if (!SSL_CTX_set_default_verify_paths(c->ctx)) {
668  // Only log the failure but do not error out, as this is not fatal
669  av_log(h, AV_LOG_WARNING, "Failure setting default verify locations: %s\n",
671  }
672  }
673 
674  if (s->cert_file) {
675  ret = SSL_CTX_use_certificate_chain_file(c->ctx, s->cert_file);
676  if (ret <= 0) {
677  av_log(h, AV_LOG_ERROR, "Unable to load cert file %s: %s\n",
678  s->cert_file, openssl_get_error(c));
679  ret = AVERROR(EIO);
680  goto fail;
681  }
682  } else if (s->cert_buf) {
683  cert = cert_from_pem_string(s->cert_buf);
684  if (SSL_CTX_use_certificate(c->ctx, cert) != 1) {
685  av_log(c, AV_LOG_ERROR, "SSL: Init SSL_CTX_use_certificate failed, %s\n", openssl_get_error(c));
686  ret = AVERROR(EINVAL);
687  goto fail;
688  }
689  }
690 
691  if (s->key_file) {
692  ret = SSL_CTX_use_PrivateKey_file(c->ctx, s->key_file, SSL_FILETYPE_PEM);
693  if (ret <= 0) {
694  av_log(h, AV_LOG_ERROR, "Unable to load key file %s: %s\n",
695  s->key_file, openssl_get_error(c));
696  ret = AVERROR(EIO);
697  goto fail;
698  }
699  } else if (s->key_buf) {
700  pkey = pkey_from_pem_string(s->key_buf, 1);
701  if (SSL_CTX_use_PrivateKey(c->ctx, pkey) != 1) {
702  av_log(c, AV_LOG_ERROR, "Init SSL_CTX_use_PrivateKey failed, %s\n", openssl_get_error(c));
703  ret = AVERROR(EINVAL);
704  goto fail;
705  }
706  }
707 
708  if (s->listen && !s->cert_file && !s->cert_buf && !s->key_file && !s->key_buf) {
709  av_log(h, AV_LOG_VERBOSE, "No server certificate provided, using self-signed\n");
710 
711  ret = openssl_gen_private_key(&pkey);
712  if (ret < 0)
713  goto fail;
714 
715  ret = openssl_gen_certificate(pkey, &cert, NULL);
716  if (ret < 0)
717  goto fail;
718 
719  if (SSL_CTX_use_certificate(c->ctx, cert) != 1) {
720  av_log(c, AV_LOG_ERROR, "SSL_CTX_use_certificate failed for self-signed cert, %s\n", openssl_get_error(c));
721  ret = AVERROR(EINVAL);
722  goto fail;
723  }
724 
725  if (SSL_CTX_use_PrivateKey(c->ctx, pkey) != 1) {
726  av_log(c, AV_LOG_ERROR, "SSL_CTX_use_PrivateKey failed for self-signed cert, %s\n", openssl_get_error(c));
727  ret = AVERROR(EINVAL);
728  goto fail;
729  }
730  }
731 
732  ret = 0;
733 fail:
734  X509_free(cert);
735  EVP_PKEY_free(pkey);
736  return ret;
737 }
738 
739 /**
740  * Once the DTLS role has been negotiated - active for the DTLS client or passive for the
741  * DTLS server - we proceed to set up the DTLS state and initiate the handshake.
742  */
743 static int dtls_start(URLContext *h, const char *url, int flags, AVDictionary **options)
744 {
745  TLSContext *c = h->priv_data;
746  TLSShared *s = &c->tls_shared;
747  int ret = 0;
748  s->is_dtls = 1;
749 
750  if (!c->tls_shared.external_sock) {
751  if ((ret = ff_tls_open_underlying(&c->tls_shared, h, url, options)) < 0) {
752  av_log(c, AV_LOG_ERROR, "Failed to connect %s\n", url);
753  return ret;
754  }
755  }
756 
757  c->ctx = SSL_CTX_new(s->listen ? DTLS_server_method() : DTLS_client_method());
758  if (!c->ctx) {
759  ret = AVERROR(ENOMEM);
760  goto fail;
761  }
762 
764  if (ret < 0) goto fail;
765 
766  /* Note, this doesn't check that the peer certificate actually matches the requested hostname. */
767  if (s->verify)
768  SSL_CTX_set_verify(c->ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
769 
770  if (s->use_srtp) {
771  /**
772  * The profile for OpenSSL's SRTP is SRTP_AES128_CM_SHA1_80, see ssl/d1_srtp.c.
773  * The profile for FFmpeg's SRTP is SRTP_AES128_CM_HMAC_SHA1_80, see libavformat/srtp.c.
774  */
775  const char* profiles = "SRTP_AES128_CM_SHA1_80";
776  if (SSL_CTX_set_tlsext_use_srtp(c->ctx, profiles)) {
777  av_log(c, AV_LOG_ERROR, "Init SSL_CTX_set_tlsext_use_srtp failed, profiles=%s, %s\n",
779  ret = AVERROR(EINVAL);
780  goto fail;
781  }
782  }
783 
784  /* The ssl should not be created unless the ctx has been initialized. */
785  c->ssl = SSL_new(c->ctx);
786  if (!c->ssl) {
787  ret = AVERROR(ENOMEM);
788  goto fail;
789  }
790 
791  if (!s->listen && !s->numerichost)
792  SSL_set_tlsext_host_name(c->ssl, s->host);
793 
794  /* Setup the callback for logging. */
795  SSL_set_ex_data(c->ssl, 0, c);
796  SSL_CTX_set_info_callback(c->ctx, openssl_info_callback);
797 
798  /**
799  * We have set the MTU to fragment the DTLS packet. It is important to note that the
800  * packet is split to ensure that each handshake packet is smaller than the MTU.
801  */
802  if (s->mtu <= 0)
803  s->mtu = 1096;
804  SSL_set_options(c->ssl, SSL_OP_NO_QUERY_MTU);
805  SSL_set_mtu(c->ssl, s->mtu);
806  DTLS_set_link_mtu(c->ssl, s->mtu);
808 
809  /* This seems to be necessary despite explicitly setting client/server method above. */
810  if (s->listen)
811  SSL_set_accept_state(c->ssl);
812  else
813  SSL_set_connect_state(c->ssl);
814 
815  /**
816  * During initialization, we only need to call SSL_do_handshake once because SSL_read consumes
817  * the handshake message if the handshake is incomplete.
818  * To simplify maintenance, we initiate the handshake for both the DTLS server and client after
819  * sending out the ICE response in the start_active_handshake function. It's worth noting that
820  * although the DTLS server may receive the ClientHello immediately after sending out the ICE
821  * response, this shouldn't be an issue as the handshake function is called before any DTLS
822  * packets are received.
823  *
824  * The SSL_do_handshake can't be called if DTLS hasn't prepare for udp.
825  */
826  if (!c->tls_shared.external_sock) {
827  ret = dtls_handshake(h);
828  // Fatal SSL error, for example, no available suite when peer is DTLS 1.0 while we are DTLS 1.2.
829  if (ret < 0) {
830  av_log(c, AV_LOG_ERROR, "Failed to drive SSL context, ret=%d\n", ret);
831  return AVERROR(EIO);
832  }
833  }
834 
835  av_log(c, AV_LOG_VERBOSE, "Setup ok, MTU=%d\n", c->tls_shared.mtu);
836 
837  return 0;
838 fail:
839  tls_close(h);
840  return ret;
841 }
842 
843 static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
844 {
845  TLSContext *c = h->priv_data;
846  TLSShared *s = &c->tls_shared;
847  int ret;
848 
849  if ((ret = ff_tls_open_underlying(s, h, uri, options)) < 0)
850  goto fail;
851 
852  // We want to support all versions of TLS >= 1.0, but not the deprecated
853  // and insecure SSLv2 and SSLv3. Despite the name, TLS_*_method()
854  // enables support for all versions of SSL and TLS, and we then disable
855  // support for the old protocols immediately after creating the context.
856  c->ctx = SSL_CTX_new(s->listen ? TLS_server_method() : TLS_client_method());
857  if (!c->ctx) {
859  ret = AVERROR(EIO);
860  goto fail;
861  }
862  if (!SSL_CTX_set_min_proto_version(c->ctx, TLS1_VERSION)) {
863  av_log(h, AV_LOG_ERROR, "Failed to set minimum TLS version to TLSv1\n");
865  goto fail;
866  }
868  if (ret < 0) goto fail;
869 
870  if (s->verify)
871  SSL_CTX_set_verify(c->ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
872  c->ssl = SSL_new(c->ctx);
873  if (!c->ssl) {
875  ret = AVERROR(EIO);
876  goto fail;
877  }
878  SSL_set_ex_data(c->ssl, 0, c);
879  SSL_CTX_set_info_callback(c->ctx, openssl_info_callback);
881  if (!s->listen && !s->numerichost) {
882  // By default OpenSSL does too lax wildcard matching
883  SSL_set_hostflags(c->ssl, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
884  if (!SSL_set1_host(c->ssl, s->host)) {
885  av_log(h, AV_LOG_ERROR, "Failed to set hostname for TLS/SSL verification: %s\n",
888  goto fail;
889  }
890  if (!SSL_set_tlsext_host_name(c->ssl, s->host)) {
891  av_log(h, AV_LOG_ERROR, "Failed to set hostname for SNI: %s\n", openssl_get_error(c));
893  goto fail;
894  }
895  }
896  ret = s->listen ? SSL_accept(c->ssl) : SSL_connect(c->ssl);
897  if (ret == 0) {
898  av_log(h, AV_LOG_ERROR, "Unable to negotiate TLS/SSL session\n");
899  ret = AVERROR(EIO);
900  goto fail;
901  } else if (ret < 0) {
902  ret = print_ssl_error(h, ret);
903  goto fail;
904  }
905 
906  return 0;
907 fail:
908  tls_close(h);
909  return ret;
910 }
911 
912 static int tls_read(URLContext *h, uint8_t *buf, int size)
913 {
914  TLSContext *c = h->priv_data;
915  TLSShared *s = &c->tls_shared;
916  URLContext *uc = s->is_dtls ? s->udp : s->tcp;
917  int ret;
918  // Set or clear the AVIO_FLAG_NONBLOCK on the underlying socket
919  uc->flags &= ~AVIO_FLAG_NONBLOCK;
920  uc->flags |= h->flags & AVIO_FLAG_NONBLOCK;
921  ret = SSL_read(c->ssl, buf, size);
922  if (ret > 0)
923  return ret;
924  if (ret == 0)
925  return AVERROR_EOF;
926  return print_ssl_error(h, ret);
927 }
928 
929 static int tls_write(URLContext *h, const uint8_t *buf, int size)
930 {
931  TLSContext *c = h->priv_data;
932  TLSShared *s = &c->tls_shared;
933  URLContext *uc = s->is_dtls ? s->udp : s->tcp;
934  int ret;
935 
936  // Set or clear the AVIO_FLAG_NONBLOCK on c->tls_shared.tcp
937  uc->flags &= ~AVIO_FLAG_NONBLOCK;
938  uc->flags |= h->flags & AVIO_FLAG_NONBLOCK;
939 
940  if (s->is_dtls) {
941  const size_t mtu_size = DTLS_get_data_mtu(c->ssl);
942  size = FFMIN(size, mtu_size);
943  }
944 
945  ret = SSL_write(c->ssl, buf, size);
946  if (ret > 0)
947  return ret;
948  if (ret == 0)
949  return AVERROR_EOF;
950  return print_ssl_error(h, ret);
951 }
952 
954 {
955  TLSContext *c = h->priv_data;
956  TLSShared *s = &c->tls_shared;
957  return ffurl_get_file_handle(s->is_dtls ? s->udp : s->tcp);
958 }
959 
961 {
962  TLSContext *c = h->priv_data;
963  TLSShared *s = &c->tls_shared;
964  return ffurl_get_short_seek(s->is_dtls ? s->udp : s->tcp);
965 }
966 
967 static const AVOption options[] = {
968  TLS_COMMON_OPTIONS(TLSContext, tls_shared),
969  { NULL }
970 };
971 
972 static const AVClass tls_class = {
973  .class_name = "tls",
974  .item_name = av_default_item_name,
975  .option = options,
976  .version = LIBAVUTIL_VERSION_INT,
977 };
978 
980  .name = "tls",
981  .url_open2 = tls_open,
982  .url_read = tls_read,
983  .url_write = tls_write,
984  .url_close = tls_close,
985  .url_get_file_handle = tls_get_file_handle,
986  .url_get_short_seek = tls_get_short_seek,
987  .priv_data_size = sizeof(TLSContext),
989  .priv_data_class = &tls_class,
990 };
991 
992 static const AVClass dtls_class = {
993  .class_name = "dtls",
994  .item_name = av_default_item_name,
995  .option = options,
996  .version = LIBAVUTIL_VERSION_INT,
997 };
998 
1000  .name = "dtls",
1001  .url_open2 = dtls_start,
1002  .url_handshake = dtls_handshake,
1003  .url_close = tls_close,
1004  .url_read = tls_read,
1005  .url_write = tls_write,
1006  .url_get_file_handle = tls_get_file_handle,
1007  .url_get_short_seek = tls_get_short_seek,
1008  .priv_data_size = sizeof(TLSContext),
1010  .priv_data_class = &dtls_class,
1011 };
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:400
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:216
TLSContext
Definition: tls_gnutls.c:45
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
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
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
openssl_get_error
static const char * openssl_get_error(TLSContext *c)
Retrieves the error message for the latest OpenSSL error.
Definition: tls_openssl.c:437
read_bytes
static void read_bytes(const uint8_t *src, float *dst, int src_stride, int dst_stride, int width, int height, float scale)
Definition: vf_nnedi.c:442
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
URLProtocol
Definition: url.h:51
os_support.h
sockaddr_storage
Definition: network.h:111
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
x509_fingerprint
static int x509_fingerprint(X509 *cert, char **fingerprint)
Generate a SHA-256 fingerprint of an X.509 certificate.
Definition: tls_openssl.c:94
ff_dtls_export_materials
int ff_dtls_export_materials(URLContext *h, char *dtls_srtp_materials, size_t materials_sz)
Definition: tls_openssl.c:462
TLS_COMMON_OPTIONS
#define TLS_COMMON_OPTIONS(pstruct, options_field)
Definition: tls.h:88
tls_class
static const AVClass tls_class
Definition: tls_openssl.c:972
fail
#define fail()
Definition: checkasm.h:206
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:517
openssl_gen_private_key
static int openssl_gen_private_key(EVP_PKEY **pkey)
Definition: tls_openssl.c:184
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:115
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:106
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:929
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:231
ff_tls_protocol
const URLProtocol ff_tls_protocol
Definition: tls_openssl.c:979
ff_udp_set_remote_addr
int ff_udp_set_remote_addr(URLContext *h, const struct sockaddr *dest_addr, socklen_t dest_addr_len, int do_connect)
This function is identical to ff_udp_set_remote_url, except that it takes a sockaddr directly.
Definition: udp.c:472
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
dtls_handshake
static int dtls_handshake(URLContext *h)
Definition: tls_openssl.c:626
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:76
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:241
ff_udp_get_last_recv_addr
void ff_udp_get_last_recv_addr(URLContext *h, struct sockaddr_storage *addr, socklen_t *addr_len)
Definition: udp.c:510
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:340
url_bio_ctrl
static long url_bio_ctrl(BIO *b, int cmd, long num, void *ptr)
Definition: tls_openssl.c:576
url_bio_destroy
static int url_bio_destroy(BIO *b)
Definition: tls_openssl.c:525
ff_tls_set_external_socket
int ff_tls_set_external_socket(URLContext *h, URLContext *sock)
Definition: tls_openssl.c:449
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:560
tls_open
static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
Definition: tls_openssl.c:843
TLSContext::error_message
char error_message[256]
Definition: tls_openssl.c:425
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:116
av_bprint_finalize
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition: bprint.c:235
cert_to_pem_string
static int cert_to_pem_string(X509 *cert, char *out, size_t out_sz)
Convert an X509 certificate to a PEM string.
Definition: tls_openssl.c:66
url_bio_bread
static int url_bio_bread(BIO *b, char *buf, int len)
Definition: tls_openssl.c:530
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:421
pkey_to_pem_string
static int pkey_to_pem_string(EVP_PKEY *pkey, char *out, size_t out_sz)
Convert an EVP_PKEY to a PEM string.
Definition: tls_openssl.c: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:967
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:607
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:953
init_bio_method
static av_cold void init_bio_method(URLContext *h)
Definition: tls_openssl.c:590
TLSContext::ssl
SSL * ssl
Definition: tls_openssl.c:422
TLSContext::dest_addr
struct sockaddr_storage dest_addr
Definition: tls_openssl.c:426
URLContext
Definition: url.h:35
print_ssl_error
static int print_ssl_error(URLContext *h, int ret)
Definition: tls_openssl.c:477
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
TLSContext::dest_addr_len
socklen_t dest_addr_len
Definition: tls_openssl.c:427
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
url.h
len
int len
Definition: vorbis_enc_data.h:426
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:34
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:122
network.h
tls.h
random_seed.h
tls_get_short_seek
static int tls_get_short_seek(URLContext *h)
Definition: tls_openssl.c:960
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:912
mem.h
MAX_CERTIFICATE_SIZE
#define MAX_CERTIFICATE_SIZE
Maximum size limit of a certificate and private key size.
Definition: tls.h:35
TLSShared
Definition: tls.h:37
openssl_init_ca_key_cert
static av_cold int openssl_init_ca_key_cert(URLContext *h)
Definition: tls_openssl.c:655
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:743
AVIO_FLAG_NONBLOCK
#define AVIO_FLAG_NONBLOCK
Use non-blocking mode.
Definition: avio.h:636
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:370
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:992
tls_close
static int tls_close(URLContext *h)
Definition: tls_openssl.c:501
ff_dtls_protocol
const URLProtocol ff_dtls_protocol
Definition: tls_openssl.c:999
openssl_gen_certificate
static int openssl_gen_certificate(EVP_PKEY *pkey, X509 **cert, char **fingerprint)
Definition: tls_openssl.c:258
TLSContext::url_bio_method
BIO_METHOD * url_bio_method
Definition: tls_openssl.c:423
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:585
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