summaryrefslogtreecommitdiffstats
path: root/net/socket
diff options
context:
space:
mode:
authoragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-20 19:39:06 +0000
committeragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-20 19:39:06 +0000
commitae780c8ff8cf7a6ee227beb8e7c6837f4933b02c (patch)
treeb452938a0277732cd8b3c55a191458ce2baaf3d1 /net/socket
parentfe2255a16ad2c2ffb6390c1ec9d6b6bc0ae9a708 (diff)
downloadchromium_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.cc57
-rw-r--r--net/socket/ssl_client_socket_nss.h1
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