We recently introduced a pySim.utils.build_construct() wrapper around
the raw call of the construct.build() method. So far, this wrapper
was only used from pySim.tlv, but let's also use it from
pySim.filesystem.
Basically, whenever we use parse_construct(), we should use
build_construct() as the inverse operation.
Change-Id: Ibfd61cd87edc72882aa66d6ff17861a3e918affb
The method build_select_path_to uses the internal file system tree model
to find the path to a given file. This works the same for applications
(ADF) as it works for normal files (EF/DF). However, an application can
be selected anytime from any location in the filesystem tree. There is
no need to select a specific path leading to that application first.
This means that if there is an ADF somewhere in the resulting
inter_path, we may clip everything before that ADF.
Related: OS#5418
Change-Id: I838a99bb47afc73b4274baecb04fff31abf7b2e2
An ADF may or may not support a file system. For example ADF.ARA-M does
not have any filesystem support, which means the SELECT we may use from
this ADF is limited and an can only select a different application. To
know about this in advance let's add a flag that we set when we
instantiate an ADF.
Change-Id: Ifd0f7c34164685ea18d8a746394e55416fa0aa66
Related: OS#5418
The method build_select_path_to chops off the first element of the
current path. This is done to prevent re-selection of the first file in
the current path.
Unfortunately chopping off the first element in the current path does
not work properly in a situation when the current path points to the MF.
This would chop off the first and last element in the list and the for
loop below would run 0 times.
To fix this, let's keep the first element and chop it off from the
resulting path.
Related: OS#5418
Change-Id: Ia521a7ac4c25fd3a2bc8edffdc45ec89ba4b16eb
In some cases, the specs do not specify an absolute record length.
Instead there may be only a minimum record length specified. The card
vendor may then chose to use larger record length at will. This usually
is no problem since the data is usually written from the left and the
remaining bytes are padded at the end (right side) of the data. However
in some rare cases (EF.MSISDN, see also 3GPP TS 51.011, section 10.5.5)
the data must be written right-aligned towards the physical record
length. This means that the data is padded from the left in this case.
To fix this: Let's add a "leftpad" flag to LinFixedEF, which we set to
true in those corner cases. The code that updates the record in
commands.py must then check this flag and padd the data accordingly.
Change-Id: I241d9fd656f9064a3ebb4e8e01a52b6b030f9923
Related: OS#5714
We have a strict "one CardProfile per card" rule. For a modern UICC
without legacy SIM support, that works great, as all applications
have AID and ADF and can hence be enumerated/detected that way.
However, in reality there are mostly UICC that have legacy SIM, GSM-R
or even CDMA support, all of which are not proper UICC applications
for historical reasons.
So instead of having hard-coded hacks in various places, let's introduce
the new concept of a CardProfileAddon. Every profile can have any
number of those. When building up the RuntimeState, we iterate over the
CardProfile addons, and probe which of those are actually on the card.
For those discovered, we add their files to the filesystem hierarchy.
Change-Id: I5866590b6d48f85eb889c9b1b8ab27936d2378b9
This was currently not handled in build_select_path_to(), resulting in
weird exceptions like 'Cannot determine path from MF(3f00) to MF(3f00)'
Change-Id: I41b9f047ee5dc6b91b487f370f011af994aaca04
In cmd2, the upstream authors decided to rename a method in 2.0.0
without providing a backwards compatibility wrapper. Let's add that
locally.
Change-Id: Iaa17b93db13ba330551799cce5f0388c78217224
Closes: OS#6071
Also accept ProtocolError in addition to SwMatchError in filesystem.py
when probing for applications
Change-Id: I82b50408328f8eaaee5c9e311c4620d20f930642
This fixes a regression introduced in Change-Id
I02d6942016dd0631b21d1fd301711c13cb27962b which added support for
different encoding/decoding of records by their record number.
Change-Id: I0c5fd21a96d2344bfd9551f31030eba0769636bf
In their infinite wisdom, the authors of the EIRENE FFFIS for GSM-R SIM
cards invented yet a new way of encoding data in SIM card files: The
first record of a file may be encoded differently than further records
of files.
Let's add the required infrastructure to pySim so that the encode and
decode methods for record-oriented files get passed in the current
record number.
Change-Id: I02d6942016dd0631b21d1fd301711c13cb27962b
Related: OS#5784
I didn't check the specs, but at least experience with real-world cards
(and modems) shows that it's not just permitted to select the immediate
parent DF, but all ancestors of the currently selected file.
So adjust the get_selectables() method to not just return the immediate
parent, but to recurse all the way up and report the FID of any ancestor
DF.
Change-Id: Ic9037aa9a13af6fb0c2c22b673aa4afa78575b49
All other get_selectables() understand a flag like 'FIDS' to request
only the hexadecimal FIDs and not the file names. However, the
CardEF.get_selectables() ignored those flags and unconditionally
returned the names.
Change-Id: Icdc37cae3eecd36d167da76c30224b9d48c844fd
The size should be a *tuple*. In reality we so far passed a set. The
problem with the set is that ordering is not guaranteed, and hence we
cannot assume the first and second item have meaning (minimum vs.
default record length).
Change-Id: I470f4e69c83cb2761861b3350bf8d49e31f4d957
As the documentation strings say: The size should be a *tuple*. In
reality we so far passed a set. The problem with the set is that
ordering is not guaranteed, and hence we cannot assume the first and
second item have meaning (minimum vs. default size).
While at it, use a type annotation to catch such bugs easily.
Change-Id: I553616f8c6c4aaa8f635b3d7d94e8e8f49ed5a56
Reduce all the copy+pasted '/'.join(path_list) constructs with
a method returning the formatted path string.
Change-Id: I5e9bfb425c3a3fade13ca4ccd2b891a0c21ed56d
cards can have multiple logical channels; each logical channel
has its own state of what is the current selected file + application.
Let's split the RuntimeState class into the global RuntimeState and the
per-lchan-specific RuntimeLchan class.
This code doesn't actually introduce any code that uses lchans other
than the basic logical channel (0), but just modifies the data model
to accomodate those in the future.
Change-Id: I7aa994b625467d4e46a2edd8123240b930305360
When using __str__ for a CardDF we would get "DF(DF.TELECOM)"
but when using it on CardADF we would get ADF(a0000000871002)"
instead of "ADF(ADF.USIM)". Let's fix that.
Change-Id: I5801a08bcc28cb222734af6d9ee835227f4fee69
As it is possible to select files relative to the currently selected
ADF, we should keep track of that.
Change-Id: I83c93fdcd23b1d3877644ef0bf72d330343fbbc7
We should first see if any of the files in the tree actually
require a service mapping before raising
ValueError('TODO: implement recursive service -> file mapping')
Change-Id: I9c339f0cac020e7eec7f4f840748040e5f77923d
he method probe_file returns the decoded FCP after it managed to
successfully probe the file. Lets also return the encoded FCP string, as
it is needed by the caller.
Change-Id: Ia5659e106fb0d6fb8b77506a10eba309e764723e
These commands can be used to decode a user-provided hex-string,
instead of decoding the data read from the file. This is useful
for quickly manually decoding some values read from other locations,
such as e.g. copy+pasted from a eSIM profile in ASN.1 value notation.
Change-Id: I81f73bce2c26e3e5dfc7538d223bb2d2483c7fa0
The FCP template provides us a lot of context, like the permissions of
a given file. Let's make it part of the 'export' output, both in raw
and in decoded form.
Change-Id: I05f17bbebd7a9b3535204b821900851a5f66e88f
Closes: OS#5457
This adds support for creating/deleting and terminating files,
as well as support for permanent card termination.
Change-Id: I5b1ffb1334afa18d62beb642268066a30deb7ea6
With this patch applied, users can directly enter commands like
select DF.GSM/EF.IMSI or
select ADF.USIM/DF.5GS/EF.5GAUTHKEYS
This feature doesn't have tabl completion, so it's mostly useful
for when you know what to select, or for use within scripts.
Change-Id: I681a132eb2df4b2aba4c2ccbdd21c6d5b88443e3
We must not only consider files in the current directory (ADF.USIM)
but also in its sub-directories. This requires us to be able to
determine the path we need to traverse between the currently selected
file (EF.UST) and the respective file in some other directory,
which is implemented via CardFile.build_select_path_to().
Change-Id: I61797fefa9dafa36a8a62c11aa2cfaeecb015740
We had service annotations only for ADF.USIM so far, but not for
the related sub-directories.
Change-Id: Iaa56a26ba53eaf18fce14845ae07a27c52a2c58a
Note: The code doesn't make use of them in any reasonable way yet!
This can be populated by card profiles with the SST/IST/UST service
that is associated with the file.
Change-Id: I3b3f74b691368fa09967ecb377a9f7a6d8af7869
This happens e.g. when selecting the ARA-M applet on sysmoISIM-SJA2:
pySIM-shell (MF)> select ADF.ARA-M
-> 00a4040409 a00000015141434c00
<- 9000:
Traceback (most recent call last):
File "/space/home/laforge/.local/lib/python3.9/site-packages/cmd2/cmd2.py", line 2064, in onecmd_plus_hooks
stop = self.onecmd(statement, add_to_history=add_to_history)
File "/space/home/laforge/.local/lib/python3.9/site-packages/cmd2/cmd2.py", line 2494, in onecmd
stop = func(statement)
File "/space/home/laforge/projects/git/pysim/./pySim-shell.py", line 750, in do_select
fcp_dec = self._cmd.rs.select(path, self._cmd)
File "/space/home/laforge/projects/git/pysim/pySim/filesystem.py", line 1314, in select
select_resp = f.decode_select_response(data)
File "/space/home/laforge/projects/git/pysim/pySim/filesystem.py", line 193, in decode_select_response
return self.parent.decode_select_response(data_hex)
File "/space/home/laforge/projects/git/pysim/pySim/filesystem.py", line 378, in decode_select_response
return profile.decode_select_response(data_hex)
File "/space/home/laforge/projects/git/pysim/pySim/ts_102_221.py", line 796, in decode_select_response
t.from_tlv(h2b(resp_hex))
File "/space/home/laforge/projects/git/pysim/pySim/tlv.py", line 231, in from_tlv
(rawtag, remainder) = self.__class__._parse_tag_raw(do)
File "/space/home/laforge/projects/git/pysim/pySim/tlv.py", line 258, in _parse_tag_raw
return bertlv_parse_tag_raw(do)
File "/space/home/laforge/projects/git/pysim/pySim/utils.py", line 208, in bertlv_parse_tag_raw
if binary[0] == 0xff and len(binary) == 1 or binary[0] == 0xff and binary[1] == 0xff:
IndexError: bytearray index out of range
EXCEPTION of type 'IndexError' occurred with message: 'bytearray index out of range'
Change-Id: I910e6deba27d1483dff1e986c89f1a1b2165f49b
We had a mixture of tab and 4space based indenting, which is a bad
idea. 4space is the standard in python, so convert all our code to
that. The result unfortuantely still shoed even more inconsistencies,
so I've decided to run autopep8 on the entire code base.
Change-Id: I4a4b1b444a2f43fab05fc5d2c8a7dd6ddecb5f07
As we've seen in recent patches, this has been a source of bugs, so
let's be tolerant and deal with both.
Change-Id: I0a5ec2a860104ffe4524c647105a42505ac394d6
When probing applications on a card by running select_adf_by_aid()
SwMatchError exceptions indicating the non exsistance of that
application on the card should be ignored.
Change-Id: I3aa7deaf46bdf352a201c3089b3714405a06f281
When printing applications found by probing for a specific AID, then the
wrong variable is used to print the AID.
Change-Id: I3d5ec28e46fe00c0d793a1d9ef0a0e0900649a4d
A profile can cover lots of different applications. Those applications
may not exist on all card models. To exclude applications that are not
installed on the particular card EF.DIR is evaluated. However, there may
be applications that are not registered in EF.DIR but supported by the
profile. To cover those as well, lets try to select the applications we
do not see in EF.DIR. If selecting works we know that the application
exists on the card and we can include them in the RuntimeState.
Change-Id: I3fa77a68664fe50d690a18adfb1ae1a88a189827
UICC and old SIM cards can be difficult to tell apart without prior
knowledge of the card. The ATR won't tell if the card is UICC or not.
The only remaining option is to try out if the card is able to handle
UICC APDUs. The same is true for 2G SIM cards. It is not guranteed that
every UICC card will have 2G functionality.
Lets add functionality to match a profile to the currently plugged card
by actively probing it.
Lets also add another profile to distinguish between UICC-only cards and
UICC cards that include SIM functionality.
Change-Id: If090d32551145f75c644657b90085a3ef5bfa691
Related: OS#5274
The table that holds the status word descriptions is initialized as an
empty list '[]'. This is not correct since the interpret_sw method
processes this data as dictionary, so lets initialize the sw member with
an empty dict '{}' when not status word description is given.
Change-Id: I3cae83f0f6ab274546991ecd14425f094b2816b2
Related: OS#5274
The class byte and the select control bytes are different for SIM cards
and UICC cards. Lets define those parameters in the card profile, so
that we always get the correct parameters depending on which profile we
use.
Change-Id: I2d175e28bd748a4871b1373273b3a9be9ae8c4d0
Related: OS#5274
When the runtime state is created there is already some interaction with
the card. Lets make sure that the card is in a defined state when we
leave the constructor of the RuntimeState.
Change-Id: I986204964903069bcce781afdbf3c5d26682b749
Related: OS#5274
When the profile does not define any ADFs, then do not try to read any
AIDs. This is the case for old non UICC SIMs for example.
Change-Id: I8cfbee1d23e9f99461fa5f4fbf92c1a0929c50bf
Related: OS#5274
There are some problems with the usage of decode_select_response. At the
moment the ADF files overload the related method to provide decoding of
the select responses as per 3gpp TS 102 221. However, this also means
that the decoder is only available under ADF.USIM and ADF.ISIM. DF.GSM
and DF.TELECOM also overload the decoder method, just like an ADF would
do. This decoding method is then implemented as per 3gpp TS 51 011.
Since this a a problem on UICCs, the method detects the magic byte 0x62
that can be found at the beginning on every select response of an UICC
to defer to the TS 102 221 decoding method. TS 51 011 defines the first
two bytes of the select response as RFU. This at least problematic.
To solve this there should be a default method for
decode_select_response in the profile, which can be used if no file
overloads it with a specific decoder. ADFs use specific decoders, but
everything else should use the default decoder. When we deal with an
UICC, we expect the select response to be consistantly conform to TS
102 221, if we deal with a clasic sim we expect responses as per TS 51
011 only.
Since it is still possible to replace the select response decoder we
still have the opportunity to have custom select response in cartain
DFs and ADFs should we need them.
Change-Id: I95e33ec1755727dc9bbbc6016ce2d99a9e66f214
Related: OS#5274