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/logging.h" 8#include "base/strings/string_piece.h" 9#include "crypto/ec_private_key.h" 10#include "crypto/ec_signature_creator.h" 11#include "net/base/net_errors.h" 12#include "net/cert/asn1_util.h" 13#include "net/socket/ssl_client_socket.h" 14#include "net/spdy/spdy_framer.h" 15#include "net/ssl/server_bound_cert_service.h" 16 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, 29 const std::string& key, 30 const std::string& cert, 31 size_t slot, 32 SpdyCredential* credential) { 33 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 87