| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |