| 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 |