The Marvel of SIM Cards

TL;DR: SIM cards are a marvel of software engineering

Christian Hujer, CEO / CTO at Nelkinda Software Craft Pvt Ltd
First Published:
by NNelkinda Software Craft Private Limited
Last Modified:
by Christian Hujer
Approximate reading time:
Figure -1: SIM Card by Telefónica O2 Europe

SIM Cards are fantastic little beasts and an often overlooked and underestimated marvel of software engineering. How so? Let's look at their hardware, and then let's look at what software they're running.

1 SIM Card Hardware

Let's look at two examples from Samsung, the Samsung S3FV9RRP and the Samsung S3K250AF. Their capabilities look like a mix between an 8-Bit home computer from the 1980s regarding RAM and a 1990s PC regarding CPU.

Clock70 MHz40 MHz
RAM53 KiB11 KiB
Flash2048 KiB252 KiB
Table 1-1: Specifications of some SIM card controllers

2 SIM Card Software

Let's assume the SIM card is running the Sm@rtSIM operating system from Giesecke & Devrient or BengalOS from Nelkinda. We can then assume that it should have the following features:

Putting all of this together to fit in chips like above is really a marvel of software engineering. It requires frugal use of memory, clever use of the CPU, and a lot of ingenuity to make it all work. Remember, these things have to work with 11-53 KiB of RAM. This goes far beyond just correctness.

3 Required Engineering Capabilities

To develop the software for a SIM card, certain engineering capabilities need to be present.

Unlike most other software, the firmware of a SIM card cannot be updated. It is possible to update the applications and on some advanced SIMs even the firmware, but this is not the norm. Therefore, the firmware must be correct. In SIM card development, the ratio of test code to production code is typically 10:1. Functional correctness is paramount. The recall of a defect SIM would typically not be a single unit, but an entire batch of hundreds of thousands or even millions of units. The margin per unit is very small, so the cost of a recall is very high. A recall has to be prevented at all costs. This is additionally hardened by the interoperability requirements. A SIM card has to work in a wide variety of devices, and the devices have to work with a wide variety of SIM cards.
As seen above, the SIM card has a very limited amount of memory. Therefore, the code must be as small as possible. Code reuse across the entire OS is paramount to avoid unnecessary duplication of code as much as possible. For this, while the engineers are highly specialized in their domains like memory management, Java Card VM, cryptography, and so on, they must also be able to work together.
The CPU of a SIM card is not very powerful and also must draw as little power as possible. Additionally, the intended use of a modern SIM card might include payment. For payment, stringent tests, evaluations, and certifications from the payment card industry are required. For example, Mastercard requires a maximum response time of 200 ms for a contactless payment transaction.
It goes almost without saying that the SIM card must be secure. The SIM card is a trusted device, and it must not be possible to compromise it. The SIM card must be tamper-proof. It must be impossible to extract the private keys from the SIM card even if the SIM card is physically destroyed and the chip is extracted and the chip is analyzed and the chip is reverse engineered and the reverse engineered chip is analyzed. It must be impossible to get the SIM card to wrongly authenticate itself to a network. Defenses in software have to deal with scenarios like light attacks to flip bits for critical operations combined with power curve analysis to extract information.

Those qualities can only be achieved by programming close to the metal. Cryptographic algorithms are typically implemented in Assembler and not only proven functionally correct but also hardened against attacks, including but not limited to timing and power curve analysis attacks. Most of the firmware is written in C, with some performance and security critical parts written in Assembler. High-level aspects are written in Java (Java Card).

For the development, a lot of tools for quality assurance are used, like static code analysis, code coverage, and fuzzing. Code is unit tested, integration tested, and system tested. Furthermore, code is also stress tested, performance tested, and security tested. As already mentioned, the ratio of test code to production code in this domain is typically 10:1.