From 7c1f6b4143a9429ffb80c16eaf784e7008292a05 Mon Sep 17 00:00:00 2001 From: Changyu Li Date: Fri, 29 Mar 2024 03:39:59 +0000 Subject: [PATCH] Merged PR 10481180: Add OpenSSL implementation for AesGcm test ## Description: ## Admin Checklist: - [ ] You have updated documentation in symcrypt.h to reflect any changes in behavior - [ ] You have updated CHANGELOG.md to reflect any changes in behavior - [ ] You have updated symcryptunittest to exercise any new functionality - [ ] If you have introduced any symbols in symcrypt.h you have updated production and test dynamic export symbols (exports.ver / exports.def / symcrypt.src) and tested the updated dynamic modules with symcryptunittest - [ ] If you have introduced functionality that varies based on CPU features, you have manually tested with and without relevant features - [ ] If you have made significant changes to a particular algorithm, you have checked that performance numbers reported by symcryptunittest are in line with expectations - [ ] If you have added new algorithms/modes, you have updated the status indicator text for the associated modules if necessary Add OpenSSL implementation for AesGcm test --- .pipelines/OneBranch.PullRequest.yml | 6 +- .pipelines/templates/build-linux.yml | 12 +- .vscode/launch.json | 37 +-- .vscode/settings.json | 15 +- .vscode/tasks.json | 73 +++-- BUILD.md | 7 +- CMakeLists.txt | 5 +- cmake-configs/OpenSSL.cmake | 16 +- unittest/CMakeLists.txt | 9 + unittest/inc/openssl_implementations.h | 10 +- unittest/lib/openssl_implementations.cpp | 388 ++++++++++++++++++++++- unittest/lib/perfPrint.cpp | 27 ++ 12 files changed, 532 insertions(+), 73 deletions(-) diff --git a/.pipelines/OneBranch.PullRequest.yml b/.pipelines/OneBranch.PullRequest.yml index 0935263..924d1bf 100644 --- a/.pipelines/OneBranch.PullRequest.yml +++ b/.pipelines/OneBranch.PullRequest.yml @@ -146,7 +146,8 @@ extends: cc: 'gcc' cxx: 'g++' skipTests: true - additionalArgs: '--no-asm --openssl' + additionalArgs: '--no-asm' + openssl: true identifier: 'NoAsm' - template: .pipelines/templates/build-linux.yml@self parameters: @@ -155,7 +156,8 @@ extends: cc: 'clang' cxx: 'clang++' skipTests: true - additionalArgs: '--no-asm --openssl' + additionalArgs: '--no-asm' + openssl: true identifier: 'NoAsm' - template: .pipelines/templates/build-linux.yml@self parameters: diff --git a/.pipelines/templates/build-linux.yml b/.pipelines/templates/build-linux.yml index 6c2c5d8..bacd594 100644 --- a/.pipelines/templates/build-linux.yml +++ b/.pipelines/templates/build-linux.yml @@ -50,7 +50,7 @@ jobs: ${{ else }}: verbose_build_flag: '' ${{ if eq(parameters.openssl, true) }}: - openssl_build_flag: '--openssl' + openssl_build_flag: '--openssl-build-from-source' ${{ else }}: openssl_build_flag: '' @@ -86,10 +86,12 @@ jobs: apt-get install -y gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf qemu-user displayName: 'Install arm cross-compilation tools' - - ${{ if eq(parameters.openssl, true) }}: - - script: | - apt-get install -y libssl-dev - displayName: 'Install OpenSSL' + # TODO: Once we move to Azure Linux 3 we can use the system-provided OpenSSL package. + # For now we will built from source since Ubuntu 20.04 doesn't have OpenSSL 3. + # - ${{ if eq(parameters.openssl, true) }}: + # - script: | + # apt-get install -y libssl-dev + # displayName: 'Install OpenSSL' - task: PipAuthenticate@1 inputs: diff --git a/.vscode/launch.json b/.vscode/launch.json index 5489d20..6ba95e4 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -4,6 +4,14 @@ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ + { + "type": "lldb", + "request": "launch", + "name": "(lldb) symcryptunittest", + "program": "${workspaceFolder}/bin/exe/symcryptunittest", + "args": [], + "cwd": "${workspaceFolder}" + }, { "name": "(Windows) symcryptunittest", "type": "cppvsdbg", @@ -17,34 +25,5 @@ "console": "integratedTerminal", "internalConsoleOptions": "openOnSessionStart" }, - { - "name": "(Windows) symcryptunittest [+openssl +symcrypt +xtsaes]", - "type": "cppvsdbg", - "request": "launch", - "program": "${workspaceFolder}/bin/exe/symcryptunittest.exe", - "args": [ - "+openssl", - "+symcrypt", - "+xtsaes", - ], - "stopAtEntry": false, - "cwd": "${fileDirname}", - "console": "integratedTerminal", - }, - { - "name": "(Windows) symcryptunittest [+openssl +symcrypt +xtsaes -vaes]", - "type": "cppvsdbg", - "request": "launch", - "program": "${workspaceFolder}/bin/exe/symcryptunittest.exe", - "args": [ - "+openssl", - "+symcrypt", - "+xtsaes", - "-vaes" - ], - "stopAtEntry": false, - "cwd": "${fileDirname}", - "console": "integratedTerminal", - }, ] } \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index d4fee91..ae2cdc9 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -11,5 +11,18 @@ "icon": "terminal-powershell", "overrideName": true, } - } + }, + "terminal.integrated.defaultProfile.linux": "SymCrypt Profile", + "terminal.integrated.profiles.linux": { + "SymCrypt Profile": { + "args": [ + "-c", + "[ -f ./.venv/bin/activate ] && . ./.venv/bin/activate; exec bash" + ], + "path": "bash", + "source": "bash", + "icon": "terminal-bash", + "overrideName": true, + } + }, } \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 6a3043b..7ef1246 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -11,16 +11,20 @@ } }, }, + "linux": { + "options": { + "shell": { + "executable": "bash", + "args": [ + "-c", + ] + } + }, + }, "tasks": [ { "label": "Setup", "type": "shell", - "command": [ - "python -m venv .venv;", - ". .\\.venv\\Scripts\\activate.ps1;", - "pip install -r .\\scripts\\requirements.txt;", - "Set-Content -value ('pushd;\n& \"\"\"' + (resolve-path 'C:\\Program Files\\Microsoft Visual Studio\\*\\*\\Common7\\Tools\\Launch-VsDevShell.ps1').path + '\"\"\" -Arch $env:PROCESSOR_ARCHITECTURE -HostArch $env:PROCESSOR_ARCHITECTURE;\npopd') -path '${workspaceFolder}\\.venv\\profile.ps1';", - ], "options": { "cwd": "${workspaceFolder}/", }, @@ -31,14 +35,36 @@ "panel": "shared", "showReuseMessage": true, "clear": false, + }, + "windows": { + "command": [ + "python -m venv .venv;", + ". .\\.venv\\Scripts\\activate.ps1;", + "pip install -r .\\scripts\\requirements.txt;", + "Set-Content -value ('pushd;\n& \"\"\"' + (resolve-path 'C:\\Program Files\\Microsoft Visual Studio\\*\\*\\Common7\\Tools\\Launch-VsDevShell.ps1').path + '\"\"\" -Arch $env:PROCESSOR_ARCHITECTURE -HostArch $env:PROCESSOR_ARCHITECTURE;\npopd') -path '${workspaceFolder}\\.venv\\profile.ps1';", + ], + }, + "linux": { + "command": [ + "python3 -m venv .venv;", + ". ./.venv/bin/activate;", + "pip install -r ./scripts/requirements.txt;", + ], } }, { "label": "Clean", "type": "shell", - "command": [ - "del -recurse bin_*,bin;", - ], + "windows": { + "command": [ + "del -recurse bin_*,bin,.venv;", + ], + }, + "linux": { + "command": [ + "rm -rf bin_* bin .venv" + ] + }, "options": { "cwd": "${workspaceFolder}/", }, @@ -54,16 +80,25 @@ { "label": "Build [Debug]", "type": "shell", - "command": "python", - "args": [ - ".\\scripts\\build.py", - "cmake", - "bin", - "--arch", - "amd64", - "--config", - "Debug", - ], + "windows": { + "command": "python", + "args": [ + ".\\scripts\\build.py", + "cmake", + "bin", + "--arch", + "amd64", + "--config", + "Debug", + ], + }, + "linux": { + "command": [ + "[ -f ./.venv/bin/activate ] && . ./.venv/bin/activate;", + "python3 ./scripts/build.py cmake bin --arch amd64 --config Debug;", + "exit", + ] + }, "options": { "cwd": "${workspaceFolder}/", }, diff --git a/BUILD.md b/BUILD.md index 8c97e1b..e7f0618 100644 --- a/BUILD.md +++ b/BUILD.md @@ -89,6 +89,7 @@ apt update apt -y install --no-install-recommends \ cmake \ python3-pyelftools \ + build-essential \ gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf ``` `python3-pyelftools` is for integrity verification and `gcc-arm-linux-gnueabihf` `g++-arm-linux-gnueabihf` are for ARM cross compile @@ -110,19 +111,19 @@ prerequisites to building OpenSSL. ``` winget install nasm strawberryperl -.\scripts\build.py cmake bin --config Release --openssl-build-from-source +python3 .\scripts\build.py cmake bin --config Release --openssl-build-from-source ``` And on Linux we can use OpenSSL installed by system's package manager. ``` sudo apt install -y libssl-dev -./scripts/build.py cmake bin --config Release --openssl +python3 ./scripts/build.py cmake bin --config Release --openssl ``` To build OpenSSL on Linux we need to install following prerequisites. ``` sudo apt install -y nasm perl -.\scripts\build.py cmake bin --config Release --openssl-build-from-source +python3 ./scripts/build.py cmake bin --config Release --openssl-build-from-source ``` diff --git a/CMakeLists.txt b/CMakeLists.txt index d3583f7..1a1e9f8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,9 +81,6 @@ option( OFF) -if (SYMCRYPT_TEST_WITH_OPENSSL) - include(${CMAKE_SOURCE_DIR}/cmake-configs/OpenSSL.cmake) -endif() include(${CMAKE_SOURCE_DIR}/cmake-configs/SymCrypt-Platforms.cmake) if(NOT DEFINED CMAKE_BUILD_TYPE) @@ -122,4 +119,4 @@ configure_file(build/symcrypt.pc.in symcrypt.pc @ONLY) add_subdirectory(lib) add_subdirectory(modules) -add_subdirectory(unittest) \ No newline at end of file +add_subdirectory(unittest) diff --git a/cmake-configs/OpenSSL.cmake b/cmake-configs/OpenSSL.cmake index 14ef79f..9866354 100644 --- a/cmake-configs/OpenSSL.cmake +++ b/cmake-configs/OpenSSL.cmake @@ -29,12 +29,12 @@ if(OPENSSL_BUILD_FROM_SOURCE) set(ENV{CL} /MP) if(OPENSSL_BUILD_TYPE STREQUAL "release") execute_process( - COMMAND perl Configure no-ssl no-tls1 no-tls1_1 --release + COMMAND perl Configure no-ssl no-tls no-dtls no-legacy no-engine no-weak-ssl-ciphers no-rc4 no-rc5 no-rc2 no-md4 no-deprecated no-apps no-docs no-tests no-shared --release WORKING_DIRECTORY ${OPENSSL_BUILD_ROOT} RESULT_VARIABLE result) else() execute_process( - COMMAND perl Configure no-ssl no-tls1 no-tls1_1 --debug + COMMAND perl Configure no-ssl no-tls no-dtls no-legacy no-engine no-weak-ssl-ciphers no-rc4 no-rc5 no-rc2 no-md4 no-deprecated no-apps no-docs no-tests no-shared --debug WORKING_DIRECTORY ${OPENSSL_BUILD_ROOT} RESULT_VARIABLE result) endif() @@ -61,11 +61,11 @@ if(OPENSSL_BUILD_FROM_SOURCE) include(${OPENSSL_BUILD_ROOT}/OpenSSLConfig.cmake) else() - find_package(OpenSSL REQUIRED) + find_package(OpenSSL 3 REQUIRED) endif() -message("Found OpenSSL include directory ${OPENSSL_INCLUDE_DIR}") -include_directories(${OPENSSL_INCLUDE_DIR}) -link_directories(${OPENSSL_LIBRARY_DIR}) -link_libraries(${OPENSSL_CRYPTO_LIBRARIES}) -add_compile_options(-DINCLUDE_IMPL_OPENSSL=1) +if(OPENSSL_VERSION_MAJOR LESS 3) + message(FATAL_ERROR "-- Invalid OpenSSL version found ${OPENSSL_VERSION} at ${OPENSSL_INCLUDE_DIR}") +else() + message("-- Found OpenSSL ${OPENSSL_VERSION} include directory ${OPENSSL_INCLUDE_DIR}") +endif() diff --git a/unittest/CMakeLists.txt b/unittest/CMakeLists.txt index a94dd05..9c82f28 100644 --- a/unittest/CMakeLists.txt +++ b/unittest/CMakeLists.txt @@ -79,6 +79,15 @@ if(WIN32 AND SYMCRYPT_TARGET_ARCH MATCHES "X86") add_link_options(/SAFESEH:NO) endif() + +if(SYMCRYPT_TEST_WITH_OPENSSL) + include(${CMAKE_SOURCE_DIR}/cmake-configs/OpenSSL.cmake) + include_directories(${OPENSSL_INCLUDE_DIR}) + link_directories(${OPENSSL_LIBRARY_DIR}) + link_libraries(${OPENSSL_CRYPTO_LIBRARIES}) + add_compile_options(-DINCLUDE_IMPL_OPENSSL=1) +endif() + include_directories(inc) include_directories(lib) include_directories(resource) diff --git a/unittest/inc/openssl_implementations.h b/unittest/inc/openssl_implementations.h index 5b58aa4..6dd715a 100644 --- a/unittest/inc/openssl_implementations.h +++ b/unittest/inc/openssl_implementations.h @@ -24,5 +24,13 @@ public: EVP_CIPHER_CTX* decCtx; }; +template<> +class AuthEncImpState { +public: + EVP_CIPHER_CTX* encCtx; + EVP_CIPHER_CTX* decCtx; + BOOLEAN inComputation; +}; + VOID -addOpensslAlgs(); \ No newline at end of file +addOpensslAlgs(); diff --git a/unittest/lib/openssl_implementations.cpp b/unittest/lib/openssl_implementations.cpp index 88e0910..56d869a 100644 --- a/unittest/lib/openssl_implementations.cpp +++ b/unittest/lib/openssl_implementations.cpp @@ -4,6 +4,8 @@ #include "precomp.h" #include +#include +#include #include char * ImpOpenssl::name = "OpenSSL"; @@ -28,6 +30,8 @@ std::string getOpensslError() #define CHECK_OPENSSL_SUCCESS(osslInvocation) CHECK(((osslInvocation) == 1), getOpensslError().data()) +// AlgXtsAes + struct ExpandedKeyContext { EVP_CIPHER_CTX* encCtx; @@ -337,11 +341,393 @@ XtsImp::decryptWith128bTweak( return STATUS_SUCCESS; } +// AlgXtsAes end + +// ModeGcm + +template<> +VOID +algImpKeyPerfFunction< ImpOpenssl, AlgAes, ModeGcm>( PBYTE expandedKey, PBYTE keyBytes, PBYTE buf3, SIZE_T keySize ) +{ + UNREFERENCED_PARAMETER( buf3 ); + + // SymCryptGcmExpandKey( (PSYMCRYPT_GCM_EXPANDED_KEY) expandedKey, + // SymCryptAesBlockCipher, + // keyBytes, keySize ); + + const EVP_CIPHER *cipher = NULL; + + if (keySize == 32) + { + cipher = EVP_aes_256_gcm(); + } + else if (keySize == 24) + { + cipher = EVP_aes_192_gcm(); + } + else if (keySize == 16) + { + cipher = EVP_aes_128_gcm(); + } + CHECK(cipher != NULL, "Unsupported key length"); + + EVP_CIPHER_CTX* encCtx = EVP_CIPHER_CTX_new(); + EVP_CIPHER_CTX* decCtx = EVP_CIPHER_CTX_new(); + CHECK_OPENSSL_SUCCESS(EVP_EncryptInit_ex(encCtx, cipher, NULL, keyBytes, NULL)); + CHECK_OPENSSL_SUCCESS(EVP_DecryptInit_ex(decCtx, cipher, NULL, keyBytes, NULL)); + + ExpandedKeyContext *pContext = (ExpandedKeyContext *)expandedKey; + pContext->encCtx = encCtx; + pContext->decCtx = decCtx; +} + +template<> +VOID +algImpDataPerfFunction( PBYTE expandedKey, PBYTE buf2, PBYTE buf3, SIZE_T dataSize ) +{ + // SymCryptGcmEncrypt( (PCSYMCRYPT_GCM_EXPANDED_KEY) expandedKey, + // buf2, 12, + // nullptr, 0, + // buf2 + 16, buf3 + 16, dataSize, + // buf3, 16 ); + + int outlen = 0; + PCBYTE pbNonce = buf2; + PCBYTE pbSrc = buf2 + 16; + PBYTE pbDst = buf3 + 16; + SIZE_T cbData = dataSize; + PBYTE pbTag = buf3; + SIZE_T cbTag = 16; + ExpandedKeyContext *pContext = (ExpandedKeyContext *)expandedKey; + + // Default nonce size is 12. + CHECK(EVP_EncryptInit_ex2(pContext->encCtx, NULL, NULL, pbNonce, NULL) == 1, getOpensslError().data()); + CHECK(EVP_EncryptUpdate(pContext->encCtx, pbDst, &outlen, pbSrc, (int)cbData) == 1, getOpensslError().data()); + CHECK(EVP_EncryptFinal_ex(pContext->encCtx, pbDst, &outlen) == 1, getOpensslError().data()); + CHECK(EVP_CIPHER_CTX_ctrl(pContext->encCtx, EVP_CTRL_AEAD_GET_TAG, (int)cbTag, pbTag) > 0, getOpensslError().data()); +} + +template<> +VOID +algImpDecryptPerfFunction( PBYTE expandedKey, PBYTE buf2, PBYTE buf3, SIZE_T dataSize ) +{ + // SymCryptGcmDecrypt( (PCSYMCRYPT_GCM_EXPANDED_KEY) buf1, + // buf2, 12, + // nullptr, 0, + // buf3 + 16, buf2 + 16, dataSize, + // buf3, 16 ); + int outlen = 0; + PCBYTE pbNonce = buf2; + PCBYTE pbSrc = buf3 + 16; + PBYTE pbDst = buf2 + 16; + SIZE_T cbData = dataSize; + PBYTE pbTag = buf3; + SIZE_T cbTag = 16; + ExpandedKeyContext *pContext = (ExpandedKeyContext *)expandedKey; + + // Default nonce size is 12. + CHECK(EVP_DecryptInit_ex2(pContext->decCtx, NULL, NULL, pbNonce, NULL) == 1, getOpensslError().data()); + CHECK(EVP_DecryptUpdate(pContext->decCtx, pbDst, &outlen, pbSrc, (int)cbData) == 1, getOpensslError().data()); + CHECK(EVP_CIPHER_CTX_ctrl(pContext->decCtx, EVP_CTRL_AEAD_SET_TAG, + (int)cbTag, (void *)pbTag) > 0, getOpensslError().data()); + CHECK(EVP_DecryptFinal_ex(pContext->decCtx, pbDst, &outlen) == 1, getOpensslError().data()); +} + +template<> +VOID +algImpCleanPerfFunction( PBYTE expandedKey, PBYTE buf2, PBYTE buf3 ) +{ + ExpandedKeyContext *pContext = (ExpandedKeyContext *)expandedKey; + UNREFERENCED_PARAMETER( buf2 ); + UNREFERENCED_PARAMETER( buf3 ); + + EVP_CIPHER_CTX_free(pContext->encCtx); + EVP_CIPHER_CTX_free(pContext->decCtx); +} + +template<> +AuthEncImp::AuthEncImp() +{ + m_perfKeyFunction = &algImpKeyPerfFunction; + m_perfCleanFunction = &algImpCleanPerfFunction; + m_perfDataFunction = &algImpDataPerfFunction; + m_perfDecryptFunction = &algImpDecryptPerfFunction; + state.encCtx = EVP_CIPHER_CTX_new(); + state.decCtx = EVP_CIPHER_CTX_new(); +} + +template<> +AuthEncImp::~AuthEncImp() +{ + EVP_CIPHER_CTX_free(state.encCtx); + EVP_CIPHER_CTX_free(state.decCtx); +} + +template<> +std::set +AuthEncImp::getKeySizes() +{ + std::set res; + + res.insert( 16 ); + res.insert( 24 ); + res.insert( 32 ); + + return res; +} + + +template<> +std::set +AuthEncImp::getNonceSizes() +{ + std::set res; + + for(int i = 1; i <= 256; ++i) + { + res.insert( i ); + } + + return res; +} + + +template<> +std::set +AuthEncImp::getTagSizes() +{ + std::set res; + + for( int i=12; i<=16; i ++ ) + { + res.insert( i ); + } + + return res; +} + +template<> +NTSTATUS +AuthEncImp::setKey( PCBYTE pbKey, SIZE_T cbKey ) +{ + const EVP_CIPHER *cipher = NULL; + + if (cbKey == 32) + { + cipher = EVP_aes_256_gcm(); + } + else if (cbKey == 24) + { + cipher = EVP_aes_192_gcm(); + } + else if (cbKey == 16) + { + cipher = EVP_aes_128_gcm(); + } + else + { + return STATUS_NOT_SUPPORTED; + } + + CHECK(EVP_EncryptInit_ex2(state.encCtx, cipher, pbKey, NULL, NULL) == 1, getOpensslError().data()); + CHECK(EVP_DecryptInit_ex2(state.decCtx, cipher, pbKey, NULL, NULL) == 1, getOpensslError().data()); + + + // SymCryptGcmExpandKey( &state.key, SymCryptAesBlockCipher, pbKey, cbKey ); + + state.inComputation = FALSE; + return STATUS_SUCCESS; +} + +template<> +VOID +AuthEncImp::setTotalCbData( SIZE_T ) +{ +} + +template<> +NTSTATUS +AuthEncImp::encrypt( + _In_reads_( cbNonce ) PCBYTE pbNonce, + SIZE_T cbNonce, + _In_reads_( cbAuthData ) PCBYTE pbAuthData, + SIZE_T cbAuthData, + _In_reads_( cbData ) PCBYTE pbSrc, + _Out_writes_( cbData ) PBYTE pbDst, + SIZE_T cbData, + _Out_writes_( cbTag ) PBYTE pbTag, + SIZE_T cbTag, + ULONG flags ) +{ + NTSTATUS status = STATUS_SUCCESS; + int outlen = 0; + + CHECK( (flags & ~AUTHENC_FLAG_PARTIAL) == 0, "Unknown flag" ); + + const int GCM_IV_MAX_SIZE = (1024 / 8); + if( cbNonce > GCM_IV_MAX_SIZE ) + { + return STATUS_NOT_SUPPORTED; + } + + if( (flags & AUTHENC_FLAG_PARTIAL) == 0 ) + { + // simple straight GCM computation. + // CHECK( SymCryptGcmValidateParameters( + // SymCryptAesBlockCipher, + // cbNonce, + // cbAuthData, + // cbData, + // cbTag ) == SYMCRYPT_NO_ERROR, "?" ); + + // SymCryptGcmEncrypt( &state.key, + // pbNonce, cbNonce, pbAuthData, cbAuthData, + // pbSrc, pbDst, cbData, + // pbTag, cbTag ); + OSSL_PARAM params[2] = { + OSSL_PARAM_END, OSSL_PARAM_END + }; + + params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_AEAD_IVLEN, + &cbNonce); + CHECK(EVP_EncryptInit_ex2(state.encCtx, NULL, NULL, pbNonce, params) == 1, getOpensslError().data()); + CHECK(EVP_EncryptUpdate(state.encCtx, NULL, &outlen, pbAuthData, (int)cbAuthData) == 1, getOpensslError().data()); + CHECK(EVP_EncryptUpdate(state.encCtx, pbDst, &outlen, pbSrc, (int)cbData) == 1, getOpensslError().data()); + CHECK(EVP_EncryptFinal_ex(state.encCtx, pbDst, &outlen) == 1, getOpensslError().data()); + params[0] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, + pbTag, cbTag); + + CHECK(EVP_CIPHER_CTX_get_params(state.encCtx, params) == 1, getOpensslError().data()); + + // Done + goto cleanup; + } + + if( !state.inComputation ) + { + OSSL_PARAM params[2] = { + OSSL_PARAM_END, OSSL_PARAM_END + }; + + params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_AEAD_IVLEN, + &cbNonce); + CHECK(EVP_EncryptInit_ex2(state.encCtx, NULL, NULL, pbNonce, params) == 1, getOpensslError().data()); + CHECK(EVP_EncryptUpdate(state.encCtx, NULL, &outlen, pbAuthData, (int)cbAuthData) == 1, getOpensslError().data()); + state.inComputation = TRUE; + } + + CHECK(EVP_EncryptUpdate(state.encCtx, pbDst, &outlen, pbSrc, (int)cbData) == 1, getOpensslError().data()); + + if( pbTag != nullptr ) + { + CHECK(EVP_EncryptFinal_ex(state.encCtx, pbDst, &outlen) == 1, getOpensslError().data()); + EVP_CIPHER_CTX_ctrl(state.encCtx, EVP_CTRL_AEAD_GET_TAG, (int)cbTag, pbTag); + state.inComputation = FALSE; + } + +cleanup: + return status; +} + +template<> +NTSTATUS +AuthEncImp::decrypt( + _In_reads_( cbNonce ) PCBYTE pbNonce, + SIZE_T cbNonce, + _In_reads_( cbAuthData ) PCBYTE pbAuthData, + SIZE_T cbAuthData, + _In_reads_( cbData ) PCBYTE pbSrc, + _Out_writes_( cbData ) PBYTE pbDst, + SIZE_T cbData, + _In_reads_( cbTag ) PCBYTE pbTag, + SIZE_T cbTag, + ULONG flags ) +{ + int scError = 1; + int outlen = 0; + + CHECK( (flags & ~AUTHENC_FLAG_PARTIAL) == 0, "Unknown flag" ); + const int GCM_IV_MAX_SIZE = (1024 / 8); + if( cbNonce > GCM_IV_MAX_SIZE ) + { + return STATUS_NOT_SUPPORTED; + } + + if( (flags & AUTHENC_FLAG_PARTIAL) == 0 ) + { + // simple straight GCM computation. + // CHECK( SymCryptGcmValidateParameters( + // SymCryptAesBlockCipher, + // cbNonce, + // cbAuthData, + // cbData, + // cbTag ) == SYMCRYPT_NO_ERROR, "?" ); + + // scError = SymCryptGcmDecrypt( &state.key, + // pbNonce, cbNonce, pbAuthData, cbAuthData, + // pbSrc, pbDst, cbData, + // pbTag, cbTag ); + + OSSL_PARAM params[2] = { + OSSL_PARAM_END, OSSL_PARAM_END + }; + + params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_AEAD_IVLEN, + &cbNonce); + + CHECK(EVP_DecryptInit_ex2(state.decCtx, NULL, NULL, pbNonce, params) == 1, getOpensslError().data()); + CHECK(EVP_DecryptUpdate(state.decCtx, NULL, &outlen, pbAuthData, (int)cbAuthData) == 1, getOpensslError().data()); + CHECK(EVP_DecryptUpdate(state.decCtx, pbDst, &outlen, pbSrc, (int)cbData) == 1, getOpensslError().data()); + params[0] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, + (void *)pbTag, cbTag); + + CHECK(EVP_CIPHER_CTX_set_params(state.decCtx, params) == 1, getOpensslError().data()); + scError = EVP_DecryptFinal_ex(state.decCtx, pbDst, &outlen); + + // Done + goto cleanup; + } + + if( !state.inComputation ) + { + OSSL_PARAM params[2] = { + OSSL_PARAM_END, OSSL_PARAM_END + }; + + params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_AEAD_IVLEN, + &cbNonce); + CHECK(EVP_DecryptInit_ex2(state.decCtx, NULL, NULL, pbNonce, params) == 1, getOpensslError().data()); + CHECK(EVP_DecryptUpdate(state.decCtx, NULL, &outlen, pbAuthData, (int)cbAuthData) == 1, getOpensslError().data()); + state.inComputation = TRUE; + } + CHECK(EVP_DecryptUpdate(state.decCtx, pbDst, &outlen, pbSrc, (int)cbData) == 1, getOpensslError().data()); + + if( pbTag != nullptr ) + { + // OSSL_PARAM params[2] = { + // OSSL_PARAM_END, OSSL_PARAM_END + // }; + + // params[0] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, + // (void *)pbTag, cbTag); + EVP_CIPHER_CTX_ctrl(state.decCtx, EVP_CTRL_AEAD_SET_TAG, + (int)cbTag, (void *)pbTag); + scError = EVP_DecryptFinal_ex(state.decCtx, pbDst, &outlen); + state.inComputation = FALSE; + } + +cleanup: + return scError > 0 ? 0 : STATUS_AUTH_TAG_MISMATCH; +} + +// ModeGcm end + + VOID addOpensslAlgs() { addImplementationToGlobalList>(); - // addImplementationToGlobalList>(); + addImplementationToGlobalList>(); // addImplementationToGlobalList>(); // addImplementationToGlobalList>(); // addImplementationToGlobalList>(); diff --git a/unittest/lib/perfPrint.cpp b/unittest/lib/perfPrint.cpp index e5cbccd..e75dd24 100644 --- a/unittest/lib/perfPrint.cpp +++ b/unittest/lib/perfPrint.cpp @@ -32,6 +32,15 @@ print( const char *format, ...) va_start( vl, format ); + // TODO: We should use CHECK here but CHECK will re-enter this function via fatal() + // so we should fix fatal to use fprintf instead of buffering to Output. + if ( OutputOffset >= MAX_OUTPUT_SIZE ) + { + fputs( "Out of output buffer space.\n", stderr ); + exit(-1); + } + + // TODO: We should also replace compiler dependent VSNPRINTF_S with std::vsnprintf. res = VSNPRINTF_S( &Output[OutputOffset], MAX_OUTPUT_SIZE - OutputOffset, _TRUNCATE, format, vl ); CHECK( res >= 0 , "WHOA!!!" ); @@ -117,6 +126,12 @@ iprint( const char *format, ...) va_start( vl, format ); + if ( OutputOffset >= MAX_OUTPUT_SIZE ) + { + fputs( "Out of output buffer space.\n", stderr ); + exit(-1); + } + res = VSNPRINTF_S( &Output[OutputOffset], MAX_OUTPUT_SIZE - OutputOffset, _TRUNCATE, format, vl ); CHECK( res >= 0 , "WHOA!!!" ); @@ -134,6 +149,12 @@ dprint( const char * format, ... ) va_start( vl, format ); + if ( OutputOffset >= MAX_OUTPUT_SIZE ) + { + fputs( "Out of output buffer space.\n", stderr ); + exit(-1); + } + res = _vsnprintf_s( &Output[OutputOffset], MAX_OUTPUT_SIZE - OutputOffset, _TRUNCATE, format, vl ); CHECK( res >= 0 , "WHOA!!!" ); @@ -164,6 +185,12 @@ vprint(BOOL bPrint, const char *format, ...) { va_start( vl, format ); + if ( OutputOffset >= MAX_OUTPUT_SIZE ) + { + fputs( "Out of output buffer space.\n", stderr ); + exit(-1); + } + res = VSNPRINTF_S( &Output[OutputOffset], MAX_OUTPUT_SIZE - OutputOffset, _TRUNCATE, format, vl ); CHECK( res >= 0 , "WHOA!!!" );