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