VirtualBox

Changeset 52537 in vbox


Ignore:
Timestamp:
Aug 31, 2014 7:28:17 PM (10 years ago)
Author:
vboxsync
Message:

IPRT,SUP: First part of timestamp counter signatures support.

Location:
trunk
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/asn1.h

    r52533 r52537  
    12521252typedef enum RTASN1TYPE
    12531253{
    1254     /** Invalid zero value. */
    1255     RTASN1TYPE_INVALID = 0,
    12561254    /** Not present. */
    1257     RTASN1TYPE_NOT_PRESENT,
     1255    RTASN1TYPE_NOT_PRESENT = 0,
    12581256    /** Generic ASN.1 for unknown tag/class. */
    12591257    RTASN1TYPE_CORE,
  • trunk/include/iprt/crypto/pkcs7.h

    r52503 r52537  
    174174#define RTCR_PKCS9_ID_COUNTER_SIGNATURE_OID "1.2.840.113549.1.9.6"
    175175/** @} */
     176
     177/**
     178 * Get the (next) signing time attribute from the specfied SignerInfo or one of
     179 * the immediate counter signatures.
     180 *
     181 * @returns Pointer to the signing time if found, NULL if not.
     182 * @param   pThis               The SignerInfo to search.
     183 * @param   ppSignerInfo        Pointer to variable keeping track of the
     184 *                              enumeration, optional.
     185 *
     186 *                              If specified the input value is taken to the be
     187 *                              SignerInfo of the previously returned signing
     188 *                              time.  The value pointed to is NULL, the
     189 *                              search/enum restarts.
     190 *
     191 *                              On successful return this is set to the
     192 *                              SignerInfo which we found the signing time in.
     193 */
     194RTDECL(PCRTASN1TIME) RTCrPkcs7SignerInfo_GetSigningTime(PCRTCRPKCS7SIGNERINFO pThis, PCRTCRPKCS7SIGNERINFO *ppSignerInfo);
     195
    176196
    177197
     
    302322 *                              This is NIL_RTCRX509CERTPATHS if the certificate
    303323 *                              is directly trusted.
     324 * @param   fFlags              Mix of the RTCRPKCS7VCC_F_XXX flags.
    304325 * @param   pvUser              The user argument.
    305326 * @param   pErrInfo            Optional error info buffer.
    306327 */
    307 typedef DECLCALLBACK(int) RTCRPKCS7VERIFYCERTCALLBACK(PCRTCRX509CERTIFICATE pCert, RTCRX509CERTPATHS hCertPaths,
    308                                                       void *pvUser, PRTERRINFO pErrInfo);
    309 /** Pointer to a RTCRPKCS7VERIFYCERTCALLBACK callback. */
    310 typedef RTCRPKCS7VERIFYCERTCALLBACK *PRTCRPKCS7VERIFYCERTCALLBACK;
     328typedef DECLCALLBACK(int) FNRTCRPKCS7VERIFYCERTCALLBACK(PCRTCRX509CERTIFICATE pCert, RTCRX509CERTPATHS hCertPaths,
     329                                                        uint32_t fFlags, void *pvUser, PRTERRINFO pErrInfo);
     330/** Pointer to a FNRTCRPKCS7VERIFYCERTCALLBACK callback. */
     331typedef FNRTCRPKCS7VERIFYCERTCALLBACK *PFNRTCRPKCS7VERIFYCERTCALLBACK;
     332
     333/** @name RTCRPKCS7VCC_F_XXX - Flags for FNRTCRPKCS7VERIFYCERTCALLBACK.
     334 * @{ */
     335/** Normal callback for a direct signatory of the signed data. */
     336#define RTCRPKCS7VCC_F_SIGNED_DATA                      RT_BIT_32(0)
     337/** Check that the signatory can be trusted for timestamps. */
     338#define RTCRPKCS7VCC_F_TIMESTAMP                        RT_BIT_32(1)
     339/** @} */
    311340
    312341/**
     
    314343 *  Default implementation that checks for the DigitalSignature KeyUsage bit.}
    315344 */
    316 RTDECL(int) RTCrPkcs7VerifyCertCallbackDefault(PCRTCRX509CERTIFICATE pCert, RTCRX509CERTPATHS hCertPaths,
     345RTDECL(int) RTCrPkcs7VerifyCertCallbackDefault(PCRTCRX509CERTIFICATE pCert, RTCRX509CERTPATHS hCertPaths, uint32_t fFlags,
    317346                                               void *pvUser, PRTERRINFO pErrInfo);
    318347
     
    321350 * Standard code signing.  Use this for Microsoft SPC.}
    322351 */
    323 RTDECL(int) RTCrPkcs7VerifyCertCallbackCodeSigning(PCRTCRX509CERTIFICATE pCert, RTCRX509CERTPATHS hCertPaths,
     352RTDECL(int) RTCrPkcs7VerifyCertCallbackCodeSigning(PCRTCRX509CERTIFICATE pCert, RTCRX509CERTPATHS hCertPaths, uint32_t fFlags,
    324353                                                   void *pvUser, PRTERRINFO pErrInfo);
    325354
     
    337366 * @param   hTrustedCerts       Store containing trusted certificates.
    338367 * @param   pValidationTime     The time we're supposed to validate the
    339  *                              certificates chains at.
     368 *                              certificates chains at.  Ignored for signatures
     369 *                              with valid signing time attributes.
    340370 * @param   pfnVerifyCert       Callback for checking that a certificate used
    341371 *                              for signing the data is suitable.
     
    345375RTDECL(int) RTCrPkcs7VerifySignedData(PCRTCRPKCS7CONTENTINFO pContentInfo, uint32_t fFlags,
    346376                                      RTCRSTORE hAdditionalCerts, RTCRSTORE hTrustedCerts,
    347                                       PCRTTIMESPEC pValidationTime, PRTCRPKCS7VERIFYCERTCALLBACK pfnVerifyCert, void *pvUser,
     377                                      PCRTTIMESPEC pValidationTime, PFNRTCRPKCS7VERIFYCERTCALLBACK pfnVerifyCert, void *pvUser,
    348378                                      PRTERRINFO pErrInfo);
    349379
    350380/** @name RTCRPKCS7VERIFY_SD_F_XXX - Flags for RTCrPkcs7VerifySignedData
    351381 * @{ */
     382/** Always use the signing time attribute if present, requiring it to be
     383 * verified as valid.  The default behavior is to ignore unverifiable
     384 * signing time attributes and use the @a pValidationTime instead. */
     385#define RTCRPKCS7VERIFY_SD_F_ALWAYS_USE_SIGNING_TIME_IF_PRESENT     RT_BIT_32(0)
     386/** Only use signging time attributes from counter signatures. */
     387#define RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE_SIGNING_TIME_ONLY    RT_BIT_32(1)
     388/** Don't validate the counter signature containing the signing time, just use
     389 * it unverified.  This is useful if we don't necessarily have the root
     390 * certificates for the timestamp server handy, but use with great care. */
     391#define RTCRPKCS7VERIFY_SD_F_USE_SIGNING_TIME_UNVERIFIED            RT_BIT_32(2)
     392/** Indicates internally that we're validating a counter signature and should
     393 * use different rules when checking out the authenticated attributes.
     394 * @internal  */
     395#define RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE                      RT_BIT_32(31)
    352396/** @} */
    353397
  • trunk/include/iprt/crypto/x509.h

    r51856 r52537  
    801801#define RTCRX509CERT_EKU_F_IPSEC_TUNNEL                     RT_BIT_64(6)
    802802#define RTCRX509CERT_EKU_F_IPSEC_USER                       RT_BIT_64(7)
    803 #define RTCRX509CERT_EKU_F_TIME_STAMPING                    RT_BIT_64(8)
     803#define RTCRX509CERT_EKU_F_TIMESTAMPING                     RT_BIT_64(8)
    804804#define RTCRX509CERT_EKU_F_OCSP_SIGNING                     RT_BIT_64(9)
    805805#define RTCRX509CERT_EKU_F_DVCS                             RT_BIT_64(10)
     
    835835#define RTCRX509_ID_KP_IPSEC_TUNNEL_OID                     "1.3.6.1.5.5.7.3.6"
    836836#define RTCRX509_ID_KP_IPSEC_USER_OID                       "1.3.6.1.5.5.7.3.7"
    837 #define RTCRX509_ID_KP_TIME_STAMPING_OID                    "1.3.6.1.5.5.7.3.8"
     837#define RTCRX509_ID_KP_TIMESTAMPING_OID                     "1.3.6.1.5.5.7.3.8"
    838838#define RTCRX509_ID_KP_OCSP_SIGNING_OID                     "1.3.6.1.5.5.7.3.9"
    839839#define RTCRX509_ID_KP_DVCS_OID                             "1.3.6.1.5.5.7.3.10"
     
    876876/** @} */
    877877
    878 /** @name Microsoft extended key usage OIDs
     878/** @name Apple extended key usage OIDs
    879879 * @{ */
    880880#define RTCRX509_APPLE_EKU_APPLE_EXTENDED_KEY_USAGE_OID     "1.2.840.113635.100.4"
  • trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyImage-win.cpp

    r52529 r52537  
    874874 */
    875875static DECLCALLBACK(int) supHardNtViCertVerifyCallback(PCRTCRX509CERTIFICATE pCert, RTCRX509CERTPATHS hCertPaths,
    876                                                        void *pvUser, PRTERRINFO pErrInfo)
     876                                                       uint32_t fFlags, void *pvUser, PRTERRINFO pErrInfo)
    877877{
    878878    PSUPHNTVIRDR pNtViRdr = (PSUPHNTVIRDR)pvUser;
     
    894894     * Standard code signing capabilites required.
    895895     */
    896     int rc = RTCrPkcs7VerifyCertCallbackCodeSigning(pCert, hCertPaths, NULL, pErrInfo);
    897     if (RT_SUCCESS(rc))
     896    int rc = RTCrPkcs7VerifyCertCallbackCodeSigning(pCert, hCertPaths, fFlags, NULL, pErrInfo);
     897    if (   RT_SUCCESS(rc)
     898        && (fFlags & RTCRPKCS7VCC_F_SIGNED_DATA))
    898899    {
    899900        /*
     
    992993
    993994    /*
    994      * Verify the signature.
     995     * Verify the signature.  We instruct the verifier to use the signing time
     996     * counter signature present when present, falling back on the timestamp
     997     * planted by the linker when absent.  In ring-0 we don't have all the
     998     * necessary timestamp server root certificate info, so we have to allow
     999     * using counter signatures unverified there.
    9951000     */
    9961001    RTTIMESPEC ValidationTime;
    9971002    RTTimeSpecSetSeconds(&ValidationTime, pNtViRdr->uTimestamp);
    9981003
    999     return RTCrPkcs7VerifySignedData(pContentInfo, 0, g_hSpcAndNtKernelSuppStore, g_hSpcAndNtKernelRootStore, &ValidationTime,
    1000                                      supHardNtViCertVerifyCallback, pNtViRdr, pErrInfo);
     1004    uint32_t fFlags = RTCRPKCS7VERIFY_SD_F_ALWAYS_USE_SIGNING_TIME_IF_PRESENT
     1005                    | RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE_SIGNING_TIME_ONLY;
     1006#ifdef IN_RING0
     1007    fFlags |= RTCRPKCS7VERIFY_SD_F_USE_SIGNING_TIME_UNVERIFIED;
     1008#endif
     1009    return RTCrPkcs7VerifySignedData(pContentInfo, fFlags, g_hSpcAndNtKernelSuppStore, g_hSpcAndNtKernelRootStore,
     1010                                     &ValidationTime, supHardNtViCertVerifyCallback, pNtViRdr, pErrInfo);
    10011011}
    10021012
  • trunk/src/VBox/Runtime/common/crypto/pkcs7-core.cpp

    r51770 r52537  
    3939
    4040/*
     41 * PCKS #7 SignerInfo
     42 */
     43
     44RTDECL(PCRTASN1TIME) RTCrPkcs7SignerInfo_GetSigningTime(PCRTCRPKCS7SIGNERINFO pThis, PCRTCRPKCS7SIGNERINFO *ppSignerInfo)
     45{
     46    /*
     47     * Check the immediate level, unless we're continuing a previous search.
     48     * Note! We ASSUME a single signing time attribute, which simplifies the interface.
     49     */
     50    uint32_t                cAttrsLeft;
     51    PCRTCRPKCS7ATTRIBUTE    pAttr;
     52    if (!ppSignerInfo || *ppSignerInfo == NULL)
     53    {
     54        cAttrsLeft = pThis->AuthenticatedAttributes.cItems;
     55        pAttr      = pThis->AuthenticatedAttributes.paItems;
     56        while (cAttrsLeft-- > 0)
     57        {
     58            if (   pAttr->enmType == RTCRPKCS7ATTRIBUTETYPE_SIGNING_TIME
     59                && pAttr->uValues.pSigningTime->cItems > 0)
     60            {
     61                if (ppSignerInfo)
     62                    *ppSignerInfo = pThis;
     63                return &pAttr->uValues.pSigningTime->paItems[0];
     64            }
     65            pAttr++;
     66        }
     67    }
     68    else if (*ppSignerInfo == pThis)
     69        *ppSignerInfo = NULL;
     70
     71    /*
     72     * Check counter signatures.
     73     */
     74    cAttrsLeft = pThis->UnauthenticatedAttributes.cItems;
     75    pAttr      = pThis->UnauthenticatedAttributes.paItems;
     76    while (cAttrsLeft-- > 0)
     77    {
     78        if (pAttr->enmType == RTCRPKCS7ATTRIBUTETYPE_COUNTER_SIGNATURES)
     79        {
     80            uint32_t              cSignatures = pAttr->uValues.pCounterSignatures->cItems;
     81            PCRTCRPKCS7SIGNERINFO pSignature  = pAttr->uValues.pCounterSignatures->paItems;
     82
     83            /* Skip past the previous counter signature. */
     84            if (ppSignerInfo && *ppSignerInfo != NULL)
     85                while (cSignatures > 0)
     86                {
     87                    cSignatures--;
     88                    if (pSignature == *ppSignerInfo)
     89                    {
     90                        *ppSignerInfo = NULL;
     91                        pSignature++;
     92                        break;
     93                    }
     94                    pSignature++;
     95                }
     96
     97            /* Search the counter signatures (if any remaining). */
     98            while (cSignatures-- > 0)
     99            {
     100                uint32_t                cCounterAttrsLeft = pSignature->AuthenticatedAttributes.cItems;
     101                PCRTCRPKCS7ATTRIBUTE    pCounterAttr      = pSignature->AuthenticatedAttributes.paItems;
     102                while (cCounterAttrsLeft-- > 0)
     103                {
     104                    if (   pCounterAttr->enmType == RTCRPKCS7ATTRIBUTETYPE_SIGNING_TIME
     105                        && pCounterAttr->uValues.pSigningTime->cItems > 0)
     106                    {
     107                        if (ppSignerInfo)
     108                            *ppSignerInfo = pSignature;
     109                        return &pCounterAttr->uValues.pSigningTime->paItems[0];
     110                    }
     111                    pCounterAttr++;
     112                }
     113                pSignature++;
     114            }
     115        }
     116        pAttr++;
     117    }
     118
     119    /*
     120     * No signing timestamp found.
     121     */
     122    if (ppSignerInfo)
     123        *ppSignerInfo = NULL;
     124
     125    return NULL;
     126}
     127
     128
     129/*
    41130 * PCKS #7 ContentInfo.
    42131 */
  • trunk/src/VBox/Runtime/common/crypto/pkcs7-verify.cpp

    r51776 r52537  
    117117
    118118
    119 /**
    120  * @callback_method_impl{RTCRPKCS7VERIFYCERTCALLBACK,
    121  *  Default implementation that checks for the DigitalSignature KeyUsage bit.}
    122  */
    123 RTDECL(int) RTCrPkcs7VerifyCertCallbackDefault(PCRTCRX509CERTIFICATE pCert, RTCRX509CERTPATHS hCertPaths,
    124                                                void *pvUser, PRTERRINFO pErrInfo)
    125 {
    126     /*
    127      * Check for the digital signature key usage.
    128      */
     119
     120static int rtCrPkcs7VerifyCertUsageTimstamping(PCRTCRX509CERTIFICATE pCert, PRTERRINFO pErrInfo)
     121{
     122    if (!(pCert->TbsCertificate.T3.fFlags & RTCRX509TBSCERTIFICATE_F_PRESENT_EXT_KEY_USAGE))
     123        return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_KEY_USAGE_MISMATCH, "No extended key usage certificate attribute.");
     124    if (!(pCert->TbsCertificate.T3.fExtKeyUsage & (RTCRX509CERT_EKU_F_TIMESTAMPING | RTCRX509CERT_EKU_F_MS_TIMESTAMP_SIGNING)))
     125        return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_KEY_USAGE_MISMATCH, "fExtKeyUsage=%#x, missing %#x (time stamping)",
     126                             pCert->TbsCertificate.T3.fExtKeyUsage,
     127                             RTCRX509CERT_EKU_F_TIMESTAMPING | RTCRX509CERT_EKU_F_MS_TIMESTAMP_SIGNING);
     128    return VINF_SUCCESS;
     129}
     130
     131
     132static int rtCrPkcs7VerifyCertUsageDigitalSignature(PCRTCRX509CERTIFICATE pCert, PRTERRINFO pErrInfo)
     133{
    129134    if (   (pCert->TbsCertificate.T3.fFlags & RTCRX509TBSCERTIFICATE_F_PRESENT_KEY_USAGE)
    130135        && !(pCert->TbsCertificate.T3.fKeyUsage & RTCRX509CERT_KEY_USAGE_F_DIGITAL_SIGNATURE))
     
    137142/**
    138143 * @callback_method_impl{RTCRPKCS7VERIFYCERTCALLBACK,
     144 *  Default implementation that checks for the DigitalSignature KeyUsage bit.}
     145 */
     146RTDECL(int) RTCrPkcs7VerifyCertCallbackDefault(PCRTCRX509CERTIFICATE pCert, RTCRX509CERTPATHS hCertPaths, uint32_t fFlags,
     147                                               void *pvUser, PRTERRINFO pErrInfo)
     148{
     149    int rc = VINF_SUCCESS;
     150
     151    if (fFlags & RTCRPKCS7VCC_F_SIGNED_DATA)
     152        rc = rtCrPkcs7VerifyCertUsageDigitalSignature(pCert, pErrInfo);
     153
     154    if (   (fFlags & RTCRPKCS7VCC_F_TIMESTAMP)
     155        && RT_SUCCESS(rc))
     156        rc = rtCrPkcs7VerifyCertUsageTimstamping(pCert, pErrInfo);
     157
     158    return rc;
     159}
     160
     161
     162/**
     163 * @callback_method_impl{RTCRPKCS7VERIFYCERTCALLBACK,
    139164 * Standard code signing.  Use this for Microsoft SPC.}
    140165 */
    141 RTDECL(int) RTCrPkcs7VerifyCertCallbackCodeSigning(PCRTCRX509CERTIFICATE pCert, RTCRX509CERTPATHS hCertPaths,
     166RTDECL(int) RTCrPkcs7VerifyCertCallbackCodeSigning(PCRTCRX509CERTIFICATE pCert, RTCRX509CERTPATHS hCertPaths, uint32_t fFlags,
    142167                                                   void *pvUser, PRTERRINFO pErrInfo)
    143168{
    144     /*
    145      * Check for the digital signature key usage.  Not required to be present.
    146      */
    147     if (pCert->TbsCertificate.T3.fFlags & RTCRX509TBSCERTIFICATE_F_PRESENT_KEY_USAGE)
    148     {
    149         if (!(pCert->TbsCertificate.T3.fKeyUsage & RTCRX509CERT_KEY_USAGE_F_DIGITAL_SIGNATURE))
    150             return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_KEY_USAGE_MISMATCH, "fKeyUsage=%#x, missing %#x",
    151                                  pCert->TbsCertificate.T3.fKeyUsage, RTCRX509CERT_KEY_USAGE_F_DIGITAL_SIGNATURE);
    152     }
    153 
    154     /*
    155      * Check the extended key usage bits if present.
    156      */
    157     if (!(pCert->TbsCertificate.T3.fFlags & RTCRX509TBSCERTIFICATE_F_PRESENT_EXT_KEY_USAGE))
    158         return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_KEY_USAGE_MISMATCH, "No extended key usage certificate attribute.");
    159     if (!(pCert->TbsCertificate.T3.fExtKeyUsage & RTCRX509CERT_EKU_F_CODE_SIGNING))
    160         return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_KEY_USAGE_MISMATCH, "fExtKeyUsage=%#x, missing %#x",
    161                              pCert->TbsCertificate.T3.fExtKeyUsage, RTCRX509CERT_EKU_F_CODE_SIGNING);
    162     return VINF_SUCCESS;
     169    int rc = VINF_SUCCESS;
     170    if (fFlags & RTCRPKCS7VCC_F_SIGNED_DATA)
     171    {
     172        /*
     173         * If KeyUsage is present it must include digital signature.
     174         */
     175        rc = rtCrPkcs7VerifyCertUsageDigitalSignature(pCert, pErrInfo);
     176        if (RT_SUCCESS(rc))
     177        {
     178            /*
     179             * The extended usage 'code signing' must be present.
     180             */
     181            if (!(pCert->TbsCertificate.T3.fFlags & RTCRX509TBSCERTIFICATE_F_PRESENT_EXT_KEY_USAGE))
     182                return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_KEY_USAGE_MISMATCH, "No extended key usage certificate attribute.");
     183            if (!(pCert->TbsCertificate.T3.fExtKeyUsage & RTCRX509CERT_EKU_F_CODE_SIGNING))
     184                return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_KEY_USAGE_MISMATCH, "fExtKeyUsage=%#x, missing %#x",
     185                                     pCert->TbsCertificate.T3.fExtKeyUsage, RTCRX509CERT_EKU_F_CODE_SIGNING);
     186        }
     187    }
     188
     189    /*
     190     * Timestamping too?
     191     */
     192    if (   (fFlags & RTCRPKCS7VCC_F_TIMESTAMP)
     193        && RT_SUCCESS(rc))
     194        rc = rtCrPkcs7VerifyCertUsageTimstamping(pCert, pErrInfo);
     195
     196    return rc;
    163197}
    164198
     
    206240            AssertReturn(pAttrib->uValues.pObjIds->cItems == 1, VERR_CR_PKCS7_INTERNAL_ERROR);
    207241
    208             if (RTAsn1ObjId_Compare(&pAttrib->uValues.pObjIds->paItems[0], &pSignedData->ContentInfo.ContentType) != 0)
    209                 return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_CONTENT_TYPE_ATTRIB_MISMATCH,
    210                                      "Expected content-type %s, found %s",
    211                                      &pAttrib->uValues.pObjIds->paItems[0], pSignedData->ContentInfo.ContentType.szObjId);
     242            if (   !(fFlags & RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE) /* See note about microsoft below. */
     243                && RTAsn1ObjId_Compare(&pAttrib->uValues.pObjIds->paItems[0], &pSignedData->ContentInfo.ContentType) != 0)
     244                   return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_CONTENT_TYPE_ATTRIB_MISMATCH,
     245                                        "Expected content-type %s, found %s",
     246                                        &pAttrib->uValues.pObjIds->paItems[0], pSignedData->ContentInfo.ContentType.szObjId);
    212247            cContentTypes++;
    213248        }
     
    239274    }
    240275
    241     AssertReturn(cContentTypes == 1, VERR_CR_PKCS7_INTERNAL_ERROR);
    242     AssertReturn(cMessageDigests == 1, VERR_CR_PKCS7_INTERNAL_ERROR);
     276    /*
     277     * Full error reporting here as we don't currently extensively santiy check
     278     * counter signatures.
     279     * Note! Microsoft includes content info in their timestamp counter signatures,
     280     *       at least for vista, despite the RFC-3852 stating counter signatures
     281     *       "MUST NOT contain a content-type".
     282     */
     283    if (RT_UNLIKELY(   cContentTypes != 1
     284                    && !(fFlags & RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE)))
     285        return RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_MISSING_CONTENT_TYPE_ATTRIB,
     286                            "Missing authenticated content-type attribute.");
     287    if (RT_UNLIKELY(cMessageDigests != 1))
     288        return RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_MISSING_MESSAGE_DIGEST_ATTRIB,
     289                            "Missing authenticated message-digest attribute.");
    243290
    244291    /*
     
    272319
    273320/**
     321 * Find the handle to the digest given by the specified SignerInfo.
     322 *
     323 * @returns IPRT status code
     324 * @param   phDigest            Where to return a referenced digest handle on
     325 *                              success.
     326 * @param   pSignedData         The signed data structure.
     327 * @param   pSignerInfo         The signer info.
     328 * @param   pahDigests          Array of content digests that runs parallel to
     329 *                              pSignedData->DigestAlgorithms.
     330 * @param   pErrInfo            Where to store additional error details,
     331 *                              optional.
     332 */
     333static int rtCrPkcs7VerifyFindDigest(PRTCRDIGEST phDigest, PCRTCRPKCS7SIGNEDDATA pSignedData,
     334                                     PCRTCRPKCS7SIGNERINFO pSignerInfo, PRTCRDIGEST pahDigests, PRTERRINFO pErrInfo)
     335{
     336    uint32_t iDigest = pSignedData->DigestAlgorithms.cItems;
     337    while (iDigest-- > 0)
     338        if (RTCrX509AlgorithmIdentifier_Compare(&pSignedData->DigestAlgorithms.paItems[iDigest],
     339                                                &pSignerInfo->DigestAlgorithm) == 0)
     340        {
     341            RTCRDIGEST hDigest = pahDigests[iDigest];
     342            uint32_t cRefs = RTCrDigestRetain(hDigest);
     343            AssertReturn(cRefs != UINT32_MAX, VERR_CR_PKCS7_INTERNAL_ERROR);
     344            *phDigest = hDigest;
     345            return VINF_SUCCESS;
     346        }
     347
     348    return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_DIGEST_ALGO_NOT_FOUND_IN_LIST,
     349                         "SignerInfo.DigestAlgorithm %s not found.",
     350                         pSignerInfo->DigestAlgorithm.Algorithm.szObjId);
     351}
     352
     353
     354/**
    274355 * Verifies one signature on a PKCS \#7 SignedData.
    275356 *
     
    277358 * @param   pSignerInfo         The signature.
    278359 * @param   pSignedData         The SignedData.
    279  * @param   pahDigests          Array of content digests that runs parallel to
    280  *                              pSignedData->DigestAlgorithms.
     360 * @param   hDigests            The digest corresponding to
     361 *                              pSignerInfo->DigestAlgorithm.
    281362 * @param   fFlags              Verficiation flags.
    282363 * @param   hAdditionalCerts    Store containing optional certificates,
     
    286367 *                              certificates chains at.
    287368 * @param   pfnVerifyCert       Signing certificate verification callback.
     369 * @param   fVccFlags           Signing certificate verification callback flags.
    288370 * @param   pvUser              Callback parameter.
    289371 * @param   pErrInfo            Where to store additional error details,
     
    291373 */
    292374static int rtCrPkcs7VerifySignerInfo(PCRTCRPKCS7SIGNERINFO pSignerInfo, PCRTCRPKCS7SIGNEDDATA pSignedData,
    293                                      PRTCRDIGEST pahDigests, uint32_t fFlags, RTCRSTORE hAdditionalCerts, RTCRSTORE hTrustedCerts,
    294                                      PCRTTIMESPEC pValidationTime, RTCRPKCS7VERIFYCERTCALLBACK pfnVerifyCert, void *pvUser,
    295                                      PRTERRINFO pErrInfo)
    296 {
    297     /*
    298      * Check for counter signatures with timestamp.  Verify the signature for
    299      * the current time if not present.
    300      */
    301     /** @todo timestamp counter signatures. */
    302 
     375                                     RTCRDIGEST hDigest, uint32_t fFlags, RTCRSTORE hAdditionalCerts, RTCRSTORE hTrustedCerts,
     376                                     PCRTTIMESPEC pValidationTime, PFNRTCRPKCS7VERIFYCERTCALLBACK pfnVerifyCert,
     377                                     uint32_t fVccFlags, void *pvUser, PRTERRINFO pErrInfo)
     378{
    303379    /*
    304380     * Locate the certificate used for signing.
     
    364440                 */
    365441                if (RT_SUCCESS(rc))
    366                     rc = pfnVerifyCert(pSignerCert, hCertPaths, pvUser, pErrInfo);
     442                    rc = pfnVerifyCert(pSignerCert, hCertPaths, fVccFlags, pvUser, pErrInfo);
    367443            }
    368444            else
     
    375451     */
    376452    else
    377         rc = pfnVerifyCert(pSignerCert, NIL_RTCRX509CERTPATHS, pvUser, pErrInfo);
    378 
    379     /*
    380      * Find the digest that is signed and reference it so we can replace it
    381      * below if necessary.
    382      */
    383     RTCRDIGEST hDigest = NIL_RTCRDIGEST;
    384     uint32_t iDigest = pSignedData->DigestAlgorithms.cItems;
    385     while (iDigest-- > 0)
    386         if (RTCrX509AlgorithmIdentifier_Compare(&pSignedData->DigestAlgorithms.paItems[iDigest],
    387                                                 &pSignerInfo->DigestAlgorithm) == 0)
    388         {
    389             hDigest = pahDigests[iDigest];
    390             uint32_t cRefs = RTCrDigestRetain(hDigest);
    391             AssertStmt(cRefs != UINT32_MAX, cRefs = NIL_RTCRDIGEST; rc = VERR_CR_PKCS7_INTERNAL_ERROR);
    392             break;
    393         }
    394     if (hDigest == NIL_RTCRDIGEST && RT_SUCCESS(rc))
    395         rc = RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_DIGEST_ALGO_NOT_FOUND_IN_LIST,
    396                            "SignerInfo.DigestAlgorithm %s not found.",
    397                            pSignerInfo->DigestAlgorithm.Algorithm.szObjId);
    398 
    399     /*
    400      * If there are authenticated attributes, we've got more work before we
    401      * can verify the signature.
     453        rc = pfnVerifyCert(pSignerCert, NIL_RTCRX509CERTPATHS, fVccFlags, pvUser, pErrInfo);
     454
     455    /*
     456     * Reference the digest so we can safely replace with one on the
     457     * authenticated attributes below.
    402458     */
    403459    if (   RT_SUCCESS(rc)
    404         && RTCrPkcs7Attributes_IsPresent(&pSignerInfo->AuthenticatedAttributes))
    405         rc = rtCrPkcs7VerifySignerInfoAuthAttribs(pSignerInfo, pSignedData, &hDigest, fFlags, pErrInfo);
    406 
    407     /*
    408      * Verify the signature.
    409      */
    410     if (RT_SUCCESS(rc))
    411     {
    412         RTCRPKIXSIGNATURE hSignature;
    413         rc = RTCrPkixSignatureCreateByObjId(&hSignature,
    414                                             &pSignerCert->TbsCertificate.SubjectPublicKeyInfo.Algorithm.Algorithm,
    415                                             false /*fSigning*/,
    416                                             &pSignerCert->TbsCertificate.SubjectPublicKeyInfo.SubjectPublicKey,
    417                                             &pSignerInfo->DigestEncryptionAlgorithm.Parameters);
     460        && RTCrDigestRetain(hDigest) != UINT32_MAX)
     461    {
     462        /*
     463         * If there are authenticated attributes, we've got more work before we
     464         * can verify the signature.
     465         */
     466        if (   RT_SUCCESS(rc)
     467            && RTCrPkcs7Attributes_IsPresent(&pSignerInfo->AuthenticatedAttributes))
     468            rc = rtCrPkcs7VerifySignerInfoAuthAttribs(pSignerInfo, pSignedData, &hDigest, fFlags, pErrInfo);
     469
     470        /*
     471         * Verify the signature.
     472         */
    418473        if (RT_SUCCESS(rc))
    419474        {
    420             /** @todo Check that DigestEncryptionAlgorithm is compatible with hSignature
    421              *        (this is not vital). */
    422             rc = RTCrPkixSignatureVerifyOctetString(hSignature, hDigest, &pSignerInfo->EncryptedDigest);
    423             if (RT_FAILURE(rc))
    424                 rc = RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_SIGNATURE_VERIFICATION_FAILED,
    425                                    "Signature verficiation failed: %Rrc", rc);
    426             RTCrPkixSignatureRelease(hSignature);
    427         }
    428         else
    429             rc = RTErrInfoSetF(pErrInfo, rc, "Failure to instantiate public key algorithm [IPRT]: %s (%s)",
    430                                pSignerCert->TbsCertificate.SubjectPublicKeyInfo.Algorithm.Algorithm.szObjId,
    431                                pSignerInfo->DigestEncryptionAlgorithm.Algorithm.szObjId);
    432     }
    433 
    434     RTCrDigestRelease(hDigest);
     475            RTCRPKIXSIGNATURE hSignature;
     476            rc = RTCrPkixSignatureCreateByObjId(&hSignature,
     477                                                &pSignerCert->TbsCertificate.SubjectPublicKeyInfo.Algorithm.Algorithm,
     478                                                false /*fSigning*/,
     479                                                &pSignerCert->TbsCertificate.SubjectPublicKeyInfo.SubjectPublicKey,
     480                                                &pSignerInfo->DigestEncryptionAlgorithm.Parameters);
     481            if (RT_SUCCESS(rc))
     482            {
     483                /** @todo Check that DigestEncryptionAlgorithm is compatible with hSignature
     484                 *        (this is not vital). */
     485                rc = RTCrPkixSignatureVerifyOctetString(hSignature, hDigest, &pSignerInfo->EncryptedDigest);
     486                if (RT_FAILURE(rc))
     487                    rc = RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_SIGNATURE_VERIFICATION_FAILED,
     488                                       "Signature verficiation failed: %Rrc", rc);
     489                RTCrPkixSignatureRelease(hSignature);
     490            }
     491            else
     492                rc = RTErrInfoSetF(pErrInfo, rc, "Failure to instantiate public key algorithm [IPRT]: %s (%s)",
     493                                   pSignerCert->TbsCertificate.SubjectPublicKeyInfo.Algorithm.Algorithm.szObjId,
     494                                   pSignerInfo->DigestEncryptionAlgorithm.Algorithm.szObjId);
     495        }
     496
     497        RTCrDigestRelease(hDigest);
     498    }
     499    else if (RT_SUCCESS(rc))
     500        rc = VERR_CR_PKCS7_INTERNAL_ERROR;
    435501    RTCrCertCtxRelease(pSignerCertCtx);
    436502    return rc;
     
    438504
    439505
     506/**
     507 * Verifies a counter signature.
     508 *
     509 * @returns IPRT status code.
     510 * @param   pCounterSignerInfo  The counter signature.
     511 * @param   pPrimarySignerInfo  The primary signature (can be a counter
     512 *                              signature too if nested).
     513 * @param   pSignedData         The SignedData.
     514 * @param   fFlags              Verficiation flags.
     515 * @param   hAdditionalCerts    Store containing optional certificates,
     516 *                              optional.
     517 * @param   hTrustedCerts       Store containing trusted certificates, required.
     518 * @param   pValidationTime     The time we're supposed to validate the
     519 *                              certificates chains at.
     520 * @param   pfnVerifyCert       Signing certificate verification callback.
     521 * @param   fVccFlags           Signing certificate verification callback flags.
     522 * @param   pvUser              Callback parameter.
     523 * @param   pErrInfo            Where to store additional error details,
     524 *                              optional.
     525 */
     526static int rtCrPkcs7VerifyCounterSignerInfo(PCRTCRPKCS7SIGNERINFO pCounterSignerInfo, PCRTCRPKCS7SIGNERINFO pPrimarySignerInfo,
     527                                            PCRTCRPKCS7SIGNEDDATA pSignedData, uint32_t fFlags,
     528                                            RTCRSTORE hAdditionalCerts, RTCRSTORE hTrustedCerts, PCRTTIMESPEC pValidationTime,
     529                                            PFNRTCRPKCS7VERIFYCERTCALLBACK pfnVerifyCert, uint32_t fVccFlags,
     530                                            void *pvUser, PRTERRINFO pErrInfo)
     531{
     532    /*
     533     * Calculate the digest we need to verify.
     534     */
     535    RTCRDIGEST hDigest;
     536    int rc = RTCrDigestCreateByObjId(&hDigest, &pCounterSignerInfo->DigestAlgorithm.Algorithm);
     537    if (RT_SUCCESS(rc))
     538    {
     539        rc = RTCrDigestUpdate(hDigest,
     540                              pPrimarySignerInfo->EncryptedDigest.Asn1Core.uData.pv,
     541                              pPrimarySignerInfo->EncryptedDigest.Asn1Core.cb);
     542        if (RT_SUCCESS(rc))
     543            rc = RTCrDigestFinal(hDigest, NULL, 0);
     544        if (RT_SUCCESS(rc))
     545        {
     546            /*
     547             * Pass it on to the common SignerInfo verifier function.
     548             */
     549            rc = rtCrPkcs7VerifySignerInfo(pCounterSignerInfo, pSignedData, hDigest,
     550                                           fFlags | RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE,
     551                                           hAdditionalCerts, hTrustedCerts, pValidationTime,
     552                                           pfnVerifyCert, fVccFlags, pvUser, pErrInfo);
     553
     554        }
     555        else
     556            rc = RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_DIGEST_CALC_ERROR,
     557                               "Hashing for counter signature failed unexpectedly: %Rrc", rc);
     558        RTCrDigestRelease(hDigest);
     559    }
     560    else
     561        rc = RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_DIGEST_CREATE_ERROR, "Error creating digest for '%s': %Rrc",
     562                           pCounterSignerInfo->DigestAlgorithm.Algorithm.szObjId, rc);
     563
     564    return rc;
     565}
     566
     567
    440568RTDECL(int) RTCrPkcs7VerifySignedData(PCRTCRPKCS7CONTENTINFO pContentInfo, uint32_t fFlags,
    441569                                      RTCRSTORE hAdditionalCerts, RTCRSTORE hTrustedCerts,
    442                                       PCRTTIMESPEC pValidationTime, PRTCRPKCS7VERIFYCERTCALLBACK pfnVerifyCert, void *pvUser,
     570                                      PCRTTIMESPEC pValidationTime, PFNRTCRPKCS7VERIFYCERTCALLBACK pfnVerifyCert, void *pvUser,
    443571                                      PRTERRINFO pErrInfo)
    444572{
     
    458586        return rc;
    459587
     588    AssertReturn(!(fFlags & RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE), VERR_INVALID_FLAGS);
     589
    460590    /*
    461591     * Hash the content info.
     
    513643            for (i = 0; i < pSignedData->SignerInfos.cItems; i++)
    514644            {
    515                 rc = rtCrPkcs7VerifySignerInfo(&pSignedData->SignerInfos.paItems[i], pSignedData, ahDigests,
    516                                                fFlags, hAdditionalCerts, hTrustedCerts, pValidationTime,
    517                                                pfnVerifyCert, pvUser, pErrInfo);
     645                PCRTCRPKCS7SIGNERINFO   pSignerInfo       = &pSignedData->SignerInfos.paItems[i];
     646                RTCRDIGEST              hThisDigest;
     647                rc = rtCrPkcs7VerifyFindDigest(&hThisDigest, pSignedData, pSignerInfo, ahDigests, pErrInfo);
     648                if (RT_FAILURE(rc))
     649                    break;
     650
     651                /*
     652                 * See if we can find a trusted signing time.
     653                 */
     654                bool                    fDone              = false;
     655                PCRTCRPKCS7SIGNERINFO   pSigningTimeSigner = NULL;
     656                PCRTASN1TIME            pSignedTime;
     657                while (   !fDone
     658                       && (pSignedTime = RTCrPkcs7SignerInfo_GetSigningTime(pSignerInfo, &pSigningTimeSigner)) != NULL)
     659                {
     660                    RTTIMESPEC ThisValidationTime;
     661                    if (RT_LIKELY(RTTimeImplode(&ThisValidationTime, &pSignedTime->Time)))
     662                    {
     663                        if (pSigningTimeSigner == pSignerInfo)
     664                        {
     665                            if (fFlags & RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE_SIGNING_TIME_ONLY)
     666                                continue;
     667                            rc = rtCrPkcs7VerifySignerInfo(pSignerInfo, pSignedData, hThisDigest, fFlags,
     668                                                           hAdditionalCerts, hTrustedCerts, &ThisValidationTime,
     669                                                           pfnVerifyCert, RTCRPKCS7VCC_F_SIGNED_DATA | RTCRPKCS7VCC_F_TIMESTAMP,
     670                                                           pvUser, pErrInfo);
     671                        }
     672                        else
     673                        {
     674                            rc = VINF_SUCCESS;
     675                            if (!(fFlags & RTCRPKCS7VERIFY_SD_F_USE_SIGNING_TIME_UNVERIFIED))
     676                                rc = rtCrPkcs7VerifyCounterSignerInfo(pSigningTimeSigner, pSignerInfo, pSignedData, fFlags,
     677                                                                      hAdditionalCerts, hTrustedCerts, &ThisValidationTime,
     678                                                                      pfnVerifyCert, RTCRPKCS7VCC_F_TIMESTAMP, pvUser, pErrInfo);
     679                            if (RT_SUCCESS(rc))
     680                                rc = rtCrPkcs7VerifySignerInfo(pSignerInfo, pSignedData, hThisDigest, fFlags, hAdditionalCerts,
     681                                                               hTrustedCerts, &ThisValidationTime,
     682                                                               pfnVerifyCert, RTCRPKCS7VCC_F_SIGNED_DATA, pvUser, pErrInfo);
     683                        }
     684                        fDone = RT_SUCCESS(rc)
     685                             || (fFlags & RTCRPKCS7VERIFY_SD_F_ALWAYS_USE_SIGNING_TIME_IF_PRESENT);
     686                    }
     687                    else
     688                    {
     689                        rc = RTErrInfoSet(pErrInfo, VERR_INTERNAL_ERROR_3, "RTTimeImplode failed");
     690                        fDone = true;
     691                    }
     692                }
     693
     694                /*
     695                 * No valid signing time found, use the one specified instead.
     696                 */
     697                if (!fDone)
     698                    rc = rtCrPkcs7VerifySignerInfo(pSignerInfo, pSignedData, hThisDigest, fFlags, hAdditionalCerts, hTrustedCerts,
     699                                                   pValidationTime, pfnVerifyCert, RTCRPKCS7VCC_F_SIGNED_DATA, pvUser, pErrInfo);
     700                RTCrDigestRelease(hThisDigest);
    518701                if (RT_FAILURE(rc))
    519702                    break;
  • trunk/src/VBox/Runtime/common/crypto/pkix-signature-rsa.cpp

    r51770 r52537  
    227227 * @param   hDigest         The digest which hash to turn into a signature.
    228228 * @param   cbEncodedMsg    The desired encoded message length.
     229 * @param   fNoDigestInfo   If true, skip the DigestInfo and encode the digest
     230 *                          without any prefix like described in v1.5 (RFC-2313)
     231 *                          and observed with RSA+MD5 signed timestamps.  If
     232 *                          false, include the prefix like v2.0 (RFC-2437)
     233 *                          describes in step in section 9.2.1
     234 *                          (EMSA-PKCS1-v1_5)
    229235 */
    230 static int rtCrPkixSignatureRsa_EmsaPkcs1V15Encode(PRTCRPKIXSIGNATURERSA pThis, RTCRDIGEST hDigest, size_t cbEncodedMsg)
     236static int rtCrPkixSignatureRsa_EmsaPkcs1V15Encode(PRTCRPKIXSIGNATURERSA pThis, RTCRDIGEST hDigest, size_t cbEncodedMsg,
     237                                                   bool fNoDigestInfo)
    231238{
    232239    AssertReturn(cbEncodedMsg * 2 <= sizeof(pThis->Scratch), VERR_CR_PKIX_INTERNAL_ERROR);
     
    257264    AssertReturn(cbHash == pbDigestInfoStart[cbDigestInfoStart - 1], VERR_CR_PKIX_INTERNAL_ERROR);
    258265
     266    if (fNoDigestInfo)
     267        cbDigestInfoStart = 0;
     268
    259269    if (cbDigestInfoStart + cbHash + 11 > cbEncodedMsg)
    260270        return VERR_CR_PKIX_HASH_TOO_LONG_FOR_KEY;
     
    265275    uint8_t *pbDst = &pThis->Scratch.abSignature[0];
    266276    pbDst[0] = 0x00;
    267     pbDst[1] = 0x01;
     277    pbDst[1] = 0x01;    /* BT - block type, see RFC-2313. */
    268278    size_t cbFFs = cbEncodedMsg - cbHash - cbDigestInfoStart - 3;
    269279    memset(&pbDst[2], 0xff, cbFFs);
     
    279289    return VINF_SUCCESS;
    280290}
     291
    281292
    282293
     
    327338                             * 8.2.2.3 - Build a hopefully identical signature using hDigest.
    328339                             */
    329                             rc = rtCrPkixSignatureRsa_EmsaPkcs1V15Encode(pThis, hDigest, cbDecrypted);
     340                            rc = rtCrPkixSignatureRsa_EmsaPkcs1V15Encode(pThis, hDigest, cbDecrypted, false /* fNoDigestInfo */);
    330341                            if (RT_SUCCESS(rc))
    331342                            {
     
    336347                                    rc = VINF_SUCCESS;
    337348                                else
    338                                     rc = VERR_CR_PKIX_SIGNATURE_MISMATCH;
     349                                {
     350                                    /*
     351                                     * Try again without digestinfo.  This style signing has been
     352                                     * observed in Vista timestamp counter signatures (Thawte).
     353                                     */
     354                                    rc = rtCrPkixSignatureRsa_EmsaPkcs1V15Encode(pThis, hDigest, cbDecrypted,
     355                                                                                 true /* fNoDigestInfo */);
     356                                    if (RT_SUCCESS(rc))
     357                                    {
     358                                        if (memcmp(&pThis->Scratch.abSignature[0], pbDecrypted, cbDecrypted) == 0)
     359                                            rc = VINF_SUCCESS;
     360                                        else
     361                                            rc = VERR_CR_PKIX_SIGNATURE_MISMATCH;
     362                                    }
     363                                }
    339364                            }
    340365                        }
  • trunk/src/VBox/Runtime/common/crypto/x509-core.cpp

    r52206 r52537  
    12781278                    case  6: pThis->T3.fExtKeyUsage |= RTCRX509CERT_EKU_F_IPSEC_TUNNEL; break;
    12791279                    case  7: pThis->T3.fExtKeyUsage |= RTCRX509CERT_EKU_F_IPSEC_USER; break;
    1280                     case  8: pThis->T3.fExtKeyUsage |= RTCRX509CERT_EKU_F_TIME_STAMPING; break;
     1280                    case  8: pThis->T3.fExtKeyUsage |= RTCRX509CERT_EKU_F_TIMESTAMPING; break;
    12811281                    case  9: pThis->T3.fExtKeyUsage |= RTCRX509CERT_EKU_F_OCSP_SIGNING; break;
    12821282                    case 10: pThis->T3.fExtKeyUsage |= RTCRX509CERT_EKU_F_DVCS; break;
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette