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

Side by Side Diff: net/cert/x509_certificate_mac.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_bytes.cc ('k') | net/cert/x509_certificate_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 <CoreServices/CoreServices.h> 8 #include <CoreServices/CoreServices.h>
9 #include <Security/Security.h> 9 #include <Security/Security.h>
10 10
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
110 OSStatus status = cached_cert.GetField(&CSSMOID_X509V1SerialNumber, 110 OSStatus status = cached_cert.GetField(&CSSMOID_X509V1SerialNumber,
111 &serial_number); 111 &serial_number);
112 if (status || !serial_number.field()) 112 if (status || !serial_number.field())
113 return std::string(); 113 return std::string();
114 114
115 return std::string( 115 return std::string(
116 reinterpret_cast<const char*>(serial_number.field()->Data), 116 reinterpret_cast<const char*>(serial_number.field()->Data),
117 serial_number.field()->Length); 117 serial_number.field()->Length);
118 } 118 }
119 119
120 // Test that a given |cert_handle| is actually a valid X.509 certificate, and
121 // return true if it is.
122 //
123 // On OS X, SecCertificateCreateFromData() does not return any errors if
124 // called with invalid data, as long as data is present. The actual decoding
125 // of the certificate does not happen until an API that requires a CSSM
126 // handle is called. While SecCertificateGetCLHandle is the most likely
127 // candidate, as it performs the parsing, it does not check whether the
128 // parsing was actually successful. Instead, SecCertificateGetSubject is
129 // used (supported since 10.3), as a means to check that the certificate
130 // parsed as a valid X.509 certificate.
131 bool IsValidOSCertHandle(SecCertificateRef cert_handle) {
132 const CSSM_X509_NAME* sanity_check = NULL;
133 OSStatus status = SecCertificateGetSubject(cert_handle, &sanity_check);
134 return status == noErr && sanity_check;
135 }
136
137 // Parses |data| of length |length|, attempting to decode it as the specified 120 // Parses |data| of length |length|, attempting to decode it as the specified
138 // |format|. If |data| is in the specified format, any certificates contained 121 // |format|. If |data| is in the specified format, any certificates contained
139 // within are stored into |output|. 122 // within are stored into |output|.
140 void AddCertificatesFromBytes(const char* data, size_t length, 123 void AddCertificatesFromBytes(const char* data, size_t length,
141 SecExternalFormat format, 124 SecExternalFormat format,
142 X509Certificate::OSCertHandles* output) { 125 X509Certificate::OSCertHandles* output) {
143 SecExternalFormat input_format = format; 126 SecExternalFormat input_format = format;
144 ScopedCFTypeRef<CFDataRef> local_data(CFDataCreateWithBytesNoCopy( 127 ScopedCFTypeRef<CFDataRef> local_data(CFDataCreateWithBytesNoCopy(
145 kCFAllocatorDefault, reinterpret_cast<const UInt8*>(data), 128 kCFAllocatorDefault, reinterpret_cast<const UInt8*>(data),
146 base::checked_cast<CFIndex>(length), kCFAllocatorNull)); 129 base::checked_cast<CFIndex>(length), kCFAllocatorNull));
(...skipping 28 matching lines...) Expand all
175 // encoded, attempting to decode data based on internal rules for PEM 158 // encoded, attempting to decode data based on internal rules for PEM
176 // block headers. If a PKCS#7 blob is encoded with a PEM block of 159 // block headers. If a PKCS#7 blob is encoded with a PEM block of
177 // CERTIFICATE, OS X 10.5 will return a single, invalid certificate 160 // CERTIFICATE, OS X 10.5 will return a single, invalid certificate
178 // based on the decoded data. If this happens, the certificate should 161 // based on the decoded data. If this happens, the certificate should
179 // not be included in |output|. Because |output| is empty, 162 // not be included in |output|. Because |output| is empty,
180 // CreateCertificateListfromBytes will use PEMTokenizer to decode the 163 // CreateCertificateListfromBytes will use PEMTokenizer to decode the
181 // data. When called again with the decoded data, OS X will honor 164 // data. When called again with the decoded data, OS X will honor
182 // |input_format|, causing decode to succeed. On OS X 10.6, the data 165 // |input_format|, causing decode to succeed. On OS X 10.6, the data
183 // is properly decoded as a PKCS#7, whether PEM or not, which avoids 166 // is properly decoded as a PKCS#7, whether PEM or not, which avoids
184 // the need to fallback to internal decoding. 167 // the need to fallback to internal decoding.
185 if (IsValidOSCertHandle(cert)) { 168 if (x509_util::IsValidSecCertificate(cert)) {
186 CFRetain(cert); 169 CFRetain(cert);
187 output->push_back(cert); 170 output->push_back(cert);
188 } 171 }
189 } 172 }
190 } 173 }
191 } 174 }
192 175
193 } // namespace 176 } // namespace
194 177
195 bool X509Certificate::Initialize() { 178 bool X509Certificate::Initialize() {
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
291 bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a, 274 bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a,
292 X509Certificate::OSCertHandle b) { 275 X509Certificate::OSCertHandle b) {
293 DCHECK(a && b); 276 DCHECK(a && b);
294 return CFEqual(a, b); 277 return CFEqual(a, b);
295 } 278 }
296 279
297 // static 280 // static
298 X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( 281 X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes(
299 const char* data, 282 const char* data,
300 size_t length) { 283 size_t length) {
301 CSSM_DATA cert_data; 284 return x509_util::CreateSecCertificateFromBytes(
302 cert_data.Data = const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(data)); 285 reinterpret_cast<const uint8_t*>(data), length)
303 cert_data.Length = length; 286 .release();
304
305 OSCertHandle cert_handle = NULL;
306 OSStatus status = SecCertificateCreateFromData(&cert_data,
307 CSSM_CERT_X_509v3,
308 CSSM_CERT_ENCODING_DER,
309 &cert_handle);
310 if (status != noErr)
311 return NULL;
312 if (!IsValidOSCertHandle(cert_handle)) {
313 CFRelease(cert_handle);
314 return NULL;
315 }
316 return cert_handle;
317 } 287 }
318 288
319 // static 289 // static
320 X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes( 290 X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes(
321 const char* data, 291 const char* data,
322 size_t length, 292 size_t length,
323 Format format) { 293 Format format) {
324 OSCertHandles results; 294 OSCertHandles results;
325 295
326 switch (format) { 296 switch (format) {
(...skipping 23 matching lines...) Expand all
350 } 320 }
351 321
352 // static 322 // static
353 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { 323 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) {
354 if (cert_handle) 324 if (cert_handle)
355 CFRelease(cert_handle); 325 CFRelease(cert_handle);
356 } 326 }
357 327
358 // static 328 // static
359 SHA256HashValue X509Certificate::CalculateFingerprint256(OSCertHandle cert) { 329 SHA256HashValue X509Certificate::CalculateFingerprint256(OSCertHandle cert) {
360 SHA256HashValue sha256; 330 return x509_util::CalculateFingerprint256(cert);
361 memset(sha256.data, 0, sizeof(sha256.data));
362
363 CSSM_DATA cert_data;
364 OSStatus status = SecCertificateGetData(cert, &cert_data);
365 if (status)
366 return sha256;
367
368 DCHECK(cert_data.Data);
369 DCHECK_NE(cert_data.Length, 0U);
370
371 CC_SHA256(cert_data.Data, cert_data.Length, sha256.data);
372
373 return sha256;
374 } 331 }
375 332
376 // static 333 // static
377 SHA256HashValue X509Certificate::CalculateCAFingerprint256( 334 SHA256HashValue X509Certificate::CalculateCAFingerprint256(
378 const OSCertHandles& intermediates) { 335 const OSCertHandles& intermediates) {
379 SHA256HashValue sha256; 336 SHA256HashValue sha256;
380 memset(sha256.data, 0, sizeof(sha256.data)); 337 memset(sha256.data, 0, sizeof(sha256.data));
381 338
382 // The CC_SHA(3cc) man page says all CC_SHA256_xxx routines return 1, so 339 // The CC_SHA(3cc) man page says all CC_SHA256_xxx routines return 1, so
383 // we don't check their return values. 340 // we don't check their return values.
384 CC_SHA256_CTX sha256_ctx; 341 CC_SHA256_CTX sha256_ctx;
385 CC_SHA256_Init(&sha256_ctx); 342 CC_SHA256_Init(&sha256_ctx);
386 CSSM_DATA cert_data; 343 CSSM_DATA cert_data;
387 for (size_t i = 0; i < intermediates.size(); ++i) { 344 for (size_t i = 0; i < intermediates.size(); ++i) {
388 OSStatus status = SecCertificateGetData(intermediates[i], &cert_data); 345 OSStatus status = SecCertificateGetData(intermediates[i], &cert_data);
389 if (status) 346 if (status)
390 return sha256; 347 return sha256;
391 CC_SHA256_Update(&sha256_ctx, cert_data.Data, cert_data.Length); 348 CC_SHA256_Update(&sha256_ctx, cert_data.Data, cert_data.Length);
392 } 349 }
393 CC_SHA256_Final(sha256.data, &sha256_ctx); 350 CC_SHA256_Final(sha256.data, &sha256_ctx);
394 351
395 return sha256; 352 return sha256;
396 } 353 }
397 354
398 CFMutableArrayRef X509Certificate::CreateOSCertChainForCert() const {
399 CFMutableArrayRef cert_list =
400 CFArrayCreateMutable(kCFAllocatorDefault, 0,
401 &kCFTypeArrayCallBacks);
402 if (!cert_list)
403 return NULL;
404
405 CFArrayAppendValue(cert_list, os_cert_handle());
406 for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i)
407 CFArrayAppendValue(cert_list, intermediate_ca_certs_[i]);
408
409 return cert_list;
410 }
411
412 // static 355 // static
413 X509Certificate::OSCertHandle X509Certificate::ReadOSCertHandleFromPickle( 356 X509Certificate::OSCertHandle X509Certificate::ReadOSCertHandleFromPickle(
414 base::PickleIterator* pickle_iter) { 357 base::PickleIterator* pickle_iter) {
415 const char* data; 358 const char* data;
416 int length; 359 int length;
417 if (!pickle_iter->ReadData(&data, &length)) 360 if (!pickle_iter->ReadData(&data, &length))
418 return NULL; 361 return NULL;
419 362
420 return CreateOSCertHandleFromBytes(data, length); 363 return CreateOSCertHandleFromBytes(data, length);
421 } 364 }
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
474 break; 417 break;
475 default: 418 default:
476 *type = kPublicKeyTypeUnknown; 419 *type = kPublicKeyTypeUnknown;
477 *size_bits = 0; 420 *size_bits = 0;
478 break; 421 break;
479 } 422 }
480 } 423 }
481 424
482 // static 425 // static
483 bool X509Certificate::IsSelfSigned(OSCertHandle cert_handle) { 426 bool X509Certificate::IsSelfSigned(OSCertHandle cert_handle) {
484 x509_util::CSSMCachedCertificate cached_cert; 427 return x509_util::IsSelfSigned(cert_handle);
485 OSStatus status = cached_cert.Init(cert_handle);
486 if (status != noErr)
487 return false;
488
489 x509_util::CSSMFieldValue subject;
490 status = cached_cert.GetField(&CSSMOID_X509V1SubjectNameStd, &subject);
491 if (status != CSSM_OK || !subject.field())
492 return false;
493
494 x509_util::CSSMFieldValue issuer;
495 status = cached_cert.GetField(&CSSMOID_X509V1IssuerNameStd, &issuer);
496 if (status != CSSM_OK || !issuer.field())
497 return false;
498
499 if (subject.field()->Length != issuer.field()->Length ||
500 memcmp(subject.field()->Data, issuer.field()->Data,
501 issuer.field()->Length) != 0) {
502 return false;
503 }
504
505 CSSM_CL_HANDLE cl_handle = CSSM_INVALID_HANDLE;
506 status = SecCertificateGetCLHandle(cert_handle, &cl_handle);
507 if (status)
508 return false;
509 CSSM_DATA cert_data;
510 status = SecCertificateGetData(cert_handle, &cert_data);
511 if (status)
512 return false;
513
514 if (CSSM_CL_CertVerify(cl_handle, 0, &cert_data, &cert_data, NULL, 0))
515 return false;
516 return true;
517 } 428 }
518 429
519 #pragma clang diagnostic pop // "-Wdeprecated-declarations" 430 #pragma clang diagnostic pop // "-Wdeprecated-declarations"
520 431
521 } // namespace net 432 } // namespace net
OLDNEW
« no previous file with comments | « net/cert/x509_certificate_bytes.cc ('k') | net/cert/x509_certificate_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698