857 lines
30 KiB
C
857 lines
30 KiB
C
//+-------------------------------------------------------------------------
|
|
// Microsoft Windows
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 2001 - 2001
|
|
//
|
|
// File: minasn1.h
|
|
//
|
|
// Contents: Minimal ASN.1 Utility and Parsing API Prototypes
|
|
// and Definitions
|
|
//
|
|
// Contains functions to parse X.509 certificates, PKCS #7
|
|
// Signed Data messages, Certificate Trusts Lists (CTLs),
|
|
// hash catalogs, Authenticode Indirect Data and
|
|
// RSA public keys.
|
|
//
|
|
// These APIs are implemented to be self contained and to
|
|
// allow for code obfuscation. These APIs will be included
|
|
// in such applications as, DRM or licensing verification.
|
|
//
|
|
// Additionally, since these APIs have been pared down
|
|
// from their wincrypt.h and crypt32.dll counterparts they are
|
|
// a good candidate for applications with minimal memory and CPU
|
|
// resources.
|
|
//
|
|
// These parsing functions don't depend on more heavy wait
|
|
// ASN.1 runtimes, such as, msoss.dll or msasn1.dll.
|
|
//
|
|
// These functions will only use stack memory. No heap
|
|
// allocations. No calls to APIs in other DLLs.
|
|
//
|
|
// APIs:
|
|
// MinAsn1DecodeLength
|
|
// MinAsn1ExtractContent
|
|
// MinAsn1ExtractValues
|
|
//
|
|
// MinAsn1ParseCertificate
|
|
// MinAsn1ParseAlgorithmIdentifier
|
|
// MinAsn1ParsePublicKeyInfo
|
|
// MinAsn1ParseRSAPublicKey
|
|
// MinAsn1ParseExtensions
|
|
// MinAsn1ParseSignedData
|
|
// MinAsn1ParseSignedDataCertificates
|
|
// MinAsn1ParseAttributes
|
|
// MinAsn1ParseCTL
|
|
// MinAsn1ParseCTLSubject
|
|
// MinAsn1ParseIndirectData
|
|
//
|
|
// MinAsn1FindExtension
|
|
// MinAsn1FindAttribute
|
|
// MinAsn1ExtractParsedCertificatesFromSignedData
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#ifndef __MINASN1_H__
|
|
#define __MINASN1_H__
|
|
|
|
|
|
#if defined (_MSC_VER)
|
|
|
|
#if ( _MSC_VER >= 800 )
|
|
#if _MSC_VER >= 1200
|
|
#pragma warning(push)
|
|
#endif
|
|
#pragma warning(disable:4201) /* Nameless struct/union */
|
|
#endif
|
|
|
|
#if (_MSC_VER > 1020)
|
|
#pragma once
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
#include <wincrypt.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// ASN.1 Tag Defines
|
|
//--------------------------------------------------------------------------
|
|
#define MINASN1_TAG_NULL 0x00
|
|
#define MINASN1_TAG_BOOLEAN 0x01
|
|
#define MINASN1_TAG_INTEGER 0x02
|
|
#define MINASN1_TAG_BITSTRING 0x03
|
|
#define MINASN1_TAG_OCTETSTRING 0x04
|
|
#define MINASN1_TAG_OID 0x06
|
|
#define MINASN1_TAG_UTC_TIME 0x17
|
|
#define MINASN1_TAG_GENERALIZED_TIME 0x18
|
|
#define MINASN1_TAG_CONSTRUCTED 0x20
|
|
#define MINASN1_TAG_SEQ 0x30
|
|
#define MINASN1_TAG_SET 0x31
|
|
#define MINASN1_TAG_CONTEXT_0 0x80
|
|
#define MINASN1_TAG_CONTEXT_1 0x81
|
|
#define MINASN1_TAG_CONTEXT_2 0x82
|
|
#define MINASN1_TAG_CONTEXT_3 0x83
|
|
|
|
#define MINASN1_TAG_CONSTRUCTED_CONTEXT_0 \
|
|
(MINASN1_TAG_CONSTRUCTED | MINASN1_TAG_CONTEXT_0)
|
|
#define MINASN1_TAG_CONSTRUCTED_CONTEXT_1 \
|
|
(MINASN1_TAG_CONSTRUCTED | MINASN1_TAG_CONTEXT_1)
|
|
#define MINASN1_TAG_CONSTRUCTED_CONTEXT_3 \
|
|
(MINASN1_TAG_CONSTRUCTED | MINASN1_TAG_CONTEXT_3)
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// ASN.1 Length Defines for indefinite length encooding
|
|
//--------------------------------------------------------------------------
|
|
#define MINASN1_LENGTH_INDEFINITE 0x80
|
|
#define MINASN1_LENGTH_NULL 0x00
|
|
|
|
#define MINASN1_LENGTH_TOO_LARGE -1
|
|
#define MINASN1_INSUFFICIENT_DATA -2
|
|
#define MINASN1_UNSUPPORTED_INDEFINITE_LENGTH -3
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Get the number of contents octets in a definite-length BER-encoding.
|
|
//
|
|
// Parameters:
|
|
// pcbContent - receives the number of contents octets
|
|
// pbLength - points to the first length octet
|
|
// cbBER - number of bytes remaining in the BER encoding
|
|
//
|
|
// Returns:
|
|
// success - the number of bytes in the length field, > 0
|
|
// failure - < 0
|
|
//
|
|
// One of the following failure values can be returned:
|
|
// MINASN1_LENGTH_TOO_LARGE
|
|
// MINASN1_INSUFFICIENT_DATA
|
|
// MINASN1_UNSUPPORTED_INDEFINITE_LENGTH
|
|
//--------------------------------------------------------------------------
|
|
LONG
|
|
WINAPI
|
|
MinAsn1DecodeLength(
|
|
OUT DWORD *pcbContent,
|
|
IN const BYTE *pbLength,
|
|
IN DWORD cbBER
|
|
);
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Point to the content octets in a definite-length BER-encoded blob.
|
|
//
|
|
// Returns:
|
|
// success - the number of bytes skipped, > 0
|
|
// failure - < 0
|
|
//
|
|
// One of the following failure values can be returned:
|
|
// MINASN1_LENGTH_TOO_LARGE
|
|
// MINASN1_INSUFFICIENT_DATA
|
|
// MINASN1_UNSUPPORTED_INDEFINITE_LENGTH
|
|
//
|
|
// Assumption: pbData points to a definite-length BER-encoded blob.
|
|
// If *pcbContent isn't within cbBER, MINASN1_INSUFFICIENT_DATA
|
|
// is returned.
|
|
//--------------------------------------------------------------------------
|
|
LONG
|
|
WINAPI
|
|
MinAsn1ExtractContent(
|
|
IN const BYTE *pbBER,
|
|
IN DWORD cbBER,
|
|
OUT DWORD *pcbContent,
|
|
OUT const BYTE **ppbContent
|
|
);
|
|
|
|
|
|
typedef struct _MINASN1_EXTRACT_VALUE_PARA {
|
|
// See below for list of operations and optional return blobs.
|
|
DWORD dwFlags;
|
|
|
|
// Index into rgValueBlob of the returned value. Ignored if none of
|
|
// the ASN1_PARSE_RETURN_*_BLOB_FLAG's is set in the above dwFlags.
|
|
DWORD dwIndex;
|
|
|
|
// The following 0 terminated array of tags is optional. If ommited, the
|
|
// value may contain any tag.
|
|
const BYTE *rgbTag;
|
|
} MINASN1_EXTRACT_VALUE_PARA, *PMINASN1_EXTRACT_VALUE_PARA;
|
|
|
|
// The lower 8 bits of dwFlags is set to one of the following operations
|
|
#define MINASN1_MASK_VALUE_OP 0xFF
|
|
#define MINASN1_STEP_OVER_VALUE_OP 1
|
|
#define MINASN1_OPTIONAL_STEP_OVER_VALUE_OP 2
|
|
#define MINASN1_STEP_INTO_VALUE_OP 3
|
|
#define MINASN1_OPTIONAL_STEP_INTO_VALUE_OP 4
|
|
#define MINASN1_STEP_OUT_VALUE_OP 5
|
|
|
|
#define MINASN1_RETURN_VALUE_BLOB_FLAG 0x80000000
|
|
#define MINASN1_RETURN_CONTENT_BLOB_FLAG 0x40000000
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Extract one or more tagged values from the ASN.1 encoded byte array.
|
|
//
|
|
// Either steps into the value's content octets (MINASN1_STEP_INTO_VALUE_OP or
|
|
// MINASN1_OPTIONAL_STEP_INTO_VALUE_OP) or steps over the value's tag,
|
|
// length and content octets (MINASN1_STEP_OVER_VALUE_OP or
|
|
// MINASN1_OPTIONAL_STEP_OVER_VALUE_OP).
|
|
//
|
|
// You can step out of a stepped into sequence via MINASN1_STEP_OUT_VALUE_OP.
|
|
//
|
|
// For tag matching, only supports single byte tags.
|
|
//
|
|
// Only definite-length ASN.1 is supported.
|
|
//
|
|
// *pcValue is updated with the number of values successfully extracted.
|
|
//
|
|
// Returns:
|
|
// success - >= 0 => length of all bytes consumed through the last value
|
|
// extracted. For STEP_INTO, only the tag and length
|
|
// octets.
|
|
// failure - < 0 => negative (offset + 1) of first bad tagged value
|
|
//
|
|
// A non-NULL rgValueBlob[] is updated with the pointer to and length of the
|
|
// tagged value or its content octets. The rgValuePara[].dwIndex is used to
|
|
// index into rgValueBlob[]. For OPTIONAL_STEP_OVER or
|
|
// OPTIONAL_STEP_INTO, if no more bytes in the outer SEQUENCE or if the tag
|
|
// isn't found, pbData and cbData are set to 0. Additioanlly, for
|
|
// OPTIONAL_STEP_INTO, all subsequent values are skipped and their
|
|
// rgValueBlob[] entries zeroed until a STEP_OUT is encountered.
|
|
//
|
|
// If MINASN1_RETURN_VALUE_BLOB_FLAG is set, pbData points to
|
|
// the tag. cbData includes the tag, length and content octets.
|
|
//
|
|
// If MINASN1_RETURN_CONTENT_BLOB_FLAG is set, pbData points to the content
|
|
// octets. cbData includes only the content octets.
|
|
//
|
|
// If neither BLOB_FLAG is set, rgValueBlob[] isn't updated.
|
|
//
|
|
// For MINASN1_RETURN_CONTENT_BLOB_FLAG of a BITSTRING, pbData is
|
|
// advanced past the first contents octet containing the number of
|
|
// unused bits and cbData has been decremented by 1. If cbData > 0, then,
|
|
// *(pbData - 1) will contain the number of unused bits.
|
|
//--------------------------------------------------------------------------
|
|
LONG
|
|
WINAPI
|
|
MinAsn1ExtractValues(
|
|
IN const BYTE *pbEncoded,
|
|
IN DWORD cbEncoded,
|
|
IN OUT DWORD *pcValuePara,
|
|
IN const MINASN1_EXTRACT_VALUE_PARA *rgValuePara,
|
|
IN DWORD cValueBlob,
|
|
OUT OPTIONAL PCRYPT_DER_BLOB rgValueBlob
|
|
);
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// 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
|
|
//
|
|
// The rgCertBlob[] is updated with pointer to and length of the following
|
|
// fields in the encoded X.509 certificate.
|
|
//
|
|
// All BITSTRING fields have been advanced past the unused count octet.
|
|
//--------------------------------------------------------------------------
|
|
|
|
// Encoded bytes including To Be Signed and Signature
|
|
#define MINASN1_CERT_ENCODED_IDX 1
|
|
|
|
// To Be Signed bytes
|
|
#define MINASN1_CERT_TO_BE_SIGNED_IDX 2
|
|
|
|
// Signature Algorithm value bytes (MinAsn1ParseAlgorithmIdentifier)
|
|
#define MINASN1_CERT_SIGN_ALGID_IDX 3
|
|
|
|
// Signature content bytes (BITSTRING)
|
|
#define MINASN1_CERT_SIGNATURE_IDX 4
|
|
|
|
// Version content bytes (OPTIONAL INTEGER)
|
|
#define MINASN1_CERT_VERSION_IDX 5
|
|
|
|
// Serial Number content bytes (INTEGER)
|
|
#define MINASN1_CERT_SERIAL_NUMBER_IDX 6
|
|
|
|
// Issuer Name value bytes (ANY)
|
|
#define MINASN1_CERT_ISSUER_IDX 7
|
|
|
|
// Not Before value bytes (UTC_TIME or GENERALIZED_TIME)
|
|
#define MINASN1_CERT_NOT_BEFORE_IDX 8
|
|
|
|
// Not After value bytes (UTC_TIME or GENERALIZED_TIME)
|
|
#define MINASN1_CERT_NOT_AFTER_IDX 9
|
|
|
|
// Subject Name value bytes (ANY)
|
|
#define MINASN1_CERT_SUBJECT_IDX 10
|
|
|
|
// Public Key Info value bytes (MinAsn1ParsePublicKeyInfo)
|
|
#define MINASN1_CERT_PUBKEY_INFO_IDX 11
|
|
|
|
// Issuer Unique Id content bytes (OPTIONAL BITSTRING)
|
|
#define MINASN1_CERT_ISSUER_UNIQUE_ID_IDX 12
|
|
|
|
// Subject Unique Id content bytes (OPTIONAL BITSTRING)
|
|
#define MINASN1_CERT_SUBJECT_UNIQUE_ID_IDX 13
|
|
|
|
// Extensions value bytes skipping "[3] EXPLICIT" tag
|
|
// (OPTIONAL MinAsn1ParseExtensions)
|
|
#define MINASN1_CERT_EXTS_IDX 14
|
|
|
|
#define MINASN1_CERT_BLOB_CNT 15
|
|
|
|
LONG
|
|
WINAPI
|
|
MinAsn1ParseCertificate(
|
|
IN const BYTE *pbEncoded,
|
|
IN DWORD cbEncoded,
|
|
OUT CRYPT_DER_BLOB rgCertBlob[MINASN1_CERT_BLOB_CNT]
|
|
);
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// 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
|
|
//
|
|
// The rgAlgIdBlob[] is updated with pointer to and length of the following
|
|
// fields in the encoded Algorithm Identifier
|
|
//--------------------------------------------------------------------------
|
|
|
|
// Encoded bytes including outer SEQUENCE tag and length octets
|
|
#define MINASN1_ALGID_ENCODED_IDX 1
|
|
|
|
// Object Identifier content bytes (OID)
|
|
#define MINASN1_ALGID_OID_IDX 2
|
|
|
|
// Encoded parameters value bytes (OPTIONAL ANY)
|
|
#define MINASN1_ALGID_PARA_IDX 3
|
|
|
|
#define MINASN1_ALGID_BLOB_CNT 4
|
|
|
|
|
|
LONG
|
|
WINAPI
|
|
MinAsn1ParseAlgorithmIdentifier(
|
|
IN PCRYPT_DER_BLOB pAlgIdValueBlob,
|
|
OUT CRYPT_DER_BLOB rgAlgIdBlob[MINASN1_ALGID_BLOB_CNT]
|
|
);
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// 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
|
|
//
|
|
// The rgPubKeyInfoBlob[] is updated with pointer to and length of the
|
|
// following fields in the encoded Public Key Info.
|
|
//
|
|
// All BITSTRING fields have been advanced past the unused count octet.
|
|
//--------------------------------------------------------------------------
|
|
|
|
// Encoded bytes including outer SEQUENCE tag and length octets
|
|
#define MINASN1_PUBKEY_INFO_ENCODED_IDX 1
|
|
|
|
// Algorithm Identifier value bytes (MinAsn1ParseAlgorithmIdentifier)
|
|
#define MINASN1_PUBKEY_INFO_ALGID_IDX 2
|
|
|
|
// Public Key content bytes (BITSTRING, MinAsn1ParseRSAPublicKey)
|
|
#define MINASN1_PUBKEY_INFO_PUBKEY_IDX 3
|
|
|
|
#define MINASN1_PUBKEY_INFO_BLOB_CNT 4
|
|
|
|
|
|
LONG
|
|
WINAPI
|
|
MinAsn1ParsePublicKeyInfo(
|
|
IN PCRYPT_DER_BLOB pPubKeyInfoValueBlob,
|
|
CRYPT_DER_BLOB rgPubKeyInfoBlob[MINASN1_PUBKEY_INFO_BLOB_CNT]
|
|
);
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// 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
|
|
//
|
|
// The rgRSAPubKeyBlob[] is updated with pointer to and length of the
|
|
// following fields in the encoded RSA Public Key.
|
|
//--------------------------------------------------------------------------
|
|
|
|
// Encoded bytes including outer SEQUENCE tag and length octets
|
|
#define MINASN1_RSA_PUBKEY_ENCODED_IDX 1
|
|
|
|
// Modulus content bytes (INTEGER)
|
|
#define MINASN1_RSA_PUBKEY_MODULUS_IDX 2
|
|
|
|
// Exponent content bytes (INTEGER)
|
|
#define MINASN1_RSA_PUBKEY_EXPONENT_IDX 3
|
|
|
|
#define MINASN1_RSA_PUBKEY_BLOB_CNT 4
|
|
|
|
LONG
|
|
WINAPI
|
|
MinAsn1ParseRSAPublicKey(
|
|
IN PCRYPT_DER_BLOB pPubKeyContentBlob,
|
|
CRYPT_DER_BLOB rgRSAPubKeyBlob[MINASN1_RSA_PUBKEY_BLOB_CNT]
|
|
);
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// 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
|
|
//
|
|
// The rgrgExtBlob[][] is updated with pointer to and length of the
|
|
// following fields in the encoded extension.
|
|
//--------------------------------------------------------------------------
|
|
|
|
// Encoded bytes including outer SEQUENCE tag and length octets
|
|
#define MINASN1_EXT_ENCODED_IDX 1
|
|
|
|
// Object Identifier content bytes (OID)
|
|
#define MINASN1_EXT_OID_IDX 2
|
|
|
|
// Critical content bytes (OPTIONAL BOOLEAN, DEFAULT FALSE)
|
|
#define MINASN1_EXT_CRITICAL_IDX 3
|
|
|
|
// Value content bytes (OCTETSTRING)
|
|
#define MINASN1_EXT_VALUE_IDX 4
|
|
|
|
#define MINASN1_EXT_BLOB_CNT 5
|
|
|
|
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]
|
|
);
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// 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
|
|
//
|
|
// The rgSignedDataBlob[] is updated with pointer to and length of the
|
|
// following fields in the encoded PKCS #7 message.
|
|
//--------------------------------------------------------------------------
|
|
|
|
// Encoded bytes including outer SEQUENCE tag and length octets
|
|
#define MINASN1_SIGNED_DATA_ENCODED_IDX 1
|
|
|
|
// Outer Object Identfier content bytes (OID, should be "1.2.840.113549.1.7.2")
|
|
#define MINASN1_SIGNED_DATA_OUTER_OID_IDX 2
|
|
|
|
// Version content bytes (INTEGER)
|
|
#define MINASN1_SIGNED_DATA_VERSION_IDX 3
|
|
|
|
// Set of Digest Algorithms value bytes (SET OF)
|
|
#define MINASN1_SIGNED_DATA_DIGEST_ALGIDS_IDX 4
|
|
|
|
// Inner Object Identifier content bytes (OID)
|
|
#define MINASN1_SIGNED_DATA_CONTENT_OID_IDX 5
|
|
|
|
// Signed content data content bytes excluding "[0] EXPLICIT" tag
|
|
// (OPTIONAL ANY, MinAsn1ParseCTL, MinAsn1ParseIndirectData)
|
|
#define MINASN1_SIGNED_DATA_CONTENT_DATA_IDX 6
|
|
|
|
// Certificates value bytes including "[1] IMPLICIT" tag
|
|
// (OPTIONAL, MinAsn1ParseSignedDataCertificates)
|
|
#define MINASN1_SIGNED_DATA_CERTS_IDX 7
|
|
|
|
// CRL value bytes including "[2] IMPLICIT" tag (OPTIONAL)
|
|
#define MINASN1_SIGNED_DATA_CRLS_IDX 8
|
|
|
|
// Encoded bytes including outer SET tag and length octets
|
|
#define MINASN1_SIGNED_DATA_SIGNER_INFOS_IDX 9
|
|
|
|
// The following point to the first Signer Info fields (OPTIONAL)
|
|
|
|
// Encoded bytes including outer SEQUENCE tag and length octets
|
|
#define MINASN1_SIGNED_DATA_SIGNER_INFO_ENCODED_IDX 10
|
|
|
|
// Version content bytes (INTEGER)
|
|
#define MINASN1_SIGNED_DATA_SIGNER_INFO_VERSION_IDX 11
|
|
|
|
// Issuer Name value bytes (ANY)
|
|
#define MINASN1_SIGNED_DATA_SIGNER_INFO_ISSUER_IDX 12
|
|
|
|
// Serial Number content bytes (INTEGER)
|
|
#define MINASN1_SIGNED_DATA_SIGNER_INFO_SERIAL_NUMBER_IDX 13
|
|
|
|
// Digest Algorithm value bytes (MinAsn1ParseAlgorithmIdentifier)
|
|
#define MINASN1_SIGNED_DATA_SIGNER_INFO_DIGEST_ALGID_IDX 14
|
|
|
|
// Authenticated attributes value bytes including "[0] IMPLICIT" tag
|
|
// (OPTIONAL, MinAsn1ParseAttributes)
|
|
#define MINASN1_SIGNED_DATA_SIGNER_INFO_AUTH_ATTRS_IDX 15
|
|
|
|
// Encrypted Digest Algorithm value bytes (MinAsn1ParseAlgorithmIdentifier)
|
|
#define MINASN1_SIGNED_DATA_SIGNER_INFO_ENCRYPT_DIGEST_ALGID_IDX 16
|
|
|
|
// Encrypted digest content bytes (OCTET STRING)
|
|
#define MINASN1_SIGNED_DATA_SIGNER_INFO_ENCYRPT_DIGEST_IDX 17
|
|
|
|
// Unauthenticated attributes value bytes including "[1] IMPLICIT" tag
|
|
// (OPTIONAL, MinAsn1ParseAttributes)
|
|
#define MINASN1_SIGNED_DATA_SIGNER_INFO_UNAUTH_ATTRS_IDX 18
|
|
|
|
#define MINASN1_SIGNED_DATA_BLOB_CNT 19
|
|
|
|
LONG
|
|
WINAPI
|
|
MinAsn1ParseSignedData(
|
|
IN const BYTE *pbEncoded,
|
|
IN DWORD cbEncoded,
|
|
OUT CRYPT_DER_BLOB rgSignedDataBlob[MINASN1_SIGNED_DATA_BLOB_CNT]
|
|
);
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// 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]
|
|
);
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// 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
|
|
//
|
|
// The rgrgAttrBlob[][] is updated with pointer to and length of the
|
|
// following fields in the encoded attribute.
|
|
//--------------------------------------------------------------------------
|
|
|
|
// Encoded bytes including outer SEQUENCE tag and length octets
|
|
#define MINASN1_ATTR_ENCODED_IDX 1
|
|
|
|
// Object Identifier content bytes (OID)
|
|
#define MINASN1_ATTR_OID_IDX 2
|
|
|
|
// Values value bytes (SET OF)
|
|
#define MINASN1_ATTR_VALUES_IDX 3
|
|
|
|
// First Value's value bytes (OPTIONAL ANY)
|
|
#define MINASN1_ATTR_VALUE_IDX 4
|
|
|
|
#define MINASN1_ATTR_BLOB_CNT 5
|
|
|
|
LONG
|
|
WINAPI
|
|
MinAsn1ParseAttributes(
|
|
IN PCRYPT_DER_BLOB pAttrsValueBlob,
|
|
IN OUT DWORD *pcAttr,
|
|
OUT CRYPT_DER_BLOB rgrgAttrBlob[][MINASN1_ATTR_BLOB_CNT]
|
|
);
|
|
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// 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
|
|
//
|
|
// The rgCTLBlob[] is updated with pointer to and length of the following
|
|
// fields in the encoded CTL.
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
// Encoded bytes including outer SEQUENCE tag and length octets
|
|
#define MINASN1_CTL_ENCODED_IDX 1
|
|
|
|
// Version content bytes (OPTIONAL INTEGER)
|
|
#define MINASN1_CTL_VERSION_IDX 2
|
|
|
|
// Subject usage value bytes (SEQUENCE OF OID)
|
|
#define MINASN1_CTL_SUBJECT_USAGE_IDX 3
|
|
|
|
// List Identifier content bytes (OPTIONAL OCTETSTRING)
|
|
#define MINASN1_CTL_LIST_ID_IDX 4
|
|
|
|
// Sequence number content bytes (OPTIONAL INTEGER)
|
|
#define MINASN1_CTL_SEQUENCE_NUMBER_IDX 5
|
|
|
|
// This Update value bytes (UTC_TIME or GENERALIZED_TIME)
|
|
#define MINASN1_CTL_THIS_UPDATE_IDX 6
|
|
|
|
// Next Update value bytes (OPTIONAL UTC_TIME or GENERALIZED_TIME)
|
|
#define MINASN1_CTL_NEXT_UPDATE_IDX 7
|
|
|
|
// Subject Algorithm Identifier value bytes (MinAsn1ParseAlgorithmIdentifier)
|
|
#define MINASN1_CTL_SUBJECT_ALGID_IDX 8
|
|
|
|
// Subjects value bytes (OPTIONAL, iterative MinAsn1ParseCTLSubject)
|
|
#define MINASN1_CTL_SUBJECTS_IDX 9
|
|
|
|
// Extensions value bytes skipping "[0] EXPLICIT" tag
|
|
// (OPTIONAL, MinAsn1ParseExtensions)
|
|
#define MINASN1_CTL_EXTS_IDX 10
|
|
|
|
#define MINASN1_CTL_BLOB_CNT 11
|
|
|
|
LONG
|
|
WINAPI
|
|
MinAsn1ParseCTL(
|
|
IN PCRYPT_DER_BLOB pEncodedContentBlob,
|
|
OUT CRYPT_DER_BLOB rgCTLBlob[MINASN1_CTL_BLOB_CNT]
|
|
);
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// 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
|
|
//
|
|
// The rgCTLSubjectBlob[][] is updated with pointer to and length of the
|
|
// following fields in the encoded subject.
|
|
//--------------------------------------------------------------------------
|
|
|
|
// Encoded bytes including outer SEQUENCE tag and length octets
|
|
#define MINASN1_CTL_SUBJECT_ENCODED_IDX 1
|
|
|
|
// Subject Identifier content bytes (OCTETSTRING)
|
|
#define MINASN1_CTL_SUBJECT_ID_IDX 2
|
|
|
|
// Attributes value bytes (OPTIONAL, MinAsn1ParseAttributes)
|
|
#define MINASN1_CTL_SUBJECT_ATTRS_IDX 3
|
|
|
|
#define MINASN1_CTL_SUBJECT_BLOB_CNT 4
|
|
|
|
LONG
|
|
WINAPI
|
|
MinAsn1ParseCTLSubject(
|
|
IN const BYTE *pbEncoded,
|
|
IN DWORD cbEncoded,
|
|
OUT CRYPT_DER_BLOB rgCTLSubjectBlob[MINASN1_CTL_SUBJECT_BLOB_CNT]
|
|
);
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// 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
|
|
//
|
|
// The rgIndirectDataBlob[] is updated with pointer to and length of the
|
|
// following fields in the encoded Indirect Data.
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
// Encoded bytes including outer SEQUENCE tag and length octets
|
|
#define MINASN1_INDIRECT_DATA_ENCODED_IDX 1
|
|
|
|
// Attribute Object Identifier content bytes (OID)
|
|
#define MINASN1_INDIRECT_DATA_ATTR_OID_IDX 2
|
|
|
|
// Attribute value bytes (OPTIONAL ANY)
|
|
#define MINASN1_INDIRECT_DATA_ATTR_VALUE_IDX 3
|
|
|
|
// Digest Algorithm Identifier (MinAsn1ParseAlgorithmIdentifier)
|
|
#define MINASN1_INDIRECT_DATA_DIGEST_ALGID_IDX 4
|
|
|
|
// Digest content bytes (OCTETSTRING)
|
|
#define MINASN1_INDIRECT_DATA_DIGEST_IDX 5
|
|
|
|
#define MINASN1_INDIRECT_DATA_BLOB_CNT 6
|
|
|
|
LONG
|
|
WINAPI
|
|
MinAsn1ParseIndirectData(
|
|
IN PCRYPT_DER_BLOB pEncodedContentBlob,
|
|
OUT CRYPT_DER_BLOB rgIndirectDataBlob[MINASN1_INDIRECT_DATA_BLOB_CNT]
|
|
);
|
|
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Find an extension identified by its Encoded Object Identifier.
|
|
//
|
|
// Searches the list of parsed extensions returned by
|
|
// MinAsn1ParseExtensions().
|
|
//
|
|
// If found, returns pointer to the rgExtBlob[MINASN1_EXT_BLOB_CNT].
|
|
// Otherwise, returns NULL.
|
|
//--------------------------------------------------------------------------
|
|
PCRYPT_DER_BLOB
|
|
WINAPI
|
|
MinAsn1FindExtension(
|
|
IN PCRYPT_DER_BLOB pEncodedOIDBlob,
|
|
IN DWORD cExt,
|
|
IN CRYPT_DER_BLOB rgrgExtBlob[][MINASN1_EXT_BLOB_CNT]
|
|
);
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Find the first attribute identified by its Encoded Object Identifier.
|
|
//
|
|
// Searches the list of parsed attributes returned by
|
|
// MinAsn1ParseAttributes().
|
|
//
|
|
// If found, returns pointer to the rgAttrBlob[MINASN1_ATTR_BLOB_CNT].
|
|
// Otherwise, returns NULL.
|
|
//--------------------------------------------------------------------------
|
|
PCRYPT_DER_BLOB
|
|
WINAPI
|
|
MinAsn1FindAttribute(
|
|
IN PCRYPT_DER_BLOB pEncodedOIDBlob,
|
|
IN DWORD cAttr,
|
|
IN CRYPT_DER_BLOB rgrgAttrBlob[][MINASN1_ATTR_BLOB_CNT]
|
|
);
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Parses an ASN.1 encoded PKCS #7 Signed Data Message to extract and
|
|
// parse the X.509 certificates it contains.
|
|
//
|
|
// Assumes the PKCS #7 message is definite length encoded.
|
|
// Assumes PKCS #7 version 1.5, ie, not the newer CMS version.
|
|
//
|
|
// Upon input, *pcCert contains the maximum number of parsed certificates
|
|
// that can be returned. Updated with the number of certificates processed.
|
|
//
|
|
// If the encoded message was successfully parsed, TRUE is returned
|
|
// with *pcCert updated with the number of parsed certificates. Otherwise,
|
|
// FALSE is returned for a parse error.
|
|
// Returns:
|
|
// success - >= 0 => bytes skipped, length of the encoded certificates
|
|
// processed.
|
|
// failure - < 0 => negative (offset + 1) of first bad tagged value
|
|
// from beginning of message.
|
|
//
|
|
// The rgrgCertBlob[][] is updated with pointer to and length of the
|
|
// fields in the encoded certificate. See MinAsn1ParseCertificate for the
|
|
// field definitions.
|
|
//--------------------------------------------------------------------------
|
|
LONG
|
|
WINAPI
|
|
MinAsn1ExtractParsedCertificatesFromSignedData(
|
|
IN const BYTE *pbEncoded,
|
|
IN DWORD cbEncoded,
|
|
IN OUT DWORD *pcCert,
|
|
OUT CRYPT_DER_BLOB rgrgCertBlob[][MINASN1_CERT_BLOB_CNT]
|
|
);
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
} // Balance extern "C" above
|
|
#endif
|
|
|
|
#if defined (_MSC_VER)
|
|
#if ( _MSC_VER >= 800 )
|
|
|
|
#if _MSC_VER >= 1200
|
|
#pragma warning(pop)
|
|
#else
|
|
#pragma warning(default:4201)
|
|
#endif
|
|
|
|
#endif
|
|
#endif
|
|
|
|
#endif // __MINASN1_H__
|
|
|