/*
 * SecCmsSignedDataVerifySignerInfo - check the signatures.
 *
 * The digests were either calculated during decoding (and are stored in the
 * signedData itself) or set after decoding using SecCmsSignedDataSetDigests.
 *
 * The verification checks if the signing cert is valid and has a trusted chain
 * for the purpose specified by "policies".
 *
 * If trustRef is NULL the cert chain is verified and the VerificationStatus is set accordingly.
 * Otherwise a SecTrust object is returned for the caller to evaluate using SecTrustEvaluate().
 */
OSStatus
SecCmsSignedDataVerifySignerInfo(SecCmsSignedDataRef sigd, int i, 
			    SecKeychainRef keychainOrArray, CFTypeRef policies, SecTrustRef *trustRef)
{
    SecCmsSignerInfoRef signerinfo;
    SecCmsContentInfoRef cinfo;
    SECOidData *algiddata;
    CSSM_DATA_PTR contentType, digest;
    OSStatus status, status2;

    cinfo = &(sigd->contentInfo);

    signerinfo = sigd->signerInfos[i];

    /* Signature or digest level verificationStatus errors should supercede
       certificate level errors, so check the digest and signature first.  */

    /* Find digest and contentType for signerinfo */
    algiddata = SecCmsSignerInfoGetDigestAlg(signerinfo);
    if (algiddata == NULL) {
        return errSecInternalError; // shouldn't have happened, this is likely due to corrupted data
    }
    
    digest = SecCmsSignedDataGetDigestByAlgTag(sigd, algiddata->offset);
	if(digest == NULL) {
		/* 
		 * No digests; this probably had detached content the caller has to 
		 * deal with. 
		 * FIXME: need some error return for this (as well as many 
		 * other places in this library).
		 */
		return errSecDataNotAvailable;
	}
    contentType = SecCmsContentInfoGetContentTypeOID(cinfo);

    /* verify signature */
    CFTypeRef timeStampPolicies=SecPolicyCreateAppleTimeStampingAndRevocationPolicies(policies);
    status = SecCmsSignerInfoVerifyWithPolicy(signerinfo, timeStampPolicies, digest, contentType);
    CFReleaseSafe(timeStampPolicies);

    /* Now verify the certificate.  We do this even if the signature failed to verify so we can
       return a trustRef to the caller for display purposes.  */
    status2 = SecCmsSignerInfoVerifyCertificate(signerinfo, keychainOrArray,
	policies, trustRef);
    dprintf("SecCmsSignedDataVerifySignerInfo: status %d status2 %d\n", (int) status, (int)status2);
    /* The error from SecCmsSignerInfoVerify() supercedes error from SecCmsSignerInfoVerifyCertificate(). */
    if (status)
	return status;

    return status2;
}
Example #2
0
/*
 * SecCmsSignerInfoVerify - verify the signature of a single SignerInfo
 *
 * Just verifies the signature. The assumption is that verification of the certificate
 * is done already.
 */
OSStatus
SecCmsSignerInfoVerify(SecCmsSignerInfoRef signerinfo, CSSM_DATA_PTR digest, CSSM_DATA_PTR contentType)
{
    return SecCmsSignerInfoVerifyWithPolicy(signerinfo,NULL, digest,contentType);
}