OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/quic/crypto/p256_key_exchange.h" | 5 #include "net/quic/crypto/p256_key_exchange.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/numerics/safe_conversions.h" | 8 #include "base/numerics/safe_conversions.h" |
9 #include "base/sys_byteorder.h" | 9 #include "base/sys_byteorder.h" |
10 | 10 |
11 using base::StringPiece; | 11 using base::StringPiece; |
12 using std::string; | 12 using std::string; |
13 using std::vector; | 13 using std::vector; |
14 | 14 |
15 namespace net { | 15 namespace net { |
16 | 16 |
17 namespace { | 17 namespace { |
18 | 18 |
19 // Password used by |NewPrivateKey| to encrypt exported EC private keys. | 19 // Password used by |NewPrivateKey| to encrypt exported EC private keys. |
20 // This is not used to provide any security, but to workaround NSS being | 20 // This is not used to provide any security, but to workaround NSS being |
21 // unwilling to export unencrypted EC keys. Note that SPDY and ChannelID | 21 // unwilling to export unencrypted EC keys. Note that SPDY and ChannelID |
22 // use the same approach. | 22 // use the same approach. |
23 const char kExportPassword[] = ""; | 23 const char kExportPassword[] = ""; |
24 | 24 |
25 // Convert StringPiece to vector of uint8. | 25 // Convert StringPiece to vector of uint8_t. |
26 static vector<uint8> StringPieceToVector(StringPiece piece) { | 26 static vector<uint8_t> StringPieceToVector(StringPiece piece) { |
27 return vector<uint8>(piece.data(), piece.data() + piece.length()); | 27 return vector<uint8_t>(piece.data(), piece.data() + piece.length()); |
28 } | 28 } |
29 | 29 |
30 } // namespace | 30 } // namespace |
31 | 31 |
32 P256KeyExchange::P256KeyExchange(crypto::ECPrivateKey* key_pair, | 32 P256KeyExchange::P256KeyExchange(crypto::ECPrivateKey* key_pair, |
33 const uint8* public_key) | 33 const uint8_t* public_key) |
34 : key_pair_(key_pair) { | 34 : key_pair_(key_pair) { |
35 memcpy(public_key_, public_key, sizeof(public_key_)); | 35 memcpy(public_key_, public_key, sizeof(public_key_)); |
36 } | 36 } |
37 | 37 |
38 P256KeyExchange::~P256KeyExchange() {} | 38 P256KeyExchange::~P256KeyExchange() {} |
39 | 39 |
40 // static | 40 // static |
41 P256KeyExchange* P256KeyExchange::New(StringPiece key) { | 41 P256KeyExchange* P256KeyExchange::New(StringPiece key) { |
42 if (key.size() < 2) { | 42 if (key.size() < 2) { |
43 DVLOG(1) << "Key pair is too small."; | 43 DVLOG(1) << "Key pair is too small."; |
44 return nullptr; | 44 return nullptr; |
45 } | 45 } |
46 | 46 |
47 const uint8* data = reinterpret_cast<const uint8*>(key.data()); | 47 const uint8_t* data = reinterpret_cast<const uint8_t*>(key.data()); |
48 size_t size = | 48 size_t size = |
49 static_cast<size_t>(data[0]) | (static_cast<size_t>(data[1]) << 8); | 49 static_cast<size_t>(data[0]) | (static_cast<size_t>(data[1]) << 8); |
50 key.remove_prefix(2); | 50 key.remove_prefix(2); |
51 if (key.size() < size) { | 51 if (key.size() < size) { |
52 DVLOG(1) << "Key pair does not contain key material."; | 52 DVLOG(1) << "Key pair does not contain key material."; |
53 return nullptr; | 53 return nullptr; |
54 } | 54 } |
55 | 55 |
56 StringPiece private_piece(key.data(), size); | 56 StringPiece private_piece(key.data(), size); |
57 key.remove_prefix(size); | 57 key.remove_prefix(size); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
106 | 106 |
107 // static | 107 // static |
108 string P256KeyExchange::NewPrivateKey() { | 108 string P256KeyExchange::NewPrivateKey() { |
109 scoped_ptr<crypto::ECPrivateKey> key_pair(crypto::ECPrivateKey::Create()); | 109 scoped_ptr<crypto::ECPrivateKey> key_pair(crypto::ECPrivateKey::Create()); |
110 | 110 |
111 if (!key_pair.get()) { | 111 if (!key_pair.get()) { |
112 DVLOG(1) << "Can't generate new key pair."; | 112 DVLOG(1) << "Can't generate new key pair."; |
113 return string(); | 113 return string(); |
114 } | 114 } |
115 | 115 |
116 vector<uint8> private_key; | 116 vector<uint8_t> private_key; |
117 if (!key_pair->ExportEncryptedPrivateKey(kExportPassword, 1 /* iteration */, | 117 if (!key_pair->ExportEncryptedPrivateKey(kExportPassword, 1 /* iteration */, |
118 &private_key)) { | 118 &private_key)) { |
119 DVLOG(1) << "Can't export private key."; | 119 DVLOG(1) << "Can't export private key."; |
120 return string(); | 120 return string(); |
121 } | 121 } |
122 | 122 |
123 // NSS lacks the ability to import an ECC private key without | 123 // NSS lacks the ability to import an ECC private key without |
124 // also importing the public key, so it is necessary to also | 124 // also importing the public key, so it is necessary to also |
125 // store the public key. | 125 // store the public key. |
126 vector<uint8> public_key; | 126 vector<uint8_t> public_key; |
127 if (!key_pair->ExportPublicKey(&public_key)) { | 127 if (!key_pair->ExportPublicKey(&public_key)) { |
128 DVLOG(1) << "Can't export public key."; | 128 DVLOG(1) << "Can't export public key."; |
129 return string(); | 129 return string(); |
130 } | 130 } |
131 | 131 |
132 // TODO(thaidn): determine how large encrypted private key can be | 132 // TODO(thaidn): determine how large encrypted private key can be |
133 uint16 private_key_size = base::checked_cast<uint16>(private_key.size()); | 133 uint16_t private_key_size = base::checked_cast<uint16_t>(private_key.size()); |
134 const size_t result_size = | 134 const size_t result_size = |
135 sizeof(private_key_size) + private_key_size + public_key.size(); | 135 sizeof(private_key_size) + private_key_size + public_key.size(); |
136 vector<char> result(result_size); | 136 vector<char> result(result_size); |
137 char* resultp = &result[0]; | 137 char* resultp = &result[0]; |
138 // Export the key string. | 138 // Export the key string. |
139 // The first two bytes are the private key's size in little endian. | 139 // The first two bytes are the private key's size in little endian. |
140 private_key_size = base::ByteSwapToLE16(private_key_size); | 140 private_key_size = base::ByteSwapToLE16(private_key_size); |
141 memcpy(resultp, &private_key_size, sizeof(private_key_size)); | 141 memcpy(resultp, &private_key_size, sizeof(private_key_size)); |
142 resultp += sizeof(private_key_size); | 142 resultp += sizeof(private_key_size); |
143 memcpy(resultp, &private_key[0], private_key.size()); | 143 memcpy(resultp, &private_key[0], private_key.size()); |
(...skipping 25 matching lines...) Expand all Loading... |
169 | 169 |
170 peer_public_key.keyType = ecKey; | 170 peer_public_key.keyType = ecKey; |
171 // Both sides of a ECDH key exchange need to use the same EC params. | 171 // Both sides of a ECDH key exchange need to use the same EC params. |
172 peer_public_key.u.ec.DEREncodedParams.len = | 172 peer_public_key.u.ec.DEREncodedParams.len = |
173 key_pair_->public_key()->u.ec.DEREncodedParams.len; | 173 key_pair_->public_key()->u.ec.DEREncodedParams.len; |
174 peer_public_key.u.ec.DEREncodedParams.data = | 174 peer_public_key.u.ec.DEREncodedParams.data = |
175 key_pair_->public_key()->u.ec.DEREncodedParams.data; | 175 key_pair_->public_key()->u.ec.DEREncodedParams.data; |
176 | 176 |
177 peer_public_key.u.ec.publicValue.type = siBuffer; | 177 peer_public_key.u.ec.publicValue.type = siBuffer; |
178 peer_public_key.u.ec.publicValue.data = | 178 peer_public_key.u.ec.publicValue.data = |
179 reinterpret_cast<uint8*>(const_cast<char*>(peer_public_value.data())); | 179 reinterpret_cast<uint8_t*>(const_cast<char*>(peer_public_value.data())); |
180 peer_public_key.u.ec.publicValue.len = peer_public_value.size(); | 180 peer_public_key.u.ec.publicValue.len = peer_public_value.size(); |
181 | 181 |
182 // The NSS function performing ECDH key exchange is PK11_PubDeriveWithKDF. | 182 // The NSS function performing ECDH key exchange is PK11_PubDeriveWithKDF. |
183 // As this function is used for SSL/TLS's ECDH key exchanges it has many | 183 // As this function is used for SSL/TLS's ECDH key exchanges it has many |
184 // arguments, most of which are not required in QUIC. | 184 // arguments, most of which are not required in QUIC. |
185 // Key derivation function CKD_NULL is used because the return value of | 185 // Key derivation function CKD_NULL is used because the return value of |
186 // |CalculateSharedKey| is the actual ECDH shared key, not any derived keys | 186 // |CalculateSharedKey| is the actual ECDH shared key, not any derived keys |
187 // from it. | 187 // from it. |
188 crypto::ScopedPK11SymKey premaster_secret( | 188 crypto::ScopedPK11SymKey premaster_secret( |
189 PK11_PubDeriveWithKDF(key_pair_->key(), &peer_public_key, PR_FALSE, | 189 PK11_PubDeriveWithKDF(key_pair_->key(), &peer_public_key, PR_FALSE, |
(...skipping 25 matching lines...) Expand all Loading... |
215 StringPiece P256KeyExchange::public_value() const { | 215 StringPiece P256KeyExchange::public_value() const { |
216 return StringPiece(reinterpret_cast<const char*>(public_key_), | 216 return StringPiece(reinterpret_cast<const char*>(public_key_), |
217 sizeof(public_key_)); | 217 sizeof(public_key_)); |
218 } | 218 } |
219 | 219 |
220 QuicTag P256KeyExchange::tag() const { | 220 QuicTag P256KeyExchange::tag() const { |
221 return kP256; | 221 return kP256; |
222 } | 222 } |
223 | 223 |
224 } // namespace net | 224 } // namespace net |
OLD | NEW |