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);
 
  630         c->tls_shared.udp = sock;
 
  632         c->tls_shared.tcp = sock;
 
  639 #if HAVE_SECPKGCONTEXT_KEYINGMATERIALINFO 
  642     SecPkgContext_KeyingMaterialInfo keying_info = { 0 };
 
  643     SecPkgContext_KeyingMaterial keying_material = { 0 };
 
  645     const char* 
dst = 
"EXTRACTOR-dtls_srtp";
 
  646     SECURITY_STATUS sspi_ret;
 
  648     if (!
c->have_context)
 
  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;
 
  657     sspi_ret = SetContextAttributes(&
c->ctxt_handle, SECPKG_ATTR_KEYING_MATERIAL_INFO, &keying_info, 
sizeof(keying_info));
 
  658     if (sspi_ret != SEC_E_OK) {
 
  663     sspi_ret = QueryContextAttributes(&
c->ctxt_handle, SECPKG_ATTR_KEYING_MATERIAL, &keying_material);
 
  664     if (sspi_ret != SEC_E_OK) {
 
  669     memcpy(dtls_srtp_materials, keying_material.pbKeyingMaterial, 
FFMIN(materials_sz, keying_material.cbKeyingMaterial));
 
  670     FreeContextBuffer(keying_material.pbKeyingMaterial);
 
  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);
 
  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);
 
  777 #ifdef SEC_I_MESSAGE_FRAGMENT
 
  778                 sspi_ret == SEC_I_MESSAGE_FRAGMENT ||
 
  780                 sspi_ret == SEC_I_CONTINUE_NEEDED);
 
  796     DeleteSecurityContext(&
c->ctxt_handle);
 
  797     FreeCredentialsHandle(&
c->cred_handle);
 
  800     c->enc_buf_size = 
c->enc_buf_offset = 0;
 
  803     c->dec_buf_size = 
c->dec_buf_offset = 0;
 
  806     c->send_buf_size = 
