24 #include "config_components.h"
34 #define SECURITY_WIN32
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);
104 static 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;
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);
508 static 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;
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)
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);
631 c->tls_shared.udp = sock;
633 c->tls_shared.tcp = sock;
640 #if HAVE_SECPKGCONTEXT_KEYINGMATERIALINFO
643 SecPkgContext_KeyingMaterialInfo keying_info = { 0 };
644 SecPkgContext_KeyingMaterial keying_material = { 0 };
646 const char*
dst =
"EXTRACTOR-dtls_srtp";
647 SECURITY_STATUS sspi_ret;
649 if (!
c->have_context)
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;
658 sspi_ret = SetContextAttributes(&
c->ctxt_handle, SECPKG_ATTR_KEYING_MATERIAL_INFO, &keying_info,
sizeof(keying_info));
659 if (sspi_ret != SEC_E_OK) {
664 sspi_ret = QueryContextAttributes(&
c->ctxt_handle, SECPKG_ATTR_KEYING_MATERIAL, &keying_material);
665 if (sspi_ret != SEC_E_OK) {
670 memcpy(dtls_srtp_materials, keying_material.pbKeyingMaterial,
FFMIN(materials_sz, keying_material.cbKeyingMaterial));
671 FreeContextBuffer(keying_material.pbKeyingMaterial);
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);
687 return c->tls_shared.state;
699 unsigned long buffer_count)
701 desc->ulVersion = SECBUFFER_VERSION;
702 desc->pBuffers = buffers;
703 desc->cBuffers = buffer_count;
716 ret =
ffurl_write(uc,
c->send_buf +
c->send_buf_offset,
c->send_buf_size -
c->send_buf_offset);
719 }
else if (
ret < 0) {
724 c->send_buf_offset +=
ret;
726 if (
c->send_buf_offset <
c->send_buf_size)
730 c->send_buf_size =
c->send_buf_offset = 0;
743 SecBufferDesc BuffDesc;
745 SECURITY_STATUS sspi_ret;
747 SecBufferDesc outbuf_desc;
749 DWORD dwshut = SCHANNEL_SHUTDOWN;
758 sspi_ret = ApplyControlToken(&
c->ctxt_handle, &BuffDesc);
759 if (sspi_ret != SEC_E_OK)
767 sspi_ret = AcceptSecurityContext(&
c->cred_handle, &
c->ctxt_handle,
NULL,
c->request_flags, 0,
768 &
c->ctxt_handle, &outbuf_desc, &
c->context_flags,
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);
775 if (outbuf.pvBuffer) {
776 if (outbuf.cbBuffer > 0) {
778 if (
ret < 0 ||
ret != outbuf.cbBuffer)
781 FreeContextBuffer(outbuf.pvBuffer);
784 #ifdef SEC_I_MESSAGE_FRAGMENT
785 sspi_ret == SEC_I_MESSAGE_FRAGMENT ||
787 sspi_ret == SEC_I_CONTINUE_NEEDED);
803 DeleteSecurityContext(&
c->ctxt_handle);
804 FreeCredentialsHandle(&
c->cred_handle);
807 c->enc_buf_size =
c->enc_buf_offset = 0;
810 c->dec_buf_size =
c->dec_buf_offset = 0;
813 c->send_buf_size =
c->send_buf_offset = 0;
816 if (!
s->external_sock)
830 SECURITY_STATUS sspi_ret;
831 SecBuffer outbuf[3] = { 0 };
832 SecBufferDesc outbuf_desc;
834 SecBufferDesc inbuf_desc;
836 socklen_t recv_addr_len = 0;
839 if (
c->enc_buf ==
NULL) {
840 c->enc_buf_offset = 0;
847 if (
c->dec_buf ==
NULL) {
848 c->dec_buf_offset = 0;
862 c->enc_buf_size =
c->enc_buf_offset = 0;
868 ret =
ffurl_read(uc,
c->enc_buf +
c->enc_buf_offset,
c->enc_buf_size -
c->enc_buf_offset);
873 c->enc_buf_offset +=
ret;
874 if (
s->is_dtls && !recv_addr_len) {
891 if (
s->listen &&
s->is_dtls) {
892 init_sec_buffer(&inbuf[2], SECBUFFER_EXTRA, &recv_addr, recv_addr_len);
898 if (inbuf[0].pvBuffer ==
NULL) {
904 memcpy(inbuf[0].pvBuffer,
c->enc_buf,
c->enc_buf_offset);
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);
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);
922 av_log(
h,
AV_LOG_TRACE,
"Handshake res with %d bytes of data: 0x%lx\n",
c->enc_buf_offset, sspi_ret);
924 if (sspi_ret == SEC_E_INCOMPLETE_MESSAGE) {
933 if (sspi_ret == SEC_I_INCOMPLETE_CREDENTIALS &&
934 !(
c->request_flags & ISC_REQ_USE_SUPPLIED_CREDS)) {
936 c->request_flags |= ISC_REQ_USE_SUPPLIED_CREDS;
942 if (sspi_ret == SEC_I_CONTINUE_NEEDED ||
943 #ifdef SEC_I_MESSAGE_FRAGMENT
944 sspi_ret == SEC_I_MESSAGE_FRAGMENT ||
946 sspi_ret == SEC_E_OK) {
947 for (
i = 0;
i < 3;
i++) {
948 if (outbuf[
i].BufferType == SECBUFFER_TOKEN && outbuf[
i].cbBuffer > 0) {
950 if (
ret < 0 ||
ret != outbuf[
i].cbBuffer) {
957 if (outbuf[
i].pvBuffer !=
NULL) {
958 FreeContextBuffer(outbuf[
i].pvBuffer);
959 outbuf[
i].pvBuffer =
NULL;
963 if (sspi_ret == SEC_E_WRONG_PRINCIPAL)
971 #ifdef SEC_I_MESSAGE_FRAGMENT
972 if (sspi_ret == SEC_I_MESSAGE_FRAGMENT) {
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,
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);
991 c->enc_buf_offset = 0;
994 if (sspi_ret == SEC_I_CONTINUE_NEEDED) {
1009 for (
i = 0;
i < 3;
i++) {
1010 if (outbuf[
i].pvBuffer !=
NULL) {
1011 FreeContextBuffer(outbuf[
i].pvBuffer);
1012 outbuf[
i].pvBuffer =
NULL;
1027 SecBufferDesc outbuf_desc;
1028 SECURITY_STATUS sspi_ret;
1034 c->request_flags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT |
1035 ISC_REQ_CONFIDENTIALITY | ISC_REQ_ALLOCATE_MEMORY;
1037 c->request_flags |= ISC_REQ_DATAGRAM;
1039 c->request_flags |= ISC_REQ_STREAM;
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) {
1050 c->have_context = 1;
1054 FreeContextBuffer(outbuf.pvBuffer);
1055 if (
ret < 0 ||
ret != outbuf.cbBuffer) {
1064 DeleteSecurityContext(&
c->ctxt_handle);
1073 c->request_flags = ASC_REQ_SEQUENCE_DETECT | ASC_REQ_REPLAY_DETECT |
1074 ASC_REQ_CONFIDENTIALITY | ASC_REQ_ALLOCATE_MEMORY;
1076 c->request_flags |= ASC_REQ_DATAGRAM;
1078 c->request_flags |= ASC_REQ_STREAM;
1080 c->have_context = 0;
1089 SECURITY_STATUS sspi_ret;
1100 #if CONFIG_DTLS_PROTOCOL
1101 if (
s->is_dtls &&
s->mtu > 0) {
1103 sspi_ret = SetContextAttributes(&
c->ctxt_handle, SECPKG_ATTR_DTLS_MTU, &mtu,
sizeof(mtu));
1104 if (sspi_ret != SEC_E_OK) {
1124 SECURITY_STATUS sspi_ret;
1125 SCHANNEL_CRED schannel_cred = { 0 };
1126 PCCERT_CONTEXT crtctx =
NULL;
1127 NCRYPT_KEY_HANDLE
key = 0;
1130 if (!
s->external_sock) {
1136 schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
1139 if (
c->cert_store_name &&
c->cert_store_subject) {
1141 }
else if (
s->key_buf &&
s->cert_buf) {
1143 }
else if (
s->key_file &&
s->cert_file) {
1153 schannel_cred.cCreds = 1;
1154 schannel_cred.paCred = &crtctx;
1156 schannel_cred.dwFlags = SCH_CRED_NO_SYSTEM_MAPPER | SCH_CRED_MANUAL_CRED_VALIDATION;
1158 #if CONFIG_DTLS_PROTOCOL
1160 schannel_cred.grbitEnabledProtocols = SP_PROT_DTLS1_X_SERVER;
1164 schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION |
1165 SCH_CRED_REVOCATION_CHECK_CHAIN;
1167 schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION |
1168 SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
1169 SCH_CRED_IGNORE_REVOCATION_OFFLINE;
1171 #if CONFIG_DTLS_PROTOCOL
1173 schannel_cred.grbitEnabledProtocols = SP_PROT_DTLS1_X_CLIENT;
1178 sspi_ret = AcquireCredentialsHandle(
NULL, (TCHAR *)UNISP_NAME,
1179 s->listen ? SECPKG_CRED_INBOUND : SECPKG_CRED_OUTBOUND,
1181 &
c->cred_timestamp);
1182 if (sspi_ret != SEC_E_OK) {
1188 if (!
s->external_sock) {
1201 CertFreeCertificateContext(crtctx);
1203 if (NCryptDeleteKey(
key, NCRYPT_SILENT_FLAG) != ERROR_SUCCESS)
1204 NCryptFreeObject(
key);
1209 #if CONFIG_DTLS_PROTOCOL
1226 SECURITY_STATUS sspi_ret = SEC_E_OK;
1228 SecBufferDesc inbuf_desc;
1237 if (
c->dec_buf_offset > 0)
1240 if (
c->sspi_close_notify)
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) {
1247 if (
c->enc_buf_size < min_enc_buf_size)
1248 c->enc_buf_size = min_enc_buf_size;
1251 c->enc_buf_size =
c->enc_buf_offset = 0;
1260 c->enc_buf_size -
c->enc_buf_offset);
1262 c->connection_closed = 1;
1266 }
else if (
ret < 0) {
1271 c->enc_buf_offset +=
ret;
1274 while (
c->enc_buf_offset > 0 && sspi_ret == SEC_E_OK) {
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) {
1288 if (inbuf[1].BufferType == SECBUFFER_DATA) {
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;
1298 c->dec_buf_size =
c->dec_buf_offset = 0;
1304 size = inbuf[1].cbBuffer;
1306 memcpy(
c->dec_buf +
c->dec_buf_offset, inbuf[1].pvBuffer,
size);
1307 c->dec_buf_offset +=
size;
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,
1314 c->enc_buf_offset = inbuf[3].cbBuffer;
1317 c->enc_buf_offset = 0;
1319 if (sspi_ret == SEC_I_RENEGOTIATE) {
1320 if (
c->enc_buf_offset) {
1331 sspi_ret = SEC_E_OK;
1335 c->send_buf_size =
c->send_buf_offset = 0;
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;
1347 }
else if (sspi_ret == SEC_E_INCOMPLETE_MESSAGE) {
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;
1369 if (
ret == 0 && !
c->connection_closed)
1380 SECURITY_STATUS sspi_ret;
1381 SecBuffer outbuf[4];
1382 SecBufferDesc outbuf_desc;
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)
1399 len =
FFMIN(
len,
c->sizes.cbMaximumMessage -
c->sizes.cbHeader -
c->sizes.cbTrailer);
1401 c->send_buf_size =
c->sizes.cbHeader +
len +
c->sizes.cbTrailer;
1403 if (
c->send_buf ==
NULL)
1407 c->send_buf,
c->sizes.cbHeader);
1409 c->send_buf +
c->sizes.cbHeader,
len);
1411 c->send_buf +
c->sizes.cbHeader +
len,
1412 c->sizes.cbTrailer);
1416 memcpy(outbuf[1].pvBuffer, buf,
len);
1418 sspi_ret = EncryptMessage(&
c->ctxt_handle, 0, &outbuf_desc, 0);
1419 if (sspi_ret != SEC_E_OK) {
1422 if (sspi_ret == SEC_E_INSUFFICIENT_MEMORY)
1427 c->send_buf_size = outbuf[0].cbBuffer + outbuf[1].cbBuffer + outbuf[2].cbBuffer;
1428 c->send_buf_offset = 0;
1435 return outbuf[1].cbBuffer;
1436 }
else if (
ret < 0) {
1440 return outbuf[1].cbBuffer;
1457 #define OFFSET(x) offsetof(TLSContext, x)
1460 {
"cert_store_subject",
"Load certificate (and associated key) from users keystore by subject",
1462 {
"cert_store_name",
"Name of the specific cert store to search in (for cert_store_subject)",
1467 #if CONFIG_TLS_PROTOCOL
1489 #if CONFIG_DTLS_PROTOCOL
1499 .url_open2 = dtls_open,