Index: net/spdy/spdy_credential_builder_unittest.cc |
diff --git a/net/spdy/spdy_credential_builder_unittest.cc b/net/spdy/spdy_credential_builder_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..92ded699fdb80e51f7012086fab4b43fd4bf1ef3 |
--- /dev/null |
+++ b/net/spdy/spdy_credential_builder_unittest.cc |
@@ -0,0 +1,140 @@ |
+// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "net/spdy/spdy_credential_builder.h" |
+ |
+#include "base/threading/sequenced_worker_pool.h" |
+#include "crypto/ec_signature_creator.h" |
+#include "crypto/ec_private_key.h" |
+#include "net/base/asn1_util.h" |
+#include "net/base/default_server_bound_cert_store.h" |
+#include "net/base/server_bound_cert_service.h" |
+#include "net/spdy/spdy_test_util_spdy3.h" |
+#include "testing/platform_test.h" |
+ |
+using namespace net::test_spdy3; |
+ |
+namespace net { |
+ |
+namespace { |
+ |
+const static size_t kSlot = 2; |
+const static char kSecretPrefix[] = |
+ "SPDY CREDENTIAL ChannelID\0client -> server"; |
+ |
+class MockBuilder : public SpdyCredentialBuilder { |
ramant (doing other things)
2012/08/02 00:03:05
overly nit: do we need this class? Can we call Spd
Ryan Hamilton
2012/08/02 15:53:49
As I've moved GetCredentialSecret from protected t
|
+ public: |
+ std::string GetCredentialSecret() { |
ramant (doing other things)
2012/08/02 00:03:05
nit: why GetCredentialSecret public?
ramant (doing other things)
2012/08/02 00:54:20
Please ignore this.
|
+ return SpdyCredentialBuilder::GetCredentialSecret( |
+ MockClientSocket::kTlsUnique); |
+ } |
+}; |
+ |
+void CreateCertAndKey(std::string* cert, std::string* key) { |
+ scoped_refptr<base::SequencedWorkerPool> sequenced_worker_pool = |
+ new base::SequencedWorkerPool(1, "SpdyHttpStreamSpdy3Test"); |
ramant (doing other things)
2012/08/02 00:03:05
nit: consider using "CreateCertAndKey" or "SpdyCre
Ryan Hamilton
2012/08/02 15:53:49
I don't know what you mean? The method is already
|
+ scoped_ptr<ServerBoundCertService> server_bound_cert_service( |
ramant (doing other things)
2012/08/02 00:03:05
overly nit: It would be really awesome to share co
Ryan Hamilton
2012/08/02 15:53:49
Done.
|
+ new ServerBoundCertService(new DefaultServerBoundCertStore(NULL), |
+ sequenced_worker_pool)); |
+ |
+ TestCompletionCallback callback; |
+ std::vector<uint8> requested_cert_types; |
+ requested_cert_types.push_back(CLIENT_CERT_ECDSA_SIGN); |
+ SSLClientCertType cert_type; |
+ ServerBoundCertService::RequestHandle request_handle; |
+ int rv = server_bound_cert_service->GetDomainBoundCert( |
+ "https://www.google.com", requested_cert_types, &cert_type, key, cert, |
+ callback.callback(), &request_handle); |
+ EXPECT_EQ(ERR_IO_PENDING, rv); |
+ EXPECT_EQ(OK, callback.WaitForResult()); |
+ EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, cert_type); |
+ |
+ sequenced_worker_pool->Shutdown(); |
+} |
+ |
+} // namespace |
+ |
+class SpdyCredentialBuilderTest : public testing::Test { |
+ public: |
+ SpdyCredentialBuilderTest() { |
+ CreateCertAndKey(&cert_, &key_); |
+ } |
+ |
+ protected: |
+ int BuildWithType(SSLClientCertType type) { |
+ return builder_.Build( |
+ MockClientSocket::kTlsUnique, type, key_, cert_, kSlot, &credential_); |
+ } |
+ |
+ int Build() { |
+ return BuildWithType(CLIENT_CERT_ECDSA_SIGN); |
+ } |
+ |
+ SpdyTestStateHelper helper_; |
jar (doing other things)
2012/08/02 02:23:04
nit: all members should be private.
Ryan Hamilton
2012/08/02 15:53:49
Normally, this is true, but the style guide specif
|
+ std::string cert_; |
ramant (doing other things)
2012/08/02 00:03:05
nit: do we need helper_?
Ryan Hamilton
2012/08/02 15:53:49
(you comment seems to be one line below the line y
|
+ std::string key_; |
+ MockBuilder builder_; |
+ SpdyCredential credential_; |
+}; |
+ |
+TEST_F(SpdyCredentialBuilderTest, GetCredentialSecret) { |
+ std::string secret_str(kSecretPrefix, arraysize(kSecretPrefix)); |
+ secret_str.append(MockClientSocket::kTlsUnique); |
+ |
+ EXPECT_EQ(secret_str, builder_.GetCredentialSecret()); |
+} |
+ |
+TEST_F(SpdyCredentialBuilderTest, SucceedsWithECDSACert) { |
+ EXPECT_EQ(OK, BuildWithType(CLIENT_CERT_ECDSA_SIGN)); |
+} |
+ |
+TEST_F(SpdyCredentialBuilderTest, FailsWithRSACert) { |
+#if !defined(DCHECK_ALWAYS_ON) |
+ EXPECT_DEBUG_DEATH(BuildWithType(CLIENT_CERT_RSA_SIGN), ""); |
+#else |
+ EXPECT_EQ(ERR_BAD_SSL_CLIENT_AUTH_CERT, |
+ BuildWithType(CLIENT_CERT_RSA_SIGN)); |
+#endif |
+} |
+ |
+TEST_F(SpdyCredentialBuilderTest, SetsSlotCorrectly) { |
+ ASSERT_EQ(OK, Build()); |
+ EXPECT_EQ(kSlot, credential_.slot); |
+} |
+ |
+TEST_F(SpdyCredentialBuilderTest, SetsCertCorrectly) { |
+ ASSERT_EQ(OK, Build()); |
+ base::StringPiece spki; |
+ ASSERT_TRUE(asn1::ExtractSPKIFromDERCert(cert_, &spki)); |
+ base::StringPiece spk; |
+ ASSERT_TRUE(asn1::ExtractSubjectPublicKeyFromSPKI(spki, &spk)); |
+ EXPECT_EQ(1u, credential_.certs.size()); |
+ EXPECT_EQ(0, (int)spk[0]); |
+ EXPECT_EQ(4, (int)spk[1]); |
+ EXPECT_EQ(spk.substr(2, spk.length()).as_string(), credential_.certs[0]); |
+} |
+ |
+TEST_F(SpdyCredentialBuilderTest, SetsProofCorrectly) { |
+ ASSERT_EQ(OK, Build()); |
+ base::StringPiece spki; |
+ ASSERT_TRUE(asn1::ExtractSPKIFromDERCert(cert_, &spki)); |
+ std::vector<uint8> spki_data(spki.data(), |
+ spki.data() + spki.size()); |
+ std::vector<uint8> key_data(key_.data(), |
+ key_.data() + key_.length()); |
+ std::vector<uint8> proof_data; |
+ scoped_ptr<crypto::ECPrivateKey> private_key( |
+ crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( |
+ ServerBoundCertService::kEPKIPassword, key_data, spki_data)); |
+ scoped_ptr<crypto::ECSignatureCreator> creator( |
+ crypto::ECSignatureCreator::Create(private_key.get())); |
+ std::string secret = builder_.GetCredentialSecret(); |
+ creator->Sign(reinterpret_cast<const unsigned char *>(secret.data()), |
+ secret.length(), &proof_data); |
+ |
+ std::string proof(proof_data.begin(), proof_data.end()); |
+ EXPECT_EQ(proof, credential_.proof); |
+} |
+ |
+} // namespace net |