Commit Graph

38 Commits

Author SHA1 Message Date
Philipp Maier
eb7c5d85d0 runtime/cosmetic: add line break
The other source files have a line break between the character encoding
qualifier line and the python comment. Let's add a line break here
as well to maintain consistency.

Change-Id: Ied6b77eede748f1ddf6fde17c9b434fa4dd1114a
2026-01-06 15:03:53 +01:00
Harald Welte
572a81f2af pySim.runtime: Fix file selection by upper case hex FID
When trying to remove a file (e.g. DF.5G_ProSe, 5FF0),
there seems to be a case sensitive check when checking for the dict:
pySim/runtime.py: get_file_for_filename():

478          def get_file_for_filename(self, name: str):
479              """Get the related CardFile object for a specified filename."""
480              sels = self.selected_file.get_selectables()
481              return sels[name]

The dict sels contains 5ff0, but not 5FF0.
The type of argument name is str. So a case sensitive check will be used.

Change-Id: Idd0db1f4bbd3ee9eec20f5fd0f4371c2882950cd
Closes: OS#6898
2025-12-10 13:34:27 +00:00
Philipp Maier
f94f366cf9 runtime: check record/file size before write
When writing data to a transparent or linear fixed (record oriented)
and the data to write exceeds the record/file size, then the UICC will
respond with an error "6700: Checking errors - Wrong length"

In particular when the data is supplied as a JSON object and not as a
hex string, it may not be immediately obvious to the average user what
the problem actually is.

Let's check the record/file size before writing the data and raise an
exception in case the data excieeds the record/file size. Let's also
print an informative string message in case the data length is less
than the record/file size to make the user aware of unwritten bytes
at the end of a record/file.

Related: OS#6864
Change-Id: I7fa717d803ae79398d2c5daf92a7336be660c5ad
2025-10-28 13:39:35 +01:00
Philipp Maier
4429e1cc70 pySim-shell: add a logger class to centralize logging
In many sub modules we still use print() to occassionally print status
messages or warnings. This technically does not hurt, but it is an unclean
solution which we should replace with something more mature.

Let's use python's built in logging framework to create a static logger
class that fits our needs. To maintain compatibility let's also make sure
that the logger class will behave like a normal print() statement when no
configuration parameters are supplied by the API user.

To illustrate how the approach can be used in sub-modules, this patch
replaces the print statements in runtime.py. The other print statements
will the be fixed in follow-up patches.

Related: OS#6864
Change-Id: I187f117e7e1ccdb2a85dfdfb18e84bd7561704eb
2025-10-25 19:46:34 +00:00
Kian-Meng Ang
4ee99c18cd Fix typos
Found via `codespell -S tests -L ist,adn,ciph,ue,ot,readd,te,oce,tye`

Change-Id: I00a72e4f479dcef88f7d1058ce53edd0129d336a
2025-09-24 17:59:17 +00:00
Bjoern Riemer
4dddcf932a Make sure to select MF before probing for files/Addons
Change-Id: I685367c282f57a8856668a3172a9391a5bbcf2e2
2025-08-28 21:44:24 +00:00
Harald Welte
08ba187fd4 ATR: align get_atr() return value type
type annotations claimed the return type was Hexstr, but in reality
it was a list of integers.  Let's fix that.

Change-Id: I01b247dad40ec986cf199302f8e92d16848bd499
Closes: OS#6322
2025-01-29 13:00:53 +01:00
Philipp Maier
67c0fff15b pySim-shell: change Prompt character to "#" after "verify_adm"
Let's change the prompt from ">" to "#" when the user gains admin
privilegs using verify_adm.

Related: OS#6640
Change-Id: I957b9df7b5069b6fce5bf958c94e8ffda833c77f
2024-11-27 14:41:38 +01:00
Philipp Maier
efddffe015 filesystem: pass total_len to construct of when encoding file contents
In our construct models we frequently use a context parameter "total_len",
we also pass this parameter to construct when we decode files, but we
do not pass it when we generate files. This is a problem, because when
total_len is used in the construct model, this parameter must be known
also when decoding the file.

Let's make sure that the total_len is properly determined and and passed
to construct (via pyosmocom).

Related: OS#5714
Change-Id: I1b7a51594fbc5d9fe01132c39354a2fa88d53f9b
2024-09-27 18:17:19 +02:00
Philipp Maier
d5ddd04f33 pySim-shell: improve command "desc"
The "desc" command displays a string with a file description, let's also
display some size information as part of the description as well.

