The main loop and the initialization of the hardware and operating system
After the smart card is reset, the program counter is loaded with the address of the reset vector, and the processor then starts to execute the first program code. The hardware is tested right away to see if it is in good working order, just as with PCs. This consists of a RAM test to start with, followed by the calculation of several checksums for the contents of the ROM and EEPROM. If an error occurs here, the smart card attempts to send a special error ATR, following which it does nothing except to wait in an endless loop for the next reset. The success of the attempt to send the error ATR depends primarily on the nature of the error that has occurred. If the error is serious and affects the RAM or the program code of the transmission routine, only a garbled ATR or no ATR at all can be sent. After the chip hardware has been tested and initialized, the initialization of the operating system starts. The important aspects of this are setting the data transmission parameters for the T = 1 protocol, automatically selecting the MF and establishing the security conditions for file accesses. If the MF cannot be found, this is a serious error, and Small-OS then terminates all further actions after sending an error ATR.

The I/O manager
The entire process of transferring data from and to the terminal is handled by the I/O manager. Two hardware-independent program routines in the core of the operating system called Kernel IO SendByte and Kernel IO ReceiveByte form the basis for transmitting and receiving messages. All other parts of the I/O program code are independent of the target hardware for Small-OS. The ATR and the T = 1 transmission protocol are completely executed in the I/O manager for both successful and unsuccessful instruction processing. A dedicated state machine had to be developed for this, primarily to handle the relatively complicated procedures of the T = 1 protocol. The ISO/IEC 7816-3 Amd. 1 standard describes the reactions of the I/O manager in case of both success and failure by means of many examples. With manually optimized assembler code, a good I/O manager requires at least one kilobyte of memory, which is usually located in ROM. Real I/O managers preferably use only the RAM for the I/O buffer, since write accesses to the RAM take place at the full speed of the CPU. However, there are now many smart card operating systems whose transmit and receive buffers are larger than the available amount of RAM. In such cases, a certain part of the EEPROM is used as an extension to the data transmission buffer when the amount of data exceeds a certain threshold. This avoids any restrictions on the size of the I/O buffer, but the price for this is a considerably reduced data transmission rate, due to the time required to write to the EEPROM. In addition, with this sort of extended I/O buffer, there is a danger that the buffer could reach the end of its useful life in a relatively short time, due to frequent write accesses to the EEPROM. In spite of these limitations, this is the only technically feasible means to make the data transmission buffer larger than the amount of available RAM.

Operating system kernel
All of the routines that belong to the core of the operating system are collected together in the OS kernel. Most of these routines are either hardware-dependent or rather time-critical, and must therefore be adapted when the program is ported to a different hardware platform. The functions provided by these routines are in each case described by their names. Some of these subroutines can influence aspects of the system that are of concern to its security. For example, the execution time of a subroutine such as Kernel CompareByteString should not vary depending on the result of the comparison, since any such variations could be used as the basis for determining the internal results of PIN computations by measuring elapsed times. Nowadays, this type of attack has been eliminated by incrementing the retry counter before each PIN comparison as a precautionary measure, but not long ago this was a very promising way to attack a PIN.

Command interpreter
The Small-OS command interpreter is constructed in a relatively simple manner. It works on the principle of a dispatcher that, based on the class and instruction bytes, calls a routine that processes the recognized command. This implementation uses little memory and has the additional important advantage that it is relatively easy to integrate new commands into the operating system. This can be done by just adding a few lines of code to the command interpreter. These identify the new command and the associated subroutine call. With suitable code in place, the new command will be recognized and executed as necessary. The structures of command interpreters that are commonly used in practice, however, are far more complicated. This is partly because they must run in unalterable ROM, but also because it must be possible to download program code into the EEPROM when the operating system is completed. This downloaded code must then be recognized and called when the program runs. The principle that is used for this is a jump table located in the EEPROM, which can be extended as necessary when the card is completed. Fixed polling of a particular class byte, as used in the Small-OS command interpreter, only makes sense in operating systems that do not support either secure messaging or logical channels, and which also support only a single command class conforming to the ISO/IEC 7816-4 standard. In all other cases, the class byte is used to identify previously defined options, so it need not be the same for all commands.

