X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/fa7225c82381bac4432a6edf16f53b5370238d85..07691282a056c4efea71e1e505527601e8cc166b:/OSX/libsecurity_smime/lib/SecCMS.c diff --git a/OSX/libsecurity_smime/lib/SecCMS.c b/OSX/libsecurity_smime/lib/SecCMS.c index 0bf6f89f..53e74aac 100644 --- a/OSX/libsecurity_smime/lib/SecCMS.c +++ b/OSX/libsecurity_smime/lib/SecCMS.c @@ -36,6 +36,9 @@ #include #include #include +#include +#include +#include #include #include @@ -51,6 +54,13 @@ CFTypeRef kSecCMSAdditionalCerts = CFSTR("kSecCMSAdditionalCerts"); CFTypeRef kSecCMSSignedAttributes = CFSTR("kSecCMSSignedAttributes"); CFTypeRef kSecCMSSignDate = CFSTR("kSecCMSSignDate"); CFTypeRef kSecCMSAllCerts = CFSTR("kSecCMSAllCerts"); +CFTypeRef kSecCMSHashAgility = CFSTR("kSecCMSHashAgility"); +CFTypeRef kSecCMSHashAgilityV2 = CFSTR("kSecCMSHashAgilityV2"); +CFTypeRef kSecCMSExpirationDate = CFSTR("kSecCMSExpirationDate"); + +CFTypeRef kSecCMSBulkEncryptionAlgorithm = CFSTR("kSecCMSBulkEncryptionAlgorithm"); +CFTypeRef kSecCMSEncryptionAlgorithmDESCBC = CFSTR("kSecCMSEncryptionAlgorithmDESCBC"); +CFTypeRef kSecCMSEncryptionAlgorithmAESCBC = CFSTR("kSecCMSEncryptionAlgorithmAESCBC"); CFTypeRef kSecCMSSignHashAlgorithm = CFSTR("kSecCMSSignHashAlgorithm"); CFTypeRef kSecCMSHashingAlgorithmSHA1 = CFSTR("kSecCMSHashingAlgorithmSHA1"); @@ -143,6 +153,8 @@ static OSStatus SecCMSSignDataOrDigestAndAttributes(SecIdentityRef identity, if (signed_attributes) CFDictionaryApplyFunction(signed_attributes, sign_all_attributes, signerinfo); + require_noerr(SecCmsSignedDataAddSignerInfo(sigd, signerinfo), out); + SecAsn1Item input = {}; if (data) { input.Length = CFDataGetLength(data); @@ -173,6 +185,20 @@ out: return status; } +OSStatus SecCMSSignDataAndAttributes(SecIdentityRef identity, CFDataRef data, bool detached, + CFMutableDataRef signed_data, CFDictionaryRef signed_attributes) +{ + return SecCMSSignDataOrDigestAndAttributes(identity, data, detached, false, SEC_OID_SHA1, + signed_data, signed_attributes, SecCmsCMCertChain, NULL); +} + +OSStatus SecCMSSignDigestAndAttributes(SecIdentityRef identity, CFDataRef digest, + CFMutableDataRef signed_data, CFDictionaryRef signed_attributes) +{ + return SecCMSSignDataOrDigestAndAttributes(identity, digest, true, true, SEC_OID_SHA1, + signed_data, signed_attributes, SecCmsCMCertChain, NULL); +} + OSStatus SecCMSCreateSignedData(SecIdentityRef identity, CFDataRef data, CFDictionaryRef parameters, CFDictionaryRef signed_attributes, CFMutableDataRef signed_data) @@ -242,6 +268,9 @@ SecCmsSignedDataSetDigestContext(SecCmsSignedDataRef sigd, if (SecCmsSignedDataSetDigests(sigd, digestAlgorithms, digests) != SECSuccess) goto loser; + if (arena) { + PORT_FreeArena(arena, PR_FALSE); + } return 0; loser: if (arena) @@ -273,6 +302,7 @@ static OSStatus SecCMSVerifySignedData_internal(CFDataRef message, CFDataRef det SecCmsSignedDataRef sigd = NULL; OSStatus status = errSecParam; + require(message, out); SecAsn1Item encoded_message = { CFDataGetLength(message), (uint8_t*)CFDataGetBytePtr(message) }; require_noerr_action_quiet(SecCmsMessageDecode(&encoded_message, NULL, NULL, NULL, NULL, NULL, NULL, &cmsg), out, status = errSecDecode); @@ -360,6 +390,29 @@ static OSStatus SecCMSVerifySignedData_internal(CFDataRef message, CFDataRef det } } + CFDataRef hash_agility_value = NULL; + if (errSecSuccess == SecCmsSignerInfoGetAppleCodesigningHashAgility(sigd->signerInfos[0], &hash_agility_value)) { + if (hash_agility_value) { + CFDictionarySetValue(attrs, kSecCMSHashAgility, hash_agility_value); + } + } + + CFDictionaryRef hash_agility_values = NULL; + if (errSecSuccess == SecCmsSignerInfoGetAppleCodesigningHashAgilityV2(sigd->signerInfos[0], &hash_agility_values)) { + if (hash_agility_values) { + CFDictionarySetValue(attrs, kSecCMSHashAgilityV2, hash_agility_values); + } + } + + CFAbsoluteTime expiration_time; + if (errSecSuccess == SecCmsSignerInfoGetAppleExpirationTime(sigd->signerInfos[0], &expiration_time)) { + CFDateRef expiration_date = CFDateCreate(NULL, expiration_time); + if (expiration_date) { + CFDictionarySetValue(attrs, kSecCMSExpirationDate, expiration_date); + CFRetainSafe(expiration_date); + } + } + *signed_attributes = attrs; if (certs) CFRelease(certs); } @@ -406,6 +459,10 @@ CFArrayRef SecCMSCertificatesOnlyMessageCopyCertificates(CFDataRef message) { SecCmsSignedDataRef sigd = NULL; CFMutableArrayRef certs = NULL; + if (!message) { + return NULL; + } + CSSM_DATA encoded_message = { CFDataGetLength(message), (uint8_t*)CFDataGetBytePtr(message) }; require_noerr_quiet(SecCmsMessageDecode(&encoded_message, NULL, NULL, NULL, NULL, NULL, NULL, &cmsg), out); /* expected to be a signed data message at the top level */ @@ -430,8 +487,10 @@ CFArrayRef SecCMSCertificatesOnlyMessageCopyCertificates(CFDataRef message) { } out: - if (cmsg) - SecCmsMessageDestroy(cmsg); + if (cmsg) { SecCmsMessageDestroy(cmsg); } + if (certs && CFArrayGetCount(certs) < 1) { + CFReleaseNull(certs); + } return certs; } @@ -565,3 +624,110 @@ out: } return message; } + +OSStatus SecCMSCreateEnvelopedData(CFTypeRef recipient_or_cfarray_thereof, + CFDictionaryRef params, CFDataRef data, CFMutableDataRef enveloped_data) +{ + SecCmsMessageRef cmsg = NULL; + SecCmsContentInfoRef cinfo; + SecCmsEnvelopedDataRef envd = NULL; + SECOidTag algorithmTag = SEC_OID_DES_EDE3_CBC; + int keySize = 192; + OSStatus status = errSecParam; + PLArenaPool *arena = NULL; + + if (params) { + CFStringRef algorithm_name = CFDictionaryGetValue(params, kSecCMSBulkEncryptionAlgorithm); + if (algorithm_name) { + if (CFEqual(kSecCMSEncryptionAlgorithmDESCBC, algorithm_name)) { + algorithmTag = SEC_OID_DES_CBC; + keySize = 64; + } else if (CFEqual(kSecCMSEncryptionAlgorithmAESCBC, algorithm_name)) { + algorithmTag = SEC_OID_AES_128_CBC; + keySize = 128; + } + } + } + + require(cmsg = SecCmsMessageCreate(NULL), out); + require(envd = SecCmsEnvelopedDataCreate(cmsg, algorithmTag, keySize), out); + require(cinfo = SecCmsMessageGetContentInfo(cmsg), out); + require_noerr(SecCmsContentInfoSetContentEnvelopedData(cmsg, cinfo, envd), out); + require(cinfo = SecCmsEnvelopedDataGetContentInfo(envd), out); + require_noerr(SecCmsContentInfoSetContentData(cmsg, cinfo, NULL, false), out); + // == wrapper of: require(SECSuccess == SecCmsContentInfoSetContent(cinfo, SEC_OID_PKCS7_DATA, NULL), out); + + if (CFGetTypeID(recipient_or_cfarray_thereof) == CFArrayGetTypeID()) { + CFIndex dex, numCerts = CFArrayGetCount(recipient_or_cfarray_thereof); + for(dex=0; dexrecipientInfos; + while (!used_recipient && *rinfo) { + used_recipient = (*rinfo)->cert; + rinfo++; + } + require_quiet(2 == SecCmsMessageContentLevelCount(cmsg), out); + require_quiet(cinfo = SecCmsMessageContentLevel(cmsg, 1), out); + require_quiet(SecCmsContentInfoGetContentTypeTag(cinfo) == SEC_OID_PKCS7_DATA, out); + const SecAsn1Item *content = SecCmsMessageGetContent(cmsg); + if (content) + CFDataAppendBytes(data, content->Data, content->Length); + if (recipient) { + CFRetainSafe(used_recipient); + *recipient = used_recipient; + } + status = errSecSuccess; +out: + if (cmsg) SecCmsMessageDestroy(cmsg); + return status; +}