OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "net/cert/x509_certificate.h" | |
6 | |
7 #include <CommonCrypto/CommonDigest.h> | |
8 #include <Security/Security.h> | |
9 | |
10 #include <openssl/x509.h> | |
11 #include <openssl/x509v3.h> | |
12 | |
13 #include "base/mac/scoped_cftyperef.h" | |
14 #include "base/pickle.h" | |
15 #include "base/strings/string_piece.h" | |
16 #include "base/strings/string_util.h" | |
17 #include "crypto/openssl_util.h" | |
18 #include "crypto/scoped_openssl_types.h" | |
19 #include "net/base/ip_address_number.h" | |
20 #include "net/cert/x509_util_openssl.h" | |
21 #include "net/ssl/openssl_ssl_util.h" | |
22 | |
23 using base::ScopedCFTypeRef; | |
24 | |
25 namespace net { | |
26 | |
27 namespace { | |
28 | |
29 using ScopedGENERAL_NAMES = | |
30 crypto::ScopedOpenSSL<GENERAL_NAMES, GENERAL_NAMES_free>; | |
31 | |
32 // Returns true if a given |cert_handle| is actually a valid X.509 certificate | |
33 // handle. | |
34 // | |
35 // SecCertificateCreateFromData() does not always force the immediate parsing of | |
36 // the certificate, and as such, may return a SecCertificateRef for an | |
37 // invalid/unparsable certificate. Force parsing to occur to ensure that the | |
38 // SecCertificateRef is correct. On later versions where | |
39 // SecCertificateCreateFromData() immediately parses, rather than lazily, this | |
40 // call is cheap, as the subject is cached. | |
41 bool IsValidOSCertHandle(SecCertificateRef cert_handle) { | |
42 ScopedCFTypeRef<CFStringRef> sanity_check( | |
43 SecCertificateCopySubjectSummary(cert_handle)); | |
44 return sanity_check != nullptr; | |
45 } | |
46 | |
47 void CreateOSCertHandlesFromPKCS7Bytes( | |
48 const char* data, | |
49 size_t length, | |
50 X509Certificate::OSCertHandles* handles) { | |
51 crypto::EnsureOpenSSLInit(); | |
52 crypto::OpenSSLErrStackTracer err_cleaner(FROM_HERE); | |
53 | |
54 CBS der_data; | |
55 CBS_init(&der_data, reinterpret_cast<const uint8_t*>(data), length); | |
56 STACK_OF(X509)* certs = sk_X509_new_null(); | |
57 | |
58 if (PKCS7_get_certificates(certs, &der_data)) { | |
59 for (size_t i = 0; i < sk_X509_num(certs); ++i) { | |
60 X509* x509_cert = sk_X509_value(certs, i); | |
61 base::StringPiece der; | |
62 if (!x509_util::GetDER(x509_cert, &der)) | |
63 return; | |
64 handles->push_back(X509Certificate::CreateOSCertHandleFromBytes( | |
65 der.data(), der.length())); | |
66 } | |
67 } | |
68 sk_X509_pop_free(certs, X509_free); | |
69 } | |
70 | |
71 void ParsePrincipalValues(X509_NAME* name, | |
72 int nid, | |
73 std::vector<std::string>* fields) { | |
74 for (int index = -1; | |
75 (index = X509_NAME_get_index_by_NID(name, nid, index)) != -1;) { | |
76 std::string field; | |
77 if (!x509_util::ParsePrincipalValueByIndex(name, index, &field)) | |
78 break; | |
79 fields->push_back(field); | |
80 } | |
81 } | |
82 | |
83 void ParsePrincipal(X509Certificate::OSCertHandle os_cert, | |
84 X509_NAME* x509_name, | |
85 CertPrincipal* principal) { | |
86 if (!x509_name) | |
87 return; | |
88 | |
89 ParsePrincipalValues(x509_name, NID_streetAddress, | |
90 &principal->street_addresses); | |
91 ParsePrincipalValues(x509_name, NID_organizationName, | |
92 &principal->organization_names); | |
93 ParsePrincipalValues(x509_name, NID_organizationalUnitName, | |
94 &principal->organization_unit_names); | |
95 ParsePrincipalValues(x509_name, NID_domainComponent, | |
96 &principal->domain_components); | |
97 | |
98 x509_util::ParsePrincipalValueByNID(x509_name, NID_commonName, | |
99 &principal->common_name); | |
100 x509_util::ParsePrincipalValueByNID(x509_name, NID_localityName, | |
101 &principal->locality_name); | |
102 x509_util::ParsePrincipalValueByNID(x509_name, NID_stateOrProvinceName, | |
103 &principal->state_or_province_name); | |
104 x509_util::ParsePrincipalValueByNID(x509_name, NID_countryName, | |
105 &principal->country_name); | |
106 } | |
107 | |
108 void ParseSubjectAltName(X509Certificate::OSCertHandle os_cert, | |
109 std::vector<std::string>* dns_names, | |
110 std::vector<std::string>* ip_addresses) { | |
111 DCHECK(dns_names || ip_addresses); | |
112 ScopedX509 cert = OSCertHandleToOpenSSL(os_cert); | |
113 if (!cert.get()) | |
114 return; | |
115 int index = X509_get_ext_by_NID(cert.get(), NID_subject_alt_name, -1); | |
116 X509_EXTENSION* alt_name_ext = X509_get_ext(cert.get(), index); | |
117 if (!alt_name_ext) | |
118 return; | |
119 | |
120 ScopedGENERAL_NAMES alt_names( | |
121 reinterpret_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(alt_name_ext))); | |
122 if (!alt_names.get()) | |
123 return; | |
124 | |
125 for (size_t i = 0; i < sk_GENERAL_NAME_num(alt_names.get()); ++i) { | |
126 const GENERAL_NAME* name = sk_GENERAL_NAME_value(alt_names.get(), i); | |
127 if (name->type == GEN_DNS && dns_names) { | |
128 const unsigned char* dns_name = ASN1_STRING_data(name->d.dNSName); | |
129 if (!dns_name) | |
130 continue; | |
131 int dns_name_len = ASN1_STRING_length(name->d.dNSName); | |
132 dns_names->push_back( | |
133 std::string(reinterpret_cast<const char*>(dns_name), dns_name_len)); | |
134 } else if (name->type == GEN_IPADD && ip_addresses) { | |
135 const unsigned char* ip_addr = name->d.iPAddress->data; | |
136 if (!ip_addr) | |
137 continue; | |
138 int ip_addr_len = name->d.iPAddress->length; | |
139 if (ip_addr_len != static_cast<int>(kIPv4AddressSize) && | |
140 ip_addr_len != static_cast<int>(kIPv6AddressSize)) { | |
141 // http://www.ietf.org/rfc/rfc3280.txt requires subjectAltName iPAddress | |
142 // to have 4 or 16 bytes, whereas in a name constraint it includes a | |
143 // net mask hence 8 or 32 bytes. Logging to help diagnose any mixup. | |
144 LOG(WARNING) << "Bad sized IP Address in cert: " << ip_addr_len; | |
145 continue; | |
146 } | |
147 ip_addresses->push_back( | |
148 std::string(reinterpret_cast<const char*>(ip_addr), ip_addr_len)); | |
149 } | |
150 } | |
151 } | |
152 | |
153 // Used to free a list of X509_NAMEs and the objects it points to. | |
154 void sk_X509_NAME_free_all(STACK_OF(X509_NAME) * sk) { | |
155 sk_X509_NAME_pop_free(sk, X509_NAME_free); | |
156 } | |
157 | |
158 } // namespace | |
159 | |
160 // static | |
161 X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle( | |
162 OSCertHandle handle) { | |
163 if (!handle) | |
164 return nullptr; | |
165 return reinterpret_cast<OSCertHandle>(const_cast<void*>(CFRetain(handle))); | |
166 } | |
167 | |
168 // static | |
169 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { | |
170 if (cert_handle) | |
171 CFRelease(cert_handle); | |
172 } | |
173 | |
174 void X509Certificate::Initialize() { | |
175 crypto::EnsureOpenSSLInit(); | |
176 fingerprint_ = CalculateFingerprint(cert_handle_); | |
177 ca_fingerprint_ = CalculateCAFingerprint(intermediate_ca_certs_); | |
178 ScopedX509 x509_cert = OSCertHandleToOpenSSL(cert_handle_); | |
179 if (!x509_cert) | |
180 return; | |
181 ASN1_INTEGER* serial_num = X509_get_serialNumber(x509_cert.get()); | |
182 if (serial_num) { | |
183 // ASN1_INTEGERS represent the decoded number, in a format internal to | |
184 // OpenSSL. Most notably, this may have leading zeroes stripped off for | |
185 // numbers whose first byte is >= 0x80. Thus, it is necessary to | |
186 // re-encoded the integer back into DER, which is what the interface | |
187 // of X509Certificate exposes, to ensure callers get the proper (DER) | |
188 // value. | |
189 int bytes_required = i2c_ASN1_INTEGER(serial_num, nullptr); | |
190 unsigned char* buffer = reinterpret_cast<unsigned char*>( | |
191 base::WriteInto(&serial_number_, bytes_required + 1)); | |
192 int bytes_written = i2c_ASN1_INTEGER(serial_num, &buffer); | |
193 DCHECK_EQ(static_cast<size_t>(bytes_written), serial_number_.size()); | |
194 } | |
195 | |
196 ParsePrincipal(cert_handle_, X509_get_subject_name(x509_cert.get()), | |
197 &subject_); | |
198 ParsePrincipal(cert_handle_, X509_get_issuer_name(x509_cert.get()), &issuer_); | |
199 x509_util::ParseDate(X509_get_notBefore(x509_cert.get()), &valid_start_); | |
200 x509_util::ParseDate(X509_get_notAfter(x509_cert.get()), &valid_expiry_); | |
201 } | |
202 | |
203 // static | |
204 SHA1HashValue X509Certificate::CalculateFingerprint(OSCertHandle cert) { | |
205 SHA1HashValue sha1; | |
206 memset(sha1.data, 0, sizeof(sha1.data)); | |
207 | |
208 ScopedCFTypeRef<CFDataRef> cert_data(SecCertificateCopyData(cert)); | |
209 if (!cert_data) | |
210 return sha1; | |
211 DCHECK(CFDataGetBytePtr(cert_data)); | |
212 DCHECK_NE(0, CFDataGetLength(cert_data)); | |
213 CC_SHA1(CFDataGetBytePtr(cert_data), CFDataGetLength(cert_data), sha1.data); | |
214 | |
215 return sha1; | |
216 } | |
217 | |
218 // static | |
219 SHA256HashValue X509Certificate::CalculateFingerprint256(OSCertHandle cert) { | |
220 SHA256HashValue sha256; | |
221 memset(sha256.data, 0, sizeof(sha256.data)); | |
222 | |
223 ScopedCFTypeRef<CFDataRef> cert_data(SecCertificateCopyData(cert)); | |
224 if (!cert_data) | |
225 return sha256; | |
226 DCHECK(CFDataGetBytePtr(cert_data)); | |
227 DCHECK_NE(0, CFDataGetLength(cert_data)); | |
228 CC_SHA256(CFDataGetBytePtr(cert_data), CFDataGetLength(cert_data), | |
229 sha256.data); | |
230 | |
231 return sha256; | |
232 } | |
233 | |
234 // static | |
235 SHA1HashValue X509Certificate::CalculateCAFingerprint( | |
236 const OSCertHandles& intermediates) { | |
237 SHA1HashValue sha1; | |
238 memset(sha1.data, 0, sizeof(sha1.data)); | |
239 | |
240 CC_SHA1_CTX sha1_ctx; | |
241 CC_SHA1_Init(&sha1_ctx); | |
242 for (size_t i = 0; i < intermediates.size(); ++i) { | |
243 ScopedCFTypeRef<CFDataRef> cert_data( | |
244 SecCertificateCopyData(intermediates[i])); | |
245 if (!cert_data) | |
246 return sha1; | |
247 CC_SHA1_Update(&sha1_ctx, CFDataGetBytePtr(cert_data), | |
248 CFDataGetLength(cert_data)); | |
249 } | |
250 CC_SHA1_Final(sha1.data, &sha1_ctx); | |
251 return sha1; | |
252 } | |
253 | |
254 // static | |
255 X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( | |
256 const char* data, | |
257 size_t length) { | |
258 ScopedCFTypeRef<CFDataRef> cert_data(CFDataCreateWithBytesNoCopy( | |
259 kCFAllocatorDefault, reinterpret_cast<const UInt8*>(data), | |
260 base::checked_cast<CFIndex>(length), kCFAllocatorNull)); | |
261 if (!cert_data) | |
262 return nullptr; | |
263 OSCertHandle cert_handle = SecCertificateCreateWithData(nullptr, cert_data); | |
264 if (!cert_handle) | |
265 return nullptr; | |
266 if (!IsValidOSCertHandle(cert_handle)) { | |
267 CFRelease(cert_handle); | |
268 return nullptr; | |
269 } | |
270 return cert_handle; | |
271 } | |
272 | |
273 // static | |
274 X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes( | |
275 const char* data, | |
276 size_t length, | |
277 Format format) { | |
278 OSCertHandles results; | |
279 | |
280 switch (format) { | |
281 case FORMAT_SINGLE_CERTIFICATE: { | |
282 OSCertHandle handle = | |
283 X509Certificate::CreateOSCertHandleFromBytes(data, length); | |
284 if (handle) | |
285 results.push_back(handle); | |
286 break; | |
287 } | |
288 case FORMAT_PKCS7: { | |
289 CreateOSCertHandlesFromPKCS7Bytes(data, length, &results); | |
290 break; | |
291 } | |
292 default: { | |
293 NOTREACHED() << "Certificate format " << format << " unimplemented"; | |
294 break; | |
295 } | |
296 } | |
297 | |
298 return results; | |
299 } | |
300 | |
301 void X509Certificate::GetSubjectAltName( | |
302 std::vector<std::string>* dns_names, | |
303 std::vector<std::string>* ip_addrs) const { | |
304 if (dns_names) | |
305 dns_names->clear(); | |
306 if (ip_addrs) | |
307 ip_addrs->clear(); | |
308 | |
309 ParseSubjectAltName(cert_handle_, dns_names, ip_addrs); | |
310 } | |
311 | |
312 // static | |
313 bool X509Certificate::GetDEREncoded(X509Certificate::OSCertHandle cert_handle, | |
314 std::string* encoded) { | |
315 base::StringPiece der; | |
316 if (!cert_handle) | |
317 return false; | |
318 ScopedCFTypeRef<CFDataRef> der_data(SecCertificateCopyData(cert_handle)); | |
319 if (!der_data) | |
320 return false; | |
321 encoded->assign(reinterpret_cast<const char*>(CFDataGetBytePtr(der_data)), | |
322 CFDataGetLength(der_data)); | |
323 return true; | |
324 } | |
325 | |
326 // static | |
327 bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a, | |
328 X509Certificate::OSCertHandle b) { | |
329 DCHECK(a && b); | |
330 return CFEqual(a, b); | |
331 } | |
332 | |
333 // static | |
334 X509Certificate::OSCertHandle X509Certificate::ReadOSCertHandleFromPickle( | |
335 base::PickleIterator* pickle_iter) { | |
336 const char* data; | |
337 int length; | |
338 if (!pickle_iter->ReadData(&data, &length)) | |
339 return nullptr; | |
340 | |
341 return X509Certificate::CreateOSCertHandleFromBytes(data, length); | |
342 } | |
343 | |
344 // static | |
345 bool X509Certificate::WriteOSCertHandleToPickle(OSCertHandle cert_handle, | |
346 base::Pickle* pickle) { | |
347 ScopedCFTypeRef<CFDataRef> cert_data(SecCertificateCopyData(cert_handle)); | |
348 if (!cert_data) | |
349 return false; | |
350 | |
351 return pickle->WriteData( | |
352 reinterpret_cast<const char*>(CFDataGetBytePtr(cert_data)), | |
353 CFDataGetLength(cert_data)); | |
354 } | |
355 | |
356 // static | |
357 void X509Certificate::GetPublicKeyInfo(OSCertHandle os_cert, | |
358 size_t* size_bits, | |
359 PublicKeyType* type) { | |
360 *type = kPublicKeyTypeUnknown; | |
361 *size_bits = 0; | |
362 ScopedX509 cert = OSCertHandleToOpenSSL(os_cert); | |
363 if (!cert) | |
364 return; | |
365 crypto::ScopedEVP_PKEY scoped_key(X509_get_pubkey(cert.get())); | |
366 if (!scoped_key) | |
367 return; | |
368 | |
369 EVP_PKEY* key = scoped_key.get(); | |
370 | |
371 switch (key->type) { | |
372 case EVP_PKEY_RSA: | |
373 *type = kPublicKeyTypeRSA; | |
374 break; | |
375 case EVP_PKEY_DSA: | |
376 *type = kPublicKeyTypeDSA; | |
377 break; | |
378 case EVP_PKEY_EC: | |
379 *type = kPublicKeyTypeECDSA; | |
380 break; | |
381 case EVP_PKEY_DH: | |
382 *type = kPublicKeyTypeDH; | |
383 break; | |
384 } | |
385 *size_bits = EVP_PKEY_bits(key); | |
386 } | |
387 | |
388 bool X509Certificate::SupportsSSLClientAuth() const { | |
389 return false; | |
390 } | |
391 | |
392 CFMutableArrayRef X509Certificate::CreateOSCertChainForCert() const { | |
393 CFMutableArrayRef cert_list = | |
394 CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); | |
395 if (!cert_list) | |
396 return nullptr; | |
397 | |
398 CFArrayAppendValue(cert_list, os_cert_handle()); | |
399 for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) | |
400 CFArrayAppendValue(cert_list, intermediate_ca_certs_[i]); | |
401 | |
402 return cert_list; | |
403 } | |
404 | |
405 bool X509Certificate::IsIssuedByEncoded( | |
406 const std::vector<std::string>& valid_issuers) { | |
407 if (valid_issuers.empty()) | |
408 return false; | |
409 | |
410 // Convert to a temporary list of X509_NAME objects. | |
411 // It will own the objects it points to. | |
412 crypto::ScopedOpenSSL<STACK_OF(X509_NAME), sk_X509_NAME_free_all> | |
413 issuer_names(sk_X509_NAME_new_null()); | |
414 if (!issuer_names) | |
415 return false; | |
416 | |
417 for (std::vector<std::string>::const_iterator it = valid_issuers.begin(); | |
418 it != valid_issuers.end(); ++it) { | |
419 const unsigned char* p = reinterpret_cast<const unsigned char*>(it->data()); | |
420 long len = static_cast<long>(it->length()); | |
421 X509_NAME* ca_name = d2i_X509_NAME(nullptr, &p, len); | |
422 if (ca_name == nullptr) | |
423 return false; | |
424 sk_X509_NAME_push(issuer_names.get(), ca_name); | |
425 } | |
426 | |
427 ScopedX509 x509_cert = OSCertHandleToOpenSSL(cert_handle_); | |
428 if (!x509_cert) | |
429 return false; | |
430 X509_NAME* cert_issuer = X509_get_issuer_name(x509_cert.get()); | |
431 if (cert_issuer == nullptr) | |
432 return false; | |
433 | |
434 for (size_t m = 0; m < sk_X509_NAME_num(issuer_names.get()); ++m) { | |
435 X509_NAME* issuer = sk_X509_NAME_value(issuer_names.get(), m); | |
436 if (X509_NAME_cmp(issuer, cert_issuer) == 0) { | |
437 return true; | |
438 } | |
439 } | |
440 | |
441 for (OSCertHandles::iterator it = intermediate_ca_certs_.begin(); | |
442 it != intermediate_ca_certs_.end(); ++it) { | |
443 ScopedX509 intermediate_cert = OSCertHandleToOpenSSL(*it); | |
444 if (!intermediate_cert) | |
445 return false; | |
446 cert_issuer = X509_get_issuer_name(intermediate_cert.get()); | |
447 if (cert_issuer == nullptr) | |
448 return false; | |
449 | |
450 for (size_t m = 0; m < sk_X509_NAME_num(issuer_names.get()); ++m) { | |
451 X509_NAME* issuer = sk_X509_NAME_value(issuer_names.get(), m); | |
452 if (X509_NAME_cmp(issuer, cert_issuer) == 0) { | |
453 return true; | |
454 } | |
455 } | |
456 } | |
457 | |
458 return false; | |
459 } | |
460 | |
461 // static | |
462 bool X509Certificate::IsSelfSigned(OSCertHandle os_cert) { | |
463 ScopedX509 cert = OSCertHandleToOpenSSL(os_cert); | |
464 if (!cert) | |
465 return false; | |
466 crypto::ScopedEVP_PKEY scoped_key(X509_get_pubkey(cert.get())); | |
467 if (!scoped_key) | |
468 return false; | |
469 | |
470 // NOTE: X509_verify() returns 1 in case of success, 0 or -1 on error. | |
471 return X509_verify(cert.get(), scoped_key.get()) == 1; | |
472 } | |
473 | |
474 } // namespace net | |
OLD | NEW |