Smart Card Internals and Vulnerabilities
Consider the problem of designing a secure computer system for a smart card. This system must include
If the flash memory is larger than the RAM, it must be possible to flash erase blocks smaller than the RAM. If this were not the case, it would be impossible to read a block from flash memory into RAM, alter some of the content of that block, flash erase that block, and restore its contents, as altered. As a consequence, if the RAM is 64 bytes, we might use 32-byte blocks of flash memory. A 4K byte flash memory would then be viewed as composed of 128 blocks of 32 bytes each. (Some of the smallest flash memory chips currently on the market actually do use 32-byte blocks).
To minimize the complexity of the system, we can make the CPU execute code directly from the flash memory, so when the chip is reset, the program counter is set to read the first instruction from byte zero of block zero of the flash memory. This eliminates the need for a special program memory. Consider, for example, using a 2-byte program counter, with the least significant byte holding the byte-in-block field and the most significant byte holding the block number. So what that a block is less than 256 bytes! If a block is just 32 bytes, we only use the least significant 5 bits of the least significant byte of the program counter, and we make it so incrementing the program counter from 001F16 gives 010016 instead of 002016.
Very small processors typically use a Harvard architecture, that is, they use entirely different memories for code and data. Code addresses come from the program counter, while load and store instructions only address RAM. Typical very small processors such as we are interested in use memory-mapped I/O, so all device interface registers appear, to the program, as special RAM addresses. If, for example, the RAM is only 64 bytes, with a 6-bit RAM address field in memory-reference instructions, we might sacrifice the first two RAM addresses for access to the program counter, so storing bytes in those addresses is equivalent to a jump.
A flash memory integrated with a CPU chip will typically have a block address register, a byte address register, a data register, and a control register. These registers would all appear as special RAM addresses. The block address register selects the block to be flash erased and it holds the most significant part of the address for read and write operations. The byte address register selects one byte in the current block for reading and writing. Reading a byte from the data register reads the byte addressed by the block and byte address registers. Writing a byte to the data register would typically OR that byte with whatever was already stored in the addressed byte. Normally, blocks are erased before written, and ORing with zero is equivalent to a normal store operation. The control register would be used to perform flash erase cycles. Flash erases are slow, and the control register may also serve as a timer to indicate when the erase is done and it is safe to change the block address register and read or write that block again.
The typical serial port interface for a smart card would involve a one-byte data register, plus a status and control register, also appearing as RAM addresses. The data register is shifted one place for each clock cycle. In read mode, data is shifted from the data line of the serial interface into the data register. In write mode, data is shifted from the data register to the data line of the serial interface. A ready bit is set after each 8 shifts to indicate that a byte is ready to be read by the software from the data register (in read mode) or written to the data register (in write mode).
The mechanisms described above allow the following behavior when the machine is reset in programming mode:
Each time the serial port read register is filled with 8 data bits from the serial port while in programming mode, the contents of the data register are directly written to the flash memory data register, which is to say, written to flash memory, and the flash memory byte address register is incremented. The net result, as seen by the outside world, is to shift data from the serial port directly into the flash memory. Note that all of this requires very little added hardware.
This model only allows block zero of the flash memory to be written from the outside world in programming mode. How do you write the rest of the flash memory from the outside world?
The answer is simple. Write a small loader in block zero. Then reset the chip in normal mode, not programming mode, so that this loader runs. Then, shift the appropriate object code (in whatever very simple format this loader understands) into the serial port so that this loader can load it into any place in the flash memory.
Having done this, how do you get rid of the loader, so that resetting the smart card will run your applicaton, not the loader?
There are two solutions to this. One is to use the loader to patch the loader -- that is, to change itself, as its last act. Consider, for example, the fact that the loader can store bytes anywhere in the flash memory. If it stores a byte over itself, our definition of the flash memory interface says that that byte is ORed with whatever was already there.If the loader begins with a jump instruction that simply jumps to the next consecutive instruction (for example, the instruction at address zero jumps to the instruction at address three), this can be changed to a jump to any address ending in binary 11.
There are several other solutions to this problem.
Suppose that an attacker is given a smart card that is designed according to the above specifications. How can the attacker read out the contents of the flash memory?
The answer is simple. Write a program to read the contents of flash memory, such that the attack program fits in one block of the flash memory. Then, use program mode to write this program into block zero of the flash memory. At this point, restarting the chip in normal mode will run the attack program, which will extract the contents of the flash memory and write it out on the serial port.
Note that this leaves block zero protected! Our attempt to extract the contents of the flash memory overwrote block zero. Therefore, a secure applicaton for our hypothetical smart-card processor must store all of its security critical data in block zero. So, the final configuration of a loaded application must include just two things in block zero, a jump to the start of the real application, starting at byte zero of block zero, and whatever secrets the system must hide from the outside world.
This leaves a programming challenge: How do you replace the loader with these secrets?
Loading flash memory or EEPROM over a serial port is subject to several kinds of errors, so it is normal to want to verify the contents of memory after loading. Unfortunately, the operation a programmer wants to do in order to verify the contents of the flash memory is exactly the same operation that an attacker wants to do in order to read out what he should not be able to read.
How can the application be written so that it will detect that it has been mis-loaded and make it obvious that there is a problem? One idea is to have the application begin by scanning itself and computing a checksum, then comparing this checksum with the expected value. If the result is incorrect, the application should report this fact.
How should the application report failure? What if the error is in the startup code that checks the checksum?
One alternative to the above design is to have a reset in program mode flash erase the entire flash memory. This clearly prevents any attack based on loading a memory dump program into part of the chip. On the other hand, it interferes with several solutions for full use of the chip.
Yet another addition is to have the auto-increment of the flash memory byte address register automatically increment the block address register whenever it rolls over to zero from the maximum byte number in a block. This allows programming mode to load the entire flash memory, assuming that the load operation begins with a flash erase of the entire memory.
On larger systems, such as those found in a thumb drive, the processor and flash memory are on separate chips. In that case, it is difficult to force the automatic erasure of any of the primary flash memory. Typical small processors in such applications include their own EEPROM or flash memory for code. As a result, attacks on the contents of the primary flash memory by either reprogramming the processor or physically removing the processor and replacing it with a new one become quite straightforward.
What if someone manages to physically disassemble the smart card in order to extract the chip from the enclosing plastic. The card is organic, and it may be possible to dissolve it with solvents that do not attack silicon, aluminum and glass -- the materials of the chip itself. An initial attack with abrasives to grind away the surface of the card would be sensible to reduce the amount of plastic that needs to be removed by solvents. Attacks by oxygen plasma in a partial vacuum will destroy many materials, but may leave the surface of the integrated circuit chip undamaged, since the surface is mostly aluminum and silicon oxide.
Once a chip is extracted from its package, all kinds of attacks become practical. The contents of EEPROM and flash memory can be read out, in theory, using an electron microscope. Scanning tunneling microscopes may also be able to study the charge distribution on the chip, again allowing direct reading of the contents of the flash memory.
With direct access to the surface of the chip, it may be possible to use a microscope and appropriate very sharp needles to make electrical contact with points on the chip other than the official external connections. (Integrated circuts are tested in the factory before they are packaged using precisely such a setup, sometimes described as a bed of nails.)
It is highly unlikely that an attacker intent on credit card theft would have access to these tools, and few credit cards have credit limits high enough to warrant the cost of using such tools. On the other hand, if the same smart card technology were used to protect Microsoft's corporate assets or the national security secrets of the United States, it is clear that such tools would be easily justified by the potential return on investment to the attacker. This poses the ultimate limit on such devices.
For an example very small processor that could potentially have applications in places like smart cards, take a look at the PIC family of processors from Microchip corp. The PIC12F629 is an example, with only 128 bytes of data memory. The PIC line is very diverse.
Sun Microsystems is pushing Javacards where, of course, Java is the featured programming language.