31 #define SECURITY_WIN32
37 #define SCHANNEL_INITIAL_BUFFER_SIZE 4096
38 #define SCHANNEL_FREE_BUFFER_SIZE 1024
41 #ifndef SECBUFFER_ALERT
42 #define SECBUFFER_ALERT 17
58 #define FF_NCRYPT_TEMP_KEY_NAME L"FFMPEG_TEMP_TLS_KEY"
62 const int line_length = 64;
68 if (!CryptBinaryToStringA(
data,
len, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF,
NULL, &base64len)) {
76 if (!CryptBinaryToStringA(
data,
len, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, base64, &base64len)) {
85 for (DWORD
i = 0;
i < base64len;
i += line_length) {
86 av_bprintf(&pem,
"%.*s\n", line_length, base64 +
i);
101 static int pem_to_der(
const char *pem,
char **buf,
int *out_len)
105 if (!CryptStringToBinaryA(pem, 0, CRYPT_STRING_BASE64HEADER,
NULL, &derlen,
NULL,
NULL)) {
114 if (!CryptStringToBinaryA(pem, 0, CRYPT_STRING_BASE64HEADER, *buf, &derlen,
NULL,
NULL)) {
127 unsigned char hash[32];
128 DWORD hashsize =
sizeof(
hash);
130 if (!CryptHashCertificate2(BCRYPT_SHA256_ALGORITHM, 0,
NULL,
data,
len,
hash, &hashsize))
138 for (
int i = 0;
i < hashsize - 1;
i++)
147 NCRYPT_PROV_HANDLE provider = 0;
148 CERT_NAME_BLOB subject = { 0 };
150 DWORD export_props = NCRYPT_ALLOW_EXPORT_FLAG | NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG;
151 DWORD usage_props = NCRYPT_ALLOW_ALL_USAGES;
152 LPCSTR ext_usages[] = { szOID_PKIX_KP_SERVER_AUTH };
153 BYTE key_usage = CERT_KEY_ENCIPHERMENT_KEY_USAGE | CERT_DIGITAL_SIGNATURE_KEY_USAGE;
154 CRYPT_BIT_BLOB key_usage_blob = { 0 };
155 CERT_ENHKEY_USAGE eku = { 0 };
156 CERT_BASIC_CONSTRAINTS2_INFO basic_constraints = { 0 };
157 CERT_ALT_NAME_ENTRY san_entry = { 0 };
158 CERT_ALT_NAME_INFO san_info = { 0 };
159 CERT_EXTENSION ext[4] = { 0 };
160 CERT_EXTENSIONS exts = { 0 };
161 CRYPT_ALGORITHM_IDENTIFIER sig_alg = { (LPSTR)szOID_ECDSA_SHA256 };
162 CRYPT_KEY_PROV_INFO prov_info = { 0 };
163 const char *subj_str =
"CN=lavf";
165 SECURITY_STATUS sspi_ret;
170 sspi_ret = NCryptOpenStorageProvider(&provider, MS_KEY_STORAGE_PROVIDER, 0);
171 if (sspi_ret != ERROR_SUCCESS) {
177 sspi_ret = NCryptCreatePersistedKey(provider,
key, BCRYPT_ECDSA_P256_ALGORITHM,
FF_NCRYPT_TEMP_KEY_NAME, 0, NCRYPT_OVERWRITE_KEY_FLAG);
178 if (sspi_ret != ERROR_SUCCESS) {
184 sspi_ret = NCryptSetProperty(*
key, NCRYPT_EXPORT_POLICY_PROPERTY, (PBYTE)&export_props,
sizeof(export_props), 0);
185 if (sspi_ret != ERROR_SUCCESS) {
191 sspi_ret = NCryptSetProperty(*
key, NCRYPT_KEY_USAGE_PROPERTY, (PBYTE)&usage_props,
sizeof(usage_props), 0);
192 if (sspi_ret != ERROR_SUCCESS) {
198 sspi_ret = NCryptFinalizeKey(*
key, 0);
199 if (sspi_ret != ERROR_SUCCESS) {
205 if (!CertStrToNameA(X509_ASN_ENCODING, subj_str, 0,
NULL,
NULL, &subject.cbData,
NULL))
212 subject.pbData =
av_malloc(subject.cbData);
213 if (!subject.pbData) {
218 if (!CertStrToNameA(X509_ASN_ENCODING, subj_str, 0,
NULL, subject.pbData, &subject.cbData,
NULL))
226 eku.cUsageIdentifier = 1;
227 eku.rgpszUsageIdentifier = (LPSTR*)ext_usages;
229 if (!CryptEncodeObjectEx(X509_ASN_ENCODING, X509_ENHANCED_KEY_USAGE, &eku,
230 CRYPT_ENCODE_ALLOC_FLAG,
NULL, &ext[0].Value.pbData, &ext[0].Value.cbData)) {
236 ext[0].pszObjId = (LPSTR)szOID_ENHANCED_KEY_USAGE;
237 ext[0].fCritical = TRUE;
240 key_usage_blob.cbData =
sizeof(key_usage);
241 key_usage_blob.pbData = &key_usage;
243 if (!CryptEncodeObjectEx(X509_ASN_ENCODING, X509_BITS, &key_usage_blob,
244 CRYPT_ENCODE_ALLOC_FLAG,
NULL, &ext[1].Value.pbData, &ext[1].Value.cbData)) {
250 ext[1].pszObjId = (LPSTR)szOID_KEY_USAGE;
251 ext[1].fCritical = TRUE;
254 basic_constraints.fCA = FALSE;
256 if (!CryptEncodeObjectEx(X509_ASN_ENCODING, X509_BASIC_CONSTRAINTS2, &basic_constraints,
257 CRYPT_ENCODE_ALLOC_FLAG,
NULL, &ext[2].Value.pbData, &ext[2].Value.cbData)) {
263 ext[2].pszObjId = (LPSTR)szOID_BASIC_CONSTRAINTS2;
264 ext[2].fCritical = TRUE;
267 san_entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
268 san_entry.pwszDNSName = (LPWSTR)
L"localhost";
270 san_info.cAltEntry = 1;
271 san_info.rgAltEntry = &san_entry;
273 if (!CryptEncodeObjectEx(X509_ASN_ENCODING, X509_ALTERNATE_NAME, &san_info,
274 CRYPT_ENCODE_ALLOC_FLAG,
NULL, &ext[3].Value.pbData, &ext[3].Value.cbData)) {
280 ext[3].pszObjId = (LPSTR)szOID_SUBJECT_ALT_NAME2;
281 ext[3].fCritical = TRUE;
284 exts.rgExtension = ext;
286 prov_info.pwszProvName = (LPWSTR)MS_KEY_STORAGE_PROVIDER;
288 prov_info.dwFlags = CERT_SET_KEY_CONTEXT_PROP_ID;
290 *crtctx = CertCreateSelfSignCertificate(*
key, &subject, 0, &prov_info, &sig_alg,
NULL,
NULL, &exts);
297 NCryptFreeObject(provider);
300 LocalFree(ext[
i].Value.pbData);
306 CertFreeCertificateContext(*crtctx);
308 if (NCryptDeleteKey(*
key, NCRYPT_SILENT_FLAG) != ERROR_SUCCESS)
309 NCryptFreeObject(*
key);
311 NCryptFreeObject(provider);
315 if (ext[
i].Value.pbData)
316 LocalFree(ext[
i].Value.pbData);
325 char *key_buf,
size_t key_sz,
char *cert_buf,
size_t cert_sz,
char **fingerprint)
330 SECURITY_STATUS sspi_ret;
333 sspi_ret = NCryptExportKey(
key, 0, NCRYPT_PKCS8_PRIVATE_KEY_BLOB,
NULL,
NULL, 0, &keysize, 0);
334 if (sspi_ret != ERROR_SUCCESS) {
346 sspi_ret = NCryptExportKey(
key, 0, NCRYPT_PKCS8_PRIVATE_KEY_BLOB,
NULL, keybuf, keysize, &keysize, 0);
347 if (sspi_ret != ERROR_SUCCESS) {
353 ret =
der_to_pem(keybuf, keysize,
"PRIVATE KEY", key_buf, key_sz);
357 ret =
der_to_pem(crtctx->pbCertEncoded, crtctx->cbCertEncoded,
"CERTIFICATE", cert_buf, cert_sz);
372 NCRYPT_KEY_HANDLE
key = 0;
373 PCCERT_CONTEXT crtctx =
NULL;
385 if (NCryptDeleteKey(
key, NCRYPT_SILENT_FLAG) != ERROR_SUCCESS)
386 NCryptFreeObject(
key);
388 CertFreeCertificateContext(crtctx);
395 NCRYPT_PROV_HANDLE provider = 0;
397 DWORD export_props = NCRYPT_ALLOW_EXPORT_FLAG | NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG;
398 DWORD usage_props = NCRYPT_ALLOW_ALL_USAGES;
399 NCryptBufferDesc buffer_desc = { 0 };
400 NCryptBuffer
buffer = { 0 };
401 CRYPT_KEY_PROV_INFO prov_info = { 0 };
403 int key_der_len = 0, cert_der_len = 0;
404 char *key_der =
NULL, *cert_der =
NULL;
406 SECURITY_STATUS sspi_ret;
417 sspi_ret = NCryptOpenStorageProvider(&provider, MS_KEY_STORAGE_PROVIDER, 0);
418 if (sspi_ret != ERROR_SUCCESS) {
424 buffer_desc.ulVersion = NCRYPTBUFFER_VERSION;
425 buffer_desc.cBuffers = 1;
426 buffer_desc.pBuffers = &
buffer;
428 buffer.BufferType = NCRYPTBUFFER_PKCS_KEY_NAME;
432 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);
433 if (sspi_ret != ERROR_SUCCESS) {
439 sspi_ret = NCryptSetProperty(*
key, NCRYPT_EXPORT_POLICY_PROPERTY, (PBYTE)&export_props,
sizeof(export_props), 0);
440 if (sspi_ret != ERROR_SUCCESS) {
446 sspi_ret = NCryptSetProperty(*
key, NCRYPT_KEY_USAGE_PROPERTY, (PBYTE)&usage_props,
sizeof(usage_props), 0);
447 if (sspi_ret != ERROR_SUCCESS) {
453 sspi_ret = NCryptFinalizeKey(*
key, 0);
454 if (sspi_ret != ERROR_SUCCESS) {
460 *crtctx = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, cert_der, cert_der_len);
467 if (!CertSetCertificateContextProperty(*crtctx, CERT_NCRYPT_KEY_HANDLE_PROP_ID, 0,
key)) {
468 av_log(
NULL,
AV_LOG_ERROR,
"CertSetCertificateContextProperty(CERT_NCRYPT_KEY_HANDLE_PROP_ID) failed: %lu\n", GetLastError());
473 prov_info.pwszProvName = (LPWSTR)MS_KEY_STORAGE_PROVIDER;
475 prov_info.dwFlags = CERT_SET_KEY_CONTEXT_PROP_ID;
477 if (!CertSetCertificateContextProperty(*crtctx, CERT_KEY_PROV_INFO_PROP_ID, 0, &prov_info)) {
478 av_log(
NULL,
AV_LOG_ERROR,
"CertSetCertificateContextProperty(CERT_KEY_PROV_INFO_PROP_ID) failed: %lu\n", GetLastError());
487 if (NCryptDeleteKey(*
key, NCRYPT_SILENT_FLAG) != ERROR_SUCCESS)
488 NCryptFreeObject(*
key);
490 CertFreeCertificateContext(*crtctx);
501 NCryptFreeObject(provider);
505 static int tls_cert_from_store(
void *logctx,
const char *cert_store_name,
const char *cert_subj, PCCERT_CONTEXT *crtctx)
507 HCERTSTORE cert_store =
NULL;
510 cert_store = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, 0, CERT_SYSTEM_STORE_CURRENT_USER, cert_store_name);
517 *crtctx = CertFindCertificateInStore(cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_SUBJECT_STR_A, cert_subj,
NULL);
526 CertCloseStore(cert_store, 0);
533 AVBPrint key_bp, cert_bp;
563 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)
565 NCRYPT_KEY_HANDLE
key = 0;
566 PCCERT_CONTEXT crtctx =
NULL;
578 if (NCryptDeleteKey(
key, NCRYPT_SILENT_FLAG) != ERROR_SUCCESS)
579 NCryptFreeObject(
key);
581 CertFreeCertificateContext(crtctx);
628 c->tls_shared.udp = sock;
630 c->tls_shared.tcp = sock;
639 SecPkgContext_KeyingMaterialInfo keying_info = { 0 };
640 SecPkgContext_KeyingMaterial keying_material = { 0 };
642 const char*
dst =
"EXTRACTOR-dtls_srtp";
643 SECURITY_STATUS sspi_ret;
645 if (!
c->have_context)
648 keying_info.cbLabel = strlen(
dst) + 1;
649 keying_info.pszLabel = (LPSTR)
dst;
650 keying_info.cbContextValue = 0;
651 keying_info.pbContextValue =
NULL;
652 keying_info.cbKeyingMaterial = materials_sz;
654 sspi_ret = SetContextAttributes(&
c->ctxt_handle, SECPKG_ATTR_KEYING_MATERIAL_INFO, &keying_info,
sizeof(keying_info));
655 if (sspi_ret != SEC_E_OK) {
660 sspi_ret = QueryContextAttributes(&
c->ctxt_handle, SECPKG_ATTR_KEYING_MATERIAL, &keying_material);
661 if (sspi_ret != SEC_E_OK) {
666 memcpy(dtls_srtp_materials, keying_material.pbKeyingMaterial,
FFMIN(materials_sz, keying_material.cbKeyingMaterial));
667 FreeContextBuffer(keying_material.pbKeyingMaterial);
669 if (keying_material.cbKeyingMaterial > materials_sz) {
670 av_log(
h,
AV_LOG_WARNING,
"Keying material size mismatch: %ld > %zu\n", keying_material.cbKeyingMaterial, materials_sz);
680 return c->tls_shared.state;
692 unsigned long buffer_count)
694 desc->ulVersion = SECBUFFER_VERSION;
695 desc->pBuffers = buffers;
696 desc->cBuffers = buffer_count;
709 ret =
ffurl_write(uc,
c->send_buf +
c->send_buf_offset,
c->send_buf_size -
c->send_buf_offset);
712 }
else if (
ret < 0) {
717 c->send_buf_offset +=
ret;
719 if (
c->send_buf_offset <
c->send_buf_size)
723 c->send_buf_size =
c->send_buf_offset = 0;
736 SecBufferDesc BuffDesc;
738 SECURITY_STATUS sspi_ret;
740 SecBufferDesc outbuf_desc;
742 DWORD dwshut = SCHANNEL_SHUTDOWN;
751 sspi_ret = ApplyControlToken(&
c->ctxt_handle, &BuffDesc);
752 if (sspi_ret != SEC_E_OK)
760 sspi_ret = AcceptSecurityContext(&
c->cred_handle, &
c->ctxt_handle,
NULL,
c->request_flags, 0,
761 &
c->ctxt_handle, &outbuf_desc, &
c->context_flags,
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);
768 if (outbuf.pvBuffer) {
769 if (outbuf.cbBuffer > 0) {
771 if (
ret < 0 ||
ret != outbuf.cbBuffer)
774 FreeContextBuffer(outbuf.pvBuffer);
776 }
while(sspi_ret == SEC_I_MESSAGE_FRAGMENT || sspi_ret == SEC_I_CONTINUE_NEEDED);
792 DeleteSecurityContext(&
c->ctxt_handle);
793 FreeCredentialsHandle(&
c->cred_handle);
796 c->enc_buf_size =
c->enc_buf_offset = 0;
799 c->dec_buf_size =
c->dec_buf_offset = 0;
802 c->send_buf_size =
c->send_buf_offset = 0;
805 if (!
s->external_sock)
819 SECURITY_STATUS sspi_ret;
820 SecBuffer outbuf[3] = { 0 };
821 SecBufferDesc outbuf_desc;
823 SecBufferDesc inbuf_desc;
825 socklen_t recv_addr_len = 0;
828 if (
c->enc_buf ==
NULL) {
829 c->enc_buf_offset = 0;
836 if (
c->dec_buf ==
NULL) {
837 c->dec_buf_offset = 0;
851 c->enc_buf_size =
c->enc_buf_offset = 0;
857 ret =
ffurl_read(uc,
c->enc_buf +
c->enc_buf_offset,
c->enc_buf_size -
c->enc_buf_offset);
862 c->enc_buf_offset +=
ret;
863 if (
s->is_dtls && !recv_addr_len) {
880 if (
s->listen &&
s->is_dtls) {
881 init_sec_buffer(&inbuf[2], SECBUFFER_EXTRA, &recv_addr, recv_addr_len);
887 if (inbuf[0].pvBuffer ==
NULL) {
893 memcpy(inbuf[0].pvBuffer,
c->enc_buf,
c->enc_buf_offset);
902 sspi_ret = AcceptSecurityContext(&
c->cred_handle,
c->have_context ? &
c->ctxt_handle :
NULL, &inbuf_desc,
903 c->request_flags, 0, &
c->ctxt_handle, &outbuf_desc,
904 &
c->context_flags, &
c->ctxt_timestamp);
906 sspi_ret = InitializeSecurityContext(&
c->cred_handle,
c->have_context ? &
c->ctxt_handle :
NULL,
907 s->host,
c->request_flags, 0, 0, &inbuf_desc, 0, &
c->ctxt_handle,
908 &outbuf_desc, &
c->context_flags, &
c->ctxt_timestamp);
911 av_log(
h,
AV_LOG_TRACE,
"Handshake res with %d bytes of data: 0x%lx\n",
c->enc_buf_offset, sspi_ret);
913 if (sspi_ret == SEC_E_INCOMPLETE_MESSAGE) {
922 if (sspi_ret == SEC_I_INCOMPLETE_CREDENTIALS &&
923 !(
c->request_flags & ISC_REQ_USE_SUPPLIED_CREDS)) {
925 c->request_flags |= ISC_REQ_USE_SUPPLIED_CREDS;
931 if (sspi_ret == SEC_I_CONTINUE_NEEDED || sspi_ret == SEC_I_MESSAGE_FRAGMENT || sspi_ret == SEC_E_OK) {
932 for (
i = 0;
i < 3;
i++) {
933 if (outbuf[
i].BufferType == SECBUFFER_TOKEN && outbuf[
i].cbBuffer > 0) {
935 if (
ret < 0 ||
ret != outbuf[
i].cbBuffer) {
942 if (outbuf[
i].pvBuffer !=
NULL) {
943 FreeContextBuffer(outbuf[
i].pvBuffer);
944 outbuf[
i].pvBuffer =
NULL;
948 if (sspi_ret == SEC_E_WRONG_PRINCIPAL)
956 if (sspi_ret == SEC_I_MESSAGE_FRAGMENT) {
962 if (inbuf[1].BufferType == SECBUFFER_EXTRA && inbuf[1].cbBuffer > 0) {
963 if (
c->enc_buf_offset > inbuf[1].cbBuffer) {
964 memmove(
c->enc_buf, (
c->enc_buf +
c->enc_buf_offset) - inbuf[1].cbBuffer,
966 c->enc_buf_offset = inbuf[1].cbBuffer;
967 if (sspi_ret == SEC_I_CONTINUE_NEEDED) {
968 av_log(
h,
AV_LOG_TRACE,
"Sent reply, handshake continues. %d extra bytes\n", (
int)inbuf[1].cbBuffer);
974 c->enc_buf_offset = 0;
977 if (sspi_ret == SEC_I_CONTINUE_NEEDED) {
992 for (
i = 0;
i < 3;
i++) {
993 if (outbuf[
i].pvBuffer !=
NULL) {
994 FreeContextBuffer(outbuf[
i].pvBuffer);
995 outbuf[
i].pvBuffer =
NULL;
1010 SecBufferDesc outbuf_desc;
1011 SECURITY_STATUS sspi_ret;
1017 c->request_flags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT |
1018 ISC_REQ_CONFIDENTIALITY | ISC_REQ_ALLOCATE_MEMORY;
1020 c->request_flags |= ISC_REQ_DATAGRAM;
1022 c->request_flags |= ISC_REQ_STREAM;
1024 sspi_ret = InitializeSecurityContext(&
c->cred_handle,
NULL,
s->host,
c->request_flags, 0, 0,
1025 NULL, 0, &
c->ctxt_handle, &outbuf_desc, &
c->context_flags,
1026 &
c->ctxt_timestamp);
1027 if (sspi_ret != SEC_I_CONTINUE_NEEDED) {
1033 c->have_context = 1;
1037 FreeContextBuffer(outbuf.pvBuffer);
1038 if (
ret < 0 ||
ret != outbuf.cbBuffer) {
1047 DeleteSecurityContext(&
c->ctxt_handle);
1056 c->request_flags = ASC_REQ_SEQUENCE_DETECT | ASC_REQ_REPLAY_DETECT |
1057 ASC_REQ_CONFIDENTIALITY | ASC_REQ_ALLOCATE_MEMORY;
1059 c->request_flags |= ASC_REQ_DATAGRAM;
1061 c->request_flags |= ASC_REQ_STREAM;
1063 c->have_context = 0;
1072 SECURITY_STATUS sspi_ret;
1083 if (
s->is_dtls &&
s->mtu > 0) {
1085 sspi_ret = SetContextAttributes(&
c->ctxt_handle, SECPKG_ATTR_DTLS_MTU, &mtu,
sizeof(mtu));
1086 if (sspi_ret != SEC_E_OK) {
1105 SECURITY_STATUS sspi_ret;
1106 SCHANNEL_CRED schannel_cred = { 0 };
1107 PCCERT_CONTEXT crtctx =
NULL;
1108 NCRYPT_KEY_HANDLE
key = 0;
1111 if (!
s->external_sock) {
1117 schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
1120 if (
c->cert_store_name &&
c->cert_store_subject) {
1122 }
else if (
s->key_buf &&
s->cert_buf) {
1124 }
else if (
s->key_file &&
s->cert_file) {
1134 schannel_cred.cCreds = 1;
1135 schannel_cred.paCred = &crtctx;
1137 schannel_cred.dwFlags = SCH_CRED_NO_SYSTEM_MAPPER | SCH_CRED_MANUAL_CRED_VALIDATION;
1140 schannel_cred.grbitEnabledProtocols = SP_PROT_DTLS1_X_SERVER;
1143 schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION |
1144 SCH_CRED_REVOCATION_CHECK_CHAIN;
1146 schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION |
1147 SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
1148 SCH_CRED_IGNORE_REVOCATION_OFFLINE;
1151 schannel_cred.grbitEnabledProtocols = SP_PROT_DTLS1_X_CLIENT;
1155 sspi_ret = AcquireCredentialsHandle(
NULL, (TCHAR *)UNISP_NAME,
1156 s->listen ? SECPKG_CRED_INBOUND : SECPKG_CRED_OUTBOUND,
1158 &
c->cred_timestamp);
1159 if (sspi_ret != SEC_E_OK) {
1165 if (!
s->external_sock) {
1178 CertFreeCertificateContext(crtctx);
1180 if (NCryptDeleteKey(
key, NCRYPT_SILENT_FLAG) != ERROR_SUCCESS)
1181 NCryptFreeObject(
key);
1201 SECURITY_STATUS sspi_ret = SEC_E_OK;
1203 SecBufferDesc inbuf_desc;
1212 if (
c->dec_buf_offset > 0)
1215 if (
c->sspi_close_notify)
1218 if (!
c->connection_closed) {
1219 size =
c->enc_buf_size -
c->enc_buf_offset;
1220 if (size < SCHANNEL_FREE_BUFFER_SIZE || c->enc_buf_size < min_enc_buf_size) {
1222 if (
c->enc_buf_size < min_enc_buf_size)
1223 c->enc_buf_size = min_enc_buf_size;
1226 c->enc_buf_size =
c->enc_buf_offset = 0;
1235 c->enc_buf_size -
c->enc_buf_offset);
1237 c->connection_closed = 1;
1241 }
else if (
ret < 0) {
1246 c->enc_buf_offset +=
ret;
1249 while (
c->enc_buf_offset > 0 && sspi_ret == SEC_E_OK) {
1259 sspi_ret = DecryptMessage(&
c->ctxt_handle, &inbuf_desc, 0,
NULL);
1260 if (sspi_ret == SEC_E_OK || sspi_ret == SEC_I_RENEGOTIATE ||
1261 sspi_ret == SEC_I_CONTEXT_EXPIRED) {
1263 if (inbuf[1].BufferType == SECBUFFER_DATA) {
1267 if (
c->dec_buf_size -
c->dec_buf_offset <
size ||
c->dec_buf_size <
len) {
1268 c->dec_buf_size =
c->dec_buf_offset +
size;
1269 if (
c->dec_buf_size <
len)
1270 c->dec_buf_size =
len;
1273 c->dec_buf_size =
c->dec_buf_offset = 0;
1279 size = inbuf[1].cbBuffer;
1281 memcpy(
c->dec_buf +
c->dec_buf_offset, inbuf[1].pvBuffer,
size);
1282 c->dec_buf_offset +=
size;
1285 if (inbuf[3].BufferType == SECBUFFER_EXTRA && inbuf[3].cbBuffer > 0) {
1286 if (
c->enc_buf_offset > inbuf[3].cbBuffer) {
1287 memmove(
c->enc_buf, (
c->enc_buf +
c->enc_buf_offset) - inbuf[3].cbBuffer,
1289 c->enc_buf_offset = inbuf[3].cbBuffer;
1292 c->enc_buf_offset = 0;
1294 if (sspi_ret == SEC_I_RENEGOTIATE) {
1295 if (
c->enc_buf_offset) {
1306 sspi_ret = SEC_E_OK;
1310 c->send_buf_size =
c->send_buf_offset = 0;
1313 }
else if (sspi_ret == SEC_I_CONTEXT_EXPIRED) {
1314 c->sspi_close_notify = 1;
1315 if (!
c->connection_closed) {
1316 c->connection_closed = 1;
1322 }
else if (sspi_ret == SEC_E_INCOMPLETE_MESSAGE) {
1337 memcpy(buf,
c->dec_buf,
size);
1338 memmove(
c->dec_buf,
c->dec_buf +
size,
c->dec_buf_offset -
size);
1339 c->dec_buf_offset -=
size;
1344 if (
ret == 0 && !
c->connection_closed)
1355 SECURITY_STATUS sspi_ret;
1356 SecBuffer outbuf[4];
1357 SecBufferDesc outbuf_desc;
1367 if (
c->sizes.cbMaximumMessage == 0) {
1368 sspi_ret = QueryContextAttributes(&
c->ctxt_handle, SECPKG_ATTR_STREAM_SIZES, &
c->sizes);
1369 if (sspi_ret != SEC_E_OK)
1374 len =
FFMIN(
len,
c->sizes.cbMaximumMessage -
c->sizes.cbHeader -
c->sizes.cbTrailer);
1376 c->send_buf_size =
c->sizes.cbHeader +
len +
c->sizes.cbTrailer;
1378 if (
c->send_buf ==
NULL)
1382 c->send_buf,
c->sizes.cbHeader);
1384 c->send_buf +
c->sizes.cbHeader,
len);
1386 c->send_buf +
c->sizes.cbHeader +
len,
1387 c->sizes.cbTrailer);
1391 memcpy(outbuf[1].pvBuffer, buf,
len);
1393 sspi_ret = EncryptMessage(&
c->ctxt_handle, 0, &outbuf_desc, 0);
1394 if (sspi_ret != SEC_E_OK) {
1397 if (sspi_ret == SEC_E_INSUFFICIENT_MEMORY)
1402 c->send_buf_size = outbuf[0].cbBuffer + outbuf[1].cbBuffer + outbuf[2].cbBuffer;
1403 c->send_buf_offset = 0;
1410 return outbuf[1].cbBuffer;
1411 }
else if (
ret < 0) {
1415 return outbuf[1].cbBuffer;
1432 #define OFFSET(x) offsetof(TLSContext, x)
1435 {
"cert_store_subject",
"Load certificate (and associated key) from users keystore by subject",
1437 {
"cert_store_name",
"Name of the specific cert store to search in (for cert_store_subject)",