1/*
2 * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24/*
25 * CMSDecoder.cpp - Interface for decoding CMS messages.
26 */
27
28#include "CMSDecoder.h"
29#include "CMSPrivate.h"
30#include "CMSUtils.h"
31#include <../libsecurity_codesigning/lib/csutilities.h>
32
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>
45#include <pthread.h>
46#include <AssertMacros.h>
47
48#pragma mark --- Private types and definitions ---
49
50/*
51 * Decoder state.
52 */
53typedef enum {
54	DS_Init,		/* between CMSDecoderCreate and CMSDecoderUpdateMessage */
55	DS_Updating,	/* between first CMSDecoderUpdateMessage and CMSDecoderFinalizeMessage */
56	DS_Final		/* CMSDecoderFinalizeMessage has been called */
57} CMSDecoderState;
58
59/*
60 * Caller's CMSDecoderRef points to one of these.
61 */
62struct _CMSDecoder {
63	CFRuntimeBase		base;
64	CMSDecoderState		decState;
65	SecArenaPoolRef		arena;				/* the decoder's arena */
66	SecCmsDecoderRef	decoder;
67	CFDataRef			detachedContent;
68	CFTypeRef			keychainOrArray;	/* from CMSDecoderSetSearchKeychain() */
69
70	/*
71	 * The following are valid (and quiescent) after CMSDecoderFinalizeMessage().
72	 */
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 */
77	size_t				numSigners;
78	CSSM_OID			*eContentType;
79	/* etc. */
80};
81
82static void cmsDecoderInit(CFTypeRef dec);
83static void cmsDecoderFinalize(CFTypeRef dec);
84
85static CFRuntimeClass cmsDecoderRuntimeClass =
86{
87	0,			/* version */
88	"CMSDecoder",
89	cmsDecoderInit,
90	NULL,		/* copy */
91	cmsDecoderFinalize,
92	NULL,		/* equal - just use pointer equality */
93	NULL,		/* hash, ditto */
94	NULL,		/* copyFormattingDesc */
95	NULL		/* copyDebugDesc */
96};
97
98#pragma mark --- Private Routines ---
99
100static CFTypeID cmsDecoderTypeID = _kCFRuntimeNotATypeID;
101
102/* one time only class init, called via pthread_once() in CMSDecoderGetTypeID() */
103static void cmsDecoderClassInitialize(void)
104{
105	cmsDecoderTypeID =
106    _CFRuntimeRegisterClass((const CFRuntimeClass * const)&cmsDecoderRuntimeClass);
107}
108
109/* init called out from _CFRuntimeCreateInstance() */
110static void cmsDecoderInit(CFTypeRef dec)
111{
112	char *start = ((char *)dec) + sizeof(CFRuntimeBase);
113	memset(start, 0, sizeof(struct _CMSDecoder) - sizeof(CFRuntimeBase));
114}
115
116/*
117 * Dispose of a CMSDecoder. Called out from CFRelease().
118 */
119static void cmsDecoderFinalize(
120                               CFTypeRef		dec)
121{
122	CMSDecoderRef cmsDecoder = (CMSDecoderRef)dec;
123	if(cmsDecoder == NULL) {
124		return;
125	}
126	if(cmsDecoder->decoder != NULL) {
127		/*
128		 * Normally this gets freed in SecCmsDecoderFinish - this is
129		 * an error case.
130		 * FIXME: SecCmsDecoderDestroy() appears to destroy the
131		 * cmsMsg too! Plus there's a comment there re: a leak...
132		 */
133		SecCmsDecoderDestroy(cmsDecoder->decoder);
134	}
135	CFRELEASE(cmsDecoder->detachedContent);
136	CFRELEASE(cmsDecoder->keychainOrArray);
137	if(cmsDecoder->cmsMsg != NULL) {
138		SecCmsMessageDestroy(cmsDecoder->cmsMsg);
139	}
140	if(cmsDecoder->arena != NULL) {
141		SecArenaPoolFree(cmsDecoder->arena, false);
142	}
143}
144
145
146/*
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).
151 */
152static OSStatus cmsDigestDetachedContent(
153                                         CMSDecoderRef cmsDecoder)
154{
155	ASSERT((cmsDecoder->signedData != NULL) && (cmsDecoder->detachedContent != NULL));
156
157	SECAlgorithmID **digestAlgorithms = SecCmsSignedDataGetDigestAlgs(cmsDecoder->signedData);
158	if(digestAlgorithms == NULL) {
159		return errSecUnknownFormat;
160	}
161	SecCmsDigestContextRef digcx = SecCmsDigestContextStartMultiple(digestAlgorithms);
162	if(digcx == NULL) {
163		return errSecAllocate;
164	}
165	CSSM_DATA **digests = NULL;
166
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);
171	if(ortn) {
172		ortn = cmsRtnToOSStatus(ortn);
173		CSSM_PERROR("SecCmsDigestContextFinishMultiple", ortn);
174		return ortn;
175	}
176	ortn = SecCmsSignedDataSetDigests(cmsDecoder->signedData, digestAlgorithms, digests);
177	if(ortn) {
178		ortn = cmsRtnToOSStatus(ortn);
179		CSSM_PERROR("SecCmsSignedDataSetDigests", ortn);
180	}
181	return ortn;
182}
183
184#pragma mark --- Start of Public API ---
185
186CFTypeID CMSDecoderGetTypeID(void)
187{
188	static pthread_once_t once = PTHREAD_ONCE_INIT;
189
190	if(cmsDecoderTypeID == _kCFRuntimeNotATypeID) {
191		pthread_once(&once, &cmsDecoderClassInitialize);
192	}
193	return cmsDecoderTypeID;
194}
195
196/*
197 * Create a CMSDecoder. Result must eventually be freed via CFRelease().
198 */
199OSStatus CMSDecoderCreate(
200                          CMSDecoderRef		*cmsDecoderOut)	/* RETURNED */
201{
202	CMSDecoderRef cmsDecoder = NULL;
203
204	uint32_t extra = sizeof(*cmsDecoder) - sizeof(cmsDecoder->base);
205	cmsDecoder = (CMSDecoderRef)_CFRuntimeCreateInstance(NULL, CMSDecoderGetTypeID(),
206                                                         extra, NULL);
207	if(cmsDecoder == NULL) {
208		return errSecAllocate;
209	}
210	cmsDecoder->decState = DS_Init;
211	*cmsDecoderOut = cmsDecoder;
212	return errSecSuccess;
213}
214
215/*
216 * Feed raw bytes of the message to be decoded into the decoder. Can be called
217 * multiple times.
218 */
219OSStatus CMSDecoderUpdateMessage(
220                                 CMSDecoderRef		cmsDecoder,
221                                 const void			*msgBytes,
222                                 size_t				msgBytesLen)
223{
224	if(cmsDecoder == NULL) {
225		return errSecParam;
226	}
227
228	OSStatus ortn;
229	switch(cmsDecoder->decState) {
230		case DS_Init:
231			/* First time through; set up */
232			ASSERT(cmsDecoder->decoder == NULL);
233			ASSERT(cmsDecoder->arena == NULL);
234			ortn = SecArenaPoolCreate(1024, &cmsDecoder->arena);
235			if(ortn) {
236				return cmsRtnToOSStatus(ortn);
237			}
238			ortn = SecCmsDecoderCreate(cmsDecoder->arena,
239                                       NULL, NULL, NULL, NULL, NULL, NULL, &cmsDecoder->decoder);
240			if(ortn) {
241				ortn = cmsRtnToOSStatus(ortn);
242				CSSM_PERROR("SecCmsDecoderCreate", ortn);
243				return ortn;
244			}
245			cmsDecoder->decState = DS_Updating;
246			break;
247
248		case DS_Updating:
249			ASSERT(cmsDecoder->decoder != NULL);
250			break;
251
252		case DS_Final:
253			/* Too late for another update */
254			return errSecParam;
255
256		default:
257			dprintf("CMSDecoderUpdateMessage: bad decState\n");
258			return errSecInternalComponent;
259	}
260
261	/* FIXME - CFIndex same size as size_t on 64bit? */
262	ortn = SecCmsDecoderUpdate(cmsDecoder->decoder, msgBytes, (CFIndex)msgBytesLen);
263	if(ortn) {
264		ortn = cmsRtnToOSStatus(ortn, errSecUnknownFormat);
265		CSSM_PERROR("SecCmsDecoderUpdate", ortn);
266	}
267	return ortn;
268}
269
270/*
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.
274 */
275OSStatus CMSDecoderFinalizeMessage(
276                                   CMSDecoderRef		cmsDecoder)
277{
278	if(cmsDecoder == NULL) {
279		return errSecParam;
280	}
281	if(cmsDecoder->decState != DS_Updating) {
282		return errSecParam;
283	}
284	ASSERT(cmsDecoder->decoder != NULL);
285	OSStatus ortn = SecCmsDecoderFinish(cmsDecoder->decoder, &cmsDecoder->cmsMsg);
286	cmsDecoder->decState = DS_Final;
287
288	/* SecCmsDecoderFinish destroyed the decoder even on failure */
289	cmsDecoder->decoder = NULL;
290
291	if(ortn) {
292		ortn = cmsRtnToOSStatus(ortn, errSecUnknownFormat);
293		CSSM_PERROR("SecCmsDecoderFinish", ortn);
294		return ortn;
295	}
296
297	ASSERT(cmsDecoder->cmsMsg != NULL);
298	cmsDecoder->wasEncrypted = SecCmsMessageIsEncrypted(cmsDecoder->cmsMsg);
299
300	/* Look for a SignedData */
301	int numContentInfos = SecCmsMessageContentLevelCount(cmsDecoder->cmsMsg);
302	int dex;
303	for(dex=0; dex<numContentInfos; dex++) {
304		SecCmsContentInfoRef ci = SecCmsMessageContentLevel(cmsDecoder->cmsMsg, dex);
305		SECOidTag tag = SecCmsContentInfoGetContentTypeTag(ci);
306		switch(tag) {
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);
313				break;
314			default:
315				break;
316		}
317		if(cmsDecoder->signedData != NULL) {
318			break;
319		}
320
321	}
322
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);
330		}
331	}
332	return ortn;
333}
334
335/*
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.
339 *
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().
345 */
346OSStatus CMSDecoderSetDetachedContent(
347                                      CMSDecoderRef		cmsDecoder,
348                                      CFDataRef			detachedContent)
349{
350	if((cmsDecoder == NULL) || (detachedContent == NULL)) {
351		return errSecParam;
352	}
353	cmsDecoder->detachedContent = detachedContent;
354	CFRetain(detachedContent);
355
356	if(cmsDecoder->signedData != NULL) {
357		/* time to calculate digests from detached content */
358		ASSERT(cmsDecoder->decState == DS_Final);
359		return cmsDigestDetachedContent(cmsDecoder);
360	}
361	return errSecSuccess;
362}
363
364/*
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.
368 */
369OSStatus CMSDecoderCopyDetachedContent(
370                                       CMSDecoderRef		cmsDecoder,
371                                       CFDataRef			*detachedContent)		/* RETURNED */
372{
373	if((cmsDecoder == NULL) || (detachedContent == NULL)) {
374		return errSecParam;
375	}
376	if(cmsDecoder->detachedContent != NULL) {
377		CFRetain(cmsDecoder->detachedContent);
378	}
379	*detachedContent = cmsDecoder->detachedContent;
380	return errSecSuccess;
381}
382
383/*
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
388 * certs.
389 * IF this is called, it must be called before CMSDecoderCopySignerStatus().
390 */
391OSStatus CMSDecoderSetSearchKeychain(
392                                     CMSDecoderRef		cmsDecoder,
393                                     CFTypeRef			keychainOrArray)
394{
395	if(cmsDecoder == NULL) {
396		return errSecParam;
397	}
398	cmsDecoder->keychainOrArray = keychainOrArray;
399	if(keychainOrArray) {
400		CFRetain(keychainOrArray);
401	}
402	return errSecSuccess;
403}
404
405/*
406 * Obtain the number of signers of a message. A result of zero indicates that
407 * the message was not signed.
408 */
409OSStatus CMSDecoderGetNumSigners(
410                                 CMSDecoderRef		cmsDecoder,
411                                 size_t				*numSigners)			/* RETURNED */
412{
413	if((cmsDecoder == NULL) || (numSigners == NULL)) {
414		return errSecParam;
415	}
416	if(cmsDecoder->decState != DS_Final) {
417		return errSecParam;
418	}
419	*numSigners = cmsDecoder->numSigners;
420	return errSecSuccess;
421}
422
423/*
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.
427 */
428OSStatus CMSDecoderCopySignerStatus(
429                                    CMSDecoderRef		cmsDecoder,
430                                    size_t				signerIndex,
431                                    CFTypeRef			policyOrArray,
432                                    Boolean				evaluateSecTrust,
433                                    CMSSignerStatus		*signerStatus,			/* optional; RETURNED */
434                                    SecTrustRef			*secTrust,				/* optional; RETURNED */
435                                    OSStatus			*certVerifyResultCode)	/* optional; RETURNED */
436{
437	if((cmsDecoder == NULL) || (cmsDecoder->decState != DS_Final)) {
438		return errSecParam;
439	}
440
441	/* initialize return values */
442	if(signerStatus) {
443		*signerStatus = kCMSSignerUnsigned;
444	}
445	if(secTrust) {
446		*secTrust = NULL;
447	}
448	if(certVerifyResultCode) {
449		*certVerifyResultCode = 0;
450	}
451
452	if(cmsDecoder->signedData == NULL) {
453		*signerStatus = kCMSSignerUnsigned;	/* redundant, I know, but explicit */
454		return errSecSuccess;
455	}
456	ASSERT(cmsDecoder->numSigners > 0);
457	if(signerIndex >= cmsDecoder->numSigners) {
458		*signerStatus = kCMSSignerInvalidIndex;
459		return errSecSuccess;
460	}
461	if(!SecCmsSignedDataHasDigests(cmsDecoder->signedData)) {
462		*signerStatus = kCMSSignerNeedsDetachedContent;
463		return errSecSuccess;
464	}
465
466	/*
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
470	 * to the caller.
471	 */
472	SecTrustRef theTrust = NULL;
473	OSStatus vfyRtn = SecCmsSignedDataVerifySignerInfo(cmsDecoder->signedData,
474                                                       (int)signerIndex,
475                                                       /*
476                                                        * FIXME this cast should not be necessary, but libsecurity_smime
477                                                        * declares this argument as a SecKeychainRef
478                                                        */
479                                                       (SecKeychainRef)cmsDecoder->keychainOrArray,
480                                                       policyOrArray,
481                                                       &theTrust);
482    /* Subsequent errors to errOut: */
483
484	/*
485	 * NOTE the smime lib did NOT evaluate that SecTrust - it only does
486	 * SecTrustEvaluate() if we don't ask for a copy.
487	 *
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".
491	 */
492	OSStatus ortn = errSecSuccess;
493	SecTrustResultType secTrustResult;
494	CSSM_RETURN tpVfyStatus = CSSM_OK;
495	OSStatus evalRtn;
496
497	if(secTrust != NULL) {
498		*secTrust = theTrust;
499		/* we'll release our reference at the end */
500		if (theTrust)
501			CFRetain(theTrust);
502	}
503	SecCmsSignerInfoRef signerInfo =
504    SecCmsSignedDataGetSignerInfo(cmsDecoder->signedData, (int)signerIndex);
505	if(signerInfo == NULL) {
506		/* should never happen */
507		ASSERT(0);
508		dprintf("CMSDecoderCopySignerStatus: no signerInfo\n");
509		ortn = errSecInternalComponent;
510		goto errOut;
511	}
512
513	/* now do the actual cert verify */
514	if(evaluateSecTrust) {
515		evalRtn = SecTrustEvaluate(theTrust, &secTrustResult);
516		if(evalRtn) {
517			/* should never happen */
518			CSSM_PERROR("SecTrustEvaluate", evalRtn);
519			dprintf("CMSDecoderCopySignerStatus: SecTrustEvaluate error\n");
520			ortn = errSecInternalComponent;
521			goto errOut;
522		}
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 */
528				break;
529			case kSecTrustResultDeny:
530				tpVfyStatus = CSSMERR_APPLETP_TRUST_SETTING_DENY;
531				break;
532			case kSecTrustResultConfirm:
533				dprintf("SecTrustEvaluate reported confirm\n");
534				tpVfyStatus = CSSMERR_TP_NOT_TRUSTED;
535				break;
536			default:
537			{
538				/* get low-level TP error */
539				OSStatus tpStatus;
540				ortn = SecTrustGetCssmResultCode(theTrust, &tpStatus);
541				if(ortn) {
542					CSSM_PERROR("SecTrustGetCssmResultCode", ortn);
543				}
544				else {
545					tpVfyStatus = tpStatus;
546				}
547				CSSM_PERROR("TP status after SecTrustEvaluate", tpVfyStatus);
548				break;
549			}
550		} 	/* switch(secTrustResult) */
551	}		/* evaluateSecTrust true */
552	if(certVerifyResultCode != NULL) {
553		*certVerifyResultCode = tpVfyStatus;
554	}
555
556	/* cook up global status based on vfyRtn and tpVfyStatus */
557	if(signerStatus != NULL) {
558		if((vfyRtn == errSecSuccess) && (tpVfyStatus == CSSM_OK))  {
559			*signerStatus = kCMSSignerValid;
560		}
561		else if(vfyRtn != errSecSuccess) {
562			/* this could mean other things, but for now... */
563			*signerStatus = kCMSSignerInvalidSignature;
564		}
565		else {
566			*signerStatus = kCMSSignerInvalidCert;
567		}
568	}
569errOut:
570	CFRELEASE(theTrust);
571	return ortn;
572}
573
574/*
575 * Obtain the email address of signer 'signerIndex' of a CMS message, if
576 * present.
577 *
578 * This cannot be called until after CMSDecoderFinalizeMessage() is called.
579 */
580OSStatus CMSDecoderCopySignerEmailAddress(
581                                          CMSDecoderRef		cmsDecoder,
582                                          size_t				signerIndex,
583                                          CFStringRef			*signerEmailAddress)	/* RETURNED */
584{
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)) {
590		return errSecParam;
591	}
592
593	SecCmsSignerInfoRef signerInfo =
594    SecCmsSignedDataGetSignerInfo(cmsDecoder->signedData, (int)signerIndex);
595	if(signerInfo == NULL) {
596		/* should never happen */
597		ASSERT(0);
598		dprintf("CMSDecoderCopySignerEmailAddress: no signerInfo\n");
599		return errSecInternalComponent;
600	}
601
602	/*
603	 * This is leaking memory in libsecurityKeychain per Radar 4412699.
604	 */
605	*signerEmailAddress = SecCmsSignerInfoGetSignerEmailAddress(signerInfo);
606	return errSecSuccess;
607}
608
609/*
610 * Obtain the certificate of signer 'signerIndex' of a CMS message, if
611 * present.
612 *
613 * This cannot be called until after CMSDecoderFinalizeMessage() is called.
614 */
615OSStatus CMSDecoderCopySignerCert(
616                                  CMSDecoderRef		cmsDecoder,
617                                  size_t				signerIndex,
618                                  SecCertificateRef	*signerCert)			/* RETURNED */
619{
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)) {
625		return errSecParam;
626	}
627
628	SecCmsSignerInfoRef signerInfo =
629    SecCmsSignedDataGetSignerInfo(cmsDecoder->signedData, (int)signerIndex);
630	if(signerInfo == NULL) {
631		/* should never happen */
632		ASSERT(0);
633		dprintf("CMSDecoderCopySignerCertificate: no signerInfo\n");
634		return errSecInternalComponent;
635	}
636	*signerCert = SecCmsSignerInfoGetSigningCertificate(signerInfo, NULL);
637	/* libsecurity_smime does NOT retain that */
638	if(*signerCert == NULL) {
639		/* should never happen */
640		ASSERT(0);
641		dprintf("CMSDecoderCopySignerCertificate: no signerCert\n");
642		return errSecInternalComponent;
643	}
644	CFRetain(*signerCert);
645	return errSecSuccess;
646}
647
648/*
649 * Determine whether a CMS message was encrypted, and if so, whether we were
650 * able to decrypt it.
651 */
652OSStatus CMSDecoderIsContentEncrypted(
653                                      CMSDecoderRef	cmsDecoder,
654                                      Boolean			*wasEncrypted)
655{
656	if((cmsDecoder == NULL) || (wasEncrypted == NULL)) {
657		return errSecParam;
658	}
659	if(cmsDecoder->decState != DS_Final) {
660		return errSecParam;
661	}
662	*wasEncrypted = cmsDecoder->wasEncrypted;
663	return errSecSuccess;
664}
665
666/*
667 * Obtain the eContentType OID for a SignedData's EncapsulatedContentType, if
668 * present.
669 */
670OSStatus CMSDecoderCopyEncapsulatedContentType(
671                                               CMSDecoderRef		cmsDecoder,
672                                               CFDataRef			*eContentType)		/* RETURNED */
673{
674	if((cmsDecoder == NULL) || (eContentType == NULL)) {
675		return errSecParam;
676	}
677	if(cmsDecoder->decState != DS_Final) {
678		return errSecParam;
679	}
680	if(cmsDecoder->signedData == NULL) {
681		*eContentType = NULL;
682	}
683	else {
684		CSSM_OID *ecOid = cmsDecoder->eContentType;
685		*eContentType = CFDataCreate(NULL, ecOid->Data, ecOid->Length);
686	}
687	return errSecSuccess;
688}
689
690/*
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
693 * array.
694 * This cannot be called until after CMSDecoderFinalizeMessage() is called.
695 */
696OSStatus CMSDecoderCopyAllCerts(
697                                CMSDecoderRef		cmsDecoder,
698                                CFArrayRef			*certs)					/* RETURNED */
699{
700	if((cmsDecoder == NULL) || (certs == NULL)) {
701		return errSecParam;
702	}
703	if(cmsDecoder->decState != DS_Final) {
704		return errSecParam;
705	}
706	if(cmsDecoder->signedData == NULL) {
707		/* message wasn't signed */
708		*certs = NULL;
709		return errSecSuccess;
710	}
711
712	/* NULL_terminated array of CSSM_DATA ptrs */
713	CSSM_DATA_PTR *cssmCerts = SecCmsSignedDataGetCertificateList(cmsDecoder->signedData);
714	if((cssmCerts == NULL) || (*cssmCerts == NULL)) {
715		*certs = NULL;
716		return errSecSuccess;
717	}
718
719	CFMutableArrayRef allCerts = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
720	CSSM_DATA_PTR *cssmCert;
721	for(cssmCert=cssmCerts; *cssmCert!=NULL; cssmCert++) {
722		OSStatus ortn;
723		SecCertificateRef cfCert;
724		ortn = SecCertificateCreateFromData(*cssmCert,
725                                            CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER,
726                                            &cfCert);
727		if(ortn) {
728			CFRelease(allCerts);
729			return ortn;
730		}
731		CFArrayAppendValue(allCerts, cfCert);
732		/* the array holds the only needed refcount */
733		CFRelease(cfCert);
734	}
735	*certs = allCerts;
736	return errSecSuccess;
737}
738
739/*
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.
743 */
744OSStatus CMSDecoderCopyContent(
745                               CMSDecoderRef		cmsDecoder,
746                               CFDataRef			*content)				/* RETURNED */
747{
748	if((cmsDecoder == NULL) || (content == NULL)) {
749		return errSecParam;
750	}
751	if(cmsDecoder->decState != DS_Final) {
752		return errSecParam;
753	}
754	if(cmsDecoder->cmsMsg == NULL) {
755		/* Hmmm....looks like the finalize call failed */
756		return errSecParam;
757	}
758	CSSM_DATA_PTR odata = SecCmsMessageGetContent(cmsDecoder->cmsMsg);
759	if((odata == NULL) || (odata->Length == 0)) {
760		/* i.e., detached content */
761		*content = NULL;
762		return errSecSuccess;
763	}
764	*content = CFDataCreate(NULL, (const UInt8 *)odata->Data, odata->Length);
765	return errSecSuccess;
766}
767
768#pragma mark --- SPI declared in CMSPrivate.h ---
769
770/*
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
776 * called.
777 *
778 * The CMSDecoder retains ownership of the returned SecCmsMessageRef.
779 */
780OSStatus CMSDecoderGetCmsMessage(
781                                 CMSDecoderRef		cmsDecoder,
782                                 SecCmsMessageRef	*cmsMessage)		/* RETURNED */
783{
784	if((cmsDecoder == NULL) || (cmsMessage == NULL)) {
785		return errSecParam;
786	}
787	/* any state, whether we have a msg or not is OK */
788	*cmsMessage = cmsDecoder->cmsMsg;
789	return errSecSuccess;
790}
791
792/*
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.
797 */
798OSStatus CMSDecoderSetDecoder(
799                              CMSDecoderRef		cmsDecoder,
800                              SecCmsDecoderRef	decoder)
801{
802	if((cmsDecoder == NULL) || (decoder == NULL)) {
803		return errSecParam;
804	}
805	switch(cmsDecoder->decState) {
806		case DS_Init:
807			ASSERT(cmsDecoder->decoder == NULL);
808			cmsDecoder->decoder = decoder;
809			cmsDecoder->decState = DS_Updating;
810			return errSecSuccess;
811		case DS_Updating:
812		case DS_Final:
813			return errSecParam;
814	}
815	return errSecSuccess;
816}
817
818/*
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.
823 */
824OSStatus CMSDecoderGetDecoder(
825                              CMSDecoderRef		cmsDecoder,
826                              SecCmsDecoderRef	*decoder)			/* RETURNED */
827{
828	if((cmsDecoder == NULL) || (decoder == NULL)) {
829		return errSecParam;
830	}
831	/* any state, whether we have a decoder or not is OK */
832	*decoder = cmsDecoder->decoder;
833	return errSecSuccess;
834}
835
836/*
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.
840 *
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.
843 *
844 * This cannot be called until after CMSDecoderFinalizeMessage() is called.
845 */
846OSStatus CMSDecoderCopySignerSigningTime(
847                                         CMSDecoderRef		cmsDecoder,
848                                         size_t				signerIndex,            /* usually 0 */
849                                         CFAbsoluteTime      *signingTime)			/* RETURNED */
850{
851    OSStatus status = errSecParam;
852	SecCmsMessageRef cmsg;
853	SecCmsSignedDataRef signedData = NULL;
854    int numContentInfos = 0;
855
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++)
860    {
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))
866                {
867                    status = SecCmsSignerInfoGetSigningTime(signerInfo, signingTime);
868                    break;
869                }
870    }
871xit:
872    return status;
873}
874
875/*
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.
879 *
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.
882 *
883 * This cannot be called until after CMSDecoderFinalizeMessage() is called.
884 */
885OSStatus CMSDecoderCopySignerTimestamp(
886                                       CMSDecoderRef		cmsDecoder,
887                                       size_t				signerIndex,        /* usually 0 */
888                                       CFAbsoluteTime      *timestamp)			/* RETURNED */
889{
890    OSStatus status = errSecParam;
891	SecCmsMessageRef cmsg;
892	SecCmsSignedDataRef signedData = NULL;
893    int numContentInfos = 0;
894
895    require(cmsDecoder && timestamp, xit);
896	require_noerr(CMSDecoderGetCmsMessage(cmsDecoder, &cmsg), xit);
897    numContentInfos = SecCmsMessageContentLevelCount(cmsg);
898    for (int dex = 0; !signedData && dex < numContentInfos; dex++)
899    {
900        SecCmsContentInfoRef ci = SecCmsMessageContentLevel(cmsg, dex);
901        SECOidTag tag = SecCmsContentInfoGetContentTypeTag(ci);
902        if (tag == SEC_OID_PKCS7_SIGNED_DATA)
903            if ((signedData = SecCmsSignedDataRef(SecCmsContentInfoGetContent(ci))))
904                if (SecCmsSignerInfoRef signerInfo = SecCmsSignedDataGetSignerInfo(signedData, (int)signerIndex))
905                {
906                    status = SecCmsSignerInfoGetTimestampTime(signerInfo, timestamp);
907                    break;
908                }
909    }
910
911xit:
912    return status;
913}
914
915/*
916 * Obtain an array of the certificates in a timestamp response. Elements of the
917 * returned array are SecCertificateRefs. The caller must CFRelease the returned
918 * array. This timestamp is an authenticated timestamp provided by
919 * a timestamping authority.
920 *
921 * Returns errSecParam if the CMS message was not signed or if signerIndex
922 * is greater than the number of signers of the message minus one. It returns
923 * errSecItemNotFound if no certificates were found.
924 *
925 * This cannot be called until after CMSDecoderFinalizeMessage() is called.
926 */
927OSStatus CMSDecoderCopySignerTimestampCertificates(
928                                                   CMSDecoderRef		cmsDecoder,
929                                                   size_t				signerIndex,            /* usually 0 */
930                                                   CFArrayRef          *certificateRefs)       /* RETURNED */
931{
932    OSStatus status = errSecParam;
933	SecCmsMessageRef cmsg = NULL;
934	SecCmsSignedDataRef signedData = NULL;
935    int numContentInfos = 0;
936    CFIndex tsn = 0;
937    bool good = false;
938
939    require(cmsDecoder && certificateRefs, xit);
940	require_noerr(CMSDecoderGetCmsMessage(cmsDecoder, &cmsg), xit);
941    numContentInfos = SecCmsMessageContentLevelCount(cmsg);
942    for (int dex = 0; !signedData && dex < numContentInfos; dex++)
943    {
944        SecCmsContentInfoRef ci = SecCmsMessageContentLevel(cmsg, dex);
945        SECOidTag tag = SecCmsContentInfoGetContentTypeTag(ci);
946        if (tag == SEC_OID_PKCS7_SIGNED_DATA)
947            if ((signedData = SecCmsSignedDataRef(SecCmsContentInfoGetContent(ci))))
948                if (SecCmsSignerInfoRef signerInfo = SecCmsSignedDataGetSignerInfo(signedData, (int)signerIndex))
949                {
950                    CFArrayRef certList = SecCmsSignerInfoGetTimestampCertList(signerInfo);
951                    require_action(certList, xit, status = errSecItemNotFound);
952                    CFMutableArrayRef certs = CFArrayCreateMutableCopy(kCFAllocatorDefault, CFArrayGetCount(certList), certList);
953
954                    if(certs){
955                        //reorder certificates:
956                        tsn = CFArrayGetCount(certs);
957                        good = tsn > 0 && Security::CodeSigning::isAppleCA(SecCertificateRef(CFArrayGetValueAtIndex(certs, tsn-1)));
958
959                        if ( good == false )
960                        {
961                            //change TS certificate ordering.
962                            for (CFIndex n = 0; n < tsn; n++)
963                            {
964                                if (SecCertificateRef tsRoot = SecCertificateRef(CFArrayGetValueAtIndex(certs, n)))
965                                    if ((good = Security::CodeSigning::isAppleCA(tsRoot))) {
966                                        CFArrayExchangeValuesAtIndices(certs, n, tsn-1);
967                                        break;
968                                    }
969                            }
970                        }
971
972                        *certificateRefs = CFArrayCreateCopy(kCFAllocatorDefault, certs);
973                        CFRelease(certs);
974                        status = errSecSuccess;
975                    }
976                    break;
977                }
978    }
979
980
981    xit:
982        return status;
983    }
984