windows-nt/Source/XPSP1/NT/ds/win32/ntcrypto/test/stress/strestst.c

4652 lines
122 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
// *****************************************************************************
//
// Purpose : Multithreaded stress test
//
// Created : arunm 03/20/96
// Modified: dangriff 11/6/00
//
// *****************************************************************************
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <wincrypt.h>
#include "strestst.h"
#include <pincache.h>
// ===========================================================================
int Usage(void)
{
printf("%s -c <CSP Index> [options]\n", APP_NAME) ;
printf(" -?: This message\n") ;
printf(" -n <N>: # of threads to create (Def: %d)\n", StressGetDefaultThreadCount());
printf(" -t <N>: End test in N minutes (Def: never end)\n");
printf(" -e: Ephemeral keys\n");
printf(" -u: User-protected keys (cannot be used with -e)\n");
printf(" -r: Run regression tests\n");
printf(" -d: Delete all key containers\n");
printf(" -a<Flags> <Container>: Call CryptAcquireContext with Flags\n");
printf("\nCryptAcquireContext Flags:\n");
printf(" v - CRYPT_VERIFYCONTEXT (don't specify <Container>)\n");
printf(" n - CRYPT_NEWKEYSET\n");
printf(" l - CRYPT_MACHINE_KEYSET\n");
printf(" d - CRYPT_DELETEKEYSET\n");
printf(" q - CRYPT_SILENT\n");
printf(" x - create a Key Exchange keyset\n");
printf(" s - create a Signature keyset\n");
printf(" u - request keyset to be User Protected\n");
return 1;
}
//
// Function: StressGetDefaultThreadCount
//
DWORD StressGetDefaultThreadCount(void)
{
SYSTEM_INFO SystemInfo;
ZeroMemory(&SystemInfo, sizeof(SystemInfo));
GetSystemInfo(&SystemInfo);
return
SystemInfo.dwNumberOfProcessors == 1 ?
STRESS_DEFAULT_THREAD_COUNT :
SystemInfo.dwNumberOfProcessors;
}
//
// Function: MyAlloc
//
LPVOID MyAlloc(SIZE_T dwBytes)
{
return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytes);
}
//
// Function: MyFree
//
BOOL MyFree(LPVOID lpMem)
{
return HeapFree(GetProcessHeap(), 0, lpMem);
}
//
// Function: PrintBytes
//
#define CROW 8
void PrintBytes(LPSTR pszHdr, BYTE *pb, DWORD cbSize)
{
ULONG cb, i;
CHAR rgsz[1024];
printf("\n %s, %d bytes ::\n", pszHdr, cbSize);
while (cbSize > 0)
{
// Start every row with an extra space
printf(" ");
cb = min(CROW, cbSize);
cbSize -= cb;
for (i = 0; i < cb; i++)
printf(" %02x", pb[i]);
for (i = cb; i < CROW; i++)
printf(" ");
printf(" '");
for (i = 0; i < cb; i++)
{
if (pb[i] >= 0x20 && pb[i] <= 0x7f)
printf("%c", pb[i]);
else
printf(".");
}
printf("\n");
pb += cb;
}
}
//
// Function: UnalignedImportExportRegression
//
DWORD UnalignedImportExportRegression(PTHREAD_DATA pThreadData)
{
DWORD dwError = ERROR_SUCCESS;
BYTE rgbKeyBuf[2000];
DWORD cbKeyBuf = sizeof(rgbKeyBuf);
PBYTE pbKeyBuf = NULL;
HCRYPTKEY hKey = 0;
HCRYPTKEY hWrapKey = 0;
BOOL fSuccess = FALSE;
if (! CryptGenKey(
pThreadData->hProv, CALG_RC2, 0, &hWrapKey))
{
printf("CryptGenKey CALG_RC2 ");
goto Ret;
}
//
// 1a) Exchange key pair PRIVATEKEYBLOB
//
// Unalign the output buffer
pbKeyBuf = rgbKeyBuf + 1;
cbKeyBuf = sizeof(rgbKeyBuf) - 1;
if (! CryptExportKey(
pThreadData->hExchangeKey, 0, PRIVATEKEYBLOB, 0, pbKeyBuf, &cbKeyBuf))
{
printf("CryptExportKey KeyEx PRIVATEKEYBLOB ");
goto Ret;
}
if (! CryptImportKey(
pThreadData->hProv, pbKeyBuf, cbKeyBuf, 0, CRYPT_EXPORTABLE, &hKey))
{
printf("CryptImportKey KeyEx PRIVATEKEYBLOB ");
goto Ret;
}
if (! CryptDestroyKey(hKey))
{
printf("CryptDestroyKey KeyEx PRIVATEKEYBLOB ");
goto Ret;
}
//
// 1b) Exchange key pair PRIVATEKEYBLOB, encrypted
//
// Unalign the output buffer
pbKeyBuf = rgbKeyBuf + 1;
cbKeyBuf = sizeof(rgbKeyBuf) - 1;
if (! CryptExportKey(
pThreadData->hExchangeKey,
hWrapKey,
PRIVATEKEYBLOB,
0,
pbKeyBuf,
&cbKeyBuf))
{
printf("CryptExportKey KeyEx PRIVATEKEYBLOB b ");
goto Ret;
}
if (! CryptImportKey(
pThreadData->hProv,
pbKeyBuf,
cbKeyBuf,
hWrapKey,
CRYPT_EXPORTABLE,
&hKey))
{
printf("CryptImportKey KeyEx PRIVATEKEYBLOB b ");
goto Ret;
}
if (! CryptDestroyKey(hKey))
{
printf("CryptDestroyKey KeyEx PRIVATEKEYBLOB b ");
goto Ret;
}
//
// 2) Exchange key pair PUBLICKEYBLOB
//
// Unalign the output buffer
pbKeyBuf = rgbKeyBuf + 1;
cbKeyBuf = sizeof(rgbKeyBuf) - 1;
if (! CryptExportKey(
pThreadData->hExchangeKey, 0, PUBLICKEYBLOB, 0, pbKeyBuf, &cbKeyBuf))
{
printf("CryptExportKey KeyEx PUBLICKEYBLOB ");
goto Ret;
}
if (! CryptImportKey(
pThreadData->hProv,
pbKeyBuf,
cbKeyBuf,
pThreadData->dwProvType == PROV_DSS_DH ? pThreadData->hExchangeKey : 0,
0,
&hKey))
{
printf("CryptImportKey KeyEx PUBLICKEYBLOB ");
goto Ret;
}
if (! CryptDestroyKey(hKey))
{
printf("CryptDestroyKey KeyEx PUBLICKEYBLOB ");
goto Ret;
}
//
// 3a) Signature key pair PRIVATEKEYBLOB
//
// Unalign the output buffer
pbKeyBuf = rgbKeyBuf + 1;
cbKeyBuf = sizeof(rgbKeyBuf) - 1;
if (! CryptExportKey(
pThreadData->hSignatureKey, 0, PRIVATEKEYBLOB, 0, pbKeyBuf, &cbKeyBuf))
{
printf("CryptExportKey Sig PRIVATEKEYBLOB ");
goto Ret;
}
if (! CryptImportKey(
pThreadData->hProv, pbKeyBuf, cbKeyBuf, 0, CRYPT_EXPORTABLE, &hKey))
{
printf("CryptImportKey Sig PRIVATEKEYBLOB ");
goto Ret;
}
if (! CryptDestroyKey(hKey))
{
printf("CryptDestroyKey Sig PRIVATEKEYBLOB ");
goto Ret;
}
//
// 3b) Signature key pair PRIVATEKEYBLOB, encrypted
//
// Unalign the output buffer
pbKeyBuf = rgbKeyBuf + 1;
cbKeyBuf = sizeof(rgbKeyBuf) - 1;
if (! CryptExportKey(
pThreadData->hSignatureKey,
hWrapKey,
PRIVATEKEYBLOB,
0,
pbKeyBuf,
&cbKeyBuf))
{
printf("CryptExportKey Sig PRIVATEKEYBLOB b ");
goto Ret;
}
if (! CryptImportKey(
pThreadData->hProv,
pbKeyBuf,
cbKeyBuf,
hWrapKey,
CRYPT_EXPORTABLE,
&hKey))
{
printf("CryptImportKey Sig PRIVATEKEYBLOB b ");
goto Ret;
}
if (! CryptDestroyKey(hKey))
{
printf("CryptDestroyKey Sig PRIVATEKEYBLOB b ");
goto Ret;
}
if (! CryptDestroyKey(hWrapKey))
{
printf("CryptDestroyKey CALG_RC2 ");
goto Ret;
}
//
// 4) Signature key pair PUBLICKEYBLOB
//
// Unalign the output buffer
pbKeyBuf = rgbKeyBuf + 1;
cbKeyBuf = sizeof(rgbKeyBuf) - 1;
if (! CryptExportKey(
pThreadData->hSignatureKey, 0, PUBLICKEYBLOB, 0, pbKeyBuf, &cbKeyBuf))
{
printf("CryptExportKey Sig PUBLICKEYBLOB ");
goto Ret;
}
if (! CryptImportKey(
pThreadData->hProv, pbKeyBuf, cbKeyBuf, 0, 0, &hKey))
{
printf("CryptImportKey Sig PUBLICKEYBLOB ");
goto Ret;
}
if (! CryptDestroyKey(hKey))
{
printf("CryptDestroyKey Sig PUBLICKEYBLOB ");
goto Ret;
}
//
// 5) SIMPLEBLOB
//
if (pThreadData->dwProvType != PROV_DSS_DH &&
pThreadData->dwProvType != PROV_DSS)
{
if (! CryptGenKey(
pThreadData->hProv, CALG_RC2, CRYPT_EXPORTABLE, &hKey))
{
printf("CryptGenKey CALG_RC2 SIMPLEBLOB ");
goto Ret;
}
// Unalign the output buffer
pbKeyBuf = rgbKeyBuf + 1;
cbKeyBuf = sizeof(rgbKeyBuf) - 1;
if (! CryptExportKey(
hKey, pThreadData->hExchangeKey, SIMPLEBLOB, 0, pbKeyBuf, &cbKeyBuf))
{
printf("CryptExportKey SIMPLEBLOB ");
goto Ret;
}
if (! CryptDestroyKey(hKey))
{
printf("CryptDestroyKey CALG_RC2 A SIMPLEBLOB ");
goto Ret;
}
if (! CryptImportKey(
pThreadData->hProv, pbKeyBuf, cbKeyBuf, pThreadData->hExchangeKey, 0, &hKey))
{
printf("CryptImportKey SIMPLEBLOB ");
goto Ret;
}
if (! CryptDestroyKey(hKey))
{
printf("CryptDestroyKey CALG_RC2 B SIMPLEBLOB ");
goto Ret;
}
}
//
// 6) SYMMETRICWRAPKEYBLOB
//
if (! CryptGenKey(
pThreadData->hProv, CALG_RC2, CRYPT_EXPORTABLE, &hKey))
{
printf("CryptGenKey CALG_RC2 SYMMETRICWRAPKEYBLOB A ");
goto Ret;
}
if (! CryptGenKey(
pThreadData->hProv, CALG_RC2, CRYPT_EXPORTABLE, &hWrapKey))
{
printf("CryptGenKey CALG_RC2 SYMMETRICWRAPKEYBLOB B ");
goto Ret;
}
// Unalign the output buffer
pbKeyBuf = rgbKeyBuf + 1;
cbKeyBuf = sizeof(rgbKeyBuf) - 1;
if (! CryptExportKey(
hKey, hWrapKey, SYMMETRICWRAPKEYBLOB, 0, pbKeyBuf, &cbKeyBuf))
{
printf("CryptExportKey SYMMETRICWRAPKEYBLOB ");
goto Ret;
}
if (! CryptDestroyKey(hKey))
{
printf("CryptDestroyKey CALG_RC2 A SYMMETRICWRAPKEYBLOB ");
goto Ret;
}
if (! CryptImportKey(
pThreadData->hProv, pbKeyBuf, cbKeyBuf, hWrapKey, 0, &hKey))
{
printf("CryptImportKey SYMMETRICWRAPKEYBLOB ");
goto Ret;
}
if (! CryptDestroyKey(hKey))
{
printf("CryptDestroyKey CALG_RC2 B SYMMETRICWRAPKEYBLOB ");
goto Ret;
}
if (! CryptDestroyKey(hWrapKey))
{
printf("CryptDestroyKey CALG_RC2 C SYMMETRICWRAPKEYBLOB ");
goto Ret;
}
//
// 7) PLAINTEXTKEYBLOB
//
if (! CryptGenKey(
pThreadData->hProv, CALG_RC2, CRYPT_EXPORTABLE, &hKey))
{
printf("CryptGenKey CALG_RC2 PLAINTEXTKEYBLOB ");
goto Ret;
}
// Unalign the output buffer
pbKeyBuf = rgbKeyBuf + 1;
cbKeyBuf = sizeof(rgbKeyBuf) - 1;
if (! CryptExportKey(
hKey, 0, PLAINTEXTKEYBLOB, 0, pbKeyBuf, &cbKeyBuf))
{
printf("CryptExportKey PLAINTEXTKEYBLOB ");
goto Ret;
}
if (! CryptDestroyKey(hKey))
{
printf("CryptDestroyKey CALG_RC2 A PLAINTEXTKEYBLOB ");
goto Ret;
}
if (! CryptImportKey(
pThreadData->hProv, pbKeyBuf, cbKeyBuf, 0, 0, &hKey))
{
printf("CryptImportKey PLAINTEXTKEYBLOB ");
goto Ret;
}
if (! CryptDestroyKey(hKey))
{
printf("CryptDestroyKey CALG_RC2 B PLAINTEXTKEYBLOB ");
goto Ret;
}
fSuccess = TRUE;
Ret:
if (! fSuccess)
printf("- error 0x%x\n", dwError = GetLastError());
return dwError;
}
static BYTE rgbPrivateKeyWithExponentOfOne[] =
{
0x07, 0x02, 0x00, 0x00, 0x00, 0xA4, 0x00, 0x00,
0x52, 0x53, 0x41, 0x32, 0x00, 0x02, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0xAB, 0xEF, 0xFA, 0xC6,
0x7D, 0xE8, 0xDE, 0xFB, 0x68, 0x38, 0x09, 0x92,
0xD9, 0x42, 0x7E, 0x6B, 0x89, 0x9E, 0x21, 0xD7,
0x52, 0x1C, 0x99, 0x3C, 0x17, 0x48, 0x4E, 0x3A,
0x44, 0x02, 0xF2, 0xFA, 0x74, 0x57, 0xDA, 0xE4,
0xD3, 0xC0, 0x35, 0x67, 0xFA, 0x6E, 0xDF, 0x78,
0x4C, 0x75, 0x35, 0x1C, 0xA0, 0x74, 0x49, 0xE3,
0x20, 0x13, 0x71, 0x35, 0x65, 0xDF, 0x12, 0x20,
0xF5, 0xF5, 0xF5, 0xC1, 0xED, 0x5C, 0x91, 0x36,
0x75, 0xB0, 0xA9, 0x9C, 0x04, 0xDB, 0x0C, 0x8C,
0xBF, 0x99, 0x75, 0x13, 0x7E, 0x87, 0x80, 0x4B,
0x71, 0x94, 0xB8, 0x00, 0xA0, 0x7D, 0xB7, 0x53,
0xDD, 0x20, 0x63, 0xEE, 0xF7, 0x83, 0x41, 0xFE,
0x16, 0xA7, 0x6E, 0xDF, 0x21, 0x7D, 0x76, 0xC0,
0x85, 0xD5, 0x65, 0x7F, 0x00, 0x23, 0x57, 0x45,
0x52, 0x02, 0x9D, 0xEA, 0x69, 0xAC, 0x1F, 0xFD,
0x3F, 0x8C, 0x4A, 0xD0,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x64, 0xD5, 0xAA, 0xB1,
0xA6, 0x03, 0x18, 0x92, 0x03, 0xAA, 0x31, 0x2E,
0x48, 0x4B, 0x65, 0x20, 0x99, 0xCD, 0xC6, 0x0C,
0x15, 0x0C, 0xBF, 0x3E, 0xFF, 0x78, 0x95, 0x67,
0xB1, 0x74, 0x5B, 0x60,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
//
// 64-bit and 56-bit DES SIMPLEBLOB's exported with
// above public key. These keys are functionally
// equivalent on Windows 2000 due to a buffer overrun
// bug.
//
static BYTE g_rgbDes56BitKeyBlob[] =
{
0x01, 0x02, 0x00, 0x00, 0x01, 0x66, 0x00, 0x00,
0x00, 0xa4, 0x00, 0x00, 0x29, 0x32, 0xc4, 0xd0,
0x75, 0x25, 0xa4, 0x00, 0xa8, 0x6f, 0x02, 0x35,
0x0e, 0x53, 0x75, 0xaa, 0xad, 0x8d, 0x21, 0x67,
0xf6, 0x8a, 0x93, 0x78, 0x12, 0x27, 0x5c, 0xd1,
0xa2, 0x13, 0x0f, 0xab, 0xe4, 0x68, 0x8e, 0x28,
0xcc, 0x3e, 0xf1, 0xa5, 0x52, 0xe4, 0xf7, 0xa4,
0x57, 0xaa, 0x86, 0x93, 0xc8, 0x73, 0xb1, 0x9f,
0x77, 0xc8, 0x84, 0x97, 0xe4, 0xad, 0x63, 0xad,
0x5d, 0x76, 0x02, 0x00
};
static BYTE g_rgbDes64BitKeyBlob[] =
{
0x01, 0x02, 0x00, 0x00, 0x01, 0x66, 0x00, 0x00,
0x00, 0xa4, 0x00, 0x00, 0x00, 0x29, 0x32, 0xc4,
0xd0, 0x75, 0x25, 0xa4, 0x00, 0xa8, 0x6f, 0x02,
0x0e, 0x53, 0x75, 0xaa, 0xad, 0x8d, 0x21, 0x67,
0xf6, 0x8a, 0x93, 0x78, 0x12, 0x27, 0x5c, 0xd1,
0xa2, 0x13, 0x0f, 0xab, 0xe4, 0x68, 0x8e, 0x28,
0xcc, 0x3e, 0xf1, 0xa5, 0x52, 0xe4, 0xf7, 0xa4,
0x57, 0xaa, 0x86, 0x93, 0xc8, 0x73, 0xb1, 0x9f,
0x77, 0xc8, 0x84, 0x97, 0xe4, 0xad, 0x63, 0xad,
0x5d, 0x76, 0x02, 0x00
};
static BYTE g_rgbDesPlainText[] =
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
};
static BYTE g_rgbDesCipherText[] =
{
0x3b, 0xd9, 0x09, 0xfb, 0xd6, 0xa7, 0x9c, 0x37,
0xf6, 0x5d, 0xe1, 0x50, 0x6d, 0x39, 0xb0, 0x0c
};
//
// 112 and 128 bit "equivalent" 3Des-2Key blobs
//
static BYTE g_rgbDes112BitKeyBlob[] =
{
0x01, 0x02, 0x00, 0x00, 0x09, 0x66, 0x00, 0x00,
0x00, 0xa4, 0x00, 0x00, 0x29, 0x32, 0xc4, 0xd0,
0x75, 0x25, 0xa4, 0x75, 0xa8, 0x6f, 0x02, 0x35,
0x0e, 0x53, 0x00, 0xaa, 0xad, 0x8d, 0x21, 0x67,
0xf6, 0x8a, 0x93, 0x78, 0x12, 0x27, 0x5c, 0xd1,
0xa2, 0x13, 0x0f, 0xab, 0xe4, 0x68, 0x8e, 0x28,
0xcc, 0x3e, 0xf1, 0xa5, 0x52, 0xe4, 0xf7, 0xa4,
0x57, 0xaa, 0x86, 0x93, 0xc8, 0x73, 0xb1, 0x9f,
0x77, 0xc8, 0x84, 0x97, 0xe4, 0xad, 0x63, 0xad,
0x5d, 0x76, 0x02, 0x00
};
static BYTE g_rgbDes128BitKeyBlob[] =
{
0x01, 0x02, 0x00, 0x00, 0x09, 0x66, 0x00, 0x00,
0x00, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x29, 0x32,
0xc4, 0xd0, 0x75, 0x25, 0xa4, 0x75, 0xa8, 0x6f,
0x02, 0x35, 0x0e, 0x53, 0x00, 0xaa, 0xad, 0x8d,
0xf6, 0x8a, 0x93, 0x78, 0x12, 0x27, 0x5c, 0xd1,
0xa2, 0x13, 0x0f, 0xab, 0xe4, 0x68, 0x8e, 0x28,
0xcc, 0x3e, 0xf1, 0xa5, 0x52, 0xe4, 0xf7, 0xa4,
0x57, 0xaa, 0x86, 0x93, 0xc8, 0x73, 0xb1, 0x9f,
0x77, 0xc8, 0x84, 0x97, 0xe4, 0xad, 0x63, 0xad,
0x5d, 0x76, 0x02, 0x00
};
static BYTE g_rgb2DesCipherText[] =
{
0x56, 0x03, 0xdf, 0x55, 0xeb, 0xfb, 0x76, 0x1f,
0x93, 0x38, 0xd7, 0xef, 0x8f, 0x38, 0x76, 0x49
};
//
// 168 and 192 bit "equivalent" 3Des blobs
//
static BYTE g_rgbDes168BitKeyBlob[] =
{
0x01, 0x02, 0x00, 0x00, 0x03, 0x66, 0x00, 0x00,
0x00, 0xa4, 0x00, 0x00, 0x29, 0x32, 0xc4, 0xd0,
0x75, 0x25, 0xa4, 0x8a, 0xa8, 0x6f, 0x02, 0x35,
0x0e, 0x53, 0x75, 0xaa, 0xad, 0x8d, 0x21, 0x67,
0xf6, 0x00, 0x93, 0x78, 0x12, 0x27, 0x5c, 0xd1,
0xa2, 0x13, 0x0f, 0xab, 0xe4, 0x68, 0x8e, 0x28,
0xcc, 0x3e, 0xf1, 0xa5, 0x52, 0xe4, 0xf7, 0xa4,
0x57, 0xaa, 0x86, 0x93, 0xc8, 0x73, 0xb1, 0x9f,
0x77, 0xc8, 0x84, 0x97, 0xe4, 0xad, 0x63, 0xad,
0x5d, 0x76, 0x02, 0x00
};
static BYTE g_rgbDes192BitKeyBlob[] =
{
0x01, 0x02, 0x00, 0x00, 0x03, 0x66, 0x00, 0x00,
0x00, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29,
0x32, 0xc4, 0xd0, 0x75, 0x25, 0xa4, 0x8a, 0xa8,
0x6f, 0x02, 0x35, 0x0e, 0x53, 0x75, 0xaa, 0xad,
0x8d, 0x21, 0x67, 0xf6, 0x00, 0x93, 0x78, 0x12,
0xa2, 0x13, 0x0f, 0xab, 0xe4, 0x68, 0x8e, 0x28,
0xcc, 0x3e, 0xf1, 0xa5, 0x52, 0xe4, 0xf7, 0xa4,
0x57, 0xaa, 0x86, 0x93, 0xc8, 0x73, 0xb1, 0x9f,
0x77, 0xc8, 0x84, 0x97, 0xe4, 0xad, 0x63, 0xad,
0x5d, 0x76, 0x02, 0x00
};
static BYTE g_rgb3DesCipherText[] =
{
0x25, 0x25, 0x14, 0x94, 0x6b, 0xe0, 0x69, 0x21,
0xea, 0x3d, 0xb5, 0xa6, 0x5b, 0xaa, 0x6c, 0x87
};
//
// Function: DesImportEquivalenceTest
// Purpose: Verify that the provided des key correctly
// encrypts the above rgbDesPlainText.
//
DWORD DesImportEquivalenceTest(
PTHREAD_DATA pThreadData,
PBYTE pbDesKey,
DWORD cbDesKey,
PBYTE pbDesShortKey,
DWORD cbDesShortKey,
PBYTE pbCipherText,
DWORD cbCipherText)
{
DWORD dwError = ERROR_SUCCESS;
BOOL fSuccess = FALSE;
HCRYPTKEY hPubKey = 0;
HCRYPTKEY hDesKey = 0;
PBYTE pb = NULL;
DWORD cb = 0;
BYTE rgbPlain[sizeof(g_rgbDesPlainText) * 2];
DWORD cbPlain = sizeof(rgbPlain);
BOOL fBlobError = FALSE;
PBYTE p1 = NULL, p2 = NULL, p3 = NULL;
if (! CryptImportKey(
pThreadData->hVerifyCtx, rgbPrivateKeyWithExponentOfOne,
sizeof(rgbPrivateKeyWithExponentOfOne), 0, 0, &hPubKey))
{
printf("CryptImportKey privatekeywithexponentofone ");
goto Ret;
}
// Try to import the short key; should fail
if (CryptImportKey(
pThreadData->hVerifyCtx, pbDesShortKey, cbDesShortKey,
hPubKey, 0, &hDesKey))
{
printf("CryptImportKey ShortDesKey should've failed ");
goto Ret;
}
PrintBytes("Testing this des key SIMPLEBLOB", pbDesKey, cbDesKey);
if (! CryptImportKey(
pThreadData->hVerifyCtx, pbDesKey, cbDesKey,
hPubKey, CRYPT_EXPORTABLE, &hDesKey))
{
printf("CryptImportKey deskeyblob ");
goto Ret;
}
cb = sizeof(g_rgbDesPlainText);
memcpy(rgbPlain, g_rgbDesPlainText, cb);
if (! CryptEncrypt(
hDesKey, 0, TRUE, 0, rgbPlain, &cb, cbPlain))
{
printf("CryptEncrypt ");
goto Ret;
}
if (0 != memcmp(rgbPlain, pbCipherText, cbCipherText))
{
printf("Cipher text doesn't match\n");
PrintBytes("Expected cipher text", pbCipherText, cbCipherText);
PrintBytes("Actual cipher text", rgbPlain, sizeof(rgbPlain));
fBlobError = TRUE;
}
if (! CryptExportKey(
hDesKey, hPubKey, SIMPLEBLOB, 0, NULL, &cb))
{
printf("CryptExportKey size ");
goto Ret;
}
if (NULL == (pb = (PBYTE) MyAlloc(cb)))
return ERROR_NOT_ENOUGH_MEMORY;
if (! CryptExportKey(
hDesKey, hPubKey, SIMPLEBLOB, 0, pb, &cb))
{
printf("CryptExportKey ");
goto Ret;
}
if (0 != memcmp(
pb, pbDesKey,
sizeof(SIMPLEBLOB) + sizeof(ALG_ID) + 8))
{
printf("Header + key portion of blob doesn't match\n");
PrintBytes("Expected key blob", pbDesKey, cbDesKey);
PrintBytes("Actual key blob", pb, cb);
fBlobError = TRUE;
}
fSuccess = TRUE;
Ret:
if (fBlobError)
dwError = -1;
if (! fSuccess)
printf("- error 0x%x\n", dwError = GetLastError());
if (hDesKey)
CryptDestroyKey(hDesKey);
if (hPubKey)
CryptDestroyKey(hPubKey);
if (pb)
MyFree(pb);
return dwError;
}
//
// Function: DesImportRegression
//
DWORD DesImportRegression(PTHREAD_DATA pThreadData)
{
DWORD dwSts;
DWORD dwError = ERROR_SUCCESS;
if (ERROR_SUCCESS != (dwSts =
DesImportEquivalenceTest(
pThreadData,
g_rgbDes64BitKeyBlob,
sizeof(g_rgbDes64BitKeyBlob),
g_rgbDes56BitKeyBlob,
sizeof(g_rgbDes56BitKeyBlob),
g_rgbDesCipherText,
sizeof(g_rgbDesCipherText))))
dwError = dwSts;
if (ERROR_SUCCESS != (dwSts =
DesImportEquivalenceTest(
pThreadData,
g_rgbDes128BitKeyBlob,
sizeof(g_rgbDes128BitKeyBlob),
g_rgbDes112BitKeyBlob,
sizeof(g_rgbDes112BitKeyBlob),
g_rgb2DesCipherText,
sizeof(g_rgb2DesCipherText))))
dwError = dwSts;
if (ERROR_SUCCESS != (dwSts =
DesImportEquivalenceTest(
pThreadData,
g_rgbDes192BitKeyBlob,
sizeof(g_rgbDes192BitKeyBlob),
g_rgbDes168BitKeyBlob,
sizeof(g_rgbDes168BitKeyBlob),
g_rgb3DesCipherText,
sizeof(g_rgb3DesCipherText))))
dwError = dwSts;
return dwError;
}
static BYTE rgbPlainText[] =
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
};
static BYTE rgbIV[] =
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
};
BYTE rgbRC2PlainTextKey [] = {
0x08, 0x02, 0x00, 0x00, 0x02, 0x66, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00, 0x10, 0x62, 0x0a, 0x8a,
0x6b, 0x0d, 0x60, 0xbe, 0xf3, 0x94, 0x99, 0x12,
0xef, 0x39, 0xbf, 0x4f
};
BYTE rgbRC2CipherText [] = {
0xfd, 0x25, 0x3e, 0x7a, 0xff, 0xb5, 0xc2, 0x6e,
0x13, 0xcf, 0x52, 0xf1, 0xba, 0xa3, 0x9a, 0xef,
0x1c, 0xfb, 0x91, 0x88, 0x9d, 0xf7, 0xe5, 0x12
};
BYTE rgbDESPlainTextKey [] = {
0x08, 0x02, 0x00, 0x00, 0x01, 0x66, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00, 0xef, 0x8f, 0x10, 0xec,
0xea, 0x7a, 0x2c, 0x01
};
BYTE rgbDESCipherText [] = {
0x13, 0x68, 0x16, 0xc5, 0x15, 0x3d, 0x59, 0x1f,
0x8e, 0x9c, 0x9c, 0x4f, 0x03, 0x7b, 0xb2, 0x12,
0x24, 0xa7, 0x81, 0x5e, 0x68, 0xb1, 0x58, 0xaa
};
BYTE rgb3DES112PlainTextKey [] = {
0x08, 0x02, 0x00, 0x00, 0x09, 0x66, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00, 0x6d, 0x07, 0xcd, 0xe9,
0xa4, 0x23, 0xc7, 0x97, 0x4a, 0x4f, 0x5b, 0x2f,
0x34, 0x92, 0xb5, 0x92
};
BYTE rgb3DES112CipherText [] = {
0xf4, 0xfd, 0xde, 0x15, 0xfd, 0x50, 0xaa, 0x3c,
0x02, 0xb1, 0x07, 0x3b, 0x0f, 0x0f, 0x93, 0x23,
0xc2, 0x23, 0xda, 0x1f, 0x65, 0x81, 0x59, 0x24
};
BYTE rgb3DESCipherText [] = {
0xa6, 0xae, 0xa2, 0x97, 0xc4, 0x85, 0xda, 0xa7,
0x43, 0xc8, 0x5d, 0xf4, 0x97, 0xb4, 0xbc, 0x03,
0x96, 0xf9, 0xa2, 0x66, 0x9e, 0x18, 0x91, 0x4a
};
BYTE rgb3DESPlainTextKey [] = {
0x08, 0x02, 0x00, 0x00, 0x03, 0x66, 0x00, 0x00,
0x18, 0x00, 0x00, 0x00, 0xdc, 0x0d, 0x20, 0xf2,
0xcb, 0xa8, 0xb6, 0x15, 0x3e, 0x23, 0x38, 0xb6,
0x31, 0x62, 0x4a, 0x16, 0xa4, 0x49, 0xe5, 0xe5,
0x61, 0x76, 0x75, 0x23
};
BYTE rgbAES128PlainTextKey [] = {
0x08, 0x02, 0x00, 0x00, 0x0e, 0x66, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00, 0x7d, 0xda, 0x8c, 0x7f,
0xac, 0x2e, 0xe7, 0xa6, 0x6f, 0x4c, 0x3b, 0x98,
0x2b, 0xe6, 0xff, 0xc9
};
BYTE rgbAES128CipherText [] = {
0xd7, 0xb4, 0x60, 0x15, 0x39, 0xac, 0x42, 0x8c,
0x67, 0x09, 0x0d, 0x3f, 0x45, 0xa0, 0x4e, 0xf5,
0x6b, 0x7d, 0x6d, 0x21, 0x28, 0xd7, 0x93, 0x13,
0xd8, 0x5a, 0x7a, 0x92, 0x34, 0x98, 0xfe, 0x73
};
BYTE rgbAES192PlainTextKey [] = {
0x08, 0x02, 0x00, 0x00, 0x0f, 0x66, 0x00, 0x00,
0x18, 0x00, 0x00, 0x00, 0x09, 0x38, 0x0e, 0xfd,
0x49, 0x16, 0x95, 0x95, 0x01, 0x6e, 0x8b, 0xfd,
0x3a, 0x34, 0x24, 0x62, 0x23, 0xd6, 0xd4, 0x01,
0x38, 0x97, 0x96, 0x48
};
BYTE rgbAES192CipherText [] = {
0xa6, 0x57, 0x36, 0xbb, 0xb2, 0x4f, 0x22, 0xee,
0x2b, 0xb8, 0x0b, 0x65, 0xf3, 0xc1, 0x82, 0x93,
0x92, 0xcc, 0xcc, 0x0a, 0xf3, 0x4e, 0x3b, 0x28,
0xb7, 0x6d, 0x89, 0xd3, 0x9a, 0x0c, 0xa0, 0x95
};
BYTE rgbAES256PlainTextKey [] = {
0x08, 0x02, 0x00, 0x00, 0x10, 0x66, 0x00, 0x00,
0x20, 0x00, 0x00, 0x00, 0xb5, 0xe8, 0xa8, 0xb3,
0x1b, 0x0b, 0x9c, 0x14, 0x9e, 0x27, 0xe8, 0x99,
0x58, 0xce, 0x89, 0x57, 0x34, 0x2f, 0x1a, 0x41,
0x29, 0x4e, 0xfe, 0x64, 0xc3, 0xe9, 0xe9, 0x2b,
0x63, 0x47, 0x58, 0x54
};
BYTE rgbAES256CipherText [] = {
0x51, 0xf2, 0x8d, 0x49, 0x7d, 0x10, 0xd4, 0x66,
0xe8, 0xc2, 0x70, 0xf3, 0xff, 0x19, 0xa2, 0x7e,
0xe7, 0x89, 0x1d, 0x11, 0xe7, 0x25, 0xd7, 0x42,
0x75, 0xe2, 0x72, 0x78, 0x38, 0x52, 0x30, 0xc9
};
typedef struct _KnownBlockCipherResult {
ALG_ID ai;
BYTE *pbKey;
DWORD cbKey;
BYTE *pbCipherText;
DWORD cbCipherText;
} KnownBlockCipherResult, *pKnownBlockCipherResult;
KnownBlockCipherResult g_rgKnownBlockCipherResults [] = {
{ CALG_RC2, rgbRC2PlainTextKey, sizeof(rgbRC2PlainTextKey),
rgbRC2CipherText, sizeof(rgbRC2CipherText) },
{ CALG_DES, rgbDESPlainTextKey, sizeof(rgbDESPlainTextKey),
rgbDESCipherText, sizeof(rgbDESCipherText) },
{ CALG_3DES_112, rgb3DES112PlainTextKey, sizeof(rgb3DES112PlainTextKey),
rgb3DES112CipherText, sizeof(rgb3DES112CipherText) },
{ CALG_3DES, rgb3DESPlainTextKey, sizeof(rgb3DESPlainTextKey),
rgb3DESCipherText, sizeof(rgb3DESCipherText) },
{ CALG_AES_128, rgbAES128PlainTextKey, sizeof(rgbAES128PlainTextKey),
rgbAES128CipherText, sizeof(rgbAES128CipherText) },
{ CALG_AES_192, rgbAES192PlainTextKey, sizeof(rgbAES192PlainTextKey),
rgbAES192CipherText, sizeof(rgbAES192CipherText) },
{ CALG_AES_256, rgbAES256PlainTextKey, sizeof(rgbAES256PlainTextKey),
rgbAES256CipherText, sizeof(rgbAES256CipherText) }
};
static const unsigned g_cKnownBlockCipherResults =
sizeof(g_rgKnownBlockCipherResults) / sizeof(KnownBlockCipherResult);
//
// Function: KnownSymKeyRegression
//
DWORD KnownBlockCipherKeyRegression(PTHREAD_DATA pThreadData)
{
DWORD dwError = ERROR_SUCCESS;
BOOL fSuccess = FALSE;
BOOL fBlobError = FALSE;
HCRYPTKEY hPubKey = 0;
HCRYPTKEY hSymKey = 0;
PALGNODE pAlgNode = NULL;
PBYTE pb = NULL;
DWORD cb = 0;
DWORD cbBuf = 0;
DWORD dw = 0;
CHAR rgsz[1024];
unsigned u;
for ( pAlgNode = pThreadData->pAlgList;
pAlgNode != NULL;
pAlgNode = pAlgNode->pNext)
{
if ((ALG_CLASS_DATA_ENCRYPT != GET_ALG_CLASS(pAlgNode->EnumalgsEx.aiAlgid))
|| (ALG_TYPE_BLOCK != GET_ALG_TYPE(pAlgNode->EnumalgsEx.aiAlgid)))
continue;
for ( u = 0;
u < g_cKnownBlockCipherResults &&
pAlgNode->EnumalgsEx.aiAlgid != g_rgKnownBlockCipherResults[u].ai;
u++);
// CYLINK_MEK is not supported with PLAINTEXTKEYBLOB's
if (CALG_CYLINK_MEK == pAlgNode->EnumalgsEx.aiAlgid)
continue;
sprintf(
rgsz,
"Importing 0x%x blob for CSP alg %s (0x%x)",
g_rgKnownBlockCipherResults[u].ai,
pAlgNode->EnumalgsEx.szName,
pAlgNode->EnumalgsEx.aiAlgid);
PrintBytes(
rgsz,
g_rgKnownBlockCipherResults[u].pbKey,
g_rgKnownBlockCipherResults[u].cbKey);
if (! CryptImportKey(
pThreadData->hProv,
g_rgKnownBlockCipherResults[u].pbKey,
g_rgKnownBlockCipherResults[u].cbKey,
0, 0, &hSymKey))
{
printf("CryptImportKey ");
goto Ret;
}
if (! CryptSetKeyParam(hSymKey, KP_IV, rgbIV, 0))
{
printf("CryptSetKeyParam ");
goto Ret;
}
dw = CRYPT_MODE_CBC;
if (! CryptSetKeyParam(hSymKey, KP_MODE, (PBYTE) &dw, 0))
{
printf("CryptSetKeyParam ");
goto Ret;
}
cb = sizeof(rgbPlainText);
if (! CryptEncrypt(hSymKey, 0, TRUE, 0, NULL, &cb, 0))
{
printf("CryptEncrypt ");
goto Ret;
}
if (NULL == (pb = (PBYTE) MyAlloc(cb)))
return ERROR_NOT_ENOUGH_MEMORY;
cbBuf = cb;
cb = sizeof(rgbPlainText);
memcpy(pb, rgbPlainText, cb);
if (! CryptEncrypt(hSymKey, 0, TRUE, 0, pb, &cb, cbBuf))
{
printf("CryptEncrypt ");
goto Ret;
}
if (0 != memcmp(pb, g_rgKnownBlockCipherResults[u].pbCipherText, cb)
|| 0 == cb)
{
printf(
"Ciphertext is wrong for alg %s\n",
pAlgNode->EnumalgsEx.szName);
PrintBytes(
"Expected ciphertext",
g_rgKnownBlockCipherResults[u].pbCipherText,
cb);
PrintBytes(
"Actual ciphertext",
pb, cb);
fBlobError = TRUE;
}
}
fSuccess = TRUE;
Ret:
if (fBlobError)
dwError = -1;
if ((! fSuccess) && (! fBlobError))
printf("- error 0x%x\n", dwError = GetLastError());
return dwError;
}
typedef struct _HMAC_TEST
{
PBYTE pbKey;
DWORD cbKey;
PBYTE pbData;
DWORD cbData;
PBYTE pbData2;
DWORD cbData2;
PBYTE pbHmac;
DWORD cbHmac;
ALG_ID aiHash;
} HMAC_TEST, *PHMAC_TEST;
//
// Function: DoHmacTestCase
//
DWORD DoHmacTestCase(
IN PTHREAD_DATA pThreadData,
IN PHMAC_TEST pHmac)
{
HCRYPTKEY hKey = 0;
HCRYPTHASH hHash = 0;
DWORD cb = 0;
BLOBHEADER *pHeader = NULL;
BOOL fSuccess = FALSE;
DWORD dwError = ERROR_SUCCESS;
BYTE rgBuf[1024];
HMAC_INFO HmacInfo;
ZeroMemory(rgBuf, sizeof(rgBuf));
ZeroMemory(&HmacInfo, sizeof(HmacInfo));
pHeader = (BLOBHEADER *) rgBuf;
pHeader->bType = PLAINTEXTKEYBLOB;
pHeader->bVersion = CUR_BLOB_VERSION;
pHeader->aiKeyAlg = CALG_RC2;
*(DWORD*)(rgBuf + sizeof(BLOBHEADER)) = pHmac->cbKey;
memcpy(
rgBuf + sizeof(BLOBHEADER) + sizeof(DWORD),
pHmac->pbKey, pHmac->cbKey);
if (! CryptImportKey(
pThreadData->hProv, rgBuf,
sizeof(BLOBHEADER) + sizeof(DWORD) + pHmac->cbKey,
0, CRYPT_IPSEC_HMAC_KEY, &hKey))
{
printf("CryptImportKey");
goto Ret;
}
if (! CryptCreateHash(
pThreadData->hProv, CALG_HMAC, hKey, 0, &hHash))
{
printf("CryptCreateHash");
goto Ret;
}
HmacInfo.HashAlgid = pHmac->aiHash;
if (! CryptSetHashParam(
hHash, HP_HMAC_INFO, (PBYTE) &HmacInfo, 0))
{
printf("CryptSetHashParam");
goto Ret;
}
if (! CryptHashData(
hHash, pHmac->pbData, pHmac->cbData, 0))
{
printf("CryptHashData");
goto Ret;
}
if (pHmac->cbData2)
{
if (! CryptHashData(
hHash, pHmac->pbData2, pHmac->cbData2, 0))
{
printf("CryptHashData 2");
goto Ret;
}
}
cb = sizeof(rgBuf);
ZeroMemory(rgBuf, sizeof(rgBuf));
if (! CryptGetHashParam(
hHash, HP_HASHVAL, rgBuf, &cb, 0))
{
printf("CryptGetHashParam");
goto Ret;
}
PrintBytes("Expected Hmac", pHmac->pbHmac, pHmac->cbHmac);
PrintBytes("Actual Hmac", rgBuf, cb);
if ( 0 != memcmp(rgBuf, pHmac->pbHmac, cb)
|| cb != pHmac->cbHmac)
goto Ret;
if (! CryptDestroyKey(hKey))
{
printf("CryptDestroyKey");
goto Ret;
}
if (! CryptDestroyHash(hHash))
{
printf("CryptDestroyHash");
goto Ret;
}
fSuccess = TRUE;
Ret:
if (! fSuccess)
{
dwError = GetLastError();
printf(" error - 0x%x\n", dwError);
if (0 == dwError)
dwError = -1;
}
return dwError;
}
//
// Function: HmacRegression
//
DWORD HmacRegression(PTHREAD_DATA pThreadData)
{
BOOL fSuccess = FALSE;
DWORD dwError = ERROR_SUCCESS;
HMAC_TEST Hmac;
// SHA Test case 1
BYTE rgKey1 [] = {
0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
0x0b, 0x0b, 0x0b, 0x0b, 0x0b
};
LPSTR pszData1 = "Hi There";
BYTE rgHmac1 [] = {
0xb6, 0x17, 0x31, 0x86, 0x55,
0x05, 0x72, 0x64, 0xe2, 0x8b,
0xc0, 0xb6, 0xfb, 0x37, 0x8c,
0x8e, 0xf1, 0x46, 0xbe, 0x00
};
// SHA Test case 2
BYTE rgKey2 [] = {
0x01, 0x02, 0x03, 0x04, 0x05,
0x06, 0x07, 0x08, 0x09, 0x0a,
0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14,
0x15, 0x16, 0x17, 0x18, 0x19
};
BYTE rgData2 [50];
BYTE rgHmac2 [] = {
0x4c, 0x90, 0x07, 0xf4, 0x02,
0x62, 0x50, 0xc6, 0xbc, 0x84,
0x14, 0xf9, 0xbf, 0x50, 0xc8,
0x6c, 0x2d, 0x72, 0x35, 0xda
};
// SHA Test case 3
BYTE rgKey3 [80];
LPSTR pszData3 = "Test Using Larger Than Block-Size Key - Hash Key First";
BYTE rgHmac3 [] = {
0xaa, 0x4a, 0xe5, 0xe1, 0x52,
0x72, 0xd0, 0x0e, 0x95, 0x70,
0x56, 0x37, 0xce, 0x8a, 0x3b,
0x55, 0xed, 0x40, 0x21, 0x12
};
// MD5 Test case 1
// use rgKey1 (16 bytes only) and pszData1
BYTE rgHmacMD1 [] = {
0x92, 0x94, 0x72, 0x7a,
0x36, 0x38, 0xbb, 0x1c,
0x13, 0xf4, 0x8e, 0xf8,
0x15, 0x8b, 0xfc, 0x9d
};
// MD5 Test case 2
// use rgKey3 (full length) and pszData3
BYTE rgHmacMD2 [] = {
0x6b, 0x1a, 0xb7, 0xfe,
0x4b, 0xd7, 0xbf, 0x8f,
0x0b, 0x62, 0xe6, 0xce,
0x61, 0xb9, 0xd0, 0xcd
};
// IPSec MD5 vectors
BYTE rgKeyIpsec [] = {
0x66, 0x6f, 0x6f
};
BYTE rgDataIpsecA [] = {
0x38, 0x8e, 0x5e, 0x8a,
0xb0, 0x79, 0x16, 0x47,
0x29, 0x1b, 0xf0, 0x02,
0x78, 0x5e, 0x38, 0xe5,
0x82, 0x3c, 0x17, 0x0d
};
BYTE rgDataIpsecB [] = {
0x34, 0xdd, 0xdb, 0x22,
0x9e, 0x21, 0x75, 0x28,
0x5e, 0x4d, 0x7d, 0xdf,
0xea, 0x35, 0xc5, 0xfc,
0x44, 0xdb, 0x62, 0xad
};
BYTE rgHmacIpsec [] = {
0x52, 0x07, 0x38, 0x15,
0xef, 0xb0, 0x68, 0x43,
0x89, 0x8e, 0x0b, 0xdc,
0x58, 0xc0, 0x70, 0xc0
};
memset(rgData2, 0xcd, sizeof(rgData2));
memset(rgKey3, 0xaa, sizeof(rgKey3));
// SHA 1
ZeroMemory(&Hmac, sizeof(HMAC_TEST));
Hmac.cbData = strlen(pszData1) * sizeof(CHAR);
Hmac.pbData = (PBYTE) pszData1;
Hmac.cbHmac = sizeof(rgHmac1);
Hmac.pbHmac = rgHmac1;
Hmac.cbKey = sizeof(rgKey1);
Hmac.pbKey = rgKey1;
Hmac.aiHash = CALG_SHA1;
if (ERROR_SUCCESS != (dwError = DoHmacTestCase(pThreadData, &Hmac)))
{
printf("ERROR: DoHmacTestCase SHA 1\n");
return dwError;
}
// SHA 2
ZeroMemory(&Hmac, sizeof(HMAC_TEST));
Hmac.cbData = sizeof(rgData2);
Hmac.pbData = rgData2;
Hmac.cbHmac = sizeof(rgHmac2);
Hmac.pbHmac = rgHmac2;
Hmac.cbKey = sizeof(rgKey2);
Hmac.pbKey = rgKey2;
Hmac.aiHash = CALG_SHA1;
if (ERROR_SUCCESS != (dwError = DoHmacTestCase(pThreadData, &Hmac)))
{
printf("ERROR: DoHmacTestCase SHA 2\n");
return dwError;
}
// SHA 3
ZeroMemory(&Hmac, sizeof(HMAC_TEST));
Hmac.cbData = strlen(pszData3) * sizeof(CHAR);
Hmac.pbData = (PBYTE) pszData3;
Hmac.cbHmac = sizeof(rgHmac3);
Hmac.pbHmac = rgHmac3;
Hmac.cbKey = sizeof(rgKey3);
Hmac.pbKey = rgKey3;
Hmac.aiHash = CALG_SHA1;
if (ERROR_SUCCESS != (dwError = DoHmacTestCase(pThreadData, &Hmac)))
{
printf("ERROR: DoHmacTestCase SHA 3\n");
return dwError;
}
// MD5 1
ZeroMemory(&Hmac, sizeof(HMAC_TEST));
Hmac.cbData = strlen(pszData1) * sizeof(CHAR);
Hmac.pbData = (PBYTE) pszData1;
Hmac.cbHmac = sizeof(rgHmacMD1);
Hmac.pbHmac = rgHmacMD1;
Hmac.cbKey = 16; // only 16-byte key for this one
Hmac.pbKey = rgKey1;
Hmac.aiHash = CALG_MD5;
if (ERROR_SUCCESS != (dwError = DoHmacTestCase(pThreadData, &Hmac)))
{
printf("ERROR: DoHmacTestCase MD5 1\n");
return dwError;
}
// MD5 2
ZeroMemory(&Hmac, sizeof(HMAC_TEST));
Hmac.cbData = strlen(pszData3) * sizeof(CHAR);
Hmac.pbData = (PBYTE) pszData3;
Hmac.cbHmac = sizeof(rgHmacMD2);
Hmac.pbHmac = rgHmacMD2;
Hmac.cbKey = sizeof(rgKey3);
Hmac.pbKey = rgKey3;
Hmac.aiHash = CALG_MD5;
if (ERROR_SUCCESS != (dwError = DoHmacTestCase(pThreadData, &Hmac)))
{
printf("ERROR: DoHmacTestCase MD5 2\n");
return dwError;
}
// MD5 Ipsec vector
ZeroMemory(&Hmac, sizeof(HMAC_TEST));
Hmac.cbData = sizeof(rgDataIpsecA);
Hmac.pbData = rgDataIpsecA;
Hmac.cbData2 = sizeof(rgDataIpsecB);
Hmac.pbData2 = rgDataIpsecB;
Hmac.cbHmac = sizeof(rgHmacIpsec);
Hmac.pbHmac = rgHmacIpsec;
Hmac.cbKey = sizeof(rgKeyIpsec);
Hmac.pbKey = rgKeyIpsec;
Hmac.aiHash = CALG_MD5;
if (ERROR_SUCCESS != (dwError = DoHmacTestCase(pThreadData, &Hmac)))
{
printf("ERROR: DoHmacTestCase MD5 Ipsec\n");
return dwError;
}
return ERROR_SUCCESS;
}
//
// Function: KeyArchiveRegression
//
// Not thread safe
//
DWORD KeyArchiveRegression(PTHREAD_DATA pThreadData)
{
HCRYPTPROV hProv = 0;
HCRYPTKEY hKey = 0;
DWORD dwError = 0;
LPSTR pszContainer = "KeyArchiveRegression";
BYTE rgbKey[2048];
DWORD cbKey;
DWORD dwData;
DWORD cbData;
BOOL fSuccess = FALSE;
CryptAcquireContext(
&hProv,
pszContainer,
pThreadData->rgszProvName,
pThreadData->dwProvType,
CRYPT_DELETEKEYSET);
if (! CryptAcquireContext(
&hProv,
pszContainer,
pThreadData->rgszProvName,
pThreadData->dwProvType,
CRYPT_NEWKEYSET))
{
printf("CryptAcquireContext newkeyset ");
goto Ret;
}
if (! CryptGenKey(
hProv,
AT_SIGNATURE,
CRYPT_ARCHIVABLE,
&hKey))
{
printf("CryptGenKey archivable ");
goto Ret;
}
cbData = sizeof(dwData);
if (! CryptGetKeyParam(
hKey, KP_PERMISSIONS, (PBYTE) &dwData, &cbData, 0))
{
printf("CryptGetKeyParam ");
goto Ret;
}
if (! ((CRYPT_ARCHIVE & dwData) && (! (CRYPT_EXPORT & dwData))))
{
printf("incorrect KP_PERMISSIONS ");
goto Ret;
}
cbKey = sizeof(rgbKey);
if (! CryptExportKey(
hKey,
0,
PRIVATEKEYBLOB,
0,
rgbKey,
&cbKey))
{
printf("CryptExportKey privatekeyblob ");
goto Ret;
}
if (! CryptDestroyKey(hKey))
{
printf("CryptDestroyKey ");
goto Ret;
}
if (! CryptReleaseContext(hProv, 0))
{
printf("CryptReleaseContext ");
goto Ret;
}
if (! CryptAcquireContext(
&hProv,
pszContainer,
pThreadData->rgszProvName,
pThreadData->dwProvType,
0))
{
printf("CryptAcquireContext ");
goto Ret;
}
if (! CryptGetUserKey(hProv, AT_SIGNATURE, &hKey))
{
printf("CryptGetUserKey ");
goto Ret;
}
// try to set the key export/archive perms; should fail
cbData = sizeof(dwData);
if (! CryptGetKeyParam(
hKey, KP_PERMISSIONS, (PBYTE) &dwData, &cbData, 0))
{
printf("CryptGetKeyParam ");
goto Ret;
}
dwData |= CRYPT_EXPORT | CRYPT_ARCHIVE;
// should fail
if (CryptSetKeyParam(hKey, KP_PERMISSIONS, (PBYTE) &dwData, 0))
{
printf("CryptSetKeyParam should have failed ");
goto Ret;
}
// should fail
cbKey = sizeof(rgbKey);
if (CryptExportKey(
hKey,
0,
PRIVATEKEYBLOB,
0,
rgbKey,
&cbKey))
{
printf("CryptExportKey should have failed ");
goto Ret;
}
fSuccess = TRUE;
Ret:
if (! fSuccess)
printf("- error 0x%x\n", dwError = GetLastError());
if (hKey)
CryptDestroyKey(hKey);
if (hProv)
CryptReleaseContext(hProv, 0);
return dwError;
}
//
// Function: PlaintextBlobRegression
//
DWORD PlaintextBlobRegression(PTHREAD_DATA pThreadData)
{
HCRYPTKEY hKey = 0;
DWORD cbKey = 0;
PBYTE pbKey = NULL;
PALGNODE pAlgNode = NULL;
BLOBHEADER *header = NULL;
PBYTE pbTemp = NULL;
DWORD cbData, cb;
BYTE rgbData[1024];
BOOL fSuccess = FALSE;
DWORD dwError = ERROR_SUCCESS;
DWORD cbKeySize = 0;
// try an invalid key type
if (CryptExportKey(
pThreadData->hSignatureKey,
0,
PLAINTEXTKEYBLOB,
0,
NULL,
&cbKey))
{
printf("CryptExportKey plaintextkeyblob should have failed ");
goto Ret;
}
// try all the valid key types
for (pAlgNode = pThreadData->pAlgList; pAlgNode != NULL; pAlgNode = pAlgNode->pNext)
{
if (ALG_CLASS_DATA_ENCRYPT != GET_ALG_CLASS(pAlgNode->EnumalgsEx.aiAlgid)
|| (ALG_TYPE_BLOCK != GET_ALG_TYPE(pAlgNode->EnumalgsEx.aiAlgid)
&& ALG_TYPE_STREAM != GET_ALG_TYPE(pAlgNode->EnumalgsEx.aiAlgid)))
continue;
// Plaintext import not supported for CYLINK_MEK
if (CALG_CYLINK_MEK == pAlgNode->EnumalgsEx.aiAlgid)
continue;
/*
if (PROV_DSS == pThreadData->dwProvType
|| PROV_DSS_DH == pThreadData->dwProvType)
{
cbKeySize = pAlgNode->EnumalgsEx.dwMaxLen / 8;
}
else
{
*/
switch (pAlgNode->EnumalgsEx.aiAlgid)
{
case CALG_DES:
cbKeySize = pAlgNode->EnumalgsEx.dwMaxLen / 8 + 1;
break;
case CALG_3DES_112:
cbKeySize = pAlgNode->EnumalgsEx.dwMaxLen / 8 + 2;
break;
case CALG_3DES:
cbKeySize = pAlgNode->EnumalgsEx.dwMaxLen / 8 + 3;
break;
default:
cbKeySize = pAlgNode->EnumalgsEx.dwMaxLen / 8;
}
/*
}
*/
printf(
"Importing Alg: %xh (%s), Size: %d bits\n",
pAlgNode->EnumalgsEx.aiAlgid,
pAlgNode->EnumalgsEx.szName,
cbKeySize * 8);
cbKey = sizeof(BLOBHEADER) + sizeof(DWORD) + cbKeySize;
if (NULL == (pbKey = (PBYTE) MyAlloc(cbKey)))
return ERROR_NOT_ENOUGH_MEMORY;
header = (BLOBHEADER *) pbKey;
header->aiKeyAlg = pAlgNode->EnumalgsEx.aiAlgid;
header->bType = PLAINTEXTKEYBLOB;
header->bVersion = CUR_BLOB_VERSION;
header->reserved = 0;
pbTemp = pbKey + sizeof(BLOBHEADER);
*((DWORD*)pbTemp) = cbKeySize;
pbTemp += sizeof(DWORD);
// create some key data
if (! CryptGenRandom(
pThreadData->hProv,
cbKeySize,
pbTemp))
{
printf("CryptGenRandom ");
goto Ret;
}
if (! CryptImportKey(
pThreadData->hProv,
pbKey, cbKey, 0, CRYPT_EXPORTABLE, &hKey))
{
printf("CryptImportKey ");
goto Ret;
}
MyFree(pbKey);
// create some data to encrypt
if (! CryptGenRandom(
pThreadData->hProv,
sizeof(rgbData),
rgbData))
{
printf("CryptGenRandom ");
goto Ret;
}
cbData = sizeof(rgbData);
cb = cbData / 2;
if (! CryptEncrypt(
hKey, 0, TRUE, 0, rgbData, &cb, cbData))
{
printf("CryptEncrypt ");
goto Ret;
}
if (! CryptExportKey(
hKey, 0, PLAINTEXTKEYBLOB, 0, NULL, &cbKey))
{
printf("CryptExportKey size ");
goto Ret;
}
if (NULL == (pbKey = (PBYTE) MyAlloc(cbKey)))
return ERROR_NOT_ENOUGH_MEMORY;
if (! CryptExportKey(
hKey, 0, PLAINTEXTKEYBLOB, 0, pbKey, &cbKey))
{
printf("CryptExportKey ");
goto Ret;
}
// check the blob
header = (BLOBHEADER *) pbKey;
if (pAlgNode->EnumalgsEx.aiAlgid != header->aiKeyAlg)
{
printf("header->aiKeyAlg is wrong ");
goto Ret;
}
if (CUR_BLOB_VERSION != header->bVersion)
{
printf("header->bVersion is wrong ");
goto Ret;
}
if (0 != header->reserved)
{
printf("header->reserved is wrong ");
goto Ret;
}
if (PLAINTEXTKEYBLOB != header->bType)
{
printf("header->bType is wrong ");
goto Ret;
}
pbTemp = pbKey + sizeof(BLOBHEADER);
if (cbKeySize != *((DWORD*)pbTemp))
{
printf(
"blob key size is %d, but should be %d ",
*((DWORD*)pbTemp),
cbKeySize);
goto Ret;
}
MyFree(pbKey);
if (! CryptDestroyKey(hKey))
{
printf("CryptDestroyKey ");
goto Ret;
}
}
fSuccess = TRUE;
Ret:
if (! fSuccess)
printf("- error 0x%x\n", dwError = GetLastError());
if (hKey)
CryptDestroyKey(hKey);
return dwError;
}
//
// Function: LoadAesCspRegression
//
DWORD LoadAesCspRegression(PTHREAD_DATA pThreadData)
{
DWORD dwError = 0;
BOOL fSuccess = FALSE;
HMODULE hMod = NULL;
if (NULL == (hMod = LoadLibraryEx(RSA_AES_CSP, NULL, 0)))
{
printf("LoadLibraryEx %s ", RSA_AES_CSP);
goto Ret;
}
if (! FreeLibrary(hMod))
{
printf("FreeLibrary %s ", RSA_AES_CSP);
goto Ret;
}
fSuccess = TRUE;
Ret:
if (! fSuccess)
printf("- error 0x%x\n", dwError = GetLastError());
return dwError;
}
DWORD VerifyPinCallback(PPINCACHE_PINS pPins, PVOID pvData)
{
DWORD dwReturn = *(DWORD*)pvData;
PrintBytes(
"VerifyPinCallback current pin",
pPins->pbCurrentPin, pPins->cbCurrentPin);
PrintBytes(
"VerifyPinCallback new pin",
pPins->pbNewPin, pPins->cbNewPin);
return dwReturn;
}
static USHORT l_uTestLogonID;
void SetLogonID(USHORT uLogon)
{
l_uTestLogonID = uLogon;
}
void GetLogonID(LUID *pLuid)
{
memset(pLuid, l_uTestLogonID, sizeof(LUID));
}
BOOL MyGetTokenInformation(
HANDLE TokenHandle,
TOKEN_INFORMATION_CLASS TokenInformationClass,
LPVOID TokenInformation,
DWORD TokenInformationLength,
PDWORD ReturnLength)
{
NTSTATUS status = NtQueryInformationToken(
TokenHandle, TokenInformationClass,
TokenInformation, TokenInformationLength,
ReturnLength);
if (TokenStatistics == TokenInformationClass)
{
printf("MyGetTokenInformation: intercepted TokenStatistics call\n");
GetLogonID(&((TOKEN_STATISTICS*) TokenInformation)->AuthenticationId);
}
return (S_OK == status);
}
//
// Function: PinCacheRegression
//
DWORD PinCacheRegression(PTHREAD_DATA pThreadData)
{
DWORD dwError = 0;
BOOL fSuccess = FALSE;
PINCACHE_HANDLE hCache = NULL;
BYTE rgPin[] = { 1, 2, 3, 4 };
DWORD cbPin = sizeof(rgPin);
BYTE rgPin2[] = { 5, 6, 7, 8, 9 };
BYTE *pbPin = NULL;
PFN_VERIFYPIN_CALLBACK pfnVerifyPin = VerifyPinCallback;
DWORD dwCallbackReturn;
PINCACHE_PINS Pins;
ZeroMemory(&Pins, sizeof(PINCACHE_PINS));
Pins.cbCurrentPin = sizeof(rgPin);
Pins.pbCurrentPin = rgPin;
dwCallbackReturn = 0x7070;
if (0x7070 != (dwError =
PinCacheAdd(&hCache, &Pins,
pfnVerifyPin, (PVOID) &dwCallbackReturn)))
{
printf("PinCacheAdd with callback fail ");
goto Ret;
}
//
// (0)
// Cache uninitialized
//
SetLogonID(1);
dwCallbackReturn = ERROR_SUCCESS;
if (ERROR_SUCCESS != (dwError =
PinCacheAdd(&hCache, &Pins,
pfnVerifyPin, (PVOID) &dwCallbackReturn)))
{
printf("PinCacheAdd ");
goto Ret;
}
if (ERROR_SUCCESS != (dwError = PinCacheQuery(hCache, NULL, &cbPin)))
{
printf("PinCacheQuery NULL for size ");
goto Ret;
}
if (NULL == (pbPin = (PBYTE) MyAlloc(cbPin)))
return ERROR_NOT_ENOUGH_MEMORY;
cbPin--;
if (ERROR_SUCCESS == (dwError = PinCacheQuery(hCache, pbPin, &cbPin)))
{
printf("PinCacheQuery insufficient size succeeded ");
goto Ret;
}
if (ERROR_SUCCESS != (dwError = PinCacheQuery(hCache, pbPin, &cbPin)))
{
printf("PinCacheQuery ");
goto Ret;
}
if (sizeof(rgPin) != RtlCompareMemory(pbPin, rgPin, cbPin))
{
PrintBytes("Actual cache", pbPin, cbPin);
PrintBytes("Expected cache", rgPin, sizeof(rgPin));
printf("Cache is incorrect ");
goto Ret;
}
PinCacheFlush(&hCache);
if (NULL != hCache)
{
printf("PinCacheFlush should set hCache=NULL ");
goto Ret;
}
// Re-initialize to continue tests
if (ERROR_SUCCESS != (dwError =
PinCacheAdd(&hCache, &Pins,
pfnVerifyPin, (PVOID) &dwCallbackReturn)))
{
printf("PinCacheAdd ");
goto Ret;
}
//
// (1)
// Same LogonID, same Pin
//
if (ERROR_SUCCESS != (dwError =
PinCacheAdd(&hCache, &Pins,
pfnVerifyPin, (PVOID) &dwCallbackReturn)))
{
printf("PinCacheAdd 1 ");
goto Ret;
}
cbPin = sizeof(rgPin);
if (ERROR_SUCCESS != (dwError = PinCacheQuery(hCache, pbPin, &cbPin)))
{
printf("PinCacheQuery 1 ");
goto Ret;
}
if (sizeof(rgPin) != RtlCompareMemory(pbPin, rgPin, cbPin))
{
PrintBytes("Actual cache", pbPin, cbPin);
PrintBytes("Expected cache", rgPin, sizeof(rgPin));
printf("Cache is incorrect 1 ");
goto Ret;
}
// Try a pin change
Pins.cbNewPin = sizeof(rgPin2);
Pins.pbNewPin = rgPin2;
if (ERROR_SUCCESS != (dwError =
PinCacheAdd(&hCache, &Pins,
pfnVerifyPin, (PVOID) &dwCallbackReturn)))
{
printf("PinCacheAdd 1 change ");
goto Ret;
}
if (ERROR_SUCCESS != (dwError = PinCacheQuery(hCache, NULL, &cbPin)))
{
printf("PinCacheQuery 1 change query ");
goto Ret;
}
MyFree(pbPin);
pbPin = NULL;
if (NULL == (pbPin = (PBYTE) MyAlloc(cbPin)))
return ERROR_NOT_ENOUGH_MEMORY;
if (ERROR_SUCCESS != (dwError = PinCacheQuery(hCache, pbPin, &cbPin)))
{
printf("PinCacheQuery 1 change ");
goto Ret;
}
if (sizeof(rgPin2) != RtlCompareMemory(pbPin, rgPin2, cbPin))
{
PrintBytes("Actual cache", pbPin, cbPin);
PrintBytes("Expected cache", rgPin, sizeof(rgPin));
printf("Cache is incorrect 1 change ");
goto Ret;
}
// Try a failed pin change
Pins.cbCurrentPin = sizeof(rgPin2);
Pins.pbCurrentPin = rgPin2;
Pins.cbNewPin = sizeof(rgPin);
Pins.pbNewPin = rgPin;
dwCallbackReturn = -1;
if (-1 != (dwError =
PinCacheAdd(&hCache, &Pins,
pfnVerifyPin, (PVOID) &dwCallbackReturn)))
{
printf("PinCacheAdd 1 change-fail ");
goto Ret;
}
// Cache should have been preserved
cbPin = sizeof(rgPin2);
ZeroMemory(pbPin, sizeof(rgPin2));
if (ERROR_SUCCESS != (dwError = PinCacheQuery(hCache, pbPin, &cbPin)))
{
printf("PinCacheQuery 1 change-fail ");
goto Ret;
}
if (sizeof(rgPin2) != RtlCompareMemory(pbPin, rgPin2, cbPin))
{
PrintBytes("Actual cache", pbPin, cbPin);
PrintBytes("Expected cache", rgPin2, sizeof(rgPin2));
printf("Cache is incorrect 1 change-fail ");
goto Ret;
}
//
// (2)
// Different LogonID, different Pin
//
SetLogonID(2);
Pins.cbCurrentPin -= 1;
Pins.cbNewPin = 0;
Pins.pbNewPin = NULL;
dwCallbackReturn = ERROR_SUCCESS;
if (SCARD_W_WRONG_CHV != (dwError =
PinCacheAdd(&hCache, &Pins,
pfnVerifyPin, (PVOID) &dwCallbackReturn)))
{
printf("PinCacheAdd 2 ");
goto Ret;
}
SetLogonID(1);
cbPin = sizeof(rgPin2);
if (ERROR_SUCCESS != (dwError = PinCacheQuery(hCache, pbPin, &cbPin)))
{
printf("PinCacheQuery 2 ");
goto Ret;
}
if (sizeof(rgPin2) != RtlCompareMemory(pbPin, rgPin2, cbPin))
{
PrintBytes("Actual cache", pbPin, cbPin);
PrintBytes("Expected cache", rgPin2, sizeof(rgPin2));
printf("Cache is incorrect 2 ");
goto Ret;
}
//
// (3)
// Different LogonID, same Pin
//
SetLogonID(2);
Pins.cbCurrentPin = sizeof(rgPin2);
if (ERROR_SUCCESS != (dwError =
PinCacheAdd(&hCache, &Pins,
pfnVerifyPin, (PVOID) &dwCallbackReturn)))
{
printf("PinCacheAdd 3 ");
goto Ret;
}
cbPin = sizeof(rgPin2);
if (ERROR_SUCCESS != (dwError = PinCacheQuery(hCache, pbPin, &cbPin)))
{
printf("PinCacheQuery 3 ");
goto Ret;
}
if (sizeof(rgPin2) != RtlCompareMemory(pbPin, rgPin2, cbPin))
{
PrintBytes("Actual cache", pbPin, cbPin);
PrintBytes("Expected cache", rgPin2, sizeof(rgPin2));
printf("Cache is incorrect 3 ");
goto Ret;
}
SetLogonID(1);
if (ERROR_SUCCESS != (dwError = PinCacheQuery(hCache, pbPin, &cbPin)))
{
printf("PinCacheQuery 3,1 ");
goto Ret;
}
if (0 != cbPin)
{
printf("PinCacheQuery 3,1 should have returned NULL pin ");
goto Ret;
}
//
// (4)
// Same LogonID, different Pin
//
SetLogonID(2);
Pins.cbCurrentPin -= 1;
if (SCARD_W_WRONG_CHV != (dwError =
PinCacheAdd(&hCache, &Pins,
pfnVerifyPin, (PVOID) &dwCallbackReturn)))
{
printf("PinCacheAdd 4 ");
goto Ret;
}
// cache should have been left intact
cbPin = sizeof(rgPin2);
if (ERROR_SUCCESS != (dwError = PinCacheQuery(hCache, pbPin, &cbPin)))
{
printf("PinCacheQuery 4 ");
goto Ret;
}
if (sizeof(rgPin2) != RtlCompareMemory(pbPin, rgPin2, cbPin))
{
PrintBytes("Actual cache", pbPin, cbPin);
PrintBytes("Expected cache", rgPin2, sizeof(rgPin2));
printf("Cache is incorrect 4 ");
goto Ret;
}
dwError = ERROR_SUCCESS;
fSuccess = TRUE;
Ret:
if (pbPin)
MyFree(pbPin);
if (! fSuccess)
{
printf("- error 0x%x\n", dwError);
if (0 == dwError)
return -1;
}
return dwError;
}
//
// Function: VerifyDesKeyParams
//
DWORD VerifyDesKeyParams(
IN HCRYPTKEY hKey,
IN DWORD dwExpectedKeyLen,
IN DWORD dwExpectedEffectiveKeyLen)
{
DWORD dwError = 0;
DWORD dwParam = 0;
DWORD cb = sizeof(dwParam);
BOOL fSuccess = FALSE;
if (! CryptGetKeyParam(hKey, KP_KEYLEN, (PBYTE) &dwParam, &cb, 0))
{
dwError = GetLastError();
printf("CryptGetKeyParam KP_KEYLEN ");
goto Ret;
}
if (dwExpectedKeyLen != dwParam)
{
printf(
"FAIL: VerifyDesKeyParams expected KP_KEYLEN=%d, actual=%d\n",
dwExpectedKeyLen, dwParam);
goto Ret;
}
if (! CryptGetKeyParam(hKey, KP_EFFECTIVE_KEYLEN, (PBYTE) &dwParam, &cb, 0))
{
dwError = GetLastError();
printf("CryptGetKeyParam KP_EFFECTIVE_KEYLEN ");
goto Ret;
}
if (dwExpectedEffectiveKeyLen != dwParam)
{
printf(
"FAIL: VerifyDesKeyParams expected KP_EFFECTIVE_KEYLEN=%d, actual=%d\n",
dwExpectedEffectiveKeyLen, dwParam);
goto Ret;
}
fSuccess = TRUE;
Ret:
if (! fSuccess)
{
printf(" - error 0x%x\n", dwError);
if (0 == dwError)
dwError = -1;
}
return dwError;
}
//
// Function: DesGetKeyParamRegression
//
DWORD DesGetKeyParamRegression(PTHREAD_DATA pThreadData)
{
DWORD dwError = ERROR_SUCCESS;
BOOL fSuccess = FALSE;
HCRYPTKEY hKey = 0;
if (! CryptGenKey(pThreadData->hProv, CALG_DES, 0, &hKey))
{
dwError = GetLastError();
printf("CryptGenKey des ");
goto Ret;
}
if (ERROR_SUCCESS != (dwError = VerifyDesKeyParams(hKey, 64, 56)))
{
printf("VerifyDesKeyParams des ");
goto Ret;
}
if (! CryptDestroyKey(hKey))
{
dwError = GetLastError();
printf("CryptDestroyKey des ");
goto Ret;
}
hKey = 0;
if (! CryptGenKey(pThreadData->hProv, CALG_3DES_112, 0, &hKey))
{
dwError = GetLastError();
printf("CryptGenKey 3des_112 ");
goto Ret;
}
if (ERROR_SUCCESS != (dwError = VerifyDesKeyParams(hKey, 128, 112)))
{
printf("VerifyDesKeyParams 3des_112 ");
goto Ret;
}
if (! CryptDestroyKey(hKey))
{
dwError = GetLastError();
printf("CryptDestroyKey 3des_112 ");
goto Ret;
}
hKey = 0;
if (! CryptGenKey(pThreadData->hProv, CALG_3DES, 0, &hKey))
{
dwError = GetLastError();
printf("CryptGenKey 3des ");
goto Ret;
}
if (ERROR_SUCCESS != (dwError = VerifyDesKeyParams(hKey, 192, 168)))
{
printf("VerifyDesKeyParams 3des ");
goto Ret;
}
if (! CryptDestroyKey(hKey))
{
dwError = GetLastError();
printf("CryptDestroyKey 3des ");
goto Ret;
}
fSuccess = TRUE;
Ret:
if (! fSuccess)
{
printf("- error 0x%x\n", dwError);
if (0 == dwError)
return -1;
}
return dwError;
}
//
// Function: MacEncryptRegression
//
DWORD MacEncryptRegression(
IN PTHREAD_DATA pThreadData)
{
DWORD dwError = ERROR_SUCCESS;
BOOL fSuccess = FALSE;
HCRYPTKEY hSymKey = 0;
HCRYPTKEY hMacKey = 0;
HCRYPTKEY hMacKey2 = 0;
HCRYPTHASH hMac = 0;
BYTE rgPlaintext[31];
DWORD cb = sizeof(rgPlaintext);
DWORD cbBuf = 0;
PBYTE pbMac = NULL;
DWORD cbMac = 0;
PBYTE pb = NULL;
if (! CryptGenKey(pThreadData->hProv, CALG_RC2, 0, &hSymKey))
{
printf("CryptGenKey rc2");
goto Ret;
}
if (! CryptGenKey(pThreadData->hProv, CALG_RC2, 0, &hMacKey))
{
printf("CryptGenKey rc2 2");
goto Ret;
}
if (! CryptDuplicateKey(hMacKey, NULL, 0, &hMacKey2))
{
printf("CryptDuplicateKey");
goto Ret;
}
if (! CryptCreateHash(pThreadData->hProv, CALG_MAC, hMacKey, 0, &hMac))
{
printf("CryptCreateHash");
goto Ret;
}
while (cb--)
rgPlaintext[cb] = (BYTE) cb;
cb = sizeof(rgPlaintext);
if (! CryptEncrypt(hSymKey, 0, TRUE, 0, NULL, &cb, 0))
{
printf("CryptEncrypt size");
goto Ret;
}
if (NULL == (pb = (PBYTE) MyAlloc(cb)))
return ERROR_NOT_ENOUGH_MEMORY;
cbBuf = cb;
cb = sizeof(rgPlaintext);
if (! CryptEncrypt(hSymKey, hMac, TRUE, 0, pb, &cb, cbBuf))
{
printf("CryptEncrypt");
goto Ret;
}
if (! CryptGetHashParam(hMac, HP_HASHVAL, NULL, &cbMac, 0))
{
printf("CryptGetHashParam size");
goto Ret;
}
if (NULL == (pbMac = (PBYTE) MyAlloc(cbMac)))
return ERROR_NOT_ENOUGH_MEMORY;
if (! CryptGetHashParam(hMac, HP_HASHVAL, pbMac, &cbMac, 0))
{
printf("CryptGetHashParam");
goto Ret;
}
if (! CryptDestroyHash(hMac))
{
printf("CryptDestroyHash");
goto Ret;
}
hMac = 0;
if (! CryptCreateHash(pThreadData->hProv, CALG_MAC, hMacKey2, 0, &hMac))
{
printf("CryptCreateHash 2");
goto Ret;
}
if (! CryptDecrypt(hSymKey, hMac, TRUE, 0, pb, &cb))
{
printf("CryptDecrypt");
goto Ret;
}
MyFree(pb);
pb = NULL;
if (! CryptGetHashParam(hMac, HP_HASHVAL, NULL, &cb, 0))
{
printf("CryptGetHashParam size");
goto Ret;
}
if (NULL == (pb = (PBYTE) MyAlloc(cb)))
return ERROR_NOT_ENOUGH_MEMORY;
if (! CryptGetHashParam(hMac, HP_HASHVAL, pb, &cb, 0))
{
printf("CryptGetHashParam");
goto Ret;
}
PrintBytes("Expected Mac result", pbMac, cbMac);
PrintBytes("Actual Mac result", pb, cb);
if (0 != memcmp(pb, pbMac, cb)
|| 0 == cb
|| cb != cbMac)
{
goto Ret;
}
fSuccess = TRUE;
Ret:
if (! fSuccess)
{
dwError = GetLastError();
printf(" - error 0x%x\n", dwError);
if (0 == dwError)
dwError = -1;
}
if (pb)
MyFree(pb);
if (pbMac)
MyFree(pbMac);
if (hSymKey)
CryptDestroyKey(hSymKey);
if (hMacKey)
CryptDestroyKey(hMacKey);
if (hMacKey2)
CryptDestroyKey(hMacKey2);
if (hMac)
CryptDestroyHash(hMac);
return dwError;
}
//
// Function: StressEncryptionTest
//
DWORD StressEncryptionTest(
IN HCRYPTPROV hProv,
IN PENCRYPTION_TEST_DATA pTestData)
{
HCRYPTKEY hEncryptionKey = 0;
HCRYPTKEY hHashKey1 = 0;
HCRYPTKEY hHashKey2 = 0;
HCRYPTHASH hHash = 0;
PBYTE pbData = 0;
DWORD dwData = 0;
DWORD cbData = 0;
DWORD cbPlainText = 0;
DWORD cbCipherText = 0;
DWORD cbProcessed = 0;
DWORD dwKeyAlg = 0;
DWORD dwBlockLen = 0;
BOOL fFinal = FALSE;
DWORD dwError = 0;
BOOL fSuccess = FALSE;
BYTE rgbHashVal1[200];
BYTE rgbHashVal2[200];
ZeroMemory(rgbHashVal1, 200);
ZeroMemory(rgbHashVal2, 200);
if (! CryptGenKey(
hProv,
pTestData->aiEncryptionKey,
0,
&hEncryptionKey))
{
goto Cleanup;
}
//
// Check for requested simultaneous encryption/hashing
//
if (pTestData->aiHash)
{
//
// Is this a keyed hash?
//
if (pTestData->aiHashKey)
{
if (! CryptGenKey(
hProv,
pTestData->aiHashKey,
0,
&hHashKey1))
{
goto Cleanup;
}
//
// To verify the result of hashing the same data in two
// separate keyed hashes, the key must first be duplicated,
// since its state changes once it's used.
//
if (! CryptDuplicateKey(
hHashKey1,
NULL,
0,
&hHashKey2))
{
goto Cleanup;
}
}
if (! CryptCreateHash(
hProv,
pTestData->aiHash,
hHashKey1,
0,
&hHash))
{
goto Cleanup;
}
}
//
// Is this a block encryption alg?
//
if (ALG_TYPE_BLOCK & pTestData->aiEncryptionKey)
{
//
// Get the block size of this encryption alg
//
cbData = sizeof(dwBlockLen);
if (! CryptGetKeyParam(
hEncryptionKey,
KP_BLOCKLEN,
(PBYTE) &dwBlockLen,
&cbData,
0))
{
goto Cleanup;
}
//
// Choose an "interesting" plaintext length, based on the block length
// of this alg.
//
cbPlainText = 2 * dwBlockLen + 1;
}
else
{
//
// Plaintext length for a stream encryption alg
//
cbPlainText = 500;
}
cbCipherText = cbPlainText;
//
// Determine size of ciphertext
//
if (! CryptEncrypt(
hEncryptionKey,
0,
TRUE,
0,
NULL,
&cbCipherText,
0))
{
goto Cleanup;
}
if (NULL == (pbData = (PBYTE) MyAlloc(cbCipherText)))
{
goto Cleanup;
}
//
// Initialize the plaintext
//
memset(pbData, 0xDA, cbPlainText);
memset(pbData + cbPlainText, 0, cbCipherText - cbPlainText);
//
// Encrypt
//
cbProcessed = 0;
while (! fFinal)
{
if (0 == dwBlockLen)
{
cbData = cbPlainText;
fFinal = TRUE;
}
else
{
if (cbPlainText - cbProcessed > dwBlockLen)
{
cbData = dwBlockLen;
}
else
{
cbData = cbPlainText % dwBlockLen;
fFinal = TRUE;
}
}
if (! CryptEncrypt(
hEncryptionKey,
hHash,
fFinal,
0,
pbData + cbProcessed,
&cbData,
cbCipherText))
{
goto Cleanup;
}
cbProcessed += cbData;
}
if (cbProcessed != cbCipherText)
{
goto Cleanup;
}
if (0 != hHash)
{
//
// Get hash result from encryption
//
cbData = sizeof(rgbHashVal1);
if (! CryptGetHashParam(
hHash,
HP_HASHVAL,
rgbHashVal1,
&cbData,
0))
{
goto Cleanup;
}
if (! CryptDestroyHash(hHash))
{
goto Cleanup;
}
if (! CryptCreateHash(
hProv,
pTestData->aiHash,
hHashKey2,
0,
&hHash))
{
goto Cleanup;
}
}
//
// Decrypt
//
cbProcessed = 0;
fFinal = FALSE;
while (! fFinal)
{
if (0 == dwBlockLen)
{
cbData = cbCipherText;
fFinal = TRUE;
}
else
{
if (cbCipherText - cbProcessed > dwBlockLen)
{
cbData = dwBlockLen;
}
else
{
cbData = cbCipherText - cbProcessed;
fFinal = TRUE;
}
}
if (! CryptDecrypt(
hEncryptionKey,
hHash,
fFinal,
0,
pbData + cbProcessed,
&cbData))
{
goto Cleanup;
}
cbProcessed += cbData;
}
if (cbProcessed != cbPlainText)
{
goto Cleanup;
}
while (cbPlainText)
{
if (0xDA != pbData[cbPlainText - 1])
{
goto Cleanup;
}
cbPlainText--;
}
if (0 != hHash)
{
//
// Get hash result from decryption
//
cbData = sizeof(rgbHashVal2);
if (! CryptGetHashParam(
hHash,
HP_HASHVAL,
rgbHashVal2,
&cbData,
0))
{
goto Cleanup;
}
if (0 != memcmp(rgbHashVal1, rgbHashVal2, cbData))
{
goto Cleanup;
}
}
fSuccess = TRUE;
Cleanup:
if (! fSuccess)
{
if (0 == (dwError = GetLastError()))
{
dwError = -1;
}
}
if (hEncryptionKey)
{
CryptDestroyKey(hEncryptionKey);
}
if (hHashKey1)
{
CryptDestroyKey(hHashKey1);
}
if (hHashKey2)
{
CryptDestroyKey(hHashKey2);
}
if (hHash)
{
CryptDestroyHash(hHash);
}
if (pbData)
{
MyFree(pbData);
}
return dwError;
}
//
// Function: StressTestAllEncryptionAlgs
//
DWORD StressTestAllEncryptionAlgs(
PTHREAD_DATA pThreadData,
BOOL fContinueOnMacError,
BOOL *pfMacErrorOccurred)
{
DWORD dwError = 0;
ENCRYPTION_TEST_DATA TestData;
PALGNODE pEncryptionAlg, pHashAlg, pBlockEncryptionAlg;
ZeroMemory(&TestData, sizeof(TestData));
for ( pEncryptionAlg = pThreadData->pAlgList;
NULL != pEncryptionAlg;
pEncryptionAlg = pEncryptionAlg->pNext)
{
if (! (pEncryptionAlg->EnumalgsEx.aiAlgid & ALG_CLASS_DATA_ENCRYPT))
continue;
TestData.aiEncryptionKey = pEncryptionAlg->EnumalgsEx.aiAlgid;
for ( pHashAlg = pThreadData->pAlgList;
NULL != pHashAlg;
pHashAlg = pHashAlg->pNext)
{
if ( (! (pHashAlg->EnumalgsEx.aiAlgid & ALG_CLASS_HASH &&
pHashAlg->EnumalgsEx.aiAlgid & ALG_TYPE_ANY)) ||
CALG_SSL3_SHAMD5 == pHashAlg->EnumalgsEx.aiAlgid ||
CALG_TLS1PRF == pHashAlg->EnumalgsEx.aiAlgid)
continue;
TestData.aiHash = pHashAlg->EnumalgsEx.aiAlgid;
if (CALG_MAC == pHashAlg->EnumalgsEx.aiAlgid)
{
for ( pBlockEncryptionAlg = pThreadData->pAlgList;
NULL != pBlockEncryptionAlg;
pBlockEncryptionAlg = pBlockEncryptionAlg->pNext)
{
if (! ( pBlockEncryptionAlg->EnumalgsEx.aiAlgid & ALG_CLASS_DATA_ENCRYPT &&
pBlockEncryptionAlg->EnumalgsEx.aiAlgid & ALG_TYPE_BLOCK))
continue;
TestData.aiHashKey = pBlockEncryptionAlg->EnumalgsEx.aiAlgid;
if (ERROR_SUCCESS != (dwError = StressEncryptionTest(pThreadData->hProv, &TestData)))
{
if (fContinueOnMacError)
*pfMacErrorOccurred = TRUE;
else
return dwError;
}
}
}
else
{
if (ERROR_SUCCESS != (dwError = StressEncryptionTest(pThreadData->hProv, &TestData)))
return dwError;
}
}
}
return dwError;
}
//+ ===========================================================================
//- ===========================================================================
void L_ErrorBox(LPSTR pszMsg, DWORD dwThreadNum)
{
char szErrorMsg[256] ;
sprintf(szErrorMsg, "Thread %d: %s in L_ErrorBox", dwThreadNum, pszMsg) ;
MessageBox(NULL, szErrorMsg, ERROR_CAPTION, MB_OK | MB_ICONERROR) ;
}
//+ ===========================================================================
//- ===========================================================================
void L_LastErrorBox(LPSTR pszMsg, DWORD dwThreadNum)
{
char szErrorMsg[256] ;
sprintf(szErrorMsg, "Thread %d: %s 0x%x in L_LastErrorBox", dwThreadNum, pszMsg, GetLastError()) ;
MessageBox(NULL, szErrorMsg, ERROR_CAPTION, MB_OK | MB_ICONERROR) ;
}
//+ =================================================================================
//
// L_GetKeyAlg
// Local function that given a key handle, returns the key Alg.
//
//- =================================================================================
DWORD L_GetKeyAlg(HCRYPTKEY hKey)
{
DWORD dwData = 0;
DWORD cbData=0 ;
char szErrorMsg[256];
cbData = sizeof(dwData) ;
if (!CryptGetKeyParam(
hKey,
KP_ALGID,
(PBYTE) &dwData,
&cbData,
0))
{
GENERIC_FAIL(CryptGetKeyParam) ;
}
ErrorReturn:
return dwData;
}
//+ =================================================================================
//
// L_GetKeySize
// Local function that given a key handle, returns the key length.
//
//- =================================================================================
DWORD L_GetKeySize(HCRYPTKEY hKey)
{
DWORD dwData = 0;
DWORD cbData=0 ;
char szErrorMsg[256];
cbData = sizeof(dwData) ;
if (!CryptGetKeyParam(
hKey,
KP_KEYLEN,
(PBYTE) &dwData,
&cbData,
0))
{
GENERIC_FAIL(CryptGetKeyParam) ;
}
ErrorReturn:
return dwData;
}
//+ ==============================================================================
//- ==============================================================================
DWORD Hlp_GetKeyAlgId(HCRYPTKEY hKey)
{
DWORD dwRetVal=0 ;
PBYTE pbData=NULL ;
DWORD cbData=sizeof(DWORD) ;
char szErrorMsg[256] ;
DWORD dwAlgId=0 ;
if (!CryptGetKeyParam(
hKey,
KP_ALGID,
(PBYTE)&dwAlgId,
&cbData,
0))
GENERIC_FAIL(CryptGetKeyParam) ;
dwRetVal=dwAlgId ;
ErrorReturn :
return dwRetVal ;
}
//+ =================================================================================
//
// L_GetKeyParam
// Local function that given a key handle, retrieves the specified Key Param.
// The Key param is not of too much interest in this case. In a multithread scenario,
// we just care to see if the call succeeds.
//
//- =================================================================================
DWORD L_GetKeyParam(HCRYPTKEY hKey, DWORD dwParam)
{
DWORD dwRetVal=0 ;
PBYTE pbData=NULL ;
DWORD cbData=0 ;
char szErrorMsg[256] ;
DWORD dwAlgId=0 ;
DWORD dwError=0 ;
if (!CryptGetKeyParam( hKey,
dwParam,
NULL,
&cbData,
0))
GENERIC_FAIL(CryptGetKeyParam) ;
if (NULL == (pbData = (PBYTE) MyAlloc(cbData)))
ALLOC_FAIL(pbData);
if (!CryptGetKeyParam( hKey,
dwParam,
pbData,
&cbData,
0))
GENERIC_FAIL(CryptGetKeyParam) ;
dwRetVal=1 ;
ErrorReturn :
MyFree(pbData) ;
return dwRetVal ;
}
//+ ======================================================================================
// ProgramInit
// Acquire context
// Generate Keys that will be used by all the threads. (AT_SIGNATURE and AT_KEYEXCHANGE)
//- ======================================================================================
DWORD ProgramInit(PTHREAD_DATA pThreadData)
{
DWORD dwRetVal = 0;
char szErrorMsg[256]; // defined for GENERIC_FAIL
LPSTR pszContainer = NULL;
DWORD dwContextFlags = 0;
DWORD dwKeyFlags = CRYPT_EXPORTABLE;
if (pThreadData->fEphemeralKeys)
{
dwContextFlags = CRYPT_VERIFYCONTEXT;
}
else
{
pszContainer = KEY_CONTAINER_NAME;
dwContextFlags = CRYPT_NEWKEYSET;
CryptAcquireContext(
&pThreadData->hProv,
pszContainer,
pThreadData->rgszProvName,
pThreadData->dwProvType,
CRYPT_DELETEKEYSET);
// Create a Verify Context for some of the sub-tests to use
if (! CryptAcquireContext(
&pThreadData->hVerifyCtx,
NULL,
pThreadData->rgszProvName,
pThreadData->dwProvType,
CRYPT_VERIFYCONTEXT))
{
pThreadData->hVerifyCtx = 0;
GENERIC_FAIL(CryptAcquireContext_VERIFYCONTEXT);
}
}
if (pThreadData->fUserProtectedKeys)
dwKeyFlags |= CRYPT_USER_PROTECTED;
if (!CryptAcquireContext(
&pThreadData->hProv,
pszContainer,
pThreadData->rgszProvName,
pThreadData->dwProvType,
dwContextFlags))
{
pThreadData->hProv = 0;
GENERIC_FAIL(CryptAcquireContext_Init);
}
// Generate a sign and exchange key
if (!CryptGenKey(
pThreadData->hProv,
AT_SIGNATURE,
dwKeyFlags,
&pThreadData->hSignatureKey))
{
GENERIC_FAIL(CryptGenKey_AT_SIGNATURE);
CryptReleaseContext(pThreadData->hProv, 0);
pThreadData->hProv = 0;
pThreadData->hSignatureKey = 0;
}
if (PROV_RSA_FULL == pThreadData->dwProvType ||
PROV_DSS_DH == pThreadData->dwProvType)
{
if (!CryptGenKey(
pThreadData->hProv,
AT_KEYEXCHANGE,
dwKeyFlags,
&pThreadData->hExchangeKey))
{
GENERIC_FAIL(CryptGenKey_AT_KEYEXCHANGE);
CryptReleaseContext(pThreadData->hProv, 0);
pThreadData->hProv = 0;
pThreadData->hExchangeKey = 0;
}
}
dwRetVal=1;
ErrorReturn:
return dwRetVal;
}
// ======================================================================================
// Terminates all the threads after the specified amount of time has elapsed (-t option)
// This thread sleeps for the specified amount of time and them then turns off the
// g_dwLoopSwitch.
// ======================================================================================
void WINAPI KillProgramTimer(LPVOID pvThreadData)
{
DWORD dwSleepTime=0;
PTHREAD_DATA pThreadData = (PTHREAD_DATA) pvThreadData;
if (pThreadData->dwProgramMins)
{
dwSleepTime = pThreadData->dwProgramMins * 60 * 1000;
SleepEx(dwSleepTime, FALSE);
if (! SetEvent(pThreadData->hEndTestEvent))
{
printf("SetEvent() failed, 0x%x\n", GetLastError());
exit(1);
}
printf("All threads should be shutting down now....\n");
}
}
// ======================================================================================
// Prints the status of all the threads
// The status is represented in iteration count in ThreadStatus[i][0]
// ======================================================================================
void WINAPI PrintThreadStatus(LPVOID pvThreadData)
{
DWORD thread;
PTHREAD_DATA pThreadData = (PTHREAD_DATA) pvThreadData;
char rgStatus[256] ;
printf("\n\n\n") ;
while (WAIT_TIMEOUT == WaitForSingleObject(pThreadData->hEndTestEvent, 0))
{
Sleep(10000);
ZeroMemory(rgStatus, sizeof(rgStatus));
for (thread = 0; thread < pThreadData->dwThreadCount; thread++)
{
sprintf(
rgStatus + strlen(rgStatus),
" %4x",
pThreadData->rgdwThreadStatus[thread]);
}
printf("%s\n", rgStatus);
}
}
//+ ========================================================================
//
// Function : L_GetAllKeyParams
// Purpose : Gets all the key params and does nothing with it
//
//- ========================================================================
DWORD L_GetAllKeyParams(HCRYPTKEY hKey, DWORD dwThreadNum)
{
char szErrorMsg[256] ;
ALG_ID AlgId=0 ;
DWORD dwRetVal=0 ;
AlgId = (ALG_ID)Hlp_GetKeyAlgId(hKey) ;
// Get Keys Length
if (!L_GetKeyParam(hKey, KP_KEYLEN))
{
sprintf(szErrorMsg, "Thread %d: L_GetKeyParam KP_KEYLEN error 0x%x",
dwThreadNum, GetLastError()) ;
MessageBox(NULL, szErrorMsg, ERROR_CAPTION, MB_OK | MB_ICONERROR) ;
goto ErrorReturn ;
}
// Get ALGID
if (!L_GetKeyParam(hKey, KP_ALGID))
{
sprintf(szErrorMsg, "Thread %d: L_GetKeyParam KP_ALGID error 0x%x",
dwThreadNum, GetLastError()) ;
MessageBox(NULL, szErrorMsg, ERROR_CAPTION, MB_OK | MB_ICONERROR) ;
goto ErrorReturn ;
}
// Get KP_BLOCKLEN
// Although this is meaningful only for block cipher keys, it will not fail
// for RSA Keys. It'll just return 0 as the block len (which we don't care
// about for multi tests.
if (!L_GetKeyParam(hKey, KP_BLOCKLEN))
{
sprintf(szErrorMsg, "Thread %d: L_GetKeyParam KP_BLOCKLEN error 0x%x",
dwThreadNum, GetLastError()) ;
MessageBox(NULL, szErrorMsg, ERROR_CAPTION, MB_OK | MB_ICONERROR) ;
goto ErrorReturn ;
}
/*
if (! (ALG_CLASS_SIGNATURE == GET_ALG_CLASS(AlgId)
|| ALG_CLASS_KEY_EXCHANGE == GET_ALG_CLASS(AlgId)))
{
if (!L_GetKeyParam(hKey, KP_SALT))
{
sprintf(szErrorMsg, "Thread %d: L_GetKeyParam KP_SALT error 0x%x",
dwThreadNum, GetLastError()) ;
MessageBox(NULL, szErrorMsg, ERROR_CAPTION, MB_OK | MB_ICONERROR) ;
goto ErrorReturn ;
}
}
*/
// Get KP_PERMISSIONS
if (!L_GetKeyParam(hKey, KP_PERMISSIONS))
{
sprintf(szErrorMsg, "Thread %d: L_GetKeyParam KP_PERMISSION error 0x%x",
dwThreadNum, GetLastError()) ;
MessageBox(NULL, szErrorMsg, ERROR_CAPTION, MB_OK | MB_ICONERROR) ;
goto ErrorReturn ;
}
// Effective KeyLen can be queried only for RC2 key
if (CALG_RC2 == AlgId)
{
// Get KP_EFFECTIVE_KEYLEN
if (!L_GetKeyParam(hKey, KP_EFFECTIVE_KEYLEN))
{
sprintf(szErrorMsg, "Thread %d: L_GetKeyParam KP_EFFECTIVE_KEYLEN error 0x%x",
dwThreadNum, GetLastError()) ;
MessageBox(NULL, szErrorMsg, ERROR_CAPTION, MB_OK | MB_ICONERROR) ;
goto ErrorReturn ;
}
}
// These Key Params are good only for Block Cipher Keys
if (ALG_TYPE_BLOCK == GET_ALG_TYPE(AlgId)
&& ALG_CLASS_DATA_ENCRYPT == GET_ALG_CLASS(AlgId))
{
// Get KP_IV
if (!L_GetKeyParam(hKey, KP_IV))
{
sprintf(szErrorMsg, "Thread %d: L_GetKeyParam KP_IV error 0x%x",
dwThreadNum, GetLastError()) ;
MessageBox(NULL, szErrorMsg, ERROR_CAPTION, MB_OK | MB_ICONERROR) ;
goto ErrorReturn ;
}
// Get KP_PADDING
if (!L_GetKeyParam(hKey, KP_PADDING))
{
sprintf(szErrorMsg, "Thread %d: L_GetKeyParam KP_PADDING error 0x%x",
dwThreadNum, GetLastError()) ;
MessageBox(NULL, szErrorMsg, ERROR_CAPTION, MB_OK | MB_ICONERROR) ;
goto ErrorReturn ;
}
// Get KP_MODE
if (!L_GetKeyParam(hKey, KP_MODE))
{
sprintf(szErrorMsg, "Thread %d: L_GetKeyParam KP_MODE error 0x%x",
dwThreadNum, GetLastError()) ;
MessageBox(NULL, szErrorMsg, ERROR_CAPTION, MB_OK | MB_ICONERROR) ;
goto ErrorReturn ;
}
// Get KP_MODE_BITS
if (!L_GetKeyParam(hKey, KP_MODE_BITS))
{
sprintf(szErrorMsg, "Thread %d: L_GetKeyParam KP_MODE_BITS error 0x%x",
dwThreadNum, GetLastError()) ;
MessageBox(NULL, szErrorMsg, ERROR_CAPTION, MB_OK | MB_ICONERROR) ;
goto ErrorReturn ;
}
}
dwRetVal=1 ;
ErrorReturn :
return dwRetVal ;
}
/*
L_ProvParam2Text
dangriff -- Modifying this function so that caller must free the psz
return value.
*/
char *L_ProvParam2Text(DWORD dwParam)
{
LPSTR pszProvParamText = NULL;
if (NULL == (pszProvParamText = (LPSTR) MyAlloc(PROV_PARAM_BUFFER_SIZE)))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
switch(dwParam)
{
case PP_ENUMALGS :
strcpy(pszProvParamText, "PP_ENUMALGS") ;
break ;
case PP_ENUMCONTAINERS :
strcpy(pszProvParamText, "PP_ENUMCONTAINERS") ;
break ;
case PP_IMPTYPE :
strcpy(pszProvParamText, "PP_IMPTYPE") ;
break ;
case PP_NAME :
strcpy(pszProvParamText, "PP_NAME") ;
break ;
case PP_VERSION :
strcpy(pszProvParamText, "PP_VERSION") ;
break ;
case PP_CONTAINER :
strcpy(pszProvParamText, "PP_CONTAINER") ;
break ;
case PP_CHANGE_PASSWORD :
strcpy(pszProvParamText, "PP_CHANGE_PASSWORD") ;
break ;
case PP_KEYSET_SEC_DESCR :
strcpy(pszProvParamText, "PP_KEYSET_SEC_DESCR") ;
break ;
case PP_CERTCHAIN :
strcpy(pszProvParamText, "PP_CERTCHAIN") ;
break ;
case PP_KEY_TYPE_SUBTYPE :
strcpy(pszProvParamText, "PP_KEY_TYPE_SUBTYPE") ;
break ;
case PP_PROVTYPE :
strcpy(pszProvParamText, "PP_PROVTYPE") ;
break ;
case PP_KEYSTORAGE :
strcpy(pszProvParamText, "PP_KEYSTORAGE") ;
break ;
case PP_APPLI_CERT :
strcpy(pszProvParamText, "PP_APPLI_CERT") ;
break ;
case PP_SYM_KEYSIZE :
strcpy(pszProvParamText, "PP_SYM_KEYSIZE") ;
break ;
case PP_SESSION_KEYSIZE :
strcpy(pszProvParamText, "PP_SESSION_KEYSIZE") ;
break ;
case PP_UI_PROMPT :
strcpy(pszProvParamText, "PP_UI_PROMPT") ;
break ;
case PP_ENUMALGS_EX :
strcpy(pszProvParamText, "PP_ENUMALGS_EX") ;
break ;
case PP_ENUMMANDROOTS :
strcpy(pszProvParamText, "PP_ENUMMANDROOTS") ;
break ;
case PP_ENUMELECTROOTS :
strcpy(pszProvParamText, "PP_ENUMELECTROOTS") ;
break ;
case PP_KEYSET_TYPE :
strcpy(pszProvParamText, "PP_KEYSET_TYPE") ;
break ;
case PP_ADMIN_PIN :
strcpy(pszProvParamText, "PP_ADMIN_PIN") ;
break ;
case PP_KEYEXCHANGE_PIN :
strcpy(pszProvParamText, "PP_KEYEXCHANGE_PIN") ;
break ;
case PP_SIGNATURE_PIN :
strcpy(pszProvParamText, "PP_SIGNATURE_PIN") ;
break ;
case PP_SIG_KEYSIZE_INC :
strcpy(pszProvParamText, "PP_SIG_KEYSIZE_INC") ;
break ;
case PP_KEYX_KEYSIZE_INC :
strcpy(pszProvParamText, "PP_KEYX_KEYSIZE_INC") ;
break ;
case PP_UNIQUE_CONTAINER :
strcpy(pszProvParamText, "PP_UNIQUE_CONTAINER") ;
break ;
case PP_SGC_INFO :
strcpy(pszProvParamText, "PP_SGC_INFO") ;
break ;
case PP_USE_HARDWARE_RNG :
strcpy(pszProvParamText, "PP_USE_HARDWARE_RNG") ;
break ;
case PP_KEYSPEC :
strcpy(pszProvParamText, "PP_KEYSPEC") ;
break ;
case PP_ENUMEX_SIGNING_PROT :
strcpy(pszProvParamText, "PP_ENUMEX_SIGNING_PROT") ;
break ;
}
return pszProvParamText ;
}
//+ ==================================================================
//
// Function : L_GetProvParam
// Purpose : Gets the requested Prov Param
// Does nothing with the ProvParam
// Has special logic for all enumeration params
//
//- ==================================================================
DWORD L_GetProvParam(HCRYPTPROV hProv, DWORD dwParam, DWORD dwThreadNum)
{
PBYTE pbProvData=NULL ;
DWORD cbProvData=0 ;
DWORD dwFlags=0 ;
DWORD dwEnumFlag=0 ;
char szErrorMsg[256] ;
DWORD dwRetVal=0 ;
LPSTR pszProvParamText = NULL;
DWORD dwError = 0;
if ((PP_ENUMALGS == dwParam) ||
(PP_ENUMALGS_EX == dwParam) ||
(PP_ENUMCONTAINERS == dwParam))
{
dwEnumFlag = 1 ;
dwFlags = CRYPT_FIRST ;
}
// dwFlags needs to be set in the case of PP_KEYSET_SECR_DECR
if (PP_KEYSET_SEC_DESCR == dwParam)
{
dwFlags = SACL_SECURITY_INFORMATION ;
}
if (!CryptGetProvParam( hProv,
dwParam,
NULL,
&cbProvData,
dwFlags))
{
if ((ERROR_PRIVILEGE_NOT_HELD == (dwError = GetLastError())) &&
(PP_KEYSET_SEC_DESCR == dwParam))
{
// At this point the test has done it's job. The call is an expected failure call
// so we aren't going to try and make any more.
// This call with fail with that expected LastError.
dwRetVal=1 ;
goto ErrorReturn ;
}
else
{
pszProvParamText = L_ProvParam2Text(dwParam);
sprintf(szErrorMsg, "Thread %d: CryptGetProvParam 1 %s error 0x%x",
dwThreadNum, pszProvParamText, dwError) ;
MessageBox(NULL, szErrorMsg, ERROR_CAPTION, MB_OK | MB_ICONERROR) ;
MyFree(pszProvParamText);
goto ErrorReturn ;
}
}
if (NULL == (pbProvData = (PBYTE) MyAlloc(cbProvData)))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return 0;
}
// If this is an enumeration, keep calling the function until
// the enumeration reaches the end.
do
{
if (!CryptGetProvParam( hProv,
dwParam,
pbProvData,
&cbProvData,
dwFlags))
{
// Have we reached the end of the enumeration ? If yes, flag it.
if (ERROR_NO_MORE_ITEMS == (dwError = GetLastError()))
{
dwEnumFlag=0 ;
}
else
{
pszProvParamText = L_ProvParam2Text(dwParam);
sprintf(szErrorMsg, "Thread %d: CryptGetProvParam 2 %s error 0x%x",
dwThreadNum, pszProvParamText, dwError) ;
MessageBox(NULL, szErrorMsg, ERROR_CAPTION, MB_OK | MB_ICONERROR) ;
MyFree(pszProvParamText);
goto ErrorReturn ;
}
}
dwFlags=0 ;
} while (dwEnumFlag) ;
dwRetVal=1 ;
ErrorReturn :
MyFree(pbProvData) ;
return dwRetVal ;
}
//+ =================================================================================
//- =================================================================================
/*
DWORD L_GetAllProvParams(HCRYPTPROV hProv, DWORD dwThreadNum)
{
DWORD dwRetVal=0 ;
EnterCriticalSection(&g_CSEnumParam);
if (!L_GetProvParam(hProv, PP_ENUMALGS, dwThreadNum))
{
LeaveCriticalSection(&g_CSEnumParam);
goto ErrorReturn;
}
LeaveCriticalSection(&g_CSEnumParam);
if (!L_CheckHeap(dwThreadNum, "after L_GetProvParam PP_ENUMALGS"))
goto ErrorReturn ;
EnterCriticalSection(&g_CSEnumParam);
if (!L_GetProvParam(hProv, PP_ENUMALGS, dwThreadNum))
{
LeaveCriticalSection(&g_CSEnumParam);
goto ErrorReturn ;
}
LeaveCriticalSection(&g_CSEnumParam);
if (!L_CheckHeap(dwThreadNum, "after L_GetProvParam PP_ENUMALGS"))
goto ErrorReturn ;
EnterCriticalSection(&g_CSEnumParam);
if (!L_GetProvParam(hProv, PP_ENUMCONTAINERS, dwThreadNum))
{
LeaveCriticalSection(&g_CSEnumParam);
goto ErrorReturn ;
}
LeaveCriticalSection(&g_CSEnumParam);
if (!L_GetProvParam(hProv, PP_NAME, dwThreadNum))
goto ErrorReturn ;
if (!L_CheckHeap(dwThreadNum, "after L_GetProvParam PP_NAME"))
goto ErrorReturn ;
if (!L_GetProvParam(hProv, PP_CONTAINER, dwThreadNum))
goto ErrorReturn ;
if (!L_CheckHeap(dwThreadNum, "after L_GetProvParam PP_CONTAINER"))
goto ErrorReturn ;
if (!L_GetProvParam(hProv, PP_IMPTYPE, dwThreadNum))
goto ErrorReturn ;
if (!L_CheckHeap(dwThreadNum, "after L_GetProvParam PP_IMPTYPE"))
goto ErrorReturn ;
if (!L_GetProvParam(hProv, PP_VERSION, dwThreadNum))
goto ErrorReturn ;
if (!L_CheckHeap(dwThreadNum, "after L_GetProvParam PP_VERSION"))
goto ErrorReturn ;
if (!L_GetProvParam(hProv, PP_KEYSET_SEC_DESCR, dwThreadNum))
goto ErrorReturn ;
if (!L_CheckHeap(dwThreadNum, "after L_GetProvParam PP_KEYSET_SEC_DESCR"))
goto ErrorReturn ;
if (!L_GetProvParam(hProv, PP_UNIQUE_CONTAINER, dwThreadNum))
goto ErrorReturn ;
if (!L_CheckHeap(dwThreadNum, "after L_GetProvParam PP_UNIQUE_CONTAINER"))
goto ErrorReturn ;
if (!L_GetProvParam(hProv, PP_PROVTYPE, dwThreadNum))
goto ErrorReturn ;
if (!L_CheckHeap(dwThreadNum, "after L_GetProvParam PP_PROVTYPE"))
goto ErrorReturn ;
if (!L_GetProvParam(hProv, PP_SIG_KEYSIZE_INC, dwThreadNum))
goto ErrorReturn ;
if (!L_CheckHeap(dwThreadNum, "after L_GetProvParam PP_SIG_KEYSIZE_INC"))
goto ErrorReturn ;
if (!L_GetProvParam(hProv, PP_KEYX_KEYSIZE_INC, dwThreadNum))
goto ErrorReturn ;
dwRetVal=1 ;
ErrorReturn :
return dwRetVal ;
}
*/
//+ ======================================================================
//- ======================================================================
DWORD L_ImportAndCheckSessionKeys( HCRYPTPROV hProv,
HCRYPTKEY hKeyExch,
PBYTE pbRCx_KeyBlob,
DWORD cbRCx_KeyBlob,
PBYTE pbRCx_CipherText,
DWORD cbRCx_CipherText,
PBYTE pbPlainText,
DWORD cbPlainText,
DWORD dwThreadNum)
{
DWORD dwRetVal=0 ;
HCRYPTKEY hRCxKey=0 ;
if (!CryptImportKey(hProv,
pbRCx_KeyBlob,
cbRCx_KeyBlob,
hKeyExch,
0,
&hRCxKey))
L_LastErrorBox("Failed to import session Key", dwThreadNum) ;
if (!CryptDecrypt(hRCxKey,
0,
TRUE,
0,
pbRCx_CipherText,
&cbRCx_CipherText))
L_LastErrorBox("Failed CryptDecrypt", dwThreadNum) ;
if (memcmp(pbRCx_CipherText, pbPlainText, cbPlainText))
L_ErrorBox("Ciphertext does not match plaintext after decrypting", dwThreadNum) ;
//ErrorReturn :
if (!CryptDestroyKey(hRCxKey))
L_LastErrorBox("Failed CryptDestroyKey sessionKey", dwThreadNum) ;
dwRetVal=1 ;
return dwRetVal ;
}
//+ ======================================================================
//- ======================================================================
DWORD L_TestContextAddRef(HCRYPTPROV hProv, DWORD dwThreadNum)
{
DWORD dwRetVal=0 ;
DWORD i=0 ;
DWORD dwCount=50 ;
for (i=0; i<dwCount ; i++)
{
if (!CryptContextAddRef(hProv, NULL, 0))
{
L_LastErrorBox("Failed CryptContextAddRef", dwThreadNum) ;
goto ErrorReturn ;
}
}
for (i=0; i<dwCount ; i++)
{
if (!CryptReleaseContext(hProv, 0))
{
L_LastErrorBox("Failed CryptReleaseContext (AddRef Test)", dwThreadNum) ;
goto ErrorReturn ;
}
}
dwRetVal=1 ;
ErrorReturn :
return dwRetVal ;
}
//+ ===========================================================================
// L_ExportKey
//
// Exports a session key, given the exchange key
// Mem Allocated here needs to be freed by the calling funtion.
//- ===========================================================================
DWORD L_ExportKey( HCRYPTKEY hRC_Key,
HCRYPTKEY hKeyExch,
DWORD dwType,
DWORD dwMustBeZero,
PBYTE *ppbRC_KeyBlob,
DWORD *pcbRC_KeyBlob)
{
DWORD dwRetVal=0 ;
char szErrorMsg[256] ;
if (!CryptExportKey(hRC_Key,
hKeyExch,
dwType,
0,
NULL,
pcbRC_KeyBlob))
GENERIC_FAIL(CryptExportKey_RC) ;
if (NULL == (*ppbRC_KeyBlob = (PBYTE) MyAlloc(*pcbRC_KeyBlob)))
return 0;
memset(*ppbRC_KeyBlob, 33, *pcbRC_KeyBlob) ;
if (!CryptExportKey(hRC_Key,
hKeyExch,
SIMPLEBLOB,
0,
*ppbRC_KeyBlob,
pcbRC_KeyBlob))
GENERIC_FAIL(CryptExportKey_RC) ;
dwRetVal=1 ;
ErrorReturn :
return dwRetVal ;
}
//+ ==========================================================================
//
//
//- ==========================================================================
DWORD L_GetHashParam(HCRYPTHASH hHash, DWORD dwParam)
{
DWORD dwRetVal=0 ;
char szErrorMsg[256] ;
PBYTE pbData=NULL ;
DWORD cbData=0 ;
if (!CryptGetHashParam( hHash,
dwParam,
NULL,
&cbData,
0))
GENERIC_FAIL(CryptGetHashParam) ;
if (NULL == (pbData = (PBYTE) MyAlloc(cbData)))
return 0;
if (!CryptGetHashParam( hHash,
dwParam,
pbData,
&cbData,
0))
GENERIC_FAIL(CryptGetHashParam) ;
dwRetVal=1 ;
ErrorReturn :
MyFree(pbData) ;
return dwRetVal ;
}
//+ ==========================================================================
//
//
//- ==========================================================================
DWORD L_GetAllHashParams(HCRYPTHASH hHash, DWORD dwThreadNum)
{
DWORD dwRetVal=0 ;
char szErrorMsg[256] ;
if (!L_GetHashParam(hHash, HP_ALGID))
goto ErrorReturn ;
if (!L_GetHashParam(hHash, HP_HASHSIZE))
goto ErrorReturn ;
if (!L_GetHashParam(hHash, HP_HASHVAL))
goto ErrorReturn ;
dwRetVal=1 ;
ErrorReturn :
return dwRetVal ;
}
//
// Function: ThreadAcquireContextTest
//
DWORD ThreadAcquireContextTest(PTHREAD_DATA pThreadData, DWORD dwThreadNum)
{
HCRYPTPROV hProv = 0;
HCRYPTKEY hKey = 0;
DWORD dwError = 0;
CHAR rgsz[100];
ZeroMemory(rgsz, sizeof(rgsz));
sprintf(rgsz, "%s_%d", "ThreadContainer", dwThreadNum);
if (! CryptAcquireContext(
&hProv, rgsz, pThreadData->rgszProvName,
pThreadData->dwProvType, 0))
{
dwError = GetLastError();
printf("CryptAcquireContext: %s, %d, 0x%x\n", rgsz, dwThreadNum, dwError);
if (NTE_BAD_KEYSET == dwError)
{
if (! CryptAcquireContext(
&hProv, rgsz, pThreadData->rgszProvName,
pThreadData->dwProvType, CRYPT_NEWKEYSET))
{
dwError = GetLastError();
printf("CryptAcquireContext CRYPT_NEWKEYSET: %s, %d, 0x%x\n", rgsz, dwThreadNum, dwError);
goto Ret;
}
}
else
goto Ret;
}
if (! CryptGetUserKey(hProv, AT_SIGNATURE, &hKey))
{
if (NTE_NO_KEY == (dwError = GetLastError()))
{
if (! CryptGenKey(hProv, AT_SIGNATURE, 0, &hKey))
{
dwError = GetLastError();
goto Ret;
}
}
else
goto Ret;
}
if (! CryptDestroyKey(hKey))
{
dwError = GetLastError();
goto Ret;
}
if (! CryptReleaseContext(hProv, 0))
{
dwError = GetLastError();
goto Ret;
}
dwError = 0;
Ret:
return dwError;
}
//
// Function: ThreadHashingTest
//
DWORD ThreadHashingTest(PTHREAD_DATA pThreadData, PBYTE pbData, DWORD cbData)
{
HCRYPTHASH hHash = 0;
HCRYPTKEY hKey = 0;
BYTE rgHash[100];
DWORD cb = 0;
DWORD dwError = 0;
PALGNODE pHashAlg;
for ( pHashAlg = pThreadData->pAlgList;
NULL != pHashAlg;
pHashAlg = pHashAlg->pNext)
{
if (CALG_SHA1 != pHashAlg->EnumalgsEx.aiAlgid &&
CALG_MD5 != pHashAlg->EnumalgsEx.aiAlgid)
continue;
if (! CryptCreateHash(pThreadData->hProv, pHashAlg->EnumalgsEx.aiAlgid, 0, 0, &hHash))
{
dwError = GetLastError();
goto Ret;
}
if (! CryptHashData(hHash, pbData, cbData, 0))
{
dwError = GetLastError();
goto Ret;
}
if (! CryptHashData(hHash, pbData, cbData, 0))
{
dwError = GetLastError();
goto Ret;
}
cb = sizeof(rgHash);
if (! CryptGetHashParam(hHash, HP_HASHVAL, rgHash, &cb, 0))
{
dwError = GetLastError();
goto Ret;
}
if (! CryptDestroyHash(hHash))
{
dwError = GetLastError();
goto Ret;
}
hHash = 0;
}
//dwError = HmacRegression(pThreadData);
Ret:
return dwError;
}
//
// Function: ThreadSignatureTest
//
DWORD ThreadSignatureTest(PTHREAD_DATA pThreadData)
{
HCRYPTHASH hHash = 0;
PBYTE pbData = NULL;
DWORD cbData = 0;
PBYTE pbSignature = NULL;
DWORD cbSignature = 0;
DWORD dwError = 0;
PALGNODE pHashAlg = NULL;
if (! CryptCreateHash(
pThreadData->hProv, CALG_SHA1, 0, 0, &hHash))
{
dwError = GetLastError();
goto Ret;
}
cbData = SIGN_DATA_SIZE;
if (NULL == (pbData = (PBYTE) MyAlloc(cbData)))
{
dwError = ERROR_NOT_ENOUGH_MEMORY;
goto Ret;
}
if (! CryptGenRandom(
pThreadData->hProv, cbData, pbData))
{
dwError = GetLastError();
goto Ret;
}
if (! CryptHashData(
hHash, pbData, cbData, 0))
{
dwError = GetLastError();
goto Ret;
}
if (! CryptSignHash(
hHash, AT_SIGNATURE, NULL, 0, NULL, &cbSignature))
{
dwError = GetLastError();
goto Ret;
}
if (NULL == (pbSignature = (PBYTE) MyAlloc(cbSignature)))
{
dwError = ERROR_NOT_ENOUGH_MEMORY;
goto Ret;
}
if (! CryptSignHash(
hHash, AT_SIGNATURE, NULL, 0, pbSignature, &cbSignature))
{
dwError = GetLastError();
goto Ret;
}
if (! CryptVerifySignature(
hHash, pbSignature, cbSignature,
pThreadData->hSignatureKey, NULL, 0))
{
dwError = GetLastError();
goto Ret;
}
if (! CryptDestroyHash(hHash))
{
dwError = GetLastError();
goto Ret;
}
MyFree(pbData);
MyFree(pbSignature);
Ret:
return dwError;
}
// ======================================================================================
// MULTITHREADED routine
// ======================================================================================
void WINAPI ThreadRoutine(LPVOID pvThreadData)
{
DWORD dwThreadNum = 0;
DWORD dwError = 0;
BOOL fMacErrorOccurred = FALSE;
PTHREAD_DATA pThreadData = (PTHREAD_DATA) pvThreadData;
CHAR szErrorMsg[256];
BYTE rgbData[HASH_DATA_SIZE];
// Get identifier for this thread
EnterCriticalSection(&pThreadData->CSThreadData);
dwThreadNum = pThreadData->dwThreadID;
pThreadData->dwThreadID++;
LeaveCriticalSection(&pThreadData->CSThreadData);
if (! CryptGenRandom(pThreadData->hProv, sizeof(rgbData), rgbData))
{
dwError = GetLastError();
goto ErrorReturn;
}
do
{
if (RUN_THREAD_SIGNATURE_TEST & pThreadData->dwTestsToRun)
{
if (ERROR_SUCCESS != (dwError = ThreadSignatureTest(pThreadData)))
{
sprintf(
szErrorMsg,
"Thread %d: ThreadSignatureTest error 0x%x",
dwThreadNum,
dwError);
MessageBox(NULL, szErrorMsg, ERROR_CAPTION, MB_OK | MB_ICONERROR);
goto ErrorReturn;
}
}
if (RUN_STRESS_TEST_ALL_ENCRYPTION_ALGS & pThreadData->dwTestsToRun)
{
//
// Call new shared encryption stress tests
//
if (ERROR_SUCCESS != (dwError =
StressTestAllEncryptionAlgs(pThreadData, TRUE, &fMacErrorOccurred)))
{
sprintf(
szErrorMsg,
"Thread %d: StressTestAllEncryptionAlgs error 0x%x",
dwThreadNum,
dwError);
MessageBox(NULL, szErrorMsg, ERROR_CAPTION, MB_OK | MB_ICONERROR);
goto ErrorReturn;
}
}
if (RUN_THREAD_HASHING_TEST & pThreadData->dwTestsToRun)
{
if (ERROR_SUCCESS != (dwError = ThreadHashingTest(pThreadData, rgbData, sizeof(rgbData))))
{
sprintf(
szErrorMsg,
"Thread %d: ThreadHashingTest error 0x%x",
dwThreadNum,
dwError);
MessageBox(NULL, szErrorMsg, ERROR_CAPTION, MB_OK | MB_ICONERROR);
goto ErrorReturn;
}
}
if (RUN_THREAD_ACQUIRE_CONTEXT_TEST & pThreadData->dwTestsToRun)
{
if (ERROR_SUCCESS != (dwError = ThreadAcquireContextTest(pThreadData, dwThreadNum)))
{
sprintf(
szErrorMsg,
"Thread %d: ThreadAcquireContextTest error 0x%x",
dwThreadNum,
dwError);
MessageBox(NULL, szErrorMsg, ERROR_CAPTION, MB_OK | MB_ICONERROR);
goto ErrorReturn;
}
}
pThreadData->rgdwThreadStatus[dwThreadNum]++;
}
while (WAIT_TIMEOUT == WaitForSingleObject(pThreadData->hEndTestEvent, 0));
ErrorReturn:
if (fMacErrorOccurred)
{
printf("ERROR: Mac bug 189368 is not fixed!\n");
}
return;
}
//
// Function: GetNextRegisteredCSP
//
DWORD GetNextRegisteredCSP(
LPSTR pszCsp,
PDWORD pcbCsp,
PDWORD pdwProvType,
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,
pszCsp,
pcbCsp))
{
dwError = GetLastError();
switch (dwError)
{
case ERROR_NO_MORE_ITEMS:
dwNextEnumIndex = 0;
break;
}
}
else
{
if (ENUMERATE_REGISTERED_CSP == dwRequestedIndex)
{
dwNextEnumIndex++;
}
}
return dwError;
}
//
// Function: InitializeAlgList
// Purpose: Create a list of algorithms supported by this CSP
//
DWORD InitializeAlgList(PTHREAD_DATA pThreadData)
{
PALGNODE pAlgNode = NULL, pPrevNode = NULL;
DWORD dwError = 0;
DWORD cbData = sizeof(ALGNODE);
DWORD dwFlags = CRYPT_FIRST;
if (NULL == (pThreadData->pAlgList = (PALGNODE) MyAlloc(sizeof(ALGNODE))))
return ERROR_NOT_ENOUGH_MEMORY;
pAlgNode = pThreadData->pAlgList;
while (CryptGetProvParam(
pThreadData->hProv,
PP_ENUMALGS_EX,
(PBYTE) &pAlgNode->EnumalgsEx,
&cbData,
dwFlags))
{
dwFlags = 0;
if (NULL == (pAlgNode->pNext = (PALGNODE) MyAlloc(sizeof(ALGNODE))))
return ERROR_NOT_ENOUGH_MEMORY;
pPrevNode = pAlgNode;
pAlgNode = pAlgNode->pNext;
}
if (ERROR_NO_MORE_ITEMS != (dwError = GetLastError()))
return dwError;
MyFree(pAlgNode);
pPrevNode->pNext = NULL;
return ERROR_SUCCESS;
}
//
// Function: RunRegressionTests
//
BOOL RunRegressionTests(PTHREAD_DATA pThreadData)
{
DWORD dwError = ERROR_SUCCESS;
unsigned u;
BOOL fAllPassed = TRUE;
for (u = 0; u < g_cRegressTests; u++)
{
if (pThreadData->dwProvType & g_rgRegressTests[u].dwExclude)
{
printf(
"Skipping %s\n\n", g_rgRegressTests[u].pszDescription);
continue;
}
if (ERROR_SUCCESS !=
(dwError = (g_rgRegressTests[u].pfTest)(pThreadData)))
{
printf(
"FAIL: %s, 0x%x\n\n",
g_rgRegressTests[u].pszDescription,
dwError);
fAllPassed = FALSE;
}
else
printf("PASS: %s\n\n", g_rgRegressTests[u].pszDescription);
}
return fAllPassed;
}
//
// Function: CallCryptAcquireContext
//
BOOL CallCryptAcquireContext(
IN PTHREAD_DATA pThreadData,
IN LPSTR pszOptions,
IN LPSTR pszContainer)
{
HCRYPTPROV hProv = 0;
HCRYPTKEY hKey = 0;
DWORD dwFlags = 0;
unsigned uLen = strlen(pszOptions);
ALG_ID ai = 0;
DWORD dwKeyFlags = 0;
BOOL fSuccess = TRUE;
printf(" pszContainer = %s\n", pszContainer);
printf(" dwFlags =");
while (uLen)
{
switch (pszOptions[uLen - 1])
{
case 'l':
dwFlags |= CRYPT_MACHINE_KEYSET;
printf(" CRYPT_MACHINE_KEYSET");
break;
case 'v':
dwFlags |= CRYPT_VERIFYCONTEXT;
printf(" CRYPT_VERIFYCONTEXT");
break;
case 'n':
dwFlags |= CRYPT_NEWKEYSET;
printf(" CRYPT_NEWKEYSET");
break;
case 'd':
dwFlags |= CRYPT_DELETEKEYSET;
printf(" CRYPT_DELETEKEYSET");
break;
case 'q':
dwFlags |= CRYPT_SILENT;
printf(" CRYPT_SILENT");
break;
case 'x':
ai = AT_KEYEXCHANGE;
break;
case 's':
ai = AT_SIGNATURE;
break;
case 'u':
dwKeyFlags = CRYPT_USER_PROTECTED;
break;
default:
printf(" Invalid!\n");
return FALSE;
}
uLen--;
}
printf("\n");
if (CryptAcquireContext(
&hProv, pszContainer, pThreadData->rgszProvName,
pThreadData->dwProvType, dwFlags))
{
printf("Success\n");
if (0 != ai)
{
printf("\nCalling CryptGenKey ...\n");
if (AT_KEYEXCHANGE == ai)
printf(" Algid = AT_KEYEXCHANGE\n");
else
printf(" Algid = AT_SIGNATURE\n");
if (dwKeyFlags & CRYPT_USER_PROTECTED)
printf(" dwFlags = CRYPT_USER_PROTECTED\n");
else
printf(" dwFlags =\n");
if (CryptGenKey(
hProv, ai, dwKeyFlags, &hKey))
{
printf("Success\n");
}
else
{
printf("ERROR: CryptGenKey failed - 0x%x\n", GetLastError());
fSuccess = FALSE;
}
}
}
else
{
printf("ERROR: CryptAcquireContext failed - 0x%x\n", GetLastError());
fSuccess = FALSE;
}
if (hKey)
{
if (! CryptDestroyKey(hKey))
{
printf("ERROR: CryptDestroyKey failed - 0x%x\n", GetLastError());
fSuccess = FALSE;
}
}
if (hProv)
{
if ((! dwFlags & CRYPT_DELETEKEYSET) &&
FALSE == CryptReleaseContext(hProv, 0))
{
printf("ERROR: CryptReleaseContext failed - 0x%x\n", GetLastError());
fSuccess = FALSE;
}
}
return fSuccess;
}
//
// Function: DeleteAllContainers
//
BOOL DeleteAllContainers(THREAD_DATA *pThreadData)
{
HCRYPTPROV hDefProv = 0;
HCRYPTPROV hProv = 0;
CHAR rgszContainer[MAX_PATH];
CHAR rgszDefCont[MAX_PATH];
DWORD cbContainer = MAX_PATH;
DWORD dwFlags = CRYPT_FIRST;
if (! CryptAcquireContext(
&hDefProv, NULL, pThreadData->rgszProvName,
pThreadData->dwProvType, 0))
{
printf("CryptAcquireContext default keyset failed - 0x%x\n", GetLastError());
return FALSE;
}
if (! CryptGetProvParam(
hDefProv, PP_CONTAINER, (PBYTE) rgszDefCont,
&cbContainer, 0))
{
printf("CryptGetProvParam PP_CONTAINER failed - 0x%x\n", GetLastError());
return FALSE;
}
cbContainer = MAX_PATH;
while (CryptGetProvParam(
hDefProv, PP_ENUMCONTAINERS, (PBYTE) rgszContainer,
&cbContainer, dwFlags))
{
if (dwFlags)
dwFlags = 0;
// If the enumerated container is the same as the default
// container, skip it for now
if (0 == strcmp(rgszContainer, rgszDefCont))
continue;
printf("\"%s\" - ", rgszContainer);
if (! CryptAcquireContext(
&hProv, rgszContainer, pThreadData->rgszProvName,
pThreadData->dwProvType, CRYPT_DELETEKEYSET))
printf("CryptAcquireContext CRYPT_DELETEKEYSET failed - 0x%x\n", GetLastError());
else
printf("Deleted\n");
cbContainer = MAX_PATH;
}
if (! CryptReleaseContext(hDefProv, 0))
{
printf("CryptReleaseContext failed - 0x%x\n", GetLastError());
return FALSE;
}
// Now try to delete default keyset
printf("\"%s\" - ", rgszDefCont);
if (! CryptAcquireContext(
&hProv, rgszDefCont, pThreadData->rgszProvName,
pThreadData->dwProvType, CRYPT_DELETEKEYSET))
printf("CryptAcquireContext CRYPT_DELETEKEYSET failed - 0x%x\n", GetLastError());
else
printf("Deleted\n");
return TRUE;
}
//*****************************************************
//
int _cdecl main(int argc, char * argv[])
{
HANDLE rghThread[MAX_THREADS];
DWORD rgdwThreadID[MAX_THREADS];
DWORD threadID=0;
DWORD thread_number=0;
DWORD dwErr=0;
DWORD dwArg = 0;
DWORD cbCspName = 0;
DWORD dwFreeHandle=0;
DWORD i = 0 ;
DWORD tick_StartTime=0;
char szErrorMsg[256] ;
THREAD_DATA ThreadData;
BOOL fInvalidArgs = FALSE;
PALGNODE pAlgNode = NULL;
BOOL fRunRegressions = FALSE;
BOOL fAcquireContext = FALSE;
LPSTR pszOptions = NULL;
LPSTR pszContainer = NULL;
BOOL fDeleteContainers = FALSE;
// Set high-order bit on dwSpinCount param so that the event used
// by EnterCriticalSection() will be pre-allocated by
// InitializeCriticalSectionAndSpinCount()
DWORD dwSpinCount = 0x8000;
ZeroMemory(&ThreadData, sizeof(ThreadData));
__try
{
InitializeCriticalSectionAndSpinCount(&ThreadData.CSThreadData, dwSpinCount);
}
__except (STATUS_NO_MEMORY == GetExceptionCode() ?
EXCEPTION_EXECUTE_HANDLER :
EXCEPTION_CONTINUE_SEARCH )
{
printf("InitializeCriticalSectionAndSpinCount failed: STATUS_NO_MEMORY exception\n");
exit(1);
}
// Setting all the defaults
ThreadData.dwThreadCount = StressGetDefaultThreadCount();
ThreadData.dwTestsToRun = RUN_ALL_TESTS;
while (--argc>0)
{
if (**++argv == '-')
{
switch(argv[0][1])
{
case 'n':
argv++;
argc--;
if (0 == argc || 0 == (dwArg = atoi(argv[0])))
{
fInvalidArgs = TRUE;
goto Ret;
}
ThreadData.dwThreadCount = dwArg;
break;
case 't':
argv++;
argc--;
if (0 == argc || 0 == (dwArg = atoi(argv[0])))
{
fInvalidArgs = TRUE;
goto Ret;
}
ThreadData.dwProgramMins = dwArg;
break;
case 'c':
argv++;
argc--;
if (0 == argc)
{
fInvalidArgs = TRUE;
goto Ret;
}
cbCspName = MAX_PATH;
dwErr = GetNextRegisteredCSP(
ThreadData.rgszProvName,
&cbCspName,
&ThreadData.dwProvType,
atoi(*argv));
if (ERROR_SUCCESS != dwErr)
{
fInvalidArgs = TRUE;
goto Ret;
}
break;
case 'e':
ThreadData.fEphemeralKeys = TRUE;
break;
case 'u':
ThreadData.fUserProtectedKeys = TRUE;
break;
case 'r':
fRunRegressions = TRUE;
break;
case '?':
fInvalidArgs = TRUE;
goto Ret;
case 'a':
fAcquireContext = TRUE;
pszOptions = argv[0] + 2;
if (NULL == strchr(pszOptions, 'v'))
{
argv++;
argc--;
pszContainer = *argv;
}
break;
case 'd':
fDeleteContainers = TRUE;
break;
case 'T':
argv++;
argc--;
if (0 == argc || 0 == (dwArg = atoi(argv[0])))
{
fInvalidArgs = TRUE;
goto Ret;
}
ThreadData.dwTestsToRun = dwArg;
break;
default:
fInvalidArgs = TRUE;
goto Ret;
}
}
}
//
// Check arg validity
//
if ( 0 != argc ||
0 == ThreadData.dwProvType ||
(ThreadData.fEphemeralKeys && ThreadData.fUserProtectedKeys) ||
(fRunRegressions && fAcquireContext))
{
fInvalidArgs = TRUE;
goto Ret;
}
printf("Provider: %s, Type: %d\n\n", ThreadData.rgszProvName, ThreadData.dwProvType);
if (fDeleteContainers)
{
printf("Deleting all key containers ...\n");
if (! DeleteAllContainers(&ThreadData))
exit(1);
goto Ret;
}
if (fAcquireContext)
{
printf("Calling CryptAcquireContext ...\n");
if (! CallCryptAcquireContext(
&ThreadData, pszOptions, pszContainer))
exit(1);
goto Ret;
}
if (!ProgramInit(&ThreadData))
{
printf("ProgramInit() failed\n");
exit(1) ;
}
//
// Initialize list of supported algorithms
//
if (ERROR_SUCCESS != (dwErr = InitializeAlgList(&ThreadData)))
{
printf("InitializeAlgList failed, 0x%x\n", dwErr);
exit(1);
}
if (fRunRegressions)
{
printf("Running regression tests ...\n");
if (! RunRegressionTests(&ThreadData))
exit(1);
goto Ret;
}
//
// Summarize user options
//
printf("Number of threads: %d\n", ThreadData.dwThreadCount);
if (ThreadData.dwProgramMins)
printf(" - Timeout in %d minute(s)\n", ThreadData.dwProgramMins);
if (ThreadData.fEphemeralKeys)
printf(" - Using ephemeral keys\n");
if (ThreadData.fUserProtectedKeys)
printf(" - Using user-protected keys\n");
// Create event that can be used by the timer thread to stop
// the worker threads.
if ((ThreadData.hEndTestEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL)
{
printf("CreateEvent() failed, 0x%x\n", GetLastError());
exit(1);
}
// Create the threads
tick_StartTime = GetTickCount() ;
for (thread_number = 0; thread_number < ThreadData.dwThreadCount; thread_number++)
{
if ((rghThread[thread_number] =
CreateThread(
NULL,
0,
(LPTHREAD_START_ROUTINE) ThreadRoutine,
&ThreadData,
0,
&threadID)) != NULL)
{
rgdwThreadID[thread_number] = threadID ;
}
else
{
sprintf(szErrorMsg, "\n\nERROR creating thread number 0x%x. Error 0x%x",
thread_number, GetLastError()) ;
MessageBox(NULL, szErrorMsg, ERROR_CAPTION, MB_OK | MB_ICONERROR) ;
exit(0) ;
}
}
// Spawn PrintThreadStatus
rghThread[thread_number++] = CreateThread(
NULL, 0,
(LPTHREAD_START_ROUTINE)PrintThreadStatus,
&ThreadData,
0, &threadID);
// Spawn KillProgramTimer (This will shut down all the threads and kill the program)
rghThread[thread_number++] = CreateThread(
NULL, 0,
(LPTHREAD_START_ROUTINE)KillProgramTimer,
&ThreadData,
0, &threadID);
// Done Creating all threads
// End multithreading
dwErr = WaitForMultipleObjects(thread_number, rghThread, TRUE, INFINITE) ;
if (dwErr == WAIT_FAILED)
printf("WaitForMultipleObjects() failed, 0x%x\n", GetLastError());
if (! CryptDestroyKey(ThreadData.hSignatureKey))
{
sprintf(szErrorMsg, "FAILED CryptDestroyKey SIG error 0x%x\n", GetLastError()) ;
MessageBox(NULL, szErrorMsg, ERROR_CAPTION, MB_OK | MB_ICONERROR) ;
}
if (ThreadData.hExchangeKey && (! CryptDestroyKey(ThreadData.hExchangeKey)))
{
sprintf(szErrorMsg, "FAILED CryptDestroyKey KEYX error 0x%x\n", GetLastError()) ;
MessageBox(NULL, szErrorMsg, ERROR_CAPTION, MB_OK | MB_ICONERROR) ;
}
if (! CryptReleaseContext(ThreadData.hVerifyCtx, 0))
{
sprintf(szErrorMsg, "FAILED CryptReleaseContext 1 error 0x%x\n", GetLastError());
MessageBox(NULL, szErrorMsg, ERROR_CAPTION, MB_OK | MB_ICONERROR);
}
if (! CryptReleaseContext(ThreadData.hProv, 0))
{
sprintf(szErrorMsg, "FAILED CryptReleaseContext 2 error 0x%x\n", GetLastError()) ;
MessageBox(NULL, szErrorMsg, ERROR_CAPTION, MB_OK | MB_ICONERROR) ;
}
DeleteCriticalSection(&ThreadData.CSThreadData);
CloseHandle(ThreadData.hEndTestEvent);
while (thread_number--)
CloseHandle(rghThread[thread_number]);
Ret:
while (ThreadData.pAlgList)
{
pAlgNode = ThreadData.pAlgList->pNext;
MyFree(ThreadData.pAlgList);
ThreadData.pAlgList = pAlgNode;
}
if (fInvalidArgs)
{
Usage();
printf("\nRegistered CSP's:\n");
cbCspName = MAX_PATH;
for ( i = 0;
ERROR_SUCCESS == GetNextRegisteredCSP(
ThreadData.rgszProvName,
&cbCspName,
&ThreadData.dwProvType,
ENUMERATE_REGISTERED_CSP);
i++, cbCspName = MAX_PATH)
{
printf(" %d: %s, Type %d\n", i, ThreadData.rgszProvName, ThreadData.dwProvType);
}
exit(1);
}
return 0 ;
}