c->send_buf_offset = 0;
 
  809         if (!
s->external_sock)
 
  823     SECURITY_STATUS sspi_ret;
 
  824     SecBuffer outbuf[3] = { 0 };
 
  825     SecBufferDesc outbuf_desc;
 
  827     SecBufferDesc inbuf_desc;
 
  829     socklen_t recv_addr_len = 0;
 
  832     if (
c->enc_buf == 
NULL) {
 
  833         c->enc_buf_offset = 0;
 
  840     if (
c->dec_buf == 
NULL) {
 
  841         c->dec_buf_offset = 0;
 
  855                 c->enc_buf_size = 
c->enc_buf_offset = 0;
 
  861             ret = 
ffurl_read(uc, 
c->enc_buf + 
c->enc_buf_offset, 
c->enc_buf_size - 
c->enc_buf_offset);
 
  866             c->enc_buf_offset += 
ret;
 
  867             if (
s->is_dtls && !recv_addr_len) {
 
  884         if (
s->listen && 
s->is_dtls) {
 
  885             init_sec_buffer(&inbuf[2], SECBUFFER_EXTRA, &recv_addr, recv_addr_len);
 
  891         if (inbuf[0].pvBuffer == 
NULL) {
 
  897         memcpy(inbuf[0].pvBuffer, 
c->enc_buf, 
c->enc_buf_offset);
 
  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);
 
  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);
 
  915         av_log(
h, 
AV_LOG_TRACE, 
"Handshake res with %d bytes of data: 0x%lx\n", 
c->enc_buf_offset, sspi_ret);
 
  917         if (sspi_ret == SEC_E_INCOMPLETE_MESSAGE) {
 
  926         if (sspi_ret == SEC_I_INCOMPLETE_CREDENTIALS &&
 
  927             !(
c->request_flags & ISC_REQ_USE_SUPPLIED_CREDS)) {
 
  929             c->request_flags |= ISC_REQ_USE_SUPPLIED_CREDS;
 
  935         if (sspi_ret == SEC_I_CONTINUE_NEEDED ||
 
  936 #ifdef SEC_I_MESSAGE_FRAGMENT
 
  937             sspi_ret == SEC_I_MESSAGE_FRAGMENT ||
 
  939             sspi_ret == SEC_E_OK) {
 
  940             for (
i = 0; 
i < 3; 
i++) {
 
  941                 if (outbuf[
i].BufferType == SECBUFFER_TOKEN && outbuf[
i].cbBuffer > 0) {
 
  943                     if (
ret < 0 || 
ret != outbuf[
i].cbBuffer) {
 
  950                 if (outbuf[
i].pvBuffer != 
NULL) {
 
  951                     FreeContextBuffer(outbuf[
i].pvBuffer);
 
  952                     outbuf[
i].pvBuffer = 
NULL;
 
  956             if (sspi_ret == SEC_E_WRONG_PRINCIPAL)
 
  964 #ifdef SEC_I_MESSAGE_FRAGMENT 
  965         if (sspi_ret == SEC_I_MESSAGE_FRAGMENT) {
 
  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,
 
  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);
 
  984             c->enc_buf_offset  = 0;
 
  987         if (sspi_ret == SEC_I_CONTINUE_NEEDED) {
 
 1002     for (
i = 0; 
i < 3; 
i++) {
 
 1003         if (outbuf[
i].pvBuffer != 
NULL) {
 
 1004             FreeContextBuffer(outbuf[
i].pvBuffer);
 
 1005             outbuf[
i].pvBuffer = 
NULL;
 
 1020     SecBufferDesc outbuf_desc;
 
 1021     SECURITY_STATUS sspi_ret;
 
 1027     c->request_flags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT |
 
 1028                        ISC_REQ_CONFIDENTIALITY | ISC_REQ_ALLOCATE_MEMORY;
 
 1030         c->request_flags |= ISC_REQ_DATAGRAM;
 
 1032         c->request_flags |= ISC_REQ_STREAM;
 
 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) {
 
 1043     c->have_context = 1;
 
 1047     FreeContextBuffer(outbuf.pvBuffer);
 
 1048     if (
ret < 0 || 
ret != outbuf.cbBuffer) {
 
 1057     DeleteSecurityContext(&
c->ctxt_handle);
 
 1066     c->request_flags = ASC_REQ_SEQUENCE_DETECT | ASC_REQ_REPLAY_DETECT |
 
 1067                        ASC_REQ_CONFIDENTIALITY | ASC_REQ_ALLOCATE_MEMORY;
 
 1069         c->request_flags |= ASC_REQ_DATAGRAM;
 
 1071         c->request_flags |= ASC_REQ_STREAM;
 
 1073     c->have_context = 0;
 
 1082     SECURITY_STATUS sspi_ret;
 
 1093 #if CONFIG_DTLS_PROTOCOL 
 1094     if (
s->is_dtls && 
s->mtu > 0) {
 
 1096         sspi_ret = SetContextAttributes(&
c->ctxt_handle, SECPKG_ATTR_DTLS_MTU, &mtu, 
sizeof(mtu));
 
 1097         if (sspi_ret != SEC_E_OK) {
 
 1116     SECURITY_STATUS sspi_ret;
 
 1117     SCHANNEL_CRED schannel_cred = { 0 };
 
 1118     PCCERT_CONTEXT crtctx = 
NULL;
 
 1119     NCRYPT_KEY_HANDLE 
key = 0;
 
 1122     if (!
s->external_sock) {
 
 1128     schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
 
 1131         if (
c->cert_store_name && 
c->cert_store_subject) {
 
 1133         } 
else if (
s->key_buf && 
s->cert_buf) {
 
 1135         } 
else if (
s->key_file && 
s->cert_file) {
 
 1145         schannel_cred.cCreds = 1;
 
 1146         schannel_cred.paCred = &crtctx;
 
 1148         schannel_cred.dwFlags = SCH_CRED_NO_SYSTEM_MAPPER | SCH_CRED_MANUAL_CRED_VALIDATION;
 
 1150 #if CONFIG_DTLS_PROTOCOL 
 1152             schannel_cred.grbitEnabledProtocols = SP_PROT_DTLS1_X_SERVER;
 
 1156             schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION |
 
 1157                                     SCH_CRED_REVOCATION_CHECK_CHAIN;
 
 1159             schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION |
 
 1160                                     SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
 
 1161                                     SCH_CRED_IGNORE_REVOCATION_OFFLINE;
 
 1163 #if CONFIG_DTLS_PROTOCOL 
 1165             schannel_cred.grbitEnabledProtocols = SP_PROT_DTLS1_X_CLIENT;
 
 1170     sspi_ret = AcquireCredentialsHandle(
NULL, (TCHAR *)UNISP_NAME,
 
 1171                                         s->listen ? SECPKG_CRED_INBOUND : SECPKG_CRED_OUTBOUND,
 
 1173                                         &
c->cred_timestamp);
 
 1174     if (sspi_ret != SEC_E_OK) {
 
 1180     if (!
s->external_sock) {
 
 1193         CertFreeCertificateContext(crtctx);
 
 1195         if (NCryptDeleteKey(
key, NCRYPT_SILENT_FLAG) != ERROR_SUCCESS)
 
 1196             NCryptFreeObject(
key);
 
 1201 #if CONFIG_DTLS_PROTOCOL 
 1218     SECURITY_STATUS sspi_ret = SEC_E_OK;
 
 1220     SecBufferDesc inbuf_desc;
 
 1229     if (
c->dec_buf_offset > 0)
 
 1232     if (
c->sspi_close_notify)
 
 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) {
 
 1239             if (
c->enc_buf_size < min_enc_buf_size)
 
 1240                 c->enc_buf_size = min_enc_buf_size;
 
 1243                 c->enc_buf_size = 
c->enc_buf_offset = 0;
 
 1252                          c->enc_buf_size - 
c->enc_buf_offset);
 
 1254             c->connection_closed = 1;
 
 1258         } 
else if (
ret < 0) {
 
 1263         c->enc_buf_offset += 
ret;
 
 1266     while (
c->enc_buf_offset > 0 && sspi_ret == SEC_E_OK) {
 
 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) {
 
 1280             if (inbuf[1].BufferType == SECBUFFER_DATA) {
 
 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;
 
 1290                         c->dec_buf_size = 
c->dec_buf_offset = 0;
 
 1296                 size = inbuf[1].cbBuffer;
 
 1298                     memcpy(
c->dec_buf + 
c->dec_buf_offset, inbuf[1].pvBuffer, 
size);
 
 1299                     c->dec_buf_offset += 
size;
 
 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,
 
 1306                     c->enc_buf_offset = inbuf[3].cbBuffer;
 
 1309                 c->enc_buf_offset = 0;
 
 1311             if (sspi_ret == SEC_I_RENEGOTIATE) {
 
 1312                 if (
c->enc_buf_offset) {
 
 1323                 sspi_ret = SEC_E_OK;
 
 1327                 c->send_buf_size = 
c->send_buf_offset = 0;
 
 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;
 
 1339         } 
else if (sspi_ret == SEC_E_INCOMPLETE_MESSAGE) {
 
 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;
 
 1361     if (
ret == 0 && !
c->connection_closed)
 
 1372     SECURITY_STATUS sspi_ret;
 
 1373     SecBuffer outbuf[4];
 
 1374     SecBufferDesc outbuf_desc;
 
 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)
 
 1391     len = 
FFMIN(
len, 
c->sizes.cbMaximumMessage - 
c->sizes.cbHeader - 
c->sizes.cbTrailer);
 
 1393     c->send_buf_size = 
c->sizes.cbHeader + 
len + 
c->sizes.cbTrailer;
 
 1395     if (
c->send_buf == 
NULL)
 
 1399                     c->send_buf, 
c->sizes.cbHeader);
 
 1401                     c->send_buf + 
c->sizes.cbHeader, 
len);
 
 1403                     c->send_buf + 
c->sizes.cbHeader + 
len,
 
 1404                     c->sizes.cbTrailer);
 
 1408     memcpy(outbuf[1].pvBuffer, buf, 
len);
 
 1410     sspi_ret = EncryptMessage(&
c->ctxt_handle, 0, &outbuf_desc, 0);
 
 1411     if (sspi_ret != SEC_E_OK) {
 
 1414         if (sspi_ret == SEC_E_INSUFFICIENT_MEMORY)
 
 1419     c->send_buf_size = outbuf[0].cbBuffer + outbuf[1].cbBuffer + outbuf[2].cbBuffer;
 
 1420     c->send_buf_offset = 0;
 
 1427         return outbuf[1].cbBuffer;
 
 1428     } 
else if (
ret < 0) {
 
 1432     return outbuf[1].cbBuffer;
 
 1449 #define OFFSET(x) offsetof(TLSContext, x) 
 1452     { 
"cert_store_subject", 
"Load certificate (and associated key) from users keystore by subject",
 
 1454     { 
"cert_store_name",    
"Name of the specific cert store to search in (for cert_store_subject)",
 
 1459 #if CONFIG_TLS_PROTOCOL 
 1481 #if CONFIG_DTLS_PROTOCOL