зеркало из https://github.com/microsoft/SymCrypt.git
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
This commit is contained in:
Родитель
476b8382f0
Коммит
7c1f6b4143
|
@ -146,7 +146,8 @@ extends:
|
||||||
cc: 'gcc'
|
cc: 'gcc'
|
||||||
cxx: 'g++'
|
cxx: 'g++'
|
||||||
skipTests: true
|
skipTests: true
|
||||||
additionalArgs: '--no-asm --openssl'
|
additionalArgs: '--no-asm'
|
||||||
|
openssl: true
|
||||||
identifier: 'NoAsm'
|
identifier: 'NoAsm'
|
||||||
- template: .pipelines/templates/build-linux.yml@self
|
- template: .pipelines/templates/build-linux.yml@self
|
||||||
parameters:
|
parameters:
|
||||||
|
@ -155,7 +156,8 @@ extends:
|
||||||
cc: 'clang'
|
cc: 'clang'
|
||||||
cxx: 'clang++'
|
cxx: 'clang++'
|
||||||
skipTests: true
|
skipTests: true
|
||||||
additionalArgs: '--no-asm --openssl'
|
additionalArgs: '--no-asm'
|
||||||
|
openssl: true
|
||||||
identifier: 'NoAsm'
|
identifier: 'NoAsm'
|
||||||
- template: .pipelines/templates/build-linux.yml@self
|
- template: .pipelines/templates/build-linux.yml@self
|
||||||
parameters:
|
parameters:
|
||||||
|
|
|
@ -50,7 +50,7 @@ jobs:
|
||||||
${{ else }}:
|
${{ else }}:
|
||||||
verbose_build_flag: ''
|
verbose_build_flag: ''
|
||||||
${{ if eq(parameters.openssl, true) }}:
|
${{ if eq(parameters.openssl, true) }}:
|
||||||
openssl_build_flag: '--openssl'
|
openssl_build_flag: '--openssl-build-from-source'
|
||||||
${{ else }}:
|
${{ else }}:
|
||||||
openssl_build_flag: ''
|
openssl_build_flag: ''
|
||||||
|
|
||||||
|
@ -86,10 +86,12 @@ jobs:
|
||||||
apt-get install -y gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf qemu-user
|
apt-get install -y gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf qemu-user
|
||||||
displayName: 'Install arm cross-compilation tools'
|
displayName: 'Install arm cross-compilation tools'
|
||||||
|
|
||||||
- ${{ if eq(parameters.openssl, true) }}:
|
# TODO: Once we move to Azure Linux 3 we can use the system-provided OpenSSL package.
|
||||||
- script: |
|
# For now we will built from source since Ubuntu 20.04 doesn't have OpenSSL 3.
|
||||||
apt-get install -y libssl-dev
|
# - ${{ if eq(parameters.openssl, true) }}:
|
||||||
displayName: 'Install OpenSSL'
|
# - script: |
|
||||||
|
# apt-get install -y libssl-dev
|
||||||
|
# displayName: 'Install OpenSSL'
|
||||||
|
|
||||||
- task: PipAuthenticate@1
|
- task: PipAuthenticate@1
|
||||||
inputs:
|
inputs:
|
||||||
|
|
|
@ -4,6 +4,14 @@
|
||||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
|
{
|
||||||
|
"type": "lldb",
|
||||||
|
"request": "launch",
|
||||||
|
"name": "(lldb) symcryptunittest",
|
||||||
|
"program": "${workspaceFolder}/bin/exe/symcryptunittest",
|
||||||
|
"args": [],
|
||||||
|
"cwd": "${workspaceFolder}"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "(Windows) symcryptunittest",
|
"name": "(Windows) symcryptunittest",
|
||||||
"type": "cppvsdbg",
|
"type": "cppvsdbg",
|
||||||
|
@ -17,34 +25,5 @@
|
||||||
"console": "integratedTerminal",
|
"console": "integratedTerminal",
|
||||||
"internalConsoleOptions": "openOnSessionStart"
|
"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",
|
|
||||||
},
|
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -11,5 +11,18 @@
|
||||||
"icon": "terminal-powershell",
|
"icon": "terminal-powershell",
|
||||||
"overrideName": true,
|
"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,
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
|
@ -11,16 +11,20 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"linux": {
|
||||||
|
"options": {
|
||||||
|
"shell": {
|
||||||
|
"executable": "bash",
|
||||||
|
"args": [
|
||||||
|
"-c",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
"tasks": [
|
"tasks": [
|
||||||
{
|
{
|
||||||
"label": "Setup",
|
"label": "Setup",
|
||||||
"type": "shell",
|
"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": {
|
"options": {
|
||||||
"cwd": "${workspaceFolder}/",
|
"cwd": "${workspaceFolder}/",
|
||||||
},
|
},
|
||||||
|
@ -31,14 +35,36 @@
|
||||||
"panel": "shared",
|
"panel": "shared",
|
||||||
"showReuseMessage": true,
|
"showReuseMessage": true,
|
||||||
"clear": false,
|
"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",
|
"label": "Clean",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": [
|
"windows": {
|
||||||
"del -recurse bin_*,bin;",
|
"command": [
|
||||||
],
|
"del -recurse bin_*,bin,.venv;",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"linux": {
|
||||||
|
"command": [
|
||||||
|
"rm -rf bin_* bin .venv"
|
||||||
|
]
|
||||||
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"cwd": "${workspaceFolder}/",
|
"cwd": "${workspaceFolder}/",
|
||||||
},
|
},
|
||||||
|
@ -54,16 +80,25 @@
|
||||||
{
|
{
|
||||||
"label": "Build [Debug]",
|
"label": "Build [Debug]",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "python",
|
"windows": {
|
||||||
"args": [
|
"command": "python",
|
||||||
".\\scripts\\build.py",
|
"args": [
|
||||||
"cmake",
|
".\\scripts\\build.py",
|
||||||
"bin",
|
"cmake",
|
||||||
"--arch",
|
"bin",
|
||||||
"amd64",
|
"--arch",
|
||||||
"--config",
|
"amd64",
|
||||||
"Debug",
|
"--config",
|
||||||
],
|
"Debug",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"linux": {
|
||||||
|
"command": [
|
||||||
|
"[ -f ./.venv/bin/activate ] && . ./.venv/bin/activate;",
|
||||||
|
"python3 ./scripts/build.py cmake bin --arch amd64 --config Debug;",
|
||||||
|
"exit",
|
||||||
|
]
|
||||||
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"cwd": "${workspaceFolder}/",
|
"cwd": "${workspaceFolder}/",
|
||||||
},
|
},
|
||||||
|
|
7
BUILD.md
7
BUILD.md
|
@ -89,6 +89,7 @@ apt update
|
||||||
apt -y install --no-install-recommends \
|
apt -y install --no-install-recommends \
|
||||||
cmake \
|
cmake \
|
||||||
python3-pyelftools \
|
python3-pyelftools \
|
||||||
|
build-essential \
|
||||||
gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf
|
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
|
`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
|
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.
|
And on Linux we can use OpenSSL installed by system's package manager.
|
||||||
|
|
||||||
```
|
```
|
||||||
sudo apt install -y libssl-dev
|
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.
|
To build OpenSSL on Linux we need to install following prerequisites.
|
||||||
|
|
||||||
```
|
```
|
||||||
sudo apt install -y nasm perl
|
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
|
||||||
```
|
```
|
||||||
|
|
|
@ -81,9 +81,6 @@ option(
|
||||||
OFF)
|
OFF)
|
||||||
|
|
||||||
|
|
||||||
if (SYMCRYPT_TEST_WITH_OPENSSL)
|
|
||||||
include(${CMAKE_SOURCE_DIR}/cmake-configs/OpenSSL.cmake)
|
|
||||||
endif()
|
|
||||||
include(${CMAKE_SOURCE_DIR}/cmake-configs/SymCrypt-Platforms.cmake)
|
include(${CMAKE_SOURCE_DIR}/cmake-configs/SymCrypt-Platforms.cmake)
|
||||||
|
|
||||||
if(NOT DEFINED CMAKE_BUILD_TYPE)
|
if(NOT DEFINED CMAKE_BUILD_TYPE)
|
||||||
|
@ -122,4 +119,4 @@ configure_file(build/symcrypt.pc.in symcrypt.pc @ONLY)
|
||||||
|
|
||||||
add_subdirectory(lib)
|
add_subdirectory(lib)
|
||||||
add_subdirectory(modules)
|
add_subdirectory(modules)
|
||||||
add_subdirectory(unittest)
|
add_subdirectory(unittest)
|
||||||
|
|
|
@ -29,12 +29,12 @@ if(OPENSSL_BUILD_FROM_SOURCE)
|
||||||
set(ENV{CL} /MP)
|
set(ENV{CL} /MP)
|
||||||
if(OPENSSL_BUILD_TYPE STREQUAL "release")
|
if(OPENSSL_BUILD_TYPE STREQUAL "release")
|
||||||
execute_process(
|
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}
|
WORKING_DIRECTORY ${OPENSSL_BUILD_ROOT}
|
||||||
RESULT_VARIABLE result)
|
RESULT_VARIABLE result)
|
||||||
else()
|
else()
|
||||||
execute_process(
|
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}
|
WORKING_DIRECTORY ${OPENSSL_BUILD_ROOT}
|
||||||
RESULT_VARIABLE result)
|
RESULT_VARIABLE result)
|
||||||
endif()
|
endif()
|
||||||
|
@ -61,11 +61,11 @@ if(OPENSSL_BUILD_FROM_SOURCE)
|
||||||
|
|
||||||
include(${OPENSSL_BUILD_ROOT}/OpenSSLConfig.cmake)
|
include(${OPENSSL_BUILD_ROOT}/OpenSSLConfig.cmake)
|
||||||
else()
|
else()
|
||||||
find_package(OpenSSL REQUIRED)
|
find_package(OpenSSL 3 REQUIRED)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
message("Found OpenSSL include directory ${OPENSSL_INCLUDE_DIR}")
|
if(OPENSSL_VERSION_MAJOR LESS 3)
|
||||||
include_directories(${OPENSSL_INCLUDE_DIR})
|
message(FATAL_ERROR "-- Invalid OpenSSL version found ${OPENSSL_VERSION} at ${OPENSSL_INCLUDE_DIR}")
|
||||||
link_directories(${OPENSSL_LIBRARY_DIR})
|
else()
|
||||||
link_libraries(${OPENSSL_CRYPTO_LIBRARIES})
|
message("-- Found OpenSSL ${OPENSSL_VERSION} include directory ${OPENSSL_INCLUDE_DIR}")
|
||||||
add_compile_options(-DINCLUDE_IMPL_OPENSSL=1)
|
endif()
|
||||||
|
|
|
@ -79,6 +79,15 @@ if(WIN32 AND SYMCRYPT_TARGET_ARCH MATCHES "X86")
|
||||||
add_link_options(/SAFESEH:NO)
|
add_link_options(/SAFESEH:NO)
|
||||||
endif()
|
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(inc)
|
||||||
include_directories(lib)
|
include_directories(lib)
|
||||||
include_directories(resource)
|
include_directories(resource)
|
||||||
|
|
|
@ -24,5 +24,13 @@ public:
|
||||||
EVP_CIPHER_CTX* decCtx;
|
EVP_CIPHER_CTX* decCtx;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
class AuthEncImpState<ImpOpenssl, AlgAes, ModeGcm> {
|
||||||
|
public:
|
||||||
|
EVP_CIPHER_CTX* encCtx;
|
||||||
|
EVP_CIPHER_CTX* decCtx;
|
||||||
|
BOOLEAN inComputation;
|
||||||
|
};
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
addOpensslAlgs();
|
addOpensslAlgs();
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
#include "precomp.h"
|
#include "precomp.h"
|
||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <openssl/core_names.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
char * ImpOpenssl::name = "OpenSSL";
|
char * ImpOpenssl::name = "OpenSSL";
|
||||||
|
@ -28,6 +30,8 @@ std::string getOpensslError()
|
||||||
|
|
||||||
#define CHECK_OPENSSL_SUCCESS(osslInvocation) CHECK(((osslInvocation) == 1), getOpensslError().data())
|
#define CHECK_OPENSSL_SUCCESS(osslInvocation) CHECK(((osslInvocation) == 1), getOpensslError().data())
|
||||||
|
|
||||||
|
// AlgXtsAes
|
||||||
|
|
||||||
struct ExpandedKeyContext
|
struct ExpandedKeyContext
|
||||||
{
|
{
|
||||||
EVP_CIPHER_CTX* encCtx;
|
EVP_CIPHER_CTX* encCtx;
|
||||||
|
@ -337,11 +341,393 @@ XtsImp<ImpOpenssl, AlgXtsAes>::decryptWith128bTweak(
|
||||||
return STATUS_SUCCESS;
|
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<ImpOpenssl,AlgAes, ModeGcm>( 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<ImpOpenssl,AlgAes, ModeGcm>( 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<ImpOpenssl,AlgAes, ModeGcm>( 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<ImpOpenssl, AlgAes, ModeGcm>::AuthEncImp()
|
||||||
|
{
|
||||||
|
m_perfKeyFunction = &algImpKeyPerfFunction<ImpOpenssl, AlgAes, ModeGcm>;
|
||||||
|
m_perfCleanFunction = &algImpCleanPerfFunction<ImpOpenssl, AlgAes, ModeGcm>;
|
||||||
|
m_perfDataFunction = &algImpDataPerfFunction<ImpOpenssl, AlgAes, ModeGcm>;
|
||||||
|
m_perfDecryptFunction = &algImpDecryptPerfFunction<ImpOpenssl, AlgAes, ModeGcm>;
|
||||||
|
state.encCtx = EVP_CIPHER_CTX_new();
|
||||||
|
state.decCtx = EVP_CIPHER_CTX_new();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
AuthEncImp<ImpOpenssl, AlgAes, ModeGcm>::~AuthEncImp()
|
||||||
|
{
|
||||||
|
EVP_CIPHER_CTX_free(state.encCtx);
|
||||||
|
EVP_CIPHER_CTX_free(state.decCtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
std::set<SIZE_T>
|
||||||
|
AuthEncImp<ImpOpenssl, AlgAes, ModeGcm>::getKeySizes()
|
||||||
|
{
|
||||||
|
std::set<SIZE_T> res;
|
||||||
|
|
||||||
|
res.insert( 16 );
|
||||||
|
res.insert( 24 );
|
||||||
|
res.insert( 32 );
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<>
|
||||||
|
std::set<SIZE_T>
|
||||||
|
AuthEncImp<ImpOpenssl, AlgAes, ModeGcm>::getNonceSizes()
|
||||||
|
{
|
||||||
|
std::set<SIZE_T> res;
|
||||||
|
|
||||||
|
for(int i = 1; i <= 256; ++i)
|
||||||
|
{
|
||||||
|
res.insert( i );
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<>
|
||||||
|
std::set<SIZE_T>
|
||||||
|
AuthEncImp<ImpOpenssl, AlgAes, ModeGcm>::getTagSizes()
|
||||||
|
{
|
||||||
|
std::set<SIZE_T> res;
|
||||||
|
|
||||||
|
for( int i=12; i<=16; i ++ )
|
||||||
|
{
|
||||||
|
res.insert( i );
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
NTSTATUS
|
||||||
|
AuthEncImp<ImpOpenssl, AlgAes, ModeGcm>::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<ImpOpenssl, AlgAes, ModeGcm>::setTotalCbData( SIZE_T )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
NTSTATUS
|
||||||
|
AuthEncImp<ImpOpenssl, AlgAes, ModeGcm>::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<ImpOpenssl, AlgAes, ModeGcm>::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
|
VOID
|
||||||
addOpensslAlgs()
|
addOpensslAlgs()
|
||||||
{
|
{
|
||||||
addImplementationToGlobalList<XtsImp<ImpOpenssl, AlgXtsAes>>();
|
addImplementationToGlobalList<XtsImp<ImpOpenssl, AlgXtsAes>>();
|
||||||
// addImplementationToGlobalList<AuthEncImp<ImpOpenssl, AlgAes, ModeGcm>>();
|
addImplementationToGlobalList<AuthEncImp<ImpOpenssl, AlgAes, ModeGcm>>();
|
||||||
// addImplementationToGlobalList<RsaSignImp<ImpOpenssl, AlgRsaSignPss>>();
|
// addImplementationToGlobalList<RsaSignImp<ImpOpenssl, AlgRsaSignPss>>();
|
||||||
// addImplementationToGlobalList<HashImp<ImpOpenssl, AlgSha256>>();
|
// addImplementationToGlobalList<HashImp<ImpOpenssl, AlgSha256>>();
|
||||||
// addImplementationToGlobalList<HashImp<ImpOpenssl, AlgSha384>>();
|
// addImplementationToGlobalList<HashImp<ImpOpenssl, AlgSha384>>();
|
||||||
|
|
|
@ -32,6 +32,15 @@ print( const char *format, ...)
|
||||||
|
|
||||||
va_start( vl, 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 );
|
res = VSNPRINTF_S( &Output[OutputOffset], MAX_OUTPUT_SIZE - OutputOffset, _TRUNCATE, format, vl );
|
||||||
|
|
||||||
CHECK( res >= 0 , "WHOA!!!" );
|
CHECK( res >= 0 , "WHOA!!!" );
|
||||||
|
@ -117,6 +126,12 @@ iprint( const char *format, ...)
|
||||||
|
|
||||||
va_start( vl, 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 );
|
res = VSNPRINTF_S( &Output[OutputOffset], MAX_OUTPUT_SIZE - OutputOffset, _TRUNCATE, format, vl );
|
||||||
|
|
||||||
CHECK( res >= 0 , "WHOA!!!" );
|
CHECK( res >= 0 , "WHOA!!!" );
|
||||||
|
@ -134,6 +149,12 @@ dprint( const char * format, ... )
|
||||||
|
|
||||||
va_start( vl, 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 );
|
res = _vsnprintf_s( &Output[OutputOffset], MAX_OUTPUT_SIZE - OutputOffset, _TRUNCATE, format, vl );
|
||||||
|
|
||||||
CHECK( res >= 0 , "WHOA!!!" );
|
CHECK( res >= 0 , "WHOA!!!" );
|
||||||
|
@ -164,6 +185,12 @@ vprint(BOOL bPrint, const char *format, ...)
|
||||||
{
|
{
|
||||||
va_start( vl, 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 );
|
res = VSNPRINTF_S( &Output[OutputOffset], MAX_OUTPUT_SIZE - OutputOffset, _TRUNCATE, format, vl );
|
||||||
|
|
||||||
CHECK( res >= 0 , "WHOA!!!" );
|
CHECK( res >= 0 , "WHOA!!!" );
|
||||||
|
|
Загрузка…
Ссылка в новой задаче