eve.tls.windows.schannel

Windows SChannel TLS Implementation (EXPERIMENTAL)

WARNING: This module is experimental. The API may change and security properties have not been fully audited. Do not use in production without independent security review.

This module provides TLS/SSL support for Windows using the native SChannel (Secure Channel) SSPI provider. SChannel is the Windows built-in SSL/TLS implementation requiring no external dependencies.

The implementation wraps the SSPI API to provide a clean interface matching the eve.tls.api contract.

Version Compatibility:

  • Minimum: Windows Vista / Server 2008 (SSPI base API)
  • TLS 1.2: Fully supported (Windows 7 / Server 2008 R2+)
  • ALPN: Windows 8.1 / Server 2012 R2+
  • TLS 1.3: Windows 10 1809 / Server 2019+

SSPI bindings are locally declared and audited against Windows SDK headers. All type sizes use platform-correct widths (size_t for DWORD_PTR/UINT_PTR, uint for DWORD/ULONG, void* for opaque handles).

var ASC_REQ_ALLOCATE_MEMORY ASC_REQ_CONFIDENTIALITY ASC_REQ_REPLAY_DETECT ASC_REQ_SEQUENCE_DETECT ASC_REQ_STREAM CERT_ENCODING_TYPE CERT_FIND_ANY CERT_NAME_ISSUER_FLAG CERT_NAME_SIMPLE_DISPLAY_TYPE CERT_STORE_ADD_ALWAYS CERT_STORE_PROV_MEMORY CRYPT_STRING_BASE64_ANY CRYPT_STRING_BASE64HEADER IO_BUFFER_SIZE ISC_REQ_ALLOCATE_MEMORY ISC_REQ_CONFIDENTIALITY ISC_REQ_MANUAL_CRED_VALIDATION ISC_REQ_REPLAY_DETECT ISC_REQ_SEQUENCE_DETECT ISC_REQ_STREAM ISC_REQ_USE_SUPPLIED_CREDS PKCS12_NO_PERSIST_KEY PKCS_7_ASN_ENCODING SCH_CRED_MANUAL_CRED_VALIDATION SCH_CRED_NO_DEFAULT_CREDS SCH_USE_STRONG_CRYPTO SCHANNEL_CRED_VERSION SEC_APPLICATION_PROTOCOL_NEGOTIATION_STATUS_Negotiated SEC_E_CERT_EXPIRED SEC_E_CERT_UNKNOWN SEC_E_INCOMPLETE_MESSAGE SEC_E_INTERNAL_ERROR SEC_E_INVALID_HANDLE SEC_E_INVALID_TOKEN SEC_E_OK SEC_E_UNTRUSTED_ROOT SEC_E_WRONG_PRINCIPAL SEC_I_CONTEXT_EXPIRED SEC_I_CONTINUE_NEEDED SEC_I_INCOMPLETE_CREDENTIALS SECBUFFER_ALERT SECBUFFER_DATA SECBUFFER_EMPTY SECBUFFER_EXTRA SECBUFFER_SEND_GENERIC_TLS_EXTENSION SECBUFFER_STREAM_HEADER SECBUFFER_STREAM_TRAILER SECBUFFER_TOKEN SECBUFFER_VERSION SECPKG_ATTR_APPLICATION_PROTOCOL SECPKG_ATTR_REMOTE_CERT_CONTEXT SECPKG_ATTR_STREAM_SIZES SECPKG_CRED_INBOUND SECPKG_CRED_OUTBOUND SecPkgApplicationProtocolNegotiationExt_ALPN SOCKET_ERROR SP_PROT_TLS1_0_CLIENT SP_PROT_TLS1_0_SERVER SP_PROT_TLS1_1_CLIENT SP_PROT_TLS1_1_SERVER SP_PROT_TLS1_2_CLIENT SP_PROT_TLS1_2_SERVER SP_PROT_TLS1_3_CLIENT SP_PROT_TLS1_3_SERVER TLS1_ALPN_EXTENSION TLS_MAX_RECORD_SIZE WSAEWOULDBLOCK X509_ASN_ENCODING

Types 17

aliasSECURITY_STATUS = int

Security status codes

Credential handle

Fields
size_t dwLower
size_t dwUpper

Context handle

Fields
size_t dwLower
size_t dwUpper
structTimeStamp

Timestamp structure

Fields
uint dwLowDateTime
uint dwHighDateTime
structSecBuffer

Security buffer

Fields
uint cbBuffer
uint bufferType
void * pvBuffer

Security buffer descriptor

Fields
uint ulVersion
uint cBuffers
SecBuffer * pBuffers

Stream sizes for encryption

