Commit Graph

74 Commits

Author SHA1 Message Date
Harald Welte
d8c45dc07e pySim.esim.saip: Implement optimized file content encoding
Make sure we make use of the fill pattern when encoding file contents:
Only encode the differences to the fill pattern of the file, in order
to reduce the profile download size.

Change-Id: I61e4a5e04beba5c9092979fc546292d5ef3d7aad
2026-01-26 21:19:05 +01:00
Harald Welte
51da6263b7 Fix esim.saip.ProfileElementSequence.remove_naas_of_type
This method did not work at all at the moment, likely due to API churn
over time.  This change makes the following exception go away:

Traceback (most recent call last):
  File "projects/git/pysim/contrib/saip-tool.py", line 473, in <module>
    do_remove_naa(pes, opts)
    ~~~~~~~~~~~~~^^^^^^^^^^^
  File "projects/git/pysim/contrib/saip-tool.py", line 203, in do_remove_naa
    pes.remove_naas_of_type(naa)
    ~~~~~~~~~~~~~~~~~~~~~~~^^^^^
  File "projects/git/pysim/contrib/pySim/esim/saip/__init__.py", line 1748, in remove_naas_of_type
    if template in hdr.decoded['eUICC-Mandatory-GFSTEList']:
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "projects/git/pysim/contrib/pySim/esim/saip/oid.py", line 48, in __eq__
    return (self.intlist == other.intlist)
                            ^^^^^^^^^^^^^
AttributeError: 'str' object has no attribute 'intlist'

A subsequent patch should introduce unit tests to avoid such breakage in
the future.

Change-Id: I88d862d751198c3d1648ab7f11d6e6a8fdbc41c9
2026-01-20 09:50:03 +01:00
Alexander Couzens
8557ec86be saip: ProfileElementSD: call _post_decode() when instantiating with decoded argument
Otherwise self.keys is not generated from the given data and encoding will fail.

Change-Id: I3020f581a908fecc01d5d255ab5991ce1652e3ec
2026-01-17 21:52:38 +00:00
Alexander Couzens
2e7944cc98 saip: calculate the number of records for LF and CY
Some templates (e.g. for 5GS) define files which aren't completely defined.
5GS OPL5G: doesn't have a file size defined in the template,
but a record size.

Change-Id: I5ec1757d6852eb24d3662ec1c3fc88365e90a616
2026-01-14 00:21:33 +00:00
Alexander Couzens
1347d5ffa2 saip: rework file sizes for "half-defined" template files
Define the file size early if possible.
Some templates (e.g. for 5GS) define files which aren't completely defined.
Fixes the parsing for 5GS SUCI_Calc_Info which doesn't have a file size defined.

The saip-tool will other crash when reading a 5G enabled profile:
```
Traceback (most recent call last):
  File "./contrib/saip-tool.py", line 458, in <module>
    pes = ProfileElementSequence.from_der(f.read())
  File "pySim/esim/saip/__init__.py", line 1679, in from_der
    inst.parse_der(der)
    ~~~~~~~~~~~~~~^^^^^
  File "pySim/esim/saip/__init__.py", line 1552, in parse_der
    self.pe_list.append(ProfileElement.from_der(first_tlv, pe_sequence=self))
                        ~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "pySim/esim/saip/__init__.py", line 557, in from_der
    inst._post_decode()
    ~~~~~~~~~~~~~~~~~^^
  File "pySim/esim/saip/__init__.py", line 668, in _post_decode
    self.pe2files()
    ~~~~~~~~~~~~~^^
  File "pySim/esim/saip/__init__.py", line 655, in pe2files
    file = File(k, v, template.files_by_pename.get(k, None))
  File "pySim/esim/saip/__init__.py", line 133, in __init__
    self.from_tuples(l)
    ~~~~~~~~~~~~~~~~^^^
  File "pySim/esim/saip/__init__.py", line 358, in from_tuples
    self._body = self.file_content_from_tuples(l)
                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^
  File "pySim/esim/saip/__init__.py", line 393, in file_content_from_tuples
    stream.write(self.template.expand_default_value_pattern(self.file_size))
                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^
  File "pySim/esim/saip/templates.py", line 123, in expand_default_value_pattern
    raise ValueError("%s does not have a default length" % self)
ValueError: FileTemplate(EF.SUCI_Calc_Info) does not have a default length
```

Change-Id: I7c4a0914aef1049a416e6b091f23daab39a1dd9c
2026-01-14 00:21:33 +00:00
Harald Welte
097d565310 esim.saip: Better docstring about FsNode class
Change-Id: Id9d196e8d9b1d1b892ec50100b170d72d2c3910b
2026-01-06 21:10:29 +00:00
Harald Welte
a8ae89a041 pySim.esim.saip.ProfileElementSequence: Update type annotations
The type annotations didn't reflect reality in two cases.

