summaryrefslogtreecommitdiffstats
path: root/include/iprt/crypto/spc.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/iprt/crypto/spc.h')
-rw-r--r--include/iprt/crypto/spc.h503
1 files changed, 503 insertions, 0 deletions
diff --git a/include/iprt/crypto/spc.h b/include/iprt/crypto/spc.h
new file mode 100644
index 00000000..46617277
--- /dev/null
+++ b/include/iprt/crypto/spc.h
@@ -0,0 +1,503 @@
+/** @file
+ * IPRT - Crypto - Microsoft SPC / Authenticode.
+ */
+
+/*
+ * Copyright (C) 2006-2020 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef IPRT_INCLUDED_crypto_spc_h
+#define IPRT_INCLUDED_crypto_spc_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/asn1.h>
+#include <iprt/crypto/x509.h>
+#include <iprt/crypto/pkcs7.h>
+#include <iprt/md5.h>
+#include <iprt/sha.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_cr_spc RTCrSpc - Microsoft Authenticode
+ * @ingroup grp_rt_crypto
+ * @{
+ */
+
+/**
+ * PE Image page hash table, generic union.
+ *
+ * @remarks This table isn't used by ldrPE.cpp, it walks the table in a generic
+ * fashion using the hash size. So, we can ditch it if we feel like it.
+ */
+typedef union RTCRSPCPEIMAGEPAGEHASHES
+{
+ /** MD5 page hashes. */
+ struct
+ {
+ /** The file offset. */
+ uint32_t offFile;
+ /** The hash. */
+ uint8_t abHash[RTSHA1_HASH_SIZE];
+ } aMd5[1];
+
+ /** SHA-1 page hashes. */
+ struct
+ {
+ /** The file offset. */
+ uint32_t offFile;
+ /** The hash. */
+ uint8_t abHash[RTSHA1_HASH_SIZE];
+ } aSha1[1];
+
+ /** SHA-256 page hashes. */
+ struct
+ {
+ /** The file offset. */
+ uint32_t offFile;
+ /** The hash. */
+ uint8_t abHash[RTSHA256_HASH_SIZE];
+ } aSha256[1];
+
+ /** SHA-512 page hashes. */
+ struct
+ {
+ /** The file offset. */
+ uint32_t offFile;
+ /** The hash. */
+ uint8_t abHash[RTSHA512_HASH_SIZE];
+ } aSha512[1];
+
+ /** Generic view of ONE hash. */
+ struct
+ {
+ /** The file offset. */
+ uint32_t offFile;
+ /** Variable length hash field. */
+ uint8_t abHash[1];
+ } Generic;
+} RTCRSPCPEIMAGEPAGEHASHES;
+/** Pointer to a PE image page hash table union. */
+typedef RTCRSPCPEIMAGEPAGEHASHES *PRTCRSPCPEIMAGEPAGEHASHES;
+/** Pointer to a const PE image page hash table union. */
+typedef RTCRSPCPEIMAGEPAGEHASHES const *PCRTCRSPCPEIMAGEPAGEHASHES;
+
+
+/**
+ * Serialization wrapper for raw RTCRSPCPEIMAGEPAGEHASHES data.
+ */
+typedef struct RTCRSPCSERIALIZEDPAGEHASHES
+{
+ /** The page hashes are within a set. Dunno if there could be multiple
+ * entries in this set, never seen it yet, so I doubt it. */
+ RTASN1SETCORE SetCore;
+ /** Octet string containing the raw data. */
+ RTASN1OCTETSTRING RawData;
+
+ /** Pointer to the hash data within that string.
+ * The hash algorithm is given by the object attribute type in
+ * RTCRSPCSERIALIZEDOBJECTATTRIBUTE. It is generally the same as for the
+ * whole image hash. */
+ PCRTCRSPCPEIMAGEPAGEHASHES pData;
+ /** Field the user can use to store the number of pages in pData. */
+ uint32_t cPages;
+} RTCRSPCSERIALIZEDPAGEHASHES;
+/** Pointer to a serialized wrapper for page hashes. */
+typedef RTCRSPCSERIALIZEDPAGEHASHES *PRTCRSPCSERIALIZEDPAGEHASHES;
+/** Pointer to a const serialized wrapper for page hashes. */
+typedef RTCRSPCSERIALIZEDPAGEHASHES const *PCRTCRSPCSERIALIZEDPAGEHASHES;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRSPCSERIALIZEDPAGEHASHES, RTDECL, RTCrSpcSerializedPageHashes, SetCore.Asn1Core);
+
+RTDECL(int) RTCrSpcSerializedPageHashes_UpdateDerivedData(PRTCRSPCSERIALIZEDPAGEHASHES pThis);
+
+
+/**
+ * Data type selection for RTCRSPCSERIALIZEDOBJECTATTRIBUTE.
+ */
+typedef enum RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE
+{
+ /** Invalid zero entry. */
+ RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE_INVALID = 0,
+ /** Not present pro forma. */
+ RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE_NOT_PRESENT,
+ /** Unknown object. */
+ RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE_UNKNOWN,
+ /** SHA-1 page hashes (pPageHashes). */
+ RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE_PAGE_HASHES_V1,
+ /** SHA-256 page hashes (pPageHashes). */
+ RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE_PAGE_HASHES_V2,
+ /** End of valid values. */
+ RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE_END,
+ /** Blow up the type to at least 32-bits. */
+ RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE_32BIT_HACK
+} RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE;
+
+/**
+ * One serialized object attribute (PE image data).
+ */
+typedef struct RTCRSPCSERIALIZEDOBJECTATTRIBUTE
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The attribute type. */
+ RTASN1OBJID Type;
+ /** The allocation of the data type. */
+ RTASN1ALLOCATION Allocation;
+ /** Indicates the valid value in the union. */
+ RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE enmType;
+ /** Union with data format depending on the Type. */
+ union
+ {
+ /** The unknown value (RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE_UNKNOWN). */
+ PRTASN1CORE pCore;
+ /** Page hashes (RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE_PAGE_HASHES_V1 or
+ * RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE_PAGE_HASHES_V2). */
+ PRTCRSPCSERIALIZEDPAGEHASHES pPageHashes;
+ } u;
+} RTCRSPCSERIALIZEDOBJECTATTRIBUTE;
+/** Pointer to a serialized object attribute. */
+typedef RTCRSPCSERIALIZEDOBJECTATTRIBUTE *PRTCRSPCSERIALIZEDOBJECTATTRIBUTE;
+/** Pointer to a const serialized object attribute. */
+typedef RTCRSPCSERIALIZEDOBJECTATTRIBUTE const *PCRTCRSPCSERIALIZEDOBJECTATTRIBUTE;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRSPCSERIALIZEDOBJECTATTRIBUTE, RTDECL, RTCrSpcSerializedObjectAttribute, SeqCore.Asn1Core);
+
+/** @name RTCRSPCSERIALIZEDOBJECTATTRIBUTE::Type values
+ * @{ */
+/** Serialized object attribute type for page hashes version 1. */
+#define RTCRSPC_PE_IMAGE_HASHES_V1_OID "1.3.6.1.4.1.311.2.3.1"
+/** Serialized object attribute type for page hashes version 2. */
+#define RTCRSPC_PE_IMAGE_HASHES_V2_OID "1.3.6.1.4.1.311.2.3.2"
+/** @} */
+
+
+/*
+ * Set of serialized object attributes (PE image data).
+ */
+RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTCRSPCSERIALIZEDOBJECTATTRIBUTES, RTCRSPCSERIALIZEDOBJECTATTRIBUTE, RTDECL,
+ RTCrSpcSerializedObjectAttributes);
+
+/** The UUID found in RTCRSPCSERIALIZEDOBJECT::Uuid for
+ * RTCRSPCSERIALIZEDOBJECTATTRIBUTES. */
+#define RTCRSPCSERIALIZEDOBJECT_UUID_STR "d586b5a6-a1b4-6624-ae05-a217da8e60d6"
+
+
+/**
+ * Decoded encapsulated data type selection in RTCRSPCSERIALIZEDOBJECT.
+ */
+typedef enum RTCRSPCSERIALIZEDOBJECTTYPE
+{
+ /** Invalid zero value. */
+ RTCRSPCSERIALIZEDOBJECTTYPE_INVALID = 0,
+ /** Serialized object attributes (RTCRSPCSERIALIZEDOBJECT_UUID_STR / pAttribs). */
+ RTCRSPCSERIALIZEDOBJECTTYPE_ATTRIBUTES,
+ /** End of valid values. */
+ RTCRSPCSERIALIZEDOBJECTTYPE_END,
+ /** MAke sure the type is at least 32-bit wide. */
+ RTCRSPCSERIALIZEDOBJECTTYPE_32BIT_HACK = 0x7fffffff
+} RTCRSPCSERIALIZEDOBJECTTYPE;
+
+/**
+ * A serialized object (PE image data).
+ */
+typedef struct RTCRSPCSERIALIZEDOBJECT
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The UUID of the data object. */
+ RTASN1OCTETSTRING Uuid;
+ /** Serialized data object. */
+ RTASN1OCTETSTRING SerializedData;
+
+ /** Indicates the valid pointer in the union. */
+ RTCRSPCSERIALIZEDOBJECTTYPE enmType;
+ /** Union of pointers shadowing SerializedData.pEncapsulated. */
+ union
+ {
+ /** Generic core pointer. */
+ PRTASN1CORE pCore;
+ /** Pointer to decoded data if Uuid is RTCRSPCSERIALIZEDOBJECT_UUID_STR. */
+ PRTCRSPCSERIALIZEDOBJECTATTRIBUTES pData;
+ } u;
+} RTCRSPCSERIALIZEDOBJECT;
+/** Pointer to a serialized object (PE image data). */
+typedef RTCRSPCSERIALIZEDOBJECT *PRTCRSPCSERIALIZEDOBJECT;
+/** Pointer to a const serialized object (PE image data). */
+typedef RTCRSPCSERIALIZEDOBJECT const *PCRTCRSPCSERIALIZEDOBJECT;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRSPCSERIALIZEDOBJECT, RTDECL, RTCrSpcSerializedObject, SeqCore.Asn1Core);
+
+
+/**
+ * RTCRSPCSTRING choices.
+ */
+typedef enum RTCRSPCSTRINGCHOICE
+{
+ /** Invalid zero value. */
+ RTCRSPCSTRINGCHOICE_INVALID = 0,
+ /** Not present. */
+ RTCRSPCSTRINGCHOICE_NOT_PRESENT,
+ /** UCS-2 string (pUcs2). */
+ RTCRSPCSTRINGCHOICE_UCS2,
+ /** ASCII string (pAscii). */
+ RTCRSPCSTRINGCHOICE_ASCII,
+ /** End of valid values. */
+ RTCRSPCSTRINGCHOICE_END,
+ /** Blow the type up to 32-bit. */
+ RTCRSPCSTRINGCHOICE_32BIT_HACK = 0x7fffffff
+} RTCRSPCSTRINGCHOICE;
+
+/**
+ * Stupid microsoft choosy string type.
+ */
+typedef struct RTCRSPCSTRING
+{
+ /** Dummy core. */
+ RTASN1DUMMY Dummy;
+ /** Allocation of what the pointer below points to. */
+ RTASN1ALLOCATION Allocation;
+ /** Pointer choice.*/
+ RTCRSPCSTRINGCHOICE enmChoice;
+ /** Pointer union. */
+ union
+ {
+ /** Tag 0, implicit: UCS-2 (BMP) string. */
+ PRTASN1STRING pUcs2;
+ /** Tag 1, implicit: ASCII (IA5) string. */
+ PRTASN1STRING pAscii;
+ } u;
+} RTCRSPCSTRING;
+/** Pointer to a stupid microsoft string choice. */
+typedef RTCRSPCSTRING *PRTCRSPCSTRING;
+/** Pointer to a const stupid microsoft string choice. */
+typedef RTCRSPCSTRING const *PCRTCRSPCSTRING;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRSPCSTRING, RTDECL, RTCrSpcString, Dummy.Asn1Core);
+
+
+/**
+ * RTCRSPCSTRING choices.
+ */
+typedef enum RTCRSPCLINKCHOICE
+{
+ /** Invalid zero value. */
+ RTCRSPCLINKCHOICE_INVALID = 0,
+ /** Not present. */
+ RTCRSPCLINKCHOICE_NOT_PRESENT,
+ /** URL (ASCII) string (pUrl). */
+ RTCRSPCLINKCHOICE_URL,
+ /** Serialized object (pMoniker). */
+ RTCRSPCLINKCHOICE_MONIKER,
+ /** Filename (pT2). */
+ RTCRSPCLINKCHOICE_FILE,
+ /** End of valid values. */
+ RTCRSPCLINKCHOICE_END,
+ /** Blow the type up to 32-bit. */
+ RTCRSPCLINKCHOICE_32BIT_HACK = 0x7fffffff
+} RTCRSPCLINKCHOICE;
+
+/**
+ * PE image data link.
+ */
+typedef struct RTCRSPCLINK
+{
+ /** Dummy core. */
+ RTASN1DUMMY Dummy;
+ /** Allocation of what the pointer below points to. */
+ RTASN1ALLOCATION Allocation;
+ /** Pointer choice.*/
+ RTCRSPCLINKCHOICE enmChoice;
+ /** Pointer union. */
+ union
+ {
+ /** Tag 0, implicit: An URL encoded as an IA5 STRING. */
+ PRTASN1STRING pUrl;
+ /** Tag 1, implicit: A serialized object. */
+ PRTCRSPCSERIALIZEDOBJECT pMoniker;
+ /** Tag 2, explicit: The default, a file name.
+ * Documented to be set to "<<<Obsolete>>>" when used. */
+ struct
+ {
+ /** Context tag 2. */
+ RTASN1CONTEXTTAG2 CtxTag2;
+ /** The file name string. */
+ RTCRSPCSTRING File;
+ } *pT2;
+ } u;
+} RTCRSPCLINK;
+/** Poitner to a PE image data link. */
+typedef RTCRSPCLINK *PRTCRSPCLINK;
+/** Poitner to a const PE image data link. */
+typedef RTCRSPCLINK const *PCRTCRSPCLINK;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRSPCLINK, RTDECL, RTCrSpcLink, Dummy.Asn1Core);
+
+
+#if 0 /** @todo Might not be the correct bit order. */
+/**
+ * Flag values for RTCRSPCPEIMAGEDATA::Flags and RTCRSPCPEIMAGEDATA::fFlags.
+ */
+typedef enum RTCRSPCPEIMAGEFLAGS
+{
+ RTCRSPCPEIMAGEFLAGS_INCLUDE_RESOURCES = 0,
+ RTCRSPCPEIMAGEFLAGS_INCLUDE_DEBUG_INFO = 1,
+ RTCRSPCPEIMAGEFLAGS_IMPORT_ADDRESS_TABLE = 2
+} RTCRSPCPEIMAGEFLAGS;
+#endif
+
+
+/**
+ * Authenticode PE Image data.
+ */
+typedef struct RTCRSPCPEIMAGEDATA
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** One of the RTCRSPCPEIMAGEFLAGS value, default is
+ * RTCRSPCPEIMAGEFLAGS_INCLUDE_RESOURCES. Obsolete with v2 page hashes? */
+ RTASN1BITSTRING Flags;
+ /** Tag 0, explicit: Link to the data. */
+ struct
+ {
+ /** Context tag 0. */
+ RTASN1CONTEXTTAG0 CtxTag0;
+ /** Link to the data. */
+ RTCRSPCLINK File;
+ } T0;
+} RTCRSPCPEIMAGEDATA;
+/** Pointer to a authenticode PE image data representation. */
+typedef RTCRSPCPEIMAGEDATA *PRTCRSPCPEIMAGEDATA;
+/** Pointer to a const authenticode PE image data representation. */
+typedef RTCRSPCPEIMAGEDATA const *PCRTCRSPCPEIMAGEDATA;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRSPCPEIMAGEDATA, RTDECL, RTCrSpcPeImageData, SeqCore.Asn1Core);
+
+/** The object ID for SpcPeImageData. */
+#define RTCRSPCPEIMAGEDATA_OID "1.3.6.1.4.1.311.2.1.15"
+
+
+/**
+ * Data type selection for RTCRSPCATTRIBUTETYPEANDOPTIONALVALUE.
+ */
+typedef enum RTCRSPCAAOVTYPE
+{
+ /** Invalid zero entry. */
+ RTCRSPCAAOVTYPE_INVALID = 0,
+ /** Not present (pro forma). */
+ RTCRSPCAAOVTYPE_NOT_PRESENT,
+ /** Unknown object. */
+ RTCRSPCAAOVTYPE_UNKNOWN,
+ /** PE image data (pPeImage). */
+ RTCRSPCAAOVTYPE_PE_IMAGE_DATA,
+ /** End of valid values. */
+ RTCRSPCAAOVTYPE_END,
+ /** Blow up the type to at least 32-bits. */
+ RTCRSPCAAOVTYPE_32BIT_HACK
+} RTCRSPCAAOVTYPE;
+
+/**
+ * Authenticode attribute type and optional value.
+ *
+ * Note! Spec says the value should be explicitly tagged, but in real life
+ * it isn't. So, not very optional?
+ */
+typedef struct RTCRSPCATTRIBUTETYPEANDOPTIONALVALUE
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** An object ID indicating the type of the value. */
+ RTASN1OBJID Type;
+ /** Allocation of the optional data value. */
+ RTASN1ALLOCATION Allocation;
+ /** The valid pointer. */
+ RTCRSPCAAOVTYPE enmType;
+ /** The value part depends on the Type. */
+ union
+ {
+ /** RTCRSPCAAOVTYPE_UNKNOWN / Generic. */
+ PRTASN1CORE pCore;
+ /** RTCRSPCAAOVTYPE_PE_IMAGE_DATA / RTCRSPCPEIMAGEDATA_OID. */
+ PRTCRSPCPEIMAGEDATA pPeImage;
+ } uValue;
+} RTCRSPCATTRIBUTETYPEANDOPTIONALVALUE;
+/** Pointer to a authentication attribute type and optional value
+ * representation. */
+typedef RTCRSPCATTRIBUTETYPEANDOPTIONALVALUE *PRTCRSPCATTRIBUTETYPEANDOPTIONALVALUE;
+/** Pointer to a const authentication attribute type and optional value
+ * representation. */
+typedef RTCRSPCATTRIBUTETYPEANDOPTIONALVALUE const *PCRTCRSPCATTRIBUTETYPEANDOPTIONALVALUE;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRSPCATTRIBUTETYPEANDOPTIONALVALUE, RTDECL, RTCrSpcAttributeTypeAndOptionalValue, SeqCore.Asn1Core);
+
+
+/**
+ * Authenticode indirect data content.
+ */
+typedef struct RTCRSPCINDIRECTDATACONTENT
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** Additional data. */
+ RTCRSPCATTRIBUTETYPEANDOPTIONALVALUE Data;
+ /** The whole image digest. */
+ RTCRPKCS7DIGESTINFO DigestInfo;
+} RTCRSPCINDIRECTDATACONTENT;
+/** Pointer to a authenticode indirect data content representation. */
+typedef RTCRSPCINDIRECTDATACONTENT *PRTCRSPCINDIRECTDATACONTENT;
+/** Pointer to a const authenticode indirect data content representation. */
+typedef RTCRSPCINDIRECTDATACONTENT const *PCRTCRSPCINDIRECTDATACONTENT;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRSPCINDIRECTDATACONTENT, RTDECL, RTCrSpcIndirectDataContent, SeqCore.Asn1Core);
+
+/** The object ID for SpcIndirectDataContent. */
+#define RTCRSPCINDIRECTDATACONTENT_OID "1.3.6.1.4.1.311.2.1.4"
+
+/**
+ * Check the sanity of an Authenticode SPCIndirectDataContent object.
+ *
+ * @returns IPRT status code
+ * @param pIndData The Authenticode SPCIndirectDataContent to
+ * check.
+ * @param pSignedData The related signed data object.
+ * @param fFlags RTCRSPCINDIRECTDATACONTENT_SANITY_F_XXX.
+ * @param pErrInfo Optional error info.
+ */
+RTDECL(int) RTCrSpcIndirectDataContent_CheckSanityEx(PCRTCRSPCINDIRECTDATACONTENT pIndData, PCRTCRPKCS7SIGNEDDATA pSignedData,
+ uint32_t fFlags, PRTERRINFO pErrInfo);
+/** @name RTCRSPCINDIRECTDATACONTENT_SANITY_F_XXX for RTCrSpcIndirectDataContent_CheckSanityEx.
+ * @{ */
+/** The digest hash algorithm must be known to IPRT. */
+#define RTCRSPCINDIRECTDATACONTENT_SANITY_F_ONLY_KNOWN_HASH RT_BIT_32(0)
+/** PE image signing, check expectations of the spec. */
+#define RTCRSPCINDIRECTDATACONTENT_SANITY_F_PE_IMAGE RT_BIT_32(1)
+/** @} */
+
+/**
+ * Gets the first SPC serialized object attribute in a SPC PE image.
+ *
+ * @returns Pointer to the attribute with the given type, NULL if not found.
+ * @param pThis The Authenticode SpcIndirectDataContent.
+ * @param enmType The type of attribute to get.
+ */
+RTDECL(PCRTCRSPCSERIALIZEDOBJECTATTRIBUTE)
+RTCrSpcIndirectDataContent_GetPeImageObjAttrib(PCRTCRSPCINDIRECTDATACONTENT pThis,
+ RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE enmType);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_crypto_spc_h */
+