pySim-shell: Authenticate (3g) support
This adds support for AUTHENTICATE to the USIM and ISIM application,
based on the newly-introduced 'construct' encoder/decoder support.
Change-Id: Id5697463e29c3dceff98bcf80f5400f7f2bcaa6c
diff --git a/docs/shell.rst b/docs/shell.rst
index 854944c..1072ee8 100644
--- a/docs/shell.rst
+++ b/docs/shell.rst
@@ -300,6 +300,17 @@
This allows for easy interactive modification of file contents.
+USIM commands
+-------------
+
+authenticate
+~~~~~~~~~~~~
+.. argparse::
+ :module: pySim.ts_31_102
+ :func: ADF_USIM.AddlShellCommands.authenticate_parser
+
+
+
cmd2 settable parameters
------------------------
diff --git a/pySim/commands.py b/pySim/commands.py
index 7919099..791b995 100644
--- a/pySim/commands.py
+++ b/pySim/commands.py
@@ -21,6 +21,8 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
+from construct import *
+from pySim.construct import LV
from pySim.utils import rpad, b2h, sw_match
from pySim.exceptions import SwMatchError
@@ -274,6 +276,26 @@
self.select_path(['3f00', '7f20'])
return self._tp.send_apdu(self.cla_byte + '88000010' + rand)
+ def authenticate(self, rand:str, autn:str, context='3g'):
+ """Execute AUTHENTICATE (USIM/ISIM)."""
+ # 3GPP TS 31.102 Section 7.1.2.1
+ AuthCmd3G = Struct('rand'/LV, 'autn'/Optional(LV))
+ AuthResp3GSyncFail = Struct(Const(b'\xDC'), 'auts'/LV)
+ AuthResp3GSuccess = Struct(Const(b'\xDB'), 'res'/LV, 'ck'/LV, 'ik'/LV, 'kc'/Optional(LV))
+ AuthResp3G = Select(AuthResp3GSyncFail, AuthResp3GSuccess)
+ # build parameters
+ cmd_data = {'rand': rand, 'autn': autn}
+ if context == '3g':
+ p2 = '81'
+ elif context == 'gsm':
+ p2 = '80'
+ (data, sw) = self._tp.send_apdu_constr(self.cla_byte, '88', '00', p2, AuthCmd3G, cmd_data, AuthResp3G)
+ if 'auts' in data:
+ ret = {'synchronisation_failure': data}
+ else:
+ ret = {'successful_3g_authentication': data}
+ return (ret, sw)
+
def reset_card(self):
"""Physically reset the card"""
return self._tp.reset_card()
diff --git a/pySim/ts_31_102.py b/pySim/ts_31_102.py
index 267008d..cdb6612 100644
--- a/pySim/ts_31_102.py
+++ b/pySim/ts_31_102.py
@@ -268,6 +268,7 @@
# ADF.USIM
######################################################################
+from struct import unpack, pack
from pySim.filesystem import *
from pySim.ts_51_011 import EF_IMSI, EF_xPLMNwAcT, EF_SPN, EF_CBMI, EF_ACC, EF_PLMNsel, EF_AD
from pySim.ts_51_011 import EF_CBMID, EF_CBMIR
@@ -489,6 +490,8 @@
def __init__(self, aid='a0000000871002', name='ADF.USIM', fid=None, sfid=None,
desc='USIM Application'):
super().__init__(aid=aid, fid=fid, sfid=sfid, name=name, desc=desc)
+ # add those commands to the general commands of a TransparentEF
+ self.shell_commands += [self.AddlShellCommands()]
files = [
EF_LI(sfid=0x02),
@@ -520,6 +523,23 @@
def decode_select_response(self, data_hex):
return pySim.ts_102_221.decode_select_response(data_hex)
+ @with_default_category('Application-Specific Commands')
+ class AddlShellCommands(CommandSet):
+ def __init__(self):
+ super().__init__()
+
+ authenticate_parser = argparse.ArgumentParser()
+ authenticate_parser.add_argument('rand', help='Random challenge')
+ authenticate_parser.add_argument('autn', help='Authentication Nonce')
+ #authenticate_parser.add_argument('--context', help='Authentication context', default='3G')
+ @cmd2.with_argparser(authenticate_parser)
+ def do_authenticate(self, opts):
+ """Perform Authentication and Key Agreement (AKA)."""
+ (data, sw) = self._cmd.card._scc.authenticate(opts.rand, opts.autn)
+ self._cmd.poutput_json(data)
+
+
+
# TS 31.102 Section 7.3
sw_usim = {
'Security management': {
diff --git a/pySim/ts_31_103.py b/pySim/ts_31_103.py
index 8209845..effdbf7 100644
--- a/pySim/ts_31_103.py
+++ b/pySim/ts_31_103.py
@@ -25,6 +25,7 @@
from pySim.filesystem import *
from pySim.utils import *
from pySim.ts_51_011 import EF_AD
+from pySim.ts_31_102 import ADF_USIM
import pySim.ts_102_221
# Mapping between ISIM Service Number and its description
@@ -186,6 +187,8 @@
EF_WebRTCURI(),
]
self.add_files(files)
+ # add those commands to the general commands of a TransparentEF
+ self.shell_commands += [ADF_USIM.AddlShellCommands()]
def decode_select_response(self, data_hex):
return pySim.ts_102_221.decode_select_response(data_hex)