Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

3336 lines
105 KiB

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1995 - 1996
//
// File: tsca.cpp
//
// Contents: Simplified Cryptographic API (SCA) Tests
//
// See Usage() for list of test options.
//
//
// Functions: main
//
// History: 08-Mar-96 philh created
// 20-Aug-96 jeffspel name changes
//
//--------------------------------------------------------------------------
#define CMS_PKCS7 1
#ifdef CMS_PKCS7
#define CRYPT_SIGN_MESSAGE_PARA_HAS_CMS_FIELDS 1
#endif // CMS_PKCS7
#define CRYPT_DECRYPT_MESSAGE_PARA_HAS_EXTRA_FIELDS 1
#include <windows.h>
#include <assert.h>
#include "wincrypt.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stddef.h>
#include <memory.h>
#include <time.h>
#include <malloc.h>
#include <dbgdef.h>
// #define ENABLE_SCA_STREAM_TEST 1
#define SCA_STREAM_ENABLE_FLAG 0x80000000
#define SCA_INDEFINITE_STREAM_FLAG 0x40000000
//+-------------------------------------------------------------------------
// Parameters, data used to encode the messages.
//--------------------------------------------------------------------------
static DWORD dwCryptProvType = PROV_RSA_FULL;
static DWORD dwPubKeyBitLen = 0;
static LPCSTR pszHashName = "md5";
static LPCSTR pszEncryptName = "rc2";
static DWORD dwEncryptBitLen = 0;
static BOOL fEncryptIV = FALSE;
static BOOL fVerbose = FALSE;
static HCERTSTORE hCertStore = 0;
static LPSTR pszMsgCertFilename = NULL;
static LPSTR pszMsgEncodedFilename = NULL;
static LPSTR pszReadEncodedFilename = NULL;
static BOOL fDetached = FALSE;
static DWORD dwMsgEncodingType = PKCS_7_ASN_ENCODING;
static DWORD dwCertEncodingType = X509_ASN_ENCODING;
static DWORD dwSignKeySpec = AT_SIGNATURE;
static BOOL fInnerSigned = FALSE;
static LPSTR pszCertNameFindStr = NULL;
#ifdef ENABLE_SCA_STREAM_TEST
static BOOL fStream = FALSE;
static BOOL fIndefiniteStream = FALSE;
#endif
BOOL fNoRecipients = FALSE;
BOOL fAllRecipients = FALSE;
BOOL fDhRecipient = FALSE;
BOOL fEncapsulatedContent = FALSE;
#ifdef CMS_PKCS7
BOOL fSP3Encrypt = FALSE;
BOOL fDefaultGetSigner = FALSE;
BOOL fRecipientKeyId = FALSE;
BOOL fSignerKeyId = FALSE;
BOOL fHashEncryptionAlgorithm = FALSE;
BOOL fNoSalt = FALSE;
#define MAX_SALT_LEN 11
BYTE rgbSalt[MAX_SALT_LEN];
CMSG_RC4_AUX_INFO RC4AuxInfo;
BOOL fSilentKey = FALSE;
#endif
#define MAX_MSG_CERT 30
#define MAX_MSG_CRL 30
#define MAX_RECIPIENT_CERT 50
#define MAX_HASH_LEN 20
static LPCSTR pszMsgContent = "Message Content Message Content";
static LPCSTR pszMsgContent2 = "Second Message Content";
static LPCSTR pszMsgContent3 = "Third Message Content";
static const BYTE *pbToBeEncoded = (const BYTE *) pszMsgContent;
static DWORD cbToBeEncoded = strlen(pszMsgContent) + 1;
#define DETACHED_CONTENT_CNT 3
static const BYTE *rgpbDetachedToBeEncoded[DETACHED_CONTENT_CNT] = {
(const BYTE *) pszMsgContent,
(const BYTE *) pszMsgContent2,
(const BYTE *) pszMsgContent3
};
static DWORD rgcbDetachedToBeEncoded[DETACHED_CONTENT_CNT] = {
strlen(pszMsgContent) + 1,
strlen(pszMsgContent2) + 1,
strlen(pszMsgContent3) + 1
};
#define DELTA_LESS_LENGTH 8
#define DELTA_MORE_LENGTH 32
static CMSG_RC2_AUX_INFO RC2AuxInfo;
BOOL fAuthAttr = FALSE;
#define AUTH_ATTR_COUNT 2
BYTE attr1[] = {0x04, 0x0c, 'A','t','t','r','i','b','u','t','e',' ','1',0};
BYTE attr2[] = {0x04, 0x0c, 'A','t','t','r','i','b','u','t','e',' ','2',0};
BYTE attr3[] = {0x04, 0x0c, 'A','t','t','r','i','b','u','t','e',' ','3',0};
CRYPT_ATTR_BLOB rgatrblob1[] = {
{ sizeof( attr1), attr1}
};
CRYPT_ATTR_BLOB rgatrblob2[] = {
{ sizeof( attr2), attr2},
{ sizeof( attr3), attr3}
};
CRYPT_ATTRIBUTE rgAuthAttr[AUTH_ATTR_COUNT] = {
{"1.2.3.5.7", 1, rgatrblob1},
{"1.2.3.5.11", 2, rgatrblob2}
};
static inline IsDSSProv(
IN DWORD dwProvType
)
{
return (PROV_DSS == dwProvType || PROV_DSS_DH == dwProvType);
}
//+-------------------------------------------------------------------------
// Error output routines
//--------------------------------------------------------------------------
static void PrintError(LPCSTR pszMsg)
{
printf("%s\n", pszMsg);
}
static void PrintLastError(LPCSTR pszMsg)
{
DWORD dwErr = GetLastError();
printf("%s failed => 0x%x (%d) \n", pszMsg, dwErr, dwErr);
}
static void CheckLessLength(
LPCSTR pszMsg,
BOOL fResult,
DWORD cbActual,
DWORD cbExpected
)
{
if (fResult)
printf("%s failed => expected ERROR_MORE_DATA\n", pszMsg);
else {
DWORD dwErr = GetLastError();
if (fVerbose)
printf("%s with less length got expected error => 0x%x (%d)\n",
pszMsg, dwErr, dwErr);
if (ERROR_MORE_DATA != dwErr)
printf("%s failed => LastError = %d, expected = %d\n",
pszMsg, dwErr, ERROR_MORE_DATA);
}
if (cbActual != cbExpected)
printf("%s failed => ", pszMsg);
if (fVerbose || cbActual != cbExpected)
printf("cbData = %d, expected = %d\n", cbActual, cbExpected);
}
static void CheckMoreLength(
LPCSTR pszMsg,
DWORD cbActual,
DWORD cbExpected
)
{
if (cbActual != cbExpected) {
printf("%s failed => ", pszMsg);
printf("cbData = %d, expected = %d\n", cbActual, cbExpected);
}
}
//+-------------------------------------------------------------------------
// Test allocation and free routines
//--------------------------------------------------------------------------
static void *TestAlloc(
IN size_t cbBytes
)
{
void *pv;
pv = malloc(cbBytes);
if (pv == NULL) {
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
PrintLastError("TestAlloc");
}
return pv;
}
static void TestFree(
IN void *pv
)
{
if (pv)
free(pv);
}
static BOOL AllocAndEncodeObject(
IN LPCSTR lpszStructType,
IN const void *pvStructInfo,
OUT BYTE **ppbEncoded,
OUT DWORD *pcbEncoded
)
{
BOOL fResult;
BYTE *pbEncoded = NULL;
DWORD cbEncoded;
fResult = CryptEncodeObject(
dwCertEncodingType,
lpszStructType,
pvStructInfo,
NULL, // pbEncoded
&cbEncoded);
if (!fResult || cbEncoded == 0) {
if ((DWORD_PTR) lpszStructType <= 0xFFFF)
printf("CryptEncodeObject(StructType: %d, cbEncoded == 0)",
(DWORD)(DWORD_PTR) lpszStructType);
else
printf("CryptEncodeObject(StructType: %s, cbEncoded == 0)",
lpszStructType);
PrintLastError("");
goto ErrorReturn;
}
if (NULL == (pbEncoded = (BYTE *) TestAlloc(cbEncoded)))
goto ErrorReturn;
if (!CryptEncodeObject(
dwCertEncodingType,
lpszStructType,
pvStructInfo,
pbEncoded,
&cbEncoded
)) {
if ((DWORD_PTR) lpszStructType <= 0xFFFF)
printf("CryptEncodeObject(StructType: %d)",
(DWORD)(DWORD_PTR) lpszStructType);
else
printf("CryptEncodeObject(StructType: %s)",
lpszStructType);
PrintLastError("");
goto ErrorReturn;
}
fResult = TRUE;
CommonReturn:
*ppbEncoded = pbEncoded;
*pcbEncoded = cbEncoded;
return fResult;
ErrorReturn:
if (pbEncoded) {
TestFree(pbEncoded);
pbEncoded = NULL;
}
cbEncoded = 0;
fResult = FALSE;
goto CommonReturn;
}
static PCCRYPT_OID_INFO GetOIDInfo(LPCSTR pszName, DWORD dwGroupId = 0)
{
WCHAR wszName[256];
PCCRYPT_OID_INFO pInfo;
MultiByteToWideChar(
CP_ACP,
0, // dwFlags
pszName,
-1, // null terminated
wszName,
sizeof(wszName) / sizeof(wszName[0]));
return CryptFindOIDInfo(
CRYPT_OID_INFO_NAME_KEY,
(void *) wszName,
dwGroupId
);
}
static LPCSTR GetOID(LPCSTR pszName, DWORD dwGroupId = 0)
{
PCCRYPT_OID_INFO pInfo;
if (pInfo = GetOIDInfo(pszName, dwGroupId))
return pInfo->pszOID;
else
return NULL;
}
static ALG_ID GetAlgid(LPCSTR pszName, DWORD dwGroupId = 0)
{
PCCRYPT_OID_INFO pInfo;
if (pInfo = GetOIDInfo(pszName, dwGroupId))
return pInfo->Algid;
else
return 0;
}
#define CROW 16
static void PrintBytes(LPCSTR pszHdr, BYTE *pb, DWORD cbSize)
{
ULONG cb, i;
while (cbSize > 0)
{
printf("%s", pszHdr);
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(".");
pb += cb;
printf("'\n");
}
}
//+-------------------------------------------------------------------------
// Allocate and read an encoded DER blob from a file
//--------------------------------------------------------------------------
static BOOL ReadDERFromFile(
LPCSTR pszFileName,
PBYTE *ppbDER,
PDWORD pcbDER
)
{
BOOL fRet;
HANDLE hFile = 0;
PBYTE pbDER = NULL;
DWORD cbDER;
DWORD cbRead;
if( INVALID_HANDLE_VALUE == (hFile = CreateFile( pszFileName, GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL))) {
printf( "can't open %s\n", pszFileName);
goto ErrorReturn;
}
cbDER = GetFileSize( hFile, NULL);
if (cbDER == 0) {
printf( "empty file %s\n", pszFileName);
goto ErrorReturn;
}
if (NULL == (pbDER = (PBYTE)TestAlloc(cbDER))) {
printf( "can't alloc %d bytes\n", cbDER);
goto ErrorReturn;
}
if (!ReadFile( hFile, pbDER, cbDER, &cbRead, NULL) ||
(cbRead != cbDER)) {
printf( "can't read %s\n", pszFileName);
goto ErrorReturn;
}
*ppbDER = pbDER;
*pcbDER = cbDER;
fRet = TRUE;
CommonReturn:
if (hFile)
CloseHandle(hFile);
return fRet;
ErrorReturn:
if (pbDER)
TestFree(pbDER);
*ppbDER = NULL;
*pcbDER = 0;
fRet = FALSE;
goto CommonReturn;
}
//+-------------------------------------------------------------------------
// Write an encoded DER blob to a file
//--------------------------------------------------------------------------
static BOOL WriteDERToFile(
LPCSTR pszFileName,
PBYTE pbDER,
DWORD cbDER
)
{
BOOL fResult;
// Write the Encoded Blob to the file
HANDLE hFile;
hFile = CreateFile(pszFileName,
GENERIC_WRITE,
0, // fdwShareMode
NULL, // lpsa
CREATE_ALWAYS,
0, // fdwAttrsAndFlags
0); // TemplateFile
if (INVALID_HANDLE_VALUE == hFile) {
fResult = FALSE;
PrintLastError("WriteDERToFile::CreateFile");
} else {
DWORD dwBytesWritten;
if (!(fResult = WriteFile(
hFile,
pbDER,
cbDER,
&dwBytesWritten,
NULL // lpOverlapped
)))
PrintLastError("WriteDERToFile::WriteFile");
CloseHandle(hFile);
}
return fResult;
}
static HCERTSTORE OpenStore(LPCSTR pszStoreFilename)
{
HCERTSTORE hStore;
HANDLE hFile = 0;
if( INVALID_HANDLE_VALUE == (hFile = CreateFile(pszStoreFilename,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL))) {
printf( "can't open %s\n", pszStoreFilename);
hStore = CertOpenStore(
CERT_STORE_PROV_MEMORY,
dwCertEncodingType,
0, // hProv
0, // dwFlags
NULL // pvPara
);
} else {
hStore = CertOpenStore(
CERT_STORE_PROV_FILE,
dwCertEncodingType,
0, // hProv
0, // dwFlags
hFile
);
CloseHandle(hFile);
}
if (hStore == NULL)
PrintLastError("CertOpenStore");
return hStore;
}
static void SaveStore(HCERTSTORE hStore, LPCSTR pszSaveFilename)
{
HANDLE hFile;
hFile = CreateFile(pszSaveFilename,
GENERIC_WRITE,
0, // fdwShareMode
NULL, // lpsa
CREATE_ALWAYS,
0, // fdwAttrsAndFlags
0); // TemplateFile
if (INVALID_HANDLE_VALUE == hFile) {
printf( "can't open %s\n", pszSaveFilename);
PrintLastError("CloseStore::CreateFile");
} else {
if (!CertSaveStore(
hStore,
0, // dwEncodingType,
CERT_STORE_SAVE_AS_STORE,
CERT_STORE_SAVE_TO_FILE,
(void *) hFile,
0 // dwFlags
))
PrintLastError("CertSaveStore");
CloseHandle(hFile);
}
}
static void DisplayCert(PCCERT_CONTEXT pCert);
static void DisplayCrl(PCCRL_CONTEXT pCrl);
//+-------------------------------------------------------------------------
// Functions for initializing and freeing SCA parameters
//--------------------------------------------------------------------------
static BOOL InitSignPara(OUT PCRYPT_SIGN_MESSAGE_PARA pPara);
static void FreeSignPara(IN PCRYPT_SIGN_MESSAGE_PARA pPara);
static BOOL InitVerifyPara(OUT PCRYPT_VERIFY_MESSAGE_PARA pPara);
static void FreeVerifyPara(IN PCRYPT_VERIFY_MESSAGE_PARA pPara);
static BOOL InitEncryptPara(
OUT PCRYPT_ENCRYPT_MESSAGE_PARA pPara,
OUT DWORD *pcRecipientCert,
OUT PCCERT_CONTEXT **pppRecipientCert
);
static void FreeEncryptPara(
IN PCRYPT_ENCRYPT_MESSAGE_PARA pPara,
IN DWORD cRecipientCert,
IN PCCERT_CONTEXT *ppRecipientCert
);
static BOOL InitDecryptPara(OUT PCRYPT_DECRYPT_MESSAGE_PARA pPara);
static void FreeDecryptPara(IN PCRYPT_DECRYPT_MESSAGE_PARA pPara);
static BOOL InitHashPara(OUT PCRYPT_HASH_MESSAGE_PARA pPara);
static void FreeHashPara(IN PCRYPT_HASH_MESSAGE_PARA pPara);
//+-------------------------------------------------------------------------
// Top Level Test Functions
//--------------------------------------------------------------------------
static BOOL TestSign()
{
BOOL fResult;
CRYPT_SIGN_MESSAGE_PARA SignPara;
CRYPT_VERIFY_MESSAGE_PARA VerifyPara;
BYTE *pbSignedBlob = NULL;
DWORD cbSignedBlob;
BYTE *pbDecoded = NULL;
DWORD cbDecoded;
DWORD *pcbDecoded;
PCCERT_CONTEXT pSignerCert = NULL;
PCCERT_CONTEXT pSignerCert2 = NULL;
LONG lSignerCount;
BYTE *pbDecoded2 = NULL;
DWORD cbDecoded2;
DWORD dwMsgType;
DWORD cbData;
DWORD dwInnerContentType = 0x1233467;
DWORD cToBeSigned;
const BYTE **ppbToBeSigned;
DWORD *pcbToBeSigned;
ppbToBeSigned = rgpbDetachedToBeEncoded;
pcbToBeSigned = rgcbDetachedToBeEncoded;
if (fDetached)
cToBeSigned = DETACHED_CONTENT_CNT;
else if (0 == cbToBeEncoded) {
cToBeSigned = 0;
ppbToBeSigned = NULL;
pcbToBeSigned = NULL;
} else
cToBeSigned = 1;
if (pszReadEncodedFilename)
fResult = TRUE;
else
fResult = InitSignPara(&SignPara);
fResult &= InitVerifyPara(&VerifyPara);
if (!fResult) goto ErrorReturn;
if (pszReadEncodedFilename) {
if (!ReadDERFromFile(
pszReadEncodedFilename,
&pbSignedBlob,
&cbSignedBlob
))
goto ErrorReturn;
} else {
cbSignedBlob = 1; // bad length should be ignored
fResult = CryptSignMessage(
&SignPara,
fDetached,
cToBeSigned,
ppbToBeSigned,
pcbToBeSigned,
NULL, // pbSignedBlob
&cbSignedBlob
);
if (!fResult || cbSignedBlob == 0) {
PrintLastError("CryptSignMessage(cb == 0)");
goto ErrorReturn;
}
if (NULL == (pbSignedBlob = (BYTE *) TestAlloc(
cbSignedBlob + DELTA_MORE_LENGTH)))
goto ErrorReturn;
if (!CryptSignMessage(
&SignPara,
fDetached,
cToBeSigned,
ppbToBeSigned,
pcbToBeSigned,
pbSignedBlob,
&cbSignedBlob
)) {
PrintLastError("CryptSignMessage");
goto ErrorReturn;
}
cbData = cbSignedBlob - DELTA_LESS_LENGTH;
fResult = CryptSignMessage(
&SignPara,
fDetached,
cToBeSigned,
ppbToBeSigned,
pcbToBeSigned,
pbSignedBlob,
&cbData
);
// Note, length varies for DSS
if (!IsDSSProv(dwCryptProvType))
CheckLessLength("CryptSignMessage", fResult, cbData, cbSignedBlob);
cbData = cbSignedBlob + DELTA_MORE_LENGTH;
if (!CryptSignMessage(
&SignPara,
fDetached,
cToBeSigned,
ppbToBeSigned,
pcbToBeSigned,
pbSignedBlob,
&cbData
)) {
PrintLastError("CryptSignMessage");
goto ErrorReturn;
}
// Note, length varies for DSS
if (!IsDSSProv(dwCryptProvType))
CheckMoreLength("CryptSignMessage", cbData, cbSignedBlob);
cbSignedBlob = cbData;
}
if (NULL == pszReadEncodedFilename && pszMsgEncodedFilename)
WriteDERToFile(pszMsgEncodedFilename, pbSignedBlob, cbSignedBlob);
if (pszMsgCertFilename) {
HCERTSTORE hMsgCertStore;
if (hMsgCertStore = CryptGetMessageCertificates(
dwMsgEncodingType | dwCertEncodingType,
0, // hCryptProv,
0, // dwFlags
pbSignedBlob,
cbSignedBlob
)) {
SaveStore(hMsgCertStore, pszMsgCertFilename);
CertCloseStore(hMsgCertStore, 0);
} else
PrintLastError("CryptGetMessageCertificates");
}
lSignerCount = CryptGetMessageSignerCount(dwMsgEncodingType,
pbSignedBlob, cbSignedBlob);
if (lSignerCount < 0)
PrintLastError("CryptGetMessageSignerCount");
else if (fVerbose)
printf("Signer Count: %d\n", lSignerCount);
if (fDetached) {
if (!CryptVerifyDetachedMessageSignature(
&VerifyPara,
0, // dwSignerIndex
pbSignedBlob,
cbSignedBlob,
DETACHED_CONTENT_CNT,
rgpbDetachedToBeEncoded,
rgcbDetachedToBeEncoded,
&pSignerCert
)) {
PrintLastError("CryptVerifyDetachedMessageSignature");
goto ErrorReturn;
}
} else {
cbDecoded = 3; // bad length should be ignored
if (!CryptVerifyMessageSignature(
&VerifyPara,
0, // dwSignerIndex
pbSignedBlob,
cbSignedBlob,
NULL, // pbDecoded
&cbDecoded,
NULL // ppSignerCert
)) {
PrintLastError("CryptVerifyMessageSignature");
goto ErrorReturn;
}
if (cbDecoded == 0)
// Message doesn't contain any content, only certs and CRLs
pcbDecoded = NULL;
else {
pcbDecoded = &cbDecoded;
if (NULL == (pbDecoded = (BYTE *) TestAlloc(
cbDecoded + DELTA_MORE_LENGTH)))
goto ErrorReturn;
}
if (!CryptVerifyMessageSignature(
&VerifyPara,
0, // dwSignerIndex
pbSignedBlob,
cbSignedBlob,
pbDecoded,
pcbDecoded,
&pSignerCert
)) {
if (GetLastError() == CRYPT_E_NO_SIGNER) {
printf("message has no signers\n");
// Try again with all out parameters set to NULL.
// GetSignerCertificate should still be called
fResult = CryptVerifyMessageSignature(
&VerifyPara,
0, // dwSignerIndex
pbSignedBlob,
cbSignedBlob,
NULL, // pbDecoded
NULL, // pcbDecoded
NULL // ppSignerCert
);
if (fResult) {
printf("CryptVerifyMessageSignature(no signer, NULL outs)");
printf(" failed => returned SUCCESS\n");
} else if (GetLastError() != CRYPT_E_NO_SIGNER)
PrintLastError("CryptVerifyMessageSignature(no signer, NULL outs)");
} else {
PrintLastError("CryptVerifyMessageSignature");
goto ErrorReturn;
}
}
if (cbDecoded > DELTA_LESS_LENGTH) {
cbData = cbDecoded - DELTA_LESS_LENGTH;
fResult = CryptVerifyMessageSignature(
&VerifyPara,
0, // dwSignerIndex
pbSignedBlob,
cbSignedBlob,
pbDecoded,
&cbData,
NULL // ppSignerCert
);
CheckLessLength("CryptVerifyMessageSignature", fResult, cbData,
cbDecoded);
cbData = cbDecoded + DELTA_MORE_LENGTH;
if (!CryptVerifyMessageSignature(
&VerifyPara,
0, // dwSignerIndex
pbSignedBlob,
cbSignedBlob,
pbDecoded,
&cbData,
NULL // ppSignerCert
)) {
if (GetLastError() == CRYPT_E_NO_SIGNER)
printf("message has no signers\n");
else {
PrintLastError("CryptVerifyMessageSignature");
goto ErrorReturn;
}
}
CheckMoreLength("CryptVerifyMessageSignature", cbData, cbDecoded);
}
}
if (pSignerCert) {
if (fVerbose) {
printf("----- Verifier -----\n");
DisplayCert(pSignerCert);
}
} else
printf("no verifier cert\n");
if (!fDetached) {
if (!pszReadEncodedFilename) {
if (cbDecoded == cbToBeEncoded &&
memcmp(pbDecoded, pbToBeEncoded, cbDecoded) == 0) {
if (fVerbose)
printf("SUCCESS:: Decoded == ToBeEncoded\n");
} else
printf("***** ERROR:: Decoded != ToBeEncoded\n");
}
if (fVerbose) {
printf("Decoded bytes::\n");
PrintBytes(" ", pbDecoded, cbDecoded);
}
if (pszReadEncodedFilename && pszMsgEncodedFilename)
WriteDERToFile(pszMsgEncodedFilename, pbDecoded, cbDecoded);
cbDecoded2 = cbDecoded;
if (cbDecoded2 ) {
if (NULL == (pbDecoded2 = (BYTE *) TestAlloc(
cbDecoded2 + DELTA_MORE_LENGTH)))
goto ErrorReturn;
}
if (!CryptDecodeMessage(
CMSG_ALL_FLAGS,
NULL, // pDecryptPara
&VerifyPara,
0, // dwSignerIndex
pbSignedBlob,
cbSignedBlob,
0, // dwPrevInnerContentType
&dwMsgType,
&dwInnerContentType,
pbDecoded2,
&cbDecoded2,
NULL, // ppXchgCert
&pSignerCert2
)) {
if (GetLastError() == CRYPT_E_NO_SIGNER)
printf("message has no signers\n");
else {
PrintLastError("CryptDecodeMessage(CMSG_SIGNED)");
goto ErrorReturn;
}
}
if (cbDecoded2 > DELTA_LESS_LENGTH) {
cbData = cbDecoded2 - DELTA_LESS_LENGTH;
fResult = CryptDecodeMessage(
CMSG_ALL_FLAGS,
NULL, // pDecryptPara
&VerifyPara,
0, // dwSignerIndex
pbSignedBlob,
cbSignedBlob,
0, // dwPrevInnerContentType
&dwMsgType,
NULL, // pdwInnerContentType
pbDecoded2,
&cbData,
NULL, // ppXchgCert
NULL // ppSignerCert
);
CheckLessLength("CryptDecodeMessage(SIGN)", fResult, cbData,
cbDecoded2);
cbData = cbDecoded2 + DELTA_MORE_LENGTH;
if (!CryptDecodeMessage(
CMSG_ALL_FLAGS,
NULL, // pDecryptPara
&VerifyPara,
0, // dwSignerIndex
pbSignedBlob,
cbSignedBlob,
0, // dwPrevInnerContentType
&dwMsgType,
&dwInnerContentType,
pbDecoded2,
&cbData,
NULL, // ppXchgCert
NULL // ppSignerCert
)) {
if (GetLastError() == CRYPT_E_NO_SIGNER)
printf("message has no signers\n");
else {
PrintLastError("CryptDecodeMessage(CMSG_SIGNED)");
goto ErrorReturn;
}
}
CheckMoreLength("CryptDecodeMessage", cbData, cbDecoded2);
}
if (dwMsgType != CMSG_SIGNED)
printf("failed :: dwMsgType(%d) != CMSG_SIGNED\n", dwMsgType);
else if (fVerbose)
printf("SUCCESS:: CryptDecodeMessage(CMSG_SIGNED)\n");
#ifdef CMS_PKCS7
if ((fEncapsulatedContent && dwInnerContentType != CMSG_HASHED) ||
(!fEncapsulatedContent && dwInnerContentType != CMSG_DATA)) {
#else
if (dwInnerContentType != CMSG_DATA) {
#endif // CMS_PKCS7
if (pszReadEncodedFilename)
printf("SIGNED InnerContentType = %d\n", dwInnerContentType);
else {
#ifdef CMS_PKCS7
if (fEncapsulatedContent)
printf("SIGNED failed :: dwInnerContentType(%d) != CMSG_HASHED\n",
dwInnerContentType);
else
#endif // CMS_PKCS7
printf("SIGNED failed :: dwInnerContentType(%d) != CMSG_DATA\n",
dwInnerContentType);
}
}
if (cbDecoded2 != cbDecoded ||
(cbDecoded > 0 &&
memcmp(pbDecoded, pbDecoded2, cbDecoded) != 0))
printf("failed :: bad decoded content for CryptDecodeMessage(CMSG_SIGNED)\n");
if (pSignerCert && (pSignerCert2 == NULL ||
!CertCompareCertificate(dwCertEncodingType,
pSignerCert->pCertInfo, pSignerCert2->pCertInfo)))
printf("failed :: bad signer cert for CryptDecodeMessage(CMSG_SIGNED)\n");
}
fResult = TRUE;
goto CommonReturn;
ErrorReturn:
fResult = FALSE;
CommonReturn:
if (!pszReadEncodedFilename)
FreeSignPara(&SignPara);
FreeVerifyPara(&VerifyPara);
if (pbSignedBlob)
TestFree(pbSignedBlob);
if (pbDecoded)
TestFree(pbDecoded);
if (pbDecoded2)
TestFree(pbDecoded2);
if (pSignerCert)
CertFreeCertificateContext(pSignerCert);
if (pSignerCert2)
CertFreeCertificateContext(pSignerCert2);
return fResult;
}
static BOOL TestEnvelope()
{
BOOL fResult;
CRYPT_ENCRYPT_MESSAGE_PARA EncryptPara;
DWORD cRecipientCert;
PCCERT_CONTEXT *ppRecipientCert;
CRYPT_DECRYPT_MESSAGE_PARA DecryptPara;
BYTE *pbEncryptedBlob = NULL;
DWORD cbEncryptedBlob;
BYTE *pbDecoded = NULL;
DWORD cbDecoded;
PCCERT_CONTEXT pXchgCert = NULL;
BYTE *pbDecoded2 = NULL;
DWORD cbDecoded2;
DWORD dwMsgType;
PCCERT_CONTEXT pXchgCert2 = NULL;
DWORD cbData;
DWORD dwInnerContentType = 0x1233467;
if (pszReadEncodedFilename)
fResult = TRUE;
else
fResult = InitEncryptPara(&EncryptPara, &cRecipientCert,
&ppRecipientCert);
fResult &= InitDecryptPara(&DecryptPara);
if (!fResult) goto ErrorReturn;
if (pszReadEncodedFilename) {
if (!ReadDERFromFile(
pszReadEncodedFilename,
&pbEncryptedBlob,
&cbEncryptedBlob
))
goto ErrorReturn;
} else {
fResult = CryptEncryptMessage(
&EncryptPara,
cRecipientCert,
ppRecipientCert,
pbToBeEncoded,
cbToBeEncoded,
NULL, // pbEncryptedBlob
&cbEncryptedBlob
);
if (!fResult || cbEncryptedBlob == 0) {
PrintLastError("CryptEncryptMessage(cb == 0)");
goto ErrorReturn;
}
if (NULL == (pbEncryptedBlob = (BYTE *) TestAlloc(
cbEncryptedBlob + DELTA_MORE_LENGTH)))
goto ErrorReturn;
fResult = CryptEncryptMessage(
&EncryptPara,
cRecipientCert,
ppRecipientCert,
pbToBeEncoded,
cbToBeEncoded,
pbEncryptedBlob,
&cbEncryptedBlob
);
if (!fResult) {
PrintLastError("CryptEncryptMessage");
goto ErrorReturn;
}
cbData = cbEncryptedBlob - DELTA_LESS_LENGTH;
fResult = CryptEncryptMessage(
&EncryptPara,
cRecipientCert,
ppRecipientCert,
pbToBeEncoded,
cbToBeEncoded,
pbEncryptedBlob,
&cbData
);
// Note, length varies for DH
if (!fDhRecipient)
CheckLessLength("CryptEncryptMessage", fResult, cbData,
cbEncryptedBlob);
cbData = cbEncryptedBlob + DELTA_MORE_LENGTH;
fResult = CryptEncryptMessage(
&EncryptPara,
cRecipientCert,
ppRecipientCert,
pbToBeEncoded,
cbToBeEncoded,
pbEncryptedBlob,
&cbData
);
if (!fResult) {
PrintLastError("CryptEncryptMessage");
goto ErrorReturn;
}
// Note, length varies for DH
if (!fDhRecipient)
CheckMoreLength("CryptEncryptMessage", cbData, cbEncryptedBlob);
cbEncryptedBlob = cbData;
}
if (NULL == pszReadEncodedFilename && pszMsgEncodedFilename)
WriteDERToFile(pszMsgEncodedFilename, pbEncryptedBlob, cbEncryptedBlob);
cbDecoded = 0;
fResult = CryptDecryptMessage(
&DecryptPara,
pbEncryptedBlob,
cbEncryptedBlob,
NULL, // pbDecoded
&cbDecoded,
NULL // ppXchgCert
);
if (!fResult && GetLastError() == CRYPT_E_RECIPIENT_NOT_FOUND)
printf("message has no recipients\n");
else if (!fResult || (cbToBeEncoded > 0 && cbDecoded == 0 &&
NULL == pszReadEncodedFilename)) {
PrintLastError("CryptDecryptMessage(cb == 0)");
goto ErrorReturn;
}
if (NULL == (pbDecoded = (BYTE *) TestAlloc(cbDecoded + DELTA_MORE_LENGTH)))
goto ErrorReturn;
if (!CryptDecryptMessage(
&DecryptPara,
pbEncryptedBlob,
cbEncryptedBlob,
pbDecoded,
&cbDecoded,
&pXchgCert
)) {
if (GetLastError() == CRYPT_E_RECIPIENT_NOT_FOUND)
printf("message has no recipients\n");
else {
PrintLastError("CryptDecryptMessage");
goto ErrorReturn;
}
}
if (pszReadEncodedFilename && pszMsgEncodedFilename)
WriteDERToFile(pszMsgEncodedFilename, pbDecoded, cbDecoded);
if (cbDecoded > DELTA_LESS_LENGTH) {
cbData = cbDecoded - DELTA_LESS_LENGTH;
fResult = CryptDecryptMessage(
&DecryptPara,
pbEncryptedBlob,
cbEncryptedBlob,
pbDecoded,
&cbData,
NULL // ppXchgCert
);
CheckLessLength("CryptDecryptMessage", fResult, cbData, cbDecoded);
}
cbData = cbDecoded + DELTA_MORE_LENGTH;
if (!CryptDecryptMessage(
&DecryptPara,
pbEncryptedBlob,
cbEncryptedBlob,
pbDecoded,
&cbData,
NULL // ppXchgCert
)) {
if (GetLastError() == CRYPT_E_RECIPIENT_NOT_FOUND)
printf("message has no recipients\n");
else {
PrintLastError("CryptDecryptMessage");
goto ErrorReturn;
}
}
CheckMoreLength("CryptDecryptMessage", cbData, cbDecoded);
if (pXchgCert) {
if (fVerbose) {
printf("----- XchgCert -----\n");
DisplayCert(pXchgCert);
}
} else
printf("no xchg cert\n");
if (!pszReadEncodedFilename && !fNoRecipients) {
if (cbDecoded == cbToBeEncoded &&
memcmp(pbDecoded, pbToBeEncoded, cbDecoded) == 0) {
if (fVerbose)
printf("SUCCESS:: Decoded == ToBeEncoded\n");
} else
printf("***** ERROR:: Decoded != ToBeEncoded\n");
}
if (fVerbose) {
printf("Decoded bytes::\n");
PrintBytes(" ", pbDecoded, cbDecoded);
}
cbDecoded2 = cbDecoded;
if (NULL == (pbDecoded2 = (BYTE *) TestAlloc(
cbDecoded2 + DELTA_MORE_LENGTH)))
goto ErrorReturn;
if (!CryptDecodeMessage(
CMSG_ALL_FLAGS,
&DecryptPara,
NULL, // pVerifyPara
0, // dwSignerIndex
pbEncryptedBlob,
cbEncryptedBlob,
0, // dwPrevInnerContentType
&dwMsgType,
&dwInnerContentType,
pbDecoded2,
&cbDecoded2,
&pXchgCert2,
NULL // pSignerCert
)) {
if (GetLastError() == CRYPT_E_RECIPIENT_NOT_FOUND)
printf("message has no recipients\n");
else {
PrintLastError("CryptDecodeMessage(CMSG_ENVELOPED)");
goto ErrorReturn;
}
}
if (cbDecoded2 > DELTA_LESS_LENGTH) {
cbData = cbDecoded2 - DELTA_LESS_LENGTH;
fResult = CryptDecodeMessage(
CMSG_ALL_FLAGS,
&DecryptPara,
NULL, // pVerifyPara
0, // dwSignerIndex
pbEncryptedBlob,
cbEncryptedBlob,
0, // dwPrevInnerContentType
&dwMsgType,
NULL, // pdwInnerContentType
pbDecoded2,
&cbData,
NULL, // ppXchgCert
NULL // ppSignerCert
);
CheckLessLength("CryptDecodeMessage(ENVELOPE)", fResult, cbData,
cbDecoded2);
}
cbData = cbDecoded2 + DELTA_MORE_LENGTH;
if (!CryptDecodeMessage(
CMSG_ALL_FLAGS,
&DecryptPara,
NULL, // pVerifyPara
0, // dwSignerIndex
pbEncryptedBlob,
cbEncryptedBlob,
0, // dwPrevInnerContentType
&dwMsgType,
&dwInnerContentType,
pbDecoded2,
&cbData,
NULL, // ppXchgCert
NULL // ppSignerCert
)) {
if (GetLastError() == CRYPT_E_RECIPIENT_NOT_FOUND)
printf("message has no recipients\n");
else {
PrintLastError("CryptDecodeMessage(CMSG_ENVELOPED)");
goto ErrorReturn;
}
}
CheckMoreLength("CryptDecodeMessage(ENVELOPE)", cbData, cbDecoded2);
if (dwMsgType != CMSG_ENVELOPED)
printf("failed :: dwMsgType(%d) != CMSG_ENVELOPED\n", dwMsgType);
else if (fVerbose)
printf("SUCCESS:: CryptDecodeMessage(CMSG_ENVELOPED)\n");
if (!pszReadEncodedFilename) {
#ifdef CMS_PKCS7
if ((fEncapsulatedContent && dwInnerContentType != CMSG_HASHED) ||
(!fEncapsulatedContent && dwInnerContentType != CMSG_DATA)) {
#else
if (dwInnerContentType != CMSG_DATA) {
#endif // CMS_PKCS7
#ifdef CMS_PKCS7
if (fEncapsulatedContent)
printf("ENVELOPE failed :: dwInnerContentType(%d) != CMSG_HASHED\n",
dwInnerContentType);
else
#endif // CMS_PKCS7
printf("ENVELOPE failed :: dwInnerContentType(%d) != CMSG_DATA\n",
dwInnerContentType);
}
}
if (cbDecoded2 != cbDecoded ||
(cbDecoded > 0 &&
memcmp(pbDecoded, pbDecoded2, cbDecoded) != 0))
printf("failed :: bad decoded content for CryptDecodeMessage(CMSG_ENVELOPED)\n");
if (pXchgCert && (pXchgCert2 == NULL ||
!CertCompareCertificate(dwCertEncodingType,
pXchgCert->pCertInfo, pXchgCert2->pCertInfo)))
printf("failed :: bad xchg cert for CryptDecodeMessage(CMSG_ENVELOPED)\n");
fResult = TRUE;
goto CommonReturn;
ErrorReturn:
fResult = FALSE;
CommonReturn:
if (!pszReadEncodedFilename)
FreeEncryptPara(&EncryptPara, cRecipientCert, ppRecipientCert);
FreeDecryptPara(&DecryptPara);
if (pbEncryptedBlob)
TestFree(pbEncryptedBlob);
if (pbDecoded)
TestFree(pbDecoded);
if (pbDecoded2)
TestFree(pbDecoded2);
if (pXchgCert)
CertFreeCertificateContext(pXchgCert);
if (pXchgCert2)
CertFreeCertificateContext(pXchgCert2);
return fResult;
}
static BOOL TestSignAndEnvelope()
{
BOOL fResult;
CRYPT_SIGN_MESSAGE_PARA SignPara;
CRYPT_VERIFY_MESSAGE_PARA VerifyPara;
CRYPT_ENCRYPT_MESSAGE_PARA EncryptPara;
DWORD cRecipientCert;
PCCERT_CONTEXT *ppRecipientCert;
CRYPT_DECRYPT_MESSAGE_PARA DecryptPara;
BYTE *pbEncodedBlob = NULL;
DWORD cbEncodedBlob;
BYTE *pbDecoded = NULL;
DWORD cbDecoded;
PCCERT_CONTEXT pSignerCert = NULL;
PCCERT_CONTEXT pXchgCert = NULL;
DWORD cbData;
fResult = InitSignPara(&SignPara);
fResult &= InitVerifyPara(&VerifyPara);
fResult &= InitEncryptPara(&EncryptPara, &cRecipientCert, &ppRecipientCert);
fResult &= InitDecryptPara(&DecryptPara);
if (!fResult) goto ErrorReturn;
if (fInnerSigned || fEncapsulatedContent) {
SignPara.dwFlags |= CRYPT_MESSAGE_BARE_CONTENT_OUT_FLAG;
EncryptPara.dwInnerContentType = CMSG_SIGNED;
}
fResult = CryptSignAndEncryptMessage(
&SignPara,
&EncryptPara,
cRecipientCert,
ppRecipientCert,
pbToBeEncoded,
cbToBeEncoded,
NULL, // pbEncodedBlob
&cbEncodedBlob
);
if (!fResult || cbEncodedBlob == 0) {
PrintLastError("CryptSignAndEncryptMessage(cb == 0)");
goto ErrorReturn;
}
if (NULL == (pbEncodedBlob = (BYTE *) TestAlloc(
cbEncodedBlob + DELTA_MORE_LENGTH)))
goto ErrorReturn;
fResult = CryptSignAndEncryptMessage(
&SignPara,
&EncryptPara,
cRecipientCert,
ppRecipientCert,
pbToBeEncoded,
cbToBeEncoded,
pbEncodedBlob,
&cbEncodedBlob
);
if (!fResult){
PrintLastError("CryptSignAndEncryptMessage");
goto ErrorReturn;
}
cbData = cbEncodedBlob - DELTA_LESS_LENGTH;
fResult = CryptSignAndEncryptMessage(
&SignPara,
&EncryptPara,
cRecipientCert,
ppRecipientCert,
pbToBeEncoded,
cbToBeEncoded,
pbEncodedBlob,
&cbData
);
// Note, length varies for DSS or DH
if (!IsDSSProv(dwCryptProvType) && !fDhRecipient)
CheckLessLength("CryptSignAndEncryptMessage", fResult, cbData,
cbEncodedBlob);
cbData = cbEncodedBlob + DELTA_MORE_LENGTH;
fResult = CryptSignAndEncryptMessage(
&SignPara,
&EncryptPara,
cRecipientCert,
ppRecipientCert,
pbToBeEncoded,
cbToBeEncoded,
pbEncodedBlob,
&cbData
);
if (!fResult){
PrintLastError("CryptSignAndEncryptMessage");
goto ErrorReturn;
}
// Note, length varies for DSS or DH
if (!IsDSSProv(dwCryptProvType) && !fDhRecipient)
CheckMoreLength("CryptSignAndEncryptMessage", cbData, cbEncodedBlob);
cbEncodedBlob = cbData;
if (pszMsgEncodedFilename)
WriteDERToFile(pszMsgEncodedFilename, pbEncodedBlob, cbEncodedBlob);
fResult = CryptDecryptAndVerifyMessageSignature(
&DecryptPara,
&VerifyPara,
0, // dwSignerIndex
pbEncodedBlob,
cbEncodedBlob,
NULL, // pbDecoded
&cbDecoded,
NULL, // ppXchgCert
NULL // ppSignerCert
);
if (!fResult || cbDecoded == 0) {
PrintLastError("CryptDecryptAndVerifyMessageSignature(cb == 0)");
goto ErrorReturn;
}
if (NULL == (pbDecoded = (BYTE *) TestAlloc(
cbDecoded + DELTA_MORE_LENGTH)))
goto ErrorReturn;
if (!CryptDecryptAndVerifyMessageSignature(
&DecryptPara,
&VerifyPara,
0, // dwSignerIndex
pbEncodedBlob,
cbEncodedBlob,
pbDecoded,
&cbDecoded,
&pXchgCert,
&pSignerCert
)) {
PrintLastError("CryptDecryptAndVerifyMessageSignature");
goto ErrorReturn;
}
cbData = cbDecoded - DELTA_LESS_LENGTH;
fResult = CryptDecryptAndVerifyMessageSignature(
&DecryptPara,
&VerifyPara,
0, // dwSignerIndex
pbEncodedBlob,
cbEncodedBlob,
pbDecoded,
&cbData,
NULL, // ppXchgCert
NULL // ppSignerCert
);
CheckLessLength("CryptDecryptAndVerifyMessageSignature", fResult, cbData,
cbDecoded);
cbData = cbDecoded + DELTA_MORE_LENGTH;
if (!CryptDecryptAndVerifyMessageSignature(
&DecryptPara,
&VerifyPara,
0, // dwSignerIndex
pbEncodedBlob,
cbEncodedBlob,
pbDecoded,
&cbData,
NULL, // ppXchgCert
NULL // ppSignerCert
)) {
PrintLastError("CryptDecryptAndVerifyMessageSignature");
goto ErrorReturn;
}
CheckMoreLength("CryptDecryptAndVerifyMessageSignature", cbData,
cbDecoded);
if (pXchgCert) {
if (fVerbose) {
printf("----- XchgCert -----\n");
DisplayCert(pXchgCert);
}
} else
printf("no xchg cert\n");
if (pSignerCert) {
if (fVerbose) {
printf("----- Verifier -----\n");
DisplayCert(pSignerCert);
}
} else
printf("no verifier cert\n");
if (cbDecoded == cbToBeEncoded &&
memcmp(pbDecoded, pbToBeEncoded, cbDecoded) == 0) {
if (fVerbose)
printf("SUCCESS:: Decoded == ToBeEncoded\n");
} else
printf("***** ERROR:: Decoded != ToBeEncoded\n");
if (fVerbose) {
printf("Decoded bytes::\n");
PrintBytes(" ", pbDecoded, cbDecoded);
}
fResult = TRUE;
goto CommonReturn;
ErrorReturn:
fResult = FALSE;
CommonReturn:
FreeSignPara(&SignPara);
FreeVerifyPara(&VerifyPara);
FreeEncryptPara(&EncryptPara, cRecipientCert, ppRecipientCert);
FreeDecryptPara(&DecryptPara);
if (pbEncodedBlob)
TestFree(pbEncodedBlob);
if (pbDecoded)
TestFree(pbDecoded);
if (pSignerCert)
CertFreeCertificateContext(pSignerCert);
if (pXchgCert)
CertFreeCertificateContext(pXchgCert);
return fResult;
}
static BOOL TestHash()
{
BOOL fResult;
CRYPT_HASH_MESSAGE_PARA HashPara;
CRYPT_VERIFY_MESSAGE_PARA VerifyPara;
BYTE *pbHashedBlob = NULL;
DWORD cbHashedBlob;
BYTE *pbDecoded = NULL;
DWORD cbDecoded;
BYTE *pbDecoded2 = NULL;
DWORD cbDecoded2;
DWORD dwMsgType;
DWORD cbData;
DWORD dwInnerContentType = 0x1233467;
fResult = InitHashPara(&HashPara);
if (!fResult) goto ErrorReturn;
cbHashedBlob = 0;
fResult = CryptHashMessage(
&HashPara,
fDetached,
fDetached ? DETACHED_CONTENT_CNT : 1,
rgpbDetachedToBeEncoded,
rgcbDetachedToBeEncoded,
NULL, // pbHashedBlob
&cbHashedBlob,
NULL, // pbComputedHash
NULL // pcbComputedHash
);
if (!fResult || cbHashedBlob == 0) {
PrintLastError("CryptHashMessage(cb == 0)");
goto ErrorReturn;
}
if (NULL == (pbHashedBlob = (BYTE *) TestAlloc(
cbHashedBlob + DELTA_MORE_LENGTH)))
goto ErrorReturn;
if (!CryptHashMessage(
&HashPara,
fDetached,
fDetached ? DETACHED_CONTENT_CNT : 1,
rgpbDetachedToBeEncoded,
rgcbDetachedToBeEncoded,
pbHashedBlob,
&cbHashedBlob,
NULL, // pbComputedHash
NULL // pcbComputedHash
)) {
PrintLastError("CryptHashMessage");
goto ErrorReturn;
}
cbData = cbHashedBlob - DELTA_LESS_LENGTH;
fResult = CryptHashMessage(
&HashPara,
fDetached,
fDetached ? DETACHED_CONTENT_CNT : 1,
rgpbDetachedToBeEncoded,
rgcbDetachedToBeEncoded,
pbHashedBlob,
&cbData,
NULL, // pbComputedHash
NULL // pcbComputedHash
);
CheckLessLength("CryptHashMessage", fResult, cbData, cbHashedBlob);
cbData = cbHashedBlob + DELTA_MORE_LENGTH;
if (!CryptHashMessage(
&HashPara,
fDetached,
fDetached ? DETACHED_CONTENT_CNT : 1,
rgpbDetachedToBeEncoded,
rgcbDetachedToBeEncoded,
pbHashedBlob,
&cbData,
NULL, // pbComputedHash
NULL // pcbComputedHash
)) {
PrintLastError("CryptHashMessage");
goto ErrorReturn;
}
CheckMoreLength("CryptHashMessage", cbData, cbHashedBlob);
if (pszMsgEncodedFilename)
WriteDERToFile(pszMsgEncodedFilename, pbHashedBlob, cbHashedBlob);
if (fDetached) {
if (!CryptVerifyDetachedMessageHash(
&HashPara,
pbHashedBlob,
cbHashedBlob,
DETACHED_CONTENT_CNT,
rgpbDetachedToBeEncoded,
rgcbDetachedToBeEncoded,
NULL, // pbComputedHash
NULL // pcbComputedHash
)) {
PrintLastError("CryptVerifyDetachedMessageHash");
goto ErrorReturn;
}
} else {
fResult = CryptVerifyMessageHash(
&HashPara,
pbHashedBlob,
cbHashedBlob,
NULL, // pbDecoded
&cbDecoded,
NULL, // pbComputedHash
NULL // pcbComputedHash
);
if (!fResult || cbDecoded == 0) {
PrintLastError("CryptVerifyMessageHash(cb == 0)");
goto ErrorReturn;
}
if (NULL == (pbDecoded = (BYTE *) TestAlloc(
cbDecoded + DELTA_MORE_LENGTH)))
goto ErrorReturn;
if (!CryptVerifyMessageHash(
&HashPara,
pbHashedBlob,
cbHashedBlob,
pbDecoded,
&cbDecoded,
NULL, // pbComputedHash
NULL // pcbComputedHash
)) {
PrintLastError("CryptVerifyMessageHash");
goto ErrorReturn;
}
cbData = cbDecoded - DELTA_LESS_LENGTH;
fResult = CryptVerifyMessageHash(
&HashPara,
pbHashedBlob,
cbHashedBlob,
pbDecoded,
&cbData,
NULL, // pbComputedHash
NULL // pcbComputedHash
);
CheckLessLength("CryptVerifyMessageHash", fResult, cbData, cbDecoded);
cbData = cbDecoded + DELTA_MORE_LENGTH;
if (!CryptVerifyMessageHash(
&HashPara,
pbHashedBlob,
cbHashedBlob,
pbDecoded,
&cbData,
NULL, // pbComputedHash
NULL // pcbComputedHash
)) {
PrintLastError("CryptVerifyMessageHash");
goto ErrorReturn;
}
CheckMoreLength("CryptVerifyMessageHash", cbData, cbDecoded);
}
if (!fDetached) {
if (cbDecoded == cbToBeEncoded &&
memcmp(pbDecoded, pbToBeEncoded, cbDecoded) == 0) {
if (fVerbose)
printf("SUCCESS:: Decoded == ToBeEncoded\n");
} else
printf("***** ERROR:: Decoded != ToBeEncoded\n");
if (fVerbose) {
printf("Decoded bytes::\n");
PrintBytes(" ", pbDecoded, cbDecoded);
}
cbDecoded2 = cbDecoded;
if (cbDecoded2 ) {
if (NULL == (pbDecoded2 = (BYTE *) TestAlloc(cbDecoded2)))
goto ErrorReturn;
}
InitVerifyPara(&VerifyPara);
if (!CryptDecodeMessage(
CMSG_ALL_FLAGS,
NULL, // pDecryptPara
&VerifyPara,
0, // dwSignerIndex
pbHashedBlob,
cbHashedBlob,
0, // dwPrevInnerContentType
&dwMsgType,
&dwInnerContentType,
pbDecoded2,
&cbDecoded2,
NULL, // ppXchgCert
NULL // ppSignCert
)) {
PrintLastError("CryptDecodeMessage(CMSG_HASHED)");
goto ErrorReturn;
}
if (dwMsgType != CMSG_HASHED)
printf("failed :: dwMsgType(%d) != CMSG_HASHED\n", dwMsgType);
else if (fVerbose)
printf("SUCCESS:: CryptDecodeMessage(CMSG_HASHED)\n");
if (dwInnerContentType != CMSG_DATA) {
printf("HASHED failed :: dwInnerContentType(%d) != CMSG_DATA\n",
dwInnerContentType);
}
if (cbDecoded2 != cbDecoded ||
(cbDecoded > 0 &&
memcmp(pbDecoded, pbDecoded2, cbDecoded) != 0))
printf("failed :: bad decoded content for CryptDecodeMessage(CMSG_HASHED)\n");
}
fResult = TRUE;
goto CommonReturn;
ErrorReturn:
fResult = FALSE;
CommonReturn:
FreeHashPara(&HashPara);
if (pbHashedBlob)
TestFree(pbHashedBlob);
if (pbDecoded)
TestFree(pbDecoded);
if (pbDecoded2)
TestFree(pbDecoded2);
return fResult;
}
static BOOL TestComputedHash()
{
BOOL fResult;
CRYPT_HASH_MESSAGE_PARA HashPara;
BYTE *pbHashedBlob = NULL;
DWORD cbHashedBlob;
BYTE *pbDecoded = NULL;
DWORD cbDecoded;
BYTE rgbEncodedComputedHash[MAX_HASH_LEN];
BYTE rgbDecodedComputedHash[MAX_HASH_LEN];
DWORD cbEncodedComputedHash;
DWORD cbDecodedComputedHash;
fResult = InitHashPara(&HashPara);
if (!fResult) goto ErrorReturn;
cbHashedBlob = 0;
cbEncodedComputedHash = 0;
fResult = CryptHashMessage(
&HashPara,
fDetached,
fDetached ? DETACHED_CONTENT_CNT : 1,
rgpbDetachedToBeEncoded,
rgcbDetachedToBeEncoded,
NULL, // pbHashedBlob
&cbHashedBlob,
NULL, // pbComputedHash
&cbEncodedComputedHash
);
if (!fResult || cbHashedBlob == 0) {
PrintLastError("CryptHashMessage(cb == 0)");
goto ErrorReturn;
}
if (cbEncodedComputedHash == 0) {
PrintLastError("CryptHashMessage(cbComputedHash == 0)");
goto ErrorReturn;
}
if (cbEncodedComputedHash > MAX_HASH_LEN) {
PrintLastError("CryptHashMessage(cbComputedHash > MAX_HASH_LEN)");
goto ErrorReturn;
}
if (NULL == (pbHashedBlob = (BYTE *) TestAlloc(cbHashedBlob)))
goto ErrorReturn;
if (!CryptHashMessage(
&HashPara,
fDetached,
fDetached ? DETACHED_CONTENT_CNT : 1,
rgpbDetachedToBeEncoded,
rgcbDetachedToBeEncoded,
pbHashedBlob,
&cbHashedBlob,
rgbEncodedComputedHash,
&cbEncodedComputedHash
)) {
PrintLastError("CryptHashMessage");
goto ErrorReturn;
}
if (fVerbose) {
printf("Encoded Computed Hash::\n");
PrintBytes(" ", rgbEncodedComputedHash, cbEncodedComputedHash);
}
if (pszMsgEncodedFilename)
WriteDERToFile(pszMsgEncodedFilename, pbHashedBlob, cbHashedBlob);
if (fDetached) {
cbDecodedComputedHash = MAX_HASH_LEN;
if(!CryptVerifyDetachedMessageHash(
&HashPara,
pbHashedBlob,
cbHashedBlob,
DETACHED_CONTENT_CNT,
rgpbDetachedToBeEncoded,
rgcbDetachedToBeEncoded,
rgbDecodedComputedHash,
&cbDecodedComputedHash
)) {
PrintLastError("CryptVerifyDetachedMessageHash");
goto ErrorReturn;
}
if (cbDecodedComputedHash == 0) {
PrintLastError("CryptVerifyDetachedMessageHash(cbComputedHash == 0)");
goto ErrorReturn;
}
if (cbDecodedComputedHash > MAX_HASH_LEN) {
PrintLastError("CryptVerifyDetachedMessageHash(cbComputedHash > MAX_HASH_LEN)");
goto ErrorReturn;
}
} else {
cbDecoded = 0;
cbDecodedComputedHash = 0;
fResult = CryptVerifyMessageHash(
&HashPara,
pbHashedBlob,
cbHashedBlob,
NULL, // pbDecoded
&cbDecoded,
NULL, // pbComputedHash
&cbDecodedComputedHash
);
if (!fResult || cbDecoded == 0) {
PrintLastError("CryptVerifyMessageHash(cb == 0)");
goto ErrorReturn;
}
if (cbDecodedComputedHash == 0) {
PrintLastError("CryptVerifyMessageHash(cbComputedHash == 0)");
goto ErrorReturn;
}
if (cbDecodedComputedHash > MAX_HASH_LEN) {
PrintLastError("CryptVerifyMessageHash(cbComputedHash > MAX_HASH_LEN)");
goto ErrorReturn;
}
if (NULL == (pbDecoded = (BYTE *) TestAlloc(cbDecoded)))
goto ErrorReturn;
if(!CryptVerifyMessageHash(
&HashPara,
pbHashedBlob,
cbHashedBlob,
pbDecoded,
&cbDecoded,
rgbDecodedComputedHash,
&cbDecodedComputedHash
)) {
PrintLastError("CryptVerifyMessageHash");
goto ErrorReturn;
}
}
if (fVerbose) {
printf("Decoded Computed Hash::\n");
PrintBytes(" ", rgbDecodedComputedHash, cbDecodedComputedHash);
}
if (cbDecodedComputedHash == cbEncodedComputedHash &&
memcmp(rgbDecodedComputedHash, rgbEncodedComputedHash,
cbDecodedComputedHash) == 0) {
if (fVerbose)
printf("SUCCESS:: Computed Hash Decoded == ToBeEncoded\n");
} else
printf("***** ERROR:: Computed Hash Decoded != ToBeEncoded\n");
if (!fDetached) {
if (cbDecoded == cbToBeEncoded &&
memcmp(pbDecoded, pbToBeEncoded, cbDecoded) == 0) {
if (fVerbose)
printf("SUCCESS:: Decoded == ToBeEncoded\n");
} else
printf("***** ERROR:: Decoded != ToBeEncoded\n");
if (fVerbose) {
printf("Decoded bytes::\n");
PrintBytes(" ", pbDecoded, cbDecoded);
}
}
fResult = TRUE;
goto CommonReturn;
ErrorReturn:
fResult = FALSE;
CommonReturn:
FreeHashPara(&HashPara);
if (pbHashedBlob)
TestFree(pbHashedBlob);
if (pbDecoded)
TestFree(pbDecoded);
return fResult;
}
static BOOL TestNoCertSign()
{
BOOL fResult;
HCRYPTPROV hCryptProv = 0;
CRYPT_KEY_SIGN_MESSAGE_PARA SignPara;
CRYPT_KEY_VERIFY_MESSAGE_PARA VerifyPara;
BYTE *pbSignedBlob = NULL;
DWORD cbSignedBlob;
BYTE *pbDecoded = NULL;
DWORD cbDecoded;
PCERT_PUBLIC_KEY_INFO pPublicKeyInfo1 = NULL;
PCERT_PUBLIC_KEY_INFO pPublicKeyInfo2 = NULL;
DWORD cbInfo;
BYTE *pbEncodedKey = NULL;
DWORD cbEncodedKey;
fResult = CryptAcquireContext(
&hCryptProv,
NULL, // pszContainer
NULL, // pszProvider
dwCryptProvType,
0 // dwFlags
);
if (!fResult) {
hCryptProv = 0;
PrintLastError("TestNoCertSign::CryptAcquireContext");
goto ErrorReturn;
}
cbInfo = 0;
fResult = CryptExportPublicKeyInfo(
hCryptProv,
dwSignKeySpec,
dwCertEncodingType,
NULL, // pPubKeyInfo
&cbInfo
);
if (!fResult || cbInfo == 0) {
PrintLastError("CryptExportPublicKeyInfo(cb == 0)");
goto ErrorReturn;
}
if (NULL == (pPublicKeyInfo1 = (PCERT_PUBLIC_KEY_INFO) TestAlloc(cbInfo)))
goto ErrorReturn;
if (!CryptExportPublicKeyInfo(
hCryptProv,
dwSignKeySpec,
dwCertEncodingType,
pPublicKeyInfo1,
&cbInfo
)) {
PrintLastError("CryptExportPublicKeyInfo");
goto ErrorReturn;
}
cbEncodedKey = 0;
fResult = CryptEncodeObject(
dwCertEncodingType,
X509_PUBLIC_KEY_INFO,
pPublicKeyInfo1,
NULL, // pbEncodedKey
&cbEncodedKey
);
if (!fResult || cbEncodedKey == 0) {
PrintLastError("CryptEncodeObject(cb == 0)");
goto ErrorReturn;
}
if (NULL == (pbEncodedKey = (BYTE *) TestAlloc(cbEncodedKey)))
goto ErrorReturn;
if (!CryptEncodeObject(
dwCertEncodingType,
X509_PUBLIC_KEY_INFO,
pPublicKeyInfo1,
pbEncodedKey,
&cbEncodedKey
)) {
PrintLastError("CryptEncodeObject");
goto ErrorReturn;
}
memset(&SignPara, 0, sizeof(SignPara));
SignPara.cbSize = sizeof(SignPara);
SignPara.dwMsgAndCertEncodingType =
dwMsgEncodingType | dwCertEncodingType;
SignPara.hCryptProv = hCryptProv;
SignPara.dwKeySpec = dwSignKeySpec;
if (NULL == (SignPara.HashAlgorithm.pszObjId = (LPSTR) GetOID(
pszHashName, CRYPT_HASH_ALG_OID_GROUP_ID))) {
printf("Failed => unknown hash name (%s)\n", pszHashName);
goto ErrorReturn;
}
if (IsDSSProv(dwCryptProvType)) {
SignPara.cbSize = sizeof(SignPara);
SignPara.PubKeyAlgorithm.pszObjId = (LPSTR) GetOID(
"Dss", CRYPT_PUBKEY_ALG_OID_GROUP_ID);
} else
SignPara.cbSize = offsetof(CRYPT_KEY_SIGN_MESSAGE_PARA,
PubKeyAlgorithm);
memset(&VerifyPara, 0, sizeof(VerifyPara));
VerifyPara.cbSize = sizeof(VerifyPara);
VerifyPara.dwMsgEncodingType = dwMsgEncodingType;
VerifyPara.hCryptProv = 0;
cbSignedBlob = 0;
fResult = CryptSignMessageWithKey(
&SignPara,
pbEncodedKey,
cbEncodedKey,
NULL, // pbSignedBlob
&cbSignedBlob
);
if (!fResult || cbSignedBlob == 0) {
PrintLastError("CryptSignMessageWithKey(cb == 0)");
goto ErrorReturn;
}
if (NULL == (pbSignedBlob = (BYTE *) TestAlloc(cbSignedBlob)))
goto ErrorReturn;
if (!CryptSignMessageWithKey(
&SignPara,
pbEncodedKey,
cbEncodedKey,
pbSignedBlob,
&cbSignedBlob
)) {
PrintLastError("CryptSignMessageWithKey");
goto ErrorReturn;
}
if (pszMsgEncodedFilename)
WriteDERToFile(pszMsgEncodedFilename, pbSignedBlob, cbSignedBlob);
// First get the encoded public key info (ie, don't verify the signature)
cbDecoded = 0;
fResult = CryptVerifyMessageSignatureWithKey(
&VerifyPara,
NULL, // pPublicKeyInfo
pbSignedBlob,
cbSignedBlob,
NULL, // pbDecoded
&cbDecoded
);
if (!fResult || cbDecoded == 0) {
PrintLastError("CryptVerifyMessageSignatureWithKey(cb == 0)");
goto ErrorReturn;
}
if (NULL == (pbDecoded = (BYTE *) TestAlloc(cbDecoded)))
goto ErrorReturn;
if(!CryptVerifyMessageSignatureWithKey(
&VerifyPara,
NULL, // pPublicKeyInfo
pbSignedBlob,
cbSignedBlob,
pbDecoded,
&cbDecoded
)) {
PrintLastError("CryptVerifyMessageSignatureWithKey");
goto ErrorReturn;
}
// Now decode the public key info stored in the signed message
cbInfo = 0;
fResult = CryptDecodeObject(
dwCertEncodingType,
X509_PUBLIC_KEY_INFO,
pbDecoded,
cbDecoded,
0, // dwFlags
NULL, // pInfo
&cbInfo
);
if (!fResult || cbInfo == 0) {
PrintLastError("CryptDecodeObject(cb == 0)");
goto ErrorReturn;
}
if (NULL == (pPublicKeyInfo2 = (PCERT_PUBLIC_KEY_INFO) TestAlloc(cbInfo)))
goto ErrorReturn;
if (!CryptDecodeObject(
dwCertEncodingType,
X509_PUBLIC_KEY_INFO,
pbDecoded,
cbDecoded,
0, // dwFlags
pPublicKeyInfo2,
&cbInfo
)) {
PrintLastError("CryptDecodeObject");
goto ErrorReturn;
}
if (fVerbose) {
printf("Decoded Algorithm Identifier:: %s\n",
pPublicKeyInfo2->Algorithm.pszObjId);
printf("Decoded public key bytes::\n");
PrintBytes(" ", pPublicKeyInfo2->PublicKey.pbData,
pPublicKeyInfo2->PublicKey.cbData);
}
if (strcmp(pPublicKeyInfo1->Algorithm.pszObjId,
pPublicKeyInfo2->Algorithm.pszObjId) == 0 &&
CertComparePublicKeyInfo(
dwCertEncodingType,
pPublicKeyInfo1,
pPublicKeyInfo2)) {
if (fVerbose)
printf("SUCCESS:: Decoded PublicKeyInfo == PublicKeyInfo\n");
} else {
printf("***** ERROR:: Decoded PublicKeyInfo != PublicKeyInfo\n");
if (fVerbose) {
printf("Expected Algorithm Identifier:: %s\n",
pPublicKeyInfo1->Algorithm.pszObjId);
printf("Expected public key bytes::\n");
PrintBytes(" ", pPublicKeyInfo1->PublicKey.pbData,
pPublicKeyInfo1->PublicKey.cbData);
}
goto ErrorReturn;
}
// Use the public key info to verify the signature
if (!CryptVerifyMessageSignatureWithKey(
&VerifyPara,
pPublicKeyInfo2,
pbSignedBlob,
cbSignedBlob,
NULL, // pbDecoded
NULL // pcbDecoded
)) {
PrintLastError("CryptVerifyMessageSignatureWithKey(pPublicKeyInfo verify)");
goto ErrorReturn;
}
fResult = TRUE;
goto CommonReturn;
ErrorReturn:
fResult = FALSE;
CommonReturn:
if (hCryptProv)
CryptReleaseContext(hCryptProv, 0);
if (pPublicKeyInfo1)
TestFree(pPublicKeyInfo1);
if (pPublicKeyInfo2)
TestFree(pPublicKeyInfo2);
if (pbSignedBlob)
TestFree(pbSignedBlob);
if (pbDecoded)
TestFree(pbDecoded);
if (pbEncodedKey)
TestFree(pbEncodedKey);
return fResult;
}
static BOOL TimeStampTest(PCRYPT_TIME_STAMP_REQUEST_INFO pTSInfo) {
BYTE * pbDer = NULL;
DWORD cbEncode = 0;
DWORD cbDecode = 0;
PCRYPT_TIME_STAMP_REQUEST_INFO pbTSInfo = NULL;
BOOL fOk = TRUE;
// encode it
if(
!CryptEncodeObject(
CRYPT_ASN_ENCODING,
PKCS_TIME_REQUEST,
pTSInfo,
NULL,
&cbEncode) ||
(pbDer = (PBYTE) _alloca(cbEncode)) == NULL ||
!CryptEncodeObject(
CRYPT_ASN_ENCODING,
PKCS_TIME_REQUEST,
pTSInfo,
pbDer,
&cbEncode) )
{
goto CryptEncodeTimeRequestError;
}
// decode it
if(
!CryptDecodeObject(
CRYPT_ASN_ENCODING,
PKCS_TIME_REQUEST,
pbDer,
cbEncode,
CRYPT_DECODE_NOCOPY_FLAG,
NULL,
&cbDecode) ||
(pbTSInfo = (PCRYPT_TIME_STAMP_REQUEST_INFO) _alloca(cbDecode)) == NULL ||
!CryptDecodeObject(
CRYPT_ASN_ENCODING,
PKCS_TIME_REQUEST,
pbDer,
cbEncode,
CRYPT_DECODE_NOCOPY_FLAG,
pbTSInfo,
&cbDecode) )
{
goto CryptDecodeTimeRequestError;
}
// compare encoded data with decoded data
if(
_stricmp(pTSInfo->pszTimeStampAlgorithm, pbTSInfo->pszTimeStampAlgorithm) ||
_stricmp(pTSInfo->pszContentType, pbTSInfo->pszContentType) ||
pTSInfo->Content.cbData != pbTSInfo->Content.cbData ||
pTSInfo->cAttribute != pbTSInfo->cAttribute )
{
goto CompareTimeRequestError;
}
if(pTSInfo->Content.cbData != 0 &&
memcmp(pTSInfo->Content.pbData, pbTSInfo->Content.pbData, pTSInfo->Content.cbData) )
{
goto CompareTimeRequestError;
}
CommonReturn:
return(fOk);
ErrorReturn:
fOk = FALSE;
goto CommonReturn;
// TRACE_ERROR(BuildTimeStampError);
TRACE_ERROR(CryptEncodeTimeRequestError);
TRACE_ERROR(CryptDecodeTimeRequestError);
TRACE_ERROR(CompareTimeRequestError);
}
static BOOL TestTimeStamp()
{
CRYPT_TIME_STAMP_REQUEST_INFO TSInfo;
BOOL fOk;
BYTE rgTestData[] = {
0x1b, 0xf6, 0x92, 0xee, 0x6c, 0x44, 0xc5, 0xed, 0x51, 0xe4, 0x1a, 0xac, 0x21, 0x07, 0x2f, 0x63,
0x6b, 0xc9, 0x27, 0x30, 0x90, 0xb8, 0x3c, 0xa6, 0x75, 0xf8, 0x17, 0x5a, 0x28, 0x2b, 0xe7, 0x3f,
0xd7, 0x47, 0xad, 0x82, 0x1a, 0x34, 0x37, 0x27, 0x22, 0xd2, 0x64, 0x8b, 0x24, 0xe6, 0x42, 0x55,
0x8a, 0xfe, 0xd1, 0xb4, 0xcf, 0x96, 0xa3, 0xea, 0x90, 0xf9, 0x2b, 0xeb, 0x16, 0x27, 0xaa, 0x5b
};
// initialize the timestamp structure
TSInfo.pszTimeStampAlgorithm = szOID_RSA_signingTime;
TSInfo.pszContentType = szOID_RSA_data;
TSInfo.Content.cbData = sizeof(rgTestData);
TSInfo.Content.pbData = rgTestData;
TSInfo.cAttribute = 0;
TSInfo.rgAttribute = NULL;
if( (fOk = TimeStampTest(&TSInfo) ) == TRUE ) {
TSInfo.Content.cbData = 0;
TSInfo.Content.pbData = NULL;
fOk = TimeStampTest(&TSInfo);
}
return(fOk);
}
static BOOL TestPKCS10Attr() {
CRYPT_ENROLLMENT_NAME_VALUE_PAIR nameValuePair = {L"Name", L"Value"};
PCRYPT_ENROLLMENT_NAME_VALUE_PAIR pNameValuePair = NULL;
DWORD cb = 0;
CRYPT_DATA_BLOB blob;
BOOL fOk = TRUE;
BYTE signatureData[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA};
CRYPT_CSP_PROVIDER cspProvider = {32, L"My CSP", {sizeof(signatureData), signatureData, 0}};
PCRYPT_CSP_PROVIDER pCSPProvider = NULL;
memset(&blob, 0, sizeof(CRYPT_DATA_BLOB));
if(!CryptEncodeObjectEx(
CRYPT_ASN_ENCODING,
szOID_ENROLLMENT_NAME_VALUE_PAIR,
&nameValuePair,
CRYPT_ENCODE_ALLOC_FLAG,
NULL,
&blob.pbData,
&blob.cbData
))
goto ErrorCryptEncodeNameValuePair;
if(!CryptDecodeObjectEx(
CRYPT_ASN_ENCODING,
szOID_ENROLLMENT_NAME_VALUE_PAIR,
blob.pbData,
blob.cbData,
CRYPT_ENCODE_ALLOC_FLAG,
NULL,
&pNameValuePair,
&cb
))
goto ErrorCryptDecodeNameValuePair;
if(
wcscmp(nameValuePair.pwszName, pNameValuePair->pwszName) ||
wcscmp(nameValuePair.pwszValue, pNameValuePair->pwszValue) )
goto CompareNameValuePair;
// szOID_ENROLLMENT_CSP_PROVIDER
assert(blob.pbData != NULL);
LocalFree(blob.pbData);
memset(&blob, 0, sizeof(CRYPT_DATA_BLOB));
cb = 0;
if(!CryptEncodeObjectEx(
CRYPT_ASN_ENCODING,
szOID_ENROLLMENT_CSP_PROVIDER,
&cspProvider,
CRYPT_ENCODE_ALLOC_FLAG,
NULL,
&blob.pbData,
&blob.cbData
))
goto ErrorCryptEncodeCSPProvider;
if(!CryptDecodeObjectEx(
CRYPT_ASN_ENCODING,
szOID_ENROLLMENT_CSP_PROVIDER,
blob.pbData,
blob.cbData,
CRYPT_ENCODE_ALLOC_FLAG,
NULL,
&pCSPProvider,
&cb
))
goto ErrorCryptDecodeCSPProvider;
if(
wcscmp(cspProvider.pwszProviderName, pCSPProvider->pwszProviderName) ||
cspProvider.Signature.cbData != pCSPProvider->Signature.cbData ||
cspProvider.Signature.cUnusedBits != pCSPProvider->Signature.cUnusedBits ||
cspProvider.dwKeySpec != pCSPProvider->dwKeySpec ||
memcmp(cspProvider.Signature.pbData, pCSPProvider->Signature.pbData, cspProvider.Signature.cbData) )
goto CompareCSPProvider;
CommonReturn:
if(blob.pbData != NULL)
LocalFree(blob.pbData);
if(pNameValuePair != NULL)
LocalFree(pNameValuePair);
if(pCSPProvider != NULL)
LocalFree(pCSPProvider);
return(fOk);
ErrorReturn:
fOk = FALSE;
goto CommonReturn;
// TRACE_ERROR(BuildTimeStampError);
TRACE_ERROR(ErrorCryptEncodeNameValuePair);
TRACE_ERROR(ErrorCryptDecodeNameValuePair);
TRACE_ERROR(CompareNameValuePair);
TRACE_ERROR(ErrorCryptEncodeCSPProvider);
TRACE_ERROR(ErrorCryptDecodeCSPProvider);
TRACE_ERROR(CompareCSPProvider);
}
typedef BOOL (*PFN_TEST)(void);
static struct
{
LPCSTR pszName;
PFN_TEST pfn;
} Tests[] = {
"Sign", TestSign,
"Envelope", TestEnvelope,
"SignAndEnvelope", TestSignAndEnvelope,
"Hash", TestHash,
"ComputedHash", TestComputedHash,
"NoCertSign", TestNoCertSign,
"TimeStamp", TestTimeStamp,
"PKCS10Attr", TestPKCS10Attr
};
#define NTESTS (sizeof(Tests)/sizeof(Tests[0]))
static void Usage(void)
{
int i;
printf("Usage: tsca [options] <StoreFilename> [<TestName>] [<CertNameString>]\n");
printf("Options are:\n");
#ifdef CMS_PKCS7
printf(" -EncapsulatedContent - CMS encapsulated content\n");
printf(" -SP3Encrypt - SP3 compatible encrypt\n");
printf(" -DefaultGetSigner - Use default GetSignerCertificate\n");
printf(" -NoRecipients - No Envelope Recipients\n");
printf(" -AllRecipients - All Envelope Recipients in store\n");
printf(" -RecipientKeyId - Use KeyId for recipients\n");
printf(" -SignerKeyId - Use KeyId for signers\n");
printf(" -HashEncryptionAlgorithm - Use signature as hash encrypt algorithm\n");
printf(" -NoSalt - NoSalt for RC4\n");
printf(" -SilentKey - Silent private key usage\n");
#endif // CMS_PKCS7
printf(" -h - This message\n");
printf(" -A - Authenticated Attributes\n");
printf(" -D - Detached Hash or Signature\n");
printf(" -I - Inner Signed Content for SignAndEnvelope\n");
printf(" -X - Sign using keyeXchange\n");
printf(" -l - Print command line\n");
printf(" -v - Verbose\n");
printf(" -H<name> - Hash algorithm, default of \"md5\"\n");
printf(" -E<name> - Encrypt algorithm, default of \"rc2\"\n");
printf(" -e<EncryptBitLen> - Encrypt key bit length\n");
printf(" -i - Include IV in encrypt parameters\n");
printf(" -p<provider> - Specify crypto provider type number\n");
printf(" -P<PubKeyBitLen> - Public key bit length\n");
printf(" -r<filename> - Read encoded message from file\n");
printf(" -m<filename> - Write encoded message to file\n");
printf(" -c<filename> - Write message cert store to file\n");
printf(" -0 - Zero length content\n");
#ifdef ENABLE_SCA_STREAM_TEST
printf(" -s - Enable streaming\n");
printf(" -S - Enable indefinite length streaming\n");
#endif
printf("\n");
printf("Tests are (case insensitive name):\n");
for (i = 0; i < NTESTS; i++)
printf(" %s\n", Tests[i].pszName);
printf("\n");
printf("Default: ALL Tests\n");
}
int _cdecl main(int argc, char * argv[])
{
BOOL fResult;
LPSTR pszStoreFilename = NULL;
LPSTR pszTestName = NULL;
int TestIdx = 0;
while (--argc>0)
{
if (**++argv == '-')
{
#ifdef CMS_PKCS7
if (0 == _stricmp(argv[0]+1, "EncapsulatedContent")) {
fEncapsulatedContent = TRUE;
} else if (0 == _stricmp(argv[0]+1, "SP3Encrypt")) {
fSP3Encrypt = TRUE;
} else if (0 == _stricmp(argv[0]+1, "DefaultGetSigner")) {
fDefaultGetSigner = TRUE;
} else if (0 == _stricmp(argv[0]+1, "NoRecipients")) {
fNoRecipients = TRUE;
} else if (0 == _stricmp(argv[0]+1, "AllRecipients")) {
fAllRecipients = TRUE;
} else if (0 == _stricmp(argv[0]+1, "RecipientKeyId")) {
fRecipientKeyId = TRUE;
} else if (0 == _stricmp(argv[0]+1, "SignerKeyId")) {
fSignerKeyId = TRUE;
} else if (0 == _stricmp(argv[0]+1, "HashEncryptionAlgorithm")) {
fHashEncryptionAlgorithm = TRUE;
} else if (0 == _stricmp(argv[0]+1, "NoSalt")) {
fNoSalt = TRUE;
} else if (0 == _stricmp(argv[0]+1, "SilentKey")) {
fSilentKey = TRUE;
} else {
#endif // CMS_PKCS7
switch(argv[0][1])
{
case 'A':
fAuthAttr = TRUE;
break;
case 'D':
fDetached = TRUE;
break;
case 'I':
fInnerSigned = TRUE;
break;
case 'l':
printf("command line: %s\n", GetCommandLine());
break;
case 'p':
dwCryptProvType = strtoul( argv[0]+2, NULL, 0);
break;
case 'P':
dwPubKeyBitLen = strtoul( argv[0]+2, NULL, 0);
break;
case 'H':
pszHashName = argv[0]+2;
break;
case 'E':
pszEncryptName = argv[0]+2;
break;
case 'e':
dwEncryptBitLen = strtoul( argv[0]+2, NULL, 0);
break;
case 'i':
fEncryptIV = TRUE;
break;
case 'v':
fVerbose = TRUE;
break;
case 'X':
dwSignKeySpec = AT_KEYEXCHANGE;
break;
case 'm':
pszMsgEncodedFilename = argv[0]+2;
if (*pszMsgEncodedFilename == '\0') {
printf("Need to specify filename\n");
Usage();
return -1;
}
break;
case 'c':
pszMsgCertFilename = argv[0]+2;
if (*pszMsgCertFilename == '\0') {
printf("Need to specify filename\n");
Usage();
return -1;
}
break;
case 'r':
pszReadEncodedFilename = argv[0]+2;
if (*pszReadEncodedFilename == '\0') {
printf("Need to specify filename\n");
Usage();
return -1;
}
break;
case '0':
cbToBeEncoded = 0;
rgcbDetachedToBeEncoded[0] = 0;
break;
#ifdef ENABLE_SCA_STREAM_TEST
case 'S':
fIndefiniteStream = TRUE;
case 's':
fStream = TRUE;
break;
#endif
case 'h':
default:
Usage();
return -1;
}
#ifdef CMS_PKCS7
}
#endif // CMS_PKCS7
} else {
if (pszStoreFilename == NULL)
pszStoreFilename = argv[0];
else if(pszTestName == NULL)
pszTestName = argv[0];
else if (pszCertNameFindStr == NULL)
pszCertNameFindStr = argv[0];
else {
printf("Too many arguments\n");
Usage();
return -1;
}
}
}
if (pszStoreFilename == NULL) {
printf("missing store filename\n");
Usage();
return -1;
}
if (pszTestName) {
for (TestIdx = 0; TestIdx < NTESTS; TestIdx++) {
if (_stricmp(pszTestName, Tests[TestIdx].pszName) == 0)
break;
}
if (TestIdx >= NTESTS) {
printf("Bad TestName: %s\n", pszTestName);
Usage();
return -1;
}
} else
TestIdx = 0;
if (fDetached) printf("Detached Enabled ");
if (pszReadEncodedFilename)
printf("Reading encoded msg from file: %s ", pszReadEncodedFilename);
if (pszMsgEncodedFilename)
printf("Writing encoded msg to file: %s ", pszMsgEncodedFilename);
if (pszMsgCertFilename)
printf("Writing msg cert store to file: %s ", pszMsgCertFilename);
printf("\n");
// Attempt to open the store
hCertStore = OpenStore(pszStoreFilename);
if (hCertStore == NULL)
goto ErrorReturn;
for ( ; TestIdx < NTESTS; TestIdx++) {
printf("Starting %s Test\n", Tests[TestIdx].pszName);
fResult = Tests[TestIdx].pfn();
if (fResult)
printf("Passed\n");
else
printf("Failed\n");
printf("\n");
if (pszTestName)
break;
}
ErrorReturn:
if (hCertStore) {
if (!CertCloseStore(hCertStore, CERT_CLOSE_STORE_CHECK_FLAG))
PrintLastError("CertCloseStore");
}
return 0;
}
static BOOL NameAttributeValueCompare(
IN const BYTE *pbValue,
IN DWORD cbValue,
IN PCERT_NAME_BLOB pName
)
{
BOOL fResult;
PCERT_NAME_INFO pInfo = NULL;
DWORD cbInfo;
DWORD cRDN, cAttr;
PCERT_RDN pRDN;
PCERT_RDN_ATTR pAttr;
cbInfo = 0;
fResult = CryptDecodeObject(
dwCertEncodingType,
X509_NAME,
pName->pbData,
pName->cbData,
0, // dwFlags
NULL, // pInfo
&cbInfo
);
if (!fResult || cbInfo == 0) {
PrintLastError(
"NameAttributeValueCompare::CryptDecodeObject(cbInfo == 0)");
goto ErrorReturn;
}
pInfo = (PCERT_NAME_INFO) TestAlloc(cbInfo);
if (pInfo == NULL) goto ErrorReturn;
if (!CryptDecodeObject(
dwCertEncodingType,
X509_NAME,
pName->pbData,
pName->cbData,
0, // dwFlags
pInfo,
&cbInfo
)) {
PrintLastError("NameAttributeValueCompare::CryptDecodeObject");
goto ErrorReturn;
}
for (cRDN = pInfo->cRDN, pRDN = pInfo->rgRDN; cRDN > 0; cRDN--, pRDN++) {
for (cAttr = pRDN->cRDNAttr, pAttr = pRDN->rgRDNAttr;
cAttr > 0; cAttr--, pAttr++) {
if (pAttr->Value.cbData == cbValue &&
memcmp(pAttr->Value.pbData, pbValue, cbValue) == 0) {
fResult = TRUE;
goto CommonReturn;
}
}
}
ErrorReturn:
fResult = FALSE;
CommonReturn:
if (pInfo)
TestFree(pInfo);
return fResult;
}
static PCCERT_CONTEXT FindCertWithKey(IN DWORD dwKeySpec)
{
PCCERT_CONTEXT pCert;
void *pvFindPara;
DWORD dwFindType;
if (pszCertNameFindStr) {
dwFindType = CERT_FIND_SUBJECT_STR_A;
pvFindPara = (void *) pszCertNameFindStr;
} else {
dwFindType = CERT_FIND_ANY;
pvFindPara = NULL;
}
// Find the first certificate in the store with a CRYPT_KEY_PROV_INFO
// property matching the specified dwSignKeySpec, dwCryptProvType and
// dwPubKeyBitLen
pCert = NULL;
while (TRUE) {
pCert = CertFindCertificateInStore(
hCertStore,
dwCertEncodingType,
0, // dwFindFlags,
dwFindType,
pvFindPara,
pCert
);
if (pCert == NULL)
break;
PCRYPT_KEY_PROV_INFO pInfo = NULL;
DWORD cbInfo = 0;
CertGetCertificateContextProperty(
pCert,
CERT_KEY_PROV_INFO_PROP_ID,
NULL,
&cbInfo
);
if (cbInfo >= sizeof(CRYPT_KEY_PROV_INFO) &&
(pInfo = (PCRYPT_KEY_PROV_INFO) TestAlloc(cbInfo))) {
BOOL fMatch = FALSE;
if (CertGetCertificateContextProperty(
pCert,
CERT_KEY_PROV_INFO_PROP_ID,
pInfo,
&cbInfo) &&
dwKeySpec == pInfo->dwKeySpec &&
dwCryptProvType == pInfo->dwProvType) {
if (0 == dwPubKeyBitLen)
fMatch = TRUE;
else
fMatch = (dwPubKeyBitLen == CertGetPublicKeyLength(
pCert->dwCertEncodingType,
&pCert->pCertInfo->SubjectPublicKeyInfo));
}
TestFree(pInfo);
if (fMatch)
break;
}
}
return pCert;
}
static BOOL InitSignPara(OUT PCRYPT_SIGN_MESSAGE_PARA pPara)
{
BOOL fResult;
PCCERT_CONTEXT pCert;
PCCERT_CONTEXT pIssuer;
PCCRL_CONTEXT pCrl;
DWORD dwFlags;
BYTE bIntendedKeyUsage;
memset(pPara, 0, sizeof(*pPara));
pPara->cbSize = sizeof(*pPara);
pPara->dwMsgEncodingType = dwMsgEncodingType;
if (NULL == (pPara->HashAlgorithm.pszObjId = (LPSTR) GetOID(
pszHashName, CRYPT_HASH_ALG_OID_GROUP_ID))) {
printf("Failed => unknown hash name (%s) for signing\n",
pszHashName);
goto ErrorReturn;
}
#ifdef ENABLE_SCA_STREAM_TEST
if (fStream) {
pPara->dwFlags |= SCA_STREAM_ENABLE_FLAG;
if (fIndefiniteStream)
pPara->dwFlags |= SCA_INDEFINITE_STREAM_FLAG;
}
#endif
#ifdef CMS_PKCS7
if (fSignerKeyId)
pPara->dwFlags |= CRYPT_MESSAGE_KEYID_SIGNER_FLAG;
if (fEncapsulatedContent) {
pPara->dwFlags |= CRYPT_MESSAGE_ENCAPSULATED_CONTENT_OUT_FLAG;
pPara->dwInnerContentType = CMSG_HASHED;
}
if (fSilentKey)
pPara->dwFlags |= CRYPT_MESSAGE_SILENT_KEYSET_FLAG;
#endif // CMS_PKCS7
pPara->rgpMsgCert = (PCCERT_CONTEXT*) TestAlloc(
sizeof(PCCERT_CONTEXT) * MAX_MSG_CERT);
if (pPara->rgpMsgCert == NULL) goto ErrorReturn;
pPara->rgpMsgCrl = (PCCRL_CONTEXT*) TestAlloc(
sizeof(PCCRL_CONTEXT) * MAX_MSG_CRL);
if (pPara->rgpMsgCrl == NULL) goto ErrorReturn;
pCert = FindCertWithKey(dwSignKeySpec);
if (pCert == NULL) {
PrintError("Couldn't find a cert having a key provider");
goto ErrorReturn;
} else if (fVerbose) {
printf("----- Signer -----\n");
DisplayCert(pCert);
}
#ifdef CMS_PKCS7
if (fHashEncryptionAlgorithm) {
pPara->HashEncryptionAlgorithm = pCert->pCertInfo->SignatureAlgorithm;
}
#endif // CMS_PKCS7
pPara->pSigningCert = pCert;
pPara->cMsgCert = 1;
pPara->rgpMsgCert[0] = pCert;
// Add the cert's issuer certs to the message. Add the issuer CRLs to
// the message.
while (TRUE) {
dwFlags = 0;
pIssuer = CertGetIssuerCertificateFromStore(
hCertStore,
pCert,
NULL, // pPrevIssuerContext
&dwFlags
);
if (pIssuer == NULL) break;
if (pPara->cMsgCert == MAX_MSG_CERT) {
PrintError("cMsgCert == MAX_MSG_CERT");
CertFreeCertificateContext(pIssuer);
break;
}
pCert = pIssuer;
pPara->rgpMsgCert[pPara->cMsgCert++] = pCert;
pCrl = NULL;
while (TRUE) {
dwFlags = 0;
pCrl = CertGetCRLFromStore(
pIssuer->hCertStore,
pIssuer,
pCrl,
&dwFlags
);
if (pCrl == NULL) break;
if (pPara->cMsgCrl == MAX_MSG_CRL) {
PrintError("cMsgCrl == MAX_MSG_CRL");
CertFreeCRLContext(pCrl);
break;
}
pPara->rgpMsgCrl[pPara->cMsgCrl++] = CertDuplicateCRLContext(pCrl);
}
}
if (fAuthAttr) {
pPara->cAuthAttr = AUTH_ATTR_COUNT;
pPara->rgAuthAttr = rgAuthAttr;
}
if (fVerbose) {
DWORD i;
printf("Msg Certs: %d MsgCrls: %d\n", pPara->cMsgCert, pPara->cMsgCrl);
for (i = 0; i < pPara->cMsgCert; i++) {
printf("----- Msg Cert[%i] -----\n", i);
DisplayCert(pPara->rgpMsgCert[i]);
}
for (i = 0; i < pPara->cMsgCrl; i++) {
printf("----- Msg Crl[%i] -----\n", i);
DisplayCrl(pPara->rgpMsgCrl[i]);
}
}
fResult = TRUE;
goto CommonReturn;
ErrorReturn:
FreeSignPara(pPara);
fResult = FALSE;
CommonReturn:
return fResult;
}
static void FreeSignPara(IN PCRYPT_SIGN_MESSAGE_PARA pPara)
{
while (pPara->cMsgCert-- > 0)
CertFreeCertificateContext(pPara->rgpMsgCert[pPara->cMsgCert]);
while (pPara->cMsgCrl-- > 0)
CertFreeCRLContext(pPara->rgpMsgCrl[pPara->cMsgCrl]);
if (pPara->rgpMsgCert)
TestFree(pPara->rgpMsgCert);
if (pPara->rgpMsgCrl)
TestFree(pPara->rgpMsgCrl);
memset(pPara, 0, sizeof(*pPara));
}
static PCCERT_CONTEXT WINAPI GetSignerCertificate(
IN void *pvGetArg,
IN DWORD dwCertEncodingType,
IN PCERT_INFO pSignerId, // Only the Issuer and SerialNumber
// fields are used
IN HCERTSTORE hMsgCertStore
)
{
if (fVerbose)
printf("GetSignerCertificate pSignerId = 0x%p\n", pSignerId);
return CertGetSubjectCertificateFromStore(hMsgCertStore, dwCertEncodingType,
pSignerId);
}
static BOOL InitVerifyPara(OUT PCRYPT_VERIFY_MESSAGE_PARA pPara)
{
memset(pPara, 0, sizeof(*pPara));
pPara->cbSize = sizeof(*pPara);
pPara->dwMsgAndCertEncodingType =
dwMsgEncodingType | dwCertEncodingType;
#ifdef ENABLE_SCA_STREAM_TEST
if (fStream)
pPara->dwMsgAndCertEncodingType |= SCA_STREAM_ENABLE_FLAG;
#endif
pPara->hCryptProv = 0;
#ifdef CMS_PKCS7
if (!fDefaultGetSigner)
#endif
pPara->pfnGetSignerCertificate = GetSignerCertificate;
return TRUE;
}
static void FreeVerifyPara(IN PCRYPT_VERIFY_MESSAGE_PARA pPara)
{
}
#define IV_LENGTH 8
static BOOL GetIV(BYTE rgbIV[IV_LENGTH])
{
SYSTEMTIME st;
GetSystemTime(&st);
assert(IV_LENGTH == sizeof(FILETIME));
SystemTimeToFileTime(&st, (LPFILETIME) rgbIV);
return TRUE;
}
static BOOL InitEncryptPara(
OUT PCRYPT_ENCRYPT_MESSAGE_PARA pPara,
OUT DWORD *pcRecipientCert,
OUT PCCERT_CONTEXT **pppRecipientCert
)
{
BOOL fResult;
PCCERT_CONTEXT pCert;
BYTE bIntendedKeyUsage;
PCRYPT_OBJID_BLOB pAlgPara;
*pppRecipientCert = NULL;
memset(pPara, 0, sizeof(*pPara));
pPara->cbSize = sizeof(*pPara);
pPara->dwMsgEncodingType = dwMsgEncodingType;
pPara->hCryptProv = 0;
#ifdef ENABLE_SCA_STREAM_TEST
if (fStream) {
pPara->dwFlags |= SCA_STREAM_ENABLE_FLAG;
if (fIndefiniteStream)
pPara->dwFlags |= SCA_INDEFINITE_STREAM_FLAG;
}
#endif
#ifdef CMS_PKCS7
if (fRecipientKeyId)
pPara->dwFlags |= CRYPT_MESSAGE_KEYID_RECIPIENT_FLAG;
if (fEncapsulatedContent) {
pPara->dwFlags |= CRYPT_MESSAGE_ENCAPSULATED_CONTENT_OUT_FLAG;
pPara->dwInnerContentType = CMSG_HASHED;
}
#endif // CMS_PKCS7
if (NULL == (pPara->ContentEncryptionAlgorithm.pszObjId = (LPSTR) GetOID(
pszEncryptName, CRYPT_ENCRYPT_ALG_OID_GROUP_ID))) {
printf("Failed => unknown encrypt name (%s)\n", pszEncryptName);
goto ErrorReturn;
}
pAlgPara = &pPara->ContentEncryptionAlgorithm.Parameters;
if (0 != dwEncryptBitLen && CALG_RC2 == GetAlgid(
pszEncryptName, CRYPT_ENCRYPT_ALG_OID_GROUP_ID)) {
if (fEncryptIV) {
CRYPT_RC2_CBC_PARAMETERS RC2Parameters;
switch (dwEncryptBitLen) {
case 40:
RC2Parameters.dwVersion = CRYPT_RC2_40BIT_VERSION;
break;
case 64:
RC2Parameters.dwVersion = CRYPT_RC2_64BIT_VERSION;
break;
case 128:
RC2Parameters.dwVersion = CRYPT_RC2_128BIT_VERSION;
break;
default:
printf("Failed => unknown RC2 length (%d)\n",
dwEncryptBitLen);
goto ErrorReturn;
}
RC2Parameters.fIV = fEncryptIV;
if (fEncryptIV) {
if (!GetIV(RC2Parameters.rgbIV))
goto ErrorReturn;
}
if (!AllocAndEncodeObject(
PKCS_RC2_CBC_PARAMETERS,
&RC2Parameters,
&pAlgPara->pbData,
&pAlgPara->cbData))
goto ErrorReturn;
} else {
RC2AuxInfo.cbSize = sizeof(RC2AuxInfo);
RC2AuxInfo.dwBitLen = dwEncryptBitLen;
pPara->pvEncryptionAuxInfo = &RC2AuxInfo;
#ifdef CMS_PKCS7
if (fSP3Encrypt)
RC2AuxInfo.dwBitLen |= CMSG_SP3_COMPATIBLE_ENCRYPT_FLAG;
#endif
}
} else if (CALG_RC4 == GetAlgid(pszEncryptName,
CRYPT_ENCRYPT_ALG_OID_GROUP_ID)) {
if (fEncryptIV) {
CRYPT_DATA_BLOB Salt;
DWORD i;
for (i = 0; i < MAX_SALT_LEN; i++)
rgbSalt[i] = (BYTE) i;
Salt.cbData = MAX_SALT_LEN;
Salt.pbData = rgbSalt;
if (!AllocAndEncodeObject(
X509_OCTET_STRING,
&Salt,
&pAlgPara->pbData,
&pAlgPara->cbData
))
goto ErrorReturn;
} else if (0 != dwEncryptBitLen) {
memset(&RC4AuxInfo, 0, sizeof(RC4AuxInfo));
RC4AuxInfo.cbSize = sizeof(RC4AuxInfo);
RC4AuxInfo.dwBitLen = dwEncryptBitLen;
if (fNoSalt)
RC4AuxInfo.dwBitLen |= CMSG_RC4_NO_SALT_FLAG;
pPara->pvEncryptionAuxInfo = &RC4AuxInfo;
}
} else if (fEncryptIV) {
BYTE rgbIV[IV_LENGTH];
CRYPT_DATA_BLOB Data;
Data.pbData = rgbIV;
Data.cbData = sizeof(rgbIV);
if (!GetIV(rgbIV))
goto ErrorReturn;
if (!AllocAndEncodeObject(
X509_OCTET_STRING,
&Data,
&pAlgPara->pbData,
&pAlgPara->cbData))
goto ErrorReturn;
}
#ifdef CMS_PKCS7
else if (fSP3Encrypt) {
RC2AuxInfo.cbSize = sizeof(RC2AuxInfo);
RC2AuxInfo.dwBitLen = CMSG_SP3_COMPATIBLE_ENCRYPT_FLAG;
pPara->pvEncryptionAuxInfo = &RC2AuxInfo;
}
#endif
*pcRecipientCert = 0;
*pppRecipientCert = (PCCERT_CONTEXT*) TestAlloc(
sizeof(PCCERT_CONTEXT) * MAX_RECIPIENT_CERT);
if (*pppRecipientCert == NULL) goto ErrorReturn;
#ifdef CMS_PKCS7
if (fNoRecipients)
;
else if (fAllRecipients) {
pCert = NULL;
while (pCert = CertEnumCertificatesInStore(hCertStore, pCert)) {
if (*pcRecipientCert == MAX_RECIPIENT_CERT) {
PrintError("cRecipientCert == MAX_RECIPIENT_CERT");
CertFreeCertificateContext(pCert);
break;
}
(*pppRecipientCert)[*pcRecipientCert] =
CertDuplicateCertificateContext(pCert);
*pcRecipientCert += 1;
}
} else
#endif // CMS_PKCS7
if (0 != dwPubKeyBitLen && !IsDSSProv(dwCryptProvType)) {
// Get exchange cert of the specified key length
pCert = FindCertWithKey(AT_KEYEXCHANGE);
if (pCert == NULL) {
printf(
"Failed => couldn't find an exchange cert with key length (%d)\n",
dwPubKeyBitLen);
goto ErrorReturn;
} else {
(*pppRecipientCert)[*pcRecipientCert] = pCert;
*pcRecipientCert += 1;
}
} else {
// Find certificates in the store with xchg key usage
pCert = NULL;
while (TRUE) {
pCert = CertEnumCertificatesInStore(
hCertStore,
pCert);
if (pCert == NULL)
break;
CertGetIntendedKeyUsage(
dwCertEncodingType,
pCert->pCertInfo,
&bIntendedKeyUsage,
1 // cbKeyUsage
);
if (bIntendedKeyUsage &
(CERT_KEY_ENCIPHERMENT_KEY_USAGE |
CERT_DATA_ENCIPHERMENT_KEY_USAGE |
CERT_KEY_AGREEMENT_KEY_USAGE)) {
if (*pcRecipientCert == MAX_RECIPIENT_CERT) {
PrintError("cRecipientCert == MAX_RECIPIENT_CERT");
CertFreeCertificateContext(pCert);
break;
}
(*pppRecipientCert)[*pcRecipientCert] =
CertDuplicateCertificateContext(pCert);
*pcRecipientCert += 1;
}
}
}
#ifdef CMS_PKCS7
if (fNoRecipients)
;
else
#endif // CMS_PKCS7
if (*pcRecipientCert == 0) {
PrintError("Couldn't find a recipient xchg cert");
goto ErrorReturn;
} else {
DWORD i;
if (fVerbose)
printf("Recipient Certs: %d\n", *pcRecipientCert);
for (i = 0; i < *pcRecipientCert; i++) {
if (fVerbose) {
printf("----- Recipient Cert[%i] -----\n", i);
DisplayCert((*pppRecipientCert)[i]);
}
if (!fDhRecipient) {
PCERT_INFO pCertInfo = (*pppRecipientCert)[i]->pCertInfo;
PCERT_PUBLIC_KEY_INFO pPublicKeyInfo =
&pCertInfo->SubjectPublicKeyInfo;
PCCRYPT_OID_INFO pOIDInfo;
ALG_ID aiPubKey;
if (pOIDInfo = CryptFindOIDInfo(
CRYPT_OID_INFO_OID_KEY,
pPublicKeyInfo->Algorithm.pszObjId,
CRYPT_PUBKEY_ALG_OID_GROUP_ID))
aiPubKey = pOIDInfo->Algid;
else
aiPubKey = 0;
if (aiPubKey == CALG_DH_SF || aiPubKey == CALG_DH_EPHEM) {
printf("Has Diffie Hellman recipients\n");
fDhRecipient = TRUE;
}
}
}
}
fResult = TRUE;
goto CommonReturn;
ErrorReturn:
FreeEncryptPara(pPara, *pcRecipientCert, *pppRecipientCert);
*pcRecipientCert = 0;
*pppRecipientCert = NULL;
fResult = FALSE;
CommonReturn:
return fResult;
}
static void FreeEncryptPara(
IN PCRYPT_ENCRYPT_MESSAGE_PARA pPara,
IN DWORD cRecipientCert,
IN PCCERT_CONTEXT *ppRecipientCert
)
{
TestFree(pPara->ContentEncryptionAlgorithm.Parameters.pbData);
pPara->ContentEncryptionAlgorithm.Parameters.pbData = NULL;
if (ppRecipientCert) {
while (cRecipientCert-- > 0) {
CertFreeCertificateContext(ppRecipientCert[cRecipientCert]);
}
TestFree(ppRecipientCert);
}
}
static BOOL InitDecryptPara(OUT PCRYPT_DECRYPT_MESSAGE_PARA pPara)
{
memset(pPara, 0, sizeof(*pPara));
pPara->cbSize = sizeof(*pPara);
pPara->dwMsgAndCertEncodingType =
dwMsgEncodingType | dwCertEncodingType;
#ifdef ENABLE_SCA_STREAM_TEST
if (fStream)
pPara->dwMsgAndCertEncodingType |= SCA_STREAM_ENABLE_FLAG;
#endif
pPara->rghCertStore = (HCERTSTORE*) TestAlloc(sizeof(HCERTSTORE));
if (fSilentKey)
pPara->dwFlags |= CRYPT_MESSAGE_SILENT_KEYSET_FLAG;
if (pPara->rghCertStore) {
pPara->rghCertStore[0] = hCertStore;
pPara->cCertStore = 1;
return TRUE;
} else
return FALSE;
}
static void FreeDecryptPara(IN PCRYPT_DECRYPT_MESSAGE_PARA pPara)
{
if (pPara->rghCertStore) {
TestFree(pPara->rghCertStore);
pPara->rghCertStore = 0;
}
}
static BOOL InitHashPara(OUT PCRYPT_HASH_MESSAGE_PARA pPara)
{
memset(pPara, 0, sizeof(*pPara));
pPara->cbSize = sizeof(*pPara);
pPara->dwMsgEncodingType = dwMsgEncodingType;
pPara->hCryptProv = 0;
if (NULL == (pPara->HashAlgorithm.pszObjId = (LPSTR) GetOID(
pszHashName, CRYPT_HASH_ALG_OID_GROUP_ID))) {
printf("Failed => unknown hash name (%s)\n", pszHashName);
return FALSE;
}
return TRUE;
}
static void FreeHashPara(IN PCRYPT_HASH_MESSAGE_PARA pPara)
{
}
static BOOL DecodeName(BYTE *pbEncoded, DWORD cbEncoded)
{
BOOL fResult;
PCERT_NAME_INFO pInfo = NULL;
DWORD cbInfo;
DWORD i,j;
PCERT_RDN pRDN;
PCERT_RDN_ATTR pAttr;
cbInfo = 0;
fResult = CryptDecodeObject(
dwCertEncodingType,
X509_NAME,
pbEncoded,
cbEncoded,
0, // dwFlags
NULL, // pInfo
&cbInfo
);
if (!fResult || cbInfo == 0) {
PrintLastError("DecodeName::CryptDecodeObject(cbInfo == 0)");
goto ErrorReturn;
}
pInfo = (PCERT_NAME_INFO) TestAlloc(cbInfo);
if (pInfo == NULL) goto ErrorReturn;
if (!CryptDecodeObject(
dwCertEncodingType,
X509_NAME,
pbEncoded,
cbEncoded,
0, // dwFlags
pInfo,
&cbInfo
)) {
PrintLastError("DecodeName::CryptDecodeObject");
goto ErrorReturn;
}
for (i = 0, pRDN = pInfo->rgRDN; i < pInfo->cRDN; i++, pRDN++) {
for (j = 0, pAttr = pRDN->rgRDNAttr; j < pRDN->cRDNAttr; j++, pAttr++) {
LPSTR pszObjId = pAttr->pszObjId;
if (pszObjId == NULL)
pszObjId = "<NULL OBJID>";
if ((pAttr->dwValueType == CERT_RDN_ENCODED_BLOB) ||
(pAttr->dwValueType == CERT_RDN_OCTET_STRING)) {
printf(" [%d,%d] %s ValueType: %d\n",
i, j, pszObjId, pAttr->dwValueType);
} else
printf(" [%d,%d] %s %s\n",
i, j, pszObjId, pAttr->Value.pbData);
}
}
fResult = TRUE;
goto CommonReturn;
ErrorReturn:
fResult = FALSE;
CommonReturn:
if (pInfo)
TestFree(pInfo);
return fResult;
}
static void DisplayCert(PCCERT_CONTEXT pCert)
{
printf("Subject::\n");
DecodeName(pCert->pCertInfo->Subject.pbData,
pCert->pCertInfo->Subject.cbData);
printf("Issuer::\n");
DecodeName(pCert->pCertInfo->Issuer.pbData,
pCert->pCertInfo->Issuer.cbData);
{
DWORD cb;
BYTE *pb;
printf("SerialNumber::");
for (cb = pCert->pCertInfo->SerialNumber.cbData,
pb = pCert->pCertInfo->SerialNumber.pbData + (cb - 1);
cb > 0; cb--, pb--) {
printf(" %02X", *pb);
}
printf("\n");
}
}
static void PrintCrlEntries(DWORD cEntry, PCRL_ENTRY pEntry)
{
DWORD i;
for (i = 0; i < cEntry; i++, pEntry++) {
DWORD cb;
BYTE *pb;
printf(" [%d] SerialNumber::", i);
for (cb = pEntry->SerialNumber.cbData,
pb = pEntry->SerialNumber.pbData + (cb - 1); cb > 0; cb--, pb++) {
printf(" %02X", *pb);
}
printf("\n");
}
}
static void DisplayCrl(PCCRL_CONTEXT pCrl)
{
printf("Issuer::\n");
DecodeName(pCrl->pCrlInfo->Issuer.pbData,
pCrl->pCrlInfo->Issuer.cbData);
if (pCrl->pCrlInfo->cCRLEntry == 0)
printf("Entries:: NONE\n");
else {
printf("Entries::\n");
PrintCrlEntries(pCrl->pCrlInfo->cCRLEntry,
pCrl->pCrlInfo->rgCRLEntry);
}
}