Index: /trunk/include/iprt/asn1-generator-asn1-decoder.h
===================================================================
--- /trunk/include/iprt/asn1-generator-asn1-decoder.h	(revision 52599)
+++ /trunk/include/iprt/asn1-generator-asn1-decoder.h	(revision 52600)
@@ -24,4 +24,6 @@
  */
 
+#include <iprt/string.h>
+
 #define RTASN1TMPL_PASS RTASN1TMPL_PASS_DECODE
 #include <iprt/asn1-generator-pass.h>
Index: /trunk/include/iprt/asn1-generator-init.h
===================================================================
--- /trunk/include/iprt/asn1-generator-init.h	(revision 52599)
+++ /trunk/include/iprt/asn1-generator-init.h	(revision 52600)
@@ -24,4 +24,5 @@
  */
 
+#include <iprt/string.h>
 
 #define RTASN1TMPL_PASS                 RTASN1TMPL_PASS_INIT
Index: /trunk/include/iprt/asn1-generator-pass.h
===================================================================
--- /trunk/include/iprt/asn1-generator-pass.h	(revision 52599)
+++ /trunk/include/iprt/asn1-generator-pass.h	(revision 52600)
@@ -1039,4 +1039,16 @@
     { a_MoreConstraints }
 
+# define RTASN1TMPL_MEMBER_CONSTR_U64_MIN_MAX(a_Name, uMin, uMax, a_MoreConstraints) \
+    if (RT_SUCCESS(rc)) \
+    { \
+        if (RT_UNLIKELY(   RTAsn1Integer_UnsignedCompareWithU64(&pThis->a_Name, uMin) < 0 \
+                        || RTAsn1Integer_UnsignedCompareWithU64(&pThis->a_Name, uMax) > 0) ) \
+            rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, \
+                               "%s::" #a_Name ": Out of range: %#x not in {%#llx..%#llx}", \
+                               pszErrorTag, pThis->a_Name.Asn1Core.cb > 8 ? UINT64_MAX : pThis->a_Name.uValue.u, \
+                               (uint64_t)(uMin), (uint64_t)(uMax)); \
+    } \
+    { a_MoreConstraints }
+
 # define RTASN1TMPL_MEMBER_CONSTR_PRESENT(a_Name, a_Api, a_MoreConstraints) \
     if (RT_SUCCESS(rc) && RT_UNLIKELY(!RT_CONCAT(a_Api,_IsPresent)(&pThis->a_Name))) \
@@ -1259,4 +1271,8 @@
     RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, RTASN1TMPL_ITAG_F_UP, RT_NOTHING)
 #endif
+#ifndef RTASN1TMPL_PCHOICE_ITAG_UC
+# define RTASN1TMPL_PCHOICE_ITAG_UC(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api) \
+    RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, RTASN1TMPL_ITAG_F_UC, RT_NOTHING)
+#endif
 #ifndef RTASN1TMPL_PCHOICE_ITAG_CP
 # define RTASN1TMPL_PCHOICE_ITAG_CP(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api) \
@@ -1283,4 +1299,7 @@
 #ifndef RTASN1TMPL_MEMBER_CONSTR_BITSTRING_MIN_MAX
 # define RTASN1TMPL_MEMBER_CONSTR_BITSTRING_MIN_MAX(a_Name, cMinBits, cMaxBits, a_MoreConstraints)
+#endif
+#ifndef RTASN1TMPL_MEMBER_CONSTR_U64_MIN_MAX
+# define RTASN1TMPL_MEMBER_CONSTR_U64_MIN_MAX(a_Name, uMin, uMax, a_MoreConstraints)
 #endif
 #ifndef RTASN1TMPL_MEMBER_CONSTR_PRESENT
@@ -1372,4 +1391,5 @@
 #undef RTASN1TMPL_MEMBER_CONSTR_MIN_MAX
 #undef RTASN1TMPL_MEMBER_CONSTR_BITSTRING_MIN_MAX
+#undef RTASN1TMPL_MEMBER_CONSTR_U64_MIN_MAX
 #undef RTASN1TMPL_MEMBER_CONSTR_PRESENT
 
Index: /trunk/include/iprt/asn1.h
===================================================================
--- /trunk/include/iprt/asn1.h	(revision 52599)
+++ /trunk/include/iprt/asn1.h	(revision 52600)
@@ -397,5 +397,11 @@
 
 
-/** Aliases two ASN.1 types. */
+/** Aliases two ASN.1 types, no method aliases. */
+#define RTASN1TYPE_ALIAS_TYPE_ONLY(a_TypeNm, a_AliasType) \
+    typedef a_AliasType a_TypeNm; \
+    typedef a_TypeNm *RT_CONCAT(P,a_TypeNm); \
+    typedef a_TypeNm const *RT_CONCAT(PC,a_TypeNm)
+
+/** Aliases two ASN.1 types and methods. */
 #define RTASN1TYPE_ALIAS(a_TypeNm, a_AliasType, a_ImplExtNm, a_AliasExtNm) \
     typedef a_AliasType a_TypeNm; \
Index: /trunk/include/iprt/crypto/pkcs7.h
===================================================================
--- /trunk/include/iprt/crypto/pkcs7.h	(revision 52599)
+++ /trunk/include/iprt/crypto/pkcs7.h	(revision 52600)
@@ -85,4 +85,6 @@
     /** Signing time (PKCS \#9), use pSigningTime. */
     RTCRPKCS7ATTRIBUTETYPE_SIGNING_TIME,
+    /** Microsoft timestamp info (RFC-3161) signed data, use pContentInfo. */
+    RTCRPKCS7ATTRIBUTETYPE_MS_TIMESTAMP,
     /** Blow the type up to 32-bits. */
     RTCRPKCS7ATTRIBUTETYPE_32BIT_HACK = 0x7fffffff
@@ -115,4 +117,6 @@
         /** Signing time(s) (RTCRPKCS7ATTRIBUTETYPE_SIGNING_TIME). */
         PRTASN1SETOFTIMES               pSigningTime;
+        /** Microsoft timestamp (RFC-3161 signed data). */
+        struct RTCRPKCS7SETOFCONTENTINFOS *pContentInfos;
     } uValues;
 } RTCRPKCS7ATTRIBUTE;
@@ -173,5 +177,10 @@
  * Value: SignerInfo. */
 #define RTCR_PKCS9_ID_COUNTER_SIGNATURE_OID "1.2.840.113549.1.9.6"
+/** Microsoft timestamp (RTF-3161) counter signature (SignedData).
+ * @remarks This isn't defined by PKCS \#9, but lumped in here for
+ *          convenience.  It's actually listed as SPC by MS. */
+#define RTCR_PKCS9_ID_MS_TIMESTAMP          "1.3.6.1.4.1.311.3.3.1"
 /** @} */
+
 
 /**
@@ -193,4 +202,17 @@
  */
 RTDECL(PCRTASN1TIME) RTCrPkcs7SignerInfo_GetSigningTime(PCRTCRPKCS7SIGNERINFO pThis, PCRTCRPKCS7SIGNERINFO *ppSignerInfo);
+
+
+/**
+ * Get the (first) timestamp from within a Microsoft timestamp server counter
+ * signature.
+ *
+ * @returns Pointer to the signing time if found, NULL if not.
+ * @param   pThis               The SignerInfo to search.
+ * @param   ppContentInfo       Where to return the pointer to the counter
+ *                              signature, optional.
+ */
+RTDECL(PCRTASN1TIME) RTCrPkcs7SignerInfo_GetMsTimestamp(PCRTCRPKCS7SIGNERINFO pThis,
+                                                        struct RTCRPKCS7CONTENTINFO const **ppContentInfo);
 
 
@@ -223,4 +245,14 @@
      */
     RTASN1OCTETSTRING                   Content;
+    /** Pointer to the CMS octet string that's inside the Content, NULL if PKCS \#7.
+     *
+     * Hack alert! When transitioning from PKCS \#7 to CMS, the designers decided to
+     * change things and add another wrapper.  This time we're talking about a real
+     * octet string, not like the one above which is really an explicit content tag.
+     * When constructing or decoding CMS content, this will be the same pointer as
+     * Content.pEncapsulated, while the union below will be holding the same pointer
+     * as pCmsContent->pEncapsulated.
+     */
+    PRTASN1OCTETSTRING                  pCmsContent;
     /** Same as Content.pEncapsulated, except a choice of known types. */
     union
@@ -230,4 +262,6 @@
         /** ContentType is RTCRSPCINDIRECTDATACONTENT_OID. */
         struct RTCRSPCINDIRECTDATACONTENT  *pIndirectDataContent;
+        /** ContentType is RTCRTSPTSTINFO_OID. */
+        struct RTCRTSPTSTINFO              *pTstInfo;
         /** Generic / Unknown / User. */
         PRTASN1CORE                         pCore;
@@ -238,8 +272,63 @@
 /** Pointer to the const IPRT representation of a PKCS \#7 ContentInfo. */
 typedef RTCRPKCS7CONTENTINFO const *PCRTCRPKCS7CONTENTINFO;
-
 RTASN1TYPE_STANDARD_PROTOTYPES(RTCRPKCS7CONTENTINFO, RTDECL, RTCrPkcs7ContentInfo, SeqCore.Asn1Core);
+RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTCRPKCS7SETOFCONTENTINFOS, RTCRPKCS7CONTENTINFO, RTDECL, RTCrPkcs7SetOfContentInfos);
 
 RTDECL(bool) RTCrPkcs7ContentInfo_IsSignedData(PCRTCRPKCS7CONTENTINFO pThis);
+
+
+/**
+ * PKCS \#7 Certificate choice.
+ */
+typedef enum RTCRPKCS7CERTCHOICE
+{
+    RTCRPKCS7CERTCHOICE_INVALID = 0,
+    RTCRPKCS7CERTCHOICE_X509,
+    RTCRPKCS7CERTCHOICE_EXTENDED_PKCS6,
+    RTCRPKCS7CERTCHOICE_AC_V1,
+    RTCRPKCS7CERTCHOICE_AC_V2,
+    RTCRPKCS7CERTCHOICE_OTHER,
+    RTCRPKCS7CERTCHOICE_END,
+    RTCRPKCS7CERTCHOICE_32BIT_HACK = 0x7fffffff
+} RTCRPKCS7CERTCHOICE;
+
+
+/**
+ * Common representation for PKCS \#7 ExtendedCertificateOrCertificate and the
+ * CMS CertificateChoices types.
+ */
+typedef struct RTCRPKCS7CERT
+{
+    /** Dummy ASN.1 record, not encoded. */
+    RTASN1DUMMY                         Dummy;
+    /** The value allocation. */
+    RTASN1ALLOCATION                    Allocation;
+    /** The choice of value.   */
+    RTCRPKCS7CERTCHOICE                 enmChoice;
+    /** The value union. */
+    union
+    {
+        /** Standard X.509 certificate (RTCRCMSCERTIFICATECHOICE_X509). */
+        PRTCRX509CERTIFICATE            pX509Cert;
+        /** Extended PKCS \#6 certificate (RTCRCMSCERTIFICATECHOICE_EXTENDED_PKCS6). */
+        PRTASN1CORE                     pExtendedCert;
+        /** Attribute certificate version 1 (RTCRCMSCERTIFICATECHOICE_AC_V1). */
+        PRTASN1CORE                     pAcV1;
+        /** Attribute certificate version 2 (RTCRCMSCERTIFICATECHOICE_AC_V2). */
+        PRTASN1CORE                     pAcV2;
+        /** Other certificate (RTCRCMSCERTIFICATECHOICE_OTHER). */
+        PRTASN1CORE                     pOtherCert;
+    } u;
+} RTCRPKCS7CERT;
+/** Pointer to the IPRT representation of PKCS \#7 or CMS certificate. */
+typedef RTCRPKCS7CERT *PRTCRPKCS7CERT;
+/** Pointer to the const IPRT representation of PKCS \#7 or CMS certificate. */
+typedef RTCRPKCS7CERT const *PCRTCRPKCS7CERT;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRPKCS7CERT, RTDECL, RTCrPkcs7Cert, Dummy.Asn1Core);
+RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTCRPKCS7SETOFCERTS, RTCRPKCS7CERT, RTDECL, RTCrPkcs7SetOfCerts);
+
+RTDECL(PCRTCRX509CERTIFICATE) RTCrPkcs7SetOfCerts_FindX509ByIssuerAndSerialNumber(PCRTCRPKCS7SETOFCERTS pCertificates,
+                                                                                  PCRTCRX509NAME pIssuer,
+                                                                                  PCRTASN1INTEGER pSerialNumber);
 
 
@@ -258,5 +347,5 @@
     RTCRPKCS7CONTENTINFO                ContentInfo;
     /** Certificates, optional, implicit tag 0. (Required by Authenticode.) */
-    RTCRX509CERTIFICATES                Certificates;
+    RTCRPKCS7SETOFCERTS                 Certificates;
     /** Certificate revocation lists, optional, implicit tag 1.
      * Not used by Authenticode, so currently stubbed. */
@@ -270,4 +359,5 @@
 typedef RTCRPKCS7SIGNEDDATA const *PCRTCRPKCS7SIGNEDDATA;
 RTASN1TYPE_STANDARD_PROTOTYPES(RTCRPKCS7SIGNEDDATA, RTDECL, RTCrPkcs7SignedData, SeqCore.Asn1Core);
+RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTCRPKCS7SETOFSIGNEDDATA, RTCRPKCS7SIGNEDDATA, RTDECL, RTCrPkcs7SetOfSignedData);
 
 /** PKCS \#7 SignedData object ID.  */
@@ -276,4 +366,18 @@
 /** PKCS \#7 SignedData version number 1.  */
 #define RTCRPKCS7SIGNEDDATA_V1    1
+/* No version 2 seems to exist. */
+/** CMS SignedData version number 3.
+ * This should only be used if there are version 1 attribute certificates
+ * present, or if there are version 3 SignerInfo items present, or if
+ * enmcCountInfo is not id-data (RFC-5652, section 5.1). */
+#define RTCRPKCS7SIGNEDDATA_V3    3
+/** CMS SignedData version number 4.
+ * This should only be used if there are version 2 attribute certificates
+ * present (RFC-5652, section 5.1). */
+#define RTCRPKCS7SIGNEDDATA_V4    4
+/** CMS SignedData version number 5.
+ * This should only be used if there are certificates or/and CRLs of the
+ * OTHER type present (RFC-5652, section 5.1). */
+#define RTCRPKCS7SIGNEDDATA_V5    5
 
 
@@ -384,10 +488,24 @@
  * signing time attributes and use the @a pValidationTime instead. */
 #define RTCRPKCS7VERIFY_SD_F_ALWAYS_USE_SIGNING_TIME_IF_PRESENT     RT_BIT_32(0)
+/** Same as RTCRPKCS7VERIFY_SD_F_ALWAYS_USE_SIGNING_TIME_IF_PRESENT for the MS
+ *  timestamp counter sigantures. */
+#define RTCRPKCS7VERIFY_SD_F_ALWAYS_USE_MS_TIMESTAMP_IF_PRESENT     RT_BIT_32(1)
 /** Only use signging time attributes from counter signatures. */
