diff options
author | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-20 19:39:06 +0000 |
---|---|---|
committer | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-20 19:39:06 +0000 |
commit | ae780c8ff8cf7a6ee227beb8e7c6837f4933b02c (patch) | |
tree | b452938a0277732cd8b3c55a191458ce2baaf3d1 /net/socket | |
parent | fe2255a16ad2c2ffb6390c1ec9d6b6bc0ae9a708 (diff) | |
download | chromium_src-ae780c8ff8cf7a6ee227beb8e7c6837f4933b02c.zip chromium_src-ae780c8ff8cf7a6ee227beb8e7c6837f4933b02c.tar.gz chromium_src-ae780c8ff8cf7a6ee227beb8e7c6837f4933b02c.tar.bz2 |
net: support side-pinning of public keys.
Side-pinning allows a site to pin to a public key that is both offline and not
a CA public key (without owning an intermediate CA themselves).
We do this by supporting a superfluous certificate in the chain which contains
a P256 public key and ECDSA signature over the leaf SPKI.
BUG=none
TEST=net_unittests
Review URL: http://codereview.chromium.org/7951005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@101993 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/socket')
-rw-r--r-- | net/socket/ssl_client_socket_nss.cc | 57 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_nss.h | 1 |
2 files changed, 58 insertions, 0 deletions
diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc index 186cc86..879689a 100644 --- a/net/socket/ssl_client_socket_nss.cc +++ b/net/socket/ssl_client_socket_nss.cc @@ -76,12 +76,14 @@ #include "crypto/rsa_private_key.h" #include "crypto/scoped_nss_types.h" #include "net/base/address_list.h" +#include "net/base/asn1_util.h" #include "net/base/cert_status_flags.h" #include "net/base/cert_verifier.h" #include "net/base/connection_type_histograms.h" #include "net/base/dns_util.h" #include "net/base/dnsrr_resolver.h" #include "net/base/dnssec_chain_verifier.h" +#include "net/base/transport_security_state.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" #include "net/base/net_log.h" @@ -488,6 +490,11 @@ void SSLClientSocketNSS::GetSSLInfo(SSLInfo* ssl_info) { ssl_info->cert = server_cert_; ssl_info->connection_status = ssl_connection_status_; ssl_info->public_key_hashes = server_cert_verify_result_->public_key_hashes; + for (std::vector<SHA1Fingerprint>::const_iterator + i = side_pinned_public_keys_.begin(); + i != side_pinned_public_keys_.end(); i++) { + ssl_info->public_key_hashes.push_back(*i); + } ssl_info->is_issued_by_known_root = server_cert_verify_result_->is_issued_by_known_root; @@ -1713,6 +1720,56 @@ int SSLClientSocketNSS::DoVerifyCertComplete(int result) { UMA_HISTOGRAM_TIMES("Net.SSLCertVerificationTimeError", verify_time); } + PeerCertificateChain chain(nss_fd_); + for (unsigned i = 1; i < chain.size(); i++) { + if (strcmp(chain[i]->subjectName, "CN=meta") != 0) + continue; + + base::StringPiece leaf_der( + reinterpret_cast<char*>(server_cert_nss_->derCert.data), + server_cert_nss_->derCert.len); + base::StringPiece leaf_spki; + if (!asn1::ExtractSPKIFromDERCert(leaf_der, &leaf_spki)) + break; + + static SECOidTag side_data_tag; + static bool side_data_tag_valid; + if (!side_data_tag_valid) { + // It's harmless if multiple threads enter this block concurrently. + static const uint8 kSideDataOID[] = + // 1.3.6.1.4.1.11129.2.1.4 + // (iso.org.dod.internet.private.enterprises.google.googleSecurity. + // certificateExtensions.sideData) + {0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6, 0x79, 0x02, 0x01, 0x05}; + SECOidData oid_data; + memset(&oid_data, 0, sizeof(oid_data)); + oid_data.oid.data = const_cast<uint8*>(kSideDataOID); + oid_data.oid.len = sizeof(kSideDataOID); + oid_data.desc = "Certificate side data"; + oid_data.supportedExtension = SUPPORTED_CERT_EXTENSION; + side_data_tag = SECOID_AddEntry(&oid_data); + DCHECK_NE(SEC_OID_UNKNOWN, side_data_tag); + side_data_tag_valid = true; + } + + SECItem side_data_item; + SECStatus rv = CERT_FindCertExtension(chain[i], + side_data_tag, &side_data_item); + if (rv != SECSuccess) + continue; + + base::StringPiece side_data( + reinterpret_cast<char*>(side_data_item.data), + side_data_item.len); + + if (!TransportSecurityState::ParseSidePin( + leaf_spki, side_data, &side_pinned_public_keys_)) { + LOG(WARNING) << "Side pinning data failed to parse: " + << host_and_port_.host(); + } + break; + } + // We used to remember the intermediate CA certs in the NSS database // persistently. However, NSS opens a connection to the SQLite database // during NSS initialization and doesn't close the connection until NSS diff --git a/net/socket/ssl_client_socket_nss.h b/net/socket/ssl_client_socket_nss.h index 88e8fde..0d0b342 100644 --- a/net/socket/ssl_client_socket_nss.h +++ b/net/socket/ssl_client_socket_nss.h @@ -219,6 +219,7 @@ class SSLClientSocketNSS : public SSLClientSocket { // we used an SSLHostInfo's verification. const CertVerifyResult* server_cert_verify_result_; CertVerifyResult local_server_cert_verify_result_; + std::vector<SHA1Fingerprint> side_pinned_public_keys_; int ssl_connection_status_; // Stores client authentication information between ClientAuthHandler and |