Change-Id: Ib99c00a38bf009c63180b4a593d6cc796ff282d3
2026-01-06 21:10:19 +00:00
Harald Welte
c6fd1d314a esim.saip.FsProfileElement: Add file2pe() for single file conversion
We've had files2pe() for re-encoding all of the files, but let's add
a specific one for re-encoding only one of the files (such as commonly
needed during personalization)

Change-Id: I7b7f61aae6b7df6946dadf2f78fddf92995603ec
2025-12-23 20:57:01 +01:00
Harald Welte
11dfad88e6 pySim.esim.saip: Fix compatibility with pytohn < 3.11
In python up to 3.10, the byteorder argument of the int.to_bytes()
method was mandatory, even if the length of the target byte sequence
is 1 and there factually is no byteorder.

https://docs.python.org/3.10/library/stdtypes.html#int.to_bytes
vs
https://docs.python.org/3.11/library/stdtypes.html#int.to_bytes

See also: https://discourse.osmocom.org/t/assistance-required-with-saip-pysim-tool-error-while-adding-applets-to-exiting-upp-der/2413/2

Change-Id: I8ba29d42c8d7bf0a36772cc3370eff1f6afa879f
2025-12-14 13:58:34 +01:00
Harald Welte
c07ecbae52 pySim.esim.saip: Hex representation of SecurityDomainKey
Let's print the key_usage_qualifier in hexadecimal notation (more compact)

Change-Id: Ic9a92d53d73378eafca1760dd8351215bce1157a
2025-12-09 16:23:49 +00:00
Harald Welte
947154639c pySim.esim.saip.FsNodeADF: Fix __str__ method
It's quite common for a FsNodeADF to not have a df_name, so we need
to guard against that during stringification to avoid an exception.

Change-Id: I919d7c46575e0ebcdf3b979347a5cdd1a9feb294
2025-09-24 17:59:17 +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
Harald Welte
e37cdbcd3e docs: Better python doc-strings for better pySim.esim manual
Change-Id: I7be6264c665a2a25105681bb5e72d0f6715bbef8
2025-05-07 10:50:47 +02:00
Philipp Maier
d5da431fd4 saip-tool: add commandline option to edit mandatory services list
Change-Id: I120b98d4b0942c26674bc1365c5711101ec95235
2025-04-16 10:35:15 +02:00
Philipp Maier
1dea0f39dc saip-tool: add features to add, remove and inspect application PEs
The PE-Application object is used to provision JAVA-card applications
into an eUICC during profile installation. Let's extend the SAIP-tool
so that we are able to add, remove and inspect applications.

Change-Id: I41db96f2f0ccc29c1725a92215ce6b17d87b76ce
2025-04-14 11:01:24 +00:00
Philipp Maier
40e795a825 saip-tool: add ProfileElement class for application PE
The application profile element has no ProfileElement class yet, so
let's create a ProfileElementApplication class and move the existing
extract-apps code into a method of ProfileElementApplication.

Change-Id: Iaa43036d388fbf1714c53cab1fc21092c4667a21
2025-03-31 12:27:24 +02:00
Harald Welte
0bb8b44ea8 esim.saip.ProfileElementUSIM: Fix IMSI decode if [only] template based
In case the fileDescriptor of EF.IMSI is purely template based and only
the file content is given in the actual profile, we must pass a template
reference to the File() constructor before we can read the IMSI.

This fixes the following exception for some profiles:
	ValueError: File(ef-imsi): No fileDescriptor found in tuple, and none set by template before

Change-Id: I14157a7b62ccd9b5b42de9b8060f2ebc5f91ebb3
2024-11-23 15:43:12 +01:00
Harald Welte
9d7caef810 esim.saip.FsProfileElement: Add create_file() method
So far we mainly created File() instances when parsing existing
profiles.  However, sometimes we want to programmatically create Files
and we should offer a convenience helper to do so, rather than asking
API users to worry about low-level details.

Change-Id: I0817819af40f3d0dc0c3d2b91039c5748dd31ee2
2024-11-22 21:02:35 +01:00
Harald Welte
9ac4ff3229 esim.saip.File: Suppress encoding attributes that are like template
The point of the SAIP template mechanism is to reduce the size of the
encoded profile.  Therefore, our encoder in the to_fileDescriptor()
method should suppress generating attributes if their value is identical
to that of the template (if any).

Change-Id: I337ee6c7e882ec711bece17b7a0def9da36b0ad7
2024-11-22 21:00:47 +01:00
Harald Welte
0f1ffd20ef esim.saip.File: Proper ARR conversion of template (into) to file (bytes)
The encoding of the access rule reference is different in FileTemplate
vs File, let's make sure we properly convert it when instantiating a
File from a FileTemplate.

