/ libsecurity_smime / lib / CMSDecoder.c
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  }