X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/866f8763175ff60e4fa455b92b5eb660a12fe6c7..07691282a056c4efea71e1e505527601e8cc166b:/OSX/libsecurity_smime/lib/cmssiginfo.c diff --git a/OSX/libsecurity_smime/lib/cmssiginfo.c b/OSX/libsecurity_smime/lib/cmssiginfo.c index ac389d3c..3c1ff754 100644 --- a/OSX/libsecurity_smime/lib/cmssiginfo.c +++ b/OSX/libsecurity_smime/lib/cmssiginfo.c @@ -53,6 +53,7 @@ #include #include #include +#include #include #include #include @@ -338,11 +339,21 @@ SecCmsSignerInfoDestroy(SecCmsSignerInfoRef si) (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 ??? */ } @@ -623,9 +634,7 @@ SecCmsSignerInfoVerifyWithPolicy(SecCmsSignerInfoRef signerinfo,CFTypeRef timeSt debugShowSigningCertificate(signerinfo); - OSStatus status; - if ((status = SecCertificateCopyPublicKey(cert, &publickey))) { - syslog(LOG_ERR, "SecCmsSignerInfoVerifyWithPolicy: copy public key failed %d", (int)status); + if (NULL == (publickey = SecCertificateCopyKey(cert))) { vs = SecCmsVSProcessingError; goto loser; } @@ -811,6 +820,10 @@ SecCmsSignerInfoVerifyUnAuthAttrsWithPolicy(SecCmsSignerInfoRef signerinfo,CFTyp 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; } @@ -856,12 +869,18 @@ SecCmsSignerInfoGetCertList(SecCmsSignerInfoRef signerinfo) 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) @@ -972,6 +991,148 @@ SecCmsSignerInfoGetAppleCodesigningHashAgility(SecCmsSignerInfoRef sinfo, CFData 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. * @@ -1241,7 +1402,7 @@ loser: /* * 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. @@ -1369,7 +1530,7 @@ SecCmsSignerInfoAddCounterSignature(SecCmsSignerInfoRef signerinfo, /*! @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 signed Apple code signatures. + @discussion This is expected to be included in outgoing Apple code signatures. */ OSStatus SecCmsSignerInfoAddAppleCodesigningHashAgility(SecCmsSignerInfoRef signerinfo, CFDataRef attrValue) @@ -1414,6 +1575,131 @@ loser: 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; @@ -1426,6 +1712,12 @@ SecCertificateRef SecCmsSignerInfoCopyCertFromEncryptionKeyPreference(SecCmsSign 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, @@ -1434,11 +1726,17 @@ SecCertificateRef SecCmsSignerInfoCopyCertFromEncryptionKeyPreference(SecCmsSign ekp = SecCmsAttributeGetValue(attr); if (ekp == NULL) return NULL; + cert = SecSMIMEGetCertFromEncryptionKeyPreference(keychainOrArray, rawCerts, ekp); + } + if(cert) return cert; - CSSM_DATA_PTR *rawCerts = NULL; - if (signerinfo->sigd) { - rawCerts = signerinfo->sigd->rawCerts; - } + 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;