|
|
/*
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; }
|