[1/6] 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 . name: set a default name from the python class, as ClassVarMeta did. Also allow setting an explicit string as name instead, per subclass implementation (see I31f390d634e58c384589c50a33ca45d6f86d4e10). Related: SYS#6768 Change-Id: I60ea8fd11fb438ec90ddb08b17b658cbb789c051
This commit is contained in:
@@ -34,24 +34,34 @@ def file_replace_content(file: List[Tuple], new_content: bytes):
|
|||||||
file.append(('fillFileContent', new_content))
|
file.append(('fillFileContent', new_content))
|
||||||
return file
|
return file
|
||||||
|
|
||||||
class ClassVarMeta(abc.ABCMeta):
|
class ConfigurableParameter:
|
||||||
"""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):
|
|
||||||
"""Base class representing a part of the eSIM profile that is configurable during the
|
"""Base class representing a part of the eSIM profile that is configurable during the
|
||||||
personalization process (with dynamic data from elsewhere)."""
|
personalization process (with dynamic data from elsewhere)."""
|
||||||
|
|
||||||
|
# A subclass can set an explicit string as name (like name = "PIN1").
|
||||||
|
# If name is left None, then __init__() will set self.name to a name derived from the python class name (like
|
||||||
|
# "pin1"). See also the get_name() classmethod when you have no instance at hand.
|
||||||
|
name = None
|
||||||
|
|
||||||
def __init__(self, input_value):
|
def __init__(self, input_value):
|
||||||
self.input_value = input_value # the raw input value as given by caller
|
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()
|
self.value = None # the processed input value (e.g. with check digit) as produced by validate()
|
||||||
|
|
||||||
|
# set the instance's name to either an explicit name string, or to a name derived from the class name.
|
||||||
|
if self.name is None:
|
||||||
|
self.name = self.get_name()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_name(cls):
|
||||||
|
"""Return cls.name when it is set, otherwise return the python class name converted from 'CamelCase' to
|
||||||
|
'snake_case'.
|
||||||
|
When using class *instances*, you can just use my_instance.name.
|
||||||
|
When using *classes*, cls.get_name() returns the same name a class instance would have.
|
||||||
|
"""
|
||||||
|
if cls.name:
|
||||||
|
return cls.name
|
||||||
|
return camel_to_snake(cls.__name__)
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
"""Optional validation method. Can be used by derived classes to perform validation
|
"""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."""
|
of the input value (self.value). Will raise an exception if validation fails."""
|
||||||
@@ -105,7 +115,7 @@ class Imsi(ConfigurableParameter):
|
|||||||
# TODO: DF.GSM_ACCESS if not linked?
|
# 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."""
|
"""Configurable Security Domain (SD) Key. Value is presented as bytes."""
|
||||||
# these will be set by derived classes
|
# these will be set by derived classes
|
||||||
key_type = None
|
key_type = None
|
||||||
@@ -144,59 +154,108 @@ class SdKey(ConfigurableParameter, metaclass=ClassVarMeta):
|
|||||||
for pe in pes.get_pes_for_type('securityDomain'):
|
for pe in pes.get_pes_for_type('securityDomain'):
|
||||||
self._apply_sd(pe)
|
self._apply_sd(pe)
|
||||||
|
|
||||||
class SdKeyScp80_01(SdKey, kvn=0x01, key_type=0x88, permitted_len=[16,24,32]): # AES key type
|
class SdKeyScp80_01(SdKey):
|
||||||
pass
|
kvn = 0x01
|
||||||
class SdKeyScp80_01Kic(SdKeyScp80_01, key_id=0x01, key_usage_qual=0x18): # FIXME: ordering?
|
key_type = 0x88 # AES key type
|
||||||
pass
|
allow_len = (16,24,32)
|
||||||
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 SdKeyScp81_01(SdKey, kvn=0x81): # FIXME
|
class SdKeyScp80_01Kic(SdKeyScp80_01):
|
||||||
pass
|
key_id = 0x01
|
||||||
class SdKeyScp81_01Psk(SdKeyScp81_01, key_id=0x01, key_type=0x85, key_usage_qual=0x3C):
|
key_usage_qual = 0x18 # FIXME: ordering?
|
||||||
pass
|
|
||||||
class SdKeyScp81_01Dek(SdKeyScp81_01, key_id=0x02, key_type=0x88, key_usage_qual=0x48):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class SdKeyScp02_20(SdKey, kvn=0x20, key_type=0x88, permitted_len=[16,24,32]): # AES key type
|
class SdKeyScp80_01Kid(SdKeyScp80_01):
|
||||||
pass
|
key_id = 0x02
|
||||||
class SdKeyScp02_20Enc(SdKeyScp02_20, key_id=0x01, key_usage_qual=0x18):
|
key_usage_qual = 0x14
|
||||||
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 SdKeyScp03_30(SdKey, kvn=0x30, key_type=0x88, permitted_len=[16,24,32]): # AES key type
|
class SdKeyScp80_01Kik(SdKeyScp80_01):
|
||||||
pass
|
key_id = 0x03
|
||||||
class SdKeyScp03_30Enc(SdKeyScp03_30, key_id=0x01, key_usage_qual=0x18):
|
key_usage_qual = 0x48
|
||||||
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 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:
|
def obtain_singleton_pe_from_pelist(l: List[ProfileElement], wanted_type: str) -> ProfileElement:
|
||||||
@@ -208,7 +267,7 @@ def obtain_first_pe_from_pelist(l: List[ProfileElement], wanted_type: str) -> Pr
|
|||||||
filtered = list(filter(lambda x: x.type == wanted_type, l))
|
filtered = list(filter(lambda x: x.type == wanted_type, l))
|
||||||
return filtered[0]
|
return filtered[0]
|
||||||
|
|
||||||
class Puk(ConfigurableParameter, metaclass=ClassVarMeta):
|
class Puk(ConfigurableParameter):
|
||||||
"""Configurable PUK (Pin Unblock Code). String ASCII-encoded digits."""
|
"""Configurable PUK (Pin Unblock Code). String ASCII-encoded digits."""
|
||||||
keyReference = None
|
keyReference = None
|
||||||
def validate(self):
|
def validate(self):
|
||||||
@@ -230,12 +289,14 @@ class Puk(ConfigurableParameter, metaclass=ClassVarMeta):
|
|||||||
pukCode['pukValue'] = h2b(padded_puk)
|
pukCode['pukValue'] = h2b(padded_puk)
|
||||||
return
|
return
|
||||||
raise ValueError('cannot find pukCode')
|
raise ValueError('cannot find pukCode')
|
||||||
class Puk1(Puk, keyReference=0x01):
|
|
||||||
pass
|
|
||||||
class Puk2(Puk, keyReference=0x81):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class Pin(ConfigurableParameter, metaclass=ClassVarMeta):
|
class Puk1(Puk):
|
||||||
|
keyReference = 0x01
|
||||||
|
|
||||||
|
class Puk2(Puk):
|
||||||
|
keyReference = 0x81
|
||||||
|
|
||||||
|
class Pin(ConfigurableParameter):
|
||||||
"""Configurable PIN (Personal Identification Number). String of digits."""
|
"""Configurable PIN (Personal Identification Number). String of digits."""
|
||||||
keyReference = None
|
keyReference = None
|
||||||
def validate(self):
|
def validate(self):
|
||||||
@@ -259,7 +320,8 @@ class Pin(ConfigurableParameter, metaclass=ClassVarMeta):
|
|||||||
pinCode['pinValue'] = h2b(padded_pin)
|
pinCode['pinValue'] = h2b(padded_pin)
|
||||||
return
|
return
|
||||||
raise ValueError('cannot find pinCode')
|
raise ValueError('cannot find pinCode')
|
||||||
class AppPin(ConfigurableParameter, metaclass=ClassVarMeta):
|
|
||||||
|
class AppPin(ConfigurableParameter):
|
||||||
"""Configurable PIN (Personal Identification Number). String of digits."""
|
"""Configurable PIN (Personal Identification Number). String of digits."""
|
||||||
keyReference = None
|
keyReference = None
|
||||||
def validate(self):
|
def validate(self):
|
||||||
@@ -288,18 +350,21 @@ class AppPin(ConfigurableParameter, metaclass=ClassVarMeta):
|
|||||||
continue
|
continue
|
||||||
for instance in pes.pes_by_naa[naa]:
|
for instance in pes.pes_by_naa[naa]:
|
||||||
self._apply_one(instance)
|
self._apply_one(instance)
|
||||||
class Pin1(Pin, keyReference=0x01):
|
class Pin1(Pin):
|
||||||
pass
|
keyReference = 0x01
|
||||||
|
|
||||||
# PIN2 is special: telecom + usim + isim + csim
|
# PIN2 is special: telecom + usim + isim + csim
|
||||||
class Pin2(AppPin, keyReference=0x81):
|
class Pin2(AppPin):
|
||||||
pass
|
keyReference = 0x81
|
||||||
class Adm1(Pin, keyReference=0x0A):
|
|
||||||
pass
|
class Adm1(Pin):
|
||||||
class Adm2(Pin, keyReference=0x0B):
|
keyReference = 0x0A
|
||||||
pass
|
|
||||||
|
class Adm2(Pin):
|
||||||
|
keyReference = 0x0B
|
||||||
|
|
||||||
|
|
||||||
class AlgoConfig(ConfigurableParameter, metaclass=ClassVarMeta):
|
class AlgoConfig(ConfigurableParameter):
|
||||||
"""Configurable Algorithm parameter."""
|
"""Configurable Algorithm parameter."""
|
||||||
key = None
|
key = None
|
||||||
def validate(self):
|
def validate(self):
|
||||||
@@ -313,11 +378,13 @@ class AlgoConfig(ConfigurableParameter, metaclass=ClassVarMeta):
|
|||||||
continue
|
continue
|
||||||
algoConfiguration[1][self.key] = self.value
|
algoConfiguration[1][self.key] = self.value
|
||||||
|
|
||||||
class K(AlgoConfig, key='key'):
|
class K(AlgoConfig):
|
||||||
pass
|
key = 'key'
|
||||||
class Opc(AlgoConfig, key='opc'):
|
class Opc(AlgoConfig):
|
||||||
pass
|
key = 'opc'
|
||||||
class AlgorithmID(AlgoConfig, key='algorithmID'):
|
|
||||||
|
class AlgorithmID(AlgoConfig):
|
||||||
|
key = 'algorithmID'
|
||||||
def validate(self):
|
def validate(self):
|
||||||
if self.input_value not in [1, 2, 3]:
|
if self.input_value not in [1, 2, 3]:
|
||||||
raise ValueError('Invalid algorithmID %s' % (self.input_value))
|
raise ValueError('Invalid algorithmID %s' % (self.input_value))
|
||||||
|
|||||||
Reference in New Issue
Block a user