Related: OS#5714
Change-Id: I98e139ba2bf35df5524245cdd96f5c52cf09b986
2024-09-18 10:41:34 +02:00
Philipp Maier
9a6425b6f2 runtime: add new API functions to get the record len and file size
We have an API function to get the number of records, let's now also
add API functions to get the record length and the overall size of
the currently selected file.

Related: OS#5714
Change-Id: Ica7811c04161d8098b40c7219ed6b939df716cfd
2024-09-17 17:59:46 +00:00
Harald Welte
a3962b2076 Migrate over to using pyosmocom
We're creating a 'pyosmocom' pypi module which contains a number of core
Osmocom libraries / interfaces that are not specific to SIM card stuff
contained here.

The main modules moved in this initial step are pySim.tlv, pySim.utils
and pySim.construct. utils is split, not all of the contents is
unrelated to SIM Cards.  The other two are moved completely.

Change-Id: I4b63e45bcb0c9ba2424dacf85e0222aee735f411
2024-09-03 21:57:47 +02:00
Philipp Maier
89dbdbdccc runtime: fix get_file_by_name
The method get_file_by_name compares the selectable directly with the
given file name. This is not correct. The comparison should be with the
path element from the pathlist.

Related: OS#6092
Change-Id: Id2d0704678935d9b9e2f1aeb6eaccbff6fa9d429
2024-08-23 06:51:37 +00:00
Philipp Maier
12cc6821c4 runtime: add method to lookup a file by name without selecting it
In some cases it might come in handy to be able to lookup a random file
in the file system tree before actually selecting it. This would be
very useful in situations where we need to check the presence of the
file or if we need to check certain file attributes before performing
some task.

Related: OS#6092
Change-Id: I6b6121e749cea843163659e1a26bb3893c032e29
2024-08-08 15:37:35 +02:00
Philipp Maier
8597b64ee6 runtime: integrate escape route for applications without ADF support
the select_parent method in RuntimeLchan currently implements a way
to escape from an application that has no filesystem support. However,
this escape route can be integrated directly into the select_file
method. This will give us the benefit that it will work transparently
in all code locations.

(This also means we can get rid of the select_parent method again)

Related: OS#6120
Change-Id: Ie6f37d13af880d24a9c7a8a95cef436b603587c7
2024-08-08 15:37:35 +02:00
Harald Welte
2a963a7ac0 pySim.runtime: Be more verbose if incompatible method is called
Change-Id: I57190d50a63e0c22a8c5921e1348fae31b23e3d4
2024-07-27 10:30:26 +02:00
Philipp Maier
dff7bb0687 pySim-shell: clean up method calls in do_switch_channel
The function do_switch_channel method calls methods in RuntimeLchan
that should be private. There is also a code duplication in
RuntimeLchan that should be cleaned up.

Related: OS#6092
Change-Id: Ie5e5f45787abaaf032e1b49f51d447653cf2c996
2024-07-27 08:22:04 +00:00
Philipp Maier
4fefac78b8 pySim-shell: fix reset command
The reset command resets the card using the card object. This unfortunately
leaves the RuntimeState uninformed about the event. However, the RuntimeState
class also has a reset method that resets the card and the RuntimeState. Let's
use this reset method. Also fix this method so that it ensures that the SCP is
also no longer present.

Related: OS#6092
Change-Id: I1ad29c9e7ce7d80bebc92fa173ed7a44ee4c2998
2024-07-27 08:22:04 +00:00
Philipp Maier
7858f591fe pySim-shell: turn "ADF-escape-code" into an lchan method.
When we traverse the file system using the command "export" we will
also select all ADFs but not all ADFs may have UICC file system support.
This makes it impossible to exit those ADFs again. To exit anyway we
select an application with filesystem support first and then the parent
EF we wanted to select originally. This method may not only be useful
when traversing the filesystem, so let's put it into the RuntimeLchan
class and change it a little so that it would also work if the ADF in
question is an a sub DF.

Related: OS#6092
Change-Id: I72de51bc7519fafbcc71d829719a8af35d774342
2024-07-27 08:22:04 +00:00
Philipp Maier
c78ea1ffa6 runtime: rename get_file_for_selectable to get_file_for_filename
Let's rename get_file_for_selectable to get_file_for_filename so that it
is immediately clear what the method does.

