91 Commits

Author SHA1 Message Date
Vadim Yanitskiy
a297cdba73 ModemATCommandLink: fix SyntaxWarning: invalid escape sequence '\+'
Change-Id: If8de5299a4dc5a8525ef6657213db95d30e3c83b
Fixes: OS#6948
2026-02-09 12:44:41 +00:00
Philipp Maier
a4895702d7 transport/init: use PySimLogger to print messages
The module still uses print to output information. Let's replace
those print calls with the more modern PySimLogger method calls.

Change-Id: I2e2ec2b84f3b84dbd8a029ae9bb64b7a96ddbde3
2026-01-28 12:19:54 +01:00
Philipp Maier
eda6182edd transport/init/cosmetic: move copryight header to the top
The copyright header seems to be misplaced, let's move it to the top.

Change-Id: I8358cca3bc9adb5a186a8b38a3bd90d7aec60d5c
2026-01-06 15:00:49 +01: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
Harald Welte
701e011e14 [cosmetic] pySim.transport: Fix spelling/typos in comment
Change-Id: Ia20cc2439bf00c1b6479f36c05514945ac4faf71
2025-03-28 09:13:11 +01:00
Philipp Maier
edcd62435d pySim/transport: add abstract get_atr method to LinkBase
The implementations that inheret from the LinkBase class are expected to
implement a get_atr method. This method is mandatory, since it is one of
the most basic functionalities of pySim to display an ATR. Also the ATR
is sometimes needed to distinguish between different card models.

The modem_atcmd and calypso implementation completely lack the get_atr
method. Apparantly it is not possible to get an ATR in those
environments, so lets add a dummy method there.

Related: OS#6322
Change-Id: I4fc020ca45658af78e495a5c1b985213f83cbb50
2025-01-29 13:35:44 +01: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
852eff54df pySim/transport add support for T=1 protocol and fix APDU/TPDU layer conflicts
ETSI TS 102 221, section 7.3 specifies that UICCs (and eUICCs) may support two
different transport protocols: T=0 or T=1 or both. The spec also says that the
terminal must support both protocols.

This patch adds the necessary functionality to support the T=1 protocol
alongside the T=0 protocol. However, this also means that we have to sharpen
the lines between APDUs and TPDUs.

As this patch also touches the low level interface to readers it was also
manually tested with a classic serial reader. Calypso and AT command readers
were not tested.

Change-Id: I8b56d7804a2b4c392f43f8540e0b6e70001a8970
Related: OS#6367
2024-11-19 10:56:26 +01:00
Harald Welte
2fe9b6a3e9 pySim.transport: Also trace card reset events in ApduTracer
Change-Id: Ia46b65124520eb2b8015dfa3f0a135b497668b92
2024-09-10 20:37:56 +02:00
Harald Welte
241d65db12 pySim.transport: Add support for generic stdout apdu tracer
Any program using argparse_add_reader_args() will get a new
long-opt '--apdu-trace' which enables a raw APDU trace to the console.

Change-Id: I4bc3d2e023ba360f07f024d7b661a93322f87530
2024-09-07 14:43:58 +02:00
Harald Welte
726097e51f transport: define TERMINAL RESPONSE content within ProactiveHandler
So far the core proactive handling code would always generate a positive
response, with no way for the ProactiveHandler call-back to influence
that or to include additional IEs/TLVs.

Let's change that.

Change-Id: Ic772b3383533f845689ac97ad03fcf67cf59c208
2024-09-05 11:30:53 +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
Harald Welte
c805f00bff transport: Implement treatment of 62xx and 63xx warning/error responses
TS 102 221 specifies that (in case of a class 4 command) and as SW
62xx or 63xx, we should send a GET RESPONSE just like in the 61xx
case in order to get the respective response.

As we don't really know if it's a case1/2/3/4 command in the
pySim.transport, let's always send the GET RESPONSE in case SW 62xx or
63xx are received.  It shouldn't hurt - in the worst case there's no
response available...

Change-Id: Ibb1398194a16fc1f1f9bc46af6c66fb6575240cd
2024-07-13 23:09:02 +02:00
Harald Welte
b865d383aa pySim.transport: Fix proactive_handler from_dict() calls
Change-Id: I2aa19ef6a19085d77c1b4f2d434a01ee241bd9a8
2024-07-13 23:04:20 +02:00
Oliver Smith
56264669a7 pcsc: don't assume opts.pcsc_shared is present
Fixes running contrib/sim-rest-server.py:
  builtins.AttributeError: 'Namespace' object has no attribute 'pcsc_shared'

