crypto_test_utils_nss.cc revision 7d4cd473f85ac64c3747c96c277f9e506a0d2246
1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// found in the LICENSE file. 4868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "net/quic/test_tools/crypto_test_utils.h" 6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 77d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include <keyhi.h> 87d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include <pk11pub.h> 97d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include <sechash.h> 107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/stl_util.h" 127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string_util.h" 137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "crypto/ec_private_key.h" 14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "net/quic/crypto/channel_id.h" 15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)using base::StringPiece; 17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)using std::string; 18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace net { 20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace test { 22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// TODO(rtenneti): Implement NSS support ChannelIDSigner. Convert Sign() to be 24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// asynchronous using completion callback. After porting TestChannelIDSigner, 25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// implement real ChannelIDSigner. 26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class TestChannelIDSigner : public ChannelIDSigner { 27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public: 287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) virtual ~TestChannelIDSigner() { 297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) STLDeleteValues(&hostname_to_key_); 307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // ChannelIDSigner implementation. 33868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 34868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) virtual bool Sign(const string& hostname, 35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) StringPiece signed_data, 36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) string* out_key, 37868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) string* out_signature) OVERRIDE { 387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) crypto::ECPrivateKey* ecdsa_keypair = HostnameToKey(hostname); 397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!ecdsa_keypair) { 407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return false; 417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) *out_key = SerializeKey(ecdsa_keypair->public_key()); 44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (out_key->empty()) { 45868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return false; 46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) unsigned char hash_buf[SHA256_LENGTH]; 497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) SECItem hash_item = { siBuffer, hash_buf, sizeof(hash_buf) }; 50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) HASHContext* sha256 = HASH_Create(HASH_AlgSHA256); 527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!sha256) { 537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return false; 547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) HASH_Begin(sha256); 567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) HASH_Update(sha256, 577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) reinterpret_cast<const unsigned char*>( 587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ChannelIDVerifier::kContextStr), 597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) strlen(ChannelIDVerifier::kContextStr) + 1); 607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) HASH_Update(sha256, 617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) reinterpret_cast<const unsigned char*>( 627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ChannelIDVerifier::kClientToServerStr), 637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) strlen(ChannelIDVerifier::kClientToServerStr) + 1); 647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) HASH_Update(sha256, 657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) reinterpret_cast<const unsigned char*>(signed_data.data()), 667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) signed_data.size()); 677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) HASH_End(sha256, hash_buf, &hash_item.len, sizeof(hash_buf)); 687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) HASH_Destroy(sha256); 697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // The signature consists of a pair of 32-byte numbers. 717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) static const unsigned int kSignatureLength = 32 * 2; 727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) string signature; 737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) SECItem sig_item = { 747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) siBuffer, 757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) reinterpret_cast<unsigned char*>( 767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) WriteInto(&signature, kSignatureLength + 1)), 777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) kSignatureLength 787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) }; 797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (PK11_Sign(ecdsa_keypair->key(), &sig_item, &hash_item) != SECSuccess) { 817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return false; 827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) *out_signature = signature; 84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return true; 85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) virtual string GetKeyForHostname(const string& hostname) OVERRIDE { 887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) crypto::ECPrivateKey* ecdsa_keypair = HostnameToKey(hostname); 897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!ecdsa_keypair) { 907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return ""; 917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return SerializeKey(ecdsa_keypair->public_key()); 93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private: 967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) typedef std::map<string, crypto::ECPrivateKey*> HostnameToKeyMap; 977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) crypto::ECPrivateKey* HostnameToKey(const string& hostname) { 997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) HostnameToKeyMap::const_iterator it = hostname_to_key_.find(hostname); 1007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (it != hostname_to_key_.end()) { 1017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return it->second; 1027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 1037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 1047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) crypto::ECPrivateKey* keypair = crypto::ECPrivateKey::Create(); 1057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!keypair) { 1067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return NULL; 1077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 1087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) hostname_to_key_[hostname] = keypair; 1097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return keypair; 110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) static string SerializeKey(const SECKEYPublicKey* public_key) { 1137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // public_key->u.ec.publicValue is an ANSI X9.62 public key which, for 1147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // a P-256 key, is 0x04 (meaning uncompressed) followed by the x and y field 1157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // elements as 32-byte, big-endian numbers. 1167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) static const unsigned int kExpectedKeyLength = 65; 1177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 1187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const unsigned char* const data = public_key->u.ec.publicValue.data; 1197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const unsigned int len = public_key->u.ec.publicValue.len; 1207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (len != kExpectedKeyLength || data[0] != 0x04) { 1217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return ""; 1227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 1237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 1247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) string key(reinterpret_cast<const char*>(data + 1), kExpectedKeyLength - 1); 1257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return key; 126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 1277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 1287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) HostnameToKeyMap hostname_to_key_; 129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}; 130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// static 132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)ChannelIDSigner* CryptoTestUtils::ChannelIDSignerForTesting() { 133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return new TestChannelIDSigner(); 134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} // namespace test 137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} // namespace net 139