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.
 
 
 
 
 
 

2826 lines
88 KiB

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1995 - 1996
//
// File: tencode.cpp
//
// Contents: Test the encode/decode APIs. Test all the different length
// cases.
//
//
// Functions: main
//
// History: 17-Dec-96 philh created
//
//--------------------------------------------------------------------------
#include <windows.h>
#include <assert.h>
#include "wincrypt.h"
#include "certtest.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <memory.h>
#include <time.h>
#include <stddef.h>
#define DELTA_MORE_LENGTH 32
#define DELTA_LESS_LENGTH 8
static CRYPT_ENCODE_PARA TestEncodePara = {
offsetof(CRYPT_ENCODE_PARA, pfnFree) + sizeof(TestEncodePara.pfnFree),
TestAlloc,
TestFree
};
static BOOL AllocAndEncodeObject(
IN LPCSTR lpszStructType,
IN const void *pvStructInfo,
OUT BYTE **ppbEncoded,
OUT DWORD *pcbEncoded,
IN DWORD dwFlags = 0,
IN BOOL fIgnoreError = FALSE
)
{
BOOL fResult;
fResult = CryptEncodeObjectEx(
dwCertEncodingType,
lpszStructType,
pvStructInfo,
dwFlags | CRYPT_ENCODE_ALLOC_FLAG,
&TestEncodePara,
(void *) ppbEncoded,
pcbEncoded
);
if (!fResult && !fIgnoreError) {
if ((DWORD_PTR) lpszStructType <= 0xFFFF)
printf("CryptEncodeObject(StructType: %d)",
(DWORD)(DWORD_PTR) lpszStructType);
else
printf("CryptEncodeObject(StructType: %s)",
lpszStructType);
PrintLastError("");
}
return fResult;
}
static CRYPT_DECODE_PARA TestDecodePara = {
offsetof(CRYPT_DECODE_PARA, pfnFree) + sizeof(TestDecodePara.pfnFree),
TestAlloc,
TestFree
};
static void *AllocAndDecodeObject(
IN LPCSTR lpszStructType,
IN const BYTE *pbEncoded,
IN DWORD cbEncoded,
OUT DWORD *pcbStructInfo = NULL,
IN DWORD dwFlags = 0
)
{
DWORD cbStructInfo;
void *pvStructInfo;
if (!CryptDecodeObjectEx(
dwCertEncodingType,
lpszStructType,
pbEncoded,
cbEncoded,
dwFlags | CRYPT_DECODE_NOCOPY_FLAG | 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;
}
static void TestX942OtherInfo()
{
BOOL fResult;
BYTE *pbEncoded = NULL;
DWORD cbEncoded;
PCRYPT_X942_OTHER_INFO pInfo = NULL;
CRYPT_X942_OTHER_INFO X942OtherInfo;
LPCSTR pszObjId = "1.2.33.44.55";
BYTE rgbPubInfo[] = {0x11, 0x22, 0x33, 0x44, 0x55};
X942OtherInfo.pszContentEncryptionObjId = (LPSTR) pszObjId;
X942OtherInfo.rgbCounter[0] = 0x00;
X942OtherInfo.rgbCounter[1] = 0x11;
X942OtherInfo.rgbCounter[2] = 0x22;
X942OtherInfo.rgbCounter[3] = 0x33;
X942OtherInfo.rgbKeyLength[0] = 192;
X942OtherInfo.rgbKeyLength[1] = 0x00;
X942OtherInfo.rgbKeyLength[2] = 0x00;
X942OtherInfo.rgbKeyLength[3] = 0x00;
X942OtherInfo.PubInfo.cbData = sizeof(rgbPubInfo);
X942OtherInfo.PubInfo.pbData = rgbPubInfo;
printf("Test encode/decode X942_OTHER_INFO\n");
if (!AllocAndEncodeObject(
X942_OTHER_INFO,
&X942OtherInfo,
&pbEncoded,
&cbEncoded))
goto CommonReturn;
if (NULL == (pInfo = (PCRYPT_X942_OTHER_INFO) AllocAndDecodeObject(
X942_OTHER_INFO,
pbEncoded,
cbEncoded
))) goto CommonReturn;
if (0 != strcmp(pInfo->pszContentEncryptionObjId, pszObjId) ||
pInfo->PubInfo.cbData != sizeof(rgbPubInfo) ||
0 != memcmp(pInfo->PubInfo.pbData, rgbPubInfo,
sizeof(rgbPubInfo)) ||
0 != memcmp(X942OtherInfo.rgbCounter, pInfo->rgbCounter,
sizeof(X942OtherInfo.rgbCounter)) ||
0 != memcmp(X942OtherInfo.rgbKeyLength, pInfo->rgbKeyLength,
sizeof(X942OtherInfo.rgbKeyLength)))
printf("X942_OTHER_INFO failed => decode != encode input\n");
printf("Test encode/decode X942_OTHER_INFO with No PubInfo\n");
X942OtherInfo.PubInfo.cbData = 0;
X942OtherInfo.PubInfo.pbData = NULL;
TestFree(pbEncoded);
if (!AllocAndEncodeObject(
X942_OTHER_INFO,
&X942OtherInfo,
&pbEncoded,
&cbEncoded))
goto CommonReturn;
TestFree(pInfo);
if (NULL == (pInfo = (PCRYPT_X942_OTHER_INFO) AllocAndDecodeObject(
X942_OTHER_INFO,
pbEncoded,
cbEncoded
))) goto CommonReturn;
if (0 != strcmp(pInfo->pszContentEncryptionObjId, pszObjId) ||
pInfo->PubInfo.cbData != 0 ||
0 != memcmp(X942OtherInfo.rgbCounter, pInfo->rgbCounter,
sizeof(X942OtherInfo.rgbCounter)) ||
0 != memcmp(X942OtherInfo.rgbKeyLength, pInfo->rgbKeyLength,
sizeof(X942OtherInfo.rgbKeyLength)))
printf("X942_OTHER_INFO failed => decode != encode input\n");
CommonReturn:
if (pbEncoded)
TestFree(pbEncoded);
if (pInfo)
TestFree(pInfo);
}
static void TestExtensions()
{
BOOL fResult;
BYTE *pbEncoded = NULL;
DWORD cbEncoded;
BYTE *pbT61Encoded = NULL;
DWORD cbT61Encoded;
PCERT_EXTENSIONS pInfo = NULL;
BYTE rgbExt[] = {0x1, 0x2, 0x3};
CERT_EXTENSION Ext[2] = {
"1.2.3.4.5", TRUE, sizeof(rgbExt), rgbExt,
"1.2.3.6.7", FALSE, sizeof(rgbExt), rgbExt
};
CERT_EXTENSIONS ExtsInfo;
CERT_NAME_VALUE T61ExtsInfo;
ExtsInfo.cExtension = 2;
ExtsInfo.rgExtension = Ext;
printf("Test encode/decode X509_EXTENSIONS\n");
if (!AllocAndEncodeObject(
X509_EXTENSIONS,
&ExtsInfo,
&pbEncoded,
&cbEncoded))
goto CommonReturn;
if (NULL == (pInfo = (PCERT_EXTENSIONS) AllocAndDecodeObject(
X509_EXTENSIONS,
pbEncoded,
cbEncoded
))) goto CommonReturn;
if (pInfo->cExtension != ExtsInfo.cExtension ||
0 != strcmp(pInfo->rgExtension[0].pszObjId,
ExtsInfo.rgExtension[0].pszObjId))
printf("X509_EXTENSIONS failed => decode != encode input\n");
TestFree(pInfo);
pInfo = NULL;
printf("Test encode/decode T61 wrapped X509_EXTENSIONS\n");
T61ExtsInfo.dwValueType = CERT_RDN_T61_STRING;
T61ExtsInfo.Value.cbData = cbEncoded;
T61ExtsInfo.Value.pbData = pbEncoded;
if (!AllocAndEncodeObject(
X509_ANY_STRING,
&T61ExtsInfo,
&pbT61Encoded,
&cbT61Encoded))
goto CommonReturn;
if (NULL == (pInfo = (PCERT_EXTENSIONS) AllocAndDecodeObject(
X509_EXTENSIONS,
pbT61Encoded,
cbT61Encoded
))) goto CommonReturn;
if (pInfo->cExtension != ExtsInfo.cExtension ||
0 != strcmp(pInfo->rgExtension[0].pszObjId,
ExtsInfo.rgExtension[0].pszObjId))
printf("T61 wrapped X509_EXTENSIONS failed => decode != encode input\n");
CommonReturn:
if (pbEncoded)
TestFree(pbEncoded);
if (pbT61Encoded)
TestFree(pbT61Encoded);
if (pInfo)
TestFree(pInfo);
}
static void TestPKCSAttribute()
{
BOOL fResult;
BYTE *pbEncoded = NULL;
DWORD cbEncoded;
PCRYPT_ATTRIBUTE pInfo = NULL;
CRYPT_ATTRIBUTE Attribute;
LPCSTR pszObjId = "1.2.33.44.55";
BYTE rgb0[] = {0x2, 0x2, 0x11, 0x22}; // INTEGER
BYTE rgb1[] = {0x4, 0x5, 0x11, 0x22, 0x33, 0x44, 0x55}; // OCTET STRING
CRYPT_ATTR_BLOB rgValue[2] = {
sizeof(rgb0), rgb0,
sizeof(rgb1), rgb1
};
Attribute.pszObjId = (LPSTR) pszObjId;
Attribute.cValue = 2;
Attribute.rgValue = rgValue;
printf("Test encode/decode PKCS_ATTRIBUTE\n");
if (!AllocAndEncodeObject(
PKCS_ATTRIBUTE,
&Attribute,
&pbEncoded,
&cbEncoded))
goto CommonReturn;
if (NULL == (pInfo = (PCRYPT_ATTRIBUTE) AllocAndDecodeObject(
PKCS_ATTRIBUTE,
pbEncoded,
cbEncoded
))) goto CommonReturn;
if (0 != strcmp(pInfo->pszObjId, pszObjId) ||
pInfo->cValue != 2 ||
pInfo->rgValue[0].cbData != sizeof(rgb0) ||
0 != memcmp(pInfo->rgValue[0].pbData, rgb0, sizeof(rgb0)) ||
pInfo->rgValue[1].cbData != sizeof(rgb1) ||
0 != memcmp(pInfo->rgValue[1].pbData, rgb1, sizeof(rgb1)))
printf("PKCS_ATTRIBUTE failed => decode != encode input\n");
printf("Test encode/decode PKCS_ATTRIBUTE with empty OID\n");
TestFree(pbEncoded);
Attribute.pszObjId = "";
if (AllocAndEncodeObject(
PKCS_ATTRIBUTE,
&Attribute,
&pbEncoded,
&cbEncoded,
0, // dwFlags
TRUE)) // fIgnoreError
printf(" failed => expected error\n");
else {
DWORD dwErr = GetLastError();
printf(" Got LastError: 0x%x (%d)\n", dwErr, dwErr);
}
CommonReturn:
if (pbEncoded)
TestFree(pbEncoded);
if (pInfo)
TestFree(pInfo);
}
static void TestPKCSAttributes()
{
BOOL fResult;
BYTE *pbEncoded = NULL;
DWORD cbEncoded;
PCRYPT_ATTRIBUTES pInfo = NULL;
DWORD i;
#define ATTRIBUTE_CNT 3
CRYPT_ATTRIBUTES Attributes;
CRYPT_ATTRIBUTE rgAttribute[ATTRIBUTE_CNT];
LPCSTR pszObjId = "1.2.33.44.55";
BYTE rgb0[] = {0x2, 0x2, 0x11, 0x22}; // INTEGER
BYTE rgb1[] = {0x4, 0x5, 0x11, 0x22, 0x33, 0x44, 0x55}; // OCTET STRING
CRYPT_ATTR_BLOB rgValue[2] = {
sizeof(rgb0), rgb0,
sizeof(rgb1), rgb1
};
for (i = 0; i < ATTRIBUTE_CNT; i++) {
rgAttribute[i].pszObjId = (LPSTR) pszObjId;
rgAttribute[i].cValue = 2;
rgAttribute[i].rgValue = rgValue;
}
Attributes.cAttr = ATTRIBUTE_CNT;
Attributes.rgAttr = rgAttribute;
printf("Test encode/decode PKCS_ATTRIBUTES\n");
if (!AllocAndEncodeObject(
PKCS_ATTRIBUTES,
&Attributes,
&pbEncoded,
&cbEncoded))
goto CommonReturn;
if (NULL == (pInfo = (PCRYPT_ATTRIBUTES) AllocAndDecodeObject(
PKCS_ATTRIBUTES,
pbEncoded,
cbEncoded
))) goto CommonReturn;
// Note, ATTRIBUTES is a SET OF. Entries are re-ordered
if (pInfo->cAttr != ATTRIBUTE_CNT)
printf("PKCS_ATTRIBUTES failed => decode != encode attr count\n");
else {
for (i = 0; i < ATTRIBUTE_CNT; i++) {
PCRYPT_ATTRIBUTE pAttr = &pInfo->rgAttr[i];
if (0 != strcmp(pAttr->pszObjId, pszObjId) ||
pAttr->cValue != 2 ||
pAttr->rgValue[0].cbData != sizeof(rgb0) ||
0 != memcmp(pAttr->rgValue[0].pbData, rgb0, sizeof(rgb0)) ||
pAttr->rgValue[1].cbData != sizeof(rgb1) ||
0 != memcmp(pAttr->rgValue[1].pbData, rgb1, sizeof(rgb1))) {
printf("PKCS_ATTRIBUTES failed => decode != encode input\n");
break;
}
}
}
CommonReturn:
if (pbEncoded)
TestFree(pbEncoded);
if (pInfo)
TestFree(pInfo);
}
static void TestContentInfoSequenceOfAny()
{
BOOL fResult;
BYTE *pbEncoded = NULL;
DWORD cbEncoded;
PCRYPT_CONTENT_INFO_SEQUENCE_OF_ANY pInfo = NULL;
CRYPT_CONTENT_INFO_SEQUENCE_OF_ANY SeqOfAny;
BYTE rgb0[] = {0x4, 0x5, 0x11, 0x22, 0x33, 0x44, 0x55}; // OCTET STRING
BYTE rgb1[] = {0x2, 0x2, 0x11, 0x22}; // INTEGER
CRYPT_DER_BLOB rgValue[2] = {
sizeof(rgb0), rgb0,
sizeof(rgb1), rgb1
};
SeqOfAny.pszObjId = szOID_NETSCAPE_CERT_SEQUENCE;
SeqOfAny.cValue = 2;
SeqOfAny.rgValue = rgValue;
printf("Test encode/decode PKCS_CONTENT_INFO_SEQUENCE_OF_ANY\n");
if (!AllocAndEncodeObject(
PKCS_CONTENT_INFO_SEQUENCE_OF_ANY,
&SeqOfAny,
&pbEncoded,
&cbEncoded))
goto CommonReturn;
if (NULL == (pInfo =
(PCRYPT_CONTENT_INFO_SEQUENCE_OF_ANY) AllocAndDecodeObject(
PKCS_CONTENT_INFO_SEQUENCE_OF_ANY,
pbEncoded,
cbEncoded
))) goto CommonReturn;
if (0 != strcmp(pInfo->pszObjId, szOID_NETSCAPE_CERT_SEQUENCE) ||
pInfo->cValue != 2 ||
pInfo->rgValue[0].cbData != sizeof(rgb0) ||
0 != memcmp(pInfo->rgValue[0].pbData, rgb0, sizeof(rgb0)) ||
pInfo->rgValue[1].cbData != sizeof(rgb1) ||
0 != memcmp(pInfo->rgValue[1].pbData, rgb1, sizeof(rgb1)))
printf("PKCS_CONTENT_INFO_SEQUENCE_OF_ANY failed => decode != encode input\n");
CommonReturn:
if (pbEncoded)
TestFree(pbEncoded);
if (pInfo)
TestFree(pInfo);
}
static void TestSequenceOfAny()
{
BOOL fResult;
BYTE *pbEncoded = NULL;
DWORD cbEncoded;
PCRYPT_SEQUENCE_OF_ANY pInfo = NULL;
CRYPT_SEQUENCE_OF_ANY SeqOfAny;
BYTE rgb0[] = {0x4, 0x5, 0x11, 0x22, 0x33, 0x44, 0x55}; // OCTET STRING
BYTE rgb1[] = {0x2, 0x2, 0x11, 0x22}; // INTEGER
CRYPT_DER_BLOB rgValue[2] = {
sizeof(rgb0), rgb0,
sizeof(rgb1), rgb1
};
SeqOfAny.cValue = 2;
SeqOfAny.rgValue = rgValue;
printf("Test encode/decode X509_SEQUENCE_OF_ANY\n");
if (!AllocAndEncodeObject(
X509_SEQUENCE_OF_ANY,
&SeqOfAny,
&pbEncoded,
&cbEncoded))
goto CommonReturn;
if (NULL == (pInfo =
(PCRYPT_SEQUENCE_OF_ANY) AllocAndDecodeObject(
X509_SEQUENCE_OF_ANY,
pbEncoded,
cbEncoded
))) goto CommonReturn;
if (pInfo->cValue != 2 ||
pInfo->rgValue[0].cbData != sizeof(rgb0) ||
0 != memcmp(pInfo->rgValue[0].pbData, rgb0, sizeof(rgb0)) ||
pInfo->rgValue[1].cbData != sizeof(rgb1) ||
0 != memcmp(pInfo->rgValue[1].pbData, rgb1, sizeof(rgb1)))
printf("X509_SEQUENCE_OF_ANY failed => decode != encode input\n");
CommonReturn:
if (pbEncoded)
TestFree(pbEncoded);
if (pInfo)
TestFree(pInfo);
}
static void TestInteger(
int iEncode
)
{
BOOL fResult;
BYTE *pbEncoded = NULL;
DWORD cbEncoded;
int iDecode = 0;
DWORD cbInfo;
printf("Test encode/decode X509_INTEGER: 0x%x (%d)\n", iEncode, iEncode);
if (!AllocAndEncodeObject(
X509_INTEGER,
&iEncode,
&pbEncoded,
&cbEncoded))
goto CommonReturn;
cbInfo = sizeof(iDecode);
if (!CryptDecodeObject(
dwCertEncodingType,
X509_INTEGER,
pbEncoded,
cbEncoded,
0, // dwFlags
&iDecode,
&cbInfo
)) {
PrintLastError("CryptDecodeObject(X509_INTEGER)");
goto CommonReturn;
}
if (cbInfo != sizeof(iDecode))
printf("X509_INTEGER failed => unexpected decode length\n");
if (iEncode != iDecode)
printf("X509_INTEGER failed => decoded output (%d) != encode input\n",
iDecode);
CommonReturn:
if (pbEncoded)
TestFree(pbEncoded);
}
static void TestInteger()
{
TestInteger(0);
TestInteger(0x12345678);
TestInteger(-1234);
TestInteger(123);
}
static void TestMultiByteInteger(
BYTE *pb,
DWORD cb
)
{
BOOL fResult;
BYTE *pbEncoded = NULL;
DWORD cbEncoded;
PCRYPT_INTEGER_BLOB pInfo = NULL;
CRYPT_INTEGER_BLOB MultiByteInteger = {cb, pb };
printf("Test encode/decode X509_MULTI_BYTE_INTEGER\n");
PrintBytes(" ", pb, cb);
if (!AllocAndEncodeObject(
X509_MULTI_BYTE_INTEGER,
&MultiByteInteger,
&pbEncoded,
&cbEncoded))
goto CommonReturn;
if (NULL == (pInfo = (PCRYPT_INTEGER_BLOB) AllocAndDecodeObject(
X509_MULTI_BYTE_INTEGER,
pbEncoded,
cbEncoded
))) goto CommonReturn;
if (!CertCompareIntegerBlob(pInfo, &MultiByteInteger))
printf("X509_MULTI_BYTE_INTEGER failed => decode != encode input\n");
CommonReturn:
if (pbEncoded)
TestFree(pbEncoded);
if (pInfo)
TestFree(pInfo);
}
static void TestMultiByteInteger()
{
BYTE rgb1[] = {0x11, 0x22, 0x33, 0x44, 0x55};
BYTE rgb2[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0xFF, 0x00};
BYTE rgb3[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0xFF, 0xFF};
BYTE rgb4[] = {0x11, 0x22, 0x33, 0x44, 0x80, 0xFF, 0xFF};
BYTE rgb5[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x00};
BYTE rgb6[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x00, 0x00, 0x00};
TestMultiByteInteger(rgb1, sizeof(rgb1));
TestMultiByteInteger(rgb2, sizeof(rgb2));
TestMultiByteInteger(rgb3, sizeof(rgb2));
TestMultiByteInteger(rgb4, sizeof(rgb2));
TestMultiByteInteger(rgb5, sizeof(rgb2));
TestMultiByteInteger(rgb6, sizeof(rgb2));
}
static const BYTE rgbUnusedAndMask[8] =
{0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80};
static void TestBits(
PCRYPT_BIT_BLOB pBits
)
{
BOOL fResult;
BYTE *pbEncoded = NULL;
DWORD cbEncoded;
PCRYPT_BIT_BLOB pInfo = NULL;
printf("Test encode/decode X509_BITS(cb:%d, cUnused: %d)\n",
pBits->cbData, pBits->cUnusedBits);
PrintBytes(" ", pBits->pbData, pBits->cbData);
if (!AllocAndEncodeObject(
X509_BITS,
pBits,
&pbEncoded,
&cbEncoded))
goto CommonReturn;
if (NULL == (pInfo = (PCRYPT_BIT_BLOB) AllocAndDecodeObject(
X509_BITS,
pbEncoded,
cbEncoded
))) goto CommonReturn;
if (pInfo->cbData != pBits->cbData ||
pInfo->cUnusedBits != pBits->cUnusedBits)
printf("X509_BITS failed => decode != encode (cbData or cUnusedBits)\n");
else {
DWORD cbData = pInfo->cbData;
if (cbData > 1) {
if (0 != memcmp(pInfo->pbData, pBits->pbData, cbData - 1))
printf("X509_BITS failed => decode != encode input\n");
}
if (cbData > 0) {
if ((pBits->pbData[cbData - 1] &
rgbUnusedAndMask[pInfo->cUnusedBits]) !=
pInfo->pbData[cbData - 1])
printf("X509_BITS failed => decode != encode (last byte)\n");
}
}
CommonReturn:
if (pbEncoded)
TestFree(pbEncoded);
if (pInfo)
TestFree(pInfo);
}
static void TestBits()
{
BYTE rgb1[] = {0xFF, 0x00, 0x00, 0x00};
BYTE rgb2[] = {0x00, 0xFE, 0xFC};
CRYPT_BIT_BLOB Bits;
memset(&Bits, 0, sizeof(Bits));
TestBits(&Bits);
Bits.pbData = rgb1;
TestBits(&Bits);
Bits.cbData = 1;
TestBits(&Bits);
Bits.cUnusedBits = 1;
TestBits(&Bits);
Bits.cUnusedBits = 7;
TestBits(&Bits);
Bits.cbData = sizeof(rgb1);
Bits.cUnusedBits = 0;
TestBits(&Bits);
Bits.cUnusedBits = 1;
TestBits(&Bits);
Bits.cUnusedBits = 7;
TestBits(&Bits);
Bits.pbData = rgb2;
Bits.cUnusedBits = 0;
Bits.cbData = 1;
TestBits(&Bits);
Bits.cUnusedBits = 1;
TestBits(&Bits);
Bits.cUnusedBits = 7;
TestBits(&Bits);
Bits.cbData = sizeof(rgb2);
Bits.cUnusedBits = 0;
TestBits(&Bits);
Bits.cUnusedBits = 1;
TestBits(&Bits);
Bits.cUnusedBits = 7;
TestBits(&Bits);
}
static void TestBitsWithoutTrailingZeroes(
PCRYPT_BIT_BLOB pBits,
DWORD cbData,
DWORD cUnusedBits
)
{
BOOL fResult;
BYTE *pbEncoded = NULL;
DWORD cbEncoded;
PCRYPT_BIT_BLOB pInfo = NULL;
printf("Test encode/decode X509_BITS_WO_ZEROES(cb:%d, cUnused: %d) Expected(cb:%d, cUnused:%d)\n",
pBits->cbData, pBits->cUnusedBits, cbData, cUnusedBits);
PrintBytes(" Input:: ", pBits->pbData, pBits->cbData);
if (!AllocAndEncodeObject(
X509_BITS_WITHOUT_TRAILING_ZEROES,
pBits,
&pbEncoded,
&cbEncoded))
goto CommonReturn;
if (NULL == (pInfo = (PCRYPT_BIT_BLOB) AllocAndDecodeObject(
X509_BITS_WITHOUT_TRAILING_ZEROES,
pbEncoded,
cbEncoded
))) goto CommonReturn;
PrintBytes(" Encoded:: ", pbEncoded, cbEncoded);
if (pInfo->cbData != cbData ||
pInfo->cUnusedBits != cUnusedBits)
printf("X509_BITS_WO_ZEROES failed => decode != encode (cbData or cUnusedBits)\n");
else {
if (cbData > 1) {
if (0 != memcmp(pInfo->pbData, pBits->pbData, cbData - 1))
printf("X509_BITS_WO_ZEROES failed => decode != encode input\n");
}
if (cbData > 0) {
if ((pBits->pbData[cbData - 1] &
rgbUnusedAndMask[cUnusedBits]) !=
pInfo->pbData[cbData - 1])
printf("X509_BITS_WO_ZEROES failed => decode != encode (last byte)\n");
}
}
CommonReturn:
if (pbEncoded)
TestFree(pbEncoded);
if (pInfo)
TestFree(pInfo);
}
static void TestBitsWithoutTrailingZeroes()
{
BYTE rgb1[] = {0xFF, 0x00, 0x00, 0x00};
BYTE rgb2[] = {0x00, 0xFE, 0xFC};
BYTE rgb3[] = {0x00, 0x18, 0x00, 0x20};
CRYPT_BIT_BLOB Bits;
int i;
BYTE b;
memset(&Bits, 0, sizeof(Bits));
TestBitsWithoutTrailingZeroes(&Bits, 0,0);
Bits.pbData = rgb1;
TestBitsWithoutTrailingZeroes(&Bits, 0,0);
Bits.cbData = 1;
TestBitsWithoutTrailingZeroes(&Bits, 1,0);
Bits.cUnusedBits = 1;
TestBitsWithoutTrailingZeroes(&Bits, 1,1);
Bits.cUnusedBits = 7;
TestBitsWithoutTrailingZeroes(&Bits, 1,7);
Bits.cbData = sizeof(rgb1);
Bits.cUnusedBits = 0;
TestBitsWithoutTrailingZeroes(&Bits, 1,0);
Bits.cUnusedBits = 1;
TestBitsWithoutTrailingZeroes(&Bits, 1,0);
Bits.cUnusedBits = 7;
TestBitsWithoutTrailingZeroes(&Bits, 1,0);
Bits.pbData = rgb2;
Bits.cUnusedBits = 0;
Bits.cbData = 1;
TestBitsWithoutTrailingZeroes(&Bits, 0,0);
Bits.cUnusedBits = 1;
TestBitsWithoutTrailingZeroes(&Bits, 0,0);
Bits.cUnusedBits = 7;
TestBitsWithoutTrailingZeroes(&Bits, 0,0);
Bits.cbData = sizeof(rgb2);
Bits.cUnusedBits = 0;
TestBitsWithoutTrailingZeroes(&Bits, 3,2);
Bits.cUnusedBits = 1;
TestBitsWithoutTrailingZeroes(&Bits, 3,2);
Bits.cUnusedBits = 2;
TestBitsWithoutTrailingZeroes(&Bits, 3,2);
Bits.cUnusedBits = 4;
TestBitsWithoutTrailingZeroes(&Bits, 3,4);
Bits.cUnusedBits = 7;
TestBitsWithoutTrailingZeroes(&Bits, 3,7);
Bits.pbData = rgb3;
Bits.cbData = sizeof(rgb3);
Bits.cUnusedBits = 0;
TestBitsWithoutTrailingZeroes(&Bits, 4,5);
Bits.cUnusedBits = 3;
TestBitsWithoutTrailingZeroes(&Bits, 4,5);
Bits.cUnusedBits = 4;
TestBitsWithoutTrailingZeroes(&Bits, 4,5);
Bits.cUnusedBits = 5;
TestBitsWithoutTrailingZeroes(&Bits, 4,5);
Bits.cUnusedBits = 6;
TestBitsWithoutTrailingZeroes(&Bits, 2,3);
Bits.cUnusedBits = 7;
TestBitsWithoutTrailingZeroes(&Bits, 2,3);
Bits.pbData = &b;
Bits.cbData = 1;
for (i = 0; i <= 7; i++) {
b = 1 << i;
Bits.cUnusedBits = 0;
TestBitsWithoutTrailingZeroes(&Bits, 1,i);
Bits.cUnusedBits = i;
TestBitsWithoutTrailingZeroes(&Bits, 1,i);
}
}
static void TestOID(
IN LPCSTR pszObjId
)
{
BOOL fResult;
BYTE *pbEncoded = NULL;
DWORD cbEncoded;
PCRYPT_ATTRIBUTE pInfo = NULL;
CRYPT_ATTRIBUTE Attribute;
memset(&Attribute, 0, sizeof(Attribute));
Attribute.pszObjId = (LPSTR) pszObjId;
printf("Test encode/decode OID: %s\n", pszObjId);
if (!AllocAndEncodeObject(
PKCS_ATTRIBUTE,
&Attribute,
&pbEncoded,
&cbEncoded))
goto CommonReturn;
if (NULL == (pInfo = (PCRYPT_ATTRIBUTE) AllocAndDecodeObject(
PKCS_ATTRIBUTE,
pbEncoded,
cbEncoded
))) goto CommonReturn;
if (0 != strcmp(pInfo->pszObjId, pszObjId))
printf("OID failed => decode != encode input\n");
CommonReturn:
if (pbEncoded)
TestFree(pbEncoded);
if (pInfo)
TestFree(pInfo);
}
static void TestOID()
{
TestOID("0.1");
TestOID("0.9.2342.19200300.100.1.25");
TestOID("1.2.3.111111111144444444444");
TestOID("1.2.3.111111111144444444444.55555555555555555.666666666666666");
TestOID("1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20");
}
static void TestUnicodeAnyString(
DWORD dwValueType,
LPCWSTR pwszValue,
DWORD dwExpectedErr,
DWORD dwExpectedErrLocation,
DWORD dwFlags = 0
)
{
BOOL fResult;
BYTE *pbEncoded = NULL;
DWORD cbEncoded;
PCERT_NAME_VALUE pInfo = NULL;
CERT_NAME_VALUE NameValue;
memset(&NameValue, 0, sizeof(NameValue));
NameValue.dwValueType = dwValueType;
NameValue.Value.pbData = (BYTE *) pwszValue;
if (dwExpectedErr ) {
printf("Test encode X509_UNICODE_ANY_STRING:: dwValueType: %d 0x%x Expected Err: 0x%x Location: %d\n",
dwValueType, dwValueType, dwExpectedErr, dwExpectedErrLocation);
if (CryptEncodeObject(
dwCertEncodingType,
X509_UNICODE_ANY_STRING,
&NameValue,
NULL, // pbEncoded
&cbEncoded
))
printf(" failed => expected error\n");
else {
DWORD dwErr = GetLastError();
if (dwErr != dwExpectedErr)
printf(" LastError failed => expected: 0x%x (%d), got: 0x%x (%d)\n",
dwExpectedErr, dwExpectedErr, dwErr, dwErr);
if (dwExpectedErrLocation != cbEncoded)
printf(" ErrLocation failed => expected: %d, got: %d\n",
dwExpectedErrLocation, cbEncoded);
}
}
printf("Test alloc encode/decode X509_UNICODE_ANY_STRING:: dwValueType: %d 0x%x string: %S\n",
dwValueType, dwValueType, pwszValue);
if (!AllocAndEncodeObject(
X509_UNICODE_ANY_STRING,
&NameValue,
&pbEncoded,
&cbEncoded,
dwFlags,
dwExpectedErr != 0 // fIgnoreError
)) {
if (dwExpectedErr) {
DWORD dwErr = GetLastError();
if (dwErr != dwExpectedErr)
printf(" LastError failed => expected: 0x%x (%d), got: 0x%x (%d)\n",
dwExpectedErr, dwExpectedErr, dwErr, dwErr);
if (dwExpectedErrLocation != cbEncoded)
printf(" ErrLocation failed => expected: %d, got: %d\n",
dwExpectedErrLocation, cbEncoded);
}
goto CommonReturn;
} else if (dwExpectedErr)
printf(" failed => expected error\n");
if (NULL == (pInfo = (PCERT_NAME_VALUE) AllocAndDecodeObject(
X509_UNICODE_ANY_STRING,
pbEncoded,
cbEncoded,
NULL,
dwFlags
))) goto CommonReturn;
if (wcslen(pwszValue) != wcslen((LPWSTR) pInfo->Value.pbData) ||
wcslen(pwszValue) * 2 != pInfo->Value.cbData ||
0 != wcscmp(pwszValue, (LPWSTR) pInfo->Value.pbData))
printf("X509_UNICODE_ANY_STRING failed => decoded output (%S) != encode input\n",
(LPWSTR) pInfo->Value.pbData);
CommonReturn:
if (pbEncoded)
TestFree(pbEncoded);
if (pInfo)
TestFree(pInfo);
}
static void TestUnicodeAnyString(
DWORD dwValueType,
PCRYPT_DATA_BLOB pDataBlob,
DWORD dwExpectedErr
)
{
BOOL fResult;
BYTE *pbEncoded = NULL;
DWORD cbEncoded;
DWORD cbInfo;
CERT_NAME_VALUE NameValue;
memset(&NameValue, 0, sizeof(NameValue));
NameValue.dwValueType = dwValueType;
NameValue.Value.pbData = pDataBlob->pbData;
NameValue.Value.cbData = pDataBlob->cbData;
printf("Test encode/decode X509_UNICODE_ANY_STRING:: dwValueType: %d Expected Err: 0x%x\n",
dwValueType, dwExpectedErr);
if (CryptEncodeObject(
dwCertEncodingType,
X509_UNICODE_ANY_STRING,
&NameValue,
NULL, // pbEncoded
&cbEncoded
))
printf(" Encode failed => expected error\n");
else {
DWORD dwErr = GetLastError();
if (dwErr != dwExpectedErr)
printf(" Encode LastError failed => expected: 0x%x (%d), got: 0x%x (%d)\n",
dwExpectedErr, dwExpectedErr, dwErr, dwErr);
}
if (!AllocAndEncodeObject(
X509_ANY_STRING,
&NameValue,
&pbEncoded,
&cbEncoded))
goto CommonReturn;
if (CryptDecodeObject(
dwCertEncodingType,
X509_UNICODE_ANY_STRING,
pbEncoded,
cbEncoded,
0, // dwFlags
NULL, // pInfo
&cbInfo
))
printf(" Decode failed => expected error\n");
else {
DWORD dwErr = GetLastError();
if (dwErr != dwExpectedErr)
printf(" Decode LastError failed => expected: 0x%x (%d), got: 0x%x (%d)\n",
dwExpectedErr, dwExpectedErr, dwErr, dwErr);
}
CommonReturn:
if (pbEncoded)
TestFree(pbEncoded);
}
static void TestUnicodeAnyString()
{
DWORD dwValueType;
WORD rgwBadIA5[] = {0x30, 0x31, 0x32, 0x80, 0x33, 0x00};
BYTE rgb0[] = {0x2, 0x2, 0x11, 0x22}; // Encoded INTEGER
CRYPT_DATA_BLOB EncodedBlob = {sizeof(rgb0), rgb0};
BYTE rgb1[] = {0, 0x11, 0x22, 0x33, 0x44, 0x55};
CRYPT_DATA_BLOB OctetString = {sizeof(rgb1), rgb1};
TestUnicodeAnyString(CERT_RDN_ENCODED_BLOB, &EncodedBlob,
(DWORD) CRYPT_E_NOT_CHAR_STRING);
TestUnicodeAnyString(CERT_RDN_OCTET_STRING, &OctetString,
(DWORD) CRYPT_E_NOT_CHAR_STRING);
TestUnicodeAnyString(CERT_RDN_NUMERIC_STRING,
L"0123456789 ",
0, 0);
for (dwValueType = CERT_RDN_PRINTABLE_STRING;
dwValueType <= CERT_RDN_BMP_STRING; dwValueType++)
TestUnicodeAnyString(dwValueType,
L"UNICODE string to be encoded",
0, 0);
TestUnicodeAnyString(CERT_RDN_ANY_TYPE, L"InvalidArg",
(DWORD) CRYPT_E_NOT_CHAR_STRING, 0);
TestUnicodeAnyString(CERT_RDN_NUMERIC_STRING,
// 0123456789012345678901234567890
L"0123456789a013",
(DWORD) CRYPT_E_INVALID_NUMERIC_STRING, 10);
TestUnicodeAnyString(CERT_RDN_PRINTABLE_STRING,
// 0123456789012345678901234567890
L"Invalid printable ### az AZ 09 \'()+,-./:=?",
(DWORD) CRYPT_E_INVALID_PRINTABLE_STRING, 18);
TestUnicodeAnyString(CERT_RDN_DISABLE_CHECK_TYPE_FLAG |
CERT_RDN_PRINTABLE_STRING,
// 0123456789012345678901234567890
L"Invalid printable ### az AZ 09 \'()+,-./:=?",
0, 0);
TestUnicodeAnyString(CERT_RDN_PRINTABLE_STRING,
// 0123456789012345678901234567890
L"Invalid printable ### az AZ 09 \'()+,-./:=?",
0, 0,
CRYPT_UNICODE_NAME_ENCODE_DISABLE_CHECK_TYPE_FLAG);
TestUnicodeAnyString(CERT_RDN_T61_STRING,
// 0123456789012345678901234567890
L"T61 ### az AZ 09 \'()+,-./:=?",
0, 0, 0);
TestUnicodeAnyString(CERT_RDN_T61_STRING,
// 0123456789012345678901234567890
L"T61 ### az AZ 09 \'()+,-./:=?",
0, 0, CERT_RDN_DISABLE_IE4_UTF8_FLAG);
TestUnicodeAnyString(CERT_RDN_IA5_STRING,
rgwBadIA5,
(DWORD) CRYPT_E_INVALID_IA5_STRING, 3);
}
static void TestUniversalString()
{
BOOL fResult;
BYTE *pbEncoded = NULL;
DWORD cbEncoded;
PCERT_NAME_VALUE pInfo = NULL;
CERT_NAME_VALUE NameValue;
DWORD rgdwUniversal[] = {
0x00ffff,
0x110000,
0x010000,
0xffffffff,
0x110001,
0x10FFFF,
};
LPWSTR pwszExpectedUniversal =
L"\xffff"
L"\xfffd"
L"\xd800\xdc00"
L"\xfffd"
L"\xfffd"
L"\xdbff\xdfff"
;
TestUnicodeAnyString(CERT_RDN_UNIVERSAL_STRING,
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",
0, 0, 0);
// Encode a universal string containing characters > 0x10FFFF. These
// Should be converted to 0xFFFD
memset(&NameValue, 0, sizeof(NameValue));
NameValue.dwValueType = CERT_RDN_UNIVERSAL_STRING;
NameValue.Value.pbData = (BYTE *) rgdwUniversal;
NameValue.Value.cbData = sizeof(rgdwUniversal);
if (!AllocAndEncodeObject(
X509_ANY_STRING,
&NameValue,
&pbEncoded,
&cbEncoded
)) {
goto CommonReturn;
}
if (NULL == (pInfo = (PCERT_NAME_VALUE) AllocAndDecodeObject(
X509_UNICODE_ANY_STRING,
pbEncoded,
cbEncoded,
NULL
))) goto CommonReturn;
if (wcslen(pwszExpectedUniversal) != wcslen((LPWSTR) pInfo->Value.pbData) ||
wcslen(pwszExpectedUniversal) * 2 != pInfo->Value.cbData ||
0 != wcscmp(pwszExpectedUniversal, (LPWSTR) pInfo->Value.pbData))
printf("UniversalString encode/decode failed\n");
CommonReturn:
if (pbEncoded)
TestFree(pbEncoded);
if (pInfo)
TestFree(pInfo);
}
static void TestChoiceOfTime(
FILETIME *pftEncode
)
{
BOOL fResult;
BYTE *pbEncoded = NULL;
DWORD cbEncoded;
FILETIME ftDecode;
DWORD cbInfo;
printf("Test encode/decode X509_CHOICE_OF_TIME: %s\n",
FileTimeText(pftEncode));
if (!AllocAndEncodeObject(
X509_CHOICE_OF_TIME,
pftEncode,
&pbEncoded,
&cbEncoded))
goto CommonReturn;
cbInfo = sizeof(ftDecode);
if (!CryptDecodeObject(
dwCertEncodingType,
X509_CHOICE_OF_TIME,
pbEncoded,
cbEncoded,
0, // dwFlags
&ftDecode,
&cbInfo
)) {
PrintLastError("CryptDecodeObject(X509_CHOICE_OF_TIME)");
goto CommonReturn;
}
if (cbInfo != sizeof(ftDecode))
printf("X509_CHOICE_OF_TIME failed => unexpected decode length\n");
if (0 != memcmp(pftEncode, &ftDecode, sizeof(ftDecode)))
printf("X509_CHOICE_OF_TIME failed => decode (%s) != encode input\n",
FileTimeText(&ftDecode));
CommonReturn:
if (pbEncoded)
TestFree(pbEncoded);
}
static void TestChoiceOfTime()
{
FILETIME ft;
SYSTEMTIME t;
memset(&t, 0, sizeof(t));
t.wYear = 2000;
t.wMonth = 1;
t.wDay = 2;
t.wHour = 3;
t.wMinute = 4;
t.wSecond = 5;
if (!SystemTimeToFileTime(&t, &ft)) {
PrintLastError("SystemTimeToFileTime");
return;
}
TestChoiceOfTime(&ft);
t.wYear = 1900;
if (!SystemTimeToFileTime(&t, &ft)) {
PrintLastError("SystemTimeToFileTime");
return;
}
TestChoiceOfTime(&ft);
t.wYear = 2080;
if (!SystemTimeToFileTime(&t, &ft)) {
PrintLastError("SystemTimeToFileTime");
return;
}
TestChoiceOfTime(&ft);
}
static void TestUtcTime(
FILETIME *pftEncode
)
{
BOOL fResult;
BYTE *pbEncoded = NULL;
DWORD cbEncoded;
FILETIME ftDecode;
DWORD cbInfo;
printf("Test encode/decode PKCS_UTC_TIME: %s\n",
FileTimeText(pftEncode));
if (!AllocAndEncodeObject(
PKCS_UTC_TIME,
pftEncode,
&pbEncoded,
&cbEncoded))
goto CommonReturn;
cbInfo = sizeof(ftDecode);
if (!CryptDecodeObject(
dwCertEncodingType,
PKCS_UTC_TIME,
pbEncoded,
cbEncoded,
0, // dwFlags
&ftDecode,
&cbInfo
)) {
PrintLastError("CryptDecodeObject(PKCS_UTC_TIME)");
goto CommonReturn;
}
if (cbInfo != sizeof(ftDecode))
printf("PKCS_UTC_TIME failed => unexpected decode length\n");
if (0 != memcmp(pftEncode, &ftDecode, sizeof(ftDecode)))
printf("PKCS_UTC_TIME failed => decode (%s) != encode input\n",
FileTimeText(&ftDecode));
CommonReturn:
if (pbEncoded)
TestFree(pbEncoded);
}
static void TestUtcTime()
{
FILETIME ft;
SYSTEMTIME t;
memset(&t, 0, sizeof(t));
t.wYear = 1950;
t.wMonth = 1;
t.wDay = 2;
t.wHour = 3;
t.wMinute = 4;
t.wSecond = 5;
if (!SystemTimeToFileTime(&t, &ft)) {
PrintLastError("SystemTimeToFileTime");
return;
}
TestUtcTime(&ft);
t.wYear = 2049;
if (!SystemTimeToFileTime(&t, &ft)) {
PrintLastError("SystemTimeToFileTime");
return;
}
TestUtcTime(&ft);
t.wMonth = 1;
t.wDay = 1;
t.wHour = 0;
t.wMinute = 0;
t.wSecond = 0;
if (!SystemTimeToFileTime(&t, &ft)) {
PrintLastError("SystemTimeToFileTime");
return;
}
TestUtcTime(&ft);
}
static void TestBadAltName(
PCERT_ALT_NAME_INFO pInfo,
DWORD dwEntryIndex,
DWORD dwValueIndex
)
{
DWORD cbEncoded;
printf("Test encode X509_ALTERNATE_NAME:: Bad Entry: %d Value: %d\n",
dwEntryIndex, dwValueIndex);
if (CryptEncodeObject(
dwCertEncodingType,
X509_ALTERNATE_NAME,
pInfo,
NULL, // pbEncoded
&cbEncoded
))
printf(" failed => expected error\n");
else {
DWORD dwErr = GetLastError();
if (CRYPT_E_INVALID_IA5_STRING != dwErr)
printf(" LastError failed => expected: 0x%x (%d), got: 0x%x (%d)\n",
CRYPT_E_INVALID_IA5_STRING, CRYPT_E_INVALID_IA5_STRING,
dwErr, dwErr);
if (dwEntryIndex != GET_CERT_ALT_NAME_ENTRY_ERR_INDEX(cbEncoded))
printf(" EntryIndex failed => expected: %d, got: %d\n",
dwEntryIndex, GET_CERT_ALT_NAME_ENTRY_ERR_INDEX(cbEncoded));
if (dwValueIndex != GET_CERT_ALT_NAME_VALUE_ERR_INDEX(cbEncoded))
printf(" ValueIndex failed => expected: %d, got: %d\n",
dwValueIndex, GET_CERT_ALT_NAME_VALUE_ERR_INDEX(cbEncoded));
}
}
static void TestBadAltName()
{
CERT_ALT_NAME_INFO AltNameInfo;
WORD rgwBadIA5[] = {0x30, 0x31, 0x32, 0x33, 0x80, 0x35, 0x00};
#define ALT_NAME_ENTRY_CNT 4
CERT_ALT_NAME_ENTRY rgAltNameEntry[ALT_NAME_ENTRY_CNT];
rgAltNameEntry[0].dwAltNameChoice = CERT_ALT_NAME_RFC822_NAME;
rgAltNameEntry[0].pwszRfc822Name = L"RFC822";
rgAltNameEntry[1].dwAltNameChoice = CERT_ALT_NAME_URL;
rgAltNameEntry[1].pwszURL = L"URL string";
rgAltNameEntry[2].dwAltNameChoice = CERT_ALT_NAME_URL;
rgAltNameEntry[2].pwszURL = rgwBadIA5;
rgAltNameEntry[3].dwAltNameChoice = CERT_ALT_NAME_RFC822_NAME;
rgAltNameEntry[3].pwszRfc822Name = L"RFC822";
AltNameInfo.cAltEntry = ALT_NAME_ENTRY_CNT;
AltNameInfo.rgAltEntry = rgAltNameEntry;
TestBadAltName(&AltNameInfo, 2, 4);
}
static void TestBadAuthorityInfoAccess(
PCERT_AUTHORITY_INFO_ACCESS pInfo,
DWORD dwEntryIndex,
DWORD dwValueIndex
)
{
DWORD cbEncoded;
printf("Test encode X509_AUTHORITY_INFO_ACCESS:: Bad Entry: %d Value: %d\n",
dwEntryIndex, dwValueIndex);
if (CryptEncodeObject(
dwCertEncodingType,
X509_AUTHORITY_INFO_ACCESS,
pInfo,
NULL, // pbEncoded
&cbEncoded
))
printf(" failed => expected error\n");
else {
DWORD dwErr = GetLastError();
if (CRYPT_E_INVALID_IA5_STRING != dwErr)
printf(" LastError failed => expected: 0x%x (%d), got: 0x%x (%d)\n",
CRYPT_E_INVALID_IA5_STRING, CRYPT_E_INVALID_IA5_STRING,
dwErr, dwErr);
if (dwEntryIndex != GET_CERT_ALT_NAME_ENTRY_ERR_INDEX(cbEncoded))
printf(" EntryIndex failed => expected: %d, got: %d\n",
dwEntryIndex, GET_CERT_ALT_NAME_ENTRY_ERR_INDEX(cbEncoded));
if (dwValueIndex != GET_CERT_ALT_NAME_VALUE_ERR_INDEX(cbEncoded))
printf(" ValueIndex failed => expected: %d, got: %d\n",
dwValueIndex, GET_CERT_ALT_NAME_VALUE_ERR_INDEX(cbEncoded));
}
}
static void TestBadAuthorityInfoAccess()
{
CERT_AUTHORITY_INFO_ACCESS AuthorityInfoAccess;
CERT_ACCESS_DESCRIPTION rgAccess[5];
WORD rgwBadIA5[] = {0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x80, 0x37, 0x00};
rgAccess[0].pszAccessMethod = szOID_PKIX_OCSP;
rgAccess[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
rgAccess[0].AccessLocation.pwszURL = L"URL to the stars";
rgAccess[1].pszAccessMethod = szOID_PKIX_OCSP;
rgAccess[1].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
rgAccess[1].AccessLocation.pwszURL = L"URL to the stars";
rgAccess[2].pszAccessMethod = szOID_PKIX_CA_ISSUERS;
rgAccess[2].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_RFC822_NAME;
rgAccess[2].AccessLocation.pwszRfc822Name = L"[email protected]";
rgAccess[3].pszAccessMethod = szOID_PKIX_OCSP;
rgAccess[3].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
rgAccess[3].AccessLocation.pwszURL = rgwBadIA5;
rgAccess[4].pszAccessMethod = szOID_PKIX_OCSP;
rgAccess[4].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
rgAccess[4].AccessLocation.pwszURL = L"URL to the POLICY";
AuthorityInfoAccess.cAccDescr = 5;
AuthorityInfoAccess.rgAccDescr = rgAccess;
TestBadAuthorityInfoAccess(&AuthorityInfoAccess, 3, 6);
}
static void TestBadAuthorityKeyId2(
PCERT_AUTHORITY_KEY_ID2_INFO pInfo,
DWORD dwEntryIndex,
DWORD dwValueIndex
)
{
DWORD cbEncoded;
printf("Test encode X509_AUTHORITY_KEY_ID2:: Bad Entry: %d Value: %d\n",
dwEntryIndex, dwValueIndex);
if (CryptEncodeObject(
dwCertEncodingType,
X509_AUTHORITY_KEY_ID2,
pInfo,
NULL, // pbEncoded
&cbEncoded
))
printf(" failed => expected error\n");
else {
DWORD dwErr = GetLastError();
if (CRYPT_E_INVALID_IA5_STRING != dwErr)
printf(" LastError failed => expected: 0x%x (%d), got: 0x%x (%d)\n",
CRYPT_E_INVALID_IA5_STRING, CRYPT_E_INVALID_IA5_STRING,
dwErr, dwErr);
if (dwEntryIndex != GET_CERT_ALT_NAME_ENTRY_ERR_INDEX(cbEncoded))
printf(" EntryIndex failed => expected: %d, got: %d\n",
dwEntryIndex, GET_CERT_ALT_NAME_ENTRY_ERR_INDEX(cbEncoded));
if (dwValueIndex != GET_CERT_ALT_NAME_VALUE_ERR_INDEX(cbEncoded))
printf(" ValueIndex failed => expected: %d, got: %d\n",
dwValueIndex, GET_CERT_ALT_NAME_VALUE_ERR_INDEX(cbEncoded));
}
}
static void TestBadAuthorityKeyId2()
{
CERT_AUTHORITY_KEY_ID2_INFO KeyId2Info;
WORD rgwBadIA5[] = {0x30, 0x31, 0x32, 0x33, 0x80, 0x35, 0x00};
#define KEY_ID_ALT_NAME_ENTRY_CNT 2
CERT_ALT_NAME_ENTRY rgAltNameEntry[KEY_ID_ALT_NAME_ENTRY_CNT];
rgAltNameEntry[0].dwAltNameChoice = CERT_ALT_NAME_RFC822_NAME;
rgAltNameEntry[0].pwszRfc822Name = L"RFC822";
rgAltNameEntry[1].dwAltNameChoice = CERT_ALT_NAME_URL;
rgAltNameEntry[1].pwszURL = rgwBadIA5;
memset(&KeyId2Info, 0, sizeof(KeyId2Info));
KeyId2Info.AuthorityCertIssuer.cAltEntry = KEY_ID_ALT_NAME_ENTRY_CNT;
KeyId2Info.AuthorityCertIssuer.rgAltEntry = rgAltNameEntry;
TestBadAuthorityKeyId2(&KeyId2Info, 1, 4);
}
static void TestBadNameConstraints(
PCERT_NAME_CONSTRAINTS_INFO pInfo,
DWORD dwEntryIndex,
DWORD dwValueIndex,
BOOL fExcludedSubtree
)
{
DWORD cbEncoded;
printf("Test encode NAME_CONSTRAINTS:: Bad Entry: %d Value: %d fExcluded: %d\n",
dwEntryIndex, dwValueIndex, fExcludedSubtree);
if (CryptEncodeObject(
dwCertEncodingType,
X509_NAME_CONSTRAINTS,
pInfo,
NULL, // pbEncoded
&cbEncoded
))
printf(" failed => expected error\n");
else {
DWORD dwErr = GetLastError();
if (CRYPT_E_INVALID_IA5_STRING != dwErr)
printf(" LastError failed => expected: 0x%x (%d), got: 0x%x (%d)\n",
CRYPT_E_INVALID_IA5_STRING, CRYPT_E_INVALID_IA5_STRING,
dwErr, dwErr);
if (dwEntryIndex != GET_CERT_ALT_NAME_ENTRY_ERR_INDEX(cbEncoded))
printf(" EntryIndex failed => expected: %d, got: %d\n",
dwEntryIndex, GET_CERT_ALT_NAME_ENTRY_ERR_INDEX(cbEncoded));
if (dwValueIndex != GET_CERT_ALT_NAME_VALUE_ERR_INDEX(cbEncoded))
printf(" ValueIndex failed => expected: %d, got: %d\n",
dwValueIndex, GET_CERT_ALT_NAME_VALUE_ERR_INDEX(cbEncoded));
if (fExcludedSubtree != IS_CERT_EXCLUDED_SUBTREE(cbEncoded))
printf(" fExcludedSubtree failed => expected: %d, got: %d\n",
fExcludedSubtree, IS_CERT_EXCLUDED_SUBTREE(cbEncoded));
}
}
static void TestBadNameConstraints()
{
CERT_NAME_CONSTRAINTS_INFO Info;
WORD rgwBadIA5[] = {0x30, 0x31, 0x32, 0x33, 0x80, 0x35, 0x00};
#define NAME_CONSTRAINTS_SUBTREE_CNT 2
CERT_GENERAL_SUBTREE rgSubtree[NAME_CONSTRAINTS_SUBTREE_CNT];
memset(rgSubtree, 0, sizeof(rgSubtree));
rgSubtree[0].Base.dwAltNameChoice = CERT_ALT_NAME_RFC822_NAME;
rgSubtree[0].Base.pwszRfc822Name = L"RFC822";
rgSubtree[1].Base.dwAltNameChoice = CERT_ALT_NAME_URL;
rgSubtree[1].Base.pwszURL = rgwBadIA5;
memset(&Info, 0, sizeof(Info));
Info.cPermittedSubtree = NAME_CONSTRAINTS_SUBTREE_CNT;
Info.rgPermittedSubtree = rgSubtree;
TestBadNameConstraints(&Info, 1, 4, FALSE);
memset(&Info, 0, sizeof(Info));
Info.cExcludedSubtree = NAME_CONSTRAINTS_SUBTREE_CNT;
Info.rgExcludedSubtree = rgSubtree;
TestBadNameConstraints(&Info, 1, 4, TRUE);
}
static void TestBadIssuingDistPoint(
PCRL_ISSUING_DIST_POINT pInfo,
DWORD dwEntryIndex,
DWORD dwValueIndex
)
{
DWORD cbEncoded;
printf("Test encode ISSUING_DIST_POINT:: Bad Entry: %d Value: %d\n",
dwEntryIndex, dwValueIndex);
if (CryptEncodeObject(
dwCertEncodingType,
X509_ISSUING_DIST_POINT,
pInfo,
NULL, // pbEncoded
&cbEncoded
))
printf(" failed => expected error\n");
else {
DWORD dwErr = GetLastError();
if (CRYPT_E_INVALID_IA5_STRING != dwErr)
printf(" LastError failed => expected: 0x%x (%d), got: 0x%x (%d)\n",
CRYPT_E_INVALID_IA5_STRING, CRYPT_E_INVALID_IA5_STRING,
dwErr, dwErr);
if (dwEntryIndex != GET_CERT_ALT_NAME_ENTRY_ERR_INDEX(cbEncoded))
printf(" EntryIndex failed => expected: %d, got: %d\n",
dwEntryIndex, GET_CERT_ALT_NAME_ENTRY_ERR_INDEX(cbEncoded));
if (dwValueIndex != GET_CERT_ALT_NAME_VALUE_ERR_INDEX(cbEncoded))
printf(" ValueIndex failed => expected: %d, got: %d\n",
dwValueIndex, GET_CERT_ALT_NAME_VALUE_ERR_INDEX(cbEncoded));
}
}
static void TestBadIssuingDistPoint()
{
CRL_ISSUING_DIST_POINT Info;
WORD rgwBadIA5[] = {0x30, 0x31, 0x32, 0x33, 0x80, 0x35, 0x00};
#define IDP_ALT_NAME_ENTRY_CNT 2
CERT_ALT_NAME_ENTRY rgAltNameEntry[IDP_ALT_NAME_ENTRY_CNT];
rgAltNameEntry[0].dwAltNameChoice = CERT_ALT_NAME_RFC822_NAME;
rgAltNameEntry[0].pwszRfc822Name = L"RFC822";
rgAltNameEntry[1].dwAltNameChoice = CERT_ALT_NAME_URL;
rgAltNameEntry[1].pwszURL = rgwBadIA5;
memset(&Info, 0, sizeof(Info));
Info.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
Info.DistPointName.FullName.cAltEntry = IDP_ALT_NAME_ENTRY_CNT;
Info.DistPointName.FullName.rgAltEntry = rgAltNameEntry;
TestBadIssuingDistPoint(&Info, 1, 4);
}
static void TestCryptExportPublicKeyInfo()
{
BOOL fResult;
LPCSTR pszResult;
HCRYPTPROV hProv = 0;
PCERT_PUBLIC_KEY_INFO pCorrectInfo = NULL;
DWORD cbCorrectInfo;
PCERT_PUBLIC_KEY_INFO pInfo = NULL;
DWORD cbInfo;
DWORD cbTotal;
printf("\n");
if (0 == (hProv = GetCryptProv()))
goto ErrorReturn;
// Test: cbInfo == correct length
if (!CryptExportPublicKeyInfo(
hProv,
AT_SIGNATURE,
dwCertEncodingType,
NULL, // pInfo
&cbCorrectInfo
)) {
PrintLastError("CryptExportPublicKeyInfo(pInfo == NULL)");
goto ErrorReturn;
}
if (NULL == (pCorrectInfo = (PCERT_PUBLIC_KEY_INFO) TestAlloc(
cbCorrectInfo)))
goto ErrorReturn;
cbTotal = cbCorrectInfo + DELTA_MORE_LENGTH;
if (NULL == (pInfo = (PCERT_PUBLIC_KEY_INFO) TestAlloc(cbTotal)))
goto ErrorReturn;
memset(pCorrectInfo, 0, cbCorrectInfo);
if (!CryptExportPublicKeyInfo(
hProv,
AT_SIGNATURE,
dwCertEncodingType,
pCorrectInfo,
&cbCorrectInfo
)) {
PrintLastError("CryptExportPublicKeyInfo(cbInfo == correct length)");
goto ErrorReturn;
}
printf("For cbInfo == correct length\n");
printf("Info Length = %d (0x%x) Content::\n",
cbCorrectInfo, cbCorrectInfo);
PrintBytes(" ", (BYTE *)pCorrectInfo, cbCorrectInfo);
// Test: cbInfo < correct length
printf("\n");
memset(pInfo, 0, cbTotal);
cbInfo = cbCorrectInfo - DELTA_LESS_LENGTH;
fResult = CryptExportPublicKeyInfo(
hProv,
AT_SIGNATURE,
dwCertEncodingType,
pInfo,
&cbInfo
);
if (fResult) {
pszResult = "TRUE";
printf("failed => CryptExportPublicKeyInfo(cbInfo < correct length) returned success\n");
} else {
DWORD dwErr = GetLastError();
pszResult = "FALSE";
if (0 == dwErr)
printf("failed => CryptExportPublicKey(cbInfo < correct length) LastError == 0\n");
else
printf(
"CryptExportPublicKey(cbInfo < correct length) LastError = 0x%x (%d)\n",
dwErr, dwErr);
}
printf("For cbInfo < correct length, fResult = %s\n", pszResult);
printf("Info Length = %d (0x%x) Content::\n", cbInfo, cbInfo);
PrintBytes(" ", (BYTE *) pInfo, cbTotal);
if (cbInfo != cbCorrectInfo)
printf("failed => for cbInfo < correct length:: wrong cbInfo\n");
// Test: cbInfo > correct length
printf("\n");
memset(pInfo, 0, cbTotal);
cbInfo = cbTotal;
fResult = CryptExportPublicKeyInfo(
hProv,
AT_SIGNATURE,
dwCertEncodingType,
pInfo,
&cbInfo
);
if (fResult)
pszResult = "TRUE";
else {
pszResult = "FALSE";
PrintLastError("CryptExportPublicKeyInfo(cbInfo > correct length)");
}
printf("For cbInfo > correct length, fResult = %s\n", pszResult);
printf("Info Length = %d (0x%x) Content::\n", cbInfo, cbInfo);
PrintBytes(" ", (BYTE *) pInfo, cbTotal);
if (cbInfo != cbCorrectInfo)
printf("failed => for cbInfo > correct length:: wrong cbInfo\n");
// Test: pInfo != NULL, cbInfo == 0
printf("\n");
memset(pInfo, 0, cbTotal);
cbInfo = 0;
fResult = CryptExportPublicKeyInfo(
hProv,
AT_SIGNATURE,
dwCertEncodingType,
pInfo,
&cbInfo
);
if (fResult) {
pszResult = "TRUE";
printf("failed => CryptExportPublicKeyInfo(pInfo != NULL, cbInfo == 0) returned success\n");
} else {
DWORD dwErr = GetLastError();
pszResult = "FALSE";
if (0 == dwErr)
printf("failed => CryptExportPublicKeyInfo(pInfo != NULL, cbInfo == 0) LastError == 0\n");
else
printf(
"CryptExportPublicKeyInfo(pInfo != NULL, cbInfo == 0) LastError = 0x%x (%d)\n",
dwErr, dwErr);
}
printf("For pInfo != NULL, cbInfo == 0, fResult = %s\n", pszResult);
printf("Info Length = %d (0x%x) Content::\n", cbInfo, cbInfo);
PrintBytes(" ", (BYTE *) pInfo, cbTotal);
CommonReturn:
if (pInfo)
TestFree(pInfo);
if (pCorrectInfo)
TestFree(pCorrectInfo);
if (hProv)
CryptReleaseContext(hProv, 0);
return;
ErrorReturn:
goto CommonReturn;
}
//+-------------------------------------------------------------------------
// Compare 2 CRYPT_DATA_BLOB structs.
//
// Returns: FALSE iff differ
//--------------------------------------------------------------------------
BOOL
WINAPI
EqualCryptDataBlob(
IN PCRYPT_DATA_BLOB p1,
IN PCRYPT_DATA_BLOB p2)
{
if (p1->cbData != p2->cbData)
return FALSE;
if (p1->cbData == 0)
return TRUE;
return (0 == memcmp(p1->pbData, p2->pbData, p1->cbData));
}
//+-------------------------------------------------------------------------
// Compare 2 CRYPT_ATTRIBUTE structs.
//
// Returns: FALSE iff differ
//--------------------------------------------------------------------------
BOOL
WINAPI
EqualAttribute(
IN PCRYPT_ATTRIBUTE patr1,
IN PCRYPT_ATTRIBUTE patr2)
{
BOOL fRet;
DWORD i;
PCRYPT_ATTR_BLOB pabl1;
PCRYPT_ATTR_BLOB pabl2;
fRet = (0 == strcmp( patr1->pszObjId, patr2->pszObjId));
fRet &= (patr1->cValue == patr2->cValue);
if (fRet) {
for (i=patr1->cValue, pabl1=patr1->rgValue, pabl2=patr2->rgValue;
i>0;
i--, pabl1++, pabl2++) {
fRet &= (pabl1->cbData == pabl2->cbData);
if (fRet) {
fRet &= (0 == memcmp( pabl1->pbData,
pabl2->pbData,
pabl1->cbData));
}
}
}
return fRet;
}
static void TestCmcData()
{
BOOL fResult;
BYTE *pbEncoded = NULL;
DWORD cbEncoded;
PCMC_DATA_INFO pInfo = NULL;
CMC_DATA_INFO CmcData;
BYTE rgb0[] = {0x2, 0x2, 0x11, 0x22}; // INTEGER
BYTE rgb1[] = {0x4, 0x5, 0x11, 0x22, 0x33, 0x44, 0x55}; // OCTET STRING
BYTE rgb2[] = {0x30, 0x0}; // Empty SEQUENCE
CRYPT_ATTR_BLOB rgValue[3] = {
sizeof(rgb0), rgb0,
sizeof(rgb1), rgb1,
sizeof(rgb2), rgb2
};
CMC_TAGGED_ATTRIBUTE rgTagAttr[2];
CMC_TAGGED_CERT_REQUEST rgTagCertReq[3];
CMC_TAGGED_REQUEST rgTagReq[3];
CMC_TAGGED_CONTENT_INFO rgTagContentInfo[2];
CMC_TAGGED_OTHER_MSG rgTagOtherMsg[2];
DWORD i;
rgTagAttr[0].dwBodyPartID = 0x7FFFFFFF;
rgTagAttr[0].Attribute.pszObjId = "1.2.3.4";
rgTagAttr[0].Attribute.cValue = 2;
rgTagAttr[0].Attribute.rgValue = rgValue;
rgTagAttr[1].dwBodyPartID = 0x80000001;
rgTagAttr[1].Attribute.pszObjId = "1.2.3.5";
rgTagAttr[1].Attribute.cValue = 0;
rgTagAttr[1].Attribute.rgValue = NULL;
CmcData.cTaggedAttribute = 2;
CmcData.rgTaggedAttribute = rgTagAttr;
rgTagCertReq[0].dwBodyPartID = 0x12345678;
rgTagCertReq[0].SignedCertRequest = rgValue[0];
rgTagCertReq[1].dwBodyPartID = 0x87654321;
rgTagCertReq[1].SignedCertRequest = rgValue[1];
rgTagCertReq[2].dwBodyPartID = 0x1;
rgTagCertReq[2].SignedCertRequest = rgValue[2];
rgTagReq[0].dwTaggedRequestChoice = CMC_TAGGED_CERT_REQUEST_CHOICE;
rgTagReq[0].pTaggedCertRequest = &rgTagCertReq[0];
rgTagReq[1].dwTaggedRequestChoice = CMC_TAGGED_CERT_REQUEST_CHOICE;
rgTagReq[1].pTaggedCertRequest = &rgTagCertReq[1];
rgTagReq[2].dwTaggedRequestChoice = CMC_TAGGED_CERT_REQUEST_CHOICE;
rgTagReq[2].pTaggedCertRequest = &rgTagCertReq[2];
CmcData.cTaggedRequest = 3;
CmcData.rgTaggedRequest = rgTagReq;
rgTagContentInfo[0].dwBodyPartID = 2;
rgTagContentInfo[0].EncodedContentInfo = rgValue[0];
rgTagContentInfo[1].dwBodyPartID = 3;
rgTagContentInfo[1].EncodedContentInfo = rgValue[2];
CmcData.cTaggedContentInfo = 2;
CmcData.rgTaggedContentInfo = rgTagContentInfo;
rgTagOtherMsg[0].dwBodyPartID = 14;
rgTagOtherMsg[0].pszObjId = "1.2.44.55.66";
rgTagOtherMsg[0].Value = rgValue[0];
rgTagOtherMsg[1].dwBodyPartID = 15;
rgTagOtherMsg[1].pszObjId = "1.2.44.55.66.77";
rgTagOtherMsg[1].Value = rgValue[1];
CmcData.cTaggedOtherMsg = 2;
CmcData.rgTaggedOtherMsg = rgTagOtherMsg;
printf("Test encode/decode CMC_DATA\n");
if (!AllocAndEncodeObject(
CMC_DATA,
&CmcData,
&pbEncoded,
&cbEncoded))
goto CommonReturn;
if (NULL == (pInfo =
(PCMC_DATA_INFO) AllocAndDecodeObject(
CMC_DATA,
pbEncoded,
cbEncoded
))) goto CommonReturn;
if (pInfo->cTaggedAttribute != CmcData.cTaggedAttribute ||
pInfo->cTaggedRequest != CmcData.cTaggedRequest ||
pInfo->cTaggedContentInfo != CmcData.cTaggedContentInfo ||
pInfo->cTaggedOtherMsg != CmcData.cTaggedOtherMsg) {
printf("CMC_DATA failed => invalid decoded tag counts\n");
goto CommonReturn;
}
for (i = 0; i < CmcData.cTaggedAttribute; i++) {
if (CmcData.rgTaggedAttribute[i].dwBodyPartID !=
pInfo->rgTaggedAttribute[i].dwBodyPartID ||
!EqualAttribute(&CmcData.rgTaggedAttribute[i].Attribute,
&pInfo->rgTaggedAttribute[i].Attribute)) {
printf("CMC_DATA failed => invalid decoded tagged attribute\n");
goto CommonReturn;
}
}
for (i = 0; i < CmcData.cTaggedRequest; i++) {
PCMC_TAGGED_CERT_REQUEST pEncodeTagReq;
PCMC_TAGGED_CERT_REQUEST pDecodeTagReq;
if (CMC_TAGGED_CERT_REQUEST_CHOICE !=
pInfo->rgTaggedRequest[i].dwTaggedRequestChoice) {
printf("CMC_DATA failed => invalid decoded tagged request\n");
goto CommonReturn;
}
pEncodeTagReq = CmcData.rgTaggedRequest[i].pTaggedCertRequest;
pDecodeTagReq = pInfo->rgTaggedRequest[i].pTaggedCertRequest;
if (pEncodeTagReq->dwBodyPartID != pDecodeTagReq->dwBodyPartID ||
!EqualCryptDataBlob(&pEncodeTagReq->SignedCertRequest,
&pDecodeTagReq->SignedCertRequest)) {
printf("CMC_DATA failed => invalid decoded tagged request\n");
goto CommonReturn;
}
}
for (i = 0; i < CmcData.cTaggedContentInfo; i++) {
if (CmcData.rgTaggedContentInfo[i].dwBodyPartID !=
pInfo->rgTaggedContentInfo[i].dwBodyPartID ||
!EqualCryptDataBlob(
&CmcData.rgTaggedContentInfo[i].EncodedContentInfo,
&pInfo->rgTaggedContentInfo[i].EncodedContentInfo)) {
printf("CMC_DATA failed => invalid decoded tagged ContentInfo\n");
goto CommonReturn;
}
}
for (i = 0; i < CmcData.cTaggedOtherMsg; i++) {
if (CmcData.rgTaggedOtherMsg[i].dwBodyPartID !=
pInfo->rgTaggedOtherMsg[i].dwBodyPartID ||
0 != strcmp(CmcData.rgTaggedOtherMsg[i].pszObjId,
pInfo->rgTaggedOtherMsg[i].pszObjId) ||
!EqualCryptDataBlob(&CmcData.rgTaggedOtherMsg[i].Value,
&pInfo->rgTaggedOtherMsg[i].Value)) {
printf("CMC_DATA failed => invalid decoded tagged OtherMsg\n");
goto CommonReturn;
}
}
TestFree(pbEncoded);
pbEncoded = NULL;
TestFree(pInfo);
pInfo = NULL;
// Do and encode/decode without any tagged entries
memset(&CmcData, 0, sizeof(CmcData));
printf("Test encode/decode CMC_DATA(No Tagged Entries)\n");
if (!AllocAndEncodeObject(
CMC_DATA,
&CmcData,
&pbEncoded,
&cbEncoded))
goto CommonReturn;
if (NULL == (pInfo =
(PCMC_DATA_INFO) AllocAndDecodeObject(
CMC_DATA,
pbEncoded,
cbEncoded
))) goto CommonReturn;
if (pInfo->cTaggedAttribute != 0 ||
pInfo->cTaggedRequest != 0 ||
pInfo->cTaggedContentInfo != 0 ||
pInfo->cTaggedOtherMsg != 0) {
printf("CMC_DATA failed => invalid decoded tag counts\n");
goto CommonReturn;
}
CommonReturn:
if (pbEncoded)
TestFree(pbEncoded);
if (pInfo)
TestFree(pInfo);
}
static void TestCmcResponse()
{
BOOL fResult;
BYTE *pbEncoded = NULL;
DWORD cbEncoded;
PCMC_RESPONSE_INFO pInfo = NULL;
CMC_RESPONSE_INFO CmcResponse;
BYTE rgb0[] = {0x2, 0x2, 0x11, 0x22}; // INTEGER
BYTE rgb1[] = {0x4, 0x5, 0x11, 0x22, 0x33, 0x44, 0x55}; // OCTET STRING
BYTE rgb2[] = {0x30, 0x0}; // Empty SEQUENCE
CRYPT_ATTR_BLOB rgValue[3] = {
sizeof(rgb0), rgb0,
sizeof(rgb1), rgb1,
sizeof(rgb2), rgb2
};
CMC_TAGGED_ATTRIBUTE rgTagAttr[2];
CMC_TAGGED_CONTENT_INFO rgTagContentInfo[2];
CMC_TAGGED_OTHER_MSG rgTagOtherMsg[2];
DWORD i;
rgTagAttr[0].dwBodyPartID = 0x7FFFFFFF;
rgTagAttr[0].Attribute.pszObjId = "1.2.3.4";
rgTagAttr[0].Attribute.cValue = 2;
rgTagAttr[0].Attribute.rgValue = rgValue;
rgTagAttr[1].dwBodyPartID = 0x80000001;
rgTagAttr[1].Attribute.pszObjId = "1.2.3.5";
rgTagAttr[1].Attribute.cValue = 0;
rgTagAttr[1].Attribute.rgValue = NULL;
CmcResponse.cTaggedAttribute = 2;
CmcResponse.rgTaggedAttribute = rgTagAttr;
rgTagContentInfo[0].dwBodyPartID = 2;
rgTagContentInfo[0].EncodedContentInfo = rgValue[0];
rgTagContentInfo[1].dwBodyPartID = 3;
rgTagContentInfo[1].EncodedContentInfo = rgValue[2];
CmcResponse.cTaggedContentInfo = 2;
CmcResponse.rgTaggedContentInfo = rgTagContentInfo;
rgTagOtherMsg[0].dwBodyPartID = 14;
rgTagOtherMsg[0].pszObjId = "1.2.44.55.66";
rgTagOtherMsg[0].Value = rgValue[0];
rgTagOtherMsg[1].dwBodyPartID = 15;
rgTagOtherMsg[1].pszObjId = "1.2.44.55.66.77";
rgTagOtherMsg[1].Value = rgValue[1];
CmcResponse.cTaggedOtherMsg = 2;
CmcResponse.rgTaggedOtherMsg = rgTagOtherMsg;
printf("Test encode/decode CMC_RESPONSE\n");
if (!AllocAndEncodeObject(
CMC_RESPONSE,
&CmcResponse,
&pbEncoded,
&cbEncoded))
goto CommonReturn;
if (NULL == (pInfo =
(PCMC_RESPONSE_INFO) AllocAndDecodeObject(
CMC_RESPONSE,
pbEncoded,
cbEncoded
))) goto CommonReturn;
if (pInfo->cTaggedAttribute != CmcResponse.cTaggedAttribute ||
pInfo->cTaggedContentInfo != CmcResponse.cTaggedContentInfo ||
pInfo->cTaggedOtherMsg != CmcResponse.cTaggedOtherMsg) {
printf("CMC_RESPONSE failed => invalid decoded tag counts\n");
goto CommonReturn;
}
for (i = 0; i < CmcResponse.cTaggedAttribute; i++) {
if (CmcResponse.rgTaggedAttribute[i].dwBodyPartID !=
pInfo->rgTaggedAttribute[i].dwBodyPartID ||
!EqualAttribute(&CmcResponse.rgTaggedAttribute[i].Attribute,
&pInfo->rgTaggedAttribute[i].Attribute)) {
printf("CMC_RESPONSE failed => invalid decoded tagged attribute\n");
goto CommonReturn;
}
}
for (i = 0; i < CmcResponse.cTaggedContentInfo; i++) {
if (CmcResponse.rgTaggedContentInfo[i].dwBodyPartID !=
pInfo->rgTaggedContentInfo[i].dwBodyPartID ||
!EqualCryptDataBlob(
&CmcResponse.rgTaggedContentInfo[i].EncodedContentInfo,
&pInfo->rgTaggedContentInfo[i].EncodedContentInfo)) {
printf("CMC_RESPONSE failed => invalid decoded tagged ContentInfo\n");
goto CommonReturn;
}
}
for (i = 0; i < CmcResponse.cTaggedOtherMsg; i++) {
if (CmcResponse.rgTaggedOtherMsg[i].dwBodyPartID !=
pInfo->rgTaggedOtherMsg[i].dwBodyPartID ||
0 != strcmp(CmcResponse.rgTaggedOtherMsg[i].pszObjId,
pInfo->rgTaggedOtherMsg[i].pszObjId) ||
!EqualCryptDataBlob(&CmcResponse.rgTaggedOtherMsg[i].Value,
&pInfo->rgTaggedOtherMsg[i].Value)) {
printf("CMC_RESPONSE failed => invalid decoded tagged OtherMsg\n");
goto CommonReturn;
}
}
CommonReturn:
if (pbEncoded)
TestFree(pbEncoded);
if (pInfo)
TestFree(pInfo);
}
static void TestCmcStatus(
DWORD dwOtherInfoChoice
)
{
BOOL fResult;
BYTE *pbEncoded = NULL;
DWORD cbEncoded;
PCMC_STATUS_INFO pInfo = NULL;
CMC_STATUS_INFO CmcStatus;
DWORD rgdwBodyList[3] = {0x80000000, 0x7FFFFFFF, 0x123 };
BYTE rgbPendToken[] = {1,2,3,4,5};
CMC_PEND_INFO PendInfo;
SYSTEMTIME t;
DWORD i;
CmcStatus.dwStatus = 0x12345678;
CmcStatus.cBodyList = 3;
CmcStatus.rgdwBodyList = rgdwBodyList;
switch (dwOtherInfoChoice) {
case CMC_OTHER_INFO_FAIL_CHOICE:
CmcStatus.pwszStatusString = L"\0";
CmcStatus.dwOtherInfoChoice = CMC_OTHER_INFO_FAIL_CHOICE;
CmcStatus.dwFailInfo = 0x11223344;
break;
case CMC_OTHER_INFO_PEND_CHOICE:
CmcStatus.pwszStatusString = L"Status String";
CmcStatus.dwOtherInfoChoice = CMC_OTHER_INFO_PEND_CHOICE;
CmcStatus.pPendInfo = &PendInfo;
PendInfo.PendToken.cbData = sizeof(rgbPendToken);
PendInfo.PendToken.pbData = rgbPendToken;
memset(&t, 0, sizeof(t));
t.wYear = 2000;
t.wMonth = 1;
t.wDay = 2;
t.wHour = 3;
t.wMinute = 4;
t.wSecond = 5;
t.wMilliseconds = 678;
if (!SystemTimeToFileTime(&t, &PendInfo.PendTime)) {
PrintLastError("SystemTimeToFileTime");
return;
}
break;
case CMC_OTHER_INFO_NO_CHOICE:
default:
CmcStatus.pwszStatusString = NULL;
CmcStatus.dwOtherInfoChoice = CMC_OTHER_INFO_NO_CHOICE;
CmcStatus.cBodyList = 0;
CmcStatus.rgdwBodyList = NULL;
}
printf("Test encode/decode CMC_STATUS(OtherInfoChoice:%d)\n",
dwOtherInfoChoice);
if (!AllocAndEncodeObject(
CMC_STATUS,
&CmcStatus,
&pbEncoded,
&cbEncoded))
goto CommonReturn;
if (NULL == (pInfo =
(PCMC_STATUS_INFO) AllocAndDecodeObject(
CMC_STATUS,
pbEncoded,
cbEncoded
))) goto CommonReturn;
if (CmcStatus.dwStatus != pInfo->dwStatus ||
CmcStatus.cBodyList != pInfo->cBodyList ||
CmcStatus.dwOtherInfoChoice != pInfo->dwOtherInfoChoice) {
printf("CMC_STATUS failed => encode/decode mismatch\n");
goto CommonReturn;
}
switch (CmcStatus.dwOtherInfoChoice) {
case CMC_OTHER_INFO_FAIL_CHOICE:
if (pInfo->pwszStatusString != NULL)
printf("CMC_STATUS failed => expected NULL StatusString\n");
if (CmcStatus.dwFailInfo != pInfo->dwFailInfo)
printf("CMC_STATUS failed => bad FailInfo\n");
break;
case CMC_OTHER_INFO_PEND_CHOICE:
{
PCMC_PEND_INFO pEncodePendInfo;
PCMC_PEND_INFO pDecodePendInfo;
if (pInfo->pwszStatusString == NULL ||
0 != wcscmp(CmcStatus.pwszStatusString,
pInfo->pwszStatusString))
printf("CMC_STATUS failed => bad StatusString\n");
pEncodePendInfo = CmcStatus.pPendInfo;
pDecodePendInfo = pInfo->pPendInfo;
if (!EqualCryptDataBlob(
&pEncodePendInfo->PendToken,
&pDecodePendInfo->PendToken))
printf("CMC_STATUS failed => bad PendToken\n");
if (0 != memcmp(&pEncodePendInfo->PendTime,
&pDecodePendInfo->PendTime,
sizeof(pDecodePendInfo->PendTime)))
printf("CMC_STATUS failed => bad PendTime\n");
}
break;
case CMC_OTHER_INFO_NO_CHOICE:
default:
if (pInfo->pwszStatusString != NULL)
printf("CMC_STATUS failed => expected NULL StatusString\n");
}
for (i = 0; i < CmcStatus.cBodyList; i++) {
if (CmcStatus.rgdwBodyList[i] != pInfo->rgdwBodyList[i]) {
printf("CMC_STATUS failed => invalid decoded tagged BodyList\n");
goto CommonReturn;
}
}
CommonReturn:
if (pbEncoded)
TestFree(pbEncoded);
if (pInfo)
TestFree(pInfo);
}
static void TestCmcAddExtensions()
{
BOOL fResult;
BYTE *pbEncoded = NULL;
DWORD cbEncoded;
PCMC_ADD_EXTENSIONS_INFO pInfo = NULL;
CMC_ADD_EXTENSIONS_INFO CmcAddExtensions;
DWORD rgdwCertReference[3] = {0x80000000, 0x7FFFFFFF, 0x123 };
BYTE rgbExt[] = {0x1, 0x2, 0x3};
CERT_EXTENSION rgExt[2] = {
"1.2.3.4.5", TRUE, sizeof(rgbExt), rgbExt,
"1.2.3.6.7", FALSE, sizeof(rgbExt), rgbExt
};
DWORD i;
CmcAddExtensions.dwCmcDataReference = 0x12345678;
CmcAddExtensions.cCertReference = 3;
CmcAddExtensions.rgdwCertReference = rgdwCertReference;
CmcAddExtensions.cExtension = 2;
CmcAddExtensions.rgExtension = rgExt;
printf("Test encode/decode CMC_ADD_EXTENSIONS\n");
if (!AllocAndEncodeObject(
CMC_ADD_EXTENSIONS,
&CmcAddExtensions,
&pbEncoded,
&cbEncoded))
goto CommonReturn;
if (NULL == (pInfo =
(PCMC_ADD_EXTENSIONS_INFO) AllocAndDecodeObject(
CMC_ADD_EXTENSIONS,
pbEncoded,
cbEncoded
))) goto CommonReturn;
if (CmcAddExtensions.dwCmcDataReference != pInfo->dwCmcDataReference ||
CmcAddExtensions.cCertReference != pInfo->cCertReference ||
CmcAddExtensions.cExtension != pInfo->cExtension) {
printf("CMC_ADD_EXTENSIONS failed => encode/decode mismatch\n");
goto CommonReturn;
}
for (i = 0; i < CmcAddExtensions.cCertReference; i++) {
if (CmcAddExtensions.rgdwCertReference[i] !=
pInfo->rgdwCertReference[i]) {
printf("CMC_ADD_EXTENSIONS failed => invalid decoded CertReference\n");
goto CommonReturn;
}
}
for (i = 0; i < CmcAddExtensions.cExtension; i++) {
PCERT_EXTENSION pEncodeExt = &CmcAddExtensions.rgExtension[i];
PCERT_EXTENSION pDecodeExt = &pInfo->rgExtension[i];
if (0 != strcmp(pEncodeExt->pszObjId, pDecodeExt->pszObjId) ||
pEncodeExt->fCritical != pDecodeExt->fCritical ||
!EqualCryptDataBlob(&pEncodeExt->Value, &pEncodeExt->Value)) {
printf("CMC_ADD_EXTENSIONS failed => invalid decoded Extensions\n");
goto CommonReturn;
}
}
CommonReturn:
if (pbEncoded)
TestFree(pbEncoded);
if (pInfo)
TestFree(pInfo);
}
static void TestCmcAddAttributes()
{
BOOL fResult;
BYTE *pbEncoded = NULL;
DWORD cbEncoded;
PCMC_ADD_ATTRIBUTES_INFO pInfo = NULL;
CMC_ADD_ATTRIBUTES_INFO CmcAddAttributes;
DWORD rgdwCertReference[3] = {0x80000000, 0x7FFFFFFF, 0x123 };
BYTE rgb0[] = {0x2, 0x2, 0x11, 0x22}; // INTEGER
BYTE rgb1[] = {0x4, 0x5, 0x11, 0x22, 0x33, 0x44, 0x55}; // OCTET STRING
CRYPT_ATTR_BLOB rgValue[2] = {
sizeof(rgb0), rgb0,
sizeof(rgb1), rgb1
};
CRYPT_ATTRIBUTE rgAttr[3] = {
"1.2.3.6.8", 0, NULL,
"1.2.3.6.7", 1, rgValue,
"1.2.3.4.5", 2, rgValue,
};
DWORD i;
CmcAddAttributes.dwCmcDataReference = 0x12345678;
CmcAddAttributes.cCertReference = 3;
CmcAddAttributes.rgdwCertReference = rgdwCertReference;
CmcAddAttributes.cAttribute = 3;
CmcAddAttributes.rgAttribute = rgAttr;
printf("Test encode/decode CMC_ADD_ATTRIBUTES\n");
if (!AllocAndEncodeObject(
CMC_ADD_ATTRIBUTES,
&CmcAddAttributes,
&pbEncoded,
&cbEncoded))
goto CommonReturn;
if (NULL == (pInfo =
(PCMC_ADD_ATTRIBUTES_INFO) AllocAndDecodeObject(
CMC_ADD_ATTRIBUTES,
pbEncoded,
cbEncoded
))) goto CommonReturn;
if (CmcAddAttributes.dwCmcDataReference != pInfo->dwCmcDataReference ||
CmcAddAttributes.cCertReference != pInfo->cCertReference ||
CmcAddAttributes.cAttribute != pInfo->cAttribute) {
printf("CMC_ADD_ATTRIBUTES failed => encode/decode mismatch\n");
goto CommonReturn;
}
for (i = 0; i < CmcAddAttributes.cCertReference; i++) {
if (CmcAddAttributes.rgdwCertReference[i] !=
pInfo->rgdwCertReference[i]) {
printf("CMC_ADD_ATTRIBUTES failed => invalid decoded CertReference\n");
goto CommonReturn;
}
}
for (i = 0; i < CmcAddAttributes.cAttribute; i++) {
PCRYPT_ATTRIBUTE pEncodeAttr = &CmcAddAttributes.rgAttribute[i];
PCRYPT_ATTRIBUTE pDecodeAttr = &pInfo->rgAttribute[i];
if (!EqualAttribute(pEncodeAttr, pDecodeAttr))
printf("CMC_ADD_ATTRIBUTES failed => invalid decoded Attributes\n");
}
CommonReturn:
if (pbEncoded)
TestFree(pbEncoded);
if (pInfo)
TestFree(pInfo);
}
static void TestCertTemplate()
{
BOOL fResult;
BYTE *pbEncoded = NULL;
DWORD cbEncoded;
PCERT_TEMPLATE_EXT pInfo = NULL;
CERT_TEMPLATE_EXT CertTemplate;
CertTemplate.pszObjId = "1.2.3.4.5.6.7.8.9";
CertTemplate.dwMajorVersion = 0x11223344;
CertTemplate.fMinorVersion = FALSE;
printf("Test encode/decode X509_CERTIFICATE_TEMPLATE\n");
if (!AllocAndEncodeObject(
X509_CERTIFICATE_TEMPLATE,
&CertTemplate,
&pbEncoded,
&cbEncoded))
goto CommonReturn;
if (NULL == (pInfo =
(PCERT_TEMPLATE_EXT) AllocAndDecodeObject(
X509_CERTIFICATE_TEMPLATE,
pbEncoded,
cbEncoded
))) goto CommonReturn;
if (0 != strcmp(pInfo->pszObjId, CertTemplate.pszObjId) ||
pInfo->dwMajorVersion != CertTemplate.dwMajorVersion ||
pInfo->fMinorVersion != CertTemplate.fMinorVersion)
printf("X509_CERTIFICATE_TEMPLATE failed => decode != encode input\n");
TestFree(pbEncoded);
pbEncoded = NULL;
TestFree(pInfo);
pInfo = NULL;
CertTemplate.fMinorVersion = TRUE;
CertTemplate.dwMinorVersion = 12345678;
if (!AllocAndEncodeObject(
szOID_CERTIFICATE_TEMPLATE,
&CertTemplate,
&pbEncoded,
&cbEncoded))
goto CommonReturn;
if (NULL == (pInfo =
(PCERT_TEMPLATE_EXT) AllocAndDecodeObject(
szOID_CERTIFICATE_TEMPLATE,
pbEncoded,
cbEncoded
))) goto CommonReturn;
if (0 != strcmp(pInfo->pszObjId, CertTemplate.pszObjId) ||
pInfo->dwMajorVersion != CertTemplate.dwMajorVersion ||
pInfo->fMinorVersion != CertTemplate.fMinorVersion ||
pInfo->dwMinorVersion != CertTemplate.dwMinorVersion)
printf("szOID_CERTIFICATE_TEMPLATE failed => decode != encode input\n");
CommonReturn:
if (pbEncoded)
TestFree(pbEncoded);
if (pInfo)
TestFree(pInfo);
}
int _cdecl main(int argc, char * argv[])
{
BOOL fResult;
LPCSTR pszResult;
CERT_NAME_INFO Name;
CERT_RDN Rdn[2];
CERT_RDN_ATTR RdnAttr[2];
#define ATTR_VALUE0 "Name 0"
RdnAttr[0].pszObjId = "1.2.3.4";
RdnAttr[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
RdnAttr[0].Value.pbData = (BYTE *) ATTR_VALUE0;
RdnAttr[0].Value.cbData = strlen(ATTR_VALUE0);
#define ATTR_VALUE1 "Name 11111"
RdnAttr[1].pszObjId = "1.2.3.4.1";
RdnAttr[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
RdnAttr[1].Value.pbData = (BYTE *) ATTR_VALUE1;
RdnAttr[1].Value.cbData = strlen(ATTR_VALUE1);
Rdn[0].cRDNAttr = 2;
Rdn[0].rgRDNAttr = RdnAttr;
Rdn[1].cRDNAttr = 1;
Rdn[1].rgRDNAttr = &RdnAttr[1];
Name.cRDN = 2;
Name.rgRDN = Rdn;
BYTE *pbEncoded = NULL;
DWORD cbEncoded;
BYTE *pbCorrectEncoded = NULL;
DWORD cbCorrectEncoded;
DWORD cbTotal;
PCERT_NAME_INFO pDecodedInfo = NULL;
DWORD cbDecodedInfo;
PCERT_NAME_INFO pCorrectDecodedInfo = NULL;
DWORD cbCorrectDecodedInfo;
printf("command line: %s\n", GetCommandLine());
TestExtensions();
TestX942OtherInfo();
TestPKCSAttribute();
TestPKCSAttributes();
TestContentInfoSequenceOfAny();
TestSequenceOfAny();
TestInteger();
TestMultiByteInteger();
TestBits();
TestBitsWithoutTrailingZeroes();
TestOID();
TestUnicodeAnyString();
TestUniversalString();
TestChoiceOfTime();
TestUtcTime();
TestBadAltName();
TestBadAuthorityInfoAccess();
TestBadAuthorityKeyId2();
TestBadNameConstraints();
TestBadIssuingDistPoint();
TestCmcData();
TestCmcResponse();
TestCmcStatus(CMC_OTHER_INFO_NO_CHOICE);
TestCmcStatus(CMC_OTHER_INFO_FAIL_CHOICE);
TestCmcStatus(CMC_OTHER_INFO_PEND_CHOICE);
TestCmcAddExtensions();
TestCmcAddAttributes();
TestCertTemplate();
TestCryptExportPublicKeyInfo();
// Test: cbEncoded == correct length
if (!CryptEncodeObject(
dwCertEncodingType,
X509_NAME,
&Name,
NULL, // pbEncoded
&cbCorrectEncoded
)) {
PrintLastError("CryptEncodeObject(pbEncoded == NULL)");
goto ErrorReturn;
}
if (NULL == (pbCorrectEncoded = (BYTE *) TestAlloc(cbCorrectEncoded)))
goto ErrorReturn;
cbTotal = cbCorrectEncoded + DELTA_MORE_LENGTH;
if (NULL == (pbEncoded = (BYTE *) TestAlloc(cbTotal)))
goto ErrorReturn;
memset(pbCorrectEncoded, 0, cbCorrectEncoded);
if (!CryptEncodeObject(
dwCertEncodingType,
X509_NAME,
&Name,
pbCorrectEncoded,
&cbCorrectEncoded
)) {
PrintLastError("CryptEncodeObject(cbEncoded == correct length)");
goto ErrorReturn;
}
printf("For cbEncoded == correct length\n");
printf("Encoded Length = %d (0x%x) Content::\n",
cbCorrectEncoded, cbCorrectEncoded);
PrintBytes(" ", pbCorrectEncoded, cbCorrectEncoded);
// Test: cbEncoded < correct length
printf("\n");
memset(pbEncoded, 0, cbTotal);
cbEncoded = cbCorrectEncoded - DELTA_LESS_LENGTH;
fResult = CryptEncodeObject(
dwCertEncodingType,
X509_NAME,
&Name,
pbEncoded,
&cbEncoded
);
if (fResult) {
pszResult = "TRUE";
printf("failed => CryptEncodeObject(cbEncoded < correct length) returned success\n");
} else {
DWORD dwErr = GetLastError();
pszResult = "FALSE";
if (0 == dwErr)
printf("failed => CryptEncodeObject(cbEncoded < correct length) LastError == 0\n");
else
printf(
"CryptEncodeObject(cbEncoded < correct length) LastError = 0x%x (%d)\n",
dwErr, dwErr);
}
printf("For cbEncoded < correct length, fResult = %s\n", pszResult);
printf("Encoded Length = %d (0x%x) Content::\n", cbEncoded, cbEncoded);
PrintBytes(" ", pbEncoded, cbTotal);
if (cbEncoded != cbCorrectEncoded)
printf("failed => for cbEncoded < correct length:: wrong cbEncoded\n");
// Test: cbEncoded > correct length
printf("\n");
memset(pbEncoded, 0, cbTotal);
cbEncoded = cbTotal;
fResult = CryptEncodeObject(
dwCertEncodingType,
X509_NAME,
&Name,
pbEncoded,
&cbEncoded
);
if (fResult)
pszResult = "TRUE";
else {
pszResult = "FALSE";
PrintLastError("CryptEncodeObject(cbEncoded > correct length)");
}
printf("For cbEncoded > correct length, fResult = %s\n", pszResult);
printf("Encoded Length = %d (0x%x) Content::\n", cbEncoded, cbEncoded);
PrintBytes(" ", pbEncoded, cbTotal);
if (cbEncoded != cbCorrectEncoded)
printf("failed => for cbEncoded > correct length:: wrong cbEncoded\n");
else if (0 != memcmp(pbEncoded, pbCorrectEncoded, cbCorrectEncoded))
printf("failed => for cbEncoded > correct length:: bad pbEncoded content\n");
// Test: pbEncoded != NULL, cbEncoded == 0
printf("\n");
memset(pbEncoded, 0, cbTotal);
cbEncoded = 0;
fResult = CryptEncodeObject(
dwCertEncodingType,
X509_NAME,
&Name,
pbEncoded,
&cbEncoded
);
if (fResult) {
pszResult = "TRUE";
printf("failed => CryptEncodeObject(pbEncoded != NULL, cbEncoded == 0) returned success\n");
} else {
DWORD dwErr = GetLastError();
pszResult = "FALSE";
if (0 == dwErr)
printf("failed => CryptEncodeObject(pbEncoded != NULL, cbEncoded == 0) LastError == 0\n");
else
printf(
"CryptEncodeObject(pbEncoded != NULL, cbEncoded == 0) LastError = 0x%x (%d)\n",
dwErr, dwErr);
}
printf("For pbEncoded != NULL, cbEncoded == 0, fResult = %s\n", pszResult);
printf("Encoded Length = %d (0x%x) Content::\n", cbEncoded, cbEncoded);
PrintBytes(" ", pbEncoded, cbTotal);
printf("\n");
// Test: cbDecodedInfo == correct length
if (!CryptDecodeObject(
dwCertEncodingType,
X509_NAME,
pbCorrectEncoded,
cbCorrectEncoded,
0, // dwFlags
NULL, // pvStructInfo
&cbCorrectDecodedInfo
)) {
PrintLastError("CryptDecodeObject(pvStructInfo == NULL)");
goto ErrorReturn;
}
if (NULL == (pCorrectDecodedInfo = (PCERT_NAME_INFO) TestAlloc(
cbCorrectDecodedInfo)))
goto ErrorReturn;
cbTotal = cbCorrectDecodedInfo + DELTA_MORE_LENGTH;
if (NULL == (pDecodedInfo = (PCERT_NAME_INFO) TestAlloc(cbTotal)))
goto ErrorReturn;
memset(pCorrectDecodedInfo, 0, cbCorrectDecodedInfo);
if (!CryptDecodeObject(
dwCertEncodingType,
X509_NAME,
pbCorrectEncoded,
cbCorrectEncoded,
0, // dwFlags
pCorrectDecodedInfo,
&cbCorrectDecodedInfo
)) {
PrintLastError("CryptDecodeObject(cbStructInfo == correct length)");
goto ErrorReturn;
}
// Test: cbDecodedInfo > correct length
memset(pDecodedInfo, 0, cbTotal);
cbDecodedInfo = cbTotal;
fResult = CryptDecodeObject(
dwCertEncodingType,
X509_NAME,
pbCorrectEncoded,
cbCorrectEncoded,
0, // dwFlags
pDecodedInfo,
&cbDecodedInfo
);
if (!fResult)
PrintLastError("CryptDecodeObject(cbStructInfo > correct length)");
if (cbDecodedInfo != cbCorrectDecodedInfo)
printf("failed => for cbStructInfo > correct length:: wrong cbStructInfo\n");
// Test: cbDecodedInfo < correct length
memset(pDecodedInfo, 0, cbTotal);
cbDecodedInfo = cbCorrectDecodedInfo - DELTA_LESS_LENGTH;
fResult = CryptDecodeObject(
dwCertEncodingType,
X509_NAME,
pbCorrectEncoded,
cbCorrectEncoded,
0, // dwFlags
pDecodedInfo,
&cbDecodedInfo
);
if (fResult)
printf("failed => CryptDecodeObject(cbStructInfo < correct length) returned success\n");
else {
DWORD dwErr = GetLastError();
if (0 == dwErr)
printf("failed => CryptDecodeObject(cbStructInfo < correct length) LastError == 0\n");
else
printf(
"CryptDecodeObject(cbStructInfo < correct length) LastError = 0x%x (%d)\n",
dwErr, dwErr);
}
if (cbDecodedInfo != cbCorrectDecodedInfo)
printf("failed => for cbStructInfo < correct length:: wrong cbStructInfo\n");
// Test: pvStructInfo != NULL, cbStructInfo == 0
memset(pDecodedInfo, 0, cbTotal);
cbDecodedInfo = 0;
fResult = CryptDecodeObject(
dwCertEncodingType,
X509_NAME,
pbCorrectEncoded,
cbCorrectEncoded,
0, // dwFlags
pDecodedInfo,
&cbDecodedInfo
);
if (fResult)
printf("failed => CryptDecodeObject(pvStructInfo != NULL, cbStructInfo == 0) returned success\n");
else {
DWORD dwErr = GetLastError();
if (0 == dwErr)
printf("failed => CryptDecodeObject(pvStructInfo != NULL, cbStructInfo == 0) LastError == 0\n");
else
printf(
"CryptDecodeObject(pvStructInfo != NULL, cbStructInfo == 0) LastError = 0x%x (%d)\n",
dwErr, dwErr);
}
// Test decoding missing the last bytes
memset(pDecodedInfo, 0, cbTotal);
cbDecodedInfo = cbCorrectDecodedInfo;
fResult = CryptDecodeObject(
dwCertEncodingType,
X509_NAME,
pbCorrectEncoded,
cbCorrectEncoded -30,
0, // dwFlags
pDecodedInfo,
&cbDecodedInfo
);
if (fResult)
printf("failed => CryptDecodeObject(incomplete cbEncoded) returned success\n");
else {
DWORD dwErr = GetLastError();
if (0 == dwErr)
printf("failed => CryptDecodeObject(incomplete cbEncoded) LastError == 0\n");
else
printf(
"CryptDecodeObject(incomplete cbEncoded) LastError = 0x%x (%d)\n",
dwErr, dwErr);
}
ErrorReturn:
if (pbEncoded)
TestFree(pbEncoded);
if (pbCorrectEncoded)
TestFree(pbCorrectEncoded);
if (pDecodedInfo)
TestFree(pDecodedInfo);
if (pCorrectDecodedInfo)
TestFree(pCorrectDecodedInfo);
printf("Done.\n");
return 0;
}