diff --git a/src/generated/linux/cert_capi.c.clog.h b/src/generated/linux/cert_capi.c.clog.h index dd7479d3ad..c31ded5a2f 100644 --- a/src/generated/linux/cert_capi.c.clog.h +++ b/src/generated/linux/cert_capi.c.clog.h @@ -38,10 +38,10 @@ extern "C" { CertCapiVerifiedChain, "CertVerifyChain: %S 0x%x, result=0x%x", ServerName, - IgnoreFlags, + CredFlags, Status); // arg2 = arg2 = ServerName -// arg3 = arg3 = IgnoreFlags +// arg3 = arg3 = CredFlags // arg4 = arg4 = Status ----------------------------------------------------------*/ #define _clog_5_ARGS_TRACE_CertCapiVerifiedChain(uniqueId, encoded_arg_string, arg2, arg3, arg4)\ diff --git a/src/generated/linux/cert_capi.c.clog.h.lttng.h b/src/generated/linux/cert_capi.c.clog.h.lttng.h index 2f4fd76fd0..6a0706c922 100644 --- a/src/generated/linux/cert_capi.c.clog.h.lttng.h +++ b/src/generated/linux/cert_capi.c.clog.h.lttng.h @@ -8,10 +8,10 @@ CertCapiVerifiedChain, "CertVerifyChain: %S 0x%x, result=0x%x", ServerName, - IgnoreFlags, + CredFlags, Status); // arg2 = arg2 = ServerName -// arg3 = arg3 = IgnoreFlags +// arg3 = arg3 = CredFlags // arg4 = arg4 = Status ----------------------------------------------------------*/ TRACEPOINT_EVENT(CLOG_CERT_CAPI_C, CertCapiVerifiedChain, diff --git a/src/generated/linux/cert_capi_openssl.c.clog.h b/src/generated/linux/cert_capi_openssl.c.clog.h index 251f82a165..e551d84968 100644 --- a/src/generated/linux/cert_capi_openssl.c.clog.h +++ b/src/generated/linux/cert_capi_openssl.c.clog.h @@ -314,6 +314,138 @@ tracepoint(CLOG_CERT_CAPI_OPENSSL_C, AllocFailure , arg2, arg3);\ +#ifndef _clog_4_ARGS_TRACE_LibraryErrorStatus + + + +/*---------------------------------------------------------- +// Decoder Ring for LibraryErrorStatus +// [ lib] ERROR, %u, %s. +// QuicTraceEvent( + LibraryErrorStatus, + "[ lib] ERROR, %u, %s.", + Type, + "Unsupported Type passed to CxPlatGetTestCertificate"); +// arg2 = arg2 = Type +// arg3 = arg3 = "Unsupported Type passed to CxPlatGetTestCertificate" +----------------------------------------------------------*/ +#define _clog_4_ARGS_TRACE_LibraryErrorStatus(uniqueId, encoded_arg_string, arg2, arg3)\ + +#endif + + + + +#ifndef _clog_4_ARGS_TRACE_LibraryErrorStatus + + + +/*---------------------------------------------------------- +// Decoder Ring for LibraryErrorStatus +// [ lib] ERROR, %u, %s. +// QuicTraceEvent( + LibraryErrorStatus, + "[ lib] ERROR, %u, %s.", + (unsigned int)QUIC_STATUS_INVALID_PARAMETER, + "NULL CertHash passed to CxPlatGetTestCertificate"); +// arg2 = arg2 = (unsigned int)QUIC_STATUS_INVALID_PARAMETER +// arg3 = arg3 = "NULL CertHash passed to CxPlatGetTestCertificate" +----------------------------------------------------------*/ +#define _clog_4_ARGS_TRACE_LibraryErrorStatus(uniqueId, encoded_arg_string, arg2, arg3)\ + +#endif + + + + +#ifndef _clog_4_ARGS_TRACE_LibraryErrorStatus + + + +/*---------------------------------------------------------- +// Decoder Ring for LibraryErrorStatus +// [ lib] ERROR, %u, %s. +// QuicTraceEvent( + LibraryErrorStatus, + "[ lib] ERROR, %u, %s.", + (unsigned int)QUIC_STATUS_INVALID_PARAMETER, + "NULL CertHashStore passed to CxPlatGetTestCertificate"); +// arg2 = arg2 = (unsigned int)QUIC_STATUS_INVALID_PARAMETER +// arg3 = arg3 = "NULL CertHashStore passed to CxPlatGetTestCertificate" +----------------------------------------------------------*/ +#define _clog_4_ARGS_TRACE_LibraryErrorStatus(uniqueId, encoded_arg_string, arg2, arg3)\ + +#endif + + + + +#ifndef _clog_4_ARGS_TRACE_LibraryErrorStatus + + + +/*---------------------------------------------------------- +// Decoder Ring for LibraryErrorStatus +// [ lib] ERROR, %u, %s. +// QuicTraceEvent( + LibraryErrorStatus, + "[ lib] ERROR, %u, %s.", + (unsigned int)QUIC_STATUS_INVALID_PARAMETER, + "NULL Principal passed to CxPlatGetTestCertificate"); +// arg2 = arg2 = (unsigned int)QUIC_STATUS_INVALID_PARAMETER +// arg3 = arg3 = "NULL Principal passed to CxPlatGetTestCertificate" +----------------------------------------------------------*/ +#define _clog_4_ARGS_TRACE_LibraryErrorStatus(uniqueId, encoded_arg_string, arg2, arg3)\ + +#endif + + + + +#ifndef _clog_4_ARGS_TRACE_LibraryErrorStatus + + + +/*---------------------------------------------------------- +// Decoder Ring for LibraryErrorStatus +// [ lib] ERROR, %u, %s. +// QuicTraceEvent( + LibraryErrorStatus, + "[ lib] ERROR, %u, %s.", + CredType, + "Unsupported CredType passed to CxPlatGetTestCertificate"); +// arg2 = arg2 = CredType +// arg3 = arg3 = "Unsupported CredType passed to CxPlatGetTestCertificate" +----------------------------------------------------------*/ +#define _clog_4_ARGS_TRACE_LibraryErrorStatus(uniqueId, encoded_arg_string, arg2, arg3)\ + +#endif + + + + +#ifndef _clog_4_ARGS_TRACE_LibraryErrorStatus + + + +/*---------------------------------------------------------- +// Decoder Ring for LibraryErrorStatus +// [ lib] ERROR, %u, %s. +// QuicTraceEvent( + LibraryErrorStatus, + "[ lib] ERROR, %u, %s.", + GetLastError(), + "CertOpenStore failed"); +// arg2 = arg2 = GetLastError() +// arg3 = arg3 = "CertOpenStore failed" +----------------------------------------------------------*/ +#define _clog_4_ARGS_TRACE_LibraryErrorStatus(uniqueId, encoded_arg_string, arg2, arg3)\ + +#endif + + + + #ifdef __cplusplus } #endif diff --git a/src/inc/quic_cert.h b/src/inc/quic_cert.h index 274e821ea8..a624844ee1 100644 --- a/src/inc/quic_cert.h +++ b/src/inc/quic_cert.h @@ -82,7 +82,7 @@ CxPlatCertValidateChain( _In_ const QUIC_CERTIFICATE* Certificate, _In_opt_z_ const char* Host, _In_ uint32_t CertFlags, - _In_ uint32_t IgnoreFlags, + _In_ uint32_t CredFlags, _Out_opt_ uint32_t* ValidationError ); diff --git a/src/platform/cert_capi.c b/src/platform/cert_capi.c index 6fd20e2436..8ea0894225 100644 --- a/src/platform/cert_capi.c +++ b/src/platform/cert_capi.c @@ -796,7 +796,7 @@ DWORD CxPlatCertVerifyCertChainPolicy( _In_ PCCERT_CHAIN_CONTEXT ChainContext, _In_opt_ PWSTR ServerName, - _In_ ULONG IgnoreFlags + _In_ uint32_t CredFlags ) { DWORD Status = NO_ERROR; @@ -807,9 +807,10 @@ CxPlatCertVerifyCertChainPolicy( memset(&HttpsPolicy, 0, sizeof(HTTPSPolicyCallbackData)); HttpsPolicy.cbStruct = sizeof(HTTPSPolicyCallbackData); - HttpsPolicy.dwAuthType = AUTHTYPE_SERVER; + HttpsPolicy.dwAuthType = + (CredFlags & QUIC_CREDENTIAL_FLAG_CLIENT) ? AUTHTYPE_SERVER : AUTHTYPE_CLIENT; HttpsPolicy.fdwChecks = 0; - HttpsPolicy.pwszServerName = ServerName; + HttpsPolicy.pwszServerName = (CredFlags & QUIC_CREDENTIAL_FLAG_CLIENT) ? ServerName : NULL; memset(&PolicyPara, 0, sizeof(PolicyPara)); PolicyPara.cbSize = sizeof(PolicyPara); @@ -832,10 +833,10 @@ CxPlatCertVerifyCertChainPolicy( goto Exit; } else if (PolicyStatus.dwError == CRYPT_E_NO_REVOCATION_CHECK && - (IgnoreFlags & QUIC_CREDENTIAL_FLAG_IGNORE_NO_REVOCATION_CHECK)) { + (CredFlags & QUIC_CREDENTIAL_FLAG_IGNORE_NO_REVOCATION_CHECK)) { Status = NO_ERROR; } else if (PolicyStatus.dwError == CRYPT_E_REVOCATION_OFFLINE && - (IgnoreFlags & QUIC_CREDENTIAL_FLAG_IGNORE_REVOCATION_OFFLINE)) { + (CredFlags & QUIC_CREDENTIAL_FLAG_IGNORE_REVOCATION_OFFLINE)) { Status = NO_ERROR; } else if (PolicyStatus.dwError != NO_ERROR) { @@ -854,7 +855,7 @@ CxPlatCertVerifyCertChainPolicy( CertCapiVerifiedChain, "CertVerifyChain: %S 0x%x, result=0x%x", ServerName, - IgnoreFlags, + CredFlags, Status); return Status; @@ -866,7 +867,7 @@ CxPlatCertValidateChain( _In_ const QUIC_CERTIFICATE* Certificate, _In_opt_z_ PCSTR Host, _In_ uint32_t CertFlags, - _In_ uint32_t IgnoreFlags, + _In_ uint32_t CredFlags, _Out_opt_ uint32_t* ValidationError ) { @@ -879,12 +880,16 @@ CxPlatCertValidateChain( CERT_CHAIN_PARA ChainPara; - static const LPSTR UsageOids[] = { + static const LPSTR ServerUsageOids[] = { szOID_PKIX_KP_SERVER_AUTH, szOID_SERVER_GATED_CRYPTO, szOID_SGC_NETSCAPE }; + static const LPSTR ClientUsageOids[] = { + szOID_PKIX_KP_CLIENT_AUTH + }; + if (ValidationError != NULL) { *ValidationError = NO_ERROR; } @@ -892,8 +897,10 @@ CxPlatCertValidateChain( memset(&ChainPara, 0, sizeof(ChainPara)); ChainPara.cbSize = sizeof(ChainPara); ChainPara.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR; - ChainPara.RequestedUsage.Usage.cUsageIdentifier = ARRAYSIZE(UsageOids); - ChainPara.RequestedUsage.Usage.rgpszUsageIdentifier = (LPSTR*)UsageOids; + ChainPara.RequestedUsage.Usage.cUsageIdentifier = + (CredFlags & QUIC_CREDENTIAL_FLAG_CLIENT) ? ARRAYSIZE(ServerUsageOids) : ARRAYSIZE(ClientUsageOids); + ChainPara.RequestedUsage.Usage.rgpszUsageIdentifier = + (CredFlags & QUIC_CREDENTIAL_FLAG_CLIENT) ? (LPSTR*)ServerUsageOids : (LPSTR*)ClientUsageOids; if (!CertGetCertificateChain( NULL, @@ -933,7 +940,7 @@ CxPlatCertValidateChain( CxPlatCertVerifyCertChainPolicy( ChainContext, ServerName, - IgnoreFlags); + CredFlags); Result = NO_ERROR == Error; diff --git a/src/platform/cert_capi_openssl.c b/src/platform/cert_capi_openssl.c index 938f5ee56f..d5e3089a00 100644 --- a/src/platform/cert_capi_openssl.c +++ b/src/platform/cert_capi_openssl.c @@ -14,6 +14,7 @@ --*/ +#define QUIC_TEST_APIS 1 #include "platform_internal.h" #define OPENSSL_SUPPRESS_DEPRECATED 1 // For hmac.h, which was deprecated in 3.0 @@ -35,6 +36,22 @@ #include #include "msquic.h" +#define CXPLAT_CERT_CREATION_EVENT_NAME L"MsQuicCertEvent" +#define CXPLAT_CERT_CREATION_EVENT_WAIT 10000 +#define CXPLAT_CERTIFICATE_TEST_FRIENDLY_NAME L"MsQuicTestCert2" +#define CXPLAT_CERTIFICATE_TEST_CLIENT_FRIENDLY_NAME L"MsQuicTestClientCert" +#define CXPLAT_KEY_CONTAINER_NAME L"MsQuicSelfSignKey2" +#define CXPLAT_KEY_SIZE 2048 + +#define CXPLAT_TEST_CERT_VALID_SERVER_FRIENDLY_NAME L"MsQuicTestServer" +#define CXPLAT_TEST_CERT_VALID_CLIENT_FRIENDLY_NAME L"MsQuicTestClient" +#define CXPLAT_TEST_CERT_EXPIRED_SERVER_FRIENDLY_NAME L"MsQuicTestExpiredServer" +#define CXPLAT_TEST_CERT_EXPIRED_CLIENT_FRIENDLY_NAME L"MsQuicTestExpiredClient" +#define CXPLAT_TEST_CERT_VALID_SERVER_SUBJECT_NAME "MsQuicTestServer" +#define CXPLAT_TEST_CERT_VALID_CLIENT_SUBJECT_NAME "MsQuicTestClient" +#define CXPLAT_TEST_CERT_EXPIRED_SERVER_SUBJECT_NAME "MsQuicTestExpiredServer" +#define CXPLAT_TEST_CERT_EXPIRED_CLIENT_SUBJECT_NAME "MsQuicTestExpiredClient" + _Success_(return != FALSE) BOOLEAN CxPlatTlsVerifyCertificate( @@ -87,15 +104,12 @@ CxPlatTlsVerifyCertificate( CertFlags |= CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT; } - uint32_t IgnoreFlags = - CredFlags & (QUIC_CREDENTIAL_FLAG_IGNORE_REVOCATION_OFFLINE | QUIC_CREDENTIAL_FLAG_IGNORE_NO_REVOCATION_CHECK); - Result = CxPlatCertValidateChain( CertContext, SNI, CertFlags, - IgnoreFlags, + CredFlags, PlatformVerificationError); Exit: @@ -349,3 +363,187 @@ CxPlatTlsExtractPrivateKey( return Status; } + +_Success_(return != NULL) +PCCERT_CONTEXT +FindCertificate( + _In_ HCERTSTORE CertStore, + _In_ BOOLEAN IncludeInvalid, + _In_z_ const wchar_t* SearchFriendlyName, + _Out_writes_all_(20) uint8_t* CertHash + ); + +_Success_(return == TRUE) +BOOLEAN +CxPlatGetTestCertificateWindows( + _In_ CXPLAT_TEST_CERT_TYPE Type, + _In_ CXPLAT_SELF_SIGN_CERT_TYPE StoreType, + _In_ uint32_t CredType, + _Out_ QUIC_CREDENTIAL_CONFIG* Params, + _When_(CredType == QUIC_CREDENTIAL_TYPE_CERTIFICATE_HASH, _Out_) + _When_(CredType != QUIC_CREDENTIAL_TYPE_CERTIFICATE_HASH, _Reserved_) + QUIC_CERTIFICATE_HASH* CertHash, + _When_(CredType == QUIC_CREDENTIAL_TYPE_CERTIFICATE_HASH_STORE, _Out_) + _When_(CredType != QUIC_CREDENTIAL_TYPE_CERTIFICATE_HASH_STORE, _Reserved_) + QUIC_CERTIFICATE_HASH_STORE* CertHashStore, + _When_(CredType == QUIC_CREDENTIAL_TYPE_NONE, _Out_z_bytecap_(100)) + _When_(CredType != QUIC_CREDENTIAL_TYPE_NONE, _Reserved_) + char Principal[100] + ) +{ + BOOLEAN Success = FALSE; + PCCERT_CONTEXT Cert = NULL; + const wchar_t* FriendlyName = NULL; + const char* SubjectName = NULL; + + switch (Type) { + case CXPLAT_TEST_CERT_VALID_SERVER: + FriendlyName = CXPLAT_TEST_CERT_VALID_SERVER_FRIENDLY_NAME; + SubjectName = CXPLAT_TEST_CERT_VALID_SERVER_SUBJECT_NAME; + break; + case CXPLAT_TEST_CERT_VALID_CLIENT: + FriendlyName = CXPLAT_TEST_CERT_VALID_CLIENT_FRIENDLY_NAME; + SubjectName = CXPLAT_TEST_CERT_VALID_CLIENT_SUBJECT_NAME; + break; + case CXPLAT_TEST_CERT_EXPIRED_SERVER: + FriendlyName = CXPLAT_TEST_CERT_EXPIRED_SERVER_FRIENDLY_NAME; + SubjectName = CXPLAT_TEST_CERT_EXPIRED_SERVER_SUBJECT_NAME; + break; + case CXPLAT_TEST_CERT_EXPIRED_CLIENT: + FriendlyName = CXPLAT_TEST_CERT_EXPIRED_CLIENT_FRIENDLY_NAME; + SubjectName = CXPLAT_TEST_CERT_EXPIRED_CLIENT_SUBJECT_NAME; + break; + default: + QuicTraceEvent( + LibraryErrorStatus, + "[ lib] ERROR, %u, %s.", + Type, + "Unsupported Type passed to CxPlatGetTestCertificate"); + return FALSE; + } + + switch (CredType) { + case QUIC_CREDENTIAL_TYPE_CERTIFICATE_HASH: + if (CertHash == NULL) { + QuicTraceEvent( + LibraryErrorStatus, + "[ lib] ERROR, %u, %s.", + (unsigned int)QUIC_STATUS_INVALID_PARAMETER, + "NULL CertHash passed to CxPlatGetTestCertificate"); + return FALSE; + } + break; + case QUIC_CREDENTIAL_TYPE_CERTIFICATE_HASH_STORE: + if (CertHashStore == NULL) { + QuicTraceEvent( + LibraryErrorStatus, + "[ lib] ERROR, %u, %s.", + (unsigned int)QUIC_STATUS_INVALID_PARAMETER, + "NULL CertHashStore passed to CxPlatGetTestCertificate"); + return FALSE; + } + break; + case QUIC_CREDENTIAL_TYPE_NONE: + if (Principal == NULL) { + QuicTraceEvent( + LibraryErrorStatus, + "[ lib] ERROR, %u, %s.", + (unsigned int)QUIC_STATUS_INVALID_PARAMETER, + "NULL Principal passed to CxPlatGetTestCertificate"); + return FALSE; + } + break; + case QUIC_CREDENTIAL_TYPE_CERTIFICATE_CONTEXT: + break; + default: + QuicTraceEvent( + LibraryErrorStatus, + "[ lib] ERROR, %u, %s.", + CredType, + "Unsupported CredType passed to CxPlatGetTestCertificate"); + return FALSE; + } + + CxPlatZeroMemory(Params, sizeof(*Params)); + + HCERTSTORE CertStore = + CertOpenStore( + CERT_STORE_PROV_SYSTEM_A, + 0, + 0, + StoreType == CXPLAT_SELF_SIGN_CERT_USER ? + CERT_SYSTEM_STORE_CURRENT_USER : + CERT_SYSTEM_STORE_LOCAL_MACHINE, + "MY"); + if (CertStore == NULL) { + QuicTraceEvent( + LibraryErrorStatus, + "[ lib] ERROR, %u, %s.", + GetLastError(), + "CertOpenStore failed"); + goto Done; + } + uint8_t CertHashBytes[20]; + + Cert = FindCertificate( + CertStore, + TRUE, + FriendlyName, + CertHashBytes); + + if (Cert == NULL) { + goto Done; + } + + switch (CredType) { + case QUIC_CREDENTIAL_TYPE_CERTIFICATE_HASH: + Params->Type = QUIC_CREDENTIAL_TYPE_CERTIFICATE_HASH; + Params->CertificateHash = CertHash; + CxPlatCopyMemory(CertHash->ShaHash, CertHashBytes, sizeof(CertHash->ShaHash)); + break; + case QUIC_CREDENTIAL_TYPE_CERTIFICATE_HASH_STORE: + Params->Type = QUIC_CREDENTIAL_TYPE_CERTIFICATE_HASH_STORE; + Params->CertificateHashStore = CertHashStore; + CxPlatCopyMemory(CertHashStore->ShaHash, CertHashBytes, sizeof(CertHashStore->ShaHash)); + strncpy_s(CertHashStore->StoreName, sizeof(CertHashStore->StoreName), "MY", sizeof("MY")); + CertHashStore->Flags = + StoreType == CXPLAT_SELF_SIGN_CERT_USER ? + QUIC_CERTIFICATE_HASH_STORE_FLAG_NONE : + QUIC_CERTIFICATE_HASH_STORE_FLAG_MACHINE_STORE; + break; + case QUIC_CREDENTIAL_TYPE_NONE: + // + // Assume Principal in use here + // + Params->Type = QUIC_CREDENTIAL_TYPE_NONE; + Params->Principal = Principal; + strncpy_s(Principal, 100, SubjectName, 100); + break; + case QUIC_CREDENTIAL_TYPE_CERTIFICATE_CONTEXT: + Params->Type = QUIC_CREDENTIAL_TYPE_CERTIFICATE_CONTEXT; + Params->CertificateContext = (QUIC_CERTIFICATE*)Cert; + Cert = NULL; + break; + } + Success = TRUE; +Done: + if (Cert != NULL) { + CertFreeCertificateContext(Cert); + } + if (CertStore != NULL) { + CertCloseStore(CertStore, 0); + } + + return Success; +} + +_IRQL_requires_max_(PASSIVE_LEVEL) +void +CxPlatFreeTestCertWindows( + _In_ QUIC_CREDENTIAL_CONFIG* Params + ) +{ + if (Params->Type == QUIC_CREDENTIAL_TYPE_CERTIFICATE_CONTEXT) { + CertFreeCertificateContext((PCCERT_CONTEXT)Params->CertificateContext); + } +} diff --git a/src/platform/darwin_openssl.c b/src/platform/darwin_openssl.c index 163989e210..525a67ae12 100644 --- a/src/platform/darwin_openssl.c +++ b/src/platform/darwin_openssl.c @@ -123,7 +123,10 @@ CxPlatTlsVerifyCertificate( goto Exit; } - SSLPolicy = SecPolicyCreateSSL(TRUE, SNIString); + SSLPolicy = + SecPolicyCreateSSL( + (CredFlags & QUIC_CREDENTIAL_FLAG_CLIENT) ? TRUE : FALSE, + SNIString); if (SSLPolicy == NULL) { QuicTraceEvent( LibraryError, diff --git a/src/platform/selfsign_openssl.c b/src/platform/selfsign_openssl.c index af9a6e444d..5f5b4c2e2e 100644 --- a/src/platform/selfsign_openssl.c +++ b/src/platform/selfsign_openssl.c @@ -459,6 +459,17 @@ CxPlatGetTestCertificate( char Principal[100] ) { +#ifdef _WIN32 + return + CxPlatGetTestCertificateWindows( + Type, + StoreType, + CredType, + Params, + CertHash, + CertHashStore, + Principal); +#else // Not yet supported UNREFERENCED_PARAMETER(Type); UNREFERENCED_PARAMETER(StoreType); @@ -468,6 +479,7 @@ CxPlatGetTestCertificate( UNREFERENCED_PARAMETER(CertHashStore); UNREFERENCED_PARAMETER(Principal); return FALSE; +#endif } _IRQL_requires_max_(PASSIVE_LEVEL) @@ -476,7 +488,11 @@ CxPlatFreeTestCert( _In_ QUIC_CREDENTIAL_CONFIG* Params ) { +#ifdef _WIN32 + CxPlatFreeTestCertWindows(Params); +#else UNREFERENCED_PARAMETER(Params); +#endif } _IRQL_requires_max_(PASSIVE_LEVEL)