Change-Id: Ibb8afb85cc0006bc5c59230ebf28b2c0c1a8a8ed
2024-11-22 20:59:19 +01:00
Harald Welte
0516e4c47a esim.saip.File: Re-compute file_size when changing body
If the API user modifies the size of the body, we need to check if we
need to re-compute the file_size attribute which is later encoded into
the fileDescriptor.  The size obviously must be large enough to fit the
body.  Let's do this implicitly by introducing a setter for File.body

Change-Id: I1a908504b845b7c90f31294faf2a6e988bdd8049
2024-11-22 20:56:58 +01:00
Harald Welte
3442333760 esim.saip: New methods for inserting ProfileElement into sequence
ProfileElements.insert_after_pe() is a convenience method to insert
a new PE after an existing one in the sequence.  This is a frequent
task as there are strict ordering requirements in the SAIP format.

Change-Id: I4424926127b4867931c2157e9340bacd2682ff0c
2024-11-22 20:49:24 +01:00
Harald Welte
93237f4407 [cosmetic] esim.saip: Fix various typos in comments/docs/messages
Change-Id: I4fc603634a0f2b53e432a77f05e811a38ba065c2
2024-11-22 16:59:26 +01:00
Harald Welte
779092b0cd esim.saip: Fix computation of file content
When generating the file content (body), we need to proceed in the
following order:

1a) If FCP contains fillPattern/repeatPattern, compute file content from those

1b) If FCP doesn't contain fillPattern/repeatPattern but template
    exists, compute file content from template

2)  Apply any fillFileConten / fillFileOffset from the SAIP File on top
    of the above

Change-Id: I822bb5fbec11a3be35910a496af7168458fd949c
Closes: OS#6642
2024-11-22 16:03:58 +01:00
Harald Welte
6046102cbb esim.saip: Compute number of records from efFileSize and record_len
If we know the efFileSize and record_len, but Fcp doesn't contain
the number of records, we can simply compute it.

Change-Id: I0cc8e7241e37ee23df00c2622422904e7ccdca77
2024-11-22 16:01:58 +01:00
Harald Welte
118624d256 pySim.esim.saip: Treat "Readable and Updateable when deactivated" flag
There's a second flag hidden in the TS 102 222 "Special File
Information"; let's parse + re-encode it properly.

Change-Id: I7644d265f746c662b64f7156b3be08a01e3a97aa
Related: OS#6643
2024-11-22 16:01:58 +01:00
Harald Welte
599845394e esim.saip: Fix parsing/generating fillPattern + repeatPattern
So far we only thought of default filling coming from a template.
However, filling can happen from the Fcp, and we need to properly parse
and [re-]encode that information.

Change-Id: Iff339cbe841112a01c9c617f43b0e69df2521b51
Related: OS#6643
2024-11-22 16:01:25 +01:00
Harald Welte
b22bab0b20 pySim.esim.saip.ProfileElementGFM: Initialize 'fileManagementCMD'
When constructing a ProfileElmentGFM from scratch, initialize the
decoded['fileManagementCMD'], as it is a mandatory member during
ASN.1 encode.

Change-Id: Iaae99348d36b7f0c739daf039d6ea2305b7ca9db
2024-09-03 21:57:47 +02:00
Harald Welte
981220641d pySim.esim.saip.File: Turn file_size into a computed property
This way, we can use file_size for both record-oriented and transparent EF

Change-Id: Ib787cabe969202073a8c10042e200f3d2c29db73
2024-09-03 21:57:47 +02:00
Harald Welte
73dd3d0637 pySim.esim.saip: Add missing initialization of File.df_name
Change-Id: Iaf596a8914850ccae584c3b78dc7711db736ac80
2024-09-03 21:57:47 +02:00
Harald Welte
65cbe48953 pySim.esim.saip: Another naming irregularity.
The choice member is called df-5gprose but the header is called
'df-5g-prose-header' (note the '-' between '5g' and 'prose'). WTF.

Change-Id: I86004ac2e18a187c26c5e470344908512d21fb9e
2024-09-03 21:57:47 +02:00
Harald Welte
52735f3685 pySim.esim.saip: Fix weird DF names
Sometimes the struct member is called like df-telecom, but in other
cases it's called df-df-saip  with a double 'df' in front.  That makes
no sense, but we have to deal with it from our constructors...

Change-Id: If5e670441f03a47fa34e97a326909b24927c12f7
2024-09-03 21:57:47 +02: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
f807983a98 pySim.esim.saip: Add missing entry for 'rfm' to class4petype
Change-Id: I5fec2b026fc6a1197fc1e18d880ea6d10fd4a611
2024-08-27 14:23:40 +00:00
Harald Welte
c6f8457ff1 pySim.esim.saip: maintain a parsed fileystem hierarchy
With this change, the ProfileElementSequence object will maintain a
representation of the filesystem hierarchy of the eSIM profile.  Every
file that is added by a ProfileElement will add a FsNode into that tree,
and each FsNode will point to the File object for the respective file.

