Esempio n. 1
0
RTCrSpcIndirectDataContent_GetPeImageObjAttrib(PCRTCRSPCINDIRECTDATACONTENT pThis,
                                               RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE enmType)
{
    if (pThis->Data.enmType == RTCRSPCAAOVTYPE_PE_IMAGE_DATA)
    {
        Assert(RTAsn1ObjId_CompareWithString(&pThis->Data.Type, RTCRSPCPEIMAGEDATA_OID) == 0);

        if (   pThis->Data.uValue.pPeImage
            && pThis->Data.uValue.pPeImage->T0.File.enmChoice == RTCRSPCLINKCHOICE_MONIKER
            && RTCrSpcSerializedObject_IsPresent(pThis->Data.uValue.pPeImage->T0.File.u.pMoniker) )
        {
            if (pThis->Data.uValue.pPeImage->T0.File.u.pMoniker->enmType == RTCRSPCSERIALIZEDOBJECTTYPE_ATTRIBUTES)
            {
                Assert(RTUuidCompareStr(pThis->Data.uValue.pPeImage->T0.File.u.pMoniker->Uuid.Asn1Core.uData.pUuid,
                                        RTCRSPCSERIALIZEDOBJECT_UUID_STR) == 0);
                PCRTCRSPCSERIALIZEDOBJECTATTRIBUTES pData = pThis->Data.uValue.pPeImage->T0.File.u.pMoniker->u.pData;
                if (pData)
                    for (uint32_t i = 0; i < pData->cItems; i++)
                        if (pData->paItems[i].enmType == enmType)
                            return &pData->paItems[i];
            }
        }
    }
    return NULL;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
RTDECL(int) RTCrX509Certificate_VerifySignature(PCRTCRX509CERTIFICATE pThis, PCRTASN1OBJID pAlgorithm,
                                                PCRTASN1DYNTYPE pParameters, PCRTASN1BITSTRING pPublicKey,
                                                PRTERRINFO pErrInfo)
{
    /*
     * Validate the input a little.
     */
    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
    AssertReturn(RTCrX509Certificate_IsPresent(pThis), VERR_INVALID_PARAMETER);

    AssertPtrReturn(pAlgorithm, VERR_INVALID_POINTER);
    AssertReturn(RTAsn1ObjId_IsPresent(pAlgorithm), VERR_INVALID_POINTER);

    if (pParameters)
    {
        AssertPtrReturn(pParameters, VERR_INVALID_POINTER);
        if (pParameters->enmType == RTASN1TYPE_NULL)
            pParameters = NULL;
    }

    AssertPtrReturn(pPublicKey, VERR_INVALID_POINTER);
    AssertReturn(RTAsn1BitString_IsPresent(pPublicKey), VERR_INVALID_POINTER);

    /*
     * Check if the algorithm matches.
     */
    const char *pszCipherOid = RTCrPkixGetCiperOidFromSignatureAlgorithm(&pThis->SignatureAlgorithm.Algorithm);
    if (!pszCipherOid)
        return RTErrInfoSetF(pErrInfo, VERR_CR_X509_UNKNOWN_CERT_SIGN_ALGO,
                             "Certificate signature algorithm not known: %s",
                             pThis->SignatureAlgorithm.Algorithm.szObjId);

    if (RTAsn1ObjId_CompareWithString(pAlgorithm, pszCipherOid) != 0)
        return RTErrInfoSetF(pErrInfo, VERR_CR_X509_CERT_SIGN_ALGO_MISMATCH,
                             "Certificate signature cipher algorithm mismatch: cert uses %s (%s) while key uses %s",
                             pszCipherOid, pThis->SignatureAlgorithm.Algorithm.szObjId, pAlgorithm->szObjId);

    /*
     * Here we should recode the to-be-signed part as DER, but we'll ASSUME
     * that it's already in DER encoding.  This is safe.
     */
    return RTCrPkixPubKeyVerifySignature(&pThis->SignatureAlgorithm.Algorithm, pParameters, pPublicKey, &pThis->SignatureValue,
                                         RTASN1CORE_GET_RAW_ASN1_PTR(&pThis->TbsCertificate.SeqCore.Asn1Core),
                                         RTASN1CORE_GET_RAW_ASN1_SIZE(&pThis->TbsCertificate.SeqCore.Asn1Core),
                                         pErrInfo);
}
static int rtCrPkcs7ContentInfo_DecodeExtra(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTCRPKCS7CONTENTINFO pThis,
                                            const char *pszErrorTag)
{
    pThis->u.pCore = NULL;

    /*
     * Figure the type.
     */
    RTCRPKCS7CONTENTINFOCHOICE  enmChoice;
    size_t                      cbContent = 0;
    if (RTAsn1ObjId_CompareWithString(&pThis->ContentType, RTCRPKCS7SIGNEDDATA_OID) == 0)
    {
        enmChoice = RTCRPKCS7CONTENTINFOCHOICE_SIGNED_DATA;
        cbContent = sizeof(*pThis->u.pSignedData);
    }
    else if (RTAsn1ObjId_CompareWithString(&pThis->ContentType, RTCRSPCINDIRECTDATACONTENT_OID) == 0)
    {
        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))
        {
            /*
             * Allocate memory for the decoded content.
             */
            rc = RTAsn1MemAllocZ(&pOctetString->EncapsulatedAllocation, (void **)&pOctetString->pEncapsulated, cbContent);
            if (RT_SUCCESS(rc))
            {
                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;
            }
        }
    }
    return rc;
}
static int rtCrPkcs7SignedData_CheckSanityExtra(PCRTCRPKCS7SIGNEDDATA pSignedData, uint32_t fFlags,
                                                PRTERRINFO pErrInfo, const char *pszErrorTag)
{
    bool const fAuthenticode = RT_BOOL(fFlags & RTCRPKCS7SIGNEDDATA_SANITY_F_AUTHENTICODE);

    //RTAsn1Dump(&pSignedData->SeqCore.Asn1Core, 0, 0, RTAsn1DumpStrmPrintfV, g_pStdOut);

    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);

    /*
     * DigestAlgorithms.
     */
    if (pSignedData->DigestAlgorithms.cItems == 0) /** @todo this might be too strict */
        return RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_SIGNED_DATA_NO_DIGEST_ALGOS, "SignedData.DigestAlgorithms is empty");
    if (pSignedData->DigestAlgorithms.cItems != 1 && fAuthenticode)
        return RTErrInfoSetF(pErrInfo, VERR_CR_SPC_NOT_EXACTLY_ONE_DIGEST_ALGO,
                             "SignedData.DigestAlgorithms has more than one algorithm (%u)",
                             pSignedData->DigestAlgorithms.cItems);

    if (fFlags & RTCRPKCS7SIGNEDDATA_SANITY_F_ONLY_KNOWN_HASH)
        for (uint32_t i = 0; i < pSignedData->DigestAlgorithms.cItems; i++)
        {
            if (RTCrX509AlgorithmIdentifier_QueryDigestType(&pSignedData->DigestAlgorithms.paItems[i]) == RTDIGESTTYPE_INVALID)
                return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_UNKNOWN_DIGEST_ALGORITHM,
                                     "SignedData.DigestAlgorithms[%i] is not known: %s",
                                     i, pSignedData->DigestAlgorithms.paItems[i].Algorithm.szObjId);
            if (pSignedData->DigestAlgorithms.paItems[i].Parameters.enmType != RTASN1TYPE_NULL)
                return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_DIGEST_PARAMS_NOT_IMPL,
                                     "SignedData.DigestAlgorithms[%i] has parameters: tag=%u",
                                     i, pSignedData->DigestAlgorithms.paItems[i].Parameters.u.Core.uTag);
        }

    /*
     * Certificates.
     */
    if (   (fFlags & RTCRPKCS7SIGNEDDATA_SANITY_F_SIGNING_CERT_PRESENT)
        && pSignedData->Certificates.cItems == 0)
        return RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_NO_CERTIFICATES,
                            "SignedData.Certifcates is empty, expected at least one certificate");

    /*
     * Crls.
     */
    if (fAuthenticode && RTAsn1Core_IsPresent(&pSignedData->Crls))
        return RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_EXPECTED_NO_CRLS,
                            "SignedData.Crls is not empty as expected for authenticode.");
    /** @todo check Crls when they become important. */

    /*
     * SignerInfos.
     */
    if (pSignedData->SignerInfos.cItems == 0)
        return RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_NO_SIGNER_INFOS, "SignedData.SignerInfos is empty?");
    if (fAuthenticode && pSignedData->SignerInfos.cItems != 1)
        return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_EXPECTED_ONE_SIGNER_INFO,
                             "SignedData.SignerInfos should have one entry for authenticode: %u",
                             pSignedData->SignerInfos.cItems);

    for (uint32_t i = 0; i < pSignedData->SignerInfos.cItems; i++)
    {
        PCRTCRPKCS7SIGNERINFO pSignerInfo = &pSignedData->SignerInfos.paItems[i];

        if (RTAsn1Integer_UnsignedCompareWithU32(&pSignerInfo->Version, RTCRPKCS7SIGNERINFO_V1) != 0)
            return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_SIGNER_INFO_VERSION,
                                 "SignedData.SignerInfos[%u] version is %llu, expected %u",
                                 pSignerInfo->Version.uValue.u, RTCRPKCS7SIGNERINFO_V1);

        /* IssuerAndSerialNumber. */
        int rc = RTCrX509Name_CheckSanity(&pSignerInfo->IssuerAndSerialNumber.Name, 0, pErrInfo,
                                          "SignedData.SignerInfos[#].IssuerAndSerialNumber.Name");
        if (RT_FAILURE(rc))
            return rc;

        if (pSignerInfo->IssuerAndSerialNumber.SerialNumber.Asn1Core.cb == 0)
            return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_SIGNER_INFO_NO_ISSUER_SERIAL_NO,
                                 "SignedData.SignerInfos[%u].IssuerAndSerialNumber.SerialNumber is missing (zero length)", i);

        PCRTCRX509CERTIFICATE pCert;
        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,
                                 "SignedData.SignerInfos[%u].IssuerAndSerialNumber not found in T0.Certificates", i);

        /* DigestAlgorithm */
        uint32_t j = 0;
        while (   j < pSignedData->DigestAlgorithms.cItems
               && RTCrX509AlgorithmIdentifier_Compare(&pSignedData->DigestAlgorithms.paItems[j],
                                                      &pSignerInfo->DigestAlgorithm) != 0)
            j++;
        if (j >= pSignedData->DigestAlgorithms.cItems)
            return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_DIGEST_ALGO_NOT_FOUND_IN_LIST,
                                 "SignedData.SignerInfos[%u].DigestAlgorithm (%s) not found in SignedData.DigestAlgorithms",
                                 i, pSignerInfo->DigestAlgorithm.Algorithm.szObjId);

        /* 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,
                                                   &pCert->TbsCertificate.SubjectPublicKeyInfo.Algorithm) != 0)
            return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_SIGNER_INFO_DIGEST_ENCRYPT_MISMATCH,
                                 "SignedData.SignerInfos[%u].DigestEncryptionAlgorithm (%s) mismatch with certificate (%s)",
                                 i, pSignerInfo->DigestEncryptionAlgorithm.Algorithm.szObjId,
                                 pCert->TbsCertificate.SubjectPublicKeyInfo.Algorithm.Algorithm.szObjId);
#endif

        /* Authenticated attributes we know. */
        if (RTCrPkcs7Attributes_IsPresent(&pSignerInfo->AuthenticatedAttributes))
        {
            bool fFoundContentInfo   = false;
            bool fFoundMessageDigest = false;
            for (j = 0; j < pSignerInfo->AuthenticatedAttributes.cItems; j++)
            {
                PCRTCRPKCS7ATTRIBUTE pAttrib = &pSignerInfo->AuthenticatedAttributes.paItems[j];
                if (RTAsn1ObjId_CompareWithString(&pAttrib->Type, RTCR_PKCS9_ID_CONTENT_TYPE_OID) == 0)
                {
                    if (fFoundContentInfo)
                        return RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_MISSING_CONTENT_TYPE_ATTRIB,
                                            "Multiple authenticated content-type attributes.");
                    fFoundContentInfo = true;
                    AssertReturn(pAttrib->enmType == RTCRPKCS7ATTRIBUTETYPE_OBJ_IDS, VERR_INTERNAL_ERROR_3);
                    if (pAttrib->uValues.pObjIds->cItems != 1)
                        return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_BAD_CONTENT_TYPE_ATTRIB,
                                             "Expected exactly one value for content-type attrib, found: %u",
                                             pAttrib->uValues.pObjIds->cItems);
                }
                else if (RTAsn1ObjId_CompareWithString(&pAttrib->Type, RTCR_PKCS9_ID_MESSAGE_DIGEST_OID) == 0)
                {
                    if (fFoundMessageDigest)
                        return RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_MISSING_MESSAGE_DIGEST_ATTRIB,
                                            "Multiple authenticated message-digest attributes.");
                    fFoundMessageDigest = true;
                    AssertReturn(pAttrib->enmType == RTCRPKCS7ATTRIBUTETYPE_OCTET_STRINGS, VERR_INTERNAL_ERROR_3);
                    if (pAttrib->uValues.pOctetStrings->cItems != 1)
                        return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_BAD_CONTENT_TYPE_ATTRIB,
                                             "Expected exactly one value for message-digest attrib, found: %u",
                                             pAttrib->uValues.pOctetStrings->cItems);
                }
                else
                    AssertReturn(pAttrib->enmType == RTCRPKCS7ATTRIBUTETYPE_UNKNOWN, VERR_INTERNAL_ERROR_3);
            }

            if (!fFoundContentInfo)
                return RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_MISSING_CONTENT_TYPE_ATTRIB,
                                    "Missing authenticated content-type attribute.");
            if (!fFoundMessageDigest)
                return RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_MISSING_MESSAGE_DIGEST_ATTRIB,
                                    "Missing authenticated message-digest attribute.");
        }
    }

    return VINF_SUCCESS;
}
Esempio n. 6
0
/*
 * One X.509 Extension.
 */
