laforge has uploaded this change for review. ( 
https://gerrit.osmocom.org/c/pysim/+/35764?usp=email )


Change subject: Add global_platform shell command establish_scp02 and 
release_scp
......................................................................

Add global_platform shell command establish_scp02 and release_scp

Those commands can be used to establish and release a SCP02 secure
channel on the currently active logical channel.

The prompt is adjusted with a 'SCP02' prefix while the secure channel is
established.

Change-Id: Ib2f3c8f0563f81a941dd55b97c9836e3a6856407
---
M docs/shell.rst
M pySim-shell.py
M pySim/global_platform/__init__.py
M pySim/global_platform/scp02.py
4 files changed, 83 insertions(+), 2 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/64/35764/1

diff --git a/docs/shell.rst b/docs/shell.rst
index a917f8f..dff6cd1 100644
--- a/docs/shell.rst
+++ b/docs/shell.rst
@@ -959,6 +959,16 @@
    :module: pySim.global_platform
    :func: ADF_SD.AddlShellCommands.put_key_parser

+establish_scp02
+~~~~~~~~~~~~~~~
+.. argparse::
+   :module: pySim.global_platform
+   :func: ADF_SD.AddlShellCommands.est_scp02_parser
+
+release_scp
+~~~~~~~~~~~
+Release any previously established SCP (Secure Channel Protocol)
+

 eUICC ISD-R commands
 --------------------
diff --git a/pySim-shell.py b/pySim-shell.py
index 70eaee2..abe0b5f 100755
--- a/pySim-shell.py
+++ b/pySim-shell.py
@@ -205,7 +205,11 @@
     def update_prompt(self):
         if self.lchan:
             path_str = self.lchan.selected_file.fully_qualified_path_str(not 
self.numeric_path)
-            self.prompt = 'pySIM-shell (%02u:%s)> ' % (self.lchan.lchan_nr, 
path_str)
+            scp = self.lchan.scc.scp
+            if scp:
+                self.prompt = 'pySIM-shell (%s:%02u:%s)> ' % (str(scp), 
self.lchan.lchan_nr, path_str)
+            else:
+                self.prompt = 'pySIM-shell (%02u:%s)> ' % 
(self.lchan.lchan_nr, path_str)
         else:
             if self.card:
                 self.prompt = 'pySIM-shell (no card profile)> '
@@ -258,6 +262,8 @@
     def do_reset(self, opts):
         """Reset the Card."""
         atr = self.card.reset()
+        if self.lchan and self.lchan.scc.scp:
+            self.lchan.scc.scp = None
         self.poutput('Card ATR: %s' % i2h(atr))
         self.update_prompt()

diff --git a/pySim/global_platform/__init__.py 
b/pySim/global_platform/__init__.py
index 385d438..44a24df 100644
--- a/pySim/global_platform/__init__.py
+++ b/pySim/global_platform/__init__.py
@@ -1,7 +1,7 @@
 # coding=utf-8
 """Partial Support for GlobalPLatform Card Spec (currently 2.1.1)

-(C) 2022-2023 by Harald Welte <lafo...@osmocom.org>
+(C) 2022-2024 by Harald Welte <lafo...@osmocom.org>

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
@@ -21,6 +21,8 @@
 from construct import Optional as COptional
 from construct import *
 from bidict import bidict
+from Cryptodome.Random import get_random_bytes
+from pySim.global_platform.scp02 import SCP02
 from pySim.construct import *
 from pySim.utils import *
 from pySim.filesystem import *
@@ -582,6 +584,47 @@
                     p2 |= 0x01
             return grd_list

+        est_scp02_parser = argparse.ArgumentParser()
+        est_scp02_parser.add_argument('--key-ver', type=auto_int, 
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('--host-challenge', type=is_hexstr,
+                                      help='Hard-code the host challenge; 
default: random')
+        est_scp02_parser.add_argument('--security-level', type=auto_int, 
default=0x01,
+                                      help='Security Level. Default: 0x01 
(C-MAC only)')
+
+        @cmd2.with_argparser(est_scp02_parser)
+        def do_establish_scp02(self, opts):
+            """Establish a secure channel using the GlobalPlatform SCP02 
protocol."""
+            if self._cmd.lchan.scc.scp:
+                self._cmd.poutput("Cannot establish SCP02 as this lchan 
already has a SCP instance!")
+                return
+            host_challenge = h2b(opts.host_challenge) if opts.host_challenge 
else get_random_bytes(8)
+            kset = GpCardKeyset(opts.key_ver, h2b(opts.key_enc), 
h2b(opts.key_mac), h2b(opts.key_dek))
+            scp02 = SCP02(card_keys=kset)
+            init_update_apdu = 
scp02.gen_init_update_apdu(host_challenge=host_challenge)
+            init_update_resp, sw = 
self._cmd.lchan.scc.send_apdu_checksw(b2h(init_update_apdu))
+            scp02.parse_init_update_resp(h2b(init_update_resp))
+            ext_auth_apdu = scp02.gen_ext_auth_apdu(opts.security_level)
+            ext_auth_resp, sw = 
self._cmd.lchan.scc.send_apdu_checksw(b2h(ext_auth_apdu))
+            self._cmd.poutput("Successfully established a SCP02 secure 
channel")
+            # store a reference to the SCP instance
+            self._cmd.lchan.scc.scp = scp02
+            self._cmd.update_prompt()
+
+        def do_relase_scp(self, opts):
+            """Release a secure channel."""
+            if not self._cmd.lchan.scc.scp:
+                self._cmd.poutput("Cannot release SCP as none is established")
+                return
+            self._cmd.lchan.scc.scp = None
+            self._cmd.update_prompt()
+

 # Card Application of a Security Domain
 class CardApplicationSD(CardApplication):
diff --git a/pySim/global_platform/scp02.py b/pySim/global_platform/scp02.py
index 29c0021..a2a032e 100644
--- a/pySim/global_platform/scp02.py
+++ b/pySim/global_platform/scp02.py
@@ -107,6 +107,13 @@
         self.card_keys = card_keys
         self.sk = None
         self.mac_on_unmodified = False
+        self.security_level = None
+
+    def __str__(self) -> str:
+        if self.security_level:
+            return "%s[%02x]" % (self.__class__.__name__, self.security_level)
+        else:
+            return "%s[??]" % (self.__class__.__name__)

     def _cla(self, sm: bool = False, b8: bool = True) -> int:
         ret = 0x80 if b8 else 0x00

--
To view, visit https://gerrit.osmocom.org/c/pysim/+/35764?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: Ib2f3c8f0563f81a941dd55b97c9836e3a6856407
Gerrit-Change-Number: 35764
Gerrit-PatchSet: 1
Gerrit-Owner: laforge <lafo...@osmocom.org>
Gerrit-MessageType: newchange

Reply via email to