-#define RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE_SIGNING_TIME_ONLY    RT_BIT_32(1)
+#define RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE_SIGNING_TIME_ONLY    RT_BIT_32(2)
 /** Don't validate the counter signature containing the signing time, just use
  * it unverified.  This is useful if we don't necessarily have the root
- * certificates for the timestamp server handy, but use with great care. */
-#define RTCRPKCS7VERIFY_SD_F_USE_SIGNING_TIME_UNVERIFIED            RT_BIT_32(2)
+ * certificates for the timestamp server handy, but use with great care.
+ * @sa RTCRPKCS7VERIFY_SD_F_USE_MS_TIMESTAMP_UNVERIFIED */
+#define RTCRPKCS7VERIFY_SD_F_USE_SIGNING_TIME_UNVERIFIED            RT_BIT_32(3)
+/** Don't validate the MS counter signature containing the signing timestamp.
+ * @sa RTCRPKCS7VERIFY_SD_F_USE_SIGNING_TIME_UNVERIFIED */
+#define RTCRPKCS7VERIFY_SD_F_USE_MS_TIMESTAMP_UNVERIFIED            RT_BIT_32(4)
+/** Do not consider timestamps in microsoft counter signatures. */
+#define RTCRPKCS7VERIFY_SD_F_IGNORE_MS_TIMESTAMP                    RT_BIT_32(5)
+/** The signed data requires certificates to have the timestamp extended
+ * usage bit present.  This is used for recursivly verifying MS timestamp
+ * signatures. */
+#define RTCRPKCS7VERIFY_SD_F_USAGE_TIMESTAMPING                     RT_BIT_32(6)
+
 /** Indicates internally that we're validating a counter signature and should
  * use different rules when checking out the authenticated attributes.
Index: /trunk/include/iprt/crypto/x509.h
===================================================================
--- /trunk/include/iprt/crypto/x509.h	(revision 52599)
+++ /trunk/include/iprt/crypto/x509.h	(revision 52600)
@@ -1023,4 +1023,5 @@
 RTDECL(int) RTCrX509CertPathsSetUntrustedStore(RTCRX509CERTPATHS hCertPaths, RTCRSTORE hUntrustedStore);
 RTDECL(int) RTCrX509CertPathsSetUntrustedArray(RTCRX509CERTPATHS hCertPaths, PCRTCRX509CERTIFICATE paCerts, uint32_t cCerts);
+RTDECL(int) RTCrX509CertPathsSetUntrustedSet(RTCRX509CERTPATHS hCertPaths, struct RTCRPKCS7SETOFCERTS const *pSetOfCerts);
 RTDECL(int) RTCrX509CertPathsSetValidTime(RTCRX509CERTPATHS hCertPaths, PCRTTIME pTime);
 RTDECL(int) RTCrX509CertPathsSetValidTimeSpec(RTCRX509CERTPATHS hCertPaths, PCRTTIMESPEC pTimeSpec);
Index: /trunk/include/iprt/mangling.h
===================================================================
--- /trunk/include/iprt/mangling.h	(revision 52599)
+++ /trunk/include/iprt/mangling.h	(revision 52600)
@@ -2397,4 +2397,5 @@
 # define RTCrPkcs7SignerInfo_Enum                       RT_MANGLER(RTCrPkcs7SignerInfo_Enum)
 # define RTCrPkcs7SignerInfo_GetSigningTime             RT_MANGLER(RTCrPkcs7SignerInfo_GetSigningTime)
+# define RTCrPkcs7SignerInfo_GetMsTimestamp             RT_MANGLER(RTCrPkcs7SignerInfo_GetMsTimestamp)
 # define RTCrPkcs7SignerInfos_Compare                   RT_MANGLER(RTCrPkcs7SignerInfos_Compare)
 # define RTCrPkcs7SignerInfos_Delete                    RT_MANGLER(RTCrPkcs7SignerInfos_Delete)
@@ -2760,4 +2761,25 @@
 # define RTCrTafTrustAnchorInfo_CheckSanity             RT_MANGLER(RTCrTafTrustAnchorInfo_CheckSanity)
 # define RTCrTafTrustAnchorList_CheckSanity             RT_MANGLER(RTCrTafTrustAnchorList_CheckSanity)
+# define RTCrTspAccuracy_CheckSanity                    RT_MANGLER(RTCrTspAccuracy_CheckSanity)
+# define RTCrTspAccuracy_Clone                          RT_MANGLER(RTCrTspAccuracy_Clone)
+# define RTCrTspAccuracy_Compare                        RT_MANGLER(RTCrTspAccuracy_Compare)
+# define RTCrTspAccuracy_DecodeAsn1                     RT_MANGLER(RTCrTspAccuracy_DecodeAsn1)
+# define RTCrTspAccuracy_Delete                         RT_MANGLER(RTCrTspAccuracy_Delete)
+# define RTCrTspAccuracy_Enum                           RT_MANGLER(RTCrTspAccuracy_Enum)
+# define RTCrTspAccuracy_Init                           RT_MANGLER(RTCrTspAccuracy_Init)
+# define RTCrTspMessageImprint_CheckSanity              RT_MANGLER(RTCrTspMessageImprint_CheckSanity)
+# define RTCrTspMessageImprint_Clone                    RT_MANGLER(RTCrTspMessageImprint_Clone)
+# define RTCrTspMessageImprint_Compare                  RT_MANGLER(RTCrTspMessageImprint_Compare)
+# define RTCrTspMessageImprint_DecodeAsn1               RT_MANGLER(RTCrTspMessageImprint_DecodeAsn1)
+# define RTCrTspMessageImprint_Delete                   RT_MANGLER(RTCrTspMessageImprint_Delete)
+# define RTCrTspMessageImprint_Enum                     RT_MANGLER(RTCrTspMessageImprint_Enum)
+# define RTCrTspMessageImprint_Init                     RT_MANGLER(RTCrTspMessageImprint_Init)
+# define RTCrTspTstInfo_CheckSanity                     RT_MANGLER(RTCrTspTstInfo_CheckSanity)
+# define RTCrTspTstInfo_Clone                           RT_MANGLER(RTCrTspTstInfo_Clone)
+# define RTCrTspTstInfo_Compare                         RT_MANGLER(RTCrTspTstInfo_Compare)
+# define RTCrTspTstInfo_DecodeAsn1                      RT_MANGLER(RTCrTspTstInfo_DecodeAsn1)
+# define RTCrTspTstInfo_Delete                          RT_MANGLER(RTCrTspTstInfo_Delete)
+# define RTCrTspTstInfo_Enum                            RT_MANGLER(RTCrTspTstInfo_Enum)
+# define RTCrTspTstInfo_Init                            RT_MANGLER(RTCrTspTstInfo_Init)
 # define RTCrCertCtxRelease                             RT_MANGLER(RTCrCertCtxRelease)
 # define RTCrCertCtxRetain                              RT_MANGLER(RTCrCertCtxRetain)
Index: /trunk/src/VBox/HostDrivers/Support/Makefile.kmk
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/Makefile.kmk	(revision 52599)
+++ /trunk/src/VBox/HostDrivers/Support/Makefile.kmk	(revision 52600)
@@ -281,4 +281,8 @@
 	$(VBOX_PATH_RUNTIME_SRC)/common/crypto/taf-init.cpp \
 	$(VBOX_PATH_RUNTIME_SRC)/common/crypto/taf-sanity.cpp \
+	$(VBOX_PATH_RUNTIME_SRC)/common/crypto/tsp-asn1-decoder.cpp \
+	$(VBOX_PATH_RUNTIME_SRC)/common/crypto/tsp-core.cpp \
+	$(VBOX_PATH_RUNTIME_SRC)/common/crypto/tsp-init.cpp \
+	$(VBOX_PATH_RUNTIME_SRC)/common/crypto/tsp-sanity.cpp \
 	$(VBOX_PATH_RUNTIME_SRC)/common/checksum/alt-md2.cpp \
 	$(VBOX_PATH_RUNTIME_SRC)/common/checksum/alt-md5.cpp \
Index: /trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyImage-win.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyImage-win.cpp	(revision 52599)
+++ /trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyImage-win.cpp	(revision 52600)
@@ -1004,9 +1004,10 @@
 
     uint32_t fFlags = RTCRPKCS7VERIFY_SD_F_ALWAYS_USE_SIGNING_TIME_IF_PRESENT
+                    | RTCRPKCS7VERIFY_SD_F_ALWAYS_USE_MS_TIMESTAMP_IF_PRESENT
                     | RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE_SIGNING_TIME_ONLY;
 #ifndef IN_RING0
     if (!g_fHaveOtherRoots)
 #endif
-        fFlags |= RTCRPKCS7VERIFY_SD_F_USE_SIGNING_TIME_UNVERIFIED;
+        fFlags |= RTCRPKCS7VERIFY_SD_F_USE_SIGNING_TIME_UNVERIFIED | RTCRPKCS7VERIFY_SD_F_USE_MS_TIMESTAMP_UNVERIFIED;
     return RTCrPkcs7VerifySignedData(pContentInfo, fFlags, g_hSpcAndNtKernelSuppStore, g_hSpcAndNtKernelRootStore,
                                      &ValidationTime, supHardNtViCertVerifyCallback, pNtViRdr, pErrInfo);
Index: /trunk/src/VBox/Runtime/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Runtime/Makefile.kmk	(revision 52599)
+++ /trunk/src/VBox/Runtime/Makefile.kmk	(revision 52600)
@@ -359,4 +359,8 @@
 	common/crypto/taf-init.cpp \
 	common/crypto/taf-sanity.cpp \
+	common/crypto/tsp-asn1-decoder.cpp \
+	common/crypto/tsp-core.cpp \
+	common/crypto/tsp-init.cpp \
+	common/crypto/tsp-sanity.cpp \
 	common/crypto/store.cpp \
 	common/crypto/store-inmem.cpp \
@@ -1920,4 +1924,8 @@
 	common/crypto/taf-init.cpp \
 	common/crypto/taf-sanity.cpp \
+	common/crypto/tsp-asn1-decoder.cpp \
+	common/crypto/tsp-core.cpp \
+	common/crypto/tsp-init.cpp \
+	common/crypto/tsp-sanity.cpp \
 	common/checksum/alt-md2.cpp \
 	common/checksum/alt-sha1.cpp \
@@ -2734,4 +2742,5 @@
 spc-template.o spc-template.obj: spc-core.o spc-asn1-decoder.o spc-sanity.o spc-init.o
 taf-template.o taf-template.obj: taf-core.o taf-asn1-decoder.o taf-sanity.o taf-init.o
+tsp-template.o tsp-template.obj: tsp-core.o tsp-asn1-decoder.o tsp-sanity.o tsp-init.o
 x509-template.o x509-template.obj: x509-core.o x509-asn1-decoder.o x509-sanity.o x509-init.o
 pkcs7-template.o pkcs7-template.obj: pkcs7-core.o pkcs7-asn1-decoder.o pkcs7-sanity.o pkcs7-init.o
Index: /trunk/src/VBox/Runtime/common/asn1/asn1-cursor.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/asn1/asn1-cursor.cpp	(revision 52599)
+++ /trunk/src/VBox/Runtime/common/asn1/asn1-cursor.cpp	(revision 52600)
@@ -28,4 +28,5 @@
 *   Header Files                                                               *
 *******************************************************************************/
+#define RT_STRICT
 #include "internal/iprt.h"
 #include <iprt/asn1.h>
@@ -47,5 +48,6 @@
  *
  * For reference, 'RTSignTool verify-exe RTSignTool.exe', requires a value of 15
- * to work without hitting the limit.
+ * to work without hitting the limit for signatures with simple timestamps, and
+ * 23 (amd64/rel = ~3KB) for the new microsoft timestamp counter signatures.
  */
 #ifdef IN_RING3
Index: /trunk/src/VBox/Runtime/common/asn1/asn1-dump.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/asn1/asn1-dump.cpp	(revision 52599)
+++ /trunk/src/VBox/Runtime/common/asn1/asn1-dump.cpp	(revision 52600)
@@ -84,12 +84,11 @@
 static void rtAsn1DumpPrintIdent(PRTASN1DUMPDATA pData, uint32_t uDepth)
 {
-    uint32_t i = 0;
-    uDepth *= 2;
-    while (i < uDepth)
+    uint32_t cchLeft = uDepth * 2;
+    while (cchLeft > 0)
     {
         static char const s_szSpaces[] = "                                        ";
-        uint32_t cch = RT_MIN(uDepth, sizeof(s_szSpaces) - 1);
+        uint32_t cch = RT_MIN(cchLeft, sizeof(s_szSpaces) - 1);
         rtAsn1DumpPrintf(pData, &s_szSpaces[sizeof(s_szSpaces) - 1 - cch]);
-        i += cch;
+        cchLeft -= cch;
     }
 }
