OLD | NEW |
1 // Copyright (c) 2016 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 <CommonCrypto/CommonDigest.h> | 7 #include <CommonCrypto/CommonDigest.h> |
8 #include <Security/Security.h> | 8 #include <Security/Security.h> |
9 | 9 |
10 #include "base/mac/scoped_cftyperef.h" | 10 #include "base/mac/scoped_cftyperef.h" |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
93 x509_util::ParsePrincipalValueByNID(x509_name, NID_commonName, | 93 x509_util::ParsePrincipalValueByNID(x509_name, NID_commonName, |
94 &principal->common_name); | 94 &principal->common_name); |
95 x509_util::ParsePrincipalValueByNID(x509_name, NID_localityName, | 95 x509_util::ParsePrincipalValueByNID(x509_name, NID_localityName, |
96 &principal->locality_name); | 96 &principal->locality_name); |
97 x509_util::ParsePrincipalValueByNID(x509_name, NID_stateOrProvinceName, | 97 x509_util::ParsePrincipalValueByNID(x509_name, NID_stateOrProvinceName, |
98 &principal->state_or_province_name); | 98 &principal->state_or_province_name); |
99 x509_util::ParsePrincipalValueByNID(x509_name, NID_countryName, | 99 x509_util::ParsePrincipalValueByNID(x509_name, NID_countryName, |
100 &principal->country_name); | 100 &principal->country_name); |
101 } | 101 } |
102 | 102 |
103 void ParseSubjectAltName(X509Certificate::OSCertHandle os_cert, | 103 bool ParseSubjectAltName(X509Certificate::OSCertHandle os_cert, |
104 std::vector<std::string>* dns_names, | 104 std::vector<std::string>* dns_names, |
105 std::vector<std::string>* ip_addresses) { | 105 std::vector<std::string>* ip_addresses) { |
106 DCHECK(dns_names || ip_addresses); | |
107 bssl::UniquePtr<X509> cert = OSCertHandleToOpenSSL(os_cert); | 106 bssl::UniquePtr<X509> cert = OSCertHandleToOpenSSL(os_cert); |
108 if (!cert.get()) | 107 if (!cert.get()) |
109 return; | 108 return false; |
110 int index = X509_get_ext_by_NID(cert.get(), NID_subject_alt_name, -1); | 109 int index = X509_get_ext_by_NID(cert.get(), NID_subject_alt_name, -1); |
111 X509_EXTENSION* alt_name_ext = X509_get_ext(cert.get(), index); | 110 X509_EXTENSION* alt_name_ext = X509_get_ext(cert.get(), index); |
112 if (!alt_name_ext) | 111 if (!alt_name_ext) |
113 return; | 112 return false; |
114 | 113 |
115 bssl::UniquePtr<GENERAL_NAMES> alt_names( | 114 bssl::UniquePtr<GENERAL_NAMES> alt_names( |
116 reinterpret_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(alt_name_ext))); | 115 reinterpret_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(alt_name_ext))); |
117 if (!alt_names.get()) | 116 if (!alt_names.get()) |
118 return; | 117 return false; |
119 | 118 |
| 119 bool has_san = false; |
120 for (size_t i = 0; i < sk_GENERAL_NAME_num(alt_names.get()); ++i) { | 120 for (size_t i = 0; i < sk_GENERAL_NAME_num(alt_names.get()); ++i) { |
121 const GENERAL_NAME* name = sk_GENERAL_NAME_value(alt_names.get(), i); | 121 const GENERAL_NAME* name = sk_GENERAL_NAME_value(alt_names.get(), i); |
122 if (name->type == GEN_DNS && dns_names) { | 122 if (name->type == GEN_DNS) { |
123 const unsigned char* dns_name = ASN1_STRING_data(name->d.dNSName); | 123 has_san = true; |
124 if (!dns_name) | 124 if (dns_names) { |
125 continue; | 125 const unsigned char* dns_name = ASN1_STRING_data(name->d.dNSName); |
126 int dns_name_len = ASN1_STRING_length(name->d.dNSName); | 126 int dns_name_len = ASN1_STRING_length(name->d.dNSName); |
127 dns_names->push_back( | 127 dns_names->push_back( |
128 std::string(reinterpret_cast<const char*>(dns_name), dns_name_len)); | 128 base::StringPiece(reinterpret_cast<const char*>(dns_name), |
129 } else if (name->type == GEN_IPADD && ip_addresses) { | 129 dns_name_len) |
130 const unsigned char* ip_addr = name->d.iPAddress->data; | 130 .as_string()); |
131 if (!ip_addr) | |
132 continue; | |
133 int ip_addr_len = name->d.iPAddress->length; | |
134 if (ip_addr_len != static_cast<int>(IPAddress::kIPv4AddressSize) && | |
135 ip_addr_len != static_cast<int>(IPAddress::kIPv6AddressSize)) { | |
136 // http://www.ietf.org/rfc/rfc3280.txt requires subjectAltName iPAddress | |
137 // to have 4 or 16 bytes, whereas in a name constraint it includes a | |
138 // net mask hence 8 or 32 bytes. Logging to help diagnose any mixup. | |
139 LOG(WARNING) << "Bad sized IP Address in cert: " << ip_addr_len; | |
140 continue; | |
141 } | 131 } |
142 ip_addresses->push_back( | 132 } else if (name->type == GEN_IPADD) { |
143 std::string(reinterpret_cast<const char*>(ip_addr), ip_addr_len)); | 133 has_san = true; |
| 134 if (ip_addresses) { |
| 135 const unsigned char* ip_addr = name->d.iPAddress->data; |
| 136 int ip_addr_len = name->d.iPAddress->length; |
| 137 ip_addresses->push_back( |
| 138 base::StringPiece(reinterpret_cast<const char*>(ip_addr), |
| 139 ip_addr_len) |
| 140 .as_string()); |
| 141 } |
144 } | 142 } |
| 143 // Fast path: Found at least one subjectAltName and the caller doesn't |
| 144 // need the actual values. |
| 145 if (has_san && !ip_addresses && !dns_names) |
| 146 return true; |
145 } | 147 } |
| 148 |
| 149 return has_san; |
146 } | 150 } |
147 | 151 |
148 } // namespace | 152 } // namespace |
149 | 153 |
150 // static | 154 // static |
151 X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle( | 155 X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle( |
152 OSCertHandle handle) { | 156 OSCertHandle handle) { |
153 if (!handle) | 157 if (!handle) |
154 return nullptr; | 158 return nullptr; |
155 return reinterpret_cast<OSCertHandle>(const_cast<void*>(CFRetain(handle))); | 159 return reinterpret_cast<OSCertHandle>(const_cast<void*>(CFRetain(handle))); |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
264 } | 268 } |
265 default: { | 269 default: { |
266 NOTREACHED() << "Certificate format " << format << " unimplemented"; | 270 NOTREACHED() << "Certificate format " << format << " unimplemented"; |
267 break; | 271 break; |
268 } | 272 } |
269 } | 273 } |
270 | 274 |
271 return results; | 275 return results; |
272 } | 276 } |
273 | 277 |
274 void X509Certificate::GetSubjectAltName( | 278 bool X509Certificate::GetSubjectAltName( |
275 std::vector<std::string>* dns_names, | 279 std::vector<std::string>* dns_names, |
276 std::vector<std::string>* ip_addrs) const { | 280 std::vector<std::string>* ip_addrs) const { |
277 if (dns_names) | 281 if (dns_names) |
278 dns_names->clear(); | 282 dns_names->clear(); |
279 if (ip_addrs) | 283 if (ip_addrs) |
280 ip_addrs->clear(); | 284 ip_addrs->clear(); |
281 | 285 |
282 ParseSubjectAltName(cert_handle_, dns_names, ip_addrs); | 286 return ParseSubjectAltName(cert_handle_, dns_names, ip_addrs); |
283 } | 287 } |
284 | 288 |
285 // static | 289 // static |
286 bool X509Certificate::GetDEREncoded(X509Certificate::OSCertHandle cert_handle, | 290 bool X509Certificate::GetDEREncoded(X509Certificate::OSCertHandle cert_handle, |
287 std::string* encoded) { | 291 std::string* encoded) { |
288 base::StringPiece der; | 292 base::StringPiece der; |
289 if (!cert_handle) | 293 if (!cert_handle) |
290 return false; | 294 return false; |
291 ScopedCFTypeRef<CFDataRef> der_data(SecCertificateCopyData(cert_handle)); | 295 ScopedCFTypeRef<CFDataRef> der_data(SecCertificateCopyData(cert_handle)); |
292 if (!der_data) | 296 if (!der_data) |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
437 return false; | 441 return false; |
438 bssl::UniquePtr<EVP_PKEY> scoped_key(X509_get_pubkey(cert.get())); | 442 bssl::UniquePtr<EVP_PKEY> scoped_key(X509_get_pubkey(cert.get())); |
439 if (!scoped_key) | 443 if (!scoped_key) |
440 return false; | 444 return false; |
441 if (!X509_verify(cert.get(), scoped_key.get())) | 445 if (!X509_verify(cert.get(), scoped_key.get())) |
442 return false; | 446 return false; |
443 return X509_check_issued(cert.get(), cert.get()) == X509_V_OK; | 447 return X509_check_issued(cert.get(), cert.get()) == X509_V_OK; |
444 } | 448 } |
445 | 449 |
446 } // namespace net | 450 } // namespace net |
OLD | NEW |