The return code manager and the file manager
The return code manager uses a passed-in value to look up the return code in a table, and then adds it to the end of any data block in the transmit buffer. A dedicated manager is used for this, for two main reasons. First, it is better programming style to have all return codes in one central location. For example, this makes it possible to substitute another return code for a particular return code, easily and in one central place, in case of a software error. This can sometimes be essential. Second, using a return code manager saves precious memory. It is easy to calculate that storing each return code only once in a common table takes up less memory than repeating it everywhere it is needed. In real smart card operating systems, all file accesses take place via a central file manager, for reasons of security. Frequently, the file manager also computes the checksum of the file header when the file is accessed. In a concession to simplicity, Small-OS accesses the multidimensional variables of the file tree directly when a command is processed, without separating levels or first computing a checksum. The only check that it makes for all commands is to test whether access to the file is allowed. With a complete file manager, read and write accesses to files would take place in a similar manner.

The basic structure of the program code for smart card commands
The basic functions of smart card commands are described in Chapter 7 (‘Smart Card Commands’). The command processing program code listings shown here are always divided into three sections, separated by thin lines. Any associated subroutines are separated from the main body of the code (and from each other) by thick lines. The first functional block of the main body of the code investigates the command header (which means the CLS, INS, P1 and P2) as much as is possible at the time. This respects the well-known software design principle of testing the consistency and range of the data as early as possible. Following this, the basic prerequisites for the execution of the command are checked. For example, monitoring the file structure or the access conditions occurs in this section. If all these checks are completed without any rejections, the actual command execution then takes place. This usually involves only a very small amount of code. Finally, the return code for successful execution of the command is set, and a jump to the I/O manager is made (via the command interpreter and the return code manager). The I/O manager sends the result of the command processing and then waits for a new command. If an error is detected in any of the tests in the pseudocode, the relevant return code is immediately set and program execution branches via the central exit of the subroutine in question.

The command set
All seven of the commands listed below correspond to the ISO/IEC 7816-4 standard in their structure and coding. However, given the freedom of implementation that a standard naturally allows, it is necessary to specify the details of each command in addition to referring to the standard. The specifications of all the commands of Small-OS are thus described in the following subsections. The specifications have been kept relatively short and formal, so they represent only the essential elements.

SELECT FILE
The SELECT FILE command is used to select a file (MF, DF or EF). This normally requires a 2-byte FID (file identifier). Profile N of the ISO/IEC 7816-4 standard also allows DFs to be selected using a DF name, which can contain an AID (application identifier). In Small-OS, the AID can be passed only in its complete form. In the special case of the MF, no FID is required to make the selection, since a suitable command option can be used instead. The MF is also automatically selected after the smart card is reset, and it can be selected from every other directory during a session. SELECT FILE falls under Case 1 when theMFis directly selected, which means that neither the command APDU nor the response APDU contains a data portion. When the selection is made using a FID or a DF name, SELECT FILE falls under Case 3. This means that a data portion is present in the command APDU but not in the response APDU. After a reset, the security state of the MF is reset to the ground state (0). Selecting a DF does not affect the security state of the MF, but the security state of the DF is automatically set to the ground state (0) when it is selected. When a linear fixed EF is selected, the record pointer is set to ‘invalid’. The search order, which means whether the operating system should first search for a DF or an EF when selection is made using a FID, is not specified in the standard. However, this is of considerable significance in certain cases. For example, if the MF is currently selected and there is a DF as well as an EF with the same FID, it may not be possible to select the EF, depending on the search routine. Consequently, in implementing the search routine of Small-OS, we have chosen to always search the list of EFs first, followed by the list of DFs. In case of a conflict, the DF can always be selected using its DF name, so using the FID is not absolutely necessary in such cases.

