| 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 23 matching lines...) Expand all Loading... |
| 34 memcpy(public_key_, public_key, sizeof(public_key_)); | 34 memcpy(public_key_, public_key, sizeof(public_key_)); |
| 35 } | 35 } |
| 36 | 36 |
| 37 P256KeyExchange::~P256KeyExchange() { | 37 P256KeyExchange::~P256KeyExchange() { |
| 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 nullptr; |
| 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 = static_cast<size_t>(data[0]) | |
| 49 (static_cast<size_t>(data[1]) << 8); | 49 (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 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); |
| 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."; |
| 60 return NULL; | 60 return nullptr; |
| 61 } | 61 } |
| 62 | 62 |
| 63 StringPiece public_piece(key); | 63 StringPiece public_piece(key); |
| 64 | 64 |
| 65 scoped_ptr<crypto::ECPrivateKey> key_pair( | 65 scoped_ptr<crypto::ECPrivateKey> key_pair( |
| 66 crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( | 66 crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( |
| 67 kExportPassword, | 67 kExportPassword, |
| 68 // TODO(thaidn): fix this interface to avoid copying secrets. | 68 // TODO(thaidn): fix this interface to avoid copying secrets. |
| 69 StringPieceToVector(private_piece), | 69 StringPieceToVector(private_piece), |
| 70 StringPieceToVector(public_piece))); | 70 StringPieceToVector(public_piece))); |
| 71 | 71 |
| 72 if (!key_pair.get()) { | 72 if (!key_pair.get()) { |
| 73 DVLOG(1) << "Can't decrypt private key."; | 73 DVLOG(1) << "Can't decrypt private key."; |
| 74 return NULL; | 74 return nullptr; |
| 75 } | 75 } |
| 76 | 76 |
| 77 // Perform some sanity checks on the public key. | 77 // Perform some sanity checks on the public key. |
| 78 SECKEYPublicKey* public_key = key_pair->public_key(); | 78 SECKEYPublicKey* public_key = key_pair->public_key(); |
| 79 if (public_key->keyType != ecKey || | 79 if (public_key->keyType != ecKey || |
| 80 public_key->u.ec.publicValue.len != kUncompressedP256PointBytes || | 80 public_key->u.ec.publicValue.len != kUncompressedP256PointBytes || |
| 81 !public_key->u.ec.publicValue.data || | 81 !public_key->u.ec.publicValue.data || |
| 82 public_key->u.ec.publicValue.data[0] != kUncompressedECPointForm) { | 82 public_key->u.ec.publicValue.data[0] != kUncompressedECPointForm) { |
| 83 DVLOG(1) << "Key is invalid."; | 83 DVLOG(1) << "Key is invalid."; |
| 84 return NULL; | 84 return nullptr; |
| 85 } | 85 } |
| 86 | 86 |
| 87 // Ensure that the key is using the correct curve, i.e., NIST P-256. | 87 // Ensure that the key is using the correct curve, i.e., NIST P-256. |
| 88 const SECOidData* oid_data = SECOID_FindOIDByTag(SEC_OID_SECG_EC_SECP256R1); | 88 const SECOidData* oid_data = SECOID_FindOIDByTag(SEC_OID_SECG_EC_SECP256R1); |
| 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 nullptr; |
| 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, oid_data->oid.len) != 0) { |
| 100 DVLOG(1) << "Key is invalid."; | 100 DVLOG(1) << "Key is invalid."; |
| 101 } | 101 } |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 185 // As this function is used for SSL/TLS's ECDH key exchanges it has many | 185 // 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. | 186 // arguments, most of which are not required in QUIC. |
| 187 // Key derivation function CKD_NULL is used because the return value of | 187 // Key derivation function CKD_NULL is used because the return value of |
| 188 // |CalculateSharedKey| is the actual ECDH shared key, not any derived keys | 188 // |CalculateSharedKey| is the actual ECDH shared key, not any derived keys |
| 189 // from it. | 189 // from it. |
| 190 crypto::ScopedPK11SymKey premaster_secret( | 190 crypto::ScopedPK11SymKey premaster_secret( |
| 191 PK11_PubDeriveWithKDF( | 191 PK11_PubDeriveWithKDF( |
| 192 key_pair_->key(), | 192 key_pair_->key(), |
| 193 &peer_public_key, | 193 &peer_public_key, |
| 194 PR_FALSE, | 194 PR_FALSE, |
| 195 NULL, | 195 nullptr, |
| 196 NULL, | 196 nullptr, |
| 197 CKM_ECDH1_DERIVE, /* mechanism */ | 197 CKM_ECDH1_DERIVE, /* mechanism */ |
| 198 CKM_GENERIC_SECRET_KEY_GEN, /* target */ | 198 CKM_GENERIC_SECRET_KEY_GEN, /* target */ |
| 199 CKA_DERIVE, | 199 CKA_DERIVE, |
| 200 0, | 200 0, |
| 201 CKD_NULL, /* kdf */ | 201 CKD_NULL, /* kdf */ |
| 202 NULL, | 202 nullptr, |
| 203 NULL)); | 203 nullptr)); |
| 204 | 204 |
| 205 if (!premaster_secret.get()) { | 205 if (!premaster_secret.get()) { |
| 206 DVLOG(1) << "Can't derive ECDH shared key."; | 206 DVLOG(1) << "Can't derive ECDH shared key."; |
| 207 return false; | 207 return false; |
| 208 } | 208 } |
| 209 | 209 |
| 210 if (PK11_ExtractKeyValue(premaster_secret.get()) != SECSuccess) { | 210 if (PK11_ExtractKeyValue(premaster_secret.get()) != SECSuccess) { |
| 211 DVLOG(1) << "Can't extract raw ECDH shared key."; | 211 DVLOG(1) << "Can't extract raw ECDH shared key."; |
| 212 return false; | 212 return false; |
| 213 } | 213 } |
| 214 | 214 |
| 215 SECItem* key_data = PK11_GetKeyData(premaster_secret.get()); | 215 SECItem* key_data = PK11_GetKeyData(premaster_secret.get()); |
| 216 if (!key_data || !key_data->data || key_data->len != kP256FieldBytes) { | 216 if (!key_data || !key_data->data || key_data->len != kP256FieldBytes) { |
| 217 DVLOG(1) << "ECDH shared key is invalid."; | 217 DVLOG(1) << "ECDH shared key is invalid."; |
| 218 return false; | 218 return false; |
| 219 } | 219 } |
| 220 | 220 |
| 221 out_result->assign(reinterpret_cast<char*>(key_data->data), key_data->len); | 221 out_result->assign(reinterpret_cast<char*>(key_data->data), key_data->len); |
| 222 return true; | 222 return true; |
| 223 } | 223 } |
| 224 | 224 |
| 225 StringPiece P256KeyExchange::public_value() const { | 225 StringPiece P256KeyExchange::public_value() const { |
| 226 return StringPiece(reinterpret_cast<const char*>(public_key_), | 226 return StringPiece(reinterpret_cast<const char*>(public_key_), |
| 227 sizeof(public_key_)); | 227 sizeof(public_key_)); |
| 228 } | 228 } |
| 229 | 229 |
| 230 QuicTag P256KeyExchange::tag() const { return kP256; } | 230 QuicTag P256KeyExchange::tag() const { return kP256; } |
| 231 | 231 |
| 232 } // namespace net | 232 } // namespace net |
| 233 | |
| OLD | NEW |