Related: OS#6092
Change-Id: Ifed860814229857ad8b969e50849debbf5d8918f
2024-07-26 06:24:07 +00:00
Philipp Maier
2cca36e8fd runtime: add missing docstring
Change-Id: Iee2702c5326f1ec2a32c40b675ba1647387c40c8
Related: OS#6092
2024-07-26 06:24:07 +00:00
Harald Welte
f47433863e runtime: Introduce an 'identity' dict for things like ATR, ICCID, EID
This patch introduces the dict, as well as its first use for ATR storage

Change-Id: Ief5ceaf5afe82800e33da233573293527befd2f4
2024-05-26 11:01:29 +02:00
Harald Welte
356a6c0f99 pylint: runtime.py
pySim/runtime.py:272:0: C0325: Unnecessary parens after 'raise' keyword (superfluous-parens)
pySim/runtime.py:276:0: C0325: Unnecessary parens after 'if' keyword (superfluous-parens)
pySim/runtime.py:280:0: C0325: Unnecessary parens after 'if' keyword (superfluous-parens)
pySim/runtime.py:349:0: C0325: Unnecessary parens after 'raise' keyword (superfluous-parens)
pySim/runtime.py:549:0: C0305: Trailing newlines (trailing-newlines)
pySim/runtime.py:29:4: R1705: Unnecessary "elif" after "return", remove the leading "el" from "elif" (no-else-return)
pySim/runtime.py:119:16: W0612: Unused variable 'data' (unused-variable)
pySim/runtime.py:153:8: R1705: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it (no-else-return)
pySim/runtime.py:161:8: R1705: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it (no-else-return)
pySim/runtime.py:212:8: R1705: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it (no-else-return)
pySim/runtime.py:273:12: W0707: Consider explicitly re-raising using 'raise RuntimeError('%s: %s - %s' % (swm.sw_actual, k[0], k[1])) from swm' (raise-missing-from)
pySim/runtime.py:267:19: W0612: Unused variable 'sw' (unused-variable)
pySim/runtime.py:343:27: W0612: Unused variable 'sw' (unused-variable)
pySim/runtime.py:397:15: W0612: Unused variable 'sw' (unused-variable)
pySim/runtime.py:527:14: W0612: Unused variable 'sw' (unused-variable)
pySim/runtime.py:528:8: W0612: Unused variable 'tag' (unused-variable)
pySim/runtime.py:528:13: W0612: Unused variable 'length' (unused-variable)
pySim/runtime.py:528:28: W0612: Unused variable 'remainder' (unused-variable)

Change-Id: I2e164dbaa2070116bed3bac63b0fa5b8aa5b1331
2024-02-05 11:27:36 +01:00
Harald Welte
7f2263b4a0 runtime: Reset selected_file_fcp[_hex] if SELECT returns no data
In case SELECT doesn't return any response data, we must reset
the lchan.selected_file_fcp* members to None to prevent pySim-shell
preventing stale data from the previously selected file.

Change-Id: Ia04b8634e328e604e8df7e8d59b7fd532242d2ca
2024-01-27 21:47:13 +01:00
Philipp Maier
82cc7cc11a runtime: refactor file selection methods select and select_file
The implementation of the methods select and select_file of class
RuntimeLchan is a bit complex. We access the card directly in several
places which makes it difficult to track the state changes. We should
clean this up so that we call self.rs.card.select_adf_by_aid/
self.scc.select_file from a single place only.

This means that the method select uses the method select_file. This
results in a much cleaner implementation. We also should take care
that the important states that we track (selected_file, selected_adf,
etc.) are updated by a single private method. Since the update always
must happen after a select _select_post is a good place to do this.

Related: OS#5418
Change-Id: I9ae213f3b078983f3e6d4c11db38fdbe504c84f2
2023-12-13 12:47:36 +01:00
Philipp Maier
174fd32f17 runtime: explain how file probing works
We use a trick to probe a file (that does not exist in the local file
model yet). Let's explain further how that works, in particular why we
do not have to upate any state if probing fails.

Change-Id: I2a8af73654251d105af8de1c17da53dfa10dc669
Related: OS#5418
2023-12-13 09:02:30 +00:00
Philipp Maier
c038cccdd8 runtime: cosmetic: prnounce file reference data
One of the most important properties of the RuntimeLchan are the
selected_file/adf properties. Let's reformat the code so that those
properties are more pronounced.

