As is well known, design errors first manifest themselves in the implementation stage, where they result in costs that are several times greater than those for a better design with fewer errors. However, errors are a fact of life in all software projects. In order to minimize such errors, it is recommended to observe several principles during the design and implementation of a smart card operating system. Due to its functional specification, a smart card operating system is a secure operating system designed to manage information and above all keep information confidential. In addition, it is normally not possible to make any changes at all to the software once it is in use. The first principle follows directly from these considerations. A smart card operating system must be extremely reliable, which means it must have an extremely small number of errors. Total elimination of errors is in reality never achievable, since even the smallest smart card operating systems are too large for all of the capabilities of their internal processes to be completely tested. However, strict modular design makes a decisive contribution to the discovery and elimination of any errors that may be present at the implementation stage. This modularity, which strongly increases the reliability of the operating system, need not necessarily result in large increase in the volume of program code. An additional benefit of a modular design is that any system crashes that may occur generally do not affect the system’s security as strongly as with highly optimized program code occupying less memory. With a modular design, the consequences of any errors remain localized, and the operating system as a whole is more robust and more stable.

The fact that the software most often must be implemented in assembler makes it more prone to errors. A design based on individual, fully testable modules strongly contributes to detecting programming errors in a timely manner and limiting the scope of their effects, due to use of defined interfaces. The layered operating system architecture shown in Figure 5.1 is a consequence of this modular approach. The increased amount of planning and programming effort that this requires is offset, at least financially, by the fact that testing and verification are significantly easier. For this reason, almost all current operating systems have an architecture essentially equivalent to the one described here. The method usually used to design an operating system is based on the module–interface concept. In the design process, the tasks of the operating system and the application are broken down as much as possible into functions, and these functions are then incorporated into modules. Once the interfaces to the modules have been exactly defined, the individual modules can be programmed, possibly by several persons. In the ideal case, the first version of the implementation is platform-independent, which means that it does not yet depend on the characteristics of the microcontroller that is used. After this version has been completely tested, the necessary adaptations to the microcontroller can be made. Since the amount of program code for a smart card operating system is relatively small, this very pragmatic approach can be used without any major problems. Its advantages, which are the relatively small amount of planning that is needed and the possibility of dividing the programming tasks among several persons, along with reusability of the program code, yield the maximum benefits here. The drawbacks of this approach, which are the difficulty of demonstrating the correctness of the system and the fact that changes to the system may strongly affect many modules, must be balanced against its benefits.

The development of software for smart card operating systems is moving away from programming entirely in assembler. Many recent projects have been executed from the very beginning in the high-level language C, which is relatively close to the hardware. However, the kernel of the operating system is still based on machine-dependent assembler routines, with all higher level modules, such as the file manager, the state machine and the command interpreter, being programmed in C. This significantly reduces the development time and makes the code more portable and more reusable. Above all, using a high-level language markedly improves the testability of the software. The improved, more easily understood program structure provided by a high-level language also yields a distinctly lower error rate. Unfortunately, the program code generated by a C compiler, even if it is highly optimized, occupies 20 to 40 % more space in ROM than equivalent code in assembler for the same functionality. In addition, the speed of a C implementation is marginally lower than an assembler implementation. However, this is only critical for cryptographic algorithms and the data transmission protocol, since the other parts of the smart card operating system software normally do not contain time-critical processes. The greatest problem with C programming is not necessarily the extra memory space needed in the ROM or reduced execution speed, but the amount of RAM that is used. This type of memory is extremely limited in smart cards, and it has the further disadvantage that it takes up the most space per bit on the chip. This is the main reason why high-level languages have up to now been used rather sparingly in programming smart card operating systems.

Since smart cards are used in application areas in which security is a very important factor, the card issuer and/or application supplier must have considerable trust in the integrity of producer of the operating system. The latter has every opportunity to take unfair advantage of the entire system by means of deliberately introduced security gaps. For example, consider an electronic purse in a smart card whose load command has been manipulated such that under certain conditions the purse can be reloaded without authorization. Such scenarios are the reason why only a few operating system producers have become established up to now. The risk that an ostensibly secure operating system contains a Trojan horse is significantly greater if it comes from a small, unknown vendor than if it comes from one of the well-known firms in the field. Nevertheless, there has recently been an increasing effort to evaluate smart card operating systems according to the ITSEC or its successor, Common Criteria, in order to achieve a higher level of comprehensibility and security with regard to such scenarios.1 This occurs either on the initiative of the producer or in response to the demands of major card issuers, whose objective with such an evaluation is to achieve an increased level of confidence that there are no significant errors in the program code. Checking for deliberately introduced Trojan horses during an evaluation would probably be of limited use, since there is practically no limit to the number of ways a Trojan horse can be incorporated into a program. Up to now, the usual evaluation levels for smart card operating systems have been ITSEC E3 and E4. Level E6 is also occasionally demanded or provided. It must be borne in mind that an evaluation of a complete smart card operating system at the E4 level can cost around €300,000. The obligation to repeat the evaluation after any modifications to the program code comes on top of this, although a re-evaluation is of course less costly than an initial evaluation. This is essentially why only relatively few smart card operating systems can boast ITSEC evaluations. More commonly, evaluations are performed by testing agencies without using the ITSEC. In such cases, testing is limited to a thorough review of the design criteria, the source code and the documentation. For example, this is a fundamental requirement for operating systems used in German Eurocheque cards.