From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- .../nss/gtests/ssl_gtest/tls_xyber_unittest.cc | 274 +++++++++++++++++++++ 1 file changed, 274 insertions(+) create mode 100644 security/nss/gtests/ssl_gtest/tls_xyber_unittest.cc (limited to 'security/nss/gtests/ssl_gtest/tls_xyber_unittest.cc') diff --git a/security/nss/gtests/ssl_gtest/tls_xyber_unittest.cc b/security/nss/gtests/ssl_gtest/tls_xyber_unittest.cc new file mode 100644 index 0000000000..6881228c8e --- /dev/null +++ b/security/nss/gtests/ssl_gtest/tls_xyber_unittest.cc @@ -0,0 +1,274 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "ssl.h" +#include "sslerr.h" +#include "sslproto.h" + +extern "C" { +// This is not something that should make you happy. +#include "libssl_internals.h" +} + +#include "gtest_utils.h" +#include "nss_scoped_ptrs.h" +#include "tls_connect.h" +#include "tls_filter.h" +#include "tls_parser.h" + +namespace nss_test { + +TEST_P(TlsKeyExchangeTest13, Xyber768d00Supported) { + EnsureKeyShareSetup(); + ConfigNamedGroups({ssl_grp_kem_xyber768d00}); + + Connect(); + CheckKeys(ssl_kea_ecdh_hybrid, ssl_grp_kem_xyber768d00, ssl_auth_rsa_sign, + ssl_sig_rsa_pss_rsae_sha256); +} + +TEST_P(TlsKeyExchangeTest, Tls12ClientXyber768d00NotSupported) { + EnsureKeyShareSetup(); + client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2, + SSL_LIBRARY_VERSION_TLS_1_2); + server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2, + SSL_LIBRARY_VERSION_TLS_1_3); + client_->DisableAllCiphers(); + client_->EnableCiphersByKeyExchange(ssl_kea_ecdh); + client_->EnableCiphersByKeyExchange(ssl_kea_ecdh_hybrid); + EXPECT_EQ(SECSuccess, SSL_SendAdditionalKeyShares( + client_->ssl_fd(), + kECDHEGroups.size() + kEcdhHybridGroups.size())); + + Connect(); + std::vector groups = GetGroupDetails(groups_capture_); + for (auto group : groups) { + EXPECT_NE(group, ssl_grp_kem_xyber768d00); + } +} + +TEST_P(TlsKeyExchangeTest13, Tls12ServerXyber768d00NotSupported) { + if (variant_ == ssl_variant_datagram) { + /* Bug 1874451 - reenable this test */ + return; + } + + EnsureKeyShareSetup(); + + client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2, + SSL_LIBRARY_VERSION_TLS_1_3); + server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2, + SSL_LIBRARY_VERSION_TLS_1_2); + + client_->DisableAllCiphers(); + client_->EnableCiphersByKeyExchange(ssl_kea_ecdh); + client_->EnableCiphersByKeyExchange(ssl_kea_ecdh_hybrid); + client_->ConfigNamedGroups({ssl_grp_kem_xyber768d00, ssl_grp_ec_curve25519}); + EXPECT_EQ(SECSuccess, SSL_SendAdditionalKeyShares(client_->ssl_fd(), 1)); + + server_->EnableCiphersByKeyExchange(ssl_kea_ecdh); + server_->EnableCiphersByKeyExchange(ssl_kea_ecdh_hybrid); + server_->ConfigNamedGroups({ssl_grp_kem_xyber768d00, ssl_grp_ec_curve25519}); + + Connect(); + CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_rsa_sign, + ssl_sig_rsa_pss_rsae_sha256); +} + +TEST_P(TlsKeyExchangeTest13, Xyber768d00ClientDisabledByPolicy) { + EnsureKeyShareSetup(); + client_->SetPolicy(SEC_OID_XYBER768D00, 0, NSS_USE_ALG_IN_SSL_KX); + ConfigNamedGroups({ssl_grp_kem_xyber768d00, ssl_grp_ec_secp256r1}); + + Connect(); + CheckKEXDetails({ssl_grp_ec_secp256r1}, {ssl_grp_ec_secp256r1}); +} + +TEST_P(TlsKeyExchangeTest13, Xyber768d00ServerDisabledByPolicy) { + EnsureKeyShareSetup(); + server_->SetPolicy(SEC_OID_XYBER768D00, 0, NSS_USE_ALG_IN_SSL_KX); + ConfigNamedGroups({ssl_grp_kem_xyber768d00, ssl_grp_ec_secp256r1}); + + Connect(); + CheckKEXDetails({ssl_grp_kem_xyber768d00, ssl_grp_ec_secp256r1}, + {ssl_grp_kem_xyber768d00}, ssl_grp_ec_secp256r1); +} + +class XyberShareDamager : public TlsExtensionFilter { + public: + typedef enum { + downgrade, + extend, + truncate, + zero_ecdh, + modify_ecdh, + modify_kyber, + } damage_type; + + XyberShareDamager(const std::shared_ptr& a, damage_type damage) + : TlsExtensionFilter(a), damage_(damage) {} + + virtual PacketFilter::Action FilterExtension(uint16_t extension_type, + const DataBuffer& input, + DataBuffer* output) { + if (extension_type != ssl_tls13_key_share_xtn) { + return KEEP; + } + + // Find the Xyber768d00 share + size_t offset = 0; + if (agent()->role() == TlsAgent::CLIENT) { + offset += 2; // skip KeyShareClientHello length + } + + uint32_t named_group; + uint32_t named_group_len; + input.Read(offset, 2, &named_group); + input.Read(offset + 2, 2, &named_group_len); + while (named_group != ssl_grp_kem_xyber768d00) { + offset += 2 + 2 + named_group_len; + input.Read(offset, 2, &named_group); + input.Read(offset + 2, 2, &named_group_len); + } + EXPECT_EQ(named_group, ssl_grp_kem_xyber768d00); + + DataBuffer xyber_key_share(input.data() + offset, 2 + 2 + named_group_len); + + // Damage the Xyber768d00 share + unsigned char* ecdh_component = xyber_key_share.data() + 2 + 2; + unsigned char* kyber_component = + xyber_key_share.data() + 2 + 2 + X25519_PUBLIC_KEY_BYTES; + switch (damage_) { + case XyberShareDamager::downgrade: + // Downgrade a Xyber768d00 share to X25519 + xyber_key_share.Truncate(2 + 2 + X25519_PUBLIC_KEY_BYTES); + xyber_key_share.Write(0, ssl_grp_ec_curve25519, 2); + xyber_key_share.Write(2, X25519_PUBLIC_KEY_BYTES, 2); + break; + case XyberShareDamager::truncate: + // Truncate a Xyber768d00 share after the X25519 component + xyber_key_share.Truncate(2 + 2 + X25519_PUBLIC_KEY_BYTES); + xyber_key_share.Write(2, X25519_PUBLIC_KEY_BYTES, 2); + break; + case XyberShareDamager::extend: + // Append 4 bytes to a Xyber768d00 share + uint32_t current_len; + xyber_key_share.Read(2, 2, ¤t_len); + xyber_key_share.Write(xyber_key_share.len(), current_len, 4); + xyber_key_share.Write(2, current_len + 4, 2); + break; + case XyberShareDamager::zero_ecdh: + // Replace an X25519 component with 0s + memset(ecdh_component, 0, X25519_PUBLIC_KEY_BYTES); + break; + case XyberShareDamager::modify_ecdh: + // Flip a bit in the X25519 component + ecdh_component[0] ^= 0x01; + break; + case XyberShareDamager::modify_kyber: + // Flip a bit in the Kyber component + kyber_component[0] ^= 0x01; + break; + } + + *output = input; + output->Splice(xyber_key_share, offset, 2 + 2 + named_group_len); + + // Fix the KeyShareClientHello length if necessary + if (agent()->role() == TlsAgent::CLIENT && + xyber_key_share.len() != 2 + 2 + named_group_len) { + output->Write(0, output->len() - 2, 2); + } + + return CHANGE; + } + + private: + damage_type damage_; +}; + +class TlsXyberDamageTest + : public TlsConnectTestBase, + public ::testing::WithParamInterface { + public: + TlsXyberDamageTest() + : TlsConnectTestBase(ssl_variant_stream, SSL_LIBRARY_VERSION_TLS_1_3) {} + + protected: + void Damage(const std::shared_ptr& agent) { + EnsureTlsSetup(); + client_->ConfigNamedGroups( + {ssl_grp_ec_curve25519, ssl_grp_kem_xyber768d00}); + server_->ConfigNamedGroups( + {ssl_grp_kem_xyber768d00, ssl_grp_ec_curve25519}); + EXPECT_EQ(SECSuccess, SSL_SendAdditionalKeyShares(client_->ssl_fd(), 1)); + MakeTlsFilter(agent, GetParam()); + } +}; + +TEST_P(TlsXyberDamageTest, DamageClientShare) { + Damage(client_); + + switch (GetParam()) { + case XyberShareDamager::extend: + case XyberShareDamager::truncate: + ConnectExpectAlert(server_, kTlsAlertIllegalParameter); + server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_HYBRID_KEY_SHARE); + break; + case XyberShareDamager::zero_ecdh: + ConnectExpectAlert(server_, kTlsAlertIllegalParameter); + server_->CheckErrorCode(SEC_ERROR_INVALID_KEY); + break; + case XyberShareDamager::downgrade: + case XyberShareDamager::modify_ecdh: + case XyberShareDamager::modify_kyber: + client_->ExpectSendAlert(kTlsAlertBadRecordMac); + server_->ExpectSendAlert(kTlsAlertBadRecordMac); + ConnectExpectFail(); + client_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ); + server_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ); + break; + } +} + +TEST_P(TlsXyberDamageTest, DamageServerShare) { + Damage(server_); + + switch (GetParam()) { + case XyberShareDamager::extend: + case XyberShareDamager::truncate: + client_->ExpectSendAlert(kTlsAlertIllegalParameter); + server_->ExpectSendAlert(kTlsAlertUnexpectedMessage); + ConnectExpectFail(); + client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_HYBRID_KEY_SHARE); + break; + case XyberShareDamager::zero_ecdh: + client_->ExpectSendAlert(kTlsAlertIllegalParameter); + server_->ExpectSendAlert(kTlsAlertUnexpectedMessage); + ConnectExpectFail(); + client_->CheckErrorCode(SEC_ERROR_INVALID_KEY); + break; + case XyberShareDamager::downgrade: + case XyberShareDamager::modify_ecdh: + case XyberShareDamager::modify_kyber: + client_->ExpectSendAlert(kTlsAlertBadRecordMac); + server_->ExpectSendAlert(kTlsAlertBadRecordMac); + ConnectExpectFail(); + client_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ); + server_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ); + break; + } +} + +INSTANTIATE_TEST_SUITE_P(TlsXyberDamageTest, TlsXyberDamageTest, + ::testing::Values(XyberShareDamager::downgrade, + XyberShareDamager::extend, + XyberShareDamager::truncate, + XyberShareDamager::zero_ecdh, + XyberShareDamager::modify_ecdh, + XyberShareDamager::modify_kyber)); + +} // namespace nss_test -- cgit v1.2.3