1 // Copyright 2013 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/quic/test_tools/crypto_test_utils.h" 6 7 #include <keyhi.h> 8 #include <pk11pub.h> 9 #include <sechash.h> 10 11 #include "base/stl_util.h" 12 #include "base/strings/string_util.h" 13 #include "crypto/ec_private_key.h" 14 #include "net/quic/crypto/channel_id.h" 15 16 using base::StringPiece; 17 using std::string; 18 19 namespace net { 20 21 namespace test { 22 23 // TODO(rtenneti): Convert Sign() to be asynchronous using a completion 24 // callback. 25 class TestChannelIDKey : public ChannelIDKey { 26 public: 27 explicit TestChannelIDKey(crypto::ECPrivateKey* ecdsa_keypair) 28 : ecdsa_keypair_(ecdsa_keypair) {} 29 virtual ~TestChannelIDKey() {} 30 31 // ChannelIDKey implementation. 32 33 virtual bool Sign(StringPiece signed_data, 34 string* out_signature) const OVERRIDE { 35 unsigned char hash_buf[SHA256_LENGTH]; 36 SECItem hash_item = { siBuffer, hash_buf, sizeof(hash_buf) }; 37 38 HASHContext* sha256 = HASH_Create(HASH_AlgSHA256); 39 if (!sha256) { 40 return false; 41 } 42 HASH_Begin(sha256); 43 HASH_Update(sha256, 44 reinterpret_cast<const unsigned char*>( 45 ChannelIDVerifier::kContextStr), 46 strlen(ChannelIDVerifier::kContextStr) + 1); 47 HASH_Update(sha256, 48 reinterpret_cast<const unsigned char*>( 49 ChannelIDVerifier::kClientToServerStr), 50 strlen(ChannelIDVerifier::kClientToServerStr) + 1); 51 HASH_Update(sha256, 52 reinterpret_cast<const unsigned char*>(signed_data.data()), 53 signed_data.size()); 54 HASH_End(sha256, hash_buf, &hash_item.len, sizeof(hash_buf)); 55 HASH_Destroy(sha256); 56 57 // The signature consists of a pair of 32-byte numbers. 58 static const unsigned int kSignatureLength = 32 * 2; 59 string signature; 60 SECItem sig_item = { 61 siBuffer, 62 reinterpret_cast<unsigned char*>( 63 WriteInto(&signature, kSignatureLength + 1)), 64 kSignatureLength 65 }; 66 67 if (PK11_Sign(ecdsa_keypair_->key(), &sig_item, &hash_item) != SECSuccess) { 68 return false; 69 } 70 *out_signature = signature; 71 return true; 72 } 73 74 virtual string SerializeKey() const OVERRIDE { 75 const SECKEYPublicKey* public_key = ecdsa_keypair_->public_key(); 76 77 // public_key->u.ec.publicValue is an ANSI X9.62 public key which, for 78 // a P-256 key, is 0x04 (meaning uncompressed) followed by the x and y field 79 // elements as 32-byte, big-endian numbers. 80 static const unsigned int kExpectedKeyLength = 65; 81 82 const unsigned char* const data = public_key->u.ec.publicValue.data; 83 const unsigned int len = public_key->u.ec.publicValue.len; 84 if (len != kExpectedKeyLength || data[0] != 0x04) { 85 return ""; 86 } 87 88 string key(reinterpret_cast<const char*>(data + 1), kExpectedKeyLength - 1); 89 return key; 90 } 91 92 private: 93 crypto::ECPrivateKey* ecdsa_keypair_; 94 }; 95 96 class TestChannelIDSource : public ChannelIDSource { 97 public: 98 virtual ~TestChannelIDSource() { 99 STLDeleteValues(&hostname_to_key_); 100 } 101 102 // ChannelIDSource implementation. 103 104 virtual QuicAsyncStatus GetChannelIDKey( 105 const string& hostname, 106 scoped_ptr<ChannelIDKey>* channel_id_key, 107 ChannelIDSourceCallback* /*callback*/) OVERRIDE { 108 channel_id_key->reset(new TestChannelIDKey(HostnameToKey(hostname))); 109 return QUIC_SUCCESS; 110 } 111 112 private: 113 typedef std::map<string, crypto::ECPrivateKey*> HostnameToKeyMap; 114 115 crypto::ECPrivateKey* HostnameToKey(const string& hostname) { 116 HostnameToKeyMap::const_iterator it = hostname_to_key_.find(hostname); 117 if (it != hostname_to_key_.end()) { 118 return it->second; 119 } 120 121 crypto::ECPrivateKey* keypair = crypto::ECPrivateKey::Create(); 122 if (!keypair) { 123 return NULL; 124 } 125 hostname_to_key_[hostname] = keypair; 126 return keypair; 127 } 128 129 HostnameToKeyMap hostname_to_key_; 130 }; 131 132 // static 133 ChannelIDSource* CryptoTestUtils::ChannelIDSourceForTesting() { 134 return new TestChannelIDSource(); 135 } 136 137 } // namespace test 138 139 } // namespace net 140