]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_cms/lib/CMSDecoder.cpp
dcb79035d9ea57aaa32b67ab183117b12dd6648e
[apple/security.git] / OSX / 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 <syslog.h>
47 #include <AssertMacros.h>
48
49 #pragma mark --- Private types and definitions ---
50
51 /*
52 * Decoder state.
53 */
54 typedef enum {
55 DS_Init, /* between CMSDecoderCreate and CMSDecoderUpdateMessage */
56 DS_Updating, /* between first CMSDecoderUpdateMessage and CMSDecoderFinalizeMessage */
57 DS_Final /* CMSDecoderFinalizeMessage has been called */
58 } CMSDecoderState;
59
60 /*
61 * Caller's CMSDecoderRef points to one of these.
62 */
63 struct _CMSDecoder {
64 CFRuntimeBase base;
65 CMSDecoderState decState;
66 SecArenaPoolRef arena; /* the decoder's arena */
67 SecCmsDecoderRef decoder;
68 CFDataRef detachedContent;
69 CFTypeRef keychainOrArray; /* from CMSDecoderSetSearchKeychain() */
70
71 /*
72 * The following are valid (and quiescent) after CMSDecoderFinalizeMessage().
73 */
74 SecCmsMessageRef cmsMsg;
75 Boolean wasEncrypted; /* valid after CMSDecoderFinalizeMessage() */
76 SecCmsSignedDataRef signedData; /* if there is one... */
77 /* only non-NULL if we found a signedData */
78 size_t numSigners;
79 CSSM_OID *eContentType;
80 /* etc. */
81 };
82
83 static void cmsDecoderInit(CFTypeRef dec);
84 static void cmsDecoderFinalize(CFTypeRef dec);
85
86 static CFRuntimeClass cmsDecoderRuntimeClass =
87 {
88 0, /* version */
89 "CMSDecoder",
90 cmsDecoderInit,
91 NULL, /* copy */
92 cmsDecoderFinalize,
93 NULL, /* equal - just use pointer equality */
94 NULL, /* hash, ditto */
95 NULL, /* copyFormattingDesc */
96 NULL /* copyDebugDesc */
97 };
98
99 #pragma mark --- Private Routines ---
100
101 static CFTypeID cmsDecoderTypeID = _kCFRuntimeNotATypeID;
102
103 /* one time only class init, called via pthread_once() in CMSDecoderGetTypeID() */
104 static void cmsDecoderClassInitialize(void)
105 {
106 cmsDecoderTypeID =
107 _CFRuntimeRegisterClass((const CFRuntimeClass * const)&cmsDecoderRuntimeClass);
108 }
109
110 /* init called out from _CFRuntimeCreateInstance() */
111 static void cmsDecoderInit(CFTypeRef dec)
112 {
113 char *start = ((char *)dec) + sizeof(CFRuntimeBase);
114 memset(start, 0, sizeof(struct _CMSDecoder) - sizeof(CFRuntimeBase));
115 }
116
117 /*
118 * Dispose of a CMSDecoder. Called out from CFRelease().
119 */
120 static void cmsDecoderFinalize(
121 CFTypeRef dec)
122 {
123 CMSDecoderRef cmsDecoder = (CMSDecoderRef)dec;
124 if(cmsDecoder == NULL) {
125 return;
126 }
127 if(cmsDecoder->decoder != NULL) {
128 /*
129 * Normally this gets freed in SecCmsDecoderFinish - this is
130 * an error case. Unlike Finish, this calls SecCmsMessageDestroy.
131 */
132 SecCmsDecoderDestroy(cmsDecoder->decoder);
133 cmsDecoder->cmsMsg = NULL;
134 }
135 CFRELEASE(cmsDecoder->detachedContent);
136 CFRELEASE(cmsDecoder->keychainOrArray);
137 if(cmsDecoder->cmsMsg != NULL) {
138 SecCmsMessageDestroy(cmsDecoder->cmsMsg);
139 cmsDecoder->cmsMsg = NULL;
140 }
141 if(cmsDecoder->arena != NULL) {
142 SecArenaPoolFree(cmsDecoder->arena, false);
143 cmsDecoder->arena = NULL;
144 }
145 }
146
147
148 /*
149 * Given detached content and a valid (decoded) SignedData, digest the detached
150 * content. This occurs at the later of {CMSDecoderFinalizeMessage() finding a
151 * SignedData when already have detachedContent, or CMSDecoderSetDetachedContent()
152 * when we already have a SignedData).
153 */
154 static OSStatus cmsDigestDetachedContent(
155 CMSDecoderRef cmsDecoder)
156 {
157 ASSERT((cmsDecoder->signedData != NULL) && (cmsDecoder->detachedContent != NULL));
158
159 SECAlgorithmID **digestAlgorithms = SecCmsSignedDataGetDigestAlgs(cmsDecoder->signedData);
160 if(digestAlgorithms == NULL) {
161 return errSecUnknownFormat;
162 }
163 SecCmsDigestContextRef digcx = SecCmsDigestContextStartMultiple(digestAlgorithms);
164 if(digcx == NULL) {
165 return errSecAllocate;
166 }
167 CSSM_DATA **digests = NULL;
168
169 SecCmsDigestContextUpdate(digcx, CFDataGetBytePtr(cmsDecoder->detachedContent),
170 CFDataGetLength(cmsDecoder->detachedContent));
171 /* note this frees the digest content regardless */
172 OSStatus ortn = SecCmsDigestContextFinishMultiple(digcx, cmsDecoder->arena, &digests);
173 if(ortn) {
174 ortn = cmsRtnToOSStatus(ortn);
175 CSSM_PERROR("SecCmsDigestContextFinishMultiple", ortn);
176 return ortn;
177 }
178 ortn = SecCmsSignedDataSetDigests(cmsDecoder->signedData, digestAlgorithms, digests);
179 if(ortn) {
180 ortn = cmsRtnToOSStatus(ortn);
181 CSSM_PERROR("SecCmsSignedDataSetDigests", ortn);
182 }
183 return ortn;
184 }
185
186 #pragma mark --- Start of Public API ---
187
188 CFTypeID CMSDecoderGetTypeID(void)
189 {
190 static pthread_once_t once = PTHREAD_ONCE_INIT;
191
192 if(cmsDecoderTypeID == _kCFRuntimeNotATypeID) {
193 pthread_once(&once, &cmsDecoderClassInitialize);
194 }
195 return cmsDecoderTypeID;
196 }
197
198 /*
199 * Create a CMSDecoder. Result must eventually be freed via CFRelease().
200 */
201 OSStatus CMSDecoderCreate(
202 CMSDecoderRef *cmsDecoderOut) /* RETURNED */
203 {
204 CMSDecoderRef cmsDecoder = NULL;
205
206 uint32_t extra = sizeof(*cmsDecoder) - sizeof(cmsDecoder->base);
207 cmsDecoder = (CMSDecoderRef)_CFRuntimeCreateInstance(NULL, CMSDecoderGetTypeID(),
208 extra, NULL);
209 if(cmsDecoder == NULL) {
210 return errSecAllocate;
211 }
212 cmsDecoder->decState = DS_Init;
213 *cmsDecoderOut = cmsDecoder;
214 return errSecSuccess;
215 }
216
217 /*
218 * Feed raw bytes of the message to be decoded into the decoder. Can be called
219 * multiple times.
220 */
221 OSStatus CMSDecoderUpdateMessage(
222 CMSDecoderRef cmsDecoder,
223 const void *msgBytes,
224 size_t msgBytesLen)
225 {
226 if(cmsDecoder == NULL) {
227 return errSecParam;
228 }
229
230 OSStatus ortn;
231 switch(cmsDecoder->decState) {
232 case DS_Init:
233 /* First time through; set up */
234 ASSERT(cmsDecoder->decoder == NULL);
235 ASSERT(cmsDecoder->arena == NULL);
236 ortn = SecArenaPoolCreate(1024, &cmsDecoder->arena);
237 if(ortn) {
238 return cmsRtnToOSStatus(ortn);
239 }
240 ortn = SecCmsDecoderCreate(cmsDecoder->arena,
241 NULL, NULL, NULL, NULL, NULL, NULL, &cmsDecoder->decoder);
242 if(ortn) {
243 ortn = cmsRtnToOSStatus(ortn);
244 CSSM_PERROR("SecCmsDecoderCreate", ortn);
245 return ortn;
246 }
247 cmsDecoder->decState = DS_Updating;
248 break;
249
250 case DS_Updating:
251 ASSERT(cmsDecoder->decoder != NULL);
252 break;
253
254 case DS_Final:
255 /* Too late for another update */
256 return errSecParam;
257
258 default:
259 dprintf("CMSDecoderUpdateMessage: bad decState\n");
260 return errSecInternalComponent;
261 }
262
263 /* FIXME - CFIndex same size as size_t on 64bit? */
264 ortn = SecCmsDecoderUpdate(cmsDecoder->decoder, msgBytes, (CFIndex)msgBytesLen);
265 if(ortn) {
266 ortn = cmsRtnToOSStatus(ortn, errSecUnknownFormat);
267 CSSM_PERROR("SecCmsDecoderUpdate", ortn);
268 }
269 return ortn;
270 }
271
272 /*
273 * Indicate that no more CMSDecoderUpdateMessage() calls are forthcoming;
274 * finish decoding the message. We parse the message as best we can, up to
275 * but not including verifying individual signerInfos.
276 */
277 OSStatus CMSDecoderFinalizeMessage(
278 CMSDecoderRef cmsDecoder)
279 {
280 if(cmsDecoder == NULL) {
281 return errSecParam;
282 }
283 if(cmsDecoder->decState != DS_Updating) {
284 return errSecParam;
285 }
286 ASSERT(cmsDecoder->decoder != NULL);
287 OSStatus ortn = SecCmsDecoderFinish(cmsDecoder->decoder, &cmsDecoder->cmsMsg);
288 cmsDecoder->decState = DS_Final;
289
290 /* SecCmsDecoderFinish destroyed the decoder even on failure */
291 cmsDecoder->decoder = NULL;
292
293 if(ortn) {
294 ortn = cmsRtnToOSStatus(ortn, errSecUnknownFormat);
295 CSSM_PERROR("SecCmsDecoderFinish", ortn);
296 return ortn;
297 }
298
299 ASSERT(cmsDecoder->cmsMsg != NULL);
300 cmsDecoder->wasEncrypted = SecCmsMessageIsEncrypted(cmsDecoder->cmsMsg);
301
302 /* Look for a SignedData */
303 int numContentInfos = SecCmsMessageContentLevelCount(cmsDecoder->cmsMsg);
304 int dex;
305 for(dex=0; dex<numContentInfos; dex++) {
306 SecCmsContentInfoRef ci = SecCmsMessageContentLevel(cmsDecoder->cmsMsg, dex);
307 SECOidTag tag = SecCmsContentInfoGetContentTypeTag(ci);
308 switch(tag) {
309 case SEC_OID_PKCS7_SIGNED_DATA:
310 cmsDecoder->signedData =
311 (SecCmsSignedDataRef)SecCmsContentInfoGetContent(ci);
312 /* dig down one more layer for eContentType */
313 ci = SecCmsSignedDataGetContentInfo(cmsDecoder->signedData);
314 cmsDecoder->eContentType = SecCmsContentInfoGetContentTypeOID(ci);
315 break;
316 default:
317 break;
318 }
319 if(cmsDecoder->signedData != NULL) {
320 break;
321 }
322
323 }
324
325 /* minimal processing of optional signedData... */
326 if(cmsDecoder->signedData != NULL) {
327 cmsDecoder->numSigners = (size_t)
328 SecCmsSignedDataSignerInfoCount(cmsDecoder->signedData);
329 if(cmsDecoder->detachedContent != NULL) {
330 /* time to calculate digests from detached content */
331 ortn = cmsDigestDetachedContent(cmsDecoder);
332 }
333 }
334 return ortn;
335 }
336
337 /*
338 * A signed CMS message optionally includes the data which was signed. If the
339 * message does not include the signed data, caller specifies the signed data
340 * (the "detached content") here.
341 *
342 * This can be called either before or after the actual decoding of the message
343 * (via CMSDecoderUpdateMessage() and CMSDecoderFinalizeMessage()); the only
344 * restriction is that, if detached content is required, this function must
345 * be called befoere successfully ascertaining the signature status via
346 * CMSDecoderCopySignerStatus().
347 */
348 OSStatus CMSDecoderSetDetachedContent(
349 CMSDecoderRef cmsDecoder,
350 CFDataRef detachedContent)
351 {
352 if((cmsDecoder == NULL) || (detachedContent == NULL)) {
353 return errSecParam;
354 }
355 cmsDecoder->detachedContent = detachedContent;
356 CFRetain(detachedContent);
357
358 if(cmsDecoder->signedData != NULL) {
359 /* time to calculate digests from detached content */
360 ASSERT(cmsDecoder->decState == DS_Final);
361 return cmsDigestDetachedContent(cmsDecoder);
362 }
363 return errSecSuccess;
364 }
365
366 /*
367 * Obtain the detached content specified in CMSDecoderSetDetachedContent().
368 * Returns a NULL detachedContent if no detached content has been specified.
369 * Caller must CFRelease() the result.
370 */
371 OSStatus CMSDecoderCopyDetachedContent(
372 CMSDecoderRef cmsDecoder,
373 CFDataRef *detachedContent) /* RETURNED */
374 {
375 if((cmsDecoder == NULL) || (detachedContent == NULL)) {
376 return errSecParam;
377 }
378 if(cmsDecoder->detachedContent != NULL) {
379 CFRetain(cmsDecoder->detachedContent);
380 }
381 *detachedContent = cmsDecoder->detachedContent;
382 return errSecSuccess;
383 }
384
385 /*
386 * Optionally specify a SecKeychainRef, or an array of them, containing
387 * intermediate certs to be used in verifying a signed message's signer
388 * certs. By default, the default keychain search list is used for this.
389 * Specify an empty CFArrayRef to search *no* keychains for intermediate
390 * certs.
391 * IF this is called, it must be called before CMSDecoderCopySignerStatus().
392 */
393 OSStatus CMSDecoderSetSearchKeychain(
394 CMSDecoderRef cmsDecoder,
395 CFTypeRef keychainOrArray)
396 {
397 if(cmsDecoder == NULL) {
398 return errSecParam;
399 }
400 cmsDecoder->keychainOrArray = keychainOrArray;
401 if(keychainOrArray) {
402 CFRetain(keychainOrArray);
403 }
404 return errSecSuccess;
405 }
406
407 /*
408 * Obtain the number of signers of a message. A result of zero indicates that
409 * the message was not signed.
410 */
411 OSStatus CMSDecoderGetNumSigners(
412 CMSDecoderRef cmsDecoder,
413 size_t *numSigners) /* RETURNED */
414 {
415 if((cmsDecoder == NULL) || (numSigners == NULL)) {
416 return errSecParam;
417 }
418 if(cmsDecoder->decState != DS_Final) {
419 return errSecParam;
420 }
421 *numSigners = cmsDecoder->numSigners;
422 return errSecSuccess;
423 }
424
425 /*
426 * Obtain the status of a CMS message's signature. A CMS message can
427 * be signed my multiple signers; this function returns the status
428 * associated with signer 'n' as indicated by the signerIndex parameter.
429 */
430 OSStatus CMSDecoderCopySignerStatus(
431 CMSDecoderRef cmsDecoder,
432 size_t signerIndex,
433 CFTypeRef policyOrArray,
434 Boolean evaluateSecTrust,
435 CMSSignerStatus *signerStatus, /* optional; RETURNED */
436 SecTrustRef *secTrust, /* optional; RETURNED */
437 OSStatus *certVerifyResultCode) /* optional; RETURNED */
438 {
439 if((cmsDecoder == NULL) || (cmsDecoder->decState != DS_Final) || (!policyOrArray)) {
440 return errSecParam;
441 }
442
443 /* initialize return values */
444 if(signerStatus) {
445 *signerStatus = kCMSSignerUnsigned;
446 }
447 if(secTrust) {
448 *secTrust = NULL;
449 }
450 if(certVerifyResultCode) {
451 *certVerifyResultCode = 0;
452 }
453
454 if(cmsDecoder->signedData == NULL) {
455 *signerStatus = kCMSSignerUnsigned; /* redundant, I know, but explicit */
456 return errSecSuccess;
457 }
458 ASSERT(cmsDecoder->numSigners > 0);
459 if(signerIndex >= cmsDecoder->numSigners) {
460 *signerStatus = kCMSSignerInvalidIndex;
461 return errSecSuccess;
462 }
463 if(!SecCmsSignedDataHasDigests(cmsDecoder->signedData)) {
464 *signerStatus = kCMSSignerNeedsDetachedContent;
465 return errSecSuccess;
466 }
467
468 /*
469 * OK, we should be able to verify this signerInfo.
470 * I think we have to do the SecCmsSignedDataVerifySignerInfo first
471 * in order get all the cert pieces into place before returning them
472 * to the caller.
473 */
474 SecTrustRef theTrust = NULL;
475 OSStatus vfyRtn = SecCmsSignedDataVerifySignerInfo(cmsDecoder->signedData,
476 (int)signerIndex,
477 /*
478 * FIXME this cast should not be necessary, but libsecurity_smime
479 * declares this argument as a SecKeychainRef
480 */
481 (SecKeychainRef)cmsDecoder->keychainOrArray,
482 policyOrArray,
483 &theTrust);
484
485 #if SECTRUST_VERBOSE_DEBUG
486 syslog(LOG_ERR, "CMSDecoderCopySignerStatus: SecCmsSignedDataVerifySignerInfo returned %d", (int)vfyRtn);
487 if (policyOrArray) CFShow(policyOrArray);
488 if (theTrust) CFShow(theTrust);
489 #endif
490
491 /* Subsequent errors to errOut: */
492
493 /*
494 * NOTE the smime lib did NOT evaluate that SecTrust - it only does
495 * SecTrustEvaluate() if we don't ask for a copy.
496 *
497 * FIXME deal with multitudes of status returns here...for now, proceed with
498 * obtaining components the caller wants and assume that a nonzero vfyRtn
499 * means "bad signature".
500 */
501 OSStatus ortn = errSecSuccess;
502 SecTrustResultType secTrustResult;
503 CSSM_RETURN tpVfyStatus = CSSM_OK;
504 OSStatus evalRtn;
505
506 if(secTrust != NULL) {
507 *secTrust = theTrust;
508 /* we'll release our reference at the end */
509 if (theTrust)
510 CFRetain(theTrust);
511 }
512 SecCmsSignerInfoRef signerInfo =
513 SecCmsSignedDataGetSignerInfo(cmsDecoder->signedData, (int)signerIndex);
514 if(signerInfo == NULL) {
515 /* should never happen */
516 ASSERT(0);
517 dprintf("CMSDecoderCopySignerStatus: no signerInfo\n");
518 ortn = errSecInternalComponent;
519 goto errOut;
520 }
521
522 /* now do the actual cert verify */
523 if(evaluateSecTrust) {
524 evalRtn = SecTrustEvaluate(theTrust, &secTrustResult);
525 if(evalRtn) {
526 /* should never happen */
527 CSSM_PERROR("SecTrustEvaluate", evalRtn);
528 dprintf("CMSDecoderCopySignerStatus: SecTrustEvaluate error\n");
529 ortn = errSecInternalComponent;
530 goto errOut;
531 }
532 switch(secTrustResult) {
533 case kSecTrustResultUnspecified:
534 /* cert chain valid, no special UserTrust assignments */
535 case kSecTrustResultProceed:
536 /* cert chain valid AND user explicitly trusts this */
537 break;
538 case kSecTrustResultDeny:
539 tpVfyStatus = CSSMERR_APPLETP_TRUST_SETTING_DENY;
540 break;
541 case kSecTrustResultConfirm:
542 dprintf("SecTrustEvaluate reported confirm\n");
543 tpVfyStatus = CSSMERR_TP_NOT_TRUSTED;
544 break;
545 default:
546 {
547 /* get low-level TP error */
548 OSStatus tpStatus;
549 ortn = SecTrustGetCssmResultCode(theTrust, &tpStatus);
550 if(ortn) {
551 CSSM_PERROR("SecTrustGetCssmResultCode", ortn);
552 }
553 else {
554 tpVfyStatus = tpStatus;
555 }
556 CSSM_PERROR("TP status after SecTrustEvaluate", tpVfyStatus);
557 break;
558 }
559 } /* switch(secTrustResult) */
560 } /* evaluateSecTrust true */
561 if(certVerifyResultCode != NULL) {
562 *certVerifyResultCode = tpVfyStatus;
563 }
564
565 /* cook up global status based on vfyRtn and tpVfyStatus */
566 if(signerStatus != NULL) {
567 if((vfyRtn == errSecSuccess) && (tpVfyStatus == CSSM_OK)) {
568 *signerStatus = kCMSSignerValid;
569 }
570 else if(vfyRtn != errSecSuccess) {
571 /* this could mean other things, but for now... */
572 *signerStatus = kCMSSignerInvalidSignature;
573 }
574 else {
575 *signerStatus = kCMSSignerInvalidCert;
576 }
577 }
578 errOut:
579 CFRELEASE(theTrust);
580 return ortn;
581 }
582
583 /*
584 * Obtain the email address of signer 'signerIndex' of a CMS message, if
585 * present.
586 *
587 * This cannot be called until after CMSDecoderFinalizeMessage() is called.
588 */
589 OSStatus CMSDecoderCopySignerEmailAddress(
590 CMSDecoderRef cmsDecoder,
591 size_t signerIndex,
592 CFStringRef *signerEmailAddress) /* RETURNED */
593 {
594 if((cmsDecoder == NULL) ||
595 (signerEmailAddress == NULL) ||
596 (cmsDecoder->signedData == NULL) || /* not signed */
597 (signerIndex >= cmsDecoder->numSigners) || /* index out of range */
598 (cmsDecoder->decState != DS_Final)) {
599 return errSecParam;
600 }
601
602 SecCmsSignerInfoRef signerInfo =
603 SecCmsSignedDataGetSignerInfo(cmsDecoder->signedData, (int)signerIndex);
604 if(signerInfo == NULL) {
605 /* should never happen */
606 ASSERT(0);
607 dprintf("CMSDecoderCopySignerEmailAddress: no signerInfo\n");
608 return errSecInternalComponent;
609 }
610
611 /*
612 * This is leaking memory in libsecurityKeychain per Radar 4412699.
613 */
614 *signerEmailAddress = SecCmsSignerInfoGetSignerEmailAddress(signerInfo);
615 return errSecSuccess;
616 }
617
618 /*
619 * Obtain the certificate of signer 'signerIndex' of a CMS message, if
620 * present.
621 *
622 * This cannot be called until after CMSDecoderFinalizeMessage() is called.
623 */
624 OSStatus CMSDecoderCopySignerCert(
625 CMSDecoderRef cmsDecoder,
626 size_t signerIndex,
627 SecCertificateRef *signerCert) /* RETURNED */
628 {
629 if((cmsDecoder == NULL) ||
630 (signerCert == NULL) ||
631 (cmsDecoder->signedData == NULL) || /* not signed */
632 (signerIndex >= cmsDecoder->numSigners) || /* index out of range */
633 (cmsDecoder->decState != DS_Final)) {
634 return errSecParam;
635 }
636
637 SecCmsSignerInfoRef signerInfo =
638 SecCmsSignedDataGetSignerInfo(cmsDecoder->signedData, (int)signerIndex);
639 if(signerInfo == NULL) {
640 /* should never happen */
641 ASSERT(0);
642 dprintf("CMSDecoderCopySignerCertificate: no signerInfo\n");
643 return errSecInternalComponent;
644 }
645 *signerCert = SecCmsSignerInfoGetSigningCertificate(signerInfo, NULL);
646 /* libsecurity_smime does NOT retain that */
647 if(*signerCert == NULL) {
648 /* should never happen */
649 ASSERT(0);
650 dprintf("CMSDecoderCopySignerCertificate: no signerCert\n");
651 return errSecInternalComponent;
652 }
653 CFRetain(*signerCert);
654 return errSecSuccess;
655 }
656
657 /*
658 * Determine whether a CMS message was encrypted, and if so, whether we were
659 * able to decrypt it.
660 */
661 OSStatus CMSDecoderIsContentEncrypted(
662 CMSDecoderRef cmsDecoder,
663 Boolean *wasEncrypted)
664 {
665 if((cmsDecoder == NULL) || (wasEncrypted == NULL)) {
666 return errSecParam;
667 }
668 if(cmsDecoder->decState != DS_Final) {
669 return errSecParam;
670 }
671 *wasEncrypted = cmsDecoder->wasEncrypted;
672 return errSecSuccess;
673 }
674
675 /*
676 * Obtain the eContentType OID for a SignedData's EncapsulatedContentType, if
677 * present.
678 */
679 OSStatus CMSDecoderCopyEncapsulatedContentType(
680 CMSDecoderRef cmsDecoder,
681 CFDataRef *eContentType) /* RETURNED */
682 {
683 if((cmsDecoder == NULL) || (eContentType == NULL)) {
684 return errSecParam;
685 }
686 if(cmsDecoder->decState != DS_Final) {
687 return errSecParam;
688 }
689 if(cmsDecoder->signedData == NULL) {
690 *eContentType = NULL;
691 }
692 else {
693 CSSM_OID *ecOid = cmsDecoder->eContentType;
694 *eContentType = CFDataCreate(NULL, ecOid->Data, ecOid->Length);
695 }
696 return errSecSuccess;
697 }
698
699 /*
700 * Obtain an array of all of the certificates in a message. Elements of the
701 * returned array are SecCertificateRefs. The caller must CFRelease the returned
702 * array.
703 * This cannot be called until after CMSDecoderFinalizeMessage() is called.
704 */
705 OSStatus CMSDecoderCopyAllCerts(
706 CMSDecoderRef cmsDecoder,
707 CFArrayRef *certs) /* RETURNED */
708 {
709 if((cmsDecoder == NULL) || (certs == NULL)) {
710 return errSecParam;
711 }
712 if(cmsDecoder->decState != DS_Final) {
713 return errSecParam;
714 }
715 if(cmsDecoder->signedData == NULL) {
716 /* message wasn't signed */
717 *certs = NULL;
718 return errSecSuccess;
719 }
720
721 /* NULL_terminated array of CSSM_DATA ptrs */
722 CSSM_DATA_PTR *cssmCerts = SecCmsSignedDataGetCertificateList(cmsDecoder->signedData);
723 if((cssmCerts == NULL) || (*cssmCerts == NULL)) {
724 *certs = NULL;
725 return errSecSuccess;
726 }
727
728 CFMutableArrayRef allCerts = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
729 CSSM_DATA_PTR *cssmCert;
730 for(cssmCert=cssmCerts; *cssmCert!=NULL; cssmCert++) {
731 OSStatus ortn;
732 SecCertificateRef cfCert;
733 ortn = SecCertificateCreateFromData(*cssmCert,
734 CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER,
735 &cfCert);
736 if(ortn) {
737 CFRelease(allCerts);
738 return ortn;
739 }
740 CFArrayAppendValue(allCerts, cfCert);
741 /* the array holds the only needed refcount */
742 CFRelease(cfCert);
743 }
744 *certs = allCerts;
745 return errSecSuccess;
746 }
747
748 /*
749 * Obtain the actual message content (payload), if any. If the message was
750 * signed with detached content this will return NULL.
751 * Caller must CFRelease the result.
752 */
753 OSStatus CMSDecoderCopyContent(
754 CMSDecoderRef cmsDecoder,
755 CFDataRef *content) /* RETURNED */
756 {
757 if((cmsDecoder == NULL) || (content == NULL)) {
758 return errSecParam;
759 }
760 if(cmsDecoder->decState != DS_Final) {
761 return errSecParam;
762 }
763 if(cmsDecoder->cmsMsg == NULL) {
764 /* Hmmm....looks like the finalize call failed */
765 return errSecParam;
766 }
767 CSSM_DATA_PTR odata = SecCmsMessageGetContent(cmsDecoder->cmsMsg);
768 if((odata == NULL) || (odata->Length == 0)) {
769 /* i.e., detached content */
770 *content = NULL;
771 return errSecSuccess;
772 }
773 *content = CFDataCreate(NULL, (const UInt8 *)odata->Data, odata->Length);
774 return errSecSuccess;
775 }
776
777 #pragma mark --- SPI declared in CMSPrivate.h ---
778
779 /*
780 * Obtain the SecCmsMessageRef associated with a CMSDecoderRef. Intended
781 * to be called after decoding the message (i.e., after
782 * CMSDecoderFinalizeMessage() to gain finer access to the contents of the
783 * SecCmsMessageRef than is otherwise available via the CMSDecoder interface.
784 * Returns a NULL SecCmsMessageRef if CMSDecoderFinalizeMessage() has not been
785 * called.
786 *
787 * The CMSDecoder retains ownership of the returned SecCmsMessageRef.
788 */
789 OSStatus CMSDecoderGetCmsMessage(
790 CMSDecoderRef cmsDecoder,
791 SecCmsMessageRef *cmsMessage) /* RETURNED */
792 {
793 if((cmsDecoder == NULL) || (cmsMessage == NULL)) {
794 return errSecParam;
795 }
796 /* any state, whether we have a msg or not is OK */
797 *cmsMessage = cmsDecoder->cmsMsg;
798 return errSecSuccess;
799 }
800
801 /*
802 * Optionally specify a SecCmsDecoderRef to use with a CMSDecoderRef.
803 * If this is called, it must be called before the first call to
804 * CMSDecoderUpdateMessage(). The CMSDecoderRef takes ownership of the
805 * incoming SecCmsDecoderRef.
806 */
807 OSStatus CMSDecoderSetDecoder(
808 CMSDecoderRef cmsDecoder,
809 SecCmsDecoderRef decoder)
810 {
811 if((cmsDecoder == NULL) || (decoder == NULL)) {
812 return errSecParam;
813 }
814 switch(cmsDecoder->decState) {
815 case DS_Init:
816 ASSERT(cmsDecoder->decoder == NULL);
817 cmsDecoder->decoder = decoder;
818 cmsDecoder->decState = DS_Updating;
819 return errSecSuccess;
820 case DS_Updating:
821 case DS_Final:
822 return errSecParam;
823 }
824 return errSecSuccess;
825 }
826
827 /*
828 * Obtain the SecCmsDecoderRef associated with a CMSDecoderRef.
829 * Returns a NULL SecCmsDecoderRef if neither CMSDecoderSetDecoder() nor
830 * CMSDecoderUpdateMessage() has been called.
831 * The CMSDecoderRef retains ownership of the SecCmsDecoderRef.
832 */
833 OSStatus CMSDecoderGetDecoder(
834 CMSDecoderRef cmsDecoder,
835 SecCmsDecoderRef *decoder) /* RETURNED */
836 {
837 if((cmsDecoder == NULL) || (decoder == NULL)) {
838 return errSecParam;
839 }
840 /* any state, whether we have a decoder or not is OK */
841 *decoder = cmsDecoder->decoder;
842 return errSecSuccess;
843 }
844
845 /*
846 * Obtain the signing time of signer 'signerIndex' of a CMS message, if
847 * present. This is an unauthenticate time, although it is part of the
848 * signed attributes of the message.
849 *
850 * Returns errSecParam if the CMS message was not signed or if signerIndex
851 * is greater than the number of signers of the message minus one.
852 *
853 * This cannot be called until after CMSDecoderFinalizeMessage() is called.
854 */
855 OSStatus CMSDecoderCopySignerSigningTime(
856 CMSDecoderRef cmsDecoder,
857 size_t signerIndex, /* usually 0 */
858 CFAbsoluteTime *signingTime) /* RETURNED */
859 {
860 OSStatus status = errSecParam;
861 SecCmsMessageRef cmsg;
862 SecCmsSignedDataRef signedData = NULL;
863 int numContentInfos = 0;
864
865 require(cmsDecoder && signingTime, xit);
866 require_noerr(CMSDecoderGetCmsMessage(cmsDecoder, &cmsg), xit);
867 numContentInfos = SecCmsMessageContentLevelCount(cmsg);
868 for (int dex = 0; !signedData && dex < numContentInfos; dex++)
869 {
870 SecCmsContentInfoRef ci = SecCmsMessageContentLevel(cmsg, dex);
871 SECOidTag tag = SecCmsContentInfoGetContentTypeTag(ci);
872 if (tag == SEC_OID_PKCS7_SIGNED_DATA)
873 if ((signedData = SecCmsSignedDataRef(SecCmsContentInfoGetContent(ci))))
874 if (SecCmsSignerInfoRef signerInfo = SecCmsSignedDataGetSignerInfo(signedData, (int)signerIndex))
875 {
876 status = SecCmsSignerInfoGetSigningTime(signerInfo, signingTime);
877 break;
878 }
879 }
880 xit:
881 return status;
882 }
883
884 /*
885 * Obtain the timestamp of signer 'signerIndex' of a CMS message, if
886 * present. This timestamp is an authenticated timestamp provided by
887 * a timestamping authority.
888 *
889 * Returns errSecParam if the CMS message was not signed or if signerIndex
890 * is greater than the number of signers of the message minus one.
891 *
892 * This cannot be called until after CMSDecoderFinalizeMessage() is called.
893 */
894
895 OSStatus CMSDecoderCopySignerTimestamp(
896 CMSDecoderRef cmsDecoder,
897 size_t signerIndex, /* usually 0 */
898 CFAbsoluteTime *timestamp) /* RETURNED */
899 {
900 return CMSDecoderCopySignerTimestampWithPolicy(cmsDecoder, NULL, signerIndex, timestamp);
901 }
902
903 OSStatus CMSDecoderCopySignerTimestampWithPolicy(
904 CMSDecoderRef cmsDecoder,
905 CFTypeRef timeStampPolicy,
906 size_t signerIndex, /* usually 0 */
907 CFAbsoluteTime *timestamp) /* RETURNED */
908 {
909 OSStatus status = errSecParam;
910 SecCmsMessageRef cmsg;
911 SecCmsSignedDataRef signedData = NULL;
912 int numContentInfos = 0;
913
914 require(cmsDecoder && timestamp, xit);
915 require_noerr(CMSDecoderGetCmsMessage(cmsDecoder, &cmsg), xit);
916 numContentInfos = SecCmsMessageContentLevelCount(cmsg);
917 for (int dex = 0; !signedData && dex < numContentInfos; dex++)
918 {
919 SecCmsContentInfoRef ci = SecCmsMessageContentLevel(cmsg, dex);
920 SECOidTag tag = SecCmsContentInfoGetContentTypeTag(ci);
921 if (tag == SEC_OID_PKCS7_SIGNED_DATA)
922 if ((signedData = SecCmsSignedDataRef(SecCmsContentInfoGetContent(ci))))
923 if (SecCmsSignerInfoRef signerInfo = SecCmsSignedDataGetSignerInfo(signedData, (int)signerIndex))
924 {
925 status = SecCmsSignerInfoGetTimestampTimeWithPolicy(signerInfo, timeStampPolicy, timestamp);
926 break;
927 }
928 }
929
930 xit:
931 return status;
932 }
933
934 /*
935 * Obtain an array of the certificates in a timestamp response. Elements of the
936 * returned array are SecCertificateRefs. The caller must CFRelease the returned
937 * array. This timestamp is an authenticated timestamp provided by
938 * a timestamping authority.
939 *
940 * Returns errSecParam if the CMS message was not signed or if signerIndex
941 * is greater than the number of signers of the message minus one. It returns
942 * errSecItemNotFound if no certificates were found.
943 *
944 * This cannot be called until after CMSDecoderFinalizeMessage() is called.
945 */
946 OSStatus CMSDecoderCopySignerTimestampCertificates(
947 CMSDecoderRef cmsDecoder,
948 size_t signerIndex, /* usually 0 */
949 CFArrayRef *certificateRefs) /* RETURNED */
950 {
951 OSStatus status = errSecParam;
952 SecCmsMessageRef cmsg = NULL;
953 SecCmsSignedDataRef signedData = NULL;
954 int numContentInfos = 0;
955 CFIndex tsn = 0;
956 bool good = false;
957
958 require(cmsDecoder && certificateRefs, xit);
959 require_noerr(CMSDecoderGetCmsMessage(cmsDecoder, &cmsg), xit);
960 numContentInfos = SecCmsMessageContentLevelCount(cmsg);
961 for (int dex = 0; !signedData && dex < numContentInfos; dex++)
962 {
963 SecCmsContentInfoRef ci = SecCmsMessageContentLevel(cmsg, dex);
964 SECOidTag tag = SecCmsContentInfoGetContentTypeTag(ci);
965 if (tag == SEC_OID_PKCS7_SIGNED_DATA)
966 if ((signedData = SecCmsSignedDataRef(SecCmsContentInfoGetContent(ci))))
967 if (SecCmsSignerInfoRef signerInfo = SecCmsSignedDataGetSignerInfo(signedData, (int)signerIndex))
968 {
969 CFArrayRef certList = SecCmsSignerInfoGetTimestampCertList(signerInfo);
970 require_action(certList, xit, status = errSecItemNotFound);
971 CFMutableArrayRef certs = CFArrayCreateMutableCopy(kCFAllocatorDefault, CFArrayGetCount(certList), certList);
972
973 if(certs){
974 //reorder certificates:
975 tsn = CFArrayGetCount(certs);
976 good = tsn > 0 && Security::CodeSigning::isAppleCA(SecCertificateRef(CFArrayGetValueAtIndex(certs, tsn-1)));
977
978 if ( good == false )
979 {
980 //change TS certificate ordering.
981 for (CFIndex n = 0; n < tsn; n++)
982 {
983 if (SecCertificateRef tsRoot = SecCertificateRef(CFArrayGetValueAtIndex(certs, n)))
984 if ((good = Security::CodeSigning::isAppleCA(tsRoot))) {
985 CFArrayExchangeValuesAtIndices(certs, n, tsn-1);
986 break;
987 }
988 }
989 }
990
991 *certificateRefs = CFArrayCreateCopy(kCFAllocatorDefault, certs);
992 CFRelease(certs);
993 status = errSecSuccess;
994 }
995 break;
996 }
997 }
998
999
1000 xit:
1001 return status;
1002 }
1003
1004 /*
1005 * Obtain the Hash Agility attribute value of signer 'signerIndex'
1006 * of a CMS message, if present.
1007 *
1008 * Returns errSecParam if the CMS message was not signed or if signerIndex
1009 * is greater than the number of signers of the message minus one.
1010 *
1011 * This cannot be called until after CMSDecoderFinalizeMessage() is called.
1012 */
1013 OSStatus CMSDecoderCopySignerAppleCodesigningHashAgility(
1014 CMSDecoderRef cmsDecoder,
1015 size_t signerIndex, /* usually 0 */
1016 CFDataRef CF_RETURNS_RETAINED *hashAgilityAttrValue) /* RETURNED */
1017 {
1018 OSStatus status = errSecParam;
1019 SecCmsMessageRef cmsg;
1020 SecCmsSignedDataRef signedData = NULL;
1021 int numContentInfos = 0;
1022 CFDataRef returnedValue = NULL;
1023
1024 require(cmsDecoder && hashAgilityAttrValue, xit);
1025 require_noerr(CMSDecoderGetCmsMessage(cmsDecoder, &cmsg), xit);
1026 numContentInfos = SecCmsMessageContentLevelCount(cmsg);
1027 for (int dex = 0; !signedData && dex < numContentInfos; dex++)
1028 {
1029 SecCmsContentInfoRef ci = SecCmsMessageContentLevel(cmsg, dex);
1030 SECOidTag tag = SecCmsContentInfoGetContentTypeTag(ci);
1031 if (tag == SEC_OID_PKCS7_SIGNED_DATA)
1032 if ((signedData = SecCmsSignedDataRef(SecCmsContentInfoGetContent(ci))))
1033 if (SecCmsSignerInfoRef signerInfo = SecCmsSignedDataGetSignerInfo(signedData, (int)signerIndex))
1034 {
1035 status = SecCmsSignerInfoGetAppleCodesigningHashAgility(signerInfo, &returnedValue);
1036 break;
1037 }
1038 }
1039 xit:
1040 if (status == errSecSuccess && returnedValue) {
1041 *hashAgilityAttrValue = (CFDataRef) CFRetain(returnedValue);
1042 } else {
1043 *hashAgilityAttrValue = NULL;
1044 }
1045 return status;
1046 }