FFmpeg
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
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 
685 {
686  TLSContext *c = h->priv_data;
687  return c->tls_shared.state;
688 }
689 
690 static void init_sec_buffer(SecBuffer *buffer, unsigned long type,
691  void *data, unsigned long size)
692 {
693  buffer->cbBuffer = size;
694  buffer->BufferType = type;
695  buffer->pvBuffer = data;
696 }
697 
698 static void init_sec_buffer_desc(SecBufferDesc *desc, SecBuffer *buffers,
699  unsigned long buffer_count)
700 {
701  desc->ulVersion = SECBUFFER_VERSION;
702  desc->pBuffers = buffers;
703  desc->cBuffers = buffer_count;
704 }
705 
707 {
708  TLSContext *c = h->priv_data;
709  TLSShared *s = &c->tls_shared;
710  URLContext *uc = s->is_dtls ? s->udp : s->tcp;
711  int ret;
712 
713  if (!c->send_buf)
714  return 0;
715 
716  ret = ffurl_write(uc, c->send_buf + c->send_buf_offset, c->send_buf_size - c->send_buf_offset);
717  if (ret == AVERROR(EAGAIN)) {
718  return AVERROR(EAGAIN);
719  } else if (ret < 0) {
720  av_log(h, AV_LOG_ERROR, "Writing encrypted data to socket failed\n");
721  return AVERROR(EIO);
722  }
723 
724  c->send_buf_offset += ret;
725 
726  if (c->send_buf_offset < c->send_buf_size)
727  return AVERROR(EAGAIN);
728 
729  av_freep(&c->send_buf);
730  c->send_buf_size = c->send_buf_offset = 0;
731 
732  return 0;
733 }
734 
736 {
737  TLSContext *c = h->priv_data;
738  TLSShared *s = &c->tls_shared;
739  URLContext *uc = s->is_dtls ? s->udp : s->tcp;
740  int ret;
741 
742  if (c->connected) {
743  SecBufferDesc BuffDesc;
744  SecBuffer Buffer;
745  SECURITY_STATUS sspi_ret;
746  SecBuffer outbuf;
747  SecBufferDesc outbuf_desc;
748 
749  DWORD dwshut = SCHANNEL_SHUTDOWN;
750  init_sec_buffer(&Buffer, SECBUFFER_TOKEN, &dwshut, sizeof(dwshut));
751  init_sec_buffer_desc(&BuffDesc, &Buffer, 1);
752 
753  uc->flags &= ~AVIO_FLAG_NONBLOCK;
755  if (ret < 0)
756  return ret;
757 
758  sspi_ret = ApplyControlToken(&c->ctxt_handle, &BuffDesc);
759  if (sspi_ret != SEC_E_OK)
760  av_log(h, AV_LOG_ERROR, "ApplyControlToken failed\n");
761 
762  init_sec_buffer(&outbuf, SECBUFFER_TOKEN, NULL, 0);
763  init_sec_buffer_desc(&outbuf_desc, &outbuf, 1);
764 
765  do {
766  if (s->listen)
767  sspi_ret = AcceptSecurityContext(&c->cred_handle, &c->ctxt_handle, NULL, c->request_flags, 0,
768  &c->ctxt_handle, &outbuf_desc, &c->context_flags,
769  &c->ctxt_timestamp);
770  else
771  sspi_ret = InitializeSecurityContext(&c->cred_handle, &c->ctxt_handle, s->host,
772  c->request_flags, 0, 0, NULL, 0, &c->ctxt_handle,
773  &outbuf_desc, &c->context_flags, &c->ctxt_timestamp);
774 
775  if (outbuf.pvBuffer) {
776  if (outbuf.cbBuffer > 0) {
777  ret = ffurl_write(uc, outbuf.pvBuffer, outbuf.cbBuffer);
778  if (ret < 0 || ret != outbuf.cbBuffer)
779  av_log(h, AV_LOG_ERROR, "Failed to send close message\n");
780  }
781  FreeContextBuffer(outbuf.pvBuffer);
782  }
783  } while(
784 #ifdef SEC_I_MESSAGE_FRAGMENT
785  sspi_ret == SEC_I_MESSAGE_FRAGMENT ||
786 #endif
787  sspi_ret == SEC_I_CONTINUE_NEEDED);
788 
789  av_log(h, AV_LOG_DEBUG, "Close session result: 0x%lx\n", sspi_ret);
790 
791  c->connected = 0;
792  }
793  return 0;
794 }
795 
796 static int tls_close(URLContext *h)
797 {
798  TLSContext *c = h->priv_data;
799  TLSShared *s = &c->tls_shared;
800 
802 
803  DeleteSecurityContext(&c->ctxt_handle);
804  FreeCredentialsHandle(&c->cred_handle);
805 
806  av_freep(&c->enc_buf);
807  c->enc_buf_size = c->enc_buf_offset = 0;
808 
809  av_freep(&c->dec_buf);
810  c->dec_buf_size = c->dec_buf_offset = 0;
811 
812  av_freep(&c->send_buf);
813  c->send_buf_size = c->send_buf_offset = 0;
814 
815  if (s->is_dtls) {
816  if (!s->external_sock)
817  ffurl_closep(&c->tls_shared.udp);
818  } else {
819  ffurl_closep(&c->tls_shared.tcp);
820  }
821 
822  return 0;
823 }
824 
825 static int tls_handshake_loop(URLContext *h, int initial)
826 {
827  TLSContext *c = h->priv_data;
828  TLSShared *s = &c->tls_shared;
829  URLContext *uc = s->is_dtls ? s->udp : s->tcp;
830  SECURITY_STATUS sspi_ret;
831  SecBuffer outbuf[3] = { 0 };
832  SecBufferDesc outbuf_desc;
833  SecBuffer inbuf[3];
834  SecBufferDesc inbuf_desc;
835  struct sockaddr_storage recv_addr = { 0 };
836  socklen_t recv_addr_len = 0;
837  int i, ret = 0, read_data = initial;
838 
839  if (c->enc_buf == NULL) {
840  c->enc_buf_offset = 0;
842  if (ret < 0)
843  goto fail;
844  c->enc_buf_size = SCHANNEL_INITIAL_BUFFER_SIZE;
845  }
846 
847  if (c->dec_buf == NULL) {
848  c->dec_buf_offset = 0;
850  if (ret < 0)
851  goto fail;
852  c->dec_buf_size = SCHANNEL_INITIAL_BUFFER_SIZE;
853  }
854 
855  uc->flags &= ~AVIO_FLAG_NONBLOCK;
856 
857  while (1) {
858  if (c->enc_buf_size - c->enc_buf_offset < SCHANNEL_FREE_BUFFER_SIZE) {
859  c->enc_buf_size = c->enc_buf_offset + SCHANNEL_FREE_BUFFER_SIZE;
860  ret = av_reallocp(&c->enc_buf, c->enc_buf_size);
861  if (ret < 0) {
862  c->enc_buf_size = c->enc_buf_offset = 0;
863  goto fail;
864  }
865  }
866 
867  if (read_data) {
868  ret = ffurl_read(uc, c->enc_buf + c->enc_buf_offset, c->enc_buf_size - c->enc_buf_offset);
869  if (ret < 0) {
870  av_log(h, AV_LOG_ERROR, "Failed to read handshake response\n");
871  goto fail;
872  }
873  c->enc_buf_offset += ret;
874  if (s->is_dtls && !recv_addr_len) {
875  ff_udp_get_last_recv_addr(uc, &recv_addr, &recv_addr_len);
876 
877  if (s->listen) {
878  ret = ff_udp_set_remote_addr(uc, (struct sockaddr *)&recv_addr, recv_addr_len, 1);
879  if (ret < 0) {
880  av_log(h, AV_LOG_ERROR, "Failed connecting udp context\n");
881  goto fail;
882  }
883  av_log(h, AV_LOG_TRACE, "Set UDP remote addr on UDP socket, now 'connected'\n");
884  }
885  }
886  }
887 
888  /* input buffers */
889  init_sec_buffer(&inbuf[0], SECBUFFER_TOKEN, av_malloc(c->enc_buf_offset), c->enc_buf_offset);
890  init_sec_buffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0);
891  if (s->listen && s->is_dtls) {
892  init_sec_buffer(&inbuf[2], SECBUFFER_EXTRA, &recv_addr, recv_addr_len);
893  init_sec_buffer_desc(&inbuf_desc, inbuf, 3);
894  } else {
895  init_sec_buffer_desc(&inbuf_desc, inbuf, 2);
896  }
897 
898  if (inbuf[0].pvBuffer == NULL) {
899  av_log(h, AV_LOG_ERROR, "Failed to allocate input buffer\n");
900  ret = AVERROR(ENOMEM);
901  goto fail;
902  }
903 
904  memcpy(inbuf[0].pvBuffer, c->enc_buf, c->enc_buf_offset);
905 
906  /* output buffers */
907  init_sec_buffer(&outbuf[0], SECBUFFER_TOKEN, NULL, 0);
908  init_sec_buffer(&outbuf[1], SECBUFFER_ALERT, NULL, 0);
909  init_sec_buffer(&outbuf[2], SECBUFFER_EMPTY, NULL, 0);
910  init_sec_buffer_desc(&outbuf_desc, outbuf, 3);
911 
912  if (s->listen)
913  sspi_ret = AcceptSecurityContext(&c->cred_handle, c->have_context ? &c->ctxt_handle : NULL, &inbuf_desc,
914  c->request_flags, 0, &c->ctxt_handle, &outbuf_desc,
915  &c->context_flags, &c->ctxt_timestamp);
916  else
917  sspi_ret = InitializeSecurityContext(&c->cred_handle, c->have_context ? &c->ctxt_handle : NULL,
918  s->host, c->request_flags, 0, 0, &inbuf_desc, 0, &c->ctxt_handle,
919  &outbuf_desc, &c->context_flags, &c->ctxt_timestamp);
920  av_freep(&inbuf[0].pvBuffer);
921 
922  av_log(h, AV_LOG_TRACE, "Handshake res with %d bytes of data: 0x%lx\n", c->enc_buf_offset, sspi_ret);
923 
924  if (sspi_ret == SEC_E_INCOMPLETE_MESSAGE) {
925  av_log(h, AV_LOG_TRACE, "Received incomplete handshake, need more data\n");
926  read_data = 1;
927  continue;
928  }
929 
930  c->have_context = 1;
931 
932  /* remote requests a client certificate - attempt to continue without one anyway */
933  if (sspi_ret == SEC_I_INCOMPLETE_CREDENTIALS &&
934  !(c->request_flags & ISC_REQ_USE_SUPPLIED_CREDS)) {
935  av_log(h, AV_LOG_VERBOSE, "Client certificate has been requested, ignoring\n");
936  c->request_flags |= ISC_REQ_USE_SUPPLIED_CREDS;
937  read_data = 0;
938  continue;
939  }
940 
941  /* continue handshake */
942  if (sspi_ret == SEC_I_CONTINUE_NEEDED ||
943 #ifdef SEC_I_MESSAGE_FRAGMENT
944  sspi_ret == SEC_I_MESSAGE_FRAGMENT ||
945 #endif
946  sspi_ret == SEC_E_OK) {
947  for (i = 0; i < 3; i++) {
948  if (outbuf[i].BufferType == SECBUFFER_TOKEN && outbuf[i].cbBuffer > 0) {
949  ret = ffurl_write(uc, outbuf[i].pvBuffer, outbuf[i].cbBuffer);
950  if (ret < 0 || ret != outbuf[i].cbBuffer) {
951  av_log(h, AV_LOG_VERBOSE, "Failed to send handshake data\n");
952  ret = AVERROR(EIO);
953  goto fail;
954  }
955  }
956 
957  if (outbuf[i].pvBuffer != NULL) {
958  FreeContextBuffer(outbuf[i].pvBuffer);
959  outbuf[i].pvBuffer = NULL;
960  }
961  }
962  } else {
963  if (sspi_ret == SEC_E_WRONG_PRINCIPAL)
964  av_log(h, AV_LOG_ERROR, "SNI or certificate check failed\n");
965  else
966  av_log(h, AV_LOG_ERROR, "Creating security context failed (0x%lx)\n", sspi_ret);
968  goto fail;
969  }
970 
971 #ifdef SEC_I_MESSAGE_FRAGMENT
972  if (sspi_ret == SEC_I_MESSAGE_FRAGMENT) {
973  av_log(h, AV_LOG_TRACE, "Writing fragmented output message part\n");
974  read_data = 0;
975  continue;
976  }
977 #endif
978 
979  if (inbuf[1].BufferType == SECBUFFER_EXTRA && inbuf[1].cbBuffer > 0) {
980  if (c->enc_buf_offset > inbuf[1].cbBuffer) {
981  memmove(c->enc_buf, (c->enc_buf + c->enc_buf_offset) - inbuf[1].cbBuffer,
982  inbuf[1].cbBuffer);
983  c->enc_buf_offset = inbuf[1].cbBuffer;
984  if (sspi_ret == SEC_I_CONTINUE_NEEDED) {
985  av_log(h, AV_LOG_TRACE, "Sent reply, handshake continues. %d extra bytes\n", (int)inbuf[1].cbBuffer);
986  read_data = 0;
987  continue;
988  }
989  }
990  } else {
991  c->enc_buf_offset = 0;
992  }
993 
994  if (sspi_ret == SEC_I_CONTINUE_NEEDED) {
995  av_log(h, AV_LOG_TRACE, "Handshake continues\n");
996  read_data = 1;
997  continue;
998  }
999 
1000  break;
1001  }
1002 
1003  av_log(h, AV_LOG_TRACE, "Handshake completed\n");
1004 
1005  return 0;
1006 
1007 fail:
1008  /* free any remaining output data */
1009  for (i = 0; i < 3; i++) {
1010  if (outbuf[i].pvBuffer != NULL) {
1011  FreeContextBuffer(outbuf[i].pvBuffer);
1012  outbuf[i].pvBuffer = NULL;
1013  }
1014  }
1015 
1016  av_log(h, AV_LOG_TRACE, "Handshake failed\n");
1017 
1018  return ret;
1019 }
1020 
1022 {
1023  TLSContext *c = h->priv_data;
1024  TLSShared *s = &c->tls_shared;
1025  URLContext *uc = s->is_dtls ? s->udp : s->tcp;
1026  SecBuffer outbuf;
1027  SecBufferDesc outbuf_desc;
1028  SECURITY_STATUS sspi_ret;
1029  int ret;
1030 
1031  init_sec_buffer(&outbuf, SECBUFFER_EMPTY, NULL, 0);
1032  init_sec_buffer_desc(&outbuf_desc, &outbuf, 1);
1033 
1034  c->request_flags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT |
1035  ISC_REQ_CONFIDENTIALITY | ISC_REQ_ALLOCATE_MEMORY;
1036  if (s->is_dtls)
1037  c->request_flags |= ISC_REQ_DATAGRAM;
1038  else
1039  c->request_flags |= ISC_REQ_STREAM;
1040 
1041  sspi_ret = InitializeSecurityContext(&c->cred_handle, NULL, s->host, c->request_flags, 0, 0,
1042  NULL, 0, &c->ctxt_handle, &outbuf_desc, &c->context_flags,
1043  &c->ctxt_timestamp);
1044  if (sspi_ret != SEC_I_CONTINUE_NEEDED) {
1045  av_log(h, AV_LOG_ERROR, "Unable to create initial security context (0x%lx)\n", sspi_ret);
1046  ret = AVERROR_UNKNOWN;
1047  goto fail;
1048  }
1049 
1050  c->have_context = 1;
1051 
1052  uc->flags &= ~AVIO_FLAG_NONBLOCK;
1053  ret = ffurl_write(uc, outbuf.pvBuffer, outbuf.cbBuffer);
1054  FreeContextBuffer(outbuf.pvBuffer);
1055  if (ret < 0 || ret != outbuf.cbBuffer) {
1056  av_log(h, AV_LOG_ERROR, "Failed to send initial handshake data\n");
1057  ret = AVERROR(EIO);
1058  goto fail;
1059  }
1060 
1061  return tls_handshake_loop(h, 1);
1062 
1063 fail:
1064  DeleteSecurityContext(&c->ctxt_handle);
1065  return ret;
1066 }
1067 
1069 {
1070  TLSContext *c = h->priv_data;
1071  TLSShared *s = &c->tls_shared;
1072 
1073  c->request_flags = ASC_REQ_SEQUENCE_DETECT | ASC_REQ_REPLAY_DETECT |
1074  ASC_REQ_CONFIDENTIALITY | ASC_REQ_ALLOCATE_MEMORY;
1075  if (s->is_dtls)
1076  c->request_flags |= ASC_REQ_DATAGRAM;
1077  else
1078  c->request_flags |= ASC_REQ_STREAM;
1079 
1080  c->have_context = 0;
1081 
1082  return tls_handshake_loop(h, 1);
1083 }
1084 
1086 {
1087  TLSContext *c = h->priv_data;
1088  TLSShared *s = &c->tls_shared;
1089  SECURITY_STATUS sspi_ret;
1090  int ret = 0;
1091 
1092  if (s->listen)
1094  else
1096 
1097  if (ret < 0)
1098  goto fail;
1099 
1100 #if CONFIG_DTLS_PROTOCOL
1101  if (s->is_dtls && s->mtu > 0) {
1102  ULONG mtu = s->mtu;
1103  sspi_ret = SetContextAttributes(&c->ctxt_handle, SECPKG_ATTR_DTLS_MTU, &mtu, sizeof(mtu));
1104  if (sspi_ret != SEC_E_OK) {
1105  av_log(h, AV_LOG_ERROR, "Failed setting DTLS MTU to %d.\n", s->mtu);
1106  ret = AVERROR(EINVAL);
1107  goto fail;
1108  }
1109  av_log(h, AV_LOG_VERBOSE, "Set DTLS MTU to %d\n", s->mtu);
1110  }
1111 #endif
1112 
1113  c->connected = 1;
1114  s->state = DTLS_STATE_FINISHED;
1115 
1116 fail:
1117  return ret;
1118 }
1119 
1120 static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
1121 {
1122  TLSContext *c = h->priv_data;
1123  TLSShared *s = &c->tls_shared;
1124  SECURITY_STATUS sspi_ret;
1125  SCHANNEL_CRED schannel_cred = { 0 };
1126  PCCERT_CONTEXT crtctx = NULL;
1127  NCRYPT_KEY_HANDLE key = 0;
1128  int ret = 0;
1129 
1130  if (!s->external_sock) {
1131  if ((ret = ff_tls_open_underlying(s, h, uri, options)) < 0)
1132  goto fail;
1133  }
1134 
1135  /* SChannel Options */
1136  schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
1137 
1138  if (s->listen) {
1139  if (c->cert_store_name && c->cert_store_subject) {
1140  ret = tls_cert_from_store(h, c->cert_store_name, c->cert_store_subject, &crtctx);
1141  } else if (s->key_buf && s->cert_buf) {
1142  ret = tls_import_key_cert(s->key_buf, s->cert_buf, &key, &crtctx);
1143  } else if (s->key_file && s->cert_file) {
1144  ret = tls_load_key_cert(s->key_file, s->cert_file, &key, &crtctx);
1145  } else {
1146  av_log(h, AV_LOG_VERBOSE, "No server certificate provided, using self-signed\n");
1147  ret = tls_gen_self_signed(&key, &crtctx);
1148  }
1149 
1150  if (ret < 0)
1151  goto fail;
1152 
1153  schannel_cred.cCreds = 1;
1154  schannel_cred.paCred = &crtctx;
1155 
1156  schannel_cred.dwFlags = SCH_CRED_NO_SYSTEM_MAPPER | SCH_CRED_MANUAL_CRED_VALIDATION;
1157 
1158 #if CONFIG_DTLS_PROTOCOL
1159  if (s->is_dtls)
1160  schannel_cred.grbitEnabledProtocols = SP_PROT_DTLS1_X_SERVER;
1161 #endif
1162  } else {
1163  if (s->verify)
1164  schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION |
1165  SCH_CRED_REVOCATION_CHECK_CHAIN;
1166  else
1167  schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION |
1168  SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
1169  SCH_CRED_IGNORE_REVOCATION_OFFLINE;
1170 
1171 #if CONFIG_DTLS_PROTOCOL
1172  if (s->is_dtls)
1173  schannel_cred.grbitEnabledProtocols = SP_PROT_DTLS1_X_CLIENT;
1174 #endif
1175  }
1176 
1177  /* Get credential handle */
1178  sspi_ret = AcquireCredentialsHandle(NULL, (TCHAR *)UNISP_NAME,
1179  s->listen ? SECPKG_CRED_INBOUND : SECPKG_CRED_OUTBOUND,
1180  NULL, &schannel_cred, NULL, NULL, &c->cred_handle,
1181  &c->cred_timestamp);
1182  if (sspi_ret != SEC_E_OK) {
1183  av_log(h, AV_LOG_ERROR, "Unable to acquire security credentials (0x%lx)\n", sspi_ret);
1184  ret = AVERROR_UNKNOWN;
1185  goto fail;
1186  }
1187 
1188  if (!s->external_sock) {
1189  ret = tls_handshake(h);
1190  if (ret < 0)
1191  goto fail;
1192  }
1193 
1194  goto end;
1195 
1196 fail:
1197  tls_close(h);
1198 
1199 end:
1200  if (crtctx)
1201  CertFreeCertificateContext(crtctx);
1202  if (key)
1203  if (NCryptDeleteKey(key, NCRYPT_SILENT_FLAG) != ERROR_SUCCESS)
1204  NCryptFreeObject(key);
1205 
1206  return ret;
1207 }
1208 
1209 #if CONFIG_DTLS_PROTOCOL
1210 static int dtls_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
1211 {
1212  TLSContext *c = h->priv_data;
1213  TLSShared *s = &c->tls_shared;
1214 
1215  s->is_dtls = 1;
1216 
1217  return tls_open(h, uri, flags, options);
1218 }
1219 #endif
1220 
1221 static int tls_read(URLContext *h, uint8_t *buf, int len)
1222 {
1223  TLSContext *c = h->priv_data;
1224  TLSShared *s = &c->tls_shared;
1225  URLContext *uc = s->is_dtls ? s->udp : s->tcp;
1226  SECURITY_STATUS sspi_ret = SEC_E_OK;
1227  SecBuffer inbuf[4];
1228  SecBufferDesc inbuf_desc;
1229  int size, ret = 0;
1230  int min_enc_buf_size = len + SCHANNEL_FREE_BUFFER_SIZE;
1231 
1232  /* If we have some left-over data from previous network activity,
1233  * return it first in case it is enough. It may contain
1234  * data that is required to know whether this connection
1235  * is still required or not, esp. in case of HTTP keep-alive
1236  * connections. */
1237  if (c->dec_buf_offset > 0)
1238  goto cleanup;
1239 
1240  if (c->sspi_close_notify)
1241  goto cleanup;
1242 
1243  if (!c->connection_closed) {
1244  size = c->enc_buf_size - c->enc_buf_offset;
1245  if (size < SCHANNEL_FREE_BUFFER_SIZE || c->enc_buf_size < min_enc_buf_size) {
1246  c->enc_buf_size = c->enc_buf_offset + SCHANNEL_FREE_BUFFER_SIZE;
1247  if (c->enc_buf_size < min_enc_buf_size)
1248  c->enc_buf_size = min_enc_buf_size;
1249  ret = av_reallocp(&c->enc_buf, c->enc_buf_size);
1250  if (ret < 0) {
1251  c->enc_buf_size = c->enc_buf_offset = 0;
1252  return ret;
1253  }
1254  }
1255 
1256  uc->flags &= ~AVIO_FLAG_NONBLOCK;
1257  uc->flags |= h->flags & AVIO_FLAG_NONBLOCK;
1258 
1259  ret = ffurl_read(uc, c->enc_buf + c->enc_buf_offset,
1260  c->enc_buf_size - c->enc_buf_offset);
1261  if (ret == AVERROR_EOF) {
1262  c->connection_closed = 1;
1263  ret = 0;
1264  } else if (ret == AVERROR(EAGAIN)) {
1265  ret = 0;
1266  } else if (ret < 0) {
1267  av_log(h, AV_LOG_ERROR, "Unable to read from socket\n");
1268  return ret;
1269  }
1270 
1271  c->enc_buf_offset += ret;
1272  }
1273 
1274  while (c->enc_buf_offset > 0 && sspi_ret == SEC_E_OK) {
1275  /* input buffer */
1276  init_sec_buffer(&inbuf[0], SECBUFFER_DATA, c->enc_buf, c->enc_buf_offset);
1277 
1278  /* additional buffers for possible output */
1279  init_sec_buffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0);
1280  init_sec_buffer(&inbuf[2], SECBUFFER_EMPTY, NULL, 0);
1281  init_sec_buffer(&inbuf[3], SECBUFFER_EMPTY, NULL, 0);
1282  init_sec_buffer_desc(&inbuf_desc, inbuf, 4);
1283 
1284  sspi_ret = DecryptMessage(&c->ctxt_handle, &inbuf_desc, 0, NULL);
1285  if (sspi_ret == SEC_E_OK || sspi_ret == SEC_I_RENEGOTIATE ||
1286  sspi_ret == SEC_I_CONTEXT_EXPIRED) {
1287  /* handle decrypted data */
1288  if (inbuf[1].BufferType == SECBUFFER_DATA) {
1289  /* grow buffer if needed */
1290  size = inbuf[1].cbBuffer > SCHANNEL_FREE_BUFFER_SIZE ?
1291  inbuf[1].cbBuffer : SCHANNEL_FREE_BUFFER_SIZE;
1292  if (c->dec_buf_size - c->dec_buf_offset < size || c->dec_buf_size < len) {
1293  c->dec_buf_size = c->dec_buf_offset + size;
1294  if (c->dec_buf_size < len)
1295  c->dec_buf_size = len;
1296  ret = av_reallocp(&c->dec_buf, c->dec_buf_size);
1297  if (ret < 0) {
1298  c->dec_buf_size = c->dec_buf_offset = 0;
1299  return ret;
1300  }
1301  }
1302 
1303  /* copy decrypted data to buffer */
1304  size = inbuf[1].cbBuffer;
1305  if (size) {
1306  memcpy(c->dec_buf + c->dec_buf_offset, inbuf[1].pvBuffer, size);
1307  c->dec_buf_offset += size;
1308  }
1309  }
1310  if (inbuf[3].BufferType == SECBUFFER_EXTRA && inbuf[3].cbBuffer > 0) {
1311  if (c->enc_buf_offset > inbuf[3].cbBuffer) {
1312  memmove(c->enc_buf, (c->enc_buf + c->enc_buf_offset) - inbuf[3].cbBuffer,
1313  inbuf[3].cbBuffer);
1314  c->enc_buf_offset = inbuf[3].cbBuffer;
1315  }
1316  } else
1317  c->enc_buf_offset = 0;
1318 
1319  if (sspi_ret == SEC_I_RENEGOTIATE) {
1320  if (c->enc_buf_offset) {
1321  av_log(h, AV_LOG_ERROR, "Cannot renegotiate, encrypted data buffer not empty\n");
1322  ret = AVERROR_UNKNOWN;
1323  goto cleanup;
1324  }
1325 
1326  av_log(h, AV_LOG_VERBOSE, "Re-negotiating security context\n");
1327  ret = tls_handshake_loop(h, 0);
1328  if (ret < 0) {
1329  goto cleanup;
1330  }
1331  sspi_ret = SEC_E_OK;
1332 
1333  /* if somehow any send data was left, it is now invalid */
1334  av_freep(&c->send_buf);
1335  c->send_buf_size = c->send_buf_offset = 0;
1336 
1337  continue;
1338  } else if (sspi_ret == SEC_I_CONTEXT_EXPIRED) {
1339  c->sspi_close_notify = 1;
1340  if (!c->connection_closed) {
1341  c->connection_closed = 1;
1342  av_log(h, AV_LOG_VERBOSE, "Server closed the connection\n");
1343  }
1344  ret = 0;
1345  goto cleanup;
1346  }
1347  } else if (sspi_ret == SEC_E_INCOMPLETE_MESSAGE) {
1348  ret = AVERROR(EAGAIN);
1349  goto cleanup;
1350  } else {
1351  av_log(h, AV_LOG_ERROR, "Unable to decrypt message (error 0x%x)\n", (unsigned)sspi_ret);
1352  ret = AVERROR(EIO);
1353  goto cleanup;
1354  }
1355  }
1356 
1357  ret = 0;
1358 
1359 cleanup:
1360  size = FFMIN(len, c->dec_buf_offset);
1361  if (size) {
1362  memcpy(buf, c->dec_buf, size);
1363  memmove(c->dec_buf, c->dec_buf + size, c->dec_buf_offset - size);
1364  c->dec_buf_offset -= size;
1365 
1366  return size;
1367  }
1368 
1369  if (ret == 0 && !c->connection_closed)
1370  ret = AVERROR(EAGAIN);
1371 
1372  return ret < 0 ? ret : AVERROR_EOF;
1373 }
1374 
1375 static int tls_write(URLContext *h, const uint8_t *buf, int len)
1376 {
1377  TLSContext *c = h->priv_data;
1378  TLSShared *s = &c->tls_shared;
1379  URLContext *uc = s->is_dtls ? s->udp : s->tcp;
1380  SECURITY_STATUS sspi_ret;
1381  SecBuffer outbuf[4];
1382  SecBufferDesc outbuf_desc;
1383  int ret = 0;
1384 
1385  uc->flags &= ~AVIO_FLAG_NONBLOCK;
1386  uc->flags |= h->flags & AVIO_FLAG_NONBLOCK;
1387 
1389  if (ret < 0)
1390  return ret;
1391 
1392  if (c->sizes.cbMaximumMessage == 0) {
1393  sspi_ret = QueryContextAttributes(&c->ctxt_handle, SECPKG_ATTR_STREAM_SIZES, &c->sizes);
1394  if (sspi_ret != SEC_E_OK)
1395  return AVERROR_UNKNOWN;
1396  }
1397 
1398  /* limit how much data we can consume */
1399  len = FFMIN(len, c->sizes.cbMaximumMessage - c->sizes.cbHeader - c->sizes.cbTrailer);
1400 
1401  c->send_buf_size = c->sizes.cbHeader + len + c->sizes.cbTrailer;
1402  c->send_buf = av_malloc(c->send_buf_size);
1403  if (c->send_buf == NULL)
1404  return AVERROR(ENOMEM);
1405 
1406  init_sec_buffer(&outbuf[0], SECBUFFER_STREAM_HEADER,
1407  c->send_buf, c->sizes.cbHeader);
1408  init_sec_buffer(&outbuf[1], SECBUFFER_DATA,
1409  c->send_buf + c->sizes.cbHeader, len);
1410  init_sec_buffer(&outbuf[2], SECBUFFER_STREAM_TRAILER,
1411  c->send_buf + c->sizes.cbHeader + len,
1412  c->sizes.cbTrailer);
1413  init_sec_buffer(&outbuf[3], SECBUFFER_EMPTY, NULL, 0);
1414  init_sec_buffer_desc(&outbuf_desc, outbuf, 4);
1415 
1416  memcpy(outbuf[1].pvBuffer, buf, len);
1417 
1418  sspi_ret = EncryptMessage(&c->ctxt_handle, 0, &outbuf_desc, 0);
1419  if (sspi_ret != SEC_E_OK) {
1420  av_freep(&c->send_buf);
1421  av_log(h, AV_LOG_ERROR, "Encrypting data failed\n");
1422  if (sspi_ret == SEC_E_INSUFFICIENT_MEMORY)
1423  return AVERROR(ENOMEM);
1424  return AVERROR(EIO);
1425  }
1426 
1427  c->send_buf_size = outbuf[0].cbBuffer + outbuf[1].cbBuffer + outbuf[2].cbBuffer;
1428  c->send_buf_offset = 0;
1429 
1431  if (ret == AVERROR(EAGAIN)) {
1432  /* We always need to signal that we consumed all (encryped) data since schannel must not
1433  be fed the same data again. Sending will then be completed next call to this function,
1434  and EAGAIN returned until all remaining buffer is sent. */
1435  return outbuf[1].cbBuffer;
1436  } else if (ret < 0) {
1437  return ret;
1438  }
1439 
1440  return outbuf[1].cbBuffer;
1441 }
1442 
1444 {
1445  TLSContext *c = h->priv_data;
1446  TLSShared *s = &c->tls_shared;
1447  return ffurl_get_file_handle(s->is_dtls ? s->udp : s->tcp);
1448 }
1449 
1451 {
1452  TLSContext *c = h->priv_data;
1453  TLSShared *s = &c->tls_shared;
1454  return ffurl_get_short_seek(s->is_dtls ? s->udp : s->tcp);
1455 }
1456 
1457 #define OFFSET(x) offsetof(TLSContext, x)
1458 static const AVOption options[] = {
1459  TLS_COMMON_OPTIONS(TLSContext, tls_shared),
1460  { "cert_store_subject", "Load certificate (and associated key) from users keystore by subject",
1461  OFFSET(cert_store_subject), AV_OPT_TYPE_STRING, .flags = TLS_OPTFL },
1462  { "cert_store_name", "Name of the specific cert store to search in (for cert_store_subject)",
1463  OFFSET(cert_store_name), AV_OPT_TYPE_STRING, { .str = "MY" }, .flags = TLS_OPTFL },
1464  { NULL }
1465 };
1466 
1467 #if CONFIG_TLS_PROTOCOL
1468 static const AVClass tls_class = {
1469  .class_name = "tls",
1470  .item_name = av_default_item_name,
1471  .option = options,
1472  .version = LIBAVUTIL_VERSION_INT,
1473 };
1474 
1475 const URLProtocol ff_tls_protocol = {
1476  .name = "tls",
1477  .url_open2 = tls_open,
1478  .url_read = tls_read,
1479  .url_write = tls_write,
1480  .url_close = tls_close,
1481  .url_get_file_handle = tls_get_file_handle,
1482  .url_get_short_seek = tls_get_short_seek,
1483  .priv_data_size = sizeof(TLSContext),
1485  .priv_data_class = &tls_class,
1486 };
1487 #endif
1488 
1489 #if CONFIG_DTLS_PROTOCOL
1490 static const AVClass dtls_class = {
1491  .class_name = "dtls",
1492  .item_name = av_default_item_name,
1493  .option = options,
1494  .version = LIBAVUTIL_VERSION_INT,
1495 };
1496 
1497 const URLProtocol ff_dtls_protocol = {
1498  .name = "dtls",
1499  .url_open2 = dtls_open,
1500  .url_handshake = tls_handshake,
1501  .url_close = tls_close,
1502  .url_read = tls_read,
1503  .url_write = tls_write,
1504  .url_get_file_handle = tls_get_file_handle,
1505  .url_get_short_seek = tls_get_short_seek,
1506  .priv_data_size = sizeof(TLSContext),
1508  .priv_data_class = &dtls_class,
1509 };
1510 #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:1772
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:1068
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:1458
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:1375
TLS_COMMON_OPTIONS
#define TLS_COMMON_OPTIONS(pstruct, options_field)
Definition: tls.h:89
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:1120
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:1078
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:698
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:79
URLContext::flags
int flags
Definition: url.h:40
OFFSET
#define OFFSET(x)
Definition: tls_schannel.c:1457
tls_read
static int tls_read(URLContext *h, uint8_t *buf, int len)
Definition: tls_schannel.c:1221
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:1085
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:735
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:240
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:690
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:796
ff_url_read_all
int ff_url_read_all(const char *url, AVBPrint *bp)
Read all data from the given URL url and store it in the given buffer bp.
Definition: tls.c:150
av_bprint_finalize
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition: bprint.c:240
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:706
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:1021
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:99
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:1443
mem.h
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:47
av_free
#define av_free(p)
Definition: tableprint_vlc.h:34
ff_dtls_state
int ff_dtls_state(URLContext *h)
Definition: tls_schannel.c:684
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:825
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:1071
DTLS_STATE_FINISHED
@ DTLS_STATE_FINISHED
Definition: tls.h:40
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:1450
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