Index: trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyImage-win.cpp
===================================================================
--- trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyImage-win.cpp	(revision 52536)
+++ trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyImage-win.cpp	(revision 52537)
@@ -874,5 +874,5 @@
  */
 static DECLCALLBACK(int) supHardNtViCertVerifyCallback(PCRTCRX509CERTIFICATE pCert, RTCRX509CERTPATHS hCertPaths,
-                                                       void *pvUser, PRTERRINFO pErrInfo)
+                                                       uint32_t fFlags, void *pvUser, PRTERRINFO pErrInfo)
 {
     PSUPHNTVIRDR pNtViRdr = (PSUPHNTVIRDR)pvUser;
@@ -894,6 +894,7 @@
      * Standard code signing capabilites required.
      */
-    int rc = RTCrPkcs7VerifyCertCallbackCodeSigning(pCert, hCertPaths, NULL, pErrInfo);
-    if (RT_SUCCESS(rc))
+    int rc = RTCrPkcs7VerifyCertCallbackCodeSigning(pCert, hCertPaths, fFlags, NULL, pErrInfo);
+    if (   RT_SUCCESS(rc)
+        && (fFlags & RTCRPKCS7VCC_F_SIGNED_DATA))
     {
         /*
@@ -992,11 +993,20 @@
 
     /*
-     * Verify the signature.
+     * Verify the signature.  We instruct the verifier to use the signing time
+     * counter signature present when present, falling back on the timestamp
+     * planted by the linker when absent.  In ring-0 we don't have all the
+     * necessary timestamp server root certificate info, so we have to allow
+     * using counter signatures unverified there.
      */
     RTTIMESPEC ValidationTime;
     RTTimeSpecSetSeconds(&ValidationTime, pNtViRdr->uTimestamp);
 
-    return RTCrPkcs7VerifySignedData(pContentInfo, 0, g_hSpcAndNtKernelSuppStore, g_hSpcAndNtKernelRootStore, &ValidationTime,
-                                     supHardNtViCertVerifyCallback, pNtViRdr, pErrInfo);
+    uint32_t fFlags = RTCRPKCS7VERIFY_SD_F_ALWAYS_USE_SIGNING_TIME_IF_PRESENT
+                    | RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE_SIGNING_TIME_ONLY;
+#ifdef IN_RING0
+    fFlags |= RTCRPKCS7VERIFY_SD_F_USE_SIGNING_TIME_UNVERIFIED;
+#endif
+    return RTCrPkcs7VerifySignedData(pContentInfo, fFlags, g_hSpcAndNtKernelSuppStore, g_hSpcAndNtKernelRootStore,
+                                     &ValidationTime, supHardNtViCertVerifyCallback, pNtViRdr, pErrInfo);
 }
 
Index: trunk/src/VBox/Runtime/common/crypto/pkcs7-core.cpp
===================================================================
--- trunk/src/VBox/Runtime/common/crypto/pkcs7-core.cpp	(revision 52536)
+++ trunk/src/VBox/Runtime/common/crypto/pkcs7-core.cpp	(revision 52537)
@@ -39,4 +39,93 @@
 
 /*
+ * PCKS #7 SignerInfo
+ */
+
+RTDECL(PCRTASN1TIME) RTCrPkcs7SignerInfo_GetSigningTime(PCRTCRPKCS7SIGNERINFO pThis, PCRTCRPKCS7SIGNERINFO *ppSignerInfo)
+{
+    /*
+     * Check the immediate level, unless we're continuing a previous search.
+     * Note! We ASSUME a single signing time attribute, which simplifies the interface.
+     */
+    uint32_t                cAttrsLeft;
+    PCRTCRPKCS7ATTRIBUTE    pAttr;
+    if (!ppSignerInfo || *ppSignerInfo == NULL)
+    {
+        cAttrsLeft = pThis->AuthenticatedAttributes.cItems;
+        pAttr      = pThis->AuthenticatedAttributes.paItems;
+        while (cAttrsLeft-- > 0)
+        {
+            if (   pAttr->enmType == RTCRPKCS7ATTRIBUTETYPE_SIGNING_TIME
+                && pAttr->uValues.pSigningTime->cItems > 0)
+            {
+                if (ppSignerInfo)
+                    *ppSignerInfo = pThis;
+                return &pAttr->uValues.pSigningTime->paItems[0];
+            }
+            pAttr++;
+        }
+    }
+    else if (*ppSignerInfo == pThis)
+        *ppSignerInfo = NULL;
+
+    /*
+     * Check counter signatures.
+     */
+    cAttrsLeft = pThis->UnauthenticatedAttributes.cItems;
+    pAttr      = pThis->UnauthenticatedAttributes.paItems;
+    while (cAttrsLeft-- > 0)
+    {
+        if (pAttr->enmType == RTCRPKCS7ATTRIBUTETYPE_COUNTER_SIGNATURES)
+        {
+            uint32_t              cSignatures = pAttr->uValues.pCounterSignatures->cItems;
+            PCRTCRPKCS7SIGNERINFO pSignature  = pAttr->uValues.pCounterSignatures->paItems;
+
+            /* Skip past the previous counter signature. */
+            if (ppSignerInfo && *ppSignerInfo != NULL)
+                while (cSignatures > 0)
+                {
+                    cSignatures--;
+                    if (pSignature == *ppSignerInfo)
+                    {
+                        *ppSignerInfo = NULL;
+                        pSignature++;
+                        break;
+                    }
+                    pSignature++;
+                }
+
+            /* Search the counter signatures (if any remaining). */
+            while (cSignatures-- > 0)
+            {
+                uint32_t                cCounterAttrsLeft = pSignature->AuthenticatedAttributes.cItems;
+                PCRTCRPKCS7ATTRIBUTE    pCounterAttr      = pSignature->AuthenticatedAttributes.paItems;
+                while (cCounterAttrsLeft-- > 0)
+                {
+                    if (   pCounterAttr->enmType == RTCRPKCS7ATTRIBUTETYPE_SIGNING_TIME
+                        && pCounterAttr->uValues.pSigningTime->cItems > 0)
+                    {
+                        if (ppSignerInfo)
+                            *ppSignerInfo = pSignature;
+                        return &pCounterAttr->uValues.pSigningTime->paItems[0];
+                    }
+                    pCounterAttr++;
+                }
+                pSignature++;
+            }
+        }
+        pAttr++;
+    }
+
+    /*
+     * No signing timestamp found.
+     */
+    if (ppSignerInfo)
+        *ppSignerInfo = NULL;
+
+    return NULL;
+}
+
+
+/*
  * PCKS #7 ContentInfo.
  */
Index: trunk/src/VBox/Runtime/common/crypto/pkcs7-verify.cpp
===================================================================
--- trunk/src/VBox/Runtime/common/crypto/pkcs7-verify.cpp	(revision 52536)
+++ trunk/src/VBox/Runtime/common/crypto/pkcs7-verify.cpp	(revision 52537)
@@ -117,14 +117,19 @@
 
 
-/**
- * @callback_method_impl{RTCRPKCS7VERIFYCERTCALLBACK,
- *  Default implementation that checks for the DigitalSignature KeyUsage bit.}
- */
-RTDECL(int) RTCrPkcs7VerifyCertCallbackDefault(PCRTCRX509CERTIFICATE pCert, RTCRX509CERTPATHS hCertPaths,
-                                               void *pvUser, PRTERRINFO pErrInfo)
-{
-    /*
-     * Check for the digital signature key usage.
-     */
+
+static int rtCrPkcs7VerifyCertUsageTimstamping(PCRTCRX509CERTIFICATE pCert, PRTERRINFO pErrInfo)
+{
+    if (!(pCert->TbsCertificate.T3.fFlags & RTCRX509TBSCERTIFICATE_F_PRESENT_EXT_KEY_USAGE))
+        return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_KEY_USAGE_MISMATCH, "No extended key usage certificate attribute.");
+    if (!(pCert->TbsCertificate.T3.fExtKeyUsage & (RTCRX509CERT_EKU_F_TIMESTAMPING | RTCRX509CERT_EKU_F_MS_TIMESTAMP_SIGNING)))
+        return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_KEY_USAGE_MISMATCH, "fExtKeyUsage=%#x, missing %#x (time stamping)",
+                             pCert->TbsCertificate.T3.fExtKeyUsage,
+                             RTCRX509CERT_EKU_F_TIMESTAMPING | RTCRX509CERT_EKU_F_MS_TIMESTAMP_SIGNING);
+    return VINF_SUCCESS;
+}
+
+
+static int rtCrPkcs7VerifyCertUsageDigitalSignature(PCRTCRX509CERTIFICATE pCert, PRTERRINFO pErrInfo)
+{
     if (   (pCert->TbsCertificate.T3.fFlags & RTCRX509TBSCERTIFICATE_F_PRESENT_KEY_USAGE)
         && !(pCert->TbsCertificate.T3.fKeyUsage & RTCRX509CERT_KEY_USAGE_F_DIGITAL_SIGNATURE))
@@ -137,28 +142,57 @@
 /**
  * @callback_method_impl{RTCRPKCS7VERIFYCERTCALLBACK,
+ *  Default implementation that checks for the DigitalSignature KeyUsage bit.}
+ */
+RTDECL(int) RTCrPkcs7VerifyCertCallbackDefault(PCRTCRX509CERTIFICATE pCert, RTCRX509CERTPATHS hCertPaths, uint32_t fFlags,
+                                               void *pvUser, PRTERRINFO pErrInfo)
+{
+    int rc = VINF_SUCCESS;
+
+    if (fFlags & RTCRPKCS7VCC_F_SIGNED_DATA)
+        rc = rtCrPkcs7VerifyCertUsageDigitalSignature(pCert, pErrInfo);
+
+    if (   (fFlags & RTCRPKCS7VCC_F_TIMESTAMP)
+        && RT_SUCCESS(rc))
+        rc = rtCrPkcs7VerifyCertUsageTimstamping(pCert, pErrInfo);
+
+    return rc;
+}
+
+
+/**
+ * @callback_method_impl{RTCRPKCS7VERIFYCERTCALLBACK,
  * Standard code signing.  Use this for Microsoft SPC.}
  */
-RTDECL(int) RTCrPkcs7VerifyCertCallbackCodeSigning(PCRTCRX509CERTIFICATE pCert, RTCRX509CERTPATHS hCertPaths,
+RTDECL(int) RTCrPkcs7VerifyCertCallbackCodeSigning(PCRTCRX509CERTIFICATE pCert, RTCRX509CERTPATHS hCertPaths, uint32_t fFlags,
                                                    void *pvUser, PRTERRINFO pErrInfo)
 {
-    /*
-     * Check for the digital signature key usage.  Not required to be present.
-     */
-    if (pCert->TbsCertificate.T3.fFlags & RTCRX509TBSCERTIFICATE_F_PRESENT_KEY_USAGE)
-    {
-        if (!(pCert->TbsCertificate.T3.fKeyUsage & RTCRX509CERT_KEY_USAGE_F_DIGITAL_SIGNATURE))
-            return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_KEY_USAGE_MISMATCH, "fKeyUsage=%#x, missing %#x",
-                                 pCert->TbsCertificate.T3.fKeyUsage, RTCRX509CERT_KEY_USAGE_F_DIGITAL_SIGNATURE);
-    }
-
-    /*
-     * Check the extended key usage bits if present.
-     */
-    if (!(pCert->TbsCertificate.T3.fFlags & RTCRX509TBSCERTIFICATE_F_PRESENT_EXT_KEY_USAGE))
-        return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_KEY_USAGE_MISMATCH, "No extended key usage certificate attribute.");
-    if (!(pCert->TbsCertificate.T3.fExtKeyUsage & RTCRX509CERT_EKU_F_CODE_SIGNING))
-        return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_KEY_USAGE_MISMATCH, "fExtKeyUsage=%#x, missing %#x",
-                             pCert->TbsCertificate.T3.fExtKeyUsage, RTCRX509CERT_EKU_F_CODE_SIGNING);
-    return VINF_SUCCESS;
+    int rc = VINF_SUCCESS;
+    if (fFlags & RTCRPKCS7VCC_F_SIGNED_DATA)
+    {
+        /*
+         * If KeyUsage is present it must include digital signature.
+         */
+        rc = rtCrPkcs7VerifyCertUsageDigitalSignature(pCert, pErrInfo);
+        if (RT_SUCCESS(rc))
+        {
+            /*
+             * The extended usage 'code signing' must be present.
+             */
+            if (!(pCert->TbsCertificate.T3.fFlags & RTCRX509TBSCERTIFICATE_F_PRESENT_EXT_KEY_USAGE))
+                return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_KEY_USAGE_MISMATCH, "No extended key usage certificate attribute.");
+            if (!(pCert->TbsCertificate.T3.fExtKeyUsage & RTCRX509CERT_EKU_F_CODE_SIGNING))
+                return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_KEY_USAGE_MISMATCH, "fExtKeyUsage=%#x, missing %#x",
+                                     pCert->TbsCertificate.T3.fExtKeyUsage, RTCRX509CERT_EKU_F_CODE_SIGNING);
+        }
+    }
+
+    /*
+     * Timestamping too?
+     */
+    if (   (fFlags & RTCRPKCS7VCC_F_TIMESTAMP)
+        && RT_SUCCESS(rc))
+        rc = rtCrPkcs7VerifyCertUsageTimstamping(pCert, pErrInfo);
+
+    return rc;
 }
 
