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);