#include <Security/CMSDecoder.h>
#include <Security/CMSPrivate.h>
#include "CMSUtils.h"
#include <Security/SecCmsDecoder.h>
#include <Security/SecCmsEnvelopedData.h>
#include <Security/SecCmsMessage.h>
#include <Security/SecCmsSignedData.h>
#include <Security/SecCmsSignerInfo.h>
#include <Security/SecCmsContentInfo.h>
#include <Security/SecCmsDigestContext.h>
#include <Security/SecCertificate.h>
#include <Security/SecCertificatePriv.h>
#include <Security/SecSMIME.h>
#include <Security/oidsattr.h>
#include <Security/SecTrustPriv.h>
#include <utilities/SecAppleAnchorPriv.h>
#include <utilities/SecCFWrappers.h>
#include <CoreFoundation/CFRuntime.h>
#include <pthread.h>
#include <syslog.h>
#include <AssertMacros.h>
#pragma mark --- Private types and definitions ---
typedef enum {
DS_Init,
DS_Updating,
DS_Final
} CMSDecoderState;
struct _CMSDecoder {
CFRuntimeBase base;
CMSDecoderState decState;
SecCmsDecoderRef decoder;
CFDataRef detachedContent;
SecCmsMessageRef cmsMsg;
Boolean wasEncrypted;
SecCmsSignedDataRef signedData;
size_t numSigners;
SecAsn1Oid *eContentType;
};
static void cmsDecoderInit(CFTypeRef dec);
static void cmsDecoderFinalize(CFTypeRef dec);
static CFRuntimeClass cmsDecoderRuntimeClass =
{
0,
"CMSDecoder",
cmsDecoderInit,
NULL,
cmsDecoderFinalize,
NULL,
NULL,
NULL,
NULL
};
#pragma mark --- Private Routines ---
static CFTypeID cmsDecoderTypeID = _kCFRuntimeNotATypeID;
static void cmsDecoderClassInitialize(void)
{
cmsDecoderTypeID =
_CFRuntimeRegisterClass((const CFRuntimeClass * const)&cmsDecoderRuntimeClass);
}
static void cmsDecoderInit(CFTypeRef dec)
{
char *start = ((char *)dec) + sizeof(CFRuntimeBase);
memset(start, 0, sizeof(struct _CMSDecoder) - sizeof(CFRuntimeBase));
}
static void cmsDecoderFinalize(
CFTypeRef dec)
{
CMSDecoderRef cmsDecoder = (CMSDecoderRef)dec;
if(cmsDecoder == NULL) {
return;
}
if(cmsDecoder->decoder != NULL) {
SecCmsDecoderDestroy(cmsDecoder->decoder);
cmsDecoder->cmsMsg = NULL;
}
CFRELEASE(cmsDecoder->detachedContent);
if(cmsDecoder->cmsMsg != NULL) {
SecCmsMessageDestroy(cmsDecoder->cmsMsg);
cmsDecoder->cmsMsg = NULL;
}
}
static OSStatus cmsDigestDetachedContent(
CMSDecoderRef cmsDecoder)
{
ASSERT((cmsDecoder->signedData != NULL) && (cmsDecoder->detachedContent != NULL));
SECAlgorithmID **digestAlgorithms = SecCmsSignedDataGetDigestAlgs(cmsDecoder->signedData);
if(digestAlgorithms == NULL) {
return errSecUnknownFormat;
}
SecCmsDigestContextRef digcx = SecCmsDigestContextStartMultiple(digestAlgorithms);
if(digcx == NULL) {
return errSecAllocate;
}
SecCmsDigestContextUpdate(digcx, CFDataGetBytePtr(cmsDecoder->detachedContent),
CFDataGetLength(cmsDecoder->detachedContent));
OSStatus ortn = SecCmsSignedDataSetDigestContext(cmsDecoder->signedData, digcx);
SecCmsDigestContextDestroy(digcx);
if(ortn) {
ortn = cmsRtnToOSStatus(ortn);
CSSM_PERROR("SecCmsSignedDataSetDigestContext", ortn);
return ortn;
}
return ortn;
}
#pragma mark --- Start of Public API ---
CFTypeID CMSDecoderGetTypeID(void)
{
static pthread_once_t once = PTHREAD_ONCE_INIT;
if(cmsDecoderTypeID == _kCFRuntimeNotATypeID) {
pthread_once(&once, &cmsDecoderClassInitialize);
}
return cmsDecoderTypeID;
}
OSStatus CMSDecoderCreate(
CMSDecoderRef *cmsDecoderOut)
{
CMSDecoderRef cmsDecoder = NULL;
uint32_t extra = sizeof(*cmsDecoder) - sizeof(cmsDecoder->base);
cmsDecoder = (CMSDecoderRef)_CFRuntimeCreateInstance(NULL, CMSDecoderGetTypeID(),
extra, NULL);
if(cmsDecoder == NULL) {
return errSecAllocate;
}
cmsDecoder->decState = DS_Init;
*cmsDecoderOut = cmsDecoder;
return errSecSuccess;
}
OSStatus CMSDecoderUpdateMessage(
CMSDecoderRef cmsDecoder,
const void *msgBytes,
size_t msgBytesLen)
{
if(cmsDecoder == NULL) {
return errSecParam;
}
OSStatus ortn;
switch(cmsDecoder->decState) {
case DS_Init:
ASSERT(cmsDecoder->decoder == NULL);
ASSERT(cmsDecoder->arena == NULL);
ortn = SecCmsDecoderCreate(NULL, NULL, NULL, NULL, NULL, NULL, &cmsDecoder->decoder);
if(ortn) {
ortn = cmsRtnToOSStatus(ortn);
CSSM_PERROR("SecCmsDecoderCreate", ortn);
return ortn;
}
cmsDecoder->decState = DS_Updating;
break;
case DS_Updating:
ASSERT(cmsDecoder->decoder != NULL);
break;
case DS_Final:
return errSecParam;
default:
dprintf("CMSDecoderUpdateMessage: bad decState\n");
return errSecInternalComponent;
}
ortn = SecCmsDecoderUpdate(cmsDecoder->decoder, msgBytes, (CFIndex)msgBytesLen);
if(ortn) {
ortn = cmsRtnToOSStatusDefault(ortn, errSecUnknownFormat);
CSSM_PERROR("SecCmsDecoderUpdate", ortn);
}
return ortn;
}
OSStatus CMSDecoderFinalizeMessage(
CMSDecoderRef cmsDecoder)
{
if(cmsDecoder == NULL) {
return errSecParam;
}
if(cmsDecoder->decState != DS_Updating) {
return errSecParam;
}
ASSERT(cmsDecoder->decoder != NULL);
OSStatus ortn = SecCmsDecoderFinish(cmsDecoder->decoder, &cmsDecoder->cmsMsg);
cmsDecoder->decState = DS_Final;
cmsDecoder->decoder = NULL;
if(ortn) {
ortn = cmsRtnToOSStatusDefault(ortn, errSecUnknownFormat);
CSSM_PERROR("SecCmsDecoderFinish", ortn);
return ortn;
}
ASSERT(cmsDecoder->cmsMsg != NULL);
cmsDecoder->wasEncrypted = SecCmsMessageIsEncrypted(cmsDecoder->cmsMsg);
int numContentInfos = SecCmsMessageContentLevelCount(cmsDecoder->cmsMsg);
int dex;
for(dex=0; dex<numContentInfos; dex++) {
SecCmsContentInfoRef ci = SecCmsMessageContentLevel(cmsDecoder->cmsMsg, dex);
SECOidTag tag = SecCmsContentInfoGetContentTypeTag(ci);
switch(tag) {
case SEC_OID_PKCS7_SIGNED_DATA:
cmsDecoder->signedData =
(SecCmsSignedDataRef)SecCmsContentInfoGetContent(ci);
ci = SecCmsSignedDataGetContentInfo(cmsDecoder->signedData);
if (ci) {
cmsDecoder->eContentType = SecCmsContentInfoGetContentTypeOID(ci);
}
break;
default:
break;
}
if(cmsDecoder->signedData != NULL) {
break;
}
}
if(cmsDecoder->signedData != NULL) {
cmsDecoder->numSigners = (size_t)
SecCmsSignedDataSignerInfoCount(cmsDecoder->signedData);
if(cmsDecoder->detachedContent != NULL) {
ortn = cmsDigestDetachedContent(cmsDecoder);
}
}
return ortn;
}
OSStatus CMSDecoderSetDetachedContent(
CMSDecoderRef cmsDecoder,
CFDataRef detachedContent)
{
if((cmsDecoder == NULL) || (detachedContent == NULL)) {
return errSecParam;
}
cmsDecoder->detachedContent = detachedContent;
CFRetain(detachedContent);
if(cmsDecoder->signedData != NULL) {
ASSERT(cmsDecoder->decState == DS_Final);
return cmsDigestDetachedContent(cmsDecoder);
}
return errSecSuccess;
}
OSStatus CMSDecoderCopyDetachedContent(
CMSDecoderRef cmsDecoder,
CFDataRef *detachedContent)
{
if((cmsDecoder == NULL) || (detachedContent == NULL)) {
return errSecParam;
}
if(cmsDecoder->detachedContent != NULL) {
CFRetain(cmsDecoder->detachedContent);
}
*detachedContent = cmsDecoder->detachedContent;
return errSecSuccess;
}
OSStatus CMSDecoderGetNumSigners(
CMSDecoderRef cmsDecoder,
size_t *numSigners)
{
if((cmsDecoder == NULL) || (numSigners == NULL)) {
return errSecParam;
}
if(cmsDecoder->decState != DS_Final) {
return errSecParam;
}
*numSigners = cmsDecoder->numSigners;
return errSecSuccess;
}
OSStatus CMSDecoderCopySignerStatus(
CMSDecoderRef cmsDecoder,
size_t signerIndex,
CFTypeRef policyOrArray,
Boolean evaluateSecTrust,
CMSSignerStatus *signerStatus,
SecTrustRef *secTrust,
OSStatus *certVerifyResultCode)
{
if((cmsDecoder == NULL) || (cmsDecoder->decState != DS_Final) || (!policyOrArray) || !signerStatus) {
return errSecParam;
}
if(signerStatus) {
*signerStatus = kCMSSignerUnsigned;
}
if(secTrust) {
*secTrust = NULL;
}
if(certVerifyResultCode) {
*certVerifyResultCode = 0;
}
if(cmsDecoder->signedData == NULL) {
*signerStatus = kCMSSignerUnsigned;
return errSecSuccess;
}
ASSERT(cmsDecoder->numSigners > 0);
if(signerIndex >= cmsDecoder->numSigners) {
*signerStatus = kCMSSignerInvalidIndex;
return errSecSuccess;
}
if(!SecCmsSignedDataHasDigests(cmsDecoder->signedData)) {
*signerStatus = kCMSSignerNeedsDetachedContent;
return errSecSuccess;
}
SecTrustRef theTrust = NULL;
OSStatus vfyRtn = SecCmsSignedDataVerifySignerInfo(cmsDecoder->signedData,
(int)signerIndex,
NULL,
policyOrArray,
&theTrust);
#if SECTRUST_VERBOSE_DEBUG
syslog(LOG_ERR, "CMSDecoderCopySignerStatus: SecCmsSignedDataVerifySignerInfo returned %d", (int)vfyRtn);
if (policyOrArray) CFShow(policyOrArray);
if (theTrust) CFShow(theTrust);
#endif
OSStatus ortn = errSecSuccess;
SecTrustResultType secTrustResult;
OSStatus evalRtn, verifyStatus = errSecSuccess;
if(secTrust != NULL) {
*secTrust = theTrust;
CFRetainSafe(theTrust);
}
SecCmsSignerInfoRef signerInfo =
SecCmsSignedDataGetSignerInfo(cmsDecoder->signedData, (int)signerIndex);
if(signerInfo == NULL) {
ASSERT(0);
dprintf("CMSDecoderCopySignerStatus: no signerInfo\n");
ortn = errSecInternalComponent;
goto errOut;
}
if(evaluateSecTrust) {
evalRtn = SecTrustEvaluate(theTrust, &secTrustResult);
if(evalRtn) {
CSSM_PERROR("SecTrustEvaluate", evalRtn);
dprintf("CMSDecoderCopySignerStatus: SecTrustEvaluate error\n");
ortn = errSecInternalComponent;
goto errOut;
}
switch(secTrustResult) {
case kSecTrustResultUnspecified:
case kSecTrustResultProceed:
break;
case kSecTrustResultDeny:
verifyStatus = errSecTrustSettingDeny;
break;
default:
{
verifyStatus = errSecNotTrusted;
break;
}
}
}
if(certVerifyResultCode != NULL) {
*certVerifyResultCode = verifyStatus;
}
if(signerStatus != NULL) {
if((vfyRtn == errSecSuccess) && (verifyStatus == errSecSuccess)) {
*signerStatus = kCMSSignerValid;
}
else if(vfyRtn != errSecSuccess) {
*signerStatus = kCMSSignerInvalidSignature;
}
else {
*signerStatus = kCMSSignerInvalidCert;
}
}
errOut:
CFRELEASE(theTrust);
return ortn;
}
OSStatus CMSDecoderCopySignerEmailAddress(
CMSDecoderRef cmsDecoder,
size_t signerIndex,
CFStringRef *signerEmailAddress)
{
if((cmsDecoder == NULL) ||
(signerEmailAddress == NULL) ||
(cmsDecoder->signedData == NULL) ||
(signerIndex >= cmsDecoder->numSigners) ||
(cmsDecoder->decState != DS_Final)) {
return errSecParam;
}
SecCmsSignerInfoRef signerInfo =
SecCmsSignedDataGetSignerInfo(cmsDecoder->signedData, (int)signerIndex);
if(signerInfo == NULL) {
ASSERT(0);
dprintf("CMSDecoderCopySignerEmailAddress: no signerInfo\n");
return errSecInternalComponent;
}
*signerEmailAddress = SecCmsSignerInfoGetSignerEmailAddress(signerInfo);
return errSecSuccess;
}
OSStatus CMSDecoderCopySignerCert(
CMSDecoderRef cmsDecoder,
size_t signerIndex,
SecCertificateRef *signerCert)
{
if((cmsDecoder == NULL) ||
(signerCert == NULL) ||
(cmsDecoder->signedData == NULL) ||
(signerIndex >= cmsDecoder->numSigners) ||
(cmsDecoder->decState != DS_Final)) {
return errSecParam;
}
SecCmsSignerInfoRef signerInfo =
SecCmsSignedDataGetSignerInfo(cmsDecoder->signedData, (int)signerIndex);
if(signerInfo == NULL) {
ASSERT(0);
dprintf("CMSDecoderCopySignerCertificate: no signerInfo\n");
return errSecInternalComponent;
}
*signerCert = SecCmsSignerInfoGetSigningCertificate(signerInfo, NULL);
if(*signerCert == NULL) {
ASSERT(0);
dprintf("CMSDecoderCopySignerCertificate: no signerCert\n");
return errSecInternalComponent;
}
CFRetain(*signerCert);
return errSecSuccess;
}
OSStatus CMSDecoderIsContentEncrypted(
CMSDecoderRef cmsDecoder,
Boolean *wasEncrypted)
{
if((cmsDecoder == NULL) || (wasEncrypted == NULL)) {
return errSecParam;
}
if(cmsDecoder->decState != DS_Final) {
return errSecParam;
}
*wasEncrypted = cmsDecoder->wasEncrypted;
return errSecSuccess;
}
OSStatus CMSDecoderCopyEncapsulatedContentType(
CMSDecoderRef cmsDecoder,
CFDataRef *eContentType)
{
if((cmsDecoder == NULL) || (eContentType == NULL)) {
return errSecParam;
}
if(cmsDecoder->decState != DS_Final) {
return errSecParam;
}
if(cmsDecoder->signedData == NULL) {
*eContentType = NULL;
}
else {
SecAsn1Oid *ecOid = cmsDecoder->eContentType;
*eContentType = CFDataCreate(NULL, ecOid->Data, ecOid->Length);
}
return errSecSuccess;
}
OSStatus CMSDecoderCopyAllCerts(
CMSDecoderRef cmsDecoder,
CFArrayRef *certs)
{
if((cmsDecoder == NULL) || (certs == NULL)) {
return errSecParam;
}
if(cmsDecoder->decState != DS_Final) {
return errSecParam;
}
if(cmsDecoder->signedData == NULL) {
*certs = NULL;
return errSecSuccess;
}
SecAsn1Item **cssmCerts = SecCmsSignedDataGetCertificateList(cmsDecoder->signedData);
if((cssmCerts == NULL) || (*cssmCerts == NULL)) {
*certs = NULL;
return errSecSuccess;
}
CFMutableArrayRef allCerts = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
SecAsn1Item **cssmCert;
for(cssmCert=cssmCerts; *cssmCert!=NULL; cssmCert++) {
SecCertificateRef cfCert = SecCertificateCreateWithBytes(NULL, (*cssmCert)->Data, (*cssmCert)->Length);
if(!cfCert) {
CFRelease(allCerts);
return errSecDecode;
}
CFArrayAppendValue(allCerts, cfCert);
CFRelease(cfCert);
}
*certs = allCerts;
return errSecSuccess;
}
OSStatus CMSDecoderCopyContent(
CMSDecoderRef cmsDecoder,
CFDataRef *content)
{
if((cmsDecoder == NULL) || (content == NULL)) {
return errSecParam;
}
if(cmsDecoder->decState != DS_Final) {
return errSecParam;
}
if(cmsDecoder->cmsMsg == NULL) {
return errSecParam;
}
const SecAsn1Item *odata = SecCmsMessageGetContent(cmsDecoder->cmsMsg);
if((odata == NULL) || (odata->Length == 0)) {
*content = NULL;
return errSecSuccess;
}
*content = CFDataCreate(NULL, (const UInt8 *)odata->Data, odata->Length);
return errSecSuccess;
}
#pragma mark --- SPI declared in CMSPrivate.h ---
OSStatus CMSDecoderGetCmsMessage(
CMSDecoderRef cmsDecoder,
SecCmsMessageRef *cmsMessage)
{
if((cmsDecoder == NULL) || (cmsMessage == NULL)) {
return errSecParam;
}
*cmsMessage = cmsDecoder->cmsMsg;
return errSecSuccess;
}
OSStatus CMSDecoderSetDecoder(
CMSDecoderRef cmsDecoder,
SecCmsDecoderRef decoder)
{
if((cmsDecoder == NULL) || (decoder == NULL)) {
return errSecParam;
}
switch(cmsDecoder->decState) {
case DS_Init:
ASSERT(cmsDecoder->decoder == NULL);
cmsDecoder->decoder = decoder;
cmsDecoder->decState = DS_Updating;
return errSecSuccess;
case DS_Updating:
case DS_Final:
return errSecParam;
}
return errSecSuccess;
}
OSStatus CMSDecoderGetDecoder(
CMSDecoderRef cmsDecoder,
SecCmsDecoderRef *decoder)
{
if((cmsDecoder == NULL) || (decoder == NULL)) {
return errSecParam;
}
*decoder = cmsDecoder->decoder;
return errSecSuccess;
}
OSStatus CMSDecoderCopySignerSigningTime(
CMSDecoderRef cmsDecoder,
size_t signerIndex,
CFAbsoluteTime *signingTime)
{
OSStatus status = errSecParam;
SecCmsMessageRef cmsg;
SecCmsSignedDataRef signedData = NULL;
int numContentInfos = 0;
require(cmsDecoder && signingTime, 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 = SecCmsSignerInfoGetSigningTime(signerInfo, signingTime);
break;
}
}
}
xit:
return status;
}
#if TIMESTAMPING_SUPPORTED
OSStatus CMSDecoderCopySignerTimestamp(
CMSDecoderRef cmsDecoder,
size_t signerIndex,
CFAbsoluteTime *timestamp)
{
return CMSDecoderCopySignerTimestampWithPolicy(cmsDecoder, NULL, signerIndex, timestamp);
}
OSStatus CMSDecoderCopySignerTimestampWithPolicy(
CMSDecoderRef cmsDecoder,
CFTypeRef timeStampPolicy,
size_t signerIndex,
CFAbsoluteTime *timestamp)
{
OSStatus status = errSecParam;
SecCmsMessageRef cmsg;
SecCmsSignedDataRef signedData = NULL;
int numContentInfos = 0;
require(cmsDecoder && timestamp, 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 = SecCmsSignerInfoGetTimestampTimeWithPolicy(signerInfo, timeStampPolicy, timestamp);
break;
}
}
}
xit:
return status;
}
OSStatus CMSDecoderCopySignerTimestampCertificates(
CMSDecoderRef cmsDecoder,
size_t signerIndex,
CFArrayRef *certificateRefs)
{
OSStatus status = errSecParam;
SecCmsMessageRef cmsg = NULL;
SecCmsSignedDataRef signedData = NULL;
int numContentInfos = 0;
CFIndex tsn = 0;
bool good = false;
require(cmsDecoder && certificateRefs, 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)
{
CFArrayRef certList = SecCmsSignerInfoGetTimestampCertList(signerInfo);
require_action(certList, xit, status = errSecItemNotFound);
CFMutableArrayRef certs = CFArrayCreateMutableCopy(kCFAllocatorDefault, CFArrayGetCount(certList), certList);
if(certs){
tsn = CFArrayGetCount(certs);
good = tsn > 0 && SecIsAppleTrustAnchor((SecCertificateRef)CFArrayGetValueAtIndex(certs, tsn-1), 0);
if ( good == false )
{
for (CFIndex n = 0; n < tsn; n++)
{
SecCertificateRef tsRoot = (SecCertificateRef)CFArrayGetValueAtIndex(certs, n);
if (tsRoot)
if ((good = SecIsAppleTrustAnchor(tsRoot, 0))) {
CFArrayExchangeValuesAtIndices(certs, n, tsn-1);
break;
}
}
}
*certificateRefs = CFArrayCreateCopy(kCFAllocatorDefault, certs);
CFRelease(certs);
status = errSecSuccess;
}
break;
}
}
}
xit:
return status;
}
#endif
OSStatus CMSDecoderCopySignerAppleCodesigningHashAgility(
CMSDecoderRef cmsDecoder,
size_t signerIndex,
CFDataRef CF_RETURNS_RETAINED *hashAgilityAttrValue)
{
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))) {
SecCmsSignerInfoRef signerInfo = SecCmsSignedDataGetSignerInfo(signedData, (int)signerIndex);
if (signerInfo)
{
status = SecCmsSignerInfoGetAppleCodesigningHashAgility(signerInfo, &returnedValue);
break;
}
}
}
exit:
if (status == errSecSuccess && returnedValue) {
*hashAgilityAttrValue = (CFDataRef) CFRetain(returnedValue);
} else {
*hashAgilityAttrValue = NULL;
}
return status;
}
OSStatus CMSDecoderCopySignerAppleCodesigningHashAgilityV2(
CMSDecoderRef cmsDecoder,
size_t signerIndex,
CFDictionaryRef CF_RETURNS_RETAINED *hashAgilityV2AttrValues)
{
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;
}
OSStatus CMSDecoderCopySignerAppleExpirationTime(
CMSDecoderRef cmsDecoder,
size_t signerIndex,
CFAbsoluteTime *expirationTime)
{
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;
}