938 lines
32 KiB
C++
938 lines
32 KiB
C++
//+-------------------------------------------------------------------------
|
|
// Microsoft Windows
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 2001 - 2001
|
|
//
|
|
// File: asn1parse.cpp
|
|
//
|
|
// Contents: Minimal ASN.1 parse functions.
|
|
//
|
|
// Functions: MinAsn1ParseCertificate
|
|
// MinAsn1ParseAlgorithmIdentifier
|
|
// MinAsn1ParsePublicKeyInfo
|
|
// MinAsn1ParseRSAPublicKey
|
|
// MinAsn1ParseExtensions
|
|
// MinAsn1ParseSignedData
|
|
// MinAsn1ParseSignedDataCertificates
|
|
// MinAsn1ParseAttributes
|
|
// MinAsn1ParseCTL
|
|
// MinAsn1ParseCTLSubject
|
|
// MinAsn1ParseIndirectData
|
|
//
|
|
// History: 15-Jan-01 philh created
|
|
//--------------------------------------------------------------------------
|
|
|
|
#include "global.hxx"
|
|
|
|
const BYTE rgbSeqTag[] = {MINASN1_TAG_SEQ, 0};
|
|
const BYTE rgbSetTag[] = {MINASN1_TAG_SET, 0};
|
|
const BYTE rgbOIDTag[] = {MINASN1_TAG_OID, 0};
|
|
const BYTE rgbIntegerTag[] = {MINASN1_TAG_INTEGER, 0};
|
|
const BYTE rgbBooleanTag[] = {MINASN1_TAG_BOOLEAN, 0};
|
|
const BYTE rgbBitStringTag[] = {MINASN1_TAG_BITSTRING, 0};
|
|
const BYTE rgbOctetStringTag[] = {MINASN1_TAG_OCTETSTRING, 0};
|
|
const BYTE rgbConstructedContext0Tag[] =
|
|
{MINASN1_TAG_CONSTRUCTED_CONTEXT_0, 0};
|
|
const BYTE rgbConstructedContext1Tag[] =
|
|
{MINASN1_TAG_CONSTRUCTED_CONTEXT_1, 0};
|
|
const BYTE rgbConstructedContext3Tag[] =
|
|
{MINASN1_TAG_CONSTRUCTED_CONTEXT_3, 0};
|
|
const BYTE rgbContext1Tag[] = {MINASN1_TAG_CONTEXT_1, 0};
|
|
const BYTE rgbContext2Tag[] = {MINASN1_TAG_CONTEXT_2, 0};
|
|
const BYTE rgbChoiceOfTimeTag[] =
|
|
{MINASN1_TAG_UTC_TIME, MINASN1_TAG_GENERALIZED_TIME, 0};
|
|
|
|
|
|
const MINASN1_EXTRACT_VALUE_PARA rgParseCertPara[] = {
|
|
// 0 - SignedContent ::= SEQUENCE {
|
|
MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_INTO_VALUE_OP,
|
|
MINASN1_CERT_ENCODED_IDX, rgbSeqTag,
|
|
|
|
// 0.1 - toBeSigned ::== SEQUENCE {
|
|
MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_INTO_VALUE_OP,
|
|
MINASN1_CERT_TO_BE_SIGNED_IDX, rgbSeqTag,
|
|
|
|
// 0.1.0 - version [0] EXPLICIT CertificateVersion DEFAULT v1,
|
|
MINASN1_OPTIONAL_STEP_INTO_VALUE_OP, 0, rgbConstructedContext0Tag,
|
|
|
|
// 0.1.0.0 - version number (INTEGER)
|
|
MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
|
|
MINASN1_CERT_VERSION_IDX, rgbIntegerTag,
|
|
// 0.1.0.1
|
|
MINASN1_STEP_OUT_VALUE_OP, 0, NULL,
|
|
|
|
// 0.1.1 - serialNumber CertificateSerialNumber,
|
|
MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
|
|
MINASN1_CERT_SERIAL_NUMBER_IDX, rgbIntegerTag,
|
|
// 0.1.2 - signature AlgorithmIdentifier,
|
|
MINASN1_STEP_OVER_VALUE_OP, 0, rgbSeqTag,
|
|
// 0.1.3 - issuer NOCOPYANY, -- really Name
|
|
MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
|
|
MINASN1_CERT_ISSUER_IDX, rgbSeqTag,
|
|
// 0.1.4 - validity Validity,
|
|
MINASN1_STEP_INTO_VALUE_OP, 0, rgbSeqTag,
|
|
|
|
// 0.1.4.0 - notBefore ChoiceOfTime,
|
|
MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
|
|
MINASN1_CERT_NOT_BEFORE_IDX, rgbChoiceOfTimeTag,
|
|
// 0.1.4.1 - notAfter ChoiceOfTime,
|
|
MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
|
|
MINASN1_CERT_NOT_AFTER_IDX, rgbChoiceOfTimeTag,
|
|
// 0.1.4.2
|
|
MINASN1_STEP_OUT_VALUE_OP, 0, NULL,
|
|
|
|
// 0.1.5 - subject NOCOPYANY, -- really Name
|
|
MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
|
|
MINASN1_CERT_SUBJECT_IDX, rgbSeqTag,
|
|
// 0.1.6 - subjectPublicKeyInfo SubjectPublicKeyInfo,
|
|
MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
|
|
MINASN1_CERT_PUBKEY_INFO_IDX, rgbSeqTag,
|
|
// 0.1.7 - issuerUniqueIdentifier [1] IMPLICIT BITSTRING OPTIONAL,
|
|
// Note, advanced past the unused bits octet
|
|
MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_OPTIONAL_STEP_OVER_VALUE_OP,
|
|
MINASN1_CERT_ISSUER_UNIQUE_ID_IDX, rgbContext1Tag,
|
|
// 0.1.8 - subjectUniqueIdentifier [2] IMPLICIT BITSTRING OPTIONAL,
|
|
// Note, advanced past the unused bits octet
|
|
MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_OPTIONAL_STEP_OVER_VALUE_OP,
|
|
MINASN1_CERT_SUBJECT_UNIQUE_ID_IDX, rgbContext2Tag,
|
|
// 0.1.9 - extensions [3] EXPLICIT Extensions OPTIONAL
|
|
MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_OPTIONAL_STEP_OVER_VALUE_OP,
|
|
MINASN1_CERT_EXTS_IDX, rgbConstructedContext3Tag,
|
|
|
|
// 0.1.10
|
|
MINASN1_STEP_OUT_VALUE_OP, 0, NULL,
|
|
|
|
// 0.2 - signatureAlgorithm AlgorithmIdentifier,
|
|
MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
|
|
MINASN1_CERT_SIGN_ALGID_IDX, rgbSeqTag,
|
|
// 0.3 - signature BITSTRING
|
|
// Note, advanced past the unused bits octet
|
|
MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
|
|
MINASN1_CERT_SIGNATURE_IDX, rgbBitStringTag,
|
|
};
|
|
#define PARSE_CERT_PARA_CNT \
|
|
(sizeof(rgParseCertPara) / sizeof(rgParseCertPara[0]))
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Function: MinAsn1ParseCertificate
|
|
//
|
|
// Parses an ASN.1 encoded X.509 certificate.
|
|
//
|
|
// Returns:
|
|
// success - > 0 => bytes skipped, length of the encoded certificate
|
|
// failure - < 0 => negative (offset + 1) of first bad tagged value
|
|
//
|
|
// All BITSTRING fields have been advanced past the unused count octet.
|
|
//--------------------------------------------------------------------------
|
|
LONG
|
|
WINAPI
|
|
MinAsn1ParseCertificate(
|
|
IN const BYTE *pbEncoded,
|
|
IN DWORD cbEncoded,
|
|
OUT CRYPT_DER_BLOB rgCertBlob[MINASN1_CERT_BLOB_CNT]
|
|
)
|
|
{
|
|
|
|
LONG lSkipped;
|
|
DWORD cValuePara = PARSE_CERT_PARA_CNT;
|
|
|
|
lSkipped = MinAsn1ExtractValues(
|
|
pbEncoded,
|
|
cbEncoded,
|
|
&cValuePara,
|
|
rgParseCertPara,
|
|
MINASN1_CERT_BLOB_CNT,
|
|
rgCertBlob
|
|
);
|
|
|
|
if (0 < lSkipped) {
|
|
lSkipped = rgCertBlob[MINASN1_CERT_ENCODED_IDX].cbData;
|
|
|
|
// If present, fixup the ISSUER_UNIQUE_ID and SUBJECT_UNIQUE_ID bit
|
|
// fields to advance past the first contents octet containing the
|
|
// number of unused bits
|
|
if (0 != rgCertBlob[MINASN1_CERT_ISSUER_UNIQUE_ID_IDX].cbData) {
|
|
rgCertBlob[MINASN1_CERT_ISSUER_UNIQUE_ID_IDX].pbData += 1;
|
|
rgCertBlob[MINASN1_CERT_ISSUER_UNIQUE_ID_IDX].cbData -= 1;
|
|
}
|
|
|
|
if (0 != rgCertBlob[MINASN1_CERT_SUBJECT_UNIQUE_ID_IDX].cbData) {
|
|
rgCertBlob[MINASN1_CERT_SUBJECT_UNIQUE_ID_IDX].pbData += 1;
|
|
rgCertBlob[MINASN1_CERT_SUBJECT_UNIQUE_ID_IDX].cbData -= 1;
|
|
}
|
|
}
|
|
|
|
return lSkipped;
|
|
}
|
|
|
|
const MINASN1_EXTRACT_VALUE_PARA rgParseAlgIdPara[] = {
|
|
// 0 - AlgorithmIdentifier ::= SEQUENCE {
|
|
MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_INTO_VALUE_OP,
|
|
MINASN1_ALGID_ENCODED_IDX, rgbSeqTag,
|
|
|
|
// 0.0 - algorithm ObjectID,
|
|
MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
|
|
MINASN1_ALGID_OID_IDX, rgbOIDTag,
|
|
// 0.1 parameters ANY OPTIONAL
|
|
MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_OPTIONAL_STEP_OVER_VALUE_OP,
|
|
MINASN1_ALGID_PARA_IDX, NULL,
|
|
};
|
|
#define PARSE_ALGID_PARA_CNT \
|
|
(sizeof(rgParseAlgIdPara) / sizeof(rgParseAlgIdPara[0]))
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Function: MinAsn1ParseAlgorithmIdentifier
|
|
//
|
|
// Parses an ASN.1 encoded Algorithm Identifier contained in numerous
|
|
// other ASN.1 structures, such as, X.509 certificate and PKCS #7 Signed Data
|
|
// message.
|
|
//
|
|
// Returns:
|
|
// success - > 0 => bytes skipped, length of the encoded algorithm
|
|
// identifier
|
|
// failure - < 0 => negative (offset + 1) of first bad tagged value
|
|
//--------------------------------------------------------------------------
|
|
LONG
|
|
WINAPI
|
|
MinAsn1ParseAlgorithmIdentifier(
|
|
IN PCRYPT_DER_BLOB pAlgIdValueBlob,
|
|
OUT CRYPT_DER_BLOB rgAlgIdBlob[MINASN1_ALGID_BLOB_CNT]
|
|
)
|
|
{
|
|
|
|
LONG lSkipped;
|
|
DWORD cValuePara = PARSE_ALGID_PARA_CNT;
|
|
|
|
lSkipped = MinAsn1ExtractValues(
|
|
pAlgIdValueBlob->pbData,
|
|
pAlgIdValueBlob->cbData,
|
|
&cValuePara,
|
|
rgParseAlgIdPara,
|
|
MINASN1_ALGID_BLOB_CNT,
|
|
rgAlgIdBlob
|
|
);
|
|
|
|
if (0 < lSkipped)
|
|
lSkipped = rgAlgIdBlob[MINASN1_ALGID_ENCODED_IDX].cbData;
|
|
|
|
return lSkipped;
|
|
}
|
|
|
|
|
|
|
|
const MINASN1_EXTRACT_VALUE_PARA rgParsePubKeyInfoPara[] = {
|
|
// 0 - PublicKeyInfo ::= SEQUENCE {
|
|
MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_INTO_VALUE_OP,
|
|
MINASN1_PUBKEY_INFO_ENCODED_IDX, rgbSeqTag,
|
|
|
|
// 0.0 - algorithm AlgorithmIdentifier,
|
|
MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
|
|
MINASN1_PUBKEY_INFO_ALGID_IDX, rgbSeqTag,
|
|
|
|
// 0.1 - PublicKey BITSTRING
|
|
MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
|
|
MINASN1_PUBKEY_INFO_PUBKEY_IDX, rgbBitStringTag,
|
|
};
|
|
#define PARSE_PUBKEY_INFO_PARA_CNT \
|
|
(sizeof(rgParsePubKeyInfoPara) / sizeof(rgParsePubKeyInfoPara[0]))
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Function: MinAsn1ParsePublicKeyInfo
|
|
//
|
|
// Parses an ASN.1 encoded Public Key Info structure contained in an
|
|
// X.509 certificate
|
|
//
|
|
// Returns:
|
|
// success - > 0 => bytes skipped, length of the encoded public key
|
|
// info
|
|
// failure - < 0 => negative (offset + 1) of first bad tagged value
|
|
//
|
|
// All BITSTRING fields have been advanced past the unused count octet.
|
|
//--------------------------------------------------------------------------
|
|
LONG
|
|
WINAPI
|
|
MinAsn1ParsePublicKeyInfo(
|
|
IN PCRYPT_DER_BLOB pPubKeyInfoValueBlob,
|
|
CRYPT_DER_BLOB rgPubKeyInfoBlob[MINASN1_PUBKEY_INFO_BLOB_CNT]
|
|
)
|
|
{
|
|
|
|
LONG lSkipped;
|
|
DWORD cValuePara = PARSE_PUBKEY_INFO_PARA_CNT;
|
|
|
|
lSkipped = MinAsn1ExtractValues(
|
|
pPubKeyInfoValueBlob->pbData,
|
|
pPubKeyInfoValueBlob->cbData,
|
|
&cValuePara,
|
|
rgParsePubKeyInfoPara,
|
|
MINASN1_PUBKEY_INFO_BLOB_CNT,
|
|
rgPubKeyInfoBlob
|
|
);
|
|
|
|
if (0 < lSkipped)
|
|
lSkipped = rgPubKeyInfoBlob[MINASN1_PUBKEY_INFO_ENCODED_IDX].cbData;
|
|
|
|
return lSkipped;
|
|
}
|
|
|
|
|
|
|
|
const MINASN1_EXTRACT_VALUE_PARA rgParseRSAPubKeyPara[] = {
|
|
// 0 - RSAPublicKey ::= SEQUENCE {
|
|
MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_INTO_VALUE_OP,
|
|
MINASN1_RSA_PUBKEY_ENCODED_IDX, rgbSeqTag,
|
|
|
|
// 0.0 - modulus HUGEINTEGER, -- n
|
|
MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
|
|
MINASN1_RSA_PUBKEY_MODULUS_IDX, rgbIntegerTag,
|
|
// 0.1 - publicExponent INTEGER (0..4294967295) -- e
|
|
MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
|
|
MINASN1_RSA_PUBKEY_EXPONENT_IDX, rgbIntegerTag,
|
|
};
|
|
#define PARSE_RSA_PUBKEY_PARA_CNT \
|
|
(sizeof(rgParseRSAPubKeyPara) / sizeof(rgParseRSAPubKeyPara[0]))
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Function: MinAsn1ParseRSAPublicKey
|
|
//
|
|
// Parses an ASN.1 encoded RSA PKCS #1 Public Key contained in the contents of
|
|
// Public Key BITSTRING in a X.509 certificate.
|
|
//
|
|
// Returns:
|
|
// success - > 0 => bytes skipped, length of the encoded RSA public key
|
|
// failure - < 0 => negative (offset + 1) of first bad tagged value
|
|
//--------------------------------------------------------------------------
|
|
LONG
|
|
WINAPI
|
|
MinAsn1ParseRSAPublicKey(
|
|
IN PCRYPT_DER_BLOB pPubKeyContentBlob,
|
|
CRYPT_DER_BLOB rgRSAPubKeyBlob[MINASN1_RSA_PUBKEY_BLOB_CNT]
|
|
)
|
|
{
|
|
|
|
LONG lSkipped;
|
|
DWORD cValuePara = PARSE_RSA_PUBKEY_PARA_CNT;
|
|
|
|
lSkipped = MinAsn1ExtractValues(
|
|
pPubKeyContentBlob->pbData,
|
|
pPubKeyContentBlob->cbData,
|
|
&cValuePara,
|
|
rgParseRSAPubKeyPara,
|
|
MINASN1_RSA_PUBKEY_BLOB_CNT,
|
|
rgRSAPubKeyBlob
|
|
);
|
|
|
|
if (0 < lSkipped)
|
|
lSkipped = rgRSAPubKeyBlob[MINASN1_RSA_PUBKEY_ENCODED_IDX].cbData;
|
|
|
|
return lSkipped;
|
|
}
|
|
|
|
|
|
const MINASN1_EXTRACT_VALUE_PARA rgParseExtPara[] = {
|
|
// 0 - Extension ::= SEQUENCE {
|
|
MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_INTO_VALUE_OP,
|
|
MINASN1_EXT_ENCODED_IDX, rgbSeqTag,
|
|
|
|
// 0.0 - extnId EncodedObjectID,
|
|
MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
|
|
MINASN1_EXT_OID_IDX, rgbOIDTag,
|
|
// 0.1 - critical BOOLEAN DEFAULT FALSE,
|
|
MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_OPTIONAL_STEP_OVER_VALUE_OP,
|
|
MINASN1_EXT_CRITICAL_IDX, rgbBooleanTag,
|
|
// 0.2 - extnValue OCTETSTRING
|
|
MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
|
|
MINASN1_EXT_VALUE_IDX, rgbOctetStringTag,
|
|
};
|
|
|
|
#define PARSE_EXT_PARA_CNT \
|
|
(sizeof(rgParseExtPara) / sizeof(rgParseExtPara[0]))
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Function: MinAsn1ParseExtensions
|
|
//
|
|
// Parses an ASN.1 encoded sequence of extensions contained in
|
|
// other ASN.1 structures, such as, X.509 certificate and CTL.
|
|
//
|
|
// Upon input, *pcExt contains the maximum number of parsed extensions
|
|
// that can be returned. Updated with the number of extensions processed.
|
|
//
|
|
// Returns:
|
|
// success - >= 0 => bytes skipped, length of the encoded extensions
|
|
// processed. If all extensions were processed,
|
|
// bytes skipped = pExtsValueBlob->cbData.
|
|
// failure - < 0 => negative (offset + 1) of first bad tagged value
|
|
//--------------------------------------------------------------------------
|
|
LONG
|
|
WINAPI
|
|
MinAsn1ParseExtensions(
|
|
IN PCRYPT_DER_BLOB pExtsValueBlob, // Extensions ::= SEQUENCE OF Extension
|
|
IN OUT DWORD *pcExt,
|
|
OUT CRYPT_DER_BLOB rgrgExtBlob[][MINASN1_EXT_BLOB_CNT]
|
|
)
|
|
{
|
|
const BYTE *pbEncoded = (const BYTE *) pExtsValueBlob->pbData;
|
|
DWORD cbEncoded = pExtsValueBlob->cbData;
|
|
DWORD cExt = *pcExt;
|
|
DWORD iExt = 0;
|
|
LONG lAllExts = 0;
|
|
|
|
const BYTE *pb;
|
|
DWORD cb;
|
|
|
|
if (0 == cbEncoded)
|
|
// No extensions
|
|
goto CommonReturn;
|
|
|
|
// Step into the SEQUENCE
|
|
if (0 >= MinAsn1ExtractContent(
|
|
pbEncoded,
|
|
cbEncoded,
|
|
&cb,
|
|
&pb
|
|
)) {
|
|
lAllExts = -1;
|
|
goto CommonReturn;
|
|
}
|
|
|
|
for (iExt = 0; 0 < cb && iExt < cExt; iExt++) {
|
|
LONG lExt;
|
|
DWORD cbExt;
|
|
DWORD cValuePara = PARSE_EXT_PARA_CNT;
|
|
|
|
lExt = MinAsn1ExtractValues(
|
|
pb,
|
|
cb,
|
|
&cValuePara,
|
|
rgParseExtPara,
|
|
MINASN1_EXT_BLOB_CNT,
|
|
rgrgExtBlob[iExt]
|
|
);
|
|
|
|
if (0 >= lExt) {
|
|
if (0 == lExt)
|
|
lExt = -1;
|
|
lAllExts = -((LONG)(pb - pbEncoded)) + lExt;
|
|
goto CommonReturn;
|
|
}
|
|
|
|
cbExt = rgrgExtBlob[iExt][MINASN1_EXT_ENCODED_IDX].cbData;
|
|
pb += cbExt;
|
|
cb -= cbExt;
|
|
}
|
|
|
|
lAllExts = (LONG)(pb - pbEncoded);
|
|
assert((DWORD) lAllExts <= cbEncoded);
|
|
|
|
CommonReturn:
|
|
*pcExt = iExt;
|
|
return lAllExts;
|
|
}
|
|
|
|
|
|
const MINASN1_EXTRACT_VALUE_PARA rgParseSignedDataPara[] = {
|
|
// 0 - ContentInfo ::= SEQUENCE {
|
|
MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_INTO_VALUE_OP,
|
|
MINASN1_SIGNED_DATA_ENCODED_IDX, rgbSeqTag,
|
|
|
|
// 0.0 - contentType ContentType,
|
|
MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
|
|
MINASN1_SIGNED_DATA_OUTER_OID_IDX, rgbOIDTag,
|
|
// 0.1 - content [0] EXPLICIT ANY -- OPTIONAL
|
|
MINASN1_STEP_INTO_VALUE_OP, 0, rgbConstructedContext0Tag,
|
|
|
|
// 0.1.0 - SignedData ::= SEQUENCE {
|
|
MINASN1_STEP_INTO_VALUE_OP, 0, rgbSeqTag,
|
|
|
|
// 0.1.0.0 - version INTEGER,
|
|
MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
|
|
MINASN1_SIGNED_DATA_VERSION_IDX, rgbIntegerTag,
|
|
// 0.1.0.1 - digestAlgorithms DigestAlgorithmIdentifiers,
|
|
MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
|
|
MINASN1_SIGNED_DATA_DIGEST_ALGIDS_IDX, rgbSetTag,
|
|
// 0.1.0.2 - ContentInfo ::= SEQUENCE {
|
|
MINASN1_STEP_INTO_VALUE_OP, 0, rgbSeqTag,
|
|
|
|
// 0.1.0.2.0 - contentType ContentType,
|
|
MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
|
|
MINASN1_SIGNED_DATA_CONTENT_OID_IDX, rgbOIDTag,
|
|
// 0.1.0.2.1 - content [0] EXPLICIT ANY -- OPTIONAL
|
|
MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_OPTIONAL_STEP_OVER_VALUE_OP,
|
|
MINASN1_SIGNED_DATA_CONTENT_DATA_IDX, rgbConstructedContext0Tag,
|
|
// 0.1.0.2.2
|
|
MINASN1_STEP_OUT_VALUE_OP, 0, NULL,
|
|
|
|
// 0.1.0.3 - certificates [0] IMPLICIT Certificates OPTIONAL,
|
|
MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_OPTIONAL_STEP_OVER_VALUE_OP,
|
|
MINASN1_SIGNED_DATA_CERTS_IDX, rgbConstructedContext0Tag,
|
|
// 0.1.0.4 - crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
|
|
MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_OPTIONAL_STEP_OVER_VALUE_OP,
|
|
MINASN1_SIGNED_DATA_CRLS_IDX, rgbConstructedContext1Tag,
|
|
// 0.1.0.5 - signerInfos :: = SET OF
|
|
MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_INTO_VALUE_OP,
|
|
MINASN1_SIGNED_DATA_SIGNER_INFOS_IDX, rgbSetTag,
|
|
|
|
// 0.1.0.5.0 - SignerInfo ::= SEQUENCE {
|
|
MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_OPTIONAL_STEP_INTO_VALUE_OP,
|
|
MINASN1_SIGNED_DATA_SIGNER_INFO_ENCODED_IDX, rgbSeqTag,
|
|
|
|
// 0.1.0.5.0.0 - version INTEGER,
|
|
MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
|
|
MINASN1_SIGNED_DATA_SIGNER_INFO_VERSION_IDX, rgbIntegerTag,
|
|
// 0.1.0.5.0.1 - issuerAndSerialNumber IssuerAndSerialNumber
|
|
MINASN1_STEP_INTO_VALUE_OP, 0, rgbSeqTag,
|
|
|
|
// 0.1.0.5.0.1.0 - issuer ANY,
|
|
MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
|
|
MINASN1_SIGNED_DATA_SIGNER_INFO_ISSUER_IDX, rgbSeqTag,
|
|
// 0.1.0.5.0.1.1 - serialNumber INTEGER
|
|
MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
|
|
MINASN1_SIGNED_DATA_SIGNER_INFO_SERIAL_NUMBER_IDX, rgbIntegerTag,
|
|
// 0.1.0.5.0.1.2
|
|
MINASN1_STEP_OUT_VALUE_OP, 0, NULL,
|
|
|
|
// 0.1.0.5.0.2 - digestAlgorithm DigestAlgorithmIdentifier,
|
|
MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
|
|
MINASN1_SIGNED_DATA_SIGNER_INFO_DIGEST_ALGID_IDX, rgbSeqTag,
|
|
// 0.1.0.5.0.3 - authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
|
|
MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_OPTIONAL_STEP_OVER_VALUE_OP,
|
|
MINASN1_SIGNED_DATA_SIGNER_INFO_AUTH_ATTRS_IDX, rgbConstructedContext0Tag,
|
|
// 0.1.0.5.0.4 - digestEncryptionAlgorithm DigestEncryptionAlgId,
|
|
MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
|
|
MINASN1_SIGNED_DATA_SIGNER_INFO_ENCRYPT_DIGEST_ALGID_IDX, rgbSeqTag,
|
|
// 0.1.0.5.0.5 - encryptedDigest EncryptedDigest,
|
|
MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
|
|
MINASN1_SIGNED_DATA_SIGNER_INFO_ENCYRPT_DIGEST_IDX, rgbOctetStringTag,
|
|
// 0.1.0.5.0.6 - unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL
|
|
MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_OPTIONAL_STEP_OVER_VALUE_OP,
|
|
MINASN1_SIGNED_DATA_SIGNER_INFO_UNAUTH_ATTRS_IDX, rgbConstructedContext1Tag,
|
|
};
|
|
#define PARSE_SIGNED_DATA_PARA_CNT \
|
|
(sizeof(rgParseSignedDataPara) / sizeof(rgParseSignedDataPara[0]))
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Function: MinAsn1ParseSignedData
|
|
//
|
|
// Parses an ASN.1 encoded PKCS #7 Signed Data Message. Assumes the
|
|
// PKCS #7 message is definite length encoded. Assumes PKCS #7 version
|
|
// 1.5, ie, not the newer CMS version.
|
|
//
|
|
// Returns:
|
|
// success - > 0 => bytes skipped, length of the encoded message
|
|
// failure - < 0 => negative (offset + 1) of first bad tagged value
|
|
//--------------------------------------------------------------------------
|
|
LONG
|
|
WINAPI
|
|
MinAsn1ParseSignedData(
|
|
IN const BYTE *pbEncoded,
|
|
IN DWORD cbEncoded,
|
|
OUT CRYPT_DER_BLOB rgSignedDataBlob[MINASN1_SIGNED_DATA_BLOB_CNT]
|
|
)
|
|
{
|
|
|
|
LONG lSkipped;
|
|
DWORD cValuePara = PARSE_SIGNED_DATA_PARA_CNT;
|
|
|
|
lSkipped = MinAsn1ExtractValues(
|
|
pbEncoded,
|
|
cbEncoded,
|
|
&cValuePara,
|
|
rgParseSignedDataPara,
|
|
MINASN1_SIGNED_DATA_BLOB_CNT,
|
|
rgSignedDataBlob
|
|
);
|
|
|
|
if (0 < lSkipped)
|
|
lSkipped = rgSignedDataBlob[MINASN1_SIGNED_DATA_ENCODED_IDX].cbData;
|
|
|
|
return lSkipped;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Function: MinAsn1ParseSignedDataCertificates
|
|
//
|
|
// Parses an ASN.1 encoded set of certificates contained in
|
|
// a Signed Data message.
|
|
//
|
|
// Upon input, *pcCert contains the maximum number of parsed certificates
|
|
// that can be returned. Updated with the number of certificates processed.
|
|
//
|
|
// Returns:
|
|
// success - >= 0 => bytes skipped, length of the encoded certificates
|
|
// processed. If all certificates were processed,
|
|
// bytes skipped = pCertsValueBlob->cbData.
|
|
// failure - < 0 => negative (offset + 1) of first bad tagged value
|
|
//
|
|
// The rgrgCertBlob[][] is updated with pointer to and length of the
|
|
// fields in the encoded certificate. See MinAsn1ParseCertificate for the
|
|
// field definitions.
|
|
//--------------------------------------------------------------------------
|
|
LONG
|
|
WINAPI
|
|
MinAsn1ParseSignedDataCertificates(
|
|
IN PCRYPT_DER_BLOB pCertsValueBlob,
|
|
IN OUT DWORD *pcCert,
|
|
OUT CRYPT_DER_BLOB rgrgCertBlob[][MINASN1_CERT_BLOB_CNT]
|
|
)
|
|
{
|
|
const BYTE *pbEncoded = (const BYTE *) pCertsValueBlob->pbData;
|
|
DWORD cbEncoded = pCertsValueBlob->cbData;
|
|
DWORD cCert = *pcCert;
|
|
DWORD iCert = 0;
|
|
LONG lAllCerts = 0;
|
|
|
|
const BYTE *pb;
|
|
DWORD cb;
|
|
|
|
if (0 == cbEncoded)
|
|
// No certificates
|
|
goto CommonReturn;
|
|
|
|
// Skip outer tag and length
|
|
if (0 >= MinAsn1ExtractContent(
|
|
pbEncoded,
|
|
cbEncoded,
|
|
&cb,
|
|
&pb
|
|
)) {
|
|
lAllCerts = -1;
|
|
goto CommonReturn;
|
|
}
|
|
|
|
for (iCert = 0; 0 < cb && iCert < cCert; iCert++) {
|
|
LONG lCert;
|
|
|
|
lCert = MinAsn1ParseCertificate(
|
|
pb,
|
|
cb,
|
|
rgrgCertBlob[iCert]
|
|
);
|
|
|
|
if (0 >= lCert) {
|
|
if (0 == lCert)
|
|
lCert = -1;
|
|
lAllCerts = -((LONG)(pb - pbEncoded)) + lCert;
|
|
goto CommonReturn;
|
|
}
|
|
|
|
pb += lCert;
|
|
cb -= lCert;
|
|
}
|
|
|
|
lAllCerts = (LONG)(pb - pbEncoded);
|
|
assert((DWORD) lAllCerts <= cbEncoded);
|
|
|
|
CommonReturn:
|
|
*pcCert = iCert;
|
|
return lAllCerts;
|
|
}
|
|
|
|
|
|
const MINASN1_EXTRACT_VALUE_PARA rgParseAttrPara[] = {
|
|
// 0 - Attribute ::= SEQUENCE {
|
|
MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_INTO_VALUE_OP,
|
|
MINASN1_ATTR_ENCODED_IDX, rgbSeqTag,
|
|
|
|
// 0.0 - attributeType ObjectID,
|
|
MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
|
|
MINASN1_ATTR_OID_IDX, rgbOIDTag,
|
|
// 0.1 - attributeValue SET OF
|
|
MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_STEP_INTO_VALUE_OP,
|
|
MINASN1_ATTR_VALUES_IDX, rgbSetTag,
|
|
|
|
// 0.1.0 - Value ANY -- OPTIONAL
|
|
MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_OPTIONAL_STEP_OVER_VALUE_OP,
|
|
MINASN1_ATTR_VALUE_IDX, NULL,
|
|
};
|
|
#define PARSE_ATTR_PARA_CNT \
|
|
(sizeof(rgParseAttrPara) / sizeof(rgParseAttrPara[0]))
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Function: MinAsn1ParseAttributes
|
|
//
|
|
// Parses an ASN.1 encoded sequence of attributes contained in
|
|
// other ASN.1 structures, such as, Signer Info authenticated or
|
|
// unauthenticated attributes.
|
|
//
|
|
// The outer tag is ignored. It can be a SET, [0] IMPLICIT, or [1] IMPLICIT.
|
|
//
|
|
// Upon input, *pcAttr contains the maximum number of parsed attributes
|
|
// that can be returned. Updated with the number of attributes processed.
|
|
//
|
|
// Returns:
|
|
// success - >= 0 => bytes skipped, length of the encoded attributes
|
|
// processed. If all attributes were processed,
|
|
// bytes skipped = pAttrsValueBlob->cbData.
|
|
// failure - < 0 => negative (offset + 1) of first bad tagged value
|
|
//--------------------------------------------------------------------------
|
|
LONG
|
|
WINAPI
|
|
MinAsn1ParseAttributes(
|
|
IN PCRYPT_DER_BLOB pAttrsValueBlob,
|
|
IN OUT DWORD *pcAttr,
|
|
OUT CRYPT_DER_BLOB rgrgAttrBlob[][MINASN1_ATTR_BLOB_CNT]
|
|
)
|
|
{
|
|
const BYTE *pbEncoded = (const BYTE *) pAttrsValueBlob->pbData;
|
|
DWORD cbEncoded = pAttrsValueBlob->cbData;
|
|
DWORD cAttr = *pcAttr;
|
|
DWORD iAttr = 0;
|
|
LONG lAllAttrs = 0;
|
|
|
|
const BYTE *pb;
|
|
DWORD cb;
|
|
|
|
if (0 == cbEncoded)
|
|
// No attributes
|
|
goto CommonReturn;
|
|
|
|
// Skip the outer tag and length
|
|
if (0 >= MinAsn1ExtractContent(
|
|
pbEncoded,
|
|
cbEncoded,
|
|
&cb,
|
|
&pb
|
|
)) {
|
|
lAllAttrs = -1;
|
|
goto CommonReturn;
|
|
}
|
|
|
|
for (iAttr = 0; 0 < cb && iAttr < cAttr; iAttr++) {
|
|
LONG lAttr;
|
|
DWORD cbAttr;
|
|
DWORD cValuePara = PARSE_ATTR_PARA_CNT;
|
|
|
|
lAttr = MinAsn1ExtractValues(
|
|
pb,
|
|
cb,
|
|
&cValuePara,
|
|
rgParseAttrPara,
|
|
MINASN1_ATTR_BLOB_CNT,
|
|
rgrgAttrBlob[iAttr]
|
|
);
|
|
|
|
if (0 >= lAttr) {
|
|
if (0 == lAttr)
|
|
lAttr = -1;
|
|
lAllAttrs = -((LONG)(pb - pbEncoded)) + lAttr;
|
|
goto CommonReturn;
|
|
}
|
|
|
|
cbAttr = rgrgAttrBlob[iAttr][MINASN1_ATTR_ENCODED_IDX].cbData;
|
|
pb += cbAttr;
|
|
cb -= cbAttr;
|
|
}
|
|
|
|
lAllAttrs = (LONG)(pb - pbEncoded);
|
|
assert((DWORD) lAllAttrs <= cbEncoded);
|
|
|
|
CommonReturn:
|
|
*pcAttr = iAttr;
|
|
return lAllAttrs;
|
|
}
|
|
|
|
|
|
|
|
const MINASN1_EXTRACT_VALUE_PARA rgParseCTLPara[] = {
|
|
// 0 - CertificateTrustList ::= SEQUENCE {
|
|
MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_INTO_VALUE_OP,
|
|
MINASN1_CTL_ENCODED_IDX, rgbSeqTag,
|
|
|
|
// 0.0 - version CTLVersion DEFAULT v1,
|
|
MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_OPTIONAL_STEP_OVER_VALUE_OP,
|
|
MINASN1_CTL_VERSION_IDX, rgbIntegerTag,
|
|
// 0.1 - subjectUsage SubjectUsage,
|
|
MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
|
|
MINASN1_CTL_SUBJECT_USAGE_IDX, rgbSeqTag,
|
|
// 0.2 - listIdentifier ListIdentifier OPTIONAL,
|
|
MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_OPTIONAL_STEP_OVER_VALUE_OP,
|
|
MINASN1_CTL_LIST_ID_IDX, rgbOctetStringTag,
|
|
// 0.3 - sequenceNumber HUGEINTEGER OPTIONAL,
|
|
MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_OPTIONAL_STEP_OVER_VALUE_OP,
|
|
MINASN1_CTL_SEQUENCE_NUMBER_IDX, rgbIntegerTag,
|
|
// 0.4 - ctlThisUpdate ChoiceOfTime,
|
|
MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
|
|
MINASN1_CTL_THIS_UPDATE_IDX, rgbChoiceOfTimeTag,
|
|
// 0.5 - ctlNextUpdate ChoiceOfTime OPTIONAL,
|
|
MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_OPTIONAL_STEP_OVER_VALUE_OP,
|
|
MINASN1_CTL_NEXT_UPDATE_IDX, rgbChoiceOfTimeTag,
|
|
// 0.6 - subjectAlgorithm AlgorithmIdentifier,
|
|
MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
|
|
MINASN1_CTL_SUBJECT_ALGID_IDX, rgbSeqTag,
|
|
// 0.7 - trustedSubjects TrustedSubjects OPTIONAL,
|
|
MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_OPTIONAL_STEP_OVER_VALUE_OP,
|
|
MINASN1_CTL_SUBJECTS_IDX, rgbSeqTag,
|
|
// 0.8 - ctlExtensions [0] EXPLICIT Extensions OPTIONAL
|
|
MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_OPTIONAL_STEP_OVER_VALUE_OP,
|
|
MINASN1_CTL_EXTS_IDX, rgbConstructedContext0Tag,
|
|
};
|
|
#define PARSE_CTL_PARA_CNT \
|
|
(sizeof(rgParseCTLPara) / sizeof(rgParseCTLPara[0]))
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Function: MinAsn1ParseCTL
|
|
//
|
|
// Parses an ASN.1 encoded Certificate Trust List (CTL). A CTL is always
|
|
// contained as the inner content data in a PKCS #7 Signed Data. A CTL has
|
|
// the following OID: "1.3.6.1.4.1.311.10.1".
|
|
//
|
|
// A catalog file is formatted as a PKCS #7 Signed CTL.
|
|
//
|
|
// Returns:
|
|
// success - > 0 => bytes skipped, length of the encoded CTL
|
|
// failure - < 0 => negative (offset + 1) of first bad tagged value
|
|
//--------------------------------------------------------------------------
|
|
LONG
|
|
WINAPI
|
|
MinAsn1ParseCTL(
|
|
IN PCRYPT_DER_BLOB pEncodedContentBlob,
|
|
OUT CRYPT_DER_BLOB rgCTLBlob[MINASN1_CTL_BLOB_CNT]
|
|
)
|
|
{
|
|
|
|
LONG lSkipped;
|
|
DWORD cValuePara = PARSE_CTL_PARA_CNT;
|
|
|
|
lSkipped = MinAsn1ExtractValues(
|
|
pEncodedContentBlob->pbData,
|
|
pEncodedContentBlob->cbData,
|
|
&cValuePara,
|
|
rgParseCTLPara,
|
|
MINASN1_CTL_BLOB_CNT,
|
|
rgCTLBlob
|
|
);
|
|
|
|
if (0 < lSkipped)
|
|
lSkipped = rgCTLBlob[MINASN1_CTL_ENCODED_IDX].cbData;
|
|
|
|
return lSkipped;
|
|
}
|
|
|
|
|
|
const MINASN1_EXTRACT_VALUE_PARA rgParseCTLSubjectPara[] = {
|
|
// 0 - TrustedSubject ::= SEQUENCE {
|
|
MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_INTO_VALUE_OP,
|
|
MINASN1_CTL_SUBJECT_ENCODED_IDX, rgbSeqTag,
|
|
|
|
// 0.0 - subjectIdentifier SubjectIdentifier,
|
|
MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
|
|
MINASN1_CTL_SUBJECT_ID_IDX, rgbOctetStringTag,
|
|
// 0.1 - subjectAttributes Attributes OPTIONAL
|
|
MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_OPTIONAL_STEP_OVER_VALUE_OP,
|
|
MINASN1_CTL_SUBJECT_ATTRS_IDX, rgbSetTag,
|
|
};
|
|
#define PARSE_CTL_SUBJECT_PARA_CNT \
|
|
(sizeof(rgParseCTLSubjectPara) / sizeof(rgParseCTLSubjectPara[0]))
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Function: MinAsn1ParseCTLSubject
|
|
//
|
|
// Parses an ASN.1 encoded CTL Subject contained within a CTL's SEQUENCE OF
|
|
// Subjects.
|
|
//
|
|
// Returns:
|
|
// success - > 0 => bytes skipped, length of the encoded subject.
|
|
// failure - < 0 => negative (offset + 1) of first bad tagged value
|
|
//--------------------------------------------------------------------------
|
|
LONG
|
|
WINAPI
|
|
MinAsn1ParseCTLSubject(
|
|
IN const BYTE *pbEncoded,
|
|
IN DWORD cbEncoded,
|
|
OUT CRYPT_DER_BLOB rgCTLSubjectBlob[MINASN1_CTL_SUBJECT_BLOB_CNT]
|
|
)
|
|
{
|
|
|
|
LONG lSkipped;
|
|
DWORD cValuePara = PARSE_CTL_SUBJECT_PARA_CNT;
|
|
|
|
lSkipped = MinAsn1ExtractValues(
|
|
pbEncoded,
|
|
cbEncoded,
|
|
&cValuePara,
|
|
rgParseCTLSubjectPara,
|
|
MINASN1_CTL_SUBJECT_BLOB_CNT,
|
|
rgCTLSubjectBlob
|
|
);
|
|
|
|
if (0 < lSkipped)
|
|
lSkipped = rgCTLSubjectBlob[MINASN1_CTL_SUBJECT_ENCODED_IDX].cbData;
|
|
|
|
return lSkipped;
|
|
}
|
|
|
|
|
|
|
|
const MINASN1_EXTRACT_VALUE_PARA rgParseIndirectDataPara[] = {
|
|
// 0 - SpcIndirectDataContent ::= SEQUENCE {
|
|
MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_INTO_VALUE_OP,
|
|
MINASN1_INDIRECT_DATA_ENCODED_IDX, rgbSeqTag,
|
|
|
|
// 0.0 - data SpcAttributeTypeAndOptionalValue,
|
|
MINASN1_STEP_INTO_VALUE_OP, 0, rgbSeqTag,
|
|
|
|
// 0.0.0 - type ObjectID,
|
|
MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
|
|
MINASN1_INDIRECT_DATA_ATTR_OID_IDX, rgbOIDTag,
|
|
// 0.0.1 - value NOCOPYANY OPTIONAL
|
|
MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_OPTIONAL_STEP_OVER_VALUE_OP,
|
|
MINASN1_INDIRECT_DATA_ATTR_VALUE_IDX, NULL,
|
|
// 0.0.2
|
|
MINASN1_STEP_OUT_VALUE_OP, 0, NULL,
|
|
|
|
// 0.1 - messageDigest DigestInfo
|
|
MINASN1_STEP_INTO_VALUE_OP, 0, rgbSeqTag,
|
|
|
|
// 0.1.0 - digestAlgorithm AlgorithmIdentifier,
|
|
MINASN1_RETURN_VALUE_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
|
|
MINASN1_INDIRECT_DATA_DIGEST_ALGID_IDX, rgbSeqTag,
|
|
// 0.1.1 - digest OCTETSTRING
|
|
MINASN1_RETURN_CONTENT_BLOB_FLAG | MINASN1_STEP_OVER_VALUE_OP,
|
|
MINASN1_INDIRECT_DATA_DIGEST_IDX, rgbOctetStringTag,
|
|
};
|
|
#define PARSE_INDIRECT_DATA_PARA_CNT \
|
|
(sizeof(rgParseIndirectDataPara) / sizeof(rgParseIndirectDataPara[0]))
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Function: MinAsn1ParseIndirectData
|
|
//
|
|
// Parses an ASN.1 encoded Indirect Data. Indirect Data is always
|
|
// contained as the inner content data in a PKCS #7 Signed Data. It has
|
|
// the following OID: "1.3.6.1.4.1.311.2.1.4"
|
|
//
|
|
// An Authenticode signed file contains a PKCS #7 Signed Indirect Data.
|
|
//
|
|
// Returns:
|
|
// success - > 0 => bytes skipped, length of the encoded Indirect Data
|
|
// failure - < 0 => negative (offset + 1) of first bad tagged value
|
|
//--------------------------------------------------------------------------
|
|
LONG
|
|
WINAPI
|
|
MinAsn1ParseIndirectData(
|
|
IN PCRYPT_DER_BLOB pEncodedContentBlob,
|
|
OUT CRYPT_DER_BLOB rgIndirectDataBlob[MINASN1_INDIRECT_DATA_BLOB_CNT]
|
|
)
|
|
{
|
|
|
|
LONG lSkipped;
|
|
DWORD cValuePara = PARSE_INDIRECT_DATA_PARA_CNT;
|
|
|
|
lSkipped = MinAsn1ExtractValues(
|
|
pEncodedContentBlob->pbData,
|
|
pEncodedContentBlob->cbData,
|
|
&cValuePara,
|
|
rgParseIndirectDataPara,
|
|
MINASN1_INDIRECT_DATA_BLOB_CNT,
|
|
rgIndirectDataBlob
|
|
);
|
|
|
|
if (0 < lSkipped)
|
|
lSkipped = rgIndirectDataBlob[MINASN1_INDIRECT_DATA_ENCODED_IDX].cbData;
|
|
|
|
return lSkipped;
|
|
}
|
|
|
|
|