Fields
uint cbHeader
uint cbTrailer
uint cbMaximumMessage
uint cBuffers
uint cbBlockSize

SChannel credentials

Fields
uint dwVersion
uint cCreds
void * * paCred
void * hRootStore
uint cMappers
void * * aphMappers
uint cSupportedAlgs
uint * palgSupportedAlgs
uint grbitEnabledProtocols
uint dwMinimumCipherStrength
uint dwMaximumCipherStrength
uint dwSessionLifespan
uint dwFlags
uint dwCredFormat
Fields
uint ProtoNegoState
uint ProtoNegoExt
ushort ProtocolIdSize
char * ProtocolId
private structCRYPT_DATA_BLOB
Fields
uint cbData
ubyte * pbData
Fields
char * pszObjId
CRYPT_DATA_BLOB Parameters
private aliasFILETIME = TimeStamp
private structCERT_INFO
Fields
uint dwVersion
CRYPT_DATA_BLOB SerialNumber
CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm
FILETIME NotBefore
FILETIME NotAfter
private structCERT_CONTEXT
Fields
uint cbCertEncoded
ubyte * pbCertEncoded
void * hCertStore
CERT_INFO * pCertInfo
private structSYSTEMTIME
Fields
ushort wYear
ushort wMonth
ushort wDayOfWeek
ushort wDay
ushort wHour
ushort wMinute
ushort wSecond
ushort wMilliseconds

SChannel credential handle wrapper.

Manages the lifecycle of SSPI credentials used for TLS connections. Credentials are acquired based on the TlsContext configuration and must be released when no longer needed.