READ BINARY
The READ BINARY command can be used to read data from a transparent EF, starting from a location specified by a 15-bit offset parameter passed by the command. READ BINARY falls under Case 2, which means that there is no data part in the command APDU, but there is a data part in the response APDU. All length specifications must be an integral number of bytes. The maximum length of the data to be read is limited to the maximum data volume of a transparent EF, which is 255 bytes for Small-OS. If a value of zero is given for the length, all data from the given offset location to the end of the file are read. Profile N of the ISO/IEC 7816-4 standard does not provide for the implicit selection of EFs by means of short file identifiers, so this option is not implemented here. Before data can be read from an EF using this command, the associated access conditions must be satisfied. Otherwise, the command will be rejected with an appropriate error report.

UPDATE BINARY
The UPDATE BINARY command can be used to read data from a transparent EF, starting from a location specified by a 15-bit offset parameter passed by the command. UPDATE BINARY falls under Case 3, which means that there is a data part in the command APDU, but there is no data part in the response APDU. All length specifications must be an integral number of bytes. The maximum length of the data to be read is limited to the maximum data volume of a transparent EF, which is 255 bytes for Small-OS. If a value of zero is given for the length, all data from the given offset location to the end of the file are read. Profile N of the ISO/IEC 7816-4 standard does not provide for the implicit selection of EFs by means of short file identifiers, so this option is not implemented here. Before data can be written to an EF using this command, the associated access conditions must be satisfied. Otherwise, the command will be rejected with a suitable error report.

READ RECORD
The READ RECORD command can be used to read a record from a linear fixed EF. The maximum amount of data to be read is limited to the maximum record length of 255 bytes. The length specification must either match the length of the addressed record or be set to zero. With a length of zero, the entire record is automatically read. All length specifications must be an integer number of bytes. Profile N of the ISO/IEC 7816-4 standard does not provide for the implicit selection of EFs by means of short file identifiers, so this option is not implemented here. READ RECORD falls under Case 2, which means that there is no data part in the command APDU, but there is a data part in the response APDU. A record in a linear fixed EF can be addressed in three different ways. The number of the desired record can be passed directly with the READ RECORD command. If this record is present in the file, its contents are returned in the response; otherwise the answer contains a suitable error report. This type of access does not affect the record pointer, which can only be modified with the command options ‘first’, ‘last’, ‘next’ and ‘previous’. The record pointer is set to ‘invalid’ immediately after an EF is newly selected. If the option ‘next’ or ‘previous’ is selected when the record pointer is invalid, the record pointer is automatically set to the first or last record of the file, respectively. This makes it possible to (for example) read the records in a file by first selecting the EF and then sending a series of READ RECORD commands with
the ‘next’ option, without having to use any other commands. The third type of access is to use the ‘current’ option. In this case the record that is currently indicated by the current record pointer is read. If the record pointer is invalid, the command is aborted with an appropriate error report. Before data can be read from an EF using this command, the associated access conditions must be satisfied. Otherwise, the command will be rejected with a suitable error report. The record returned in the response when the command is successfully executed is not TLV coded, although this is optionally allowed by the ISO/IEC 7816-4 standard.

