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.
5 #include "net/spdy/spdy_credential_builder.h"
7 #include "base/threading/sequenced_worker_pool.h"
8 #include "crypto/ec_signature_creator.h"
9 #include "crypto/ec_private_key.h"
10 #include "net/base/asn1_util.h"
11 #include "net/base/default_server_bound_cert_store.h"
12 #include "net/base/server_bound_cert_service.h"
13 #include "net/spdy/spdy_test_util_spdy3.h"
14 #include "testing/platform_test.h"
16 using namespace net::test_spdy3
;
22 const static size_t kSlot
= 2;
23 const static char kSecretPrefix
[] =
24 "SPDY CREDENTIAL ChannelID\0client -> server";
26 void CreateCertAndKey(std::string
* cert
, std::string
* key
) {
27 // TODO(rch): Share this code with ServerBoundCertServiceTest.
28 scoped_refptr
<base::SequencedWorkerPool
> sequenced_worker_pool
=
29 new base::SequencedWorkerPool(1, "CreateCertAndKey");
30 scoped_ptr
<ServerBoundCertService
> server_bound_cert_service(
31 new ServerBoundCertService(new DefaultServerBoundCertStore(NULL
),
32 sequenced_worker_pool
));
34 TestCompletionCallback callback
;
35 std::vector
<uint8
> requested_cert_types
;
36 requested_cert_types
.push_back(CLIENT_CERT_ECDSA_SIGN
);
37 SSLClientCertType cert_type
;
38 ServerBoundCertService::RequestHandle request_handle
;
39 int rv
= server_bound_cert_service
->GetDomainBoundCert(
40 "https://www.google.com", requested_cert_types
, &cert_type
, key
, cert
,
41 callback
.callback(), &request_handle
);
42 EXPECT_EQ(ERR_IO_PENDING
, rv
);
43 EXPECT_EQ(OK
, callback
.WaitForResult());
44 EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN
, cert_type
);
46 sequenced_worker_pool
->Shutdown();
51 class SpdyCredentialBuilderTest
: public testing::Test
{
53 SpdyCredentialBuilderTest() {
54 CreateCertAndKey(&cert_
, &key_
);
58 int BuildWithType(SSLClientCertType type
) {
59 return SpdyCredentialBuilder::Build(
60 MockClientSocket::kTlsUnique
, type
, key_
, cert_
, kSlot
, &credential_
);
64 return BuildWithType(CLIENT_CERT_ECDSA_SIGN
);
67 std::string
GetCredentialSecret() {
68 return SpdyCredentialBuilder::GetCredentialSecret(
69 MockClientSocket::kTlsUnique
);
74 SpdyCredential credential_
;
75 MockECSignatureCreatorFactory ec_signature_creator_factory_
;
78 // http://crbug.com/142833, http://crbug.com/140991. The following tests fail
79 // with OpenSSL due to the unimplemented ec_private_key_openssl.cc.
80 #if defined(USE_OPENSSL)
81 #define MAYBE_GetCredentialSecret DISABLED_GetCredentialSecret
83 #define MAYBE_GetCredentialSecret GetCredentialSecret
86 TEST_F(SpdyCredentialBuilderTest
, MAYBE_GetCredentialSecret
) {
87 std::string
secret_str(kSecretPrefix
, arraysize(kSecretPrefix
));
88 secret_str
.append(MockClientSocket::kTlsUnique
);
90 EXPECT_EQ(secret_str
, GetCredentialSecret());
93 #if defined(USE_OPENSSL)
94 #define MAYBE_SucceedsWithECDSACert DISABLED_SucceedsWithECDSACert
96 #define MAYBE_SucceedsWithECDSACert SucceedsWithECDSACert
99 TEST_F(SpdyCredentialBuilderTest
, MAYBE_SucceedsWithECDSACert
) {
100 EXPECT_EQ(OK
, BuildWithType(CLIENT_CERT_ECDSA_SIGN
));
103 #if defined(USE_OPENSSL)
104 #define MAYBE_FailsWithRSACert DISABLED_FailsWithRSACert
106 #define MAYBE_FailsWithRSACert FailsWithRSACert
109 TEST_F(SpdyCredentialBuilderTest
, MAYBE_FailsWithRSACert
) {
110 EXPECT_EQ(ERR_BAD_SSL_CLIENT_AUTH_CERT
,
111 BuildWithType(CLIENT_CERT_RSA_SIGN
));
114 #if defined(USE_OPENSSL)
115 #define MAYBE_SetsSlotCorrectly DISABLED_SetsSlotCorrectly
117 #define MAYBE_SetsSlotCorrectly SetsSlotCorrectly
120 TEST_F(SpdyCredentialBuilderTest
, MAYBE_SetsSlotCorrectly
) {
121 ASSERT_EQ(OK
, Build());
122 EXPECT_EQ(kSlot
, credential_
.slot
);
125 #if defined(USE_OPENSSL)
126 #define MAYBE_SetsCertCorrectly DISABLED_SetsCertCorrectly
128 #define MAYBE_SetsCertCorrectly SetsCertCorrectly
131 TEST_F(SpdyCredentialBuilderTest
, MAYBE_SetsCertCorrectly
) {
132 ASSERT_EQ(OK
, Build());
133 base::StringPiece spki
;
134 ASSERT_TRUE(asn1::ExtractSPKIFromDERCert(cert_
, &spki
));
135 base::StringPiece spk
;
136 ASSERT_TRUE(asn1::ExtractSubjectPublicKeyFromSPKI(spki
, &spk
));
137 EXPECT_EQ(1u, credential_
.certs
.size());
138 EXPECT_EQ(0, (int)spk
[0]);
139 EXPECT_EQ(4, (int)spk
[1]);
140 EXPECT_EQ(spk
.substr(2, spk
.length()).as_string(), credential_
.certs
[0]);
143 #if defined(USE_OPENSSL)
144 #define MAYBE_SetsProofCorrectly DISABLED_SetsProofCorrectly
146 #define MAYBE_SetsProofCorrectly SetsProofCorrectly
149 TEST_F(SpdyCredentialBuilderTest
, MAYBE_SetsProofCorrectly
) {
150 ASSERT_EQ(OK
, Build());
151 base::StringPiece spki
;
152 ASSERT_TRUE(asn1::ExtractSPKIFromDERCert(cert_
, &spki
));
153 std::vector
<uint8
> spki_data(spki
.data(),
154 spki
.data() + spki
.size());
155 std::vector
<uint8
> key_data(key_
.data(),
156 key_
.data() + key_
.length());
157 std::vector
<uint8
> proof_data
;
158 scoped_ptr
<crypto::ECPrivateKey
> private_key(
159 crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
160 ServerBoundCertService::kEPKIPassword
, key_data
, spki_data
));
161 scoped_ptr
<crypto::ECSignatureCreator
> creator(
162 crypto::ECSignatureCreator::Create(private_key
.get()));
163 std::string secret
= GetCredentialSecret();
164 creator
->Sign(reinterpret_cast<const unsigned char *>(secret
.data()),
165 secret
.length(), &proof_data
);
167 std::string
proof(proof_data
.begin(), proof_data
.end());
168 EXPECT_EQ(proof
, credential_
.proof
);