Index: /trunk/src/VBox/Runtime/common/asn1/asn1-ut-time-decode.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/asn1/asn1-ut-time-decode.cpp	(revision 52599)
+++ /trunk/src/VBox/Runtime/common/asn1/asn1-ut-time-decode.cpp	(revision 52600)
@@ -178,5 +178,5 @@
      * Check the dot.
      */
-    if (*pchFraction == '.')
+    if (*pchFraction != '.')
         return RTAsn1CursorSetInfo(pCursor, VERR_ASN1_INVALID_GENERALIZED_TIME_ENCODING,
                                    "%s: Expected GeneralizedTime fraction dot, found: '%c' ('%.*s')",
Index: /trunk/src/VBox/Runtime/common/crypto/pkcs7-asn1-decoder.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/crypto/pkcs7-asn1-decoder.cpp	(revision 52599)
+++ /trunk/src/VBox/Runtime/common/crypto/pkcs7-asn1-decoder.cpp	(revision 52600)
@@ -35,4 +35,5 @@
 #include <iprt/string.h>
 #include <iprt/crypto/spc.h>
+#include <iprt/crypto/tsp.h>
 
 #include "pkcs7-internal.h"
@@ -42,4 +43,14 @@
  * PKCS #7 ContentInfo
  */
+typedef enum RTCRPKCS7CONTENTINFOCHOICE
+{
+    RTCRPKCS7CONTENTINFOCHOICE_INVALID = 0,
+    RTCRPKCS7CONTENTINFOCHOICE_UNKNOWN,
+    RTCRPKCS7CONTENTINFOCHOICE_SIGNED_DATA,
+    RTCRPKCS7CONTENTINFOCHOICE_SPC_INDIRECT_DATA_CONTENT,
+    RTCRPKCS7CONTENTINFOCHOICE_TSP_TST_INFO,
+    RTCRPKCS7CONTENTINFOCHOICE_END,
+    RTCRPKCS7CONTENTINFOCHOICE_32BIT_HACK = 0x7fffffff
+} RTCRPKCS7CONTENTINFOCHOICE;
 
 static int rtCrPkcs7ContentInfo_DecodeExtra(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTCRPKCS7CONTENTINFO pThis,
@@ -48,37 +59,97 @@
     pThis->u.pCore = NULL;
 
-    int             rc;
-    RTASN1CURSOR    ContentCursor;
+    /*
+     * Figure the type.
+     */
+    RTCRPKCS7CONTENTINFOCHOICE  enmChoice;
+    size_t                      cbContent = 0;
     if (RTAsn1ObjId_CompareWithString(&pThis->ContentType, RTCRPKCS7SIGNEDDATA_OID) == 0)
     {
-        rc = RTAsn1MemAllocZ(&pThis->Content.EncapsulatedAllocation, (void **)&pThis->Content.pEncapsulated,
-                             sizeof(*pThis->u.pSignedData));
-        if (RT_SUCCESS(rc))
-        {
-            pThis->u.pCore = pThis->Content.pEncapsulated;
-            rc = RTAsn1CursorInitSubFromCore(pCursor, &pThis->Content.Asn1Core, &ContentCursor, "Content");
-            if (RT_SUCCESS(rc))
-                rc = RTCrPkcs7SignedData_DecodeAsn1(&ContentCursor, 0, pThis->u.pSignedData, "SignedData");
-        }
+        enmChoice = RTCRPKCS7CONTENTINFOCHOICE_SIGNED_DATA;
+        cbContent = sizeof(*pThis->u.pSignedData);
     }
     else if (RTAsn1ObjId_CompareWithString(&pThis->ContentType, RTCRSPCINDIRECTDATACONTENT_OID) == 0)
     {
-        rc = RTAsn1MemAllocZ(&pThis->Content.EncapsulatedAllocation, (void **)&pThis->Content.pEncapsulated,
-                             sizeof(*pThis->u.pIndirectDataContent));
+        enmChoice = RTCRPKCS7CONTENTINFOCHOICE_SPC_INDIRECT_DATA_CONTENT;
+        cbContent = sizeof(*pThis->u.pIndirectDataContent);
+    }
+    else if (RTAsn1ObjId_CompareWithString(&pThis->ContentType, RTCRTSPTSTINFO_OID) == 0)
+    {
+        enmChoice = RTCRPKCS7CONTENTINFOCHOICE_TSP_TST_INFO;
+        cbContent = sizeof(*pThis->u.pTstInfo);
+    }
+    else
+    {
+        enmChoice = RTCRPKCS7CONTENTINFOCHOICE_UNKNOWN;
+        cbContent = 0;
+    }
+
+    int rc = VINF_SUCCESS;
+    if (enmChoice != RTCRPKCS7CONTENTINFOCHOICE_UNKNOWN)
+    {
+        /*
+         * Detect CMS octet string and open the content cursor.
+         * Current we don't have work with any contet which is octet string,
+         * they're all sequences, which make detection so much simpler.
+         */
+        PRTASN1OCTETSTRING  pOctetString = &pThis->Content;
+        RTASN1CURSOR        ContentCursor;
+        rc = RTAsn1CursorInitSubFromCore(pCursor, &pThis->Content.Asn1Core, &ContentCursor, "Content");
+        if (   RT_SUCCESS(rc)
+            && RTAsn1CursorIsNextEx(&ContentCursor, ASN1_TAG_OCTET_STRING, ASN1_TAGFLAG_PRIMITIVE | ASN1_TAGCLASS_UNIVERSAL))
+        {
+            rc = RTAsn1MemAllocZ(&pThis->Content.EncapsulatedAllocation, (void **)&pThis->Content.pEncapsulated,
+                                 sizeof(*pOctetString));
+            if (RT_SUCCESS(rc))
+            {
+                pThis->pCmsContent = pOctetString = (PRTASN1OCTETSTRING)pThis->Content.pEncapsulated;
+                rc = RTAsn1OctetString_DecodeAsn1(&ContentCursor, 0, pOctetString, "CmsContent");
+                if (RT_SUCCESS(rc))
+                    rc = RTAsn1CursorCheckEnd(&ContentCursor);
+                if (RT_SUCCESS(rc))
+                    rc = RTAsn1CursorInitSubFromCore(pCursor, &pOctetString->Asn1Core, &ContentCursor, "CmsContent");
+            }
+        }
         if (RT_SUCCESS(rc))
         {
-            pThis->u.pCore = pThis->Content.pEncapsulated;
-            rc = RTAsn1CursorInitSubFromCore(pCursor, &pThis->Content.Asn1Core, &ContentCursor, "Content");
+            /*
+             * Allocate memory for the decoded content.
+             */
+            rc = RTAsn1MemAllocZ(&pOctetString->EncapsulatedAllocation, (void **)&pOctetString->pEncapsulated, cbContent);
             if (RT_SUCCESS(rc))
-                rc = RTCrSpcIndirectDataContent_DecodeAsn1(&ContentCursor, 0, pThis->u.pIndirectDataContent, "IndirectDataContent");
+            {
+                pThis->u.pCore = pOctetString->pEncapsulated;
+
+                /*
+                 * Decode it.
+                 */
+                switch (enmChoice)
+                {
+                    case RTCRPKCS7CONTENTINFOCHOICE_SIGNED_DATA:
+                        rc = RTCrPkcs7SignedData_DecodeAsn1(&ContentCursor, 0, pThis->u.pSignedData, "SignedData");
+                        break;
+                    case RTCRPKCS7CONTENTINFOCHOICE_SPC_INDIRECT_DATA_CONTENT:
+                        rc = RTCrSpcIndirectDataContent_DecodeAsn1(&ContentCursor, 0, pThis->u.pIndirectDataContent,
+                                                                   "IndirectDataContent");
+                        break;
+                    case RTCRPKCS7CONTENTINFOCHOICE_TSP_TST_INFO:
+                        rc = RTCrTspTstInfo_DecodeAsn1(&ContentCursor, 0, pThis->u.pTstInfo, "TstInfo");
+                        break;
+                    default:
+                        AssertFailed();
+                        rc = VERR_IPE_NOT_REACHED_DEFAULT_CASE;
+                        break;
+                }
+                if (RT_SUCCESS(rc))
+                    rc = RTAsn1CursorCheckEnd(&ContentCursor);
+                if (RT_SUCCESS(rc))
+                    return VINF_SUCCESS;
+
+                RTAsn1MemFree(&pOctetString->EncapsulatedAllocation, pOctetString->pEncapsulated);
+                pOctetString->pEncapsulated = NULL;
+                pThis->u.pCore = NULL;
+            }
         }
     }
-    else
-        return VINF_SUCCESS;
-
-    if (RT_SUCCESS(rc))
-        rc = RTAsn1CursorCheckEnd(&ContentCursor);
-    if (RT_SUCCESS(rc))
-        return VINF_SUCCESS;
     return rc;
 }
Index: /trunk/src/VBox/Runtime/common/crypto/pkcs7-core.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/crypto/pkcs7-core.cpp	(revision 52599)
+++ /trunk/src/VBox/Runtime/common/crypto/pkcs7-core.cpp	(revision 52600)
@@ -34,4 +34,5 @@
 #include <iprt/err.h>
 #include <iprt/string.h>
+#include <iprt/crypto/tsp.h>
 
 #include "pkcs7-internal.h"
@@ -127,4 +128,46 @@
 
 
+RTDECL(PCRTASN1TIME) RTCrPkcs7SignerInfo_GetMsTimestamp(PCRTCRPKCS7SIGNERINFO pThis, PCRTCRPKCS7CONTENTINFO *ppContentInfo)
+{
+    /*
+     * Assume there is only one, so no need to enumerate anything here.
+     */
+    uint32_t             cAttrsLeft = pThis->UnauthenticatedAttributes.cItems;
+    PCRTCRPKCS7ATTRIBUTE pAttr      = pThis->UnauthenticatedAttributes.paItems;
+    while (cAttrsLeft-- > 0)
+    {
+        if (pAttr->enmType == RTCRPKCS7ATTRIBUTETYPE_MS_TIMESTAMP)
+        {
+            uint32_t                cLeft        = pAttr->uValues.pContentInfos->cItems;
+            PCRTCRPKCS7CONTENTINFO  pContentInfo = &pAttr->uValues.pContentInfos->paItems[0];
+            while (cLeft-- > 0)
+            {
+                if (RTAsn1ObjId_CompareWithString(&pContentInfo->ContentType, RTCRPKCS7SIGNEDDATA_OID) == 0)
+                {
+                    if (RTAsn1ObjId_CompareWithString(&pContentInfo->u.pSignedData->ContentInfo.ContentType,
+                                                      RTCRTSPTSTINFO_OID) == 0)
+                    {
+                        if (ppContentInfo)
+                            *ppContentInfo = pContentInfo;
+                        return &pContentInfo->u.pSignedData->ContentInfo.u.pTstInfo->GenTime;
+                    }
+                }
+
+                pContentInfo++;
+            }
+        }
+        pAttr++;
+    }
+
+    /*
+     * No signature was found.
+     */
+    if (ppContentInfo)
+        *ppContentInfo = NULL;
+
+    return NULL;
+}
+
+
 /*
  * PCKS #7 ContentInfo.
@@ -138,4 +181,20 @@
 
 /*
+ * Set of some kind of certificate supported by PKCS #7 or CMS.
+ */
+
+RTDECL(PCRTCRX509CERTIFICATE)
+RTCrPkcs7SetOfCerts_FindX509ByIssuerAndSerialNumber(PCRTCRPKCS7SETOFCERTS pCertificates,
+                                                    PCRTCRX509NAME pIssuer, PCRTASN1INTEGER pSerialNumber)
+{
+    for (uint32_t i = 0; i < pCertificates->cItems; i++)
+        if (   pCertificates->paItems[i].enmChoice == RTCRPKCS7CERTCHOICE_X509
+            && RTCrX509Certificate_MatchIssuerAndSerialNumber(pCertificates->paItems[i].u.pX509Cert, pIssuer, pSerialNumber))
+            return pCertificates->paItems[i].u.pX509Cert;
+    return NULL;
+}
+
+
+/*
  * Generate the standard core code.
  */
Index: /trunk/src/VBox/Runtime/common/crypto/pkcs7-sanity.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/crypto/pkcs7-sanity.cpp	(revision 52599)
+++ /trunk/src/VBox/Runtime/common/crypto/pkcs7-sanity.cpp	(revision 52600)
@@ -47,5 +47,8 @@
     //RTAsn1Dump(&pSignedData->SeqCore.Asn1Core, 0, 0, RTAsn1DumpStrmPrintfV, g_pStdOut);
 
-    if (RTAsn1Integer_UnsignedCompareWithU32(&pSignedData->Version, RTCRPKCS7SIGNEDDATA_V1) != 0)
+    if (   RTAsn1Integer_UnsignedCompareWithU32(&pSignedData->Version, RTCRPKCS7SIGNEDDATA_V1) != 0
+        && RTAsn1Integer_UnsignedCompareWithU32(&pSignedData->Version, RTCRPKCS7SIGNEDDATA_V3) != 0
+        && RTAsn1Integer_UnsignedCompareWithU32(&pSignedData->Version, RTCRPKCS7SIGNEDDATA_V4) != 0
+        && RTAsn1Integer_UnsignedCompareWithU32(&pSignedData->Version, RTCRPKCS7SIGNEDDATA_V5) != 0)
         return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_SIGNED_DATA_VERSION, "SignedData version is %llu, expected %u",
                              pSignedData->Version.uValue.u, RTCRPKCS7SIGNEDDATA_V1);