Change-Id: I864f65849c5d43cf7c73e60f1935afdf4273f696
2024-05-24 20:23:01 +00:00
Harald Welte
24a7f168bd pcsc: open reader/card in EXCLUSIVE mode by default
There was a support request hinting that other applications
concurrently accessed the SIM and were messing up the card state while
pySim-shell was running.

Let's avoid such situations by opening the card/reader in EXCLUSIVE mode
by default.  If somebody really has a special use case, they can now add
the --pcsc-shared flag to restore the legacy behavior (SHARED mode).

Change-Id: I90d887714b559a4604708d3c6dd23b5e05f40576
2024-03-15 20:33:09 +00:00
Harald Welte
49d69335b2 pylint: transport/__init__.py
pySim/transport/__init__.py:139:0: C0325: Unnecessary parens after 'if' keyword (superfluous-parens)

Change-Id: Ibeeb7d6fde40bb37774bbd09ad185203ac7bcb48
2024-02-05 09:52:46 +01:00
Harald Welte
fdaefd9a8a pylint: transport/serial.py
pySim/transport/serial.py:54:0: C0325: Unnecessary parens after 'if' keyword (superfluous-parens)
pySim/transport/serial.py:89:0: C0325: Unnecessary parens after 'if' keyword (superfluous-parens)
pySim/transport/serial.py:225:0: C0325: Unnecessary parens after 'while' keyword (superfluous-parens)
pySim/transport/serial.py:63:12: R1705: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it (no-else-return)
pySim/transport/serial.py:106:8: R1720: Unnecessary "elif" after "raise", remove the leading "el" from "elif" (no-else-raise)
pySim/transport/serial.py:124:12: W0707: Consider explicitly re-raising using 'except Exception as exc' and 'raise ValueError('Invalid reset pin %s' % self._rst_pin) from exc' (raise-missing-from)
pySim/transport/serial.py:204:12: R1723: Unnecessary "elif" after "break", remove the leading "el" from "elif" (no-else-break)
pySim/transport/serial.py:20:0: C0411: standard import "import time" should be placed before "import serial" (wrong-import-order)
pySim/transport/serial.py:21:0: C0411: standard import "import os" should be placed before "import serial" (wrong-import-order)
pySim/transport/serial.py:22:0: C0411: standard import "import argparse" should be placed before "import serial" (wrong-import-order)
pySim/transport/serial.py:23:0: C0411: standard import "from typing import Optional" should be placed before "import serial" (wrong-import-order)

Change-Id: I82ef12492615a18a13cbdecf0371b3a5d02bbd5c
2024-02-05 09:52:40 +01:00
Harald Welte
7781c70c09 pylint: transport/pcsc.py
pySim/transport/pcsc.py:26:0: W0404: Reimport 'CardConnectionException' (imported line 26) (reimported)
pySim/transport/pcsc.py:60:4: R1711: Useless return at end of function or method (useless-return)
pySim/transport/pcsc.py:74:12: W0707: Consider explicitly re-raising using 'except CardRequestTimeoutException as exc' and 'raise NoCardError() from exc' (raise-missing-from)
pySim/transport/pcsc.py:86:12: W0707: Consider explicitly re-raising using 'except CardConnectionException as exc' and 'raise ProtocolError() from exc' (raise-missing-from)
pySim/transport/pcsc.py:88:12: W0707: Consider explicitly re-raising using 'except NoCardException as exc' and 'raise NoCardError() from exc' (raise-missing-from)
pySim/transport/pcsc.py:22:0: W0611: Unused Union imported from typing (unused-import)

