24#include "config_components.h"
40#define SCHANNEL_INITIAL_BUFFER_SIZE 4096
41#define SCHANNEL_FREE_BUFFER_SIZE 1024
44#ifndef SECBUFFER_ALERT
45#define SECBUFFER_ALERT 17
61#define FF_NCRYPT_TEMP_KEY_NAME L"FFMPEG_TEMP_TLS_KEY"
65 const int line_length = 64;
71 if (!CryptBinaryToStringA(
data,
len, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF,
NULL, &base64len)) {
79 if (!CryptBinaryToStringA(
data,
len, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, base64, &base64len)) {
88 for (DWORD
i = 0;
i < base64len;
i += line_length) {
89 av_bprintf(&pem,
"%.*s\n", line_length, base64 +
i);
104static int pem_to_der(
const char *pem,
char **buf,
int *out_len)
108 if (!CryptStringToBinaryA(pem, 0, CRYPT_STRING_BASE64HEADER,
NULL, &derlen,
NULL,
NULL)) {
117 if (!CryptStringToBinaryA(pem, 0, CRYPT_STRING_BASE64HEADER, *buf, &derlen,
NULL,
NULL)) {
130 unsigned char hash[32];
131 DWORD hashsize =
sizeof(
hash);
133 if (!CryptHashCertificate2(BCRYPT_SHA256_ALGORITHM, 0,
NULL,
data,
len,
hash, &hashsize))
141 for (
int i = 0;
i < hashsize - 1;
i++)
150 NCRYPT_PROV_HANDLE provider = 0;
151 CERT_NAME_BLOB subject = { 0 };
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";
168 SECURITY_STATUS sspi_ret;
173 sspi_ret = NCryptOpenStorageProvider(&provider, MS_KEY_STORAGE_PROVIDER, 0);
174 if (sspi_ret != ERROR_SUCCESS) {
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) {
187 sspi_ret = NCryptSetProperty(*
key, NCRYPT_EXPORT_POLICY_PROPERTY, (PBYTE)&export_props,
sizeof(export_props), 0);
188 if (sspi_ret != ERROR_SUCCESS) {
194 sspi_ret = NCryptSetProperty(*
key, NCRYPT_KEY_USAGE_PROPERTY, (PBYTE)&usage_props,
sizeof(usage_props), 0);
195 if (sspi_ret != ERROR_SUCCESS) {
201 sspi_ret = NCryptFinalizeKey(*
key, 0);
202 if (sspi_ret != ERROR_SUCCESS) {
208 if (!CertStrToNameA(X509_ASN_ENCODING, subj_str, 0,
NULL,
NULL, &subject.cbData,
NULL))
215 subject.pbData =
av_malloc(subject.cbData);
216 if (!subject.pbData) {
221 if (!CertStrToNameA(X509_ASN_ENCODING, subj_str, 0,
NULL, subject.pbData, &subject.cbData,
NULL))
229 eku.cUsageIdentifier = 1;
230 eku.rgpszUsageIdentifier = (LPSTR*)ext_usages;
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)) {
239 ext[0].pszObjId = (LPSTR)szOID_ENHANCED_KEY_USAGE;
240 ext[0].fCritical = TRUE;
243 key_usage_blob.cbData =
sizeof(key_usage);
244 key_usage_blob.pbData = &key_usage;
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)) {
253 ext[1].pszObjId = (LPSTR)szOID_KEY_USAGE;
254 ext[1].fCritical = TRUE;
257 basic_constraints.fCA = FALSE;
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)) {
266 ext[2].pszObjId = (LPSTR)szOID_BASIC_CONSTRAINTS2;
267 ext[2].fCritical = TRUE;
270 san_entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
271 san_entry.pwszDNSName = (LPWSTR)
L"localhost";
273 san_info.cAltEntry = 1;
274 san_info.rgAltEntry = &san_entry;
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)) {
283 ext[3].pszObjId = (LPSTR)szOID_SUBJECT_ALT_NAME2;
284 ext[3].fCritical = TRUE;
287 exts.rgExtension = ext;
289 prov_info.pwszProvName = (LPWSTR)MS_KEY_STORAGE_PROVIDER;
291 prov_info.dwFlags = CERT_SET_KEY_CONTEXT_PROP_ID;
293 *crtctx = CertCreateSelfSignCertificate(*
key, &subject, 0, &prov_info, &sig_alg,
NULL,
NULL, &exts);
300 NCryptFreeObject(provider);
303 LocalFree(ext[
i].Value.pbData);
309 CertFreeCertificateContext(*crtctx);
311 if (NCryptDeleteKey(*
key, NCRYPT_SILENT_FLAG) != ERROR_SUCCESS)
312 NCryptFreeObject(*
key);
314 NCryptFreeObject(provider);
318 if (ext[
i].Value.pbData)
319 LocalFree(ext[
i].Value.pbData);
328 char *key_buf,
size_t key_sz,
char *cert_buf,
size_t cert_sz,
char **fingerprint)
333 SECURITY_STATUS sspi_ret;
336 sspi_ret = NCryptExportKey(
key, 0, NCRYPT_PKCS8_PRIVATE_KEY_BLOB,
NULL,
NULL, 0, &keysize, 0);
337 if (sspi_ret != ERROR_SUCCESS) {
349 sspi_ret = NCryptExportKey(
key, 0, NCRYPT_PKCS8_PRIVATE_KEY_BLOB,
NULL, keybuf, keysize, &keysize, 0);
350 if (sspi_ret != ERROR_SUCCESS) {
356 ret =
der_to_pem(keybuf, keysize,
"PRIVATE KEY", key_buf, key_sz);
360 ret =
der_to_pem(crtctx->pbCertEncoded, crtctx->cbCertEncoded,
"CERTIFICATE", cert_buf, cert_sz);
375 NCRYPT_KEY_HANDLE
key = 0;
376 PCCERT_CONTEXT crtctx =
NULL;
388 if (NCryptDeleteKey(
key, NCRYPT_SILENT_FLAG) != ERROR_SUCCESS)
389 NCryptFreeObject(
key);
391 CertFreeCertificateContext(crtctx);
398 NCRYPT_PROV_HANDLE provider = 0;
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 };
406 int key_der_len = 0, cert_der_len = 0;
407 char *key_der =
NULL, *cert_der =
NULL;
409 SECURITY_STATUS sspi_ret;
412 ret =
pem_to_der(key_buf, &key_der, &key_der_len);
416 ret =
pem_to_der(cert_buf, &cert_der, &cert_der_len);
420 sspi_ret = NCryptOpenStorageProvider(&provider, MS_KEY_STORAGE_PROVIDER, 0);
421 if (sspi_ret != ERROR_SUCCESS) {
427 buffer_desc.ulVersion = NCRYPTBUFFER_VERSION;
428 buffer_desc.cBuffers = 1;
429 buffer_desc.pBuffers = &
buffer;
431 buffer.BufferType = NCRYPTBUFFER_PKCS_KEY_NAME;
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) {
442 sspi_ret = NCryptSetProperty(*
key, NCRYPT_EXPORT_POLICY_PROPERTY, (PBYTE)&export_props,
sizeof(export_props), 0);
443 if (sspi_ret != ERROR_SUCCESS) {
449 sspi_ret = NCryptSetProperty(*
key, NCRYPT_KEY_USAGE_PROPERTY, (PBYTE)&usage_props,
sizeof(usage_props), 0);
450 if (sspi_ret != ERROR_SUCCESS) {
456 sspi_ret = NCryptFinalizeKey(*
key, 0);
457 if (sspi_ret != ERROR_SUCCESS) {
463 *crtctx = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, cert_der, cert_der_len);
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());
476 prov_info.pwszProvName = (LPWSTR)MS_KEY_STORAGE_PROVIDER;
478 prov_info.dwFlags = CERT_SET_KEY_CONTEXT_PROP_ID;
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());
490 if (NCryptDeleteKey(*
key, NCRYPT_SILENT_FLAG) != ERROR_SUCCESS)
491 NCryptFreeObject(*
key);
493 CertFreeCertificateContext(*crtctx);
504 NCryptFreeObject(provider);
508static int tls_cert_from_store(
void *logctx,
const char *cert_store_name,
const char *cert_subj, PCCERT_CONTEXT *crtctx)
510 HCERTSTORE cert_store =
NULL;
513 cert_store = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, 0, CERT_SYSTEM_STORE_CURRENT_USER, cert_store_name);
520 *crtctx = CertFindCertificateInStore(cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_SUBJECT_STR_A, cert_subj,
NULL);
529 CertCloseStore(cert_store, 0);
536 AVBPrint key_bp, cert_bp;
566int 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)
568 NCRYPT_KEY_HANDLE
key = 0;
569 PCCERT_CONTEXT crtctx =
NULL;
581 if (NCryptDeleteKey(
key, NCRYPT_SILENT_FLAG) != ERROR_SUCCESS)
582 NCryptFreeObject(
key);
584 CertFreeCertificateContext(crtctx);
632 c->tls_shared.udp = sock;
634 c->tls_shared.tcp = sock;
641#if HAVE_SECPKGCONTEXT_KEYINGMATERIALINFO
644 SecPkgContext_KeyingMaterialInfo keying_info = { 0 };
645 SecPkgContext_KeyingMaterial keying_material = { 0 };
647 const char*
dst =
"EXTRACTOR-dtls_srtp";
648 SECURITY_STATUS sspi_ret;
650 if (!
c->have_context)
653 keying_info.cbLabel = strlen(
dst) + 1;
654 keying_info.pszLabel = (LPSTR)
dst;
655 keying_info.cbContextValue = 0;
656 keying_info.pbContextValue =
NULL;
657 keying_info.cbKeyingMaterial = materials_sz;
659 sspi_ret = SetContextAttributes(&
c->ctxt_handle, SECPKG_ATTR_KEYING_MATERIAL_INFO, &keying_info,
sizeof(keying_info));
660 if (sspi_ret != SEC_E_OK) {
665 sspi_ret = QueryContextAttributes(&
c->ctxt_handle, SECPKG_ATTR_KEYING_MATERIAL, &keying_material);
666 if (sspi_ret != SEC_E_OK) {
671 memcpy(dtls_srtp_materials, keying_material.pbKeyingMaterial,
FFMIN(materials_sz, keying_material.cbKeyingMaterial));
672 FreeContextBuffer(keying_material.pbKeyingMaterial);
674 if (keying_material.cbKeyingMaterial > materials_sz) {
675 av_log(
h,
AV_LOG_WARNING,
"Keying material size mismatch: %ld > %zu\n", keying_material.cbKeyingMaterial, materials_sz);
694 unsigned long buffer_count)
696 desc->ulVersion = SECBUFFER_VERSION;
697 desc->pBuffers = buffers;
698 desc->cBuffers = buffer_count;
711 ret =
ffurl_write(uc,
c->send_buf +
c->send_buf_offset,
c->send_buf_size -
c->send_buf_offset);
714 }
else if (ret < 0) {
719 c->send_buf_offset += ret;
721 if (
c->send_buf_offset <
c->send_buf_size)
725 c->send_buf_size =
c->send_buf_offset = 0;
738 SecBufferDesc BuffDesc;
740 SECURITY_STATUS sspi_ret;
742 SecBufferDesc outbuf_desc;
744 DWORD dwshut = SCHANNEL_SHUTDOWN;
753 sspi_ret = ApplyControlToken(&
c->ctxt_handle, &BuffDesc);
754 if (sspi_ret != SEC_E_OK)
762 sspi_ret = AcceptSecurityContext(&
c->cred_handle, &
c->ctxt_handle,
NULL,
c->request_flags, 0,
763 &
c->ctxt_handle, &outbuf_desc, &
c->context_flags,
766 sspi_ret = InitializeSecurityContext(&
c->cred_handle, &
c->ctxt_handle,
s->host,
767 c->request_flags, 0, 0,
NULL, 0, &
c->ctxt_handle,
768 &outbuf_desc, &
c->context_flags, &
c->ctxt_timestamp);
770 if (outbuf.pvBuffer) {
771 if (outbuf.cbBuffer > 0) {
772 ret =
ffurl_write(uc, outbuf.pvBuffer, outbuf.cbBuffer);
773 if (ret < 0 || ret != outbuf.cbBuffer)
776 FreeContextBuffer(outbuf.pvBuffer);
779#ifdef SEC_I_MESSAGE_FRAGMENT
780 sspi_ret == SEC_I_MESSAGE_FRAGMENT ||
782 sspi_ret == SEC_I_CONTINUE_NEEDED);
798 DeleteSecurityContext(&
c->ctxt_handle);
799 FreeCredentialsHandle(&
c->cred_handle);
802 c->enc_buf_size =
c->enc_buf_offset = 0;
805 c->dec_buf_size =
c->dec_buf_offset = 0;
808 c->send_buf_size =
c->send_buf_offset = 0;
811 if (!
s->external_sock)
825 SECURITY_STATUS sspi_ret;
826 SecBuffer outbuf[3] = { 0 };
827 SecBufferDesc outbuf_desc;
829 SecBufferDesc inbuf_desc;
831 socklen_t recv_addr_len = 0;
834 if (
c->enc_buf ==
NULL) {
835 c->enc_buf_offset = 0;
842 if (
c->dec_buf ==
NULL) {
843 c->dec_buf_offset = 0;
857 c->enc_buf_size =
c->enc_buf_offset = 0;
863 ret =
ffurl_read(uc,
c->enc_buf +
c->enc_buf_offset,
c->enc_buf_size -
c->enc_buf_offset);
868 c->enc_buf_offset += ret;
869 if (
s->is_dtls && !recv_addr_len) {
886 if (
s->listen &&
s->is_dtls) {
887 init_sec_buffer(&inbuf[2], SECBUFFER_EXTRA, &recv_addr, recv_addr_len);
893 if (inbuf[0].pvBuffer ==
NULL) {
899 memcpy(inbuf[0].pvBuffer,
c->enc_buf,
c->enc_buf_offset);
908 sspi_ret = AcceptSecurityContext(&
c->cred_handle,
c->have_context ? &
c->ctxt_handle :
NULL, &inbuf_desc,
909 c->request_flags, 0, &
c->ctxt_handle, &outbuf_desc,
910 &
c->context_flags, &
c->ctxt_timestamp);
912 sspi_ret = InitializeSecurityContext(&
c->cred_handle,
c->have_context ? &
c->ctxt_handle :
NULL,
913 s->host,
c->request_flags, 0, 0, &inbuf_desc, 0, &
c->ctxt_handle,
914 &outbuf_desc, &
c->context_flags, &
c->ctxt_timestamp);
917 av_log(
h,
AV_LOG_TRACE,
"Handshake res with %d bytes of data: 0x%lx\n",
c->enc_buf_offset, sspi_ret);
919 if (sspi_ret == SEC_E_INCOMPLETE_MESSAGE) {
928 if (sspi_ret == SEC_I_INCOMPLETE_CREDENTIALS &&
929 !(
c->request_flags & ISC_REQ_USE_SUPPLIED_CREDS)) {
931 c->request_flags |= ISC_REQ_USE_SUPPLIED_CREDS;
937 if (sspi_ret == SEC_I_CONTINUE_NEEDED ||
938#ifdef SEC_I_MESSAGE_FRAGMENT
939 sspi_ret == SEC_I_MESSAGE_FRAGMENT ||
941 sspi_ret == SEC_E_OK) {
942 for (
i = 0;
i < 3;
i++) {
943 if (outbuf[
i].BufferType == SECBUFFER_TOKEN && outbuf[
i].cbBuffer > 0) {
944 ret =
ffurl_write(uc, outbuf[
i].pvBuffer, outbuf[
i].cbBuffer);
945 if (ret < 0 || ret != outbuf[
i].cbBuffer) {
952 if (outbuf[
i].pvBuffer !=
NULL) {
953 FreeContextBuffer(outbuf[
i].pvBuffer);
954 outbuf[
i].pvBuffer =
NULL;
958 if (sspi_ret == SEC_E_WRONG_PRINCIPAL)
966#ifdef SEC_I_MESSAGE_FRAGMENT
967 if (sspi_ret == SEC_I_MESSAGE_FRAGMENT) {
974 if (inbuf[1].BufferType == SECBUFFER_EXTRA && inbuf[1].cbBuffer > 0) {
975 if (
c->enc_buf_offset > inbuf[1].cbBuffer) {
976 memmove(
c->enc_buf, (
c->enc_buf +
c->enc_buf_offset) - inbuf[1].cbBuffer,
978 c->enc_buf_offset = inbuf[1].cbBuffer;
979 if (sspi_ret == SEC_I_CONTINUE_NEEDED) {
980 av_log(
h,
AV_LOG_TRACE,
"Sent reply, handshake continues. %d extra bytes\n", (
int)inbuf[1].cbBuffer);
986 c->enc_buf_offset = 0;
989 if (sspi_ret == SEC_I_CONTINUE_NEEDED) {
1004 for (
i = 0;
i < 3;
i++) {
1005 if (outbuf[
i].pvBuffer !=
NULL) {
1006 FreeContextBuffer(outbuf[
i].pvBuffer);
1007 outbuf[
i].pvBuffer =
NULL;
1022 SecBufferDesc outbuf_desc;
1023 SECURITY_STATUS sspi_ret;
1029 c->request_flags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT |
1030 ISC_REQ_CONFIDENTIALITY | ISC_REQ_ALLOCATE_MEMORY;
1032 c->request_flags |= ISC_REQ_DATAGRAM;
1034 c->request_flags |= ISC_REQ_STREAM;
1035 if (
c->have_private_cert)
1036 c->request_flags |= ISC_REQ_USE_SUPPLIED_CREDS;
1038 sspi_ret = InitializeSecurityContext(&
c->cred_handle,
NULL,
s->host,
c->request_flags, 0, 0,
1039 NULL, 0, &
c->ctxt_handle, &outbuf_desc, &
c->context_flags,
1040 &
c->ctxt_timestamp);
1041 if (sspi_ret != SEC_I_CONTINUE_NEEDED) {
1047 c->have_context = 1;
1050 ret =
ffurl_write(uc, outbuf.pvBuffer, outbuf.cbBuffer);
1051 FreeContextBuffer(outbuf.pvBuffer);
1052 if (ret < 0 || ret != outbuf.cbBuffer) {
1061 DeleteSecurityContext(&
c->ctxt_handle);
1070 c->request_flags = ASC_REQ_SEQUENCE_DETECT | ASC_REQ_REPLAY_DETECT |
1071 ASC_REQ_CONFIDENTIALITY | ASC_REQ_ALLOCATE_MEMORY;
1073 c->request_flags |= ASC_REQ_DATAGRAM;
1075 c->request_flags |= ASC_REQ_STREAM;
1077 c->have_context = 0;
1086 SECURITY_STATUS sspi_ret;
1097#if CONFIG_DTLS_PROTOCOL
1098 if (
s->is_dtls &&
s->mtu > 0) {
1100 sspi_ret = SetContextAttributes(&
c->ctxt_handle, SECPKG_ATTR_DTLS_MTU, &mtu,
sizeof(mtu));
1101 if (sspi_ret != SEC_E_OK) {
1120 SECURITY_STATUS sspi_ret;
1121 SCHANNEL_CRED schannel_cred = { 0 };
1122 PCCERT_CONTEXT crtctx =
NULL;
1123 NCRYPT_KEY_HANDLE
key = 0;
1126 if (!
s->external_sock) {
1132 schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
1134 if (
c->cert_store_name &&
c->cert_store_subject) {
1136 }
else if (
s->key_buf &&
s->cert_buf) {
1138 }
else if (
s->key_file &&
s->cert_file) {
1140 }
else if (!
s->listen && (
s->key_buf ||
s->cert_buf ||
s->key_file ||
s->cert_file)) {
1142 }
else if (
s->listen) {
1151 schannel_cred.cCreds = 1;
1152 schannel_cred.paCred = &crtctx;
1153 c->have_private_cert = 1;
1157 schannel_cred.dwFlags = SCH_CRED_NO_SYSTEM_MAPPER | SCH_CRED_MANUAL_CRED_VALIDATION;
1159#if CONFIG_DTLS_PROTOCOL
1161 schannel_cred.grbitEnabledProtocols = SP_PROT_DTLS1_X_SERVER;
1165 schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION |
1166 SCH_CRED_REVOCATION_CHECK_CHAIN;
1168 schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION |
1169 SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
1170 SCH_CRED_IGNORE_REVOCATION_OFFLINE;
1171 schannel_cred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS;
1173#if CONFIG_DTLS_PROTOCOL
1175 schannel_cred.grbitEnabledProtocols = SP_PROT_DTLS1_X_CLIENT;
1180 sspi_ret = AcquireCredentialsHandle(
NULL, (TCHAR *)UNISP_NAME,
1181 s->listen ? SECPKG_CRED_INBOUND : SECPKG_CRED_OUTBOUND,
1183 &
c->cred_timestamp);
1184 if (sspi_ret != SEC_E_OK) {
1190 if (!
s->external_sock) {
1203 CertFreeCertificateContext(crtctx);
1205 if (NCryptDeleteKey(
key, NCRYPT_SILENT_FLAG) != ERROR_SUCCESS)
1206 NCryptFreeObject(
key);
1211#if CONFIG_DTLS_PROTOCOL
1228 SECURITY_STATUS sspi_ret = SEC_E_OK;
1230 SecBufferDesc inbuf_desc;
1239 if (
c->dec_buf_offset > 0)
1242 if (
c->sspi_close_notify)
1245 if (!
c->connection_closed) {
1246 size =
c->enc_buf_size -
c->enc_buf_offset;
1249 if (
c->enc_buf_size < min_enc_buf_size)
1250 c->enc_buf_size = min_enc_buf_size;
1253 c->enc_buf_size =
c->enc_buf_offset = 0;
1262 c->enc_buf_size -
c->enc_buf_offset);
1264 c->connection_closed = 1;
1266 }
else if (ret ==
AVERROR(EAGAIN)) {
1268 }
else if (ret < 0) {
1273 c->enc_buf_offset += ret;
1276 while (
c->enc_buf_offset > 0 && sspi_ret == SEC_E_OK) {
1286 sspi_ret = DecryptMessage(&
c->ctxt_handle, &inbuf_desc, 0,
NULL);
1287 if (sspi_ret == SEC_E_OK || sspi_ret == SEC_I_RENEGOTIATE ||
1288 sspi_ret == SEC_I_CONTEXT_EXPIRED) {
1290 if (inbuf[1].BufferType == SECBUFFER_DATA) {
1294 if (
c->dec_buf_size -
c->dec_buf_offset <
size ||
c->dec_buf_size <
len) {
1295 c->dec_buf_size =
c->dec_buf_offset +
size;
1296 if (
c->dec_buf_size <
len)
1297 c->dec_buf_size =
len;
1300 c->dec_buf_size =
c->dec_buf_offset = 0;
1306 size = inbuf[1].cbBuffer;
1308 memcpy(
c->dec_buf +
c->dec_buf_offset, inbuf[1].pvBuffer,
size);
1309 c->dec_buf_offset +=
size;
1312 if (inbuf[3].BufferType == SECBUFFER_EXTRA && inbuf[3].cbBuffer > 0) {
1313 if (
c->enc_buf_offset > inbuf[3].cbBuffer) {
1314 memmove(
c->enc_buf, (
c->enc_buf +
c->enc_buf_offset) - inbuf[3].cbBuffer,
1316 c->enc_buf_offset = inbuf[3].cbBuffer;
1319 c->enc_buf_offset = 0;
1321 if (sspi_ret == SEC_I_RENEGOTIATE) {
1322 if (
c->enc_buf_offset) {
1333 sspi_ret = SEC_E_OK;
1337 c->send_buf_size =
c->send_buf_offset = 0;
1340 }
else if (sspi_ret == SEC_I_CONTEXT_EXPIRED) {
1341 c->sspi_close_notify = 1;
1342 if (!
c->connection_closed) {
1343 c->connection_closed = 1;
1349 }
else if (sspi_ret == SEC_E_INCOMPLETE_MESSAGE) {
1364 memcpy(buf,
c->dec_buf,
size);
1365 memmove(
c->dec_buf,
c->dec_buf +
size,
c->dec_buf_offset -
size);
1366 c->dec_buf_offset -=
size;
1371 if (ret == 0 && !
c->connection_closed)
1382 SECURITY_STATUS sspi_ret;
1383 SecBuffer outbuf[4];
1384 SecBufferDesc outbuf_desc;
1394 if (
c->sizes.cbMaximumMessage == 0) {
1395 sspi_ret = QueryContextAttributes(&
c->ctxt_handle, SECPKG_ATTR_STREAM_SIZES, &
c->sizes);
1396 if (sspi_ret != SEC_E_OK)
1401 len =
FFMIN(
len,
c->sizes.cbMaximumMessage -
c->sizes.cbHeader -
c->sizes.cbTrailer);
1403 c->send_buf_size =
c->sizes.cbHeader +
len +
c->sizes.cbTrailer;
1405 if (
c->send_buf ==
NULL)
1409 c->send_buf,
c->sizes.cbHeader);
1411 c->send_buf +
c->sizes.cbHeader,
len);
1413 c->send_buf +
c->sizes.cbHeader +
len,
1414 c->sizes.cbTrailer);
1418 memcpy(outbuf[1].pvBuffer, buf,
len);
1420 sspi_ret = EncryptMessage(&
c->ctxt_handle, 0, &outbuf_desc, 0);
1421 if (sspi_ret != SEC_E_OK) {
1424 if (sspi_ret == SEC_E_INSUFFICIENT_MEMORY)
1429 c->send_buf_size = outbuf[0].cbBuffer + outbuf[1].cbBuffer + outbuf[2].cbBuffer;
1430 c->send_buf_offset = 0;
1437 return outbuf[1].cbBuffer;
1438 }
else if (ret < 0) {
1442 return outbuf[1].cbBuffer;
1459#define OFFSET(x) offsetof(TLSContext, x)
1462 {
"cert_store_subject",
"Load certificate (and associated key) from users keystore by subject",
1464 {
"cert_store_name",
"Name of the specific cert store to search in (for cert_store_subject)",
1469#if CONFIG_TLS_PROTOCOL
1471 .class_name =
"tls",
1491#if CONFIG_DTLS_PROTOCOL
1493 .class_name =
"dtls",
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
static uint8_t hash[HASH_SIZE]
int ffurl_closep(URLContext **hh)
Close the resource accessed by the URLContext h, and free the memory used by it.
int ffurl_get_short_seek(void *urlcontext)
Return the current short seek threshold value for this URL.
int ffurl_get_file_handle(URLContext *h)
Return the file descriptor associated with this URL.
#define AVIO_FLAG_NONBLOCK
Use non-blocking mode.
void av_bprintf(AVBPrint *buf, const char *fmt,...)
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
#define flags(name, subs,...)
#define i(width, name, range_min, range_max)
static int read_data(void *opaque, uint8_t *buf, int buf_size)
static av_cold void cleanup(FlashSV2Context *s)
@ 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...
static int av_bprint_is_complete(const AVBPrint *buf)
Test if the print buffer is complete (not truncated).
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
void av_bprint_init_for_buffer(AVBPrint *buf, char *buffer, unsigned size)
Init a print buffer using a pre-existing buffer.
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
#define AVERROR_EXTERNAL
Generic error in an external library.
#define AVERROR_EOF
End of file.
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
#define AV_LOG_WARNING
Something somehow does not look correct.
#define AV_LOG_VERBOSE
Detailed information.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
const char * av_default_item_name(void *ptr)
Return the context name.
int av_reallocp(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory through a pointer to a pointer.
#define LIBAVUTIL_VERSION_INT
Memory handling functions.
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.
void ff_udp_get_last_recv_addr(URLContext *h, struct sockaddr_storage *addr, socklen_t *addr_len)
miscellaneous OS support macros and functions.
const URLProtocol ff_dtls_protocol
const URLProtocol ff_tls_protocol
static const uint8_t header[24]
#define FF_ARRAY_ELEMS(a)
Describe the class of an AVClass context structure.
char * cert_store_subject
SecPkgContext_StreamSizes sizes
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.
int ff_tls_open_underlying(TLSShared *c, URLContext *parent, const char *uri, AVDictionary **options)
#define MAX_CERTIFICATE_SIZE
Maximum size limit of a certificate and private key size.
#define TLS_COMMON_OPTIONS(pstruct, options_field)
static int tls_handshake(URLContext *h)
static int tls_close(URLContext *h)
static const AVClass tls_class
static int tls_read(URLContext *h, uint8_t *buf, int size)
static int dtls_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
static int tls_get_short_seek(URLContext *h)
static int tls_write(URLContext *h, const uint8_t *buf, int size)
static const AVClass dtls_class
static int tls_get_file_handle(URLContext *h)
#define FF_NCRYPT_TEMP_KEY_NAME
static int tls_handshake(URLContext *h)
static int tls_close(URLContext *h)
static int tls_load_key_cert(char *key_url, char *cert_url, NCRYPT_KEY_HANDLE *key, PCCERT_CONTEXT *crtctx)
static void init_sec_buffer_desc(SecBufferDesc *desc, SecBuffer *buffers, unsigned long buffer_count)
static int tls_handshake_loop(URLContext *h, int initial)
static int pem_to_der(const char *pem, char **buf, int *out_len)
static int tls_server_handshake(URLContext *h)
static int tls_read(URLContext *h, uint8_t *buf, int len)
int ff_ssl_gen_key_cert(char *key_buf, size_t key_sz, char *cert_buf, size_t cert_sz, char **fingerprint)
static int tls_shutdown_client(URLContext *h)
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)
static int tls_write(URLContext *h, const uint8_t *buf, int len)
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)
static int der_to_fingerprint(const char *data, size_t len, char **fingerprint)
static int tls_client_handshake(URLContext *h)
int ff_dtls_export_materials(URLContext *h, char *dtls_srtp_materials, size_t materials_sz)
static int tls_cert_from_store(void *logctx, const char *cert_store_name, const char *cert_subj, PCCERT_CONTEXT *crtctx)
static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
static void init_sec_buffer(SecBuffer *buffer, unsigned long type, void *data, unsigned long size)
#define SCHANNEL_INITIAL_BUFFER_SIZE
static int tls_get_short_seek(URLContext *h)
static int tls_import_key_cert(char *key_buf, char *cert_buf, NCRYPT_KEY_HANDLE *key, PCCERT_CONTEXT *crtctx)
static int der_to_pem(const char *data, size_t len, const char *header, char *buf, size_t bufsize)
static int tls_get_file_handle(URLContext *h)
static int tls_process_send_buffer(URLContext *h)
int ff_tls_set_external_socket(URLContext *h, URLContext *sock)
static int tls_gen_self_signed(NCRYPT_KEY_HANDLE *key, PCCERT_CONTEXT *crtctx)
#define SCHANNEL_FREE_BUFFER_SIZE
unbuffered private I/O API
static int ffurl_write(URLContext *h, const uint8_t *buf, int size)
Write size bytes from buf to the resource accessed by h.
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.
#define URL_PROTOCOL_FLAG_NETWORK