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.
8351 lines
182 KiB
8351 lines
182 KiB
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 1995 - 1999
|
|
//
|
|
// File: dump.cpp
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
#include <pch.cpp>
|
|
|
|
#pragma hdrstop
|
|
|
|
#include "csprop.h"
|
|
#include "cscsp.h"
|
|
#include "csber.h"
|
|
|
|
#define __dwFILE__ __dwFILE_CERTUTIL_DUMP_CPP__
|
|
|
|
|
|
#if DBG
|
|
#define wszCERTUTIL L"(certutil)"
|
|
#else
|
|
#define wszCERTUTIL L""
|
|
#endif
|
|
|
|
WCHAR const g_wszCertUtil[] = wszCERTUTIL;
|
|
|
|
DWORD s_DbgSsRecoveryTrace = DBG_SS_CERTUTILI;
|
|
|
|
|
|
HRESULT
|
|
DumpAttributes(
|
|
IN CRYPT_ATTRIBUTE const *rgAttr,
|
|
IN DWORD cAttr,
|
|
IN BOOL fQuiet,
|
|
IN DWORD Type, // FOT_*
|
|
OPTIONAL IN HCERTSTORE hStore,
|
|
OPTIONAL OUT BYTE *pbHashUserCert,
|
|
OPTIONAL IN OUT DWORD *pcbHashUserCert,
|
|
OPTIONAL IN OUT CERT_EXTENSIONS **ppExtInfo);
|
|
|
|
|
|
WCHAR const *
|
|
wszRDNValueType(
|
|
IN DWORD dwValueType)
|
|
{
|
|
WCHAR const *pwsz;
|
|
|
|
switch (CERT_RDN_TYPE_MASK & dwValueType)
|
|
{
|
|
case CERT_RDN_ANY_TYPE:
|
|
pwsz = L"CERT_RDN_ANY_TYPE";
|
|
break;
|
|
|
|
case CERT_RDN_ENCODED_BLOB:
|
|
pwsz = L"CERT_RDN_ENCODED_BLOB";
|
|
break;
|
|
|
|
case CERT_RDN_OCTET_STRING:
|
|
pwsz = L"CERT_RDN_OCTET_STRING";
|
|
break;
|
|
|
|
case CERT_RDN_NUMERIC_STRING:
|
|
pwsz = L"CERT_RDN_NUMERIC_STRING";
|
|
break;
|
|
|
|
case CERT_RDN_PRINTABLE_STRING:
|
|
pwsz = L"CERT_RDN_PRINTABLE_STRING";
|
|
break;
|
|
|
|
case CERT_RDN_TELETEX_STRING:
|
|
pwsz = L"CERT_RDN_TELETEX_STRING";
|
|
break;
|
|
|
|
//case CERT_RDN_T61_STRING:
|
|
//pwsz = L"CERT_RDN_T61_STRING";
|
|
//break;
|
|
|
|
case CERT_RDN_VIDEOTEX_STRING:
|
|
pwsz = L"CERT_RDN_VIDEOTEX_STRING";
|
|
break;
|
|
|
|
case CERT_RDN_IA5_STRING:
|
|
pwsz = L"CERT_RDN_IA5_STRING";
|
|
break;
|
|
|
|
case CERT_RDN_GRAPHIC_STRING:
|
|
pwsz = L"CERT_RDN_GRAPHIC_STRING";
|
|
break;
|
|
|
|
//case CERT_RDN_VISIBLE_STRING:
|
|
//pwsz = L"CERT_RDN_VISIBLE_STRING";
|
|
//break;
|
|
|
|
case CERT_RDN_ISO646_STRING:
|
|
pwsz = L"CERT_RDN_ISO646_STRING";
|
|
break;
|
|
|
|
case CERT_RDN_GENERAL_STRING:
|
|
pwsz = L"CERT_RDN_GENERAL_STRING";
|
|
break;
|
|
|
|
case CERT_RDN_UNIVERSAL_STRING:
|
|
pwsz = L"CERT_RDN_UNIVERSAL_STRING";
|
|
break;
|
|
|
|
//case CERT_RDN_INT4_STRING:
|
|
//pwsz = L"CERT_RDN_INT4_STRING";
|
|
//break;
|
|
|
|
//case CERT_RDN_BMP_STRING:
|
|
//pwsz = L"CERT_RDN_BMP_STRING";
|
|
//break;
|
|
|
|
case CERT_RDN_UNICODE_STRING:
|
|
pwsz = L"CERT_RDN_UNICODE_STRING";
|
|
break;
|
|
|
|
case CERT_RDN_UTF8_STRING:
|
|
pwsz = L"CERT_RDN_UTF8_STRING";
|
|
break;
|
|
|
|
default:
|
|
pwsz = myLoadResourceString(IDS_QUESTIONMARKS); // "???"
|
|
break;
|
|
}
|
|
return(pwsz);
|
|
}
|
|
|
|
|
|
VOID
|
|
cuPrintCRLFString(
|
|
IN WCHAR const *pwszPrefix,
|
|
IN WCHAR const *pwszIn)
|
|
{
|
|
if (NULL == pwszPrefix)
|
|
{
|
|
pwszPrefix = g_wszEmpty;
|
|
}
|
|
while (L'\0' != *pwszIn)
|
|
{
|
|
DWORD i;
|
|
WCHAR const *pwc;
|
|
|
|
pwc = pwszIn++;
|
|
i = wcscspn(pwszIn, L"\r\n");
|
|
|
|
wprintf(
|
|
L"%.1ws%ws%.*ws",
|
|
pwc,
|
|
L'\n' == *pwc? pwszPrefix : g_wszEmpty,
|
|
i,
|
|
pwszIn);
|
|
pwszIn += i;
|
|
|
|
if (L'\r' == *pwszIn)
|
|
{
|
|
pwszIn++;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
cuPrintPossibleObjectIdName(
|
|
IN WCHAR const *pwszObjId)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (iswdigit(*pwszObjId))
|
|
{
|
|
hr = myVerifyObjId(pwszObjId);
|
|
if (S_OK == hr)
|
|
{
|
|
WCHAR const *pwszName = cuGetOIDName(pwszObjId);
|
|
|
|
if (NULL != pwszName && L'\0' != *pwszName)
|
|
{
|
|
wprintf(L" %ws", pwszName);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
WCHAR const *
|
|
cuGetOIDNameA(
|
|
IN char const *pszObjId)
|
|
{
|
|
HRESULT hr;
|
|
WCHAR const *pwszName1 = g_wszEmpty;
|
|
WCHAR const *pwszName2;
|
|
char *pszT = NULL;
|
|
static WCHAR s_wszName[512];
|
|
|
|
pszT = (char *) LocalAlloc(LMEM_FIXED, 1 + strlen(pszObjId) + 1);
|
|
if (NULL == pszT)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "LocalAlloc");
|
|
}
|
|
strcpy(&pszT[1], pszObjId);
|
|
|
|
*pszT = '+';
|
|
pwszName1 = myGetOIDNameA(pszT); // Group OID lookup
|
|
|
|
*pszT = '-';
|
|
pwszName2 = myGetOIDNameA(pszT); // Generic OID lookup
|
|
|
|
if (0 == mylstrcmpiL(pwszName1, pwszName2))
|
|
{
|
|
pwszName2 = g_wszEmpty; // display only one if they're the same
|
|
}
|
|
if (L'\0' == *pwszName1)
|
|
{
|
|
pwszName1 = pwszName2;
|
|
pwszName2 = g_wszEmpty;
|
|
}
|
|
|
|
if (L'\0' != *pwszName2 &&
|
|
ARRAYSIZE(s_wszName) > wcslen(pwszName1) + wcslen(pwszName2) + 3)
|
|
{
|
|
wcscpy(s_wszName, pwszName1);
|
|
wcscat(s_wszName, L" " wszLPAREN);
|
|
wcscat(s_wszName, pwszName2);
|
|
wcscat(s_wszName, wszRPAREN);
|
|
pwszName1 = s_wszName;
|
|
}
|
|
|
|
error:
|
|
if (NULL != pszT)
|
|
{
|
|
LocalFree(pszT);
|
|
}
|
|
return(pwszName1);
|
|
}
|
|
|
|
|
|
WCHAR const *
|
|
cuGetOIDName(
|
|
IN WCHAR const *pwszObjId)
|
|
{
|
|
HRESULT hr;
|
|
char *pszObjId = NULL;
|
|
WCHAR const *pwszName = g_wszEmpty;
|
|
|
|
if (!myConvertWszToSz(&pszObjId, pwszObjId, -1))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "myConvertWszToSz");
|
|
}
|
|
pwszName = cuGetOIDNameA(pszObjId);
|
|
|
|
error:
|
|
if (NULL != pszObjId)
|
|
{
|
|
LocalFree(pszObjId);
|
|
}
|
|
return(pwszName);
|
|
}
|
|
|
|
|
|
VOID
|
|
cuDumpOIDAndDescriptionA(
|
|
IN char const *pszObjId)
|
|
{
|
|
WCHAR const *pwsz;
|
|
|
|
wprintf(L"%hs", pszObjId);
|
|
pwsz = cuGetOIDNameA(pszObjId);
|
|
if (NULL != pwsz && L'\0' != *pwsz)
|
|
{
|
|
wprintf(L" %ws", pwsz);
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
cuDumpOIDAndDescription(
|
|
IN WCHAR const *pwszObjId)
|
|
{
|
|
WCHAR const *pwsz;
|
|
|
|
wprintf(L"%ws", pwszObjId);
|
|
pwsz = cuGetOIDName(pwszObjId);
|
|
if (NULL != pwsz && L'\0' != *pwsz)
|
|
{
|
|
wprintf(L" %ws", pwsz);
|
|
}
|
|
}
|
|
|
|
|
|
HRESULT
|
|
cuCertNameToStr(
|
|
IN BOOL fMultiLine,
|
|
IN CERT_NAME_BLOB const *pNameBlob,
|
|
OUT WCHAR **ppwszCertName)
|
|
{
|
|
HRESULT hr;
|
|
DWORD Flags = CERT_X500_NAME_STR |
|
|
CERT_NAME_STR_REVERSE_FLAG |
|
|
CERT_NAME_STR_NO_QUOTING_FLAG;
|
|
|
|
*ppwszCertName = NULL;
|
|
if (fMultiLine)
|
|
{
|
|
Flags |= CERT_NAME_STR_CRLF_FLAG;
|
|
}
|
|
hr = myCertNameToStr(
|
|
X509_ASN_ENCODING,
|
|
pNameBlob,
|
|
Flags,
|
|
ppwszCertName);
|
|
_JumpIfError(hr, error, "myCertNameToStr");
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
typedef struct _RDNTABLE
|
|
{
|
|
CHAR const *pszObjId;
|
|
DWORD cchMax;
|
|
} RDNTABLE;
|
|
|
|
RDNTABLE const g_RdnTable[] =
|
|
{
|
|
{ szOID_COUNTRY_NAME, cchCOUNTRYNAMEMAX },
|
|
{ szOID_ORGANIZATION_NAME, cchORGANIZATIONNAMEMAX },
|
|
{ szOID_ORGANIZATIONAL_UNIT_NAME, cchORGANIZATIONALUNITNAMEMAX },
|
|
{ szOID_COMMON_NAME, cchCOMMONNAMEMAX },
|
|
{ szOID_LOCALITY_NAME, cchLOCALITYMANAMEMAX },
|
|
{ szOID_STATE_OR_PROVINCE_NAME, cchSTATEORPROVINCENAMEMAX },
|
|
{ szOID_TITLE, cchTITLEMAX },
|
|
{ szOID_GIVEN_NAME, cchGIVENNAMEMAX },
|
|
{ szOID_INITIALS, cchINITIALSMAX },
|
|
{ szOID_SUR_NAME, cchSURNAMEMAX },
|
|
{ szOID_DOMAIN_COMPONENT, cchDOMAINCOMPONENTMAX },
|
|
{ szOID_RSA_emailAddr, cchEMAILMAX },
|
|
{ szOID_STREET_ADDRESS, cchSTREETADDRESSMAX },
|
|
{ szOID_RSA_unstructName, cchUNSTRUCTUREDNAMEMAX },
|
|
{ szOID_RSA_unstructAddr, cchUNSTRUCTUREDADDRESSMAX },
|
|
{ szOID_DEVICE_SERIAL_NUMBER, cchDEVICESERIALNUMBERMAX },
|
|
{ NULL, 0 },
|
|
};
|
|
|
|
|
|
DWORD
|
|
cwcRDNMax(
|
|
IN char const *pszObjId)
|
|
{
|
|
RDNTABLE const *pRdnTable;
|
|
DWORD cwcMax = MAXDWORD;
|
|
|
|
for (pRdnTable = g_RdnTable; NULL != pRdnTable->pszObjId; pRdnTable++)
|
|
{
|
|
if (0 == strcmp(pszObjId, pRdnTable->pszObjId))
|
|
{
|
|
cwcMax = pRdnTable->cchMax;
|
|
break;
|
|
}
|
|
}
|
|
return(cwcMax);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
cuDisplayCertNameValue(
|
|
OPTIONAL IN char const *pszObjId,
|
|
OPTIONAL IN WCHAR const *pwszChoice,
|
|
IN DWORD dwValueType,
|
|
IN CRYPT_DATA_BLOB const *pValueW,
|
|
IN CRYPT_DATA_BLOB const *pValueA)
|
|
{
|
|
HRESULT hr;
|
|
DWORD cwc;
|
|
DWORD cwcMax = MAXDWORD;
|
|
CRYPT_DATA_BLOB ValueUTF8;
|
|
|
|
ValueUTF8.pbData = NULL;
|
|
cwc = pValueW->cbData / sizeof(WCHAR);
|
|
if (NULL != pszObjId)
|
|
{
|
|
cwcMax = cwcRDNMax(pszObjId);
|
|
}
|
|
|
|
if (CERT_RDN_UTF8_STRING == dwValueType)
|
|
{
|
|
if (myConvertWszToUTF8(
|
|
(char **) &ValueUTF8.pbData,
|
|
(WCHAR const *) pValueW->pbData,
|
|
pValueW->cbData / sizeof(WCHAR)))
|
|
{
|
|
ValueUTF8.cbData = strlen((CHAR const *) ValueUTF8.pbData);
|
|
pValueA = &ValueUTF8;
|
|
}
|
|
}
|
|
|
|
wprintf(
|
|
L"%ws, %ws = %u",
|
|
wszRDNValueType(dwValueType),
|
|
myLoadResourceString(IDS_LENGTH), // "Length"
|
|
pValueA->cbData);
|
|
|
|
if (MAXDWORD != cwcMax || CERT_RDN_OCTET_STRING != dwValueType)
|
|
{
|
|
wprintf(
|
|
L" " wszLPAREN L"%ws%ws%u",
|
|
cwc <= cwcMax? g_wszEmpty : myLoadResourceString(IDS_OVERFLOW), // "OVERFLOW:"
|
|
cwc <= cwcMax? g_wszEmpty : L" ",
|
|
cwc);
|
|
if (NULL != pszObjId && MAXDWORD != cwcMax)
|
|
{
|
|
wprintf(L"/%u", cwcMax);
|
|
}
|
|
wprintf(
|
|
L" %ws" wszRPAREN,
|
|
myLoadResourceString(IDS_CHARS)); // "Characters"
|
|
}
|
|
wprintf(wszNewLine);
|
|
|
|
wprintf(g_wszPad8);
|
|
if (NULL != pszObjId)
|
|
{
|
|
cuDumpOIDAndDescriptionA(pszObjId);
|
|
wprintf(L"=");
|
|
}
|
|
else if (NULL != pwszChoice)
|
|
{
|
|
wprintf(L"%ws=", pwszChoice);
|
|
}
|
|
if (CERT_RDN_OCTET_STRING != dwValueType)
|
|
{
|
|
wprintf(L"\"%ws\"\n", pValueW->pbData);
|
|
}
|
|
wprintf(wszNewLine);
|
|
|
|
DumpHex(
|
|
DH_NOADDRESS | DH_NOTABPREFIX | 8,
|
|
pValueA->pbData,
|
|
pValueA->cbData);
|
|
|
|
if (pValueA->cbData != pValueW->cbData ||
|
|
0 != memcmp(pValueA->pbData, pValueW->pbData, pValueW->cbData))
|
|
{
|
|
wprintf(wszNewLine);
|
|
DumpHex(
|
|
DH_NOADDRESS | DH_NOTABPREFIX | 8,
|
|
pValueW->pbData,
|
|
pValueW->cbData);
|
|
}
|
|
hr = S_OK;
|
|
|
|
//error:
|
|
if (NULL != ValueUTF8.pbData)
|
|
{
|
|
LocalFree(ValueUTF8.pbData);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
cuDisplayCertName(
|
|
IN BOOL fMultiLine,
|
|
OPTIONAL IN WCHAR const *pwszNamePrefix,
|
|
OPTIONAL IN WCHAR const *pwszName,
|
|
IN WCHAR const *pwszPad,
|
|
IN CERT_NAME_BLOB const *pNameBlob,
|
|
OPTIONAL IN CERT_INFO const *pCertInfo)
|
|
{
|
|
WCHAR *pwszCertName = NULL;
|
|
DWORD i;
|
|
HRESULT hr = S_OK;
|
|
CERT_NAME_INFO *pNameInfoA = NULL;
|
|
CERT_NAME_INFO *pNameInfoW = NULL;
|
|
WCHAR *pwszAltName = NULL;
|
|
DWORD cb;
|
|
|
|
hr = cuCertNameToStr(fMultiLine, pNameBlob, &pwszCertName);
|
|
_JumpIfError(hr, error, "cuCertNameToStr");
|
|
|
|
if (NULL != pwszNamePrefix)
|
|
{
|
|
wprintf(pwszNamePrefix);
|
|
}
|
|
if (NULL != pwszName)
|
|
{
|
|
wprintf(L"%ws:", pwszName);
|
|
}
|
|
wprintf(fMultiLine? L"\n%ws" : L" ", pwszPad);
|
|
cuPrintCRLFString(pwszPad, pwszCertName);
|
|
if (L'\0' == *pwszCertName)
|
|
{
|
|
wprintf(L"%ws", myLoadResourceString(IDS_PROP_EMPTY)); // "EMPTY"
|
|
if (NULL != pCertInfo)
|
|
{
|
|
CERT_EXTENSION const *pExt;
|
|
|
|
pExt = CertFindExtension(
|
|
szOID_SUBJECT_ALT_NAME2,
|
|
pCertInfo->cExtension,
|
|
pCertInfo->rgExtension);
|
|
if (NULL != pExt)
|
|
{
|
|
if (!CryptFormatObject(
|
|
X509_ASN_ENCODING,
|
|
0,
|
|
CRYPT_FORMAT_STR_NO_HEX,
|
|
NULL,
|
|
pExt->pszObjId,
|
|
pExt->Value.pbData,
|
|
pExt->Value.cbData,
|
|
NULL,
|
|
&cb))
|
|
{
|
|
hr = myHLastError();
|
|
_PrintError(hr, "CryptFormatObject");
|
|
if (S_OK == hr)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pwszAltName = (WCHAR *) LocalAlloc(LMEM_FIXED, cb);
|
|
if (NULL == pwszAltName)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "LocalAlloc");
|
|
}
|
|
if (!CryptFormatObject(
|
|
X509_ASN_ENCODING,
|
|
0,
|
|
CRYPT_FORMAT_STR_NO_HEX,
|
|
NULL,
|
|
pExt->pszObjId,
|
|
pExt->Value.pbData,
|
|
pExt->Value.cbData,
|
|
pwszAltName,
|
|
&cb))
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, error, "CryptFormatObject");
|
|
}
|
|
wprintf(L" (%ws)", pwszAltName);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
wprintf(wszNewLine);
|
|
|
|
if (1 < g_fVerbose)
|
|
{
|
|
DumpHex(
|
|
DH_NOTABPREFIX | 4,
|
|
pNameBlob->pbData,
|
|
pNameBlob->cbData);
|
|
wprintf(wszNewLine);
|
|
}
|
|
|
|
if (!myDecodeName(
|
|
X509_ASN_ENCODING,
|
|
X509_UNICODE_NAME,
|
|
pNameBlob->pbData,
|
|
pNameBlob->cbData,
|
|
CERTLIB_USE_LOCALALLOC,
|
|
&pNameInfoW,
|
|
&cb))
|
|
{
|
|
|
|
hr = myHLastError();
|
|
_JumpError(hr, error, "myDecodeName");
|
|
}
|
|
|
|
if (!myDecodeName(
|
|
X509_ASN_ENCODING,
|
|
X509_NAME,
|
|
pNameBlob->pbData,
|
|
pNameBlob->cbData,
|
|
CERTLIB_USE_LOCALALLOC,
|
|
&pNameInfoA,
|
|
&cb))
|
|
{
|
|
|
|
hr = myHLastError();
|
|
_JumpError(hr, error, "myDecodeName");
|
|
}
|
|
|
|
if (g_fVerbose)
|
|
{
|
|
for (i = 0; i < pNameInfoW->cRDN; i++)
|
|
{
|
|
CERT_RDN const *prdnA;
|
|
CERT_RDN const *prdnW;
|
|
DWORD j;
|
|
|
|
prdnA = &pNameInfoA->rgRDN[i];
|
|
prdnW = &pNameInfoW->rgRDN[i];
|
|
|
|
for (j = 0; j < prdnW->cRDNAttr; j++)
|
|
{
|
|
CERT_RDN_ATTR const *prdnaA;
|
|
CERT_RDN_ATTR const *prdnaW;
|
|
|
|
prdnaA = &prdnA->rgRDNAttr[j];
|
|
prdnaW = &prdnW->rgRDNAttr[j];
|
|
|
|
wprintf(L" [%u,%u]: ", i, j);
|
|
hr = cuDisplayCertNameValue(
|
|
prdnaW->pszObjId,
|
|
NULL,
|
|
prdnaW->dwValueType,
|
|
&prdnaW->Value,
|
|
&prdnaA->Value);
|
|
_PrintIfError(hr, "cuDisplayCertNameValue");
|
|
wprintf(wszNewLine);
|
|
}
|
|
}
|
|
}
|
|
|
|
error:
|
|
if (NULL != pwszCertName)
|
|
{
|
|
LocalFree(pwszCertName);
|
|
}
|
|
if (NULL != pwszAltName)
|
|
{
|
|
LocalFree(pwszAltName);
|
|
}
|
|
if (NULL != pNameInfoW)
|
|
{
|
|
LocalFree(pNameInfoW);
|
|
}
|
|
if (NULL != pNameInfoA)
|
|
{
|
|
LocalFree(pNameInfoA);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
cuDisplayCertNames(
|
|
IN BOOL fMultiLine,
|
|
OPTIONAL IN WCHAR const *pwszNamePrefix,
|
|
IN CERT_INFO const *pCertInfo)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = cuDisplayCertName(
|
|
fMultiLine,
|
|
pwszNamePrefix,
|
|
myLoadResourceString(IDS_ISSUER), // "Issuer"
|
|
g_wszPad4,
|
|
&pCertInfo->Issuer,
|
|
NULL);
|
|
_JumpIfError(hr, error, "cuDisplayCertName(Issuer)");
|
|
|
|
hr = cuDisplayCertName(
|
|
fMultiLine,
|
|
pwszNamePrefix,
|
|
myLoadResourceString(IDS_SUBJECT), // "Subject"
|
|
g_wszPad4,
|
|
&pCertInfo->Subject,
|
|
pCertInfo);
|
|
_JumpIfError(hr, error, "cuDisplayCertName(Subject)");
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
#define POLICY_MASK \
|
|
(EXTENSION_POLICY_MASK & ~(EXTENSION_CRITICAL_FLAG | EXTENSION_DISABLE_FLAG))
|
|
|
|
#define EXTRA_MASK (~(EXTENSION_POLICY_MASK | EXTENSION_ORIGIN_MASK))
|
|
|
|
WCHAR const *
|
|
cuwszFromExtFlags(
|
|
DWORD ExtFlags)
|
|
{
|
|
static WCHAR awc[MAX_PATH];
|
|
WCHAR const *pwszComma;
|
|
WCHAR const *pwszSep = wszLPAREN;
|
|
DWORD msgid;
|
|
WCHAR const *pwszT;
|
|
|
|
awc[0] = L'\0';
|
|
pwszComma = myLoadResourceString(IDS_SEPARATOR); // ", "
|
|
if (NULL == pwszComma)
|
|
{
|
|
pwszComma = L", ";
|
|
}
|
|
if (EXTENSION_CRITICAL_FLAG & ExtFlags)
|
|
{
|
|
wcscat(awc, pwszSep);
|
|
pwszSep = pwszComma;
|
|
pwszT = myLoadResourceString(IDS_CRITICAL); // "Critical"
|
|
if (NULL != pwszT)
|
|
{
|
|
wcscat(awc, pwszT);
|
|
}
|
|
}
|
|
if (~EXTENSION_CRITICAL_FLAG & ExtFlags)
|
|
{
|
|
if (EXTENSION_DISABLE_FLAG & ExtFlags)
|
|
{
|
|
wcscat(awc, pwszSep);
|
|
pwszSep = pwszComma;
|
|
pwszT = myLoadResourceString(IDS_DISABLED); // "Disabled"
|
|
if (NULL != pwszT)
|
|
{
|
|
wcscat(awc, pwszT);
|
|
}
|
|
}
|
|
if (POLICY_MASK & ExtFlags)
|
|
{
|
|
wcscat(awc, pwszSep);
|
|
pwszSep = pwszComma;
|
|
pwszT = myLoadResourceString(IDS_FORMAT_POLICYFLAGS); // "PolicyFlags=%x"
|
|
if (NULL == pwszT)
|
|
{
|
|
pwszT = L"PolicyFlags=%x";
|
|
}
|
|
wsprintf(&awc[wcslen(awc)], pwszT, POLICY_MASK & ExtFlags);
|
|
}
|
|
switch (EXTENSION_ORIGIN_MASK & ExtFlags)
|
|
{
|
|
case EXTENSION_ORIGIN_REQUEST:
|
|
msgid = IDS_REQUEST; // "Request"
|
|
break;
|
|
|
|
case EXTENSION_ORIGIN_POLICY:
|
|
msgid = IDS_POLICY; // "Policy"
|
|
break;
|
|
|
|
case EXTENSION_ORIGIN_ADMIN:
|
|
msgid = IDS_ADMIN; // "Admin"
|
|
break;
|
|
|
|
case EXTENSION_ORIGIN_SERVER:
|
|
msgid = IDS_SERVER; // "Server"
|
|
break;
|
|
|
|
case EXTENSION_ORIGIN_RENEWALCERT:
|
|
msgid = IDS_RENEWALCERT; // "Renewal Cert"
|
|
break;
|
|
|
|
case EXTENSION_ORIGIN_IMPORTEDCERT:
|
|
msgid = IDS_IMPORTEDCERT; // "Imported Cert"
|
|
break;
|
|
|
|
case EXTENSION_ORIGIN_PKCS7:
|
|
msgid = IDS_PKCS7ATTRIBUTE; // "PKCS7 Attribute"
|
|
break;
|
|
|
|
case EXTENSION_ORIGIN_CMC:
|
|
msgid = IDS_CMCATTRIBUTE; // "CMC Attribute"
|
|
break;
|
|
|
|
case EXTENSION_ORIGIN_CACERT:
|
|
msgid = IDS_CACERTEXT; // "CA Cert"
|
|
break;
|
|
|
|
default:
|
|
msgid = IDS_UNKNOWN; // "UNKNOWN"
|
|
break;
|
|
}
|
|
wcscat(awc, pwszSep);
|
|
pwszSep = pwszComma;
|
|
pwszT = myLoadResourceString(IDS_FORMAT_ORIGIN); // "Origin=%ws"
|
|
if (NULL == pwszT)
|
|
{
|
|
pwszT = L"Origin=%ws";
|
|
}
|
|
wsprintf(&awc[wcslen(awc)], pwszT, myLoadResourceString(msgid));
|
|
|
|
if (EXTRA_MASK & ExtFlags)
|
|
{
|
|
wcscat(awc, pwszSep);
|
|
pwszT = myLoadResourceString(IDS_FORMAT_UNKNOWN_HEX); // "???=%x"
|
|
if (NULL == pwszT)
|
|
{
|
|
pwszT = L"???=%x";
|
|
}
|
|
wsprintf(&awc[wcslen(awc)], pwszT, EXTRA_MASK & ExtFlags);
|
|
}
|
|
}
|
|
if (L'\0' != awc[0])
|
|
{
|
|
wcscat(awc, wszRPAREN);
|
|
}
|
|
return(awc);
|
|
}
|
|
|
|
|
|
VOID
|
|
PrintStringWithPrefix(
|
|
IN WCHAR const *pwszPrefix,
|
|
IN WCHAR const *pwszIn)
|
|
{
|
|
while (L'\0' != *pwszIn)
|
|
{
|
|
DWORD i;
|
|
DWORD j;
|
|
WCHAR const *pwszNewLine;
|
|
|
|
pwszNewLine = g_wszEmpty;
|
|
j = 0;
|
|
i = wcscspn(pwszIn, L"\n");
|
|
if (L'\n' == pwszIn[i])
|
|
{
|
|
pwszNewLine = L"\n";
|
|
j++;
|
|
if (0 < i && L'\r' == pwszIn[i - 1])
|
|
{
|
|
i--;
|
|
j++;
|
|
}
|
|
}
|
|
wprintf(L"%ws%.*ws%ws", pwszPrefix, i, pwszIn, pwszNewLine);
|
|
pwszIn += i + j;
|
|
}
|
|
}
|
|
|
|
|
|
WCHAR const *
|
|
wszAltNameChoice(
|
|
IN LONG Choice)
|
|
{
|
|
WCHAR const *pwsz;
|
|
|
|
switch (Choice)
|
|
{
|
|
case CERT_ALT_NAME_OTHER_NAME:
|
|
pwsz = L"CERT_ALT_NAME_OTHER_NAME";
|
|
break;
|
|
|
|
case CERT_ALT_NAME_RFC822_NAME:
|
|
pwsz = L"CERT_ALT_NAME_RFC822_NAME";
|
|
break;
|
|
|
|
case CERT_ALT_NAME_DNS_NAME:
|
|
pwsz = L"CERT_ALT_NAME_DNS_NAME";
|
|
break;
|
|
|
|
case CERT_ALT_NAME_X400_ADDRESS:
|
|
pwsz = L"CERT_ALT_NAME_X400_ADDRESS";
|
|
break;
|
|
|
|
case CERT_ALT_NAME_DIRECTORY_NAME:
|
|
pwsz = L"CERT_ALT_NAME_DIRECTORY_NAME";
|
|
break;
|
|
|
|
case CERT_ALT_NAME_EDI_PARTY_NAME:
|
|
pwsz = L"CERT_ALT_NAME_EDI_PARTY_NAME";
|
|
break;
|
|
|
|
case CERT_ALT_NAME_URL:
|
|
pwsz = L"CERT_ALT_NAME_URL";
|
|
break;
|
|
|
|
case CERT_ALT_NAME_IP_ADDRESS:
|
|
pwsz = L"CERT_ALT_NAME_IP_ADDRESS";
|
|
break;
|
|
|
|
case CERT_ALT_NAME_REGISTERED_ID:
|
|
pwsz = L"CERT_ALT_NAME_REGISTERED_ID";
|
|
break;
|
|
|
|
default:
|
|
pwsz = myLoadResourceString(IDS_QUESTIONMARKS); // "???"
|
|
break;
|
|
}
|
|
return(pwsz);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
DumpIPAddress(
|
|
IN WCHAR const *pwszPad,
|
|
IN UINT idsMsg,
|
|
IN BYTE const *pb,
|
|
IN DWORD cb)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (CB_IPV6ADDRESS != cb && CB_IPV4ADDRESS != cb)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
|
|
_JumpError(hr, error, "IPAddress size");
|
|
}
|
|
wprintf(L"%ws %ws = ", pwszPad, myLoadResourceString(idsMsg));
|
|
if (CB_IPV6ADDRESS == cb)
|
|
{
|
|
BYTE abZero[CB_IPV6ADDRESS - CB_IPV4ADDRESS];
|
|
|
|
ZeroMemory(abZero, sizeof(abZero));
|
|
if (0 == memcmp(abZero, pb, sizeof(abZero)))
|
|
{
|
|
wprintf(L"::");
|
|
pb += sizeof(abZero);
|
|
cb = CB_IPV4ADDRESS;
|
|
CSASSERT(CB_IPV6ADDRESS - sizeof(abZero) == cb);
|
|
}
|
|
else
|
|
{
|
|
DWORD j;
|
|
WCHAR const *pwsz = L"";
|
|
BOOL fZeroSeen = FALSE;
|
|
BOOL fZero = FALSE;
|
|
|
|
for (j = 0; j < cb / sizeof(USHORT); j++)
|
|
{
|
|
USHORT us =
|
|
(pb[sizeof(USHORT) * j] << 8) |
|
|
pb[sizeof(USHORT) * j + 1];
|
|
|
|
if (0 == us && (fZero || !fZeroSeen))
|
|
{
|
|
fZero = TRUE;
|
|
fZeroSeen = TRUE;
|
|
pwsz = L"::";
|
|
}
|
|
else
|
|
{
|
|
wprintf(L"%ws%04x", pwsz, us);
|
|
pwsz = L":";
|
|
fZero = FALSE;
|
|
}
|
|
}
|
|
if (fZero)
|
|
{
|
|
wprintf(L"%ws", pwsz);
|
|
CSASSERT(0 == lstrcmp(pwsz, L"::"));
|
|
}
|
|
}
|
|
}
|
|
if (CB_IPV4ADDRESS == cb)
|
|
{
|
|
wprintf(
|
|
L"%u.%u.%u.%u",
|
|
pb[0],
|
|
pb[1],
|
|
pb[2],
|
|
pb[3]);
|
|
}
|
|
wprintf(wszNewLine);
|
|
hr = S_OK;
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
DumpAltName(
|
|
IN WCHAR const *pwszPad,
|
|
IN DWORD dwSubtreeIndex,
|
|
IN BYTE const *pbExtension,
|
|
IN DWORD cbExtension)
|
|
{
|
|
HRESULT hr;
|
|
BSTR strExtension = NULL;
|
|
BSTR strObjId = NULL;
|
|
BSTR strName = NULL;
|
|
ICertEncodeAltName *pAltName = NULL;
|
|
CRYPT_DATA_BLOB *pBlob = NULL;
|
|
LONG Count;
|
|
LONG Choice;
|
|
LONG i;
|
|
DWORD cb;
|
|
|
|
hr = CoCreateInstance(
|
|
CLSID_CCertEncodeAltName,
|
|
NULL, // pUnkOuter
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_ICertEncodeAltName,
|
|
(VOID **) &pAltName);
|
|
_JumpIfError(hr, error, "CoCreateInstance");
|
|
|
|
if (!ConvertWszToBstr(
|
|
&strExtension,
|
|
(WCHAR const *) pbExtension,
|
|
cbExtension))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "ConvertWszToBstr");
|
|
}
|
|
hr = pAltName->Decode(strExtension);
|
|
_JumpIfError(hr, error, "Decode");
|
|
|
|
hr = pAltName->GetNameCount(&Count);
|
|
_JumpIfError(hr, error, "GetNameCount");
|
|
|
|
if (MAXDWORD == dwSubtreeIndex)
|
|
{
|
|
wprintf(pwszPad);
|
|
wprintf(
|
|
myLoadResourceString(IDS_FORMAT_ALTNAMECOUNT), // "AltName: %u entries:"
|
|
Count);
|
|
wprintf(wszNewLine);
|
|
}
|
|
|
|
for (i = 0; i < Count; i++)
|
|
{
|
|
BOOL fHex = FALSE;
|
|
BOOL fNameBlob = FALSE;
|
|
|
|
hr = pAltName->GetNameChoice(i, &Choice);
|
|
_JumpIfError(hr, error, "GetNameChoice");
|
|
|
|
if (NULL != strName)
|
|
{
|
|
SysFreeString(strName);
|
|
strName = NULL;
|
|
}
|
|
hr = pAltName->GetName(i, &strName);
|
|
_JumpIfError(hr, error, "GetName");
|
|
|
|
myRegisterMemAlloc(strName, -1, CSM_SYSALLOC);
|
|
|
|
wprintf(pwszPad);
|
|
if (MAXDWORD == dwSubtreeIndex)
|
|
{
|
|
wprintf(
|
|
L"%ws[%u] ",
|
|
myLoadResourceString(IDS_ALTNAME), // "AltName"
|
|
i);
|
|
}
|
|
wprintf(L"%ws:", wszAltNameChoice(Choice));
|
|
if (CERT_ALT_NAME_DIRECTORY_NAME == Choice)
|
|
{
|
|
fNameBlob = TRUE; // Name is encoded as a blob
|
|
}
|
|
else if (CERT_ALT_NAME_IP_ADDRESS == Choice)
|
|
{
|
|
BYTE const *pb = (BYTE const *) strName;
|
|
|
|
cb = SysStringByteLen(strName);
|
|
|
|
wprintf(wszNewLine);
|
|
if (2 * CB_IPV6ADDRESS == cb || 2 * CB_IPV4ADDRESS == cb)
|
|
{
|
|
DumpIPAddress(pwszPad, IDS_IPADDRESS, pb, cb / 2);
|
|
DumpIPAddress(pwszPad, IDS_MASK, &pb[cb / 2], cb / 2);
|
|
}
|
|
else
|
|
{
|
|
fHex = TRUE;
|
|
}
|
|
}
|
|
else if (CERT_ALT_NAME_OTHER_NAME == Choice)
|
|
{
|
|
if (NULL != strObjId)
|
|
{
|
|
SysFreeString(strObjId);
|
|
strObjId = NULL;
|
|
}
|
|
hr = pAltName->GetName(EAN_NAMEOBJECTID | i, &strObjId);
|
|
_JumpIfError(hr, error, "GetName");
|
|
|
|
myRegisterMemAlloc(strObjId, -1, CSM_SYSALLOC);
|
|
|
|
wprintf(L" ");
|
|
cuDumpOIDAndDescription(strObjId);
|
|
wprintf(L": ");
|
|
|
|
if (0 == lstrcmp(TEXT(szOID_NT_PRINCIPAL_NAME), strObjId) ||
|
|
BER_UTF8_STRING == *(BYTE const *) strName ||
|
|
BER_UNICODE_STRING == *(BYTE const *) strName)
|
|
{
|
|
CERT_NAME_VALUE *pNameValueA = NULL;
|
|
CERT_NAME_VALUE *pNameValueW = NULL;
|
|
|
|
if (!myDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_ANY_STRING,
|
|
(BYTE *) strName,
|
|
SysStringByteLen(strName),
|
|
CERTLIB_USE_LOCALALLOC,
|
|
(VOID **) &pNameValueA,
|
|
&cb))
|
|
{
|
|
hr = myHLastError();
|
|
_PrintError(hr, "myDecodeObject");
|
|
CSASSERT(NULL == pNameValueA);
|
|
}
|
|
|
|
if (!myDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_UNICODE_ANY_STRING,
|
|
(BYTE *) strName,
|
|
SysStringByteLen(strName),
|
|
CERTLIB_USE_LOCALALLOC,
|
|
(VOID **) &pNameValueW,
|
|
&cb))
|
|
{
|
|
hr = myHLastError();
|
|
_PrintError(hr, "myDecodeObject");
|
|
CSASSERT(NULL == pNameValueW);
|
|
}
|
|
|
|
if (NULL != pNameValueA && NULL != pNameValueW)
|
|
{
|
|
wprintf(wszNewLine);
|
|
wprintf(L"%ws ", pwszPad);
|
|
hr = cuDisplayCertNameValue(
|
|
NULL,
|
|
NULL, // wszAltNameChoice(Choice),
|
|
pNameValueW->dwValueType,
|
|
&pNameValueW->Value,
|
|
&pNameValueA->Value);
|
|
_PrintIfError(hr, "cuDisplayCertNameValue");
|
|
wprintf(wszNewLine);
|
|
}
|
|
if (NULL != pNameValueA)
|
|
{
|
|
LocalFree(pNameValueA);
|
|
}
|
|
if (NULL != pNameValueW)
|
|
{
|
|
LocalFree(pNameValueW);
|
|
}
|
|
}
|
|
else
|
|
if (0 == lstrcmp(TEXT(szOID_NTDS_REPLICATION), strObjId) ||
|
|
BER_OCTET_STRING == *(BYTE const *) strName)
|
|
{
|
|
fHex = TRUE;
|
|
if (myDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_OCTET_STRING,
|
|
(BYTE const *) strName,
|
|
SysStringByteLen(strName),
|
|
CERTLIB_USE_LOCALALLOC,
|
|
(VOID **) &pBlob,
|
|
&cb))
|
|
{
|
|
if (0 == lstrcmp(TEXT(szOID_NTDS_REPLICATION), strObjId) &&
|
|
pBlob->cbData == sizeof(GUID))
|
|
{
|
|
WCHAR *pwsz;
|
|
|
|
hr = myCLSIDToWsz((CLSID const *) pBlob->pbData, &pwsz);
|
|
if (S_OK == hr)
|
|
{
|
|
wprintf(L"\n%ws %ws\n", pwszPad, pwsz);
|
|
LocalFree(pwsz);
|
|
fHex = FALSE;
|
|
}
|
|
}
|
|
if (fHex)
|
|
{
|
|
wprintf(wszNewLine);
|
|
DumpHex(
|
|
DH_NOTABPREFIX | 8,
|
|
pBlob->pbData,
|
|
pBlob->cbData);
|
|
wprintf(wszNewLine);
|
|
fHex = FALSE;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fHex = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
wprintf(L" \"%ws\"\n", strName);
|
|
}
|
|
if (fNameBlob)
|
|
{
|
|
CERT_NAME_BLOB Name;
|
|
|
|
Name.pbData = (BYTE *) strName;
|
|
Name.cbData = SysStringByteLen(strName);
|
|
|
|
hr = cuDisplayCertName(
|
|
TRUE,
|
|
NULL,
|
|
NULL, // wszAltNameChoice(Choice)
|
|
g_wszPad8,
|
|
&Name,
|
|
NULL);
|
|
_PrintIfError(hr, "cuDisplayCertName(DirectoryName)");
|
|
if (S_OK != hr)
|
|
{
|
|
fHex = TRUE;
|
|
}
|
|
}
|
|
if (fHex)
|
|
{
|
|
wprintf(wszNewLine);
|
|
DumpHex(
|
|
DH_NOTABPREFIX | 8,
|
|
(BYTE *) strName,
|
|
SysStringByteLen(strName));
|
|
wprintf(wszNewLine);
|
|
}
|
|
}
|
|
|
|
error:
|
|
if (NULL != pBlob)
|
|
{
|
|
LocalFree(pBlob);
|
|
}
|
|
if (NULL != strObjId)
|
|
{
|
|
SysFreeString(strObjId);
|
|
}
|
|
if (NULL != strName)
|
|
{
|
|
SysFreeString(strName);
|
|
}
|
|
if (NULL != strExtension)
|
|
{
|
|
SysFreeString(strExtension);
|
|
}
|
|
if (NULL != pAltName)
|
|
{
|
|
pAltName->Release();
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
DumpGeneralSubTree(
|
|
IN UINT idsMsg,
|
|
IN DWORD cSubtree,
|
|
IN CERT_GENERAL_SUBTREE const *rgSubtree)
|
|
{
|
|
HRESULT hr;
|
|
HRESULT hr2;
|
|
DWORD i;
|
|
CERT_ALT_NAME_INFO cani;
|
|
BYTE *pb = NULL;
|
|
DWORD cb;
|
|
|
|
wprintf(L" %ws:\n", myLoadResourceString(idsMsg));
|
|
hr = S_OK;
|
|
for (i = 0; i < cSubtree; i++)
|
|
{
|
|
wprintf(
|
|
L" %ws[%u]: " wszLPAREN L"%u...",
|
|
myLoadResourceString(IDS_SUBTREE),
|
|
i,
|
|
rgSubtree[i].dwMinimum);
|
|
wprintf(
|
|
rgSubtree[i].fMaximum? L"%u" : L"Max",
|
|
rgSubtree[i].dwMaximum);
|
|
wprintf(wszRPAREN L"\n");
|
|
|
|
cani.cAltEntry = 1;
|
|
cani.rgAltEntry = const_cast<CERT_ALT_NAME_ENTRY *>(&rgSubtree[i].Base);
|
|
|
|
if (!myEncodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_ALTERNATE_NAME,
|
|
&cani,
|
|
0,
|
|
CERTLIB_USE_LOCALALLOC,
|
|
&pb, // pbEncoded
|
|
&cb))
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, error, "myEncodeObject");
|
|
}
|
|
hr2 = DumpAltName(g_wszPad6, i, pb, cb);
|
|
_PrintIfError(hr2, "DumpAltName");
|
|
if (S_OK == hr)
|
|
{
|
|
hr = hr2;
|
|
}
|
|
LocalFree(pb);
|
|
pb = NULL;
|
|
}
|
|
_JumpIfError(hr, error, "DumpAltName");
|
|
|
|
error:
|
|
if (NULL != pb)
|
|
{
|
|
LocalFree(pb);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
DumpNameConstraints(
|
|
IN BYTE const *pbExtension,
|
|
IN DWORD cbExtension)
|
|
{
|
|
HRESULT hr;
|
|
HRESULT hr2;
|
|
CERT_NAME_CONSTRAINTS_INFO *pnci = NULL;
|
|
DWORD cb;
|
|
|
|
if (!myDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_NAME_CONSTRAINTS,
|
|
pbExtension,
|
|
cbExtension,
|
|
CERTLIB_USE_LOCALALLOC,
|
|
(VOID **) &pnci,
|
|
&cb))
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, error, "myDecodeObject");
|
|
}
|
|
hr = DumpGeneralSubTree(
|
|
IDS_PERMITTED,
|
|
pnci->cPermittedSubtree,
|
|
pnci->rgPermittedSubtree);
|
|
_PrintIfError(hr, "DumpGeneralSubTree");
|
|
|
|
hr2 = DumpGeneralSubTree(
|
|
IDS_EXCLUDED,
|
|
pnci->cExcludedSubtree,
|
|
pnci->rgExcludedSubtree);
|
|
_PrintIfError(hr2, "DumpGeneralSubTree");
|
|
if (S_OK == hr)
|
|
{
|
|
hr = hr2;
|
|
}
|
|
_JumpIfError(hr, error, "DumpGeneralSubTree");
|
|
|
|
error:
|
|
if (NULL != pnci)
|
|
{
|
|
LocalFree(pnci);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
DumpOctetHash(
|
|
IN WCHAR const *pwszPad,
|
|
IN UINT idsDescription,
|
|
OPTIONAL IN WCHAR const *pwszCertutil,
|
|
IN BYTE const *pbIn,
|
|
IN DWORD cbIn,
|
|
OPTIONAL OUT BYTE *pbOut,
|
|
OPTIONAL IN OUT DWORD *pcbOut)
|
|
{
|
|
HRESULT hr;
|
|
CRYPT_DATA_BLOB aBlob[1 + BLOB_ROUND(CBMAX_CRYPT_HASH_LEN)];
|
|
DWORD cb;
|
|
BSTR strHash = NULL;
|
|
|
|
cb = sizeof(aBlob);
|
|
if (CryptDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_OCTET_STRING,
|
|
pbIn,
|
|
cbIn,
|
|
0,
|
|
aBlob,
|
|
&cb))
|
|
{
|
|
if (NULL == pbOut)
|
|
{
|
|
wprintf(
|
|
L"%ws%ws%ws:\n",
|
|
pwszPad,
|
|
0 != idsDescription?
|
|
myLoadResourceString(idsDescription) : g_wszEmpty,
|
|
NULL != pwszCertutil? pwszCertutil : g_wszEmpty);
|
|
|
|
hr = MultiByteIntegerToBstr(
|
|
TRUE,
|
|
aBlob[0].cbData,
|
|
aBlob[0].pbData,
|
|
&strHash);
|
|
_JumpIfError(hr, error, "MultiByteIntegerToBstr");
|
|
|
|
wprintf(L" %ws\n", strHash);
|
|
}
|
|
else
|
|
{
|
|
if (NULL == pcbOut)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
_JumpError(hr, error, "NULL parm");
|
|
}
|
|
cb = *pcbOut;
|
|
*pcbOut = aBlob[0].cbData;
|
|
CopyMemory(pbOut, aBlob[0].pbData, min(cb, aBlob[0].cbData));
|
|
|
|
if (cb < aBlob[0].cbData)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
|
|
_JumpError(hr, error, "buffer too small");
|
|
}
|
|
}
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
if (NULL != strHash)
|
|
{
|
|
SysFreeString(strHash);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
DumpHash(
|
|
OPTIONAL IN WCHAR const *pwszPrefix,
|
|
OPTIONAL IN DWORD idMessage,
|
|
OPTIONAL IN WCHAR const *pwszHashNamePrefix,
|
|
IN WCHAR const *pwszHashName,
|
|
IN BYTE const *pbHash,
|
|
IN DWORD cbHash)
|
|
{
|
|
HRESULT hr;
|
|
BSTR strHash = NULL;
|
|
WCHAR *pwsz = NULL;
|
|
|
|
|
|
if (NULL != pbHash)
|
|
{
|
|
hr = MultiByteIntegerToBstr(TRUE, cbHash, pbHash, &strHash);
|
|
_JumpIfError(hr, error, "MultiByteIntegerToBstr");
|
|
|
|
if (NULL != pwszPrefix)
|
|
{
|
|
wprintf(pwszPrefix);
|
|
}
|
|
if (0 != idMessage)
|
|
{
|
|
if (NULL != pwszHashNamePrefix)
|
|
{
|
|
DWORD cwc;
|
|
|
|
cwc = wcslen(pwszHashNamePrefix) + 1 + wcslen(pwszHashName);
|
|
pwsz = (WCHAR *) LocalAlloc(
|
|
LMEM_FIXED,
|
|
(cwc + 1) * sizeof(WCHAR));
|
|
if (NULL == pwsz)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "LocalAlloc");
|
|
}
|
|
wcscpy(pwsz, pwszHashNamePrefix);
|
|
wcscat(pwsz, L" ");
|
|
wcscat(pwsz, pwszHashName);
|
|
CSASSERT(wcslen(pwsz) == cwc);
|
|
pwszHashName = pwsz;
|
|
}
|
|
wprintf(myLoadResourceString(idMessage), pwszHashName, strHash);
|
|
}
|
|
else
|
|
{
|
|
wprintf(strHash);
|
|
}
|
|
wprintf(wszNewLine);
|
|
|
|
if (1 < g_fVerbose)
|
|
{
|
|
DumpHex(DH_NOTABPREFIX | 4, pbHash, cbHash);
|
|
wprintf(wszNewLine);
|
|
}
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
if (NULL != pwsz)
|
|
{
|
|
LocalFree(pwsz);
|
|
}
|
|
if (NULL != strHash)
|
|
{
|
|
SysFreeString(strHash);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
#define FOT_EXTENSION 0
|
|
#define FOT_ATTRIBUTE 1
|
|
#define FOT_PROPERTY 2
|
|
|
|
|
|
BOOL
|
|
DumpFormattedObject(
|
|
IN char const *pszObjId,
|
|
IN DWORD Type, // FOT_*
|
|
IN BYTE const *pbObject,
|
|
IN DWORD cbObject)
|
|
{
|
|
HRESULT hr;
|
|
BOOL fDisplayed = FALSE;
|
|
WCHAR *pwszFormatted = NULL;
|
|
DWORD cbFormatted;
|
|
CRYPT_DATA_BLOB *pBlobProp = NULL;
|
|
DWORD cbBlobProp;
|
|
WCHAR const *pwszPrefix0 = g_wszPad4;
|
|
WCHAR const *pwszPrefix1 = g_wszPad8;
|
|
WCHAR const *pwszDescriptiveName;
|
|
|
|
// format the object using the installed formatting function
|
|
|
|
hr = S_OK;
|
|
if (!CryptFormatObject(
|
|
X509_ASN_ENCODING,
|
|
0,
|
|
CRYPT_FORMAT_STR_MULTI_LINE | CRYPT_FORMAT_STR_NO_HEX,
|
|
NULL,
|
|
pszObjId,
|
|
pbObject,
|
|
cbObject,
|
|
NULL,
|
|
&cbFormatted))
|
|
{
|
|
hr = myHLastError();
|
|
_PrintErrorStr2(hr, pszObjId, L"CryptFormatObject", hr);
|
|
if (S_OK == hr)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
|
|
}
|
|
}
|
|
|
|
if (S_OK != hr)
|
|
{
|
|
if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr &&
|
|
CRYPT_E_ASN1_BADTAG != hr &&
|
|
CRYPT_E_ASN1_CORRUPT != hr)
|
|
{
|
|
_JumpError(hr, error, "CryptFormatObject");
|
|
}
|
|
if (FOT_PROPERTY == Type)
|
|
{
|
|
if (!myDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_OCTET_STRING,
|
|
pbObject,
|
|
cbObject,
|
|
CERTLIB_USE_LOCALALLOC,
|
|
(VOID **) &pBlobProp,
|
|
&cbBlobProp))
|
|
{
|
|
hr = myHLastError();
|
|
_PrintError(hr, "myDecodeObject");
|
|
}
|
|
else
|
|
{
|
|
hr = cuDumpFormattedProperty(
|
|
MAXDWORD,
|
|
pszObjId,
|
|
pBlobProp->pbData,
|
|
pBlobProp->cbData);
|
|
_PrintIfError(hr, "cuDumpFormattedProperty");
|
|
if (S_OK == hr)
|
|
{
|
|
fDisplayed = TRUE;
|
|
}
|
|
}
|
|
}
|
|
if (S_OK != hr && !g_fQuiet)
|
|
{
|
|
PrintStringWithPrefix(
|
|
pwszPrefix0,
|
|
myLoadResourceString(FOT_ATTRIBUTE == Type?
|
|
IDS_UNKNOWN_ATTRIBUTE : // "Unknown Attribute type"
|
|
(FOT_EXTENSION == Type?
|
|
IDS_UNKNOWN_EXTENSION : // "Unknown Extension type"
|
|
IDS_UNKNOWN_PROPERTY))); // "Unknown Property"
|
|
wprintf(wszNewLine);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pwszFormatted = (WCHAR *) LocalAlloc(LMEM_FIXED, cbFormatted);
|
|
if (NULL == pwszFormatted)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "LocalAlloc");
|
|
}
|
|
|
|
if (!CryptFormatObject(
|
|
X509_ASN_ENCODING,
|
|
0,
|
|
CRYPT_FORMAT_STR_MULTI_LINE | CRYPT_FORMAT_STR_NO_HEX,
|
|
NULL,
|
|
pszObjId,
|
|
pbObject,
|
|
cbObject,
|
|
pwszFormatted,
|
|
&cbFormatted))
|
|
{
|
|
hr = myHLastError();
|
|
_JumpErrorStr(hr, error, pszObjId, L"CryptFormatObject");
|
|
}
|
|
PrintStringWithPrefix(g_fQuiet? g_wszEmpty : pwszPrefix1, pwszFormatted);
|
|
fDisplayed = TRUE;
|
|
}
|
|
|
|
if (g_fVerbose)
|
|
{
|
|
if (0 == strcmp(szOID_SUBJECT_ALT_NAME, pszObjId) ||
|
|
0 == strcmp(szOID_SUBJECT_ALT_NAME2, pszObjId) ||
|
|
0 == strcmp(szOID_ISSUER_ALT_NAME, pszObjId) ||
|
|
0 == strcmp(szOID_ISSUER_ALT_NAME2, pszObjId))
|
|
{
|
|
DumpAltName(g_wszPad4, MAXDWORD, pbObject, cbObject);
|
|
}
|
|
else
|
|
if (0 == strcmp(szOID_NAME_CONSTRAINTS, pszObjId))
|
|
{
|
|
DumpNameConstraints(pbObject, cbObject);
|
|
}
|
|
}
|
|
|
|
error:
|
|
if (NULL != pBlobProp)
|
|
{
|
|
LocalFree(pBlobProp);
|
|
}
|
|
if (NULL != pwszFormatted)
|
|
{
|
|
LocalFree(pwszFormatted);
|
|
}
|
|
return(fDisplayed);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
cuDumpUsage(
|
|
OPTIONAL IN WCHAR const *pwszPrefix,
|
|
IN DWORD idMessage,
|
|
IN CTL_USAGE const *pUsage)
|
|
{
|
|
HRESULT hr;
|
|
DWORD i;
|
|
|
|
if (NULL == pwszPrefix)
|
|
{
|
|
pwszPrefix = L"";
|
|
}
|
|
wprintf(L"%ws", pwszPrefix);
|
|
wprintf(myLoadResourceString(idMessage));
|
|
wprintf(L" %u\n", pUsage->cUsageIdentifier);
|
|
for (i = 0; i < pUsage->cUsageIdentifier; i++)
|
|
{
|
|
wprintf(
|
|
L"%ws%ws[%d] ",
|
|
pwszPrefix,
|
|
g_wszPad2,
|
|
i);
|
|
cuDumpOIDAndDescriptionA(pUsage->rgpszUsageIdentifier[i]);
|
|
wprintf(wszNewLine);
|
|
}
|
|
hr = S_OK;
|
|
|
|
//error:
|
|
return(hr);
|
|
}
|
|
|
|
#ifndef XENROLL_PASS_THRU_PROP_ID
|
|
#define XENROLL_PASS_THRU_PROP_ID (CERT_FIRST_USER_PROP_ID + 0x100)
|
|
#endif
|
|
|
|
#ifndef XENROLL_RENEWAL_CERTIFICATE_PROP_ID
|
|
#define XENROLL_RENEWAL_CERTIFICATE_PROP_ID (CERT_FIRST_USER_PROP_ID + 0x101)
|
|
#endif
|
|
|
|
|
|
typedef struct _DUMPPROP
|
|
{
|
|
DWORD dwPropId;
|
|
WCHAR const *pwszDescription;
|
|
} DUMPPROP;
|
|
|
|
#define _DFPROP(def) { (def), L#def }
|
|
|
|
DUMPPROP s_apwszPropIds[] = {
|
|
_DFPROP(CERT_KEY_PROV_HANDLE_PROP_ID),
|
|
_DFPROP(CERT_KEY_PROV_INFO_PROP_ID),
|
|
_DFPROP(CERT_SHA1_HASH_PROP_ID),
|
|
_DFPROP(CERT_MD5_HASH_PROP_ID),
|
|
_DFPROP(CERT_KEY_CONTEXT_PROP_ID),
|
|
_DFPROP(CERT_KEY_SPEC_PROP_ID),
|
|
_DFPROP(CERT_IE30_RESERVED_PROP_ID),
|
|
_DFPROP(CERT_PUBKEY_HASH_RESERVED_PROP_ID),
|
|
_DFPROP(CERT_ENHKEY_USAGE_PROP_ID),
|
|
_DFPROP(CERT_NEXT_UPDATE_LOCATION_PROP_ID),
|
|
_DFPROP(CERT_FRIENDLY_NAME_PROP_ID),
|
|
_DFPROP(CERT_PVK_FILE_PROP_ID),
|
|
_DFPROP(CERT_DESCRIPTION_PROP_ID),
|
|
_DFPROP(CERT_ACCESS_STATE_PROP_ID),
|
|
_DFPROP(CERT_SIGNATURE_HASH_PROP_ID),
|
|
_DFPROP(CERT_SMART_CARD_DATA_PROP_ID),
|
|
_DFPROP(CERT_EFS_PROP_ID),
|
|
_DFPROP(CERT_FORTEZZA_DATA_PROP_ID),
|
|
_DFPROP(CERT_ARCHIVED_PROP_ID),
|
|
_DFPROP(CERT_KEY_IDENTIFIER_PROP_ID),
|
|
_DFPROP(CERT_AUTO_ENROLL_PROP_ID),
|
|
_DFPROP(CERT_PUBKEY_ALG_PARA_PROP_ID),
|
|
_DFPROP(CERT_CROSS_CERT_DIST_POINTS_PROP_ID),
|
|
_DFPROP(CERT_ISSUER_PUBLIC_KEY_MD5_HASH_PROP_ID),
|
|
_DFPROP(CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID),
|
|
_DFPROP(CERT_ENROLLMENT_PROP_ID),
|
|
_DFPROP(CERT_DATE_STAMP_PROP_ID),
|
|
_DFPROP(CERT_ISSUER_SERIAL_NUMBER_MD5_HASH_PROP_ID),
|
|
_DFPROP(CERT_SUBJECT_NAME_MD5_HASH_PROP_ID),
|
|
_DFPROP(CERT_EXTENDED_ERROR_INFO_PROP_ID),
|
|
_DFPROP(XENROLL_PASS_THRU_PROP_ID),
|
|
_DFPROP(XENROLL_RENEWAL_CERTIFICATE_PROP_ID),
|
|
};
|
|
|
|
|
|
HRESULT
|
|
cuDecodeBool(
|
|
IN BYTE const *pbIn,
|
|
IN DWORD cbIn,
|
|
OUT BOOL *pfWriteToDS)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = E_INVALIDARG;
|
|
if (3 == cbIn && BER_BOOL == pbIn[0] && 1 == pbIn[1])
|
|
{
|
|
*pfWriteToDS = FALSE;
|
|
if (0 != pbIn[2])
|
|
{
|
|
if (0xff != pbIn[2])
|
|
{
|
|
_PrintError(hr, "BER_BOOL");
|
|
}
|
|
*pfWriteToDS = TRUE;
|
|
}
|
|
hr = S_OK;
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
DecodeRequestFlags(
|
|
IN BYTE const *pbIn,
|
|
IN DWORD cbIn,
|
|
OUT BOOL *pfWriteToCSP,
|
|
OUT BOOL *pfWriteToDS,
|
|
OUT DWORD *popenFlags)
|
|
{
|
|
HRESULT hr;
|
|
CRYPT_SEQUENCE_OF_ANY *pSeq = NULL;
|
|
DWORD cb;
|
|
|
|
hr = cuDecodeSequence(pbIn, cbIn, 3, &pSeq);
|
|
_JumpIfError(hr, error, "cuDecodeSequence");
|
|
|
|
hr = cuDecodeBool(
|
|
pSeq->rgValue[0].pbData,
|
|
pSeq->rgValue[0].cbData,
|
|
pfWriteToCSP);
|
|
_JumpIfError(hr, error, "cuDecodeBool");
|
|
|
|
hr = cuDecodeBool(
|
|
pSeq->rgValue[1].pbData,
|
|
pSeq->rgValue[1].cbData,
|
|
pfWriteToDS);
|
|
_JumpIfError(hr, error, "cuDecodeBool");
|
|
|
|
cb = sizeof(*popenFlags);
|
|
*popenFlags = 0;
|
|
if (!CryptDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_INTEGER,
|
|
pSeq->rgValue[2].pbData,
|
|
pSeq->rgValue[2].cbData,
|
|
0,
|
|
popenFlags,
|
|
&cb))
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, error, "CryptDecodeObject");
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
if (NULL != pSeq)
|
|
{
|
|
LocalFree(pSeq);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
cuDumpFormattedProperty(
|
|
IN DWORD dwPropId,
|
|
OPTIONAL IN char const *pszObjId,
|
|
IN BYTE const *pb,
|
|
IN DWORD cb)
|
|
{
|
|
HRESULT hr;
|
|
char szObjId[sizeof(szOID_CERT_PROP_ID_PREFIX) + 20];
|
|
WCHAR const *pwszDescriptiveName;
|
|
BOOL fDisplayed;
|
|
DWORD i;
|
|
|
|
CSASSERT(NULL == pszObjId || MAXDWORD == dwPropId);
|
|
|
|
hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
|
|
if (NULL != pszObjId)
|
|
{
|
|
char const *psz;
|
|
|
|
if (0 != strncmp(
|
|
szOID_CERT_PROP_ID_PREFIX,
|
|
pszObjId,
|
|
ARRAYSIZE(szOID_CERT_PROP_ID_PREFIX) - 1))
|
|
{
|
|
_JumpError(hr, error, "Not a property ObjId");
|
|
}
|
|
psz = &pszObjId[ARRAYSIZE(szOID_CERT_PROP_ID_PREFIX) - 1];
|
|
dwPropId = atol(psz);
|
|
while ('\0' != *psz)
|
|
{
|
|
if (!isdigit(*psz))
|
|
{
|
|
_JumpError(hr, error, "Bad property ObjId suffix");
|
|
}
|
|
psz++;
|
|
}
|
|
}
|
|
|
|
wprintf(wszNewLine);
|
|
for (i = 0; ; i++)
|
|
{
|
|
if (i >= ARRAYSIZE(s_apwszPropIds))
|
|
{
|
|
pwszDescriptiveName = myLoadResourceString(IDS_UNKNOWN_PROPERTY); // "Unknown Property"
|
|
break;
|
|
}
|
|
if (s_apwszPropIds[i].dwPropId == dwPropId)
|
|
{
|
|
pwszDescriptiveName = s_apwszPropIds[i].pwszDescription;
|
|
break;
|
|
}
|
|
}
|
|
wprintf(L" %ws", pwszDescriptiveName);
|
|
if (NULL != pszObjId)
|
|
{
|
|
wprintf(L"(%hs)", pszObjId);
|
|
}
|
|
else
|
|
{
|
|
wprintf(L"(%u)", dwPropId);
|
|
}
|
|
|
|
sprintf(szObjId, "%hs%u", szOID_CERT_PROP_ID_PREFIX, dwPropId);
|
|
pwszDescriptiveName = cuGetOIDNameA(szObjId);
|
|
if (NULL != pwszDescriptiveName && L'\0' != *pwszDescriptiveName)
|
|
{
|
|
wprintf(L" %ws", pwszDescriptiveName);
|
|
}
|
|
wprintf(L":\n");
|
|
#if 0
|
|
fDisplayed = DumpFormattedObject(szObjId, FOT_PROPERTY, pb, cb);
|
|
#else
|
|
fDisplayed = FALSE;
|
|
#endif
|
|
|
|
if (!fDisplayed)
|
|
{
|
|
if (IS_CERT_HASH_PROP_ID(dwPropId) ||
|
|
IS_PUBKEY_HASH_PROP_ID(dwPropId) ||
|
|
IS_CHAIN_HASH_PROP_ID(dwPropId) ||
|
|
CERT_KEY_IDENTIFIER_PROP_ID == dwPropId)
|
|
{
|
|
wprintf(g_wszPad4);
|
|
|
|
hr = DumpHash(NULL, 0, NULL, g_wszEmpty, pb, cb);
|
|
_JumpIfError(hr, error, "DumpHash");
|
|
|
|
fDisplayed = TRUE;
|
|
}
|
|
else
|
|
if (CERT_FRIENDLY_NAME_PROP_ID == dwPropId ||
|
|
CERT_DESCRIPTION_PROP_ID == dwPropId)
|
|
{
|
|
wprintf(L"%ws%ws\n", g_wszPad4, pb);
|
|
fDisplayed = TRUE;
|
|
}
|
|
else
|
|
if (CERT_KEY_PROV_INFO_PROP_ID == dwPropId)
|
|
{
|
|
hr = cuDumpCertKeyProviderInfo(
|
|
g_wszPad4,
|
|
NULL,
|
|
(CRYPT_KEY_PROV_INFO *) pb,
|
|
NULL);
|
|
_JumpIfError(hr, error, "cuDumpCertKeyProviderInfo");
|
|
|
|
fDisplayed = TRUE;
|
|
}
|
|
else
|
|
if (CERT_AUTO_ENROLL_PROP_ID == dwPropId)
|
|
{
|
|
wprintf(
|
|
L"%ws%ws = %.*ws\n",
|
|
g_wszPad4,
|
|
myLoadResourceString(IDS_PROP_AUTOENROLL), // "AutoEnroll Property"
|
|
cb / sizeof(WCHAR),
|
|
pb);
|
|
fDisplayed = TRUE;
|
|
}
|
|
else
|
|
if (CERT_ENROLLMENT_PROP_ID == dwPropId)
|
|
{
|
|
BYTE const *pbTmp = pb;
|
|
DWORD cbTmp = cb;
|
|
DWORD cwc;
|
|
|
|
if (sizeof(LONG) <= cbTmp)
|
|
{
|
|
// RequestId:
|
|
|
|
wprintf(
|
|
L"%ws%ws = %u\n",
|
|
g_wszPad4,
|
|
myLoadResourceString(IDS_REQUESTID), // "RequestId"
|
|
*(LONG *) pbTmp);
|
|
pbTmp += sizeof(LONG);
|
|
cbTmp -= sizeof(LONG);
|
|
|
|
if (sizeof(cwc) <= cbTmp)
|
|
{
|
|
// CA DNS name:
|
|
|
|
cwc = *(DWORD *) pbTmp;
|
|
pbTmp += sizeof(cwc); // skip count of next field
|
|
cbTmp -= sizeof(cwc);
|
|
|
|
wprintf(
|
|
L"%ws%ws = %.*ws\\",
|
|
g_wszPad4,
|
|
myLoadResourceString(IDS_CADNSNAME), // "Authority"
|
|
min(cwc, cbTmp / sizeof(WCHAR)),
|
|
pbTmp);
|
|
pbTmp += cwc * sizeof(WCHAR);
|
|
cbTmp -= cwc * sizeof(WCHAR);
|
|
|
|
if (sizeof(cwc) <= cbTmp)
|
|
{
|
|
// CA name:
|
|
|
|
cwc = *(DWORD UNALIGNED *) pbTmp;
|
|
pbTmp += sizeof(cwc); // skip count of next field
|
|
cbTmp -= sizeof(cwc);
|
|
|
|
wprintf(
|
|
L"%.*ws\n",
|
|
min(cwc, cbTmp / sizeof(WCHAR)),
|
|
pbTmp);
|
|
pbTmp += cwc * sizeof(WCHAR);
|
|
cbTmp -= cwc * sizeof(WCHAR);
|
|
|
|
if (sizeof(cwc) <= cbTmp)
|
|
{
|
|
// friendly name:
|
|
|
|
cwc = *(DWORD UNALIGNED *) pbTmp;
|
|
pbTmp += sizeof(cwc); // skip count of next field
|
|
cbTmp -= sizeof(cwc);
|
|
|
|
wprintf(
|
|
L"%ws%ws = %.*ws\n",
|
|
g_wszPad4,
|
|
myLoadResourceString(IDS_FRIENDLYNAME), // "Friendly Name"
|
|
min(cwc, cbTmp / sizeof(WCHAR)),
|
|
pbTmp);
|
|
pbTmp += cwc * sizeof(WCHAR);
|
|
cbTmp -= cwc * sizeof(WCHAR);
|
|
|
|
fDisplayed = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
else
|
|
if (CERT_CTL_USAGE_PROP_ID == dwPropId)
|
|
{
|
|
CTL_USAGE *pUsage;
|
|
|
|
if (!myDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_ENHANCED_KEY_USAGE,
|
|
pb,
|
|
cb,
|
|
CERTLIB_USE_LOCALALLOC,
|
|
(VOID **) &pUsage,
|
|
&cb))
|
|
{
|
|
hr = myHLastError();
|
|
_PrintError(hr, "myDecodeObject");
|
|
}
|
|
else
|
|
{
|
|
hr = cuDumpUsage(g_wszPad2, IDS_USAGEENTRIES, pUsage);
|
|
_JumpIfError(hr, error, "cuDumpUsage");
|
|
|
|
fDisplayed = TRUE;
|
|
}
|
|
}
|
|
else
|
|
if (CERT_PUBKEY_ALG_PARA_PROP_ID == dwPropId)
|
|
{
|
|
CERT_DSS_PARAMETERS *pDssParms;
|
|
|
|
if (!myDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_DSS_PARAMETERS,
|
|
pb,
|
|
cb,
|
|
CERTLIB_USE_LOCALALLOC,
|
|
(VOID **) &pDssParms,
|
|
&cb))
|
|
{
|
|
hr = myHLastError();
|
|
_PrintError(hr, "myDecodeObject");
|
|
}
|
|
else
|
|
{
|
|
|
|
wprintf(
|
|
myLoadResourceString(IDS_FORMAT_DSSKEY_LENGTH), // "DSS Key Length: %u bits"
|
|
pDssParms->p.cbData * 8);
|
|
|
|
wprintf(L" DSS P:\n");
|
|
DumpHex(
|
|
DH_NOADDRESS | DH_NOTABPREFIX | 4,
|
|
pDssParms->p.pbData,
|
|
pDssParms->p.cbData);
|
|
|
|
wprintf(L" DSS Q:\n");
|
|
DumpHex(
|
|
DH_NOADDRESS | DH_NOTABPREFIX | 4,
|
|
pDssParms->q.pbData,
|
|
pDssParms->q.cbData);
|
|
|
|
wprintf(L" DSS G:\n");
|
|
DumpHex(
|
|
DH_NOADDRESS | DH_NOTABPREFIX | 4,
|
|
pDssParms->g.pbData,
|
|
pDssParms->g.cbData);
|
|
|
|
LocalFree(pDssParms);
|
|
fDisplayed = TRUE;
|
|
}
|
|
}
|
|
else
|
|
if (XENROLL_PASS_THRU_PROP_ID == dwPropId)
|
|
{
|
|
BOOL fWriteToCSP;
|
|
BOOL fWriteToDS;
|
|
DWORD openFlags;
|
|
hr = DecodeRequestFlags(
|
|
pb,
|
|
cb,
|
|
&fWriteToCSP,
|
|
&fWriteToDS,
|
|
&openFlags);
|
|
_PrintIfError(hr, "DecodeRequestFlags");
|
|
if (S_OK == hr)
|
|
{
|
|
wprintf(L" fWriteToCSP: %u\n", fWriteToCSP);
|
|
wprintf(L" fWriteToDS: %u\n", fWriteToDS);
|
|
wprintf(L" openFlags: 0x%x\n", openFlags);
|
|
fDisplayed = TRUE;
|
|
}
|
|
}
|
|
else
|
|
if (XENROLL_RENEWAL_CERTIFICATE_PROP_ID == dwPropId)
|
|
{
|
|
wprintf(myLoadResourceString(IDS_RENEWAL_CERT)); // "Renewal Certificate:"
|
|
wprintf(wszNewLine);
|
|
|
|
hr = cuDumpAsnBinary(pb, cb, MAXDWORD);
|
|
_JumpIfError(hr, error, "cuDumpAsnBinary");
|
|
}
|
|
}
|
|
if (!fDisplayed || g_fVerbose)
|
|
{
|
|
DumpHex(DH_NOADDRESS | DH_NOTABPREFIX | 4, pb, cb);
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// cuDecodeObjId -- decode an ASN.1 encoded ObjectId
|
|
//
|
|
// Construct an ASN.1 encoded PKCS_ATTRIBUTE with an array of empty values,
|
|
// to trick CryptDecodeObject into decoding the passed in encoded Object Id.
|
|
//--------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
cuDecodeObjId(
|
|
IN BYTE const *pbData,
|
|
IN DWORD cbData,
|
|
OUT char **ppszObjId)
|
|
{
|
|
HRESULT hr;
|
|
CRYPT_ATTRIBUTE *pAttr = NULL;
|
|
BYTE *pbAlloc = NULL;
|
|
DWORD cbAlloc;
|
|
BYTE *pb;
|
|
DWORD cb;
|
|
|
|
//DumpHex(DH_NOTABPREFIX | 2, pbData, cbData);
|
|
cbAlloc = 2 + cbData + 2;
|
|
pbAlloc = (BYTE *) LocalAlloc(LMEM_FIXED, cbAlloc);
|
|
if (NULL == pbAlloc)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "LocalAlloc");
|
|
}
|
|
pb = pbAlloc;
|
|
*pb++ = BER_SEQUENCE; // PKCS_ATTRIBUTE sequence
|
|
CSASSERT(0x7f >= cbData + 2);
|
|
*pb++ = (BYTE ) (cbData + 2); // overall length
|
|
CopyMemory(pb, pbData, cbData); // copy encoded Object Id
|
|
pb += cbData;
|
|
*pb++ = BER_SET; // empty array of attribute values
|
|
*pb = 0; // zero length array of values
|
|
|
|
//DumpHex(DH_NOTABPREFIX | 2, pbAlloc, cbAlloc);
|
|
|
|
if (!myDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
PKCS_ATTRIBUTE,
|
|
pbAlloc,
|
|
cbAlloc,
|
|
CERTLIB_USE_LOCALALLOC,
|
|
(VOID **) &pAttr,
|
|
&cb))
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, error, "myDecodeObject");
|
|
}
|
|
hr = myDupStringA(pAttr->pszObjId, ppszObjId);
|
|
_JumpIfError(hr, error, "myDupStringA");
|
|
|
|
error:
|
|
if (NULL != pbAlloc)
|
|
{
|
|
LocalFree(pbAlloc);
|
|
}
|
|
if (NULL != pAttr)
|
|
{
|
|
LocalFree(pAttr);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// cuEncodeObjId -- decode an ASN.1 encoded ObjectId
|
|
//
|
|
// Construct an ASN.1 encoded PKCS_ATTRIBUTE with an array of empty values,
|
|
// to trick CryptEncodeObject into decoding the passed in encoded Object Id.
|
|
//--------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
cuEncodeObjId(
|
|
IN char const *pszObjId,
|
|
OUT BYTE **ppbData,
|
|
OUT DWORD *pcbData)
|
|
{
|
|
HRESULT hr;
|
|
CRYPT_ATTRIBUTE Attr;
|
|
BYTE *pbAttr = NULL;
|
|
DWORD cbAttr;
|
|
|
|
*ppbData = NULL;
|
|
|
|
ZeroMemory(&Attr, sizeof(Attr));
|
|
Attr.pszObjId = const_cast<char *>(pszObjId);
|
|
|
|
if (!myEncodeObject(
|
|
X509_ASN_ENCODING,
|
|
PKCS_ATTRIBUTE,
|
|
&Attr,
|
|
0,
|
|
CERTLIB_USE_LOCALALLOC,
|
|
&pbAttr, // pbEncoded
|
|
&cbAttr))
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, error, "myEncodeObject");
|
|
}
|
|
if (cbAttr <= 2 + 2 + 2 ||
|
|
BER_SEQUENCE != pbAttr[0] ||
|
|
cbAttr != pbAttr[1] + 2 ||
|
|
BER_OBJECT_ID != pbAttr[2] ||
|
|
cbAttr != pbAttr[3] + 2 + 2 + 2 ||
|
|
BER_SET != pbAttr[cbAttr - 2] ||
|
|
0 != pbAttr[cbAttr - 1])
|
|
{
|
|
hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
|
|
_JumpError(hr, error, "bad Attr");
|
|
}
|
|
|
|
*pcbData = cbAttr - 4;
|
|
*ppbData = (BYTE *) LocalAlloc(LMEM_FIXED, *pcbData);
|
|
if (NULL == *ppbData)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "LocalAlloc");
|
|
}
|
|
CopyMemory(*ppbData, &pbAttr[2], *pcbData);
|
|
hr = S_OK;
|
|
|
|
error:
|
|
if (NULL != pbAttr)
|
|
{
|
|
LocalFree(pbAttr);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
// UnicodeDecode()
|
|
//
|
|
// This function is responsible for decoding unicode crypt data blobs from
|
|
// various certificate fields. The returned WCHAR * must be freed by LocalFree
|
|
//
|
|
// Params:
|
|
//
|
|
// pBlob - IN CRYPT_DATA_BLOB to be decoded, expected UNICODE
|
|
//
|
|
// Returns:
|
|
//
|
|
// WCHAR * to decoded string, to be freed using LocalFree
|
|
|
|
|
|
HRESULT
|
|
UnicodeDecode(
|
|
IN CRYPT_DATA_BLOB const *pBlob,
|
|
OUT WCHAR **ppwszOut)
|
|
{
|
|
HRESULT hr;
|
|
CERT_NAME_VALUE *pName = NULL;
|
|
DWORD cb;
|
|
|
|
*ppwszOut = NULL;
|
|
|
|
if (!myDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_UNICODE_ANY_STRING,
|
|
pBlob->pbData,
|
|
pBlob->cbData,
|
|
CERTLIB_USE_LOCALALLOC,
|
|
(VOID **) &pName,
|
|
&cb))
|
|
{
|
|
CSASSERT(NULL == pName);
|
|
hr = myHLastError();
|
|
_JumpError(hr, error, "myDecodeObject");
|
|
}
|
|
|
|
hr = myDupString((WCHAR const *) pName->Value.pbData, ppwszOut);
|
|
_JumpIfError(hr, error, "myDupString");
|
|
|
|
error:
|
|
if (NULL != pName)
|
|
{
|
|
LocalFree(pName);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
BOOL
|
|
cuDumpFormattedExtension(
|
|
IN WCHAR const *pwszName,
|
|
IN BYTE const *pbObject,
|
|
IN DWORD cbObject)
|
|
{
|
|
HRESULT hr;
|
|
BOOL fDisplayed = FALSE;
|
|
char *pszObjId = NULL;
|
|
BSTR strHash = NULL;
|
|
WCHAR const *pwszDescriptiveName;
|
|
DWORD cb;
|
|
WCHAR const *pwszPad = g_fQuiet? g_wszEmpty : g_wszPad4;
|
|
|
|
if (!ConvertWszToSz(&pszObjId, pwszName, -1))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "ConvertWszToSz");
|
|
}
|
|
pwszDescriptiveName = cuGetOIDName(pwszName);
|
|
if (NULL != pwszDescriptiveName && L'\0' != *pwszDescriptiveName)
|
|
{
|
|
PrintStringWithPrefix(pwszPad, pwszDescriptiveName);
|
|
if (g_fQuiet)
|
|
{
|
|
wprintf(L": ");
|
|
}
|
|
else
|
|
{
|
|
wprintf(wszNewLine);
|
|
}
|
|
}
|
|
if (0 == cbObject)
|
|
{
|
|
if (!g_fQuiet)
|
|
{
|
|
wprintf(
|
|
L"%ws%ws\n",
|
|
g_wszPad8,
|
|
myLoadResourceString(IDS_PROP_EMPTY)); // "EMPTY"
|
|
}
|
|
fDisplayed = TRUE;
|
|
}
|
|
else
|
|
{
|
|
fDisplayed = DumpFormattedObject(
|
|
pszObjId,
|
|
FOT_EXTENSION,
|
|
pbObject,
|
|
cbObject);
|
|
if (!fDisplayed)
|
|
{
|
|
if (0 == strcmp(pszObjId, szOID_CERTSRV_CA_VERSION))
|
|
{
|
|
DWORD NameId;
|
|
|
|
cb = sizeof(NameId);
|
|
NameId = 0;
|
|
if (CryptDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_INTEGER,
|
|
pbObject,
|
|
cbObject,
|
|
0,
|
|
&NameId,
|
|
&cb))
|
|
{
|
|
wprintf(
|
|
L"%ws%ws%ws: %u.%u\n",
|
|
pwszPad,
|
|
myLoadResourceString(IDS_CAVERSION),
|
|
g_wszCertUtil,
|
|
CANAMEIDTOICERT(NameId),
|
|
CANAMEIDTOIKEY(NameId));
|
|
fDisplayed = TRUE;
|
|
}
|
|
}
|
|
else
|
|
if (0 == strcmp(pszObjId, szOID_CERTSRV_CROSSCA_VERSION))
|
|
{
|
|
DWORD CrossCAVersion;
|
|
|
|
cb = sizeof(CrossCAVersion);
|
|
CrossCAVersion = 0;
|
|
if (CryptDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_INTEGER,
|
|
pbObject,
|
|
cbObject,
|
|
0,
|
|
&CrossCAVersion,
|
|
&cb))
|
|
{
|
|
wprintf(
|
|
L"%ws%ws%ws: (%u-%u)\n",
|
|
pwszPad,
|
|
myLoadResourceString(IDS_CAVERSION),
|
|
g_wszCertUtil,
|
|
CROSSCAVERSIONTOSOURCE(CrossCAVersion),
|
|
CROSSCAVERSIONTOTARGET(CrossCAVersion));
|
|
fDisplayed = TRUE;
|
|
}
|
|
}
|
|
else
|
|
if (0 == strcmp(pszObjId, szOID_CERTSRV_PREVIOUS_CERT_HASH))
|
|
{
|
|
hr = DumpOctetHash(
|
|
pwszPad,
|
|
IDS_PREVIOUS_CA_CERT_HASH,
|
|
g_wszCertUtil,
|
|
pbObject,
|
|
cbObject,
|
|
NULL,
|
|
NULL);
|
|
if (S_OK == hr)
|
|
{
|
|
fDisplayed = TRUE;
|
|
}
|
|
}
|
|
else
|
|
if (0 == strcmp(pszObjId, szOID_CRL_NUMBER))
|
|
{
|
|
DWORD CRLNumber;
|
|
|
|
cb = sizeof(CRLNumber);
|
|
CRLNumber = 0;
|
|
if (CryptDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_INTEGER,
|
|
pbObject,
|
|
cbObject,
|
|
0,
|
|
&CRLNumber,
|
|
&cb))
|
|
{
|
|
wprintf(
|
|
L"%ws%ws%ws: %u\n",
|
|
pwszPad,
|
|
myLoadResourceString(IDS_CRL_NUMBER),
|
|
g_wszCertUtil,
|
|
CRLNumber);
|
|
fDisplayed = TRUE;
|
|
}
|
|
}
|
|
else
|
|
if (0 == strcmp(pszObjId, szOID_DELTA_CRL_INDICATOR))
|
|
{
|
|
DWORD CRLNumber;
|
|
|
|
cb = sizeof(CRLNumber);
|
|
CRLNumber = 0;
|
|
if (CryptDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_INTEGER,
|
|
pbObject,
|
|
cbObject,
|
|
0,
|
|
&CRLNumber,
|
|
&cb))
|
|
{
|
|
wprintf(
|
|
L"%ws%ws%ws: %u\n",
|
|
pwszPad,
|
|
myLoadResourceString(IDS_MINIMUM_BASE_CRL_NUMBER),
|
|
g_wszCertUtil,
|
|
CRLNumber);
|
|
fDisplayed = TRUE;
|
|
}
|
|
}
|
|
else
|
|
if (0 == strcmp(pszObjId, szOID_CRL_VIRTUAL_BASE))
|
|
{
|
|
DWORD CRLNumber;
|
|
|
|
cb = sizeof(CRLNumber);
|
|
CRLNumber = 0;
|
|
if (CryptDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_INTEGER,
|
|
pbObject,
|
|
cbObject,
|
|
0,
|
|
&CRLNumber,
|
|
&cb))
|
|
{
|
|
wprintf(
|
|
L"%ws%ws%ws: %u\n",
|
|
pwszPad,
|
|
myLoadResourceString(IDS_VIRTUAL_BASE_CRL_NUMBER),
|
|
g_wszCertUtil,
|
|
CRLNumber);
|
|
fDisplayed = TRUE;
|
|
}
|
|
}
|
|
else
|
|
if (0 == strcmp(pszObjId, szOID_CRL_NEXT_PUBLISH) ||
|
|
0 == strcmp(pszObjId, szOID_RSA_signingTime))
|
|
{
|
|
FILETIME ft;
|
|
|
|
cb = sizeof(ft);
|
|
if (CryptDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_CHOICE_OF_TIME,
|
|
pbObject,
|
|
cbObject,
|
|
0,
|
|
&ft,
|
|
&cb))
|
|
{
|
|
wprintf(
|
|
L"%ws%ws%ws: ",
|
|
pwszPad,
|
|
myLoadResourceString(
|
|
0 == strcmp(pszObjId, szOID_CRL_NEXT_PUBLISH)?
|
|
IDS_CRL_NEXT_PUBLISH : IDS_SIGNING_TIME),
|
|
g_wszCertUtil);
|
|
hr = cuDumpFileTime(0, NULL, &ft);
|
|
_JumpIfError(hr, error, "cuDumpFileTime");
|
|
|
|
fDisplayed = TRUE;
|
|
}
|
|
}
|
|
else
|
|
if (0 == strcmp(pszObjId, szOID_FRESHEST_CRL))
|
|
{
|
|
wprintf(
|
|
L"%ws%ws%ws:\n",
|
|
pwszPad,
|
|
myLoadResourceString(IDS_FRESHEST_CRL_CDP),
|
|
g_wszCertUtil);
|
|
cuDumpFormattedExtension(
|
|
TEXT(szOID_CRL_DIST_POINTS),
|
|
pbObject,
|
|
cbObject);
|
|
fDisplayed = TRUE;
|
|
}
|
|
else
|
|
if (0 == strcmp(pszObjId, szOID_CRL_SELF_CDP))
|
|
{
|
|
wprintf(
|
|
L"%ws%ws%ws:\n",
|
|
pwszPad,
|
|
myLoadResourceString(IDS_CRL_SELF_CDP),
|
|
g_wszCertUtil);
|
|
cuDumpFormattedExtension(
|
|
TEXT(szOID_CRL_DIST_POINTS),
|
|
pbObject,
|
|
cbObject);
|
|
fDisplayed = TRUE;
|
|
}
|
|
else
|
|
if (0 == strcmp(pszObjId, szOID_PKIX ".2"))
|
|
{
|
|
// Exchange policy module intended to use szOID_PKIX_CA_ISSUERS,
|
|
// but the ".48.2" suffix was instead written as ".2".
|
|
//
|
|
// szOID_PKIX_CA_ISSUERS was wrong anyway -- it should have
|
|
// used szOID_AUTHORITY_INFO_ACCESS instead.
|
|
|
|
wprintf(
|
|
L"%ws%ws%ws:\n",
|
|
pwszPad,
|
|
myLoadResourceString(IDS_EXCHANGEAIA), // "Exchange Authority Information Access"
|
|
g_wszCertUtil);
|
|
cuDumpFormattedExtension(
|
|
TEXT(szOID_AUTHORITY_INFO_ACCESS),
|
|
pbObject,
|
|
cbObject);
|
|
fDisplayed = TRUE;
|
|
}
|
|
else
|
|
if (0 == strcmp(pszObjId, szOID_ISSUER_ALT_NAME))
|
|
{
|
|
// Exchange policy module overloaded this OID and stored the
|
|
// file version information for expolicy.dll and certsrv.exe.
|
|
|
|
typedef struct _CUVER {
|
|
USHORT usMajor;
|
|
USHORT usMinor;
|
|
USHORT usBuild;
|
|
USHORT usBuildMinor;
|
|
} CUVER;
|
|
|
|
CUVER const *pVer;
|
|
CRYPT_INTEGER_BLOB aBlob[1 + BLOB_ROUND(2 * sizeof(*pVer))];
|
|
|
|
cb = sizeof(aBlob);
|
|
if (CryptDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_MULTI_BYTE_INTEGER,
|
|
pbObject,
|
|
cbObject,
|
|
0,
|
|
aBlob,
|
|
&cb))
|
|
{
|
|
if (2 * sizeof(*pVer) == aBlob[0].cbData)
|
|
{
|
|
wprintf(
|
|
L"%ws%ws%ws:\n",
|
|
pwszPad,
|
|
myLoadResourceString(IDS_EXCHANGEVERSION), // "Exchange Version"
|
|
g_wszCertUtil);
|
|
|
|
pVer = (CUVER const *) aBlob[0].pbData;
|
|
wprintf(
|
|
L" expolicy.dll: %u.%u:%u.%u\n",
|
|
pVer->usMajor,
|
|
pVer->usMinor,
|
|
pVer->usBuild,
|
|
pVer->usBuildMinor);
|
|
|
|
pVer++;
|
|
wprintf(
|
|
L" certsrv.exe: %u.%u:%u.%u\n",
|
|
pVer->usMajor,
|
|
pVer->usMinor,
|
|
pVer->usBuild,
|
|
pVer->usBuildMinor);
|
|
fDisplayed = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, error, "CryptDecodeObject");
|
|
}
|
|
}
|
|
else
|
|
if (0 == strcmp(pszObjId, szOID_APPLICATION_CERT_POLICIES))
|
|
{
|
|
wprintf(
|
|
L"%ws%ws%ws:\n",
|
|
pwszPad,
|
|
myLoadResourceString(IDS_APPLICATION_CERT_POLICIES),
|
|
g_wszCertUtil);
|
|
cuDumpFormattedExtension(
|
|
TEXT(szOID_CERT_POLICIES),
|
|
pbObject,
|
|
cbObject);
|
|
fDisplayed = TRUE;
|
|
}
|
|
else
|
|
if (0 == strcmp(pszObjId, szOID_APPLICATION_POLICY_MAPPINGS))
|
|
{
|
|
wprintf(
|
|
L"%ws%ws%ws:\n",
|
|
pwszPad,
|
|
myLoadResourceString(IDS_APPLICATION_POLICY_MAPPINGS),
|
|
g_wszCertUtil);
|
|
cuDumpFormattedExtension(
|
|
TEXT(szOID_POLICY_MAPPINGS),
|
|
pbObject,
|
|
cbObject);
|
|
fDisplayed = TRUE;
|
|
}
|
|
else
|
|
if (0 == strcmp(pszObjId, szOID_APPLICATION_POLICY_CONSTRAINTS))
|
|
{
|
|
wprintf(
|
|
L"%ws%ws%ws:\n",
|
|
pwszPad,
|
|
myLoadResourceString(IDS_APPLICATION_POLICY_CONSTRAINTS),
|
|
g_wszCertUtil);
|
|
cuDumpFormattedExtension(
|
|
TEXT(szOID_POLICY_CONSTRAINTS),
|
|
pbObject,
|
|
cbObject);
|
|
fDisplayed = TRUE;
|
|
}
|
|
else
|
|
if (0 == strcmp(pszObjId, szOID_POLICY_MAPPINGS))
|
|
{
|
|
CERT_POLICY_MAPPINGS_INFO *pPolicyMappings = NULL;
|
|
DWORD i;
|
|
|
|
if (!myDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_POLICY_MAPPINGS,
|
|
pbObject,
|
|
cbObject,
|
|
CERTLIB_USE_LOCALALLOC,
|
|
(VOID **) &pPolicyMappings,
|
|
&cb))
|
|
{
|
|
hr = myHLastError();
|
|
CSASSERT(NULL == pPolicyMappings);
|
|
_JumpIfError(hr, error, "myDecodeObject");
|
|
}
|
|
|
|
wprintf(
|
|
L"%ws%ws%ws:\n",
|
|
pwszPad,
|
|
myLoadResourceString(IDS_POLICY_MAPPINGS),
|
|
g_wszCertUtil);
|
|
|
|
for (i = 0; i < pPolicyMappings->cPolicyMapping; i++)
|
|
{
|
|
wprintf(g_wszPad4);
|
|
wprintf(myLoadResourceString(IDS_FORMAT_MAP_ARRAY_COLON), i);
|
|
wprintf(wszNewLine);
|
|
|
|
wprintf(g_wszPad8);
|
|
wprintf(myLoadResourceString(IDS_ISSUER_DOMAIN_POLICY));
|
|
|
|
cuDumpOIDAndDescriptionA(
|
|
pPolicyMappings->rgPolicyMapping[i].pszIssuerDomainPolicy);
|
|
wprintf(wszNewLine);
|
|
|
|
wprintf(g_wszPad8);
|
|
wprintf(myLoadResourceString(IDS_SUBJECT_DOMAIN_POLICY));
|
|
|
|
cuDumpOIDAndDescriptionA(
|
|
pPolicyMappings->rgPolicyMapping[i].pszSubjectDomainPolicy);
|
|
wprintf(wszNewLine);
|
|
}
|
|
|
|
LocalFree(pPolicyMappings);
|
|
fDisplayed = TRUE;
|
|
}
|
|
else
|
|
if (0 == strcmp(pszObjId, szOID_POLICY_CONSTRAINTS))
|
|
{
|
|
CERT_POLICY_CONSTRAINTS_INFO Constraints;
|
|
|
|
cb = sizeof(Constraints);
|
|
if (!CryptDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_POLICY_CONSTRAINTS,
|
|
pbObject,
|
|
cbObject,
|
|
0,
|
|
&Constraints,
|
|
&cb))
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, error, "CryptDecodeObject");
|
|
}
|
|
wprintf(
|
|
L"%ws%ws%ws:\n",
|
|
pwszPad,
|
|
myLoadResourceString(IDS_POLICY_CONSTRAINTS),
|
|
g_wszCertUtil);
|
|
if (Constraints.fRequireExplicitPolicy)
|
|
{
|
|
wprintf(
|
|
L" dwRequireExplicitPolicySkipCerts: %u\n",
|
|
Constraints.dwRequireExplicitPolicySkipCerts);
|
|
}
|
|
if (Constraints.fInhibitPolicyMapping)
|
|
{
|
|
wprintf(
|
|
L" dwInhibitPolicyMappingSkipCerts: %u\n",
|
|
Constraints.dwInhibitPolicyMappingSkipCerts);
|
|
}
|
|
fDisplayed = TRUE;
|
|
}
|
|
else
|
|
if (0 == strcmp(pszObjId, szOID_REASON_CODE_HOLD))
|
|
{
|
|
char *pszObjIdT;
|
|
|
|
hr = cuDecodeObjId(pbObject, cbObject, &pszObjIdT);
|
|
if (S_OK == hr)
|
|
{
|
|
wprintf(pwszPad);
|
|
cuDumpOIDAndDescriptionA(pszObjIdT);
|
|
wprintf(wszNewLine);
|
|
LocalFree(pszObjIdT);
|
|
|
|
fDisplayed = TRUE;
|
|
}
|
|
}
|
|
else
|
|
if (0 == strcmp(pszObjId, szOID_VERISIGN_ONSITE_JURISDICTION_HASH))
|
|
{
|
|
CRYPT_DATA_BLOB Value;
|
|
WCHAR *pwsz;
|
|
|
|
Value.pbData = const_cast<BYTE *>(pbObject);
|
|
Value.cbData = cbObject;
|
|
hr = UnicodeDecode(&Value, &pwsz);
|
|
if (S_OK == hr)
|
|
{
|
|
wprintf(L"%ws%ws\n", pwszPad, pwsz);
|
|
LocalFree(pwsz);
|
|
fDisplayed = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
error:
|
|
if (NULL != strHash)
|
|
{
|
|
SysFreeString(strHash);
|
|
}
|
|
if (NULL != pszObjId)
|
|
{
|
|
LocalFree(pszObjId);
|
|
}
|
|
return(fDisplayed);
|
|
}
|
|
|
|
|
|
WCHAR const * const g_apwszFieldNames[] = {
|
|
wszCONFIG_COMMONNAME,
|
|
wszCONFIG_ORGUNIT,
|
|
wszCONFIG_ORGANIZATION,
|
|
wszCONFIG_LOCALITY,
|
|
wszCONFIG_STATE,
|
|
wszCONFIG_COUNTRY,
|
|
wszCONFIG_CONFIG,
|
|
wszCONFIG_EXCHANGECERTIFICATE,
|
|
wszCONFIG_SIGNATURECERTIFICATE,
|
|
wszCONFIG_DESCRIPTION,
|
|
wszCONFIG_SERVER,
|
|
wszCONFIG_AUTHORITY,
|
|
wszCONFIG_SANITIZEDNAME,
|
|
wszCONFIG_SHORTNAME,
|
|
wszCONFIG_SANITIZEDSHORTNAME,
|
|
wszCONFIG_FLAGS,
|
|
};
|
|
#define CSTRING (sizeof(g_apwszFieldNames)/sizeof(g_apwszFieldNames[0]))
|
|
|
|
WCHAR const *g_apwszDisplayNames[CSTRING];
|
|
|
|
LONG g_amsgidDisplayNames[CSTRING] = {
|
|
IDS_CONFIGDISPLAY_COMMONNAME_COLON,
|
|
IDS_CONFIGDISPLAY_ORGUNIT_COLON,
|
|
IDS_CONFIGDISPLAY_ORG_COLON,
|
|
IDS_CONFIGDISPLAY_LOCALITY_COLON,
|
|
IDS_CONFIGDISPLAY_STATE_COLON,
|
|
IDS_CONFIGDISPLAY_COUNTRY_COLON,
|
|
IDS_CONFIGDISPLAY_CONFIG_COLON,
|
|
IDS_CONFIGDISPLAY_EXCHANGECERT_COLON,
|
|
IDS_CONFIGDISPLAY_SIGCERT_COLON,
|
|
IDS_CONFIGDISPLAY_DESCRIPTION_COLON,
|
|
IDS_CONFIGDISPLAY_SERVER_COLON,
|
|
IDS_CONFIGDISPLAY_AUTHORITY_COLON,
|
|
IDS_CONFIGDISPLAY_SANITIZEDNAME_COLON,
|
|
IDS_CONFIGDISPLAY_SHORTNAME_COLON,
|
|
IDS_CONFIGDISPLAY_SANITIZEDSHORTNAME_COLON,
|
|
IDS_CONFIGDISPLAY_FLAGS_COLON,
|
|
};
|
|
|
|
|
|
HRESULT
|
|
cuConfigDump(VOID)
|
|
{
|
|
HRESULT hr;
|
|
DWORD i;
|
|
|
|
for (i = 0; i < CSTRING; i++)
|
|
{
|
|
g_apwszDisplayNames[i] = myLoadResourceString(g_amsgidDisplayNames[i]);
|
|
}
|
|
|
|
hr = ConfigDumpSetDisplayNames(
|
|
g_apwszFieldNames,
|
|
g_apwszDisplayNames,
|
|
CSTRING);
|
|
_JumpIfError(hr, error, "ConfigDumpSetDisplayNames");
|
|
|
|
hr = ConfigDump(
|
|
g_DispatchFlags,
|
|
myLoadResourceString(IDS_CONFIGDISPLAY_ENTRY), // "Entry"
|
|
myLoadResourceString(IDS_CONFIGDISPLAY_LOCAL), // "(Local)"
|
|
g_pwszDnsName,
|
|
g_pwszOldName);
|
|
_JumpIfError(hr, error, "ConfigDump");
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
typedef HRESULT (FNDUMP)(
|
|
IN DWORD idMessage,
|
|
IN BYTE const *pbIn,
|
|
IN DWORD cbIn,
|
|
IN BYTE const *pbDecoded,
|
|
IN DWORD cbDecoded,
|
|
IN CERT_SIGNED_CONTENT_INFO const *pcsci);
|
|
|
|
FNDUMP dumpCert, dumpCRL, dumpRequest, dumpCMCRequest, dumpCMCResponse,
|
|
dumpKeyGenRequest, dumpCertSequence, dumpCTL;
|
|
|
|
typedef struct _ASNFORMATS
|
|
{
|
|
char const *pszFormat;
|
|
FNDUMP *pfnDump;
|
|
DWORD idMessage;
|
|
WCHAR const *pwszExtension;
|
|
} ASNFORMATS;
|
|
|
|
|
|
ASNFORMATS g_aasn[] = {
|
|
{
|
|
X509_CERT_TO_BE_SIGNED,
|
|
dumpCert,
|
|
IDS_DUMP_CERT,
|
|
L".crt",
|
|
},
|
|
{
|
|
X509_CERT_CRL_TO_BE_SIGNED,
|
|
dumpCRL,
|
|
IDS_DUMP_CRL,
|
|
L".crl",
|
|
},
|
|
{
|
|
X509_CERT_REQUEST_TO_BE_SIGNED,
|
|
dumpRequest,
|
|
IDS_DUMP_REQUEST,
|
|
L".p10",
|
|
},
|
|
{
|
|
CMC_DATA,
|
|
dumpCMCRequest,
|
|
IDS_DUMP_CMC,
|
|
L".cmc",
|
|
},
|
|
{
|
|
CMC_RESPONSE,
|
|
dumpCMCResponse,
|
|
IDS_DUMP_CMCRESPONSE,
|
|
L".res",
|
|
},
|
|
{
|
|
X509_KEYGEN_REQUEST_TO_BE_SIGNED,
|
|
dumpKeyGenRequest,
|
|
IDS_DUMP_KEYGEN,
|
|
L".req",
|
|
},
|
|
{
|
|
PKCS_CONTENT_INFO_SEQUENCE_OF_ANY,
|
|
dumpCertSequence,
|
|
IDS_DUMP_CERTSEQ,
|
|
L".seq",
|
|
},
|
|
{
|
|
PKCS_CTL,
|
|
dumpCTL,
|
|
IDS_DUMP_CTL,
|
|
L".stl",
|
|
},
|
|
};
|
|
#define CASNFORMATS (sizeof(g_aasn)/sizeof(g_aasn[0]))
|
|
|
|
|
|
HRESULT
|
|
dumpPKCS7(
|
|
OPTIONAL IN HCERTSTORE hStoreWrapper,
|
|
IN BYTE const *pbIn,
|
|
IN DWORD cbIn);
|
|
|
|
|
|
typedef struct _DUMPALGID
|
|
{
|
|
ALG_ID Algid;
|
|
WCHAR const *pwszDescription;
|
|
} DUMPALGID;
|
|
|
|
#define _DFALGID(algid) { (algid), L#algid }
|
|
|
|
|
|
DUMPALGID g_adfAlgids[] =
|
|
{
|
|
_DFALGID(CALG_MD2),
|
|
_DFALGID(CALG_MD4),
|
|
_DFALGID(CALG_MD5),
|
|
//_DFALGID(CALG_SHA), same as CALG_SHA1
|
|
_DFALGID(CALG_SHA1),
|
|
_DFALGID(CALG_MAC),
|
|
_DFALGID(CALG_RSA_SIGN),
|
|
_DFALGID(CALG_DSS_SIGN),
|
|
_DFALGID(CALG_NO_SIGN),
|
|
_DFALGID(CALG_RSA_KEYX),
|
|
_DFALGID(CALG_DES),
|
|
_DFALGID(CALG_3DES_112),
|
|
_DFALGID(CALG_3DES),
|
|
_DFALGID(CALG_DESX),
|
|
_DFALGID(CALG_RC2),
|
|
_DFALGID(CALG_RC4),
|
|
_DFALGID(CALG_SEAL),
|
|
_DFALGID(CALG_DH_SF),
|
|
_DFALGID(CALG_DH_EPHEM),
|
|
_DFALGID(CALG_AGREEDKEY_ANY),
|
|
_DFALGID(CALG_KEA_KEYX),
|
|
_DFALGID(CALG_HUGHES_MD5),
|
|
_DFALGID(CALG_SKIPJACK),
|
|
_DFALGID(CALG_TEK),
|
|
_DFALGID(CALG_CYLINK_MEK),
|
|
_DFALGID(CALG_SSL3_SHAMD5),
|
|
_DFALGID(CALG_SSL3_MASTER),
|
|
_DFALGID(CALG_SCHANNEL_MASTER_HASH),
|
|
_DFALGID(CALG_SCHANNEL_MAC_KEY),
|
|
_DFALGID(CALG_SCHANNEL_ENC_KEY),
|
|
_DFALGID(CALG_PCT1_MASTER),
|
|
_DFALGID(CALG_SSL2_MASTER),
|
|
_DFALGID(CALG_TLS1_MASTER),
|
|
_DFALGID(CALG_RC5),
|
|
_DFALGID(CALG_HMAC),
|
|
_DFALGID(CALG_TLS1PRF),
|
|
_DFALGID(CALG_HASH_REPLACE_OWF),
|
|
_DFALGID(CALG_AES_128),
|
|
_DFALGID(CALG_AES_192),
|
|
_DFALGID(CALG_AES_256),
|
|
_DFALGID(CALG_AES),
|
|
};
|
|
|
|
|
|
DUMPALGID g_adfClass[] =
|
|
{
|
|
_DFALGID(ALG_CLASS_ANY),
|
|
_DFALGID(ALG_CLASS_SIGNATURE),
|
|
_DFALGID(ALG_CLASS_MSG_ENCRYPT),
|
|
_DFALGID(ALG_CLASS_DATA_ENCRYPT),
|
|
_DFALGID(ALG_CLASS_HASH),
|
|
_DFALGID(ALG_CLASS_KEY_EXCHANGE),
|
|
};
|
|
|
|
|
|
DUMPALGID g_adfType[] =
|
|
{
|
|
_DFALGID(ALG_TYPE_ANY),
|
|
_DFALGID(ALG_TYPE_DSS),
|
|
_DFALGID(ALG_TYPE_RSA),
|
|
_DFALGID(ALG_TYPE_BLOCK),
|
|
_DFALGID(ALG_TYPE_STREAM),
|
|
_DFALGID(ALG_TYPE_DH),
|
|
_DFALGID(ALG_TYPE_SECURECHANNEL),
|
|
};
|
|
|
|
|
|
// Generic sub-ids
|
|
|
|
DUMPALGID g_adfSubIdAny[] =
|
|
{
|
|
_DFALGID(ALG_SID_ANY),
|
|
};
|
|
|
|
|
|
// Some DSS sub-ids
|
|
|
|
DUMPALGID g_adfSubIdDSS[] =
|
|
{
|
|
_DFALGID(ALG_SID_DSS_ANY),
|
|
_DFALGID(ALG_SID_DSS_PKCS),
|
|
_DFALGID(ALG_SID_DSS_DMS),
|
|
};
|
|
|
|
|
|
// Some RSA sub-ids
|
|
|
|
DUMPALGID g_adfSubIdRSA[] =
|
|
{
|
|
_DFALGID(ALG_SID_RSA_ANY),
|
|
_DFALGID(ALG_SID_RSA_PKCS),
|
|
_DFALGID(ALG_SID_RSA_MSATWORK),
|
|
_DFALGID(ALG_SID_RSA_ENTRUST),
|
|
_DFALGID(ALG_SID_RSA_PGP),
|
|
};
|
|
|
|
|
|
// Block cipher sub ids
|
|
|
|
DUMPALGID g_adfSubIdBlock[] =
|
|
{
|
|
// RC2 sub-ids
|
|
|
|
_DFALGID(ALG_SID_RC2),
|
|
|
|
// DES sub_ids
|
|
|
|
_DFALGID(ALG_SID_DES),
|
|
_DFALGID(ALG_SID_3DES),
|
|
_DFALGID(ALG_SID_DESX),
|
|
_DFALGID(ALG_SID_IDEA),
|
|
_DFALGID(ALG_SID_CAST),
|
|
_DFALGID(ALG_SID_SAFERSK64),
|
|
_DFALGID(ALG_SID_SAFERSK128),
|
|
_DFALGID(ALG_SID_3DES_112),
|
|
_DFALGID(ALG_SID_CYLINK_MEK),
|
|
_DFALGID(ALG_SID_RC5),
|
|
_DFALGID(ALG_SID_AES_128),
|
|
_DFALGID(ALG_SID_AES_192),
|
|
_DFALGID(ALG_SID_AES_256),
|
|
_DFALGID(ALG_SID_AES),
|
|
|
|
// Fortezza sub-ids
|
|
|
|
_DFALGID(ALG_SID_SKIPJACK),
|
|
_DFALGID(ALG_SID_TEK),
|
|
};
|
|
|
|
|
|
// Stream cipher sub-ids
|
|
|
|
DUMPALGID g_adfSubIdStream[] =
|
|
{
|
|
_DFALGID(ALG_SID_RC4),
|
|
_DFALGID(ALG_SID_SEAL),
|
|
};
|
|
|
|
|
|
// Diffie-Hellman sub-ids
|
|
|
|
DUMPALGID g_adfSubIdDH[] =
|
|
{
|
|
_DFALGID(ALG_SID_DH_SANDF),
|
|
_DFALGID(ALG_SID_DH_EPHEM),
|
|
_DFALGID(ALG_SID_AGREED_KEY_ANY),
|
|
_DFALGID(ALG_SID_KEA),
|
|
};
|
|
|
|
|
|
// secure channel sub ids
|
|
|
|
DUMPALGID g_adfSubIdSecureChannel[] =
|
|
{
|
|
_DFALGID(ALG_SID_SSL3_MASTER),
|
|
_DFALGID(ALG_SID_SCHANNEL_MASTER_HASH),
|
|
_DFALGID(ALG_SID_SCHANNEL_MAC_KEY),
|
|
_DFALGID(ALG_SID_PCT1_MASTER),
|
|
_DFALGID(ALG_SID_SSL2_MASTER),
|
|
_DFALGID(ALG_SID_TLS1_MASTER),
|
|
_DFALGID(ALG_SID_SCHANNEL_ENC_KEY),
|
|
};
|
|
|
|
|
|
// Hash sub ids
|
|
|
|
DUMPALGID g_adfSubIdHash[] =
|
|
{
|
|
_DFALGID(ALG_SID_MD2),
|
|
_DFALGID(ALG_SID_MD4),
|
|
_DFALGID(ALG_SID_MD5),
|
|
_DFALGID(ALG_SID_SHA1),
|
|
_DFALGID(ALG_SID_MAC),
|
|
_DFALGID(ALG_SID_RIPEMD),
|
|
_DFALGID(ALG_SID_RIPEMD160),
|
|
_DFALGID(ALG_SID_SSL3SHAMD5),
|
|
_DFALGID(ALG_SID_HMAC),
|
|
_DFALGID(ALG_SID_TLS1PRF),
|
|
_DFALGID(ALG_SID_HASH_REPLACE_OWF),
|
|
};
|
|
|
|
|
|
#if 0
|
|
// KP_MODE
|
|
#define CRYPT_MODE_CBCI 6 // ANSI CBC Interleaved
|
|
#define CRYPT_MODE_CFBP 7 // ANSI CFB Pipelined
|
|
#define CRYPT_MODE_OFBP 8 // ANSI OFB Pipelined
|
|
#define CRYPT_MODE_CBCOFM 9 // ANSI CBC + OF Masking
|
|
#define CRYPT_MODE_CBCOFMI 10 // ANSI CBC + OFM Interleaved
|
|
#endif
|
|
|
|
|
|
typedef struct _DUMPSUBIDMAP
|
|
{
|
|
DWORD dwAlgType;
|
|
DUMPALGID *adfSubId;
|
|
DWORD cdfSubId;
|
|
} DUMPSUBIDMAP;
|
|
|
|
#define _DFARRAYANDSIZE(adf) (adf), ARRAYSIZE(adf)
|
|
|
|
|
|
DUMPSUBIDMAP g_adfSubIdMap[] =
|
|
{
|
|
{ ALG_TYPE_ANY, _DFARRAYANDSIZE(g_adfSubIdAny) },
|
|
{ ALG_TYPE_DSS, _DFARRAYANDSIZE(g_adfSubIdDSS) },
|
|
{ ALG_TYPE_RSA, _DFARRAYANDSIZE(g_adfSubIdRSA) },
|
|
{ ALG_TYPE_BLOCK, _DFARRAYANDSIZE(g_adfSubIdBlock) },
|
|
{ ALG_TYPE_STREAM, _DFARRAYANDSIZE(g_adfSubIdStream) },
|
|
{ ALG_TYPE_DH, _DFARRAYANDSIZE(g_adfSubIdDH) },
|
|
{ ALG_TYPE_SECURECHANNEL, _DFARRAYANDSIZE(g_adfSubIdSecureChannel) },
|
|
};
|
|
|
|
|
|
VOID
|
|
cuDumpAlgid(
|
|
IN DWORD Algid)
|
|
{
|
|
WCHAR const *pwsz;
|
|
WCHAR const *pwszQuestionMarks;
|
|
DUMPALGID *pda;
|
|
DUMPALGID *pdaSubId;
|
|
DWORD cdaSubId;
|
|
DUMPSUBIDMAP *pdsm;
|
|
DWORD AlgClass;
|
|
DWORD AlgType;
|
|
DWORD AlgSubId;
|
|
|
|
pwszQuestionMarks = myLoadResourceString(IDS_QUESTIONMARKS); // "???"
|
|
|
|
for (pda = g_adfAlgids; pda < &g_adfAlgids[ARRAYSIZE(g_adfAlgids)]; pda++)
|
|
{
|
|
if (Algid == pda->Algid)
|
|
{
|
|
wprintf(L" %ws\n", pda->pwszDescription);
|
|
break;
|
|
}
|
|
}
|
|
|
|
AlgClass = GET_ALG_CLASS(Algid);
|
|
pwsz = pwszQuestionMarks;
|
|
for (pda = g_adfClass; pda < &g_adfClass[ARRAYSIZE(g_adfClass)]; pda++)
|
|
{
|
|
if (AlgClass == pda->Algid)
|
|
{
|
|
pwsz = pda->pwszDescription;
|
|
break;
|
|
}
|
|
}
|
|
wprintf(
|
|
L" %ws: 0x%x(%u) %ws\n",
|
|
myLoadResourceString(IDS_ALGORITHM_CLASS), // "Algorithm Class"
|
|
AlgClass,
|
|
AlgClass >> 13,
|
|
pwsz);
|
|
|
|
AlgType = GET_ALG_TYPE(Algid);
|
|
pwsz = pwszQuestionMarks;
|
|
for (pda = g_adfType; pda < &g_adfType[ARRAYSIZE(g_adfType)]; pda++)
|
|
{
|
|
if (AlgType == pda->Algid)
|
|
{
|
|
pwsz = pda->pwszDescription;
|
|
break;
|
|
}
|
|
}
|
|
wprintf(
|
|
L" %ws: 0x%x(%u) %ws\n",
|
|
myLoadResourceString(IDS_ALGORITHM_TYPE), // "Algorithm Type"
|
|
AlgType,
|
|
AlgType >> 9,
|
|
pwsz);
|
|
|
|
pdaSubId = g_adfSubIdAny;
|
|
cdaSubId = ARRAYSIZE(g_adfSubIdAny);
|
|
for (pdsm = g_adfSubIdMap; pdsm < &g_adfSubIdMap[ARRAYSIZE(g_adfSubIdMap)]; pdsm++)
|
|
{
|
|
if (AlgType == pdsm->dwAlgType)
|
|
{
|
|
pdaSubId = pdsm->adfSubId;
|
|
cdaSubId = pdsm->cdfSubId;
|
|
break;
|
|
}
|
|
}
|
|
if (ALG_CLASS_HASH == AlgClass && pdaSubId == g_adfSubIdAny)
|
|
{
|
|
pdaSubId = g_adfSubIdHash;
|
|
cdaSubId = ARRAYSIZE(g_adfSubIdHash);
|
|
}
|
|
pwsz = pwszQuestionMarks;
|
|
AlgSubId = GET_ALG_SID(Algid);
|
|
for (pda = pdaSubId; pda < &pdaSubId[cdaSubId]; pda++)
|
|
{
|
|
if (AlgSubId == pda->Algid)
|
|
{
|
|
pwsz = pda->pwszDescription;
|
|
break;
|
|
}
|
|
}
|
|
wprintf(
|
|
L" %ws: 0x%x(%u) %ws\n",
|
|
myLoadResourceString(IDS_ALGORITHM_SUBID), // "Algorithm Sub-id"
|
|
AlgSubId,
|
|
AlgSubId >> 0,
|
|
pwsz);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
cuDumpPrivateKeyBlob(
|
|
IN BYTE const *pbKey,
|
|
IN DWORD cbKey,
|
|
IN BOOL fQuiet)
|
|
{
|
|
HRESULT hr;
|
|
PUBLICKEYSTRUC const *pkey = (PUBLICKEYSTRUC const *) pbKey;
|
|
WCHAR const *pwszType;
|
|
|
|
if (sizeof(*pkey) >= cbKey)
|
|
{
|
|
//DumpHex(DH_NOTABPREFIX | DH_PRIVATEDATA | 2, pbKey, cbKey);
|
|
hr = CRYPT_E_ASN1_BADTAG;
|
|
_JumpError2(hr, error, "key check", hr);
|
|
}
|
|
switch (pkey->bType)
|
|
{
|
|
case SIMPLEBLOB: pwszType = L"SIMPLEBLOB"; break;
|
|
case PUBLICKEYBLOB: pwszType = L"PUBLICKEYBLOB"; break;
|
|
case PRIVATEKEYBLOB: pwszType = L"PRIVATEKEYBLOB"; break;
|
|
case PLAINTEXTKEYBLOB: pwszType = L"PLAINTEXTKEYBLOB"; break;
|
|
case OPAQUEKEYBLOB: pwszType = L"OPAQUEKEYBLOB"; break;
|
|
case PUBLICKEYBLOBEX: pwszType = L"PUBLICKEYBLOBEX"; break;
|
|
case SYMMETRICWRAPKEYBLOB: pwszType = L"SYMMETRICWRAPKEYBLOB"; break;
|
|
default:
|
|
//DumpHex(DH_NOTABPREFIX | DH_PRIVATEDATA | 2, pbKey, cbKey);
|
|
hr = CRYPT_E_ASN1_BADTAG;
|
|
_JumpError2(hr, error, "key check", hr);
|
|
}
|
|
if (fQuiet)
|
|
{
|
|
hr = S_OK;
|
|
goto error;
|
|
}
|
|
wprintf(myLoadResourceString(IDS_PRIVATEKEY));
|
|
wprintf(wszNewLine);
|
|
|
|
wprintf(L" %ws\n", pwszType);
|
|
|
|
wprintf(g_wszPad2);
|
|
wprintf(
|
|
myLoadResourceString(IDS_FORMAT_VERSION), // "Version: %u"
|
|
pkey->bVersion);
|
|
wprintf(wszNewLine);
|
|
|
|
wprintf(L" aiKeyAlg: 0x%x\n", pkey->aiKeyAlg);
|
|
cuDumpAlgid(pkey->aiKeyAlg);
|
|
|
|
DumpHex(
|
|
DH_NOTABPREFIX | DH_PRIVATEDATA | 2,
|
|
(BYTE const *) &pkey[1],
|
|
cbKey - sizeof(*pkey));
|
|
hr = S_OK;
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT DisplayUniqueContainer(IN HCRYPTPROV hProv);
|
|
|
|
HRESULT
|
|
cuDumpPrivateKey(
|
|
IN CERT_CONTEXT const *pCert,
|
|
OPTIONAL OUT BOOL *pfSigningKey,
|
|
OPTIONAL OUT BOOL *pfMatchingKey)
|
|
{
|
|
HRESULT hr;
|
|
HCRYPTPROV hProv = NULL;
|
|
HCRYPTKEY hKey = NULL;
|
|
DWORD dwKeySpec;
|
|
DWORD cb;
|
|
CRYPT_BIT_BLOB PrivateKey;
|
|
CERT_PUBLIC_KEY_INFO *pPublicKeyInfo = NULL;
|
|
|
|
ZeroMemory(&PrivateKey, sizeof(PrivateKey));
|
|
if (NULL != pfSigningKey)
|
|
{
|
|
*pfSigningKey = FALSE;
|
|
}
|
|
if (NULL != pfMatchingKey)
|
|
{
|
|
*pfMatchingKey = FALSE;
|
|
}
|
|
if (!CryptAcquireCertificatePrivateKey(
|
|
pCert,
|
|
0, // dwFlags
|
|
NULL, // pvReserved
|
|
&hProv,
|
|
&dwKeySpec,
|
|
NULL)) // pfCallerFreeProv
|
|
{
|
|
hr = myHLastError();
|
|
if (CRYPT_E_NO_KEY_PROPERTY == hr)
|
|
{
|
|
wprintf(myLoadResourceString(IDS_NO_KEY_PROPERTY)); // "No stored keyset property"
|
|
wprintf(wszNewLine);
|
|
hr = S_OK;
|
|
|
|
_JumpError2(
|
|
CRYPT_E_NO_KEY_PROPERTY,
|
|
error,
|
|
"CryptAcquireCertificatePrivateKey",
|
|
CRYPT_E_NO_KEY_PROPERTY);
|
|
}
|
|
if (NTE_BAD_KEYSET == hr)
|
|
{
|
|
wprintf(myLoadResourceString(IDS_NO_KEY)); // "Missing stored keyset"
|
|
wprintf(wszNewLine);
|
|
hr = S_OK;
|
|
|
|
_JumpError2(
|
|
NTE_BAD_KEYSET,
|
|
error,
|
|
"CryptAcquireCertificatePrivateKey",
|
|
NTE_BAD_KEYSET);
|
|
}
|
|
_JumpError(hr, error, "CryptAcquireCertificatePrivateKey");
|
|
}
|
|
if (!g_fQuiet)
|
|
{
|
|
DisplayUniqueContainer(hProv);
|
|
}
|
|
if (NULL != pfSigningKey)
|
|
{
|
|
*pfSigningKey = AT_SIGNATURE == dwKeySpec;
|
|
}
|
|
|
|
if (!CryptGetUserKey(hProv, dwKeySpec, &hKey))
|
|
{
|
|
hr = myHLastError();
|
|
_PrintError(hr, "CryptGetUserKey");
|
|
cuPrintError(IDS_ERR_FORMAT_LOADKEY, hr);
|
|
goto error;
|
|
}
|
|
hr = myCryptExportPrivateKey(
|
|
hKey,
|
|
&PrivateKey.pbData,
|
|
&PrivateKey.cbData);
|
|
if (NTE_BAD_TYPE == hr || NTE_BAD_KEY_STATE == hr || NTE_PERM == hr)
|
|
{
|
|
wprintf(myLoadResourceString(IDS_PRIVATE_KEY_NOT_EXPORTABLE)); // "Private key is NOT exportable"
|
|
wprintf(wszNewLine);
|
|
}
|
|
else
|
|
{
|
|
_JumpIfError(hr, error, "myCryptExportPrivateKey");
|
|
}
|
|
|
|
if (!myCryptExportPublicKeyInfo(
|
|
hProv,
|
|
dwKeySpec,
|
|
CERTLIB_USE_LOCALALLOC,
|
|
&pPublicKeyInfo,
|
|
&cb))
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, error, "myCryptExportPublicKeyInfo");
|
|
}
|
|
|
|
if (!myCertComparePublicKeyInfo(
|
|
X509_ASN_ENCODING,
|
|
CERT_V1 == pCert->pCertInfo->dwVersion,
|
|
pPublicKeyInfo,
|
|
&pCert->pCertInfo->SubjectPublicKeyInfo))
|
|
{
|
|
// by design, (my)CertComparePublicKeyInfo doesn't set last error!
|
|
|
|
wprintf(myLoadResourceString(IDS_ERR_PUBLICKEY_MISMATCH)); // "ERROR: Certificate public key does NOT match stored keyset"
|
|
wprintf(wszNewLine);
|
|
}
|
|
else
|
|
{
|
|
if (AT_SIGNATURE == dwKeySpec)
|
|
{
|
|
hr = myValidateKeyForSigning(
|
|
hProv,
|
|
&pCert->pCertInfo->SubjectPublicKeyInfo,
|
|
CALG_SHA1);
|
|
_PrintIfError(hr, "myValidateKeyForSigning");
|
|
}
|
|
else
|
|
{
|
|
hr = myValidateKeyForEncrypting(
|
|
hProv,
|
|
&pCert->pCertInfo->SubjectPublicKeyInfo,
|
|
CALG_RC4);
|
|
_PrintIfError(hr, "myValidateKeyForEncrypting");
|
|
}
|
|
if (S_OK != hr)
|
|
{
|
|
wprintf(myLoadResourceString(IDS_ERR_PRIVATEKEY_MISMATCH)); // "ERROR: Certificate public key does NOT match private key"
|
|
wprintf(wszNewLine);
|
|
hr = S_OK;
|
|
}
|
|
else if (NULL != pfMatchingKey)
|
|
{
|
|
*pfMatchingKey = TRUE;
|
|
}
|
|
if (!g_fQuiet && NULL != PrivateKey.pbData)
|
|
{
|
|
wprintf(wszNewLine);
|
|
hr = cuDumpPrivateKeyBlob(
|
|
PrivateKey.pbData,
|
|
PrivateKey.cbData,
|
|
FALSE);
|
|
_JumpIfError(hr, error, "cuDumpPrivateKeyBlob");
|
|
}
|
|
}
|
|
|
|
error:
|
|
if (NULL != PrivateKey.pbData)
|
|
{
|
|
SecureZeroMemory(PrivateKey.pbData, PrivateKey.cbData); // Key material
|
|
LocalFree(PrivateKey.pbData);
|
|
}
|
|
if (NULL != pPublicKeyInfo)
|
|
{
|
|
LocalFree(pPublicKeyInfo);
|
|
}
|
|
if (NULL != hKey)
|
|
{
|
|
CryptDestroyKey(hKey);
|
|
}
|
|
if (NULL != hProv)
|
|
{
|
|
CryptReleaseContext(hProv, 0);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
cuDumpCertKeyProviderInfo(
|
|
IN WCHAR const *pwszPrefix,
|
|
OPTIONAL IN CERT_CONTEXT const *pCert,
|
|
OPTIONAL IN CRYPT_KEY_PROV_INFO *pkpi,
|
|
OPTIONAL OUT CRYPT_KEY_PROV_INFO **ppkpi)
|
|
{
|
|
HRESULT hr;
|
|
CRYPT_KEY_PROV_INFO *pkpiT = NULL;
|
|
DWORD i;
|
|
|
|
if (NULL != ppkpi)
|
|
{
|
|
*ppkpi = NULL;
|
|
}
|
|
CSASSERT((NULL == pCert) ^ (NULL == pkpi));
|
|
|
|
if (NULL != pCert)
|
|
{
|
|
CSASSERT(NULL == pkpi);
|
|
hr = myCertGetKeyProviderInfo(pCert, &pkpiT);
|
|
if (S_OK != hr)
|
|
{
|
|
_PrintIfError2(hr, "myCertGetKeyProviderInfo", CRYPT_E_NOT_FOUND);
|
|
if (CRYPT_E_NOT_FOUND != hr)
|
|
{
|
|
_JumpError(hr, error, "myCertGetKeyProviderInfo");
|
|
}
|
|
|
|
// Ignore missing property if we're just dumping the key provider info
|
|
|
|
wprintf(myLoadResourceString(IDS_NO_KEY_PROVIDER_INFO)); // "No key provider information"
|
|
wprintf(wszNewLine);
|
|
CSASSERT(NULL == pkpiT);
|
|
hr = S_OK;
|
|
goto error;
|
|
}
|
|
pkpi = pkpiT;
|
|
}
|
|
else
|
|
{
|
|
CSASSERT(NULL != pkpi);
|
|
}
|
|
wprintf(pwszPrefix);
|
|
wprintf(
|
|
myLoadResourceString(IDS_FORMAT_KEY_CONTAINER),
|
|
pkpi->pwszContainerName);
|
|
wprintf(wszNewLine);
|
|
|
|
wprintf(pwszPrefix);
|
|
wprintf(
|
|
myLoadResourceString(IDS_FORMAT_PROVIDER_NAME),
|
|
pkpi->pwszProvName);
|
|
wprintf(wszNewLine);
|
|
|
|
if (!g_fQuiet)
|
|
{
|
|
wprintf(pwszPrefix);
|
|
wprintf(
|
|
myLoadResourceString(IDS_FORMAT_PROVIDER_TYPE),
|
|
pkpi->dwProvType);
|
|
wprintf(wszNewLine);
|
|
}
|
|
|
|
if (!g_fQuiet)
|
|
{
|
|
wprintf(pwszPrefix);
|
|
wprintf(
|
|
myLoadResourceString(IDS_FORMAT_FLAGS),
|
|
pkpi->dwFlags);
|
|
wprintf(wszNewLine);
|
|
|
|
if (NULL != pkpi->rgProvParam)
|
|
{
|
|
for (i = 0; i < pkpi->cProvParam; i++)
|
|
{
|
|
wprintf(pwszPrefix);
|
|
wprintf(
|
|
myLoadResourceString(IDS_FORMAT_PROVPARM),
|
|
pkpi->rgProvParam[i].dwParam);
|
|
wprintf(wszNewLine);
|
|
|
|
DumpHex(
|
|
DH_MULTIADDRESS | DH_NOTABPREFIX | 4,
|
|
pkpi->rgProvParam[i].pbData,
|
|
pkpi->rgProvParam[i].cbData);
|
|
|
|
wprintf(pwszPrefix);
|
|
wprintf(
|
|
myLoadResourceString(IDS_FORMAT_PROVPARMFLAGS),
|
|
pkpi->rgProvParam[i].dwFlags);
|
|
wprintf(wszNewLine);
|
|
}
|
|
}
|
|
wprintf(pwszPrefix);
|
|
wprintf(
|
|
myLoadResourceString(IDS_FORMAT_KEYSPEC),
|
|
pkpi->dwKeySpec);
|
|
wprintf(wszNewLine);
|
|
}
|
|
if (NULL != pkpiT && NULL != ppkpi)
|
|
{
|
|
*ppkpi = pkpiT;
|
|
pkpiT = NULL;
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
if (NULL != pkpiT)
|
|
{
|
|
LocalFree(pkpiT);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
VOID
|
|
cuDumpAlgorithm(
|
|
IN DWORD idMessage,
|
|
IN CRYPT_ALGORITHM_IDENTIFIER const *pAlg)
|
|
{
|
|
wprintf(myLoadResourceString(idMessage));
|
|
wprintf(wszNewLine);
|
|
|
|
wprintf(g_wszPad4);
|
|
wprintf(myLoadResourceString(IDS_ALG_OID)); // "Algorithm ObjectId"
|
|
wprintf(L": ");
|
|
cuDumpOIDAndDescriptionA(pAlg->pszObjId);
|
|
wprintf(wszNewLine);
|
|
|
|
wprintf(g_wszPad4);
|
|
wprintf(myLoadResourceString(IDS_ALG_PARAMETERS_COLON)); // "Algorithm Parameters:"
|
|
if (NULL != pAlg->Parameters.pbData)
|
|
{
|
|
wprintf(wszNewLine);
|
|
DumpHex(
|
|
DH_MULTIADDRESS | DH_NOTABPREFIX | DH_NOASCIIHEX | 4,
|
|
pAlg->Parameters.pbData,
|
|
pAlg->Parameters.cbData);
|
|
}
|
|
else
|
|
{
|
|
wprintf(L" %ws\n", myLoadResourceString(IDS_NULL)); // "NULL"
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
cuDumpPublicKey(
|
|
IN CERT_PUBLIC_KEY_INFO const *pKey)
|
|
{
|
|
cuDumpAlgorithm(IDS_PUBLICKEY_ALGORITHM, &pKey->Algorithm);
|
|
|
|
wprintf(
|
|
myLoadResourceString(IDS_FORMAT_PUBLICKEY_LENGTH), // "Public Key Length: %u bits"
|
|
CertGetPublicKeyLength(
|
|
X509_ASN_ENCODING,
|
|
const_cast<CERT_PUBLIC_KEY_INFO *>(pKey)));
|
|
wprintf(wszNewLine);
|
|
|
|
wprintf(
|
|
myLoadResourceString(IDS_FORMAT_PUBLICKEY_UNUSEDBITS), // "Public Key: UnusedBits=%u"
|
|
pKey->PublicKey.cUnusedBits);
|
|
|
|
wprintf(wszNewLine);
|
|
DumpHex(
|
|
DH_NOTABPREFIX | DH_NOASCIIHEX | 4,
|
|
pKey->PublicKey.pbData,
|
|
pKey->PublicKey.cbData);
|
|
}
|
|
|
|
|
|
VOID
|
|
cuDumpSignature(
|
|
OPTIONAL IN CERT_SIGNED_CONTENT_INFO const *pcsci)
|
|
{
|
|
if (NULL == pcsci)
|
|
{
|
|
wprintf(myLoadResourceString(IDS_NO_SIGNATURE));
|
|
wprintf(wszNewLine);
|
|
goto error;
|
|
}
|
|
if (1 < g_fVerbose)
|
|
{
|
|
DumpHex(
|
|
DH_NOTABPREFIX | 4,
|
|
pcsci->ToBeSigned.pbData,
|
|
pcsci->ToBeSigned.cbData);
|
|
}
|
|
cuDumpAlgorithm(IDS_SIGNATURE_ALGORITHM, &pcsci->SignatureAlgorithm);
|
|
|
|
wprintf(
|
|
myLoadResourceString(IDS_FORMAT_SIGNATURE_UNUSEDBITS), // "Signature: UnusedBits=%u"
|
|
pcsci->Signature.cUnusedBits);
|
|
wprintf(wszNewLine);
|
|
|
|
DumpHex(
|
|
DH_NOTABPREFIX | DH_NOASCIIHEX | 4,
|
|
pcsci->Signature.pbData,
|
|
pcsci->Signature.cbData);
|
|
|
|
error:
|
|
;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
cuSaveAsnToFile(
|
|
IN BYTE const *pbIn,
|
|
IN DWORD cbIn,
|
|
IN int imajor,
|
|
IN int ilevel,
|
|
IN DWORD iElement,
|
|
IN WCHAR const *pwszExtension)
|
|
{
|
|
HRESULT hr;
|
|
WCHAR awc[MAX_PATH];
|
|
|
|
CSASSERT(0 < imajor);
|
|
CSASSERT(0 < ilevel);
|
|
|
|
wsprintf(
|
|
awc,
|
|
MAXDWORD == iElement? L"Blob%d_%d" : L"Blob%d_%d_%d",
|
|
imajor - 1,
|
|
ilevel - 1,
|
|
iElement);
|
|
if (wcslen(awc) + wcslen(pwszExtension) >= ARRAYSIZE(awc))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
|
|
_JumpErrorStr(hr, error, "awc", pwszExtension);
|
|
}
|
|
wcscat(awc, pwszExtension);
|
|
|
|
if (g_fSplitASN)
|
|
{
|
|
//wprintf(L"cuSaveAsnToFile: %d %d %d: %ws\n", imajor - 1, ilevel - 1, iElement, awc);
|
|
hr = EncodeToFileW(awc, pbIn, cbIn, CRYPT_STRING_BINARY | g_EncodeFlags);
|
|
_JumpIfError(hr, error, "EncodeToFileW");
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
DumpAsnBlob(
|
|
OPTIONAL IN HCERTSTORE hStoreWrapper,
|
|
IN BOOL fQuiet,
|
|
IN BYTE const *pbIn,
|
|
IN DWORD cbIn,
|
|
IN DWORD iElement)
|
|
{
|
|
HRESULT hr;
|
|
HRESULT hr2;
|
|
ASNFORMATS *pasn;
|
|
ASNFORMATS *pasnEnd;
|
|
DWORD cbDecoded;
|
|
BYTE *pbDecoded = NULL;
|
|
HCERTSTORE hStorePFX = NULL;
|
|
CERT_CONTEXT const *pCert = NULL;
|
|
CRYPT_KEY_PROV_INFO *pkpi = NULL;
|
|
CERT_SIGNED_CONTENT_INFO *pcsci = NULL;
|
|
DWORD cbcsci;
|
|
static int s_major = 0;
|
|
static int s_level = 0;
|
|
BOOL fSaved = FALSE;
|
|
WCHAR wszPassword[MAX_PATH];
|
|
|
|
if (0 == s_level)
|
|
{
|
|
s_major++;
|
|
}
|
|
s_level++;
|
|
if (1 < s_level)
|
|
{
|
|
wprintf(myLoadResourceString(IDS_FORMAT_DUMP_LEVEL_START), s_level - 1);
|
|
wprintf(wszNewLine);
|
|
}
|
|
if (MAXDWORD != iElement)
|
|
{
|
|
wprintf(myLoadResourceString(IDS_FORMAT_ELEMENT), iElement);
|
|
wprintf(wszNewLine);
|
|
}
|
|
|
|
if (1 < g_fVerbose)
|
|
{
|
|
wprintf(myLoadResourceString(IDS_FORMAT_ELEMENT_DUMP)); // "Embedded ASN.1 Element:"
|
|
wprintf(wszNewLine);
|
|
DumpHex(0, pbIn, cbIn);
|
|
}
|
|
|
|
pasnEnd = &g_aasn[CASNFORMATS];
|
|
for (pasn = g_aasn; pasn < pasnEnd; pasn++)
|
|
{
|
|
CSASSERT(NULL == pbDecoded);
|
|
if (myDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
pasn->pszFormat,
|
|
pbIn,
|
|
cbIn,
|
|
CERTLIB_USE_LOCALALLOC,
|
|
(VOID **) &pbDecoded,
|
|
&cbDecoded))
|
|
{
|
|
if (!myDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_CERT,
|
|
pbIn,
|
|
cbIn,
|
|
CERTLIB_USE_LOCALALLOC,
|
|
(VOID **) &pcsci,
|
|
&cbcsci))
|
|
{
|
|
hr = myHLastError();
|
|
_PrintError3(
|
|
hr,
|
|
"myDecodeObject",
|
|
CRYPT_E_ASN1_BADTAG,
|
|
CRYPT_E_ASN1_EOD);
|
|
}
|
|
|
|
hr = (*pasn->pfnDump)(
|
|
pasn->idMessage,
|
|
pbIn,
|
|
cbIn,
|
|
pbDecoded,
|
|
cbDecoded,
|
|
pcsci);
|
|
if (S_OK != hr && dumpCertSequence == pasn->pfnDump)
|
|
{
|
|
LocalFree(pbDecoded);
|
|
pbDecoded = NULL;
|
|
CSASSERT(NULL == pcsci);
|
|
continue;
|
|
}
|
|
hr2 = cuSaveAsnToFile(
|
|
pbIn,
|
|
cbIn,
|
|
s_major,
|
|
s_level,
|
|
iElement,
|
|
pasn->pwszExtension);
|
|
_PrintIfError(hr2, "cuSaveAsnToFile");
|
|
fSaved = TRUE;
|
|
_JumpIfError(hr, error, "(*pfnDump)");
|
|
|
|
break;
|
|
}
|
|
hr = myHLastError();
|
|
_PrintError2(hr, "myDecodeObject", hr);
|
|
CSASSERT(S_OK != hr);
|
|
}
|
|
if (pasn >= pasnEnd)
|
|
{
|
|
CRYPT_DATA_BLOB pfx;
|
|
|
|
CSASSERT(S_OK != hr);
|
|
|
|
pfx.pbData = const_cast<BYTE *>(pbIn);
|
|
pfx.cbData = cbIn;
|
|
|
|
if (PFXIsPFXBlob(&pfx))
|
|
{
|
|
DWORD dwKeySpec;
|
|
DWORD dwFlags;
|
|
WCHAR const *pwszPassword;
|
|
DWORD iCert;
|
|
|
|
hr = cuGetPassword(
|
|
0, // idsPrompt
|
|
NULL, // pwszfn
|
|
g_pwszPassword,
|
|
FALSE, // fVerify
|
|
wszPassword,
|
|
ARRAYSIZE(wszPassword),
|
|
&pwszPassword);
|
|
_JumpIfError(hr, error, "cuGetPassword");
|
|
|
|
hStorePFX = myPFXImportCertStore(
|
|
&pfx,
|
|
pwszPassword,
|
|
CRYPT_EXPORTABLE);
|
|
if (NULL == hStorePFX)
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, error, "myPFXImportCertStore");
|
|
}
|
|
hr = cuSaveAsnToFile(pbIn, cbIn, s_major, s_level, iElement, L".p12");
|
|
_PrintIfError(hr, "cuSaveAsnToFile");
|
|
fSaved = TRUE;
|
|
|
|
for (iCert = 0; ; iCert++)
|
|
{
|
|
BOOL fSigningKey;
|
|
BOOL fMatchingKey;
|
|
BOOL fRepaired = FALSE;
|
|
|
|
pCert = CertEnumCertificatesInStore(hStorePFX, pCert);
|
|
if (NULL == pCert)
|
|
{
|
|
break;
|
|
}
|
|
hr = cuDumpAsnBinary(
|
|
pCert->pbCertEncoded,
|
|
pCert->cbCertEncoded,
|
|
iCert);
|
|
_JumpIfError(hr, error, "cuDumpAsnBinary");
|
|
|
|
while (TRUE)
|
|
{
|
|
if (NULL != pkpi)
|
|
{
|
|
LocalFree(pkpi);
|
|
pkpi = NULL;
|
|
}
|
|
hr = cuDumpCertKeyProviderInfo(
|
|
g_wszPad2,
|
|
pCert,
|
|
NULL,
|
|
&pkpi);
|
|
if (S_OK != hr)
|
|
{
|
|
if (CRYPT_E_NOT_FOUND != hr)
|
|
{
|
|
_JumpError(hr, error, "cuDumpCertKeyProviderInfo");
|
|
}
|
|
}
|
|
else
|
|
if (NULL != pkpi)
|
|
{
|
|
// NT4 PFXImportCertStore doesn't set machine keyset
|
|
|
|
hr = cuDumpPrivateKey(
|
|
pCert,
|
|
&fSigningKey,
|
|
&fMatchingKey);
|
|
_PrintIfError2(
|
|
hr,
|
|
"cuDumpPrivateKey",
|
|
CRYPT_E_NO_KEY_PROPERTY);
|
|
if (S_OK == hr &&
|
|
!fMatchingKey &&
|
|
!fRepaired &&
|
|
0 == (CRYPT_MACHINE_KEYSET & pkpi->dwFlags))
|
|
{
|
|
LocalFree(pkpi);
|
|
pkpi = NULL;
|
|
hr = myRepairCertKeyProviderInfo(pCert, TRUE, NULL);
|
|
_JumpIfError(hr, error, "myRepairCertKeyProviderInfo");
|
|
fRepaired = TRUE;
|
|
continue;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hr = dumpPKCS7(hStoreWrapper, pbIn, cbIn);
|
|
if (S_OK == hr)
|
|
{
|
|
hr = cuSaveAsnToFile(
|
|
pbIn,
|
|
cbIn,
|
|
s_major,
|
|
s_level,
|
|
iElement,
|
|
L".p7b");
|
|
_PrintIfError(hr, "cuSaveAsnToFile");
|
|
fSaved = TRUE;
|
|
}
|
|
else
|
|
{
|
|
hr = cuDumpPrivateKeyBlob(pbIn, cbIn, fQuiet);
|
|
if (S_OK == hr)
|
|
{
|
|
hr = cuSaveAsnToFile(
|
|
pbIn,
|
|
cbIn,
|
|
s_major,
|
|
s_level,
|
|
iElement,
|
|
L".key");
|
|
_PrintIfError(hr, "cuSaveAsnToFile");
|
|
fSaved = TRUE;
|
|
}
|
|
else
|
|
{
|
|
_PrintError2(hr, "dumpPKCS7", CRYPT_E_ASN1_BADTAG);
|
|
if (!fQuiet)
|
|
{
|
|
DumpHex(DH_MULTIADDRESS | DH_NOTABPREFIX | 4, pbIn, cbIn);
|
|
}
|
|
}
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
}
|
|
|
|
error:
|
|
SecureZeroMemory(wszPassword, sizeof(wszPassword)); // password data
|
|
if (!fSaved)
|
|
{
|
|
hr2 = cuSaveAsnToFile(pbIn, cbIn, s_major, s_level, iElement, L".bin");
|
|
_PrintIfError(hr2, "cuSaveAsnToFile");
|
|
}
|
|
if (NULL != pkpi)
|
|
{
|
|
LocalFree(pkpi);
|
|
}
|
|
if (NULL != pCert)
|
|
{
|
|
CertFreeCertificateContext(pCert);
|
|
}
|
|
if (NULL != hStorePFX)
|
|
{
|
|
myDeleteGuidKeys(hStorePFX, FALSE);
|
|
CertCloseStore(hStorePFX, CERT_CLOSE_STORE_CHECK_FLAG);
|
|
}
|
|
if (NULL != pcsci)
|
|
{
|
|
LocalFree(pcsci);
|
|
}
|
|
if (NULL != pbDecoded)
|
|
{
|
|
LocalFree(pbDecoded);
|
|
}
|
|
if (1 < s_level)
|
|
{
|
|
wprintf(myLoadResourceString(IDS_FORMAT_DUMP_LEVEL_END), s_level - 1);
|
|
wprintf(wszNewLine);
|
|
}
|
|
s_level--;
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
cuDumpAsnBinary(
|
|
IN BYTE const *pbIn,
|
|
IN DWORD cbIn,
|
|
IN DWORD iElement)
|
|
{
|
|
return(DumpAsnBlob(NULL, FALSE, pbIn, cbIn, iElement));
|
|
}
|
|
|
|
|
|
HRESULT
|
|
cuDumpExtensionArray(
|
|
IN DWORD idMessage,
|
|
IN DWORD cExtension,
|
|
IN CERT_EXTENSION const *rgExtension)
|
|
{
|
|
HRESULT hr;
|
|
DWORD i;
|
|
WCHAR *pwszName = NULL;
|
|
WCHAR const *pwszExtensionFormat;
|
|
|
|
if (!g_fQuiet)
|
|
{
|
|
wprintf(myLoadResourceString(idMessage));
|
|
wprintf(L" %u\n", cExtension);
|
|
}
|
|
|
|
pwszExtensionFormat = myLoadResourceString(IDS_FORMAT_EXTENSION); // "%ws: Flags = %x%ws, Length = %x"
|
|
|
|
for (i = 0; i < cExtension; i++)
|
|
{
|
|
CERT_EXTENSION const *pce;
|
|
|
|
if (NULL != pwszName)
|
|
{
|
|
LocalFree(pwszName);
|
|
pwszName = NULL;
|
|
}
|
|
pce = &rgExtension[i];
|
|
if (g_fQuiet &&
|
|
0 != strcmp(pce->pszObjId, szOID_CERTSRV_CA_VERSION) &&
|
|
0 != strcmp(pce->pszObjId, szOID_ENROLL_CERTTYPE_EXTENSION) &&
|
|
0 != strcmp(pce->pszObjId, szOID_CRL_NUMBER) &&
|
|
0 != strcmp(pce->pszObjId, szOID_CRL_VIRTUAL_BASE) &&
|
|
0 != strcmp(pce->pszObjId, szOID_DELTA_CRL_INDICATOR))
|
|
{
|
|
continue;
|
|
}
|
|
if (!ConvertSzToWsz(&pwszName, pce->pszObjId, -1))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "ConvertSzToWsz");
|
|
}
|
|
|
|
if (!g_fQuiet)
|
|
{
|
|
wprintf(g_wszPad4);
|
|
wprintf(
|
|
pwszExtensionFormat,
|
|
pwszName,
|
|
pce->fCritical,
|
|
cuwszFromExtFlags(pce->fCritical),
|
|
pce->Value.cbData);
|
|
wprintf(wszNewLine);
|
|
}
|
|
if (!cuDumpFormattedExtension(
|
|
pwszName,
|
|
pce->Value.pbData,
|
|
pce->Value.cbData) ||
|
|
g_fVerbose)
|
|
{
|
|
wprintf(wszNewLine);
|
|
DumpHex(DH_NOTABPREFIX | 4, pce->Value.pbData, pce->Value.cbData);
|
|
}
|
|
if (!g_fQuiet)
|
|
{
|
|
wprintf(wszNewLine);
|
|
}
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
if (NULL != pwszName)
|
|
{
|
|
LocalFree(pwszName);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
VOID
|
|
cuDumpVersion(
|
|
IN DWORD dwVersion)
|
|
{
|
|
wprintf(
|
|
myLoadResourceString(IDS_FORMAT_VERSION), // "Version: %u"
|
|
dwVersion);
|
|
wprintf(wszNewLine);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
cuDumpCMSSignerInfo(
|
|
IN CMSG_CMS_SIGNER_INFO const *pcsi,
|
|
IN DWORD iElement,
|
|
IN BOOL fQuiet,
|
|
DWORD idVerify,
|
|
OPTIONAL IN HCERTSTORE hStore,
|
|
OPTIONAL OUT BYTE *pbHashUserCert,
|
|
OPTIONAL IN OUT DWORD *pcbHashUserCert)
|
|
{
|
|
HRESULT hr;
|
|
WCHAR const *pwszFmt = MAXDWORD == iElement? L"%ws:\n" : L"%ws[%u]:\n";
|
|
|
|
if (!fQuiet || g_fVerbose)
|
|
{
|
|
if (!fQuiet)
|
|
{
|
|
wprintf(wszNewLine);
|
|
}
|
|
wprintf(
|
|
pwszFmt,
|
|
myLoadResourceString(IDS_SIGNER_INFO), // "Signer Info"
|
|
iElement);
|
|
if (!fQuiet)
|
|
{
|
|
WCHAR const *pwszVersion = NULL;
|
|
|
|
if (0 != idVerify)
|
|
{
|
|
wprintf(myLoadResourceString(idVerify));
|
|
wprintf(wszNewLine);
|
|
}
|
|
switch (pcsi->dwVersion)
|
|
{
|
|
case CMSG_SIGNER_INFO_PKCS_1_5_VERSION:
|
|
pwszVersion = L"CMSG_SIGNER_INFO_PKCS_1_5_VERSION";
|
|
break;
|
|
|
|
case CMSG_SIGNER_INFO_CMS_VERSION:
|
|
pwszVersion = L"CMSG_SIGNER_INFO_CMS_VERSION";
|
|
break;
|
|
}
|
|
if (NULL == pwszVersion)
|
|
{
|
|
cuDumpVersion(pcsi->dwVersion);
|
|
}
|
|
else
|
|
{
|
|
wprintf(L"%ws(%u)\n", pwszVersion, pcsi->dwVersion);
|
|
}
|
|
}
|
|
switch (pcsi->SignerId.dwIdChoice)
|
|
{
|
|
case CERT_ID_ISSUER_SERIAL_NUMBER:
|
|
wprintf(
|
|
L"%ws(%u)\n",
|
|
L"CERT_ID_ISSUER_SERIAL_NUMBER",
|
|
pcsi->SignerId.dwIdChoice);
|
|
hr = cuDumpIssuerSerialAndSubject(
|
|
&pcsi->SignerId.IssuerSerialNumber.Issuer,
|
|
&pcsi->SignerId.IssuerSerialNumber.SerialNumber,
|
|
NULL, // pSubject
|
|
hStore);
|
|
_JumpIfError(hr, error, "cuDumpIssuerSerialAndSubject(Signer)");
|
|
|
|
break;
|
|
|
|
case CERT_ID_KEY_IDENTIFIER:
|
|
wprintf(
|
|
L"%ws(%u)\n",
|
|
L"CERT_ID_KEY_IDENTIFIER",
|
|
pcsi->SignerId.dwIdChoice);
|
|
DumpHex(
|
|
DH_MULTIADDRESS | DH_NOTABPREFIX | DH_NOASCIIHEX | 4,
|
|
pcsi->SignerId.KeyId.pbData,
|
|
pcsi->SignerId.KeyId.cbData);
|
|
break;
|
|
|
|
case CERT_ID_SHA1_HASH:
|
|
wprintf(
|
|
L"%ws(%u)\n",
|
|
L"CERT_ID_SHA1_HASH",
|
|
pcsi->SignerId.dwIdChoice);
|
|
DumpHex(
|
|
DH_MULTIADDRESS | DH_NOTABPREFIX | DH_NOASCIIHEX | 4,
|
|
pcsi->SignerId.HashId.pbData,
|
|
pcsi->SignerId.HashId.cbData);
|
|
break;
|
|
|
|
default:
|
|
wprintf(
|
|
L"%ws(%u)\n",
|
|
myLoadResourceString(IDS_QUESTIONMARKS), // "???"
|
|
pcsi->SignerId.dwIdChoice);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!fQuiet)
|
|
{
|
|
cuDumpAlgorithm(IDS_HASH_ALGORITHM, &pcsi->HashAlgorithm);
|
|
cuDumpAlgorithm(IDS_HASH_ENCRYPTION_ALGORITHM, &pcsi->HashEncryptionAlgorithm);
|
|
wprintf(myLoadResourceString(IDS_FORMAT_ENCRYPTEDHASH_COLON)); // "Encrypted Hash:"
|
|
wprintf(wszNewLine);
|
|
|
|
DumpHex(
|
|
DH_MULTIADDRESS | DH_NOTABPREFIX | DH_NOASCIIHEX | 4,
|
|
pcsi->EncryptedHash.pbData,
|
|
pcsi->EncryptedHash.cbData);
|
|
|
|
wprintf(wszNewLine);
|
|
wprintf(
|
|
pwszFmt,
|
|
myLoadResourceString(IDS_DUMP_PKCS7_ATTRIBUTES),
|
|
iElement);
|
|
}
|
|
|
|
if (!fQuiet || NULL != pbHashUserCert)
|
|
{
|
|
hr = DumpAttributes(
|
|
pcsi->AuthAttrs.rgAttr,
|
|
pcsi->AuthAttrs.cAttr,
|
|
fQuiet,
|
|
FOT_ATTRIBUTE,
|
|
hStore,
|
|
pbHashUserCert,
|
|
pcbHashUserCert,
|
|
NULL);
|
|
_JumpIfError(hr, error, "DumpAttributes");
|
|
}
|
|
|
|
if (!fQuiet)
|
|
{
|
|
wprintf(wszNewLine);
|
|
wprintf(
|
|
pwszFmt,
|
|
myLoadResourceString(IDS_DUMP_PKCS7_UNAUTHATTRIBUTES),
|
|
iElement);
|
|
|
|
hr = DumpAttributes(
|
|
pcsi->UnauthAttrs.rgAttr,
|
|
pcsi->UnauthAttrs.cAttr,
|
|
fQuiet,
|
|
FOT_ATTRIBUTE,
|
|
hStore,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
_JumpIfError(hr, error, "DumpAttributes");
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
cuDumpSignerInfo(
|
|
IN CMSG_SIGNER_INFO const *psi,
|
|
IN DWORD iElement,
|
|
IN BOOL fQuiet,
|
|
DWORD idVerify,
|
|
OPTIONAL IN HCERTSTORE hStore,
|
|
OPTIONAL OUT BYTE *pbHashUserCert,
|
|
OPTIONAL IN OUT DWORD *pcbHashUserCert)
|
|
{
|
|
HRESULT hr;
|
|
CMSG_CMS_SIGNER_INFO csi;
|
|
|
|
ZeroMemory(&csi, sizeof(csi));
|
|
|
|
csi.dwVersion = psi->dwVersion;
|
|
csi.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
|
|
csi.SignerId.IssuerSerialNumber.Issuer = psi->Issuer;
|
|
csi.SignerId.IssuerSerialNumber.SerialNumber = psi->SerialNumber;
|
|
csi.HashAlgorithm = psi->HashAlgorithm;
|
|
csi.HashEncryptionAlgorithm = psi->HashEncryptionAlgorithm;
|
|
csi.EncryptedHash = psi->EncryptedHash;
|
|
csi.AuthAttrs = psi->AuthAttrs;
|
|
csi.UnauthAttrs = psi->UnauthAttrs;
|
|
|
|
hr = cuDumpCMSSignerInfo(
|
|
&csi,
|
|
iElement,
|
|
fQuiet,
|
|
idVerify,
|
|
hStore,
|
|
pbHashUserCert,
|
|
pcbHashUserCert);
|
|
_JumpIfError(hr, error, "cuDumpCMSSignerInfo");
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
|
|
|
|
HRESULT
|
|
DumpAttributes(
|
|
IN CRYPT_ATTRIBUTE const *rgAttr,
|
|
IN DWORD cAttr,
|
|
IN BOOL fQuiet,
|
|
IN DWORD Type, // FOT_*
|
|
OPTIONAL IN HCERTSTORE hStore,
|
|
OPTIONAL OUT BYTE *pbHashUserCert,
|
|
OPTIONAL IN OUT DWORD *pcbHashUserCert,
|
|
OPTIONAL IN OUT CERT_EXTENSIONS **ppExtInfo)
|
|
{
|
|
HRESULT hr;
|
|
CRYPT_ATTRIBUTE const *pAttr;
|
|
CRYPT_ATTRIBUTE const *pAttrEnd;
|
|
CRYPT_ENROLLMENT_NAME_VALUE_PAIR *pNamePair = NULL;
|
|
CERT_EXTENSIONS *pExtInfo = NULL;
|
|
CERT_NAME_VALUE *pNameInfo = NULL;
|
|
DWORD cb;
|
|
DWORD iv;
|
|
|
|
if (NULL != ppExtInfo)
|
|
{
|
|
*ppExtInfo = NULL;
|
|
}
|
|
if (!fQuiet && FOT_PROPERTY != Type)
|
|
{
|
|
wprintf(
|
|
myLoadResourceString(IDS_FORMAT_PKCS7_ATTRIBUTE_COUNT), // " %d attributes:"
|
|
cAttr);
|
|
wprintf(wszNewLine);
|
|
}
|
|
|
|
pAttrEnd = &rgAttr[cAttr];
|
|
for (pAttr = rgAttr; pAttr < pAttrEnd; pAttr++)
|
|
{
|
|
WCHAR const *pwszOID = cuGetOIDNameA(pAttr->pszObjId);
|
|
|
|
if (!fQuiet && FOT_PROPERTY != Type)
|
|
{
|
|
wprintf(wszNewLine);
|
|
wprintf(
|
|
L" %ws[%u]: %hs%ws%ws%ws\n",
|
|
myLoadResourceString(IDS_ATTRIBUTE), // "Attribute"
|
|
pAttr - rgAttr,
|
|
pAttr->pszObjId,
|
|
L'\0' != *pwszOID? L" " wszLPAREN : g_wszEmpty,
|
|
pwszOID,
|
|
L'\0' != *pwszOID? wszRPAREN : g_wszEmpty);
|
|
}
|
|
|
|
for (iv = 0; iv < pAttr->cValue; iv++)
|
|
{
|
|
CRYPT_ATTR_BLOB const *pval = &pAttr->rgValue[iv];
|
|
|
|
if (fQuiet)
|
|
{
|
|
if (0 == strcmp(pAttr->pszObjId, szOID_ARCHIVED_KEY_CERT_HASH))
|
|
{
|
|
hr = DumpOctetHash(
|
|
g_wszEmpty,
|
|
0,
|
|
g_wszEmpty,
|
|
pval->pbData,
|
|
pval->cbData,
|
|
pbHashUserCert,
|
|
pcbHashUserCert);
|
|
_JumpIfError(hr, error, "DumpOctetHash");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (FOT_PROPERTY != Type)
|
|
{
|
|
wprintf(
|
|
myLoadResourceString(IDS_FORMAT_PKCS7_ATTRIBUTE_VALUE), // " Value[%d][%d]:"
|
|
pAttr - rgAttr,
|
|
iv);
|
|
wprintf(wszNewLine);
|
|
}
|
|
|
|
if (!DumpFormattedObject(
|
|
pAttr->pszObjId,
|
|
Type, // FOT_*
|
|
pval->pbData,
|
|
pval->cbData))
|
|
{
|
|
BOOL fDumpHex = FALSE;
|
|
|
|
if (0 == strcmp(pAttr->pszObjId, szOID_ENROLLMENT_NAME_VALUE_PAIR))
|
|
{
|
|
if (g_fVerbose)
|
|
{
|
|
DumpHex(0, pval->pbData, pval->cbData);
|
|
}
|
|
if (NULL != pNamePair)
|
|
{
|
|
LocalFree(pNamePair);
|
|
pNamePair = NULL;
|
|
}
|
|
if (!myDecodeNameValuePair(
|
|
X509_ASN_ENCODING,
|
|
pval->pbData,
|
|
pval->cbData,
|
|
CERTLIB_USE_LOCALALLOC,
|
|
&pNamePair,
|
|
&cb))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
|
|
_JumpError(hr, error, "myDecodeNameValuePair");
|
|
|
|
// if attribute name & value are both non-empty ...
|
|
}
|
|
wprintf(
|
|
L" %ws%ws = %ws\n",
|
|
pNamePair->pwszName,
|
|
g_wszCertUtil,
|
|
pNamePair->pwszValue);
|
|
}
|
|
else
|
|
if (0 == strcmp(pAttr->pszObjId, szOID_CERT_EXTENSIONS) ||
|
|
0 == strcmp(pAttr->pszObjId, szOID_RSA_certExtensions))
|
|
{
|
|
if (NULL != pNameInfo)
|
|
{
|
|
LocalFree(pNameInfo);
|
|
pNameInfo = NULL;
|
|
}
|
|
while (TRUE)
|
|
{
|
|
if (NULL != pExtInfo)
|
|
{
|
|
LocalFree(pExtInfo);
|
|
pExtInfo = NULL;
|
|
}
|
|
if (myDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_EXTENSIONS,
|
|
pval->pbData,
|
|
pval->cbData,
|
|
CERTLIB_USE_LOCALALLOC,
|
|
(VOID **) &pExtInfo,
|
|
&cb))
|
|
{
|
|
break; // success
|
|
}
|
|
hr = myHLastError();
|
|
|
|
// if we already decoded the attribute as a T61
|
|
// string, or if it's not a PKCS 9.14 attribute,
|
|
// just hex dump the attribute -- we don't know
|
|
// what it contains.
|
|
|
|
if (NULL != pNameInfo ||
|
|
0 != strcmp(
|
|
pAttr->pszObjId,
|
|
szOID_RSA_certExtensions))
|
|
{
|
|
//_JumpError(hr, error, "myDecodeObject");
|
|
_PrintError(hr, "myDecodeObject");
|
|
fDumpHex = TRUE;
|
|
break;
|
|
}
|
|
|
|
// decode the attribute as a T61 string. Some
|
|
// implementations wrap the PKCS 9.14 extension
|
|
// array in an extra level of encoding as a Teletex
|
|
// string.
|
|
|
|
if (!myDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_ANY_STRING,
|
|
pval->pbData,
|
|
pval->cbData,
|
|
CERTLIB_USE_LOCALALLOC,
|
|
(VOID **) &pNameInfo,
|
|
&cb))
|
|
{
|
|
hr = myHLastError();
|
|
//_JumpError(hr, error, "myDecodeObject");
|
|
_PrintError(hr, "myDecodeObject");
|
|
fDumpHex = TRUE;
|
|
break;
|
|
}
|
|
|
|
// Now loop again and try to decode the raw name
|
|
// blob as X509_EXTENSIONS.
|
|
|
|
pval = &pNameInfo->Value;
|
|
wprintf(myLoadResourceString(IDS_TELETEX_EXTENSIONS)); // "Decoded extra Extension Array encoding layer (Teletex string)"
|
|
wprintf(wszNewLine);
|
|
}
|
|
if (!fDumpHex)
|
|
{
|
|
hr = cuDumpExtensionArray(
|
|
IDS_CERTIFICATE_EXTENSIONS,
|
|
pExtInfo->cExtension,
|
|
pExtInfo->rgExtension);
|
|
_JumpIfError(hr, error, "cuDumpExtensionArray");
|
|
}
|
|
}
|
|
else
|
|
if (0 == strcmp(pAttr->pszObjId, szOID_RENEWAL_CERTIFICATE) ||
|
|
0 == strcmp(pAttr->pszObjId, szOID_RSA_SMIMECapabilities))
|
|
{
|
|
wprintf(myLoadResourceString(
|
|
0 == strcmp(
|
|
pAttr->pszObjId,
|
|
szOID_RENEWAL_CERTIFICATE)?
|
|
IDS_RENEWAL_CERT : // "Renewal Certificate:"
|
|
IDS_SMIME_CAPABILITIES)); // "SMIME Capabilities:"
|
|
wprintf(wszNewLine);
|
|
|
|
hr = cuDumpAsnBinary(pval->pbData, pval->cbData, MAXDWORD);
|
|
_JumpIfError(hr, error, "cuDumpAsnBinary");
|
|
}
|
|
else
|
|
if (0 == strcmp(pAttr->pszObjId, szOID_RSA_contentType))
|
|
{
|
|
char *pszObjId;
|
|
|
|
hr = cuDecodeObjId(pval->pbData, pval->cbData, &pszObjId);
|
|
if (S_OK != hr)
|
|
{
|
|
fDumpHex = TRUE;
|
|
}
|
|
else
|
|
{
|
|
wprintf(g_wszPad4);
|
|
cuDumpOIDAndDescriptionA(pszObjId);
|
|
wprintf(wszNewLine);
|
|
LocalFree(pszObjId);
|
|
}
|
|
}
|
|
else
|
|
if (0 == strcmp(pAttr->pszObjId, szOID_RSA_messageDigest))
|
|
{
|
|
hr = DumpOctetHash(
|
|
g_wszPad4,
|
|
IDS_MESSAGE_DIGEST,
|
|
g_wszCertUtil,
|
|
pval->pbData,
|
|
pval->cbData,
|
|
NULL,
|
|
NULL);
|
|
if (S_OK != hr)
|
|
{
|
|
fDumpHex = TRUE;
|
|
}
|
|
}
|
|
else
|
|
if (0 == strcmp(pAttr->pszObjId, szOID_ARCHIVED_KEY_ATTR))
|
|
{
|
|
hr = cuDumpAsnBinary(pval->pbData, pval->cbData, MAXDWORD);
|
|
if (S_OK != hr)
|
|
{
|
|
fDumpHex = TRUE;
|
|
}
|
|
}
|
|
else
|
|
if (0 == strcmp(pAttr->pszObjId, szOID_ARCHIVED_KEY_CERT_HASH))
|
|
{
|
|
hr = DumpOctetHash(
|
|
g_wszPad4,
|
|
IDS_ARCHIVED_KEY_CERT_HASH,
|
|
g_wszCertUtil,
|
|
pval->pbData,
|
|
pval->cbData,
|
|
pbHashUserCert,
|
|
pcbHashUserCert);
|
|
if (S_OK != hr)
|
|
{
|
|
fDumpHex = TRUE;
|
|
}
|
|
}
|
|
else
|
|
if (0 == strcmp(pAttr->pszObjId, szOID_ISSUED_CERT_HASH))
|
|
{
|
|
hr = DumpOctetHash(
|
|
g_wszPad4,
|
|
IDS_ISSUED_CERT_HASH,
|
|
g_wszCertUtil,
|
|
pval->pbData,
|
|
pval->cbData,
|
|
pbHashUserCert,
|
|
pcbHashUserCert);
|
|
if (S_OK != hr)
|
|
{
|
|
fDumpHex = TRUE;
|
|
}
|
|
}
|
|
else
|
|
if (0 == strcmp(pAttr->pszObjId, szOID_ENCRYPTED_KEY_HASH))
|
|
{
|
|
hr = DumpOctetHash(
|
|
g_wszPad4,
|
|
IDS_ENCRYPTED_KEY_HASH,
|
|
g_wszCertUtil,
|
|
pval->pbData,
|
|
pval->cbData,
|
|
NULL,
|
|
NULL);
|
|
if (S_OK != hr)
|
|
{
|
|
fDumpHex = TRUE;
|
|
}
|
|
}
|
|
else
|
|
if (0 == strcmp(pAttr->pszObjId, szOID_ENROLLMENT_CSP_PROVIDER))
|
|
{
|
|
CRYPT_CSP_PROVIDER *pccp;
|
|
|
|
hr = myDecodeCSPProviderAttribute(
|
|
pval->pbData,
|
|
pval->cbData,
|
|
&pccp);
|
|
if (S_OK == hr)
|
|
{
|
|
wprintf(g_wszPad4);
|
|
wprintf(
|
|
myLoadResourceString(IDS_CSP_PROVIDER_INFO));
|
|
wprintf(wszNewLine);
|
|
|
|
wprintf(g_wszPad4);
|
|
wprintf(
|
|
myLoadResourceString(IDS_FORMAT_KEYSPEC),
|
|
pccp->dwKeySpec);
|
|
wprintf(wszNewLine);
|
|
|
|
wprintf(g_wszPad4);
|
|
wprintf(
|
|
myLoadResourceString(IDS_FORMAT_PROVIDER_NAME),
|
|
NULL == pccp->pwszProviderName?
|
|
myLoadResourceString(IDS_PROP_EMPTY) :
|
|
pccp->pwszProviderName);
|
|
wprintf(wszNewLine);
|
|
|
|
wprintf(g_wszPad4);
|
|
wprintf(
|
|
myLoadResourceString(IDS_FORMAT_SIGNATURE_UNUSEDBITS), // "Signature: UnusedBits=%u"
|
|
pccp->Signature.cUnusedBits);
|
|
wprintf(wszNewLine);
|
|
|
|
DumpHex(
|
|
DH_NOTABPREFIX | DH_NOASCIIHEX | 4,
|
|
pccp->Signature.pbData,
|
|
pccp->Signature.cbData);
|
|
|
|
LocalFree(pccp);
|
|
}
|
|
else
|
|
{
|
|
fDumpHex = TRUE;
|
|
}
|
|
}
|
|
else
|
|
if (0 == strcmp(pAttr->pszObjId, szOID_RSA_signingTime))
|
|
{
|
|
FILETIME ft;
|
|
|
|
cb = sizeof(ft);
|
|
if (CryptDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_CHOICE_OF_TIME,
|
|
pval->pbData,
|
|
pval->cbData,
|
|
0,
|
|
&ft,
|
|
&cb))
|
|
{
|
|
wprintf(
|
|
L"%ws%ws%ws: ",
|
|
g_wszPad4,
|
|
myLoadResourceString(IDS_SIGNING_TIME),
|
|
g_wszCertUtil);
|
|
|
|
hr = cuDumpFileTime(0, NULL, &ft);
|
|
_JumpIfError(hr, error, "cuDumpFileTime");
|
|
}
|
|
else
|
|
{
|
|
fDumpHex = TRUE;
|
|
}
|
|
}
|
|
else
|
|
if (0 == strcmp(pAttr->pszObjId, szOID_REQUEST_CLIENT_INFO))
|
|
{
|
|
CRYPT_REQUEST_CLIENT_INFO *pcrci = NULL;
|
|
|
|
hr = myDecodeRequestClientAttribute(
|
|
pval->pbData,
|
|
pval->cbData,
|
|
&pcrci);
|
|
if (S_OK == hr)
|
|
{
|
|
wprintf(g_wszPad2);
|
|
cuRegPrintDwordValue(
|
|
TRUE,
|
|
wszREQUESTCLIENTID,
|
|
myLoadResourceString(IDS_CLIENTID),
|
|
pcrci->dwClientId);
|
|
wprintf(
|
|
L"%ws%ws %ws\n",
|
|
g_wszPad4,
|
|
myLoadResourceString(IDS_USERCOLON),
|
|
pcrci->pwszUser);
|
|
|
|
wprintf(
|
|
L"%ws%ws %ws\n",
|
|
g_wszPad4,
|
|
myLoadResourceString(IDS_MACHINECOLON),
|
|
pcrci->pwszMachine);
|
|
|
|
wprintf(
|
|
L"%ws%ws %ws\n",
|
|
g_wszPad4,
|
|
myLoadResourceString(IDS_PROCESSCOLON),
|
|
pcrci->pwszProcess);
|
|
|
|
LocalFree(pcrci);
|
|
}
|
|
else
|
|
{
|
|
fDumpHex = TRUE;
|
|
}
|
|
}
|
|
else
|
|
if (0 == strcmp(pAttr->pszObjId, szOID_RSA_counterSign))
|
|
{
|
|
CMSG_SIGNER_INFO *psi = NULL;
|
|
|
|
if (!myDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
PKCS7_SIGNER_INFO,
|
|
pval->pbData,
|
|
pval->cbData,
|
|
CERTLIB_USE_LOCALALLOC,
|
|
(VOID **) &psi,
|
|
&cb))
|
|
{
|
|
CSASSERT(NULL == psi);
|
|
hr = myHLastError();
|
|
_PrintError(hr, "myDecodeObject");
|
|
fDumpHex = TRUE;
|
|
}
|
|
else
|
|
{
|
|
wprintf(
|
|
L"%ws%ws%ws: ",
|
|
g_wszPad4,
|
|
myLoadResourceString(IDS_COUNTER_SIGNATURE),
|
|
g_wszCertUtil);
|
|
|
|
hr = cuDumpSignerInfo(
|
|
psi,
|
|
MAXDWORD, // iElement
|
|
fQuiet,
|
|
0,
|
|
hStore,
|
|
pbHashUserCert,
|
|
pcbHashUserCert);
|
|
_PrintIfError(hr, "cuDumpSignerInfo");
|
|
if (S_OK != hr)
|
|
{
|
|
fDumpHex = TRUE;
|
|
}
|
|
}
|
|
if (NULL != psi)
|
|
{
|
|
LocalFree(psi);
|
|
}
|
|
}
|
|
else
|
|
if (0 == strcmp(pAttr->pszObjId, szOID_RSA_challengePwd))
|
|
{
|
|
CRYPT_DATA_BLOB Value;
|
|
WCHAR *pwsz;
|
|
|
|
Value.pbData = pval->pbData;
|
|
Value.cbData = pval->cbData;
|
|
hr = UnicodeDecode(&Value, &pwsz);
|
|
if (S_OK == hr)
|
|
{
|
|
wprintf(L"%ws%ws\n", g_wszPad4, pwsz);
|
|
LocalFree(pwsz);
|
|
}
|
|
else
|
|
{
|
|
fDumpHex = TRUE;
|
|
}
|
|
}
|
|
else
|
|
if (0 == strcmp(pAttr->pszObjId, szOID_YESNO_TRUST_ATTR))
|
|
{
|
|
DWORD Bool;
|
|
|
|
cb = sizeof(Bool);
|
|
Bool = 0;
|
|
if (CryptDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_INTEGER,
|
|
pval->pbData,
|
|
pval->cbData,
|
|
0,
|
|
&Bool,
|
|
&cb))
|
|
{
|
|
wprintf(
|
|
L"%ws%x\n",
|
|
g_wszPad4,
|
|
Bool);
|
|
}
|
|
else
|
|
{
|
|
fDumpHex = TRUE;
|
|
}
|
|
}
|
|
if (fDumpHex)
|
|
{
|
|
DumpHex(
|
|
DH_NOTABPREFIX | 4,
|
|
pval->pbData,
|
|
pval->cbData);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (NULL != ppExtInfo)
|
|
{
|
|
*ppExtInfo = pExtInfo;
|
|
pExtInfo = NULL;
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
if (NULL != pNamePair)
|
|
{
|
|
LocalFree(pNamePair);
|
|
}
|
|
if (NULL != pExtInfo)
|
|
{
|
|
LocalFree(pExtInfo);
|
|
}
|
|
if (NULL != pNameInfo)
|
|
{
|
|
LocalFree(pNameInfo);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
FindCertStoreIndex(
|
|
IN HCERTSTORE hStore,
|
|
IN CERT_CONTEXT const *pCertSigner,
|
|
OUT DWORD *piElement)
|
|
{
|
|
HRESULT hr;
|
|
DWORD iElement;
|
|
CERT_CONTEXT const *pcc = NULL;
|
|
|
|
*piElement = -1;
|
|
for (iElement = 0; ; iElement++)
|
|
{
|
|
pcc = CertEnumCertificatesInStore(hStore, pcc);
|
|
if (NULL == pcc)
|
|
{
|
|
hr = CRYPT_E_NOT_FOUND;
|
|
_JumpError(hr, error, "CertEnumCertificatesInStore");
|
|
}
|
|
if (pCertSigner->cbCertEncoded == pcc->cbCertEncoded &&
|
|
0 == memcmp(
|
|
pCertSigner->pbCertEncoded,
|
|
pcc->pbCertEncoded,
|
|
pcc->cbCertEncoded))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
*piElement = iElement;
|
|
hr = S_OK;
|
|
|
|
error:
|
|
if (NULL != pcc)
|
|
{
|
|
CertFreeCertificateContext(pcc);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
cuDumpIssuerSerialAndSubject(
|
|
IN CERT_NAME_BLOB const *pIssuer,
|
|
IN CRYPT_INTEGER_BLOB const *pSerialNumber,
|
|
OPTIONAL IN CERT_NAME_BLOB const *pSubject,
|
|
OPTIONAL IN HCERTSTORE hStore)
|
|
{
|
|
HRESULT hr;
|
|
BOOL fVerbose = g_fVerbose;
|
|
CERT_ID CertId;
|
|
CERT_CONTEXT const *pcc = NULL;
|
|
BOOL fMultiLine = NULL == pSerialNumber || g_fVerbose;
|
|
|
|
if (g_fVerbose)
|
|
{
|
|
g_fVerbose--;
|
|
}
|
|
hr = cuDumpSerial(g_wszPad4, IDS_SERIAL, pSerialNumber);
|
|
_JumpIfError(hr, error, "cuDumpSerial");
|
|
|
|
hr = cuDisplayCertName(
|
|
fMultiLine,
|
|
g_wszPad4,
|
|
myLoadResourceString(IDS_ISSUER), // "Issuer"
|
|
g_wszPad8,
|
|
pIssuer,
|
|
NULL);
|
|
_JumpIfError(hr, error, "cuDisplayCertName(Issuer)");
|
|
|
|
ZeroMemory(&CertId, sizeof(CertId));
|
|
CertId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
|
|
CertId.IssuerSerialNumber.Issuer = *pIssuer;
|
|
if (NULL != pSerialNumber)
|
|
{
|
|
CertId.IssuerSerialNumber.SerialNumber = *pSerialNumber;
|
|
}
|
|
|
|
if (NULL == pSubject && NULL != hStore)
|
|
{
|
|
pcc = CertFindCertificateInStore(
|
|
hStore,
|
|
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
|
|
0, // dwFindFlags
|
|
CERT_FIND_CERT_ID,
|
|
&CertId,
|
|
NULL);
|
|
if (NULL == pcc)
|
|
{
|
|
hr = myHLastError();
|
|
_PrintError2(hr, "CertFindCertificateInStore", hr);
|
|
}
|
|
else
|
|
{
|
|
pSubject = &pcc->pCertInfo->Subject;
|
|
}
|
|
}
|
|
if (NULL != pSubject)
|
|
{
|
|
hr = cuDisplayCertName(
|
|
fMultiLine,
|
|
g_wszPad4,
|
|
myLoadResourceString(IDS_SUBJECT), // "Subject"
|
|
g_wszPad8,
|
|
pSubject,
|
|
NULL);
|
|
_JumpIfError(hr, error, "cuDisplayCertName(Issuer)");
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
g_fVerbose = fVerbose;
|
|
if (NULL != pcc)
|
|
{
|
|
CertFreeCertificateContext(pcc);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
cuDumpSigners(
|
|
IN HCRYPTMSG hMsg,
|
|
IN CHAR const *pszInnerContentObjId,
|
|
IN HCERTSTORE hStore,
|
|
IN DWORD cSigner,
|
|
IN BOOL fContentEmpty,
|
|
IN BOOL fQuiet,
|
|
OPTIONAL OUT BYTE *pbHashUserCert,
|
|
OPTIONAL IN OUT DWORD *pcbHashUserCert)
|
|
{
|
|
HRESULT hr;
|
|
DWORD i;
|
|
CMSG_CMS_SIGNER_INFO *pcsi = NULL;
|
|
DWORD cb;
|
|
CERT_CONTEXT const *pcc = NULL;
|
|
BYTE abHash[CBMAX_CRYPT_HASH_LEN];
|
|
DWORD iElement;
|
|
DWORD VerifyState;
|
|
BOOL fVerbose = g_fVerbose;
|
|
CERT_REQUEST_INFO *pRequest = NULL;
|
|
|
|
if (!fQuiet)
|
|
{
|
|
if (0 == cSigner)
|
|
{
|
|
wprintf(myLoadResourceString(IDS_DUMP_PKCS7_NO_SIGNER));
|
|
wprintf(wszNewLine);
|
|
}
|
|
else
|
|
{
|
|
wprintf(
|
|
L"%ws: %d\n",
|
|
myLoadResourceString(IDS_DUMP_PKCS7_SIGNER_COUNT),
|
|
cSigner);
|
|
}
|
|
}
|
|
for (i = 0; i < cSigner; i++)
|
|
{
|
|
DWORD idVerify = 0;
|
|
|
|
if (NULL != pcsi)
|
|
{
|
|
LocalFree(pcsi);
|
|
pcsi = NULL;
|
|
}
|
|
hr = myCryptMsgGetParam(
|
|
hMsg,
|
|
CMSG_CMS_SIGNER_INFO_PARAM,
|
|
i,
|
|
CERTLIB_USE_LOCALALLOC,
|
|
(VOID **) &pcsi,
|
|
&cb);
|
|
_JumpIfError(hr, error, "myCryptMsgGetParam");
|
|
|
|
if (CERT_ID_KEY_IDENTIFIER == pcsi->SignerId.dwIdChoice ||
|
|
(NULL != pcsi->HashEncryptionAlgorithm.pszObjId &&
|
|
0 == strcmp(
|
|
szOID_PKIX_NO_SIGNATURE,
|
|
pcsi->HashEncryptionAlgorithm.pszObjId)))
|
|
{
|
|
CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA cvse;
|
|
|
|
ZeroMemory(&cvse, sizeof(cvse));
|
|
cvse.cbSize = sizeof(cvse);
|
|
cvse.dwSignerIndex = i;
|
|
|
|
if (CERT_ID_KEY_IDENTIFIER == pcsi->SignerId.dwIdChoice)
|
|
{
|
|
if (NULL == pRequest)
|
|
{
|
|
hr = myGetInnerPKCS10(
|
|
hMsg,
|
|
pszInnerContentObjId,
|
|
&pRequest);
|
|
_JumpIfError(hr, error, "myGetInnerPKCS10");
|
|
}
|
|
cvse.dwSignerType = CMSG_VERIFY_SIGNER_PUBKEY;
|
|
cvse.pvSigner = &pRequest->SubjectPublicKeyInfo;
|
|
}
|
|
else
|
|
{
|
|
cvse.dwSignerType = CMSG_VERIFY_SIGNER_NULL;
|
|
}
|
|
|
|
if (!CryptMsgControl(
|
|
hMsg,
|
|
0, // dwFlags
|
|
CMSG_CTRL_VERIFY_SIGNATURE_EX,
|
|
&cvse))
|
|
{
|
|
hr = myHLastError();
|
|
_PrintError(hr, "CryptMsgControl");
|
|
cuPrintError(0, hr);
|
|
}
|
|
else
|
|
{
|
|
idVerify = CERT_ID_KEY_IDENTIFIER == pcsi->SignerId.dwIdChoice?
|
|
IDS_REQUEST_SIGNATUREMATCHES : // "Signature matches request Public Key"
|
|
IDS_NULL_SIGNATUREMATCHES; // "NULL signature verifies"
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DWORD dwFlags;
|
|
|
|
dwFlags = CMSG_USE_SIGNER_INDEX_FLAG;
|
|
while (TRUE)
|
|
{
|
|
iElement = i;
|
|
if (CryptMsgGetAndVerifySigner(
|
|
hMsg,
|
|
0, // cSignerStore
|
|
NULL, // rghSignerStore
|
|
dwFlags,
|
|
&pcc,
|
|
&iElement))
|
|
{
|
|
hr = S_OK;
|
|
break;
|
|
}
|
|
hr = myHLastError();
|
|
_PrintError(hr, "CryptMsgGetAndVerifySigner");
|
|
|
|
if (CMSG_SIGNER_ONLY_FLAG & dwFlags)
|
|
{
|
|
cuPrintError(0, hr);
|
|
break;
|
|
}
|
|
cuPrintError(
|
|
(fContentEmpty && NTE_BAD_SIGNATURE == hr)?
|
|
IDS_DETACHED_SIGNATURE : // "Cannot verify detached signature"
|
|
0,
|
|
hr);
|
|
dwFlags |= CMSG_SIGNER_ONLY_FLAG;
|
|
}
|
|
if (S_OK == hr)
|
|
{
|
|
idVerify = IDS_SIGNATUREMATCHES; // "Signature matches Public Key"
|
|
hr = FindCertStoreIndex(hStore, pcc, &iElement);
|
|
_JumpIfError(hr, error, "FindCertStoreIndex");
|
|
|
|
if (!fQuiet)
|
|
{
|
|
wprintf(
|
|
L"%ws: %u\n",
|
|
myLoadResourceString(IDS_DUMP_PKCS7_SIGNCERT), // "Signing Certificate Index"
|
|
iElement);
|
|
}
|
|
hr = cuVerifyCertContext(
|
|
pcc,
|
|
hStore,
|
|
0, // cApplicationPolicies
|
|
NULL, // apszApplicationPolicies
|
|
0, // cIssuancePolicies
|
|
NULL, // apszIssuancePolicies
|
|
FALSE, // fNTAuth
|
|
&VerifyState);
|
|
_PrintIfError(hr, "cuVerifyCertContext");
|
|
|
|
CertFreeCertificateContext(pcc);
|
|
pcc = NULL;
|
|
}
|
|
}
|
|
|
|
hr = cuDumpCMSSignerInfo(
|
|
pcsi,
|
|
i,
|
|
fQuiet,
|
|
idVerify,
|
|
hStore,
|
|
pbHashUserCert,
|
|
pcbHashUserCert);
|
|
_PrintIfError(hr, "cuDumpCMSSignerInfo");
|
|
|
|
cb = sizeof(abHash);
|
|
if (!CryptMsgGetParam(
|
|
hMsg,
|
|
CMSG_COMPUTED_HASH_PARAM,
|
|
0,
|
|
abHash,
|
|
&cb))
|
|
{
|
|
hr = myHLastError();
|
|
_PrintError(hr, "CryptMsgGetParam(computed hash)");
|
|
}
|
|
else
|
|
{
|
|
wprintf(wszNewLine);
|
|
hr = DumpHash(
|
|
NULL,
|
|
IDS_FORMAT_COMPUTED_HASH_COLON, // "Computed Hash%ws: %ws"
|
|
NULL,
|
|
g_wszEmpty,
|
|
abHash,
|
|
cb);
|
|
_JumpIfError(hr, error, "DumpHash");
|
|
}
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
if (NULL != pRequest)
|
|
{
|
|
LocalFree(pRequest);
|
|
}
|
|
if (NULL != pcsi)
|
|
{
|
|
LocalFree(pcsi);
|
|
}
|
|
if (NULL != pcc)
|
|
{
|
|
CertFreeCertificateContext(pcc);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
cuDumpRecipientCertHash(
|
|
IN CERT_INFO const *pci,
|
|
IN HCERTSTORE hStore)
|
|
{
|
|
HRESULT hr;
|
|
CERT_CONTEXT const *pcc = NULL;
|
|
CERT_ID CertId;
|
|
|
|
CSASSERT(NULL != hStore);
|
|
|
|
CertId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
|
|
CertId.IssuerSerialNumber.Issuer = pci->Issuer;
|
|
CertId.IssuerSerialNumber.SerialNumber = pci->SerialNumber;
|
|
|
|
pcc = CertFindCertificateInStore(
|
|
hStore,
|
|
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
|
|
0, // dwFindFlags
|
|
CERT_FIND_CERT_ID,
|
|
&CertId,
|
|
NULL);
|
|
if (NULL == pcc)
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, error, "CertFindCertificateInStore");
|
|
}
|
|
hr = cuDisplayHash(g_wszPad4, pcc, NULL, CERT_SHA1_HASH_PROP_ID, L"sha1");
|
|
_JumpIfError(hr, error, "cuDisplayHash");
|
|
|
|
error:
|
|
if (NULL != pcc)
|
|
{
|
|
CertFreeCertificateContext(pcc);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
cuDumpRecipients(
|
|
IN HCRYPTMSG hMsg,
|
|
OPTIONAL IN HCERTSTORE hStoreWrapper,
|
|
IN DWORD cRecipient,
|
|
IN BOOL fQuiet)
|
|
{
|
|
HRESULT hr;
|
|
DWORD i;
|
|
CERT_INFO *pci = NULL;
|
|
DWORD cb;
|
|
|
|
if (!fQuiet)
|
|
{
|
|
if (0 == cRecipient)
|
|
{
|
|
wprintf(myLoadResourceString(IDS_DUMP_PKCS7_NO_RECIPIENT));
|
|
wprintf(wszNewLine);
|
|
}
|
|
else
|
|
{
|
|
wprintf(
|
|
L"%ws: %d\n",
|
|
myLoadResourceString(IDS_DUMP_PKCS7_RECIPIENT_COUNT),
|
|
cRecipient);
|
|
}
|
|
}
|
|
for (i = 0; i < cRecipient; i++)
|
|
{
|
|
if (NULL != pci)
|
|
{
|
|
LocalFree(pci);
|
|
pci = NULL;
|
|
}
|
|
hr = myCryptMsgGetParam(
|
|
hMsg,
|
|
CMSG_RECIPIENT_INFO_PARAM,
|
|
i,
|
|
CERTLIB_USE_LOCALALLOC,
|
|
(VOID **) &pci,
|
|
&cb);
|
|
_JumpIfError(hr, error, "myCryptMsgGetParam");
|
|
|
|
wprintf(wszNewLine);
|
|
wprintf(
|
|
L"%ws[%u]:\n",
|
|
myLoadResourceString(IDS_RECIPIENT_INFO), // "Recipient Info"
|
|
i);
|
|
|
|
hr = cuDumpIssuerSerialAndSubject(
|
|
&pci->Issuer,
|
|
&pci->SerialNumber,
|
|
NULL, // pSubject
|
|
hStoreWrapper);
|
|
_JumpIfError(hr, error, "cuDumpIssuerSerialAndSubject(Recipient)");
|
|
|
|
if (NULL != hStoreWrapper)
|
|
{
|
|
hr = cuDumpRecipientCertHash(pci, hStoreWrapper);
|
|
_PrintIfError(hr, "cuDumpRecipientCertHash");
|
|
}
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
if (NULL != pci)
|
|
{
|
|
LocalFree(pci);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
OpenCAXchgMemoryStore(
|
|
OUT HCERTSTORE *phStore)
|
|
{
|
|
HRESULT hr;
|
|
WCHAR const *pwszConfig = g_pwszConfig;
|
|
BSTR strConfig = NULL;
|
|
DISPATCHINTERFACE diRequest;
|
|
BSTR strCert = NULL;
|
|
HCERTSTORE hStore = NULL;
|
|
|
|
if (NULL == pwszConfig)
|
|
{
|
|
hr = ConfigGetConfig(g_DispatchFlags, CC_LOCALACTIVECONFIG, &strConfig);
|
|
_JumpIfError(hr, error, "ConfigGetConfig");
|
|
|
|
pwszConfig = strConfig;
|
|
}
|
|
|
|
hr = Request_Init(g_DispatchFlags, &diRequest);
|
|
_JumpIfError(hr, error, "Request_Init");
|
|
|
|
hr = Request2_GetCAProperty(
|
|
&diRequest,
|
|
pwszConfig,
|
|
CR_PROP_CAXCHGCERT,
|
|
MAXDWORD, // PropIndex
|
|
PROPTYPE_BINARY,
|
|
CR_OUT_BINARY,
|
|
&strCert);
|
|
_JumpIfError(hr, error, "Request2_GetCAProperty");
|
|
|
|
hStore = CertOpenStore(
|
|
CERT_STORE_PROV_MEMORY,
|
|
X509_ASN_ENCODING,
|
|
NULL,
|
|
0,
|
|
NULL);
|
|
if (NULL == hStore)
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, error, "CertOpenStore");
|
|
}
|
|
|
|
// Add as encoded blob to avoid all properties, key prov info, etc.
|
|
|
|
if (!CertAddEncodedCertificateToStore(
|
|
hStore,
|
|
X509_ASN_ENCODING,
|
|
(BYTE *) strCert,
|
|
SysStringByteLen(strCert),
|
|
CERT_STORE_ADD_REPLACE_EXISTING,
|
|
NULL)) // ppCertContext
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, error, "CertAddEncodedCertificateToStore");
|
|
}
|
|
*phStore = hStore;
|
|
hStore = NULL;
|
|
hr = S_OK;
|
|
|
|
error:
|
|
if (NULL != hStore)
|
|
{
|
|
CertCloseStore(hStore, CERT_CLOSE_STORE_CHECK_FLAG);
|
|
}
|
|
if (NULL != strCert)
|
|
{
|
|
SysFreeString(strCert);
|
|
}
|
|
Request_Release(&diRequest);
|
|
if (NULL != strConfig)
|
|
{
|
|
SysFreeString(strConfig);
|
|
}
|
|
return(hr);
|
|
|
|
}
|
|
|
|
|
|
HRESULT
|
|
OpenNamedStore(
|
|
IN BOOL fUserStore,
|
|
IN WCHAR const *pwszStoreName,
|
|
OUT HCERTSTORE *phStore)
|
|
{
|
|
HRESULT hr;
|
|
|
|
*phStore = CertOpenStore(
|
|
CERT_STORE_PROV_SYSTEM_W,
|
|
X509_ASN_ENCODING,
|
|
NULL, // hProv
|
|
CERT_STORE_OPEN_EXISTING_FLAG |
|
|
CERT_STORE_READONLY_FLAG |
|
|
CERT_STORE_ENUM_ARCHIVED_FLAG |
|
|
(fUserStore?
|
|
CERT_SYSTEM_STORE_CURRENT_USER :
|
|
CERT_SYSTEM_STORE_LOCAL_MACHINE),
|
|
pwszStoreName);
|
|
if (NULL == *phStore)
|
|
{
|
|
hr = myHLastError();
|
|
_JumpErrorStr2(
|
|
hr,
|
|
error,
|
|
"CertOpenStore",
|
|
pwszStoreName,
|
|
HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
cuCryptDecryptMessageFromCert(
|
|
IN CERT_CONTEXT const *pcc,
|
|
IN BYTE const *pbIn,
|
|
IN DWORD cbIn,
|
|
OUT DWORD *pdwKeySpecFound,
|
|
OUT BYTE **ppbDecrypted,
|
|
OUT DWORD *pcbDecrypted)
|
|
{
|
|
HRESULT hr;
|
|
HCERTSTORE hStore = NULL;
|
|
CERT_CONTEXT const *pccStore = NULL;
|
|
CERT_KEY_CONTEXT ckc;
|
|
HCRYPTPROV hProv = NULL;
|
|
DWORD dwKeySpec;
|
|
CRYPT_KEY_PROV_INFO *pkpi = NULL;
|
|
DWORD dwTickCount = GetTickCount();
|
|
|
|
*pdwKeySpecFound = 0;
|
|
hStore = CertOpenStore(
|
|
CERT_STORE_PROV_MEMORY,
|
|
X509_ASN_ENCODING,
|
|
NULL,
|
|
0,
|
|
NULL);
|
|
if (NULL == hStore)
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, error, "CertOpenStore");
|
|
}
|
|
|
|
// Add as encoded blob to avoid all properties, key prov info, etc.
|
|
|
|
if (!CertAddEncodedCertificateToStore(
|
|
hStore,
|
|
X509_ASN_ENCODING,
|
|
pcc->pbCertEncoded,
|
|
pcc->cbCertEncoded,
|
|
CERT_STORE_ADD_REPLACE_EXISTING,
|
|
&pccStore)) // ppCertContext
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, error, "CertAddEncodedCertificateToStore");
|
|
}
|
|
hr = myCertGetKeyProviderInfo(pcc, &pkpi);
|
|
_PrintIfError2(hr, "myCertGetKeyProviderInfo", CRYPT_E_NOT_FOUND);
|
|
if (S_OK == hr)
|
|
{
|
|
DBGPRINT((
|
|
s_DbgSsRecoveryTrace,
|
|
"Original KeyProvInfo: container=%ws, type=%x, prov=%ws, KeySpec=%x, f=%x\n",
|
|
pkpi->pwszContainerName,
|
|
pkpi->dwProvType,
|
|
pkpi->pwszProvName,
|
|
pkpi->dwKeySpec,
|
|
pkpi->dwFlags));
|
|
}
|
|
else if (!g_fForce)
|
|
{
|
|
_JumpError2(hr, error, "myCertGetKeyProviderInfo", CRYPT_E_NOT_FOUND);
|
|
}
|
|
DBGPRINT((
|
|
s_DbgSsRecoveryTrace,
|
|
"Before CryptAcquireCertificatePrivateKey: Ticks=%u\n",
|
|
GetTickCount() - dwTickCount));
|
|
|
|
if (!CryptAcquireCertificatePrivateKey(
|
|
pcc,
|
|
0, // dwFlags
|
|
NULL, // pvReserved
|
|
&hProv,
|
|
&dwKeySpec,
|
|
NULL)) // pfCallerFreeProv
|
|
{
|
|
hr = myHLastError();
|
|
_PrintError2(
|
|
hr,
|
|
"CryptAcquireCertificatePrivateKey",
|
|
CRYPT_E_NO_KEY_PROPERTY);
|
|
|
|
DBGPRINT((
|
|
s_DbgSsRecoveryTrace,
|
|
"Before CryptFindCertificateKeyProvInfo: Ticks=%u\n",
|
|
GetTickCount() - dwTickCount));
|
|
|
|
if (!CryptFindCertificateKeyProvInfo(pcc, 0, NULL))
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError2(
|
|
hr,
|
|
error,
|
|
"CryptFindCertificateKeyProvInfo",
|
|
HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
|
|
}
|
|
if (NULL != pkpi)
|
|
{
|
|
LocalFree(pkpi);
|
|
pkpi = NULL;
|
|
}
|
|
|
|
hr = myCertGetKeyProviderInfo(pcc, &pkpi);
|
|
_JumpIfError(hr, error, "myCertGetKeyProviderInfo");
|
|
|
|
DBGPRINT((
|
|
s_DbgSsRecoveryTrace,
|
|
"Constructed KeyProvInfo: container=%ws, type=%x, prov=%ws, KeySpec=%x, f=%x\n",
|
|
pkpi->pwszContainerName,
|
|
pkpi->dwProvType,
|
|
pkpi->pwszProvName,
|
|
pkpi->dwKeySpec,
|
|
pkpi->dwFlags));
|
|
dwKeySpec = pkpi->dwKeySpec;
|
|
|
|
DBGPRINT((
|
|
s_DbgSsRecoveryTrace,
|
|
"Before CryptAcquireContext: Ticks=%u\n",
|
|
GetTickCount() - dwTickCount));
|
|
|
|
if (!CryptAcquireContext(
|
|
&hProv,
|
|
pkpi->pwszContainerName,
|
|
pkpi->pwszProvName,
|
|
pkpi->dwProvType,
|
|
pkpi->dwFlags))
|
|
{
|
|
hr = myHLastError();
|
|
_JumpErrorStr(
|
|
hr,
|
|
error,
|
|
"CryptAcquireContext",
|
|
pkpi->pwszContainerName);
|
|
}
|
|
}
|
|
ZeroMemory(&ckc, sizeof(ckc));
|
|
ckc.cbSize = sizeof(ckc);
|
|
ckc.dwKeySpec = dwKeySpec;
|
|
ckc.hCryptProv = hProv;
|
|
|
|
*pdwKeySpecFound = dwKeySpec;
|
|
|
|
DBGPRINT((
|
|
s_DbgSsRecoveryTrace,
|
|
"Before CertSetCertificateContextProperty: Ticks=%u\n",
|
|
GetTickCount() - dwTickCount));
|
|
|
|
if (!CertSetCertificateContextProperty(
|
|
pccStore,
|
|
CERT_KEY_CONTEXT_PROP_ID,
|
|
CERT_STORE_NO_CRYPT_RELEASE_FLAG,
|
|
&ckc))
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, error, "CertSetCertificateContextProperty");
|
|
}
|
|
|
|
DBGPRINT((
|
|
s_DbgSsRecoveryTrace,
|
|
"Before myCryptDecryptMessage: Ticks=%u\n",
|
|
GetTickCount() - dwTickCount));
|
|
|
|
hr = myCryptDecryptMessage(
|
|
hStore,
|
|
pbIn,
|
|
cbIn,
|
|
CERTLIB_USE_LOCALALLOC,
|
|
ppbDecrypted,
|
|
pcbDecrypted);
|
|
_JumpIfError(hr, error, "myCryptDecryptMessage");
|
|
|
|
DBGPRINT((
|
|
s_DbgSsRecoveryTrace,
|
|
"After myCryptDecryptMessage: Ticks=%u\n",
|
|
GetTickCount() - dwTickCount));
|
|
|
|
error:
|
|
if (S_OK != hr)
|
|
{
|
|
DBGPRINT((
|
|
s_DbgSsRecoveryTrace,
|
|
"Skipped myCryptDecryptMessage(%x): Ticks=%u\n",
|
|
hr,
|
|
GetTickCount() - dwTickCount));
|
|
}
|
|
|
|
if (NULL != pkpi)
|
|
{
|
|
LocalFree(pkpi);
|
|
}
|
|
if (NULL != pccStore)
|
|
{
|
|
CertFreeCertificateContext(pccStore);
|
|
}
|
|
if (NULL != hStore)
|
|
{
|
|
CertCloseStore(hStore, CERT_CLOSE_STORE_CHECK_FLAG);
|
|
}
|
|
if (NULL != hProv)
|
|
{
|
|
CryptReleaseContext(hProv, 0);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
// Attempt to find any one recipient cert with a usable private key in the
|
|
// following locations:
|
|
// - the next outer PKCS7 store (hStoreWrapper parameter)
|
|
// - the PKCS7 store (hStorePKCS7 parameter)
|
|
// - the local machine's current CA Exchange cert
|
|
// - the HKLM KRA store
|
|
// - the HKLM MY store
|
|
// - the HKCU MY store
|
|
|
|
HRESULT
|
|
cuDumpEncryptedAsnBinary(
|
|
IN HCRYPTMSG hMsg,
|
|
IN DWORD cRecipient,
|
|
IN DWORD RecipientIndex,
|
|
OPTIONAL IN HCERTSTORE hStoreWrapper,
|
|
IN HCERTSTORE hStorePKCS7,
|
|
IN BYTE const *pbIn,
|
|
IN DWORD cbIn,
|
|
IN BOOL fQuiet,
|
|
OPTIONAL OUT BYTE **ppbDecrypted,
|
|
OPTIONAL OUT DWORD *pcbDecrypted)
|
|
{
|
|
HRESULT hr;
|
|
HCERTSTORE ahStore[6];
|
|
WCHAR *apwszStore[6];
|
|
DWORD cStore = 0;
|
|
DWORD iRecipient;
|
|
DWORD iStore;
|
|
DWORD cb;
|
|
CERT_INFO *pci = NULL;
|
|
CERT_CONTEXT const *pcc = NULL;
|
|
BOOL fDecrypted = FALSE;
|
|
BYTE *pbDecrypted = NULL;
|
|
DWORD cbDecrypted;
|
|
DWORD dwKeySpecFound;
|
|
BOOL fSignatureKey = FALSE;
|
|
BOOL fExchangeKey = FALSE;
|
|
DWORD dwTickCount = GetTickCount();
|
|
|
|
if (NULL != ppbDecrypted)
|
|
{
|
|
*ppbDecrypted = NULL;
|
|
}
|
|
if (NULL != pcbDecrypted)
|
|
{
|
|
*pcbDecrypted = 0;
|
|
}
|
|
s_DbgSsRecoveryTrace = g_fVerbose? DBG_SS_CERTUTIL : DBG_SS_CERTUTILI;
|
|
hr = OpenNamedStore(TRUE, wszMY_CERTSTORE, &ahStore[cStore]);
|
|
if (S_OK == hr)
|
|
{
|
|
apwszStore[cStore] = L"HKCU MY";
|
|
cStore++;
|
|
}
|
|
hr = OpenNamedStore(FALSE, wszMY_CERTSTORE, &ahStore[cStore]);
|
|
if (S_OK == hr)
|
|
{
|
|
apwszStore[cStore] = L"HKLM MY";
|
|
cStore++;
|
|
}
|
|
if (NULL != hStoreWrapper)
|
|
{
|
|
apwszStore[cStore] = L"PKCS7 Wrapper";
|
|
ahStore[cStore++] = hStoreWrapper;
|
|
}
|
|
if (NULL != hStorePKCS7)
|
|
{
|
|
apwszStore[cStore] = L"PKCS7";
|
|
ahStore[cStore++] = hStorePKCS7;
|
|
}
|
|
hr = OpenCAXchgMemoryStore(&ahStore[cStore]);
|
|
if (S_OK == hr)
|
|
{
|
|
apwszStore[cStore] = L"CAXchgMemory";
|
|
cStore++;
|
|
}
|
|
hr = OpenNamedStore(FALSE, wszKRA_CERTSTORE, &ahStore[cStore]);
|
|
if (S_OK == hr)
|
|
{
|
|
apwszStore[cStore] = L"HKLM KRA";
|
|
cStore++;
|
|
}
|
|
|
|
for (iRecipient = 0; !fDecrypted && iRecipient < cRecipient; iRecipient++)
|
|
{
|
|
CERT_ID CertId;
|
|
|
|
if (MAXDWORD != RecipientIndex && iRecipient != RecipientIndex)
|
|
{
|
|
continue;
|
|
}
|
|
if (NULL != pci)
|
|
{
|
|
LocalFree(pci);
|
|
pci = NULL;
|
|
}
|
|
hr = myCryptMsgGetParam(
|
|
hMsg,
|
|
CMSG_RECIPIENT_INFO_PARAM,
|
|
iRecipient,
|
|
CERTLIB_USE_LOCALALLOC,
|
|
(VOID **) &pci,
|
|
&cb);
|
|
_JumpIfError(hr, error, "myCryptMsgGetParam");
|
|
|
|
CertId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
|
|
CertId.IssuerSerialNumber.Issuer = pci->Issuer;
|
|
CertId.IssuerSerialNumber.SerialNumber = pci->SerialNumber;
|
|
|
|
for (iStore = 0; !fDecrypted && iStore < cStore; iStore++)
|
|
{
|
|
if (NULL != pcc)
|
|
{
|
|
CertFreeCertificateContext(pcc);
|
|
pcc = NULL;
|
|
}
|
|
while (TRUE)
|
|
{
|
|
pcc = CertFindCertificateInStore(
|
|
ahStore[iStore],
|
|
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
|
|
0, // dwFindFlags
|
|
CERT_FIND_CERT_ID,
|
|
&CertId,
|
|
pcc);
|
|
if (NULL == pcc)
|
|
{
|
|
hr = myHLastError();
|
|
_PrintError2(hr, "CertFindCertificateInStore", hr);
|
|
break;
|
|
}
|
|
{
|
|
WCHAR *pwsz;
|
|
|
|
pwsz = NULL;
|
|
hr = myCertNameToStr(
|
|
X509_ASN_ENCODING,
|
|
&pcc->pCertInfo->Subject,
|
|
CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG,
|
|
&pwsz);
|
|
_PrintIfError(hr, "myCertNameToStr");
|
|
DBGPRINT((
|
|
s_DbgSsRecoveryTrace,
|
|
"================================================\n"));
|
|
|
|
DBGPRINT((
|
|
s_DbgSsRecoveryTrace,
|
|
"Found Recipient[%u] in %ws -- ahStore[%u of %u]: %ws\n",
|
|
iRecipient,
|
|
apwszStore[iStore],
|
|
iStore,
|
|
cStore,
|
|
pwsz));
|
|
if (NULL != pwsz)
|
|
{
|
|
LocalFree(pwsz);
|
|
}
|
|
}
|
|
if (g_fVerbose)
|
|
{
|
|
wprintf(wszNewLine);
|
|
wprintf(
|
|
L"%ws[%u]:\n",
|
|
myLoadResourceString(IDS_RECIPIENT_INFO), // "Recipient Info"
|
|
iRecipient);
|
|
hr = cuDumpIssuerSerialAndSubject(
|
|
&pci->Issuer,
|
|
&pci->SerialNumber,
|
|
&pcc->pCertInfo->Subject,
|
|
NULL); // hStore
|
|
_JumpIfError(hr, error, "cuDumpIssuerSerialAndSubject(Recipient)");
|
|
}
|
|
|
|
hr = cuCryptDecryptMessageFromCert(
|
|
pcc,
|
|
pbIn,
|
|
cbIn,
|
|
&dwKeySpecFound,
|
|
&pbDecrypted,
|
|
&cbDecrypted);
|
|
_PrintIfError2(
|
|
hr,
|
|
"cuCryptDecryptMessageFromCert",
|
|
HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
|
|
{
|
|
DBGPRINT((
|
|
s_DbgSsRecoveryTrace,
|
|
"cuCryptDecryptMessageFromCert(Recipient[%u]): %x\n",
|
|
iRecipient,
|
|
hr));
|
|
}
|
|
|
|
if (AT_SIGNATURE == dwKeySpecFound)
|
|
{
|
|
fSignatureKey = TRUE;
|
|
}
|
|
else if (AT_KEYEXCHANGE == dwKeySpecFound)
|
|
{
|
|
fExchangeKey = TRUE;
|
|
}
|
|
if (S_OK != hr)
|
|
{
|
|
DBGPRINT((
|
|
s_DbgSsRecoveryTrace,
|
|
"cuDumpEncryptedAsnBinary failed(%x): Ticks=%u\n",
|
|
hr,
|
|
GetTickCount() - dwTickCount));
|
|
continue;
|
|
}
|
|
wprintf(myLoadResourceString(IDS_DUMP_DECRYPTED)); // "Decrypted PKCS7 Content"
|
|
wprintf(wszNewLine);
|
|
hr = DumpAsnBlob(
|
|
NULL,
|
|
fQuiet,
|
|
pbDecrypted,
|
|
cbDecrypted,
|
|
MAXDWORD);
|
|
_PrintIfError(hr, "DumpAsnBlob(decrypted content)");
|
|
if (S_OK == hr)
|
|
{
|
|
fDecrypted = TRUE;
|
|
if (NULL != ppbDecrypted)
|
|
{
|
|
*ppbDecrypted = pbDecrypted;
|
|
pbDecrypted = NULL;
|
|
}
|
|
if (NULL != pcbDecrypted)
|
|
{
|
|
*pcbDecrypted = cbDecrypted;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
DBGPRINT((
|
|
s_DbgSsRecoveryTrace,
|
|
"cuDumpEncryptedAsnBinary end(fDecrypted=%d): Ticks=%u\n",
|
|
fDecrypted,
|
|
GetTickCount() - dwTickCount));
|
|
if (!fDecrypted)
|
|
{
|
|
if (fSignatureKey && !fExchangeKey)
|
|
{
|
|
wprintf(myLoadResourceString(IDS_SIGNATURE_NOTKEYEXCHANGE)); // "Found AT_SIGNATURE key but no AT_KEYEXCHANGE key"
|
|
wprintf(wszNewLine);
|
|
}
|
|
hr = CRYPT_E_NO_DECRYPT_CERT;
|
|
_JumpError(hr, error, "No decryption key");
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
if (NULL != pbDecrypted)
|
|
{
|
|
LocalFree(pbDecrypted);
|
|
}
|
|
if (NULL != pci)
|
|
{
|
|
LocalFree(pci);
|
|
}
|
|
if (NULL != pcc)
|
|
{
|
|
CertFreeCertificateContext(pcc);
|
|
}
|
|
for (iStore = 0; iStore < cStore; iStore++)
|
|
{
|
|
if (NULL != ahStore[iStore] &&
|
|
hStoreWrapper != ahStore[iStore] &&
|
|
hStorePKCS7 != ahStore[iStore])
|
|
{
|
|
CertCloseStore(ahStore[iStore], CERT_CLOSE_STORE_CHECK_FLAG);
|
|
}
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
dumpPKCS7(
|
|
OPTIONAL IN HCERTSTORE hStoreWrapper,
|
|
IN BYTE const *pbIn,
|
|
IN DWORD cbIn)
|
|
{
|
|
HRESULT hr;
|
|
BYTE *pbContents = NULL;
|
|
DWORD cbContents;
|
|
HCERTSTORE hStore = NULL;
|
|
CERT_CONTEXT const *pCert = NULL;
|
|
CRL_CONTEXT const *pCRL = NULL;
|
|
HCRYPTMSG hMsg = NULL;
|
|
CRYPT_ATTRIBUTES *pAttrib = NULL;
|
|
BOOL fDisplayed;
|
|
DWORD iElement;
|
|
DWORD cSigner;
|
|
DWORD cRecipient;
|
|
DWORD cb;
|
|
DWORD dwMsgType;
|
|
DWORD dwMsgVersion;
|
|
char *pszInnerContentObjId = NULL;
|
|
WCHAR const *pwsz;
|
|
WCHAR const *pwszVersion;
|
|
UINT idsType = IDS_DUMP_PKCS7;
|
|
|
|
hr = myDecodePKCS7(
|
|
pbIn,
|
|
cbIn,
|
|
&pbContents,
|
|
&cbContents,
|
|
&dwMsgType,
|
|
&pszInnerContentObjId,
|
|
&cSigner,
|
|
&cRecipient,
|
|
&hStore,
|
|
&hMsg);
|
|
_JumpIfError2(hr, error, "myDecodePKCS7", CRYPT_E_ASN1_BADTAG);
|
|
|
|
cb = sizeof(dwMsgVersion);
|
|
if (!CryptMsgGetParam(
|
|
hMsg,
|
|
CMSG_VERSION_PARAM,
|
|
0,
|
|
&dwMsgVersion,
|
|
&cb))
|
|
{
|
|
hr = myHLastError();
|
|
_PrintError(hr, "CryptMsgGetParam(version)");
|
|
dwMsgVersion = MAXDWORD;
|
|
}
|
|
|
|
pwszVersion = NULL;
|
|
switch (dwMsgType)
|
|
{
|
|
case CMSG_DATA:
|
|
pwsz = L"CMSG_DATA";
|
|
break;
|
|
|
|
case CMSG_ENVELOPED:
|
|
pwsz = L"CMSG_ENVELOPED";
|
|
switch (dwMsgVersion)
|
|
{
|
|
case CMSG_ENVELOPED_DATA_PKCS_1_5_VERSION:
|
|
pwszVersion = L"CMSG_ENVELOPED_DATA_PKCS_1_5_VERSION";
|
|
break;
|
|
|
|
case CMSG_ENVELOPED_DATA_CMS_VERSION:
|
|
pwszVersion = L"CMSG_ENVELOPED_DATA_CMS_VERSION";
|
|
idsType = IDS_DUMP_PKCS7CMS;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case CMSG_HASHED:
|
|
pwsz = L"CMSG_HASHED";
|
|
switch (dwMsgVersion)
|
|
{
|
|
case CMSG_HASHED_DATA_PKCS_1_5_VERSION:
|
|
pwszVersion = L"CMSG_HASHED_DATA_PKCS_1_5_VERSION";
|
|
break;
|
|
|
|
case CMSG_HASHED_DATA_CMS_VERSION:
|
|
pwszVersion = L"CMSG_HASHED_DATA_CMS_VERSION";
|
|
idsType = IDS_DUMP_PKCS7CMS;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case CMSG_SIGNED:
|
|
pwsz = L"CMSG_SIGNED";
|
|
switch (dwMsgVersion)
|
|
{
|
|
case CMSG_SIGNED_DATA_PKCS_1_5_VERSION:
|
|
pwszVersion = L"CMSG_SIGNED_DATA_PKCS_1_5_VERSION";
|
|
break;
|
|
|
|
case CMSG_SIGNED_DATA_CMS_VERSION:
|
|
pwszVersion = L"CMSG_SIGNED_DATA_CMS_VERSION";
|
|
idsType = IDS_DUMP_PKCS7CMS;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case CMSG_SIGNED_AND_ENVELOPED:
|
|
pwsz = L"CMSG_SIGNED_AND_ENVELOPED";
|
|
break;
|
|
|
|
default:
|
|
pwsz = myLoadResourceString(IDS_QUESTIONMARKS); // "???"
|
|
break;
|
|
}
|
|
|
|
wprintf(myLoadResourceString(idsType));
|
|
wprintf(wszNewLine);
|
|
|
|
wprintf(L" %ws(%u)\n", pwsz, dwMsgType);
|
|
if (NULL != pwszVersion)
|
|
{
|
|
wprintf(L" %ws(%u)\n", pwszVersion, dwMsgVersion);
|
|
}
|
|
if (NULL != pszInnerContentObjId)
|
|
{
|
|
wprintf(
|
|
L" %ws: ",
|
|
myLoadResourceString(IDS_DUMP_PKCS7_CONTENT_TYPE));
|
|
cuDumpOIDAndDescriptionA(pszInnerContentObjId);
|
|
wprintf(wszNewLine);
|
|
}
|
|
wprintf(wszNewLine);
|
|
|
|
if (NULL == pbContents)
|
|
{
|
|
wprintf(myLoadResourceString(IDS_DUMP_PKCS7_NO_CONTENT));
|
|
wprintf(wszNewLine);
|
|
}
|
|
else
|
|
{
|
|
wprintf(myLoadResourceString(IDS_DUMP_PKCS7_CONTENTS)); // "PKCS7 Message Content:"
|
|
wprintf(wszNewLine);
|
|
|
|
fDisplayed = FALSE;
|
|
if (CMSG_ENVELOPED != dwMsgType)
|
|
{
|
|
hr = DumpAsnBlob(hStore, FALSE, pbContents, cbContents, MAXDWORD);
|
|
_PrintIfError(hr, "DumpAsnBlob(content)");
|
|
fDisplayed = TRUE;
|
|
}
|
|
else if (NULL != hMsg && 0 != cRecipient)
|
|
{
|
|
hr = cuDumpEncryptedAsnBinary(
|
|
hMsg,
|
|
cRecipient,
|
|
MAXDWORD, // RecipientIndex
|
|
hStoreWrapper,
|
|
hStore,
|
|
pbIn,
|
|
cbIn,
|
|
FALSE,
|
|
NULL,
|
|
NULL);
|
|
_PrintIfError(hr, "cuDumpEncryptedAsnBinary");
|
|
if (S_OK == hr)
|
|
{
|
|
fDisplayed = TRUE;
|
|
}
|
|
}
|
|
if (!fDisplayed)
|
|
{
|
|
DumpHex(0, pbContents, cbContents);
|
|
}
|
|
}
|
|
wprintf(wszNewLine);
|
|
|
|
if (NULL != hMsg)
|
|
{
|
|
BYTE abHash[CBMAX_CRYPT_HASH_LEN];
|
|
|
|
hr = cuDumpSigners(
|
|
hMsg,
|
|
pszInnerContentObjId,
|
|
hStore,
|
|
cSigner,
|
|
NULL == pbContents, // fContentEmpty
|
|
FALSE, // fVerifyOnly
|
|
NULL, // pbHashUserCert
|
|
NULL); // pcbHashUserCert
|
|
_JumpIfError(hr, error, "cuDumpSigners");
|
|
|
|
hr = cuDumpRecipients(hMsg, hStoreWrapper, cRecipient, FALSE);
|
|
_JumpIfError(hr, error, "cuDumpRecipients");
|
|
|
|
cb = sizeof(abHash);
|
|
if (!CryptMsgGetParam(
|
|
hMsg,
|
|
CMSG_HASH_DATA_PARAM,
|
|
0,
|
|
abHash,
|
|
&cb))
|
|
{
|
|
hr = myHLastError();
|
|
_PrintError2(hr, "CryptMsgGetParam(stored hash)", CRYPT_E_INVALID_MSG_TYPE);
|
|
}
|
|
else
|
|
{
|
|
hr = DumpHash(
|
|
NULL,
|
|
IDS_FORMAT_STORED_HASH_COLON, // "Stored Hash%ws: %ws"
|
|
NULL,
|
|
g_wszEmpty,
|
|
abHash,
|
|
cb);
|
|
_JumpIfError(hr, error, "DumpHash");
|
|
}
|
|
wprintf(wszNewLine);
|
|
}
|
|
|
|
fDisplayed = FALSE;
|
|
if (NULL != hStore)
|
|
{
|
|
CSASSERT(NULL == pCert);
|
|
for (iElement = 0; ; iElement++)
|
|
{
|
|
pCert = CertEnumCertificatesInStore(hStore, pCert);
|
|
if (NULL == pCert)
|
|
{
|
|
break;
|
|
}
|
|
if (!fDisplayed)
|
|
{
|
|
wprintf(myLoadResourceString(IDS_DUMP_PKCS7_CERTIFICATES));
|
|
wprintf(wszNewLine);
|
|
fDisplayed = TRUE;
|
|
}
|
|
hr = cuDumpAsnBinary(
|
|
pCert->pbCertEncoded,
|
|
pCert->cbCertEncoded,
|
|
iElement);
|
|
_JumpIfError(hr, error, "cuDumpAsnBinary");
|
|
}
|
|
}
|
|
if (!fDisplayed)
|
|
{
|
|
wprintf(myLoadResourceString(IDS_DUMP_PKCS7_NO_CERTIFICATES));
|
|
wprintf(wszNewLine);
|
|
}
|
|
|
|
fDisplayed = FALSE;
|
|
if (NULL != hStore)
|
|
{
|
|
CSASSERT(NULL == pCRL);
|
|
for (iElement = 0; ; iElement++)
|
|
{
|
|
pCRL = CertEnumCRLsInStore(hStore, pCRL);
|
|
if (NULL == pCRL)
|
|
{
|
|
break;
|
|
}
|
|
if (!fDisplayed)
|
|
{
|
|
wprintf(myLoadResourceString(IDS_DUMP_PKCS7_CRLS));
|
|
wprintf(wszNewLine);
|
|
fDisplayed = TRUE;
|
|
}
|
|
hr = cuDumpAsnBinary(
|
|
pCRL->pbCrlEncoded,
|
|
pCRL->cbCrlEncoded,
|
|
iElement);
|
|
_JumpIfError(hr, error, "cuDumpAsnBinary");
|
|
}
|
|
}
|
|
if (!fDisplayed)
|
|
{
|
|
wprintf(myLoadResourceString(IDS_DUMP_PKCS7_NO_CRLS));
|
|
wprintf(wszNewLine);
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
if (NULL != pszInnerContentObjId)
|
|
{
|
|
LocalFree(pszInnerContentObjId);
|
|
}
|
|
if (NULL != pAttrib)
|
|
{
|
|
LocalFree(pAttrib);
|
|
}
|
|
if (NULL != hMsg)
|
|
{
|
|
CryptMsgClose(hMsg);
|
|
}
|
|
if (NULL != pCRL)
|
|
{
|
|
CertFreeCRLContext(pCRL);
|
|
}
|
|
if (NULL != pCert)
|
|
{
|
|
CertFreeCertificateContext(pCert);
|
|
}
|
|
if (NULL != hStore)
|
|
{
|
|
CertCloseStore(hStore, CERT_CLOSE_STORE_CHECK_FLAG);
|
|
}
|
|
if (NULL != pbContents)
|
|
{
|
|
LocalFree(pbContents);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
GetVersionStuff(
|
|
IN WCHAR const *pwszFileName,
|
|
OUT DWORD *pdwLangRet,
|
|
OUT VS_FIXEDFILEINFO *pvsRet)
|
|
{
|
|
HRESULT hr;
|
|
VOID *pvData = NULL;
|
|
DWORD cbData;
|
|
DWORD dwHandle;
|
|
DWORD *pdwTranslation;
|
|
UINT uLen;
|
|
DWORD dwDefLang = 0x409;
|
|
VS_FIXEDFILEINFO *pvs;
|
|
|
|
cbData = GetFileVersionInfoSize(
|
|
const_cast<WCHAR *>(pwszFileName),
|
|
&dwHandle);
|
|
if (0 == cbData)
|
|
{
|
|
hr = GetLastError();
|
|
if (S_OK == hr)
|
|
{
|
|
hr = ERROR_RESOURCE_DATA_NOT_FOUND;
|
|
}
|
|
goto error;
|
|
}
|
|
|
|
pvData = LocalAlloc(LMEM_FIXED, cbData);
|
|
if (NULL == pvData)
|
|
{
|
|
hr = GetLastError();
|
|
goto error;
|
|
}
|
|
|
|
if (!GetFileVersionInfo(
|
|
const_cast<WCHAR *>(pwszFileName),
|
|
0,
|
|
cbData,
|
|
pvData))
|
|
{
|
|
hr = GetLastError();
|
|
goto error;
|
|
}
|
|
|
|
if (!VerQueryValue(pvData, L"\\VarFileInfo\\Translation", (VOID **) &pdwTranslation, &uLen))
|
|
{
|
|
pdwTranslation = &dwDefLang;
|
|
uLen = sizeof(DWORD);
|
|
}
|
|
|
|
*pdwLangRet = *pdwTranslation;
|
|
|
|
if (!VerQueryValue(pvData, L"\\", (VOID **) &pvs, &uLen))
|
|
{
|
|
hr = GetLastError();
|
|
goto error;
|
|
}
|
|
*pvsRet = *pvs;
|
|
hr = S_OK;
|
|
|
|
error:
|
|
if (NULL != pvData)
|
|
{
|
|
LocalFree(pvData);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
FileVersionDump(
|
|
IN WCHAR const *pwszFileName)
|
|
{
|
|
HRESULT hr;
|
|
DWORD dwLang;
|
|
VS_FIXEDFILEINFO vs;
|
|
|
|
hr = GetVersionStuff(pwszFileName, &dwLang, &vs);
|
|
if (S_OK == hr)
|
|
{
|
|
wprintf(
|
|
myLoadResourceString(IDS_FORMAT_LANG), // "%ws: Lang %08x (%d.%d)"
|
|
pwszFileName,
|
|
dwLang,
|
|
HIWORD(dwLang),
|
|
LOWORD(dwLang));
|
|
|
|
wprintf(
|
|
myLoadResourceString(IDS_FORMAT_FILE), // " File %d.%d:%d.%d"
|
|
HIWORD(vs.dwFileVersionMS),
|
|
LOWORD(vs.dwFileVersionMS),
|
|
HIWORD(vs.dwFileVersionLS),
|
|
LOWORD(vs.dwFileVersionLS));
|
|
|
|
wprintf(
|
|
myLoadResourceString(IDS_FORMAT_PRODUCT), // " Product %d.%d:%d.%d\n"
|
|
HIWORD(vs.dwProductVersionMS),
|
|
LOWORD(vs.dwProductVersionMS),
|
|
HIWORD(vs.dwProductVersionLS),
|
|
LOWORD(vs.dwProductVersionLS));
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
cuFileDump(
|
|
IN WCHAR const *pwszfn)
|
|
{
|
|
HRESULT hr;
|
|
BYTE *pbIn = NULL;
|
|
DWORD cbIn;
|
|
|
|
hr = FileVersionDump(pwszfn);
|
|
if (S_OK == hr)
|
|
{
|
|
goto error;
|
|
}
|
|
hr = EPFFileDump(pwszfn, g_pwszPassword, NULL);
|
|
if (S_FALSE != hr)
|
|
{
|
|
_PrintIfError(hr, "EPFFileDump");
|
|
goto error;
|
|
}
|
|
hr = DecodeFileW(pwszfn, &pbIn, &cbIn, CRYPT_STRING_ANY);
|
|
if (S_OK != hr)
|
|
{
|
|
cuPrintError(IDS_ERR_FORMAT_DECODEFILE, hr);
|
|
goto error;
|
|
}
|
|
CSASSERT(NULL != pbIn);
|
|
|
|
hr = cuDumpAsnBinary(pbIn, cbIn, MAXDWORD);
|
|
if (S_OK != hr)
|
|
{
|
|
cuPrintError(IDS_ERR_FORMAT_CANNOT_DECODE, hr);
|
|
goto error;
|
|
}
|
|
|
|
error:
|
|
if (NULL != pbIn)
|
|
{
|
|
LocalFree(pbIn);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
cuDumpSerial(
|
|
OPTIONAL IN WCHAR const *pwszPrefix,
|
|
IN DWORD idMessage,
|
|
IN CRYPT_INTEGER_BLOB const *pSerial)
|
|
{
|
|
HRESULT hr;
|
|
BSTR strSerial = NULL;
|
|
|
|
hr = MultiByteIntegerToBstr(
|
|
FALSE,
|
|
pSerial->cbData,
|
|
pSerial->pbData,
|
|
&strSerial);
|
|
_JumpIfError(hr, error, "MultiByteIntegerToBstr");
|
|
|
|
if (NULL != pwszPrefix)
|
|
{
|
|
wprintf(pwszPrefix);
|
|
}
|
|
wprintf(myLoadResourceString(idMessage));
|
|
wprintf(L" %ws\n", strSerial);
|
|
|
|
if (g_fVerbose)
|
|
{
|
|
DumpHex(
|
|
DH_MULTIADDRESS | DH_NOTABPREFIX | DH_NOASCIIHEX | 4,
|
|
pSerial->pbData,
|
|
pSerial->cbData);
|
|
}
|
|
|
|
error:
|
|
if (NULL != strSerial)
|
|
{
|
|
SysFreeString(strSerial);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
cuDumpFileTimePeriod(
|
|
IN DWORD idMessage,
|
|
OPTIONAL IN WCHAR const *pwszQuote,
|
|
IN FILETIME const *pftGMT)
|
|
{
|
|
HRESULT hr;
|
|
WCHAR *pwszTimePeriod;
|
|
|
|
hr = myFileTimePeriodToWszTimePeriod(pftGMT, g_fSeconds, &pwszTimePeriod);
|
|
_JumpIfError(hr, error, "myFileTimePeriodToWszTimePeriod");
|
|
|
|
if (NULL == pwszQuote)
|
|
{
|
|
pwszQuote = g_wszEmpty;
|
|
}
|
|
wprintf(L" %ws%ws%ws\n", pwszQuote, pwszTimePeriod, pwszQuote);
|
|
hr = S_OK;
|
|
|
|
error:
|
|
if (NULL != pwszTimePeriod)
|
|
{
|
|
LocalFree(pwszTimePeriod);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
cuDumpFileTime(
|
|
IN DWORD idMessage,
|
|
OPTIONAL IN WCHAR const *pwszQuote,
|
|
IN FILETIME const *pftGMT)
|
|
{
|
|
HRESULT hr;
|
|
WCHAR *pwszDate = NULL;
|
|
WCHAR const *pwszResource = NULL;
|
|
|
|
if (0 != idMessage)
|
|
{
|
|
pwszResource = myLoadResourceString(idMessage);
|
|
}
|
|
if (NULL == pwszResource)
|
|
{
|
|
pwszResource = g_wszEmpty;
|
|
}
|
|
if (NULL == pwszQuote)
|
|
{
|
|
pwszQuote = g_wszEmpty;
|
|
}
|
|
if (0 == pftGMT->dwLowDateTime &&
|
|
0 == pftGMT->dwHighDateTime)
|
|
{
|
|
wprintf(
|
|
L"%ws %ws\n",
|
|
pwszResource,
|
|
myLoadResourceString(IDS_PROP_EMPTY)); // "EMPTY"
|
|
}
|
|
else
|
|
{
|
|
if (g_fGMT)
|
|
{
|
|
hr = myFileTimeToWszTime(pftGMT, g_fSeconds, &pwszDate);
|
|
_JumpIfError(hr, error, "myFileTimeToWszTime");
|
|
}
|
|
else
|
|
{
|
|
hr = myGMTFileTimeToWszLocalTime(pftGMT, g_fSeconds, &pwszDate);
|
|
_JumpIfError(hr, error, "myGMTFileTimeToWszLocalTime");
|
|
}
|
|
wprintf(
|
|
L"%ws %ws%ws%ws%ws%ws\n",
|
|
pwszResource,
|
|
pwszQuote,
|
|
pwszDate,
|
|
g_fGMT? L" " : g_wszEmpty,
|
|
g_fGMT? myLoadResourceString(IDS_GMT_SUFFIX) : g_wszEmpty,
|
|
pwszQuote);
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
if (NULL != pwszDate)
|
|
{
|
|
LocalFree(pwszDate);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
cuDumpFileTimeOrPeriod(
|
|
IN DWORD idMessage,
|
|
OPTIONAL IN WCHAR const *pwszQuote,
|
|
IN FILETIME const *pftGMT)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (0 <= (LONG) pftGMT->dwHighDateTime)
|
|
{
|
|
hr = cuDumpFileTime(idMessage, pwszQuote, pftGMT);
|
|
_JumpIfError(hr, error, "cuDumpFileTime");
|
|
}
|
|
else
|
|
{
|
|
hr = cuDumpFileTimePeriod(idMessage, pwszQuote, pftGMT);
|
|
_JumpIfError(hr, error, "cuDumpFileTimePeriod");
|
|
}
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
cuDumpDate(
|
|
IN DATE const *pDate)
|
|
{
|
|
HRESULT hr;
|
|
FILETIME ft;
|
|
|
|
if (0.0 == *pDate)
|
|
{
|
|
ft.dwLowDateTime = 0;
|
|
ft.dwHighDateTime = 0;
|
|
}
|
|
else
|
|
{
|
|
hr = myDateToFileTime(pDate, &ft);
|
|
_JumpIfError(hr, error, "myDateToFileTime");
|
|
}
|
|
hr = cuDumpFileTime(0, NULL, &ft);
|
|
_JumpIfError(hr, error, "cuDumpFileTime");
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
VOID
|
|
DumpBlob(
|
|
IN DWORD idMessage,
|
|
IN CRYPT_BIT_BLOB const *pBlob)
|
|
{
|
|
if (NULL != pBlob->pbData)
|
|
{
|
|
wprintf(myLoadResourceString(idMessage));
|
|
wprintf(wszNewLine);
|
|
DumpHex(DH_NOTABPREFIX | 4, pBlob->pbData, pBlob->cbData);
|
|
}
|
|
}
|
|
|
|
|
|
HRESULT
|
|
cuDisplayKeyIdFromExtension(
|
|
IN DWORD cExtension,
|
|
OPTIONAL IN CERT_EXTENSION const *rgExtension,
|
|
BYTE const *pbHash,
|
|
DWORD cbHash)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = S_FALSE;
|
|
if (0 != cExtension && NULL != rgExtension)
|
|
{
|
|
CERT_EXTENSION const *pExt;
|
|
DWORD cb;
|
|
CRYPT_DATA_BLOB aBlob[1 + BLOB_ROUND(CBMAX_CRYPT_HASH_LEN)];
|
|
|
|
pExt = CertFindExtension(
|
|
szOID_SUBJECT_KEY_IDENTIFIER,
|
|
cExtension,
|
|
const_cast<CERT_EXTENSION *>(rgExtension));
|
|
if (NULL != pExt)
|
|
{
|
|
cb = sizeof(aBlob);
|
|
if (!CryptDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_OCTET_STRING,
|
|
pExt->Value.pbData,
|
|
pExt->Value.cbData,
|
|
0,
|
|
aBlob,
|
|
&cb))
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, error, "CryptDecodeObject");
|
|
}
|
|
if (cbHash != aBlob[0].cbData ||
|
|
0 != memcmp(pbHash, aBlob[0].pbData, aBlob[0].cbData))
|
|
{
|
|
hr = DumpHash(
|
|
NULL,
|
|
IDS_FORMAT_SUBJECTKEYID_COLON, // "Subject Key Id (%ws): %ws"
|
|
NULL,
|
|
myLoadResourceString(IDS_PRECOMPUTED), // "precomputed"
|
|
aBlob[0].pbData,
|
|
aBlob[0].cbData);
|
|
_JumpIfError(hr, error, "DumpHash");
|
|
}
|
|
}
|
|
hr = S_OK;
|
|
}
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
cuDisplayKeyIdCanonicalized(
|
|
IN CERT_PUBLIC_KEY_INFO const *pPublicKeyInfo)
|
|
{
|
|
HRESULT hr;
|
|
CERT_PUBLIC_KEY_INFO PublicKeyInfo;
|
|
BYTE *pbKey = NULL;
|
|
DWORD cbKey;
|
|
DWORD cbHash;
|
|
BYTE abHash[CBMAX_CRYPT_HASH_LEN];
|
|
|
|
#if 0
|
|
DumpHex(
|
|
DH_NOTABPREFIX | 4,
|
|
pPublicKeyInfo->PublicKey.pbData,
|
|
pPublicKeyInfo->PublicKey.cbData);
|
|
#endif
|
|
|
|
hr = myCanonicalizePublicKey(
|
|
pPublicKeyInfo->PublicKey.pbData,
|
|
pPublicKeyInfo->PublicKey.cbData,
|
|
&pbKey,
|
|
&cbKey);
|
|
_JumpIfError2(hr, error, "myCanonicalizePublicKey", hr);
|
|
|
|
PublicKeyInfo = *pPublicKeyInfo;
|
|
PublicKeyInfo.PublicKey.pbData = pbKey;
|
|
PublicKeyInfo.PublicKey.cbData = cbKey;
|
|
|
|
#if 0
|
|
DumpHex(
|
|
DH_NOTABPREFIX | 4,
|
|
PublicKeyInfo.PublicKey.pbData,
|
|
PublicKeyInfo.PublicKey.cbData);
|
|
#endif
|
|
|
|
cbHash = sizeof(abHash);
|
|
if (!CryptHashPublicKeyInfo(
|
|
NULL, // hCryptProv
|
|
CALG_SHA1,
|
|
0, // dwFlags,
|
|
X509_ASN_ENCODING,
|
|
&PublicKeyInfo,
|
|
abHash,
|
|
&cbHash))
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, error, "CryptHashPublicKeyInfo");
|
|
}
|
|
hr = DumpHash(
|
|
NULL,
|
|
IDS_FORMAT_KEYIDHASH_COLON, // "Public Key Hash(%ws): %ws"
|
|
myLoadResourceString(IDS_CANONICALIZED), // "canonicalized"
|
|
L"sha1",
|
|
abHash,
|
|
cbHash);
|
|
_JumpIfError(hr, error, "DumpHash");
|
|
|
|
error:
|
|
if (NULL != pbKey)
|
|
{
|
|
LocalFree(pbKey);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
cuDisplayKeyId(
|
|
IN CERT_PUBLIC_KEY_INFO const *pPublicKeyInfo,
|
|
IN DWORD cExtension,
|
|
OPTIONAL IN CERT_EXTENSION const *rgExtension)
|
|
{
|
|
HRESULT hr;
|
|
DWORD cbHash;
|
|
BYTE abHash[CBMAX_CRYPT_HASH_LEN];
|
|
|
|
cbHash = sizeof(abHash);
|
|
if (!CryptHashPublicKeyInfo(
|
|
NULL, // hCryptProv
|
|
CALG_SHA1,
|
|
0, // dwFlags,
|
|
X509_ASN_ENCODING,
|
|
const_cast<CERT_PUBLIC_KEY_INFO *>(pPublicKeyInfo),
|
|
abHash,
|
|
&cbHash))
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, error, "CryptHashPublicKeyInfo");
|
|
}
|
|
hr = DumpHash(
|
|
NULL,
|
|
IDS_FORMAT_KEYIDHASH_COLON, // "Public Key Hash(%ws): %ws"
|
|
NULL,
|
|
L"sha1",
|
|
abHash,
|
|
cbHash);
|
|
_JumpIfError(hr, error, "DumpHash");
|
|
|
|
hr = cuDisplayKeyIdFromExtension(
|
|
cExtension,
|
|
rgExtension,
|
|
abHash,
|
|
cbHash);
|
|
_PrintIfError2(hr, "cuDisplayKeyIdFromExtension", hr);
|
|
|
|
hr = cuDisplayKeyIdCanonicalized(pPublicKeyInfo);
|
|
_PrintIfError2(hr, "cuDisplayKeyIdCanonicalized", hr);
|
|
|
|
hr = S_OK;
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
cuDisplayHash(
|
|
OPTIONAL IN WCHAR const *pwszPrefix,
|
|
OPTIONAL IN CERT_CONTEXT const *pCertContext,
|
|
OPTIONAL IN CRL_CONTEXT const *pCRLContext,
|
|
IN DWORD dwPropId,
|
|
IN WCHAR const *pwszHashName)
|
|
{
|
|
HRESULT hr;
|
|
BYTE abHash[CBMAX_CRYPT_HASH_LEN];
|
|
DWORD cbHash;
|
|
UINT idMsg;
|
|
|
|
cbHash = sizeof(abHash);
|
|
if (NULL != pCertContext)
|
|
{
|
|
if (!CertGetCertificateContextProperty(
|
|
pCertContext,
|
|
dwPropId,
|
|
abHash,
|
|
&cbHash))
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, error, "CertGetCertificateContextProperty");
|
|
}
|
|
idMsg = IDS_FORMAT_CERTHASH_COLON; // "Cert Hash(%ws): %ws"
|
|
}
|
|
else
|
|
{
|
|
CSASSERT(NULL != pCRLContext);
|
|
if (!CertGetCRLContextProperty(pCRLContext, dwPropId, abHash, &cbHash))
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, error, "CertGetCRLContextProperty");
|
|
}
|
|
idMsg = IDS_FORMAT_CRLHASH_COLON; // "CRL Hash(%ws): %ws"
|
|
}
|
|
hr = DumpHash(pwszPrefix, idMsg, NULL, pwszHashName, abHash, cbHash);
|
|
_JumpIfError(hr, error, "DumpHash");
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
cuGetCertType(
|
|
IN CERT_INFO const *pCertInfo,
|
|
OPTIONAL OUT WCHAR **ppwszCertTypeNameV1,
|
|
OPTIONAL OUT WCHAR **ppwszDisplayNameV1,
|
|
OPTIONAL OUT WCHAR **ppwszCertTypeObjId,
|
|
OPTIONAL OUT WCHAR **ppwszCertTypeName,
|
|
OPTIONAL OUT WCHAR **ppwszDisplayName)
|
|
{
|
|
HRESULT hr;
|
|
CERT_EXTENSION *pExt;
|
|
WCHAR *pwszCertTypeNameV1 = NULL;
|
|
WCHAR *pwszCNV1 = NULL;
|
|
WCHAR *pwszDisplayNameV1 = NULL;
|
|
WCHAR *pwszCertTypeObjId = NULL;
|
|
WCHAR *pwszCN = NULL;
|
|
WCHAR *pwszDisplayName = NULL;
|
|
CERT_TEMPLATE_EXT *pTemplate = NULL;
|
|
|
|
if (NULL != ppwszCertTypeNameV1)
|
|
{
|
|
*ppwszCertTypeNameV1 = NULL;
|
|
}
|
|
if (NULL != ppwszDisplayNameV1)
|
|
{
|
|
*ppwszDisplayNameV1 = NULL;
|
|
}
|
|
if (NULL != ppwszCertTypeObjId)
|
|
{
|
|
*ppwszCertTypeObjId = NULL;
|
|
}
|
|
if (NULL != ppwszCertTypeName)
|
|
{
|
|
*ppwszCertTypeName = NULL;
|
|
}
|
|
if (NULL != ppwszDisplayName)
|
|
{
|
|
*ppwszDisplayName = NULL;
|
|
}
|
|
|
|
// Look for the V1 cert type extension first
|
|
|
|
pExt = CertFindExtension(
|
|
szOID_ENROLL_CERTTYPE_EXTENSION,
|
|
pCertInfo->cExtension,
|
|
pCertInfo->rgExtension);
|
|
if (NULL != pExt)
|
|
{
|
|
hr = UnicodeDecode(&pExt->Value, &pwszCertTypeNameV1);
|
|
_JumpIfError(hr, error, "UnicodeDecode");
|
|
|
|
hr = cuGetTemplateNames(
|
|
pwszCertTypeNameV1,
|
|
&pwszCNV1,
|
|
&pwszDisplayNameV1);
|
|
_PrintIfErrorStr2(hr, "cuGetTemplateNames", pwszCertTypeNameV1, hr);
|
|
if (HRESULT_FROM_WIN32(ERROR_NOT_FOUND) != hr)
|
|
{
|
|
_JumpIfErrorStr(hr, error, "cuGetTemplateNames", pwszCertTypeNameV1);
|
|
}
|
|
}
|
|
|
|
pExt = CertFindExtension(
|
|
szOID_CERTIFICATE_TEMPLATE,
|
|
pCertInfo->cExtension,
|
|
pCertInfo->rgExtension);
|
|
if (NULL != pExt)
|
|
{
|
|
DWORD cb;
|
|
|
|
if (!myDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_CERTIFICATE_TEMPLATE,
|
|
pExt->Value.pbData,
|
|
pExt->Value.cbData,
|
|
CERTLIB_USE_LOCALALLOC,
|
|
(VOID **) &pTemplate,
|
|
&cb))
|
|
{
|
|
CSASSERT(NULL == pTemplate);
|
|
hr = myHLastError();
|
|
_JumpError(hr, error, "myDecodeObject");
|
|
}
|
|
if (!ConvertSzToWsz(&pwszCertTypeObjId, pTemplate->pszObjId, -1))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "ConvertSzToWsz");
|
|
}
|
|
hr = cuGetTemplateNames(pwszCertTypeObjId, &pwszCN, &pwszDisplayName);
|
|
_PrintIfErrorStr2(hr, "cuGetTemplateNames", pwszCertTypeObjId, hr);
|
|
if (HRESULT_FROM_WIN32(ERROR_NOT_FOUND) != hr)
|
|
{
|
|
_JumpIfErrorStr(hr, error, "cuGetTemplateNames", pwszCertTypeObjId);
|
|
}
|
|
|
|
}
|
|
if (NULL == pwszCertTypeNameV1 && NULL == pwszCertTypeObjId)
|
|
{
|
|
hr = CRYPT_E_NOT_FOUND;
|
|
_JumpError2(hr, error, "CertFindExtension", CRYPT_E_NOT_FOUND);
|
|
}
|
|
if (NULL != ppwszCertTypeNameV1)
|
|
{
|
|
if (NULL != pwszCNV1)
|
|
{
|
|
*ppwszCertTypeNameV1 = pwszCNV1;
|
|
pwszCNV1 = NULL;
|
|
}
|
|
else
|
|
{
|
|
*ppwszCertTypeNameV1 = pwszCertTypeNameV1;
|
|
pwszCertTypeNameV1 = NULL;
|
|
}
|
|
}
|
|
if (NULL != ppwszDisplayNameV1)
|
|
{
|
|
*ppwszDisplayNameV1 = pwszDisplayNameV1;
|
|
pwszDisplayNameV1 = NULL;
|
|
}
|
|
if (NULL != ppwszCertTypeObjId)
|
|
{
|
|
*ppwszCertTypeObjId = pwszCertTypeObjId;
|
|
pwszCertTypeObjId = NULL;
|
|
}
|
|
if (NULL != ppwszCertTypeName)
|
|
{
|
|
*ppwszCertTypeName = pwszCN;
|
|
pwszCN = NULL;
|
|
}
|
|
if (NULL != ppwszDisplayName)
|
|
{
|
|
*ppwszDisplayName = pwszDisplayName;
|
|
pwszDisplayName = NULL;
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
if (NULL != pwszCertTypeNameV1)
|
|
{
|
|
LocalFree(pwszCertTypeNameV1);
|
|
}
|
|
if (NULL != pwszCNV1)
|
|
{
|
|
LocalFree(pwszCNV1);
|
|
}
|
|
if (NULL != pwszDisplayNameV1)
|
|
{
|
|
LocalFree(pwszDisplayNameV1);
|
|
}
|
|
if (NULL != pwszCertTypeObjId)
|
|
{
|
|
LocalFree(pwszCertTypeObjId);
|
|
}
|
|
if (NULL != pwszCN)
|
|
{
|
|
LocalFree(pwszCN);
|
|
}
|
|
if (NULL != pwszDisplayName)
|
|
{
|
|
LocalFree(pwszDisplayName);
|
|
}
|
|
if (NULL != pTemplate)
|
|
{
|
|
LocalFree(pTemplate);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
cuDumpCertType(
|
|
OPTIONAL IN WCHAR const *pwszPrefix,
|
|
IN CERT_INFO const *pCertInfo)
|
|
{
|
|
HRESULT hr;
|
|
WCHAR *apwsz[6];
|
|
DWORD i;
|
|
DWORD j;
|
|
BOOL fFirst;
|
|
|
|
ZeroMemory(apwsz, sizeof(apwsz));
|
|
|
|
hr = cuGetCertType(
|
|
pCertInfo,
|
|
&apwsz[0], // ppwszCertTypeNameV1
|
|
&apwsz[1], // ppwszDisplayNameV1
|
|
&apwsz[2], // ppwszCertTypeObjId
|
|
&apwsz[3], // ppwszCertTypeName
|
|
&apwsz[4]); // ppwszDisplayName
|
|
_JumpIfError2(hr, error, "cuGetCertType", CRYPT_E_NOT_FOUND);
|
|
|
|
if (NULL != apwsz[2]) // pwszCertTypeObjId
|
|
{
|
|
WCHAR const *pwszFriendlyName;
|
|
|
|
pwszFriendlyName = cuGetOIDName(apwsz[2]);
|
|
if (NULL != pwszFriendlyName && L'\0' != *pwszFriendlyName)
|
|
{
|
|
hr = myDupString(pwszFriendlyName, &apwsz[5]);
|
|
_JumpIfError(hr, error, "myDupString");
|
|
}
|
|
}
|
|
|
|
wprintf(
|
|
L"%ws%ws: ",
|
|
NULL != pwszPrefix? pwszPrefix : L"",
|
|
myLoadResourceString(IDS_TEMPLATE_NAME)); // "Template"
|
|
|
|
// Suppress the long, ugly ObjId, unless they really want to see it:
|
|
|
|
if (!g_fVerbose &&
|
|
NULL != apwsz[2] &&
|
|
(NULL != apwsz[0] || NULL != apwsz[3]))
|
|
{
|
|
LocalFree(apwsz[2]);
|
|
apwsz[2] = NULL;
|
|
}
|
|
|
|
fFirst = TRUE;
|
|
for (i = 0; i < ARRAYSIZE(apwsz); i++)
|
|
{
|
|
if (NULL != apwsz[i])
|
|
{
|
|
BOOL fDup = FALSE;
|
|
|
|
for (j = 0; j < i; j++)
|
|
{
|
|
if (NULL != apwsz[j] && 0 == lstrcmp(apwsz[i], apwsz[j]))
|
|
{
|
|
fDup = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if (!fDup)
|
|
{
|
|
if (!fFirst)
|
|
{
|
|
wprintf(L", ");
|
|
}
|
|
wprintf(L"%ws", apwsz[i]);
|
|
fFirst = FALSE;
|
|
}
|
|
}
|
|
}
|
|
wprintf(wszNewLine);
|
|
|
|
error:
|
|
for (i = 0; i < ARRAYSIZE(apwsz); i++)
|
|
{
|
|
if (NULL != apwsz[i])
|
|
{
|
|
LocalFree(apwsz[i]);
|
|
}
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
dumpCert(
|
|
IN DWORD idMessage,
|
|
IN BYTE const *pbIn,
|
|
IN DWORD cbIn,
|
|
IN BYTE const *pbDecoded,
|
|
IN DWORD cbDecoded,
|
|
IN CERT_SIGNED_CONTENT_INFO const *pcsci)
|
|
{
|
|
HRESULT hr;
|
|
CERT_CONTEXT const *pCertContext = NULL;
|
|
CERT_INFO *pCertInfo;
|
|
BOOL fIssuerMatches;
|
|
DWORD id;
|
|
|
|
pCertContext = CertCreateCertificateContext(X509_ASN_ENCODING, pbIn, cbIn);
|
|
if (NULL == pCertContext)
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, error, "CertCreateCertificateContext");
|
|
}
|
|
pCertInfo = pCertContext->pCertInfo;
|
|
|
|
if (!g_fQuiet)
|
|
{
|
|
wprintf(myLoadResourceString(idMessage));
|
|
wprintf(wszNewLine);
|
|
|
|
cuDumpVersion(pCertInfo->dwVersion + 1);
|
|
}
|
|
|
|
hr = cuDumpSerial(NULL, IDS_SERIAL, &pCertInfo->SerialNumber);
|
|
_JumpIfError(hr, error, "cuDumpSerial");
|
|
|
|
if (!g_fQuiet)
|
|
{
|
|
cuDumpAlgorithm(IDS_SIGNATURE_ALGORITHM, &pCertInfo->SignatureAlgorithm);
|
|
}
|
|
|
|
hr = cuDisplayCertName(
|
|
!g_fQuiet,
|
|
NULL,
|
|
myLoadResourceString(IDS_ISSUER), // "Issuer"
|
|
g_wszPad4,
|
|
&pCertInfo->Issuer,
|
|
NULL);
|
|
_JumpIfError(hr, error, "cuDisplayCertName(Issuer)");
|
|
|
|
if (!g_fQuiet)
|
|
{
|
|
wprintf(wszNewLine);
|
|
hr = cuDumpFileTime(IDS_NOTBEFORE, NULL, &pCertInfo->NotBefore);
|
|
_JumpIfError(hr, error, "cuDumpFileTime");
|
|
|
|
hr = cuDumpFileTime(IDS_NOTAFTER, NULL, &pCertInfo->NotAfter);
|
|
_JumpIfError(hr, error, "cuDumpFileTime");
|
|
|
|
wprintf(wszNewLine);
|
|
}
|
|
hr = cuDisplayCertName(
|
|
!g_fQuiet,
|
|
NULL,
|
|
myLoadResourceString(IDS_SUBJECT), // "Subject"
|
|
g_wszPad4,
|
|
&pCertInfo->Subject,
|
|
pCertInfo);
|
|
_JumpIfError(hr, error, "cuDisplayCertName(Subject)");
|
|
|
|
if (!g_fQuiet)
|
|
{
|
|
wprintf(wszNewLine);
|
|
cuDumpPublicKey(&pCertInfo->SubjectPublicKeyInfo);
|
|
DumpBlob(IDS_ISSUERUNIQUEID, &pCertInfo->IssuerUniqueId);
|
|
DumpBlob(IDS_SUBJECTUNIQUEID, &pCertInfo->SubjectUniqueId);
|
|
}
|
|
|
|
hr = cuDumpExtensionArray(
|
|
IDS_CERTIFICATE_EXTENSIONS,
|
|
pCertInfo->cExtension,
|
|
pCertInfo->rgExtension);
|
|
_JumpIfError(hr, error, "cuDumpExtensionArray");
|
|
|
|
if (!g_fQuiet)
|
|
{
|
|
cuDumpSignature(pcsci);
|
|
}
|
|
|
|
if (!CertCompareCertificateName(
|
|
X509_ASN_ENCODING,
|
|
&pCertInfo->Issuer,
|
|
&pCertInfo->Subject))
|
|
{
|
|
fIssuerMatches = FALSE;
|
|
}
|
|
else
|
|
{
|
|
fIssuerMatches = TRUE;
|
|
}
|
|
|
|
hr = cuVerifySignature(pbIn, cbIn, &pCertInfo->SubjectPublicKeyInfo, FALSE, TRUE);
|
|
if (S_OK != hr)
|
|
{
|
|
if (fIssuerMatches)
|
|
{
|
|
id = IDS_ERR_FORMAT_ROOT_CERT_BAD_SIG; // "Possible Root Certificate: Subject matches Issuer, but Signature check fails: %x"
|
|
}
|
|
else
|
|
{
|
|
id = IDS_NO_ROOT_CERT; // "Non-root Certificate"
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (fIssuerMatches)
|
|
{
|
|
id = IDS_ROOT_CERT; // "Root Certificate: Subject matches Issuer"
|
|
}
|
|
else
|
|
{
|
|
id = IDS_NO_ROOT_CERT_GOOD_SIG; // "Non-root Certificate uses same Public Key as Issuer"
|
|
}
|
|
}
|
|
wprintf(myLoadResourceString(id), hr);
|
|
wprintf(wszNewLine);
|
|
|
|
if (g_fQuiet)
|
|
{
|
|
hr = cuDumpCertType(NULL, pCertContext->pCertInfo);
|
|
_PrintIfError2(hr, "cuDumpCertType", CRYPT_E_NOT_FOUND);
|
|
}
|
|
else
|
|
{
|
|
cuDisplayKeyId(
|
|
&pCertContext->pCertInfo->SubjectPublicKeyInfo,
|
|
pCertContext->pCertInfo->cExtension,
|
|
pCertContext->pCertInfo->rgExtension);
|
|
hr = cuDisplayHash(
|
|
NULL,
|
|
pCertContext,
|
|
NULL,
|
|
CERT_MD5_HASH_PROP_ID,
|
|
L"md5");
|
|
_JumpIfError(hr, error, "cuDisplayHash");
|
|
}
|
|
hr = cuDisplayHash(
|
|
NULL,
|
|
pCertContext,
|
|
NULL,
|
|
CERT_SHA1_HASH_PROP_ID,
|
|
L"sha1");
|
|
_JumpIfError(hr, error, "cuDisplayHash");
|
|
|
|
error:
|
|
if (NULL != pCertContext)
|
|
{
|
|
CertFreeCertificateContext(pCertContext);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
dumpCertSequence(
|
|
IN DWORD idMessage,
|
|
IN BYTE const *pbIn,
|
|
IN DWORD cbIn,
|
|
IN BYTE const *pbDecoded,
|
|
IN DWORD cbDecoded,
|
|
IN CERT_SIGNED_CONTENT_INFO const *pcsci)
|
|
{
|
|
HRESULT hr;
|
|
HRESULT hr2;
|
|
DWORD iCert;
|
|
CRYPT_CONTENT_INFO_SEQUENCE_OF_ANY const *pSeq;
|
|
|
|
pSeq = (CRYPT_CONTENT_INFO_SEQUENCE_OF_ANY const *) pbDecoded;
|
|
|
|
if (0 != strcmp(szOID_NETSCAPE_CERT_SEQUENCE, pSeq->pszObjId))
|
|
{
|
|
hr = CRYPT_E_ASN1_ERROR;
|
|
_JumpError2(hr, error, "not a cert sequence", hr);
|
|
}
|
|
|
|
wprintf(myLoadResourceString(idMessage));
|
|
wprintf(wszNewLine);
|
|
|
|
hr = S_OK;
|
|
for (iCert = 0; iCert < pSeq->cValue; iCert++)
|
|
{
|
|
wprintf(
|
|
myLoadResourceString(IDS_FORMAT_DUMP_CERT_INDEX), // "================ Certificate %d ================"
|
|
iCert);
|
|
wprintf(wszNewLine);
|
|
|
|
hr2 = cuDumpAsnBinary(
|
|
pSeq->rgValue[iCert].pbData,
|
|
pSeq->rgValue[iCert].cbData,
|
|
iCert);
|
|
if (S_OK != hr2)
|
|
{
|
|
cuPrintError(IDS_ERR_FORMAT_CANNOT_DECODE, hr2);
|
|
if (S_OK == hr)
|
|
{
|
|
hr = hr2;
|
|
}
|
|
}
|
|
}
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
dumpCRL(
|
|
IN DWORD idMessage,
|
|
IN BYTE const *pbIn,
|
|
IN DWORD cbIn,
|
|
IN BYTE const *pbDecoded,
|
|
IN DWORD cbDecoded,
|
|
IN CERT_SIGNED_CONTENT_INFO const *pcsci)
|
|
{
|
|
HRESULT hr;
|
|
CRL_CONTEXT const *pCRLContext = NULL;
|
|
CRL_INFO const *pCRLInfo;
|
|
DWORD i;
|
|
CRL_ENTRY *pCRLEntry;
|
|
|
|
CSASSERT(NULL != pbIn && 0 != cbIn);
|
|
CSASSERT(NULL != pbDecoded && 0 != cbDecoded);
|
|
|
|
pCRLContext = CertCreateCRLContext(X509_ASN_ENCODING, pbIn, cbIn);
|
|
if (NULL == pCRLContext)
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, error, "CertCreateCRLContext");
|
|
}
|
|
pCRLInfo = pCRLContext->pCrlInfo;
|
|
|
|
if (!g_fQuiet)
|
|
{
|
|
wprintf(myLoadResourceString(idMessage));
|
|
wprintf(wszNewLine);
|
|
|
|
cuDumpVersion(pCRLInfo->dwVersion + 1);
|
|
cuDumpAlgorithm(IDS_SIGNATURE_ALGORITHM, &pCRLInfo->SignatureAlgorithm);
|
|
}
|
|
|
|
hr = cuDisplayCertName(
|
|
TRUE,
|
|
NULL,
|
|
myLoadResourceString(IDS_ISSUER), // "Issuer"
|
|
g_wszPad4,
|
|
&pCRLInfo->Issuer,
|
|
NULL);
|
|
_JumpIfError(hr, error, "cuDisplayCertName(Issuer)");
|
|
|
|
if (!g_fQuiet)
|
|
{
|
|
wprintf(wszNewLine);
|
|
|
|
hr = cuDumpFileTime(IDS_THISUPDATE, NULL, &pCRLInfo->ThisUpdate);
|
|
_JumpIfError(hr, error, "cuDumpFileTime");
|
|
|
|
hr = cuDumpFileTime(IDS_NEXTUPDATE, NULL, &pCRLInfo->NextUpdate);
|
|
_JumpIfError(hr, error, "cuDumpFileTime");
|
|
|
|
wprintf(myLoadResourceString(IDS_CRLENTRIES)); // "CRL Entries:"
|
|
wprintf(L" %u\n", pCRLInfo->cCRLEntry);
|
|
|
|
for (i = 0; i < pCRLInfo->cCRLEntry; i++)
|
|
{
|
|
pCRLEntry = &pCRLInfo->rgCRLEntry[i];
|
|
|
|
wprintf(g_wszPad2);
|
|
hr = cuDumpSerial(NULL, IDS_SERIAL, &pCRLEntry->SerialNumber);
|
|
_JumpIfError(hr, error, "cuDumpSerial");
|
|
|
|
wprintf(g_wszPad2);
|
|
hr = cuDumpFileTime(
|
|
IDS_REVOCATIONDATE,
|
|
NULL,
|
|
&pCRLEntry->RevocationDate);
|
|
_JumpIfError(hr, error, "cuDumpFileTime");
|
|
|
|
if (0 != pCRLEntry->cExtension)
|
|
{
|
|
wprintf(g_wszPad2);
|
|
hr = cuDumpExtensionArray(
|
|
IDS_EXTENSIONS,
|
|
pCRLEntry->cExtension,
|
|
pCRLEntry->rgExtension);
|
|
_JumpIfError(hr, error, "cuDumpExtensionArray");
|
|
}
|
|
wprintf(wszNewLine);
|
|
}
|
|
}
|
|
if (0 != pCRLInfo->cExtension)
|
|
{
|
|
hr = cuDumpExtensionArray(
|
|
IDS_CRLEXTENSIONS,
|
|
pCRLInfo->cExtension,
|
|
pCRLInfo->rgExtension);
|
|
_JumpIfError(hr, error, "cuDumpExtensionArray");
|
|
}
|
|
if (!g_fQuiet)
|
|
{
|
|
cuDumpSignature(pcsci);
|
|
hr = cuDisplayHash(
|
|
NULL,
|
|
NULL,
|
|
pCRLContext,
|
|
CERT_MD5_HASH_PROP_ID,
|
|
L"md5");
|
|
_JumpIfError(hr, error, "cuDisplayHash");
|
|
}
|
|
hr = cuDisplayHash(
|
|
NULL,
|
|
NULL,
|
|
pCRLContext,
|
|
CERT_SHA1_HASH_PROP_ID,
|
|
L"sha1");
|
|
_JumpIfError(hr, error, "cuDisplayHash");
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
dumpRequest(
|
|
IN DWORD idMessage,
|
|
IN BYTE const *pbIn,
|
|
IN DWORD cbIn,
|
|
IN BYTE const *pbDecoded,
|
|
IN DWORD cbDecoded,
|
|
IN CERT_SIGNED_CONTENT_INFO const *pcsci)
|
|
{
|
|
HRESULT hr;
|
|
CERT_REQUEST_INFO const *pRequest;
|
|
CERT_EXTENSIONS *pExtInfo = NULL;
|
|
|
|
CSASSERT(NULL != pbIn && 0 != cbIn);
|
|
CSASSERT(NULL != pbDecoded && 0 != cbDecoded);
|
|
|
|
wprintf(myLoadResourceString(idMessage));
|
|
wprintf(wszNewLine);
|
|
|
|
pRequest = (CERT_REQUEST_INFO const *) pbDecoded;
|
|
|
|
cuDumpVersion(pRequest->dwVersion + 1);
|
|
|
|
hr = cuDisplayCertName(
|
|
TRUE,
|
|
NULL,
|
|
myLoadResourceString(IDS_SUBJECT), // "Subject"
|
|
g_wszPad4,
|
|
&pRequest->Subject,
|
|
NULL);
|
|
_JumpIfError(hr, error, "cuDisplayCertName(Subject)");
|
|
|
|
wprintf(wszNewLine);
|
|
cuDumpPublicKey(&pRequest->SubjectPublicKeyInfo);
|
|
|
|
wprintf(myLoadResourceString(IDS_REQUEST_ATTRIBUTES)); // "Request Attributes:"
|
|
wprintf(L" %u\n", pRequest->cAttribute);
|
|
|
|
// Dump attributes and certificate extensions
|
|
|
|
hr = DumpAttributes(
|
|
pRequest->rgAttribute,
|
|
pRequest->cAttribute,
|
|
FALSE,
|
|
FOT_ATTRIBUTE,
|
|
NULL, // hStore
|
|
NULL,
|
|
NULL,
|
|
&pExtInfo);
|
|
_JumpIfError(hr, error, "DumpAttributes");
|
|
|
|
cuDumpSignature(pcsci);
|
|
|
|
if (NULL != pcsci)
|
|
{
|
|
hr = cuVerifySignature(
|
|
pbIn,
|
|
cbIn,
|
|
&pRequest->SubjectPublicKeyInfo,
|
|
FALSE,
|
|
FALSE);
|
|
_JumpIfError(hr, error, "cuVerifySignature");
|
|
}
|
|
|
|
hr = cuDisplayKeyId(
|
|
&pRequest->SubjectPublicKeyInfo,
|
|
NULL == pExtInfo? 0 : pExtInfo->cExtension,
|
|
NULL == pExtInfo? NULL : pExtInfo->rgExtension);
|
|
_JumpIfError(hr, error, "cuDisplayKeyId");
|
|
|
|
hr = S_OK;
|
|
|
|
error:
|
|
if (NULL != pExtInfo)
|
|
{
|
|
LocalFree(pExtInfo);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
VOID
|
|
DumpCMCDataReference(
|
|
IN DWORD dwCmcDataReference,
|
|
IN DWORD cCertReference,
|
|
IN DWORD const *rgdwCertReference)
|
|
{
|
|
DWORD i;
|
|
|
|
wprintf(
|
|
L" %ws: %u\n",
|
|
myLoadResourceString(IDS_DATA_REFERENCE),
|
|
dwCmcDataReference);
|
|
|
|
for (i = 0; i < cCertReference; i++)
|
|
{
|
|
wprintf(
|
|
L" %ws[%u]: %u\n",
|
|
myLoadResourceString(IDS_CERT_REFERENCE),
|
|
i,
|
|
rgdwCertReference[i]);
|
|
}
|
|
}
|
|
|
|
|
|
HRESULT
|
|
DumpCMCStatus(
|
|
IN CMC_STATUS_INFO const *pcmcStatus)
|
|
{
|
|
HRESULT hr;
|
|
WCHAR const *pwsz;
|
|
DWORD i;
|
|
|
|
switch (pcmcStatus->dwStatus)
|
|
{
|
|
case CMC_STATUS_SUCCESS:
|
|
pwsz = L"CMC_STATUS_SUCCESS";
|
|
break;
|
|
|
|
case CMC_STATUS_FAILED:
|
|
pwsz = L"CMC_STATUS_FAILED";
|
|
break;
|
|
|
|
case CMC_STATUS_PENDING:
|
|
pwsz = L"CMC_STATUS_PENDING";
|
|
break;
|
|
|
|
case CMC_STATUS_NO_SUPPORT:
|
|
pwsz = L"CMC_STATUS_NO_SUPPORT";
|
|
break;
|
|
|
|
case CMC_STATUS_CONFIRM_REQUIRED:
|
|
pwsz = L"CMC_STATUS_CONFIRM_REQUIRED";
|
|
break;
|
|
|
|
default:
|
|
pwsz = g_wszEmpty;
|
|
break;
|
|
}
|
|
wprintf(
|
|
L" %ws: %ws(%u)\n",
|
|
myLoadResourceString(IDS_CMC_STATUS),
|
|
pwsz,
|
|
pcmcStatus->dwStatus);
|
|
|
|
for (i = 0; i < pcmcStatus->cBodyList; i++)
|
|
{
|
|
wprintf(
|
|
L" %ws[%u]: %u\n",
|
|
myLoadResourceString(IDS_BODY_REFERENCE),
|
|
i,
|
|
pcmcStatus->rgdwBodyList[i]);
|
|
}
|
|
if (NULL != pcmcStatus->pwszStatusString)
|
|
{
|
|
wprintf(
|
|
L" %ws: %ws\n",
|
|
myLoadResourceString(IDS_CMC_STATUSSTRING),
|
|
pcmcStatus->pwszStatusString);
|
|
}
|
|
switch (pcmcStatus->dwOtherInfoChoice)
|
|
{
|
|
case CMC_OTHER_INFO_NO_CHOICE:
|
|
pwsz = L"CMC_OTHER_INFO_NO_CHOICE";
|
|
break;
|
|
|
|
case CMC_OTHER_INFO_FAIL_CHOICE:
|
|
pwsz = L"CMC_OTHER_INFO_FAIL_CHOICE";
|
|
break;
|
|
|
|
case CMC_OTHER_INFO_PEND_CHOICE:
|
|
pwsz = L"CMC_OTHER_INFO_PEND_CHOICE";
|
|
break;
|
|
|
|
default:
|
|
pwsz = g_wszEmpty;
|
|
break;
|
|
}
|
|
wprintf(
|
|
L" %ws: %ws(%u)\n",
|
|
myLoadResourceString(IDS_CMC_OTHERCHOICE),
|
|
pwsz,
|
|
pcmcStatus->dwOtherInfoChoice);
|
|
|
|
switch (pcmcStatus->dwOtherInfoChoice)
|
|
{
|
|
case CMC_OTHER_INFO_FAIL_CHOICE:
|
|
switch (pcmcStatus->dwFailInfo)
|
|
{
|
|
case CMC_FAIL_BAD_ALG:
|
|
pwsz = L"CMC_FAIL_BAD_ALG";
|
|
break;
|
|
|
|
case CMC_FAIL_BAD_MESSAGE_CHECK:
|
|
pwsz = L"CMC_FAIL_BAD_MESSAGE_CHECK";
|
|
break;
|
|
|
|
case CMC_FAIL_BAD_REQUEST:
|
|
pwsz = L"CMC_FAIL_BAD_REQUEST";
|
|
break;
|
|
|
|
case CMC_FAIL_BAD_TIME:
|
|
pwsz = L"CMC_FAIL_BAD_TIME";
|
|
break;
|
|
|
|
case CMC_FAIL_BAD_CERT_ID:
|
|
pwsz = L"CMC_FAIL_BAD_CERT_ID";
|
|
break;
|
|
|
|
case CMC_FAIL_UNSUPORTED_EXT:
|
|
pwsz = L"CMC_FAIL_UNSUPORTED_EXT";
|
|
break;
|
|
|
|
case CMC_FAIL_MUST_ARCHIVE_KEYS:
|
|
pwsz = L"CMC_FAIL_MUST_ARCHIVE_KEYS";
|
|
break;
|
|
|
|
case CMC_FAIL_BAD_IDENTITY:
|
|
pwsz = L"CMC_FAIL_BAD_IDENTITY";
|
|
break;
|
|
|
|
case CMC_FAIL_POP_REQUIRED:
|
|
pwsz = L"CMC_FAIL_POP_REQUIRED";
|
|
break;
|
|
|
|
case CMC_FAIL_POP_FAILED:
|
|
pwsz = L"CMC_FAIL_POP_FAILED";
|
|
break;
|
|
|
|
case CMC_FAIL_NO_KEY_REUSE:
|
|
pwsz = L"CMC_FAIL_NO_KEY_REUSE";
|
|
break;
|
|
|
|
case CMC_FAIL_INTERNAL_CA_ERROR:
|
|
pwsz = L"CMC_FAIL_INTERNAL_CA_ERROR";
|
|
break;
|
|
|
|
case CMC_FAIL_TRY_LATER:
|
|
pwsz = L"CMC_FAIL_TRY_LATER";
|
|
break;
|
|
|
|
default:
|
|
pwsz = g_wszEmpty;
|
|
break;
|
|
}
|
|
wprintf(
|
|
L" %ws: %ws(%u)\n",
|
|
myLoadResourceString(IDS_CMC_FAILINFO),
|
|
pwsz,
|
|
pcmcStatus->dwFailInfo);
|
|
break;
|
|
|
|
case CMC_OTHER_INFO_PEND_CHOICE:
|
|
|
|
wprintf(myLoadResourceString(IDS_PENDTOKEN)); //"Pend Token:"
|
|
DumpHex(
|
|
DH_NOTABPREFIX | 4,
|
|
pcmcStatus->pPendInfo->PendToken.pbData,
|
|
pcmcStatus->pPendInfo->PendToken.cbData);
|
|
|
|
wprintf(g_wszPad4);
|
|
hr = cuDumpFileTime(
|
|
IDS_PENDTIME,
|
|
NULL,
|
|
&pcmcStatus->pPendInfo->PendTime);
|
|
_JumpIfError(hr, error, "cuDumpFileTime");
|
|
|
|
break;
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
DumpCMCRegInfo(
|
|
IN BYTE const *pbData,
|
|
IN DWORD cbData)
|
|
{
|
|
HRESULT hr;
|
|
WCHAR *pwszDup = NULL;
|
|
WCHAR *pwszBuf;
|
|
WCHAR const *pwszName;
|
|
WCHAR const *pwszValue;
|
|
WCHAR *pwszNameAlloc = NULL;
|
|
WCHAR *pwszValueAlloc = NULL;
|
|
|
|
if (NULL == pbData || 0 == cbData)
|
|
{
|
|
hr = S_OK;
|
|
goto error; // silently ignore empty string
|
|
}
|
|
|
|
hr = myDecodeCMCRegInfo(pbData, cbData, &pwszDup);
|
|
_JumpIfError(hr, error, "myDecodeCMCRegInfo");
|
|
|
|
if (NULL != pwszDup)
|
|
{
|
|
pwszBuf = pwszDup;
|
|
|
|
while (TRUE)
|
|
{
|
|
hr = myParseNextAttribute(&pwszBuf, TRUE, &pwszName, &pwszValue);
|
|
if (S_FALSE == hr)
|
|
{
|
|
break;
|
|
}
|
|
_JumpIfError(hr, error, "myParseNextAttribute");
|
|
|
|
if (NULL != pwszNameAlloc)
|
|
{
|
|
LocalFree(pwszNameAlloc);
|
|
pwszNameAlloc = NULL;
|
|
}
|
|
if (NULL != pwszValueAlloc)
|
|
{
|
|
LocalFree(pwszValueAlloc);
|
|
pwszValueAlloc = NULL;
|
|
}
|
|
hr = myUncanonicalizeURLParm(pwszName, &pwszNameAlloc);
|
|
_JumpIfError(hr, error, "myUncanonicalizeURLParm");
|
|
|
|
hr = myUncanonicalizeURLParm(pwszValue, &pwszValueAlloc);
|
|
_JumpIfError(hr, error, "myUncanonicalizeURLParm");
|
|
|
|
wprintf(L"%ws%ws: %ws\n", g_wszPad4, pwszNameAlloc, pwszValueAlloc);
|
|
}
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
if (NULL != pwszNameAlloc)
|
|
{
|
|
LocalFree(pwszNameAlloc);
|
|
}
|
|
if (NULL != pwszValueAlloc)
|
|
{
|
|
LocalFree(pwszValueAlloc);
|
|
}
|
|
if (NULL != pwszDup)
|
|
{
|
|
LocalFree(pwszDup);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
DumpTaggedAttributes(
|
|
IN DWORD cTaggedAttribute,
|
|
IN CMC_TAGGED_ATTRIBUTE const *rgTaggedAttribute)
|
|
{
|
|
HRESULT hr;
|
|
DWORD i;
|
|
DWORD cb;
|
|
CMC_ADD_EXTENSIONS_INFO *pcmcExt = NULL;
|
|
CMC_ADD_ATTRIBUTES_INFO *pcmcAttrib = NULL;
|
|
CMC_STATUS_INFO *pcmcStatus = NULL;
|
|
|
|
wprintf(myLoadResourceString(IDS_TAGGED_ATTRIBUTES)); //"Tagged Attributes:"
|
|
wprintf(L" %u\n", cTaggedAttribute);
|
|
wprintf(wszNewLine);
|
|
|
|
for (i = 0; i < cTaggedAttribute; i++)
|
|
{
|
|
CMC_TAGGED_ATTRIBUTE const *pTaggedAttribute = &rgTaggedAttribute[i];
|
|
CRYPT_ATTRIBUTE const *pAttribute = &pTaggedAttribute->Attribute;
|
|
DWORD j;
|
|
|
|
wprintf(g_wszPad2);
|
|
wprintf(myLoadResourceString(IDS_BODY_PART_ID)); // "Body Part Id:"
|
|
wprintf(L" %u\n", pTaggedAttribute->dwBodyPartID);
|
|
|
|
wprintf(g_wszPad2);
|
|
cuDumpOIDAndDescriptionA(pAttribute->pszObjId);
|
|
wprintf(wszNewLine);
|
|
|
|
for (j = 0; j < pAttribute->cValue; j++)
|
|
{
|
|
BOOL fUnknown = FALSE;
|
|
|
|
wprintf(L" %ws[%u]:\n", myLoadResourceString(IDS_VALUE), j);
|
|
|
|
if (0 == strcmp(szOID_CMC_ADD_EXTENSIONS, pAttribute->pszObjId))
|
|
{
|
|
// Decode CMC_ADD_EXTENSIONS_INFO from Attribute Blob
|
|
|
|
CSASSERT(NULL == pcmcExt);
|
|
if (!myDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
CMC_ADD_EXTENSIONS,
|
|
pAttribute->rgValue[j].pbData,
|
|
pAttribute->rgValue[j].cbData,
|
|
CERTLIB_USE_LOCALALLOC,
|
|
(VOID **) &pcmcExt,
|
|
&cb))
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, error, "myDecodeObject");
|
|
}
|
|
DumpCMCDataReference(
|
|
pcmcExt->dwCmcDataReference,
|
|
pcmcExt->cCertReference,
|
|
pcmcExt->rgdwCertReference);
|
|
|
|
wprintf(g_wszPad2);
|
|
hr = cuDumpExtensionArray(
|
|
IDS_EXTENSIONS,
|
|
pcmcExt->cExtension,
|
|
pcmcExt->rgExtension);
|
|
_JumpIfError(hr, error, "cuDumpExtensionArray");
|
|
|
|
LocalFree(pcmcExt);
|
|
pcmcExt = NULL;
|
|
}
|
|
else
|
|
if (0 == strcmp(szOID_CMC_ADD_ATTRIBUTES, pAttribute->pszObjId))
|
|
{
|
|
// Decode CMC_ADD_ATTRIBUTES_INFO from Attribute Blob
|
|
|
|
CSASSERT(NULL == pcmcAttrib);
|
|
if (!myDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
CMC_ADD_ATTRIBUTES,
|
|
pAttribute->rgValue[j].pbData,
|
|
pAttribute->rgValue[j].cbData,
|
|
CERTLIB_USE_LOCALALLOC,
|
|
(VOID **) &pcmcAttrib,
|
|
&cb))
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, error, "myDecodeObject");
|
|
}
|
|
DumpCMCDataReference(
|
|
pcmcAttrib->dwCmcDataReference,
|
|
pcmcAttrib->cCertReference,
|
|
pcmcAttrib->rgdwCertReference);
|
|
|
|
hr = DumpAttributes(
|
|
pcmcAttrib->rgAttribute,
|
|
pcmcAttrib->cAttribute,
|
|
FALSE,
|
|
FOT_ATTRIBUTE,
|
|
NULL, // hStore
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
_JumpIfError(hr, error, "DumpAttributes");
|
|
|
|
wprintf(wszNewLine);
|
|
LocalFree(pcmcAttrib);
|
|
pcmcAttrib = NULL;
|
|
}
|
|
else
|
|
if (0 == strcmp(szOID_CMC_STATUS_INFO, pAttribute->pszObjId))
|
|
{
|
|
// Decode CMC_STATUS_INFO from Attribute Blob
|
|
|
|
CSASSERT(NULL == pcmcStatus);
|
|
if (!myDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
CMC_STATUS,
|
|
pAttribute->rgValue[j].pbData,
|
|
pAttribute->rgValue[j].cbData,
|
|
CERTLIB_USE_LOCALALLOC,
|
|
(VOID **) &pcmcStatus,
|
|
&cb))
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, error, "myDecodeObject");
|
|
}
|
|
|
|
hr = DumpCMCStatus(pcmcStatus);
|
|
_JumpIfError(hr, error, "DumpStatus");
|
|
|
|
wprintf(wszNewLine);
|
|
LocalFree(pcmcStatus);
|
|
pcmcStatus = NULL;
|
|
}
|
|
else
|
|
if (0 == strcmp(szOID_CMC_TRANSACTION_ID, pAttribute->pszObjId))
|
|
{
|
|
DWORD XactId;
|
|
|
|
cb = sizeof(XactId);
|
|
XactId = 0;
|
|
if (CryptDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_INTEGER,
|
|
pAttribute->rgValue[j].pbData,
|
|
pAttribute->rgValue[j].cbData,
|
|
0,
|
|
&XactId,
|
|
&cb))
|
|
{
|
|
wprintf(
|
|
L"%ws%x(%u)\n\n",
|
|
g_wszPad4,
|
|
XactId,
|
|
XactId);
|
|
}
|
|
else
|
|
{
|
|
fUnknown = TRUE;
|
|
}
|
|
}
|
|
else
|
|
if (0 == strcmp(szOID_CMC_REG_INFO, pAttribute->pszObjId))
|
|
{
|
|
hr = DumpCMCRegInfo(
|
|
pAttribute->rgValue[j].pbData,
|
|
pAttribute->rgValue[j].cbData);
|
|
if (S_OK != hr)
|
|
{
|
|
fUnknown = TRUE;
|
|
}
|
|
}
|
|
else
|
|
if (0 == strcmp(szOID_CMC_QUERY_PENDING, pAttribute->pszObjId) ||
|
|
0 == strcmp(szOID_CMC_SENDER_NONCE, pAttribute->pszObjId) ||
|
|
0 == strcmp(szOID_CMC_RECIPIENT_NONCE, pAttribute->pszObjId))
|
|
{
|
|
CRYPT_DATA_BLOB *pBlob;
|
|
DWORD cbBlob;
|
|
|
|
if (myDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_OCTET_STRING,
|
|
pAttribute->rgValue[j].pbData,
|
|
pAttribute->rgValue[j].cbData,
|
|
CERTLIB_USE_LOCALALLOC,
|
|
(VOID **) &pBlob,
|
|
&cbBlob))
|
|
{
|
|
DumpHex(
|
|
DH_NOTABPREFIX | 4,
|
|
pBlob->pbData,
|
|
pBlob->cbData);
|
|
wprintf(wszNewLine);
|
|
LocalFree(pBlob);
|
|
}
|
|
else
|
|
{
|
|
fUnknown = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fUnknown = TRUE;
|
|
}
|
|
if (fUnknown)
|
|
{
|
|
wprintf(myLoadResourceString(IDS_UNKNOWN_TAGGED_ATTRIBUTE)); // "UNKNOWN Tagged Attribute"
|
|
wprintf(wszNewLine);
|
|
DumpHex(
|
|
DH_NOTABPREFIX | 4,
|
|
pAttribute->rgValue[j].pbData,
|
|
pAttribute->rgValue[j].cbData);
|
|
wprintf(wszNewLine);
|
|
}
|
|
}
|
|
}
|
|
if (0 < i)
|
|
{
|
|
wprintf(wszNewLine);
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
if (NULL != pcmcExt)
|
|
{
|
|
LocalFree(pcmcExt);
|
|
}
|
|
if (NULL != pcmcAttrib)
|
|
{
|
|
LocalFree(pcmcAttrib);
|
|
}
|
|
if (NULL != pcmcStatus)
|
|
{
|
|
LocalFree(pcmcStatus);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
DumpTaggedRequests(
|
|
IN DWORD cTaggedRequest,
|
|
IN CMC_TAGGED_REQUEST const *rgTaggedRequest)
|
|
{
|
|
HRESULT hr;
|
|
DWORD i;
|
|
|
|
wprintf(myLoadResourceString(IDS_TAGGED_REQUESTS)); // "Tagged Requests:"
|
|
wprintf(L" %u\n", cTaggedRequest);
|
|
|
|
for (i = 0; i < cTaggedRequest; i++)
|
|
{
|
|
CMC_TAGGED_REQUEST const *pTaggedRequest = &rgTaggedRequest[i];
|
|
CMC_TAGGED_CERT_REQUEST const *pTaggedCertRequest;
|
|
|
|
switch (pTaggedRequest->dwTaggedRequestChoice)
|
|
{
|
|
case CMC_TAGGED_CERT_REQUEST_CHOICE:
|
|
pTaggedCertRequest = pTaggedRequest->pTaggedCertRequest;
|
|
wprintf(L" CMC_TAGGED_CERT_REQUEST_CHOICE:\n");
|
|
wprintf(g_wszPad2);
|
|
wprintf(myLoadResourceString(IDS_BODY_PART_ID)); // "Body Part Id:"
|
|
wprintf(L" %u\n", pTaggedCertRequest->dwBodyPartID);
|
|
|
|
hr = cuDumpAsnBinary(
|
|
pTaggedCertRequest->SignedCertRequest.pbData,
|
|
pTaggedCertRequest->SignedCertRequest.cbData,
|
|
i);
|
|
_JumpIfError(hr, error, "cuDumpAsnBinary");
|
|
break;
|
|
|
|
default:
|
|
wprintf(myLoadResourceString(IDS_UNKNOWN_REQUEST_CHOICE)); // "UNKNOWN Request Choice"
|
|
wprintf(wszNewLine);
|
|
break;
|
|
}
|
|
}
|
|
if (0 < i)
|
|
{
|
|
wprintf(wszNewLine);
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
DumpTaggedContent(
|
|
IN DWORD cTaggedContentInfo,
|
|
IN CMC_TAGGED_CONTENT_INFO const *rgTaggedContentInfo)
|
|
{
|
|
HRESULT hr;
|
|
DWORD i;
|
|
|
|
wprintf(myLoadResourceString(IDS_TAGGED_CONTENTINFO)); // "Tagged Content Info:"
|
|
wprintf(L" %u\n", cTaggedContentInfo);
|
|
|
|
for (i = 0; i < cTaggedContentInfo; i++)
|
|
{
|
|
CMC_TAGGED_CONTENT_INFO const *pTaggedContentInfo = &rgTaggedContentInfo[i];
|
|
|
|
wprintf(g_wszPad2);
|
|
wprintf(myLoadResourceString(IDS_BODY_PART_ID)); // "Body Part Id:"
|
|
wprintf(L" %u\n", pTaggedContentInfo->dwBodyPartID);
|
|
|
|
hr = cuDumpAsnBinary(
|
|
pTaggedContentInfo->EncodedContentInfo.pbData,
|
|
pTaggedContentInfo->EncodedContentInfo.cbData,
|
|
i);
|
|
_JumpIfError(hr, error, "cuDumpAsnBinary");
|
|
}
|
|
if (0 < i)
|
|
{
|
|
wprintf(wszNewLine);
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
DumpTaggedOther(
|
|
IN DWORD cTaggedOtherMsg,
|
|
IN CMC_TAGGED_OTHER_MSG const *rgTaggedOtherMsg)
|
|
{
|
|
HRESULT hr;
|
|
DWORD i;
|
|
|
|
wprintf(myLoadResourceString(IDS_TAGGED_OTHERMESSAGES)); // "Tagged Other Messages:"
|
|
wprintf(L" %u\n", cTaggedOtherMsg);
|
|
|
|
for (i = 0; i < cTaggedOtherMsg; i++)
|
|
{
|
|
CMC_TAGGED_OTHER_MSG const *pTaggedOtherMsg = &rgTaggedOtherMsg[i];
|
|
|
|
wprintf(L" TaggedOtherMessage[%u]\n", i);
|
|
wprintf(g_wszPad2);
|
|
cuDumpOIDAndDescriptionA(pTaggedOtherMsg->pszObjId);
|
|
|
|
wprintf(L" %ws[%u]:\n", myLoadResourceString(IDS_VALUE), i);
|
|
DumpHex(
|
|
DH_NOADDRESS | DH_NOTABPREFIX | 4,
|
|
pTaggedOtherMsg->Value.pbData,
|
|
pTaggedOtherMsg->Value.cbData);
|
|
}
|
|
if (0 < i)
|
|
{
|
|
wprintf(wszNewLine);
|
|
}
|
|
hr = S_OK;
|
|
|
|
//error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
dumpCMCRequest(
|
|
IN DWORD idMessage,
|
|
IN BYTE const *pbIn,
|
|
IN DWORD cbIn,
|
|
IN BYTE const *pbDecoded,
|
|
IN DWORD cbDecoded,
|
|
IN CERT_SIGNED_CONTENT_INFO const *pcsci)
|
|
{
|
|
HRESULT hr;
|
|
CMC_DATA_INFO const *pcmcData;
|
|
|
|
CSASSERT(NULL != pbIn && 0 != cbIn);
|
|
CSASSERT(NULL != pbDecoded && 0 != cbDecoded);
|
|
|
|
wprintf(myLoadResourceString(idMessage));
|
|
wprintf(wszNewLine);
|
|
|
|
pcmcData = (CMC_DATA_INFO const *) pbDecoded;
|
|
|
|
hr = DumpTaggedAttributes(
|
|
pcmcData->cTaggedAttribute,
|
|
pcmcData->rgTaggedAttribute);
|
|
_JumpIfError(hr, error, "DumpTaggedAttributes");
|
|
|
|
hr = DumpTaggedRequests(
|
|
pcmcData->cTaggedRequest,
|
|
pcmcData->rgTaggedRequest);
|
|
_JumpIfError(hr, error, "DumpTaggedRequests");
|
|
|
|
hr = DumpTaggedContent(
|
|
pcmcData->cTaggedContentInfo,
|
|
pcmcData->rgTaggedContentInfo);
|
|
_JumpIfError(hr, error, "DumpTaggedContent");
|
|
|
|
hr = DumpTaggedOther(
|
|
pcmcData->cTaggedOtherMsg,
|
|
pcmcData->rgTaggedOtherMsg);
|
|
_JumpIfError(hr, error, "DumpTaggedOther");
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
dumpCMCResponse(
|
|
IN DWORD idMessage,
|
|
IN BYTE const *pbIn,
|
|
IN DWORD cbIn,
|
|
IN BYTE const *pbDecoded,
|
|
IN DWORD cbDecoded,
|
|
IN CERT_SIGNED_CONTENT_INFO const *pcsci)
|
|
{
|
|
HRESULT hr;
|
|
CMC_RESPONSE_INFO const *pcmcResponse;
|
|
|
|
CSASSERT(NULL != pbIn && 0 != cbIn);
|
|
CSASSERT(NULL != pbDecoded && 0 != cbDecoded);
|
|
|
|
wprintf(myLoadResourceString(idMessage));
|
|
wprintf(wszNewLine);
|
|
|
|
pcmcResponse = (CMC_RESPONSE_INFO const *) pbDecoded;
|
|
|
|
hr = DumpTaggedAttributes(
|
|
pcmcResponse->cTaggedAttribute,
|
|
pcmcResponse->rgTaggedAttribute);
|
|
_JumpIfError(hr, error, "DumpTaggedAttributes");
|
|
|
|
hr = DumpTaggedContent(
|
|
pcmcResponse->cTaggedContentInfo,
|
|
pcmcResponse->rgTaggedContentInfo);
|
|
_JumpIfError(hr, error, "DumpTaggedContent");
|
|
|
|
hr = DumpTaggedOther(
|
|
pcmcResponse->cTaggedOtherMsg,
|
|
pcmcResponse->rgTaggedOtherMsg);
|
|
_JumpIfError(hr, error, "DumpTaggedOther");
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
dumpKeyGenRequest(
|
|
IN DWORD idMessage,
|
|
IN BYTE const *pbIn,
|
|
IN DWORD cbIn,
|
|
IN BYTE const *pbDecoded,
|
|
IN DWORD cbDecoded,
|
|
IN CERT_SIGNED_CONTENT_INFO const *pcsci)
|
|
{
|
|
HRESULT hr;
|
|
CERT_KEYGEN_REQUEST_INFO const *pKeyGenRequest;
|
|
|
|
CSASSERT(NULL != pbIn && 0 != cbIn);
|
|
CSASSERT(NULL != pbDecoded && 0 != cbDecoded);
|
|
|
|
wprintf(myLoadResourceString(idMessage));
|
|
wprintf(wszNewLine);
|
|
|
|
pKeyGenRequest = (CERT_KEYGEN_REQUEST_INFO const *) pbDecoded;
|
|
|
|
cuDumpPublicKey(&pKeyGenRequest->SubjectPublicKeyInfo);
|
|
|
|
wprintf(
|
|
myLoadResourceString(IDS_FORMAT_CHALLENGE_STRING), // "ChallengeString: ""%ws"""
|
|
pKeyGenRequest->pwszChallengeString);
|
|
wprintf(wszNewLine);
|
|
|
|
cuDumpSignature(pcsci);
|
|
|
|
hr = cuVerifySignature(
|
|
pbIn,
|
|
cbIn,
|
|
&pKeyGenRequest->SubjectPublicKeyInfo,
|
|
FALSE,
|
|
FALSE);
|
|
_JumpIfError(hr, error, "cuVerifySignature");
|
|
|
|
hr = S_OK;
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
dumpCTL(
|
|
IN DWORD idMessage,
|
|
IN BYTE const *pbIn,
|
|
IN DWORD cbIn,
|
|
IN BYTE const *pbDecoded,
|
|
IN DWORD cbDecoded,
|
|
IN CERT_SIGNED_CONTENT_INFO const *pcsci)
|
|
{
|
|
HRESULT hr;
|
|
CTL_INFO const *pCTLInfo;
|
|
CTL_CONTEXT const *pCTLContext = NULL;
|
|
BOOL fIssuerMatches;
|
|
DWORD id;
|
|
DWORD i;
|
|
|
|
pCTLInfo = (CTL_INFO const *) pbDecoded;
|
|
|
|
//if (!g_fQuiet)
|
|
{
|
|
wprintf(myLoadResourceString(idMessage));
|
|
wprintf(wszNewLine);
|
|
|
|
cuDumpVersion(pCTLInfo->dwVersion + 1);
|
|
}
|
|
hr = cuDumpUsage(NULL, IDS_USAGEENTRIES, &pCTLInfo->SubjectUsage);
|
|
_JumpIfError(hr, error, "cuDumpUsage");
|
|
|
|
if (0 != pCTLInfo->ListIdentifier.cbData)
|
|
{
|
|
hr = cuDumpSerial(NULL, IDS_LISTID, &pCTLInfo->ListIdentifier);
|
|
_JumpIfError(hr, error, "cuDumpSerial");
|
|
}
|
|
if (0 != pCTLInfo->SequenceNumber.cbData)
|
|
{
|
|
hr = cuDumpSerial(NULL, IDS_SEQUENCENO, &pCTLInfo->SequenceNumber);
|
|
_JumpIfError(hr, error, "cuDumpSerial");
|
|
}
|
|
|
|
hr = cuDumpFileTime(IDS_THISUPDATE, NULL, &pCTLInfo->ThisUpdate);
|
|
_JumpIfError(hr, error, "cuDumpFileTime");
|
|
|
|
hr = cuDumpFileTime(IDS_NEXTUPDATE, NULL, &pCTLInfo->NextUpdate);
|
|
_JumpIfError(hr, error, "cuDumpFileTime");
|
|
|
|
cuDumpAlgorithm(IDS_SUBJECT_ALGORITHM, &pCTLInfo->SubjectAlgorithm);
|
|
|
|
wprintf(myLoadResourceString(IDS_CTLENTRIES)); // "CTL Entries:"
|
|
wprintf(L" %u\n", pCTLInfo->cCTLEntry);
|
|
|
|
for (i = 0; i < pCTLInfo->cCTLEntry; i++)
|
|
{
|
|
CTL_ENTRY const *pCTLEntry = &pCTLInfo->rgCTLEntry[i];
|
|
|
|
wprintf(wszNewLine);
|
|
|
|
hr = DumpHash(
|
|
g_wszEmpty,
|
|
IDS_FORMAT_SUBJECTID_COLON,
|
|
NULL,
|
|
g_wszEmpty,
|
|
pCTLEntry->SubjectIdentifier.pbData,
|
|
pCTLEntry->SubjectIdentifier.cbData);
|
|
_JumpIfError(hr, error, "DumpHash");
|
|
|
|
hr = DumpAttributes(
|
|
pCTLEntry->rgAttribute,
|
|
pCTLEntry->cAttribute,
|
|
g_fQuiet,
|
|
FOT_ATTRIBUTE,
|
|
NULL, // hStore
|
|
NULL, // pbHashUserCert
|
|
NULL, // pcbHashUserCert
|
|
NULL); // ppExtInfo
|
|
_JumpIfError(hr, error, "DumpAttributes");
|
|
}
|
|
hr = cuDumpExtensionArray(
|
|
IDS_EXTENSIONS,
|
|
pCTLInfo->cExtension,
|
|
pCTLInfo->rgExtension);
|
|
_JumpIfError(hr, error, "cuDumpExtensionArray");
|
|
|
|
hr = S_OK;
|
|
|
|
error:
|
|
if (NULL != pCTLContext)
|
|
{
|
|
CertFreeCTLContext(pCTLContext);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
verbDump(
|
|
IN WCHAR const *pwszOption,
|
|
IN WCHAR const *pwszfn,
|
|
IN WCHAR const *pwszArg2,
|
|
IN WCHAR const *pwszArg3,
|
|
IN WCHAR const *pwszArg4)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (NULL == pwszfn)
|
|
{
|
|
hr = cuConfigDump();
|
|
_JumpIfError(hr, error, "cuConfigDump");
|
|
}
|
|
else
|
|
{
|
|
hr = cuFileDump(pwszfn);
|
|
_JumpIfErrorStr(hr, error, "cuFileDump", pwszfn);
|
|
}
|
|
|
|
error:
|
|
return(hr);
|
|
}
|