Update on Overleaf.

This commit is contained in:
nb72soza Bittner
2025-07-01 23:50:06 +00:00
committed by node
parent 928dcd72df
commit 05541d57ab
10 changed files with 690 additions and 539 deletions

View File

@@ -33,7 +33,7 @@ The proposed method was to:
\begin{enumerate}
\item Record the \gls{apdu} traffic between the \gls{lpa} and the \gls{euicc} during an \gls{rsp} session.
\item Store this traffic in a structured format.
\item Replace the original \gls{euicc} with another one inserted into a \gls{pcsc}-compatible card reader.
\item Replace the original \gls{euicc} with another one inserted into a PC/SC-compatible card reader.
\item Replay each recorded \gls{apdu} and monitor the response.
\end{enumerate}
@@ -48,7 +48,7 @@ The goal was to detect behavioral differences, such as differing \glspl{sw} or e
\item A custom \gls{lpa} allows for controlled mutation and injection of \gls{apdu} sequences.
\end{itemize}
The implemented \gls{lpa} performs a target operation (e.g., profile download or enablement) by issuing the appropriate command sequence to the \gls{euicc} in the \gls{pcsc} card reader. Before sending, \glspl{apdu} can be programmatically mutated to evaluate robustness of the implementation against malformed or unexpected inputs. The \gls{lpa} records returned status words and checks for behavioral consistency across different \glspl{euicc}.
The implemented \gls{lpa} performs a target operation (e.g., profile download or enablement) by issuing the appropriate command sequence to the \gls{euicc} in the PC/SC card reader. Before sending, \glspl{apdu} can be programmatically mutated to evaluate robustness of the implementation against malformed or unexpected inputs. The \gls{lpa} records returned status words and checks for behavioral consistency across different \glspl{euicc}.
While this approach allows for a more precise control, it has some drawbacks. \gls{rsp} is a stateful protocol, and provisioning actions rely on interaction with the profile vendor's \gls{smdpp} server. Consequently, execution speed is constrained by network latency and backend responsiveness as well as restoring the \gls{euicc} state after a reset.
@@ -89,7 +89,7 @@ The tracing functionality comprises two main operations:
\begin{itemize}
\item \textbf{Tracing and recording:} Captures \glspl{apdu} traffic from a physical interface using \texttt{simtrace2}~\cite{osmocom_simtrace_nodate} and associates it with functional interpretations (e.g., profile enablement, deletion). The \glspl{apdu} are parsed and stored along with contextual information such as sender and receiver addresses.
\item \textbf{Replaying:} Replays previously recorded \glspl{apdu} sequences to an \gls{euicc} in a \gls{pcsc} card reader. It replaces context-specific identifiers and checks for discrepancies in response behavior.
\item \textbf{Replaying:} Replays previously recorded \glspl{apdu} sequences to an \gls{euicc} in a PC/SC card reader. It replaces context-specific identifiers and checks for discrepancies in response behavior.
\end{itemize}
\begin{figure}[h!]
@@ -101,13 +101,13 @@ The tracing functionality comprises two main operations:
The implementation consists of several key components:
\begin{description}
\item[\texttt{PcscLink}] A thin wrapper over the Python \texttt{pyscard} library~\cite{rousseau_pyscard_2025}, which abstracts away low-level communication with \gls{pcsc}-compatible card readers. It handles session establishment, \glspl{apdu}/\gls{tpdu} transmission, and automatic processing of status words such as \texttt{61XX} (i.e., triggering \texttt{GET RESPONSE} when necessary).
\item[\texttt{PcscLink}] A thin wrapper over the Python \texttt{pyscard} library~\cite{rousseau_pyscard_2025}, which abstracts away low-level communication with PC/SC-compatible card readers. It handles session establishment, \glspl{apdu}/\gls{tpdu} transmission, and automatic processing of status words such as \texttt{61XX} (i.e., triggering \texttt{GET RESPONSE} when necessary).
\item[\texttt{Card}] Represents a connected card in a \gls{pcsc} reader. It queries the card to determine its type (e.g., standard \gls{sim}, test \gls{euicc}, or commercial \gls{euicc}), and identifies installed applications such as \texttt{\gls{isdr}} or \texttt{\gls{ecasd}}. The class serves as the interface for sending \glspl{apdu} to the card through the \texttt{pcsc\_link}.
\item[\texttt{Card}] Represents a connected card in a PC/SC reader. It queries the card to determine its type (e.g., standard \gls{sim}, test \gls{euicc}, or commercial \gls{euicc}), and identifies installed applications such as \texttt{\gls{isdr}} or \texttt{\gls{ecasd}}. The class serves as the interface for sending \glspl{apdu} to the card through the \texttt{pcsc\_link}.
\item[\texttt{Tracer}] A dummy implementation of the \texttt{Card} interface used during passive tracing. It parses incoming \glspl{apdu} from the \gls{gsmtap} interface using \texttt{pysim} and attempts to classify them based on instruction type. This allows mapping observed \glspl{apdu} to functional operations.
\item[\texttt{Tracer}] A dummy implementation of the \texttt{Card} interface used during passive tracing. It parses incoming \glspl{apdu} from the GSMTAP interface using \texttt{pysim} and attempts to classify them based on instruction type. This allows mapping observed \glspl{apdu} to functional operations.
\item[\texttt{Recorder}] Coordinates tracing and recording. It spawns a separate tracer thread that listens for \glspl{apdu} from \gls{gsmtap} in a loop until a timeout occurs or a stop signal is issued. \glspl{apdu} are recorded alongside the designated target \texttt{\gls{isdr}} for later analysis.
\item[\texttt{Recorder}] Coordinates tracing and recording. It spawns a separate tracer thread that listens for \glspl{apdu} from GSMTAP in a loop until a timeout occurs or a stop signal is issued. \glspl{apdu} are recorded alongside the designated target \texttt{\gls{isdr}} for later analysis.
\item[\texttt{recording}] An abstraction for a recorded session. It stores the list of \glspl{apdu}, associated source and target \texttt{\gls{isdr}} addresses, and metadata. It provides serialization functions for saving to and loading from disk, as well as validity checks to determine whether a recording is replayable.
@@ -189,15 +189,15 @@ This modular structure allows for easy integration into both automated test pipe
% before returning the data to the caller -> client checks for error on server and eventually raises the corresponding exception -> as explained in the exception handling part
% smdp+ client is mostly used by the isd-r
Due to the limitations of the \texttt{tracer} implementation in correctly replaying \gls{rsp} interactions, a dedicated \gls{lpa} implementation was developed to initiate valid interactions with the \gls{euicc}. This enables the controlled generation and mutation of valid traffic which we will further explain in \cref{sec:fuzzing}. Our implementation targets the \gls{sgp22} v3.1 specification, which was the latest version available at the time of writing.
Due to the limitations of the \texttt{tracer} implementation in correctly replaying \gls{rsp} interactions, a dedicated \gls{lpa} implementation was developed to initiate valid interactions with the \gls{euicc}. This enables the controlled generation and mutation of valid traffic which we will further explain in \cref{sec:fuzzing}. Our implementation targets the SGP.22 v3.1 specification, which was the latest version available at the time of writing \cite{gsma_sgp22_2025}.
The \gls{lpa} is composed of multiple components:
\paragraph{Card}
Represents the \gls{euicc} currently inserted into the \gls{pcsc} card reader. Upon initialization, it scans the card for supported applications, identifying the applicable \gls{adf} through probing. This is necessary as eSIM-on-SIM implementations often use proprietary \glspl{adf}, diverging from the \glspl{adf} specified in the \gls{sgp22} standard. The card object keeps track of the selected application to reduce unnecessary reselection and traffic.
Represents the \gls{euicc} currently inserted into the PC/SC card reader. Upon initialization, it scans the card for supported applications, identifying the applicable \gls{adf} through probing. This is necessary as eSIM-on-SIM implementations often use proprietary \glspl{adf}, diverging from the \glspl{adf} specified in the SGP.22 standard as we will evaluate in \cref{sec:eval_tracing}. The card object keeps track of the selected application to reduce unnecessary reselection and traffic.
\paragraph{PC/SC Link}
This component is based on \texttt{pySim}'s \texttt{LinkBaseTpdu}. It establishes an exclusive connection to the \gls{pcsc} reader to maintain session state consistency, which is required due to the stateful nature of \gls{euicc} interactions. During initialization:
This component is based on \texttt{pySim}'s \texttt{LinkBaseTpdu}. It establishes an exclusive connection to the PC/SC reader to maintain session state consistency, which is required due to the stateful nature of \gls{euicc} interactions. During initialization:
\begin{itemize}
\item The supported transmission protocol (T=0 or T=1) is detected.
\item A connection is established and validated.
@@ -213,17 +213,17 @@ Known \glspl{adf} for \gls{isdr} observed during analysis:
\item 5Ber.esim: \texttt{A0000005591010FFFFFFFF8900050500}
\item Xesim: \texttt{A0000005591010FFFFFFFF8900000177}
\item esim.me: \texttt{A0000005591010000000008900000300}
\end{itemize}as
\end{itemize}
The decoded response data is further processed using \texttt{pydantic} data classes. These enable structured parsing of values including Base64-encoded strings, bitfields, version types, and more. Custom encoders/decoders are used to simplify readability and downstream data processing. For bit fields, a mixin is used to allow checking for specific feature flags via simple accessors.
The decoded response data is further processed using \texttt{pydantic} data classes. \texttt{pydantic} is a python library that enable structured parsing of values including Base64-encoded strings, bitfields, version types, and more. Custom encoders/decoders are used to simplify readability and downstream data processing. For bit fields, a mixin is used to allow checking for specific feature flags via simple accessors.
The \texttt{estk\_fwupd} application implements a proprietary firmware update interface, which was reverse-engineered (see \cref{sec:findings}). It supports reading the current firmware version, unlocking\footnote{This unlocking is distinct from \gls{gp}-defined unlocking, which allows the execution of generic \gls{gp} commands. See \gls{gp} Card Specification.} the \gls{euicc} for updates, and installing new binaries.
\paragraph{Exception Handling}
The \gls{sgp22} standard defines a variety of response codes and error conditions. The \gls{lpa} library maps these response codes to custom exception classes for precise error handling. This is essential for both debugging and for the differential testing framework to reason about diverging behavior across implementations. A code listing of the exception handling mappings is provided in \cref{sec:exception-handling}.
The SGP.22 standard defines a variety of response codes and error conditions. The \gls{lpa} library maps these response codes to custom exception classes for precise error handling. This is essential for both debugging and for the differential testing framework to reason about diverging behavior across implementations. A code listing of the exception handling mappings is provided in \cref{sec:exception-handling}.
\paragraph{SM-DP+ Client}
In addition to \gls{euicc} communication, the \gls{lpa} must interact with the \gls{smdpp} server via the ES9+ interface. Our implementation uses \texttt{httpx} for HTTP interactions and adheres to the expected headers and structure as defined by \gls{sgp22}:
In addition to \gls{euicc} communication, the \gls{lpa} must interact with the \gls{smdpp} server via the ES9+ interface. Our implementation uses \texttt{httpx} for HTTP interactions and adheres to the expected headers and structure as defined by SGP.22:
\begin{lstlisting}[language=json,caption={ES9+ Request Headers}]
{
"Content-Type": "application/json",
@@ -322,15 +322,17 @@ To uncover behavioral differences between \gls{euicc} implementations, we implem
\subsubsection*{Fuzzing Scenarios and Execution}
Fuzzing is conducted through predefined \emph{scenarios}—sequences of function calls that operate on the \gls{euicc}. Each function in a scenario interacts with the \gls{euicc} through the \gls{lpa} and is subject to mutation. The scenario runner initiates a fresh \gls{pcsc} link, resets the card into a clean state (processing all notifications and performing a full memory reset), and executes each function with multiple mutations.
Fuzzing is conducted through predefined \emph{scenarios}—sequences of function calls that operate on the \gls{euicc}. Each function in a scenario interacts with the \gls{euicc} through the \gls{lpa} and is subject to mutation. The scenario runner initiates a fresh PC/SC link, resets the card into a clean state (processing all notifications and performing a full memory reset) using our \gls{lpa} implementation, and executes each function with multiple mutations.
This process is guided by an \textbf{operation recorder} that tracks each function call, applied mutations, and resulting responses in a structured \emph{mutation tree}. Each tree node represents a specific function call executed with one type of mutation. A tree level corresponds to a function in the scenario; sibling nodes represent different mutations of that function.
This process is guided by an \textbf{operation recorder} that tracks each function call, applied mutations, and resulting responses in a structured \emph{mutation tree}. Each tree node represents a specific function call executed with one type of mutation. A tree level corresponds to a function in the scenario and sibling nodes represent different mutations of that function.
\subsubsection*{Mutation Engine}
\label{subsubsec:mutation_engine}
The mutation engine supports both \textit{deterministic} and \textit{random} mutation modes, and implements the following strategies:
\todo{Go into more detail on how the muations are performed}
\begin{itemize}
\item \textbf{Bit flip:} Flips a fixed number of bits based on mutation rate and payload length.
\item \textbf{Random byte:} Swaps random byte positions.
@@ -339,7 +341,7 @@ The mutation engine supports both \textit{deterministic} and \textit{random} mut
\item \textbf{Truncate:} Removes the tail of the \gls{apdu}.
\end{itemize}
Deterministic mode ensures reproducibility by always mutating the same offset, while the random mode selects targets dynamically. This allows us to explore both fixed and variable fuzzing behavior. Both modes behave similar to the deterministic and non-deterministic mutation modes used in AFLPlusPlus.
Deterministic mode ensures reproducibility by always mutating the same offset, while the random mode selects targets dynamically. This allows us to explore both fixed and variable fuzzing behavior. Both modes behave similar to the deterministic and non-deterministic mutation modes used in AFLPlusPlus~\cite{fioraldi_afl_2020}.
\subsubsection*{Fuzzing Workflow}
@@ -347,7 +349,7 @@ The \gls{apdu} fuzzing workflow is illustrated in \cref{fig:scenario_flow} and p
\begin{enumerate}
\item \textbf{Mutation selection:} The operation recorder decides the next mutation to apply based on a depth-first traversal of the mutation tree. If all mutations for the current function are exhausted, the runner searches for unexplored child nodes.
\item \textbf{\gls{apdu} mutation:} The selected mutation is applied to the original APDU using the mutation engine.
\item \textbf{\gls{apdu} mutation:} The selected mutation is applied to the original \gls{apdu} using the mutation engine.
\item \textbf{\gls{apdu} transmission:} The mutated \gls{apdu} is sent to the card. Success or failure is recorded in the current node.
\item \textbf{Recording:} The response (or exception) is saved to the mutation tree node for further analysis.
\end{enumerate}
@@ -406,7 +408,7 @@ This strategy is both exhaustive and progress-aware. It ensures that:
\subsubsection*{Error Handling and Retry Logic}
Errors during execution are logged and associated with the current mutation node. If a function fails (e.g., due to protocol state loss or card reset), the runner resets the \gls{pcsc} link and the card, then resumes execution. This ensures that failures do not corrupt the mutation tree and allows exploration to continue.
Errors during execution are logged and associated with the current mutation node. If a function fails (e.g., due to protocol state loss or card reset), the runner resets the PC/SC link and the card, then resumes execution. This ensures that failures do not corrupt the mutation tree and allows exploration to continue.
\subsubsection*{Scenario Persistence and Reuse}
@@ -508,7 +510,7 @@ To address this limitation, we introduce a complementary \textit{data fuzzing} a
\paragraph{Fuzzing with Hypothesis}
Hypothesis is a property-based testing framework, which allows developers to define \textit{strategies} for input data. The framework then generates test cases based on these strategies and attempts to explore edge cases through randomized sampling and shrinking. Unlike traditional random fuzzing, Hypothesis ensures that generated inputs conform to the structural invariants defined by the strategy, thereby increasing the likelihood of discovering subtle logic errors in protocol handling.
Hypothesis integrates seamlessly with \texttt{pytest} and uses the \texttt{@given} decorator to specify input generation strategies. For example, given the \gls{asn1} structure defined in the \gls{sgp22} specification for the \texttt{GetProfileInfo} function:
Hypothesis integrates seamlessly with \texttt{pytest} and uses the \texttt{@given} decorator to specify input generation strategies. For example, given the \gls{asn1} structure defined in the SGP.22 specification for the \texttt{GetProfileInfo} function:
\begin{lstlisting}[caption={ASN.1 definition of the ProfileInfoListRequest}]
ProfileInfoListRequest ::= [45] SEQUENCE {
@@ -557,10 +559,10 @@ Specifically, we implemented fuzzing tests for the following functions:
\end{itemize}
\paragraph{Fuzzing Lifecycle}
Each fuzzing test class is executed under a shared fixture. During the \texttt{setUpClass} phase, a \gls{pcsc} link is initialized, and the \gls{euicc} is prepared (e.g., by installing a test profile) to ensure the preconditions for each function are met. After executing the class's test suite, the \texttt{eUICCMemoryReset} function is called with all reset options enabled to restore a clean state. All leftover notifications are processed to leave the card in a consistent state for subsequent tests.
Each fuzzing test class is executed under a shared fixture. During the \texttt{setUpClass} phase, a PC/SC link is initialized, and the \gls{euicc} is prepared (e.g., by installing a test profile) to ensure the preconditions for each function are met. After executing the class's test suite, the \texttt{eUICCMemoryReset} function is called with all reset options enabled to restore a clean state. All leftover notifications are processed to leave the card in a consistent state for subsequent tests.
\paragraph{Error Classification}
According to the \gls{sgp22} specification, many functions may return a generic \texttt{UndefinedError} in response to unexpected or malformed input. In our implementation, exceptions raised by the \gls{euicc} that map to well-defined error codes (i.e., subclasses of \texttt{EuiccException}) are not treated as test failures. These represent handled errors indicating that the input was invalid but the card responded appropriately.
According to the SGP.22 specification, many functions may return a generic \texttt{UndefinedError} in response to unexpected or malformed input. In our implementation, exceptions raised by the \gls{euicc} that map to well-defined error codes (i.e., subclasses of \texttt{EuiccException}) are not treated as test failures. These represent handled errors indicating that the input was invalid but the card responded appropriately.
By contrast, when an \texttt{UndefinedError} is returned, we treat this as a potential indicator of an unhandled internal error or inconsistent implementation behavior. These cases are flagged for further investigation. Additionally, exceptions occurring outside the \gls{euicc}, such as Python \texttt{AssertionError}s or test harness failures, are treated as bugs in the testing infrastructure and are logged separately.
@@ -593,7 +595,7 @@ By combining property-based data generation with structural knowledge of \gls{as
% completly independet from library -> library does not depend on cli
While the implemented library provides a programmatic interface to the \gls{lpa} and \gls{euicc} operations, many usersespecially testers and engineersrequire a more accessible method for interacting with the system. For this reason, we provide a fully-featured \gls{cli} that exposes all major functionalities of the system, including \gls{apdu} tracing, \gls{lpa} operations, and fuzzing workflows.
While the implemented library provides a programmatic interface to the \gls{lpa} and \gls{euicc} operations, many users, especially testers and engineers, require a more accessible method for interacting with the system. For this reason, we provide a fully-featured \gls{cli} that exposes all major functionalities of the system, including \gls{apdu} tracing, \gls{lpa} operations, and fuzzing workflows.
The \gls{cli} is built using Pythons standard \texttt{argparse} module for argument parsing, extended with \texttt{argcomplete} to enable shell auto-completion. For improved readability and formatting of terminal output, the \texttt{rich} library is used. This combination allows for an interactive, user-friendly \gls{cli} with both developer ergonomics and production readiness in mind.
@@ -602,10 +604,10 @@ The CLI is organized around three core commands:
\begin{itemize}
\item \textbf{tracing} — Interfaces with the \texttt{simtrace2} device and the \gls{lpa} to capture \gls{apdu} traffic in real time. This functionality is discussed in detail in \cref{sec:tracing}.
\item \textbf{lpa} — Exposes \gls{euicc} communication features such as profile management, notification handling, and remote procedure execution via the \gls{cli}.
\item \textbf{fuzzing} — Wraps both \gls{apdu}-level and data-level fuzzing. Additionally, it provides a \texttt{compare} command to compare multiple trace recordings and highlight structural differences in \gls{json} format.
\item \textbf{fuzzing} — Wraps both \gls{apdu}-level and data-level fuzzing. Additionally, it provides a \texttt{compare} command to compare multiple trace recordings and highlight structural differences in JSON format.
\end{itemize}
Each of these commands is implemented in its respective subfolder (e.g., \texttt{tracing/}, \texttt{lpa/}, \texttt{fuzz/}). The modular structure of the \gls{cli} is shown in Figure~\ref{fig:cli_structure}, which illustrates how the subcommands map to the file and folder hierarchy of the project.
Each of these commands is implemented in its respective subfolder (e.g., \texttt{tracing/}, \texttt{lpa/}, \texttt{fuzz/}). The modular structure of the \gls{cli} is shown in \cref{fig:cli_structure}, which illustrates how the subcommands map to the file and folder hierarchy of the project.
\begin{figure}[h]
\centering
@@ -653,7 +655,7 @@ Each of these commands is implemented in its respective subfolder (e.g., \texttt
]
]
\end{forest}
\caption{CLI folder structure and modular separation of functionality}
\caption{\gls{cli} folder structure and modular separation of functionality}
\label{fig:cli_structure}
\end{figure}