Home | History | Annotate | Download | only in spdy
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "net/spdy/spdy_credential_builder.h"
      6 
      7 #include "base/threading/sequenced_worker_pool.h"
      8 #include "crypto/ec_private_key.h"
      9 #include "crypto/ec_signature_creator.h"
     10 #include "net/cert/asn1_util.h"
     11 #include "net/spdy/spdy_test_util_common.h"
     12 #include "net/ssl/default_server_bound_cert_store.h"
     13 #include "net/ssl/server_bound_cert_service.h"
     14 #include "testing/platform_test.h"
     15 
     16 namespace net {
     17 
     18 namespace {
     19 
     20 const static size_t kSlot = 2;
     21 const static char kSecretPrefix[] =
     22     "SPDY CREDENTIAL ChannelID\0client -> server";
     23 
     24 void CreateCertAndKey(std::string* cert, std::string* key) {
     25   // TODO(rch): Share this code with ServerBoundCertServiceTest.
     26   scoped_refptr<base::SequencedWorkerPool> sequenced_worker_pool =
     27       new base::SequencedWorkerPool(1, "CreateCertAndKey");
     28   scoped_ptr<ServerBoundCertService> server_bound_cert_service(
     29       new ServerBoundCertService(new DefaultServerBoundCertStore(NULL),
     30                                  sequenced_worker_pool));
     31 
     32   TestCompletionCallback callback;
     33   ServerBoundCertService::RequestHandle request_handle;
     34   int rv = server_bound_cert_service->GetDomainBoundCert(
     35       "www.google.com", key, cert,
     36       callback.callback(), &request_handle);
     37   EXPECT_EQ(ERR_IO_PENDING, rv);
     38   EXPECT_EQ(OK, callback.WaitForResult());
     39 
     40   sequenced_worker_pool->Shutdown();
     41 }
     42 
     43 }  // namespace
     44 
     45 class SpdyCredentialBuilderTest : public testing::Test {
     46  public:
     47   SpdyCredentialBuilderTest() {
     48     CreateCertAndKey(&cert_, &key_);
     49   }
     50 
     51  protected:
     52   int Build() {
     53     return SpdyCredentialBuilder::Build(
     54         MockClientSocket::kTlsUnique, key_, cert_, kSlot, &credential_);
     55   }
     56 
     57   std::string GetCredentialSecret() {
     58     return SpdyCredentialBuilder::GetCredentialSecret(
     59         MockClientSocket::kTlsUnique);
     60   }
     61 
     62   std::string cert_;
     63   std::string key_;
     64   SpdyCredential credential_;
     65   MockECSignatureCreatorFactory ec_signature_creator_factory_;
     66 };
     67 
     68 // http://crbug.com/142833, http://crbug.com/140991. The following tests fail
     69 // with OpenSSL due to the unimplemented ec_private_key_openssl.cc.
     70 #if defined(USE_OPENSSL)
     71 #define MAYBE_GetCredentialSecret DISABLED_GetCredentialSecret
     72 #else
     73 #define MAYBE_GetCredentialSecret GetCredentialSecret
     74 #endif
     75 
     76 TEST_F(SpdyCredentialBuilderTest, MAYBE_GetCredentialSecret) {
     77   std::string secret_str(kSecretPrefix, arraysize(kSecretPrefix));
     78   secret_str.append(MockClientSocket::kTlsUnique);
     79 
     80   EXPECT_EQ(secret_str, GetCredentialSecret());
     81 }
     82 
     83 #if defined(USE_OPENSSL)
     84 #define MAYBE_Succeeds DISABLED_Succeeds
     85 #else
     86 #define MAYBE_Succeeds Succeeds
     87 #endif
     88 
     89 TEST_F(SpdyCredentialBuilderTest, MAYBE_Succeeds) {
     90   EXPECT_EQ(OK, Build());
     91 }
     92 
     93 #if defined(USE_OPENSSL)
     94 #define MAYBE_SetsSlotCorrectly DISABLED_SetsSlotCorrectly
     95 #else
     96 #define MAYBE_SetsSlotCorrectly SetsSlotCorrectly
     97 #endif
     98 
     99 TEST_F(SpdyCredentialBuilderTest, MAYBE_SetsSlotCorrectly) {
    100   ASSERT_EQ(OK, Build());
    101   EXPECT_EQ(kSlot, credential_.slot);
    102 }
    103 
    104 #if defined(USE_OPENSSL)
    105 #define MAYBE_SetsCertCorrectly DISABLED_SetsCertCorrectly
    106 #else
    107 #define MAYBE_SetsCertCorrectly SetsCertCorrectly
    108 #endif
    109 
    110 TEST_F(SpdyCredentialBuilderTest, MAYBE_SetsCertCorrectly) {
    111   ASSERT_EQ(OK, Build());
    112   base::StringPiece spki;
    113   ASSERT_TRUE(asn1::ExtractSPKIFromDERCert(cert_, &spki));
    114   base::StringPiece spk;
    115   ASSERT_TRUE(asn1::ExtractSubjectPublicKeyFromSPKI(spki, &spk));
    116   EXPECT_EQ(1u, credential_.certs.size());
    117   EXPECT_EQ(0, (int)spk[0]);
    118   EXPECT_EQ(4, (int)spk[1]);
    119   EXPECT_EQ(spk.substr(2, spk.length()).as_string(), credential_.certs[0]);
    120 }
    121 
    122 #if defined(USE_OPENSSL)
    123 #define MAYBE_SetsProofCorrectly DISABLED_SetsProofCorrectly
    124 #else
    125 #define MAYBE_SetsProofCorrectly SetsProofCorrectly
    126 #endif
    127 
    128 TEST_F(SpdyCredentialBuilderTest, MAYBE_SetsProofCorrectly) {
    129   ASSERT_EQ(OK, Build());
    130   base::StringPiece spki;
    131   ASSERT_TRUE(asn1::ExtractSPKIFromDERCert(cert_, &spki));
    132   std::vector<uint8> spki_data(spki.data(),
    133                                spki.data() + spki.size());
    134   std::vector<uint8> key_data(key_.data(),
    135                               key_.data() + key_.length());
    136   std::vector<uint8> proof_data;
    137   scoped_ptr<crypto::ECPrivateKey> private_key(
    138       crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
    139           ServerBoundCertService::kEPKIPassword, key_data, spki_data));
    140   scoped_ptr<crypto::ECSignatureCreator> creator(
    141       crypto::ECSignatureCreator::Create(private_key.get()));
    142   std::string secret = GetCredentialSecret();
    143   creator->Sign(reinterpret_cast<const unsigned char *>(secret.data()),
    144                 secret.length(), &proof_data);
    145 
    146   std::string proof(proof_data.begin(), proof_data.end());
    147   EXPECT_EQ(proof, credential_.proof);
    148 }
    149 
    150 }  // namespace net
    151