@@ -206,8 +240,9 @@
             AssertReturn(pAttrib->uValues.pObjIds->cItems == 1, VERR_CR_PKCS7_INTERNAL_ERROR);
 
-            if (RTAsn1ObjId_Compare(&pAttrib->uValues.pObjIds->paItems[0], &pSignedData->ContentInfo.ContentType) != 0)
-                return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_CONTENT_TYPE_ATTRIB_MISMATCH,
-                                     "Expected content-type %s, found %s",
-                                     &pAttrib->uValues.pObjIds->paItems[0], pSignedData->ContentInfo.ContentType.szObjId);
+            if (   !(fFlags & RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE) /* See note about microsoft below. */
+                && RTAsn1ObjId_Compare(&pAttrib->uValues.pObjIds->paItems[0], &pSignedData->ContentInfo.ContentType) != 0)
+                   return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_CONTENT_TYPE_ATTRIB_MISMATCH,
+                                        "Expected content-type %s, found %s",
+                                        &pAttrib->uValues.pObjIds->paItems[0], pSignedData->ContentInfo.ContentType.szObjId);
             cContentTypes++;
         }
@@ -239,6 +274,18 @@
     }
 
-    AssertReturn(cContentTypes == 1, VERR_CR_PKCS7_INTERNAL_ERROR);
-    AssertReturn(cMessageDigests == 1, VERR_CR_PKCS7_INTERNAL_ERROR);
+    /*
+     * Full error reporting here as we don't currently extensively santiy check
+     * counter signatures.
+     * Note! Microsoft includes content info in their timestamp counter signatures,
+     *       at least for vista, despite the RFC-3852 stating counter signatures
+     *       "MUST NOT contain a content-type".
+     */
+    if (RT_UNLIKELY(   cContentTypes != 1
+                    && !(fFlags & RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE)))
+        return RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_MISSING_CONTENT_TYPE_ATTRIB,
+                            "Missing authenticated content-type attribute.");
+    if (RT_UNLIKELY(cMessageDigests != 1))
+        return RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_MISSING_MESSAGE_DIGEST_ATTRIB,
+                            "Missing authenticated message-digest attribute.");
 
     /*
@@ -272,4 +319,38 @@
 
 /**
+ * Find the handle to the digest given by the specified SignerInfo.
+ *
+ * @returns IPRT status code
+ * @param   phDigest            Where to return a referenced digest handle on
+ *                              success.
+ * @param   pSignedData         The signed data structure.
+ * @param   pSignerInfo         The signer info.
+ * @param   pahDigests          Array of content digests that runs parallel to
+ *                              pSignedData->DigestAlgorithms.
+ * @param   pErrInfo            Where to store additional error details,
+ *                              optional.
+ */
+static int rtCrPkcs7VerifyFindDigest(PRTCRDIGEST phDigest, PCRTCRPKCS7SIGNEDDATA pSignedData,
+                                     PCRTCRPKCS7SIGNERINFO pSignerInfo, PRTCRDIGEST pahDigests, PRTERRINFO pErrInfo)
+{
+    uint32_t iDigest = pSignedData->DigestAlgorithms.cItems;
+    while (iDigest-- > 0)
+        if (RTCrX509AlgorithmIdentifier_Compare(&pSignedData->DigestAlgorithms.paItems[iDigest],
+                                                &pSignerInfo->DigestAlgorithm) == 0)
+        {
+            RTCRDIGEST hDigest = pahDigests[iDigest];
+            uint32_t cRefs = RTCrDigestRetain(hDigest);
+            AssertReturn(cRefs != UINT32_MAX, VERR_CR_PKCS7_INTERNAL_ERROR);
+            *phDigest = hDigest;
+            return VINF_SUCCESS;
+        }
+
+    return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_DIGEST_ALGO_NOT_FOUND_IN_LIST,
+                         "SignerInfo.DigestAlgorithm %s not found.",
+                         pSignerInfo->DigestAlgorithm.Algorithm.szObjId);
+}
+
+
+/**
  * Verifies one signature on a PKCS \#7 SignedData.
  *
@@ -277,6 +358,6 @@
  * @param   pSignerInfo         The signature.
  * @param   pSignedData         The SignedData.
- * @param   pahDigests          Array of content digests that runs parallel to
- *                              pSignedData->DigestAlgorithms.
+ * @param   hDigests            The digest corresponding to
+ *                              pSignerInfo->DigestAlgorithm.
  * @param   fFlags              Verficiation flags.
  * @param   hAdditionalCerts    Store containing optional certificates,
@@ -286,4 +367,5 @@
  *                              certificates chains at.
  * @param   pfnVerifyCert       Signing certificate verification callback.
+ * @param   fVccFlags           Signing certificate verification callback flags.
  * @param   pvUser              Callback parameter.
  * @param   pErrInfo            Where to store additional error details,
@@ -291,14 +373,8 @@
  */
 static int rtCrPkcs7VerifySignerInfo(PCRTCRPKCS7SIGNERINFO pSignerInfo, PCRTCRPKCS7SIGNEDDATA pSignedData,
-                                     PRTCRDIGEST pahDigests, uint32_t fFlags, RTCRSTORE hAdditionalCerts, RTCRSTORE hTrustedCerts,
-                                     PCRTTIMESPEC pValidationTime, RTCRPKCS7VERIFYCERTCALLBACK pfnVerifyCert, void *pvUser,
-                                     PRTERRINFO pErrInfo)
-{
-    /*
-     * Check for counter signatures with timestamp.  Verify the signature for
-     * the current time if not present.
-     */
-    /** @todo timestamp counter signatures. */
-
+                                     RTCRDIGEST hDigest, uint32_t fFlags, RTCRSTORE hAdditionalCerts, RTCRSTORE hTrustedCerts,
+                                     PCRTTIMESPEC pValidationTime, PFNRTCRPKCS7VERIFYCERTCALLBACK pfnVerifyCert,
+                                     uint32_t fVccFlags, void *pvUser, PRTERRINFO pErrInfo)
+{
     /*
      * Locate the certificate used for signing.
@@ -364,5 +440,5 @@
                  */
                 if (RT_SUCCESS(rc))
-                    rc = pfnVerifyCert(pSignerCert, hCertPaths, pvUser, pErrInfo);
+                    rc = pfnVerifyCert(pSignerCert, hCertPaths, fVccFlags, pvUser, pErrInfo);
             }
             else
@@ -375,62 +451,52 @@
      */
     else
-        rc = pfnVerifyCert(pSignerCert, NIL_RTCRX509CERTPATHS, pvUser, pErrInfo);
-
-    /*
-     * Find the digest that is signed and reference it so we can replace it
-     * below if necessary.
-     */
-    RTCRDIGEST hDigest = NIL_RTCRDIGEST;
-    uint32_t iDigest = pSignedData->DigestAlgorithms.cItems;
-    while (iDigest-- > 0)
-        if (RTCrX509AlgorithmIdentifier_Compare(&pSignedData->DigestAlgorithms.paItems[iDigest],
-                                                &pSignerInfo->DigestAlgorithm) == 0)
-        {
-            hDigest = pahDigests[iDigest];
-            uint32_t cRefs = RTCrDigestRetain(hDigest);
-            AssertStmt(cRefs != UINT32_MAX, cRefs = NIL_RTCRDIGEST; rc = VERR_CR_PKCS7_INTERNAL_ERROR);
-            break;
-        }
-    if (hDigest == NIL_RTCRDIGEST && RT_SUCCESS(rc))
-        rc = RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_DIGEST_ALGO_NOT_FOUND_IN_LIST,
-                           "SignerInfo.DigestAlgorithm %s not found.",
-                           pSignerInfo->DigestAlgorithm.Algorithm.szObjId);
-
-    /*
-     * If there are authenticated attributes, we've got more work before we
-     * can verify the signature.
+        rc = pfnVerifyCert(pSignerCert, NIL_RTCRX509CERTPATHS, fVccFlags, pvUser, pErrInfo);
+
+    /*
+     * Reference the digest so we can safely replace with one on the
+     * authenticated attributes below.
      */
     if (   RT_SUCCESS(rc)
-        && RTCrPkcs7Attributes_IsPresent(&pSignerInfo->AuthenticatedAttributes))
-        rc = rtCrPkcs7VerifySignerInfoAuthAttribs(pSignerInfo, pSignedData, &hDigest, fFlags, pErrInfo);
-
-    /*
-     * Verify the signature.
-     */
-    if (RT_SUCCESS(rc))
-    {
-        RTCRPKIXSIGNATURE hSignature;
-        rc = RTCrPkixSignatureCreateByObjId(&hSignature,
-                                            &pSignerCert->TbsCertificate.SubjectPublicKeyInfo.Algorithm.Algorithm,
-                                            false /*fSigning*/,
-                                            &pSignerCert->TbsCertificate.SubjectPublicKeyInfo.SubjectPublicKey,
-                                            &pSignerInfo->DigestEncryptionAlgorithm.Parameters);
+        && RTCrDigestRetain(hDigest) != UINT32_MAX)
+    {
+        /*
+         * If there are authenticated attributes, we've got more work before we
+         * can verify the signature.
+         */
+        if (   RT_SUCCESS(rc)
+            && RTCrPkcs7Attributes_IsPresent(&pSignerInfo->AuthenticatedAttributes))
+            rc = rtCrPkcs7VerifySignerInfoAuthAttribs(pSignerInfo, pSignedData, &hDigest, fFlags, pErrInfo);
+
+        /*
+         * Verify the signature.
+         */
         if (RT_SUCCESS(rc))
         {
-            /** @todo Check that DigestEncryptionAlgorithm is compatible with hSignature
-             *        (this is not vital). */
-            rc = RTCrPkixSignatureVerifyOctetString(hSignature, hDigest, &pSignerInfo->EncryptedDigest);
-            if (RT_FAILURE(rc))
-                rc = RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_SIGNATURE_VERIFICATION_FAILED,
-                                   "Signature verficiation failed: %Rrc", rc);
-            RTCrPkixSignatureRelease(hSignature);
-        }
-        else
-            rc = RTErrInfoSetF(pErrInfo, rc, "Failure to instantiate public key algorithm [IPRT]: %s (%s)",
-                               pSignerCert->TbsCertificate.SubjectPublicKeyInfo.Algorithm.Algorithm.szObjId,
-                               pSignerInfo->DigestEncryptionAlgorithm.Algorithm.szObjId);
-    }
-
-    RTCrDigestRelease(hDigest);
+            RTCRPKIXSIGNATURE hSignature;
+            rc = RTCrPkixSignatureCreateByObjId(&hSignature,
+                                                &pSignerCert->TbsCertificate.SubjectPublicKeyInfo.Algorithm.Algorithm,
+                                                false /*fSigning*/,
+                                                &pSignerCert->TbsCertificate.SubjectPublicKeyInfo.SubjectPublicKey,
+                                                &pSignerInfo->DigestEncryptionAlgorithm.Parameters);
+            if (RT_SUCCESS(rc))
+            {
+                /** @todo Check that DigestEncryptionAlgorithm is compatible with hSignature
+                 *        (this is not vital). */
+                rc = RTCrPkixSignatureVerifyOctetString(hSignature, hDigest, &pSignerInfo->EncryptedDigest);
+                if (RT_FAILURE(rc))
+                    rc = RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_SIGNATURE_VERIFICATION_FAILED,
+                                       "Signature verficiation failed: %Rrc", rc);
+                RTCrPkixSignatureRelease(hSignature);
+            }
+            else
+                rc = RTErrInfoSetF(pErrInfo, rc, "Failure to instantiate public key algorithm [IPRT]: %s (%s)",
+                                   pSignerCert->TbsCertificate.SubjectPublicKeyInfo.Algorithm.Algorithm.szObjId,
+                                   pSignerInfo->DigestEncryptionAlgorithm.Algorithm.szObjId);
+        }
+
+        RTCrDigestRelease(hDigest);
+    }
+    else if (RT_SUCCESS(rc))
+        rc = VERR_CR_PKCS7_INTERNAL_ERROR;
     RTCrCertCtxRelease(pSignerCertCtx);
     return rc;