UPDATE RECORD
The UPDATE RECORD command can be used to write a record to a linear fixed EF. The data passed by the command are not allowed to be TLV coded, although this is allowed as an option by the ISO/IEC 7816-4 standard. The maximum amount of data to be written is limited to the maximum record length of 255 bytes. The length specification must exactly match the length of the addressed record, and all length specifications must be an integer number of bytes. Profile N of the ISO/IEC 7816-4 standard does not provide for the implicit selection of EFs by means of short file identifiers, so this option is not implemented here. READ RECORD falls under Case 3, which means that there is a data part in the command APDU, but there is no data part in the response APDU. A record in a linear fixed EF can be addressed in three different ways. The number of the desired record can be passed directly with the UPDATE RECORD command. If this record is present in the file, its contents are returned in the response; otherwise, the answer contains a suitable error report. This type of access does not affect the record pointer, which can only be modified with the command options ‘first’, ‘last’, ‘next’ and ‘previous’. The record pointer is set to ‘invalid’ immediately after an EF is newly selected. If the option ‘next’ or ‘previous’ is selected when the record pointer is invalid, the record pointer is automatically set to the first or last record of the file, respectively. This makes it possible to (for example) write all the records in a file by first selecting the EF and then sending a series of UPDATE RECORD commands with the ‘next’ option, without having to use any other commands. The third type of access is to use the ‘current’ option. In this case, the record that is currently indicated by the current record pointer is written. If the record pointer is invalid, the command is aborted with an appropriate error report. Before data can be written to an EF using this command, the associated access conditions must be satisfied. Otherwise, the command will be rejected with a suitable error report.

VERIFY
The VERIFY command is used to compare a secret item that has been passed over to the smart card, such as a PIN, to a stored reference value. The length of the PIN must be between one and eight bytes. The operating system does perform any sort of testing of the coding of the data string that is passed in. This means that, for example, a 4-digit PIN (e.g.”1234”) could be coded as two BCD bytes (’12′||’34′) or as four ASCII bytes [(''1''||''2''||''3''||''4'') = ('31' ||'32'||'33'||'34')]. The VERIFY command falls under Class 3, which means that there is a data part in the command APDU but not in the response APDU. At most two PINs (PIN number 1 and PIN number 2) can be addressed. They can be located in either the EF Key of the MF or the EF Key of the currently selected DF. A PIN that is stored in the EF Key of the MF is used as a common PIN for all applications in the smart card. If a PIN is stored in the EF Key of a DF, it can be used only for the application associated with that DF. Such a PIN is thus an application-specific PIN. Every PIN has a retry counter that is reset to zero when a positive comparison result is obtained and incremented by one when a negative result is obtained. If the state of the retry counter is not zero, the number of PIN attempts still allowed is returned encoded in SW2. If the retry counter reaches its maximum value, this is indicated by a separate return code. Since Small-OS does not have any command to reset the retry counter, whenever a retry counter is standing at its maximum value, there is absolutely no possibility of ever making any further PIN comparisons. Depending on the application, this might mean that the smart card could no longer be used. The PIN located in the EF Key cannot be altered by the user, although this possibility is commonly found in many smart card applications. A specific command would be needed for this (CHANGE REFERENCE DATA as per ISO/IEC 7816-8), but this is not provided in the ISO/IEC 7816-4 standard. The implementation presented here has a small peculiarity due to simplification. The retry counter is located in EEPROM, as you know. However, EEPROM write accesses need not always be successful, due to the possibility of a write error. Consequently, it is necessary to test the data after each write operation to verify that they have been correctly written. If the result of the test is negative, a suitable return code is set. The retry counter is altered so often in the VERIFY command that no such test has been included in the pseudocode, since the basic relationships of the code would no longer be clear if it were present. You should bear this in mind when examining the code. The VERIFY command is naturally predestined to be used for attacks on the PIN. The implementation has been designed to make it impossible to base an attack on an analysis of timing behavior or current consumption. The retry counter is always incremented before the received PIN is compared to the reference PIN stored in the EF Key. This ensures that cutting off the power supply to the card immediately following the PIN comparison does not cause the retry counter to be incremented, which would allow an attacker an unlimited number of PIN comparisons. The actual EEPROM writing process for incrementing the retry counter is by no means as trivial as one might initially imagine. The coding of the retry counter must be constructed such that breaking off the process during the write operation, or during the erase operation that may be necessary before the write operation, cannot result in the retry counter being reset to its initial zero value. The code internal to the operating system must therefore be designed with reference to the minimum-energy state of the EEPROM, which is also known as its secure state. This means that with an EEPROM whose secure state is zero, for example, the initial value of the retry counter may not be coded as zero. If it were, the retry counter could be reset to zero by skillfully switching off the supply voltage during the EEPROM write operation. It would then be possible to determine the PIN within a relatively short time by trial and error, since the retry counter would not be able to fulfill its role as a counter for unsuccessful PIN comparisons. Ideally, the technique of using atomic operations23 can also be used for writing the retry counter.

