split pySim/legacy/{cards,utils} from pySim/{cards,utils}

There are some functions / classes which are only needed by the legacy
tools pySim-{read,prog}, bypassing our modern per-file transcoder
classes.  Let's move this code to the pySim/legacy sub-directory,
rendering pySim.legacy.* module names.

The long-term goal is to get rid of those and have all code use the
modern pySim/filesystem classes for reading/decoding/encoding/writing
any kind of data on cards.

Change-Id: Ia8cf831929730c48f90679a83d69049475cc5077
This commit is contained in:
Harald Welte 2023-07-09 17:58:38 +02:00
parent 263fb0871c
commit f8d2e2ba08
11 changed files with 1926 additions and 1928 deletions

View File

@ -36,7 +36,7 @@ import csv
from pySim.commands import SimCardCommands
from pySim.transport import init_reader
from pySim.cards import _cards_classes, card_detect
from pySim.legacy.cards import _cards_classes, card_detect
from pySim.utils import h2b, swap_nibbles, rpad, derive_milenage_opc, calculate_luhn, dec_iccid
from pySim.ts_51_011 import EF, EF_AD
from pySim.card_handler import *

View File

@ -35,10 +35,9 @@ from pySim.ts_31_103 import EF_IST_map, EF_ISIM_ADF_map
from pySim.commands import SimCardCommands
from pySim.transport import init_reader, argparse_add_reader_args
from pySim.exceptions import SwMatchError
from pySim.cards import card_detect, SimCard, UsimCard, IsimCard
from pySim.utils import h2b, swap_nibbles, rpad, dec_imsi, dec_iccid, dec_msisdn
from pySim.utils import format_xplmn_w_act, dec_st
from pySim.utils import h2s, format_ePDGSelection
from pySim.legacy.cards import card_detect, SimCard, UsimCard, IsimCard
from pySim.utils import h2b, h2s, swap_nibbles, rpad, dec_imsi, dec_iccid, dec_msisdn
from pySim.legacy.utils import format_xplmn_w_act, dec_st
option_parser = argparse.ArgumentParser(description='Legacy tool for reading some parts of a SIM card',
formatter_class=argparse.ArgumentDefaultsHelpFormatter)

View File

@ -49,7 +49,7 @@ from pprint import pprint as pp
from pySim.exceptions import *
from pySim.commands import SimCardCommands
from pySim.transport import init_reader, ApduTracer, argparse_add_reader_args, ProactiveHandler
from pySim.cards import card_detect, SimCard, UsimCard
from pySim.cards import card_detect, SimCardBase, UiccCardBase
from pySim.utils import h2b, b2h, i2h, swap_nibbles, rpad, JsonEncoder, bertlv_parse_one, sw_match
from pySim.utils import sanitize_pin_adm, tabulate_str_list, boxed_heading_str, Hexstr
from pySim.card_handler import CardHandler, CardHandlerAuto
@ -95,10 +95,10 @@ def init_card(sl):
return None, None
generic_card = False
card = card_detect("auto", scc)
card = card_detect(scc)
if card is None:
print("Warning: Could not detect card type - assuming a generic card type...")
card = SimCard(scc)
card = SimCardBase(scc)
generic_card = True
profile = CardProfile.pick(scc)
@ -132,7 +132,7 @@ def init_card(sl):
# IF we don't do this, we will have a SimCard but try USIM specific commands like
# the update_ust method (see https://osmocom.org/issues/6055)
if generic_card:
card = UsimCard(scc)
card = UiccCardBase(scc)
# Create runtime state with card profile
rs = RuntimeState(card, profile)

View File