Change-Id: I4aa028f66879b7d6c2a1cd102cda8d8ca5ff48b1
Related: OS#5418
2023-12-07 12:29:17 +01:00
Philipp Maier
e30456b07a runtime: explain why we may access the card object directly
When we are in the constructor of RuntimeState, we may/must access the
card object directly. Let's explain why, since it may not be immediately
obvious.

Change-Id: I01f74d5f021d46679d1c9fa83fb8753382b0f88f
Related: OS#5418
2023-12-07 12:28:57 +01:00
Philipp Maier
b8b61bf8af runtime: do not use the _scc object of the card object to select MF
The constructor of the RuntimeState object selects the MF befor it does
some other steps. However it does this through the _scc object of the
card object. This method is before we had lchan abstraction, so we
should now use the lchan object like in all other places.

Related: OS#5418
Change-Id: I9a751c0228c77077e3fabb50a9a68e4489e7151c
2023-12-07 12:28:39 +01:00
Philipp Maier
578cf12e73 runtime: fix tracking of selected_adf
The class property selected_adf is not updated in all locations where an
ADF is selected, this means that we may loose track of the currently
selected ADF in some locations

Change-Id: I4cc0c58ff887422b4f3954d35c8380ddc00baa1d
Related: OS#5418
2023-11-09 14:43:08 +00:00
Philipp Maier
1da8636c0f runtime: cosmetic: fix formatting of comment
Change-Id: I4e949a08c1bfab413b82e958a64404390e58148f
2023-10-31 17:25:51 +01:00
Harald Welte
6dd6f3e12c prevent SimCardCommands.select_adf_by_aid bypassing lchan
Now that pySim-shell is aware of logical channels and issues almost
all of its APDUs on the currently selected channel, we must also make
sure that ADF selection by AID (implemented by the CardBase class)
issues the SELECT on the respective logical channel.

Before this patch, SELECT ADF by AID would always be issued on the
primary logical channel (0), irrespective of the currently active
RuntimeLchan.

Change-Id: Idf05c297e6a2e24ca539408b8912e348c0782bb4
Related: OS#6230
2023-10-24 15:10:01 +02:00
Harald Welte
46255121e0 pySim-shell: Create + use per-RuntimeLchan SimCardCommands
This new approach will "fork" separate SimCardCommands instances
for each RuntimeLchan.  Higher-layer code should now always use the
RuntimeLchan.scc rather than the RuntimeState.card._scc in order to
make sure commands use the correct logical channel.

Change-Id: I13e2e871f2afc2460d9fd1cd566de42267c7d389
Related: OS#6230
2023-10-24 15:10:01 +02:00
Harald Welte
49acc06327 RuntimeState: Add type annotation for 'card' argument
Change-Id: I3c5138a918f7e45aabe3972883714d05ee704877
2023-10-21 21:47:04 +02:00
Philipp Maier
37e57e0c45 filesystem: add attribute "leftpad" to class LinFixedEF
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
2023-09-07 14:19:26 +02:00
Philipp Maier
d62182ca43 runtime: make sure applications are always listed in the same order
When we print the profile applications. which are not registered in
EF.DIR, we use python sets to subtract the applications which were part
of EF.DIR and hence already listed. Since we use sets the order may be
arbitrary. This is so far not a problem, since the output is meant to be
read by humans, but as soon as we try to use the output for unit-test
verifications we need a consistent order (sorted)

Related: OS#6094
Change-Id: Ie75613910aaba14c27420c52b6596ab080588273
2023-08-01 15:47:27 +02:00
Philipp Maier
92b9356ed2 runtime: fix lchan deletion in method reset
When we perform a reset while multiple channels are open (this is in
particular the case when parsing real world traces with pySim-trace). To
delete those channels during the reset we iterate over the dictionary
using the keys and delete the channels one by one. However, this must
not be done using the keys as index directly. Python will then throw an
exception: "RuntimeError: dictionary changed size during iteration".

Instead using the keys directly we should cast them into a list and then
using that list for the iteration.

Related: OS#6094
Change-Id: I430ef216cf847ffbde2809f492ee9ed9030343b6
2023-07-21 11:52:10 +02:00
Harald Welte
531894d386 move Runtime{State,Lchan} from pySim.filesystem to new pySim.runtime
Those two are really separate concepts, so let's keep them in separate
source code files.

Change-Id: I9ec54304dd8f4a4cba9487054a8eb8d265c2d340
2023-07-12 22:05:14 +02:00