Change in pysim[master]: pySim/transport: introduce Calypso based reader interface

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

Vadim Yanitskiy gerrit-no-reply at lists.osmocom.org
Mon Nov 12 15:25:12 UTC 2018


Vadim Yanitskiy has submitted this change and it was merged. ( https://gerrit.osmocom.org/11480 )

Change subject: pySim/transport: introduce Calypso based reader interface
......................................................................

pySim/transport: introduce Calypso based reader interface

This interface allows to use a Calypso based phone (e.g. Motorola
C1XX) as a SIM card reader. It basically implements a few L1CTL
messages that are used to interact with the SIM card through
the OsmocomBB 'layer1' firmware.

Please note, that this is an experimental implementation, and
there is a risk that SIM programming would fail. Nevertheless,
I've managed to program and read one of my SIMs a few times.

Change-Id: Iec8101140581bf9e2cf7cf3a0b54bdf1875fc51b
---
M pySim/exceptions.py
A pySim/transport/calypso.py
2 files changed, 160 insertions(+), 0 deletions(-)

Approvals:
  Jenkins Builder: Verified
  Harald Welte: Looks good to me, but someone else must approve
  tnt: Looks good to me, approved



diff --git a/pySim/exceptions.py b/pySim/exceptions.py
index 403f54c..831b1c9 100644
--- a/pySim/exceptions.py
+++ b/pySim/exceptions.py
@@ -31,3 +31,6 @@
 
 class ProtocolError(exceptions.Exception):
 	pass
+
+class ReaderError(exceptions.Exception):
+	pass
diff --git a/pySim/transport/calypso.py b/pySim/transport/calypso.py
new file mode 100644
index 0000000..fd501b5
--- /dev/null
+++ b/pySim/transport/calypso.py
@@ -0,0 +1,157 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+""" pySim: Transport Link for Calypso bases phones
+"""
+
+#
+# Copyright (C) 2018 Vadim Yanitskiy <axilirator at gmail.com>
+#
+# 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 __future__ import absolute_import
+
+import select
+import struct
+import socket
+import os
+
+from pySim.transport import LinkBase
+from pySim.exceptions import *
+from pySim.utils import h2b, b2h
+
+class L1CTLMessage(object):
+
+	# Every (encoded) L1CTL message has the following structure:
+	#  - msg_length (2 bytes, net order)
+	#  - l1ctl_hdr (packed structure)
+	#    - msg_type
+	#    - flags
+	#    - padding (2 spare bytes)
+	#  - ... payload ...
+
+	def __init__(self, msg_type, flags = 0x00):
+		# Init L1CTL message header
+		self.data = struct.pack("BBxx", msg_type, flags)
+
+	def gen_msg(self):
+		return struct.pack("!H", len(self.data)) + self.data
+
+class L1CTLMessageReset(L1CTLMessage):
+
+	# L1CTL message types
+	L1CTL_RESET_REQ		= 0x0d
+	L1CTL_RESET_IND		= 0x07
+	L1CTL_RESET_CONF	= 0x0e
+
+	# Reset types
+	L1CTL_RES_T_BOOT	= 0x00
+	L1CTL_RES_T_FULL	= 0x01
+	L1CTL_RES_T_SCHED	= 0x02
+
+	def __init__(self, type = L1CTL_RES_T_FULL):
+		super(L1CTLMessageReset, self).__init__(self.L1CTL_RESET_REQ)
+		self.data += struct.pack("Bxxx", type)
+
+class L1CTLMessageSIM(L1CTLMessage):
+
+	# SIM related message types
+	L1CTL_SIM_REQ		= 0x16
+	L1CTL_SIM_CONF		= 0x17
+
+	def __init__(self, pdu):
+		super(L1CTLMessageSIM, self).__init__(self.L1CTL_SIM_REQ)
+		self.data += pdu
+
+class CalypsoSimLink(LinkBase):
+
+	def __init__(self, sock_path = "/tmp/osmocom_l2"):
+		# Make sure that a given socket path exists
+		if not os.path.exists(sock_path):
+			raise ReaderError("There is no such ('%s') UNIX socket" % sock_path)
+
+		print("Connecting to osmocon at '%s'..." % sock_path)
+
+		# Establish a client connection
+		self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+		self.sock.connect(sock_path)
+
+	def __del__(self):
+		self.sock.close()
+
+	def wait_for_rsp(self, exp_len = 128):
+		# Wait for incoming data (timeout is 3 seconds)
+		s, _, _ = select.select([self.sock], [], [], 3.0)
+		if not s:
+			raise ReaderError("Timeout waiting for card response")
+
+		# Receive expected amount of bytes from osmocon
+		rsp = self.sock.recv(exp_len)
+		return rsp
+
+	def reset_card(self):
+		# Request FULL reset
+		req_msg = L1CTLMessageReset()
+		self.sock.send(req_msg.gen_msg())
+
+		# Wait for confirmation
+		rsp = self.wait_for_rsp()
+		rsp_msg = struct.unpack_from("!HB", rsp)
+		if rsp_msg[1] != L1CTLMessageReset.L1CTL_RESET_CONF:
+			raise ReaderError("Failed to reset Calypso PHY")
+
+	def connect(self):
+		self.reset_card()
+
+	def disconnect(self):
+		pass # Nothing to do really ...
+
+	def wait_for_card(self, timeout = None, newcardonly = False):
+		pass # Nothing to do really ...
+
+	def send_apdu_raw(self, pdu):
+		"""see LinkBase.send_apdu_raw"""
+
+		# Request FULL reset
+		req_msg = L1CTLMessageSIM(h2b(pdu))
+		self.sock.send(req_msg.gen_msg())
+
+		# Read message length first
+		rsp = self.wait_for_rsp(struct.calcsize("!H"))
+		msg_len = struct.unpack_from("!H", rsp)[0]
+		if msg_len < struct.calcsize("BBxx"):
+			raise ReaderError("Missing L1CTL header for L1CTL_SIM_CONF")
+
+		# Read the whole message then
+		rsp = self.sock.recv(msg_len)
+
+		# Verify L1CTL header
+		hdr = struct.unpack_from("BBxx", rsp)
+		if hdr[0] != L1CTLMessageSIM.L1CTL_SIM_CONF:
+			raise ReaderError("Unexpected L1CTL message received")
+
+		# Verify the payload length
+		offset = struct.calcsize("BBxx")
+		if len(rsp) <= offset:
+			raise ProtocolError("Empty response from SIM?!?")
+
+		# Omit L1CTL header
+		rsp = rsp[offset:]
+
+		# Unpack data and SW
+		data = rsp[:-2]
+		sw = rsp[-2:]
+
+		return b2h(data), b2h(sw)

-- 
To view, visit https://gerrit.osmocom.org/11480
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-MessageType: merged
Gerrit-Change-Id: Iec8101140581bf9e2cf7cf3a0b54bdf1875fc51b
Gerrit-Change-Number: 11480
Gerrit-PatchSet: 3
Gerrit-Owner: Vadim Yanitskiy <axilirator at gmail.com>
Gerrit-Assignee: tnt <tnt at 246tNt.com>
Gerrit-Reviewer: Harald Welte <laforge at gnumonks.org>
Gerrit-Reviewer: Jenkins Builder (1000002)
Gerrit-Reviewer: Vadim Yanitskiy <axilirator at gmail.com>
Gerrit-Reviewer: tnt <tnt at 246tNt.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20181112/1d7fe892/attachment.htm>


More information about the gerrit-log mailing list