view doc/Sniffer-FPGA-design @ 37:432d756a21f1

doc/Sniffing-workflow: document written
author Mychaela Falconia <falcon@freecalypso.org>
date Wed, 30 Aug 2023 03:03:04 +0000
parents 695ca51e1564
children 1068f9fd41d5
line wrap: on
line source

FPGA component of SIMtrace3 sniffer
===================================

The SIM interface sniffing apparatus of SIMtrace3 consists of a sniffer pod
(hardware adapter with level shifters) and a Lattice Icestick FPGA board, loaded
with the appropriate gateware image from the present project.  This document
describes the design and operation of the FPGA component of this SIMtrace3
sniffing solution.

Hardware architecture and FPGA design principle
===============================================

The two principal components of the Icestick board are an iCE40HX1K FPGA and an
FT2232H-based USB host interface.  Our sniffer logic function in the FPGA
operates principally as a byte forwarder from the ISO 7816-3 sniffer block to
the FT2232H UART: every time the bus sniffer block captures a character (in ISO
7816-3 terminology) being passed on the SIM electrical interface in either
direction (the two directions of transmission are indistinguishable to a tap
sniffer that does not actively participate in the protocol), the FPGA forwards
this character to the connected host computer (by way of FT2232H UART) for
further processing in software.  The UART data line going from the FPGA to the
FT2232H is the sole functional output from this FPGA, aside from some
non-essential LED outputs: right now the green LED shows the current state of
SIM RST line, and we might add another LED showing if SIM CLK is running or
stopped.  The other UART data line going the opposite direction (output from
FT2232H) remains unused in this application, i.e., the host software application
will only read/receive from the ttyUSBx FPGA device and won't send anything to
it.  All modem control lines on this UART interface likewise remain unused.

Serial interface format
=======================

For every ISO 7816-3 character captured by the sniffer, two back-to-back UART
bytes are transferred from the FPGA to the host computer; more generally, the
FPGA can only transmit pairs of back-to-back bytes on this UART and no
singletons or other arrangements - thus the host receiver can always recover
synchronization by dropping any partially received two-byte message (the first
byte of an expected pair) during prolonged pauses.  The FPGA transmits the two
back-to-back UART bytes as a single shift-out of 20 bits, conveying two bytes
in 8N1 framing.

Why are we turning every captured ISO 7816-3 character into a pair of bytes on
our internal UART interface, why not simply forward it as a single byte?  The
reason is that we need to pass some additional bits beyond the 8 that comprise
the ISO 7816-3 character payload; the additional bits which we need to pass are
as follows:

- the received parity bit;
- a flag indicating whether or not an error signal (ISO 7816-3 section 7.3)
  was seen;
- additional flag bits communicating SIM RST assertion and negation events,
  as distinct from ISO 7816-3 characters;
- additional flags indicating actions of the integrated PPS catcher state
  machine, to be described later in this document.

Assertion or negation of SIM RST is the only other possible event (besides ISO
7816-3 character capture, with or without attendant PPS catcher state machine
action) that can cause the FPGA to send a byte-pair UART message to the host
computer.  One bit in the 16-bit message will distinguish between characters
and RST events, another bit will indicate the state of RST at the time of the
event (new RST for transitions, 1 for characters), and all other bits are
meaningful only for characters.

Detailed serial interface format
--------------------------------

Treating the two transmitted bytes as a single 16-bit word, with the least
significant 8 bits transmitted first (matching the transmission order of bits
within a byte, see IEN 137), the 16 bits of this word are assigned as follows:

Bit 15: set to 0 if this message signals ISO 7816-3 character reception or 1 if
it signals a change of state in the RST line.

Bit 14: new state of RST in the case of RST state change messages; should always
be 1 in character Rx messages.

The remaining bits are valid only in character Rx messages:

Bit 13: set to 0 if this character was captured in F/D=372 mode or 1 if it was
captured in one of the supported speed enhancement modes (F=512, D=8/16/32/64).

