Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

550 lines
13 KiB

//
// Utils.c
//
// 7/6/00 dangriff created
//
#include <windows.h>
#include <wincrypt.h>
#include <stdio.h>
#include "utils.h"
#include "cspstruc.h"
#include "csptestsuite.h"
#include "logging.h"
//
// Function: BuildAlgList
//
BOOL BuildAlgList(HCRYPTPROV hProv, PCSPINFO pCSPInfo)
{
DWORD cb = 0;
DWORD dwFlags = 0;
PALGNODE pAlgNode = NULL;
PTESTCASE ptc = &(pCSPInfo->TestCase);
PROV_ENUMALGS_EX ProvEnumalgsEx;
// Enumerate all supported algs
dwFlags = CRYPT_FIRST;
cb = sizeof(ProvEnumalgsEx);
memset(&ProvEnumalgsEx, 0, cb);
LogTestCaseSeparator(FALSE); // Log a blank line first
LogInfo(L"CryptGetProvParam PP_ENUMALGS_EX: enumerating supported algorithms");
while (CryptGetProvParam(
hProv,
PP_ENUMALGS_EX,
(PBYTE) &ProvEnumalgsEx,
&cb,
dwFlags))
{
// Increment the test case counter for every enumerated alg
++ptc->dwTestCaseID;
if (NULL == pCSPInfo->pAlgList)
{
//
// Allocate first node at user's pointer
//
LOG_TRY(TestAlloc(
&((PBYTE) pCSPInfo->pAlgList),
sizeof(ALGNODE),
ptc));
pAlgNode = pCSPInfo->pAlgList;
}
else
{
//
// Add another node to the list
//
LOG_TRY(TestAlloc(
&((PBYTE) pAlgNode->pAlgNodeNext),
sizeof(ALGNODE),
ptc));
pAlgNode = pAlgNode->pAlgNodeNext;
}
// Zero out the ALGNODE struct
memset(pAlgNode, 0, sizeof(ALGNODE));
// Copy the ProvEnumalgsEx data into the ALGNODE struct
memcpy(&(pAlgNode->ProvEnumalgsEx), &ProvEnumalgsEx, cb);
//
// We just need to know if the current algorithm is considered "known"
// by the Test Suite. First, search through the list of REQUIRED algs,
// and assume that all REQUIRED algs are also KNOWN.
//
if (TRUE == (pAlgNode->fIsRequiredAlg =
IsRequiredAlg(
ProvEnumalgsEx.aiAlgid,
pCSPInfo->dwExternalProvType)))
{
pAlgNode->fIsKnownAlg = TRUE;
}
else
{
//
// Now search through the remaining KNOWN, non-required, algorithms
//
pAlgNode->fIsKnownAlg =
IsKnownAlg(
ProvEnumalgsEx.aiAlgid,
pCSPInfo->dwExternalProvType);
}
if (CRYPT_FIRST == dwFlags)
{
dwFlags = 0;
}
LogProvEnumalgsEx(&ProvEnumalgsEx);
}
if (ERROR_NO_MORE_ITEMS != GetLastError())
{
ptc->dwErrorCode = ERROR_NO_MORE_ITEMS;
ptc->fExpectSuccess = FALSE;
ptc->pwszErrorHelp = L"CryptGetProvParam PP_ENUMALGS_EX: Wrong error code returned at end of enumeration";
//
// Log a FAIL
//
return CheckAndLogStatus(
API_CRYPTGETPROVPARAM,
FALSE,
ptc,
NULL,
0);
}
//
// Log a PASS
//
/*
return CheckAndLogStatus(
API_CRYPTGETPROVPARAM,
TRUE,
ptc,
NULL,
0);
*/
return TRUE;
Cleanup:
return FALSE;
}
//
// Function: CreateNewInteropContext
//
BOOL CreateNewInteropContext(
OUT HCRYPTPROV *phProv,
IN LPWSTR pwszContainer,
IN DWORD dwFlags,
IN PTESTCASE ptc)
{
BOOL fSuccess = FALSE;
//DWORD dwError = 0;
DWORD dwProvType = LogGetInteropProvType();
LPWSTR pwszProvName = LogGetInteropProvName();
BOOL fSavedExpectSuccess = ptc->fExpectSuccess;
DWORD dwSavedErrorLevel = ptc->dwErrorLevel;
//
// All calls to CreateNewInteropContext are considered critical, since
// they are typically followed by additional dependent test code. Set a high
// failure rate for this reason.
//
ptc->dwErrorLevel = CSP_ERROR_API;
ptc->fExpectSuccess = TRUE;
if (CRYPT_VERIFYCONTEXT != (dwFlags & CRYPT_VERIFYCONTEXT))
{
TAcquire(
phProv,
pwszContainer,
pwszProvName,
dwProvType,
CRYPT_DELETEKEYSET,
ptc);
dwFlags &= CRYPT_NEWKEYSET;
}
fSuccess = TAcquire(
phProv,
pwszContainer,
pwszProvName,
dwProvType,
dwFlags,
ptc);
ptc->dwErrorLevel = dwSavedErrorLevel;
ptc->fExpectSuccess = fSavedExpectSuccess;
return fSuccess;
}
//
// Function: CreateNewContext
//
BOOL CreateNewContext(
OUT HCRYPTPROV *phProv,
IN LPWSTR pwszContainer,
IN DWORD dwFlags,
IN PTESTCASE ptc)
{
BOOL fSuccess = FALSE;
//DWORD dwError = 0;
DWORD dwProvType = LogGetProvType();
LPWSTR pwszProvName = LogGetProvName();
BOOL fSavedExpectSuccess = ptc->fExpectSuccess;
DWORD dwSavedErrorLevel = ptc->dwErrorLevel;
//
// All calls to CreateNewContext are considered critical, since
// they are typically followed by additional dependent test code. Set a high
// failure rate for this reason.
//
ptc->dwErrorLevel = CSP_ERROR_API;
ptc->fExpectSuccess = TRUE;
if ( ! (dwFlags & CRYPT_VERIFYCONTEXT))
{
//
// Call the CryptAcquireContext API directly (instead of
// TAcquire) since this key container may not already exist.
//
if (dwFlags & CRYPT_MACHINE_KEYSET)
{
CryptAcquireContext(
phProv,
pwszContainer,
pwszProvName,
dwProvType,
CRYPT_DELETEKEYSET | CRYPT_MACHINE_KEYSET);
}
else
{
CryptAcquireContext(
phProv,
pwszContainer,
pwszProvName,
dwProvType,
CRYPT_DELETEKEYSET);
}
if (FALSE == ptc->fTestingUserProtected &&
FALSE == ptc->fSmartCardCSP)
{
//
// Unless the above flag is set, all non-VERIFYCONTEXT context handles
// will be created with with the CRYPT_SILENT flag in order to
// maximize the test exposure to this flag.
//
dwFlags |= CRYPT_SILENT;
}
}
fSuccess = TAcquire(
phProv,
pwszContainer,
pwszProvName,
dwProvType,
dwFlags,
ptc);
ptc->dwErrorLevel = dwSavedErrorLevel;
ptc->fExpectSuccess = fSavedExpectSuccess;
return fSuccess;
}
//
// Function: CreateNewKey
//
BOOL CreateNewKey(
IN HCRYPTPROV hProv,
IN ALG_ID Algid,
IN DWORD dwFlags,
OUT HCRYPTKEY *phKey,
IN PTESTCASE ptc)
{
BOOL fSuccess = FALSE;
//DWORD dwError = 0;
BOOL fSavedExpectSuccess = ptc->fExpectSuccess;
DWORD dwSavedErrorLevel = ptc->dwErrorLevel;
//
// All calls to CreateNewKey are considered critical, since
// they are typically followed by additional dependent test code. Set a high
// failure rate for the next CSP call for this reason.
//
ptc->dwErrorLevel = CSP_ERROR_API;
ptc->fExpectSuccess = TRUE;
fSuccess = TGenKey(
hProv,
Algid,
dwFlags,
phKey,
ptc);
ptc->dwErrorLevel = dwSavedErrorLevel;
ptc->fExpectSuccess = fSavedExpectSuccess;
return fSuccess;
}
//
// Function: CreateNewHash
//
BOOL CreateNewHash(
IN HCRYPTPROV hProv,
IN ALG_ID Algid,
OUT HCRYPTHASH *phHash,
IN PTESTCASE ptc)
{
BOOL fSuccess = FALSE;
//DWORD dwError = 0;
BOOL fSavedExpectSuccess = ptc->fExpectSuccess;
DWORD dwSavedErrorLevel = ptc->dwErrorLevel;
//
// All calls to CreateNewHash are considered critical, since
// they are typically followed by additional dependent test code. Set a high
// failure rate for the next CSP call for this reason.
//
ptc->dwErrorLevel = CSP_ERROR_API;
ptc->fExpectSuccess = TRUE;
fSuccess = TCreateHash(
hProv,
Algid,
0, // hKey
0, // dwFlags
phHash,
ptc);
ptc->dwErrorLevel = dwSavedErrorLevel;
ptc->fExpectSuccess = fSavedExpectSuccess;
return fSuccess;
}
//
// Function: TestAlloc
//
BOOL TestAlloc(OUT PBYTE *ppb, IN DWORD cb, PTESTCASE ptc)
{
if (NULL == (*ppb = (PBYTE) malloc(cb)))
{
LogApiFailure(
API_MEMORY,
ERROR_API_FAILED,
ptc);
return FALSE;
}
memset(*ppb, 0, cb);
return TRUE;
}
//
// Function: AlgListIterate
//
BOOL AlgListIterate(
IN PALGNODE pAlgList,
IN PFN_ALGNODE_FILTER pfnFilter,
IN PFN_ALGNODE_PROC pfnProc,
IN PVOID pvProcData,
IN PTESTCASE ptc)
{
BOOL fErrorOccurred = FALSE;
PALGNODE pAlgNode = NULL;
for (pAlgNode = pAlgList; pAlgNode != NULL; pAlgNode = pAlgNode->pAlgNodeNext)
{
if ( ((*pfnFilter)(pAlgNode)) )
{
if (! ((*pfnProc)(pAlgNode, ptc, pvProcData)) )
{
fErrorOccurred = TRUE;
}
}
}
if (fErrorOccurred)
{
return FALSE;
}
else
{
return TRUE;
}
}
//
// Function: HashAlgFilter
//
BOOL HashAlgFilter(PALGNODE pAlgNode)
{
if ( (ALG_CLASS_HASH == GET_ALG_CLASS(pAlgNode->ProvEnumalgsEx.aiAlgid)) &&
pAlgNode->fIsKnownAlg)
{
return ! MacAlgFilter(pAlgNode);
}
return FALSE;
}
//
// Function: MacAlgFilter
//
BOOL MacAlgFilter(PALGNODE pAlgNode)
{
if ( ((CALG_MAC == pAlgNode->ProvEnumalgsEx.aiAlgid) ||
(CALG_HMAC == pAlgNode->ProvEnumalgsEx.aiAlgid)) &&
pAlgNode->fIsKnownAlg)
{
return TRUE;
}
else
{
return FALSE;
}
}
//
// Function: BlockCipherFilter
//
BOOL BlockCipherFilter(PALGNODE pAlgNode)
{
if ( (ALG_TYPE_BLOCK == GET_ALG_TYPE(pAlgNode->ProvEnumalgsEx.aiAlgid)) &&
pAlgNode->fIsKnownAlg)
{
return TRUE;
}
else
{
return FALSE;
}
}
//
// Function: DataEncryptFilter
//
BOOL DataEncryptFilter(PALGNODE pAlgNode)
{
if ( (ALG_CLASS_DATA_ENCRYPT == GET_ALG_CLASS(pAlgNode->ProvEnumalgsEx.aiAlgid)) &&
pAlgNode->fIsKnownAlg)
{
return TRUE;
}
else
{
return FALSE;
}
}
//
// Function: AllEncryptionAlgsFilter
// Purpose: Same algorithm set as DataEncryptFilter above,
// with the addition of the RSA key-exchange alg.
//
BOOL AllEncryptionAlgsFilter(PALGNODE pAlgNode)
{
return (CALG_RSA_KEYX == pAlgNode->ProvEnumalgsEx.aiAlgid) ||
DataEncryptFilter(pAlgNode);
}
//
// Function: RSAAlgFilter
//
BOOL RSAAlgFilter(PALGNODE pAlgNode)
{
return (CALG_RSA_KEYX == pAlgNode->ProvEnumalgsEx.aiAlgid) ||
(CALG_RSA_SIGN == pAlgNode->ProvEnumalgsEx.aiAlgid);
}
//
// Function: PrintBytes
//
#define CROW 8
void PrintBytes(LPWSTR pwszHdr, BYTE *pb, DWORD cbSize)
{
ULONG cb, i;
WCHAR rgwsz[1024];
wsprintf(rgwsz, L" %s, %d bytes ::", pwszHdr, cbSize);
LogInfo(rgwsz);
while (cbSize > 0)
{
// Start every row with an extra space
wsprintf(rgwsz, L" ");
cb = min(CROW, cbSize);
cbSize -= cb;
for (i = 0; i < cb; i++)
wsprintf(rgwsz + wcslen(rgwsz), L" %02x", pb[i]);
for (i = cb; i < CROW; i++)
wsprintf(rgwsz + wcslen(rgwsz), L" ");
wsprintf(rgwsz + wcslen(rgwsz), L" '");
for (i = 0; i < cb; i++)
{
if (pb[i] >= 0x20 && pb[i] <= 0x7f)
wsprintf(rgwsz + wcslen(rgwsz), L"%c", pb[i]);
else
wsprintf(rgwsz + wcslen(rgwsz), L".");
}
LogInfo(rgwsz);
pb += cb;
}
}
//
// Function: MkWStr
//
LPWSTR MkWStr(LPSTR psz)
{
int cWChars = 0;
LPWSTR pwsz = NULL;
if (psz == NULL)
{
return NULL;
}
cWChars = MultiByteToWideChar(
0,
0,
psz,
-1,
NULL,
0);
if (NULL == (pwsz = (LPWSTR) malloc(cWChars * sizeof(WCHAR))))
{
return NULL;
}
MultiByteToWideChar(
0,
0,
psz,
-1,
pwsz,
cWChars);
return(pwsz);
}