blob: 79567b668afc7e8729225d3241e4f5f9ee55605a [file] [log] [blame]
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001// 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/logging.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01008#include "base/strings/string_piece.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009#include "crypto/ec_private_key.h"
10#include "crypto/ec_signature_creator.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000011#include "net/base/net_errors.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010012#include "net/cert/asn1_util.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000013#include "net/socket/ssl_client_socket.h"
14#include "net/spdy/spdy_framer.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000015#include "net/ssl/server_bound_cert_service.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000016
17namespace net {
18
19namespace {
20
21std::vector<uint8> ToVector(base::StringPiece piece) {
22 return std::vector<uint8>(piece.data(), piece.data() + piece.length());
23}
24
25} // namespace
26
27// static
28int SpdyCredentialBuilder::Build(const std::string& tls_unique,
Torne (Richard Coles)58218062012-11-14 11:43:16 +000029 const std::string& key,
30 const std::string& cert,
31 size_t slot,
32 SpdyCredential* credential) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +000033 std::string secret = SpdyCredentialBuilder::GetCredentialSecret(tls_unique);
34
35 // Extract the SubjectPublicKeyInfo from the certificate.
36 base::StringPiece public_key_info;
37 if(!asn1::ExtractSPKIFromDERCert(cert, &public_key_info))
38 return ERR_BAD_SSL_CLIENT_AUTH_CERT;
39
40 // Next, extract the SubjectPublicKey data, which will actually
41 // be stored in the cert field of the credential frame.
42 base::StringPiece public_key;
43 if (!asn1::ExtractSubjectPublicKeyFromSPKI(public_key_info, &public_key))
44 return ERR_BAD_SSL_CLIENT_AUTH_CERT;
45 // Drop one byte of padding bits count from the BIT STRING
46 // (this will always be zero). Drop one byte of X9.62 format specification
47 // (this will always be 4 to indicated an uncompressed point).
48 DCHECK_GT(public_key.length(), 2u);
49 DCHECK_EQ(0, static_cast<int>(public_key[0]));
50 DCHECK_EQ(4, static_cast<int>(public_key[1]));
51 public_key = public_key.substr(2, public_key.length());
52
53 // Convert the strings into a vector<unit8>
54 std::vector<uint8> der_signature;
55 scoped_ptr<crypto::ECPrivateKey> private_key(
56 crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
57 ServerBoundCertService::kEPKIPassword,
58 ToVector(key), ToVector(public_key_info)));
59 scoped_ptr<crypto::ECSignatureCreator> creator(
60 crypto::ECSignatureCreator::Create(private_key.get()));
61 creator->Sign(reinterpret_cast<const unsigned char *>(secret.data()),
62 secret.length(), &der_signature);
63
64 std::vector<uint8> proof_vector;
65 if (!creator->DecodeSignature(der_signature, &proof_vector)) {
66 NOTREACHED();
67 return ERR_UNEXPECTED;
68 }
69
70 credential->slot = slot;
71 credential->certs.push_back(public_key.as_string());
72 credential->proof.assign(proof_vector.begin(), proof_vector.end());
73 return OK;
74}
75
76// static
77std::string SpdyCredentialBuilder::GetCredentialSecret(
78 const std::string& tls_unique) {
79 const char prefix[] = "SPDY CREDENTIAL ChannelID\0client -> server";
80 std::string secret(prefix, arraysize(prefix));
81 secret.append(tls_unique);
82
83 return secret;
84}
85
86} // namespace net