Allow returning text/plain Content-Types as 'data' output argument.
So far, all the esim/http_json_api functions require a JSON response.
However, a specific vendor has a list function where the request is JSON
but the response is text/plain CSV data. Allow and return in a dict.
Change-Id: Iba6e4cef1048b376050a435a900c0f395655a790
By default, numeric_base = None, to indicate that there are no explicit
limitations on the number space.
For parameters that are definitely decimal, set numeric_base = 10.
For definitely hexadecimal, set numeric_base = 16.
Do the same for ConfigurableParameter as well as ParamSource, so callers
can match them up: if a parameter is numeric_base = 10, then omit
sources that are numeric_base = 16, and vice versa.
Change-Id: Ib0977bbdd9a85167be7eb46dd331fedd529dae01
This reverts commit I974cb6c393a2ed2248a6240c2722d157e9235c33
Now, finally, all SdKey classes have a unified logical naming scheme.
Change-Id: Ic185af4a903c2211a5361d023af9e7c6fc57ae78
To help existing applications transition to a common naming scheme for
the SdKey classes, offer this intermediate result, where the SdKey
classes' .name are still unchanged as before generating them.
Change-Id: I974cb6c393a2ed2248a6240c2722d157e9235c33
Reading the TS48 V6.0 eSIM_GTP_SAIP2.1A_NoBERTLV profile results in an
exception [1] in SmspTpScAddr. I have a caller that needs to skip
erratic values instead of raising.
The underlying issue, I presume, is that either the data needs
validation before decode_record_bin(), or decode_record_bin() needs
well-defined error handling.
So far I know only of this IndexError, so, as a workaround, catch that.
[1]
File "/pysim/pySim/esim/saip/personalization.py", line 617, in get_values_from_pes
ef_smsp_dec = ef_smsp.decode_record_bin(f_smsp.body, 1)
File "/pysim/pySim/filesystem.py", line 1047, in decode_record_bin
return parse_construct(self._construct, raw_bin_data)
File "/application/venv/lib/python3.13/site-packages/osmocom/construct.py", line 550, in parse_construct
parsed = c.parse(raw_bin_data, total_len=length, **context)
File "/application/venv/lib/python3.13/site-packages/construct/core.py", line 404, in parse
return self.parse_stream(io.BytesIO(data), **contextkw)
~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/application/venv/lib/python3.13/site-packages/construct/core.py", line 416, in parse_stream
return self._parsereport(stream, context, "(parsing)")
~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/application/venv/lib/python3.13/site-packages/construct/core.py", line 428, in _parsereport
obj = self._parse(stream, context, path)
File "/application/venv/lib/python3.13/site-packages/construct/core.py", line 2236, in _parse
subobj = sc._parsereport(stream, context, path)
File "/application/venv/lib/python3.13/site-packages/construct/core.py", line 428, in _parsereport
obj = self._parse(stream, context, path)
File "/application/venv/lib/python3.13/site-packages/construct/core.py", line 2770, in _parse
return self.subcon._parsereport(stream, context, path)
~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^
File "/application/venv/lib/python3.13/site-packages/construct/core.py", line 428, in _parsereport
obj = self._parse(stream, context, path)
File "/application/venv/lib/python3.13/site-packages/construct/core.py", line 2236, in _parse
subobj = sc._parsereport(stream, context, path)
File "/application/venv/lib/python3.13/site-packages/construct/core.py", line 428, in _parsereport
obj = self._parse(stream, context, path)
File "/application/venv/lib/python3.13/site-packages/construct/core.py", line 2770, in _parse
return self.subcon._parsereport(stream, context, path)
~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^
File "/application/venv/lib/python3.13/site-packages/construct/core.py", line 428, in _parsereport
obj = self._parse(stream, context, path)
File "/application/venv/lib/python3.13/site-packages/construct/core.py", line 820, in _parse
return self._decode(obj, context, path)
~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^
File "/application/venv/lib/python3.13/site-packages/osmocom/construct.py", line 268, in _decode
if r[-1] == 'f':
~^^^^
File "/application/venv/lib/python3.13/site-packages/osmocom/utils.py", line 50, in __getitem__
return hexstr(super().__getitem__(val))
~~~~~~~~~~~~~~~~~~~^^^^^
IndexError: string index out of range
Change-Id: Ic436e206776b81f24de126e8ee0ae8bf5f3e8d7a
secrets.SystemRandom is defined as the most secure random source
available on the given operating system.
Change-Id: I8049cd1292674b3ced82b0926569128535af6efe
By a flag, allow to audit also all Security Domain KVN that we have
*not* created ConfigurableParameter subclasses for.
For example, SCP80 has reserved kvn 0x01..0x0f, but we offer only
Scp80Kvn01, Scp80Kvn02, Scp80Kvn03. So we would not show kvn
0x03..0x0f in an audit.
This patch includes audits of all SD key kvn there may be in the UPP.
This will help to spot SD keys that may already be present in a UPP
template, with unexpected / unusual kvn.
Change-Id: Icaf6f7b589f117868633c0968a99f2f0252cf612
'securityDomain' elements are decoded to ProfileElementSD instances,
which keep higher level representations of the key data apart from the
decoded[] lists.
So far, apply_val() was dropping binary values in decoded[], which does
not work, because ProfileElementSD._pre_encode() overwrites
self.decoded[] from the higher level representation.
Implement using
- ProfileElementSD.find_key() and SecurityDomainKeyComponent to modify
an exsiting entry, or
- ProfileElementSD.add_key() to create a new entry.
Before this patch, SdKey parameters seemed to patch PES successfully,
but their modifications did not end up in the encoded DER.
(BTW, this does not fix any other errors that may still be present in
the various SdKey subclasses, patches coming up.)
Related: SYS#6768
Change-Id: I07dfc378705eba1318e9e8652796cbde106c6a52
The aim is to tell a user interface how wide an input text field should
be chosen to be convenient -- ideally showing the entire value in all
cases, but not too huge for fields that have no sane size limit.
Change-Id: I2568a032167a10517d4d75d8076a747be6e21890
The AlgorithmID has a few preset values, and hardly anyone knows which
is which. So instead of entering '1', '2' or '3', make it work with
prededined values 'Milenage', 'TUAK' and 'usim-test'.
Implement the enum value part abstractly in new EnumParam.
Make AlgorithmID a subclass of EnumParam and define the values as from
pySim/esim/asn1/saip/PE_Definitions-3.3.1.asn
Related: SYS#6768
Change-Id: I71c2ec1b753c66cb577436944634f32792353240
Add default_source class members pointing to ParamSource classes to all
ConfigurableParameter subclasses.
This is useful to automatically set up a default ParamSource for a given
ConfigurableParameter subclass, during user interaction to produce a
batch personalization.
For example, if the user selects a Pin1 parameter, a calling program can
implicitly set this to a RandomDigitSource, which will magically make it
work the way that most users need.
BTW, default_source and default_value can be combined to configure a
matching ParamSource instance:
my_source = MyParam.default_source.from_str( MyParam.default_value )
Change-Id: Ie58d13bce3fa1aa2547cf3cee918c2f5b30a8b32
Implement get_values_from_pes(), the reverse direction of apply_val():
read back and return values from a ProfileElementSequence. Implement for
all ConfigurableParameter subclasses.
Future: SdKey.get_values_from_pes() is reading pe.decoded[], which works
fine, but I07dfc378705eba1318e9e8652796cbde106c6a52 will change this
implementation to use the higher level ProfileElementSD members.
Implementation detail:
Implement get_values_from_pes() as classmethod that returns a generator.
Subclasses should yield all occurences of their parameter in a given
PES.
For example, the ICCID can appear in multiple places.
Iccid.get_values_from_pes() yields all of the individual values. A set()
of the results quickly tells whether the PES is consistent.
Rationales for reading back values:
This allows auditing an eSIM profile, particularly for producing an
output.csv from a batch personalization (that generated lots of random
key material which now needs to be fed to an HLR...).
Reading back from a binary result is more reliable than storing the
values that were fed into a personalization.
By auditing final DER results with this code, I discovered:
- "oh, there already was some key material in my UPP template."
- "all IMSIs ended up the same, forgot to set up the parameter."
- the SdKey.apply() implementations currently don't work, see
I07dfc378705eba1318e9e8652796cbde106c6a52 for a fix.
Change-Id: I234fc4317f0bdc1a486f0cee4fa432c1dce9b463
Implement pySim.esim.saip.batch.BatchPersonalization,
generating N eSIM profiles from a preset configuration.
Batch parameters can be fed by a constant, incrementing, random or from
CSV rows: add pySim.esim.saip.param_source.* classes to feed such input
to each of the BatchPersonalization's ConfigurableParameter instances.
Related: SYS#6768
Change-Id: I01ae40a06605eb205bfb409189fcd2b3a128855a
The tuples defining a DF or ADF in an eSIM template must contain a
pinStatusTemplateDO. When parsing tuples into a File() instance, we
must save it, and re-create it at the time we re-encode that file.
Same applies to the lcsi (life cycle state indicator), which may
optionally exist for any file.
Change-Id: I073aa4374f2cd664d07fa0224bf0d4c809cdf4aa
Closes: OS#6955
We already have documentation that explains how to run pySim-smpp2sim.
With smpp-ota-tool we now have a counterpart for pySim-smpp2sim, so
let's add documentation for this tool as well.
Related: SYS#7881
Change-Id: If0d18a263f5a6dc035b90f5c5c6a942d46bbba49
The commandline arguments are currently defined under __main__ in a
private scope. From there they are not reachable to the sphinx
argparse module. We have to define the arguments globally at the
top. (like in the other applications)
Related: SYS#7881
Change-Id: I2d9782e3f5b1cac78c22d206fdcac4118c7d5e7c
Some commandline arguments have an underscore in their name. Let's
replace those with dashes.
Change-Id: Icbe9d753d59263997e9ca34d46ed0daca36ca16c
Related: SYS#6868
Extend the existing test script so that it can handle multiple
testcases. Also add support for switching eUICC profiles.
Finally, add a testcases to test OTA-SMS (RFM) with AES128 and
AES256 encryption.
Change-Id: I1f10504f3a29a8c74a17991632d932819fecfa5a
Related: OS#6868
In our test setup we run the card_sanitizer.py script regualary to ensure that
we have consistent start conditions when running our tests. In case a testcase
crashes for some reason and leaves messed up files on a test card. The
card_sanitizer.py script will ensure that any problem like that is cleaned up
over night.
For the testcases we are about to add in the patch following this one, we need
to provision a new test keyset to one of our test cards. This has been already
done manually. However since the card_sanitizer still has the old keys in its
backup we will have to update that as well.
Change-Id: I5aa8a413b19b3e43a79d03e904daab50b4b1e767
Related: OS#6868