Fields
private CredHandle handle
private bool valid_
private void * rootStore_
private CERT_CONTEXT * serverCert_
private void * pfxStore_
Methods
TlsErrorCode initialize(ref const(TlsContext) ctx) @trusted nothrowInitialize credentials from a TLS context.
void release() @trusted nothrow
bool isValid() const pure @safe nothrow @nogc
CredHandle * handlePtr() @trusted nothrow @nogc
void * loadCaCertFile(string path) @trusted nothrow
CERT_CONTEXT * loadCertFromPem(string path) @trusted nothrow
ptrdiff_t indexOf(const(char)[] haystack, const(char)[] needle, size_t start) pure nothrow
CERT_CONTEXT * loadCertAndKeyFromPfx(string path) @trusted nothrowLoad a certificate with its private key from a PFX (PKCS#12) file.
bool endsWith(const(char)[] str, const(char)[] suffix) static pure nothrow @nogc
Destructors
structTlsStream(Transport)

SChannel TLS Stream.

Provides TLS encryption/decryption over an underlying transport. This struct wraps the SSPI/SChannel API to implement the TLS stream interface defined in eve.tls.api.

Parameters

TransportThe underlying transport type (must support read/write).
Fields
Transport * transport_
TlsContext context_
SchannelCredentials credentials_
CtxtHandle secContext_
bool contextValid_
TlsState state_
HandshakeState handshakeState_
bool streamSizesValid_
ubyte[IO_BUFFER_SIZE] recvBuffer_
size_t recvBufferLen_
ubyte[IO_BUFFER_SIZE] decryptedBuffer_
size_t decryptedBufferLen_
size_t decryptedBufferPos_
ubyte[IO_BUFFER_SIZE] pendingSendBuffer_
size_t pendingSendLen_
size_t pendingSendPos_
ubyte[IO_BUFFER_SIZE] handshakeOutBuffer_
size_t handshakeOutBufferLen_
size_t handshakeOutBufferPos_
TlsErrorCode lastError_
Methods
TlsState state() @property const pure @safe nothrow @nogcGet the current TLS stream state.
TlsErrorCode lastError() @property const pure @safe nothrow @nogcGet the last error code.
TlsIoInterest ioInterest() const pure @safe nothrow @nogcGet the current I/O interest for the underlying transport.
HandshakeResult handshake() @trustedPerform the TLS handshake.
TlsIOResult read(ubyte[] buffer) @trustedRead decrypted data from the TLS stream.
TlsIOResult write(const(ubyte)[] data) @trustedWrite data to be encrypted and sent.
void shutdown() @trustedInitiate graceful TLS shutdown.
CertificateInfo peerCertificate() @trustedGet the peer's certificate information.
string negotiatedProtocol() @trustedGet the negotiated ALPN protocol, if any.
int rawSend(const(ubyte)[] data) @trusted nothrow
int rawRecv(ubyte[] buffer) @trusted nothrow
TlsErrorCode queryStreamSizes() @trusted nothrow @nogc
size_t buildAlpnExtension(ubyte[] buf) nothrow
TlsIOResult readAndDecrypt(ubyte[] buffer) @trusted
TlsIOResult encryptAndSend(const(ubyte)[] data) @trusted
Constructors
this(Transport * transport, TlsContext ctx)Construct a TLS stream over the given transport.

Functions 28

fnSECURITY_STATUS AcquireCredentialsHandleA( PCHAR pszPrincipal, PCHAR pszPackage, ULONG fCredentialUse, void * pvLogonId, void * pAuthData, void * pGetKeyFn, void * pvGetKeyArgument, CredHandle * phCredential, TimeStamp * ptsExpiry )
fnSECURITY_STATUS InitializeSecurityContextA( CredHandle * phCredential, CtxtHandle * phContext, PCHAR pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, SecBufferDesc * pInput, ULONG Reserved2, CtxtHandle * phNewContext, SecBufferDesc * pOutput, ULONG * pfContextAttr, TimeStamp * ptsExpiry )
fnSECURITY_STATUS AcceptSecurityContext( CredHandle * phCredential, CtxtHandle * phContext, SecBufferDesc * pInput, ULONG fContextReq, ULONG TargetDataRep, CtxtHandle * phNewContext, SecBufferDesc * pOutput, ULONG * pfContextAttr, TimeStamp * ptsExpiry )
fnSECURITY_STATUS QueryContextAttributesA( CtxtHandle * phContext, ULONG ulAttribute, void * pBuffer )
fnSECURITY_STATUS EncryptMessage( CtxtHandle * phContext, ULONG fQOP, SecBufferDesc * pMessage, ULONG MessageSeqNo )
fnSECURITY_STATUS DecryptMessage( CtxtHandle * phContext, SecBufferDesc * pMessage, ULONG MessageSeqNo, ULONG * pfQOP )
fnSECURITY_STATUS FreeContextBuffer(void * pvContextBuffer)
fnint send(size_t s, const(void) * buf, int len, int flags)
fnint recv(size_t s, void * buf, int len, int flags)
fnDWORD CertGetNameStringA( CERT_CONTEXT * pCertContext, DWORD dwType, DWORD dwFlags, void * pvTypePara, PCHAR pszNameString, DWORD cchNameString )
fnBOOL FileTimeToSystemTime(const FILETIME * lpFileTime, SYSTEMTIME * lpSystemTime)
fnvoid * CertOpenStore(PCHAR lpszStoreProvider, DWORD dwMsgAndCertEncodingType, void * hCryptProv, DWORD dwFlags, const void * pvPara)
fnBOOL CertCloseStore(void * hCertStore, DWORD dwFlags)
fnCERT_CONTEXT * CertCreateCertificateContext(DWORD dwCertEncodingType, const(ubyte) * pbCertEncoded, DWORD cbCertEncoded)
fnBOOL CertAddCertificateContextToStore(void * hCertStore, CERT_CONTEXT * pCertContext, DWORD dwAddDisposition, CERT_CONTEXT * * ppStoreContext)
fnBOOL CryptStringToBinaryA(PCHAR pszString, DWORD cchString, DWORD dwFlags, ubyte * pbBinary, DWORD * pcbBinary, DWORD * pdwSkip, DWORD * pdwFlags)
fnvoid * PFXImportCertStore(CRYPT_DATA_BLOB * pPFX, const(wchar) * szPassword, DWORD dwFlags)
fnCERT_CONTEXT * CertFindCertificateInStore(void * hCertStore, DWORD dwCertEncodingType, DWORD dwFindFlags, DWORD dwFindType, const void * pvFindPara, CERT_CONTEXT * pPrevCertContext)
private fnuint tlsVersionToProtocol(TlsVersion ver, bool isClient) pure @safe nothrow @nogcConvert TlsVersion to SChannel protocol flags.
private fnuint buildProtocolFlags(TlsVersion minVer, TlsVersion maxVer, bool isClient) pure @safe nothrow @nogcBuild protocol flags for a version range.
private fnTlsErrorCode statusToErrorCode(SECURITY_STATUS status) pure @safe nothrow @nogcConvert SECURITY_STATUS to TlsErrorCode.
fnTlsStream!T tlsClient(T)(T * transport, string serverName) @safeCreate a TLS stream for client connections.
fnTlsStream!T tlsServer(T)(T * transport) @safeCreate a TLS stream for server connections.

Variables 68

enumvarSECPKG_CRED_OUTBOUND = 0x00000002
enumvarSECPKG_CRED_INBOUND = 0x00000001
enumvarISC_REQ_SEQUENCE_DETECT = 0x00000008
enumvarISC_REQ_REPLAY_DETECT = 0x00000004
enumvarISC_REQ_CONFIDENTIALITY = 0x00000010
enumvarISC_REQ_USE_SUPPLIED_CREDS = 0x00000080
enumvarISC_REQ_ALLOCATE_MEMORY = 0x00000100
enumvarISC_REQ_STREAM = 0x00008000
enumvarISC_REQ_MANUAL_CRED_VALIDATION = 0x00080000
enumvarASC_REQ_SEQUENCE_DETECT = 0x00000008
enumvarASC_REQ_REPLAY_DETECT = 0x00000004
enumvarASC_REQ_CONFIDENTIALITY = 0x00000010
enumvarASC_REQ_ALLOCATE_MEMORY = 0x00000100
enumvarASC_REQ_STREAM = 0x00008000
enumvarSECBUFFER_VERSION = 0
enumvarSECBUFFER_EMPTY = 0
enumvarSECBUFFER_DATA = 1
enumvarSECBUFFER_TOKEN = 2
enumvarSECBUFFER_EXTRA = 5
enumvarSECBUFFER_STREAM_TRAILER = 6
enumvarSECBUFFER_STREAM_HEADER = 7
enumvarSECBUFFER_ALERT = 17
enumvarSCHANNEL_CRED_VERSION = 4
enumvarSCH_CRED_NO_DEFAULT_CREDS = 0x00000010
enumvarSCH_CRED_MANUAL_CRED_VALIDATION = 0x00000008
enumvarSCH_USE_STRONG_CRYPTO = 0x00400000
enumvarSP_PROT_TLS1_0_CLIENT = 0x00000080
enumvarSP_PROT_TLS1_0_SERVER = 0x00000040
enumvarSP_PROT_TLS1_1_CLIENT = 0x00000200
enumvarSP_PROT_TLS1_1_SERVER = 0x00000100
enumvarSP_PROT_TLS1_2_CLIENT = 0x00000800
enumvarSP_PROT_TLS1_2_SERVER = 0x00000400
enumvarSP_PROT_TLS1_3_CLIENT = 0x00002000
enumvarSP_PROT_TLS1_3_SERVER = 0x00001000
enumvarSEC_E_OK = 0x00000000
enumvarSEC_I_CONTINUE_NEEDED = 0x00090312
enumvarSEC_E_INCOMPLETE_MESSAGE = 0x80090318
enumvarSEC_I_INCOMPLETE_CREDENTIALS = 0x00090320
enumvarSEC_I_CONTEXT_EXPIRED = 0x00090317
enumvarSEC_E_INTERNAL_ERROR = 0x80090304
enumvarSEC_E_INVALID_HANDLE = 0x80090301
enumvarSEC_E_INVALID_TOKEN = 0x80090308
enumvarSEC_E_CERT_EXPIRED = 0x80090328
enumvarSEC_E_CERT_UNKNOWN = 0x80090327
enumvarSEC_E_UNTRUSTED_ROOT = 0x80090325
enumvarSEC_E_WRONG_PRINCIPAL = 0x80090322
enumvarSECPKG_ATTR_STREAM_SIZES = 4
enumvarSECPKG_ATTR_REMOTE_CERT_CONTEXT = 0x40
enumvarSECPKG_ATTR_APPLICATION_PROTOCOL = 0x5C
enumvarSECBUFFER_SEND_GENERIC_TLS_EXTENSION = 45
enumvarSEC_APPLICATION_PROTOCOL_NEGOTIATION_STATUS_Negotiated = 3
enumvarSecPkgApplicationProtocolNegotiationExt_ALPN = 2
enumvarTLS1_ALPN_EXTENSION = 0x0010
enumvarSOCKET_ERROR = - 1
enumvarWSAEWOULDBLOCK = 10035
enumvarCERT_NAME_SIMPLE_DISPLAY_TYPE = 4
enumvarCERT_NAME_ISSUER_FLAG = 0x00000001
enumvarCERT_STORE_PROV_MEMORY = 2
enumvarCERT_STORE_ADD_ALWAYS = 4
enumvarX509_ASN_ENCODING = 0x00000001
enumvarPKCS_7_ASN_ENCODING = 0x00010000
enumvarCRYPT_STRING_BASE64HEADER = 0x00000000
enumvarCRYPT_STRING_BASE64_ANY = 0x00000006
enumvarPKCS12_NO_PERSIST_KEY = 0x00008000
enumvarCERT_FIND_ANY = 0
enumvarCERT_ENCODING_TYPE = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING
private enumvarTLS_MAX_RECORD_SIZE = 16384

Maximum TLS record size.

private enumvarIO_BUFFER_SIZE = TLS_MAX_RECORD_SIZE + 512

Buffer size for I/O operations.