| /** @file |
| * |
| * A brief file description |
| * |
| * @section license License |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "catch.hpp" |
| |
| #include <iostream> |
| #include <fstream> |
| #include <iomanip> |
| |
| #ifdef OPENSSL_IS_BORINGSSL |
| #include <openssl/base.h> |
| #endif |
| |
| #include <openssl/ssl.h> |
| |
| // #include "Mock.h" |
| #include "QUICPacketHeaderProtector.h" |
| #include "QUICPacketPayloadProtector.h" |
| #include "QUICPacketProtectionKeyInfo.h" |
| #include "QUICTLS.h" |
| |
| // XXX For NetVCOptions::reset |
| struct PollCont; |
| #include "P_UDPConnection.h" |
| #include "P_UnixNet.h" |
| #include "P_UnixNetVConnection.h" |
| |
| #include "./server_cert.h" |
| |
| static void |
| print_hex(const uint8_t *v, size_t len) |
| { |
| for (size_t i = 0; i < len; i++) { |
| std::cout << std::setw(2) << std::setfill('0') << std::hex << static_cast<uint32_t>(v[i]) << " "; |
| |
| if (i != 0 && (i + 1) % 32 == 0 && i != len - 1) { |
| std::cout << std::endl; |
| } |
| } |
| |
| std::cout << std::endl; |
| |
| return; |
| } |
| |
| static const uint8_t original[] = { |
| 0x41, 0x70, 0x61, 0x63, 0x68, 0x65, 0x20, 0x54, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x20, 0x53, |
| 0x65, 0x72, 0x76, 0x65, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| }; |
| static const uint64_t pkt_num = 0x123456789; |
| static const uint8_t ad[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}; |
| |
| TEST_CASE("QUICHandshakeProtocol") |
| { |
| // Client |
| SSL_CTX *client_ssl_ctx = SSL_CTX_new(TLS_method()); |
| SSL_CTX_set_min_proto_version(client_ssl_ctx, TLS1_3_VERSION); |
| SSL_CTX_set_max_proto_version(client_ssl_ctx, TLS1_3_VERSION); |
| #ifndef OPENSSL_IS_BORINGSSL |
| SSL_CTX_clear_options(client_ssl_ctx, SSL_OP_ENABLE_MIDDLEBOX_COMPAT); |
| #endif |
| #ifdef SSL_MODE_QUIC_HACK |
| SSL_CTX_set_mode(client_ssl_ctx, SSL_MODE_QUIC_HACK); |
| #endif |
| |
| // Server |
| SSL_CTX *server_ssl_ctx = SSL_CTX_new(TLS_method()); |
| SSL_CTX_set_min_proto_version(server_ssl_ctx, TLS1_3_VERSION); |
| SSL_CTX_set_max_proto_version(server_ssl_ctx, TLS1_3_VERSION); |
| #ifndef OPENSSL_IS_BORINGSSL |
| SSL_CTX_clear_options(server_ssl_ctx, SSL_OP_ENABLE_MIDDLEBOX_COMPAT); |
| #endif |
| #ifdef SSL_MODE_QUIC_HACK |
| SSL_CTX_set_mode(server_ssl_ctx, SSL_MODE_QUIC_HACK); |
| #endif |
| BIO *crt_bio(BIO_new_mem_buf(server_crt, sizeof(server_crt))); |
| X509 *x509 = PEM_read_bio_X509(crt_bio, nullptr, nullptr, nullptr); |
| SSL_CTX_use_certificate(server_ssl_ctx, x509); |
| BIO *key_bio(BIO_new_mem_buf(server_key, sizeof(server_key))); |
| EVP_PKEY *pkey = PEM_read_bio_PrivateKey(key_bio, nullptr, nullptr, nullptr); |
| SSL_CTX_use_PrivateKey(server_ssl_ctx, pkey); |
| |
| SECTION("Full Handshake", "[quic]") |
| { |
| QUICPacketProtectionKeyInfo pp_key_info_client; |
| QUICPacketProtectionKeyInfo pp_key_info_server; |
| NetVCOptions netvc_options; |
| QUICHandshakeProtocol *client = new QUICTLS(pp_key_info_client, client_ssl_ctx, NET_VCONNECTION_OUT, netvc_options); |
| QUICHandshakeProtocol *server = new QUICTLS(pp_key_info_server, server_ssl_ctx, NET_VCONNECTION_IN, netvc_options); |
| QUICPacketPayloadProtector ppp_client(pp_key_info_client); |
| QUICPacketPayloadProtector ppp_server(pp_key_info_server); |
| |
| auto client_tp = std::make_shared<QUICTransportParametersInClientHello>(); |
| auto server_tp = std::make_shared<QUICTransportParametersInEncryptedExtensions>(); |
| client_tp->set(QUICTransportParameterId::MAX_IDLE_TIMEOUT, 10); |
| server_tp->set(QUICTransportParameterId::MAX_IDLE_TIMEOUT, 10); |
| client->set_local_transport_parameters(client_tp); |
| server->set_local_transport_parameters(server_tp); |
| |
| CHECK(client->initialize_key_materials({reinterpret_cast<const uint8_t *>("\x83\x94\xc8\xf0\x3e\x51\x57\x00"), 8})); |
| CHECK(server->initialize_key_materials({reinterpret_cast<const uint8_t *>("\x83\x94\xc8\xf0\x3e\x51\x57\x00"), 8})); |
| |
| // CH |
| QUICHandshakeMsgs msg0; |
| msg0.offsets[0] = 0; |
| msg0.offsets[1] = 0; |
| msg0.offsets[2] = 0; |
| msg0.offsets[3] = 0; |
| msg0.offsets[4] = 0; |
| |
| QUICHandshakeMsgs *msg1 = nullptr; |
| REQUIRE(client->handshake(&msg1, &msg0) == 1); |
| REQUIRE(msg1); |
| std::cout << "### Messages from client" << std::endl; |
| print_hex(msg1->buf, msg1->offsets[4]); |
| |
| // SH, EE, CERT, CV, FIN |
| QUICHandshakeMsgs *msg2 = nullptr; |
| REQUIRE(server->handshake(&msg2, msg1) == 1); |
| REQUIRE(msg2); |
| std::cout << "### Messages from server" << std::endl; |
| print_hex(msg2->buf, msg2->offsets[4]); |
| |
| // FIN |
| QUICHandshakeMsgs *msg3; |
| |
| // SH |
| QUICHandshakeMsgs msg2_1; |
| uint8_t msg2_1_buf[MAX_HANDSHAKE_MSG_LEN] = {0}; |
| msg2_1.buf = msg2_1_buf; |
| msg2_1.max_buf_len = MAX_HANDSHAKE_MSG_LEN; |
| |
| memcpy(msg2_1.buf, msg2->buf, msg2->offsets[1]); |
| msg2_1.offsets[0] = 0; |
| msg2_1.offsets[1] = msg2->offsets[1]; |
| msg2_1.offsets[2] = msg2->offsets[1]; |
| msg2_1.offsets[3] = msg2->offsets[1]; |
| msg2_1.offsets[4] = msg2->offsets[1]; |
| |
| // EE - FIN |
| QUICHandshakeMsgs msg2_2; |
| uint8_t msg2_2_buf[MAX_HANDSHAKE_MSG_LEN] = {0}; |
| msg2_2.buf = msg2_2_buf; |
| msg2_2.max_buf_len = MAX_HANDSHAKE_MSG_LEN; |
| |
| size_t len = msg2->offsets[3] - msg2->offsets[2]; |
| memcpy(msg2_2.buf, msg2->buf + msg2->offsets[1], len); |
| msg2_2.offsets[0] = 0; |
| msg2_2.offsets[1] = 0; |
| msg2_2.offsets[2] = 0; |
| msg2_2.offsets[3] = len; |
| msg2_2.offsets[4] = len; |
| |
| REQUIRE(client->handshake(&msg3, &msg2_1) == 1); |
| REQUIRE(client->handshake(&msg3, &msg2_2) == 1); |
| std::cout << "### Messages from client" << std::endl; |
| print_hex(msg3->buf, msg3->offsets[4]); |
| |
| // NS |
| QUICHandshakeMsgs *msg4 = nullptr; |
| REQUIRE(server->handshake(&msg4, msg3) == 1); |
| REQUIRE(msg4); |
| std::cout << "### Messages from server" << std::endl; |
| print_hex(msg4->buf, msg4->offsets[4]); |
| |
| QUICHandshakeMsgs *msg5 = nullptr; |
| REQUIRE(client->handshake(&msg5, msg4) == 1); |
| REQUIRE(msg5 == nullptr); |
| |
| // encrypt - decrypt |
| // client (encrypt) - server (decrypt) |
| std::cout << "### Original Text" << std::endl; |
| print_hex(original, sizeof(original)); |
| |
| Ptr<IOBufferBlock> original_ibb = make_ptr<IOBufferBlock>(new_IOBufferBlock()); |
| original_ibb->set_internal(const_cast<uint8_t *>(original), sizeof(original), BUFFER_SIZE_NOT_ALLOCATED); |
| Ptr<IOBufferBlock> header_ibb = make_ptr<IOBufferBlock>(new_IOBufferBlock()); |
| header_ibb->set_internal(const_cast<uint8_t *>(ad), sizeof(ad), BUFFER_SIZE_NOT_ALLOCATED); |
| Ptr<IOBufferBlock> cipher = ppp_client.protect(header_ibb, original_ibb, pkt_num, QUICKeyPhase::PHASE_0); |
| CHECK(cipher); |
| |
| std::cout << "### Encrypted Text" << std::endl; |
| print_hex(reinterpret_cast<uint8_t *>(cipher->buf()), cipher->size()); |
| |
| Ptr<IOBufferBlock> plain = ppp_server.unprotect(header_ibb, cipher, pkt_num, QUICKeyPhase::PHASE_0); |
| CHECK(plain); |
| |
| std::cout << "### Decrypted Text" << std::endl; |
| print_hex(reinterpret_cast<uint8_t *>(plain->buf()), plain->size()); |
| |
| CHECK(sizeof(original) == (plain->size())); |
| CHECK(memcmp(original, plain->buf(), plain->size()) == 0); |
| |
| // Teardown |
| delete client; |
| delete server; |
| } |
| |
| SECTION("Full Handshake with HRR", "[quic]") |
| { |
| // client key_share will be X25519 (default of OpenSSL) |
| #ifdef SSL_CTX_set1_groups_list |
| if (SSL_CTX_set1_groups_list(server_ssl_ctx, "P-521:P-384:P-256") != 1) { |
| #else |
| if (SSL_CTX_set1_curves_list(server_ssl_ctx, "P-521:P-384:P-256") != 1) { |
| #endif |
| REQUIRE(false); |
| } |
| |
| QUICPacketProtectionKeyInfo pp_key_info_client; |
| QUICPacketProtectionKeyInfo pp_key_info_server; |
| NetVCOptions netvc_options; |
| QUICHandshakeProtocol *client = new QUICTLS(pp_key_info_client, client_ssl_ctx, NET_VCONNECTION_OUT, netvc_options); |
| QUICHandshakeProtocol *server = new QUICTLS(pp_key_info_server, server_ssl_ctx, NET_VCONNECTION_IN, netvc_options); |
| QUICPacketPayloadProtector ppp_client(pp_key_info_client); |
| QUICPacketPayloadProtector ppp_server(pp_key_info_server); |
| |
| auto client_tp = std::make_shared<QUICTransportParametersInClientHello>(); |
| auto server_tp = std::make_shared<QUICTransportParametersInEncryptedExtensions>(); |
| client_tp->set(QUICTransportParameterId::MAX_IDLE_TIMEOUT, 10); |
| server_tp->set(QUICTransportParameterId::MAX_IDLE_TIMEOUT, 10); |
| client->set_local_transport_parameters(client_tp); |
| server->set_local_transport_parameters(server_tp); |
| |
| CHECK(client->initialize_key_materials({reinterpret_cast<const uint8_t *>("\x83\x94\xc8\xf0\x3e\x51\x57\x00"), 8})); |
| CHECK(server->initialize_key_materials({reinterpret_cast<const uint8_t *>("\x83\x94\xc8\xf0\x3e\x51\x57\x00"), 8})); |
| |
| // CH |
| QUICHandshakeMsgs msg0; |
| msg0.offsets[0] = 0; |
| msg0.offsets[1] = 0; |
| msg0.offsets[2] = 0; |
| msg0.offsets[3] = 0; |
| msg0.offsets[4] = 0; |
| |
| QUICHandshakeMsgs *msg1 = nullptr; |
| REQUIRE(client->handshake(&msg1, &msg0) == 1); |
| REQUIRE(msg1); |
| std::cout << "### Messages from client" << std::endl; |
| print_hex(msg1->buf, msg1->offsets[4]); |
| |
| // HRR |
| QUICHandshakeMsgs *msg2 = nullptr; |
| REQUIRE(server->handshake(&msg2, msg1) == 1); |
| REQUIRE(msg2); |
| std::cout << "### Messages from server" << std::endl; |
| print_hex(msg2->buf, msg2->offsets[4]); |
| |
| // CH |
| QUICHandshakeMsgs *msg3 = nullptr; |
| REQUIRE(client->handshake(&msg3, msg2) == 1); |
| REQUIRE(msg3); |
| std::cout << "### Messages from client" << std::endl; |
| print_hex(msg3->buf, msg3->offsets[4]); |
| |
| // SH, EE, CERT, CV, FIN |
| QUICHandshakeMsgs *msg4 = nullptr; |
| REQUIRE(server->handshake(&msg4, msg3) == 1); |
| REQUIRE(msg4); |
| std::cout << "### Messages from server" << std::endl; |
| print_hex(msg4->buf, msg4->offsets[4]); |
| |
| // FIN |
| QUICHandshakeMsgs *msg5 = nullptr; |
| |
| // SH |
| QUICHandshakeMsgs msg4_1; |
| uint8_t msg4_1_buf[MAX_HANDSHAKE_MSG_LEN] = {0}; |
| msg4_1.buf = msg4_1_buf; |
| msg4_1.max_buf_len = MAX_HANDSHAKE_MSG_LEN; |
| |
| memcpy(msg4_1.buf, msg4->buf, msg4->offsets[1]); |
| msg4_1.offsets[0] = 0; |
| msg4_1.offsets[1] = msg4->offsets[1]; |
| msg4_1.offsets[2] = msg4->offsets[1]; |
| msg4_1.offsets[3] = msg4->offsets[1]; |
| msg4_1.offsets[4] = msg4->offsets[1]; |
| |
| // EE - FIN |
| QUICHandshakeMsgs msg4_2; |
| uint8_t msg4_2_buf[MAX_HANDSHAKE_MSG_LEN] = {0}; |
| msg4_2.buf = msg4_2_buf; |
| msg4_2.max_buf_len = MAX_HANDSHAKE_MSG_LEN; |
| |
| size_t len = msg4->offsets[3] - msg4->offsets[2]; |
| memcpy(msg4_2.buf, msg4->buf + msg4->offsets[1], len); |
| msg4_2.offsets[0] = 0; |
| msg4_2.offsets[1] = 0; |
| msg4_2.offsets[2] = 0; |
| msg4_2.offsets[3] = len; |
| msg4_2.offsets[4] = len; |
| |
| REQUIRE(client->handshake(&msg5, &msg4_1) == 1); |
| REQUIRE(client->handshake(&msg5, &msg4_2) == 1); |
| REQUIRE(msg5); |
| std::cout << "### Messages from client" << std::endl; |
| print_hex(msg5->buf, msg5->offsets[4]); |
| |
| // NS |
| QUICHandshakeMsgs *msg6 = nullptr; |
| REQUIRE(server->handshake(&msg6, msg5) == 1); |
| REQUIRE(msg6); |
| std::cout << "### Messages from server" << std::endl; |
| print_hex(msg6->buf, msg6->offsets[4]); |
| |
| Ptr<IOBufferBlock> original_ibb = make_ptr<IOBufferBlock>(new_IOBufferBlock()); |
| original_ibb->set_internal(const_cast<uint8_t *>(original), sizeof(original), BUFFER_SIZE_NOT_ALLOCATED); |
| Ptr<IOBufferBlock> header_ibb = make_ptr<IOBufferBlock>(new_IOBufferBlock()); |
| header_ibb->set_internal(const_cast<uint8_t *>(ad), sizeof(ad), BUFFER_SIZE_NOT_ALLOCATED); |
| |
| // encrypt - decrypt |
| // client (encrypt) - server (decrypt) |
| std::cout << "### Original Text" << std::endl; |
| print_hex(original, sizeof(original)); |
| |
| Ptr<IOBufferBlock> cipher = ppp_client.protect(header_ibb, original_ibb, pkt_num, QUICKeyPhase::PHASE_0); |
| CHECK(cipher); |
| |
| std::cout << "### Encrypted Text" << std::endl; |
| print_hex(reinterpret_cast<uint8_t *>(cipher->buf()), cipher->size()); |
| |
| Ptr<IOBufferBlock> plain = ppp_server.unprotect(header_ibb, cipher, pkt_num, QUICKeyPhase::PHASE_0); |
| CHECK(plain); |
| |
| std::cout << "### Decrypted Text" << std::endl; |
| print_hex(reinterpret_cast<uint8_t *>(plain->buf()), plain->size()); |
| |
| CHECK(sizeof(original) == plain->size()); |
| CHECK(memcmp(original, plain->buf(), plain->size()) == 0); |
| |
| // Teardown |
| // Make it back to the default settings |
| #ifdef SSL_CTX_set1_groups_list |
| if (SSL_CTX_set1_groups_list(server_ssl_ctx, "X25519:P-521:P-384:P-256") != 1) { |
| #else |
| if (SSL_CTX_set1_curves_list(server_ssl_ctx, "X25519:P-521:P-384:P-256") != 1) { |
| #endif |
| REQUIRE(false); |
| } |
| |
| delete client; |
| delete server; |
| } |
| |
| SECTION("Alert", "[quic]") |
| { |
| QUICPacketProtectionKeyInfo pp_key_info_server; |
| NetVCOptions netvc_options; |
| QUICHandshakeProtocol *server = new QUICTLS(pp_key_info_server, server_ssl_ctx, NET_VCONNECTION_IN, netvc_options); |
| CHECK(server->initialize_key_materials({reinterpret_cast<const uint8_t *>("\x83\x94\xc8\xf0\x3e\x51\x57\x00"), 8})); |
| |
| // Malformed CH (finished) |
| uint8_t msg1_buf[] = {0x14, 0x00, 0x00, 0x30, 0x35, 0xb9, 0x82, 0x9d, 0xb9, 0x14, 0x70, 0x03, 0x60, |
| 0xd2, 0x5a, 0x03, 0x12, 0x12, 0x3d, 0x17, 0xc2, 0x13, 0x8c, 0xd7, 0x8b, 0x6e, |
| 0xc5, 0x4e, 0x50, 0x0a, 0x78, 0x6e, 0xa8, 0x54, 0x5f, 0x74, 0xfb, 0xf5, 0x6e, |
| 0x09, 0x90, 0x07, 0x58, 0x5a, 0x30, 0x5a, 0xe9, 0xcb, 0x1b, 0xa0, 0x69, 0x35}; |
| size_t msg1_len = sizeof(msg1_buf); |
| |
| QUICHandshakeMsgs msg1; |
| msg1.buf = msg1_buf; |
| msg1.max_buf_len = MAX_HANDSHAKE_MSG_LEN; |
| msg1.offsets[0] = 0; |
| msg1.offsets[1] = msg1_len; |
| msg1.offsets[2] = msg1_len; |
| msg1.offsets[3] = msg1_len; |
| msg1.offsets[4] = msg1_len; |
| |
| QUICHandshakeMsgs *msg2 = nullptr; |
| CHECK(server->handshake(&msg2, &msg1) != 1); |
| CHECK(server->has_crypto_error()); |
| CHECK((server->crypto_error() == 0x10a || server->crypto_error() == 0x150)); //< 0x100 + unexpected_message(10) |
| |
| // Teardown |
| delete server; |
| } |
| |
| SECTION("Full Handshake + Packet Number Protection", "[quic]") |
| { |
| QUICPacketProtectionKeyInfo pp_key_info_client; |
| QUICPacketProtectionKeyInfo pp_key_info_server; |
| NetVCOptions netvc_options; |
| QUICHandshakeProtocol *client = new QUICTLS(pp_key_info_client, client_ssl_ctx, NET_VCONNECTION_OUT, netvc_options); |
| QUICHandshakeProtocol *server = new QUICTLS(pp_key_info_server, server_ssl_ctx, NET_VCONNECTION_IN, netvc_options); |
| |
| auto client_tp = std::make_shared<QUICTransportParametersInClientHello>(); |
| auto server_tp = std::make_shared<QUICTransportParametersInEncryptedExtensions>(); |
| client_tp->set(QUICTransportParameterId::MAX_IDLE_TIMEOUT, 10); |
| server_tp->set(QUICTransportParameterId::MAX_IDLE_TIMEOUT, 10); |
| client->set_local_transport_parameters(client_tp); |
| server->set_local_transport_parameters(server_tp); |
| |
| CHECK(client->initialize_key_materials({reinterpret_cast<const uint8_t *>("\x83\x94\xc8\xf0\x3e\x51\x57\x00"), 8})); |
| CHECK(server->initialize_key_materials({reinterpret_cast<const uint8_t *>("\x83\x94\xc8\xf0\x3e\x51\x57\x00"), 8})); |
| |
| // # Start Handshake |
| |
| QUICHandshakeMsgs msg0; |
| msg0.offsets[0] = 0; |
| msg0.offsets[1] = 0; |
| msg0.offsets[2] = 0; |
| msg0.offsets[3] = 0; |
| msg0.offsets[4] = 0; |
| |
| // CH |
| QUICHandshakeMsgs *msg1 = nullptr; |
| REQUIRE(client->handshake(&msg1, &msg0) == 1); |
| REQUIRE(msg1); |
| |
| // SH, EE, CERT, CV, FIN |
| QUICHandshakeMsgs *msg2 = nullptr; |
| REQUIRE(server->handshake(&msg2, msg1) == 1); |
| REQUIRE(msg2); |
| |
| // FIN |
| QUICHandshakeMsgs *msg3 = nullptr; |
| |
| // SH |
| QUICHandshakeMsgs msg2_1; |
| uint8_t msg2_1_buf[MAX_HANDSHAKE_MSG_LEN] = {0}; |
| msg2_1.buf = msg2_1_buf; |
| msg2_1.max_buf_len = MAX_HANDSHAKE_MSG_LEN; |
| |
| memcpy(msg2_1.buf, msg2->buf, msg2->offsets[1]); |
| msg2_1.offsets[0] = 0; |
| msg2_1.offsets[1] = msg2->offsets[1]; |
| msg2_1.offsets[2] = msg2->offsets[1]; |
| msg2_1.offsets[3] = msg2->offsets[1]; |
| msg2_1.offsets[4] = msg2->offsets[1]; |
| |
| // EE - FIN |
| QUICHandshakeMsgs msg2_2; |
| uint8_t msg2_2_buf[MAX_HANDSHAKE_MSG_LEN] = {0}; |
| msg2_2.buf = msg2_2_buf; |
| msg2_2.max_buf_len = MAX_HANDSHAKE_MSG_LEN; |
| |
| size_t len = msg2->offsets[3] - msg2->offsets[2]; |
| memcpy(msg2_2.buf, msg2->buf + msg2->offsets[1], len); |
| msg2_2.offsets[0] = 0; |
| msg2_2.offsets[1] = 0; |
| msg2_2.offsets[2] = 0; |
| msg2_2.offsets[3] = len; |
| msg2_2.offsets[4] = len; |
| |
| REQUIRE(client->handshake(&msg3, &msg2_1) == 1); |
| REQUIRE(client->handshake(&msg3, &msg2_2) == 1); |
| |
| // NS |
| QUICHandshakeMsgs *msg4 = nullptr; |
| REQUIRE(server->handshake(&msg4, msg3) == 1); |
| REQUIRE(msg4); |
| |
| QUICHandshakeMsgs *msg5 = nullptr; |
| REQUIRE(client->handshake(&msg5, msg4) == 1); |
| REQUIRE(msg5 == nullptr); |
| |
| // # End Handshake |
| |
| // Teardown |
| delete client; |
| delete server; |
| } |
| |
| BIO_free(crt_bio); |
| BIO_free(key_bio); |
| |
| X509_free(x509); |
| EVP_PKEY_free(pkey); |
| |
| SSL_CTX_free(server_ssl_ctx); |
| SSL_CTX_free(client_ssl_ctx); |
| } |