@@ -82,11 +85,4 @@
                             "SignedData.Certifcates is empty, expected at least one certificate");
 
-    if (pSignedData->Certificates.cItems > 0)
-    {
-        int rc = RTCrX509Certificates_CheckSanity(&pSignedData->Certificates, 0, pErrInfo, "SignedData.T0.Certificates");
-        if (RT_FAILURE(rc))
-            return rc;
-    }
-
     /*
      * Crls.
@@ -127,7 +123,7 @@
 
         PCRTCRX509CERTIFICATE pCert;
-        pCert = RTCrX509Certificates_FindByIssuerAndSerialNumber(&pSignedData->Certificates,
-                                                                 &pSignerInfo->IssuerAndSerialNumber.Name,
-                                                                 &pSignerInfo->IssuerAndSerialNumber.SerialNumber);
+        pCert = RTCrPkcs7SetOfCerts_FindX509ByIssuerAndSerialNumber(&pSignedData->Certificates,
+                                                                    &pSignerInfo->IssuerAndSerialNumber.Name,
+                                                                    &pSignerInfo->IssuerAndSerialNumber.SerialNumber);
         if (!pCert && (fFlags & RTCRPKCS7SIGNEDDATA_SANITY_F_SIGNING_CERT_PRESENT))
             return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_SIGNER_CERT_NOT_SHIPPED,
@@ -146,4 +142,5 @@
 
         /* Digest encryption algorithm. */
