| // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include "net/spdy/spdy_credential_builder.h" | 
 |  | 
 | #include "base/logging.h" | 
 | #include "base/string_piece.h" | 
 | #include "crypto/ec_private_key.h" | 
 | #include "crypto/ec_signature_creator.h" | 
 | #include "net/base/asn1_util.h" | 
 | #include "net/base/server_bound_cert_service.h" | 
 | #include "net/base/net_errors.h" | 
 | #include "net/socket/ssl_client_socket.h" | 
 | #include "net/spdy/spdy_framer.h" | 
 |  | 
 | namespace net { | 
 |  | 
 | namespace { | 
 |  | 
 | std::vector<uint8> ToVector(base::StringPiece piece) { | 
 |   return std::vector<uint8>(piece.data(), piece.data() + piece.length()); | 
 | } | 
 |  | 
 | }  // namespace | 
 |  | 
 | // static | 
 | int SpdyCredentialBuilder::Build(const std::string& tls_unique, | 
 |                                  SSLClientCertType type, | 
 |                                  const std::string& key, | 
 |                                  const std::string& cert, | 
 |                                  size_t slot, | 
 |                                  SpdyCredential* credential) { | 
 |   if (type != CLIENT_CERT_ECDSA_SIGN) | 
 |     return ERR_BAD_SSL_CLIENT_AUTH_CERT; | 
 |  | 
 |   std::string secret = SpdyCredentialBuilder::GetCredentialSecret(tls_unique); | 
 |  | 
 |   // Extract the SubjectPublicKeyInfo from the certificate. | 
 |   base::StringPiece public_key_info; | 
 |   if(!asn1::ExtractSPKIFromDERCert(cert, &public_key_info)) | 
 |     return ERR_BAD_SSL_CLIENT_AUTH_CERT; | 
 |  | 
 |   // Next, extract the SubjectPublicKey data, which will actually | 
 |   // be stored in the cert field of the credential frame. | 
 |   base::StringPiece public_key; | 
 |   if (!asn1::ExtractSubjectPublicKeyFromSPKI(public_key_info, &public_key)) | 
 |     return ERR_BAD_SSL_CLIENT_AUTH_CERT; | 
 |   // Drop one byte of padding bits count from the BIT STRING | 
 |   // (this will always be zero).  Drop one byte of X9.62 format specification | 
 |   // (this will always be 4 to indicated an uncompressed point). | 
 |   DCHECK_GT(public_key.length(), 2u); | 
 |   DCHECK_EQ(0, static_cast<int>(public_key[0])); | 
 |   DCHECK_EQ(4, static_cast<int>(public_key[1])); | 
 |   public_key = public_key.substr(2, public_key.length()); | 
 |  | 
 |   // Convert the strings into a vector<unit8> | 
 |   std::vector<uint8> der_signature; | 
 |   scoped_ptr<crypto::ECPrivateKey> private_key( | 
 |       crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( | 
 |           ServerBoundCertService::kEPKIPassword, | 
 |           ToVector(key), ToVector(public_key_info))); | 
 |   scoped_ptr<crypto::ECSignatureCreator> creator( | 
 |       crypto::ECSignatureCreator::Create(private_key.get())); | 
 |   creator->Sign(reinterpret_cast<const unsigned char *>(secret.data()), | 
 |                 secret.length(), &der_signature); | 
 |  | 
 |   std::vector<uint8> proof_vector; | 
 |   if (!creator->DecodeSignature(der_signature, &proof_vector)) { | 
 |     NOTREACHED(); | 
 |     return ERR_UNEXPECTED; | 
 |   } | 
 |  | 
 |   credential->slot = slot; | 
 |   credential->certs.push_back(public_key.as_string()); | 
 |   credential->proof.assign(proof_vector.begin(), proof_vector.end()); | 
 |   return OK; | 
 | } | 
 |  | 
 | // static | 
 | std::string SpdyCredentialBuilder::GetCredentialSecret( | 
 |     const std::string& tls_unique) { | 
 |   const char prefix[] = "SPDY CREDENTIAL ChannelID\0client -> server"; | 
 |   std::string secret(prefix, arraysize(prefix)); | 
 |   secret.append(tls_unique); | 
 |  | 
 |   return secret; | 
 | } | 
 |  | 
 | }  // namespace net |