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/sys_byteorder.h" | 8 #include "base/sys_byteorder.h" |
9 | 9 |
10 using base::StringPiece; | 10 using base::StringPiece; |
(...skipping 27 matching lines...) Expand all Loading... |
38 } | 38 } |
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 NULL; | 44 return NULL; |
45 } | 45 } |
46 | 46 |
47 const uint8* data = reinterpret_cast<const uint8*>(key.data()); | 47 const uint8* data = reinterpret_cast<const uint8*>(key.data()); |
48 size_t size = static_cast<size_t>(data[0]) | | 48 size_t size = |
49 (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 NULL; | 53 return NULL; |
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); |
58 if (key.empty()) { | 58 if (key.empty()) { |
59 DVLOG(1) << "Key pair does not contain public key."; | 59 DVLOG(1) << "Key pair does not contain public key."; |
(...skipping 29 matching lines...) Expand all Loading... |
89 if (!oid_data) { | 89 if (!oid_data) { |
90 DVLOG(1) << "Can't get P-256's OID."; | 90 DVLOG(1) << "Can't get P-256's OID."; |
91 return NULL; | 91 return NULL; |
92 } | 92 } |
93 | 93 |
94 if (public_key->u.ec.DEREncodedParams.len != oid_data->oid.len + 2 || | 94 if (public_key->u.ec.DEREncodedParams.len != oid_data->oid.len + 2 || |
95 !public_key->u.ec.DEREncodedParams.data || | 95 !public_key->u.ec.DEREncodedParams.data || |
96 public_key->u.ec.DEREncodedParams.data[0] != SEC_ASN1_OBJECT_ID || | 96 public_key->u.ec.DEREncodedParams.data[0] != SEC_ASN1_OBJECT_ID || |
97 public_key->u.ec.DEREncodedParams.data[1] != oid_data->oid.len || | 97 public_key->u.ec.DEREncodedParams.data[1] != oid_data->oid.len || |
98 memcmp(public_key->u.ec.DEREncodedParams.data + 2, | 98 memcmp(public_key->u.ec.DEREncodedParams.data + 2, |
99 oid_data->oid.data, oid_data->oid.len) != 0) { | 99 oid_data->oid.data, |
| 100 oid_data->oid.len) != 0) { |
100 DVLOG(1) << "Key is invalid."; | 101 DVLOG(1) << "Key is invalid."; |
101 } | 102 } |
102 | 103 |
103 return new P256KeyExchange(key_pair.release(), | 104 return new P256KeyExchange(key_pair.release(), |
104 public_key->u.ec.publicValue.data); | 105 public_key->u.ec.publicValue.data); |
105 } | 106 } |
106 | 107 |
107 // static | 108 // static |
108 string P256KeyExchange::NewPrivateKey() { | 109 string P256KeyExchange::NewPrivateKey() { |
109 scoped_ptr<crypto::ECPrivateKey> key_pair(crypto::ECPrivateKey::Create()); | 110 scoped_ptr<crypto::ECPrivateKey> key_pair(crypto::ECPrivateKey::Create()); |
110 | 111 |
111 if (!key_pair.get()) { | 112 if (!key_pair.get()) { |
112 DVLOG(1) << "Can't generate new key pair."; | 113 DVLOG(1) << "Can't generate new key pair."; |
113 return string(); | 114 return string(); |
114 } | 115 } |
115 | 116 |
116 vector<uint8> private_key; | 117 vector<uint8> private_key; |
117 if (!key_pair->ExportEncryptedPrivateKey(kExportPassword, | 118 if (!key_pair->ExportEncryptedPrivateKey( |
118 1 /* iteration */, | 119 kExportPassword, 1 /* iteration */, &private_key)) { |
119 &private_key)) { | |
120 DVLOG(1) << "Can't export private key."; | 120 DVLOG(1) << "Can't export private key."; |
121 return string(); | 121 return string(); |
122 } | 122 } |
123 | 123 |
124 // NSS lacks the ability to import an ECC private key without | 124 // NSS lacks the ability to import an ECC private key without |
125 // also importing the public key, so it is necessary to also | 125 // also importing the public key, so it is necessary to also |
126 // store the public key. | 126 // store the public key. |
127 vector<uint8> public_key; | 127 vector<uint8> public_key; |
128 if (!key_pair->ExportPublicKey(&public_key)) { | 128 if (!key_pair->ExportPublicKey(&public_key)) { |
129 DVLOG(1) << "Can't export public key."; | 129 DVLOG(1) << "Can't export public key."; |
130 return string(); | 130 return string(); |
131 } | 131 } |
132 | 132 |
133 // TODO(thaidn): determine how large encrypted private key can be | 133 // TODO(thaidn): determine how large encrypted private key can be |
134 uint16 private_key_size = private_key.size(); | 134 uint16 private_key_size = private_key.size(); |
135 const size_t result_size = sizeof(private_key_size) + | 135 const size_t result_size = |
136 private_key_size + | 136 sizeof(private_key_size) + private_key_size + public_key.size(); |
137 public_key.size(); | |
138 vector<char> result(result_size); | 137 vector<char> result(result_size); |
139 char* resultp = &result[0]; | 138 char* resultp = &result[0]; |
140 // Export the key string. | 139 // Export the key string. |
141 // The first two bytes are the private key's size in little endian. | 140 // The first two bytes are the private key's size in little endian. |
142 private_key_size = base::ByteSwapToLE16(private_key_size); | 141 private_key_size = base::ByteSwapToLE16(private_key_size); |
143 memcpy(resultp, &private_key_size, sizeof(private_key_size)); | 142 memcpy(resultp, &private_key_size, sizeof(private_key_size)); |
144 resultp += sizeof(private_key_size); | 143 resultp += sizeof(private_key_size); |
145 memcpy(resultp, &private_key[0], private_key.size()); | 144 memcpy(resultp, &private_key[0], private_key.size()); |
146 resultp += private_key.size(); | 145 resultp += private_key.size(); |
147 memcpy(resultp, &public_key[0], public_key.size()); | 146 memcpy(resultp, &public_key[0], public_key.size()); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
181 reinterpret_cast<uint8*>(const_cast<char*>(peer_public_value.data())); | 180 reinterpret_cast<uint8*>(const_cast<char*>(peer_public_value.data())); |
182 peer_public_key.u.ec.publicValue.len = peer_public_value.size(); | 181 peer_public_key.u.ec.publicValue.len = peer_public_value.size(); |
183 | 182 |
184 // The NSS function performing ECDH key exchange is PK11_PubDeriveWithKDF. | 183 // The NSS function performing ECDH key exchange is PK11_PubDeriveWithKDF. |
185 // As this function is used for SSL/TLS's ECDH key exchanges it has many | 184 // As this function is used for SSL/TLS's ECDH key exchanges it has many |
186 // arguments, most of which are not required in QUIC. | 185 // arguments, most of which are not required in QUIC. |
187 // Key derivation function CKD_NULL is used because the return value of | 186 // Key derivation function CKD_NULL is used because the return value of |
188 // |CalculateSharedKey| is the actual ECDH shared key, not any derived keys | 187 // |CalculateSharedKey| is the actual ECDH shared key, not any derived keys |
189 // from it. | 188 // from it. |
190 crypto::ScopedPK11SymKey premaster_secret( | 189 crypto::ScopedPK11SymKey premaster_secret( |
191 PK11_PubDeriveWithKDF( | 190 PK11_PubDeriveWithKDF(key_pair_->key(), |
192 key_pair_->key(), | 191 &peer_public_key, |
193 &peer_public_key, | 192 PR_FALSE, |
194 PR_FALSE, | 193 NULL, |
195 NULL, | 194 NULL, |
196 NULL, | 195 CKM_ECDH1_DERIVE, /* mechanism */ |
197 CKM_ECDH1_DERIVE, /* mechanism */ | 196 CKM_GENERIC_SECRET_KEY_GEN, /* target */ |
198 CKM_GENERIC_SECRET_KEY_GEN, /* target */ | 197 CKA_DERIVE, |
199 CKA_DERIVE, | 198 0, |
200 0, | 199 CKD_NULL, /* kdf */ |
201 CKD_NULL, /* kdf */ | 200 NULL, |
202 NULL, | 201 NULL)); |
203 NULL)); | |
204 | 202 |
205 if (!premaster_secret.get()) { | 203 if (!premaster_secret.get()) { |
206 DVLOG(1) << "Can't derive ECDH shared key."; | 204 DVLOG(1) << "Can't derive ECDH shared key."; |
207 return false; | 205 return false; |
208 } | 206 } |
209 | 207 |
210 if (PK11_ExtractKeyValue(premaster_secret.get()) != SECSuccess) { | 208 if (PK11_ExtractKeyValue(premaster_secret.get()) != SECSuccess) { |
211 DVLOG(1) << "Can't extract raw ECDH shared key."; | 209 DVLOG(1) << "Can't extract raw ECDH shared key."; |
212 return false; | 210 return false; |
213 } | 211 } |
214 | 212 |
215 SECItem* key_data = PK11_GetKeyData(premaster_secret.get()); | 213 SECItem* key_data = PK11_GetKeyData(premaster_secret.get()); |
216 if (!key_data || !key_data->data || key_data->len != kP256FieldBytes) { | 214 if (!key_data || !key_data->data || key_data->len != kP256FieldBytes) { |
217 DVLOG(1) << "ECDH shared key is invalid."; | 215 DVLOG(1) << "ECDH shared key is invalid."; |
218 return false; | 216 return false; |
219 } | 217 } |
220 | 218 |
221 out_result->assign(reinterpret_cast<char*>(key_data->data), key_data->len); | 219 out_result->assign(reinterpret_cast<char*>(key_data->data), key_data->len); |
222 return true; | 220 return true; |
223 } | 221 } |
224 | 222 |
225 StringPiece P256KeyExchange::public_value() const { | 223 StringPiece P256KeyExchange::public_value() const { |
226 return StringPiece(reinterpret_cast<const char*>(public_key_), | 224 return StringPiece(reinterpret_cast<const char*>(public_key_), |
227 sizeof(public_key_)); | 225 sizeof(public_key_)); |
228 } | 226 } |
229 | 227 |
230 QuicTag P256KeyExchange::tag() const { return kP256; } | 228 QuicTag P256KeyExchange::tag() const { |
| 229 return kP256; |
| 230 } |
231 | 231 |
232 } // namespace net | 232 } // namespace net |
233 | |
OLD | NEW |