]> git.saurik.com Git - apple/security.git/blob - Security/libsecurity_cms/lib/CMSDecoder.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / Security / libsecurity_cms / lib / CMSDecoder.cpp
1 /*
2 * Copyright (c) 2006-2014 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 */
53 typedef 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 */
62 struct _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
82 static void cmsDecoderInit(CFTypeRef dec);
83 static void cmsDecoderFinalize(CFTypeRef dec);
84
85 static 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
100 static CFTypeID cmsDecoderTypeID = _kCFRuntimeNotATypeID;
101
102 /* one time only class init, called via pthread_once() in CMSDecoderGetTypeID() */
103 static void cmsDecoderClassInitialize(void)
104 {
105 cmsDecoderTypeID =
106 _CFRuntimeRegisterClass((const CFRuntimeClass * const)&cmsDecoderRuntimeClass);
107 }
108
109 /* init called out from _CFRuntimeCreateInstance() */
110 static 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 */
119 static 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 */
152 static 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
186 CFTypeID 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 */
199 OSStatus 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 */
219 OSStatus 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 */
275 OSStatus 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 */
346 OSStatus 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 */
369 OSStatus 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 */
391 OSStatus 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 */
409 OSStatus 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 */
428 OSStatus 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 }
569 errOut:
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 */
580 OSStatus 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 */
615 OSStatus 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 */
652 OSStatus 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 */
670 OSStatus 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 */
696 OSStatus 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 */
744 OSStatus 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 */
780 OSStatus 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 */
798 OSStatus 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 */
824 OSStatus 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 */
846 OSStatus 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 }
871 xit:
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 */
885
886 OSStatus CMSDecoderCopySignerTimestamp(
887 CMSDecoderRef cmsDecoder,
888 size_t signerIndex, /* usually 0 */
889 CFAbsoluteTime *timestamp) /* RETURNED */
890 {
891 return CMSDecoderCopySignerTimestampWithPolicy(cmsDecoder, NULL, signerIndex, timestamp);
892 }
893
894 OSStatus CMSDecoderCopySignerTimestampWithPolicy(
895 CMSDecoderRef cmsDecoder,
896 CFTypeRef timeStampPolicy,
897 size_t signerIndex, /* usually 0 */
898 CFAbsoluteTime *timestamp) /* RETURNED */
899 {
900 OSStatus status = errSecParam;
901 SecCmsMessageRef cmsg;
902 SecCmsSignedDataRef signedData = NULL;
903 int numContentInfos = 0;
904
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++)
909 {
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))
915 {
916 status = SecCmsSignerInfoGetTimestampTimeWithPolicy(signerInfo, timeStampPolicy, timestamp);
917 break;
918 }
919 }
920
921 xit:
922 return status;
923 }
924
925 /*
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.
930 *
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.
934 *
935 * This cannot be called until after CMSDecoderFinalizeMessage() is called.
936 */
937 OSStatus CMSDecoderCopySignerTimestampCertificates(
938 CMSDecoderRef cmsDecoder,
939 size_t signerIndex, /* usually 0 */
940 CFArrayRef *certificateRefs) /* RETURNED */
941 {
942 OSStatus status = errSecParam;
943 SecCmsMessageRef cmsg = NULL;
944 SecCmsSignedDataRef signedData = NULL;
945 int numContentInfos = 0;
946 CFIndex tsn = 0;
947 bool good = false;
948
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++)
953 {
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))
959 {
960 CFArrayRef certList = SecCmsSignerInfoGetTimestampCertList(signerInfo);
961 require_action(certList, xit, status = errSecItemNotFound);
962 CFMutableArrayRef certs = CFArrayCreateMutableCopy(kCFAllocatorDefault, CFArrayGetCount(certList), certList);
963
964 if(certs){
965 //reorder certificates:
966 tsn = CFArrayGetCount(certs);
967 good = tsn > 0 && Security::CodeSigning::isAppleCA(SecCertificateRef(CFArrayGetValueAtIndex(certs, tsn-1)));
968
969 if ( good == false )
970 {
971 //change TS certificate ordering.
972 for (CFIndex n = 0; n < tsn; n++)
973 {
974 if (SecCertificateRef tsRoot = SecCertificateRef(CFArrayGetValueAtIndex(certs, n)))
975 if ((good = Security::CodeSigning::isAppleCA(tsRoot))) {
976 CFArrayExchangeValuesAtIndices(certs, n, tsn-1);
977 break;
978 }
979 }
980 }
981
982 *certificateRefs = CFArrayCreateCopy(kCFAllocatorDefault, certs);
983 CFRelease(certs);
984 status = errSecSuccess;
985 }
986 break;
987 }
988 }
989
990
991 xit:
992 return status;
993 }