Merged PR 5935572: Create SymCrypt shared object module with integrity verification

This change adds a new SymCrypt shared object module for Linux. The shared object module implements integrity verification for FIPS compliance by reading its own memory at runtime, reversing any relocations, calculating the HMAC-SHA256 digest of the module contents in memory, and comparing the digest to a known-good value which is injected into the module (outside the FIPS boundary) post compilation by a Python script.

Related work items: #30397153, #30397542, #30397643, #30397707, #30397781, #32407416
This commit is contained in:
Mitch Lindgren 🦎 2021-04-30 19:52:39 +00:00
Родитель a667baeaa5
Коммит 5b1cfe0171
37 изменённых файлов: 4581 добавлений и 115 удалений

1
.gitignore поставляемый
Просмотреть файл

@ -29,6 +29,7 @@ x64/*
*.pdb
*.aps
*.a
*.bin
# Generated files
inc/*.dat.h

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

@ -24,7 +24,7 @@ message(STATUS "Target: ${CMAKE_SYSTEM_NAME} ${CMAKE_SYSTEM_PROCESSOR} ${SYMCRYP
# Set output directories binaries
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib/${CMAKE_SYSTEM_PROCESSOR}/${SYMCRYPT_TARGET_ENV})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib/${CMAKE_SYSTEM_PROCESSOR}/${SYMCRYPT_TARGET_ENV})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/module/${CMAKE_SYSTEM_PROCESSOR}/${SYMCRYPT_TARGET_ENV})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/exe/${CMAKE_SYSTEM_PROCESSOR}/${SYMCRYPT_TARGET_ENV})
if(WIN32 AND SYMCRYPT_TARGET_ENV MATCHES "WindowsUserMode")
@ -57,6 +57,8 @@ elseif(NOT WIN32)
add_compile_options(-g)
add_compile_options(-Wno-multichar)
add_compile_options(-fPIC)
add_compile_options(-fno-stack-protector)
add_compile_options(-fno-plt)
# GCC and clang unroll more aggressively than they should for best performance
# When we want to unroll loops, we unroll in the source code, so tell the compiler not to unroll
@ -77,4 +79,9 @@ include_directories(${CMAKE_BINARY_DIR}/inc)
include(build/buildInfo.cmake)
add_subdirectory(lib)
if(NOT WIN32)
add_subdirectory(module)
endif()
add_subdirectory(unittest)

25
NOTICE Normal file
Просмотреть файл

@ -0,0 +1,25 @@
SymCrypt on Linux uses elfdefinitions.h from FreeBSD. See the following license notice:
Copyright (c) 2010 Joseph Koshy
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.

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

@ -22,6 +22,7 @@ jobs:
steps:
- checkout: self # self represents the repo where the initial Pipelines YAML file was found
submodules: recursive
- task: ComponentGovernanceComponentDetection@0
# Initialize CMake
# cd bin; cmake .. -DCMAKE_TOOLCHAIN_FILE=../cmake-toolchain/windows-amd64.cmake
- task: CMake@1
@ -33,13 +34,12 @@ jobs:
- task: CMake@1
inputs:
workingDirectory: '$(Build.SourcesDirectory)/bin'
cmakeArgs: '--build .'
cmakeArgs: '--build . -j 8'
# Execute unit tests using the inline script
- script: |
cd bin\exe\AMD64\WindowsUserMode\Debug
.\symcryptunittest.exe
displayName: 'Execute generic unit test'
name: 'WindowsGenericUnitTest'
displayName: 'Execute unit test'
# Copy build output files to artifact staging directory
- task: CopyFiles@2
inputs:
@ -66,12 +66,11 @@ jobs:
- task: CMake@1
inputs:
workingDirectory: '$(Build.SourcesDirectory)/bin'
cmakeArgs: '--build .'
cmakeArgs: '--build . -j 8'
- script: |
cd bin\exe\x86\WindowsUserMode\Debug
.\symcryptunittest.exe
displayName: 'Execute generic unit test'
name: 'WindowsGenericUnitTest'
displayName: 'Execute unit test'
- task: CopyFiles@2
inputs:
SourceFolder: 'bin'
@ -89,14 +88,23 @@ jobs:
steps:
- checkout: self
submodules: recursive
- task: ComponentGovernanceComponentDetection@0
- script: |
python -m pip install --upgrade pip setuptools wheel
pip install -r $(Build.SourcesDirectory)/scripts/requirements.txt
displayName: 'Install Python requirements'
- task: CMake@1
inputs:
workingDirectory: '$(Build.SourcesDirectory)/bin'
cmakeArgs: '.. -DCMAKE_TOOLCHAIN_FILE=cmake-toolchain/linux-amd64.cmake -DCMAKE_C_COMPILER=gcc'
cmakeArgs: '.. -DCMAKE_TOOLCHAIN_FILE=cmake-toolchain/linux-amd64.cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++'
- task: CMake@1
inputs:
workingDirectory: '$(Build.SourcesDirectory)/bin'
cmakeArgs: '--build .'
cmakeArgs: '--build . -j 8'
- script: |
cd bin/exe/AMD64/Linux
./symcryptmoduletest
displayName: 'Execute module test'
- script: |
cd bin/exe/AMD64/Linux
./symcryptunittest
@ -119,19 +127,26 @@ jobs:
steps:
- checkout: self
submodules: recursive
- script: |
python -m pip install --upgrade pip setuptools wheel
pip install -r $(Build.SourcesDirectory)/scripts/requirements.txt
displayName: 'Install Python requirements'
- task: CMake@1
inputs:
workingDirectory: '$(Build.SourcesDirectory)/bin'
cmakeArgs: '.. -DCMAKE_TOOLCHAIN_FILE=cmake-toolchain/linux-amd64.cmake -DCMAKE_C_COMPILER=clang'
cmakeArgs: '.. -DCMAKE_TOOLCHAIN_FILE=cmake-toolchain/linux-amd64.cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++'
- task: CMake@1
inputs:
workingDirectory: '$(Build.SourcesDirectory)/bin'
cmakeArgs: '--build .'
cmakeArgs: '--build . -j 8'
- script: |
cd bin/exe/AMD64/Linux
./symcryptmoduletest
displayName: 'Execute module test'
- script: |
cd bin/exe/AMD64/Linux
./symcryptunittest
displayName: 'Execute generic unit test'
name: 'LinuxGenericUnitTest'
displayName: 'Execute unit test'
- task: CopyFiles@2
inputs:
SourceFolder: 'bin'

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

@ -4,5 +4,5 @@
#define _SYMCRYPT_EXPAND_JOIN(a, b) _SYMCRYPT_JOIN(a, b)
#define SYMCRYPT_BUILD_INFO_BRANCH "@SYMCRYPT_BUILD_INFO_BRANCH@"
#define SYMCRYPT_BUILD_INFO_COMMIT "@SYMCRYPT_BUILD_INFO_COMMIT@"
#define SYMCRYPT_BUILD_INFO_VERSION _SYMCRYPT_EXPAND_JOIN(SYMCRYPT_CODE_VERSION_API, SYMCRYPT_CODE_VERSION_MINOR)
#define SYMCRYPT_BUILD_INFO_VERSION _SYMCRYPT_EXPAND_JOIN(_SYMCRYPT_EXPAND_JOIN(SYMCRYPT_CODE_VERSION_API, SYMCRYPT_CODE_VERSION_MINOR), SYMCRYPT_CODE_VERSION_PATCH)
#define SYMCRYPT_BUILD_INFO_TIMESTAMP "@SYMCRYPT_BUILD_INFO_TIMESTAMP@"

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

@ -465,7 +465,7 @@ SymCryptUint64Bytesize( UINT64 value );
//
// SYMCRYPT_ENVIRONMENT_WINDOWS_BOOTLIBRARY // only for the current OS release
//
// SYMCRYPT_ENVIRONMENT_WINDWOS_KERNELMODE_LEGACY // Use for any version of Windows.
// SYMCRYPT_ENVIRONMENT_WINDOWS_KERNELMODE_LEGACY // Use for any version of Windows.
// SYMCRYPT_ENVIRONMENT_WINDOWS_KERNELMODE_WIN7_N_LATER // Only for Win7 and later
// SYMCRYPT_ENVIRONMENT_WINDOWS_KERNELMODE_WIN8_1_N_LATER // Only for WinBlue and later
// SYMCRYPT_ENVIRONMENT_WINDOWS_KERNELMODE_LATEST // use for latest OS
@ -477,6 +477,8 @@ SymCryptUint64Bytesize( UINT64 value );
//
// SYMCRYPT_ENVIRONMENT_WINDOWS_KERNELDEBUGGER
//
// SYMCRYPT_ENVIRONMENT_LINUX_USERMODE // use for Linux
//
// SYMCRYPT_ENVIRONMENT_GENERIC // use for all other situations
//
@ -484,8 +486,9 @@ VOID
SYMCRYPT_CALL
SymCryptInit();
//
// Initialize the library.
// Initialize the static library.
// This function MUST be called before any other function in the library.
// It is not necessary to call this function when using the shared object library.
//
// This function does not perform the self tests in the library.
// Doing so would force the linking of all the algorithm in the library,
@ -501,7 +504,20 @@ SymCryptInit();
// to invoke one of the environment macros documented above.
//
VOID
SYMCRYPT_CALL
SymCryptModuleInit(
_In_ UINT32 api,
_In_ UINT32 minor,
_In_ UINT32 patch);
#define SYMCRYPT_MODULE_INIT() SymCryptModuleInit(SYMCRYPT_CODE_VERSION_API, SYMCRYPT_CODE_VERSION_MINOR, SYMCRYPT_CODE_VERSION_PATCH);
//
// Initialize the SymCrypt shared object module/dynamic-link library. This function verifies
// that the module version supports the version requested by the application. If the version
// is unsupported, a fatal error will occur. The macro SYMCRYPT_MODULE_INIT can be used
// to call SymCryptModuleInit with the correct arguments.
//
//==========================================================================
// DATA MANIPULATION
@ -4258,6 +4274,7 @@ SymCryptCallbackFree( VOID * pMem );
_Success_(return == SYMCRYPT_NO_ERROR)
SYMCRYPT_ERROR
SYMCRYPT_CALL
SYMCRYPT_WEAK_SYMBOL
SymCryptCallbackRandom(
_Out_writes_bytes_( cbBuffer ) PBYTE pbBuffer,
SIZE_T cbBuffer );

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

@ -300,13 +300,20 @@ C_ASSERT( (SYMCRYPT_ALIGN_VALUE & (SYMCRYPT_ALIGN_VALUE - 1 )) == 0 );
#define SYMCRYPT_ALIGN_UP( _p ) ((PBYTE) ( ((UINT_PTR) (_p) + SYMCRYPT_ALIGN_VALUE - 1) & ~(SYMCRYPT_ALIGN_VALUE - 1 ) ) )
#if SYMCRYPT_MS_VC
#define SYMCRYPT_ALIGN __declspec(align(SYMCRYPT_ALIGN_VALUE))
#define SYMCRYPT_ALIGN_STRUCT SYMCRYPT_ALIGN struct
#define SYMCRYPT_ALIGN_AT(x) __declspec(align(x))
#define SYMCRYPT_ALIGN __declspec(align(SYMCRYPT_ALIGN_VALUE))
#define SYMCRYPT_ALIGN_STRUCT SYMCRYPT_ALIGN struct
#define SYMCRYPT_ALIGN_AT(x) __declspec(align(x))
#define SYMCRYPT_WEAK_SYMBOL
#elif SYMCRYPT_GNUC
#define SYMCRYPT_ALIGN __attribute__((aligned(SYMCRYPT_ALIGN_VALUE)))
#define SYMCRYPT_ALIGN_STRUCT struct SYMCRYPT_ALIGN
#define SYMCRYPT_ALIGN_AT(x) __attribute__((aligned(x)))
#define SYMCRYPT_WEAK_SYMBOL __attribute__((weak))
#else
#define SYMCRYPT_ALIGN __attribute__((aligned(SYMCRYPT_ALIGN_VALUE)))
#define SYMCRYPT_ALIGN_STRUCT struct SYMCRYPT_ALIGN
#define SYMCRYPT_ALIGN_AT(x) __attribute__((aligned(x)))
#define SYMCRYPT_ALIGN
#define SYMCRYPT_ALIGN_STRUCT
#define SYMCRYPT_ALIGN_AT(x)
#define SYMCRYPT_WEAK_SYMBOL
#endif
@ -2498,6 +2505,8 @@ SYMCRYPT_EXTERN_C_END
#define SYMCRYPT_ENVIRONMENT_WINDOWS_USERMODE_LATEST SYMCRYPT_ENVIRONMENT_WINDOWS_USERMODE_WIN8_1_N_LATER
#define SYMCRYPT_ENVIRONMENT_LINUX_USERMODE SYMCRYPT_ENVIRONMENT_DEFS( LinuxUsermode )
//////////////////////////////////////////////////////////
//
// SymCryptWipe & SymCryptWipeKnownSize

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

@ -32,6 +32,7 @@
SYMCRYPT_CODE_VERSION_API EQU 100
SYMCRYPT_CODE_VERSION_MINOR EQU 16
SYMCRYPT_CODE_VERSION_PATCH EQU 0
if 0 ; Start an area that the assembler ignores
@ -39,6 +40,7 @@ SYMCRYPT_CODE_VERSION_MINOR EQU 16
#define SYMCRYPT_CODE_VERSION_API 100
#define SYMCRYPT_CODE_VERSION_MINOR 16
#define SYMCRYPT_CODE_VERSION_PATCH 0
;/* ; Switch back into a C comment so that we can close the IF
endif

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

@ -1,99 +1,98 @@
set(SOURCES_COMMON
blockciphermodes.c
hash.c
parhash.c
ccm.c
ghash.c
gcm.c
aes-default.c
aes-default-bc.c
aes-key.c
aes-c.c
3des.c
a_dispatch.c
aes-asm.c
aes-xmm.c
aes-ymm.c
aes-c.c
aes-default-bc.c
aes-default.c
aes-key.c
aes-neon.c
aes-selftest.c
AesTables.c
aes-xmm.c
aes-ymm.c
aescmac.c
xtsaes.c
3des.c
aesCtrDrbg.c
AesTables.c
blockciphermodes.c
ccm.c
chacha20_poly1305.c
chacha20.c
cpuid_notry.c
cpuid_um.c
cpuid.c
crt.c
DesTables.c
desx.c
rc2.c
rc4.c
sha1.c
sha256.c
sha512.c
md5.c
md4.c
md2.c
dh.c
dl_internal_groups.c
dlgroup.c
dlkey.c
dsa.c
ec_dh.c
ec_dispatch.c
ec_dsa.c
ec_internal_curves.c
ec_montgomery.c
ec_mul.c
ec_short_weierstrass.c
ec_twisted_edwards.c
eckey.c
ecpoint.c
ecurve.c
equal.c
FatalIntercept.c
fdef_general.c
fdef_int.c
fdef_mod.c
fdef369_mod.c
gcm.c
gen_int.c
ghash.c
hash.c
hkdf_selftest.c
hkdf.c
hmacmd5.c
hmacsha1.c
hmacsha256.c
hmacsha384.c
hmacsha512.c
tlsCbcVerify.c
aesCtrDrbg.c
libmain.c
equal.c
FatalIntercept.c
selftest.c
rdrand.c
rdseed.c
sha256Par.c
sha256Par-ymm.c
sha512Par.c
sha512Par-ymm.c
marvin32.c
cpuid.c
cpuid_um.c
cpuid_notry.c
pbkdf2.c
md2.c
md4.c
md5.c
modexp.c
parhash.c
pbkdf2_hmacsha1.c
pbkdf2_hmacsha256.c
sp800_108.c
sp800_108_hmacsha1.c
sp800_108_hmacsha256.c
tlsprf.c
tlsprf_selftest.c
hkdf.c
hkdf_selftest.c
chacha20.c
pbkdf2.c
poly1305.c
chacha20_poly1305.c
a_dispatch.c
fdef_general.c
fdef_int.c
fdef_mod.c
fdef369_mod.c
ecpoint.c
ecurve.c
eckey.c
ec_dispatch.c
ec_short_weierstrass.c
ec_internal_curves.c
ec_dsa.c
ec_dh.c
ec_montgomery.c
ec_twisted_edwards.c
ec_mul.c
ScsTable.c
scsTools.c
primes.c
modexp.c
gen_int.c
crt.c
rsakey.c
rc2.c
rc4.c
rdrand.c
rdseed.c
recoding.c
rsa_enc.c
rsa_padding.c
dlgroup.c
dlkey.c
dsa.c
dh.c
dl_internal_groups.c
recoding.c
IEEE802_11SaeCustom.c
rsakey.c
ScsTable.c
scsTools.c
selftest.c
sha1.c
sha256.c
sha256Par.c
sha256Par-ymm.c
sha512.c
sha512Par.c
sha512Par-ymm.c
sp800_108_hmacsha1.c
sp800_108_hmacsha256.c
sp800_108.c
tlsCbcVerify.c
tlsprf_selftest.c
tlsprf.c
xtsaes.c
)
function(process_cppasm filepath outformat archdefine)
@ -176,7 +175,9 @@ function(process_symcryptasm filepath outformat archdefine)
process_cppasm(${output_cppasm} ${outformat} ${archdefine})
endfunction()
if(NOT WIN32)
if(WIN32)
list(APPEND SOURCES_COMMON IEEE802_11SaeCustom.c)
else()
list(APPEND SOURCES_COMMON linux/intrinsics.c)
endif()
@ -284,11 +285,14 @@ if(WIN32)
target_link_libraries(symcrypt_windows10sgx symcrypt_common)
endif()
set(SOURCES_GENERIC ${SOURCES_COMMON})
list(APPEND SOURCES_GENERIC env_generic.c)
if(NOT WIN32)
add_compile_options(-Wno-trigraphs)
add_library(symcrypt_linuxusermode STATIC env_linuxUserMode.c)
set_target_properties(symcrypt_linuxusermode PROPERTIES PREFIX "")
target_link_libraries(symcrypt_linuxusermode symcrypt_common)
endif()
add_library(symcrypt_generic STATIC env_generic.c)
set_target_properties(symcrypt_generic PROPERTIES PREFIX "")
target_link_libraries(symcrypt_generic symcrypt_common)

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

@ -55,7 +55,7 @@ const UINT32 g_SymCryptModFnsMask = sizeof( g_SymCryptModFns ) - sizeof( g_SymCr
//
// Tweaking the selection & function tables allows different tradeoffs of performance vs codesize
//
SYMCRYPT_MODULUS_TYPE_SELECTION_ENTRY SymCryptModulusTypeSelections[] =
const SYMCRYPT_MODULUS_TYPE_SELECTION_ENTRY SymCryptModulusTypeSelections[] =
{
#if SYMCRYPT_CPU_AMD64
// Mulx used for 257-512 and 577-... bits

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

@ -287,7 +287,7 @@ SymCryptRngAesGenerateBlocks(
SymCryptAesEncrypt( pAesKey, Vcopy, buf );
if( memcmp( buf, pbCheck, 16 ) != 0 )
{
SymCryptFatal( '????' );
SymCryptFatal( 'OLD?' );
}
pbCheck += SYMCRYPT_AES_BLOCK_SIZE;
cbCheck -= SYMCRYPT_AES_BLOCK_SIZE;

142
lib/env_linuxUserMode.c Normal file
Просмотреть файл

@ -0,0 +1,142 @@
//
// env_linuxUserMode.c
// Platform-specific code for linux user mode.
//
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
//
#include "precomp.h"
SYMCRYPT_CPU_FEATURES SYMCRYPT_CALL SymCryptCpuFeaturesNeverPresentEnvLinuxUsermode()
{
return 0;
}
VOID
SYMCRYPT_CALL
SymCryptInitEnvLinuxUsermode( UINT32 version )
{
if( g_SymCryptFlags & SYMCRYPT_FLAG_LIB_INITIALIZED )
{
return;
}
#if SYMCRYPT_CPU_X86 | SYMCRYPT_CPU_AMD64
SymCryptDetectCpuFeaturesByCpuid( SYMCRYPT_CPUID_DETECT_FLAG_CHECK_OS_SUPPORT_FOR_YMM );
//
// Don't use Ymm registers if the OS doesn't report them as available.
// We assume Ymm register swapping isn't supported unless we can verify that it is.
//
g_SymCryptCpuFeaturesNotPresent |= SYMCRYPT_CPU_FEATURE_AVX2;
#if SYMCRYPT_MS_VC
if( (GetEnabledXStateFeatures() & XSTATE_MASK_AVX) != 0 )
{
g_SymCryptCpuFeaturesNotPresent &= ~SYMCRYPT_CPU_FEATURE_AVX2;
}
#endif
//
// Our SaveXmm function never fails because it doesn't have to do anything in User mode.
//
g_SymCryptCpuFeaturesNotPresent &= ~SYMCRYPT_CPU_FEATURE_SAVEXMM_NOFAIL;
#elif SYMCRYPT_CPU_ARM
g_SymCryptCpuFeaturesNotPresent = (SYMCRYPT_CPU_FEATURES) ~SYMCRYPT_CPU_FEATURE_NEON;
#elif SYMCRYPT_CPU_ARM64
SymCryptDetectCpuFeaturesFromIsProcessorFeaturePresent();
#endif
SymCryptInitEnvCommon( version );
}
_Analysis_noreturn_
VOID
SYMCRYPT_CALL
SymCryptFatalEnvLinuxUsermode( ULONG fatalCode )
{
UINT32 fatalCodeVar;
SymCryptFatalIntercept( fatalCode );
//
// Put the fatal code in a location where it shows up in the dump
//
SYMCRYPT_FORCE_WRITE32( &fatalCodeVar, fatalCode );
//
// Our first preference is to fastfail,
// the second to create an AV, which can trigger a core dump so that we get to
// see what is going wrong.
//
__fastfail( FAST_FAIL_CRYPTO_LIBRARY );
//
// Next we write to the NULL pointer, this causes an AV
//
SYMCRYPT_FORCE_WRITE32( (volatile UINT32 *)NULL, fatalCode );
SymCryptFatalHang( fatalCode );
}
#if SYMCRYPT_CPU_AMD64
SYMCRYPT_ERROR
SYMCRYPT_CALL
SymCryptSaveXmmEnvLinuxUsermode( _Out_ PSYMCRYPT_EXTENDED_SAVE_DATA pSaveData )
{
UNREFERENCED_PARAMETER( pSaveData );
return SYMCRYPT_NO_ERROR;
}
VOID
SYMCRYPT_CALL
SymCryptRestoreXmmEnvLinuxUsermode( _Inout_ PSYMCRYPT_EXTENDED_SAVE_DATA pSaveData )
{
UNREFERENCED_PARAMETER( pSaveData );
}
SYMCRYPT_ERROR
SYMCRYPT_CALL
SymCryptSaveYmmEnvLinuxUsermode( _Out_ PSYMCRYPT_EXTENDED_SAVE_DATA pSaveData )
{
UNREFERENCED_PARAMETER( pSaveData );
return SYMCRYPT_NO_ERROR;
}
VOID
SYMCRYPT_CALL
SymCryptRestoreYmmEnvLinuxUsermode( _Inout_ PSYMCRYPT_EXTENDED_SAVE_DATA pSaveData )
{
UNREFERENCED_PARAMETER( pSaveData );
}
VOID
SYMCRYPT_CALL
SymCryptCpuidExFuncEnvLinuxUsermode( int cpuInfo[4], int function_id, int subfunction_id )
{
__cpuidex( cpuInfo, function_id, subfunction_id );
}
#endif
VOID
SYMCRYPT_CALL
SymCryptTestInjectErrorEnvLinuxUsermode( PBYTE pbBuf, SIZE_T cbBuf )
{
//
// This feature is only used during testing. In production it is always
// an empty function that the compiler can optimize away.
//
UNREFERENCED_PARAMETER( pbBuf );
UNREFERENCED_PARAMETER( cbBuf );
}

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

@ -23,7 +23,7 @@
#elif SYMCRYPT_CPU_ARM64
#define SYMCRYPT_FDEF369_DIGITS_TO_NUINT32( nD ) ((nD) * 6)
#else
#??
#error ??
#endif
VOID

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

@ -277,7 +277,7 @@ SymCryptFdefDecideModulusType( PCSYMCRYPT_INT piSrc, UINT32 nDigits, UINT32 aver
{
UINT32 res = 0;
BOOLEAN disableMontgomery = 0;
PSYMCRYPT_MODULUS_TYPE_SELECTION_ENTRY pEntry;
PCSYMCRYPT_MODULUS_TYPE_SELECTION_ENTRY pEntry;
UINT32 nBitsizeOfValue = SymCryptIntBitsizeOfValue( piSrc );
UINT32 modulusFeatures = 0;

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

@ -32,9 +32,9 @@ SymCryptLibraryWasNotInitialized()
#endif
const CHAR * SymCryptBuildString =
"v" SYMCRYPT_BUILD_INFO_VERSION
"_" SYMCRYPT_BUILD_INFO_BRANCH
const CHAR * const SymCryptBuildString =
"v" SYMCRYPT_BUILD_INFO_VERSION
"_" SYMCRYPT_BUILD_INFO_BRANCH
"_" SYMCRYPT_BUILD_INFO_COMMIT
"_" SYMCRYPT_BUILD_INFO_TIMESTAMP;

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

@ -1628,8 +1628,9 @@ typedef struct _SYMCRYPT_MODULUS_TYPE_SELECTION_ENTRY
UINT32 maxBits; // Max # bits that the actual value of the modulus is, 0 = no limit
UINT32 modulusFeatures; // Required features of the modulus
} SYMCRYPT_MODULUS_TYPE_SELECTION_ENTRY, *PSYMCRYPT_MODULUS_TYPE_SELECTION_ENTRY;
typedef const SYMCRYPT_MODULUS_TYPE_SELECTION_ENTRY* PCSYMCRYPT_MODULUS_TYPE_SELECTION_ENTRY;
extern SYMCRYPT_MODULUS_TYPE_SELECTION_ENTRY SymCryptModulusTypeSelections[]; // Array can be any size...
extern const SYMCRYPT_MODULUS_TYPE_SELECTION_ENTRY SymCryptModulusTypeSelections[]; // Array can be any size...
// Check that the size is a power of 2

2
module/CMakeLists.txt Normal file
Просмотреть файл

@ -0,0 +1,2 @@
add_subdirectory(linux_common) # Common functionality for Linux modules
add_subdirectory(oe_full) # OpenEnclave with all functionality

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

@ -0,0 +1,6 @@
set(SOURCES
integrity.c)
include_directories(${CMAKE_SOURCE_DIR}/inc)
add_library(symcrypt_module_linux_common STATIC ${SOURCES})

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

@ -0,0 +1,15 @@
{
"Registrations": [
{
"Component": {
"Type": "Other",
"Other": {
"Name": "elfdefinitions.h",
"Version": "3769",
"DownloadUrl": "https://cgit.freebsd.org/src/plain/contrib/elftoolchain/common/elfdefinitions.h"
}
},
"DevelopmentDependency": false
}
]
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -0,0 +1,270 @@
//
// integrity.c
// FIPS 140-3 integrity verification implementation for ELF binaries
//
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
//
#include "precomp.h"
#define SYMCRYPT_FIPS_ASSERT(x) { if(!(x)){ SymCryptFatal('FIPS'); } }
#define PLACEHOLDER_VALUE 0x8BADF00D
#define PLACEHOLDER_ARRAY \
{\
0x5B, 0x75, 0xBB, 0xE4, 0x9E, 0x18, 0x03, 0x55,\
0x08, 0x4E, 0x3F, 0xE7, 0x60, 0x7E, 0x4F, 0x08,\
0xAA, 0x77, 0x0F, 0x0B, 0xAB, 0xC6, 0x58, 0x5A,\
0xA9, 0x9F, 0x83, 0x4B, 0xD0, 0x6E, 0x67, 0x05\
}
// The following variables use placeholder values which will be modified after compile time by our
// helper script. They need to be statically initialized to non-zero values so they are put in the
// .data segment rather than the .bss segment, as the latter's representation in the module on disk
// is not necessarily the same size as the values in memory at runtime.
//
// Because these values are modified after compile time, the scalar values must be read using
// SYMCRYPT_FORCE_READ64 or the compiler may inline the placeholder values, leading to incorrect
// results at runtime.
const Elf64_Addr SymCryptVolatileFipsHmacKeyRva = (Elf64_Addr) PLACEHOLDER_VALUE;
const Elf64_Off SymCryptVolatileFipsBoundaryOffset = PLACEHOLDER_VALUE;
const unsigned char SymCryptVolatileFipsHmacKey[32] = PLACEHOLDER_ARRAY;
unsigned char SymCryptVolatileFipsHmacDigest[SYMCRYPT_HMAC_SHA256_RESULT_SIZE] = PLACEHOLDER_ARRAY;
void SymCryptModuleUndoRelocation(
_In_ const Elf64_Addr module_base,
_Inout_ Elf64_Xword* const target,
_In_ const Elf64_Rela* rela )
{
Elf64_Xword replacement = 0;
switch( ELF64_R_TYPE( rela->r_info ) )
{
case R_X86_64_RELATIVE:
replacement = *target - (Elf64_Off) module_base;
break;
case R_X86_64_64:
case R_X86_64_GLOB_DAT:
replacement = 0;
break;
case R_X86_64_JUMP_SLOT:
default:
// We cannot handle other relocation types
SYMCRYPT_FIPS_ASSERT( FALSE );
break;
}
*target = replacement;
}
void SymCryptModuleFindRelocationInfo(
_In_ const Elf64_Dyn* const dynStart,
_Out_ Elf64_Rela** relaStart,
_Out_ size_t* relaEntryCount )
{
size_t relaTotalSize = 0;
size_t relaEntrySize = 0;
for( const Elf64_Dyn* dyn = dynStart; dyn->d_tag != DT_NULL; ++dyn )
{
switch( dyn->d_tag )
{
case DT_RELA:
*relaStart = (Elf64_Rela*) dyn->d_un.d_ptr;
break;
case DT_RELASZ:
relaTotalSize = dyn->d_un.d_val;
break;
case DT_RELAENT:
relaEntrySize = dyn->d_un.d_val;
break;
case DT_JMPREL:
case DT_PLTRELSZ:
// We cannot handle PLT relocations
SYMCRYPT_FIPS_ASSERT( FALSE );
break;
default:
break;
}
}
SYMCRYPT_FIPS_ASSERT( relaStart != NULL );
SYMCRYPT_FIPS_ASSERT( relaEntrySize == sizeof( Elf64_Rela ) );
SYMCRYPT_FIPS_ASSERT( relaTotalSize != 0 && relaTotalSize % relaEntrySize == 0 );
*relaEntryCount = relaTotalSize / relaEntrySize;
}
size_t SymCryptModuleProcessSectionWithRelocations(
_In_ const Elf64_Addr module_base,
_In_ const Elf64_Phdr* const programHeader,
_In_ const Elf64_Dyn* const dynStart,
_In_ const Elf64_Rela* const relaStart,
_In_ const size_t relaEntryCount,
_Inout_ SYMCRYPT_HMAC_SHA256_STATE* hmacState )
{
// The segment that contains relocations consists of the following sections, in this order:
// .data.rel.ro .dynamic .got .data .bss
//
// .data.rel.ro, .dynamic and .got contain relocations, but are not modified by the code itself
// once the dynamic linker has performed the relocations, so these sections are included in our
// HMAC calculation.
//
// .data includes non-constant global variables which can change at runtime. We cannot reverse
// these values without tightly coupling this integrity verification implementation to internal
// implementation details of SymCrypt, so it is not included in our HMAC. The .bss section in
// the module on disk is usually a different size than at runtime, so we cannot include it in
// our HMAC either.
//
// FipsBoundaryOffset marks the start of the .data section, so we read from the start of the
// segment up to that offset.
size_t hashableSectionSize = SYMCRYPT_FORCE_READ64( &SymCryptVolatileFipsBoundaryOffset ) - programHeader->p_offset;
Elf64_Addr segmentStart = module_base + programHeader->p_vaddr;
BYTE* segmentCopy = SymCryptCallbackAlloc( hashableSectionSize );
SYMCRYPT_FIPS_ASSERT( segmentCopy != NULL );
memcpy( segmentCopy, (const unsigned char*) segmentStart, hashableSectionSize );
// Some of the entries in the .dynamic section get relocated, but those relocations are not
// included in the list of relocations given in the .rela.dyn section. Thus, we must process
// these relocations separately. We find the .dynamic section in the copied buffer based on
// its offset from the start of the section, which is calculated by subtracting the address
// of the start of the segment from the address of the .dynamic section in the segment.
Elf64_Off dynOffsetInBuffer = (Elf64_Addr) dynStart - (Elf64_Addr) programHeader->p_vaddr - (Elf64_Off) module_base;
Elf64_Dyn* dynStartInBuffer = (Elf64_Dyn*) (segmentCopy + dynOffsetInBuffer);
for( Elf64_Dyn* dyn = dynStartInBuffer; dyn->d_tag != DT_NULL; ++dyn )
{
// The following types of .dynamic entries have the module's base address added to
// their initial value
if( dyn->d_tag == DT_STRTAB ||
dyn->d_tag == DT_SYMTAB ||
dyn->d_tag == DT_RELA ||
dyn->d_tag == DT_GNU_HASH ||
dyn->d_tag == DT_VERSYM )
{
dyn->d_un.d_val -= (Elf64_Xword) module_base;
}
}
// Now we can process the normal relocations listed in the relocation table
for( size_t i = 0; i < relaEntryCount; ++i )
{
const Elf64_Rela* rela = relaStart + i;
// Find the relocation within the section. Note that for a shared object module,
// rela->r_offset is actually a virtual address
Elf64_Xword* target = (Elf64_Xword*) ( segmentCopy +
(Elf64_Off) rela->r_offset - (Elf64_Off) programHeader->p_vaddr );
SymCryptModuleUndoRelocation( module_base, target, rela );
}
SymCryptHmacSha256Append( hmacState, segmentCopy, hashableSectionSize );
SymCryptCallbackFree( segmentCopy );
return hashableSectionSize;
}
void SymCryptModuleDoHmac(
_In_ const Elf64_Addr module_base,
_In_ const Elf64_Dyn* const dynStart,
_In_ const Elf64_Rela* const relaStart,
_In_ const size_t relaEntryCount )
{
SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
SYMCRYPT_HMAC_SHA256_EXPANDED_KEY hmacKey;
SYMCRYPT_HMAC_SHA256_STATE hmacState;
BYTE actualDigest[SYMCRYPT_HMAC_SHA256_RESULT_SIZE] = {0xFF};
scError = SymCryptHmacSha256ExpandKey( &hmacKey, SymCryptVolatileFipsHmacKey,
sizeof(SymCryptVolatileFipsHmacKey) );
SYMCRYPT_FIPS_ASSERT( scError == SYMCRYPT_NO_ERROR );
SymCryptHmacSha256Init( &hmacState, &hmacKey );
const Elf64_Ehdr* header = (Elf64_Ehdr*) module_base;
const Elf64_Phdr* programHeaderStart = (Elf64_Phdr*) ( module_base + header->e_phoff );
for( const Elf64_Phdr* programHeader = programHeaderStart;
programHeader->p_type == PT_LOAD; ++programHeader )
{
// Sometimes the virtual address of a segment is greater than its offset into the module
// file on disk. This means extra NULL bytes will be inserted into the module's memory
// space at runtime. Those bytes are not part of our FIPS boundary, so we skip over them
// and always start reading from the segment's virtual address
Elf64_Addr segmentStart = module_base + (Elf64_Off) programHeader->p_vaddr;
if( (programHeader->p_flags & PF_W) == 0 )
{
// For AMD64, non-writeable segments do not contain relocations, so we can write them in
// their entirety without modification. Note that the size in memory of the section may
// be larger than the size on disk, but again, the additional size in memory is not
// part of our FIPS boundary
SymCryptHmacSha256Append( &hmacState, (const unsigned char*) segmentStart,
programHeader->p_filesz );
}
else
{
SymCryptModuleProcessSectionWithRelocations( module_base, programHeader, dynStart, relaStart,
relaEntryCount, &hmacState );
}
}
SymCryptHmacSha256Result( &hmacState, actualDigest );
// Verify that the HMAC result matches our expected digest
SYMCRYPT_FIPS_ASSERT(
memcmp( actualDigest, SymCryptVolatileFipsHmacDigest, SYMCRYPT_HMAC_SHA256_RESULT_SIZE ) == 0 );
}
void SymCryptModuleVerifyIntegrity()
{
// Verify that our placeholder values were modified after compile time. The build script
// should have replaced the placeholder values with their expected values
SYMCRYPT_FIPS_ASSERT( SYMCRYPT_FORCE_READ64( &SymCryptVolatileFipsHmacKeyRva ) != PLACEHOLDER_VALUE );
SYMCRYPT_FIPS_ASSERT( SYMCRYPT_FORCE_READ64( &SymCryptVolatileFipsBoundaryOffset ) != PLACEHOLDER_VALUE );
const Elf64_Addr module_base = (Elf64_Addr) SymCryptVolatileFipsHmacKey -
SYMCRYPT_FORCE_READ64( &SymCryptVolatileFipsHmacKeyRva );
const Elf64_Ehdr* header = (Elf64_Ehdr*) module_base;
SYMCRYPT_FIPS_ASSERT( memcmp(header->e_ident.ident.magic, ElfMagic, sizeof(ElfMagic)) == 0 );
SYMCRYPT_FIPS_ASSERT( header->e_type == ET_DYN );
SYMCRYPT_FIPS_ASSERT( header->e_machine == EM_X86_64 );
SYMCRYPT_FIPS_ASSERT( header->e_version == EV_CURRENT );
SYMCRYPT_FIPS_ASSERT( header->e_ehsize == sizeof(Elf64_Ehdr) );
SYMCRYPT_FIPS_ASSERT( header->e_phentsize == sizeof(Elf64_Phdr) );
const Elf64_Phdr* programHeaderStart = (Elf64_Phdr*) ( module_base + header->e_phoff );
Elf64_Rela* relaStart = NULL;
size_t relaEntryCount = 0;
Elf64_Dyn* dynStart = NULL;
for( unsigned int i = 0; i < header->e_phnum; ++i )
{
const Elf64_Phdr* programHeader = programHeaderStart + i;
if( programHeader->p_type == PT_DYNAMIC )
{
dynStart = (Elf64_Dyn*) (module_base + (Elf64_Off) programHeader->p_vaddr);
SymCryptModuleFindRelocationInfo( dynStart, &relaStart, &relaEntryCount );
// We only expect one PT_DYNAMIC segment
break;
}
}
SymCryptModuleDoHmac( module_base, dynStart, relaStart, relaEntryCount );
}

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

@ -0,0 +1,21 @@
//
// integrity.h
// FIPS 140-3 integrity verification header for ELF binaries
//
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
//
void SymCryptModuleVerifyIntegrity();
//
// This function verifies the integrity of the loadable segments of the SymCrypt ELF module using
// HMAC-SHA256. The module must have been postprocessed after compilation using
// process_fips_module.py. The integrity check finds the module's base address in memory by
// subtracting the relative virtual address of a known variable from its actual address in memory.
// It then uses the ELF header to find all the loadable segments in the module and calculate the
// HMAC-SHA256 digest of these segments. For writeable segments which are subject to relocations,
// the relocations will be reversed prior to being added to the HMAC, so that the HMAC input will
// match the contents of the file on disk prior to relocation.
//
// If the integrity check fails for any reason, the module will fastfail, crashing the process,
// since a failed integrity check means it cannot operate in compliance with FIPS 140-3.
//

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

@ -0,0 +1,14 @@
//
// SymCrypt DLL/shared object library pre-compiled header file
//
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
//
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "symcrypt.h"
#include "elfdefinitions.h"
#include "integrity.h"

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

@ -0,0 +1,33 @@
set(SOURCES
module.c)
include_directories(${CMAKE_SOURCE_DIR}/inc ../linux_common)
add_library(symcrypt SHARED ${SOURCES})
target_link_options(symcrypt PRIVATE
-Wl,--whole-archive
$<TARGET_FILE:symcrypt_module_linux_common>
$<TARGET_FILE:symcrypt_linuxusermode>
$<TARGET_FILE:symcrypt_common>
-Wl,--no-whole-archive
-Wl,-Bsymbolic
-Wl,-z,noexecstack
-Wl,-z,now
-Wl,-gc-sections
-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/exports.ver
-nostdlib
-nodefaultlibs
-nostartfiles
)
add_dependencies(symcrypt symcrypt_linuxusermode symcrypt_common symcrypt_module_linux_common)
add_custom_target(
symcrypt_fips ALL
COMMAND ${CMAKE_SOURCE_DIR}/scripts/process_fips_module.py $<TARGET_FILE:symcrypt> -d
DEPENDS $<TARGET_FILE:symcrypt>
COMMENT "Postprocessing SymCrypt shared object for FIPS integrity verification"
)
# -Wl,--no-undefined,-Bstatic,-Bsymbolic,--export-dynamic,-pie,--build-id

520
module/oe_full/exports.ver Normal file
Просмотреть файл

@ -0,0 +1,520 @@
VERSION_100.16 {
global:
SymCrypt3DesBlockCipher;
SymCrypt3DesCbcDecrypt;
SymCrypt3DesCbcEncrypt;
SymCrypt3DesDecrypt;
SymCrypt3DesEncrypt;
SymCrypt3DesExpandKey;
SymCrypt3DesSelftest;
SymCryptAesBlockCipher;
SymCryptAesCbcDecrypt;
SymCryptAesCbcEncrypt;
SymCryptAesCbcMac;
SymCryptAesCmac;
SymCryptAesCmacAlgorithm;
SymCryptAesCmacAppend;
SymCryptAesCmacExpandKey;
SymCryptAesCmacInit;
SymCryptAesCmacKeyCopy;
SymCryptAesCmacResult;
SymCryptAesCmacSelftest;
SymCryptAesCmacStateCopy;
SymCryptAesCtrMsb64;
SymCryptAesDecrypt;
SymCryptAesEcbDecrypt;
SymCryptAesEcbEncrypt;
SymCryptAesEncrypt;
SymCryptAesExpandKey;
SymCryptAesExpandKeyEncryptOnly;
SymCryptAesKeyCopy;
SymCryptAesSelftest;
SymCryptBuildString;
SymCryptCbcDecrypt;
SymCryptCbcEncrypt;
SymCryptCbcMac;
SymCryptCcmDecrypt;
SymCryptCcmDecryptFinal;
SymCryptCcmDecryptPart;
SymCryptCcmEncrypt;
SymCryptCcmEncryptFinal;
SymCryptCcmEncryptPart;
SymCryptCcmInit;
SymCryptCcmSelftest;
SymCryptCcmValidateParameters;
SymCryptCfbDecrypt;
SymCryptCfbEncrypt;
SymCryptChaCha20Crypt;
SymCryptChaCha20Init;
SymCryptChaCha20Poly1305Decrypt;
SymCryptChaCha20Poly1305Encrypt;
SymCryptChaCha20Poly1305Selftest;
SymCryptChaCha20Selftest;
SymCryptChaCha20SetOffset;
SymCryptCpuFeaturesNeverPresent;
SymCryptCreateTrialDivisionContext;
SymCryptCrtGenerateInverses;
SymCryptCrtSolve;
SymCryptCtrMsb64;
SymCryptDesBlockCipher;
SymCryptDesDecrypt;
SymCryptDesEncrypt;
SymCryptDesExpandKey;
SymCryptDesSelftest;
SymCryptDesxBlockCipher;
SymCryptDesxDecrypt;
SymCryptDesxEncrypt;
SymCryptDesxExpandKey;
SymCryptDesxSelftest;
SymCryptDhSecretAgreement;
SymCryptDigitsFromBits;
SymCryptDivisorAllocate;
SymCryptDivisorCopy;
SymCryptDivisorCreate;
SymCryptDivisorDigitsizeOfObject;
SymCryptDivisorFree;
SymCryptDivisorFromModulus;
SymCryptDivisorWipe;
SymCryptDlgroupAllocate;
SymCryptDlgroupCopy;
SymCryptDlgroupCreate;
SymCryptDlgroupFree;
SymCryptDlgroupGenerate;
SymCryptDlgroupGetSizes;
SymCryptDlgroupGetValue;
SymCryptDlgroupIsSame;
SymCryptDlgroupSetValue;
SymCryptDlgroupSetValueSafePrime;
SymCryptDlgroupWipe;
SymCryptDlkeyAllocate;
SymCryptDlkeyCopy;
SymCryptDlkeyCreate;
SymCryptDlkeyFree;
SymCryptDlkeyGenerate;
SymCryptDlkeyGetGroup;
SymCryptDlkeyGetValue;
SymCryptDlkeyHasPrivateKey;
SymCryptDlkeySetValue;
SymCryptDlkeySizeofPrivateKey;
SymCryptDlkeySizeofPublicKey;
SymCryptDlkeyWipe;
SymCryptDsaSign;
SymCryptDsaVerify;
SymCryptEcDhSecretAgreement;
SymCryptEcDsaSign;
SymCryptEcDsaSignDeterministic;
SymCryptEcDsaSignEx;
SymCryptEcDsaVerify;
SymCryptEcbDecrypt;
SymCryptEcbEncrypt;
SymCryptEckeyAllocate;
SymCryptEckeyCopy;
SymCryptEckeyCreate;
SymCryptEckeyFree;
SymCryptEckeyGetValue;
SymCryptEckeyHasPrivateKey;
SymCryptEckeySetRandom;
SymCryptEckeySetValue;
SymCryptEckeySizeofPrivateKey;
SymCryptEckeySizeofPublicKey;
SymCryptEckeyWipe;
SymCryptEcpointAdd;
SymCryptEcpointAddDiffNonZero;
SymCryptEcpointAllocate;
SymCryptEcpointCopy;
SymCryptEcpointCreate;
SymCryptEcpointDouble;
SymCryptEcpointFree;
SymCryptEcpointGetValue;
SymCryptEcpointIsEqual;
SymCryptEcpointIsZero;
SymCryptEcpointMaskedCopy;
SymCryptEcpointMultiScalarMul;
SymCryptEcpointNegate;
SymCryptEcpointOnCurve;
SymCryptEcpointRetrieveHandle;
SymCryptEcpointScalarMul;
SymCryptEcpointSetDistinguishedPoint;
SymCryptEcpointSetRandom;
SymCryptEcpointSetValue;
SymCryptEcpointSetZero;
SymCryptEcpointWipe;
SymCryptEcurveAllocate;
SymCryptEcurveBitsizeofFieldModulus;
SymCryptEcurveBitsizeofGroupOrder;
SymCryptEcurveDigitsofFieldElement;
SymCryptEcurveDigitsofScalarMultiplier;
SymCryptEcurveFree;
SymCryptEcurveGroupOrder;
SymCryptEcurveHighBitRestrictionNumOfBits;
SymCryptEcurveHighBitRestrictionPosition;
SymCryptEcurveHighBitRestrictionValue;
SymCryptEcurveIsSame;
SymCryptEcurveParamsCurve25519;
SymCryptEcurveParamsNistP192;
SymCryptEcurveParamsNistP224;
SymCryptEcurveParamsNistP256;
SymCryptEcurveParamsNistP384;
SymCryptEcurveParamsNistP521;
SymCryptEcurveParamsNumsP256t1;
SymCryptEcurveParamsNumsP384t1;
SymCryptEcurveParamsNumsP512t1;
SymCryptEcurvePrivateKeyDefaultFormat;
SymCryptEcurveSizeofFieldElement;
SymCryptEcurveSizeofScalarMultiplier;
SymCryptFreeTrialDivisionContext;
SymCryptGcmAuthPart;
SymCryptGcmDecrypt;
SymCryptGcmDecryptFinal;
SymCryptGcmDecryptPart;
SymCryptGcmEncrypt;
SymCryptGcmEncryptFinal;
SymCryptGcmEncryptPart;
SymCryptGcmExpandKey;
SymCryptGcmInit;
SymCryptGcmKeyCopy;
SymCryptGcmSelftest;
SymCryptGcmStateCopy;
SymCryptGcmValidateParameters;
SymCryptHash;
SymCryptHashAppend;
SymCryptHashInit;
SymCryptHashInputBlockSize;
SymCryptHashResult;
SymCryptHashResultSize;
SymCryptHashStateSize;
SymCryptHkdf;
SymCryptHkdfDerive;
SymCryptHkdfExpandKey;
SymCryptHkdfPrkExpandKey;
SymCryptHkdfSelfTest;
SymCryptHmacMd5;
SymCryptHmacMd5Algorithm;
SymCryptHmacMd5Append;
SymCryptHmacMd5ExpandKey;
SymCryptHmacMd5Init;
SymCryptHmacMd5KeyCopy;
SymCryptHmacMd5Result;
SymCryptHmacMd5Selftest;
SymCryptHmacMd5StateCopy;
SymCryptHmacSha1;
SymCryptHmacSha1Algorithm;
SymCryptHmacSha1Append;
SymCryptHmacSha1ExpandKey;
SymCryptHmacSha1Init;
SymCryptHmacSha1KeyCopy;
SymCryptHmacSha1Result;
SymCryptHmacSha1Selftest;
SymCryptHmacSha1StateCopy;
SymCryptHmacSha256;
SymCryptHmacSha256Algorithm;
SymCryptHmacSha256Append;
SymCryptHmacSha256ExpandKey;
SymCryptHmacSha256Init;
SymCryptHmacSha256KeyCopy;
SymCryptHmacSha256Result;
SymCryptHmacSha256Selftest;
SymCryptHmacSha256StateCopy;
SymCryptHmacSha384;
SymCryptHmacSha384Algorithm;
SymCryptHmacSha384Append;
SymCryptHmacSha384ExpandKey;
SymCryptHmacSha384Init;
SymCryptHmacSha384KeyCopy;
SymCryptHmacSha384Result;
SymCryptHmacSha384Selftest;
SymCryptHmacSha384StateCopy;
SymCryptHmacSha512;
SymCryptHmacSha512Algorithm;
SymCryptHmacSha512Append;
SymCryptHmacSha512ExpandKey;
SymCryptHmacSha512Init;
SymCryptHmacSha512KeyCopy;
SymCryptHmacSha512Result;
SymCryptHmacSha512Selftest;
SymCryptHmacSha512StateCopy;
SymCryptIntAddMixedSize;
SymCryptIntAddSameSize;
SymCryptIntAddUint32;
SymCryptIntAllocate;
SymCryptIntBitsizeOfObject;
SymCryptIntBitsizeOfValue;
SymCryptIntConditionalCopy;
SymCryptIntConditionalSwap;
SymCryptIntCopy;
SymCryptIntCopyMixedSize;
SymCryptIntCreate;
SymCryptIntDigitsizeOfObject;
SymCryptIntDivMod;
SymCryptIntDivPow2;
SymCryptIntExtendedGcd;
SymCryptIntFindSmallDivisor;
SymCryptIntFree;
SymCryptIntFromDivisor;
SymCryptIntFromModulus;
SymCryptIntGenerateRandomPrime;
SymCryptIntGetBit;
SymCryptIntGetBits;
SymCryptIntGetValue;
SymCryptIntGetValueLsbits32;
SymCryptIntGetValueLsbits64;
SymCryptIntIsEqual;
SymCryptIntIsEqualUint32;
SymCryptIntIsLessThan;
SymCryptIntMaskedCopy;
SymCryptIntMillerRabinPrimalityTest;
SymCryptIntModPow2;
SymCryptIntMulMixedSize;
SymCryptIntMulPow2;
SymCryptIntMulSameSize;
SymCryptIntMulUint32;
SymCryptIntNeg;
SymCryptIntSetBits;
SymCryptIntSetValue;
SymCryptIntSetValueUint32;
SymCryptIntSetValueUint64;
SymCryptIntShr1;
SymCryptIntSquare;
SymCryptIntSubMixedSize;
SymCryptIntSubSameSize;
SymCryptIntSubUint32;
SymCryptIntToDivisor;
SymCryptIntToModElement;
SymCryptIntToModulus;
SymCryptIntWipe;
SymCryptLoadLsbFirstUint32;
SymCryptLoadLsbFirstUint64;
SymCryptLoadMsbFirstUint32;
SymCryptLoadMsbFirstUint64;
SymCryptMarvin32;
SymCryptMarvin32Append;
SymCryptMarvin32DefaultSeed;
SymCryptMarvin32ExpandSeed;
SymCryptMarvin32Init;
SymCryptMarvin32Result;
SymCryptMarvin32SeedCopy;
SymCryptMarvin32Selftest;
SymCryptMarvin32StateCopy;
SymCryptMask32EqU32;
SymCryptMask32IsNonzeroU31;
SymCryptMask32IsZeroU31;
SymCryptMask32LtU31;
SymCryptMask32NeqU31;
SymCryptMd2;
SymCryptMd2Algorithm;
SymCryptMd2Append;
SymCryptMd2Init;
SymCryptMd2Result;
SymCryptMd2Selftest;
SymCryptMd2StateCopy;
SymCryptMd2StateExport;
SymCryptMd2StateImport;
SymCryptMd4;
SymCryptMd4Algorithm;
SymCryptMd4Append;
SymCryptMd4Init;
SymCryptMd4Result;
SymCryptMd4Selftest;
SymCryptMd4StateCopy;
SymCryptMd4StateExport;
SymCryptMd4StateImport;
SymCryptMd5;
SymCryptMd5Algorithm;
SymCryptMd5Append;
SymCryptMd5Init;
SymCryptMd5OidList;
SymCryptMd5Result;
SymCryptMd5Selftest;
SymCryptMd5StateCopy;
SymCryptMd5StateExport;
SymCryptMd5StateImport;
SymCryptModAdd;
SymCryptModDivPow2;
SymCryptModElementAllocate;
SymCryptModElementConditionalSwap;
SymCryptModElementCopy;
SymCryptModElementCreate;
SymCryptModElementFree;
SymCryptModElementGetValue;
SymCryptModElementIsEqual;
SymCryptModElementIsZero;
SymCryptModElementMaskedCopy;
SymCryptModElementSetValue;
SymCryptModElementSetValueNegUint32;
SymCryptModElementSetValueUint32;
SymCryptModElementToInt;
SymCryptModElementWipe;
SymCryptModExp;
SymCryptModInv;
SymCryptModMul;
SymCryptModMultiExp;
SymCryptModNeg;
SymCryptModSetRandom;
SymCryptModSquare;
SymCryptModSub;
SymCryptModuleInit;
SymCryptModulusAllocate;
SymCryptModulusBitsizeOfObject;
SymCryptModulusCopy;
SymCryptModulusCreate;
SymCryptModulusDigitsizeOfObject;
SymCryptModulusFree;
SymCryptModulusWipe;
SymCryptParallelSha256Init;
SymCryptParallelSha256Process;
SymCryptParallelSha256Selftest;
SymCryptParallelSha384Init;
SymCryptParallelSha384Process;
SymCryptParallelSha384Selftest;
SymCryptParallelSha512Init;
SymCryptParallelSha512Process;
SymCryptParallelSha512Selftest;
SymCryptPbkdf2;
SymCryptPbkdf2Derive;
SymCryptPbkdf2ExpandKey;
SymCryptPbkdf2_HmacSha1SelfTest;
SymCryptPbkdf2_HmacSha256SelfTest;
SymCryptPoly1305;
SymCryptPoly1305Append;
SymCryptPoly1305Init;
SymCryptPoly1305Result;
SymCryptPoly1305Selftest;
SymCryptRc2BlockCipher;
SymCryptRc2Decrypt;
SymCryptRc2Encrypt;
SymCryptRc2ExpandKey;
SymCryptRc2ExpandKeyEx;
SymCryptRc2Selftest;
SymCryptRc4Crypt;
SymCryptRc4Init;
SymCryptRc4Selftest;
SymCryptRdrandGet;
SymCryptRdrandGetBytes;
SymCryptRdrandStatus;
SymCryptRdseedGet;
SymCryptRdseedGetBytes;
SymCryptRdseedStatus;
SymCryptRngAesFips140_2Generate;
SymCryptRngAesFips140_2Instantiate;
SymCryptRngAesFips140_2Reseed;
SymCryptRngAesFips140_2Uninstantiate;
SymCryptRngAesGenerate;
SymCryptRngAesGenerateSelftest;
SymCryptRngAesInstantiate;
SymCryptRngAesInstantiateSelftest;
SymCryptRngAesReseed;
SymCryptRngAesReseedSelftest;
SymCryptRngAesUninstantiate;
SymCryptRoundUpPow2Sizet;
SymCryptRsaOaepDecrypt;
SymCryptRsaOaepEncrypt;
SymCryptRsaPkcs1Decrypt;
SymCryptRsaPkcs1Encrypt;
SymCryptRsaPkcs1Sign;
SymCryptRsaPkcs1Verify;
SymCryptRsaPssSign;
SymCryptRsaPssVerify;
SymCryptRsaRawDecrypt;
SymCryptRsaRawEncrypt;
SymCryptRsakeyAllocate;
SymCryptRsakeyFree;
SymCryptRsakeyGenerate;
SymCryptRsakeyGetCrtValue;
SymCryptRsakeyGetNumberOfPrimes;
SymCryptRsakeyGetNumberOfPublicExponents;
SymCryptRsakeyGetValue;
SymCryptRsakeyHasPrivateKey;
SymCryptRsakeyModulusBits;
SymCryptRsakeySetValue;
SymCryptRsakeySizeofModulus;
SymCryptRsakeySizeofPrime;
SymCryptRsakeySizeofPublicExponent;
SymCryptRsakeyWipe;
SymCryptScsCopy;
SymCryptScsRotateBuffer;
SymCryptScsTableInit;
SymCryptScsTableLoad;
SymCryptScsTableSetBuffer;
SymCryptScsTableStore;
SymCryptScsTableWipe;
SymCryptSha1;
SymCryptSha1Algorithm;
SymCryptSha1Append;
SymCryptSha1Init;
SymCryptSha1OidList;
SymCryptSha1Result;
SymCryptSha1Selftest;
SymCryptSha1StateCopy;
SymCryptSha1StateExport;
SymCryptSha1StateImport;
SymCryptSha256;
SymCryptSha256Algorithm;
SymCryptSha256Append;
SymCryptSha256Init;
SymCryptSha256OidList;
SymCryptSha256Result;
SymCryptSha256Selftest;
SymCryptSha256StateCopy;
SymCryptSha256StateExport;
SymCryptSha256StateImport;
SymCryptSha384;
SymCryptSha384Algorithm;
SymCryptSha384Append;
SymCryptSha384Init;
SymCryptSha384OidList;
SymCryptSha384Result;
SymCryptSha384Selftest;
SymCryptSha384StateCopy;
SymCryptSha384StateExport;
SymCryptSha384StateImport;
SymCryptSha512;
SymCryptSha512Algorithm;
SymCryptSha512Append;
SymCryptSha512Init;
SymCryptSha512OidList;
SymCryptSha512Result;
SymCryptSha512Selftest;
SymCryptSha512StateCopy;
SymCryptSha512StateExport;
SymCryptSha512StateImport;
SymCryptSizeofDivisorFromDigits;
SymCryptSizeofDlgroupFromBitsizes;
SymCryptSizeofDlkeyFromDlgroup;
SymCryptSizeofEckeyFromCurve;
SymCryptSizeofEcpointFromCurve;
SymCryptSizeofIntFromDigits;
SymCryptSizeofModElementFromModulus;
SymCryptSizeofModulusFromDigits;
SymCryptSizeofRsakeyFromParams;
SymCryptSp800_108;
SymCryptSp800_108Derive;
SymCryptSp800_108ExpandKey;
SymCryptSp800_108_HmacSha1SelfTest;
SymCryptSp800_108_HmacSha256SelfTest;
SymCryptStoreLsbFirstUint32;
SymCryptStoreLsbFirstUint64;
SymCryptStoreMsbFirstUint32;
SymCryptStoreMsbFirstUint64;
SymCryptTlsCbcHmacVerify;
SymCryptTlsPrf1_1;
SymCryptTlsPrf1_1Derive;
SymCryptTlsPrf1_1ExpandKey;
SymCryptTlsPrf1_1SelfTest;
SymCryptTlsPrf1_2;
SymCryptTlsPrf1_2Derive;
SymCryptTlsPrf1_2ExpandKey;
SymCryptTlsPrf1_2SelfTest;
SymCryptUint32Bitsize;
SymCryptUint32Bytesize;
SymCryptUint64Bitsize;
SymCryptUint64Bytesize;
SymCryptUint64Gcd;
SymCryptWipe;
SymCryptWipeKnownSize;
SymCryptXtsAesDecrypt;
SymCryptXtsAesEncrypt;
SymCryptXtsAesExpandKey;
SymCryptXtsAesSelftest;
local:
*;
};

73
module/oe_full/module.c Normal file
Просмотреть файл

@ -0,0 +1,73 @@
//
// module.c
// Main file for SymCrypt DLL/shared object library
//
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
//
#include "precomp.h"
SYMCRYPT_ENVIRONMENT_LINUX_USERMODE
// Module main function executed by the runtime upon load
VOID __attribute__((constructor)) SymCryptModuleMain()
{
SymCryptInit();
// We must test HMAC-SHA256 first since it's used by our integrity verification
SymCryptHmacSha256Selftest();
SymCryptModuleVerifyIntegrity();
SymCrypt3DesSelftest();
SymCryptAesSelftest( SYMCRYPT_AES_SELFTEST_ALL );
SymCryptAesCmacSelftest();
SymCryptCcmSelftest();
SymCryptGcmSelftest();
SymCryptXtsAesSelftest();
SymCryptRngAesInstantiateSelftest();
SymCryptRngAesReseedSelftest();
SymCryptRngAesGenerateSelftest();
SymCryptHmacSha1Selftest();
SymCryptHmacSha384Selftest();
SymCryptHmacSha512Selftest();
SymCryptParallelSha256Selftest();
SymCryptParallelSha512Selftest();
SymCryptTlsPrf1_1SelfTest();
SymCryptTlsPrf1_2SelfTest();
SymCryptHkdfSelfTest();
}
PVOID
SYMCRYPT_CALL
SymCryptCallbackAlloc( SIZE_T nBytes )
{
PVOID ptr = NULL;
if(posix_memalign( &ptr, SYMCRYPT_ASYM_ALIGN_VALUE, nBytes ) != 0)
{
return NULL;
}
return ptr;
}
VOID
SYMCRYPT_CALL
SymCryptCallbackFree( VOID * pMem )
{
free( pMem );
}
VOID SYMCRYPT_CALL SymCryptModuleInit( UINT32 api, UINT32 minor, UINT32 patch )
{
if( api > SYMCRYPT_CODE_VERSION_API )
{
SymCryptFatal( 'vers' );
}
}

10
module/oe_full/precomp.h Normal file
Просмотреть файл

@ -0,0 +1,10 @@
//
// SymCrypt DLL/shared object library pre-compiled header file
//
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
//
#include <stdlib.h>
#include "symcrypt.h"
#include "integrity.h"

262
scripts/process_fips_module.py Executable file
Просмотреть файл

@ -0,0 +1,262 @@
#!/usr/bin/env python3
"""
This script facilitaties module integrity verification for FIPS 140 by processing the input ELF
shared object module and replacing key variables so that the module can calculate its own base
address, and thereby HMAC its own memory, at runtime.
Requires PyElfTools: https://github.com/eliben/pyelftools
Copyright (c) Microsoft Corporation. Licensed under the MIT license.
"""
import argparse
import hashlib
import hmac
import io
import logging
import os
import secrets
import stat
import struct
import sys
from elftools.elf.elffile import ELFFile
from elftools.elf.sections import Section, SymbolTableSection, Symbol
from elftools.elf.segments import Segment
KEY_NAME = "SymCryptVolatileFipsHmacKey"
KEY_RVA_NAME = "SymCryptVolatileFipsHmacKeyRva"
BOUNDARY_OFFSET_NAME = "SymCryptVolatileFipsBoundaryOffset"
DIGEST_NAME = "SymCryptVolatileFipsHmacDigest"
PLACEHOLDER_VALUE = struct.pack("Q", 0x8BADF00D)
PLACEHOLDER_ARRAY = bytes((
0x5B, 0x75, 0xBB, 0xE4, 0x9E, 0x18, 0x03, 0x55,
0x08, 0x4E, 0x3F, 0xE7, 0x60, 0x7E, 0x4F, 0x08,
0xAA, 0x77, 0x0F, 0x0B, 0xAB, 0xC6, 0x58, 0x5A,
0xA9, 0x9F, 0x83, 0x4B, 0xD0, 0x6E, 0x67, 0x05))
# Writeable flag for segments since elftools doesn't define it
PF_W = 2
class Variable(object):
"""
Wrapper for a pyelftools Symbol which makes it easier to get the value and offset/
virtual address of the object that the symbol represents.
"""
def __init__(self, elf_file, name):
"""
Initializes a Variable object by finding the symbol name in the symbol table and mapping
it to the offset in the file.
"""
self.elf_file = elf_file
self.name = name
symtab = self.elf_file.get_section_by_name(".symtab")
symbols = symtab.get_symbol_by_name(name)
assert(len(symbols) == 1)
self.symbol = symbols[0]
self.vaddr = self.symbol.entry["st_value"]
self.length = self.symbol.entry["st_size"]
self.section = self.elf_file.get_section(self.symbol["st_shndx"])
self.section_offset = self.vaddr - self.section.header["sh_addr"]
self.offset = self.section.header["sh_offset"] + self.section_offset
@property
def value(self):
return self.section.data()[self.section_offset:self.section_offset + self.length]
@value.setter
def value(self, value):
assert(type(value) == bytes)
assert(len(value) == self.length)
assert(bool(self.section.compressed) is False)
# The .data() method returns a bytes object. We can't use it to write back to the original
# buffer, so we need to find the appropriate section within the stream using sh_offset and
# write to that.
logging.debug("Writing {} to offset {}".format(value.hex(), hex(self.offset)))
self.section.stream.seek(self.offset)
self.section.stream.write(value)
def set_value(self, format, *args):
new_value = struct.pack(format, *args)
assert(len(new_value) == self.length)
logging.debug("Changing {} value".format(self.name))
self.value = new_value
def log_variable(var):
logging.debug("{}: offset {}, virtual address {}, Value {}".format(
var.name,
hex(var.offset),
hex(var.vaddr),
var.value.hex()))
def hmac_module(loadable_segments, data_section_offset, key, digest, dump_file_path = None):
"""
Performs HMAC-SHA256 on module contents and writes it back to the module buffer
"""
module_bytes = bytearray()
last_segment_offset = -1
for (index, segment) in enumerate(loadable_segments):
segment_hashable_length = 0
# Ensure the loadable segments were given in ascending order by offset
# (i.e. the same order as in the file)
assert(last_segment_offset < segment["p_offset"])
if segment["p_offset"] + segment["p_filesz"] > data_section_offset:
segment_hashable_length = data_section_offset - segment["p_offset"]
module_bytes += segment.data()[:segment_hashable_length]
else:
module_bytes += segment.data()
segment_hashable_length = len(segment.data())
logging.info("Segment {}: {} - {}".format(
index,
hex(segment["p_offset"]),
hex(segment["p_offset"] + segment_hashable_length)))
last_segment_offset = segment["p_offset"]
if dump_file_path is not None:
with open(dump_file_path, "wb") as dump_file:
dump_file.write(module_bytes)
logging.debug("Using key: {}".format(key.value.hex()))
digest_bytes = hmac.digest(key.value, module_bytes, hashlib.sha256)
logging.debug("Calculated SHA256 digest: {}".format(digest_bytes.hex()))
digest.set_value(str(len(digest_bytes)) + "s", digest_bytes)
log_variable(digest)
def process_loadable_segments(elf_file):
"""
Finds all loadable segments in the module and ensures that the assumptions made by our runtime
integrity verification code are valid. Returns the list of loadable segments. If an assumption
is found to be invalid, an exception will be thrown.
"""
# Find all loadable segments and calculate their sizes and offsets
loadable_segments = []
writeable_segment = None
for segment in elf_file.iter_segments():
if segment["p_type"] == "PT_LOAD":
logging.debug("PT_LOAD: Offset {} VAddr {} PAddr {} FileSz {} MemSz {} Align {}".format(
hex(segment["p_offset"]),
hex(segment["p_vaddr"]),
hex(segment["p_paddr"]),
hex(segment["p_filesz"]),
hex(segment["p_memsz"]),
hex(segment["p_align"])
))
loadable_segments.append(segment)
if writeable_segment is not None:
# There must be exactly one writeable segment, and it must be the last of the
# PT_LOAD segments
logging.error("Found more than one loadable, writeable segment!")
raise RuntimeError
if segment["p_flags"] & PF_W != 0:
writeable_segment = segment
writeable_segment_sections = []
for section in elf_file.iter_sections():
if writeable_segment.section_in_segment(section):
writeable_segment_sections.append(section)
# We set our FIPS module boundary based on where the .data section starts (since it and the
# .bss section cannot be included in the HMAC). Therefore, .data and .bss must be the second
# last and last sections of that segment, respectively.
if writeable_segment_sections[-2].name != ".data" or \
writeable_segment_sections[-1].name != ".bss":
logging.error("Unexpected section order in writeable segment!")
raise RuntimeError
return loadable_segments
def main():
"""
Entrypoint
"""
parser = argparse.ArgumentParser(description = "Postprocess SymCrypt shared object module")
parser.add_argument("input", type=str, help = "Path to SymCrypt module")
parser.add_argument("-d", "--debug", action = "store_true", help = "Enable debug output (also dumps hashable module contents to file)")
args = parser.parse_args()
if args.debug:
logging.basicConfig(level = logging.DEBUG)
else:
logging.basicConfig(level = logging.INFO)
with open(args.input, "rb") as input_file:
buffer = input_file.read()
buffer_stream = io.BytesIO(buffer)
# Copy the original input file to a backup file
os.replace(args.input, args.input + ".bak")
elf_file = ELFFile(buffer_stream)
loadable_segments = process_loadable_segments(elf_file)
# Find the HMAC key placeholder and replace it with a randomly generated key
key_variable = Variable(elf_file, KEY_NAME)
assert(key_variable.value == PLACEHOLDER_ARRAY)
random_key = secrets.token_bytes(len(key_variable.value)) # NB: not actually a secret
key_variable.set_value(str(len(random_key)) + "s", random_key)
log_variable(key_variable)
# Find the HMAC key relative virtual address placeholder and replace it with
# the actual relative virtual address of the HMAC key
key_rva_variable = Variable(elf_file, KEY_RVA_NAME)
assert(key_rva_variable.value == PLACEHOLDER_VALUE)
key_rva_variable.set_value("Q", key_variable.vaddr)
log_variable(key_rva_variable)
# Find the FIPS module boundary placeholder and replace it with the our actual
# FIPS module boundary, which we have defined to be the start of the .data section
fips_boundary_variable = Variable(elf_file, BOUNDARY_OFFSET_NAME)
assert(fips_boundary_variable.value == PLACEHOLDER_VALUE)
data_section = elf_file.get_section_by_name(".data")
data_section_offset = data_section["sh_offset"]
fips_boundary_variable.set_value("Q", data_section_offset)
log_variable(fips_boundary_variable)
# Find the HMAC digest placeholder, HMAC the loadable segments of the module, and replace
# the placeholder with the actual digest
digest_variable = Variable(elf_file, DIGEST_NAME)
assert(digest_variable.value == PLACEHOLDER_ARRAY)
hmac_module(loadable_segments, data_section_offset, key_variable, digest_variable,
dump_file_path = args.input + ".loadable.bin" if args.debug else None)
with open(args.input, "wb") as output_file:
output_file.write(buffer_stream.getbuffer())
# chmod 0755 the new output file so that it"s marked as executable (required by some platforms)
os.chmod(args.input,
stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR | # User: read, write, execute
stat.S_IRGRP | stat.S_IXGRP | # Group: read, execute
stat.S_IXOTH | stat.S_IXOTH) # Other: read, execute
logging.info("Success!")
if __name__ == "__main__":
main()

1
scripts/requirements.txt Normal file
Просмотреть файл

@ -0,0 +1 @@
pyelftools

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

@ -92,4 +92,5 @@ if(WIN32)
add_subdirectory(exe_Win8_1nLater)
else()
add_subdirectory(exe_linux)
add_subdirectory(exe_moduletest)
endif()

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

@ -8,4 +8,4 @@ add_compile_options(-DINCLUDE_IMPL_MSBIGNUM=0)
add_compile_options(-DINCLUDE_IMPL_RSA32=0)
add_executable(symcryptunittest ${SOURCES})
target_link_libraries(symcryptunittest symcryptunittest_lib symcrypt_generic)
target_link_libraries(symcryptunittest symcryptunittest_lib symcrypt_common)

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

@ -0,0 +1,8 @@
set(SOURCES
moduletest.cpp
)
add_executable(symcryptmoduletest ${SOURCES})
target_link_libraries(symcryptmoduletest symcrypt)
add_dependencies(symcryptmoduletest symcrypt_fips)

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

@ -0,0 +1,21 @@
//
// moduletest.cpp
// Test executable for SymCrypt module smoke tests
//
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
//
#include <stddef.h>
#include <stdio.h>
#include "symcrypt.h"
int
main( int argc, _In_reads_( argc ) char * argv[] )
{
SYMCRYPT_MODULE_INIT();
printf("Success!\n");
return 0;
}

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

@ -929,7 +929,7 @@ extern DWORD g_osVersion; // 0xaabb for major version aa and minor version
_Analysis_noreturn_
VOID
fatal( _In_ PSTR file, ULONG line, _In_ PSTR text, ... );
fatal( _In_ PCSTR file, ULONG line, _In_ PCSTR text, ... );
typedef CONST CHAR * PCCHAR;

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

@ -32,7 +32,6 @@ set(SOURCES
testDsa.cpp
testScsTable.cpp
testScsTools.cpp
testIEEE802_11SaeCustom.cpp
perf.cpp
)
@ -43,6 +42,7 @@ if(WIN32)
capi_implementations.cpp
cng_implementations.cpp
msbignum_implementations.cpp
testIEEE802_11SaeCustom.cpp
# testInterop.cpp
# testRsa.cpp
# testRsa_sc.cpp

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

@ -898,7 +898,7 @@ AlgorithmImplementationVector g_algorithmImplementation;
_Analysis_noreturn_
VOID
fatal( _In_ PSTR file, ULONG line, _In_ PSTR format, ... )
fatal( _In_ PCSTR file, ULONG line, _In_ PCSTR format, ... )
{
va_list vl;
printOutput( 0 );
@ -1196,7 +1196,7 @@ testpbkdf2()
//
// Reach into the internals of Symcrypt to retrieve the build string
extern "C" {
extern const CHAR * SymCryptBuildString;
extern const CHAR * const SymCryptBuildString;
};
VOID
@ -1561,7 +1561,9 @@ runFunctionalTests()
testEcc();
#if SYMCRYPT_MS_VC
testIEEE802_11SaeCustom();
#endif
iprint( "Functional testing done.\n" );

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

@ -6877,6 +6877,7 @@ EccImp<ImpSc, AlgEcdh>::~EccImp()
}
//============================
#if SYMCRYPT_MS_VC
template<>
VOID
algImpKeyPerfFunction<ImpSc, AlgIEEE802_11SaeCustom>( PBYTE buf1, PBYTE buf2, PBYTE buf3, SIZE_T keySize )
@ -6926,7 +6927,7 @@ template<>
ArithImp<ImpSc, AlgIEEE802_11SaeCustom>::~ArithImp()
{
}
#endif
VOID
@ -7083,7 +7084,9 @@ addSymCryptAlgs()
addImplementationToGlobalList<EccImp<ImpSc, AlgEcdsaVerify>>();
addImplementationToGlobalList<EccImp<ImpSc, AlgEcdh>>();
#if SYMCRYPT_MS_VC
addImplementationToGlobalList<ArithImp<ImpSc, AlgIEEE802_11SaeCustom>>();
#endif
addImplementationToGlobalList<ArithImp<ImpSc, AlgDeveloperTest>>();
}