Change-Id: I0ef440d8825300d6efb8959a67da095ab5623f9c
2024-02-05 09:52:29 +01:00
Harald Welte
181becb676 pylint: transport/modem_atcmd.py
pySim/transport/modem_atcmd.py:70:0: C0325: Unnecessary parens after 'assert' keyword (superfluous-parens)
pySim/transport/modem_atcmd.py:28:0: W0401: Wildcard import pySim.exceptions (wildcard-import)
pySim/transport/modem_atcmd.py:60:22: C0123: Use isinstance() rather than type() for a typecheck. (unidiomatic-typecheck)
pySim/transport/modem_atcmd.py:72:12: W0707: Consider explicitly re-raising using 'except Exception as exc' and 'raise ReaderError('Failed to send AT command: %s' % cmd) from exc' (raise-missing-from)
pySim/transport/modem_atcmd.py:120:12: R1705: Unnecessary "elif" after "return", remove the leading "el" from "elif" (no-else-return)
pySim/transport/modem_atcmd.py:138:8: W1201: Use lazy % formatting in logging functions (logging-not-lazy)
pySim/transport/modem_atcmd.py:170:12: W0707: Consider explicitly re-raising using 'except Exception as exc' and 'raise ReaderError('Failed to parse response from modem: %s' % rsp) from exc' (raise-missing-from)
pySim/transport/modem_atcmd.py:168:13: W0612: Unused variable 'rsp_pdu_len' (unused-variable)
pySim/transport/modem_atcmd.py:21:0: C0411: standard import "import time" should be placed before "import serial" (wrong-import-order)
pySim/transport/modem_atcmd.py:22:0: C0411: standard import "import re" should be placed before "import serial" (wrong-import-order)
pySim/transport/modem_atcmd.py:23:0: C0411: standard import "import argparse" should be placed before "import serial" (wrong-import-order)
pySim/transport/modem_atcmd.py:24:0: C0411: standard import "from typing import Optional" should be placed before "import serial" (wrong-import-order)
pySim/transport/modem_atcmd.py:28:0: W0614: Unused import(s) NoCardError and SwMatchError from wildcard import of pySim.exceptions (unused-wildcard-import)

Change-Id: I2c8994eabd973b65132af1030429b1021d0c20df
2024-02-05 09:52:24 +01:00
Harald Welte
c4d80870e8 pylint: transport/calypso.py
pySim/transport/calypso.py:27:0: W0401: Wildcard import pySim.exceptions (wildcard-import)
pySim/transport/calypso.py:61:23: W0622: Redefining built-in 'type' (redefined-builtin)
pySim/transport/calypso.py:62:8: R1725: Consider using Python 3 style super() without arguments (super-with-arguments)
pySim/transport/calypso.py:73:8: R1725: Consider using Python 3 style super() without arguments (super-with-arguments)
pySim/transport/calypso.py:27:0: W0614: Unused import(s) NoCardError and SwMatchError from wildcard import of pySim.exceptions (unused-wildcard-import)

Change-Id: I6b10d5f3370c00b07288300b537c6f0e17c84a87
2024-02-05 09:52:17 +01:00
Harald Welte
eecef54eee commands.py: Wrap the transport send_apdu* methods
Let's not have higher level code directly call the transports send_apdu*
methods.  We do this as a precursor to introducing secure channel
support, where the secure channel driver would add MAC and/or encrypt
APDUs before they are sent to the transport.

Change-Id: I1b870140959aa8241cda2246e74576390123cb2d
2024-02-01 12:06:07 +01:00
Harald Welte
0ecbf63a02 transport: Extend the documentation for each transport driver
This driver description we add to the code is automatically added to the
respective user manual sections.

Change-Id: I8807bfb11f43b167f1321d556e09ec5234fff629
2023-12-21 12:33:12 +01:00
Harald Welte
baec4e9c81 transport: Move printing of reader number/name to generic code
Let's avoid copy+pasting print statements everywhere.  The instances
do already have a __str__ method for the purpose of printing their name in a
generic way.

Change-Id: I663a9ea69bf7e7aaa6502896b6a71ef692f8d844
2023-12-21 12:33:12 +01:00
Harald Welte
ad002797e2 transport/pcsc: Allow opening PC/SC readers by a regex of their name
Opening PC/SC readers by index/number is very error-prone as the order
is never deterministic in any system with multiple (hot-plugged, USB)
readers.  Instead, let's offer the alternative of specifying a regular
expression to match the reader name (similar to remsim-bankd).

Change-Id: I983f19c6741904c1adf27749c9801b44a03a5d78
2023-12-21 12:33:12 +01:00
Harald Welte
0f177c1d29 transport: Pass argparse.Namespace directly into transport classes
It's odd that the individual transport driver specifies their argparse
options but then the core transport part evaluates them individually.
This means we cannot add new options within a transport.

Let's pass the Namespace instance into the constructor of the
specific transport to improve this.

Change-Id: Ib977007dd605ec9a9c09a3d143d2c2308991a12c
2023-12-21 11:31:57 +00:00
Harald Welte
4e02436dba perform multiple GET RESPONSE cycles if more data is available
So far we implemented only one round of "Send the APDU, get SW=61xx,
call GET RESPONSE".  This permitted us to receive only data up to 256
bytes.

Let's extend that to doing multiple rounds, concatenating the result.
This allows us to obtain arbitrary-length data from the card.

See Annex C.1 of ETSI TS 102 221 for examples showing multiple 61xx
iterations.

Change-Id: Ib17da655aa0b0eb203c29dc92690c81bd1300778
Closes: OS#6287
2023-12-04 21:38:50 +01:00
Harald Welte
2d44f03af2 transport: Log it explicitly if user doesn't specify a reader
Change-Id: I37e9d62fabf237ece7e49d8f2253c606999d3d02
2023-11-04 15:48:55 +00:00
Philipp Maier
4af63dc760 transport: print reader device/number on init
When we initialize the reader, we currently tell only which type of
interface we are using, but we do not print the reader number or the
device path.

Let's extend the messages so that the path is printed. To prevent
problems with integration-tests, let's also add an environment variable
that we can use to detect when pySim runs inside a integration-test.

Related: OS#6210
Change-Id: Ibe296d51885b1ef5f9c9ecaf1d28da52014dcc4b
2023-10-26 15:17:07 +00:00
Philipp Maier
8c82378bfd transport: move argument parser setup into concrete classes
The argument parser is set up globally for all LinkBase objects in
__init__.py. Since we tend to have only platform independed code in
__init__.py, we should move the argument parser setup into the
specific LinkBase classes.

Related: OS#6210
Change-Id: I22c32aa81ca0588e3314c3ff4546f6e5092c11df
2023-10-24 19:28:34 +00:00
Philipp Maier
3077343739 transport: move init message into concrete classes
In in the module __init__.py we print an init message (which type of
LinkBase class is providing the SimLink). However in __init__.py we tend
to have only platform independed code but the message string can already
be categorized as platform depened. Let's put the init message into the
constructor of the concrete classes of LinkBase.

Related: OS#6210
Change-Id: I0a6dd7deb79a5f3e42b29094a1cf2535075fa430
2023-10-24 19:28:34 +00:00
Philipp Maier
af4e5bb18c transport: do not catch exceptions in init_reader
We currently catch any exceptions that may occur when the card reader is
initialized. Then we print the exception string or the exception type
when no string is available. However, a failure during the reader
initialization is usually a severe problem, so a traceback would provde
a lot of helpful information to debug the issue. So lets not catch any
exceptions at this level so that we get the full backtrace.

Related: OS#6210
Change-Id: I4c4807576fe63cf71a7d33b243a3f8fea0b7ff23
2023-10-16 14:36:02 +02:00
Philipp Maier
58e89eb15a transport: add return type annotation to method __str__
The abstract class LinkBase has no return type annotation on its
__str__ method.

Related: OS#6210
Change-Id: I26d3d2714708dbe957704b60d17ba2afa325b2c4
2023-10-10 12:06:57 +02:00
Philipp Maier
6bfa8a8533 pySim-shell: print device info in case an exception occurs
When an exception occurs while initializing or handling the card we
print a traceback, but we do not print any info that allows us to
identify the device that was involved when the exception occurred. Let's
include the device path or number in the error message before we print
the traceback.

In order to make it easier to print the device information, let's add a
__str__() method to all of our devices. This method shall return the
device number or path.

Related: OS#6210
Change-Id: I200463e692245da40ea6d5b609bfc0ca02d15bdb
2023-10-10 11:51:08 +02:00
Harald Welte
f9f8d7a294 pySim/transport: Use newly-defined ResTuple type
Let's use the newly-added ResTuple type annotation rather than
open-coding it everywhere.

Change-Id: I122589e8aec4bf66dc2e86d7602ebecb771dcb93
2023-07-11 08:42:12 +02:00
Harald Welte
ab6897c4cd pySim/transport: More type annotations
Change-Id: I62e081271e3a579851a588a4ed7282017e56f852
2023-07-11 08:42:12 +02:00
Philipp Maier
621f78c943 serial: return a return code in reset_card()
The method reset_card does not return a return code, while the
coresponding pcsc implementation does return 1 on success.

Change-Id: I658dd6857580652696b4a77e7d6cfe5778f09eff
2023-06-07 10:00:52 +00:00
Tobias Engel
d70ac22618 modem_atcmd: raise ProtocolError instead of ReaderError on CME ERROR
Also accept ProtocolError in addition to SwMatchError in filesystem.py
when probing for applications

Change-Id: I82b50408328f8eaaee5c9e311c4620d20f930642
2023-06-02 15:35:43 +00:00
Christian Amsüss
59f3b1154f proactive: Send a Terminal Response automatically after a Fetch
Change-Id: I43bc994e7517b5907fb40a98d84797c54056c47d
2022-08-21 11:54:33 +00:00
Christian Amsüss
98552ef1bd proactive: Avoid clobbering the output of the command that triggered the FETCH
Change-Id: I2b794a5c5bc808b9703b4bc679c119341a0ed41c
2022-08-21 11:54:00 +00:00
Harald Welte
fd476b4d62 pySim.transport: Add mechanism for handling for CAT/USAT proactive cmds
This introduces an optional argument to the LinkBase class constructor,
where the application can pass an instance of a ProactiveHandler derived
class in order to handle the proactive commands that the LinkBase is
automatically fetching whenever the card indicates so.

Change-Id: I844504e2fc1b27ce4fc7ede20b2307e698baa0f6
2022-08-06 18:56:42 +02:00
Vadim Yanitskiy
04b5d9d7ab Py2 -> Py3: do not inherit classes from object
https://stackoverflow.com/questions/4015417/why-do-python-classes-inherit-object/45062077

Change-Id: I15003ba591510d68f3235f71526ad5d8a456088e
2022-07-07 03:05:30 +07:00
Vadim Yanitskiy
e6b86872ce transport/pcsc: throw ReaderError with a message
Before this patch:

  $ ./pySim-shell.py -p 0
  Card reader initialization failed with an exception of type:
  <class 'pySim.exceptions.ReaderError'>

after:

  $ ./pySim-shell.py -p 0
  Card reader initialization failed with exception:
  No reader found for number 0

Change-Id: Id08c4990857f7083a8d1cefc90ff85fc20ab6fef
2022-04-25 18:24:41 +03:00
Harald Welte
c91085e744 cosmetic: Switch to consistent four-spaces indent; run autopep8
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
2022-02-11 13:32:58 +01:00
Steve Markgraf
9c93cec32a transport/serial: fix for Python 3
Change-Id: I21e5a7ad4f623ed30681dce1ff819679b8714c5b
2022-01-25 01:14:44 +01:00
Harald Welte
846a898ee0 Add API + shell command for sending TERMINAL PROFILE to card
This allows a very first start to play with PROACTIVE SIM

Change-Id: Id8f23f7cebe0f9efce2c0ce4229509f35cd93d6a
2021-10-14 16:41:57 +02:00
Philipp Maier
8bf2125a19 transport/pcsc: make sure reader is disconnected
Make sure that a reader is disconnected before connecting it. This will
efectively prevent resource leakage in the lower PCSC layers when the
reader is connected multiple times during bulk provisioning

Change-Id: I266e56f2330da25c680a76f4c0ca630a38e1f61b
2021-09-22 16:21:16 +02:00
Philipp Maier
7328f10165 transport/init: print exception type if the execption has no string
There may be corner cases where an execption contains no error message.
In this case it might still be helpful to display the type of the
exeption calss to get at least an idea of what kind of error we are
dealing with.

Change-Id: I6e6b3acd17e40934050b9b088960a2f851120b26
2021-09-22 16:11:33 +02:00
Harald Welte
8dfd6d070f transport: Add support for SW 6Cxx
According to ETSI TS 102 221 Section 7.2.2.3.1 Table 7.1 the UICC
may respond with SW 6Cxx to tell us to re-issue the command with
a modified P3/Le.

Change-Id: Ia7e6202bbd0f61034a985ecf76d0542d959922ce
2021-05-25 22:23:00 +02:00
Harald Welte
2db843e7b5 transport/pcsc: Raise exception if reader number is out of range
Change-Id: I0acd6900feabb1cfa03b84f24903c6b746a6bdea
2021-05-22 09:32:39 +02:00