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.
 
 
 
 
 
 

4530 lines
147 KiB

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1995 - 1996
//
// File: certtest.cpp
//
// Contents: Certificate Test Helper APIs
//
// History: 11-Apr-96 philh created
// 31-May-96 helles Removed check for a particular error code,
// NTE_PROV_TYPE_NOT_DEF, since this can get
// overwritten due to known problem with
// the msvcr40d.dll on Win95.
// 20-Aug-96 jeffspel name changes
//--------------------------------------------------------------------------
#include <windows.h>
#include <winldap.h>
#include <assert.h>
#include "certtest.h"
#include "cryptuiapi.h"
#include "spc.h"
#include "setcert.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <memory.h>
#include <time.h>
#include <stddef.h>
DWORD dwCertEncodingType = X509_ASN_ENCODING;
DWORD dwMsgEncodingType = PKCS_7_ASN_ENCODING;
DWORD dwMsgAndCertEncodingType = PKCS_7_ASN_ENCODING | X509_ASN_ENCODING;
#define NULL_ASN_TAG 0x05
//+-------------------------------------------------------------------------
// Error output routines
//--------------------------------------------------------------------------
void PrintError(LPCSTR pszMsg)
{
printf("%s\n", pszMsg);
}
void PrintLastError(LPCSTR pszMsg)
{
DWORD dwErr = GetLastError();
printf("%s failed => 0x%x (%d) \n", pszMsg, dwErr, dwErr);
}
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;
if (st.wMilliseconds) {
char *pch = buf + strlen(buf);
sprintf(pch, " <milliseconds:: %03d>", st.wMilliseconds);
}
}
else
sprintf(buf, "<FILETIME %08lX:%08lX>", pft->dwHighDateTime,
pft->dwLowDateTime);
return buf;
}
#define CROW 16
void PrintBytes(LPCSTR pszHdr, BYTE *pb, DWORD cbSize)
{
ULONG cb, i;
if (cbSize == 0) {
printf("%s NO Value Bytes\n", pszHdr);
return;
}
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");
}
}
//+-------------------------------------------------------------------------
// Test allocation and free routines
//--------------------------------------------------------------------------
LPVOID
WINAPI
TestAlloc(
IN size_t cbBytes
)
{
LPVOID pv;
pv = malloc(cbBytes);
if (pv == NULL) {
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
PrintLastError("TestAlloc");
}
return pv;
}
LPVOID
WINAPI
TestRealloc(
IN LPVOID pvOrg,
IN size_t cbBytes
)
{
LPVOID pv;
if (NULL == (pv = pvOrg ? realloc(pvOrg, cbBytes) : malloc(cbBytes))) {
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
PrintLastError("TestAlloc");
}
return pv;
}
VOID
WINAPI
TestFree(
IN LPVOID pv
)
{
if (pv)
free(pv);
}
//+-------------------------------------------------------------------------
// Allocate and convert a multi-byte string to a wide string
//--------------------------------------------------------------------------
LPWSTR AllocAndSzToWsz(LPCSTR psz)
{
size_t cb;
LPWSTR pwsz = NULL;
if (-1 == (cb = mbstowcs( NULL, psz, strlen(psz))))
goto bad_param;
cb += 1; // terminating NULL
if (NULL == (pwsz = (LPWSTR)TestAlloc( cb * sizeof(WCHAR)))) {
PrintLastError("AllocAndSzToWsz");
goto failed;
}
if (-1 == mbstowcs( pwsz, psz, cb))
goto bad_param;
goto common_return;
bad_param:
PrintError("Bad AllocAndSzToWsz");
failed:
if (pwsz) {
TestFree(pwsz);
pwsz = NULL;
}
common_return:
return pwsz;
}
static CRYPT_DECODE_PARA TestDecodePara = {
offsetof(CRYPT_DECODE_PARA, pfnFree) + sizeof(TestDecodePara.pfnFree),
TestAlloc,
TestFree
};
static void *TestNoCopyDecodeObject(
IN LPCSTR lpszStructType,
IN const BYTE *pbEncoded,
IN DWORD cbEncoded,
OUT DWORD *pcbStructInfo = NULL
)
{
DWORD cbStructInfo;
void *pvStructInfo;
if (!CryptDecodeObjectEx(
dwCertEncodingType,
lpszStructType,
pbEncoded,
cbEncoded,
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;
}
//+-------------------------------------------------------------------------
// 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;
}
HCRYPTPROV GetCryptProvEx(BOOL fVerbose)
{
HCRYPTPROV hProv = 0;
BOOL fResult;
DWORD dwCryptProvType = PROV_RSA_FULL;
fResult = CryptAcquireContext(
&hProv,
NULL, // pszContainer
NULL, // pszProvider
dwCryptProvType,
0 // dwFlags
);
if (fResult) {
if (fVerbose)
printf("Using default sign and xchg keys for provider: %d\n",
dwCryptProvType);
} else {
DWORD dwErr = GetLastError();
if (dwErr == NTE_BAD_KEYSET) {
// Need to create the keys
printf("Generating SIGNATURE and EXCHANGE private keys\n");
hProv = 0;
fResult = CryptAcquireContext(
&hProv,
NULL, // pszContainer
NULL, // pszProvider
dwCryptProvType,
CRYPT_NEWKEYSET
);
if (!fResult || hProv == 0) {
PrintLastError("CryptAcquireContext");
return 0;
}
HCRYPTKEY hKey = 0;
fResult = CryptGenKey(
hProv,
AT_SIGNATURE,
CRYPT_EXPORTABLE,
&hKey
);
if (!fResult || hKey == 0)
PrintLastError("CryptGenKey(AT_SIGNATURE)");
else
CryptDestroyKey(hKey);
hKey = 0;
fResult = CryptGenKey(
hProv,
AT_KEYEXCHANGE,
CRYPT_EXPORTABLE,
&hKey
);
if (!fResult || hKey == 0)
PrintLastError("CryptGenKey(AT_KEYEXCHANGE)");
else
CryptDestroyKey(hKey);
} else {
PrintLastError("CryptAcquireContext");
return 0;
}
}
return hProv;
}
HCRYPTPROV GetCryptProv() {
return GetCryptProvEx(TRUE);
}
static HKEY OpenRelocateKey(
IN OUT LPCSTR *ppszStoreFilename,
IN DWORD dwFlags
)
{
LPCSTR pszStoreFilename = *ppszStoreFilename;
HKEY hKeyRelocate;
char szRelocate[256];
LPCSTR pszRelocate;
int i = 0;
HKEY hKeyBase;
LONG err;
// Use the following characters until the terminating ":" as the
// relocation path
while ('\0' != *pszStoreFilename && ':' != *pszStoreFilename) {
if (i >= sizeof(szRelocate) - 1)
break;
szRelocate[i++] = *pszStoreFilename++;
}
if (':' == *pszStoreFilename)
pszStoreFilename++;
szRelocate[i] = '\0';
*ppszStoreFilename = pszStoreFilename;
if (0 == _stricmp(szRelocate, "NULL")) {
return NULL;
} else if (0 == _strnicmp(szRelocate, "HKCU", 4)) {
hKeyRelocate = HKEY_CURRENT_USER;
pszRelocate = szRelocate+4;
if ('\\' == *pszRelocate)
pszRelocate++;
} else if (0 == _strnicmp(szRelocate, "HKLM", 4)) {
hKeyRelocate = HKEY_LOCAL_MACHINE;
pszRelocate = szRelocate+4;
if ('\\' == *pszRelocate)
pszRelocate++;
} else {
hKeyRelocate = HKEY_CURRENT_USER;
pszRelocate = szRelocate;
}
if (dwFlags & (CERT_STORE_READONLY_FLAG | CERT_STORE_OPEN_EXISTING_FLAG)) {
REGSAM samDesired;
if (dwFlags & CERT_STORE_READONLY_FLAG)
samDesired = KEY_READ;
else
samDesired = KEY_ALL_ACCESS;
if (ERROR_SUCCESS != (err = RegOpenKeyExA(
hKeyRelocate,
pszRelocate,
0, // dwReserved
samDesired,
&hKeyBase))) {
printf("RegOpenKeyExA(%s) failed => %d 0x%x\n",
pszRelocate, err, err);
hKeyBase = NULL;
}
} else {
DWORD dwDisposition;
if (ERROR_SUCCESS != (err = RegCreateKeyExA(
hKeyRelocate,
pszRelocate,
0, // dwReserved
NULL, // lpClass
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL, // lpSecurityAttributes
&hKeyBase,
&dwDisposition))) {
printf("RegCreateKeyExA(%s) failed => %d 0x%x\n",
pszRelocate, err, err);
hKeyBase = NULL;
}
}
return hKeyBase;
}
// LastError can get globbered when doing remote registry access
static void CloseRelocateKey(
IN HKEY hKey
)
{
if (hKey) {
DWORD dwErr = GetLastError();
LONG RegCloseKeyStatus;
RegCloseKeyStatus = RegCloseKey(hKey);
assert(ERROR_SUCCESS == RegCloseKeyStatus);
SetLastError(dwErr);
}
}
typedef PLDAP (LDAPAPI *PFN_LDAP_INIT_W)(
const PWCHAR HostName,
ULONG PortNumber
);
typedef ULONG (LDAPAPI *PFN_LDAP_UNBIND)(
LDAP *ld
);
typedef ULONG (LDAPAPI *PFN_LDAP_CONNECT)(
LDAP *ld,
struct l_timeval *timeout
);
typedef ULONG (LDAPAPI *PFN_LDAP_BIND_SW)(
LDAP *ld,
PWCHAR dn,
PWCHAR cred,
ULONG method
);
static
HCERTSTORE
OpenLdapStore(
IN DWORD dwFlags,
IN OUT LPWSTR pwszLdapUrl
)
{
HCERTSTORE hStore = NULL;
LPWSTR pwszHostName = NULL;
LPWSTR pwszTrailingSlash = NULL;
CERT_LDAP_STORE_OPENED_PARA OpenPara = {NULL, pwszLdapUrl};
HMODULE hDll = NULL;
PFN_LDAP_INIT_W pfn_ldap_initW = NULL;
PFN_LDAP_BIND_SW pfn_ldap_bind_sW = NULL;
PFN_LDAP_UNBIND pfn_ldap_unbind = NULL;
LDAP *ld = NULL;
ULONG ulStatus;
if (0 == _wcsnicmp(L"ldap://", pwszLdapUrl, 7)) {
pwszHostName = pwszLdapUrl + 7;
pwszTrailingSlash = pwszHostName;
while (L'\0' != *pwszTrailingSlash && L'/' != *pwszTrailingSlash)
pwszTrailingSlash++;
if (L'/' == *pwszTrailingSlash && pwszTrailingSlash != pwszHostName) {
*pwszTrailingSlash = L'\0';
} else {
pwszHostName = NULL;
pwszTrailingSlash = NULL;
}
}
if (NULL == (hDll = LoadLibraryA("wldap32.dll"))) {
PrintLastError("LoadLibraryA(wldap32.dll)");
goto CommonReturn;
}
if (NULL == (pfn_ldap_initW =
(PFN_LDAP_INIT_W) GetProcAddress(hDll,
"ldap_initW"))) {
PrintLastError("GetProcAddress(ldap_initW)");
goto CommonReturn;
}
if (NULL == (pfn_ldap_bind_sW =
(PFN_LDAP_BIND_SW) GetProcAddress(hDll,
"ldap_bind_sW"))) {
PrintLastError("GetProcAddress(ldap_bind_sW)");
goto CommonReturn;
}
if (NULL == (pfn_ldap_unbind =
(PFN_LDAP_UNBIND) GetProcAddress(hDll,
"ldap_unbind"))) {
PrintLastError("GetProcAddress(ldap_unbind)");
goto CommonReturn;
}
ld = pfn_ldap_initW(pwszHostName, 0);
if (pwszTrailingSlash)
*pwszTrailingSlash = L'/';
if (NULL == ld) {
PrintError("ldap_initW failed");
goto CommonReturn;
}
OpenPara.pvLdapSessionHandle = ld;
ulStatus = pfn_ldap_bind_sW(ld, NULL, NULL, LDAP_AUTH_SSPI);
if (LDAP_SUCCESS != ulStatus) {
printf("ldap_bind_sW failed ==> 0x%x\n", ulStatus);
goto CommonReturn;
}
if (0 == (dwFlags & CERT_STORE_READONLY_FLAG))
dwFlags |= CERT_LDAP_STORE_UNBIND_FLAG;
hStore = CertOpenStore(
CERT_STORE_PROV_LDAP_W,
dwCertEncodingType | dwMsgEncodingType,
0, // hCryptProv
dwFlags | CERT_LDAP_STORE_OPENED_FLAG,
(const void *) &OpenPara
);
if (NULL == hStore) {
PrintLastError("CertOpenStore(CERT_LDAP_STORE_OPENED_FLAG)");
if (0 != (dwFlags & CERT_STORE_DELETE_FLAG) && 0 == GetLastError() &&
0 != (dwFlags & CERT_LDAP_STORE_UNBIND_FLAG))
ld = NULL;
} else if (0 != (dwFlags & CERT_LDAP_STORE_UNBIND_FLAG))
ld = NULL;
CommonReturn:
if (ld)
pfn_ldap_unbind(ld);
if (hDll)
FreeLibrary(hDll);
return hStore;
}
typedef struct _SYSTEM_LOCATION_INFO {
LPCSTR pszPrefix;
DWORD dwStoreLocation;
} SYSTEM_LOCATION_INFO;
static SYSTEM_LOCATION_INFO rgSystemLocationInfo[] = {
"LocalMachine:", CERT_SYSTEM_STORE_LOCAL_MACHINE,
"LM:", CERT_SYSTEM_STORE_LOCAL_MACHINE,
"Services:", CERT_SYSTEM_STORE_SERVICES,
"Users:", CERT_SYSTEM_STORE_USERS,
"CurrentService:", CERT_SYSTEM_STORE_CURRENT_SERVICE,
"CS:", CERT_SYSTEM_STORE_CURRENT_SERVICE,
"CurrentUser:", CERT_SYSTEM_STORE_CURRENT_USER,
"CU:", CERT_SYSTEM_STORE_CURRENT_USER,
"CUGP:", CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY,
"LMGP:", CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY,
"Enterprise:", CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE,
"EP:", CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE
};
#define NUM_SYSTEM_LOCATION (sizeof(rgSystemLocationInfo) / \
sizeof(rgSystemLocationInfo[0]))
// returns NULL if unable to open. Doesn't open memory store.
HCERTSTORE OpenStoreEx2(BOOL fSystemStore, LPCSTR pszStoreFilename,
DWORD dwFlags)
{
HCERTSTORE hStore = NULL;
if (fSystemStore) {
DWORD i;
// Check for special System Location Prefix. If found, strip off,
// set store location and try again
for (i = 0; i < NUM_SYSTEM_LOCATION; i++) {
LPCSTR pszPrefix = rgSystemLocationInfo[i].pszPrefix;
DWORD cchPrefix = strlen(pszPrefix);
if (0 == _strnicmp(pszPrefix, pszStoreFilename, cchPrefix)) {
if (0 == (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK))
dwFlags |= rgSystemLocationInfo[i].dwStoreLocation;
return OpenStoreEx2(TRUE, pszStoreFilename + cchPrefix,
dwFlags);
}
}
// Check for special "archived:" Prefix. If found, strip off and
// set ENUM_ARCHIVE flag and try again
if (0 == _strnicmp("archived:", pszStoreFilename, 9)) {
dwFlags |= CERT_STORE_ENUM_ARCHIVED_FLAG;
return OpenStoreEx2(TRUE, pszStoreFilename + 9,
dwFlags);
}
// Check for special "reg:", "unprotected:", "phy:", "prov:ProvName:",
// "rel:<RegPath>:", "relreg:<RegPath>:" or "relphy:<RegPath>:" prefix
//
// Where <RegPath> is <string>, HKCU\<string>, HKLM\<string> or
// NULL. <string> defaults to HKCU.
if (0 == _strnicmp("reg:", pszStoreFilename, 4)) {
if (0 == (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK))
dwFlags |= CERT_SYSTEM_STORE_CURRENT_USER;
hStore = CertOpenStore(
CERT_STORE_PROV_SYSTEM_REGISTRY_A,
dwCertEncodingType | dwMsgEncodingType,
0, // hCryptProv
dwFlags,
(const void *) (pszStoreFilename + 4)
);
} else if (0 == _strnicmp("unprotected:", pszStoreFilename, 12)) {
if (0 == (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK))
dwFlags |= CERT_SYSTEM_STORE_CURRENT_USER;
hStore = CertOpenStore(
CERT_STORE_PROV_SYSTEM_REGISTRY_A,
dwCertEncodingType | dwMsgEncodingType,
0, // hCryptProv
dwFlags | CERT_SYSTEM_STORE_UNPROTECTED_FLAG,
(const void *) (pszStoreFilename + 12)
);
} else if (0 == _strnicmp("phy:", pszStoreFilename, 4)) {
LPWSTR pwszStore;
if (0 == (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK))
dwFlags |= CERT_SYSTEM_STORE_CURRENT_USER;
if (pwszStore = AllocAndSzToWsz(pszStoreFilename + 4)) {
hStore = CertOpenStore(
CERT_STORE_PROV_PHYSICAL,
dwCertEncodingType | dwMsgEncodingType,
0, // hCryptProv
dwFlags,
(const void *) pwszStore
);
TestFree(pwszStore);
}
} else if (0 == _strnicmp("prov:", pszStoreFilename, 5)) {
LPWSTR pwszStore;
char ch;
char szStoreProvider[256];
int i = 0;
// Advance past "prov:"
pszStoreFilename += 5;
// Use the following characters until the terminating ":" as the
// store provider
while ('\0' != *pszStoreFilename && ':' != *pszStoreFilename) {
if (i >= sizeof(szStoreProvider) - 1)
break;
szStoreProvider[i++] = *pszStoreFilename++;
}
if (':' == *pszStoreFilename)
pszStoreFilename++;
szStoreProvider[i] = '\0';
if (pwszStore = AllocAndSzToWsz(pszStoreFilename)) {
if (0 == _stricmp("ldap", szStoreProvider) &&
0 != (dwFlags & CERT_LDAP_STORE_OPENED_FLAG))
hStore = OpenLdapStore(dwFlags, pwszStore);
else
hStore = CertOpenStore(
szStoreProvider,
dwCertEncodingType | dwMsgEncodingType,
0, // hCryptProv
dwFlags,
(const void *) pwszStore
);
TestFree(pwszStore);
}
} else if (0 == _strnicmp("rel:", pszStoreFilename, 4)) {
CERT_SYSTEM_STORE_RELOCATE_PARA RelocatePara;
pszStoreFilename += 4;
RelocatePara.hKeyBase = OpenRelocateKey(&pszStoreFilename, dwFlags);
RelocatePara.pszSystemStore = pszStoreFilename;
if (0 == (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK))
dwFlags |= CERT_SYSTEM_STORE_CURRENT_USER;
dwFlags |= CERT_SYSTEM_STORE_RELOCATE_FLAG;
hStore = CertOpenStore(
CERT_STORE_PROV_SYSTEM_A,
dwCertEncodingType | dwMsgEncodingType,
0, // hCryptProv
dwFlags,
(const void *) &RelocatePara
);
CloseRelocateKey(RelocatePara.hKeyBase);
} else if (0 == _strnicmp("relsys:", pszStoreFilename, 7)) {
CERT_SYSTEM_STORE_RELOCATE_PARA RelocatePara;
pszStoreFilename += 7;
RelocatePara.hKeyBase = OpenRelocateKey(&pszStoreFilename, dwFlags);
RelocatePara.pszSystemStore = pszStoreFilename;
if (0 == (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK))
dwFlags |= CERT_SYSTEM_STORE_CURRENT_USER;
dwFlags |= CERT_SYSTEM_STORE_RELOCATE_FLAG;
hStore = CertOpenStore(
CERT_STORE_PROV_SYSTEM_REGISTRY_A,
dwCertEncodingType | dwMsgEncodingType,
0, // hCryptProv
dwFlags,
(const void *) &RelocatePara
);
CloseRelocateKey(RelocatePara.hKeyBase);
} else if (0 == _strnicmp("relphy:", pszStoreFilename, 7)) {
LPWSTR pwszStore;
CERT_SYSTEM_STORE_RELOCATE_PARA RelocatePara;
pszStoreFilename += 7;
RelocatePara.hKeyBase = OpenRelocateKey(&pszStoreFilename, dwFlags);
if (pwszStore = AllocAndSzToWsz(pszStoreFilename)) {
RelocatePara.pwszSystemStore = pwszStore;
if (0 == (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK))
dwFlags |= CERT_SYSTEM_STORE_CURRENT_USER;
dwFlags |= CERT_SYSTEM_STORE_RELOCATE_FLAG;
hStore = CertOpenStore(
CERT_STORE_PROV_PHYSICAL_W,
dwCertEncodingType | dwMsgEncodingType,
0, // hCryptProv
dwFlags,
(const void *) &RelocatePara
);
TestFree(pwszStore);
}
CloseRelocateKey(RelocatePara.hKeyBase);
} else if (0 != (dwFlags & ~CERT_STORE_SET_LOCALIZED_NAME_FLAG)) {
if (0 == (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK))
dwFlags |= CERT_SYSTEM_STORE_CURRENT_USER;
hStore = CertOpenStore(
CERT_STORE_PROV_SYSTEM_A,
dwCertEncodingType | dwMsgEncodingType,
0, // hCryptProv
dwFlags,
(const void *) pszStoreFilename
);
} else
hStore = CertOpenSystemStore(NULL, pszStoreFilename);
} else
hStore = CertOpenStore(
CERT_STORE_PROV_FILENAME_A,
dwCertEncodingType | dwMsgEncodingType,
0, // hCryptProv
dwFlags,
(const void *) pszStoreFilename
);
if (dwFlags & CERT_STORE_DELETE_FLAG) {
if (NULL != hStore)
printf(
"failed => CERT_STORE_DELETE_FLAG returned non-NULL hStore\n");
else {
if (0 == GetLastError())
printf("Successful delete store\n");
else
PrintLastError("CertOpenStore(CERT_STORE_DELETE_FLAG)");
}
hStore = NULL;
} else if (NULL == hStore) {
DWORD dwErr = GetLastError();
printf("NULL OpenStoreEx %d 0x%x\n", dwErr, dwErr);
} else {
if (dwFlags & CERT_STORE_SET_LOCALIZED_NAME_FLAG) {
LPWSTR pwszLocalizedName;
DWORD cbLocalizedName;
if (!CertGetStoreProperty(
hStore,
CERT_STORE_LOCALIZED_NAME_PROP_ID,
NULL,
&cbLocalizedName
)) {
if (CRYPT_E_NOT_FOUND == GetLastError())
printf("No localized store name property\n");
else
PrintLastError("CertGetStoreProperty");
} else if (pwszLocalizedName = (LPWSTR) TestAlloc(
cbLocalizedName)) {
if (!CertGetStoreProperty(
hStore,
CERT_STORE_LOCALIZED_NAME_PROP_ID,
pwszLocalizedName,
&cbLocalizedName
))
PrintLastError("CertGetStoreProperty");
else
printf("Localized Store Name:: %S\n", pwszLocalizedName);
TestFree(pwszLocalizedName);
}
}
DWORD dwAccessStateFlags;
DWORD cbData = sizeof(dwAccessStateFlags);
CertGetStoreProperty(
hStore,
CERT_ACCESS_STATE_PROP_ID,
&dwAccessStateFlags,
&cbData
);
if (0 == cbData)
printf("No Store AccessState PropId\n");
else {
printf("Store AccessState PropId dwFlags:: 0x%x",
dwAccessStateFlags);
if (dwAccessStateFlags & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG)
printf(" WRITE_PERSIST");
if (dwAccessStateFlags & CERT_ACCESS_STATE_SYSTEM_STORE_FLAG)
printf(" SYSTEM_STORE");
if (dwAccessStateFlags & CERT_ACCESS_STATE_LM_SYSTEM_STORE_FLAG)
printf(" LM_SYSTEM_STORE");
printf("\n");
}
}
return hStore;
}
HCERTSTORE OpenSystemStoreOrFile(BOOL fSystemStore, LPCSTR pszStoreFilename,
DWORD dwFlags)
{
HCERTSTORE hStore;
hStore = OpenStoreEx2(fSystemStore, pszStoreFilename, dwFlags);
if (hStore == NULL) {
DWORD dwErr = GetLastError();
printf( "can't open %s\n", pszStoreFilename);
SetLastError(dwErr);
PrintLastError("CertOpenStore");
}
return hStore;
}
HCERTSTORE OpenStoreEx(BOOL fSystemStore, LPCSTR pszStoreFilename,
DWORD dwFlags)
{
HCERTSTORE hStore;
hStore = OpenStoreEx2(fSystemStore, pszStoreFilename, dwFlags);
if (hStore == NULL) {
printf( "can't open %s\n", pszStoreFilename);
hStore = CertOpenStore(
CERT_STORE_PROV_MEMORY,
0, // dwEncodingType
0, // hCryptProv
0, // dwFlags
NULL // pvPara
);
}
if (hStore == NULL)
PrintLastError("CertOpenStore");
return hStore;
}
HCERTSTORE OpenStore(BOOL fSystemStore, LPCSTR pszStoreFilename)
{
return OpenStoreEx(fSystemStore, pszStoreFilename, 0);
}
HCERTSTORE OpenStoreOrSpc(BOOL fSystemStore, LPCSTR pszStoreFilename,
BOOL *pfSpc)
{
*pfSpc = FALSE;
return OpenStore(fSystemStore, pszStoreFilename);
}
void SaveStore(HCERTSTORE hStore, LPCSTR pszSaveFilename)
{
HANDLE hFile;
hFile = CreateFile(pszSaveFilename,
GENERIC_WRITE,
0, // fdwShareMode
NULL, // lpsa
CREATE_ALWAYS,
0, // fdwAttrsAndFlags
0); // TemplateFile
if (INVALID_HANDLE_VALUE == hFile) {
printf( "can't open %s\n", pszSaveFilename);
PrintLastError("CloseStore::CreateFile");
} else {
printf("Saving store to %s\n", pszSaveFilename);
if (!CertSaveStore(
hStore,
0, // dwEncodingType,
CERT_STORE_SAVE_AS_STORE,
CERT_STORE_SAVE_TO_FILE,
(void *) hFile,
0 // dwFlags
))
PrintLastError("CertSaveStore");
CloseHandle(hFile);
}
}
void SaveStoreEx(HCERTSTORE hStore, BOOL fPKCS7Save, LPCSTR pszSaveFilename)
{
DWORD dwSaveAs;
if (fPKCS7Save) {
dwSaveAs = CERT_STORE_SAVE_AS_PKCS7;
printf("Saving store as PKCS #7 to %s\n", pszSaveFilename);
} else {
dwSaveAs = CERT_STORE_SAVE_AS_STORE;
printf("Saving store to %s\n", pszSaveFilename);
}
if (!CertSaveStore(
hStore,
dwCertEncodingType | dwMsgEncodingType,
dwSaveAs,
CERT_STORE_SAVE_TO_FILENAME_A,
(void *) pszSaveFilename,
0 // dwFlags
))
PrintLastError("CertSaveStore");
}
LPCWSTR GetOIDName(LPCSTR pszOID, DWORD dwGroupId)
{
PCCRYPT_OID_INFO pInfo;
if (pInfo = CryptFindOIDInfo(
CRYPT_OID_INFO_OID_KEY,
(void *) pszOID,
dwGroupId
)) {
if (L'\0' != pInfo->pwszName[0])
return pInfo->pwszName;
}
return L"???";
}
ALG_ID GetAlgid(LPCSTR pszOID, DWORD dwGroupId)
{
PCCRYPT_OID_INFO pInfo;
if (pInfo = CryptFindOIDInfo(
CRYPT_OID_INFO_OID_KEY,
(void *) pszOID,
dwGroupId
))
return pInfo->Algid;
return 0;
}
static void GetSignAlgids(
IN LPCSTR pszOID,
OUT ALG_ID *paiHash,
OUT ALG_ID *paiPubKey
)
{
PCCRYPT_OID_INFO pInfo;
*paiHash = 0;
*paiPubKey = 0;
if (pInfo = CryptFindOIDInfo(
CRYPT_OID_INFO_OID_KEY,
(void *) pszOID,
CRYPT_SIGN_ALG_OID_GROUP_ID
)) {
DWORD cExtra = pInfo->ExtraInfo.cbData / sizeof(DWORD);
DWORD *pdwExtra = (DWORD *) pInfo->ExtraInfo.pbData;
*paiHash = pInfo->Algid;
if (1 <= cExtra)
*paiPubKey = pdwExtra[0];
}
}
void DisplayVerifyFlags(LPSTR pszHdr, DWORD dwFlags)
{
if (dwFlags == CERT_STORE_TIME_VALIDITY_FLAG)
printf("***** %s: Warning:: Time Invalid\n", pszHdr);
else if (dwFlags != 0) {
printf("***** %s: Failed Verification Checks:: ", pszHdr);
if (dwFlags & CERT_STORE_SIGNATURE_FLAG)
printf("SIGNATURE ");
if (dwFlags & CERT_STORE_TIME_VALIDITY_FLAG)
printf("TIME ");
if (dwFlags & CERT_STORE_REVOCATION_FLAG)
printf("REVOCATION ");
if (dwFlags & CERT_STORE_NO_CRL_FLAG)
printf("NO_CRL ");
if (dwFlags & CERT_STORE_NO_ISSUER_FLAG)
printf("NO_ISSUER ");
if (dwFlags & CERT_STORE_DELTA_CRL_FLAG)
printf("NOT_DELTA_CRL ");
if (dwFlags & CERT_STORE_BASE_CRL_FLAG)
printf("NOT_BASE_CRL ");
printf("\n");
}
}
static void DisplayThumbprint(
LPCSTR pszHash,
BYTE *pbHash,
DWORD cbHash
)
{
printf("%s Thumbprint:: ", pszHash);
if (cbHash == 0)
printf("???");
else {
ULONG cb;
while (cbHash > 0) {
cb = min(4, cbHash);
cbHash -= cb;
for (; cb > 0; cb--, pbHash++)
printf("%02X", *pbHash);
printf(" ");
}
}
printf("\n");
}
static void DisplaySerialNumber(
PCRYPT_INTEGER_BLOB pSerialNumber
)
{
DWORD cb;
BYTE *pb;
for (cb = pSerialNumber->cbData,
pb = pSerialNumber->pbData + (cb - 1); cb > 0; cb--, pb--) {
printf(" %02X", *pb);
}
}
static void DisplayAnyString(
LPCSTR pszPrefix,
BYTE *pbEncoded,
DWORD cbEncoded,
DWORD dwDisplayFlags
)
{
PCERT_NAME_VALUE pInfo = NULL;
if (NULL == (pInfo = (PCERT_NAME_VALUE) TestNoCopyDecodeObject(
X509_UNICODE_ANY_STRING,
pbEncoded,
cbEncoded
))) goto CommonReturn;
if (pInfo->dwValueType == CERT_RDN_ENCODED_BLOB ||
pInfo->dwValueType == CERT_RDN_OCTET_STRING) {
printf("%s ValueType: %d\n", pszPrefix, pInfo->dwValueType);
PrintBytes(" ", pInfo->Value.pbData, pInfo->Value.cbData);
} else
printf("%s ValueType: %d String: %S\n",
pszPrefix, pInfo->dwValueType, pInfo->Value.pbData);
CommonReturn:
if (pInfo)
TestFree(pInfo);
}
static void DisplayBits(
LPCSTR pszPrefix,
BYTE *pbEncoded,
DWORD cbEncoded,
DWORD dwDisplayFlags)
{
PCRYPT_BIT_BLOB pInfo = NULL;
if (NULL == (pInfo = (PCRYPT_BIT_BLOB) TestNoCopyDecodeObject(
X509_BITS,
pbEncoded,
cbEncoded
))) goto CommonReturn;
printf("%s", pszPrefix);
if (1 == pInfo->cbData) {
printf(" %02X", *pInfo->pbData);
if (pInfo->cUnusedBits)
printf(" UnusedBits: %d\n", pInfo->cUnusedBits);
else
printf("\n");
} else {
if (pInfo->cbData) {
printf("\n");
PrintBytes(" ", pInfo->pbData, pInfo->cbData);
printf(" UnusedBits: %d\n", pInfo->cUnusedBits);
} else
printf(" NONE\n");
}
CommonReturn:
if (pInfo)
TestFree(pInfo);
}
static void DisplayInteger(
BYTE *pbEncoded,
DWORD cbEncoded,
DWORD dwDisplayFlags)
{
int iInfo = 0;
DWORD cbInfo;
cbInfo = sizeof(iInfo);
if (!CryptDecodeObject(
dwCertEncodingType,
X509_INTEGER,
pbEncoded,
cbEncoded,
0, // dwFlags
&iInfo,
&cbInfo
)) {
PrintLastError("IntegerDecode");
goto CommonReturn;
}
printf(" Integer:: %d (0x%x)\n", iInfo, iInfo);
CommonReturn:
return;
}
static void DisplayOctetString(
LPCSTR pszPrefix,
BYTE *pbEncoded,
DWORD cbEncoded,
DWORD dwDisplayFlags)
{
PCRYPT_DATA_BLOB pInfo = NULL;
if (NULL == (pInfo = (PCRYPT_DATA_BLOB) TestNoCopyDecodeObject(
X509_OCTET_STRING,
pbEncoded,
cbEncoded
))) goto CommonReturn;
printf("%s", pszPrefix);
if (pInfo->cbData) {
printf("\n");
PrintBytes(" ", pInfo->pbData, pInfo->cbData);
} else
printf(" NONE\n");
CommonReturn:
if (pInfo)
TestFree(pInfo);
}
static BOOL DecodeName(BYTE *pbEncoded, DWORD cbEncoded, DWORD dwDisplayFlags)
{
BOOL fResult;
PCERT_NAME_INFO pInfo = NULL;
DWORD i,j;
PCERT_RDN pRDN;
PCERT_RDN_ATTR pAttr;
#if 0
{
CERT_NAME_BLOB Name;
DWORD cwsz;
LPWSTR pwsz;
DWORD csz;
LPSTR psz;
Name.pbData = pbEncoded;
Name.cbData = cbEncoded;
DWORD rgdwStrType[] = {
CERT_SIMPLE_NAME_STR | CERT_NAME_STR_SEMICOLON_FLAG |
CERT_NAME_STR_NO_PLUS_FLAG | CERT_NAME_STR_NO_QUOTING_FLAG,
CERT_OID_NAME_STR,
CERT_X500_NAME_STR | CERT_NAME_STR_NO_PLUS_FLAG |
CERT_NAME_STR_NO_QUOTING_FLAG,
0
};
DWORD *pdwStrType;
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);
}
for (pdwStrType = rgdwStrType; *pdwStrType; 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);
TestFree(psz);
}
}
}
#endif
if (NULL == (pInfo = (PCERT_NAME_INFO) TestNoCopyDecodeObject(
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>";
if ((dwDisplayFlags & DISPLAY_VERBOSE_FLAG) ||
(pAttr->dwValueType == CERT_RDN_ENCODED_BLOB) ||
(pAttr->dwValueType == CERT_RDN_OCTET_STRING)) {
printf(" [%d,%d] %s (%S) ValueType: %d\n",
i, j, pszObjId, GetOIDName(pszObjId), pAttr->dwValueType);
PrintBytes(" ", pAttr->Value.pbData, pAttr->Value.cbData);
} else if (pAttr->dwValueType == CERT_RDN_UNIVERSAL_STRING) {
printf(" [%d,%d] %s (%S)",
i, j, pszObjId, GetOIDName(pszObjId));
DWORD cdw = pAttr->Value.cbData / 4;
DWORD *pdw = (DWORD *) pAttr->Value.pbData;
for ( ; cdw > 0; cdw--, pdw++)
printf(" 0x%08X", *pdw);
printf("\n");
DWORD csz;
csz = CertRDNValueToStrA(
pAttr->dwValueType,
&pAttr->Value,
NULL, // psz
0 // csz
);
if (csz > 1) {
LPSTR psz = (LPSTR) TestAlloc(csz);
if (psz) {
CertRDNValueToStrA(
pAttr->dwValueType,
&pAttr->Value,
psz,
csz
);
printf(" Str: %s\n", psz);
PrintBytes(" ", (BYTE *) psz, csz);
TestFree(psz);
}
}
DWORD cwsz;
cwsz = CertRDNValueToStrW(
pAttr->dwValueType,
&pAttr->Value,
NULL, // pwsz
0 // cwsz
);
if (cwsz > 1) {
LPWSTR pwsz =
(LPWSTR) TestAlloc(cwsz * sizeof(WCHAR));
if (pwsz) {
CertRDNValueToStrW(
pAttr->dwValueType,
&pAttr->Value,
pwsz,
cwsz
);
printf(" WStr: %S\n", pwsz);
PrintBytes(" ", (BYTE *) pwsz, cwsz * sizeof(WCHAR));
TestFree(pwsz);
}
}
} else if (pAttr->dwValueType == CERT_RDN_BMP_STRING ||
pAttr->dwValueType == CERT_RDN_UTF8_STRING) {
printf(" [%d,%d] %s (%S) %S\n",
i, j, pszObjId, GetOIDName(pszObjId), pAttr->Value.pbData);
} else
printf(" [%d,%d] %s (%S) %s\n",
i, j, pszObjId, GetOIDName(pszObjId), pAttr->Value.pbData);
}
}
fResult = TRUE;
goto CommonReturn;
ErrorReturn:
fResult = FALSE;
CommonReturn:
if (pInfo)
TestFree(pInfo);
return fResult;
}
static void DisplayAltNameEntry(
PCERT_ALT_NAME_ENTRY pEntry,
DWORD dwDisplayFlags)
{
switch (pEntry->dwAltNameChoice) {
case CERT_ALT_NAME_OTHER_NAME:
printf("OtherName: %s\n", pEntry->pOtherName->pszObjId);
PrintBytes(" ", pEntry->pOtherName->Value.pbData,
pEntry->pOtherName->Value.cbData);
break;
case CERT_ALT_NAME_X400_ADDRESS:
printf("X400Address:\n");
break;
case CERT_ALT_NAME_DIRECTORY_NAME:
printf("DirectoryName:\n");
DecodeName(pEntry->DirectoryName.pbData,
pEntry->DirectoryName.cbData, dwDisplayFlags);
break;
case CERT_ALT_NAME_EDI_PARTY_NAME:
printf("EdiPartyName:\n");
break;
case CERT_ALT_NAME_RFC822_NAME:
printf("RFC822: %S\n", pEntry->pwszRfc822Name);
break;
case CERT_ALT_NAME_DNS_NAME:
printf("DNS: %S\n", pEntry->pwszDNSName);
break;
case CERT_ALT_NAME_URL:
printf("URL: %S\n", pEntry->pwszURL);
break;
case CERT_ALT_NAME_IP_ADDRESS:
printf("IPAddress:\n");
PrintBytes(" ", pEntry->IPAddress.pbData, pEntry->IPAddress.cbData);
break;
case CERT_ALT_NAME_REGISTERED_ID:
printf("RegisteredID: %s\n", pEntry->pszRegisteredID);
break;
default:
printf("Unknown choice: %d\n", pEntry->dwAltNameChoice);
}
}
static void DisplayAltName(
PCERT_ALT_NAME_INFO pInfo,
DWORD dwDisplayFlags)
{
DWORD i;
PCERT_ALT_NAME_ENTRY pEntry = pInfo->rgAltEntry;
DWORD cEntry = pInfo->cAltEntry;
for (i = 0; i < cEntry; i++, pEntry++) {
printf(" [%d] ", i);
DisplayAltNameEntry(pEntry, dwDisplayFlags);
}
}
static void DecodeAndDisplayAltName(
BYTE *pbEncoded,
DWORD cbEncoded,
DWORD dwDisplayFlags)
{
PCERT_ALT_NAME_INFO pInfo = NULL;
if (NULL == (pInfo = (PCERT_ALT_NAME_INFO) TestNoCopyDecodeObject(
X509_ALTERNATE_NAME,
pbEncoded,
cbEncoded
))) goto CommonReturn;
DisplayAltName(pInfo, dwDisplayFlags);
CommonReturn:
if (pInfo)
TestFree(pInfo);
}
static void DisplayAuthorityKeyIdExtension(
BYTE *pbEncoded,
DWORD cbEncoded,
DWORD dwDisplayFlags)
{
PCERT_AUTHORITY_KEY_ID_INFO pInfo;
printf(" <AuthorityKeyId>\n");
if (NULL == (pInfo = (PCERT_AUTHORITY_KEY_ID_INFO) TestNoCopyDecodeObject(
X509_AUTHORITY_KEY_ID,
pbEncoded,
cbEncoded
))) goto CommonReturn;
if (pInfo->KeyId.cbData) {
printf(" KeyId::\n");
PrintBytes(" ", pInfo->KeyId.pbData, pInfo->KeyId.cbData);
}
if (pInfo->CertIssuer.cbData) {
printf(" CertIssuer::\n");
DecodeName(pInfo->CertIssuer.pbData, pInfo->CertIssuer.cbData,
dwDisplayFlags);
}
if (pInfo->CertSerialNumber.cbData) {
printf(" CertSerialNumber::");
DisplaySerialNumber(&pInfo->CertSerialNumber);
printf("\n");
}
CommonReturn:
if (pInfo)
TestFree(pInfo);
}
static void DisplayAuthorityKeyId2Extension(
BYTE *pbEncoded,
DWORD cbEncoded,
DWORD dwDisplayFlags)
{
PCERT_AUTHORITY_KEY_ID2_INFO pInfo;
printf(" <AuthorityKeyId #2>\n");
if (NULL == (pInfo = (PCERT_AUTHORITY_KEY_ID2_INFO) TestNoCopyDecodeObject(
X509_AUTHORITY_KEY_ID2,
pbEncoded,
cbEncoded
))) goto CommonReturn;
if (pInfo->KeyId.cbData) {
printf(" KeyId::\n");
PrintBytes(" ", pInfo->KeyId.pbData, pInfo->KeyId.cbData);
}
if (pInfo->AuthorityCertIssuer.cAltEntry) {
printf(" AuthorityCertIssuer::\n");
DisplayAltName(&pInfo->AuthorityCertIssuer, dwDisplayFlags);
}
if (pInfo->AuthorityCertSerialNumber.cbData) {
printf(" AuthorityCertSerialNumber::");
DisplaySerialNumber(&pInfo->AuthorityCertSerialNumber);
printf("\n");
}
CommonReturn:
if (pInfo)
TestFree(pInfo);
}
static void DisplayKeyAttrExtension(
BYTE *pbEncoded,
DWORD cbEncoded,
DWORD dwDisplayFlags)
{
PCERT_KEY_ATTRIBUTES_INFO pInfo;
if (NULL == (pInfo = (PCERT_KEY_ATTRIBUTES_INFO) TestNoCopyDecodeObject(
X509_KEY_ATTRIBUTES,
pbEncoded,
cbEncoded
))) goto CommonReturn;
if (pInfo->KeyId.cbData) {
printf(" KeyId::\n");
PrintBytes(" ", pInfo->KeyId.pbData, pInfo->KeyId.cbData);
}
if (pInfo->IntendedKeyUsage.cbData) {
BYTE bFlags = *pInfo->IntendedKeyUsage.pbData;
printf(" IntendedKeyUsage:: ");
if (bFlags == 0)
printf("<NONE> ");
if (bFlags & CERT_DIGITAL_SIGNATURE_KEY_USAGE)
printf("DIGITAL_SIGNATURE ");
if (bFlags & CERT_NON_REPUDIATION_KEY_USAGE)
printf("NON_REPUDIATION ");
if (bFlags & CERT_KEY_ENCIPHERMENT_KEY_USAGE)
printf("KEY_ENCIPHERMENT ");
if (bFlags & CERT_DATA_ENCIPHERMENT_KEY_USAGE)
printf("DATA_ENCIPHERMENT ");
if (bFlags & CERT_KEY_AGREEMENT_KEY_USAGE)
printf("KEY_AGREEMENT ");
if (bFlags & CERT_KEY_CERT_SIGN_KEY_USAGE)
printf("KEY_CERT ");
if (bFlags & CERT_OFFLINE_CRL_SIGN_KEY_USAGE)
printf("OFFLINE_CRL_SIGN ");
printf("\n");
}
if (pInfo->pPrivateKeyUsagePeriod) {
PCERT_PRIVATE_KEY_VALIDITY p = pInfo->pPrivateKeyUsagePeriod;
printf(" NotBefore:: %s\n", FileTimeText(&p->NotBefore));
printf(" NotAfter:: %s\n", FileTimeText(&p->NotAfter));
}
CommonReturn:
if (pInfo)
TestFree(pInfo);
}
static void DisplayKeyUsageRestrictionExtension(
BYTE *pbEncoded,
DWORD cbEncoded,
DWORD dwDisplayFlags)
{
PCERT_KEY_USAGE_RESTRICTION_INFO pInfo;
if (NULL == (pInfo =
(PCERT_KEY_USAGE_RESTRICTION_INFO) TestNoCopyDecodeObject(
X509_KEY_USAGE_RESTRICTION,
pbEncoded,
cbEncoded
))) goto ErrorReturn;
if (pInfo->cCertPolicyId) {
DWORD i, j;
printf(" CertPolicySet::\n");
PCERT_POLICY_ID pPolicyId = pInfo->rgCertPolicyId;
for (i = 0; i < pInfo->cCertPolicyId; i++, pPolicyId++) {
if (pPolicyId->cCertPolicyElementId == 0)
printf(" [%d,*] <NO ELEMENTS>\n", i);
LPSTR *ppszObjId = pPolicyId->rgpszCertPolicyElementId;
for (j = 0; j < pPolicyId->cCertPolicyElementId; j++, ppszObjId++) {
LPSTR pszObjId = *ppszObjId;
if (pszObjId == NULL)
pszObjId = "<NULL OBJID>";
printf(" [%d,%d] %s\n", i, j, pszObjId);
}
}
}
if (pInfo->RestrictedKeyUsage.cbData) {
BYTE bFlags = *pInfo->RestrictedKeyUsage.pbData;
printf(" RestrictedKeyUsage:: ");
if (bFlags == 0)
printf("<NONE> ");
if (bFlags & CERT_DIGITAL_SIGNATURE_KEY_USAGE)
printf("DIGITAL_SIGNATURE ");
if (bFlags & CERT_NON_REPUDIATION_KEY_USAGE)
printf("NON_REPUDIATION ");
if (bFlags & CERT_KEY_ENCIPHERMENT_KEY_USAGE)
printf("KEY_ENCIPHERMENT ");
if (bFlags & CERT_DATA_ENCIPHERMENT_KEY_USAGE)
printf("DATA_ENCIPHERMENT ");
if (bFlags & CERT_KEY_AGREEMENT_KEY_USAGE)
printf("KEY_AGREEMENT ");
if (bFlags & CERT_KEY_CERT_SIGN_KEY_USAGE)
printf("KEY_CERT ");
if (bFlags & CERT_OFFLINE_CRL_SIGN_KEY_USAGE)
printf("OFFLINE_CRL_SIGN ");
printf("\n");
}
goto CommonReturn;
ErrorReturn:
CommonReturn:
if (pInfo)
TestFree(pInfo);
}
static void DisplayBasicConstraintsExtension(
BYTE *pbEncoded,
DWORD cbEncoded,
DWORD dwDisplayFlags)
{
PCERT_BASIC_CONSTRAINTS_INFO pInfo;
if (NULL == (pInfo = (PCERT_BASIC_CONSTRAINTS_INFO) TestNoCopyDecodeObject(
X509_BASIC_CONSTRAINTS,
pbEncoded,
cbEncoded
))) goto ErrorReturn;
printf(" SubjectType:: ");
if (pInfo->SubjectType.cbData == 0)
printf("<NONE> ");
else {
BYTE bSubjectType = *pInfo->SubjectType.pbData;
if (bSubjectType == 0)
printf("<NONE> ");
if (bSubjectType & CERT_CA_SUBJECT_FLAG)
printf("CA ");
if (bSubjectType & CERT_END_ENTITY_SUBJECT_FLAG)
printf("END_ENTITY ");
}
printf("\n");
printf(" PathLenConstraint:: ");
if (pInfo->fPathLenConstraint)
printf("%d", pInfo->dwPathLenConstraint);
else
printf("<NONE>");
printf("\n");
if (pInfo->cSubtreesConstraint) {
DWORD i;
PCERT_NAME_BLOB pSubtrees = pInfo->rgSubtreesConstraint;
for (i = 0; i < pInfo->cSubtreesConstraint; i++, pSubtrees++) {
printf(" SubtreesConstraint[%d]::\n", i);
DecodeName(pSubtrees->pbData, pSubtrees->cbData, dwDisplayFlags);
}
}
goto CommonReturn;
ErrorReturn:
CommonReturn:
if (pInfo)
TestFree(pInfo);
}
static void DisplayKeyUsageExtension(
BYTE *pbEncoded,
DWORD cbEncoded,
DWORD dwDisplayFlags)
{
PCRYPT_BIT_BLOB pInfo;
BYTE bFlags;
if (NULL == (pInfo =
(PCRYPT_BIT_BLOB) TestNoCopyDecodeObject(
X509_KEY_USAGE,
pbEncoded,
cbEncoded
))) goto ErrorReturn;
printf(" KeyUsage:: ");
if (pInfo->cbData)
bFlags = *pInfo->pbData;
else
bFlags = 0;
if (bFlags == 0)
printf("<NONE> ");
if (bFlags & CERT_DIGITAL_SIGNATURE_KEY_USAGE)
printf("DIGITAL_SIGNATURE ");
if (bFlags & CERT_NON_REPUDIATION_KEY_USAGE)
printf("NON_REPUDIATION ");
if (bFlags & CERT_KEY_ENCIPHERMENT_KEY_USAGE)
printf("KEY_ENCIPHERMENT ");
if (bFlags & CERT_DATA_ENCIPHERMENT_KEY_USAGE)
printf("DATA_ENCIPHERMENT ");
if (bFlags & CERT_KEY_AGREEMENT_KEY_USAGE)
printf("KEY_AGREEMENT ");
if (bFlags & CERT_KEY_CERT_SIGN_KEY_USAGE)
printf("KEY_CERT ");
if (bFlags & CERT_OFFLINE_CRL_SIGN_KEY_USAGE)
printf("OFFLINE_CRL_SIGN ");
printf("\n");
ErrorReturn:
if (pInfo)
TestFree(pInfo);
}
static void DisplayBasicConstraints2Extension(
BYTE *pbEncoded,
DWORD cbEncoded,
DWORD dwDisplayFlags)
{
PCERT_BASIC_CONSTRAINTS2_INFO pInfo;
if (NULL == (pInfo = (PCERT_BASIC_CONSTRAINTS2_INFO) TestNoCopyDecodeObject(
X509_BASIC_CONSTRAINTS2,
pbEncoded,
cbEncoded
))) goto ErrorReturn;
printf(" Basic Constraints:: ");
if (pInfo->fCA)
printf("CA\n");
else
printf("End-user\n");
printf(" PathLenConstraint:: ");
if (pInfo->fPathLenConstraint)
printf("%d", pInfo->dwPathLenConstraint);
else
printf("<NONE>");
printf("\n");
ErrorReturn:
if (pInfo)
TestFree(pInfo);
}
static void DisplayPoliciesExtension(
LPSTR pszType, // "Certificate" | "Revocation" | "Application"
BYTE *pbEncoded,
DWORD cbEncoded,
DWORD dwDisplayFlags)
{
PCERT_POLICIES_INFO pInfo;
DWORD cPolicy;
PCERT_POLICY_INFO pPolicy;
DWORD i;
if (NULL == (pInfo =
(PCERT_POLICIES_INFO) TestNoCopyDecodeObject(
X509_CERT_POLICIES,
pbEncoded,
cbEncoded
))) goto ErrorReturn;
cPolicy = pInfo->cPolicyInfo;
pPolicy = pInfo->rgPolicyInfo;
if (cPolicy == 0)
printf(" No %s Policies\n", pszType);
else
printf(" %s Policies::\n", pszType);
for (i = 0; i < cPolicy; i++, pPolicy++) {
DWORD cQualifier = pPolicy->cPolicyQualifier;
PCERT_POLICY_QUALIFIER_INFO pQualifier;
DWORD j;
if (pPolicy->pszPolicyIdentifier)
printf(" [%d] %s", i, pPolicy->pszPolicyIdentifier);
if (cQualifier)
printf(" Qualifiers::");
printf("\n");
pQualifier = pPolicy->rgPolicyQualifier;
for (j = 0; j < cQualifier; j++, pQualifier++) {
printf(" [%d] %s", j, pQualifier->pszPolicyQualifierId);
if (pQualifier->Qualifier.cbData) {
printf(" Encoded Data::\n");
PrintBytes(" ",
pQualifier->Qualifier.pbData, pQualifier->Qualifier.cbData);
} else
printf("\n");
}
}
ErrorReturn:
if (pInfo)
TestFree(pInfo);
}
static void DisplaySMIMECapabilitiesExtension(
BYTE *pbEncoded,
DWORD cbEncoded,
DWORD dwDisplayFlags)
{
PCRYPT_SMIME_CAPABILITIES pInfo;
DWORD cCap;
PCRYPT_SMIME_CAPABILITY pCap;
DWORD i;
if (NULL == (pInfo =
(PCRYPT_SMIME_CAPABILITIES) TestNoCopyDecodeObject(
PKCS_SMIME_CAPABILITIES,
pbEncoded,
cbEncoded
))) goto ErrorReturn;
cCap = pInfo->cCapability;
pCap = pInfo->rgCapability;
if (cCap == 0)
printf(" No SMIME Capabilities\n");
else
printf(" SMIME Capabilties::\n");
for (i = 0; i < cCap; i++, pCap++) {
LPSTR pszObjId = pCap->pszObjId;
printf(" [%d] %s (%S)", i, pszObjId, GetOIDName(pszObjId));
if (pCap->Parameters.cbData) {
printf(" Parameters::\n");
PrintBytes(" ",
pCap->Parameters.pbData,
pCap->Parameters.cbData);
} else
printf("\n");
}
ErrorReturn:
if (pInfo)
TestFree(pInfo);
}
static void DecodeAndDisplayCtlUsage(
BYTE *pbEncoded,
DWORD cbEncoded,
DWORD dwDisplayFlags)
{
PCTL_USAGE pInfo;
DWORD cId;
LPSTR *ppszId;
DWORD i;
if (NULL == (pInfo =
(PCTL_USAGE) TestNoCopyDecodeObject(
X509_ENHANCED_KEY_USAGE,
pbEncoded,
cbEncoded
))) goto ErrorReturn;
cId = pInfo->cUsageIdentifier;
ppszId = pInfo->rgpszUsageIdentifier;
if (cId == 0)
printf(" No Usage Identifiers\n");
for (i = 0; i < cId; i++, ppszId++)
printf(" [%d] %s\n", i, *ppszId);
ErrorReturn:
if (pInfo)
TestFree(pInfo);
}
static void DisplayEnhancedKeyUsageExtension(
BYTE *pbEncoded,
DWORD cbEncoded,
DWORD dwDisplayFlags)
{
printf(" EnhancedKeyUsage::\n");
DecodeAndDisplayCtlUsage(pbEncoded, cbEncoded, dwDisplayFlags);
}
static void DisplayAltNameExtension(
LPCSTR pszExt,
BYTE *pbEncoded,
DWORD cbEncoded,
DWORD dwDisplayFlags)
{
printf(" <%s>\n", pszExt);
DecodeAndDisplayAltName(pbEncoded, cbEncoded, dwDisplayFlags);
}
static void DisplayNameConstraintsSubtree(
DWORD cSubtree,
PCERT_GENERAL_SUBTREE pSubtree,
DWORD dwDisplayFlags
)
{
DWORD i;
for (i = 0; i < cSubtree; i++, pSubtree++) {
printf(" Subtree[%d] ", i);
if (pSubtree->dwMinimum || pSubtree->fMaximum) {
printf("(%d ", pSubtree->dwMinimum);
if (pSubtree->fMaximum)
printf("- %d) ", pSubtree->dwMaximum);
else
printf("...) ");
}
DisplayAltNameEntry(&pSubtree->Base, dwDisplayFlags);
}
}
static void DisplayNameConstraintsExtension(
BYTE *pbEncoded,
DWORD cbEncoded,
DWORD dwDisplayFlags)
{
PCERT_NAME_CONSTRAINTS_INFO pInfo = NULL;
if (NULL == (pInfo = (PCERT_NAME_CONSTRAINTS_INFO) TestNoCopyDecodeObject(
X509_NAME_CONSTRAINTS,
pbEncoded,
cbEncoded
))) goto CommonReturn;
if (pInfo->cPermittedSubtree) {
printf(" <PermittedSubtree>\n");
DisplayNameConstraintsSubtree(pInfo->cPermittedSubtree,
pInfo->rgPermittedSubtree, dwDisplayFlags);
} else
printf(" No PermittedSubtree\n");
if (pInfo->cExcludedSubtree) {
printf(" <ExcludedSubtree>\n");
DisplayNameConstraintsSubtree(pInfo->cExcludedSubtree,
pInfo->rgExcludedSubtree, dwDisplayFlags);
} else
printf(" No ExcludedSubtree\n");
CommonReturn:
if (pInfo)
TestFree(pInfo);
}
static void DisplayPolicyMappingsExtension(
BYTE *pbEncoded,
DWORD cbEncoded,
DWORD dwDisplayFlags)
{
PCERT_POLICY_MAPPINGS_INFO pInfo = NULL;
DWORD i;
if (NULL == (pInfo = (PCERT_POLICY_MAPPINGS_INFO) TestNoCopyDecodeObject(
X509_POLICY_MAPPINGS,
pbEncoded,
cbEncoded
))) goto CommonReturn;
if (pInfo->cPolicyMapping) {
for (i = 0; i < pInfo->cPolicyMapping; i++) {
printf(" [%d] Issuer: %s Subject: %s\n", i,
pInfo->rgPolicyMapping[i].pszIssuerDomainPolicy,
pInfo->rgPolicyMapping[i].pszSubjectDomainPolicy);
}
} else
printf(" No PolicyMappings\n");
CommonReturn:
if (pInfo)
TestFree(pInfo);
}
static void DisplayPolicyConstraintsExtension(
BYTE *pbEncoded,
DWORD cbEncoded,
DWORD dwDisplayFlags)
{
PCERT_POLICY_CONSTRAINTS_INFO pInfo = NULL;
if (NULL == (pInfo = (PCERT_POLICY_CONSTRAINTS_INFO) TestNoCopyDecodeObject(
X509_POLICY_CONSTRAINTS,
pbEncoded,
cbEncoded
))) goto CommonReturn;
if (pInfo->fRequireExplicitPolicy)
printf(" RequireExplicitPolicySkipCerts: %d",
pInfo->dwRequireExplicitPolicySkipCerts);
if (pInfo->fInhibitPolicyMapping)
printf(" InhibitPolicyMappingSkipCerts: %d",
pInfo->dwInhibitPolicyMappingSkipCerts);
printf("\n");
CommonReturn:
if (pInfo)
TestFree(pInfo);
}
static void DisplayCrossCertDistPointsExtension(
BYTE *pbEncoded,
DWORD cbEncoded,
DWORD dwDisplayFlags)
{
PCROSS_CERT_DIST_POINTS_INFO pInfo = NULL;
DWORD i;
if (NULL == (pInfo = (PCROSS_CERT_DIST_POINTS_INFO) TestNoCopyDecodeObject(
X509_CROSS_CERT_DIST_POINTS,
pbEncoded,
cbEncoded
))) goto CommonReturn;
printf(" SyncDeltaTime (seconds) : %d\n", pInfo->dwSyncDeltaTime);
for (i = 0; i < pInfo->cDistPoint; i++) {
printf(" DistPoint[%d]\n", i);
DisplayAltName(&pInfo->rgDistPoint[i], dwDisplayFlags);
}
CommonReturn:
if (pInfo)
TestFree(pInfo);
}
static void DisplayAccessDescriptions(
LPCSTR pszAccDescr,
DWORD cAccDescr,
PCERT_ACCESS_DESCRIPTION pAccDescr,
DWORD dwDisplayFlags)
{
DWORD i;
for (i = 0; i < cAccDescr; i++, pAccDescr++) {
printf(" %s[%d] %s ", pszAccDescr, i, pAccDescr->pszAccessMethod);
DisplayAltNameEntry(&pAccDescr->AccessLocation, dwDisplayFlags);
}
}
static void DisplayAuthorityInfoAccessExtension(
BYTE *pbEncoded,
DWORD cbEncoded,
DWORD dwDisplayFlags)
{
PCERT_AUTHORITY_INFO_ACCESS pInfo = NULL;
if (NULL == (pInfo = (PCERT_AUTHORITY_INFO_ACCESS) TestNoCopyDecodeObject(
X509_AUTHORITY_INFO_ACCESS,
pbEncoded,
cbEncoded
))) goto CommonReturn;
printf(" <AuthorityInfoAccess>\n");
if (pInfo->cAccDescr)
DisplayAccessDescriptions("",
pInfo->cAccDescr, pInfo->rgAccDescr, dwDisplayFlags);
CommonReturn:
if (pInfo)
TestFree(pInfo);
}
static void DisplayCrlDistPointsExtension(
BYTE *pbEncoded,
DWORD cbEncoded,
DWORD dwDisplayFlags)
{
PCRL_DIST_POINTS_INFO pInfo = NULL;
DWORD i;
if (NULL == (pInfo = (PCRL_DIST_POINTS_INFO) TestNoCopyDecodeObject(
X509_CRL_DIST_POINTS,
pbEncoded,
cbEncoded
))) goto CommonReturn;
if (0 == pInfo->cDistPoint)
printf(" NO CRL Distribution Points\n");
else {
DWORD cPoint = pInfo->cDistPoint;
PCRL_DIST_POINT pPoint = pInfo->rgDistPoint;
for (i = 0; i < cPoint; i++, pPoint++) {
printf(" CRL Distribution Point[%d]\n", i);
DWORD dwNameChoice = pPoint->DistPointName.dwDistPointNameChoice;
switch (dwNameChoice) {
case CRL_DIST_POINT_NO_NAME:
break;
case CRL_DIST_POINT_FULL_NAME:
printf(" FullName:\n");
DisplayAltName(&pPoint->DistPointName.FullName,
dwDisplayFlags);
break;
case CRL_DIST_POINT_ISSUER_RDN_NAME:
printf(" IssuerRDN: (Not Implemented)\n");
break;
default:
printf(" Unknown name choice: %d\n", dwNameChoice);
}
if (pPoint->ReasonFlags.cbData) {
BYTE bFlags;
printf(" ReasonFlags: ");
bFlags = *pPoint->ReasonFlags.pbData;
if (bFlags == 0)
printf("<NONE> ");
if (bFlags & CRL_REASON_UNUSED_FLAG)
printf("UNUSED ");
if (bFlags & CRL_REASON_KEY_COMPROMISE_FLAG)
printf("KEY_COMPROMISE ");
if (bFlags & CRL_REASON_CA_COMPROMISE_FLAG)
printf("CA_COMPROMISE ");
if (bFlags & CRL_REASON_AFFILIATION_CHANGED_FLAG)
printf("AFFILIATION_CHANGED ");
if (bFlags & CRL_REASON_SUPERSEDED_FLAG)
printf("SUPERSEDED ");
if (bFlags & CRL_REASON_CESSATION_OF_OPERATION_FLAG)
printf("CESSATION_OF_OPERATION ");
if (bFlags & CRL_REASON_CERTIFICATE_HOLD_FLAG)
printf("CERTIFICATE_HOLD ");
printf("\n");
}
if (pPoint->CRLIssuer.cAltEntry) {
printf(" CRLIssuer:");
DisplayAltName(&pPoint->CRLIssuer, dwDisplayFlags);
}
}
}
CommonReturn:
if (pInfo)
TestFree(pInfo);
}
static void DisplayIssuingDistPointExtension(
BYTE *pbEncoded,
DWORD cbEncoded,
DWORD dwDisplayFlags)
{
PCRL_ISSUING_DIST_POINT pInfo = NULL;
DWORD i;
DWORD dwNameChoice;
if (NULL == (pInfo = (PCRL_ISSUING_DIST_POINT) TestNoCopyDecodeObject(
X509_ISSUING_DIST_POINT,
pbEncoded,
cbEncoded
))) goto CommonReturn;
dwNameChoice = pInfo->DistPointName.dwDistPointNameChoice;
switch (dwNameChoice) {
case CRL_DIST_POINT_NO_NAME:
printf(" No DistPointName\n");
break;
case CRL_DIST_POINT_FULL_NAME:
printf(" DistPointName FullName:\n");
DisplayAltName(&pInfo->DistPointName.FullName,
dwDisplayFlags);
break;
case CRL_DIST_POINT_ISSUER_RDN_NAME:
printf(" DistPointName IssuerRDN: (Not Implemented)\n");
break;
default:
printf(" Unknown DistPointName choice: %d\n", dwNameChoice);
}
if (pInfo->fOnlyContainsUserCerts ||
pInfo->fOnlyContainsCACerts ||
pInfo->fIndirectCRL
) {
printf(" ");
if (pInfo->fOnlyContainsUserCerts)
printf(" OnlyContainsUserCerts");
if (pInfo->fOnlyContainsCACerts)
printf(" OnlyContainsCACerts");
if (pInfo->fIndirectCRL)
printf(" IndirectCRL");
printf("\n");
}
if (pInfo->OnlySomeReasonFlags.cbData) {
BYTE bFlags;
printf(" OnlySomeReasonFlags: ");
bFlags = *pInfo->OnlySomeReasonFlags.pbData;
if (bFlags == 0)
printf("<NONE> ");
if (bFlags & CRL_REASON_UNUSED_FLAG)
printf("UNUSED ");
if (bFlags & CRL_REASON_KEY_COMPROMISE_FLAG)
printf("KEY_COMPROMISE ");
if (bFlags & CRL_REASON_CA_COMPROMISE_FLAG)
printf("CA_COMPROMISE ");
if (bFlags & CRL_REASON_AFFILIATION_CHANGED_FLAG)
printf("AFFILIATION_CHANGED ");
if (bFlags & CRL_REASON_SUPERSEDED_FLAG)
printf("SUPERSEDED ");
if (bFlags & CRL_REASON_CESSATION_OF_OPERATION_FLAG)
printf("CESSATION_OF_OPERATION ");
if (bFlags & CRL_REASON_CERTIFICATE_HOLD_FLAG)
printf("CERTIFICATE_HOLD ");
printf("\n");
}
CommonReturn:
if (pInfo)
TestFree(pInfo);
}
static void DisplaySETAccountAliasExtension(
BYTE *pbEncoded,
DWORD cbEncoded,
DWORD dwDisplayFlags)
{
BOOL bInfo = FALSE;
DWORD cbInfo;
cbInfo = sizeof(bInfo);
if (!CryptDecodeObject(
dwCertEncodingType,
szOID_SET_ACCOUNT_ALIAS,
pbEncoded,
cbEncoded,
0, // dwFlags
&bInfo,
&cbInfo
)) {
PrintLastError("SETAccountAliasDecode");
goto CommonReturn;
}
if (bInfo)
printf(" SETAccountAlias:: TRUE\n");
else
printf(" SETAccountAlias:: FALSE\n");
CommonReturn:
return;
}
static void DisplaySETHashedRootKeyExtension(
BYTE *pbEncoded,
DWORD cbEncoded,
DWORD dwDisplayFlags)
{
BYTE rgbInfo[SET_HASHED_ROOT_LEN];
DWORD cbInfo;
cbInfo = sizeof(rgbInfo);
if (!CryptDecodeObject(
dwCertEncodingType,
szOID_SET_HASHED_ROOT_KEY,
pbEncoded,
cbEncoded,
0, // dwFlags
rgbInfo,
&cbInfo
)) {
PrintLastError("SETHashedRootKeyDecode");
goto CommonReturn;
}
DisplayThumbprint(" SETHashedRootKey", rgbInfo, cbInfo);
CommonReturn:
return;
}
static void DisplaySETCertTypeExtension(
BYTE *pbEncoded,
DWORD cbEncoded,
DWORD dwDisplayFlags)
{
PCRYPT_BIT_BLOB pInfo;
if (NULL == (pInfo = (PCRYPT_BIT_BLOB) TestNoCopyDecodeObject(
szOID_SET_CERTIFICATE_TYPE,
pbEncoded,
cbEncoded
))) goto ErrorReturn;
printf(" SETCertificateType:: ");
if (pInfo->cbData == 0)
printf("<NONE> ");
else {
DWORD cb;
BYTE *pb;
for (cb = pInfo->cbData, pb = pInfo->pbData; cb > 0; cb--, pb++)
printf(" %02X", *pb);
}
printf("\n");
goto CommonReturn;
ErrorReturn:
CommonReturn:
if (pInfo)
TestFree(pInfo);
}
static void DisplaySETMerchantDataExtension(
BYTE *pbEncoded,
DWORD cbEncoded,
DWORD dwDisplayFlags)
{
PSET_MERCHANT_DATA_INFO pInfo;
if (NULL == (pInfo = (PSET_MERCHANT_DATA_INFO) TestNoCopyDecodeObject(
szOID_SET_MERCHANT_DATA,
pbEncoded,
cbEncoded
))) goto ErrorReturn;
printf(" SETMerchantData:: \n");
if(pInfo->pszMerID && *pInfo->pszMerID)
printf(" MerID: %s\n", pInfo->pszMerID);
if(pInfo->pszMerAcquirerBIN && *pInfo->pszMerAcquirerBIN)
printf(" MerAcquirerBIN: %s\n", pInfo->pszMerAcquirerBIN);
if(pInfo->pszMerTermID && *pInfo->pszMerTermID)
printf(" MerTermID: %s\n", pInfo->pszMerTermID);
if(pInfo->pszMerName && *pInfo->pszMerName)
printf(" MerName: %s\n", pInfo->pszMerName);
if(pInfo->pszMerCity && *pInfo->pszMerCity)
printf(" MerCity: %s\n", pInfo->pszMerCity);
if(pInfo->pszMerStateProvince && *pInfo->pszMerStateProvince)
printf(" MerStateProvince: %s\n", pInfo->pszMerStateProvince);
if(pInfo->pszMerPostalCode && *pInfo->pszMerPostalCode)
printf(" MerPostalCode: %s\n", pInfo->pszMerPostalCode);
if(pInfo->pszMerCountry && *pInfo->pszMerCountry)
printf(" MerCountry: %s\n", pInfo->pszMerCountry);
if(pInfo->pszMerPhone && *pInfo->pszMerPhone)
printf(" MerPhone: %s\n", pInfo->pszMerPhone);
if(pInfo->fMerPhoneRelease)
printf(" MerPhoneRelease: TRUE\n");
else
printf(" MerPhoneRelease: FALSE\n");
if(pInfo->fMerAuthFlag)
printf(" MerAuthFlag: TRUE\n");
else
printf(" MerAuthFlag: FALSE\n");
goto CommonReturn;
ErrorReturn:
CommonReturn:
if (pInfo)
TestFree(pInfo);
}
#pragma pack(1)
struct SplitGuid
{
DWORD dw1;
WORD w1;
WORD w2;
BYTE b[8];
};
#pragma pack()
static char *GuidText(GUID *pguid)
{
static char buf[39];
SplitGuid *psg = (SplitGuid *)pguid;
sprintf(buf, "{%08lX-%04hX-%04hX-%02X%02X-%02X%02X%02X%02X%02X%02X}",
psg->dw1, psg->w1, psg->w2, psg->b[0], psg->b[1], psg->b[2],
psg->b[3], psg->b[4], psg->b[5], psg->b[6], psg->b[7]);
return buf;
}
void DisplaySpcLink(PSPC_LINK pSpcLink)
{
switch (pSpcLink->dwLinkChoice) {
case SPC_URL_LINK_CHOICE:
printf("URL=> %S\n", pSpcLink->pwszUrl);
break;
case SPC_MONIKER_LINK_CHOICE:
printf("%s\n", GuidText((GUID *) pSpcLink->Moniker.ClassId));
if (pSpcLink->Moniker.SerializedData.cbData) {
printf(" SerializedData::\n");
PrintBytes(" ", pSpcLink->Moniker.SerializedData.pbData,
pSpcLink->Moniker.SerializedData.cbData);
}
break;
case SPC_FILE_LINK_CHOICE:
printf("FILE=> %S\n", pSpcLink->pwszFile);
break;
default:
printf("Bad SPC Link Choice:: %d\n", pSpcLink->dwLinkChoice);
}
}
static void DisplaySpcSpAgencyExtension(
BYTE *pbEncoded,
DWORD cbEncoded,
DWORD dwDisplayFlags)
{
PSPC_SP_AGENCY_INFO pInfo;
if (NULL == (pInfo = (PSPC_SP_AGENCY_INFO) TestNoCopyDecodeObject(
SPC_SP_AGENCY_INFO_OBJID,
pbEncoded,
cbEncoded
))) goto ErrorReturn;
printf(" SpAgencyInfo::\n");
if (pInfo->pPolicyInformation) {
printf(" PolicyInformation: ");
DisplaySpcLink(pInfo->pPolicyInformation);
}
if (pInfo->pwszPolicyDisplayText) {
printf(" PolicyDisplayText: %S\n", pInfo->pwszPolicyDisplayText);
}
if (pInfo->pLogoImage) {
PSPC_IMAGE pImage = pInfo->pLogoImage;
if (pImage->pImageLink) {
printf(" ImageLink: ");
DisplaySpcLink(pImage->pImageLink);
}
if (pImage->Bitmap.cbData) {
printf(" Bitmap:\n");
PrintBytes(" ", pImage->Bitmap.pbData, pImage->Bitmap.cbData);
}
if (pImage->Metafile.cbData) {
printf(" Metafile:\n");
PrintBytes(" ", pImage->Metafile.pbData,
pImage->Metafile.cbData);
}
if (pImage->EnhancedMetafile.cbData) {
printf(" EnhancedMetafile:\n");
PrintBytes(" ", pImage->EnhancedMetafile.pbData,
pImage->EnhancedMetafile.cbData);
}
if (pImage->GifFile.cbData) {
printf(" GifFile:\n");
PrintBytes(" ", pImage->GifFile.pbData,
pImage->GifFile.cbData);
}
}
if (pInfo->pLogoLink) {
printf(" LogoLink: ");
DisplaySpcLink(pInfo->pLogoLink);
}
goto CommonReturn;
ErrorReturn:
CommonReturn:
if (pInfo)
TestFree(pInfo);
}
static void DisplaySpcFinancialCriteriaExtension(
BYTE *pbEncoded,
DWORD cbEncoded,
DWORD dwDisplayFlags)
{
SPC_FINANCIAL_CRITERIA FinancialCriteria;
DWORD cbInfo = sizeof(FinancialCriteria);
if (!CryptDecodeObject(
dwCertEncodingType,
SPC_FINANCIAL_CRITERIA_OBJID,
pbEncoded,
cbEncoded,
0, // dwFlags
&FinancialCriteria,
&cbInfo
)) {
PrintLastError("SpcFinancialCriteriaInfoDecode");
return;
}
printf(" FinancialCriteria:: ");
if (FinancialCriteria.fFinancialInfoAvailable)
printf("Financial Info Available.");
else
printf("NO Financial Info.");
if (FinancialCriteria.fMeetsCriteria)
printf(" Meets Criteria.");
else
printf(" Doesn't Meet Criteria.");
printf("\n");
}
static void DisplaySpcMinimalCriteriaExtension(
BYTE *pbEncoded,
DWORD cbEncoded,
DWORD dwDisplayFlags)
{
BOOL fMinimalCriteria;
DWORD cbInfo = sizeof(fMinimalCriteria);
if (!CryptDecodeObject(
dwCertEncodingType,
SPC_MINIMAL_CRITERIA_OBJID,
pbEncoded,
cbEncoded,
0, // dwFlags
&fMinimalCriteria,
&cbInfo)) {
PrintLastError("SpcMinimalCriteriaInfoDecode");
return;
}
printf(" MinimalCriteria:: ");
if (fMinimalCriteria)
printf("Meets Minimal Criteria.");
else
printf("Doesn't Meet Minimal Criteria.");
printf("\n");
}
static void DisplayCommonNameExtension(
BYTE *pbEncoded,
DWORD cbEncoded,
DWORD dwDisplayFlags)
{
PCERT_NAME_VALUE pInfo = NULL;
LPWSTR pwsz = NULL;
DWORD cwsz;
if (NULL == (pInfo = (PCERT_NAME_VALUE) TestNoCopyDecodeObject(
X509_NAME_VALUE,
pbEncoded,
cbEncoded
))) goto ErrorReturn;
cwsz = CertRDNValueToStrW(
pInfo->dwValueType,
&pInfo->Value,
NULL, // pwsz
0 // cwsz
);
if (cwsz > 1) {
pwsz = (LPWSTR) TestAlloc(cwsz * sizeof(WCHAR));
if (pwsz)
CertRDNValueToStrW(
pInfo->dwValueType,
&pInfo->Value,
pwsz,
cwsz
);
}
printf(" CommonName:: ValueType: %d String: ", pInfo->dwValueType);
if (pwsz)
printf("%S\n", pwsz);
else
printf("NULL");
goto CommonReturn;
ErrorReturn:
CommonReturn:
if (pInfo)
TestFree(pInfo);
if (pwsz)
TestFree(pwsz);
}
static void DisplayCRLReason(
BYTE *pbEncoded,
DWORD cbEncoded,
DWORD dwDisplayFlags)
{
DWORD cbInfo;
int CRLReason;
cbInfo = sizeof(CRLReason);
if (!CryptDecodeObject(
dwCertEncodingType,
szOID_CRL_REASON_CODE,
pbEncoded,
cbEncoded,
0, // dwFlags
&CRLReason,
&cbInfo
)) {
PrintLastError("CRLReason");
return;
}
printf(" CRL Reason:: ");
switch (CRLReason) {
case CRL_REASON_UNSPECIFIED:
printf("Unspecified");
break;
case CRL_REASON_KEY_COMPROMISE:
printf("Key Compromise");
break;
case CRL_REASON_CA_COMPROMISE:
printf("CA Compromise");
break;
case CRL_REASON_AFFILIATION_CHANGED:
printf("Affiliation Changed");
break;
case CRL_REASON_SUPERSEDED:
printf("Superseded");
break;
case CRL_REASON_CESSATION_OF_OPERATION:
printf("Cessation of Operation");
break;
case CRL_REASON_CERTIFICATE_HOLD:
printf("Certificate Hold");
break;
case CRL_REASON_REMOVE_FROM_CRL:
printf("Remove from CRL");
break;
default:
printf("%d", CRLReason);
break;
}
printf("\n");
}
static void PrintExtensions(DWORD cExt, PCERT_EXTENSION pExt, DWORD dwDisplayFlags)
{
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("Extension[%d] %s (%S) Critical: %s::\n",
i, pszObjId, GetOIDName(pszObjId), pszCritical);
PrintBytes(" ", pExt->Value.pbData, pExt->Value.cbData);
if (strcmp(pszObjId, szOID_AUTHORITY_KEY_IDENTIFIER) == 0)
DisplayAuthorityKeyIdExtension(
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_AUTHORITY_KEY_IDENTIFIER2) == 0)
DisplayAuthorityKeyId2Extension(
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_AUTHORITY_INFO_ACCESS) == 0)
DisplayAuthorityInfoAccessExtension(
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_CRL_DIST_POINTS) == 0)
DisplayCrlDistPointsExtension(
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_SUBJECT_KEY_IDENTIFIER) == 0)
DisplayOctetString(" SubjectKeyIdentifer::",
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_KEY_ATTRIBUTES) == 0)
DisplayKeyAttrExtension(
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_SUBJECT_ALT_NAME) == 0)
DisplayAltNameExtension("Subject AltName",
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_ISSUER_ALT_NAME) == 0)
DisplayAltNameExtension("Issuer AltName",
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_SUBJECT_ALT_NAME2) == 0)
DisplayAltNameExtension("Subject AltName #2",
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_ISSUER_ALT_NAME2) == 0)
DisplayAltNameExtension("Issuer AltName #2",
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_NEXT_UPDATE_LOCATION) == 0)
DisplayAltNameExtension("NextUpdateLocation",
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_KEY_USAGE_RESTRICTION) == 0)
DisplayKeyUsageRestrictionExtension(
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_BASIC_CONSTRAINTS) == 0)
DisplayBasicConstraintsExtension(
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_KEY_USAGE) == 0)
DisplayKeyUsageExtension(
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_BASIC_CONSTRAINTS2) == 0)
DisplayBasicConstraints2Extension(
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_CERT_POLICIES) == 0)
DisplayPoliciesExtension("Certificate",
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_CERT_POLICIES_95) == 0)
DisplayPoliciesExtension("Certificate",
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_APPLICATION_CERT_POLICIES) == 0)
DisplayPoliciesExtension("Application",
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_SET_ACCOUNT_ALIAS) == 0)
DisplaySETAccountAliasExtension(
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_SET_HASHED_ROOT_KEY) == 0)
DisplaySETHashedRootKeyExtension(
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_SET_CERTIFICATE_TYPE) == 0)
DisplaySETCertTypeExtension(
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_SET_MERCHANT_DATA) == 0)
DisplaySETMerchantDataExtension(
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, SPC_SP_AGENCY_INFO_OBJID) == 0)
DisplaySpcSpAgencyExtension(
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, SPC_FINANCIAL_CRITERIA_OBJID) == 0)
DisplaySpcFinancialCriteriaExtension(
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, SPC_MINIMAL_CRITERIA_OBJID) == 0)
DisplaySpcMinimalCriteriaExtension(
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_COMMON_NAME) == 0)
DisplayCommonNameExtension(
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_ENHANCED_KEY_USAGE) == 0)
DisplayEnhancedKeyUsageExtension(
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_RSA_SMIMECapabilities) == 0)
DisplaySMIMECapabilitiesExtension(
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
// CRL extensions
else if (strcmp(pszObjId, szOID_CRL_REASON_CODE) == 0)
DisplayCRLReason(
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_CRL_NUMBER) == 0)
DisplayInteger(
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_DELTA_CRL_INDICATOR) == 0)
DisplayInteger(
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_ISSUING_DIST_POINT) == 0)
DisplayIssuingDistPointExtension(
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_FRESHEST_CRL) == 0)
DisplayCrlDistPointsExtension(
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_NAME_CONSTRAINTS) == 0)
DisplayNameConstraintsExtension(
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_POLICY_MAPPINGS) == 0)
DisplayPolicyMappingsExtension(
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_LEGACY_POLICY_MAPPINGS) == 0)
DisplayPolicyMappingsExtension(
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_APPLICATION_POLICY_MAPPINGS) == 0)
DisplayPolicyMappingsExtension(
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_POLICY_CONSTRAINTS) == 0)
DisplayPolicyConstraintsExtension(
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_APPLICATION_POLICY_CONSTRAINTS) == 0)
DisplayPolicyConstraintsExtension(
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_CROSS_CERT_DIST_POINTS) == 0)
DisplayCrossCertDistPointsExtension(
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
// Netscape extensions
else if (strcmp(pszObjId, szOID_NETSCAPE_CERT_TYPE) == 0)
DisplayBits(" NetscapeCertType::",
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_NETSCAPE_BASE_URL) == 0)
DisplayAnyString(" NetscapeBaseURL::",
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_NETSCAPE_REVOCATION_URL) == 0)
DisplayAnyString(" NetscapeRevocationURL::",
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_NETSCAPE_CA_REVOCATION_URL) == 0)
DisplayAnyString(" NetscapeCARevocationURL::",
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_NETSCAPE_CERT_RENEWAL_URL) == 0)
DisplayAnyString(" NetscapeCertRenewalURL::",
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_NETSCAPE_CA_POLICY_URL) == 0)
DisplayAnyString(" NetscapeCAPolicyURL::",
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_NETSCAPE_SSL_SERVER_NAME) == 0)
DisplayAnyString(" NetscapeSSLServerName::",
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
else if (strcmp(pszObjId, szOID_NETSCAPE_COMMENT) == 0)
DisplayAnyString(" NetscapeComment::",
pExt->Value.pbData, pExt->Value.cbData, dwDisplayFlags);
}
}
static void DecodeAndDisplayDSSParameters(
IN BYTE *pbData,
IN DWORD cbData
)
{
PCERT_DSS_PARAMETERS pDssParameters;
DWORD cbDssParameters;
if (pDssParameters =
(PCERT_DSS_PARAMETERS) TestNoCopyDecodeObject(
X509_DSS_PARAMETERS,
pbData,
cbData,
&cbDssParameters
)) {
DWORD cbKey = pDssParameters->p.cbData;
printf("DSS Key Length:: %d bytes, %d bits\n", cbKey,
cbKey*8);
printf("DSS P (little endian)::\n");
PrintBytes(" ", pDssParameters->p.pbData,
pDssParameters->p.cbData);
printf("DSS Q (little endian)::\n");
PrintBytes(" ", pDssParameters->q.pbData,
pDssParameters->q.cbData);
printf("DSS G (little endian)::\n");
PrintBytes(" ", pDssParameters->g.pbData,
pDssParameters->g.cbData);
TestFree(pDssParameters);
}
}
static void PrintAuxCertProperties(
PCCERT_CONTEXT pCert,
DWORD dwDisplayFlags
)
{
if (0 == (dwDisplayFlags & DISPLAY_VERBOSE_FLAG))
return;
DWORD dwPropId = 0;
while (dwPropId = CertEnumCertificateContextProperties(pCert, dwPropId)) {
switch (dwPropId) {
case CERT_KEY_PROV_INFO_PROP_ID:
case CERT_SHA1_HASH_PROP_ID:
case CERT_MD5_HASH_PROP_ID:
case CERT_SIGNATURE_HASH_PROP_ID:
case CERT_KEY_CONTEXT_PROP_ID:
case CERT_KEY_IDENTIFIER_PROP_ID:
// Formatted elsewhere
break;
default:
{
BYTE *pbData;
DWORD cbData;
if (CERT_ARCHIVED_PROP_ID == dwPropId)
printf("Archived PropId %d (0x%x) ::\n",
dwPropId, dwPropId);
else
printf("Aux PropId %d (0x%x) ::\n", dwPropId, dwPropId);
CertGetCertificateContextProperty(
pCert,
dwPropId,
NULL, // pvData
&cbData
);
if (cbData) {
if (pbData = (BYTE *) TestAlloc(cbData)) {
// Try without a large enough buffer
DWORD cbSmall = cbData - 1;
if (CertGetCertificateContextProperty(
pCert,
dwPropId,
pbData,
&cbSmall
))
printf("failed => returned success for too small buffer\n");
else {
DWORD dwErr = GetLastError();
if (ERROR_MORE_DATA != dwErr)
printf("failed => returned: %d 0x%x instead of ERROR_MORE_DATA\n", dwErr, dwErr);
}
if (cbSmall != cbData)
printf("failed => wrong size returned for small buffer\n");
if (CertGetCertificateContextProperty(
pCert,
dwPropId,
pbData,
&cbData
)) {
PrintBytes(" ", pbData, cbData);
if (CERT_CTL_USAGE_PROP_ID == dwPropId) {
printf(" EnhancedKeyUsage::\n");
DecodeAndDisplayCtlUsage(pbData, cbData,
dwDisplayFlags);
} else if (CERT_CROSS_CERT_DIST_POINTS_PROP_ID ==
dwPropId) {
printf(" CrossCertDistPoints::\n");
DisplayCrossCertDistPointsExtension(
pbData, cbData, dwDisplayFlags);
#ifdef CERT_PUBKEY_ALG_PARA_PROP_ID
} else if (CERT_PUBKEY_ALG_PARA_PROP_ID ==
dwPropId) {
DecodeAndDisplayDSSParameters(pbData, cbData);
#endif
}
} else
printf(" ERROR getting property bytes\n");
TestFree(pbData);
}
} else
printf(" NO Property Bytes\n");
}
break;
}
}
}
//+-------------------------------------------------------------------------
// Reverses a buffer of bytes in place
//--------------------------------------------------------------------------
void
ReverseBytes(
IN OUT PBYTE pbIn,
IN DWORD cbIn
)
{
// reverse in place
PBYTE pbLo;
PBYTE pbHi;
BYTE bTmp;
for (pbLo = pbIn, pbHi = pbIn + cbIn - 1; pbLo < pbHi; pbHi--, pbLo++) {
bTmp = *pbHi;
*pbHi = *pbLo;
*pbLo = bTmp;
}
}
static void DisplaySignature(
BYTE *pbEncoded,
DWORD cbEncoded,
DWORD dwDisplayFlags
)
{
PCERT_SIGNED_CONTENT_INFO pSignedContent;
if (pSignedContent = (PCERT_SIGNED_CONTENT_INFO) TestNoCopyDecodeObject(
X509_CERT,
pbEncoded,
cbEncoded
)) {
LPSTR pszObjId;
pszObjId = pSignedContent->SignatureAlgorithm.pszObjId;
if (pszObjId == NULL)
pszObjId = "<NULL OBJID>";
printf("Content SignatureAlgorithm:: %s (%S)\n",
pszObjId, GetOIDName(pszObjId, CRYPT_SIGN_ALG_OID_GROUP_ID));
if (pSignedContent->SignatureAlgorithm.Parameters.cbData) {
printf("Content SignatureAlgorithm.Parameters::\n");
PrintBytes(" ",
pSignedContent->SignatureAlgorithm.Parameters.pbData,
pSignedContent->SignatureAlgorithm.Parameters.cbData);
}
if (pSignedContent->Signature.cbData) {
ALG_ID aiHash;
ALG_ID aiPubKey;
printf("Content Signature (little endian)::\n");
PrintBytes(" ", pSignedContent->Signature.pbData,
pSignedContent->Signature.cbData);
GetSignAlgids(pszObjId, &aiHash, &aiPubKey);
if (CALG_SHA == aiHash && CALG_DSS_SIGN == aiPubKey) {
BYTE *pbDssSignature;
DWORD cbDssSignature;
ReverseBytes(pSignedContent->Signature.pbData,
pSignedContent->Signature.cbData);
if (pbDssSignature =
(BYTE *) TestNoCopyDecodeObject(
X509_DSS_SIGNATURE,
pSignedContent->Signature.pbData,
pSignedContent->Signature.cbData,
&cbDssSignature
)) {
if (CERT_DSS_SIGNATURE_LEN == cbDssSignature) {
printf("DSS R (little endian)::\n");
PrintBytes(" ", pbDssSignature, CERT_DSS_R_LEN);
printf("DSS S (little endian)::\n");
PrintBytes(" ", pbDssSignature + CERT_DSS_R_LEN,
CERT_DSS_S_LEN);
} else {
printf("DSS Signature (unexpected length, little endian)::\n");
PrintBytes(" ", pbDssSignature, cbDssSignature);
}
TestFree(pbDssSignature);
}
}
} else
printf("Content Signature:: NONE\n");
printf("Content Length:: %d\n", pSignedContent->ToBeSigned.cbData);
TestFree(pSignedContent);
}
}
void DisplayStore(
IN HCERTSTORE hStore,
IN DWORD dwDisplayFlags
)
{
DWORD i;
DWORD dwFlags;
PCCERT_CONTEXT pCert;
PCCRL_CONTEXT pCrl;
PCCTL_CONTEXT pCtl;
printf("#### Certificates ####\n");
pCert = NULL;
i = 0;
while (pCert = CertEnumCertificatesInStore(hStore, pCert)) {
printf("===== %d =====\n", i);
DisplayCert(pCert, dwDisplayFlags);
i++;
}
printf("#### CRLs ####\n");
pCrl = NULL;
i = 0;
while (pCrl = CertEnumCRLsInStore(hStore, pCrl)) {
printf("===== %d =====\n", i);
DisplayCrl(pCrl, dwDisplayFlags);
i++;
}
printf("#### CTLs ####\n");
pCtl = NULL;
i = 0;
while (pCtl = CertEnumCTLsInStore(hStore, pCtl)) {
printf("===== %d =====\n", i);
DisplayCtl(pCtl, dwDisplayFlags);
i++;
}
}
// Not displayed when DISPLAY_BRIEF_FLAG is set
void DisplayCertKeyProvInfo(
PCCERT_CONTEXT pCert,
DWORD dwDisplayFlags
)
{
PCRYPT_KEY_PROV_INFO pInfo = NULL;
DWORD cbInfo;
if (dwDisplayFlags & DISPLAY_BRIEF_FLAG)
return;
cbInfo = 0;
CertGetCertificateContextProperty(
pCert,
CERT_KEY_PROV_INFO_PROP_ID,
NULL, // pvData
&cbInfo
);
if (cbInfo) {
pInfo = (PCRYPT_KEY_PROV_INFO) TestAlloc(cbInfo);
if (pInfo) {
// Try without a large enough buffer
DWORD cbSmall = cbInfo - 1;
if (CertGetCertificateContextProperty(
pCert,
CERT_KEY_PROV_INFO_PROP_ID,
pInfo,
&cbSmall
))
printf("failed => returned success for too small buffer\n");
else {
DWORD dwErr = GetLastError();
if (ERROR_MORE_DATA != dwErr)
printf("failed => returned: %d 0x%x instead of ERROR_MORE_DATA\n", dwErr, dwErr);
}
if (cbSmall != cbInfo)
printf("failed => wrong size returned for small buffer\n");
if (CertGetCertificateContextProperty(
pCert,
CERT_KEY_PROV_INFO_PROP_ID,
pInfo,
&cbInfo
)) {
printf("Key Provider:: Type: %d", pInfo->dwProvType);
if (pInfo->pwszProvName)
printf(" Name: %S", pInfo->pwszProvName);
if (pInfo->dwFlags) {
printf(" Flags: 0x%x", pInfo->dwFlags);
if (pInfo->dwFlags & CRYPT_MACHINE_KEYSET)
printf(" (MACHINE_KEYSET)");
if (pInfo->dwFlags & CERT_SET_KEY_CONTEXT_PROP_ID)
printf(" (SET_KEY_CONTEXT_PROP)");
printf(" ");
}
if (pInfo->pwszContainerName)
printf(" Container: %S", pInfo->pwszContainerName);
if (pInfo->dwKeySpec)
printf(" KeySpec: %d", pInfo->dwKeySpec);
printf("\n");
if (pInfo->cProvParam) {
DWORD i;
printf("Key Provider Params::\n");
for (i = 0; i < pInfo->cProvParam; i++) {
PCRYPT_KEY_PROV_PARAM pParam =
&pInfo->rgProvParam[i];
printf(" [%d] dwParam: 0x%x dwFlags: 0x%x\n",
i, pParam->dwParam, pParam->dwFlags);
if (pParam->cbData)
PrintBytes(" ",
pParam->pbData, pParam->cbData);
}
}
} else
PrintLastError("CertGetCertificateContextProperty");
TestFree(pInfo);
}
}
}
void DisplayFriendlyName(
IN PCCERT_CONTEXT pCertContext,
IN DWORD dwDisplayFlags
)
{
DWORD cch;
LPWSTR pwsz = NULL;
if (0 == (dwDisplayFlags & DISPLAY_VERBOSE_FLAG))
return;
cch = CertGetNameStringW(
pCertContext,
CERT_NAME_FRIENDLY_DISPLAY_TYPE,
0, // dwFlags
NULL, // pvTypePara
NULL, // pwsz
0); // cch
if (cch <= 1) {
DWORD dwErr = GetLastError();
printf("failed => CertGetNameStringW returned empty string\n");
} else if (pwsz = (LPWSTR) TestAlloc(cch * sizeof(WCHAR))) {
cch = CertGetNameStringW(
pCertContext,
CERT_NAME_FRIENDLY_DISPLAY_TYPE,
0, // dwFlags
NULL, // pvTypePara
pwsz,
cch);
printf("Friendly Name:: <%S>\n", pwsz);
TestFree(pwsz);
}
}
void DisplayUPN(
IN PCCERT_CONTEXT pCertContext,
IN DWORD dwDisplayFlags
)
{
DWORD cch;
LPWSTR pwsz = NULL;
if (0 == (dwDisplayFlags & DISPLAY_VERBOSE_FLAG))
return;
cch = CertGetNameStringW(
pCertContext,
CERT_NAME_UPN_TYPE,
0, // dwFlags
NULL, // pvTypePara
NULL, // pwsz
0); // cch
if (cch <= 1) {
;
} else if (pwsz = (LPWSTR) TestAlloc(cch * sizeof(WCHAR))) {
cch = CertGetNameStringW(
pCertContext,
CERT_NAME_UPN_TYPE,
0, // dwFlags
NULL, // pvTypePara
pwsz,
cch);
printf("UPN Name:: <%S>\n", pwsz);
TestFree(pwsz);
}
}
void DisplayCert(
PCCERT_CONTEXT pCert,
DWORD dwDisplayFlags,
DWORD dwIssuer
)
{
DisplayCert2(
pCert->hCertStore,
pCert,
dwDisplayFlags,
dwIssuer
);
}
typedef BOOL (WINAPI *PFN_CRYPT_UI_DLG_VIEW_CONTEXT)(
IN DWORD dwContextType,
IN const void *pvContext,
IN OPTIONAL HWND hwnd, // Defaults to the desktop window
IN OPTIONAL LPCWSTR pwszTitle, // Defaults to the context type title
IN DWORD dwFlags,
IN void *pvReserved
);
void DisplayContextUI(
IN DWORD dwContextType,
IN const void *pvContext
)
{
HMODULE hDll = NULL;
PFN_CRYPT_UI_DLG_VIEW_CONTEXT pfnCryptUIDlgViewContext;
if (NULL == (hDll = LoadLibraryA("cryptui.dll"))) {
PrintLastError("LoadLibraryA(cryptui.dll)");
goto CommonReturn;
}
if (NULL == (pfnCryptUIDlgViewContext =
(PFN_CRYPT_UI_DLG_VIEW_CONTEXT) GetProcAddress(hDll,
"CryptUIDlgViewContext"))) {
PrintLastError("GetProcAddress(CryptUIDlgViewContext)");
goto CommonReturn;
}
if (!pfnCryptUIDlgViewContext(
dwContextType,
pvContext,
NULL, // hHwnd
NULL, // pwszTitle
0, // dwFlags
NULL // pvReserved
))
PrintLastError("CryptUIDlgViewContext");
CommonReturn:
if (hDll)
FreeLibrary(hDll);
}
void DisplayCert2(
HCERTSTORE hStore,
PCCERT_CONTEXT pCert,
DWORD dwDisplayFlags,
DWORD dwIssuer
)
{
if (dwDisplayFlags & DISPLAY_UI_FLAG) {
DisplayContextUI(CERT_STORE_CERTIFICATE_CONTEXT, pCert);
dwDisplayFlags = DISPLAY_BRIEF_FLAG;
}
DisplayFriendlyName(pCert, dwDisplayFlags);
DisplayUPN(pCert, dwDisplayFlags);
printf("Subject::\n");
DecodeName(pCert->pCertInfo->Subject.pbData,
pCert->pCertInfo->Subject.cbData, dwDisplayFlags);
if (!(dwDisplayFlags & DISPLAY_BRIEF_FLAG)) {
printf("Issuer::\n");
DecodeName(pCert->pCertInfo->Issuer.pbData,
pCert->pCertInfo->Issuer.cbData, dwDisplayFlags);
{
printf("SerialNumber::");
DisplaySerialNumber(&pCert->pCertInfo->SerialNumber);
printf("\n");
}
}
{
BYTE rgbHash[MAX_HASH_LEN];
DWORD cbHash = MAX_HASH_LEN;
#define MAX_KEY_ID_LEN 128
BYTE rgbKeyId[MAX_KEY_ID_LEN];
DWORD cbKeyId;
CertGetCertificateContextProperty(
pCert,
CERT_SHA1_HASH_PROP_ID,
rgbHash,
&cbHash
);
DisplayThumbprint("SHA1", rgbHash, cbHash);
cbHash = MAX_HASH_LEN;
CertGetCertificateContextProperty(
pCert,
CERT_MD5_HASH_PROP_ID,
rgbHash,
&cbHash
);
DisplayThumbprint("MD5", rgbHash, cbHash);
cbHash = MAX_HASH_LEN;
CertGetCertificateContextProperty(
pCert,
CERT_SIGNATURE_HASH_PROP_ID,
rgbHash,
&cbHash
);
DisplayThumbprint("Signature", rgbHash, cbHash);
cbKeyId = MAX_KEY_ID_LEN;
if (CertGetCertificateContextProperty(
pCert,
CERT_KEY_IDENTIFIER_PROP_ID,
rgbKeyId,
&cbKeyId
))
DisplayThumbprint("KeyIdentifier", rgbKeyId, cbKeyId);
else
PrintLastError(
"CertGetCertificateContextProperty(KEY_IDENTIFIER)");
cbKeyId = MAX_KEY_ID_LEN;
if (CryptHashPublicKeyInfo(
NULL, // hCryptProv
CALG_SHA1,
0, // dwFlags
X509_ASN_ENCODING,
&pCert->pCertInfo->SubjectPublicKeyInfo,
rgbKeyId,
&cbKeyId
))
DisplayThumbprint("SHA1 KeyIdentifier", rgbKeyId, cbKeyId);
else
PrintLastError(
"CertGetCertificateContextProperty(SHA1 KEY_IDENTIFIER)");
if (dwDisplayFlags & DISPLAY_KEY_THUMB_FLAG) {
HCRYPTPROV hProv = 0;
CryptAcquireContext(
&hProv,
NULL,
NULL, // pszProvider
PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT
);
if (hProv) {
cbHash = MAX_HASH_LEN;
CryptHashPublicKeyInfo(
hProv,
CALG_MD5,
0, // dwFlags
dwCertEncodingType,
&pCert->pCertInfo->SubjectPublicKeyInfo,
rgbHash,
&cbHash
);
DisplayThumbprint("Key (MD5)", rgbHash, cbHash);
CryptReleaseContext(hProv, 0);
}
}
}
DisplayCertKeyProvInfo(pCert);
if (dwDisplayFlags & DISPLAY_VERBOSE_FLAG) {
DWORD dwAccessStateFlags;
DWORD cbData = sizeof(dwAccessStateFlags);
CertGetCertificateContextProperty(
pCert,
CERT_ACCESS_STATE_PROP_ID,
&dwAccessStateFlags,
&cbData
);
if (0 == cbData)
printf("No AccessState PropId\n");
else {
printf("AccessState PropId dwFlags:: 0x%x", dwAccessStateFlags);
if (dwAccessStateFlags & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG)
printf(" WRITE_PERSIST");
if (dwAccessStateFlags & CERT_ACCESS_STATE_SYSTEM_STORE_FLAG)
printf(" SYSTEM_STORE");
if (dwAccessStateFlags & CERT_ACCESS_STATE_LM_SYSTEM_STORE_FLAG)
printf(" LM_SYSTEM_STORE");
printf("\n");
}
}
PrintAuxCertProperties(pCert, dwDisplayFlags);
if (dwDisplayFlags & DISPLAY_VERBOSE_FLAG) {
LPSTR pszObjId;
ALG_ID aiPubKey;
DWORD dwBitLen;
printf("Version:: %d\n", pCert->pCertInfo->dwVersion);
pszObjId = pCert->pCertInfo->SignatureAlgorithm.pszObjId;
if (pszObjId == NULL)
pszObjId = "<NULL OBJID>";
printf("SignatureAlgorithm:: %s (%S)\n",
pszObjId, GetOIDName(pszObjId, CRYPT_SIGN_ALG_OID_GROUP_ID));
if (pCert->pCertInfo->SignatureAlgorithm.Parameters.cbData) {
printf("SignatureAlgorithm.Parameters::\n");
PrintBytes(" ",
pCert->pCertInfo->SignatureAlgorithm.Parameters.pbData,
pCert->pCertInfo->SignatureAlgorithm.Parameters.cbData);
}
printf("NotBefore:: %s\n", FileTimeText(&pCert->pCertInfo->NotBefore));
printf("NotAfter:: %s\n", FileTimeText(&pCert->pCertInfo->NotAfter));
pszObjId = pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId;
if (pszObjId == NULL)
pszObjId = "<NULL OBJID>";
printf("SubjectPublicKeyInfo.Algorithm:: %s (%S)\n",
pszObjId, GetOIDName(pszObjId, CRYPT_PUBKEY_ALG_OID_GROUP_ID));
aiPubKey = GetAlgid(pszObjId, CRYPT_PUBKEY_ALG_OID_GROUP_ID);
if (pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.cbData) {
printf("SubjectPublicKeyInfo.Algorithm.Parameters::\n");
PrintBytes(" ",
pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.pbData,
pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.cbData);
if (NULL_ASN_TAG ==
*pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.pbData)
{
// NULL parameters
} else if (CALG_DSS_SIGN == aiPubKey) {
DecodeAndDisplayDSSParameters(
pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.pbData,
pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.cbData);
} else if (CALG_DH_SF == aiPubKey || CALG_DH_EPHEM == aiPubKey) {
PCERT_X942_DH_PARAMETERS pDhParameters;
DWORD cbDhParameters;
if (pDhParameters =
(PCERT_X942_DH_PARAMETERS) TestNoCopyDecodeObject(
X942_DH_PARAMETERS,
pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.pbData,
pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.cbData,
&cbDhParameters
)) {
DWORD cbKey = pDhParameters->p.cbData;
printf("DH Key Length:: %d bytes, %d bits\n", cbKey,
cbKey*8);
printf("DH P (little endian)::\n");
PrintBytes(" ", pDhParameters->p.pbData,
pDhParameters->p.cbData);
printf("DH G (little endian)::\n");
PrintBytes(" ", pDhParameters->g.pbData,
pDhParameters->g.cbData);
if (pDhParameters->q.cbData) {
printf("DH Q (little endian)::\n");
PrintBytes(" ", pDhParameters->q.pbData,
pDhParameters->q.cbData);
}
if (pDhParameters->j.cbData) {
printf("DH J (little endian)::\n");
PrintBytes(" ", pDhParameters->j.pbData,
pDhParameters->j.cbData);
}
if (pDhParameters->pValidationParams) {
printf("DH seed ::\n");
PrintBytes(" ",
pDhParameters->pValidationParams->seed.pbData,
pDhParameters->pValidationParams->seed.cbData);
printf("DH pgenCounter:: %d (0x%x)\n",
pDhParameters->pValidationParams->pgenCounter,
pDhParameters->pValidationParams->pgenCounter);
}
TestFree(pDhParameters);
}
}
}
printf("SubjectPublicKeyInfo.PublicKey");
if (0 != (dwBitLen = CertGetPublicKeyLength(
dwCertEncodingType,
&pCert->pCertInfo->SubjectPublicKeyInfo)))
printf(" (BitLength: %d)", dwBitLen);
if (pCert->pCertInfo->SubjectPublicKeyInfo.PublicKey.cUnusedBits)
printf(" (UnusedBits: %d)",
pCert->pCertInfo->SubjectPublicKeyInfo.PublicKey.cUnusedBits);
printf("::\n");
if (pCert->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData) {
PrintBytes(" ",
pCert->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
pCert->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData);
if (CALG_RSA_SIGN == aiPubKey || CALG_RSA_KEYX == aiPubKey) {
PUBLICKEYSTRUC *pPubKeyStruc;
DWORD cbPubKeyStruc;
printf("RSA_CSP_PUBLICKEYBLOB::\n");
if (pPubKeyStruc = (PUBLICKEYSTRUC *) TestNoCopyDecodeObject(
RSA_CSP_PUBLICKEYBLOB,
pCert->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
pCert->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData,
&cbPubKeyStruc
)) {
PrintBytes(" ", (BYTE *) pPubKeyStruc, cbPubKeyStruc);
TestFree(pPubKeyStruc);
}
} else if (CALG_DSS_SIGN == aiPubKey) {
PCRYPT_UINT_BLOB pDssPubKey;
DWORD cbDssPubKey;
printf("DSS Y (little endian)::\n");
if (pDssPubKey = (PCRYPT_UINT_BLOB) TestNoCopyDecodeObject(
X509_DSS_PUBLICKEY,
pCert->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
pCert->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData,
&cbDssPubKey
)) {
PrintBytes(" ", pDssPubKey->pbData, pDssPubKey->cbData);
TestFree(pDssPubKey);
}
} else if (CALG_DH_SF == aiPubKey || CALG_DH_EPHEM == aiPubKey) {
PCRYPT_UINT_BLOB pDhPubKey;
DWORD cbDhPubKey;
printf("DH Y (little endian)::\n");
if (pDhPubKey = (PCRYPT_UINT_BLOB) TestNoCopyDecodeObject(
X509_DH_PUBLICKEY,
pCert->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
pCert->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData,
&cbDhPubKey
)) {
PrintBytes(" ", pDhPubKey->pbData, pDhPubKey->cbData);
TestFree(pDhPubKey);
}
}
} else
printf(" No public key\n");
DisplaySignature(
pCert->pbCertEncoded,
pCert->cbCertEncoded,
dwDisplayFlags);
if (pCert->pCertInfo->IssuerUniqueId.cbData) {
printf("IssuerUniqueId");
if (pCert->pCertInfo->IssuerUniqueId.cUnusedBits)
printf(" (UnusedBits: %d)",
pCert->pCertInfo->IssuerUniqueId.cUnusedBits);
printf("::\n");
PrintBytes(" ", pCert->pCertInfo->IssuerUniqueId.pbData,
pCert->pCertInfo->IssuerUniqueId.cbData);
}
if (pCert->pCertInfo->SubjectUniqueId.cbData) {
printf("SubjectUniqueId");
if (pCert->pCertInfo->SubjectUniqueId.cUnusedBits)
printf(" (UnusedBits: %d)",
pCert->pCertInfo->SubjectUniqueId.cUnusedBits);
printf("::\n");
PrintBytes(" ", pCert->pCertInfo->SubjectUniqueId.pbData,
pCert->pCertInfo->SubjectUniqueId.cbData);
}
if (pCert->pCertInfo->cExtension != 0) {
PrintExtensions(pCert->pCertInfo->cExtension,
pCert->pCertInfo->rgExtension, dwDisplayFlags);
}
}
if (dwDisplayFlags & DISPLAY_CHECK_FLAG) {
// Display any CRLs associated with the certificate
PCCRL_CONTEXT pCrl = NULL;
PCCRL_CONTEXT pFindCrl = NULL;
DWORD dwFlags;
int i;
// i = 0 => BASE
// i = 1 => DELTA
for (i = 0; i <= 1; i++) {
while (TRUE) {
if (dwDisplayFlags &
(DISPLAY_CHECK_SIGN_FLAG | DISPLAY_CHECK_TIME_FLAG)) {
dwFlags = 0;
if (dwDisplayFlags & DISPLAY_CHECK_SIGN_FLAG)
dwFlags |= CERT_STORE_SIGNATURE_FLAG;
if (dwDisplayFlags & DISPLAY_CHECK_TIME_FLAG)
dwFlags |= CERT_STORE_TIME_VALIDITY_FLAG;
} else
dwFlags = CERT_STORE_SIGNATURE_FLAG |
CERT_STORE_TIME_VALIDITY_FLAG;
if (i == 0)
dwFlags |= CERT_STORE_BASE_CRL_FLAG;
else
dwFlags |= CERT_STORE_DELTA_CRL_FLAG;
pCrl = CertGetCRLFromStore(
hStore,
pCert,
pCrl,
&dwFlags
);
// Check that find comes up with the same CRL
pFindCrl = CertFindCRLInStore(
hStore,
pCert->dwCertEncodingType,
(i == 0) ? CRL_FIND_ISSUED_BY_BASE_FLAG :
CRL_FIND_ISSUED_BY_DELTA_FLAG,
CRL_FIND_ISSUED_BY,
(const void *) pCert,
pFindCrl
);
if (pCrl == NULL) {
if (pFindCrl != NULL) {
printf("failed => CertFindCRLInStore didn't return expected NULL\n");
CertFreeCRLContext(pFindCrl);
pFindCrl = NULL;
}
break;
} else if (pFindCrl == NULL) {
printf("failed => CertFindCRLInStore returned unexpected NULL\n");
CertFreeCRLContext(pCrl);
pCrl = NULL;
break;
}
if (!(pFindCrl->pbCrlEncoded == pCrl->pbCrlEncoded
||
(pFindCrl->cbCrlEncoded == pCrl->cbCrlEncoded &&
0 == memcmp(pFindCrl->pbCrlEncoded, pCrl->pbCrlEncoded,
pFindCrl->cbCrlEncoded))))
printf("failed => CertFindCRLInStore didn't match CertGetCRLFromStore\n");
if (i == 0)
printf("----- BASE CRL -----\n");
else
printf("----- DELTA CRL -----\n");
DisplayCrl(pCrl, dwDisplayFlags | DISPLAY_NO_ISSUER_FLAG);
DisplayVerifyFlags("CRL", dwFlags);
}
}
}
if (dwDisplayFlags & DISPLAY_CHECK_FLAG) {
BOOL fIssuer = FALSE;
PCCERT_CONTEXT pIssuer = NULL;
DWORD dwFlags;
while (TRUE) {
if (dwDisplayFlags &
(DISPLAY_CHECK_SIGN_FLAG | DISPLAY_CHECK_TIME_FLAG)) {
dwFlags = 0;
if (dwDisplayFlags & DISPLAY_CHECK_SIGN_FLAG)
dwFlags |= CERT_STORE_SIGNATURE_FLAG;
if (dwDisplayFlags & DISPLAY_CHECK_TIME_FLAG)
dwFlags |= CERT_STORE_TIME_VALIDITY_FLAG;
} else
dwFlags = CERT_STORE_SIGNATURE_FLAG |
CERT_STORE_TIME_VALIDITY_FLAG |
CERT_STORE_REVOCATION_FLAG;
pIssuer = CertGetIssuerCertificateFromStore(
hStore,
pCert,
pIssuer,
&dwFlags
);
if (pIssuer) {
printf("----- Issuer [%d] -----\n", dwIssuer);
DisplayVerifyFlags("Above Subject", dwFlags);
DisplayCert2(hStore, pIssuer, dwDisplayFlags, dwIssuer + 1);
fIssuer = TRUE;
} else {
DWORD dwErr = GetLastError();
if (dwErr == CRYPT_E_SELF_SIGNED) {
printf("----- Self Signed Issuer -----\n");
DisplayVerifyFlags("Issuer", dwFlags);
} else if (dwErr != CRYPT_E_NOT_FOUND)
PrintLastError("CertGetIssuerCertificateFromStore");
else if (!fIssuer) {
printf("----- No Issuer -----\n");
DisplayVerifyFlags("Above Subject", dwFlags);
}
break;
}
}
}
}
void PrintCrlEntries(
DWORD cEntry,
PCRL_ENTRY pEntry,
DWORD dwDisplayFlags
)
{
DWORD i;
for (i = 0; i < cEntry; i++, pEntry++) {
{
printf(" [%d] SerialNumber::", i);
DisplaySerialNumber(&pEntry->SerialNumber);
printf("\n");
}
if (dwDisplayFlags & DISPLAY_VERBOSE_FLAG) {
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,
dwDisplayFlags);
}
}
}
}
static void PrintAuxCrlProperties(
PCCRL_CONTEXT pCrl,
DWORD dwDisplayFlags
)
{
if (0 == (dwDisplayFlags & DISPLAY_VERBOSE_FLAG))
return;
DWORD dwPropId = 0;
while (dwPropId = CertEnumCRLContextProperties(pCrl, dwPropId)) {
switch (dwPropId) {
case CERT_SHA1_HASH_PROP_ID:
case CERT_MD5_HASH_PROP_ID:
// Formatted elsewhere
break;
default:
{
BYTE *pbData;
DWORD cbData;
printf("Aux PropId %d (0x%x) ::\n", dwPropId, dwPropId);
CertGetCRLContextProperty(
pCrl,
dwPropId,
NULL, // pvData
&cbData
);
if (cbData) {
if (pbData = (BYTE *) TestAlloc(cbData)) {
if (CertGetCRLContextProperty(
pCrl,
dwPropId,
pbData,
&cbData
))
PrintBytes(" ", pbData, cbData);
else
printf(" ERROR getting property bytes\n");
TestFree(pbData);
}
} else
printf(" NO Property Bytes\n");
}
break;
}
}
}
void DisplayCrl(PCCRL_CONTEXT pCrl, DWORD dwDisplayFlags)
{
if (dwDisplayFlags & DISPLAY_UI_FLAG) {
DisplayContextUI(CERT_STORE_CRL_CONTEXT, pCrl);
dwDisplayFlags = DISPLAY_BRIEF_FLAG;
}
if (!(dwDisplayFlags & DISPLAY_NO_ISSUER_FLAG)) {
printf("Issuer::\n");
DecodeName(pCrl->pCrlInfo->Issuer.pbData,
pCrl->pCrlInfo->Issuer.cbData, dwDisplayFlags);
}
printf("ThisUpdate:: %s\n", FileTimeText(&pCrl->pCrlInfo->ThisUpdate));
printf("NextUpdate:: %s\n", FileTimeText(&pCrl->pCrlInfo->NextUpdate));
{
BYTE rgbHash[MAX_HASH_LEN];
DWORD cbHash = MAX_HASH_LEN;
CertGetCRLContextProperty(
pCrl,
CERT_SHA1_HASH_PROP_ID,
rgbHash,
&cbHash
);
DisplayThumbprint("SHA1", rgbHash, cbHash);
cbHash = MAX_HASH_LEN;
CertGetCRLContextProperty(
pCrl,
CERT_MD5_HASH_PROP_ID,
rgbHash,
&cbHash
);
DisplayThumbprint("MD5", rgbHash, cbHash);
cbHash = MAX_HASH_LEN;
CertGetCRLContextProperty(
pCrl,
CERT_SIGNATURE_HASH_PROP_ID,
rgbHash,
&cbHash
);
DisplayThumbprint("Signature", rgbHash, cbHash);
}
PrintAuxCrlProperties(pCrl, dwDisplayFlags);
if (dwDisplayFlags & DISPLAY_VERBOSE_FLAG) {
LPSTR pszObjId;
printf("Version:: %d\n", pCrl->pCrlInfo->dwVersion);
pszObjId = pCrl->pCrlInfo->SignatureAlgorithm.pszObjId;
if (pszObjId == NULL)
pszObjId = "<NULL OBJID>";
printf("SignatureAlgorithm:: %s (%S)\n",
pszObjId, GetOIDName(pszObjId, CRYPT_SIGN_ALG_OID_GROUP_ID));
if (pCrl->pCrlInfo->SignatureAlgorithm.Parameters.cbData) {
printf("SignatureAlgorithm.Parameters::\n");
PrintBytes(" ",
pCrl->pCrlInfo->SignatureAlgorithm.Parameters.pbData,
pCrl->pCrlInfo->SignatureAlgorithm.Parameters.cbData);
}
if (pCrl->pCrlInfo->cExtension != 0) {
PrintExtensions(pCrl->pCrlInfo->cExtension,
pCrl->pCrlInfo->rgExtension,
dwDisplayFlags);
}
}
if (pCrl->pCrlInfo->cCRLEntry == 0)
printf("Entries:: NONE\n");
else {
printf("Entries::\n");
PrintCrlEntries(pCrl->pCrlInfo->cCRLEntry,
pCrl->pCrlInfo->rgCRLEntry, dwDisplayFlags);
}
}
static void PrintAttributes(DWORD cAttr, PCRYPT_ATTRIBUTE pAttr,
DWORD dwDisplayFlags)
{
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_NEXT_UPDATE_LOCATION) == 0) {
printf(" NextUpdateLocation::\n");
DecodeAndDisplayAltName(pValue->pbData, pValue->cbData,
dwDisplayFlags);
}
} else
printf(" NO Value Bytes\n");
}
} else
printf(" [%d] %s :: No Values\n", i, pszObjId);
}
}
static void PrintCtlEntries(
PCCTL_CONTEXT pCtl,
DWORD dwDisplayFlags,
HCERTSTORE hStore)
{
PCTL_INFO pInfo = pCtl->pCtlInfo;
DWORD cEntry = pInfo->cCTLEntry;
PCTL_ENTRY pEntry = pInfo->rgCTLEntry;
DWORD i;
DWORD Algid;
DWORD dwFindType;
Algid = CertOIDToAlgId(pInfo->SubjectAlgorithm.pszObjId);
switch (Algid) {
case CALG_SHA1:
dwFindType = CERT_FIND_SHA1_HASH;
break;
case CALG_MD5:
dwFindType = CERT_FIND_MD5_HASH;
break;
default:
dwFindType = 0;
}
for (i = 0; i < cEntry; i++, pEntry++) {
printf(" [%d] SubjectIdentifier::\n", i);
PrintBytes(" ",
pEntry->SubjectIdentifier.pbData,
pEntry->SubjectIdentifier.cbData);
if (hStore && dwFindType) {
PCCERT_CONTEXT pCert;
pCert = CertFindCertificateInStore(
hStore,
dwCertEncodingType,
0, // dwFindFlags
dwFindType,
(void *) &pEntry->SubjectIdentifier,
NULL // pPrevCert
);
if (pCert) {
DWORD cwsz;
LPWSTR pwsz;
cwsz = CertNameToStrW(
dwCertEncodingType,
&pCert->pCertInfo->Subject,
CERT_SIMPLE_NAME_STR,
NULL, // pwsz
0); // cwsz
if (pwsz = (LPWSTR) TestAlloc(cwsz * sizeof(WCHAR))) {
CertNameToStrW(
dwCertEncodingType,
&pCert->pCertInfo->Subject,
CERT_SIMPLE_NAME_STR,
pwsz,
cwsz);
printf(" Subject: %S\n", pwsz);
TestFree(pwsz);
}
CertFreeCertificateContext(pCert);
}
}
if (dwDisplayFlags & DISPLAY_VERBOSE_FLAG) {
if (pEntry->cAttribute) {
printf(" [%d] Attributes::\n", i);
PrintAttributes(pEntry->cAttribute, pEntry->rgAttribute,
dwDisplayFlags);
}
}
}
}
static void PrintAuxCtlProperties(
PCCTL_CONTEXT pCtl,
DWORD dwDisplayFlags
)
{
if (0 == (dwDisplayFlags & DISPLAY_VERBOSE_FLAG))
return;
DWORD dwPropId = 0;
while (dwPropId = CertEnumCTLContextProperties(pCtl, dwPropId)) {
switch (dwPropId) {
case CERT_SHA1_HASH_PROP_ID:
#if 0
case CERT_MD5_HASH_PROP_ID:
#endif
// Formatted elsewhere
break;
default:
{
BYTE *pbData;
DWORD cbData;
printf("Aux PropId %d (0x%x) ::\n", dwPropId, dwPropId);
CertGetCTLContextProperty(
pCtl,
dwPropId,
NULL, // pvData
&cbData
);
if (cbData) {
if (pbData = (BYTE *) TestAlloc(cbData)) {
if (CertGetCTLContextProperty(
pCtl,
dwPropId,
pbData,
&cbData
)) {
PrintBytes(" ", pbData, cbData);
if (CERT_NEXT_UPDATE_LOCATION_PROP_ID ==
dwPropId) {
printf(" NextUpdateLocation::\n");
DecodeAndDisplayAltName(pbData, cbData,
dwDisplayFlags);
}
} else
printf(" ERROR getting property bytes\n");
TestFree(pbData);
}
} else
printf(" NO Property Bytes\n");
}
break;
}
}
}
//+-------------------------------------------------------------------------
// Returns TRUE if the CTL is still time valid.
//
// A CTL without a NextUpdate is considered time valid.
//--------------------------------------------------------------------------
BOOL IsTimeValidCtl(
IN PCCTL_CONTEXT pCtl
)
{
PCTL_INFO pCtlInfo = pCtl->pCtlInfo;
SYSTEMTIME SystemTime;
FILETIME CurrentTime;
// Get current time to be used to determine if CTLs are time valid
GetSystemTime(&SystemTime);
SystemTimeToFileTime(&SystemTime, &CurrentTime);
// Note, NextUpdate is optional. When not present, its set to 0
if ((0 == pCtlInfo->NextUpdate.dwLowDateTime &&
0 == pCtlInfo->NextUpdate.dwHighDateTime) ||
CompareFileTime(&pCtlInfo->NextUpdate, &CurrentTime) >= 0)
return TRUE;
else
return FALSE;
}
//+-------------------------------------------------------------------------
// Allocates and returns the specified cryptographic message parameter.
//--------------------------------------------------------------------------
static void *AllocAndGetMsgParam(
IN HCRYPTMSG hMsg,
IN DWORD dwParamType,
IN DWORD dwIndex,
OUT DWORD *pcbData
)
{
void *pvData;
DWORD cbData;
if (!CryptMsgGetParam(
hMsg,
dwParamType,
dwIndex,
NULL, // pvData
&cbData) || 0 == cbData)
goto ErrorReturn;
if (NULL == (pvData = TestAlloc(cbData)))
goto ErrorReturn;
if (!CryptMsgGetParam(
hMsg,
dwParamType,
dwIndex,
pvData,
&cbData)) {
TestFree(pvData);
goto ErrorReturn;
}
CommonReturn:
*pcbData = cbData;
return pvData;
ErrorReturn:
pvData = NULL;
cbData = 0;
goto CommonReturn;
}
void DisplaySignerInfo(
HCRYPTMSG hMsg,
DWORD dwSignerIndex,
DWORD dwDisplayFlags
)
{
DWORD cbData;
PCRYPT_ATTRIBUTES pAttrs;
if (pAttrs = (PCRYPT_ATTRIBUTES) AllocAndGetMsgParam(
hMsg,
CMSG_SIGNER_AUTH_ATTR_PARAM,
dwSignerIndex,
&cbData)) {
printf("----- Signer [%d] AuthenticatedAttributes -----\n",
dwSignerIndex);
PrintAttributes(pAttrs->cAttr, pAttrs->rgAttr, dwDisplayFlags);
TestFree(pAttrs);
}
if (pAttrs = (PCRYPT_ATTRIBUTES) AllocAndGetMsgParam(
hMsg,
CMSG_SIGNER_UNAUTH_ATTR_PARAM,
dwSignerIndex,
&cbData)) {
printf("----- Signer [%d] UnauthenticatedAttributes -----\n",
dwSignerIndex);
PrintAttributes(pAttrs->cAttr, pAttrs->rgAttr, dwDisplayFlags);
TestFree(pAttrs);
}
}
static BOOL CompareSortedAttributes(
IN DWORD dwSubject,
IN PCTL_ENTRY pEntry,
IN PCRYPT_DER_BLOB pEncodedAttributes
)
{
BOOL fResult;
PCRYPT_ATTRIBUTES pAttrs = NULL;
DWORD i;
if (0 == pEntry->cAttribute) {
if (0 != pEncodedAttributes->cbData) {
printf("failed => Didn't expect sorted attributes for subject %d\n",
dwSubject);
return FALSE;
} else
return TRUE;
}
if (0 == pEncodedAttributes->cbData) {
printf("failed => Expected sorted attributes for subject %d\n",
dwSubject);
return FALSE;
}
if (NULL == (pAttrs = (PCRYPT_ATTRIBUTES) TestNoCopyDecodeObject(
PKCS_ATTRIBUTES,
pEncodedAttributes->pbData,
pEncodedAttributes->cbData
)))
goto ErrorReturn;
if (pAttrs->cAttr != pEntry->cAttribute) {
printf("failed => Wrong number of sorted attributes for subject %d\n",
dwSubject);
goto ErrorReturn;
}
for (i = 0; i < pAttrs->cAttr; i++) {
PCRYPT_ATTRIBUTE pAttr = &pEntry->rgAttribute[i];
PCRYPT_ATTRIBUTE pSortedAttr = &pAttrs->rgAttr[i];
DWORD j;
if (0 != strcmp(pAttr->pszObjId, pSortedAttr->pszObjId)) {
printf("failed => wrong sorted attribute[%d] OID for subject %d\n",
i, dwSubject);
goto ErrorReturn;
}
if (pAttr->cValue != pSortedAttr->cValue) {
printf("failed => Wrong number of values for attribute[%d] for subject %d\n",
i, dwSubject);
goto ErrorReturn;
}
for (j = 0; j < pAttr->cValue; j++) {
PCRYPT_ATTR_BLOB pValue = &pAttr->rgValue[j];
PCRYPT_ATTR_BLOB pSortedValue = &pSortedAttr->rgValue[j];
if (pValue->cbData != pSortedValue->cbData ||
(0 != pValue->cbData &&
0 != memcmp(pValue->pbData, pSortedValue->pbData,
pValue->cbData))) {
printf("failed => bad value[%d, %d] for subject %d\n",
i, j, dwSubject);
goto ErrorReturn;
}
}
}
fResult = TRUE;
CommonReturn:
TestFree(pAttrs);
return fResult;
ErrorReturn:
fResult = FALSE;
goto CommonReturn;
}
void DisplayCtl(PCCTL_CONTEXT pCtl, DWORD dwDisplayFlags, HCERTSTORE hStore)
{
PCTL_INFO pInfo = pCtl->pCtlInfo;
PCCTL_CONTEXT pSortedCtl;
if (dwDisplayFlags & DISPLAY_UI_FLAG) {
DisplayContextUI(CERT_STORE_CTL_CONTEXT, pCtl);
dwDisplayFlags = DISPLAY_BRIEF_FLAG;
}
// Test the creation of a sorted CTL. Its decoded output should match
// the normal decoded CTL.
if (NULL == (pSortedCtl = (PCCTL_CONTEXT) CertCreateContext(
CERT_STORE_CTL_CONTEXT,
pCtl->dwMsgAndCertEncodingType,
pCtl->pbCtlEncoded,
pCtl->cbCtlEncoded,
CERT_CREATE_CONTEXT_NOCOPY_FLAG |
CERT_CREATE_CONTEXT_SORTED_FLAG,
NULL // pCreatePara
)))
PrintLastError("CertCreateContext(CTL => NOCOPY, SORTED)");
else {
PCTL_INFO pSortedInfo = pSortedCtl->pCtlInfo;
DWORD cEntry = pInfo->cCTLEntry;
PCTL_ENTRY pEntry = pInfo->rgCTLEntry;
DWORD iEntry;
void *pvNextSubject;
CRYPT_DER_BLOB SubjectIdentifier;
CRYPT_DER_BLOB EncodedAttributes;
// Check that the sorted info matches
if (pSortedInfo->dwVersion != pInfo->dwVersion ||
pSortedInfo->SubjectUsage.cUsageIdentifier !=
pInfo->SubjectUsage.cUsageIdentifier ||
0 != CompareFileTime(&pSortedInfo->ThisUpdate,
&pInfo->ThisUpdate) ||
0 != CompareFileTime(&pSortedInfo->NextUpdate,
&pInfo->NextUpdate) ||
0 != strcmp(pSortedInfo->SubjectAlgorithm.pszObjId,
pInfo->SubjectAlgorithm.pszObjId) ||
pSortedInfo->SubjectAlgorithm.Parameters.cbData !=
pInfo->SubjectAlgorithm.Parameters.cbData)
printf("failed => SortedCtl info doesn't match Ctl info\n");
else {
// Check that the sorted extensions match
DWORD cExt = pInfo->cExtension;
PCERT_EXTENSION pExt = pInfo->rgExtension;
DWORD cSortedExt = pSortedInfo->cExtension;
PCERT_EXTENSION pSortedExt = pSortedInfo->rgExtension;
if (cExt > 0 && 0 == strcmp(pExt->pszObjId, szOID_SORTED_CTL)) {
cExt--,
pExt++;
}
if (cSortedExt != cExt)
printf("failed => SortedCtl extension count doesn't match Ctl\n");
else {
for ( ; cExt; cExt--, pSortedExt++, pExt++) {
if (0 != strcmp(pSortedExt->pszObjId, pExt->pszObjId) ||
pSortedExt->fCritical != pExt->fCritical ||
pSortedExt->Value.cbData != pExt->Value.cbData) {
printf("failed => SortedCtl extension doesn't match Ctl\n");
break;
}
if (pSortedExt->Value.cbData && 0 != memcmp(
pSortedExt->Value.pbData, pExt->Value.pbData,
pSortedExt->Value.cbData)) {
printf("failed => SortedCtl extension doesn't match Ctl\n");
break;
}
}
}
}
pvNextSubject = NULL;
iEntry = 0;
while (CertEnumSubjectInSortedCTL(
pSortedCtl,
&pvNextSubject,
&SubjectIdentifier,
&EncodedAttributes
)) {
if (iEntry >= cEntry) {
printf( "failed => CertEnumSubjectInSortedCTL(too many subjects)\n");
break;
}
if (SubjectIdentifier.cbData !=
pEntry[iEntry].SubjectIdentifier.cbData ||
0 != memcmp(SubjectIdentifier.pbData,
pEntry[iEntry].SubjectIdentifier.pbData,
SubjectIdentifier.cbData)) {
printf("failed => CertEnumSubjectsInSortedCTL(invalid subject %d)\n",
iEntry);
iEntry = cEntry;
break;
}
if (!CompareSortedAttributes(
iEntry,
&pEntry[iEntry],
&EncodedAttributes
)) {
iEntry = cEntry;
break;
}
iEntry++;
}
if (iEntry != cEntry)
printf( "failed => CertEnumSubjectInSortedCTL(missing subjects)\n");
if (0 == cEntry) {
BYTE rgbIdentifier[] = {0x1, 0x2};
SubjectIdentifier.pbData = rgbIdentifier;
SubjectIdentifier.cbData = sizeof(rgbIdentifier);
if (CertFindSubjectInSortedCTL(
&SubjectIdentifier,
pSortedCtl,
0, // dwFlags
NULL, // pvReserved,
&EncodedAttributes
))
printf("failed => CertFindSubjectInSortedCTL returned success for no entries\n");
else if (GetLastError() != CRYPT_E_NOT_FOUND)
printf("failed => CertFindSubjectInSortedCTL didn't return CRYPT_E_NOT_FOUND for no entries\n");
} else {
DWORD rgiEntry[] = {0, cEntry/3, cEntry/2, cEntry -1};
DWORD i;
for (i = 0; i < sizeof(rgiEntry) / sizeof(rgiEntry[0]); i++) {
iEntry = rgiEntry[i];
if (!CertFindSubjectInSortedCTL(
&pEntry[iEntry].SubjectIdentifier,
pSortedCtl,
0, // dwFlags
NULL, // pvReserved,
&EncodedAttributes
)) {
PrintLastError("CertFindSubjectInSortedCTL");
break;
}
}
}
CertFreeCTLContext(pSortedCtl);
}
if (dwDisplayFlags & DISPLAY_VERBOSE_FLAG)
printf("Version:: %d\n", pInfo->dwVersion);
{
DWORD cId;
LPSTR *ppszId;
DWORD i;
printf("SubjectUsage::\n");
cId = pInfo->SubjectUsage.cUsageIdentifier;
ppszId = pInfo->SubjectUsage.rgpszUsageIdentifier;
if (cId == 0)
printf(" No Usage Identifiers\n");
for (i = 0; i < cId; i++, ppszId++)
printf(" [%d] %s\n", i, *ppszId);
}
if (pInfo->ListIdentifier.cbData) {
printf("ListIdentifier::\n");
PrintBytes(" ",
pInfo->ListIdentifier.pbData,
pInfo->ListIdentifier.cbData);
}
if (pInfo->SequenceNumber.cbData) {
printf("SequenceNumber::");
DisplaySerialNumber(&pInfo->SequenceNumber);
printf("\n");
}
printf("ThisUpdate:: %s\n", FileTimeText(&pCtl->pCtlInfo->ThisUpdate));
printf("NextUpdate:: %s\n", FileTimeText(&pCtl->pCtlInfo->NextUpdate));
if (!IsTimeValidCtl(pCtl))
printf("****** Time Invalid CTL\n");
{
BYTE rgbHash[MAX_HASH_LEN];
DWORD cbHash = MAX_HASH_LEN;
CertGetCTLContextProperty(
pCtl,
CERT_SHA1_HASH_PROP_ID,
rgbHash,
&cbHash
);
DisplayThumbprint("SHA1", rgbHash, cbHash);
#if 0
CertGetCTLContextProperty(
pCtl,
CERT_MD5_HASH_PROP_ID,
rgbHash,
&cbHash
);
DisplayThumbprint("MD5", rgbHash, cbHash);
#endif
}
PrintAuxCtlProperties(pCtl, dwDisplayFlags);
if (dwDisplayFlags & DISPLAY_VERBOSE_FLAG) {
LPSTR pszObjId;
pszObjId = pInfo->SubjectAlgorithm.pszObjId;
if (pszObjId == NULL)
pszObjId = "<NULL OBJID>";
printf("SubjectAlgorithm:: %s\n", pszObjId);
if (pInfo->SubjectAlgorithm.Parameters.cbData) {
printf("SubjectAlgorithm.Parameters::\n");
PrintBytes(" ",
pInfo->SubjectAlgorithm.Parameters.pbData,
pInfo->SubjectAlgorithm.Parameters.cbData);
}
if (pInfo->cExtension != 0) {
PrintExtensions(pInfo->cExtension, pInfo->rgExtension,
dwDisplayFlags);
}
}
if (dwDisplayFlags & DISPLAY_NO_ISSUER_FLAG)
;
else if (0 == (dwDisplayFlags & DISPLAY_VERBOSE_FLAG)) {
DWORD dwFlags;
PCCERT_CONTEXT pSigner;
if (dwDisplayFlags & DISPLAY_CHECK_FLAG)
dwFlags = 0;
else
dwFlags = CMSG_SIGNER_ONLY_FLAG;
if (CryptMsgGetAndVerifySigner(
pCtl->hCryptMsg,
1, // cSignerStore
&hStore, // rghSignerStore
dwFlags,
&pSigner,
NULL // pdwSignerIndex
)) {
printf("----- Signer -----\n");
DisplayCert(pSigner, dwDisplayFlags & DISPLAY_BRIEF_FLAG);
CertFreeCertificateContext(pSigner);
} else {
DWORD dwErr = GetLastError();
if (CRYPT_E_NO_TRUSTED_SIGNER == dwErr)
printf("----- No Trusted Signer -----\n");
else {
printf("----- Signer -----\n");
PrintLastError("CryptMsgGetAndVerifySigner");
}
}
} else {
DWORD dwSignerCount;
DWORD cbData;
cbData = sizeof(dwSignerCount);
if (!CryptMsgGetParam(
pCtl->hCryptMsg,
CMSG_SIGNER_COUNT_PARAM,
0, // dwIndex
&dwSignerCount,
&cbData)) {
printf("----- Signer -----\n");
PrintLastError("CryptMsgGetParam(SIGNER_COUNT)");
} else if (0 == dwSignerCount)
printf("----- No Signers -----\n");
else {
DWORD dwSignerIndex;
for (dwSignerIndex = 0; dwSignerIndex < dwSignerCount;
dwSignerIndex++) {
DWORD dwFlags;
PCCERT_CONTEXT pSigner;
dwFlags = CMSG_USE_SIGNER_INDEX_FLAG;
if (0 == (dwDisplayFlags & DISPLAY_CHECK_FLAG))
dwFlags |= CMSG_SIGNER_ONLY_FLAG;
if (CryptMsgGetAndVerifySigner(
pCtl->hCryptMsg,
1, // cSignerStore
&hStore, // rghSignerStore
dwFlags,
&pSigner,
&dwSignerIndex
)) {
printf("----- Signer [%d] -----\n", dwSignerIndex);
DisplayCert(pSigner, 0);
CertFreeCertificateContext(pSigner);
} else {
DWORD dwErr = GetLastError();
if (CRYPT_E_NO_TRUSTED_SIGNER == dwErr)
printf("----- No Trusted Signer [%d] -----\n",
dwSignerIndex);
else {
printf("----- Signer [%d] -----\n", dwSignerIndex);
PrintLastError("CryptMsgGetAndVerifySigner");
}
}
DisplaySignerInfo(pCtl->hCryptMsg, dwSignerIndex,
dwDisplayFlags);
}
}
}
if (0 == (dwDisplayFlags & DISPLAY_BRIEF_FLAG)) {
if (pInfo->cCTLEntry == 0)
printf("----- No Entries -----\n");
else {
printf("----- Entries -----\n");
PrintCtlEntries(pCtl, dwDisplayFlags, hStore);
}
}
}