FFmpeg
tls_schannel.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Hendrik Leppkes
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 /** Based on the CURL SChannel module */
22 
23 #include "config.h"
24 #include "config_components.h"
25 
26 #include "libavutil/mem.h"
27 #include "avformat.h"
28 #include "internal.h"
29 #include "network.h"
30 #include "os_support.h"
31 #include "url.h"
32 #include "tls.h"
33 
34 #define SECURITY_WIN32
35 #include <windows.h>
36 #include <security.h>
37 #include <schnlsp.h>
38 #include <sddl.h>
39 
40 #define SCHANNEL_INITIAL_BUFFER_SIZE 4096
41 #define SCHANNEL_FREE_BUFFER_SIZE 1024
42 
43 /* mingw does not define this symbol */
44 #ifndef SECBUFFER_ALERT
45 #define SECBUFFER_ALERT 17
46 #endif
47 
48 /* This is the name used for the private key in the MS Keystore.
49  * There is as of time of writing no way to use schannel without
50  * persisting the private key. Which usually means the default MS
51  * keystore will write it to disk unencrypted, user-read/writable.
52  * To combat this as much as possible, the code makes sure to
53  * delete the private key ASAP once SChannel has gotten ahold of
54  * it.
55  * Apparently this is because SChannel neglects marshaling the
56  * private key alongside the certificate for the out-of-process
57  * tls handler.
58  * See this GitHub issue for the most detailed explanation out there:
59  * https://github.com/dotnet/runtime/issues/23749#issuecomment-485947319
60  */
61 #define FF_NCRYPT_TEMP_KEY_NAME L"FFMPEG_TEMP_TLS_KEY"
62 
63 static int der_to_pem(const char *data, size_t len, const char *header, char *buf, size_t bufsize)
64 {
65  const int line_length = 64;
66  AVBPrint pem;
67  DWORD base64len = 0;
68  char *base64 = NULL;
69  int ret = 0;
70 
71  if (!CryptBinaryToStringA(data, len, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, NULL, &base64len)) {
72  av_log(NULL, AV_LOG_ERROR, "CryptBinaryToString failed\n");
74  goto end;
75  }
76 
77  base64 = av_malloc(base64len);
78 
79  if (!CryptBinaryToStringA(data, len, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, base64, &base64len)) {
80  av_log(NULL, AV_LOG_ERROR, "CryptBinaryToString failed\n");
82  goto end;
83  }
84 
85  av_bprint_init_for_buffer(&pem, buf, bufsize);
86  av_bprintf(&pem, "-----BEGIN %s-----\n", header);
87 
88  for (DWORD i = 0; i < base64len; i += line_length) {
89  av_bprintf(&pem, "%.*s\n", line_length, base64 + i);
90  }
91 
92  av_bprintf(&pem, "-----END %s-----\n", header);
93 
94  if (!av_bprint_is_complete(&pem)) {
95  ret = AVERROR(ENOSPC);
96  goto end;
97  }
98 
99 end:
100  av_free(base64);
101  return ret;
102 }
103 
104 static int pem_to_der(const char *pem, char **buf, int *out_len)
105 {
106  DWORD derlen = 0;
107 
108  if (!CryptStringToBinaryA(pem, 0, CRYPT_STRING_BASE64HEADER, NULL, &derlen, NULL, NULL)) {
109  av_log(NULL, AV_LOG_ERROR, "CryptStringToBinaryA failed\n");
110  return AVERROR(EINVAL);
111  }
112 
113  *buf = av_malloc(derlen);
114  if (!*buf)
115  return AVERROR(ENOMEM);
116 
117  if (!CryptStringToBinaryA(pem, 0, CRYPT_STRING_BASE64HEADER, *buf, &derlen, NULL, NULL)) {
118  av_log(NULL, AV_LOG_ERROR, "CryptStringToBinaryA failed\n");
119  return AVERROR(EINVAL);
120  }
121 
122  *out_len = derlen;
123 
124  return 0;
125 }
126 
127 static int der_to_fingerprint(const char *data, size_t len, char **fingerprint)
128 {
129  AVBPrint buf;
130  unsigned char hash[32];
131  DWORD hashsize = sizeof(hash);
132 
133  if (!CryptHashCertificate2(BCRYPT_SHA256_ALGORITHM, 0, NULL, data, len, hash, &hashsize))
134  {
135  av_log(NULL, AV_LOG_ERROR, "CryptHashCertificate2 failed\n");
136  return AVERROR_EXTERNAL;
137  }
138 
139  av_bprint_init(&buf, hashsize*3, hashsize*3);
140 
141  for (int i = 0; i < hashsize - 1; i++)
142  av_bprintf(&buf, "%02X:", hash[i]);
143  av_bprintf(&buf, "%02X", hash[hashsize - 1]);
144 
145  return av_bprint_finalize(&buf, fingerprint);
146 }
147 
148 static int tls_gen_self_signed(NCRYPT_KEY_HANDLE *key, PCCERT_CONTEXT *crtctx)
149 {
150  NCRYPT_PROV_HANDLE provider = 0;
151  CERT_NAME_BLOB subject = { 0 };
152 
153  DWORD export_props = NCRYPT_ALLOW_EXPORT_FLAG | NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG;
154  DWORD usage_props = NCRYPT_ALLOW_ALL_USAGES;
155  LPCSTR ext_usages[] = { szOID_PKIX_KP_SERVER_AUTH };
156  BYTE key_usage = CERT_KEY_ENCIPHERMENT_KEY_USAGE | CERT_DIGITAL_SIGNATURE_KEY_USAGE;
157  CRYPT_BIT_BLOB key_usage_blob = { 0 };
158  CERT_ENHKEY_USAGE eku = { 0 };
159  CERT_BASIC_CONSTRAINTS2_INFO basic_constraints = { 0 };
160  CERT_ALT_NAME_ENTRY san_entry = { 0 };
161  CERT_ALT_NAME_INFO san_info = { 0 };
162  CERT_EXTENSION ext[4] = { 0 };
163  CERT_EXTENSIONS exts = { 0 };
164  CRYPT_ALGORITHM_IDENTIFIER sig_alg = { (LPSTR)szOID_ECDSA_SHA256 };
165  CRYPT_KEY_PROV_INFO prov_info = { 0 };
166  const char *subj_str = "CN=lavf";
167 
168  SECURITY_STATUS sspi_ret;
169  int ret = 0;
170 
171  *crtctx = NULL;
172 
173  sspi_ret = NCryptOpenStorageProvider(&provider, MS_KEY_STORAGE_PROVIDER, 0);
174  if (sspi_ret != ERROR_SUCCESS) {
175  av_log(NULL, AV_LOG_ERROR, "NCryptOpenStorageProvider failed(0x%lx)\n", sspi_ret);
177  goto fail;
178  }
179 
180  sspi_ret = NCryptCreatePersistedKey(provider, key, BCRYPT_ECDSA_P256_ALGORITHM, FF_NCRYPT_TEMP_KEY_NAME, 0, NCRYPT_OVERWRITE_KEY_FLAG);
181  if (sspi_ret != ERROR_SUCCESS) {
182  av_log(NULL, AV_LOG_ERROR, "NCryptCreatePersistedKey failed(0x%lx)\n", sspi_ret);
184  goto fail;
185  }
186 
187  sspi_ret = NCryptSetProperty(*key, NCRYPT_EXPORT_POLICY_PROPERTY, (PBYTE)&export_props, sizeof(export_props), 0);
188  if (sspi_ret != ERROR_SUCCESS) {
189  av_log(NULL, AV_LOG_ERROR, "NCryptSetProperty(NCRYPT_EXPORT_POLICY_PROPERTY) failed(0x%lx)\n", sspi_ret);
191  goto fail;
192  }
193 
194  sspi_ret = NCryptSetProperty(*key, NCRYPT_KEY_USAGE_PROPERTY, (PBYTE)&usage_props, sizeof(usage_props), 0);
195  if (sspi_ret != ERROR_SUCCESS) {
196  av_log(NULL, AV_LOG_ERROR, "NCryptSetProperty(NCRYPT_KEY_USAGE_PROPERTY) failed(0x%lx)\n", sspi_ret);
198  goto fail;
199  }
200 
201  sspi_ret = NCryptFinalizeKey(*key, 0);
202  if (sspi_ret != ERROR_SUCCESS) {
203  av_log(NULL, AV_LOG_ERROR, "NCryptFinalizeKey failed(0x%lx)\n", sspi_ret);
205  goto fail;
206  }
207 
208  if (!CertStrToNameA(X509_ASN_ENCODING, subj_str, 0, NULL, NULL, &subject.cbData, NULL))
209  {
210  av_log(NULL, AV_LOG_ERROR, "Initial subj init failed\n");
212  goto fail;
213  }
214 
215  subject.pbData = av_malloc(subject.cbData);
216  if (!subject.pbData) {
217  ret = AVERROR(ENOMEM);
218  goto fail;
219  }
220 
221  if (!CertStrToNameA(X509_ASN_ENCODING, subj_str, 0, NULL, subject.pbData, &subject.cbData, NULL))
222  {
223  av_log(NULL, AV_LOG_ERROR, "Subj init failed\n");
225  goto fail;
226  }
227 
228  // Extended Key Usage extension
229  eku.cUsageIdentifier = 1;
230  eku.rgpszUsageIdentifier = (LPSTR*)ext_usages;
231 
232  if (!CryptEncodeObjectEx(X509_ASN_ENCODING, X509_ENHANCED_KEY_USAGE, &eku,
233  CRYPT_ENCODE_ALLOC_FLAG, NULL, &ext[0].Value.pbData, &ext[0].Value.cbData)) {
234  av_log(NULL, AV_LOG_ERROR, "CryptEncodeObjectEx for EKU failed\n");
236  goto fail;
237  }
238 
239  ext[0].pszObjId = (LPSTR)szOID_ENHANCED_KEY_USAGE;
240  ext[0].fCritical = TRUE;
241 
242  // Key usage extension
243  key_usage_blob.cbData = sizeof(key_usage);
244  key_usage_blob.pbData = &key_usage;
245 
246  if (!CryptEncodeObjectEx(X509_ASN_ENCODING, X509_BITS, &key_usage_blob,
247  CRYPT_ENCODE_ALLOC_FLAG, NULL, &ext[1].Value.pbData, &ext[1].Value.cbData)) {
248  av_log(NULL, AV_LOG_ERROR, "CryptEncodeObjectEx for KU failed\n");
250  goto fail;
251  }
252 
253  ext[1].pszObjId = (LPSTR)szOID_KEY_USAGE;
254  ext[1].fCritical = TRUE;
255 
256  // Cert Basic Constraints
257  basic_constraints.fCA = FALSE;
258 
259  if (!CryptEncodeObjectEx(X509_ASN_ENCODING, X509_BASIC_CONSTRAINTS2, &basic_constraints,
260  CRYPT_ENCODE_ALLOC_FLAG, NULL, &ext[2].Value.pbData, &ext[2].Value.cbData)) {
261  av_log(NULL, AV_LOG_ERROR, "CryptEncodeObjectEx for KU failed\n");
263  goto fail;
264  }
265 
266  ext[2].pszObjId = (LPSTR)szOID_BASIC_CONSTRAINTS2;
267  ext[2].fCritical = TRUE;
268 
269  // Subject Alt Names
270  san_entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
271  san_entry.pwszDNSName = (LPWSTR)L"localhost";
272 
273  san_info.cAltEntry = 1;
274  san_info.rgAltEntry = &san_entry;
275 
276  if (!CryptEncodeObjectEx(X509_ASN_ENCODING, X509_ALTERNATE_NAME, &san_info,
277  CRYPT_ENCODE_ALLOC_FLAG, NULL, &ext[3].Value.pbData, &ext[3].Value.cbData)) {
278  av_log(NULL, AV_LOG_ERROR, "CryptEncodeObjectEx for KU failed\n");
280  goto fail;
281  }
282 
283  ext[3].pszObjId = (LPSTR)szOID_SUBJECT_ALT_NAME2;
284  ext[3].fCritical = TRUE;
285 
286  exts.cExtension = 4;
287  exts.rgExtension = ext;
288 
289  prov_info.pwszProvName = (LPWSTR)MS_KEY_STORAGE_PROVIDER;
290  prov_info.pwszContainerName = (LPWSTR)FF_NCRYPT_TEMP_KEY_NAME;
291  prov_info.dwFlags = CERT_SET_KEY_CONTEXT_PROP_ID;
292 
293  *crtctx = CertCreateSelfSignCertificate(*key, &subject, 0, &prov_info, &sig_alg, NULL, NULL, &exts);
294  if (!*crtctx) {
295  av_log(NULL, AV_LOG_ERROR, "CertCreateSelfSignCertificate failed: %lu\n", GetLastError());
297  goto fail;
298  }
299 
300  NCryptFreeObject(provider);
301  av_free(subject.pbData);
302  for (int i = 0; i < FF_ARRAY_ELEMS(ext); i++)
303  LocalFree(ext[i].Value.pbData);
304 
305  return 0;
306 
307 fail:
308  if (*crtctx)
309  CertFreeCertificateContext(*crtctx);
310  if (*key)
311  if (NCryptDeleteKey(*key, NCRYPT_SILENT_FLAG) != ERROR_SUCCESS)
312  NCryptFreeObject(*key);
313  if (provider)
314  NCryptFreeObject(provider);
315  if (subject.pbData)
316  av_free(subject.pbData);
317  for (int i = 0; i < FF_ARRAY_ELEMS(ext); i++)
318  if (ext[i].Value.pbData)
319  LocalFree(ext[i].Value.pbData);
320 
321  *key = 0;
322  *crtctx = NULL;
323 
324  return ret;
325 }
326 
327 static int tls_export_key_cert(NCRYPT_KEY_HANDLE key, PCCERT_CONTEXT crtctx,
328  char *key_buf, size_t key_sz, char *cert_buf, size_t cert_sz, char **fingerprint)
329 {
330  DWORD keysize = 0;
331  char *keybuf = NULL;
332 
333  SECURITY_STATUS sspi_ret;
334  int ret = 0;
335 
336  sspi_ret = NCryptExportKey(key, 0, NCRYPT_PKCS8_PRIVATE_KEY_BLOB, NULL, NULL, 0, &keysize, 0);
337  if (sspi_ret != ERROR_SUCCESS) {
338  av_log(NULL, AV_LOG_ERROR, "Initial NCryptExportKey failed(0x%lx)\n", sspi_ret);
340  goto end;
341  }
342 
343  keybuf = av_malloc(keysize);
344  if (!keybuf) {
345  ret = AVERROR(ENOMEM);
346  goto end;
347  }
348 
349  sspi_ret = NCryptExportKey(key, 0, NCRYPT_PKCS8_PRIVATE_KEY_BLOB, NULL, keybuf, keysize, &keysize, 0);
350  if (sspi_ret != ERROR_SUCCESS) {
351  av_log(NULL, AV_LOG_ERROR, "Initial NCryptExportKey failed(0x%lx)\n", sspi_ret);
353  goto end;
354  }
355 
356  ret = der_to_pem(keybuf, keysize, "PRIVATE KEY", key_buf, key_sz);
357  if (ret < 0)
358  goto end;
359 
360  ret = der_to_pem(crtctx->pbCertEncoded, crtctx->cbCertEncoded, "CERTIFICATE", cert_buf, cert_sz);
361  if (ret < 0)
362  goto end;
363 
364  ret = der_to_fingerprint(crtctx->pbCertEncoded, crtctx->cbCertEncoded, fingerprint);
365  if (ret < 0)
366  goto end;
367 
368 end:
369  av_free(keybuf);
370  return ret;
371 }
372 
373 int ff_ssl_gen_key_cert(char *key_buf, size_t key_sz, char *cert_buf, size_t cert_sz, char **fingerprint)
374 {
375  NCRYPT_KEY_HANDLE key = 0;
376  PCCERT_CONTEXT crtctx = NULL;
377 
378  int ret = tls_gen_self_signed(&key, &crtctx);
379  if (ret < 0)
380  goto end;
381 
382  ret = tls_export_key_cert(key, crtctx, key_buf, key_sz, cert_buf, cert_sz, fingerprint);
383  if (ret < 0)
384  goto end;
385 
386 end:
387  if (key)
388  if (NCryptDeleteKey(key, NCRYPT_SILENT_FLAG) != ERROR_SUCCESS)
389  NCryptFreeObject(key);
390  if (crtctx)
391  CertFreeCertificateContext(crtctx);
392 
393  return ret;
394 }
395 
396 static int tls_import_key_cert(char *key_buf, char *cert_buf, NCRYPT_KEY_HANDLE *key, PCCERT_CONTEXT *crtctx)
397 {
398  NCRYPT_PROV_HANDLE provider = 0;
399 
400  DWORD export_props = NCRYPT_ALLOW_EXPORT_FLAG | NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG;
401  DWORD usage_props = NCRYPT_ALLOW_ALL_USAGES;
402  NCryptBufferDesc buffer_desc = { 0 };
403  NCryptBuffer buffer = { 0 };
404  CRYPT_KEY_PROV_INFO prov_info = { 0 };
405 
406  int key_der_len = 0, cert_der_len = 0;
407  char *key_der = NULL, *cert_der = NULL;
408 
409  SECURITY_STATUS sspi_ret;
410  int ret = 0;
411 
412  ret = pem_to_der(key_buf, &key_der, &key_der_len);
413  if (ret < 0)
414  goto fail;
415 
416  ret = pem_to_der(cert_buf, &cert_der, &cert_der_len);
417  if (ret < 0)
418  goto fail;
419 
420  sspi_ret = NCryptOpenStorageProvider(&provider, MS_KEY_STORAGE_PROVIDER, 0);
421  if (sspi_ret != ERROR_SUCCESS) {
422  av_log(NULL, AV_LOG_ERROR, "NCryptOpenStorageProvider failed(0x%lx)\n", sspi_ret);
424  goto fail;
425  }
426 
427  buffer_desc.ulVersion = NCRYPTBUFFER_VERSION;
428  buffer_desc.cBuffers = 1;
429  buffer_desc.pBuffers = &buffer;
430 
431  buffer.BufferType = NCRYPTBUFFER_PKCS_KEY_NAME;
432  buffer.pvBuffer = (LPWSTR)FF_NCRYPT_TEMP_KEY_NAME;
433  buffer.cbBuffer = sizeof(FF_NCRYPT_TEMP_KEY_NAME);
434 
435  sspi_ret = NCryptImportKey(provider, 0, NCRYPT_PKCS8_PRIVATE_KEY_BLOB, &buffer_desc, key, key_der, key_der_len, NCRYPT_DO_NOT_FINALIZE_FLAG | NCRYPT_OVERWRITE_KEY_FLAG);
436  if (sspi_ret != ERROR_SUCCESS) {
437  av_log(NULL, AV_LOG_ERROR, "NCryptImportKey failed(0x%lx)\n", sspi_ret);
439  goto fail;
440  }
441 
442  sspi_ret = NCryptSetProperty(*key, NCRYPT_EXPORT_POLICY_PROPERTY, (PBYTE)&export_props, sizeof(export_props), 0);
443  if (sspi_ret != ERROR_SUCCESS) {
444  av_log(NULL, AV_LOG_ERROR, "NCryptSetProperty(NCRYPT_EXPORT_POLICY_PROPERTY) failed(0x%lx)\n", sspi_ret);
446  goto fail;
447  }
448 
449  sspi_ret = NCryptSetProperty(*key, NCRYPT_KEY_USAGE_PROPERTY, (PBYTE)&usage_props, sizeof(usage_props), 0);
450  if (sspi_ret != ERROR_SUCCESS) {
451  av_log(NULL, AV_LOG_ERROR, "NCryptSetProperty(NCRYPT_KEY_USAGE_PROPERTY) failed(0x%lx)\n", sspi_ret);
453  goto fail;
454  }
455 
456  sspi_ret = NCryptFinalizeKey(*key, 0);
457  if (sspi_ret != ERROR_SUCCESS) {
458  av_log(NULL, AV_LOG_ERROR, "NCryptFinalizeKey failed(0x%lx)\n", sspi_ret);
460  goto fail;
461  }
462 
463  *crtctx = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, cert_der, cert_der_len);
464  if (!*crtctx) {
465  av_log(NULL, AV_LOG_ERROR, "CertCreateCertificateContext failed: %lu\n", GetLastError());
467  goto fail;
468  }
469 
470  if (!CertSetCertificateContextProperty(*crtctx, CERT_NCRYPT_KEY_HANDLE_PROP_ID, 0, key)) {
471  av_log(NULL, AV_LOG_ERROR, "CertSetCertificateContextProperty(CERT_NCRYPT_KEY_HANDLE_PROP_ID) failed: %lu\n", GetLastError());
473  goto fail;
474  }
475 
476  prov_info.pwszProvName = (LPWSTR)MS_KEY_STORAGE_PROVIDER;
477  prov_info.pwszContainerName = (LPWSTR)FF_NCRYPT_TEMP_KEY_NAME;
478  prov_info.dwFlags = CERT_SET_KEY_CONTEXT_PROP_ID;
479 
480  if (!CertSetCertificateContextProperty(*crtctx, CERT_KEY_PROV_INFO_PROP_ID, 0, &prov_info)) {
481  av_log(NULL, AV_LOG_ERROR, "CertSetCertificateContextProperty(CERT_KEY_PROV_INFO_PROP_ID) failed: %lu\n", GetLastError());
483  goto fail;
484  }
485 
486  goto end;
487 
488 fail:
489  if (*key)
490  if (NCryptDeleteKey(*key, NCRYPT_SILENT_FLAG) != ERROR_SUCCESS)
491  NCryptFreeObject(*key);
492  if (*crtctx)
493  CertFreeCertificateContext(*crtctx);
494 
495  *key = 0;
496  *crtctx = NULL;
497 
498 end:
499  if (key_der)
500  av_free(key_der);
501  if (cert_der)
502  av_free(cert_der);
503  if (provider)
504  NCryptFreeObject(provider);
505  return ret;
506 }
507 
508 static int tls_cert_from_store(void *logctx, const char *cert_store_name, const char *cert_subj, PCCERT_CONTEXT *crtctx)
509 {
510  HCERTSTORE cert_store = NULL;
511  int ret = 0;
512 
513  cert_store = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, 0, CERT_SYSTEM_STORE_CURRENT_USER, cert_store_name);
514  if (!cert_store) {
515  av_log(logctx, AV_LOG_ERROR, "Opening user cert store %s failed\n", cert_store_name);
517  goto end;
518  }
519 
520  *crtctx = CertFindCertificateInStore(cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_SUBJECT_STR_A, cert_subj, NULL);
521  if (!*crtctx) {
522  av_log(logctx, AV_LOG_ERROR, "Could not find certificate in store\n");
524  goto end;
525  }
526 
527 end:
528  if (cert_store)
529  CertCloseStore(cert_store, 0);
530 
531  return ret;
532 }
533 
534 static int tls_load_key_cert(char *key_url, char *cert_url, NCRYPT_KEY_HANDLE *key, PCCERT_CONTEXT *crtctx)
535 {
536  AVBPrint key_bp, cert_bp;
537  int ret = 0;
538 
540  av_bprint_init(&cert_bp, 1, MAX_CERTIFICATE_SIZE);
541 
542  /* Read key file. */
543  ret = ff_url_read_all(key_url, &key_bp);
544  if (ret < 0) {
545  av_log(NULL, AV_LOG_ERROR, "Failed to open key file %s\n", key_url);
546  goto end;
547  }
548 
549  ret = ff_url_read_all(cert_url, &cert_bp);
550  if (ret < 0) {
551  av_log(NULL, AV_LOG_ERROR, "Failed to open cert file %s\n", cert_url);
552  goto end;
553  }
554 
555  ret = tls_import_key_cert(key_bp.str, cert_bp.str, key, crtctx);
556  if (ret < 0)
557  goto end;
558 
559 end:
560  av_bprint_finalize(&key_bp, NULL);
561  av_bprint_finalize(&cert_bp, NULL);
562 
563  return ret;
564 }
565 
566 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)
567 {
568  NCRYPT_KEY_HANDLE key = 0;
569  PCCERT_CONTEXT crtctx = NULL;
570 
571  int ret = tls_load_key_cert(key_url, cert_url, &key, &crtctx);
572  if (ret < 0)
573  goto end;
574 
575  ret = tls_export_key_cert(key, crtctx, key_buf, key_sz, cert_buf, cert_sz, fingerprint);
576  if (ret < 0)
577  goto end;
578 
579 end:
580  if (key)
581  if (NCryptDeleteKey(key, NCRYPT_SILENT_FLAG) != ERROR_SUCCESS)
582  NCryptFreeObject(key);
583  if (crtctx)
584  CertFreeCertificateContext(crtctx);
585 
586  return ret;
587 }
588 
589 typedef struct TLSContext {
590  const AVClass *class;
592 
595 
596  CredHandle cred_handle;
597  TimeStamp cred_timestamp;
598 
599  CtxtHandle ctxt_handle;
601  TimeStamp ctxt_timestamp;
602 
605 
606  uint8_t *enc_buf;
609 
610  uint8_t *dec_buf;
613 
614  char *send_buf;
617 
618  SecPkgContext_StreamSizes sizes;
619 
623 } TLSContext;
624 
626 {
627  TLSContext *c = h->priv_data;
628  TLSShared *s = &c->tls_shared;
629 
630  if (s->is_dtls)
631  c->tls_shared.udp = sock;
632  else
633  c->tls_shared.tcp = sock;
634 
635  return 0;
636 }
637 
638 int ff_dtls_export_materials(URLContext *h, char *dtls_srtp_materials, size_t materials_sz)
639 {
640 #if HAVE_SECPKGCONTEXT_KEYINGMATERIALINFO
641  TLSContext *c = h->priv_data;
642 
643  SecPkgContext_KeyingMaterialInfo keying_info = { 0 };
644  SecPkgContext_KeyingMaterial keying_material = { 0 };
645 
646  const char* dst = "EXTRACTOR-dtls_srtp";
647  SECURITY_STATUS sspi_ret;
648 
649  if (!c->have_context)
650  return AVERROR(EINVAL);
651 
652  keying_info.cbLabel = strlen(dst) + 1;
653  keying_info.pszLabel = (LPSTR)dst;
654  keying_info.cbContextValue = 0;
655  keying_info.pbContextValue = NULL;
656  keying_info.cbKeyingMaterial = materials_sz;
657 
658  sspi_ret = SetContextAttributes(&c->ctxt_handle, SECPKG_ATTR_KEYING_MATERIAL_INFO, &keying_info, sizeof(keying_info));
659  if (sspi_ret != SEC_E_OK) {
660  av_log(h, AV_LOG_ERROR, "Setting keying material info failed: %lx\n", sspi_ret);
661  return AVERROR_EXTERNAL;
662  }
663 
664  sspi_ret = QueryContextAttributes(&c->ctxt_handle, SECPKG_ATTR_KEYING_MATERIAL, &keying_material);
665  if (sspi_ret != SEC_E_OK) {
666  av_log(h, AV_LOG_ERROR, "Querying keying material failed: %lx\n", sspi_ret);
667  return AVERROR_EXTERNAL;
668  }
669 
670  memcpy(dtls_srtp_materials, keying_material.pbKeyingMaterial, FFMIN(materials_sz, keying_material.cbKeyingMaterial));
671  FreeContextBuffer(keying_material.pbKeyingMaterial);
672 
673  if (keying_material.cbKeyingMaterial > materials_sz) {
674  av_log(h, AV_LOG_WARNING, "Keying material size mismatch: %ld > %zu\n", keying_material.cbKeyingMaterial, materials_sz);
675  return AVERROR(ENOSPC);
676  }
677 
678  return 0;
679 #else
680  return AVERROR(ENOSYS);
681 #endif
682 }
683 
684 static void init_sec_buffer(SecBuffer *buffer, unsigned long type,
685  void *data, unsigned long size)
686 {
687  buffer->cbBuffer = size;
688  buffer->BufferType = type;
689  buffer->pvBuffer = data;
690 }
691 
692 static void init_sec_buffer_desc(SecBufferDesc *desc, SecBuffer *buffers,
693  unsigned long buffer_count)
694 {
695  desc->ulVersion = SECBUFFER_VERSION;
696  desc->pBuffers = buffers;
697  desc->cBuffers = buffer_count;
698 }
699 
701 {
702  TLSContext *c = h->priv_data;
703  TLSShared *s = &c->tls_shared;
704  URLContext *uc = s->is_dtls ? s->udp : s->tcp;
705  int ret;
706 
707  if (!c->send_buf)
708  return 0;
709 
710  ret = ffurl_write(uc, c->send_buf + c->send_buf_offset, c->send_buf_size - c->send_buf_offset);
711  if (ret == AVERROR(EAGAIN)) {
712  return AVERROR(EAGAIN);
713  } else if (ret < 0) {
714  av_log(h, AV_LOG_ERROR, "Writing encrypted data to socket failed\n");
715  return AVERROR(EIO);
716  }
717 
718  c->send_buf_offset += ret;
719 
720  if (c->send_buf_offset < c->send_buf_size)
721  return AVERROR(EAGAIN);
722 
723  av_freep(&c->send_buf);
724  c->send_buf_size = c->send_buf_offset = 0;
725 
726  return 0;
727 }
728 
730 {
731  TLSContext *c = h->priv_data;
732  TLSShared *s = &c->tls_shared;
733  URLContext *uc = s->is_dtls ? s->udp : s->tcp;
734  int ret;
735 
736  if (c->connected) {
737  SecBufferDesc BuffDesc;
738  SecBuffer Buffer;
739  SECURITY_STATUS sspi_ret;
740  SecBuffer outbuf;
741  SecBufferDesc outbuf_desc;
742 
743  DWORD dwshut = SCHANNEL_SHUTDOWN;
744  init_sec_buffer(&Buffer, SECBUFFER_TOKEN, &dwshut, sizeof(dwshut));
745  init_sec_buffer_desc(&BuffDesc, &Buffer, 1);
746 
747  uc->flags &= ~AVIO_FLAG_NONBLOCK;
749  if (ret < 0)
750  return ret;
751 
752  sspi_ret = ApplyControlToken(&c->ctxt_handle, &BuffDesc);
753  if (sspi_ret != SEC_E_OK)
754  av_log(h, AV_LOG_ERROR, "ApplyControlToken failed\n");
755 
756  init_sec_buffer(&outbuf, SECBUFFER_TOKEN, NULL, 0);
757  init_sec_buffer_desc(&outbuf_desc, &outbuf, 1);
758 
759  do {
760  if (s->listen)
761  sspi_ret = AcceptSecurityContext(&c->cred_handle, &c->ctxt_handle, NULL, c->request_flags, 0,
762  &c->ctxt_handle, &outbuf_desc, &c->context_flags,
763  &c->ctxt_timestamp);
764  else
765  sspi_ret = InitializeSecurityContext(&c->cred_handle, &c->ctxt_handle, s->host,
766  c->request_flags, 0, 0, NULL, 0, &c->ctxt_handle,
767  &outbuf_desc, &c->context_flags, &c->ctxt_timestamp);
768 
769  if (outbuf.pvBuffer) {
770  if (outbuf.cbBuffer > 0) {
771  ret = ffurl_write(uc, outbuf.pvBuffer, outbuf.cbBuffer);
772  if (ret < 0 || ret != outbuf.cbBuffer)
773  av_log(h, AV_LOG_ERROR, "Failed to send close message\n");
774  }
775  FreeContextBuffer(outbuf.pvBuffer);
776  }
777  } while(
778 #ifdef SEC_I_MESSAGE_FRAGMENT
779  sspi_ret == SEC_I_MESSAGE_FRAGMENT ||
780 #endif
781  sspi_ret == SEC_I_CONTINUE_NEEDED);
782 
783  av_log(h, AV_LOG_DEBUG, "Close session result: 0x%lx\n", sspi_ret);
784 
785  c->connected = 0;
786  }
787  return 0;
788 }
789 
790 static int tls_close(URLContext *h)
791 {
792  TLSContext *c = h->priv_data;
793  TLSShared *s = &c->tls_shared;
794 
796 
797  DeleteSecurityContext(&c->ctxt_handle);
798  FreeCredentialsHandle(&c->cred_handle);
799 
800  av_freep(&c->enc_buf);
801  c->enc_buf_size = c->enc_buf_offset = 0;
802 
803  av_freep(&c->dec_buf);
804  c->dec_buf_size = c->dec_buf_offset = 0;
805 
806  av_freep(&c->send_buf);
807  c->send_buf_size = c->send_buf_offset = 0;
808 
809  if (s->is_dtls) {
810  if (!s->external_sock)
811  ffurl_closep(&c->tls_shared.udp);
812  } else {
813  ffurl_closep(&c->tls_shared.tcp);
814  }
815 
816  return 0;
817 }
818 
819 static int tls_handshake_loop(URLContext *h, int initial)
820 {
821  TLSContext *c = h->priv_data;
822  TLSShared *s = &c->tls_shared;
823  URLContext *uc = s->is_dtls ? s->udp : s->tcp;
824  SECURITY_STATUS sspi_ret;
825  SecBuffer outbuf[3] = { 0 };
826  SecBufferDesc outbuf_desc;
827  SecBuffer inbuf[3];
828  SecBufferDesc inbuf_desc;
829  struct sockaddr_storage recv_addr = { 0 };
830  socklen_t recv_addr_len = 0;
831  int i, ret = 0, read_data = initial;
832 
833  if (c->enc_buf == NULL) {
834  c->enc_buf_offset = 0;
836  if (ret < 0)
837  goto fail;
838  c->enc_buf_size = SCHANNEL_INITIAL_BUFFER_SIZE;
839  }
840 
841  if (c->dec_buf == NULL) {
842  c->dec_buf_offset = 0;
844  if (ret < 0)
845  goto fail;
846  c->dec_buf_size = SCHANNEL_INITIAL_BUFFER_SIZE;
847  }
848 
849  uc->flags &= ~AVIO_FLAG_NONBLOCK;
850 
851  while (1) {
852  if (c->enc_buf_size - c->enc_buf_offset < SCHANNEL_FREE_BUFFER_SIZE) {
853  c->enc_buf_size = c->enc_buf_offset + SCHANNEL_FREE_BUFFER_SIZE;
854  ret = av_reallocp(&c->enc_buf, c->enc_buf_size);
855  if (ret < 0) {
856  c->enc_buf_size = c->enc_buf_offset = 0;
857  goto fail;
858  }
859  }
860 
861  if (read_data) {
862  ret = ffurl_read(uc, c->enc_buf + c->enc_buf_offset, c->enc_buf_size - c->enc_buf_offset);
863  if (ret < 0) {
864  av_log(h, AV_LOG_ERROR, "Failed to read handshake response\n");
865  goto fail;
866  }
867  c->enc_buf_offset += ret;
868  if (s->is_dtls && !recv_addr_len) {
869  ff_udp_get_last_recv_addr(uc, &recv_addr, &recv_addr_len);
870 
871  if (s->listen) {
872  ret = ff_udp_set_remote_addr(uc, (struct sockaddr *)&recv_addr, recv_addr_len, 1);
873  if (ret < 0) {
874  av_log(h, AV_LOG_ERROR, "Failed connecting udp context\n");
875  goto fail;
876  }
877  av_log(h, AV_LOG_TRACE, "Set UDP remote addr on UDP socket, now 'connected'\n");
878  }
879  }
880  }
881 
882  /* input buffers */
883  init_sec_buffer(&inbuf[0], SECBUFFER_TOKEN, av_malloc(c->enc_buf_offset), c->enc_buf_offset);
884  init_sec_buffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0);
885  if (s->listen && s->is_dtls) {
886  init_sec_buffer(&inbuf[2], SECBUFFER_EXTRA, &recv_addr, recv_addr_len);
887  init_sec_buffer_desc(&inbuf_desc, inbuf, 3);
888  } else {
889  init_sec_buffer_desc(&inbuf_desc, inbuf, 2);
890  }
891 
892  if (inbuf[0].pvBuffer == NULL) {
893  av_log(h, AV_LOG_ERROR, "Failed to allocate input buffer\n");
894  ret = AVERROR(ENOMEM);
895  goto fail;
896  }
897 
898  memcpy(inbuf[0].pvBuffer, c->enc_buf, c->enc_buf_offset);
899 
900  /* output buffers */
901  init_sec_buffer(&outbuf[0], SECBUFFER_TOKEN, NULL, 0);
902  init_sec_buffer(&outbuf[1], SECBUFFER_ALERT, NULL, 0);
903  init_sec_buffer(&outbuf[2], SECBUFFER_EMPTY, NULL, 0);
904  init_sec_buffer_desc(&outbuf_desc, outbuf, 3);
905 
906  if (s->listen)
907  sspi_ret = AcceptSecurityContext(&c->cred_handle, c->have_context ? &c->ctxt_handle : NULL, &inbuf_desc,
908  c->request_flags, 0, &c->ctxt_handle, &outbuf_desc,
909  &c->context_flags, &c->ctxt_timestamp);
910  else
911  sspi_ret = InitializeSecurityContext(&c->cred_handle, c->have_context ? &c->ctxt_handle : NULL,
912  s->host, c->request_flags, 0, 0, &inbuf_desc, 0, &c->ctxt_handle,
913  &outbuf_desc, &c->context_flags, &c->ctxt_timestamp);
914  av_freep(&inbuf[0].pvBuffer);
915 
916  av_log(h, AV_LOG_TRACE, "Handshake res with %d bytes of data: 0x%lx\n", c->enc_buf_offset, sspi_ret);
917 
918  if (sspi_ret == SEC_E_INCOMPLETE_MESSAGE) {
919  av_log(h, AV_LOG_TRACE, "Received incomplete handshake, need more data\n");
920  read_data = 1;
921  continue;
922  }
923 
924  c->have_context = 1;
925 
926  /* remote requests a client certificate - attempt to continue without one anyway */
927  if (sspi_ret == SEC_I_INCOMPLETE_CREDENTIALS &&
928  !(c->request_flags & ISC_REQ_USE_SUPPLIED_CREDS)) {
929  av_log(h, AV_LOG_VERBOSE, "Client certificate has been requested, ignoring\n");
930  c->request_flags |= ISC_REQ_USE_SUPPLIED_CREDS;
931  read_data = 0;
932  continue;
933  }
934 
935  /* continue handshake */
936  if (sspi_ret == SEC_I_CONTINUE_NEEDED ||
937 #ifdef SEC_I_MESSAGE_FRAGMENT
938  sspi_ret == SEC_I_MESSAGE_FRAGMENT ||
939 #endif
940  sspi_ret == SEC_E_OK) {
941  for (i = 0; i < 3; i++) {
942  if (outbuf[i].BufferType == SECBUFFER_TOKEN && outbuf[i].cbBuffer > 0) {
943  ret = ffurl_write(uc, outbuf[i].pvBuffer, outbuf[i].cbBuffer);
944  if (ret < 0 || ret != outbuf[i].cbBuffer) {
945  av_log(h, AV_LOG_VERBOSE, "Failed to send handshake data\n");
946  ret = AVERROR(EIO);
947  goto fail;
948  }
949  }
950 
951  if (outbuf[i].pvBuffer != NULL) {
952  FreeContextBuffer(outbuf[i].pvBuffer);
953  outbuf[i].pvBuffer = NULL;
954  }
955  }
956  } else {
957  if (sspi_ret == SEC_E_WRONG_PRINCIPAL)
958  av_log(h, AV_LOG_ERROR, "SNI or certificate check failed\n");
959  else
960  av_log(h, AV_LOG_ERROR, "Creating security context failed (0x%lx)\n", sspi_ret);
962  goto fail;
963  }
964 
965 #ifdef SEC_I_MESSAGE_FRAGMENT
966  if (sspi_ret == SEC_I_MESSAGE_FRAGMENT) {
967  av_log(h, AV_LOG_TRACE, "Writing fragmented output message part\n");
968  read_data = 0;
969  continue;
970  }
971 #endif
972 
973  if (inbuf[1].BufferType == SECBUFFER_EXTRA && inbuf[1].cbBuffer > 0) {
974  if (c->enc_buf_offset > inbuf[1].cbBuffer) {
975  memmove(c->enc_buf, (c->enc_buf + c->enc_buf_offset) - inbuf[1].cbBuffer,
976  inbuf[1].cbBuffer);
977  c->enc_buf_offset = inbuf[1].cbBuffer;
978  if (sspi_ret == SEC_I_CONTINUE_NEEDED) {
979  av_log(h, AV_LOG_TRACE, "Sent reply, handshake continues. %d extra bytes\n", (int)inbuf[1].cbBuffer);
980  read_data = 0;
981  continue;
982  }
983  }
984  } else {
985  c->enc_buf_offset = 0;
986  }
987 
988  if (sspi_ret == SEC_I_CONTINUE_NEEDED) {
989  av_log(h, AV_LOG_TRACE, "Handshake continues\n");
990  read_data = 1;
991  continue;
992  }
993 
994  break;
995  }
996 
997  av_log(h, AV_LOG_TRACE, "Handshake completed\n");
998 
999  return 0;
1000 
1001 fail:
1002  /* free any remaining output data */
1003  for (i = 0; i < 3; i++) {
1004  if (outbuf[i].pvBuffer != NULL) {
1005  FreeContextBuffer(outbuf[i].pvBuffer);
1006  outbuf[i].pvBuffer = NULL;
1007  }
1008  }
1009 
1010  av_log(h, AV_LOG_TRACE, "Handshake failed\n");
1011 
1012  return ret;
1013 }
1014 
1016 {
1017  TLSContext *c = h->priv_data;
1018  TLSShared *s = &c->tls_shared;
1019  URLContext *uc = s->is_dtls ? s->udp : s->tcp;
1020  SecBuffer outbuf;
1021  SecBufferDesc outbuf_desc;
1022  SECURITY_STATUS sspi_ret;
1023  int ret;
1024 
1025  init_sec_buffer(&outbuf, SECBUFFER_EMPTY, NULL, 0);
1026  init_sec_buffer_desc(&outbuf_desc, &outbuf, 1);
1027 
1028  c->request_flags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT |
1029  ISC_REQ_CONFIDENTIALITY | ISC_REQ_ALLOCATE_MEMORY;
1030  if (s->is_dtls)
1031  c->request_flags |= ISC_REQ_DATAGRAM;
1032  else
1033  c->request_flags |= ISC_REQ_STREAM;
1034 
1035  sspi_ret = InitializeSecurityContext(&c->cred_handle, NULL, s->host, c->request_flags, 0, 0,
1036  NULL, 0, &c->ctxt_handle, &outbuf_desc, &c->context_flags,
1037  &c->ctxt_timestamp);
1038  if (sspi_ret != SEC_I_CONTINUE_NEEDED) {
1039  av_log(h, AV_LOG_ERROR, "Unable to create initial security context (0x%lx)\n", sspi_ret);
1040  ret = AVERROR_UNKNOWN;
1041  goto fail;
1042  }
1043 
1044  c->have_context = 1;
1045 
1046  uc->flags &= ~AVIO_FLAG_NONBLOCK;
1047  ret = ffurl_write(uc, outbuf.pvBuffer, outbuf.cbBuffer);
1048  FreeContextBuffer(outbuf.pvBuffer);
1049  if (ret < 0 || ret != outbuf.cbBuffer) {
1050  av_log(h, AV_LOG_ERROR, "Failed to send initial handshake data\n");
1051  ret = AVERROR(EIO);
1052  goto fail;
1053  }
1054 
1055  return tls_handshake_loop(h, 1);
1056 
1057 fail:
1058  DeleteSecurityContext(&c->ctxt_handle);
1059  return ret;
1060 }
1061 
1063 {
1064  TLSContext *c = h->priv_data;
1065  TLSShared *s = &c->tls_shared;
1066 
1067  c->request_flags = ASC_REQ_SEQUENCE_DETECT | ASC_REQ_REPLAY_DETECT |
1068  ASC_REQ_CONFIDENTIALITY | ASC_REQ_ALLOCATE_MEMORY;
1069  if (s->is_dtls)
1070  c->request_flags |= ASC_REQ_DATAGRAM;
1071  else
1072  c->request_flags |= ASC_REQ_STREAM;
1073 
1074  c->have_context = 0;
1075 
1076  return tls_handshake_loop(h, 1);
1077 }
1078 
1080 {
1081  TLSContext *c = h->priv_data;
1082  TLSShared *s = &c->tls_shared;
1083  SECURITY_STATUS sspi_ret;
1084  int ret = 0;
1085 
1086  if (s->listen)
1088  else
1090 
1091  if (ret < 0)
1092  goto fail;
1093 
1094 #if CONFIG_DTLS_PROTOCOL
1095  if (s->is_dtls && s->mtu > 0) {
1096  ULONG mtu = s->mtu;
1097  sspi_ret = SetContextAttributes(&c->ctxt_handle, SECPKG_ATTR_DTLS_MTU, &mtu, sizeof(mtu));
1098  if (sspi_ret != SEC_E_OK) {
1099  av_log(h, AV_LOG_ERROR, "Failed setting DTLS MTU to %d.\n", s->mtu);
1100  ret = AVERROR(EINVAL);
1101  goto fail;
1102  }
1103  av_log(h, AV_LOG_VERBOSE, "Set DTLS MTU to %d\n", s->mtu);
1104  }
1105 #endif
1106 
1107  c->connected = 1;
1108 
1109 fail:
1110  return ret;
1111 }
1112 
1113 static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
1114 {
1115  TLSContext *c = h->priv_data;
1116  TLSShared *s = &c->tls_shared;
1117  SECURITY_STATUS sspi_ret;
1118  SCHANNEL_CRED schannel_cred = { 0 };
1119  PCCERT_CONTEXT crtctx = NULL;
1120  NCRYPT_KEY_HANDLE key = 0;
1121  int ret = 0;
1122 
1123  if (!s->external_sock) {
1124  if ((ret = ff_tls_open_underlying(s, h, uri, options)) < 0)
1125  goto fail;
1126  }
1127 
1128  /* SChannel Options */
1129  schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
1130 
1131  if (s->listen) {
1132  if (c->cert_store_name && c->cert_store_subject) {
1133  ret = tls_cert_from_store(h, c->cert_store_name, c->cert_store_subject, &crtctx);
1134  } else if (s->key_buf && s->cert_buf) {
1135  ret = tls_import_key_cert(s->key_buf, s->cert_buf, &key, &crtctx);
1136  } else if (s->key_file && s->cert_file) {
1137  ret = tls_load_key_cert(s->key_file, s->cert_file, &key, &crtctx);
1138  } else {
1139  av_log(h, AV_LOG_VERBOSE, "No server certificate provided, using self-signed\n");
1140  ret = tls_gen_self_signed(&key, &crtctx);
1141  }
1142 
1143  if (ret < 0)
1144  goto fail;
1145 
1146  schannel_cred.cCreds = 1;
1147  schannel_cred.paCred = &crtctx;
1148 
1149  schannel_cred.dwFlags = SCH_CRED_NO_SYSTEM_MAPPER | SCH_CRED_MANUAL_CRED_VALIDATION;
1150 
1151 #if CONFIG_DTLS_PROTOCOL
1152  if (s->is_dtls)
1153  schannel_cred.grbitEnabledProtocols = SP_PROT_DTLS1_X_SERVER;
1154 #endif
1155  } else {
1156  if (s->verify)
1157  schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION |
1158  SCH_CRED_REVOCATION_CHECK_CHAIN;
1159  else
1160  schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION |
1161  SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
1162  SCH_CRED_IGNORE_REVOCATION_OFFLINE;
1163 
1164 #if CONFIG_DTLS_PROTOCOL
1165  if (s->is_dtls)
1166  schannel_cred.grbitEnabledProtocols = SP_PROT_DTLS1_X_CLIENT;
1167 #endif
1168  }
1169 
1170  /* Get credential handle */
1171  sspi_ret = AcquireCredentialsHandle(NULL, (TCHAR *)UNISP_NAME,
1172  s->listen ? SECPKG_CRED_INBOUND : SECPKG_CRED_OUTBOUND,
1173  NULL, &schannel_cred, NULL, NULL, &c->cred_handle,
1174  &c->cred_timestamp);
1175  if (sspi_ret != SEC_E_OK) {
1176  av_log(h, AV_LOG_ERROR, "Unable to acquire security credentials (0x%lx)\n", sspi_ret);
1177  ret = AVERROR_UNKNOWN;
1178  goto fail;
1179  }
1180 
1181  if (!s->external_sock) {
1182  ret = tls_handshake(h);
1183  if (ret < 0)
1184  goto fail;
1185  }
1186 
1187  goto end;
1188 
1189 fail:
1190  tls_close(h);
1191 
1192 end:
1193  if (crtctx)
1194  CertFreeCertificateContext(crtctx);
1195  if (key)
1196  if (NCryptDeleteKey(key, NCRYPT_SILENT_FLAG) != ERROR_SUCCESS)
1197  NCryptFreeObject(key);
1198 
1199  return ret;
1200 }
1201 
1202 #if CONFIG_DTLS_PROTOCOL
1203 static int dtls_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
1204 {
1205  TLSContext *c = h->priv_data;
1206  TLSShared *s = &c->tls_shared;
1207 
1208  s->is_dtls = 1;
1209 
1210  return tls_open(h, uri, flags, options);
1211 }
1212 #endif
1213 
1214 static int tls_read(URLContext *h, uint8_t *buf, int len)
1215 {
1216  TLSContext *c = h->priv_data;
1217  TLSShared *s = &c->tls_shared;
1218  URLContext *uc = s->is_dtls ? s->udp : s->tcp;
1219  SECURITY_STATUS sspi_ret = SEC_E_OK;
1220  SecBuffer inbuf[4];
1221  SecBufferDesc inbuf_desc;
1222  int size, ret = 0;
1223  int min_enc_buf_size = len + SCHANNEL_FREE_BUFFER_SIZE;
1224 
1225  /* If we have some left-over data from previous network activity,
1226  * return it first in case it is enough. It may contain
1227  * data that is required to know whether this connection
1228  * is still required or not, esp. in case of HTTP keep-alive
1229  * connections. */
1230  if (c->dec_buf_offset > 0)
1231  goto cleanup;
1232 
1233  if (c->sspi_close_notify)
1234  goto cleanup;
1235 
1236  if (!c->connection_closed) {
1237  size = c->enc_buf_size - c->enc_buf_offset;
1238  if (size < SCHANNEL_FREE_BUFFER_SIZE || c->enc_buf_size < min_enc_buf_size) {
1239  c->enc_buf_size = c->enc_buf_offset + SCHANNEL_FREE_BUFFER_SIZE;
1240  if (c->enc_buf_size < min_enc_buf_size)
1241  c->enc_buf_size = min_enc_buf_size;
1242  ret = av_reallocp(&c->enc_buf, c->enc_buf_size);
1243  if (ret < 0) {
1244  c->enc_buf_size = c->enc_buf_offset = 0;
1245  return ret;
1246  }
1247  }
1248 
1249  uc->flags &= ~AVIO_FLAG_NONBLOCK;
1250  uc->flags |= h->flags & AVIO_FLAG_NONBLOCK;
1251 
1252  ret = ffurl_read(uc, c->enc_buf + c->enc_buf_offset,
1253  c->enc_buf_size - c->enc_buf_offset);
1254  if (ret == AVERROR_EOF) {
1255  c->connection_closed = 1;
1256  ret = 0;
1257  } else if (ret == AVERROR(EAGAIN)) {
1258  ret = 0;
1259  } else if (ret < 0) {
1260  av_log(h, AV_LOG_ERROR, "Unable to read from socket\n");
1261  return ret;
1262  }
1263 
1264  c->enc_buf_offset += ret;
1265  }
1266 
1267  while (c->enc_buf_offset > 0 && sspi_ret == SEC_E_OK) {
1268  /* input buffer */
1269  init_sec_buffer(&inbuf[0], SECBUFFER_DATA, c->enc_buf, c->enc_buf_offset);
1270 
1271  /* additional buffers for possible output */
1272  init_sec_buffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0);
1273  init_sec_buffer(&inbuf[2], SECBUFFER_EMPTY, NULL, 0);
1274  init_sec_buffer(&inbuf[3], SECBUFFER_EMPTY, NULL, 0);
1275  init_sec_buffer_desc(&inbuf_desc, inbuf, 4);
1276 
1277  sspi_ret = DecryptMessage(&c->ctxt_handle, &inbuf_desc, 0, NULL);
1278  if (sspi_ret == SEC_E_OK || sspi_ret == SEC_I_RENEGOTIATE ||
1279  sspi_ret == SEC_I_CONTEXT_EXPIRED) {
1280  /* handle decrypted data */
1281  if (inbuf[1].BufferType == SECBUFFER_DATA) {
1282  /* grow buffer if needed */
1283  size = inbuf[1].cbBuffer > SCHANNEL_FREE_BUFFER_SIZE ?
1284  inbuf[1].cbBuffer : SCHANNEL_FREE_BUFFER_SIZE;
1285  if (c->dec_buf_size - c->dec_buf_offset < size || c->dec_buf_size < len) {
1286  c->dec_buf_size = c->dec_buf_offset + size;
1287  if (c->dec_buf_size < len)
1288  c->dec_buf_size = len;
1289  ret = av_reallocp(&c->dec_buf, c->dec_buf_size);
1290  if (ret < 0) {
1291  c->dec_buf_size = c->dec_buf_offset = 0;
1292  return ret;
1293  }
1294  }
1295 
1296  /* copy decrypted data to buffer */
1297  size = inbuf[1].cbBuffer;
1298  if (size) {
1299  memcpy(c->dec_buf + c->dec_buf_offset, inbuf[1].pvBuffer, size);
1300  c->dec_buf_offset += size;
1301  }
1302  }
1303  if (inbuf[3].BufferType == SECBUFFER_EXTRA && inbuf[3].cbBuffer > 0) {
1304  if (c->enc_buf_offset > inbuf[3].cbBuffer) {
1305  memmove(c->enc_buf, (c->enc_buf + c->enc_buf_offset) - inbuf[3].cbBuffer,
1306  inbuf[3].cbBuffer);
1307  c->enc_buf_offset = inbuf[3].cbBuffer;
1308  }
1309  } else
1310  c->enc_buf_offset = 0;
1311 
1312  if (sspi_ret == SEC_I_RENEGOTIATE) {
1313  if (c->enc_buf_offset) {
1314  av_log(h, AV_LOG_ERROR, "Cannot renegotiate, encrypted data buffer not empty\n");
1315  ret = AVERROR_UNKNOWN;
1316  goto cleanup;
1317  }
1318 
1319  av_log(h, AV_LOG_VERBOSE, "Re-negotiating security context\n");
1320  ret = tls_handshake_loop(h, 0);
1321  if (ret < 0) {
1322  goto cleanup;
1323  }
1324  sspi_ret = SEC_E_OK;
1325 
1326  /* if somehow any send data was left, it is now invalid */
1327  av_freep(&c->send_buf);
1328  c->send_buf_size = c->send_buf_offset = 0;
1329 
1330  continue;
1331  } else if (sspi_ret == SEC_I_CONTEXT_EXPIRED) {
1332  c->sspi_close_notify = 1;
1333  if (!c->connection_closed) {
1334  c->connection_closed = 1;
1335  av_log(h, AV_LOG_VERBOSE, "Server closed the connection\n");
1336  }
1337  ret = 0;
1338  goto cleanup;
1339  }
1340  } else if (sspi_ret == SEC_E_INCOMPLETE_MESSAGE) {
1341  ret = AVERROR(EAGAIN);
1342  goto cleanup;
1343  } else {
1344  av_log(h, AV_LOG_ERROR, "Unable to decrypt message (error 0x%x)\n", (unsigned)sspi_ret);
1345  ret = AVERROR(EIO);
1346  goto cleanup;
1347  }
1348  }
1349 
1350  ret = 0;
1351 
1352 cleanup:
1353  size = FFMIN(len, c->dec_buf_offset);
1354  if (size) {
1355  memcpy(buf, c->dec_buf, size);
1356  memmove(c->dec_buf, c->dec_buf + size, c->dec_buf_offset - size);
1357  c->dec_buf_offset -= size;
1358 
1359  return size;
1360  }
1361 
1362  if (ret == 0 && !c->connection_closed)
1363  ret = AVERROR(EAGAIN);
1364 
1365  return ret < 0 ? ret : AVERROR_EOF;
1366 }
1367 
1368 static int tls_write(URLContext *h, const uint8_t *buf, int len)
1369 {
1370  TLSContext *c = h->priv_data;
1371  TLSShared *s = &c->tls_shared;
1372  URLContext *uc = s->is_dtls ? s->udp : s->tcp;
1373  SECURITY_STATUS sspi_ret;
1374  SecBuffer outbuf[4];
1375  SecBufferDesc outbuf_desc;
1376  int ret = 0;
1377 
1378  uc->flags &= ~AVIO_FLAG_NONBLOCK;
1379  uc->flags |= h->flags & AVIO_FLAG_NONBLOCK;
1380 
1382  if (ret < 0)
1383  return ret;
1384 
1385  if (c->sizes.cbMaximumMessage == 0) {
1386  sspi_ret = QueryContextAttributes(&c->ctxt_handle, SECPKG_ATTR_STREAM_SIZES, &c->sizes);
1387  if (sspi_ret != SEC_E_OK)
1388  return AVERROR_UNKNOWN;
1389  }
1390 
1391  /* limit how much data we can consume */
1392  len = FFMIN(len, c->sizes.cbMaximumMessage - c->sizes.cbHeader - c->sizes.cbTrailer);
1393 
1394  c->send_buf_size = c->sizes.cbHeader + len + c->sizes.cbTrailer;
1395  c->send_buf = av_malloc(c->send_buf_size);
1396  if (c->send_buf == NULL)
1397  return AVERROR(ENOMEM);
1398 
1399  init_sec_buffer(&outbuf[0], SECBUFFER_STREAM_HEADER,
1400  c->send_buf, c->sizes.cbHeader);
1401  init_sec_buffer(&outbuf[1], SECBUFFER_DATA,
1402  c->send_buf + c->sizes.cbHeader, len);
1403  init_sec_buffer(&outbuf[2], SECBUFFER_STREAM_TRAILER,
1404  c->send_buf + c->sizes.cbHeader + len,
1405  c->sizes.cbTrailer);
1406  init_sec_buffer(&outbuf[3], SECBUFFER_EMPTY, NULL, 0);
1407  init_sec_buffer_desc(&outbuf_desc, outbuf, 4);
1408 
1409  memcpy(outbuf[1].pvBuffer, buf, len);
1410 
1411  sspi_ret = EncryptMessage(&c->ctxt_handle, 0, &outbuf_desc, 0);
1412  if (sspi_ret != SEC_E_OK) {
1413  av_freep(&c->send_buf);
1414  av_log(h, AV_LOG_ERROR, "Encrypting data failed\n");
1415  if (sspi_ret == SEC_E_INSUFFICIENT_MEMORY)
1416  return AVERROR(ENOMEM);
1417  return AVERROR(EIO);
1418  }
1419 
1420  c->send_buf_size = outbuf[0].cbBuffer + outbuf[1].cbBuffer + outbuf[2].cbBuffer;
1421  c->send_buf_offset = 0;
1422 
1424  if (ret == AVERROR(EAGAIN)) {
1425  /* We always need to signal that we consumed all (encrypted) data since schannel must not
1426  be fed the same data again. Sending will then be completed next call to this function,
1427  and EAGAIN returned until all remaining buffer is sent. */
1428  return outbuf[1].cbBuffer;
1429  } else if (ret < 0) {
1430  return ret;
1431  }
1432 
1433  return outbuf[1].cbBuffer;
1434 }
1435 
1437 {
1438  TLSContext *c = h->priv_data;
1439  TLSShared *s = &c->tls_shared;
1440  return ffurl_get_file_handle(s->is_dtls ? s->udp : s->tcp);
1441 }
1442 
1444 {
1445  TLSContext *c = h->priv_data;
1446  TLSShared *s = &c->tls_shared;
1447  return ffurl_get_short_seek(s->is_dtls ? s->udp : s->tcp);
1448 }
1449 
1450 #define OFFSET(x) offsetof(TLSContext, x)
1451 static const AVOption options[] = {
1452  TLS_COMMON_OPTIONS(TLSContext, tls_shared),
1453  { "cert_store_subject", "Load certificate (and associated key) from users keystore by subject",
1454  OFFSET(cert_store_subject), AV_OPT_TYPE_STRING, .flags = TLS_OPTFL },
1455  { "cert_store_name", "Name of the specific cert store to search in (for cert_store_subject)",
1456  OFFSET(cert_store_name), AV_OPT_TYPE_STRING, { .str = "MY" }, .flags = TLS_OPTFL },
1457  { NULL }
1458 };
1459 
1460 #if CONFIG_TLS_PROTOCOL
1461 static const AVClass tls_class = {
1462  .class_name = "tls",
1463  .item_name = av_default_item_name,
1464  .option = options,
1465  .version = LIBAVUTIL_VERSION_INT,
1466 };
1467 
1468 const URLProtocol ff_tls_protocol = {
1469  .name = "tls",
1470  .url_open2 = tls_open,
1471  .url_read = tls_read,
1472  .url_write = tls_write,
1473  .url_close = tls_close,
1474  .url_get_file_handle = tls_get_file_handle,
1475  .url_get_short_seek = tls_get_short_seek,
1476  .priv_data_size = sizeof(TLSContext),
1478  .priv_data_class = &tls_class,
1479 };
1480 #endif
1481 
1482 #if CONFIG_DTLS_PROTOCOL
1483 static const AVClass dtls_class = {
1484  .class_name = "dtls",
1485  .item_name = av_default_item_name,
1486  .option = options,
1487  .version = LIBAVUTIL_VERSION_INT,
1488 };
1489 
1490 const URLProtocol ff_dtls_protocol = {
1491  .name = "dtls",
1492  .url_open2 = dtls_open,
1493  .url_handshake = tls_handshake,
1494  .url_close = tls_close,
1495  .url_read = tls_read,
1496  .url_write = tls_write,
1497  .url_get_file_handle = tls_get_file_handle,
1498  .url_get_short_seek = tls_get_short_seek,
1499  .priv_data_size = sizeof(TLSContext),
1501  .priv_data_class = &dtls_class,
1502 };
1503 #endif
flags
const SwsFlags flags[]
Definition: swscale.c:61
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:216
TLSContext
Definition: tls_gnutls.c:44
read_data
static int read_data(void *opaque, uint8_t *buf, int buf_size)
Definition: dashdec.c:1781
av_bprint_is_complete
static int av_bprint_is_complete(const AVBPrint *buf)
Test if the print buffer is complete (not truncated).
Definition: bprint.h:218
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
URL_PROTOCOL_FLAG_NETWORK
#define URL_PROTOCOL_FLAG_NETWORK
Definition: url.h:33
av_bprint_init
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition: bprint.c:69
TLSContext::cert_store_name
char * cert_store_name
Definition: tls_schannel.c:594
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_schannel.c:566
TLSContext::context_flags
ULONG context_flags
Definition: tls_schannel.c:604
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:57
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_schannel.c:373
tls_server_handshake
static int tls_server_handshake(URLContext *h)
Definition: tls_schannel.c:1062
TLSContext::request_flags
ULONG request_flags
Definition: tls_schannel.c:603
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
SCHANNEL_FREE_BUFFER_SIZE
#define SCHANNEL_FREE_BUFFER_SIZE
Definition: tls_schannel.c:41
cleanup
static av_cold void cleanup(FlashSV2Context *s)
Definition: flashsv2enc.c:130
TLSContext::have_context
int have_context
Definition: tls_schannel.c:600
AVOption
AVOption.
Definition: opt.h:429
data
const char data[16]
Definition: mxf.c:149
tls_class
static const AVClass tls_class
Definition: tls_gnutls.c:293
options
static const AVOption options[]
Definition: tls_schannel.c:1451
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:226
AVDictionary
Definition: dict.c:32
AVERROR_UNKNOWN
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition: error.h:73
hash
uint8_t hash[HASH_SIZE]
Definition: movenc.c:58
URLProtocol
Definition: url.h:51
os_support.h
TLSContext::dec_buf
uint8_t * dec_buf
Definition: tls_schannel.c:610
TLSContext::cred_handle
CredHandle cred_handle
Definition: tls_schannel.c:596
sockaddr_storage
Definition: network.h:111
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:31
tls_write
static int tls_write(URLContext *h, const uint8_t *buf, int len)
Definition: tls_schannel.c:1368
TLS_COMMON_OPTIONS
#define TLS_COMMON_OPTIONS(pstruct, options_field)
Definition: tls.h:84
av_bprint_init_for_buffer
void av_bprint_init_for_buffer(AVBPrint *buf, char *buffer, unsigned size)
Init a print buffer using a pre-existing buffer.
Definition: bprint.c:85
fail
#define fail()
Definition: checkasm.h:199
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
tls_open
static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
Definition: tls_schannel.c:1113
type
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf type
Definition: writing_filters.txt:86
ff_dtls_protocol
const URLProtocol ff_dtls_protocol
Definition: tls_openssl.c:1000
TLSContext::sspi_close_notify
int sspi_close_notify
Definition: tls_schannel.c:622
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
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
init_sec_buffer_desc
static void init_sec_buffer_desc(SecBufferDesc *desc, SecBuffer *buffers, unsigned long buffer_count)
Definition: tls_schannel.c:692
s
#define s(width, name)
Definition: cbs_vp9.c:198
TLSContext::dec_buf_offset
int dec_buf_offset
Definition: tls_schannel.c:612
TLSContext::cert_store_subject
char * cert_store_subject
Definition: tls_schannel.c:593
TLS_OPTFL
#define TLS_OPTFL
Definition: tls.h:68
URLContext::flags
int flags
Definition: url.h:40
OFFSET
#define OFFSET(x)
Definition: tls_schannel.c:1450
tls_read
static int tls_read(URLContext *h, uint8_t *buf, int len)
Definition: tls_schannel.c:1214
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:231
key
const char * key
Definition: hwcontext_opencl.c:189
TLSContext::send_buf_size
int send_buf_size
Definition: tls_schannel.c:615
TLSContext::enc_buf_offset
int enc_buf_offset
Definition: tls_schannel.c:608
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:471
internal.h
tls_handshake
static int tls_handshake(URLContext *h)
Definition: tls_schannel.c:1079
SECBUFFER_ALERT
#define SECBUFFER_ALERT
Definition: tls_schannel.c:45
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:76
NULL
#define NULL
Definition: coverity.c:32
tls_shutdown_client
static int tls_shutdown_client(URLContext *h)
Definition: tls_schannel.c:729
ff_tls_set_external_socket
int ff_tls_set_external_socket(URLContext *h, URLContext *sock)
Definition: tls_schannel.c:625
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:509
init_sec_buffer
static void init_sec_buffer(SecBuffer *buffer, unsigned long type, void *data, unsigned long size)
Definition: tls_schannel.c:684
options
Definition: swscale.c:43
der_to_fingerprint
static int der_to_fingerprint(const char *data, size_t len, char **fingerprint)
Definition: tls_schannel.c:127
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
tls_close
static int tls_close(URLContext *h)
Definition: tls_schannel.c:790
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:235
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:87
size
int size
Definition: twinvq_data.h:10344
av_reallocp
int av_reallocp(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory through a pointer to a pointer.
Definition: mem.c:188
TLSContext::tls_shared
TLSShared tls_shared
Definition: tls_gnutls.c:46
URLProtocol::name
const char * name
Definition: url.h:52
tls_load_key_cert
static int tls_load_key_cert(char *key_url, char *cert_url, NCRYPT_KEY_HANDLE *key, PCCERT_CONTEXT *crtctx)
Definition: tls_schannel.c:534
TLSContext::send_buf
char * send_buf
Definition: tls_schannel.c:614
tls_process_send_buffer
static int tls_process_send_buffer(URLContext *h)
Definition: tls_schannel.c:700
header
static const uint8_t header[24]
Definition: sdr2.c:68
AVERROR_EXTERNAL
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:59
pem_to_der
static int pem_to_der(const char *pem, char **buf, int *out_len)
Definition: tls_schannel.c:104
tls_export_key_cert
static int tls_export_key_cert(NCRYPT_KEY_HANDLE key, PCCERT_CONTEXT crtctx, char *key_buf, size_t key_sz, char *cert_buf, size_t cert_sz, char **fingerprint)
Definition: tls_schannel.c:327
tls_cert_from_store
static int tls_cert_from_store(void *logctx, const char *cert_store_name, const char *cert_subj, PCCERT_CONTEXT *crtctx)
Definition: tls_schannel.c:508
TLSContext::enc_buf_size
int enc_buf_size
Definition: tls_schannel.c:607
URLContext
Definition: url.h:35
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
TLSContext::send_buf_offset
int send_buf_offset
Definition: tls_schannel.c:616
TLSContext::ctxt_timestamp
TimeStamp ctxt_timestamp
Definition: tls_schannel.c:601
TLSContext::connected
int connected
Definition: tls_schannel.c:620
TLSContext::ctxt_handle
CtxtHandle ctxt_handle
Definition: tls_schannel.c:599
tls_client_handshake
static int tls_client_handshake(URLContext *h)
Definition: tls_schannel.c:1015
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
TLSContext::cred_timestamp
TimeStamp cred_timestamp
Definition: tls_schannel.c:597
url.h
len
int len
Definition: vorbis_enc_data.h:426
TLSContext::sizes
SecPkgContext_StreamSizes sizes
Definition: tls_schannel.c:618
FF_NCRYPT_TEMP_KEY_NAME
#define FF_NCRYPT_TEMP_KEY_NAME
Definition: tls_schannel.c:61
der_to_pem
static int der_to_pem(const char *data, size_t len, const char *header, char *buf, size_t bufsize)
Definition: tls_schannel.c:63
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
tls_import_key_cert
static int tls_import_key_cert(char *key_buf, char *cert_buf, NCRYPT_KEY_HANDLE *key, PCCERT_CONTEXT *crtctx)
Definition: tls_schannel.c:396
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
SCHANNEL_INITIAL_BUFFER_SIZE
#define SCHANNEL_INITIAL_BUFFER_SIZE
Definition: tls_schannel.c:40
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
avformat.h
av_bprintf
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition: bprint.c:122
ff_dtls_export_materials
int ff_dtls_export_materials(URLContext *h, char *dtls_srtp_materials, size_t materials_sz)
Definition: tls_schannel.c:638
network.h
TLSContext::enc_buf
uint8_t * enc_buf
Definition: tls_schannel.c:606
tls.h
buffer
the frame and frame reference mechanism is intended to as much as expensive copies of that data while still allowing the filters to produce correct results The data is stored in buffers represented by AVFrame structures Several references can point to the same frame buffer
Definition: filter_design.txt:49
L
#define L(x)
Definition: vpx_arith.h:36
ff_tls_protocol
const URLProtocol ff_tls_protocol
Definition: tls_gnutls.c:300
desc
const char * desc
Definition: libsvtav1.c:79
tls_get_file_handle
static int tls_get_file_handle(URLContext *h)
Definition: tls_schannel.c:1436
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
av_free
#define av_free(p)
Definition: tableprint_vlc.h:34
AVIO_FLAG_NONBLOCK
#define AVIO_FLAG_NONBLOCK
Use non-blocking mode.
Definition: avio.h:636
TLSContext::connection_closed
int connection_closed
Definition: tls_schannel.c:621
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
TLSContext::dec_buf_size
int dec_buf_size
Definition: tls_schannel.c:611
tls_gen_self_signed
static int tls_gen_self_signed(NCRYPT_KEY_HANDLE *key, PCCERT_CONTEXT *crtctx)
Definition: tls_schannel.c:148
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
tls_handshake_loop
static int tls_handshake_loop(URLContext *h, int initial)
Definition: tls_schannel.c:819
h
h
Definition: vp9dsp_template.c:2070
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
Definition: opt.h:276
dtls_class
static const AVClass dtls_class
Definition: tls_openssl.c:993
ffurl_get_file_handle
int ffurl_get_file_handle(URLContext *h)
Return the file descriptor associated with this URL.
Definition: avio.c:815
tls_get_short_seek
static int tls_get_short_seek(URLContext *h)
Definition: tls_schannel.c:1443
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