// // precomp.h Precompiled header file for SymCrypt unit test // // Copyright (c) Microsoft Corporation. Licensed under the MIT license. // // Prevent Windows header files from defining min and max macros (breaks STL) #define NOMINMAX #ifdef KERNEL_MODE //#include //#include //#include #pragma warning(push) #pragma warning(disable:4201) #include #pragma warning(pop) #include #include #include #include #elif defined(__GNUC__) #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "symcrypt_no_sal.h" // Ignore the multi-character character constant warnings #pragma GCC diagnostic ignored "-Wmultichar" // Ignore the ISO C++ 11 does allow conversion from string literal to PSTR // #pragma GCC diagnostic ignored "-Wc++11-compat-deprecated-writable-strings" // Ignore the unused entity issue with UNREFERENCED PARAMETER #pragma GCC diagnostic ignored "-Wunused-value" #define DWORD UINT32 #define PSTR char * #define PCSTR CONST PSTR #define LPSTR PSTR #define LPCSTR CONST PSTR #define PUCHAR unsigned char * #define WCHAR wchar_t #define PWSTR wchar_t * #define LPWSTR PWSTR #define CONST const #define LONGLONG INT64 #define ULONGLONG UINT64 #define ULONG_PTR UINT_PTR #define LPVOID PVOID #define NTSTATUS INT32 #define STATUS_INVALID_SIGNATURE ((NTSTATUS)0xC000A000L) #define STATUS_INVALID_PARAMETER ((NTSTATUS)0xC000000DL) #define STATUS_NO_MEMORY ((NTSTATUS)0xC0000017L) #define STATUS_NOT_SUPPORTED ((NTSTATUS)0xC00000BBL) #define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L) #define STATUS_SUCCESS ((NTSTATUS)0x00000000L) #define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) #define STATUS_AUTH_TAG_MISMATCH ((NTSTATUS)0xC000A002L) #define STATUS_ENCRYPTION_FAILED ((NTSTATUS)0xC000028AL) #define UNREFERENCED_PARAMETER(x) (x) #define __success(x) #define __out_bcount_part_opt(x, y) #define WINAPI #define BOOL_SUCCESS BOOL typedef size_t DWORDREG; typedef const DWORDREG DWORDREGC; typedef enum { BCRYPT_HASH_OPERATION_HASH_DATA = 1, BCRYPT_HASH_OPERATION_FINISH_HASH = 2, } BCRYPT_HASH_OPERATION_TYPE; typedef struct _BCRYPT_MULTI_HASH_OPERATION { uint32_t iHash; // index of hash object BCRYPT_HASH_OPERATION_TYPE hashOperation; // operation to be performed PUCHAR pbBuffer; // data to be hashed, or result buffer uint32_t cbBuffer; } BCRYPT_MULTI_HASH_OPERATION; #define InterlockedAdd64(ptr, val) __sync_fetch_and_add(ptr, val) #define InterlockedIncrement64(ptr) __sync_fetch_and_add(ptr, 1) #define InterlockedDecrement64(ptr) __sync_fetch_and_sub(ptr, 1) // aligned_alloc requires size to be integer multiple of alignment #define ALIGNED_ALLOC( alignment, size ) aligned_alloc( alignment, (size + (alignment - 1)) & ~(alignment - 1) ) #define ALIGNED_FREE( ptr ) free( ptr ) #include #define Sleep(x) sleep((x)/1000) #else // MSVC #include // Ensure that windows.h doesn't re-define the status_* symbols #define WIN32_NO_STATUS #include #include #include // // Hack to get all the BCrypt declarations even though our binaries target down-level platforms. // #pragma push_macro("NTDDI_VERSION") #undef NTDDI_VERSION #define NTDDI_VERSION NTDDI_WINTHRESHOLD #include #pragma pop_macro("NTDDI_VERSION") #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef PRIx64 #define PRIx64 "llx" #endif #ifndef PRId64 #define PRId64 "lld" #endif #define ALIGNED_ALLOC( alignment, size ) _aligned_malloc( size, alignment ) #define ALIGNED_FREE( ptr ) _aligned_free( ptr ) #endif #include "symcrypt.h" #include "symcrypt_low_level.h" extern "C" { #include "../../lib/sc_lib.h" } #if SYMCRYPT_CPU_X86 | SYMCRYPT_CPU_AMD64 #include #include #if SYMCRYPT_GNUC #include #define _XCR_XFEATURE_ENABLED_MASK (0) #endif #endif // // Disable certain strange warnings // #pragma warning( disable: 4505 ) // unreferenced local function has been removed. // Don't understand why I get that one; something about templates... #pragma warning( disable: 4127 ) // conditional expression is constant #pragma warning( disable: 6262 ) // excessive stack usage. This is test code, I don't care. #pragma warning( disable: 4702 ) // unreachable code. The compilers are not equally smart, and some complain // about 'function must return a value' and some about 'unreachable code' #pragma warning( disable: 4296 ) // expression is always false - this warning is forced to be an error by a // pragma in the SDK warning.h, but we don't consider it useful // // Macros for different environments // #if SYMCRYPT_MS_VC #define STRICMP _stricmp #define STRNICMP _strnicmp #define SNPRINTF_S(a,b,c,d,...) _snprintf_s((a),(b),(c),(d),__VA_ARGS__) #define VSNPRINTF_S(a,b,c,d,...) _vsnprintf_s((a),(b),(c),(d),__VA_ARGS__) #define GENRANDOM(pbBuf, cbBuf) BCryptGenRandom( NULL, (PBYTE) (pbBuf), (cbBuf), BCRYPT_USE_SYSTEM_PREFERRED_RNG ) FORCEINLINE PVOID ALLOCATE_FAST_INPROC_MUTEX() { LPCRITICAL_SECTION lpCriticalSection = new CRITICAL_SECTION; InitializeCriticalSection(lpCriticalSection); return (PVOID)lpCriticalSection; } FORCEINLINE VOID FREE_FAST_INPROC_MUTEX(PVOID pMutex) { LPCRITICAL_SECTION lpCriticalSection = (LPCRITICAL_SECTION)pMutex; DeleteCriticalSection(lpCriticalSection); delete lpCriticalSection; } #define ACQUIRE_FAST_INPROC_MUTEX(pMutex) EnterCriticalSection((LPCRITICAL_SECTION)pMutex) #define RELEASE_FAST_INPROC_MUTEX(pMutex) LeaveCriticalSection((LPCRITICAL_SECTION)pMutex) #define SLEEP Sleep #if defined( _X86_ ) | defined( _ARM_ ) #define BitScanReverseSizeT _BitScanReverse #elif defined( _AMD64_ ) || defined( _ARM64_ ) #define BitScanReverseSizeT _BitScanReverse64 #endif #define SECUREZEROMEMORY(dest, sz) RtlSecureZeroMemory( (dest), (sz) ) #define TRAP_DEBUGGER() do \ { \ if( IsDebuggerPresent() ) { DebugBreak(); } \ } while (false) #elif SYMCRYPT_GNUC #define STRICMP strcasecmp #define STRNICMP strncasecmp #define SNPRINTF_S(a,b,c,d,...) std::snprintf((a),(b),(d),__VA_ARGS__) #define VSNPRINTF_S(a,b,c,d,...) std::vsnprintf((a),(b),(d),__VA_ARGS__) #if SYMCRYPT_PLATFORM_APPLE #include #define GENRANDOM(pbBuf, cbBuf) SecRandomCopyBytes( kSecRandomDefault, cbBuf, (PBYTE) pbBuf ) #else #include // write as a function wrapper to handle unexpected return values as errors FORCEINLINE ssize_t GENRANDOM(void * pbBuf, size_t cbBuf) { return (getrandom( pbBuf, cbBuf, 0 ) == (ssize_t) cbBuf) ? 0 : -1; } #endif #include FORCEINLINE PVOID ALLOCATE_FAST_INPROC_MUTEX() { PVOID ptr = malloc(sizeof(pthread_mutex_t)); if( ptr ) { if( pthread_mutex_init( (pthread_mutex_t *)ptr, NULL ) != 0 ) { free(ptr); ptr = NULL; } } return ptr; } FORCEINLINE VOID FREE_FAST_INPROC_MUTEX(PVOID pMutex) { pthread_mutex_destroy( (pthread_mutex_t *)pMutex ); free(pMutex); } #define ACQUIRE_FAST_INPROC_MUTEX(pMutex) pthread_mutex_lock((pthread_mutex_t *)pMutex) #define RELEASE_FAST_INPROC_MUTEX(pMutex) pthread_mutex_unlock((pthread_mutex_t *)pMutex) #define SLEEP usleep #if defined(__LP64__) #define SIZET_BITS_1 63 #else #define SIZET_BITS_1 31 #endif #define BitScanReverseSizeT(pInd, mask) \ ({*(pInd) = SIZET_BITS_1 - __builtin_clzl( (mask) ); \ ( (mask)==0 )? 0 : 1; }) #define SECUREZEROMEMORY(dest, sz) ({ \ memset(dest, 0, sz); \ asm volatile("" ::: "memory"); \ }) #if __linux__ #include #include #define TRAP_DEBUGGER() do \ { \ if( ptrace(PTRACE_TRACEME, 0, 1, 0) == -1 ) { raise(SIGTRAP); } \ } while (false) #else #define TRAP_DEBUGGER() #endif // __linux__ #endif #if !defined( INCLUDE_IMPL_RSA32 ) #define INCLUDE_IMPL_RSA32 (1) #endif #if !defined( INCLUDE_IMPL_MSBIGNUM ) #define INCLUDE_IMPL_MSBIGNUM (1) #endif #if !defined( INCLUDE_IMPL_CAPI ) #define INCLUDE_IMPL_CAPI (1) #endif #if !defined( INCLUDE_IMPL_CNG ) #define INCLUDE_IMPL_CNG (1) #endif #if !defined( INCLUDE_IMPL_OPENSSL ) // OpenSSL implementation is disabled by default #define INCLUDE_IMPL_OPENSSL (0) #endif #if !defined( INCLUDE_IMPL_LIBCRUX ) // libcrux implementation is disabled by default #define INCLUDE_IMPL_LIBCRUX (0) #endif #if !defined( INCLUDE_IMPL_REF ) #define INCLUDE_IMPL_REF (1) #endif // // Our own header info // typedef std::string String; // String of characters typedef std::basic_string BString; // String of bytes #define ARRAY_SIZE( x ) (sizeof(x)/sizeof(x[0])) #define STRING_INT( x ) #x #define STRING( x ) STRING_INT( x ) // This extra macro indirection ensures we get enough macro expansion. #define LSTRING_INT( x ) L#x #define LSTRING( x ) LSTRING_INT( x ) #define CONCAT_I2( a, b ) a##b #define CONCAT_I3( a, b, c ) a##b##c #define CONCAT_I4( a, b, c, d ) a##b##c##d #define CONCAT2( a, b ) CONCAT_I2( a, b ) #define CONCAT3( a, b, c ) CONCAT_I3( a, b, c ) #define CONCAT4( a, b, c, d ) CONCAT_I4( a, b, c, d ) #define ImpXxx CONCAT2( Imp, IMP_Name ) #define AlgXxx CONCAT2( Alg, ALG_Name ) #define ModeXxx CONCAT2( Mode, ALG_Mode ) #define BaseAlgXxx CONCAT2( Alg, ALG_Base ) #define SCSHIM_Xxx(...) CONCAT2( ScShimSymCrypt, ALG_Name )(__VA_ARGS__) #define SCSHIM_XXX_STATE CONCAT3( SYMCRYPT_, ALG_NAME, _STATE ) #define SCSHIM_XXX_EXPANDED_KEY CONCAT3( SYMCRYPT_, ALG_NAME, _EXPANDED_KEY ) #define SCSHIM_XxxStateCopy(...) CONCAT3( ScShimSymCrypt, ALG_Name, StateCopy )(__VA_ARGS__) #define SCSHIM_XxxInit(...) CONCAT3( ScShimSymCrypt, ALG_Name, Init )(__VA_ARGS__) #define SCSHIM_XxxAppend(...) CONCAT3( ScShimSymCrypt, ALG_Name, Append )(__VA_ARGS__) #define SCSHIM_XxxResult(...) CONCAT3( ScShimSymCrypt, ALG_Name, Result )(__VA_ARGS__) #define SCSHIM_XxxResultEx(...) CONCAT3( ScShimSymCrypt, ALG_Name, ResultEx )(__VA_ARGS__) #define SCSHIM_XxxExtract(...) CONCAT3( ScShimSymCrypt, ALG_Name, Extract )(__VA_ARGS__) #define SCSHIM_XxxAppendBlocks(...) CONCAT3( ScShimSymCrypt, ALG_Name, AppendBlocks )(__VA_ARGS__) #define SCSHIM_XxxExpandKey(...) CONCAT3( ScShimSymCrypt, ALG_Name, ExpandKey )(__VA_ARGS__) #define SCSHIM_XxxExpandKeyEx(...) CONCAT3( ScShimSymCrypt, ALG_Name, ExpandKeyEx )(__VA_ARGS__) #define SCSHIM_XxxKeyCopy(...) CONCAT3( ScShimSymCrypt, ALG_Name, KeyCopy )(__VA_ARGS__) #define SCSHIM_XxxEncrypt(...) CONCAT3( ScShimSymCrypt, ALG_Name, Encrypt )(__VA_ARGS__) #define SCSHIM_XxxDecrypt(...) CONCAT3( ScShimSymCrypt, ALG_Name, Decrypt )(__VA_ARGS__) #define SCSHIM_XxxXxxEncrypt(...) CONCAT4( ScShimSymCrypt, ALG_Name, ALG_Mode, Encrypt )(__VA_ARGS__) #define SCSHIM_XxxXxxDecrypt(...) CONCAT4( ScShimSymCrypt, ALG_Name, ALG_Mode, Decrypt )(__VA_ARGS__) #define SCSHIM_XxxStateExport(...) CONCAT3( ScShimSymCrypt, ALG_Name, StateExport )(__VA_ARGS__) #define SCSHIM_XxxStateImport(...) CONCAT3( ScShimSymCrypt, ALG_Name, StateImport )(__VA_ARGS__) #define SCSHIM_XxxAlgorithm CONCAT3( ScShimSymCrypt, ALG_Name, Algorithm ) #define SCSHIM_BaseXxxAlgorithm CONCAT3( ScShimSymCrypt, ALG_Base, Algorithm ) #define SCSHIM_XXX_BLOCK_SIZE CONCAT3( SYMCRYPT_, ALG_NAME, _BLOCK_SIZE ) #define SCSHIM_XXX_INPUT_BLOCK_SIZE CONCAT3( SYMCRYPT_, ALG_NAME, _INPUT_BLOCK_SIZE ) #define SCSHIM_XXX_RESULT_SIZE CONCAT3( SYMCRYPT_, ALG_NAME, _RESULT_SIZE ) #define SCSHIM_XXX_STATE_EXPORT_SIZE CONCAT3( SYMCRYPT_, ALG_NAME, _STATE_EXPORT_SIZE ) #define RSA32_XXX_INPUT_BLOCK_SIZE CONCAT3( RSA32_, ALG_NAME, _INPUT_BLOCK_SIZE ) #define RSA32_XXX_RESULT_SIZE CONCAT3( RSA32_, ALG_NAME, _RESULT_SIZE ) #define RSA32_XXX_BLOCK_SIZE CONCAT3( RSA32_, ALG_NAME, _BLOCK_SIZE ) #define CNG_XXX_CHAIN_MODE CONCAT2( BCRYPT_CHAIN_MODE_, ALG_MODE ) #define CNG_XXX_HASH_ALG_NAMEU CONCAT3( Cng, ALG_Base, HashAlgNameU ) #define SYMCRYPT_2DES_BLOCK_SIZE SYMCRYPT_3DES_BLOCK_SIZE #define BCRYPT_2DES_ALGORITHM BCRYPT_3DES_112_ALGORITHM #define MAX_SIZE_T ((SIZE_T) -1) // // Discriminator classes, one for each algorithm. // These are used to specialize our algorithm implementation template classes. // class AlgMd2{ public: const static char * name; }; class AlgMd4{ public: const static char * name; }; class AlgMd5{ public: const static char * name; }; class AlgSha1{ public: const static char * name; }; class AlgSha256{ public: static constexpr const char * name = "Sha256"; }; class AlgSha384{ public: static constexpr const char * name = "Sha384"; }; class AlgSha512{ public: static constexpr const char * name = "Sha512"; }; class AlgSha3_256{ public: static constexpr const char * name = "Sha3-256"; }; class AlgSha3_384{ public: static constexpr const char * name = "Sha3-384"; }; class AlgSha3_512{ public: static constexpr const char * name = "Sha3-512"; }; class AlgShake128{ public: const static char * name; }; class AlgShake256{ public: const static char * name; }; class AlgCShake128{ public: const static char * name; }; class AlgCShake256{ public: const static char * name; }; class AlgKmac128{ public: const static char * name; }; class AlgKmac256{ public: const static char * name; }; class AlgHmacMd5{ public: const static char * name; }; class AlgHmacSha1{ public: const static char * name; }; class AlgHmacSha256{ public: const static char * name; }; class AlgHmacSha384{ public: const static char * name; }; class AlgHmacSha512{ public: const static char * name; }; class AlgHmacSha3_256{ public: const static char * name; }; class AlgHmacSha3_384{ public: const static char * name; }; class AlgHmacSha3_512{ public: const static char * name; }; class AlgAesCmac{ public: const static char * name; }; class AlgMarvin32{ public: const static char * name; }; class AlgAes{ public: const static char * name; }; class AlgDes{ public: const static char * name; }; class Alg2Des{ public: const static char * name; }; class Alg3Des{ public: const static char * name; }; class AlgDesx{ public: const static char * name; }; class AlgRc2{ public: const static char * name; }; class AlgRc4{ public: const static char * name; static BOOL isRandomAccess; }; class AlgChaCha20 { public: const static char * name; static BOOL isRandomAccess; }; class AlgPoly1305 { public: const static char * name; }; class AlgChaCha20Poly1305 { public: const static char* name; }; class AlgAesCtrDrbg{ public: const static char * name; }; class AlgAesCtrF142{ public: const static char * name; }; class AlgDynamicRandom{ public: const static char * name; }; class AlgParallelSha256{ public: const static char * name; const static WCHAR * pwstrBasename; // e.g. L"SHA256" }; class AlgParallelSha384{ public: const static char * name; const static WCHAR * pwstrBasename; }; class AlgParallelSha512{ public: const static char * name; const static WCHAR * pwstrBasename; }; class AlgPbkdf2{ public: const static char * name; }; class AlgSp800_108{ public: const static char * name; }; class AlgTlsPrf1_1{ public: const static char * name; }; class AlgTlsPrf1_2{ public: const static char * name; }; class AlgSshKdf{ public: const static char * name; }; class AlgSrtpKdf{ public: const static char * name; }; class AlgHkdf{ public: const static char * name; }; class AlgSskdfMac{ public: const static char * name; }; class AlgSskdfHash{ public: const static char * name; }; class AlgXtsAes{ public: const static char * name; }; class AlgTlsCbcHmacSha1 { public: const static char * name; }; class AlgTlsCbcHmacSha256 { public: const static char * name; }; class AlgTlsCbcHmacSha384 { public: const static char * name; }; #define MODE_FLAG_CHAIN 1 #define MODE_FLAG_CFB 2 class ModeEcb{ public: const static char * name; static ULONG flags; }; class ModeCbc{ public: const static char * name; static ULONG flags; }; class ModeCfb{ public: const static char * name; static ULONG flags; }; class ModeCcm{ public: const static char * name; }; class ModeGcm{ public: const static char * name; }; class ModeNone { public: const static char* name; }; class AlgIntAdd{ public: const static char * name; }; class AlgIntSub{ public: const static char * name; }; class AlgIntMul{ public: const static char * name; }; class AlgIntSquare{ public: const static char * name; }; class AlgIntDivMod{ public: const static char * name; }; class AlgModAdd{ public: const static char * name; }; class AlgModSub{ public: const static char * name; }; class AlgModMul{ public: const static char * name; }; class AlgModSquare{ public: const static char * name; }; class AlgModInv{ public: const static char * name; }; class AlgModExp{ public: const static char * name; }; class AlgScsTable{ public: const static char * name; }; class AlgIEEE802_11SaeCustom{ public: const static char * name; }; class AlgTrialDivision{ public: const static char * name; }; class AlgTrialDivisionContext{ public: const static char * name; }; class AlgWipe{ public: const static char * name; }; class AlgRsaEncRaw{ public: const static char * name; }; class AlgRsaEncPkcs1{ public: const static char * name; }; class AlgRsaEncOaep{ public: const static char * name; }; class AlgRsaSignPkcs1{ public: const static char * name; }; class AlgRsaSignPss{ public: const static char * name; }; class AlgDsaSign{ public: const static char * name; }; class AlgDsaVerify{ public: const static char * name; }; class AlgDh{ public: const static char * name; }; class AlgDsa{ public: const static char * name; }; class AlgEcurveAllocate{ public: const static char * name; }; class AlgEckeySetRandom{ public: const static char * name; }; class AlgEcpointSetZero{ public: const static char * name; }; class AlgEcpointSetDistinguished{ public: const static char * name; }; class AlgEcpointSetRandom{ public: const static char * name; }; class AlgEcpointIsEqual{ public: const static char * name; }; class AlgEcpointIsZero{ public: const static char * name; }; class AlgEcpointOnCurve{ public: const static char * name; }; class AlgEcpointAdd{ public: const static char * name; }; class AlgEcpointAddDiffNz{ public: const static char * name; }; class AlgEcpointDouble{ public: const static char * name; }; class AlgEcpointScalarMul{ public: const static char * name; }; class AlgEcdsaSign{ public: const static char * name; }; class AlgEcdsaVerify{ public: const static char * name; }; class AlgEcdh{ public: const static char * name; }; class AlgXmss { public: const static char * name; }; class AlgMlKem{ public: const static char * name; }; // Used only for performance testing // In ML-KEM, an important operation is importing an encapsulation key to a key object class AlgMlKemkeySetValue{ public: const static char * name; }; class AlgDeveloperTest{ public: const static char * name; }; // // Macros for easy testing // #define FATAL( text ) {fatal( __FILE__, __LINE__, text );} #define FATAL2( text, a ) {fatal( __FILE__, __LINE__, text, a );} #define FATAL3( text, a, b ) {fatal( __FILE__, __LINE__, text, a, b );} #define FATAL4( text, a, b, c ) {fatal( __FILE__, __LINE__, text, a, b, c );} #define FATAL5( text, a, b, c, d ) {fatal( __FILE__, __LINE__, text, a, b, c, d );} #define FATAL6( text, a, b, c, d, e ) {fatal( __FILE__, __LINE__, text, a, b, c, d, e );} #define CHECK( cond, text ) { if( !(cond) ) { fatal(__FILE__, __LINE__, text );}; _Analysis_assume_( cond );} #define CHECK3( cond, text, a ) { if( !(cond) ) { fatal(__FILE__, __LINE__, text, a );}; _Analysis_assume_( cond );} #define CHECK4( cond, text, a, b ) { if( !(cond) ) { fatal(__FILE__, __LINE__, text, a, b );}; _Analysis_assume_( cond );} #define CHECK5( cond, text, a, b, c ) { if( !(cond) ) { fatal(__FILE__, __LINE__, text, a, b, c );}; _Analysis_assume_( cond );} #define SOFTCHECK( cond, text ) if( !(cond) ) { print( "%s(%d): %s\n", __FILE__, __LINE__, text ); } extern DWORD g_osVersion; // 0xaabb for major version aa and minor version bb #define OS_VERSION_VISTA 0x0600 #define OS_VERSION_WIN7 0x0601 #define OS_VERSION_WIN8 0x0602 #define OS_VERSION_WIN8_1 0x0603 _Analysis_noreturn_ VOID fatal( _In_ PCSTR file, ULONG line, _In_ PCSTR text, ... ); typedef CONST CHAR * PCCHAR; #include "kat.h" #include "rng.h" #include "perf.h" extern SIZE_T g_modeCfbShiftParam; #include "algorithm_base.h" typedef std::vector AlgorithmImplementationVector; extern AlgorithmImplementationVector g_algorithmImplementation; #include "perfprint.h" typedef std::set StringSet; extern StringSet g_algorithmsToTest; extern StringSet g_implementationsToTest; BOOL setContainsPrefix( const StringSet & set, const std::string & str ); #include "main_inline.h" #include "resultMerge.h" extern const char * g_implementationNames[]; // // Include the info from the implementations we support on this compilation // // We always include the SymCrypt implementation #include "sc_implementations.h" #if INCLUDE_IMPL_CAPI #include "capi_implementations.h" #endif #if INCLUDE_IMPL_CNG #include "cng_implementations.h" #endif #if INCLUDE_IMPL_MSBIGNUM #include "msbignum_implementations.h" #endif #if INCLUDE_IMPL_REF #include "ref_implementations.h" #endif #if INCLUDE_IMPL_RSA32 #include "rsa32_implementations.h" #endif #if INCLUDE_IMPL_OPENSSL #include "openssl_implementations.h" #endif #if INCLUDE_IMPL_LIBCRUX #include "libcrux_implementations.h" #endif #include "printtable.h" #include "rndDriver.h" extern Rng g_rng; extern BOOL g_showPerfRangeInfo; extern BOOL g_verbose; extern BOOL g_profile; extern UINT32 g_profile_iterations; extern UINT32 g_profile_key; extern BOOL g_measure_specific_sizes; extern UINT32 g_measure_sizes_start; extern UINT32 g_measure_sizes_end; extern UINT32 g_measure_sizes_increment; extern UINT32 g_measure_sizes_repetitions; extern String g_measure_sizes_stringPrefix; extern BOOL g_perfTestsRunning; extern ULONG g_rc2EffectiveKeyLength; extern ULONG g_cngKeySizeFlag; extern double g_tscFreq; extern BOOL g_sgx; extern PVOID g_dynamicSymCryptModuleHandle; extern BOOL g_useDynamicFunctionsInTestCall; // Environment specific functions for handling dynamic modules PVOID loadDynamicModuleFromPath(PCSTR dynamicModulePath); // dlopen on Linux, LoadLibraryA on Windows typedef enum { SCTEST_DYNSYM_FUNCTION_PTR = 1, SCTEST_DYNSYM_SYMBOL_PTR = 2, SCTEST_DYNSYM_ARRAY = 3, } SCTEST_DYNSYM_TYPE; PVOID getDynamicSymbolPointerFromString(PVOID hModule, PCSTR pSymbolName, SCTEST_DYNSYM_TYPE symbolType); // dlsym on Linux, GetProcAddress on Windows // // We distinguish between looking up function pointers and symbols // Looked up function pointers must be callable by the unit test executable, so the // pointers must be to functions in the address space of the unit tests, which invoke // the SymCrypt API in the module under test // // Looked up symbols may or may not be in the address space of the unit tests. // Looked up extern arrays (i.e. SymCryptSha256OidList) are _not_ dereferenced by the unit tests // before being passed back to dynamic SymCrypt functions. They must be a symbol address which is // directly consumed by the eventual SymCrypt module under test (i.e. may not be in the address // space of the unit tests) // Looked up extern pointers (i.e. SymCryptSha256Algorithm) _are_ dereferenced by the unit tests // before being passed back to dynamic SymCrypt functions. They must be an address in the unit tests' // address space which contains a value of the pointer which is consumed by the SymCrypt module under // test SYMCRYPT_CPU_FEATURES SctestDisableCpuFeatures(SYMCRYPT_CPU_FEATURES disable); // Optional function that dynamic test modules may expose to enable the unit tests to disable certain // CPU features from being used. // // If present must only be called once just after a call to SymCryptModuleInit as some test modules may // defer full initialization until they know which features to disable. We do it this way as CPU features // may affect the memory layout of internal SymCrypt structures, so for the lifetime of the module the // CPU features available must be consistent. // // Returns the CPU features mask that will be used in the dynamic test module. // // Currently assumes that the unit test binary will have the same CPU architecture as the module under test VOID initVectorRegisters(); VOID verifyVectorRegisters(); VOID cleanVectorRegisters(); // // Wrappers for calls into SymCrypt which check that vector registers are saved/restored appropriately // // initVectorRegisters sets up vector registers to be in a state that should not be modified by a call // verifyVectorRegisters checks that the state that should not have been modified has not been modified // // These additional calls may do nothing if TestSaveXXXEnabled is FALSE, but it can also: // On Windows AMD64 set Xmm6-Xmm15 to random values // these values are non-volatile in Window x64 ABI, so should be preserved. If they are not // preserved it indicates a problem with our assembly not adhering to the Windows ABI // On Linux AMD64 set Ymm0-Ymm15 to random values // these values are naturally volatile on Linux, but symcryptunittest callers may specify the // following environment variable: // GLIBC_TUNABLES=glibc.cpu.hwcaps=-AVX_Usable,-AVX_Fast_Unaligned_Load,-AVX2_Usable // to avoid use of AVX in glibc. This means we can test the Ymm save/restore logic that is // used in Windows kernel using Linux user mode. // template auto ScTestCallFunctionWithVectorRegistersTest(Functor f, Args&&... args) -> typename std::enable_if < std::is_same(args)...)), void>::value, void>::type { initVectorRegisters(); f(std::forward(args)...); verifyVectorRegisters(); return; } template auto ScTestCallFunctionWithVectorRegistersTest(Functor f, Args&&... args) -> typename std::enable_if < !std::is_same(args)...)), void>::value, decltype(f(std::forward(args)...))>::type { initVectorRegisters(); auto result = f(std::forward(args)...); verifyVectorRegisters(); return result; } // // Lookup dynamic symbol, may return NULL if symbol cannot be found // // Note that because we use static variables here, 1 call to getDynamicSymbolPointerFromString (the // actual environment specific dynamic symbol lookup function) is performed per scope in which this // lambda function is instantiated // This means we have a few more (maybe ~10x - depending on how many locations lookup the same symbol) // dynamic symbol lookups than are strictly needed, but it does not materially impact on unit test // runtime, and our performance testing infrastructure can easily handle the first run of a function // of interest being more costly // // We have the IsCallable parameter to distinguish between symbols the unit tests are looking up in // the module to call vs. symbols the module is looking up to pass back to the module. // #define SCTEST_LOOKUP_DYNSYM(SymCryptSymbol, IsCallable) \ []() { \ static PVOID dynamicSymbolStatic = NULL; \ static bool lookupAttempted = false; \ if (!lookupAttempted) \ { \ SCTEST_DYNSYM_TYPE symbolType = SCTEST_DYNSYM_SYMBOL_PTR; \ if( IsCallable ) \ { \ symbolType = SCTEST_DYNSYM_FUNCTION_PTR; \ } else if( std::is_array::value ) { \ symbolType = SCTEST_DYNSYM_ARRAY; \ } \ dynamicSymbolStatic = getDynamicSymbolPointerFromString(g_dynamicSymCryptModuleHandle, #SymCryptSymbol, symbolType); \ lookupAttempted = true; \ } \ return (decltype(&SymCryptSymbol)) dynamicSymbolStatic; \ }() // Get dynamic symbol - Fatal if symbol cannot be found #define SCTEST_GET_DYNSYM(SymCryptSymbol, IsCallable) \ []() { \ decltype(&SymCryptSymbol) dynamicSymbol = SCTEST_LOOKUP_DYNSYM(SymCryptSymbol, IsCallable); \ CHECK4(dynamicSymbol != NULL, "Could not find %s %s", #SymCryptSymbol, "Function" ); \ return dynamicSymbol; \ }() // In a template for ImpSc call statically linked function with Vector register save/restore tests // In a template for ImpScStatic call statically linked function directly // In a template for ImpScDynamic call dynamically linked function #define SCTEST_CALL_SCIMPFN(SymCryptFunction, ...) \ [&]() { \ if constexpr ( std::is_same::value ) \ { \ return ScTestCallFunctionWithVectorRegistersTest(SymCryptFunction, __VA_ARGS__); \ } \ else if constexpr ( std::is_same::value ) \ { \ return SymCryptFunction(__VA_ARGS__); \ } \ else if constexpr ( std::is_same::value ) \ { \ return SCTEST_GET_DYNSYM(SymCryptFunction, TRUE)(__VA_ARGS__); \ } \ else \ { \ CHECK(FALSE, "Instantiation of SCTEST_CALL_SCIMPFN in unexpected scope"); \ } \ }() // In a template for ImpSc or ImpScStatic return pointer to statically linked symbol // In a template for ImpScDynamic return pointer to dynamically linked symbol if it is available #define SCTEST_LOOKUP_SCIMPSYM(SymCryptSymbol) \ []() { \ if constexpr ( std::is_same::value || \ std::is_same::value ) \ { \ return &SymCryptSymbol; \ } \ else if constexpr ( std::is_same::value ) \ { \ return SCTEST_LOOKUP_DYNSYM(SymCryptSymbol, FALSE); \ } \ else \ { \ CHECK(FALSE, "Instantiation of SCTEST_LOOKUP_SCIMPSYM in unexpected scope"); \ } \ }() // In a template for ImpSc or ImpScStatic return statically linked symbol // In a template for ImpScDynamic return dynamically linked symbol - Fatal if it cannot be found #define SCTEST_GET_SCIMPSYM(SymCryptSymbol) \ []() { \ decltype(&SymCryptSymbol) dynamicSymbol = SCTEST_LOOKUP_SCIMPSYM(SymCryptSymbol); \ CHECK3(dynamicSymbol != NULL, "Could not find symbol %s", #SymCryptSymbol); \ return *dynamicSymbol; \ }() // Some tests do not use the multi-implementation setup with templates, but instead call the SymCrypt // API directly. We can refactor these tests to optionally call the static or dynamic functions based // on the value of g_useDynamicFunctionsInTestCall, using the following SCTEST_CALL_DISPATCHFN macros #define SCTEST_CALL_DISPATCHFN_0(SymCryptFunction) \ []() { \ if( g_useDynamicFunctionsInTestCall ) \ { \ return SCTEST_GET_DYNSYM(SymCryptFunction, TRUE)(); \ } \ return ScTestCallFunctionWithVectorRegistersTest(SymCryptFunction); \ }() #define SCTEST_CALL_DISPATCHFN(SymCryptFunction, ...) \ [&]() { \ if( g_useDynamicFunctionsInTestCall ) \ { \ return SCTEST_GET_DYNSYM(SymCryptFunction, TRUE)(__VA_ARGS__); \ } \ return ScTestCallFunctionWithVectorRegistersTest(SymCryptFunction, __VA_ARGS__); \ }() #define SCTEST_LOOKUP_DISPATCHSYM(SymCryptSymbol) \ []() { \ if( g_useDynamicFunctionsInTestCall ) \ { \ return SCTEST_LOOKUP_DYNSYM(SymCryptSymbol, FALSE); \ } \ return &SymCryptSymbol; \ }() #define SCTEST_GET_DISPATCHSYM(SymCryptSymbol) \ []() { \ decltype(&SymCryptSymbol) dynamicSymbol = SCTEST_LOOKUP_DISPATCHSYM(SymCryptSymbol); \ CHECK3(dynamicSymbol != NULL, "Could not find symbol %s", #SymCryptSymbol); \ return *dynamicSymbol; \ }() #include "sc_dispatch_shims.h" template< typename AlgType > std::unique_ptr> getAlgorithmsOfOneType( ); extern BOOLEAN TestSelftestsEnabled; extern BOOLEAN TestSaveXmmEnabled; extern BOOLEAN TestSaveYmmEnabled; extern ULONGLONG TestFatalCount; extern ULONGLONG TestErrorInjectionCount; extern ULONGLONG TestErrorInjectionCalls; extern ULONG TestErrorInjectionProb; extern BYTE TestErrorInjectionSeed[ SYMCRYPT_SHA1_RESULT_SIZE ]; #if SYMCRYPT_CPU_X86 | SYMCRYPT_CPU_AMD64 // // These Save/Restore functions are used by user mode SaveXmm and Ymm code, plus the testing code. // extern "C" { VOID SYMCRYPT_CALL SymCryptEnvUmSaveXmmRegistersAsm( __m128i * buffer ); VOID SYMCRYPT_CALL SymCryptEnvUmRestoreXmmRegistersAsm( __m128i * buffer ); VOID SYMCRYPT_CALL SymCryptEnvUmSaveYmmRegistersAsm( __m256i * buffer ); VOID SYMCRYPT_CALL SymCryptEnvUmRestoreYmmRegistersAsm( __m256i * buffer ); } #endif VOID testWipe(); VOID testUtil(); VOID testHashAlgorithms(); VOID testMacAlgorithms(); VOID testXofAlgorithms(); VOID testCustomizableXofAlgorithms(); VOID testKmacAlgorithms(); VOID testBlockCipherAlgorithms(); VOID testAuthEncAlgorithms(); VOID testStreamCipherAlgorithms(); VOID testKdfAlgorithms(); VOID testXtsAlgorithms(); VOID testIEEE802_11SaeCustom(); VOID testTlsCbcHmacAlgorithms(); VOID testAesCtrDrbg(); VOID testArithmetic(); VOID testKem(); VOID testScsTable(); VOID testScsTools(); VOID testPaddingPkcs7(); VOID testEcc(); VOID testRsaSignAlgorithms(); VOID testRsaEncAlgorithms(); VOID testDhAlgorithms(); VOID testDsaAlgorithms(); VOID testStatusIndicator(BOOL); VOID testHbs(); KatData * getCustomResource( _In_ PSTR resourceName, _In_ PSTR resourceType ); VOID randomTestGetSubstringPosition( _In_reads_( bufSize ) PCBYTE buf, SIZE_T bufSize, _Inout_ SIZE_T * idx, _Out_ SIZE_T * pos, _Out_ SIZE_T * len ); VOID measurePerf( AlgorithmImplementation * pAlgImp ); VOID measurePerfOfWipe(); VOID initPerfSystem(); VOID testSelftestPerf(); VOID testSelftest(); CHAR charToLower( CHAR c ); #define PERF_WIPE_MAX_SIZE 64 #define PERF_WIPE_N_OFFSETS 16 extern double g_wipePerf[PERF_WIPE_MAX_SIZE+1][PERF_WIPE_N_OFFSETS]; VOID addAllAlgs(); VOID addCapiAlgs(); VOID addCngAlgs(); VOID addRsa32Algs(); VOID addMsBignumAlgs(); VOID addSymCryptAlgs(); VOID updateSymCryptStaticAlgs(); VOID addRefAlgs(); VOID initTestInfrastructure( int argc, _In_reads_( argc ) char * argv[] ); VOID runFunctionalTests(); VOID runPerfTests(); VOID runProfiling(); VOID exitTestInfrastructure(); // // Function pointers to deal with various BCrypt versions // #if INCLUDE_IMPL_CNG typedef _Must_inspect_result_ NTSTATUS (WINAPI * BCryptDeriveKeyPBKDF2Fn)( _In_ BCRYPT_ALG_HANDLE hPrf, _In_reads_bytes_( cbPassword ) PUCHAR pbPassword, _In_ ULONG cbPassword, _In_reads_bytes_opt_( cbSalt ) PUCHAR pbSalt, _In_ ULONG cbSalt, _In_ ULONGLONG cIterations, _Out_writes_bytes_( cbDerivedKey ) PUCHAR pbDerivedKey, _In_ ULONG cbDerivedKey, _In_ ULONG dwFlags); typedef _Must_inspect_result_ NTSTATUS (WINAPI * BCryptKeyDerivationFn)( _In_ BCRYPT_KEY_HANDLE hKey, _In_opt_ BCryptBufferDesc *pParameterList, _Out_writes_bytes_to_(cbDerivedKey, *pcbResult) PUCHAR pbDerivedKey, _In_ ULONG cbDerivedKey, _Out_ ULONG *pcbResult, _In_ ULONG dwFlags); typedef _Must_inspect_result_ NTSTATUS (WINAPI * BCryptCreateMultiHashFn)( _Inout_ BCRYPT_ALG_HANDLE hAlgorithm, _Out_ BCRYPT_HASH_HANDLE *phHash, _In_ ULONG nHashes, _Out_writes_bytes_all_opt_(cbHashObject) PUCHAR pbHashObject, _In_ ULONG cbHashObject, _In_reads_bytes_opt_(cbSecret) PUCHAR pbSecret, // optional _In_ ULONG cbSecret, // optional _In_ ULONG dwFlags); typedef _Must_inspect_result_ NTSTATUS (WINAPI * BCryptProcessMultiOperationsFn)( _Inout_ BCRYPT_HANDLE hObject, _In_ BCRYPT_MULTI_OPERATION_TYPE operationType, _In_reads_bytes_(cbOperations) PVOID pOperations, _In_ ULONG cbOperations, _In_ ULONG dwFlags ); typedef _Must_inspect_result_ NTSTATUS (WINAPI * BCryptOpenAlgorithmProviderFn)( _Out_ BCRYPT_ALG_HANDLE *phAlgorithm, _In_ LPCWSTR pszAlgId, _In_opt_ LPCWSTR pszImplementation, _In_ ULONG dwFlags); typedef _Must_inspect_result_ NTSTATUS (WINAPI * BCryptGetPropertyFn)( _In_ BCRYPT_HANDLE hObject, _In_ LPCWSTR pszProperty, _Out_writes_bytes_to_opt_(cbOutput, *pcbResult) PUCHAR pbOutput, _In_ ULONG cbOutput, _Out_ ULONG *pcbResult, _In_ ULONG dwFlags); typedef _Must_inspect_result_ NTSTATUS (WINAPI * BCryptSetPropertyFn)( _Inout_ BCRYPT_HANDLE hObject, _In_ LPCWSTR pszProperty, _In_reads_bytes_(cbInput) PUCHAR pbInput, _In_ ULONG cbInput, _In_ ULONG dwFlags); typedef _Must_inspect_result_ NTSTATUS (WINAPI * BCryptCloseAlgorithmProviderFn)( _Inout_ BCRYPT_ALG_HANDLE hAlgorithm, _In_ ULONG dwFlags); typedef _Must_inspect_result_ NTSTATUS (WINAPI * BCryptGenerateSymmetricKeyFn)( _Inout_ BCRYPT_ALG_HANDLE hAlgorithm, _Out_ BCRYPT_KEY_HANDLE *phKey, _Out_writes_bytes_all_opt_(cbKeyObject) PUCHAR pbKeyObject, _In_ ULONG cbKeyObject, _In_reads_bytes_(cbSecret) PUCHAR pbSecret, _In_ ULONG cbSecret, _In_ ULONG dwFlags); typedef _Must_inspect_result_ NTSTATUS (WINAPI * BCryptGenerateKeyPairFn)( _Inout_ BCRYPT_ALG_HANDLE hAlgorithm, _Out_ BCRYPT_KEY_HANDLE *phKey, _In_ ULONG dwLength, _In_ ULONG dwFlags); typedef _Must_inspect_result_ NTSTATUS (WINAPI * BCryptEncryptFn)( _Inout_ BCRYPT_KEY_HANDLE hKey, _In_reads_bytes_opt_(cbInput) PUCHAR pbInput, _In_ ULONG cbInput, _In_opt_ VOID *pPaddingInfo, _Inout_updates_bytes_opt_(cbIV) PUCHAR pbIV, _In_ ULONG cbIV, _Out_writes_bytes_to_opt_(cbOutput, *pcbResult) PUCHAR pbOutput, _In_ ULONG cbOutput, _Out_ ULONG *pcbResult, _In_ ULONG dwFlags); typedef _Must_inspect_result_ NTSTATUS (WINAPI * BCryptDecryptFn)( _Inout_ BCRYPT_KEY_HANDLE hKey, _In_reads_bytes_opt_(cbInput) PUCHAR pbInput, _In_ ULONG cbInput, _In_opt_ VOID *pPaddingInfo, _Inout_updates_bytes_opt_(cbIV) PUCHAR pbIV, _In_ ULONG cbIV, _Out_writes_bytes_to_opt_(cbOutput, *pcbResult) PUCHAR pbOutput, _In_ ULONG cbOutput, _Out_ ULONG *pcbResult, _In_ ULONG dwFlags); typedef _Must_inspect_result_ NTSTATUS (WINAPI * BCryptExportKeyFn)( _In_ BCRYPT_KEY_HANDLE hKey, _In_opt_ BCRYPT_KEY_HANDLE hExportKey, _In_ LPCWSTR pszBlobType, _Out_writes_bytes_to_opt_(cbOutput, *pcbResult) PUCHAR pbOutput, _In_ ULONG cbOutput, _Out_ ULONG *pcbResult, _In_ ULONG dwFlags); typedef _Must_inspect_result_ NTSTATUS (WINAPI * BCryptImportKeyFn)( _In_ BCRYPT_ALG_HANDLE hAlgorithm, _In_opt_ BCRYPT_KEY_HANDLE hImportKey, _In_ LPCWSTR pszBlobType, _Out_ BCRYPT_KEY_HANDLE *phKey, _Out_writes_bytes_all_opt_(cbKeyObject) PUCHAR pbKeyObject, _In_ ULONG cbKeyObject, _In_reads_bytes_(cbInput) PUCHAR pbInput, _In_ ULONG cbInput, _In_ ULONG dwFlags); typedef _Must_inspect_result_ NTSTATUS (WINAPI * BCryptImportKeyPairFn)( _In_ BCRYPT_ALG_HANDLE hAlgorithm, _In_opt_ BCRYPT_KEY_HANDLE hImportKey, _In_ LPCWSTR pszBlobType, _Out_ BCRYPT_KEY_HANDLE *phKey, _In_reads_bytes_(cbInput) PUCHAR pbInput, _In_ ULONG cbInput, _In_ ULONG dwFlags); typedef _Must_inspect_result_ NTSTATUS (WINAPI * BCryptDuplicateKeyFn)( _In_ BCRYPT_KEY_HANDLE hKey, _Out_ BCRYPT_KEY_HANDLE *phNewKey, _Out_writes_bytes_all_opt_(cbKeyObject) PUCHAR pbKeyObject, _In_ ULONG cbKeyObject, _In_ ULONG dwFlags); typedef _Must_inspect_result_ NTSTATUS (WINAPI * BCryptFinalizeKeyPairFn)( _Inout_ BCRYPT_KEY_HANDLE hKey, _In_ ULONG dwFlags); typedef _Must_inspect_result_ NTSTATUS (WINAPI * BCryptDestroyKeyFn)( _Inout_ BCRYPT_KEY_HANDLE hKey); typedef _Must_inspect_result_ NTSTATUS (WINAPI * BCryptDestroySecretFn)( _Inout_ BCRYPT_SECRET_HANDLE hSecret); typedef _Must_inspect_result_ NTSTATUS (WINAPI * BCryptSignHashFn)( _In_ BCRYPT_KEY_HANDLE hKey, _In_opt_ VOID *pPaddingInfo, _In_reads_bytes_(cbInput) PUCHAR pbInput, _In_ ULONG cbInput, _Out_writes_bytes_to_opt_(cbOutput, *pcbResult) PUCHAR pbOutput, _In_ ULONG cbOutput, _Out_ ULONG *pcbResult, _In_ ULONG dwFlags); typedef _Must_inspect_result_ NTSTATUS (WINAPI * BCryptVerifySignatureFn)( _In_ BCRYPT_KEY_HANDLE hKey, _In_opt_ VOID *pPaddingInfo, _In_reads_bytes_(cbHash) PUCHAR pbHash, _In_ ULONG cbHash, _In_reads_bytes_(cbSignature) PUCHAR pbSignature, _In_ ULONG cbSignature, _In_ ULONG dwFlags); typedef _Must_inspect_result_ NTSTATUS (WINAPI * BCryptSecretAgreementFn)( _In_ BCRYPT_KEY_HANDLE hPrivKey, _In_ BCRYPT_KEY_HANDLE hPubKey, _Out_ BCRYPT_SECRET_HANDLE *phAgreedSecret, _In_ ULONG dwFlags); typedef _Must_inspect_result_ NTSTATUS (WINAPI * BCryptDeriveKeyFn)( _In_ BCRYPT_SECRET_HANDLE hSharedSecret, _In_ LPCWSTR pwszKDF, _In_opt_ BCryptBufferDesc *pParameterList, _Out_writes_bytes_to_opt_(cbDerivedKey, *pcbResult) PUCHAR pbDerivedKey, _In_ ULONG cbDerivedKey, _Out_ ULONG *pcbResult, _In_ ULONG dwFlags); typedef _Must_inspect_result_ NTSTATUS (WINAPI * BCryptHashFn)( _Inout_ BCRYPT_ALG_HANDLE hAlgorithm, _In_reads_bytes_opt_(cbSecret) PUCHAR pbSecret, // for keyed algs _In_ ULONG cbSecret, // for keyed algs _In_reads_bytes_(cbInput) PUCHAR pbInput, _In_ ULONG cbInput, _Out_writes_bytes_all_(cbOutput) PUCHAR pbOutput, _In_ ULONG cbOutput); typedef _Must_inspect_result_ NTSTATUS (WINAPI * BCryptCreateHashFn)( _Inout_ BCRYPT_ALG_HANDLE hAlgorithm, _Out_ BCRYPT_HASH_HANDLE *phHash, _Out_writes_bytes_all_opt_(cbHashObject) PUCHAR pbHashObject, _In_ ULONG cbHashObject, _In_reads_bytes_opt_(cbSecret) PUCHAR pbSecret, // optional _In_ ULONG cbSecret, // optional _In_ ULONG dwFlags); typedef _Must_inspect_result_ NTSTATUS (WINAPI * BCryptHashDataFn)( _Inout_ BCRYPT_HASH_HANDLE hHash, _In_reads_bytes_(cbInput) PUCHAR pbInput, _In_ ULONG cbInput, _In_ ULONG dwFlags); typedef _Must_inspect_result_ NTSTATUS (WINAPI * BCryptFinishHashFn)( _Inout_ BCRYPT_HASH_HANDLE hHash, _Out_writes_bytes_all_(cbOutput) PUCHAR pbOutput, _In_ ULONG cbOutput, _In_ ULONG dwFlags); typedef _Must_inspect_result_ NTSTATUS (WINAPI * BCryptDuplicateHashFn)( _In_ BCRYPT_HASH_HANDLE hHash, _Out_ BCRYPT_HASH_HANDLE *phNewHash, _Out_writes_bytes_all_opt_(cbHashObject) PUCHAR pbHashObject, _In_ ULONG cbHashObject, _In_ ULONG dwFlags); typedef _Must_inspect_result_ NTSTATUS (WINAPI * BCryptDestroyHashFn)( _Inout_ BCRYPT_HASH_HANDLE hHash); typedef _Must_inspect_result_ NTSTATUS (WINAPI * BCryptGenRandomFn)( _In_opt_ BCRYPT_ALG_HANDLE hAlgorithm, _Out_writes_bytes_(cbBuffer) PUCHAR pbBuffer, _In_ ULONG cbBuffer, _In_ ULONG dwFlags); typedef _Must_inspect_result_ NTSTATUS (WINAPI * BCryptDeriveKeyCapiFn)( _In_ BCRYPT_HASH_HANDLE hHash, _In_opt_ BCRYPT_ALG_HANDLE hTargetAlg, _Out_writes_bytes_(cbDerivedKey) PUCHAR pbDerivedKey, _In_ ULONG cbDerivedKey, _In_ ULONG dwFlags); extern BCryptDeriveKeyPBKDF2Fn CngPbkdf2Fn; extern BCryptKeyDerivationFn CngKeyDerivationFn; extern BCryptCreateMultiHashFn CngCreateMultiHashFn; extern BCryptProcessMultiOperationsFn CngProcessMultiOperationsFn; extern BCryptCloseAlgorithmProviderFn CngCloseAlgorithmProviderFn; extern BCryptCreateHashFn CngCreateHashFn; extern BCryptDecryptFn CngDecryptFn; extern BCryptDeriveKeyFn CngDeriveKeyFn; extern BCryptDeriveKeyCapiFn CngDeriveKeyCapiFn; extern BCryptDestroyHashFn CngDestroyHashFn; extern BCryptDestroyKeyFn CngDestroyKeyFn; extern BCryptDestroySecretFn CngDestroySecretFn; extern BCryptDuplicateHashFn CngDuplicateHashFn; extern BCryptDuplicateKeyFn CngDuplicateKeyFn; extern BCryptEncryptFn CngEncryptFn; extern BCryptExportKeyFn CngExportKeyFn; extern BCryptFinalizeKeyPairFn CngFinalizeKeyPairFn; extern BCryptFinishHashFn CngFinishHashFn; extern BCryptGenerateKeyPairFn CngGenerateKeyPairFn; extern BCryptGenerateSymmetricKeyFn CngGenerateSymmetricKeyFn; extern BCryptGenRandomFn CngGenRandomFn; extern BCryptGetPropertyFn CngGetPropertyFn; extern BCryptHashFn CngHashFn; extern BCryptHashDataFn CngHashDataFn; extern BCryptImportKeyFn CngImportKeyFn; extern BCryptImportKeyPairFn CngImportKeyPairFn; extern BCryptOpenAlgorithmProviderFn CngOpenAlgorithmProviderFn; extern BCryptSecretAgreementFn CngSecretAgreementFn; extern BCryptSetPropertyFn CngSetPropertyFn; extern BCryptSignHashFn CngSignHashFn; extern BCryptVerifySignatureFn CngVerifySignatureFn; #endif //SYMCRYPT_MS_VC extern BOOLEAN g_fExitMultithreadTest; extern ULONGLONG g_nMultithreadTestsRun; typedef VOID (SYMCRYPT_CALL * SelfTestFn)(); typedef struct _SELFTEST_INFO { SelfTestFn f; LPSTR name; } SELFTEST_INFO; extern const SELFTEST_INFO g_selfTests[]; // Some selftests require allocations, and we do not support them in KM test driver yet extern const SELFTEST_INFO g_selfTests_allocating[]; VOID runTestThread( VOID * seed ); VOID printHexArray( PCBYTE pData, SIZE_T nElements, SIZE_T elementSize ); #define XMM_SAVE_ERR 4506 extern "C" { extern ULONG g_nXmmSaves; VOID printXmmRegisters( PCSTR text ); } #define MAX_INT_BITS (1 << 10) #define MAX_INT_BYTES (MAX_INT_BITS/8) #define PERF_KEY_FLAGS_MASK (0xff000000) // // For testing the different moduli types, we signal the type of modulus in the upper bits of the size parameter. // #define PERF_KEY_SECRET 0x01000000 // Modulus is secret (Requires generic implementation) #define PERF_KEY_PUB_ODD 0x02000000 // Modulus parity is public & odd (allows Montgomery reduction) #define PERF_KEY_PUBLIC 0x03000000 // Modulus is public #define PERF_KEY_PUB_PM 0x04000000 // Modulus is public & Pseudo-Mersenne #define PERF_KEY_PUB_NIST 0x05000000 // Modulus is public & NIST curve prime // // For testing the different XTS data unit sizes // #define PERF_KEY_XTS_DATA_UNIT_512 0x06000000 // 512-byte data unit #define PERF_KEY_XTS_DATA_UNIT_4096 0x07000000 // 4096-byte data unit #define PERF_KEY_PRIME 0x80000000 // Modulus is prime (orthogonal to the other flags) // // For testing the different internal curves // The first byte denotes the type of curve while the lower bytes the field length // #define PERF_KEY_NIST_CURVE 0x10000000 // NIST curve #define PERF_KEY_NUMS_CURVE 0x20000000 // NUMS curve #define PERF_KEY_C255_CURVE 0x30000000 // 25519 curve #define PERF_KEY_SW_TEST_CURVE 0x40000000 // Short-Weierstrass test curve (curve which is included in test program) #define PERF_KEY_NIST192 ( PERF_KEY_NIST_CURVE | 24 ) #define PERF_KEY_NIST224 ( PERF_KEY_NIST_CURVE | 28 ) #define PERF_KEY_NIST256 ( PERF_KEY_NIST_CURVE | 32 ) #define PERF_KEY_NIST384 ( PERF_KEY_NIST_CURVE | 48 ) #define PERF_KEY_NIST521 ( PERF_KEY_NIST_CURVE | 66 ) #define PERF_KEY_NUMS256 ( PERF_KEY_NUMS_CURVE | 32 ) #define PERF_KEY_NUMS384 ( PERF_KEY_NUMS_CURVE | 48 ) #define PERF_KEY_NUMS512 ( PERF_KEY_NUMS_CURVE | 64 ) #define PERF_KEY_C255_19 ( PERF_KEY_C255_CURVE | 32 ) #define PERF_KEY_W22519 ( PERF_KEY_SW_TEST_CURVE | 32 ) #define PERF_KEY_W448 ( PERF_KEY_SW_TEST_CURVE | 56 ) #define PERF_KEY_XMSS_SHA2_10_256 (SYMCRYPT_XMSS_SHA2_10_256) #define PERF_KEY_XMSS_SHA2_16_256 (SYMCRYPT_XMSS_SHA2_16_256) #define PERF_KEY_XMSS_SHA2_20_256 (SYMCRYPT_XMSS_SHA2_20_256) #define PERF_KEY_XMSS_SHA2_10_512 (SYMCRYPT_XMSS_SHA2_10_512) #define PERF_KEY_XMSS_SHA2_16_512 (SYMCRYPT_XMSS_SHA2_16_512) #define PERF_KEY_XMSS_SHA2_20_512 (SYMCRYPT_XMSS_SHA2_20_512) #define PERF_KEY_XMSS_SHAKE256_10_256 (SYMCRYPT_XMSS_SHAKE256_10_256) #define PERF_KEY_XMSS_SHAKE256_16_256 (SYMCRYPT_XMSS_SHAKE256_16_256) #define PERF_KEY_XMSS_SHAKE256_20_256 (SYMCRYPT_XMSS_SHAKE256_20_256) // // For testing ML-KEM parameters. These are not the key sizes, but refer to the different // ML-KEM parameter sets defined in FIPS 203. // #define PERF_KEY_MLKEM_512 (512 / 8) // ML-KEM-512 #define PERF_KEY_MLKEM_768 (768 / 8) // ML-KEM-768 #define PERF_KEY_MLKEM_1024 (1024 / 8) // ML-KEM-1024 PCBYTE getPerfTestModulus( UINT32 exKeySize ); // // Checked alloc definitions // extern volatile INT64 g_nOutstandingCheckedAllocs; // Global to track the number of outstanding allocations extern volatile INT64 g_nAllocs; // Global to track the number of allocations (only in single threaded runs) extern volatile INT64 g_nOutstandingCheckedAllocsMsBignum; extern volatile INT64 g_nAllocsMsBignum; VOID SYMCRYPT_CALL AllocWithChecksInit(); PVOID SYMCRYPT_CALL AllocWithChecksSc( SIZE_T nBytes ); VOID FreeWithChecksSc( PVOID ptr ); PVOID SYMCRYPT_CALL AllocWithChecksMsBignum( SIZE_T nBytes ); VOID FreeWithChecksMsBignum( PVOID ptr ); //////// // // Elliptic Curve parameters we want to test against but do not yet want to include in production binaries // //////// // As we have introduced NIST-prime specific SW code, we now need to test SW curves which // are not NIST prime curves to catch any bugs with the non-specialized codepaths. // W25519 from SP800-186; this is isomorphic to Curve25519, but is in SW form rather // than Montgomery form. It should not be used in any real use case, but is helpful // for testing static const BYTE rgbW25519[] = { //dwVersion 0x01, 0x00, 0x00, 0x00, //dwCurveType 0x01, 0x00, 0x00, 0x00, //dwCurveGenerationAlgId 0x00, 0x00, 0x00, 0x00, //cbFieldLength 0x20, 0x00, 0x00, 0x00, //cbSubgroupOrder 0x20, 0x00, 0x00, 0x00, //cbCofactor 0x01, 0x00, 0x00, 0x00, //cbSeed 0x00, 0x00, 0x00, 0x00, //p 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xED, //A 0x2A, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x98, 0x49, 0x14, 0xA1, 0x44, //B 0x7B, 0x42, 0x5E, 0xD0, 0x97, 0xB4, 0x25, 0xED, 0x09, 0x7B, 0x42, 0x5E, 0xD0, 0x97, 0xB4, 0x25, 0xED, 0x09, 0x7B, 0x42, 0x5E, 0xD0, 0x97, 0xB4, 0x26, 0x0B, 0x5E, 0x9C, 0x77, 0x10, 0xC8, 0x64, //x 0x2A, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAD, 0x24, 0x5A, //y 0x5F, 0x51, 0xE6, 0x5E, 0x47, 0x5F, 0x79, 0x4B, 0x1F, 0xE1, 0x22, 0xD3, 0x88, 0xB7, 0x2E, 0xB3, 0x6D, 0xC2, 0xB2, 0x81, 0x92, 0x83, 0x9E, 0x4D, 0xD6, 0x16, 0x3A, 0x5D, 0x81, 0x31, 0x2C, 0x14, //q 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xDE, 0xF9, 0xDE, 0xA2, 0xF7, 0x9C, 0xD6, 0x58, 0x12, 0x63, 0x1A, 0x5C, 0xF5, 0xD3, 0xED, //h 0x08, }; const PCSYMCRYPT_ECURVE_PARAMS SymCryptEcurveParamsW25519 = (PCSYMCRYPT_ECURVE_PARAMS) rgbW25519; // W448 from SP800-186; this is isomorphic to Curve448, but is in SW form rather // than Montgomery form. It should not be used in any real use case, but is helpful // for testing static const BYTE rgbW448[] = { //dwVersion 0x01, 0x00, 0x00, 0x00, //dwCurveType 0x01, 0x00, 0x00, 0x00, //dwCurveGenerationAlgId 0x00, 0x00, 0x00, 0x00, //cbFieldLength 0x38, 0x00, 0x00, 0x00, //cbSubgroupOrder 0x38, 0x00, 0x00, 0x00, //cbCofactor 0x01, 0x00, 0x00, 0x00, //cbSeed 0x00, 0x00, 0x00, 0x00, //p 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //A 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xA9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x1A, 0x76, 0xD4, 0x1F, //B 0x5E, 0xD0, 0x97, 0xB4, 0x25, 0xED, 0x09, 0x7B, 0x42, 0x5E, 0xD0, 0x97, 0xB4, 0x25, 0xED, 0x09, 0x7B, 0x42, 0x5E, 0xD0, 0x97, 0xB4, 0x25, 0xED, 0x09, 0x7B, 0x42, 0x5E, 0x71, 0xC7, 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7, 0x1C, 0x72, 0xC8, 0x7B, 0x7C, 0xC6, 0x9F, 0x70, //x 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCB, 0x91, //y 0x7D, 0x23, 0x5D, 0x12, 0x95, 0xF5, 0xB1, 0xF6, 0x6C, 0x98, 0xAB, 0x6E, 0x58, 0x32, 0x6F, 0xCE, 0xCB, 0xAE, 0x5D, 0x34, 0xF5, 0x55, 0x45, 0xD0, 0x60, 0xF7, 0x5D, 0xC2, 0x8D, 0xF3, 0xF6, 0xED, 0xB8, 0x02, 0x7E, 0x23, 0x46, 0x43, 0x0D, 0x21, 0x13, 0x12, 0xC4, 0xB1, 0x50, 0x67, 0x7A, 0xF7, 0x6F, 0xD7, 0x22, 0x3D, 0x45, 0x7B, 0x5B, 0x1A, //q 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7C, 0xCA, 0x23, 0xE9, 0xC4, 0x4E, 0xDB, 0x49, 0xAE, 0xD6, 0x36, 0x90, 0x21, 0x6C, 0xC2, 0x72, 0x8D, 0xC5, 0x8F, 0x55, 0x23, 0x78, 0xC2, 0x92, 0xAB, 0x58, 0x44, 0xF3, //h 0x04, }; const PCSYMCRYPT_ECURVE_PARAMS SymCryptEcurveParamsW448 = (PCSYMCRYPT_ECURVE_PARAMS) rgbW448; // Table with the internal curves' parameters and the mapping to PERF_KEYs const struct { UINT32 exKeyParam; PCSYMCRYPT_ECURVE_PARAMS pParams; } g_exKeyToCurve[] = { { PERF_KEY_NIST192, SymCryptEcurveParamsNistP192 }, { PERF_KEY_NIST224, SymCryptEcurveParamsNistP224 }, { PERF_KEY_NIST256, SymCryptEcurveParamsNistP256 }, { PERF_KEY_NIST384, SymCryptEcurveParamsNistP384 }, { PERF_KEY_NIST521, SymCryptEcurveParamsNistP521 }, { PERF_KEY_NUMS256, SymCryptEcurveParamsNumsP256t1 }, { PERF_KEY_NUMS384, SymCryptEcurveParamsNumsP384t1 }, { PERF_KEY_NUMS512, SymCryptEcurveParamsNumsP512t1 }, { PERF_KEY_C255_19, SymCryptEcurveParamsCurve25519 }, { PERF_KEY_W22519, SymCryptEcurveParamsW25519 }, { PERF_KEY_W448, SymCryptEcurveParamsW448 }, }; #define NUM_OF_HIGH_BIT_RESTRICTION_ITERATIONS (100) VOID testMontgomery(PSYMCRYPT_ECURVE pCurve); template VOID addRsaKeyGenPerfSymCrypt( PrintTable &table ); VOID addRsaKeyGenPerfMsBignum( PrintTable &table ); // Constants for RSA performance tests (OAEP, PKCS1, PSS modes) #define PERF_RSA_PKCS1_LESS_BYTES (11) #define PERF_RSA_LABEL_LENGTH (8) #define PERF_RSA_SALT_LENGTH (8) #define PERF_RSA_HASH_ALG_SC (ScShimSymCryptSha256Algorithm) #define PERF_RSA_HASH_ALG_CNG (BCRYPT_SHA256_ALGORITHM) #define PERF_RSA_HASH_ALG_SIZE (SYMCRYPT_SHA256_RESULT_SIZE) #define PERF_RSA_HASH_ALG_OIDS_SC (ScShimSymCryptSha256OidList) #define PERF_RSA_HASH_ALG_NOIDS_SC (SYMCRYPT_SHA256_OID_COUNT) #define PERF_RSA_OAEP_LESS_BYTES (2 + 2*SYMCRYPT_SHA256_RESULT_SIZE) #define MAX_RSA_TESTKEYS (50) extern RSAKEY_TESTBLOB g_RsaTestKeyBlobs[ MAX_RSA_TESTKEYS ]; extern UINT32 g_nRsaTestKeyBlobs; #define MAX_TEST_DLGROUPS (60) extern DLGROUP_TESTBLOB g_DlGroup[ MAX_TEST_DLGROUPS ]; extern UINT32 g_nDlgroups; extern UINT32 g_nDhNamedGroups; VOID fprintHex( FILE * f, PCBYTE pbData, SIZE_T cbData ); VOID rsaTestKeysGenerate(); PSYMCRYPT_RSAKEY rsaKeyFromTestBlob( PCRSAKEY_TESTBLOB pBlob ); PSYMCRYPT_RSAKEY rsaTestKeyRandom(); PSYMCRYPT_RSAKEY rsaTestKeyForSize( SIZE_T nBits ); PCDLGROUP_TESTBLOB dlgroupForSize( SIZE_T nBits, BOOLEAN forDiffieHellman ); VOID generateDlGroups(); template PSYMCRYPT_DLGROUP dlgroupObjectFromTestBlob( PCDLGROUP_TESTBLOB pBlob ); // Must free object after use VOID ReverseMemCopy( PBYTE pbDst, PCBYTE pbSrc, SIZE_T cbSrc ); BOOL SYMCRYPT_CALL RefIsPrime( _In_ PCSYMCRYPT_INT piSrc, _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, SIZE_T cbScratch );