+#if 0  /** @todo Unimportant: Seen timestamp signatures specifying pkcs1-Sha256WithRsaEncryption in SignerInfo and just RSA in the certificate.  Figure out how to compare the two. */
         if (   pCert
             && RTCrX509AlgorithmIdentifier_Compare(&pSignerInfo->DigestEncryptionAlgorithm,
@@ -153,4 +150,5 @@
                                  i, pSignerInfo->DigestEncryptionAlgorithm.Algorithm.szObjId,
                                  pCert->TbsCertificate.SubjectPublicKeyInfo.Algorithm.Algorithm.szObjId);
+#endif
 
         /* Authenticated attributes we know. */
Index: /trunk/src/VBox/Runtime/common/crypto/pkcs7-template.h
===================================================================
--- /trunk/src/VBox/Runtime/common/crypto/pkcs7-template.h	(revision 52599)
+++ /trunk/src/VBox/Runtime/common/crypto/pkcs7-template.h	(revision 52600)
@@ -59,4 +59,6 @@
 RTASN1TMPL_MEMBER_DYN(          uValues,    pSigningTime,   RTASN1SETOFTIMES,           RTAsn1SetOfTimes,           Allocation,
     enmType, RTCRPKCS7ATTRIBUTETYPE_SIGNING_TIME,   RTAsn1ObjId_CompareWithString(&pThis->Type, RTCR_PKCS9_ID_SIGNING_TIME_OID) == 0);
+RTASN1TMPL_MEMBER_DYN(          uValues,    pContentInfos,  RTCRPKCS7SETOFCONTENTINFOS, RTCrPkcs7SetOfContentInfos, Allocation,
+    enmType, RTCRPKCS7ATTRIBUTETYPE_MS_TIMESTAMP,   RTAsn1ObjId_CompareWithString(&pThis->Type, RTCR_PKCS9_ID_MS_TIMESTAMP) == 0);
 RTASN1TMPL_MEMBER_DYN_DEFAULT(  uValues,    pCores,         RTASN1SETOFCORES,           RTAsn1SetOfCores,           Allocation,
     enmType, RTCRPKCS7ATTRIBUTETYPE_UNKNOWN);
@@ -122,9 +124,21 @@
 RTASN1TMPL_MEMBER(              DigestAlgorithms,           RTCRX509ALGORITHMIDENTIFIERS,   RTCrX509AlgorithmIdentifiers);
 RTASN1TMPL_MEMBER(              ContentInfo,                RTCRPKCS7CONTENTINFO,           RTCrPkcs7ContentInfo);
-RTASN1TMPL_MEMBER_OPT_ITAG(     Certificates,               RTCRX509CERTIFICATES,           RTCrX509Certificates,   0);
+RTASN1TMPL_MEMBER_OPT_ITAG(     Certificates,               RTCRPKCS7SETOFCERTS,            RTCrPkcs7SetOfCerts,    0);
 RTASN1TMPL_MEMBER_OPT_ITAG(     Crls,                       RTASN1CORE,                     RTAsn1Core,             1);
 RTASN1TMPL_MEMBER(              SignerInfos,                RTCRPKCS7SIGNERINFOS,           RTCrPkcs7SignerInfos);
 RTASN1TMPL_EXEC_CHECK_SANITY(   rc = rtCrPkcs7SignedData_CheckSanityExtra(pThis, fFlags, pErrInfo, pszErrorTag) ) /* no ; */
 RTASN1TMPL_END_SEQCORE();
+#undef RTASN1TMPL_TYPE
+#undef RTASN1TMPL_EXT_NAME
+#undef RTASN1TMPL_INT_NAME
+
+
+/*
+ * Set of PCKS #7 SignedData.
+ */
+#define RTASN1TMPL_TYPE         RTCRPKCS7SETOFSIGNEDDATA
+#define RTASN1TMPL_EXT_NAME     RTCrPkcs7SetOfSignedData
+#define RTASN1TMPL_INT_NAME     rtCrPkcs7SetOfSignedData
+RTASN1TMPL_SET_OF(RTCRPKCS7SIGNEDDATA, RTCrPkcs7SignedData);
 #undef RTASN1TMPL_TYPE
 #undef RTASN1TMPL_EXT_NAME
@@ -163,2 +177,44 @@
 #undef RTASN1TMPL_INT_NAME
 
+
+/*
+ * Set of PCKS #7 ContentInfo.
+ */
+#define RTASN1TMPL_TYPE         RTCRPKCS7SETOFCONTENTINFOS
+#define RTASN1TMPL_EXT_NAME     RTCrPkcs7SetOfContentInfos
+#define RTASN1TMPL_INT_NAME     rtCrPkcs7SetOfContentInfos
+RTASN1TMPL_SET_OF(RTCRPKCS7CONTENTINFO, RTCrPkcs7ContentInfo);
+#undef RTASN1TMPL_TYPE
+#undef RTASN1TMPL_EXT_NAME
+#undef RTASN1TMPL_INT_NAME
+
+
+/*
+ * One PKCS #7 ExtendedCertificateOrCertificate or a CMS CertificateChoices (sic).
+ */
+#define RTASN1TMPL_TYPE         RTCRPKCS7CERT
+#define RTASN1TMPL_EXT_NAME     RTCrPkcs7Cert
+#define RTASN1TMPL_INT_NAME     rtCrPkcs7Cert
+RTASN1TMPL_BEGIN_PCHOICE();
+RTASN1TMPL_PCHOICE_ITAG_UC(     ASN1_TAG_SEQUENCE, RTCRPKCS7CERTCHOICE_X509, u.pX509Cert, X509Cert,     RTCRX509CERTIFICATE, RTCrX509Certificate);
+RTASN1TMPL_PCHOICE_ITAG(        0, RTCRPKCS7CERTCHOICE_EXTENDED_PKCS6, u.pExtendedCert,   ExtendedCert, RTASN1CORE, RTAsn1Core);
+RTASN1TMPL_PCHOICE_ITAG(        1, RTCRPKCS7CERTCHOICE_AC_V1,          u.pAcV1,           AcV1,         RTASN1CORE, RTAsn1Core);
+RTASN1TMPL_PCHOICE_ITAG(        2, RTCRPKCS7CERTCHOICE_AC_V2,          u.pAcV2,           AcV2,         RTASN1CORE, RTAsn1Core);
+RTASN1TMPL_PCHOICE_ITAG(        3, RTCRPKCS7CERTCHOICE_OTHER,          u.pOtherCert,      OtherCert,    RTASN1CORE, RTAsn1Core);
+RTASN1TMPL_END_PCHOICE();
+#undef RTASN1TMPL_TYPE
+#undef RTASN1TMPL_EXT_NAME
+#undef RTASN1TMPL_INT_NAME
+
+
+/*
+ * Set of PKCS #7 ExtendedCertificateOrCertificate or a CMS CertificateChoices.
+ */
+#define RTASN1TMPL_TYPE         RTCRPKCS7SETOFCERTS
+#define RTASN1TMPL_EXT_NAME     RTCrPkcs7SetOfCerts
+#define RTASN1TMPL_INT_NAME     rtCrPkcs7SetOfCerts
+RTASN1TMPL_SET_OF(RTCRPKCS7CERT, RTCrPkcs7Cert);
+#undef RTASN1TMPL_TYPE
+#undef RTASN1TMPL_EXT_NAME
+#undef RTASN1TMPL_INT_NAME
+
Index: /trunk/src/VBox/Runtime/common/crypto/pkcs7-verify.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/crypto/pkcs7-verify.cpp	(revision 52599)
+++ /trunk/src/VBox/Runtime/common/crypto/pkcs7-verify.cpp	(revision 52600)
@@ -71,6 +71,8 @@
         if (RT_SUCCESS(rcOssl))
         {
-            for (uint32_t i = 0; i < pContentInfo->u.pSignedData->Certificates.cItems; i++)
-                rtCrOpenSslAddX509CertToStack(pAddCerts, &pContentInfo->u.pSignedData->Certificates.paItems[i]);
+            PCRTCRPKCS7SETOFCERTS pCerts = &pContentInfo->u.pSignedData->Certificates;
+            for (uint32_t i = 0; i < pCerts->cItems; i++)
+                if (pCerts->paItems[i].enmChoice == RTCRPKCS7CERTCHOICE_X509)
+                    rtCrOpenSslAddX509CertToStack(pAddCerts, pCerts->paItems[i].u.pX509Cert);
 
 
@@ -398,7 +400,7 @@
     {
         hSignerCertSrc = NULL;
-        pSignerCert = RTCrX509Certificates_FindByIssuerAndSerialNumber(&pSignedData->Certificates,
-                                                                       &pSignerInfo->IssuerAndSerialNumber.Name,
-                                                                       &pSignerInfo->IssuerAndSerialNumber.SerialNumber);
+        pSignerCert = RTCrPkcs7SetOfCerts_FindX509ByIssuerAndSerialNumber(&pSignedData->Certificates,
+                                                                          &pSignerInfo->IssuerAndSerialNumber.Name,
+                                                                          &pSignerInfo->IssuerAndSerialNumber.SerialNumber);
         if (!pSignerCert)
             return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_SIGNED_DATA_CERT_NOT_FOUND,
@@ -426,7 +428,5 @@
                 rc = RTCrX509CertPathsSetUntrustedStore(hCertPaths, hAdditionalCerts);
             if (pSignedData->Certificates.cItems > 0 && RT_SUCCESS(rc))
-                rc = RTCrX509CertPathsSetUntrustedArray(hCertPaths,
-                                                        pSignedData->Certificates.paItems,
-                                                        pSignedData->Certificates.cItems);
+                rc = RTCrX509CertPathsSetUntrustedSet(hCertPaths, &pSignedData->Certificates);
             if (RT_SUCCESS(rc))
             {
@@ -586,6 +586,4 @@
         return rc;
 
-    AssertReturn(!(fFlags & RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE), VERR_INVALID_FLAGS);
-
     /*
      * Hash the content info.
@@ -640,4 +638,6 @@
              * Validate the signed infos.
              */
+            uint32_t fPrimaryVccFlags = !(fFlags & RTCRPKCS7VERIFY_SD_F_USAGE_TIMESTAMPING)
+                                      ? RTCRPKCS7VCC_F_SIGNED_DATA : RTCRPKCS7VCC_F_TIMESTAMP;
             rc = VERR_CR_PKCS7_NO_SIGNER_INFOS;
             for (i = 0; i < pSignedData->SignerInfos.cItems; i++)
@@ -651,4 +651,6 @@
                 /*
                  * See if we can find a trusted signing time.
+                 * (Note that while it would make sense splitting up this function,
+                 * we need to carry a lot of arguments around, so better not.)
                  */
                 bool                    fDone              = false;
@@ -667,5 +669,5 @@
                             rc = rtCrPkcs7VerifySignerInfo(pSignerInfo, pSignedData, hThisDigest, fFlags,
                                                            hAdditionalCerts, hTrustedCerts, &ThisValidationTime,
-                                                           pfnVerifyCert, RTCRPKCS7VCC_F_SIGNED_DATA | RTCRPKCS7VCC_F_TIMESTAMP,
+                                                           pfnVerifyCert, fPrimaryVccFlags | RTCRPKCS7VCC_F_TIMESTAMP,
                                                            pvUser, pErrInfo);
                         }
@@ -680,5 +682,5 @@
                                 rc = rtCrPkcs7VerifySignerInfo(pSignerInfo, pSignedData, hThisDigest, fFlags, hAdditionalCerts,
                                                                hTrustedCerts, &ThisValidationTime,
-                                                               pfnVerifyCert, RTCRPKCS7VCC_F_SIGNED_DATA, pvUser, pErrInfo);
+                                                               pfnVerifyCert, fPrimaryVccFlags, pvUser, pErrInfo);
                         }
                         fDone = RT_SUCCESS(rc)
@@ -693,9 +695,45 @@
 
                 /*
+                 * If not luck, check for microsoft timestamp counter signatures.
+                 */
+                if (!fDone && !(fFlags & RTCRPKCS7VERIFY_SD_F_IGNORE_MS_TIMESTAMP))
+                {
+                    PCRTCRPKCS7CONTENTINFO pSignedTimestamp = NULL;
+                    pSignedTime = RTCrPkcs7SignerInfo_GetMsTimestamp(pSignerInfo, &pSignedTimestamp);
+                    if (pSignedTime)
+                    {
+                        RTTIMESPEC ThisValidationTime;
+                        if (RT_LIKELY(RTTimeImplode(&ThisValidationTime, &pSignedTime->Time)))
+                        {
+                            rc = VINF_SUCCESS;
+                            if (!(fFlags & RTCRPKCS7VERIFY_SD_F_USE_MS_TIMESTAMP_UNVERIFIED))
+                                rc = RTCrPkcs7VerifySignedData(pSignedTimestamp,
+                                                               fFlags | RTCRPKCS7VERIFY_SD_F_IGNORE_MS_TIMESTAMP
+                                                               | RTCRPKCS7VERIFY_SD_F_USAGE_TIMESTAMPING,
+                                                               hAdditionalCerts, hTrustedCerts, &ThisValidationTime,
+                                                               pfnVerifyCert, pvUser, pErrInfo);
+
+                            if (RT_SUCCESS(rc))
+                                rc = rtCrPkcs7VerifySignerInfo(pSignerInfo, pSignedData, hThisDigest, fFlags, hAdditionalCerts,
+                                                               hTrustedCerts, &ThisValidationTime,
+                                                               pfnVerifyCert, fPrimaryVccFlags, pvUser, pErrInfo);
+                            fDone = RT_SUCCESS(rc)
+                                 || (fFlags & RTCRPKCS7VERIFY_SD_F_ALWAYS_USE_MS_TIMESTAMP_IF_PRESENT);
+                        }
+                        else
+                        {
+                            rc = RTErrInfoSet(pErrInfo, VERR_INTERNAL_ERROR_3, "RTTimeImplode failed");
+                            fDone = true;
+                        }
+
+                    }
+                }
+
+                /*
                  * No valid signing time found, use the one specified instead.
                  */
                 if (!fDone)
                     rc = rtCrPkcs7VerifySignerInfo(pSignerInfo, pSignedData, hThisDigest, fFlags, hAdditionalCerts, hTrustedCerts,
-                                                   pValidationTime, pfnVerifyCert, RTCRPKCS7VCC_F_SIGNED_DATA, pvUser, pErrInfo);
+                                                   pValidationTime, pfnVerifyCert, fPrimaryVccFlags, pvUser, pErrInfo);
                 RTCrDigestRelease(hThisDigest);
                 if (RT_FAILURE(rc))
