mirror of
https://gitea.osmocom.org/sim-card/pysim.git
synced 2026-03-16 18:38:32 +03:00
Migrate over to using pyosmocom
We're creating a 'pyosmocom' pypi module which contains a number of core Osmocom libraries / interfaces that are not specific to SIM card stuff contained here. The main modules moved in this initial step are pySim.tlv, pySim.utils and pySim.construct. utils is split, not all of the contents is unrelated to SIM Cards. The other two are moved completely. Change-Id: I4b63e45bcb0c9ba2424dacf85e0222aee735f411
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import unittest
|
||||
from pySim.utils import h2b, b2h
|
||||
from pySim.construct import filter_dict
|
||||
from osmocom.utils import h2b, b2h
|
||||
from osmocom.construct import filter_dict
|
||||
|
||||
from pySim.apdu import Apdu
|
||||
from pySim.apdu.ts_31_102 import UsimAuthenticateEven
|
||||
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import unittest
|
||||
from pySim.utils import b2h, h2b
|
||||
from pySim.construct import *
|
||||
from construct import FlagsEnum
|
||||
|
||||
tests = [
|
||||
( b'\x80', 0x80 ),
|
||||
( b'\x80\x01', 0x8001 ),
|
||||
( b'\x80\x00\x01', 0x800001 ),
|
||||
( b'\x80\x23\x42\x01', 0x80234201 ),
|
||||
]
|
||||
|
||||
class TestGreedyInt(unittest.TestCase):
|
||||
def test_GreedyInt_decoder(self):
|
||||
gi = GreedyInteger()
|
||||
for t in tests:
|
||||
self.assertEqual(gi.parse(t[0]), t[1])
|
||||
def test_GreedyInt_encoder(self):
|
||||
gi = GreedyInteger()
|
||||
for t in tests:
|
||||
self.assertEqual(t[0], gi.build(t[1]))
|
||||
pass
|
||||
|
||||
class TestUtils(unittest.TestCase):
|
||||
def test_filter_dict(self):
|
||||
inp = {'foo': 0xf00, '_bar' : 0xba5, 'baz': 0xba2 }
|
||||
out = {'foo': 0xf00, 'baz': 0xba2 }
|
||||
self.assertEqual(filter_dict(inp), out)
|
||||
|
||||
def test_filter_dict_nested(self):
|
||||
inp = {'foo': 0xf00, 'nest': {'_bar' : 0xba5}, 'baz': 0xba2 }
|
||||
out = {'foo': 0xf00, 'nest': {}, 'baz': 0xba2 }
|
||||
self.assertEqual(filter_dict(inp), out)
|
||||
|
||||
|
||||
class TestUcs2Adapter(unittest.TestCase):
|
||||
# the three examples from TS 102 221 Annex A
|
||||
EXAMPLE1 = b'\x80\x00\x30\x00\x31\x00\x32\x00\x33'
|
||||
EXAMPLE2 = b'\x81\x05\x13\x53\x95\xa6\xa6\xff\xff'
|
||||
EXAMPLE3 = b'\x82\x05\x05\x30\x2d\x82\xd3\x2d\x31'
|
||||
ad = Ucs2Adapter(GreedyBytes)
|
||||
|
||||
def test_example1_decode(self):
|
||||
dec = self.ad._decode(self.EXAMPLE1, None, None)
|
||||
self.assertEqual(dec, "0123")
|
||||
|
||||
def test_example2_decode(self):
|
||||
dec = self.ad._decode(self.EXAMPLE2, None, None)
|
||||
self.assertEqual(dec, "S\u0995\u09a6\u09a6\u09ff")
|
||||
|
||||
def test_example3_decode(self):
|
||||
dec = self.ad._decode(self.EXAMPLE3, None, None)
|
||||
self.assertEqual(dec, "-\u0532\u0583-1")
|
||||
|
||||
testdata = [
|
||||
# variant 2 with only GSM alphabet characters
|
||||
( "mahlzeit", '8108006d61686c7a656974' ),
|
||||
# variant 2 with mixed GSM alphabet + UCS2
|
||||
( "mahlzeit\u099523", '810b136d61686c7a656974953233' ),
|
||||
# variant 3 due to codepoint exceeding 8 bit
|
||||
( "mahl\u8023zeit", '820980236d61686c807a656974' ),
|
||||
# variant 1 as there is no common codepoint pointer / prefix
|
||||
( "\u3000\u2000\u1000", '80300020001000' ),
|
||||
]
|
||||
|
||||
def test_data_decode(self):
|
||||
for string, encoded_hex in self.testdata:
|
||||
encoded = h2b(encoded_hex)
|
||||
dec = self.ad._decode(encoded, None, None)
|
||||
self.assertEqual(dec, string)
|
||||
|
||||
def test_data_encode(self):
|
||||
for string, encoded_hex in self.testdata:
|
||||
encoded = h2b(encoded_hex)
|
||||
re_enc = self.ad._encode(string, None, None)
|
||||
self.assertEqual(encoded, re_enc)
|
||||
|
||||
class TestTrailerAdapter(unittest.TestCase):
|
||||
Privileges = FlagsEnum(StripTrailerAdapter(GreedyBytes, 3), security_domain=0x800000,
|
||||
dap_verification=0x400000,
|
||||
delegated_management=0x200000, card_lock=0x100000,
|
||||
card_terminate=0x080000, card_reset=0x040000,
|
||||
cvm_management=0x020000, mandated_dap_verification=0x010000,
|
||||
trusted_path=0x8000, authorized_management=0x4000,
|
||||
token_management=0x2000, global_delete=0x1000,
|
||||
global_lock=0x0800, global_registry=0x0400,
|
||||
final_application=0x0200, global_service=0x0100,
|
||||
receipt_generation=0x80, ciphered_load_file_data_block=0x40,
|
||||
contactless_activation=0x20, contactless_self_activation=0x10)
|
||||
examples = ['00', '80', '8040', '400010']
|
||||
def test_examples(self):
|
||||
for e in self.examples:
|
||||
dec = self.Privileges.parse(h2b(e))
|
||||
reenc = self.Privileges.build(dec)
|
||||
self.assertEqual(e, b2h(reenc))
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -18,8 +18,8 @@
|
||||
import unittest
|
||||
import logging
|
||||
import base64
|
||||
from osmocom.utils import b2h, h2b
|
||||
|
||||
from pySim.utils import b2h, h2b
|
||||
from pySim.esim.bsp import *
|
||||
import pySim.esim.rsp as rsp
|
||||
from pySim.esim import ActivationCode
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
import unittest
|
||||
import logging
|
||||
import base64
|
||||
from osmocom.utils import b2h, h2b
|
||||
|
||||
from pySim.utils import b2h, h2b
|
||||
from pySim.esim.bsp import *
|
||||
import pySim.esim.rsp as rsp
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
import unittest
|
||||
import logging
|
||||
import copy
|
||||
from osmocom.utils import h2b, b2h
|
||||
|
||||
from pySim.utils import h2b, b2h
|
||||
from pySim.esim.saip import *
|
||||
from pySim.esim.saip.personalization import *
|
||||
from pprint import pprint as pp
|
||||
|
||||
@@ -17,10 +17,9 @@
|
||||
|
||||
import unittest
|
||||
import logging
|
||||
from osmocom.utils import *
|
||||
|
||||
from pySim.utils import *
|
||||
from pySim.filesystem import *
|
||||
|
||||
import pySim.iso7816_4
|
||||
import pySim.ts_102_221
|
||||
import pySim.ts_102_222
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
|
||||
import unittest
|
||||
import logging
|
||||
from osmocom.utils import b2h, h2b
|
||||
|
||||
from pySim.global_platform import *
|
||||
from pySim.global_platform.scp import *
|
||||
from pySim.utils import b2h, h2b
|
||||
|
||||
KIC = h2b('100102030405060708090a0b0c0d0e0f') # enc
|
||||
KID = h2b('101102030405060708090a0b0c0d0e0f') # MAC
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import unittest
|
||||
from pySim.utils import h2b, b2h
|
||||
from osmocom.utils import h2b, b2h
|
||||
from pySim.sms import SMS_SUBMIT, SMS_DELIVER, AddressField
|
||||
from pySim.ota import *
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import unittest
|
||||
from pySim.utils import h2b, b2h
|
||||
from osmocom.utils import h2b, b2h
|
||||
from pySim.sms import *
|
||||
|
||||
class Test_SMS_UDH(unittest.TestCase):
|
||||
|
||||
@@ -1,145 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# (C) 2022 by Harald Welte <laforge@osmocom.org>
|
||||
# All Rights Reserved
|
||||
#
|
||||
# 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/>.
|
||||
|
||||
import unittest
|
||||
from construct import Int8ub, GreedyBytes
|
||||
from pySim.tlv import *
|
||||
from pySim.utils import h2b
|
||||
|
||||
class TestUtils(unittest.TestCase):
|
||||
def test_camel_to_snake(self):
|
||||
cases = [
|
||||
('CamelCase', 'camel_case'),
|
||||
('CamelCaseUPPER', 'camel_case_upper'),
|
||||
('Camel_CASE_underSCORE', 'camel_case_under_score'),
|
||||
]
|
||||
for c in cases:
|
||||
self.assertEqual(camel_to_snake(c[0]), c[1])
|
||||
|
||||
def test_flatten_dict_lists(self):
|
||||
inp = [
|
||||
{ 'first': 1 },
|
||||
{ 'second': 2 },
|
||||
{ 'third': 3 },
|
||||
]
|
||||
out = { 'first': 1, 'second':2, 'third': 3}
|
||||
self.assertEqual(flatten_dict_lists(inp), out)
|
||||
|
||||
def test_flatten_dict_lists_nodict(self):
|
||||
inp = [
|
||||
{ 'first': 1 },
|
||||
{ 'second': 2 },
|
||||
{ 'third': 3 },
|
||||
4,
|
||||
]
|
||||
self.assertEqual(flatten_dict_lists(inp), inp)
|
||||
|
||||
def test_flatten_dict_lists_nested(self):
|
||||
inp = {'top': [
|
||||
{ 'first': 1 },
|
||||
{ 'second': 2 },
|
||||
{ 'third': 3 },
|
||||
] }
|
||||
out = {'top': { 'first': 1, 'second':2, 'third': 3 } }
|
||||
self.assertEqual(flatten_dict_lists(inp), out)
|
||||
|
||||
class TestTranscodable(unittest.TestCase):
|
||||
class XC_constr_class(Transcodable):
|
||||
_construct = Int8ub
|
||||
def __init__(self):
|
||||
super().__init__();
|
||||
|
||||
def test_XC_constr_class(self):
|
||||
"""Transcodable derived class with _construct class variable"""
|
||||
xc = TestTranscodable.XC_constr_class()
|
||||
self.assertEqual(xc.from_bytes(b'\x23'), 35)
|
||||
self.assertEqual(xc.to_bytes(), b'\x23')
|
||||
|
||||
class XC_constr_instance(Transcodable):
|
||||
def __init__(self):
|
||||
super().__init__();
|
||||
self._construct = Int8ub
|
||||
|
||||
def test_XC_constr_instance(self):
|
||||
"""Transcodable derived class with _construct instance variable"""
|
||||
xc = TestTranscodable.XC_constr_instance()
|
||||
self.assertEqual(xc.from_bytes(b'\x23'), 35)
|
||||
self.assertEqual(xc.to_bytes(), b'\x23')
|
||||
|
||||
class XC_method_instance(Transcodable):
|
||||
def __init__(self):
|
||||
super().__init__();
|
||||
def _from_bytes(self, do):
|
||||
return ('decoded', do)
|
||||
def _to_bytes(self):
|
||||
return self.decoded[1]
|
||||
|
||||
def test_XC_method_instance(self):
|
||||
"""Transcodable derived class with _{from,to}_bytes() methods"""
|
||||
xc = TestTranscodable.XC_method_instance()
|
||||
self.assertEqual(xc.to_bytes(), b'')
|
||||
self.assertEqual(xc.from_bytes(b''), None)
|
||||
self.assertEqual(xc.from_bytes(b'\x23'), ('decoded', b'\x23'))
|
||||
self.assertEqual(xc.to_bytes(), b'\x23')
|
||||
|
||||
class TestIE(unittest.TestCase):
|
||||
class MyIE(IE, tag=0x23, desc='My IE description'):
|
||||
_construct = Int8ub
|
||||
def to_ie(self):
|
||||
return self.to_bytes()
|
||||
|
||||
def test_IE_empty(self):
|
||||
ie = TestIE.MyIE()
|
||||
self.assertEqual(ie.to_dict(), {'my_ie': None})
|
||||
self.assertEqual(repr(ie), 'MyIE(None)')
|
||||
self.assertEqual(ie.is_constructed(), False)
|
||||
|
||||
def test_IE_from_bytes(self):
|
||||
ie = TestIE.MyIE()
|
||||
ie.from_bytes(b'\x42')
|
||||
self.assertEqual(ie.to_dict(), {'my_ie': 66})
|
||||
self.assertEqual(repr(ie), 'MyIE(66)')
|
||||
self.assertEqual(ie.is_constructed(), False)
|
||||
self.assertEqual(ie.to_bytes(), b'\x42')
|
||||
self.assertEqual(ie.to_ie(), b'\x42')
|
||||
|
||||
class TestCompact(unittest.TestCase):
|
||||
class IE_3(COMPACT_TLV_IE, tag=0x3):
|
||||
_construct = GreedyBytes
|
||||
class IE_7(COMPACT_TLV_IE, tag=0x7):
|
||||
_construct = GreedyBytes
|
||||
class IE_5(COMPACT_TLV_IE, tag=0x5):
|
||||
_construct = GreedyBytes
|
||||
# pylint: disable=undefined-variable
|
||||
class IE_Coll(TLV_IE_Collection, nested=[IE_3, IE_7, IE_5]):
|
||||
_construct = GreedyBytes
|
||||
def test_ATR(self):
|
||||
atr = h2b("31E073FE211F5745437531301365")
|
||||
c = self.IE_Coll()
|
||||
c.from_tlv(atr)
|
||||
self.assertEqual(c.children[0].tag, 3)
|
||||
self.assertEqual(c.children[0].to_bytes(), b'\xe0')
|
||||
self.assertEqual(c.children[1].tag, 7)
|
||||
self.assertEqual(c.children[1].to_bytes(), b'\xfe\x21\x1f')
|
||||
self.assertEqual(c.children[2].tag, 5)
|
||||
self.assertEqual(c.children[2].to_bytes(), b'\x45\x43\x75\x31\x30\x13\x65')
|
||||
self.assertEqual(c.to_tlv(), atr)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -18,8 +18,8 @@
|
||||
import unittest
|
||||
import logging
|
||||
|
||||
from pySim.utils import b2h, h2b, all_subclasses
|
||||
from pySim.tlv import *
|
||||
from osmocom.utils import b2h, h2b, all_subclasses
|
||||
from osmocom.tlv import *
|
||||
|
||||
import pySim.iso7816_4
|
||||
import pySim.ts_102_221
|
||||
|
||||
@@ -172,70 +172,6 @@ class DecTestCase(unittest.TestCase):
|
||||
msisdn_decoded = utils.dec_msisdn("ffffffffffffffffffffffffffffffffffffffff0bb121436587092143658709ffff")
|
||||
self.assertEqual(msisdn_decoded, (1, 3, "12345678901234567890"))
|
||||
|
||||
class TestBerTlv(unittest.TestCase):
|
||||
def test_BerTlvTagDec(self):
|
||||
res = utils.bertlv_parse_tag(b'\x01')
|
||||
self.assertEqual(res, ({'tag':1, 'constructed':False, 'class': 0}, b''))
|
||||
res = utils.bertlv_parse_tag(b'\x21')
|
||||
self.assertEqual(res, ({'tag':1, 'constructed':True, 'class': 0}, b''))
|
||||
res = utils.bertlv_parse_tag(b'\x81\x23')
|
||||
self.assertEqual(res, ({'tag':1, 'constructed':False, 'class': 2}, b'\x23'))
|
||||
res = utils.bertlv_parse_tag(b'\x1f\x8f\x00\x23')
|
||||
self.assertEqual(res, ({'tag':0xf<<7, 'constructed':False, 'class': 0}, b'\x23'))
|
||||
|
||||
def test_BerTlvLenDec(self):
|
||||
self.assertEqual(utils.bertlv_encode_len(1), b'\x01')
|
||||
self.assertEqual(utils.bertlv_encode_len(127), b'\x7f')
|
||||
self.assertEqual(utils.bertlv_encode_len(128), b'\x81\x80')
|
||||
self.assertEqual(utils.bertlv_encode_len(0x123456), b'\x83\x12\x34\x56')
|
||||
|
||||
def test_BerTlvLenEnc(self):
|
||||
self.assertEqual(utils.bertlv_parse_len(b'\x01\x23'), (1, b'\x23'))
|
||||
self.assertEqual(utils.bertlv_parse_len(b'\x7f'), (127, b''))
|
||||
self.assertEqual(utils.bertlv_parse_len(b'\x81\x80'), (128, b''))
|
||||
self.assertEqual(utils.bertlv_parse_len(b'\x83\x12\x34\x56\x78'), (0x123456, b'\x78'))
|
||||
|
||||
def test_BerTlvParseOne(self):
|
||||
res = utils.bertlv_parse_one(b'\x81\x01\x01');
|
||||
self.assertEqual(res, ({'tag':1, 'constructed':False, 'class':2}, 1, b'\x01', b''))
|
||||
|
||||
class TestComprTlv(unittest.TestCase):
|
||||
def test_ComprTlvTagDec(self):
|
||||
res = utils.comprehensiontlv_parse_tag(b'\x12\x23')
|
||||
self.assertEqual(res, ({'tag': 0x12, 'comprehension': False}, b'\x23'))
|
||||
res = utils.comprehensiontlv_parse_tag(b'\x92')
|
||||
self.assertEqual(res, ({'tag': 0x12, 'comprehension': True}, b''))
|
||||
res = utils.comprehensiontlv_parse_tag(b'\x7f\x12\x34')
|
||||
self.assertEqual(res, ({'tag': 0x1234, 'comprehension': False}, b''))
|
||||
res = utils.comprehensiontlv_parse_tag(b'\x7f\x82\x34\x56')
|
||||
self.assertEqual(res, ({'tag': 0x234, 'comprehension': True}, b'\x56'))
|
||||
|
||||
def test_ComprTlvTagEnc(self):
|
||||
res = utils.comprehensiontlv_encode_tag(0x12)
|
||||
self.assertEqual(res, b'\x12')
|
||||
res = utils.comprehensiontlv_encode_tag({'tag': 0x12})
|
||||
self.assertEqual(res, b'\x12')
|
||||
res = utils.comprehensiontlv_encode_tag({'tag': 0x12, 'comprehension':True})
|
||||
self.assertEqual(res, b'\x92')
|
||||
res = utils.comprehensiontlv_encode_tag(0x1234)
|
||||
self.assertEqual(res, b'\x7f\x12\x34')
|
||||
res = utils.comprehensiontlv_encode_tag({'tag': 0x1234, 'comprehension':True})
|
||||
self.assertEqual(res, b'\x7f\x92\x34')
|
||||
|
||||
class TestDgiTlv(unittest.TestCase):
|
||||
def test_DgiTlvLenEnc(self):
|
||||
self.assertEqual(utils.dgi_encode_len(10), b'\x0a')
|
||||
self.assertEqual(utils.dgi_encode_len(254), b'\xfe')
|
||||
self.assertEqual(utils.dgi_encode_len(255), b'\xff\x00\xff')
|
||||
self.assertEqual(utils.dgi_encode_len(65535), b'\xff\xff\xff')
|
||||
with self.assertRaises(ValueError):
|
||||
utils.dgi_encode_len(65536)
|
||||
|
||||
def testDgiTlvLenDec(self):
|
||||
self.assertEqual(utils.dgi_parse_len(b'\x0a\x0b'), (10, b'\x0b'))
|
||||
self.assertEqual(utils.dgi_parse_len(b'\xfe\x0b'), (254, b'\x0b'))
|
||||
self.assertEqual(utils.dgi_parse_len(b'\xff\x00\xff\x0b'), (255, b'\x0b'))
|
||||
|
||||
class TestLuhn(unittest.TestCase):
|
||||
def test_verify(self):
|
||||
utils.verify_luhn('8988211000000530082')
|
||||
|
||||
Reference in New Issue
Block a user