This allows us to find files by their path, as well as add files by
path.

Change-Id: I2caadc24b1087855f23f3c57cdf8dabbf81757c0
2024-08-23 06:51:07 +00:00
Harald Welte
cd22b9aee3 pySim.esim.saip.File: move away from stream for file content
Let's linearize the file content in a bytes member variable self.body.

Change-Id: I6cb23a3a644854abd3dfd3b50b586ce80da21353
2024-08-18 19:38:44 +02:00
Harald Welte
39613da6a7 pySim.esim.saip: Fix key used in FsProfileElement.files2pe
The self.files member is a dict.  Hence we should use those dict
keys when [re]building the decoded dict. The previous code ignored
it and re-constructed the key from File.pe_name - but that's not
always identical.

Change-Id: I0e6c97721fb1cfc6b5c21595d85bd374d485b573
2024-08-18 19:38:44 +02:00
Harald Welte
ab3e04fdb1 pySim.esim.saip: Fix typo in ProfileElementAKA.set_mapping() method
Change-Id: Icd1594c6c2a8536a4ab8d1fc698307f05f539bdb
2024-08-18 19:38:44 +02:00
Harald Welte
3a95fa12f6 pySim.esim.saip: Add some more docstring comments
Change-Id: I70cf2b4dff1952f581efa3b21211c542f43ce565
2024-08-18 19:38:44 +02:00
Harald Welte
b349149a88 pySim.esim.saip: Back-reference from ProfileElement to ProfileElementSequence
Store a back-reference to the PE-Sequence in the PE object; this is
neccessary for some upcoming patches, e.g. to determine the position in
the sequence, access the global filesystem hierarchy, etc.

Change-Id: I24b692e47e4dd0afb5a17b04d5e0251dded3d611
2024-08-18 19:38:44 +02:00
Harald Welte
3b30994ff0 pySim.esim.saip: pass up **kwargs from ProfileElement sub-class constructors
Change-Id: Ib2b7f6d7428d03e9a8c23af39a61f450096c12bc
2024-08-18 19:38:44 +02:00
Harald Welte
6a1e5eb4ee pySim.esim.saip: Move AKA specific post_dec + pre_enc to AKA subclass
Having AKA specific code in the generic ProfileElement base class dated
back to when we didn't have a ProfileElementAKA subclass.

Change-Id: Icd332183758b8ef20a77507b728f5e455698def0
2024-08-18 19:38:44 +02:00
Harald Welte
31c3c9a1e3 pySim.esim.saip: Refactor file size encoding into a method
Change-Id: I46b8cb81ef8cc1794c11b61e0adfb575f937b349
2024-08-18 19:38:44 +02:00
Harald Welte
6d495fb24d pySim.esim.saip: Improve File.from_template feature support
When populating a File from a FileTemplate, let's make sure we
* correctly treat the maximum file size for BER-TLV files
* respect the default value pattern / repeat pattern
* respect the high_update flag.

Change-Id: I3ba092e0893f53a18264dff5fa37b12ccd9bd47e
2024-08-18 19:38:44 +02:00
Harald Welte
d3a6bbc215 pySim.esim.saip: Add subcasses for EAP, DF.SNPN and DF.5G_ProSe
Change-Id: I8f29e72d387c66c99ceccffc9de23a68fd15dc46
2024-08-04 12:46:12 +02:00
Harald Welte
4fd3fa445c pySim.esim.saip: Add subclasses for gsm-access, phonebook, 5gs, saip
Those are all optional ProfileElements related to the USIM NAA.

Change-Id: I621cc3d2440babdc11b4b038f16acf418bbc88ad
2024-07-29 13:06:27 +02:00
Harald Welte
4f9ee0fa75 pySim.esim.saip: Refactor from_der() method to have class_for_petype()
Change-Id: I2e70dddb0b3adb41781e4db76de60bff2ae4fdb7
2024-07-29 13:06:27 +02:00
Harald Welte
3d6a712e8c Fix missing AIDs in pySim.saip templates
Change-Id: Ie02e2d27ece0fbd9719468c8d31febd1937468f8
2024-07-29 13:06:27 +02:00
Harald Welte
8b1060a30e Reference pySim.filesystem derived classes from SAIP templates
Change-Id: Ia1c810262f1cfa48dae192c7de620c7f0fb69c25
2024-07-29 13:06:27 +02:00
Harald Welte
e354ef7d05 pySim.esim.saip: Initial support for parsing GenericFileManagement
Change-Id: I4a92f5849158a59f6acca05121d38adc0a495906
2024-07-29 13:06:16 +02:00