Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/pickle.h" | 8 #include "base/pickle.h" |
| 9 #include "base/sha1.h" | 9 #include "base/sha1.h" |
| 10 #include "base/string_tokenizer.h" | 10 #include "base/string_tokenizer.h" |
| (...skipping 612 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 623 if (alt_name->rgAltEntry[i].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME) | 623 if (alt_name->rgAltEntry[i].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME) |
| 624 dns_names->push_back( | 624 dns_names->push_back( |
| 625 WideToASCII(alt_name->rgAltEntry[i].pwszDNSName)); | 625 WideToASCII(alt_name->rgAltEntry[i].pwszDNSName)); |
| 626 } | 626 } |
| 627 } | 627 } |
| 628 } | 628 } |
| 629 if (dns_names->empty()) | 629 if (dns_names->empty()) |
| 630 dns_names->push_back(subject_.common_name); | 630 dns_names->push_back(subject_.common_name); |
| 631 } | 631 } |
| 632 | 632 |
| 633 X509Certificate::OSCertListHandle | |
| 634 X509Certificate::CreateOSCertListHandle() const { | |
| 635 // Create a temporary certificate store to hold |cert_handle_| and any | |
|
wtc
2011/10/04 00:26:34
temporary => in-memory
| |
| 636 // associated intermediates. The store will be referenced in the returned | |
|
wtc
2011/10/04 00:26:34
intermediates => intermediate certificates
| |
| 637 // OSCertListHandle, and will not be freed until the OSCertListHandle is | |
| 638 // freed. | |
| 639 OSCertListHandle cert_list = NULL; | |
| 640 DWORD flags = CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG; | |
| 641 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, | |
| 642 NULL, flags, NULL); | |
| 643 | |
| 644 if (store) { | |
| 645 // NOTE: This preserves all of the properties of |cert_handle_| except for | |
| 646 // CERT_KEY_PROV_HANDLE_PROP_ID and CERT_KEY_CONTEXT_PROP_ID - the two | |
| 647 // properties that hold access to already-opened private keys. If a handle | |
| 648 // has already been unlocked (eg: PIN prompt), then the first time that | |
| 649 // the identity is used for client auth, it may prompt the user again. | |
|
wtc
2011/10/04 00:26:34
Nit: identity => certificate handle?
Do we ever u
Ryan Sleevi
2011/10/04 03:38:07
Now that certificate prompting has been moved into
wtc
2011/10/04 18:00:51
You can keep this comment. I asked the question t
| |
| 650 BOOL ok = CertAddCertificateContextToStore(store, cert_handle_, | |
| 651 CERT_STORE_ADD_ALWAYS, | |
| 652 &cert_list); | |
| 653 if (ok && cert_list) { | |
| 654 for (size_t i = 0; ok && i < intermediate_ca_certs_.size(); ++i) { | |
| 655 ok = CertAddCertificateContextToStore(store, intermediate_ca_certs_[i], | |
| 656 CERT_STORE_ADD_ALWAYS, NULL); | |
| 657 } | |
| 658 } | |
| 659 | |
| 660 // If |cert_list| points to a valid certificate, this will not actually | |
| 661 // close and free |store| until |cert_list| is freed. | |
| 662 CertCloseStore(store, 0); | |
| 663 | |
| 664 if (!ok) { | |
| 665 FreeOSCertListHandle(cert_list); | |
| 666 return NULL; | |
| 667 } | |
| 668 } | |
| 669 | |
| 670 return cert_list; | |
| 671 } | |
| 672 | |
| 633 int X509Certificate::VerifyInternal(const std::string& hostname, | 673 int X509Certificate::VerifyInternal(const std::string& hostname, |
| 634 int flags, | 674 int flags, |
| 635 CertVerifyResult* verify_result) const { | 675 CertVerifyResult* verify_result) const { |
| 636 if (!cert_handle_) | 676 if (!cert_handle_) |
| 637 return ERR_UNEXPECTED; | 677 return ERR_UNEXPECTED; |
| 638 | 678 |
| 639 // Build and validate certificate chain. | 679 // Build and validate certificate chain. |
| 640 CERT_CHAIN_PARA chain_para; | 680 CERT_CHAIN_PARA chain_para; |
| 641 memset(&chain_para, 0, sizeof(chain_para)); | 681 memset(&chain_para, 0, sizeof(chain_para)); |
| 642 chain_para.cbSize = sizeof(chain_para); | 682 chain_para.cbSize = sizeof(chain_para); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 689 // corresponds to HCCE_CURRENT_USER and is is initialized as needed by | 729 // corresponds to HCCE_CURRENT_USER and is is initialized as needed by |
| 690 // crypt32. However, when testing, it is necessary to create a new | 730 // crypt32. However, when testing, it is necessary to create a new |
| 691 // HCERTCHAINENGINE and use that instead. This is because each | 731 // HCERTCHAINENGINE and use that instead. This is because each |
| 692 // HCERTCHAINENGINE maintains a cache of information about certificates | 732 // HCERTCHAINENGINE maintains a cache of information about certificates |
| 693 // encountered, and each test run may modify the trust status of a | 733 // encountered, and each test run may modify the trust status of a |
| 694 // certificate. | 734 // certificate. |
| 695 ScopedHCERTCHAINENGINE chain_engine(NULL); | 735 ScopedHCERTCHAINENGINE chain_engine(NULL); |
| 696 if (TestRootCerts::HasInstance()) | 736 if (TestRootCerts::HasInstance()) |
| 697 chain_engine.reset(TestRootCerts::GetInstance()->GetChainEngine()); | 737 chain_engine.reset(TestRootCerts::GetInstance()->GetChainEngine()); |
| 698 | 738 |
| 739 OSCertListHandle cert_list = CreateOSCertListHandle(); | |
| 699 PCCERT_CHAIN_CONTEXT chain_context; | 740 PCCERT_CHAIN_CONTEXT chain_context; |
| 700 // IE passes a non-NULL pTime argument that specifies the current system | 741 // IE passes a non-NULL pTime argument that specifies the current system |
| 701 // time. IE passes CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT as the | 742 // time. IE passes CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT as the |
| 702 // chain_flags argument. | 743 // chain_flags argument. |
| 703 if (!CertGetCertificateChain( | 744 if (!CertGetCertificateChain( |
| 704 chain_engine, | 745 chain_engine, |
| 705 cert_handle_, | 746 cert_list, |
| 706 NULL, // current system time | 747 NULL, // current system time |
| 707 cert_handle_->hCertStore, | 748 cert_list->hCertStore, |
| 708 &chain_para, | 749 &chain_para, |
| 709 chain_flags, | 750 chain_flags, |
| 710 NULL, // reserved | 751 NULL, // reserved |
| 711 &chain_context)) { | 752 &chain_context)) { |
| 753 FreeOSCertListHandle(cert_list); | |
|
wtc
2011/10/04 00:26:34
Do we have a scoped type for PCCERTCONTEXT? We co
| |
| 712 return MapSecurityError(GetLastError()); | 754 return MapSecurityError(GetLastError()); |
| 713 } | 755 } |
| 756 | |
| 714 if (chain_context->TrustStatus.dwErrorStatus & | 757 if (chain_context->TrustStatus.dwErrorStatus & |
| 715 CERT_TRUST_IS_NOT_VALID_FOR_USAGE) { | 758 CERT_TRUST_IS_NOT_VALID_FOR_USAGE) { |
| 716 ev_policy_oid = NULL; | 759 ev_policy_oid = NULL; |
| 717 chain_para.RequestedIssuancePolicy.Usage.cUsageIdentifier = 0; | 760 chain_para.RequestedIssuancePolicy.Usage.cUsageIdentifier = 0; |
| 718 chain_para.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier = NULL; | 761 chain_para.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier = NULL; |
| 719 CertFreeCertificateChain(chain_context); | 762 CertFreeCertificateChain(chain_context); |
| 720 if (!CertGetCertificateChain( | 763 if (!CertGetCertificateChain( |
| 721 chain_engine, | 764 chain_engine, |
| 722 cert_handle_, | 765 cert_list, |
| 723 NULL, // current system time | 766 NULL, // current system time |
| 724 cert_handle_->hCertStore, | 767 cert_list->hCertStore, |
| 725 &chain_para, | 768 &chain_para, |
| 726 chain_flags, | 769 chain_flags, |
| 727 NULL, // reserved | 770 NULL, // reserved |
| 728 &chain_context)) { | 771 &chain_context)) { |
| 772 FreeOSCertListHandle(cert_list); | |
| 729 return MapSecurityError(GetLastError()); | 773 return MapSecurityError(GetLastError()); |
| 730 } | 774 } |
| 731 } | 775 } |
| 776 FreeOSCertListHandle(cert_list); | |
| 777 | |
| 732 ScopedCertChainContext scoped_chain_context(chain_context); | 778 ScopedCertChainContext scoped_chain_context(chain_context); |
| 733 | 779 |
| 734 GetCertChainInfo(chain_context, verify_result); | 780 GetCertChainInfo(chain_context, verify_result); |
| 735 verify_result->cert_status |= MapCertChainErrorStatusToCertStatus( | 781 verify_result->cert_status |= MapCertChainErrorStatusToCertStatus( |
| 736 chain_context->TrustStatus.dwErrorStatus); | 782 chain_context->TrustStatus.dwErrorStatus); |
| 737 | 783 |
| 738 // Treat certificates signed using broken signature algorithms as invalid. | 784 // Treat certificates signed using broken signature algorithms as invalid. |
| 739 if (verify_result->has_md4) | 785 if (verify_result->has_md4) |
| 740 verify_result->cert_status |= CERT_STATUS_INVALID; | 786 verify_result->cert_status |= CERT_STATUS_INVALID; |
| 741 | 787 |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 933 OSCertHandle cert_handle) { | 979 OSCertHandle cert_handle) { |
| 934 return CertDuplicateCertificateContext(cert_handle); | 980 return CertDuplicateCertificateContext(cert_handle); |
| 935 } | 981 } |
| 936 | 982 |
| 937 // static | 983 // static |
| 938 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { | 984 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { |
| 939 CertFreeCertificateContext(cert_handle); | 985 CertFreeCertificateContext(cert_handle); |
| 940 } | 986 } |
| 941 | 987 |
| 942 // static | 988 // static |
| 989 void X509Certificate::FreeOSCertListHandle(OSCertListHandle cert_list) { | |
| 990 CertFreeCertificateContext(cert_list); | |
| 991 } | |
| 992 | |
| 993 // static | |
| 943 SHA1Fingerprint X509Certificate::CalculateFingerprint( | 994 SHA1Fingerprint X509Certificate::CalculateFingerprint( |
| 944 OSCertHandle cert) { | 995 OSCertHandle cert) { |
| 945 DCHECK(NULL != cert->pbCertEncoded); | 996 DCHECK(NULL != cert->pbCertEncoded); |
| 946 DCHECK_NE(static_cast<DWORD>(0), cert->cbCertEncoded); | 997 DCHECK_NE(static_cast<DWORD>(0), cert->cbCertEncoded); |
| 947 | 998 |
| 948 BOOL rv; | 999 BOOL rv; |
| 949 SHA1Fingerprint sha1; | 1000 SHA1Fingerprint sha1; |
| 950 DWORD sha1_size = sizeof(sha1.data); | 1001 DWORD sha1_size = sizeof(sha1.data); |
| 951 rv = CryptHashCertificate(NULL, CALG_SHA1, 0, cert->pbCertEncoded, | 1002 rv = CryptHashCertificate(NULL, CALG_SHA1, 0, cert->pbCertEncoded, |
| 952 cert->cbCertEncoded, sha1.data, &sha1_size); | 1003 cert->cbCertEncoded, sha1.data, &sha1_size); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 991 if (!CertSerializeCertificateStoreElement(cert_handle, 0, &buffer[0], | 1042 if (!CertSerializeCertificateStoreElement(cert_handle, 0, &buffer[0], |
| 992 &length)) { | 1043 &length)) { |
| 993 return false; | 1044 return false; |
| 994 } | 1045 } |
| 995 | 1046 |
| 996 return pickle->WriteData(reinterpret_cast<const char*>(&buffer[0]), | 1047 return pickle->WriteData(reinterpret_cast<const char*>(&buffer[0]), |
| 997 length); | 1048 length); |
| 998 } | 1049 } |
| 999 | 1050 |
| 1000 } // namespace net | 1051 } // namespace net |
| OLD | NEW |