@@ -438,7 +504,69 @@
 
 
+/**
+ * Verifies a counter signature.
+ *
+ * @returns IPRT status code.
+ * @param   pCounterSignerInfo  The counter signature.
+ * @param   pPrimarySignerInfo  The primary signature (can be a counter
+ *                              signature too if nested).
+ * @param   pSignedData         The SignedData.
+ * @param   fFlags              Verficiation flags.
+ * @param   hAdditionalCerts    Store containing optional certificates,
+ *                              optional.
+ * @param   hTrustedCerts       Store containing trusted certificates, required.
+ * @param   pValidationTime     The time we're supposed to validate the
+ *                              certificates chains at.
+ * @param   pfnVerifyCert       Signing certificate verification callback.
+ * @param   fVccFlags           Signing certificate verification callback flags.
+ * @param   pvUser              Callback parameter.
+ * @param   pErrInfo            Where to store additional error details,
+ *                              optional.
+ */
+static int rtCrPkcs7VerifyCounterSignerInfo(PCRTCRPKCS7SIGNERINFO pCounterSignerInfo, PCRTCRPKCS7SIGNERINFO pPrimarySignerInfo,
+                                            PCRTCRPKCS7SIGNEDDATA pSignedData, uint32_t fFlags,
+                                            RTCRSTORE hAdditionalCerts, RTCRSTORE hTrustedCerts, PCRTTIMESPEC pValidationTime,
+                                            PFNRTCRPKCS7VERIFYCERTCALLBACK pfnVerifyCert, uint32_t fVccFlags,
+                                            void *pvUser, PRTERRINFO pErrInfo)
+{
+    /*
+     * Calculate the digest we need to verify.
+     */
+    RTCRDIGEST hDigest;
+    int rc = RTCrDigestCreateByObjId(&hDigest, &pCounterSignerInfo->DigestAlgorithm.Algorithm);
+    if (RT_SUCCESS(rc))
+    {
+        rc = RTCrDigestUpdate(hDigest,
+                              pPrimarySignerInfo->EncryptedDigest.Asn1Core.uData.pv,
+                              pPrimarySignerInfo->EncryptedDigest.Asn1Core.cb);
+        if (RT_SUCCESS(rc))
+            rc = RTCrDigestFinal(hDigest, NULL, 0);
+        if (RT_SUCCESS(rc))
+        {
+            /*
+             * Pass it on to the common SignerInfo verifier function.
+             */
+            rc = rtCrPkcs7VerifySignerInfo(pCounterSignerInfo, pSignedData, hDigest,
+                                           fFlags | RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE,
+                                           hAdditionalCerts, hTrustedCerts, pValidationTime,
+                                           pfnVerifyCert, fVccFlags, pvUser, pErrInfo);
+
+        }
+        else
+            rc = RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_DIGEST_CALC_ERROR,
+                               "Hashing for counter signature failed unexpectedly: %Rrc", rc);
+        RTCrDigestRelease(hDigest);
+    }
+    else
+        rc = RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_DIGEST_CREATE_ERROR, "Error creating digest for '%s': %Rrc",
+                           pCounterSignerInfo->DigestAlgorithm.Algorithm.szObjId, rc);
+
+    return rc;
+}
+
+
 RTDECL(int) RTCrPkcs7VerifySignedData(PCRTCRPKCS7CONTENTINFO pContentInfo, uint32_t fFlags,
                                       RTCRSTORE hAdditionalCerts, RTCRSTORE hTrustedCerts,
-                                      PCRTTIMESPEC pValidationTime, PRTCRPKCS7VERIFYCERTCALLBACK pfnVerifyCert, void *pvUser,
+                                      PCRTTIMESPEC pValidationTime, PFNRTCRPKCS7VERIFYCERTCALLBACK pfnVerifyCert, void *pvUser,
                                       PRTERRINFO pErrInfo)
 {
@@ -458,4 +586,6 @@
         return rc;
 
+    AssertReturn(!(fFlags & RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE), VERR_INVALID_FLAGS);
+
     /*
      * Hash the content info.
@@ -513,7 +643,60 @@
             for (i = 0; i < pSignedData->SignerInfos.cItems; i++)
             {
-                rc = rtCrPkcs7VerifySignerInfo(&pSignedData->SignerInfos.paItems[i], pSignedData, ahDigests,
-                                               fFlags, hAdditionalCerts, hTrustedCerts, pValidationTime,
-                                               pfnVerifyCert, pvUser, pErrInfo);
+                PCRTCRPKCS7SIGNERINFO   pSignerInfo       = &pSignedData->SignerInfos.paItems[i];
+                RTCRDIGEST              hThisDigest;
+                rc = rtCrPkcs7VerifyFindDigest(&hThisDigest, pSignedData, pSignerInfo, ahDigests, pErrInfo);
+                if (RT_FAILURE(rc))
+                    break;
+
+                /*
+                 * See if we can find a trusted signing time.
+                 */
+                bool                    fDone              = false;
+                PCRTCRPKCS7SIGNERINFO   pSigningTimeSigner = NULL;
+                PCRTASN1TIME            pSignedTime;
+                while (   !fDone
+                       && (pSignedTime = RTCrPkcs7SignerInfo_GetSigningTime(pSignerInfo, &pSigningTimeSigner)) != NULL)
+                {
+                    RTTIMESPEC ThisValidationTime;
+                    if (RT_LIKELY(RTTimeImplode(&ThisValidationTime, &pSignedTime->Time)))
+                    {
+                        if (pSigningTimeSigner == pSignerInfo)
+                        {
+                            if (fFlags & RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE_SIGNING_TIME_ONLY)
+                                continue;
+                            rc = rtCrPkcs7VerifySignerInfo(pSignerInfo, pSignedData, hThisDigest, fFlags,
+                                                           hAdditionalCerts, hTrustedCerts, &ThisValidationTime,
+                                                           pfnVerifyCert, RTCRPKCS7VCC_F_SIGNED_DATA | RTCRPKCS7VCC_F_TIMESTAMP,
+                                                           pvUser, pErrInfo);
+                        }
+                        else
+                        {
+                            rc = VINF_SUCCESS;
+                            if (!(fFlags & RTCRPKCS7VERIFY_SD_F_USE_SIGNING_TIME_UNVERIFIED))
+                                rc = rtCrPkcs7VerifyCounterSignerInfo(pSigningTimeSigner, pSignerInfo, pSignedData, fFlags,
+                                                                      hAdditionalCerts, hTrustedCerts, &ThisValidationTime,
+                                                                      pfnVerifyCert, RTCRPKCS7VCC_F_TIMESTAMP, pvUser, pErrInfo);
+                            if (RT_SUCCESS(rc))
+                                rc = rtCrPkcs7VerifySignerInfo(pSignerInfo, pSignedData, hThisDigest, fFlags, hAdditionalCerts,
+                                                               hTrustedCerts, &ThisValidationTime,
+                                                               pfnVerifyCert, RTCRPKCS7VCC_F_SIGNED_DATA, pvUser, pErrInfo);
+                        }
+                        fDone = RT_SUCCESS(rc)
+                             || (fFlags & RTCRPKCS7VERIFY_SD_F_ALWAYS_USE_SIGNING_TIME_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);
+                RTCrDigestRelease(hThisDigest);
                 if (RT_FAILURE(rc))
                     break;
Index: trunk/src/VBox/Runtime/common/crypto/pkix-signature-rsa.cpp
===================================================================
--- trunk/src/VBox/Runtime/common/crypto/pkix-signature-rsa.cpp	(revision 52536)
+++ trunk/src/VBox/Runtime/common/crypto/pkix-signature-rsa.cpp	(revision 52537)
@@ -227,6 +227,13 @@
  * @param   hDigest         The digest which hash to turn into a signature.
  * @param   cbEncodedMsg    The desired encoded message length.
+ * @param   fNoDigestInfo   If true, skip the DigestInfo and encode the digest
+ *                          without any prefix like described in v1.5 (RFC-2313)
+ *                          and observed with RSA+MD5 signed timestamps.  If
+ *                          false, include the prefix like v2.0 (RFC-2437)
+ *                          describes in step in section 9.2.1
+ *                          (EMSA-PKCS1-v1_5)
  */
-static int rtCrPkixSignatureRsa_EmsaPkcs1V15Encode(PRTCRPKIXSIGNATURERSA pThis, RTCRDIGEST hDigest, size_t cbEncodedMsg)
+static int rtCrPkixSignatureRsa_EmsaPkcs1V15Encode(PRTCRPKIXSIGNATURERSA pThis, RTCRDIGEST hDigest, size_t cbEncodedMsg,
+                                                   bool fNoDigestInfo)
 {
     AssertReturn(cbEncodedMsg * 2 <= sizeof(pThis->Scratch), VERR_CR_PKIX_INTERNAL_ERROR);
@@ -257,4 +264,7 @@
     AssertReturn(cbHash == pbDigestInfoStart[cbDigestInfoStart - 1], VERR_CR_PKIX_INTERNAL_ERROR);
 
+    if (fNoDigestInfo)
+        cbDigestInfoStart = 0;
+
     if (cbDigestInfoStart + cbHash + 11 > cbEncodedMsg)
         return VERR_CR_PKIX_HASH_TOO_LONG_FOR_KEY;
@@ -265,5 +275,5 @@
     uint8_t *pbDst = &pThis->Scratch.abSignature[0];
     pbDst[0] = 0x00;
-    pbDst[1] = 0x01;
+    pbDst[1] = 0x01;    /* BT - block type, see RFC-2313. */
     size_t cbFFs = cbEncodedMsg - cbHash - cbDigestInfoStart - 3;
     memset(&pbDst[2], 0xff, cbFFs);
@@ -279,4 +289,5 @@
     return VINF_SUCCESS;
 }
+
 
 
@@ -327,5 +338,5 @@
                              * 8.2.2.3 - Build a hopefully identical signature using hDigest.
                              */
-                            rc = rtCrPkixSignatureRsa_EmsaPkcs1V15Encode(pThis, hDigest, cbDecrypted);
+                            rc = rtCrPkixSignatureRsa_EmsaPkcs1V15Encode(pThis, hDigest, cbDecrypted, false /* fNoDigestInfo */);
                             if (RT_SUCCESS(rc))
                             {
@@ -336,5 +347,19 @@
                                     rc = VINF_SUCCESS;
                                 else
-                                    rc = VERR_CR_PKIX_SIGNATURE_MISMATCH;
+                                {
+                                    /*
+                                     * Try again without digestinfo.  This style signing has been
+                                     * observed in Vista timestamp counter signatures (Thawte).
+                                     */
+                                    rc = rtCrPkixSignatureRsa_EmsaPkcs1V15Encode(pThis, hDigest, cbDecrypted,
+                                                                                 true /* fNoDigestInfo */);
+                                    if (RT_SUCCESS(rc))
+                                    {
+                                        if (memcmp(&pThis->Scratch.abSignature[0], pbDecrypted, cbDecrypted) == 0)
+                                            rc = VINF_SUCCESS;
+                                        else
+                                            rc = VERR_CR_PKIX_SIGNATURE_MISMATCH;
+                                    }
+                                }
                             }
                         }
Index: trunk/src/VBox/Runtime/common/crypto/x509-core.cpp
===================================================================
--- trunk/src/VBox/Runtime/common/crypto/x509-core.cpp	(revision 52536)
+++ trunk/src/VBox/Runtime/common/crypto/x509-core.cpp	(revision 52537)
@@ -1278,5 +1278,5 @@
                     case  6: pThis->T3.fExtKeyUsage |= RTCRX509CERT_EKU_F_IPSEC_TUNNEL; break;
                     case  7: pThis->T3.fExtKeyUsage |= RTCRX509CERT_EKU_F_IPSEC_USER; break;
-                    case  8: pThis->T3.fExtKeyUsage |= RTCRX509CERT_EKU_F_TIME_STAMPING; break;
+                    case  8: pThis->T3.fExtKeyUsage |= RTCRX509CERT_EKU_F_TIMESTAMPING; break;
                     case  9: pThis->T3.fExtKeyUsage |= RTCRX509CERT_EKU_F_OCSP_SIGNING; break;
                     case 10: pThis->T3.fExtKeyUsage |= RTCRX509CERT_EKU_F_DVCS; break;