INTERNAL AUTHENTICATE
The INTERNAL AUTHENTICATE command is used to authenticate the smart card via a challenge–response procedure. An 8-byte random number is sent to the smart card, which encrypts it using the DES algorithm. The number of the key to be used must be given in parameter P2, which must indicate whether the key to be used is located in the EF Key file of the MF or the currently selected DF. INTERNAL AUTHENTICATE falls under Case 4, which means that a data part is present in both the command APDU and the response APDU. The ISO/IEC 7816-4 standard only specifies a few parameters for the authentication commands. The cryptographic algorithm, for example, is not specified. In Small-OS, the DES algorithm has been chosen as the cryptographic algorithm. As an extension to Profile N of the ISO/IEC 7816-4 standard, a 5-byte key number is passed with the command. In Small-OS, INTERNALAUTHENTICATE can in principle be used to encrypt eight bytes of plaintext into eight bytes of ciphertext using a selectable key. A smart card with Small-OS would thus fall under strict export control in almost all countries, so that it would take several weeks or even months to obtain an export permit for the card. Consequently, INTERNAL AUTHENTICATE is implemented in many real smart cards such that it is not possible to directly encrypt data. This avoids the export restrictions. The ability to directly encrypt a plaintext block into a ciphertext block is equally risky from a cryptographic perspective, since it could be used to generate plaintext–ciphertext pairs for brute-force attacks. In addition, this implementation would be very susceptible to differential fault analysis.24 The simplest form of attack to implement would be a timing attack25 on the computation of the DES, which thus must be noise-free. Otherwise, the key could be determined by measuring the processing time for the computation. For all of these reasons, the starting value is most commonly extended in practice by appending a random number generated inside the smart card and the card’s own unique number. The resulting number is then encrypted, and the ciphertext is sent back to the terminal along with the data used to extend the original number. This means that this command can no longer be used to encrypt data (which solves the export problem). In addition, the fact that a different value is encrypted each time provides the basis for protection against differential fault analysis (DFA) and differential performance analysis (DPA).26 All of these measures show relatively dramatically that both the specification and the implementation of even an ostensibly simple command, such as INTERNAL AUTHENTICATE, requires considerable knowledge and experience to protect the keys of a smart card application against attack.

