pySim/cards: Split legacy classes away from core SIM + UICC

This introduces an internal split between
* the code that is shared between pySim-shell and legacy tools, which is
  now in the new class hierarchy {Card,SimCard,UiccCard}Base
* the code that is only used by legacy tools,
  which is using the old class names inherited from the *Base above

All users still go through the legacy {Sim,Usim,Isim}Card classes, they
will be adjusted in subsequent patches.

Change-Id: Id36140675def5fc44eedce81fc7b09e0adc527e1
This commit is contained in:
Harald Welte 2023-07-09 17:15:36 +02:00
parent 02a7f7441f
commit 263fb0871c
3 changed files with 81 additions and 70 deletions

View File

@ -5,7 +5,7 @@
#
# Copyright (C) 2009-2010 Sylvain Munaut <tnt@246tNt.com>
# Copyright (C) 2011 Harald Welte <laforge@gnumonks.org>
# Copyright (C) 2011-2023 Harald Welte <laforge@gnumonks.org>
# Copyright (C) 2017 Alexander.Chemeris <Alexander.Chemeris@gmail.com>
#
# This program is free software: you can redistribute it and/or modify
@ -25,13 +25,81 @@
from typing import Optional, Dict, Tuple
import abc
from pySim.ts_51_011 import EF, DF, EF_AD, EF_SPN
from pySim.ts_31_102 import EF_USIM_ADF_map
from pySim.ts_31_103 import EF_ISIM_ADF_map
from pySim.utils import *
class CardBase:
"""General base class for some kind of telecommunications card."""
def __init__(self, scc):
self._scc = scc
self._aids = []
def reset(self):
rc = self._scc.reset_card()
if rc == 1:
return self._scc.get_atr()
else:
return None
def set_apdu_parameter(self, cla, sel_ctrl):
"""Set apdu parameters (class byte and selection control bytes)"""
self._scc.cla_byte = cla
self._scc.sel_ctrl = sel_ctrl
def get_apdu_parameter(self):
"""Get apdu parameters (class byte and selection control bytes)"""
return (self._scc.cla_byte, self._scc.sel_ctrl)
def erase(self):
print("warning: erasing is not supported for specified card type!")
return
def file_exists(self, fid):
res_arr = self._scc.try_select_path(fid)
for res in res_arr:
if res[1] != '9000':
return False
return True
def read_aids(self):
# a non-UICC doesn't have any applications. Convenience helper to avoid
# callers having to do hasattr('read_aids') ahead of every call.
return []
class SimCardBase(CardBase):
"""Here we only add methods for commands specified in TS 51.011, without
any higher-layer processing."""
name = 'SIM'
def read_binary(self, ef, length=None, offset=0):
ef_path = ef in EF and EF[ef] or ef
return self._scc.read_binary(ef_path, length, offset)
def read_record(self, ef, rec_no):
ef_path = ef in EF and EF[ef] or ef
return self._scc.read_record(ef_path, rec_no)
class UiccCardBase(SimCardBase):
name = 'UICC'
def __init__(self, ssc):
super(UiccCardBase, self).__init__(ssc)
# See also: ETSI TS 102 221, Table 9.3
self._adm_chv_num = 0xA0
################################################################################
# LEGACY
################################################################################
from smartcard.util import toBytes
from pytlv.TLV import *
from pySim.ts_51_011 import EF, DF, EF_AD, EF_SPN
from pySim.ts_31_102 import EF_USIM_ADF_map
from pySim.ts_31_103 import EF_ISIM_ADF_map
def format_addr(addr: str, addr_type: str) -> str:
"""
@ -52,32 +120,13 @@ def format_addr(addr: str, addr_type: str) -> str:
return res
class SimCard:
name = 'SIM'
class SimCard(SimCardBase):
"""Higher-layer class that is used *only* by legacy pySim-{prog,read}."""
def __init__(self, scc):
self._scc = scc
self._adm_chv_num = 4
self._aids = []
def reset(self):
rc = self._scc.reset_card()
if rc == 1:
return self._scc.get_atr()
else:
return None
def erase(self):
print("warning: erasing is not supported for specified card type!")
return
def file_exists(self, fid):
res_arr = self._scc.try_select_path(fid)
for res in res_arr:
if res[1] != '9000':
return False
return True
super().__init__(scc)
def verify_adm(self, key):
"""Authenticate with ADM key"""
@ -252,14 +301,6 @@ class SimCard:
data, sw = self._scc.update_binary(EF['SPN'], content)
return sw
def read_binary(self, ef, length=None, offset=0):
ef_path = ef in EF and EF[ef] or ef
return self._scc.read_binary(ef_path, length, offset)
def read_record(self, ef, rec_no):
ef_path = ef in EF and EF[ef] or ef
return self._scc.read_record(ef_path, rec_no)
def read_gid1(self):
(res, sw) = self._scc.read_binary(EF['GID1'])
if sw == '9000':
@ -274,6 +315,10 @@ class SimCard:
else:
return (None, sw)
class UsimCard(UiccCardBase, SimCard):
"""Higher-layer class that is used *only* by legacy pySim-{prog,read}."""
def read_aids(self):
"""Fetch all the AIDs present on UICC"""
self._aids = []
@ -335,36 +380,6 @@ class SimCard:
return self._scc.select_adf(aid)
return (None, None)
def erase_binary(self, ef):
"""Erase the contents of a file"""
len = self._scc.binary_size(ef)
self._scc.update_binary(ef, "ff" * len, offset=0, verify=True)
def erase_record(self, ef, rec_no):
"""Erase the contents of a single record"""
len = self._scc.record_size(ef)
self._scc.update_record(ef, rec_no, "ff" * len,
force_len=False, verify=True)
def set_apdu_parameter(self, cla, sel_ctrl):
"""Set apdu parameters (class byte and selection control bytes)"""
self._scc.cla_byte = cla
self._scc.sel_ctrl = sel_ctrl
def get_apdu_parameter(self):
"""Get apdu parameters (class byte and selection control bytes)"""
return (self._scc.cla_byte, self._scc.sel_ctrl)
class UsimCard(SimCard):
name = 'USIM'
def __init__(self, ssc):
super(UsimCard, self).__init__(ssc)
# See also: ETSI TS 102 221, Table 9.3
self._adm_chv_num = 0xA0
def read_ehplmn(self):
(res, sw) = self._scc.read_binary(EF_USIM_ADF_map['EHPLMN'])
@ -469,13 +484,11 @@ class UsimCard(SimCard):
class IsimCard(SimCard):
class IsimCard(UiccCardBase):
"""Higher-layer class that is used *only* by legacy pySim-{prog,read}."""
name = 'ISIM'
def __init__(self, ssc):
super(IsimCard, self).__init__(ssc)
def read_pcscf(self):
rec_cnt = self._scc.record_count(EF_ISIM_ADF_map['PCSCF'])
pcscf_recs = ""

View File

@ -1,7 +1,6 @@
Using PC/SC reader interface
Reading ...
Autodetected card type: fakemagicsim
Can't read AIDs from SIM -- SW match failed! Expected 9000 and got 9404.
ICCID: 1122334455667788990
IMSI: 001010000000102
GID1: Can't read file -- SW match failed! Expected 9000 and got 9404.

View File

@ -1,7 +1,6 @@
Using PC/SC reader interface
Reading ...
Autodetected card type: sysmosim-gr1
Can't read AIDs from SIM -- SW match failed! Expected 9000 and got 9404.
ICCID: 1122334455667788990
IMSI: 001010000000102
GID1: Can't read file -- SW match failed! Expected 9000 and got 9404.