Bit 12: set to 1 in the byte position that is expected to be the final PCK byte
of the card's PPS response in the case of supported speed enhancement modes,
0 otherwise.

Bit 11: set to 1 in the byte position that is expected to be the PPS1 byte of
the card's PPS response, 0 otherwise.

Bit 10: set to 1 if the error signal of ISO 7816-3 section 7.3 was detected,
0 otherwise.

Bit 9: sampled line value at the midpoint of the start bit, should be 0 in a
properly working system.

Bit 8: received parity bit;

Bits [7:0]: payload bits of the received character.

UART baud rate
==============

The baud rate on the UART interface between the FPGA and the FT2232H converter
is 3000000 bps.  This high (and very non-RS232-standard) UART baud rate was
chosen for the following reasons:

* Our UART interface is totally private, going nowhere but the on-board FT2232H,
  thus it doesn't matter if the baud rate is standard-ish or totally
  non-standard.

* No cables of any kind are used, instead the UART interface is confined to
  short PCB traces running between the FPGA and the FTDI chip on the same board
  - hence high baud rates are not a problem.

* Our UART baud rate needs to be high enough to provide good margin, despite
  our 2x expansion, at the highest possible effective bps rate on the SIM
  interface, meaning the highest possible SIM CLK frequency and the most
  aggressive F/D ratio.  The combination of SIM CLK at 5 MHz, F=512 and D=64
  corresponds to 625000 bps effective on the SIM interface; running our UART at
  3 Mbps provides sufficient margin.

Clocking design
===============

The FPGA on the Icestick board receives a 12 MHz clock input.  Our original
plan was to use the FPGA's on-chip PLL to multiply this clock by 4, producing a
48 MHz system clock - however, this plan has been shelved for now, and our
current sniffer design uses the 12 MHz clock directly as its system clock.

The 3 inputs to the FPGA coming from the SIM electrical sniffer (buffered and
level-shifted SIM RST, CLK and I/O lines) pass through two cascaded DFFs,
bringing them into our internal clock domain.  The delay added by these cascaded
DFFs is not a concern: we are a passive sniffer without any output back to the
SIM interface, and all 3 signal inputs will be subject to the same delay.

As stated in the previous section, the baud rate on the UART interface between
the FPGA and the FT2232H converter is 3000000 bps.  The UART output block in
the FPGA uses a simple /4 divider from CLK12 (board-level 12 MHz clock input)
to time its output bits; the original intent was to use a /16 divider from
48 MHz SYSCLK.

ISO 7816-3 sniffer block
========================

Our ISO 7816-3 receiver triggers on the falling edge of the I/O line.  Once it
detects a high-to-low transition on the SYSCLK-synchronized SIM_IO input, it
starts counting SIM CLK cycles - we are arbitrarily choosing low-to-high
transition of SYSCLK-synchronized SIM_CLK input as the trigger point.  (This
choice is arbitrary because per the spec there is no defined phase relation
between SIM CLK and SIM I/O transitions.)

Our ISO 7816-3 receiver needs to know how many SIM CLK cycles constitute one
etu - or more precisely, our sniffing receiver needs to know how many SIM CLK
cycles constitute 0.5 etu, 1 etu and 1.5 etu, in order to locate various needed
sampling points relative to the instant at which SIM_IO was initially sampled
low.  Our sniffer-pps FPGA supports the following combinations:

F=372, D=1: 372 clocks per etu
F=512, D=8: 64 clocks per etu
F=512, D=16: 32 clocks per etu
F=512, D=32: 16 clocks per etu
F=512, D=64: 8 clocks per etu

