From e2e2a902f4c2d3c83e55f4f5e03e77f31ec97e46 Mon Sep 17 00:00:00 2001 From: Anthony Rossi <41394064+anrossi@users.noreply.github.com> Date: Mon, 24 Feb 2020 14:06:36 -0800 Subject: [PATCH] Add platform unit tests (#162) Adds testing of the platform layers, and fixes an issue in the OpenSSL hash calculation discovered by these tests. Fixes #93 Co-authored-by: Nick Banks --- .azure/azure-pipelines.ci.yml | 2 +- CMakeLists.txt | 9 + scripts/build.ps1 | 18 +- scripts/test.ps1 | 4 + src/core/inline.c | 11 - src/inc/quic_platform_linux.h | 2 +- src/platform/inline.c | 11 + src/platform/tls_openssl.c | 133 +- src/platform/unittest/CMakeLists.txt | 37 + src/platform/unittest/CryptTest.cpp | 428 +++-- src/platform/unittest/DataPathTest.cpp | 700 ++++---- src/platform/unittest/TlsTest.cpp | 783 ++++----- src/platform/unittest/linux/DataPathTest.c | 1013 ----------- src/platform/unittest/linux/TlsTest.c | 1847 -------------------- src/platform/unittest/main.cpp | 44 +- src/platform/unittest/main.h | 21 + 16 files changed, 1083 insertions(+), 3980 deletions(-) create mode 100644 src/platform/unittest/CMakeLists.txt delete mode 100644 src/platform/unittest/linux/DataPathTest.c delete mode 100644 src/platform/unittest/linux/TlsTest.c create mode 100644 src/platform/unittest/main.h diff --git a/.azure/azure-pipelines.ci.yml b/.azure/azure-pipelines.ci.yml index 583e34f73e17..26e05d7a42ed 100644 --- a/.azure/azure-pipelines.ci.yml +++ b/.azure/azure-pipelines.ci.yml @@ -124,7 +124,7 @@ stages: arch: x64 tls: mitls logProfile: Full.Light - extraArgs: -Filter -*Unreachable/0 + extraArgs: -Filter -*Unreachable/0:CryptTest/CryptTest.Encryption/2 # OpenSSL tests are broken because they can't load on a different # machine from where they were built. # - template: ./templates/run-bvt.yml diff --git a/CMakeLists.txt b/CMakeLists.txt index 4e749c7d97df..d3123529ed7a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -87,6 +87,10 @@ if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") set(QUIC_COMMON_FLAGS "${QUIC_COMMON_FLAGS} -DQUIC_DISABLE_0RTT") endif() + if(QUIC_TLS STREQUAL "stub") + set(QUIC_COMMON_FLAGS "${QUIC_COMMON_FLAGS} -DQUIC_TLS_STUB") + endif() + if(QUIC_SANITIZE_ADDRESS) message(STATUS "Address sanitizer unsupported on this platform.") endif() @@ -135,6 +139,10 @@ else() set(QUIC_COMMON_FLAGS "${QUIC_COMMON_FLAGS} -fsanitize=address -fno-omit-frame-pointer -Wno-maybe-uninitialized -O0 -Og -g") endif() + if(QUIC_TLS STREQUAL "stub") + set(QUIC_COMMON_FLAGS "${QUIC_COMMON_FLAGS} -DQUIC_TLS_STUB") + endif() + set(QUIC_C_FLAGS "${QUIC_COMMON_FLAGS}") set(QUIC_CXX_FLAGS "${QUIC_COMMON_FLAGS} --std=c++17 -g -Wno-reorder -Wno-sign-compare -Wno-format") endif() @@ -196,6 +204,7 @@ if(QUIC_BUILD_TEST) add_subdirectory(submodules/googletest) add_subdirectory(src/core/unittest) + add_subdirectory(src/platform/unittest) add_subdirectory(src/test/lib) add_subdirectory(src/test/bin) endif() diff --git a/scripts/build.ps1 b/scripts/build.ps1 index 9baad73e3349..135450a54f13 100644 --- a/scripts/build.ps1 +++ b/scripts/build.ps1 @@ -36,6 +36,9 @@ This script provides helpers for building msquic. .PARAMETER InstallOutput Installs the build output to the current machine. +.PARAMETER Parallel + Enables CMake to build in parallel, where possible. + .EXAMPLE build.ps1 -InstallDependencies @@ -82,7 +85,10 @@ param ( [switch]$Clean = $false, [Parameter(Mandatory = $false)] - [switch]$InstallOutput = $false + [switch]$InstallOutput = $false, + + [Parameter(Mandatory = $false)] + [int32]$Parallel = -1 ) Set-StrictMode -Version 'Latest' @@ -195,16 +201,16 @@ function CMake-Generate { # Uses cmake to generate the build configuration files. function CMake-Build { $Arguments = "--build ." + if ($Parallel -gt 0) { + $Arguments += " --parallel $($Parallel)" + } elseif ($Parallel -eq 0) { + $Arguments += " --parallel" + } if ($IsWindows) { $Arguments += " --config " + $Config } CMake-Execute $Arguments - - if ($Tls -eq "openssl") { - $OpensslDir = Join-Path $BuildDir "openssl" "lib" "*" - Copy-Item $OpensslDir -Destination $ArtifactsDir -Recurse - } } # Installs all the build output. diff --git a/scripts/test.ps1 b/scripts/test.ps1 index 5f0f2ab98ece..8bfe0b54a161 100644 --- a/scripts/test.ps1 +++ b/scripts/test.ps1 @@ -134,12 +134,15 @@ $RunTest = Join-Path $RootDir ".azure/scripts/run-gtest.ps1" # Path to the msquictest exectuable. $MsQuicTest = $null $MsQuicCoreTest = $null +$MsQuicPlatTest = $null if ($IsWindows) { $MsQuicTest = Join-Path $RootDir "\artifacts\windows\$($Arch)_$($Config)_$($Tls)\msquictest.exe" $MsQuicCoreTest = Join-Path $RootDir "\artifacts\windows\$($Arch)_$($Config)_$($Tls)\msquiccoretest.exe" + $MsQuicPlatTest = Join-Path $RootDir "\artifacts\windows\$($Arch)_$($Config)_$($Tls)\msquicplatformtest.exe" } else { $MsQuicTest = Join-Path $RootDir "/artifacts/linux/$($Arch)_$($Config)_$($Tls)/msquictest" $MsQuicCoreTest = Join-Path $RootDir "/artifacts/linux/$($Arch)_$($Config)_$($Tls)/msquiccoretest" + $MsQuicPlatTest = Join-Path $RootDir "/artifacts/linux/$($Arch)_$($Config)_$($Tls)/msquicplatformtest" } # Build up all the arguments to pass to the Powershell script. @@ -178,4 +181,5 @@ if ($CompressOutput) { # Run the script. Invoke-Expression ($RunTest + " -Path $($MsQuicCoreTest) " + $TestArguments) +Invoke-Expression ($RunTest + " -Path $($MsQuicPlatTest) " + $TestArguments) Invoke-Expression ($RunTest + " -Path $($MsQuicTest) " + $TestArguments) diff --git a/src/core/inline.c b/src/core/inline.c index 27e5edfecb7e..61d6edfa606d 100644 --- a/src/core/inline.c +++ b/src/core/inline.c @@ -160,11 +160,6 @@ QuicKeyTypeToEncryptLevel( QUIC_PACKET_KEY_TYPE KeyType ); -uint16_t -QuicKeyLength( - QUIC_AEAD_TYPE Type - ); - QUIC_PACKET_KEY_TYPE QuicPacketTypeToKeyType( uint8_t PacketType @@ -612,9 +607,3 @@ int64_t QuicTimeEpochMs64( void ); - -void -QuicTraceStubVarArgs( - _In_ const void* Fmt, - ... - ); diff --git a/src/inc/quic_platform_linux.h b/src/inc/quic_platform_linux.h index 6864439f8b9d..ec5ea9c24318 100644 --- a/src/inc/quic_platform_linux.h +++ b/src/inc/quic_platform_linux.h @@ -94,7 +94,7 @@ QuicPlatformUninitialize( #define UNREFERENCED_PARAMETER(P) (P) -#define QuicNetByteSwapShort(x) htons((x) +#define QuicNetByteSwapShort(x) htons((x)) #define SIZEOF_STRUCT_MEMBER(StructType, StructMember) sizeof(((StructType *)0)->StructMember) #define TYPEOF_STRUCT_MEMBER(StructType, StructMember) typeof(((StructType *)0)->StructMember) diff --git a/src/platform/inline.c b/src/platform/inline.c index 61f6f228352b..f0d67f5046d5 100644 --- a/src/platform/inline.c +++ b/src/platform/inline.c @@ -135,6 +135,11 @@ QuicHashLength( QUIC_HASH_TYPE Type ); +uint16_t +QuicKeyLength( + QUIC_AEAD_TYPE Type + ); + uint64_t QuicTimeDiff64( _In_ uint64_t T1, @@ -158,3 +163,9 @@ QuicTimeAtOrBefore32( _In_ uint32_t T1, _In_ uint32_t T2 ); + +void +QuicTraceStubVarArgs( + _In_ const void* Fmt, + ... + ); diff --git a/src/platform/tls_openssl.c b/src/platform/tls_openssl.c index 1f5e6612bbae..5afdfbe3a32d 100644 --- a/src/platform/tls_openssl.c +++ b/src/platform/tls_openssl.c @@ -399,18 +399,6 @@ QuicTlsHeaderMask( _In_ const EVP_CIPHER *Aead ); -static -BOOLEAN -QuicTlsHash( - _Out_writes_bytes_(OutputBufferLen) uint8_t *OutputBuffer, - _In_ size_t OutputBufferLen, - _In_reads_bytes_(SecretLen) const uint8_t *Secret, - _In_ size_t SecretLen, - _In_reads_bytes_(SaltLen) const uint8_t *Salt, - _In_ size_t SaltLen, - _In_ QUIC_HASH *Hash - ); - static void QuicTlsSecConfigDelete( @@ -1992,16 +1980,50 @@ QuicHashCompute( _Out_writes_all_(OutputLength) uint8_t* const Output ) { - return - QuicTlsHash( - Output, - OutputLength, - Input, - InputLength, - Hash->Salt, - Hash->SaltLength, - Hash) != 0 ? - QUIC_STATUS_SUCCESS : QUIC_STATUS_INTERNAL_ERROR; + QUIC_STATUS Status = QUIC_STATUS_SUCCESS; + EVP_MD_CTX* HashContext = NULL; + EVP_PKEY* HmacKey = NULL; + + HashContext = EVP_MD_CTX_create(); + if (HashContext == NULL) { + Status = QUIC_STATUS_OUT_OF_MEMORY; + goto Error; + } + + HmacKey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, Hash->Salt, Hash->SaltLength); + if (HmacKey == NULL) { + Status = QUIC_STATUS_OUT_OF_MEMORY; + goto Error; + } + + if (!EVP_DigestSignInit(HashContext, NULL, Hash->Md, NULL, HmacKey)) { + Status = QUIC_STATUS_INTERNAL_ERROR; + goto Error; + } + + if (!EVP_DigestSignUpdate(HashContext, Input, InputLength)) { + Status = QUIC_STATUS_INTERNAL_ERROR; + goto Error; + } + + size_t ActualOutputSize = OutputLength; + if (!EVP_DigestSignFinal(HashContext, Output, &ActualOutputSize)) { + Status = QUIC_STATUS_INTERNAL_ERROR; + goto Error; + } + + QUIC_FRE_ASSERT(ActualOutputSize == OutputLength); + +Error: + if (HashContext != NULL) { + EVP_MD_CTX_free(HashContext); + } + + if (HmacKey != NULL) { + EVP_PKEY_free(HmacKey); + } + + return Status; } static @@ -2886,70 +2908,3 @@ QuicTlsHeaderMask( return Ret; } - -static -BOOLEAN -QuicTlsHash( - _Out_writes_bytes_(OutputBufferLen) uint8_t *OutputBuffer, - _In_ size_t OutputBufferLen, - _In_reads_bytes_(SecretLen) const uint8_t *Secret, - _In_ size_t SecretLen, - _In_reads_bytes_(SaltLen) const uint8_t *Salt, - _In_ size_t SaltLen, - _In_ QUIC_HASH *Hash - ) -{ - BOOLEAN Ret = TRUE; - EVP_PKEY_CTX *KeyCtx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL); - - if (KeyCtx == NULL) { - QuicTraceLogError("[ tls] KeyCtx alloc failed."); - Ret = FALSE; - goto Exit; - } - - if (EVP_PKEY_derive_init(KeyCtx) != 1) { - QuicTraceLogError("[ tls] EVP_PKEY_derive_init failed."); - Ret = FALSE; - goto Exit; - } - - if (EVP_PKEY_CTX_hkdf_mode(KeyCtx, EVP_PKEY_HKDEF_MODE_EXPAND_ONLY) != 1) { - QuicTraceLogError("[ tls] EVP_PKEY_CTX_hkdf_mode failed."); - Ret = FALSE; - goto Exit; - } - - if (EVP_PKEY_CTX_set_hkdf_md(KeyCtx, Hash->Md) != 1) { - QuicTraceLogError("[ tls] EVP_PKEY_CTX_set_hkdf_md failed."); - Ret = FALSE; - goto Exit; - } - - if (EVP_PKEY_CTX_set1_hkdf_salt(KeyCtx, Salt, SaltLen) != 1) { - QuicTraceLogError("[ tls] EVP_PKEY_CTX_set1_hkdf_salt failed."); - Ret = FALSE; - goto Exit; - } - - if (EVP_PKEY_CTX_set1_hkdf_key(KeyCtx, Secret, SecretLen) != 1) { - QuicTraceLogError("[ tls] EVP_PKEY_CTX_set1_hkdf_key failed."); - Ret = FALSE; - goto Exit; - } - - if (EVP_PKEY_derive(KeyCtx, OutputBuffer, &OutputBufferLen) != 1) { - QuicTraceLogError("[ tls] EVP_PKEY_derive failed."); - Ret = FALSE; - goto Exit; - } - -Exit: - - if (KeyCtx != NULL) { - EVP_PKEY_CTX_free(KeyCtx); - KeyCtx = NULL; - } - - return Ret; -} diff --git a/src/platform/unittest/CMakeLists.txt b/src/platform/unittest/CMakeLists.txt new file mode 100644 index 000000000000..7911d475a808 --- /dev/null +++ b/src/platform/unittest/CMakeLists.txt @@ -0,0 +1,37 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +include_directories(${CMAKE_SOURCE_DIR}/src/platform) +include_directories(${CMAKE_SOURCE_DIR}/submodules/googletest/googletest/include) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${QUIC_CXX_FLAGS}") + +set( + SOURCES + main.cpp + CryptTest.cpp + DataPathTest.cpp + # StorageTest.cpp + TlsTest.cpp +) + +add_executable(msquicplatformtest ${SOURCES}) + +if(WIN32) + target_link_libraries(msquicplatformtest ntdll ws2_32 bcrypt) +endif() + +if(QUIC_TLS STREQUAL "schannel") + target_link_libraries(msquicplatformtest schannel ncrypt crypt32) +elseif(QUIC_TLS STREQUAL "openssl") + add_dependencies(msquicplatformtest OpenSSL) + target_link_libraries(msquicplatformtest + ${QUIC_BUILD_DIR}/openssl/lib/libcrypto.so + ${QUIC_BUILD_DIR}/openssl/lib/libssl.so) +elseif(QUIC_TLS STREQUAL "mitls") + target_link_libraries(msquicplatformtest kremlib evercrypt mitls quiccrypto ncrypt crypt32) +endif() + +target_link_libraries(msquicplatformtest platform gtest) + +add_test(msquicplatformtest msquicplatformtest) diff --git a/src/platform/unittest/CryptTest.cpp b/src/platform/unittest/CryptTest.cpp index b18c95d7b217..92eb52d773e4 100644 --- a/src/platform/unittest/CryptTest.cpp +++ b/src/platform/unittest/CryptTest.cpp @@ -5,27 +5,17 @@ --*/ -#include "quic_platform.h" +#include "main.h" #include "msquic.h" #include "quic_tls.h" -#define LOG_ONLY_FAILURES -#define INLINE_TEST_METHOD_MARKUP -#include -#include - #include "msquichelper.h" -#include "quic_trace.h" #ifdef QUIC_LOGS_WPP #include "crypttest.tmh" #endif -using namespace WEX::Common; -using namespace WEX::Logging; -using namespace WEX::TestExecution; - -#define VERIFY_QUIC_SUCCESS(result, ...) VERIFY_ARE_EQUAL(QUIC_STATUS_SUCCESS, result, __VA_ARGS__) +#ifndef QUIC_TLS_STUB void LogTestBuffer( @@ -38,17 +28,13 @@ LogTestBuffer( for (size_t i = 0; i < Length; ++i) { sprintf_s(&Str[i*2], 3, "%.2X", Buffer[i]); } - Log::Comment(String().Format(L"%S[%u]: %S", Name, (uint32_t)Length, Str)); + std::cout << Name << "[" << Length << "]: " << Str << std::endl; delete [] Str; } -struct CryptTest : public WEX::TestClass +struct CryptTest : public ::testing::TestWithParam { - CryptTest() { } - ~CryptTest() { } - - BEGIN_TEST_CLASS(CryptTest) - END_TEST_CLASS() + protected: struct QuicKey { @@ -56,11 +42,11 @@ struct CryptTest : public WEX::TestClass QuicKey(QUIC_AEAD_TYPE AeadType, const uint8_t* const RawKey) : Ptr(NULL) { QUIC_STATUS Status = QuicKeyCreate(AeadType, RawKey, &Ptr); if (Status == QUIC_STATUS_NOT_SUPPORTED) { - Log::Comment(L"AEAD Type unsupported"); + GTEST_SKIP_NO_RETURN_(": AEAD Type unsupported"); return; } - VERIFY_QUIC_SUCCESS(Status); - VERIFY_IS_NOT_NULL(Ptr); + EXPECT_EQ(Status, QUIC_STATUS_SUCCESS); + EXPECT_NE(Ptr, nullptr); } ~QuicKey() { @@ -125,11 +111,11 @@ struct CryptTest : public WEX::TestClass ) : Ptr(NULL) { QUIC_STATUS Status = QuicHashCreate(HashType, Salt, SaltLength, &Ptr); if (Status == QUIC_STATUS_NOT_SUPPORTED) { - Log::Comment(L"HASH Type unsupported"); + GTEST_SKIP_NO_RETURN_(": HASH Type unsupported"); return; } - VERIFY_QUIC_SUCCESS(Status); - VERIFY_IS_NOT_NULL(Ptr); + EXPECT_EQ(Status, QUIC_STATUS_SUCCESS); + EXPECT_NE(Ptr, nullptr); } ~QuicHash() { @@ -179,219 +165,215 @@ struct CryptTest : public WEX::TestClass delete [] Data; } }; +}; - TEST_METHOD(WellKnownClientInitial) - { - const QuicBuffer InitialSalt("c3eef712c72ebb5a11a7d2432bb46365bef9f502"); - const QuicBuffer ConnectionID("8394c8f03e515708"); - - const QuicBuffer InitialPacketHeader("c3ff000017088394c8f03e5157080000449e00000002"); - const QuicBuffer InitialPacketPayload("060040c4010000c003036660261ff947cea49cce6cfad687f457cf1b14531ba14131a0e8f309a1d0b9c4000006130113031302010000910000000b0009000006736572766572ff01000100000a00140012001d0017001800190100010101020103010400230000003300260024001d00204cfdfcd178b784bf328cae793b136f2aedce005ff183d7bb1495207236647037002b0003020304000d0020001e040305030603020308040805080604010501060102010402050206020202002d00020101001c00024001"); - const uint64_t InitialPacketNumber = 2; - - uint8_t PacketBuffer[1200] = {0}; - memcpy(PacketBuffer, InitialPacketHeader.Data, InitialPacketHeader.Length); - memcpy(PacketBuffer + InitialPacketHeader.Length, InitialPacketPayload.Data, InitialPacketPayload.Length); - - QUIC_TLS_PROCESS_STATE State = {0}; - VERIFY_QUIC_SUCCESS( - QuicPacketKeyCreateInitial( - FALSE, - InitialSalt.Data, - (uint8_t)ConnectionID.Length, - ConnectionID.Data, - &State.ReadKeys[QUIC_PACKET_KEY_INITIAL], - &State.WriteKeys[QUIC_PACKET_KEY_INITIAL])); - - uint8_t Iv[QUIC_IV_LENGTH]; - QuicCryptoCombineIvAndPacketNumber(State.WriteKeys[0]->Iv, (uint8_t*) &InitialPacketNumber, Iv); - - VERIFY_QUIC_SUCCESS( - QuicEncrypt( - State.WriteKeys[0]->PacketKey, - Iv, - InitialPacketHeader.Length, - PacketBuffer, - sizeof(PacketBuffer) - InitialPacketHeader.Length, - PacketBuffer + InitialPacketHeader.Length)); - - const QuicBuffer ExpectedSample("535064a4268a0d9d7b1c9d250ae35516"); - //LogTestBuffer("ExpectedSample", ExpectedSample.Data, ExpectedSample.Length); - //LogTestBuffer(" ActualSample", PacketBuffer + InitialPacketHeader.Length, ExpectedSample.Length); - VERIFY_ARE_EQUAL(0, memcmp(ExpectedSample.Data, PacketBuffer + InitialPacketHeader.Length, ExpectedSample.Length)); - - uint8_t HpMask[16]; - VERIFY_QUIC_SUCCESS( - QuicHpComputeMask( - State.WriteKeys[0]->HeaderKey, - 1, - PacketBuffer + InitialPacketHeader.Length, - HpMask)); - - const QuicBuffer ExpectedHpMask("833b343aaa"); - //LogTestBuffer("ExpectedHpMask", ExpectedHpMask.Data, ExpectedHpMask.Length); - //LogTestBuffer(" ActualHpMask", HpMask, ExpectedHpMask.Length); - VERIFY_ARE_EQUAL(0, memcmp(ExpectedHpMask.Data, HpMask, ExpectedHpMask.Length)); - - PacketBuffer[0] ^= HpMask[0] & 0x0F; - for (uint8_t i = 1; i < 5; ++i) { - PacketBuffer[17 + i] ^= HpMask[i]; - } - - const QuicBuffer ExpectedHeader("c0ff000017088394c8f03e5157080000449e3b343aa8"); - //LogTestBuffer("ExpectedHeader", ExpectedHeader.Data, ExpectedHeader.Length); - //LogTestBuffer(" ActualHeader", PacketBuffer, ExpectedHeader.Length); - VERIFY_ARE_EQUAL(0, memcmp(ExpectedHeader.Data, PacketBuffer, ExpectedHeader.Length)); - - const QuicBuffer EncryptedPacket("c0ff000017088394c8f03e5157080000449e3b343aa8535064a4268a0d9d7b1c9d250ae355162276e9b1e3011ef6bbc0ab48ad5bcc2681e953857ca62becd7524daac473e68d7405fbba4e9ee616c87038bdbe908c06d9605d9ac49030359eecb1d05a14e117db8cede2bb09d0dbbfee271cb374d8f10abec82d0f59a1dee29fe95638ed8dd41da07487468791b719c55c46968eb3b54680037102a28e53dc1d12903db0af5821794b41c4a93357fa59ce69cfe7f6bdfa629eef78616447e1d611c4baf71bf33febcb03137c2c75d25317d3e13b684370f668411c0f00304b501c8fd422bd9b9ad81d643b20da89ca0525d24d2b142041cae0af205092e430080cd8559ea4c5c6e4fa3f66082b7d303e52ce0162baa958532b0bbc2bc785681fcf37485dff6595e01e739c8ac9efba31b985d5f656cc092432d781db9522172487641c4d3ab8ece01e39bc85b15436614775a98ba8fa12d46f9b35e2a55eb72d7f85181a366663387ddc20551807e007673bd7e26bf9b29b5ab10a1ca87cbb7ad97e99eb66959c2a9bc3cbde4707ff7720b110fa95354674e395812e47a0ae53b464dcb2d1f345df360dc227270c750676f6724eb479f0d2fbb6124429990457ac6c9167f40aab739998f38b9eccb24fd47c8410131bf65a52af841275d5b3d1880b197df2b5dea3e6de56ebce3ffb6e9277a82082f8d9677a6767089b671ebd244c214f0bde95c2beb02cd1172d58bdf39dce56ff68eb35ab39b49b4eac7c815ea60451d6e6ab82119118df02a586844a9ffe162ba006d0669ef57668cab38b62f71a2523a084852cd1d079b3658dc2f3e87949b550bab3e177cfc49ed190dff0630e43077c30de8f6ae081537f1e83da537da980afa668e7b7fb25301cf741524be3c49884b42821f17552fbd1931a813017b6b6590a41ea18b6ba49cd48a440bd9a3346a7623fb4ba34a3ee571e3c731f35a7a3cf25b551a680fa68763507b7fde3aaf023c50b9d22da6876ba337eb5e9dd9ec3daf970242b6c5aab3aa4b296ad8b9f6832f686ef70fa938b31b4e5ddd7364442d3ea72e73d668fb0937796f462923a81a47e1cee7426ff6d9221269b5a62ec03d6ec94d12606cb485560bab574816009e96504249385bb61a819be04f62c2066214d8360a2022beb316240b6c7d78bbe56c13082e0ca272661210abf020bf3b5783f1426436cf9ff41840593a5d0638d32fc51c5c65ff291a3a7a52fd6775e623a4439cc08dd25582febc944ef92d8dbd329c91de3e9c9582e41f17f3d186f104ad3f90995116c682a2a14a3b4b1f547c335f0be710fc9fc03e0e587b8cda31ce65b969878a4ad4283e6d5b0373f43da86e9e0ffe1ae0fddd3516255bd74566f36a38703d5f34249ded1f66b3d9b45b9af2ccfefe984e13376b1b2c6404aa48c8026132343da3f3a33659ec1b3e95080540b28b7f3fcd35fa5d843b579a84c089121a60d8c1754915c344eeaf45a9bf27dc0c1e78416169122091313eb0e87555abd706626e557fc36a04fcd191a58829104d6075c5594f627ca506bf181daec940f4a4f3af0074eee89daacde6758312622d4fa675b39f728e062d2bee680d8f41a597c262648bb18bcfc13c8b3d97b1a77b2ac3af745d61a34cc4709865bac824a94bb19058015e4e42dc9be6c7803567321829dd85853396269"); - //LogTestBuffer("ExpectedPacket", EncryptedPacket.Data, EncryptedPacket.Length); - //LogTestBuffer(" ActualPacket", PacketBuffer, sizeof(PacketBuffer)); - VERIFY_ARE_EQUAL(EncryptedPacket.Length, (uint16_t)sizeof(PacketBuffer)); - VERIFY_ARE_EQUAL(0, memcmp(EncryptedPacket.Data, PacketBuffer, EncryptedPacket.Length)); - - // - // Little hack to convert the initial key to a 1-RTT key for a key update test. - // - uint8_t PacketKeyBuffer[sizeof(QUIC_SECRET) + sizeof(QUIC_PACKET_KEY)] = {0}; - QUIC_PACKET_KEY* PacketKey = (QUIC_PACKET_KEY*)PacketKeyBuffer; - memcpy(PacketKey, State.ReadKeys[0], sizeof(QUIC_PACKET_KEY)); - PacketKey->Type = QUIC_PACKET_KEY_1_RTT; - - QUIC_PACKET_KEY* NewPacketKey = NULL; - VERIFY_QUIC_SUCCESS(QuicPacketKeyUpdate(PacketKey, &NewPacketKey)); - - const QuicBuffer ExpectedTrafficSecret("53dd8c90e78fc6ea92864f791865be060d933be0824befcb2b59ac901f306035"); - VERIFY_ARE_EQUAL(0, memcmp(ExpectedTrafficSecret.Data, NewPacketKey->TrafficSecret[0].Secret, ExpectedTrafficSecret.Length)); - - QuicPacketKeyFree(State.ReadKeys[0]); - QuicPacketKeyFree(State.WriteKeys[0]); - QuicPacketKeyFree(NewPacketKey); +TEST_F(CryptTest, WellKnownClientInitial) +{ + const QuicBuffer InitialSalt("c3eef712c72ebb5a11a7d2432bb46365bef9f502"); + const QuicBuffer ConnectionID("8394c8f03e515708"); + + const QuicBuffer InitialPacketHeader("c3ff000017088394c8f03e5157080000449e00000002"); + const QuicBuffer InitialPacketPayload("060040c4010000c003036660261ff947cea49cce6cfad687f457cf1b14531ba14131a0e8f309a1d0b9c4000006130113031302010000910000000b0009000006736572766572ff01000100000a00140012001d0017001800190100010101020103010400230000003300260024001d00204cfdfcd178b784bf328cae793b136f2aedce005ff183d7bb1495207236647037002b0003020304000d0020001e040305030603020308040805080604010501060102010402050206020202002d00020101001c00024001"); + const uint64_t InitialPacketNumber = 2; + + uint8_t PacketBuffer[1200] = {0}; + memcpy(PacketBuffer, InitialPacketHeader.Data, InitialPacketHeader.Length); + memcpy(PacketBuffer + InitialPacketHeader.Length, InitialPacketPayload.Data, InitialPacketPayload.Length); + + QUIC_TLS_PROCESS_STATE State = {0}; + VERIFY_QUIC_SUCCESS( + QuicPacketKeyCreateInitial( + FALSE, + InitialSalt.Data, + (uint8_t)ConnectionID.Length, + ConnectionID.Data, + &State.ReadKeys[QUIC_PACKET_KEY_INITIAL], + &State.WriteKeys[QUIC_PACKET_KEY_INITIAL])); + + uint8_t Iv[QUIC_IV_LENGTH]; + QuicCryptoCombineIvAndPacketNumber(State.WriteKeys[0]->Iv, (uint8_t*) &InitialPacketNumber, Iv); + + VERIFY_QUIC_SUCCESS( + QuicEncrypt( + State.WriteKeys[0]->PacketKey, + Iv, + InitialPacketHeader.Length, + PacketBuffer, + sizeof(PacketBuffer) - InitialPacketHeader.Length, + PacketBuffer + InitialPacketHeader.Length)); + + const QuicBuffer ExpectedSample("535064a4268a0d9d7b1c9d250ae35516"); + //LogTestBuffer("ExpectedSample", ExpectedSample.Data, ExpectedSample.Length); + //LogTestBuffer(" ActualSample", PacketBuffer + InitialPacketHeader.Length, ExpectedSample.Length); + ASSERT_EQ(0, memcmp(ExpectedSample.Data, PacketBuffer + InitialPacketHeader.Length, ExpectedSample.Length)); + + uint8_t HpMask[16]; + VERIFY_QUIC_SUCCESS( + QuicHpComputeMask( + State.WriteKeys[0]->HeaderKey, + 1, + PacketBuffer + InitialPacketHeader.Length, + HpMask)); + + const QuicBuffer ExpectedHpMask("833b343aaa"); + //LogTestBuffer("ExpectedHpMask", ExpectedHpMask.Data, ExpectedHpMask.Length); + //LogTestBuffer(" ActualHpMask", HpMask, ExpectedHpMask.Length); + ASSERT_EQ(0, memcmp(ExpectedHpMask.Data, HpMask, ExpectedHpMask.Length)); + + PacketBuffer[0] ^= HpMask[0] & 0x0F; + for (uint8_t i = 1; i < 5; ++i) { + PacketBuffer[17 + i] ^= HpMask[i]; } - TEST_METHOD(Encryption) - { - BEGIN_TEST_METHOD_PROPERTIES() - TEST_METHOD_PROPERTY(L"Data:AEAD", L"{0,1,2}") - END_TEST_METHOD_PROPERTIES() + const QuicBuffer ExpectedHeader("c0ff000017088394c8f03e5157080000449e3b343aa8"); + //LogTestBuffer("ExpectedHeader", ExpectedHeader.Data, ExpectedHeader.Length); + //LogTestBuffer(" ActualHeader", PacketBuffer, ExpectedHeader.Length); + ASSERT_EQ(0, memcmp(ExpectedHeader.Data, PacketBuffer, ExpectedHeader.Length)); + + const QuicBuffer EncryptedPacket("c0ff000017088394c8f03e5157080000449e3b343aa8535064a4268a0d9d7b1c9d250ae355162276e9b1e3011ef6bbc0ab48ad5bcc2681e953857ca62becd7524daac473e68d7405fbba4e9ee616c87038bdbe908c06d9605d9ac49030359eecb1d05a14e117db8cede2bb09d0dbbfee271cb374d8f10abec82d0f59a1dee29fe95638ed8dd41da07487468791b719c55c46968eb3b54680037102a28e53dc1d12903db0af5821794b41c4a93357fa59ce69cfe7f6bdfa629eef78616447e1d611c4baf71bf33febcb03137c2c75d25317d3e13b684370f668411c0f00304b501c8fd422bd9b9ad81d643b20da89ca0525d24d2b142041cae0af205092e430080cd8559ea4c5c6e4fa3f66082b7d303e52ce0162baa958532b0bbc2bc785681fcf37485dff6595e01e739c8ac9efba31b985d5f656cc092432d781db9522172487641c4d3ab8ece01e39bc85b15436614775a98ba8fa12d46f9b35e2a55eb72d7f85181a366663387ddc20551807e007673bd7e26bf9b29b5ab10a1ca87cbb7ad97e99eb66959c2a9bc3cbde4707ff7720b110fa95354674e395812e47a0ae53b464dcb2d1f345df360dc227270c750676f6724eb479f0d2fbb6124429990457ac6c9167f40aab739998f38b9eccb24fd47c8410131bf65a52af841275d5b3d1880b197df2b5dea3e6de56ebce3ffb6e9277a82082f8d9677a6767089b671ebd244c214f0bde95c2beb02cd1172d58bdf39dce56ff68eb35ab39b49b4eac7c815ea60451d6e6ab82119118df02a586844a9ffe162ba006d0669ef57668cab38b62f71a2523a084852cd1d079b3658dc2f3e87949b550bab3e177cfc49ed190dff0630e43077c30de8f6ae081537f1e83da537da980afa668e7b7fb25301cf741524be3c49884b42821f17552fbd1931a813017b6b6590a41ea18b6ba49cd48a440bd9a3346a7623fb4ba34a3ee571e3c731f35a7a3cf25b551a680fa68763507b7fde3aaf023c50b9d22da6876ba337eb5e9dd9ec3daf970242b6c5aab3aa4b296ad8b9f6832f686ef70fa938b31b4e5ddd7364442d3ea72e73d668fb0937796f462923a81a47e1cee7426ff6d9221269b5a62ec03d6ec94d12606cb485560bab574816009e96504249385bb61a819be04f62c2066214d8360a2022beb316240b6c7d78bbe56c13082e0ca272661210abf020bf3b5783f1426436cf9ff41840593a5d0638d32fc51c5c65ff291a3a7a52fd6775e623a4439cc08dd25582febc944ef92d8dbd329c91de3e9c9582e41f17f3d186f104ad3f90995116c682a2a14a3b4b1f547c335f0be710fc9fc03e0e587b8cda31ce65b969878a4ad4283e6d5b0373f43da86e9e0ffe1ae0fddd3516255bd74566f36a38703d5f34249ded1f66b3d9b45b9af2ccfefe984e13376b1b2c6404aa48c8026132343da3f3a33659ec1b3e95080540b28b7f3fcd35fa5d843b579a84c089121a60d8c1754915c344eeaf45a9bf27dc0c1e78416169122091313eb0e87555abd706626e557fc36a04fcd191a58829104d6075c5594f627ca506bf181daec940f4a4f3af0074eee89daacde6758312622d4fa675b39f728e062d2bee680d8f41a597c262648bb18bcfc13c8b3d97b1a77b2ac3af745d61a34cc4709865bac824a94bb19058015e4e42dc9be6c7803567321829dd85853396269"); + //LogTestBuffer("ExpectedPacket", EncryptedPacket.Data, EncryptedPacket.Length); + //LogTestBuffer(" ActualPacket", PacketBuffer, sizeof(PacketBuffer)); + ASSERT_EQ(EncryptedPacket.Length, (uint16_t)sizeof(PacketBuffer)); + ASSERT_EQ(0, memcmp(EncryptedPacket.Data, PacketBuffer, EncryptedPacket.Length)); + + // + // Little hack to convert the initial key to a 1-RTT key for a key update test. + // + uint8_t PacketKeyBuffer[sizeof(QUIC_SECRET) + sizeof(QUIC_PACKET_KEY)] = {0}; + QUIC_PACKET_KEY* PacketKey = (QUIC_PACKET_KEY*)PacketKeyBuffer; + memcpy(PacketKey, State.ReadKeys[0], sizeof(QUIC_PACKET_KEY)); + PacketKey->Type = QUIC_PACKET_KEY_1_RTT; + + QUIC_PACKET_KEY* NewPacketKey = NULL; + VERIFY_QUIC_SUCCESS(QuicPacketKeyUpdate(PacketKey, &NewPacketKey)); + + const QuicBuffer ExpectedTrafficSecret("53dd8c90e78fc6ea92864f791865be060d933be0824befcb2b59ac901f306035"); + ASSERT_EQ(0, memcmp(ExpectedTrafficSecret.Data, NewPacketKey->TrafficSecret[0].Secret, ExpectedTrafficSecret.Length)); + + QuicPacketKeyFree(State.ReadKeys[0]); + QuicPacketKeyFree(State.WriteKeys[0]); + QuicPacketKeyFree(NewPacketKey); +} - int AEAD; - TestData::TryGetValue(L"AEAD", AEAD); +TEST_P(CryptTest, Encryption) +{ - uint8_t RawKey[32]; - uint8_t Iv[QUIC_IV_LENGTH]; - uint8_t AuthData[12]; - uint8_t Buffer[128]; + int AEAD = GetParam(); - QuicKey Key((QUIC_AEAD_TYPE)AEAD, RawKey); - if (Key.Ptr == NULL) return; + uint8_t RawKey[32]; + uint8_t Iv[QUIC_IV_LENGTH]; + uint8_t AuthData[12]; + uint8_t Buffer[128]; - // - // Positive cases - // + QuicKey Key((QUIC_AEAD_TYPE)AEAD, RawKey); + if (Key.Ptr == NULL) return; - VERIFY_IS_TRUE(Key.Encrypt(Iv, 0, NULL, sizeof(Buffer), Buffer)); - VERIFY_IS_TRUE(Key.Decrypt(Iv, 0, NULL, sizeof(Buffer), Buffer)); - VERIFY_IS_TRUE(Key.Encrypt(Iv, sizeof(AuthData), AuthData, sizeof(Buffer), Buffer)); - VERIFY_IS_TRUE(Key.Decrypt(Iv, sizeof(AuthData), AuthData, sizeof(Buffer), Buffer)); + // + // Positive cases + // - // - // Negative cases - // + ASSERT_TRUE(Key.Encrypt(Iv, 0, NULL, sizeof(Buffer), Buffer)); + ASSERT_TRUE(Key.Decrypt(Iv, 0, NULL, sizeof(Buffer), Buffer)); + ASSERT_TRUE(Key.Encrypt(Iv, sizeof(AuthData), AuthData, sizeof(Buffer), Buffer)); + ASSERT_TRUE(Key.Decrypt(Iv, sizeof(AuthData), AuthData, sizeof(Buffer), Buffer)); - VERIFY_IS_TRUE(Key.Encrypt(Iv, 0, NULL, sizeof(Buffer), Buffer)); - VERIFY_IS_FALSE(Key.Decrypt(Iv, 0, NULL, sizeof(Buffer) - 1, Buffer)); + // + // Negative cases + // - VERIFY_IS_TRUE(Key.Encrypt(Iv, sizeof(AuthData), AuthData, sizeof(Buffer), Buffer)); - VERIFY_IS_FALSE(Key.Decrypt(Iv, sizeof(AuthData), AuthData, sizeof(Buffer) - 1, Buffer)); + ASSERT_TRUE(Key.Encrypt(Iv, 0, NULL, sizeof(Buffer), Buffer)); + ASSERT_FALSE(Key.Decrypt(Iv, 0, NULL, sizeof(Buffer) - 1, Buffer)); - VERIFY_IS_TRUE(Key.Encrypt(Iv, sizeof(AuthData), AuthData, sizeof(Buffer), Buffer)); - VERIFY_IS_FALSE(Key.Decrypt(Iv, sizeof(AuthData) - 1, AuthData, sizeof(Buffer), Buffer)); + ASSERT_TRUE(Key.Encrypt(Iv, sizeof(AuthData), AuthData, sizeof(Buffer), Buffer)); + ASSERT_FALSE(Key.Decrypt(Iv, sizeof(AuthData), AuthData, sizeof(Buffer) - 1, Buffer)); - VERIFY_IS_TRUE(Key.Encrypt(Iv, 0, NULL, sizeof(Buffer), Buffer)); - Buffer[0] ^= 1; - VERIFY_IS_FALSE(Key.Decrypt(Iv, 0, NULL, sizeof(Buffer), Buffer)); + ASSERT_TRUE(Key.Encrypt(Iv, sizeof(AuthData), AuthData, sizeof(Buffer), Buffer)); + ASSERT_FALSE(Key.Decrypt(Iv, sizeof(AuthData) - 1, AuthData, sizeof(Buffer), Buffer)); - VERIFY_IS_TRUE(Key.Encrypt(Iv, 0, NULL, sizeof(Buffer), Buffer)); - Buffer[127] ^= 1; - VERIFY_IS_FALSE(Key.Decrypt(Iv, 0, NULL, sizeof(Buffer), Buffer)); + ASSERT_TRUE(Key.Encrypt(Iv, 0, NULL, sizeof(Buffer), Buffer)); + Buffer[0] ^= 1; + ASSERT_FALSE(Key.Decrypt(Iv, 0, NULL, sizeof(Buffer), Buffer)); - VERIFY_IS_TRUE(Key.Encrypt(Iv, sizeof(AuthData), AuthData, sizeof(Buffer), Buffer)); - AuthData[0] ^= 1; - VERIFY_IS_FALSE(Key.Decrypt(Iv, sizeof(AuthData), AuthData, sizeof(Buffer), Buffer)); + ASSERT_TRUE(Key.Encrypt(Iv, 0, NULL, sizeof(Buffer), Buffer)); + Buffer[127] ^= 1; + ASSERT_FALSE(Key.Decrypt(Iv, 0, NULL, sizeof(Buffer), Buffer)); - VERIFY_IS_TRUE(Key.Encrypt(Iv, sizeof(AuthData), AuthData, sizeof(Buffer), Buffer)); - Buffer[127] ^= 1; - VERIFY_IS_FALSE(Key.Decrypt(Iv, sizeof(AuthData), AuthData, sizeof(Buffer), Buffer)); - } + ASSERT_TRUE(Key.Encrypt(Iv, sizeof(AuthData), AuthData, sizeof(Buffer), Buffer)); + AuthData[0] ^= 1; + ASSERT_FALSE(Key.Decrypt(Iv, sizeof(AuthData), AuthData, sizeof(Buffer), Buffer)); - TEST_METHOD(HashWellKnown) - { - BEGIN_TEST_METHOD_PROPERTIES() - TEST_METHOD_PROPERTY(L"Data:HASH", L"{0,1,2}") - END_TEST_METHOD_PROPERTIES() - - int HASH; - TestData::TryGetValue(L"HASH", HASH); - - const QuicBuffer WellKnownOutput0("6a2434c718a984ad38abc419e1300c066e0a61e84bf8403876cf2e32f9103938"); - const QuicBuffer WellKnownOutput1("1aa0fa65e1b94d6cf9eaeaa062d55bc643259b9f42b6750547cf325c1489ddb76e069081bc13152614a2ff4a85e920ce"); - const QuicBuffer WellKnownOutput2("a2827af996dc82f3721cfb6c5c7d3d307d088438caa77b330f105e711d2b1eadd3c0bcd5ac3498bf05c15e8ab73ac86fb9522b80e735e017db17c40d29d0e588"); - - const QuicBuffer* WellKnownOutput[] = { - &WellKnownOutput0, &WellKnownOutput1, &WellKnownOutput2 - }; - - uint8_t Salt[20] = {0xff}; - uint8_t Input[256] = {0xaa}; - uint8_t Output[QUIC_HASH_MAX_SIZE] = {0}; - const uint16_t OutputLength = QuicHashLength((QUIC_HASH_TYPE)HASH); - - QuicHash Hash((QUIC_HASH_TYPE)HASH, Salt, sizeof(Salt)); - if (Hash.Ptr == NULL) return; - - VERIFY_IS_TRUE( - Hash.Compute( - Input, - sizeof(Input), - OutputLength, - Output)); - VERIFY_ARE_EQUAL((uint16_t)WellKnownOutput[HASH]->Length, OutputLength); - VERIFY_ARE_EQUAL(0, memcmp(WellKnownOutput[HASH]->Data, Output, OutputLength)); - } + ASSERT_TRUE(Key.Encrypt(Iv, sizeof(AuthData), AuthData, sizeof(Buffer), Buffer)); + Buffer[127] ^= 1; + ASSERT_FALSE(Key.Decrypt(Iv, sizeof(AuthData), AuthData, sizeof(Buffer), Buffer)); +} - TEST_METHOD(HashRandom) - { - BEGIN_TEST_METHOD_PROPERTIES() - TEST_METHOD_PROPERTY(L"Data:HASH", L"{0,1,2}") - END_TEST_METHOD_PROPERTIES() - - int HASH; - TestData::TryGetValue(L"HASH", HASH); - - uint8_t Salt[20]; - uint8_t Input[256]; - uint8_t Output[QUIC_HASH_MAX_SIZE]; - uint8_t Output2[QUIC_HASH_MAX_SIZE]; - const uint16_t OutputLength = QuicHashLength((QUIC_HASH_TYPE)HASH); - - QuicRandom(sizeof(Salt), Salt); - QuicRandom(sizeof(Input), Input); - - QuicHash Hash((QUIC_HASH_TYPE)HASH, Salt, sizeof(Salt)); - if (Hash.Ptr == NULL) return; - - VERIFY_IS_TRUE( - Hash.Compute( - Input, - sizeof(Input), - OutputLength, - Output)); - VERIFY_IS_TRUE( - Hash.Compute( - Input, - sizeof(Input), - OutputLength, - Output2)); - VERIFY_ARE_EQUAL(0, memcmp(Output, Output2, OutputLength)); - } -}; +TEST_P(CryptTest, HashWellKnown) +{ + int HASH = GetParam(); + + const QuicBuffer WellKnownOutput0("6a2434c718a984ad38abc419e1300c066e0a61e84bf8403876cf2e32f9103938"); + const QuicBuffer WellKnownOutput1("1aa0fa65e1b94d6cf9eaeaa062d55bc643259b9f42b6750547cf325c1489ddb76e069081bc13152614a2ff4a85e920ce"); + const QuicBuffer WellKnownOutput2("a2827af996dc82f3721cfb6c5c7d3d307d088438caa77b330f105e711d2b1eadd3c0bcd5ac3498bf05c15e8ab73ac86fb9522b80e735e017db17c40d29d0e588"); + + const QuicBuffer* WellKnownOutput[] = { + &WellKnownOutput0, &WellKnownOutput1, &WellKnownOutput2 + }; + + uint8_t Salt[20]; + QuicZeroMemory(Salt, sizeof(Salt)); + Salt[0] = 0xff; + uint8_t Input[256]; + QuicZeroMemory(Input, sizeof(Input)); + Input[0] = 0xaa; + + uint8_t Output[QUIC_HASH_MAX_SIZE]; + QuicZeroMemory(Output, sizeof(Output)); + const uint16_t OutputLength = QuicHashLength((QUIC_HASH_TYPE)HASH); + + QuicHash Hash((QUIC_HASH_TYPE)HASH, Salt, sizeof(Salt)); + if (Hash.Ptr == NULL) return; + + ASSERT_TRUE( + Hash.Compute( + Input, + sizeof(Input), + OutputLength, + Output)); + ASSERT_EQ(WellKnownOutput[HASH]->Length, OutputLength); + ASSERT_EQ(0, memcmp(WellKnownOutput[HASH]->Data, Output, OutputLength)); +} + +TEST_P(CryptTest, HashRandom) +{ + int HASH = GetParam(); + + uint8_t Salt[20]; + uint8_t Input[256]; + uint8_t Output[QUIC_HASH_MAX_SIZE]; + uint8_t Output2[QUIC_HASH_MAX_SIZE]; + const uint16_t OutputLength = QuicHashLength((QUIC_HASH_TYPE)HASH); + + QuicRandom(sizeof(Salt), Salt); + QuicRandom(sizeof(Input), Input); + + QuicHash Hash((QUIC_HASH_TYPE)HASH, Salt, sizeof(Salt)); + if (Hash.Ptr == NULL) return; + + ASSERT_TRUE( + Hash.Compute( + Input, + sizeof(Input), + OutputLength, + Output)); + ASSERT_TRUE( + Hash.Compute( + Input, + sizeof(Input), + OutputLength, + Output2)); + ASSERT_EQ(0, memcmp(Output, Output2, OutputLength)); +} + +INSTANTIATE_TEST_SUITE_P(CryptTest, CryptTest, ::testing::Values(0, 1, 2)); + +#endif // QUIC_TLS_STUB diff --git a/src/platform/unittest/DataPathTest.cpp b/src/platform/unittest/DataPathTest.cpp index 5dd71f2b95ba..00cb37349468 100644 --- a/src/platform/unittest/DataPathTest.cpp +++ b/src/platform/unittest/DataPathTest.cpp @@ -9,28 +9,15 @@ --*/ -#include "quic_platform.h" +#include "main.h" #include "quic_datapath.h" -#include -#include -#include -#include - -#define LOG_ONLY_FAILURES -#define INLINE_TEST_METHOD_MARKUP -#include -#include #include "msquic.h" -#include "quic_trace.h" #ifdef QUIC_LOGS_WPP #include "datapathtest.tmh" #endif -using namespace WEX::Logging; - -#define VERIFY_QUIC_SUCCESS(result, ...) VERIFY_ARE_EQUAL(QUIC_STATUS_SUCCESS, result, __VA_ARGS__) const uint32_t ExpectedDataSize = 1 * 1024; char* ExpectedData; @@ -40,9 +27,9 @@ char* ExpectedData; // struct QuicAddr { - SOCKADDR_INET SockAddr; + QUIC_ADDR SockAddr; - UINT16 Port() { + uint16_t Port() { if (SockAddr.si_family == AF_INET) { return SockAddr.Ipv4.sin_port; } else { @@ -51,7 +38,7 @@ struct QuicAddr } #undef SetPort - void SetPort(UINT16 port) { + void SetPort(uint16_t port) { if (SockAddr.si_family == AF_INET) { SockAddr.Ipv4.sin_port = port; } else { @@ -60,48 +47,49 @@ struct QuicAddr } QuicAddr() { - ZeroMemory(this, sizeof(*this)); + QuicZeroMemory(this, sizeof(*this)); } - void Resolve(QUIC_ADDRESS_FAMILY af, PSTR hostname) { - WSADATA wsaData; - ADDRINFOA hints = { 0 }; - ADDRINFOA *ai; - - // - // Prepopulate hint with input family. - // - hints.ai_family = af; - hints.ai_flags = AI_CANONNAME; - - VERIFY_ARE_EQUAL( - WSAStartup(MAKEWORD(2, 2), &wsaData), - (int)0); - - VERIFY_ARE_EQUAL( - GetAddrInfoA(hostname, nullptr, &hints, &ai), - (int)0); - - memcpy(&SockAddr, ai->ai_addr, ai->ai_addrlen); - - FreeAddrInfoA(ai); - WSACleanup(); + void Resolve(QUIC_ADDRESS_FAMILY af, const char* hostname) { + QUIC_DATAPATH* Datapath = nullptr; + if (QUIC_FAILED( + QuicDataPathInitialize( + 0, + (QUIC_DATAPATH_RECEIVE_CALLBACK_HANDLER)(1), + (QUIC_DATAPATH_UNREACHABLE_CALLBACK_HANDLER)(1), + &Datapath))) { + GTEST_FATAL_FAILURE_(" QuicDataPathInitialize failed."); + } + if (QUIC_FAILED( + QuicDataPathResolveAddress( + Datapath, + hostname, + &SockAddr))) { + GTEST_FATAL_FAILURE_("Failed to resolve IP address."); + } + QuicDataPathUninitialize(Datapath); } }; -struct DataPathTest : public WEX::TestClass +struct DataRecvContext { + QUIC_ADDR ServerAddress; + QUIC_EVENT ClientCompletion; +}; + +struct DataPathTest : public ::testing::TestWithParam { - volatile uint16_t NextPort; - QuicAddr LocalIPv4; - QuicAddr LocalIPv6; +protected: + static volatile uint16_t NextPort; + static QuicAddr LocalIPv4; + static QuicAddr LocalIPv6; // // Helper to get a new port to bind to. // - UINT16 + uint16_t GetNextPort() { - return htons((UINT16)InterlockedIncrement16((PSHORT)&NextPort)); + return QuicNetByteSwapShort((uint16_t)InterlockedIncrement16((volatile short*)&NextPort)); } // @@ -134,47 +122,41 @@ struct DataPathTest : public WEX::TestClass QuicAddr GetNewLocalAddr(bool randomPort = true) { - int addressFamily; - VERIFY_SUCCEEDED(WEX::TestExecution::TestData::TryGetValue(L"Family", addressFamily)); + int addressFamily = GetParam(); if (addressFamily == 4) { return GetNewLocalIPv4(randomPort); } else if (addressFamily == 6) { return GetNewLocalIPv6(randomPort); } else { - VERIFY_FAIL(L"Malconfigured test data; This should never happen!!"); + GTEST_NONFATAL_FAILURE_("Malconfigured test data; This should never happen!!"); return QuicAddr(); } } - BEGIN_TEST_CLASS(DataPathTest) - TEST_CLASS_PROPERTY(L"Data:Family", L"{4,6}") - END_TEST_CLASS() - - TEST_CLASS_SETUP(Setup) + static void SetUpTestSuite() { // // Initialize a semi-random base port number. // - NextPort = 50000 + (GetCurrentProcessId() % 10000) + (rand() % 5000); + NextPort = 50000 + (QuicCurThreadID() % 10000) + (rand() % 5000); LocalIPv4.Resolve(AF_INET, "localhost"); LocalIPv6.Resolve(AF_INET6, "localhost"); - ExpectedData = (char*)LocalAlloc(NONZEROLPTR, ExpectedDataSize); - return ExpectedData != nullptr; + ExpectedData = (char*)QUIC_ALLOC_NONPAGED(ExpectedDataSize); + ASSERT_NE(ExpectedData, nullptr); } - TEST_CLASS_CLEANUP(Cleanup) + static void TearDownTestSuite() { - LocalFree(ExpectedData); - return true; + QUIC_FREE(ExpectedData); } static void EmptyReceiveCallback( _In_ QUIC_DATAPATH_BINDING* /* Binding */, - _In_ PVOID /* RecvContext */, + _In_ void * /* RecvContext */, _In_ QUIC_RECV_DATAGRAM* /* RecvPacketChain */ ) { @@ -183,161 +165,37 @@ struct DataPathTest : public WEX::TestClass static void EmptyUnreachableCallback( _In_ QUIC_DATAPATH_BINDING* /* Binding */, - _In_ PVOID /* Context */, - _In_ const SOCKADDR_INET* /* RemoteAddress */ + _In_ void * /* Context */, + _In_ const QUIC_ADDR* /* RemoteAddress */ ) { } - TEST_METHOD(Initialize) - { - QUIC_DATAPATH* datapath = nullptr; - - VERIFY_QUIC_SUCCESS( - QuicDataPathInitialize( - 0, - EmptyReceiveCallback, - EmptyUnreachableCallback, - &datapath)); - VERIFY_IS_NOT_NULL(datapath); - - QuicDataPathUninitialize( - datapath); - } - - TEST_METHOD(InitializeInvalid) - { - VERIFY_ARE_EQUAL(QUIC_STATUS_INVALID_PARAMETER, - QuicDataPathInitialize( - 0, - EmptyReceiveCallback, - EmptyUnreachableCallback, - nullptr)); - - QUIC_DATAPATH* datapath = nullptr; - VERIFY_ARE_EQUAL(QUIC_STATUS_INVALID_PARAMETER, - QuicDataPathInitialize( - 0, - nullptr, - EmptyUnreachableCallback, - &datapath)); - VERIFY_ARE_EQUAL(QUIC_STATUS_INVALID_PARAMETER, - QuicDataPathInitialize( - 0, - EmptyReceiveCallback, - nullptr, - &datapath)); - } - - TEST_METHOD(Bind) - { - QUIC_DATAPATH* datapath = nullptr; - QUIC_DATAPATH_BINDING* binding = nullptr; - - VERIFY_QUIC_SUCCESS( - QuicDataPathInitialize( - 0, - EmptyReceiveCallback, - EmptyUnreachableCallback, - &datapath)); - VERIFY_IS_NOT_NULL(datapath); - - VERIFY_QUIC_SUCCESS( - QuicDataPathBindingCreate( - datapath, - nullptr, - nullptr, - nullptr, - &binding)); - VERIFY_IS_NOT_NULL(binding); - - SOCKADDR_INET Address; - QuicDataPathBindingGetLocalAddress(binding, &Address); - VERIFY_ARE_NOT_EQUAL(Address.Ipv4.sin_port, (UINT16)0); - - QuicDataPathBindingDelete(binding); - - QuicDataPathUninitialize( - datapath); - } - - TEST_METHOD(Rebind) - { - QUIC_DATAPATH* datapath = nullptr; - QUIC_DATAPATH_BINDING* binding1 = nullptr; - QUIC_DATAPATH_BINDING* binding2 = nullptr; - - VERIFY_QUIC_SUCCESS( - QuicDataPathInitialize( - 0, - EmptyReceiveCallback, - EmptyUnreachableCallback, - &datapath)); - VERIFY_IS_NOT_NULL(datapath); - - VERIFY_QUIC_SUCCESS( - QuicDataPathBindingCreate( - datapath, - nullptr, - nullptr, - nullptr, - &binding1)); - VERIFY_IS_NOT_NULL(binding1); - - SOCKADDR_INET Address1; - QuicDataPathBindingGetLocalAddress(binding1, &Address1); - VERIFY_ARE_NOT_EQUAL(Address1.Ipv4.sin_port, (UINT16)0); - - VERIFY_QUIC_SUCCESS( - QuicDataPathBindingCreate( - datapath, - nullptr, - nullptr, - nullptr, - &binding2)); - VERIFY_IS_NOT_NULL(binding2); - - SOCKADDR_INET Address2; - QuicDataPathBindingGetLocalAddress(binding2, &Address2); - VERIFY_ARE_NOT_EQUAL(Address2.Ipv4.sin_port, (UINT16)0); - - QuicDataPathBindingDelete(binding1); - QuicDataPathBindingDelete(binding2); - - QuicDataPathUninitialize( - datapath); - } - - struct DataRecvContext { - SOCKADDR_INET ServerAddress; - HANDLE ClientCompletion; - }; - static void DataRecvCallback( _In_ QUIC_DATAPATH_BINDING* binding, - _In_ PVOID recvContext, + _In_ void * recvContext, _In_ QUIC_RECV_DATAGRAM* recvBufferChain ) { DataRecvContext* RecvContext = (DataRecvContext*)recvContext; - VERIFY_IS_NOT_NULL(RecvContext); + ASSERT_NE(nullptr, RecvContext); QUIC_RECV_DATAGRAM* recvBuffer = recvBufferChain; while (recvBuffer != NULL) { - VERIFY_ARE_EQUAL(recvBuffer->BufferLength, ExpectedDataSize); - VERIFY_ARE_EQUAL(0, memcmp(recvBuffer->Buffer, ExpectedData, ExpectedDataSize)); + ASSERT_EQ(recvBuffer->BufferLength, ExpectedDataSize); + ASSERT_EQ(0, memcmp(recvBuffer->Buffer, ExpectedData, ExpectedDataSize)); if (recvBuffer->Tuple->LocalAddress.Ipv4.sin_port == RecvContext->ServerAddress.Ipv4.sin_port) { auto ServerSendContext = QuicDataPathBindingAllocSendContext(binding, 0); - VERIFY_IS_NOT_NULL(ServerSendContext); + ASSERT_NE(nullptr, ServerSendContext); auto ServerDatagram = QuicDataPathBindingAllocSendDatagram(ServerSendContext, ExpectedDataSize); - VERIFY_IS_NOT_NULL(ServerDatagram); + ASSERT_NE(nullptr, ServerDatagram); memcpy(ServerDatagram->Buffer, recvBuffer->Buffer, recvBuffer->BufferLength); @@ -350,8 +208,7 @@ struct DataPathTest : public WEX::TestClass )); } else { - - VERIFY_ARE_EQUAL(TRUE, SetEvent(RecvContext->ClientCompletion)); + QuicEventSet(RecvContext->ClientCompletion); } recvBuffer = recvBuffer->Next; @@ -359,183 +216,318 @@ struct DataPathTest : public WEX::TestClass QuicDataPathBindingReturnRecvDatagrams(recvBufferChain); } +}; - TEST_METHOD(Data) - { - QUIC_DATAPATH* datapath = nullptr; - QUIC_DATAPATH_BINDING* server = nullptr; - QUIC_DATAPATH_BINDING* client = nullptr; - auto serverAddress = GetNewLocalAddr(); - - DataRecvContext RecvContext = - { - { 0 }, - CreateEvent(nullptr, FALSE, FALSE, nullptr) - }; - - VERIFY_QUIC_SUCCESS( - QuicDataPathInitialize( - 0, - DataRecvCallback, - EmptyUnreachableCallback, - &datapath)); - VERIFY_IS_NOT_NULL(datapath); - - QUIC_STATUS Status = WSAEADDRINUSE; - while (Status == WSAEADDRINUSE) { - serverAddress.SockAddr.Ipv4.sin_port = GetNextPort(); - Status = - QuicDataPathBindingCreate( - datapath, - &serverAddress.SockAddr, - nullptr, - &RecvContext, - &server); - } - VERIFY_QUIC_SUCCESS(Status); - VERIFY_IS_NOT_NULL(server); - QuicDataPathBindingGetLocalAddress(server, &RecvContext.ServerAddress); - VERIFY_ARE_NOT_EQUAL(RecvContext.ServerAddress.Ipv4.sin_port, (UINT16)0); - serverAddress.SetPort(RecvContext.ServerAddress.Ipv4.sin_port); +volatile uint16_t DataPathTest::NextPort; +QuicAddr DataPathTest::LocalIPv4; +QuicAddr DataPathTest::LocalIPv6; + +TEST_F(DataPathTest, Initialize) +{ + QUIC_DATAPATH* datapath = nullptr; - VERIFY_QUIC_SUCCESS( + VERIFY_QUIC_SUCCESS( + QuicDataPathInitialize( + 0, + EmptyReceiveCallback, + EmptyUnreachableCallback, + &datapath)); + ASSERT_NE(datapath, nullptr); + + QuicDataPathUninitialize( + datapath); +} + +TEST_F(DataPathTest, InitializeInvalid) +{ + ASSERT_EQ(QUIC_STATUS_INVALID_PARAMETER, + QuicDataPathInitialize( + 0, + EmptyReceiveCallback, + EmptyUnreachableCallback, + nullptr)); + + QUIC_DATAPATH* datapath = nullptr; + ASSERT_EQ(QUIC_STATUS_INVALID_PARAMETER, + QuicDataPathInitialize( + 0, + nullptr, + EmptyUnreachableCallback, + &datapath)); + ASSERT_EQ(QUIC_STATUS_INVALID_PARAMETER, + QuicDataPathInitialize( + 0, + EmptyReceiveCallback, + nullptr, + &datapath)); +} + +TEST_F(DataPathTest, Bind) +{ + QUIC_DATAPATH* datapath = nullptr; + QUIC_DATAPATH_BINDING* binding = nullptr; + + VERIFY_QUIC_SUCCESS( + QuicDataPathInitialize( + 0, + EmptyReceiveCallback, + EmptyUnreachableCallback, + &datapath)); + ASSERT_NE(datapath, nullptr); + + VERIFY_QUIC_SUCCESS( + QuicDataPathBindingCreate( + datapath, + nullptr, + nullptr, + nullptr, + &binding)); + ASSERT_NE(nullptr, binding); + + QUIC_ADDR Address; + QuicDataPathBindingGetLocalAddress(binding, &Address); + ASSERT_NE(Address.Ipv4.sin_port, (uint16_t)0); + + QuicDataPathBindingDelete(binding); + + QuicDataPathUninitialize( + datapath); +} + +TEST_F(DataPathTest, Rebind) +{ + QUIC_DATAPATH* datapath = nullptr; + QUIC_DATAPATH_BINDING* binding1 = nullptr; + QUIC_DATAPATH_BINDING* binding2 = nullptr; + + VERIFY_QUIC_SUCCESS( + QuicDataPathInitialize( + 0, + EmptyReceiveCallback, + EmptyUnreachableCallback, + &datapath)); + ASSERT_NE(nullptr, datapath); + + VERIFY_QUIC_SUCCESS( + QuicDataPathBindingCreate( + datapath, + nullptr, + nullptr, + nullptr, + &binding1)); + ASSERT_NE(nullptr, binding1); + + QUIC_ADDR Address1; + QuicDataPathBindingGetLocalAddress(binding1, &Address1); + ASSERT_NE(Address1.Ipv4.sin_port, (uint16_t)0); + + VERIFY_QUIC_SUCCESS( + QuicDataPathBindingCreate( + datapath, + nullptr, + nullptr, + nullptr, + &binding2)); + ASSERT_NE(nullptr, binding2); + + QUIC_ADDR Address2; + QuicDataPathBindingGetLocalAddress(binding2, &Address2); + ASSERT_NE(Address2.Ipv4.sin_port, (uint16_t)0); + + QuicDataPathBindingDelete(binding1); + QuicDataPathBindingDelete(binding2); + + QuicDataPathUninitialize( + datapath); +} + +TEST_P(DataPathTest, Data) +{ + QUIC_DATAPATH* datapath = nullptr; + QUIC_DATAPATH_BINDING* server = nullptr; + QUIC_DATAPATH_BINDING* client = nullptr; + auto serverAddress = GetNewLocalAddr(); + + DataRecvContext RecvContext = {}; + + QuicEventInitialize(&RecvContext.ClientCompletion, FALSE, FALSE); + + VERIFY_QUIC_SUCCESS( + QuicDataPathInitialize( + 0, + DataRecvCallback, + EmptyUnreachableCallback, + &datapath)); + ASSERT_NE(nullptr, datapath); + + QUIC_STATUS Status = QUIC_STATUS_ADDRESS_IN_USE; + while (Status == QUIC_STATUS_ADDRESS_IN_USE) { + serverAddress.SockAddr.Ipv4.sin_port = GetNextPort(); + Status = QuicDataPathBindingCreate( datapath, - nullptr, &serverAddress.SockAddr, + nullptr, &RecvContext, - &client)); - VERIFY_IS_NOT_NULL(client); + &server); +#ifdef _WIN32 + if (Status == HRESULT_FROM_WIN32(WSAEACCES)) { + Status = QUIC_STATUS_ADDRESS_IN_USE; + std::cout << "Replacing EACCESS with ADDRINUSE for port: " << + htons(serverAddress.SockAddr.Ipv4.sin_port) << std::endl; + } +#endif //_WIN32 + } + VERIFY_QUIC_SUCCESS(Status); + ASSERT_NE(nullptr, server); + QuicDataPathBindingGetLocalAddress(server, &RecvContext.ServerAddress); + ASSERT_NE(RecvContext.ServerAddress.Ipv4.sin_port, (uint16_t)0); + serverAddress.SetPort(RecvContext.ServerAddress.Ipv4.sin_port); - auto ClientSendContext = - QuicDataPathBindingAllocSendContext(client, 0); - VERIFY_IS_NOT_NULL(ClientSendContext); + VERIFY_QUIC_SUCCESS( + QuicDataPathBindingCreate( + datapath, + nullptr, + &serverAddress.SockAddr, + &RecvContext, + &client)); + ASSERT_NE(nullptr, client); - auto ClientDatagram = - QuicDataPathBindingAllocSendDatagram(ClientSendContext, ExpectedDataSize); - VERIFY_IS_NOT_NULL(ClientDatagram); + auto ClientSendContext = + QuicDataPathBindingAllocSendContext(client, 0); + ASSERT_NE(nullptr, ClientSendContext); - memcpy(ClientDatagram->Buffer, ExpectedData, ExpectedDataSize); + auto ClientDatagram = + QuicDataPathBindingAllocSendDatagram(ClientSendContext, ExpectedDataSize); + ASSERT_NE(nullptr, ClientDatagram); - VERIFY_QUIC_SUCCESS( - QuicDataPathBindingSendTo( - client, - &serverAddress.SockAddr, - ClientSendContext)); + memcpy(ClientDatagram->Buffer, ExpectedData, ExpectedDataSize); - VERIFY_ARE_EQUAL((DWORD)WAIT_OBJECT_0, WaitForSingleObject(RecvContext.ClientCompletion, 2000)); + VERIFY_QUIC_SUCCESS( + QuicDataPathBindingSendTo( + client, + &serverAddress.SockAddr, + ClientSendContext)); - QuicDataPathBindingDelete(client); - QuicDataPathBindingDelete(server); + ASSERT_TRUE(QuicEventWaitWithTimeout(RecvContext.ClientCompletion, 2000)); - QuicDataPathUninitialize( - datapath); + QuicDataPathBindingDelete(client); + QuicDataPathBindingDelete(server); - CloseHandle(RecvContext.ClientCompletion); - } + QuicDataPathUninitialize( + datapath); - TEST_METHOD(DataRebind) - { - QUIC_DATAPATH* datapath = nullptr; - QUIC_DATAPATH_BINDING* server = nullptr; - QUIC_DATAPATH_BINDING* client = nullptr; - auto serverAddress = GetNewLocalAddr(); - - DataRecvContext RecvContext = - { - { 0 }, - CreateEvent(nullptr, FALSE, FALSE, nullptr) - }; - - VERIFY_QUIC_SUCCESS( - QuicDataPathInitialize( - 0, - DataRecvCallback, - EmptyUnreachableCallback, - &datapath)); - VERIFY_IS_NOT_NULL(datapath); - - QUIC_STATUS Status = WSAEADDRINUSE; - while (Status == WSAEADDRINUSE) { - serverAddress.SockAddr.Ipv4.sin_port = GetNextPort(); - Status = - QuicDataPathBindingCreate( - datapath, - &serverAddress.SockAddr, - nullptr, - &RecvContext, - &server); - } - VERIFY_QUIC_SUCCESS(Status); - VERIFY_IS_NOT_NULL(server); - QuicDataPathBindingGetLocalAddress(server, &RecvContext.ServerAddress); - VERIFY_ARE_NOT_EQUAL(RecvContext.ServerAddress.Ipv4.sin_port, (UINT16)0); - serverAddress.SetPort(RecvContext.ServerAddress.Ipv4.sin_port); + QuicEventUninitialize(RecvContext.ClientCompletion); +} - VERIFY_QUIC_SUCCESS( +TEST_P(DataPathTest, DataRebind) +{ + QUIC_DATAPATH* datapath = nullptr; + QUIC_DATAPATH_BINDING* server = nullptr; + QUIC_DATAPATH_BINDING* client = nullptr; + auto serverAddress = GetNewLocalAddr(); + + DataRecvContext RecvContext = {}; + + QuicEventInitialize(&RecvContext.ClientCompletion, FALSE, FALSE); + + VERIFY_QUIC_SUCCESS( + QuicDataPathInitialize( + 0, + DataRecvCallback, + EmptyUnreachableCallback, + &datapath)); + ASSERT_NE(nullptr, datapath); + + QUIC_STATUS Status = QUIC_STATUS_ADDRESS_IN_USE; + while (Status == QUIC_STATUS_ADDRESS_IN_USE) { + serverAddress.SockAddr.Ipv4.sin_port = GetNextPort(); + Status = QuicDataPathBindingCreate( datapath, - nullptr, &serverAddress.SockAddr, - &RecvContext, - &client)); - VERIFY_IS_NOT_NULL(client); - - auto ClientSendContext = - QuicDataPathBindingAllocSendContext(client, 0); - VERIFY_IS_NOT_NULL(ClientSendContext); - - auto ClientDatagram = - QuicDataPathBindingAllocSendDatagram(ClientSendContext, ExpectedDataSize); - VERIFY_IS_NOT_NULL(ClientDatagram); - - memcpy(ClientDatagram->Buffer, ExpectedData, ExpectedDataSize); - - VERIFY_QUIC_SUCCESS( - QuicDataPathBindingSendTo( - client, - &serverAddress.SockAddr, - ClientSendContext)); - - VERIFY_ARE_EQUAL((DWORD)WAIT_OBJECT_0, WaitForSingleObject(RecvContext.ClientCompletion, 2000)); - - QuicDataPathBindingDelete(client); - client = nullptr; - ResetEvent(RecvContext.ClientCompletion); - - VERIFY_QUIC_SUCCESS( - QuicDataPathBindingCreate( - datapath, nullptr, - &serverAddress.SockAddr, &RecvContext, - &client)); - VERIFY_IS_NOT_NULL(client); - - ClientSendContext = - QuicDataPathBindingAllocSendContext(client, 0); - VERIFY_IS_NOT_NULL(ClientSendContext); - - ClientDatagram = - QuicDataPathBindingAllocSendDatagram(ClientSendContext, ExpectedDataSize); - VERIFY_IS_NOT_NULL(ClientDatagram); - - memcpy(ClientDatagram->Buffer, ExpectedData, ExpectedDataSize); - - VERIFY_QUIC_SUCCESS( - QuicDataPathBindingSendTo( - client, - &serverAddress.SockAddr, - ClientSendContext)); - - VERIFY_ARE_EQUAL((DWORD)WAIT_OBJECT_0, WaitForSingleObject(RecvContext.ClientCompletion, 2000)); - - QuicDataPathBindingDelete(client); - QuicDataPathBindingDelete(server); - - QuicDataPathUninitialize( - datapath); - - CloseHandle(RecvContext.ClientCompletion); + &server); +#ifdef _WIN32 + if (Status == HRESULT_FROM_WIN32(WSAEACCES)) { + Status = QUIC_STATUS_ADDRESS_IN_USE; + std::cout << "Replacing EACCESS with ADDRINUSE for port: " << + htons(serverAddress.SockAddr.Ipv4.sin_port) << std::endl; + } +#endif //_WIN32 } -}; + VERIFY_QUIC_SUCCESS(Status); + ASSERT_NE(nullptr, server); + QuicDataPathBindingGetLocalAddress(server, &RecvContext.ServerAddress); + ASSERT_NE(RecvContext.ServerAddress.Ipv4.sin_port, (uint16_t)0); + serverAddress.SetPort(RecvContext.ServerAddress.Ipv4.sin_port); + + VERIFY_QUIC_SUCCESS( + QuicDataPathBindingCreate( + datapath, + nullptr, + &serverAddress.SockAddr, + &RecvContext, + &client)); + ASSERT_NE(nullptr, client); + + auto ClientSendContext = + QuicDataPathBindingAllocSendContext(client, 0); + ASSERT_NE(nullptr, ClientSendContext); + + auto ClientDatagram = + QuicDataPathBindingAllocSendDatagram(ClientSendContext, ExpectedDataSize); + ASSERT_NE(nullptr, ClientDatagram); + + memcpy(ClientDatagram->Buffer, ExpectedData, ExpectedDataSize); + + VERIFY_QUIC_SUCCESS( + QuicDataPathBindingSendTo( + client, + &serverAddress.SockAddr, + ClientSendContext)); + + ASSERT_TRUE(QuicEventWaitWithTimeout(RecvContext.ClientCompletion, 2000)); + + QuicDataPathBindingDelete(client); + client = nullptr; + QuicEventReset(RecvContext.ClientCompletion); + + VERIFY_QUIC_SUCCESS( + QuicDataPathBindingCreate( + datapath, + nullptr, + &serverAddress.SockAddr, + &RecvContext, + &client)); + ASSERT_NE(nullptr, client); + + ClientSendContext = + QuicDataPathBindingAllocSendContext(client, 0); + ASSERT_NE(nullptr, ClientSendContext); + + ClientDatagram = + QuicDataPathBindingAllocSendDatagram(ClientSendContext, ExpectedDataSize); + ASSERT_NE(nullptr, ClientDatagram); + + memcpy(ClientDatagram->Buffer, ExpectedData, ExpectedDataSize); + + VERIFY_QUIC_SUCCESS( + QuicDataPathBindingSendTo( + client, + &serverAddress.SockAddr, + ClientSendContext)); + + ASSERT_TRUE(QuicEventWaitWithTimeout(RecvContext.ClientCompletion, 2000)); + + QuicDataPathBindingDelete(client); + QuicDataPathBindingDelete(server); + + QuicDataPathUninitialize( + datapath); + + QuicEventUninitialize(RecvContext.ClientCompletion); +} + +INSTANTIATE_TEST_SUITE_P(DataPathTest, DataPathTest, ::testing::Values(4, 6), testing::PrintToStringParamName()); diff --git a/src/platform/unittest/TlsTest.cpp b/src/platform/unittest/TlsTest.cpp index 287f95b4118c..9de6636a7eeb 100644 --- a/src/platform/unittest/TlsTest.cpp +++ b/src/platform/unittest/TlsTest.cpp @@ -5,53 +5,36 @@ --*/ -#include "quic_platform.h" +#include "main.h" #include "msquic.h" #include "quic_tls.h" -#define LOG_ONLY_FAILURES -#define INLINE_TEST_METHOD_MARKUP -#include -#include - -#include "quic_trace.h" - #ifdef QUIC_LOGS_WPP #include "tlstest.tmh" #endif -using namespace WEX::Common; -using namespace WEX::Logging; -using namespace WEX::TestExecution; - -#define VERIFY_QUIC_SUCCESS(result, ...) VERIFY_IS_TRUE(QUIC_SUCCEEDED(result), __VA_ARGS__) - -extern "C" { -void* CreateServerCertificate(); -void FreeServerCertificate(void* CertCtx); -} - const uint32_t CertValidationIgnoreFlags = QUIC_CERTIFICATE_FLAG_IGNORE_UNKNOWN_CA | QUIC_CERTIFICATE_FLAG_IGNORE_CERTIFICATE_CN_INVALID; -struct TlsTest : public WEX::TestClass +struct TlsTest : public ::testing::TestWithParam { +protected: QUIC_RUNDOWN_REF SecConfigRundown; - HANDLE SecConfigDoneEvent; - void* SecConfigertContext; + QUIC_EVENT SecConfigDoneEvent; QUIC_SEC_CONFIG* SecConfig; + static QUIC_SEC_CONFIG_PARAMS* SelfSignedCertParams; TlsTest() : - SecConfigDoneEvent(CreateEvent(nullptr, FALSE, FALSE, nullptr)), SecConfig(nullptr) { QuicRundownInitialize(&SecConfigRundown); + QuicEventInitialize(&SecConfigDoneEvent, FALSE, FALSE); } ~TlsTest() { - CloseHandle(SecConfigDoneEvent); + QuicEventUninitialize(SecConfigDoneEvent); if (SecConfig != nullptr) { QuicTlsSecConfigRelease(SecConfig); } @@ -59,10 +42,9 @@ struct TlsTest : public WEX::TestClass QuicRundownUninitialize(&SecConfigRundown); } - BEGIN_TEST_CLASS(TlsTest) - END_TEST_CLASS() - + _Function_class_(QUIC_SEC_CONFIG_CREATE_COMPLETE) static void + QUIC_API OnSecConfigCreateComplete( _In_opt_ void* Context, _In_ QUIC_STATUS Status, @@ -72,43 +54,45 @@ struct TlsTest : public WEX::TestClass TlsTest* pThis = (TlsTest*)Context; VERIFY_QUIC_SUCCESS(Status); pThis->SecConfig = SecConfig; - SetEvent(pThis->SecConfigDoneEvent); + QuicEventSet(pThis->SecConfigDoneEvent); + } + + static void SetUpTestSuite() + { + SelfSignedCertParams = QuicPlatGetSelfSignedCert(QUIC_SELF_SIGN_CERT_USER); + ASSERT_NE(nullptr, SelfSignedCertParams); + } + + static void TearDownTestSuite() + { + QuicPlatFreeSelfSignedCert(SelfSignedCertParams); + SelfSignedCertParams = nullptr; } - TEST_CLASS_SETUP(Setup) + void SetUp() override { - VERIFY_IS_NOT_NULL((SecConfigertContext = CreateServerCertificate())); VERIFY_QUIC_SUCCESS( QuicTlsServerSecConfigCreate( &SecConfigRundown, - QUIC_SEC_CONFIG_FLAG_CERTIFICATE_CONTEXT, - SecConfigertContext, - nullptr, + (QUIC_SEC_CONFIG_FLAGS)SelfSignedCertParams->Flags, + SelfSignedCertParams->Certificate, + SelfSignedCertParams->Principal, this, OnSecConfigCreateComplete)); - VERIFY_IS_TRUE(WaitForSingleObject(SecConfigDoneEvent, 5000) == WAIT_OBJECT_0); - return SecConfig != nullptr; + ASSERT_TRUE(QuicEventWaitWithTimeout(SecConfigDoneEvent, 5000)); } - TEST_CLASS_CLEANUP(Cleanup) + void TearDown() override { QuicTlsSecConfigRelease(SecConfig); SecConfig = nullptr; - FreeServerCertificate(SecConfigertContext); - SecConfigertContext = nullptr; - return true; - } - - TEST_METHOD_CLEANUP(MethodCleanup) - { - return true; } struct TlsSession { QUIC_TLS_SESSION* Ptr; TlsSession() : Ptr(nullptr) { - VERIFY_QUIC_SUCCESS(QuicTlsSessionInitialize("MsQuicTest", &Ptr)); + EXPECT_EQ(QUIC_STATUS_SUCCESS, QuicTlsSessionInitialize("MsQuicTest", &Ptr)); } ~TlsSession() { QuicTlsSessionUninitialize(Ptr); @@ -118,7 +102,7 @@ struct TlsTest : public WEX::TestClass struct TlsContext { QUIC_TLS* Ptr; - HANDLE ProcessCompleteEvent; + QUIC_EVENT ProcessCompleteEvent; QUIC_TLS_PROCESS_STATE State; @@ -128,16 +112,16 @@ struct TlsTest : public WEX::TestClass TlsContext() : Ptr(nullptr), - ProcessCompleteEvent(CreateEvent(nullptr, FALSE, FALSE, nullptr)), Connected(false) { - RtlZeroMemory(&State, sizeof(State)); - State.Buffer = (UINT8*)QUIC_ALLOC_NONPAGED(8000); + QuicEventInitialize(&ProcessCompleteEvent, FALSE, FALSE); + QuicZeroMemory(&State, sizeof(State)); + State.Buffer = (uint8_t*)QUIC_ALLOC_NONPAGED(8000); State.BufferAllocLength = 8000; } ~TlsContext() { QuicTlsUninitialize(Ptr); - CloseHandle(ProcessCompleteEvent); + QuicEventUninitialize(ProcessCompleteEvent); QUIC_FREE(State.Buffer); for (uint8_t i = 0; i < QUIC_PACKET_KEY_COUNT; ++i) { QuicPacketKeyFree(State.ReadKeys[i]); @@ -244,15 +228,15 @@ struct TlsTest : public WEX::TestClass ProcessData( _In_ QUIC_PACKET_KEY_TYPE BufferKey, _In_reads_bytes_(*BufferLength) - const UINT8 * Buffer, - _In_ UINT32 * BufferLength + const uint8_t * Buffer, + _In_ uint32_t * BufferLength ) { - ResetEvent(ProcessCompleteEvent); + QuicEventReset(ProcessCompleteEvent); - VERIFY_IS_TRUE(Buffer != nullptr || *BufferLength == 0); + EXPECT_TRUE(Buffer != nullptr || *BufferLength == 0); if (Buffer != nullptr) { - VERIFY_ARE_EQUAL(BufferKey, State.ReadKey); + EXPECT_EQ(BufferKey, State.ReadKey); *BufferLength = GetCompleteTlsMessagesLength(Buffer, *BufferLength); if (*BufferLength == 0) return (QUIC_TLS_RESULT_FLAGS)0; } @@ -264,11 +248,11 @@ struct TlsTest : public WEX::TestClass BufferLength, &State); if (Result & QUIC_TLS_RESULT_PENDING) { - WaitForSingleObject(ProcessCompleteEvent, INFINITE); + QuicEventWaitForever(ProcessCompleteEvent); Result = QuicTlsProcessDataComplete(Ptr, BufferLength); } - VERIFY_IS_TRUE((Result & QUIC_TLS_RESULT_ERROR) == 0); + EXPECT_TRUE((Result & QUIC_TLS_RESULT_ERROR) == 0); return Result; } @@ -277,14 +261,14 @@ struct TlsTest : public WEX::TestClass ProcessFragmentedData( _In_ QUIC_PACKET_KEY_TYPE BufferKey, _In_reads_bytes_(BufferLength) - const UINT8 * Buffer, - _In_ UINT32 BufferLength, - _In_ UINT32 FragmentSize + const uint8_t * Buffer, + _In_ uint32_t BufferLength, + _In_ uint32_t FragmentSize ) { - UINT32 Result = 0; - UINT32 ConsumedBuffer = FragmentSize; - UINT32 Count = 1; + uint32_t Result = 0; + uint32_t ConsumedBuffer = FragmentSize; + uint32_t Count = 1; while (BufferLength != 0) { if (BufferLength < FragmentSize) { @@ -292,11 +276,9 @@ struct TlsTest : public WEX::TestClass ConsumedBuffer = FragmentSize; } - Log::Comment( - String().Format( - L"Processing fragment of %u bytes", FragmentSize)); + std::cout << "Processing fragment of " << FragmentSize << " bytes" << std::endl; - Result |= (UINT32)ProcessData(BufferKey, Buffer, &ConsumedBuffer); + Result |= (uint32_t)ProcessData(BufferKey, Buffer, &ConsumedBuffer); if (ConsumedBuffer > 0) { Buffer += ConsumedBuffer; @@ -315,24 +297,24 @@ struct TlsTest : public WEX::TestClass QUIC_TLS_RESULT_FLAGS ProcessData( _Inout_ QUIC_TLS_PROCESS_STATE* PeerState, - _In_ UINT32 FragmentSize = 1200 + _In_ uint32_t FragmentSize = 1200 ) { if (PeerState == nullptr) { // // Special case for client hello/initial. // - UINT32 Zero = 0; + uint32_t Zero = 0; return ProcessData(QUIC_PACKET_KEY_INITIAL, nullptr, &Zero); } - UINT32 Result; + uint32_t Result; while (PeerState->BufferLength != 0) { - UINT16 BufferLength; + uint16_t BufferLength; QUIC_PACKET_KEY_TYPE PeerWriteKey; - UINT32 StartOffset = PeerState->BufferTotalLength - PeerState->BufferLength; + uint32_t StartOffset = PeerState->BufferTotalLength - PeerState->BufferLength; if (PeerState->BufferOffset1Rtt != 0 && StartOffset >= PeerState->BufferOffset1Rtt) { PeerWriteKey = QUIC_PACKET_KEY_1_RTT; BufferLength = PeerState->BufferLength; @@ -340,7 +322,7 @@ struct TlsTest : public WEX::TestClass } else if (PeerState->BufferOffsetHandshake != 0 && StartOffset >= PeerState->BufferOffsetHandshake) { PeerWriteKey = QUIC_PACKET_KEY_HANDSHAKE; if (PeerState->BufferOffset1Rtt != 0) { - BufferLength = (UINT16)(PeerState->BufferOffset1Rtt - StartOffset); + BufferLength = (uint16_t)(PeerState->BufferOffset1Rtt - StartOffset); } else { BufferLength = PeerState->BufferLength; } @@ -348,21 +330,21 @@ struct TlsTest : public WEX::TestClass } else { PeerWriteKey = QUIC_PACKET_KEY_INITIAL; if (PeerState->BufferOffsetHandshake != 0) { - BufferLength = (UINT16)(PeerState->BufferOffsetHandshake - StartOffset); + BufferLength = (uint16_t)(PeerState->BufferOffsetHandshake - StartOffset); } else { BufferLength = PeerState->BufferLength; } } Result |= - (UINT32)ProcessFragmentedData( + (uint32_t)ProcessFragmentedData( PeerWriteKey, PeerState->Buffer, BufferLength, FragmentSize); PeerState->BufferLength -= BufferLength; - RtlMoveMemory( + QuicMoveMemory( PeerState->Buffer, PeerState->Buffer + BufferLength, PeerState->BufferLength); @@ -378,7 +360,7 @@ struct TlsTest : public WEX::TestClass _In_ QUIC_CONNECTION* Connection ) { - SetEvent(((TlsContext*)Connection)->ProcessCompleteEvent); + QuicEventSet(((TlsContext*)Connection)->ProcessCompleteEvent); } static BOOLEAN @@ -399,10 +381,10 @@ struct TlsTest : public WEX::TestClass { QUIC_PACKET_KEY* Ptr; PacketKey(QUIC_PACKET_KEY* Key) : Ptr(Key) { - VERIFY_IS_NOT_NULL(Key); + EXPECT_NE(nullptr, Key); } - UINT16 + uint16_t Overhead() { return QUIC_ENCRYPTION_OVERHEAD; @@ -410,11 +392,11 @@ struct TlsTest : public WEX::TestClass bool Encrypt( - _In_ UINT16 HeaderLength, + _In_ uint16_t HeaderLength, _In_reads_bytes_(HeaderLength) - const UINT8* const Header, + const uint8_t* const Header, _In_ uint64_t PacketNumber, - _In_ UINT16 BufferLength, + _In_ uint16_t BufferLength, _Inout_updates_bytes_(BufferLength) uint8_t* Buffer ) { @@ -434,11 +416,11 @@ struct TlsTest : public WEX::TestClass bool Decrypt( - _In_ UINT16 HeaderLength, + _In_ uint16_t HeaderLength, _In_reads_bytes_(HeaderLength) - const UINT8* const Header, + const uint8_t* const Header, _In_ uint64_t PacketNumber, - _In_ UINT16 BufferLength, + _In_ uint16_t BufferLength, _Inout_updates_bytes_(BufferLength) uint8_t* Buffer ) { @@ -459,9 +441,9 @@ struct TlsTest : public WEX::TestClass bool ComputeHpMask( _In_reads_bytes_(16) - const UINT8* const Cipher, + const uint8_t* const Cipher, _Out_writes_bytes_(16) - UINT8* Mask + uint8_t* Mask ) { return @@ -478,404 +460,393 @@ struct TlsTest : public WEX::TestClass DoHandshake( TlsContext& ServerContext, TlsContext& ClientContext, - UINT32 FragmentSize = 1200 + uint32_t FragmentSize = 1200 ) { auto Result = ClientContext.ProcessData(nullptr); - VERIFY_IS_TRUE(Result & QUIC_TLS_RESULT_DATA); + ASSERT_TRUE(Result & QUIC_TLS_RESULT_DATA); Result = ServerContext.ProcessData(&ClientContext.State, FragmentSize); - VERIFY_IS_TRUE(Result & QUIC_TLS_RESULT_DATA); - VERIFY_IS_NOT_NULL(ServerContext.State.WriteKeys[QUIC_PACKET_KEY_1_RTT]); + ASSERT_TRUE(Result & QUIC_TLS_RESULT_DATA); + ASSERT_NE(nullptr, ServerContext.State.WriteKeys[QUIC_PACKET_KEY_1_RTT]); Result = ClientContext.ProcessData(&ServerContext.State, FragmentSize); - VERIFY_IS_TRUE(Result & QUIC_TLS_RESULT_DATA); - VERIFY_IS_TRUE(Result & QUIC_TLS_RESULT_COMPLETE); - VERIFY_IS_NOT_NULL(ClientContext.State.WriteKeys[QUIC_PACKET_KEY_1_RTT]); + ASSERT_TRUE(Result & QUIC_TLS_RESULT_DATA); + ASSERT_TRUE(Result & QUIC_TLS_RESULT_COMPLETE); + ASSERT_NE(nullptr, ClientContext.State.WriteKeys[QUIC_PACKET_KEY_1_RTT]); Result = ServerContext.ProcessData(&ClientContext.State, FragmentSize); - VERIFY_IS_TRUE(Result & QUIC_TLS_RESULT_COMPLETE); + ASSERT_TRUE(Result & QUIC_TLS_RESULT_COMPLETE); } - TEST_METHOD(Initialize) + int64_t + DoEncryption( + PacketKey& Key, + uint16_t BufferSize, + uint64_t LoopCount + ) { - TlsSession ServerSession, ClientSession; - { - TlsContext ServerContext, ClientContext; - ServerContext.InitializeServer(ServerSession, SecConfig); - ClientContext.InitializeClient(ClientSession); - } - } + uint8_t Header[32] = { 0 }; + uint8_t Buffer[(uint16_t)~0] = { 0 }; + uint16_t OverHead = Key.Overhead(); - TEST_METHOD(Handshake) - { - TlsSession ServerSession, ClientSession; - { - TlsContext ServerContext, ClientContext; - ServerContext.InitializeServer(ServerSession, SecConfig); - ClientContext.InitializeClient(ClientSession); - DoHandshake(ServerContext, ClientContext); - } - } + uint64_t Start, End; + Start = QuicTimeUs64(); - TEST_METHOD(HandshakeFragmented) - { - TlsSession ServerSession, ClientSession; - { - TlsContext ServerContext, ClientContext; - ServerContext.InitializeServer(ServerSession, SecConfig); - ClientContext.InitializeClient(ClientSession); - DoHandshake(ServerContext, ClientContext, 200); + for (uint64_t j = 0; j < LoopCount; ++j) { + Key.Encrypt( + sizeof(Header), + Header, + j, + BufferSize + OverHead, + Buffer); } - } - TEST_METHOD(HandshakesSerial) - { - // Server fails to decrypt message during second handshake with shared ClientSession. - // Server still fail to decrypt second handshake with separate ClientSessions. - // Server still fails to decrypt when using the same ServerContext again. - // passes with different ServerContexts. - TlsSession ServerSession, ClientSession/*, ClientSession2*/; - QUIC_SEC_CONFIG* ClientSecConfig = nullptr; - VERIFY_QUIC_SUCCESS( - QuicTlsClientSecConfigCreate( - CertValidationIgnoreFlags, - &ClientSecConfig)); - { - TlsContext ServerContext, ClientContext1; - ServerContext.InitializeServer(ServerSession, SecConfig); - ClientContext1.InitializeClient(ClientSession, ClientSecConfig); - DoHandshake(ServerContext, ClientContext1); - } - { - TlsContext ServerContext, ClientContext2; - ServerContext.InitializeServer(ServerSession, SecConfig); - ClientContext2.InitializeClient(ClientSession, ClientSecConfig); - DoHandshake(ServerContext, ClientContext2); - } - QuicTlsSecConfigRelease(ClientSecConfig); + End = QuicTimeUs64(); + + return End - Start; } - TEST_METHOD(HandshakesInterleaved) + int64_t + DoEncryptionWithPNE( + PacketKey& Key, + uint16_t BufferSize, + uint64_t LoopCount + ) { - TlsSession ServerSession, ClientSession; - QUIC_SEC_CONFIG* ClientSecConfig = nullptr; - VERIFY_QUIC_SUCCESS( - QuicTlsClientSecConfigCreate( - CertValidationIgnoreFlags, - &ClientSecConfig)); - { - TlsContext ServerContext1, ServerContext2, ClientContext1, ClientContext2; - ServerContext1.InitializeServer(ServerSession, SecConfig); - ClientContext1.InitializeClient(ClientSession, ClientSecConfig); - ServerContext2.InitializeServer(ServerSession, SecConfig); - ClientContext2.InitializeClient(ClientSession, ClientSecConfig); - - auto Result = ClientContext1.ProcessData(nullptr); - VERIFY_IS_TRUE(Result & QUIC_TLS_RESULT_DATA); - - Result = ClientContext2.ProcessData(nullptr); - VERIFY_IS_TRUE(Result & QUIC_TLS_RESULT_DATA); + uint8_t Header[32] = { 0 }; + uint8_t Buffer[(uint16_t)~0] = { 0 }; + uint16_t OverHead = Key.Overhead(); + uint8_t Mask[16]; - Result = ServerContext1.ProcessData(&ClientContext1.State); - VERIFY_IS_TRUE(Result & QUIC_TLS_RESULT_DATA); - VERIFY_IS_NOT_NULL(ServerContext1.State.WriteKeys[QUIC_PACKET_KEY_1_RTT]); + uint64_t Start, End; + Start = QuicTimeUs64(); - Result = ServerContext2.ProcessData(&ClientContext2.State); - VERIFY_IS_TRUE(Result & QUIC_TLS_RESULT_DATA); - VERIFY_IS_NOT_NULL(ServerContext2.State.WriteKeys[QUIC_PACKET_KEY_1_RTT]); + for (uint64_t j = 0; j < LoopCount; ++j) { + Key.Encrypt( + sizeof(Header), + Header, + j, + BufferSize + OverHead, + Buffer); + Key.ComputeHpMask(Buffer, Mask); + for (uint32_t i = 0; i < sizeof(Mask); i++) { + Header[i] ^= Mask[i]; + } + } - Result = ClientContext1.ProcessData(&ServerContext1.State); - VERIFY_IS_TRUE(Result & QUIC_TLS_RESULT_DATA); - VERIFY_IS_TRUE(Result & QUIC_TLS_RESULT_COMPLETE); - VERIFY_IS_NOT_NULL(ClientContext1.State.WriteKeys[QUIC_PACKET_KEY_1_RTT]); + End = QuicTimeUs64(); - Result = ClientContext2.ProcessData(&ServerContext2.State); - VERIFY_IS_TRUE(Result & QUIC_TLS_RESULT_DATA); - VERIFY_IS_TRUE(Result & QUIC_TLS_RESULT_COMPLETE); - VERIFY_IS_NOT_NULL(ClientContext2.State.WriteKeys[QUIC_PACKET_KEY_1_RTT]); + return End - Start; + } +}; - Result = ServerContext1.ProcessData(&ClientContext1.State); - VERIFY_IS_TRUE(Result & QUIC_TLS_RESULT_COMPLETE); +QUIC_SEC_CONFIG_PARAMS* TlsTest::SelfSignedCertParams = nullptr; - Result = ServerContext2.ProcessData(&ClientContext2.State); - VERIFY_IS_TRUE(Result & QUIC_TLS_RESULT_COMPLETE); - } - QuicTlsSecConfigRelease(ClientSecConfig); +TEST_F(TlsTest, Initialize) +{ + TlsSession ServerSession, ClientSession; + { + TlsContext ServerContext, ClientContext; + ServerContext.InitializeServer(ServerSession, SecConfig); + ClientContext.InitializeClient(ClientSession); } +} - TEST_METHOD(One1RttKey) +TEST_F(TlsTest, Handshake) +{ + TlsSession ServerSession, ClientSession; { - BEGIN_TEST_METHOD_PROPERTIES() - TEST_METHOD_PROPERTY(L"Data:PNE", L"{0,1}") - END_TEST_METHOD_PROPERTIES() + TlsContext ServerContext, ClientContext; + ServerContext.InitializeServer(ServerSession, SecConfig); + ClientContext.InitializeClient(ClientSession); + DoHandshake(ServerContext, ClientContext); + } +} - int PNE; - TestData::TryGetValue(L"PNE", PNE); +TEST_F(TlsTest, HandshakeFragmented) +{ + TlsSession ServerSession, ClientSession; + { + TlsContext ServerContext, ClientContext; + ServerContext.InitializeServer(ServerSession, SecConfig); + ClientContext.InitializeClient(ClientSession); + DoHandshake(ServerContext, ClientContext, 200); + } +} - TlsSession ServerSession, ClientSession; - { - TlsContext ServerContext, ClientContext; - ServerContext.InitializeServer(ServerSession, SecConfig); - ClientContext.InitializeClient(ClientSession); - DoHandshake(ServerContext, ClientContext); +TEST_F(TlsTest, HandshakesSerial) +{ + // Server fails to decrypt message during second handshake with shared ClientSession. + // Server still fail to decrypt second handshake with separate ClientSessions. + // Server still fails to decrypt when using the same ServerContext again. + // passes with different ServerContexts. + TlsSession ServerSession, ClientSession/*, ClientSession2*/; + QUIC_SEC_CONFIG* ClientSecConfig = nullptr; + VERIFY_QUIC_SUCCESS( + QuicTlsClientSecConfigCreate( + CertValidationIgnoreFlags, + &ClientSecConfig)); + { + TlsContext ServerContext, ClientContext1; + ServerContext.InitializeServer(ServerSession, SecConfig); + ClientContext1.InitializeClient(ClientSession, ClientSecConfig); + DoHandshake(ServerContext, ClientContext1); + } + { + TlsContext ServerContext, ClientContext2; + ServerContext.InitializeServer(ServerSession, SecConfig); + ClientContext2.InitializeClient(ClientSession, ClientSecConfig); + DoHandshake(ServerContext, ClientContext2); + } + QuicTlsSecConfigRelease(ClientSecConfig); +} - PacketKey ServerKey(ServerContext.State.WriteKeys[QUIC_PACKET_KEY_1_RTT]); - PacketKey ClientKey(ClientContext.State.ReadKeys[QUIC_PACKET_KEY_1_RTT]); +TEST_F(TlsTest, HandshakesInterleaved) +{ + TlsSession ServerSession, ClientSession; + QUIC_SEC_CONFIG* ClientSecConfig = nullptr; + VERIFY_QUIC_SUCCESS( + QuicTlsClientSecConfigCreate( + CertValidationIgnoreFlags, + &ClientSecConfig)); + { + TlsContext ServerContext1, ServerContext2, ClientContext1, ClientContext2; + ServerContext1.InitializeServer(ServerSession, SecConfig); + ClientContext1.InitializeClient(ClientSession, ClientSecConfig); + ServerContext2.InitializeServer(ServerSession, SecConfig); + ClientContext2.InitializeClient(ClientSession, ClientSecConfig); - UINT8 Header[32] = { 1, 2, 3, 4 }; - uint64_t PacketNumber = 0; - UINT8 Buffer[1000] = { 0 }; + auto Result = ClientContext1.ProcessData(nullptr); + ASSERT_TRUE(Result & QUIC_TLS_RESULT_DATA); - VERIFY_IS_TRUE( - ServerKey.Encrypt( - sizeof(Header), - Header, - PacketNumber, - sizeof(Buffer), - Buffer)); + Result = ClientContext2.ProcessData(nullptr); + ASSERT_TRUE(Result & QUIC_TLS_RESULT_DATA); - if (PNE != 0) { - UINT8 Mask[16]; + Result = ServerContext1.ProcessData(&ClientContext1.State); + ASSERT_TRUE(Result & QUIC_TLS_RESULT_DATA); + ASSERT_NE(nullptr, ServerContext1.State.WriteKeys[QUIC_PACKET_KEY_1_RTT]); - VERIFY_IS_TRUE( - ServerKey.ComputeHpMask( - Buffer, - Mask)); + Result = ServerContext2.ProcessData(&ClientContext2.State); + ASSERT_TRUE(Result & QUIC_TLS_RESULT_DATA); + ASSERT_NE(nullptr, ServerContext2.State.WriteKeys[QUIC_PACKET_KEY_1_RTT]); - for (UINT32 i = 0; i < sizeof(Mask); i++) { - Header[i] ^= Mask[i]; - } + Result = ClientContext1.ProcessData(&ServerContext1.State); + ASSERT_TRUE(Result & QUIC_TLS_RESULT_DATA); + ASSERT_TRUE(Result & QUIC_TLS_RESULT_COMPLETE); + ASSERT_NE(nullptr, ClientContext1.State.WriteKeys[QUIC_PACKET_KEY_1_RTT]); - VERIFY_IS_TRUE( - ClientKey.ComputeHpMask( - Buffer, - Mask)); + Result = ClientContext2.ProcessData(&ServerContext2.State); + ASSERT_TRUE(Result & QUIC_TLS_RESULT_DATA); + ASSERT_TRUE(Result & QUIC_TLS_RESULT_COMPLETE); + ASSERT_NE(nullptr, ClientContext2.State.WriteKeys[QUIC_PACKET_KEY_1_RTT]); - for (UINT32 i = 0; i < sizeof(Mask); i++) { - Header[i] ^= Mask[i]; - } - } + Result = ServerContext1.ProcessData(&ClientContext1.State); + ASSERT_TRUE(Result & QUIC_TLS_RESULT_COMPLETE); - VERIFY_IS_TRUE( - ClientKey.Decrypt( - sizeof(Header), - Header, - PacketNumber, - sizeof(Buffer), - Buffer)); - } + Result = ServerContext2.ProcessData(&ClientContext2.State); + ASSERT_TRUE(Result & QUIC_TLS_RESULT_COMPLETE); } + QuicTlsSecConfigRelease(ClientSecConfig); +} + +TEST_P(TlsTest, One1RttKey) +{ + bool PNE = GetParam(); - TEST_METHOD(KeyUpdate) + TlsSession ServerSession, ClientSession; { - BEGIN_TEST_METHOD_PROPERTIES() - TEST_METHOD_PROPERTY(L"Data:PNE", L"{0,1}") - END_TEST_METHOD_PROPERTIES() + TlsContext ServerContext, ClientContext; + ServerContext.InitializeServer(ServerSession, SecConfig); + ClientContext.InitializeClient(ClientSession); + DoHandshake(ServerContext, ClientContext); - int PNE; - TestData::TryGetValue(L"PNE", PNE); + PacketKey ServerKey(ServerContext.State.WriteKeys[QUIC_PACKET_KEY_1_RTT]); + PacketKey ClientKey(ClientContext.State.ReadKeys[QUIC_PACKET_KEY_1_RTT]); - TlsSession ServerSession, ClientSession; - { - TlsContext ServerContext, ClientContext; - ServerContext.InitializeServer(ServerSession, SecConfig); - ClientContext.InitializeClient(ClientSession); - DoHandshake(ServerContext, ClientContext); + uint8_t Header[32] = { 1, 2, 3, 4 }; + uint64_t PacketNumber = 0; + uint8_t Buffer[1000] = { 0 }; - QUIC_PACKET_KEY* UpdateWriteKey, *UpdateReadKey = nullptr; + ASSERT_TRUE( + ServerKey.Encrypt( + sizeof(Header), + Header, + PacketNumber, + sizeof(Buffer), + Buffer)); - VERIFY_QUIC_SUCCESS( - QuicPacketKeyUpdate( - ServerContext.State.WriteKeys[QUIC_PACKET_KEY_1_RTT], - &UpdateWriteKey)); - VERIFY_QUIC_SUCCESS( - QuicPacketKeyUpdate( - ClientContext.State.ReadKeys[QUIC_PACKET_KEY_1_RTT], - &UpdateReadKey)); + if (PNE) { + uint8_t Mask[16]; - if (PNE != 0) { - // - // If PNE is enabled, copy the header keys to the new packet - // key structs. - // - UpdateWriteKey->HeaderKey = ServerContext.State.WriteKeys[QUIC_PACKET_KEY_1_RTT]->HeaderKey; - ServerContext.State.WriteKeys[QUIC_PACKET_KEY_1_RTT]->HeaderKey = NULL; + ASSERT_TRUE( + ServerKey.ComputeHpMask( + Buffer, + Mask)); - UpdateReadKey->HeaderKey = ClientContext.State.ReadKeys[QUIC_PACKET_KEY_1_RTT]->HeaderKey; - ClientContext.State.ReadKeys[QUIC_PACKET_KEY_1_RTT]->HeaderKey = NULL; + for (uint32_t i = 0; i < sizeof(Mask); i++) { + Header[i] ^= Mask[i]; } - PacketKey ServerKey(UpdateWriteKey); - PacketKey ClientKey(UpdateReadKey); - - UINT8 Header[32] = { 1, 2, 3, 4 }; - uint64_t PacketNumber = 0; - UINT8 Buffer[1000] = { 0 }; - - VERIFY_IS_TRUE( - ServerKey.Encrypt( - sizeof(Header), - Header, - PacketNumber, - sizeof(Buffer), - Buffer)); + ASSERT_TRUE( + ClientKey.ComputeHpMask( + Buffer, + Mask)); - if (PNE != 0) { - UINT8 Mask[16]; + for (uint32_t i = 0; i < sizeof(Mask); i++) { + Header[i] ^= Mask[i]; + } + } - VERIFY_IS_TRUE( - ServerKey.ComputeHpMask( - Buffer, - Mask)); + ASSERT_TRUE( + ClientKey.Decrypt( + sizeof(Header), + Header, + PacketNumber, + sizeof(Buffer), + Buffer)); + } +} - for (UINT32 i = 0; i < sizeof(Mask); i++) { - Header[i] ^= Mask[i]; - } +TEST_P(TlsTest, KeyUpdate) +{ - VERIFY_IS_TRUE( - ClientKey.ComputeHpMask( - Buffer, - Mask)); + bool PNE = GetParam(); - for (UINT32 i = 0; i < sizeof(Mask); i++) { - Header[i] ^= Mask[i]; - } - } + TlsSession ServerSession, ClientSession; + { + TlsContext ServerContext, ClientContext; + ServerContext.InitializeServer(ServerSession, SecConfig); + ClientContext.InitializeClient(ClientSession); + DoHandshake(ServerContext, ClientContext); - VERIFY_IS_TRUE( - ClientKey.Decrypt( - sizeof(Header), - Header, - PacketNumber, - sizeof(Buffer), - Buffer)); + QUIC_PACKET_KEY* UpdateWriteKey, *UpdateReadKey = nullptr; - QuicPacketKeyFree(UpdateWriteKey); - QuicPacketKeyFree(UpdateReadKey); + VERIFY_QUIC_SUCCESS( + QuicPacketKeyUpdate( + ServerContext.State.WriteKeys[QUIC_PACKET_KEY_1_RTT], + &UpdateWriteKey)); + VERIFY_QUIC_SUCCESS( + QuicPacketKeyUpdate( + ClientContext.State.ReadKeys[QUIC_PACKET_KEY_1_RTT], + &UpdateReadKey)); + + if (PNE) { + // + // If PNE is enabled, copy the header keys to the new packet + // key structs. + // + UpdateWriteKey->HeaderKey = ServerContext.State.WriteKeys[QUIC_PACKET_KEY_1_RTT]->HeaderKey; + ServerContext.State.WriteKeys[QUIC_PACKET_KEY_1_RTT]->HeaderKey = NULL; + + UpdateReadKey->HeaderKey = ClientContext.State.ReadKeys[QUIC_PACKET_KEY_1_RTT]->HeaderKey; + ClientContext.State.ReadKeys[QUIC_PACKET_KEY_1_RTT]->HeaderKey = NULL; } - } - LONGLONG - DoEncryption( - PacketKey& Key, - UINT16 BufferSize, - uint64_t LoopCount - ) - { - UINT8 Header[32] = { 0 }; - UINT8 Buffer[MAXUINT16] = { 0 }; - UINT16 OverHead = Key.Overhead(); + PacketKey ServerKey(UpdateWriteKey); + PacketKey ClientKey(UpdateReadKey); - LARGE_INTEGER Start, End; - QueryPerformanceCounter(&Start); + uint8_t Header[32] = { 1, 2, 3, 4 }; + uint64_t PacketNumber = 0; + uint8_t Buffer[1000] = { 0 }; - for (uint64_t j = 0; j < LoopCount; ++j) { - Key.Encrypt( + ASSERT_TRUE( + ServerKey.Encrypt( sizeof(Header), Header, - j, - BufferSize + OverHead, - Buffer); - } + PacketNumber, + sizeof(Buffer), + Buffer)); - QueryPerformanceCounter(&End); + if (PNE) { + uint8_t Mask[16]; - return End.QuadPart - Start.QuadPart; - } + ASSERT_TRUE( + ServerKey.ComputeHpMask( + Buffer, + Mask)); - LONGLONG - DoEncryptionWithPNE( - PacketKey& Key, - UINT16 BufferSize, - uint64_t LoopCount - ) - { - UINT8 Header[32] = { 0 }; - UINT8 Buffer[MAXUINT16] = { 0 }; - UINT16 OverHead = Key.Overhead(); - UINT8 Mask[16]; + for (uint32_t i = 0; i < sizeof(Mask); i++) { + Header[i] ^= Mask[i]; + } - LARGE_INTEGER Start, End; - QueryPerformanceCounter(&Start); + ASSERT_TRUE( + ClientKey.ComputeHpMask( + Buffer, + Mask)); - for (uint64_t j = 0; j < LoopCount; ++j) { - Key.Encrypt( - sizeof(Header), - Header, - j, - BufferSize + OverHead, - Buffer); - Key.ComputeHpMask(Buffer, Mask); - for (UINT32 i = 0; i < sizeof(Mask); i++) { + for (uint32_t i = 0; i < sizeof(Mask); i++) { Header[i] ^= Mask[i]; } } - QueryPerformanceCounter(&End); + ASSERT_TRUE( + ClientKey.Decrypt( + sizeof(Header), + Header, + PacketNumber, + sizeof(Buffer), + Buffer)); - return End.QuadPart - Start.QuadPart; + QuicPacketKeyFree(UpdateWriteKey); + QuicPacketKeyFree(UpdateReadKey); } +} - TEST_METHOD(PacketEncryptionPerf) + +TEST_P(TlsTest, PacketEncryptionPerf) +{ + + bool PNE = GetParam(); + + TlsSession ServerSession, ClientSession; { - BEGIN_TEST_METHOD_PROPERTIES() - TEST_METHOD_PROPERTY(L"Data:PNE", L"{0,1}") - END_TEST_METHOD_PROPERTIES() + TlsContext ServerContext, ClientContext; + ServerContext.InitializeServer(ServerSession, SecConfig); + ClientContext.InitializeClient(ClientSession); + DoHandshake(ServerContext, ClientContext); - int PNE; - TestData::TryGetValue(L"PNE", PNE); + PacketKey ServerKey(ServerContext.State.WriteKeys[QUIC_PACKET_KEY_1_RTT]); - TlsSession ServerSession, ClientSession; + const uint64_t LoopCount = 10000; + uint16_t BufferSizes[] = { - TlsContext ServerContext, ClientContext; - ServerContext.InitializeServer(ServerSession, SecConfig); - ClientContext.InitializeClient(ClientSession); - DoHandshake(ServerContext, ClientContext); - - PacketKey ServerKey(ServerContext.State.WriteKeys[QUIC_PACKET_KEY_1_RTT]); - - const uint64_t LoopCount = 10000; - UINT16 BufferSizes[] = - { - 4, - 16, - 64, - 256, - 600, - 1000, - 1200, - 1450, - //8000, - //65000 - }; - - LARGE_INTEGER PerfFreq; - QueryPerformanceFrequency(&PerfFreq); - - HANDLE CurrentThread = GetCurrentThread(); - DWORD ProcNumber = GetCurrentProcessorNumber(); - DWORD_PTR OldAffinityMask = - SetThreadAffinityMask(CurrentThread, (DWORD_PTR)1 << (DWORD_PTR)ProcNumber); - SetThreadPriority(CurrentThread, THREAD_PRIORITY_HIGHEST); - - for (UINT8 i = 0; i < ARRAYSIZE(BufferSizes); ++i) { - LONGLONG elapsedMicroseconds = - PNE == 0 ? - DoEncryption(ServerKey, BufferSizes[i], LoopCount) : - DoEncryptionWithPNE(ServerKey, BufferSizes[i], LoopCount); - elapsedMicroseconds *= 1000000; - elapsedMicroseconds /= PerfFreq.QuadPart; - - Log::Comment( - String().Format( - L"%lld.%d milliseconds elapsed encrypting %u bytes %u times", - elapsedMicroseconds / 1000, (int)(elapsedMicroseconds % 1000), - BufferSizes[i], LoopCount)); - } + 4, + 16, + 64, + 256, + 600, + 1000, + 1200, + 1450, + //8000, + //65000 + }; + +#ifdef _WIN32 + HANDLE CurrentThread = GetCurrentThread(); + DWORD ProcNumber = GetCurrentProcessorNumber(); + DWORD_PTR OldAffinityMask = + SetThreadAffinityMask(CurrentThread, (DWORD_PTR)1 << (DWORD_PTR)ProcNumber); + SetThreadPriority(CurrentThread, THREAD_PRIORITY_HIGHEST); +#endif + + for (uint8_t i = 0; i < ARRAYSIZE(BufferSizes); ++i) { + int64_t elapsedMicroseconds = + PNE == 0 ? + DoEncryption(ServerKey, BufferSizes[i], LoopCount) : + DoEncryptionWithPNE(ServerKey, BufferSizes[i], LoopCount); - SetThreadPriority(CurrentThread, THREAD_PRIORITY_NORMAL); - SetThreadAffinityMask(CurrentThread, OldAffinityMask); + std::cout << elapsedMicroseconds / 1000 << "." << (int)(elapsedMicroseconds % 1000) << + " milliseconds elapsed encrypting " + << BufferSizes[i] << " bytes " << LoopCount << " times" << std::endl; } + +#ifdef _WIN32 + SetThreadPriority(CurrentThread, THREAD_PRIORITY_NORMAL); + SetThreadAffinityMask(CurrentThread, OldAffinityMask); +#endif } -}; +} + +INSTANTIATE_TEST_SUITE_P(TlsTest, TlsTest, ::testing::Bool()); diff --git a/src/platform/unittest/linux/DataPathTest.c b/src/platform/unittest/linux/DataPathTest.c deleted file mode 100644 index e8db3e7a2a5b..000000000000 --- a/src/platform/unittest/linux/DataPathTest.c +++ /dev/null @@ -1,1013 +0,0 @@ -/*++ - - Copyright (c) Microsoft Corporation. - Licensed under the MIT License. - ---*/ - -#include "quic_datapath.h" -#include "msquic.h" - -#define LOGINFO(fmt, ...) \ - printf("[INFO]: " fmt "\n", ##__VA_ARGS__) - -#define LOGERROR(fmt, ...) \ - printf("[ERROR]: " fmt "\n", ##__VA_ARGS__) - - -// -// Test case info. -// - -typedef struct _DAL_TESTCASE { - // - // Test case runner. - // - BOOLEAN(*TestCaseFunc)(); - - // - // Test case name. - // - - char* TestCaseName; - -} DAL_TESTCASE, *PDAL_TESTCASE; - - -// -// Receive context. -// - -typedef struct _DAL_TEST_RECV_CONTEXT { - // - // The server address. - // - - QUIC_ADDR ServerAddress; - - // - // Client receive completion event. - // - - QUIC_EVENT ClientCompletion; - -} DAL_TEST_RECV_CONTEXT; - - -static const size_t DalTestExpectedDataSize = 1 * 1024; -static char* DalTestExpectedData = NULL; -static uint16_t DalTestNextPortH = 0; -static QUIC_ADDR DalTestLocalIPv4 = {0}; -static QUIC_ADDR DalTestLocalIPv6 = {0}; -static QUIC_ADDR DalTestZeroIP = {0}; - - -static -void -DalTestResolve( - _Out_ QUIC_ADDR* SockAddr, - _In_ QUIC_ADDRESS_FAMILY Af, - _In_ const char *HostName - ); - -static -uint16_t -DalTestGetNextPortH( - void - ); - -static -uint16_t -DalTestGetNextPortN( - void - ); - -static -QUIC_ADDR -DalTestGetNewLocalIPv4( - bool RandomPort - ); - -static -QUIC_ADDR -DalTestGetNewLocalIPv6( - _In_ bool RandomPort - ); - -static -QUIC_ADDR -DalTestGetNewLocalAddr( - _In_ int AddressFamily, - _In_ bool RandomPort - ); - -static -void -DalTestSetUpTestCase( - void - ); - -static -void -DalTestTearDownTestCase( - void - ); - -static -void -DalTestEmptyReceiveCallback( - _In_ QUIC_DATAPATH_BINDING* Binding, - _In_ void* RecvContext, - _In_ QUIC_RECV_DATAGRAM* RecvPacket - ); - -static -void -DalTestEmptyUnreachableCallback( - _In_ QUIC_DATAPATH_BINDING* Binding, - _In_ void* Context, - _In_ const QUIC_ADDR* RemoteAddress - ); - -static -void -DalTestDataRecvCallback( - _In_ QUIC_DATAPATH_BINDING* Binding, - _In_ void *Context, - _In_ QUIC_RECV_DATAGRAM* RecvPacket - ); - -static -BOOLEAN -DalTestInitialize( - void - ); - -static -BOOLEAN -DalTestInitializeInvalid( - void - ); - -static -BOOLEAN -DalTestBind( - void - ); - -static -BOOLEAN -DalTestRebind( - void - ); - -static -BOOLEAN -DalTestDataSend( - void - ); - -static -BOOLEAN -DalTestDataSendMultiple( - void - ); - -static -void -DalTestExecuteTestCase( - _In_ uint32_t TestCaseIndex - ); - -static -void -DalTestHelp( - _In_ char *argv[] - ); - - -static -void -DalTestResolve( - _Out_ QUIC_ADDR* SockAddr, - _In_ QUIC_ADDRESS_FAMILY Af, - _In_ const char *HostName - ) - -{ - int Ret = 0; - ADDRINFO hints = {0}; - ADDRINFO *ai = NULL; - - // - // Prepopulate hint with input family. - // - - hints.ai_family = Af; - hints.ai_flags = AI_CANONNAME; - - Ret = getaddrinfo(HostName, NULL, &hints, &ai); - QUIC_FRE_ASSERT(Ret == 0); - - memcpy(SockAddr, ai->ai_addr, ai->ai_addrlen); - - freeaddrinfo(ai); -} - - -static -uint16_t -DalTestGetNextPortH( - void - ) - -{ - return (++DalTestNextPortH); -} - - -static -uint16_t -DalTestGetNextPortN( - void - ) - -{ - return htons(DalTestGetNextPortH()); -} - - -static -QUIC_ADDR -DalTestGetNewLocalIPv4( - bool RandomPort - ) - -{ - QUIC_ADDR ipv4Copy = DalTestLocalIPv4; - - if (RandomPort) { - ipv4Copy.Ipv4.sin_port = DalTestGetNextPortN(); - } else { - ipv4Copy.Ipv4.sin_port = 0; - } - - return ipv4Copy; -} - - -static -QUIC_ADDR -DalTestGetNewLocalIPv6( - _In_ bool RandomPort - ) - -{ - QUIC_ADDR ipv6Copy = DalTestLocalIPv6; - - if (RandomPort) { - ipv6Copy.Ipv6.sin6_port = DalTestGetNextPortN(); - } else { - ipv6Copy.Ipv6.sin6_port = 0; - } - - return ipv6Copy; -} - - -static -QUIC_ADDR -DalTestGetNewLocalAddr( - _In_ int AddressFamily, - _In_ bool RandomPort - ) - -{ - if (AddressFamily == 4) { - return DalTestGetNewLocalIPv4(RandomPort); - } else if (AddressFamily == 6) { - return DalTestGetNewLocalIPv6(RandomPort); - } else { - QUIC_FRE_ASSERT(FALSE); - return DalTestZeroIP; - } -} - - -static -void -DalTestSetUpTestCase( - void - ) - -{ - // - // Initialize a semi-random base port number. - // - - DalTestNextPortH = 50000 + (getpid() % 10000) + (rand() % 5000); - - DalTestResolve(&DalTestLocalIPv4, AF_INET, "localhost"); - DalTestResolve(&DalTestLocalIPv6, AF_INET6, "ip6-localhost"); - - DalTestExpectedData = (char*)malloc(DalTestExpectedDataSize); - QUIC_FRE_ASSERT(DalTestExpectedData != NULL); -} - - -static -void -DalTestTearDownTestCase( - void - ) - -{ - if (DalTestExpectedData != NULL) { - free(DalTestExpectedData); - DalTestExpectedData = NULL; - } -} - - -static -void -DalTestEmptyReceiveCallback( - _In_ QUIC_DATAPATH_BINDING* Binding, - _In_ void* RecvContext, - _In_ QUIC_RECV_DATAGRAM* RecvPacket - ) - -{ - UNREFERENCED_PARAMETER(Binding); - UNREFERENCED_PARAMETER(RecvContext); - UNREFERENCED_PARAMETER(RecvPacket); - return; -} - - -static -void -DalTestEmptyUnreachableCallback( - _In_ QUIC_DATAPATH_BINDING* Binding, - _In_ void* Context, - _In_ const QUIC_ADDR* RemoteAddress - ) - -{ - UNREFERENCED_PARAMETER(Binding); - UNREFERENCED_PARAMETER(Context); - UNREFERENCED_PARAMETER(RemoteAddress); - return; -} - - -static -BOOLEAN -DalTestInitialize( - void - ) - -{ - QUIC_DATAPATH* datapath = NULL; - QUIC_STATUS Status = QUIC_STATUS_SUCCESS; - - Status = - QuicDataPathInitialize( - 0, - DalTestEmptyReceiveCallback, - DalTestEmptyUnreachableCallback, - &datapath); - - if (Status != QUIC_STATUS_SUCCESS) { - LOGINFO("QuicDataPathInitialize failed"); - return FALSE; - } - - if (datapath == NULL) { - LOGINFO("datapth is NULL"); - return FALSE; - } - - QuicDataPathUninitialize(datapath); - - return TRUE; -} - - -static -BOOLEAN -DalTestInitializeInvalid( - void - ) - -{ - QUIC_DATAPATH* datapath = NULL; - QUIC_STATUS Status = QuicDataPathInitialize(0, 0, 0, 0); - - if (Status != QUIC_STATUS_INVALID_PARAMETER) { - return FALSE; - } - - return TRUE; -} - - -static -BOOLEAN -DalTestBind( - void - ) - -{ - QUIC_DATAPATH* datapath = NULL; - QUIC_DATAPATH_BINDING* binding = NULL; - QUIC_STATUS Status = QUIC_STATUS_SUCCESS; - - Status = - QuicDataPathInitialize( - 0, - DalTestEmptyReceiveCallback, - DalTestEmptyUnreachableCallback, - &datapath); - - if (Status != QUIC_STATUS_SUCCESS) { - return FALSE; - } - - if (Status != QUIC_STATUS_SUCCESS) { - return FALSE; - } - - if (datapath == NULL) { - return FALSE; - } - - Status = - QuicDataPathBindingCreate( - datapath, - NULL, - NULL, - NULL, - &binding); - - if (Status != QUIC_STATUS_SUCCESS) { - return FALSE; - } - - if (binding == NULL) { - return FALSE; - } - - QUIC_ADDR Address; - QuicDataPathBindingGetLocalAddress(binding, &Address); - - if (QuicAddrGetPort(&Address) == (uint16_t)0) { - return FALSE; - } - - QuicDataPathBindingDelete(binding); - - QuicDataPathUninitialize(datapath); - - return TRUE; -} - - -static -BOOLEAN -DalTestRebind( - void - ) - -{ - QUIC_DATAPATH* datapath = NULL; - QUIC_DATAPATH_BINDING* binding1 = NULL; - QUIC_DATAPATH_BINDING* binding2 = NULL; - QUIC_STATUS Status = QUIC_STATUS_SUCCESS; - - Status = - QuicDataPathInitialize( - 0, - DalTestEmptyReceiveCallback, - DalTestEmptyUnreachableCallback, - &datapath); - - if (Status != QUIC_STATUS_SUCCESS) { - return FALSE; - } - - if (datapath == NULL) { - return FALSE; - } - - Status = - QuicDataPathBindingCreate( - datapath, - NULL, - NULL, - NULL, - &binding1); - - if (Status != QUIC_STATUS_SUCCESS) { - return FALSE; - } - - if (binding1 == NULL) { - return FALSE; - } - - QUIC_ADDR Address1 = {0}; - QuicDataPathBindingGetLocalAddress(binding1, &Address1); - - if (QuicAddrGetPort(&Address1) == (uint16_t)0) { - return FALSE; - } - - Status = - QuicDataPathBindingCreate( - datapath, - NULL, - NULL, - NULL, - &binding2); - - if (Status != QUIC_STATUS_SUCCESS) { - return FALSE; - } - - if (binding2 == NULL) { - return FALSE; - } - - QUIC_ADDR Address2 = {0}; - QuicDataPathBindingGetLocalAddress(binding2, &Address2); - - if (QuicAddrGetPort(&Address2) == (uint16_t)0) { - return FALSE; - } - - QuicDataPathBindingDelete(binding1); - QuicDataPathBindingDelete(binding2); - - QuicDataPathUninitialize(datapath); - - return TRUE; -} - - -static -void -DalTestDataRecvCallback( - _In_ QUIC_DATAPATH_BINDING* Binding, - _In_ void *Context, - _In_ QUIC_RECV_DATAGRAM* RecvPacket - ) - -{ - QUIC_STATUS Status = QUIC_STATUS_SUCCESS; - DAL_TEST_RECV_CONTEXT* RecvContext = (DAL_TEST_RECV_CONTEXT*)Context; - - if (RecvContext == NULL) { - LOGERROR("RecvContext NULL"); - return; - } - - if (RecvPacket->BufferLength != DalTestExpectedDataSize) { - LOGERROR("RecvPacket->BufferLength != DalTestExpectedDataSize"); - return; - } - - if (memcmp(RecvPacket->Buffer, DalTestExpectedData, DalTestExpectedDataSize) != 0) { - LOGERROR("RecvPacket->Buffer != DalTestExpectedData"); - return; - } - - if (QuicAddrGetPort(&RecvPacket->Tuple->LocalAddress) == - QuicAddrGetPort(&RecvContext->ServerAddress)) { - LOGINFO("Sending PONG"); - QUIC_DATAPATH_SEND_CONTEXT* ServerSendContext = - QuicDataPathBindingAllocSendContext(Binding, 0); - - if (ServerSendContext == NULL) { - LOGERROR("ServerSendContext == NULL"); - return; - } - - QUIC_BUFFER *ServerSendBuffer = - QuicDataPathBindingAllocSendDatagram(ServerSendContext, DalTestExpectedDataSize); - - if (ServerSendBuffer == NULL) { - LOGERROR("ServerSendBuffer == NULL"); - return; - } - - memcpy(ServerSendBuffer->Buffer, RecvPacket->Buffer, RecvPacket->BufferLength); - - Status = - QuicDataPathBindingSendFromTo( - Binding, - &RecvPacket->Tuple->LocalAddress, - &RecvPacket->Tuple->RemoteAddress, - ServerSendContext); - - if (!QUIC_SUCCEEDED(Status)) { - LOGERROR("QuicDataPathBindingSendFromTo failed"); - return; - } - } else { - LOGINFO("Received PONG"); - QuicEventSet(RecvContext->ClientCompletion); - } - - QuicDataPathBindingReturnRecvDatagrams(RecvPacket); -} - - -static -BOOLEAN -DalTestDataSend( - void - ) - -{ - QUIC_STATUS Status = QUIC_STATUS_SUCCESS; - QUIC_DATAPATH* datapath = NULL; - QUIC_DATAPATH_BINDING* server = NULL; - QUIC_DATAPATH_BINDING* client = NULL; - QUIC_ADDR serverAddress = DalTestGetNewLocalAddr(4, TRUE); - DAL_TEST_RECV_CONTEXT RecvContext = {0}; - - QuicEventInitialize(&RecvContext.ClientCompletion, FALSE, FALSE); - - Status = - QuicDataPathInitialize( - 0, - DalTestDataRecvCallback, - DalTestEmptyUnreachableCallback, - &datapath); - - if (!QUIC_SUCCEEDED(Status)) { - LOGERROR("QuicDataPathInitialize failed %ld", Status); - return FALSE; - } - - if (datapath == NULL) { - LOGERROR("Datapath is NULL"); - return FALSE; - } - - Status = QUIC_STATUS_ADDRESS_IN_USE; - - while (Status == QUIC_STATUS_ADDRESS_IN_USE) { - QuicAddrSetPort(&serverAddress, DalTestGetNextPortH()); - - Status = - QuicDataPathBindingCreate( - datapath, - &serverAddress, - NULL, - &RecvContext, - &server); - } - - if (!QUIC_SUCCEEDED(Status)) { - LOGERROR("QuicDataPathBindingCreate failed %ld", Status); - return FALSE; - } - - if(server == NULL) { - LOGERROR("server is NULL"); - return FALSE; - } - - QuicDataPathBindingGetLocalAddress(server, &RecvContext.ServerAddress); - - uint16_t ServerPortH = QuicAddrGetPort(&RecvContext.ServerAddress); - - if (ServerPortH == (uint16_t)0) { - LOGERROR("QuicAddrGetPort failed %d", ServerPortH); - return FALSE; - } - - QuicAddrSetPort(&serverAddress, ServerPortH); - - Status = - QuicDataPathBindingCreate( - datapath, - NULL, - &serverAddress, - &RecvContext, - &client); - - if (client == NULL) { - LOGERROR("QuicDataPathBindingCreate failed %ld", Status); - return FALSE; - } - - QUIC_DATAPATH_SEND_CONTEXT* ClientSendContext = - QuicDataPathBindingAllocSendContext(client, 0); - - if (ClientSendContext == NULL) { - LOGERROR("ClientSendContext is NULL"); - return FALSE; - } - - QUIC_BUFFER *ClientSendBuffer = - QuicDataPathBindingAllocSendDatagram(ClientSendContext, DalTestExpectedDataSize); - - if (ClientSendBuffer == NULL) { - LOGERROR("ClientSendBuffer is NULL"); - return FALSE; - } - - memcpy(ClientSendBuffer->Buffer, DalTestExpectedData, DalTestExpectedDataSize); - - LOGINFO("Sending PING"); - - Status = - QuicDataPathBindingSendTo( - client, - &serverAddress, - ClientSendContext); - - if (!QUIC_SUCCEEDED(Status)) { - LOGERROR("QuicDataPathBindingSendTo failed %ld", Status); - return FALSE; - } - - BOOLEAN Signaled = QuicEventWaitWithTimeout(RecvContext.ClientCompletion, 5000); - - if (!Signaled) { - LOGERROR("Signal failed"); - return FALSE; - } - - QuicDataPathBindingDelete(client); - QuicDataPathBindingDelete(server); - QuicDataPathUninitialize(datapath); - - return TRUE; -} - - -static -BOOLEAN -DalTestDataSendMultiple( - void - ) - -{ - QUIC_DATAPATH* datapath = NULL; - QUIC_DATAPATH_BINDING* server = NULL; - QUIC_DATAPATH_BINDING* client = NULL; - QUIC_ADDR serverAddress = DalTestGetNewLocalAddr(4, TRUE); - DAL_TEST_RECV_CONTEXT RecvContext = {0}; - QUIC_STATUS Status = QUIC_STATUS_SUCCESS; - - QuicEventInitialize(&RecvContext.ClientCompletion, FALSE, FALSE); - - Status = - QuicDataPathInitialize( - 0, - DalTestDataRecvCallback, - DalTestEmptyUnreachableCallback, - &datapath); - - if (!QUIC_SUCCEEDED(Status)) { - return FALSE; - } - - if (datapath == NULL) { - return FALSE; - } - - Status = QUIC_STATUS_ADDRESS_IN_USE; - - while (Status == QUIC_STATUS_ADDRESS_IN_USE) { - QuicAddrSetPort(&serverAddress, DalTestGetNextPortH()); - Status = - QuicDataPathBindingCreate( - datapath, - &serverAddress, - NULL, - &RecvContext, - &server); - } - - if (!QUIC_SUCCEEDED(Status)) { - return FALSE; - } - - if(server == NULL) { - return FALSE; - } - - QuicDataPathBindingGetLocalAddress(server, &RecvContext.ServerAddress); - - uint16_t ServerPortH = QuicAddrGetPort(&RecvContext.ServerAddress); - - if (ServerPortH == 0) - { - return FALSE; - } - - QuicAddrSetPort(&serverAddress, ServerPortH); - - Status = - QuicDataPathBindingCreate( - datapath, - NULL, - &serverAddress, - &RecvContext, - &client); - - if (client == NULL) { - return FALSE; - } - - QUIC_DATAPATH_SEND_CONTEXT* ClientSendContext = - QuicDataPathBindingAllocSendContext(client, 0); - - if (ClientSendContext == NULL) { - return FALSE; - } - - QUIC_BUFFER *ClientSendBuffer = - QuicDataPathBindingAllocSendDatagram(ClientSendContext, DalTestExpectedDataSize); - - if (ClientSendBuffer == NULL) { - return FALSE; - } - - memcpy(ClientSendBuffer->Buffer, DalTestExpectedData, DalTestExpectedDataSize); - - LOGINFO("Sending PING"); - - Status = - QuicDataPathBindingSendTo( - client, - &serverAddress, - ClientSendContext); - - if (!QUIC_SUCCEEDED(Status)) { - return FALSE; - } - - BOOLEAN Signaled = QuicEventWaitWithTimeout(RecvContext.ClientCompletion, 5000); - - if (!Signaled) { - return FALSE; - } - - QuicDataPathBindingDelete(client); - client = NULL; - - Status = - QuicDataPathBindingCreate( - datapath, - NULL, - &serverAddress, - &RecvContext, - &client); - - if (client == NULL) { - return FALSE; - } - - ClientSendContext = QuicDataPathBindingAllocSendContext(client, 0); - - if (ClientSendContext == NULL) { - return FALSE; - } - - ClientSendBuffer = - QuicDataPathBindingAllocSendDatagram(ClientSendContext, DalTestExpectedDataSize); - - if (ClientSendBuffer == NULL) { - return FALSE; - } - - memcpy(ClientSendBuffer->Buffer, DalTestExpectedData, DalTestExpectedDataSize); - - LOGINFO("Sending PING"); - - Status = - QuicDataPathBindingSendTo( - client, - &serverAddress, - ClientSendContext); - - if (!QUIC_SUCCEEDED(Status)) { - return FALSE; - } - - Signaled = QuicEventWaitWithTimeout(RecvContext.ClientCompletion, 2000); - - if (!Signaled) { - return FALSE; - } - - QuicDataPathBindingDelete(client); - QuicDataPathBindingDelete(server); - QuicDataPathUninitialize(datapath); - - return TRUE; -} - - -// -// List of all test cases. -// - -static DAL_TESTCASE TestCases[] = { - { DalTestInitialize, "DalTestInitialize" }, - { DalTestInitializeInvalid, "DalTestInitializeInvalid" }, - { DalTestBind, "DalTestBind" }, - { DalTestRebind, "DalTestRebind" }, - { DalTestDataSend, "DalTestDataSend" }, - { DalTestDataSendMultiple, "DalTestDataSendMultiple" }, -}; - - -static -void -DalTestExecuteTestCase( - _In_ uint32_t TestCaseIndex - ) - -{ - LOGINFO("*Start Testcase: %s.*", TestCases[TestCaseIndex].TestCaseName); - if ((TestCases[TestCaseIndex].TestCaseFunc)()) { - LOGINFO("*Testcase succeeded.*"); - } else { - LOGERROR("*Testcase failed.*"); - } - LOGINFO("*Stop Testcase:%s.*", TestCases[TestCaseIndex].TestCaseName); -} - - -static -void -DalTestHelp( - _In_ char *argv[] - ) - -{ - printf("Usage: \n"); - printf("To execute all tests: %s %ld \n", argv[0], ARRAYSIZE(TestCases)); - printf("To execute a specific test: %s \n", argv[0]); - printf("Test cases: \n"); - for (uint32_t Iter = 0; Iter < ARRAYSIZE(TestCases); Iter++) { - printf("\t%lu: %s\n", Iter, TestCases[Iter].TestCaseName); - } -} - - -int -main( - _In_ int argc, - _In_reads_(argc) char *argv[] - ) -/*++ - -Routine Description: - - Program entry point. - -Arguments: - - argc - Number of tokens. - - argv - Array of tokens. The caller will populate the first token with the - program name/path. - -Return Value: - - Exit Code. - ---*/ -{ - uint32_t Input = 0; - - if (argc != 2) { - DalTestHelp(argv); - return 0; - } - - DalTestSetUpTestCase(); - - Input = atoi(argv[1]); - if (Input < ARRAYSIZE(TestCases)) { - DalTestExecuteTestCase(Input); - } else if (Input == ARRAYSIZE(TestCases)) { - for (uint32_t Iter = 0; Iter < ARRAYSIZE(TestCases); Iter++) { - DalTestExecuteTestCase(Iter); - } - } else { - LOGERROR("Incorrect Input"); - DalTestHelp(argv); - } - - DalTestTearDownTestCase(); -} - diff --git a/src/platform/unittest/linux/TlsTest.c b/src/platform/unittest/linux/TlsTest.c deleted file mode 100644 index bc878f8614a3..000000000000 --- a/src/platform/unittest/linux/TlsTest.c +++ /dev/null @@ -1,1847 +0,0 @@ -/*++ - - Copyright (c) Microsoft Corporation. - Licensed under the MIT License. - -Abstract: - - Implements the TLS unit tests. - ---*/ - -#define QUIC_TEST_APIS 1 - -#include "quic_platform.h" -#include "msquic.h" -#include "msquicp.h" -#include "quic_tls.h" - -#define LOGINFO(fmt, ...) \ - printf("[INFO]: " fmt "\n", ##__VA_ARGS__) - -#define LOGERROR(fmt, ...) \ - printf("[ERROR]: " fmt "\n", ##__VA_ARGS__) - - -static QUIC_RUNDOWN_REF TalTestSecConfigRundown = {0}; -static QUIC_EVENT TalTestSecConfigDoneEvent = NULL; -static QUIC_EVENT TalTestProcessCompleteEvent = NULL; - -static QUIC_SEC_CONFIG_PARAMS* TalTestSelfSignedCert = NULL; - - -// -// Test case info. -// - -typedef struct _TAL_TESTCASE { - // - // Test case runner. - // - - BOOLEAN(*TestCaseFunc)(); - - // - // Test case name. - // - - char* TestCaseName; - -} TAL_TESTCASE, *PTAL_TESTCASE; - - -static -void -TalTestSetUpTestCase( - void - ); - -static -void -TalTestTearDownTestCase( - void - ); - -static -void -TalTestHelp( - _In_ char *argv[] - ); - -static -BOOLEAN -TalTestInitialize( - void - ); - -static -BOOLEAN -TalTestHandshake( - void - ); - -static -BOOLEAN -TalTestHandshakeFragmented( - void - ); - -static -BOOLEAN -TalTestHandshakeSerial( - void - ); - -static -BOOLEAN -TalTestHandshakeInterleaved( - void - ); - -static -BOOLEAN -TalTestOneRttKey( - void - ); - -static -BOOLEAN -TalTestKeyUpdate( - void - ); - - -static -QUIC_TLS_RESULT_FLAGS -TalTestProcessData2( - _In_ QUIC_TLS* TlsContext, - _Inout_ QUIC_TLS_PROCESS_STATE* State, - _In_ QUIC_PACKET_KEY_TYPE BufferKey, - _In_reads_bytes_(*BufferLength) const uint8_t * Buffer, - _In_ uint32_t * BufferLength - ); - -static -QUIC_TLS_RESULT_FLAGS -TalTestProcessData( - _In_ QUIC_TLS* TlsContext, - _Inout_ QUIC_TLS_PROCESS_STATE* State, - _Inout_ QUIC_TLS_PROCESS_STATE* PeerState, - _In_ uint32_t FragmentSize - ); - -static -BOOLEAN -TalTestDoHandshake( - _In_ QUIC_TLS* ServerContext, - _In_ QUIC_TLS* ClientContext, - _Inout_ QUIC_TLS_PROCESS_STATE *ServerState, - _Inout_ QUIC_TLS_PROCESS_STATE *ClientState, - _In_ uint32_t FragmentSize - ); - -static -QUIC_TLS_RESULT_FLAGS -TalTestProcessFragmentedData( - _In_ QUIC_TLS* TlsContext, - _Inout_ QUIC_TLS_PROCESS_STATE* State, - _In_ QUIC_PACKET_KEY_TYPE BufferKey, - _In_reads_bytes_(BufferLength) const uint8_t * Buffer, - _In_ uint32_t BufferLength, - _In_ uint32_t FragmentSize - ); - - -static -void -TalTestOnSecConfigCreateComplete( - _In_opt_ void* Context, - _In_ QUIC_STATUS Status, - _In_opt_ QUIC_SEC_CONFIG* SecConfig - ) - -{ - QUIC_SEC_CONFIG** ServerConfig = Context; - - *ServerConfig = SecConfig; - QuicEventSet(TalTestSecConfigDoneEvent); -} - - -static -void -TalTestSetUpTestCase( - void - ) - -{ - QUIC_STATUS Status = QUIC_STATUS_SUCCESS; - char Template[] = "/tmp/quictest.XXXXXX"; - - QuicRundownInitialize(&TalTestSecConfigRundown); - QuicEventInitialize(&TalTestSecConfigDoneEvent, FALSE, FALSE); - QuicEventInitialize(&TalTestProcessCompleteEvent, FALSE, FALSE); - - TalTestSelfSignedCert = QuicPlatGetSelfSignedCert(QUIC_SELF_SIGN_CERT_USER); - if (TalTestSelfSignedCert == NULL) { - LOGERROR("QuicPlatGetSelfSignedCert() failed"); - - // - // Kill the test as all the tests are dependent on this. - // - - exit(EXIT_FAILURE); - } -} - - -static -void -TalTestTearDownTestCase( - void - ) - -{ - char RmCmd[26] = {0}; - - if (TalTestProcessCompleteEvent != NULL) { - QuicEventUninitialize(TalTestProcessCompleteEvent); - TalTestProcessCompleteEvent = NULL; - } - - if (TalTestSecConfigDoneEvent != NULL) { - QuicEventUninitialize(TalTestSecConfigDoneEvent); - TalTestSecConfigDoneEvent = NULL; - } - - QuicRundownUninitialize(&TalTestSecConfigRundown); - - QuicPlatFreeSelfSignedCert(TalTestSelfSignedCert); - TalTestSelfSignedCert = NULL; -} - - -// -// List of all test cases. -// - -static TAL_TESTCASE TestCases[] = { - { TalTestInitialize, "TalTestInitialize" }, - { TalTestHandshake, "TalTestHandshake" }, - { TalTestHandshakeFragmented, "TalTestHandshakeFragmented" }, - { TalTestHandshakeSerial, "TalTestHandshakeSerial" }, - { TalTestHandshakeInterleaved, "TalTestHandshakeInterleaved" }, - { TalTestOneRttKey, "TalTestOneRttKey" }, - { TalTestKeyUpdate, "TalTestKeyUpdate" }, -}; - - -static -void -TalTestOnProcessComplete( - _In_ QUIC_CONNECTION* Connection - ) - -{ - QUIC_EVENT Event = (QUIC_EVENT)Connection; - - QuicEventSet(Event); -} - -static -BOOLEAN -TalTestOnRecvQuicTP( - _In_ QUIC_CONNECTION* Connection, - _In_ uint16_t TPLength, - _In_reads_(TPLength) const uint8_t* TPBuffer - ) -{ - UNREFERENCED_PARAMETER(Connection); - UNREFERENCED_PARAMETER(TPLength); - UNREFERENCED_PARAMETER(TPBuffer); - return TRUE; -} - - -static -QUIC_TLS_RESULT_FLAGS -TalTestProcessData2( - _In_ QUIC_TLS* TlsContext, - _Inout_ QUIC_TLS_PROCESS_STATE* State, - _In_ QUIC_PACKET_KEY_TYPE BufferKey, - _In_reads_bytes_(*BufferLength) const uint8_t * Buffer, - _In_ uint32_t * BufferLength - ) -{ - QUIC_FRE_ASSERT(Buffer != NULL || *BufferLength == 0); - - if (Buffer != NULL) { - if (BufferKey != State->ReadKey) { - LOGERROR("BufferKey != State->ReadKey"); - return 0; - } - } - - QUIC_TLS_RESULT_FLAGS Result = - QuicTlsProcessData( - TlsContext, - Buffer, - BufferLength, - State); - - if (Result & QUIC_TLS_RESULT_PENDING) { - QuicEventWaitForever(TalTestProcessCompleteEvent); - Result = QuicTlsProcessDataComplete(TlsContext, BufferLength); - } - - if ((Result & QUIC_TLS_RESULT_ERROR) != 0) { - LOGERROR("Result & QUIC_TLS_RESULT_ERROR) != 0"); - } - - return Result; -} - - -static -QUIC_TLS_RESULT_FLAGS -TalTestProcessFragmentedData( - _In_ QUIC_TLS* TlsContext, - _Inout_ QUIC_TLS_PROCESS_STATE* State, - _In_ QUIC_PACKET_KEY_TYPE BufferKey, - _In_reads_bytes_(BufferLength) const uint8_t * Buffer, - _In_ uint32_t BufferLength, - _In_ uint32_t FragmentSize - ) -{ - uint32_t Result = 0; - uint32_t ConsumedBuffer = FragmentSize; - uint32_t Count = 1; - uint32_t TotalBufferLength = BufferLength; - - while (BufferLength != 0) { - - if (BufferLength < FragmentSize) { - FragmentSize = BufferLength; - ConsumedBuffer = FragmentSize; - } - - LOGINFO("Processing fragment of %u/%u bytes", FragmentSize, TotalBufferLength); - - Result |= - (uint32_t)TalTestProcessData2( - TlsContext, - State, - BufferKey, - Buffer, - &ConsumedBuffer); - - if ((Result & QUIC_TLS_RESULT_ERROR) != 0) { - goto Exit; - } - - if (ConsumedBuffer > 0) { - Buffer += ConsumedBuffer; - BufferLength -= ConsumedBuffer; - } else { - ConsumedBuffer = FragmentSize * ++Count; - ConsumedBuffer = min(ConsumedBuffer, BufferLength); - } - } - -Exit: - - return (QUIC_TLS_RESULT_FLAGS)Result; -} - - -static -QUIC_TLS_RESULT_FLAGS -TalTestProcessData( - _In_ QUIC_TLS* TlsContext, - _Inout_ QUIC_TLS_PROCESS_STATE* State, - _Inout_ QUIC_TLS_PROCESS_STATE* PeerState, - _In_ uint32_t FragmentSize - ) -{ - if (PeerState == NULL) { - // - // Special case for client hello/initial. - // - uint32_t Zero = 0; - return TalTestProcessData2(TlsContext, State, QUIC_PACKET_KEY_INITIAL, NULL, &Zero); - } - - uint32_t Result; - - while (PeerState->BufferLength != 0) { - uint16_t BufferLength; - QUIC_PACKET_KEY_TYPE PeerWriteKey; - - uint32_t StartOffset = PeerState->BufferTotalLength - PeerState->BufferLength; - if (PeerState->BufferOffset1Rtt != 0 && StartOffset >= PeerState->BufferOffset1Rtt) { - PeerWriteKey = QUIC_PACKET_KEY_1_RTT; - BufferLength = PeerState->BufferLength; - - } else if (PeerState->BufferOffsetHandshake != 0 && StartOffset >= PeerState->BufferOffsetHandshake) { - PeerWriteKey = QUIC_PACKET_KEY_HANDSHAKE; - if (PeerState->BufferOffset1Rtt != 0) { - BufferLength = (uint16_t)(PeerState->BufferOffset1Rtt - StartOffset); - } else { - BufferLength = PeerState->BufferLength; - } - - } else { - PeerWriteKey = QUIC_PACKET_KEY_INITIAL; - if (PeerState->BufferOffsetHandshake != 0) { - BufferLength = (uint16_t)(PeerState->BufferOffsetHandshake - StartOffset); - } else { - BufferLength = PeerState->BufferLength; - } - } - - Result |= - (uint32_t)TalTestProcessFragmentedData( - TlsContext, - State, - PeerWriteKey, - PeerState->Buffer, - BufferLength, - FragmentSize); - - PeerState->BufferLength -= BufferLength; - QuicMoveMemory( - PeerState->Buffer, - PeerState->Buffer + BufferLength, - PeerState->BufferLength); - } - - return (QUIC_TLS_RESULT_FLAGS)Result; -} - - -static -BOOLEAN -TalTestDoHandshake( - _In_ QUIC_TLS* ServerContext, - _In_ QUIC_TLS* ClientContext, - _Inout_ QUIC_TLS_PROCESS_STATE *ServerState, - _Inout_ QUIC_TLS_PROCESS_STATE *ClientState, - _In_ uint32_t FragmentSize - ) -{ - BOOLEAN Ret = TRUE; - - ClientState->BufferAllocLength = 8000; - ClientState->Buffer = (uint8_t*)QUIC_ALLOC_NONPAGED(8000); - - if (ClientState->Buffer == NULL) { - LOGERROR("Buffer alloc failure"); - Ret = FALSE; - goto Exit; - } - - ServerState->BufferAllocLength = 8000; - ServerState->Buffer = (uint8_t*)QUIC_ALLOC_NONPAGED(8000); - - if (ServerState->Buffer == NULL) { - LOGERROR("Buffer alloc failure"); - Ret = FALSE; - goto Exit; - } - - QUIC_TLS_RESULT_FLAGS Result = - TalTestProcessData( - ClientContext, - ClientState, - NULL, - FragmentSize); - - if (!(Result & QUIC_TLS_RESULT_DATA)) { - LOGERROR("!(Result & QUIC_TLS_RESULT_DATA)"); - Ret = FALSE; - goto Exit; - } - - Result = - TalTestProcessData( - ServerContext, - ServerState, - ClientState, - FragmentSize); - - if (!(Result & QUIC_TLS_RESULT_DATA)) { - LOGERROR("!(Result & QUIC_TLS_RESULT_DATA)"); - Ret = FALSE; - goto Exit; - } - - if (ServerState->WriteKeys[QUIC_PACKET_KEY_1_RTT] == NULL) { - LOGERROR("TalTestServerState.WriteKeys[QUIC_PACKET_KEY_1_RTT] == NULL"); - Ret = FALSE; - goto Exit; - } - - Result = - TalTestProcessData( - ClientContext, - ClientState, - ServerState, - FragmentSize); - - if (!(Result & QUIC_TLS_RESULT_DATA)) { - LOGERROR("!(Result & QUIC_TLS_RESULT_DATA)"); - Ret = FALSE; - goto Exit; - } - - if (!(Result & QUIC_TLS_RESULT_COMPLETE)) { - LOGERROR("!(Result & QUIC_TLS_RESULT_COMPLETE)"); - Ret = FALSE; - goto Exit; - } - - if (ClientState->WriteKeys[QUIC_PACKET_KEY_1_RTT] == NULL) { - LOGERROR("TalTestServerState.WriteKeys[QUIC_PACKET_KEY_1_RTT] == NULL"); - Ret = FALSE; - goto Exit; - } - - Result = - TalTestProcessData( - ServerContext, - ServerState, - ClientState, - FragmentSize); - - if (!(Result & QUIC_TLS_RESULT_COMPLETE)) { - LOGERROR("!(Result & QUIC_TLS_RESULT_COMPLETE)"); - Ret = FALSE; - goto Exit; - } - -Exit: - - if (ClientState->Buffer != NULL) { - QuicFree(ClientState->Buffer); - ClientState->Buffer = NULL; - } - - if (ServerState->Buffer != NULL) { - QuicFree(ServerState->Buffer); - ServerState->Buffer = NULL; - } - - return Ret; -} - - -BOOLEAN -TalTestInitializeServer( - _In_ QUIC_TLS_SESSION* Session, - _In_ QUIC_SEC_CONFIG* SecConfig, - _Out_ QUIC_TLS* *TlsContext - ) - -{ - QUIC_STATUS Status = QUIC_STATUS_SUCCESS; - QUIC_TLS_CONFIG Config = {0}; - QUIC_TLS* TempTlsContext = NULL; - uint32_t QuicVersion = 1; - QUIC_EVENT ProcessCompletionEvent = NULL; - - QuicEventInitialize(&ProcessCompletionEvent, TRUE, FALSE); - - Config.IsServer = TRUE; - Config.LocalTPBuffer = QuicAlloc(QuicTlsTPHeaderSize + 64); - QUIC_FRE_ASSERT(Config.LocalTPBuffer != NULL); - Config.LocalTPLength = QuicTlsTPHeaderSize + 64; - Config.ProcessCompleteCallback = TalTestOnProcessComplete; - Config.ReceiveTPCallback = TalTestOnRecvQuicTP; - Config.SecConfig = (QUIC_SEC_CONFIG*) SecConfig; - Config.TlsSession = Session; - Config.Connection = NULL; - - Status = QuicTlsInitialize(&Config, &TempTlsContext); - - if (QUIC_FAILED(Status)) { - LOGERROR("TLS server init failed, error: %lu.", Status); - return FALSE; - } - - *TlsContext = TempTlsContext; - return TRUE; -} - - -BOOLEAN -TalTestInitializeClient( - _In_ QUIC_TLS_SESSION* Session, - _In_ QUIC_SEC_CONFIG* SecConfig, - _Out_ QUIC_TLS* *TlsContext - ) - -{ - QUIC_STATUS Status = QUIC_STATUS_SUCCESS; - QUIC_TLS_CONFIG Config = {0}; - QUIC_TLS* TempTlsContext = NULL; - uint32_t QuicVersion = 1; - QUIC_EVENT ProcessCompletionEvent = NULL; - - QuicEventInitialize(&ProcessCompletionEvent, TRUE, FALSE); - - Config.ServerName = "localhost"; - Config.IsServer = FALSE; - Config.LocalTPBuffer = QuicAlloc(QuicTlsTPHeaderSize + 64); - QUIC_FRE_ASSERT(Config.LocalTPBuffer != NULL); - Config.LocalTPLength = QuicTlsTPHeaderSize + 64; - Config.ProcessCompleteCallback = TalTestOnProcessComplete; - Config.ReceiveTPCallback = TalTestOnRecvQuicTP; - Config.SecConfig = (QUIC_SEC_CONFIG*) SecConfig; - Config.TlsSession = Session; - Config.Connection = NULL; - - Status = QuicTlsInitialize(&Config, &TempTlsContext); - - if (QUIC_FAILED(Status)) { - printf("TLS client init failed, error: %lu.", Status); - return FALSE; - } - - *TlsContext = TempTlsContext; - return TRUE; -} - - -static -BOOLEAN -TalTestInitialize( - void - ) - -{ - QUIC_STATUS Status = QUIC_STATUS_SUCCESS; - BOOLEAN Ret = TRUE; - QUIC_SEC_CONFIG* ClientConfig = NULL; - QUIC_SEC_CONFIG* ServerConfig = NULL; - QUIC_TLS* ClientTlsContext = NULL; - QUIC_TLS* ServerTlsContext = NULL; - QUIC_TLS_SESSION* TlsSession = NULL; - - Status = QuicTlsSessionInitialize("MsQuicTest", &TlsSession); - - if (!QUIC_SUCCEEDED(Status)) { - LOGERROR("QuicTlsSessionInitialize() failed, error %lu", Status); - Ret = FALSE; - goto Exit; - } - - Status = - QuicTlsServerSecConfigCreate( - &TalTestSecConfigRundown, - (QUIC_SEC_CONFIG_FLAGS)TalTestSelfSignedCert->Flags, - TalTestSelfSignedCert->Certificate, - TalTestSelfSignedCert->Principal, - &ServerConfig, - TalTestOnSecConfigCreateComplete); - - if (!QUIC_SUCCEEDED(Status)) { - LOGERROR("QuicTlsServerSecConfigCreate() failed, error %lu", Status); - Ret = FALSE; - goto Exit; - } - - QuicEventWaitWithTimeout(TalTestSecConfigDoneEvent, 2000); - - if (!TalTestInitializeServer( - TlsSession, - ServerConfig, - &ServerTlsContext)) { - return FALSE; - } - - Status = QuicTlsClientSecConfigCreate(0, &ClientConfig); - - if (!QUIC_SUCCEEDED(Status)) { - LOGERROR("QuicTlsClientSecConfigCreate() failed, error %lu", Status); - Ret = FALSE; - goto Exit; - } - - if (!TalTestInitializeClient( - TlsSession, - ClientConfig, - &ClientTlsContext)) { - return FALSE; - } - -Exit: - - if (ServerTlsContext != NULL) { - QuicTlsUninitialize(ServerTlsContext); - ServerTlsContext = NULL; - } - - if (ServerConfig != NULL) { - QuicTlsSecConfigRelease(ServerConfig); - ServerConfig = NULL; - } - - if (ClientTlsContext != NULL) { - QuicTlsUninitialize(ClientTlsContext); - ClientTlsContext = NULL; - } - - if (ClientConfig != NULL) { - QuicTlsSecConfigRelease(ClientConfig); - ClientConfig = NULL; - } - - if (TlsSession != NULL) { - QuicTlsSessionUninitialize(TlsSession); - TlsSession = NULL; - } - - return Ret; -} - - -static -BOOLEAN -TalTestHandshake( - void - ) - -{ - QUIC_STATUS Status = QUIC_STATUS_SUCCESS; - BOOLEAN Ret = TRUE; - QUIC_SEC_CONFIG* ClientConfig = NULL; - QUIC_SEC_CONFIG* ServerConfig = NULL; - QUIC_TLS* ClientTlsContext = NULL; - QUIC_TLS* ServerTlsContext = NULL; - QUIC_TLS_PROCESS_STATE ClientState = {0}; - QUIC_TLS_PROCESS_STATE ServerState = {0}; - QUIC_TLS_SESSION* TlsSession = NULL; - - Status = QuicTlsSessionInitialize("MsQuicTest", &TlsSession); - - if (!QUIC_SUCCEEDED(Status)) { - LOGERROR("QuicTlsSessionInitialize() failed, error %lu", Status); - Ret = FALSE; - goto Exit; - } - - Status = - QuicTlsServerSecConfigCreate( - &TalTestSecConfigRundown, - (QUIC_SEC_CONFIG_FLAGS)TalTestSelfSignedCert->Flags, - TalTestSelfSignedCert->Certificate, - TalTestSelfSignedCert->Principal, - &ServerConfig, - TalTestOnSecConfigCreateComplete); - - if (!QUIC_SUCCEEDED(Status)) { - LOGERROR("QuicTlsServerSecConfigCreate() failed, error %lu", Status); - Ret = FALSE; - goto Exit; - } - - QuicEventWaitWithTimeout(TalTestSecConfigDoneEvent, 2000); - - if (!TalTestInitializeServer( - TlsSession, - ServerConfig, - &ServerTlsContext)) { - Ret = FALSE; - goto Exit; - } - - Status = QuicTlsClientSecConfigCreate(0, &ClientConfig); - - if (!QUIC_SUCCEEDED(Status)) { - LOGERROR("QuicTlsClientSecConfigCreate() failed, error %lu", Status); - Ret = FALSE; - goto Exit; - } - - if (!TalTestInitializeClient( - TlsSession, - ClientConfig, - &ClientTlsContext)) { - Ret = FALSE; - goto Exit; - } - - if (!TalTestDoHandshake( - ServerTlsContext, - ClientTlsContext, - &ServerState, - &ClientState, - 1200)) { - Ret = FALSE; - goto Exit; - } - -Exit: - - if (ServerTlsContext != NULL) { - QuicTlsUninitialize(ServerTlsContext); - ServerTlsContext = NULL; - } - - if (ServerConfig != NULL) { - QuicTlsSecConfigRelease(ServerConfig); - ServerConfig = NULL; - } - - if (ClientTlsContext != NULL) { - QuicTlsUninitialize(ClientTlsContext); - ClientTlsContext = NULL; - } - - if (ClientConfig != NULL) { - QuicTlsSecConfigRelease(ClientConfig); - ClientConfig = NULL; - } - - if (TlsSession != NULL) { - QuicTlsSessionUninitialize(TlsSession); - TlsSession = NULL; - } - - return Ret; -} - - -static -BOOLEAN -TalTestHandshakeFragmented( - void - ) - -{ - QUIC_STATUS Status = QUIC_STATUS_SUCCESS; - BOOLEAN Ret = TRUE; - QUIC_SEC_CONFIG* ClientConfig = NULL; - QUIC_SEC_CONFIG* ServerConfig = NULL; - QUIC_TLS* ClientTlsContext = NULL; - QUIC_TLS* ServerTlsContext = NULL; - QUIC_TLS_PROCESS_STATE ClientState = {0}; - QUIC_TLS_PROCESS_STATE ServerState = {0}; - QUIC_TLS_SESSION* TlsSession = NULL; - - Status = QuicTlsSessionInitialize("MsQuicTest", &TlsSession); - - if (!QUIC_SUCCEEDED(Status)) { - LOGERROR("QuicTlsSessionInitialize() failed, error %lu", Status); - Ret = FALSE; - goto Exit; - } - - QuicEventReset(TalTestSecConfigDoneEvent); - - Status = - QuicTlsServerSecConfigCreate( - &TalTestSecConfigRundown, - (QUIC_SEC_CONFIG_FLAGS)TalTestSelfSignedCert->Flags, - TalTestSelfSignedCert->Certificate, - TalTestSelfSignedCert->Principal, - &ServerConfig, - TalTestOnSecConfigCreateComplete); - - if (!QUIC_SUCCEEDED(Status)) { - LOGERROR("Test Init failed. QuicTlsServerSecConfigCreate() failed, error %lu", Status); - Ret = FALSE; - goto Exit; - } - - QuicEventWaitWithTimeout(TalTestSecConfigDoneEvent, 2000); - - if (!TalTestInitializeServer( - TlsSession, - ServerConfig, - &ServerTlsContext)) { - Ret = FALSE; - goto Exit; - } - - Status = QuicTlsClientSecConfigCreate(0, &ClientConfig); - - if (!QUIC_SUCCEEDED(Status)) { - LOGERROR("QuicTlsClientSecConfigCreate() failed, error %lu", Status); - Ret = FALSE; - goto Exit; - } - - - if (!TalTestInitializeClient( - TlsSession, - ClientConfig, - &ClientTlsContext)) { - Ret = FALSE; - goto Exit; - } - - if (!TalTestDoHandshake(ServerTlsContext, ClientTlsContext, &ServerState, &ClientState, 300)) { - Ret = FALSE; - goto Exit; - } - -Exit: - - if (ServerTlsContext != NULL) { - QuicTlsUninitialize(ServerTlsContext); - ServerTlsContext = NULL; - } - - if (ServerConfig != NULL) { - QuicTlsSecConfigRelease(ServerConfig); - ServerConfig = NULL; - } - - if (ClientTlsContext != NULL) { - QuicTlsUninitialize(ClientTlsContext); - ClientTlsContext = NULL; - } - - if (ClientConfig != NULL) { - QuicTlsSecConfigRelease(ClientConfig); - ClientConfig = NULL; - } - - if (TlsSession != NULL) { - QuicTlsSessionUninitialize(TlsSession); - TlsSession = NULL; - } - - return Ret; -} - - -static -BOOLEAN -TalTestHandshakeSerial( - void - ) - -{ - QUIC_STATUS Status = QUIC_STATUS_SUCCESS; - BOOLEAN Ret = TRUE; - QUIC_SEC_CONFIG* ClientConfig = NULL; - QUIC_SEC_CONFIG* ServerConfig = NULL; - QUIC_TLS* ClientTlsContext1 = NULL; - QUIC_TLS* ClientTlsContext2 = NULL; - QUIC_TLS* ServerTlsContext1= NULL; - QUIC_TLS* ServerTlsContext2 = NULL; - QUIC_TLS_PROCESS_STATE ClientState1 = {0}; - QUIC_TLS_PROCESS_STATE ServerState1 = {0}; - QUIC_TLS_PROCESS_STATE ClientState2 = {0}; - QUIC_TLS_PROCESS_STATE ServerState2 = {0}; - QUIC_TLS_SESSION* TlsSession = NULL; - - Status = QuicTlsSessionInitialize("MsQuicTest", &TlsSession); - - if (!QUIC_SUCCEEDED(Status)) { - LOGERROR("QuicTlsSessionInitialize() failed, error %lu", Status); - Ret = FALSE; - goto Exit; - } - - QuicEventReset(TalTestSecConfigDoneEvent); - - Status = - QuicTlsServerSecConfigCreate( - &TalTestSecConfigRundown, - (QUIC_SEC_CONFIG_FLAGS)TalTestSelfSignedCert->Flags, - TalTestSelfSignedCert->Certificate, - TalTestSelfSignedCert->Principal, - &ServerConfig, - TalTestOnSecConfigCreateComplete); - - if (!QUIC_SUCCEEDED(Status)) { - LOGERROR("Test Init failed. QuicTlsServerSecConfigCreate() failed, error %lu", Status); - Ret = FALSE; - goto Exit; - } - - QuicEventWaitWithTimeout(TalTestSecConfigDoneEvent, 2000); - - if (!TalTestInitializeServer( - TlsSession, - ServerConfig, - &ServerTlsContext1)) { - Ret = FALSE; - goto Exit; - } - - Status = QuicTlsClientSecConfigCreate(0, &ClientConfig); - - if (!QUIC_SUCCEEDED(Status)) { - LOGERROR("QuicTlsClientSecConfigCreate() failed, error %lu", Status); - Ret = FALSE; - goto Exit; - } - - if (!TalTestInitializeClient( - TlsSession, - ClientConfig, - &ClientTlsContext1)) { - Ret = FALSE; - goto Exit; - } - - if (!TalTestDoHandshake(ServerTlsContext1, ClientTlsContext1, &ServerState1, &ClientState1, 1200)) { - Ret = FALSE; - goto Exit; - } - - if (!TalTestInitializeServer( - TlsSession, - ServerConfig, - &ServerTlsContext2)) { - Ret = FALSE; - goto Exit; - } - - if (!TalTestInitializeClient( - TlsSession, - ClientConfig, - &ClientTlsContext2)) { - Ret = FALSE; - goto Exit; - } - - if (!TalTestDoHandshake(ServerTlsContext2, ClientTlsContext2, &ServerState2, &ClientState2, 1200)) { - Ret = FALSE; - goto Exit; - } - -Exit: - - if (ServerTlsContext1 != NULL) { - QuicTlsUninitialize(ServerTlsContext1); - ServerTlsContext1 = NULL; - } - - if (ServerTlsContext2 != NULL) { - QuicTlsUninitialize(ServerTlsContext2); - ServerTlsContext2 = NULL; - } - - if (ServerConfig != NULL) { - QuicTlsSecConfigRelease(ServerConfig); - ServerConfig = NULL; - } - - if (ClientTlsContext1 != NULL) { - QuicTlsUninitialize(ClientTlsContext1); - ClientTlsContext1 = NULL; - } - - if (ClientTlsContext2!= NULL) { - QuicTlsUninitialize(ClientTlsContext2); - ClientTlsContext2 = NULL; - } - - if (ClientConfig != NULL) { - QuicTlsSecConfigRelease(ClientConfig); - ClientConfig = NULL; - } - - if (TlsSession != NULL) { - QuicTlsSessionUninitialize(TlsSession); - TlsSession = NULL; - } - - return Ret; -} - - -static -BOOLEAN -TalTestHandshakeInterleaved( - void - ) - -{ - QUIC_STATUS Status = QUIC_STATUS_SUCCESS; - BOOLEAN Ret = TRUE; - QUIC_SEC_CONFIG* ClientConfig = NULL; - QUIC_SEC_CONFIG* ServerConfig = NULL; - QUIC_TLS* ClientTlsContext1 = NULL; - QUIC_TLS* ClientTlsContext2 = NULL; - QUIC_TLS* ServerTlsContext1 = NULL; - QUIC_TLS* ServerTlsContext2 = NULL; - QUIC_TLS_SESSION* TlsSession = NULL; - QUIC_TLS_PROCESS_STATE ClientState1 = {0}; - QUIC_TLS_PROCESS_STATE ServerState1 = {0}; - QUIC_TLS_PROCESS_STATE ClientState2 = {0}; - QUIC_TLS_PROCESS_STATE ServerState2 = {0}; - - ClientState1.BufferAllocLength = 8000; - ClientState1.Buffer = (uint8_t*)QUIC_ALLOC_NONPAGED(8000); - - if (ClientState1.Buffer == NULL) { - LOGERROR("Buffer alloc failure"); - Ret = FALSE; - goto Exit; - } - - ClientState2.BufferAllocLength = 8000; - ClientState2.Buffer = (uint8_t*)QUIC_ALLOC_NONPAGED(8000); - - if (ClientState2.Buffer == NULL) { - LOGERROR("Buffer alloc failure"); - Ret = FALSE; - goto Exit; - } - - ServerState1.BufferAllocLength = 8000; - ServerState1.Buffer = (uint8_t*)QUIC_ALLOC_NONPAGED(8000); - - if (ServerState1.Buffer == NULL) { - LOGERROR("Buffer alloc failure"); - Ret = FALSE; - goto Exit; - } - - ServerState2.BufferAllocLength = 8000; - ServerState2.Buffer = (uint8_t*)QUIC_ALLOC_NONPAGED(8000); - - if (ServerState2.Buffer == NULL) { - LOGERROR("Buffer alloc failure"); - Ret = FALSE; - goto Exit; - } - - Status = QuicTlsSessionInitialize("MsQuicTest", &TlsSession); - - if (!QUIC_SUCCEEDED(Status)) { - LOGERROR("QuicTlsSessionInitialize() failed, error %lu", Status); - Ret = FALSE; - goto Exit; - } - - QuicEventReset(TalTestSecConfigDoneEvent); - - Status = - QuicTlsServerSecConfigCreate( - &TalTestSecConfigRundown, - (QUIC_SEC_CONFIG_FLAGS)TalTestSelfSignedCert->Flags, - TalTestSelfSignedCert->Certificate, - TalTestSelfSignedCert->Principal, - &ServerConfig, - TalTestOnSecConfigCreateComplete); - - if (!QUIC_SUCCEEDED(Status)) { - LOGERROR("Test Init failed. QuicTlsServerSecConfigCreate() failed, error %lu", Status); - Ret = FALSE; - goto Exit; - } - - QuicEventWaitWithTimeout(TalTestSecConfigDoneEvent, 2000); - - if (!TalTestInitializeServer( - TlsSession, - ServerConfig, - &ServerTlsContext1)) { - Ret = FALSE; - goto Exit; - } - - Status = QuicTlsClientSecConfigCreate(0, &ClientConfig); - - if (!QUIC_SUCCEEDED(Status)) { - LOGERROR("QuicTlsClientSecConfigCreate() failed, error %lu", Status); - Ret = FALSE; - goto Exit; - } - - if (!TalTestInitializeClient( - TlsSession, - ClientConfig, - &ClientTlsContext1)) { - Ret = FALSE; - goto Exit; - } - - if (!TalTestInitializeServer( - TlsSession, - ServerConfig, - &ServerTlsContext2)) { - Ret = FALSE; - goto Exit; - } - - if (!TalTestInitializeClient( - TlsSession, - ClientConfig, - &ClientTlsContext2)) { - Ret = FALSE; - goto Exit; - } - - QUIC_TLS_RESULT_FLAGS Result = - TalTestProcessData( - ClientTlsContext1, - &ClientState1, - NULL, - 1200); - - if (!(Result & QUIC_TLS_RESULT_DATA)) { - LOGERROR("!(Result & QUIC_TLS_RESULT_DATA)"); - Ret = FALSE; - goto Exit; - } - - Result = - TalTestProcessData( - ClientTlsContext2, - &ClientState2, - NULL, - 1200); - - if (!(Result & QUIC_TLS_RESULT_DATA)) { - LOGERROR("!(Result & QUIC_TLS_RESULT_DATA)"); - Ret = FALSE; - goto Exit; - } - - Result = - TalTestProcessData( - ServerTlsContext1, - &ServerState1, - &ClientState1, - 1200); - - if (!(Result & QUIC_TLS_RESULT_DATA)) { - LOGERROR("!(Result & QUIC_TLS_RESULT_DATA)"); - Ret = FALSE; - goto Exit; - } - - if (ServerState1.WriteKeys[QUIC_PACKET_KEY_1_RTT] == NULL) { - LOGERROR("TalTestServerState.WriteKeys[QUIC_PACKET_KEY_1_RTT] == NULL"); - Ret = FALSE; - goto Exit; - } - - Result = - TalTestProcessData( - ServerTlsContext2, - &ServerState2, - &ClientState2, - 1200); - - if (!(Result & QUIC_TLS_RESULT_DATA)) { - LOGERROR("!(Result & QUIC_TLS_RESULT_DATA)"); - Ret = FALSE; - goto Exit; - } - - if (ServerState2.WriteKeys[QUIC_PACKET_KEY_1_RTT] == NULL) { - LOGERROR("TalTestServerState.WriteKeys[QUIC_PACKET_KEY_1_RTT] == NULL"); - Ret = FALSE; - goto Exit; - } - - Result = - TalTestProcessData( - ClientTlsContext1, - &ClientState1, - &ServerState1, - 1200); - - if (!(Result & QUIC_TLS_RESULT_DATA)) { - LOGERROR("!(Result & QUIC_TLS_RESULT_DATA)"); - Ret = FALSE; - goto Exit; - } - - if (!(Result & QUIC_TLS_RESULT_COMPLETE)) { - LOGERROR("!(Result & QUIC_TLS_RESULT_COMPLETE)"); - Ret = FALSE; - goto Exit; - } - - if (ClientState1.WriteKeys[QUIC_PACKET_KEY_1_RTT] == NULL) { - LOGERROR("TalTestServerState.WriteKeys[QUIC_PACKET_KEY_1_RTT] == NULL"); - Ret = FALSE; - goto Exit; - } - - Result = - TalTestProcessData( - ClientTlsContext2, - &ClientState2, - &ServerState2, - 1200); - - if (!(Result & QUIC_TLS_RESULT_DATA)) { - LOGERROR("!(Result & QUIC_TLS_RESULT_DATA)"); - Ret = FALSE; - goto Exit; - } - - if (!(Result & QUIC_TLS_RESULT_COMPLETE)) { - LOGERROR("!(Result & QUIC_TLS_RESULT_COMPLETE)"); - Ret = FALSE; - goto Exit; - } - - if (ClientState2.WriteKeys[QUIC_PACKET_KEY_1_RTT] == NULL) { - LOGERROR("TalTestServerState.WriteKeys[QUIC_PACKET_KEY_1_RTT] == NULL"); - Ret = FALSE; - goto Exit; - } - - Result = - TalTestProcessData( - ServerTlsContext1, - &ServerState1, - &ClientState1, - 1200); - - if (!(Result & QUIC_TLS_RESULT_COMPLETE)) { - LOGERROR("!(Result & QUIC_TLS_RESULT_COMPLETE)"); - Ret = FALSE; - goto Exit; - } - - Result = - TalTestProcessData( - ServerTlsContext2, - &ServerState2, - &ClientState2, - 1200); - - if (!(Result & QUIC_TLS_RESULT_COMPLETE)) { - LOGERROR("!(Result & QUIC_TLS_RESULT_COMPLETE)"); - Ret = FALSE; - goto Exit; - } - -Exit: - - if (ServerTlsContext1 != NULL) { - QuicTlsUninitialize(ServerTlsContext1); - ServerTlsContext1 = NULL; - } - - if (ServerTlsContext2 != NULL) { - QuicTlsUninitialize(ServerTlsContext2); - ServerTlsContext2 = NULL; - } - - if (ServerConfig != NULL) { - QuicTlsSecConfigRelease(ServerConfig); - ServerConfig = NULL; - } - - if (ClientTlsContext1 != NULL) { - QuicTlsUninitialize(ClientTlsContext1); - ClientTlsContext1 = NULL; - } - - if (ClientTlsContext2 != NULL) { - QuicTlsUninitialize(ClientTlsContext2); - ClientTlsContext2 = NULL; - } - - if (ClientConfig != NULL) { - QuicTlsSecConfigRelease(ClientConfig); - ClientConfig = NULL; - } - - if (TlsSession != NULL) { - QuicTlsSessionUninitialize(TlsSession); - TlsSession = NULL; - } - - if (ClientState1.Buffer != NULL) { - QuicFree(ClientState1.Buffer); - ClientState1.Buffer = NULL; - } - - if (ServerState1.Buffer != NULL) { - QuicFree(ServerState1.Buffer); - ServerState1.Buffer = NULL; - } - - if (ClientState2.Buffer != NULL) { - QuicFree(ClientState2.Buffer); - ClientState2.Buffer = NULL; - } - - if (ServerState2.Buffer != NULL) { - QuicFree(ServerState2.Buffer); - ServerState2.Buffer = NULL; - } - - return Ret; -} - - -static -BOOLEAN -TalTestOneRttKey( - void - ) - -{ - QUIC_STATUS Status = QUIC_STATUS_SUCCESS; - BOOLEAN Ret = TRUE; - QUIC_SEC_CONFIG* ClientConfig = NULL; - QUIC_SEC_CONFIG* ServerConfig = NULL; - QUIC_TLS* ClientTlsContext = NULL; - QUIC_TLS* ServerTlsContext = NULL; - QUIC_TLS_PROCESS_STATE ClientState = {0}; - QUIC_TLS_PROCESS_STATE ServerState = {0}; - QUIC_TLS_SESSION* TlsSession = NULL; - - Status = QuicTlsSessionInitialize("MsQuicTest", &TlsSession); - - if (!QUIC_SUCCEEDED(Status)) { - LOGERROR("QuicTlsSessionInitialize() failed, error %lu", Status); - Ret = FALSE; - goto Exit; - } - - Status = - QuicTlsServerSecConfigCreate( - &TalTestSecConfigRundown, - (QUIC_SEC_CONFIG_FLAGS)TalTestSelfSignedCert->Flags, - TalTestSelfSignedCert->Certificate, - TalTestSelfSignedCert->Principal, - &ServerConfig, - TalTestOnSecConfigCreateComplete); - - if (!QUIC_SUCCEEDED(Status)) { - LOGERROR("Test Init failed. QuicTlsServerSecConfigCreate() failed, error %lu", Status); - Ret = FALSE; - goto Exit; - } - - QuicEventWaitWithTimeout(TalTestSecConfigDoneEvent, 2000); - - if (!TalTestInitializeServer( - TlsSession, - ServerConfig, - &ServerTlsContext)) { - Ret = FALSE; - goto Exit; - } - - Status = QuicTlsClientSecConfigCreate(0, &ClientConfig); - - if (!QUIC_SUCCEEDED(Status)) { - LOGERROR("QuicTlsClientSecConfigCreate() failed, error %lu", Status); - Ret = FALSE; - goto Exit; - } - - if (!TalTestInitializeClient( - TlsSession, - ClientConfig, - &ClientTlsContext)) { - Ret = FALSE; - goto Exit; - } - - if (!TalTestDoHandshake(ServerTlsContext, ClientTlsContext, &ServerState, &ClientState, 1200)) { - Ret = FALSE; - goto Exit; - } - - uint8_t Header[32] = { 1, 2, 3, 4 }; - uint64_t PacketNumber = 0; - uint8_t Buffer[1000] = { 0 }; - uint8_t Iv[QUIC_IV_LENGTH] = {0}; - - QuicCryptoCombineIvAndPacketNumber( - ServerState.WriteKeys[QUIC_PACKET_KEY_1_RTT]->Iv, - (uint8_t *)&PacketNumber, - Iv); - - if (QuicEncrypt( - ServerState.WriteKeys[QUIC_PACKET_KEY_1_RTT]->PacketKey, - Iv, - sizeof(Header), - Header, - sizeof(Buffer), - Buffer) != QUIC_STATUS_SUCCESS) { - Ret = FALSE; - goto Exit; - } - - uint8_t Mask[16]; - - if (QuicHpComputeMask( - ServerState.WriteKeys[QUIC_PACKET_KEY_1_RTT]->HeaderKey, - 1, - Buffer, - Mask) != QUIC_STATUS_SUCCESS) { - Ret = FALSE; - goto Exit; - } - - for (uint32_t i = 0; i < sizeof(Mask); i++) { - Header[i] ^= Mask[i]; - } - - if (QuicHpComputeMask( - ClientState.ReadKeys[QUIC_PACKET_KEY_1_RTT]->HeaderKey, - 1, - Buffer, - Mask) != QUIC_STATUS_SUCCESS) { - Ret = FALSE; - goto Exit; - } - - for (uint32_t i = 0; i < sizeof(Mask); i++) { - Header[i] ^= Mask[i]; - } - - QuicCryptoCombineIvAndPacketNumber( - ServerState.ReadKeys[QUIC_PACKET_KEY_1_RTT]->Iv, - (uint8_t *)&PacketNumber, - Iv); - - if (QuicDecrypt( - ClientState.ReadKeys[QUIC_PACKET_KEY_1_RTT]->PacketKey, - Iv, - sizeof(Header), - Header, - sizeof(Buffer), - Buffer) != QUIC_STATUS_SUCCESS) { - Ret = FALSE; - goto Exit; - } - - if (Header[0] != 1 || - Header[1] != 2 || - Header[2] != 3 || - Header[3] != 4) { - Ret = FALSE; - goto Exit; - } - - for (uint32_t i = 0; i < sizeof(Buffer) - QUIC_ENCRYPTION_OVERHEAD; i++) { - if (Buffer[i] != 0) { - Ret = FALSE; - goto Exit; - } - } - -Exit: - - if (ServerTlsContext != NULL) { - QuicTlsUninitialize(ServerTlsContext); - ServerTlsContext = NULL; - } - - if (ServerConfig != NULL) { - QuicTlsSecConfigRelease(ServerConfig); - ServerConfig = NULL; - } - - if (ClientTlsContext != NULL) { - QuicTlsUninitialize(ClientTlsContext); - ClientTlsContext = NULL; - } - - if (ClientConfig != NULL) { - QuicTlsSecConfigRelease(ClientConfig); - ClientConfig = NULL; - } - - if (TlsSession != NULL) { - QuicTlsSessionUninitialize(TlsSession); - TlsSession = NULL; - } - - return Ret; -} - - -static -BOOLEAN -TalTestKeyUpdate( - void - ) - -{ - QUIC_STATUS Status = QUIC_STATUS_SUCCESS; - BOOLEAN Ret = TRUE; - QUIC_SEC_CONFIG* ClientConfig = NULL; - QUIC_SEC_CONFIG* ServerConfig = NULL; - QUIC_TLS* ClientTlsContext = NULL; - QUIC_TLS* ServerTlsContext = NULL; - QUIC_TLS_PROCESS_STATE ClientState = {0}; - QUIC_TLS_PROCESS_STATE ServerState = {0}; - QUIC_TLS_SESSION* TlsSession = NULL; - QUIC_PACKET_KEY *UpdateWriteKey = NULL; - QUIC_PACKET_KEY *UpdateReadKey = NULL; - - Status = QuicTlsSessionInitialize("MsQuicTest", &TlsSession); - - if (!QUIC_SUCCEEDED(Status)) { - LOGERROR("QuicTlsSessionInitialize() failed, error %lu", Status); - Ret = FALSE; - goto Exit; - } - - Status = - QuicTlsServerSecConfigCreate( - &TalTestSecConfigRundown, - (QUIC_SEC_CONFIG_FLAGS)TalTestSelfSignedCert->Flags, - TalTestSelfSignedCert->Certificate, - TalTestSelfSignedCert->Principal, - &ServerConfig, - TalTestOnSecConfigCreateComplete); - - if (!QUIC_SUCCEEDED(Status)) { - LOGERROR("Test Init failed. QuicTlsServerSecConfigCreate() failed, error %lu", Status); - Ret = FALSE; - goto Exit; - } - - QuicEventWaitWithTimeout(TalTestSecConfigDoneEvent, 2000); - - if (!TalTestInitializeServer( - TlsSession, - ServerConfig, - &ServerTlsContext)) { - Ret = FALSE; - goto Exit; - } - - Status = QuicTlsClientSecConfigCreate(0, &ClientConfig); - - if (!QUIC_SUCCEEDED(Status)) { - LOGERROR("QuicTlsClientSecConfigCreate() failed, error %lu", Status); - Ret = FALSE; - goto Exit; - } - - if (!TalTestInitializeClient( - TlsSession, - ClientConfig, - &ClientTlsContext)) { - Ret = FALSE; - goto Exit; - } - - if (!TalTestDoHandshake(ServerTlsContext, ClientTlsContext, &ServerState, &ClientState, 1200)) { - Ret = FALSE; - goto Exit; - } - - if (!QUIC_SUCCEEDED( - QuicPacketKeyUpdate( - ServerState.WriteKeys[QUIC_PACKET_KEY_1_RTT], - &UpdateWriteKey))) { - Ret = FALSE; - goto Exit; - } - - if (!QUIC_SUCCEEDED( - QuicPacketKeyUpdate( - ClientState.ReadKeys[QUIC_PACKET_KEY_1_RTT], - &UpdateReadKey))) { - Ret = FALSE; - goto Exit; - } - - uint8_t Header[32] = { 1, 2, 3, 4 }; - uint64_t PacketNumber = 0; - uint8_t Buffer[1000] = { 0 }; - uint8_t Iv[QUIC_IV_LENGTH] = {0}; - - QuicCryptoCombineIvAndPacketNumber( - UpdateWriteKey->Iv, - (uint8_t *)&PacketNumber, - Iv); - - if (QuicEncrypt( - UpdateWriteKey->PacketKey, - Iv, - sizeof(Header), - Header, - sizeof(Buffer), - Buffer) != QUIC_STATUS_SUCCESS) { - Ret = FALSE; - goto Exit; - } - - uint8_t Mask[16]; - - if (QuicHpComputeMask( - UpdateWriteKey->HeaderKey, - 1, - Buffer, - Mask) != QUIC_STATUS_SUCCESS) { - Ret = FALSE; - goto Exit; - } - - for (uint32_t i = 0; i < sizeof(Mask); i++) { - Header[i] ^= Mask[i]; - } - - if (QuicHpComputeMask( - UpdateReadKey->HeaderKey, - 1, - Buffer, - Mask) != QUIC_STATUS_SUCCESS) { - Ret = FALSE; - goto Exit; - } - - for (uint32_t i = 0; i < sizeof(Mask); i++) { - Header[i] ^= Mask[i]; - } - - QuicCryptoCombineIvAndPacketNumber( - UpdateReadKey->Iv, - (uint8_t *)&PacketNumber, - Iv); - - if (QuicDecrypt( - UpdateReadKey->PacketKey, - Iv, - sizeof(Header), - Header, - sizeof(Buffer), - Buffer) != QUIC_STATUS_SUCCESS) { - Ret = FALSE; - goto Exit; - } - - if (Header[0] != 1 || - Header[1] != 2 || - Header[2] != 3 || - Header[3] != 4) { - Ret = FALSE; - goto Exit; - } - - for (uint32_t i = 0; i < sizeof(Buffer) - QUIC_ENCRYPTION_OVERHEAD; i++) { - if (Buffer[i] != 0) { - Ret = FALSE; - goto Exit; - } - } - -Exit: - - if (ServerTlsContext != NULL) { - QuicTlsUninitialize(ServerTlsContext); - ServerTlsContext = NULL; - } - - if (ServerConfig != NULL) { - QuicTlsSecConfigRelease(ServerConfig); - ServerConfig = NULL; - } - - if (ClientTlsContext != NULL) { - QuicTlsUninitialize(ClientTlsContext); - ClientTlsContext = NULL; - } - - if (ClientConfig != NULL) { - QuicTlsSecConfigRelease(ClientConfig); - ClientConfig = NULL; - } - - if (TlsSession != NULL) { - QuicTlsSessionUninitialize(TlsSession); - TlsSession = NULL; - } - - return Ret; -} - - -static -void -TalTestExecuteTestCase( - _In_ uint32_t TestCaseIndex - ) - -{ - LOGINFO("*Start Testcase: %s.*", TestCases[TestCaseIndex].TestCaseName); - if ((TestCases[TestCaseIndex].TestCaseFunc)()) { - LOGINFO("*Testcase succeeded.*"); - } else { - LOGERROR("*Testcase failed.*"); - } - LOGINFO("*Stop Testcase:%s.*", TestCases[TestCaseIndex].TestCaseName); -} - - -static -void -TalTestHelp( - _In_ char *argv[] - ) - -{ - printf("Usage: \n"); - printf("To execute all tests: %s %ld \n", argv[0], ARRAYSIZE(TestCases)); - printf("To execute a specific test: %s \n", argv[0]); - printf("Test cases: \n"); - for (uint32_t Iter = 0; Iter < ARRAYSIZE(TestCases); Iter++) { - printf("\t%lu: %s\n", Iter, TestCases[Iter].TestCaseName); - } -} - - -int -main( - _In_ int argc, - _In_reads_(argc) char *argv[] - ) -/*++ - -Routine Description: - - Program entry point. - -Arguments: - - argc - Number of tokens. - - argv - Array of tokens. The caller will populate the first token with the - program name/path. - -Return Value: - - Exit Code. - ---*/ -{ - uint32_t Input = 0; - - if (argc != 2) { - TalTestHelp(argv); - return 0; - } - - TalTestSetUpTestCase(); - - Input = atoi(argv[1]); - if (Input < ARRAYSIZE(TestCases)) { - TalTestExecuteTestCase(Input); - } else if (Input == ARRAYSIZE(TestCases)) { - for (uint32_t Iter = 0; Iter < ARRAYSIZE(TestCases); Iter++) { - TalTestExecuteTestCase(Iter); - } - } else { - LOGERROR("Incorrect Input"); - TalTestHelp(argv); - } - - TalTestTearDownTestCase(); -} - diff --git a/src/platform/unittest/main.cpp b/src/platform/unittest/main.cpp index cf5e97cb87dd..a7f286a8804e 100644 --- a/src/platform/unittest/main.cpp +++ b/src/platform/unittest/main.cpp @@ -5,42 +5,28 @@ --*/ -#include "quic_platform.h" - -#define LOG_ONLY_FAILURES -#define INLINE_TEST_METHOD_MARKUP -#include -#include - -#include "quic_trace.h" +#include "main.h" #ifdef QUIC_LOGS_WPP #include "main.tmh" #endif -using namespace WEX::Common; - -BEGIN_MODULE() - MODULE_PROPERTY(L"BinaryUnderTest", L"platform.lib") - MODULE_PROPERTY(L"Description", L"Tests the QUIC platform user-mode library") - MODULE_PROPERTY(L"Owner", L"nibanks") -END_MODULE() +extern "C" _IRQL_requires_max_(PASSIVE_LEVEL) void QuicTraceRundown(void) { } -extern "C" void QuicTraceRundown(void) { } - -MODULE_SETUP(GlobalTestSetup) -{ - QuicPlatformSystemLoad(); - if (QUIC_FAILED(QuicPlatformInitialize())) { +class QuicCoreTestEnvironment : public ::testing::Environment { +public: + void SetUp() override { + QuicPlatformSystemLoad(); + ASSERT_TRUE(QUIC_SUCCEEDED(QuicPlatformInitialize())); + } + void TearDown() override { + QuicPlatformUninitialize(); QuicPlatformSystemUnload(); - return false; } - return true; -} +}; -MODULE_CLEANUP(GlobalTestCleanup) -{ - QuicPlatformUninitialize(); - QuicPlatformSystemUnload(); - return true; +int main(int argc, char** argv) { + ::testing::AddGlobalTestEnvironment(new QuicCoreTestEnvironment); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); } diff --git a/src/platform/unittest/main.h b/src/platform/unittest/main.h new file mode 100644 index 000000000000..b89e2eed5c91 --- /dev/null +++ b/src/platform/unittest/main.h @@ -0,0 +1,21 @@ +/*++ + + Copyright (c) Microsoft Corporation. + Licensed under the MIT License. + +--*/ + +#undef min // gtest headers conflict with previous definitions of min/max. +#undef max +#include "gtest/gtest.h" + +#define QUIC_TEST_APIS 1 + +#include "quic_platform.h" + +#include "quic_trace.h" + +#define VERIFY_QUIC_SUCCESS(result) ASSERT_TRUE(QUIC_SUCCEEDED(result)) + +#define GTEST_SKIP_NO_RETURN_(message) \ + GTEST_MESSAGE_(message, ::testing::TestPartResult::kSkip)