summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/net.gyp6
-rw-r--r--net/quic/crypto/channel_id.h4
-rw-r--r--net/quic/crypto/channel_id_openssl.cc11
-rw-r--r--net/quic/crypto/channel_id_test.cc5
-rw-r--r--net/quic/crypto/crypto_handshake.cc4
-rw-r--r--net/quic/crypto/crypto_handshake.h2
-rw-r--r--net/quic/quic_crypto_server_stream_test.cc7
-rw-r--r--net/quic/test_tools/crypto_test_utils.cc7
-rw-r--r--net/quic/test_tools/crypto_test_utils.h6
-rw-r--r--net/quic/test_tools/crypto_test_utils_nss.cc103
-rw-r--r--net/quic/test_tools/crypto_test_utils_openssl.cc7
11 files changed, 122 insertions, 40 deletions
diff --git a/net/net.gyp b/net/net.gyp
index c82af14..5a0bc49 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -2732,6 +2732,12 @@
'tools/quic/test_tools/run_all_unittests.cc',
],
'conditions': [
+ [ 'use_glib == 1', {
+ 'dependencies': [
+ '../build/linux/system.gyp:ssl',
+ ],
+ },
+ ],
[ 'use_openssl==1', {
# When building for OpenSSL, we need to exclude NSS specific tests.
'sources!': [
diff --git a/net/quic/crypto/channel_id.h b/net/quic/crypto/channel_id.h
index 6151f0f..2d0c29d 100644
--- a/net/quic/crypto/channel_id.h
+++ b/net/quic/crypto/channel_id.h
@@ -25,6 +25,10 @@ class NET_EXPORT_PRIVATE ChannelIDSigner {
base::StringPiece signed_data,
std::string* out_key,
std::string* out_signature) = 0;
+
+ // GetKeyForHostname returns the ChannelID key that |ChannelIDSigner| will use
+ // for the given hostname.
+ virtual std::string GetKeyForHostname(const std::string& hostname) = 0;
};
// ChannelIDVerifier verifies ChannelID signatures.
diff --git a/net/quic/crypto/channel_id_openssl.cc b/net/quic/crypto/channel_id_openssl.cc
index d27bbb4..241acae 100644
--- a/net/quic/crypto/channel_id_openssl.cc
+++ b/net/quic/crypto/channel_id_openssl.cc
@@ -47,12 +47,13 @@ bool ChannelIDVerifier::VerifyRaw(StringPiece key,
sig.s = s.get();
const uint8* key_bytes = reinterpret_cast<const uint8*>(key.data());
- const uint8* proof_bytes = reinterpret_cast<const uint8*>(signature.data());
+ const uint8* signature_bytes =
+ reinterpret_cast<const uint8*>(signature.data());
- if (BN_bin2bn(key_bytes + 0, 32, x.get()) == NULL ||
- BN_bin2bn(key_bytes + 32, 32, y.get()) == NULL ||
- BN_bin2bn(proof_bytes + 0, 32, sig.r) == NULL ||
- BN_bin2bn(proof_bytes + 32, 32, sig.s) == NULL) {
+ if (BN_bin2bn(key_bytes + 0, 32, x.get()) == NULL ||
+ BN_bin2bn(key_bytes + 32, 32, y.get()) == NULL ||
+ BN_bin2bn(signature_bytes + 0, 32, sig.r) == NULL ||
+ BN_bin2bn(signature_bytes + 32, 32, sig.s) == NULL) {
return false;
}
diff --git a/net/quic/crypto/channel_id_test.cc b/net/quic/crypto/channel_id_test.cc
index 41851be..d29bfce 100644
--- a/net/quic/crypto/channel_id_test.cc
+++ b/net/quic/crypto/channel_id_test.cc
@@ -267,8 +267,7 @@ TEST(ChannelIDTest, VerifyKnownAnswerTest) {
}
}
-// TODO(rtenneti): Enable testing of ChannelID.
-TEST(ChannelIDTest, DISABLED_SignAndVerify) {
+TEST(ChannelIDTest, SignAndVerify) {
scoped_ptr<ChannelIDSigner> signer(
CryptoTestUtils::ChannelIDSignerForTesting());
@@ -277,7 +276,7 @@ TEST(ChannelIDTest, DISABLED_SignAndVerify) {
string key, signature;
ASSERT_TRUE(signer->Sign(hostname, signed_data, &key, &signature));
- EXPECT_EQ(key, CryptoTestUtils::ChannelIDKeyForHostname(hostname));
+ EXPECT_EQ(key, signer->GetKeyForHostname(hostname));
EXPECT_TRUE(ChannelIDVerifier::Verify(key, signed_data, signature));
diff --git a/net/quic/crypto/crypto_handshake.cc b/net/quic/crypto/crypto_handshake.cc
index bd5a4a5..be296be 100644
--- a/net/quic/crypto/crypto_handshake.cc
+++ b/net/quic/crypto/crypto_handshake.cc
@@ -844,6 +844,10 @@ void QuicCryptoClientConfig::SetProofVerifier(ProofVerifier* verifier) {
proof_verifier_.reset(verifier);
}
+ChannelIDSigner* QuicCryptoClientConfig::channel_id_signer() const {
+ return channel_id_signer_.get();
+}
+
void QuicCryptoClientConfig::SetChannelIDSigner(ChannelIDSigner* signer) {
channel_id_signer_.reset(signer);
}
diff --git a/net/quic/crypto/crypto_handshake.h b/net/quic/crypto/crypto_handshake.h
index 1727a08..919f777 100644
--- a/net/quic/crypto/crypto_handshake.h
+++ b/net/quic/crypto/crypto_handshake.h
@@ -356,6 +356,8 @@ class NET_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
// the server.
void SetProofVerifier(ProofVerifier* verifier);
+ ChannelIDSigner* channel_id_signer() const;
+
// SetChannelIDSigner sets a ChannelIDSigner that will be called when the
// server supports channel IDs to sign a message proving possession of the
// given ChannelID. This object takes ownership of |signer|.
diff --git a/net/quic/quic_crypto_server_stream_test.cc b/net/quic/quic_crypto_server_stream_test.cc
index cb26ac95..fb829db 100644
--- a/net/quic/quic_crypto_server_stream_test.cc
+++ b/net/quic/quic_crypto_server_stream_test.cc
@@ -249,8 +249,7 @@ TEST_F(QuicCryptoServerStreamTest, WithoutCertificates) {
EXPECT_TRUE(stream_.handshake_confirmed());
}
-// TODO(rtenneti): Enable testing of ChannelID.
-TEST_F(QuicCryptoServerStreamTest, DISABLED_ChannelID) {
+TEST_F(QuicCryptoServerStreamTest, ChannelID) {
if (!Aes128Gcm12Encrypter::IsSupported()) {
LOG(INFO) << "AES GCM not supported. Test skipped.";
return;
@@ -258,11 +257,11 @@ TEST_F(QuicCryptoServerStreamTest, DISABLED_ChannelID) {
client_options_.channel_id_enabled = true;
// TODO(rtenneti): Enable testing of ProofVerifier.
+ // CompleteCryptoHandshake verifies
+ // stream_.crypto_negotiated_params().channel_id is correct.
EXPECT_EQ(2, CompleteCryptoHandshake());
EXPECT_TRUE(stream_.encryption_established());
EXPECT_TRUE(stream_.handshake_confirmed());
- EXPECT_EQ(CryptoTestUtils::ChannelIDKeyForHostname("test.example.com"),
- stream_.crypto_negotiated_params().channel_id);
}
} // namespace
diff --git a/net/quic/test_tools/crypto_test_utils.cc b/net/quic/test_tools/crypto_test_utils.cc
index d469bfa..113bdde 100644
--- a/net/quic/test_tools/crypto_test_utils.cc
+++ b/net/quic/test_tools/crypto_test_utils.cc
@@ -4,6 +4,7 @@
#include "net/quic/test_tools/crypto_test_utils.h"
+#include "net/quic/crypto/channel_id.h"
#include "net/quic/crypto/common_cert_set.h"
#include "net/quic/crypto/crypto_handshake.h"
#include "net/quic/crypto/crypto_server_config.h"
@@ -191,6 +192,12 @@ int CryptoTestUtils::HandshakeWithFakeClient(
CompareClientAndServerKeys(&client, server);
+ if (options.channel_id_enabled) {
+ EXPECT_EQ(crypto_config.channel_id_signer()->GetKeyForHostname(
+ "test.example.com"),
+ server->crypto_negotiated_params().channel_id);
+ }
+
return client.num_sent_client_hellos();
}
diff --git a/net/quic/test_tools/crypto_test_utils.h b/net/quic/test_tools/crypto_test_utils.h
index 3946c44..7b0c952 100644
--- a/net/quic/test_tools/crypto_test_utils.h
+++ b/net/quic/test_tools/crypto_test_utils.h
@@ -46,7 +46,7 @@ class CryptoTestUtils {
// If channel_id_enabled is true then the client will attempt to send a
// ChannelID. The key will be the same as is returned by
- // |ChannelIDKeyForHostname|.
+ // ChannelIDSigner's |GetKeyForHostname|.
bool channel_id_enabled;
};
@@ -120,10 +120,6 @@ class CryptoTestUtils {
// deterministically based on the hostname given in the Sign call.
static ChannelIDSigner* ChannelIDSignerForTesting();
- // ChannelIDKeyForHostname returns the ChannelID key that
- // |ChannelIDSignerForTesting| will use for the given hostname.
- static std::string ChannelIDKeyForHostname(const std::string& hostname);
-
private:
static void CompareClientAndServerKeys(QuicCryptoClientStream* client,
QuicCryptoServerStream* server);
diff --git a/net/quic/test_tools/crypto_test_utils_nss.cc b/net/quic/test_tools/crypto_test_utils_nss.cc
index d6be917..88c8767 100644
--- a/net/quic/test_tools/crypto_test_utils_nss.cc
+++ b/net/quic/test_tools/crypto_test_utils_nss.cc
@@ -4,6 +4,13 @@
#include "net/quic/test_tools/crypto_test_utils.h"
+#include <keyhi.h>
+#include <pk11pub.h>
+#include <sechash.h>
+
+#include "base/stl_util.h"
+#include "base/strings/string_util.h"
+#include "crypto/ec_private_key.h"
#include "net/quic/crypto/channel_id.h"
using base::StringPiece;
@@ -18,7 +25,9 @@ namespace test {
// implement real ChannelIDSigner.
class TestChannelIDSigner : public ChannelIDSigner {
public:
- virtual ~TestChannelIDSigner() { }
+ virtual ~TestChannelIDSigner() {
+ STLDeleteValues(&hostname_to_key_);
+ }
// ChannelIDSigner implementation.
@@ -26,32 +35,97 @@ class TestChannelIDSigner : public ChannelIDSigner {
StringPiece signed_data,
string* out_key,
string* out_signature) OVERRIDE {
- string key(HostnameToKey(hostname));
+ crypto::ECPrivateKey* ecdsa_keypair = HostnameToKey(hostname);
+ if (!ecdsa_keypair) {
+ return false;
+ }
- *out_key = SerializeKey(key);
+ *out_key = SerializeKey(ecdsa_keypair->public_key());
if (out_key->empty()) {
return false;
}
- *out_signature = signed_data.as_string();
+ unsigned char hash_buf[SHA256_LENGTH];
+ SECItem hash_item = { siBuffer, hash_buf, sizeof(hash_buf) };
+ HASHContext* sha256 = HASH_Create(HASH_AlgSHA256);
+ if (!sha256) {
+ return false;
+ }
+ HASH_Begin(sha256);
+ HASH_Update(sha256,
+ reinterpret_cast<const unsigned char*>(
+ ChannelIDVerifier::kContextStr),
+ strlen(ChannelIDVerifier::kContextStr) + 1);
+ HASH_Update(sha256,
+ reinterpret_cast<const unsigned char*>(
+ ChannelIDVerifier::kClientToServerStr),
+ strlen(ChannelIDVerifier::kClientToServerStr) + 1);
+ HASH_Update(sha256,
+ reinterpret_cast<const unsigned char*>(signed_data.data()),
+ signed_data.size());
+ HASH_End(sha256, hash_buf, &hash_item.len, sizeof(hash_buf));
+ HASH_Destroy(sha256);
+
+ // The signature consists of a pair of 32-byte numbers.
+ static const unsigned int kSignatureLength = 32 * 2;
+ string signature;
+ SECItem sig_item = {
+ siBuffer,
+ reinterpret_cast<unsigned char*>(
+ WriteInto(&signature, kSignatureLength + 1)),
+ kSignatureLength
+ };
+
+ if (PK11_Sign(ecdsa_keypair->key(), &sig_item, &hash_item) != SECSuccess) {
+ return false;
+ }
+ *out_signature = signature;
return true;
}
- static string KeyForHostname(const string& hostname) {
- string key(HostnameToKey(hostname));
- return SerializeKey(key);
+ virtual string GetKeyForHostname(const string& hostname) OVERRIDE {
+ crypto::ECPrivateKey* ecdsa_keypair = HostnameToKey(hostname);
+ if (!ecdsa_keypair) {
+ return "";
+ }
+ return SerializeKey(ecdsa_keypair->public_key());
}
private:
- static string HostnameToKey(const string& hostname) {
- string ret = hostname;
- return ret;
+ typedef std::map<string, crypto::ECPrivateKey*> HostnameToKeyMap;
+
+ crypto::ECPrivateKey* HostnameToKey(const string& hostname) {
+ HostnameToKeyMap::const_iterator it = hostname_to_key_.find(hostname);
+ if (it != hostname_to_key_.end()) {
+ return it->second;
+ }
+
+ crypto::ECPrivateKey* keypair = crypto::ECPrivateKey::Create();
+ if (!keypair) {
+ return NULL;
+ }
+ hostname_to_key_[hostname] = keypair;
+ return keypair;
}
- static string SerializeKey(string& key) {
- return string(key);
+ static string SerializeKey(const SECKEYPublicKey* public_key) {
+ // public_key->u.ec.publicValue is an ANSI X9.62 public key which, for
+ // a P-256 key, is 0x04 (meaning uncompressed) followed by the x and y field
+ // elements as 32-byte, big-endian numbers.
+ static const unsigned int kExpectedKeyLength = 65;
+
+ const unsigned char* const data = public_key->u.ec.publicValue.data;
+ const unsigned int len = public_key->u.ec.publicValue.len;
+ if (len != kExpectedKeyLength || data[0] != 0x04) {
+ return "";
+ }
+
+ string key(reinterpret_cast<const char*>(data + 1), kExpectedKeyLength - 1);
+ return key;
}
+
+ HostnameToKeyMap hostname_to_key_;
};
// static
@@ -59,11 +133,6 @@ ChannelIDSigner* CryptoTestUtils::ChannelIDSignerForTesting() {
return new TestChannelIDSigner();
}
-// static
-string CryptoTestUtils::ChannelIDKeyForHostname(const string& hostname) {
- return TestChannelIDSigner::KeyForHostname(hostname);
-}
-
} // namespace test
} // namespace net
diff --git a/net/quic/test_tools/crypto_test_utils_openssl.cc b/net/quic/test_tools/crypto_test_utils_openssl.cc
index 24d0bc7..842118d 100644
--- a/net/quic/test_tools/crypto_test_utils_openssl.cc
+++ b/net/quic/test_tools/crypto_test_utils_openssl.cc
@@ -94,7 +94,7 @@ class TestChannelIDSigner : public ChannelIDSigner {
return true;
}
- static string KeyForHostname(const string& hostname) {
+ virtual string GetKeyForHostname(const string& hostname) OVERRIDE {
crypto::ScopedOpenSSL<EVP_PKEY, EVP_PKEY_free> ecdsa_key(
HostnameToKey(hostname));
return SerializeKey(ecdsa_key.get());
@@ -168,11 +168,6 @@ ChannelIDSigner* CryptoTestUtils::ChannelIDSignerForTesting() {
return new TestChannelIDSigner();
}
-// static
-string CryptoTestUtils::ChannelIDKeyForHostname(const string& hostname) {
- return TestChannelIDSigner::KeyForHostname(hostname);
-}
-
} // namespace test
} // namespace net