new API for async certificate validation (#3318)

* new API for async certificate validation

* Fix func pointer assignment

* generate dotnet
This commit is contained in:
Daiki AMINAKA 2022-12-31 19:09:43 -08:00 коммит произвёл GitHub
Родитель da33894d0c
Коммит 97616f7601
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
13 изменённых файлов: 184 добавлений и 4 удалений

Просмотреть файл

@ -0,0 +1,40 @@
ConnectionCertificateValidationComplete function
======
Uses the QUIC (client) handle to complete resumption ticket validation. This must be called after client app handles certificate validation and then return QUIC_STATUS_PENDING.
# Syntax
```C
typedef
_IRQL_requires_max_(DISPATCH_LEVEL)
QUIC_STATUS
(QUIC_API * QUIC_CONNECTION_COMP_CERT_FN)(
_In_ _Pre_defensive_ HQUIC Connection,
_In_ BOOLEAN Result
);
```
# Parameters
`Connection`
The valid handle to an open connection object.
`Result`
Ticket validation result.
# Return Value
The function returns a [QUIC_STATUS](QUIC_STATUS.md). The app may use `QUIC_FAILED` or `QUIC_SUCCEEDED` to determine if the function failed or succeeded.
# Remarks
- Available from v2.2
# See Also
[ConnectionOpen](ConnectionStart.md)<br>
[ConnectionClose](ConnectionClose.md)<br>
[ConnectionShutdown](ConnectionShutdown.md)<br>

Просмотреть файл

@ -1721,3 +1721,77 @@ Error:
return Status;
}
_IRQL_requires_max_(DISPATCH_LEVEL)
QUIC_STATUS
QUIC_API
MsQuicConnectionCertificateValidationComplete(
_In_ _Pre_defensive_ HQUIC Handle,
_In_ BOOLEAN Result
)
{
QUIC_STATUS Status;
QUIC_CONNECTION* Connection;
QUIC_OPERATION* Oper;
QuicTraceEvent(
ApiEnter,
"[ api] Enter %u (%p).",
QUIC_TRACE_API_CONNECTION_COMPLETE_CERTIFICATE_VALIDATION,
Handle);
if (IS_CONN_HANDLE(Handle)) {
#pragma prefast(suppress: __WARNING_25024, "Pointer cast already validated.")
Connection = (QUIC_CONNECTION*)Handle;
} else if (IS_STREAM_HANDLE(Handle)) {
#pragma prefast(suppress: __WARNING_25024, "Pointer cast already validated.")
QUIC_STREAM* Stream = (QUIC_STREAM*)Handle;
CXPLAT_TEL_ASSERT(!Stream->Flags.HandleClosed);
CXPLAT_TEL_ASSERT(!Stream->Flags.Freed);
Connection = Stream->Connection;
} else {
Status = QUIC_STATUS_INVALID_PARAMETER;
goto Error;
}
QUIC_CONN_VERIFY(Connection, !Connection->State.Freed);
if (QuicConnIsServer(Connection)) {
Status = QUIC_STATUS_INVALID_PARAMETER;
goto Error;
}
if (Connection->Crypto.TlsState.HandshakeComplete) {
Status = QUIC_STATUS_INVALID_STATE;
goto Error;
}
Oper = QuicOperationAlloc(Connection->Worker, QUIC_OPER_TYPE_API_CALL);
if (Oper == NULL) {
Status = QUIC_STATUS_OUT_OF_MEMORY;
QuicTraceEvent(
AllocFailure,
"Allocation of '%s' failed. (%llu bytes)",
"CONN_COMPLETE_CERTIFICATE_VALIDATION operation",
0);
goto Error;
}
Oper->API_CALL.Context->Type = QUIC_API_TYPE_CONN_COMPLETE_CERTIFICATE_VALIDATION;
Oper->API_CALL.Context->CONN_COMPLETE_CERTIFICATE_VALIDATION.Result = Result;
//
// Queue the operation but don't wait for the completion.
//
QuicConnQueueOper(Connection, Oper);
Status = QUIC_STATUS_PENDING;
Error:
QuicTraceEvent(
ApiExitStatus,
"[ api] Exit %u",
Status);
return Status;
}

