windows-nt/Source/XPSP1/NT/ds/win32/ntcrypto/test/testsuit/csptestsuite.c
2020-09-26 16:20:57 +08:00

9311 lines
243 KiB
C

/*
CSPTestSuite.c
4/23/00 dangriff created
---Introduction---
This is the framework code for the Cryptographic Service Provider Test Suite.
External CSP types (such as PROV_RSA_SIG, defined in wincrypt.h) are internally assigned
both a CSP_TYPE and a CLASS value (defined below). This combination of values determines
which test cases and algorithms will be used to exercise a given CSP.
---Sample Test Execution---
For a sample PROV_RSA_FULL CSP called "MyCSP", the test suite would be run with the following
options:
csptestsuite -n MyCSP -t 1
The flow of the test in this example would be:
* Lookup the test suite mappings for PROV_RSA_FULL. They are CSP_TYPE_RSA and
CLASS_SIG_ONLY | CLASS_SIG_KEYX | CLASS_FULL.
* Begin running all tests for CLASS_SIG_ONLY
* Begin running all TEST_LEVEL_CSP tests for this class. For example, this test level
consists of the API's CryptAcquireContext (partial; some CryptAcquireContext tests
are TEST_LEVEL_CONTAINER), CryptGetProvParam, CryptSetProvParam, and CryptReleaseContext.
Note that some TEST_LEVEL test case sets may be empty for a given class.
* Begin running all TEST_LEVEL_PROV tests for this class
* Begin running all TEST_LEVEL_HASH tests for this class
* Begin running all TEST_LEVEL_KEY tests for this class
* Begin running all TEST_LEVEL_CONTAINER tests for this class
* Begin running all tests for CLASS_SIG_KEYX
* Begin running all TEST_LEVEL_CSP tests for this class. Note that each TEST_LEVEL set of
test cases for a given CLASS is unique. No individual test case will be run twice.
* Similarly for TEST_LEVEL_PROV, TEST_LEVEL_HASH, TEST_LEVEL_KEY, and TEST_LEVEL_CONTAINER.
* Begin running all tests for CLASS_FULL
* As above for TEST_LEVEL_CSP, TEST_LEVEL_PROV, TEST_LEVEL_HASH, TEST_LEVEL_KEY,
and TEST_LEVEL_CONTAINER.
* End. Report the test results.
---Supported CSP Types---
PROV_RSA_SIG
PROV_RSA_FULL
*/
#include <windows.h>
#include <wincrypt.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "csptestsuite.h"
#include "logging.h"
#include "interop.h"
#include "utils.h"
//
// Function: Usage
// Purpose: Display list of command line options to console
//
void Usage()
{
WCHAR rgwsz [BUFFER_SIZE];
wprintf(
L"Usage: %s -c <CSP> [ -t <Test> ] [ -i <Interop CSP> ]\n",
TEST_APP_NAME);
wprintf(L"\n<Test> options:\n");
TestCaseTypeToString(TEST_CASES_POSITIVE, rgwsz);
wprintf(
L" %d: %s (default)\n",
TEST_CASES_POSITIVE,
rgwsz);
TestCaseTypeToString(TEST_CASES_NEGATIVE, rgwsz);
wprintf(
L" %d: %s\n",
TEST_CASES_NEGATIVE,
rgwsz);
TestCaseTypeToString(TEST_CASES_SCENARIO, rgwsz);
wprintf(
L" %d: %s\n",
TEST_CASES_SCENARIO,
rgwsz);
TestCaseTypeToString(TEST_CASES_INTEROP, rgwsz);
wprintf(
L" %d: %s\n",
TEST_CASES_INTEROP,
rgwsz);
wprintf(L"\nLog file is %s in the current directory.\n", LOGFILE);
}
//
// Function: IsVersionCorrect
//
//
BOOL IsVersionCorrect(
IN DWORD dwMajorVersion,
IN DWORD dwMinorVersion,
IN DWORD dwServicePackMajor,
IN DWORD dwServicePackMinor)
{
DWORDLONG dwlConditionMask = 0;
OSVERSIONINFOEX OsviEx;
memset(&OsviEx, 0, sizeof(OsviEx));
OsviEx.dwOSVersionInfoSize = sizeof(OsviEx);
OsviEx.dwMajorVersion = dwMajorVersion;
OsviEx.dwMinorVersion = dwMinorVersion;
OsviEx.wServicePackMajor = (WORD) dwServicePackMajor;
OsviEx.wServicePackMinor = (WORD) dwServicePackMinor;
//
// We want to check that the system has a less than
// or equal Rev to the caller parameters.
//
dwlConditionMask =
VerSetConditionMask(0, VER_MAJORVERSION, VER_LESS_EQUAL);
dwlConditionMask =
VerSetConditionMask(dwlConditionMask, VER_MINORVERSION, VER_LESS_EQUAL);
dwlConditionMask =
VerSetConditionMask(dwlConditionMask, VER_SERVICEPACKMAJOR, VER_LESS_EQUAL);
dwlConditionMask =
VerSetConditionMask(dwlConditionMask, VER_SERVICEPACKMINOR, VER_LESS_EQUAL);
return VerifyVersionInfo(
&OsviEx,
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
dwlConditionMask);
}
//
// Function: GetNextRegisteredCSP
//
DWORD GetNextRegisteredCSP(
OUT LPWSTR pwszCsp,
IN OUT PDWORD pcbCsp,
OUT PDWORD pdwProvType,
IN DWORD dwRequestedIndex)
{
static DWORD dwNextEnumIndex = 0;
DWORD dwActualIndex = 0;
DWORD dwError = 0;
dwActualIndex =
(ENUMERATE_REGISTERED_CSP == dwRequestedIndex) ? dwNextEnumIndex : dwRequestedIndex;
if (! CryptEnumProviders(
dwActualIndex,
NULL,
0,
pdwProvType,
pwszCsp,
pcbCsp))
{
dwError = GetLastError();
switch (dwError)
{
case ERROR_NO_MORE_ITEMS:
dwNextEnumIndex = 0;
break;
}
}
else
{
if (ENUMERATE_REGISTERED_CSP == dwRequestedIndex)
{
dwNextEnumIndex++;
}
}
return dwError;
}
//
// -----------------
// Utility functions
// -----------------
//
//
// Function: IsRequiredAlg
//
BOOL IsRequiredAlg(
IN ALG_ID ai,
IN DWORD dwInternalProvType)
{
DWORD cItems = 0;
PALGID_TABLE pTable = NULL;
switch (dwInternalProvType)
{
case CSP_TYPE_RSA:
{
cItems = sizeof(g_RequiredAlgs_RSA) / sizeof(ALGID_TABLE);
pTable = g_RequiredAlgs_RSA;
break;
}
case CSP_TYPE_AES:
{
cItems = sizeof(g_RequiredAlgs_AES) / sizeof(ALGID_TABLE);
pTable = g_RequiredAlgs_AES;
break;
}
default:
{
return FALSE;
}
}
while (cItems > 0)
{
if (ai == pTable[cItems - 1].ai)
{
return TRUE;
}
else
{
cItems--;
}
}
return FALSE;
}
//
// Function: IsKnownAlg
//
BOOL IsKnownAlg(ALG_ID ai, DWORD dwInternalProvType)
{
DWORD cItems = 0;
PALGID_TABLE pTable = NULL;
switch (dwInternalProvType)
{
case CSP_TYPE_RSA:
{
cItems = sizeof(g_OtherKnownAlgs_RSA) / sizeof(ALGID_TABLE);
pTable = g_OtherKnownAlgs_RSA;
break;
}
case CSP_TYPE_AES:
{
cItems = sizeof(g_OtherKnownAlgs_AES) / sizeof(ALGID_TABLE);
pTable = g_OtherKnownAlgs_AES;
break;
}
default:
{
return FALSE;
}
}
while (cItems > 0)
{
if (ai == pTable[cItems - 1].ai)
{
return TRUE;
}
else
{
cItems--;
}
}
return FALSE;
}
//
// -------------------
// Crypto API wrappers
// -------------------
//
//
// Function: TAcquire
// Purpose: Call CryptAcquireContext with the supplied parameters and pass
// the result to the logging routine.
//
BOOL TAcquire(
HCRYPTPROV *phProv,
LPWSTR pszContainer,
LPWSTR pszProvider,
DWORD dwProvType,
DWORD dwFlags,
PTESTCASE ptc)
{
BOOL fApiSuccessful = FALSE;
//BOOL fUnexpected = TRUE;
BOOL fContinue = FALSE;
DWORD cbData = sizeof(HCRYPTPROV);
API_PARAM_INFO ParamInfo [] = {
{ L"phProv", Pointer, 0, NULL, TRUE, &cbData, NULL },
{ L"pszContainer", String, 0, NULL, FALSE, NULL, NULL },
{ L"pszProvider", String, 0, NULL, FALSE, NULL, NULL },
{ L"dwProvType", Dword, dwProvType, NULL, FALSE, NULL, NULL },
{ L"dwFlags", Dword, dwFlags, AcquireContextFlagToString, FALSE, NULL, NULL }
};
ParamInfo[0].pbParam = (PBYTE) phProv;
ParamInfo[1].pwszParam = pszContainer;
ParamInfo[2].pwszParam = pszProvider;
if (NULL == phProv)
{
fApiSuccessful =
CryptAcquireContext(
NULL,
pszContainer,
pszProvider,
dwProvType,
dwFlags);
}
else
{
fApiSuccessful =
CryptAcquireContext(
phProv,
pszContainer,
pszProvider,
dwProvType,
dwFlags);
}
fContinue = CheckAndLogStatus(
API_CRYPTACQUIRECONTEXT,
fApiSuccessful,
ptc,
ParamInfo,
APIPARAMINFO_SIZE(ParamInfo));
return fContinue;
}
//
// Function: TGetProv
// Purpose: Call CryptGetProvParam with the supplied parameters and pass
// the result to the logging routine.
//
BOOL TGetProv(
HCRYPTPROV hProv,
DWORD dwParam,
BYTE *pbData,
DWORD *pdwDataLen,
DWORD dwFlags,
PTESTCASE ptc)
{
BOOL fApiSuccessful = FALSE;
//BOOL fUnexpected = TRUE;
BOOL fContinue = FALSE;
DWORD cbData = sizeof(DWORD);
API_PARAM_INFO ParamInfo [] = {
{ L"hProv", Handle, 0, NULL, FALSE, NULL, NULL },
{ L"dwParam", Dword, dwParam, GetProvParamToString, FALSE, NULL, NULL },
{ L"pbData", Pointer, 0, NULL, TRUE, pdwDataLen, NULL },
{ L"pdwDataLen", Pointer, 0, NULL, TRUE, &cbData, NULL },
{ L"dwFlags", Dword, dwFlags, NULL, FALSE, NULL, NULL }
};
ParamInfo[0].pulParam = hProv;
ParamInfo[2].pbParam = pbData;
ParamInfo[3].pbParam = (PBYTE) pdwDataLen;
switch (dwParam)
{
case PP_ENUMALGS:
case PP_ENUMALGS_EX:
case PP_ENUMCONTAINERS:
{
ParamInfo[4].pfnFlagToString = ProvParamEnumFlagToString;
break;
}
case PP_KEYSET_SEC_DESCR:
{
ParamInfo[4].pfnFlagToString = ProvParamSecDescrFlagToString;
break;
}
case PP_IMPTYPE:
{
ParamInfo[4].pfnFlagToString = ProvParamImpTypeToString;
break;
}
}
if (! ptc->fEnumerating)
{
if (! LogInitParamInfo(
ParamInfo,
APIPARAMINFO_SIZE(ParamInfo),
ptc))
{
return FALSE;
}
}
fApiSuccessful = CryptGetProvParam(hProv, dwParam, pbData, pdwDataLen, dwFlags);
if (ptc->fEnumerating)
{
return fApiSuccessful;
}
fContinue = CheckAndLogStatus(
API_CRYPTGETPROVPARAM,
fApiSuccessful,
ptc,
ParamInfo,
APIPARAMINFO_SIZE(ParamInfo));
LogCleanupParamInfo(ParamInfo, APIPARAMINFO_SIZE(ParamInfo));
return fContinue;
}
//
// Function: TSetProv
// Purpose: Call CryptSetProvParam with the supplied parameters and pass
// the result to the logging routine.
//
BOOL TSetProv(
HCRYPTPROV hProv,
DWORD dwParam,
BYTE *pbData,
DWORD dwFlags,
PTESTCASE ptc)
{
BOOL fApiSuccessful = FALSE;
//BOOL fUnexpected = TRUE;
BOOL fContinue = FALSE;
API_PARAM_INFO ParamInfo [] = {
{ L"hProv", Handle, 0, NULL, FALSE, NULL, NULL },
{ L"dwParam", Dword, dwParam, SetProvParamToString, FALSE, NULL, NULL },
{ L"pbData", Pointer, 0, NULL, FALSE, NULL, NULL },
{ L"dwFlags", Dword, dwFlags, NULL, FALSE, NULL, NULL }
};
ParamInfo[0].pulParam = hProv;
ParamInfo[2].pbParam = pbData;
switch (dwParam)
{
case PP_KEYSET_SEC_DESCR:
{
ParamInfo[3].pfnFlagToString = ProvParamSecDescrFlagToString;
break;
}
case PP_IMPTYPE:
{
ParamInfo[3].pfnFlagToString = ProvParamImpTypeToString;
break;
}
}
fApiSuccessful = CryptSetProvParam(hProv, dwParam, pbData, dwFlags);
fContinue = CheckAndLogStatus(
API_CRYPTSETPROVPARAM,
fApiSuccessful,
ptc,
ParamInfo,
APIPARAMINFO_SIZE(ParamInfo));
return fContinue;
}
//
// Function: TRelease
// Purpose: Call CryptReleaseContext with the supplied parameters and pass
// the result to the logging routine.
//
BOOL TRelease(
HCRYPTPROV hProv,
DWORD dwFlags,
PTESTCASE ptc)
{
BOOL fApiSuccessful = FALSE;
//BOOL fUnexpected = TRUE;
BOOL fContinue = FALSE;
BOOL fSavedExpectSuccess = ptc->fExpectSuccess;
API_PARAM_INFO ParamInfo [] = {
{ L"hProv", Handle, 0, NULL, FALSE, NULL, NULL },
{ L"dwFlags", Dword, dwFlags, NULL, FALSE, NULL, NULL }
};
ParamInfo[0].pulParam = hProv;
if (! ptc->fTestingReleaseContext)
{
ptc->fExpectSuccess = TRUE;
}
fApiSuccessful = CryptReleaseContext(hProv, dwFlags);
fContinue = CheckAndLogStatus(
API_CRYPTRELEASECONTEXT,
fApiSuccessful,
ptc,
ParamInfo,
APIPARAMINFO_SIZE(ParamInfo));
ptc->fExpectSuccess = fSavedExpectSuccess;
return fContinue;
}
//
// Function: TGenRand
// Purpose: Call CryptGenRandom with the supplied parameters and pass
// the result to the logging routine.
//
BOOL TGenRand(
HCRYPTPROV hProv,
DWORD dwLen,
BYTE *pbBuffer,
PTESTCASE ptc)
{
BOOL fApiSuccessful = FALSE;
//BOOL fUnexpected = TRUE;
BOOL fContinue = FALSE;
API_PARAM_INFO ParamInfo [] = {
{ L"hProv", Handle, 0, NULL, FALSE, NULL, NULL },
{ L"dwLen", Dword, dwLen, NULL, FALSE, NULL, NULL },
{ L"pbBuffer", Pointer, 0, NULL, FALSE, NULL, NULL }
};
ParamInfo[0].pulParam = hProv;
ParamInfo[2].pbParam = pbBuffer;
fApiSuccessful = CryptGenRandom(hProv, dwLen, pbBuffer);
fContinue = CheckAndLogStatus(
API_CRYPTGENRANDOM,
fApiSuccessful,
ptc,
ParamInfo,
APIPARAMINFO_SIZE(ParamInfo));
return fContinue;
}
//
// Function: TCreateHash
// Purpose: Call CryptCreateHash with the supplied parameters and pass
// the result to the logging routine.
//
BOOL TCreateHash(
HCRYPTPROV hProv,
ALG_ID Algid,
HCRYPTKEY hKey,
DWORD dwFlags,
HCRYPTHASH *phHash,
PTESTCASE ptc)
{
BOOL fApiSuccessful = FALSE;
//BOOL fUnexpected = TRUE;
BOOL fContinue = FALSE;
DWORD cbData = sizeof(HCRYPTHASH);
API_PARAM_INFO ParamInfo [] = {
{ L"hProv", Handle, 0, NULL, FALSE, NULL, NULL },
{ L"Algid", Dword, Algid, AlgidToString, FALSE, NULL, NULL },
{ L"hKey", Handle, 0, NULL, FALSE, NULL, NULL },
{ L"dwFlags", Dword, dwFlags, NULL, FALSE, NULL, NULL },
{ L"phHash", Pointer, 0, NULL, TRUE, &cbData, NULL }
};
ParamInfo[0].pulParam = hProv;
ParamInfo[2].pulParam = hKey;
ParamInfo[4].pbParam = (PBYTE) phHash;
fApiSuccessful = CryptCreateHash(hProv, Algid, hKey, dwFlags, phHash);
fContinue = CheckAndLogStatus(
API_CRYPTCREATEHASH,
fApiSuccessful,
ptc,
ParamInfo,
APIPARAMINFO_SIZE(ParamInfo));
return fContinue;
}
//
// Function: TDestroyHash
// Purpose: Call CryptDestroyHash with the supplied parameters and pass
// the result to the logging routine.
//
BOOL TDestroyHash(
HCRYPTHASH hHash,
PTESTCASE ptc)
{
BOOL fApiSuccessful = FALSE;
//BOOL fUnexpected = TRUE;
BOOL fContinue = FALSE;
BOOL fSavedExpectSuccess = ptc->fExpectSuccess;
API_PARAM_INFO ParamInfo [] = {
{ L"hHash", Handle, 0, NULL, FALSE, NULL, NULL }
};
ParamInfo[0].pulParam = hHash;
if (! ptc->fTestingDestroyHash)
{
ptc->fExpectSuccess = TRUE;
}
fApiSuccessful = CryptDestroyHash(hHash);
fContinue = CheckAndLogStatus(
API_CRYPTDESTROYHASH,
fApiSuccessful,
ptc,
ParamInfo,
APIPARAMINFO_SIZE(ParamInfo));
ptc->fExpectSuccess = fSavedExpectSuccess;
return fContinue;
}
//
// Function: TDuplicateHash
// Purpose: Call CryptDuplicateHash with the supplied parameters and pass
// the result to the logging routine.
//
BOOL TDuplicateHash(
HCRYPTHASH hHash,
DWORD *pdwReserved,
DWORD dwFlags,
HCRYPTHASH *phHash,
PTESTCASE ptc)
{
BOOL fApiSuccessful = FALSE;
//BOOL fUnexpected = TRUE;
BOOL fContinue = FALSE;
API_PARAM_INFO ParamInfo [] = {
{ L"hHash", Handle, 0, NULL, FALSE, NULL, NULL },
{ L"pdwReserved", Pointer, 0, NULL, FALSE, NULL, NULL },
{ L"dwFlags", Dword, dwFlags, NULL, FALSE, NULL, NULL },
{ L"phHash", Pointer, 0, NULL, FALSE, NULL, NULL }
};
ParamInfo[0].pulParam = hHash;
ParamInfo[1].pbParam = (PBYTE) pdwReserved;
ParamInfo[3].pbParam = (PBYTE) phHash;
fApiSuccessful = CryptDuplicateHash(hHash, pdwReserved, dwFlags, phHash);
fContinue = CheckAndLogStatus(
API_CRYPTDUPLICATEHASH,
fApiSuccessful,
ptc,
ParamInfo,
APIPARAMINFO_SIZE(ParamInfo));
return fContinue;
}
//
// Function: TGetHash
// Purpose: Call CryptGetHashParam with the supplied parameters and pass
// the result to the logging routine.
//
BOOL TGetHash(
HCRYPTHASH hHash,
DWORD dwParam,
BYTE *pbData,
DWORD *pdwDataLen,
DWORD dwFlags,
PTESTCASE ptc)
{
BOOL fApiSuccessful = FALSE;
//BOOL fUnexpected = TRUE;
BOOL fContinue = FALSE;
DWORD cbData = sizeof(DWORD);
API_PARAM_INFO ParamInfo [] = {
{ L"hHash", Handle, 0, NULL, FALSE, NULL, NULL },
{ L"dwParam", Dword, dwParam, HashParamToString, FALSE, NULL, NULL },
{ L"pbData", Pointer, 0, NULL, TRUE, pdwDataLen, NULL },
{ L"pdwDataLen", Pointer, 0, NULL, TRUE, &cbData, NULL },
{ L"dwFlags", Dword, dwFlags, NULL, FALSE, NULL, NULL }
};
ParamInfo[0].pulParam = hHash;
ParamInfo[2].pbParam = pbData;
ParamInfo[3].pbParam = (PBYTE) pdwDataLen;
if (! LogInitParamInfo(
ParamInfo,
APIPARAMINFO_SIZE(ParamInfo),
ptc))
{
return FALSE;
}
fApiSuccessful = CryptGetHashParam(hHash, dwParam, pbData, pdwDataLen, dwFlags);
fContinue = CheckAndLogStatus(
API_CRYPTGETHASHPARAM,
fApiSuccessful,
ptc,
ParamInfo,
APIPARAMINFO_SIZE(ParamInfo));
LogCleanupParamInfo(
ParamInfo,
APIPARAMINFO_SIZE(ParamInfo));
return fContinue;
}
//
// Function: THashData
// Purpose: Call CryptHashData with the supplied parameters and pass
// the result to the logging routine.
//
BOOL THashData(
HCRYPTHASH hHash,
BYTE *pbData,
DWORD dwDataLen,
DWORD dwFlags,
PTESTCASE ptc)
{
BOOL fApiSuccessful = FALSE;
//BOOL fUnexpected = TRUE;
BOOL fContinue = FALSE;
API_PARAM_INFO ParamInfo [] = {
{ L"hHash", Handle, 0, NULL, FALSE, NULL, NULL },
{ L"pbData", Pointer, 0, NULL, TRUE, &dwDataLen, NULL },
{ L"dwDataLen", Dword, dwDataLen, NULL, FALSE, NULL, NULL },
{ L"dwFlags", Dword, dwFlags, HashDataFlagToString, FALSE, NULL, NULL }
};
ParamInfo[0].pulParam = hHash;
ParamInfo[1].pbParam = pbData;
if (! LogInitParamInfo(
ParamInfo,
APIPARAMINFO_SIZE(ParamInfo),
ptc))
{
return FALSE;
}
fApiSuccessful = CryptHashData(hHash, pbData, dwDataLen, dwFlags);
fContinue = CheckAndLogStatus(
API_CRYPTHASHDATA,
fApiSuccessful,
ptc,
ParamInfo,
APIPARAMINFO_SIZE(ParamInfo));
LogCleanupParamInfo(
ParamInfo,
APIPARAMINFO_SIZE(ParamInfo));
return fContinue;
}
//
// Function: TSetHash
// Purpose: Call CryptSetHashParam with the supplied parameters and pass
// the result to the logging routine.
//
BOOL TSetHash(
HCRYPTHASH hHash,
DWORD dwParam,
BYTE *pbData,
DWORD dwFlags,
PTESTCASE ptc)
{
BOOL fApiSuccessful = FALSE;
//BOOL fUnexpected = TRUE;
BOOL fContinue = FALSE;
API_PARAM_INFO ParamInfo [] = {
{ L"hHash", Handle, 0, NULL, FALSE, NULL, NULL },
{ L"dwParam", Dword, dwParam, HashParamToString, FALSE, NULL, NULL },
{ L"pbData", Pointer, 0, NULL, FALSE, NULL, NULL },
{ L"dwFlags", Dword, dwFlags, NULL, FALSE, NULL, NULL }
};
ParamInfo[0].pulParam = hHash;
ParamInfo[2].pbParam = pbData;
fApiSuccessful = CryptSetHashParam(hHash, dwParam, pbData, dwFlags);
fContinue = CheckAndLogStatus(
API_CRYPTSETHASHPARAM,
fApiSuccessful,
ptc,
ParamInfo,
APIPARAMINFO_SIZE(ParamInfo));
return fContinue;
}
//
// Function: TDecrypt
// Purpose: Call CryptDecrypt with the supplied parameters and pass
// the result to the logging routine.
//
BOOL TDecrypt(
HCRYPTKEY hKey,
HCRYPTHASH hHash,
BOOL Final,
DWORD dwFlags,
BYTE *pbData,
DWORD *pdwDataLen,
PTESTCASE ptc)
{
BOOL fApiSuccessful = FALSE;
//BOOL fUnexpected = TRUE;
BOOL fContinue = FALSE;
DWORD cbData = sizeof(DWORD);
API_PARAM_INFO ParamInfo [] = {
{ L"hKey", Handle, 0, NULL, FALSE, NULL, NULL },
{ L"hHash", Handle, 0, NULL, FALSE, NULL, NULL },
{ L"Final", Boolean, 0, NULL, FALSE, NULL, NULL },
{ L"dwFlags", Dword, dwFlags, EncryptFlagToString, FALSE, NULL, NULL },
{ L"pbData", Pointer, 0, NULL, TRUE, pdwDataLen, NULL },
{ L"pdwDataLen", Pointer, 0, NULL, TRUE, &cbData, NULL },
};
ParamInfo[0].pulParam = hKey;
ParamInfo[1].pulParam = hHash;
ParamInfo[2].fParam = Final;
ParamInfo[4].pbParam = pbData;
ParamInfo[5].pbParam = (PBYTE) pdwDataLen;
if (! LogInitParamInfo(
ParamInfo,
APIPARAMINFO_SIZE(ParamInfo),
ptc))
{
return FALSE;
}
fApiSuccessful = CryptDecrypt(hKey, hHash, Final, dwFlags, pbData, pdwDataLen);
fContinue = CheckAndLogStatus(
API_CRYPTDECRYPT,
fApiSuccessful,
ptc,
ParamInfo,
APIPARAMINFO_SIZE(ParamInfo));
LogCleanupParamInfo(ParamInfo, APIPARAMINFO_SIZE(ParamInfo));
return fContinue;
}
//
// Function: TDeriveKey
// Purpose: Call CryptDeriveKey with the supplied parameters and pass
// the result to the logging routine.
//
BOOL TDeriveKey(
HCRYPTPROV hProv,
ALG_ID Algid,
HCRYPTHASH hBaseData,
DWORD dwFlags,
HCRYPTKEY *phKey,
PTESTCASE ptc)
{
BOOL fApiSuccessful = FALSE;
//BOOL fUnexpected = TRUE;
BOOL fContinue = FALSE;
API_PARAM_INFO ParamInfo [] = {
{ L"hProv", Handle, 0, NULL, FALSE, NULL, NULL },
{ L"Algid", Dword, Algid, AlgidToString, FALSE, NULL, NULL },
{ L"hBaseData", Handle, 0, NULL, FALSE, NULL, NULL },
{ L"dwFlags", Dword, dwFlags, DeriveKeyFlagToString,FALSE, NULL, NULL },
{ L"phKey", Pointer, 0, NULL, FALSE, NULL, NULL}
};
ParamInfo[0].pulParam = hProv;
ParamInfo[2].pulParam = hBaseData;
ParamInfo[4].pbParam = (PBYTE) phKey;
fApiSuccessful = CryptDeriveKey(hProv, Algid, hBaseData, dwFlags, phKey);
fContinue = CheckAndLogStatus(
API_CRYPTDERIVEKEY,
fApiSuccessful,
ptc,
ParamInfo,
APIPARAMINFO_SIZE(ParamInfo));
return fContinue;
}
//
// Function: TDestroyKey
// Purpose: Call CryptDestroyKey with the supplied parameters and pass
// the result to the logging routine.
//
BOOL TDestroyKey(
HCRYPTKEY hKey,
PTESTCASE ptc)
{
BOOL fApiSuccessful = FALSE;
//BOOL fUnexpected = TRUE;
BOOL fContinue = FALSE;
BOOL fSavedExpectSuccess = ptc->fExpectSuccess;
API_PARAM_INFO ParamInfo [] = {
{ L"hKey", Handle, 0, NULL, FALSE, NULL, NULL }
};
ParamInfo[0].pulParam = hKey;
if (! ptc->fTestingDestroyKey)
{
ptc->fExpectSuccess = TRUE;
}
fApiSuccessful = CryptDestroyKey(hKey);
fContinue = CheckAndLogStatus(
API_CRYPTDESTROYKEY,
fApiSuccessful,
ptc,
ParamInfo,
APIPARAMINFO_SIZE(ParamInfo));
ptc->fExpectSuccess = fSavedExpectSuccess;
return fContinue;
}
//
// Function: TEncrypt
// Purpose: Call CryptEncrypt with the supplied parameters and pass
// the result to the logging routine.
//
BOOL TEncrypt(
HCRYPTKEY hKey,
HCRYPTHASH hHash,
BOOL Final,
DWORD dwFlags,
BYTE *pbData,
DWORD *pdwDataLen,
DWORD dwBufLen,
PTESTCASE ptc)
{
BOOL fApiSuccessful = FALSE;
//BOOL fUnexpected = TRUE;
BOOL fContinue = FALSE;
DWORD cbData = sizeof(DWORD);
API_PARAM_INFO ParamInfo [] = {
{ L"hKey", Handle, 0, NULL, FALSE, NULL, NULL },
{ L"hHash", Handle, 0, NULL, FALSE, NULL, NULL },
{ L"Final", Boolean, 0, NULL, FALSE, NULL, NULL },
{ L"dwFlags", Dword, dwFlags, EncryptFlagToString,FALSE, NULL, NULL },
{ L"pbData", Pointer, 0, NULL, TRUE, pdwDataLen, NULL },
{ L"pdwDataLen", Pointer, 0, NULL, TRUE, &cbData, NULL },
{ L"dwBufLen", Dword, dwBufLen, NULL, FALSE, NULL, NULL}
};
ParamInfo[0].pulParam = hKey;
ParamInfo[1].pulParam = hHash;
ParamInfo[2].fParam = Final;
ParamInfo[4].pbParam = pbData;
ParamInfo[5].pbParam = (PBYTE) pdwDataLen;
if (! LogInitParamInfo(
ParamInfo,
APIPARAMINFO_SIZE(ParamInfo),
ptc))
{
return FALSE;
}
fApiSuccessful = CryptEncrypt(hKey, hHash, Final, dwFlags, pbData, pdwDataLen, dwBufLen);
fContinue = CheckAndLogStatus(
API_CRYPTENCRYPT,
fApiSuccessful,
ptc,
ParamInfo,
APIPARAMINFO_SIZE(ParamInfo));
LogCleanupParamInfo(ParamInfo, APIPARAMINFO_SIZE(ParamInfo));
return fContinue;
}
//
// Function: TGenKey
// Purpose: Call CryptGenKey with the supplied parameters and pass
// the result to the logging routine.
//
BOOL TGenKey(
HCRYPTPROV hProv,
ALG_ID Algid,
DWORD dwFlags,
HCRYPTKEY *phKey,
PTESTCASE ptc)
{
BOOL fApiSuccessful = FALSE;
//BOOL fUnexpected = TRUE;
BOOL fContinue = FALSE;
DWORD cbData = sizeof(HCRYPTKEY);
API_PARAM_INFO ParamInfo [] = {
{ L"hProv", Handle, 0, NULL, FALSE, NULL, NULL },
{ L"Algid", Dword, Algid, AlgidToString, FALSE, NULL, NULL },
{ L"dwFlags", Dword, dwFlags, GenKeyFlagToString, FALSE, NULL, NULL },
{ L"phKey", Pointer, 0, NULL, TRUE, &cbData, NULL }
};
ParamInfo[0].pulParam = hProv;
ParamInfo[3].pbParam = (PBYTE) phKey;
//
// Prompt the user of the test suite when a user protected
// key is being created, UNLESS this is a negative test case.
//
if ( (CRYPT_USER_PROTECTED & dwFlags) &&
ptc->fExpectSuccess)
{
LogCreatingUserProtectedKey();
//LogInfo(L"Creating a User Protected key. You should now see UI.");
}
fApiSuccessful = CryptGenKey(hProv, Algid, dwFlags, phKey);
fContinue = CheckAndLogStatus(
API_CRYPTGENKEY,
fApiSuccessful,
ptc,
ParamInfo,
APIPARAMINFO_SIZE(ParamInfo));
return fContinue;
}
//
// Function: TGetKey
// Purpose: Call CryptGetKeyParam with the supplied parameters and pass
// the result to the logging routine.
//
BOOL TGetKey(
HCRYPTKEY hKey,
DWORD dwParam,
BYTE *pbData,
DWORD *pdwDataLen,
DWORD dwFlags,
PTESTCASE ptc)
{
BOOL fApiSuccessful = FALSE;
//BOOL fUnexpected = TRUE;
BOOL fContinue = FALSE;
DWORD cbData = sizeof(DWORD);
API_PARAM_INFO ParamInfo [] = {
{ L"hKey", Handle, 0, NULL, FALSE, NULL, NULL },
{ L"dwParam", Dword, dwParam, KeyParamToString, FALSE, NULL, NULL },
{ L"pbData", Pointer, 0, NULL, TRUE, pdwDataLen, NULL },
{ L"pdwDataLen", Pointer, 0, NULL, TRUE, &cbData, NULL },
{ L"dwFlags", Dword, dwFlags, NULL, FALSE, NULL, NULL }
};
ParamInfo[0].pulParam = hKey;
ParamInfo[2].pbParam = pbData;
ParamInfo[3].pbParam = (PBYTE) pdwDataLen;
switch (dwParam)
{
case KP_MODE:
{
ParamInfo[4].pfnFlagToString = KeyParamModeToString;
break;
}
case KP_PERMISSIONS:
{
ParamInfo[4].pfnFlagToString = KeyParamPermissionToString;
break;
}
}
if (! LogInitParamInfo(
ParamInfo,
APIPARAMINFO_SIZE(ParamInfo),
ptc))
{
return FALSE;
}
fApiSuccessful = CryptGetKeyParam(hKey, dwParam, pbData, pdwDataLen, dwFlags);
fContinue = CheckAndLogStatus(
API_CRYPTGETKEYPARAM,
fApiSuccessful,
ptc,
ParamInfo,
APIPARAMINFO_SIZE(ParamInfo));
LogCleanupParamInfo(ParamInfo, APIPARAMINFO_SIZE(ParamInfo));
return fContinue;
}
//
// Function: THashSession
// Purpose: Call CryptHashSessionKey with the supplied parameters and pass
// the result to the logging routine.
//
BOOL THashSession(
HCRYPTHASH hHash,
HCRYPTKEY hKey,
DWORD dwFlags,
PTESTCASE ptc)
{
BOOL fApiSuccessful = FALSE;
//BOOL fUnexpected = TRUE;
BOOL fContinue = FALSE;
API_PARAM_INFO ParamInfo [] = {
{ L"hHash", Handle, 0, NULL, FALSE, NULL, NULL },
{ L"hKey", Handle, 0, NULL, FALSE, NULL, NULL },
{ L"dwFlags", Dword, dwFlags, HashSessionKeyFlagToString, FALSE, NULL, NULL }
};
ParamInfo[0].pulParam = hHash;
ParamInfo[1].pulParam = hKey;
fApiSuccessful = CryptHashSessionKey(hHash, hKey, dwFlags);
fContinue = CheckAndLogStatus(
API_CRYPTHASHSESSIONKEY,
fApiSuccessful,
ptc,
ParamInfo,
APIPARAMINFO_SIZE(ParamInfo));
return fContinue;
}
//
// Function: TSetKey
// Purpose: Call CryptSetKeyParam with the supplied parameters and pass
// the result to the logging routine.
//
BOOL TSetKey(
HCRYPTKEY hKey,
DWORD dwParam,
BYTE *pbData,
DWORD dwFlags,
PTESTCASE ptc)
{
BOOL fApiSuccessful = FALSE;
//BOOL fUnexpected = TRUE;
BOOL fContinue = FALSE;
DWORD cbData = 0;
DWORD cbParam = 0;
API_PARAM_INFO ParamInfo [] = {
{ L"hKey", Handle, 0, NULL, FALSE, NULL, NULL },
{ L"dwParam", Dword, dwParam, KeyParamToString, FALSE, NULL, NULL },
{ L"pbData", Pointer, 0, NULL, FALSE, NULL, NULL },
{ L"dwFlags", Dword, dwFlags, NULL, FALSE, NULL, NULL }
};
ParamInfo[0].pulParam = hKey;
ParamInfo[2].pbParam = pbData;
switch (dwParam)
{
case KP_IV:
{
// Try to determine how long the IV buffer should be
cbData = 0;
if (CryptGetKeyParam(hKey, KP_IV, NULL, &cbData, 0) && cbData)
{
ParamInfo[2].fPrintBytes = TRUE;
ParamInfo[2].pcbBytes = &cbData;
}
break;
}
case KP_SALT:
{
// Try to determine how long the salt buffer should be
cbParam = sizeof(cbData);
if (CryptGetKeyParam(hKey, KP_SALT, (PBYTE) &cbData, &cbParam, 0) && cbData)
{
ParamInfo[2].fPrintBytes = TRUE;
ParamInfo[2].pcbBytes = &cbData;
}
break;
}
case KP_SALT_EX:
{
if (pbData != NULL && pbData != (PBYTE) TEST_INVALID_POINTER)
{
cbData = sizeof(DWORD) + ((PDATA_BLOB) pbData)->cbData;
ParamInfo[2].fPrintBytes = TRUE;
ParamInfo[2].pcbBytes = &cbData;
}
break;
}
case KP_PERMISSIONS:
{
ParamInfo[3].pfnFlagToString = KeyParamPermissionToString;
// fall through
}
case KP_ALGID:
case KP_EFFECTIVE_KEYLEN:
case KP_PADDING:
case KP_MODE_BITS:
{
cbData = sizeof(DWORD);
ParamInfo[2].fPrintBytes = TRUE;
ParamInfo[2].pcbBytes = &cbData;
break;
}
case KP_MODE:
{
cbData = sizeof(DWORD);
ParamInfo[2].fPrintBytes = TRUE;
ParamInfo[2].pcbBytes = &cbData;
ParamInfo[3].pfnFlagToString = KeyParamModeToString;
break;
}
}
if (! LogInitParamInfo(
ParamInfo,
APIPARAMINFO_SIZE(ParamInfo),
ptc))
{
return FALSE;
}
fApiSuccessful = CryptSetKeyParam(hKey, dwParam, pbData, dwFlags);
fContinue = CheckAndLogStatus(
API_CRYPTSETKEYPARAM,
fApiSuccessful,
ptc,
ParamInfo,
APIPARAMINFO_SIZE(ParamInfo));
LogCleanupParamInfo(ParamInfo, APIPARAMINFO_SIZE(ParamInfo));
return fContinue;
}
//
// Function: TExportKey
// Purpose: Call CryptExportKey with the supplied parameters and pass
// the result to the logging routine.
//
BOOL TExportKey(
HCRYPTKEY hKey,
HCRYPTKEY hExpKey,
DWORD dwBlobType,
DWORD dwFlags,
BYTE *pbData,
DWORD *pdwDataLen,
PTESTCASE ptc)
{
BOOL fApiSuccessful = FALSE;
//BOOL fUnexpected = TRUE;
BOOL fContinue = FALSE;
DWORD cbData = sizeof(DWORD);
API_PARAM_INFO ParamInfo [] = {
{ L"hKey", Handle, 0, NULL, FALSE, NULL, NULL },
{ L"hExpKey", Handle, 0, NULL, FALSE, NULL, NULL },
{ L"dwBlobType", Dword, dwBlobType, ExportKeyBlobTypeToString, FALSE, NULL, NULL },
{ L"dwFlags", Dword, dwFlags, ExportKeyFlagToString, FALSE, NULL, NULL },
{ L"pbData", Pointer, 0, NULL, TRUE, pdwDataLen, NULL },
{ L"pdwDataLen", Pointer, 0, NULL, TRUE, &cbData, NULL }
};
ParamInfo[0].pulParam = hKey;
ParamInfo[1].pulParam = hExpKey;
ParamInfo[4].pbParam = pbData;
ParamInfo[5].pbParam = (PBYTE) pdwDataLen;
if (! LogInitParamInfo(
ParamInfo,
APIPARAMINFO_SIZE(ParamInfo),
ptc))
{
return FALSE;
}
fApiSuccessful = CryptExportKey(hKey, hExpKey, dwBlobType, dwFlags, pbData, pdwDataLen);
fContinue = CheckAndLogStatus(
API_CRYPTEXPORTKEY,
fApiSuccessful,
ptc,
ParamInfo,
APIPARAMINFO_SIZE(ParamInfo));
LogCleanupParamInfo(ParamInfo, APIPARAMINFO_SIZE(ParamInfo));
return fContinue;
}
//
// Function: TGetUser
// Purpose: Call CryptGetUserKey with the supplied parameters and pass
// the result to the logging routine.
//
BOOL TGetUser(
HCRYPTPROV hProv,
DWORD dwKeySpec,
HCRYPTKEY *phUserKey,
PTESTCASE ptc)
{
BOOL fApiSuccessful = FALSE;
//BOOL fUnexpected = TRUE;
BOOL fContinue = FALSE;
API_PARAM_INFO ParamInfo [] = {
{ L"hProv", Handle, 0, NULL, FALSE, NULL, NULL },
{ L"dwKeySpec", Dword, dwKeySpec, AlgidToString, FALSE, NULL, NULL },
{ L"phUserKey", Pointer, 0, NULL, FALSE, NULL, NULL }
};
ParamInfo[0].pulParam = hProv;
ParamInfo[2].pbParam = (PBYTE) phUserKey;
fApiSuccessful = CryptGetUserKey(hProv, dwKeySpec, phUserKey);
fContinue = CheckAndLogStatus(
API_CRYPTGETUSERKEY,
fApiSuccessful,
ptc,
ParamInfo,
APIPARAMINFO_SIZE(ParamInfo));
return fContinue;
}
//
// Function: TImportKey
// Purpose: Call CryptImportKey with the supplied parameters and pass
// the result to the logging routine.
//
BOOL TImportKey(
HCRYPTPROV hProv,
BYTE *pbData,
DWORD dwDataLen,
HCRYPTKEY hPubKey,
DWORD dwFlags,
HCRYPTKEY *phKey,
PTESTCASE ptc)
{
BOOL fApiSuccessful = FALSE;
//BOOL fUnexpected = TRUE;
BOOL fContinue = FALSE;
DWORD cbData = sizeof(HCRYPTKEY);
API_PARAM_INFO ParamInfo [] = {
{ L"hProv", Handle, 0, NULL, FALSE, NULL, NULL },
{ L"pbData", Pointer, 0, NULL, TRUE, &dwDataLen, NULL },
{ L"dwDataLen", Dword, dwDataLen, NULL, FALSE, NULL, NULL },
{ L"hPubKey", Handle, 0, NULL, FALSE, NULL, NULL },
{ L"dwFlags", Dword, dwFlags, ImportKeyFlagToString,FALSE,NULL, NULL },
{ L"phKey", Pointer, 0, NULL, TRUE, &cbData, NULL }
};
ParamInfo[0].pulParam = hProv;
ParamInfo[1].pbParam = pbData;
ParamInfo[3].pulParam = hPubKey;
ParamInfo[5].pbParam = (PBYTE) phKey;
if (! LogInitParamInfo(
ParamInfo,
APIPARAMINFO_SIZE(ParamInfo),
ptc))
{
return FALSE;
}
fApiSuccessful = CryptImportKey(hProv, pbData, dwDataLen, hPubKey, dwFlags, phKey);
fContinue = CheckAndLogStatus(
API_CRYPTIMPORTKEY,
fApiSuccessful,
ptc,
ParamInfo,
APIPARAMINFO_SIZE(ParamInfo));
LogCleanupParamInfo(ParamInfo, APIPARAMINFO_SIZE(ParamInfo));
return fContinue;
}
//
// Function: TSignHash
// Purpose: Call CryptSignHash with the supplied parameters and pass
// the result to the logging routine.
//
BOOL TSignHash(
HCRYPTHASH hHash,
DWORD dwKeySpec,
LPWSTR sDescription,
DWORD dwFlags,
BYTE *pbSignature,
DWORD *pdwSigLen,
PTESTCASE ptc)
{
BOOL fApiSuccessful = FALSE;
//BOOL fUnexpected = TRUE;
BOOL fContinue = FALSE;
DWORD cbData = sizeof(DWORD);
API_PARAM_INFO ParamInfo [] = {
{ L"hHash", Handle, 0, NULL, FALSE, NULL, NULL },
{ L"dwKeySpec", Dword, dwKeySpec, AlgidToString, FALSE, NULL, NULL },
{ L"sDescription", String, 0, NULL, FALSE, NULL, NULL },
{ L"dwFlags", Dword, dwFlags, SignHashFlagToString,FALSE, NULL, NULL },
{ L"pbData", Pointer, 0, NULL, TRUE, pdwSigLen, NULL},
{ L"pdwSigLen", Pointer, 0, NULL, TRUE, &cbData, NULL}
};
ParamInfo[0].pulParam = hHash;
ParamInfo[2].pwszParam = sDescription;
ParamInfo[4].pbParam = pbSignature;
ParamInfo[5].pbParam = (PBYTE) pdwSigLen;
if (! LogInitParamInfo(
ParamInfo,
APIPARAMINFO_SIZE(ParamInfo),
ptc))
{
return FALSE;
}
fApiSuccessful = CryptSignHash(hHash, dwKeySpec, sDescription, dwFlags, pbSignature, pdwSigLen);
fContinue = CheckAndLogStatus(
API_CRYPTSIGNHASH,
fApiSuccessful,
ptc,
ParamInfo,
APIPARAMINFO_SIZE(ParamInfo));
LogCleanupParamInfo(ParamInfo, APIPARAMINFO_SIZE(ParamInfo));
return fContinue;
}
//
// Function: TVerifySign
// Purpose: Call CryptVerifySign with the supplied parameters and pass
// the result to the logging routine.
//
BOOL TVerifySign(
HCRYPTHASH hHash,
BYTE *pbSignature,
DWORD dwSigLen,
HCRYPTKEY hPubKey,
LPWSTR sDescription,
DWORD dwFlags,
PTESTCASE ptc)
{
BOOL fApiSuccessful = FALSE;
//BOOL fUnexpected = TRUE;
BOOL fContinue = FALSE;
API_PARAM_INFO ParamInfo [] = {
{ L"hHash", Handle, 0, NULL, FALSE, NULL, NULL },
{ L"pbSignature", Pointer, 0, NULL, TRUE, &dwSigLen, NULL},
{ L"dwSigLen", Dword, dwSigLen, NULL, FALSE, NULL, NULL },
{ L"hPubKey", Handle, 0, NULL, FALSE, NULL, NULL },
{ L"sDescription", String, 0, NULL, FALSE, NULL, NULL },
{ L"dwFlags", Dword, dwFlags, SignHashFlagToString,FALSE, NULL, NULL }
};
ParamInfo[0].pulParam = hHash;
ParamInfo[1].pbParam = pbSignature;
ParamInfo[3].pulParam = hPubKey;
ParamInfo[4].pwszParam = sDescription;
if (! LogInitParamInfo(
ParamInfo,
APIPARAMINFO_SIZE(ParamInfo),
ptc))
{
return FALSE;
}
fApiSuccessful = CryptVerifySignature(hHash, pbSignature, dwSigLen, hPubKey, sDescription, dwFlags);
fContinue = CheckAndLogStatus(
API_CRYPTVERIFYSIGNATURE,
fApiSuccessful,
ptc,
ParamInfo,
APIPARAMINFO_SIZE(ParamInfo));
LogCleanupParamInfo(ParamInfo, APIPARAMINFO_SIZE(ParamInfo));
return fContinue;
}
// -------------
// Test Routines
// -------------
//
// Function: PositiveAcquireContextTests
// Purpose: Run the appropriate set of positive CryptAcquireContext test cases for
// the passed in dwCSPClass.
//
BOOL PositiveAcquireContextTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
HCRYPTPROV hProv = 0;
DWORD dwProvType = LogGetProvType();
LPWSTR pwszProvName = LogGetProvName();
LPWSTR pwszContainer = TEST_CONTAINER;
//LPWSTR pwszContainer2 = TEST_CONTAINER_2;
//DWORD dwFlags = 0;
PTESTCASE ptc = &(pCSPInfo->TestCase);
switch (ptc->dwTestLevel)
{
case TEST_LEVEL_CSP:
{
//
// Group 1A
//
//
// Do CSP-level positive CryptAcquireContext tests
//
LOG_TRY(TAcquire(&hProv, NULL, pwszProvName, dwProvType, CRYPT_VERIFYCONTEXT, ptc));
break;
}
case TEST_LEVEL_CONTAINER:
{
//
// Group 5A
//
//
// Do Container-level positive CryptAcquireContext tests
//
LOG_TRY(CreateNewContext(&hProv, pwszContainer, CRYPT_NEWKEYSET, ptc));
LOG_TRY(TRelease(hProv, 0, ptc));
hProv = 0;
LOG_TRY(TAcquire(&hProv, pwszContainer, pwszProvName, dwProvType, CRYPT_SILENT, ptc));
LOG_TRY(TRelease(hProv, 0, ptc));
LOG_TRY(CreateNewContext(
&hProv,
pwszContainer,
CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET,
ptc));
LOG_TRY(TRelease(hProv, 0, ptc));
hProv = 0;
LOG_TRY(TAcquire(
&hProv,
pwszContainer,
pwszProvName,
dwProvType,
CRYPT_MACHINE_KEYSET | CRYPT_SILENT,
ptc));
break;
}
}
fSuccess = TRUE;
Cleanup:
if (hProv)
{
TRelease(hProv, 0, ptc);
}
return fSuccess;
}
//
// Function: NegativeAcquireContextTests
// Purpose: Run the appropriate set of negative CryptAcquireContext test cases
// based on the dwTestLevel parameter.
//
BOOL NegativeAcquireContextTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
HCRYPTPROV hProv = 0;
DWORD dwProvType = LogGetProvType();
LPWSTR pwszProvName = LogGetProvName();
LPWSTR pwszContainer = TEST_CONTAINER;
DWORD dwFlags = 0;
DWORD dwSavedErrorLevel = 0;
PTESTCASE ptc = &(pCSPInfo->TestCase);
switch (ptc->dwTestLevel)
{
case TEST_LEVEL_CSP:
{
//
// Do CSP-level negative CryptAcquireContext tests
//
dwFlags = CRYPT_VERIFYCONTEXT;
//
// This fails on Win2K because the VTable is constructed correctly, but
// the NULL phProv causes an AV. The bug is that the API returns True
// anyway.
//
// 7/20/00 -- Whistler status for this issue is unknown.
//
ptc->pwszErrorHelp = L"CryptAcquireContext should fail when phProv is NULL";
ptc->KnownErrorID = KNOWN_CRYPTACQUIRECONTEXT_NULLPHPROV;
ptc->dwErrorCode = ERROR_INVALID_PARAMETER;
LOG_TRY(TAcquire(NULL, NULL, pwszProvName, dwProvType, dwFlags, ptc));
ptc->pwszErrorHelp = NULL;
ptc->KnownErrorID = KNOWN_ERROR_UNKNOWN;
ptc->dwErrorCode = NTE_BAD_FLAGS;
LOG_TRY(TAcquire(&hProv, pwszContainer, pwszProvName, dwProvType, dwFlags, ptc));
//
// This fails on Win2K because the VERIFYCONTEXT flag is caught first. The API
// succeeds unexpectedly.
//
// 7/20/00 -- Whistler status for this issue is unknown.
//
ptc->pwszErrorHelp = L"This is an invalid combination of dwFlags values";
ptc->KnownErrorID = KNOWN_CRYPTACQUIRECONTEXT_BADFLAGS;
ptc->dwErrorCode = NTE_BAD_FLAGS;
LOG_TRY(TAcquire(&hProv, NULL, pwszProvName, dwProvType, CRYPT_VERIFYCONTEXT | CRYPT_NEWKEYSET, ptc));
ptc->pwszErrorHelp = NULL;
ptc->KnownErrorID = KNOWN_ERROR_UNKNOWN;
break;
}
case TEST_LEVEL_CONTAINER:
{
//
// Do Container-level negative CryptAcquireContext tests
//
ptc->dwErrorCode = NTE_BAD_KEYSET;
LOG_TRY(TAcquire(
&hProv,
TEST_CRYPTACQUIRECONTEXT_CONTAINER,
pwszProvName,
dwProvType,
0,
ptc));
//
// Test for risky characters in a container name
//
dwSavedErrorLevel = ptc->dwErrorLevel;
ptc->dwErrorLevel = CSP_ERROR_WARNING;
ptc->pwszErrorHelp = L"Some CSP's may not support container names with backslashes";
ptc->dwErrorCode = NTE_BAD_KEYSET_PARAM;
// Make sure this container doesn't already exist
CryptAcquireContext(&hProv, L"FOO\\BAR", pwszProvName, dwProvType, CRYPT_DELETEKEYSET);
LOG_TRY(TAcquire(&hProv, L"FOO\\BAR", pwszProvName, dwProvType, CRYPT_NEWKEYSET, ptc));
ptc->dwErrorLevel = dwSavedErrorLevel;
ptc->pwszErrorHelp = NULL;
// Create the keyset
LOG_TRY(CreateNewContext(&hProv, pwszContainer, CRYPT_NEWKEYSET, ptc));
// Try to create the keyset again
ptc->dwErrorCode = NTE_EXISTS;
LOG_TRY(TAcquire(&hProv, pwszContainer, pwszProvName, dwProvType, CRYPT_NEWKEYSET, ptc));
break;
}
}
fSuccess = TRUE;
Cleanup:
if (hProv)
{
TRelease(hProv, 0, ptc);
}
return fSuccess;
}
//
// Function: TestBuildAlgList
// Purpose: A wrapper for the BuildAlgList function
//
BOOL TestBuildAlgList(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
HCRYPTPROV hProv = 0;
PTESTCASE ptc = &(pCSPInfo->TestCase);
LOG_TRY(CreateNewContext(&hProv, NULL, CRYPT_VERIFYCONTEXT, ptc));
LOG_TRY(BuildAlgList(hProv, pCSPInfo));
fSuccess = TRUE;
Cleanup:
if (hProv)
{
TRelease(hProv, 0, ptc);
}
return fSuccess;
}
//
// Function: CheckEnumalgs
// Purpose: Call CryptGetProvParam with the PP_ENUMALGS flag to enumerate
// all the CSP's supported algorithms. Compare the results of this enumeration
// to the results of the PP_ENUMALGS_EX enumeration contained in the pAlgList
// param.
//
BOOL CheckEnumalgs(
IN HCRYPTPROV hProv,
IN PALGNODE pAlgList,
IN PTESTCASE ptc)
{
BOOL fContinue = TRUE;
//PBYTE pbData = NULL;
DWORD cbData = 0;
DWORD dwFlags = CRYPT_FIRST;
PROV_ENUMALGS ProvEnumalgs;
DWORD dw = 0;
//DWORD dwWinError = 0;
//DWORD dwErrorType = 0;
WCHAR rgwszError [ BUFFER_SIZE ];
memset(&ProvEnumalgs, 0, sizeof(ProvEnumalgs));
cbData = sizeof(ProvEnumalgs);
ptc->fEnumerating = TRUE;
LogTestCaseSeparator(FALSE); // Log a blank line first
LogInfo(L"CryptGetProvParam PP_ENUMALGS: enumerating supported algorithms");
while( TGetProv(
hProv,
PP_ENUMALGS,
(PBYTE) &ProvEnumalgs,
&cbData,
dwFlags,
ptc))
{
// Increment the test case counter for every enumerated alg
++ptc->dwTestCaseID;
if (NULL == pAlgList)
{
ptc->pwszErrorHelp = L"PP_ENUMALGS_EX enumerated fewer algorithms than PP_ENUMALGS";
LOG_TRY(LogApiFailure(
API_CRYPTGETPROVPARAM,
ERROR_LIST_TOO_SHORT,
ptc));
ptc->pwszErrorHelp = NULL;
}
if ( ProvEnumalgs.aiAlgid != pAlgList->ProvEnumalgsEx.aiAlgid ||
ProvEnumalgs.dwBitLen != pAlgList->ProvEnumalgsEx.dwDefaultLen ||
ProvEnumalgs.dwNameLen != pAlgList->ProvEnumalgsEx.dwNameLen ||
0 != strcmp(ProvEnumalgs.szName, pAlgList->ProvEnumalgsEx.szName) )
{
if (CALG_MAC == ProvEnumalgs.aiAlgid)
{
ptc->KnownErrorID = KNOWN_CRYPTGETPROVPARAM_MAC;
}
wsprintf(
rgwszError,
L"%s: %s",
L"PP_ENUMALGS data doesn't match PP_ENUMALGS_EX data for the following algorithm",
ProvEnumalgs.szName);
ptc->pwszErrorHelp = rgwszError;
LOG_TRY(LogApiFailure(
API_CRYPTGETPROVPARAM,
ERROR_BAD_DATA,
ptc));
ptc->pwszErrorHelp = NULL;
ptc->KnownErrorID = KNOWN_ERROR_UNKNOWN;
}
pAlgList = pAlgList->pAlgNodeNext;
if (CRYPT_FIRST == dwFlags)
{
dwFlags = 0;
}
LogProvEnumalgs(&ProvEnumalgs);
}
if (ERROR_NO_MORE_ITEMS != (dw = GetLastError()))
{
ptc->pwszErrorHelp = L"PP_ENUMALGS failed unexpectedly";
ptc->dwErrorCode = ERROR_NO_MORE_ITEMS;
ptc->fExpectSuccess = FALSE;
LOG_TRY(LogApiFailure(
API_CRYPTGETPROVPARAM,
ERROR_WRONG_ERROR_CODE,
ptc));
}
ptc->fEnumerating = FALSE;
fContinue = TRUE;
Cleanup:
ptc->KnownErrorID = KNOWN_ERROR_UNKNOWN;
ptc->pwszErrorHelp = NULL;
return fContinue;
}
//
// Function: CheckRequiredAlgs
// Purpose: Verify that all of the required algorithms
// for CSP's of this type are supported by this CSP.
//
BOOL CheckRequiredAlgs(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
DWORD dwCSPClass = pCSPInfo->dwCSPInternalClass;
PTESTCASE ptc = &(pCSPInfo->TestCase);
PALGNODE pAlgList = pCSPInfo->pAlgList;
PALGNODE pAlgNode = NULL;
DWORD iTable = 0;
BOOL fFound = FALSE;
WCHAR rgsz[BUFFER_SIZE];
//
// For each required alg for dwCSPClass, verify
// that the alg is listed in pAlgList. If it's not,
// assume that this CSP doesn't support that alg
// and flag an error.
//
LogTestCaseSeparator(FALSE); // Log a blank line first
LogInfo(L"List of Required algorithms for this CSP type");
for (
iTable = 0;
iTable < sizeof(g_RequiredAlgs_RSA) / sizeof(ALGID_TABLE);
iTable++)
{
if (! (dwCSPClass & g_RequiredAlgs_RSA[iTable].dwCSPClass))
{
continue;
}
fFound = FALSE;
AlgidToString(g_RequiredAlgs_RSA[iTable].ai, rgsz);
LogInfo(rgsz);
//
// Search pAlgList for the current ALG_ID
//
for (
pAlgNode = pAlgList;
pAlgNode != NULL && (! fFound);
pAlgNode = pAlgNode->pAlgNodeNext)
{
if (g_RequiredAlgs_RSA[iTable].ai == pAlgNode->ProvEnumalgsEx.aiAlgid)
{
fFound = TRUE;
}
}
if (! fFound)
{
LOG_TRY(LogApiFailure(
API_CRYPTGETPROVPARAM,
ERROR_REQUIRED_ALG,
ptc));
}
}
fSuccess = TRUE;
Cleanup:
return fSuccess;
}
//
// Function: PositiveGetProvParamTests
// Purpose: Run the test cases for CryptGetProvParam
//
BOOL PositiveGetProvParamTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
HCRYPTPROV hProv = 0;
LPWSTR pwszContainer = TEST_CONTAINER;
PBYTE pbData = NULL;
DWORD dwData = 0;
DWORD dwFlags = CRYPT_FIRST;
DWORD cbData = 0;
DWORD dwError = 0;
DWORD dwSavedErrorLevel = 0;
LPWSTR pwsz = NULL;
PTESTCASE ptc = &(pCSPInfo->TestCase);
switch (ptc->dwTestLevel)
{
case TEST_LEVEL_CSP:
{
//
// Group 1B
//
//
// Do CryptGetProvParam positive test cases
//
LOG_TRY(CreateNewContext(&hProv, NULL, CRYPT_VERIFYCONTEXT, ptc));
LOG_TRY(BuildAlgList(hProv, pCSPInfo));
LOG_TRY(CheckEnumalgs(hProv, pCSPInfo->pAlgList, ptc));
ptc->fExpectSuccess = TRUE;
LOG_TRY(CheckRequiredAlgs(pCSPInfo));
//
// Test PP_IMPTYPE
//
cbData = sizeof(dwData);
LOG_TRY(TGetProv(
hProv,
PP_IMPTYPE,
(PBYTE) &dwData,
&cbData,
0,
ptc));
if (CRYPT_IMPL_SOFTWARE != dwData)
{
// Set the expected behavior for a non-software-only
// CSP.
pCSPInfo->fSmartCardCSP = TRUE;
}
//
// Test PP_NAME
//
LOG_TRY(TGetProv(
hProv,
PP_NAME,
NULL,
&cbData,
0,
ptc));
LOG_TRY(TestAlloc(&pbData, cbData, ptc));
LOG_TRY(TGetProv(
hProv,
PP_NAME,
pbData,
&cbData,
0,
ptc));
ptc->KnownErrorID = KNOWN_CRYPTGETPROVPARAM_PPNAME;
if (0 != wcscmp(
(LPWSTR) pbData,
pCSPInfo->pwszCSPName))
{
ptc->pwszErrorHelp = L"CryptGetProvParam PP_NAME is not Unicode";
LOG_TRY(LogApiFailure(
API_CRYPTGETPROVPARAM,
ERROR_BAD_DATA,
ptc));
ptc->pwszErrorHelp = NULL;
}
ptc->KnownErrorID = KNOWN_ERROR_UNKNOWN;
free(pbData);
pbData = NULL;
//
// Test PP_VERSION
//
cbData = sizeof(dwData);
LOG_TRY(TGetProv(
hProv,
PP_VERSION,
(PBYTE) &dwData,
&cbData,
0,
ptc));
//
// Test PP_SIG_KEYSIZE_INC
//
cbData = sizeof(dwData);
LOG_TRY(TGetProv(
hProv,
PP_SIG_KEYSIZE_INC,
(PBYTE) &dwData,
&cbData,
0,
ptc));
pCSPInfo->dwSigKeysizeInc = dwData;
//
// Test PP_KEYX_KEYSIZE_INC
//
cbData = sizeof(dwData);
LOG_TRY(TGetProv(
hProv,
PP_KEYX_KEYSIZE_INC,
(PBYTE) &dwData,
&cbData,
0,
ptc));
pCSPInfo->dwKeyXKeysizeInc = dwData;
//
// Test PP_PROVTYPE
//
cbData = sizeof(dwData);
LOG_TRY(TGetProv(
hProv,
PP_PROVTYPE,
(PBYTE) &dwData,
&cbData,
0,
ptc));
if (dwData != pCSPInfo->dwExternalProvType)
{
ptc->pwszErrorHelp = L"CryptGetProvParam PP_PROVTYPE is incorrect";
LOG_TRY(LogApiFailure(
API_CRYPTGETPROVPARAM,
ERROR_BAD_DATA,
ptc));
ptc->pwszErrorHelp = NULL;
}
//
// Test PP_USE_HARDWARE_RNG
//
// TODO - dumb down the error level of this test case, since most
// CSP's will probably return FALSE
//
dwSavedErrorLevel = ptc->dwErrorLevel;
ptc->dwErrorLevel = CSP_ERROR_WARNING;
ptc->pwszErrorHelp =
L"CryptGetProvParam reports that this system has no hardware Random Number Generator configured";
cbData = 0;
LOG_TRY(TGetProv(
hProv,
PP_USE_HARDWARE_RNG,
NULL,
&cbData,
0,
ptc));
ptc->dwErrorLevel = dwSavedErrorLevel;
ptc->pwszErrorHelp = NULL;
//
// Test PP_KEYSPEC
//
cbData = sizeof(dwData);
LOG_TRY(TGetProv(
hProv,
PP_KEYSPEC,
(PBYTE) &dwData,
&cbData,
0,
ptc));
pCSPInfo->dwKeySpec = dwData;
break;
}
case TEST_LEVEL_CONTAINER:
{
LOG_TRY(CreateNewContext(&hProv, pwszContainer, CRYPT_NEWKEYSET, ptc));
//
// Do PP_ENUMCONTAINERS enumeration
//
dwFlags = CRYPT_FIRST;
ptc->fEnumerating = TRUE;
LogInfo(L"PP_ENUMCONTAINERS: enumerating user containers");
while (TEST_INVALID_FLAG != dwFlags)
{
while( TGetProv(
hProv,
PP_ENUMCONTAINERS,
NULL,
&cbData,
dwFlags,
ptc))
{
if (NULL != pbData)
{
free(pbData);
}
LOG_TRY(TestAlloc(&pbData, cbData, ptc));
LOG_TRY(TGetProv(
hProv,
PP_ENUMCONTAINERS,
pbData,
&cbData,
dwFlags,
ptc));
pwsz = MkWStr((LPSTR) pbData);
if (pwsz)
{
LogInfo(pwsz);
free(pwsz);
}
if (CRYPT_FIRST & dwFlags)
{
dwFlags ^= CRYPT_FIRST;
}
}
if (ERROR_NO_MORE_ITEMS != (dwError = GetLastError()))
{
ptc->fExpectSuccess = FALSE;
ptc->dwErrorCode = ERROR_NO_MORE_ITEMS;
ptc->pwszErrorHelp = L"PP_ENUMCONTAINERS failed unexpectedly";
LOG_TRY(LogApiFailure(
API_CRYPTGETPROVPARAM,
ERROR_WRONG_ERROR_CODE,
ptc));
ptc->pwszErrorHelp = NULL;
}
if (CRYPT_MACHINE_KEYSET != dwFlags)
{
dwFlags = CRYPT_MACHINE_KEYSET | CRYPT_FIRST;
LogInfo(L"PP_ENUMCONTAINERS: enumerating local machine containers");
}
else
{
dwFlags = TEST_INVALID_FLAG;
}
}
ptc->fEnumerating = FALSE;
ptc->fExpectSuccess = TRUE;
//
// Test PP_KEYSET_SEC_DESCR
//
cbData = sizeof(dwData);
LOG_TRY(TGetProv(
hProv,
PP_KEYSET_SEC_DESCR,
(PBYTE) &dwData,
&cbData,
OWNER_SECURITY_INFORMATION,
ptc));
cbData = sizeof(dwData);
LOG_TRY(TGetProv(
hProv,
PP_KEYSET_SEC_DESCR,
(PBYTE) &dwData,
&cbData,
GROUP_SECURITY_INFORMATION,
ptc));
cbData = sizeof(dwData);
LOG_TRY(TGetProv(
hProv,
PP_KEYSET_SEC_DESCR,
(PBYTE) &dwData,
&cbData,
DACL_SECURITY_INFORMATION,
ptc));
cbData = sizeof(dwData);
LOG_TRY(TGetProv(
hProv,
PP_KEYSET_SEC_DESCR,
(PBYTE) &dwData,
&cbData,
SACL_SECURITY_INFORMATION,
ptc));
//
// Test PP_UNIQUE_CONTAINER
//
LOG_TRY(TGetProv(
hProv,
PP_UNIQUE_CONTAINER,
NULL,
&cbData,
0,
ptc));
LOG_TRY(TestAlloc(&pbData, cbData, ptc));
LOG_TRY(TGetProv(
hProv,
PP_UNIQUE_CONTAINER,
pbData,
&cbData,
0,
ptc));
free(pbData);
pbData = NULL;
break;
}
}
fSuccess = TRUE;
Cleanup:
if (hProv)
{
TRelease(hProv, 0, ptc);
}
if (pbData)
{
free(pbData);
}
return fSuccess;
}
//
// Function: NegativeGetProvParamTests
// Purpose: Run the negative test cases for CryptGetProvParam
//
BOOL NegativeGetProvParamTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
HCRYPTPROV hProv = 0;
//LPWSTR pwszContainer = TEST_CONTAINER;
//PBYTE pbData = NULL;
DWORD dwData = 0;
DWORD cbData = 0;
PROV_ENUMALGS_EX ProvEnumalgsEx;
PTESTCASE ptc = &(pCSPInfo->TestCase);
//
// Do CryptGetProvParam negative test cases
//
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(TGetProv(0, PP_ENUMALGS_EX, (PBYTE) &ProvEnumalgsEx, &cbData, 0, ptc));
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(TGetProv(TEST_INVALID_HANDLE, PP_ENUMALGS_EX, (PBYTE) &ProvEnumalgsEx, &cbData, 0, ptc));
LOG_TRY(CreateNewContext(&hProv, NULL, CRYPT_VERIFYCONTEXT, ptc));
ptc->dwErrorCode = ERROR_INVALID_PARAMETER;
LOG_TRY(TGetProv(hProv, PP_VERSION, (PBYTE) &dwData, NULL, 0, ptc));
ptc->KnownErrorID = KNOWN_CRYPTGETPROVPARAM_MOREDATA;
cbData = 1;
ptc->dwErrorCode = ERROR_MORE_DATA;
LOG_TRY(TGetProv(hProv, PP_CONTAINER, (PBYTE) &dwData, &cbData, 0, ptc));
ptc->KnownErrorID = KNOWN_ERROR_UNKNOWN;
cbData = sizeof(ProvEnumalgsEx);
ptc->dwErrorCode = NTE_BAD_FLAGS;
LOG_TRY(TGetProv(hProv, PP_ENUMALGS_EX, (PBYTE) &ProvEnumalgsEx, &cbData, TEST_INVALID_FLAG, ptc));
ptc->dwErrorCode = NTE_BAD_TYPE;
LOG_TRY(TGetProv(hProv, TEST_INVALID_FLAG, (PBYTE) &ProvEnumalgsEx, &cbData, 0, ptc));
fSuccess = TRUE;
Cleanup:
if (hProv)
{
TRelease(hProv, 0, ptc);
}
return fSuccess;
}
//
// Function: PositiveSetProvParamTests
// Purpose: Run the test cases for CryptSetProvParam
//
BOOL PositiveSetProvParamTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
HCRYPTPROV hProv = 0;
LPWSTR pwszContainer = TEST_CONTAINER;
DWORD cbData = 0;
DWORD dwData = 0;
HWND hWnd = 0;
DWORD dwSavedErrorLevel = 0;
SECURITY_DESCRIPTOR SecurityDescriptor;
PTESTCASE ptc = &(pCSPInfo->TestCase);
memset(&SecurityDescriptor, 0, sizeof(SecurityDescriptor));
switch (ptc->dwTestLevel)
{
case TEST_LEVEL_CSP:
{
LOG_TRY(CreateNewContext(&hProv, NULL, CRYPT_VERIFYCONTEXT, ptc));
//
// Group 1C
//
//
// Do CryptSetProvParam positive test cases
//
//
// Test PP_CLIENT_HWND
//
if (NULL == (hWnd = GetDesktopWindow()))
{
LOG_TRY(LogApiFailure(
API_GETDESKTOPWINDOW,
ERROR_API_FAILED,
ptc));
//LOG_TRY(LogWin32Fail(ptc->dwErrorLevel, ptc->dwTestCaseID));
}
cbData = sizeof(hWnd);
LOG_TRY(TSetProv(
0,
PP_CLIENT_HWND,
(PBYTE) &hWnd,
0,
ptc));
//
// Test PP_USE_HARDWARE_RNG
//
// TODO: Dumb down the error level of this test case since
// some CSP's will not support it.
//
// TODO: What effect does this flag have on systems that don't actually
// have a hardware RNG?
//
dwSavedErrorLevel = ptc->dwErrorLevel;
ptc->dwErrorLevel = CSP_ERROR_WARNING;
ptc->pwszErrorHelp =
L"CryptSetProvParam reports that this system has no hardware Random Number Generator";
LOG_TRY(TSetProv(
hProv,
PP_USE_HARDWARE_RNG,
NULL,
0,
ptc));
ptc->dwErrorLevel = dwSavedErrorLevel;
ptc->pwszErrorHelp = NULL;
break;
}
case TEST_LEVEL_CONTAINER:
{
LOG_TRY(CreateNewContext(&hProv, pwszContainer, CRYPT_NEWKEYSET, ptc));
//
// Test PP_KEYSET_SEC_DESCR
//
cbData = sizeof(dwData);
LOG_TRY(TGetProv(
hProv,
PP_KEYSET_SEC_DESCR,
(PBYTE) &dwData,
&cbData,
OWNER_SECURITY_INFORMATION,
ptc));
LOG_TRY(TSetProv(
hProv,
PP_KEYSET_SEC_DESCR,
(PBYTE) &dwData,
OWNER_SECURITY_INFORMATION,
ptc));
cbData = sizeof(dwData);
LOG_TRY(TGetProv(
hProv,
PP_KEYSET_SEC_DESCR,
(PBYTE) &dwData,
&cbData,
GROUP_SECURITY_INFORMATION,
ptc));
LOG_TRY(TSetProv(
hProv,
PP_KEYSET_SEC_DESCR,
(PBYTE) &dwData,
GROUP_SECURITY_INFORMATION,
ptc));
cbData = sizeof(dwData);
LOG_TRY(TGetProv(
hProv,
PP_KEYSET_SEC_DESCR,
(PBYTE) &dwData,
&cbData,
DACL_SECURITY_INFORMATION,
ptc));
LOG_TRY(TSetProv(
hProv,
PP_KEYSET_SEC_DESCR,
(PBYTE) &dwData,
DACL_SECURITY_INFORMATION,
ptc));
cbData = sizeof(dwData);
LOG_TRY(TGetProv(
hProv,
PP_KEYSET_SEC_DESCR,
(PBYTE) &dwData,
&cbData,
SACL_SECURITY_INFORMATION,
ptc));
LOG_TRY(TSetProv(
hProv,
PP_KEYSET_SEC_DESCR,
(PBYTE) &dwData,
SACL_SECURITY_INFORMATION,
ptc));
break;
}
}
fSuccess = TRUE;
Cleanup:
if (hProv)
{
TRelease(hProv, 0, ptc);
}
return fSuccess;
}
//
// Function: NegativeSetProvParamTests
// Purpose: Run the negative test cases for CryptSetProvParam
//
BOOL NegativeSetProvParamTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
HCRYPTPROV hProv = 0;
//LPWSTR pwszContainer = TEST_CONTAINER;
DWORD dwData = 0;
PTESTCASE ptc = &(pCSPInfo->TestCase);
SECURITY_DESCRIPTOR SecurityDescriptor;
memset(&SecurityDescriptor, 0, sizeof(SecurityDescriptor));
//
// Group 1C
//
//
// Do CryptSetProvParam negative test cases
//
LOG_TRY(CreateNewContext(&hProv, NULL, CRYPT_VERIFYCONTEXT, ptc));
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(TSetProv(hProv, PP_CLIENT_HWND, (PBYTE) TEST_INVALID_HANDLE, 0, ptc));
ptc->dwErrorCode = ERROR_INVALID_PARAMETER;
LOG_TRY(TSetProv(hProv, PP_KEYSET_SEC_DESCR, NULL, OWNER_SECURITY_INFORMATION, ptc));
ptc->pwszErrorHelp =
L"The pbData parameter must be NULL when calling CryptSetProvParam PP_USE_HARDWARE_RNG";
ptc->KnownErrorID = KNOWN_CRYPTSETPROVPARAM_RNG;
ptc->dwErrorCode = ERROR_INVALID_PARAMETER;
LOG_TRY(TSetProv(hProv, PP_USE_HARDWARE_RNG, (PBYTE) &dwData, 0, ptc));
ptc->pwszErrorHelp = NULL;
ptc->KnownErrorID = KNOWN_ERROR_UNKNOWN;
ptc->pwszErrorHelp =
L"The dwFlags parameter must be zero when calling CryptSetProvParam PP_USE_HARDWARE_RNG";
ptc->KnownErrorID = KNOWN_CRYPTSETPROVPARAM_BADFLAGS;
ptc->dwErrorCode = NTE_BAD_FLAGS;
LOG_TRY(TSetProv(hProv, PP_USE_HARDWARE_RNG, NULL, 1, ptc));
ptc->pwszErrorHelp = NULL;
ptc->KnownErrorID = KNOWN_ERROR_UNKNOWN;
//
// 7/25/00 -- This test case is too specific to the Microsoft CSP's.
//
/*
ptc->dwErrorCode = ERROR_INVALID_PARAMETER;
LOG_TRY(TSetProv(hProv, PP_KEYSET_SEC_DESCR, (PBYTE) &SecurityDescriptor, OWNER_SECURITY_INFORMATION, ptc));
*/
ptc->dwErrorCode = NTE_BAD_TYPE;
LOG_TRY(TSetProv(hProv, TEST_INVALID_FLAG, (PBYTE) &dwData, 0, ptc));
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(TSetProv(0, PP_USE_HARDWARE_RNG, NULL, 0, ptc));
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(TSetProv(TEST_INVALID_HANDLE, PP_USE_HARDWARE_RNG, NULL, 0, ptc));
fSuccess = TRUE;
Cleanup:
if (hProv)
{
TRelease(hProv, 0, ptc);
}
return fSuccess;
}
//
// Function: PositiveReleaseContextTests
// Purpose: Run the test cases for CryptReleaseContext
//
BOOL PositiveReleaseContextTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
HCRYPTPROV hProv = 0;
//LPWSTR pwszContainer = TEST_CONTAINER;
PTESTCASE ptc = &(pCSPInfo->TestCase);
//
// Group 1D
//
//
// Do CryptReleaseContext positive test cases
//
LOG_TRY(CreateNewContext(&hProv, NULL, CRYPT_VERIFYCONTEXT, ptc));
if (! CryptContextAddRef(hProv, NULL, 0))
{
LOG_TRY(LogApiFailure(
API_CRYPTCONTEXTADDREF,
ERROR_API_FAILED,
ptc));
//LOG_TRY(LogWin32Fail(ptc->dwErrorLevel, ptc->dwTestCaseID));
}
LOG_TRY(TRelease(hProv, 0, ptc));
LOG_TRY(TRelease(hProv, 0, ptc));
fSuccess = TRUE;
Cleanup:
return fSuccess;
}
//
// Function: NegativeReleaseContextTests
// Purpose: Run the negative test cases for CryptReleaseContext
//
BOOL NegativeReleaseContextTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
HCRYPTPROV hProv = 0;
//LPWSTR pwszContainer = TEST_CONTAINER;
PTESTCASE ptc = &(pCSPInfo->TestCase);
//
// Group 1D
//
//
// Do CryptReleaseContext negative test cases
//
ptc->fTestingReleaseContext = TRUE;
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(TRelease(0, 0, ptc));
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(TRelease(TEST_INVALID_HANDLE, 0, ptc));
LOG_TRY(CreateNewContext(&hProv, NULL, CRYPT_VERIFYCONTEXT, ptc));
ptc->dwErrorCode = NTE_BAD_FLAGS;
LOG_TRY(TRelease(hProv, 1, ptc));
fSuccess = TRUE;
Cleanup:
ptc->fTestingReleaseContext = FALSE;
return fSuccess;
}
//
// Function: PositiveGenRandomTests
// Purpose: Run the test cases for CryptGenRandom
//
BOOL PositiveGenRandomTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
//LPWSTR pwszContainer = TEST_CONTAINER;
HCRYPTPROV hProv = 0;
DWORD cb = GENRANDOM_BYTE_COUNT;
BYTE rgBuffer[GENRANDOM_BYTE_COUNT];
PTESTCASE ptc = &(pCSPInfo->TestCase);
//
// Group 2A
//
//
// Do CryptGenRandom positive test cases
//
LOG_TRY(CreateNewContext(&hProv, NULL, CRYPT_VERIFYCONTEXT, ptc));
LOG_TRY(TGenRand(hProv, cb, rgBuffer, ptc));
fSuccess = TRUE;
Cleanup:
if (hProv)
{
TRelease(hProv, 0, ptc);
}
return fSuccess;
}
//
// Function: NegativeGenRandomTests
// Purpose: Run the negative test cases for CryptGenRandom
//
BOOL NegativeGenRandomTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
//LPWSTR pwszContainer = TEST_CONTAINER;
HCRYPTPROV hProv = 0;
//DWORD dw = 0;
PBYTE pb = NULL;
PTESTCASE ptc = &(pCSPInfo->TestCase);
//
// Group 2A
//
//
// Do CryptGenRandom negative test cases
//
LOG_TRY(CreateNewContext(&hProv, NULL, CRYPT_VERIFYCONTEXT, ptc));
ptc->dwErrorCode = ERROR_INVALID_PARAMETER;
LOG_TRY(TGenRand(hProv, 1, NULL, ptc));
LOG_TRY(TestAlloc(&pb, GENRANDOM_BYTE_COUNT, ptc));
ptc->dwErrorCode = ERROR_INVALID_PARAMETER;
LOG_TRY(TGenRand(hProv, 2 * GENRANDOM_BYTE_COUNT, pb, ptc));
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(TGenRand(0, GENRANDOM_BYTE_COUNT, pb, ptc));
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(TGenRand(TEST_INVALID_HANDLE, GENRANDOM_BYTE_COUNT, pb, ptc));
fSuccess = TRUE;
Cleanup:
if (hProv)
{
TRelease(hProv, 0, ptc);
}
if (pb)
{
free(pb);
}
return fSuccess;
}
//
// Function: TestCreateHashProc
// Purpose: This function verifies that CryptCreateHash is successful
// for the hash algorithm specified in the pAlgNode parameter.
//
// For known MAC algorithms (ALG_SID_MAC and ALG_SIG_HMAC), a block
// cipher key (provided via pvTestCreateHashInfo) is provided when creating
// the hash handle.
//
// For other, non-keyed, hash algorithms, the cipher key will not
// be used.
//
BOOL TestCreateHashProc(
PALGNODE pAlgNode,
PTESTCASE ptc,
PVOID pvTestCreateHashInfo)
{
BOOL fSuccess = FALSE;
HCRYPTHASH hHash = 0;
DWORD dwSavedErrorLevel = ptc->dwErrorLevel;
PTEST_CREATE_HASH_INFO pTestCreateHashInfo = (PTEST_CREATE_HASH_INFO) pvTestCreateHashInfo;
if (pAlgNode->fIsRequiredAlg)
{
ptc->dwErrorLevel = CSP_ERROR_CONTINUE;
}
else
{
ptc->dwErrorLevel = CSP_ERROR_WARNING;
}
if (MacAlgFilter(pAlgNode))
{
LOG_TRY(TCreateHash(
pTestCreateHashInfo->hProv,
pAlgNode->ProvEnumalgsEx.aiAlgid,
pTestCreateHashInfo->hBlockCipherKey,
0,
&hHash,
ptc));
}
else
{
LOG_TRY(TCreateHash(
pTestCreateHashInfo->hProv,
pAlgNode->ProvEnumalgsEx.aiAlgid,
0,
0,
&hHash,
ptc));
}
fSuccess = TRUE;
Cleanup:
ptc->dwErrorLevel = dwSavedErrorLevel;
if (hHash)
{
TDestroyHash(hHash, ptc);
}
return fSuccess;
}
//
// Function: PositiveCreateHashTests
// Purpose: Run the test cases for CryptCreateHash based on the CSP class being tested
// as specified in the dwCSPClass parameter.
//
BOOL PositiveCreateHashTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
PTESTCASE ptc = &(pCSPInfo->TestCase);
TEST_CREATE_HASH_INFO TestCreateHashInfo;
memset(&TestCreateHashInfo, 0, sizeof(TestCreateHashInfo));
LOG_TRY(CreateNewContext(
&(TestCreateHashInfo.hProv),
NULL,
CRYPT_VERIFYCONTEXT,
ptc));
//
// Create an RC2 key for testing keyed-hashes (MAC). RC2 is a required algorithm,
// but if this fails, and the CSP does support one or more MAC algs, the creation
// of the MAC hash handles (see TestCreateHashProc) may fail as well.
//
/*
LOG_TRY(CreateNewKey(
TestCreateHashInfo.hProv,
CALG_RC2,
0,
&(TestCreateHashInfo.hBlockCipherKey),
ptc));
*/
//
// Group 3A
//
//
// Do CryptCreateHash positive test cases
//
//
// Iterate through the ENUMALGS_EX structs stored in the ALGNODE list.
// Create a hash of each type supported by this CSP.
//
LOG_TRY(AlgListIterate(
pCSPInfo->pAlgList,
HashAlgFilter,
TestCreateHashProc,
(PVOID) &TestCreateHashInfo,
ptc));
// This test case set probably doesn't belong here, since
// symmetric keys haven't been tested at this point.
/*
LOG_TRY(AlgListIterate(
pCSPInfo->pAlgList,
MacAlgFilter,
TestCreateHashProc,
(PVOID) &TestCreateHashInfo,
ptc));
*/
fSuccess = TRUE;
Cleanup:
if (TestCreateHashInfo.hBlockCipherKey)
{
TDestroyKey(TestCreateHashInfo.hBlockCipherKey, ptc);
}
if (TestCreateHashInfo.hProv)
{
TRelease(TestCreateHashInfo.hProv, 0, ptc);
}
return fSuccess;
}
//
// Function: NegativeCreateHashTests
// Purpose: Run the test cases for CryptCreateHash based on the CSP class being tested
// as specified in the dwCSPClass parameter.
//
BOOL NegativeCreateHashTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
HCRYPTPROV hProv = 0;
HCRYPTHASH hHash = 0;
HCRYPTKEY hKey = 0;
//LPWSTR pwszContainer = TEST_CONTAINER;
PTESTCASE ptc = &(pCSPInfo->TestCase);
//
// Group 3A
//
//
// Do CryptGenRandom negative test cases
//
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(TCreateHash(0, CALG_SHA1, 0, 0, &hHash, ptc));
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(TCreateHash(TEST_INVALID_HANDLE, CALG_SHA1, 0, 0, &hHash, ptc));
LOG_TRY(CreateNewContext(&hProv, NULL, CRYPT_VERIFYCONTEXT, ptc));
ptc->dwErrorCode = NTE_BAD_FLAGS;
LOG_TRY(TCreateHash(hProv, CALG_SHA1, 0, TEST_INVALID_FLAG, &hHash, ptc));
ptc->dwErrorCode = NTE_BAD_KEY;
LOG_TRY(TCreateHash(hProv, CALG_HMAC, 0, 0, &hHash, ptc));
// HMAC requires a block cipher, so use a stream cipher and expect failure
LOG_TRY(CreateNewKey(hProv, CALG_RC4, 0, &hKey, ptc));
ptc->pwszErrorHelp =
L"CryptCreateHash CALG_HMAC should fail when not using a block cipher key";
ptc->KnownErrorID = KNOWN_CRYPTCREATEHASH_BADKEY;
ptc->dwErrorCode = NTE_BAD_KEY;
LOG_TRY(TCreateHash(hProv, CALG_HMAC, hKey, 0, &hHash, ptc));
ptc->pwszErrorHelp = NULL;
ptc->KnownErrorID = KNOWN_ERROR_UNKNOWN;
ptc->dwErrorCode = ERROR_INVALID_PARAMETER;
LOG_TRY(TCreateHash(hProv, CALG_SHA1, 0, 0, NULL, ptc));
ptc->dwErrorCode = NTE_BAD_ALGID;
LOG_TRY(TCreateHash(hProv, CALG_RC4, 0, 0, &hHash, ptc));
fSuccess = TRUE;
Cleanup:
if (hKey)
{
TDestroyKey(hKey, ptc);
}
if (hProv)
{
TRelease(hProv, 0, ptc);
}
return fSuccess;
}
//
// Function: PositiveDestroyHashTests
// Purpose: Run the test cases for CryptDestroyHash
//
BOOL PositiveDestroyHashTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
//LPWSTR pwszContainer = TEST_CONTAINER;
HCRYPTPROV hProv = 0;
HCRYPTHASH hHash = 0;
PTESTCASE ptc = &(pCSPInfo->TestCase);
//
// Group 3B
//
//
// Do CryptDestroyHash positive test cases
//
LOG_TRY(CreateNewContext(&hProv, NULL, CRYPT_VERIFYCONTEXT, ptc));
LOG_TRY(CreateNewHash(hProv, CALG_SHA1, &hHash, ptc));
LOG_TRY(TDestroyHash(hHash, ptc));
hHash = 0;
fSuccess = TRUE;
Cleanup:
if (hHash)
{
TDestroyHash(hHash, ptc);
}
if (hProv)
{
TRelease(hProv, 0, ptc);
}
return fSuccess;
}
//
// Function: NegativeDestroyHashTests
// Purpose: Run the test cases for CryptDestroyHash
//
BOOL NegativeDestroyHashTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
//LPWSTR pwszContainer = TEST_CONTAINER;
HCRYPTPROV hProv = 0;
HCRYPTHASH hHash = 0;
PTESTCASE ptc = &(pCSPInfo->TestCase);
//
// Group 3B
//
//
// Do CryptDestroyHash negative test cases
//
ptc->fTestingDestroyHash = TRUE;
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(TDestroyHash(0, ptc));
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(TDestroyHash(TEST_INVALID_HANDLE, ptc));
LOG_TRY(CreateNewContext(&hProv, NULL, CRYPT_VERIFYCONTEXT, ptc));
LOG_TRY(CreateNewHash(hProv, CALG_SHA1, &hHash, ptc));
/*
LOG_TRY(TRelease(hProv, 0, ptc));
hProv = 0;
// Provider handle used to create hHash is now invalid
ptc->dwErrorCode = NTE_BAD_UID;
LOG_TRY(TDestroyHash(hHash, ptc));
*/
fSuccess = TRUE;
Cleanup:
ptc->fTestingDestroyHash = FALSE;
if (hHash)
{
TDestroyHash(hHash, ptc);
}
if (hProv)
{
TRelease(hProv, 0, ptc);
}
return fSuccess;
}
//
// Function: PositiveGetHashParamTests
// Purpose: Run the test cases for CryptGetHashParam
//
BOOL PositiveGetHashParamTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
//LPWSTR pwszContainer = TEST_CONTAINER;
HCRYPTPROV hProv = 0;
HCRYPTHASH hHash = 0;
DWORD dwData = 0;
DWORD cbData = 0;
PBYTE pbData = 0;
PTESTCASE ptc = &(pCSPInfo->TestCase);
LOG_TRY(CreateNewContext(&hProv, NULL, CRYPT_VERIFYCONTEXT, ptc));
//
// Group 3D
//
//
// Do CryptGetHashParam positive test cases
//
//
// Test HP_ALGID
//
LOG_TRY(CreateNewHash(hProv, CALG_SHA1, &hHash, ptc));
cbData = sizeof(dwData);
LOG_TRY(TGetHash(
hHash,
HP_ALGID,
(PBYTE) &dwData,
&cbData,
0,
ptc));
if (CALG_SHA1 != dwData)
{
ptc->pwszErrorHelp = L"CryptGetHashParam HP_ALGID returned incorrect ALG_ID";
LOG_TRY(LogApiFailure(
API_CRYPTGETHASHPARAM,
ERROR_BAD_DATA,
ptc));
ptc->pwszErrorHelp = NULL;
}
//
// Test HP_HASHSIZE
//
cbData = sizeof(dwData);
LOG_TRY(TGetHash(
hHash,
HP_HASHSIZE,
(PBYTE) &dwData,
&cbData,
0,
ptc));
if (HASH_LENGTH_SHA1 != dwData)
{
ptc->pwszErrorHelp = L"CryptGetHashParam HP_HASHSIZE returned incorrect length";
LOG_TRY(LogApiFailure(
API_CRYPTGETHASHPARAM,
ERROR_WRONG_SIZE,
ptc));
ptc->pwszErrorHelp = NULL;
}
//
// Test HP_HASHVAL
//
cbData = HASH_LENGTH_SHA1;
LOG_TRY(TestAlloc(&pbData, cbData, ptc));
LOG_TRY(TGetHash(
hHash,
HP_HASHVAL,
pbData,
&cbData,
0,
ptc));
fSuccess = TRUE;
Cleanup:
if (hHash)
{
TDestroyHash(hHash, ptc);
}
if (hProv)
{
TRelease(hProv, 0, ptc);
}
if (pbData)
{
free(pbData);
}
return fSuccess;
}
//
// Function: NegativeGetHashParamTests
// Purpose: Run the negative test cases for CryptGetHashParam
//
BOOL NegativeGetHashParamTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
//LPWSTR pwszContainer = TEST_CONTAINER;
HCRYPTPROV hProv = 0;
HCRYPTHASH hHash = 0;
DWORD dw = 0;
DWORD cb = 0;
PTESTCASE ptc = &(pCSPInfo->TestCase);
//
// Group 3D
//
//
// Do CryptGetHashParam negative test cases
//
cb = sizeof(dw);
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(TGetHash(0, HP_HASHSIZE, (PBYTE) &dw, &cb, 0, ptc));
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(TGetHash(TEST_INVALID_HANDLE, HP_HASHSIZE, (PBYTE) &dw, &cb, 0, ptc));
LOG_TRY(CreateNewContext(&hProv, NULL, CRYPT_VERIFYCONTEXT, ptc));
LOG_TRY(CreateNewHash(hProv, CALG_SHA1, &hHash, ptc));
ptc->dwErrorCode = ERROR_INVALID_PARAMETER;
LOG_TRY(TGetHash(hHash, HP_HASHSIZE, (PBYTE) &dw, NULL, 0, ptc));
//
// This corrupts memory since it doesn't immediately AV
//
/*
cb = HASH_LENGTH_SHA1;
ptc->dwErrorCode = ERROR_INVALID_PARAMETER;
LOG_TRY(TGetHash(hHash, HP_HASHVAL, (PBYTE) &dw, &cb, 0, ptc));
*/
cb = HASH_LENGTH_SHA1 - 1;
ptc->dwErrorCode = ERROR_MORE_DATA;
LOG_TRY(TGetHash(hHash, HP_HASHVAL, (PBYTE) &dw, &cb, 0, ptc));
cb = sizeof(dw);
ptc->dwErrorCode = NTE_BAD_FLAGS;
LOG_TRY(TGetHash(hHash, HP_HASHSIZE, (PBYTE) &dw, &cb, TEST_INVALID_FLAG, ptc));
ptc->dwErrorCode = NTE_BAD_TYPE;
LOG_TRY(TGetHash(hHash, TEST_INVALID_FLAG, (PBYTE) &dw, &cb, 0, ptc));
/*
LOG_TRY(TRelease(hProv, 0, ptc));
hProv = 0;
// Provider handle used to create hHash is now invalid
ptc->dwErrorCode = NTE_BAD_UID;
LOG_TRY(TGetHash(hHash, HP_HASHSIZE, (PBYTE) &dw, &cb, 0, ptc));
*/
fSuccess = TRUE;
Cleanup:
if (hHash)
{
TDestroyHash(hHash, ptc);
}
if (hProv)
{
TRelease(hProv, 0, ptc);
}
return fSuccess;
}
//
// Function: TestMacDataWithKeyProc
// Purpose: This function tests MAC functionality. First, a session key
// is created of the block-cipher algorithm indicated in pAlgNode.
// Then a keyed hash is created using that key and the hash algorithm
// specified in pvTestHashDataInfo.
//
// After the base data (in pvTestHashDataInfo) is hashed, the result is
// passed to CheckHashedData to verify that the same result is attained
// with a second, separate CSP.
//
BOOL TestMacDataWithKeyProc(
PALGNODE pAlgNode,
PTESTCASE ptc,
PVOID pvTestHashDataInfo)
{
BOOL fSuccess = FALSE;
PTEST_HASH_DATA_INFO pTestHashDataInfo = (PTEST_HASH_DATA_INFO) pvTestHashDataInfo;
HCRYPTHASH hHash = 0;
HCRYPTKEY hKey = 0;
HASH_INFO HashInfo;
TEST_MAC_INFO MacInfo;
memset(&HashInfo, 0, sizeof(HashInfo));
memset(&MacInfo, 0, sizeof(MacInfo));
HashInfo.aiHash = pTestHashDataInfo->aiMac;
HashInfo.dbBaseData.cbData = pTestHashDataInfo->dbBaseData.cbData;
HashInfo.dbBaseData.pbData = pTestHashDataInfo->dbBaseData.pbData;
LOG_TRY(TGenKey(
pTestHashDataInfo->hProv,
pAlgNode->ProvEnumalgsEx.aiAlgid,
CRYPT_EXPORTABLE,
&hKey,
ptc));
LOG_TRY(ExportPlaintextSessionKey(
hKey,
pTestHashDataInfo->hProv,
&(MacInfo.dbKey),
ptc));
memcpy(&(MacInfo.HmacInfo), &(pTestHashDataInfo->HmacInfo), sizeof(HMAC_INFO));
LOG_TRY(CreateHashAndAddData(
pTestHashDataInfo->hProv,
&hHash,
&HashInfo,
ptc,
hKey,
&(MacInfo.HmacInfo)));
LOG_TRY(TGetHash(
hHash,
HP_HASHVAL,
NULL,
&(HashInfo.dbHashValue.cbData),
0,
ptc));
LOG_TRY(TestAlloc(
&(HashInfo.dbHashValue.pbData),
HashInfo.dbHashValue.cbData,
ptc));
LOG_TRY(TGetHash(
hHash,
HP_HASHVAL,
HashInfo.dbHashValue.pbData,
&(HashInfo.dbHashValue.cbData),
0,
ptc));
LOG_TRY(CheckHashedData(
&HashInfo,
pTestHashDataInfo->hInteropProv,
ptc,
&MacInfo));
fSuccess = TRUE;
Cleanup:
if (MacInfo.dbKey.pbData)
{
free(MacInfo.dbKey.pbData);
}
if (HashInfo.dbHashValue.pbData)
{
free(HashInfo.dbHashValue.pbData);
}
if (hHash)
{
TDestroyHash(hHash, ptc);
}
if (hKey)
{
TDestroyKey(hKey, ptc);
}
return fSuccess;
}
//
// Function: TestMacDataProc
//
BOOL TestMacDataProc(
PALGNODE pAlgNode,
PTESTCASE ptc,
PVOID pvTestHashDataInfo)
{
//
// Because of the filter used before calling this function,
// we know that pAlgNode contains a ProvEnumalgsEx structure that
// corresponds to a MAC'ing algorithm. Save the ALG_ID for the current
// MAC algorithm and pass it through to the TestMacDataWithKeyProc, which
// will do the real work of creating the keyed hash.
//
((PTEST_HASH_DATA_INFO) pvTestHashDataInfo)->aiMac = pAlgNode->ProvEnumalgsEx.aiAlgid;
return AlgListIterate(
((PTEST_HASH_DATA_INFO) pvTestHashDataInfo)->pAlgList,
BlockCipherFilter,
TestMacDataWithKeyProc,
pvTestHashDataInfo,
ptc);
}
//
// Function: TestHashDataProc
//
BOOL TestHashDataProc(
PALGNODE pAlgNode,
PTESTCASE ptc,
PVOID pvTestHashDataInfo)
{
HCRYPTHASH hHash = 0;
BOOL fSuccess = FALSE;
DWORD dwSavedErrorLevel = ptc->dwErrorLevel;
HASH_INFO HashInfo;
PTEST_HASH_DATA_INFO pTestHashDataInfo = (PTEST_HASH_DATA_INFO) pvTestHashDataInfo;
memset(&HashInfo, 0, sizeof(HashInfo));
if (! pAlgNode->fIsRequiredAlg)
{
ptc->dwErrorLevel = CSP_ERROR_WARNING;
}
HashInfo.aiHash = pAlgNode->ProvEnumalgsEx.aiAlgid;
HashInfo.dbBaseData.cbData = pTestHashDataInfo->dbBaseData.cbData;
HashInfo.dbBaseData.pbData = pTestHashDataInfo->dbBaseData.pbData;
//
// Call CreateHashAndAddData with the required parameters
// for a non-keyed hash alg.
//
LOG_TRY(CreateHashAndAddData(
pTestHashDataInfo->hProv,
&hHash,
&HashInfo,
ptc,
0, NULL));
LOG_TRY(TGetHash(
hHash,
HP_HASHVAL,
NULL,
&(HashInfo.dbHashValue.cbData),
0,
ptc));
LOG_TRY(TestAlloc(
&(HashInfo.dbHashValue.pbData),
HashInfo.dbHashValue.cbData,
ptc));
LOG_TRY(TGetHash(
hHash,
HP_HASHVAL,
HashInfo.dbHashValue.pbData,
&(HashInfo.dbHashValue.cbData),
0,
ptc));
//
// Call CheckHashedData with the required information
// for a non-keyed hash.
//
LOG_TRY(CheckHashedData(
&HashInfo,
pTestHashDataInfo->hInteropProv,
ptc,
NULL));
fSuccess = TRUE;
Cleanup:
ptc->dwErrorLevel = dwSavedErrorLevel;
if (HashInfo.dbHashValue.pbData)
{
free(HashInfo.dbHashValue.pbData);
}
if (hHash)
{
TDestroyHash(hHash, ptc);
}
return fSuccess;
}
//
// Function: InteropHashDataTests
// Purpose: Run the interop test scenarios for CryptHashData
//
BOOL InteropHashDataTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
//LPWSTR pwszContainer = TEST_CONTAINER;
PTESTCASE ptc = &(pCSPInfo->TestCase);
PALGNODE pAlgList = pCSPInfo->pAlgList;
TEST_HASH_DATA_INFO TestHashDataInfo;
memset(&TestHashDataInfo, 0, sizeof(TestHashDataInfo));
LOG_TRY(CreateNewContext(
&(TestHashDataInfo.hProv),
NULL,
CRYPT_VERIFYCONTEXT,
ptc));
LOG_TRY(CreateNewInteropContext(
&(TestHashDataInfo.hInteropProv),
NULL,
CRYPT_VERIFYCONTEXT,
ptc));
//
// Initialize the test data to be hashed
//
TestHashDataInfo.dbBaseData.cbData = wcslen(TEST_HASH_DATA) * sizeof(WCHAR);
LOG_TRY(TestAlloc(
&(TestHashDataInfo.dbBaseData.pbData),
TestHashDataInfo.dbBaseData.cbData,
ptc));
memcpy(
TestHashDataInfo.dbBaseData.pbData,
TEST_HASH_DATA,
TestHashDataInfo.dbBaseData.cbData);
//
// Non-keyed Hashes
//
// Iterate through the ENUMALGS_EX structs stored in the ALGNODE list.
// Create a hash of each type supported by this CSP.
//
LOG_TRY(AlgListIterate(
pAlgList,
HashAlgFilter,
TestHashDataProc,
(PVOID) (&TestHashDataInfo),
ptc));
//
// Keyed Hashes
//
// TODO: Currently using SHA1 as the only HMAC test case. Is
// there a problem with that? The alternative would be
// to make the below AlgListIterate loop longer.
//
TestHashDataInfo.HmacInfo.HashAlgid = CALG_SHA1;
//
// Iterate through all required hash algorithms and all
// required block cipher algorithms.
//
TestHashDataInfo.pAlgList = pCSPInfo->pAlgList;
LOG_TRY(AlgListIterate(
pAlgList,
MacAlgFilter,
TestMacDataProc,
(PVOID) (&TestHashDataInfo),
ptc));
fSuccess = TRUE;
Cleanup:
if (TestHashDataInfo.hProv)
{
TRelease(TestHashDataInfo.hProv, 0, ptc);
}
if (TestHashDataInfo.dbBaseData.pbData)
{
free(TestHashDataInfo.dbBaseData.pbData);
}
if (TestHashDataInfo.hInteropProv)
{
TRelease(TestHashDataInfo.hInteropProv, 0, ptc);
}
return fSuccess;
}
//
// Function: PositiveHashDataTests
// Purpose: Run the test cases for CryptHashData
//
BOOL PositiveHashDataTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
//LPWSTR pwszContainer = TEST_CONTAINER;
HCRYPTHASH hHash = 0;
HCRYPTPROV hProv = 0;
DWORD cb = 0;
PTESTCASE ptc = &(pCSPInfo->TestCase);
BYTE rgbHashSha[HASH_LENGTH_SHA1];
BYTE rgbHashMD5[HASH_LENGTH_MD5];
memset(rgbHashSha, 0, HASH_LENGTH_SHA1);
memset(rgbHashMD5, 0, HASH_LENGTH_MD5);
LOG_TRY(CreateNewContext(&hProv, NULL, CRYPT_VERIFYCONTEXT, ptc));
LOG_TRY(CreateNewHash(hProv, CALG_SHA1, &hHash, ptc));
LOG_TRY(THashData(hHash, KNOWN_HASH_DATA, KNOWN_HASH_DATALEN, 0, ptc));
cb = HASH_LENGTH_SHA1;
LOG_TRY(TGetHash(hHash, HP_HASHVAL, rgbHashSha, &cb, 0, ptc));
if (0 != memcmp(rgbHashSha, g_rgbKnownSHA1, HASH_LENGTH_SHA1))
{
LOG_TRY(LogBadParam(
API_CRYPTHASHDATA,
L"Incorrect SHA1 hash value",
ptc));
}
LOG_TRY(TDestroyHash(hHash, ptc));
hHash = 0;
LOG_TRY(CreateNewHash(hProv, CALG_MD5, &hHash, ptc));
LOG_TRY(THashData(hHash, KNOWN_HASH_DATA, KNOWN_HASH_DATALEN, 0, ptc));
cb = HASH_LENGTH_MD5;
LOG_TRY(TGetHash(hHash, HP_HASHVAL, rgbHashMD5, &cb, 0, ptc));
if (0 != memcmp(rgbHashMD5, g_rgbKnownMD5, HASH_LENGTH_MD5))
{
LOG_TRY(LogBadParam(
API_CRYPTHASHDATA,
L"Incorrect MD5 hash value",
ptc));
}
LOG_TRY(TDestroyHash(hHash, ptc));
hHash = 0;
fSuccess = TRUE;
Cleanup:
if (hHash)
{
TDestroyHash(hHash, ptc);
}
if (hProv)
{
TRelease(hProv, 0, ptc);
}
return fSuccess;
}
//
// Function: NegativeHashDataTests
// Purpose: Run the negative test cases for CryptHashData
//
BOOL NegativeHashDataTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
//LPWSTR pwszContainer = TEST_CONTAINER;
HCRYPTPROV hProv = 0;
HCRYPTHASH hHash = 0;
PBYTE pb = NULL;
DWORD cb = 0;
PTESTCASE ptc = &(pCSPInfo->TestCase);
DWORD dwSavedErrorLevel = 0;
//
// Group 3E
//
//
// Do CryptHashData negative test cases
//
pb = (PBYTE) TEST_HASH_DATA;
// Not hashing terminating Null
cb = wcslen(TEST_HASH_DATA) * sizeof(WCHAR);
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(THashData(0, pb, cb, 0, ptc));
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(THashData(TEST_INVALID_HANDLE, pb, cb, 0, ptc));
LOG_TRY(CreateNewContext(&hProv, NULL, CRYPT_VERIFYCONTEXT, ptc));
LOG_TRY(CreateNewHash(hProv, CALG_SHA1, &hHash, ptc));
ptc->dwErrorCode = NTE_BAD_DATA;
LOG_TRY(THashData(hHash, NULL, cb, 0, ptc));
//
// 7/25/00 -- leaving this test case out, since the current
// behavior seems friendlier.
//
/*
ptc->dwErrorCode = NTE_BAD_LEN;
LOG_TRY(THashData(hHash, pb, 0, 0, ptc));
*/
ptc->dwErrorCode = NTE_BAD_FLAGS;
LOG_TRY(THashData(hHash, pb, cb, TEST_INVALID_FLAG, ptc));
// For CSP's that support CRYPT_USERDATA, cbData must be zero, or error
dwSavedErrorLevel = ptc->dwErrorLevel;
ptc->dwErrorLevel = CSP_ERROR_WARNING;
ptc->pwszErrorHelp =
L"CryptHashData CRYPT_USERDATA should fail when dwDataLen is not zero (optional)";
ptc->dwErrorCode = NTE_BAD_LEN;
LOG_TRY(THashData(hHash, pb, 1, CRYPT_USERDATA, ptc));
ptc->dwErrorLevel = dwSavedErrorLevel;
ptc->pwszErrorHelp = NULL;
/*
LOG_TRY(TRelease(hProv, 0, ptc));
hProv = 0;
// Provider handle used to create hHash is now invalid
ptc->dwErrorCode = NTE_BAD_UID;
LOG_TRY(THashData(hHash, pb, cb, 0, ptc));
*/
fSuccess = TRUE;
Cleanup:
if (hHash)
{
TDestroyHash(hHash, ptc);
}
if (hProv)
{
TRelease(hProv, 0, ptc);
}
return fSuccess;
}
//
// Function: PositiveSetHashParamTests
// Purpose: Run the test cases for CryptSetHashParam
//
BOOL PositiveSetHashParamTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
//LPWSTR pwszContainer = TEST_CONTAINER;
HCRYPTPROV hProv = 0;
HCRYPTHASH hHash = 0;
BYTE rgHashVal[HASH_LENGTH_SHA1];
PTESTCASE ptc = &(pCSPInfo->TestCase);
memset(rgHashVal, 0, sizeof(rgHashVal));
LOG_TRY(CreateNewContext(&hProv, NULL, CRYPT_VERIFYCONTEXT, ptc));
LOG_TRY(CreateNewHash(hProv, CALG_SHA1, &hHash, ptc));
//
// Group 3F
//
//
// Do CryptSetHashParam positive test cases
//
//
// Skip testing HP_HMAC_INFO here. It's only an interesting test
// if the CSP supports a MAC alg. This is already covered in the
// CryptHashData tests.
//
//
// Test HP_HASHVAL
//
LOG_TRY(TSetHash(
hHash,
HP_HASHVAL,
rgHashVal,
0,
ptc));
fSuccess = TRUE;
Cleanup:
if (hHash)
{
TDestroyHash(hHash, ptc);
}
if (hProv)
{
TRelease(hProv, 0, ptc);
}
return fSuccess;
}
//
// Function: NegativeSetHashParamTests
// Purpose: Run the negative test cases for CryptSetHashParam
//
BOOL NegativeSetHashParamTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
LPWSTR pwszContainer = TEST_CONTAINER;
HCRYPTPROV hProv = 0;
HCRYPTHASH hHash = 0;
DWORD dw = 0;
//DWORD cb = 0;
BYTE rgHashVal[HASH_LENGTH_SHA1];
PTESTCASE ptc = &(pCSPInfo->TestCase);
memset(rgHashVal, 0, sizeof(rgHashVal));
//
// Group 3F
//
//
// Do CryptSetHashParam negative test cases
//
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(TSetHash(0, HP_HASHVAL, rgHashVal, 0, ptc));
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(TSetHash(TEST_INVALID_HANDLE, HP_HASHVAL, rgHashVal, 0, ptc));
LOG_TRY(CreateNewContext(&hProv, NULL, CRYPT_VERIFYCONTEXT, ptc));
LOG_TRY(CreateNewHash(hProv, CALG_SHA1, &hHash, ptc));
ptc->dwErrorCode = ERROR_INVALID_PARAMETER;
LOG_TRY(TSetHash(hHash, HP_HASHVAL, NULL, 0, ptc));
// Hash value buffer is too short
/*
ptc->dwErrorCode = ERROR_INVALID_PARAMETER;
LOG_TRY(TSetHash(hHash, HP_HASHVAL, (PBYTE) &dw, 0, ptc));
*/
ptc->dwErrorCode = ERROR_INVALID_PARAMETER;
LOG_TRY(TSetHash(hHash, HP_HASHVAL, (PBYTE) TEST_INVALID_POINTER, 0, ptc));
ptc->dwErrorCode = NTE_BAD_TYPE;
LOG_TRY(TSetHash(hHash, HP_HMAC_INFO, (PBYTE) &dw, 0, ptc));
ptc->dwErrorCode = NTE_BAD_FLAGS;
LOG_TRY(TSetHash(hHash, HP_HASHVAL, rgHashVal, TEST_INVALID_FLAG, ptc));
ptc->dwErrorCode = NTE_BAD_TYPE;
LOG_TRY(TSetHash(hHash, TEST_INVALID_FLAG, rgHashVal, 0, ptc));
/*
LOG_TRY(TRelease(hProv, 0, ptc));
hProv = 0;
// Provider handle used to create hHash is now invalid
ptc->dwErrorCode = NTE_BAD_UID;
LOG_TRY(TSetHash(hHash, HP_HASHVAL, rgHashVal, 0, ptc));
*/
fSuccess = TRUE;
Cleanup:
if (hHash)
{
TDestroyHash(hHash, ptc);
}
if (hProv)
{
TRelease(hProv, 0, ptc);
}
return fSuccess;
}
//
// Function: TestDecryptProc
//
BOOL TestDecryptProc(
PALGNODE pAlgNode,
PTESTCASE ptc,
PVOID pvTestDecryptInfo)
{
BOOL fSuccess = FALSE;
PTEST_DECRYPT_INFO pTestDecryptInfo = (PTEST_DECRYPT_INFO) pvTestDecryptInfo;
TEST_ENCRYPT_INFO TestEncryptInfo;
memset(&TestEncryptInfo, 0, sizeof(TestEncryptInfo));
//
// TODO: There are a lot more permutations possible when calling
// ProcessCipherData.
//
// 1) Modulate key sizes
// 2) Switch cipher modes
// 3) Use salt
// 4) Use IV's
//
TestEncryptInfo.aiKeyAlg = pAlgNode->ProvEnumalgsEx.aiAlgid;
TestEncryptInfo.dwKeySize = pAlgNode->ProvEnumalgsEx.dwMaxLen;
TestEncryptInfo.Operation = pTestDecryptInfo->fDecrypt ? OP_Decrypt : OP_Encrypt;
LOG_TRY(ProcessCipherData(
pTestDecryptInfo->hProv,
&TestEncryptInfo,
ptc));
LOG_TRY(VerifyCipherData(
pTestDecryptInfo->hInteropProv,
&TestEncryptInfo,
ptc));
fSuccess = TRUE;
Cleanup:
return fSuccess;
}
//
// Function: ScenarioDecryptTests
// Purpose: Run decrypt/encryption scenarios for this CSP
//
BOOL ScenarioDecryptTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
LPWSTR pwszContainer = TEST_CONTAINER;
LPWSTR pwszContainer2 = TEST_CONTAINER_2;
PTESTCASE ptc = &(pCSPInfo->TestCase);
TEST_DECRYPT_INFO TestDecryptInfo;
memset(&TestDecryptInfo, 0, sizeof(TestDecryptInfo));
LOG_TRY(CreateNewContext(
&(TestDecryptInfo.hProv),
pwszContainer,
CRYPT_NEWKEYSET,
ptc));
LOG_TRY(CreateNewContext(
&(TestDecryptInfo.hInteropProv),
pwszContainer2,
CRYPT_NEWKEYSET,
ptc));
LOG_TRY(AlgListIterate(
pCSPInfo->pAlgList,
DataEncryptFilter,
TestDecryptProc,
(PVOID) (&TestDecryptInfo),
ptc));
fSuccess = TRUE;
Cleanup:
if (TestDecryptInfo.hProv)
{
TRelease(TestDecryptInfo.hProv, 0, ptc);
}
if (TestDecryptInfo.hInteropProv)
{
TRelease(TestDecryptInfo.hInteropProv, 0, ptc);
}
return fSuccess;
}
//
// Function: InteropDecryptTests
// Purpose: Run decrypt/encryption interop scenarios for this
// and a second CSP.
//
BOOL InteropDecryptTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
LPWSTR pwszContainer = TEST_CONTAINER;
LPWSTR pwszInteropContainer = TEST_CONTAINER_2;
PTESTCASE ptc = &(pCSPInfo->TestCase);
TEST_DECRYPT_INFO TestDecryptInfo;
memset(&TestDecryptInfo, 0, sizeof(TestDecryptInfo));
LOG_TRY(CreateNewContext(
&(TestDecryptInfo.hProv),
pwszContainer,
CRYPT_NEWKEYSET,
ptc));
LOG_TRY(CreateNewInteropContext(
&(TestDecryptInfo.hInteropProv),
pwszInteropContainer,
CRYPT_NEWKEYSET,
ptc));
LOG_TRY(AlgListIterate(
pCSPInfo->pAlgList,
DataEncryptFilter,
TestDecryptProc,
(PVOID) (&TestDecryptInfo),
ptc));
fSuccess = TRUE;
Cleanup:
if (TestDecryptInfo.hProv)
{
TRelease(TestDecryptInfo.hProv, 0, ptc);
}
if (TestDecryptInfo.hInteropProv)
{
TRelease(TestDecryptInfo.hInteropProv, 0, ptc);
}
return fSuccess;
}
//
// RSA Key-exchange private key blob. Used
// by PositiveDecryptTests, below.
//
BYTE g_rgbRSAPrivateKeyXBlob [] =
{
0x07, 0x02, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00,
0x52, 0x53, 0x41, 0x32, 0x00, 0x02, 0x00, 0x00,
0x01, 0x00, 0x01, 0x00, 0x13, 0x98, 0xf3, 0x0d,
0x08, 0x86, 0x14, 0x94, 0xc8, 0x7b, 0x29, 0x71,
0xa4, 0x5f, 0xdf, 0xf4, 0xf4, 0x8f, 0x29, 0x00,
0x07, 0xfa, 0xb0, 0x39, 0xe2, 0x36, 0x09, 0x7e,
0xff, 0x89, 0xea, 0xb9, 0xac, 0xcd, 0xdd, 0xc6,
0xce, 0x14, 0x21, 0x42, 0x85, 0x93, 0x7a, 0x63,
0x79, 0xdc, 0x21, 0xf3, 0x8c, 0x42, 0x5e, 0xdb,
0xe1, 0x72, 0x42, 0x81, 0xdb, 0xc6, 0xc9, 0x1e,
0xd5, 0x45, 0x2a, 0xb9, 0x91, 0x0a, 0xaa, 0x2c,
0x9f, 0x41, 0xde, 0x0e, 0x31, 0x0a, 0xee, 0x17,
0x24, 0xb9, 0xe6, 0x61, 0x88, 0x15, 0x69, 0x1e,
0x24, 0xea, 0x54, 0x1d, 0xbe, 0xc9, 0x6f, 0x1d,
0x74, 0xf8, 0xa7, 0xe4, 0x63, 0x62, 0xc6, 0x44,
0x2e, 0xfa, 0x19, 0x89, 0xdf, 0x1d, 0x97, 0x70,
0x4a, 0x7a, 0xef, 0x92, 0x22, 0xff, 0xcc, 0xae,
0x4e, 0x58, 0x77, 0xff, 0x78, 0xcb, 0x03, 0x6e,
0xc3, 0xe0, 0x4e, 0xcf, 0x21, 0xdf, 0x91, 0x35,
0x3e, 0xf3, 0xa0, 0x92, 0xc5, 0x3f, 0xd9, 0xa1,
0x00, 0x1a, 0x3e, 0x72, 0xbe, 0x22, 0x10, 0xe5,
0xb3, 0xda, 0xa0, 0x95, 0x45, 0xc7, 0x92, 0x99,
0x87, 0xa4, 0x8d, 0x43, 0x55, 0xca, 0xa5, 0x8d,
0x80, 0xec, 0xb5, 0xe2, 0x1f, 0xc8, 0x9c, 0x54,
0x07, 0xfa, 0x7a, 0x4c, 0xfe, 0xf9, 0x9f, 0xe5,
0x2b, 0xb8, 0x85, 0x3c, 0x0f, 0xe9, 0x41, 0xb1,
0x74, 0x8f, 0x48, 0x99, 0x7c, 0x70, 0x40, 0x05,
0xe1, 0xb2, 0x75, 0x9a, 0xb7, 0x70, 0x40, 0xd2,
0x2e, 0xc1, 0xbb, 0xc1, 0x63, 0xbf, 0x5a, 0x59,
0x4d, 0xcf, 0xec, 0x05, 0xfb, 0x1d, 0xab, 0x5d,
0x45, 0x1c, 0x69, 0x14, 0x21, 0x56, 0x31, 0xd6,
0x86, 0x99, 0x32, 0x59, 0xd6, 0x88, 0x53, 0x12,
0x54, 0xe3, 0xe5, 0x07, 0x5b, 0xcc, 0x5e, 0xbd,
0x83, 0xea, 0x38, 0x56, 0x45, 0x74, 0x39, 0x0b,
0x30, 0xf6, 0xe2, 0x56, 0x4d, 0xae, 0x69, 0xf5,
0xb4, 0xf6, 0x35, 0x6f, 0xa8, 0x6f, 0x87, 0xb0,
0x52, 0x5b, 0x33, 0xea, 0xdc, 0xd8, 0x83, 0xa3,
0xec, 0xda, 0x2c, 0xdd, 0xb5, 0x0a, 0xea, 0x15,
0x1c, 0x68, 0xaa, 0x8b
};
//
// Cipher text encrypted with the g_rgbRSAPrivateKeyXBlob
// above. Used by PositiveDecryptTests.
//
BYTE g_rgbRSACipherText [] =
{
0xd8, 0x9f, 0xcd, 0xd2, 0x77, 0x45, 0x76, 0x77,
0x66, 0x32, 0x4c, 0x88, 0x2d, 0xcf, 0xdc, 0xfd,
0xe5, 0x03, 0xfc, 0x4e, 0x65, 0xd1, 0x77, 0xd5,
0x90, 0x3d, 0x71, 0x88, 0x1e, 0xff, 0x3b, 0x27,
0xff, 0x4c, 0xb9, 0xc5, 0x6b, 0x6b, 0x4d, 0xd9,
0x9e, 0x11, 0x88, 0xcb, 0xb8, 0xbb, 0x48, 0xc8,
0xc3, 0x7e, 0xb0, 0xd5, 0x0d, 0x1a, 0x2e, 0xed,
0x6a, 0x4a, 0x45, 0xb1, 0xdc, 0x6e, 0x65, 0x42
};
//
// Function: PositiveDecryptTests
// Purpose: Run the test cases for CryptDecrypt
//
BOOL PositiveDecryptTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
HCRYPTPROV hProv = 0;
HCRYPTKEY hKey = 0;
LPWSTR pwszContainer = TEST_CONTAINER;
PBYTE pbData = NULL;
DWORD cbData = 0;
//DWORD dw = 0;
PTESTCASE ptc = &(pCSPInfo->TestCase);
LOG_TRY(CreateNewContext(&hProv, NULL, CRYPT_VERIFYCONTEXT, ptc));
//
// Group 4A
//
//
// Do CryptDecrypt positive test cases
//
switch( pCSPInfo->TestCase.dwTestLevel )
{
case TEST_LEVEL_KEY:
{
LOG_TRY(CreateNewContext(&hProv, NULL, CRYPT_VERIFYCONTEXT, ptc));
//
// Run some basic decryption tests for a stream cipher
//
LOG_TRY(CreateNewKey(hProv, CALG_RC4, 0, &hKey, ptc));
cbData = wcslen(TEST_DECRYPT_DATA) * sizeof(WCHAR);
LOG_TRY(TestAlloc(&pbData, cbData, ptc));
memcpy(pbData, TEST_DECRYPT_DATA, cbData);
LOG_TRY(TDecrypt(hKey, 0, TRUE, 0, pbData, &cbData, ptc));
break;
}
case TEST_LEVEL_CONTAINER:
{
LOG_TRY(CreateNewContext(&hProv, NULL, CRYPT_NEWKEYSET, ptc));
//
// Import a known RSA key-exchange key pair.
//
LOG_TRY(TImportKey(
hProv,
g_rgbRSAPrivateKeyXBlob,
sizeof(g_rgbRSAPrivateKeyXBlob),
0,
0,
&hKey,
ptc));
cbData = sizeof(g_rgbRSACipherText);
LOG_TRY(TDecrypt(
hKey,
0,
TRUE,
0,
g_rgbRSACipherText,
&cbData,
ptc));
break;
}
default:
{
goto Cleanup;
}
}
fSuccess = TRUE;
Cleanup:
if (hKey)
{
TDestroyKey(hKey, ptc);
}
if (hProv)
{
TRelease(hProv, 0, ptc);
}
return fSuccess;
}
//
// Function: NegativeDecryptTests
// Purpose: Run the negative test cases for CryptDecrypt
//
BOOL NegativeDecryptTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
//LPWSTR pwszContainer = TEST_CONTAINER;
HCRYPTPROV hProv = 0;
HCRYPTKEY hKey = 0;
DWORD cb = 0;
//DWORD dw = 0;
PTESTCASE ptc = &(pCSPInfo->TestCase);
DWORD dwSavedErrorLevel = 0;
BYTE rgCipherText[TEST_CIPHER_LENGTH_RC4];
BYTE rgRC2CipherText[TEST_RC2_BUFFER_LEN];
memset(rgCipherText, 0, sizeof(rgCipherText));
memset(rgRC2CipherText, 0, sizeof(rgRC2CipherText));
//
// Group 4A
//
//
// Do CryptDecrypt negative test cases
//
cb = sizeof(rgCipherText);
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(TDecrypt(0, 0, TRUE, 0, rgCipherText, &cb, ptc));
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(TDecrypt(TEST_INVALID_HANDLE, 0, TRUE, 0, rgCipherText, &cb, ptc));
LOG_TRY(CreateNewContext(&hProv, NULL, CRYPT_VERIFYCONTEXT, ptc));
LOG_TRY(CreateNewKey(hProv, CALG_RC4, 0, &hKey, ptc));
ptc->dwErrorCode = ERROR_INVALID_PARAMETER;
LOG_TRY(TDecrypt(hKey, 0, TRUE, 0, (PBYTE) TEST_INVALID_POINTER, &cb, ptc));
cb = sizeof(rgCipherText);
ptc->dwErrorCode = NTE_BAD_FLAGS;
LOG_TRY(TDecrypt(hKey, 0, TRUE, TEST_INVALID_FLAG, rgCipherText, &cb, ptc));
ptc->dwErrorCode = NTE_BAD_HASH;
LOG_TRY(TDecrypt(hKey, TEST_INVALID_HANDLE, TRUE, 0, rgCipherText, &cb, ptc));
cb = 0;
ptc->dwErrorCode = NTE_BAD_LEN;
LOG_TRY(TDecrypt(hKey, 0, TRUE, 0, rgCipherText, &cb, ptc));
ptc->fExpectSuccess = TRUE;
cb = sizeof(rgCipherText);
LOG_TRY(TDecrypt(hKey, 0, TRUE, 0, rgCipherText, &cb, ptc));
ptc->fExpectSuccess = FALSE;
// This will only fail on no-export CSP's
dwSavedErrorLevel = ptc->dwErrorLevel;
ptc->dwErrorLevel = CSP_ERROR_WARNING;
ptc->pwszErrorHelp = L"This CSP supports double-decryption";
ptc->dwErrorCode = NTE_DOUBLE_ENCRYPT;
LOG_TRY(TDecrypt(hKey, 0, TRUE, 0, rgCipherText, &cb, ptc));
ptc->dwErrorLevel = dwSavedErrorLevel;
ptc->pwszErrorHelp = NULL;
//
// Test block cipher issues with an RC2 key
//
LOG_TRY(TDestroyKey(hKey, ptc));
hKey = 0;
LOG_TRY(CreateNewKey(hProv, CALG_RC2, 0, &hKey, ptc));
cb = TEST_RC2_DATA_LEN;
ptc->fExpectSuccess = TRUE;
LOG_TRY(TEncrypt(
hKey,
0,
TRUE,
0,
rgRC2CipherText,
&cb,
sizeof(rgRC2CipherText),
ptc));
ptc->fExpectSuccess = FALSE;
cb--;
ptc->dwErrorCode = NTE_BAD_DATA;
LOG_TRY(TDecrypt(hKey, 0, TRUE, 0, rgRC2CipherText, &cb, ptc));
/*
LOG_TRY(TRelease(hProv, 0, ptc));
hProv = 0;
cb = sizeof(rgCipherText);
memset(rgCipherText, 0, cb);
ptc->dwErrorCode = NTE_BAD_UID;
LOG_TRY(TDecrypt(hKey, 0, TRUE, 0, rgCipherText, &cb, ptc));
*/
fSuccess = TRUE;
Cleanup:
if (hKey)
{
TDestroyKey(hKey, ptc);
}
if (hProv)
{
TRelease(hProv, 0, ptc);
}
return fSuccess;
}
//
// Function: TestDeriveKeyProc
//
BOOL TestDeriveKeyProc(
PALGNODE pAlgNode,
PTESTCASE ptc,
PVOID pvTestDeriveKeyInfo)
{
BOOL fSuccess = FALSE;
HCRYPTHASH hHash = 0;
HCRYPTKEY hKey = 0;
DERIVED_KEY_INFO DerivedKeyInfo;
PTEST_DERIVE_KEY_INFO pTestDeriveKeyInfo = (PTEST_DERIVE_KEY_INFO) pvTestDeriveKeyInfo;
memset(&DerivedKeyInfo, 0, sizeof(DerivedKeyInfo));
//
// Initialize base hash information
//
DerivedKeyInfo.HashInfo.aiHash = CALG_SHA1;
DerivedKeyInfo.HashInfo.dbBaseData.pbData = (PBYTE) TEST_HASH_DATA;
DerivedKeyInfo.HashInfo.dbBaseData.cbData = wcslen(TEST_HASH_DATA) * sizeof(WCHAR);
LOG_TRY(CreateHashAndAddData(
pTestDeriveKeyInfo->hProv,
&hHash,
&(DerivedKeyInfo.HashInfo),
ptc,
0, NULL));
// Debugging
/*
DerivedKeyInfo.cbHA = sizeof(DerivedKeyInfo.rgbHashValA);
LOG_TRY(CryptGetHashParam(hHash, HP_HASHVAL, DerivedKeyInfo.rgbHashValA, &(DerivedKeyInfo.cbHA), 0));
*/
//
// Initialize the key information in DerivedKeyInfo and create the
// derived key.
//
DerivedKeyInfo.aiKey = pAlgNode->ProvEnumalgsEx.aiAlgid;
DerivedKeyInfo.dwKeySize = pAlgNode->ProvEnumalgsEx.dwDefaultLen;
LOG_TRY(TDeriveKey(
pTestDeriveKeyInfo->hProv,
DerivedKeyInfo.aiKey,
hHash,
CRYPT_EXPORTABLE | (DerivedKeyInfo.dwKeySize) << 16,
&hKey,
ptc));
// Debug
/*
DerivedKeyInfo.cbCA = 10;
LOG_TRY(CryptEncrypt(hKey, 0, TRUE, 0, DerivedKeyInfo.rgbCipherA, &(DerivedKeyInfo.cbCA), sizeof(DerivedKeyInfo.rgbCipherA)));
*/
//
// Export the derived key in plaintext and verify the resulting key
// against a second CSP.
//
LOG_TRY(ExportPlaintextSessionKey(
hKey,
pTestDeriveKeyInfo->hProv,
&(DerivedKeyInfo.dbKey),
ptc));
LOG_TRY(CheckDerivedKey(
&DerivedKeyInfo,
pTestDeriveKeyInfo->hInteropProv,
ptc));
fSuccess = TRUE;
Cleanup:
if (hHash)
{
TDestroyHash(hHash, ptc);
}
if (hKey)
{
TDestroyKey(hKey, ptc);
}
if (DerivedKeyInfo.HashInfo.dbHashValue.pbData)
{
free(DerivedKeyInfo.HashInfo.dbHashValue.pbData);
}
if (DerivedKeyInfo.dbKey.pbData)
{
free(DerivedKeyInfo.dbKey.pbData);
}
return fSuccess;
}
//
// Function: InteropDeriveKeyTests
// Purpose: Run TestDeriveKeyProc for each session key algorithm
// supported by this CSP. A second CSP is used to verify
// that the key has been derived correctly.
//
BOOL InteropDeriveKeyTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
//LPWSTR pwszContainer = TEST_CONTAINER;
//LPWSTR pwszInteropContainer = TEST_CONTAINER_2;
PTESTCASE ptc = &(pCSPInfo->TestCase);
TEST_DERIVE_KEY_INFO TestDeriveKeyInfo;
memset(&TestDeriveKeyInfo, 0, sizeof(TestDeriveKeyInfo));
LOG_TRY(CreateNewContext(
&(TestDeriveKeyInfo.hProv),
NULL,
CRYPT_VERIFYCONTEXT,
ptc));
LOG_TRY(CreateNewInteropContext(
&(TestDeriveKeyInfo.hInteropProv),
NULL,
CRYPT_VERIFYCONTEXT,
ptc));
//
// TestDeriveKeyProc will create, export, and verify a derived
// key for each session key algorithm supported by the CSP
// under test. Use of the CRYPT_EXPORTABLE flag is covered
// by that routine.
//
LOG_TRY(AlgListIterate(
pCSPInfo->pAlgList,
DataEncryptFilter,
TestDeriveKeyProc,
(PVOID) (&TestDeriveKeyInfo),
ptc));
fSuccess = TRUE;
Cleanup:
if (TestDeriveKeyInfo.hProv)
{
TRelease(TestDeriveKeyInfo.hProv, 0, ptc);
}
if (TestDeriveKeyInfo.hInteropProv)
{
TRelease(TestDeriveKeyInfo.hInteropProv, 0, ptc);
}
return fSuccess;
}
//
// Function: PositiveDeriveKeyTests
// Purpose: Run the test cases for CryptDeriveKey. The set of positive test cases
// to be executed depends on the dwCSPClass and dwTestLevel parameters.
//
// Note: Since the Microsoft RSA CSP only supports derived session keys and not
// derived public keys, the PositiveDeriveKeyTests() belong in TEST_LEVEL_KEY
// only.
//
BOOL PositiveDeriveKeyTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
//LPWSTR pwszContainer = TEST_CONTAINER;
HCRYPTPROV hProv = 0;
HCRYPTHASH hHash = 0;
HCRYPTKEY hKey = 0;
PTESTCASE ptc = &(pCSPInfo->TestCase);
HASH_INFO HashInfo;
memset(&HashInfo, 0, sizeof(HashInfo));
//
// Group 4B
//
//
// Do CryptDeriveKey positive test cases
//
LOG_TRY(CreateNewContext(
&hProv,
NULL,
CRYPT_VERIFYCONTEXT,
ptc));
//
// Tests for basic use of CryptDeriveKey, then the flags CRYPT_CREATE_SALT,
// CRYPT_NO_SALT, and
// CRYPT_UPDATE_KEY (the latter is currently not supported by the Microsoft
// CSP's) follow. Create a simple hash from which the derived keys will be
// generated.
//
HashInfo.aiHash = CALG_SHA1;
HashInfo.dbBaseData.pbData = (PBYTE) TEST_HASH_DATA;
HashInfo.dbBaseData.cbData = wcslen(TEST_HASH_DATA) * sizeof(WCHAR);
LOG_TRY(CreateHashAndAddData(
hProv,
&hHash,
&HashInfo,
ptc,
0, NULL));
//
// Base test
//
LOG_TRY(TDeriveKey(
hProv,
CALG_RC4,
hHash,
0,
&hKey,
ptc));
LOG_TRY(TDestroyKey(hKey, ptc));
hKey = 0;
//
// Test CRYPT_CREATE_SALT
//
// Derive a 40 bit RC4 key. Specifying a small key size is interesting
// because the Microsoft CSP's will not, by default, add any salt
// to a 128 bit key.
//
LOG_TRY(TDeriveKey(
hProv,
CALG_RC4,
hHash,
CRYPT_CREATE_SALT | (0x28 << 16),
&hKey,
ptc));
LOG_TRY(TDestroyKey(hKey, ptc));
hKey = 0;
//
// Test CRYPT_NO_SALT
//
LOG_TRY(TDeriveKey(
hProv,
CALG_RC4,
hHash,
CRYPT_NO_SALT | (0x28 << 16),
&hKey,
ptc));
LOG_TRY(TDestroyKey(hKey, ptc));
hKey = 0;
//
// Test CRYPT_UPDATE_KEY
//
LOG_TRY(TDeriveKey(
hProv,
CALG_RC4,
hHash,
0,
&hKey,
ptc));
//
// Using the key handle just created, attempt to update the key
// data with the same hash data. The Microsoft CSP currently ignores
// this flag.
//
LOG_TRY(TDeriveKey(
hProv,
CALG_RC4,
hHash,
CRYPT_UPDATE_KEY,
&hKey,
ptc));
fSuccess = TRUE;
Cleanup:
if (hHash)
{
TDestroyHash(hHash, ptc);
}
if (hKey)
{
TDestroyKey(hKey, ptc);
}
if (hProv)
{
TRelease(hProv, 0, ptc);
}
return fSuccess;
}
//
// Function: NegativeDeriveKeyTests
// Purpose: Run the negative test cases for CryptDeriveKey. These test cases
// will only execute for TEST_LEVEL_KEY, based on the dwTestLevel parameter.
//
BOOL NegativeDeriveKeyTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
//LPWSTR pwszContainer = TEST_CONTAINER;
//LPWSTR pwszContainer2 = TEST_CONTAINER_2;
HCRYPTPROV hProv = 0;
HCRYPTPROV hProv2 = 0;
HCRYPTKEY hKey = 0;
HCRYPTHASH hHash = 0;
HCRYPTHASH hHash2 = 0;
PTESTCASE ptc = &(pCSPInfo->TestCase);
//
// Group 4B
//
// Only run the negative test cases for TEST_LEVEL_KEY. This ensures that the same cases won't be
// re-run for TEST_LEVEL_CONTAINER. Only the positive cases are different.
if (TEST_LEVEL_KEY == ptc->dwTestLevel)
{
//
// Do CryptDeriveKey negative test cases
//
LOG_TRY(CreateNewContext(&hProv, NULL, CRYPT_VERIFYCONTEXT, ptc));
LOG_TRY(CreateNewHash(hProv, CALG_SHA1, &hHash, ptc));
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(TDeriveKey(0, CALG_RC4, hHash, 0, &hKey, ptc));
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(TDeriveKey(TEST_INVALID_HANDLE, CALG_RC4, hHash, 0, &hKey, ptc));
ptc->dwErrorCode = ERROR_INVALID_PARAMETER;
LOG_TRY(TDeriveKey(hProv, CALG_RC4, hHash, 0, NULL, ptc));
ptc->dwErrorCode = NTE_BAD_ALGID;
LOG_TRY(TDeriveKey(hProv, CALG_MD5, hHash, 0, &hKey, ptc));
ptc->dwErrorCode = NTE_BAD_FLAGS;
LOG_TRY(TDeriveKey(hProv, CALG_RC4, hHash, TEST_INVALID_FLAG, &hKey, ptc));
ptc->dwErrorCode = NTE_BAD_HASH;
LOG_TRY(TDeriveKey(hProv, CALG_RC4, TEST_INVALID_HANDLE, 0, &hKey, ptc));
ptc->dwErrorCode = NTE_SILENT_CONTEXT;
LOG_TRY(TDeriveKey(hProv, CALG_RC4, hHash, CRYPT_USER_PROTECTED, &hKey, ptc));
LOG_TRY(CreateNewContext(&hProv2, NULL, CRYPT_VERIFYCONTEXT, ptc));
LOG_TRY(CreateNewHash(hProv2, CALG_SHA1, &hHash2, ptc));
// Hash handle not created from same context as hProv
ptc->dwErrorCode = NTE_BAD_HASH;
LOG_TRY(TDeriveKey(hProv, CALG_RC4, hHash2, 0, &hKey, ptc));
}
fSuccess = TRUE;
Cleanup:
if (hHash)
{
TDestroyHash(hHash, ptc);
}
if (hHash2)
{
TDestroyHash(hHash2, ptc);
}
if (hProv)
{
TRelease(hProv, 0, ptc);
}
if (hProv2)
{
TRelease(hProv2, 0, ptc);
}
return fSuccess;
}
//
// Function: PositiveDestroyKeyTests
// Purpose: Run the test cases for CryptDestroyKey
//
BOOL PositiveDestroyKeyTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
LPWSTR pwszContainer = TEST_CONTAINER;
HCRYPTPROV hProv = 0;
HCRYPTKEY hKey = 0;
PTESTCASE ptc = &(pCSPInfo->TestCase);
//
// Group 4C
//
//
// Do CryptDestroyKey positive test cases
//
switch (pCSPInfo->TestCase.dwTestLevel)
{
case TEST_LEVEL_KEY:
{
LOG_TRY(CreateNewContext(&hProv, NULL, CRYPT_VERIFYCONTEXT, ptc));
LOG_TRY(CreateNewKey(hProv, CALG_RC4, 0, &hKey, ptc));
LOG_TRY(TDestroyKey(hKey, ptc));
hKey = 0;
break;
}
case TEST_LEVEL_CONTAINER:
{
LOG_TRY(CreateNewContext(&hProv, pwszContainer, CRYPT_NEWKEYSET, ptc));
LOG_TRY(CreateNewKey(hProv, AT_SIGNATURE, 0, &hKey, ptc));
LOG_TRY(TDestroyKey(hKey, ptc));
hKey = 0;
break;
}
default:
{
goto Cleanup;
}
}
fSuccess = TRUE;
Cleanup:
if (hKey)
{
TDestroyKey(hKey, ptc);
}
if (hProv)
{
TRelease(hProv, 0, ptc);
}
return fSuccess;
}
//
// Function: NegativeDestroyKeyTests
// Purpose: Run the negative test cases for CryptDestroyKey
//
BOOL NegativeDestroyKeyTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
//LPWSTR pwszContainer = TEST_CONTAINER;
HCRYPTPROV hProv = 0;
HCRYPTKEY hKey = 0;
PTESTCASE ptc = &(pCSPInfo->TestCase);
//
// Group 4C
//
//
// Do CryptDestroyKey negative test cases
//
ptc->fTestingDestroyKey = TRUE;
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(TDestroyKey(0, ptc));
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(TDestroyKey(TEST_INVALID_HANDLE, ptc));
LOG_TRY(CreateNewContext(&hProv, NULL, CRYPT_VERIFYCONTEXT, ptc));
LOG_TRY(CreateNewKey(hProv, CALG_RC4, 0, &hKey, ptc));
/*
LOG_TRY(TRelease(hProv, 0, ptc));
hProv = 0;
// Provider handle used to create hKey is now invalid
ptc->dwErrorCode = NTE_BAD_UID;
LOG_TRY(TDestroyKey(hKey, ptc));
*/
fSuccess = TRUE;
Cleanup:
ptc->fTestingDestroyKey = FALSE;
if (hKey)
{
TDestroyKey(hKey, ptc);
}
if (hProv)
{
TRelease(hProv, 0, ptc);
}
return fSuccess;
}
//
// Function: PositiveEncryptTests
// Purpose: Run the test cases for CryptEncrypt
//
BOOL PositiveEncryptTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
HCRYPTPROV hProv = 0;
HCRYPTKEY hKey = 0;
//LPWSTR pwszContainer = TEST_CONTAINER;
DWORD cbData = 0;
PBYTE pbData = NULL;
DWORD dw = 0;
PTESTCASE ptc = &(pCSPInfo->TestCase);
BYTE rgb [] = {
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
};
//
// Group 4E
//
//
// Do CryptEncrypt positive test cases
//
switch( pCSPInfo->TestCase.dwTestLevel )
{
case TEST_LEVEL_KEY:
{
LOG_TRY(CreateNewContext(&hProv, NULL, CRYPT_VERIFYCONTEXT, ptc));
//
// Try a simple stream cipher encryption
//
LOG_TRY(CreateNewKey(hProv, CALG_RC4, 0, &hKey, ptc));
cbData = wcslen(TEST_DECRYPT_DATA) * sizeof(WCHAR);
dw = cbData;
LOG_TRY(TestAlloc(&pbData, cbData, ptc));
memcpy(pbData, TEST_DECRYPT_DATA, cbData);
LOG_TRY(TEncrypt(hKey, 0, TRUE, 0, pbData, &cbData, dw, ptc));
//
// Verify that ciphertext is not same as plaintext
//
if (0 == memcmp(pbData, TEST_DECRYPT_DATA, dw))
{
ptc->pwszErrorHelp = L"CryptEncrypt ciphertext matches original plaintext";
LOG_TRY(LogApiFailure(
API_CRYPTENCRYPT,
ERROR_BAD_DATA,
ptc));
ptc->pwszErrorHelp = NULL;
}
LOG_TRY(TDestroyKey(hKey, ptc));
hKey = 0;
//
// Try a simple block cipher encryption
//
LOG_TRY(CreateNewKey(hProv, CALG_RC2, 0, &hKey, ptc));
cbData = sizeof(rgb) / 2;
dw = sizeof(rgb);
LOG_TRY(TEncrypt(hKey, 0, TRUE, 0, rgb, &cbData, dw, ptc));
//
// Verify that ciphertext is not still zeros
//
while (dw-- && (0 == rgb[dw - 1]));
if (0 == dw)
{
ptc->pwszErrorHelp = L"CryptEncrypt ciphertext matches original plaintext";
LOG_TRY(LogApiFailure(
API_CRYPTENCRYPT,
ERROR_BAD_DATA,
ptc));
ptc->pwszErrorHelp = NULL;
}
break;
}
case TEST_LEVEL_CONTAINER:
{
LOG_TRY(CreateNewContext(&hProv, NULL, CRYPT_NEWKEYSET, ptc));
//
// Test direct direct RSA encryption using an key-exchange public key.
//
// Not all CSP's will support this, so the error level may need to
// be adjusted.
//
LOG_TRY(CreateNewKey(hProv, AT_KEYEXCHANGE, 0, &hKey, ptc));
cbData = wcslen(TEST_DECRYPT_DATA) * sizeof(WCHAR);
dw = cbData;
LOG_TRY(TEncrypt(hKey, 0, TRUE, 0, NULL, &dw, 0, ptc));
LOG_TRY(TestAlloc(&pbData, dw, ptc));
memcpy(pbData, TEST_DECRYPT_DATA, cbData);
LOG_TRY(TEncrypt(hKey, 0, TRUE, 0, pbData, &cbData, dw, ptc));
//
// Verify that ciphertext is not same as plaintext
//
if (0 == memcmp(pbData, TEST_DECRYPT_DATA, dw))
{
ptc->pwszErrorHelp = L"CryptEncrypt ciphertext matches original plaintext";
LOG_TRY(LogApiFailure(
API_CRYPTENCRYPT,
ERROR_BAD_DATA,
ptc));
ptc->pwszErrorHelp = NULL;
}
break;
}
default:
{
goto Cleanup;
}
}
fSuccess = TRUE;
Cleanup:
if (hKey)
{
TDestroyKey(hKey, ptc);
}
if (hProv)
{
TRelease(hProv, 0, ptc);
}
return fSuccess;
}
//
// Function: NegativeEncryptTests
// Purpose: Run the negative test cases for CryptEncrypt
//
BOOL NegativeEncryptTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
//LPWSTR pwszContainer = TEST_CONTAINER;
//LPWSTR pwszContainer2 = TEST_CONTAINER_2;
HCRYPTPROV hProv = 0;
HCRYPTPROV hProv2 = 0;
HCRYPTKEY hKey = 0;
HCRYPTHASH hHash = 0;
DWORD cb = 0;
DWORD dw = 0;
PTESTCASE ptc = &(pCSPInfo->TestCase);
DWORD dwSavedErrorLevel = 0;
BYTE rgPlainText[TEST_CIPHER_LENGTH_RC4];
BYTE rgRC2PlainText[TEST_RC2_BUFFER_LEN];
BYTE rgHashVal[HASH_LENGTH_SHA1];
memset(rgHashVal, 0, sizeof(rgHashVal));
memset(rgPlainText, 0, sizeof(rgPlainText));
memset(rgRC2PlainText, 0, sizeof(rgRC2PlainText));
//
// Group 4E
//
//
// Do CryptEncrypt negative test cases
//
cb = sizeof(rgPlainText);
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(TEncrypt(0, 0, TRUE, 0, rgPlainText, &cb, cb, ptc));
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(TEncrypt(TEST_INVALID_HANDLE, 0, TRUE, 0, rgPlainText, &cb, cb, ptc));
LOG_TRY(CreateNewContext(&hProv, NULL, CRYPT_VERIFYCONTEXT, ptc));
//
// Create a block encryption key to test invalid buffer
// lengths.
//
LOG_TRY(CreateNewKey(hProv, CALG_RC2, 0, &hKey, ptc));
dw = cb = TEST_RC2_DATA_LEN;
ptc->fExpectSuccess = TRUE;
LOG_TRY(TEncrypt(hKey, 0, TRUE, 0, NULL, &cb, 0, ptc));
ptc->fExpectSuccess = FALSE;
cb--;
// dwBufLen param is now too short
ptc->dwErrorCode = ERROR_MORE_DATA;
LOG_TRY(TEncrypt(hKey, 0, TRUE, 0, rgRC2PlainText, &dw, cb, ptc));
// Done with block cipher key
LOG_TRY(TDestroyKey(hKey, ptc));
hKey = 0;
//
// Continue tests using a stream cipher key
//
cb = sizeof(rgPlainText);
LOG_TRY(CreateNewKey(hProv, CALG_RC4, 0, &hKey, ptc));
// pbData buffer is too short and will AV
ptc->dwErrorCode = ERROR_INVALID_PARAMETER;
LOG_TRY(TEncrypt(hKey, 0, TRUE, 0, (PBYTE) TEST_INVALID_POINTER, &cb, cb, ptc));
// Invalid flag
ptc->dwErrorCode = NTE_BAD_FLAGS;
LOG_TRY(TEncrypt(hKey, 0, TRUE, TEST_INVALID_FLAG, rgPlainText, &cb, cb, ptc));
ptc->fExpectSuccess = TRUE;
LOG_TRY(TEncrypt(hKey, 0, TRUE, 0, rgPlainText, &cb, cb, ptc));
ptc->fExpectSuccess = FALSE;
// Not all providers prohibit double-encryption
dwSavedErrorLevel = ptc->dwErrorLevel;
ptc->dwErrorLevel = CSP_ERROR_WARNING;
ptc->pwszErrorHelp = L"This CSP supports double-encryption";
ptc->dwErrorCode = NTE_DOUBLE_ENCRYPT;
LOG_TRY(TEncrypt(hKey, 0, TRUE, 0, rgPlainText, &cb, cb, ptc));
ptc->dwErrorLevel = dwSavedErrorLevel;
ptc->pwszErrorHelp = NULL;
memset(rgPlainText, 0, cb);
// Invalid, non-zero, hash handle
ptc->dwErrorCode = NTE_BAD_HASH;
LOG_TRY(TEncrypt(hKey, TEST_INVALID_HANDLE, TRUE, 0, rgPlainText, &cb, cb, ptc));
LOG_TRY(CreateNewHash(hProv, CALG_SHA1, &hHash, ptc));
ptc->fExpectSuccess = TRUE;
cb = sizeof(rgHashVal);
LOG_TRY(TGetHash(hHash, HP_HASHVAL, rgHashVal, &cb, 0, ptc));
ptc->fExpectSuccess = FALSE;
cb = sizeof(rgPlainText);
ptc->dwErrorCode = NTE_BAD_HASH_STATE;
LOG_TRY(TEncrypt(hKey, hHash, TRUE, 0, rgPlainText, &cb, cb, ptc));
TDestroyHash(hHash, ptc);
hHash = 0;
LOG_TRY(CreateNewContext(&hProv2, NULL, CRYPT_VERIFYCONTEXT, ptc));
// Create a new hash from a different cryptographic context
LOG_TRY(CreateNewHash(hProv2, CALG_SHA1, &hHash, ptc));
// API should not allow hKey and hHash from two different contexts
ptc->dwErrorCode = NTE_BAD_HASH;
LOG_TRY(TEncrypt(hKey, hHash, TRUE, 0, rgPlainText, &cb, cb, ptc));
// Delete the original context, hKey derived from it should now be unusable
/*
LOG_TRY(TRelease(hProv, 0, ptc));
hProv = 0;
ptc->dwErrorCode = NTE_BAD_UID;
LOG_TRY(TEncrypt(hKey, 0, TRUE, 0, rgPlainText, &cb, cb, ptc));
*/
fSuccess = TRUE;
Cleanup:
if (hHash)
{
TDestroyHash(hHash, ptc);
}
if (hKey)
{
TDestroyKey(hKey, ptc);
}
if (hProv)
{
TRelease(hProv, 0, ptc);
}
if (hProv2)
{
TRelease(hProv2, 0, ptc);
}
return fSuccess;
}
//
// Function: TestGenKeyProc
//
BOOL TestGenKeyProc(
PALGNODE pAlgNode,
PTESTCASE ptc,
PVOID pvTestGenKeyInfo)
{
HCRYPTKEY hKey = 0;
BOOL fSuccess = FALSE;
DWORD dwSize = 0;
DWORD dwFlags = 0;
HCRYPTPROV hTestProv = 0;
DWORD dwSavedErrorLevel = ptc->dwErrorLevel;
PTEST_GEN_KEY_INFO pTestGenKeyInfo = (PTEST_GEN_KEY_INFO) pvTestGenKeyInfo;
if (pAlgNode->fIsRequiredAlg)
{
ptc->dwErrorLevel = CSP_ERROR_CONTINUE;
}
else
{
ptc->dwErrorLevel = CSP_ERROR_WARNING;
}
//
// Create four different keys for the specified alg:
//
// 1) Minimum key size, with the CRYPT_NO_SALT flag.
// 2) Minimum key size, with the CRYPT_CREATE_SALT flag.
// 3) (Public keys only) Minimum key size + incremental key size
// 4) Default key size, with the CRYPT_EXPORTABLE flag
// 5) Maximum key size (Session keys only. Otherwise, use a
// reasonably large key size for public key pairs.), with the
// CRYPT_USER_PROTECTED flag set.
//
// 1
dwSize = pAlgNode->ProvEnumalgsEx.dwMinLen;
LOG_TRY(TGenKey(
pTestGenKeyInfo->hProv,
pAlgNode->ProvEnumalgsEx.aiAlgid,
CRYPT_NO_SALT | (dwSize << 16),
&hKey,
ptc));
LOG_TRY(TDestroyKey(hKey, ptc));
hKey = 0;
//
// The Microsoft CSP's do not permit salting DES
// keys.
//
// 2
if ( CALG_DES == pAlgNode->ProvEnumalgsEx.aiAlgid ||
CALG_3DES == pAlgNode->ProvEnumalgsEx.aiAlgid ||
CALG_3DES_112 == pAlgNode->ProvEnumalgsEx.aiAlgid)
{
ptc->KnownErrorID = KNOWN_CRYPTGENKEY_SALTDES;
}
LOG_TRY(TGenKey(
pTestGenKeyInfo->hProv,
pAlgNode->ProvEnumalgsEx.aiAlgid,
CRYPT_CREATE_SALT | (dwSize << 16),
&hKey,
ptc));
LOG_TRY(TDestroyKey(hKey, ptc));
hKey = 0;
ptc->KnownErrorID = KNOWN_ERROR_UNKNOWN;
//
// Is this a public key alg?
//
if (RSAAlgFilter(pAlgNode))
{
switch (pAlgNode->ProvEnumalgsEx.aiAlgid)
{
case CALG_RSA_SIGN:
{
dwSize = pAlgNode->ProvEnumalgsEx.dwMinLen + pTestGenKeyInfo->pCSPInfo->dwSigKeysizeInc;
break;
}
case CALG_RSA_KEYX:
{
dwSize = pAlgNode->ProvEnumalgsEx.dwMinLen + pTestGenKeyInfo->pCSPInfo->dwSigKeysizeInc;
break;
}
default:
{
goto Cleanup;
}
}
// 3
LOG_TRY(TGenKey(
pTestGenKeyInfo->hProv,
pAlgNode->ProvEnumalgsEx.aiAlgid,
dwSize << 16,
&hKey,
ptc));
LOG_TRY(TDestroyKey(hKey, ptc));
hKey = 0;
}
// 4
LOG_TRY(TGenKey(
pTestGenKeyInfo->hProv,
pAlgNode->ProvEnumalgsEx.aiAlgid,
CRYPT_EXPORTABLE,
&hKey,
ptc));
LOG_TRY(TDestroyKey(hKey, ptc));
hKey = 0;
// 5
if (RSAAlgFilter(pAlgNode))
{
dwFlags = CRYPT_USER_PROTECTED;
dwSize = (pAlgNode->ProvEnumalgsEx.dwMaxLen >= TEST_MAX_RSA_KEYSIZE) ? TEST_MAX_RSA_KEYSIZE : pAlgNode->ProvEnumalgsEx.dwMaxLen;
hTestProv = pTestGenKeyInfo->hNotSilentProv;
}
else
{
dwSize = pAlgNode->ProvEnumalgsEx.dwMaxLen;
hTestProv = pTestGenKeyInfo->hProv;
}
LOG_TRY(TGenKey(
hTestProv,
pAlgNode->ProvEnumalgsEx.aiAlgid,
dwFlags | (dwSize << 16),
&hKey,
ptc));
fSuccess = TRUE;
Cleanup:
ptc->dwErrorLevel = dwSavedErrorLevel;
if (hKey)
{
TDestroyKey(hKey, ptc);
}
return fSuccess;
}
//
// Function: PositiveGenKeyTests
// Purpose: Run the test cases for CryptGenKey. The set of positive
// test cases executed depends on the dwCSPClass and dwTestLevel parameters.
//
BOOL PositiveGenKeyTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
LPWSTR pwszContainer = TEST_CONTAINER;
LPWSTR pwszContainer2 = TEST_CONTAINER_2;
PTESTCASE ptc = &(pCSPInfo->TestCase);
HCRYPTKEY hKey = 0;
//PALGNODE pAlgNode = NULL;
TEST_GEN_KEY_INFO TestGenKeyInfo;
memset(&TestGenKeyInfo, 0, sizeof(TestGenKeyInfo));
TestGenKeyInfo.pCSPInfo = pCSPInfo;
//
// Do CryptGenKey positive test cases
//
switch (pCSPInfo->TestCase.dwTestLevel)
{
case TEST_LEVEL_KEY:
{
//
// Run the TestGenKeyProc test for each session key alg
// supported by this CSP.
//
LOG_TRY(CreateNewContext(&(TestGenKeyInfo.hProv), NULL, CRYPT_VERIFYCONTEXT, ptc));
LOG_TRY(AlgListIterate(
pCSPInfo->pAlgList,
DataEncryptFilter,
TestGenKeyProc,
(PVOID) &TestGenKeyInfo,
ptc));
//
// Test that a signature public key pair can be created from a
// VERIFYCONTEXT provider handle. The key will not be persisted.
//
LOG_TRY(TGenKey(
TestGenKeyInfo.hProv,
AT_SIGNATURE,
0,
&hKey,
ptc));
break;
}
case TEST_LEVEL_CONTAINER:
{
LOG_TRY(CreateNewContext(
&(TestGenKeyInfo.hProv),
pwszContainer,
CRYPT_NEWKEYSET,
ptc));
// We are not currently supporting multiple containers
// on a single smartcard, so the following test case can't
// use two different context handles for Smartcard scenario.
if (pCSPInfo->fSmartCardCSP)
{
TestGenKeyInfo.hNotSilentProv = TestGenKeyInfo.hProv;
}
else
{
//
// Set the flag so that CreateNewContext will not create a CRYPT_SILENT context
// handle.
//
ptc->fTestingUserProtected = TRUE;
LOG_TRY(CreateNewContext(
&(TestGenKeyInfo.hNotSilentProv),
pwszContainer2,
CRYPT_NEWKEYSET,
ptc));
ptc->fTestingUserProtected = FALSE;
}
if (CLASS_SIG_ONLY == pCSPInfo->TestCase.dwCSPClass)
{
LOG_TRY(TGenKey(
TestGenKeyInfo.hProv,
AT_SIGNATURE,
0,
&hKey,
ptc));
}
else
{
LOG_TRY(TGenKey(
TestGenKeyInfo.hProv,
AT_KEYEXCHANGE,
0,
&hKey,
ptc));
LOG_TRY(AlgListIterate(
pCSPInfo->pAlgList,
RSAAlgFilter,
TestGenKeyProc,
(PVOID) &TestGenKeyInfo,
ptc));
}
if (pCSPInfo->fSmartCardCSP)
{
TestGenKeyInfo.hProv = 0;
}
break;
}
default:
{
goto Cleanup;
}
}
fSuccess = TRUE;
Cleanup:
if (hKey)
{
TDestroyKey(hKey, ptc);
}
if (TestGenKeyInfo.hProv)
{
TRelease(TestGenKeyInfo.hProv, 0, ptc);
}
if (TestGenKeyInfo.hNotSilentProv)
{
TRelease(TestGenKeyInfo.hNotSilentProv, 0, ptc);
}
return fSuccess;
}
//
// Function: NegativeGenKeyTests
// Purpose: Run the negative test cases for CryptGenKey. The set of
// test cases executed depends on the dwTestLevel parameter.
//
BOOL NegativeGenKeyTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
LPWSTR pwszContainer = TEST_CONTAINER;
HCRYPTPROV hProv = 0;
HCRYPTKEY hKey = 0;
PTESTCASE ptc = &(pCSPInfo->TestCase);
// The appropriate set of negative test cases to run depends on the current Test Level
switch (ptc->dwTestLevel)
{
case TEST_LEVEL_KEY:
{
//
// Group 4F (negative)
//
//
// Do CryptGenKey TEST_LEVEL_KEY negative test cases
//
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(TGenKey(0, CALG_RC4, 0, &hKey, ptc));
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(TGenKey(TEST_INVALID_HANDLE, CALG_RC4, 0, &hKey, ptc));
LOG_TRY(CreateNewContext(&hProv, NULL, CRYPT_VERIFYCONTEXT, ptc));
ptc->dwErrorCode = NTE_BAD_ALGID;
LOG_TRY(TGenKey(hProv, CALG_SHA1, 0, &hKey, ptc));
ptc->dwErrorCode = NTE_BAD_FLAGS;
LOG_TRY(TGenKey(hProv, CALG_RC4, TEST_INVALID_FLAG, &hKey, ptc));
break;
}
case TEST_LEVEL_CONTAINER:
{
//
// Group 5D (negative)
//
//
// Do CryptGenKey TEST_LEVEL_CONTAINER negative test cases
//
//
// Test that CRYPT_USER_PROTECTED fails with a CRYPT_SILENT context
//
LOG_TRY(CreateNewContext(&hProv, pwszContainer, CRYPT_NEWKEYSET | CRYPT_SILENT, ptc));
ptc->dwErrorCode = NTE_SILENT_CONTEXT;
LOG_TRY(TGenKey(hProv, AT_SIGNATURE, CRYPT_USER_PROTECTED, &hKey, ptc));
LOG_TRY(TRelease(hProv, 0, ptc));
hProv = 0;
//
// Test that CRYPT_USER_PROTECTED fails with a CRYPT_VERIFYCONTEXT context
//
LOG_TRY(CreateNewContext(&hProv, NULL, CRYPT_VERIFYCONTEXT, ptc));
//
// In Windows 2000, the Microsoft CSP's ignore the USER_PROTECTED flag
// because the VERIFYCONTEXT flag is set. Therefore the following
// call succeeds unexpectedly. That usage should be flagged as an
// error.
//
ptc->KnownErrorID = KNOWN_CRYPTGENKEY_SILENTCONTEXT;
ptc->pwszErrorHelp =
L"The CRYPT_USER_PROTECTED flag should fail when a VERIFYCONTEXT provider handle is used";
ptc->dwErrorCode = NTE_SILENT_CONTEXT;
LOG_TRY(TGenKey(hProv, AT_SIGNATURE, CRYPT_USER_PROTECTED, &hKey, ptc));
ptc->KnownErrorID = KNOWN_ERROR_UNKNOWN;
break;
}
}
fSuccess = TRUE;
Cleanup:
if (hKey)
{
TDestroyKey(hKey, ptc);
}
if (hProv)
{
TRelease(hProv, 0, ptc);
}
return fSuccess;
}
//
// Function: PositiveGetKeyParamTests
// Purpose: Run the test cases for CryptGetKeyParam
//
BOOL PositiveGetKeyParamTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
HCRYPTPROV hProv = 0;
HCRYPTKEY hKey = 0;
DWORD dw = 0;
DWORD cb = 0;
PBYTE pb = NULL;
PTESTCASE ptc = &(pCSPInfo->TestCase);
DWORD dwSavedErrorLevel = 0;
//
// Group 4G
//
//
// Do CryptGetKeyParam positive test cases
//
LOG_TRY(CreateNewContext(&hProv, NULL, CRYPT_VERIFYCONTEXT, ptc));
//
// Test CryptGetKeyParam for a stream cipher key
//
LOG_TRY(CreateNewKey(
hProv,
CALG_RC4,
CRYPT_CREATE_SALT | CRYPT_EXPORTABLE | (40 << 16),
&hKey,
ptc));
// KP_ALGID
cb = sizeof(dw);
LOG_TRY(TGetKey(
hKey,
KP_ALGID,
(PBYTE) &dw,
&cb,
0,
ptc));
if (CALG_RC4 != dw)
{
LOG_TRY(LogBadParam(
API_CRYPTGETKEYPARAM,
L"CryptGetKeyParam KP_ALGID doesn't match",
ptc));
}
// KP_BLOCKLEN
cb = sizeof(dw);
LOG_TRY(TGetKey(
hKey,
KP_BLOCKLEN,
(PBYTE) &dw,
&cb,
0,
ptc));
if (0 != dw)
{
LOG_TRY(LogBadParam(
API_CRYPTGETKEYPARAM,
L"CryptGetKeyParam KP_BLOCKLEN should be zero",
ptc));
}
// KP_KEYLEN
cb = sizeof(dw);
LOG_TRY(TGetKey(
hKey,
KP_KEYLEN,
(PBYTE) &dw,
&cb,
0,
ptc));
// TODO: Determine the best way to verify KP_KEYLEN. CSP's will return
// the effective KEYLEN, including parity bits.
// KP_SALT
cb = 0;
LOG_TRY(TGetKey(
hKey,
KP_SALT,
NULL,
&cb,
0,
ptc));
//
// The MS_ENHANCED_PROV will use salt length zero for any key size even
// when CRYPT_CREATE_SALT has been specified.
//
// The MS_BASE_PROV will exhibit one of the following behaviors:
// 1) Default - use 11 bytes of zeroed salt
// 2) CRYPT_CREATE_SALT - use 11 bytes of random salt
// 3) CRYPT_NO_SALT - use no salt
//
// For this reason, various valid-looking salting behaviors
// should not be considered errors.
//
dwSavedErrorLevel = ptc->dwErrorLevel;
ptc->dwErrorLevel = CSP_ERROR_WARNING;
if (0 == cb)
{
LOG_TRY(LogBadParam(
API_CRYPTGETKEYPARAM,
L"CryptGetKeyParam KP_SALT has zero length after CryptGenKey CRYPT_CREATE_SALT",
ptc));
}
LOG_TRY(TestAlloc(&pb, cb, ptc));
LOG_TRY(TGetKey(
hKey,
KP_SALT,
pb,
&cb,
0,
ptc));
// Verify that salt is not completely zero
while (cb && (0 == pb[cb - 1]))
cb--;
if (0 == cb)
{
LOG_TRY(LogBadParam(
API_CRYPTGETKEYPARAM,
L"CryptGetKeyParam KP_SALT should not be zeroized after CryptGenKey CRYPT_CREATE_SALT",
ptc));
}
free(pb);
pb = NULL;
ptc->dwErrorLevel = dwSavedErrorLevel;
// KP_PERMISSIONS
cb = sizeof(dw);
LOG_TRY(TGetKey(
hKey,
KP_PERMISSIONS,
(PBYTE) &dw,
&cb,
0,
ptc));
if (! (CRYPT_EXPORT & dw))
{
LOG_TRY(LogBadParam(
API_CRYPTGETKEYPARAM,
L"CryptGetKeyParam KP_PERMISSIONS, CRYPT_EXPORT should be set",
ptc));
}
LOG_TRY(TDestroyKey(hKey, ptc));
hKey = 0;
//
// Test CryptGetKeyParam with a block cipher key
//
LOG_TRY(CreateNewKey(hProv, CALG_RC2, CRYPT_EXPORTABLE, &hKey, ptc));
// KP_BLOCKLEN
cb = sizeof(dw);
LOG_TRY(TGetKey(
hKey,
KP_BLOCKLEN,
(PBYTE) &dw,
&cb,
0,
ptc));
if (0 == dw)
{
LOG_TRY(LogBadParam(
API_CRYPTGETKEYPARAM,
L"CryptGetKeyParam KP_BLOCKLEN should not be zero for CALG_RC2 key",
ptc));
}
// KP_EFFECTIVE_KEYLEN
cb = sizeof(dw);
LOG_TRY(TGetKey(
hKey,
KP_EFFECTIVE_KEYLEN,
(PBYTE) &dw,
&cb,
0,
ptc));
// TODO: In general, how should the effective key length
// be determined?
// KP_IV
cb = 0;
LOG_TRY(TGetKey(
hKey,
KP_IV,
NULL,
&cb,
0,
ptc));
LOG_TRY(TestAlloc(&pb, cb, ptc));
LOG_TRY(TGetKey(
hKey,
KP_IV,
pb,
&cb,
0,
ptc));
// Verify that IV is zero
while (cb && (! pb[cb - 1]))
cb--;
if (0 != cb)
{
LOG_TRY(LogBadParam(
API_CRYPTGETKEYPARAM,
L"CryptGetKeyParam KP_IV should be zero",
ptc));
}
free(pb);
pb = NULL;
// KP_PADDING
cb = sizeof(dw);
LOG_TRY(TGetKey(
hKey,
KP_PADDING,
(PBYTE) &dw,
&cb,
0,
ptc));
if (PKCS5_PADDING != dw)
{
LOG_TRY(LogBadParam(
API_CRYPTGETKEYPARAM,
L"CryptGetKeyParam KP_PADDING should be PKCS5_PADDING",
ptc));
}
// KP_MODE
cb = sizeof(dw);
LOG_TRY(TGetKey(
hKey,
KP_MODE,
(PBYTE) &dw,
&cb,
0,
ptc));
if (CRYPT_MODE_CBC != dw)
{
LOG_TRY(LogBadParam(
API_CRYPTGETKEYPARAM,
L"CryptGetKeyParam KP_MODE should be CRYPT_MODE_CBC",
ptc));
}
// KP_MODE_BITS
cb = sizeof(dw);
LOG_TRY(TGetKey(
hKey,
KP_MODE_BITS,
(PBYTE) &dw,
&cb,
0,
ptc));
// TODO: Looks like this should always be initialized to zero. Is that true?
if (0 != dw)
{
LOG_TRY(LogBadParam(
API_CRYPTGETKEYPARAM,
L"CryptGetKeyParam KP_MODE_BITS should be zero",
ptc));
}
fSuccess = TRUE;
Cleanup:
if (pb)
{
free(pb);
}
if (hKey)
{
TDestroyKey(hKey, ptc);
}
if (hProv)
{
TRelease(hProv, 0, ptc);
}
return fSuccess;
}
//
// Function: NegativeGetKeyParamTests
// Purpose: Run the negative test cases for CryptGetKeyParam
//
BOOL NegativeGetKeyParamTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
//LPWSTR pwszContainer = TEST_CONTAINER;
HCRYPTPROV hProv = 0;
HCRYPTKEY hKey = 0;
DWORD dw = 0;
DWORD cb = 0;
PTESTCASE ptc = &(pCSPInfo->TestCase);
//
// Group 4G
//
//
// Do CryptGetKeyParam negative test cases
//
cb = sizeof(dw);
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(TGetKey(0, KP_KEYLEN, (PBYTE) &dw, &cb, 0, ptc));
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(TGetKey(TEST_INVALID_HANDLE, KP_KEYLEN, (PBYTE) &dw, &cb, 0, ptc));
LOG_TRY(CreateNewContext(&hProv, NULL, CRYPT_VERIFYCONTEXT, ptc));
LOG_TRY(CreateNewKey(hProv, CALG_RC4, 0, &hKey, ptc));
/*
ptc->dwErrorCode = ERROR_INVALID_PARAMETER;
LOG_TRY(TGetKey(hKey, KP_KEYLEN, NULL, &cb, 0, ptc));
*/
ptc->dwErrorCode = ERROR_INVALID_PARAMETER;
LOG_TRY(TGetKey(hKey, KP_KEYLEN, (PBYTE) TEST_INVALID_POINTER, NULL, 0, ptc));
cb = 1;
ptc->dwErrorCode = ERROR_MORE_DATA;
LOG_TRY(TGetKey(hKey, KP_KEYLEN, (PBYTE) &dw, &cb, 0, ptc));
ptc->dwErrorCode = NTE_BAD_FLAGS;
LOG_TRY(TGetKey(hKey, KP_KEYLEN, (PBYTE) &dw, &cb, TEST_INVALID_FLAG, ptc));
ptc->dwErrorCode = NTE_BAD_TYPE;
LOG_TRY(TGetKey(hKey, TEST_INVALID_FLAG, (PBYTE) &dw, &cb, 0, ptc));
/*
LOG_TRY(TRelease(hProv, 0, ptc));
hProv = 0;
// Provider handle used to create hKey is now invalid
ptc->dwErrorCode = NTE_BAD_UID;
LOG_TRY(TGetKey(hKey, KP_KEYLEN, (PBYTE) &dw, &cb, 0, ptc));
*/
fSuccess = TRUE;
Cleanup:
if (hKey)
{
TDestroyKey(hKey, ptc);
}
if (hProv)
{
TRelease(hProv, 0, ptc);
}
return fSuccess;
}
//
// Function: TestHashSessionKeyProc
// Purpose: Callback function for testing CryptHashSessionKey
// using AlgListIterate. For each session key algorithm
// supported by the target CSP, this function will be called.
//
BOOL TestHashSessionKeyProc(
PALGNODE pAlgNode,
PTESTCASE ptc,
PVOID pvTestHashSessionKey)
{
BOOL fSuccess = FALSE;
DWORD dwFlags = 0;
HASH_SESSION_INFO HashSessionInfo;
PTEST_HASH_SESSION_KEY pTestHashSessionKey = (PTEST_HASH_SESSION_KEY) pvTestHashSessionKey;
//
// Run the HashSessionKey scenario twice:
// 1) dwFlags = 0 --> hash is Big Endian
// 2) dwFlags = CRYPT_LITTLE_ENDIAN
//
while (TEST_INVALID_FLAG != dwFlags)
{
memset(&HashSessionInfo, 0, sizeof(HashSessionInfo));
HashSessionInfo.aiHash = pTestHashSessionKey->aiHash;
HashSessionInfo.aiKey = pAlgNode->ProvEnumalgsEx.aiAlgid;
HashSessionInfo.dwKeySize = pAlgNode->ProvEnumalgsEx.dwMaxLen;
HashSessionInfo.dwFlags = dwFlags;
LOG_TRY(CreateHashedSessionKey(
pTestHashSessionKey->hProv,
&HashSessionInfo,
ptc));
LOG_TRY(VerifyHashedSessionKey(
pTestHashSessionKey->hInteropProv,
&HashSessionInfo,
ptc));
if (CRYPT_LITTLE_ENDIAN == dwFlags)
{
dwFlags = TEST_INVALID_FLAG;
}
else
{
dwFlags = CRYPT_LITTLE_ENDIAN;
}
}
fSuccess = TRUE;
Cleanup:
return fSuccess;
}
//
// Function: InteropHashSessionKeyTests
// Purpose: Run the interoperability test cases for CryptHashSessionKey
// between the CSP under test and a second CSP.
//
BOOL InteropHashSessionKeyTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
//LPWSTR pwszContainer = TEST_CONTAINER;
PTESTCASE ptc = &(pCSPInfo->TestCase);
TEST_HASH_SESSION_KEY TestHashSessionKey;
memset(&TestHashSessionKey, 0, sizeof(TestHashSessionKey));
TestHashSessionKey.aiHash = CALG_SHA1;
LOG_TRY(CreateNewContext(
&(TestHashSessionKey.hProv),
NULL,
CRYPT_VERIFYCONTEXT,
ptc));
LOG_TRY(CreateNewInteropContext(
&(TestHashSessionKey.hInteropProv),
NULL,
CRYPT_VERIFYCONTEXT,
ptc));
LOG_TRY(AlgListIterate(
pCSPInfo->pAlgList,
DataEncryptFilter,
TestHashSessionKeyProc,
(PVOID) &TestHashSessionKey,
ptc));
fSuccess = TRUE;
Cleanup:
if (TestHashSessionKey.hProv)
{
TRelease(TestHashSessionKey.hProv, 0, ptc);
}
if (TestHashSessionKey.hInteropProv)
{
TRelease(TestHashSessionKey.hInteropProv, 0, ptc);
}
return fSuccess;
}
//
// Function: PositiveHashSessionKeyTests
// Purpose: Run the test cases for CryptHashSessionKey
//
BOOL PositiveHashSessionKeyTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
//LPWSTR pwszContainer = TEST_CONTAINER;
HCRYPTPROV hProv = 0;
HCRYPTKEY hKey = 0;
HCRYPTHASH hHash = 0;
PTESTCASE ptc = &(pCSPInfo->TestCase);
LOG_TRY(CreateNewContext(
&hProv,
NULL,
CRYPT_VERIFYCONTEXT,
ptc));
//
// Group 4H
//
//
// Do CryptHashSessionKey test cases
//
//
// Hash a stream cipher key
//
LOG_TRY(CreateNewHash(hProv, CALG_SHA1, &hHash, ptc));
LOG_TRY(CreateNewKey(hProv, CALG_RC4, 0, &hKey, ptc));
LOG_TRY(THashSession(hHash, hKey, 0, ptc));
//
// Hash the key again with the CRYPT_LITTLE_ENDIAN flag
//
LOG_TRY(THashSession(hHash, hKey, CRYPT_LITTLE_ENDIAN, ptc));
fSuccess = TRUE;
Cleanup:
if (hKey)
{
TDestroyKey(hKey, ptc);
}
if (hHash)
{
TDestroyHash(hHash, ptc);
}
if (hProv)
{
TRelease(hProv, 0, ptc);
}
return fSuccess;
}
//
// Function: NegativeHashSessionKeyTests
// Purpose: Run the negative test cases for CryptHashSessionKey
//
BOOL NegativeHashSessionKeyTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
//LPWSTR pwszContainer = TEST_CONTAINER;
HCRYPTPROV hProv = 0;
HCRYPTKEY hKey = 0;
HCRYPTKEY hHash = 0;
DWORD cb = 0;
BYTE rgHashVal[HASH_LENGTH_SHA1];
PTESTCASE ptc = &(pCSPInfo->TestCase);
//
// Group 4H
//
//
// Do CryptHashSessionKey negative test cases
//
LOG_TRY(CreateNewContext(&hProv, NULL, CRYPT_VERIFYCONTEXT, ptc));
LOG_TRY(CreateNewKey(hProv, CALG_RC4, 0, &hKey, ptc));
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(THashSession(0, hKey, 0, ptc));
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(THashSession(TEST_INVALID_HANDLE, hKey, 0, ptc));
LOG_TRY(CreateNewHash(hProv, CALG_SHA1, &hHash, ptc));
ptc->dwErrorCode = NTE_BAD_FLAGS;
LOG_TRY(THashSession(hHash, hKey, TEST_INVALID_FLAG, ptc));
ptc->dwErrorCode = NTE_BAD_KEY;
LOG_TRY(THashSession(hHash, TEST_INVALID_HANDLE, 0, ptc));
cb = sizeof(rgHashVal);
LOG_TRY(TGetHash(hHash, HP_HASHVAL, rgHashVal, &cb, 0, ptc));
// Hash is now finished, so any attempt to hash data should fail
ptc->dwErrorCode = NTE_BAD_HASH_STATE;
LOG_TRY(THashSession(hHash, hKey, 0, ptc));
/*
LOG_TRY(TRelease(hProv, 0, ptc));
hProv = 0;
// Provider handle used to create hHash is now invalid
ptc->dwErrorCode = NTE_BAD_UID;
LOG_TRY(THashSession(hHash, hKey, 0, ptc));
*/
fSuccess = TRUE;
Cleanup:
if (hKey)
{
TDestroyKey(hKey, ptc);
}
if (hHash)
{
TDestroyHash(hHash, ptc);
}
if (hProv)
{
TRelease(hProv, 0, ptc);
}
return fSuccess;
}
//
// Function: PositiveSetKeyParamTests
// Purpose: Run the test cases for CryptSetKeyParam
//
BOOL PositiveSetKeyParamTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
//LPWSTR pwszContainer = TEST_CONTAINER;
HCRYPTPROV hProv = 0;
HCRYPTKEY hKey = 0;
PBYTE pbData = NULL;
DWORD cbData = 0;
DWORD dw = 0;
PTESTCASE ptc = &(pCSPInfo->TestCase);
DATA_BLOB db;
memset(&db, 0, sizeof(db));
LOG_TRY(CreateNewContext(
&hProv,
NULL,
CRYPT_VERIFYCONTEXT,
ptc));
//
// Create a block cipher key for testing SetKeyParam
//
LOG_TRY(CreateNewKey(hProv, CALG_RC2, (40 << 16) | CRYPT_CREATE_SALT, &hKey, ptc));
//
// Group 4I
//
//
// Do CryptSetKeyParam test cases
//
//
// Test KP_SALT
//
LOG_TRY(TGetKey(hKey, KP_SALT, NULL, &cbData, 0, ptc));
LOG_TRY(TestAlloc(&pbData, cbData, ptc));
memset(pbData, TEST_SALT_BYTE, cbData);
// Set key's salt to a known value
LOG_TRY(TSetKey(hKey, KP_SALT, pbData, 0, ptc));
// Retrieve the salt value from the CSP for verification
LOG_TRY(TGetKey(hKey, KP_SALT, pbData, &cbData, 0, ptc));
while (cbData && (pbData[cbData - 1] == TEST_SALT_BYTE))
{
cbData--;
}
if (0 != cbData)
{
LOG_TRY(LogBadParam(
API_CRYPTSETKEYPARAM,
L"CryptSetKeyParam KP_SALT bytes have incorrect value",
ptc));
}
free(pbData);
pbData = NULL;
//
// Test KP_SALT_EX
//
db.cbData = TEST_SALT_LEN;
LOG_TRY(TestAlloc(&(db.pbData), TEST_SALT_LEN, ptc));
memset(db.pbData, TEST_SALT_BYTE, TEST_SALT_LEN);
LOG_TRY(TSetKey(hKey, KP_SALT_EX, (PBYTE) &db, 0, ptc));
// TODO: Not sure how to verify KP_SALT_EX values
//
// Test KP_PERMISSIONS
//
dw = CRYPT_EXPORT;
//
// The Microsoft CSP's do not allow the exportability of a key
// to be changed.
//
ptc->KnownErrorID = KNOWN_CRYPTSETKEYPARAM_EXPORT;
ptc->pwszErrorHelp = L"Attempt to change key to exportable";
LOG_TRY(TSetKey(hKey, KP_PERMISSIONS, (PBYTE) &dw, 0, ptc));
ptc->pwszErrorHelp = NULL;
dw = 0;
cbData = sizeof(dw);
LOG_TRY(TGetKey(hKey, KP_PERMISSIONS, (PBYTE) &dw, &cbData, 0, ptc));
if (! (CRYPT_EXPORT & dw))
{
LOG_TRY(LogBadParam(
API_CRYPTSETKEYPARAM,
L"CryptGetKeyParam KP_PERMISSIONS should now include CRYPT_EXPORT",
ptc));
}
ptc->KnownErrorID = KNOWN_ERROR_UNKNOWN;
//
// Test KP_EFFECTIVE_KEYLEN
//
dw = TEST_EFFECTIVE_KEYLEN;
LOG_TRY(TSetKey(hKey, KP_EFFECTIVE_KEYLEN, (PBYTE) &dw, 0, ptc));
dw = 0;
cbData = sizeof(dw);
LOG_TRY(TGetKey(hKey, KP_EFFECTIVE_KEYLEN, (PBYTE) &dw, &cbData, 0, ptc));
if (TEST_EFFECTIVE_KEYLEN != dw)
{
LOG_TRY(LogBadParam(
API_CRYPTSETKEYPARAM,
L"CryptSetKeyParam KP_EFFECTIVE_KEYLEN failed",
ptc));
}
//
// KP_IV
//
LOG_TRY(TGetKey(hKey, KP_IV, NULL, &cbData, 0, ptc));
LOG_TRY(TestAlloc(&pbData, cbData, ptc));
memset(pbData, TEST_IV_BYTE, cbData);
LOG_TRY(TSetKey(hKey, KP_IV, pbData, 0, ptc));
memset(pbData, 0x00, cbData);
LOG_TRY(TGetKey(hKey, KP_IV, pbData, &cbData, 0, ptc));
while (cbData && (TEST_IV_BYTE == pbData[cbData - 1]))
{
cbData--;
}
if (0 != cbData)
{
LOG_TRY(LogBadParam(
API_CRYPTSETKEYPARAM,
L"CryptSetKeyParam TEST_IV_BYTE contains incorrect data",
ptc));
}
free(pbData);
pbData = NULL;
//
// KP_PADDING
//
dw = PKCS5_PADDING;
LOG_TRY(TSetKey(hKey, KP_PADDING, (PBYTE) &dw, 0, ptc));
dw = 0;
cbData = sizeof(dw);
LOG_TRY(TGetKey(hKey, KP_PADDING, (PBYTE) &dw, &cbData, 0, ptc));
if (PKCS5_PADDING != dw)
{
LOG_TRY(LogBadParam(
API_CRYPTSETKEYPARAM,
L"CryptSetKeyParam KP_PADDING has incorrect value",
ptc));
}
//
// KP_MODE
//
dw = CRYPT_MODE_ECB;
LOG_TRY(TSetKey(hKey, KP_MODE, (PBYTE) &dw, 0, ptc));
dw = 0;
cbData = sizeof(dw);
LOG_TRY(TGetKey(hKey, KP_MODE, (PBYTE) &dw, &cbData, 0, ptc));
if (CRYPT_MODE_ECB != dw)
{
LOG_TRY(LogBadParam(
API_CRYPTSETKEYPARAM,
L"CryptSetKeyParam KP_MODE has incorrect value",
ptc));
}
//
// KP_MODE_BITS
//
dw = TEST_MODE_BITS;
LOG_TRY(TSetKey(hKey, KP_MODE_BITS, (PBYTE) &dw, 0, ptc));
dw = 0;
cbData = sizeof(dw);
LOG_TRY(TGetKey(hKey, KP_MODE_BITS, (PBYTE) &dw, &cbData, 0, ptc));
if (TEST_MODE_BITS != dw)
{
LOG_TRY(LogBadParam(
API_CRYPTSETKEYPARAM,
L"CryptSetKeyParam KP_MODE_BITS contains incorrect value",
ptc));
}
fSuccess = TRUE;
Cleanup:
if (hKey)
{
TDestroyKey(hKey, ptc);
}
if (hProv)
{
TRelease(hProv, 0, ptc);
}
return fSuccess;
}
//
// Function: NegativeSetKeyParamTests
// Purpose: Run the negative test cases for CryptSetKeyParam
//
BOOL NegativeSetKeyParamTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
//LPWSTR pwszContainer = TEST_CONTAINER;
HCRYPTPROV hProv = 0;
HCRYPTKEY hKey = 0;
DWORD dw = 0;
PTESTCASE ptc = &(pCSPInfo->TestCase);
//
// Group 4I
//
//
// Do CryptSetKeyParam negative test cases
//
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(TSetKey(0, KP_PERMISSIONS, (PBYTE) &dw, 0, ptc));
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(TSetKey(TEST_INVALID_HANDLE, KP_PERMISSIONS, (PBYTE) &dw, 0, ptc));
LOG_TRY(CreateNewContext(&hProv, NULL, CRYPT_VERIFYCONTEXT, ptc));
LOG_TRY(CreateNewKey(hProv, CALG_RC4, 0, &hKey, ptc));
ptc->dwErrorCode = ERROR_INVALID_PARAMETER;
LOG_TRY(TSetKey(hKey, KP_PERMISSIONS, NULL, 0, ptc));
ptc->dwErrorCode = NTE_BAD_FLAGS;
LOG_TRY(TSetKey(hKey, KP_PERMISSIONS, (PBYTE) &dw, TEST_INVALID_FLAG, ptc));
ptc->dwErrorCode = NTE_BAD_TYPE;
LOG_TRY(TSetKey(hKey, TEST_INVALID_FLAG, (PBYTE) &dw, 0, ptc));
fSuccess = TRUE;
Cleanup:
if (hKey)
{
TDestroyKey(hKey, ptc);
}
if (hProv)
{
TRelease(hProv, 0, ptc);
}
return fSuccess;
}
//
// Function: PositiveExportKeyTests
// Purpose: Run the test cases for CryptExportKey. The set of test cases depends on the current
// CSP class being tested, as specified in the dwCSPClass parameter.
//
BOOL PositiveExportKeyTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
LPWSTR pwszContainer = TEST_CONTAINER;
HCRYPTPROV hProv = 0;
HCRYPTKEY hKey = 0;
HCRYPTKEY hEncryptKey = 0;
PBYTE pbKey = NULL;
DWORD cbKey = 0;
PTESTCASE ptc = &(pCSPInfo->TestCase);
LOG_TRY(CreateNewContext(&hProv, pwszContainer, CRYPT_NEWKEYSET, ptc));
//
// Group 5C
//
//
// Do CryptExportKey test cases
//
switch (pCSPInfo->TestCase.dwCSPClass)
{
case CLASS_SIG_ONLY:
{
LOG_TRY(CreateNewKey(hProv, AT_SIGNATURE, CRYPT_EXPORTABLE, &hKey, ptc));
LOG_TRY(CreateNewKey(hProv, CALG_RC4, 0, &hEncryptKey, ptc));
//
// Export a PRIVATEKEYBLOB
//
// Private key export is not permitted on Smart Cards
if (! pCSPInfo->fSmartCardCSP)
{
LOG_TRY(TExportKey(hKey, hEncryptKey, PRIVATEKEYBLOB, 0, NULL, &cbKey, ptc));
LOG_TRY(TestAlloc(&pbKey, cbKey, ptc));
LOG_TRY(TExportKey(hKey, hEncryptKey, PRIVATEKEYBLOB, 0, pbKey, &cbKey, ptc));
free(pbKey);
pbKey = NULL;
}
//
// Export a PUBLICKEYBLOB
//
cbKey = 0;
LOG_TRY(TExportKey(hKey, 0, PUBLICKEYBLOB, 0, NULL, &cbKey, ptc));
LOG_TRY(TestAlloc(&pbKey, cbKey, ptc));
LOG_TRY(TExportKey(hKey, 0, PUBLICKEYBLOB, 0, pbKey, &cbKey, ptc));
free(pbKey);
pbKey = NULL;
LOG_TRY(TDestroyKey(hKey, ptc));
hKey = 0;
//
// Export a SYMMETRICWRAPKEYBLOB
//
LOG_TRY(CreateNewKey(hProv, CALG_RC4, CRYPT_EXPORTABLE, &hKey, ptc));
cbKey = 0;
LOG_TRY(TExportKey(hKey, hEncryptKey, SYMMETRICWRAPKEYBLOB, 0, NULL, &cbKey, ptc));
LOG_TRY(TestAlloc(&pbKey, cbKey, ptc));
LOG_TRY(TExportKey(hKey, hEncryptKey, SYMMETRICWRAPKEYBLOB, 0, pbKey, &cbKey, ptc));
break;
}
case CLASS_SIG_KEYX:
{
//
// Export a SIMPLEBLOB
//
LOG_TRY(CreateNewKey(hProv, CALG_RC4, CRYPT_EXPORTABLE, &hKey, ptc));
LOG_TRY(CreateNewKey(hProv, AT_KEYEXCHANGE, 0, &hEncryptKey, ptc));
cbKey = 0;
LOG_TRY(TExportKey(hKey, hEncryptKey, SIMPLEBLOB, 0, NULL, &cbKey, ptc));
LOG_TRY(TestAlloc(&pbKey, cbKey, ptc));
LOG_TRY(TExportKey(hKey, hEncryptKey, SIMPLEBLOB, 0, pbKey, &cbKey, ptc));
free(pbKey);
pbKey = NULL;
//
// Export a SIMPLEBLOB with the CRYPT_OAEP flag
//
cbKey = 0;
LOG_TRY(TExportKey(hKey, hEncryptKey, SIMPLEBLOB, CRYPT_OAEP, NULL, &cbKey, ptc));
LOG_TRY(TestAlloc(&pbKey, cbKey, ptc));
LOG_TRY(TExportKey(hKey, hEncryptKey, SIMPLEBLOB, CRYPT_OAEP, pbKey, &cbKey, ptc));
break;
}
default:
{
goto Cleanup;
}
}
fSuccess = TRUE;
Cleanup:
if (pbKey)
{
free(pbKey);
}
if (hKey)
{
TDestroyKey(hKey, ptc);
}
if (hEncryptKey)
{
TDestroyKey(hEncryptKey, ptc);
}
if (hProv)
{
TRelease(hProv, 0, ptc);
}
return fSuccess;
}
//
// Function: NegativeExportKeyTests
// Purpose: Run the negative test cases for CryptExportKey. The set of test cases depends on the current
// CSP class being tested, as specified in the dwCSPClass parameter.
//
BOOL NegativeExportKeyTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
LPWSTR pwszContainer = TEST_CONTAINER;
LPWSTR pwszContainer2 = TEST_CONTAINER_2;
HCRYPTPROV hProv = 0;
HCRYPTPROV hProv2 = 0;
HCRYPTKEY hKey = 0;
HCRYPTKEY hKeyExch = 0;
HCRYPTKEY hEncryptKey = 0;
DWORD dw = 0;
DWORD cb = 0;
PBYTE pb = NULL;
PTESTCASE ptc = &(pCSPInfo->TestCase);
//
// Group 5C
//
//
// Run only the negative test cases appropriate for the current CSP class
//
switch (ptc->dwCSPClass)
{
case CLASS_SIG_ONLY:
{
//
// Do CryptExportKey CLASS_SIG_ONLY negative test cases
//
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(TExportKey(0, 0, PUBLICKEYBLOB, 0, (PBYTE) &dw, &cb, ptc));
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(TExportKey(TEST_INVALID_HANDLE, 0, PUBLICKEYBLOB, 0, (PBYTE) &dw, &cb, ptc));
// The TEST_LEVEL_CONTAINER CryptAcquireContext tests should be run before
// other Container level tests to ensure that this works.
LOG_TRY(CreateNewContext(&hProv, pwszContainer, CRYPT_NEWKEYSET, ptc));
// Create an exportable signature key pair
LOG_TRY(CreateNewKey(hProv, AT_SIGNATURE, CRYPT_EXPORTABLE, &hKey, ptc));
ptc->dwErrorCode = ERROR_INVALID_PARAMETER;
LOG_TRY(TExportKey(hKey, 0, PUBLICKEYBLOB, 0, (PBYTE) TEST_INVALID_POINTER, NULL, ptc));
// Indicate a buffer length that is too small
cb = 1;
ptc->dwErrorCode = ERROR_MORE_DATA;
LOG_TRY(TExportKey(hKey, 0, PUBLICKEYBLOB, 0, (PBYTE) &dw, &cb, ptc));
// cb should contain the actual required buffer size to export
// try to export to buffer that's too small, will AV
ptc->dwErrorCode = ERROR_INVALID_PARAMETER;
LOG_TRY(TExportKey(hKey, 0, PUBLICKEYBLOB, 0, (PBYTE) TEST_INVALID_POINTER, &cb, ptc));
// invalid flags
ptc->dwErrorCode = NTE_BAD_FLAGS;
LOG_TRY(TExportKey(hKey, 0, PUBLICKEYBLOB, TEST_INVALID_FLAG, (PBYTE) &dw, &cb, ptc));
// invalid blob type
ptc->dwErrorCode = NTE_BAD_TYPE;
LOG_TRY(TExportKey(hKey, 0, TEST_INVALID_FLAG, 0, NULL, &cb, ptc));
// Private key export is not permitted on Smart Cards
if (pCSPInfo->fSmartCardCSP)
{
LOG_TRY(CreateNewKey(hProv, CALG_RC4, 0, &hEncryptKey, ptc));
ptc->dwErrorCode = NTE_BAD_TYPE;
LOG_TRY(TExportKey(hKey, hEncryptKey, PRIVATEKEYBLOB, 0, NULL, &cb, ptc));
}
else
{
LOG_TRY(TDestroyKey(hKey, ptc));
hKey = 0;
// Create a new non-exportable signature key pair
LOG_TRY(CreateNewKey(hProv, AT_SIGNATURE, 0, &hKey, ptc));
// Try to export non-exportable key
ptc->dwErrorCode = NTE_BAD_KEY_STATE;
LOG_TRY(TExportKey(hKey, 0, PRIVATEKEYBLOB, 0, (PBYTE) &dw, &cb, ptc));
}
break;
}
case CLASS_SIG_KEYX:
{
//
// Do CryptExportKey CLASS_SIG_KEYX negative test cases
//
// Create context and key handle for signature pair
LOG_TRY(CreateNewContext(&hProv, pwszContainer, CRYPT_NEWKEYSET, ptc));
LOG_TRY(CreateNewKey(hProv, AT_SIGNATURE, CRYPT_EXPORTABLE, &hKey, ptc));
// Create key handle for exchange pair
LOG_TRY(CreateNewKey(hProv, AT_KEYEXCHANGE, 0, &hKeyExch, ptc));
// Should not be able to export PUBLICKEYBLOB with exchange key specified
ptc->dwErrorCode = NTE_BAD_PUBLIC_KEY;
LOG_TRY(TExportKey(hKey, hKeyExch, PUBLICKEYBLOB, 0, (PBYTE) &dw, &cb, ptc));
// Destroy signature key
LOG_TRY(TDestroyKey(hKey, ptc));
hKey = 0;
// Create symmetric key
LOG_TRY(CreateNewKey(hProv, CALG_RC4, CRYPT_EXPORTABLE, &hKey, ptc));
ptc->dwErrorCode = NTE_BAD_KEY;
LOG_TRY(TExportKey(hKey, TEST_INVALID_HANDLE, SIMPLEBLOB, 0, (PBYTE) &dw, &cb, ptc));
// Destroy the key exchange pair handle
LOG_TRY(TDestroyKey(hKeyExch, ptc));
hKeyExch = 0;
// Create separate cryptographic context
LOG_TRY(CreateNewContext(&hProv2, pwszContainer2, CRYPT_NEWKEYSET, ptc));
// Create new key exchange pair in new context
LOG_TRY(CreateNewKey(hProv, AT_KEYEXCHANGE, 0, &hKeyExch, ptc));
// Should not be able to export using keys from separate contexts
ptc->dwErrorCode = NTE_BAD_KEY;
LOG_TRY(TExportKey(hKey, hKeyExch, PRIVATEKEYBLOB, 0, (PBYTE) &dw, &cb, ptc));
break;
}
}
fSuccess = TRUE;
Cleanup:
if (hKey)
{
TDestroyKey(hKey, ptc);
}
if (hKeyExch)
{
TDestroyKey(hKeyExch, ptc);
}
if (hEncryptKey)
{
TDestroyKey(hKey, ptc);
}
if (hProv)
{
TRelease(hProv, 0, ptc);
}
if (hProv2)
{
TRelease(hProv2, 0, ptc);
}
return fSuccess;
}
//
// Function: PositiveGetUserKeyTests
// Purpose: Run the test cases for CryptGetUserKey
//
BOOL PositiveGetUserKeyTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
LPWSTR pwszContainer = TEST_CONTAINER;
HCRYPTPROV hProv = 0;
HCRYPTKEY hKey = 0;
PTESTCASE ptc = &(pCSPInfo->TestCase);
LOG_TRY(CreateNewContext(&hProv, pwszContainer, CRYPT_NEWKEYSET, ptc));
//
// Group 5E
//
//
// Do CryptGetUserKey test cases
//
switch(ptc->dwCSPClass)
{
case CLASS_SIG_ONLY:
{
LOG_TRY(CreateNewKey(hProv, AT_SIGNATURE, 0, &hKey, ptc));
LOG_TRY(TDestroyKey(hKey, ptc));
LOG_TRY(TGetUser(hProv, AT_SIGNATURE, &hKey, ptc));
break;
}
case CLASS_SIG_KEYX:
{
LOG_TRY(CreateNewKey(hProv, AT_KEYEXCHANGE, 0, &hKey, ptc));
LOG_TRY(TDestroyKey(hKey, ptc));
LOG_TRY(TGetUser(hProv, AT_KEYEXCHANGE, &hKey, ptc));
break;
}
default:
{
goto Cleanup;
}
}
fSuccess = TRUE;
Cleanup:
if (hKey)
{
TDestroyKey(hKey, ptc);
}
if (hProv)
{
TRelease(hProv, 0, ptc);
}
return fSuccess;
}
//
// Function: NegativeGetUserKeyTests
// Purpose: Run the negative test cases for CryptGetUserKey
//
BOOL NegativeGetUserKeyTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
LPWSTR pwszContainer = TEST_CONTAINER;
HCRYPTPROV hProv = 0;
HCRYPTKEY hKey = 0;
PTESTCASE ptc = &(pCSPInfo->TestCase);
//
// Group 5E
//
switch (ptc->dwCSPClass)
{
case CLASS_SIG_ONLY:
{
//
// Do CryptGetUserKey negative test cases
//
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(TGetUser(0, AT_SIGNATURE, &hKey, ptc));
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(TGetUser(TEST_INVALID_HANDLE, AT_SIGNATURE, &hKey, ptc));
//
// Use context with no container access
//
LOG_TRY(CreateNewContext(&hProv, NULL, CRYPT_VERIFYCONTEXT, ptc));
//
// Create a non-persisted key pair.
//
/*
LOG_TRY(CreateNewKey(hProv, AT_SIGNATURE, 0, &hKey, ptc));
LOG_TRY(TDestroyKey(hKey, ptc));
*/
// Not sure what expected error code should be here
ptc->dwErrorCode = NTE_NO_KEY;
LOG_TRY(TGetUser(hProv, AT_SIGNATURE, &hKey, ptc));
LOG_TRY(TRelease(hProv, 0, ptc));
hProv = 0;
// Create new context but no key
LOG_TRY(CreateNewContext(&hProv, pwszContainer, CRYPT_NEWKEYSET, ptc));
ptc->dwErrorCode = NTE_BAD_KEY;
LOG_TRY(TGetUser(hProv, TEST_INVALID_FLAG, &hKey, ptc));
ptc->dwErrorCode = NTE_NO_KEY;
LOG_TRY(TGetUser(hProv, AT_SIGNATURE, &hKey, ptc));
break;
}
case CLASS_SIG_KEYX:
{
// Create new context and signature key pair
LOG_TRY(CreateNewContext(&hProv, pwszContainer, CRYPT_NEWKEYSET, ptc));
LOG_TRY(CreateNewKey(hProv, AT_SIGNATURE, 0, &hKey, ptc));
// Request key exchange key pair, should fail since it hasn't been created
ptc->dwErrorCode = NTE_NO_KEY;
LOG_TRY(TGetUser(hProv, AT_KEYEXCHANGE, &hKey, ptc));
break;
}
}
fSuccess = TRUE;
Cleanup:
if (hKey)
{
TDestroyKey(hKey, ptc);
}
if (hProv)
{
TRelease(hProv, 0, ptc);
}
return fSuccess;
}
//
// Function: TestPrivateKeyBlobProc
//
BOOL TestPrivateKeyBlobProc(
PALGNODE pAlgNode,
PTESTCASE ptc,
PVOID pvKeyExportInfo)
{
BOOL fSuccess = FALSE;
HCRYPTKEY hKey = 0;
HCRYPTKEY hEncryptKey = 0;
PBYTE pbKey = NULL;
DWORD cbKey = 0;
PKEY_EXPORT_INFO pKeyExportInfo = (PKEY_EXPORT_INFO) pvKeyExportInfo;
LOG_TRY(CreateNewKey(
pKeyExportInfo->hProv,
pKeyExportInfo->aiKey,
CRYPT_EXPORTABLE | (pKeyExportInfo->dwKeySize << 16),
&hKey,
ptc));
if (pKeyExportInfo->fUseEncryptKey)
{
LOG_TRY(CreateNewKey(
pKeyExportInfo->hProv,
pAlgNode->ProvEnumalgsEx.aiAlgid,
pKeyExportInfo->dwEncryptKeySize << 16,
&hEncryptKey,
ptc));
}
LOG_TRY(TExportKey(
hKey,
hEncryptKey,
PRIVATEKEYBLOB,
pKeyExportInfo->dwExportFlags,
NULL,
&cbKey,
ptc));
LOG_TRY(TestAlloc(&pbKey, cbKey, ptc));
LOG_TRY(TExportKey(
hKey,
hEncryptKey,
PRIVATEKEYBLOB,
pKeyExportInfo->dwExportFlags,
pbKey,
&cbKey,
ptc));
LOG_TRY(TDestroyKey(hKey, ptc));
hKey = 0;
LOG_TRY(TImportKey(
pKeyExportInfo->hProv,
pbKey,
cbKey,
hEncryptKey,
pKeyExportInfo->dwExportFlags,
&hKey,
ptc));
fSuccess = TRUE;
Cleanup:
if (pbKey)
{
free(pbKey);
}
if (hKey)
{
TDestroyKey(hKey, ptc);
}
if (hEncryptKey)
{
TDestroyKey(hEncryptKey, ptc);
}
return fSuccess;
}
//
// Function: TestSymmetricWrapKeyBlobProc
//
BOOL TestSymmetricWrapKeyBlobProc(
PALGNODE pAlgNode,
PTESTCASE ptc,
PVOID pvKeyExportInfo)
{
BOOL fSuccess = FALSE;
HCRYPTKEY hKey = 0;
HCRYPTKEY hEncryptKey = 0;
PBYTE pbKey = NULL;
DWORD cbKey = 0;
PKEY_EXPORT_INFO pKeyExportInfo = (PKEY_EXPORT_INFO) pvKeyExportInfo;
//
// Create the key to be exported
//
LOG_TRY(CreateNewKey(
pKeyExportInfo->hProv,
pAlgNode->ProvEnumalgsEx.aiAlgid,
CRYPT_EXPORTABLE | (pKeyExportInfo->dwKeySize << 16),
&hKey,
ptc));
if (! pKeyExportInfo->fUseEncryptKey)
{
return FALSE;
}
//
// Create the encryption key
//
LOG_TRY(CreateNewKey(
pKeyExportInfo->hProv,
pKeyExportInfo->aiEncryptKey,
pKeyExportInfo->dwEncryptKeySize << 16,
&hEncryptKey,
ptc));
LOG_TRY(TExportKey(
hKey,
hEncryptKey,
SYMMETRICWRAPKEYBLOB,
pKeyExportInfo->dwExportFlags,
NULL,
&cbKey,
ptc));
LOG_TRY(TestAlloc(&pbKey, cbKey, ptc));
LOG_TRY(TExportKey(
hKey,
hEncryptKey,
SYMMETRICWRAPKEYBLOB,
pKeyExportInfo->dwExportFlags,
pbKey,
&cbKey,
ptc));
LOG_TRY(TDestroyKey(hKey, ptc));
hKey = 0;
LOG_TRY(TImportKey(
pKeyExportInfo->hProv,
pbKey,
cbKey,
hEncryptKey,
pKeyExportInfo->dwExportFlags,
&hKey,
ptc));
fSuccess = TRUE;
Cleanup:
if (pbKey)
{
free(pbKey);
}
if (hKey)
{
TDestroyKey(hKey, ptc);
}
if (hEncryptKey)
{
TDestroyKey(hEncryptKey, ptc);
}
return fSuccess;
}
//
// Function: TestSymmetricWrapperProc
// Purpose: Test all possible combinations of wrapping one symmetric
// key algorithm with another. This function will be called once for
// each encryption key alg, and this function will use AlgListIterate
// to call TestSymmetricWrapKeyBlobProc once for each encryption
// key alg.
//
BOOL TestSymmetricWrapperProc(
PALGNODE pAlgNode,
PTESTCASE ptc,
PVOID pvKeyExportInfo)
{
BOOL fSuccess = FALSE;
((PKEY_EXPORT_INFO) pvKeyExportInfo)->aiEncryptKey = pAlgNode->ProvEnumalgsEx.aiAlgid;
LOG_TRY(AlgListIterate(
((PKEY_EXPORT_INFO) pvKeyExportInfo)->pAlgList,
DataEncryptFilter,
TestSymmetricWrapKeyBlobProc,
pvKeyExportInfo,
ptc));
fSuccess = TRUE;
Cleanup:
return fSuccess;
}
//
// Function: ScenarioImportKeyTests
// Purpose: Test CryptImportKey and CryptExportKey for PRIVATEKEYBLOB and
// SYMMETRICWRAPKEYBLOB scenarios. Repeat for all supported encryption
// algorithms.
//
BOOL ScenarioImportKeyTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
LPWSTR pwszContainer = TEST_CONTAINER;
PTESTCASE ptc = &(pCSPInfo->TestCase);
PALGNODE pAlgList = pCSPInfo->pAlgList;
KEY_EXPORT_INFO KeyExportInfo;
memset(&KeyExportInfo, 0, sizeof(KeyExportInfo));
LOG_TRY(CreateNewContext(
&(KeyExportInfo.hProv),
pwszContainer,
CRYPT_NEWKEYSET,
ptc));
//
// Run the PRIVATEKEYBLOB variations
//
KeyExportInfo.aiKey = AT_KEYEXCHANGE;
KeyExportInfo.fUseEncryptKey = TRUE;
LOG_TRY(AlgListIterate(
pAlgList,
DataEncryptFilter,
TestPrivateKeyBlobProc,
(PVOID) &KeyExportInfo,
ptc));
//
// Run the SYMMETRICWRAPKEYBLOB variations
//
KeyExportInfo.aiKey = 0;
KeyExportInfo.pAlgList = pAlgList;
LOG_TRY(AlgListIterate(
pAlgList,
DataEncryptFilter,
TestSymmetricWrapperProc,
(PVOID) &KeyExportInfo,
ptc));
fSuccess = TRUE;
Cleanup:
if (KeyExportInfo.hProv)
{
TRelease(KeyExportInfo.hProv, 0, ptc);
}
return fSuccess;
}
//
// RSA Signature PRIVATEKEYBLOB
//
BYTE rgbPrivateKeyBlob [] =
{
0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00,
0x52, 0x53, 0x41, 0x32, 0x00, 0x02, 0x00, 0x00,
0x01, 0x00, 0x01, 0x00, 0xf3, 0xd8, 0x26, 0xb9,
0xbc, 0x43, 0xe4, 0x7c, 0x73, 0x36, 0xf6, 0xc3,
0x92, 0x1e, 0x2d, 0x69, 0x8d, 0x17, 0x78, 0xdf,
0x49, 0x9d, 0x1c, 0x5d, 0xbd, 0x9d, 0xf9, 0x66,
0xd8, 0x27, 0xa2, 0x5f, 0x40, 0x95, 0x20, 0xe1,
0xbf, 0xd4, 0x0b, 0x0d, 0xd7, 0xb6, 0x2d, 0x8b,
0x05, 0x06, 0x9d, 0x9f, 0x4d, 0x17, 0x9e, 0x82,
0x5e, 0x48, 0x74, 0xcf, 0x73, 0x1d, 0x60, 0xea,
0x62, 0x7f, 0xfe, 0xeb, 0x37, 0x3e, 0x03, 0x3b,
0x2b, 0x50, 0xc6, 0x28, 0x4a, 0x7d, 0xd9, 0x08,
0xb3, 0x2e, 0x3c, 0x61, 0x61, 0x78, 0xf7, 0xd8,
0xfd, 0x50, 0x05, 0x87, 0xfe, 0x6a, 0x68, 0x6e,
0x15, 0xa8, 0x99, 0xfd, 0x25, 0x7d, 0x22, 0xef,
0x9f, 0x70, 0x1c, 0xa7, 0x38, 0xa5, 0x18, 0x31,
0x82, 0x72, 0x71, 0x72, 0x95, 0x01, 0x70, 0x12,
0x04, 0xc8, 0xb9, 0xa0, 0xa1, 0xde, 0x8f, 0xef,
0xc3, 0x30, 0x3a, 0xee, 0xc1, 0x57, 0xf3, 0x63,
0xef, 0xb5, 0x78, 0x12, 0xb7, 0x69, 0x55, 0x45,
0x57, 0x45, 0x51, 0x65, 0x01, 0x6e, 0x77, 0xad,
0xe1, 0x0c, 0xa0, 0x02, 0x20, 0x91, 0x2c, 0x36,
0x42, 0xad, 0x81, 0xdf, 0x21, 0x60, 0x5c, 0x06,
0x0f, 0x4b, 0x26, 0xb4, 0x58, 0x1a, 0xda, 0x19,
0x6c, 0x5b, 0x7c, 0x9a, 0x80, 0xcb, 0x15, 0x2d,
0xb3, 0xde, 0x2b, 0xb2, 0xf8, 0xb8, 0x9d, 0xc8,
0x38, 0x41, 0x93, 0xa3, 0xb1, 0x8d, 0x3e, 0x7e,
0x3c, 0x78, 0xd7, 0x6f, 0xfd, 0xea, 0xc4, 0xf8,
0xbb, 0x44, 0xb8, 0x1e, 0x3f, 0x70, 0x98, 0x38,
0x4e, 0x4c, 0x2f, 0x95, 0xb8, 0xef, 0x21, 0x2e,
0x12, 0x95, 0x0e, 0x3f, 0xb9, 0xdd, 0xa1, 0x97,
0xdb, 0xcf, 0xdb, 0xcc, 0x86, 0xfe, 0x54, 0xae,
0x59, 0xe6, 0xa7, 0x83, 0xd3, 0x7d, 0x5f, 0x5c,
0xd1, 0xf6, 0x5a, 0xf0, 0xc1, 0xe2, 0xf8, 0xb8,
0xc0, 0x7c, 0xd8, 0x2a, 0xcd, 0xc4, 0x31, 0xd5,
0xe5, 0xc2, 0xa9, 0xa3, 0xe9, 0x70, 0x64, 0x28,
0xf0, 0xb8, 0x31, 0x52, 0x6c, 0x8a, 0x3c, 0xae,
0x43, 0xc4, 0xa5, 0x93, 0x1b, 0x86, 0x0f, 0x71,
0xd1, 0x27, 0xb4, 0xe2
};
//
// RSA Signature PUBLICKEYBLOB
//
BYTE rgbPublicKeyBlob [] =
{
0x06, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00,
0x52, 0x53, 0x41, 0x31, 0x00, 0x02, 0x00, 0x00,
0x01, 0x00, 0x01, 0x00, 0xd7, 0x90, 0x56, 0x7a,
0x9e, 0x87, 0x53, 0x90, 0x94, 0x37, 0x46, 0x4e,
0x99, 0xe7, 0xee, 0xc5, 0xa8, 0x24, 0x10, 0x5c,
0xd3, 0xc9, 0x22, 0x15, 0xab, 0xfa, 0xa5, 0x2f,
0x4e, 0x51, 0x73, 0x83, 0xef, 0x4c, 0x87, 0xe7,
0x79, 0x83, 0xd0, 0xf0, 0xb7, 0x34, 0xf1, 0xe8,
0x76, 0xb2, 0x6a, 0x0b, 0x13, 0x82, 0x9c, 0x89,
0xeb, 0x57, 0xf1, 0x6b, 0x9c, 0x47, 0x99, 0xd2,
0x26, 0x9d, 0x75, 0xc4
};
//
// Function: PositiveImportKeyTests
// Purpose: Run the test cases for CryptImportKey. The set of test cases to be run
// depends on the current CSP class being tested, as specified in the dwCSPClass
// parameter.
//
BOOL PositiveImportKeyTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
LPWSTR pwszContainer = TEST_CONTAINER;
HCRYPTKEY hKey = 0;
HCRYPTKEY hEncryptKey = 0;
HCRYPTPROV hProv = 0;
PBYTE pbKey = NULL;
DWORD cbKey = 0;
PTESTCASE ptc = &(pCSPInfo->TestCase);
LOG_TRY(CreateNewContext(&hProv, pwszContainer, CRYPT_NEWKEYSET, ptc));
//
// Group 5F
//
//
// Do CryptImportKey positive test cases
//
switch (pCSPInfo->TestCase.dwCSPClass)
{
case CLASS_SIG_ONLY:
{
//
// Import a previously generated unencrypted PRIVATEKEYBLOB
//
LOG_TRY(TImportKey(
hProv,
rgbPrivateKeyBlob,
sizeof(rgbPrivateKeyBlob),
0,
0,
&hKey,
ptc));
LOG_TRY(TDestroyKey(hKey, ptc));
hKey = 0;
//
// Import a encrypted PRIVATEKEYBLOB generated from this CSP
//
LOG_TRY(CreateNewKey(hProv, AT_SIGNATURE, CRYPT_EXPORTABLE, &hKey, ptc));
LOG_TRY(CreateNewKey(hProv, CALG_RC4, 0, &hEncryptKey, ptc));
LOG_TRY(TExportKey(hKey, hEncryptKey, PRIVATEKEYBLOB, 0, NULL, &cbKey, ptc));
LOG_TRY(TestAlloc(&pbKey, cbKey, ptc));
LOG_TRY(TExportKey(hKey, hEncryptKey, PRIVATEKEYBLOB, 0, pbKey, &cbKey, ptc));
LOG_TRY(TDestroyKey(hKey, ptc));
hKey = 0;
LOG_TRY(TImportKey(hProv, pbKey, cbKey, hEncryptKey, 0, &hKey, ptc));
LOG_TRY(TDestroyKey(hKey, ptc));
hKey = 0;
free(pbKey);
pbKey = NULL;
//
// Import a previously generated PUBLICKEYBLOB
//
LOG_TRY(TImportKey(
hProv,
rgbPublicKeyBlob,
sizeof(rgbPublicKeyBlob),
0,
0,
&hKey,
ptc));
LOG_TRY(TDestroyKey(hKey, ptc));
hKey = 0;
//
// Import a SYMMETRICWRAPKEYBLOB
//
LOG_TRY(CreateNewKey(hProv, CALG_RC4, CRYPT_EXPORTABLE, &hKey, ptc));
cbKey = 0;
LOG_TRY(TExportKey(hKey, hEncryptKey, SYMMETRICWRAPKEYBLOB, 0, NULL, &cbKey, ptc));
LOG_TRY(TestAlloc(&pbKey, cbKey, ptc));
LOG_TRY(TExportKey(hKey, hEncryptKey, SYMMETRICWRAPKEYBLOB, 0, pbKey, &cbKey, ptc));
LOG_TRY(TDestroyKey(hKey, ptc));
hKey = 0;
LOG_TRY(TImportKey(hProv, pbKey, cbKey, hEncryptKey, 0, &hKey, ptc));
break;
}
case CLASS_SIG_KEYX:
{
//
// Import a SIMPLEBLOB
//
LOG_TRY(CreateNewKey(hProv, AT_KEYEXCHANGE, 0, &hEncryptKey, ptc));
LOG_TRY(CreateNewKey(hProv, CALG_RC4, CRYPT_EXPORTABLE, &hKey, ptc));
cbKey = 0;
LOG_TRY(TExportKey(hKey, hEncryptKey, SIMPLEBLOB, 0, NULL, &cbKey, ptc));
LOG_TRY(TestAlloc(&pbKey, cbKey, ptc));
LOG_TRY(TExportKey(hKey, hEncryptKey, SIMPLEBLOB, 0, pbKey, &cbKey, ptc));
LOG_TRY(TDestroyKey(hKey, ptc));
hKey = 0;
LOG_TRY(TImportKey(hProv, pbKey, cbKey, hEncryptKey, 0, &hKey, ptc));
LOG_TRY(TDestroyKey(hKey, ptc));
hKey = 0;
free(pbKey);
pbKey = NULL;
//
// Import a SIMPLEBLOB with the CRYPT_OAEP flag
//
LOG_TRY(CreateNewKey(hProv, CALG_RC4, CRYPT_EXPORTABLE, &hKey, ptc));
cbKey = 0;
LOG_TRY(TExportKey(hKey, hEncryptKey, SIMPLEBLOB, CRYPT_OAEP, NULL, &cbKey, ptc));
LOG_TRY(TestAlloc(&pbKey, cbKey, ptc));
LOG_TRY(TExportKey(hKey, hEncryptKey, SIMPLEBLOB, CRYPT_OAEP, pbKey, &cbKey, ptc));
LOG_TRY(TDestroyKey(hKey, ptc));
hKey = 0;
LOG_TRY(TImportKey(hProv, pbKey, cbKey, hEncryptKey, CRYPT_OAEP, &hKey, ptc));
break;
}
default:
{
goto Cleanup;
}
}
fSuccess = TRUE;
Cleanup:
if (pbKey)
{
free(pbKey);
}
if (hKey)
{
TDestroyKey(hKey, ptc);
}
if (hEncryptKey)
{
TDestroyKey(hEncryptKey, ptc);
}
if (hProv)
{
TRelease(hProv, 0, ptc);
}
return fSuccess;
}
//
// Function: NegativeImportKeyTests
// Purpose: Run the negative test cases for CryptImportKey. The set of test cases to be run
// depends on the current CSP class being tested, as specified in the dwCSPClass
// parameter.
//
BOOL NegativeImportKeyTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
LPWSTR pwszContainer = TEST_CONTAINER;
HCRYPTPROV hProv = 0;
HCRYPTKEY hKey = 0;
HCRYPTKEY hKeyExch = 0;
HCRYPTKEY hKeySig = 0;
HCRYPTKEY hKeyEncr = 0;
DWORD dw = 0;
DWORD cb = 0;
PBYTE pbKey = NULL;
BLOBHEADER *pBlobHeader = NULL;
PTESTCASE ptc = &(pCSPInfo->TestCase);
// Acquire context with key container access
LOG_TRY(CreateNewContext(&hProv, pwszContainer, CRYPT_NEWKEYSET, ptc));
//
// Group 5F
//
switch (ptc->dwCSPClass)
{
case CLASS_SIG_ONLY:
{
//
// Do CryptImportKey negative test cases for CSP CLASS_SIG_ONLY
//
cb = sizeof(dw);
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(TImportKey(0, (PBYTE) &dw, cb, 0, PUBLICKEYBLOB, &hKey, ptc));
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(TImportKey(TEST_INVALID_HANDLE, (PBYTE) &dw, cb, 0, PUBLICKEYBLOB, &hKey, ptc));
// Create a key signature key pair
LOG_TRY(CreateNewKey(hProv, AT_SIGNATURE, CRYPT_EXPORTABLE, &hKey, ptc));
// Get correct blob size for signature key public blob
ptc->fExpectSuccess = TRUE;
LOG_TRY(TExportKey(hKey, 0, PUBLICKEYBLOB, 0, NULL, &cb, ptc));
LOG_TRY(TestAlloc(&pbKey, cb, ptc));
// Export the key
LOG_TRY(TExportKey(hKey, 0, PUBLICKEYBLOB, 0, pbKey, &cb, ptc));
// Destroy the key handle
LOG_TRY(TDestroyKey(hKey, ptc));
hKey = 0;
ptc->fExpectSuccess = FALSE;
// Invalid flag value
ptc->KnownErrorID = KNOWN_CRYPTIMPORTKEY_BADFLAGS;
ptc->dwErrorCode = NTE_BAD_FLAGS;
LOG_TRY(TImportKey(hProv, pbKey, cb, 0, TEST_INVALID_FLAG, &hKey, ptc));
ptc->KnownErrorID = KNOWN_ERROR_UNKNOWN;
// Pass in too short buffer
ptc->dwErrorCode = ERROR_INVALID_PARAMETER;
LOG_TRY(TImportKey(hProv, (PBYTE) TEST_INVALID_POINTER, cb, 0, 0, &hKey, ptc));
break;
}
case CLASS_SIG_KEYX:
{
//
// Do CryptImportKey negative test cases for CSP CLASS_SIG_KEYX
//
// Create a key signature key pair
LOG_TRY(CreateNewKey(hProv, AT_SIGNATURE, CRYPT_EXPORTABLE, &hKeySig, ptc));
// Create a key exchange key pair
LOG_TRY(CreateNewKey(hProv, AT_KEYEXCHANGE, 0, &hKeyExch, ptc));
// Get correct blob size for signature key public blob
ptc->fExpectSuccess = TRUE;
LOG_TRY(TExportKey(hKeySig, 0, PUBLICKEYBLOB, 0, NULL, &cb, ptc));
ptc->fExpectSuccess = FALSE;
// Attempt to import an unencrypted key blob using a key-exchange key
ptc->dwErrorCode = ERROR_INVALID_PARAMETER;
LOG_TRY(TImportKey(hProv, (PBYTE) TEST_INVALID_POINTER, cb, hKeyExch, 0, &hKey, ptc));
// Get correct blob size for encrypted signature key blob
/*
ptc->fExpectSuccess = TRUE;
LOG_TRY(TExportKey(hKeySig, hKeyExch, PRIVATEKEYBLOB, 0, NULL, &cb, ptc));
LOG_TRY(TestAlloc(&pbKey, cb, ptc));
// Export the encrypted signature key
LOG_TRY(TExportKey(hKeySig, hKeyExch, PRIVATEKEYBLOB, 0, pbKey, &cb, ptc));
ptc->fExpectSuccess = FALSE;
// Attempt to import encrypted key blob with invalid key-exchange handle
ptc->dwErrorCode = NTE_BAD_KEY;
LOG_TRY(TImportKey(hProv, pbKey, cb, TEST_INVALID_HANDLE, 0, &hKey, ptc));
// Free the key blob memory
free(pbKey);
*/
// Create a new encryption key
LOG_TRY(CreateNewKey(hProv, CALG_RC4, CRYPT_EXPORTABLE, &hKeyEncr, ptc));
// Get blob size for exporting encrypted symmetric key
ptc->fExpectSuccess = TRUE;
LOG_TRY(TExportKey(hKeyEncr, hKeyExch, SIMPLEBLOB, 0, NULL, &cb, ptc));
LOG_TRY(TestAlloc(&pbKey, cb, ptc));
// Export encrypted symmetric key
LOG_TRY(TExportKey(hKeyEncr, hKeyExch, SIMPLEBLOB, 0, pbKey, &cb, ptc));
ptc->fExpectSuccess = FALSE;
// Attempt to import encrypted key blob with invalid key-exchange handle
ptc->dwErrorCode = NTE_BAD_KEY;
LOG_TRY(TImportKey(hProv, pbKey, cb, TEST_INVALID_HANDLE, 0, &hKey, ptc));
pBlobHeader = (BLOBHEADER *) pbKey;
// Save header encryption alg
dw = pBlobHeader->aiKeyAlg;
// Clear header encryption alg field
pBlobHeader->aiKeyAlg = 0;
ptc->pwszErrorHelp =
L"The blob header encryption algorithm is missing";
ptc->KnownErrorID = KNOWN_CRYPTIMPORTKEY_BADALGID;
ptc->dwErrorCode = NTE_BAD_ALGID;
LOG_TRY(TImportKey(hProv, pbKey, cb, hKeyExch, 0, &hKey, ptc));
ptc->pwszErrorHelp = NULL;
ptc->KnownErrorID = KNOWN_ERROR_UNKNOWN;
// Restore header encryption alg
pBlobHeader->aiKeyAlg = dw;
// Save blob type header field
dw = pBlobHeader->bType;
// Clear blob type header field
pBlobHeader->bType = 0;
ptc->dwErrorCode = NTE_BAD_TYPE;
LOG_TRY(TImportKey(hProv, pbKey, cb, hKeyExch, 0, &hKey, ptc));
// Restore blob type header field
pBlobHeader->bType = (BYTE) dw;
// Save blob version header field
dw = pBlobHeader->bVersion;
// Clear blob version header field
pBlobHeader->bVersion = 0;
ptc->dwErrorCode = NTE_BAD_VER;
LOG_TRY(TImportKey(hProv, pbKey, cb, hKeyExch, 0, &hKey, ptc));
break;
}
}
fSuccess = TRUE;
Cleanup:
if (pbKey)
{
free(pbKey);
}
if (hKey)
{
TDestroyKey(hKey, ptc);
}
if (hKeySig)
{
TDestroyKey(hKeySig, ptc);
}
if (hKeyExch)
{
TDestroyKey(hKeyExch, ptc);
}
if (hKeyEncr)
{
TDestroyKey(hKeyEncr, ptc);
}
if (hProv)
{
TRelease(hProv, 0, ptc);
}
return fSuccess;
}
//
// Function: PositiveSignHashTests
// Purpose: Run the test cases for CryptSignHash. The set of positive test cases to be run depends on the
// current CSP class being tested, as specified in the dwCSPClass parameter.
//
BOOL PositiveSignHashTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
LPWSTR pwszContainer = TEST_CONTAINER;
HCRYPTPROV hProv = 0;
HCRYPTKEY hKey = 0;
HCRYPTHASH hHash = 0;
PBYTE pbSignature = NULL;
DWORD cbSignature = 0;
PTESTCASE ptc = &(pCSPInfo->TestCase);
LOG_TRY(CreateNewContext(&hProv, pwszContainer, CRYPT_NEWKEYSET, ptc));
//
// Group 5G
//
//
// Do CryptSignHash positive test cases
//
switch(ptc->dwCSPClass)
{
case CLASS_SIG_ONLY:
{
//
// Sign a hash with a signature key pair
//
LOG_TRY(CreateNewKey(hProv, AT_SIGNATURE, 0, &hKey, ptc));
LOG_TRY(CreateNewHash(hProv, CALG_SHA1, &hHash, ptc));
LOG_TRY(TSignHash(hHash, AT_SIGNATURE, NULL, 0, NULL, &cbSignature, ptc));
LOG_TRY(TestAlloc(&pbSignature, cbSignature, ptc));
LOG_TRY(TSignHash(hHash, AT_SIGNATURE, NULL, 0, pbSignature, &cbSignature, ptc));
free(pbSignature);
pbSignature = NULL;
//
// Sign with the CRYPT_NOHASHOID flag
//
LOG_TRY(TSignHash(
hHash,
AT_SIGNATURE,
NULL,
CRYPT_NOHASHOID,
NULL,
&cbSignature,
ptc));
LOG_TRY(TestAlloc(&pbSignature, cbSignature, ptc));
LOG_TRY(TSignHash(
hHash,
AT_SIGNATURE,
NULL,
CRYPT_NOHASHOID,
pbSignature,
&cbSignature,
ptc));
break;
}
case CLASS_SIG_KEYX:
{
//
// Sign a hash with a key exchange key pair
//
LOG_TRY(CreateNewKey(hProv, AT_KEYEXCHANGE, 0, &hKey, ptc));
LOG_TRY(CreateNewHash(hProv, CALG_SHA1, &hHash, ptc));
LOG_TRY(TSignHash(hHash, AT_KEYEXCHANGE, NULL, 0, NULL, &cbSignature, ptc));
LOG_TRY(TestAlloc(&pbSignature, cbSignature, ptc));
LOG_TRY(TSignHash(hHash, AT_KEYEXCHANGE, NULL, 0, pbSignature, &cbSignature, ptc));
free(pbSignature);
pbSignature = NULL;
//
// Sign with the CRYPT_NOHASHOID flag
//
LOG_TRY(TSignHash(
hHash,
AT_KEYEXCHANGE,
NULL,
CRYPT_NOHASHOID,
NULL,
&cbSignature,
ptc));
LOG_TRY(TestAlloc(&pbSignature, cbSignature, ptc));
LOG_TRY(TSignHash(
hHash,
AT_KEYEXCHANGE,
NULL,
CRYPT_NOHASHOID,
pbSignature,
&cbSignature,
ptc));
break;
}
default:
{
goto Cleanup;
}
}
fSuccess = TRUE;
Cleanup:
if (pbSignature)
{
free(pbSignature);
}
if (hKey)
{
TDestroyKey(hKey, ptc);
}
if (hProv)
{
TRelease(hProv, 0, ptc);
}
return fSuccess;
}
//
// Function: NegativeSignHashTests
// Purpose: Run the negative test cases for CryptSignHash.
//
BOOL NegativeSignHashTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
LPWSTR pwszContainer = TEST_CONTAINER;
HCRYPTPROV hProv = 0;
HCRYPTKEY hKey = 0;
HCRYPTHASH hHash = 0;
DWORD dw = 0;
DWORD cb = 0;
PTESTCASE ptc = &(pCSPInfo->TestCase);
//
// Group 5G
//
//
// Do CryptSignHash negative test cases
//
// Create provider handle with key container access
LOG_TRY(CreateNewContext(&hProv, pwszContainer, CRYPT_NEWKEYSET, ptc));
// Create hash
LOG_TRY(CreateNewHash(hProv, CALG_SHA1, &hHash, ptc));
// Attempt to sign with a keyset that doesn't exist
ptc->dwErrorCode = NTE_BAD_KEYSET;
LOG_TRY(TSignHash(hHash, AT_SIGNATURE, NULL, 0, (PBYTE) &dw, &cb, ptc));
// Create signature key pair
LOG_TRY(CreateNewKey(hProv, AT_SIGNATURE, 0, &hKey, ptc));
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(TSignHash(0, AT_SIGNATURE, NULL, 0, (PBYTE) &dw, &cb, ptc));
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(TSignHash(TEST_INVALID_HANDLE, AT_SIGNATURE, NULL, 0, (PBYTE) &dw, &cb, ptc));
cb = 1;
ptc->dwErrorCode = ERROR_MORE_DATA;
LOG_TRY(TSignHash(hHash, AT_SIGNATURE, NULL, 0, (PBYTE) &dw, &cb, ptc));
ptc->dwErrorCode = NTE_BAD_ALGID;
LOG_TRY(TSignHash(hHash, TEST_INVALID_FLAG, NULL, 0, (PBYTE) &dw, &cb, ptc));
ptc->dwErrorCode = NTE_BAD_FLAGS;
LOG_TRY(TSignHash(hHash, AT_SIGNATURE, NULL, TEST_INVALID_FLAG, (PBYTE) &dw, &cb, ptc));
// Release the provider handle
/*
LOG_TRY(TRelease(hProv, 0, ptc));
hProv = 0;
// Provider handle used to create hHash is now invalid
ptc->dwErrorCode = NTE_BAD_UID;
LOG_TRY(TSignHash(hHash, AT_SIGNATURE, NULL, 0, (PBYTE) &dw, &cb, ptc));
*/
fSuccess = TRUE;
Cleanup:
if (hKey)
{
TDestroyKey(hKey, ptc);
}
if (hHash)
{
TDestroyHash(hHash, ptc);
}
if (hProv)
{
TRelease(hProv, 0, ptc);
}
return fSuccess;
}
//
// Function: SignAndVerifySignatureProc
//
BOOL SignAndVerifySignatureProc(
PALGNODE pAlgNode,
PTESTCASE ptc,
PVOID pvSignHashInfo)
{
BOOL fSuccess = FALSE;
HCRYPTHASH hHash = 0;
PBYTE pbSignature = NULL;
DWORD cbSignature = 0;
PSIGN_HASH_INFO pSignHashInfo = (PSIGN_HASH_INFO) pvSignHashInfo;
LOG_TRY(CreateNewHash(
pSignHashInfo->hProv,
pAlgNode->ProvEnumalgsEx.aiAlgid,
&hHash,
ptc));
LOG_TRY(THashData(
hHash,
pSignHashInfo->dbBaseData.pbData,
pSignHashInfo->dbBaseData.cbData,
0,
ptc));
//
// Sign the hash with the Signature key pair and verify
// the signature.
//
LOG_TRY(TSignHash(
hHash,
AT_SIGNATURE,
NULL,
0,
NULL,
&cbSignature,
ptc));
LOG_TRY(TestAlloc(&pbSignature, cbSignature, ptc));
LOG_TRY(TSignHash(
hHash,
AT_SIGNATURE,
NULL,
0,
pbSignature,
&cbSignature,
ptc));
LOG_TRY(TVerifySign(
hHash,
pbSignature,
cbSignature,
pSignHashInfo->hSigKey,
NULL,
0,
ptc));
free(pbSignature);
pbSignature = NULL;
//
// Sign the hash with the Key Exchange key pair and
// verify the signature.
//
LOG_TRY(TSignHash(
hHash,
AT_KEYEXCHANGE,
NULL,
0,
NULL,
&cbSignature,
ptc));
LOG_TRY(TestAlloc(&pbSignature, cbSignature, ptc));
LOG_TRY(TSignHash(
hHash,
AT_KEYEXCHANGE,
NULL,
0,
pbSignature,
&cbSignature,
ptc));
LOG_TRY(TVerifySign(
hHash,
pbSignature,
cbSignature,
pSignHashInfo->hExchKey,
NULL,
0,
ptc));
fSuccess = TRUE;
Cleanup:
if (pbSignature)
{
free(pbSignature);
}
if (hHash)
{
TDestroyHash(hHash, ptc);
}
return fSuccess;
}
//
// Function: ScenarioVerifySignatureTests
// Purpose: For each supported hash algorithm, call
// SignAndVerifySignatureProc.
//
BOOL ScenarioVerifySignatureTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
LPWSTR pwszContainer = TEST_CONTAINER;
PTESTCASE ptc = &(pCSPInfo->TestCase);
PALGNODE pAlgList = pCSPInfo->pAlgList;
SIGN_HASH_INFO SignHashInfo;
memset(&SignHashInfo, 0, sizeof(SignHashInfo));
LOG_TRY(CreateNewContext(
&(SignHashInfo.hProv),
pwszContainer,
CRYPT_NEWKEYSET,
ptc));
LOG_TRY(CreateNewKey(
SignHashInfo.hProv,
AT_SIGNATURE,
0,
&(SignHashInfo.hSigKey),
ptc));
LOG_TRY(CreateNewKey(
SignHashInfo.hProv,
AT_KEYEXCHANGE,
0,
&(SignHashInfo.hExchKey),
ptc));
SignHashInfo.dbBaseData.cbData = wcslen(TEST_HASH_DATA) * sizeof(WCHAR);
LOG_TRY(TestAlloc(
&(SignHashInfo.dbBaseData.pbData),
SignHashInfo.dbBaseData.cbData,
ptc));
memcpy(
SignHashInfo.dbBaseData.pbData,
TEST_HASH_DATA,
SignHashInfo.dbBaseData.cbData);
//
// The SignAndVerifySignatureProc isn't meant to work with
// MAC algorithms, so filter those out.
//
LOG_TRY(AlgListIterate(
pAlgList,
HashAlgFilter,
SignAndVerifySignatureProc,
(PVOID) &SignHashInfo,
ptc));
fSuccess = TRUE;
Cleanup:
if (SignHashInfo.dbBaseData.pbData)
{
free(SignHashInfo.dbBaseData.pbData);
}
if (SignHashInfo.hExchKey)
{
TDestroyKey(SignHashInfo.hExchKey, ptc);
}
if (SignHashInfo.hSigKey)
{
TDestroyKey(SignHashInfo.hSigKey, ptc);
}
if (SignHashInfo.hProv)
{
TRelease(SignHashInfo.hProv, 0, ptc);
}
return fSuccess;
}
//
// Function: PositiveVerifySignatureTests
// Purpose: Run the test cases for CryptVerifySignature
//
BOOL PositiveVerifySignatureTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
LPWSTR pwszContainer = TEST_CONTAINER;
HCRYPTPROV hProv = 0;
HCRYPTKEY hKey = 0;
HCRYPTHASH hHash = 0;
PBYTE pbSignature = NULL;
DWORD cbSignature = 0;
PTESTCASE ptc = &(pCSPInfo->TestCase);
LOG_TRY(CreateNewContext(&hProv, pwszContainer, CRYPT_NEWKEYSET, ptc));
//
// Group 5H
//
//
// Do CryptVerifySignature positive test cases
//
switch(ptc->dwCSPClass)
{
case CLASS_SIG_ONLY:
{
//
// Sign and verify a hash using a signature key pair
//
LOG_TRY(CreateNewKey(hProv, AT_SIGNATURE, 0, &hKey, ptc));
LOG_TRY(CreateNewHash(hProv, CALG_SHA1, &hHash, ptc));
LOG_TRY(TSignHash(hHash, AT_SIGNATURE, NULL, 0, NULL, &cbSignature, ptc));
LOG_TRY(TestAlloc(&pbSignature, cbSignature, ptc));
LOG_TRY(TSignHash(hHash, AT_SIGNATURE, NULL, 0, pbSignature, &cbSignature, ptc));
LOG_TRY(TVerifySign(
hHash,
pbSignature,
cbSignature,
hKey,
NULL,
0,
ptc));
free(pbSignature);
pbSignature = NULL;
//
// Sign and verify using the CRYPT_NOHASHOID flag
//
LOG_TRY(TSignHash(
hHash,
AT_SIGNATURE,
NULL,
CRYPT_NOHASHOID,
NULL,
&cbSignature,
ptc));
LOG_TRY(TestAlloc(&pbSignature, cbSignature, ptc));
LOG_TRY(TSignHash(
hHash,
AT_SIGNATURE,
NULL,
CRYPT_NOHASHOID,
pbSignature,
&cbSignature,
ptc));
LOG_TRY(TVerifySign(
hHash,
pbSignature,
cbSignature,
hKey,
NULL,
CRYPT_NOHASHOID,
ptc));
break;
}
case CLASS_SIG_KEYX:
{
//
// Sign and verify a hash with a key exchange key pair
//
LOG_TRY(CreateNewKey(hProv, AT_KEYEXCHANGE, 0, &hKey, ptc));
LOG_TRY(CreateNewHash(hProv, CALG_SHA1, &hHash, ptc));
LOG_TRY(TSignHash(hHash, AT_KEYEXCHANGE, NULL, 0, NULL, &cbSignature, ptc));
LOG_TRY(TestAlloc(&pbSignature, cbSignature, ptc));
LOG_TRY(TSignHash(hHash, AT_KEYEXCHANGE, NULL, 0, pbSignature, &cbSignature, ptc));
LOG_TRY(TVerifySign(
hHash,
pbSignature,
cbSignature,
hKey,
NULL,
0,
ptc));
free(pbSignature);
pbSignature = NULL;
//
// Sign and verify using the CRYPT_NOHASHOID flag
//
LOG_TRY(TSignHash(
hHash,
AT_KEYEXCHANGE,
NULL,
CRYPT_NOHASHOID,
NULL,
&cbSignature,
ptc));
LOG_TRY(TestAlloc(&pbSignature, cbSignature, ptc));
LOG_TRY(TSignHash(
hHash,
AT_KEYEXCHANGE,
NULL,
CRYPT_NOHASHOID,
pbSignature,
&cbSignature,
ptc));
LOG_TRY(TVerifySign(
hHash,
pbSignature,
cbSignature,
hKey,
NULL,
CRYPT_NOHASHOID,
ptc));
break;
}
default:
{
goto Cleanup;
}
}
fSuccess = TRUE;
Cleanup:
if (pbSignature)
{
free(pbSignature);
}
if (hKey)
{
TDestroyKey(hKey, ptc);
}
if (hProv)
{
TRelease(hProv, 0, ptc);
}
return fSuccess;
}
//
// Function: NegativeVerifySignatureTests
// Purpose: Run the negative test cases for CryptVerifySignature
//
BOOL NegativeVerifySignatureTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
LPWSTR pwszContainer = TEST_CONTAINER;
HCRYPTPROV hProv = 0;
HCRYPTKEY hKey = 0;
HCRYPTHASH hHash = 0;
//DWORD dw = 0;
DWORD cb = 0;
PBYTE pb = NULL;
PTESTCASE ptc = &(pCSPInfo->TestCase);
//
// Group 5H
//
//
// Do CryptVerifySignature negative test cases
//
// Create new context with key container access
LOG_TRY(CreateNewContext(&hProv, pwszContainer, CRYPT_NEWKEYSET, ptc));
// Create new signature key pair
LOG_TRY(CreateNewKey(hProv, AT_SIGNATURE, 0, &hKey, ptc));
// Create new hash
LOG_TRY(CreateNewHash(hProv, CALG_SHA1, &hHash, ptc));
// Sign the hash
ptc->fExpectSuccess = TRUE;
LOG_TRY(TSignHash(hHash, AT_SIGNATURE, NULL, 0, NULL, &cb, ptc));
LOG_TRY(TestAlloc(&pb, cb, ptc));
LOG_TRY(TSignHash(hHash, AT_SIGNATURE, NULL, 0, pb, &cb, ptc));
ptc->fExpectSuccess = FALSE;
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(TVerifySign(0, pb, cb, hKey, NULL, 0, ptc));
ptc->dwErrorCode = ERROR_INVALID_HANDLE;
LOG_TRY(TVerifySign(TEST_INVALID_HANDLE, pb, cb, hKey, NULL, 0, ptc));
ptc->dwErrorCode = ERROR_INVALID_PARAMETER;
LOG_TRY(TVerifySign(hHash, NULL, cb, hKey, NULL, 0, ptc));
ptc->dwErrorCode = NTE_BAD_FLAGS;
LOG_TRY(TVerifySign(hHash, pb, cb, hKey, NULL, TEST_INVALID_FLAG, ptc));
// Use invalid signature key handle
ptc->dwErrorCode = NTE_BAD_KEY;
LOG_TRY(TVerifySign(hHash, pb, cb, TEST_INVALID_HANDLE, NULL, 0, ptc));
// Indicate a too-short buffer length
ptc->dwErrorCode = NTE_BAD_SIGNATURE;
LOG_TRY(TVerifySign(hHash, pb, cb - 1, hKey, NULL, 0, ptc));
// Flip the bits in the last byte of the signature blob
pb[cb - 1] = ~(pb[cb - 1]);
ptc->dwErrorCode = NTE_BAD_SIGNATURE;
LOG_TRY(TVerifySign(hHash, pb, cb, hKey, NULL, 0, ptc));
/*
// Release the context used to create hHash
LOG_TRY(TRelease(hProv, 0, ptc));
hProv = 0;
// Provider handle used to create hHash is now invalid
ptc->dwErrorCode = NTE_BAD_UID;
LOG_TRY(TVerifySign(hHash, pb, cb, hKey, NULL, 0, ptc));
*/
fSuccess = TRUE;
Cleanup:
if (hHash)
{
TDestroyHash(hHash, ptc);
}
if (hKey)
{
TDestroyKey(hKey, ptc);
}
if (hProv)
{
TRelease(hProv, 0, ptc);
}
if (pb)
{
free(pb);
}
return fSuccess;
}
//
// Function: TestKeyExchangeProc
// Purpose: Simulate a key/data exchange scenario for the specified
// encryption alg.
//
BOOL TestKeyExchangeProc(
PALGNODE pAlgNode,
PTESTCASE ptc,
PVOID pvExchangeProcInfo)
{
BOOL fSuccess = FALSE;
PEXCHANGE_PROC_INFO pExchangeProcInfo = (PEXCHANGE_PROC_INFO) pvExchangeProcInfo;
KEYEXCHANGE_INFO KeyExchangeInfo;
KEYEXCHANGE_STATE KeyExchangeState;
memset(&KeyExchangeInfo, 0, sizeof(KeyExchangeInfo));
memset(&KeyExchangeState, 0, sizeof(KeyExchangeState));
KeyExchangeInfo.aiHash = pExchangeProcInfo->aiHashAlg;
KeyExchangeInfo.aiSessionKey = pAlgNode->ProvEnumalgsEx.aiAlgid;
KeyExchangeInfo.dbPlainText.pbData = pExchangeProcInfo->dbPlainText.pbData;
KeyExchangeInfo.dbPlainText.cbData = pExchangeProcInfo->dbPlainText.cbData;
KeyExchangeInfo.dwPubKeySize = pExchangeProcInfo->dwPublicKeySize;
LOG_TRY(RSA1_CreateKeyPair(
pExchangeProcInfo->hProv,
&KeyExchangeInfo,
&KeyExchangeState,
ptc));
LOG_TRY(RSA2_EncryptPlainText(
pExchangeProcInfo->hInteropProv,
&KeyExchangeInfo,
&KeyExchangeState,
ptc));
LOG_TRY(RSA3_DecryptAndCheck(
pExchangeProcInfo->hProv,
&KeyExchangeInfo,
&KeyExchangeState,
ptc));
fSuccess = TRUE;
Cleanup:
return fSuccess;
}
//
// Function: InteropKeyExchangeTests
// Purpose: Run the TestKeyExchangeProc for each encryption algorithm
// supported by this CSP. Cryptographic context A will be from the CSP
// under test. Context B will be from the interop context specified
// by the user.
//
BOOL InteropKeyExchangeTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
LPWSTR pwszContainer = TEST_CONTAINER;
LPWSTR pwszInteropContainer = TEST_CONTAINER_2;
PTESTCASE ptc = &(pCSPInfo->TestCase);
PALGNODE pAlgList = pCSPInfo->pAlgList;
EXCHANGE_PROC_INFO ExchangeProcInfo;
memset(&ExchangeProcInfo, 0, sizeof(ExchangeProcInfo));
LOG_TRY(CreateNewContext(
&(ExchangeProcInfo.hProv),
pwszContainer,
CRYPT_NEWKEYSET,
ptc));
LOG_TRY(CreateNewInteropContext(
&(ExchangeProcInfo.hInteropProv),
pwszInteropContainer,
CRYPT_NEWKEYSET,
ptc));
//
// Note: Using the following hard-coded information for this
// test.
//
ExchangeProcInfo.aiHashAlg = CALG_SHA1;
ExchangeProcInfo.dbPlainText.cbData = wcslen(TEST_HASH_DATA) * sizeof(WCHAR);
LOG_TRY(TestAlloc(
&(ExchangeProcInfo.dbPlainText.pbData),
ExchangeProcInfo.dbPlainText.cbData,
ptc));
memcpy(
ExchangeProcInfo.dbPlainText.pbData,
TEST_DECRYPT_DATA,
ExchangeProcInfo.dbPlainText.cbData);
LOG_TRY(AlgListIterate(
pAlgList,
DataEncryptFilter,
TestKeyExchangeProc,
(PVOID) &ExchangeProcInfo,
ptc));
fSuccess = TRUE;
Cleanup:
if (ExchangeProcInfo.dbPlainText.pbData)
{
free(ExchangeProcInfo.dbPlainText.pbData);
}
if (ExchangeProcInfo.hProv)
{
TRelease(ExchangeProcInfo.hProv, 0, ptc);
}
if (ExchangeProcInfo.hInteropProv)
{
TRelease(ExchangeProcInfo.hInteropProv, 0, ptc);
}
return fSuccess;
}
//
// Function: ScenarioKeyExchangeTests
// Purpose: Run the TestKeyExchangeProc for each encryption algorithm
// supported by this CSP. Both of the cryptographic contexts in the
// scenario will be from the CSP under test.
//
BOOL ScenarioKeyExchangeTests(PCSPINFO pCSPInfo)
{
BOOL fSuccess = FALSE;
LPWSTR pwszContainer = TEST_CONTAINER;
LPWSTR pwszContainer2 = TEST_CONTAINER_2;
PTESTCASE ptc = &(pCSPInfo->TestCase);
PALGNODE pAlgList = pCSPInfo->pAlgList;
EXCHANGE_PROC_INFO ExchangeProcInfo;
memset(&ExchangeProcInfo, 0, sizeof(ExchangeProcInfo));
LOG_TRY(CreateNewContext(
&(ExchangeProcInfo.hProv),
pwszContainer,
CRYPT_NEWKEYSET,
ptc));
LOG_TRY(CreateNewContext(
&(ExchangeProcInfo.hInteropProv),
pwszContainer2,
CRYPT_NEWKEYSET,
ptc));
//
// Note: Using the following hard-coded information for this
// test.
//
ExchangeProcInfo.aiHashAlg = CALG_SHA1;
ExchangeProcInfo.dbPlainText.cbData = wcslen(TEST_HASH_DATA) * sizeof(WCHAR);
LOG_TRY(TestAlloc(
&(ExchangeProcInfo.dbPlainText.pbData),
ExchangeProcInfo.dbPlainText.cbData,
ptc));
memcpy(
ExchangeProcInfo.dbPlainText.pbData,
(PVOID) TEST_DECRYPT_DATA,
ExchangeProcInfo.dbPlainText.cbData);
LOG_TRY(AlgListIterate(
pAlgList,
DataEncryptFilter,
TestKeyExchangeProc,
(PVOID) &ExchangeProcInfo,
ptc));
fSuccess = TRUE;
Cleanup:
if (ExchangeProcInfo.dbPlainText.pbData)
{
free(ExchangeProcInfo.dbPlainText.pbData);
}
if (ExchangeProcInfo.hProv)
{
TRelease(ExchangeProcInfo.hProv, 0, ptc);
}
if (ExchangeProcInfo.hInteropProv)
{
TRelease(ExchangeProcInfo.hInteropProv, 0, ptc);
}
return fSuccess;
}
//
// Function: GetKnownErrorValue
//
DWORD GetKnownErrorValue(
IN KNOWN_ERROR_ID KnownErrorID,
IN DWORD dwCurrentErrorLevel)
{
DWORD dwActualErrorLevel = dwCurrentErrorLevel;
int iErrorTable = 0;
//
// Search the g_KnownErrorTable for KnownErrorID
//
for (
iErrorTable = 0;
iErrorTable < (sizeof(g_KnownErrorTable) / sizeof(KNOWN_ERROR_INFO));
iErrorTable++)
{
if (KnownErrorID == g_KnownErrorTable[iErrorTable].KnownErrorID)
{
//
// This is a known error. Get the error level that should be
// applied.
//
dwActualErrorLevel = g_KnownErrorTable[iErrorTable].dwErrorLevel;
//
// Check the version information for this error
//
if (! IsVersionCorrect(
g_KnownErrorTable[iErrorTable].dwMajorVersion,
g_KnownErrorTable[iErrorTable].dwMinorVersion,
g_KnownErrorTable[iErrorTable].dwServicePackMajor,
g_KnownErrorTable[iErrorTable].dwServicePackMinor))
{
//
// This error is old. Increase the error level.
//
dwActualErrorLevel = IncrementErrorLevel(dwActualErrorLevel);
}
}
}
return dwActualErrorLevel;
}
//
// Function: IsAPIRelevant
// Purpose: Determine if the test case supplied in the pTableEntry parameter
// is appropriate for the supplied dwCSPClass and dwTestLevel.
//
BOOL IsAPIRelevant(
IN DWORD dwCSPClass,
IN DWORD dwTestLevel,
IN DWORD dwTestType,
IN PTESTTABLEENTRY pTableEntry)
{
DWORD dwAPITestLevels = 0;
switch (dwCSPClass)
{
case CLASS_SIG_ONLY:
{
dwAPITestLevels = pTableEntry->dwClassSigOnly;
break;
}
case CLASS_SIG_KEYX:
{
dwAPITestLevels = pTableEntry->dwClassSigKeyX;
break;
}
case CLASS_FULL:
{
dwAPITestLevels = pTableEntry->dwClassFull;
break;
}
case CLASS_OPTIONAL:
{
dwAPITestLevels = pTableEntry->dwClassOptional;
break;
}
default:
{
return FALSE;
}
}
if ((dwTestType == pTableEntry->dwTestType) &&
(dwAPITestLevels & dwTestLevel))
{
return TRUE;
}
return FALSE;
}
//
// Function: InitTestCase
// Purpose: Initialize a TESTCASE structure with the most typical default
// values.
//
void InitTestCase(PTESTCASE pTestCase)
{
//
// Initialize the TESTCASE structure for this API test
//
memset(pTestCase, 0, sizeof(TESTCASE));
//
// For now, set a low-enough error level so that the test will
// continue after most failed test cases.
//
// The pTestCase->dwErrorLevel is where most of the control of the flow of the
// test (with respect to error handling) is afforded. The flags used here should
// be a function of the environment in which the test is being run, and should
// be optionally controllable by command-line.
//
pTestCase->dwErrorLevel = CSP_ERROR_CONTINUE;
pTestCase->KnownErrorID = KNOWN_ERROR_UNKNOWN;
}
//
// Function: RunTestsByClassAndLevel
// Purpose: For a given CSP Class and Test Level, run the appropriate set
// of API tests, per the test mappings in the
// g_TestFunctionMappings table.
//
BOOL RunTestsByClassAndLevel(
IN DWORD dwCSPClass,
IN DWORD dwTestLevel,
IN DWORD dwTestType,
PCSPINFO pCspInfo)
{
BOOL fErrorOccurred = FALSE;
int iAPI = 0;
//
// For each (CSP_CLASS, TEST_LEVEL) combination, run through
// each of the entries in the test table above.
//
for (
iAPI = 0;
iAPI < (sizeof(g_TestFunctionMappings) / sizeof(TESTTABLEENTRY));
++iAPI)
{
//
// Determine if the current TESTTABLEENTRY in TestFunctionMappings is
// applicable for the current (dwCSPClass, dwTestLevel) combination.
//
if (IsAPIRelevant(
dwCSPClass,
dwTestLevel,
dwTestType,
&(g_TestFunctionMappings[iAPI])))
{
if (LogBeginAPI(
g_TestFunctionMappings[iAPI].ApiName,
dwTestType))
{
//
// Initialize the test TESTCASE member of the CSPINFO struct
// to typical values.
//
InitTestCase(&(pCspInfo->TestCase));
pCspInfo->TestCase.dwTestLevel = dwTestLevel;
pCspInfo->TestCase.dwCSPClass = dwCSPClass;
pCspInfo->TestCase.fSmartCardCSP = pCspInfo->fSmartCardCSP;
if (TEST_CASES_POSITIVE == dwTestType)
{
pCspInfo->TestCase.fExpectSuccess = TRUE;
}
//
// Run the current test case
//
if (! (*(g_TestFunctionMappings[iAPI].pTestFunc))(pCspInfo))
{
fErrorOccurred = TRUE;
}
LogEndAPI(
g_TestFunctionMappings[iAPI].ApiName,
dwTestType);
}
}
}
return ! fErrorOccurred;
}
//
// Function: RunStandardTests
// Purpose: Iterate through the [CSP_CLASS, TEST_LEVEL] combinations for each
// test listed in the g_TestFunctionMappings table.
//
BOOL RunStandardTests(
IN DWORD dwTargetCSPClass,
IN DWORD dwTestType,
PCSPINFO pCspInfo)
{
BOOL fErrorOccurred = FALSE;
DWORD dwCSPClass = 0;
DWORD dwTestLevel = 0;
int iCSPClass = 0;
int iTestLevel = 0;
dwCSPClass = g_rgCspClasses[iCSPClass];
//
// Run through each possible CSP_CLASS but stop after the CSP_CLASS
// specified by the dwTargetCSPClass parameter.
//
while ( LogBeginCSPClass(dwCSPClass))
{
//
// Run through each TEST_LEVEL for the current CSP_CLASS
//
for ( iTestLevel = 0;
iTestLevel < (sizeof(g_rgTestLevels) / sizeof(dwTestLevel));
++iTestLevel)
{
dwTestLevel = g_rgTestLevels[iTestLevel];
if (LogBeginTestLevel(dwTestLevel))
{
if (! RunTestsByClassAndLevel(
dwCSPClass,
dwTestLevel,
dwTestType,
pCspInfo))
{
fErrorOccurred = TRUE;
}
LogEndTestLevel(dwTestLevel);
}
}
LogEndCSPClass(dwCSPClass);
if (dwCSPClass == dwTargetCSPClass)
{
break;
}
else
{
iCSPClass++;
dwCSPClass = g_rgCspClasses[iCSPClass];
}
}
return ! fErrorOccurred;
}
//
// Function: RunPositiveTests
// Purpose: Run all of the positive test cases for a CSP of the
// specified class.
//
BOOL RunPositiveTests(DWORD dwTargetCSPClass, PCSPINFO pCSPInfo)
{
return RunStandardTests(dwTargetCSPClass, TEST_CASES_POSITIVE, pCSPInfo);
}
//
// Function: RunNegativeTests
// Purpose: Run all of the negative test cases for a CSP of the
// specified class.
//
BOOL RunNegativeTests(DWORD dwTargetCSPClass, PCSPINFO pCSPInfo)
{
return RunStandardTests(dwTargetCSPClass, TEST_CASES_NEGATIVE, pCSPInfo);
}
//
// Function: RunScenarioTests
// Purpose: Run all of the CSP Test Suite Scenario tests.
//
BOOL RunScenarioTests(PCSPINFO pCSPInfo)
{
BOOL fErrorOccurred = FALSE;
int iScenarioTable = 0;
for (
iScenarioTable = 0;
iScenarioTable < (sizeof(g_ScenarioTestTable) / sizeof(BASIC_TEST_TABLE));
iScenarioTable++)
{
InitTestCase(&(pCSPInfo->TestCase));
pCSPInfo->TestCase.fExpectSuccess = TRUE;
pCSPInfo->TestCase.dwErrorLevel = CSP_ERROR_API;
LogBeginScenarioTest(g_ScenarioTestTable[iScenarioTable].pwszDescription);
//
// Run the current test case
//
if (! (*(g_ScenarioTestTable[iScenarioTable].pTestFunc))(pCSPInfo))
{
fErrorOccurred = TRUE;
}
LogEndScenarioTest();
}
return ! fErrorOccurred;
}
//
// Function: RunInteropTests
// Purpose: Run all of the CSP Test Suite Interoperability tests.
//
BOOL RunInteropTests(PCSPINFO pCSPInfo)
{
BOOL fErrorOccurred = FALSE;
int iInteropTable = 0;
for (
iInteropTable = 0;
iInteropTable < (sizeof(g_InteropTestTable) / sizeof(BASIC_TEST_TABLE));
iInteropTable++)
{
InitTestCase(&(pCSPInfo->TestCase));
pCSPInfo->TestCase.fExpectSuccess = TRUE;
pCSPInfo->TestCase.dwErrorLevel = CSP_ERROR_API;
LogBeginInteropTest(g_InteropTestTable[iInteropTable].pwszDescription);
//
// Run the current test case
//
if (! (*(g_InteropTestTable[iInteropTable].pTestFunc))(pCSPInfo))
{
fErrorOccurred = TRUE;
}
LogEndInteropTest();
}
return ! fErrorOccurred;
}
//
// Function: CleanupCspInfo
// Purpose: Perform any cleanup or memory-freeing necessary for the
// CSPINFO struct.
//
void CleanupCspInfo(PCSPINFO pCSPInfo)
{
PALGNODE pAlgNode = NULL;
if (pCSPInfo->pwszCSPName)
{
free(pCSPInfo->pwszCSPName);
}
//
// Free the linked ALGNODE list
//
while (pCSPInfo->pAlgList)
{
pAlgNode = pCSPInfo->pAlgList->pAlgNodeNext;
free(pCSPInfo->pAlgList);
pCSPInfo->pAlgList = pAlgNode;
}
}
//
// Function: GetProviderType
// Purpose: Given the name of the CSP under test, call CryptEnumProviders
// until that CSP is found. Return the type for that CSP to the caller.
//
BOOL GetProviderType(
IN LPWSTR pwszProvName,
OUT PDWORD pdwProvType)
{
WCHAR rgProvName [MAX_PATH * sizeof(WCHAR)];
DWORD cb = sizeof(rgProvName);
DWORD dwIndex = 0;
memset(rgProvName, 0, sizeof(rgProvName));
while (CryptEnumProviders(
dwIndex,
NULL,
0,
pdwProvType,
rgProvName,
&cb))
{
if (0 == wcscmp(rgProvName, pwszProvName))
{
return TRUE;
}
else
{
dwIndex++;
cb = sizeof(rgProvName);
}
}
return FALSE;
}
//
// Function: DeleteDefaultContainer
// Purpose: Delete the default key container for the CSP
// under test.
//
BOOL DeleteDefaultContainer(PCSPINFO pCSPInfo)
{
HCRYPTPROV hProv = 0;
return CryptAcquireContext(
&hProv,
NULL,
pCSPInfo->pwszCSPName,
pCSPInfo->dwExternalProvType,
CRYPT_DELETEKEYSET);
}
//
// Function: DeleteAllContainers
// Purpose: Delete all key containers for the CSP
// under test.
//
BOOL DeleteAllContainers(PCSPINFO pCSPInfo)
{
HCRYPTPROV hDefProv = 0;
HCRYPTPROV hProv = 0;
CHAR rgszContainer[MAX_PATH];
LPWSTR pwszContainer = NULL;
DWORD cbContainer = MAX_PATH;
BOOL fCreatedDefaultKeyset = FALSE;
DWORD dwFlags = CRYPT_FIRST;
if (! CryptAcquireContext(
&hDefProv, NULL, pCSPInfo->pwszCSPName,
pCSPInfo->dwExternalProvType, 0))
{
return FALSE;
}
while (CryptGetProvParam(
hDefProv, PP_ENUMCONTAINERS, (PBYTE) rgszContainer,
&cbContainer, dwFlags))
{
if (dwFlags)
{
dwFlags = 0;
}
pwszContainer = MkWStr(rgszContainer);
if (! CryptAcquireContext(
&hProv, pwszContainer, pCSPInfo->pwszCSPName,
pCSPInfo->dwExternalProvType, CRYPT_DELETEKEYSET))
{
return FALSE;
}
cbContainer = sizeof(rgszContainer);
free(pwszContainer);
}
if (! CryptReleaseContext(hDefProv, 0))
{
return FALSE;
}
return TRUE;
}
//
// Function: main
// Purpose: Test entry function
//
int __cdecl wmain(int argc, WCHAR *wargv[])
{
BOOL fInvalidArgs = FALSE;
int iCspTypeTable = 0;
DWORD dwTestsToRun = TEST_CASES_POSITIVE;
BOOL fDeleteDefaultContainer = FALSE;
int iCsp = 0;
DWORD dwProvType = 0;
DWORD cbCspName = 0;
DWORD dwError = 0;
WCHAR rgwszCsp[ MAX_PATH ];
WCHAR rgwszOption[ MAX_PATH ];
WCHAR rgwsz[BUFFER_SIZE];
CSPINFO CspInfo;
LOGINIT_INFO LogInitInfo;
BOOL fDeleteAllContainers = FALSE;
memset(&CspInfo, 0, sizeof(CspInfo));
memset(&LogInitInfo, 0, sizeof(LogInitInfo));
if (argc < MINIMUM_ARGC)
{
fInvalidArgs = TRUE;
goto Ret;
}
argc--;
wargv++;
while (argc)
{
if (L'-' != wargv[0][0])
{
fInvalidArgs = TRUE;
goto Ret;
}
switch (wargv[0][1])
{
case L't':
{
// Assign which test to run
--argc;
++wargv;
dwTestsToRun = _wtoi(*wargv);
break;
}
case L'c':
{
// Assign CSP Name
--argc;
++wargv;
cbCspName = 0;
GetNextRegisteredCSP(
NULL,
&cbCspName,
&(CspInfo.dwExternalProvType),
_wtoi(*wargv));
if (NULL == (CspInfo.pwszCSPName = (LPWSTR) malloc(cbCspName)))
{
wprintf(L"Insufficient memory\n");
goto Ret;
}
dwError = GetNextRegisteredCSP(
CspInfo.pwszCSPName,
&cbCspName,
&(CspInfo.dwExternalProvType),
_wtoi(*wargv));
if (ERROR_SUCCESS != dwError)
{
fInvalidArgs = TRUE;
goto Ret;
}
break;
}
case L'i':
{
// Assign interop CSP name
--argc;
++wargv;
cbCspName = 0;
GetNextRegisteredCSP(
NULL,
&cbCspName,
&(LogInitInfo.dwInteropCSPExternalType),
_wtoi(*wargv));
if (NULL == (LogInitInfo.pwszInteropCSPName = (LPWSTR) malloc(cbCspName)))
{
wprintf(L"Insufficient memory\n");
goto Ret;
}
dwError = GetNextRegisteredCSP(
LogInitInfo.pwszInteropCSPName,
&cbCspName,
&(LogInitInfo.dwInteropCSPExternalType),
_wtoi(*wargv));
if (ERROR_SUCCESS != dwError)
{
fInvalidArgs = TRUE;
goto Ret;
}
break;
}
case L'd':
{
// Option to delete the default container
fDeleteDefaultContainer = TRUE;
break;
}
case L'a':
{
// Option to delete all containers
fDeleteAllContainers = TRUE;
break;
}
default:
{
fInvalidArgs = TRUE;
goto Ret;
}
}
argc--;
wargv++;
}
if ( (0 != argc) ||
(NULL == CspInfo.pwszCSPName))
{
// Bad combination of args
fInvalidArgs = TRUE;
goto Ret;
}
//
// If no interop CSP was specified, look for a default
//
if ( TEST_CASES_INTEROP == dwTestsToRun &&
NULL == LogInitInfo.pwszInteropCSPName)
{
if (! CryptGetDefaultProvider(
CspInfo.dwExternalProvType,
NULL,
CRYPT_MACHINE_DEFAULT,
NULL,
&cbCspName))
{
printf("No default interop provider found for this CSP type\n");
fInvalidArgs = TRUE;
goto Ret;
}
if (NULL == (LogInitInfo.pwszInteropCSPName = (LPWSTR) malloc(cbCspName)))
{
wprintf(L"Insufficient memory\n");
goto Ret;
}
if (! CryptGetDefaultProvider(
CspInfo.dwExternalProvType,
NULL,
CRYPT_MACHINE_DEFAULT,
LogInitInfo.pwszInteropCSPName,
&cbCspName))
{
printf("No default interop provider found for this CSP type\n");
fInvalidArgs = TRUE;
goto Ret;
}
LogInitInfo.dwInteropCSPExternalType = CspInfo.dwExternalProvType;
}
//
// Search for an entry for the external CSP type in the test suite
// CspTypeTable. The table provides mappings from external types to
// internal types used by the test.
//
while ( iCspTypeTable < (sizeof(g_CspTypeTable) / sizeof(CSPTYPEMAP)) &&
g_CspTypeTable[iCspTypeTable].dwExternalProvType != CspInfo.dwExternalProvType)
{
iCspTypeTable++;
}
//
// Check that the CSP type was found in the g_CspTypeTable
//
if (iCspTypeTable == (sizeof(g_CspTypeTable) / sizeof(CSPTYPEMAP)))
{
fInvalidArgs = TRUE;
goto Ret;
}
CspInfo.dwInternalProvType = g_CspTypeTable[iCspTypeTable].dwProvType;
CspInfo.dwCSPInternalClass = g_CspTypeTable[iCspTypeTable].dwCSPClass;
LogInitInfo.dwCSPExternalType = CspInfo.dwExternalProvType;
LogInitInfo.dwCSPInternalClass = g_CspTypeTable[iCspTypeTable].dwCSPClass;
LogInitInfo.dwCSPInternalType = g_CspTypeTable[iCspTypeTable].dwProvType;
LogInitInfo.pwszCSPName = CspInfo.pwszCSPName;
// Initialize logging routines
LogInit(&LogInitInfo);
//
// Log the settings being used (including command-line
// options that were specified).
//
swprintf(
rgwszOption,
L"CSP under test: %s",
CspInfo.pwszCSPName);
LogUserOption(rgwszOption);
swprintf(
rgwszOption,
L"CSP type: %s",
g_CspTypeTable[iCspTypeTable].pwszExternalProvType);
LogUserOption(rgwszOption);
if (TEST_CASES_INTEROP == dwTestsToRun)
{
swprintf(
rgwszOption,
L"Interop CSP: %s",
LogInitInfo.pwszInteropCSPName);
LogUserOption(rgwszOption);
}
TestCaseTypeToString(dwTestsToRun, rgwsz);
swprintf(
rgwszOption,
L"Test case set: %s",
rgwsz);
LogUserOption(rgwszOption);
//
// Delete default container, if requested
//
if (fDeleteDefaultContainer)
{
LogInfo(L"Deleting default container...");
if (DeleteDefaultContainer(&CspInfo))
{
LogInfo(L"...Success");
}
else
{
swprintf(
rgwszOption,
L"...Failed 0x%x",
GetLastError());
LogInfo(rgwszOption);
}
LogClose();
goto Ret;
}
//
// Delete all containers, if requested
//
if (fDeleteAllContainers)
{
LogInfo(L"Deleting all containers...");
if (DeleteAllContainers(&CspInfo))
{
LogInfo(L"...Success");
}
else
{
swprintf(
rgwszOption,
L"...Failed 0x%x",
GetLastError());
LogInfo(rgwszOption);
}
LogClose();
goto Ret;
}
//
// Run the set of tests requested by the user
//
switch (dwTestsToRun)
{
case TEST_CASES_POSITIVE:
{
RunPositiveTests(
g_CspTypeTable[iCspTypeTable].dwCSPClass,
&CspInfo);
break;
}
case TEST_CASES_NEGATIVE:
{
RunNegativeTests(
g_CspTypeTable[iCspTypeTable].dwCSPClass,
&CspInfo);
break;
}
case TEST_CASES_SCENARIO:
{
RunScenarioTests(&CspInfo);
break;
}
case TEST_CASES_INTEROP:
{
RunInteropTests(&CspInfo);
break;
}
}
LogClose();
Ret:
CleanupCspInfo(&CspInfo);
if (LogInitInfo.pwszInteropCSPName)
{
free(LogInitInfo.pwszInteropCSPName);
}
if (fInvalidArgs)
{
Usage();
wprintf(L"\nRegistered CSP's:\n");
cbCspName = MAX_PATH;
for ( iCsp = 0;
ERROR_SUCCESS == GetNextRegisteredCSP(
rgwszCsp,
&cbCspName,
&dwProvType,
ENUMERATE_REGISTERED_CSP);
iCsp++)
{
wprintf(L" %d: %s, Type %d\n", iCsp, rgwszCsp, dwProvType);
}
exit(1);
}
return 0;
}