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