Index: net/spdy/spdy_credential_builder.cc |
diff --git a/net/spdy/spdy_credential_builder.cc b/net/spdy/spdy_credential_builder.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..8ea0870bbbe5d030892ed49c7084361f7ba788cf |
--- /dev/null |
+++ b/net/spdy/spdy_credential_builder.cc |
@@ -0,0 +1,79 @@ |
+// 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 "crypto/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 { |
+ |
+// static |
+int SpdyCredentialBuilder::Build(std::string tls_unique, |
+ SSLClientCertType type, |
+ const std::string& key, |
+ const std::string& cert, |
+ size_t slot, |
+ SpdyCredential* credential) { |
+ DCHECK(type == CLIENT_CERT_ECDSA_SIGN); |
+ 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 spki; |
+ if(!asn1::ExtractSPKIFromDERCert(cert, &spki)) |
+ 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 spk; |
jar (doing other things)
2012/08/02 02:23:04
nit: abbreviations are discouraged..
WTC said tha
Ryan Hamilton
2012/08/02 15:53:49
Done
|
+ if (!asn1::ExtractSubjectPublicKeyFromSPKI(spki, &spk)) |
+ 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_EQ(0, (int)spk[0]); |
ramant (doing other things)
2012/08/02 00:03:05
overly nit: period at the end of comments (here an
Ryan Hamilton
2012/08/02 15:53:49
(weird, your comment is off by a line again. Is t
|
+ DCHECK_EQ(4, (int)spk[1]); |
jar (doing other things)
2012/08/02 02:23:04
Consider static_cast<int> rather than C style.
Ryan Hamilton
2012/08/02 15:53:49
Done.
|
+ spk = spk.substr(2, spk.length()); |
+ |
ramant (doing other things)
2012/08/02 00:03:05
nit: should we DCHECK_GE(spk.length(), 2)?
Ryan Hamilton
2012/08/02 15:53:49
Done.
|
+ // Convert the strings into a vector<unit8> |
+ std::vector<uint8> spki_data(spki.data(), |
+ spki.data() + spki.size()); |
jar (doing other things)
2012/08/02 02:23:04
nit: no need to wrap.
Ryan Hamilton
2012/08/02 15:53:49
Heh, the longer names complicated this :> I ended
|
+ std::vector<uint8> key_data(key.data(), |
+ key.data() + key.length()); |
+ std::vector<uint8> proof_data; |
+ scoped_ptr<crypto::ECPrivateKey> private_key( |
+ crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( |
+ ServerBoundCertService::kEPKIPassword, key_data, spki_data)); |
+ scoped_ptr<crypto::ECSignatureCreator> creator( |
+ crypto::ECSignatureCreator::Create(private_key.get())); |
+ creator->Sign(reinterpret_cast<const unsigned char *>(secret.data()), |
+ secret.length(), &proof_data); |
+ |
+ credential->slot = slot; |
+ credential->certs.push_back(spk.as_string()); |
+ credential->proof.assign(proof_data.begin(), proof_data.end()); |
ramant (doing other things)
2012/08/02 00:03:05
nit: it was confusing for me to store SubjectPubli
Ryan Hamilton
2012/08/02 15:53:49
I hear you. Until we change the spec, I'd prefer
|
+ return OK; |
+} |
+ |
+// static |
+std::string SpdyCredentialBuilder::GetCredentialSecret(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 |