- add sources.
[platform/framework/web/crosswalk.git] / src / net / quic / test_tools / crypto_test_utils_nss.cc
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): Implement NSS support ChannelIDSigner. Convert Sign() to be
24 // asynchronous using completion callback. After porting TestChannelIDSigner,
25 // implement real ChannelIDSigner.
26 class TestChannelIDSigner : public ChannelIDSigner {
27  public:
28   virtual ~TestChannelIDSigner() {
29     STLDeleteValues(&hostname_to_key_);
30   }
31
32   // ChannelIDSigner implementation.
33
34   virtual bool Sign(const string& hostname,
35                     StringPiece signed_data,
36                     string* out_key,
37                     string* out_signature) OVERRIDE {
38     crypto::ECPrivateKey* ecdsa_keypair = HostnameToKey(hostname);
39     if (!ecdsa_keypair) {
40       return false;
41     }
42
43     *out_key = SerializeKey(ecdsa_keypair->public_key());
44     if (out_key->empty()) {
45       return false;
46     }
47
48     unsigned char hash_buf[SHA256_LENGTH];
49     SECItem hash_item = { siBuffer, hash_buf, sizeof(hash_buf) };
50
51     HASHContext* sha256 = HASH_Create(HASH_AlgSHA256);
52     if (!sha256) {
53       return false;
54     }
55     HASH_Begin(sha256);
56     HASH_Update(sha256,
57                 reinterpret_cast<const unsigned char*>(
58                     ChannelIDVerifier::kContextStr),
59                 strlen(ChannelIDVerifier::kContextStr) + 1);
60     HASH_Update(sha256,
61                 reinterpret_cast<const unsigned char*>(
62                     ChannelIDVerifier::kClientToServerStr),
63                 strlen(ChannelIDVerifier::kClientToServerStr) + 1);
64     HASH_Update(sha256,
65                 reinterpret_cast<const unsigned char*>(signed_data.data()),
66                 signed_data.size());
67     HASH_End(sha256, hash_buf, &hash_item.len, sizeof(hash_buf));
68     HASH_Destroy(sha256);
69
70     // The signature consists of a pair of 32-byte numbers.
71     static const unsigned int kSignatureLength = 32 * 2;
72     string signature;
73     SECItem sig_item = {
74         siBuffer,
75         reinterpret_cast<unsigned char*>(
76             WriteInto(&signature, kSignatureLength + 1)),
77         kSignatureLength
78     };
79
80     if (PK11_Sign(ecdsa_keypair->key(), &sig_item, &hash_item) != SECSuccess) {
81       return false;
82     }
83     *out_signature = signature;
84     return true;
85   }
86
87   virtual string GetKeyForHostname(const string& hostname) OVERRIDE {
88     crypto::ECPrivateKey* ecdsa_keypair = HostnameToKey(hostname);
89     if (!ecdsa_keypair) {
90       return "";
91     }
92     return SerializeKey(ecdsa_keypair->public_key());
93   }
94
95  private:
96   typedef std::map<string, crypto::ECPrivateKey*> HostnameToKeyMap;
97
98   crypto::ECPrivateKey* HostnameToKey(const string& hostname) {
99     HostnameToKeyMap::const_iterator it = hostname_to_key_.find(hostname);
100     if (it != hostname_to_key_.end()) {
101       return it->second;
102     }
103
104     crypto::ECPrivateKey* keypair = crypto::ECPrivateKey::Create();
105     if (!keypair) {
106       return NULL;
107     }
108     hostname_to_key_[hostname] = keypair;
109     return keypair;
110   }
111
112   static string SerializeKey(const SECKEYPublicKey* public_key) {
113     // public_key->u.ec.publicValue is an ANSI X9.62 public key which, for
114     // a P-256 key, is 0x04 (meaning uncompressed) followed by the x and y field
115     // elements as 32-byte, big-endian numbers.
116     static const unsigned int kExpectedKeyLength = 65;
117
118     const unsigned char* const data = public_key->u.ec.publicValue.data;
119     const unsigned int len = public_key->u.ec.publicValue.len;
120     if (len != kExpectedKeyLength || data[0] != 0x04) {
121       return "";
122     }
123
124     string key(reinterpret_cast<const char*>(data + 1), kExpectedKeyLength - 1);
125     return key;
126   }
127
128   HostnameToKeyMap hostname_to_key_;
129 };
130
131 // static
132 ChannelIDSigner* CryptoTestUtils::ChannelIDSignerForTesting() {
133   return new TestChannelIDSigner();
134 }
135
136 }  // namespace test
137
138 }  // namespace net