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.
 
 
 
 
 
 

2706 lines
82 KiB

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1995 - 1996
//
// File: tcert.cpp
//
// Contents: Certificate and CRL Encode/Decode API Tests
//
// See Usage() for list of test options.
//
//
// Functions: main
//
// History: 04-Mar-96 philh created
// 07-Jun-96 HelleS Added printing the command line
// and Failed or Passed at the end.
// 20-Aug-96 jeffspel name changes
//
//--------------------------------------------------------------------------
#include <windows.h>
#include <regstr.h>
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <memory.h>
#include <time.h>
#include <stddef.h>
#include <wincrypt.h>
#include <signcde.h>
//#include <crypt32l.h>
// Note: the SubjectPublicKey is really the PKCS #1 ASN encoding of the
// following information. However, since the SubjectPublicKeyInfo.PublicKey
// is a CRYPT_BIT_BLOB that following is OK for testing purposes.
#ifndef RSA1
#define RSA1 ((DWORD)'R'+((DWORD)'S'<<8)+((DWORD)'A'<<16)+((DWORD)'1'<<24))
#endif
// Build my own CAPI public key
typedef struct _CAPI_PUB_KEY {
PUBLICKEYSTRUC PubKeyStruc;
RSAPUBKEY RsaPubKey;
BYTE rgbModulus[10];
} CAPI_PUB_KEY;
static const CAPI_PUB_KEY SubjectPublicKey = {
{PUBLICKEYBLOB, CUR_BLOB_VERSION, 0, CALG_RSA_SIGN}, // PUBLICKEYSTRUC
{RSA1, 10*8, 4}, // RSAPUBKEY
{0,1,2,3,4,5,6,7,8,9} // rgbModulus
};
static LPSTR pszReadFilename = NULL;
static LPSTR pszPublicKeyFilename = NULL;
static BOOL fWritePublicKeyInfo = FALSE;
static LPSTR pszForwardCertFilename = NULL;
static LPSTR pszReverseCertFilename = NULL;
//+-------------------------------------------------------------------------
// Parameters, data used to encode the messages.
//--------------------------------------------------------------------------
static DWORD dwCertEncodingType = X509_ASN_ENCODING;
static DWORD dwDecodeObjectFlags = 0;
static BOOL fFormatNameStrings = FALSE;
static BOOL fFormatAllNameStrings = FALSE;
static DWORD dwExtLen = 0;
static LPCSTR pszOIDNoSignHash = szOID_OIWSEC_sha1;
//+-------------------------------------------------------------------------
// 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);
}
void PrintNoError(LPCSTR pszMsg)
{
printf("%s failed => expected error\n", pszMsg);
}
//+-------------------------------------------------------------------------
// 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 CRYPT_DECODE_PARA TestDecodePara = {
offsetof(CRYPT_DECODE_PARA, pfnFree) + sizeof(TestDecodePara.pfnFree),
TestAlloc,
TestFree
};
static void *TestDecodeObject(
IN LPCSTR lpszStructType,
IN const BYTE *pbEncoded,
IN DWORD cbEncoded,
OUT OPTIONAL DWORD *pcbStructInfo = NULL
)
{
DWORD cbStructInfo;
void *pvStructInfo;
if (!CryptDecodeObjectEx(
dwCertEncodingType,
lpszStructType,
pbEncoded,
cbEncoded,
dwDecodeObjectFlags | CRYPT_DECODE_ALLOC_FLAG,
&TestDecodePara,
(void *) &pvStructInfo,
&cbStructInfo
))
goto ErrorReturn;
CommonReturn:
if (pcbStructInfo)
*pcbStructInfo = cbStructInfo;
return pvStructInfo;
ErrorReturn:
if ((DWORD_PTR) lpszStructType <= 0xFFFF)
printf("CryptDecodeObject(StructType: %d)",
(DWORD)(DWORD_PTR) lpszStructType);
else
printf("CryptDecodeObject(StructType: %s)",
lpszStructType);
PrintLastError("");
pvStructInfo = NULL;
goto CommonReturn;
}
//+-------------------------------------------------------------------------
// Allocate and read an encoded DER blob from a file
//--------------------------------------------------------------------------
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
//--------------------------------------------------------------------------
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;
}
typedef BOOL (*PFN_ENCODE)(BYTE **ppbEncoded, DWORD *pcbEncoded);
typedef BOOL (*PFN_DECODE)(BYTE *pbEncoded, DWORD cbEncoded);
typedef struct _TEST {
LPCSTR pszName;
PFN_ENCODE pfnEncode;
PFN_DECODE pfnDecode;
} TEST, *PTEST;
static BOOL EncodeCert(BYTE **ppbEncoded, DWORD *pcbEncoded);
static BOOL DecodeCert(BYTE *pbEncoded, DWORD cbEncoded);
static BOOL EncodeCrl(BYTE **ppbEncoded, DWORD *pcbEncoded);
static BOOL DecodeCrl(BYTE *pbEncoded, DWORD cbEncoded);
static BOOL EncodeCertReq(BYTE **ppbEncoded, DWORD *pcbEncoded);
static BOOL DecodeCertReq(BYTE *pbEncoded, DWORD cbEncoded);
static BOOL EncodeKeygenReq(BYTE **ppbEncoded, DWORD *pcbEncoded);
static BOOL DecodeKeygenReq(BYTE *pbEncoded, DWORD cbEncoded);
static BOOL EncodeContentInfo(BYTE **ppbEncoded, DWORD *pcbEncoded);
static BOOL DecodeContentInfo(BYTE *pbEncoded, DWORD cbEncoded);
static BOOL EncodeCertPair(BYTE **ppbEncoded, DWORD *pcbEncoded);
static BOOL DecodeCertPair(BYTE *pbEncoded, DWORD cbEncoded);
TEST Tests[] = {
"cert", EncodeCert, DecodeCert,
"crl", EncodeCrl, DecodeCrl,
"certReq", EncodeCertReq, DecodeCertReq,
"keygenReq", EncodeKeygenReq, DecodeKeygenReq,
"ContentInfo", EncodeContentInfo, DecodeContentInfo,
"CertPair", EncodeCertPair, DecodeCertPair
};
#define NTESTS (sizeof(Tests)/sizeof(Tests[0]))
static void Usage(void)
{
int i;
printf("Usage: tcert [options] [<ContentType>]\n");
printf("Options are:\n");
printf(" -h - This message\n");
printf(" -r<filename> - Read encoded content from file\n");
printf(" -w<filename> - Write encoded content to file\n");
printf(" -p<filename> - Write public key to file\n");
printf(" -P<filename> - Write Name, PublicKeyInfo to file\n");
printf(" -f - Enable name string formatting\n");
printf(" -fAll - Name string formatting (All types)\n");
printf(" -N - Enable NOCOPY decode\n");
printf(" -o<OID> - NoSignHash OID (SHA1 is default)\n");
printf(" -X<number> - eXtension byte length\n");
printf(" -F<CertFilename> - CertPair Forward certificate\n");
printf(" -R<CertFilename> - CertPair Reverse certificate\n");
printf("\n");
printf("ContentTypes (case insensitive):\n");
for (i = 0; i < NTESTS; i++)
printf(" %s\n", Tests[i].pszName);
printf("\n");
printf("Default: %s\n", Tests[0].pszName);
}
int _cdecl main(int argc, char * argv[])
{
int ReturnStatus;
BOOL fResult;
LPCSTR pszName = Tests[0].pszName;
LPSTR pszWriteFilename = NULL;
int c;
PTEST pTest;
BYTE *pbEncoded = NULL;
DWORD cbEncoded;
/*
if (!Crypt32DllMain( NULL, DLL_PROCESS_ATTACH, NULL)) {
printf("Crypt32DllMain attach failed, aborting\n");
ReturnStatus = -1;
goto CommonReturn;
}
*/
while (--argc>0)
{
if (**++argv == '-')
{
switch(argv[0][1])
{
case 'r':
pszReadFilename = argv[0]+2;
if (*pszReadFilename == '\0') {
printf("Need to specify filename\n");
goto BadUsage;
}
break;
case 'w':
pszWriteFilename = argv[0]+2;
if (*pszWriteFilename == '\0') {
printf("Need to specify filename\n");
goto BadUsage;
}
break;
case 'P':
fWritePublicKeyInfo = TRUE;
case 'p':
pszPublicKeyFilename = argv[0]+2;
if (*pszPublicKeyFilename == '\0') {
printf("Need to specify filename\n");
goto BadUsage;
}
break;
case 'F':
pszForwardCertFilename = argv[0]+2;
if (*pszForwardCertFilename == '\0') {
printf("Need to specify Forward filename\n");
goto BadUsage;
}
break;
case 'R':
pszReverseCertFilename = argv[0]+2;
if (*pszReverseCertFilename == '\0') {
printf("Need to specify Reverse filename\n");
goto BadUsage;
}
break;
case 'N':
dwDecodeObjectFlags |= CRYPT_DECODE_NOCOPY_FLAG;
break;
case 'X':
dwExtLen = (DWORD) strtoul(argv[0]+2, NULL, 0);
break;
case 'f':
if (argv[0][2]) {
if (0 != _stricmp(argv[0]+2, "ALL")) {
printf("Need to specify -fALL\n");
goto BadUsage;
}
fFormatAllNameStrings = TRUE;
} else
fFormatNameStrings = TRUE;
break;
case 'o':
pszOIDNoSignHash = (LPCSTR) argv[0]+2;
break;
case 'h':
default:
goto BadUsage;
}
} else
pszName = argv[0];
}
for (c = NTESTS, pTest = Tests; c > 0; c--, pTest++) {
if (_stricmp(pszName, pTest->pszName) == 0)
break;
}
if (c == 0) {
printf("Bad ContentType: %s\n", pszName);
goto BadUsage;
}
printf("command line: %s\n", GetCommandLine());
if (pszReadFilename) printf("Reading from: %s ", pszReadFilename);
if (pszWriteFilename) printf("Writing to: %s ", pszWriteFilename);
if (pszPublicKeyFilename) {
if (fWritePublicKeyInfo)
printf("PublicKeyInfo to: %s ", pszPublicKeyFilename);
else
printf("Public Key to: %s ", pszPublicKeyFilename);
}
if (pszForwardCertFilename)
printf("ForwardCert: %s ", pszForwardCertFilename);
if (pszReverseCertFilename)
printf("ReverseCert: %s ", pszReverseCertFilename);
printf("\n");
if (pszReadFilename)
fResult = ReadDERFromFile(pszReadFilename, &pbEncoded, &cbEncoded);
else
fResult = pTest->pfnEncode(&pbEncoded, &cbEncoded);
if (fResult) {
if (pszWriteFilename)
WriteDERToFile(pszWriteFilename, pbEncoded, cbEncoded);
pTest->pfnDecode(pbEncoded, cbEncoded);
TestFree(pbEncoded);
}
ReturnStatus = 0;
goto CommonReturn;
BadUsage:
Usage();
ReturnStatus = -1;
CommonReturn:
if (!ReturnStatus)
printf("Passed\n");
else
printf("Failed\n");
/*
if (!Crypt32DllMain( NULL, DLL_PROCESS_DETACH, NULL)) {
printf("Crypt32DllMain detach failed, aborting\n");
ReturnStatus = -1;
}
*/
return ReturnStatus;
}
static BOOL EncodeSignedContent(
BYTE *pbToBeSigned,
DWORD cbToBeSigned,
BYTE **ppbEncoded,
DWORD *pcbEncoded)
{
BOOL fResult;
BYTE *pbEncoded = NULL;
DWORD cbEncoded;
BYTE *pbSignature = NULL;
DWORD cbSignature;
CERT_SIGNED_CONTENT_INFO CertEncoding;
CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm = {
(LPSTR) pszOIDNoSignHash, 0, 0
};
CRYPT_DATA_BLOB EncodedBlob;
cbSignature = 0;
if (!CryptSignCertificate(
NULL, // hCryptProv
0, // dwKeySpec
dwCertEncodingType,
pbToBeSigned,
cbToBeSigned,
&SignatureAlgorithm,
NULL, // pvHashAuxInfo
NULL, // pbSignature
&cbSignature
)) {
PrintLastError("EncodeSignedContent::CryptSignCertificate(cbEncoded == 0)");
goto ErrorReturn;
}
pbSignature = (BYTE *) TestAlloc(cbSignature);
if (pbSignature == NULL) goto ErrorReturn;
if (!CryptSignCertificate(
NULL, // hCryptProv
0, // dwKeySpec
dwCertEncodingType,
pbToBeSigned,
cbToBeSigned,
&SignatureAlgorithm,
NULL, // pvHashAuxInfo
pbSignature,
&cbSignature
)) {
PrintLastError("EncodeSignedContent::CryptSignCertificate");
goto ErrorReturn;
}
ZeroMemory(&CertEncoding, sizeof(CertEncoding));
CertEncoding.ToBeSigned.pbData = pbToBeSigned;
CertEncoding.ToBeSigned.cbData = cbToBeSigned;
CertEncoding.SignatureAlgorithm = SignatureAlgorithm;
CertEncoding.Signature.pbData = pbSignature;
CertEncoding.Signature.cbData = cbSignature;
cbEncoded = 0;
CryptEncodeObject(
dwCertEncodingType,
X509_CERT,
&CertEncoding,
NULL, // pbEncoded
&cbEncoded
);
if (cbEncoded == 0) {
PrintLastError("EncodeSignedContent::CryptEncodeObject(cbEncoded == 0)");
goto ErrorReturn;
}
pbEncoded = (BYTE *) TestAlloc(cbEncoded);
if (pbEncoded == NULL) goto ErrorReturn;
if (!CryptEncodeObject(
dwCertEncodingType,
X509_CERT,
&CertEncoding,
pbEncoded,
&cbEncoded
)) {
PrintLastError("EncodeSignedContent::CryptEncodeObject");
goto ErrorReturn;
}
EncodedBlob.cbData = cbEncoded;
EncodedBlob.pbData = pbEncoded;
if (!CryptVerifyCertificateSignatureEx(
NULL, // hCryptProv
dwCertEncodingType,
CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB,
(void *) &EncodedBlob,
CRYPT_VERIFY_CERT_SIGN_ISSUER_NULL,
NULL, // pvIssuer
0, // dwFlags
NULL // pvReserved
)) {
PrintLastError("EncodeSignedContent::CryptVerifyCertificateSignatureEx");
}
fResult = TRUE;
goto CommonReturn;
ErrorReturn:
if (pbEncoded) {
TestFree(pbEncoded);
pbEncoded = NULL;
}
cbEncoded = 0;
fResult = FALSE;
CommonReturn:
if (pbSignature)
TestFree(pbSignature);
*ppbEncoded = pbEncoded;
*pcbEncoded = cbEncoded;
return fResult;
}
static void PrintBadUnicodeEncode(LPCSTR pszMsg, DWORD dwExpectedErr,
DWORD cbEncoded)
{
DWORD dwErr = GetLastError();
if (dwErr != dwExpectedErr)
printf("%s failed => expected : 0x%x (%d), LastError: 0x%x (%d)\n",
pszMsg, dwExpectedErr, dwExpectedErr, dwErr, dwErr);
printf("%s bad unicode encode => LastError: 0x%x (%d) ",
pszMsg, dwErr, dwErr);
printf("cbEncoded: 0x%x RDN: %d Attr: %d Value: %d\n",
cbEncoded,
GET_CERT_UNICODE_RDN_ERR_INDEX(cbEncoded),
GET_CERT_UNICODE_ATTR_ERR_INDEX(cbEncoded),
GET_CERT_UNICODE_VALUE_ERR_INDEX(cbEncoded));
}
static void DoBadEncodeIssuer()
{
DWORD cbIssuerEncoded;
CERT_RDN_ATTR rgBadPrintableAttr[] = {
// 0 - rgdwPrintableOrT61ValueType,
szOID_COMMON_NAME, 0, 0,
(BYTE *) L"CN: printable or t61",
// 1 - rgdwPrintableOrT61ValueType,
szOID_LOCALITY_NAME, 0, 0,
(BYTE *) L"L: printable or t61 \"###\"",
// 2 - BAD rgdwPrintableValueType,
szOID_COUNTRY_NAME, 0, 0,
(BYTE *) L"C: printable ### az AZ 09 \'()+,-./:=? "
};
CERT_RDN rgBadPrintableRDN[] = {
1, &rgBadPrintableAttr[0],
3, &rgBadPrintableAttr[0]
};
CERT_NAME_INFO BadPrintableName = {2, rgBadPrintableRDN};
CERT_RDN_ATTR rgBadNumericAttr[] = {
// 0 - rgdwPrintableOrT61ValueType,
szOID_COMMON_NAME, 0, 0,
(BYTE *) L"CN: printable or t61",
// 1 - rgdwPrintableValueType,
szOID_COUNTRY_NAME, 0, 0,
(BYTE *) L"C: printable az AZ 09 \'()+,-./:=? ",
// 2 - rgdwPrintableOrT61ValueType,
szOID_LOCALITY_NAME, 0, 0,
(BYTE *) L"L: printable or t61 \"###\"",
// 3 - BAD rgdwNumericValueType,
szOID_X21_ADDRESS, 0, 0,
(BYTE *) L"0123456789a ",
// 4 - none, use default
szOID_REGISTERED_ADDRESS, 0, 0,
(BYTE *) L"Default"
};
CERT_RDN rgBadNumericRDN[] = {
1, &rgBadNumericAttr[0],
1, &rgBadNumericAttr[1],
1, &rgBadNumericAttr[2],
1, &rgBadNumericAttr[3],
1, &rgBadNumericAttr[4]
};
CERT_NAME_INFO BadNumericName = {5, rgBadNumericRDN};
// This one has non-zero dwValueTypes
CERT_RDN_ATTR rgBadNumericAttr2[] = {
// 0 - rgdwPrintableOrT61ValueType,
szOID_COMMON_NAME, CERT_RDN_PRINTABLE_STRING, 0,
(BYTE *) L"CN: printable or t61",
// 1 - rgdwPrintableValueType,
szOID_COUNTRY_NAME, CERT_RDN_PRINTABLE_STRING, 0,
(BYTE *) L"C: printable az AZ 09 \'()+,-./:=? ",
// 2 - rgdwPrintableOrT61ValueType,
szOID_LOCALITY_NAME, CERT_RDN_T61_STRING, 0,
(BYTE *) L"L: printable or t61 \"###\"",
// 3 - BAD rgdwNumericValueType,
szOID_X21_ADDRESS, CERT_RDN_NUMERIC_STRING, 0,
(BYTE *) L"0123456789a ",
// 4 - none, use default
szOID_REGISTERED_ADDRESS, CERT_RDN_IA5_STRING, 0,
(BYTE *) L"Default"
};
CERT_RDN rgBadNumericRDN2[] = {
1, &rgBadNumericAttr2[0],
1, &rgBadNumericAttr2[1],
1, &rgBadNumericAttr2[2],
4, &rgBadNumericAttr2[1],
1, &rgBadNumericAttr2[4]
};
CERT_NAME_INFO BadNumericName2 = {5, rgBadNumericRDN2};
BYTE rgbBadIA5[] = {0x80, 0x00, 0x00, 0x00};
CERT_RDN_ATTR rgBadIA5Attr[] = {
// 0 - BAD rgdwIA5ValueType
szOID_RSA_emailAddr, 0, 0,
rgbBadIA5,
};
CERT_RDN rgBadIA5RDN[] = {
1, &rgBadIA5Attr[0]
};
CERT_NAME_INFO BadIA5Name = {1, rgBadIA5RDN};
cbIssuerEncoded = 0;
if (CryptEncodeObject(
dwCertEncodingType,
X509_UNICODE_NAME,
&BadPrintableName,
NULL, // pbEncoded
&cbIssuerEncoded
))
PrintNoError("X509_UNICODE_NAME:: BadPrintableName");
else
PrintBadUnicodeEncode("PrintableString",
(DWORD) CRYPT_E_INVALID_PRINTABLE_STRING, cbIssuerEncoded);
cbIssuerEncoded = 0;
rgBadPrintableAttr[2].dwValueType = CERT_RDN_PRINTABLE_STRING;
if (CryptEncodeObject(
dwCertEncodingType,
X509_UNICODE_NAME,
&BadPrintableName,
NULL, // pbEncoded
&cbIssuerEncoded
))
PrintNoError("X509_UNICODE_NAME:: BadPrintableName(set dwValueType)");
else
PrintBadUnicodeEncode("PrintableString(set dwValueType)",
(DWORD) CRYPT_E_INVALID_PRINTABLE_STRING, cbIssuerEncoded);
cbIssuerEncoded = 0;
if (!CryptEncodeObjectEx(
dwCertEncodingType,
X509_UNICODE_NAME,
&BadPrintableName,
CRYPT_UNICODE_NAME_ENCODE_DISABLE_CHECK_TYPE_FLAG,
NULL, // pEncodePara
NULL, // pbEncoded
&cbIssuerEncoded
) || 0 == cbIssuerEncoded)
PrintLastError("X509_UNICODE_NAME:: DISABLE_CHECK dwFlags");
rgBadPrintableAttr[2].dwValueType =
CERT_RDN_DISABLE_CHECK_TYPE_FLAG | CERT_RDN_PRINTABLE_STRING;
cbIssuerEncoded = 0;
if (!CryptEncodeObjectEx(
dwCertEncodingType,
X509_UNICODE_NAME,
&BadPrintableName,
0,
NULL, // pEncodePara
NULL, // pbEncoded
&cbIssuerEncoded
) || 0 == cbIssuerEncoded)
PrintLastError("X509_UNICODE_NAME:: DISABLE_CHECK dwValueType");
cbIssuerEncoded = 0;
if (!CryptEncodeObjectEx(
dwCertEncodingType,
X509_UNICODE_NAME,
&BadPrintableName,
CRYPT_UNICODE_NAME_ENCODE_ENABLE_T61_UNICODE_FLAG,
NULL, // pEncodePara
NULL, // pbEncoded
&cbIssuerEncoded
) || 0 == cbIssuerEncoded)
PrintLastError("X509_UNICODE_NAME:: ENABLE_T61 dwFlags");
rgBadPrintableAttr[1].dwValueType =
CERT_RDN_ENABLE_T61_UNICODE_FLAG;
cbIssuerEncoded = 0;
if (!CryptEncodeObjectEx(
dwCertEncodingType,
X509_UNICODE_NAME,
&BadPrintableName,
0,
NULL, // pEncodePara
NULL, // pbEncoded
&cbIssuerEncoded
) || 0 == cbIssuerEncoded)
PrintLastError("X509_UNICODE_NAME:: ENABLE_T61 dwValueType");
cbIssuerEncoded = 0;
if (!CryptEncodeObjectEx(
dwCertEncodingType,
X509_UNICODE_NAME,
&BadPrintableName,
CRYPT_UNICODE_NAME_ENCODE_ENABLE_UTF8_UNICODE_FLAG,
NULL, // pEncodePara
NULL, // pbEncoded
&cbIssuerEncoded
) || 0 == cbIssuerEncoded)
PrintLastError("X509_UNICODE_NAME:: ENABLE_UTF8 dwFlags");
cbIssuerEncoded = 0;
if (CryptEncodeObject(
dwCertEncodingType,
X509_UNICODE_NAME,
&BadNumericName,
NULL, // pbEncoded
&cbIssuerEncoded
))
PrintNoError("X509_UNICODE_NAME:: BadNumericName");
else
PrintBadUnicodeEncode("NumericString",
(DWORD) CRYPT_E_INVALID_NUMERIC_STRING, cbIssuerEncoded);
cbIssuerEncoded = 0;
if (CryptEncodeObject(
dwCertEncodingType,
X509_UNICODE_NAME,
&BadNumericName2,
NULL, // pbEncoded
&cbIssuerEncoded
))
PrintNoError("X509_UNICODE_NAME:: BadNumericName2");
else
PrintBadUnicodeEncode("NumericString2",
(DWORD) CRYPT_E_INVALID_NUMERIC_STRING, cbIssuerEncoded);
cbIssuerEncoded = 0;
if (CryptEncodeObject(
dwCertEncodingType,
X509_UNICODE_NAME,
&BadIA5Name,
NULL, // pbEncoded
&cbIssuerEncoded
))
PrintNoError("X509_UNICODE_NAME:: BadIA5Name");
else
PrintBadUnicodeEncode("IA5String",
(DWORD) CRYPT_E_INVALID_IA5_STRING, cbIssuerEncoded);
}
static BYTE *EncodeIssuer(DWORD *pcbIssuerEncoded)
{
BYTE *pbIssuerEncoded = NULL;
DWORD cbIssuerEncoded;
BYTE rgbOctet[] = {1, 0xFF, 0x7F};
BYTE rgbEncodedBlob[] = {0x05, 00};
CERT_RDN_ATTR rgAttr[] = {
// 0 - rgdwPrintableOrT61ValueType
szOID_COMMON_NAME, 0, 0,
(BYTE *) L"CN: printable or t61",
// 1 - rgdwPrintableValueType
szOID_COUNTRY_NAME, 0, 0,
(BYTE *) L"C: printable az AZ 09 \'()+,-./:=? ",
// 2 - rgdwPrintableOrT61ValueType
szOID_LOCALITY_NAME, 0, 0,
(BYTE *) L"L: printable or t61 \"###\"",
// 3 - rgdwNumericValueType
szOID_X21_ADDRESS, 0, 0,
(BYTE *) L" 0123456789 ",
// 4 - none, use default
szOID_REGISTERED_ADDRESS, 0, 0,
(BYTE *) L"Default",
// 5 - rgdwIA5ValueType
szOID_RSA_emailAddr, 0, 0,
(BYTE *) L"Email, IA5 !@#$%^&*()_+{|}",
// 6 - Unicode
"1.2.2.5", CERT_RDN_BMP_STRING, 0,
(BYTE *) L"Null terminated UNICODE",
// 7 - Unicode
"1.2.2.5.1", CERT_RDN_BMP_STRING, 10 *2,
(BYTE *) L"Length UNICODE",
// 8 - Universal
"1.2.2.5.2", CERT_RDN_UNIVERSAL_STRING, 0,
(BYTE *) L"Universal ~!@#$%^&*()_+{}:\"<>?",
// 9 - Octet
"1.2.2.5.3", CERT_RDN_OCTET_STRING, sizeof(rgbOctet),
rgbOctet,
// 10 - EncodedBlob
"1.2.2.5.4", CERT_RDN_ENCODED_BLOB, sizeof(rgbEncodedBlob),
rgbEncodedBlob,
// 11 - Empty rgdwPrintableOrT61ValueType
szOID_LOCALITY_NAME, 0, 0, NULL,
// 12 - Empty rgdwNumericValueType
szOID_X21_ADDRESS, 0, 0, NULL,
// 13 - DC (IA5)
szOID_DOMAIN_COMPONENT, 0, 0,
(BYTE *) L"microsoft",
// 14 - DC (IA5)
szOID_DOMAIN_COMPONENT, 0, 0,
(BYTE *) L"com",
// 15 - UTF8
"1.2.8.5", CERT_RDN_UTF8_STRING, 0,
(BYTE *) L"Null terminated UTF8",
// 16 - UTF8
"1.2.8.5.1", CERT_RDN_UTF8_STRING, 11 *2,
(BYTE *) L"Length UTF8",
// Note, FFFE and FFFF are excluded from the UTF8 standard
// 17 - UTF8
"1.2.8.5.2", CERT_RDN_UTF8_STRING, 0,
(BYTE *) L"SPECIAL UTF8: "
L"\x0001 \x0002 \x007e \x007f "
L"\x0080 \x0081 \x07fe \x07ff "
L"\x0800 \x0801 \xfffc \xfffd",
// 18 - UNICODE
"1.2.8.5.3", CERT_RDN_UNICODE_STRING, 0,
(BYTE *) L"SPECIAL UNICODE: "
L"\x0001 \x0002 \x007e \x007f "
L"\x0080 \x0081 \x07fe \x07ff "
L"\x0800 \x0801 \xfffe \xffff",
// 19 - DC (UTF8)
szOID_DOMAIN_COMPONENT, 0, 0,
(BYTE *) L"Unicode DC: "
L"\x0001 \x0002 \x007e \x007f "
L"\x0080 \x0081 \x07fe \x07ff "
L"\x0800 \x0801 \xfffe \xffff",
// 20 - Universal
"1.2.2.5.2.1.1.1", CERT_RDN_UNIVERSAL_STRING, 0,
(BYTE *) L"SPECIAL UNIVERSAL with Surrogate Pairs: "
L"\xd800\xdc00\xdbff\xdfff"
L"\xdbfe\xdc03\xd801\xdfcf"
L"\xd801\x0081\xdc01\xdc02"
L"\xd805\xd806\xd807\xdc04"
L"\xd802\xd803\xfffe\xd804",
};
CERT_RDN rgRDN[] = {
1, &rgAttr[0],
1, &rgAttr[1],
1, &rgAttr[2],
1, &rgAttr[3],
1, &rgAttr[4],
1, &rgAttr[5],
3, &rgAttr[5],
13, &rgAttr[8]
};
CERT_NAME_INFO Name = {8, rgRDN};
DoBadEncodeIssuer();
cbIssuerEncoded = 0;
CryptEncodeObject(
dwCertEncodingType,
X509_UNICODE_NAME,
&Name,
NULL, // pbEncoded
&cbIssuerEncoded
);
if (cbIssuerEncoded == 0) {
PrintLastError("EncodeIssuer::CryptEncodeObject(cbEncoded == 0)");
goto ErrorReturn;
}
pbIssuerEncoded = (BYTE *) TestAlloc(cbIssuerEncoded);
if (pbIssuerEncoded == NULL) goto ErrorReturn;
if (!CryptEncodeObject(
dwCertEncodingType,
X509_UNICODE_NAME,
&Name,
pbIssuerEncoded,
&cbIssuerEncoded
)) {
PrintLastError("EncodeIssuer::CryptEncodeObject");
goto ErrorReturn;
}
goto CommonReturn;
ErrorReturn:
if (pbIssuerEncoded)
TestFree(pbIssuerEncoded);
pbIssuerEncoded = NULL;
cbIssuerEncoded = 0;
CommonReturn:
*pcbIssuerEncoded = cbIssuerEncoded;
return pbIssuerEncoded;
}
static BOOL EncodeCert(BYTE **ppbEncoded, DWORD *pcbEncoded)
{
BOOL fResult;
BYTE *pbIssuerEncoded = NULL;
DWORD cbIssuerEncoded;
BYTE *pbNameEncoded = NULL;
DWORD cbNameEncoded;
BYTE *pbCertEncoded = NULL;
DWORD cbCertEncoded;
DWORD SerialNumber[2] = {0x12345678, 0x33445566};
SYSTEMTIME SystemTime;
#define ISSUER_UNIQUE_ID "IssuerUniqueId"
#define ATTR_0_0 "attr 0_0 printable"
#define ATTR_0_1 "attr 0_1 IA5"
#define ATTR_1_0 "attr 1_0 numeric"
#define ATTR_1_1 "attr 1_1 octet"
#define ATTR_2_0 "attr 2_0 teletex"
#define ATTR_2_1 "attr 2_1 videotex"
#define ATTR_2_2 "attr 2_2 graphic"
#define ATTR_2_3 "attr 2_3 visible"
#define ATTR_2_4 "attr 2_4 general"
#define ATTR_2_5 L"attr 2_5 BMP:: Unicode"
#define ATTR_2_6 L"attr 2_6 UTF8:: Unicode"
ULONG Universal[] = {0x12345678, 0, 0xFFFF1111, 0x87654321,
0x00FFFF,
0x010000,
0x010001,
0x10FFFE,
0x10FFFF,
0x110000,
0x10F803,
0x0107CF,
0x011C04,
};
BYTE NullDer[] = {0x05, 0x00};
BYTE IntegerDer[] = {0x02, 0x01, 0x35};
CERT_RDN_ATTR rgAttr0[] = {
"1.2.0.0", CERT_RDN_PRINTABLE_STRING,
strlen(ATTR_0_0), (BYTE *) ATTR_0_0,
"1.2.0.1", CERT_RDN_IA5_STRING,
strlen(ATTR_0_1), (BYTE *) ATTR_0_1
};
CERT_RDN_ATTR rgAttr1[] = {
"1.2.1.0", CERT_RDN_NUMERIC_STRING,
strlen(ATTR_1_0), (BYTE *) ATTR_1_0,
"1.2.1.1", CERT_RDN_OCTET_STRING,
strlen(ATTR_1_1), (BYTE *) ATTR_1_1,
"1.2.1.2", CERT_RDN_PRINTABLE_STRING,
0, NULL,
"1.2.1.3", CERT_RDN_ENCODED_BLOB,
sizeof(NullDer), NullDer,
"1.2.1.4", CERT_RDN_ENCODED_BLOB,
sizeof(IntegerDer), IntegerDer
};
CERT_RDN_ATTR rgAttr2[] = {
"1.2.2.0", CERT_RDN_TELETEX_STRING,
strlen(ATTR_2_0), (BYTE *) ATTR_2_0,
"1.2.2.1", CERT_RDN_VIDEOTEX_STRING,
strlen(ATTR_2_1), (BYTE *) ATTR_2_1,
"1.2.2.2", CERT_RDN_GRAPHIC_STRING,
strlen(ATTR_2_2), (BYTE *) ATTR_2_2,
"1.2.2.3", CERT_RDN_VISIBLE_STRING,
strlen(ATTR_2_3), (BYTE *) ATTR_2_3,
"1.2.2.4", CERT_RDN_GENERAL_STRING,
strlen(ATTR_2_4), (BYTE *) ATTR_2_4,
"1.2.2.5", CERT_RDN_BMP_STRING,
wcslen(ATTR_2_5) * 2, (BYTE *) ATTR_2_5,
"1.2.2.6", CERT_RDN_UTF8_STRING,
wcslen(ATTR_2_6) * 2, (BYTE *) ATTR_2_6,
"1.2.2.7", CERT_RDN_UNIVERSAL_STRING,
sizeof(Universal), (BYTE *) Universal
};
CERT_RDN_ATTR rgAttr3[] = {
"1.2.2.2", CERT_RDN_OCTET_STRING,
0, NULL,
"1.2.2.3", CERT_RDN_NUMERIC_STRING,
0, NULL,
"1.2.2.4", CERT_RDN_PRINTABLE_STRING,
0, NULL,
"1.2.2.5", CERT_RDN_TELETEX_STRING,
0, NULL,
"1.2.2.6", CERT_RDN_VIDEOTEX_STRING,
0, NULL,
"1.2.2.7", CERT_RDN_IA5_STRING,
0, NULL,
"1.2.2.8", CERT_RDN_GRAPHIC_STRING,
0, NULL,
"1.2.2.9", CERT_RDN_VISIBLE_STRING,
0, NULL,
"1.2.2.10", CERT_RDN_GENERAL_STRING,
0, NULL,
"1.2.2.11", CERT_RDN_UNIVERSAL_STRING,
0, NULL,
"1.2.2.12", CERT_RDN_BMP_STRING,
0, NULL,
"1.2.2.13", CERT_RDN_UTF8_STRING,
0, NULL
};
CERT_RDN rgRDN[] = {
2, rgAttr0,
5, rgAttr1,
8, rgAttr2,
12, rgAttr3
};
CERT_NAME_INFO Name = {4, rgRDN};
#define EXT_0 "extension 0 ."
#define EXT_1 "extension 1 .."
#define EXT_2 "extension 2 ..."
#define EXT_3 "extension 3 ...."
CERT_EXTENSION rgExt[] = {
"1.14.0", TRUE, strlen(EXT_0), (BYTE *) EXT_0,
"1.14.1.35.45", FALSE, strlen(EXT_1), (BYTE *) EXT_1,
"1.14.2", TRUE, strlen(EXT_2), (BYTE *) EXT_2,
"1.14.4", FALSE, strlen(EXT_3), (BYTE *) EXT_3
};
CERT_INFO Cert;
BYTE *pbExt = NULL;
if (dwExtLen) {
DWORD i;
if (NULL == (pbExt = (BYTE *) TestAlloc(dwExtLen)))
goto ErrorReturn;
for (i = 0; i < dwExtLen; i++)
pbExt[i] = (BYTE) i;
rgExt[3].Value.cbData = dwExtLen;
rgExt[3].Value.pbData = pbExt;
}
cbNameEncoded = 0;
CryptEncodeObject(
dwCertEncodingType,
X509_NAME,
&Name,
NULL, // pbEncoded
&cbNameEncoded
);
if (cbNameEncoded == 0) {
PrintLastError("EncodeCert::CryptEncodeObject(cbEncoded == 0)");
goto ErrorReturn;
}
pbNameEncoded = (BYTE *) TestAlloc(cbNameEncoded);
if (pbNameEncoded == NULL) goto ErrorReturn;
if (!CryptEncodeObject(
dwCertEncodingType,
X509_NAME,
&Name,
pbNameEncoded,
&cbNameEncoded
)) {
PrintLastError("EncodeCert::CryptEncodeObject");
goto ErrorReturn;
}
pbIssuerEncoded = EncodeIssuer(&cbIssuerEncoded);
if (NULL == pbIssuerEncoded)
goto ErrorReturn;
memset(&Cert, 0, sizeof(Cert));
Cert.dwVersion = CERT_V3;
Cert.SerialNumber.pbData = (BYTE *) &SerialNumber;
Cert.SerialNumber.cbData = sizeof(SerialNumber);
Cert.SignatureAlgorithm.pszObjId = "1.2.4.5.898";
Cert.Issuer.pbData = pbIssuerEncoded;
Cert.Issuer.cbData = cbIssuerEncoded;
GetSystemTime(&SystemTime);
SystemTimeToFileTime(&SystemTime, &Cert.NotBefore);
SystemTime.wYear++;
SystemTimeToFileTime(&SystemTime, &Cert.NotAfter);
Cert.Subject.pbData = pbNameEncoded;
Cert.Subject.cbData = cbNameEncoded;
Cert.SubjectPublicKeyInfo.Algorithm.pszObjId = "1.3.4.5.911";
Cert.SubjectPublicKeyInfo.PublicKey.pbData = (BYTE *) &SubjectPublicKey;
Cert.SubjectPublicKeyInfo.PublicKey.cbData = sizeof(SubjectPublicKey);
Cert.IssuerUniqueId.pbData = (BYTE *) ISSUER_UNIQUE_ID;
Cert.IssuerUniqueId.cbData = strlen(ISSUER_UNIQUE_ID);
Cert.IssuerUniqueId.cUnusedBits = 5;
// Cert.SubjectUniqueId = 0
Cert.cExtension = sizeof(rgExt) / sizeof(rgExt[0]);
Cert.rgExtension = rgExt;
cbCertEncoded = 0;
CryptEncodeObject(
dwCertEncodingType,
X509_CERT_TO_BE_SIGNED,
&Cert,
NULL, // pbEncoded
&cbCertEncoded
);
if (cbCertEncoded == 0) {
PrintLastError("EncodeCert::CryptEncodeObject(cbEncoded == 0)");
goto ErrorReturn;
}
pbCertEncoded = (BYTE *) TestAlloc(cbCertEncoded);
if (pbCertEncoded == NULL) goto ErrorReturn;
if (!CryptEncodeObject(
dwCertEncodingType,
X509_CERT_TO_BE_SIGNED,
&Cert,
pbCertEncoded,
&cbCertEncoded
)) {
PrintLastError("EncodeCert::CryptEncodeObject");
goto ErrorReturn;
}
if (!EncodeSignedContent(
pbCertEncoded,
cbCertEncoded,
ppbEncoded,
pcbEncoded))
goto ErrorReturn;
fResult = TRUE;
goto CommonReturn;
ErrorReturn:
*ppbEncoded = NULL;
*pcbEncoded = 0;
fResult = FALSE;
CommonReturn:
if (pbNameEncoded)
TestFree(pbNameEncoded);
if (pbIssuerEncoded)
TestFree(pbIssuerEncoded);
if (pbCertEncoded)
TestFree(pbCertEncoded);
if (pbExt)
TestFree(pbExt);
return fResult;
}
static BOOL EncodeCertReq(BYTE **ppbEncoded, DWORD *pcbEncoded)
{
BOOL fResult;
BYTE *pbNameEncoded = NULL;
DWORD cbNameEncoded;
BYTE *pbCertReqEncoded = NULL;
DWORD cbCertReqEncoded;
BYTE *pbExtEncoded = NULL;
DWORD cbExtEncoded;
#define CERT_REQ_0 "Cert Request subject 0"
#define CERT_REQ_1 "Cert Request subject 1 ...."
#define CERT_REQ_2 "Cert Request subject 2 ......."
CERT_RDN_ATTR rgNameAttr[] = {
"1.2.1.0", CERT_RDN_PRINTABLE_STRING,
strlen(CERT_REQ_0), (BYTE *) CERT_REQ_0,
"1.2.1.1", CERT_RDN_PRINTABLE_STRING,
strlen(CERT_REQ_1), (BYTE *) CERT_REQ_1,
"1.2.1.2", CERT_RDN_PRINTABLE_STRING,
strlen(CERT_REQ_2), (BYTE *) CERT_REQ_2
};
CERT_RDN rgRDN[] = {
1, &rgNameAttr[0],
1, &rgNameAttr[1],
1, &rgNameAttr[2]
};
CERT_NAME_INFO Name = {3, rgRDN};
BYTE NullDer[] = {0x05, 0x00};
BYTE IntegerDer[] = {0x02, 0x01, 0x35};
CRYPT_ATTR_BLOB rgAttrBlob[2] = {
2, (BYTE *) NullDer,
3, (BYTE *) IntegerDer
};
CRYPT_ATTR_BLOB ExtAttrBlob;
CRYPT_ATTRIBUTE rgAttr[] = {
szOID_RSA_certExtensions,
1, &ExtAttrBlob,
"1.2.3.4.5.0",
1, rgAttrBlob,
"1.2.1.1.1.1.1.1",
2, rgAttrBlob
};
#define REQ_EXT_0 "request extension 0 -"
#define REQ_EXT_1 "request extension 1 --"
#define REQ_EXT_2 "request extension 2 ---"
#define REQ_EXT_3 "request extension 3 ----"
CERT_EXTENSION rgExt[4] = {
"2.50.0", FALSE, strlen(REQ_EXT_0), (BYTE *) REQ_EXT_0,
"2.51.1", TRUE, strlen(REQ_EXT_1), (BYTE *) REQ_EXT_1,
"2.52.2", FALSE, strlen(REQ_EXT_2), (BYTE *) REQ_EXT_2,
"2.53.3", FALSE, strlen(REQ_EXT_3), (BYTE *) REQ_EXT_3
};
CERT_EXTENSIONS Extensions = {4, &rgExt[0]};
CERT_REQUEST_INFO CertReq;
cbNameEncoded = 0;
CryptEncodeObject(
dwCertEncodingType,
X509_NAME,
&Name,
NULL, // pbEncoded
&cbNameEncoded
);
if (cbNameEncoded == 0) {
PrintLastError("EncodeCertReq::CryptEncodeObject(cbEncoded == 0)");
goto ErrorReturn;
}
pbNameEncoded = (BYTE *) TestAlloc(cbNameEncoded);
if (pbNameEncoded == NULL) goto ErrorReturn;
if (!CryptEncodeObject(
dwCertEncodingType,
X509_NAME,
&Name,
pbNameEncoded,
&cbNameEncoded
)) {
PrintLastError("EncodeCertReq::CryptEncodeObject");
goto ErrorReturn;
}
cbExtEncoded = 0;
CryptEncodeObject(
dwCertEncodingType,
X509_EXTENSIONS,
&Extensions,
NULL, // pbEncoded
&cbExtEncoded
);
if (cbExtEncoded == 0) {
PrintLastError("EncodeCertReq::CryptEncodeObject(cbEncoded == 0)");
goto ErrorReturn;
}
pbExtEncoded = (BYTE *) TestAlloc(cbExtEncoded);
if (pbExtEncoded == NULL) goto ErrorReturn;
if (!CryptEncodeObject(
dwCertEncodingType,
X509_EXTENSIONS,
&Extensions,
pbExtEncoded,
&cbExtEncoded
)) {
PrintLastError("EncodeCertReq::CryptEncodeObject");
goto ErrorReturn;
}
ExtAttrBlob.pbData = pbExtEncoded;
ExtAttrBlob.cbData = cbExtEncoded;
memset(&CertReq, 0, sizeof(CertReq));
CertReq.dwVersion = 2;
CertReq.Subject.pbData = pbNameEncoded;
CertReq.Subject.cbData = cbNameEncoded;
CertReq.SubjectPublicKeyInfo.Algorithm.pszObjId = "1.3.4.5.911";
CertReq.SubjectPublicKeyInfo.PublicKey.pbData = (BYTE *) &SubjectPublicKey;
CertReq.SubjectPublicKeyInfo.PublicKey.cbData = sizeof(SubjectPublicKey);
CertReq.cAttribute = sizeof(rgAttr) / sizeof(rgAttr[0]);
CertReq.rgAttribute = rgAttr;
cbCertReqEncoded = 0;
CryptEncodeObject(
dwCertEncodingType,
X509_CERT_REQUEST_TO_BE_SIGNED,
&CertReq,
NULL, // pbEncoded
&cbCertReqEncoded
);
if (cbCertReqEncoded == 0) {
PrintLastError("EncodeCertReq::CryptEncodeObject(cbEncoded == 0)");
goto ErrorReturn;
}
pbCertReqEncoded = (BYTE *) TestAlloc(cbCertReqEncoded);
if (pbCertReqEncoded == NULL) goto ErrorReturn;
if (!CryptEncodeObject(
dwCertEncodingType,
X509_CERT_REQUEST_TO_BE_SIGNED,
&CertReq,
pbCertReqEncoded,
&cbCertReqEncoded
)) {
PrintLastError("EncodeCertReq::CryptEncodeObject");
goto ErrorReturn;
}
if (!EncodeSignedContent(
pbCertReqEncoded,
cbCertReqEncoded,
ppbEncoded,
pcbEncoded))
goto ErrorReturn;
fResult = TRUE;
goto CommonReturn;
ErrorReturn:
*ppbEncoded = NULL;
*pcbEncoded = 0;
fResult = FALSE;
CommonReturn:
if (pbExtEncoded)
TestFree(pbExtEncoded);
if (pbNameEncoded)
TestFree(pbNameEncoded);
if (pbCertReqEncoded)
TestFree(pbCertReqEncoded);
return fResult;
}
static BOOL EncodeKeygenReq(BYTE **ppbEncoded, DWORD *pcbEncoded)
{
BOOL fResult;
BYTE *pbKeygenReqEncoded = NULL;
DWORD cbKeygenReqEncoded;
CERT_KEYGEN_REQUEST_INFO KeygenReq;
memset(&KeygenReq, 0, sizeof(KeygenReq));
KeygenReq.dwVersion = CERT_KEYGEN_REQUEST_V1;
KeygenReq.SubjectPublicKeyInfo.Algorithm.pszObjId = "1.3.4.5.911";
KeygenReq.SubjectPublicKeyInfo.PublicKey.pbData = (BYTE *) &SubjectPublicKey;
KeygenReq.SubjectPublicKeyInfo.PublicKey.cbData = sizeof(SubjectPublicKey);
KeygenReq.pwszChallengeString = L"Keygen Challenge String";
cbKeygenReqEncoded = 0;
CryptEncodeObject(
dwCertEncodingType,
X509_KEYGEN_REQUEST_TO_BE_SIGNED,
&KeygenReq,
NULL, // pbEncoded
&cbKeygenReqEncoded
);
if (cbKeygenReqEncoded == 0) {
PrintLastError("EncodeKeygenReq::CryptEncodeObject(cbEncoded == 0)");
goto ErrorReturn;
}
pbKeygenReqEncoded = (BYTE *) TestAlloc(cbKeygenReqEncoded);
if (pbKeygenReqEncoded == NULL) goto ErrorReturn;
if (!CryptEncodeObject(
dwCertEncodingType,
X509_KEYGEN_REQUEST_TO_BE_SIGNED,
&KeygenReq,
pbKeygenReqEncoded,
&cbKeygenReqEncoded
)) {
PrintLastError("EncodeKeygenReq::CryptEncodeObject");
goto ErrorReturn;
}
if (!EncodeSignedContent(
pbKeygenReqEncoded,
cbKeygenReqEncoded,
ppbEncoded,
pcbEncoded))
goto ErrorReturn;
fResult = TRUE;
goto CommonReturn;
ErrorReturn:
*ppbEncoded = NULL;
*pcbEncoded = 0;
fResult = FALSE;
CommonReturn:
if (pbKeygenReqEncoded)
TestFree(pbKeygenReqEncoded);
return fResult;
}
static BOOL EncodeContentInfo(BYTE **ppbEncoded, DWORD *pcbEncoded)
{
BOOL fResult;
BYTE *pbEncoded = NULL;
DWORD cbEncoded;
CRYPT_CONTENT_INFO ContentInfo;
BYTE rgb0[] = {0x4, 0x5, 0x11, 0x22, 0x33, 0x44, 0x55}; // OCTET STRING
CRYPT_DER_BLOB Content = {
sizeof(rgb0), rgb0
};
memset(&ContentInfo, 0, sizeof(ContentInfo));
ContentInfo.pszObjId = "1.2.3.4.5.6.7.8.9.10";
ContentInfo.Content = Content;
cbEncoded = 0;
CryptEncodeObject(
dwCertEncodingType,
PKCS_CONTENT_INFO,
&ContentInfo,
NULL, // pbEncoded
&cbEncoded
);
if (cbEncoded == 0) {
PrintLastError("EncodeContentInfo::CryptEncodeObject(cbEncoded == 0)");
goto ErrorReturn;
}
pbEncoded = (BYTE *) TestAlloc(cbEncoded);
if (pbEncoded == NULL) goto ErrorReturn;
if (!CryptEncodeObject(
dwCertEncodingType,
PKCS_CONTENT_INFO,
&ContentInfo,
pbEncoded,
&cbEncoded
)) {
PrintLastError("EncodeContent::CryptEncodeObject");
goto ErrorReturn;
}
fResult = TRUE;
goto CommonReturn;
ErrorReturn:
if (pbEncoded) {
TestFree(pbEncoded);
pbEncoded = NULL;
}
cbEncoded = 0;
fResult = FALSE;
CommonReturn:
*ppbEncoded = pbEncoded;
*pcbEncoded = cbEncoded;
return fResult;
}
static LPCSTR FileTimeText(FILETIME *pft)
{
static char buf[80];
FILETIME ftLocal;
struct tm ctm;
SYSTEMTIME st;
FileTimeToLocalFileTime(pft, &ftLocal);
if (FileTimeToSystemTime(&ftLocal, &st))
{
ctm.tm_sec = st.wSecond;
ctm.tm_min = st.wMinute;
ctm.tm_hour = st.wHour;
ctm.tm_mday = st.wDay;
ctm.tm_mon = st.wMonth-1;
ctm.tm_year = st.wYear-1900;
ctm.tm_wday = st.wDayOfWeek;
ctm.tm_yday = 0;
ctm.tm_isdst = 0;
strcpy(buf, asctime(&ctm));
buf[strlen(buf)-1] = 0;
}
else
sprintf(buf, "<FILETIME %08lX:%08lX>", pft->dwHighDateTime,
pft->dwLowDateTime);
return buf;
}
#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");
}
}
static BOOL DecodeName(BYTE *pbEncoded, DWORD cbEncoded)
{
BOOL fResult;
PCERT_NAME_INFO pInfo = NULL;
DWORD i,j;
PCERT_RDN pRDN;
PCERT_RDN_ATTR pAttr;
if (NULL == (pInfo = (PCERT_NAME_INFO) TestDecodeObject(
X509_NAME,
pbEncoded,
cbEncoded
))) 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>";
printf(" [%d,%d] %s ValueType: %d\n",
i, j, pszObjId, pAttr->dwValueType);
if (pAttr->Value.cbData)
PrintBytes(" ", pAttr->Value.pbData, pAttr->Value.cbData);
else
printf(" NO Value Bytes\n");
}
}
if (fFormatAllNameStrings) {
CERT_NAME_BLOB Name;
DWORD cwsz;
LPWSTR pwsz;
DWORD csz;
LPSTR psz;
Name.pbData = pbEncoded;
Name.cbData = cbEncoded;
#define DELTA_DECRMENT 7
DWORD dwDelta;
DWORD rgdwStrType[] = {
CERT_SIMPLE_NAME_STR,
CERT_OID_NAME_STR,
CERT_X500_NAME_STR,
CERT_SIMPLE_NAME_STR | CERT_NAME_STR_SEMICOLON_FLAG |
CERT_NAME_STR_NO_PLUS_FLAG | CERT_NAME_STR_NO_QUOTING_FLAG,
CERT_X500_NAME_STR | CERT_NAME_STR_NO_PLUS_FLAG |
CERT_NAME_STR_NO_QUOTING_FLAG,
CERT_X500_NAME_STR | CERT_NAME_STR_CRLF_FLAG,
0
};
DWORD *pdwStrType;
for (pdwStrType = rgdwStrType, dwDelta = DELTA_DECRMENT; *pdwStrType;
pdwStrType++, dwDelta += DELTA_DECRMENT) {
printf("\nCertNameToStrW(dwStrType == 0x%x)\n", *pdwStrType);
cwsz = CertNameToStrW(
dwCertEncodingType,
&Name,
*pdwStrType,
NULL, // pwsz
0); // cwsz
if (pwsz = (LPWSTR) TestAlloc(cwsz * sizeof(WCHAR))) {
CertNameToStrW(
dwCertEncodingType,
&Name,
*pdwStrType,
pwsz,
cwsz);
printf(" %S\n", pwsz);
if (cwsz > dwDelta) {
CertNameToStrW(
dwCertEncodingType,
&Name,
*pdwStrType,
pwsz,
cwsz - dwDelta);
printf("Delta[-%d]\n", dwDelta);
printf(" %S\n", pwsz);
}
TestFree(pwsz);
}
}
for (pdwStrType = rgdwStrType, dwDelta = DELTA_DECRMENT; *pdwStrType;
pdwStrType++, dwDelta += DELTA_DECRMENT) {
printf("\nCertNameToStrA(dwStrType == 0x%x)\n", *pdwStrType);
csz = CertNameToStrA(
dwCertEncodingType,
&Name,
*pdwStrType,
NULL, // psz
0); // csz
if (psz = (LPSTR) TestAlloc(csz)) {
CertNameToStrA(
dwCertEncodingType,
&Name,
*pdwStrType,
psz,
csz);
printf(" %s\n", psz);
if (csz > dwDelta) {
csz = CertNameToStrA(
dwCertEncodingType,
&Name,
*pdwStrType,
psz,
csz - dwDelta);
printf("Delta[-%d]\n", dwDelta);
if (1 >= csz) {
DWORD dwErr = GetLastError();
printf(" No CertNameToStrA string, LastError: 0x%x (%d) \n",
dwErr, dwErr);
} else
printf(" %s\n", psz);
}
TestFree(psz);
}
}
} else if (fFormatNameStrings) {
CERT_NAME_BLOB Name;
DWORD cwsz;
LPWSTR pwsz;
Name.pbData = pbEncoded;
Name.cbData = cbEncoded;
cwsz = CertNameToStrW(
dwCertEncodingType,
&Name,
CERT_X500_NAME_STR,
NULL, // pwsz
0); // cwsz
if (pwsz = (LPWSTR) TestAlloc(cwsz * sizeof(WCHAR))) {
CertNameToStrW(
dwCertEncodingType,
&Name,
CERT_X500_NAME_STR,
pwsz,
cwsz);
printf(" %S\n", pwsz);
TestFree(pwsz);
}
}
fResult = TRUE;
goto CommonReturn;
ErrorReturn:
fResult = FALSE;
CommonReturn:
if (pInfo)
TestFree(pInfo);
return fResult;
}
static void DecodeSignedContent(
BYTE *pbEncoded,
DWORD cbEncoded,
LPCSTR lpszToBeSignedStructType,
DWORD cbToBeSignedStruct
)
{
BOOL fResult;
PCERT_INFO pInfo = NULL;
LPSTR pszObjId;
DWORD cbInfo;
PCERT_SIGNED_CONTENT_INFO pCertEncoding;
if (NULL == (pCertEncoding = (PCERT_SIGNED_CONTENT_INFO) TestDecodeObject(
X509_CERT,
pbEncoded,
cbEncoded
))) goto ErrorReturn;
// Decode the ToBeSigned
cbInfo = 0x12345678;
if (!CryptDecodeObject(
dwCertEncodingType,
lpszToBeSignedStructType,
pCertEncoding->ToBeSigned.pbData,
pCertEncoding->ToBeSigned.cbData,
dwDecodeObjectFlags | CRYPT_DECODE_TO_BE_SIGNED_FLAG,
NULL, // pvInfo
&cbInfo))
PrintLastError("CryptDecodeObject(TO_BE_SIGNED_FLAG)");
else if (cbInfo != cbToBeSignedStruct)
printf("failed => CryptDecodeObject(TO_BE_SIGNED_FLAG) returned cbInfo = %d, not %d\n",
cbInfo, cbToBeSignedStruct);
cbInfo = 0x12345678;
if (!CryptDecodeObject(
dwCertEncodingType,
lpszToBeSignedStructType,
pCertEncoding->ToBeSigned.pbData,
pCertEncoding->ToBeSigned.cbData,
dwDecodeObjectFlags,
NULL, // pvInfo
&cbInfo))
PrintLastError("CryptDecodeObject(ToBeSigned, without flag)");
else if (cbInfo != cbToBeSignedStruct)
printf("failed => CryptDecodeObject(ToBeSigned without flag) returned cbInfo = %d, not %d\n",
cbInfo, cbToBeSignedStruct);
pszObjId = pCertEncoding->SignatureAlgorithm.pszObjId;
if (pszObjId == NULL)
pszObjId = "<NULL OBJID>";
printf("Content SignatureAlgorithm:: %s\n", pszObjId);
if (pCertEncoding->SignatureAlgorithm.Parameters.cbData) {
printf("Content SignatureAlgorithm.Parameters::\n");
PrintBytes(" ", pCertEncoding->SignatureAlgorithm.Parameters.pbData,
pCertEncoding->SignatureAlgorithm.Parameters.cbData);
}
if (pCertEncoding->Signature.cbData) {
printf("Content Signature::\n");
PrintBytes(" ", pCertEncoding->Signature.pbData,
pCertEncoding->Signature.cbData);
} else
printf("Content Signature:: NONE\n");
printf("Content Length:: %d\n", pCertEncoding->ToBeSigned.cbData);
fResult = TRUE;
goto CommonReturn;
ErrorReturn:
fResult = FALSE;
CommonReturn:
if (pCertEncoding)
TestFree(pCertEncoding);
}
static void PrintExtensions(DWORD cExt, PCERT_EXTENSION pExt)
{
DWORD i;
for (i = 0; i < cExt; i++, pExt++) {
LPSTR pszObjId = pExt->pszObjId;
if (pszObjId == NULL)
pszObjId = "<NULL OBJID>";
LPSTR pszCritical = pExt->fCritical ? "TRUE" : "FALSE";
printf(" [%d] %s Critical: %s\n", i, pszObjId, pszCritical);
if (pExt->Value.cbData)
PrintBytes(" ", pExt->Value.pbData, pExt->Value.cbData);
else
printf(" NO Value Bytes\n");
}
}
static void DecodeExtensions(BYTE *pbEncoded, DWORD cbEncoded)
{
PCERT_EXTENSIONS pInfo;
if (NULL == (pInfo = (PCERT_EXTENSIONS) TestDecodeObject(
X509_EXTENSIONS,
pbEncoded,
cbEncoded
))) goto ErrorReturn;
PrintExtensions(pInfo->cExtension, pInfo->rgExtension);
goto CommonReturn;
ErrorReturn:
CommonReturn:
if (pInfo)
TestFree(pInfo);
}
static void PrintAttributes(DWORD cAttr, PCRYPT_ATTRIBUTE pAttr)
{
DWORD i;
DWORD j;
for (i = 0; i < cAttr; i++, pAttr++) {
DWORD cValue = pAttr->cValue;
PCRYPT_ATTR_BLOB pValue = pAttr->rgValue;
LPSTR pszObjId = pAttr->pszObjId;
if (pszObjId == NULL)
pszObjId = "<NULL OBJID>";
if (cValue) {
for (j = 0; j < cValue; j++, pValue++) {
printf(" [%d,%d] %s\n", i, j, pszObjId);
if (pValue->cbData) {
PrintBytes(" ", pValue->pbData, pValue->cbData);
if (strcmp(pszObjId, szOID_RSA_certExtensions) == 0 ||
strcmp(pszObjId, SPC_CERT_EXTENSIONS_OBJID) == 0) {
printf(" Extensions::\n");
DecodeExtensions(pValue->pbData, pValue->cbData);
}
} else
printf(" NO Value Bytes\n");
}
} else
printf(" [%d] %s :: No Values\n", i, pszObjId);
}
}
//+-------------------------------------------------------------------------
// Write the public key to the file
//--------------------------------------------------------------------------
BOOL WritePublicKeyToFile(
LPCSTR pszFileName,
PBYTE pbPub,
DWORD cbPub
)
{
FILE *stream;
DWORD i;
if (NULL == (stream = fopen(pszFileName, "w"))) {
printf("Failed to open %s for writing public key\n", pszFileName);
return FALSE;
}
for (i = 0; i < cbPub; i++) {
fprintf(stream, "0x%02X", pbPub[i]);
if (i != (cbPub - 1))
fprintf(stream, ",");
if ((i + 1) % 16 == 0)
fprintf(stream, "\n");
}
fprintf(stream, "\n");
fclose(stream);
return TRUE;
}
void WriteBytesToFile(
IN FILE *stream,
IN const BYTE *pb,
IN DWORD cb
)
{
DWORD i;
fprintf(stream, "= {\n");
for (i = 0; i < cb; i++) {
if ((i % 8) == 0)
fprintf(stream, " ");
fprintf(stream, "0x%02X", pb[i]);
if (i == (cb - 1))
fprintf(stream, "\n");
else {
fprintf(stream, ",");
if ((i + 1) % 8 == 0)
fprintf(stream, "\n");
else
fprintf(stream, " ");
}
}
fprintf(stream, "};\n\n");
}
//+-------------------------------------------------------------------------
// Write the Name and PublicKeyInfo to the file
//--------------------------------------------------------------------------
BOOL WritePublicKeyInfoToFile(
LPCSTR pszFileName,
PCERT_INFO pCertInfo
)
{
BOOL fResult;
FILE *stream;
LPWSTR pwszName = NULL;
DWORD cchName;
BYTE *pbEncoded = NULL;
DWORD cbEncoded;
if (NULL == (stream = fopen(pszFileName, "w"))) {
printf("Failed to open %s for writing PublicKeyInfo\n", pszFileName);
return FALSE;
}
// Output the Subject X500 name string as a comment
cchName = CertNameToStrW(
X509_ASN_ENCODING,
&pCertInfo->Subject,
CERT_X500_NAME_STR,
NULL, // pwsz
0 // cch
);
if (NULL == (pwszName = (LPWSTR) TestAlloc(cchName * sizeof(WCHAR))))
goto ErrorReturn;
cchName = CertNameToStrW(
X509_ASN_ENCODING,
&pCertInfo->Subject,
CERT_NAME_STR_REVERSE_FLAG |
CERT_X500_NAME_STR,
pwszName,
cchName
);
fprintf(stream, "// Name:: <%S>\n", pwszName);
// Write the encoded Subject Name bytes
WriteBytesToFile(stream, pCertInfo->Subject.pbData,
pCertInfo->Subject.cbData);
fprintf(stream, "// PublicKeyInfo\n");
// Encode and write the PublicKeyInfo bytes
if (!CryptEncodeObject(
X509_ASN_ENCODING,
X509_PUBLIC_KEY_INFO,
&pCertInfo->SubjectPublicKeyInfo,
NULL, // pbEncoded
&cbEncoded
)) {
PrintLastError("CryptEncodeObject(X509_PUBLIC_KEY_INFO)");
goto ErrorReturn;
}
pbEncoded = (BYTE *) TestAlloc(cbEncoded);
if (pbEncoded == NULL) goto ErrorReturn;
if (!CryptEncodeObject(
X509_ASN_ENCODING,
X509_PUBLIC_KEY_INFO,
&pCertInfo->SubjectPublicKeyInfo,
pbEncoded,
&cbEncoded
)) {
PrintLastError("CryptEncodeObject(X509_PUBLIC_KEY_INFO)");
goto ErrorReturn;
}
WriteBytesToFile(stream, pbEncoded, cbEncoded);
fprintf(stream, "\n");
fResult = TRUE;
CommonReturn:
fclose(stream);
TestFree(pwszName);
TestFree(pbEncoded);
return fResult;
ErrorReturn:
fResult = FALSE;
goto CommonReturn;
}
static BOOL DecodeCert(BYTE *pbEncoded, DWORD cbEncoded)
{
BOOL fResult;
PCERT_INFO pInfo = NULL;
DWORD cbInfo;
LPSTR pszObjId;
if (NULL == (pInfo = (PCERT_INFO) TestDecodeObject(
X509_CERT_TO_BE_SIGNED,
pbEncoded,
cbEncoded,
&cbInfo
))) goto ErrorReturn;
printf("Version:: %d\n", pInfo->dwVersion);
{
DWORD cb;
BYTE *pb;
printf("SerialNumber::");
for (cb = pInfo->SerialNumber.cbData,
pb = pInfo->SerialNumber.pbData + (cb - 1);
cb > 0; cb--, pb--) {
printf(" %02X", *pb);
}
printf("\n");
}
pszObjId = pInfo->SignatureAlgorithm.pszObjId;
if (pszObjId == NULL)
pszObjId = "<NULL OBJID>";
printf("SignatureAlgorithm:: %s\n", pszObjId);
if (pInfo->SignatureAlgorithm.Parameters.cbData) {
printf("SignatureAlgorithm.Parameters::\n");
PrintBytes(" ", pInfo->SignatureAlgorithm.Parameters.pbData,
pInfo->SignatureAlgorithm.Parameters.cbData);
}
printf("Issuer::\n");
DecodeName(pInfo->Issuer.pbData, pInfo->Issuer.cbData);
printf("NotBefore:: %s\n", FileTimeText(&pInfo->NotBefore));
printf("NotAfter:: %s\n", FileTimeText(&pInfo->NotAfter));
printf("Subject::\n");
DecodeName(pInfo->Subject.pbData, pInfo->Subject.cbData);
pszObjId = pInfo->SubjectPublicKeyInfo.Algorithm.pszObjId;
if (pszObjId == NULL)
pszObjId = "<NULL OBJID>";
printf("SubjectPublicKeyInfo.Algorithm:: %s\n", pszObjId);
if (pInfo->SubjectPublicKeyInfo.Algorithm.Parameters.cbData) {
printf("SubjectPublicKeyInfo.Algorithm.Parameters::\n");
PrintBytes(" ",
pInfo->SubjectPublicKeyInfo.Algorithm.Parameters.pbData,
pInfo->SubjectPublicKeyInfo.Algorithm.Parameters.cbData);
}
printf("SubjectPublicKeyInfo.PublicKey");
if (pInfo->SubjectPublicKeyInfo.PublicKey.cUnusedBits)
printf(" (UnusedBits: %d)",
pInfo->SubjectPublicKeyInfo.PublicKey.cUnusedBits);
printf("::\n");
if (pInfo->SubjectPublicKeyInfo.PublicKey.cbData) {
PrintBytes(" ", pInfo->SubjectPublicKeyInfo.PublicKey.pbData,
pInfo->SubjectPublicKeyInfo.PublicKey.cbData);
} else
printf(" No public key\n");
if (pszPublicKeyFilename) {
if (fWritePublicKeyInfo)
WritePublicKeyInfoToFile(pszPublicKeyFilename, pInfo);
else
WritePublicKeyToFile(pszPublicKeyFilename,
pInfo->SubjectPublicKeyInfo.PublicKey.pbData,
pInfo->SubjectPublicKeyInfo.PublicKey.cbData
);
}
if (pszReadFilename == NULL) {
// Verify that the public key was properly encoded/decoded
CERT_PUBLIC_KEY_INFO PublicKeyInfo;
memset(&PublicKeyInfo, 0, sizeof(PublicKeyInfo));
PublicKeyInfo.Algorithm.pszObjId = "1.3.4.5.911";
PublicKeyInfo.PublicKey.pbData = (BYTE *) &SubjectPublicKey;
PublicKeyInfo.PublicKey.cbData = sizeof(SubjectPublicKey);
if (!CertComparePublicKeyInfo(
dwCertEncodingType,
&PublicKeyInfo,
&pInfo->SubjectPublicKeyInfo))
PrintLastError("CertComparePublicKeyInfo");
}
if (pInfo->IssuerUniqueId.cbData) {
printf("IssuerUniqueId");
if (pInfo->IssuerUniqueId.cUnusedBits)
printf(" (UnusedBits: %d)", pInfo->IssuerUniqueId.cUnusedBits);
printf("::\n");
PrintBytes(" ", pInfo->IssuerUniqueId.pbData,
pInfo->IssuerUniqueId.cbData);
}
if (pInfo->SubjectUniqueId.cbData) {
printf("SubjectUniqueId");
if (pInfo->SubjectUniqueId.cUnusedBits)
printf(" (UnusedBits: %d)", pInfo->SubjectUniqueId.cUnusedBits);
printf("::\n");
PrintBytes(" ", pInfo->SubjectUniqueId.pbData,
pInfo->SubjectUniqueId.cbData);
}
if (pInfo->cExtension == 0)
printf("Extensions:: NONE\n");
else {
printf("Extensions::\n");
PrintExtensions(pInfo->cExtension, pInfo->rgExtension);
}
DecodeSignedContent(pbEncoded, cbEncoded, X509_CERT_TO_BE_SIGNED,
cbInfo);
fResult = TRUE;
goto CommonReturn;
ErrorReturn:
fResult = FALSE;
CommonReturn:
if (pInfo)
TestFree(pInfo);
return fResult;
}
static BOOL DecodeCertReq(BYTE *pbEncoded, DWORD cbEncoded)
{
BOOL fResult;
PCERT_REQUEST_INFO pInfo = NULL;
DWORD cbInfo;
LPSTR pszObjId;
if (NULL == (pInfo = (PCERT_REQUEST_INFO) TestDecodeObject(
X509_CERT_REQUEST_TO_BE_SIGNED,
pbEncoded,
cbEncoded,
&cbInfo
))) goto ErrorReturn;
printf("Version:: %d\n", pInfo->dwVersion);
printf("Subject::\n");
DecodeName(pInfo->Subject.pbData, pInfo->Subject.cbData);
pszObjId = pInfo->SubjectPublicKeyInfo.Algorithm.pszObjId;
if (pszObjId == NULL)
pszObjId = "<NULL OBJID>";
printf("SubjectPublicKeyInfo.Algorithm:: %s\n", pszObjId);
if (pInfo->SubjectPublicKeyInfo.Algorithm.Parameters.cbData) {
printf("SubjectPublicKeyInfo.Algorithm.Parameters::\n");
PrintBytes(" ",
pInfo->SubjectPublicKeyInfo.Algorithm.Parameters.pbData,
pInfo->SubjectPublicKeyInfo.Algorithm.Parameters.cbData);
}
printf("SubjectPublicKeyInfo.PublicKey");
if (pInfo->SubjectPublicKeyInfo.PublicKey.cUnusedBits)
printf(" (UnusedBits: %d)",
pInfo->SubjectPublicKeyInfo.PublicKey.cUnusedBits);
printf("::\n");
if (pInfo->SubjectPublicKeyInfo.PublicKey.cbData) {
PrintBytes(" ", pInfo->SubjectPublicKeyInfo.PublicKey.pbData,
pInfo->SubjectPublicKeyInfo.PublicKey.cbData);
} else
printf(" No public key\n");
if (pInfo->cAttribute == 0)
printf("Attributes:: NONE\n");
else {
printf("Attributes::\n");
PrintAttributes(pInfo->cAttribute, pInfo->rgAttribute);
}
DecodeSignedContent(pbEncoded, cbEncoded, X509_CERT_REQUEST_TO_BE_SIGNED,
cbInfo);
fResult = TRUE;
goto CommonReturn;
ErrorReturn:
fResult = FALSE;
CommonReturn:
if (pInfo)
TestFree(pInfo);
return fResult;
}
static BOOL DecodeKeygenReq(BYTE *pbEncoded, DWORD cbEncoded)
{
BOOL fResult;
PCERT_KEYGEN_REQUEST_INFO pInfo = NULL;
DWORD cbInfo;
LPSTR pszObjId;
if (NULL == (pInfo = (PCERT_KEYGEN_REQUEST_INFO) TestDecodeObject(
X509_KEYGEN_REQUEST_TO_BE_SIGNED,
pbEncoded,
cbEncoded,
&cbInfo
))) goto ErrorReturn;
printf("Version:: %d\n", pInfo->dwVersion);
pszObjId = pInfo->SubjectPublicKeyInfo.Algorithm.pszObjId;
if (pszObjId == NULL)
pszObjId = "<NULL OBJID>";
printf("SubjectPublicKeyInfo.Algorithm:: %s\n", pszObjId);
if (pInfo->SubjectPublicKeyInfo.Algorithm.Parameters.cbData) {
printf("SubjectPublicKeyInfo.Algorithm.Parameters::\n");
PrintBytes(" ",
pInfo->SubjectPublicKeyInfo.Algorithm.Parameters.pbData,
pInfo->SubjectPublicKeyInfo.Algorithm.Parameters.cbData);
}
printf("SubjectPublicKeyInfo.PublicKey");
if (pInfo->SubjectPublicKeyInfo.PublicKey.cUnusedBits)
printf(" (UnusedBits: %d)",
pInfo->SubjectPublicKeyInfo.PublicKey.cUnusedBits);
printf("::\n");
if (pInfo->SubjectPublicKeyInfo.PublicKey.cbData) {
PrintBytes(" ", pInfo->SubjectPublicKeyInfo.PublicKey.pbData,
pInfo->SubjectPublicKeyInfo.PublicKey.cbData);
} else
printf(" No public key\n");
printf("ChallengeString:: %S\n", pInfo->pwszChallengeString);
DecodeSignedContent(pbEncoded, cbEncoded, X509_KEYGEN_REQUEST_TO_BE_SIGNED,
cbInfo);
fResult = TRUE;
goto CommonReturn;
ErrorReturn:
fResult = FALSE;
CommonReturn:
if (pInfo)
TestFree(pInfo);
return fResult;
}
static BOOL DecodeContentInfo(BYTE *pbEncoded, DWORD cbEncoded)
{
BOOL fResult;
PCRYPT_CONTENT_INFO pInfo = NULL;
LPSTR pszObjId;
if (NULL == (pInfo = (PCRYPT_CONTENT_INFO) TestDecodeObject(
PKCS_CONTENT_INFO,
pbEncoded,
cbEncoded
))) goto ErrorReturn;
pszObjId = pInfo->pszObjId;
if (pszObjId == NULL)
pszObjId = "<NULL OBJID>";
printf("ContentType:: %s\n", pszObjId);
if (pInfo->Content.cbData) {
printf("Content::\n");
PrintBytes(" ", pInfo->Content.pbData, pInfo->Content.cbData);
} else
printf("NO Content\n");
fResult = TRUE;
goto CommonReturn;
ErrorReturn:
fResult = FALSE;
CommonReturn:
if (pInfo)
TestFree(pInfo);
return fResult;
}
static void TestCompareIntegerBlob()
{
BYTE bZero = 0;
BYTE bFF = 0xFF;
BYTE rgbLeadZero1[] = {0x12, 0x34, 0x56, 0x87, 0, 0};
BYTE rgbLeadZero2[] = {0x12, 0x34, 0x56, 0x87, 0, 0, 0, 0};
BYTE rgbLeadFF1[] = {0x12, 0x34, 0x56, 0x87, 0xFF, 0xFF};
BYTE rgbLeadFF2[] = {0x12, 0x34, 0x56, 0x87};
CRYPT_INTEGER_BLOB Int1;
CRYPT_INTEGER_BLOB Int2;
Int1.pbData = &bZero;
Int1.cbData = sizeof(bZero);
Int2 = Int1;
if (!CertCompareIntegerBlob(&Int1, &Int2))
printf("Failed => Compare of Zero == Zero\n");
Int1.pbData = &bFF;
Int1.cbData = sizeof(bFF);
Int2 = Int1;
if (!CertCompareIntegerBlob(&Int1, &Int2))
printf("Failed => Compare of FF == FF\n");
Int1.pbData = &bZero;
Int1.cbData = sizeof(bZero);
if (CertCompareIntegerBlob(&Int1, &Int2))
printf("Failed => Compare of Zero != FF\n");
Int1.pbData = rgbLeadZero1;
Int1.cbData = sizeof(rgbLeadZero1);
Int2.pbData = rgbLeadZero2;
Int2.cbData = sizeof(rgbLeadZero2);
if (!CertCompareIntegerBlob(&Int1, &Int2))
printf("Failed => Compare of Leading Zeroes\n");
Int1.pbData = rgbLeadFF1;
Int1.cbData = sizeof(rgbLeadFF1);
Int2.pbData = rgbLeadFF2;
Int2.cbData = sizeof(rgbLeadFF2);
if (!CertCompareIntegerBlob(&Int1, &Int2))
printf("Failed => Compare of Leading FFs\n");
Int1.pbData = rgbLeadZero1;
Int1.cbData = sizeof(rgbLeadZero1);
if (CertCompareIntegerBlob(&Int1, &Int2))
printf("Failed => Compare of Leading Zeroes != Leading FFs\n");
}
static BOOL EncodeCrl(BYTE **ppbEncoded, DWORD *pcbEncoded)
{
BOOL fResult;
BYTE *pbNameEncoded = NULL;
DWORD cbNameEncoded;
BYTE *pbCrlEncoded = NULL;
DWORD cbCrlEncoded;
DWORD SerialNumber0[2] = {0x12345678, 0x33445566};
DWORD SerialNumber1[1] = {0x12345678};
SYSTEMTIME SystemTime;
#define CRL_ATTR_0_0 "attr 0_0 printable"
#define CRL_ATTR_0_1 "attr 0_1 IA5"
#define CRL_ATTR_1_0 "attr 1_0 numeric"
#define CRL_ATTR_1_1 "attr 1_1 octet"
CERT_RDN_ATTR rgAttr0[] = {
"1.2.3.4.5.0.0.0", CERT_RDN_PRINTABLE_STRING,
strlen(CRL_ATTR_0_0), (BYTE *) CRL_ATTR_0_0,
"1.2.3.4.5.0.1.1.1", CERT_RDN_IA5_STRING,
strlen(CRL_ATTR_0_1), (BYTE *) CRL_ATTR_0_1
};
CERT_RDN_ATTR rgAttr1[] = {
"1.2.3.4.5.1.0", CERT_RDN_NUMERIC_STRING,
strlen(CRL_ATTR_1_0), (BYTE *) CRL_ATTR_1_0,
"1.2.3.4.5.1.1", CERT_RDN_OCTET_STRING,
strlen(CRL_ATTR_1_1), (BYTE *) CRL_ATTR_1_1,
"1.2.3.4.5.2", CERT_RDN_PRINTABLE_STRING,
0, NULL
};
CERT_RDN rgRDN[] = {
2, rgAttr0,
3, rgAttr1,
};
CERT_NAME_INFO Name = {2, rgRDN};
#define CRL_EXT_0 "extension 0 ."
#define CRL_EXT_1 "extension 1 .."
#define CRL_EXT_2 "extension 2 ..."
#define CRL_EXT_3 "extension 3 ...."
CERT_EXTENSION rgExt[] = {
"1.14.89990", FALSE, strlen(CRL_EXT_0), (BYTE *) CRL_EXT_0,
"1.14.89991", TRUE, strlen(CRL_EXT_1), (BYTE *) CRL_EXT_1,
"1.14.89992", FALSE, strlen(CRL_EXT_2), (BYTE *) CRL_EXT_2,
"1.14.89993", FALSE, strlen(CRL_EXT_3), (BYTE *) CRL_EXT_3
};
CRL_INFO Crl;
BYTE *pbExt = NULL;
if (dwExtLen) {
DWORD i;
if (NULL == (pbExt = (BYTE *) TestAlloc(dwExtLen)))
goto ErrorReturn;
for (i = 0; i < dwExtLen; i++)
pbExt[i] = (BYTE) i;
rgExt[3].Value.cbData = dwExtLen;
rgExt[3].Value.pbData = pbExt;
}
CRL_ENTRY rgCrlEntry[2];
TestCompareIntegerBlob();
cbNameEncoded = 0;
CryptEncodeObject(
dwCertEncodingType,
X509_NAME,
&Name,
NULL, // pbEncoded
&cbNameEncoded
);
if (cbNameEncoded == 0) {
PrintLastError("EncodeCrl::CryptEncodeObject(cbEncoded == 0)");
goto ErrorReturn;
}
pbNameEncoded = (BYTE *) TestAlloc(cbNameEncoded);
if (pbNameEncoded == NULL) goto ErrorReturn;
if (!CryptEncodeObject(
dwCertEncodingType,
X509_NAME,
&Name,
pbNameEncoded,
&cbNameEncoded
)) {
PrintLastError("EncodeCrl::CryptEncodeObject");
goto ErrorReturn;
}
GetSystemTime(&SystemTime);
memset(rgCrlEntry, 0, sizeof(rgCrlEntry));
rgCrlEntry[0].SerialNumber.pbData = (BYTE *) &SerialNumber0[0];
rgCrlEntry[0].SerialNumber.cbData = sizeof(SerialNumber0);
SystemTime.wYear--;
SystemTimeToFileTime(&SystemTime, &rgCrlEntry[0].RevocationDate);
rgCrlEntry[0].cExtension = 0;
rgCrlEntry[0].rgExtension = NULL;
rgCrlEntry[1].SerialNumber.pbData = (BYTE *) &SerialNumber1[0];
rgCrlEntry[1].SerialNumber.cbData = sizeof(SerialNumber1);
SystemTime.wYear--;
SystemTimeToFileTime(&SystemTime, &rgCrlEntry[1].RevocationDate);
rgCrlEntry[1].cExtension = 2;
rgCrlEntry[1].rgExtension = &rgExt[1];
memset(&Crl, 0, sizeof(Crl));
Crl.dwVersion = CRL_V2;
Crl.SignatureAlgorithm.pszObjId = "1.2.4.5.898";
Crl.Issuer.pbData = pbNameEncoded;
Crl.Issuer.cbData = cbNameEncoded;
GetSystemTime(&SystemTime);
SystemTimeToFileTime(&SystemTime, &Crl.ThisUpdate);
SystemTime.wYear++;
SystemTimeToFileTime(&SystemTime, &Crl.NextUpdate);
Crl.cCRLEntry = sizeof(rgCrlEntry) / sizeof(rgCrlEntry[0]);
Crl.rgCRLEntry = rgCrlEntry;
Crl.cExtension = sizeof(rgExt) / sizeof(rgExt[0]);
Crl.rgExtension = rgExt;
cbCrlEncoded = 0;
CryptEncodeObject(
dwCertEncodingType,
X509_CERT_CRL_TO_BE_SIGNED,
&Crl,
NULL, // pbEncoded
&cbCrlEncoded
);
if (cbCrlEncoded == 0) {
PrintLastError("EncodeCrl::CryptEncodeObject(cbEncoded == 0)");
goto ErrorReturn;
}
pbCrlEncoded = (BYTE *) TestAlloc(cbCrlEncoded);
if (pbCrlEncoded == NULL) goto ErrorReturn;
if (!CryptEncodeObject(
dwCertEncodingType,
X509_CERT_CRL_TO_BE_SIGNED,
&Crl,
pbCrlEncoded,
&cbCrlEncoded
)) {
PrintLastError("EncodeCrl::CryptEncodeObject");
goto ErrorReturn;
}
if (!EncodeSignedContent(
pbCrlEncoded,
cbCrlEncoded,
ppbEncoded,
pcbEncoded))
goto ErrorReturn;
fResult = TRUE;
goto CommonReturn;
ErrorReturn:
*ppbEncoded = NULL;
*pcbEncoded = 0;
fResult = FALSE;
CommonReturn:
if (pbNameEncoded)
TestFree(pbNameEncoded);
if (pbExt)
TestFree(pbExt);
if (pbCrlEncoded)
TestFree(pbCrlEncoded);
return fResult;
}
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");
}
printf(" [%d] RevocationDate:: %s\n", i,
FileTimeText(&pEntry->RevocationDate));
if (pEntry->cExtension == 0)
printf(" [%d] Extensions:: NONE\n", i);
else {
printf(" [%d] Extensions::\n", i);
PrintExtensions(pEntry->cExtension, pEntry->rgExtension);
}
}
}
static BOOL DecodeCrl(BYTE *pbEncoded, DWORD cbEncoded)
{
BOOL fResult;
PCRL_INFO pInfo = NULL;
DWORD cbInfo;
LPSTR pszObjId;
if (NULL == (pInfo = (PCRL_INFO) TestDecodeObject(
X509_CERT_CRL_TO_BE_SIGNED,
pbEncoded,
cbEncoded,
&cbInfo
))) goto ErrorReturn;
printf("Version:: %d\n", pInfo->dwVersion);
pszObjId = pInfo->SignatureAlgorithm.pszObjId;
if (pszObjId == NULL)
pszObjId = "<NULL OBJID>";
printf("SignatureAlgorithm:: %s\n", pszObjId);
if (pInfo->SignatureAlgorithm.Parameters.cbData) {
printf("SignatureAlgorithm.Parameters::\n");
PrintBytes(" ", pInfo->SignatureAlgorithm.Parameters.pbData,
pInfo->SignatureAlgorithm.Parameters.cbData);
}
printf("Issuer::\n");
DecodeName(pInfo->Issuer.pbData, pInfo->Issuer.cbData);
printf("ThisUpdate:: %s\n", FileTimeText(&pInfo->ThisUpdate));
printf("NextUpdate:: %s\n", FileTimeText(&pInfo->NextUpdate));
if (pInfo->cExtension == 0)
printf("Extensions:: NONE\n");
else {
printf("Extensions::\n");
PrintExtensions(pInfo->cExtension, pInfo->rgExtension);
}
if (pInfo->cCRLEntry == 0)
printf("Entries:: NONE\n");
else {
printf("Entries::\n");
PrintCrlEntries(pInfo->cCRLEntry, pInfo->rgCRLEntry);
}
DecodeSignedContent(pbEncoded, cbEncoded, X509_CERT_CRL_TO_BE_SIGNED,
cbInfo);
fResult = TRUE;
goto CommonReturn;
ErrorReturn:
fResult = FALSE;
CommonReturn:
if (pInfo)
TestFree(pInfo);
return fResult;
}
static BOOL EncodeCertPair(BYTE **ppbEncoded, DWORD *pcbEncoded)
{
BOOL fResult;
BYTE *pbEncoded = NULL;
DWORD cbEncoded;
CERT_PAIR CertPair;
memset(&CertPair, 0, sizeof(CertPair));
if (pszForwardCertFilename)
ReadDERFromFile(pszForwardCertFilename,
&CertPair.Forward.pbData, &CertPair.Forward.cbData);
if (pszReverseCertFilename)
ReadDERFromFile(pszReverseCertFilename,
&CertPair.Reverse.pbData, &CertPair.Reverse.cbData);
cbEncoded = 0;
CryptEncodeObject(
dwCertEncodingType,
X509_CERT_PAIR,
&CertPair,
NULL, // pbEncoded
&cbEncoded
);
if (cbEncoded == 0) {
PrintLastError("EncodeCertPair::CryptEncodeObject(cbEncoded == 0)");
goto ErrorReturn;
}
pbEncoded = (BYTE *) TestAlloc(cbEncoded);
if (pbEncoded == NULL) goto ErrorReturn;
if (!CryptEncodeObject(
dwCertEncodingType,
X509_CERT_PAIR,
&CertPair,
pbEncoded,
&cbEncoded
)) {
PrintLastError("EncodeCertPair::CryptEncodeObject");
goto ErrorReturn;
}
fResult = TRUE;
goto CommonReturn;
ErrorReturn:
if (pbEncoded) {
TestFree(pbEncoded);
pbEncoded = NULL;
}
cbEncoded = 0;
fResult = FALSE;
CommonReturn:
TestFree(CertPair.Forward.pbData);
TestFree(CertPair.Reverse.pbData);
*ppbEncoded = pbEncoded;
*pcbEncoded = cbEncoded;
return fResult;
}
static BOOL DecodeCertPair(BYTE *pbEncoded, DWORD cbEncoded)
{
BOOL fResult;
PCERT_PAIR pInfo = NULL;
if (NULL == (pInfo = (PCERT_PAIR) TestDecodeObject(
X509_CERT_PAIR,
pbEncoded,
cbEncoded
))) goto ErrorReturn;
if (pInfo->Forward.cbData) {
printf("Forward Certificate::\n");
PrintBytes(" ", pInfo->Forward.pbData, pInfo->Forward.cbData);
} else
printf("NO Forward Certificate\n");
if (pInfo->Reverse.cbData) {
printf("Reverse Certificate::\n");
PrintBytes(" ", pInfo->Reverse.pbData, pInfo->Reverse.cbData);
} else
printf("NO Reverse Certificate\n");
fResult = TRUE;
goto CommonReturn;
ErrorReturn:
fResult = FALSE;
CommonReturn:
TestFree(pInfo);
return fResult;
}