Beispiel #1
0
/**
 * 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;
        }
    *phDigest = NIL_RTCRDIGEST; /* Make gcc happy. */
    return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_DIGEST_ALGO_NOT_FOUND_IN_LIST,
                         "SignerInfo.DigestAlgorithm %s not found.",
                         pSignerInfo->DigestAlgorithm.Algorithm.szObjId);
}
RTDECL(int) RTCrPkixSignatureVerify(RTCRPKIXSIGNATURE hSignature, RTCRDIGEST hDigest,
                                    void const *pvSignature, size_t cbSignature)
{
    PRTCRPKIXSIGNATUREINT pThis = hSignature;
    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    AssertReturn(pThis->u32Magic == RTCRPKIXSIGNATUREINT_MAGIC, VERR_INVALID_HANDLE);
    AssertReturn(!pThis->fSigning, VERR_INVALID_FUNCTION);
    AssertReturn(pThis->uState == RTCRPKIXSIGNATURE_STATE_READY || pThis->uState == RTCRPKIXSIGNATURE_STATE_DONE, VERR_INVALID_STATE);

    uint32_t cRefs = RTCrDigestRetain(hDigest);
    AssertReturn(cRefs != UINT32_MAX, VERR_INVALID_HANDLE);

    int rc = rtCrPkxiSignatureReset(pThis);
    if (RT_SUCCESS(rc))
    {
        rc = pThis->pDesc->pfnVerify(pThis->pDesc, pThis->abState, hDigest, pvSignature, cbSignature);
        pThis->uState = RTCRPKIXSIGNATURE_STATE_DONE;
    }

    RTCrDigestRelease(hDigest);
    return rc;
}
Beispiel #3
0
/**
 * Verifies one signature on a PKCS \#7 SignedData.
 *
 * @returns IPRT status code.
 * @param   pSignerInfo         The signature.
 * @param   pSignedData         The SignedData.
 * @param   hDigests            The digest corresponding to
 *                              pSignerInfo->DigestAlgorithm.
 * @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 rtCrPkcs7VerifySignerInfo(PCRTCRPKCS7SIGNERINFO pSignerInfo, PCRTCRPKCS7SIGNEDDATA pSignedData,
                                     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.
     */
    PCRTCRCERTCTX           pSignerCertCtx = NULL;
    PCRTCRX509CERTIFICATE   pSignerCert = NULL;
    RTCRSTORE               hSignerCertSrc = hTrustedCerts;
    if (hSignerCertSrc != NIL_RTCRSTORE)
        pSignerCertCtx = RTCrStoreCertByIssuerAndSerialNo(hSignerCertSrc, &pSignerInfo->IssuerAndSerialNumber.Name,
                                                          &pSignerInfo->IssuerAndSerialNumber.SerialNumber);
    if (!pSignerCertCtx)
    {
        hSignerCertSrc = hAdditionalCerts;
        if (hSignerCertSrc != NIL_RTCRSTORE)
            pSignerCertCtx = RTCrStoreCertByIssuerAndSerialNo(hSignerCertSrc, &pSignerInfo->IssuerAndSerialNumber.Name,
                                                              &pSignerInfo->IssuerAndSerialNumber.SerialNumber);
    }
    if (pSignerCertCtx)
        pSignerCert = pSignerCertCtx->pCert;
    else
    {
        hSignerCertSrc = NULL;
        pSignerCert = RTCrPkcs7SetOfCerts_FindX509ByIssuerAndSerialNumber(&pSignedData->Certificates,
                                                                          &pSignerInfo->IssuerAndSerialNumber.Name,
                                                                          &pSignerInfo->IssuerAndSerialNumber.SerialNumber);
        if (!pSignerCert)
            return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_SIGNED_DATA_CERT_NOT_FOUND,
                                 "Certificate not found: serial=%.*Rhxs",
                                 pSignerInfo->IssuerAndSerialNumber.SerialNumber.Asn1Core.cb,
                                 pSignerInfo->IssuerAndSerialNumber.SerialNumber.Asn1Core.uData.pv);
    }

    /*
     * If not a trusted certificate, we'll have to build certificate paths
     * and verify them.  If no valid paths are found, this step will fail.
     */
    int rc = VINF_SUCCESS;
    if (   hSignerCertSrc == NIL_RTCRSTORE
        || hSignerCertSrc != hTrustedCerts)
    {
        RTCRX509CERTPATHS hCertPaths;
        rc = RTCrX509CertPathsCreate(&hCertPaths, pSignerCert);
        if (RT_SUCCESS(rc))
        {
            rc = RTCrX509CertPathsSetValidTimeSpec(hCertPaths, pValidationTime);
            if (hTrustedCerts != NIL_RTCRSTORE && RT_SUCCESS(rc))
                rc = RTCrX509CertPathsSetTrustedStore(hCertPaths, hTrustedCerts);
            if (hAdditionalCerts != NIL_RTCRSTORE && RT_SUCCESS(rc))
                rc = RTCrX509CertPathsSetUntrustedStore(hCertPaths, hAdditionalCerts);
            if (pSignedData->Certificates.cItems > 0 && RT_SUCCESS(rc))
                rc = RTCrX509CertPathsSetUntrustedSet(hCertPaths, &pSignedData->Certificates);
            if (RT_SUCCESS(rc))
            {
                rc = RTCrX509CertPathsBuild(hCertPaths, pErrInfo);
                if (RT_SUCCESS(rc))
                    rc = RTCrX509CertPathsValidateAll(hCertPaths, NULL, pErrInfo);

                /*
                 * Check that the certificate purpose and whatnot matches what
                 * is being signed.
                 */
                if (RT_SUCCESS(rc))
                    rc = pfnVerifyCert(pSignerCert, hCertPaths, fVccFlags, pvUser, pErrInfo);
            }
            else
                RTErrInfoSetF(pErrInfo, rc, "Error configuring path builder: %Rrc", rc);
            RTCrX509CertPathsRelease(hCertPaths);
        }
    }
    /*
     * Check that the certificate purpose matches what is signed.
     */
    else
        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)
        && 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))
        {
            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;
}