15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/x509_certificate.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <CommonCrypto/CommonDigest.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <CoreServices/CoreServices.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <Security/Security.h> 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/lazy_instance.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/mac/mac_logging.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/mac/scoped_cftyperef.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/singleton.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/pickle.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/sha1.h" 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/string_piece.h" 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/sys_string_conversions.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/cssm_init.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/mac_security_services_lock.h" 25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/x509_util_mac.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochusing base::ScopedCFTypeRef; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::Time; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetCertDistinguishedName( 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const x509_util::CSSMCachedCertificate& cached_cert, 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CSSM_OID* oid, 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CertPrincipal* result) { 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) x509_util::CSSMFieldValue distinguished_name; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSStatus status = cached_cert.GetField(oid, &distinguished_name); 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status || !distinguished_name.field()) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->ParseDistinguishedName(distinguished_name.field()->Data, 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) distinguished_name.field()->Length); 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool IsCertIssuerInEncodedList(X509Certificate::OSCertHandle cert_handle, 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<std::string>& issuers) { 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) x509_util::CSSMCachedCertificate cached_cert; 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (cached_cert.Init(cert_handle) != CSSM_OK) 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) x509_util::CSSMFieldValue distinguished_name; 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OSStatus status = cached_cert.GetField(&CSSMOID_X509V1IssuerNameStd, 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &distinguished_name); 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (status || !distinguished_name.field()) 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::StringPiece name_piece( 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) reinterpret_cast<const char*>(distinguished_name.field()->Data), 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static_cast<size_t>(distinguished_name.field()->Length)); 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (std::vector<std::string>::const_iterator it = issuers.begin(); 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != issuers.end(); ++it) { 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::StringPiece issuer_piece(*it); 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (name_piece == issuer_piece) 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetCertDateForOID(const x509_util::CSSMCachedCertificate& cached_cert, 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CSSM_OID* oid, 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Time* result) { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *result = Time::Time(); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) x509_util::CSSMFieldValue field; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSStatus status = cached_cert.GetField(oid, &field); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CSSM_X509_TIME* x509_time = field.GetAs<CSSM_X509_TIME>(); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (x509_time->timeType != BER_TAG_UTC_TIME && 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) x509_time->timeType != BER_TAG_GENERALIZED_TIME) { 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Unsupported date/time format " 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << x509_time->timeType; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringPiece time_string( 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const char*>(x509_time->time.Data), 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) x509_time->time.Length); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CertDateFormat format = x509_time->timeType == BER_TAG_UTC_TIME ? 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_DATE_FORMAT_UTC_TIME : CERT_DATE_FORMAT_GENERALIZED_TIME; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ParseCertificateDate(time_string, format, result)) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Invalid certificate date/time " << time_string; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetCertSerialNumber( 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const x509_util::CSSMCachedCertificate& cached_cert) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) x509_util::CSSMFieldValue serial_number; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSStatus status = cached_cert.GetField(&CSSMOID_X509V1SerialNumber, 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &serial_number); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status || !serial_number.field()) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::string(); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::string( 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const char*>(serial_number.field()->Data), 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) serial_number.field()->Length); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if |purpose| is listed as allowed in |usage|. This 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// function also considers the "Any" purpose. If the attribute is 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// present and empty, we return false. 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtendedKeyUsageAllows(const CE_ExtendedKeyUsage* usage, 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CSSM_OID* purpose) { 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (unsigned p = 0; p < usage->numPurposes; ++p) { 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CSSMOIDEqual(&usage->purposes[p], purpose)) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CSSMOIDEqual(&usage->purposes[p], &CSSMOID_ExtendedKeyUsageAny)) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that a given |cert_handle| is actually a valid X.509 certificate, and 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// return true if it is. 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// On OS X, SecCertificateCreateFromData() does not return any errors if 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// called with invalid data, as long as data is present. The actual decoding 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of the certificate does not happen until an API that requires a CSSM 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// handle is called. While SecCertificateGetCLHandle is the most likely 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// candidate, as it performs the parsing, it does not check whether the 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// parsing was actually successful. Instead, SecCertificateGetSubject is 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// used (supported since 10.3), as a means to check that the certificate 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// parsed as a valid X.509 certificate. 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsValidOSCertHandle(SecCertificateRef cert_handle) { 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CSSM_X509_NAME* sanity_check = NULL; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSStatus status = SecCertificateGetSubject(cert_handle, &sanity_check); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return status == noErr && sanity_check; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Parses |data| of length |length|, attempting to decode it as the specified 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |format|. If |data| is in the specified format, any certificates contained 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// within are stored into |output|. 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AddCertificatesFromBytes(const char* data, size_t length, 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SecExternalFormat format, 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) X509Certificate::OSCertHandles* output) { 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SecExternalFormat input_format = format; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedCFTypeRef<CFDataRef> local_data(CFDataCreateWithBytesNoCopy( 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kCFAllocatorDefault, reinterpret_cast<const UInt8*>(data), length, 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kCFAllocatorNull)); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CFArrayRef items = NULL; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSStatus status; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock lock(crypto::GetMacSecurityServicesLock()); 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status = SecKeychainItemImport(local_data, NULL, &input_format, 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, 0, NULL, NULL, &items); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status) { 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSSTATUS_DLOG(WARNING, status) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Unable to import items from data of length " << length; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedCFTypeRef<CFArrayRef> scoped_items(items); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CFTypeID cert_type_id = SecCertificateGetTypeID(); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (CFIndex i = 0; i < CFArrayGetCount(items); ++i) { 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SecKeychainItemRef item = reinterpret_cast<SecKeychainItemRef>( 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const_cast<void*>(CFArrayGetValueAtIndex(items, i))); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // While inputFormat implies only certificates will be imported, if/when 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // other formats (eg: PKCS#12) are supported, this may also include 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // private keys or other items types, so filter appropriately. 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CFGetTypeID(item) == cert_type_id) { 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SecCertificateRef cert = reinterpret_cast<SecCertificateRef>(item); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // OS X ignores |input_format| if it detects that |local_data| is PEM 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // encoded, attempting to decode data based on internal rules for PEM 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // block headers. If a PKCS#7 blob is encoded with a PEM block of 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // CERTIFICATE, OS X 10.5 will return a single, invalid certificate 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // based on the decoded data. If this happens, the certificate should 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // not be included in |output|. Because |output| is empty, 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // CreateCertificateListfromBytes will use PEMTokenizer to decode the 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // data. When called again with the decoded data, OS X will honor 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |input_format|, causing decode to succeed. On OS X 10.6, the data 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is properly decoded as a PKCS#7, whether PEM or not, which avoids 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the need to fallback to internal decoding. 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsValidOSCertHandle(cert)) { 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CFRetain(cert); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output->push_back(cert); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void X509Certificate::Initialize() { 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) x509_util::CSSMCachedCertificate cached_cert; 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cached_cert.Init(cert_handle_) == CSSM_OK) { 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetCertDistinguishedName(cached_cert, &CSSMOID_X509V1SubjectNameStd, 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &subject_); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetCertDistinguishedName(cached_cert, &CSSMOID_X509V1IssuerNameStd, 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &issuer_); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetCertDateForOID(cached_cert, &CSSMOID_X509V1ValidityNotBefore, 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &valid_start_); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetCertDateForOID(cached_cert, &CSSMOID_X509V1ValidityNotAfter, 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &valid_expiry_); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) serial_number_ = GetCertSerialNumber(cached_cert); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fingerprint_ = CalculateFingerprint(cert_handle_); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ca_fingerprint_ = CalculateCAFingerprint(intermediate_ca_certs_); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool X509Certificate::IsIssuedByEncoded( 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<std::string>& valid_issuers) { 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (IsCertIssuerInEncodedList(cert_handle_, valid_issuers)) 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (OSCertHandles::iterator it = intermediate_ca_certs_.begin(); 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != intermediate_ca_certs_.end(); ++it) { 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (IsCertIssuerInEncodedList(*it, valid_issuers)) 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void X509Certificate::GetSubjectAltName( 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<std::string>* dns_names, 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<std::string>* ip_addrs) const { 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dns_names) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dns_names->clear(); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ip_addrs) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ip_addrs->clear(); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) x509_util::CSSMCachedCertificate cached_cert; 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSStatus status = cached_cert.Init(cert_handle_); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) x509_util::CSSMFieldValue subject_alt_name; 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status = cached_cert.GetField(&CSSMOID_SubjectAltName, &subject_alt_name); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status || !subject_alt_name.field()) 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CSSM_X509_EXTENSION* cssm_ext = 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subject_alt_name.GetAs<CSSM_X509_EXTENSION>(); 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!cssm_ext || !cssm_ext->value.parsedValue) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CE_GeneralNames* alt_name = 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const CE_GeneralNames*>(cssm_ext->value.parsedValue); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t name = 0; name < alt_name->numNames; ++name) { 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CE_GeneralName& name_struct = alt_name->generalName[name]; 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CSSM_DATA& name_data = name_struct.name; 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // DNSName and IPAddress are encoded as IA5String and OCTET STRINGs 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // respectively, both of which can be byte copied from 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // CSSM_DATA::data into the appropriate output vector. 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dns_names && name_struct.nameType == GNT_DNSName) { 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dns_names->push_back(std::string( 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const char*>(name_data.Data), 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name_data.Length)); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (ip_addrs && name_struct.nameType == GNT_IPAddress) { 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ip_addrs->push_back(std::string( 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const char*>(name_data.Data), 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name_data.Length)); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool X509Certificate::GetDEREncoded(X509Certificate::OSCertHandle cert_handle, 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* encoded) { 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CSSM_DATA der_data; 2771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!cert_handle || SecCertificateGetData(cert_handle, &der_data) != noErr) 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded->assign(reinterpret_cast<char*>(der_data.Data), 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) der_data.Length); 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a, 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) X509Certificate::OSCertHandle b) { 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(a && b); 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (a == b) 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CFEqual(a, b)) 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CSSM_DATA a_data, b_data; 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SecCertificateGetData(a, &a_data) == noErr && 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SecCertificateGetData(b, &b_data) == noErr && 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) a_data.Length == b_data.Length && 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcmp(a_data.Data, b_data.Data, a_data.Length) == 0; 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* data, int length) { 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CSSM_DATA cert_data; 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cert_data.Data = const_cast<uint8*>(reinterpret_cast<const uint8*>(data)); 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cert_data.Length = length; 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSCertHandle cert_handle = NULL; 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSStatus status = SecCertificateCreateFromData(&cert_data, 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CSSM_CERT_X_509v3, 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CSSM_CERT_ENCODING_DER, 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &cert_handle); 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status != noErr) 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsValidOSCertHandle(cert_handle)) { 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CFRelease(cert_handle); 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return cert_handle; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes( 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* data, int length, Format format) { 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSCertHandles results; 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (format) { 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case FORMAT_SINGLE_CERTIFICATE: { 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSCertHandle handle = CreateOSCertHandleFromBytes(data, length); 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (handle) 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) results.push_back(handle); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case FORMAT_PKCS7: 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddCertificatesFromBytes(data, length, kSecFormatPKCS7, &results); 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Certificate format " << format << " unimplemented"; 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return results; 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle( 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSCertHandle handle) { 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!handle) 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return reinterpret_cast<OSCertHandle>(const_cast<void*>(CFRetain(handle))); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { 353116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (cert_handle) 354116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CFRelease(cert_handle); 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SHA1HashValue X509Certificate::CalculateFingerprint( 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSCertHandle cert) { 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SHA1HashValue sha1; 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(sha1.data, 0, sizeof(sha1.data)); 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CSSM_DATA cert_data; 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSStatus status = SecCertificateGetData(cert, &cert_data); 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status) 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return sha1; 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(cert_data.Data); 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(cert_data.Length, 0U); 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CC_SHA1(cert_data.Data, cert_data.Length, sha1.data); 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return sha1; 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SHA1HashValue X509Certificate::CalculateCAFingerprint( 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const OSCertHandles& intermediates) { 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SHA1HashValue sha1; 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(sha1.data, 0, sizeof(sha1.data)); 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The CC_SHA(3cc) man page says all CC_SHA1_xxx routines return 1, so 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we don't check their return values. 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CC_SHA1_CTX sha1_ctx; 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CC_SHA1_Init(&sha1_ctx); 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CSSM_DATA cert_data; 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < intermediates.size(); ++i) { 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSStatus status = SecCertificateGetData(intermediates[i], &cert_data); 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status) 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return sha1; 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CC_SHA1_Update(&sha1_ctx, cert_data.Data, cert_data.Length); 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CC_SHA1_Final(sha1.data, &sha1_ctx); 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return sha1; 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool X509Certificate::SupportsSSLClientAuth() const { 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) x509_util::CSSMCachedCertificate cached_cert; 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSStatus status = cached_cert.Init(cert_handle_); 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status) 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // RFC5280 says to take the intersection of the two extensions. 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Our underlying crypto libraries don't expose 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ClientCertificateType, so for now we will not support fixed 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Diffie-Hellman mechanisms. For rsa_sign, we need the 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // digitalSignature bit. 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In particular, if a key has the nonRepudiation bit and not the 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // digitalSignature one, we will not offer it to the user. 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) x509_util::CSSMFieldValue key_usage; 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status = cached_cert.GetField(&CSSMOID_KeyUsage, &key_usage); 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status == CSSM_OK && key_usage.field()) { 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CSSM_X509_EXTENSION* ext = key_usage.GetAs<CSSM_X509_EXTENSION>(); 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CE_KeyUsage* key_usage_value = 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const CE_KeyUsage*>(ext->value.parsedValue); 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!((*key_usage_value) & CE_KU_DigitalSignature)) 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status = cached_cert.GetField(&CSSMOID_ExtendedKeyUsage, &key_usage); 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status == CSSM_OK && key_usage.field()) { 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CSSM_X509_EXTENSION* ext = key_usage.GetAs<CSSM_X509_EXTENSION>(); 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CE_ExtendedKeyUsage* ext_key_usage = 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const CE_ExtendedKeyUsage*>(ext->value.parsedValue); 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ExtendedKeyUsageAllows(ext_key_usage, &CSSMOID_ClientAuth)) 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CFArrayRef X509Certificate::CreateOSCertChainForCert() const { 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CFMutableArrayRef cert_list = 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CFArrayCreateMutable(kCFAllocatorDefault, 0, 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &kCFTypeArrayCallBacks); 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!cert_list) 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CFArrayAppendValue(cert_list, os_cert_handle()); 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CFArrayAppendValue(cert_list, intermediate_ca_certs_[i]); 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return cert_list; 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)X509Certificate::OSCertHandle 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)X509Certificate::ReadOSCertHandleFromPickle(PickleIterator* pickle_iter) { 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* data; 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int length; 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!pickle_iter->ReadData(&data, &length)) 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return CreateOSCertHandleFromBytes(data, length); 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool X509Certificate::WriteOSCertHandleToPickle(OSCertHandle cert_handle, 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pickle* pickle) { 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CSSM_DATA cert_data; 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSStatus status = SecCertificateGetData(cert_handle, &cert_data); 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status) 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return pickle->WriteData(reinterpret_cast<char*>(cert_data.Data), 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cert_data.Length); 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void X509Certificate::GetPublicKeyInfo(OSCertHandle cert_handle, 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t* size_bits, 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PublicKeyType* type) { 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Since we might fail, set the output parameters to default values first. 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *type = kPublicKeyTypeUnknown; 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *size_bits = 0; 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SecKeyRef key; 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSStatus status = SecCertificateCopyPublicKey(cert_handle, &key); 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status) { 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "SecCertificateCopyPublicKey failed: " << status; 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedCFTypeRef<SecKeyRef> scoped_key(key); 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CSSM_KEY* cssm_key; 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status = SecKeyGetCSSMKey(key, &cssm_key); 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status) { 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "SecKeyGetCSSMKey failed: " << status; 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *size_bits = cssm_key->KeyHeader.LogicalKeySizeInBits; 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (cssm_key->KeyHeader.AlgorithmId) { 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CSSM_ALGID_RSA: 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *type = kPublicKeyTypeRSA; 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CSSM_ALGID_DSA: 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *type = kPublicKeyTypeDSA; 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CSSM_ALGID_ECDSA: 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *type = kPublicKeyTypeECDSA; 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CSSM_ALGID_DH: 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *type = kPublicKeyTypeDH; 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *type = kPublicKeyTypeUnknown; 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *size_bits = 0; 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 517