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

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

Issue 2746103003: Add X509CertificateBytes which uses CRYPTO_BUFFER instead of macOS-native certificate types. (Closed)
Patch Set: rebase Created 3 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.cc ('k') | net/cert/x509_certificate_mac.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 2017 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 "base/numerics/safe_conversions.h"
8 #include "base/pickle.h"
9 #include "crypto/openssl_util.h"
10 #include "net/base/ip_address.h"
11 #include "net/cert/asn1_util.h"
12 #include "net/cert/internal/cert_errors.h"
13 #include "net/cert/internal/name_constraints.h"
14 #include "net/cert/internal/parse_name.h"
15 #include "net/cert/internal/parsed_certificate.h"
16 #include "net/cert/internal/signature_policy.h"
17 #include "net/cert/internal/verify_name_match.h"
18 #include "net/cert/internal/verify_signed_data.h"
19 #include "net/cert/x509_util.h"
20 #include "net/cert/x509_util_openssl.h"
21 #include "net/der/parser.h"
22 #include "third_party/boringssl/src/include/openssl/evp.h"
23 #include "third_party/boringssl/src/include/openssl/pool.h"
24 #include "third_party/boringssl/src/include/openssl/sha.h"
25
26 namespace net {
27
28 namespace {
29
30 // Converts a GeneralizedTime struct to a base::Time, returning true on success
31 // or false if |generalized| was invalid or cannot be represented by
32 // base::Time.
33 bool GeneralizedTimeToBaseTime(const der::GeneralizedTime& generalized,
34 base::Time* result) {
35 base::Time::Exploded exploded = {0};
36 exploded.year = generalized.year;
37 exploded.month = generalized.month;
38 exploded.day_of_month = generalized.day;
39 exploded.hour = generalized.hours;
40 exploded.minute = generalized.minutes;
41 exploded.second = generalized.seconds;
42 return base::Time::FromUTCExploded(exploded, result);
43 }
44
45 // Sets |value| to the Value from a DER Sequence Tag-Length-Value and return
46 // true, or return false if the TLV was not a valid DER Sequence.
47 WARN_UNUSED_RESULT bool GetSequenceValue(const der::Input& tlv,
48 der::Input* value) {
49 der::Parser parser(tlv);
50 return parser.ReadTag(der::kSequence, value) && !parser.HasMore();
51 }
52
53 // Normalize |cert|'s Issuer and store it in |out_normalized_issuer|, returning
54 // true on success or false if there was a parsing error.
55 bool GetNormalizedCertIssuer(CRYPTO_BUFFER* cert,
56 std::string* out_normalized_issuer) {
57 der::Input tbs_certificate_tlv;
58 der::Input signature_algorithm_tlv;
59 der::BitString signature_value;
60 if (!ParseCertificate(
61 der::Input(CRYPTO_BUFFER_data(cert), CRYPTO_BUFFER_len(cert)),
62 &tbs_certificate_tlv, &signature_algorithm_tlv, &signature_value,
63 nullptr)) {
64 return false;
65 }
66 ParsedTbsCertificate tbs;
67 if (!ParseTbsCertificate(tbs_certificate_tlv, {}, &tbs, nullptr))
68 return false;
69
70 der::Input issuer_value;
71 if (!GetSequenceValue(tbs.issuer_tlv, &issuer_value))
72 return false;
73
74 return NormalizeName(issuer_value, out_normalized_issuer);
75 }
76
77 // Fills |principal| from the DER encoded |name_tlv|, returning true on success
78 // or false if parsing failed or some of the values could not be converted to
79 // UTF-8.
80 bool ParsePrincipal(const der::Input& name_tlv, CertPrincipal* principal) {
81 RDNSequence rdns;
82 if (!ParseName(name_tlv, &rdns))
83 return false;
84
85 for (const RelativeDistinguishedName& rdn : rdns) {
86 for (const X509NameAttribute& name_attribute : rdn) {
87 if (name_attribute.type == TypeCommonNameOid()) {
88 if (principal->common_name.empty() &&
89 !name_attribute.ValueAsString(&principal->common_name)) {
90 return false;
91 }
92 } else if (name_attribute.type == TypeLocalityNameOid()) {
93 if (principal->locality_name.empty() &&
94 !name_attribute.ValueAsString(&principal->locality_name)) {
95 return false;
96 }
97 } else if (name_attribute.type == TypeStateOrProvinceNameOid()) {
98 if (principal->state_or_province_name.empty() &&
99 !name_attribute.ValueAsString(&principal->state_or_province_name)) {
100 return false;
101 }
102 } else if (name_attribute.type == TypeCountryNameOid()) {
103 if (principal->country_name.empty() &&
104 !name_attribute.ValueAsString(&principal->country_name)) {
105 return false;
106 }
107 } else if (name_attribute.type == TypeStreetAddressOid()) {
108 std::string s;
109 if (!name_attribute.ValueAsString(&s))
110 return false;
111 principal->street_addresses.push_back(s);
112 } else if (name_attribute.type == TypeOrganizationNameOid()) {
113 std::string s;
114 if (!name_attribute.ValueAsString(&s))
115 return false;
116 principal->organization_names.push_back(s);
117 } else if (name_attribute.type == TypeOrganizationUnitNameOid()) {
118 std::string s;
119 if (!name_attribute.ValueAsString(&s))
120 return false;
121 principal->organization_unit_names.push_back(s);
122 } else if (name_attribute.type == TypeDomainComponentOid()) {
123 std::string s;
124 if (!name_attribute.ValueAsString(&s))
125 return false;
126 principal->domain_components.push_back(s);
127 }
128 }
129 }
130 return true;
131 }
132
133 // Parses certificates from a PKCS#7 SignedData structure, appending them to
134 // |handles|.
135 void CreateOSCertHandlesFromPKCS7Bytes(
136 const char* data,
137 size_t length,
138 X509Certificate::OSCertHandles* handles) {
139 crypto::EnsureOpenSSLInit();
140 crypto::OpenSSLErrStackTracer err_cleaner(FROM_HERE);
141
142 CBS der_data;
143 CBS_init(&der_data, reinterpret_cast<const uint8_t*>(data), length);
144 STACK_OF(X509)* certs = sk_X509_new_null();
145
146 if (PKCS7_get_certificates(certs, &der_data)) {
147 for (size_t i = 0; i < sk_X509_num(certs); ++i) {
148 base::StringPiece stringpiece;
149 x509_util::GetDER(sk_X509_value(certs, i), &stringpiece);
150 handles->push_back(x509_util::CreateCryptoBuffer(stringpiece).release());
151 }
152 }
153 sk_X509_pop_free(certs, X509_free);
154 }
155
156 } // namespace
157
158 bool X509Certificate::Initialize() {
159 der::Input tbs_certificate_tlv;
160 der::Input signature_algorithm_tlv;
161 der::BitString signature_value;
162
163 if (!ParseCertificate(der::Input(CRYPTO_BUFFER_data(cert_handle_),
164 CRYPTO_BUFFER_len(cert_handle_)),
165 &tbs_certificate_tlv, &signature_algorithm_tlv,
166 &signature_value, nullptr)) {
167 return false;
168 }
169
170 ParsedTbsCertificate tbs;
171 if (!ParseTbsCertificate(tbs_certificate_tlv, {}, &tbs, nullptr))
172 return false;
173
174 if (!ParsePrincipal(tbs.subject_tlv, &subject_) ||
175 !ParsePrincipal(tbs.issuer_tlv, &issuer_)) {
176 return false;
177 }
178
179 if (!GeneralizedTimeToBaseTime(tbs.validity_not_before, &valid_start_) ||
180 !GeneralizedTimeToBaseTime(tbs.validity_not_after, &valid_expiry_)) {
181 return false;
182 }
183 serial_number_ = tbs.serial_number.AsString();
184 return true;
185 }
186
187 bool X509Certificate::GetSubjectAltName(
188 std::vector<std::string>* dns_names,
189 std::vector<std::string>* ip_addrs) const {
190 if (dns_names)
191 dns_names->clear();
192 if (ip_addrs)
193 ip_addrs->clear();
194
195 der::Input tbs_certificate_tlv;
196 der::Input signature_algorithm_tlv;
197 der::BitString signature_value;
198 if (!ParseCertificate(der::Input(CRYPTO_BUFFER_data(cert_handle_),
199 CRYPTO_BUFFER_len(cert_handle_)),
200 &tbs_certificate_tlv, &signature_algorithm_tlv,
201 &signature_value, nullptr)) {
202 return false;
203 }
204
205 ParsedTbsCertificate tbs;
206 if (!ParseTbsCertificate(tbs_certificate_tlv, {}, &tbs, nullptr))
207 return false;
208 if (!tbs.has_extensions)
209 return false;
210
211 std::map<der::Input, ParsedExtension> extensions;
212 if (!ParseExtensions(tbs.extensions_tlv, &extensions))
213 return false;
214
215 ParsedExtension subject_alt_names_extension;
216 if (!ConsumeExtension(SubjectAltNameOid(), &extensions,
217 &subject_alt_names_extension)) {
218 return false;
219 }
220
221 std::unique_ptr<GeneralNames> subject_alt_names =
222 GeneralNames::Create(subject_alt_names_extension.value);
223 if (!subject_alt_names)
224 return false;
225
226 if (dns_names)
227 *dns_names = subject_alt_names->dns_names;
228 if (ip_addrs) {
229 for (const IPAddress& addr : subject_alt_names->ip_addresses) {
230 ip_addrs->push_back(
231 std::string(reinterpret_cast<const char*>(addr.bytes().data()),
232 addr.bytes().size()));
233 }
234 }
235
236 return !subject_alt_names->dns_names.empty() ||
237 !subject_alt_names->ip_addresses.empty();
238 }
239
240 bool X509Certificate::IsIssuedByEncoded(
241 const std::vector<std::string>& valid_issuers) {
242 std::vector<std::string> normalized_issuers;
243 for (const auto& raw_issuer : valid_issuers) {
244 der::Input issuer_value;
245 std::string normalized_issuer;
246 if (!GetSequenceValue(der::Input(&raw_issuer), &issuer_value) ||
247 !NormalizeName(issuer_value, &normalized_issuer)) {
248 continue;
249 }
250 normalized_issuers.push_back(std::move(normalized_issuer));
251 }
252
253 std::string normalized_cert_issuer;
254 if (!GetNormalizedCertIssuer(cert_handle_, &normalized_cert_issuer))
255 return false;
256 if (std::find(normalized_issuers.begin(), normalized_issuers.end(),
257 normalized_cert_issuer) != normalized_issuers.end())
258 return true;
259
260 for (CRYPTO_BUFFER* intermediate : intermediate_ca_certs_) {
261 if (!GetNormalizedCertIssuer(intermediate, &normalized_cert_issuer))
262 return false;
263 if (std::find(normalized_issuers.begin(), normalized_issuers.end(),
264 normalized_cert_issuer) != normalized_issuers.end())
265 return true;
266 }
267 return false;
268 }
269
270 // static
271 bool X509Certificate::GetDEREncoded(X509Certificate::OSCertHandle cert_handle,
272 std::string* encoded) {
273 if (!cert_handle)
274 return false;
275 encoded->assign(
276 reinterpret_cast<const char*>(CRYPTO_BUFFER_data(cert_handle)),
277 CRYPTO_BUFFER_len(cert_handle));
278 return true;
279 }
280
281 // static
282 void X509Certificate::GetPublicKeyInfo(OSCertHandle cert_handle,
283 size_t* size_bits,
284 PublicKeyType* type) {
285 *type = kPublicKeyTypeUnknown;
286 *size_bits = 0;
287
288 base::StringPiece spki;
289 if (!asn1::ExtractSPKIFromDERCert(
290 base::StringPiece(
291 reinterpret_cast<const char*>(CRYPTO_BUFFER_data(cert_handle)),
292 CRYPTO_BUFFER_len(cert_handle)),
293 &spki)) {
294 return;
295 }
296
297 bssl::UniquePtr<EVP_PKEY> pkey;
298 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
299 CBS cbs;
300 CBS_init(&cbs, reinterpret_cast<const uint8_t*>(spki.data()), spki.size());
301 pkey.reset(EVP_parse_public_key(&cbs));
302 if (!pkey)
303 return;
304
305 switch (pkey->type) {
306 case EVP_PKEY_RSA:
307 *type = kPublicKeyTypeRSA;
308 break;
309 case EVP_PKEY_DSA:
310 *type = kPublicKeyTypeDSA;
311 break;
312 case EVP_PKEY_EC:
313 *type = kPublicKeyTypeECDSA;
314 break;
315 case EVP_PKEY_DH:
316 *type = kPublicKeyTypeDH;
317 break;
318 }
319 *size_bits = base::saturated_cast<size_t>(EVP_PKEY_bits(pkey.get()));
320 }
321
322 // static
323 bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a,
324 X509Certificate::OSCertHandle b) {
325 DCHECK(a && b);
326 if (a == b)
327 return true;
328 return CRYPTO_BUFFER_len(a) == CRYPTO_BUFFER_len(b) &&
329 memcmp(CRYPTO_BUFFER_data(a), CRYPTO_BUFFER_data(b),
330 CRYPTO_BUFFER_len(a)) == 0;
331 }
332
333 // static
334 X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes(
335 const char* data,
336 size_t length) {
337 der::Input tbs_certificate_tlv;
338 der::Input signature_algorithm_tlv;
339 der::BitString signature_value;
340 // Do a bare minimum of DER parsing here to make sure the input is not
341 // completely crazy. (This is required for at least
342 // CreateCertificateListFromBytes with FORMAT_AUTO, if not more.)
343 if (!ParseCertificate(
344 der::Input(reinterpret_cast<const uint8_t*>(data), length),
345 &tbs_certificate_tlv, &signature_algorithm_tlv, &signature_value,
346 nullptr)) {
347 return nullptr;
348 }
349
350 return CRYPTO_BUFFER_new(reinterpret_cast<const uint8_t*>(data), length,
351 x509_util::GetBufferPool());
352 }
353
354 // static
355 X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes(
356 const char* data,
357 size_t length,
358 Format format) {
359 OSCertHandles results;
360
361 switch (format) {
362 case FORMAT_SINGLE_CERTIFICATE: {
363 OSCertHandle handle = CreateOSCertHandleFromBytes(data, length);
364 if (handle)
365 results.push_back(handle);
366 break;
367 }
368 case FORMAT_PKCS7: {
369 CreateOSCertHandlesFromPKCS7Bytes(data, length, &results);
370 break;
371 }
372 default: {
373 NOTREACHED() << "Certificate format " << format << " unimplemented";
374 break;
375 }
376 }
377
378 return results;
379 }
380
381 // static
382 X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle(
383 OSCertHandle cert_handle) {
384 CRYPTO_BUFFER_up_ref(cert_handle);
385 return cert_handle;
386 }
387
388 // static
389 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) {
390 CRYPTO_BUFFER_free(cert_handle);
391 }
392
393 // static
394 SHA256HashValue X509Certificate::CalculateFingerprint256(OSCertHandle cert) {
395 SHA256HashValue sha256;
396
397 SHA256(CRYPTO_BUFFER_data(cert), CRYPTO_BUFFER_len(cert), sha256.data);
398 return sha256;
399 }
400
401 // static
402 SHA256HashValue X509Certificate::CalculateCAFingerprint256(
403 const OSCertHandles& intermediates) {
404 SHA256HashValue sha256;
405 memset(sha256.data, 0, sizeof(sha256.data));
406
407 SHA256_CTX sha256_ctx;
408 SHA256_Init(&sha256_ctx);
409 for (CRYPTO_BUFFER* cert : intermediates) {
410 SHA256_Update(&sha256_ctx, CRYPTO_BUFFER_data(cert),
411 CRYPTO_BUFFER_len(cert));
412 }
413 SHA256_Final(sha256.data, &sha256_ctx);
414
415 return sha256;
416 }
417
418 // static
419 bool X509Certificate::IsSelfSigned(OSCertHandle cert_handle) {
420 der::Input tbs_certificate_tlv;
421 der::Input signature_algorithm_tlv;
422 der::BitString signature_value;
423 if (!ParseCertificate(der::Input(CRYPTO_BUFFER_data(cert_handle),
424 CRYPTO_BUFFER_len(cert_handle)),
425 &tbs_certificate_tlv, &signature_algorithm_tlv,
426 &signature_value, nullptr)) {
427 return false;
428 }
429 ParsedTbsCertificate tbs;
430 if (!ParseTbsCertificate(tbs_certificate_tlv, {}, &tbs, nullptr)) {
431 return false;
432 }
433
434 der::Input subject_value;
435 std::string normalized_subject;
436 if (!GetSequenceValue(tbs.subject_tlv, &subject_value) ||
437 !NormalizeName(subject_value, &normalized_subject)) {
438 return false;
439 }
440 der::Input issuer_value;
441 std::string normalized_issuer;
442 if (!GetSequenceValue(tbs.issuer_tlv, &issuer_value) ||
443 !NormalizeName(issuer_value, &normalized_issuer)) {
444 return false;
445 }
446
447 if (normalized_subject != normalized_issuer)
448 return false;
449
450 std::unique_ptr<SignatureAlgorithm> signature_algorithm =
451 SignatureAlgorithm::Create(signature_algorithm_tlv, nullptr /* errors */);
452 if (!signature_algorithm)
453 return false;
454
455 SimpleSignaturePolicy signature_policy(1024);
456 CertErrors unused_errors;
457 return VerifySignedData(*signature_algorithm, tbs_certificate_tlv,
458 signature_value, tbs.spki_tlv, &signature_policy,
459 &unused_errors);
460 }
461
462 // static
463 X509Certificate::OSCertHandle X509Certificate::ReadOSCertHandleFromPickle(
464 base::PickleIterator* pickle_iter) {
465 const char* data;
466 int length;
467 if (!pickle_iter->ReadData(&data, &length))
468 return NULL;
469
470 return CreateOSCertHandleFromBytes(data, length);
471 }
472
473 // static
474 bool X509Certificate::WriteOSCertHandleToPickle(OSCertHandle cert_handle,
475 base::Pickle* pickle) {
476 return pickle->WriteData(
477 reinterpret_cast<const char*>(CRYPTO_BUFFER_data(cert_handle)),
478 CRYPTO_BUFFER_len(cert_handle));
479 }
480
481 } // namespace net
OLDNEW
« no previous file with comments | « net/cert/x509_certificate.cc ('k') | net/cert/x509_certificate_mac.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698