An Untrusted Verifier for Typed Assembly Language

Software downloaded onto computers and executed without user oversight or intervention, otherwise known as mobile code, is playing an increasingly prominent role in today’s computing infrastructure. Java applets and ActiveX components are well known to the general public. Software components are routinely downloaded to and executed by cellular phones, smart cards, and other devices that consumers generally don’t think of as sophisticated computers. The seemingly innocuous nature of mobile code for these applications opens up opportunities for exploitation by malicious software creators. The traditional technique for preventing such abuses involves running untrusted code in a sandbox, inserting many dynamic run-time tests, and other methods that can add significant execution overhead. Newer methods rely more strongly on static analysis of code to prove absence of undesirable behavior. The Java Virtual Machine (JVM) format [4] and the Microsoft . NET Common Language Infrastructure (CLI) [1] are both designed to allow static verification of basic properties, including memory safety. However, they depend on the inclusion of many very high level instructions, including those for object-oriented features, different types of function calls, and more. Thus, while these formats are designed to be easy targets for many high level programming languages, it is common that languages sufficiently different from those original considered will have sufficiently different features to make the JVM and CLI formats poor targets. The Open Verifier project seeks to develop a more flexible and trustworthy alternative to these infrastructures. It is based around the idea of minimizing the set of abstractions built into the software verification process. Instead of using bytecode formats with many high-level instructions, it verifies programs written in standard assembly languages. The job of proving memory safety of these programs is delegated to untrusted modules, which produce proofs that are checked by a small trusted core. Each compilation strategy for each high level language can have a separate module of this kind. This frees language designers and compiler implementors to consider many different implementation strategies without being constrained by language specific features of a target format or requiring constant addition of new instructions to that format. The Open Verifier architecture’s design also reduces the amount of code that a mobile code user must trust. I am currently developing an untrusted Open Verifier module to enable checking of programs compiled from Typed Assembly Language (TAL) [5]. TAL is similar to the common language target formats described above. However, it uses a sophisticated type system to remove most need for instructions at a higher level than those generally provided by real processors. Most TAL instructions are real machine instructions augmented with typing information. The status of TAL as possibly the most expressive language of its kind makes producing a verification module for it a good test of the flexibility of the Open Verifier system. Here I present a fairly straightforward encoding of its type system in the mostly first-order logic system used by the Open Verifier. While the verifier that uses this encoding is not yet complete, the chances that the final product will integrate well with the Open Verifier seem promising.