#include <Security/SecKeyPriv.h>
#include <CoreFoundation/CFTimeZone.h>
#include <utilities/SecCFWrappers.h>
+#include <utilities/debugging.h>
#include <AssertMacros.h>
#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
#include <Security/SecPolicyPriv.h>
+#include <Security/SecItem.h>
#include "tsaSupport.h"
#include "tsaSupportPriv.h"
SecCmsSignerInfoRef signerInfo = NULL;
SecCertificateRef cert = NULL;
SecPrivateKeyRef signingKey = NULL;
+ CFDictionaryRef keyAttrs = NULL;
if (SecIdentityCopyCertificate(identity, &cert))
goto loser;
if (SecIdentityCopyPrivateKey(identity, &signingKey))
goto loser;
+ /* In some situations, the "Private Key" in the identity is actually a public key. */
+ keyAttrs = SecKeyCopyAttributes(signingKey);
+ if (!keyAttrs)
+ goto loser;
+ CFTypeRef class = CFDictionaryGetValue(keyAttrs, kSecAttrKeyClass);
+ if (!class || (CFGetTypeID(class) != CFStringGetTypeID()) || !CFEqual(class, kSecAttrKeyClassPrivate))
+ goto loser;
+
+
signerInfo = nss_cmssignerinfo_create(cmsg, SecCmsSignerIDIssuerSN, cert, NULL, NULL, signingKey, digestalgtag);
loser:
CFRelease(cert);
if (signingKey)
CFRelease(signingKey);
+ if (keyAttrs)
+ CFRelease(keyAttrs);
return signerInfo;
}
if (!subjKeyID)
goto loser;
signerinfo->signerIdentifier.id.subjectKeyID = PORT_ArenaNew(poolp, CSSM_DATA);
- SECITEM_CopyItem(poolp, signerinfo->signerIdentifier.id.subjectKeyID,
- subjKeyID);
+ if (SECITEM_CopyItem(poolp, signerinfo->signerIdentifier.id.subjectKeyID,
+ subjKeyID)) {
+ goto loser;
+ }
signerinfo->pubKey = SECKEY_CopyPublicKey(pubKey);
if (!signerinfo->pubKey)
goto loser;
(int)CFGetRetainCount(si->timestampCertList));
CFRelease(si->timestampCertList);
}
+ if (si->timestampCert != NULL) {
+ dprintfRC("SecCmsSignerInfoDestroy top: timestampCert.rc %d\n",
+ (int)CFGetRetainCount(si->timestampCert));
+ CFRelease(si->timestampCert);
+ }
+ if (si->hashAgilityAttrValue != NULL) {
+ dprintfRC("SecCmsSignerInfoDestroy top: hashAgilityAttrValue.rc %d\n",
+ (int)CFGetRetainCount(si->hashAgilityAttrValue));
+ CFRelease(si->hashAgilityAttrValue);
+ }
+ if (si->hashAgilityV2AttrValues != NULL) {
+ dprintfRC("SecCmsSignerInfoDestroy top: hashAgilityV2AttrValues.rc %d\n",
+ (int)CFGetRetainCount(si->hashAgilityV2AttrValues));
+ CFRelease(si->hashAgilityV2AttrValues);
+ }
/* XXX storage ??? */
}
SECITEM_FreeItem (&signature, PR_FALSE);
if (privkey)
SECKEY_DestroyPrivateKey(privkey);
- if((algID != NULL) & (algID != &freeAlgID)) {
- /* this is dicey - this was actually mallocd by either SecCertificate or
- * by SecKey...it all boils down to a free() in the end though. */
- SECOID_DestroyAlgorithmID((SECAlgorithmID *)algID, PR_FALSE);
- }
if (tmppoolp)
PORT_FreeArena(tmppoolp, PR_FALSE);
return SECFailure;
SecCmsSignerInfoVerifyWithPolicy(SecCmsSignerInfoRef signerinfo,CFTypeRef timeStampPolicy, CSSM_DATA_PTR digest, CSSM_DATA_PTR contentType)
{
SecPublicKeyRef publickey = NULL;
- SecCmsAttribute *attr;
+ SecCmsAttribute *attr = NULL;
CSSM_DATA encoded_attrs;
- SecCertificateRef cert;
+ SecCertificateRef cert = NULL;
SecCmsVerificationStatus vs = SecCmsVSUnverified;
- PLArenaPool *poolp;
+ PLArenaPool *poolp = NULL;
SECOidTag digestAlgTag, digestEncAlgTag;
if (signerinfo == NULL)
dprintfRC("SecCmsSignerInfoVerify top: cert %p cert.rc %d\n", cert, (int)CFGetRetainCount(cert));
debugShowSigningCertificate(signerinfo);
-
- if (SecCertificateCopyPublicKey(cert, &publickey)) {
+
+ if (NULL == (publickey = SecCertificateCopyKey(cert))) {
vs = SecCmsVSProcessingError;
goto loser;
}
goto loser;
}
- SECStatus err = SECSuccess;
- vs = ((err = VFY_VerifyData (encoded_attrs.Data, (int)encoded_attrs.Length,
+ vs = (VFY_VerifyData (encoded_attrs.Data, (int)encoded_attrs.Length,
publickey, &(signerinfo->encDigest),
digestAlgTag, digestEncAlgTag,
- signerinfo->cmsg->pwfn_arg)) != SECSuccess) ? SecCmsVSBadSignature : SecCmsVSGoodSignature;
+ signerinfo->cmsg->pwfn_arg) != SECSuccess) ? SecCmsVSBadSignature : SecCmsVSGoodSignature;
dprintf("VFY_VerifyData (authenticated attributes): %s\n",
(vs == SecCmsVSGoodSignature)?"SecCmsVSGoodSignature":"SecCmsVSBadSignature");
- if (vs != SecCmsVSGoodSignature) syslog(LOG_ERR, "VFY_VerifyData (authenticated attributes) failed: %d", err);
PORT_FreeArena(poolp, PR_FALSE); /* awkward memory management :-( */
if (sig->Length == 0)
goto loser;
- SECStatus err = SECSuccess;
- vs = ((err = VFY_VerifyDigest(digest, publickey, sig,
+ vs = (VFY_VerifyDigest(digest, publickey, sig,
digestAlgTag, digestEncAlgTag,
- signerinfo->cmsg->pwfn_arg)) != SECSuccess) ? SecCmsVSBadSignature : SecCmsVSGoodSignature;
+ signerinfo->cmsg->pwfn_arg) != SECSuccess) ? SecCmsVSBadSignature : SecCmsVSGoodSignature;
dprintf("VFY_VerifyData (plain message digest): %s\n",
(vs == SecCmsVSGoodSignature)?"SecCmsVSGoodSignature":"SecCmsVSBadSignature");
- if (vs != SecCmsVSGoodSignature) syslog(LOG_ERR, "VFY_VerifyDigest (plain message digest) failed: %d", err);
}
if (!SecCmsArrayIsEmpty((void **)signerinfo->unAuthAttr))
OSStatus rux = SecCmsSignerInfoVerifyUnAuthAttrsWithPolicy(signerinfo,timeStampPolicy);
dprintf("SecCmsSignerInfoVerifyUnAuthAttrs Status: %ld\n", (long)rux);
if (rux) {
- syslog(LOG_ERR, "SecCmsSignerInfoVerifyUnAuthAttrsWithPolicy failed: %d", (int)rux);
goto loser;
}
}
* certificate signature check that failed during the cert
* verification done above. Our error handling is really a mess.
*/
- syslog(LOG_ERR, "SecCmsSignerInforVerify bad signature PORT_GetError: %d", PORT_GetError());
if (PORT_GetError() == SEC_ERROR_BAD_SIGNATURE)
PORT_SetError(SEC_ERROR_PKCS7_BAD_SIGNATURE);
}
dprintf("found an id-ct-TSTInfo\n");
// Don't check the nonce in this case
status = decodeTimeStampTokenWithPolicy(signerinfo, timeStampPolicy, (attr->values)[0], &signerinfo->encDigest, 0);
+ if (status != errSecSuccess) {
+ secerror("timestamp verification failed: %d", (int)status);
+ }
+
xit:
return status;
}
CFArrayRef
SecCmsSignerInfoGetTimestampCertList(SecCmsSignerInfoRef signerinfo)
{
- dprintfRC("SecCmsSignerInfoGetCertList: timestampCertList.rc %d\n",
+ dprintfRC("SecCmsSignerInfoGetTimestampCertList: timestampCertList.rc %d\n",
(int)CFGetRetainCount(signerinfo->timestampCertList));
return signerinfo->timestampCertList;
}
-
+SecCertificateRef
+SecCmsSignerInfoGetTimestampSigningCert(SecCmsSignerInfoRef signerinfo)
+{
+ dprintfRC("SecCmsSignerInfoGetTimestampSigningCert: timestampCert.rc %d\n",
+ (int)CFGetRetainCount(signerinfo->timestampCert));
+ return signerinfo->timestampCert;
+}
int
SecCmsSignerInfoGetVersion(SecCmsSignerInfoRef signerinfo)
return status;
}
+/*!
+ @function
+ @abstract Return the data in the signed Codesigning Hash Agility attribute.
+ @param sinfo SignerInfo data for this signer, pointer to a CFDataRef for attribute value
+ @discussion Returns a CFDataRef containing the value of the attribute
+ @result A return value of errSecInternal is an error trying to look up the oid.
+ A status value of success with null result data indicates the attribute was not present.
+ */
+OSStatus
+SecCmsSignerInfoGetAppleCodesigningHashAgility(SecCmsSignerInfoRef sinfo, CFDataRef *sdata)
+{
+ SecCmsAttribute *attr;
+ CSSM_DATA_PTR value;
+
+ if (sinfo == NULL || sdata == NULL)
+ return paramErr;
+
+ *sdata = NULL;
+
+ if (sinfo->hashAgilityAttrValue != NULL) {
+ *sdata = sinfo->hashAgilityAttrValue; /* cached copy */
+ return SECSuccess;
+ }
+
+ attr = SecCmsAttributeArrayFindAttrByOidTag(sinfo->authAttr, SEC_OID_APPLE_HASH_AGILITY, PR_TRUE);
+
+ /* attribute not found */
+ if (attr == NULL || (value = SecCmsAttributeGetValue(attr)) == NULL)
+ return SECSuccess;
+
+ sinfo->hashAgilityAttrValue = CFDataCreate(NULL, value->Data, value->Length); /* make cached copy */
+ if (sinfo->hashAgilityAttrValue) {
+ *sdata = sinfo->hashAgilityAttrValue;
+ return SECSuccess;
+ }
+ return errSecAllocate;
+}
+
+/* AgileHash ::= SEQUENCE {
+ hashType OBJECT IDENTIFIER,
+ hashValues OCTET STRING }
+ */
+typedef struct {
+ SecAsn1Item digestOID;
+ SecAsn1Item digestValue;
+} CMSAppleAgileHash;
+
+static const SecAsn1Template CMSAppleAgileHashTemplate[] = {
+ { SEC_ASN1_SEQUENCE,
+ 0, NULL, sizeof(CMSAppleAgileHash) },
+ { SEC_ASN1_OBJECT_ID,
+ offsetof(CMSAppleAgileHash, digestOID), },
+ { SEC_ASN1_OCTET_STRING,
+ offsetof(CMSAppleAgileHash, digestValue), },
+ { 0, }
+};
+
+static OSStatus CMSAddAgileHashToDictionary(CFMutableDictionaryRef dictionary, SecAsn1Item *DERAgileHash) {
+ PLArenaPool *tmppoolp = NULL;
+ OSStatus status = errSecSuccess;
+ CMSAppleAgileHash agileHash;
+ CFDataRef digestValue = NULL;
+ CFNumberRef digestTag = NULL;
+
+ tmppoolp = PORT_NewArena(1024);
+ if (tmppoolp == NULL) {
+ return errSecAllocate;
+ }
+
+ if ((status = SEC_ASN1DecodeItem(tmppoolp, &agileHash, CMSAppleAgileHashTemplate, DERAgileHash)) != errSecSuccess) {
+ goto loser;
+ }
+
+ int64_t tag = SECOID_FindOIDTag(&agileHash.digestOID);
+ digestTag = CFNumberCreate(NULL, kCFNumberSInt64Type, &tag);
+ digestValue = CFDataCreate(NULL, agileHash.digestValue.Data, agileHash.digestValue.Length);
+ CFDictionaryAddValue(dictionary, digestTag, digestValue);
+
+loser:
+ CFReleaseNull(digestValue);
+ CFReleaseNull(digestTag);
+ if (tmppoolp) {
+ PORT_FreeArena(tmppoolp, PR_FALSE);
+ }
+ return status;
+}
+
+/*!
+ @function
+ @abstract Return the data in the signed Codesigning Hash Agility V2 attribute.
+ @param sinfo SignerInfo data for this signer, pointer to a CFDictionaryRef for attribute values
+ @discussion Returns a CFDictionaryRef containing the values of the attribute
+ @result A return value of errSecInternal is an error trying to look up the oid.
+ A status value of success with null result data indicates the attribute was not present.
+ */
+OSStatus
+SecCmsSignerInfoGetAppleCodesigningHashAgilityV2(SecCmsSignerInfoRef sinfo, CFDictionaryRef *sdict)
+{
+ SecCmsAttribute *attr;
+
+ if (sinfo == NULL || sdict == NULL) {
+ return errSecParam;
+ }
+
+ *sdict = NULL;
+
+ if (sinfo->hashAgilityV2AttrValues != NULL) {
+ *sdict = sinfo->hashAgilityV2AttrValues; /* cached copy */
+ return SECSuccess;
+ }
+
+ attr = SecCmsAttributeArrayFindAttrByOidTag(sinfo->authAttr, SEC_OID_APPLE_HASH_AGILITY_V2, PR_TRUE);
+
+ /* attribute not found */
+ if (attr == NULL) {
+ return SECSuccess;
+ }
+
+ /* attrValues SET OF AttributeValue
+ * AttributeValue ::= ANY
+ */
+ CSSM_DATA_PTR *values = attr->values;
+ if (values == NULL) { /* There must be values */
+ return errSecDecode;
+ }
+
+ CFMutableDictionaryRef agileHashValues = CFDictionaryCreateMutable(NULL, SecCmsArrayCount((void **)values),
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ while (*values != NULL) {
+ (void)CMSAddAgileHashToDictionary(agileHashValues, *values++);
+ }
+ if (CFDictionaryGetCount(agileHashValues) != SecCmsArrayCount((void **)attr->values)) {
+ CFReleaseNull(agileHashValues);
+ return errSecDecode;
+ }
+
+ sinfo->hashAgilityV2AttrValues = agileHashValues; /* make cached copy */
+ if (sinfo->hashAgilityV2AttrValues) {
+ *sdict = sinfo->hashAgilityV2AttrValues;
+ return SECSuccess;
+ }
+ return errSecAllocate;
+}
+
+/*
+ * SecCmsSignerInfoGetAppleExpirationTime - return the expiration time,
+ * in UTCTime format, of a CMS signerInfo.
+ *
+ * sinfo - signerInfo data for this signer
+ *
+ * Returns a pointer to XXXX (what?)
+ * A return value of NULL is an error.
+ */
+OSStatus
+SecCmsSignerInfoGetAppleExpirationTime(SecCmsSignerInfoRef sinfo, CFAbsoluteTime *etime)
+{
+ SecCmsAttribute *attr = NULL;
+ SecAsn1Item * value = NULL;
+
+ if (sinfo == NULL || etime == NULL) {
+ return SECFailure;
+ }
+
+ if (sinfo->expirationTime != 0) {
+ *etime = sinfo->expirationTime; /* cached copy */
+ return SECSuccess;
+ }
+
+ attr = SecCmsAttributeArrayFindAttrByOidTag(sinfo->authAttr, SEC_OID_APPLE_EXPIRATION_TIME, PR_TRUE);
+ if (attr == NULL || (value = SecCmsAttributeGetValue(attr)) == NULL) {
+ return SECFailure;
+ }
+ if (DER_UTCTimeToCFDate(value, etime) != SECSuccess) {
+ return SECFailure;
+ }
+ sinfo->expirationTime = *etime; /* make cached copy */
+ return SECSuccess;
+}
+
/*
* Return the signing cert of a CMS signerInfo.
*
sid = &signerinfo->signerIdentifier;
switch (sid->identifierType) {
case SecCmsSignerIDIssuerSN:
- cert = CERT_FindCertByIssuerAndSN(keychainOrArray, rawCerts, signerinfo->cmsg->poolp,
+ cert = CERT_FindCertByIssuerAndSN(keychainOrArray, rawCerts, signerinfo->sigd->certs, signerinfo->cmsg->poolp,
sid->id.issuerAndSN);
break;
case SecCmsSignerIDSubjectKeyID:
- cert = CERT_FindCertBySubjectKeyID(keychainOrArray, rawCerts, sid->id.subjectKeyID);
+ cert = CERT_FindCertBySubjectKeyID(keychainOrArray, rawCerts, signerinfo->sigd->certs, sid->id.subjectKeyID);
break;
default:
cert = NULL;
if ((signercert = SecCmsSignerInfoGetSigningCertificate(sinfo, NULL)) == NULL)
return NULL;
- SecCertificateCopyCommonName(signercert, &commonName);
+ if (errSecSuccess != SecCertificateCopyCommonName(signercert, &commonName)) {
+ return NULL;
+ }
return commonName;
}
/*
* SecCmsSignerInfoAddMSSMIMEEncKeyPrefs - add a SMIMEEncryptionKeyPreferences attribute to the
- * authenticated (i.e. signed) attributes of "signerinfo", using the OID prefered by Microsoft.
+ * authenticated (i.e. signed) attributes of "signerinfo", using the OID preferred by Microsoft.
*
* This is expected to be included in outgoing signed messages for email (S/MIME),
* if compatibility with Microsoft mail clients is wanted.
return SECFailure;
}
+/*!
+ @function
+ @abstract Add the Apple Codesigning Hash Agility attribute to the authenticated (i.e. signed) attributes of "signerinfo".
+ @discussion This is expected to be included in outgoing Apple code signatures.
+ */
+OSStatus
+SecCmsSignerInfoAddAppleCodesigningHashAgility(SecCmsSignerInfoRef signerinfo, CFDataRef attrValue)
+{
+ SecCmsAttribute *attr;
+ PLArenaPool *poolp = signerinfo->cmsg->poolp;
+ void *mark = PORT_ArenaMark(poolp);
+ OSStatus status = SECFailure;
+
+ /* The value is required for this attribute. */
+ if (!attrValue) {
+ status = errSecParam;
+ goto loser;
+ }
+
+ /*
+ * SecCmsAttributeCreate makes a copy of the data in value, so
+ * we don't need to copy into the CSSM_DATA struct.
+ */
+ CSSM_DATA value;
+ value.Length = CFDataGetLength(attrValue);
+ value.Data = (uint8_t *)CFDataGetBytePtr(attrValue);
+
+ if ((attr = SecCmsAttributeCreate(poolp,
+ SEC_OID_APPLE_HASH_AGILITY,
+ &value,
+ PR_FALSE)) == NULL) {
+ status = errSecAllocate;
+ goto loser;
+ }
+
+ if (SecCmsSignerInfoAddAuthAttr(signerinfo, attr) != SECSuccess) {
+ status = errSecInternalError;
+ goto loser;
+ }
+
+ PORT_ArenaUnmark(poolp, mark);
+ return SECSuccess;
+
+loser:
+ PORT_ArenaRelease(poolp, mark);
+ return status;
+}
+
+static OSStatus CMSAddAgileHashToAttribute(PLArenaPool *poolp, SecCmsAttribute *attr, CFNumberRef cftag, CFDataRef value) {
+ PLArenaPool *tmppoolp = NULL;
+ int64_t tag;
+ SECOidData *digestOid = NULL;
+ CMSAppleAgileHash agileHash;
+ SecAsn1Item attrValue = { .Data = NULL, .Length = 0 };
+ OSStatus status = errSecSuccess;
+
+ memset(&agileHash, 0, sizeof(agileHash));
+
+ if(!CFNumberGetValue(cftag, kCFNumberSInt64Type, &tag)) {
+ return errSecParam;
+ }
+ digestOid = SECOID_FindOIDByTag((SECOidTag)tag);
+
+ agileHash.digestValue.Data = (uint8_t *)CFDataGetBytePtr(value);
+ agileHash.digestValue.Length = CFDataGetLength(value);
+ agileHash.digestOID.Data = digestOid->oid.Data;
+ agileHash.digestOID.Length = digestOid->oid.Length;
+
+ tmppoolp = PORT_NewArena(1024);
+ if (tmppoolp == NULL) {
+ return errSecAllocate;
+ }
+
+ if (SEC_ASN1EncodeItem(tmppoolp, &attrValue, &agileHash, CMSAppleAgileHashTemplate) == NULL) {
+ status = errSecParam;
+ goto loser;
+ }
+
+ status = SecCmsAttributeAddValue(poolp, attr, &attrValue);
+
+loser:
+ if (tmppoolp) {
+ PORT_FreeArena(tmppoolp, PR_FALSE);
+ }
+ return status;
+}
+
+/*!
+ @function
+ @abstract Add the Apple Codesigning Hash Agility attribute to the authenticated (i.e. signed) attributes of "signerinfo".
+ @discussion This is expected to be included in outgoing Apple code signatures.
+ */
+OSStatus
+SecCmsSignerInfoAddAppleCodesigningHashAgilityV2(SecCmsSignerInfoRef signerinfo, CFDictionaryRef attrValues)
+{
+ __block SecCmsAttribute *attr;
+ __block PLArenaPool *poolp = signerinfo->cmsg->poolp;
+ void *mark = PORT_ArenaMark(poolp);
+ OSStatus status = SECFailure;
+
+ /* The value is required for this attribute. */
+ if (!attrValues) {
+ status = errSecParam;
+ goto loser;
+ }
+
+ if ((attr = SecCmsAttributeCreate(poolp, SEC_OID_APPLE_HASH_AGILITY_V2,
+ NULL, PR_TRUE)) == NULL) {
+ status = errSecAllocate;
+ goto loser;
+ }
+
+ CFDictionaryForEach(attrValues, ^(const void *key, const void *value) {
+ if (!isNumber(key) || !isData(value)) {
+ return;
+ }
+ (void)CMSAddAgileHashToAttribute(poolp, attr, (CFNumberRef)key, (CFDataRef)value);
+ });
+
+ if (SecCmsSignerInfoAddAuthAttr(signerinfo, attr) != SECSuccess) {
+ status = errSecInternal;
+ goto loser;
+ }
+
+ PORT_ArenaUnmark(poolp, mark);
+ return SECSuccess;
+
+loser:
+ PORT_ArenaRelease(poolp, mark);
+ return status;
+}
+
+/*
+ * SecCmsSignerInfoAddAppleExpirationTime - add the expiration time to the
+ * authenticated (i.e. signed) attributes of "signerinfo".
+ *
+ * This is expected to be included in outgoing signed
+ * messages for Asset Receipts but is likely useful in other situations.
+ *
+ * This should only be added once; a second call will do nothing.
+ */
+OSStatus
+SecCmsSignerInfoAddAppleExpirationTime(SecCmsSignerInfoRef signerinfo, CFAbsoluteTime t)
+{
+ SecCmsAttribute *attr = NULL;
+ PLArenaPool *poolp = signerinfo->cmsg->poolp;
+ void *mark = PORT_ArenaMark(poolp);
+
+ /* create new expiration time attribute */
+ SecAsn1Item etime;
+ if (DER_CFDateToUTCTime(t, &etime) != SECSuccess) {
+ goto loser;
+ }
+
+ if ((attr = SecCmsAttributeCreate(poolp, SEC_OID_APPLE_EXPIRATION_TIME, &etime, PR_FALSE)) == NULL) {
+ SECITEM_FreeItem (&etime, PR_FALSE);
+ goto loser;
+ }
+
+ SECITEM_FreeItem(&etime, PR_FALSE);
+
+ if (SecCmsSignerInfoAddAuthAttr(signerinfo, attr) != SECSuccess) {
+ goto loser;
+ }
+
+ PORT_ArenaUnmark(poolp, mark);
+ return SECSuccess;
+
+loser:
+ PORT_ArenaRelease(poolp, mark);
+ return SECFailure;
+}
+
+SecCertificateRef SecCmsSignerInfoCopyCertFromEncryptionKeyPreference(SecCmsSignerInfoRef signerinfo) {
+ SecCertificateRef cert = NULL;
+ SecCmsAttribute *attr;
+ CSSM_DATA_PTR ekp;
+ SecKeychainRef keychainOrArray;
+
+ (void)SecKeychainCopyDefault(&keychainOrArray);
+
+ /* sanity check - see if verification status is ok (unverified does not count...) */
+ if (signerinfo->verificationStatus != SecCmsVSGoodSignature)
+ return NULL;
+
+ /* Prep the raw certs */
+ CSSM_DATA_PTR *rawCerts = NULL;
+ if (signerinfo->sigd) {
+ rawCerts = signerinfo->sigd->rawCerts;
+ }
+
+ /* find preferred encryption cert */
+ if (!SecCmsArrayIsEmpty((void **)signerinfo->authAttr) &&
+ (attr = SecCmsAttributeArrayFindAttrByOidTag(signerinfo->authAttr,
+ SEC_OID_SMIME_ENCRYPTION_KEY_PREFERENCE, PR_TRUE)) != NULL)
+ { /* we have a SMIME_ENCRYPTION_KEY_PREFERENCE attribute! Find the cert. */
+ ekp = SecCmsAttributeGetValue(attr);
+ if (ekp == NULL)
+ return NULL;
+ cert = SecSMIMEGetCertFromEncryptionKeyPreference(keychainOrArray, rawCerts, ekp);
+ }
+ if(cert) return cert;
+
+ if (!SecCmsArrayIsEmpty((void **)signerinfo->authAttr) &&
+ (attr = SecCmsAttributeArrayFindAttrByOidTag(signerinfo->authAttr,
+ SEC_OID_MS_SMIME_ENCRYPTION_KEY_PREFERENCE, PR_TRUE)) != NULL)
+ { /* we have a MS_SMIME_ENCRYPTION_KEY_PREFERENCE attribute! Find the cert. */
+ ekp = SecCmsAttributeGetValue(attr);
+ if (ekp == NULL)
+ return NULL;
+ cert = SecSMIMEGetCertFromEncryptionKeyPreference(keychainOrArray, rawCerts, ekp);
+ }
+ return cert;
+}
+
/*
* XXXX the following needs to be done in the S/MIME layer code
* after signature of a signerinfo is verified
/* we assume that all certs coming with the message have been imported to the */
/* temporary database */
- cert = SecSMIMEGetCertFromEncryptionKeyPreference(keychainOrArray, ekp);
+ cert = SecSMIMEGetCertFromEncryptionKeyPreference(keychainOrArray, NULL, ekp);
if (cert == NULL)
return SECFailure;
must_free_cert = PR_TRUE;