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