RTDECL(int) RTCrX509Extension_ExtnValue_DecodeAsn1(PRTASN1CURSOR pCursor, uint32_t fFlags,
                                                   PRTCRX509EXTENSION pThis, const char *pszErrorTag)
{
    pThis->enmValue = RTCRX509EXTENSIONVALUE_UNKNOWN;

    /*
     * Decode the encapsulated extension bytes if know the format.
     */
    RTASN1CURSOR ValueCursor;
    int rc = RTAsn1CursorInitSubFromCore(pCursor, &pThis->ExtnValue.Asn1Core, &ValueCursor, "ExtnValue");
    if (RT_FAILURE(rc))
        return rc;
    pCursor = &ValueCursor;

    if (RTAsn1ObjId_CompareWithString(&pThis->ExtnId, RTCRX509_ID_CE_AUTHORITY_KEY_IDENTIFIER_OID) == 0)
    {
        /* 4.2.1.1 Authority Key Identifier */
        PRTCRX509AUTHORITYKEYIDENTIFIER pThat;
        rc = RTAsn1MemAllocZ(&pThis->ExtnValue.EncapsulatedAllocation, (void **)&pThat, sizeof(*pThat));
        if (RT_SUCCESS(rc))
        {
            pThis->ExtnValue.pEncapsulated = &pThat->SeqCore.Asn1Core;
            pThis->enmValue = RTCRX509EXTENSIONVALUE_AUTHORITY_KEY_IDENTIFIER;
            rc = RTCrX509AuthorityKeyIdentifier_DecodeAsn1(&ValueCursor, 0, pThat, "AuthorityKeyIdentifier");
        }
    }
    else if (RTAsn1ObjId_CompareWithString(&pThis->ExtnId, RTCRX509_ID_CE_OLD_AUTHORITY_KEY_IDENTIFIER_OID) == 0)
    {
        /* Old and obsolete version of the above, still found in microsoft certificates. */
        PRTCRX509OLDAUTHORITYKEYIDENTIFIER pThat;
        rc = RTAsn1MemAllocZ(&pThis->ExtnValue.EncapsulatedAllocation, (void **)&pThat, sizeof(*pThat));
        if (RT_SUCCESS(rc))
        {
            pThis->ExtnValue.pEncapsulated = &pThat->SeqCore.Asn1Core;
            pThis->enmValue = RTCRX509EXTENSIONVALUE_OLD_AUTHORITY_KEY_IDENTIFIER;
            rc = RTCrX509OldAuthorityKeyIdentifier_DecodeAsn1(&ValueCursor, 0, pThat, "OldAuthorityKeyIdentifier");
        }
    }
    else if (RTAsn1ObjId_CompareWithString(&pThis->ExtnId, RTCRX509_ID_CE_SUBJECT_KEY_IDENTIFIER_OID) == 0)
    {
        /* 4.2.1.2 Subject Key Identifier */
        PRTASN1OCTETSTRING pThat;
        rc = RTAsn1MemAllocZ(&pThis->ExtnValue.EncapsulatedAllocation, (void **)&pThat, sizeof(*pThat));
        if (RT_SUCCESS(rc))
        {
            pThis->ExtnValue.pEncapsulated = &pThat->Asn1Core;
            pThis->enmValue = RTCRX509EXTENSIONVALUE_OCTET_STRING;
            rc = RTAsn1CursorGetOctetString(&ValueCursor, 0, pThat, "SubjectKeyIdentifier");
        }
    }
    else if (RTAsn1ObjId_CompareWithString(&pThis->ExtnId, RTCRX509_ID_CE_KEY_USAGE_OID) == 0)
    {
        /* 4.2.1.3 Key Usage */
        PRTASN1BITSTRING pThat;
        rc = RTAsn1MemAllocZ(&pThis->ExtnValue.EncapsulatedAllocation, (void **)&pThat, sizeof(*pThat));
        if (RT_SUCCESS(rc))
        {
            pThis->ExtnValue.pEncapsulated = &pThat->Asn1Core;
            pThis->enmValue = RTCRX509EXTENSIONVALUE_BIT_STRING;
            rc = RTAsn1CursorGetBitStringEx(&ValueCursor, 0, 9, pThat, "KeyUsage");
        }
    }
    else if (RTAsn1ObjId_CompareWithString(&pThis->ExtnId, RTCRX509_ID_CE_CERTIFICATE_POLICIES_OID) == 0)
    {
        /* 4.2.1.4 Certificate Policies */
        PRTCRX509CERTIFICATEPOLICIES pThat;
        rc = RTAsn1MemAllocZ(&pThis->ExtnValue.EncapsulatedAllocation, (void **)&pThat, sizeof(*pThat));
        if (RT_SUCCESS(rc))
        {
            pThis->ExtnValue.pEncapsulated = &pThat->SeqCore.Asn1Core;
            pThis->enmValue = RTCRX509EXTENSIONVALUE_CERTIFICATE_POLICIES;
            rc = RTCrX509CertificatePolicies_DecodeAsn1(&ValueCursor, 0, pThat, "CertPolicies");
        }
    }
    else if (RTAsn1ObjId_CompareWithString(&pThis->ExtnId, RTCRX509_ID_CE_POLICY_MAPPINGS_OID) == 0)
    {
        /* 4.2.1.5 Policy Mappings */
        PRTCRX509POLICYMAPPINGS pThat;
        rc = RTAsn1MemAllocZ(&pThis->ExtnValue.EncapsulatedAllocation, (void **)&pThat, sizeof(*pThat));
        if (RT_SUCCESS(rc))
        {
            pThis->ExtnValue.pEncapsulated = &pThat->SeqCore.Asn1Core;
            pThis->enmValue = RTCRX509EXTENSIONVALUE_POLICY_MAPPINGS;
            rc = RTCrX509PolicyMappings_DecodeAsn1(&ValueCursor, 0, pThat, "PolicyMapppings");
        }
    }
    else if (   RTAsn1ObjId_CompareWithString(&pThis->ExtnId, RTCRX509_ID_CE_SUBJECT_ALT_NAME_OID) == 0
             || RTAsn1ObjId_CompareWithString(&pThis->ExtnId, RTCRX509_ID_CE_ISSUER_ALT_NAME_OID) == 0)
    {
        /* 4.2.1.6 Subject Alternative Name  /  4.2.1.7 Issuer Alternative Name */
        PRTCRX509GENERALNAMES pThat;
        rc = RTAsn1MemAllocZ(&pThis->ExtnValue.EncapsulatedAllocation, (void **)&pThat, sizeof(*pThat));
        if (RT_SUCCESS(rc))
        {
            pThis->ExtnValue.pEncapsulated = &pThat->SeqCore.Asn1Core;
            pThis->enmValue = RTCRX509EXTENSIONVALUE_GENERAL_NAMES;
            rc = RTCrX509GeneralNames_DecodeAsn1(&ValueCursor, 0, pThat, "AltName");
        }
    }
    else if (RTAsn1ObjId_CompareWithString(&pThis->ExtnId, RTCRX509_ID_CE_BASIC_CONSTRAINTS_OID) == 0)
    {
        /* 4.2.1.9 Basic Constraints */
        PRTCRX509BASICCONSTRAINTS pThat;
        rc = RTAsn1MemAllocZ(&pThis->ExtnValue.EncapsulatedAllocation, (void **)&pThat, sizeof(*pThat));
        if (RT_SUCCESS(rc))
        {
            pThis->ExtnValue.pEncapsulated = &pThat->SeqCore.Asn1Core;
            pThis->enmValue = RTCRX509EXTENSIONVALUE_BASIC_CONSTRAINTS;
            rc = RTCrX509BasicConstraints_DecodeAsn1(&ValueCursor, 0, pThat, "BasicConstraints");
        }
    }
    else if (RTAsn1ObjId_CompareWithString(&pThis->ExtnId, RTCRX509_ID_CE_NAME_CONSTRAINTS_OID) == 0)
    {
        /* 4.2.1.10 Name Constraints */
        PRTCRX509NAMECONSTRAINTS pThat;
        rc = RTAsn1MemAllocZ(&pThis->ExtnValue.EncapsulatedAllocation, (void **)&pThat, sizeof(*pThat));
        if (RT_SUCCESS(rc))
        {
            pThis->ExtnValue.pEncapsulated = &pThat->SeqCore.Asn1Core;
            pThis->enmValue = RTCRX509EXTENSIONVALUE_NAME_CONSTRAINTS;
            rc = RTCrX509NameConstraints_DecodeAsn1(&ValueCursor, 0, pThat, "NameConstraints");
        }
    }
    else if (RTAsn1ObjId_CompareWithString(&pThis->ExtnId, RTCRX509_ID_CE_POLICY_CONSTRAINTS_OID) == 0)
    {
        /* 4.2.1.11 Policy Constraints */
        PRTCRX509POLICYCONSTRAINTS pThat;
        rc = RTAsn1MemAllocZ(&pThis->ExtnValue.EncapsulatedAllocation, (void **)&pThat, sizeof(*pThat));
        if (RT_SUCCESS(rc))
        {
            pThis->ExtnValue.pEncapsulated = &pThat->SeqCore.Asn1Core;
            pThis->enmValue = RTCRX509EXTENSIONVALUE_POLICY_CONSTRAINTS;
            rc = RTCrX509PolicyConstraints_DecodeAsn1(&ValueCursor, 0, pThat, "PolicyConstraints");
        }
    }
    else if (RTAsn1ObjId_CompareWithString(&pThis->ExtnId, RTCRX509_ID_CE_EXT_KEY_USAGE_OID) == 0)
    {
        /* 4.2.1.12 Extended Key Usage */
        PRTASN1SEQOFOBJIDS pThat;
        rc = RTAsn1MemAllocZ(&pThis->ExtnValue.EncapsulatedAllocation, (void **)&pThat, sizeof(*pThat));
        if (RT_SUCCESS(rc))
        {
            pThis->ExtnValue.pEncapsulated = &pThat->SeqCore.Asn1Core;
            pThis->enmValue = RTCRX509EXTENSIONVALUE_SEQ_OF_OBJ_IDS;
            rc = RTAsn1SeqOfObjIds_DecodeAsn1(&ValueCursor, 0, pThat, "ExKeyUsage");
        }
    }
    else if (RTAsn1ObjId_CompareWithString(&pThis->ExtnId, RTCRX509_ID_CE_EXT_KEY_USAGE_OID) == 0)
    {
        /* 4.2.1.14 Inhibit anyPolicy */
        PRTASN1INTEGER pThat;
        rc = RTAsn1MemAllocZ(&pThis->ExtnValue.EncapsulatedAllocation, (void **)&pThat, sizeof(*pThat));
        if (RT_SUCCESS(rc))
        {
            pThis->ExtnValue.pEncapsulated = &pThat->Asn1Core;
            pThis->enmValue = RTCRX509EXTENSIONVALUE_INTEGER;
            rc = RTAsn1CursorGetInteger(&ValueCursor, 0, pThat, "InhibitAnyPolicy");
        }
    }
    else
        return VINF_SUCCESS;

    if (RT_SUCCESS(rc))
        rc = RTAsn1CursorCheckEnd(&ValueCursor);

    if (RT_SUCCESS(rc))
        return VINF_SUCCESS;
    return rc;
}
Esempio n. 7
0
RTDECL(int) RTCrSpcIndirectDataContent_CheckSanityEx(PCRTCRSPCINDIRECTDATACONTENT pIndData,
                                                     PCRTCRPKCS7SIGNEDDATA pSignedData,
                                                     uint32_t fFlags,
                                                     PRTERRINFO pErrInfo)
{
    /*
     * Match up the digest algorithms (page 8, v1.0).
     */
    if (pSignedData->SignerInfos.cItems != 1)
        return RTErrInfoSetF(pErrInfo, VERR_CR_SPC_NOT_EXACTLY_ONE_SIGNER_INFOS,
                             "SpcIndirectDataContent expects SignedData to have exactly one SignerInfos entries, found: %u",
                             pSignedData->SignerInfos.cItems);
    if (pSignedData->DigestAlgorithms.cItems != 1)
        return RTErrInfoSetF(pErrInfo, VERR_CR_SPC_NOT_EXACTLY_ONE_DIGEST_ALGO,
                             "SpcIndirectDataContent expects SignedData to have exactly one DigestAlgorithms entries, found: %u",
                             pSignedData->DigestAlgorithms.cItems);

    if (RTCrX509AlgorithmIdentifier_Compare(&pIndData->DigestInfo.DigestAlgorithm, /** @todo not entirely sure about this check... */
                                            &pSignedData->SignerInfos.paItems[0].DigestAlgorithm) != 0)
        return RTErrInfoSetF(pErrInfo, VERR_CR_SPC_SIGNED_IND_DATA_DIGEST_ALGO_MISMATCH,
                             "SpcIndirectDataContent DigestInfo and SignerInfos algorithms mismatch: %s vs %s",
                             pIndData->DigestInfo.DigestAlgorithm.Algorithm.szObjId,
                             pSignedData->SignerInfos.paItems[0].DigestAlgorithm.Algorithm.szObjId);

    if (RTCrX509AlgorithmIdentifier_Compare(&pIndData->DigestInfo.DigestAlgorithm,
                                            &pSignedData->DigestAlgorithms.paItems[0]) != 0)
        return RTErrInfoSetF(pErrInfo, VERR_CR_SPC_IND_DATA_DIGEST_ALGO_NOT_IN_DIGEST_ALGOS,
                             "SpcIndirectDataContent DigestInfo and SignedData.DigestAlgorithms[0] mismatch: %s vs %s",
                             pIndData->DigestInfo.DigestAlgorithm.Algorithm.szObjId,
                             pSignedData->DigestAlgorithms.paItems[0].Algorithm.szObjId);

    if (fFlags & RTCRSPCINDIRECTDATACONTENT_SANITY_F_ONLY_KNOWN_HASH)
    {
        if (RTCrX509AlgorithmIdentifier_QueryDigestType(&pIndData->DigestInfo.DigestAlgorithm) == RTDIGESTTYPE_INVALID)
            return RTErrInfoSetF(pErrInfo, VERR_CR_SPC_UNKNOWN_DIGEST_ALGO,
                                 "SpcIndirectDataContent DigestAlgortihm is not known: %s",
                                 pIndData->DigestInfo.DigestAlgorithm.Algorithm.szObjId);
    }

    uint32_t cbDigest = RTCrX509AlgorithmIdentifier_QueryDigestSize(&pIndData->DigestInfo.DigestAlgorithm);
    if (   pIndData->DigestInfo.Digest.Asn1Core.cb != cbDigest
        && (cbDigest != UINT32_MAX || (fFlags & RTCRSPCINDIRECTDATACONTENT_SANITY_F_ONLY_KNOWN_HASH)))
        return RTErrInfoSetF(pErrInfo, VERR_CR_SPC_IND_DATA_DIGEST_SIZE_MISMATCH,
                             "SpcIndirectDataContent Digest size mismatch with algorithm: %u, expected %u (%s)",
                             pIndData->DigestInfo.Digest.Asn1Core.cb, cbDigest,
                             pIndData->DigestInfo.DigestAlgorithm.Algorithm.szObjId);

    /*
     * Data.
     */
    if (fFlags & RTCRSPCINDIRECTDATACONTENT_SANITY_F_PE_IMAGE)
    {
        if (   pIndData->Data.enmType != RTCRSPCAAOVTYPE_PE_IMAGE_DATA
            || RTAsn1ObjId_CompareWithString(&pIndData->Data.Type, RTCRSPCPEIMAGEDATA_OID) != 0)
            return RTErrInfoSetF(pErrInfo, VERR_CR_SPC_EXPECTED_PE_IMAGE_DATA,
                                 "SpcIndirectDataContent.Data.Type is %s, expected %s (SpcPeImageData) [enmType=%d]",
                                 pIndData->Data.Type.szObjId, RTCRSPCPEIMAGEDATA_OID, pIndData->Data.enmType);
        if (   pIndData->Data.uValue.pPeImage
            || !RTCrSpcPeImageData_IsPresent(pIndData->Data.uValue.pPeImage) )
            return RTErrInfoSet(pErrInfo, VERR_CR_SPC_PEIMAGE_DATA_NOT_PRESENT,
                                "SpcIndirectDataContent.Data.uValue/PEImage is missing");

        if (   pIndData->Data.uValue.pPeImage->T0.File.enmChoice == RTCRSPCLINKCHOICE_MONIKER
            && RTCrSpcSerializedObject_IsPresent(pIndData->Data.uValue.pPeImage->T0.File.u.pMoniker) )
        {
            PCRTCRSPCSERIALIZEDOBJECT pObj = pIndData->Data.uValue.pPeImage->T0.File.u.pMoniker;

            if (pObj->Uuid.Asn1Core.cb != sizeof(RTUUID))
                return RTErrInfoSetF(pErrInfo, VERR_CR_SPC_BAD_MONIKER_UUID,
                                     "SpcIndirectDataContent...MonikerT1.Uuid incorrect size: %u, expected %u.",
                                     pObj->Uuid.Asn1Core.cb, sizeof(RTUUID));
            if (RTUuidCompareStr(pObj->Uuid.Asn1Core.uData.pUuid, RTCRSPCSERIALIZEDOBJECT_UUID_STR) != 0)
                return RTErrInfoSetF(pErrInfo, VERR_CR_SPC_UNKNOWN_MONIKER_UUID,
                                     "SpcIndirectDataContent...MonikerT1.Uuid mismatch: %RTuuid, expected %s.",
                                     pObj->Uuid.Asn1Core.uData.pUuid, RTCRSPCSERIALIZEDOBJECT_UUID_STR);

            if (pObj->enmType != RTCRSPCSERIALIZEDOBJECTTYPE_ATTRIBUTES)
                return RTErrInfoSetF(pErrInfo, VERR_CR_SPC_BAD_MONIKER_CHOICE,
                                     "SpcIndirectDataContent...pMoniker->enmType=%d, expected %d.",
                                     pObj->enmType, RTCRSPCSERIALIZEDOBJECTTYPE_ATTRIBUTES);
            if (!pObj->u.pData)
                return RTErrInfoSet(pErrInfo, VERR_CR_SPC_MONIKER_BAD_DATA,
                                    "SpcIndirectDataContent...pMoniker->pData is NULL.");

            uint32_t cPageHashTabs = 0;
            for (uint32_t i = 0; i < pObj->u.pData->cItems; i++)
            {
                PCRTCRSPCSERIALIZEDOBJECTATTRIBUTE pAttr = &pObj->u.pData->paItems[i];
                if (   RTAsn1ObjId_CompareWithString(&pAttr->Type, RTCRSPC_PE_IMAGE_HASHES_V1_OID) == 0
                    || RTAsn1ObjId_CompareWithString(&pAttr->Type, RTCRSPC_PE_IMAGE_HASHES_V2_OID) == 0 )
                {
                    cPageHashTabs++;
                    AssertPtr(pAttr->u.pPageHashes->pData);
                }
                else
                    return RTErrInfoSetF(pErrInfo, VERR_CR_SPC_PEIMAGE_UNKNOWN_ATTRIBUTE,
                                         "SpcIndirectDataContent...MonikerT1 unknown attribute %u: %s.",
                                         i, pAttr->Type.szObjId);
            }
            if (cPageHashTabs > 0)
                return RTErrInfoSetF(pErrInfo, VERR_CR_SPC_PEIMAGE_MULTIPLE_HASH_TABS,
                                     "SpcIndirectDataContent...MonikerT1 multiple page hash attributes (%u).", cPageHashTabs);

        }
        else if (   pIndData->Data.uValue.pPeImage->T0.File.enmChoice == RTCRSPCLINKCHOICE_FILE
                 && RTCrSpcString_IsPresent(&pIndData->Data.uValue.pPeImage->T0.File.u.pT2->File) )
        {
            /* Could check for "<<<Obsolete>>>" here, but it's really irrelevant. */
        }
        else if (   pIndData->Data.uValue.pPeImage->T0.File.enmChoice == RTCRSPCLINKCHOICE_URL
                 && RTAsn1String_IsPresent(pIndData->Data.uValue.pPeImage->T0.File.u.pUrl) )
            return RTErrInfoSet(pErrInfo, VERR_CR_SPC_PEIMAGE_URL_UNEXPECTED,
                                "SpcIndirectDataContent.Data.uValue.pPeImage->File is an URL, expected object Moniker or File.");
        else
            return RTErrInfoSet(pErrInfo, VERR_CR_SPC_PEIMAGE_NO_CONTENT,
                                "SpcIndirectDataContent.Data.uValue.pPeImage->File has no content");
    }

    return VINF_SUCCESS;
}
Esempio n. 8
0
RTDECL(bool) RTCrPkcs7ContentInfo_IsSignedData(PCRTCRPKCS7CONTENTINFO pThis)
{
    return RTAsn1ObjId_CompareWithString(&pThis->ContentType, RTCRPKCS7SIGNEDDATA_OID) == 0;
}
Esempio n. 9
0
/**
 * Deals with authenticated attributes.
 *
 * When authenticated attributes are present (checked by caller) we must:
 *  - fish out the content type and check it against the content inof,
 *  - fish out the message digest among and check it against *phDigest,
 *  - compute the message digest of the authenticated attributes and
 *    replace *phDigest with this for the signature verification.
 *
 * @returns IPRT status code.
 * @param   pSignerInfo         The signer info being verified.
 * @param   pSignedData         The signed data.
 * @param   phDigest            On input this is the digest of the content. On
 *                              output it will (on success) be a reference to
 *                              the message digest of the authenticated
 *                              attributes.  The input reference is consumed.
 *                              The caller shall release the output reference.
 * @param   fFlags              Flags.
 * @param   pErrInfo            Extended error info, optional.
 */
