Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(267)

Side by Side Diff: net/cert/x509_certificate_openssl_ios.cc

Issue 1882433002: Removing NSS files and USE_OPENSSL flag (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase. Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/cert/x509_certificate_ios.cc ('k') | net/cert/x509_certificate_win.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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
OLDNEW
« no previous file with comments | « net/cert/x509_certificate_ios.cc ('k') | net/cert/x509_certificate_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698