mirror of
https://gitea.osmocom.org/sim-card/pysim.git
synced 2026-03-16 18:38:32 +03:00
personalization: make sense of SdKey subclasses
After a call with Harald, I think I finally understand what SdKey subclasses we need. Change-Id: I8c9e6095e200103d2e1779964be06fff63c5cebf
This commit is contained in:
@@ -495,8 +495,9 @@ class SdKey(BinaryParam):
|
||||
"""Configurable Security Domain (SD) Key. Value is presented as bytes."""
|
||||
# these will be set by subclasses
|
||||
key_type = None
|
||||
key_id = None
|
||||
kvn = None
|
||||
reserved_kvn = tuple() # tuple of all reserved kvn for a given SCPxx
|
||||
key_id = None
|
||||
key_usage_qual = None
|
||||
default_source = param_source.RandomHexDigitSource
|
||||
|
||||
@@ -515,7 +516,7 @@ class SdKey(BinaryParam):
|
||||
key = SecurityDomainKey(
|
||||
key_version_number=cls.kvn,
|
||||
key_id=cls.key_id,
|
||||
key_usage_qualifier=KeyUsageQualifier.build(cls.key_usage_qual),
|
||||
key_usage_qualifier=cls.key_usage_qual,
|
||||
key_components=set_components,
|
||||
)
|
||||
pe.add_key(key)
|
||||
@@ -536,109 +537,323 @@ class SdKey(BinaryParam):
|
||||
if kc:
|
||||
yield { cls.name: b2h(kc) }
|
||||
|
||||
class SdKeyScp80_01(SdKey):
|
||||
# Offer these Security Domain Keys:
|
||||
#
|
||||
# security domain | reserved KVN range
|
||||
# ----------------------------
|
||||
# SCP80 | 0x01 .. 0x0f
|
||||
# SCP81 | 0x81 .. 0x8f
|
||||
# SCP02 | 0x20 .. 0x2f, 0xff
|
||||
# SCP03 | 0x30 .. 0x3f
|
||||
#
|
||||
# The KVN allows adding multiple security domains of the same type.
|
||||
#
|
||||
# Also, for each security domain, there are three keys: ENC, MAC and DEK, indicated by key_id.
|
||||
# key | alternate name | key_id | key_usage_qual
|
||||
#-----------------------------------------------
|
||||
# ENC | KIC | 0x01 | 0x18
|
||||
# MAC | KID | 0x02 | 0x14
|
||||
# DEK | KIK | 0x03 | 0x48
|
||||
#
|
||||
# For each, offer a couple of separate SdKey subclasses, only partially covering the reserved KVN range. For KVN, again
|
||||
# a separate subclass for eack key_id for ENC, MAC and DEK.
|
||||
#
|
||||
# All of these are AES keys.
|
||||
#
|
||||
# For example, for SCP80 we have:
|
||||
# SdKeyAes
|
||||
# SdKeyScp80Kvn01
|
||||
# SdKeyScp80Kvn01Enc
|
||||
# SdKeyScp80Kvn01Mac
|
||||
# SdKeyScp80Kvn01Dek
|
||||
# SdKeyScp80Kvn02
|
||||
# SdKeyScp80Kvn02Enc
|
||||
# SdKeyScp80Kvn02Mac
|
||||
# SdKeyScp80Kvn02Dek
|
||||
# SdKeyScp80Kvn03
|
||||
# SdKeyScp80Kvn03Enc
|
||||
# SdKeyScp80Kvn03Mac
|
||||
# SdKeyScp80Kvn03Dek
|
||||
#
|
||||
# (Only the leaf nodes with ...Enc/Mac/Dek are returned by
|
||||
# ConfigurableParameter.get_all_implementations(allow_abstract=False))
|
||||
|
||||
class SdKeyAes(SdKey):
|
||||
key_type = KeyType.aes
|
||||
allow_len = (16,24,32)
|
||||
default_value = '00' * 32
|
||||
|
||||
|
||||
class SdKeyScp80(SdKeyAes):
|
||||
name = 'SCP80'
|
||||
reserved_kvn = tuple(range(0x01, 0x0f + 1))
|
||||
|
||||
class SdKeyScp80Kvn01(SdKeyScp80):
|
||||
name = 'SCP80 KVN01'
|
||||
kvn = 0x01
|
||||
key_type = 0x88 # AES key type
|
||||
allow_len = (16,24,32)
|
||||
|
||||
class SdKeyScp80_01Kic(SdKeyScp80_01):
|
||||
class SdKeyScp80Kvn01Enc(SdKeyScp80Kvn01):
|
||||
is_abstract = False
|
||||
name = SdKeyScp80Kvn01.name + ' ENC'
|
||||
key_id = 0x01
|
||||
key_usage_qual = 0x18 # FIXME: ordering?
|
||||
|
||||
class SdKeyScp80_01Kid(SdKeyScp80_01):
|
||||
key_usage_qual = 0x18
|
||||
class SdKeyScp80Kvn01Mac(SdKeyScp80Kvn01):
|
||||
is_abstract = False
|
||||
name = SdKeyScp80Kvn01.name + ' MAC'
|
||||
key_id = 0x02
|
||||
key_usage_qual = 0x14
|
||||
|
||||
class SdKeyScp80_01Kik(SdKeyScp80_01):
|
||||
class SdKeyScp80Kvn01Dek(SdKeyScp80Kvn01):
|
||||
is_abstract = False
|
||||
name = SdKeyScp80Kvn01.name + ' DEK'
|
||||
key_id = 0x03
|
||||
key_usage_qual = 0x48
|
||||
|
||||
|
||||
class SdKeyScp81_01(SdKey):
|
||||
kvn = 0x81 # FIXME
|
||||
|
||||
class SdKeyScp81_01Psk(SdKeyScp81_01):
|
||||
class SdKeyScp80Kvn02(SdKeyScp80):
|
||||
name = 'SCP80 KVN02'
|
||||
kvn = 0x02
|
||||
class SdKeyScp80Kvn02Enc(SdKeyScp80Kvn02):
|
||||
is_abstract = False
|
||||
name = SdKeyScp80Kvn02.name + ' ENC'
|
||||
key_id = 0x01
|
||||
key_type = 0x85
|
||||
key_usage_qual = 0x3C
|
||||
|
||||
class SdKeyScp81_01Dek(SdKeyScp81_01):
|
||||
key_usage_qual = 0x18
|
||||
class SdKeyScp80Kvn02Mac(SdKeyScp80Kvn02):
|
||||
is_abstract = False
|
||||
name = SdKeyScp80Kvn02.name + ' MAC'
|
||||
key_id = 0x02
|
||||
key_type = 0x88
|
||||
key_usage_qual = 0x14
|
||||
class SdKeyScp80Kvn02Dek(SdKeyScp80Kvn02):
|
||||
is_abstract = False
|
||||
name = SdKeyScp80Kvn02.name + ' DEK'
|
||||
key_id = 0x03
|
||||
key_usage_qual = 0x48
|
||||
|
||||
class SdKeyScp80Kvn03(SdKeyScp80):
|
||||
name = 'SCP80 KVN03'
|
||||
kvn = 0x03
|
||||
class SdKeyScp80Kvn03Enc(SdKeyScp80Kvn03):
|
||||
is_abstract = False
|
||||
name = SdKeyScp80Kvn03.name + ' ENC'
|
||||
key_id = 0x01
|
||||
key_usage_qual = 0x18
|
||||
class SdKeyScp80Kvn03Mac(SdKeyScp80Kvn03):
|
||||
is_abstract = False
|
||||
name = SdKeyScp80Kvn03.name + ' MAC'
|
||||
key_id = 0x02
|
||||
key_usage_qual = 0x14
|
||||
class SdKeyScp80Kvn03Dek(SdKeyScp80Kvn03):
|
||||
is_abstract = False
|
||||
name = SdKeyScp80Kvn03.name + ' DEK'
|
||||
key_id = 0x03
|
||||
key_usage_qual = 0x48
|
||||
|
||||
class SdKeyScp02_20(SdKey):
|
||||
# "omitting" SdKeyScp80Kvn04 ... Kvn0f
|
||||
|
||||
class SdKeyScp81(SdKeyAes):
|
||||
name = 'SCP81'
|
||||
reserved_kvn = tuple(range(0x81, 0x8f + 1))
|
||||
|
||||
class SdKeyScp81Kvn81(SdKeyScp81):
|
||||
name = 'SCP81 KVN81'
|
||||
kvn = 0x81
|
||||
class SdKeyScp81Kvn81Enc(SdKeyScp81Kvn81):
|
||||
is_abstract = False
|
||||
name = SdKeyScp81Kvn81.name + ' ENC'
|
||||
key_id = 0x01
|
||||
key_usage_qual = 0x18
|
||||
class SdKeyScp81Kvn81Mac(SdKeyScp81Kvn81):
|
||||
is_abstract = False
|
||||
name = SdKeyScp81Kvn81.name + ' MAC'
|
||||
key_id = 0x02
|
||||
key_usage_qual = 0x14
|
||||
class SdKeyScp81Kvn81Dek(SdKeyScp81Kvn81):
|
||||
is_abstract = False
|
||||
name = SdKeyScp81Kvn81.name + ' DEK'
|
||||
key_id = 0x03
|
||||
key_usage_qual = 0x48
|
||||
|
||||
class SdKeyScp81Kvn82(SdKeyScp81):
|
||||
name = 'SCP81 KVN82'
|
||||
kvn = 0x82
|
||||
class SdKeyScp81Kvn82Enc(SdKeyScp81Kvn82):
|
||||
is_abstract = False
|
||||
name = SdKeyScp81Kvn82.name + ' ENC'
|
||||
key_id = 0x01
|
||||
key_usage_qual = 0x18
|
||||
class SdKeyScp81Kvn82Mac(SdKeyScp81Kvn82):
|
||||
is_abstract = False
|
||||
name = SdKeyScp81Kvn82.name + ' MAC'
|
||||
key_id = 0x02
|
||||
key_usage_qual = 0x14
|
||||
class SdKeyScp81Kvn82Dek(SdKeyScp81Kvn82):
|
||||
is_abstract = False
|
||||
name = SdKeyScp81Kvn82.name + ' DEK'
|
||||
key_id = 0x03
|
||||
key_usage_qual = 0x48
|
||||
|
||||
class SdKeyScp81Kvn83(SdKeyScp81):
|
||||
name = 'SCP81 KVN83'
|
||||
kvn = 0x83
|
||||
class SdKeyScp81Kvn83Enc(SdKeyScp81Kvn83):
|
||||
is_abstract = False
|
||||
name = SdKeyScp81Kvn83.name + ' ENC'
|
||||
key_id = 0x01
|
||||
key_usage_qual = 0x18
|
||||
class SdKeyScp81Kvn83Mac(SdKeyScp81Kvn83):
|
||||
is_abstract = False
|
||||
name = SdKeyScp81Kvn83.name + ' MAC'
|
||||
key_id = 0x02
|
||||
key_usage_qual = 0x14
|
||||
class SdKeyScp81Kvn83Dek(SdKeyScp81Kvn83):
|
||||
is_abstract = False
|
||||
name = SdKeyScp81Kvn83.name + ' DEK'
|
||||
key_id = 0x03
|
||||
key_usage_qual = 0x48
|
||||
|
||||
# "omitting" SdKeyScp81Kvn84 ... Kvn8f
|
||||
|
||||
class SdKeyScp02(SdKeyAes):
|
||||
name = 'SCP02'
|
||||
reserved_kvn = tuple(range(0x20, 0x2f + 1)) + (0xff, )
|
||||
class SdKeyScp02Kvn20(SdKeyScp02):
|
||||
name = 'SCP02 20'
|
||||
kvn = 0x20
|
||||
key_type = 0x88 # AES key type
|
||||
allow_len = (16,24,32)
|
||||
|
||||
class SdKeyScp02_20Enc(SdKeyScp02_20):
|
||||
class SdKeyScp02Kvn20Enc(SdKeyScp02Kvn20):
|
||||
is_abstract = False
|
||||
name = SdKeyScp02Kvn20.name + ' ENC'
|
||||
key_id = 0x01
|
||||
key_usage_qual = 0x18
|
||||
|
||||
class SdKeyScp02_20Mac(SdKeyScp02_20):
|
||||
class SdKeyScp02Kvn20Mac(SdKeyScp02Kvn20):
|
||||
is_abstract = False
|
||||
name = SdKeyScp02Kvn20.name + ' MAC'
|
||||
key_id = 0x02
|
||||
key_usage_qual = 0x14
|
||||
class SdKeyScp02Kvn20Dek(SdKeyScp02Kvn20):
|
||||
is_abstract = False
|
||||
name = SdKeyScp02Kvn20.name + ' DEK'
|
||||
key_id = 0x03
|
||||
key_usage_qual = 0x48
|
||||
|
||||
class SdKeyScp02_20Dek(SdKeyScp02_20):
|
||||
class SdKeyScp02Kvn21(SdKeyScp02):
|
||||
name = 'SCP02 21'
|
||||
kvn = 0x21
|
||||
class SdKeyScp02Kvn21Enc(SdKeyScp02Kvn21):
|
||||
is_abstract = False
|
||||
name = SdKeyScp02Kvn21.name + ' ENC'
|
||||
key_id = 0x01
|
||||
key_usage_qual = 0x18
|
||||
class SdKeyScp02Kvn21Mac(SdKeyScp02Kvn21):
|
||||
is_abstract = False
|
||||
name = SdKeyScp02Kvn21.name + ' MAC'
|
||||
key_id = 0x02
|
||||
key_usage_qual = 0x14
|
||||
class SdKeyScp02Kvn21Dek(SdKeyScp02Kvn21):
|
||||
is_abstract = False
|
||||
name = SdKeyScp02Kvn21.name + ' DEK'
|
||||
key_id = 0x03
|
||||
key_usage_qual = 0x48
|
||||
|
||||
class SdKeyScp02Kvn22(SdKeyScp02):
|
||||
name = 'SCP02 22'
|
||||
kvn = 0x22
|
||||
class SdKeyScp02Kvn22Enc(SdKeyScp02Kvn22):
|
||||
is_abstract = False
|
||||
name = SdKeyScp02Kvn22.name + ' ENC'
|
||||
key_id = 0x01
|
||||
key_usage_qual = 0x18
|
||||
class SdKeyScp02Kvn22Mac(SdKeyScp02Kvn22):
|
||||
is_abstract = False
|
||||
name = SdKeyScp02Kvn22.name + ' MAC'
|
||||
key_id = 0x02
|
||||
key_usage_qual = 0x14
|
||||
class SdKeyScp02Kvn22Dek(SdKeyScp02Kvn22):
|
||||
is_abstract = False
|
||||
name = SdKeyScp02Kvn22.name + ' DEK'
|
||||
key_id = 0x03
|
||||
key_usage_qual = 0x48
|
||||
|
||||
# "omitting" SdKeyScp02Kvn23 ... Kvn2f
|
||||
|
||||
class SdKeyScp02Kvnff(SdKeyScp02):
|
||||
name = 'SCP02 ff'
|
||||
kvn = 0xff
|
||||
class SdKeyScp02KvnffEnc(SdKeyScp02Kvnff):
|
||||
is_abstract = False
|
||||
name = SdKeyScp02Kvnff.name + ' ENC'
|
||||
key_id = 0x01
|
||||
key_usage_qual = 0x18
|
||||
class SdKeyScp02KvnffMac(SdKeyScp02Kvnff):
|
||||
is_abstract = False
|
||||
name = SdKeyScp02Kvnff.name + ' MAC'
|
||||
key_id = 0x02
|
||||
key_usage_qual = 0x14
|
||||
class SdKeyScp02KvnffDek(SdKeyScp02Kvnff):
|
||||
is_abstract = False
|
||||
name = SdKeyScp02Kvnff.name + ' DEK'
|
||||
key_id = 0x03
|
||||
key_usage_qual = 0x48
|
||||
|
||||
|
||||
class SdKeyScp03_30(SdKey):
|
||||
class SdKeyScp03(SdKeyAes):
|
||||
name = 'SCP03 30'
|
||||
reserved_kvn = tuple(range(0x30, 0x3f + 1))
|
||||
|
||||
class SdKeyScp03Kvn30(SdKeyScp03):
|
||||
name = 'SCP03 30'
|
||||
kvn = 0x30
|
||||
key_type = 0x88 # AES key type
|
||||
allow_len = (16,24,32)
|
||||
|
||||
class SdKeyScp03_30Enc(SdKeyScp03_30):
|
||||
class SdKeyScp03Kvn30Enc(SdKeyScp03Kvn30):
|
||||
is_abstract = False
|
||||
name = SdKeyScp03Kvn30.name + ' ENC'
|
||||
key_id = 0x01
|
||||
key_usage_qual = 0x18
|
||||
|
||||
class SdKeyScp03_30Mac(SdKeyScp03_30):
|
||||
class SdKeyScp03Kvn30Mac(SdKeyScp03Kvn30):
|
||||
is_abstract = False
|
||||
name = SdKeyScp03Kvn30.name + ' MAC'
|
||||
key_id = 0x02
|
||||
key_usage_qual = 0x14
|
||||
|
||||
class SdKeyScp03_30Dek(SdKeyScp03_30):
|
||||
class SdKeyScp03Kvn30Dek(SdKeyScp03Kvn30):
|
||||
is_abstract = False
|
||||
name = SdKeyScp03Kvn30.name + ' DEK'
|
||||
key_id = 0x03
|
||||
key_usage_qual = 0x48
|
||||
|
||||
|
||||
class SdKeyScp03_31(SdKey):
|
||||
class SdKeyScp03Kvn31(SdKeyScp03):
|
||||
name = 'SCP03 31'
|
||||
kvn = 0x31
|
||||
key_type = 0x88 # AES key type
|
||||
allow_len = (16,24,32)
|
||||
|
||||
class SdKeyScp03_31Enc(SdKeyScp03_31):
|
||||
class SdKeyScp03Kvn31Enc(SdKeyScp03Kvn31):
|
||||
is_abstract = False
|
||||
name = SdKeyScp03Kvn31.name + ' ENC'
|
||||
key_id = 0x01
|
||||
key_usage_qual = 0x18
|
||||
|
||||
class SdKeyScp03_31Mac(SdKeyScp03_31):
|
||||
class SdKeyScp03Kvn31Mac(SdKeyScp03Kvn31):
|
||||
is_abstract = False
|
||||
name = SdKeyScp03Kvn31.name + ' MAC'
|
||||
key_id = 0x02
|
||||
key_usage_qual = 0x14
|
||||
|
||||
class SdKeyScp03_31Dek(SdKeyScp03_31):
|
||||
class SdKeyScp03Kvn31Dek(SdKeyScp03Kvn31):
|
||||
is_abstract = False
|
||||
name = SdKeyScp03Kvn31.name + ' DEK'
|
||||
key_id = 0x03
|
||||
key_usage_qual = 0x48
|
||||
|
||||
|
||||
class SdKeyScp03_32(SdKey):
|
||||
class SdKeyScp03Kvn32(SdKeyScp03):
|
||||
name = 'SCP03 32'
|
||||
kvn = 0x32
|
||||
key_type = 0x88 # AES key type
|
||||
allow_len = (16,24,32)
|
||||
|
||||
class SdKeyScp03_32Enc(SdKeyScp03_32):
|
||||
class SdKeyScp03Kvn32Enc(SdKeyScp03Kvn32):
|
||||
is_abstract = False
|
||||
name = SdKeyScp03Kvn32.name + ' ENC'
|
||||
key_id = 0x01
|
||||
key_usage_qual = 0x18
|
||||
|
||||
class SdKeyScp03_32Mac(SdKeyScp03_32):
|
||||
class SdKeyScp03Kvn32Mac(SdKeyScp03Kvn32):
|
||||
is_abstract = False
|
||||
name = SdKeyScp03Kvn32.name + ' MAC'
|
||||
key_id = 0x02
|
||||
key_usage_qual = 0x14
|
||||
|
||||
class SdKeyScp03_32Dek(SdKeyScp03_32):
|
||||
class SdKeyScp03Kvn32Dek(SdKeyScp03Kvn32):
|
||||
is_abstract = False
|
||||
name = SdKeyScp03Kvn32.name + ' DEK'
|
||||
key_id = 0x03
|
||||
key_usage_qual = 0x48
|
||||
|
||||
# "omitting" SdKeyScp03Kvn33 ... Kvn3f
|
||||
|
||||
def obtain_all_pe_from_pelist(l: List[ProfileElement], wanted_type: str) -> ProfileElement:
|
||||
return (pe for pe in l if pe.type == wanted_type)
|
||||
|
||||
@@ -63,6 +63,44 @@ class SaipTest(unittest.TestCase):
|
||||
# TODO: we don't actually test the results here, but we just verify there is no exception
|
||||
pes.to_der()
|
||||
|
||||
def test_personalization2(self):
|
||||
"""Test some of the personalization operations."""
|
||||
pes = ProfileElementSequence.from_der(self.per_input)
|
||||
prev_val = set(SdKeyScp80_01Kic.get_values_from_pes(pes))
|
||||
print(f'{prev_val=}')
|
||||
self.assertTrue(prev_val)
|
||||
|
||||
set_val = '42342342342342342342342342342342'
|
||||
param = SdKeyScp80_01Kic(set_val)
|
||||
param.validate()
|
||||
param.apply(pes)
|
||||
|
||||
get_val1 = set(SdKeyScp80_01Kic.get_values_from_pes(pes))
|
||||
print(f'{get_val1=} {set_val=}')
|
||||
self.assertEqual(get_val1, set((set_val,)))
|
||||
|
||||
get_val1b = set(SdKeyScp80_01Kic.get_values_from_pes(pes))
|
||||
print(f'{get_val1b=} {set_val=}')
|
||||
self.assertEqual(get_val1b, set((set_val,)))
|
||||
|
||||
print("HELLOO")
|
||||
der = pes.to_der()
|
||||
print("DONEDONE")
|
||||
|
||||
get_val1c = set(SdKeyScp80_01Kic.get_values_from_pes(pes))
|
||||
print(f'{get_val1c=} {set_val=}')
|
||||
self.assertEqual(get_val1c, set((set_val,)))
|
||||
|
||||
# assertTrue to not dump the entire der.
|
||||
# Expecting the modified DER to be different. If this assertion fails, then no change has happened in the output
|
||||
# DER and the ConfigurableParameter subclass is buggy.
|
||||
self.assertTrue(der != self.per_input)
|
||||
|
||||
pes2 = ProfileElementSequence.from_der(der)
|
||||
get_val2 = set(SdKeyScp80_01Kic.get_values_from_pes(pes2))
|
||||
print(f'{get_val2=} {set_val=}')
|
||||
self.assertEqual(get_val2, set((set_val,)))
|
||||
|
||||
def test_constructor_encode(self):
|
||||
"""Test that DER-encoding of PE created by "empty" constructor works without raising exception."""
|
||||
for cls in [ProfileElementMF, ProfileElementPuk, ProfileElementPin, ProfileElementTelecom,
|
||||
|
||||
Reference in New Issue
Block a user