From 034e0632e42edd13dfec9d917f14c5e7bd7fb245 Mon Sep 17 00:00:00 2001 From: Sashanoraa Date: Tue, 25 Mar 2025 18:38:42 -0400 Subject: [PATCH] Box some of the larger information element enum variants An enum is always the size needed to store its largest variant. Some of the variants of the InformationElement and LteInformationElement are substantially larger than the rest. Boxing the larger variants reduces the size of the enum, in some cases by several kilobytes. Since Rust does not currently support destructing a Box via pattern matching, some code that destructures these enums had to be modified. --- bin/src/dummy_analyzer.rs | 8 ++++++-- lib/src/analysis/connection_redirect_downgrade.rs | 7 +++++-- lib/src/analysis/imsi_provided.rs | 8 ++++++-- lib/src/analysis/imsi_requested.rs | 8 ++++++-- lib/src/analysis/information_element.rs | 14 +++++++++----- lib/src/analysis/null_cipher.rs | 8 ++++++-- lib/src/analysis/priority_2g_downgrade.rs | 10 ++++++---- 7 files changed, 44 insertions(+), 19 deletions(-) diff --git a/bin/src/dummy_analyzer.rs b/bin/src/dummy_analyzer.rs index fcf65fb..1aa50b7 100644 --- a/bin/src/dummy_analyzer.rs +++ b/bin/src/dummy_analyzer.rs @@ -26,8 +26,12 @@ impl Analyzer for TestAnalyzer{ message: "multiple of 100 events processed".to_string(), }) } - let InformationElement::LTE(LteInformationElement::PCCH(pcch_msg)) = ie else { - return None; + let pcch_msg = match ie { + InformationElement::LTE(lte_ie) => match &** lte_ie { + LteInformationElement::PCCH(pcch_msg) => pcch_msg, + _ => return None, + } + _ => return None, }; let PCCH_MessageType::C1(PCCH_MessageType_c1::Paging(paging)) = &pcch_msg.message else { return None; diff --git a/lib/src/analysis/connection_redirect_downgrade.rs b/lib/src/analysis/connection_redirect_downgrade.rs index b3b6a14..6ed5dad 100644 --- a/lib/src/analysis/connection_redirect_downgrade.rs +++ b/lib/src/analysis/connection_redirect_downgrade.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use super::analyzer::{Analyzer, Event, EventType, Severity}; use super::information_element::{InformationElement, LteInformationElement}; -use telcom_parser::lte_rrc::{DL_DCCH_Message, DL_DCCH_MessageType, DL_DCCH_MessageType_c1, RRCConnectionReleaseCriticalExtensions, RRCConnectionReleaseCriticalExtensions_c1, RedirectedCarrierInfo}; +use telcom_parser::lte_rrc::{DL_DCCH_MessageType, DL_DCCH_MessageType_c1, RRCConnectionReleaseCriticalExtensions, RRCConnectionReleaseCriticalExtensions_c1, RedirectedCarrierInfo}; use super::util::unpack; // Based on HITBSecConf presentation "Forcing a targeted LTE cellphone into an @@ -22,7 +22,10 @@ impl Analyzer for ConnectionRedirect2GDowngradeAnalyzer { fn analyze_information_element(&mut self, ie: &InformationElement) -> Option { unpack!(InformationElement::LTE(lte_ie) = ie); - unpack!(LteInformationElement::DlDcch(DL_DCCH_Message { message }) = lte_ie); + let message = match &**lte_ie { + LteInformationElement::DlDcch(msg_cont) => &msg_cont.message, + _ => return None, + }; unpack!(DL_DCCH_MessageType::C1(c1) = message); unpack!(DL_DCCH_MessageType_c1::RrcConnectionRelease(release) = c1); unpack!(RRCConnectionReleaseCriticalExtensions::C1(c1) = &release.critical_extensions); diff --git a/lib/src/analysis/imsi_provided.rs b/lib/src/analysis/imsi_provided.rs index 341c376..927ebe4 100644 --- a/lib/src/analysis/imsi_provided.rs +++ b/lib/src/analysis/imsi_provided.rs @@ -18,8 +18,12 @@ impl Analyzer for ImsiProvidedAnalyzer { } fn analyze_information_element(&mut self, ie: &InformationElement) -> Option { - let InformationElement::LTE(LteInformationElement::PCCH(pcch_msg)) = ie else { - return None; + let pcch_msg = match ie { + InformationElement::LTE(lte_ie) => match &** lte_ie { + LteInformationElement::PCCH(pcch_msg) => pcch_msg, + _ => return None, + } + _ => return None, }; let PCCH_MessageType::C1(PCCH_MessageType_c1::Paging(paging)) = &pcch_msg.message else { return None; diff --git a/lib/src/analysis/imsi_requested.rs b/lib/src/analysis/imsi_requested.rs index e7d8f66..f78b348 100644 --- a/lib/src/analysis/imsi_requested.rs +++ b/lib/src/analysis/imsi_requested.rs @@ -26,8 +26,12 @@ impl Analyzer for ImsiRequestedAnalyzer { fn analyze_information_element(&mut self, ie: &InformationElement) -> Option { self.packet_num += 1; - let InformationElement::LTE(LteInformationElement::NAS(payload)) = ie else { - return None; + let payload = match ie { + InformationElement::LTE(inner) => match &**inner { + LteInformationElement::NAS(payload) => payload, + _ => return None, + } + _ => return None, }; // NAS identity request, ID type IMSI diff --git a/lib/src/analysis/information_element.rs b/lib/src/analysis/information_element.rs index 235a6b6..161ab36 100644 --- a/lib/src/analysis/information_element.rs +++ b/lib/src/analysis/information_element.rs @@ -19,14 +19,18 @@ pub enum InformationElementError { pub enum InformationElement { GSM, UMTS, - LTE(LteInformationElement), + // This element of the enum is substantially larger than the others, + // so we box it to prevent the size of the enum (any variant) from blowing up. + LTE(Box), FiveG, } #[derive(Debug, Clone, PartialEq)] pub enum LteInformationElement { DlCcch(lte_rrc::DL_CCCH_Message), - DlDcch(lte_rrc::DL_DCCH_Message), + // This element of the enum is substantially larger than the others, + // so we box it to prevent the size of the enum (any variant) from blowing up. + DlDcch(Box), UlCcch(lte_rrc::UL_CCCH_Message), UlDcch(lte_rrc::UL_DCCH_Message), BcchBch(lte_rrc::BCCH_BCH_Message), @@ -65,7 +69,7 @@ impl TryFrom<&GsmtapMessage> for InformationElement { use LteInformationElement as R; let lte = match lte_rrc_subtype { L::DlCcch => R::DlCcch(decode(&gsmtap_msg.payload)?), - L::DlDcch => R::DlDcch(decode(&gsmtap_msg.payload)?), + L::DlDcch => R::DlDcch(Box::new(decode(&gsmtap_msg.payload)?)), L::UlCcch => R::UlCcch(decode(&gsmtap_msg.payload)?), L::UlDcch => R::UlDcch(decode(&gsmtap_msg.payload)?), L::BcchBch => R::BcchBch(decode(&gsmtap_msg.payload)?), @@ -80,10 +84,10 @@ impl TryFrom<&GsmtapMessage> for InformationElement { L::SbcchSlBchV2x => R::SbcchSlBchV2x(decode(&gsmtap_msg.payload)?), _ => return Err(InformationElementError::UnsupportedGsmtapType(gsmtap_msg.header.gsmtap_type)), }; - Ok(InformationElement::LTE(lte)) + Ok(InformationElement::LTE(Box::new(lte))) }, GsmtapType::LteNas(LteNasSubtype::Plain) => { - Ok(InformationElement::LTE(LteInformationElement::NAS(gsmtap_msg.payload.clone()))) + Ok(InformationElement::LTE(Box::new(LteInformationElement::NAS(gsmtap_msg.payload.clone())))) }, _ => Err(InformationElementError::UnsupportedGsmtapType(gsmtap_msg.header.gsmtap_type)), } diff --git a/lib/src/analysis/null_cipher.rs b/lib/src/analysis/null_cipher.rs index c3090e9..095324c 100644 --- a/lib/src/analysis/null_cipher.rs +++ b/lib/src/analysis/null_cipher.rs @@ -93,8 +93,12 @@ impl Analyzer for NullCipherAnalyzer { } fn analyze_information_element(&mut self, ie: &InformationElement) -> Option { - let InformationElement::LTE(LteInformationElement::DlDcch(dcch_msg)) = ie else { - return None; + let dcch_msg = match ie { + InformationElement::LTE(lte_ie) => match &** lte_ie { + LteInformationElement::DlDcch(dcch_msg) => dcch_msg, + _ => return None, + } + _ => return None, }; let DL_DCCH_MessageType::C1(c1) = &dcch_msg.message else { return None; diff --git a/lib/src/analysis/priority_2g_downgrade.rs b/lib/src/analysis/priority_2g_downgrade.rs index 44003fd..ea7ef70 100644 --- a/lib/src/analysis/priority_2g_downgrade.rs +++ b/lib/src/analysis/priority_2g_downgrade.rs @@ -10,10 +10,12 @@ pub struct LteSib6And7DowngradeAnalyzer { impl LteSib6And7DowngradeAnalyzer { fn unpack_system_information<'a>(&self, ie: &'a InformationElement) -> Option<&'a SystemInformation_r8_IEsSib_TypeAndInfo> { - if let InformationElement::LTE(LteInformationElement::BcchDlSch(bcch_dl_sch_message)) = ie { - if let BCCH_DL_SCH_MessageType::C1(BCCH_DL_SCH_MessageType_c1::SystemInformation(system_information)) = &bcch_dl_sch_message.message { - if let SystemInformationCriticalExtensions::SystemInformation_r8(sib) = &system_information.critical_extensions { - return Some(&sib.sib_type_and_info); + if let InformationElement::LTE(lte_ie) = ie { + if let LteInformationElement::BcchDlSch(bcch_dl_sch_message) = &**lte_ie { + if let BCCH_DL_SCH_MessageType::C1(BCCH_DL_SCH_MessageType_c1::SystemInformation(system_information)) = &bcch_dl_sch_message.message { + if let SystemInformationCriticalExtensions::SystemInformation_r8(sib) = &system_information.critical_extensions { + return Some(&sib.sib_type_and_info); + } } } }