Home | History | Annotate | Download | only in test_tools
      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