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