A simple application example
The following simple smart card application illustrates the construction and contents of the variables in the EEPROMwith the Small-OS operating system. The function of this application can be described in a few words. It allows the creation of a file that is 50 bytes long, whose contents can always be read, and which can be overwritten after the PIN value ‘1234’ has been successfully tested. The reference number of the PIN is 1, and a maximum of three unsuccessful attempts is allowed for the PIN input. The EF containing the file is located underneath its own DF. All file names (DF names and FIDs) can be freely chosen. Table 5.57 shows how the required capabilities can be implemented by putting appropriate values in the structures used for the file tree. In order to realize the required access conditions, the state machine shown in Figure 5.66 is implemented. After a reset, Small-OS automatically sets the security state of the DF to zero. In this state, the EF containing the data can be read but not written. State 1 is necessary for writing to the file. If a VERIFY command is successfully executed with the correct PIN, the DF is set to security state 1 (. . . ResultState.OK ), and the file can be written. If the PIN test is not successful, the DF is set to security state 0 (. . . .ResultState.NOK ). The commands READ BINARY and UPDATE BINARY are used to read and write data from and to the file, respectively. The entire file can be read or written, or only part of it. The only decisive factor here is that the security state achieved in the DF must correspond the desired type of access. This example quite clearly shows two limitations of Small-OS, which arise only from the desire to keep the extent of the pseudocode within reasonable limits. Once security state 1 has been reached, the file can no longer be read, since reading is only allowed in security state 0. This could be remedied by integrating the option of a ‘greater than or equal’ comparison into Small-OS, in addition to the ‘equal’ comparison. Another possible solution would be to not limit the file access conditions to only one comparison test per operation (reading or writing), but instead to allow several tests for each operation. In this case, reading the file could be allowed in state 0 as well as in state 1, even if only ‘equal’ comparisons are possible. Multiple access conditions for an access operation can be integrated into Small-OS just as easily as testing for greater than or equal. However, the pseudocode would be a bit more extensive, as would be the amount of program code for an actual implementation. With real smart card operating systems, such extensions can easily cause the amount of code to exceed the amount of memory available in the microcontroller (ROM or EEPROM). In practice, these strict memory limitations often mean that certain useful functions cannot be implemented. In the application just described, state 1 cannot be exited once it has been achieved by means of a successful PIN verification, which means that the file can no longer be read, due to the access conditions. State 0 can be exited either via an unsuccessful PIN verification or by resetting the smart card. In terms of a ‘clean’ application design, this is a rather unfortunate solution. However, the problem can be remedied using a simple trick to return to the initial state. As you know, selecting a DF causes the security state of the DF in question to be reset. Consequently, the DF can be selected one more time if necessary, which automatically changes the security state from 1 back to 0. Until recently, applications such as this were coded manually in assembler, in the form shown here. Nowadays, there are application generators for almost all commercially available smart card operating systems. These programs run on PCs and have graphical user interfaces for creating files and access conditions. A similar process also takes place in the smart card simulator when a new application or file is created. Once the necessary files for the application have been created, they can be loaded into a smart card using the application generator. After this, the first trials with the new application can be carried out.

This sample application can also be profitably used to illustrate some interesting types of attacks. Although these are theoretical in nature, since they require sophisticated technical equipment, they still illustrate some noteworthy principles. The prerequisite for these attacks is the ability to alter specific contents of the EEPROM, which in technical terms amounts to the ability to manipulate the stored charges of individual EEPROMcells. The necessary techniques are discussed in more detail in Chapter 8. Here we only want to look at the consequences of this manipulation. If it were possible to deliberately alter the content of the file tree pointer that normally indicates the data of the EF, it could be changed to indicate the data content of the EF Key. The EF is always readable in state 0, and in this case, READ BINARY would read the PIN instead of the actual 50 bytes in the EF. Of course, the exact address of the data part of the EF Key must be known for this attack to be used, and a lot of insider knowledge is required to obtain this information. It would be simpler if the variable DF[2].EF[1].TransparentDataSize could be altered. If the value of this variable is increased to a large value, for example, then READ BINARY can be used to read an amount of data extending past the end of the file, according to the new value of the variable. If the EF Key is located in memory following EF 1, both the EF Key header and the actual file content could be read straightaway. Manipulation of the EEPROM could also be used to repeatedly reset the PIN retry counter. The PIN could then be determined within an acceptable amount of time by trial and error. An even simpler attack would be to set the PIN itself to a known value. These examples very clearly show that the security of a smart card would completely collapse if it were possible to manipulate the EEPROM. It would make no difference if the contents of the EEPROM could not be read, but could only be overwritten. In any case, the PIN and the keys of the card could be determined. The only thing that would have to be known is the exact memory addresses where the manipulations should be carried out. Checksums for the header contents, if present, would only make the necessary modifications to the EEPROM more complicated, but they ultimately could not prevent them. Of course, it is presently not technically possible to change individual bits at any desired locations in the EEPROM. The approaches just described thus represent theoretically interesting forms of attack rather than actual dangers. However, if this sort of manipulation of the EEPROMwere to become possible in the future, these examples clearly and unambiguously show the potential dangers that would arise.