Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Support for Custom TLS Alert in Certificate Validation Failure #3391

Merged
merged 6 commits into from
Feb 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/api/ConnectionCertificateValidationComplete.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ _IRQL_requires_max_(DISPATCH_LEVEL)
QUIC_STATUS
(QUIC_API * QUIC_CONNECTION_COMP_CERT_FN)(
_In_ _Pre_defensive_ HQUIC Connection,
_In_ BOOLEAN Result
_In_ BOOLEAN Result,
_In_ QUIC_TLS_ALERT_CODES TlsAlert
);
```

Expand Down
1 change: 1 addition & 0 deletions scripts/generate-dotnet.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ Invoke-Expression "$ToolExe $FullArgs"
-replace " QUIC_EXECUTION_PROFILE_TYPE_", " " `
-replace " QUIC_EXECUTION_PROFILE_", " " `
-replace " QUIC_LOAD_BALANCING_", " " `
-replace " QUIC_TLS_ALERT_CODE_", " " `
-replace " QUIC_CREDENTIAL_TYPE_", " " `
-replace " QUIC_CREDENTIAL_FLAG_", " " `
-replace " QUIC_ALLOWED_CIPHER_SUITE_", " " `
Expand Down
9 changes: 8 additions & 1 deletion src/core/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -1727,7 +1727,8 @@ QUIC_STATUS
QUIC_API
MsQuicConnectionCertificateValidationComplete(
_In_ _Pre_defensive_ HQUIC Handle,
_In_ BOOLEAN Result
_In_ BOOLEAN Result,
_In_ QUIC_TLS_ALERT_CODES TlsAlert
)
{
QUIC_STATUS Status;
Expand Down Expand Up @@ -1756,6 +1757,11 @@ MsQuicConnectionCertificateValidationComplete(

QUIC_CONN_VERIFY(Connection, !Connection->State.Freed);

if (!Result && TlsAlert > QUIC_TLS_ALERT_CODE_MAX) {
Status = QUIC_STATUS_INVALID_PARAMETER;
goto Error;
}

Oper = QuicOperationAlloc(Connection->Worker, QUIC_OPER_TYPE_API_CALL);
if (Oper == NULL) {
Status = QUIC_STATUS_OUT_OF_MEMORY;
Expand All @@ -1768,6 +1774,7 @@ MsQuicConnectionCertificateValidationComplete(
}

Oper->API_CALL.Context->Type = QUIC_API_TYPE_CONN_COMPLETE_CERTIFICATE_VALIDATION;
Oper->API_CALL.Context->CONN_COMPLETE_CERTIFICATE_VALIDATION.TlsAlert = TlsAlert;
Oper->API_CALL.Context->CONN_COMPLETE_CERTIFICATE_VALIDATION.Result = Result;

//
Expand Down
3 changes: 2 additions & 1 deletion src/core/api.h
Original file line number Diff line number Diff line change
Expand Up @@ -275,5 +275,6 @@ QUIC_STATUS
QUIC_API
MsQuicConnectionCertificateValidationComplete(
_In_ _Pre_defensive_ HQUIC Handle,
_In_ BOOLEAN Result
_In_ BOOLEAN Result,
_In_ QUIC_TLS_ALERT_CODES TlsAlert
nibanks marked this conversation as resolved.
Show resolved Hide resolved
);
8 changes: 6 additions & 2 deletions src/core/connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -6468,7 +6468,10 @@ QuicConnParamSet(
break;
}

QuicCryptoCustomCertValidationComplete(&Connection->Crypto, *(BOOLEAN*)Buffer);
QuicCryptoCustomCertValidationComplete(
&Connection->Crypto,
*(BOOLEAN*)Buffer,
QUIC_TLS_ALERT_CODE_BAD_CERTIFICATE);
Status = QUIC_STATUS_SUCCESS;
break;

Expand Down Expand Up @@ -7319,7 +7322,8 @@ QuicConnProcessApiOperation(
case QUIC_API_TYPE_CONN_COMPLETE_CERTIFICATE_VALIDATION:
QuicCryptoCustomCertValidationComplete(
&Connection->Crypto,
ApiCtx->CONN_COMPLETE_CERTIFICATE_VALIDATION.Result);
ApiCtx->CONN_COMPLETE_CERTIFICATE_VALIDATION.Result,
ApiCtx->CONN_COMPLETE_CERTIFICATE_VALIDATION.TlsAlert);
break;

case QUIC_API_TYPE_STRM_CLOSE:
Expand Down
6 changes: 4 additions & 2 deletions src/core/crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -1700,7 +1700,8 @@ _IRQL_requires_max_(PASSIVE_LEVEL)
void
QuicCryptoCustomCertValidationComplete(
_In_ QUIC_CRYPTO* Crypto,
_In_ BOOLEAN Result
_In_ BOOLEAN Result,
_In_ QUIC_TLS_ALERT_CODES TlsAlert
)
{
if (!Crypto->CertValidationPending) {
Expand All @@ -1720,9 +1721,10 @@ QuicCryptoCustomCertValidationComplete(
"[conn][%p] ERROR, %s.",
QuicCryptoGetConnection(Crypto),
"Custom cert validation failed.");
CXPLAT_DBG_ASSERT(TlsAlert <= QUIC_TLS_ALERT_CODE_MAX);
QuicConnTransportError(
QuicCryptoGetConnection(Crypto),
QUIC_ERROR_CRYPTO_ERROR(0xFF & CXPLAT_TLS_ALERT_CODE_BAD_CERTIFICATE));
QUIC_ERROR_CRYPTO_ERROR(0xFF & TlsAlert));
}
Crypto->PendingValidationBufferLength = 0;
}
Expand Down
3 changes: 2 additions & 1 deletion src/core/crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,8 @@ _IRQL_requires_max_(PASSIVE_LEVEL)
void
QuicCryptoCustomCertValidationComplete(
_In_ QUIC_CRYPTO* Crypto,
_In_ BOOLEAN Result
_In_ BOOLEAN Result,
_In_ QUIC_TLS_ALERT_CODES TlsAlert
);

//
Expand Down
1 change: 1 addition & 0 deletions src/core/operation.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ typedef struct QUIC_API_CONTEXT {
} CONN_COMPLETE_RESUMPTION_TICKET_VALIDATION;

struct {
QUIC_TLS_ALERT_CODES TlsAlert;
BOOLEAN Result;
} CONN_COMPLETE_CERTIFICATE_VALIDATION;

Expand Down
21 changes: 20 additions & 1 deletion src/cs/lib/msquic_generated.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,25 @@ internal enum QUIC_LOAD_BALANCING_MODE
COUNT,
}

internal enum QUIC_TLS_ALERT_CODES
{
SUCCESS = 0xFFFF,
nibanks marked this conversation as resolved.
Show resolved Hide resolved
UNEXPECTED_MESSAGE = 10,
BAD_CERTIFICATE = 42,
UNSUPPORTED_CERTIFICATE = 43,
CERTIFICATE_REVOKED = 44,
CERTIFICATE_EXPIRED = 45,
CERTIFICATE_UNKNOWN = 46,
ILLEGAL_PARAMETER = 47,
UNKNOWN_CA = 48,
ACCESS_DENIED = 49,
INSUFFICIENT_SECURITY = 71,
INTERNAL_ERROR = 80,
USER_CANCELED = 90,
CERTIFICATE_REQUIRED = 116,
MAX = 255,
}

internal enum QUIC_CREDENTIAL_TYPE
{
NONE,
Expand Down Expand Up @@ -2853,7 +2872,7 @@ internal unsafe partial struct QUIC_API_TABLE
internal delegate* unmanaged[Cdecl]<QUIC_HANDLE*, byte, int> ConnectionResumptionTicketValidationComplete;

[NativeTypeName("QUIC_CONNECTION_COMP_CERT_FN")]
internal delegate* unmanaged[Cdecl]<QUIC_HANDLE*, byte, int> ConnectionCertificateValidationComplete;
internal delegate* unmanaged[Cdecl]<QUIC_HANDLE*, byte, QUIC_TLS_ALERT_CODES, int> ConnectionCertificateValidationComplete;
}

internal static unsafe partial class MsQuic
Expand Down
24 changes: 22 additions & 2 deletions src/inc/msquic.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,24 @@ typedef enum QUIC_LOAD_BALANCING_MODE {
// MUST BE LAST
} QUIC_LOAD_BALANCING_MODE;

typedef enum QUIC_TLS_ALERT_CODES {
QUIC_TLS_ALERT_CODE_SUCCESS = 0xFFFF, // Not a real TlsAlert
QUIC_TLS_ALERT_CODE_UNEXPECTED_MESSAGE = 10,
QUIC_TLS_ALERT_CODE_BAD_CERTIFICATE = 42,
QUIC_TLS_ALERT_CODE_UNSUPPORTED_CERTIFICATE = 43,
QUIC_TLS_ALERT_CODE_CERTIFICATE_REVOKED = 44,
QUIC_TLS_ALERT_CODE_CERTIFICATE_EXPIRED = 45,
QUIC_TLS_ALERT_CODE_CERTIFICATE_UNKNOWN = 46,
QUIC_TLS_ALERT_CODE_ILLEGAL_PARAMETER = 47,
QUIC_TLS_ALERT_CODE_UNKNOWN_CA = 48,
QUIC_TLS_ALERT_CODE_ACCESS_DENIED = 49,
QUIC_TLS_ALERT_CODE_INSUFFICIENT_SECURITY = 71,
QUIC_TLS_ALERT_CODE_INTERNAL_ERROR = 80,
QUIC_TLS_ALERT_CODE_USER_CANCELED = 90,
QUIC_TLS_ALERT_CODE_CERTIFICATE_REQUIRED = 116,
QUIC_TLS_ALERT_CODE_MAX = 255,
} QUIC_TLS_ALERT_CODES;

typedef enum QUIC_CREDENTIAL_TYPE {
QUIC_CREDENTIAL_TYPE_NONE,
QUIC_CREDENTIAL_TYPE_CERTIFICATE_HASH,
Expand Down Expand Up @@ -1291,14 +1309,16 @@ QUIC_STATUS
//
// Uses the QUIC (client) handle to complete certificate validation.
// This must be called after client app handles certificate validation
// and then return QUIC_STATUS_PENDING.
// and then return QUIC_STATUS_PENDING. The TlsAlert value is ignored if Result
// equals TRUE (recommend just pass QUIC_TLS_ALERT_CODE_SUCCESS).
//
typedef
_IRQL_requires_max_(DISPATCH_LEVEL)
QUIC_STATUS
(QUIC_API * QUIC_CONNECTION_COMP_CERT_FN)(
_In_ _Pre_defensive_ HQUIC Connection,
_In_ BOOLEAN Result
_In_ BOOLEAN Result,
_In_ QUIC_TLS_ALERT_CODES TlsAlert
);

//
Expand Down
20 changes: 20 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,23 @@ pub type LoadBalancingMode = u32;
pub const LOAD_BALANCING_DISABLED: LoadBalancingMode = 0;
pub const LOAD_BALANCING_SERVER_ID_IP: LoadBalancingMode = 1;

/// Represents different TLS alert codes.
pub type TlsAlertCode = u32;
pub const TLS_ALERT_CODE_SUCCESS: TlsAlertCode = 0xffff;
pub const TLS_ALERT_CODE_UNEXPECTED_MESSAGE: TlsAlertCode = 10;
pub const TLS_ALERT_CODE_BAD_CERTIFICATE: TlsAlertCode = 42;
pub const TLS_ALERT_CODE_UNSUPPORTED_CERTIFICATE: TlsAlertCode = 43;
pub const TLS_ALERT_CODE_CERTIFICATE_REVOKED: TlsAlertCode = 44;
pub const TLS_ALERT_CODE_CERTIFICATE_EXPIRED: TlsAlertCode = 45;
pub const TLS_ALERT_CODE_CERTIFICATE_UNKNOWN: TlsAlertCode = 46;
pub const TLS_ALERT_CODE_ILLEGAL_PARAMETER: TlsAlertCode = 47;
pub const TLS_ALERT_CODE_UNKNOWN_CA: TlsAlertCode = 48;
pub const TLS_ALERT_CODE_ACCESS_DENIED: TlsAlertCode = 49;
pub const TLS_ALERT_CODE_INSUFFICIENT_SECURITY: TlsAlertCode = 71;
pub const TLS_ALERT_CODE_INTERNAL_ERROR: TlsAlertCode = 80;
pub const TLS_ALERT_CODE_USER_CANCELED: TlsAlertCode = 90;
pub const TLS_ALERT_CODE_CERTIFICATE_REQUIRED: TlsAlertCode = 116;

/// Type of credentials used for a connection.
pub type CredentialType = u32;
pub const CREDENTIAL_TYPE_NONE: CredentialType = 0;
Expand Down Expand Up @@ -1085,6 +1102,7 @@ struct ApiTable {
certificate_validation_complete: extern "C" fn(
connection: Handle,
result: BOOLEAN,
tls_alert: TlsAlertCode
) -> u32,
}

Expand Down Expand Up @@ -1546,11 +1564,13 @@ impl Connection {
pub fn certificate_validation_complete(
&self,
result: BOOLEAN,
tls_alert: TlsAlertCode,
) {
let status = unsafe {
((*self.table).certificate_validation_complete)(
self.handle,
result,
tls_alert,
)
};
if Status::failed(status) {
Expand Down
6 changes: 4 additions & 2 deletions src/test/lib/TestConnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -746,14 +746,16 @@ TestConnection::SetResumptionTicket(

QUIC_STATUS
TestConnection::SetCustomValidationResult(
bool AcceptCert
bool AcceptCert,
QUIC_TLS_ALERT_CODES TlsAlert
)
{
BOOLEAN Result = AcceptCert ? TRUE : FALSE;
return
MsQuic->ConnectionCertificateValidationComplete(
QuicConnection,
Result);
Result,
TlsAlert);
}

QUIC_STATUS
Expand Down
2 changes: 1 addition & 1 deletion src/test/lib/TestConnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ class TestConnection

QUIC_STATUS SetResumptionTicket(const QUIC_BUFFER* ResumptionTicket) const;

QUIC_STATUS SetCustomValidationResult(bool AcceptCert);
QUIC_STATUS SetCustomValidationResult(bool AcceptCert, QUIC_TLS_ALERT_CODES TlsAlert = QUIC_TLS_ALERT_CODE_BAD_CERTIFICATE);

QUIC_STATUS SetCustomTicketValidationResult(bool AcceptTicket);

Expand Down
2 changes: 1 addition & 1 deletion src/tools/spin/spinquic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -885,7 +885,7 @@ void Spin(Gbs& Gb, LockableVector<HQUIC>& Connections, std::vector<HQUIC>* Liste
case SpinQuicAPICallCompleteCertificateValidation: {
auto Connection = Connections.TryGetRandom();
BAIL_ON_NULL_CONNECTION(Connection);
MsQuic.ConnectionCertificateValidationComplete(Connection, GetRandom(2) == 0);
MsQuic.ConnectionCertificateValidationComplete(Connection, GetRandom(2) == 0, QUIC_TLS_ALERT_CODE_BAD_CERTIFICATE);
nibanks marked this conversation as resolved.
Show resolved Hide resolved
break;
}
default:
Expand Down