Skip to content

Commit

Permalink
Log QUIC_TLS_SECRETS on all TestConnections and write to disk on clea…
Browse files Browse the repository at this point in the history
…nup (#4349)

* Log QUIC_TLS_SECRETS on all TestConnections and have option to write to disk on cleanup.

* Implement kernel mode routine to write sslkeylogfile

* Add sslkeylogfile generation to handshake tests.
  • Loading branch information
anrossi committed Aug 28, 2024
1 parent 2f1a7be commit 4faa8d0
Show file tree
Hide file tree
Showing 9 changed files with 491 additions and 5 deletions.
1 change: 1 addition & 0 deletions scripts/run-gtest.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,7 @@ function Start-TestExecutable([String]$Arguments, [String]$OutputDir) {
} else {
$pinfo.FileName = $Path
$pinfo.Arguments = $Arguments
$pinfo.WorkingDirectory = $OutputDir
if (Test-Administrator) {
# Enable WER dump collection.
New-ItemProperty -Path $WerDumpRegPath -Name DumpType -PropertyType DWord -Value 2 -Force | Out-Null
Expand Down
360 changes: 359 additions & 1 deletion src/inc/msquichelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -568,9 +568,352 @@ FreeServerConfiguration(
MsQuicTable->ConfigurationClose(Configuration);
}

#ifdef _KERNEL_MODE
inline
void
WriteSslKeyLogFile(
WriteSslKeyLogFileKernelMode(
_In_z_ const char* FileName,
_In_ QUIC_TLS_SECRETS& TlsSecrets
)
{
WCHAR ConvertedFileName[MAX_PATH + 1] = {0};
char ClientRandomBuffer[(2 * sizeof(QUIC_TLS_SECRETS::ClientRandom)) + 1] = {0};
char TempHexBuffer[(2 * QUIC_TLS_SECRETS_MAX_SECRET_LEN) + 1] = {0};
char TempLogBuffer[sizeof(ClientRandomBuffer) + sizeof(TempHexBuffer) + 32 + 3 + 1] = {0};
UNICODE_STRING FileNameString = {0};
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
HANDLE Handle;
size_t RemainingLengthBytes = 0;
NTSTATUS Status;
ULONG StringLengthBytes = 0;

size_t FileNameLength = strnlen_s(FileName, MAX_PATH + 1);
if (FileNameLength == MAX_PATH + 1) {
goto Error;
}
FileNameLength++;

Status =
RtlUTF8ToUnicodeN(
ConvertedFileName,
sizeof(ConvertedFileName),
&StringLengthBytes,
FileName,
(ULONG) FileNameLength);
if (!NT_SUCCESS(Status)) {
QuicTraceEvent(
LibraryErrorStatus,
"[ lib] ERROR, %u, %s.",
Status,
"Convert string to unicode");
goto Error;
}

FileNameString.Buffer = ConvertedFileName;
FileNameString.Length = (USHORT)StringLengthBytes - sizeof(WCHAR);
FileNameString.MaximumLength = (USHORT)sizeof(ConvertedFileName);

InitializeObjectAttributes(
&ObjectAttributes,
&FileNameString,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL);

Status =
ZwCreateFile(
&Handle,
FILE_APPEND_DATA | SYNCHRONIZE,
&ObjectAttributes,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_OPEN_IF,
FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE,
NULL,
0);
if (!NT_SUCCESS(Status)) {
QuicTraceEvent(
LibraryErrorStatus,
"[ lib] ERROR, %u, %s.",
Status,
"Open sslkeylogfile for append");
goto Error;
}

if (IoStatusBlock.Information == FILE_CREATED) {
CHAR Header[] = "# TLS 1.3 secrets log file, generated by quicinterop\n";
Status =
ZwWriteFile(
Handle,
NULL,
NULL,
NULL,
&IoStatusBlock,
Header,
sizeof(Header) - 1,
NULL,
NULL);
if (!NT_SUCCESS(Status)) {
QuicTraceEvent(
LibraryErrorStatus,
"[ lib] ERROR, %u, %s.",
Status,
"Write header to sslkeylogfile");
goto WriteError;
}
}

if (TlsSecrets.IsSet.ClientRandom) {
EncodeHexBuffer(
TlsSecrets.ClientRandom,
(uint8_t)sizeof(TlsSecrets.ClientRandom),
ClientRandomBuffer);
}

if (TlsSecrets.IsSet.ClientEarlyTrafficSecret) {
EncodeHexBuffer(
TlsSecrets.ClientEarlyTrafficSecret,
TlsSecrets.SecretLength,
TempHexBuffer);

Status =
RtlStringCbPrintfExA(
TempLogBuffer,
sizeof(TempLogBuffer),
NULL,
&RemainingLengthBytes,
0,
"CLIENT_EARLY_TRAFFIC_SECRET %s %s\n",
ClientRandomBuffer,
TempHexBuffer);
if (!NT_SUCCESS(Status)) {
QuicTraceEvent(
LibraryErrorStatus,
"[ lib] ERROR, %u, %s.",
Status,
"Format CLIENT_EARLY_TRAFFIC_SECRET");
goto WriteError;
}

Status =
ZwWriteFile(
Handle,
NULL,
NULL,
NULL,
&IoStatusBlock,
TempLogBuffer,
(ULONG)(sizeof(TempLogBuffer) - RemainingLengthBytes),
NULL,
NULL);
if (!NT_SUCCESS(Status)) {
QuicTraceEvent(
LibraryErrorStatus,
"[ lib] ERROR, %u, %s.",
Status,
"Write CLIENT_EARLY_TRAFFIC_SECRET");
goto WriteError;
}
}

if (TlsSecrets.IsSet.ClientHandshakeTrafficSecret) {
EncodeHexBuffer(
TlsSecrets.ClientHandshakeTrafficSecret,
TlsSecrets.SecretLength,
TempHexBuffer);

Status =
RtlStringCbPrintfExA(
TempLogBuffer,
sizeof(TempLogBuffer),
NULL,
&RemainingLengthBytes,
0,
"CLIENT_HANDSHAKE_TRAFFIC_SECRET %s %s\n",
ClientRandomBuffer,
TempHexBuffer);
if (!NT_SUCCESS(Status)) {
QuicTraceEvent(
LibraryErrorStatus,
"[ lib] ERROR, %u, %s.",
Status,
"Format CLIENT_HANDSHAKE_TRAFFIC_SECRET");
goto WriteError;
}

Status =
ZwWriteFile(
Handle,
NULL,
NULL,
NULL,
&IoStatusBlock,
TempLogBuffer,
(ULONG)(sizeof(TempLogBuffer) - RemainingLengthBytes),
NULL,
NULL);
if (!NT_SUCCESS(Status)) {
QuicTraceEvent(
LibraryErrorStatus,
"[ lib] ERROR, %u, %s.",
Status,
"Write CLIENT_HANDSHAKE_TRAFFIC_SECRET");
goto WriteError;
}
}

if (TlsSecrets.IsSet.ServerHandshakeTrafficSecret) {
EncodeHexBuffer(
TlsSecrets.ServerHandshakeTrafficSecret,
TlsSecrets.SecretLength,
TempHexBuffer);

Status =
RtlStringCbPrintfExA(
TempLogBuffer,
sizeof(TempLogBuffer),
NULL,
&RemainingLengthBytes,
0,
"SERVER_HANDSHAKE_TRAFFIC_SECRET %s %s\n",
ClientRandomBuffer,
TempHexBuffer);
if (!NT_SUCCESS(Status)) {
QuicTraceEvent(
LibraryErrorStatus,
"[ lib] ERROR, %u, %s.",
Status,
"Format SERVER_HANDSHAKE_TRAFFIC_SECRET");
goto WriteError;
}

Status =
ZwWriteFile(
Handle,
NULL,
NULL,
NULL,
&IoStatusBlock,
TempLogBuffer,
(ULONG)(sizeof(TempLogBuffer) - RemainingLengthBytes),
NULL,
NULL);
if (!NT_SUCCESS(Status)) {
QuicTraceEvent(
LibraryErrorStatus,
"[ lib] ERROR, %u, %s.",
Status,
"Write SERVER_HANDSHAKE_TRAFFIC_SECRET");
goto WriteError;
}
}

if (TlsSecrets.IsSet.ClientTrafficSecret0) {
EncodeHexBuffer(
TlsSecrets.ClientTrafficSecret0,
TlsSecrets.SecretLength,
TempHexBuffer);

Status =
RtlStringCbPrintfExA(
TempLogBuffer,
sizeof(TempLogBuffer),
NULL,
&RemainingLengthBytes,
0,
"CLIENT_TRAFFIC_SECRET_0 %s %s\n",
ClientRandomBuffer,
TempHexBuffer);
if (!NT_SUCCESS(Status)) {
QuicTraceEvent(
LibraryErrorStatus,
"[ lib] ERROR, %u, %s.",
Status,
"Format CLIENT_TRAFFIC_SECRET_0");
goto WriteError;
}

Status =
ZwWriteFile(
Handle,
NULL,
NULL,
NULL,
&IoStatusBlock,
TempLogBuffer,
(ULONG)(sizeof(TempLogBuffer) - RemainingLengthBytes),
NULL,
NULL);
if (!NT_SUCCESS(Status)) {
QuicTraceEvent(
LibraryErrorStatus,
"[ lib] ERROR, %u, %s.",
Status,
"Write CLIENT_TRAFFIC_SECRET_0");
goto WriteError;
}
}

if (TlsSecrets.IsSet.ServerTrafficSecret0) {
EncodeHexBuffer(
TlsSecrets.ServerTrafficSecret0,
TlsSecrets.SecretLength,
TempHexBuffer);

Status =
RtlStringCbPrintfExA(
TempLogBuffer,
sizeof(TempLogBuffer),
NULL,
&RemainingLengthBytes,
0,
"SERVER_TRAFFIC_SECRET_0 %s %s\n",
ClientRandomBuffer,
TempHexBuffer);
if (!NT_SUCCESS(Status)) {
QuicTraceEvent(
LibraryErrorStatus,
"[ lib] ERROR, %u, %s.",
Status,
"Format SERVER_TRAFFIC_SECRET_0");
goto WriteError;
}

Status =
ZwWriteFile(
Handle,
NULL,
NULL,
NULL,
&IoStatusBlock,
TempLogBuffer,
(ULONG)(sizeof(TempLogBuffer) - RemainingLengthBytes),
NULL,
NULL);
if (!NT_SUCCESS(Status)) {
QuicTraceEvent(
LibraryErrorStatus,
"[ lib] ERROR, %u, %s.",
Status,
"Write SERVER_TRAFFIC_SECRET_0");
goto WriteError;
}
}

WriteError:
ZwClose(Handle);

Error:
return;
}
#endif

inline
void
WriteSslKeyLogFileUserMode(
_In_z_ const char* FileName,
_In_ QUIC_TLS_SECRETS& TlsSecrets
)
Expand Down Expand Up @@ -662,4 +1005,19 @@ WriteSslKeyLogFile(
fclose(File);
}


inline
void
WriteSslKeyLogFile(
_In_z_ const char* FileName,
_In_ QUIC_TLS_SECRETS& TlsSecrets
)
{
#ifdef _KERNEL_MODE
WriteSslKeyLogFileKernelMode(FileName, TlsSecrets);
#else
WriteSslKeyLogFileUserMode(FileName, TlsSecrets);
#endif
}

#endif // defined(__cplusplus)
Loading

0 comments on commit 4faa8d0

Please sign in to comment.