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 |