Upload
angelica-williams
View
222
Download
1
Tags:
Embed Size (px)
Citation preview
Bytecode Verification on Java Smart Cards
Xavier Leroy
Presentation(day 1)-Nithya
Overview JavaCard Architecture Sandbox model Sun’s Bytecode verification Our Verification Algorithm Performance Analysis of both Differences
Overview of JVM Stack based abstract machine
- Instructions pop their arguments off the stack
- Push their results on the stack Set of registers (local variables) can
be accessed via “load” and “store”
- push the value of a register on the stack- store the top of the stack in the register
Stack + register -> activation record for a method
Type-correctness eg. of JVM Iadd :
- Stack initially contains at least 2 elements of type int and it pushes back result of int
Getfield C.f. τ : - Top of the stack contains a reference to an
instance of class C - it then pops it and pushes back a value of
type τ (the value of the field f)
Conditions for JVM’s proper operation Type Correctness No stack overflow or underflow Code containment Register initialization Object initialization
Smart Cards What are Smart Cards? Security tokens - applications Traditional Smart Cards
- C or Assembler Challenged by Open Architectures
- Multos, Java Card
Java Card Architecture Applications written in Java and so
are portable across all Java cards Java Cards can run multiple
applications which can communicate thru shared objects
New applications called applets can be downloaded on the card post issuance
Security Issues (by malicious applet) Leaking confidential information
outside (eg: PINS and secret cryptographic keys)
Modifying sensitive information (eg: balance of an electonic purse)
Interfering with other honest application on the card (Trojan Attack)
Solution Put forward by Java Programming
Environment Execute the applets in a so called
“Sandbox” Its an insulation layer preventing
direct access to the hardware resources
Also implements a suitable access control policy
Sandbox Model-3 components Applets --> Bytecode
VM manipulates secure abstractions of data than hardware processor
No direct access to hardware resources but to a set of API classes
Upon Downloading, applet subject to static analysis called Bytecode Verification
Bytecode Verification- Purpose To check ->code is well typed Doesn’t bypass protections 1 & 2 by
performing ill typed operations at runtime:
1. Forging object references from integers2. Illegal casting of obj ref from one class to
another3. Calling private methods of API4. Jumping in middle of API method or
jumping to data as if it were code
Java Card Arch & Sandbox Component 1: Applets executed by
JVM Component 2: Java Card runtime
environment provides access control through its “firewall”
Component 3: Bytecode Verifier missing!
- complex and expensive process- requires large amounts of working memory
Approach 1 Relying on off-card tools Attesting a cryptographic signature
on well-typedness of the applet Oncard downloading restricted to
signed applets Drawbacks:
- to extend the trusted computing base to off card components- practical issues: (how to deploy the signature keys?)- legal issues: (who takes liability for a buggy applet?)
Defensive VM Approach To type-check dynamically during
applet execution VM computes bytecode instructions Keeps track of all data it manipulates Arguments- correct types?stack
overflow or underflow? Are class member accesses allowed? Drawback:
- Dynamic Type-checks expensive in terms of execution speed and memory
Traditional Bytecode Verifn For Straight line code?
-Verifier checks every instruction of the method code- Checks whether stack has enough entries- Checks whether the entries are of correct types- Effect of the instruction on Operand stack and registers
Intialisation:- Stack ->empty
- Reg (0…n-1) -> method parameters
- Reg(n…m-1)-> T (uninitialised reg)
Method invocations ?
Traditional Bytecode Verifn For Branches- Forks and Joins Forks?
- must propagate inferred stack & reg type to all successors
Joins?- makes sure the types of the stack and registers along all paths agree
Handling joins
Dictionary A data structure associating a stack and register
type to each program point that is the target of a branch or exception handler
During analysis, Updates ->type associated with target of branch
Replacing by -> LUB(prev type,type inferred for the instruction)
If changed -> the corr.instrn & successors are reanalysed until a fixpoint is reached
This way, the dictionary entry for a branch target contains LUB inferred on all branches of control that lead to this instrn.
Errors
1. Stack heights may differ An instruction can be reached through several paths with inconsistent operand stacks
1. Types for a particular stack entry or register may be incompatible
eg: branch 1: short
branch 2 : Obj Ref Type set to T in dictionary
Semi-Lattice
Interfaces and LUB Property: Every pair of types
possesses a smallest common supertype (LUB)
Does not hold ->Interfaces are types and classes can implement several interfaces
Example
interface I { ... }interface J { ... }class C1 implements I, J { ... }class C2 implements I, J { ... }
Subtyping relation
Approach
Solution to Interface problem Bytecode verification ignores interfaces Treats all interface types as class type
“Object” Verifier contains proper classes and
subtyping between them is simply inheritance relation
Subtyping relation is tree shaped ->forms a semilattice.
LUB of 2 classes ->closest common ancestor in inheritance tree
Performance Analysis Straight line Code:
Time: as fast as executing instructionSpace: 1 stack and 1 set of reg types
(if each type-3 bytes, then memory=3S+3N bytes)
Similar for method invocation:Space for method invocation = space for verification
Performance Analysis Branches- costly since instructions are analyzed
several times to reach fixpoint Real issue: Memory space for storing dictionary If B ->no of branch targets, memory =(3S+3N+3)*B
bytes [3 bytes of overhead for each Dic. Entry] Drawbacks: 1. No. of branch targets proportional to method size ->
dictionary size increases linearly2. Dictionary entries quite often redundant3. Merging several methods into a larger one result in
non-verifiable code4. Storing the dictionary in EEPROM not an option.
Questions?
Part II – Novel Bytecode Verification Algorithm
Background for Our Verification Algorithm Operand stack is empty at the
beginning and end of every statement
JCVM for e1 ? e2 : e3 :
code to evaluate e1ifeq lbl1code to evaluate e2goto lbl2lbl1: code to evaluate e3Lbl2: …(Branch to lbl2 occurs with a non-empty operand stack)
Background… In Java source, a local variable has only
one type throughout the method: τ In JCVM bytecode, register with type T
acquires the type τ at 1st store in reg. For Java code,A x;if (cond)x = new B(); // B is a subclass of Aelsex = new C(); // C is another subclass of ARegister x has type A (ie,LUB(B,C)) when two arms merge
Background
{ short x; ... }{ C y; ... } Scopes of x & y disjoint ->store x &
y in same register
Requirements R1: Operand stack is empty at all
branch and branch target instructions
R2: Each register has only one type throughout the method code
R3: On method entry,the VM initialises all registers that are not parameters to the bit pattern representing null object reference
The Algorithm Global variables: Nr,Ns,r[Nr],s[Ns],sp,chg
Initialisation: Set sp <- 0 Set r[0],…, r[n - 1] to the types of the method
arguments
Set r[n],…, r[Nr - 1] to ┴ Set chg <- true
AlgorithmWhile chg:Set chg -> falseFor each instruction i of the method, in code order:
If i is the target of a branch instruction:If sp != 0 and the previous instruction falls through,
errorSet sp -> 0
If i is the target of a JSR instruction:If the previous instruction falls through, errorSet s[0] -> retaddr and sp -> 1
If i is a handler for exceptions of class C:If the previous instruction falls through, errorSet s[0] -> C and sp -> 1
If two or more of the cases above apply, error
AlgorithmDetermine the types a1,…, an of the arguments of iIf sp < n, error (stack underflow)For k = 1,…,n: If s[sp - n + k - 1] is not subtype of ak, errorSet sp -> sp - nDetermine the types r1,…, rm of the results of iIf sp + m > Ns, error (stack overflow)For k = 1,…,m: Set s[sp + k - 1] -> rkSet sp -> sp + mIf i is a store to register number k:
Determine the type t of the value written to the registerSet r[k] -> lub(T, r[k])If r[k] changed, set chg -> true
If i is a branch instruction and sp ! = 0, error
Differences with straight line code verification Stack empty? When checking Store,reg type ->LUB Typechecking until a fixpoint Initialisation: Stack -> Empty reg(0..n-1) -> method parameter types reg(n..m-1)-> ┴ & not T (REQ R3)
Next class Subroutines Object Initialisation Off card code transformations Bytecode Transformation on small
computers