Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/cert/x509_certificate.h" | 5 #include "net/cert/x509_certificate.h" |
| 6 | 6 |
| 7 #include <openssl/asn1.h> | 7 #include <CommonCrypto/CommonDigest.h> |
| 8 #include <openssl/bytestring.h> | 8 #include <Security/Security.h> |
| 9 #include <openssl/crypto.h> | 9 |
| 10 #include <openssl/obj_mac.h> | |
| 11 #include <openssl/pem.h> | |
| 12 #include <openssl/sha.h> | |
| 13 #include <openssl/ssl.h> | |
| 14 #include <openssl/x509v3.h> | 10 #include <openssl/x509v3.h> |
|
davidben
2016/03/21 19:46:47
I think this also needs an <openssl/x509.h>
svaldez
2016/03/21 20:23:52
Done.
| |
| 15 | 11 |
| 16 #include "base/macros.h" | 12 #include "base/mac/scoped_cftyperef.h" |
| 17 #include "base/memory/singleton.h" | |
| 18 #include "base/numerics/safe_conversions.h" | |
| 19 #include "base/pickle.h" | 13 #include "base/pickle.h" |
| 20 #include "base/sha1.h" | |
| 21 #include "base/strings/string_number_conversions.h" | |
| 22 #include "base/strings/string_piece.h" | 14 #include "base/strings/string_piece.h" |
| 23 #include "base/strings/string_util.h" | 15 #include "base/strings/string_util.h" |
| 24 #include "crypto/openssl_util.h" | 16 #include "crypto/openssl_util.h" |
| 25 #include "crypto/scoped_openssl_types.h" | 17 #include "crypto/scoped_openssl_types.h" |
| 26 #include "net/base/ip_address_number.h" | 18 #include "net/base/ip_address_number.h" |
| 27 #include "net/base/net_errors.h" | |
| 28 #include "net/cert/x509_util_openssl.h" | 19 #include "net/cert/x509_util_openssl.h" |
| 20 #include "net/ssl/openssl_ssl_util.h" | |
| 29 | 21 |
| 30 #if defined(OS_ANDROID) | 22 using base::ScopedCFTypeRef; |
| 31 #include "base/logging.h" | |
| 32 #include "net/android/network_library.h" | |
| 33 #endif | |
| 34 | 23 |
| 35 namespace net { | 24 namespace net { |
| 36 | 25 |
| 37 namespace { | 26 namespace { |
| 38 | 27 |
| 39 using ScopedGENERAL_NAMES = | 28 using ScopedGENERAL_NAMES = |
| 40 crypto::ScopedOpenSSL<GENERAL_NAMES, GENERAL_NAMES_free>; | 29 crypto::ScopedOpenSSL<GENERAL_NAMES, GENERAL_NAMES_free>; |
| 41 | 30 |
| 31 // Returns true if a given |cert_handle| is actually a valid X.509 certificate | |
| 32 // handle. | |
| 33 // | |
| 34 // SecCertificateCreateFromData() does not always force the immediate parsing of | |
| 35 // the certificate, and as such, may return a SecCertificateRef for an | |
| 36 // invalid/unparsable certificate. Force parsing to occur to ensure that the | |
| 37 // SecCertificateRef is correct. On later versions where | |
| 38 // SecCertificateCreateFromData() immediately parses, rather than lazily, this | |
| 39 // call is cheap, as the subject is cached. | |
| 40 bool IsValidOSCertHandle(SecCertificateRef cert_handle) { | |
| 41 ScopedCFTypeRef<CFStringRef> sanity_check( | |
| 42 SecCertificateCopySubjectSummary(cert_handle)); | |
| 43 return sanity_check != NULL; | |
| 44 } | |
| 45 | |
| 42 void CreateOSCertHandlesFromPKCS7Bytes( | 46 void CreateOSCertHandlesFromPKCS7Bytes( |
| 43 const char* data, | 47 const char* data, |
| 44 size_t length, | 48 size_t length, |
| 45 X509Certificate::OSCertHandles* handles) { | 49 X509Certificate::OSCertHandles* handles) { |
| 46 crypto::EnsureOpenSSLInit(); | 50 crypto::EnsureOpenSSLInit(); |
| 47 crypto::OpenSSLErrStackTracer err_cleaner(FROM_HERE); | 51 crypto::OpenSSLErrStackTracer err_cleaner(FROM_HERE); |
| 48 | 52 |
| 49 CBS der_data; | 53 CBS der_data; |
| 50 CBS_init(&der_data, reinterpret_cast<const uint8_t*>(data), length); | 54 CBS_init(&der_data, reinterpret_cast<const uint8_t*>(data), length); |
| 51 STACK_OF(X509)* certs = sk_X509_new_null(); | 55 STACK_OF(X509)* certs = sk_X509_new_null(); |
| 52 | 56 |
| 53 if (PKCS7_get_certificates(certs, &der_data)) { | 57 if (PKCS7_get_certificates(certs, &der_data)) { |
|
davidben
2016/03/21 19:46:47
[Hrm. I really should get you a non-crypto/x509 ve
svaldez
2016/03/21 20:23:52
Acknowledged.
| |
| 54 for (size_t i = 0; i < sk_X509_num(certs); ++i) { | 58 for (size_t i = 0; i < sk_X509_num(certs); ++i) { |
| 55 X509* x509_cert = | 59 X509* x509_cert = sk_X509_value(certs, i); |
| 56 X509Certificate::DupOSCertHandle(sk_X509_value(certs, i)); | 60 base::StringPiece der; |
| 57 handles->push_back(x509_cert); | 61 if (!x509_util::GetDER(x509_cert, &der)) |
| 62 return; | |
| 63 handles->push_back(X509Certificate::CreateOSCertHandleFromBytes( | |
| 64 der.data(), der.length())); | |
| 58 } | 65 } |
| 59 } | 66 } |
| 60 sk_X509_pop_free(certs, X509_free); | 67 sk_X509_pop_free(certs, X509_free); |
| 61 } | 68 } |
| 62 | 69 |
| 63 void ParsePrincipalValues(X509_NAME* name, | 70 void ParsePrincipalValues(X509_NAME* name, |
| 64 int nid, | 71 int nid, |
| 65 std::vector<std::string>* fields) { | 72 std::vector<std::string>* fields) { |
| 66 for (int index = -1; | 73 for (int index = -1; |
| 67 (index = X509_NAME_get_index_by_NID(name, nid, index)) != -1;) { | 74 (index = X509_NAME_get_index_by_NID(name, nid, index)) != -1;) { |
| 68 std::string field; | 75 std::string field; |
| 69 if (!x509_util::ParsePrincipalValueByIndex(name, index, &field)) | 76 if (!x509_util::ParsePrincipalValueByIndex(name, index, &field)) |
| 70 break; | 77 break; |
| 71 fields->push_back(field); | 78 fields->push_back(field); |
| 72 } | 79 } |
| 73 } | 80 } |
| 74 | 81 |
| 75 void ParsePrincipal(X509Certificate::OSCertHandle cert, | 82 void ParsePrincipal(X509Certificate::OSCertHandle os_cert, |
| 76 X509_NAME* x509_name, | 83 X509_NAME* x509_name, |
| 77 CertPrincipal* principal) { | 84 CertPrincipal* principal) { |
| 78 if (!x509_name) | 85 if (!x509_name) |
| 79 return; | 86 return; |
| 80 | 87 |
| 81 ParsePrincipalValues(x509_name, NID_streetAddress, | 88 ParsePrincipalValues(x509_name, NID_streetAddress, |
| 82 &principal->street_addresses); | 89 &principal->street_addresses); |
| 83 ParsePrincipalValues(x509_name, NID_organizationName, | 90 ParsePrincipalValues(x509_name, NID_organizationName, |
| 84 &principal->organization_names); | 91 &principal->organization_names); |
| 85 ParsePrincipalValues(x509_name, NID_organizationalUnitName, | 92 ParsePrincipalValues(x509_name, NID_organizationalUnitName, |
| 86 &principal->organization_unit_names); | 93 &principal->organization_unit_names); |
| 87 ParsePrincipalValues(x509_name, NID_domainComponent, | 94 ParsePrincipalValues(x509_name, NID_domainComponent, |
| 88 &principal->domain_components); | 95 &principal->domain_components); |
| 89 | 96 |
| 90 x509_util::ParsePrincipalValueByNID(x509_name, NID_commonName, | 97 x509_util::ParsePrincipalValueByNID(x509_name, NID_commonName, |
| 91 &principal->common_name); | 98 &principal->common_name); |
| 92 x509_util::ParsePrincipalValueByNID(x509_name, NID_localityName, | 99 x509_util::ParsePrincipalValueByNID(x509_name, NID_localityName, |
| 93 &principal->locality_name); | 100 &principal->locality_name); |
| 94 x509_util::ParsePrincipalValueByNID(x509_name, NID_stateOrProvinceName, | 101 x509_util::ParsePrincipalValueByNID(x509_name, NID_stateOrProvinceName, |
| 95 &principal->state_or_province_name); | 102 &principal->state_or_province_name); |
| 96 x509_util::ParsePrincipalValueByNID(x509_name, NID_countryName, | 103 x509_util::ParsePrincipalValueByNID(x509_name, NID_countryName, |
| 97 &principal->country_name); | 104 &principal->country_name); |
| 98 } | 105 } |
| 99 | 106 |
| 100 void ParseSubjectAltName(X509Certificate::OSCertHandle cert, | 107 void ParseSubjectAltName(X509Certificate::OSCertHandle os_cert, |
| 101 std::vector<std::string>* dns_names, | 108 std::vector<std::string>* dns_names, |
| 102 std::vector<std::string>* ip_addresses) { | 109 std::vector<std::string>* ip_addresses) { |
| 103 DCHECK(dns_names || ip_addresses); | 110 DCHECK(dns_names || ip_addresses); |
| 104 int index = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1); | 111 ScopedX509 cert = OSCertHandleToOpenSSL(os_cert); |
|
davidben
2016/03/21 19:46:47
Check for errors here. iOS and OpenSSL may have di
svaldez
2016/03/21 20:23:52
Done.
| |
| 105 X509_EXTENSION* alt_name_ext = X509_get_ext(cert, index); | 112 int index = X509_get_ext_by_NID(cert.get(), NID_subject_alt_name, -1); |
| 113 X509_EXTENSION* alt_name_ext = X509_get_ext(cert.get(), index); | |
| 106 if (!alt_name_ext) | 114 if (!alt_name_ext) |
| 107 return; | 115 return; |
| 108 | 116 |
| 109 ScopedGENERAL_NAMES alt_names( | 117 ScopedGENERAL_NAMES alt_names( |
| 110 reinterpret_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(alt_name_ext))); | 118 reinterpret_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(alt_name_ext))); |
| 111 if (!alt_names.get()) | 119 if (!alt_names.get()) |
| 112 return; | 120 return; |
| 113 | 121 |
| 114 for (size_t i = 0; i < sk_GENERAL_NAME_num(alt_names.get()); ++i) { | 122 for (size_t i = 0; i < sk_GENERAL_NAME_num(alt_names.get()); ++i) { |
| 115 const GENERAL_NAME* name = sk_GENERAL_NAME_value(alt_names.get(), i); | 123 const GENERAL_NAME* name = sk_GENERAL_NAME_value(alt_names.get(), i); |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 132 // net mask hence 8 or 32 bytes. Logging to help diagnose any mixup. | 140 // net mask hence 8 or 32 bytes. Logging to help diagnose any mixup. |
| 133 LOG(WARNING) << "Bad sized IP Address in cert: " << ip_addr_len; | 141 LOG(WARNING) << "Bad sized IP Address in cert: " << ip_addr_len; |
| 134 continue; | 142 continue; |
| 135 } | 143 } |
| 136 ip_addresses->push_back( | 144 ip_addresses->push_back( |
| 137 std::string(reinterpret_cast<const char*>(ip_addr), ip_addr_len)); | 145 std::string(reinterpret_cast<const char*>(ip_addr), ip_addr_len)); |
| 138 } | 146 } |
| 139 } | 147 } |
| 140 } | 148 } |
| 141 | 149 |
| 142 class X509InitSingleton { | |
| 143 public: | |
| 144 static X509InitSingleton* GetInstance() { | |
| 145 // We allow the X509 store to leak, because it is used from a non-joinable | |
| 146 // worker that is not stopped on shutdown, hence may still be using | |
| 147 // OpenSSL library after the AtExit runner has completed. | |
| 148 return base::Singleton<X509InitSingleton, base::LeakySingletonTraits< | |
| 149 X509InitSingleton>>::get(); | |
| 150 } | |
| 151 X509_STORE* store() const { return store_.get(); } | |
| 152 | |
| 153 void ResetCertStore() { | |
| 154 store_.reset(X509_STORE_new()); | |
| 155 DCHECK(store_.get()); | |
| 156 X509_STORE_set_default_paths(store_.get()); | |
| 157 // TODO(joth): Enable CRL (see X509_STORE_set_flags(X509_V_FLAG_CRL_CHECK)). | |
| 158 } | |
| 159 | |
| 160 private: | |
| 161 friend struct base::DefaultSingletonTraits<X509InitSingleton>; | |
| 162 X509InitSingleton() { | |
| 163 crypto::EnsureOpenSSLInit(); | |
| 164 ResetCertStore(); | |
| 165 } | |
| 166 | |
| 167 crypto::ScopedOpenSSL<X509_STORE, X509_STORE_free> store_; | |
| 168 | |
| 169 DISALLOW_COPY_AND_ASSIGN(X509InitSingleton); | |
| 170 }; | |
| 171 | |
| 172 // Used to free a list of X509_NAMEs and the objects it points to. | 150 // Used to free a list of X509_NAMEs and the objects it points to. |
| 173 void sk_X509_NAME_free_all(STACK_OF(X509_NAME)* sk) { | 151 void sk_X509_NAME_free_all(STACK_OF(X509_NAME) * sk) { |
| 174 sk_X509_NAME_pop_free(sk, X509_NAME_free); | 152 sk_X509_NAME_pop_free(sk, X509_NAME_free); |
| 175 } | 153 } |
| 176 | 154 |
| 177 } // namespace | 155 } // namespace |
| 178 | 156 |
| 179 // static | 157 // static |
| 180 X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle( | 158 X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle( |
| 181 OSCertHandle cert_handle) { | 159 OSCertHandle handle) { |
| 182 DCHECK(cert_handle); | 160 if (!handle) |
| 183 return X509_up_ref(cert_handle); | 161 return NULL; |
| 162 return reinterpret_cast<OSCertHandle>(const_cast<void*>(CFRetain(handle))); | |
| 184 } | 163 } |
| 185 | 164 |
| 186 // static | 165 // static |
| 187 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { | 166 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { |
| 188 // Decrement the ref-count for the cert and, if all references are gone, | 167 if (cert_handle) |
| 189 // free the memory and any application-specific data associated with the | 168 CFRelease(cert_handle); |
| 190 // certificate. | |
| 191 X509_free(cert_handle); | |
| 192 } | 169 } |
| 193 | 170 |
| 194 void X509Certificate::Initialize() { | 171 void X509Certificate::Initialize() { |
| 195 crypto::EnsureOpenSSLInit(); | 172 crypto::EnsureOpenSSLInit(); |
| 196 fingerprint_ = CalculateFingerprint(cert_handle_); | 173 fingerprint_ = CalculateFingerprint(cert_handle_); |
| 197 ca_fingerprint_ = CalculateCAFingerprint(intermediate_ca_certs_); | 174 ca_fingerprint_ = CalculateCAFingerprint(intermediate_ca_certs_); |
| 198 | 175 ScopedX509 x509_cert = OSCertHandleToOpenSSL(cert_handle_); |
| 199 ASN1_INTEGER* serial_num = X509_get_serialNumber(cert_handle_); | 176 ASN1_INTEGER* serial_num = X509_get_serialNumber(x509_cert.get()); |
| 200 if (serial_num) { | 177 if (serial_num) { |
| 201 // ASN1_INTEGERS represent the decoded number, in a format internal to | 178 // ASN1_INTEGERS represent the decoded number, in a format internal to |
| 202 // OpenSSL. Most notably, this may have leading zeroes stripped off for | 179 // OpenSSL. Most notably, this may have leading zeroes stripped off for |
| 203 // numbers whose first byte is >= 0x80. Thus, it is necessary to | 180 // numbers whose first byte is >= 0x80. Thus, it is necessary to |
| 204 // re-encoded the integer back into DER, which is what the interface | 181 // re-encoded the integer back into DER, which is what the interface |
| 205 // of X509Certificate exposes, to ensure callers get the proper (DER) | 182 // of X509Certificate exposes, to ensure callers get the proper (DER) |
| 206 // value. | 183 // value. |
| 207 int bytes_required = i2c_ASN1_INTEGER(serial_num, NULL); | 184 int bytes_required = i2c_ASN1_INTEGER(serial_num, NULL); |
| 208 unsigned char* buffer = reinterpret_cast<unsigned char*>( | 185 unsigned char* buffer = reinterpret_cast<unsigned char*>( |
| 209 base::WriteInto(&serial_number_, bytes_required + 1)); | 186 base::WriteInto(&serial_number_, bytes_required + 1)); |
| 210 int bytes_written = i2c_ASN1_INTEGER(serial_num, &buffer); | 187 int bytes_written = i2c_ASN1_INTEGER(serial_num, &buffer); |
| 211 DCHECK_EQ(static_cast<size_t>(bytes_written), serial_number_.size()); | 188 DCHECK_EQ(static_cast<size_t>(bytes_written), serial_number_.size()); |
| 212 } | 189 } |
| 213 | 190 |
| 214 ParsePrincipal(cert_handle_, X509_get_subject_name(cert_handle_), &subject_); | 191 ParsePrincipal(cert_handle_, X509_get_subject_name(x509_cert.get()), |
| 215 ParsePrincipal(cert_handle_, X509_get_issuer_name(cert_handle_), &issuer_); | 192 &subject_); |
| 216 x509_util::ParseDate(X509_get_notBefore(cert_handle_), &valid_start_); | 193 ParsePrincipal(cert_handle_, X509_get_issuer_name(x509_cert.get()), &issuer_); |
| 217 x509_util::ParseDate(X509_get_notAfter(cert_handle_), &valid_expiry_); | 194 x509_util::ParseDate(X509_get_notBefore(x509_cert.get()), &valid_start_); |
| 218 } | 195 x509_util::ParseDate(X509_get_notAfter(x509_cert.get()), &valid_expiry_); |
| 219 | |
| 220 // static | |
| 221 void X509Certificate::ResetCertStore() { | |
| 222 X509InitSingleton::GetInstance()->ResetCertStore(); | |
| 223 } | 196 } |
| 224 | 197 |
| 225 // static | 198 // static |
| 226 SHA1HashValue X509Certificate::CalculateFingerprint(OSCertHandle cert) { | 199 SHA1HashValue X509Certificate::CalculateFingerprint(OSCertHandle cert) { |
| 227 SHA1HashValue sha1; | 200 SHA1HashValue sha1; |
| 228 unsigned int sha1_size = static_cast<unsigned int>(sizeof(sha1.data)); | 201 memset(sha1.data, 0, sizeof(sha1.data)); |
| 229 int ret = X509_digest(cert, EVP_sha1(), sha1.data, &sha1_size); | 202 |
| 230 CHECK(ret); | 203 ScopedCFTypeRef<CFDataRef> cert_data(SecCertificateCopyData(cert)); |
| 231 CHECK_EQ(sha1_size, sizeof(sha1.data)); | 204 if (!cert_data) |
| 205 return sha1; | |
| 206 DCHECK(CFDataGetBytePtr(cert_data)); | |
| 207 DCHECK_NE(0, CFDataGetLength(cert_data)); | |
| 208 CC_SHA1(CFDataGetBytePtr(cert_data), CFDataGetLength(cert_data), sha1.data); | |
| 209 | |
| 232 return sha1; | 210 return sha1; |
| 233 } | 211 } |
| 234 | 212 |
| 235 // static | 213 // static |
| 236 SHA256HashValue X509Certificate::CalculateFingerprint256(OSCertHandle cert) { | 214 SHA256HashValue X509Certificate::CalculateFingerprint256(OSCertHandle cert) { |
| 237 SHA256HashValue sha256; | 215 SHA256HashValue sha256; |
| 238 unsigned int sha256_size = static_cast<unsigned int>(sizeof(sha256.data)); | 216 memset(sha256.data, 0, sizeof(sha256.data)); |
| 239 int ret = X509_digest(cert, EVP_sha256(), sha256.data, &sha256_size); | 217 |
| 240 CHECK(ret); | 218 ScopedCFTypeRef<CFDataRef> cert_data(SecCertificateCopyData(cert)); |
| 241 CHECK_EQ(sha256_size, sizeof(sha256.data)); | 219 if (!cert_data) |
| 220 return sha256; | |
| 221 DCHECK(CFDataGetBytePtr(cert_data)); | |
| 222 DCHECK_NE(0, CFDataGetLength(cert_data)); | |
| 223 CC_SHA256(CFDataGetBytePtr(cert_data), CFDataGetLength(cert_data), | |
| 224 sha256.data); | |
| 225 | |
| 242 return sha256; | 226 return sha256; |
| 243 } | 227 } |
| 244 | 228 |
| 245 // static | 229 // static |
| 246 SHA1HashValue X509Certificate::CalculateCAFingerprint( | 230 SHA1HashValue X509Certificate::CalculateCAFingerprint( |
| 247 const OSCertHandles& intermediates) { | 231 const OSCertHandles& intermediates) { |
| 248 SHA1HashValue sha1; | 232 SHA1HashValue sha1; |
| 249 memset(sha1.data, 0, sizeof(sha1.data)); | 233 memset(sha1.data, 0, sizeof(sha1.data)); |
| 250 | 234 |
| 251 SHA_CTX sha1_ctx; | 235 CC_SHA1_CTX sha1_ctx; |
| 252 SHA1_Init(&sha1_ctx); | 236 CC_SHA1_Init(&sha1_ctx); |
| 253 base::StringPiece der; | |
| 254 for (size_t i = 0; i < intermediates.size(); ++i) { | 237 for (size_t i = 0; i < intermediates.size(); ++i) { |
| 255 if (!x509_util::GetDER(intermediates[i], &der)) | 238 ScopedCFTypeRef<CFDataRef> cert_data( |
| 239 SecCertificateCopyData(intermediates[i])); | |
| 240 if (!cert_data) | |
| 256 return sha1; | 241 return sha1; |
| 257 SHA1_Update(&sha1_ctx, der.data(), der.length()); | 242 CC_SHA1_Update(&sha1_ctx, CFDataGetBytePtr(cert_data), |
| 243 CFDataGetLength(cert_data)); | |
| 258 } | 244 } |
| 259 SHA1_Final(sha1.data, &sha1_ctx); | 245 CC_SHA1_Final(sha1.data, &sha1_ctx); |
| 260 | |
| 261 return sha1; | 246 return sha1; |
| 262 } | 247 } |
| 263 | 248 |
| 264 // static | 249 // static |
| 265 X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( | 250 X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( |
| 266 const char* data, | 251 const char* data, |
| 267 size_t length) { | 252 size_t length) { |
| 268 crypto::EnsureOpenSSLInit(); | 253 ScopedCFTypeRef<CFDataRef> cert_data(CFDataCreateWithBytesNoCopy( |
| 269 const unsigned char* d2i_data = | 254 kCFAllocatorDefault, reinterpret_cast<const UInt8*>(data), |
| 270 reinterpret_cast<const unsigned char*>(data); | 255 base::checked_cast<CFIndex>(length), kCFAllocatorNull)); |
| 271 // Don't cache this data for x509_util::GetDER as this wire format | 256 if (!cert_data) |
| 272 // may be not be identical from the i2d_X509 roundtrip. | 257 return nullptr; |
| 273 X509* cert = d2i_X509(NULL, &d2i_data, base::checked_cast<long>(length)); | 258 OSCertHandle cert_handle = SecCertificateCreateWithData(NULL, cert_data); |
| 274 return cert; | 259 if (!cert_handle) |
| 260 return nullptr; | |
| 261 if (!IsValidOSCertHandle(cert_handle)) { | |
| 262 CFRelease(cert_handle); | |
| 263 return nullptr; | |
| 264 } | |
| 265 return cert_handle; | |
| 275 } | 266 } |
| 276 | 267 |
| 277 // static | 268 // static |
| 278 X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes( | 269 X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes( |
| 279 const char* data, | 270 const char* data, |
| 280 size_t length, | 271 size_t length, |
| 281 Format format) { | 272 Format format) { |
| 282 OSCertHandles results; | 273 OSCertHandles results; |
| 283 | 274 |
| 284 switch (format) { | 275 switch (format) { |
| 285 case FORMAT_SINGLE_CERTIFICATE: { | 276 case FORMAT_SINGLE_CERTIFICATE: { |
| 286 OSCertHandle handle = CreateOSCertHandleFromBytes(data, length); | 277 OSCertHandle handle = |
| 278 X509Certificate::CreateOSCertHandleFromBytes(data, length); | |
| 287 if (handle) | 279 if (handle) |
| 288 results.push_back(handle); | 280 results.push_back(handle); |
| 289 break; | 281 break; |
| 290 } | 282 } |
| 291 case FORMAT_PKCS7: { | 283 case FORMAT_PKCS7: { |
| 292 CreateOSCertHandlesFromPKCS7Bytes(data, length, &results); | 284 CreateOSCertHandlesFromPKCS7Bytes(data, length, &results); |
| 293 break; | 285 break; |
| 294 } | 286 } |
| 295 default: { | 287 default: { |
| 296 NOTREACHED() << "Certificate format " << format << " unimplemented"; | 288 NOTREACHED() << "Certificate format " << format << " unimplemented"; |
| 297 break; | 289 break; |
| 298 } | 290 } |
| 299 } | 291 } |
| 300 | 292 |
| 301 return results; | 293 return results; |
| 302 } | 294 } |
| 303 | 295 |
| 304 void X509Certificate::GetSubjectAltName( | 296 void X509Certificate::GetSubjectAltName( |
| 305 std::vector<std::string>* dns_names, | 297 std::vector<std::string>* dns_names, |
| 306 std::vector<std::string>* ip_addrs) const { | 298 std::vector<std::string>* ip_addrs) const { |
| 307 if (dns_names) | 299 if (dns_names) |
| 308 dns_names->clear(); | 300 dns_names->clear(); |
| 309 if (ip_addrs) | 301 if (ip_addrs) |
| 310 ip_addrs->clear(); | 302 ip_addrs->clear(); |
| 311 | 303 |
| 312 ParseSubjectAltName(cert_handle_, dns_names, ip_addrs); | 304 ParseSubjectAltName(cert_handle_, dns_names, ip_addrs); |
| 313 } | 305 } |
| 314 | 306 |
| 315 // static | 307 // static |
| 316 X509_STORE* X509Certificate::cert_store() { | |
| 317 return X509InitSingleton::GetInstance()->store(); | |
| 318 } | |
| 319 | |
| 320 // static | |
| 321 bool X509Certificate::GetDEREncoded(X509Certificate::OSCertHandle cert_handle, | 308 bool X509Certificate::GetDEREncoded(X509Certificate::OSCertHandle cert_handle, |
| 322 std::string* encoded) { | 309 std::string* encoded) { |
| 323 base::StringPiece der; | 310 base::StringPiece der; |
| 324 if (!cert_handle || !x509_util::GetDER(cert_handle, &der)) | 311 if (!cert_handle) |
| 325 return false; | 312 return false; |
| 326 encoded->assign(der.data(), der.length()); | 313 ScopedCFTypeRef<CFDataRef> der_data(SecCertificateCopyData(cert_handle)); |
| 314 if (!der_data) | |
| 315 return false; | |
| 316 encoded->assign(reinterpret_cast<const char*>(CFDataGetBytePtr(der_data)), | |
| 317 CFDataGetLength(der_data)); | |
| 327 return true; | 318 return true; |
| 328 } | 319 } |
| 329 | 320 |
| 330 // static | 321 // static |
| 331 bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a, | 322 bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a, |
| 332 X509Certificate::OSCertHandle b) { | 323 X509Certificate::OSCertHandle b) { |
| 333 DCHECK(a && b); | 324 DCHECK(a && b); |
| 334 if (a == b) | 325 if (a == b) |
| 335 return true; | 326 return true; |
| 336 | 327 if (CFEqual(a, b)) |
| 337 // X509_cmp only checks the fingerprint, but we want to compare the whole | 328 return true; |
| 338 // DER data. Encoding it from OSCertHandle is an expensive operation, so we | 329 ScopedCFTypeRef<CFDataRef> a_data(SecCertificateCopyData(a)); |
| 339 // cache the DER (if not already cached via X509_set_ex_data). | 330 ScopedCFTypeRef<CFDataRef> b_data(SecCertificateCopyData(b)); |
| 340 base::StringPiece der_a, der_b; | 331 return a_data && b_data && |
| 341 | 332 CFDataGetLength(a_data) == CFDataGetLength(b_data) && |
| 342 return x509_util::GetDER(a, &der_a) && | 333 memcmp(CFDataGetBytePtr(a_data), CFDataGetBytePtr(b_data), |
| 343 x509_util::GetDER(b, &der_b) && | 334 CFDataGetLength(a_data)) == 0; |
| 344 der_a == der_b; | |
| 345 } | 335 } |
| 346 | 336 |
| 347 // static | 337 // static |
| 348 X509Certificate::OSCertHandle X509Certificate::ReadOSCertHandleFromPickle( | 338 X509Certificate::OSCertHandle X509Certificate::ReadOSCertHandleFromPickle( |
| 349 base::PickleIterator* pickle_iter) { | 339 base::PickleIterator* pickle_iter) { |
| 350 const char* data; | 340 const char* data; |
| 351 int length; | 341 int length; |
| 352 if (!pickle_iter->ReadData(&data, &length)) | 342 if (!pickle_iter->ReadData(&data, &length)) |
| 353 return NULL; | 343 return NULL; |
| 354 | 344 |
| 355 return CreateOSCertHandleFromBytes(data, length); | 345 return X509Certificate::CreateOSCertHandleFromBytes(data, length); |
| 356 } | 346 } |
| 357 | 347 |
| 358 // static | 348 // static |
| 359 bool X509Certificate::WriteOSCertHandleToPickle(OSCertHandle cert_handle, | 349 bool X509Certificate::WriteOSCertHandleToPickle(OSCertHandle cert_handle, |
| 360 base::Pickle* pickle) { | 350 base::Pickle* pickle) { |
| 361 base::StringPiece der; | 351 ScopedCFTypeRef<CFDataRef> cert_data(SecCertificateCopyData(cert_handle)); |
| 362 if (!x509_util::GetDER(cert_handle, &der)) | 352 if (!cert_data) |
| 363 return false; | 353 return false; |
| 364 | 354 |
| 365 return pickle->WriteData(der.data(), der.length()); | 355 return pickle->WriteData( |
| 356 reinterpret_cast<const char*>(CFDataGetBytePtr(cert_data)), | |
| 357 CFDataGetLength(cert_data)); | |
| 366 } | 358 } |
| 367 | 359 |
| 368 // static | 360 // static |
| 369 void X509Certificate::GetPublicKeyInfo(OSCertHandle cert_handle, | 361 void X509Certificate::GetPublicKeyInfo(OSCertHandle os_cert, |
| 370 size_t* size_bits, | 362 size_t* size_bits, |
| 371 PublicKeyType* type) { | 363 PublicKeyType* type) { |
|
davidben
2016/03/21 19:46:47
I'm really puzzled why this can't be done from App
svaldez
2016/03/21 20:23:52
Because its iOS?
| |
| 372 *type = kPublicKeyTypeUnknown; | 364 *type = kPublicKeyTypeUnknown; |
| 373 *size_bits = 0; | 365 *size_bits = 0; |
| 374 | 366 ScopedX509 cert = OSCertHandleToOpenSSL(os_cert); |
| 375 crypto::ScopedEVP_PKEY scoped_key(X509_get_pubkey(cert_handle)); | 367 crypto::ScopedEVP_PKEY scoped_key(X509_get_pubkey(cert.get())); |
| 376 if (!scoped_key.get()) | 368 if (!scoped_key.get()) |
| 377 return; | 369 return; |
| 378 | 370 |
| 379 CHECK(scoped_key.get()); | 371 CHECK(scoped_key.get()); |
| 380 EVP_PKEY* key = scoped_key.get(); | 372 EVP_PKEY* key = scoped_key.get(); |
| 381 | 373 |
| 382 switch (key->type) { | 374 switch (key->type) { |
| 383 case EVP_PKEY_RSA: | 375 case EVP_PKEY_RSA: |
| 384 *type = kPublicKeyTypeRSA; | 376 *type = kPublicKeyTypeRSA; |
| 385 *size_bits = EVP_PKEY_size(key) * 8; | 377 *size_bits = EVP_PKEY_size(key) * 8; |
|
davidben
2016/03/21 19:46:47
I believe all of these want to be EVP_PKEY_bits(ke
svaldez
2016/03/21 20:23:52
Done.
| |
| 386 break; | 378 break; |
| 387 case EVP_PKEY_DSA: | 379 case EVP_PKEY_DSA: |
| 388 *type = kPublicKeyTypeDSA; | 380 *type = kPublicKeyTypeDSA; |
| 389 *size_bits = EVP_PKEY_size(key) * 8; | 381 *size_bits = EVP_PKEY_size(key) * 8; |
| 390 break; | 382 break; |
| 391 case EVP_PKEY_EC: | 383 case EVP_PKEY_EC: |
| 392 *type = kPublicKeyTypeECDSA; | 384 *type = kPublicKeyTypeECDSA; |
| 393 *size_bits = EVP_PKEY_bits(key); | 385 *size_bits = EVP_PKEY_bits(key); |
| 394 break; | 386 break; |
| 395 case EVP_PKEY_DH: | 387 case EVP_PKEY_DH: |
| 396 *type = kPublicKeyTypeDH; | 388 *type = kPublicKeyTypeDH; |
| 397 *size_bits = EVP_PKEY_size(key) * 8; | 389 *size_bits = EVP_PKEY_size(key) * 8; |
| 398 break; | 390 break; |
| 399 } | 391 } |
| 400 } | 392 } |
| 401 | 393 |
| 394 bool X509Certificate::SupportsSSLClientAuth() const { | |
| 395 return false; | |
| 396 } | |
| 397 | |
| 398 CFMutableArrayRef X509Certificate::CreateOSCertChainForCert() const { | |
| 399 CFMutableArrayRef cert_list = | |
| 400 CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); | |
| 401 if (!cert_list) | |
| 402 return NULL; | |
| 403 | |
| 404 CFArrayAppendValue(cert_list, os_cert_handle()); | |
| 405 for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) | |
| 406 CFArrayAppendValue(cert_list, intermediate_ca_certs_[i]); | |
| 407 | |
| 408 return cert_list; | |
| 409 } | |
| 410 | |
| 402 bool X509Certificate::IsIssuedByEncoded( | 411 bool X509Certificate::IsIssuedByEncoded( |
| 403 const std::vector<std::string>& valid_issuers) { | 412 const std::vector<std::string>& valid_issuers) { |
| 404 if (valid_issuers.empty()) | 413 if (valid_issuers.empty()) |
| 405 return false; | 414 return false; |
| 406 | 415 |
| 407 // Convert to a temporary list of X509_NAME objects. | 416 // Convert to a temporary list of X509_NAME objects. |
| 408 // It will own the objects it points to. | 417 // It will own the objects it points to. |
| 409 crypto::ScopedOpenSSL<STACK_OF(X509_NAME), sk_X509_NAME_free_all> | 418 crypto::ScopedOpenSSL<STACK_OF(X509_NAME), sk_X509_NAME_free_all> |
| 410 issuer_names(sk_X509_NAME_new_null()); | 419 issuer_names(sk_X509_NAME_new_null()); |
| 411 if (!issuer_names.get()) | 420 if (!issuer_names.get()) |
| 412 return false; | 421 return false; |
| 413 | 422 |
| 414 for (std::vector<std::string>::const_iterator it = valid_issuers.begin(); | 423 for (std::vector<std::string>::const_iterator it = valid_issuers.begin(); |
| 415 it != valid_issuers.end(); ++it) { | 424 it != valid_issuers.end(); ++it) { |
| 416 const unsigned char* p = | 425 const unsigned char* p = reinterpret_cast<const unsigned char*>(it->data()); |
| 417 reinterpret_cast<const unsigned char*>(it->data()); | |
| 418 long len = static_cast<long>(it->length()); | 426 long len = static_cast<long>(it->length()); |
| 419 X509_NAME* ca_name = d2i_X509_NAME(NULL, &p, len); | 427 X509_NAME* ca_name = d2i_X509_NAME(NULL, &p, len); |
| 420 if (ca_name == NULL) | 428 if (ca_name == NULL) |
| 421 return false; | 429 return false; |
| 422 sk_X509_NAME_push(issuer_names.get(), ca_name); | 430 sk_X509_NAME_push(issuer_names.get(), ca_name); |
| 423 } | 431 } |
| 424 | 432 |
| 425 // Create a temporary list of X509_NAME objects corresponding | 433 // Create a temporary list of X509_NAME objects corresponding |
| 426 // to the certificate chain. It doesn't own the object it points to. | 434 // to the certificate chain. It doesn't own the object it points to. |
| 427 std::vector<X509_NAME*> cert_names; | 435 std::vector<X509_NAME*> cert_names; |
| 428 X509_NAME* issuer = X509_get_issuer_name(cert_handle_); | 436 ScopedX509 x509_cert = OSCertHandleToOpenSSL(cert_handle_); |
| 437 X509_NAME* issuer = X509_get_issuer_name(x509_cert.get()); | |
| 429 if (issuer == NULL) | 438 if (issuer == NULL) |
| 430 return false; | 439 return false; |
| 431 | 440 |
| 432 cert_names.push_back(issuer); | 441 cert_names.push_back(issuer); |
| 433 for (OSCertHandles::iterator it = intermediate_ca_certs_.begin(); | 442 for (OSCertHandles::iterator it = intermediate_ca_certs_.begin(); |
| 434 it != intermediate_ca_certs_.end(); ++it) { | 443 it != intermediate_ca_certs_.end(); ++it) { |
| 435 issuer = X509_get_issuer_name(*it); | 444 ScopedX509 intermediate_cert = OSCertHandleToOpenSSL(*it); |
| 445 issuer = X509_get_issuer_name(intermediate_cert.get()); | |
| 436 if (issuer == NULL) | 446 if (issuer == NULL) |
| 437 return false; | 447 return false; |
| 438 cert_names.push_back(issuer); | 448 cert_names.push_back(issuer); |
| 439 } | 449 } |
| 440 | 450 |
| 441 // and 'cert_names'. | 451 // and 'cert_names'. |
| 442 for (size_t n = 0; n < cert_names.size(); ++n) { | 452 for (size_t n = 0; n < cert_names.size(); ++n) { |
| 443 for (size_t m = 0; m < sk_X509_NAME_num(issuer_names.get()); ++m) { | 453 for (size_t m = 0; m < sk_X509_NAME_num(issuer_names.get()); ++m) { |
| 444 X509_NAME* issuer = sk_X509_NAME_value(issuer_names.get(), m); | 454 X509_NAME* issuer = sk_X509_NAME_value(issuer_names.get(), m); |
| 445 if (X509_NAME_cmp(issuer, cert_names[n]) == 0) { | 455 if (X509_NAME_cmp(issuer, cert_names[n]) == 0) { |
| 446 return true; | 456 return true; |
| 447 } | 457 } |
| 448 } | 458 } |
| 449 } | 459 } |
| 450 | 460 |
| 451 return false; | 461 return false; |
| 452 } | 462 } |
| 453 | 463 |
| 454 // static | 464 // static |
| 455 bool X509Certificate::IsSelfSigned(OSCertHandle cert_handle) { | 465 bool X509Certificate::IsSelfSigned(OSCertHandle os_cert) { |
| 456 crypto::ScopedEVP_PKEY scoped_key(X509_get_pubkey(cert_handle)); | 466 ScopedX509 cert = OSCertHandleToOpenSSL(os_cert); |
| 467 crypto::ScopedEVP_PKEY scoped_key(X509_get_pubkey(cert.get())); | |
| 457 if (!scoped_key) | 468 if (!scoped_key) |
| 458 return false; | 469 return false; |
| 459 | 470 |
| 460 // NOTE: X509_verify() returns 1 in case of success, 0 or -1 on error. | 471 // NOTE: X509_verify() returns 1 in case of success, 0 or -1 on error. |
| 461 return X509_verify(cert_handle, scoped_key.get()) == 1; | 472 return X509_verify(cert.get(), scoped_key.get()) == 1; |
| 462 } | 473 } |
| 463 | 474 |
| 464 } // namespace net | 475 } // namespace net |
| OLD | NEW |