2 * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 * CMSDecoder.cpp - Interface for decoding CMS messages.
28 #include "CMSDecoder.h"
29 #include "CMSPrivate.h"
31 #include <../libsecurity_codesigning/lib/csutilities.h>
33 #include <Security/SecCmsDecoder.h>
34 #include <Security/SecCmsEnvelopedData.h>
35 #include <Security/SecCmsMessage.h>
36 #include <Security/SecCmsSignedData.h>
37 #include <Security/SecCmsSignerInfo.h>
38 #include <Security/SecCmsContentInfo.h>
39 #include <Security/SecCmsDigestContext.h>
40 #include <Security/SecCertificate.h>
41 #include <Security/SecSMIME.h>
42 #include <Security/oidsattr.h>
43 #include <Security/SecTrustPriv.h>
44 #include <CoreFoundation/CFRuntime.h>
46 #include <AssertMacros.h>
48 #pragma mark --- Private types and definitions ---
54 DS_Init
, /* between CMSDecoderCreate and CMSDecoderUpdateMessage */
55 DS_Updating
, /* between first CMSDecoderUpdateMessage and CMSDecoderFinalizeMessage */
56 DS_Final
/* CMSDecoderFinalizeMessage has been called */
60 * Caller's CMSDecoderRef points to one of these.
64 CMSDecoderState decState
;
65 SecArenaPoolRef arena
; /* the decoder's arena */
66 SecCmsDecoderRef decoder
;
67 CFDataRef detachedContent
;
68 CFTypeRef keychainOrArray
; /* from CMSDecoderSetSearchKeychain() */
71 * The following are valid (and quiescent) after CMSDecoderFinalizeMessage().
73 SecCmsMessageRef cmsMsg
;
74 Boolean wasEncrypted
; /* valid after CMSDecoderFinalizeMessage() */
75 SecCmsSignedDataRef signedData
; /* if there is one... */
76 /* only non-NULL if we found a signedData */
78 CSSM_OID
*eContentType
;
82 static void cmsDecoderInit(CFTypeRef dec
);
83 static void cmsDecoderFinalize(CFTypeRef dec
);
85 static CFRuntimeClass cmsDecoderRuntimeClass
=
92 NULL
, /* equal - just use pointer equality */
93 NULL
, /* hash, ditto */
94 NULL
, /* copyFormattingDesc */
95 NULL
/* copyDebugDesc */
98 #pragma mark --- Private Routines ---
100 static CFTypeID cmsDecoderTypeID
= _kCFRuntimeNotATypeID
;
102 /* one time only class init, called via pthread_once() in CMSDecoderGetTypeID() */
103 static void cmsDecoderClassInitialize(void)
106 _CFRuntimeRegisterClass((const CFRuntimeClass
* const)&cmsDecoderRuntimeClass
);
109 /* init called out from _CFRuntimeCreateInstance() */
110 static void cmsDecoderInit(CFTypeRef dec
)
112 char *start
= ((char *)dec
) + sizeof(CFRuntimeBase
);
113 memset(start
, 0, sizeof(struct _CMSDecoder
) - sizeof(CFRuntimeBase
));
117 * Dispose of a CMSDecoder. Called out from CFRelease().
119 static void cmsDecoderFinalize(
122 CMSDecoderRef cmsDecoder
= (CMSDecoderRef
)dec
;
123 if(cmsDecoder
== NULL
) {
126 if(cmsDecoder
->decoder
!= NULL
) {
128 * Normally this gets freed in SecCmsDecoderFinish - this is
130 * FIXME: SecCmsDecoderDestroy() appears to destroy the
131 * cmsMsg too! Plus there's a comment there re: a leak...
133 SecCmsDecoderDestroy(cmsDecoder
->decoder
);
135 CFRELEASE(cmsDecoder
->detachedContent
);
136 CFRELEASE(cmsDecoder
->keychainOrArray
);
137 if(cmsDecoder
->cmsMsg
!= NULL
) {
138 SecCmsMessageDestroy(cmsDecoder
->cmsMsg
);
140 if(cmsDecoder
->arena
!= NULL
) {
141 SecArenaPoolFree(cmsDecoder
->arena
, false);
147 * Given detached content and a valid (decoded) SignedData, digest the detached
148 * content. This occurs at the later of {CMSDecoderFinalizeMessage() finding a
149 * SignedData when already have detachedContent, or CMSDecoderSetDetachedContent()
150 * when we already have a SignedData).
152 static OSStatus
cmsDigestDetachedContent(
153 CMSDecoderRef cmsDecoder
)
155 ASSERT((cmsDecoder
->signedData
!= NULL
) && (cmsDecoder
->detachedContent
!= NULL
));
157 SECAlgorithmID
**digestAlgorithms
= SecCmsSignedDataGetDigestAlgs(cmsDecoder
->signedData
);
158 if(digestAlgorithms
== NULL
) {
159 return errSecUnknownFormat
;
161 SecCmsDigestContextRef digcx
= SecCmsDigestContextStartMultiple(digestAlgorithms
);
163 return errSecAllocate
;
165 CSSM_DATA
**digests
= NULL
;
167 SecCmsDigestContextUpdate(digcx
, CFDataGetBytePtr(cmsDecoder
->detachedContent
),
168 CFDataGetLength(cmsDecoder
->detachedContent
));
169 /* note this frees the digest content regardless */
170 OSStatus ortn
= SecCmsDigestContextFinishMultiple(digcx
, cmsDecoder
->arena
, &digests
);
172 ortn
= cmsRtnToOSStatus(ortn
);
173 CSSM_PERROR("SecCmsDigestContextFinishMultiple", ortn
);
176 ortn
= SecCmsSignedDataSetDigests(cmsDecoder
->signedData
, digestAlgorithms
, digests
);
178 ortn
= cmsRtnToOSStatus(ortn
);
179 CSSM_PERROR("SecCmsSignedDataSetDigests", ortn
);
184 #pragma mark --- Start of Public API ---
186 CFTypeID
CMSDecoderGetTypeID(void)
188 static pthread_once_t once
= PTHREAD_ONCE_INIT
;
190 if(cmsDecoderTypeID
== _kCFRuntimeNotATypeID
) {
191 pthread_once(&once
, &cmsDecoderClassInitialize
);
193 return cmsDecoderTypeID
;
197 * Create a CMSDecoder. Result must eventually be freed via CFRelease().
199 OSStatus
CMSDecoderCreate(
200 CMSDecoderRef
*cmsDecoderOut
) /* RETURNED */
202 CMSDecoderRef cmsDecoder
= NULL
;
204 uint32_t extra
= sizeof(*cmsDecoder
) - sizeof(cmsDecoder
->base
);
205 cmsDecoder
= (CMSDecoderRef
)_CFRuntimeCreateInstance(NULL
, CMSDecoderGetTypeID(),
207 if(cmsDecoder
== NULL
) {
208 return errSecAllocate
;
210 cmsDecoder
->decState
= DS_Init
;
211 *cmsDecoderOut
= cmsDecoder
;
212 return errSecSuccess
;
216 * Feed raw bytes of the message to be decoded into the decoder. Can be called
219 OSStatus
CMSDecoderUpdateMessage(
220 CMSDecoderRef cmsDecoder
,
221 const void *msgBytes
,
224 if(cmsDecoder
== NULL
) {
229 switch(cmsDecoder
->decState
) {
231 /* First time through; set up */
232 ASSERT(cmsDecoder
->decoder
== NULL
);
233 ASSERT(cmsDecoder
->arena
== NULL
);
234 ortn
= SecArenaPoolCreate(1024, &cmsDecoder
->arena
);
236 return cmsRtnToOSStatus(ortn
);
238 ortn
= SecCmsDecoderCreate(cmsDecoder
->arena
,
239 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &cmsDecoder
->decoder
);
241 ortn
= cmsRtnToOSStatus(ortn
);
242 CSSM_PERROR("SecCmsDecoderCreate", ortn
);
245 cmsDecoder
->decState
= DS_Updating
;
249 ASSERT(cmsDecoder
->decoder
!= NULL
);
253 /* Too late for another update */
257 dprintf("CMSDecoderUpdateMessage: bad decState\n");
258 return errSecInternalComponent
;
261 /* FIXME - CFIndex same size as size_t on 64bit? */
262 ortn
= SecCmsDecoderUpdate(cmsDecoder
->decoder
, msgBytes
, (CFIndex
)msgBytesLen
);
264 ortn
= cmsRtnToOSStatus(ortn
, errSecUnknownFormat
);
265 CSSM_PERROR("SecCmsDecoderUpdate", ortn
);
271 * Indicate that no more CMSDecoderUpdateMessage() calls are forthcoming;
272 * finish decoding the message. We parse the message as best we can, up to
273 * but not including verifying individual signerInfos.
275 OSStatus
CMSDecoderFinalizeMessage(
276 CMSDecoderRef cmsDecoder
)
278 if(cmsDecoder
== NULL
) {
281 if(cmsDecoder
->decState
!= DS_Updating
) {
284 ASSERT(cmsDecoder
->decoder
!= NULL
);
285 OSStatus ortn
= SecCmsDecoderFinish(cmsDecoder
->decoder
, &cmsDecoder
->cmsMsg
);
286 cmsDecoder
->decState
= DS_Final
;
288 /* SecCmsDecoderFinish destroyed the decoder even on failure */
289 cmsDecoder
->decoder
= NULL
;
292 ortn
= cmsRtnToOSStatus(ortn
, errSecUnknownFormat
);
293 CSSM_PERROR("SecCmsDecoderFinish", ortn
);
297 ASSERT(cmsDecoder
->cmsMsg
!= NULL
);
298 cmsDecoder
->wasEncrypted
= SecCmsMessageIsEncrypted(cmsDecoder
->cmsMsg
);
300 /* Look for a SignedData */
301 int numContentInfos
= SecCmsMessageContentLevelCount(cmsDecoder
->cmsMsg
);
303 for(dex
=0; dex
<numContentInfos
; dex
++) {
304 SecCmsContentInfoRef ci
= SecCmsMessageContentLevel(cmsDecoder
->cmsMsg
, dex
);
305 SECOidTag tag
= SecCmsContentInfoGetContentTypeTag(ci
);
307 case SEC_OID_PKCS7_SIGNED_DATA
:
308 cmsDecoder
->signedData
=
309 (SecCmsSignedDataRef
)SecCmsContentInfoGetContent(ci
);
310 /* dig down one more layer for eContentType */
311 ci
= SecCmsSignedDataGetContentInfo(cmsDecoder
->signedData
);
312 cmsDecoder
->eContentType
= SecCmsContentInfoGetContentTypeOID(ci
);
317 if(cmsDecoder
->signedData
!= NULL
) {
323 /* minimal processing of optional signedData... */
324 if(cmsDecoder
->signedData
!= NULL
) {
325 cmsDecoder
->numSigners
= (size_t)
326 SecCmsSignedDataSignerInfoCount(cmsDecoder
->signedData
);
327 if(cmsDecoder
->detachedContent
!= NULL
) {
328 /* time to calculate digests from detached content */
329 ortn
= cmsDigestDetachedContent(cmsDecoder
);
336 * A signed CMS message optionally includes the data which was signed. If the
337 * message does not include the signed data, caller specifies the signed data
338 * (the "detached content") here.
340 * This can be called either before or after the actual decoding of the message
341 * (via CMSDecoderUpdateMessage() and CMSDecoderFinalizeMessage()); the only
342 * restriction is that, if detached content is required, this function must
343 * be called befoere successfully ascertaining the signature status via
344 * CMSDecoderCopySignerStatus().
346 OSStatus
CMSDecoderSetDetachedContent(
347 CMSDecoderRef cmsDecoder
,
348 CFDataRef detachedContent
)
350 if((cmsDecoder
== NULL
) || (detachedContent
== NULL
)) {
353 cmsDecoder
->detachedContent
= detachedContent
;
354 CFRetain(detachedContent
);
356 if(cmsDecoder
->signedData
!= NULL
) {
357 /* time to calculate digests from detached content */
358 ASSERT(cmsDecoder
->decState
== DS_Final
);
359 return cmsDigestDetachedContent(cmsDecoder
);
361 return errSecSuccess
;
365 * Obtain the detached content specified in CMSDecoderSetDetachedContent().
366 * Returns a NULL detachedContent if no detached content has been specified.
367 * Caller must CFRelease() the result.
369 OSStatus
CMSDecoderCopyDetachedContent(
370 CMSDecoderRef cmsDecoder
,
371 CFDataRef
*detachedContent
) /* RETURNED */
373 if((cmsDecoder
== NULL
) || (detachedContent
== NULL
)) {
376 if(cmsDecoder
->detachedContent
!= NULL
) {
377 CFRetain(cmsDecoder
->detachedContent
);
379 *detachedContent
= cmsDecoder
->detachedContent
;
380 return errSecSuccess
;
384 * Optionally specify a SecKeychainRef, or an array of them, containing
385 * intermediate certs to be used in verifying a signed message's signer
386 * certs. By default, the default keychain search list is used for this.
387 * Specify an empty CFArrayRef to search *no* keychains for intermediate
389 * IF this is called, it must be called before CMSDecoderCopySignerStatus().
391 OSStatus
CMSDecoderSetSearchKeychain(
392 CMSDecoderRef cmsDecoder
,
393 CFTypeRef keychainOrArray
)
395 if(cmsDecoder
== NULL
) {
398 cmsDecoder
->keychainOrArray
= keychainOrArray
;
399 if(keychainOrArray
) {
400 CFRetain(keychainOrArray
);
402 return errSecSuccess
;
406 * Obtain the number of signers of a message. A result of zero indicates that
407 * the message was not signed.
409 OSStatus
CMSDecoderGetNumSigners(
410 CMSDecoderRef cmsDecoder
,
411 size_t *numSigners
) /* RETURNED */
413 if((cmsDecoder
== NULL
) || (numSigners
== NULL
)) {
416 if(cmsDecoder
->decState
!= DS_Final
) {
419 *numSigners
= cmsDecoder
->numSigners
;
420 return errSecSuccess
;
424 * Obtain the status of a CMS message's signature. A CMS message can
425 * be signed my multiple signers; this function returns the status
426 * associated with signer 'n' as indicated by the signerIndex parameter.
428 OSStatus
CMSDecoderCopySignerStatus(
429 CMSDecoderRef cmsDecoder
,
431 CFTypeRef policyOrArray
,
432 Boolean evaluateSecTrust
,
433 CMSSignerStatus
*signerStatus
, /* optional; RETURNED */
434 SecTrustRef
*secTrust
, /* optional; RETURNED */
435 OSStatus
*certVerifyResultCode
) /* optional; RETURNED */
437 if((cmsDecoder
== NULL
) || (cmsDecoder
->decState
!= DS_Final
)) {
441 /* initialize return values */
443 *signerStatus
= kCMSSignerUnsigned
;
448 if(certVerifyResultCode
) {
449 *certVerifyResultCode
= 0;
452 if(cmsDecoder
->signedData
== NULL
) {
453 *signerStatus
= kCMSSignerUnsigned
; /* redundant, I know, but explicit */
454 return errSecSuccess
;
456 ASSERT(cmsDecoder
->numSigners
> 0);
457 if(signerIndex
>= cmsDecoder
->numSigners
) {
458 *signerStatus
= kCMSSignerInvalidIndex
;
459 return errSecSuccess
;
461 if(!SecCmsSignedDataHasDigests(cmsDecoder
->signedData
)) {
462 *signerStatus
= kCMSSignerNeedsDetachedContent
;
463 return errSecSuccess
;
467 * OK, we should be able to verify this signerInfo.
468 * I think we have to do the SecCmsSignedDataVerifySignerInfo first
469 * in order get all the cert pieces into place before returning them
472 SecTrustRef theTrust
= NULL
;
473 OSStatus vfyRtn
= SecCmsSignedDataVerifySignerInfo(cmsDecoder
->signedData
,
476 * FIXME this cast should not be necessary, but libsecurity_smime
477 * declares this argument as a SecKeychainRef
479 (SecKeychainRef
)cmsDecoder
->keychainOrArray
,
482 /* Subsequent errors to errOut: */
485 * NOTE the smime lib did NOT evaluate that SecTrust - it only does
486 * SecTrustEvaluate() if we don't ask for a copy.
488 * FIXME deal with multitudes of status returns here...for now, proceed with
489 * obtaining components the caller wants and assume that a nonzero vfyRtn
490 * means "bad signature".
492 OSStatus ortn
= errSecSuccess
;
493 SecTrustResultType secTrustResult
;
494 CSSM_RETURN tpVfyStatus
= CSSM_OK
;
497 if(secTrust
!= NULL
) {
498 *secTrust
= theTrust
;
499 /* we'll release our reference at the end */
503 SecCmsSignerInfoRef signerInfo
=
504 SecCmsSignedDataGetSignerInfo(cmsDecoder
->signedData
, (int)signerIndex
);
505 if(signerInfo
== NULL
) {
506 /* should never happen */
508 dprintf("CMSDecoderCopySignerStatus: no signerInfo\n");
509 ortn
= errSecInternalComponent
;
513 /* now do the actual cert verify */
514 if(evaluateSecTrust
) {
515 evalRtn
= SecTrustEvaluate(theTrust
, &secTrustResult
);
517 /* should never happen */
518 CSSM_PERROR("SecTrustEvaluate", evalRtn
);
519 dprintf("CMSDecoderCopySignerStatus: SecTrustEvaluate error\n");
520 ortn
= errSecInternalComponent
;
523 switch(secTrustResult
) {
524 case kSecTrustResultUnspecified
:
525 /* cert chain valid, no special UserTrust assignments */
526 case kSecTrustResultProceed
:
527 /* cert chain valid AND user explicitly trusts this */
529 case kSecTrustResultDeny
:
530 tpVfyStatus
= CSSMERR_APPLETP_TRUST_SETTING_DENY
;
532 case kSecTrustResultConfirm
:
533 dprintf("SecTrustEvaluate reported confirm\n");
534 tpVfyStatus
= CSSMERR_TP_NOT_TRUSTED
;
538 /* get low-level TP error */
540 ortn
= SecTrustGetCssmResultCode(theTrust
, &tpStatus
);
542 CSSM_PERROR("SecTrustGetCssmResultCode", ortn
);
545 tpVfyStatus
= tpStatus
;
547 CSSM_PERROR("TP status after SecTrustEvaluate", tpVfyStatus
);
550 } /* switch(secTrustResult) */
551 } /* evaluateSecTrust true */
552 if(certVerifyResultCode
!= NULL
) {
553 *certVerifyResultCode
= tpVfyStatus
;
556 /* cook up global status based on vfyRtn and tpVfyStatus */
557 if(signerStatus
!= NULL
) {
558 if((vfyRtn
== errSecSuccess
) && (tpVfyStatus
== CSSM_OK
)) {
559 *signerStatus
= kCMSSignerValid
;
561 else if(vfyRtn
!= errSecSuccess
) {
562 /* this could mean other things, but for now... */
563 *signerStatus
= kCMSSignerInvalidSignature
;
566 *signerStatus
= kCMSSignerInvalidCert
;
575 * Obtain the email address of signer 'signerIndex' of a CMS message, if
578 * This cannot be called until after CMSDecoderFinalizeMessage() is called.
580 OSStatus
CMSDecoderCopySignerEmailAddress(
581 CMSDecoderRef cmsDecoder
,
583 CFStringRef
*signerEmailAddress
) /* RETURNED */
585 if((cmsDecoder
== NULL
) ||
586 (signerEmailAddress
== NULL
) ||
587 (cmsDecoder
->signedData
== NULL
) || /* not signed */
588 (signerIndex
>= cmsDecoder
->numSigners
) || /* index out of range */
589 (cmsDecoder
->decState
!= DS_Final
)) {
593 SecCmsSignerInfoRef signerInfo
=
594 SecCmsSignedDataGetSignerInfo(cmsDecoder
->signedData
, (int)signerIndex
);
595 if(signerInfo
== NULL
) {
596 /* should never happen */
598 dprintf("CMSDecoderCopySignerEmailAddress: no signerInfo\n");
599 return errSecInternalComponent
;
603 * This is leaking memory in libsecurityKeychain per Radar 4412699.
605 *signerEmailAddress
= SecCmsSignerInfoGetSignerEmailAddress(signerInfo
);
606 return errSecSuccess
;
610 * Obtain the certificate of signer 'signerIndex' of a CMS message, if
613 * This cannot be called until after CMSDecoderFinalizeMessage() is called.
615 OSStatus
CMSDecoderCopySignerCert(
616 CMSDecoderRef cmsDecoder
,
618 SecCertificateRef
*signerCert
) /* RETURNED */
620 if((cmsDecoder
== NULL
) ||
621 (signerCert
== NULL
) ||
622 (cmsDecoder
->signedData
== NULL
) || /* not signed */
623 (signerIndex
>= cmsDecoder
->numSigners
) || /* index out of range */
624 (cmsDecoder
->decState
!= DS_Final
)) {
628 SecCmsSignerInfoRef signerInfo
=
629 SecCmsSignedDataGetSignerInfo(cmsDecoder
->signedData
, (int)signerIndex
);
630 if(signerInfo
== NULL
) {
631 /* should never happen */
633 dprintf("CMSDecoderCopySignerCertificate: no signerInfo\n");
634 return errSecInternalComponent
;
636 *signerCert
= SecCmsSignerInfoGetSigningCertificate(signerInfo
, NULL
);
637 /* libsecurity_smime does NOT retain that */
638 if(*signerCert
== NULL
) {
639 /* should never happen */
641 dprintf("CMSDecoderCopySignerCertificate: no signerCert\n");
642 return errSecInternalComponent
;
644 CFRetain(*signerCert
);
645 return errSecSuccess
;
649 * Determine whether a CMS message was encrypted, and if so, whether we were
650 * able to decrypt it.
652 OSStatus
CMSDecoderIsContentEncrypted(
653 CMSDecoderRef cmsDecoder
,
654 Boolean
*wasEncrypted
)
656 if((cmsDecoder
== NULL
) || (wasEncrypted
== NULL
)) {
659 if(cmsDecoder
->decState
!= DS_Final
) {
662 *wasEncrypted
= cmsDecoder
->wasEncrypted
;
663 return errSecSuccess
;
667 * Obtain the eContentType OID for a SignedData's EncapsulatedContentType, if
670 OSStatus
CMSDecoderCopyEncapsulatedContentType(
671 CMSDecoderRef cmsDecoder
,
672 CFDataRef
*eContentType
) /* RETURNED */
674 if((cmsDecoder
== NULL
) || (eContentType
== NULL
)) {
677 if(cmsDecoder
->decState
!= DS_Final
) {
680 if(cmsDecoder
->signedData
== NULL
) {
681 *eContentType
= NULL
;
684 CSSM_OID
*ecOid
= cmsDecoder
->eContentType
;
685 *eContentType
= CFDataCreate(NULL
, ecOid
->Data
, ecOid
->Length
);
687 return errSecSuccess
;
691 * Obtain an array of all of the certificates in a message. Elements of the
692 * returned array are SecCertificateRefs. The caller must CFRelease the returned
694 * This cannot be called until after CMSDecoderFinalizeMessage() is called.
696 OSStatus
CMSDecoderCopyAllCerts(
697 CMSDecoderRef cmsDecoder
,
698 CFArrayRef
*certs
) /* RETURNED */
700 if((cmsDecoder
== NULL
) || (certs
== NULL
)) {
703 if(cmsDecoder
->decState
!= DS_Final
) {
706 if(cmsDecoder
->signedData
== NULL
) {
707 /* message wasn't signed */
709 return errSecSuccess
;
712 /* NULL_terminated array of CSSM_DATA ptrs */
713 CSSM_DATA_PTR
*cssmCerts
= SecCmsSignedDataGetCertificateList(cmsDecoder
->signedData
);
714 if((cssmCerts
== NULL
) || (*cssmCerts
== NULL
)) {
716 return errSecSuccess
;
719 CFMutableArrayRef allCerts
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
720 CSSM_DATA_PTR
*cssmCert
;
721 for(cssmCert
=cssmCerts
; *cssmCert
!=NULL
; cssmCert
++) {
723 SecCertificateRef cfCert
;
724 ortn
= SecCertificateCreateFromData(*cssmCert
,
725 CSSM_CERT_X_509v3
, CSSM_CERT_ENCODING_DER
,
731 CFArrayAppendValue(allCerts
, cfCert
);
732 /* the array holds the only needed refcount */
736 return errSecSuccess
;
740 * Obtain the actual message content (payload), if any. If the message was
741 * signed with detached content this will return NULL.
742 * Caller must CFRelease the result.
744 OSStatus
CMSDecoderCopyContent(
745 CMSDecoderRef cmsDecoder
,
746 CFDataRef
*content
) /* RETURNED */
748 if((cmsDecoder
== NULL
) || (content
== NULL
)) {
751 if(cmsDecoder
->decState
!= DS_Final
) {
754 if(cmsDecoder
->cmsMsg
== NULL
) {
755 /* Hmmm....looks like the finalize call failed */
758 CSSM_DATA_PTR odata
= SecCmsMessageGetContent(cmsDecoder
->cmsMsg
);
759 if((odata
== NULL
) || (odata
->Length
== 0)) {
760 /* i.e., detached content */
762 return errSecSuccess
;
764 *content
= CFDataCreate(NULL
, (const UInt8
*)odata
->Data
, odata
->Length
);
765 return errSecSuccess
;
768 #pragma mark --- SPI declared in CMSPrivate.h ---
771 * Obtain the SecCmsMessageRef associated with a CMSDecoderRef. Intended
772 * to be called after decoding the message (i.e., after
773 * CMSDecoderFinalizeMessage() to gain finer access to the contents of the
774 * SecCmsMessageRef than is otherwise available via the CMSDecoder interface.
775 * Returns a NULL SecCmsMessageRef if CMSDecoderFinalizeMessage() has not been
778 * The CMSDecoder retains ownership of the returned SecCmsMessageRef.
780 OSStatus
CMSDecoderGetCmsMessage(
781 CMSDecoderRef cmsDecoder
,
782 SecCmsMessageRef
*cmsMessage
) /* RETURNED */
784 if((cmsDecoder
== NULL
) || (cmsMessage
== NULL
)) {
787 /* any state, whether we have a msg or not is OK */
788 *cmsMessage
= cmsDecoder
->cmsMsg
;
789 return errSecSuccess
;
793 * Optionally specify a SecCmsDecoderRef to use with a CMSDecoderRef.
794 * If this is called, it must be called before the first call to
795 * CMSDecoderUpdateMessage(). The CMSDecoderRef takes ownership of the
796 * incoming SecCmsDecoderRef.
798 OSStatus
CMSDecoderSetDecoder(
799 CMSDecoderRef cmsDecoder
,
800 SecCmsDecoderRef decoder
)
802 if((cmsDecoder
== NULL
) || (decoder
== NULL
)) {
805 switch(cmsDecoder
->decState
) {
807 ASSERT(cmsDecoder
->decoder
== NULL
);
808 cmsDecoder
->decoder
= decoder
;
809 cmsDecoder
->decState
= DS_Updating
;
810 return errSecSuccess
;
815 return errSecSuccess
;
819 * Obtain the SecCmsDecoderRef associated with a CMSDecoderRef.
820 * Returns a NULL SecCmsDecoderRef if neither CMSDecoderSetDecoder() nor
821 * CMSDecoderUpdateMessage() has been called.
822 * The CMSDecoderRef retains ownership of the SecCmsDecoderRef.
824 OSStatus
CMSDecoderGetDecoder(
825 CMSDecoderRef cmsDecoder
,
826 SecCmsDecoderRef
*decoder
) /* RETURNED */
828 if((cmsDecoder
== NULL
) || (decoder
== NULL
)) {
831 /* any state, whether we have a decoder or not is OK */
832 *decoder
= cmsDecoder
->decoder
;
833 return errSecSuccess
;
837 * Obtain the signing time of signer 'signerIndex' of a CMS message, if
838 * present. This is an unauthenticate time, although it is part of the
839 * signed attributes of the message.
841 * Returns errSecParam if the CMS message was not signed or if signerIndex
842 * is greater than the number of signers of the message minus one.
844 * This cannot be called until after CMSDecoderFinalizeMessage() is called.
846 OSStatus
CMSDecoderCopySignerSigningTime(
847 CMSDecoderRef cmsDecoder
,
848 size_t signerIndex
, /* usually 0 */
849 CFAbsoluteTime
*signingTime
) /* RETURNED */
851 OSStatus status
= errSecParam
;
852 SecCmsMessageRef cmsg
;
853 SecCmsSignedDataRef signedData
= NULL
;
854 int numContentInfos
= 0;
856 require(cmsDecoder
&& signingTime
, xit
);
857 require_noerr(CMSDecoderGetCmsMessage(cmsDecoder
, &cmsg
), xit
);
858 numContentInfos
= SecCmsMessageContentLevelCount(cmsg
);
859 for (int dex
= 0; !signedData
&& dex
< numContentInfos
; dex
++)
861 SecCmsContentInfoRef ci
= SecCmsMessageContentLevel(cmsg
, dex
);
862 SECOidTag tag
= SecCmsContentInfoGetContentTypeTag(ci
);
863 if (tag
== SEC_OID_PKCS7_SIGNED_DATA
)
864 if ((signedData
= SecCmsSignedDataRef(SecCmsContentInfoGetContent(ci
))))
865 if (SecCmsSignerInfoRef signerInfo
= SecCmsSignedDataGetSignerInfo(signedData
, (int)signerIndex
))
867 status
= SecCmsSignerInfoGetSigningTime(signerInfo
, signingTime
);
876 * Obtain the timestamp of signer 'signerIndex' of a CMS message, if
877 * present. This timestamp is an authenticated timestamp provided by
878 * a timestamping authority.
880 * Returns errSecParam if the CMS message was not signed or if signerIndex
881 * is greater than the number of signers of the message minus one.
883 * This cannot be called until after CMSDecoderFinalizeMessage() is called.
886 OSStatus
CMSDecoderCopySignerTimestamp(
887 CMSDecoderRef cmsDecoder
,
888 size_t signerIndex
, /* usually 0 */
889 CFAbsoluteTime
*timestamp
) /* RETURNED */
891 return CMSDecoderCopySignerTimestampWithPolicy(cmsDecoder
, NULL
, signerIndex
, timestamp
);
894 OSStatus
CMSDecoderCopySignerTimestampWithPolicy(
895 CMSDecoderRef cmsDecoder
,
896 CFTypeRef timeStampPolicy
,
897 size_t signerIndex
, /* usually 0 */
898 CFAbsoluteTime
*timestamp
) /* RETURNED */
900 OSStatus status
= errSecParam
;
901 SecCmsMessageRef cmsg
;
902 SecCmsSignedDataRef signedData
= NULL
;
903 int numContentInfos
= 0;
905 require(cmsDecoder
&& timestamp
, xit
);
906 require_noerr(CMSDecoderGetCmsMessage(cmsDecoder
, &cmsg
), xit
);
907 numContentInfos
= SecCmsMessageContentLevelCount(cmsg
);
908 for (int dex
= 0; !signedData
&& dex
< numContentInfos
; dex
++)
910 SecCmsContentInfoRef ci
= SecCmsMessageContentLevel(cmsg
, dex
);
911 SECOidTag tag
= SecCmsContentInfoGetContentTypeTag(ci
);
912 if (tag
== SEC_OID_PKCS7_SIGNED_DATA
)
913 if ((signedData
= SecCmsSignedDataRef(SecCmsContentInfoGetContent(ci
))))
914 if (SecCmsSignerInfoRef signerInfo
= SecCmsSignedDataGetSignerInfo(signedData
, (int)signerIndex
))
916 status
= SecCmsSignerInfoGetTimestampTimeWithPolicy(signerInfo
, timeStampPolicy
, timestamp
);
926 * Obtain an array of the certificates in a timestamp response. Elements of the
927 * returned array are SecCertificateRefs. The caller must CFRelease the returned
928 * array. This timestamp is an authenticated timestamp provided by
929 * a timestamping authority.
931 * Returns errSecParam if the CMS message was not signed or if signerIndex
932 * is greater than the number of signers of the message minus one. It returns
933 * errSecItemNotFound if no certificates were found.
935 * This cannot be called until after CMSDecoderFinalizeMessage() is called.
937 OSStatus
CMSDecoderCopySignerTimestampCertificates(
938 CMSDecoderRef cmsDecoder
,
939 size_t signerIndex
, /* usually 0 */
940 CFArrayRef
*certificateRefs
) /* RETURNED */
942 OSStatus status
= errSecParam
;
943 SecCmsMessageRef cmsg
= NULL
;
944 SecCmsSignedDataRef signedData
= NULL
;
945 int numContentInfos
= 0;
949 require(cmsDecoder
&& certificateRefs
, xit
);
950 require_noerr(CMSDecoderGetCmsMessage(cmsDecoder
, &cmsg
), xit
);
951 numContentInfos
= SecCmsMessageContentLevelCount(cmsg
);
952 for (int dex
= 0; !signedData
&& dex
< numContentInfos
; dex
++)
954 SecCmsContentInfoRef ci
= SecCmsMessageContentLevel(cmsg
, dex
);
955 SECOidTag tag
= SecCmsContentInfoGetContentTypeTag(ci
);
956 if (tag
== SEC_OID_PKCS7_SIGNED_DATA
)
957 if ((signedData
= SecCmsSignedDataRef(SecCmsContentInfoGetContent(ci
))))
958 if (SecCmsSignerInfoRef signerInfo
= SecCmsSignedDataGetSignerInfo(signedData
, (int)signerIndex
))
960 CFArrayRef certList
= SecCmsSignerInfoGetTimestampCertList(signerInfo
);
961 require_action(certList
, xit
, status
= errSecItemNotFound
);
962 CFMutableArrayRef certs
= CFArrayCreateMutableCopy(kCFAllocatorDefault
, CFArrayGetCount(certList
), certList
);
965 //reorder certificates:
966 tsn
= CFArrayGetCount(certs
);
967 good
= tsn
> 0 && Security::CodeSigning::isAppleCA(SecCertificateRef(CFArrayGetValueAtIndex(certs
, tsn
-1)));
971 //change TS certificate ordering.
972 for (CFIndex n
= 0; n
< tsn
; n
++)
974 if (SecCertificateRef tsRoot
= SecCertificateRef(CFArrayGetValueAtIndex(certs
, n
)))
975 if ((good
= Security::CodeSigning::isAppleCA(tsRoot
))) {
976 CFArrayExchangeValuesAtIndices(certs
, n
, tsn
-1);
982 *certificateRefs
= CFArrayCreateCopy(kCFAllocatorDefault
, certs
);
984 status
= errSecSuccess
;