| 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/core/crypto/p256_key_exchange.h" | 5 #include "net/quic/core/crypto/p256_key_exchange.h" |
| 6 | 6 |
| 7 #include <cstdint> | 7 #include <cstdint> |
| 8 #include <memory> | 8 #include <memory> |
| 9 #include <string> | 9 #include <string> |
| 10 #include <utility> | 10 #include <utility> |
| 11 | 11 |
| 12 #include "net/quic/platform/api/quic_logging.h" | 12 #include "base/logging.h" |
| 13 #include "third_party/boringssl/src/include/openssl/ec.h" | 13 #include "third_party/boringssl/src/include/openssl/ec.h" |
| 14 #include "third_party/boringssl/src/include/openssl/ecdh.h" | 14 #include "third_party/boringssl/src/include/openssl/ecdh.h" |
| 15 #include "third_party/boringssl/src/include/openssl/err.h" | 15 #include "third_party/boringssl/src/include/openssl/err.h" |
| 16 #include "third_party/boringssl/src/include/openssl/evp.h" | 16 #include "third_party/boringssl/src/include/openssl/evp.h" |
| 17 | 17 |
| 18 using base::StringPiece; | 18 using base::StringPiece; |
| 19 using std::string; | 19 using std::string; |
| 20 | 20 |
| 21 namespace net { | 21 namespace net { |
| 22 | 22 |
| 23 P256KeyExchange::P256KeyExchange(bssl::UniquePtr<EC_KEY> private_key, | 23 P256KeyExchange::P256KeyExchange(bssl::UniquePtr<EC_KEY> private_key, |
| 24 const uint8_t* public_key) | 24 const uint8_t* public_key) |
| 25 : private_key_(std::move(private_key)) { | 25 : private_key_(std::move(private_key)) { |
| 26 memcpy(public_key_, public_key, sizeof(public_key_)); | 26 memcpy(public_key_, public_key, sizeof(public_key_)); |
| 27 } | 27 } |
| 28 | 28 |
| 29 P256KeyExchange::~P256KeyExchange() {} | 29 P256KeyExchange::~P256KeyExchange() {} |
| 30 | 30 |
| 31 // static | 31 // static |
| 32 P256KeyExchange* P256KeyExchange::New(StringPiece key) { | 32 P256KeyExchange* P256KeyExchange::New(StringPiece key) { |
| 33 if (key.empty()) { | 33 if (key.empty()) { |
| 34 QUIC_DLOG(INFO) << "Private key is empty"; | 34 DVLOG(1) << "Private key is empty"; |
| 35 return nullptr; | 35 return nullptr; |
| 36 } | 36 } |
| 37 | 37 |
| 38 const uint8_t* keyp = reinterpret_cast<const uint8_t*>(key.data()); | 38 const uint8_t* keyp = reinterpret_cast<const uint8_t*>(key.data()); |
| 39 bssl::UniquePtr<EC_KEY> private_key( | 39 bssl::UniquePtr<EC_KEY> private_key( |
| 40 d2i_ECPrivateKey(nullptr, &keyp, key.size())); | 40 d2i_ECPrivateKey(nullptr, &keyp, key.size())); |
| 41 if (!private_key.get() || !EC_KEY_check_key(private_key.get())) { | 41 if (!private_key.get() || !EC_KEY_check_key(private_key.get())) { |
| 42 QUIC_DLOG(INFO) << "Private key is invalid."; | 42 DVLOG(1) << "Private key is invalid."; |
| 43 return nullptr; | 43 return nullptr; |
| 44 } | 44 } |
| 45 | 45 |
| 46 uint8_t public_key[kUncompressedP256PointBytes]; | 46 uint8_t public_key[kUncompressedP256PointBytes]; |
| 47 if (EC_POINT_point2oct(EC_KEY_get0_group(private_key.get()), | 47 if (EC_POINT_point2oct(EC_KEY_get0_group(private_key.get()), |
| 48 EC_KEY_get0_public_key(private_key.get()), | 48 EC_KEY_get0_public_key(private_key.get()), |
| 49 POINT_CONVERSION_UNCOMPRESSED, public_key, | 49 POINT_CONVERSION_UNCOMPRESSED, public_key, |
| 50 sizeof(public_key), nullptr) != sizeof(public_key)) { | 50 sizeof(public_key), nullptr) != sizeof(public_key)) { |
| 51 QUIC_DLOG(INFO) << "Can't get public key."; | 51 DVLOG(1) << "Can't get public key."; |
| 52 return nullptr; | 52 return nullptr; |
| 53 } | 53 } |
| 54 | 54 |
| 55 return new P256KeyExchange(std::move(private_key), public_key); | 55 return new P256KeyExchange(std::move(private_key), public_key); |
| 56 } | 56 } |
| 57 | 57 |
| 58 // static | 58 // static |
| 59 string P256KeyExchange::NewPrivateKey() { | 59 string P256KeyExchange::NewPrivateKey() { |
| 60 bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); | 60 bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); |
| 61 if (!key.get() || !EC_KEY_generate_key(key.get())) { | 61 if (!key.get() || !EC_KEY_generate_key(key.get())) { |
| 62 QUIC_DLOG(INFO) << "Can't generate a new private key."; | 62 DVLOG(1) << "Can't generate a new private key."; |
| 63 return string(); | 63 return string(); |
| 64 } | 64 } |
| 65 | 65 |
| 66 int key_len = i2d_ECPrivateKey(key.get(), nullptr); | 66 int key_len = i2d_ECPrivateKey(key.get(), nullptr); |
| 67 if (key_len <= 0) { | 67 if (key_len <= 0) { |
| 68 QUIC_DLOG(INFO) << "Can't convert private key to string"; | 68 DVLOG(1) << "Can't convert private key to string"; |
| 69 return string(); | 69 return string(); |
| 70 } | 70 } |
| 71 std::unique_ptr<uint8_t[]> private_key(new uint8_t[key_len]); | 71 std::unique_ptr<uint8_t[]> private_key(new uint8_t[key_len]); |
| 72 uint8_t* keyp = private_key.get(); | 72 uint8_t* keyp = private_key.get(); |
| 73 if (!i2d_ECPrivateKey(key.get(), &keyp)) { | 73 if (!i2d_ECPrivateKey(key.get(), &keyp)) { |
| 74 QUIC_DLOG(INFO) << "Can't convert private key to string."; | 74 DVLOG(1) << "Can't convert private key to string."; |
| 75 return string(); | 75 return string(); |
| 76 } | 76 } |
| 77 return string(reinterpret_cast<char*>(private_key.get()), key_len); | 77 return string(reinterpret_cast<char*>(private_key.get()), key_len); |
| 78 } | 78 } |
| 79 | 79 |
| 80 KeyExchange* P256KeyExchange::NewKeyPair(QuicRandom* /*rand*/) const { | 80 KeyExchange* P256KeyExchange::NewKeyPair(QuicRandom* /*rand*/) const { |
| 81 // TODO(agl): avoid the serialisation/deserialisation in this function. | 81 // TODO(agl): avoid the serialisation/deserialisation in this function. |
| 82 const string private_value = NewPrivateKey(); | 82 const string private_value = NewPrivateKey(); |
| 83 return P256KeyExchange::New(private_value); | 83 return P256KeyExchange::New(private_value); |
| 84 } | 84 } |
| 85 | 85 |
| 86 bool P256KeyExchange::CalculateSharedKey(StringPiece peer_public_value, | 86 bool P256KeyExchange::CalculateSharedKey(StringPiece peer_public_value, |
| 87 string* out_result) const { | 87 string* out_result) const { |
| 88 if (peer_public_value.size() != kUncompressedP256PointBytes) { | 88 if (peer_public_value.size() != kUncompressedP256PointBytes) { |
| 89 QUIC_DLOG(INFO) << "Peer public value is invalid"; | 89 DVLOG(1) << "Peer public value is invalid"; |
| 90 return false; | 90 return false; |
| 91 } | 91 } |
| 92 | 92 |
| 93 bssl::UniquePtr<EC_POINT> point( | 93 bssl::UniquePtr<EC_POINT> point( |
| 94 EC_POINT_new(EC_KEY_get0_group(private_key_.get()))); | 94 EC_POINT_new(EC_KEY_get0_group(private_key_.get()))); |
| 95 if (!point.get() || | 95 if (!point.get() || |
| 96 !EC_POINT_oct2point(/* also test if point is on curve */ | 96 !EC_POINT_oct2point(/* also test if point is on curve */ |
| 97 EC_KEY_get0_group(private_key_.get()), point.get(), | 97 EC_KEY_get0_group(private_key_.get()), point.get(), |
| 98 reinterpret_cast<const uint8_t*>( | 98 reinterpret_cast<const uint8_t*>( |
| 99 peer_public_value.data()), | 99 peer_public_value.data()), |
| 100 peer_public_value.size(), nullptr)) { | 100 peer_public_value.size(), nullptr)) { |
| 101 QUIC_DLOG(INFO) << "Can't convert peer public value to curve point."; | 101 DVLOG(1) << "Can't convert peer public value to curve point."; |
| 102 return false; | 102 return false; |
| 103 } | 103 } |
| 104 | 104 |
| 105 uint8_t result[kP256FieldBytes]; | 105 uint8_t result[kP256FieldBytes]; |
| 106 if (ECDH_compute_key(result, sizeof(result), point.get(), private_key_.get(), | 106 if (ECDH_compute_key(result, sizeof(result), point.get(), private_key_.get(), |
| 107 nullptr) != sizeof(result)) { | 107 nullptr) != sizeof(result)) { |
| 108 QUIC_DLOG(INFO) << "Can't compute ECDH shared key."; | 108 DVLOG(1) << "Can't compute ECDH shared key."; |
| 109 return false; | 109 return false; |
| 110 } | 110 } |
| 111 | 111 |
| 112 out_result->assign(reinterpret_cast<char*>(result), sizeof(result)); | 112 out_result->assign(reinterpret_cast<char*>(result), sizeof(result)); |
| 113 return true; | 113 return true; |
| 114 } | 114 } |
| 115 | 115 |
| 116 StringPiece P256KeyExchange::public_value() const { | 116 StringPiece P256KeyExchange::public_value() const { |
| 117 return StringPiece(reinterpret_cast<const char*>(public_key_), | 117 return StringPiece(reinterpret_cast<const char*>(public_key_), |
| 118 sizeof(public_key_)); | 118 sizeof(public_key_)); |
| 119 } | 119 } |
| 120 | 120 |
| 121 QuicTag P256KeyExchange::tag() const { | 121 QuicTag P256KeyExchange::tag() const { |
| 122 return kP256; | 122 return kP256; |
| 123 } | 123 } |
| 124 | 124 |
| 125 } // namespace net | 125 } // namespace net |
| OLD | NEW |