euicc: Migrate ECASD + ISD-R over to global_platform.CardApplicationSD

Actually, the GSMA eUICC is a kind of derivative of a GlobalPlatform
card, and the ECASD and ISD-R are security domains.  As such, we
should make them derived classes of global_platform.CardApplicationSD
which means they inherit some of the shared shell_commands etc.

Change-Id: I660e874d9bcbb8c28a64e4ef82dc53bee97aacfc
This commit is contained in:
Harald Welte
2024-01-11 15:46:58 +01:00
parent 91842b471d
commit 7ba09f9392

View File

@@ -49,15 +49,6 @@ AID_ECASD = "A0000005591010FFFFFFFF8900000200"
AID_ISD_P_FILE = "A0000005591010FFFFFFFF8900000D00" AID_ISD_P_FILE = "A0000005591010FFFFFFFF8900000D00"
AID_ISD_P_MODULE = "A0000005591010FFFFFFFF8900000E00" AID_ISD_P_MODULE = "A0000005591010FFFFFFFF8900000E00"
sw_isdr = {
'ISD-R': {
'6a80': 'Incorrect values in command data',
'6a82': 'Profile not found',
'6a88': 'Reference data not found',
'6985': 'Conditions of use not satisfied',
}
}
class SupportedVersionNumber(BER_TLV_IE, tag=0x82): class SupportedVersionNumber(BER_TLV_IE, tag=0x82):
_construct = GreedyBytes _construct = GreedyBytes
@@ -286,11 +277,12 @@ class EimConfigurationDataSeq(BER_TLV_IE, tag=0xa0, nested=[EimConfigurationData
class GetEimConfigurationData(BER_TLV_IE, tag=0xbf55, nested=[EimConfigurationDataSeq]): class GetEimConfigurationData(BER_TLV_IE, tag=0xbf55, nested=[EimConfigurationDataSeq]):
pass pass
class ADF_ISDR(CardADF): class CardApplicationISDR(pySim.global_platform.CardApplicationSD):
def __init__(self, aid=AID_ISD_R, name='ADF.ISD-R', fid=None, sfid=None, def __init__(self):
desc='ISD-R (Issuer Security Domain Root) Application'): super().__init__(name='ADF.ISD-R', aid=AID_ISD_R,
super().__init__(aid=aid, fid=fid, sfid=sfid, name=name, desc=desc) desc='ISD-R (Issuer Security Domain Root) Application')
self.shell_commands += [self.AddlShellCommands()] self.adf.decode_select_response = self.decode_select_response
self.adf.shell_commands += [self.AddlShellCommands()]
@staticmethod @staticmethod
def store_data(scc: SimCardCommands, tx_do: Hexstr) -> Tuple[Hexstr, SwHexstr]: def store_data(scc: SimCardCommands, tx_do: Hexstr) -> Tuple[Hexstr, SwHexstr]:
@@ -310,7 +302,7 @@ class ADF_ISDR(CardADF):
return ValueError('DO > 255 bytes not supported yet') return ValueError('DO > 255 bytes not supported yet')
else: else:
cmd_do_enc = b'' cmd_do_enc = b''
(data, sw) = ADF_ISDR.store_data(scc, b2h(cmd_do_enc)) (data, sw) = CardApplicationISDR.store_data(scc, b2h(cmd_do_enc))
if data: if data:
if resp_cls: if resp_cls:
resp_do = resp_cls() resp_do = resp_cls()
@@ -336,11 +328,11 @@ class ADF_ISDR(CardADF):
@cmd2.with_argparser(es10x_store_data_parser) @cmd2.with_argparser(es10x_store_data_parser)
def do_es10x_store_data(self, opts): def do_es10x_store_data(self, opts):
"""Perform a raw STORE DATA command as defined for the ES10x eUICC interface.""" """Perform a raw STORE DATA command as defined for the ES10x eUICC interface."""
(data, sw) = ADF_ISDR.store_data(self._cmd.lchan.scc, opts.TX_DO) (data, sw) = CardApplicationISDR.store_data(self._cmd.lchan.scc, opts.TX_DO)
def do_get_euicc_configured_addresses(self, opts): def do_get_euicc_configured_addresses(self, opts):
"""Perform an ES10a GetEuiccConfiguredAddresses function.""" """Perform an ES10a GetEuiccConfiguredAddresses function."""
eca = ADF_ISDR.store_data_tlv(self._cmd.lchan.scc, EuiccConfiguredAddresses(), EuiccConfiguredAddresses) eca = CardApplicationISDR.store_data_tlv(self._cmd.lchan.scc, EuiccConfiguredAddresses(), EuiccConfiguredAddresses)
d = eca.to_dict() d = eca.to_dict()
self._cmd.poutput_json(flatten_dict_lists(d['euicc_configured_addresses'])) self._cmd.poutput_json(flatten_dict_lists(d['euicc_configured_addresses']))
@@ -351,31 +343,31 @@ class ADF_ISDR(CardADF):
def do_set_default_dp_address(self, opts): def do_set_default_dp_address(self, opts):
"""Perform an ES10a SetDefaultDpAddress function.""" """Perform an ES10a SetDefaultDpAddress function."""
sdda_cmd = SetDefaultDpAddress(children=[DefaultDpAddress(decoded=opts.DP_ADDRESS)]) sdda_cmd = SetDefaultDpAddress(children=[DefaultDpAddress(decoded=opts.DP_ADDRESS)])
sdda = ADF_ISDR.store_data_tlv(self._cmd.lchan.scc, sdda_cmd, SetDefaultDpAddress) sdda = CardApplicationISDR.store_data_tlv(self._cmd.lchan.scc, sdda_cmd, SetDefaultDpAddress)
d = sdda.to_dict() d = sdda.to_dict()
self._cmd.poutput_json(flatten_dict_lists(d['set_default_dp_address'])) self._cmd.poutput_json(flatten_dict_lists(d['set_default_dp_address']))
def do_get_euicc_challenge(self, opts): def do_get_euicc_challenge(self, opts):
"""Perform an ES10b GetEUICCChallenge function.""" """Perform an ES10b GetEUICCChallenge function."""
gec = ADF_ISDR.store_data_tlv(self._cmd.lchan.scc, GetEuiccChallenge(), GetEuiccChallenge) gec = CardApplicationISDR.store_data_tlv(self._cmd.lchan.scc, GetEuiccChallenge(), GetEuiccChallenge)
d = gec.to_dict() d = gec.to_dict()
self._cmd.poutput_json(flatten_dict_lists(d['get_euicc_challenge'])) self._cmd.poutput_json(flatten_dict_lists(d['get_euicc_challenge']))
def do_get_euicc_info1(self, opts): def do_get_euicc_info1(self, opts):
"""Perform an ES10b GetEUICCInfo (1) function.""" """Perform an ES10b GetEUICCInfo (1) function."""
ei1 = ADF_ISDR.store_data_tlv(self._cmd.lchan.scc, EuiccInfo1(), EuiccInfo1) ei1 = CardApplicationISDR.store_data_tlv(self._cmd.lchan.scc, EuiccInfo1(), EuiccInfo1)
d = ei1.to_dict() d = ei1.to_dict()
self._cmd.poutput_json(flatten_dict_lists(d['euicc_info1'])) self._cmd.poutput_json(flatten_dict_lists(d['euicc_info1']))
def do_get_euicc_info2(self, opts): def do_get_euicc_info2(self, opts):
"""Perform an ES10b GetEUICCInfo (2) function.""" """Perform an ES10b GetEUICCInfo (2) function."""
ei2 = ADF_ISDR.store_data_tlv(self._cmd.lchan.scc, EuiccInfo2(), EuiccInfo2) ei2 = CardApplicationISDR.store_data_tlv(self._cmd.lchan.scc, EuiccInfo2(), EuiccInfo2)
d = ei2.to_dict() d = ei2.to_dict()
self._cmd.poutput_json(flatten_dict_lists(d['euicc_info2'])) self._cmd.poutput_json(flatten_dict_lists(d['euicc_info2']))
def do_list_notification(self, opts): def do_list_notification(self, opts):
"""Perform an ES10b ListNotification function.""" """Perform an ES10b ListNotification function."""
ln = ADF_ISDR.store_data_tlv(self._cmd.lchan.scc, ListNotificationReq(), ListNotificationResp) ln = CardApplicationISDR.store_data_tlv(self._cmd.lchan.scc, ListNotificationReq(), ListNotificationResp)
d = ln.to_dict() d = ln.to_dict()
self._cmd.poutput_json(flatten_dict_lists(d['list_notification_resp'])) self._cmd.poutput_json(flatten_dict_lists(d['list_notification_resp']))
@@ -386,13 +378,13 @@ class ADF_ISDR(CardADF):
def do_remove_notification_from_list(self, opts): def do_remove_notification_from_list(self, opts):
"""Perform an ES10b RemoveNotificationFromList function.""" """Perform an ES10b RemoveNotificationFromList function."""
rn_cmd = NotificationSentReq(children=[SeqNumber(decoded=opts.SEQ_NR)]) rn_cmd = NotificationSentReq(children=[SeqNumber(decoded=opts.SEQ_NR)])
rn = ADF_ISDR.store_data_tlv(self._cmd.lchan.scc, rn_cmd, NotificationSentResp) rn = CardApplicationISDR.store_data_tlv(self._cmd.lchan.scc, rn_cmd, NotificationSentResp)
d = rn.to_dict() d = rn.to_dict()
self._cmd.poutput_json(flatten_dict_lists(d['notification_sent_resp'])) self._cmd.poutput_json(flatten_dict_lists(d['notification_sent_resp']))
def do_get_profiles_info(self, opts): def do_get_profiles_info(self, opts):
"""Perform an ES10c GetProfilesInfo function.""" """Perform an ES10c GetProfilesInfo function."""
pi = ADF_ISDR.store_data_tlv(self._cmd.lchan.scc, ProfileInfoListReq(), ProfileInfoListResp) pi = CardApplicationISDR.store_data_tlv(self._cmd.lchan.scc, ProfileInfoListReq(), ProfileInfoListResp)
d = pi.to_dict() d = pi.to_dict()
self._cmd.poutput_json(flatten_dict_lists(d['profile_info_list_resp'])) self._cmd.poutput_json(flatten_dict_lists(d['profile_info_list_resp']))
@@ -411,7 +403,7 @@ class ADF_ISDR(CardADF):
p_id = ProfileIdentifier(children=[Iccid(decoded=opts.iccid)]) p_id = ProfileIdentifier(children=[Iccid(decoded=opts.iccid)])
ep_cmd_contents = [p_id, RefreshFlag(decoded=opts.refresh_required)] ep_cmd_contents = [p_id, RefreshFlag(decoded=opts.refresh_required)]
ep_cmd = EnableProfileReq(children=ep_cmd_contents) ep_cmd = EnableProfileReq(children=ep_cmd_contents)
ep = ADF_ISDR.store_data_tlv(self._cmd.lchan.scc, ep_cmd, EnableProfileResp) ep = CardApplicationISDR.store_data_tlv(self._cmd.lchan.scc, ep_cmd, EnableProfileResp)
d = ep.to_dict() d = ep.to_dict()
self._cmd.poutput_json(flatten_dict_lists(d['enable_profile_resp'])) self._cmd.poutput_json(flatten_dict_lists(d['enable_profile_resp']))
@@ -430,7 +422,7 @@ class ADF_ISDR(CardADF):
p_id = ProfileIdentifier(children=[Iccid(decoded=opts.iccid)]) p_id = ProfileIdentifier(children=[Iccid(decoded=opts.iccid)])
dp_cmd_contents = [p_id, RefreshFlag(decoded=opts.refresh_required)] dp_cmd_contents = [p_id, RefreshFlag(decoded=opts.refresh_required)]
dp_cmd = DisableProfileReq(children=dp_cmd_contents) dp_cmd = DisableProfileReq(children=dp_cmd_contents)
dp = ADF_ISDR.store_data_tlv(self._cmd.lchan.scc, dp_cmd, DisableProfileResp) dp = CardApplicationISDR.store_data_tlv(self._cmd.lchan.scc, dp_cmd, DisableProfileResp)
d = dp.to_dict() d = dp.to_dict()
self._cmd.poutput_json(flatten_dict_lists(d['disable_profile_resp'])) self._cmd.poutput_json(flatten_dict_lists(d['disable_profile_resp']))
@@ -448,16 +440,16 @@ class ADF_ISDR(CardADF):
p_id = Iccid(decoded=opts.iccid) p_id = Iccid(decoded=opts.iccid)
dp_cmd_contents = [p_id] dp_cmd_contents = [p_id]
dp_cmd = DeleteProfileReq(children=dp_cmd_contents) dp_cmd = DeleteProfileReq(children=dp_cmd_contents)
dp = ADF_ISDR.store_data_tlv(self._cmd.lchan.scc, dp_cmd, DeleteProfileResp) dp = CardApplicationISDR.store_data_tlv(self._cmd.lchan.scc, dp_cmd, DeleteProfileResp)
d = dp.to_dict() d = dp.to_dict()
self._cmd.poutput_json(flatten_dict_lists(d['delete_profile_resp'])) self._cmd.poutput_json(flatten_dict_lists(d['delete_profile_resp']))
def do_get_eid(self, opts): def do_get_eid(self, opts):
"""Perform an ES10c GetEID function.""" """Perform an ES10c GetEID function."""
(data, sw) = ADF_ISDR.store_data(self._cmd.lchan.scc, 'BF3E035C015A') (data, sw) = CardApplicationISDR.store_data(self._cmd.lchan.scc, 'BF3E035C015A')
ged_cmd = GetEuiccData(children=[TagList(decoded=[0x5A])]) ged_cmd = GetEuiccData(children=[TagList(decoded=[0x5A])])
ged = ADF_ISDR.store_data_tlv(self._cmd.lchan.scc, ged_cmd, GetEuiccData) ged = CardApplicationISDR.store_data_tlv(self._cmd.lchan.scc, ged_cmd, GetEuiccData)
d = ged.to_dict() d = ged.to_dict()
self._cmd.poutput_json(flatten_dict_lists(d['get_euicc_data'])) self._cmd.poutput_json(flatten_dict_lists(d['get_euicc_data']))
@@ -471,46 +463,36 @@ class ADF_ISDR(CardADF):
nickname = opts.profile_nickname or '' nickname = opts.profile_nickname or ''
sn_cmd_contents = [Iccid(decoded=opts.ICCID), ProfileNickname(decoded=nickname)] sn_cmd_contents = [Iccid(decoded=opts.ICCID), ProfileNickname(decoded=nickname)]
sn_cmd = SetNicknameReq(children=sn_cmd_contents) sn_cmd = SetNicknameReq(children=sn_cmd_contents)
sn = ADF_ISDR.store_data_tlv(self._cmd.lchan.scc, sn_cmd, SetNicknameResp) sn = CardApplicationISDR.store_data_tlv(self._cmd.lchan.scc, sn_cmd, SetNicknameResp)
d = sn.to_dict() d = sn.to_dict()
self._cmd.poutput_json(flatten_dict_lists(d['set_nickname_resp'])) self._cmd.poutput_json(flatten_dict_lists(d['set_nickname_resp']))
def do_get_certs(self, opts): def do_get_certs(self, opts):
"""Perform an ES10c GetCerts() function on an IoT eUICC.""" """Perform an ES10c GetCerts() function on an IoT eUICC."""
gc = ADF_ISDR.store_data_tlv(self._cmd.lchan.scc, GetCertsReq(), GetCertsResp) gc = CardApplicationISDR.store_data_tlv(self._cmd.lchan.scc, GetCertsReq(), GetCertsResp)
d = gc.to_dict() d = gc.to_dict()
self._cmd.poutput_json(flatten_dict_lists(d['get_certficiates_resp'])) self._cmd.poutput_json(flatten_dict_lists(d['get_certficiates_resp']))
def do_get_eim_configuration_data(self, opts): def do_get_eim_configuration_data(self, opts):
"""Perform an ES10b GetEimConfigurationData function on an Iot eUICC.""" """Perform an ES10b GetEimConfigurationData function on an Iot eUICC."""
gec = ADF_ISDR.store_data_tlv(self._cmd.lchan.scc, GetEimConfigurationData(), gec = CardApplicationISDR.store_data_tlv(self._cmd.lchan.scc, GetEimConfigurationData(),
GetEimConfigurationData) GetEimConfigurationData)
d = gec.to_dict() d = gec.to_dict()
self._cmd.poutput_json(flatten_dict_lists(d['get_eim_configuration_data'])) self._cmd.poutput_json(flatten_dict_lists(d['get_eim_configuration_data']))
class CardApplicationECASD(pySim.global_platform.CardApplicationSD):
class ADF_ECASD(CardADF):
def __init__(self, aid=AID_ECASD, name='ADF.ECASD', fid=None, sfid=None,
desc='ECASD (eUICC Controlling Authority Security Domain) Application'):
super().__init__(aid=aid, fid=fid, sfid=sfid, name=name, desc=desc)
self.shell_commands += [self.AddlShellCommands()]
def decode_select_response(self, data_hex: Hexstr) -> object: def decode_select_response(self, data_hex: Hexstr) -> object:
t = FciTemplate() t = FciTemplate()
t.from_tlv(h2b(data_hex)) t.from_tlv(h2b(data_hex))
d = t.to_dict() d = t.to_dict()
return flatten_dict_lists(d['fci_template']) return flatten_dict_lists(d['fci_template'])
def __init__(self):
super().__init__(name='ADF.ECASD', aid=AID_ECASD,
desc='ECASD (eUICC Controlling Authority Security Domain) Application')
self.adf.decode_select_response = self.decode_select_response
self.adf.shell_commands += [self.AddlShellCommands()]
@with_default_category('Application-Specific Commands') @with_default_category('Application-Specific Commands')
class AddlShellCommands(CommandSet): class AddlShellCommands(CommandSet):
pass pass
class CardApplicationISDR(CardApplication):
def __init__(self):
super().__init__('ISD-R', adf=ADF_ISDR(), sw=sw_isdr)
class CardApplicationECASD(CardApplication):
def __init__(self):
super().__init__('ECASD', adf=ADF_ECASD(), sw=sw_isdr)