/ OSX / libsecurity_keychain / lib / TrustAdditions.cpp
TrustAdditions.cpp
   1  /*
   2   * Copyright (c) 2002-2009,2011-2015 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  // TrustAdditions.cpp
  26  //
  27  #include "TrustAdditions.h"
  28  #include "TrustKeychains.h"
  29  #include "SecBridge.h"
  30  #include <security_keychain/SecCFTypes.h>
  31  #include <security_keychain/Globals.h>
  32  #include <security_keychain/Certificate.h>
  33  #include <security_keychain/Item.h>
  34  #include <security_keychain/KCCursor.h>
  35  #include <security_keychain/KCUtilities.h>
  36  
  37  #include <sys/stat.h>
  38  #include <sys/file.h>
  39  #include <sys/unistd.h>
  40  #include <string>
  41  #include <AvailabilityMacros.h>
  42  #include <CoreFoundation/CoreFoundation.h>
  43  #include <CommonCrypto/CommonDigest.h>
  44  #include <Security/SecBase.h>
  45  #include <Security/Security.h>
  46  #include <Security/SecCertificatePriv.h>
  47  #include <Security/cssmtype.h>
  48  #include <Security/cssmapplePriv.h>            // for CSSM_APPLE_TP_OCSP_OPTIONS, CSSM_APPLE_TP_OCSP_OPT_FLAGS
  49  
  50  #include <Security/SecTrustPriv.h>
  51  #include <Security/SecTrustSettings.h>
  52  #include <Security/SecTrustSettingsPriv.h>
  53  
  54  //
  55  // Macros
  56  //
  57  #define BEGIN_SECAPI_INTERNAL_CALL \
  58  	try {
  59  #define END_SECAPI_INTERNAL_CALL \
  60  	} /* status is only set on error */ \
  61  	catch (const MacOSError &err) { status=err.osStatus(); } \
  62  	catch (const CommonError &err) { status=SecKeychainErrFromOSStatus(err.osStatus()); } \
  63  	catch (const std::bad_alloc &) { status=errSecAllocate; } \
  64  	catch (...) { status=errSecInternalComponent; }
  65  
  66  #ifdef	NDEBUG
  67  /* this actually compiles to nothing */
  68  #define trustDebug(args...)		secinfo("trust", ## args)
  69  #else
  70  #define trustDebug(args...)		printf(args)
  71  #endif
  72  
  73  //
  74  // Static constants
  75  //
  76  static const char *EV_ROOTS_PLIST_SYSTEM_PATH = "/System/Library/Keychains/EVRoots.plist";
  77  static const char *SYSTEM_ROOTS_PLIST_SYSTEM_PATH = "/System/Library/Keychains/SystemRootCertificates.keychain";
  78  static const char *X509ANCHORS_SYSTEM_PATH = "/System/Library/Keychains/X509Anchors";
  79  
  80  //
  81  // Static functions
  82  //
  83  static CFArrayRef CF_RETURNS_RETAINED _allowedRootCertificatesForOidString(CFStringRef oidString);
  84  static CSSM_DATA_PTR _copyFieldDataForOid(CSSM_OID_PTR oid, CSSM_DATA_PTR cert, CSSM_CL_HANDLE clHandle);
  85  static CFStringRef CF_RETURNS_RETAINED _decimalStringForOid(CSSM_OID_PTR oid);
  86  static CFDictionaryRef CF_RETURNS_RETAINED _evCAOidDict();
  87  static void _freeFieldData(CSSM_DATA_PTR value, CSSM_OID_PTR oid, CSSM_CL_HANDLE clHandle);
  88  static CFStringRef CF_RETURNS_RETAINED _oidStringForCertificatePolicies(const CE_CertPolicies *certPolicies);
  89  static SecCertificateRef _rootCertificateWithSubjectOfCertificate(SecCertificateRef certificate);
  90  static SecCertificateRef _rootCertificateWithSubjectKeyIDOfCertificate(SecCertificateRef certificate);
  91  
  92  // utility function to safely release (and clear) the given CFTypeRef variable.
  93  //
  94  static void SafeCFRelease(void * CF_CONSUMED cfTypeRefPtr)
  95  {
  96  	CFTypeRef *obj = (CFTypeRef *)cfTypeRefPtr;
  97  	if (obj && *obj) {
  98  		CFRelease(*obj);
  99  		*obj = NULL;
 100  	}
 101  }
 102  
 103  // utility function to create a CFDataRef from the contents of the specified file;
 104  // caller must release
 105  //
 106  static CFDataRef CF_RETURNS_RETAINED dataWithContentsOfFile(const char *fileName)
 107  {
 108  	int rtn;
 109  	int fd;
 110  	struct stat	sb;
 111  	size_t fileSize;
 112  	UInt8 *fileData = NULL;
 113  	CFDataRef outCFData = NULL;
 114  
 115  	fd = open(fileName, O_RDONLY, 0);
 116  	if(fd < 0)
 117  		return NULL;
 118  
 119  	rtn = fstat(fd, &sb);
 120  	if(rtn)
 121  		goto errOut;
 122  
 123  	fileSize = (size_t)sb.st_size;
 124  	fileData = (UInt8 *) malloc(fileSize);
 125  	if(fileData == NULL)
 126  		goto errOut;
 127  
 128  	rtn = (int)lseek(fd, 0, SEEK_SET);
 129  	if(rtn < 0)
 130  		goto errOut;
 131  
 132  	rtn = (int)read(fd, fileData, fileSize);
 133  	if(rtn != (int)fileSize) {
 134  		rtn = EIO;
 135  	} else {
 136  		rtn = 0;
 137  		outCFData = CFDataCreate(NULL, fileData, fileSize);
 138  	}
 139  errOut:
 140  	close(fd);
 141  	if (fileData) {
 142  		free(fileData);
 143  	}
 144  	return outCFData;
 145  }
 146  
 147  // returns a SecKeychainRef for the system root certificate store; caller must release
 148  //
 149  static SecKeychainRef systemRootStore()
 150  {
 151      SecKeychainStatus keychainStatus = 0;
 152      SecKeychainRef systemRoots = NULL;
 153  	OSStatus status = errSecSuccess;
 154  	// note: Sec* APIs are not re-entrant due to the API lock
 155  	// status = SecKeychainOpen(SYSTEM_ROOTS_PLIST_SYSTEM_PATH, &systemRoots);
 156  	BEGIN_SECAPI_INTERNAL_CALL
 157  	systemRoots=globals().storageManager.make(SYSTEM_ROOTS_PLIST_SYSTEM_PATH, false)->handle();
 158  	END_SECAPI_INTERNAL_CALL
 159  
 160  	// SecKeychainOpen will return errSecSuccess even if the file didn't exist on disk.
 161  	// We need to do a further check using SecKeychainGetStatus().
 162      if (!status && systemRoots) {
 163  		// note: Sec* APIs are not re-entrant due to the API lock
 164  		// status = SecKeychainGetStatus(systemRoots, &keychainStatus);
 165  		BEGIN_SECAPI_INTERNAL_CALL
 166  		keychainStatus=(SecKeychainStatus)Keychain::optional(systemRoots)->status();
 167  		END_SECAPI_INTERNAL_CALL
 168  	}
 169      if (status || !systemRoots) {
 170  	    // SystemRootCertificates.keychain can't be opened; look in X509Anchors instead.
 171          SafeCFRelease(&systemRoots);
 172  		// note: Sec* APIs are not re-entrant due to the API lock
 173          // status = SecKeychainOpen(X509ANCHORS_SYSTEM_PATH, &systemRoots);
 174  		BEGIN_SECAPI_INTERNAL_CALL
 175  		systemRoots=globals().storageManager.make(X509ANCHORS_SYSTEM_PATH, false)->handle();
 176  		END_SECAPI_INTERNAL_CALL
 177          // SecKeychainOpen will return errSecSuccess even if the file didn't exist on disk.
 178  		// We need to do a further check using SecKeychainGetStatus().
 179          if (!status && systemRoots) {
 180  			// note: Sec* APIs are not re-entrant due to the API lock
 181              // status = SecKeychainGetStatus(systemRoots, &keychainStatus);
 182  			BEGIN_SECAPI_INTERNAL_CALL
 183  			keychainStatus=(SecKeychainStatus)Keychain::optional(systemRoots)->status();
 184  			END_SECAPI_INTERNAL_CALL
 185  		}
 186      }
 187      if (status || !systemRoots) {
 188  		// Cannot get root certificates if there is no trusted system root certificate store.
 189          SafeCFRelease(&systemRoots);
 190          return NULL;
 191      }
 192  	return systemRoots;
 193  }
 194  
 195  // returns a CFDictionaryRef created from the specified XML plist file; caller must release
 196  //
 197  static CFDictionaryRef CF_RETURNS_RETAINED dictionaryWithContentsOfPlistFile(const char *fileName)
 198  {
 199  	CFDictionaryRef resultDict = NULL;
 200  	CFDataRef fileData = dataWithContentsOfFile(fileName);
 201  	if (fileData) {
 202  		CFPropertyListRef xmlPlist = CFPropertyListCreateFromXMLData(NULL, fileData, kCFPropertyListImmutable, NULL);
 203  		if (xmlPlist && CFGetTypeID(xmlPlist) == CFDictionaryGetTypeID()) {
 204  			resultDict = (CFDictionaryRef)xmlPlist;
 205  		} else {
 206  			SafeCFRelease(&xmlPlist);
 207  		}
 208  		SafeCFRelease(&fileData);
 209  	}
 210  	return resultDict;
 211  }
 212  
 213  // returns the Organization component of the given certificate's subject name,
 214  // or nil if that component could not be found. Caller must release the string.
 215  //
 216  static CFStringRef organizationNameForCertificate(SecCertificateRef certificate)
 217  {
 218      CFStringRef organizationName = nil;
 219  	OSStatus status = errSecSuccess;
 220  
 221  #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_4
 222      CSSM_OID_PTR oidPtr = (CSSM_OID_PTR) &CSSMOID_OrganizationName;
 223  	// note: Sec* APIs are not re-entrant due to the API lock
 224  	// status = SecCertificateCopySubjectComponent(certificate, oidPtr, &organizationName);
 225  	BEGIN_SECAPI_INTERNAL_CALL
 226  	organizationName = Certificate::required(certificate)->distinguishedName(&CSSMOID_X509V1SubjectNameCStruct, oidPtr);
 227  	END_SECAPI_INTERNAL_CALL
 228      if (status) {
 229          return (CFStringRef)NULL;
 230  	}
 231  #else
 232      // SecCertificateCopySubjectComponent() doesn't exist on Tiger, so we have
 233  	// to go get the CSSMOID_OrganizationName the hard way, ourselves.
 234      CSSM_DATA_PTR *fieldValues = NULL;
 235  	// note: Sec* APIs are not re-entrant due to the API lock
 236      // status = SecCertificateCopyFieldValues(certificate, &CSSMOID_X509V1SubjectNameCStruct, &fieldValues);
 237  	BEGIN_SECAPI_INTERNAL_CALL
 238  	fieldValues = Certificate::required(certificate)->copyFieldValues(&CSSMOID_X509V1SubjectNameCStruct);
 239  	END_SECAPI_INTERNAL_CALL
 240      if (*fieldValues == NULL) {
 241          return (CFStringRef)NULL;
 242  	}
 243      if (status || (*fieldValues)->Length == 0 || (*fieldValues)->Data == NULL) {
 244  		// note: Sec* APIs are not re-entrant due to the API lock
 245  		// status = SecCertificateReleaseFieldValues(certificate, &CSSMOID_X509V1SubjectNameCStruct, fieldValues);
 246  		BEGIN_SECAPI_INTERNAL_CALL
 247  		Certificate::required(certificate)->releaseFieldValues(&CSSMOID_X509V1SubjectNameCStruct, fieldValues);
 248  		END_SECAPI_INTERNAL_CALL
 249          return (CFStringRef)NULL;
 250      }
 251  
 252      CSSM_X509_NAME_PTR x509Name = (CSSM_X509_NAME_PTR)(*fieldValues)->Data;
 253  
 254      // Iterate over all the relative distinguished name (RDN) entries...
 255      unsigned rdnIndex = 0;
 256      bool foundIt = FALSE;
 257      for (rdnIndex = 0; rdnIndex < x509Name->numberOfRDNs; rdnIndex++) {
 258          CSSM_X509_RDN *rdnPtr = x509Name->RelativeDistinguishedName + rdnIndex;
 259  
 260          // And then iterate over the attribute-value pairs of each RDN, looking for a CSSMOID_OrganizationName.
 261          unsigned pairIndex;
 262          for (pairIndex = 0; pairIndex < rdnPtr->numberOfPairs; pairIndex++) {
 263              CSSM_X509_TYPE_VALUE_PAIR *pair = rdnPtr->AttributeTypeAndValue + pairIndex;
 264  
 265              // If this pair isn't the organization name, move on to check the next one.
 266              if (!oidsAreEqual(&pair->type, &CSSMOID_OrganizationName))
 267                  continue;
 268  
 269              // We've found the organization name. Convert value to a string (eg, "Apple Inc.")
 270              // Note: there can be more than one organization name in any given CSSM_X509_RDN.
 271  			// In practice, it's OK to use the first one. In future, if we have a means for
 272  			// displaying more than one name, this would be where they should be collected
 273  			// into an array.
 274              switch (pair->valueType) {
 275                  case BER_TAG_PKIX_UTF8_STRING:
 276                  case BER_TAG_PKIX_UNIVERSAL_STRING:
 277                  case BER_TAG_GENERAL_STRING:
 278  					organizationName = CFStringCreateWithBytes(NULL, pair->value.Data, pair->value.Length, kCFStringEncodingUTF8, FALSE);
 279                      break;
 280                  case BER_TAG_PRINTABLE_STRING:
 281                  case BER_TAG_IA5_STRING:
 282  					organizationName = CFStringCreateWithBytes(NULL, pair->value.Data, pair->value.Length, kCFStringEncodingASCII, FALSE);
 283                      break;
 284                  case BER_TAG_T61_STRING:
 285                  case BER_TAG_VIDEOTEX_STRING:
 286                  case BER_TAG_ISO646_STRING:
 287  					organizationName = CFStringCreateWithBytes(NULL, pair->value.Data, pair->value.Length, kCFStringEncodingUTF8, FALSE);
 288                      // If the data cannot be represented as a UTF-8 string, fall back to ISO Latin 1
 289                      if (!organizationName) {
 290  						organizationName = CFStringCreateWithBytes(NULL, pair->value.Data, pair->value.Length, kCFStringEncodingISOLatin1, FALSE);
 291                      }
 292  					break;
 293                  case BER_TAG_PKIX_BMP_STRING:
 294  					organizationName = CFStringCreateWithBytes(NULL, pair->value.Data, pair->value.Length, kCFStringEncodingUnicode, FALSE);
 295                      break;
 296                  default:
 297                      break;
 298              }
 299  
 300              // If we found the organization name, there's no need to keep looping.
 301              if (organizationName) {
 302                  foundIt = TRUE;
 303                  break;
 304              }
 305          }
 306          if (foundIt)
 307              break;
 308      }
 309  	// note: Sec* APIs are not re-entrant due to the API lock
 310  	// status = SecCertificateReleaseFieldValues(certificate, &CSSMOID_X509V1SubjectNameCStruct, fieldValues);
 311  	BEGIN_SECAPI_INTERNAL_CALL
 312  	Certificate::required(certificate)->releaseFieldValues(&CSSMOID_X509V1SubjectNameCStruct, fieldValues);
 313  	END_SECAPI_INTERNAL_CALL
 314  #endif
 315      return organizationName;
 316  }
 317  
 318  #if !defined(NDEBUG)
 319  void showCertSKID(const void *value, void *context);
 320  #endif
 321  
 322  static ModuleNexus<Mutex> gPotentialEVChainWithCertificatesMutex;
 323  
 324  // returns a CFArrayRef of SecCertificateRef instances; caller must release the returned array
 325  //
 326  CFArrayRef potentialEVChainWithCertificates(CFArrayRef certificates)
 327  {
 328  	StLock<Mutex> _(gPotentialEVChainWithCertificatesMutex());
 329  
 330      // Given a partial certificate chain (which may or may not include the root,
 331      // and does not have a guaranteed order except the first item is the leaf),
 332      // examine intermediate certificates to see if they are cross-certified (i.e.
 333      // have the same subject and public key as a trusted root); if so, remove the
 334      // intermediate from the returned certificate array.
 335  
 336  	CFIndex chainIndex, chainLen = (certificates) ? CFArrayGetCount(certificates) : 0;
 337  	secinfo("trusteval", "potentialEVChainWithCertificates: chainLen: %ld", chainLen);
 338      if (chainLen < 2) {
 339  		if (certificates) {
 340  			CFRetain(certificates);
 341  		}
 342          return certificates;
 343  	}
 344  
 345  	CFMutableArrayRef certArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
 346      for (chainIndex = 0; chainIndex < chainLen; chainIndex++) {
 347          SecCertificateRef aCert = (SecCertificateRef) CFArrayGetValueAtIndex(certificates, chainIndex);
 348          SecCertificateRef replacementCert = NULL;
 349  		secinfo("trusteval", "potentialEVChainWithCertificates: examining chainIndex: %ld", chainIndex);
 350          if (chainIndex > 0) {
 351              // if this is not the leaf, then look for a possible replacement root to end the chain
 352  			// Try lookup using Subject Key ID first
 353  			replacementCert = _rootCertificateWithSubjectKeyIDOfCertificate(aCert);
 354  			if (!replacementCert)
 355  			{
 356  				secinfo("trusteval", "  not found using SKID, try by subject");
 357              replacementCert = _rootCertificateWithSubjectOfCertificate(aCert);
 358          }
 359          }
 360          if (!replacementCert) {
 361  			secinfo("trusteval", "  No replacement found using SKID or subject; keeping original intermediate");
 362              CFArrayAppendValue(certArray, aCert);
 363          }
 364          SafeCFRelease(&replacementCert);
 365      }
 366  	secinfo("trusteval", "potentialEVChainWithCertificates: exit: new chainLen: %ld", CFArrayGetCount(certArray));
 367  #if !defined(NDEBUG)
 368  	CFArrayApplyFunction(certArray, CFRangeMake(0, CFArrayGetCount(certArray)), showCertSKID, NULL);
 369  #endif
 370  
 371      return certArray;
 372  }
 373  
 374  // returns a reference to a root certificate, if one can be found in the
 375  // system root store whose subject name and public key are identical to
 376  // that of the provided certificate, otherwise returns nil.
 377  //
 378  static SecCertificateRef _rootCertificateWithSubjectOfCertificate(SecCertificateRef certificate)
 379  {
 380      if (!certificate) {
 381          return NULL;
 382      }
 383  
 384      StLock<Mutex> _(SecTrustKeychainsGetMutex());
 385  
 386      // get data+length for the provided certificate
 387      CSSM_CL_HANDLE clHandle = 0;
 388      CSSM_DATA certData = { 0, NULL };
 389  	OSStatus status = errSecSuccess;
 390  	// note: Sec* APIs are not re-entrant due to the API lock
 391  	// status = SecCertificateGetCLHandle(certificate, &clHandle);
 392  	BEGIN_SECAPI_INTERNAL_CALL
 393  	clHandle = Certificate::required(certificate)->clHandle();
 394  	END_SECAPI_INTERNAL_CALL
 395  	if (status)
 396  		return NULL;
 397  	// note: Sec* APIs are not re-entrant due to the API lock
 398  	// status = SecCertificateGetData(certificate, &certData);
 399  	BEGIN_SECAPI_INTERNAL_CALL
 400  	certData = Certificate::required(certificate)->data();
 401  	END_SECAPI_INTERNAL_CALL
 402  	if (status)
 403  		return NULL;
 404  
 405  	// get system roots keychain reference
 406      SecKeychainRef systemRoots = systemRootStore();
 407  	if (!systemRoots)
 408  		return NULL;
 409  
 410      // copy (normalized) subject for the provided certificate
 411      const CSSM_OID_PTR oidPtr = (const CSSM_OID_PTR) &CSSMOID_X509V1SubjectName;
 412      const CSSM_DATA_PTR subjectDataPtr = _copyFieldDataForOid(oidPtr, &certData, clHandle);
 413      if (!subjectDataPtr)
 414          return NULL;
 415  
 416      // copy public key for the provided certificate
 417      SecKeyRef keyRef = NULL;
 418      SecCertificateRef resultCert = NULL;
 419  	// note: Sec* APIs are not re-entrant due to the API lock
 420  	BEGIN_SECAPI_INTERNAL_CALL
 421  	keyRef = Certificate::required(certificate)->publicKey()->handle();
 422  	END_SECAPI_INTERNAL_CALL
 423      if (!status) {
 424          const CSSM_KEY *cssmKey = NULL;
 425  		// note: Sec* APIs are not re-entrant due to the API lock
 426  		// status = SecKeyGetCSSMKey(keyRef, &cssmKey);
 427  		BEGIN_SECAPI_INTERNAL_CALL
 428  		cssmKey = KeyItem::required(keyRef)->key();
 429  		END_SECAPI_INTERNAL_CALL
 430          if (!status) {
 431              // get SHA-1 hash of the public key
 432              uint8 buf[CC_SHA1_DIGEST_LENGTH];
 433              CSSM_DATA digest = { sizeof(buf), buf };
 434  			if (!cssmKey || !cssmKey->KeyData.Data || !cssmKey->KeyData.Length) {
 435  				status = errSecParam;
 436  			} else {
 437  				CC_SHA1(cssmKey->KeyData.Data, (CC_LONG)cssmKey->KeyData.Length, buf);
 438  			}
 439              if (!status) {
 440                  // set up attribute vector (each attribute consists of {tag, length, pointer})
 441                  // we want to match on the public key hash and the normalized subject name
 442                  // as well as ensure that the issuer matches the subject
 443                  SecKeychainAttribute attrs[] = {
 444                      { kSecPublicKeyHashItemAttr, (UInt32)digest.Length, (void *)digest.Data },
 445                      { kSecSubjectItemAttr, (UInt32)subjectDataPtr->Length, (void *)subjectDataPtr->Data },
 446                      { kSecIssuerItemAttr, (UInt32)subjectDataPtr->Length, (void *)subjectDataPtr->Data }
 447                  };
 448                  const SecKeychainAttributeList attributes = { sizeof(attrs) / sizeof(attrs[0]), attrs };
 449                  SecKeychainSearchRef searchRef = NULL;
 450  				// note: Sec* APIs are not re-entrant due to the API lock
 451  				// status = SecKeychainSearchCreateFromAttributes(systemRoots, kSecCertificateItemClass, &attributes, &searchRef);
 452  				BEGIN_SECAPI_INTERNAL_CALL
 453  				StorageManager::KeychainList keychains;
 454  				globals().storageManager.optionalSearchList(systemRoots, keychains);
 455  				KCCursor cursor(keychains, kSecCertificateItemClass, &attributes);
 456  				searchRef = cursor->handle();
 457  				END_SECAPI_INTERNAL_CALL
 458                  if (!status && searchRef) {
 459                      SecKeychainItemRef certRef = nil;
 460  					// note: Sec* APIs are not re-entrant due to the API lock
 461  					// status = SecKeychainSearchCopyNext(searchRef, &certRef); // only need the first one that matches
 462  					BEGIN_SECAPI_INTERNAL_CALL
 463  					Item item;
 464  					if (!KCCursorImpl::required(searchRef)->next(item)) {
 465  						status=errSecItemNotFound;
 466  					} else {
 467  						certRef=item->handle();
 468  					}
 469  					END_SECAPI_INTERNAL_CALL
 470                      if (!status)
 471                          resultCert = (SecCertificateRef)certRef; // caller must release
 472                      SafeCFRelease(&searchRef);
 473                  }
 474              }
 475          }
 476      }
 477      _freeFieldData(subjectDataPtr, oidPtr, clHandle);
 478      SafeCFRelease(&keyRef);
 479  	SafeCFRelease(&systemRoots);
 480  
 481      return resultCert;
 482  }
 483  
 484  
 485  #if !defined(NDEBUG)
 486  static void logSKID(const char *msg, const CssmData &subjectKeyID)
 487  {
 488  	const unsigned char *px = (const unsigned char *)subjectKeyID.data();
 489  	char buffer[256]={0,};
 490  	char bytes[16];
 491  	if (px && msg)
 492  	{
 493  		strcpy(buffer, msg);
 494  		for (unsigned int ix=0; ix<20; ix++)
 495  		{
 496  			sprintf(bytes, "%02X", px[ix]);
 497  			strcat(buffer, bytes);
 498  		}
 499  		secinfo("trusteval", " SKID: %s",buffer);
 500  	}
 501  }
 502  
 503  void showCertSKID(const void *value, void *context)
 504  {
 505  	SecCertificateRef certificate = (SecCertificateRef)value;
 506  	OSStatus status = errSecSuccess;
 507  	BEGIN_SECAPI_INTERNAL_CALL
 508  	const CssmData &subjectKeyID = Certificate::required(certificate)->subjectKeyIdentifier();
 509  	logSKID("subjectKeyID: ", subjectKeyID);
 510  	END_SECAPI_INTERNAL_CALL
 511  }
 512  #endif
 513  
 514  // returns a reference to a root certificate, if one can be found in the
 515  // system root store whose subject key ID are identical to
 516  // that of the provided certificate, otherwise returns nil.
 517  //
 518  static SecCertificateRef _rootCertificateWithSubjectKeyIDOfCertificate(SecCertificateRef certificate)
 519  {
 520      SecCertificateRef resultCert = NULL;
 521  	OSStatus status = errSecSuccess;
 522  
 523      if (!certificate) {
 524          return NULL;
 525      }
 526  
 527  	StLock<Mutex> _(SecTrustKeychainsGetMutex());
 528  
 529  	// get system roots keychain reference
 530      SecKeychainRef systemRoots = systemRootStore();
 531  	if (!systemRoots)
 532  		return NULL;
 533  
 534  	StorageManager::KeychainList keychains;
 535  	globals().storageManager.optionalSearchList(systemRoots, keychains);
 536  
 537  	BEGIN_SECAPI_INTERNAL_CALL
 538  	const CssmData &subjectKeyID = Certificate::required(certificate)->subjectKeyIdentifier();
 539  #if !defined(NDEBUG)
 540  	logSKID("search for SKID: ", subjectKeyID);
 541  #endif
 542  	// caller must release
 543  	resultCert = Certificate::required(certificate)->findBySubjectKeyID(keychains, subjectKeyID)->handle();
 544  #if !defined(NDEBUG)
 545  	logSKID("  found SKID: ", subjectKeyID);
 546  #endif
 547  	END_SECAPI_INTERNAL_CALL
 548  
 549  	SafeCFRelease(&systemRoots);
 550  
 551      return resultCert;
 552  }
 553  
 554  // returns an array of possible root certificates (SecCertificateRef instances)
 555  // for the given EV OID (a hex string); caller must release the array
 556  //
 557  static
 558  CFArrayRef CF_RETURNS_RETAINED _possibleRootCertificatesForOidString(CFStringRef oidString)
 559  {
 560  	StLock<Mutex> _(SecTrustKeychainsGetMutex());
 561  
 562      if (!oidString) {
 563          return NULL;
 564      }
 565  	CFDictionaryRef evOidDict = _evCAOidDict();
 566  	if (!evOidDict)
 567  		return NULL;
 568  	CFArrayRef possibleCertificateHashes = (CFArrayRef) CFDictionaryGetValue(evOidDict, oidString);
 569      SecKeychainRef systemRoots = systemRootStore();
 570      if (!possibleCertificateHashes || !systemRoots) {
 571  		SafeCFRelease(&evOidDict);
 572          return NULL;
 573  	}
 574  
 575  	CFMutableArrayRef possibleRootCertificates = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
 576  	CFIndex hashCount = CFArrayGetCount(possibleCertificateHashes);
 577  	secinfo("evTrust", "_possibleRootCertificatesForOidString: %d possible hashes", (int)hashCount);
 578  
 579  	OSStatus status = errSecSuccess;
 580  	SecKeychainSearchRef searchRef = NULL;
 581  	// note: Sec* APIs are not re-entrant due to the API lock
 582  	// status = SecKeychainSearchCreateFromAttributes(systemRoots, kSecCertificateItemClass, NULL, &searchRef);
 583  	BEGIN_SECAPI_INTERNAL_CALL
 584  	StorageManager::KeychainList keychains;
 585  	globals().storageManager.optionalSearchList(systemRoots, keychains);
 586  	KCCursor cursor(keychains, kSecCertificateItemClass, NULL);
 587  	searchRef = cursor->handle();
 588  	END_SECAPI_INTERNAL_CALL
 589  	if (searchRef) {
 590  		while (!status) {
 591  			SecKeychainItemRef certRef = NULL;
 592  			// note: Sec* APIs are not re-entrant due to the API lock
 593  			// status = SecKeychainSearchCopyNext(searchRef, &certRef);
 594  			BEGIN_SECAPI_INTERNAL_CALL
 595  			Item item;
 596  			if (!KCCursorImpl::required(searchRef)->next(item)) {
 597  				certRef=NULL;
 598  				status=errSecItemNotFound;
 599  			} else {
 600  				certRef=item->handle();
 601  			}
 602  			END_SECAPI_INTERNAL_CALL
 603  			if (status || !certRef) {
 604  				break;
 605  			}
 606  
 607  			CSSM_DATA certData = { 0, NULL };
 608  			// note: Sec* APIs are not re-entrant due to the API lock
 609  			// status = SecCertificateGetData((SecCertificateRef) certRef, &certData);
 610  			BEGIN_SECAPI_INTERNAL_CALL
 611  			certData = Certificate::required((SecCertificateRef)certRef)->data();
 612  			END_SECAPI_INTERNAL_CALL
 613  			if (!status) {
 614  				uint8 buf[CC_SHA1_DIGEST_LENGTH];
 615  				CSSM_DATA digest = { sizeof(buf), buf };
 616  				if (!certData.Data || !certData.Length) {
 617  					status = errSecParam;
 618  				} else {
 619  					CC_SHA1(certData.Data, (CC_LONG)certData.Length, buf);
 620  				}
 621  				if (!status) {
 622  					CFDataRef hashData = CFDataCreateWithBytesNoCopy(NULL, digest.Data, digest.Length, kCFAllocatorNull);
 623  					if (hashData && CFArrayContainsValue(possibleCertificateHashes, CFRangeMake(0, hashCount), hashData)) {
 624  						CFArrayAppendValue(possibleRootCertificates, certRef);
 625  					}
 626  					SafeCFRelease(&hashData);
 627  				}
 628  			}
 629  			SafeCFRelease(&certRef);
 630  		}
 631      }
 632  	SafeCFRelease(&searchRef);
 633      SafeCFRelease(&systemRoots);
 634  	SafeCFRelease(&evOidDict);
 635  
 636      return possibleRootCertificates;
 637  }
 638  
 639  // returns an array of allowed root certificates (SecCertificateRef instances)
 640  // for the given EV OID (a hex string); caller must release the array.
 641  // This differs from _possibleRootCertificatesForOidString in that each possible
 642  // certificate is further checked for trust settings, so we don't include
 643  // a certificate which is untrusted (or explicitly distrusted).
 644  //
 645  CFArrayRef _allowedRootCertificatesForOidString(CFStringRef oidString)
 646  {
 647  	CFMutableArrayRef allowedRootCertificates = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
 648  	CFArrayRef possibleRootCertificates = _possibleRootCertificatesForOidString(oidString);
 649  	if (possibleRootCertificates) {
 650  		CFIndex idx, count = CFArrayGetCount(possibleRootCertificates);
 651  		for (idx=0; idx<count; idx++) {
 652  			SecCertificateRef cert = (SecCertificateRef) CFArrayGetValueAtIndex(possibleRootCertificates, idx);
 653  			/* Need a unified SecCertificateRef instance to hand to SecTrustSettingsCertHashStrFromCert */
 654  			SecCertificateRef certRef = SecCertificateCreateFromItemImplInstance(cert);
 655  			CFStringRef hashStr = SecTrustSettingsCertHashStrFromCert(certRef);
 656  			if (hashStr) {
 657  				bool foundMatch = false;
 658  				bool foundAny = false;
 659  				CSSM_RETURN *errors = NULL;
 660  				uint32 errorCount = 0;
 661  				SecTrustSettingsDomain foundDomain = kSecTrustSettingsDomainUser;
 662  				SecTrustSettingsResult result = kSecTrustSettingsResultInvalid;
 663  				OSStatus status = SecTrustSettingsEvaluateCert(
 664  					hashStr,		/* certHashStr */
 665  					NULL,			/* policyOID (optional) */
 666  					NULL,			/* policyString (optional) */
 667  					0,				/* policyStringLen */
 668  					0,				/* keyUsage */
 669  					true,			/* isRootCert */
 670  					&foundDomain,	/* foundDomain */
 671  					&errors,		/* allowedErrors */
 672  					&errorCount,	/* numAllowedErrors */
 673  					&result,		/* resultType */
 674  					&foundMatch,	/* foundMatchingEntry */
 675  					&foundAny);		/* foundAnyEntry */
 676  
 677  				if (status == errSecSuccess) {
 678  					secinfo("evTrust", "_allowedRootCertificatesForOidString: cert %lu has result %d from domain %d",
 679  						idx, (int)result, (int)foundDomain);
 680  					// Root certificates must be trusted by the system (and not have
 681  					// any explicit trust overrides) to be allowed for EV use.
 682  					if (foundMatch && foundDomain == kSecTrustSettingsDomainSystem &&
 683  						result == kSecTrustSettingsResultTrustRoot) {
 684  						CFArrayAppendValue(allowedRootCertificates, cert);
 685  					}
 686  				} else {
 687  					secinfo("evTrust", "_allowedRootCertificatesForOidString: cert %lu SecTrustSettingsEvaluateCert error %d",
 688  						idx, (int)status);
 689  				}
 690  				if (errors) {
 691  					free(errors);
 692  				}
 693  				CFRelease(hashStr);
 694  			}
 695  			if (certRef) {
 696  				CFRelease(certRef);
 697  			}
 698  		}
 699  		CFRelease(possibleRootCertificates);
 700  	}
 701  
 702  	return allowedRootCertificates;
 703  }
 704  
 705  // return a CSSM_DATA_PTR containing field data; caller must release with _freeFieldData
 706  //
 707  static CSSM_DATA_PTR _copyFieldDataForOid(CSSM_OID_PTR oid, CSSM_DATA_PTR cert, CSSM_CL_HANDLE clHandle)
 708  {
 709      uint32 numFields = 0;
 710      CSSM_HANDLE results = 0;
 711      CSSM_DATA_PTR value = 0;
 712      CSSM_RETURN crtn = CSSM_CL_CertGetFirstFieldValue(clHandle, cert, oid, &results, &numFields, &value);
 713  
 714  	// we aren't going to look for any further fields, so free the results handle immediately
 715  	if (results) {
 716  		CSSM_CL_CertAbortQuery(clHandle, results);
 717  	}
 718  
 719      return (crtn || !numFields) ? NULL : value;
 720  }
 721  
 722  // Some errors are ignorable errors because they do not indicate a problem
 723  // with the certificate itself, but rather a problem getting a response from
 724  // the CA server. The EV Certificate spec does not mandate that the application
 725  // software vendor *must* get a response from OCSP or CRL, it is a "best
 726  // attempt" approach which will not fail if the server does not respond.
 727  //
 728  // The EV spec (26. EV Certificate Status Checking) says that CAs have to
 729  // maintain either a CRL or OCSP server. They are not required to maintain
 730  // an OCSP server until after Dec 31, 2010.
 731  //
 732  // As to the responsibility of the application software vendor to perform
 733  // revocation checking, this is only covered by the following section (37.2.):
 734  //
 735  // This [indemnification of Application Software Vendors]
 736  // shall not apply, however, to any claim, damages, or loss
 737  // suffered by such Application Software Vendor related to an EV Certificate
 738  // issued by the CA where such claim, damage, or loss was directly caused by
 739  // such Application Software Vendor’s software displaying as not trustworthy an
 740  // EV Certificate that is still valid, or displaying as trustworthy: (1) an EV
 741  // Certificate that has expired, or (2) an EV Certificate that has been revoked
 742  // (but only in cases where the revocation status is currently available from the
 743  // CA online, and the browser software either failed to check such status or
 744  // ignored an indication of revoked status).
 745  //
 746  // The last section describes what a browser is required to do: it must attempt
 747  // to check revocation status (as indicated by the OCSP or CRL server info in
 748  // the certificate), and it cannot ignore an indication of revoked status
 749  // (i.e. a positive thumbs-down response from the server, which would be a
 750  // different error than the ones being skipped.) However, given that we meet
 751  // those requirements, if the revocation server is down or will not give us a
 752  // response for whatever reason, that is not our problem.
 753  
 754  bool isRevocationServerMetaError(CSSM_RETURN statusCode)
 755  {
 756     switch (statusCode) {
 757         case CSSMERR_APPLETP_CRL_NOT_FOUND:             // 13. CRL not found
 758         case CSSMERR_APPLETP_CRL_SERVER_DOWN:           // 14. CRL server down
 759         case CSSMERR_APPLETP_OCSP_UNAVAILABLE:          // 33. OCSP service unavailable
 760         case CSSMERR_APPLETP_NETWORK_FAILURE:           // 36. General network failure
 761         case CSSMERR_APPLETP_OCSP_RESP_MALFORMED_REQ:   // 41. OCSP responder status: malformed request
 762         case CSSMERR_APPLETP_OCSP_RESP_INTERNAL_ERR:    // 42. OCSP responder status: internal error
 763         case CSSMERR_APPLETP_OCSP_RESP_TRY_LATER:       // 43. OCSP responder status: try later
 764         case CSSMERR_APPLETP_OCSP_RESP_SIG_REQUIRED:    // 44. OCSP responder status: signature required
 765         case CSSMERR_APPLETP_OCSP_RESP_UNAUTHORIZED:    // 45. OCSP responder status: unauthorized
 766             return true;
 767         default:
 768             return false;
 769     }
 770  }
 771  
 772  // returns true if the given status code is related to performing an OCSP revocation check
 773  //
 774  bool isOCSPStatusCode(CSSM_RETURN statusCode)
 775  {
 776      switch (statusCode)
 777      {
 778          case CSSMERR_APPLETP_OCSP_BAD_RESPONSE:         // 31. Unparseable OCSP response
 779          case CSSMERR_APPLETP_OCSP_BAD_REQUEST:          // 32. Unparseable OCSP request
 780          case CSSMERR_APPLETP_OCSP_RESP_MALFORMED_REQ:   // 41. OCSP responder status: malformed request
 781          case CSSMERR_APPLETP_OCSP_UNAVAILABLE:          // 33. OCSP service unavailable
 782          case CSSMERR_APPLETP_OCSP_STATUS_UNRECOGNIZED:  // 34. OCSP status: cert unrecognized
 783          case CSSMERR_APPLETP_OCSP_NOT_TRUSTED:          // 37. OCSP response not verifiable to anchor or root
 784          case CSSMERR_APPLETP_OCSP_INVALID_ANCHOR_CERT:  // 38. OCSP response verified to untrusted root
 785          case CSSMERR_APPLETP_OCSP_SIG_ERROR:            // 39. OCSP response signature error
 786          case CSSMERR_APPLETP_OCSP_NO_SIGNER:            // 40. No signer for OCSP response found
 787          case CSSMERR_APPLETP_OCSP_RESP_INTERNAL_ERR:    // 42. OCSP responder status: internal error
 788          case CSSMERR_APPLETP_OCSP_RESP_TRY_LATER:       // 43. OCSP responder status: try later
 789          case CSSMERR_APPLETP_OCSP_RESP_SIG_REQUIRED:    // 44. OCSP responder status: signature required
 790          case CSSMERR_APPLETP_OCSP_RESP_UNAUTHORIZED:    // 45. OCSP responder status: unauthorized
 791          case CSSMERR_APPLETP_OCSP_NONCE_MISMATCH:       // 46. OCSP response nonce did not match request
 792              return true;
 793          default:
 794              return false;
 795      }
 796  }
 797  
 798  // returns true if the given status code is related to performing a CRL revocation check
 799  //
 800  bool isCRLStatusCode(CSSM_RETURN statusCode)
 801  {
 802      switch (statusCode)
 803      {
 804          case CSSMERR_APPLETP_CRL_EXPIRED:               // 11. CRL expired
 805          case CSSMERR_APPLETP_CRL_NOT_VALID_YET:         // 12. CRL not yet valid
 806          case CSSMERR_APPLETP_CRL_NOT_FOUND:             // 13. CRL not found
 807          case CSSMERR_APPLETP_CRL_SERVER_DOWN:           // 14. CRL server down
 808          case CSSMERR_APPLETP_CRL_BAD_URI:               // 15. Illegal CRL distribution point URI
 809          case CSSMERR_APPLETP_CRL_NOT_TRUSTED:           // 18. CRL not verifiable to anchor or root
 810          case CSSMERR_APPLETP_CRL_INVALID_ANCHOR_CERT:   // 19. CRL verified to untrusted root
 811          case CSSMERR_APPLETP_CRL_POLICY_FAIL:           // 20. CRL failed policy verification
 812              return true;
 813          default:
 814              return false;
 815      }
 816  }
 817  
 818  // returns true if the given status code is related to performing a revocation check
 819  //
 820  bool isRevocationStatusCode(CSSM_RETURN statusCode)
 821  {
 822      if (statusCode == CSSMERR_APPLETP_INCOMPLETE_REVOCATION_CHECK ||  // 35. Revocation check not successful for each cert
 823          statusCode == CSSMERR_APPLETP_NETWORK_FAILURE ||              // 36. General network error
 824          isOCSPStatusCode(statusCode) == true ||                       // OCSP error
 825          isCRLStatusCode(statusCode) == true)                          // CRL error
 826          return true;
 827      else
 828          return false;
 829  }
 830  
 831  // returns a CFArrayRef of allowed root certificates for the provided leaf certificate
 832  // if it passes initial EV evaluation criteria and should be subject to OCSP revocation
 833  // checking; otherwise, NULL is returned. (Caller must release the result if not NULL.)
 834  //
 835  CFArrayRef allowedEVRootsForLeafCertificate(CFArrayRef certificates)
 836  {
 837      // Given a partial certificate chain (which may or may not include the root,
 838      // and does not have a guaranteed order except the first item is the leaf),
 839  	// determine whether the leaf claims to have a supported EV policy OID.
 840  	//
 841  	// Unless this function returns NULL, a full SSL trust evaluation with OCSP revocation
 842  	// checking must be performed successfully for the certificate to be considered valid.
 843  	// This function is intended to be called before the chain has been evaluated,
 844  	// in order to obtain the list of allowed roots for the evaluation. Once the "regular"
 845  	// TP evaluation has taken place, chainMeetsExtendedValidationCriteria() should be
 846  	// called to complete extended validation checking.
 847  
 848  	CFIndex count = (certificates) ? CFArrayGetCount(certificates) : 0;
 849  	if (count < 1)
 850          return NULL;
 851  
 852      CSSM_CL_HANDLE clHandle = 0;
 853      CSSM_DATA certData = { 0, NULL };
 854      SecCertificateRef certRef = (SecCertificateRef) CFArrayGetValueAtIndex(certificates, 0);
 855  	OSStatus status = errSecSuccess;
 856  	// note: Sec* APIs are not re-entrant due to the API lock
 857  	// status = SecCertificateGetCLHandle(certRef, &clHandle);
 858  	BEGIN_SECAPI_INTERNAL_CALL
 859  	clHandle = Certificate::required(certRef)->clHandle();
 860  	END_SECAPI_INTERNAL_CALL
 861  	if (status)
 862  		return NULL;
 863  	// note: Sec* APIs are not re-entrant due to the API lock
 864  	// status = SecCertificateGetData(certRef, &certData);
 865  	BEGIN_SECAPI_INTERNAL_CALL
 866  	certData = Certificate::required(certRef)->data();
 867  	END_SECAPI_INTERNAL_CALL
 868  	if (status)
 869  		return NULL;
 870  
 871      // Does the leaf certificate contain a Certificate Policies extension?
 872      const CSSM_OID_PTR oidPtr = (CSSM_OID_PTR) &CSSMOID_CertificatePolicies;
 873      CSSM_DATA_PTR extensionDataPtr = _copyFieldDataForOid(oidPtr, &certData, clHandle);
 874      if (!extensionDataPtr)
 875          return NULL;
 876  
 877      // Does the extension contain one of the magic EV CA OIDs we know about?
 878      CSSM_X509_EXTENSION *cssmExtension = (CSSM_X509_EXTENSION *)extensionDataPtr->Data;
 879      CE_CertPolicies *certPolicies = (CE_CertPolicies *)cssmExtension->value.parsedValue;
 880      CFStringRef oidString = _oidStringForCertificatePolicies(certPolicies);
 881  	_freeFieldData(extensionDataPtr, oidPtr, clHandle);
 882  
 883      // Fetch the allowed root CA certificates for this OID, if any
 884      CFArrayRef allowedRoots = (oidString) ? _allowedRootCertificatesForOidString(oidString) : NULL;
 885  	CFIndex rootCount = (allowedRoots) ? CFArrayGetCount(allowedRoots) : 0;
 886  	secinfo("evTrust", "allowedEVRootsForLeafCertificate: found %d allowed roots", (int)rootCount);
 887  	SafeCFRelease(&oidString);
 888  	if (!allowedRoots || !rootCount) {
 889  		SafeCFRelease(&allowedRoots);
 890  		return NULL;
 891  	}
 892  
 893  	// The leaf certificate needs extended validation (with revocation checking).
 894  	// Return the array of allowed roots for this leaf certificate.
 895  	return allowedRoots;
 896  }
 897  
 898  // returns true if the provided certificate contains a wildcard in either
 899  // its common name or subject alternative name.
 900  //
 901  static
 902  bool hasWildcardDNSName(SecCertificateRef certRef)
 903  {
 904  	OSStatus status = errSecSuccess;
 905  	CFArrayRef dnsNames = NULL;
 906  
 907  	BEGIN_SECAPI_INTERNAL_CALL
 908  	Required(&dnsNames) = Certificate::required(certRef)->copyDNSNames();
 909  	END_SECAPI_INTERNAL_CALL
 910  	if (status || !dnsNames)
 911  		return false;
 912  
 913  	bool hasWildcard = false;
 914  	const CFStringRef wildcard = CFSTR("*");
 915  	CFIndex index, count = CFArrayGetCount(dnsNames);
 916  	for (index = 0; index < count; index ++) {
 917  		CFStringRef name = (CFStringRef) CFArrayGetValueAtIndex(dnsNames, index);
 918  		if (name) {
 919  			CFRange foundRange = CFStringFind(name, wildcard, 0);
 920  			if (foundRange.length != 0 && foundRange.location != kCFNotFound) {
 921  				hasWildcard = true;
 922  				break;
 923  			}
 924  		}
 925  	}
 926  	CFRelease(dnsNames);
 927  	return hasWildcard;
 928  }
 929  
 930  // returns a CFDictionaryRef of extended validation results for the given chain,
 931  // or NULL if the certificate chain did not meet all EV criteria. (Caller must
 932  // release the result if not NULL.)
 933  //
 934  static
 935  CFDictionaryRef extendedValidationResults(CFArrayRef certChain, SecTrustResultType trustResult, OSStatus tpResult)
 936  {
 937  	// This function is intended to be called after the "regular" TP evaluation
 938  	// has taken place (i.e. trustResult and tpResult are available), and there
 939  	// is a full certificate chain to examine.
 940  
 941      CFIndex chainIndex, chainLen = (certChain) ? CFArrayGetCount(certChain) : 0;
 942  	if (chainLen < 2) {
 943  		return NULL; // invalid chain length
 944  	}
 945  
 946      if (trustResult != kSecTrustResultUnspecified) {
 947  
 948          // "Recoverable" means the certificate failed to meet all policy requirements, but is intrinsically OK.
 949          // One of the failures we might encounter is if the OCSP responder tells us to go away. Since this is a
 950          // real-world case, we'll check for OCSP and CRL meta-errors specifically.
 951          bool recovered = false;
 952          if (trustResult == kSecTrustResultRecoverableTrustFailure) {
 953              recovered = isRevocationServerMetaError((CSSM_RETURN)tpResult);
 954          }
 955          if (!recovered) {
 956              return NULL;
 957          }
 958      }
 959  
 960  	//
 961      // What we know at this point:
 962  	//
 963  	// 1. From a previous call to allowedEVRootsForLeafCertificate
 964  	// (or we wouldn't be getting called by extendedTrustResults):
 965      // - a leaf certificate exists
 966      // - that certificate contains a Certificate Policies extension
 967      // - that extension contains an OID from one of the trusted EV CAs we know about
 968  	// - we have found at least one allowed EV root for that OID
 969  	//
 970  	// 2. From the TP evaluation:
 971      // - the leaf certificate verifies back to a trusted EV root (with no trust settings overrides)
 972      // - SSL trust evaluation with OCSP revocation checking enabled returned no (fatal) errors
 973      //
 974      // We need to verify the following additional requirements for the leaf (as of EV 1.1, 6(a)(2)):
 975      // - cannot specify a wildcard in commonName or subjectAltName
 976      // (note: this is a change since EV 1.0 (9.2.1), which stated that "Wildcard FQDNs are permitted.")
 977  	//
 978  	// Finally, we need to check the following requirements (EV 1.1 specification, Appendix B):
 979      // - the trusted root, if created after 10/31/2006, must have:
 980      //      - critical basicConstraints extension with CA bit set
 981      //      - critical keyUsage extension with keyCertSign and cRLSign bits set
 982      // - intermediate certs, if present, must have:
 983      //      - certificatePolicies extension, containing either a known EV CA OID, or anyPolicy
 984      //      - non-critical cRLDistributionPoint extension
 985      //      - critical basicConstraints extension with CA bit set
 986      //      - critical keyUsage extension with keyCertSign and cRLSign bits set
 987      //
 988  
 989  	// check leaf certificate for wildcard names
 990  	if (hasWildcardDNSName((SecCertificateRef) CFArrayGetValueAtIndex(certChain, 0))) {
 991  		trustDebug("has wildcard name (does not meet EV criteria)\n");
 992  		return NULL;
 993  	}
 994  
 995      // check intermediate CA certificates for required extensions per Appendix B of EV 1.1 specification.
 996      bool hasRequiredExtensions = true;
 997  	CSSM_CL_HANDLE clHandle = 0;
 998  	CSSM_DATA certData = { 0, NULL };
 999  	CSSM_OID_PTR oidPtr = (CSSM_OID_PTR) &CSSMOID_CertificatePolicies;
1000      for (chainIndex = 1; hasRequiredExtensions && chainLen > 2 && chainIndex < chainLen - 1; chainIndex++) {
1001          SecCertificateRef intermediateCert = (SecCertificateRef) CFArrayGetValueAtIndex(certChain, chainIndex);
1002  		OSStatus status = errSecSuccess;
1003  		// note: Sec* APIs are not re-entrant due to the API lock
1004  		// status = SecCertificateGetCLHandle(intermediateCert, &clHandle);
1005  		BEGIN_SECAPI_INTERNAL_CALL
1006  		clHandle = Certificate::required(intermediateCert)->clHandle();
1007  		END_SECAPI_INTERNAL_CALL
1008  		if (status)
1009  			return NULL;
1010  		// note: Sec* APIs are not re-entrant due to the API lock
1011  		// status = SecCertificateGetData(intermediateCert, &certData);
1012  		BEGIN_SECAPI_INTERNAL_CALL
1013  		certData = Certificate::required(intermediateCert)->data();
1014  		END_SECAPI_INTERNAL_CALL
1015  		if (status)
1016  			return NULL;
1017  
1018          CSSM_DATA_PTR extensionDataPtr = _copyFieldDataForOid(oidPtr, &certData, clHandle);
1019          if (!extensionDataPtr)
1020              return NULL;
1021  
1022          CSSM_X509_EXTENSION *cssmExtension = (CSSM_X509_EXTENSION *)extensionDataPtr->Data;
1023          CE_CertPolicies *certPolicies = (CE_CertPolicies *)cssmExtension->value.parsedValue;
1024  		CFStringRef oidString = _oidStringForCertificatePolicies(certPolicies);
1025          hasRequiredExtensions = (oidString != NULL);
1026  		SafeCFRelease(&oidString);
1027          _freeFieldData(extensionDataPtr, oidPtr, clHandle);
1028  
1029          // FIX: add checks for the following (not essential to this implementation):
1030          //      - non-critical cRLDistributionPoint extension
1031          //      - critical basicConstraints extension with CA bit set
1032          //      - critical keyUsage extension with keyCertSign and cRLSign bits set
1033          // Tracked by <rdar://problem/6119322>
1034      }
1035  
1036      if (hasRequiredExtensions) {
1037  		SecCertificateRef leafCert = (SecCertificateRef) CFArrayGetValueAtIndex(certChain, 0);
1038  		CFStringRef organizationName = organizationNameForCertificate(leafCert);
1039  		if (organizationName != NULL) {
1040  			CFMutableDictionaryRef resultDict = CFDictionaryCreateMutable(NULL, 0,
1041  				&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
1042  			CFDictionaryAddValue(resultDict, kSecEVOrganizationName, organizationName);
1043  			trustDebug("[EV] extended validation succeeded\n");
1044  			SafeCFRelease(&organizationName);
1045  			return resultDict;
1046  		}
1047  	}
1048  
1049  	return NULL;
1050  }
1051  
1052  // returns a CFDictionaryRef containing extended trust results.
1053  // Caller must release this dictionary.
1054  //
1055  // If the isEVCandidate argument is true, extended validation checking is performed
1056  // and the kSecEVOrganizationName key will be set in the dictionary if EV criteria is met.
1057  // In all cases, kSecTrustEvaluationDate and kSecTrustExpirationDate will be set.
1058  //
1059  CFDictionaryRef extendedTrustResults(CFArrayRef certChain, SecTrustResultType trustResult, OSStatus tpResult, bool isEVCandidate)
1060  {
1061  	CFMutableDictionaryRef resultDict = NULL;
1062  	if (isEVCandidate) {
1063  		resultDict = (CFMutableDictionaryRef) extendedValidationResults(certChain, trustResult, tpResult);
1064  	}
1065  	if (!resultDict) {
1066  		resultDict = CFDictionaryCreateMutable(NULL, 0,
1067  			&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
1068  		if (!resultDict) {
1069  			return NULL;
1070  		}
1071  	}
1072  	CFAbsoluteTime at = CFAbsoluteTimeGetCurrent();
1073  	CFDateRef trustEvaluationDate = CFDateCreate(kCFAllocatorDefault, at);
1074  	// by default, permit caching of trust evaluation results for up to 2 hours
1075  	// FIXME: need to modify this based on cert expiration and OCSP/CRL validity
1076  	CFDateRef trustExpirationDate = CFDateCreate(kCFAllocatorDefault, at + (60*60*2));
1077  	CFDictionaryAddValue(resultDict, kSecTrustEvaluationDate, trustEvaluationDate);
1078  	SafeCFRelease(&trustEvaluationDate);
1079  	CFDictionaryAddValue(resultDict, kSecTrustExpirationDate, trustExpirationDate);
1080  	SafeCFRelease(&trustExpirationDate);
1081  
1082  	return resultDict;
1083  }
1084  
1085  // returns a CFDictionaryRef containing mappings from supported EV CA OIDs to SHA-1 hash values;
1086  // caller must release
1087  //
1088  static CFDictionaryRef _evCAOidDict()
1089  {
1090      static CFDictionaryRef s_evCAOidDict = NULL;
1091      if (s_evCAOidDict) {
1092  		CFRetain(s_evCAOidDict);
1093  		secinfo("evTrust", "_evCAOidDict: returning static instance (rc=%d)", (int)CFGetRetainCount(s_evCAOidDict));
1094          return s_evCAOidDict;
1095  	}
1096  	secinfo("evTrust", "_evCAOidDict: initializing static instance");
1097  
1098  	s_evCAOidDict = dictionaryWithContentsOfPlistFile(EV_ROOTS_PLIST_SYSTEM_PATH);
1099  	if (!s_evCAOidDict)
1100  		return NULL;
1101  
1102  #if !defined MAC_OS_X_VERSION_10_6 || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6
1103  	// Work around rdar://6302788 by hard coding a hash that was missed when addressing <rdar://problem/6238289&6238296>
1104  	// This is being addressed in SnowLeopard by rdar://6305989
1105  	CFStringRef oidString = CFSTR("2.16.840.1.114028.10.1.2");
1106  	CFMutableArrayRef hashes = (CFMutableArrayRef) CFDictionaryGetValue(s_evCAOidDict, oidString);
1107  	if (hashes) {
1108  		uint8 hashBytes[] = {0xB3, 0x1E, 0xB1, 0xB7, 0x40, 0xE3, 0x6C, 0x84, 0x02, 0xDA, 0xDC, 0x37, 0xD4, 0x4D, 0xF5, 0xD4, 0x67, 0x49, 0x52, 0xF9};
1109  		CFDataRef hashData = CFDataCreate(NULL, hashBytes, sizeof(hashBytes));
1110  		CFIndex hashCount = CFArrayGetCount(hashes);
1111  		if (hashData && CFArrayContainsValue(hashes, CFRangeMake(0, hashCount), hashData)) {
1112  			secinfo("evTrust", "_evCAOidDict: added hardcoded hash value");
1113  			CFArrayAppendValue(hashes, hashData);
1114  		}
1115  		SafeCFRelease(&hashData);
1116  	}
1117  #endif
1118  	CFRetain(s_evCAOidDict);
1119  	secinfo("evTrust", "_evCAOidDict: returning static instance (rc=%d)", (int)CFGetRetainCount(s_evCAOidDict));
1120      return s_evCAOidDict;
1121  }
1122  
1123  // returns a CFStringRef containing a decimal representation of the given OID.
1124  // Caller must release.
1125  
1126  static CFStringRef _decimalStringForOid(CSSM_OID_PTR oid)
1127  {
1128      CFMutableStringRef str = CFStringCreateMutable(NULL, 0);
1129      if (!str || oid->Length > 32)
1130          return str;
1131  
1132      // The first two levels are encoded into one byte, since the root level
1133      // has only 3 nodes (40*x + y).  However if x = joint-iso-itu-t(2) then
1134      // y may be > 39, so we have to add special-case handling for this.
1135      unsigned long value = 0;
1136      unsigned int x = oid->Data[0] / 40;
1137      unsigned int y = oid->Data[0] % 40;
1138      if (x > 2) {
1139          // Handle special case for large y if x = 2
1140          y += (x - 2) * 40;
1141          x = 2;
1142      }
1143  
1144  	CFStringAppendFormat(str, NULL, CFSTR("%d.%d"), x, y);
1145  
1146      for (x = 1; x < oid->Length; x++) {
1147          value = (value << 7) | (oid->Data[x] & 0x7F);
1148          if(!(oid->Data[x] & 0x80)) {
1149  			CFStringAppendFormat(str, NULL, CFSTR(".%ld"), value);
1150              value = 0;
1151          }
1152      }
1153  
1154  #if !defined(NDEBUG)
1155  	CFIndex nameLen = CFStringGetLength(str);
1156  	CFIndex bufLen = 1 + CFStringGetMaximumSizeForEncoding(nameLen, kCFStringEncodingUTF8);
1157  	char *nameBuf = (char *)malloc(bufLen);
1158  	if (!CFStringGetCString(str, nameBuf, bufLen-1, kCFStringEncodingUTF8))
1159  		nameBuf[0]=0;
1160  	secinfo("evTrust", "_decimalStringForOid: \"%s\"", nameBuf);
1161  	free(nameBuf);
1162  #endif
1163  
1164      return str;
1165  }
1166  
1167  static void _freeFieldData(CSSM_DATA_PTR value, CSSM_OID_PTR oid, CSSM_CL_HANDLE clHandle)
1168  {
1169  	if (value && value->Data) {
1170  		CSSM_CL_FreeFieldValue(clHandle, oid, value);
1171  	}
1172      return;
1173  }
1174  
1175  static ModuleNexus<Mutex> gOidStringForCertificatePoliciesMutex;
1176  
1177  static CFStringRef CF_RETURNS_RETAINED _oidStringForCertificatePolicies(const CE_CertPolicies *certPolicies)
1178  {
1179  	StLock<Mutex> _(gOidStringForCertificatePoliciesMutex());
1180  
1181      // returns the first EV OID (as a string) found in the given Certificate Policies extension,
1182      // or NULL if the extension does not contain any known EV OIDs. (Note that the "any policy" OID
1183      // is a special case and will be returned if present, although its presence is only meaningful
1184      // in an intermediate CA.)
1185  
1186      if (!certPolicies) {
1187  		secinfo("evTrust", "oidStringForCertificatePolicies: missing certPolicies!");
1188          return NULL;
1189  	}
1190  
1191  	CFDictionaryRef evOidDict = _evCAOidDict();
1192  	if (!evOidDict) {
1193  		secinfo("evTrust", "oidStringForCertificatePolicies: nil OID dictionary!");
1194  		return NULL;
1195  	}
1196  
1197  	CFStringRef foundOidStr = NULL;
1198      uint32 policyIndex, maxIndex = 10; // sanity check; EV certs normally have EV OID as first policy
1199      for (policyIndex = 0; policyIndex < certPolicies->numPolicies && policyIndex < maxIndex; policyIndex++) {
1200          CE_PolicyInformation *certPolicyInfo = &certPolicies->policies[policyIndex];
1201          CSSM_OID_PTR oid = &certPolicyInfo->certPolicyId;
1202          CFStringRef oidStr = _decimalStringForOid(oid);
1203  		if (!oidStr)
1204  			continue;
1205  		if (!CFStringCompare(oidStr, CFSTR("2.5.29.32.0"), 0) ||	// is it the "any" OID, or
1206  			CFDictionaryGetValue(evOidDict, oidStr) != NULL) {		// a known EV CA OID?
1207  			foundOidStr = CFStringCreateCopy(NULL, oidStr);
1208  		}
1209  		SafeCFRelease(&oidStr);
1210  		if (foundOidStr)
1211  			break;
1212      }
1213  	SafeCFRelease(&evOidDict);
1214  
1215      return foundOidStr;
1216  }
1217