Update on Overleaf.

This commit is contained in:
nb72soza Bittner
2025-05-30 14:39:35 +00:00
committed by node
parent e12765bd4a
commit 2b898d829a
2 changed files with 127 additions and 1 deletions

View File

@@ -440,7 +440,132 @@ This differential testing method highlights edge-case inconsistencies across \gl
% oss-fuzz proposes multiple fuzzer for python implementation among them are the atheris fuzzer aswell as the python hypothesis framework
% atheris coverage guided fuzzer to fuzz python code directly -> not our use case
% python hypothesis: propery based testing library for python -> define input structure which needs to be passed into function -> hypothesis generates random input data that adheres to defined structure and tests for edge cases i.e. fuzzing
%
% Defining the fuzzing strategies
% hypothesis uses strategies to define the input structure
% add decorator `@given` with a strategy as argument
% strategy can be `strategy.integers()` to define that the first argument a1 of the function accepts integers Z
% this would result in the function beeing called with a1 having the values [0, -18588, -672780074, 32616, ...]
% hypothesis does not try every possible input value but resticts itself to edge cases when not adjusting the max_sample size
% when finding failing examples hypthesis may call the function a few more times to determine the most simple possible arguments that causes the functions to fail
% for out tests we only implement fuzzing strategies for the euicc side of the rsp since we rely on external infrastructure for the smdp+ and to not want to fuzz this part of the rsp -> could be seen as a ddos attack or just overhelm their servers with fuzzing traffic
% implemented fuzzing strategies for the following functions (restricted to functions which require arguments)
% ES10a: SetDefaultDpAddress
% ES10b: PrepareDownload, LoadBoundProfilePackage, AuthenticateServer
% ES10c: GetProfileInfo, EnableProfile, DisableProfile, DeleteProfile, eUICCMemoryReset, SetNickname
% Example implementation for the ES10c GetProfileInfo function
% @given(
% use_iccid=st.booleans(),
% profile_class=st.one_of(st.integers(min_value=-20, max_value=20), st.none()),
% tags=st.one_of(
% st.lists(
% st.text(
% min_size=2,
% max_size=8,
% alphabet=string.hexdigits,
% ).filter(lambda s: len(s) % 2 == 0),
% min_size=1,
% max_size=5,
% ),
% st.binary(max_size=8),
% ),
% )
% def test_get_profiles(
% self,
% use_iccid: bool,
% profile_class: str | None,
% tags: list[str] | bytes | None,
% ):
% ...
%
% Based on this ASN1 definition from the sg22 specs
% ProfileInfoListRequest ::= [45] SEQUENCE { -- Tag 'BF2D'
% searchCriteria [0] CHOICE {
% isdpAid [APPLICATION 15] OctetTo16, -- AID of the ISD-P, tag '4F'
% iccid Iccid, -- ICCID, tag '5A'
% profileClass [21] ProfileClass -- Tag '95'
% } OPTIONAL,
% tagList [APPLICATION 28] OCTET STRING OPTIONAL -- tag '5C'
% }
% for executing the fuzzer we use pytest: hypothesis integrates with pytest
% during the setUpClass process i.e before starting a group of fuzzing tests which are bundled into a class, we setup the card by iniating a pcsc link and perform various other steps that are need in order to fuzz the card i.e install a profile in order for the fuzzer to test the enable profile function.
% when finishing a class of fuzzing tests, we reset the euicc with the eUICCMemoryReset function were all reset options are set and process all leftover notifications -> leave the card in a clean state for other fuzzing tests
% SGP22 defines UndefinedError for some functions
% since the implementation is setup to exclude all EuiccExceptions -> if we receive an euiccException most of the time this means that the euicc handled the erorr internally and responseded with an error code
% this is still an error but one that is handled properly and does not mean that we discovered a bug but rather that the input was not valid
% on the other hand an undefined error is still handled be the euicc but could not be properly handled -> could mean that there is a potential bug in the implementation and we need to do some further investigation into to this particular function call
% -> euicc exceptions are ignored unless they are an UndefinedError
While APDU-level fuzzing (see \cref{subsec:apdu_fuzzing}) is useful for evaluating command behavior across different \textit{euicc} implementations, it suffers from the drawback that random mutations—particularly at the bit or byte level—often invalidate the structured ASN.1 encoding. As a result, many \gls{apdu} mutations are immediately rejected as malformed, limiting the coverage and effectiveness of the test campaign.
To address this limitation, we introduce a complementary \textit{data fuzzing} approach that operates at the semantic level by fuzzing the input arguments of high-level \gls{lpa} function calls. This enables us to maintain structural validity while still exercising a wide variety of edge cases in the data provided to the \gls{euicc}. Our implementation builds on property-based testing frameworks designed for Python, in particular the \texttt{hypothesis} library~\cite{maciver_hypothesis_2019}.
\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:
\begin{verbatim}
ProfileInfoListRequest ::= [45] SEQUENCE {
searchCriteria [0] CHOICE {
isdpAid [APPLICATION 15] OctetTo16,
iccid Iccid,
profileClass [21] ProfileClass
} OPTIONAL,
tagList [APPLICATION 28] OCTET STRING OPTIONAL
}
\end{verbatim}
We define the following Hypothesis test for the Python implementation of \texttt{GetProfileInfo}:
\begin{lstlisting}[language=Python, caption={Hypothesis-based fuzzing of \texttt{GetProfileInfo}}]
@given(
use_iccid=st.booleans(),
profile_class=st.one_of(st.integers(min_value=-20, max_value=20), st.none()),
tags=st.one_of(
st.lists(
st.text(
min_size=2,
max_size=8,
alphabet=string.hexdigits,
).filter(lambda s: len(s) % 2 == 0),
min_size=1,
max_size=5,
),
st.binary(max_size=8),
),
)
def test_get_profiles(self, use_iccid, profile_class, tags):
...
\end{lstlisting}
This approach preserves the semantics and structure of the expected \gls{asn1} types while still allowing a wide variety of edge cases to be exercised.
\paragraph{Implementation Scope}
Due to reliance on external infrastructure, such as the \gls{smdpp} server, our fuzzing campaign focuses exclusively on the \gls{euicc}-side of the \gls{rsp} protocol. Fuzzing requests directed at the \gls{smdpp} may lead to excessive traffic and could be misinterpreted as \gls{dos} attempts. Therefore, our tests are restricted to those functions in the ES10a, ES10b, and ES10c interfaces which accept structured input arguments and interact directly with the \gls{euicc}.
Specifically, we implemented fuzzing tests for the following functions:
\begin{itemize}
\item \textbf{ES10a:} \texttt{SetDefaultDpAddress}
\item \textbf{ES10b:} \texttt{PrepareDownload}, \texttt{LoadBoundProfilePackage}, \texttt{AuthenticateServer}
\item \textbf{ES10c:} \texttt{GetProfileInfo}, \texttt{EnableProfile}, \texttt{DisableProfile}, \texttt{DeleteProfile}, \texttt{eUICCMemoryReset}, \texttt{SetNickname}
\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.
\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.
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.
\paragraph{Conclusion}
By combining property-based data generation with structural knowledge of \gls{asn1} types, we extend the fuzzing coverage of the \gls{euicc} interface beyond what is possible with \gls{apdu} mutation alone. This enables the discovery of semantic inconsistencies and unhandled corner cases in \gls{euicc} implementations, especially when compared across different vendors during differential testing as shown in \cref{subsec:differential_testing}).
\section{CLI}
\label{sec:cli}