lists.osmocom.org
Sign In Sign Up
Manage this list Sign In Sign Up

Keyboard Shortcuts

Thread View

  • j: Next unread message
  • k: Previous unread message
  • j a: Jump to all threads
  • j l: Jump to MailingList overview

gerrit-log

Thread Start a new thread
Download
Threads by month
  • ----- 2026 -----
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2025 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2024 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2023 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2022 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
gerrit-log@lists.osmocom.org

March 2025

  • 1 participants
  • 1378 discussions
[M] Change in pysim[master]: [3/7] personalization: refactor Puk
by neels 07 Mar '25

07 Mar '25
neels has uploaded this change for review. ( https://gerrit.osmocom.org/c/pysim/+/39743?usp=email ) Change subject: [3/7] personalization: refactor Puk ...................................................................... [3/7] personalization: refactor Puk Implement abstract DecimalHexParam, and use it to refactor Puk1 and Puk2 to the new ConfigurableParameter implementation style. DecimalHexParam will also be used for Pin and Adm soon. Change-Id: I271e6c030c890778ab7af9ab3bc7997e22018f6a --- M pySim/esim/saip/personalization.py 1 file changed, 33 insertions(+), 21 deletions(-) git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/43/39743/1 diff --git a/pySim/esim/saip/personalization.py b/pySim/esim/saip/personalization.py index c2d71d1..abcca61 100644 --- a/pySim/esim/saip/personalization.py +++ b/pySim/esim/saip/personalization.py @@ -326,32 +326,44 @@ filtered = list(filter(lambda x: x.type == wanted_type, l)) return filtered[0] -class Puk(ConfigurableParameter): - """Configurable PUK (Pin Unblock Code). String ASCII-encoded digits.""" - keyReference = None - def validate(self): - if isinstance(self.input_value, int): - self.value = '%08d' % self.input_value - else: - self.value = self.input_value - # FIXME: valid length? - if not self.value.isdecimal(): - raise ValueError('PUK must only contain decimal digits') +class DecimalHexParam(DecimalParam): + rpad = None + rpad_char = None - def apply(self, pes: ProfileElementSequence): - puk = ''.join(['%02x' % (ord(x)) for x in self.value]) - padded_puk = rpad(puk, 16) + @classmethod + def validate_val(cls, val): + val = super().validate_val(val) + val = ''.join('%02x' % ord(x) for x in val) + if cls.rpad is not None: + c = cls.rpad_char or 'f' + val = rpad(val, cls.rpad, c) + # a DecimalHexParam subclass expects the apply_val() input to be a bytes instance ready for the pes + return h2b(val) + +class Puk(DecimalHexParam): + """Configurable PUK (Pin Unblock Code). String ASCII-encoded digits.""" + allow_len = 8 + rpad = 16 + keyReference = None + + @classmethod + def apply_val(cls, pes: ProfileElementSequence, val): + val_bytes = val mf_pes = pes.pes_by_naa['mf'][0] pukCodes = obtain_singleton_pe_from_pelist(mf_pes, 'pukCodes') for pukCode in pukCodes.decoded['pukCodes']: - if pukCode['keyReference'] == self.keyReference: - pukCode['pukValue'] = h2b(padded_puk) + if pukCode['keyReference'] == cls.keyReference: + pukCode['pukValue'] = val_bytes return - raise ValueError('cannot find pukCode') -class Puk1(Puk, keyReference=0x01): - pass -class Puk2(Puk, keyReference=0x81): - pass + raise ValueError('input template UPP has unexpected structure:' + + f' cannot find pukCode with keyReference={cls.keyReference}') + +class Puk1(Puk): + keyReference = 0x01 + +class Puk2(Puk): + keyReference = 0x81 + class Pin(ConfigurableParameter): """Configurable PIN (Personal Identification Number). String of digits.""" -- To view, visit https://gerrit.osmocom.org/c/pysim/+/39743?usp=email To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email Gerrit-MessageType: newchange Gerrit-Project: pysim Gerrit-Branch: master Gerrit-Change-Id: I271e6c030c890778ab7af9ab3bc7997e22018f6a Gerrit-Change-Number: 39743 Gerrit-PatchSet: 1 Gerrit-Owner: neels <nhofmeyr(a)sysmocom.de>
1 0
0 0
[M] Change in pysim[master]: [2/7] personalization: refactor ConfigurableParameter, Iccid, Imsi
by neels 07 Mar '25

07 Mar '25
neels has uploaded this change for review. ( https://gerrit.osmocom.org/c/pysim/+/39742?usp=email ) Change subject: [2/7] personalization: refactor ConfigurableParameter, Iccid, Imsi ...................................................................... [2/7] personalization: refactor ConfigurableParameter, Iccid, Imsi Main points/rationales of the refactoring, details below: 1) common validation implementation 2) offer classmethods The new features are optional, and will be heavily used by batch personalization patches coming soon. Implement Iccid and Imsi to use the new way, with a common abstract DecimalParam implementation. So far leave the other parameter classes working as they always did, to follow suit in subsequent commits. Details: 1) common validation implementation: There are very common validation steps in the various parameter implementations. It is more convenient and much more readable to implement those once and set simple validation parameters per subclass. So there now is a validate_val() classmethod, which subclasses can use as-is to apply the validation parameters -- or subclasses can override their cls.validate_val() for specialized validation. (Those subclasses that this patch doesn't touch still override the self.validate() instance method. Hence they still work as before this patch, but don't use the new common features yet.) 2) offer stateless classmethods: It is useful for... - batch processing of multiple profiles (in upcoming patches) and - user input validation to be able to have classmethods that do what self.validate() and self.apply() do, but do not modify any self.* members. So far the paradigm was to create a class instance to keep state about the value. This remains available, but in addition we make available the paradigm of a singleton that is stateless (the classmethods). Using self.validate() and self.apply() still work the same as before this patch, i.e. via self.input_value and self.value -- but in addition, there are now classmethods that don't touch self.* members. Related: SYS#6768 Change-Id: I6522be4c463e34897ca9bff2309b3706a88b3ce8 --- M pySim/esim/saip/personalization.py 1 file changed, 113 insertions(+), 32 deletions(-) git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/42/39742/1 diff --git a/pySim/esim/saip/personalization.py b/pySim/esim/saip/personalization.py index e31382c..c2d71d1 100644 --- a/pySim/esim/saip/personalization.py +++ b/pySim/esim/saip/personalization.py @@ -36,54 +36,135 @@ class ConfigurableParameter: """Base class representing a part of the eSIM profile that is configurable during the personalization process (with dynamic data from elsewhere).""" - def __init__(self, input_value): + allow_types = (str, int, ) + allow_chars = None + strip_chars = None + min_len = None + max_len = None + allow_len = None # a list of specific lengths + + def __init__(self, input_value=None): self.input_value = input_value # the raw input value as given by caller self.value = None # the processed input value (e.g. with check digit) as produced by validate() def validate(self): - """Optional validation method. Can be used by derived classes to perform validation - of the input value (self.value). Will raise an exception if validation fails.""" - # default implementation: simply copy input_value over to value - self.value = self.input_value + '''Validate self.input_value and place the result in self.value. + This is also called implicitly by apply(), if self.value is still None. + To override validation in a subclass, rather re-implement the classmethod validate_val().''' + try: + self.value = self.__class__.validate_val(self.input_value) + except (TypeError, ValueError, KeyError) as e: + raise ValueError(f'{self.name}: {e}') from e - @abc.abstractmethod def apply(self, pes: ProfileElementSequence): + '''Place self.value into the ProfileElementSequence at the right place. + If self.value is None, first call self.validate() to generate a sanitized self.value from self.input_value. + To override apply() in a subclass, rather re-implement the classmethod apply_val().''' + if self.value is None: + self.validate() + assert self.value is not None + try: + self.__class__.apply_val(pes, self.value) + except (TypeError, ValueError, KeyError) as e: + raise ValueError(f'{self.name}: {e}') from e + + @classmethod + def validate_val(cls, val): + '''This function is a default implementation, with the behavior configured by subclasses' allow_types...max_len + settings. + subclasses may override this function: + Validate the contents of val, and raise ValueError on validation errors. + Return a sanitized version of val, that is ready for cls.apply_val(). + ''' + + if cls.allow_types is not None: + if not isinstance(val, cls.allow_types): + raise ValueError(f'input value must be one of {cls.allow_types}, not {type(val)}') + elif val is None: + raise ValueError('there is no value (val is None)') + + if isinstance(val, str): + if cls.strip_chars is not None: + val = ''.join(c for c in val if c not in cls.strip_chars) + if cls.allow_chars is not None: + if any(c not in cls.allow_chars for c in val): + raise ValueError(f"invalid characters in input value, valid are {cls.allow_chars}") + if cls.allow_len is not None: + l = cls.allow_len + if not isinstance(l, (tuple, list)): + l = (l,) + if len(val) not in l: + raise ValueError(f'length must be one of {cls.allow_len}, not {len(val)}') + if cls.min_len is not None: + if len(val) < cls.min_len: + raise ValueError(f'length must be at least {cls.min_len}, not {len(val)}') + if cls.max_len is not None: + if len(val) > cls.max_len: + raise ValueError(f'length must be at most {cls.max_len}, not {len(val)}') + return val + + @classmethod + def apply_val(cls, pes: ProfileElementSequence, val): + '''This is what subclasses implement: store a value in a decoded profile package. + Write the given val in the right format in all the right places in pes.''' pass -class Iccid(ConfigurableParameter): - """Configurable ICCID. Expects the value to be a string of decimal digits. - If the string of digits is only 18 digits long, a Luhn check digit will be added.""" + @classmethod + def get_len_range(cls): + vals = [] + if cls.allow_len is not None: + if isinstance(cls.allow_len, (tuple, list)): + vals.extend(cls.allow_len) + else: + vals.append(cls.allow_len) + if cls.min_len is not None: + vals.append(cls.min_len) + if cls.max_len is not None: + vals.append(cls.max_len) + if not vals: + return (None, None) + return (min(vals), max(vals)) - def validate(self): - # convert to string as it might be an integer - iccid_str = str(self.input_value) - if len(iccid_str) < 18 or len(iccid_str) > 20: - raise ValueError('ICCID must be 18, 19 or 20 digits long') - if not iccid_str.isdecimal(): - raise ValueError('ICCID must only contain decimal digits') - self.value = sanitize_iccid(iccid_str) - def apply(self, pes: ProfileElementSequence): +class DecimalParam(ConfigurableParameter): + allow_types = (str, int) + allow_chars = '0123456789' + + @classmethod + def validate_val(cls, val): + if isinstance(val, int): + min_len, max_len = cls.get_len_range() + l = min_len or 1 + val = '%0*d' % (l, val) + return super().validate_val(val) + +class Iccid(DecimalParam): + """ICCID Parameter. Input: string of decimal digits. + If the string of digits is only 18 digits long, add a Luhn check digit.""" + min_len = 18 + max_len = 20 + + @classmethod + def validate_val(cls, val): + iccid_str = super().validate_val(val) + return sanitize_iccid(iccid_str) + + @classmethod + def apply_val(cls, pes: ProfileElementSequence, val): # patch the header - pes.get_pe_for_type('header').decoded['iccid'] = h2b(rpad(self.value, 20)) + pes.get_pe_for_type('header').decoded['iccid'] = h2b(rpad(val, 20)) # patch MF/EF.ICCID - file_replace_content(pes.get_pe_for_type('mf').decoded['ef-iccid'], h2b(enc_iccid(self.value))) + file_replace_content(pes.get_pe_for_type('mf').decoded['ef-iccid'], h2b(enc_iccid(val))) -class Imsi(ConfigurableParameter): +class Imsi(DecimalParam): """Configurable IMSI. Expects value to be a string of digits. Automatically sets the ACC to the last digit of the IMSI.""" + min_len = 6 + max_len = 15 - def validate(self): - # convert to string as it might be an integer - imsi_str = str(self.input_value) - if len(imsi_str) < 6 or len(imsi_str) > 15: - raise ValueError('IMSI must be 6..15 digits long') - if not imsi_str.isdecimal(): - raise ValueError('IMSI must only contain decimal digits') - self.value = imsi_str - - def apply(self, pes: ProfileElementSequence): - imsi_str = self.value + @classmethod + def apply_val(cls, pes: ProfileElementSequence, val): + imsi_str = val # we always use the least significant byte of the IMSI as ACC acc = (1 << int(imsi_str[-1])) # patch ADF.USIM/EF.IMSI -- To view, visit https://gerrit.osmocom.org/c/pysim/+/39742?usp=email To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email Gerrit-MessageType: newchange Gerrit-Project: pysim Gerrit-Branch: master Gerrit-Change-Id: I6522be4c463e34897ca9bff2309b3706a88b3ce8 Gerrit-Change-Number: 39742 Gerrit-PatchSet: 1 Gerrit-Owner: neels <nhofmeyr(a)sysmocom.de>
1 0
0 0
[M] Change in pysim[master]: [4/7] personalization: refactor Pin, Adm
by neels 07 Mar '25

07 Mar '25
neels has uploaded this change for review. ( https://gerrit.osmocom.org/c/pysim/+/39744?usp=email ) Change subject: [4/7] personalization: refactor Pin, Adm ...................................................................... [4/7] personalization: refactor Pin, Adm Refactor Pin1, Pin2, Adm1 and Adm2 to the new ConfigurableParameter implementation style. Change-Id: I54aef10b6d4309398d4b779a3740a7d706d68603 --- M pySim/esim/saip/personalization.py 1 file changed, 55 insertions(+), 57 deletions(-) git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/44/39744/1 diff --git a/pySim/esim/saip/personalization.py b/pySim/esim/saip/personalization.py index abcca61..36baf43 100644 --- a/pySim/esim/saip/personalization.py +++ b/pySim/esim/saip/personalization.py @@ -317,6 +317,9 @@ key_usage_qual = 0x48 +def obtain_all_pe_from_pelist(l: List[ProfileElement], wanted_type: str) -> ProfileElement: + return (pe for pe in l if pe.type == wanted_type) + def obtain_singleton_pe_from_pelist(l: List[ProfileElement], wanted_type: str) -> ProfileElement: filtered = list(filter(lambda x: x.type == wanted_type, l)) assert len(filtered) == 1 @@ -364,70 +367,65 @@ class Puk2(Puk): keyReference = 0x81 - -class Pin(ConfigurableParameter): +class Pin(DecimalHexParam): """Configurable PIN (Personal Identification Number). String of digits.""" + rpad = 16 + min_len = 4 + max_len = 8 keyReference = None - def validate(self): - if isinstance(self.input_value, int): - self.value = '%04d' % self.input_value - else: - self.value = self.input_value - if len(self.value) < 4 or len(self.value) > 8: - raise ValueError('PIN mus be 4..8 digits long') - if not self.value.isdecimal(): - raise ValueError('PIN must only contain decimal digits') - def apply(self, pes: ProfileElementSequence): - pin = ''.join(['%02x' % (ord(x)) for x in self.value]) - padded_pin = rpad(pin, 16) - mf_pes = pes.pes_by_naa['mf'][0] - pinCodes = obtain_first_pe_from_pelist(mf_pes, 'pinCodes') - if pinCodes.decoded['pinCodes'][0] != 'pinconfig': - return - for pinCode in pinCodes.decoded['pinCodes'][1]: - if pinCode['keyReference'] == self.keyReference: - pinCode['pinValue'] = h2b(padded_pin) - return - raise ValueError('cannot find pinCode') -class AppPin(ConfigurableParameter): - """Configurable PIN (Personal Identification Number). String of digits.""" - keyReference = None - def validate(self): - if isinstance(self.input_value, int): - self.value = '%04d' % self.input_value - else: - self.value = self.input_value - if len(self.value) < 4 or len(self.value) > 8: - raise ValueError('PIN mus be 4..8 digits long') - if not self.value.isdecimal(): - raise ValueError('PIN must only contain decimal digits') - def _apply_one(self, pe: ProfileElement): - pin = ''.join(['%02x' % (ord(x)) for x in self.value]) - padded_pin = rpad(pin, 16) - pinCodes = obtain_first_pe_from_pelist(pe, 'pinCodes') - if pinCodes.decoded['pinCodes'][0] != 'pinconfig': - return - for pinCode in pinCodes.decoded['pinCodes'][1]: - if pinCode['keyReference'] == self.keyReference: - pinCode['pinValue'] = h2b(padded_pin) - return - raise ValueError('cannot find pinCode') - def apply(self, pes: ProfileElementSequence): + @staticmethod + def _apply_pinvalue(pe: ProfileElement, keyReference, val_bytes): + for pinCodes in obtain_all_pe_from_pelist(pe, 'pinCodes'): + if pinCodes.decoded['pinCodes'][0] != 'pinconfig': + continue + + for pinCode in pinCodes.decoded['pinCodes'][1]: + if pinCode['keyReference'] == keyReference: + pinCode['pinValue'] = val_bytes + return True + return False + + @classmethod + def apply_val(cls, pes: ProfileElementSequence, val): + val_bytes = val + if not cls._apply_pinvalue(pes.pes_by_naa['mf'][0], cls.keyReference, val_bytes): + raise ValueError('input template UPP has unexpected structure:' + + f' {cls.name} cannot find pinCode with keyReference={cls.keyReference}') + + @classmethod + def _read_all_pinvalues_from_pe(cls, pe: ProfileElement): + for pinCodes in obtain_all_pe_from_pelist(pe, 'pinCodes'): + if pinCodes.decoded['pinCodes'][0] != 'pinconfig': + continue + + for pinCode in pinCodes.decoded['pinCodes'][1]: + if pinCode['keyReference'] == cls.keyReference: + yield cls.decimal_hex_to_str(pinCode['pinValue']) + +class Pin1(Pin): + keyReference = 0x01 + +class Pin2(Pin): + keyReference = 0x81 + + @classmethod + def apply_val(cls, pes: ProfileElementSequence, val): + val_bytes = val + # PIN2 is special: telecom + usim + isim + csim for naa in pes.pes_by_naa: if naa not in ['usim','isim','csim','telecom']: continue for instance in pes.pes_by_naa[naa]: - self._apply_one(instance) -class Pin1(Pin, keyReference=0x01): - pass -# PIN2 is special: telecom + usim + isim + csim -class Pin2(AppPin, keyReference=0x81): - pass -class Adm1(Pin, keyReference=0x0A): - pass -class Adm2(Pin, keyReference=0x0B): - pass + if not cls._apply_pinvalue(instance, cls.keyReference, val_bytes): + raise ValueError('input template UPP has unexpected structure:' + + f' {cls.name} cannot find pinCode with keyReference={cls.keyReference} in {naa=}') + +class Adm1(Pin): + keyReference = 0x0A + +class Adm2(Pin): + keyReference = 0x0B class AlgoConfig(ConfigurableParameter): -- To view, visit https://gerrit.osmocom.org/c/pysim/+/39744?usp=email To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email Gerrit-MessageType: newchange Gerrit-Project: pysim Gerrit-Branch: master Gerrit-Change-Id: I54aef10b6d4309398d4b779a3740a7d706d68603 Gerrit-Change-Number: 39744 Gerrit-PatchSet: 1 Gerrit-Owner: neels <nhofmeyr(a)sysmocom.de>
1 0
0 0
[M] Change in pysim[master]: [1/7] personalization: refactor: drop ClassVarMeta use
by neels 07 Mar '25

07 Mar '25
neels has uploaded this change for review. ( https://gerrit.osmocom.org/c/pysim/+/39741?usp=email ) Change subject: [1/7] personalization: refactor: drop ClassVarMeta use ...................................................................... [1/7] personalization: refactor: drop ClassVarMeta use Drop the ClassVarMeta/metaclass/ABCMeta stuff -- it doesn't seem to serve any purpose that is not similarly achieved with plain python inheritance. Upcoming patches will use normal inheritance a lot more. Note that most use of the ClassVarMeta was in the SdKey subclasses, and that these currently don't actually work. See the fix in patch I07dfc378705eba1318e9e8652796cbde106c6a52 . Related: SYS#6768 Change-Id: I60ea8fd11fb438ec90ddb08b17b658cbb789c051 --- M pySim/esim/saip/personalization.py 1 file changed, 104 insertions(+), 66 deletions(-) git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/41/39741/1 diff --git a/pySim/esim/saip/personalization.py b/pySim/esim/saip/personalization.py index 61973e7..e31382c 100644 --- a/pySim/esim/saip/personalization.py +++ b/pySim/esim/saip/personalization.py @@ -15,7 +15,6 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -import abc import io from typing import List, Tuple @@ -34,18 +33,7 @@ file.append(('fillFileContent', new_content)) return file -class ClassVarMeta(abc.ABCMeta): - """Metaclass that puts all additional keyword-args into the class. We use this to have one - class definition for something like a PIN, and then have derived classes for PIN1, PIN2, ...""" - def __new__(metacls, name, bases, namespace, **kwargs): - #print("Meta_new_(metacls=%s, name=%s, bases=%s, namespace=%s, kwargs=%s)" % (metacls, name, bases, namespace, kwargs)) - x = super().__new__(metacls, name, bases, namespace) - for k, v in kwargs.items(): - setattr(x, k, v) - setattr(x, 'name', camel_to_snake(name)) - return x - -class ConfigurableParameter(abc.ABC, metaclass=ClassVarMeta): +class ConfigurableParameter: """Base class representing a part of the eSIM profile that is configurable during the personalization process (with dynamic data from elsewhere).""" def __init__(self, input_value): @@ -105,7 +93,7 @@ # TODO: DF.GSM_ACCESS if not linked? -class SdKey(ConfigurableParameter, metaclass=ClassVarMeta): +class SdKey(ConfigurableParameter): """Configurable Security Domain (SD) Key. Value is presented as bytes.""" # these will be set by derived classes key_type = None @@ -144,59 +132,108 @@ for pe in pes.get_pes_for_type('securityDomain'): self._apply_sd(pe) -class SdKeyScp80_01(SdKey, kvn=0x01, key_type=0x88, permitted_len=[16,24,32]): # AES key type - pass -class SdKeyScp80_01Kic(SdKeyScp80_01, key_id=0x01, key_usage_qual=0x18): # FIXME: ordering? - pass -class SdKeyScp80_01Kid(SdKeyScp80_01, key_id=0x02, key_usage_qual=0x14): - pass -class SdKeyScp80_01Kik(SdKeyScp80_01, key_id=0x03, key_usage_qual=0x48): - pass +class SdKeyScp80_01(SdKey): + kvn = 0x01 + key_type = 0x88 # AES key type + allow_len = (16,24,32) -class SdKeyScp81_01(SdKey, kvn=0x81): # FIXME - pass -class SdKeyScp81_01Psk(SdKeyScp81_01, key_id=0x01, key_type=0x85, key_usage_qual=0x3C): - pass -class SdKeyScp81_01Dek(SdKeyScp81_01, key_id=0x02, key_type=0x88, key_usage_qual=0x48): - pass +class SdKeyScp80_01Kic(SdKeyScp80_01): + key_id = 0x01 + key_usage_qual = 0x18 # FIXME: ordering? -class SdKeyScp02_20(SdKey, kvn=0x20, key_type=0x88, permitted_len=[16,24,32]): # AES key type - pass -class SdKeyScp02_20Enc(SdKeyScp02_20, key_id=0x01, key_usage_qual=0x18): - pass -class SdKeyScp02_20Mac(SdKeyScp02_20, key_id=0x02, key_usage_qual=0x14): - pass -class SdKeyScp02_20Dek(SdKeyScp02_20, key_id=0x03, key_usage_qual=0x48): - pass +class SdKeyScp80_01Kid(SdKeyScp80_01): + key_id = 0x02 + key_usage_qual = 0x14 -class SdKeyScp03_30(SdKey, kvn=0x30, key_type=0x88, permitted_len=[16,24,32]): # AES key type - pass -class SdKeyScp03_30Enc(SdKeyScp03_30, key_id=0x01, key_usage_qual=0x18): - pass -class SdKeyScp03_30Mac(SdKeyScp03_30, key_id=0x02, key_usage_qual=0x14): - pass -class SdKeyScp03_30Dek(SdKeyScp03_30, key_id=0x03, key_usage_qual=0x48): - pass - -class SdKeyScp03_31(SdKey, kvn=0x31, key_type=0x88, permitted_len=[16,24,32]): # AES key type - pass -class SdKeyScp03_31Enc(SdKeyScp03_31, key_id=0x01, key_usage_qual=0x18): - pass -class SdKeyScp03_31Mac(SdKeyScp03_31, key_id=0x02, key_usage_qual=0x14): - pass -class SdKeyScp03_31Dek(SdKeyScp03_31, key_id=0x03, key_usage_qual=0x48): - pass - -class SdKeyScp03_32(SdKey, kvn=0x32, key_type=0x88, permitted_len=[16,24,32]): # AES key type - pass -class SdKeyScp03_32Enc(SdKeyScp03_32, key_id=0x01, key_usage_qual=0x18): - pass -class SdKeyScp03_32Mac(SdKeyScp03_32, key_id=0x02, key_usage_qual=0x14): - pass -class SdKeyScp03_32Dek(SdKeyScp03_32, key_id=0x03, key_usage_qual=0x48): - pass +class SdKeyScp80_01Kik(SdKeyScp80_01): + key_id = 0x03 + key_usage_qual = 0x48 +class SdKeyScp81_01(SdKey): + kvn = 0x81 # FIXME + +class SdKeyScp81_01Psk(SdKeyScp81_01): + key_id = 0x01 + key_type = 0x85 + key_usage_qual = 0x3C + +class SdKeyScp81_01Dek(SdKeyScp81_01): + key_id = 0x02 + key_type = 0x88 + key_usage_qual = 0x48 + + +class SdKeyScp02_20(SdKey): + kvn = 0x20 + key_type = 0x88 # AES key type + allow_len = (16,24,32) + +class SdKeyScp02_20Enc(SdKeyScp02_20): + key_id = 0x01 + key_usage_qual = 0x18 + +class SdKeyScp02_20Mac(SdKeyScp02_20): + key_id = 0x02 + key_usage_qual = 0x14 + +class SdKeyScp02_20Dek(SdKeyScp02_20): + key_id = 0x03 + key_usage_qual = 0x48 + + +class SdKeyScp03_30(SdKey): + kvn = 0x30 + key_type = 0x88 # AES key type + allow_len = (16,24,32) + +class SdKeyScp03_30Enc(SdKeyScp03_30): + key_id = 0x01 + key_usage_qual = 0x18 + +class SdKeyScp03_30Mac(SdKeyScp03_30): + key_id = 0x02 + key_usage_qual = 0x14 + +class SdKeyScp03_30Dek(SdKeyScp03_30): + key_id = 0x03 + key_usage_qual = 0x48 + + +class SdKeyScp03_31(SdKey): + kvn = 0x31 + key_type = 0x88 # AES key type + allow_len = (16,24,32) + +class SdKeyScp03_31Enc(SdKeyScp03_31): + key_id = 0x01 + key_usage_qual = 0x18 + +class SdKeyScp03_31Mac(SdKeyScp03_31): + key_id = 0x02 + key_usage_qual = 0x14 + +class SdKeyScp03_31Dek(SdKeyScp03_31): + key_id = 0x03 + key_usage_qual = 0x48 + + +class SdKeyScp03_32(SdKey): + kvn = 0x32 + key_type = 0x88 # AES key type + allow_len = (16,24,32) + +class SdKeyScp03_32Enc(SdKeyScp03_32): + key_id = 0x01 + key_usage_qual = 0x18 + +class SdKeyScp03_32Mac(SdKeyScp03_32): + key_id = 0x02 + key_usage_qual = 0x14 + +class SdKeyScp03_32Dek(SdKeyScp03_32): + key_id = 0x03 + key_usage_qual = 0x48 def obtain_singleton_pe_from_pelist(l: List[ProfileElement], wanted_type: str) -> ProfileElement: @@ -208,7 +245,7 @@ filtered = list(filter(lambda x: x.type == wanted_type, l)) return filtered[0] -class Puk(ConfigurableParameter, metaclass=ClassVarMeta): +class Puk(ConfigurableParameter): """Configurable PUK (Pin Unblock Code). String ASCII-encoded digits.""" keyReference = None def validate(self): @@ -235,7 +272,7 @@ class Puk2(Puk, keyReference=0x81): pass -class Pin(ConfigurableParameter, metaclass=ClassVarMeta): +class Pin(ConfigurableParameter): """Configurable PIN (Personal Identification Number). String of digits.""" keyReference = None def validate(self): @@ -259,7 +296,8 @@ pinCode['pinValue'] = h2b(padded_pin) return raise ValueError('cannot find pinCode') -class AppPin(ConfigurableParameter, metaclass=ClassVarMeta): + +class AppPin(ConfigurableParameter): """Configurable PIN (Personal Identification Number). String of digits.""" keyReference = None def validate(self): @@ -299,7 +337,7 @@ pass -class AlgoConfig(ConfigurableParameter, metaclass=ClassVarMeta): +class AlgoConfig(ConfigurableParameter): """Configurable Algorithm parameter.""" key = None def validate(self): -- To view, visit https://gerrit.osmocom.org/c/pysim/+/39741?usp=email To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email Gerrit-MessageType: newchange Gerrit-Project: pysim Gerrit-Branch: master Gerrit-Change-Id: I60ea8fd11fb438ec90ddb08b17b658cbb789c051 Gerrit-Change-Number: 39741 Gerrit-PatchSet: 1 Gerrit-Owner: neels <nhofmeyr(a)sysmocom.de>
1 0
0 0
[S] Change in pysim[master]: [6/7] personalization: refactor K, Opc
by neels 07 Mar '25

07 Mar '25
neels has uploaded this change for review. ( https://gerrit.osmocom.org/c/pysim/+/39746?usp=email ) Change subject: [6/7] personalization: refactor K, Opc ...................................................................... [6/7] personalization: refactor K, Opc Refactor K and Opc to the new ConfigurableParameter implementation style, using a common abstract BinaryParam. Change-Id: I966817db38333b6c82f8e316552dfc987e23ab70 --- M pySim/esim/saip/personalization.py 1 file changed, 36 insertions(+), 13 deletions(-) git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/46/39746/1 diff --git a/pySim/esim/saip/personalization.py b/pySim/esim/saip/personalization.py index 34486bd..c591c7d 100644 --- a/pySim/esim/saip/personalization.py +++ b/pySim/esim/saip/personalization.py @@ -174,6 +174,28 @@ # TODO: DF.GSM_ACCESS if not linked? +class BinaryParam(ConfigurableParameter): + allow_types = (str, io.BytesIO, bytes, bytearray) + allow_chars = '0123456789abcdefABCDEF' + strip_chars = ' \t\r\n' + + @classmethod + def validate_val(cls, val): + # take care that min_len and max_len are applied to the binary length by converting to bytes first + if type(val) is str: + if cls.strip_chars is not None: + val = ''.join(c for c in val if c not in cls.strip_chars) + if len(val) & 1: + raise ValueError('Invalid hexadecimal string, must have even number of digits:' + f' {val!r} {len(val)=}') from e + try: + val = h2b(val) + except ValueError as e: + raise ValueError(f'Invalid hexadecimal string: {val!r} {len(val)=}') from e + + val = super().validate_val(val) + return bytes(val) + class SdKey(ConfigurableParameter): """Configurable Security Domain (SD) Key. Value is presented as bytes.""" # these will be set by derived classes @@ -455,21 +477,22 @@ f' {cls.name} cannot find algoParameter with key={cls.key}') -class AlgoConfig(ConfigurableParameter, metaclass=ClassVarMeta): - """Configurable Algorithm parameter.""" - key = None - def validate(self): - if not isinstance(self.input_value, (io.BytesIO, bytes, bytearray)): - raise ValueError('Value must be of bytes-like type') - self.value = self.input_value - def apply(self, pes: ProfileElementSequence): +class K(BinaryParam): + key = 'key' + allow_len = int(128/8) + + @classmethod + def apply_val(cls, pes: ProfileElementSequence, val): + found = 0 for pe in pes.get_pes_for_type('akaParameter'): algoConfiguration = pe.decoded['algoConfiguration'] if algoConfiguration[0] != 'algoParameter': continue - algoConfiguration[1][self.key] = self.value + algoConfiguration[1][cls.key] = val + found += 1 + if not found: + raise ValueError('input template UPP has unexpected structure:' + f' {cls.name} cannot find algoParameter with key={cls.key}') -class K(AlgoConfig, key='key'): - pass -class Opc(AlgoConfig, key='opc'): - pass +class Opc(K): + key = 'opc' -- To view, visit https://gerrit.osmocom.org/c/pysim/+/39746?usp=email To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email Gerrit-MessageType: newchange Gerrit-Project: pysim Gerrit-Branch: master Gerrit-Change-Id: I966817db38333b6c82f8e316552dfc987e23ab70 Gerrit-Change-Number: 39746 Gerrit-PatchSet: 1 Gerrit-Owner: neels <nhofmeyr(a)sysmocom.de>
1 0
0 0
[S] Change in pysim[master]: [5/7] personalization: refactor AlgorithmID
by neels 07 Mar '25

07 Mar '25
neels has uploaded this change for review. ( https://gerrit.osmocom.org/c/pysim/+/39745?usp=email ) Change subject: [5/7] personalization: refactor AlgorithmID ...................................................................... [5/7] personalization: refactor AlgorithmID Refactor AlgorithmID to the new ConfigurableParameter implementation style. Note from the future: AlgorithmID so far takes "raw" int values, but will turn to be an "enum" parameter with predefined meaningful strings in I71c2ec1b753c66cb577436944634f32792353240 Change-Id: I6296fdcfd5d2ed313c4aade57ff43cc362375848 --- M pySim/esim/saip/personalization.py 1 file changed, 28 insertions(+), 6 deletions(-) git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/45/39745/1 diff --git a/pySim/esim/saip/personalization.py b/pySim/esim/saip/personalization.py index 36baf43..34486bd 100644 --- a/pySim/esim/saip/personalization.py +++ b/pySim/esim/saip/personalization.py @@ -428,7 +428,34 @@ keyReference = 0x0B -class AlgoConfig(ConfigurableParameter): +class AlgorithmID(DecimalParam): + key = 'algorithmID' + allow_len = 1 + + @classmethod + def validate_val(cls, val): + val = super().validate_val(val) + val = int(val) + valid = (1, 2, 3) + if val not in valid: + raise ValueError(f'Invalid algorithmID {val!r}, must be one of {valid}') + return val + + @classmethod + def apply_val(cls, pes: ProfileElementSequence, val): + found = 0 + for pe in pes.get_pes_for_type('akaParameter'): + algoConfiguration = pe.decoded['algoConfiguration'] + if algoConfiguration[0] != 'algoParameter': + continue + algoConfiguration[1][cls.key] = val + found += 1 + if not found: + raise ValueError('input template UPP has unexpected structure:' + f' {cls.name} cannot find algoParameter with key={cls.key}') + + +class AlgoConfig(ConfigurableParameter, metaclass=ClassVarMeta): """Configurable Algorithm parameter.""" key = None def validate(self): @@ -446,8 +473,3 @@ pass class Opc(AlgoConfig, key='opc'): pass -class AlgorithmID(AlgoConfig, key='algorithmID'): - def validate(self): - if self.input_value not in [1, 2, 3]: - raise ValueError('Invalid algorithmID %s' % (self.input_value)) - self.value = self.input_value -- To view, visit https://gerrit.osmocom.org/c/pysim/+/39745?usp=email To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email Gerrit-MessageType: newchange Gerrit-Project: pysim Gerrit-Branch: master Gerrit-Change-Id: I6296fdcfd5d2ed313c4aade57ff43cc362375848 Gerrit-Change-Number: 39745 Gerrit-PatchSet: 1 Gerrit-Owner: neels <nhofmeyr(a)sysmocom.de>
1 0
0 0
[S] Change in osmo-mgw[master]: MGCP extension: add parameters for TW-TS-001 & TW-TS-002
by falconia 07 Mar '25

07 Mar '25
Attention is currently required from: pespin. falconia has posted comments on this change by falconia. ( https://gerrit.osmocom.org/c/osmo-mgw/+/39730?usp=email ) Change subject: MGCP extension: add parameters for TW-TS-001 & TW-TS-002 ...................................................................... Patch Set 1: (2 comments) Patchset: PS1: > this should be documented in doc/manuals/chapters/mgcp_extensions.adoc. That chapter begins with this sentence: "The following non-standard extensions are understood by OsmoMGW." Thus it feels wrong to me to use this chapter, or rather the OsmoMGW manual in general, as a place to document a protocol extension that exists between OsmoBSC and tw-e1abis-mgw - but is not currently implemented in OsmoMGW. I see two possible solutions: 1) Document the newly created extension somewhere else, somewhere other than OsmoMGW manual; 2) Extend my code patch to add support for the new extension not only to libosmo-mgcp-client, but also to OsmoMGW-E1, so that OsmoMGW manual will *become* a sensible place to document it. I am going to look into the feasibility of option 2. File src/libosmo-mgcp-client/mgcp_client.c: https://gerrit.osmocom.org/c/osmo-mgw/+/39730/comment/49201b15_b25be00b?usp… : PS1, Line 1436: pt, (int) mgcp_msg->param.amr_octet_aligned); > remove spacing between type cast and variable, here and below. Acknowledged -- To view, visit https://gerrit.osmocom.org/c/osmo-mgw/+/39730?usp=email To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email Gerrit-MessageType: comment Gerrit-Project: osmo-mgw Gerrit-Branch: master Gerrit-Change-Id: I0d58e6d84418f50670c8ab7cf8490af3bc2f5c26 Gerrit-Change-Number: 39730 Gerrit-PatchSet: 1 Gerrit-Owner: falconia <falcon(a)freecalypso.org> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: pespin <pespin(a)sysmocom.de> Gerrit-Attention: pespin <pespin(a)sysmocom.de> Gerrit-Comment-Date: Fri, 07 Mar 2025 17:00:57 +0000 Gerrit-HasComments: Yes Gerrit-Has-Labels: No Comment-In-Reply-To: pespin <pespin(a)sysmocom.de>
1 0
0 0
[S] Change in osmo-ttcn3-hacks[master]: testenv: use --autoreconf-in-src-copy by default
by fixeria 07 Mar '25

07 Mar '25
Attention is currently required from: osmith. fixeria has posted comments on this change by osmith. ( https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/39735?usp=email ) Change subject: testenv: use --autoreconf-in-src-copy by default ...................................................................... Patch Set 1: Code-Review+2 -- To view, visit https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/39735?usp=email To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email Gerrit-MessageType: comment Gerrit-Project: osmo-ttcn3-hacks Gerrit-Branch: master Gerrit-Change-Id: I41e1fb534e253ddb43f266d73485b83259a8aa40 Gerrit-Change-Number: 39735 Gerrit-PatchSet: 1 Gerrit-Owner: osmith <osmith(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-Reviewer: pespin <pespin(a)sysmocom.de> Gerrit-Attention: osmith <osmith(a)sysmocom.de> Gerrit-Comment-Date: Fri, 07 Mar 2025 16:54:52 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: Yes
1 0
0 0
[XS] Change in osmo-mgw[master]: cosmetic: add copy of mgcp_common.h to .gitignore
by falconia 07 Mar '25

07 Mar '25
falconia has submitted this change. ( https://gerrit.osmocom.org/c/osmo-mgw/+/39729?usp=email ) Change subject: cosmetic: add copy of mgcp_common.h to .gitignore ...................................................................... cosmetic: add copy of mgcp_common.h to .gitignore The build process copies include/osmocom/mgcp/mgcp_common.h to include/osmocom/mgcp_client/mgcp_common.h; the former is a true source while the latter is a build-generated file. The copied file needs to be included in .gitignore, otherwise it adds noise to git status output. Change-Id: Icf0e3f724564d87eef9351b22de7a3d3aa7e4264 --- M .gitignore 1 file changed, 1 insertion(+), 0 deletions(-) Approvals: laforge: Looks good to me, but someone else must approve Jenkins Builder: Verified pespin: Looks good to me, approved diff --git a/.gitignore b/.gitignore index a72cd36..3f1a890 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ Makefile.in bscconfig.h bscconfig.h.in +include/osmocom/mgcp_client/mgcp_common.h src/osmo-mgw/osmo-mgw *.*~ *.sw? -- To view, visit https://gerrit.osmocom.org/c/osmo-mgw/+/39729?usp=email To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email Gerrit-MessageType: merged Gerrit-Project: osmo-mgw Gerrit-Branch: master Gerrit-Change-Id: Icf0e3f724564d87eef9351b22de7a3d3aa7e4264 Gerrit-Change-Number: 39729 Gerrit-PatchSet: 2 Gerrit-Owner: falconia <falcon(a)freecalypso.org> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: falconia <falcon(a)freecalypso.org> Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-Reviewer: pespin <pespin(a)sysmocom.de>
1 0
0 0
[S] Change in pysim[master]: filesystem: do not decode short TransRecEF records
by dexter 07 Mar '25

07 Mar '25
Attention is currently required from: laforge. dexter has posted comments on this change by dexter. ( https://gerrit.osmocom.org/c/pysim/+/39670?usp=email ) Change subject: filesystem: do not decode short TransRecEF records ...................................................................... Patch Set 3: (1 comment) File pySim/filesystem.py: https://gerrit.osmocom.org/c/pysim/+/39670/comment/f8cd1c89_e1f07128?usp=em… : PS3, Line 1231: if len(raw_hex_data) // 2 < self.__get_rec_len(): > I would think this is too harsh. […] I think I don't get what you mean by that. The too-short trailer is output as raw data (e.g. {"raw": "ffffffff"}). So technically it is treated as invalid data. Or do you mean the decoder function should do the check and sort out any invalid input? In this case that would be utils:dec_xplmn_w_act. (I am not aware of an explicit specification that TransRecEFs must always have a length that is a multiple of the record length, however it would make sense.) -- To view, visit https://gerrit.osmocom.org/c/pysim/+/39670?usp=email To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email Gerrit-MessageType: comment Gerrit-Project: pysim Gerrit-Branch: master Gerrit-Change-Id: Ib1dc4d7ce306f1f0b080bb4b6abc36e72431d3fa Gerrit-Change-Number: 39670 Gerrit-PatchSet: 3 Gerrit-Owner: dexter <pmaier(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-CC: laforge <laforge(a)osmocom.org> Gerrit-Attention: laforge <laforge(a)osmocom.org> Gerrit-Comment-Date: Fri, 07 Mar 2025 16:09:23 +0000 Gerrit-HasComments: Yes Gerrit-Has-Labels: No Comment-In-Reply-To: laforge <laforge(a)osmocom.org>
1 0
0 0
  • ← Newer
  • 1
  • ...
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • ...
  • 138
  • Older →

HyperKitty Powered by HyperKitty version 1.3.12.