mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1871 lines
39 KiB
1871 lines
39 KiB
/*
|
|
|
|
Logging.c
|
|
|
|
4/23/00 dangriff created
|
|
|
|
This is the output/logging code used by the CSP Test Suite. Expect that this
|
|
set of wrappers will be modified as the Test Suite evolves.
|
|
|
|
*/
|
|
|
|
#include <windows.h>
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
|
|
#include "cspstruc.h"
|
|
#include "logging.h"
|
|
#include "csptestsuite.h"
|
|
|
|
//
|
|
// Logging state variables
|
|
//
|
|
static BOOL g_fTestSuiteError = FALSE;
|
|
static BOOL g_fCSPClassError = FALSE;
|
|
static BOOL g_fTestLevelError = FALSE;
|
|
static BOOL g_fAPIError = FALSE;
|
|
static BOOL g_fCurrentAPIUnexpected = FALSE;
|
|
|
|
static DWORD g_dwCurrentCSPClass = 0;
|
|
static DWORD g_dwCurrentTestLevel = 0;
|
|
static API_NAME g_CurrentAPI;
|
|
static DWORD g_dwCurrentAPISubset = 0; // TEST_CASES_POSITIVE or TEST_CASES_NEGATIVE
|
|
|
|
// Test case set counter
|
|
static DWORD g_dwTestCaseIDMajor = 0;
|
|
|
|
//
|
|
// User-specified settings
|
|
//
|
|
//static LOG_VERBOSE g_Verbose = Terse;
|
|
|
|
static LPWSTR g_pwszProvName = NULL;
|
|
static DWORD g_dwExternalProvType = 0;
|
|
|
|
static LPWSTR g_pwszInteropProvName = NULL;
|
|
static DWORD g_dwInteropProvType = 0;
|
|
|
|
//
|
|
// Function: LogInfo
|
|
//
|
|
void LogInfo(IN LPWSTR pwszInfo)
|
|
{
|
|
ezLogMsg(LOG_INFO, NULL, NULL, __LINE__, L"%s", pwszInfo);
|
|
}
|
|
|
|
//
|
|
// Function: LogUserOption
|
|
//
|
|
void LogUserOption(IN LPWSTR pwszOption)
|
|
{
|
|
ezLogMsg(LOG_USER_OPTION, NULL, NULL, __LINE__, L"%s", pwszOption);
|
|
}
|
|
|
|
//
|
|
// Function: LogCreatingUserProtectedKey
|
|
//
|
|
void LogCreatingUserProtectedKey(void)
|
|
{
|
|
LogTestCaseSeparator(TRUE);
|
|
ezLogMsg(
|
|
LOG_USER_PROTECTED_KEY,
|
|
NULL,
|
|
NULL,
|
|
__LINE__,
|
|
L"Creating user protected key. You should see UI.");
|
|
}
|
|
|
|
//
|
|
// Function: FlagToString
|
|
//
|
|
BOOL FlagToString(
|
|
IN DWORD dwFlag,
|
|
IN FLAGTOSTRING_ITEM rgFlagToString [],
|
|
IN DWORD cFlagToString,
|
|
OUT WCHAR rgwsz [],
|
|
IN FLAG_TYPE FlagType)
|
|
{
|
|
BOOL fFound = FALSE;
|
|
unsigned iString = 0;
|
|
|
|
for (iString = 0; iString < cFlagToString; iString++)
|
|
{
|
|
if ( ((ExactMatch == FlagType) &&
|
|
(dwFlag == rgFlagToString[iString].dwKey)) ||
|
|
((Maskable == FlagType) &&
|
|
(dwFlag & rgFlagToString[iString].dwKey)))
|
|
{
|
|
if (fFound)
|
|
{
|
|
//
|
|
// One or more flags have already been found,
|
|
// so print a "|" to delimit multiple strings.
|
|
//
|
|
wsprintf(
|
|
rgwsz += wcslen(rgwsz),
|
|
L" | %s",
|
|
rgFlagToString[iString].pwszString);
|
|
}
|
|
else
|
|
{
|
|
fFound = TRUE;
|
|
wcscpy(
|
|
rgwsz,
|
|
rgFlagToString[iString].pwszString);
|
|
}
|
|
|
|
if (ExactMatch == FlagType)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return fFound;
|
|
}
|
|
|
|
//
|
|
// Function: AcquireContextFlagToString
|
|
//
|
|
BOOL AcquireContextFlagToString(
|
|
IN DWORD dwFlag,
|
|
OUT WCHAR rgwsz [])
|
|
{
|
|
FLAGTOSTRING_ITEM AcquireContextFlagStrings [] = {
|
|
{ CRYPT_VERIFYCONTEXT, L"CRYPT_VERIFYCONTEXT" },
|
|
{ CRYPT_NEWKEYSET, L"CRYPT_NEWKEYSET" },
|
|
{ CRYPT_MACHINE_KEYSET, L"CRYPT_MACHINE_KEYSET" },
|
|
{ CRYPT_DELETEKEYSET, L"CRYPT_DELETEKEYSET" },
|
|
{ CRYPT_SILENT, L"CRYPT_SILENT" }
|
|
};
|
|
|
|
return FlagToString(
|
|
dwFlag,
|
|
AcquireContextFlagStrings,
|
|
FLAGTOSTRING_SIZE(AcquireContextFlagStrings),
|
|
rgwsz,
|
|
Maskable);
|
|
}
|
|
|
|
//
|
|
// Function: GetProvParamToString
|
|
//
|
|
BOOL GetProvParamToString(
|
|
IN DWORD dwFlag,
|
|
OUT WCHAR rgwsz [])
|
|
{
|
|
FLAGTOSTRING_ITEM GetProvParamStrings [] = {
|
|
{ PP_CONTAINER, L"PP_CONTAINER" },
|
|
{ PP_ENUMALGS, L"PP_ENUMALGS" },
|
|
{ PP_ENUMALGS_EX, L"PP_ENUMALGS_EX" },
|
|
{ PP_ENUMCONTAINERS, L"PP_ENUMCONTAINERS" },
|
|
{ PP_IMPTYPE, L"PP_IMPTYPE" },
|
|
{ PP_NAME, L"PP_NAME" },
|
|
{ PP_VERSION, L"PP_VERSION" },
|
|
{ PP_SIG_KEYSIZE_INC, L"PP_SIG_KEYSIZE_INC" },
|
|
{ PP_KEYX_KEYSIZE_INC, L"PP_KEYX_KEYSIZE_INC" },
|
|
{ PP_KEYSET_SEC_DESCR, L"PP_KEYSET_SEC_DESCR" },
|
|
{ PP_UNIQUE_CONTAINER, L"PP_UNIQUE_CONTAINER" },
|
|
{ PP_PROVTYPE, L"PP_PROVTYPE" },
|
|
{ PP_USE_HARDWARE_RNG, L"PP_USE_HARDWARE_RNG" },
|
|
{ PP_KEYSPEC, L"PP_KEYSPEC" }
|
|
};
|
|
|
|
return FlagToString(
|
|
dwFlag,
|
|
GetProvParamStrings,
|
|
FLAGTOSTRING_SIZE(GetProvParamStrings),
|
|
rgwsz,
|
|
ExactMatch);
|
|
}
|
|
|
|
//
|
|
// Function: SetProvParamToString
|
|
//
|
|
BOOL SetProvParamToString(
|
|
IN DWORD dwFlag,
|
|
OUT WCHAR rgwsz [])
|
|
{
|
|
FLAGTOSTRING_ITEM SetProvParamStrings [] = {
|
|
{ PP_CLIENT_HWND, L"PP_CLIENT_HWND" },
|
|
{ PP_KEYSET_SEC_DESCR, L"PP_KEYSET_SEC_DESCR" },
|
|
{ PP_USE_HARDWARE_RNG, L"PP_USE_HARDWARE_RNG" }
|
|
};
|
|
|
|
return FlagToString(
|
|
dwFlag,
|
|
SetProvParamStrings,
|
|
FLAGTOSTRING_SIZE(SetProvParamStrings),
|
|
rgwsz,
|
|
ExactMatch);
|
|
}
|
|
|
|
//
|
|
// Function: AlgidToString
|
|
//
|
|
BOOL AlgidToString(
|
|
IN DWORD dwFlag,
|
|
OUT WCHAR rgwsz [])
|
|
{
|
|
FLAGTOSTRING_ITEM AlgidStrings [] = {
|
|
{ AT_SIGNATURE, L"AT_SIGNATURE" },
|
|
{ AT_KEYEXCHANGE, L"AT_KEYEXCHANGE" },
|
|
{ CALG_MD2, L"CALG_MD2" },
|
|
{ CALG_MD4, L"CALG_MD4" },
|
|
{ CALG_MD5, L"CALG_MD5" },
|
|
{ CALG_SHA, L"CALG_SHA" },
|
|
{ CALG_SHA1, L"CALG_SHA1" },
|
|
{ CALG_MAC, L"CALG_MAC" },
|
|
{ CALG_RSA_SIGN, L"CALG_RSA_SIGN" },
|
|
{ CALG_DSS_SIGN, L"CALG_DSS_SIGN" },
|
|
{ CALG_RSA_KEYX, L"CALG_RSA_KEYX" },
|
|
{ CALG_DES, L"CALG_DES" },
|
|
{ CALG_3DES_112, L"CALG_3DES_112" },
|
|
{ CALG_3DES, L"CALG_3DES" },
|
|
{ CALG_DESX, L"CALG_DESX" },
|
|
{ CALG_RC2, L"CALG_RC2" },
|
|
{ CALG_RC4, L"CALG_RC4" },
|
|
{ CALG_SEAL, L"CALG_SEAL" },
|
|
{ CALG_DH_SF, L"CALG_DH_SF" },
|
|
{ CALG_DH_EPHEM, L"CALG_DH_EPHEM" },
|
|
{ CALG_AGREEDKEY_ANY, L"CALG_AGREEDKEY_ANY" },
|
|
{ CALG_KEA_KEYX, L"CALG_KEA_KEYX" },
|
|
{ CALG_HUGHES_MD5, L"CALG_HUGHES_MD5" },
|
|
{ CALG_SKIPJACK, L"CALG_SKIPJACK" },
|
|
{ CALG_TEK, L"CALG_TEK" },
|
|
{ CALG_CYLINK_MEK, L"CALG_CYLINK_MEK" },
|
|
{ CALG_SSL3_SHAMD5, L"CALG_SSL3_SHAMD5" },
|
|
{ CALG_SSL3_MASTER, L"CALG_SSL3_MASTER" },
|
|
{ CALG_SCHANNEL_MASTER_HASH, L"CALG_SCHANNEL_MASTER_HASH" },
|
|
{ CALG_SCHANNEL_MAC_KEY, L"CALG_SCHANNEL_MAC_KEY" },
|
|
{ CALG_SCHANNEL_ENC_KEY, L"CALG_SCHANNEL_ENC_KEY" },
|
|
{ CALG_PCT1_MASTER, L"CALG_PCT1_MASTER" },
|
|
{ CALG_SSL2_MASTER, L"CALG_SSL2_MASTER" },
|
|
{ CALG_TLS1_MASTER, L"CALG_TLS1_MASTER" },
|
|
{ CALG_RC5, L"CALG_RC5" },
|
|
{ CALG_HMAC, L"CALG_HMAC" },
|
|
{ CALG_TLS1PRF, L"CALG_TLS1PRF" },
|
|
{ CALG_HASH_REPLACE_OWF, L"CALG_HASH_REPLACE_OWF" }
|
|
};
|
|
|
|
return FlagToString(
|
|
dwFlag,
|
|
AlgidStrings,
|
|
FLAGTOSTRING_SIZE(AlgidStrings),
|
|
rgwsz,
|
|
ExactMatch);
|
|
}
|
|
|
|
//
|
|
// Function: DeriveKeyFlagToString
|
|
//
|
|
BOOL DeriveKeyFlagToString(
|
|
IN DWORD dwFlag,
|
|
OUT WCHAR rgwsz [])
|
|
{
|
|
FLAGTOSTRING_ITEM DeriveKeyFlagStrings [] = {
|
|
{ CRYPT_CREATE_SALT, L"CRYPT_CREATE_SALT" },
|
|
{ CRYPT_EXPORTABLE, L"CRYPT_EXPORTABLE" },
|
|
{ CRYPT_NO_SALT, L"CRYPT_NO_SALT" },
|
|
{ CRYPT_UPDATE_KEY, L"CRYPT_UPDATE_KEY" }
|
|
};
|
|
|
|
return FlagToString(
|
|
dwFlag,
|
|
DeriveKeyFlagStrings,
|
|
FLAGTOSTRING_SIZE(DeriveKeyFlagStrings),
|
|
rgwsz,
|
|
Maskable);
|
|
}
|
|
|
|
//
|
|
// Function: EncryptFlagToString
|
|
//
|
|
BOOL EncryptFlagToString(
|
|
IN DWORD dwFlag,
|
|
OUT WCHAR rgwsz [])
|
|
{
|
|
FLAGTOSTRING_ITEM EncryptFlagStrings [] = {
|
|
{ CRYPT_OAEP, L"CRYPT_OAEP" }
|
|
};
|
|
|
|
return FlagToString(
|
|
dwFlag,
|
|
EncryptFlagStrings,
|
|
FLAGTOSTRING_SIZE(EncryptFlagStrings),
|
|
rgwsz,
|
|
Maskable);
|
|
}
|
|
|
|
//
|
|
// Function: ExportKeyBlobTypeToString
|
|
//
|
|
BOOL ExportKeyBlobTypeToString (
|
|
IN DWORD dwFlag,
|
|
OUT WCHAR rgwsz [])
|
|
{
|
|
FLAGTOSTRING_ITEM ExportKeyBlobTypeStrings [] = {
|
|
{ OPAQUEKEYBLOB, L"OPAQUEKEYBLOB" },
|
|
{ PRIVATEKEYBLOB, L"PRIVATEKEYBLOB" },
|
|
{ PUBLICKEYBLOB, L"PUBLICKEYBLOB" },
|
|
{ SIMPLEBLOB, L"SIMPLEBLOB" },
|
|
{ SYMMETRICWRAPKEYBLOB, L"SYMMETRICWRAPKEYBLOB" }
|
|
};
|
|
|
|
return FlagToString(
|
|
dwFlag,
|
|
ExportKeyBlobTypeStrings,
|
|
FLAGTOSTRING_SIZE(ExportKeyBlobTypeStrings),
|
|
rgwsz,
|
|
ExactMatch);
|
|
}
|
|
|
|
//
|
|
// Function: ExportKeyFlagToString
|
|
//
|
|
BOOL ExportKeyFlagToString (
|
|
IN DWORD dwFlag,
|
|
OUT WCHAR rgwsz [])
|
|
{
|
|
FLAGTOSTRING_ITEM ExportKeyFlagStrings [] = {
|
|
{ CRYPT_DESTROYKEY, L"CRYPT_DESTROYKEY" },
|
|
{ CRYPT_SSL2_FALLBACK, L"CRYPT_SSL2_FALLBACK" },
|
|
{ CRYPT_OAEP, L"CRYPT_OAEP" }
|
|
};
|
|
|
|
return FlagToString(
|
|
dwFlag,
|
|
ExportKeyFlagStrings,
|
|
FLAGTOSTRING_SIZE(ExportKeyFlagStrings),
|
|
rgwsz,
|
|
Maskable);
|
|
}
|
|
|
|
//
|
|
// Function: GenKeyFlagToString
|
|
//
|
|
BOOL GenKeyFlagToString(
|
|
IN DWORD dwFlag,
|
|
OUT WCHAR rgwsz [])
|
|
{
|
|
FLAGTOSTRING_ITEM GenKeyFlagStrings [] = {
|
|
{ CRYPT_CREATE_SALT, L"CRYPT_CREATE_SALT" },
|
|
{ CRYPT_EXPORTABLE, L"CRYPT_EXPORTABLE" },
|
|
{ CRYPT_NO_SALT, L"CRYPT_NO_SALT" },
|
|
{ CRYPT_PREGEN, L"CRYPT_PREGEN" },
|
|
{ CRYPT_USER_PROTECTED, L"CRYPT_USER_PROTECTED" }
|
|
};
|
|
|
|
return FlagToString(
|
|
dwFlag,
|
|
GenKeyFlagStrings,
|
|
FLAGTOSTRING_SIZE(GenKeyFlagStrings),
|
|
rgwsz,
|
|
Maskable);
|
|
}
|
|
|
|
//
|
|
// Function: HashParamToString
|
|
//
|
|
BOOL HashParamToString(
|
|
IN DWORD dwFlag,
|
|
OUT WCHAR rgwsz [])
|
|
{
|
|
FLAGTOSTRING_ITEM HashParamStrings [] = {
|
|
{ HP_ALGID, L"HP_ALGID" },
|
|
{ HP_HASHSIZE, L"HP_HASHSIZE" },
|
|
{ HP_HASHVAL, L"HP_HASHVAL" },
|
|
{ HP_HMAC_INFO, L"HP_HMAC_INFO" }
|
|
};
|
|
|
|
return FlagToString(
|
|
dwFlag,
|
|
HashParamStrings,
|
|
FLAGTOSTRING_SIZE(HashParamStrings),
|
|
rgwsz,
|
|
ExactMatch);
|
|
}
|
|
|
|
//
|
|
// Function: KeyParamToString
|
|
//
|
|
BOOL KeyParamToString(
|
|
IN DWORD dwFlag,
|
|
OUT WCHAR rgwsz [])
|
|
{
|
|
FLAGTOSTRING_ITEM KeyParamStrings [] = {
|
|
{ KP_ALGID, L"KP_ALGID" },
|
|
{ KP_BLOCKLEN, L"KP_BLOCKLEN" },
|
|
{ KP_KEYLEN, L"KP_KEYLEN" },
|
|
{ KP_SALT, L"KP_SALT" },
|
|
{ KP_SALT_EX, L"KP_SALT_EX" },
|
|
{ KP_PERMISSIONS, L"KP_PERMISSIONS" },
|
|
{ KP_P, L"KP_P" },
|
|
{ KP_Q, L"KP_Q" },
|
|
{ KP_G, L"KP_G" },
|
|
{ KP_X, L"KP_X" },
|
|
{ KP_EFFECTIVE_KEYLEN, L"KP_EFFECTIVE_KEYLEN" },
|
|
{ KP_IV, L"KP_IV" },
|
|
{ KP_PADDING, L"KP_PADDING" },
|
|
{ KP_MODE, L"KP_MODE" },
|
|
{ KP_MODE_BITS, L"KP_MODE_BITS" },
|
|
{ KP_PUB_PARAMS, L"KP_PUB_PARAMS" }
|
|
};
|
|
|
|
return FlagToString(
|
|
dwFlag,
|
|
KeyParamStrings,
|
|
FLAGTOSTRING_SIZE(KeyParamStrings),
|
|
rgwsz,
|
|
ExactMatch);
|
|
}
|
|
|
|
//
|
|
// Function: KeyParamModeToString
|
|
//
|
|
BOOL KeyParamModeToString(
|
|
IN DWORD dwFlag,
|
|
OUT WCHAR rgwsz [])
|
|
{
|
|
FLAGTOSTRING_ITEM KeyParamModeStrings[] = {
|
|
{ CRYPT_MODE_CBC, L"CRYPT_MODE_CBC" },
|
|
{ CRYPT_MODE_CFB, L"CRYPT_MODE_CFB" },
|
|
{ CRYPT_MODE_ECB, L"CRYPT_MODE_ECB" },
|
|
{ CRYPT_MODE_OFB, L"CRYPT_MODE_OFB" }
|
|
};
|
|
|
|
return FlagToString(
|
|
dwFlag,
|
|
KeyParamModeStrings,
|
|
FLAGTOSTRING_SIZE(KeyParamModeStrings),
|
|
rgwsz,
|
|
ExactMatch);
|
|
}
|
|
|
|
//
|
|
// Function: KeyParamPermissionToString
|
|
//
|
|
BOOL KeyParamPermissionToString(
|
|
IN DWORD dwFlag,
|
|
OUT WCHAR rgwsz [])
|
|
{
|
|
FLAGTOSTRING_ITEM KeyParamPermissionStrings[] = {
|
|
{ CRYPT_DECRYPT, L"CRYPT_DECRYPT" },
|
|
{ CRYPT_ENCRYPT, L"CRYPT_ENCRYPT" },
|
|
{ CRYPT_EXPORT, L"CRYPT_EXPORT" },
|
|
{ CRYPT_MAC, L"CRYPT_MAC" },
|
|
{ CRYPT_READ, L"CRYPT_READ" },
|
|
{ CRYPT_WRITE, L"CRYPT_WRITE" }
|
|
};
|
|
|
|
return FlagToString(
|
|
dwFlag,
|
|
KeyParamPermissionStrings,
|
|
FLAGTOSTRING_SIZE(KeyParamPermissionStrings),
|
|
rgwsz,
|
|
Maskable);
|
|
}
|
|
|
|
//
|
|
// Function: ProvParamEnumFlagToString
|
|
//
|
|
BOOL ProvParamEnumFlagToString(
|
|
IN DWORD dwFlag,
|
|
OUT WCHAR rgwsz [])
|
|
{
|
|
FLAGTOSTRING_ITEM ProvParamEnumFlagStrings[] = {
|
|
{ CRYPT_FIRST, L"CRYPT_FIRST" },
|
|
{ CRYPT_MACHINE_KEYSET, L"CRYPT_MACHINE_KEYSET" }
|
|
};
|
|
|
|
return FlagToString(
|
|
dwFlag,
|
|
ProvParamEnumFlagStrings,
|
|
FLAGTOSTRING_SIZE(ProvParamEnumFlagStrings),
|
|
rgwsz,
|
|
Maskable);
|
|
}
|
|
|
|
//
|
|
// Function: ProvParamSecDescrFlagToString
|
|
//
|
|
BOOL ProvParamSecDescrFlagToString(
|
|
IN DWORD dwFlag,
|
|
OUT WCHAR rgwsz [])
|
|
{
|
|
FLAGTOSTRING_ITEM ProvParamSecDescrFlagStrings[] = {
|
|
{ OWNER_SECURITY_INFORMATION, L"OWNER_SECURITY_INFORMATION" },
|
|
{ GROUP_SECURITY_INFORMATION, L"GROUP_SECURITY_INFORMATION" },
|
|
{ DACL_SECURITY_INFORMATION, L"DACL_SECURITY_INFORMATION" },
|
|
{ SACL_SECURITY_INFORMATION, L"SACL_SECURITY_INFORMATION" }
|
|
};
|
|
|
|
return FlagToString(
|
|
dwFlag,
|
|
ProvParamSecDescrFlagStrings,
|
|
FLAGTOSTRING_SIZE(ProvParamSecDescrFlagStrings),
|
|
rgwsz,
|
|
Maskable);
|
|
}
|
|
|
|
//
|
|
// Function: ProvParamImpTypeToString
|
|
//
|
|
BOOL ProvParamImpTypeToString(
|
|
IN DWORD dwFlag,
|
|
OUT WCHAR rgwsz [])
|
|
{
|
|
FLAGTOSTRING_ITEM ProvParamImpTypeStrings[] = {
|
|
{ CRYPT_IMPL_HARDWARE, L"CRYPT_IMPL_HARDWARE" },
|
|
{ CRYPT_IMPL_SOFTWARE, L"CRYPT_IMPL_SOFTWARE" },
|
|
{ CRYPT_IMPL_MIXED, L"CRYPT_IMPL_MIXED" },
|
|
{ CRYPT_IMPL_UNKNOWN, L"CRYPT_IMPL_UNKNOWN" }
|
|
};
|
|
|
|
return FlagToString(
|
|
dwFlag,
|
|
ProvParamImpTypeStrings,
|
|
FLAGTOSTRING_SIZE(ProvParamImpTypeStrings),
|
|
rgwsz,
|
|
ExactMatch);
|
|
}
|
|
|
|
//
|
|
// Function: HashDataFlagToString
|
|
//
|
|
BOOL HashDataFlagToString(
|
|
IN DWORD dwFlag,
|
|
OUT WCHAR rgwsz [])
|
|
{
|
|
FLAGTOSTRING_ITEM HashDataFlagStrings[] = {
|
|
{ CRYPT_USERDATA, L"CRYPT_USERDATA" }
|
|
};
|
|
|
|
return FlagToString(
|
|
dwFlag,
|
|
HashDataFlagStrings,
|
|
FLAGTOSTRING_SIZE(HashDataFlagStrings),
|
|
rgwsz,
|
|
Maskable);
|
|
}
|
|
|
|
//
|
|
// Function: HashSessionKeyFlagToString
|
|
//
|
|
BOOL HashSessionKeyFlagToString(
|
|
IN DWORD dwFlag,
|
|
OUT WCHAR rgwsz [])
|
|
{
|
|
FLAGTOSTRING_ITEM HashSessionKeyFlagStrings[] = {
|
|
{ CRYPT_LITTLE_ENDIAN, L"CRYPT_LITTLE_ENDIAN" }
|
|
};
|
|
|
|
return FlagToString(
|
|
dwFlag,
|
|
HashSessionKeyFlagStrings,
|
|
FLAGTOSTRING_SIZE(HashSessionKeyFlagStrings),
|
|
rgwsz,
|
|
Maskable);
|
|
}
|
|
|
|
//
|
|
// Function: ImportKeyFlagToString
|
|
//
|
|
BOOL ImportKeyFlagToString(
|
|
IN DWORD dwFlag,
|
|
OUT WCHAR rgwsz [])
|
|
{
|
|
FLAGTOSTRING_ITEM ImportKeyFlagStrings[] = {
|
|
{ CRYPT_EXPORTABLE, L"CRYPT_EXPORTABLE" },
|
|
{ CRYPT_OAEP, L"CRYPT_OAEP" },
|
|
{ CRYPT_NO_SALT, L"CRYPT_NO_SALT" }
|
|
};
|
|
|
|
return FlagToString(
|
|
dwFlag,
|
|
ImportKeyFlagStrings,
|
|
FLAGTOSTRING_SIZE(ImportKeyFlagStrings),
|
|
rgwsz,
|
|
Maskable);
|
|
}
|
|
|
|
//
|
|
// Function: SignHashFlagToString
|
|
//
|
|
BOOL SignHashFlagToString(
|
|
IN DWORD dwFlag,
|
|
OUT WCHAR rgwsz [])
|
|
{
|
|
FLAGTOSTRING_ITEM SignHashFlagStrings[] = {
|
|
{ CRYPT_NOHASHOID, L"CRYPT_NOHASHOID" }
|
|
};
|
|
|
|
return FlagToString(
|
|
dwFlag,
|
|
SignHashFlagStrings,
|
|
FLAGTOSTRING_SIZE(SignHashFlagStrings),
|
|
rgwsz,
|
|
Maskable);
|
|
}
|
|
|
|
//
|
|
// Function: TestCaseTypeToString
|
|
//
|
|
BOOL TestCaseTypeToString(
|
|
IN DWORD dwTestCaseType,
|
|
OUT WCHAR rgwsz [])
|
|
{
|
|
FLAGTOSTRING_ITEM TestCaseTypeStrings[] = {
|
|
{ TEST_CASES_POSITIVE, L"Positive test cases. API's should return TRUE" },
|
|
{ TEST_CASES_NEGATIVE, L"Negative test cases. API's should return FALSE" },
|
|
{ TEST_CASES_SCENARIO, L"Scenario test cases. Tests using multiple API's" },
|
|
{ TEST_CASES_INTEROP, L"Interoperability test cases. Tests using multiple API's and two CSP's" }
|
|
};
|
|
|
|
return FlagToString(
|
|
dwTestCaseType,
|
|
TestCaseTypeStrings,
|
|
FLAGTOSTRING_SIZE(TestCaseTypeStrings),
|
|
rgwsz,
|
|
ExactMatch);
|
|
};
|
|
|
|
//
|
|
// Function:
|
|
//
|
|
BOOL ApiNameToString(
|
|
API_NAME ApiName,
|
|
OUT WCHAR rgwsz[])
|
|
{
|
|
FLAGTOSTRING_ITEM ApiNameStrings [] = {
|
|
{ API_CRYPTACQUIRECONTEXT, L"CryptAcquireContext" },
|
|
{ API_CRYPTCREATEHASH, L"CryptCreateHash" },
|
|
{ API_CRYPTDECRYPT, L"CryptDecrypt" },
|
|
{ API_CRYPTDERIVEKEY, L"CryptDeriveKey" },
|
|
{ API_CRYPTDESTROYHASH, L"CryptDestroyHash" },
|
|
{ API_CRYPTDESTROYKEY, L"CryptDestroyKey" },
|
|
{ API_CRYPTENCRYPT, L"CryptEncrypt" },
|
|
{ API_CRYPTEXPORTKEY, L"CryptExportKey" },
|
|
{ API_CRYPTGENKEY, L"CryptGenKey" },
|
|
{ API_CRYPTGENRANDOM, L"CryptGenRandom" },
|
|
{ API_CRYPTGETHASHPARAM, L"CryptGetHashParam" },
|
|
{ API_CRYPTGETKEYPARAM, L"CryptGetKeyParam" },
|
|
{ API_CRYPTGETPROVPARAM, L"CryptGetProvParam" },
|
|
{ API_CRYPTGETUSERKEY, L"CryptGetUserKey" },
|
|
{ API_CRYPTHASHDATA, L"CryptHashData" },
|
|
{ API_CRYPTHASHSESSIONKEY, L"CryptHashSessionKey" },
|
|
{ API_CRYPTIMPORTKEY, L"CryptImportKey" },
|
|
{ API_CRYPTRELEASECONTEXT, L"CryptReleaseContext" },
|
|
{ API_CRYPTSETHASHPARAM, L"CryptSetHashParam" },
|
|
{ API_CRYPTSETKEYPARAM, L"CryptSetKeyParam" },
|
|
{ API_CRYPTSETPROVPARAM, L"CryptSetProvParam" },
|
|
{ API_CRYPTSIGNHASH, L"CryptSignHash" },
|
|
{ API_CRYPTVERIFYSIGNATURE, L"CryptVerifySignature" },
|
|
{ API_CRYPTDUPLICATEHASH, L"CryptDuplicateHash" },
|
|
{ API_CRYPTDUPLICATEKEY, L"CryptDuplicateKey" },
|
|
|
|
//
|
|
// Advapi32 entry point
|
|
//
|
|
{ API_CRYPTCONTEXTADDREF, L"CryptContextAddRef" },
|
|
|
|
//
|
|
// Non-Crypto API functions
|
|
//
|
|
{ API_MEMORY, L"Memory allocation" },
|
|
{ API_DATACOMPARE, L"Data comparision (see previous API)" },
|
|
{ API_GETDESKTOPWINDOW, L"GetDesktopWindow" }
|
|
};
|
|
|
|
return FlagToString(
|
|
ApiName,
|
|
ApiNameStrings,
|
|
FLAGTOSTRING_SIZE(ApiNameStrings),
|
|
rgwsz,
|
|
ExactMatch);
|
|
}
|
|
|
|
//
|
|
// Function: LogCleanupParamInfo
|
|
//
|
|
void LogCleanupParamInfo(
|
|
IN OUT PAPI_PARAM_INFO pParamInfo,
|
|
IN DWORD cParamInfo)
|
|
{
|
|
unsigned iParam;
|
|
|
|
for (iParam = 0; iParam < cParamInfo; iParam++)
|
|
{
|
|
if (pParamInfo[iParam].pbSaved)
|
|
free(pParamInfo[iParam].pbSaved);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Function: LogInitParamInfo
|
|
//
|
|
BOOL LogInitParamInfo(
|
|
IN OUT PAPI_PARAM_INFO pParamInfo,
|
|
IN DWORD cParamInfo,
|
|
IN PTESTCASE ptc)
|
|
{
|
|
unsigned iParam;
|
|
|
|
for (iParam = 0; iParam < cParamInfo; iParam++)
|
|
{
|
|
if (pParamInfo[iParam].fPrintBytes)
|
|
{
|
|
if ( NULL != pParamInfo[iParam].pbParam &&
|
|
((PBYTE) TEST_INVALID_POINTER) != pParamInfo[iParam].pbParam &&
|
|
NULL != pParamInfo[iParam].pcbBytes &&
|
|
((PDWORD) TEST_INVALID_POINTER) != pParamInfo[iParam].pcbBytes)
|
|
{
|
|
// Save bytes to a second buffer
|
|
if (! TestAlloc(
|
|
&pParamInfo[iParam].pbSaved,
|
|
*pParamInfo[iParam].pcbBytes,
|
|
ptc))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
memcpy(
|
|
pParamInfo[iParam].pbSaved,
|
|
pParamInfo[iParam].pbParam,
|
|
*pParamInfo[iParam].pcbBytes);
|
|
}
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// Function: LogParamInfo
|
|
//
|
|
void LogParamInfo(
|
|
PAPI_PARAM_INFO pParamInfo,
|
|
DWORD cParamInfo,
|
|
BOOL fLogToConsole)
|
|
{
|
|
DWORD dwLogApiParameter = LOG_API_PARAMETER;
|
|
WCHAR rgwsz [ BUFFER_LENGTH ];
|
|
unsigned iParam;
|
|
|
|
if (fLogToConsole)
|
|
{
|
|
// Feedback has been to not display parameters with the console
|
|
// output. To change this, uncomment the next line.
|
|
|
|
//dwLogApiParameter = LOG_API_PARAMETER_CONSOLE;
|
|
}
|
|
|
|
memset(rgwsz, 0, sizeof(rgwsz));
|
|
|
|
for (iParam = 0; iParam < cParamInfo; iParam++)
|
|
{
|
|
switch( pParamInfo[iParam].Type )
|
|
{
|
|
case Handle:
|
|
{
|
|
ezLogMsg(
|
|
dwLogApiParameter,
|
|
NULL,
|
|
NULL,
|
|
__LINE__,
|
|
L" %s: 0x%x",
|
|
pParamInfo[iParam].pwszName,
|
|
pParamInfo[iParam].pulParam);
|
|
break;
|
|
}
|
|
case Pointer:
|
|
{
|
|
ezLogMsg(
|
|
dwLogApiParameter,
|
|
NULL,
|
|
NULL,
|
|
__LINE__,
|
|
L" %s: 0x%x",
|
|
pParamInfo[iParam].pwszName,
|
|
pParamInfo[iParam].pbParam);
|
|
|
|
if ( pParamInfo[iParam].fPrintBytes &&
|
|
pParamInfo[iParam].pbSaved)
|
|
{
|
|
wsprintf(rgwsz, L"INPUT value", pParamInfo[iParam].pwszName);
|
|
PrintBytes(
|
|
rgwsz,
|
|
pParamInfo[iParam].pbSaved,
|
|
*pParamInfo[iParam].pcbBytes);
|
|
*rgwsz = L'\0';
|
|
}
|
|
if ( pParamInfo[iParam].fPrintBytes &&
|
|
NULL != pParamInfo[iParam].pbParam &&
|
|
(PBYTE) TEST_INVALID_POINTER != pParamInfo[iParam].pbParam &&
|
|
NULL != pParamInfo[iParam].pcbBytes &&
|
|
(PDWORD) TEST_INVALID_POINTER != pParamInfo[iParam].pcbBytes)
|
|
{
|
|
wsprintf(rgwsz, L"OUTPUT value", pParamInfo[iParam].pwszName);
|
|
PrintBytes(
|
|
rgwsz,
|
|
pParamInfo[iParam].pbParam,
|
|
*(pParamInfo[iParam].pcbBytes));
|
|
*rgwsz = L'\0';
|
|
}
|
|
break;
|
|
}
|
|
case Dword:
|
|
{
|
|
//
|
|
// If a pfnFlagToString function has been specified,
|
|
// attempt to translate the flag(s).
|
|
//
|
|
if (pParamInfo[iParam].pfnFlagToString)
|
|
{
|
|
pParamInfo[iParam].pfnFlagToString(
|
|
pParamInfo[iParam].dwParam,
|
|
rgwsz);
|
|
|
|
ezLogMsg(
|
|
dwLogApiParameter,
|
|
NULL,
|
|
NULL,
|
|
__LINE__,
|
|
L" %s: 0x%x (%s)",
|
|
pParamInfo[iParam].pwszName,
|
|
pParamInfo[iParam].dwParam,
|
|
rgwsz);
|
|
rgwsz[0] = L'\0';
|
|
}
|
|
else
|
|
{
|
|
ezLogMsg(
|
|
dwLogApiParameter,
|
|
NULL,
|
|
NULL,
|
|
__LINE__,
|
|
L" %s: 0x%x",
|
|
pParamInfo[iParam].pwszName,
|
|
pParamInfo[iParam].dwParam);
|
|
}
|
|
break;
|
|
}
|
|
case String:
|
|
{
|
|
ezLogMsg(
|
|
dwLogApiParameter,
|
|
NULL,
|
|
NULL,
|
|
__LINE__,
|
|
L" %s: %s",
|
|
pParamInfo[iParam].pwszName,
|
|
pParamInfo[iParam].pwszParam);
|
|
break;
|
|
}
|
|
case Boolean:
|
|
{
|
|
ezLogMsg(
|
|
dwLogApiParameter,
|
|
NULL,
|
|
NULL,
|
|
__LINE__,
|
|
L" %s: %s",
|
|
pParamInfo[iParam].pwszName,
|
|
pParamInfo[iParam].fParam ? STRING_TRUE : STRING_FALSE);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Function: IncrementErrorLevel
|
|
//
|
|
DWORD IncrementErrorLevel(DWORD dwErrorLevel)
|
|
{
|
|
int iLevel;
|
|
|
|
for (
|
|
iLevel = 0;
|
|
iLevel < (sizeof(g_rgErrorLevels) / sizeof(DWORD) - 1);
|
|
iLevel++)
|
|
{
|
|
if (dwErrorLevel == g_rgErrorLevels[iLevel])
|
|
{
|
|
return g_rgErrorLevels[iLevel + 1];
|
|
}
|
|
}
|
|
|
|
return g_rgErrorLevels[iLevel];
|
|
}
|
|
|
|
//
|
|
// Function: LogInit
|
|
//
|
|
BOOL LogInit(
|
|
IN PLOGINIT_INFO pLogInitInfo)
|
|
{
|
|
EZLOG_OPENLOG_DATA EzLogOpenData;
|
|
|
|
g_pwszProvName = pLogInitInfo->pwszCSPName;
|
|
g_dwExternalProvType = pLogInitInfo->dwCSPExternalType;
|
|
g_pwszInteropProvName = pLogInitInfo->pwszInteropCSPName;
|
|
g_dwInteropProvType = pLogInitInfo->dwInteropCSPExternalType;
|
|
|
|
//
|
|
// Initialize EZLOG
|
|
//
|
|
memset(&EzLogOpenData, 0, sizeof(EzLogOpenData));
|
|
|
|
EzLogOpenData.Version = EZLOG_OPENLOG_DATA_VERSION;
|
|
EzLogOpenData.Flags = EZLOG_OUTPUT_STDOUT | EZLOG_USE_INDENTATION |
|
|
EZLOG_REPORT_BLOCKCLOSE | EZLOG_USE_ONLY_MY_LEVELS | EZLOG_LEVELS_ARE_MASKABLE;
|
|
EzLogOpenData.LogFileName = LOGFILE;
|
|
|
|
//
|
|
// Don't output the block summary table
|
|
//
|
|
EzLogOpenData.cReportBlockThresh = EZLOG_REPORT_NO_BLOCKS;
|
|
EzLogOpenData.cLevels = sizeof(g_EzLogLevels) / sizeof(EZLOG_LEVEL_INIT_DATA);
|
|
EzLogOpenData.pLevels = g_EzLogLevels;
|
|
|
|
if (! ezOpenLogEx(&EzLogOpenData))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// Function: LogClose
|
|
// Purpose: Close and cleanup logging
|
|
//
|
|
BOOL LogClose(void)
|
|
{
|
|
//
|
|
// Check for a Test Suite-level error
|
|
//
|
|
if (g_fTestSuiteError)
|
|
{
|
|
ezLogMsg(
|
|
CSP_ERROR_TEST_SUITE,
|
|
NULL,
|
|
NULL,
|
|
__LINE__,
|
|
L"CSP Test Suite is ending prematurely");
|
|
}
|
|
|
|
return ezCloseLog(0);
|
|
}
|
|
|
|
//
|
|
// Function: LogBeginCSPClass
|
|
// Purpose: Log the beginning of a new class, or major group, of tests.
|
|
//
|
|
BOOL LogBeginCSPClass(DWORD dwClass)
|
|
{
|
|
LPWSTR pwsz = NULL;
|
|
|
|
switch (dwClass)
|
|
{
|
|
case CLASS_INVALID:
|
|
{
|
|
pwsz = L"CLASS_INVALID";
|
|
break;
|
|
}
|
|
case CLASS_SIG_ONLY:
|
|
{
|
|
pwsz = L"CLASS_SIG_ONLY";
|
|
break;
|
|
}
|
|
case CLASS_SIG_KEYX:
|
|
{
|
|
pwsz = L"CLASS_SIG_KEYX";
|
|
break;
|
|
}
|
|
case CLASS_FULL:
|
|
{
|
|
pwsz = L"CLASS_FULL";
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If there has been a Test Suite-level error, don't allow
|
|
// a new CSP Class set of tests to begin.
|
|
//
|
|
if (g_fTestSuiteError)
|
|
{
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
g_dwCurrentCSPClass = dwClass;
|
|
|
|
return ezStartBlock(
|
|
NULL,
|
|
NULL,
|
|
EZBLOCK_OUTCOME_INDEPENDENT /*EZBLOCK_TRACK_SUBBLOCKS*/,
|
|
CSP_PASS,
|
|
L"CSP %s", pwsz);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Function: LogEndCSPClass
|
|
// Purpose: Log the completion of the current class of tests.
|
|
//
|
|
BOOL LogEndCSPClass(DWORD dwClass)
|
|
{
|
|
if (g_dwCurrentCSPClass != dwClass)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Clear CSP Class-level error flag
|
|
//
|
|
if (g_fCSPClassError)
|
|
{
|
|
ezLogMsg(
|
|
CSP_ERROR_CSP_CLASS,
|
|
NULL,
|
|
NULL,
|
|
__LINE__,
|
|
L"CSP Class is ending prematurely");
|
|
|
|
g_fCSPClassError = FALSE;
|
|
}
|
|
|
|
return ezFinishBlock(0);
|
|
}
|
|
|
|
//
|
|
// Function: LogBeginTestLevel
|
|
// Purpose: Log the beginning of a new level, or minor group, of tests.
|
|
//
|
|
BOOL LogBeginTestLevel(DWORD dwLevel)
|
|
{
|
|
LPWSTR pwsz = NULL;
|
|
|
|
switch (dwLevel)
|
|
{
|
|
case TEST_LEVEL_CSP:
|
|
{
|
|
pwsz = L"TEST_LEVEL_CSP";
|
|
break;
|
|
}
|
|
case TEST_LEVEL_PROV:
|
|
{
|
|
pwsz = L"TEST_LEVEL_PROV";
|
|
break;
|
|
}
|
|
case TEST_LEVEL_HASH:
|
|
{
|
|
pwsz = L"TEST_LEVEL_HASH";
|
|
break;
|
|
}
|
|
case TEST_LEVEL_KEY:
|
|
{
|
|
pwsz = L"TEST_LEVEL_KEY";
|
|
break;
|
|
}
|
|
case TEST_LEVEL_CONTAINER:
|
|
{
|
|
pwsz = L"TEST_LEVEL_CONTAINER";
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If there has been a CSP Class-level error, don't start
|
|
// a new test level until the error has been cleared.
|
|
//
|
|
if (g_fCSPClassError)
|
|
{
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
g_dwCurrentTestLevel = dwLevel;
|
|
|
|
return ezStartBlock(
|
|
NULL,
|
|
NULL,
|
|
EZBLOCK_OUTCOME_INDEPENDENT /*EZBLOCK_TRACK_SUBBLOCKS*/,
|
|
CSP_PASS,
|
|
L"%s", pwsz);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Function: LogEndTestLevel
|
|
// Purpose: Log the completion of the current test level.
|
|
//
|
|
BOOL LogEndTestLevel(DWORD dwLevel)
|
|
{
|
|
if (g_dwCurrentTestLevel != dwLevel)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Clear Test Level error flag
|
|
//
|
|
if (g_fTestLevelError)
|
|
{
|
|
ezLogMsg(
|
|
CSP_ERROR_TEST_LEVEL,
|
|
NULL,
|
|
NULL,
|
|
__LINE__,
|
|
L"Test Level is ending prematurely");
|
|
|
|
g_fTestLevelError = FALSE;
|
|
}
|
|
|
|
return ezFinishBlock(0);
|
|
}
|
|
|
|
//
|
|
// Function: LogBeginAPI
|
|
// Purpose: Log the beginning of a set of API test cases
|
|
//
|
|
BOOL LogBeginAPI(API_NAME ApiName, DWORD dwAPISubset)
|
|
{
|
|
WCHAR rgwsz[BUFFER_SIZE];
|
|
|
|
//
|
|
// If there has been a Test Level error, don't start a new
|
|
// API set until the error has been cleared.
|
|
//
|
|
if (g_fTestLevelError)
|
|
{
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
g_dwTestCaseIDMajor++;
|
|
g_CurrentAPI = ApiName;
|
|
g_dwCurrentAPISubset = dwAPISubset;
|
|
|
|
ApiNameToString(ApiName, rgwsz);
|
|
wcscpy(rgwsz + wcslen(rgwsz), L", ");
|
|
TestCaseTypeToString(
|
|
dwAPISubset,
|
|
rgwsz + wcslen(rgwsz));
|
|
|
|
return ezStartBlock(
|
|
NULL,
|
|
NULL,
|
|
EZBLOCK_OUTCOME_INDEPENDENT /*EZBLOCK_TRACK_SUBBLOCKS*/,
|
|
CSP_PASS,
|
|
L"API %s",
|
|
rgwsz);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Function: LogEndAPI
|
|
// Purpose: Log the completion of a set of API test cases
|
|
//
|
|
BOOL LogEndAPI(API_NAME ApiName, DWORD dwAPISubset)
|
|
{
|
|
if ( (g_CurrentAPI != ApiName) ||
|
|
(g_dwCurrentAPISubset != dwAPISubset))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Clear API-level error flag
|
|
//
|
|
g_fAPIError = FALSE;
|
|
|
|
return ezFinishBlock(0);
|
|
}
|
|
|
|
//
|
|
// Function: LogPass
|
|
// Purpose: Log a successful test case
|
|
//
|
|
BOOL LogPass(DWORD dwTestCaseID)
|
|
{
|
|
return ezLogMsg(
|
|
CSP_PASS,
|
|
NULL,
|
|
NULL,
|
|
__LINE__,
|
|
L"Test case %d.%d: PASS",
|
|
g_dwTestCaseIDMajor,
|
|
dwTestCaseID);
|
|
}
|
|
|
|
//
|
|
// Function: LogBeginScenarioTest
|
|
// Purpose: Log the beginning of a Scenario Test.
|
|
//
|
|
BOOL LogBeginScenarioTest(LPWSTR pwszDescription)
|
|
{
|
|
g_dwTestCaseIDMajor++;
|
|
return ezStartBlock(
|
|
NULL,
|
|
NULL,
|
|
EZBLOCK_OUTCOME_INDEPENDENT,
|
|
CSP_PASS,
|
|
L"Scenario test case - %s",
|
|
pwszDescription);
|
|
}
|
|
|
|
//
|
|
// Function: LogEndScenarioTest
|
|
// Purpose: Log the end of a Scenario Test
|
|
//
|
|
BOOL LogEndScenarioTest(void)
|
|
{
|
|
//
|
|
// Clear API-level error flag
|
|
//
|
|
g_fAPIError = FALSE;
|
|
|
|
return ezFinishBlock(0);
|
|
}
|
|
|
|
//
|
|
// Function: LogBeginInteropTest
|
|
// Purpose: Log the beginning of an Interoperability Test.
|
|
//
|
|
BOOL LogBeginInteropTest(LPWSTR pwszDescription)
|
|
{
|
|
g_dwTestCaseIDMajor++;
|
|
return ezStartBlock(
|
|
NULL,
|
|
NULL,
|
|
EZBLOCK_OUTCOME_INDEPENDENT,
|
|
CSP_PASS,
|
|
L"Interoperability test case - %s",
|
|
pwszDescription);
|
|
}
|
|
|
|
//
|
|
// Function: LogEndInteropTest
|
|
// Purpose: Log the end of an Interoperability Test
|
|
//
|
|
BOOL LogEndInteropTest(void)
|
|
{
|
|
//
|
|
// Clear API-level error flag
|
|
//
|
|
g_fAPIError = FALSE;
|
|
|
|
return ezFinishBlock(0);
|
|
}
|
|
|
|
//
|
|
// Function: DoError
|
|
// Purpose: Perform the operations for handling a test case error
|
|
//
|
|
BOOL DoError(DWORD dwTestCaseID, DWORD dwReportedErrorLevel)
|
|
{
|
|
LPWSTR pwszErrorLevel = NULL;
|
|
DWORD dwErrorLevel = dwReportedErrorLevel & (CSP_ERROR_CONTINUE | CSP_ERROR_API);
|
|
|
|
switch (dwErrorLevel)
|
|
{
|
|
case CSP_ERROR_CONTINUE:
|
|
pwszErrorLevel = L"ERROR_CONTINUE";
|
|
break;
|
|
case CSP_ERROR_API:
|
|
pwszErrorLevel = L"ERROR_API";
|
|
break;
|
|
}
|
|
|
|
//
|
|
// The dwErrorLevel is being masked to limit the scope of the
|
|
// error being reported at this point. If a test case fails,
|
|
// only ERROR_CONTINUE and ERROR_API (and ERROR_WARNING) errors
|
|
// will be reported. If a more severe error has been flagged,
|
|
// it will be reported when the appropriate Test Level or CSP Class
|
|
// block ends.
|
|
//
|
|
return ezLogMsg(
|
|
dwErrorLevel,
|
|
NULL,
|
|
NULL,
|
|
__LINE__,
|
|
L"Test case %d.%d: %s",
|
|
g_dwTestCaseIDMajor,
|
|
dwTestCaseID,
|
|
pwszErrorLevel);
|
|
}
|
|
|
|
//
|
|
// Function: DoWarning
|
|
// Purpose: Perform the operations for handling a test case warning
|
|
//
|
|
BOOL DoWarning(DWORD dwTestCaseID)
|
|
{
|
|
return ezLogMsg(
|
|
CSP_ERROR_WARNING,
|
|
NULL,
|
|
NULL,
|
|
__LINE__,
|
|
L"Test case %d.%d: WARNING",
|
|
g_dwTestCaseIDMajor,
|
|
dwTestCaseID);
|
|
}
|
|
|
|
//
|
|
// Function: LogTestCaseSeparator
|
|
//
|
|
BOOL LogTestCaseSeparator(BOOL fLogToConsole)
|
|
{
|
|
if (fLogToConsole)
|
|
{
|
|
return ezLogMsg(
|
|
LOG_SEPARATOR_CONSOLE,
|
|
NULL,
|
|
NULL,
|
|
__LINE__,
|
|
TEST_CASE_SEPARATOR);
|
|
}
|
|
else
|
|
{
|
|
return ezLogMsg(
|
|
LOG_SEPARATOR,
|
|
NULL,
|
|
NULL,
|
|
__LINE__,
|
|
TEST_CASE_SEPARATOR);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Function: LogTestCase
|
|
//
|
|
BOOL LogTestCase(PLOGTESTCASEINFO pLogTestCaseInfo)
|
|
{
|
|
BOOL fReturn = TRUE;
|
|
DWORD dwActualErrorLevel = pLogTestCaseInfo->dwErrorLevel;
|
|
//LPWSTR pwszExpected = NULL;
|
|
//LPWSTR pwszActual = NULL;
|
|
LPWSTR pwsz = NULL;
|
|
BOOL fLogToConsole = FALSE;
|
|
DWORD dwLogApiName = LOG_API_NAME;
|
|
DWORD dwLogInfo = LOG_INFO;
|
|
WCHAR rgwsz[BUFFER_SIZE];
|
|
|
|
if (pLogTestCaseInfo->fPass)
|
|
{
|
|
LogTestCaseSeparator(FALSE);
|
|
LogPass(pLogTestCaseInfo->dwTestCaseID);
|
|
goto Return;
|
|
}
|
|
|
|
if (KNOWN_ERROR_UNKNOWN != pLogTestCaseInfo->KnownErrorID)
|
|
{
|
|
dwActualErrorLevel = GetKnownErrorValue(
|
|
pLogTestCaseInfo->KnownErrorID,
|
|
dwActualErrorLevel);
|
|
}
|
|
|
|
if (dwActualErrorLevel & CSP_ERROR_WARNING)
|
|
{
|
|
//
|
|
// Don't look for other error flags if a warning has been flagged,
|
|
// just handle the warning and return.
|
|
//
|
|
//fLogToConsole = TRUE;
|
|
LogTestCaseSeparator(fLogToConsole);
|
|
DoWarning(pLogTestCaseInfo->dwTestCaseID);
|
|
|
|
goto Return;
|
|
}
|
|
|
|
if (dwActualErrorLevel &
|
|
(CSP_ERROR_CONTINUE | CSP_ERROR_API |
|
|
CSP_ERROR_TEST_LEVEL | CSP_ERROR_CSP_CLASS |
|
|
CSP_ERROR_TEST_SUITE))
|
|
{
|
|
fLogToConsole = TRUE;
|
|
LogTestCaseSeparator(fLogToConsole);
|
|
DoError(pLogTestCaseInfo->dwTestCaseID, dwActualErrorLevel);
|
|
}
|
|
|
|
if (dwActualErrorLevel & CSP_ERROR_API)
|
|
{
|
|
g_fAPIError = TRUE;
|
|
fReturn = FALSE;
|
|
}
|
|
|
|
if (dwActualErrorLevel & CSP_ERROR_TEST_LEVEL)
|
|
{
|
|
g_fTestLevelError = TRUE;
|
|
}
|
|
|
|
if (dwActualErrorLevel & CSP_ERROR_CSP_CLASS)
|
|
{
|
|
g_fCSPClassError = TRUE;
|
|
}
|
|
|
|
if (dwActualErrorLevel & CSP_ERROR_TEST_SUITE)
|
|
{
|
|
g_fTestSuiteError = TRUE;
|
|
}
|
|
|
|
Return:
|
|
|
|
if (fLogToConsole)
|
|
{
|
|
dwLogApiName = LOG_API_NAME_CONSOLE;
|
|
dwLogInfo = LOG_INFO_CONSOLE;
|
|
}
|
|
|
|
ApiNameToString(pLogTestCaseInfo->ApiName, rgwsz);
|
|
ezLogMsg(
|
|
dwLogApiName,
|
|
NULL,
|
|
NULL,
|
|
__LINE__,
|
|
L"%s", rgwsz);
|
|
|
|
ezLogMsg(
|
|
dwLogInfo,
|
|
NULL,
|
|
NULL,
|
|
__LINE__,
|
|
L"Returned: %s",
|
|
pLogTestCaseInfo->fReturnVal ? STRING_TRUE : STRING_FALSE);
|
|
|
|
if (! pLogTestCaseInfo->fPass)
|
|
{
|
|
switch (pLogTestCaseInfo->dwErrorType)
|
|
{
|
|
case ERROR_API_SUCCEEDED:
|
|
pwsz = L"API succeeded unexpectedly";
|
|
break;
|
|
case ERROR_API_FAILED:
|
|
pwsz = L"API failed unexpectedly";
|
|
break;
|
|
case ERROR_WRONG_ERROR_CODE:
|
|
pwsz = L"API returned an incorrect error code";
|
|
break;
|
|
case ERROR_WIN32_FAILURE:
|
|
pwsz = L"A WIN32 (non-CSP) API failed";
|
|
break;
|
|
case ERROR_WRONG_SIZE:
|
|
pwsz = L"The API returned an incorrect data size";
|
|
break;
|
|
case ERROR_BAD_DATA:
|
|
pwsz = L"The API returned bad data";
|
|
break;
|
|
case ERROR_LIST_TOO_SHORT:
|
|
pwsz = L"The list of algorithms is too short";
|
|
break;
|
|
case ERROR_REQUIRED_ALG:
|
|
pwsz = L"A required algorithm is missing";
|
|
break;
|
|
}
|
|
|
|
ezLogMsg(
|
|
dwLogInfo,
|
|
NULL,
|
|
NULL,
|
|
__LINE__,
|
|
L"Error type: %s", pwsz);
|
|
|
|
//
|
|
// Display details about the known error status here,
|
|
// after the Error/Warning has been processed above.
|
|
//
|
|
ezLogMsg(
|
|
dwLogInfo,
|
|
NULL,
|
|
NULL,
|
|
__LINE__,
|
|
L"Known error: %s",
|
|
(KNOWN_ERROR_UNKNOWN == pLogTestCaseInfo->KnownErrorID) ? L"No" : L"Yes");
|
|
|
|
if (ERROR_WRONG_ERROR_CODE == pLogTestCaseInfo->dwErrorType)
|
|
{
|
|
FormatMessage(
|
|
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_MAX_WIDTH_MASK,
|
|
NULL,
|
|
pLogTestCaseInfo->dwExpectedErrorCode,
|
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
rgwsz,
|
|
BUFFER_SIZE,
|
|
NULL);
|
|
|
|
ezLogMsg(
|
|
dwLogInfo,
|
|
NULL,
|
|
NULL,
|
|
__LINE__,
|
|
L"Expected error code: 0x%x (%s)",
|
|
pLogTestCaseInfo->dwExpectedErrorCode,
|
|
rgwsz);
|
|
*rgwsz = L'\0';
|
|
}
|
|
|
|
if ( FALSE == pLogTestCaseInfo->fReturnVal ||
|
|
ERROR_API_FAILED == pLogTestCaseInfo->dwErrorType ||
|
|
ERROR_WRONG_ERROR_CODE == pLogTestCaseInfo->dwErrorType ||
|
|
ERROR_WIN32_FAILURE == pLogTestCaseInfo->dwErrorType)
|
|
{
|
|
// Don't get the error string if the error code is 0
|
|
*rgwsz = L'\0';
|
|
if (0 != pLogTestCaseInfo->dwWinError)
|
|
{
|
|
FormatMessage(
|
|
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_MAX_WIDTH_MASK,
|
|
NULL,
|
|
pLogTestCaseInfo->dwWinError,
|
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
rgwsz,
|
|
BUFFER_SIZE,
|
|
NULL);
|
|
}
|
|
ezLogMsg(
|
|
dwLogInfo,
|
|
NULL,
|
|
NULL,
|
|
__LINE__,
|
|
L"Actual error code: 0x%x (%s)",
|
|
pLogTestCaseInfo->dwWinError,
|
|
rgwsz);
|
|
*rgwsz = L'\0';
|
|
}
|
|
|
|
//
|
|
// Log details about this failure
|
|
//
|
|
if (NULL != pLogTestCaseInfo->pwszErrorHelp)
|
|
{
|
|
ezLogMsg(
|
|
dwLogInfo,
|
|
NULL,
|
|
NULL,
|
|
__LINE__,
|
|
L"Test case description: %s",
|
|
pLogTestCaseInfo->pwszErrorHelp);
|
|
}
|
|
}
|
|
|
|
LogParamInfo(
|
|
pLogTestCaseInfo->pParamInfo,
|
|
pLogTestCaseInfo->cParamInfo,
|
|
fLogToConsole);
|
|
|
|
return fReturn;
|
|
}
|
|
|
|
//
|
|
// Function: LogGetInteropProvType
|
|
//
|
|
DWORD LogGetInteropProvType(void)
|
|
{
|
|
return g_dwInteropProvType;
|
|
}
|
|
|
|
//
|
|
// Function: LogGetInteropProvName
|
|
//
|
|
LPWSTR LogGetInteropProvName(void)
|
|
{
|
|
return g_pwszInteropProvName;
|
|
}
|
|
|
|
//
|
|
// Function: LogGetProvType
|
|
// Purpose: Return the provider type for which the CSP under
|
|
// test is registered (in the system registry).
|
|
//
|
|
DWORD LogGetProvType(void)
|
|
{
|
|
return g_dwExternalProvType;
|
|
}
|
|
|
|
//
|
|
// Function: LogGetProvName
|
|
// Purpose: Return the provider name for which the CSP under
|
|
// test is registered (in the system registry).
|
|
//
|
|
LPWSTR LogGetProvName(void)
|
|
{
|
|
return g_pwszProvName;
|
|
}
|
|
|
|
//
|
|
// Function: LogApiFailure
|
|
//
|
|
BOOL LogApiFailure(
|
|
IN API_NAME ApiName,
|
|
IN DWORD dwErrorType,
|
|
IN OUT PTESTCASE ptc)
|
|
{
|
|
LOGTESTCASEINFO LogTestCaseInfo;
|
|
|
|
InitLogTestCaseInfo(ptc, &LogTestCaseInfo);
|
|
|
|
LogTestCaseInfo.ApiName = ApiName;
|
|
LogTestCaseInfo.dwErrorType = dwErrorType;
|
|
LogTestCaseInfo.fPass = FALSE;
|
|
|
|
return LogTestCase(&LogTestCaseInfo);
|
|
}
|
|
|
|
//
|
|
// Function: CheckAndLogStatus
|
|
//
|
|
BOOL CheckAndLogStatus(
|
|
IN API_NAME ApiName,
|
|
IN BOOL fCallSucceeded,
|
|
IN OUT PTESTCASE ptc,
|
|
IN PAPI_PARAM_INFO pParamInfo,
|
|
IN DWORD cParamInfo)
|
|
{
|
|
DWORD dwWinError = 0;
|
|
//DWORD dwTestCaseID = 0;
|
|
LOGTESTCASEINFO LogTestCaseInfo;
|
|
|
|
InitLogTestCaseInfo(ptc, &LogTestCaseInfo);
|
|
LogTestCaseInfo.fReturnVal = fCallSucceeded;
|
|
|
|
if (! fCallSucceeded)
|
|
{
|
|
dwWinError = GetLastError();
|
|
|
|
if (ptc->fExpectSuccess)
|
|
{
|
|
//
|
|
// Test was expected to succeed, but it failed
|
|
//
|
|
LogTestCaseInfo.dwErrorType = ERROR_API_FAILED;
|
|
LogTestCaseInfo.dwWinError = dwWinError;
|
|
}
|
|
else
|
|
{
|
|
if (dwWinError != ptc->dwErrorCode)
|
|
{
|
|
//
|
|
// Test failed as expected, but returned the wrong
|
|
// error code.
|
|
//
|
|
LogTestCaseInfo.dwWinError = dwWinError;
|
|
LogTestCaseInfo.dwErrorType = ERROR_WRONG_ERROR_CODE;
|
|
}
|
|
|
|
//
|
|
// Otherwise, the test failed as expected, and it
|
|
// returned the correct error code.
|
|
//
|
|
else
|
|
{
|
|
LogTestCaseInfo.fPass = TRUE;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (! ptc->fExpectSuccess)
|
|
{
|
|
//
|
|
// The test was expected to fail, but it succeeded.
|
|
//
|
|
LogTestCaseInfo.dwErrorType = ERROR_API_SUCCEEDED;
|
|
}
|
|
|
|
//
|
|
// Otherwise, the test succeeded as expected.
|
|
//
|
|
else
|
|
{
|
|
LogTestCaseInfo.fPass = TRUE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Now dwErrorType will be non-zero in any of three cases:
|
|
// 1) The API should have succeeded, but failed
|
|
// 2) The API should have failed, but succeeded
|
|
// 3) The API failed as expected, but returned the wrong error code
|
|
//
|
|
if (0 != LogTestCaseInfo.dwErrorType)
|
|
{
|
|
LogTestCaseInfo.dwErrorLevel = ptc->dwErrorLevel;
|
|
LogTestCaseInfo.dwExpectedErrorCode = ptc->dwErrorCode;
|
|
|
|
//
|
|
// The Microsoft RSA CSP's in Win2K do not return
|
|
// ERROR_INVALID_HANDLE for most, if not all, of the test cases
|
|
// involving that error code in this test suite. Therefore,
|
|
// intercept those error here, and flag them as known for that
|
|
// platform.
|
|
//
|
|
if ( (ERROR_WRONG_ERROR_CODE == LogTestCaseInfo.dwErrorType) &&
|
|
(ERROR_INVALID_HANDLE == LogTestCaseInfo.dwExpectedErrorCode))
|
|
{
|
|
LogTestCaseInfo.KnownErrorID = KNOWN_ERRORINVALIDHANDLE;
|
|
}
|
|
|
|
//
|
|
// The Microsoft RSA CSP's in Win2K do not return
|
|
// NTE_BAD_KEY for the negative test cases involving that
|
|
// error code. Intercept those errors here and flag them as
|
|
// known for that platform.
|
|
//
|
|
if ( (ERROR_WRONG_ERROR_CODE == LogTestCaseInfo.dwErrorType) &&
|
|
(NTE_BAD_KEY == LogTestCaseInfo.dwExpectedErrorCode))
|
|
{
|
|
LogTestCaseInfo.KnownErrorID = KNOWN_NTEBADKEY;
|
|
}
|
|
|
|
//
|
|
// The Microsoft RSA CSP's in Win2K do not return NTE_BAD_HASH
|
|
// for the negative test cases involving that error code. Intercept
|
|
// those errors here and flag them as known for that platform.
|
|
//
|
|
if ( (ERROR_WRONG_ERROR_CODE == LogTestCaseInfo.dwErrorType) &&
|
|
(NTE_BAD_HASH == LogTestCaseInfo.dwExpectedErrorCode))
|
|
{
|
|
LogTestCaseInfo.KnownErrorID = KNOWN_NTEBADHASH;
|
|
}
|
|
}
|
|
|
|
// Finally, increment the current test case ID
|
|
++ptc->dwTestCaseID;
|
|
LogTestCaseInfo.dwTestCaseID = ptc->dwTestCaseID;
|
|
LogTestCaseInfo.pParamInfo = pParamInfo;
|
|
LogTestCaseInfo.cParamInfo = cParamInfo;
|
|
LogTestCaseInfo.ApiName = ApiName;
|
|
|
|
return LogTestCase(&LogTestCaseInfo);
|
|
}
|
|
|
|
//
|
|
// Function: InitFailInfo
|
|
//
|
|
void InitLogTestCaseInfo(
|
|
IN PTESTCASE ptc,
|
|
OUT PLOGTESTCASEINFO pLogTestCaseInfo)
|
|
{
|
|
memset(pLogTestCaseInfo, 0, sizeof(LOGTESTCASEINFO));
|
|
|
|
pLogTestCaseInfo->dwErrorLevel = ptc->dwErrorLevel;
|
|
pLogTestCaseInfo->dwExpectedErrorCode = ptc->dwErrorCode;
|
|
pLogTestCaseInfo->dwTestCaseID = ptc->dwTestCaseID;
|
|
pLogTestCaseInfo->KnownErrorID = ptc->KnownErrorID;
|
|
pLogTestCaseInfo->pwszErrorHelp = ptc->pwszErrorHelp;
|
|
}
|
|
|
|
//
|
|
// Function: LogBadParam
|
|
//
|
|
BOOL LogBadParam(
|
|
API_NAME ApiName,
|
|
LPWSTR pwszErrorHelp,
|
|
PTESTCASE ptc)
|
|
{
|
|
LOGTESTCASEINFO LogTestCaseInfo;
|
|
|
|
++ptc->dwTestCaseID;
|
|
InitLogTestCaseInfo(ptc, &LogTestCaseInfo);
|
|
|
|
LogTestCaseInfo.ApiName = ApiName;
|
|
LogTestCaseInfo.dwErrorType = ERROR_BAD_DATA;
|
|
LogTestCaseInfo.pwszErrorHelp = pwszErrorHelp;
|
|
LogTestCaseInfo.fPass = FALSE;
|
|
|
|
return LogTestCase(&LogTestCaseInfo);
|
|
}
|
|
|
|
//
|
|
// Function: LogProvEnumalgsEx
|
|
//
|
|
void LogProvEnumalgsEx(PROV_ENUMALGS_EX *pData)
|
|
{
|
|
LPWSTR pwszAlgType = NULL;
|
|
LPWSTR pwszName = MkWStr(pData->szName);
|
|
LPWSTR pwszLongName = MkWStr(pData->szLongName);
|
|
|
|
// Determine the algorithm type.
|
|
switch(GET_ALG_CLASS(pData->aiAlgid))
|
|
{
|
|
case ALG_CLASS_DATA_ENCRYPT: pwszAlgType = L"Encrypt ";
|
|
break;
|
|
case ALG_CLASS_HASH: pwszAlgType = L"Hash ";
|
|
break;
|
|
case ALG_CLASS_KEY_EXCHANGE: pwszAlgType = L"Exchange ";
|
|
break;
|
|
case ALG_CLASS_SIGNATURE: pwszAlgType = L"Signature";
|
|
break;
|
|
default: pwszAlgType = L"Unknown ";
|
|
}
|
|
|
|
// Print information about the algorithm.
|
|
ezLogMsg(
|
|
LOG_INFO,
|
|
NULL,
|
|
NULL,
|
|
__LINE__,
|
|
L"Algid:%8.8xh, Bits:%-4d, %-4d - %-4d, Type:%s",
|
|
pData->aiAlgid,
|
|
pData->dwDefaultLen,
|
|
pData->dwMinLen,
|
|
pData->dwMaxLen,
|
|
pwszAlgType);
|
|
|
|
ezLogMsg(
|
|
LOG_INFO,
|
|
NULL,
|
|
NULL,
|
|
__LINE__,
|
|
L" Name: %s LongName: %s Protocols: 0x%x",
|
|
pwszName,
|
|
pwszLongName,
|
|
pData->dwProtocols);
|
|
|
|
free(pwszName);
|
|
free(pwszLongName);
|
|
}
|
|
|
|
//
|
|
// Function: LogProvEnumalgs
|
|
// Purpose: Log the contents of a PROV_ENUMALGS struct
|
|
//
|
|
void LogProvEnumalgs(PROV_ENUMALGS *pData)
|
|
{
|
|
LPWSTR pwszAlgType = NULL;
|
|
LPWSTR pwszName = MkWStr(pData->szName);
|
|
|
|
// Determine the algorithm type.
|
|
switch(GET_ALG_CLASS(pData->aiAlgid))
|
|
{
|
|
case ALG_CLASS_DATA_ENCRYPT: pwszAlgType = L"Encrypt ";
|
|
break;
|
|
case ALG_CLASS_HASH: pwszAlgType = L"Hash ";
|
|
break;
|
|
case ALG_CLASS_KEY_EXCHANGE: pwszAlgType = L"Exchange ";
|
|
break;
|
|
case ALG_CLASS_SIGNATURE: pwszAlgType = L"Signature";
|
|
break;
|
|
default: pwszAlgType = L"Unknown ";
|
|
}
|
|
|
|
// Print information about the algorithm.
|
|
ezLogMsg(
|
|
LOG_INFO,
|
|
NULL,
|
|
NULL,
|
|
__LINE__,
|
|
L"Algid:%8.8xh, Bits:%-4d, Type:%s, NameLen:%-2d, Name:%s",
|
|
pData->aiAlgid,
|
|
pData->dwBitLen,
|
|
pwszAlgType,
|
|
pData->dwNameLen,
|
|
pwszName);
|
|
|
|
free(pwszName);
|
|
}
|