| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/test_tools/crypto_test_utils.h" | 5 #include "net/quic/test_tools/crypto_test_utils.h" |
| 6 | 6 |
| 7 #include <openssl/bn.h> |
| 8 #include <openssl/ec.h> |
| 9 #include <openssl/ecdsa.h> |
| 10 #include <openssl/evp.h> |
| 11 #include <openssl/obj_mac.h> |
| 12 #include <openssl/sha.h> |
| 13 |
| 7 #include <memory> | 14 #include <memory> |
| 8 | 15 |
| 9 #include "base/strings/string_util.h" | 16 #include "base/strings/string_util.h" |
| 17 #include "crypto/openssl_util.h" |
| 18 #include "crypto/scoped_openssl_types.h" |
| 19 #include "crypto/secure_hash.h" |
| 10 #include "net/quic/crypto/channel_id.h" | 20 #include "net/quic/crypto/channel_id.h" |
| 11 #include "net/quic/crypto/common_cert_set.h" | 21 #include "net/quic/crypto/common_cert_set.h" |
| 12 #include "net/quic/crypto/crypto_handshake.h" | 22 #include "net/quic/crypto/crypto_handshake.h" |
| 13 #include "net/quic/crypto/quic_crypto_server_config.h" | 23 #include "net/quic/crypto/quic_crypto_server_config.h" |
| 14 #include "net/quic/crypto/quic_decrypter.h" | 24 #include "net/quic/crypto/quic_decrypter.h" |
| 15 #include "net/quic/crypto/quic_encrypter.h" | 25 #include "net/quic/crypto/quic_encrypter.h" |
| 16 #include "net/quic/crypto/quic_random.h" | 26 #include "net/quic/crypto/quic_random.h" |
| 17 #include "net/quic/quic_clock.h" | 27 #include "net/quic/quic_clock.h" |
| 18 #include "net/quic/quic_crypto_client_stream.h" | 28 #include "net/quic/quic_crypto_client_stream.h" |
| 19 #include "net/quic/quic_crypto_server_stream.h" | 29 #include "net/quic/quic_crypto_server_stream.h" |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 110 callback_.reset(); | 120 callback_.reset(); |
| 111 } | 121 } |
| 112 } | 122 } |
| 113 | 123 |
| 114 private: | 124 private: |
| 115 std::unique_ptr<ChannelIDSource> sync_source_; | 125 std::unique_ptr<ChannelIDSource> sync_source_; |
| 116 std::unique_ptr<ChannelIDSourceCallback> callback_; | 126 std::unique_ptr<ChannelIDSourceCallback> callback_; |
| 117 std::unique_ptr<ChannelIDKey> channel_id_key_; | 127 std::unique_ptr<ChannelIDKey> channel_id_key_; |
| 118 }; | 128 }; |
| 119 | 129 |
| 130 class TestChannelIDKey : public ChannelIDKey { |
| 131 public: |
| 132 explicit TestChannelIDKey(EVP_PKEY* ecdsa_key) : ecdsa_key_(ecdsa_key) {} |
| 133 ~TestChannelIDKey() override {} |
| 134 |
| 135 // ChannelIDKey implementation. |
| 136 |
| 137 bool Sign(StringPiece signed_data, string* out_signature) const override { |
| 138 crypto::ScopedEVP_MD_CTX md_ctx(EVP_MD_CTX_create()); |
| 139 if (!md_ctx || |
| 140 EVP_DigestSignInit(md_ctx.get(), nullptr, EVP_sha256(), nullptr, |
| 141 ecdsa_key_.get()) != 1) { |
| 142 return false; |
| 143 } |
| 144 |
| 145 EVP_DigestUpdate(md_ctx.get(), ChannelIDVerifier::kContextStr, |
| 146 strlen(ChannelIDVerifier::kContextStr) + 1); |
| 147 EVP_DigestUpdate(md_ctx.get(), ChannelIDVerifier::kClientToServerStr, |
| 148 strlen(ChannelIDVerifier::kClientToServerStr) + 1); |
| 149 EVP_DigestUpdate(md_ctx.get(), signed_data.data(), signed_data.size()); |
| 150 |
| 151 size_t sig_len; |
| 152 if (!EVP_DigestSignFinal(md_ctx.get(), nullptr, &sig_len)) { |
| 153 return false; |
| 154 } |
| 155 |
| 156 std::unique_ptr<uint8_t[]> der_sig(new uint8_t[sig_len]); |
| 157 if (!EVP_DigestSignFinal(md_ctx.get(), der_sig.get(), &sig_len)) { |
| 158 return false; |
| 159 } |
| 160 |
| 161 uint8_t* derp = der_sig.get(); |
| 162 crypto::ScopedECDSA_SIG sig( |
| 163 d2i_ECDSA_SIG(nullptr, const_cast<const uint8_t**>(&derp), sig_len)); |
| 164 if (sig.get() == nullptr) { |
| 165 return false; |
| 166 } |
| 167 |
| 168 // The signature consists of a pair of 32-byte numbers. |
| 169 static const size_t kSignatureLength = 32 * 2; |
| 170 std::unique_ptr<uint8_t[]> signature(new uint8_t[kSignatureLength]); |
| 171 if (!BN_bn2bin_padded(&signature[0], 32, sig->r) || |
| 172 !BN_bn2bin_padded(&signature[32], 32, sig->s)) { |
| 173 return false; |
| 174 } |
| 175 |
| 176 *out_signature = |
| 177 string(reinterpret_cast<char*>(signature.get()), kSignatureLength); |
| 178 |
| 179 return true; |
| 180 } |
| 181 |
| 182 string SerializeKey() const override { |
| 183 // i2d_PublicKey will produce an ANSI X9.62 public key which, for a P-256 |
| 184 // key, is 0x04 (meaning uncompressed) followed by the x and y field |
| 185 // elements as 32-byte, big-endian numbers. |
| 186 static const int kExpectedKeyLength = 65; |
| 187 |
| 188 int len = i2d_PublicKey(ecdsa_key_.get(), nullptr); |
| 189 if (len != kExpectedKeyLength) { |
| 190 return ""; |
| 191 } |
| 192 |
| 193 uint8_t buf[kExpectedKeyLength]; |
| 194 uint8_t* derp = buf; |
| 195 i2d_PublicKey(ecdsa_key_.get(), &derp); |
| 196 |
| 197 return string(reinterpret_cast<char*>(buf + 1), kExpectedKeyLength - 1); |
| 198 } |
| 199 |
| 200 private: |
| 201 crypto::ScopedEVP_PKEY ecdsa_key_; |
| 202 }; |
| 203 |
| 204 class TestChannelIDSource : public ChannelIDSource { |
| 205 public: |
| 206 ~TestChannelIDSource() override {} |
| 207 |
| 208 // ChannelIDSource implementation. |
| 209 |
| 210 QuicAsyncStatus GetChannelIDKey( |
| 211 const string& hostname, |
| 212 std::unique_ptr<ChannelIDKey>* channel_id_key, |
| 213 ChannelIDSourceCallback* /*callback*/) override { |
| 214 channel_id_key->reset(new TestChannelIDKey(HostnameToKey(hostname))); |
| 215 return QUIC_SUCCESS; |
| 216 } |
| 217 |
| 218 private: |
| 219 static EVP_PKEY* HostnameToKey(const string& hostname) { |
| 220 // In order to generate a deterministic key for a given hostname the |
| 221 // hostname is hashed with SHA-256 and the resulting digest is treated as a |
| 222 // big-endian number. The most-significant bit is cleared to ensure that |
| 223 // the resulting value is less than the order of the group and then it's |
| 224 // taken as a private key. Given the private key, the public key is |
| 225 // calculated with a group multiplication. |
| 226 SHA256_CTX sha256; |
| 227 SHA256_Init(&sha256); |
| 228 SHA256_Update(&sha256, hostname.data(), hostname.size()); |
| 229 |
| 230 unsigned char digest[SHA256_DIGEST_LENGTH]; |
| 231 SHA256_Final(digest, &sha256); |
| 232 |
| 233 // Ensure that the digest is less than the order of the P-256 group by |
| 234 // clearing the most-significant bit. |
| 235 digest[0] &= 0x7f; |
| 236 |
| 237 crypto::ScopedBIGNUM k(BN_new()); |
| 238 CHECK(BN_bin2bn(digest, sizeof(digest), k.get()) != nullptr); |
| 239 |
| 240 crypto::ScopedEC_GROUP p256( |
| 241 EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)); |
| 242 CHECK(p256); |
| 243 |
| 244 crypto::ScopedEC_KEY ecdsa_key(EC_KEY_new()); |
| 245 CHECK(ecdsa_key && EC_KEY_set_group(ecdsa_key.get(), p256.get())); |
| 246 |
| 247 crypto::ScopedEC_POINT point(EC_POINT_new(p256.get())); |
| 248 CHECK(EC_POINT_mul(p256.get(), point.get(), k.get(), nullptr, nullptr, |
| 249 nullptr)); |
| 250 |
| 251 EC_KEY_set_private_key(ecdsa_key.get(), k.get()); |
| 252 EC_KEY_set_public_key(ecdsa_key.get(), point.get()); |
| 253 |
| 254 crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new()); |
| 255 // EVP_PKEY_set1_EC_KEY takes a reference so no |release| here. |
| 256 EVP_PKEY_set1_EC_KEY(pkey.get(), ecdsa_key.get()); |
| 257 |
| 258 return pkey.release(); |
| 259 } |
| 260 }; |
| 261 |
| 120 } // anonymous namespace | 262 } // anonymous namespace |
| 121 | 263 |
| 122 CryptoTestUtils::FakeServerOptions::FakeServerOptions() | 264 CryptoTestUtils::FakeServerOptions::FakeServerOptions() |
| 123 : token_binding_enabled(false) {} | 265 : token_binding_enabled(false) {} |
| 124 | 266 |
| 125 CryptoTestUtils::FakeClientOptions::FakeClientOptions() | 267 CryptoTestUtils::FakeClientOptions::FakeClientOptions() |
| 126 : channel_id_enabled(false), | 268 : channel_id_enabled(false), |
| 127 channel_id_source_async(false), | 269 channel_id_source_async(false), |
| 128 token_binding_enabled(false) {} | 270 token_binding_enabled(false) {} |
| 129 | 271 |
| (...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 603 std::unique_ptr<QuicData> bytes(CryptoFramer::ConstructHandshakeMessage(msg)); | 745 std::unique_ptr<QuicData> bytes(CryptoFramer::ConstructHandshakeMessage(msg)); |
| 604 std::unique_ptr<CryptoHandshakeMessage> parsed( | 746 std::unique_ptr<CryptoHandshakeMessage> parsed( |
| 605 CryptoFramer::ParseMessage(bytes->AsStringPiece())); | 747 CryptoFramer::ParseMessage(bytes->AsStringPiece())); |
| 606 CHECK(parsed.get()); | 748 CHECK(parsed.get()); |
| 607 | 749 |
| 608 va_end(ap); | 750 va_end(ap); |
| 609 return *parsed; | 751 return *parsed; |
| 610 } | 752 } |
| 611 | 753 |
| 612 // static | 754 // static |
| 755 ChannelIDSource* CryptoTestUtils::ChannelIDSourceForTesting() { |
| 756 return new TestChannelIDSource(); |
| 757 } |
| 758 |
| 759 // static |
| 613 void CryptoTestUtils::MovePackets(PacketSavingConnection* source_conn, | 760 void CryptoTestUtils::MovePackets(PacketSavingConnection* source_conn, |
| 614 size_t* inout_packet_index, | 761 size_t* inout_packet_index, |
| 615 QuicCryptoStream* dest_stream, | 762 QuicCryptoStream* dest_stream, |
| 616 PacketSavingConnection* dest_conn) { | 763 PacketSavingConnection* dest_conn) { |
| 617 SimpleQuicFramer framer(source_conn->supported_versions()); | 764 SimpleQuicFramer framer(source_conn->supported_versions()); |
| 618 CryptoFramer crypto_framer; | 765 CryptoFramer crypto_framer; |
| 619 CryptoFramerVisitor crypto_visitor; | 766 CryptoFramerVisitor crypto_visitor; |
| 620 | 767 |
| 621 // In order to properly test the code we need to perform encryption and | 768 // In order to properly test the code we need to perform encryption and |
| 622 // decryption so that the crypters latch when expected. The crypters are in | 769 // decryption so that the crypters latch when expected. The crypters are in |
| (...skipping 24 matching lines...) Expand all Loading... |
| 647 | 794 |
| 648 ASSERT_EQ(0u, crypto_framer.InputBytesRemaining()); | 795 ASSERT_EQ(0u, crypto_framer.InputBytesRemaining()); |
| 649 | 796 |
| 650 for (const CryptoHandshakeMessage& message : crypto_visitor.messages()) { | 797 for (const CryptoHandshakeMessage& message : crypto_visitor.messages()) { |
| 651 dest_stream->OnHandshakeMessage(message); | 798 dest_stream->OnHandshakeMessage(message); |
| 652 } | 799 } |
| 653 } | 800 } |
| 654 | 801 |
| 655 } // namespace test | 802 } // namespace test |
| 656 } // namespace net | 803 } // namespace net |
| OLD | NEW |