Our sniffing Rx is held down in reset (won't receive anything) while SIM RST is
low; as we come out of reset upon SIM RST line going high, our sniffing Rx is in
F/D=372 mode and the PPS catcher state machine is set to its initial state.  As
ISO 7816-3 characters captured in this F/D=372 mode are received, our PPS
catcher state machine follows the spec-defined structure of ATR to locate its
end.  If the end of ATR is followed by a PPS request which is then followed by
a PPS response, and if the PPS response from the card includes a PPS1 byte that
invokes one of our supported speed enhancement modes listed above, the sniffing
receiver's notion of etu length is switched at the correct point in time:
immediately after finishing RX of the PCK byte that concludes the card's PPS
response.

Direct and inverse coding conventions
=====================================

Only the card and not the interface device (ISO 7816-3 terminology) determines
which coding convention is used, direct or inverse.  So far we (FreeCalypso)
have not yet encountered a real-life SIM that uses the inverse convention, only
the direct convention kind.  In the sniffer function of SIMtrace-ice, we are
going to keep our FPGA gateware simple in this regard and punt all inverse
convention handling to the software application on the host computer: the FPGA
passes the 9 received bits (8 data bits and 1 parity bit) to the 16-bit UART
message as-is, without inverting or reordering them.

Integrated PPS catcher
======================

Our sniffer FPGA logic was developed incrementally.  The first version,
preserved in fpga/sniffer-basic in case we ever need to revisit it, uses an ISO
7816-3 sniffing Rx block with fixed F/D ratio of 372.  That simple version is
sufficient for sniffing exchanges between a GSM ME and a SIM *if* the etu-
defining F/D ratio is never switched from the basic default of 372, either
because the SIM does not support speed enhancement or because the ME does not
support such.  However, such no-speed-enhancement scenarios are rare:

* All commercial operators' SIMs in the present era do support speed
  enhancement, and so do our own FCSIM1 cards.  More specifically, our FCSIM1
  model supports F=512 D=8, while most commercial operators' SIMs that have
  passed through Mother's hands (plus sysmoUSIM-SJS1 and sysmoISIM-SJA2)
  support F=512 D=32.

* F=512 D=8 is a speed enhancement mode endorsed by the most classic GSM 11.11
  spec, and it is supported by classic GSM ME implementations including our dear
  Calypso.

As a result of the above two factors, most real-life GSM ME to SIM sessions
which we will need to sniff and trace in the course of Vintage Mobile Phone
debugging and support will include a PPS exchange switching from F/D=372 to a
smaller number of SIM CLK cycles per etu, specifically one of F=512 D=8/16/32/64
modes.

The main difficulty with capturing SIM interface sessions that use speed
enhancement is as follows: in order for the session capture to be complete,
without any lost bits, the sniffing receiver's knowledge of how many SIM CLK
cycles constitute an etu needs to change to the new value at exactly the
correct moment in time, which is the moment immediately after the last byte
(PCK) of the SIM's PPS response passes across the wire.  If we were to rely on
host software to decode all byte exchanges up to this point (ATR from the SIM,
PPS request from ME/ID, then PPS response) and command the FPGA (UART in the
other direction, or a modem control line) to switch the etu counters (the
0.5 etu, 1 etu and 1.5 etu counters mentioned earlier in this document), we
stand very little chance of getting this command to the FPGA in time, before
ME/ID starts transmitting its next command to the SIM using the new etu
definition.

Designs that incorporate a local CPU core immediately adjacent to the ISO 7816-3
receiver block, such as original Osmocom SIMtrace in which the local CPU core
and the ISO 7816-3 receiver sit in the same AT91SAMx chip, don't suffer from
this problem: with a local (dedicated, embedded) CPU so close, the firmware can
react and intervene in time.  However, in the case of our SIMtrace3, the nearest
CPU is the host computer separated by UART and USB links - not closely coupled
enough to provide the degree of real-time response that is needed here.  Someone
could say that we should stick a soft CPU core with firmware into our FPGA - but
we've implemented a different solution: we have a specialized PPS catcher state
machine instead.  This gateware FSM follows the spec-defined structure of ATR,
PPS request and PPS response, and locates the two key items of interest to us:

* The PPS1 byte in the card's PPS response, which we check for a supported speed
  enhancement mode (the upper 6 bits need to match 0x94) and from which we
  extract the two lsbs selecting among D=8/16/32/64;

* The PCK byte that concludes the card's PPS response - the point where we throw
  the switch to sniffing with the new F/D ratio.