diff --git a/configure.ac b/configure.ac index ca784a6bc4f..20feca47ca7 100644 --- a/configure.ac +++ b/configure.ac @@ -1272,20 +1272,11 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], AC_CHECK_FUNCS(SSL_set_quic_early_data_enabled) LIBS=$_quic_saved_LIBS ], - [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], - [[ - #ifdef SSL_MODE_QUIC_HACK - #else - # error no hack for quic - #endif - ]]) - ], - [AC_MSG_RESULT([yes]); enable_quic=yes; enable_quic_old_api=yes], - [AC_MSG_RESULT([no])]) + [ + AC_MSG_RESULT([no]) ]) AM_CONDITIONAL([ENABLE_QUIC], [test "x$enable_quic" = "xyes"]) -AM_CONDITIONAL([ENABLE_QUIC_OLD_API], [test "x$enable_quic_old_api" = "xyes"]) TS_ARG_ENABLE_VAR([use], [quic]) AC_SUBST(use_quic) diff --git a/iocore/net/quic/Makefile.am b/iocore/net/quic/Makefile.am index 9276e81dcd5..8a60a23b465 100644 --- a/iocore/net/quic/Makefile.am +++ b/iocore/net/quic/Makefile.am @@ -40,18 +40,11 @@ QUICPPProtector_impl = QUICPacketPayloadProtector_boringssl.cc QUICTLS_impl = QUICTLS_boringssl.cc QUICKeyGenerator_impl = QUICKeyGenerator_boringssl.cc else -if ENABLE_QUIC_OLD_API -QUICPHProtector_impl = QUICPacketHeaderProtector_legacy.cc -QUICPPProtector_impl = QUICPacketPayloadProtector_legacy.cc -QUICTLS_impl = QUICTLS_legacy.cc -QUICKeyGenerator_impl = QUICKeyGenerator_legacy.cc -else QUICPHProtector_impl = QUICPacketHeaderProtector_openssl.cc QUICPPProtector_impl = QUICPacketPayloadProtector_openssl.cc QUICTLS_impl = QUICTLS_openssl.cc QUICKeyGenerator_impl = QUICKeyGenerator_openssl.cc endif -endif QLog_impl = qlog/QLogEvent.cc qlog/QLogFrame.cc qlog/QLog.cc diff --git a/iocore/net/quic/QUICKeyGenerator_legacy.cc b/iocore/net/quic/QUICKeyGenerator_legacy.cc deleted file mode 100644 index 03b46e1cf1e..00000000000 --- a/iocore/net/quic/QUICKeyGenerator_legacy.cc +++ /dev/null @@ -1,63 +0,0 @@ -/** @file - * - * A key generator for QUIC connection (OpenSSL specific parts) - * - * @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 "tscore/ink_assert.h" -#include "QUICKeyGenerator.h" - -#include - -size_t -QUICKeyGenerator::_get_key_len(const EVP_CIPHER *cipher) const -{ - return EVP_CIPHER_key_length(cipher); -} - -size_t -QUICKeyGenerator::_get_iv_len(const EVP_CIPHER *cipher) const -{ - return EVP_CIPHER_iv_length(cipher); -} - -const EVP_CIPHER * -QUICKeyGenerator::_get_cipher_for_initial() const -{ - return EVP_aes_128_gcm(); -} - -const EVP_CIPHER * -QUICKeyGenerator::_get_cipher_for_protected_packet(const SSL *ssl) const -{ - switch (SSL_CIPHER_get_id(SSL_get_current_cipher(ssl))) { - case TLS1_3_CK_AES_128_GCM_SHA256: - return EVP_aes_128_gcm(); - case TLS1_3_CK_AES_256_GCM_SHA384: - return EVP_aes_256_gcm(); - case TLS1_3_CK_CHACHA20_POLY1305_SHA256: - return EVP_chacha20_poly1305(); - case TLS1_3_CK_AES_128_CCM_SHA256: - case TLS1_3_CK_AES_128_CCM_8_SHA256: - return EVP_aes_128_ccm(); - default: - ink_assert(false); - return nullptr; - } -} diff --git a/iocore/net/quic/QUICPacketHeaderProtector_legacy.cc b/iocore/net/quic/QUICPacketHeaderProtector_legacy.cc deleted file mode 100644 index 43bbba8e901..00000000000 --- a/iocore/net/quic/QUICPacketHeaderProtector_legacy.cc +++ /dev/null @@ -1,53 +0,0 @@ -/** @file - * - * QUIC Packet Header Protector (OpenSSL specific code) - * - * @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 "QUICPacketHeaderProtector.h" - -bool -QUICPacketHeaderProtector::_generate_mask(uint8_t *mask, const uint8_t *sample, const uint8_t *key, const EVP_CIPHER *cipher) const -{ - static constexpr unsigned char FIVE_ZEROS[] = {0x00, 0x00, 0x00, 0x00, 0x00}; - EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); - - if (!ctx || !EVP_EncryptInit_ex(ctx, cipher, nullptr, key, sample)) { - return false; - } - - int len = 0; - if (cipher == EVP_chacha20()) { - if (!EVP_EncryptUpdate(ctx, mask, &len, FIVE_ZEROS, sizeof(FIVE_ZEROS))) { - return false; - } - } else { - if (!EVP_EncryptUpdate(ctx, mask, &len, sample, 16)) { - return false; - } - } - if (!EVP_EncryptFinal_ex(ctx, mask + len, &len)) { - return false; - } - - EVP_CIPHER_CTX_free(ctx); - - return true; -} diff --git a/iocore/net/quic/QUICPacketPayloadProtector_legacy.cc b/iocore/net/quic/QUICPacketPayloadProtector_legacy.cc deleted file mode 100644 index 5fc9e2e6e11..00000000000 --- a/iocore/net/quic/QUICPacketPayloadProtector_legacy.cc +++ /dev/null @@ -1,136 +0,0 @@ -/** @file - * - * QUIC Packet Payload Protector (OpenSSL specific code) - * - * @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 "QUICPacketProtectionKeyInfo.h" -#include "QUICPacketPayloadProtector.h" -#include "tscore/Diags.h" - -static constexpr char tag[] = "quic_ppp"; - -bool -QUICPacketPayloadProtector::_protect(uint8_t *cipher, size_t &cipher_len, size_t max_cipher_len, const Ptr plain, - uint64_t pkt_num, const uint8_t *ad, size_t ad_len, const uint8_t *key, const uint8_t *iv, - size_t iv_len, const EVP_CIPHER *aead, size_t tag_len) const -{ - EVP_CIPHER_CTX *aead_ctx; - int len; - uint8_t nonce[EVP_MAX_IV_LENGTH] = {0}; - size_t nonce_len = 0; - - this->_gen_nonce(nonce, nonce_len, pkt_num, iv, iv_len); - - if (!(aead_ctx = EVP_CIPHER_CTX_new())) { - return false; - } - if (!EVP_EncryptInit_ex(aead_ctx, aead, nullptr, nullptr, nullptr)) { - return false; - } - if (!EVP_CIPHER_CTX_ctrl(aead_ctx, EVP_CTRL_AEAD_SET_IVLEN, nonce_len, nullptr)) { - return false; - } - if (!EVP_EncryptInit_ex(aead_ctx, nullptr, nullptr, key, nonce)) { - return false; - } - if (!EVP_EncryptUpdate(aead_ctx, nullptr, &len, ad, ad_len)) { - return false; - } - - cipher_len = 0; - for (Ptr b = plain; b; b = b->next) { - if (!EVP_EncryptUpdate(aead_ctx, cipher + cipher_len, &len, reinterpret_cast(b->start()), b->size())) { - return false; - } - cipher_len += len; - } - - if (!EVP_EncryptFinal_ex(aead_ctx, cipher + cipher_len, &len)) { - return false; - } - cipher_len += len; - - if (max_cipher_len < cipher_len + tag_len) { - return false; - } - if (!EVP_CIPHER_CTX_ctrl(aead_ctx, EVP_CTRL_AEAD_GET_TAG, tag_len, cipher + cipher_len)) { - return false; - } - cipher_len += tag_len; - - EVP_CIPHER_CTX_free(aead_ctx); - - return true; -} - -bool -QUICPacketPayloadProtector::_unprotect(uint8_t *plain, size_t &plain_len, size_t max_plain_len, const uint8_t *cipher, - size_t cipher_len, uint64_t pkt_num, const uint8_t *ad, size_t ad_len, const uint8_t *key, - const uint8_t *iv, size_t iv_len, const EVP_CIPHER *aead, size_t tag_len) const -{ - EVP_CIPHER_CTX *aead_ctx; - int len; - uint8_t nonce[EVP_MAX_IV_LENGTH] = {0}; - size_t nonce_len = 0; - - this->_gen_nonce(nonce, nonce_len, pkt_num, iv, iv_len); - - if (!(aead_ctx = EVP_CIPHER_CTX_new())) { - return false; - } - if (!EVP_DecryptInit_ex(aead_ctx, aead, nullptr, nullptr, nullptr)) { - return false; - } - if (!EVP_CIPHER_CTX_ctrl(aead_ctx, EVP_CTRL_AEAD_SET_IVLEN, nonce_len, nullptr)) { - return false; - } - if (!EVP_DecryptInit_ex(aead_ctx, nullptr, nullptr, key, nonce)) { - return false; - } - if (!EVP_DecryptUpdate(aead_ctx, nullptr, &len, ad, ad_len)) { - return false; - } - - if (cipher_len < tag_len) { - return false; - } - cipher_len -= tag_len; - if (!EVP_DecryptUpdate(aead_ctx, plain, &len, cipher, cipher_len)) { - return false; - } - plain_len = len; - - if (!EVP_CIPHER_CTX_ctrl(aead_ctx, EVP_CTRL_AEAD_SET_TAG, tag_len, const_cast(cipher + cipher_len))) { - return false; - } - - int ret = EVP_DecryptFinal_ex(aead_ctx, plain + len, &len); - - EVP_CIPHER_CTX_free(aead_ctx); - - if (ret > 0) { - plain_len += len; - return true; - } else { - Debug(tag, "Failed to decrypt -- the first 4 bytes decrypted are %0x %0x %0x %0x", plain[0], plain[1], plain[2], plain[3]); - return false; - } -} diff --git a/iocore/net/quic/QUICTLS_legacy.cc b/iocore/net/quic/QUICTLS_legacy.cc deleted file mode 100644 index d9cc410b515..00000000000 --- a/iocore/net/quic/QUICTLS_legacy.cc +++ /dev/null @@ -1,445 +0,0 @@ -/** @file - * - * QUIC Crypto (TLS to Secure QUIC) using OpenSSL - * - * @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 "QUICTLS.h" - -#include -#include -#include -#include -#include - -#include "QUICConfig.h" -#include "QUICGlobals.h" -#include "QUICDebugNames.h" -#include "QUICPacketProtectionKeyInfo.h" - -static constexpr char tag[] = "quic_tls"; - -using namespace std::literals; - -static constexpr std::string_view QUIC_CLIENT_EARLY_TRAFFIC_SECRET_LABEL("QUIC_CLIENT_EARLY_TRAFFIC_SECRET"sv); -static constexpr std::string_view QUIC_CLIENT_HANDSHAKE_TRAFFIC_SECRET_LABEL("QUIC_CLIENT_HANDSHAKE_TRAFFIC_SECRET"sv); -static constexpr std::string_view QUIC_SERVER_HANDSHAKE_TRAFFIC_SECRET_LABEL("QUIC_SERVER_HANDSHAKE_TRAFFIC_SECRET"sv); -// TODO: support key update -static constexpr std::string_view QUIC_CLIENT_TRAFFIC_SECRET_LABEL("QUIC_CLIENT_TRAFFIC_SECRET_0"sv); -static constexpr std::string_view QUIC_SERVER_TRAFFIC_SECRET_LABEL("QUIC_SERVER_TRAFFIC_SECRET_0"sv); - -void -QUICTLS::_msg_cb(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg) -{ - // Debug for reading - if (write_p == 0) { - QUICTLS::_print_hs_message(content_type, buf, len); - return; - } - - if (!write_p || (content_type != SSL3_RT_HANDSHAKE && content_type != SSL3_RT_ALERT)) { - return; - } - - QUICTLS *qtls = static_cast(SSL_get_ex_data(ssl, QUIC::ssl_quic_tls_index)); - const uint8_t *data = reinterpret_cast(buf); - if (content_type == SSL3_RT_HANDSHAKE) { - if (version != TLS1_3_VERSION) { - return; - } - - QUICEncryptionLevel level = QUICTLS::get_encryption_level(data[0]); - qtls->on_handshake_data_generated(level, data, len); - qtls->set_ready_for_write(); - } else if (content_type == SSL3_RT_ALERT && data[0] == SSL3_AL_FATAL && len == 2) { - qtls->on_tls_alert(data[1]); - } - - return; -} - -/** - This is very inspired from writing keylog format of ngtcp2's examples - https://github.com/ngtcp2/ngtcp2/blob/894ed23c970d61eede74f69d9178090af63fdf70/examples/keylog.cc - */ -static void -log_secret(SSL *ssl, int name, const unsigned char *secret, size_t secretlen) -{ - if (auto keylog_cb = SSL_CTX_get_keylog_callback(SSL_get_SSL_CTX(ssl))) { - unsigned char crandom[32]; - if (SSL_get_client_random(ssl, crandom, sizeof(crandom)) != sizeof(crandom)) { - return; - } - uint8_t line[256] = {0}; - size_t len = 0; - switch (name) { - case SSL_KEY_CLIENT_EARLY_TRAFFIC: - memcpy(line, QUIC_CLIENT_EARLY_TRAFFIC_SECRET_LABEL.data(), QUIC_CLIENT_EARLY_TRAFFIC_SECRET_LABEL.size()); - len += QUIC_CLIENT_EARLY_TRAFFIC_SECRET_LABEL.size(); - break; - case SSL_KEY_CLIENT_HANDSHAKE_TRAFFIC: - memcpy(line, QUIC_CLIENT_HANDSHAKE_TRAFFIC_SECRET_LABEL.data(), QUIC_CLIENT_HANDSHAKE_TRAFFIC_SECRET_LABEL.size()); - len += QUIC_CLIENT_HANDSHAKE_TRAFFIC_SECRET_LABEL.size(); - break; - case SSL_KEY_SERVER_HANDSHAKE_TRAFFIC: - memcpy(line, QUIC_SERVER_HANDSHAKE_TRAFFIC_SECRET_LABEL.data(), QUIC_SERVER_HANDSHAKE_TRAFFIC_SECRET_LABEL.size()); - len += QUIC_SERVER_HANDSHAKE_TRAFFIC_SECRET_LABEL.size(); - break; - case SSL_KEY_CLIENT_APPLICATION_TRAFFIC: - memcpy(line, QUIC_CLIENT_TRAFFIC_SECRET_LABEL.data(), QUIC_CLIENT_TRAFFIC_SECRET_LABEL.size()); - len += QUIC_CLIENT_TRAFFIC_SECRET_LABEL.size(); - break; - case SSL_KEY_SERVER_APPLICATION_TRAFFIC: - memcpy(line, QUIC_SERVER_TRAFFIC_SECRET_LABEL.data(), QUIC_SERVER_TRAFFIC_SECRET_LABEL.size()); - len += QUIC_SERVER_TRAFFIC_SECRET_LABEL.size(); - break; - - default: - return; - } - - line[len] = ' '; - ++len; - QUICDebug::to_hex(line + len, crandom, sizeof(crandom)); - len += sizeof(crandom) * 2; - line[len] = ' '; - ++len; - QUICDebug::to_hex(line + len, secret, secretlen); - - keylog_cb(ssl, reinterpret_cast(line)); - } -} - -static int -key_cb(SSL *ssl, int name, const unsigned char *secret, size_t secret_len, void *arg) -{ - if (arg == nullptr) { - return 0; - } - - QUICTLS *qtls = reinterpret_cast(arg); - - qtls->update_negotiated_cipher(); - - QUICEncryptionLevel level; - switch (name) { - case SSL_KEY_CLIENT_EARLY_TRAFFIC: - Debug("vv_quic_crypto", "%s", QUIC_CLIENT_EARLY_TRAFFIC_SECRET_LABEL.data()); - level = QUICEncryptionLevel::ZERO_RTT; - if (SSL_is_server(ssl)) { - qtls->update_key_materials_for_read(level, secret, secret_len); - } else { - qtls->update_key_materials_for_write(level, secret, secret_len); - } - break; - case SSL_KEY_CLIENT_HANDSHAKE_TRAFFIC: - Debug("vv_quic_crypto", "%s", QUIC_CLIENT_HANDSHAKE_TRAFFIC_SECRET_LABEL.data()); - level = QUICEncryptionLevel::HANDSHAKE; - if (SSL_is_server(ssl)) { - qtls->update_key_materials_for_read(level, secret, secret_len); - } else { - qtls->update_key_materials_for_write(level, secret, secret_len); - } - break; - case SSL_KEY_SERVER_HANDSHAKE_TRAFFIC: - Debug("vv_quic_crypto", "%s", QUIC_SERVER_HANDSHAKE_TRAFFIC_SECRET_LABEL.data()); - level = QUICEncryptionLevel::HANDSHAKE; - if (SSL_is_server(ssl)) { - qtls->update_key_materials_for_write(level, secret, secret_len); - } else { - qtls->update_key_materials_for_read(level, secret, secret_len); - } - break; - case SSL_KEY_CLIENT_APPLICATION_TRAFFIC: - Debug("vv_quic_crypto", "%s", QUIC_CLIENT_TRAFFIC_SECRET_LABEL.data()); - level = QUICEncryptionLevel::ONE_RTT; - if (SSL_is_server(ssl)) { - qtls->update_key_materials_for_read(level, secret, secret_len); - } else { - qtls->update_key_materials_for_write(level, secret, secret_len); - } - break; - case SSL_KEY_SERVER_APPLICATION_TRAFFIC: - Debug("vv_quic_crypto", "%s", QUIC_SERVER_TRAFFIC_SECRET_LABEL.data()); - level = QUICEncryptionLevel::ONE_RTT; - if (SSL_is_server(ssl)) { - qtls->update_key_materials_for_write(level, secret, secret_len); - } else { - qtls->update_key_materials_for_read(level, secret, secret_len); - } - break; - default: - level = QUICEncryptionLevel::NONE; - break; - } - - log_secret(ssl, name, secret, secret_len); - - return 1; -} - -QUICTLS::QUICTLS(QUICPacketProtectionKeyInfo &pp_key_info, SSL_CTX *ssl_ctx, NetVConnectionContext_t nvc_ctx, - const NetVCOptions &netvc_options, const char *session_file, const char *keylog_file) - : QUICHandshakeProtocol(pp_key_info), - _session_file(session_file), - _keylog_file(keylog_file), - _ssl(SSL_new(ssl_ctx)), - _netvc_context(nvc_ctx) -{ - ink_assert(this->_netvc_context != NET_VCONNECTION_UNSET); - - if (this->_netvc_context == NET_VCONNECTION_OUT) { - SSL_set_connect_state(this->_ssl); - - SSL_set_alpn_protos(this->_ssl, reinterpret_cast(netvc_options.alpn_protos.data()), - netvc_options.alpn_protos.size()); - const ats_scoped_str &tlsext_host_name = netvc_options.sni_hostname ? netvc_options.sni_hostname : netvc_options.sni_servername; - SSL_set_tlsext_host_name(this->_ssl, tlsext_host_name.get()); - } else { - SSL_set_accept_state(this->_ssl); - } - - SSL_set_ex_data(this->_ssl, QUIC::ssl_quic_tls_index, this); - SSL_set_key_callback(this->_ssl, key_cb, this); - - if (session_file && this->_netvc_context == NET_VCONNECTION_OUT) { - auto file = BIO_new_file(session_file, "r"); - if (file == nullptr) { - Debug(tag, "Could not read tls session file %s", session_file); - return; - } - - auto session = PEM_read_bio_SSL_SESSION(file, nullptr, nullptr, nullptr); - if (session == nullptr) { - Debug(tag, "Could not read tls session file %s", session_file); - } else { - if (!SSL_set_session(this->_ssl, session)) { - Debug(tag, "Session resumption failed : %s", session_file); - } else { - Debug(tag, "Session resumption success : %s", session_file); - this->_is_session_reused = true; - } - SSL_SESSION_free(session); - } - - BIO_free(file); - } -} - -QUICEncryptionLevel -QUICTLS::get_encryption_level(int msg_type) -{ - switch (msg_type) { - case SSL3_MT_CLIENT_HELLO: - case SSL3_MT_SERVER_HELLO: - return QUICEncryptionLevel::INITIAL; - case SSL3_MT_END_OF_EARLY_DATA: - return QUICEncryptionLevel::ZERO_RTT; - case SSL3_MT_ENCRYPTED_EXTENSIONS: - case SSL3_MT_CERTIFICATE_REQUEST: - case SSL3_MT_CERTIFICATE: - case SSL3_MT_CERTIFICATE_VERIFY: - case SSL3_MT_FINISHED: - return QUICEncryptionLevel::HANDSHAKE; - case SSL3_MT_KEY_UPDATE: - case SSL3_MT_NEWSESSION_TICKET: - return QUICEncryptionLevel::ONE_RTT; - default: - return QUICEncryptionLevel::NONE; - } -} - -void -QUICTLS::set_local_transport_parameters(std::shared_ptr tp) -{ - this->_local_transport_parameters = tp; -} - -int -QUICTLS::_process_post_handshake_messages(QUICHandshakeMsgs *out, const QUICHandshakeMsgs *in) -{ - ink_assert(this->_ssl != nullptr); - - int err = SSL_ERROR_NONE; - ERR_clear_error(); - int ret = 0; - - SSL_set_msg_callback(this->_ssl, QUICTLS::_msg_cb); - SSL_set_msg_callback_arg(this->_ssl, out); - - this->_pass_quic_data_to_ssl_impl(*in); - - uint8_t data[2048]; - size_t l = 0; - ret = SSL_read_ex(this->_ssl, data, 2048, &l); - - if (ret <= 0) { - err = SSL_get_error(this->_ssl, ret); - - switch (err) { - case SSL_ERROR_WANT_READ: - case SSL_ERROR_WANT_WRITE: - break; - default: - char err_buf[256] = {0}; - ERR_error_string_n(ERR_get_error(), err_buf, sizeof(err_buf)); - Debug(tag, "Handshake: %s", err_buf); - return ret; - } - } - - return 1; -} - -void -QUICTLS::_store_negotiated_cipher() -{ - ink_assert(this->_ssl); - - const QUIC_EVP_CIPHER *cipher = nullptr; - size_t tag_len = 0; - const SSL_CIPHER *ssl_cipher = SSL_get_current_cipher(this->_ssl); - - if (ssl_cipher) { - switch (SSL_CIPHER_get_id(ssl_cipher)) { - case TLS1_3_CK_AES_128_GCM_SHA256: - cipher = EVP_aes_128_gcm(); - tag_len = EVP_GCM_TLS_TAG_LEN; - break; - case TLS1_3_CK_AES_256_GCM_SHA384: - cipher = EVP_aes_256_gcm(); - tag_len = EVP_GCM_TLS_TAG_LEN; - break; - case TLS1_3_CK_CHACHA20_POLY1305_SHA256: - cipher = EVP_chacha20_poly1305(); - tag_len = EVP_CHACHAPOLY_TLS_TAG_LEN; - break; - case TLS1_3_CK_AES_128_CCM_SHA256: - cipher = EVP_aes_128_ccm(); - tag_len = EVP_GCM_TLS_TAG_LEN; - break; - case TLS1_3_CK_AES_128_CCM_8_SHA256: - cipher = EVP_aes_128_ccm(); - tag_len = EVP_CCM8_TLS_TAG_LEN; - break; - default: - ink_assert(false); - } - } else { - ink_assert(false); - } - - this->_pp_key_info.set_cipher(cipher, tag_len); -} - -void -QUICTLS::_store_negotiated_cipher_for_hp() -{ - ink_assert(this->_ssl); - - const QUIC_EVP_CIPHER *cipher_for_hp = nullptr; - const SSL_CIPHER *ssl_cipher = SSL_get_current_cipher(this->_ssl); - - if (ssl_cipher) { - switch (SSL_CIPHER_get_id(ssl_cipher)) { - case TLS1_3_CK_AES_128_GCM_SHA256: - cipher_for_hp = EVP_aes_128_ecb(); - break; - case TLS1_3_CK_AES_256_GCM_SHA384: - cipher_for_hp = EVP_aes_256_ecb(); - break; - case TLS1_3_CK_CHACHA20_POLY1305_SHA256: - cipher_for_hp = EVP_chacha20(); - break; - case TLS1_3_CK_AES_128_CCM_SHA256: - case TLS1_3_CK_AES_128_CCM_8_SHA256: - cipher_for_hp = EVP_aes_128_ecb(); - break; - default: - ink_assert(false); - break; - } - } else { - ink_assert(false); - } - - this->_pp_key_info.set_cipher_for_hp(cipher_for_hp); -} - -int -QUICTLS::_read_early_data() -{ - uint8_t early_data[8]; - size_t early_data_len = 0; - - // Early data within the TLS connection MUST NOT be used. As it is for other TLS application data, a server MUST treat receiving - // early data on the TLS connection as a connection error of type PROTOCOL_VIOLATION. - int ret = SSL_read_early_data(this->_ssl, early_data, sizeof(early_data), &early_data_len); - // error or reading empty data return 1, otherwise return 0. - if (early_data_len != 0) { - return -1; - } - if (ret == SSL_READ_EARLY_DATA_FINISH) { - return 0; - } else { - return 1; - } -} - -int -QUICTLS::_write_early_data() -{ - size_t early_data_len = 0; - - // Early data within the TLS connection MUST NOT be used. As it is for other TLS application data, a server MUST treat receiving - // early data on the TLS connection as a connection error of type PROTOCOL_VIOLATION. - SSL_write_early_data(this->_ssl, "", 0, &early_data_len); - // always return 1 - return 1; -} - -void -QUICTLS::_pass_quic_data_to_ssl_impl(const QUICHandshakeMsgs &in) -{ - // TODO: set BIO_METHOD which read from QUICHandshakeMsgs directly - BIO *rbio = BIO_new(BIO_s_mem()); - // TODO: set dummy BIO_METHOD which do nothing - BIO *wbio = BIO_new(BIO_s_mem()); - if (in.offsets[4] != 0) { - BIO_write(rbio, in.buf, in.offsets[4]); - } - SSL_set_bio(this->_ssl, rbio, wbio); -} - -const EVP_MD * -QUICTLS::_get_handshake_digest() const -{ - switch (SSL_CIPHER_get_id(SSL_get_current_cipher(this->_ssl))) { - case TLS1_3_CK_AES_128_GCM_SHA256: - case TLS1_3_CK_CHACHA20_POLY1305_SHA256: - case TLS1_3_CK_AES_128_CCM_SHA256: - case TLS1_3_CK_AES_128_CCM_8_SHA256: - return EVP_sha256(); - case TLS1_3_CK_AES_256_GCM_SHA384: - return EVP_sha384(); - default: - ink_assert(false); - return nullptr; - } -}