static int rtCrPkcs7VerifySignerInfoAuthAttribs(PCRTCRPKCS7SIGNERINFO pSignerInfo, PCRTCRPKCS7SIGNEDDATA pSignedData,
                                                PRTCRDIGEST phDigest, uint32_t fFlags, PRTERRINFO pErrInfo)
{
    /*
     * Scan the attributes and validate the two required attributes
     * (RFC-2315, chapter 9.2, fourth bullet).  Checking that we've got exactly
     * one of each of them is checked by the santiy checker function, so we'll
     * just assert that it did it's job here.
     */
    uint32_t    cContentTypes   = 0;
    uint32_t    cMessageDigests = 0;
    uint32_t    i               = pSignerInfo->AuthenticatedAttributes.cItems;
    while (i-- > 0)
    {
        PCRTCRPKCS7ATTRIBUTE pAttrib = &pSignerInfo->AuthenticatedAttributes.paItems[i];

        if (RTAsn1ObjId_CompareWithString(&pAttrib->Type, RTCR_PKCS9_ID_CONTENT_TYPE_OID) == 0)
        {
            AssertReturn(!cContentTypes, VERR_CR_PKCS7_INTERNAL_ERROR);
            AssertReturn(pAttrib->enmType == RTCRPKCS7ATTRIBUTETYPE_OBJ_IDS, VERR_CR_PKCS7_INTERNAL_ERROR);
            AssertReturn(pAttrib->uValues.pObjIds->cItems == 1, VERR_CR_PKCS7_INTERNAL_ERROR);

            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++;
        }
        else if (RTAsn1ObjId_CompareWithString(&pAttrib->Type, RTCR_PKCS9_ID_MESSAGE_DIGEST_OID) == 0)
        {
            AssertReturn(!cMessageDigests, VERR_CR_PKCS7_INTERNAL_ERROR);
            AssertReturn(pAttrib->enmType == RTCRPKCS7ATTRIBUTETYPE_OCTET_STRINGS, VERR_CR_PKCS7_INTERNAL_ERROR);
            AssertReturn(pAttrib->uValues.pOctetStrings->cItems == 1, VERR_CR_PKCS7_INTERNAL_ERROR);

            if (!RTCrDigestMatch(*phDigest,
                                 pAttrib->uValues.pOctetStrings->paItems[0].Asn1Core.uData.pv,
                                 pAttrib->uValues.pOctetStrings->paItems[0].Asn1Core.cb))
            {
                size_t cbHash = RTCrDigestGetHashSize(*phDigest);
                if (cbHash != pAttrib->uValues.pOctetStrings->paItems[0].Asn1Core.cb)
                    return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_MESSAGE_DIGEST_ATTRIB_MISMATCH,
                                         "Authenticated message-digest attribute mismatch: cbHash=%#zx cbValue=%#x",
                                         cbHash, pAttrib->uValues.pOctetStrings->paItems[0].Asn1Core.cb);
                return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_MESSAGE_DIGEST_ATTRIB_MISMATCH,
                                     "Authenticated message-digest attribute mismatch (cbHash=%#zx):\n"
                                     "signed: %.*Rhxs\n"
                                     "our:    %.*Rhxs\n",
                                     cbHash,
                                     cbHash, pAttrib->uValues.pOctetStrings->paItems[0].Asn1Core.uData.pv,
                                     cbHash, RTCrDigestGetHash(*phDigest));
            }
            cMessageDigests++;
        }
    }

    /*
     * 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.");

    /*
     * Calculate the digest of the the authenticated attributes for use in the
     * signature validation.
     */
    if (   pSignerInfo->DigestAlgorithm.Parameters.enmType != RTASN1TYPE_NULL
        && pSignerInfo->DigestAlgorithm.Parameters.enmType != RTASN1TYPE_NOT_PRESENT)
        return RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_DIGEST_PARAMS_NOT_IMPL, "Digest algorithm has unsupported parameters");

    RTCRDIGEST hDigest;
    int rc = RTCrDigestCreateByObjId(&hDigest, &pSignerInfo->DigestAlgorithm.Algorithm);
    if (RT_SUCCESS(rc))
    {
        RTCrDigestRelease(*phDigest);
        *phDigest = hDigest;

        /* ASSUMES that the attributes are encoded according to DER. */
        uint8_t const  *pbData = (uint8_t const *)RTASN1CORE_GET_RAW_ASN1_PTR(&pSignerInfo->AuthenticatedAttributes.SetCore.Asn1Core);
        uint32_t        cbData = RTASN1CORE_GET_RAW_ASN1_SIZE(&pSignerInfo->AuthenticatedAttributes.SetCore.Asn1Core);
        uint8_t         bSetOfTag = ASN1_TAG_SET | ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_CONSTRUCTED;
        rc = RTCrDigestUpdate(hDigest, &bSetOfTag, sizeof(bSetOfTag)); /* Replace the implict tag with a SET-OF tag. */
        if (RT_SUCCESS(rc))
            rc = RTCrDigestUpdate(hDigest, pbData + sizeof(bSetOfTag), cbData - sizeof(bSetOfTag)); /* Skip the implicit tag. */
        if (RT_SUCCESS(rc))
            rc = RTCrDigestFinal(hDigest, NULL, 0);
    }
    return rc;
}
Esempio n. 10
0
RTDECL(int) RTCrX509Certificate_VerifySignature(PCRTCRX509CERTIFICATE pThis, PCRTASN1OBJID pAlgorithm,
                                                PCRTASN1DYNTYPE pParameters, PCRTASN1BITSTRING pPublicKey,
                                                PRTERRINFO pErrInfo)
{
    /*
     * Validate the input a little.
     */
    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
    AssertReturn(RTCrX509Certificate_IsPresent(pThis), VERR_INVALID_PARAMETER);

    AssertPtrReturn(pAlgorithm, VERR_INVALID_POINTER);
    AssertReturn(RTAsn1ObjId_IsPresent(pAlgorithm), VERR_INVALID_POINTER);

    if (pParameters)
    {
        AssertPtrReturn(pParameters, VERR_INVALID_POINTER);
        if (pParameters->enmType == RTASN1TYPE_NULL)
            pParameters = NULL;
    }

    AssertPtrReturn(pPublicKey, VERR_INVALID_POINTER);
    AssertReturn(RTAsn1BitString_IsPresent(pPublicKey), VERR_INVALID_POINTER);

    /*
     * Check if the algorithm matches.
     */
    const char *pszCipherOid = RTCrPkixGetCiperOidFromSignatureAlgorithm(&pThis->SignatureAlgorithm.Algorithm);
    if (!pszCipherOid)
        return RTErrInfoSetF(pErrInfo, VERR_CR_X509_UNKNOWN_CERT_SIGN_ALGO,
                             "Certificate signature algorithm not known: %s",
                             pThis->SignatureAlgorithm.Algorithm.szObjId);

    if (RTAsn1ObjId_CompareWithString(pAlgorithm, pszCipherOid) != 0)
        return RTErrInfoSetF(pErrInfo, VERR_CR_X509_CERT_SIGN_ALGO_MISMATCH,
                             "Certificate signature cipher algorithm mismatch: cert uses %s (%s) while key uses %s",
                             pszCipherOid, pThis->SignatureAlgorithm.Algorithm.szObjId, pAlgorithm->szObjId);

    /*
     * Here we should recode the to-be-signed part as DER, but we'll ASSUME
     * that it's already in DER encoding and only does this if there the
     * encoded bits are missing.
     */
    if (   pThis->TbsCertificate.SeqCore.Asn1Core.uData.pu8
        && pThis->TbsCertificate.SeqCore.Asn1Core.cb > 0)
        return RTCrPkixPubKeyVerifySignature(&pThis->SignatureAlgorithm.Algorithm, pParameters, pPublicKey, &pThis->SignatureValue,
                                             RTASN1CORE_GET_RAW_ASN1_PTR(&pThis->TbsCertificate.SeqCore.Asn1Core),
                                             RTASN1CORE_GET_RAW_ASN1_SIZE(&pThis->TbsCertificate.SeqCore.Asn1Core),
                                             pErrInfo);

    uint32_t cbEncoded;
    int rc = RTAsn1EncodePrepare((PRTASN1CORE)&pThis->TbsCertificate.SeqCore.Asn1Core, RTASN1ENCODE_F_DER, &cbEncoded, pErrInfo);
    if (RT_SUCCESS(rc))
    {
        void *pvTbsBits = RTMemTmpAlloc(cbEncoded);
        if (pvTbsBits)
        {
            rc = RTAsn1EncodeToBuffer(&pThis->TbsCertificate.SeqCore.Asn1Core, RTASN1ENCODE_F_DER,
                                      pvTbsBits, cbEncoded, pErrInfo);
            if (RT_SUCCESS(rc))
                rc = RTCrPkixPubKeyVerifySignature(&pThis->SignatureAlgorithm.Algorithm, pParameters, pPublicKey,
                                                   &pThis->SignatureValue, pvTbsBits, cbEncoded, pErrInfo);
            else
                AssertRC(rc);
            RTMemTmpFree(pvTbsBits);
        }
        else
            rc = VERR_NO_TMP_MEMORY;
    }
    return rc;
}