laforge has submitted this change. ( https://gerrit.osmocom.org/c/pysim/+/36931?usp=email )
( 5 is the latest approved patch-set. No files were changed between the latest approved patch-set and the submitted one. )Change subject: global_platform/euicc: Implement obtaining SCP keys from CardKeyProvider ...................................................................... global_platform/euicc: Implement obtaining SCP keys from CardKeyProvider Now that CardKeyProvider is capable of storing key materials transport-key-encrypted, we can use this functionality to look up the SCP02 / SCP03 key material for a given security domain. This patch implements this for the ISD-R and ECASD using a look-up by EID inside the CSV. Change-Id: I2a21f031ab8af88019af1b8390612678b9b35880 --- M pySim/euicc.py M pySim/global_platform/__init__.py 2 files changed, 53 insertions(+), 8 deletions(-) Approvals: osmith: Looks good to me, but someone else must approve fixeria: Looks good to me, but someone else must approve Jenkins Builder: Verified laforge: Looks good to me, approved diff --git a/pySim/euicc.py b/pySim/euicc.py index a771a22..ddfe939 100644 --- a/pySim/euicc.py +++ b/pySim/euicc.py @@ -315,6 +315,8 @@ desc='ISD-R (Issuer Security Domain Root) Application') self.adf.decode_select_response = self.decode_select_response self.adf.shell_commands += [self.AddlShellCommands()] + # we attempt to retrieve ISD-R key material from CardKeyProvider identified by EID + self.adf.scp_key_identity = 'EID' @staticmethod def store_data(scc: SimCardCommands, tx_do: Hexstr, exp_sw: SwMatchstr ="9000") -> Tuple[Hexstr, SwHexstr]: @@ -539,6 +541,8 @@ desc='ECASD (eUICC Controlling Authority Security Domain) Application') self.adf.decode_select_response = self.decode_select_response self.adf.shell_commands += [self.AddlShellCommands()] + # we attempt to retrieve ECASD key material from CardKeyProvider identified by EID + self.adf.scp_key_identity = 'EID' @with_default_category('Application-Specific Commands') class AddlShellCommands(CommandSet): diff --git a/pySim/global_platform/__init__.py b/pySim/global_platform/__init__.py index f440fd0..0be316b 100644 --- a/pySim/global_platform/__init__.py +++ b/pySim/global_platform/__init__.py @@ -23,6 +23,7 @@ from construct import Struct, GreedyRange, FlagsEnum, Int16ub, Int24ub, Padding, Bit, Const from Cryptodome.Random import get_random_bytes from Cryptodome.Cipher import DES, DES3, AES +from pySim.card_key_provider import card_key_provider_get_field from pySim.global_platform.scp import SCP02, SCP03 from pySim.construct import * from pySim.utils import * @@ -719,23 +720,33 @@ return self._cmd.lchan.scc.send_apdu_checksw(cmd_hex) est_scp02_parser = argparse.ArgumentParser() - est_scp02_parser.add_argument('--key-ver', type=auto_uint8, required=True, - help='Key Version Number (KVN)') - est_scp02_parser.add_argument('--key-enc', type=is_hexstr, required=True, - help='Secure Channel Encryption Key') - est_scp02_parser.add_argument('--key-mac', type=is_hexstr, required=True, - help='Secure Channel MAC Key') - est_scp02_parser.add_argument('--key-dek', type=is_hexstr, required=True, - help='Data Encryption Key') + est_scp02_parser.add_argument('--key-ver', type=auto_uint8, required=True, help='Key Version Number (KVN)') est_scp02_parser.add_argument('--host-challenge', type=is_hexstr, help='Hard-code the host challenge; default: random') est_scp02_parser.add_argument('--security-level', type=auto_uint8, default=0x01, help='Security Level. Default: 0x01 (C-MAC only)') + est_scp02_p_k = est_scp02_parser.add_argument_group('Manual key specification') + est_scp02_p_k.add_argument('--key-enc', type=is_hexstr, help='Secure Channel Encryption Key') + est_scp02_p_k.add_argument('--key-mac', type=is_hexstr, help='Secure Channel MAC Key') + est_scp02_p_k.add_argument('--key-dek', type=is_hexstr, help='Data Encryption Key') + est_scp02_p_csv = est_scp02_parser.add_argument_group('Obtain keys from CardKeyProvider (e.g. CSV') + est_scp02_p_csv.add_argument('--key-provider-suffix', help='Suffix for key names in CardKeyProvider') @cmd2.with_argparser(est_scp02_parser) def do_establish_scp02(self, opts): """Establish a secure channel using the GlobalPlatform SCP02 protocol. It can be released again by using `release_scp`.""" + if opts.key_provider_suffix: + suffix = opts.key_provider_suffix + id_field_name = self._cmd.lchan.selected_adf.scp_key_identity + identity = self._cmd.rs.identity.get(id_field_name) + opts.key_enc = card_key_provider_get_field('SCP02_ENC_' + suffix, key=id_field_name, value=identity) + opts.key_mac = card_key_provider_get_field('SCP02_MAC_' + suffix, key=id_field_name, value=identity) + opts.key_dek = card_key_provider_get_field('SCP02_DEK_' + suffix, key=id_field_name, value=identity) + else: + if not opts.key_enc or not opts.key_mac: + self._cmd.poutput("Cannot establish SCP02 without at least ENC and MAC keys given!") + return if self._cmd.lchan.scc.scp: self._cmd.poutput("Cannot establish SCP02 as this lchan already has a SCP instance!") return @@ -751,6 +762,17 @@ def do_establish_scp03(self, opts): """Establish a secure channel using the GlobalPlatform SCP03 protocol. It can be released again by using `release_scp`.""" + if opts.key_provider_suffix: + suffix = opts.key_provider_suffix + id_field_name = self._cmd.lchan.selected_adf.scp_key_identity + identity = self._cmd.rs.identity.get(id_field_name) + opts.key_enc = card_key_provider_get_field('SCP03_ENC_' + suffix, key=id_field_name, value=identity) + opts.key_mac = card_key_provider_get_field('SCP03_MAC_' + suffix, key=id_field_name, value=identity) + opts.key_dek = card_key_provider_get_field('SCP03_DEK_' + suffix, key=id_field_name, value=identity) + else: + if not opts.key_enc or not opts.key_mac: + self._cmd.poutput("Cannot establish SCP03 without at least ENC and MAC keys given!") + return if self._cmd.lchan.scc.scp: self._cmd.poutput("Cannot establish SCP03 as this lchan already has a SCP instance!") return @@ -787,6 +809,9 @@ __intermediate = True def __init__(self, aid: str, name: str, desc: str): super().__init__(name, adf=ADF_SD(aid, name, desc), sw=sw_table) + # the identity (e.g. 'ICCID', 'EID') that should be used as a look-up key to attempt to retrieve + # the key material for the security domain from the CardKeyProvider + self.adf.scp_key_identity = None # Card Application of Issuer Security Domain class CardApplicationISD(CardApplicationSD): -- To view, visit https://gerrit.osmocom.org/c/pysim/+/36931?usp=email To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: pysim Gerrit-Branch: master Gerrit-Change-Id: I2a21f031ab8af88019af1b8390612678b9b35880 Gerrit-Change-Number: 36931 Gerrit-PatchSet: 7 Gerrit-Owner: laforge <lafo...@osmocom.org> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: dexter <pma...@sysmocom.de> Gerrit-Reviewer: fixeria <vyanits...@sysmocom.de> Gerrit-Reviewer: laforge <lafo...@osmocom.org> Gerrit-Reviewer: osmith <osm...@sysmocom.de> Gerrit-MessageType: merged