Просмотреть файл

@ -269,3 +269,11 @@ MsQuicConnectionResumptionTicketValidationComplete(
_In_ _Pre_defensive_ HQUIC Handle,
_In_ BOOLEAN Result
);
_IRQL_requires_max_(DISPATCH_LEVEL)
QUIC_STATUS
QUIC_API
MsQuicConnectionCertificateValidationComplete(
_In_ _Pre_defensive_ HQUIC Handle,
_In_ BOOLEAN Result
);

Просмотреть файл

@ -7313,6 +7313,13 @@ QuicConnProcessApiOperation(
ApiCtx->CONN_COMPLETE_RESUMPTION_TICKET_VALIDATION.Result);
break;
case QUIC_API_TYPE_CONN_COMPLETE_CERTIFICATE_VALIDATION:
CXPLAT_DBG_ASSERT(QuicConnIsClient(Connection));
QuicCryptoCustomCertValidationComplete(
&Connection->Crypto,
ApiCtx->CONN_COMPLETE_CERTIFICATE_VALIDATION.Result);
break;
case QUIC_API_TYPE_STRM_CLOSE:
QuicStreamClose(ApiCtx->STRM_CLOSE.Stream);
break;

Просмотреть файл

@ -1669,6 +1669,7 @@ MsQuicOpenVersion(
Api->ConnectionSetConfiguration = MsQuicConnectionSetConfiguration;
Api->ConnectionSendResumptionTicket = MsQuicConnectionSendResumptionTicket;
Api->ConnectionResumptionTicketValidationComplete = MsQuicConnectionResumptionTicketValidationComplete;
Api->ConnectionCertificateValidationComplete = MsQuicConnectionCertificateValidationComplete;
Api->StreamOpen = MsQuicStreamOpen;
Api->StreamClose = MsQuicStreamClose;

Просмотреть файл

@ -62,6 +62,7 @@ typedef enum QUIC_API_TYPE {
QUIC_API_TYPE_DATAGRAM_SEND,
QUIC_API_TYPE_CONN_COMPLETE_RESUMPTION_TICKET_VALIDATION,
QUIC_API_TYPE_CONN_COMPLETE_CERTIFICATE_VALIDATION,
} QUIC_API_TYPE;
@ -119,6 +120,10 @@ typedef struct QUIC_API_CONTEXT {
BOOLEAN Result;
} CONN_COMPLETE_RESUMPTION_TICKET_VALIDATION;
struct {
BOOLEAN Result;
} CONN_COMPLETE_CERTIFICATE_VALIDATION;
struct {
QUIC_STREAM_OPEN_FLAGS Flags;
QUIC_STREAM_CALLBACK_HANDLER Handler;

Просмотреть файл

@ -2755,6 +2755,9 @@ namespace Microsoft.Quic
[NativeTypeName("QUIC_CONNECTION_COMP_RESUMPTION_FN")]
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 static unsafe partial class MsQuic

Просмотреть файл

@ -1279,6 +1279,19 @@ QUIC_STATUS
_In_ BOOLEAN Result
);
//
// 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.
//
typedef
_IRQL_requires_max_(DISPATCH_LEVEL)
QUIC_STATUS
(QUIC_API * QUIC_CONNECTION_COMP_CERT_FN)(
_In_ _Pre_defensive_ HQUIC Connection,
_In_ BOOLEAN Result
);
//
// Streams
//
@ -1507,6 +1520,7 @@ typedef struct QUIC_API_TABLE {
QUIC_DATAGRAM_SEND_FN DatagramSend;
QUIC_CONNECTION_COMP_RESUMPTION_FN ConnectionResumptionTicketValidationComplete; // Available from v2.2
QUIC_CONNECTION_COMP_CERT_FN ConnectionCertificateValidationComplete; // Available from v2.2
} QUIC_API_TABLE;

Просмотреть файл

@ -89,6 +89,7 @@ typedef enum QUIC_TRACE_API_TYPE {
QUIC_TRACE_API_CONNECTION_SET_CONFIGURATION,
QUIC_TRACE_API_CONNECTION_SEND_RESUMPTION_TICKET,
QUIC_TRACE_API_CONNECTION_COMPLETE_RESUMPTION_TICKET_VALIDATION,
QUIC_TRACE_API_CONNECTION_COMPLETE_CERTIFICATE_VALIDATION,
QUIC_TRACE_API_STREAM_OPEN,
QUIC_TRACE_API_STREAM_CLOSE,
QUIC_TRACE_API_STREAM_START,

Просмотреть файл

@ -1082,6 +1082,10 @@ struct ApiTable {
connection: Handle,
result: BOOLEAN,
) -> u32,
certificate_validation_complete: extern "C" fn(
connection: Handle,
result: BOOLEAN,
) -> u32,
}
#[link(name = "msquic")]
@ -1538,6 +1542,21 @@ impl Connection {
panic!("ticket validation completion failure 0x{:x}", status);
}
}
pub fn certificate_validation_complete(
&self,
result: BOOLEAN,
) {
let status = unsafe {
((*self.table).certificate_validation_complete)(
self.handle,
result,
)
};
if Status::failed(status) {
panic!("ticket validation completion failure 0x{:x}", status);
}
}
}
impl Drop for Connection {

Просмотреть файл

@ -993,6 +993,7 @@ typedef enum QUIC_API_TYPE {
QUIC_API_TYPE_DATAGRAM_SEND,
QUIC_API_TYPE_CONN_COMPLETE_RESUMPTION_TICKET_VALIDATION,
QUIC_API_TYPE_CONN_COMPLETE_CERTIFICATE_VALIDATION,
} QUIC_API_TYPE;
@ -1036,6 +1037,8 @@ struct ApiCall : Struct {
return "API_TYPE_DATAGRAM_SEND";
case QUIC_API_TYPE_CONN_COMPLETE_RESUMPTION_TICKET_VALIDATION:
return "API_TYPE_CONN_COMPLETE_RESUMPTION_TICKET_VALIDATION";
case QUIC_API_TYPE_CONN_COMPLETE_CERTIFICATE_VALIDATION:
return "API_TYPE_CONN_COMPLETE_CERTIFICATE_VALIDATION";
default:
return "INVALID API";
}

Просмотреть файл

@ -751,11 +751,9 @@ TestConnection::SetCustomValidationResult(
{
BOOLEAN Result = AcceptCert ? TRUE : FALSE;
return
MsQuic->SetParam(
MsQuic->ConnectionCertificateValidationComplete(
QuicConnection,
QUIC_PARAM_CONN_PEER_CERTIFICATE_VALID,
sizeof(Result),
&Result);
Result);
}
QUIC_STATUS

Просмотреть файл

@ -258,6 +258,7 @@ typedef enum {
SpinQuicAPICallGetParamStream,
SpinQuicAPICallDatagramSend,
SpinQuicAPICallCompleteTicketValidation,
SpinQuicAPICallCompleteCertificateValidation,
SpinQuicAPICallStreamReceiveSetEnabled,
SpinQuicAPICallStreamReceiveComplete,
SpinQuicAPICallCount // Always the last element
@ -881,6 +882,12 @@ void Spin(Gbs& Gb, LockableVector<HQUIC>& Connections, std::vector<HQUIC>* Liste
MsQuic.ConnectionResumptionTicketValidationComplete(Connection, GetRandom(2) == 0);
break;
}
case SpinQuicAPICallCompleteCertificateValidation: {
auto Connection = Connections.TryGetRandom();
BAIL_ON_NULL_CONNECTION(Connection);
MsQuic.ConnectionCertificateValidationComplete(Connection, GetRandom(2) == 0);
break;
}
default:
break;
}