@@ -721,4 +759,7 @@
      * Verify using OpenSSL and combine the results (should be identical).
      */
+    /** @todo figure out how to verify MS timstamp signatures using OpenSSL. */
+    if (fFlags & RTCRPKCS7VERIFY_SD_F_USAGE_TIMESTAMPING)
+        return rc;
     int rcOssl = rtCrPkcs7VerifySignedDataUsingOpenSsl(pContentInfo, fFlags, hAdditionalCerts, hTrustedCerts,
                                                        pvContent, cbContent, RT_SUCCESS(rc) ? pErrInfo : NULL);
Index: /trunk/src/VBox/Runtime/common/crypto/tsp-asn1-decoder.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/crypto/tsp-asn1-decoder.cpp	(revision 52600)
+++ /trunk/src/VBox/Runtime/common/crypto/tsp-asn1-decoder.cpp	(revision 52600)
@@ -0,0 +1,41 @@
+/* $Id$ */
+/** @file
+ * IPRT - Crypto - Time-Stamp Protocol (RFC-3161), Decoder for ASN.1.
+ */
+
+/*
+ * Copyright (C) 2006-2014 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.
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "internal/iprt.h"
+#include <iprt/crypto/tsp.h>
+
+#include "tsp-internal.h"
+
+
+/*
+ * Generate the code.
+ */
+#include <iprt/asn1-generator-asn1-decoder.h>
+
Index: /trunk/src/VBox/Runtime/common/crypto/tsp-core.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/crypto/tsp-core.cpp	(revision 52600)
+++ /trunk/src/VBox/Runtime/common/crypto/tsp-core.cpp	(revision 52600)
@@ -0,0 +1,42 @@
+/* $Id$ */
+/** @file
+ * IPRT - Crypto - Time-Stamp Protocol (RFC-3161), Core API.
+ */
+
+/*
+ * Copyright (C) 2006-2014 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.
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "internal/iprt.h"
+#include <iprt/crypto/tsp.h>
+
+#include "tsp-internal.h"
+
+
+/*
+ * Generate the code.
+ */
+#include <iprt/asn1-generator-core.h>
+
+
Index: /trunk/src/VBox/Runtime/common/crypto/tsp-init.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/crypto/tsp-init.cpp	(revision 52600)
+++ /trunk/src/VBox/Runtime/common/crypto/tsp-init.cpp	(revision 52600)
@@ -0,0 +1,41 @@
+/* $Id$ */
+/** @file
+ * IPRT - Crypto - Time-Stamp Protocol (RFC-3161), Initialization API.
+ */
+
+/*
+ * Copyright (C) 2006-2014 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.
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "internal/iprt.h"
+#include <iprt/crypto/tsp.h>
+
+#include "tsp-internal.h"
+
+
+/*
+ * Generate the code.
+ */
+#include <iprt/asn1-generator-init.h>
+
Index: /trunk/src/VBox/Runtime/common/crypto/tsp-internal.h
===================================================================
--- /trunk/src/VBox/Runtime/common/crypto/tsp-internal.h	(revision 52600)
+++ /trunk/src/VBox/Runtime/common/crypto/tsp-internal.h	(revision 52600)
@@ -0,0 +1,35 @@
+/* $Id$ */
+/** @file
+ * IPRT - Crypto - TSP, Internal Header.
+ */
+
+/*
+ * Copyright (C) 2006-2014 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 ___common_crypto_tsp_internal_h
+#define ___common_crypto_tsp_internal_h
+
+#define RTASN1TMPL_TEMPLATE_FILE "../common/crypto/tsp-template.h"
+#include <iprt/asn1-generator-internal-header.h>
+
+#endif
+
Index: /trunk/src/VBox/Runtime/common/crypto/tsp-sanity.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/crypto/tsp-sanity.cpp	(revision 52600)
+++ /trunk/src/VBox/Runtime/common/crypto/tsp-sanity.cpp	(revision 52600)
@@ -0,0 +1,42 @@
+/* $Id$ */
+/** @file
+ * IPRT - Crypto - Time-Stamp Protocol (RFC-3161), Sanity Checkers.
+ */
+
+/*
+ * Copyright (C) 2006-2014 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.
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "internal/iprt.h"
+#include <iprt/crypto/tsp.h>
+
+#include "tsp-internal.h"
+
+
+/*
+ * Generate the code.
+ */
+#include <iprt/asn1-generator-sanity.h>
+
+
Index: /trunk/src/VBox/Runtime/common/crypto/tsp-template.h
===================================================================
--- /trunk/src/VBox/Runtime/common/crypto/tsp-template.h	(revision 52600)
+++ /trunk/src/VBox/Runtime/common/crypto/tsp-template.h	(revision 52600)
@@ -0,0 +1,98 @@
+/* $Id$ */
+/** @file
+ * IPRT - Crypto - Time-Stamp Protocol (RFC-3161), Code Generator Template.
+ */
+
+/*
+ * Copyright (C) 2006-2014 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.
+ */
+
+#define RTASN1TMPL_DECL         RTDECL
+
+/*
+ * MessageImprint
+ */
+#define RTASN1TMPL_TYPE         RTCRTSPMESSAGEIMPRINT
+#define RTASN1TMPL_EXT_NAME     RTCrTspMessageImprint
+#define RTASN1TMPL_INT_NAME     rtCrTspMessageImprint
+RTASN1TMPL_BEGIN_SEQCORE();
+RTASN1TMPL_MEMBER(              HashAlgorithm,      RTCRX509ALGORITHMIDENTIFIER,    RTCrX509AlgorithmIdentifier);
+RTASN1TMPL_MEMBER(              HashedMessage,      RTASN1OCTETSTRING,              RTAsn1OctetString);
+RTASN1TMPL_END_SEQCORE();
+#undef RTASN1TMPL_TYPE
+#undef RTASN1TMPL_EXT_NAME
+#undef RTASN1TMPL_INT_NAME
+
+/*
+ * TimeStampReq
+ */
+
+/*
+ * PKIStatusInfo
+ */
+
+/*
+ * TimeStampResp
+ */
+
+/*
+ * Accuracy
+ */
+#define RTASN1TMPL_TYPE         RTCRTSPACCURACY
+#define RTASN1TMPL_EXT_NAME     RTCrTspAccuracy
+#define RTASN1TMPL_INT_NAME     rtCrTspAccuracy
+RTASN1TMPL_BEGIN_SEQCORE();
+RTASN1TMPL_MEMBER_EX(           Seconds,    RTASN1INTEGER,  RTAsn1Integer,
+                                RTASN1TMPL_MEMBER_CONSTR_U64_MIN_MAX(Millis, 1, UINT64_MAX, RT_NOTHING));
+/** @todo The Millis and Micros fields makes no sense if Seconds > 1, while the
+ *        Micros field makes no sense with Millis > 1.  Add constraints
+ *        expressing this dependency. */
+RTASN1TMPL_MEMBER_OPT_ITAG_EX(  Millis,     RTASN1INTEGER,  RTAsn1Integer, 0, RTASN1TMPL_ITAG_F_CP,
+                                RTASN1TMPL_MEMBER_CONSTR_U64_MIN_MAX(Millis, 1, 999, RT_NOTHING));
+RTASN1TMPL_MEMBER_OPT_ITAG_EX(  Micros,     RTASN1INTEGER,  RTAsn1Integer, 1, RTASN1TMPL_ITAG_F_CP,
+                                RTASN1TMPL_MEMBER_CONSTR_U64_MIN_MAX(Millis, 1, 999, RT_NOTHING));
+RTASN1TMPL_END_SEQCORE();
+#undef RTASN1TMPL_TYPE
+#undef RTASN1TMPL_EXT_NAME
+#undef RTASN1TMPL_INT_NAME
+
+
+/*
+ * TSTInfo
+ */
+#define RTASN1TMPL_TYPE         RTCRTSPTSTINFO
+#define RTASN1TMPL_EXT_NAME     RTCrTspTstInfo
+#define RTASN1TMPL_INT_NAME     rtCrTspTstInfo
+RTASN1TMPL_BEGIN_SEQCORE();
+RTASN1TMPL_MEMBER(              Version,            RTASN1INTEGER,                  RTAsn1Integer);
+RTASN1TMPL_MEMBER(              Policy,             RTASN1OBJID,                    RTAsn1ObjId);
+RTASN1TMPL_MEMBER(              MessageImprint,     RTCRTSPMESSAGEIMPRINT,          RTCrTspMessageImprint);
+RTASN1TMPL_MEMBER(              SerialNumber,       RTASN1INTEGER,                  RTAsn1Integer);
+RTASN1TMPL_MEMBER(              GenTime,            RTASN1TIME,                     RTAsn1GeneralizedTime);
+RTASN1TMPL_MEMBER_OPT_ITAG_UC(  Accuracy,           RTCRTSPACCURACY,                RTCrTspAccuracy,                ASN1_TAG_SEQUENCE);
+RTASN1TMPL_MEMBER_DEF_ITAG_UP(  Ordering,           RTASN1BOOLEAN,                  RTAsn1Boolean,                  ASN1_TAG_BOOLEAN, 0 /*False*/);
+RTASN1TMPL_MEMBER_OPT_ITAG_UP(  Nonce,              RTASN1INTEGER,                  RTAsn1Integer,                  ASN1_TAG_INTEGER);
+RTASN1TMPL_MEMBER_OPT_XTAG(     T0, CtxTag0, Tsa,   RTCRX509GENERALNAME,            RTCrX509GeneralName,            0);
+RTASN1TMPL_MEMBER_OPT_ITAG(     Extensions,         RTCRX509EXTENSION,              RTCrX509Extension,              1);
+RTASN1TMPL_END_SEQCORE();
+#undef RTASN1TMPL_TYPE
+#undef RTASN1TMPL_EXT_NAME
+#undef RTASN1TMPL_INT_NAME
+
Index: /trunk/src/VBox/Runtime/common/crypto/x509-certpaths.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/crypto/x509-certpaths.cpp	(revision 52599)
+++ /trunk/src/VBox/Runtime/common/crypto/x509-certpaths.cpp	(revision 52600)
@@ -39,4 +39,5 @@
 #include <iprt/list.h>
 #include <iprt/time.h>
