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_private_key.h"
9 #include "crypto/ec_signature_creator.h"
10 #include "net/cert/asn1_util.h"
11 #include "net/spdy/spdy_test_util_spdy3.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"
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_FailsWithDSACert DISABLED_FailsWithDSACert
117 #define MAYBE_FailsWithDSACert FailsWithDSACert
120 TEST_F(SpdyCredentialBuilderTest
, MAYBE_FailsWithDSACert
) {
121 EXPECT_EQ(ERR_BAD_SSL_CLIENT_AUTH_CERT
,
122 BuildWithType(CLIENT_CERT_DSS_SIGN
));
125 #if defined(USE_OPENSSL)
126 #define MAYBE_SetsSlotCorrectly DISABLED_SetsSlotCorrectly
128 #define MAYBE_SetsSlotCorrectly SetsSlotCorrectly
131 TEST_F(SpdyCredentialBuilderTest
, MAYBE_SetsSlotCorrectly
) {
132 ASSERT_EQ(OK
, Build());
133 EXPECT_EQ(kSlot
, credential_
.slot
);
136 #if defined(USE_OPENSSL)
137 #define MAYBE_SetsCertCorrectly DISABLED_SetsCertCorrectly
139 #define MAYBE_SetsCertCorrectly SetsCertCorrectly
142 TEST_F(SpdyCredentialBuilderTest
, MAYBE_SetsCertCorrectly
) {
143 ASSERT_EQ(OK
, Build());
144 base::StringPiece spki
;
145 ASSERT_TRUE(asn1::ExtractSPKIFromDERCert(cert_
, &spki
));
146 base::StringPiece spk
;
147 ASSERT_TRUE(asn1::ExtractSubjectPublicKeyFromSPKI(spki
, &spk
));
148 EXPECT_EQ(1u, credential_
.certs
.size());
149 EXPECT_EQ(0, (int)spk
[0]);
150 EXPECT_EQ(4, (int)spk
[1]);
151 EXPECT_EQ(spk
.substr(2, spk
.length()).as_string(), credential_
.certs
[0]);
154 #if defined(USE_OPENSSL)
155 #define MAYBE_SetsProofCorrectly DISABLED_SetsProofCorrectly
157 #define MAYBE_SetsProofCorrectly SetsProofCorrectly
160 TEST_F(SpdyCredentialBuilderTest
, MAYBE_SetsProofCorrectly
) {
161 ASSERT_EQ(OK
, Build());
162 base::StringPiece spki
;
163 ASSERT_TRUE(asn1::ExtractSPKIFromDERCert(cert_
, &spki
));
164 std::vector
<uint8
> spki_data(spki
.data(),
165 spki
.data() + spki
.size());
166 std::vector
<uint8
> key_data(key_
.data(),
167 key_
.data() + key_
.length());
168 std::vector
<uint8
> proof_data
;
169 scoped_ptr
<crypto::ECPrivateKey
> private_key(
170 crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
171 ServerBoundCertService::kEPKIPassword
, key_data
, spki_data
));
172 scoped_ptr
<crypto::ECSignatureCreator
> creator(
173 crypto::ECSignatureCreator::Create(private_key
.get()));
174 std::string secret
= GetCredentialSecret();
175 creator
->Sign(reinterpret_cast<const unsigned char *>(secret
.data()),
176 secret
.length(), &proof_data
);
178 std::string
proof(proof_data
.begin(), proof_data
.end());
179 EXPECT_EQ(proof
, credential_
.proof
);