mirror of
https://gitea.osmocom.org/sim-card/pysim.git
synced 2026-03-28 16:28:33 +03:00
move {enc,dec}_addr_tlv functions from pySim.util to pySim.legacy.util
In the previous commit we've stopped using those functions from modern pySim-shell code. Hence, the only remaining user is the legacy tools, so we can move the code to the legacy module. Change-Id: I6f18ccb36fc33bc204c01f9ece135676510e67ec
This commit is contained in:
@@ -8,11 +8,10 @@ from pytlv.TLV import *
|
|||||||
|
|
||||||
from pySim.cards import SimCardBase, UiccCardBase
|
from pySim.cards import SimCardBase, UiccCardBase
|
||||||
from pySim.utils import dec_iccid, enc_iccid, dec_imsi, enc_imsi, dec_msisdn, enc_msisdn
|
from pySim.utils import dec_iccid, enc_iccid, dec_imsi, enc_imsi, dec_msisdn, enc_msisdn
|
||||||
from pySim.utils import dec_addr_tlv, enc_addr_tlv
|
|
||||||
from pySim.utils import enc_plmn, get_addr_type
|
from pySim.utils import enc_plmn, get_addr_type
|
||||||
from pySim.utils import is_hex, h2b, b2h, h2s, s2h, lpad, rpad
|
from pySim.utils import is_hex, h2b, b2h, h2s, s2h, lpad, rpad
|
||||||
from pySim.legacy.utils import enc_ePDGSelection, format_xplmn_w_act, format_xplmn, dec_st, enc_st
|
from pySim.legacy.utils import enc_ePDGSelection, format_xplmn_w_act, format_xplmn, dec_st, enc_st
|
||||||
from pySim.legacy.utils import format_ePDGSelection
|
from pySim.legacy.utils import format_ePDGSelection, dec_addr_tlv, enc_addr_tlv
|
||||||
from pySim.legacy.ts_51_011 import EF, DF
|
from pySim.legacy.ts_51_011 import EF, DF
|
||||||
from pySim.legacy.ts_31_102 import EF_USIM_ADF_map
|
from pySim.legacy.ts_31_102 import EF_USIM_ADF_map
|
||||||
from pySim.legacy.ts_31_103 import EF_ISIM_ADF_map
|
from pySim.legacy.ts_31_103 import EF_ISIM_ADF_map
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
|
|
||||||
from pySim.utils import Hexstr, rpad, enc_plmn
|
from pySim.utils import Hexstr, rpad, enc_plmn, h2i, i2s, s2h
|
||||||
from pySim.utils import dec_xplmn_w_act, dec_xplmn, dec_mcc_from_plmn, dec_mnc_from_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):
|
def hexstr_to_Nbytearr(s, nbytes):
|
||||||
@@ -210,3 +210,123 @@ def dec_ePDGSelection(sixhexbytes):
|
|||||||
res['epdg_priority'] = epdg_priority_str
|
res['epdg_priority'] = epdg_priority_str
|
||||||
res['epdg_fqdn_format'] = epdg_fqdn_format_str == '00' and 'Operator Identifier FQDN' or 'Location based FQDN'
|
res['epdg_fqdn_format'] = epdg_fqdn_format_str == '00' and 'Operator Identifier FQDN' or 'Location based FQDN'
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
def first_TLV_parser(bytelist):
|
||||||
|
'''
|
||||||
|
first_TLV_parser([0xAA, 0x02, 0xAB, 0xCD, 0xFF, 0x00]) -> (170, 2, [171, 205])
|
||||||
|
|
||||||
|
parses first TLV format record in a list of bytelist
|
||||||
|
returns a 3-Tuple: Tag, Length, Value
|
||||||
|
Value is a list of bytes
|
||||||
|
parsing of length is ETSI'style 101.220
|
||||||
|
'''
|
||||||
|
Tag = bytelist[0]
|
||||||
|
if bytelist[1] == 0xFF:
|
||||||
|
Len = bytelist[2]*256 + bytelist[3]
|
||||||
|
Val = bytelist[4:4+Len]
|
||||||
|
else:
|
||||||
|
Len = bytelist[1]
|
||||||
|
Val = bytelist[2:2+Len]
|
||||||
|
return (Tag, Len, Val)
|
||||||
|
|
||||||
|
|
||||||
|
def TLV_parser(bytelist):
|
||||||
|
'''
|
||||||
|
TLV_parser([0xAA, ..., 0xFF]) -> [(T, L, [V]), (T, L, [V]), ...]
|
||||||
|
|
||||||
|
loops on the input list of bytes with the "first_TLV_parser()" function
|
||||||
|
returns a list of 3-Tuples
|
||||||
|
'''
|
||||||
|
ret = []
|
||||||
|
while len(bytelist) > 0:
|
||||||
|
T, L, V = first_TLV_parser(bytelist)
|
||||||
|
if T == 0xFF:
|
||||||
|
# padding bytes
|
||||||
|
break
|
||||||
|
ret.append((T, L, V))
|
||||||
|
# need to manage length of L
|
||||||
|
if L > 0xFE:
|
||||||
|
bytelist = bytelist[L+4:]
|
||||||
|
else:
|
||||||
|
bytelist = bytelist[L+2:]
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
def dec_addr_tlv(hexstr):
|
||||||
|
"""
|
||||||
|
Decode hex string to get EF.P-CSCF Address or EF.ePDGId or EF.ePDGIdEm.
|
||||||
|
See 3GPP TS 31.102 version 13.4.0 Release 13, section 4.2.8, 4.2.102 and 4.2.104.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Convert from hex str to int bytes list
|
||||||
|
addr_tlv_bytes = h2i(hexstr)
|
||||||
|
|
||||||
|
# Get list of tuples containing parsed TLVs
|
||||||
|
tlvs = TLV_parser(addr_tlv_bytes)
|
||||||
|
|
||||||
|
for tlv in tlvs:
|
||||||
|
# tlv = (T, L, [V])
|
||||||
|
# T = Tag
|
||||||
|
# L = Length
|
||||||
|
# [V] = List of value
|
||||||
|
|
||||||
|
# Invalid Tag value scenario
|
||||||
|
if tlv[0] != 0x80:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Empty field - Zero length
|
||||||
|
if tlv[1] == 0:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Uninitialized field
|
||||||
|
if all([v == 0xff for v in tlv[2]]):
|
||||||
|
continue
|
||||||
|
|
||||||
|
# First byte in the value has the address type
|
||||||
|
addr_type = tlv[2][0]
|
||||||
|
# TODO: Support parsing of IPv6
|
||||||
|
# Address Type: 0x00 (FQDN), 0x01 (IPv4), 0x02 (IPv6), other (Reserved)
|
||||||
|
if addr_type == 0x00: # FQDN
|
||||||
|
# Skip address tye byte i.e. first byte in value list
|
||||||
|
content = tlv[2][1:]
|
||||||
|
return (i2s(content), '00')
|
||||||
|
|
||||||
|
elif addr_type == 0x01: # IPv4
|
||||||
|
# Skip address tye byte i.e. first byte in value list
|
||||||
|
# Skip the unused byte in Octect 4 after address type byte as per 3GPP TS 31.102
|
||||||
|
ipv4 = tlv[2][2:]
|
||||||
|
content = '.'.join(str(x) for x in ipv4)
|
||||||
|
return (content, '01')
|
||||||
|
else:
|
||||||
|
raise ValueError("Invalid address type")
|
||||||
|
|
||||||
|
return (None, None)
|
||||||
|
|
||||||
|
|
||||||
|
def enc_addr_tlv(addr, addr_type='00'):
|
||||||
|
"""
|
||||||
|
Encode address TLV object used in EF.P-CSCF Address, EF.ePDGId and EF.ePDGIdEm.
|
||||||
|
See 3GPP TS 31.102 version 13.4.0 Release 13, section 4.2.8, 4.2.102 and 4.2.104.
|
||||||
|
|
||||||
|
Default values:
|
||||||
|
- addr_type: 00 - FQDN format of Address
|
||||||
|
"""
|
||||||
|
|
||||||
|
s = ""
|
||||||
|
|
||||||
|
# TODO: Encoding of IPv6 address
|
||||||
|
if addr_type == '00': # FQDN
|
||||||
|
hex_str = s2h(addr)
|
||||||
|
s += '80' + ('%02x' % ((len(hex_str)//2)+1)) + '00' + hex_str
|
||||||
|
elif addr_type == '01': # IPv4
|
||||||
|
ipv4_list = addr.split('.')
|
||||||
|
ipv4_str = ""
|
||||||
|
for i in ipv4_list:
|
||||||
|
ipv4_str += ('%02x' % (int(i)))
|
||||||
|
|
||||||
|
# Unused bytes shall be set to 'ff'. i.e 4th Octet after Address Type is not used
|
||||||
|
# IPv4 Address is in octet 5 to octet 8 of the TLV data object
|
||||||
|
s += '80' + ('%02x' % ((len(ipv4_str)//2)+2)) + '01' + 'ff' + ipv4_str
|
||||||
|
|
||||||
|
return s
|
||||||
|
|||||||
120
pySim/utils.py
120
pySim/utils.py
@@ -712,126 +712,6 @@ def enc_msisdn(msisdn: str, npi: int = 0x01, ton: int = 0x03) -> Hexstr:
|
|||||||
return ('%02x' % bcd_len) + ('%02x' % npi_ton) + bcd + ("ff" * 2)
|
return ('%02x' % bcd_len) + ('%02x' % npi_ton) + bcd + ("ff" * 2)
|
||||||
|
|
||||||
|
|
||||||
def first_TLV_parser(bytelist):
|
|
||||||
'''
|
|
||||||
first_TLV_parser([0xAA, 0x02, 0xAB, 0xCD, 0xFF, 0x00]) -> (170, 2, [171, 205])
|
|
||||||
|
|
||||||
parses first TLV format record in a list of bytelist
|
|
||||||
returns a 3-Tuple: Tag, Length, Value
|
|
||||||
Value is a list of bytes
|
|
||||||
parsing of length is ETSI'style 101.220
|
|
||||||
'''
|
|
||||||
Tag = bytelist[0]
|
|
||||||
if bytelist[1] == 0xFF:
|
|
||||||
Len = bytelist[2]*256 + bytelist[3]
|
|
||||||
Val = bytelist[4:4+Len]
|
|
||||||
else:
|
|
||||||
Len = bytelist[1]
|
|
||||||
Val = bytelist[2:2+Len]
|
|
||||||
return (Tag, Len, Val)
|
|
||||||
|
|
||||||
|
|
||||||
def TLV_parser(bytelist):
|
|
||||||
'''
|
|
||||||
TLV_parser([0xAA, ..., 0xFF]) -> [(T, L, [V]), (T, L, [V]), ...]
|
|
||||||
|
|
||||||
loops on the input list of bytes with the "first_TLV_parser()" function
|
|
||||||
returns a list of 3-Tuples
|
|
||||||
'''
|
|
||||||
ret = []
|
|
||||||
while len(bytelist) > 0:
|
|
||||||
T, L, V = first_TLV_parser(bytelist)
|
|
||||||
if T == 0xFF:
|
|
||||||
# padding bytes
|
|
||||||
break
|
|
||||||
ret.append((T, L, V))
|
|
||||||
# need to manage length of L
|
|
||||||
if L > 0xFE:
|
|
||||||
bytelist = bytelist[L+4:]
|
|
||||||
else:
|
|
||||||
bytelist = bytelist[L+2:]
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
def dec_addr_tlv(hexstr):
|
|
||||||
"""
|
|
||||||
Decode hex string to get EF.P-CSCF Address or EF.ePDGId or EF.ePDGIdEm.
|
|
||||||
See 3GPP TS 31.102 version 13.4.0 Release 13, section 4.2.8, 4.2.102 and 4.2.104.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Convert from hex str to int bytes list
|
|
||||||
addr_tlv_bytes = h2i(hexstr)
|
|
||||||
|
|
||||||
# Get list of tuples containing parsed TLVs
|
|
||||||
tlvs = TLV_parser(addr_tlv_bytes)
|
|
||||||
|
|
||||||
for tlv in tlvs:
|
|
||||||
# tlv = (T, L, [V])
|
|
||||||
# T = Tag
|
|
||||||
# L = Length
|
|
||||||
# [V] = List of value
|
|
||||||
|
|
||||||
# Invalid Tag value scenario
|
|
||||||
if tlv[0] != 0x80:
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Empty field - Zero length
|
|
||||||
if tlv[1] == 0:
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Uninitialized field
|
|
||||||
if all([v == 0xff for v in tlv[2]]):
|
|
||||||
continue
|
|
||||||
|
|
||||||
# First byte in the value has the address type
|
|
||||||
addr_type = tlv[2][0]
|
|
||||||
# TODO: Support parsing of IPv6
|
|
||||||
# Address Type: 0x00 (FQDN), 0x01 (IPv4), 0x02 (IPv6), other (Reserved)
|
|
||||||
if addr_type == 0x00: # FQDN
|
|
||||||
# Skip address tye byte i.e. first byte in value list
|
|
||||||
content = tlv[2][1:]
|
|
||||||
return (i2s(content), '00')
|
|
||||||
|
|
||||||
elif addr_type == 0x01: # IPv4
|
|
||||||
# Skip address tye byte i.e. first byte in value list
|
|
||||||
# Skip the unused byte in Octect 4 after address type byte as per 3GPP TS 31.102
|
|
||||||
ipv4 = tlv[2][2:]
|
|
||||||
content = '.'.join(str(x) for x in ipv4)
|
|
||||||
return (content, '01')
|
|
||||||
else:
|
|
||||||
raise ValueError("Invalid address type")
|
|
||||||
|
|
||||||
return (None, None)
|
|
||||||
|
|
||||||
|
|
||||||
def enc_addr_tlv(addr, addr_type='00'):
|
|
||||||
"""
|
|
||||||
Encode address TLV object used in EF.P-CSCF Address, EF.ePDGId and EF.ePDGIdEm.
|
|
||||||
See 3GPP TS 31.102 version 13.4.0 Release 13, section 4.2.8, 4.2.102 and 4.2.104.
|
|
||||||
|
|
||||||
Default values:
|
|
||||||
- addr_type: 00 - FQDN format of Address
|
|
||||||
"""
|
|
||||||
|
|
||||||
s = ""
|
|
||||||
|
|
||||||
# TODO: Encoding of IPv6 address
|
|
||||||
if addr_type == '00': # FQDN
|
|
||||||
hex_str = s2h(addr)
|
|
||||||
s += '80' + ('%02x' % ((len(hex_str)//2)+1)) + '00' + hex_str
|
|
||||||
elif addr_type == '01': # IPv4
|
|
||||||
ipv4_list = addr.split('.')
|
|
||||||
ipv4_str = ""
|
|
||||||
for i in ipv4_list:
|
|
||||||
ipv4_str += ('%02x' % (int(i)))
|
|
||||||
|
|
||||||
# Unused bytes shall be set to 'ff'. i.e 4th Octet after Address Type is not used
|
|
||||||
# IPv4 Address is in octet 5 to octet 8 of the TLV data object
|
|
||||||
s += '80' + ('%02x' % ((len(ipv4_str)//2)+2)) + '01' + 'ff' + ipv4_str
|
|
||||||
|
|
||||||
return s
|
|
||||||
|
|
||||||
|
|
||||||
def is_hex(string: str, minlen: int = 2, maxlen: Optional[int] = None) -> bool:
|
def is_hex(string: str, minlen: int = 2, maxlen: Optional[int] = None) -> bool:
|
||||||
"""
|
"""
|
||||||
Check if a string is a valid hexstring
|
Check if a string is a valid hexstring
|
||||||
|
|||||||
Reference in New Issue
Block a user