+#include <iprt/crypto/pkcs7.h> /* PCRTCRPKCS7SETOFCERTS */
 #include <iprt/crypto/store.h>
 
@@ -92,8 +93,9 @@
 #define RTCRX509CERTPATHNODE_SRC_NONE               0
 #define RTCRX509CERTPATHNODE_SRC_TARGET             1
-#define RTCRX509CERTPATHNODE_SRC_UNTRUSTED_ARRAY    2
-#define RTCRX509CERTPATHNODE_SRC_UNTRUSTED_STORE    3
-#define RTCRX509CERTPATHNODE_SRC_TRUSTED_STORE      4
-#define RTCRX509CERTPATHNODE_SRC_TRUSTED_CERT       5
+#define RTCRX509CERTPATHNODE_SRC_UNTRUSTED_SET      2
+#define RTCRX509CERTPATHNODE_SRC_UNTRUSTED_ARRAY    3
+#define RTCRX509CERTPATHNODE_SRC_UNTRUSTED_STORE    4
+#define RTCRX509CERTPATHNODE_SRC_TRUSTED_STORE      5
+#define RTCRX509CERTPATHNODE_SRC_TRUSTED_CERT       6
 #define RTCRX509CERTPATHNODE_SRC_IS_TRUSTED(uSrc)   ((uSrc) >= RTCRX509CERTPATHNODE_SRC_TRUSTED_STORE)
 /** @} */
@@ -164,9 +166,10 @@
     /** Store of untrusted certificates. */
     RTCRSTORE                       hUntrustedStore;
-    /** Array of untrusted certificates, typically from the protocol (like the
-     *  certificates member of PKCS \#7 SignedData). */
+    /** Array of untrusted certificates, typically from the protocol. */
     PCRTCRX509CERTIFICATE           paUntrustedCerts;
     /** Number of entries in paUntrusted. */
     uint32_t                        cUntrustedCerts;
+    /** Set of untrusted PKCS \#7 / CMS certificatess. */
+    PCRTCRPKCS7SETOFCERTS           pUntrustedCertsSet;
 
     /** UTC time we're going to validate the path at, requires
@@ -364,4 +367,5 @@
             pThis->hUntrustedStore              = NIL_RTCRSTORE;
             pThis->paUntrustedCerts             = NULL; /* Referencing user memory. */
+            pThis->pUntrustedCertsSet           = NULL; /* Referencing user memory. */
             pThis->papInitialUserPolicySet      = NULL; /* Referencing user memory. */
             pThis->pInitialPermittedSubtrees    = NULL; /* Referencing user memory. */
@@ -438,4 +442,15 @@
     pThis->paUntrustedCerts = paCerts;
     pThis->cUntrustedCerts  = cCerts;
+    return VINF_SUCCESS;
+}
+
+
+RTDECL(int) RTCrX509CertPathsSetUntrustedSet(RTCRX509CERTPATHS hCertPaths, PCRTCRPKCS7SETOFCERTS pSetOfCerts)
+{
+    PRTCRX509CERTPATHSINT pThis = hCertPaths;
+    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+    AssertReturn(pThis->u32Magic == RTCRX509CERTPATHSINT_MAGIC, VERR_INVALID_HANDLE);
+
+    pThis->pUntrustedCertsSet = pSetOfCerts;
     return VINF_SUCCESS;
 }
@@ -694,5 +709,21 @@
             if (RTCrX509Certificate_MatchSubjectOrAltSubjectByRfc5280(&pThis->paUntrustedCerts[i], pIssuer))
                 rtCrX509CertPathsAddIssuer(pThis, pNode, &pThis->paUntrustedCerts[i], NULL,
-                                                 RTCRX509CERTPATHNODE_SRC_UNTRUSTED_ARRAY);
+                                           RTCRX509CERTPATHNODE_SRC_UNTRUSTED_ARRAY);
+
+    /** @todo Rainy day: Should abstract the untrusted array and set so we don't get
+     *        unnecessary PKCS7/CMS header dependencies. */
+
+    /*
+     * Untrusted set.
+     */
+    if (pThis->pUntrustedCertsSet)
+    {
+        uint32_t const  cCerts  = pThis->pUntrustedCertsSet->cItems;
+        PCRTCRPKCS7CERT paCerts = pThis->pUntrustedCertsSet->paItems;
+        for (uint32_t i = 0; i < cCerts; i++)
+            if (   paCerts[i].enmChoice == RTCRPKCS7CERTCHOICE_X509
+                && RTCrX509Certificate_MatchSubjectOrAltSubjectByRfc5280(paCerts[i].u.pX509Cert, pIssuer))
+                rtCrX509CertPathsAddIssuer(pThis, pNode, paCerts[i].u.pX509Cert, NULL, RTCRX509CERTPATHNODE_SRC_UNTRUSTED_SET);
+    }
 }
 
@@ -1084,4 +1115,5 @@
     {
         case RTCRX509CERTPATHNODE_SRC_TARGET:           return "target";
+        case RTCRX509CERTPATHNODE_SRC_UNTRUSTED_SET:    return "untrusted_set";
         case RTCRX509CERTPATHNODE_SRC_UNTRUSTED_ARRAY:  return "untrusted_array";
         case RTCRX509CERTPATHNODE_SRC_UNTRUSTED_STORE:  return "untrusted_store";
Index: /trunk/src/VBox/Runtime/tools/RTSignTool.cpp
===================================================================
--- /trunk/src/VBox/Runtime/tools/RTSignTool.cpp	(revision 52599)
+++ /trunk/src/VBox/Runtime/tools/RTSignTool.cpp	(revision 52600)
@@ -183,6 +183,6 @@
                     PCRTCRPKCS7ISSUERANDSERIALNUMBER pISN = &pSd->SignerInfos.paItems[0].IssuerAndSerialNumber;
                     PCRTCRX509CERTIFICATE pCert;
-                    pCert = RTCrX509Certificates_FindByIssuerAndSerialNumber(&pSd->Certificates,
-                                                                            &pISN->Name, &pISN->SerialNumber);
+                    pCert = RTCrPkcs7SetOfCerts_FindX509ByIssuerAndSerialNumber(&pSd->Certificates,
+                                                                                &pISN->Name, &pISN->SerialNumber);
                     if (pCert)
                     {
@@ -404,5 +404,6 @@
             return RTCrPkcs7VerifySignedData(pContentInfo,
                                              RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE_SIGNING_TIME_ONLY
-                                             | RTCRPKCS7VERIFY_SD_F_ALWAYS_USE_SIGNING_TIME_IF_PRESENT,
+                                             | RTCRPKCS7VERIFY_SD_F_ALWAYS_USE_SIGNING_TIME_IF_PRESENT
+                                             | RTCRPKCS7VERIFY_SD_F_ALWAYS_USE_MS_TIMESTAMP_IF_PRESENT,
                                              pState->hAdditionalStore, pState->hRootStore, &ValidationTime,
                                              VerifyExecCertVerifyCallback, pState, pErrInfo);
