Chromium Code Reviews| 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/base/x509_certificate.h" | 5 #include "net/base/x509_certificate.h" |
| 6 | 6 |
| 7 #include <openssl/asn1.h> | 7 #include <openssl/asn1.h> |
| 8 #include <openssl/crypto.h> | 8 #include <openssl/crypto.h> |
| 9 #include <openssl/obj_mac.h> | 9 #include <openssl/obj_mac.h> |
| 10 #include <openssl/pem.h> | 10 #include <openssl/pem.h> |
| (...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 358 if (!asn1::ExtractSPKIFromDERCert(der_bytes, &spki_bytes)) | 358 if (!asn1::ExtractSPKIFromDERCert(der_bytes, &spki_bytes)) |
| 359 continue; | 359 continue; |
| 360 | 360 |
| 361 SHA1Fingerprint hash; | 361 SHA1Fingerprint hash; |
| 362 base::SHA1HashBytes(reinterpret_cast<const uint8*>(spki_bytes.data()), | 362 base::SHA1HashBytes(reinterpret_cast<const uint8*>(spki_bytes.data()), |
| 363 spki_bytes.size(), hash.data); | 363 spki_bytes.size(), hash.data); |
| 364 hashes->push_back(hash); | 364 hashes->push_back(hash); |
| 365 } | 365 } |
| 366 } | 366 } |
| 367 | 367 |
| 368 #if defined(OS_ANDROID) | |
| 369 | |
| 370 // Returns true we have verification result in |verify_result| from Android | |
|
wtc
2012/02/06 20:56:30
Nit: add "if" after "Returns true".
Nit: delete t
Johnny(Jianning) Ding
2012/02/07 04:57:12
Done.
| |
| 371 // Trust Manager. Otherwise returns false. | |
| 372 bool VerifyFromAndroidTrustManager(const std::vector<std::string>& cert_bytes, | |
| 373 CertVerifyResult* verify_result) { | |
| 374 | |
| 375 // TODO(joth): Fetch the authentication type from SSL rather than hardcode. | |
| 376 // TODO(jnd): Remove unused |hostname| from net::android::VerifyX509CertChain. | |
| 377 bool verified = true; | |
| 378 #if 0 | |
| 379 android::VerifyResult result = | |
| 380 android::VerifyX509CertChain(cert_bytes, hostname, "RSA"); | |
| 381 #else | |
| 382 // TODO(jingzhao): Recover the original implementation once we support JNI. | |
| 383 android::VerifyResult result = android::VERIFY_INVOCATION_ERROR; | |
| 384 NOTIMPLEMENTED(); | |
| 385 #endif | |
| 386 switch (result) { | |
| 387 case android::VERIFY_OK: | |
| 388 break; | |
| 389 case android::VERIFY_BAD_HOSTNAME: | |
| 390 verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID; | |
| 391 break; | |
| 392 case android::VERIFY_NO_TRUSTED_ROOT: | |
| 393 verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID; | |
| 394 break; | |
| 395 case android::VERIFY_INVOCATION_ERROR: | |
| 396 verified = false; | |
| 397 break; | |
| 398 default: | |
| 399 verify_result->cert_status |= CERT_STATUS_INVALID; | |
| 400 break; | |
| 401 } | |
| 402 return verified; | |
| 403 } | |
| 404 | |
| 405 #endif | |
| 406 | |
| 368 } // namespace | 407 } // namespace |
| 369 | 408 |
| 370 // static | 409 // static |
| 371 X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle( | 410 X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle( |
| 372 OSCertHandle cert_handle) { | 411 OSCertHandle cert_handle) { |
| 373 DCHECK(cert_handle); | 412 DCHECK(cert_handle); |
| 374 // Using X509_dup causes the entire certificate to be reparsed. This | 413 // Using X509_dup causes the entire certificate to be reparsed. This |
| 375 // conversion, besides being non-trivial, drops any associated | 414 // conversion, besides being non-trivial, drops any associated |
| 376 // application-specific data set by X509_set_ex_data. Using CRYPTO_add | 415 // application-specific data set by X509_set_ex_data. Using CRYPTO_add |
| 377 // just bumps up the ref-count for the cert, without causing any allocations | 416 // just bumps up the ref-count for the cert, without causing any allocations |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 509 ip_addrs->clear(); | 548 ip_addrs->clear(); |
| 510 | 549 |
| 511 ParseSubjectAltName(cert_handle_, dns_names, ip_addrs); | 550 ParseSubjectAltName(cert_handle_, dns_names, ip_addrs); |
| 512 } | 551 } |
| 513 | 552 |
| 514 // static | 553 // static |
| 515 X509_STORE* X509Certificate::cert_store() { | 554 X509_STORE* X509Certificate::cert_store() { |
| 516 return X509InitSingleton::GetInstance()->store(); | 555 return X509InitSingleton::GetInstance()->store(); |
| 517 } | 556 } |
| 518 | 557 |
| 519 #if defined(OS_ANDROID) | |
| 520 int X509Certificate::VerifyInternal(const std::string& hostname, | 558 int X509Certificate::VerifyInternal(const std::string& hostname, |
| 521 int flags, | 559 int flags, |
| 522 CRLSet* crl_set, | 560 CRLSet* crl_set, |
| 523 CertVerifyResult* verify_result) const { | 561 CertVerifyResult* verify_result) const { |
| 524 if (!VerifyNameMatch(hostname)) | 562 if (!VerifyNameMatch(hostname)) |
| 525 verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID; | 563 verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID; |
| 526 | 564 |
| 565 bool verify_attempted = false; | |
| 566 | |
| 567 #if defined(OS_ANDROID) | |
| 527 std::vector<std::string> cert_bytes; | 568 std::vector<std::string> cert_bytes; |
| 528 GetChainDEREncodedBytes(&cert_bytes); | 569 GetChainDEREncodedBytes(&cert_bytes); |
| 529 | 570 |
| 530 // TODO(joth): Fetch the authentication type from SSL rather than hardcode. | 571 verify_attempted = VerifyFromAndroidTrustManager(cert_bytes, verify_result); |
| 531 // TODO(jingzhao): Recover the original implementation once we support JNI. | |
| 532 #if 0 | |
| 533 android::VerifyResult result = | |
| 534 android::VerifyX509CertChain(cert_bytes, hostname, "RSA"); | |
| 535 #else | |
| 536 android::VerifyResult result = android::VERIFY_INVOCATION_ERROR; | |
| 537 NOTIMPLEMENTED(); | |
| 538 #endif | 572 #endif |
| 539 switch (result) { | |
| 540 case android::VERIFY_OK: | |
| 541 break; | |
| 542 case android::VERIFY_BAD_HOSTNAME: | |
| 543 verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID; | |
| 544 break; | |
| 545 case android::VERIFY_NO_TRUSTED_ROOT: | |
| 546 verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID; | |
| 547 break; | |
| 548 case android::VERIFY_INVOCATION_ERROR: | |
| 549 default: | |
| 550 verify_result->cert_status |= CERT_STATUS_INVALID; | |
| 551 break; | |
| 552 } | |
| 553 if (IsCertStatusError(verify_result->cert_status)) | |
| 554 return MapCertStatusToNetError(verify_result->cert_status); | |
| 555 return OK; | |
| 556 } | |
| 557 | 573 |
| 558 #else | 574 if (verify_attempted) { |
| 559 int X509Certificate::VerifyInternal(const std::string& hostname, | 575 if (IsCertStatusError(verify_result->cert_status)) |
| 560 int flags, | 576 return MapCertStatusToNetError(verify_result->cert_status); |
| 561 CRLSet* crl_set, | 577 } else { |
| 562 CertVerifyResult* verify_result) const { | 578 crypto::ScopedOpenSSL<X509_STORE_CTX, X509_STORE_CTX_free> ctx( |
| 563 if (!VerifyNameMatch(hostname)) | 579 X509_STORE_CTX_new()); |
| 564 verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID; | |
| 565 | 580 |
| 566 crypto::ScopedOpenSSL<X509_STORE_CTX, X509_STORE_CTX_free> ctx( | 581 crypto::ScopedOpenSSL<STACK_OF(X509), sk_X509_free_fn> intermediates( |
| 567 X509_STORE_CTX_new()); | 582 sk_X509_new_null()); |
| 583 if (!intermediates.get()) | |
| 584 return ERR_OUT_OF_MEMORY; | |
| 568 | 585 |
| 569 crypto::ScopedOpenSSL<STACK_OF(X509), sk_X509_free_fn> intermediates( | 586 for (OSCertHandles::const_iterator it = intermediate_ca_certs_.begin(); |
| 570 sk_X509_new_null()); | 587 it != intermediate_ca_certs_.end(); ++it) { |
| 571 if (!intermediates.get()) | 588 if (!sk_X509_push(intermediates.get(), *it)) |
| 572 return ERR_OUT_OF_MEMORY; | 589 return ERR_OUT_OF_MEMORY; |
| 590 } | |
| 591 int rv = X509_STORE_CTX_init(ctx.get(), cert_store(), | |
| 592 cert_handle_, intermediates.get()); | |
| 593 CHECK_EQ(1, rv); | |
| 573 | 594 |
| 574 for (OSCertHandles::const_iterator it = intermediate_ca_certs_.begin(); | 595 if (X509_verify_cert(ctx.get()) != 1) { |
| 575 it != intermediate_ca_certs_.end(); ++it) { | 596 int x509_error = X509_STORE_CTX_get_error(ctx.get()); |
| 576 if (!sk_X509_push(intermediates.get(), *it)) | 597 CertStatus cert_status = MapCertErrorToCertStatus(x509_error); |
| 577 return ERR_OUT_OF_MEMORY; | 598 LOG(ERROR) << "X509 Verification error " |
| 578 } | 599 << X509_verify_cert_error_string(x509_error) |
| 579 int rv = X509_STORE_CTX_init(ctx.get(), cert_store(), | 600 << " : " << x509_error |
| 580 cert_handle_, intermediates.get()); | 601 << " : " << X509_STORE_CTX_get_error_depth(ctx.get()) |
| 581 CHECK_EQ(1, rv); | 602 << " : " << cert_status; |
| 603 verify_result->cert_status |= cert_status; | |
| 604 } | |
| 582 | 605 |
| 583 if (X509_verify_cert(ctx.get()) != 1) { | 606 GetCertChainInfo(ctx.get(), verify_result); |
| 584 int x509_error = X509_STORE_CTX_get_error(ctx.get()); | 607 if (IsCertStatusError(verify_result->cert_status)) |
| 585 CertStatus cert_status = MapCertErrorToCertStatus(x509_error); | 608 return MapCertStatusToNetError(verify_result->cert_status); |
| 586 LOG(ERROR) << "X509 Verification error " | 609 AppendPublicKeyHashes(ctx.get(), &verify_result->public_key_hashes); |
|
wtc
2012/02/06 20:56:30
IMPORTANT: should we move this AppendPublicKeyHash
Johnny(Jianning) Ding
2012/02/07 04:57:12
Currently the verified cert chain info doesn't ret
| |
| 587 << X509_verify_cert_error_string(x509_error) | |
| 588 << " : " << x509_error | |
| 589 << " : " << X509_STORE_CTX_get_error_depth(ctx.get()) | |
| 590 << " : " << cert_status; | |
| 591 verify_result->cert_status |= cert_status; | |
| 592 } | 610 } |
| 593 | 611 |
| 594 GetCertChainInfo(ctx.get(), verify_result); | |
| 595 | |
| 596 if (IsCertStatusError(verify_result->cert_status)) | |
| 597 return MapCertStatusToNetError(verify_result->cert_status); | |
| 598 | |
| 599 AppendPublicKeyHashes(ctx.get(), &verify_result->public_key_hashes); | |
| 600 // Currently we only ues OpenSSL's default root CA paths, so treat all | 612 // Currently we only ues OpenSSL's default root CA paths, so treat all |
| 601 // correctly verified certs as being from a known root. TODO(joth): if the | 613 // correctly verified certs as being from a known root. TODO(joth): if the |
| 602 // motivations described in http://src.chromium.org/viewvc/chrome?view=rev&rev ision=80778 | 614 // motivations described in http://src.chromium.org/viewvc/chrome?view=rev&rev ision=80778 |
| 603 // become an issue on OpenSSL builds, we will need to embed a hardcoded list | 615 // become an issue on OpenSSL builds, we will need to embed a hardcoded list |
| 604 // of well known root CAs, as per the _mac and _win versions. | 616 // of well known root CAs, as per the _mac and _win versions. |
| 605 verify_result->is_issued_by_known_root = true; | 617 verify_result->is_issued_by_known_root = true; |
| 606 | 618 |
| 607 return OK; | 619 return OK; |
| 608 } | 620 } |
| 609 | 621 |
| 610 #endif // defined(OS_ANDROID) | |
| 611 | |
| 612 // static | 622 // static |
| 613 bool X509Certificate::GetDEREncoded(X509Certificate::OSCertHandle cert_handle, | 623 bool X509Certificate::GetDEREncoded(X509Certificate::OSCertHandle cert_handle, |
| 614 std::string* encoded) { | 624 std::string* encoded) { |
| 615 DERCache der_cache; | 625 DERCache der_cache; |
| 616 if (!GetDERAndCacheIfNeeded(cert_handle, &der_cache)) | 626 if (!GetDERAndCacheIfNeeded(cert_handle, &der_cache)) |
| 617 return false; | 627 return false; |
| 618 encoded->assign(reinterpret_cast<const char*>(der_cache.data), | 628 encoded->assign(reinterpret_cast<const char*>(der_cache.data), |
| 619 der_cache.data_length); | 629 der_cache.data_length); |
| 620 return true; | 630 return true; |
| 621 } | 631 } |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 708 for (OSCertHandles::const_iterator it = cert_handles.begin(); | 718 for (OSCertHandles::const_iterator it = cert_handles.begin(); |
| 709 it != cert_handles.end(); ++it) { | 719 it != cert_handles.end(); ++it) { |
| 710 std::string cert_bytes; | 720 std::string cert_bytes; |
| 711 GetDEREncoded(*it, &cert_bytes); | 721 GetDEREncoded(*it, &cert_bytes); |
| 712 chain_bytes->push_back(cert_bytes); | 722 chain_bytes->push_back(cert_bytes); |
| 713 } | 723 } |
| 714 } | 724 } |
| 715 #endif | 725 #endif |
| 716 | 726 |
| 717 } // namespace net | 727 } // namespace net |
| OLD | NEW |