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/logging.h"
8 #include "base/string_piece.h"
9 #include "crypto/ec_private_key.h"
10 #include "crypto/ec_signature_creator.h"
11 #include "net/base/asn1_util.h"
12 #include "net/base/server_bound_cert_service.h"
13 #include "net/base/net_errors.h"
14 #include "net/socket/ssl_client_socket.h"
15 #include "net/spdy/spdy_framer.h"
21 std::vector
<uint8
> ToVector(base::StringPiece piece
) {
22 return std::vector
<uint8
>(piece
.data(), piece
.data() + piece
.length());
28 int SpdyCredentialBuilder::Build(const std::string
& tls_unique
,
29 SSLClientCertType type
,
30 const std::string
& key
,
31 const std::string
& cert
,
33 SpdyCredential
* credential
) {
34 if (type
!= CLIENT_CERT_ECDSA_SIGN
)
35 return ERR_BAD_SSL_CLIENT_AUTH_CERT
;
37 std::string secret
= SpdyCredentialBuilder::GetCredentialSecret(tls_unique
);
39 // Extract the SubjectPublicKeyInfo from the certificate.
40 base::StringPiece public_key_info
;
41 if(!asn1::ExtractSPKIFromDERCert(cert
, &public_key_info
))
42 return ERR_BAD_SSL_CLIENT_AUTH_CERT
;
44 // Next, extract the SubjectPublicKey data, which will actually
45 // be stored in the cert field of the credential frame.
46 base::StringPiece public_key
;
47 if (!asn1::ExtractSubjectPublicKeyFromSPKI(public_key_info
, &public_key
))
48 return ERR_BAD_SSL_CLIENT_AUTH_CERT
;
49 // Drop one byte of padding bits count from the BIT STRING
50 // (this will always be zero). Drop one byte of X9.62 format specification
51 // (this will always be 4 to indicated an uncompressed point).
52 DCHECK_GT(public_key
.length(), 2u);
53 DCHECK_EQ(0, static_cast<int>(public_key
[0]));
54 DCHECK_EQ(4, static_cast<int>(public_key
[1]));
55 public_key
= public_key
.substr(2, public_key
.length());
57 // Convert the strings into a vector<unit8>
58 std::vector
<uint8
> der_signature
;
59 scoped_ptr
<crypto::ECPrivateKey
> private_key(
60 crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
61 ServerBoundCertService::kEPKIPassword
,
62 ToVector(key
), ToVector(public_key_info
)));
63 scoped_ptr
<crypto::ECSignatureCreator
> creator(
64 crypto::ECSignatureCreator::Create(private_key
.get()));
65 creator
->Sign(reinterpret_cast<const unsigned char *>(secret
.data()),
66 secret
.length(), &der_signature
);
68 std::vector
<uint8
> proof_vector
;
69 if (!creator
->DecodeSignature(der_signature
, &proof_vector
)) {
71 return ERR_UNEXPECTED
;
74 credential
->slot
= slot
;
75 credential
->certs
.push_back(public_key
.as_string());
76 credential
->proof
.assign(proof_vector
.begin(), proof_vector
.end());
81 std::string
SpdyCredentialBuilder::GetCredentialSecret(
82 const std::string
& tls_unique
) {
83 const char prefix
[] = "SPDY CREDENTIAL ChannelID\0client -> server";
84 std::string
secret(prefix
, arraysize(prefix
));
85 secret
.append(tls_unique
);