400 likes | 719 Views
Formal specification of Gemplus’ electronic purse case study. Néstor Cataño & Marieke Huisman INRIA Sophia-Antipolis {ncatano, mhuisman}@sophia.inria.fr. The electronic purse . Developed by trainee at Gemplus Goal: develop more complex application, using object-oriented features
E N D
Formal specification of Gemplus’ electronic purse case study Néstor Cataño & Marieke Huisman INRIA Sophia-Antipolis {ncatano, mhuisman}@sophia.inria.fr
The electronic purse • Developed by trainee at Gemplus • Goal: develop more complex application, using object-oriented features • Revision by members research lab and new trainee • Result: not completely finished , not fully representative
Software documentation • Management & history of the development • Clear, concise and unambiguous • Correspondance with implementation
Some Fragments from LoyaltiesTable // huge modifications on 31/07/2000 // now, we handle AID objects instead of byte arrays that represents them. // that way, we gain some space, and code is clearer. /* the purse stores in this object the loyalties that are allowed to communicate with it*/ class LoyaltiesTable { //////////////// ATTRIBUTES //////////////// // temporarily modified by RM on 26/07/2000 for memory reason // private final static byte NB_MAX = (byte)20; private final static byte NB_MAX = (byte)3; … /* suppress all the entries of the loyalty specified by aid */ void delLoyalty(AID aid) {…} … /* suppress the notification of the loyalty specified by aid*/ void removeNotification(AID aid) {…}
Software documentation • Management & history of the development • Clear, concise and unambiguous • Correspondance with implementation • Formal specification • And verification Difficult and labour-intensive
This talk • Different approaches to formal specification and verification • Static checking (lightweight formal methods) • The electronic purse case study • Static checking of the electronic purse: class invariants
Specification language • Close to programming language • Expressions from programming language Eiffel , JML, ESC/Java , Jass with specification-specific constructs (forall, exists, implication etc.)
Checking techniques • Run-time checking • Full verification (syntactic or semantic) (Eiffel, JML, Jass) (Jive) (LOOP) • Static checking(ESC/Java)
Static checking with ESC/Java • Compaq Research (Leino et al.) • Focus on finding common program errors (nullpointers, array index out of bounds) • Proof obligations to dedicated theorem prover (assume - assert pairs) • Issues warnings
Static checking with ESC/Java ESC/Java = Compromise between soundness, completeness, and efficiency
ESC/Java pragmas • Preconditions (requires) • Postconditions (ensures) • Exceptional postconditions (exsures) • Modifies clause • Class invariants • Implication, quantification • Value expression in pre-state (\old(E)) • Result value of method (\result)
The electronic purse • Supports debit, credit and currency change operations • Interaction with loyalty, card issuer and terminal • Packages: utils, pacapinterfaces and purse
The purse package • PurseApplet: installation, (de)selection, communication with terminal • Purse: • implements basic functionalities • keeps track of balance, transactions, currency changes, loyalties
The purse package • AccessControl: restricted set of users for certain operations • Currencies • Cryptographic concepts
Writing the specification • For each method: requires, ensures, exsures, modifies • First basic classes (utils), then more application-specific • Appropriate class invariants, e.g. restricting domain of instance variables
Writing the specification • Discrepancies between documentation and implementation
Writing the specification • Discrepancies between documentation and implementation
Writing the specification • Discrepancies between documentation and implementation • Usage of existing API specification
Writing the specification • Discrepancies between documentation and implementation • Usage of existing API specification • .spec files for e.g. visa and crypto classes
Writing the specification • Discrepancies between documentation and implementation • Usage of existing API specification • .spec files for e.g. visa and crypto classes • Avoid warnings as much as possible, but still full specification
Class invariants Restrict state space of a class • reference never null pointer //@ invariant purse != null; • variable within a certain range /*@ invariant decPart >= 0 && decPart < PRECISION; invariant intPart >= 0 && intPart < MAX_DECIMAL_NUMBER; */ Easy to write, easy to check
Enumeration types /* the transaction status*/ public static final byte INDETERMINE = (byte)0; . . . /* the transaction status*/ public static final byte TYPE_CREDIT = (byte)50; /* the transaction status*/ public static final byte TYPE_DEBIT = (byte)51; . . . /* the transaction type: debit or credit*/ private byte type; . . . /* set all this transaction attributes to 0*/ void reset() { isValid = false; number = (short)0; type = INDETERMINE; typeProduit = (short)0; . . . }
/* the transaction type: debit or credit*/ private byte type; . . . /* set all this transaction attributes to 0*/ void reset() { isValid = false; number = (short)0; type = INDETERMINE; typeProduit = (short)0; . . . }
Enumeration types /*@ invariant condition == FREE || condition == LOCKED || condition == SECRET_CODE || condition == SECURE_MESSAGING || condition == (SECRET_CODE | SECURE_MESSAGING) */ public AccessCondition() { super(); // commented by Rodolphe Muller on 16/06/2000 // strange to set the condition here to 0 and to // FREE above setCondition((byte)0); } public AccessCondition() { super(); // commented by Rodolphe Muller on 16/06/2000 // strange to set the condition here to 0 and to // FREE above setCondition((byte)0); } public AccessCondition() { super(); // commented by Rodolphe Muller on 16/06/2000 // strange to set the condition here to 0 and to // FREE above setCondition((byte)0); } NB. FREE == (byte)1;
Avoiding dead code switch(condition) { case FREE: ... case SECRET_CODE: ... case SECURE_MESSAGING: ... case SECRET_CODE | SECURE_MESSAGING: ... case LOCKED: ... default: //@ assert false; t = AccessConditionException.C_C_INVALIDE; AccessConditionException.throwIt(t); } switch(condition) { case FREE: ... case SECRET_CODE: ... case SECURE_MESSAGING: ... case SECRET_CODE | SECURE_MESSAGING: ... case LOCKED: ... default: t = AccessConditionException.C_C_INVALIDE; AccessConditionException.throwIt(t); }
Other problems • Incorrect coding • Forgetting variable modifiers (final) • Underspecified documentation Is MAX_DECIMAL_NUMBER.999 legal? And how do you round it? • Superfluous methods (isNegatif()) • Complex and undocumented datastructures (with incorrect corrections)
Complete specification Available from http://www-sop.inria.fr/lemme/ verificard/electronic_purse
Conclusions • Using lightweight formal methods, applications can be improved • Class invariants make implicit assumptions explicit and check them • Case study convinced Gemplus to look at JML and ESC/Java • ESC/Java useful, but possibilities for improvement
Complete specification Available from http://www-sop.inria.fr/lemme/ verificard/electronic_purse
/*@ modifies M; requires true; ensures Q; exsures (E) !P; */ void m () { . . . } Writing the specification
Offensive /*@ modifies M; requires P; ensures Q; exsures (E) false; */ void m () { . . . } Defensive /*@ modifies M; requires true; ensures Q; exsures (E) !P; */ void m () { . . . } Writing the specification
Experiences with ESC/Java • Pleasant tool, easy to work with • Specifications written by non-experienced user • Two/three months work all together
Suggestions for ESC/Javaspecification language • Richer specification language modifies \nothing, modifies \field_of(E) • Extra quantifiers • Run-time exceptions without explicit throws clause • Use of pure methods in specifications
Example specification modifies sessionNumber, date.jour, date.mois, date.annee, heure.heure, heure.minute; modifies ancienneDevise, nouvelleDevise, isValid, status; modifies id[*], terminalTC[*], terminalSN[*] ; requires es != null ; requires es.id != terminalTC & es.id != terminalSN & es.terminalTC != terminalSN; ensures sessionNumber == es.sessionNumber ; ensures ancienneDevise == es.ancienneDevise ; ensures nouvelleDevise == es.nouvelleDevise ; ensures isValid == es.isValid ; ensures status == es.status ; ensures (\forall int i;0 <= i & i < ID_LENGTH ==> es.id[i] == id[i]); ensures (\forall int i;0 <= i & i < TTC_LENGTH ==> es.terminalTC[i] == terminalTC[i]); ensures (\forall int i;0 <= i & i < TSN_LENGTH ==> es.terminalSN[i] == terminalSN[i]); exsures (TransactionException e) e._reason == TransactionException.BUFFER_FULL && JCSystem._transactionDepth == 1; exsures (NullPointerException) false; exsures (ArrayIndexOutOfBoundsException) false; modifies sessionNumber, date.jour, date.mois, date.annee, heure.heure, heure.minute; modifies ancienneDevise, nouvelleDevise, isValid, status; modifies id[*], terminalTC[*], terminalSN[*] ; requires es != null ; requires es.id != terminalTC & es.id != terminalSN & es.terminalTC != terminalSN; ensures sessionNumber == es.sessionNumber ; ensures ancienneDevise == es.ancienneDevise ; ensures nouvelleDevise == es.nouvelleDevise ; ensures isValid == es.isValid ; ensures status == es.status ; ensures (\forall int i;0 <= i & i < ID_LENGTH ==> es.id[i] == id[i]); ensures (\forall int i;0 <= i & i < TTC_LENGTH ==> es.terminalTC[i] == terminalTC[i]); ensures (\forall int i;0 <= i & i < TSN_LENGTH ==> es.terminalSN[i] == terminalSN[i]); exsures (TransactionException e) e._reason == TransactionException.BUFFER_FULL && JCSystem._transactionDepth == 1; exsures (NullPointerException) false; exsures (ArrayIndexOutOfBoundsException) false;
And as we would like it to be... modifies sessionNumber, date.jour, date.mois, date.annee, heure.heure, heure.minute; modifies ancienneDevise, nouvelleDevise, isValid, status; modifies id[*], terminalTC[*], terminalSN[*] ; requires es != null ; requires es.id != terminalTC & es.id != terminalSN & es.terminalTC != terminalSN; ensures this.equal(es); exsures (TransactionException e) e._reason == TransactionException.BUFFER_FULL && JCSystem._transactionDepth == 1; exsures (NullPointerException) false; exsures (ArrayIndexOutOfBoundsException) false;
NO Verification of modifies clauses Specification accepted /*@ modifies x; ensures x == 3; */ void m() { x = 3; n (); } void n() { x = 4; } Missing modifies clause
Modifies clauses • Implementation of modifiable checker • Extension of JML • Static checking technique, based on syntax • Neither sound, nor complete • Fully described in separate paper (ask Néstor or me)
Future work • Develop application with annotations from scratch • Extension to multi-threading • Automated verification technique for termination of loops • Cryptographic aspects of the specification