mirror of
https://gitea.osmocom.org/sim-card/pysim.git
synced 2026-03-17 19:08:35 +03:00
The trace log currently does not contain any information about card resets. This makes the trace difficult to follow. Let's use the CardReset object to display the ATR in the trace. Related: OS#6094 Change-Id: Ia550a8bd2f45d2ad622cb2ac2a2905397db76bce
91 lines
3.3 KiB
Python
91 lines
3.3 KiB
Python
# coding=utf-8
|
|
|
|
# (C) 2022 by 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/>.
|
|
|
|
|
|
import sys
|
|
import logging
|
|
from pprint import pprint as pp
|
|
from typing import Tuple
|
|
import pyshark
|
|
|
|
from pySim.utils import h2b, b2h
|
|
from pySim.apdu import Tpdu
|
|
from pySim.gsmtap import GsmtapMessage
|
|
from . import ApduSource, PacketType, CardReset
|
|
|
|
from pySim.apdu.ts_102_221 import ApduCommands as UiccApduCommands
|
|
from pySim.apdu.ts_31_102 import ApduCommands as UsimApduCommands
|
|
from pySim.apdu.global_platform import ApduCommands as GpApduCommands
|
|
ApduCommands = UiccApduCommands + UsimApduCommands + GpApduCommands
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
class _PysharkGsmtap(ApduSource):
|
|
"""APDU Source [provider] base class for reading GSMTAP SIM APDU via tshark."""
|
|
|
|
def __init__(self, pyshark_inst):
|
|
self.pyshark = pyshark_inst
|
|
self.bank_id = None
|
|
self.bank_slot = None
|
|
self.cmd_tpdu = None
|
|
super().__init__()
|
|
|
|
def read_packet(self) -> PacketType:
|
|
p = self.pyshark.next()
|
|
return self._parse_packet(p)
|
|
|
|
def _set_or_verify_bank_slot(self, bsl: Tuple[int, int]):
|
|
"""Keep track of the bank:slot to make sure we don't mix traces of multiple cards"""
|
|
if not self.bank_id:
|
|
self.bank_id = bsl[0]
|
|
self.bank_slot = bsl[1]
|
|
else:
|
|
if self.bank_id != bsl[0] or self.bank_slot != bsl[1]:
|
|
raise ValueError('Received data for unexpected B(%u:%u)' % (bsl[0], bsl[1]))
|
|
|
|
def _parse_packet(self, p) -> PacketType:
|
|
udp_layer = p['udp']
|
|
udp_payload_hex = udp_layer.get_field('payload').replace(':','')
|
|
gsmtap = GsmtapMessage(h2b(udp_payload_hex))
|
|
gsmtap_msg = gsmtap.decode()
|
|
if gsmtap_msg['type'] != 'sim':
|
|
raise ValueError('Unsupported GSMTAP type %s' % gsmtap_msg['type'])
|
|
sub_type = gsmtap_msg['sub_type']
|
|
if sub_type == 'apdu':
|
|
return ApduCommands.parse_cmd_bytes(gsmtap_msg['body'])
|
|
elif sub_type == 'atr':
|
|
# card has been reset
|
|
return CardReset(gsmtap_msg['body'])
|
|
elif sub_type in ['pps_req', 'pps_rsp']:
|
|
# simply ignore for now
|
|
pass
|
|
else:
|
|
raise ValueError('Unsupported GSMTAP-SIM sub-type %s' % sub_type)
|
|
|
|
class PysharkGsmtapPcap(_PysharkGsmtap):
|
|
"""APDU Source [provider] class for reading GSMTAP from a PCAP
|
|
file via pyshark, which in turn uses tshark (part of wireshark).
|
|
"""
|
|
def __init__(self, pcap_filename):
|
|
"""
|
|
Args:
|
|
pcap_filename: File name of the pcap file to be opened
|
|
"""
|
|
pyshark_inst = pyshark.FileCapture(pcap_filename, display_filter='gsm_sim', use_json=True, keep_packets=False)
|
|
super().__init__(pyshark_inst)
|
|
|