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