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) 7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <openssl/bn.h> 8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <openssl/ec.h> 9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <openssl/ecdsa.h> 10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <openssl/evp.h> 11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <openssl/obj_mac.h> 12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <openssl/sha.h> 13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "crypto/openssl_util.h" 15116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "crypto/scoped_openssl_types.h" 16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "crypto/secure_hash.h" 17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "net/quic/crypto/channel_id.h" 18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)using base::StringPiece; 20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)using std::string; 21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace net { 23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace test { 25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class TestChannelIDKey : public ChannelIDKey { 27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public: 28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) explicit TestChannelIDKey(EVP_PKEY* ecdsa_key) : ecdsa_key_(ecdsa_key) {} 29f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) virtual ~TestChannelIDKey() OVERRIDE {} 30868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // ChannelIDKey implementation. 32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual bool Sign(StringPiece signed_data, 34f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) string* out_signature) const OVERRIDE { 35116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch crypto::ScopedEVP_MD_CTX md_ctx(EVP_MD_CTX_create()); 36116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!md_ctx || 37116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EVP_DigestSignInit(md_ctx.get(), NULL, EVP_sha256(), NULL, 38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ecdsa_key_.get()) != 1) { 39868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return false; 40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 42116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EVP_DigestUpdate(md_ctx.get(), ChannelIDVerifier::kContextStr, 43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) strlen(ChannelIDVerifier::kContextStr) + 1); 44116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EVP_DigestUpdate(md_ctx.get(), ChannelIDVerifier::kClientToServerStr, 45868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) strlen(ChannelIDVerifier::kClientToServerStr) + 1); 46116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EVP_DigestUpdate(md_ctx.get(), signed_data.data(), signed_data.size()); 47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) size_t sig_len; 49116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!EVP_DigestSignFinal(md_ctx.get(), NULL, &sig_len)) { 50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return false; 51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) scoped_ptr<uint8[]> der_sig(new uint8[sig_len]); 54116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!EVP_DigestSignFinal(md_ctx.get(), der_sig.get(), &sig_len)) { 55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return false; 56868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) uint8* derp = der_sig.get(); 59116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch crypto::ScopedECDSA_SIG sig( 60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) d2i_ECDSA_SIG(NULL, const_cast<const uint8**>(&derp), sig_len)); 61868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (sig.get() == NULL) { 62868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return false; 63868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 64868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 65868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // The signature consists of a pair of 32-byte numbers. 66868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) static const size_t kSignatureLength = 32 * 2; 67868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) scoped_ptr<uint8[]> signature(new uint8[kSignatureLength]); 68868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) memset(signature.get(), 0, kSignatureLength); 69868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) BN_bn2bin(sig.get()->r, signature.get() + 32 - BN_num_bytes(sig.get()->r)); 70868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) BN_bn2bin(sig.get()->s, signature.get() + 64 - BN_num_bytes(sig.get()->s)); 71868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 72868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *out_signature = string(reinterpret_cast<char*>(signature.get()), 73868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kSignatureLength); 74868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 75868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return true; 76868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) virtual string SerializeKey() const OVERRIDE { 79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // i2d_PublicKey will produce an ANSI X9.62 public key which, for a P-256 80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // key, is 0x04 (meaning uncompressed) followed by the x and y field 81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // elements as 32-byte, big-endian numbers. 82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) static const int kExpectedKeyLength = 65; 83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int len = i2d_PublicKey(ecdsa_key_.get(), NULL); 85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (len != kExpectedKeyLength) { 86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return ""; 87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint8 buf[kExpectedKeyLength]; 90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint8* derp = buf; 91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) i2d_PublicKey(ecdsa_key_.get(), &derp); 92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return string(reinterpret_cast<char*>(buf + 1), kExpectedKeyLength - 1); 94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) private: 97116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch crypto::ScopedEVP_PKEY ecdsa_key_; 98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}; 99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class TestChannelIDSource : public ChannelIDSource { 101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) public: 102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual ~TestChannelIDSource() {} 103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // ChannelIDSource implementation. 105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) virtual QuicAsyncStatus GetChannelIDKey( 107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const string& hostname, 108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) scoped_ptr<ChannelIDKey>* channel_id_key, 109f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ChannelIDSourceCallback* /*callback*/) OVERRIDE { 110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) channel_id_key->reset(new TestChannelIDKey(HostnameToKey(hostname))); 111f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return QUIC_SUCCESS; 112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private: 115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) static EVP_PKEY* HostnameToKey(const string& hostname) { 116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // In order to generate a deterministic key for a given hostname the 117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // hostname is hashed with SHA-256 and the resulting digest is treated as a 118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // big-endian number. The most-significant bit is cleared to ensure that 119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // the resulting value is less than the order of the group and then it's 120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // taken as a private key. Given the private key, the public key is 121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // calculated with a group multiplication. 122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SHA256_CTX sha256; 123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SHA256_Init(&sha256); 124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SHA256_Update(&sha256, hostname.data(), hostname.size()); 125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) unsigned char digest[SHA256_DIGEST_LENGTH]; 127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SHA256_Final(digest, &sha256); 128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Ensure that the digest is less than the order of the P-256 group by 130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // clearing the most-significant bit. 131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) digest[0] &= 0x7f; 132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 133116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch crypto::ScopedBIGNUM k(BN_new()); 134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) CHECK(BN_bin2bn(digest, sizeof(digest), k.get()) != NULL); 135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 136116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch crypto::ScopedOpenSSL<EC_GROUP, EC_GROUP_free>::Type p256( 137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)); 138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) CHECK(p256.get()); 139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 140116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch crypto::ScopedEC_KEY ecdsa_key(EC_KEY_new()); 141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) CHECK(ecdsa_key.get() != NULL && 142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EC_KEY_set_group(ecdsa_key.get(), p256.get())); 143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 144116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch crypto::ScopedOpenSSL<EC_POINT, EC_POINT_free>::Type point( 145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EC_POINT_new(p256.get())); 146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) CHECK(EC_POINT_mul(p256.get(), point.get(), k.get(), NULL, NULL, NULL)); 147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EC_KEY_set_private_key(ecdsa_key.get(), k.get()); 149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EC_KEY_set_public_key(ecdsa_key.get(), point.get()); 150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 151116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new()); 152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // EVP_PKEY_set1_EC_KEY takes a reference so no |release| here. 153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EVP_PKEY_set1_EC_KEY(pkey.get(), ecdsa_key.get()); 154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return pkey.release(); 156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}; 158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// static 160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ChannelIDSource* CryptoTestUtils::ChannelIDSourceForTesting() { 161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return new TestChannelIDSource(); 162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} // namespace test 165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} // namespace net 167