You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by ma...@apache.org on 2018/09/07 03:29:47 UTC
[trafficserver] 02/04: Handle TLS Alerts on msg_cb
This is an automated email from the ASF dual-hosted git repository.
masaori pushed a commit to branch quic-latest
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
commit e7c493ae72eef75958409ccade0b1b8313ace494
Author: Masaori Koshiba <ma...@apache.org>
AuthorDate: Tue Sep 4 16:20:30 2018 +0900
Handle TLS Alerts on msg_cb
---
iocore/net/quic/QUICHandshakeProtocol.h | 7 +-
iocore/net/quic/QUICTLS.cc | 6 +
iocore/net/quic/QUICTLS.h | 1 +
iocore/net/quic/QUICTLS_openssl.cc | 31 +--
iocore/net/quic/test/test_QUICHandshakeProtocol.cc | 221 ++++++++++++---------
5 files changed, 158 insertions(+), 108 deletions(-)
diff --git a/iocore/net/quic/QUICHandshakeProtocol.h b/iocore/net/quic/QUICHandshakeProtocol.h
index abc4410..f489e30 100644
--- a/iocore/net/quic/QUICHandshakeProtocol.h
+++ b/iocore/net/quic/QUICHandshakeProtocol.h
@@ -59,9 +59,10 @@ private:
};
struct QUICHandshakeMsgs {
- uint8_t *buf = nullptr; //< pointer to the buffer
- size_t max_buf_len = 0; //< size of buffer
- size_t offsets[5] = {0}; //< offset to the each encryption level - {initial, zero_rtt, handshake, one_rtt, total length}
+ uint8_t *buf = nullptr; //< pointer to the buffer
+ size_t max_buf_len = 0; //< size of buffer
+ size_t offsets[5] = {0}; //< offset to the each encryption level - {initial, zero_rtt, handshake, one_rtt, total length}
+ uint16_t error_code = 0; //< CRYPTO_ERROR - TLS Alert Desciption + 0x100
};
class QUICHandshakeProtocol
diff --git a/iocore/net/quic/QUICTLS.cc b/iocore/net/quic/QUICTLS.cc
index bfbff38..23dbfab 100644
--- a/iocore/net/quic/QUICTLS.cc
+++ b/iocore/net/quic/QUICTLS.cc
@@ -45,6 +45,12 @@ QUICTLS::~QUICTLS()
delete this->_server_pp;
}
+uint16_t
+QUICTLS::convert_to_quic_trans_error_code(uint8_t alert)
+{
+ return 0x100 | alert;
+}
+
bool
QUICTLS::is_handshake_finished() const
{
diff --git a/iocore/net/quic/QUICTLS.h b/iocore/net/quic/QUICTLS.h
index 7e040ac..d7f2ec1 100644
--- a/iocore/net/quic/QUICTLS.h
+++ b/iocore/net/quic/QUICTLS.h
@@ -49,6 +49,7 @@ public:
};
static QUICEncryptionLevel get_encryption_level(int msg_type);
+ static uint16_t convert_to_quic_trans_error_code(uint8_t alert);
// FIXME Should not exist
SSL *ssl_handle();
diff --git a/iocore/net/quic/QUICTLS_openssl.cc b/iocore/net/quic/QUICTLS_openssl.cc
index 6f3d25f..bdeda68 100644
--- a/iocore/net/quic/QUICTLS_openssl.cc
+++ b/iocore/net/quic/QUICTLS_openssl.cc
@@ -39,7 +39,7 @@ content_type_str(int type)
case SSL3_RT_CHANGE_CIPHER_SPEC:
return "SSL3_RT_CHANGE_CIPHER_SPEC";
case SSL3_RT_ALERT:
- return "SSL3_RT_ALERT 21";
+ return "SSL3_RT_ALERT";
case SSL3_RT_HANDSHAKE:
return "SSL3_RT_HANDSHAKE";
case SSL3_RT_APPLICATION_DATA:
@@ -102,25 +102,30 @@ msg_cb(int write_p, int version, int content_type, const void *buf, size_t len,
return;
}
- const uint8_t *tmp = reinterpret_cast<const uint8_t *>(buf);
- int msg_type = tmp[0];
-
- QUICEncryptionLevel level = QUICTLS::get_encryption_level(msg_type);
- int index = static_cast<int>(level);
- int next_index = index + 1;
-
QUICHandshakeMsgs *msg = reinterpret_cast<QUICHandshakeMsgs *>(arg);
if (msg == nullptr) {
return;
}
- size_t offset = msg->offsets[next_index];
- size_t next_level_offset = offset + len;
+ const uint8_t *msg_buf = reinterpret_cast<const uint8_t *>(buf);
+
+ if (content_type == SSL3_RT_HANDSHAKE) {
+ int msg_type = msg_buf[0];
- memcpy(msg->buf + offset, buf, len);
+ QUICEncryptionLevel level = QUICTLS::get_encryption_level(msg_type);
+ int index = static_cast<int>(level);
+ int next_index = index + 1;
- for (int i = next_index; i < 5; ++i) {
- msg->offsets[i] = next_level_offset;
+ size_t offset = msg->offsets[next_index];
+ size_t next_level_offset = offset + len;
+
+ memcpy(msg->buf + offset, buf, len);
+
+ for (int i = next_index; i < 5; ++i) {
+ msg->offsets[i] = next_level_offset;
+ }
+ } else if (content_type == SSL3_RT_ALERT && msg_buf[0] == SSL3_AL_FATAL && len == 2) {
+ msg->error_code = QUICTLS::convert_to_quic_trans_error_code(msg_buf[1]);
}
return;
diff --git a/iocore/net/quic/test/test_QUICHandshakeProtocol.cc b/iocore/net/quic/test/test_QUICHandshakeProtocol.cc
index 818cf8a..cf81b88 100644
--- a/iocore/net/quic/test/test_QUICHandshakeProtocol.cc
+++ b/iocore/net/quic/test/test_QUICHandshakeProtocol.cc
@@ -154,7 +154,7 @@ static const uint8_t ad[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
// delete server;
// }
-TEST_CASE("QUICHandshakeProtocol Full Handshake", "[quic]")
+TEST_CASE("QUICHandshakeProtocol")
{
// Client
SSL_CTX *client_ssl_ctx = SSL_CTX_new(TLS_method());
@@ -164,7 +164,6 @@ TEST_CASE("QUICHandshakeProtocol Full Handshake", "[quic]")
#ifdef SSL_MODE_QUIC_HACK
SSL_CTX_set_mode(client_ssl_ctx, SSL_MODE_QUIC_HACK);
#endif
- QUICHandshakeProtocol *client = new QUICTLS(client_ssl_ctx, NET_VCONNECTION_OUT);
// Server
SSL_CTX *server_ssl_ctx = SSL_CTX_new(TLS_method());
@@ -180,116 +179,154 @@ TEST_CASE("QUICHandshakeProtocol Full Handshake", "[quic]")
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);
- QUICHandshakeProtocol *server = new QUICTLS(server_ssl_ctx, NET_VCONNECTION_IN);
- BIO_free(crt_bio);
- BIO_free(key_bio);
+ SECTION("Full Handshake", "[quic]")
+ {
+ QUICHandshakeProtocol *client = new QUICTLS(client_ssl_ctx, NET_VCONNECTION_OUT);
+ QUICHandshakeProtocol *server = new QUICTLS(server_ssl_ctx, NET_VCONNECTION_IN);
- X509_free(x509);
- EVP_PKEY_free(pkey);
+ 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}));
- 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 msg1;
+ uint8_t msg1_buf[MAX_HANDSHAKE_MSG_LEN] = {0};
+ msg1.buf = msg1_buf;
+ msg1.max_buf_len = MAX_HANDSHAKE_MSG_LEN;
- // CH
- QUICHandshakeMsgs msg1;
- uint8_t msg1_buf[MAX_HANDSHAKE_MSG_LEN] = {0};
- msg1.buf = msg1_buf;
- msg1.max_buf_len = MAX_HANDSHAKE_MSG_LEN;
+ REQUIRE(client->handshake(&msg1, nullptr) == 1);
+ std::cout << "### Messages from client" << std::endl;
+ print_hex(msg1.buf, msg1.offsets[4]);
- REQUIRE(client->handshake(&msg1, nullptr) == 1);
- std::cout << "### Messages from client" << std::endl;
- print_hex(msg1.buf, msg1.offsets[4]);
+ // SH, EE, CERT, CV, FIN
+ QUICHandshakeMsgs msg2;
+ uint8_t msg2_buf[MAX_HANDSHAKE_MSG_LEN] = {0};
+ msg2.buf = msg2_buf;
+ msg2.max_buf_len = MAX_HANDSHAKE_MSG_LEN;
- // SH, EE, CERT, CV, FIN
- QUICHandshakeMsgs msg2;
- uint8_t msg2_buf[MAX_HANDSHAKE_MSG_LEN] = {0};
- msg2.buf = msg2_buf;
- msg2.max_buf_len = MAX_HANDSHAKE_MSG_LEN;
+ REQUIRE(server->handshake(&msg2, &msg1) == 1);
+ std::cout << "### Messages from server" << std::endl;
+ print_hex(msg2.buf, msg2.offsets[4]);
- REQUIRE(server->handshake(&msg2, &msg1) == 1);
- std::cout << "### Messages from server" << std::endl;
- print_hex(msg2.buf, msg2.offsets[4]);
-
- // FIN
- QUICHandshakeMsgs msg3;
- uint8_t msg3_buf[MAX_HANDSHAKE_MSG_LEN] = {0};
- msg3.buf = msg3_buf;
- msg3.max_buf_len = MAX_HANDSHAKE_MSG_LEN;
+ // FIN
+ QUICHandshakeMsgs msg3;
+ uint8_t msg3_buf[MAX_HANDSHAKE_MSG_LEN] = {0};
+ msg3.buf = msg3_buf;
+ msg3.max_buf_len = MAX_HANDSHAKE_MSG_LEN;
#ifdef SSL_MODE_QUIC_HACK
- // -- Hacks for OpenSSL with SSL_MODE_QUIC_HACK --
- // 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);
+ // -- Hacks for OpenSSL with SSL_MODE_QUIC_HACK --
+ // 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);
#else
- REQUIRE(client->handshake(&msg3, &msg2) == 1);
+ REQUIRE(client->handshake(&msg3, &msg2) == 1);
#endif
- std::cout << "### Messages from client" << std::endl;
- print_hex(msg3.buf, msg3.offsets[4]);
+ std::cout << "### Messages from client" << std::endl;
+ print_hex(msg3.buf, msg3.offsets[4]);
+
+ // NS
+ QUICHandshakeMsgs msg4;
+ uint8_t msg4_buf[MAX_HANDSHAKE_MSG_LEN] = {0};
+ msg4.buf = msg4_buf;
+ msg4.max_buf_len = MAX_HANDSHAKE_MSG_LEN;
+
+ REQUIRE(server->handshake(&msg4, &msg3) == 1);
+ std::cout << "### Messages from server" << std::endl;
+ print_hex(msg4.buf, msg4.offsets[4]);
- // NS
- QUICHandshakeMsgs msg4;
- uint8_t msg4_buf[MAX_HANDSHAKE_MSG_LEN] = {0};
- msg4.buf = msg4_buf;
- msg4.max_buf_len = MAX_HANDSHAKE_MSG_LEN;
+ // encrypt - decrypt
+ // client (encrypt) - server (decrypt)
+ std::cout << "### Original Text" << std::endl;
+ print_hex(original, sizeof(original));
- REQUIRE(server->handshake(&msg4, &msg3) == 1);
- std::cout << "### Messages from server" << std::endl;
- print_hex(msg4.buf, msg4.offsets[4]);
+ uint8_t cipher[128] = {0}; // >= original len + EVP_AEAD_max_overhead
+ size_t cipher_len = 0;
+ CHECK(client->encrypt(cipher, cipher_len, sizeof(cipher), original, sizeof(original), pkt_num, ad, sizeof(ad),
+ QUICKeyPhase::PHASE_0));
- // encrypt - decrypt
- // client (encrypt) - server (decrypt)
- std::cout << "### Original Text" << std::endl;
- print_hex(original, sizeof(original));
+ std::cout << "### Encrypted Text" << std::endl;
+ print_hex(cipher, cipher_len);
- uint8_t cipher[128] = {0}; // >= original len + EVP_AEAD_max_overhead
- size_t cipher_len = 0;
- CHECK(client->encrypt(cipher, cipher_len, sizeof(cipher), original, sizeof(original), pkt_num, ad, sizeof(ad),
- QUICKeyPhase::PHASE_0));
+ uint8_t plain[128] = {0};
+ size_t plain_len = 0;
+ CHECK(server->decrypt(plain, plain_len, sizeof(plain), cipher, cipher_len, pkt_num, ad, sizeof(ad), QUICKeyPhase::PHASE_0));
- std::cout << "### Encrypted Text" << std::endl;
- print_hex(cipher, cipher_len);
+ std::cout << "### Decrypted Text" << std::endl;
+ print_hex(plain, plain_len);
- uint8_t plain[128] = {0};
- size_t plain_len = 0;
- CHECK(server->decrypt(plain, plain_len, sizeof(plain), cipher, cipher_len, pkt_num, ad, sizeof(ad), QUICKeyPhase::PHASE_0));
+ CHECK(sizeof(original) == (plain_len));
+ CHECK(memcmp(original, plain, plain_len) == 0);
- std::cout << "### Decrypted Text" << std::endl;
- print_hex(plain, plain_len);
+ // Teardown
+ delete client;
+ delete server;
+ }
- CHECK(sizeof(original) == (plain_len));
- CHECK(memcmp(original, plain, plain_len) == 0);
+ SECTION("Alert", "[quic]")
+ {
+ QUICHandshakeProtocol *server = new QUICTLS(server_ssl_ctx, NET_VCONNECTION_IN);
+ 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;
+ uint8_t msg2_buf[MAX_HANDSHAKE_MSG_LEN] = {0};
+ msg2.buf = msg2_buf;
+ msg2.max_buf_len = MAX_HANDSHAKE_MSG_LEN;
+
+ CHECK(server->handshake(&msg2, &msg1) != 1);
+ CHECK(msg2.error_code == 0x10a); //< 0x100 + unexpected_message(10)
+
+ // Teardown
+ delete server;
+ }
- // 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);