X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/e0e0d90ebff497686991a933ae2f7db24e7d8e0f..7e6b461318c8a779d91381531435a68ee4e8b6ed:/OSX/libsecurity_cms/lib/CMSDecoder.cpp?ds=inline diff --git a/OSX/libsecurity_cms/lib/CMSDecoder.cpp b/OSX/libsecurity_cms/lib/CMSDecoder.cpp index a420e5eb..9fe2ecb9 100644 --- a/OSX/libsecurity_cms/lib/CMSDecoder.cpp +++ b/OSX/libsecurity_cms/lib/CMSDecoder.cpp @@ -25,8 +25,8 @@ * CMSDecoder.cpp - Interface for decoding CMS messages. */ -#include "CMSDecoder.h" -#include "CMSPrivate.h" +#include +#include #include "CMSUtils.h" #include <../libsecurity_codesigning/lib/csutilities.h> @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -66,7 +67,7 @@ struct _CMSDecoder { SecArenaPoolRef arena; /* the decoder's arena */ SecCmsDecoderRef decoder; CFDataRef detachedContent; - CFTypeRef keychainOrArray; /* from CMSDecoderSetSearchKeychain() */ + CFTypeRef keychainOrArray; /* unused */ /* * The following are valid (and quiescent) after CMSDecoderFinalizeMessage(). @@ -127,19 +128,20 @@ static void cmsDecoderFinalize( if(cmsDecoder->decoder != NULL) { /* * Normally this gets freed in SecCmsDecoderFinish - this is - * an error case. - * FIXME: SecCmsDecoderDestroy() appears to destroy the - * cmsMsg too! Plus there's a comment there re: a leak... + * an error case. Unlike Finish, this calls SecCmsMessageDestroy. */ SecCmsDecoderDestroy(cmsDecoder->decoder); + cmsDecoder->cmsMsg = NULL; } CFRELEASE(cmsDecoder->detachedContent); CFRELEASE(cmsDecoder->keychainOrArray); if(cmsDecoder->cmsMsg != NULL) { SecCmsMessageDestroy(cmsDecoder->cmsMsg); + cmsDecoder->cmsMsg = NULL; } if(cmsDecoder->arena != NULL) { SecArenaPoolFree(cmsDecoder->arena, false); + cmsDecoder->arena = NULL; } } @@ -310,7 +312,9 @@ OSStatus CMSDecoderFinalizeMessage( (SecCmsSignedDataRef)SecCmsContentInfoGetContent(ci); /* dig down one more layer for eContentType */ ci = SecCmsSignedDataGetContentInfo(cmsDecoder->signedData); - cmsDecoder->eContentType = SecCmsContentInfoGetContentTypeOID(ci); + if (ci) { + cmsDecoder->eContentType = SecCmsContentInfoGetContentTypeOID(ci); + } break; default: break; @@ -382,24 +386,14 @@ OSStatus CMSDecoderCopyDetachedContent( } /* - * Optionally specify a SecKeychainRef, or an array of them, containing - * intermediate certs to be used in verifying a signed message's signer - * certs. By default, the default keychain search list is used for this. - * Specify an empty CFArrayRef to search *no* keychains for intermediate - * certs. - * IF this is called, it must be called before CMSDecoderCopySignerStatus(). + * Beginning in 10.12, this function stopped affecting the behavior of the + * CMS Decoder. Its only use was in SecTrustSetKeychains which is a no-op. + * Please discontinue use. */ OSStatus CMSDecoderSetSearchKeychain( CMSDecoderRef cmsDecoder, CFTypeRef keychainOrArray) { - if(cmsDecoder == NULL) { - return errSecParam; - } - cmsDecoder->keychainOrArray = keychainOrArray; - if(keychainOrArray) { - CFRetain(keychainOrArray); - } return errSecSuccess; } @@ -435,7 +429,7 @@ OSStatus CMSDecoderCopySignerStatus( SecTrustRef *secTrust, /* optional; RETURNED */ OSStatus *certVerifyResultCode) /* optional; RETURNED */ { - if((cmsDecoder == NULL) || (cmsDecoder->decState != DS_Final) || (!policyOrArray)) { + if((cmsDecoder == NULL) || (cmsDecoder->decState != DS_Final) || (!policyOrArray) || !signerStatus) { return errSecParam; } @@ -473,11 +467,7 @@ OSStatus CMSDecoderCopySignerStatus( SecTrustRef theTrust = NULL; OSStatus vfyRtn = SecCmsSignedDataVerifySignerInfo(cmsDecoder->signedData, (int)signerIndex, - /* - * FIXME this cast should not be necessary, but libsecurity_smime - * declares this argument as a SecKeychainRef - */ - (SecKeychainRef)cmsDecoder->keychainOrArray, + NULL, policyOrArray, &theTrust); @@ -505,8 +495,7 @@ OSStatus CMSDecoderCopySignerStatus( if(secTrust != NULL) { *secTrust = theTrust; /* we'll release our reference at the end */ - if (theTrust) - CFRetain(theTrust); + CFRetainSafe(theTrust); } SecCmsSignerInfoRef signerInfo = SecCmsSignedDataGetSignerInfo(cmsDecoder->signedData, (int)signerIndex); @@ -537,10 +526,6 @@ OSStatus CMSDecoderCopySignerStatus( case kSecTrustResultDeny: tpVfyStatus = CSSMERR_APPLETP_TRUST_SETTING_DENY; break; - case kSecTrustResultConfirm: - dprintf("SecTrustEvaluate reported confirm\n"); - tpVfyStatus = CSSMERR_TP_NOT_TRUSTED; - break; default: { /* get low-level TP error */ @@ -999,3 +984,132 @@ OSStatus CMSDecoderCopySignerTimestampCertificates( xit: return status; } + +/* + * Obtain the Hash Agility attribute value of signer 'signerIndex' + * of a CMS message, if present. + * + * Returns errSecParam if the CMS message was not signed or if signerIndex + * is greater than the number of signers of the message minus one. + * + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + */ +OSStatus CMSDecoderCopySignerAppleCodesigningHashAgility( + CMSDecoderRef cmsDecoder, + size_t signerIndex, /* usually 0 */ + CFDataRef CF_RETURNS_RETAINED *hashAgilityAttrValue) /* RETURNED */ +{ + OSStatus status = errSecParam; + SecCmsMessageRef cmsg; + SecCmsSignedDataRef signedData = NULL; + int numContentInfos = 0; + CFDataRef returnedValue = NULL; + + require(cmsDecoder && hashAgilityAttrValue, exit); + require_noerr(CMSDecoderGetCmsMessage(cmsDecoder, &cmsg), exit); + numContentInfos = SecCmsMessageContentLevelCount(cmsg); + for (int dex = 0; !signedData && dex < numContentInfos; dex++) + { + SecCmsContentInfoRef ci = SecCmsMessageContentLevel(cmsg, dex); + SECOidTag tag = SecCmsContentInfoGetContentTypeTag(ci); + if (tag == SEC_OID_PKCS7_SIGNED_DATA) + if ((signedData = SecCmsSignedDataRef(SecCmsContentInfoGetContent(ci)))) + if (SecCmsSignerInfoRef signerInfo = SecCmsSignedDataGetSignerInfo(signedData, (int)signerIndex)) + { + status = SecCmsSignerInfoGetAppleCodesigningHashAgility(signerInfo, &returnedValue); + break; + } + } +exit: + if (status == errSecSuccess && returnedValue) { + *hashAgilityAttrValue = (CFDataRef) CFRetain(returnedValue); + } else { + *hashAgilityAttrValue = NULL; + } + return status; +} + +/* + * Obtain the Hash Agility V2 attribute value of signer 'signerIndex' + * of a CMS message, if present. + * + * Returns errSecParam if the CMS message was not signed or if signerIndex + * is greater than the number of signers of the message minus one. + * + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + */ +OSStatus CMSDecoderCopySignerAppleCodesigningHashAgilityV2( + CMSDecoderRef cmsDecoder, + size_t signerIndex, /* usually 0 */ + CFDictionaryRef CF_RETURNS_RETAINED *hashAgilityV2AttrValues) /* RETURNED */ +{ + OSStatus status = errSecParam; + SecCmsMessageRef cmsg; + SecCmsSignedDataRef signedData = NULL; + int numContentInfos = 0; + CFDictionaryRef returnedValue = NULL; + + require(cmsDecoder && hashAgilityV2AttrValues, exit); + require_noerr(CMSDecoderGetCmsMessage(cmsDecoder, &cmsg), exit); + numContentInfos = SecCmsMessageContentLevelCount(cmsg); + for (int dex = 0; !signedData && dex < numContentInfos; dex++) + { + SecCmsContentInfoRef ci = SecCmsMessageContentLevel(cmsg, dex); + SECOidTag tag = SecCmsContentInfoGetContentTypeTag(ci); + if (tag == SEC_OID_PKCS7_SIGNED_DATA) + if ((signedData = (SecCmsSignedDataRef)SecCmsContentInfoGetContent(ci))) { + SecCmsSignerInfoRef signerInfo = SecCmsSignedDataGetSignerInfo(signedData, (int)signerIndex); + if (signerInfo) + { + status = SecCmsSignerInfoGetAppleCodesigningHashAgilityV2(signerInfo, &returnedValue); + break; + } + } + } +exit: + if (status == errSecSuccess && returnedValue) { + *hashAgilityV2AttrValues = (CFDictionaryRef) CFRetain(returnedValue); + } else { + *hashAgilityV2AttrValues = NULL; + } + return status; +} + +/* + * Obtain the expiration time of signer 'signerIndex' of a CMS message, if + * present. This is part of the signed attributes of the message. + * + * Returns errSecParam if the CMS message was not signed or if signerIndex + * is greater than the number of signers of the message minus one. + * + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + */ +OSStatus CMSDecoderCopySignerAppleExpirationTime( + CMSDecoderRef cmsDecoder, + size_t signerIndex, + CFAbsoluteTime *expirationTime) /* RETURNED */ +{ + OSStatus status = errSecParam; + SecCmsMessageRef cmsg = NULL; + int numContentInfos = 0; + SecCmsSignedDataRef signedData = NULL; + + require(cmsDecoder && expirationTime, xit); + require_noerr(CMSDecoderGetCmsMessage(cmsDecoder, &cmsg), xit); + numContentInfos = SecCmsMessageContentLevelCount(cmsg); + for (int dex = 0; !signedData && dex < numContentInfos; dex++) { + SecCmsContentInfoRef ci = SecCmsMessageContentLevel(cmsg, dex); + SECOidTag tag = SecCmsContentInfoGetContentTypeTag(ci); + if (tag == SEC_OID_PKCS7_SIGNED_DATA) { + if ((signedData = (SecCmsSignedDataRef)SecCmsContentInfoGetContent(ci))) { + SecCmsSignerInfoRef signerInfo = SecCmsSignedDataGetSignerInfo(signedData, (int)signerIndex); + if (signerInfo) { + status = SecCmsSignerInfoGetAppleExpirationTime(signerInfo, expirationTime); + break; + } + } + } + } +xit: + return status; +}