diff options
author | rockot <rockot@chromium.org> | 2016-03-25 11:02:26 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-03-25 18:04:20 +0000 |
commit | 28472efddd70ac4affc0ba9a46a56697937840a3 (patch) | |
tree | bc7ebed81b00ac41b582b408c5595019be24b9cb /net/cert | |
parent | affa906687c76c929545f8073fffaa53ff3a1a4a (diff) | |
download | chromium_src-28472efddd70ac4affc0ba9a46a56697937840a3.zip chromium_src-28472efddd70ac4affc0ba9a46a56697937840a3.tar.gz chromium_src-28472efddd70ac4affc0ba9a46a56697937840a3.tar.bz2 |
Revert of Adding iOS OpenSSL Implementation (patchset #23 id:420001 of https://codereview.chromium.org/1810153002/ )
Reason for revert:
Broken iOS build: https://build.chromium.org/p/chromium.mac/builders/iOS_Device/builds/44491/steps/compile/logs/stdio
Let's try relanding with the potential fix from https://codereview.chromium.org/1834583006 merged in.
Original issue's description:
> This adds the OpenSSL-specific implementations for iOS, using SecTrustEvaluate in order to determine the validity of the certificate chain.
>
> BUG=591545
>
> Committed: https://crrev.com/864f9468ae2a8d1ba95c64824ef2caf05b7121fc
> Cr-Commit-Position: refs/heads/master@{#383297}
TBR=davidben@chromium.org,rsleevi@chromium.org,svaldez@chromium.org
# Skipping CQ checks because original CL landed less than 1 days ago.
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=591545
Review URL: https://codereview.chromium.org/1838513002
Cr-Commit-Position: refs/heads/master@{#383301}
Diffstat (limited to 'net/cert')
-rw-r--r-- | net/cert/cert_verify_proc.cc | 4 | ||||
-rw-r--r-- | net/cert/cert_verify_proc_ios.cc | 239 | ||||
-rw-r--r-- | net/cert/cert_verify_proc_ios.h | 36 | ||||
-rw-r--r-- | net/cert/x509_certificate_openssl_ios.cc | 475 |
4 files changed, 0 insertions, 754 deletions
diff --git a/net/cert/cert_verify_proc.cc b/net/cert/cert_verify_proc.cc index 9c8267d..eba84e6 100644 --- a/net/cert/cert_verify_proc.cc +++ b/net/cert/cert_verify_proc.cc @@ -32,8 +32,6 @@ #include "net/cert/cert_verify_proc_openssl.h" #elif defined(OS_ANDROID) #include "net/cert/cert_verify_proc_android.h" -#elif defined(OS_IOS) -#include "net/cert/cert_verify_proc_ios.h" #elif defined(OS_MACOSX) #include "net/cert/cert_verify_proc_mac.h" #elif defined(OS_WIN) @@ -211,8 +209,6 @@ CertVerifyProc* CertVerifyProc::CreateDefault() { return new CertVerifyProcOpenSSL(); #elif defined(OS_ANDROID) return new CertVerifyProcAndroid(); -#elif defined(OS_IOS) - return new CertVerifyProcIOS(); #elif defined(OS_MACOSX) return new CertVerifyProcMac(); #elif defined(OS_WIN) diff --git a/net/cert/cert_verify_proc_ios.cc b/net/cert/cert_verify_proc_ios.cc deleted file mode 100644 index 5f2884f..0000000 --- a/net/cert/cert_verify_proc_ios.cc +++ /dev/null @@ -1,239 +0,0 @@ -// Copyright (c) 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/cert/cert_verify_proc_ios.h" - -#include <CommonCrypto/CommonDigest.h> -#include <Security/Security.h> - -#include "base/logging.h" -#include "base/mac/scoped_cftyperef.h" -#include "crypto/sha2.h" -#include "net/base/net_errors.h" -#include "net/cert/asn1_util.h" -#include "net/cert/cert_verify_result.h" -#include "net/cert/test_root_certs.h" -#include "net/cert/x509_certificate.h" -#include "net/ssl/openssl_ssl_util.h" - -using base::ScopedCFTypeRef; - -namespace net { - -namespace { - -int NetErrorFromOSStatus(OSStatus status) { - switch (status) { - case noErr: - return OK; - case errSecNotAvailable: - return ERR_NOT_IMPLEMENTED; - case errSecAuthFailed: - return ERR_ACCESS_DENIED; - default: - return ERR_FAILED; - } -} - -// Creates a series of SecPolicyRefs to be added to a SecTrustRef used to -// validate a certificate for an SSL server. |hostname| contains the name of -// the SSL server that the certificate should be verified against. If -// successful, returns noErr, and stores the resultant array of SecPolicyRefs -// in |policies|. -OSStatus CreateTrustPolicies(ScopedCFTypeRef<CFArrayRef>* policies) { - ScopedCFTypeRef<CFMutableArrayRef> local_policies( - CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks)); - if (!local_policies) - return errSecAllocate; - - SecPolicyRef ssl_policy = SecPolicyCreateBasicX509(); - CFArrayAppendValue(local_policies, ssl_policy); - CFRelease(ssl_policy); - ssl_policy = SecPolicyCreateSSL(true, nullptr); - CFArrayAppendValue(local_policies, ssl_policy); - CFRelease(ssl_policy); - - policies->reset(local_policies.release()); - return noErr; -} - -// Builds and evaluates a SecTrustRef for the certificate chain contained -// in |cert_array|, using the verification policies in |trust_policies|. On -// success, returns OK, and updates |trust_ref| and |trust_result|. On failure, -// no output parameters are modified. -// -// Note: An OK return does not mean that |cert_array| is trusted, merely that -// verification was performed successfully. -int BuildAndEvaluateSecTrustRef(CFArrayRef cert_array, - CFArrayRef trust_policies, - ScopedCFTypeRef<SecTrustRef>* trust_ref, - ScopedCFTypeRef<CFArrayRef>* verified_chain, - SecTrustResultType* trust_result) { - SecTrustRef tmp_trust = nullptr; - OSStatus status = - SecTrustCreateWithCertificates(cert_array, trust_policies, &tmp_trust); - if (status) - return NetErrorFromOSStatus(status); - ScopedCFTypeRef<SecTrustRef> scoped_tmp_trust(tmp_trust); - - if (TestRootCerts::HasInstance()) { - status = TestRootCerts::GetInstance()->FixupSecTrustRef(tmp_trust); - if (status) - return NetErrorFromOSStatus(status); - } - - SecTrustResultType tmp_trust_result; - status = SecTrustEvaluate(tmp_trust, &tmp_trust_result); - if (status) - return NetErrorFromOSStatus(status); - - ScopedCFTypeRef<CFMutableArrayRef> tmp_verified_chain( - CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks)); - const CFIndex chain_length = SecTrustGetCertificateCount(tmp_trust); - for (CFIndex i = 0; i < chain_length; ++i) { - SecCertificateRef chain_cert = SecTrustGetCertificateAtIndex(tmp_trust, i); - CFArrayAppendValue(tmp_verified_chain, chain_cert); - } - - trust_ref->swap(scoped_tmp_trust); - *trust_result = tmp_trust_result; - verified_chain->reset(tmp_verified_chain.release()); - return OK; -} - -void GetCertChainInfo(CFArrayRef cert_chain, CertVerifyResult* verify_result) { - DCHECK_LT(0, CFArrayGetCount(cert_chain)); - - verify_result->has_md2 = false; - verify_result->has_md4 = false; - verify_result->has_md5 = false; - verify_result->has_sha1 = false; - verify_result->has_sha1_leaf = false; - - SecCertificateRef verified_cert = nullptr; - std::vector<SecCertificateRef> verified_chain; - for (CFIndex i = 0, count = CFArrayGetCount(cert_chain); i < count; ++i) { - SecCertificateRef chain_cert = reinterpret_cast<SecCertificateRef>( - const_cast<void*>(CFArrayGetValueAtIndex(cert_chain, i))); - if (i == 0) { - verified_cert = chain_cert; - } else { - verified_chain.push_back(chain_cert); - } - - std::string der_bytes; - if (!X509Certificate::GetDEREncoded(chain_cert, &der_bytes)) - return; - const uint8_t* bytes = reinterpret_cast<const uint8_t*>(der_bytes.data()); - ScopedX509 x509_cert(d2i_X509(NULL, &bytes, der_bytes.size())); - - base::StringPiece spki_bytes; - if (!asn1::ExtractSPKIFromDERCert(der_bytes, &spki_bytes)) - continue; - - HashValue sha1(HASH_VALUE_SHA1); - CC_SHA1(spki_bytes.data(), spki_bytes.size(), sha1.data()); - verify_result->public_key_hashes.push_back(sha1); - - HashValue sha256(HASH_VALUE_SHA256); - CC_SHA256(spki_bytes.data(), spki_bytes.size(), sha256.data()); - verify_result->public_key_hashes.push_back(sha256); - - int sig_alg = OBJ_obj2nid(x509_cert->sig_alg->algorithm); - if (sig_alg == NID_md2WithRSAEncryption) { - verify_result->has_md2 = true; - } else if (sig_alg == NID_md4WithRSAEncryption) { - verify_result->has_md4 = true; - } else if (sig_alg == NID_md5WithRSAEncryption || - sig_alg == NID_md5WithRSA) { - verify_result->has_md5 = true; - } else if (sig_alg == NID_sha1WithRSAEncryption || - sig_alg == NID_dsaWithSHA || sig_alg == NID_dsaWithSHA1 || - sig_alg == NID_dsaWithSHA1_2 || sig_alg == NID_sha1WithRSA || - sig_alg == NID_ecdsa_with_SHA1) { - verify_result->has_sha1 = true; - if (i == 0) - verify_result->has_sha1_leaf = true; - } - } - if (!verified_cert) { - NOTREACHED(); - return; - } - - verify_result->verified_cert = - X509Certificate::CreateFromHandle(verified_cert, verified_chain); -} - -} // namespace - -CertVerifyProcIOS::CertVerifyProcIOS() {} - -CertVerifyProcIOS::~CertVerifyProcIOS() {} - -bool CertVerifyProcIOS::SupportsAdditionalTrustAnchors() const { - return false; -} - -bool CertVerifyProcIOS::SupportsOCSPStapling() const { - return false; -} - -int CertVerifyProcIOS::VerifyInternal( - X509Certificate* cert, - const std::string& hostname, - const std::string& ocsp_response, - int flags, - CRLSet* crl_set, - const CertificateList& additional_trust_anchors, - CertVerifyResult* verify_result) { - ScopedCFTypeRef<CFArrayRef> trust_policies; - OSStatus status = CreateTrustPolicies(&trust_policies); - if (status) - return NetErrorFromOSStatus(status); - - ScopedCFTypeRef<CFMutableArrayRef> cert_array( - cert->CreateOSCertChainForCert()); - ScopedCFTypeRef<SecTrustRef> trust_ref; - SecTrustResultType trust_result = kSecTrustResultDeny; - ScopedCFTypeRef<CFArrayRef> final_chain; - - status = BuildAndEvaluateSecTrustRef(cert_array, trust_policies, &trust_ref, - &final_chain, &trust_result); - if (status) - return NetErrorFromOSStatus(status); - - if (CFArrayGetCount(final_chain) == 0) - return ERR_FAILED; - - GetCertChainInfo(final_chain, verify_result); - - // TODO(sleevi): Support CRLSet revocation. - // TODO(svaldez): Add specific error codes for trust errors resulting from - // expired/not-yet-valid certs. - switch (trust_result) { - case kSecTrustResultUnspecified: - case kSecTrustResultProceed: - break; - case kSecTrustResultDeny: - verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID; - default: - verify_result->cert_status |= CERT_STATUS_INVALID; - } - - // Perform hostname verification independent of SecTrustEvaluate. - if (!verify_result->verified_cert->VerifyNameMatch( - hostname, &verify_result->common_name_fallback_used)) { - verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID; - } - - verify_result->is_issued_by_known_root = false; - - if (IsCertStatusError(verify_result->cert_status)) - return MapCertStatusToNetError(verify_result->cert_status); - - return OK; -} - -} // namespace net diff --git a/net/cert/cert_verify_proc_ios.h b/net/cert/cert_verify_proc_ios.h deleted file mode 100644 index e965a48..0000000 --- a/net/cert/cert_verify_proc_ios.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_CERT_CERT_VERIFY_PROC_IOS_H_ -#define NET_CERT_CERT_VERIFY_PROC_IOS_H_ - -#include "net/cert/cert_verify_proc.h" - -namespace net { - -// Performs certificate path construction and validation using iOS's -// Security.framework. -class CertVerifyProcIOS : public CertVerifyProc { - public: - CertVerifyProcIOS(); - - bool SupportsAdditionalTrustAnchors() const override; - bool SupportsOCSPStapling() const override; - - protected: - ~CertVerifyProcIOS() override; - - private: - int VerifyInternal(X509Certificate* cert, - const std::string& hostname, - const std::string& ocsp_response, - int flags, - CRLSet* crl_set, - const CertificateList& additional_trust_anchors, - CertVerifyResult* verify_result) override; -}; - -} // namespace net - -#endif // NET_CERT_CERT_VERIFY_PROC_IOS_H_ diff --git a/net/cert/x509_certificate_openssl_ios.cc b/net/cert/x509_certificate_openssl_ios.cc deleted file mode 100644 index 49a88d7..0000000 --- a/net/cert/x509_certificate_openssl_ios.cc +++ /dev/null @@ -1,475 +0,0 @@ -// Copyright (c) 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/cert/x509_certificate.h" - -#include <CommonCrypto/CommonDigest.h> -#include <Security/Security.h> - -#include <openssl/x509.h> -#include <openssl/x509v3.h> - -#include "base/mac/scoped_cftyperef.h" -#include "base/pickle.h" -#include "base/strings/string_piece.h" -#include "base/strings/string_util.h" -#include "crypto/openssl_util.h" -#include "crypto/scoped_openssl_types.h" -#include "net/base/ip_address_number.h" -#include "net/cert/x509_util_openssl.h" -#include "net/ssl/openssl_ssl_util.h" - -using base::ScopedCFTypeRef; - -namespace net { - -namespace { - -using ScopedGENERAL_NAMES = - crypto::ScopedOpenSSL<GENERAL_NAMES, GENERAL_NAMES_free>; - -// Returns true if a given |cert_handle| is actually a valid X.509 certificate -// handle. -// -// SecCertificateCreateFromData() does not always force the immediate parsing of -// the certificate, and as such, may return a SecCertificateRef for an -// invalid/unparsable certificate. Force parsing to occur to ensure that the -// SecCertificateRef is correct. On later versions where -// SecCertificateCreateFromData() immediately parses, rather than lazily, this -// call is cheap, as the subject is cached. -bool IsValidOSCertHandle(SecCertificateRef cert_handle) { - ScopedCFTypeRef<CFStringRef> sanity_check( - SecCertificateCopySubjectSummary(cert_handle)); - return sanity_check != nullptr; -} - -void CreateOSCertHandlesFromPKCS7Bytes( - const char* data, - size_t length, - X509Certificate::OSCertHandles* handles) { - crypto::EnsureOpenSSLInit(); - crypto::OpenSSLErrStackTracer err_cleaner(FROM_HERE); - - CBS der_data; - CBS_init(&der_data, reinterpret_cast<const uint8_t*>(data), length); - STACK_OF(X509)* certs = sk_X509_new_null(); - - if (PKCS7_get_certificates(certs, &der_data)) { - for (size_t i = 0; i < sk_X509_num(certs); ++i) { - X509* x509_cert = sk_X509_value(certs, i); - base::StringPiece der; - if (!x509_util::GetDER(x509_cert, &der)) - return; - handles->push_back(X509Certificate::CreateOSCertHandleFromBytes( - der.data(), der.length())); - } - } - sk_X509_pop_free(certs, X509_free); -} - -void ParsePrincipalValues(X509_NAME* name, - int nid, - std::vector<std::string>* fields) { - for (int index = -1; - (index = X509_NAME_get_index_by_NID(name, nid, index)) != -1;) { - std::string field; - if (!x509_util::ParsePrincipalValueByIndex(name, index, &field)) - break; - fields->push_back(field); - } -} - -void ParsePrincipal(X509Certificate::OSCertHandle os_cert, - X509_NAME* x509_name, - CertPrincipal* principal) { - if (!x509_name) - return; - - ParsePrincipalValues(x509_name, NID_streetAddress, - &principal->street_addresses); - ParsePrincipalValues(x509_name, NID_organizationName, - &principal->organization_names); - ParsePrincipalValues(x509_name, NID_organizationalUnitName, - &principal->organization_unit_names); - ParsePrincipalValues(x509_name, NID_domainComponent, - &principal->domain_components); - - x509_util::ParsePrincipalValueByNID(x509_name, NID_commonName, - &principal->common_name); - x509_util::ParsePrincipalValueByNID(x509_name, NID_localityName, - &principal->locality_name); - x509_util::ParsePrincipalValueByNID(x509_name, NID_stateOrProvinceName, - &principal->state_or_province_name); - x509_util::ParsePrincipalValueByNID(x509_name, NID_countryName, - &principal->country_name); -} - -void ParseSubjectAltName(X509Certificate::OSCertHandle os_cert, - std::vector<std::string>* dns_names, - std::vector<std::string>* ip_addresses) { - DCHECK(dns_names || ip_addresses); - ScopedX509 cert = OSCertHandleToOpenSSL(os_cert); - if (!cert.get()) - return; - int index = X509_get_ext_by_NID(cert.get(), NID_subject_alt_name, -1); - X509_EXTENSION* alt_name_ext = X509_get_ext(cert.get(), index); - if (!alt_name_ext) - return; - - ScopedGENERAL_NAMES alt_names( - reinterpret_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(alt_name_ext))); - if (!alt_names.get()) - return; - - for (size_t i = 0; i < sk_GENERAL_NAME_num(alt_names.get()); ++i) { - const GENERAL_NAME* name = sk_GENERAL_NAME_value(alt_names.get(), i); - if (name->type == GEN_DNS && dns_names) { - const unsigned char* dns_name = ASN1_STRING_data(name->d.dNSName); - if (!dns_name) - continue; - int dns_name_len = ASN1_STRING_length(name->d.dNSName); - dns_names->push_back( - std::string(reinterpret_cast<const char*>(dns_name), dns_name_len)); - } else if (name->type == GEN_IPADD && ip_addresses) { - const unsigned char* ip_addr = name->d.iPAddress->data; - if (!ip_addr) - continue; - int ip_addr_len = name->d.iPAddress->length; - if (ip_addr_len != static_cast<int>(kIPv4AddressSize) && - ip_addr_len != static_cast<int>(kIPv6AddressSize)) { - // http://www.ietf.org/rfc/rfc3280.txt requires subjectAltName iPAddress - // to have 4 or 16 bytes, whereas in a name constraint it includes a - // net mask hence 8 or 32 bytes. Logging to help diagnose any mixup. - LOG(WARNING) << "Bad sized IP Address in cert: " << ip_addr_len; - continue; - } - ip_addresses->push_back( - std::string(reinterpret_cast<const char*>(ip_addr), ip_addr_len)); - } - } -} - -// Used to free a list of X509_NAMEs and the objects it points to. -void sk_X509_NAME_free_all(STACK_OF(X509_NAME) * sk) { - sk_X509_NAME_pop_free(sk, X509_NAME_free); -} - -} // namespace - -// static -X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle( - OSCertHandle handle) { - if (!handle) - return nullptr; - return reinterpret_cast<OSCertHandle>(const_cast<void*>(CFRetain(handle))); -} - -// static -void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { - if (cert_handle) - CFRelease(cert_handle); -} - -void X509Certificate::Initialize() { - crypto::EnsureOpenSSLInit(); - fingerprint_ = CalculateFingerprint(cert_handle_); - ca_fingerprint_ = CalculateCAFingerprint(intermediate_ca_certs_); - ScopedX509 x509_cert = OSCertHandleToOpenSSL(cert_handle_); - if (!x509_cert) - return; - ASN1_INTEGER* serial_num = X509_get_serialNumber(x509_cert.get()); - if (serial_num) { - // ASN1_INTEGERS represent the decoded number, in a format internal to - // OpenSSL. Most notably, this may have leading zeroes stripped off for - // numbers whose first byte is >= 0x80. Thus, it is necessary to - // re-encoded the integer back into DER, which is what the interface - // of X509Certificate exposes, to ensure callers get the proper (DER) - // value. - int bytes_required = i2c_ASN1_INTEGER(serial_num, nullptr); - unsigned char* buffer = reinterpret_cast<unsigned char*>( - base::WriteInto(&serial_number_, bytes_required + 1)); - int bytes_written = i2c_ASN1_INTEGER(serial_num, &buffer); - DCHECK_EQ(static_cast<size_t>(bytes_written), serial_number_.size()); - } - - ParsePrincipal(cert_handle_, X509_get_subject_name(x509_cert.get()), - &subject_); - ParsePrincipal(cert_handle_, X509_get_issuer_name(x509_cert.get()), &issuer_); - x509_util::ParseDate(X509_get_notBefore(x509_cert.get()), &valid_start_); - x509_util::ParseDate(X509_get_notAfter(x509_cert.get()), &valid_expiry_); -} - -// static -SHA1HashValue X509Certificate::CalculateFingerprint(OSCertHandle cert) { - SHA1HashValue sha1; - memset(sha1.data, 0, sizeof(sha1.data)); - - ScopedCFTypeRef<CFDataRef> cert_data(SecCertificateCopyData(cert)); - if (!cert_data) - return sha1; - DCHECK(CFDataGetBytePtr(cert_data)); - DCHECK_NE(0, CFDataGetLength(cert_data)); - CC_SHA1(CFDataGetBytePtr(cert_data), CFDataGetLength(cert_data), sha1.data); - - return sha1; -} - -// static -SHA256HashValue X509Certificate::CalculateFingerprint256(OSCertHandle cert) { - SHA256HashValue sha256; - memset(sha256.data, 0, sizeof(sha256.data)); - - ScopedCFTypeRef<CFDataRef> cert_data(SecCertificateCopyData(cert)); - if (!cert_data) - return sha256; - DCHECK(CFDataGetBytePtr(cert_data)); - DCHECK_NE(0, CFDataGetLength(cert_data)); - CC_SHA256(CFDataGetBytePtr(cert_data), CFDataGetLength(cert_data), - sha256.data); - - return sha256; -} - -// static -SHA1HashValue X509Certificate::CalculateCAFingerprint( - const OSCertHandles& intermediates) { - SHA1HashValue sha1; - memset(sha1.data, 0, sizeof(sha1.data)); - - CC_SHA1_CTX sha1_ctx; - CC_SHA1_Init(&sha1_ctx); - for (size_t i = 0; i < intermediates.size(); ++i) { - ScopedCFTypeRef<CFDataRef> cert_data( - SecCertificateCopyData(intermediates[i])); - if (!cert_data) - return sha1; - CC_SHA1_Update(&sha1_ctx, CFDataGetBytePtr(cert_data), - CFDataGetLength(cert_data)); - } - CC_SHA1_Final(sha1.data, &sha1_ctx); - return sha1; -} - -// static -X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( - const char* data, - size_t length) { - ScopedCFTypeRef<CFDataRef> cert_data(CFDataCreateWithBytesNoCopy( - kCFAllocatorDefault, reinterpret_cast<const UInt8*>(data), - base::checked_cast<CFIndex>(length), kCFAllocatorNull)); - if (!cert_data) - return nullptr; - OSCertHandle cert_handle = SecCertificateCreateWithData(nullptr, cert_data); - if (!cert_handle) - return nullptr; - if (!IsValidOSCertHandle(cert_handle)) { - CFRelease(cert_handle); - return nullptr; - } - return cert_handle; -} - -// static -X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes( - const char* data, - size_t length, - Format format) { - OSCertHandles results; - - switch (format) { - case FORMAT_SINGLE_CERTIFICATE: { - OSCertHandle handle = - X509Certificate::CreateOSCertHandleFromBytes(data, length); - if (handle) - results.push_back(handle); - break; - } - case FORMAT_PKCS7: { - CreateOSCertHandlesFromPKCS7Bytes(data, length, &results); - break; - } - default: { - NOTREACHED() << "Certificate format " << format << " unimplemented"; - break; - } - } - - return results; -} - -void X509Certificate::GetSubjectAltName( - std::vector<std::string>* dns_names, - std::vector<std::string>* ip_addrs) const { - if (dns_names) - dns_names->clear(); - if (ip_addrs) - ip_addrs->clear(); - - ParseSubjectAltName(cert_handle_, dns_names, ip_addrs); -} - -// static -bool X509Certificate::GetDEREncoded(X509Certificate::OSCertHandle cert_handle, - std::string* encoded) { - base::StringPiece der; - if (!cert_handle) - return false; - ScopedCFTypeRef<CFDataRef> der_data(SecCertificateCopyData(cert_handle)); - if (!der_data) - return false; - encoded->assign(reinterpret_cast<const char*>(CFDataGetBytePtr(der_data)), - CFDataGetLength(der_data)); - return true; -} - -// static -bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a, - X509Certificate::OSCertHandle b) { - DCHECK(a && b); - return CFEqual(a, b); -} - -// static -X509Certificate::OSCertHandle X509Certificate::ReadOSCertHandleFromPickle( - base::PickleIterator* pickle_iter) { - const char* data; - int length; - if (!pickle_iter->ReadData(&data, &length)) - return nullptr; - - return X509Certificate::CreateOSCertHandleFromBytes(data, length); -} - -// static -bool X509Certificate::WriteOSCertHandleToPickle(OSCertHandle cert_handle, - base::Pickle* pickle) { - ScopedCFTypeRef<CFDataRef> cert_data(SecCertificateCopyData(cert_handle)); - if (!cert_data) - return false; - - return pickle->WriteData( - reinterpret_cast<const char*>(CFDataGetBytePtr(cert_data)), - CFDataGetLength(cert_data)); -} - -// static -void X509Certificate::GetPublicKeyInfo(OSCertHandle os_cert, - size_t* size_bits, - PublicKeyType* type) { - *type = kPublicKeyTypeUnknown; - *size_bits = 0; - ScopedX509 cert = OSCertHandleToOpenSSL(os_cert); - if (!cert) - return; - crypto::ScopedEVP_PKEY scoped_key(X509_get_pubkey(cert.get())); - if (!scoped_key) - return; - - EVP_PKEY* key = scoped_key.get(); - - switch (key->type) { - case EVP_PKEY_RSA: - *type = kPublicKeyTypeRSA; - break; - case EVP_PKEY_DSA: - *type = kPublicKeyTypeDSA; - break; - case EVP_PKEY_EC: - *type = kPublicKeyTypeECDSA; - break; - case EVP_PKEY_DH: - *type = kPublicKeyTypeDH; - break; - } - *size_bits = EVP_PKEY_bits(key); -} - -bool X509Certificate::SupportsSSLClientAuth() const { - return false; -} - -CFMutableArrayRef X509Certificate::CreateOSCertChainForCert() const { - CFMutableArrayRef cert_list = - CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - if (!cert_list) - return nullptr; - - CFArrayAppendValue(cert_list, os_cert_handle()); - for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) - CFArrayAppendValue(cert_list, intermediate_ca_certs_[i]); - - return cert_list; -} - -bool X509Certificate::IsIssuedByEncoded( - const std::vector<std::string>& valid_issuers) { - if (valid_issuers.empty()) - return false; - - // Convert to a temporary list of X509_NAME objects. - // It will own the objects it points to. - crypto::ScopedOpenSSL<STACK_OF(X509_NAME), sk_X509_NAME_free_all> - issuer_names(sk_X509_NAME_new_null()); - if (!issuer_names) - return false; - - for (std::vector<std::string>::const_iterator it = valid_issuers.begin(); - it != valid_issuers.end(); ++it) { - const unsigned char* p = reinterpret_cast<const unsigned char*>(it->data()); - long len = static_cast<long>(it->length()); - X509_NAME* ca_name = d2i_X509_NAME(nullptr, &p, len); - if (ca_name == nullptr) - return false; - sk_X509_NAME_push(issuer_names.get(), ca_name); - } - - // Create a temporary list of X509_NAME objects corresponding - // to the certificate chain. It doesn't own the object it points to. - std::vector<X509_NAME*> cert_names; - ScopedX509 x509_cert = OSCertHandleToOpenSSL(cert_handle_); - if (!x509_cert) - return false; - X509_NAME* issuer = X509_get_issuer_name(x509_cert.get()); - if (issuer == nullptr) - return false; - - cert_names.push_back(issuer); - for (OSCertHandles::iterator it = intermediate_ca_certs_.begin(); - it != intermediate_ca_certs_.end(); ++it) { - ScopedX509 intermediate_cert = OSCertHandleToOpenSSL(*it); - if (!intermediate_cert) - return false; - issuer = X509_get_issuer_name(intermediate_cert.get()); - if (issuer == nullptr) - return false; - cert_names.push_back(issuer); - } - - // and 'cert_names'. - for (size_t n = 0; n < cert_names.size(); ++n) { - for (size_t m = 0; m < sk_X509_NAME_num(issuer_names.get()); ++m) { - X509_NAME* issuer = sk_X509_NAME_value(issuer_names.get(), m); - if (X509_NAME_cmp(issuer, cert_names[n]) == 0) { - return true; - } - } - } - - return false; -} - -// static -bool X509Certificate::IsSelfSigned(OSCertHandle os_cert) { - ScopedX509 cert = OSCertHandleToOpenSSL(os_cert); - if (!cert) - return false; - crypto::ScopedEVP_PKEY scoped_key(X509_get_pubkey(cert.get())); - if (!scoped_key) - return false; - - // NOTE: X509_verify() returns 1 in case of success, 0 or -1 on error. - return X509_verify(cert.get(), scoped_key.get()) == 1; -} - -} // namespace net |