@ -8,7 +8,7 @@ from pprint import pprint as pp
from pySim.apdu import *
from pySim.filesystem import RuntimeState
from pySim.cards import UsimCard
from pySim.cards import UiccCardBase
from pySim.commands import SimCardCommands
from pySim.profile import CardProfile
from pySim.ts_102_221 import CardProfileUICCSIM
@ -36,13 +36,13 @@ ApduCommands = UiccApduCommands + UsimApduCommands #+ GpApduCommands
class DummySimLink(LinkBase):
"""A dummy implementation of the LinkBase abstract base class. Currently required
as the UsimCard doesn't work without SimCardCommands, which in turn require
as the UiccCardBase doesn't work without SimCardCommands, which in turn require
a LinkBase implementation talking to a card.
In the tracer, we don't actually talk to any card, so we simply drop everything
and claim it is successful.
The UsimCard / SimCardCommands should be refactored to make this obsolete later."""
The UiccCardBase / SimCardCommands should be refactored to make this obsolete later."""
def __init__(self, debug: bool = False, **kwargs):
super().__init__(**kwargs)
self._debug = debug
@ -75,7 +75,7 @@ class Tracer:
profile.add_application(CardApplicationUSIM())
profile.add_application(CardApplicationISIM())
scc = SimCardCommands(transport=DummySimLink())
card = UsimCard(scc)
card = UiccCardBase(scc)
self.rs = RuntimeState(card, profile)
# APDU Decoder
self.ad = ApduDecoder(ApduCommands)

File diff suppressed because it is too large Load Diff

0
pySim/legacy/__init__.py Normal file
View File

1666
pySim/legacy/cards.py Normal file

File diff suppressed because it is too large Load Diff

212
pySim/legacy/utils.py Normal file
View File

@ -0,0 +1,212 @@
# -*- coding: utf-8 -*-
""" pySim: various utilities only used by legacy tools (pySim-{prog,read})
"""
# Copyright (C) 2009-2010 Sylvain Munaut <tnt@246tNt.com>
# Copyright (C) 2021 Harald Welte <laforge@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
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
from pySim.utils import Hexstr, rpad, enc_plmn
from pySim.utils import dec_xplmn_w_act, dec_xplmn, dec_mcc_from_plmn, dec_mnc_from_plmn
def hexstr_to_Nbytearr(s, nbytes):
return [s[i:i+(nbytes*2)] for i in range(0, len(s), (nbytes*2))]
def format_xplmn_w_act(hexstr):
s = ""
for rec_data in hexstr_to_Nbytearr(hexstr, 5):
rec_info = dec_xplmn_w_act(rec_data)
if rec_info['mcc'] == "" and rec_info['mnc'] == "":
rec_str = "unused"
else:
rec_str = "MCC: %s MNC: %s AcT: %s" % (
rec_info['mcc'], rec_info['mnc'], ", ".join(rec_info['act']))
s += "\t%s # %s\n" % (rec_data, rec_str)
return s
def format_xplmn(hexstr: Hexstr) -> str:
s = ""
for rec_data in hexstr_to_Nbytearr(hexstr, 3):
rec_info = dec_xplmn(rec_data)
if not rec_info['mcc'] and not rec_info['mnc']:
rec_str = "unused"
else:
rec_str = "MCC: %s MNC: %s" % (rec_info['mcc'], rec_info['mnc'])
s += "\t%s # %s\n" % (rec_data, rec_str)
return s
def format_ePDGSelection(hexstr):
ePDGSelection_info_tag_chars = 2
ePDGSelection_info_tag_str = hexstr[:2]
s = ""
# Minimum length
len_chars = 2
# TODO: Need to determine length properly - definite length support only
# Inconsistency in spec: 3GPP TS 31.102 version 15.2.0 Release 15, 4.2.104
# As per spec, length is 5n, n - number of PLMNs
# But, each PLMN entry is made of PLMN (3 Bytes) + ePDG Priority (2 Bytes) + ePDG FQDN format (1 Byte)
# Totalling to 6 Bytes, maybe length should be 6n
len_str = hexstr[ePDGSelection_info_tag_chars:ePDGSelection_info_tag_chars+len_chars]
# Not programmed scenario
if int(len_str, 16) == 255 or int(ePDGSelection_info_tag_str, 16) == 255:
len_chars = 0
ePDGSelection_info_tag_chars = 0
if len_str[0] == '8':
# The bits 7 to 1 denotes the number of length octets if length > 127
if int(len_str[1]) > 0:
# Update number of length octets
len_chars = len_chars * int(len_str[1])
len_str = hexstr[ePDGSelection_info_tag_chars:len_chars]
content_str = hexstr[ePDGSelection_info_tag_chars+len_chars:]
# Right pad to prevent index out of range - multiple of 6 bytes
content_str = rpad(content_str, len(content_str) +
(12 - (len(content_str) % 12)))
for rec_data in hexstr_to_Nbytearr(content_str, 6):
rec_info = dec_ePDGSelection(rec_data)
if rec_info['mcc'] == 0xFFF and rec_info['mnc'] == 0xFFF:
rec_str = "unused"
else:
rec_str = "MCC: %03d MNC: %03d ePDG Priority: %s ePDG FQDN format: %s" % \
(rec_info['mcc'], rec_info['mnc'],
rec_info['epdg_priority'], rec_info['epdg_fqdn_format'])
s += "\t%s # %s\n" % (rec_data, rec_str)
return s
def enc_st(st, service, state=1):
"""
Encodes the EF S/U/IST/EST and returns the updated Service Table
Parameters:
st - Current value of SIM/USIM/ISIM Service Table
service - Service Number to encode as activated/de-activated
state - 1 mean activate, 0 means de-activate
Returns:
s - Modified value of SIM/USIM/ISIM Service Table
Default values:
- state: 1 - Sets the particular Service bit to 1
"""
st_bytes = [st[i:i+2] for i in range(0, len(st), 2)]
s = ""
# Check whether the requested service is present in each byte
for i in range(0, len(st_bytes)):
# Byte i contains info about Services num (8i+1) to num (8i+8)
if service in range((8*i) + 1, (8*i) + 9):
byte = int(st_bytes[i], 16)
# Services in each byte are in order MSB to LSB
# MSB - Service (8i+8)
# LSB - Service (8i+1)
mod_byte = 0x00
# Copy bit by bit contents of byte to mod_byte with modified bit
# for requested service
for j in range(1, 9):
mod_byte = mod_byte >> 1
if service == (8*i) + j:
mod_byte = state == 1 and mod_byte | 0x80 or mod_byte & 0x7f
else:
mod_byte = byte & 0x01 == 0x01 and mod_byte | 0x80 or mod_byte & 0x7f
byte = byte >> 1
s += ('%02x' % (mod_byte))
else:
s += st_bytes[i]
return s
def dec_st(st, table="sim") -> str:
"""
Parses the EF S/U/IST and prints the list of available services in EF S/U/IST
"""
if table == "isim":
from pySim.ts_31_103 import EF_IST_map
lookup_map = EF_IST_map
elif table == "usim":
from pySim.ts_31_102 import EF_UST_map
lookup_map = EF_UST_map
else:
from pySim.ts_51_011 import EF_SST_map
lookup_map = EF_SST_map
st_bytes = [st[i:i+2] for i in range(0, len(st), 2)]
avail_st = ""
# Get each byte and check for available services
for i in range(0, len(st_bytes)):
# Byte i contains info about Services num (8i+1) to num (8i+8)
byte = int(st_bytes[i], 16)
# Services in each byte are in order MSB to LSB
# MSB - Service (8i+8)
# LSB - Service (8i+1)
for j in range(1, 9):
if byte & 0x01 == 0x01 and ((8*i) + j in lookup_map):
# Byte X contains info about Services num (8X-7) to num (8X)
# bit = 1: service available
# bit = 0: service not available
avail_st += '\tService %d - %s\n' % (
(8*i) + j, lookup_map[(8*i) + j])
byte = byte >> 1
return avail_st
def enc_ePDGSelection(hexstr, mcc, mnc, epdg_priority='0001', epdg_fqdn_format='00'):
"""
Encode ePDGSelection so it can be stored at EF.ePDGSelection or EF.ePDGSelectionEm.
See 3GPP TS 31.102 version 15.2.0 Release 15, section 4.2.104 and 4.2.106.
Default values:
- epdg_priority: '0001' - 1st Priority
- epdg_fqdn_format: '00' - Operator Identifier FQDN
"""
plmn1 = enc_plmn(mcc, mnc) + epdg_priority + epdg_fqdn_format
# TODO: Handle encoding of Length field for length more than 127 Bytes
content = '80' + ('%02x' % (len(plmn1)//2)) + plmn1
content = rpad(content, len(hexstr))
return content
def dec_ePDGSelection(sixhexbytes):
"""
Decode ePDGSelection to get EF.ePDGSelection or EF.ePDGSelectionEm.
See 3GPP TS 31.102 version 15.2.0 Release 15, section 4.2.104 and 4.2.106.
"""
res = {'mcc': 0, 'mnc': 0, 'epdg_priority': 0, 'epdg_fqdn_format': ''}
plmn_chars = 6
epdg_priority_chars = 4
epdg_fqdn_format_chars = 2
# first three bytes (six ascii hex chars)
plmn_str = sixhexbytes[:plmn_chars]
# two bytes after first three bytes
epdg_priority_str = sixhexbytes[plmn_chars:plmn_chars +
epdg_priority_chars]
# one byte after first five bytes
epdg_fqdn_format_str = sixhexbytes[plmn_chars +
epdg_priority_chars:plmn_chars + epdg_priority_chars + epdg_fqdn_format_chars]
res['mcc'] = dec_mcc_from_plmn(plmn_str)
res['mnc'] = dec_mnc_from_plmn(plmn_str)
res['epdg_priority'] = epdg_priority_str
res['epdg_fqdn_format'] = epdg_fqdn_format_str == '00' and 'Operator Identifier FQDN' or 'Location based FQDN'
return res

View File

@ -435,30 +435,6 @@ def dec_plmn(threehexbytes: Hexstr) -> dict:
return res
def dec_spn(ef):
"""Obsolete, kept for API compatibility"""
from ts_51_011 import EF_SPN
abstract_data = EF_SPN().decode_hex(ef)
show_in_hplmn = abstract_data['show_in_hplmn']
hide_in_oplmn = abstract_data['hide_in_oplmn']
name = abstract_data['spn']
return (name, show_in_hplmn, hide_in_oplmn)
def enc_spn(name: str, show_in_hplmn=False, hide_in_oplmn=False):
"""Obsolete, kept for API compatibility"""
from ts_51_011 import EF_SPN
abstract_data = {
'hide_in_oplmn': hide_in_oplmn,
'show_in_hplmn': show_in_hplmn,
'spn': name,
}
return EF_SPN().encode_hex(abstract_data)
def hexstr_to_Nbytearr(s, nbytes):
return [s[i:i+(nbytes*2)] for i in range(0, len(s), (nbytes*2))]
# Accepts hex string representing three bytes
@ -544,53 +520,6 @@ def dec_xplmn_w_act(fivehexbytes: Hexstr) -> Dict[str, Any]:
return res
def format_xplmn_w_act(hexstr):
s = ""
for rec_data in hexstr_to_Nbytearr(hexstr, 5):
rec_info = dec_xplmn_w_act(rec_data)
if rec_info['mcc'] == "" and rec_info['mnc'] == "":
rec_str = "unused"
else:
rec_str = "MCC: %s MNC: %s AcT: %s" % (
rec_info['mcc'], rec_info['mnc'], ", ".join(rec_info['act']))
s += "\t%s # %s\n" % (rec_data, rec_str)
return s
def dec_loci(hexstr):
res = {'tmsi': '', 'mcc': 0, 'mnc': 0, 'lac': '', 'status': 0}
res['tmsi'] = hexstr[:8]
res['mcc'] = dec_mcc_from_plmn(hexstr[8:14])
res['mnc'] = dec_mnc_from_plmn(hexstr[8:14])
res['lac'] = hexstr[14:18]
res['status'] = h2i(hexstr[20:22])
return res
def dec_psloci(hexstr):
res = {'p-tmsi': '', 'p-tmsi-sig': '', 'mcc': 0,
'mnc': 0, 'lac': '', 'rac': '', 'status': 0}
res['p-tmsi'] = hexstr[:8]
res['p-tmsi-sig'] = hexstr[8:14]
res['mcc'] = dec_mcc_from_plmn(hexstr[14:20])
res['mnc'] = dec_mnc_from_plmn(hexstr[14:20])
res['lac'] = hexstr[20:24]
res['rac'] = hexstr[24:26]
res['status'] = h2i(hexstr[26:28])
return res
def dec_epsloci(hexstr):
res = {'guti': '', 'mcc': 0, 'mnc': 0, 'tac': '', 'status': 0}
res['guti'] = hexstr[:24]
res['tai'] = hexstr[24:34]
res['mcc'] = dec_mcc_from_plmn(hexstr[24:30])
res['mnc'] = dec_mnc_from_plmn(hexstr[24:30])
res['tac'] = hexstr[30:34]
res['status'] = h2i(hexstr[34:36])
return res
def dec_xplmn(threehexbytes: Hexstr) -> dict:
res = {'mcc': 0, 'mnc': 0, 'act': []}
plmn_chars = 6
@ -601,18 +530,6 @@ def dec_xplmn(threehexbytes: Hexstr) -> dict:
return res
def format_xplmn(hexstr: Hexstr) -> str:
s = ""
for rec_data in hexstr_to_Nbytearr(hexstr, 3):
rec_info = dec_xplmn(rec_data)
if not rec_info['mcc'] and not rec_info['mnc']:
rec_str = "unused"
else:
rec_str = "MCC: %s MNC: %s" % (rec_info['mcc'], rec_info['mnc'])
s += "\t%s # %s\n" % (rec_data, rec_str)
return s
def derive_milenage_opc(ki_hex: Hexstr, op_hex: Hexstr) -> Hexstr:
"""
Run the milenage algorithm to calculate OPC from Ki and OP
@ -787,42 +704,6 @@ def enc_msisdn(msisdn: str, npi: int = 0x01, ton: int = 0x03) -> Hexstr:
return ('%02x' % bcd_len) + ('%02x' % npi_ton) + bcd + ("ff" * 2)
def dec_st(st, table="sim") -> str:
"""
Parses the EF S/U/IST and prints the list of available services in EF S/U/IST
"""
if table == "isim":
from pySim.ts_31_103 import EF_IST_map
lookup_map = EF_IST_map
elif table == "usim":
from pySim.ts_31_102 import EF_UST_map
lookup_map = EF_UST_map
else:
from pySim.ts_51_011 import EF_SST_map
lookup_map = EF_SST_map
st_bytes = [st[i:i+2] for i in range(0, len(st), 2)]
avail_st = ""
# Get each byte and check for available services
for i in range(0, len(st_bytes)):
# Byte i contains info about Services num (8i+1) to num (8i+8)
byte = int(st_bytes[i], 16)
# Services in each byte are in order MSB to LSB
# MSB - Service (8i+8)
# LSB - Service (8i+1)
for j in range(1, 9):
if byte & 0x01 == 0x01 and ((8*i) + j in lookup_map):
# Byte X contains info about Services num (8X-7) to num (8X)
# bit = 1: service available
# bit = 0: service not available
avail_st += '\tService %d - %s\n' % (
(8*i) + j, lookup_map[(8*i) + j])
byte = byte >> 1
return avail_st
def first_TLV_parser(bytelist):
'''
first_TLV_parser([0xAA, 0x02, 0xAB, 0xCD, 0xFF, 0x00]) -> (170, 2, [171, 205])
@ -864,50 +745,6 @@ def TLV_parser(bytelist):
return ret
def enc_st(st, service, state=1):
"""
Encodes the EF S/U/IST/EST and returns the updated Service Table
Parameters:
st - Current value of SIM/USIM/ISIM Service Table
service - Service Number to encode as activated/de-activated
state - 1 mean activate, 0 means de-activate
Returns:
s - Modified value of SIM/USIM/ISIM Service Table
Default values:
- state: 1 - Sets the particular Service bit to 1
"""
st_bytes = [st[i:i+2] for i in range(0, len(st), 2)]
s = ""
# Check whether the requested service is present in each byte
for i in range(0, len(st_bytes)):
# Byte i contains info about Services num (8i+1) to num (8i+8)
if service in range((8*i) + 1, (8*i) + 9):
byte = int(st_bytes[i], 16)
# Services in each byte are in order MSB to LSB
# MSB - Service (8i+8)
# LSB - Service (8i+1)
mod_byte = 0x00
# Copy bit by bit contents of byte to mod_byte with modified bit
# for requested service
for j in range(1, 9):
mod_byte = mod_byte >> 1
if service == (8*i) + j:
mod_byte = state == 1 and mod_byte | 0x80 or mod_byte & 0x7f
else:
mod_byte = byte & 0x01 == 0x01 and mod_byte | 0x80 or mod_byte & 0x7f
byte = byte >> 1
s += ('%02x' % (mod_byte))
else:
s += st_bytes[i]
return s
def dec_addr_tlv(hexstr):
"""
Decode hex string to get EF.P-CSCF Address or EF.ePDGId or EF.ePDGIdEm.
@ -1038,88 +875,6 @@ def sanitize_pin_adm(pin_adm, pin_adm_hex=None) -> Hexstr:
return pin_adm
def enc_ePDGSelection(hexstr, mcc, mnc, epdg_priority='0001', epdg_fqdn_format='00'):
"""
Encode ePDGSelection so it can be stored at EF.ePDGSelection or EF.ePDGSelectionEm.
See 3GPP TS 31.102 version 15.2.0 Release 15, section 4.2.104 and 4.2.106.
Default values:
- epdg_priority: '0001' - 1st Priority
- epdg_fqdn_format: '00' - Operator Identifier FQDN
"""
plmn1 = enc_plmn(mcc, mnc) + epdg_priority + epdg_fqdn_format
# TODO: Handle encoding of Length field for length more than 127 Bytes
content = '80' + ('%02x' % (len(plmn1)//2)) + plmn1
content = rpad(content, len(hexstr))
return content
def dec_ePDGSelection(sixhexbytes):
"""
Decode ePDGSelection to get EF.ePDGSelection or EF.ePDGSelectionEm.
See 3GPP TS 31.102 version 15.2.0 Release 15, section 4.2.104 and 4.2.106.
"""
res = {'mcc': 0, 'mnc': 0, 'epdg_priority': 0, 'epdg_fqdn_format': ''}
plmn_chars = 6
epdg_priority_chars = 4
epdg_fqdn_format_chars = 2
# first three bytes (six ascii hex chars)
plmn_str = sixhexbytes[:plmn_chars]
# two bytes after first three bytes
epdg_priority_str = sixhexbytes[plmn_chars:plmn_chars +
epdg_priority_chars]
# one byte after first five bytes
epdg_fqdn_format_str = sixhexbytes[plmn_chars +
epdg_priority_chars:plmn_chars + epdg_priority_chars + epdg_fqdn_format_chars]
res['mcc'] = dec_mcc_from_plmn(plmn_str)
res['mnc'] = dec_mnc_from_plmn(plmn_str)
res['epdg_priority'] = epdg_priority_str
res['epdg_fqdn_format'] = epdg_fqdn_format_str == '00' and 'Operator Identifier FQDN' or 'Location based FQDN'
return res
def format_ePDGSelection(hexstr):
ePDGSelection_info_tag_chars = 2
ePDGSelection_info_tag_str = hexstr[:2]
s = ""
# Minimum length
len_chars = 2
# TODO: Need to determine length properly - definite length support only
# Inconsistency in spec: 3GPP TS 31.102 version 15.2.0 Release 15, 4.2.104
# As per spec, length is 5n, n - number of PLMNs
# But, each PLMN entry is made of PLMN (3 Bytes) + ePDG Priority (2 Bytes) + ePDG FQDN format (1 Byte)
# Totalling to 6 Bytes, maybe length should be 6n
len_str = hexstr[ePDGSelection_info_tag_chars:ePDGSelection_info_tag_chars+len_chars]
# Not programmed scenario
if int(len_str, 16) == 255 or int(ePDGSelection_info_tag_str, 16) == 255:
len_chars = 0
ePDGSelection_info_tag_chars = 0
if len_str[0] == '8':
# The bits 7 to 1 denotes the number of length octets if length > 127
if int(len_str[1]) > 0:
# Update number of length octets
len_chars = len_chars * int(len_str[1])
len_str = hexstr[ePDGSelection_info_tag_chars:len_chars]
content_str = hexstr[ePDGSelection_info_tag_chars+len_chars:]
# Right pad to prevent index out of range - multiple of 6 bytes
content_str = rpad(content_str, len(content_str) +
(12 - (len(content_str) % 12)))
for rec_data in hexstr_to_Nbytearr(content_str, 6):
rec_info = dec_ePDGSelection(rec_data)
if rec_info['mcc'] == 0xFFF and rec_info['mnc'] == 0xFFF:
rec_str = "unused"
else:
rec_str = "MCC: %03d MNC: %03d ePDG Priority: %s ePDG FQDN format: %s" % \
(rec_info['mcc'], rec_info['mnc'],
rec_info['epdg_priority'], rec_info['epdg_fqdn_format'])
s += "\t%s # %s\n" % (rec_data, rec_str)
return s
def get_addr_type(addr):
"""
Validates the given address and returns it's type (FQDN or IPv4 or IPv6)

View File

@ -3,7 +3,7 @@ from setuptools import setup
setup(
name='pySim',
version='1.0',
packages=['pySim', 'pySim.transport', 'pySim.apdu', 'pySim.apdu_source'],
packages=['pySim', 'pySim.legacy', 'pySim.transport', 'pySim.apdu', 'pySim.apdu_source'],
url='https://osmocom.org/projects/pysim/wiki',
license='GPLv2',
author_email='simtrace@lists.osmocom.org',

View File

@ -2,6 +2,7 @@
import unittest
from pySim import utils
from pySim.legacy import utils as legacy_utils
from pySim.ts_31_102 import EF_SUCI_Calc_Info
# we don't really want to thest TS 102 221, but the underlying DataObject codebase
@ -45,7 +46,7 @@ class DecTestCase(unittest.TestCase):
"ffffff0002",
"ffffff0001",
]
self.assertEqual(utils.hexstr_to_Nbytearr(input_str, 5), expected)
self.assertEqual(legacy_utils.hexstr_to_Nbytearr(input_str, 5), expected)
def testDecMCCfromPLMN(self):
self.assertEqual(utils.dec_mcc_from_plmn("92f501"), 295)
@ -130,7 +131,7 @@ class DecTestCase(unittest.TestCase):
expected += "\tffffff0000 # unused\n"
expected += "\tffffff0000 # unused\n"
expected += "\tffffff0000 # unused\n"
self.assertEqual(utils.format_xplmn_w_act(input_str), expected)
self.assertEqual(legacy_utils.format_xplmn_w_act(input_str), expected)
def testDecodeSuciCalcInfo(self):