• Nenhum resultado encontrado

Contribuições para verificação automática de applets javacard

N/A
N/A
Protected

Academic year: 2017

Share "Contribuições para verificação automática de applets javacard"

Copied!
125
0
0

Texto

(1)

Universidade Federal do Rio Grande do Norte

Centro de Ciˆ

encias Exatas e da Terra

Departamento de Inform´

atica e Matem´

atica Aplicada

Programa de P´

os-Gradua¸c˜

ao em Sistemas e Computa¸c˜

ao

CONTRIBUIC

¸ ˜

OES PARA VERIFICAC

¸ ˜

AO

AUTOM ´

ATICA DE APPLETS JAVACARD

Antonio Augusto Oliveira Viana da Silva

DISSERTAC

¸ ˜

AO DE MESTRADO

Natal - RN

(2)

Centro de Ciˆ

encias Exatas e da Terra

Departamento de Inform´

atica e Matem´

atica Aplicada

Antonio Augusto Oliveira Viana da Silva

CONTRIBUIC

¸ ˜

OES PARA VERIFICAC

¸ ˜

AO AUTOM ´

ATICA DE

APPLETS JAVACARD

Trabalho apresentado ao Programa de Programa de P´

os-Gradua¸c˜ao em Sistemas e Computa¸c˜ao do Departamento

de Inform´atica e Matem´atica Aplicada da Universidade

Federal do Rio Grande do Norte como requisito parcial

para obten¸c˜ao do grau de Mestre em Ciˆencias da

Com-puta¸c˜ao.

Orientador: David Paul Boris Deharbe

Natal - RN

(3)
(4)
(5)
(6)

Em primeiro lugar gostaria de agradecer a todos os deuses e deusas de nosso mundo, por estarem sempre nos guiando e mostrando o caminho que temos de seguir. Mesmo que `as vezes estes pare¸cam t˜ao dif´ıceis e cheios de problemas, aprendemos que devemos sempre persistir, pois, afinal, “as coisas s˜ao como elas s˜ao porque ´e assim que elas tinham de ser”.

Agrade¸co tamb´em aos meus pais, Antonio Viana da Silva e Maria de Lourdes Oliveira Viana, n˜ao s´o por terem me dado o dom da vida, mas como tamb´em por terem cuidado de mim, e me ajudado a caminhar, especialmente quando eu me deparava com um desses caminhos dif´ıceis.

Obrigado tamb´em a todos os meus parentes, que, de maneira direta ou indireta, tamb´em fizeram parte da minha forma¸c˜ao. Agrade¸co em especial aos meus av´os, que nunca conheci (Henrique Oliveira), que tive o prazer de ter ao meu lado durante alguns anos (Esmeralda dos Santos Oliveira e Maria Euzebia da Silva) e com que convivo at´e hoje (Heleno Viana da Silva).

Tamb´em merece meu muito obrigado meu orientador, David D´eharbe, pela sua paciˆencia e perseveran¸ca, enquanto me orientava (e `as vezes desorientava) durante esse um ano e meio, enquanto eu procurava entender um pouco desse curioso mundo da verifica¸c˜ao formal.

Como n˜ao podia deixar de ser, tamb´em quero agradecer aos meus amigos (“os irm˜aos que Deus nos deixou escolher”). Agrade¸co tanto aos amigos que deixei em Aracaju quando vim para Natal, que ficaram l´a torcendo por mim e me incentivando, como a todos os que fiz por aqui, que compartilham comigo todos os sofrimentos, esperan¸cas e sucessos obtidos nesse per´ıodo. N˜ao pretendo citar o nome de todos, pois com certeza acabaria esquecendo algu´em, mas um abra¸co especial vai para os meus irm˜aos de cora¸c˜ao Rauflan dos Santos Brito, Roberto Barreto dos Anjos e Alisson Vit´orio de Lima (valeu mesmo caras!), e tamb´em para a “mangua¸ca people”, que, mesmo estando t˜ao dispersa, ainda continuam todos emangua¸cados.

Por ´ultimo gostaria de agradecer `a Ambev, pois seus produtos nos ajudaram a relaxar nos momentos mais estressantes de nosso percurso, afinal ningu´em ´e de ferro!

(7)

RESUMO

O grande crescimento do uso de smart cards (por bancos, companhias de transporte, celulares, etc) trouxe um fato importante, que deve ser considerado: a necessidade de ferramentas que possam ser usadas para verificar os cart˜oes, para que se possa garantir a corretude de seu software.

Como a grande maioria dos cart˜oes desenvolvidos hoje em dia usa a tecnologia JavaC-ard em sua camada de software, o uso daJava Modeling Language (JML) para especificar os programas aparece como uma solu¸c˜ao natural.

JML ´e uma linguagem de especifica¸c˜ao formal ligada ao Java. Ela foi inspirada pelas metodologias de Larch e Eiffel, e foi largamente adotada como a linguagem de facto em se tratando da especifica¸c˜ao de qualquer programa relacionado `a Java.

V´arias ferramentas que fazem uso de JML j´a foram desenvolvidas, cobrindo uma grande gama de funcionalidades, entre elas, a verifica¸c˜ao em tempo de execu¸c˜ao e est´atica. Mas as ferramentas existentes at´e o momento para a verifica¸c˜ao est´atica n˜ao s˜ao total-mente automatizadas, e, aquelas que s˜ao, n˜ao oferecem um n´ıvel adequado de completude e seguran¸ca.

Nosso objetivo ´e contribuir com uma serie de t´ecnicas, que podem ser usadas para alcan¸car uma verifica¸c˜ao completamente autom´atica e segura para applets JavaCard. Nesse trabalho n´os apresentamos os primeiros passos nessa dire¸c˜ao. Com o uso de uma plataforma de software composta pelo Krakatoa, Why e haRVey, n´os desenvolvemos um conjunto de t´ecnicas para reduzir o tamanho da teoria necess´aria para verificar as especi-fica¸c˜oes.

Tais t´ecnicas deram resultados muito bons, com ganhos de quase 100% em todos os testes que realizamos, e se provou como uma t´ecnica que deve ser sempre consider-ada, n˜ao somente nesse, mas na maioria dos problemas reais relacionado com verifica¸c˜ao autom´atica.

Palavras-chave: Verifica¸c˜ao Formal, Sistemas Embarcados, Java, JML, Provadores de Teorema.

(8)

The widespread growth in the use of smart cards (by banks, transport services, and cell phones, etc) has brought an important fact that must be addressed: the need of tools that can be used to verify such cards, so to guarantee the correctness of their software.

As the vast majority of cards that are being developed nowadays use the JavaCard technology as they software layer, the use of the Java Modeling Language (JML) to specify their programs appear as a natural solution.

JML is a formal language tailored to Java. It has been inspired by methodologies from Larch and Eiffel, and has been widely adopted as the de facto language when dealing with specification of any Java related program.

Various tools that make use of JML have already been developed, covering a wide range of functionalities, such as run time and static checking. But the tools existent so far for static checking are not fully automated, and, those that are, do not offer an adequate level of soundness and completeness.

Our objective is to contribute to a series of techniques, that can be used to accomplish a fully automated and confident verification of JavaCard applets. In this work we present the first steps to this. With the use of a software platform comprised by Krakatoa, Why and haRVey, we developed a set of techniques to reduce the size of the theory necessary to verify the specifications.

Such techniques have yielded very good results, with gains of almost 100% in all tested cases, and has proved as a valuable technique to be used, not only in this, but in most real world problems related to automatic verification.

Keywords: Formal Verification, Embedded Systems, Java, JML, Theorem Proving.

(9)

CONTENTS

Chapter 0—Resumo Estendido 1

0.1 Introdu¸c˜ao . . . 1

0.2 Uma abordagem baseada em Java para Smart Cards . . . 2

0.3 A Linguagem JML . . . 3

0.3.1 Pr´e- e P´os-condi¸c˜oes . . . 4

0.3.2 Invariantes . . . 4

0.3.3 Tratamento de exce¸c˜oes . . . 4

0.3.4 Heran¸ca . . . 4

0.4 Uma plataforma para a verifica¸c˜ao de programas Java . . . 4

0.4.1 Why . . . 4

0.4.2 Krakatoa . . . 5

0.4.3 haRVey . . . 6

0.5 T´ecnicas para a simplifica¸c˜ao de teorias . . . 7

0.5.1 Redu¸c˜ao puramente simb´olica . . . 7

0.5.2 Elimina¸c˜ao de quantificadores . . . 8

0.5.3 Estrutura¸c˜ao da teoria . . . 9

0.5.4 Resultados experimentais . . . 10

0.6 Conclus˜oes e trabalhos futuros . . . 12

0.6.1 Trabalhos futuros . . . 12

Chapter 1—Introduction 14 1.1 Embedded systems and formal verification . . . 15

1.2 Our approach . . . 16

1.3 Next chapters . . . 17

Chapter 2—Java based approach to smart cards 18 2.1 Smart Cards . . . 18

2.1.1 History . . . 18

2.1.2 Characteristics of smart cards . . . 19

2.1.3 Standards . . . 21

2.1.4 The APDU protocol . . . 21

2.2 JavaCard . . . 24

2.2.1 History . . . 24

2.2.2 JavaCard Overview . . . 25

2.2.3 A JavaCard example . . . 26

(10)

2.2.3.1 Variables and constants declarations . . . 27

2.2.3.2 Implementation of the Applet functions . . . 27

2.2.3.3 Helper functions . . . 28

Chapter 3—The JML language 31 3.1 Underlying JML concepts . . . 31

3.1.1 Contracts . . . 31

3.1.2 Behavioral and Interface Specification . . . 33

3.2 JML notation . . . 34

3.3 Assertions . . . 35

3.3.1 Assertions for functions . . . 36

3.3.2 Class invariants and Constraints . . . 37

3.3.3 Loops variants and invariants . . . 40

3.4 JML extensions to Java . . . 43

3.4.1 Universal quantification . . . 43

3.4.2 Existential quantification . . . 44

3.4.3 old and result . . . 44

3.5 JML modifiers . . . 45

3.5.1 Visibility of the specifications . . . 45

3.5.2 Model fields . . . 46

3.5.3 Pure methods . . . 47

3.6 Exceptions treatment . . . 48

3.7 Inheritance . . . 49

Chapter 4—A tool platform for Java verifications 54 4.1 Why . . . 54

4.1.1 Overview . . . 54

4.1.2 Declarations . . . 56

4.1.3 Annotations . . . 57

4.1.3.1 Pre- and Postconditions . . . 57

4.1.3.2 Assertions . . . 57

4.1.3.3 Loops Annotations . . . 57

4.1.3.4 Recursive functions . . . 58

4.1.3.5 Labels . . . 58

4.1.3.6 Exceptions . . . 58

4.1.3.7 Unreachable code . . . 59

4.2 Krakatoa . . . 59

4.2.1 Krakatoa workflow . . . 59

4.2.2 Interpretation of the Java memory . . . 61

4.2.3 Interpretation of Java types in Why . . . 61

4.2.4 Memory operations . . . 62

4.2.4.1 Read access . . . 62

(11)

contents ix

4.2.5 Interpretation of Java statements . . . 64

4.3 haRVey . . . 66

4.3.1 BDDs . . . 66

4.3.2 Superposition Calculus . . . 67

4.3.3 Combining both . . . 67

4.3.4 haRVey Syntax . . . 68

4.3.5 haRVey compared to other theorem provers . . . 69

Chapter 5—Techniques for simplification of large theories 70 5.1 Purely symbolic theory reduction . . . 70

5.2 Equivalence removal . . . 72

5.2.1 Restrictions to the equivalence replacement . . . 73

5.2.2 The problem with this approach . . . 74

5.2.3 Equivalence removal - A second approach . . . 74

5.3 Theory structuring . . . 76

5.4 Experimental results . . . 77

5.4.1 Heuristic problems . . . 79

Chapter 6—Conclusions and future work 82 6.1 Related work . . . 82

6.2 Future work . . . 83

Appendix A—Strutured local memory model 85

Appendix B—Lesson1.Java 96

Appendix C—Arrays.java 98

Appendix D—Purse.java 100

(12)

0.1 Esquema do workflow do Why. . . 5

0.2 Workflow do Krakatoa. . . 6

0.3 Um exemplo de arquivo do haRVey. . . 7

0.4 Nova sintaxe do haRVey. . . 10

1.1 Level of automation/expressiveness (inspired from [46]). . . 14

2.1 Smart card production life cycle (from [18]). . . 20

2.2 Life cycle of the smart card software (from [18]). . . 21

2.3 Command APDU (from [66]). . . 22

2.4 Response APDU (from [66]). . . 23

2.5 Status Words response code (from [66]). . . 23

2.6 Variables and constant definitions (from [32]). . . 27

2.7 JavaCard Applet functions (from [32]). . . 28

2.8 SetString function (from [32]). . . 29

2.9 GetString function (from [32]). . . 30

3.1 Is this piece of code correct? . . . 32

3.2 Function square root. . . 33

3.3 JML annotation (from [51]). . . 35

3.4 The use of the assertions (from [52]). . . 37

3.5 Account class (adapted from [24]). . . 39

3.6 Account class with invariant (adapted from [24]). . . 40

3.7 Invariants and constraints (from [51]). . . 40

3.8 Graphical representation of the loop computation (from [61]). . . 41

3.9 Loop invariants (from [56]). . . 42

3.10 The use of \forall (from [52]). . . 43

3.11 The use of \exists (from [56]). . . 44

3.12 The use of \old (from [56]). . . 44

3.13 Visibility modifier (from [51]). . . 46

3.14 Model field (from [51]). . . 47

3.15 Model class (from [50]). . . 48

3.16 Pure methods (from [51]). . . 49

3.17 The behavior clause (from [51]). . . 49

3.18 The exceptional behavior clause (from [50]). . . 50

3.19 Contract descent (from [61]). . . 51

3.20 Class Object (from JMLSpecifications). . . 52

(13)

LIST OF FIGURES xi

3.21 A class that extends Object (from [51]). . . 52

3.22 The resulting specification (from [51]). . . 53

4.1 Scheme of the Why workflow. . . 55

4.2 Pre- and Postcondition using Hoare Triples (from [29]). . . 57

4.3 Assertions in Why (from [29]). . . 57

4.4 Loop annotations in Why (from [29]). . . 58

4.5 Recursive functions in Why (from [29]). . . 58

4.6 Labels in Why (from [29]). . . 58

4.7 Exceptions in Why. . . 59

4.8 Unreachable code in Why (from [29]). . . 59

4.9 Krakatoa workflow (based on [58]). . . 60

4.10 Modeling of Java memory heap (from [57]). . . 61

4.11 The haRVey basic algorithm (from [22]). . . 68

4.12 Example of a haRVey input file. . . 68

5.1 The theory simplification algorithm. . . 72

5.2 Union find effect on recurrent definitions. . . 74

5.3 Problem with equivalence removal. . . 75

5.4 New haRVey syntax. . . 77

5.5 E prover problem with JML obligation. . . 80

(14)

0.1 Resultados iniciais. . . 11

0.2 Tamanho das teorias ap´os aplica¸c˜oes das t´ecnicas. . . 11

0.3 Resultados obtidos com a estrutura¸c˜ao da teoria. . . 11

0.4 Tamanho das teorias usando a teoria estruturada. . . 12

0.5 Resultados obtidos com a heur´ıstica fixa. . . 12

3.1 Courier service contract example. . . 32

3.2 Square root contract. . . 34

3.3 The visibility of specifications. . . 45

5.1 Initial results. . . 78

5.2 Reduction of the theory size. . . 79

5.3 Results with structured theory. . . 79

5.4 Reduction of the theory size with structured theory. . . 79

5.5 Results with fixed heuristic. . . 80

(15)

CHAPTER 0

RESUMO ESTENDIDO

0.1 INTRODUC¸ ˜AO

O uso de verifica¸c˜ao formal para verifica¸c˜ao de sofware ´e um assunto que vem sendo tratado desde os trabalhos seminais de Hoare. Apesar disso s´o a pouco tempo tais t´ecnicas come¸caram a ser usadas no dia-a-dia. A raz˜ao para isso ´e que at´e pouco tempo tais m´etodos s´o podiam ser usados por especialistas e adicionavam muito ao custo do projeto. Atualmente, com os avan¸cos no campo dos m´etodos formais, o aumento do poder com-putacional e a queda dos pre¸cos dos computadores, os custos para se utilizar as t´ecnicas formais finalmente compensam os benef´ıcios que elas trazem.

Mas mesmo com esse “balanceamento” n˜ao s˜ao todas as ´areas que est˜ao utilizando os m´etodos formais. O uso dessas t´ecnicas atualmente est´a restrito aos projetos onde a necessidade de se obter um software correto ´e critica, como usinas nucleares, sistemas de trafego a´ereo e sistemas embarcados.

Dessas ind´ustrias uma das que mais est´a em expans˜ao ´e a dos sistemas embarcados, em especial a de smart cards [78, 38], pequenos sistemas embarcados (geralmente no formato de um cart˜ao de cr´edito), que est˜ao sendo utilizados largamente ao redor do globo, e que, possivelmente, iram substituir todos os documentos que possu´ımos hoje em dia.

Um dos principais respons´aveis para a grande dissemina¸c˜ao dos smart cards foi o JavaCard [66, 67, 68, 77, 79], que tr´as para para esse mundo todos os benef´ıcios (e a base de programadores) que a tecnologia Java possui.

Para a especifica¸c˜ao e verifica¸c˜ao formal de tais sistemas, o padr˜ao que o mercado vem adotado atualmente ´e a JML [51, 10]. A Java Modeling Languagem (JML), ´e uma linguagem de especifica¸c˜ao formal associada ao Java que permite aos usu´arios da lin-guagem escreverem especifica¸c˜oes formais e de f´acil compreens˜ao (j´a que a sintaxe de JML ´e baseada em Java). Atualmente j´a foram desenvolvidas v´arias ferramentas para trabalharem com as especifica¸c˜oes escritas em JML, que cobrem desde a gera¸c˜ao de doc-umenta¸c˜ao at´e a verifica¸c˜ao est´atica.

No entanto as ferramentas existentes para a verifica¸c˜ao est´aticas n˜ao oferecem uma solu¸c˜ao ideal para o mercado, que necessita de uma ferramenta autom´atica e confi´avel. Esse trabalho apresenta os passos iniciais para a busca dessa solu¸c˜ao. Aqui ser˜ao ap-resentadas t´ecnicas para a redu¸c˜ao de teoria de obriga¸c˜oes de provas geradas a partir de programas Java especificados em JML. Tais t´ecnicas de redu¸c˜ao, embora n˜ao direta-mente relacionadas com os sistemas JavaCard, s˜ao de fundamental importˆancia para uma verifica¸c˜ao realmente autom´atica. Um exemplo disso ´e que nos testes que realizamos o uso dessas tecnicas oferece um ganho de at´e 100% no n´umero de obriga¸c˜oes verificadas, al´em de oferecer um ganho no tempo de verifica¸c˜ao, para as obriga¸c˜oes que j´a podiam ser verificadas.

(16)

Nosso trabalho se baseia no uso de uma plataforma de ferramentas composta por: Krakatoa [56, 58, 57], Why [29, 27, 28] e haRVey [13, 22, 71, 20, 21]. Enquanto as duas primeiras ferramentas s˜ao usadas para gerar obriga¸c˜oes de provas para v´arias ferramentas de verifica¸c˜ao, dada um programa Java especificado em JML, a ´ultima ´e um provador de teoremas que se mostrou extremamente eficiente em estudos anteriores [22, 21, 13].

Dando continuidade a essa apresenta¸c˜ao nos apresentaremos um breve hist´orico sobre os smart cards, em especial a tecnologia JavaCard na Se¸c˜ao 0.2. Na Se¸c˜ao 0.3 ser˜ao apresentados alguns dos conceitos b´asicos da linguagem JML. Em seguida, na Se¸c˜ao 0.4 nos apresentaremos as ferramentas utilizadas nessa trabalho, e na Se¸c˜ao 0.5 mostraremos as t´ecnicas de redu¸c˜ao de teoria desenvolvidas, bem como os resultados que obtivemos. Esse trabalho termina na Se¸c˜ao 0.6 com nossas conclus˜oes e trabalhos futuros.

0.2 UMA ABORDAGEM BASEADA EM JAVA PARA SMART CARDS

A tecnologia dos smart cards permite a utiliza¸c˜ao de um cart˜ao de pl´astico (geralmente do tamanho de um cart˜ao de cr´edito) com um chip embarcado nele, para as mais diversas aplica¸c˜oes. As primeiras pesquisas para o desenvolvimento da tecnologia para smart cards datam de 1968 quando dois inventores alem˜aes patentearam sua id´eia para o uso de microchips em cart˜oes de pl´astico, mas n˜ao foi s´o at´e 1976 que a ind´ustria alcan¸cou a tecnologia necess´aria para o desenvolvimento dessa tecnologia a pre¸cos aceit´aveis. Em 1981 foram feitos os primeiros testes reais de aplica¸c˜oes em smart cards, na Europa e nos Estados Unidos, utilizando os cart˜oes para fins banc´arios, de identifica¸c˜ao, de pagamentos, etc.

Atualmente tal tecnologia j´a est´a sendo comumente usada em v´arias partes do mundo, e de v´arios modos distintos. Suas aplica¸c˜oes variam desde acesso a pr´edios, assinatura digital de aplica¸c˜oes, cart˜oes para acesso a TV paga, e cart˜oes SIM para celulares. Um dos principais objetivos dos desenvolvedores de smart cards ´e que, no futuro, tal tecnologia possa ser usada como padr˜ao para armazenar todas as informa¸c˜oes do seu propriet´ario, como por exemplo, carteira de identidade, de motorista, cart˜ao de cr´edito, etc. substi-tuindo de forma eficiente (e segura) todos os cart˜oes que n´os carregamos atualmente na carteira.

(17)

0.3 a linguagem jml 3

A solu¸c˜ao para esse problema come¸cou a aparecer em 1996, quando a Sun lan¸cou a primeira vers˜ao da especifica¸c˜ao do JavaCard. JavaCard ´e uma vers˜ao reduzida da linguagem Java, que se adapta aos requisitos limitados dos smart cards e que visava trazer para essa plataforma os benef´ıcios que o Java j´a oferecia `as aplica¸c˜oes desktop (uso de orienta¸c˜ao a objeto no desenvolvimento do software, interoperabilidade e seguran¸ca). Com essa nova plataforma o desenvolvimento das aplica¸c˜oes se tornou mais simples, pois a partir do momento que o desenvolvedor tivesse um cart˜ao que implementasse um maquina virtual JavaCard (JCVM), ele teria dispon´ıvel imediatamente qualquer aplica¸c˜ao que fosse feita usando essa tecnologia.

Devido a essas vantagens o JavaCard rapidamene se tornou o padr˜ao para o desen-volvimento de aplica¸c˜oes smart cards, e j´a est´a sendo usada nos cart˜oes SIM, cart˜oes de cr´edito e cart˜oes pr´e-pagos, para citar alguns exemplos. No entanto mesmo com tantas vantagens, as aplica¸c˜oes JavaCard n˜ao oferecem os recursos necess´arios para se fazer ver-ifica¸c˜oes que garantam que um programa realmente segue uma dada especifica¸c˜ao. Para se fazer esse tipo de verifica¸c˜ao a linguagem adotada foi o JML, que ´e o padr˜ao de facto em se tratando da especifica¸c˜ao e verifica¸c˜ao formal de aplica¸c˜oes Java.

0.3 A LINGUAGEM JML

JML ´e uma Linguagem de Especifica¸c˜ao de Interface e de Comportamento (Behavioral Interface Specification Language - BISL) associada ao Java. Nela a defini¸c˜ao da interface de uma fun¸c˜ao/classe ´e dada pela pr´opria linguagem Java (nomes de fun¸c˜oes, parˆametros, etc) e o comportamento dado em JML. Enquanto a sintaxe de JML ´e estreitamente conectada a de Java, sua semˆantica vem de linguagens como Eiffel [61, 60], e Larch [85, 35, 34, 48, 49], al´em de usar aspectos do calculo de refinamento [9, 64, 63].

Os principais objetivos dos desenvolvedores de JML foi desenvolver uma linguagem que:

• Oferecesse facilidade para a documenta¸c˜ao de programas Java existes;

• Fosse f´acil de entender pelos programadores Java, inclusive aqueles com um modesto conhecimento matem´atico;

• Pudesse possuir suporte com ferramentas, gra¸cas a uma semˆantica formal.

As especifica¸c˜oes em JML geralmente s˜ao escritas juntamente com o c´odigo da aplica¸c˜ao, utilizando um tipo especial de coment´arios: /*@ e @*/, para especifica¸c˜oes em m´ultiplas linhas, ou //@ para especifica¸c˜oes de uma ´unica linha. JML j´a vem sendo usada h´a algum tempo e j´a existem muitas ferramentas que d˜ao suporte a ela. Para a verifica¸c˜ao est´atica podemos citar ESC/Java[31], LOOP[43], e o Krakatoa[58], entre outros. Al´em desses verificadores tamb´em encontrar v´arias aplica¸c˜oes que cobrem geradores de testes, utilit´arios para documenta¸c˜ao, geradores de invariantes, verificadores dinˆamicos, entre outros [7].

(18)

para definir as condi¸c˜oes podem ser escritas usando express˜oes Java que sejam puras (ou seja, sem efeitos colaterais). Pode-se tamb´em utilizar nas express˜oes alguns constru-tores oferecidos pela pr´opria JML, como \forall e \exists, que s˜ao respectivamente os quantificadores universal e existencial, entre outros.

0.3.1 Pr´e- e P´os-condi¸c˜oes

Em JML as fun¸c˜oes podem ser anotadas com pr´e- e p´os-condi¸c˜oes usando as clausulas

\requires e \ensures. Nas defini¸c˜oes de p´os-condi¸c˜oes, os construtores \result e \old podem ser usados para nos referirmos ao resultado do m´etodo e ao valor de uma express˜ao antes da execu¸c˜ao, respectivamente.

0.3.2 Invariantes

Pode-se especificar invariantes de classe em JML usando a express˜ao \invariant. ´E tamb´em poss´ıvel criar relacionamentos (constraints), que definem a rela¸c˜ao do valor de uma vari´avel antes e ap´os a execu¸c˜ao de um m´etodo, usando a clausula \constraint. 0.3.3 Tratamento de exce¸c˜oes

Exce¸c˜oes podem ser tratadas em JML usando as clausulas\exceptional behavior, que permite definir uma nova pr´e-condi¸c˜ao necess´aria para ocorrer uma exce¸c˜ao bem como uma p´os-condi¸c˜ao que diz qual ser´a o estado do sistema quando a mesma ocorrer , e

\signals que define qual exce¸c˜ao est´a sendo tratada. 0.3.4 Heran¸ca

JML oferece suporte completo a heran¸ca atrav´es do uso da palavra-chavealso quando especificando pr´e- e p´os-condi¸c˜oes para um m´etodo, para assim descrevermos condi¸c˜oes adicionais em rela¸c˜ao a uma super-classe.

0.4 UMA PLATAFORMA PARA A VERIFICAC¸ ˜AO DE PROGRAMAS JAVA

Para verificarmos com sucesso as nossas programas Java (e JavaCard em especial), n´os contamos com uma plataforma de software composta por trˆes aplica¸c˜oes: Why, Krakatoa e haRVey. Cada uma dessas ferramentas ser´a apresentada a seguir.

0.4.1 Why

O Why ´e uma ferramenta multi-linguagem e multi-provador que, recebendo como entrada um programa anotado, pode gerar obriga¸c˜oes de provas para diversas ferramen-tas. A id´eia dessa abordagem vem do fato de que, desenvolver uma boa ferramenta de verifica¸c˜ao requer um esfor¸co consider´avel, e deve ser deixado para os especialistas. No entanto a gera¸c˜ao de obriga¸c˜oes para esses provadores desse ser o mais f´acil poss´ıvel.

(19)

0.4 uma plataforma para a verificac¸˜ao de programas java 5

HOL Light e os verificadores de teorema Simplify e haRVey. Segundo os desenvolvedores, sa´ıdas adicionais podem ser adicionadas rapidamente.

Para alcan¸car essa flexibilidade o Why trabalha internamente com uma linguagem baseada no ML (chamada de WL). Assim, quando o Why recebe um programa anotado como entrada ele primeiro transforma esse programa para sua linguagem interna e gera obriga¸c˜oes de provas para ela (baseado nas anota¸c˜oes dadas). O Why usa ent˜ao essas obriga¸c˜oes “gen´ericas” para gerar as obriga¸c˜oes de prova na linguagem especifica do provador.

Um esquema de como funciona esse processo poder ser visto na Figura 0.1.

Figura 0.1. Esquema doworkflow do Why.

0.4.2 Krakatoa

O Krakatoa trabalha em conjunto com o Why para lhe dar suporte a linguagem Java. Ele ´e respons´avel por transformar os programas/anota¸c˜oes em Java/JML em obriga¸c˜oes de prova. O funcionamento do Krakatoa ´e intimamente relacionado com o Why, e com isso ela herda a capacidade de gerar obriga¸c˜oes para v´arios provadores.

Quando verificando uma programa anotado o Krakatoa segue os seguintes passos [58]:

i) Retirar os “a¸c´ucar sint´atico” de cada especifica¸c˜ao JML, para que no final tenhamos m´etodos com somente uma clausularequires, umaassignable, umaensures and uma signals, e que invariantes de classe sejam contidos em uma ´unica clausula invariant;

ii) Calcular, para cada m´etodo, quando ele vai acessar/escrever na pilha ou aces-sar/escrever em qualquer vari´avel est´atica existente no programa;

iii) Gerar especifica¸c˜oes na linguagem do Why para o programa (uma para cada classe). Cada um dos arquivos gerados cont´em declara¸c˜oes de vari´aveis globais, declara¸c˜oes de m´etodos bem como fun¸c˜oes externas do Why e declara¸c˜oes de predicados para cada m´etodo puro;

(20)

v) Gerar arquivos do Why para cada m´etodo que ser´a verificado, contendo programas traduzidos do c´odigo Java e das especifica¸c˜oes JML diretamente para o Why.

O trabalho do Krakatoa termina nesse ponto. Ap´os esses passos estarem completos n´os utilizamos o Why para gerar as obriga¸c˜oes de provas e o provador para verific´a-las. A Figura 0.2 demonstra esse esquema.

Figura 0.2. Workflow do Krakatoa.

0.4.3 haRVey

haRVey ´e a ferramenta que implementa a t´ecnica de light-weight theorem proving [20, 22]. Tal t´ecnica combina o uso de Binary Decission Diagrams (BDDs) [6, 82, 5] ou SAT-Solvers com o c´alculo de superposi¸c˜ao [65] (no caso implementado pelo E prover [74, 75, 76]) para alcan¸car melhores resultados na verifica¸c˜ao autom´atica de problemas.

O haRVey pode verificar problemas do tipo: τ |= φ, onde τ ´e um conjunto finito de axiomas ax1, ax2, . . . , axn. No caso φ e axi s˜ao f´ormulas da l´ogica de predicados,

com quantificadores. Para mostrar a f´ormula φ ´e v´alida, com respeito a uma teoria

τ, o provador de teoremas utiliza uma prova por refuta¸c˜ao, mostrando que ¬φ ´e n˜ao-satisf´ativel, com respeito a teoria τ.

(21)

0.5 t´ecnicas para a simplificac¸˜ao de teorias 7

A sintaxe dos arquivos de entrada do haRVey ´e bem simples e baseado na linguagem LISP. Ele consiste em duas se¸c˜oes, delimitadas por parˆenteses. A primeira se¸c˜ao corre-sponde a um conjunto (talvez vazio) de formulas, que v˜ao axiomatizar o problema em quest˜ao, e ´e chamada de teoria. A segunda parte do arquivo corresponde `a f´ormula que queremos provar, e ´e chamada de goal. Na Figura 0.3 n´os podemos ver um problema simples representado na sintaxe do haRVey.

(

(forall A I E (= (read (write A I E) I) E))

(forall A I J E (-> (not (= I J)) (= (read (write A I E) J) (read A J)))) )

(->

(= (read r a) (read r b)) (or

(and (= (read r x) (read r a)) (= (read r x) (read r b))) (and (not (= (read r x) (read r a)))

(= (read r x) (read r x))) )

)

Figura 0.3. Um exemplo de arquivo do haRVey.

0.5 T´ECNICAS PARA A SIMPLIFICAC¸ ˜AO DE TEORIAS

Nessa se¸c˜ao ser˜ao apresentadas as t´ecnicas que desenvolvemos, bem como os resultados obtidos, `a partir dos estudos para a redu¸c˜ao da teoria nos problemas relativos `a verifica¸c˜ao de programas Java.

0.5.1 Redu¸c˜ao puramente simb´olica

A t´ecnica puramente simb´olica que n´os desenvolvemos se baseia na id´eia de que, dado um problema a = b, b = c, d= e |= a = c, n´os podemos prova-lo utilizando somente os axiomasa=b eb =c, sem a necessidade do terceiro axioma. A nossa id´eia inicial foi que os axiomas necess´arios para a verifica¸c˜ao de um problema, seriam somente aqueles que contivessem s´ımbolos que fizessem parte do conjunto de s´ımbolos do goal. No entanto essa id´eia n˜ao ´e verdadeira no caso de problemas como a=b, d=c, b=d|=a=c, onde a rela¸c˜ao entre os axiomas e os s´ımbolos ´e indireta.

Para contornar esse problema n´os reformulamos nosso conceito ´e decidimos guardar as informa¸c˜oes sobre o relacionamento existente entre os axiomas. Para alcan¸car isso n´os particionamos a teoria em conjuntos de axiomas relacionados. Dois axiomas Ax1 e Ax2

(22)

ii) existe um axioma oAx3, tal que,Ax1 ρ Ax3 ∧ Ax3 ρ Ax2.

Adicionalmente ´e definido ρ-Axcomo sendo aρ-classe de todos os axiomas relaciona-dos `a Ax.

Agora suponha um s´ımbolo s, e um conjunto de axiomas associados a s (denotado porχs). Ses aparece no axioma Axi, ent˜ao o novo valor deχsvai serχs ∪ ρ-Axi, se n˜ao

χs ´e deixado sem mudan¸cas. Depois de termos terminado de passar todos os axiomas da

teoria, a semˆantica de um s´ımbolo s ´e definida pelo conjunto χs de axiomas.

Com isso, se n´os temos de mostrar que uma f´ormula φ ´e valida, com respeito a uma dada teoria τ, ´e suficiente que consideremos a uni˜ao dasρ-classes de axiomas de χs, para

todo s´ımbolo s aparecendo emφ.

0.5.2 Elimina¸c˜ao de quantificadores

A id´eia para a t´ecnica de elimina¸c˜ao de quantificadores veio do fato que, alguns ex-perimentos com o haRVey, demonstraram que o mesmo n˜ao apresentava resultados satis-fat´orios quando trabalhando com uma grande quantidade de equivalˆencias em conjunto com quantificadores universais.

Nosso objetivo com essa t´ecnica foi ent˜ao tentar reduzir ao m´aximo poss´ıvel o n´umero de ocorrˆencias de equivalˆencias em um dado problema, eliminando-as e substituindo qual-quer ocorrˆencia do seu lado esqual-querdo pelo valor equivalente do lado direito.

Apesar de ser uma id´eia simples, a sua implementa¸c˜ao esbarrou em diversos problemas, que implicaram em restri¸c˜oes para sua utiliza¸c˜ao.

A primeira preocupa¸c˜ao que n´os tivemos com essa abordagem foi com a ocorrˆencia de casos como:

a↔b b↔c c↔a

que gerariam substitui¸c˜oes recursivas (e infinitas). Felizmente, no nosso caso, esse tipo de problema n˜ao ocorre devido ao algoritmo que utilizamos para recuperar as

informa¸c˜oes de substitui¸c˜oes (o algoritmo de uni˜ao-busca).

Um outro problema relativo `a recursividade pode ser representado pela seguinte ex-press˜ao: (forall U V (<-> (f U) (g V (f U)))). Nesse caso n´os temos uma ocorrˆencia do termo do lado esquerdo no outro lado da equivalˆencia, o que tamb´em geraria substitui¸c˜oes recursivas. Nesse caso n´os decidimos simplesmente ignorar essas ocorrˆencias, e manter as equivalˆencias sem altera¸c˜oes.

(23)

0.5 t´ecnicas para a simplificac¸˜ao de teorias 9

momento n´os decidimos deixar esse crit´erio como uma op¸c˜ao a ser escolhida pelo usu´ario para cada problema.

No entanto essas restri¸c˜oes n˜ao foram suficientes para nos garantir completude que desejavamos, e por isso decidimos estender as restri¸c˜oes para a substitui¸c˜ao. Agora, al´em dos crit´erios anteriores, para uma equivalˆencia ser considerada para substitui¸c˜ao ela tem de satisfazer a seguinte conjectura:

Conjectura 0.1 Se um axioma ´e uma equivalˆencia universalmente quantificada, tal que um dos seus lados ´e um ´atomo, tal que, todas as vari´aveis nele s˜ao universalmente quan-tificadas, n´os podemos eliminar esse axioma, e substituir todas as instˆancias do ´atomo pelo outro lado da equivalˆencia, fazendo as devidas substitui¸c˜oes de vari´aveis.

Com isso se tiv´essemos um equivalˆencia(forall U V (<->(f U V) (g a b))), n´os ir´ıamos substituir qualquer ocorrˆencia def por(g a b). Assim, se tiv´essemos uma express˜ao(and (f (h b) (h c)) (h d)), ela se tornaria (and (g a b) (h d)).

Adicionalmente a partir desse momento n´os tamb´em passamos a considerar o lado direito de uma equivalˆencia como candidato para a substitui¸c˜ao, caso o lado esquerdo n˜ao possa ser usado.

0.5.3 Estrutura¸c˜ao da teoria

O desenvolvimento dessa t´ecnica ´e baseado no trabalho de Reif e Schellhorn [72], onde s˜ao descritos os passos necess´arios para se trabalhar com grandes teorias, utilizando teorias estruturadas (no caso ´e utilizada a ferramenta KIV, que possui uma linguagem de entrada similar a das especifica¸c˜oes alg´ebricas).

Reif e Schellhorn dividem essa t´ecnica em duas partes:

i) Elimina¸c˜ao dos enriquecimentos desnecess´arios; ii) Elimina¸c˜ao dos axiomas desnecess´arios;

A segunda parte dessa abordagem j´a ´e realizada pela nossa abordagem puramente simb´olica (Se¸c˜ao 0.5.1). A primeira parte se baseia no conceito de hierarquias persistentes, ou seja, se temos uma especifica¸c˜ao SPEC, que enriquece MSPEC com um conjunto de axiomas ∆, e uma f´ormula φ. Se φ cont´em somente s´ımbolos presentes em MSPEC, ent˜ao, se φ ´e verdadeira em SPEC, ent˜ao ela tamb´em ser´a verdadeira em MSPEC. Com isso n´os podemos eliminar todos os ∆ axiomas acrescentados por SPEC de nossa teoria. Para implementar essa estrat´egia de redu¸c˜ao n´os implementamos o algoritmo dado por Reif e Schellhorn, que se baseia em quatro crit´erios:

i) crit´erio da minimalidade: encontrar uma especifica¸c˜ao m´ınima MSPEC que con-tenha todos os s´ımbolos presentes em sigφ.

(24)

(

[(theory [theory name]

(extends [extended theory]*) (axioms [axiom]*)

)]* )

[goal formula]*

Figura 0.4.Nova sintaxe do haRVey.

iii) crit´erio da especifica¸c˜ao: em uma especifica¸c˜ao elementar, o crit´erio acima tamb´em pode ser usado para determinar se uma opera¸c˜ao definida sobre essa especifica¸c˜ao, ´e hierarquicamente persistente;

iv) crit´erio da recursividade: os trˆes crit´erios anteriores podem ser aplicados recursiva-mente, at´e o conjunto de axiomas se estabilizar;.

Adicionalmente, para que pud´essemos escrever especifica¸c˜oes que sejam hierarquica-mente persistentes, n´os tivemos de mudar a sintaxe dos arquivos de entrada do haRVey, para uma formato que lembrasse as especifica¸c˜oes alg´ebricas. A nova sintaxe pode ser vista na Figura 0.4.

0.5.4 Resultados experimentais

Para testar o real impacto dessas t´ecnicas para a verifica¸c˜ao de aplica¸c˜oes Java n´os usamos como base um conjunto de quatro classes (Lesson1, Arrays, Purse e Flag) que acompanham a distribui¸c˜ao do Krakatoa [56].

At´e o presente momento n˜ao foram realizados testes com aplica¸c˜oes JavaCard reais, por dois motivos: i) a n˜ao disponibilidade de applets JavaCard que se adequem `as re-stri¸c˜oes apresentadas pelo Krakatoa; ii) at´e o momento a verifica¸c˜ao dos exemplos em Java (teoricamente mais simples que applets reais), n˜ao se deu de forma 100% satisfat´oria, e por isso n˜ao nos pareceu interessante partir para o teste de aplica¸c˜oes mais complexas;

Os resultados dos experimentos s˜ao exibidos nas Tabelas 0.1 a 0.4. A Tabela 0.1 mostra os resultados do n´umero de obriga¸c˜oes de prova verificadas, usando a sintaxe original do haRVey, com cada uma das t´ecnicas que desenvolvemos. Nesse caso a primeira coluna mostra quais t´ecnicas foram aplicadas, a segunda o n´umero de obriga¸c˜oes que foram verificadas, a terceira o n´umero de obriga¸c˜oes que n˜ao se pode decidir, a quarta quantas obriga¸c˜oes geraram um time out (para um tempo de 30 segundos), e a ´ultima o tempo total que a verifica¸c˜ao levou (para as obriga¸c˜oes verificadas e que n˜ao puderam ser decididas). A Tabela 0.2 mostra o tamanho da teoria ap´os o uso de cada uma das t´ecnicas de redu¸c˜ao para cada um dos problemas.

(25)

0.5 t´ecnicas para a simplificac¸˜ao de teorias 11

Verificado N˜ao pode decidir Timed out Tempo de prova

normal 14 0 40 1.821

eql 14 0 40 1.632

tailor 14 0 40 1.684

eqf 14 0 40 1.575

eql + tailor 15 2 37 1.917

eqf + tailor 15 2 37 1.862

Tabela 0.1. Resultados iniciais.

Problema original tailor eql eqf eql + tailor eqf + tailor

Lesson1 79 60 55 51 48 44

Arrays 79 59 55 51 47 43

Purse 79 59 55 51 47 43

Flag 76 60 56 51 49 44

Tabela 0.2.Tamanho das teorias ap´os aplica¸c˜oes das t´ecnicas.

Um ponto importante que foi levantado durante esses experimentos foi um problema apresentado pela ferramenta que implementa o calculo por superposi¸c˜ao, o E prover. O E prover utiliza uma s´erie de heur´ısticas para verificar cada problema e decidir qual estrat´egia utilizar na sua resolu¸c˜ao. O que ocorreu foi que durante nossos testes o E prover se mostrou extremamente sens´ıvel diante da varia¸c˜ao da estrutura de um problema. `As vezes a remo¸c˜ao de um axioma (n˜ao necess´ario) da teoria poderia mudar a heur´ıstica escolhida pelo E prover, e com isso mudar a resposta do problema (gerandotime outs ou fazendo um problema aparecer como n˜ao decidivel).

Para avaliar o impacto dessas heur´ısticas nos nossos problemas n´os decidimos refazer todos os experimentos fixando uma heur´ıstica a ser utilizada. Para isso n´os escolhemos, dentre os problemas que puderam ser verificados, a heur´ıstica que foi mais utilizada, e for¸camos o E prover a utiliz´a-la sempre, independente do problema. O resultado disso pode ser visto na Tabela 0.5.

Como pode ser visto a heur´ıstica fixa de fato nos deu melhores resultados (cerca de 20% melhores do que permitindo que o E prover escolha as heur´ısticas). Essas resultados nos mostram que ainda existe muito trabalho a ser feito, numa integra¸c˜ao melhor do

Verificado N˜ao pode decidir Timed out Tempo de prova

normal 24 1 29 2.340

eql 23 2 29 2.243

tailor 24 1 29 2.302

eqf 23 2 29 2.208

eql + tailor 23 2 29 2.253

eqf + tailor 23 2 29 2.218

(26)

Problema original tailor eql eqf eql + tailor eqf + tailor Lesson1 5 - 6 5 - 6 3 - 4 2 - 3 3 - 4 2 - 3

Arrays 15 - 18 15 - 18 12 - 15 10 - 13 12 - 15 10 - 13 Purse 14 - 30 14 - 30 11 - 27 10 - 23 11 - 27 10 - 23 Flag 13 - 23 13 - 23 12 - 22 9 - 18 12 - 22 9 - 18

Tabela 0.4. Tamanho das teorias usando a teoria estruturada.

E prover com o haRVey, ou mesmo nos crit´erios que o E prover usa para escolher suas heur´ısticas.

Verificado N˜ao pode decidir Timed out Tempo de prova

normal 29 4 21 41.757

eql 28 5 21 41.861

tailor 29 4 21 42.354

eqf 28 5 21 27.830

eql + tailor 28 5 21 42.771

eqf + tailor 28 5 21 27.946

Tabela 0.5.Resultados obtidos com a heur´ıstica fixa.

0.6 CONCLUS ˜OES E TRABALHOS FUTUROS

O nosso trabalho se concentrou no estudo de t´ecnicas para a redu¸c˜ao de teorias. Tais t´ecnicas se mostraram de extrema valia nos casos estudados, e achamos que elas devem ser consideradas como parte vital em qualquer situa¸c˜ao onde se esteja trabalhando com teorias grandes (o que ´e comumente o caso). O uso de tais t´ecnicas nos permitiu ganhos de at´e 100% no n´umero de obriga¸c˜oes verificadas, e a obten¸c˜ao de teorias, em m´edia, cinco vezes menores que as originais.

Tais resultados tamb´em serviram para demonstrar que uma verifica¸c˜ao totalmente autom´atica de programas Java especificados em JML ´e poss´ıvel com a utiliza¸c˜ao do haRVey. Nossos estudos tamb´em revelaram um problema com o provador de teoremas utilizando pelo haRVey (o E prover [74, 75, 76]) no que diz respeito `a escolha de heur´ısticas para o processo de verifica¸c˜ao. Tal problema demonstra a necessidade de um estudo mais detalhado em coopera¸c˜ao com os autores do E prover.

0.6.1 Trabalhos futuros

Os pr´oximos passos necess´arios para tornar o conjunto de ferramentas o mais au-tom´atico e completo poss´ıvel incluem:

• Melhor esquema para a determina¸c˜ao de heur´ısticas;

(27)

0.6 conclus˜oes e trabalhos futuros 13

• Adicionar ao Krakatoa suporte para cobrir completamente a sintaxe do Java e de JML;

Adicionalmente, n´os planejamos o estudo (e poss´ıvel inclus˜ao no haRVey) de uma t´ecnica baseada em particionamento, apresentada em [1, 55], que divide os axiomas de uma dada teoria em subconjuntos, baseado na assinatura de cada axioma. Cada um desses subconjuntos ´e adicionado `a obriga¸c˜ao somente quando necess´ario, fazendo com que assim estejamos trabalhando sempre com um conjunto m´ınimo de axiomas.

(28)

INTRODUCTION

The use of formal verification methods can be traced back to the beginning of computer science, with the seminal works of Hoare. The main objective of such methods is to verify if a “model” of a system (being it hardware or software) satisfies certain conditions by having a given attribute. They usually differ from traditional verifications, in the sense that they convey a promise of mathematical certainty, while “normal” verifications, are, usually, based on testing (or simulating, when dealing with hardware). With the increasing size of the systems, the use of tests and simulations has become prohibitively expensive. Current systems are so large that exhaustive coverage is practically impossible. Also, tests can be used only to discover the presence of bugs, and not to prove their absence. To accomplish a full verification of a system, the use of formal (and automated) verification has become of extreme importance. Such verifications became a synonymous of “computer-aided verification”, where the computer is used to speed up the steps of a verification. Generally, formal verification, may be viewed as theorem proving in a given logic, but, in practice, it is divided in various subcategories. Such categories usually offer to the user a trade off between the expressiveness and automation. Such subcategories (and their relative level of expressiveness/automation) can be seen in Figure 1.1.

Figure 1.1.Level of automation/expressiveness (inspired from [46]).

While the verification of models by hand can guarantee a greater expressiveness, it is clear that, even with small systems, this approach can not be effectively used. Following

(29)

1.1 embedded systems and formal verification 15

the manual approach in level of expressiveness, we have the use of proof assistants. Such tools, while not fully automated, can be used to automate some of the steps necessary in a verification. If one wishes full automation, in the expense of expressiveness, he may choose among theorem provers or model checkers. The main difference among them is that, while the later offers a great degree of automation, it can only work over finite systems, while the former can work on infinite ones.

While the use of formal methods for software verification has already been around for many years, offering the possibility to show that a software is free of errors, they generally came at a high cost, demanding considerable mathematical skills to developers and costing many additional hours of development time to assist with discharging proof obligations [14]. Today this scenario has changed, with the advances in formal verification, the rise of computers’ raw power, and the fall of their prices, the costs of software verification are really balanced by the benefits it brings.

But, even with these advances, only a small portion of the market is using the full power of formal verification. Some of the main reasons for this are the belief that only people with considerable mathematical skills can write formal specifications, and the lack of robust tool support. The main fields of the industry that are adopting formal methods are those where the correctness of the software is critical, as, for example, nuclear plants, air control systems and embedded systems.

1.1 EMBEDDED SYSTEMS AND FORMAL VERIFICATION

Embedded systems usually posses small pieces of software that are used as a part of a larger system (like the break system of a car, a cell phone and so on). This kind of systems, are, by nature, more sensible than the systems we are used to work with. First, they can not be “patched” after they have been delivered, or even if they can, the cost to do it would be extremely expensive. This kind of systems need to be done right in the first delivery, and not just that, but they can not be “free of bugs” in the traditional no bugs were found until now sense of the word. These systems need to be completely trustworthy, in the sense that it is (almost) impossible to them to behave incorrectly.

One special case that is getting increasing attention is the use of smart cards. Smart cards are a credit card like piece of plastic with memory and a micro processor on it. Currently they are being used in various countries for storing information of its users, for pre-paid cards, and in cell phones. A problem that the smart cards faced at their beginning was the fact that, while there were various standards that dealt with the physical layer of the card, there were not a standard for the software layer, what lead to a lack of reuse, and the necessity to create new projects always from scratch. One of the technologies responsible for overcoming this is the JavaCard standard. JavaCard is a subset of the Java language, which allows developers to write smart cards applications at a high level, and with all the benefits from the Java language (security, interoperability, etc).

(30)

statements about the programs, and, as JML is a formal language, we can use it to make automatic verifications. Some tools have already been developed with this objective in mind, like Krakatoa, LOOP, Jack, ESC/Java, etc.

The downside of most of these tools is that they usually use a proof assistant to reason about the programs. While this gives them a high degree of correctness, the verification of JML specifications using proof assistants can be very tedious and time consuming task. Other approaches (like ESC/Java) try to bring a full automated decision procedure to the JML world, but to do this it allows itself to be less “precise” than the other tools, by not guaranteeing that it will find all the problems, and stating that it may return false positives.

1.2 OUR APPROACH

In [15] we developed an early study to compare two tools, the ESC/Java [31] (that uses the Simplify [17] theorem prover) and Krakatoa (using the Coq proof assistant [80, 36, 4]). Such tools were used to specify a program written for SASHIMI [40, 41, 42] (a tool to automatically generate embedded systems based on Java programs). While the former is a characterized as being an Extended Static Checker (i.e. a tool to automatically find common mistakes in the source code), the latter is a tool for static verification of the code using a proof assistant for that.

In our experiments we have found strong and weak points in both tools. The first thing that we must note is that ESC/Java is an extended static checker and not a static checker, so, as a design decision, to increase the automation of the tool, it was chosen to leave it unsound and incomplete. The drawback of this is that we may have lots of false negatives and also some errors might possibly be left undetected. On the other hand (part of) the Krakatoa approach to the problem aims to a sound and complete result but with a limited level of automation. So, neither of the tools was, at that time, delivering what day-by-day users would need: reliability and automation.

The objective of our work is then to start the development of techniques, that would allow us to verify JML specifications of JavaCard applets, fully automatically, and with a great degree of confidence. To do this we plan to use the automated theorem prover haRVey. Previous results obtained with it show that it can be used in very different environments, while still reaching a notable level of success. These resulrs were a very encouraging motivation to use the haRVey theorem prover to verify JML specifications, specially when we consider the benefits that would be brought by automatically discharg-ing proofs without the need of human interaction. To accomplish this, we have used the Krakatoa tool to build proof obligations that would be verified using haRVey. Krakatoa is a tool that generates proofs obligations for various theorem provers and proof assistants based on the Java/JML program/specifications. Krakatoa was our tool of choice because Why, the tool responsible for generating the various outputs for Krakatoa, already had support for haRVey, so the transition would be less problematic.

(31)

1.3 next chapters 17

reduction of the size of the theory allow many problems, that could not be verified, to be checked, since it would reduce the search space of the theorem prover. Even problems that can already be verified would benefit with a speed up in the time needed for the verification when reduzing the background theoriy. In our experiments, we discovered that haRVey was having problems trying to prove some basic Java classes that come with the Krakatoa distribution. This was happening because the Krakatoa/Why approach generates proof obligations with a theory composed of a very large set of axioms (mostly of which are not used). So our work has focused by now on developing techniques to provide such sound reduction of the background theory. We will present here three tech-niques we have developed to accomplish this, and how they influence the verification of the problems we had at hand.

1.3 NEXT CHAPTERS

The next chapters of this work are divided as follows.

Chapter 2 will give a brief introduction to the history and concepts behind the func-tionality of smart cards in general and JavaCard specifically, and show why it is the technology of choice for so many developers;

Chapter 3 presents the JML language, that is used to specify Java/JavaCard programs. We will show its underlying concepts, such as design by contract and two tiered approach to specification, as well as its syntax;

Chapter 4 will present the tools with which we are working with, namely, Krakatoa, Why and haRVey, presenting their technology and basic functionality.

Chapter 5 shows the work we have developed so far, and presenting the algorithms we have used to reduce the size of the theory of the Java examples, as well, as the results we have obtained with each of these approaches;

(32)

JAVA BASED APPROACH TO SMART CARDS

Before the appearance of JavaCard all the smart card companies had to design their own proprietary solutions for their cards. With the use of JavaCard, various possibilities were brought, such as the ability to have more than one application running on the same card, interoperability between all manufacturers that use JavaCard and the possibility to dynamically add new functionalities to the card after it is issued (post-issuance). Another major impact of the use of JavaCard is the possibility to use all the power of the object orientation paradigm during the development cycle, and having available the already established base of Java programmers.

In this section, we will present the basic ideas behind the concept of the smart cards in general and of JavaCard in particular, showing the impact and the importance that such language is having on the growth of the “mobile computing” technologies.

2.1 SMART CARDS

2.1.1 History

Today one of the greatest objectives in the computer field is that of mobile computing, trying to bring the usefulness of computers on the go. Some obvious examples of this are PDAs, laptops and smart-phones that offer to their users the ability to load their most important programs and data wherever they are. But one of the most widespread methods for mobile computing is the smart card. Smart cards are different from the more traditional mobile devices in the sense that they work locally, keeping the information and programs always accessible for the user [45]. The smart cards are already being widely used in Europe and USA where they are being employed to store information about medical history or bank account of the owner. But the smart cards proponents aim higher, with the objective to be a centralized medium of information, where it would store all the data about its owner (not only medical and bank info, but also driver license, ID, etc), and eventually all we would need would be just one card that would replace the half-dozen cards that we carry in our wallet nowadays.

The term smart card usually refers to a plastic card (of the size of a credit card) with a chip that holds a micro-processor and a data storage unit. The development on smart cards started back in the 60s, where, in 1968, two German inventors patented their idea of using plastic cards as a carrier for micro chips, but it was not until 1976 that the industry was capable of producing such cards with an acceptable price. In 1981 the first field experiments were conducted around the globe using banks, telepayment and identification cards, among other projects. After that the smart cards usage spread fast with companies like MasterCard, Visa and France T´el´econ adopting it. Today, smart cards are used in a wide variety of applications ranging from building access systems to

(33)

2.1 smart cards 19

electronic payment schemes, from conditional access methods for satellite TV to electronic signature applications, and from loyalty programs to public transportation applications [38], not to mention the use of them in the current GSM mobile phones in the form of SIM cards [66].

As defined in [73] the smart cards can fit into three possible categories, these being:

Memory cards are cards that possess a chip that can store an average of 4KB of in-formation, but do not have a processor inside it. Because of the absence of a processor they must be used with an external reader to access these data and per-form the required operations. The typical usage of memory cards is with pre-paid disposable-cards, like phone cards;

Optical memory cards look like a CD glued on top of a card and can store an average of 4MB of data. As CD-Rs, once the data is written it can not be erased. It main usage is to keep non-changeable information, like medical or driving records;

Microprocessor cards are the ones that are really “smart”, since they do not have just a memory chip, but also a processor that can perform operations on the data stored on the card.

In the rest of our work, we will be focusing on microprocessor cards, and whenever we say smart card we will be referring to them. In the next sections we will present some more details about this kind of card, showing its components, its limitations and the standards that guide the industry of smart cards.

2.1.2 Characteristics of smart cards

A microprocessor smart card differentiates itself from the traditional magnetic strip card and memory card in the sense that while the latter is used just to store information, the former can make computations on that information. The microprocessor card can add, delete, and manipulate information on the card, while a memory-chip card can only undertake a pre-defined operation [38, 73].

The main components of a smart card are: an operating system that controls access to the card’s data and functions; data stored in EEPROM; and RAM for transient results. Typically, the CPU of choice was old 8 bits processors, but nowadays some cards are already shipping with 16 or 32 bits, RISC or CISC CPUs [19]. Some smart cards also offer additional features, such as fingerprint sensors, wireless interface, or even displays. Some cards will not even appear to be a card, such as the JavaRing [38]. The main constraints we face when dealing with these devices are the low-power CPU, low throughput serial I/O and little memory (typically 1-4 KB RAM, 32-128 KB ROM and 16-64 KB Flash RAM) [18].

(34)

may be used in authorization process, such as building access. They can also be contact or contactless. Contact smart cards work by communicating via physical contact between a card reader and the smart card. Contactless smart cards communicate using a radio frequency signal, with a typical range of less than 2 feet [66].

Smart cards do not contain any battery and become active just when inserted in a card reader. When in the reader, the smart card initializes itself and stays in a passive mode waiting to receive a command from the reader (these commands are transferred using the APDU protocol that will be presented in Section 2.1.4). After it receives the command, it makes the necessary processing and sends back the result to the reader.

The typical participants in the life cycle of a smart card are illustrated in Figure 2.1, and are [18]:

Semiconductor manufacturers are in charge of chip design and mass production;

Smart card manufacturers are associated here with smart card software producers and are responsible for embedding issuers’ requirements;

Card issuers traditionally have more business/behavioral considerations while deploy-ing and managdeploy-ing smart card-based solutions;

Service providers design and deploy (under the control of issuers) value-added services; and

Users benefit from those services.

Figure 2.1.Smart card production life cycle (from [18]).

The first smart cards were developed as monolithic systems, that is, all the require-ments for its functionality were already embedded during manufacturing and there was no possibility of reuse. This approach incurred high maintenance costs, and, with the years, the developers came to see that the best approach was to make the cards as modular as possible and add the possibility to dopost issuance, that is, to add new functionalities to the card after it has been shipped. This kind of cards usually rely on a virtual machine, both for portability (a single application can be loaded into several different cards, i.e. relying on different hardware, without needing to be modified) and for security (it is usually easier to prove or ensure the safety with intermediate codes) [18]. With these ideas in mind the life cycle of the smart card software can be seen in Figure 2.2 with each stage described as follows [18]:

(35)

2.1 smart cards 21

Init/Instantiate: is done after the download, depending on the nature of the application (ready-to-run or ready-to-load applications). With this, the application registers itself on the card, and makes any necessary initializations (since the card is always running it is done only once);

Use: after that the application is ready for use by the client.

Figure 2.2.Life cycle of the smart card software (from [18]).

2.1.3 Standards

One of the most known problems for the wide acceptance of smart cards was the lack of a standard. When the smart cards started being mass commercialized, an application developed to run in one card could not run on the other without having to be rewritten from scratch. This is a great problem when considering that if the smart cards are really intended to be used as a unique device for all companies, there should be a standardization for the cards and on the software/platform in which they will run.

The main standards used today come from the International Organization for Stan-dardization (ISO). Those standards rule nearly all smart card features from physical char-acteristics to application management. These standards are under the name of ISO7816-x and cover physical characteristics (ISO 7816-1); contact location and dimension (ISO 7816-2); and electrical signals along with low-level transport (ISO 7816-3) and high-level application (ISO 7816-4) communication protocols (the APDU protocol that will be ad-dressed later). The ISO7816 also addresses other issues such as numbering systems and registration procedures for smart-card applications, taglength-value data structures, en-hanced smart-card commands (mutual authentication, SQL access, and encryption), and more [38, 18, 73].

But the ISO is not the only standard that is on the market, there are also others, such as that from European Telecommunications Standards Institute, Groupe Sp´eciale Mobile subscriber identity module (GSM SIM), EMV Payment System specification by Europay, MasterCard, and Visa, Visa’s Open Platform specification and the international Common Electronic Purse Standard (CEPS) [38, 73].

2.1.4 The APDU protocol

(36)

former is sent by the reader to the card when requesting an operation, and the latter is sent by the card to the reader in response to the request (if no error occurs the card should always send a response APDU, even if it contains no data) [32].

The structure of the command APDU is shown in Figure 2.3. As seen in the figure, the first four fields are always mandatory and their representation is as follows [66]:

CLA (1 byte, required): identifies an application-specificCLAss of instructions. Valid CLA values are defined in the ISO 7816-4 specification:

0x0n, 0x1n: ISO 7816-4 card instructions, such as for file access and security operations

20 to 0x7F: Reserved

0x8n or 0x9n: ISO/IEC 7816-4 format you can use for your application-specific instructions, interpreting ’X’ according to the standard

0xAn: Application- or vendor-specific instructions

B0 to CF: ISO/IEC 7816-4 format you can use for application-specific instruc-tions

D0 to FE: Application- or vendor-specific instructions FF: Reserved for protocol type selection

INS (1 byte, required): indicates a specific INStruction within the instruction class identified by the CLA field (a table showing the possible INS when CLA is 0x0n is shown in [66]).

P1 (1 byte, required): defines aParameter (1) for the instruction, used to qualify the INS field, or for input data.

P2 (1 byte, required): defines an additional Parameter (2) for the instruction, used to qualify the INS field, or for input data.

Figure 2.3. Command APDU (from [66]).

The next three fields are optional and are used when there is need to exchange data with the card. They are defined as follows:

Lc (1 byte, optional): the Length (in bytes) of the data field of the command;

(37)

2.1 smart cards 23

Le (1 byte, optional): the maximum Length (in bytes) of the data field of the expected response.

The response APDU format is given in the Figure 2.4 and has two required fields and one optional. Their meanings are the following:

Data field (variable length, determined by Le in the command APDU, optional): contains the data returned by the applet.

SW1 (1 byte, required): the Status Word 1.

SW2 (1 byte, required): the Status Word 2.

The value of the status words varies depending on the result of the computation, so to indicate if the operation terminated normally or if an error happened. A representation of the possible values for SW1 and SW2 is given in Figure 2.5.

Figure 2.4.Response APDU (from [66]).

Figure 2.5.Status Words response code (from [66]).

(38)

2.2 JAVACARD

2.2.1 History

The adoption of the Java technology in the smart card market has been pushed over the years because of the advantages that it would bring, such as giving the ability to the well established Java community to quickly start developing smart card applications, the possibility to download new “applets” (as JavaCard programs are known) to an already issued card (post-issuance), not to mention Java portability and security. These factors have made Java the language of choice to extend the smart cards possibilities, even considering that it is an interpreted language and could slow down the system [3, 73].

The history of JavaCard [3, 73] begins in 1996 when the first steps to bring the Java technology to smart cards were taken, with the first JavaCard API specification being given by Sun based on the work made by Schlumberger [3, 62]. This first JavaCard Specification was limited only to the description of the general goals and the architecture of JavaCard. In the next year Gemplus and Schlumberger joined forces and founded the JavaCard forum. Still in this year smart card manufacturers such as De La Rue, Bull, and Gieseke & Devrient (G&D) joined the forum and released the version 2.0 of JavaCard specification at the end of 1997. This new version of the specification was a lot more detailed since it contained more details about the API, such as how to access the underlying memory and cryptographic functions and the JavaCard Virtual Machine (JCVM), a smaller and simpler JVM that sheds many of standard Java’s features. Even then the first release of version 2 was still incomplete in the sense that lots of details were still missing leaving most of the design decisions still in the hands of the developers. The result of this was that lots of applets were still incompatible, even at source code level [3].

In 1998 Visa introduced the Visa Open Platform (VOP) smart card specification, defining an architecture for managing applications on multi application smart cards (that is, the possibility to download and install an applet in a secure way). Since the beginning this platform was aimed to the JavaCard products and with security in mind. When, in 1999, Visa opened this standard and renamed it to Open Platform 2.0 neither Sun nor the JavaCard forum had any security platform specified, so Visa’s Open Platform was chosen as the de facto standard for the matter [3].

In 1999, when Sun introduced the JavaCard 2.1 specification, it offered the support for byte code verification using the scheme of code signing [3]. Even then Sun did not claim to completely trust this method and introduced the use of software firewalls. With this, objects are explicitly associated with their owning applets, and additional checks are done in the JCVM to ensure proper access rights for each object. In this version security was also a concern with the cryptographic API being extended to numerous classes. Also, for the first time, any applet could run in any smart card that was compliant with the JC2.1 specification using Converted Applets (CAP).

(39)

2.2 javacard 25

continue to be the dominating technology with respect to high-end microprocessor-based smart cards [33]. To follow this increasing demand there is already work on the specifica-tion of JavaCard 3.0 that aims to bring the JavaCard technology closer to the standard Java. The objective with this is to make a better use of the new hardware technologies (32 bits processors), to enable a wider development of JavaCard by developers already famil-iar with standard Java and to bypass the bottleneck of the specific smart card ISO7816 communication protocols [33].

2.2.2 JavaCard Overview

A JavaCard is a regular smart card in the sense that it conforms to all the smart card standards, the only difference is that it possesses a Java Virtual Machine implemented on its ROM. The JCVM (JavaCard VM) controls the access to all smart card resources, such as memory and I/O, and thus essentially serves as the smart card’s operating system. The JCVM is able to run applets that were written in a subset of the full Java language. Since the processing and storage power of smart cards is a lot inferior when compared to desktops, some restrictions needed to be made in the JavaCard design. So some features present in the standard Java were wiped out of JavaCard. The main unsupported components, for JC2.0, as stated in [79, 66], are:

Dynamic Class Loading: A JavaCard system is not able to load classes dynamically. Objects are created in the card either into the card’s ROM during manufacturing or through post-issuance;

Security Manager: The security model of JavaCard systems differs from standard Java in fairly significant ways. Language security policies are implemented by the virtual machine. There is no Security Manager class which makes policy decisions on whether to allow operations;

Threads: The JavaCard Virtual Machine does not support multiple threads of control;

Cloning: JavaCard does not support cloning of objects. JavaCard’s version of class Object does not implement a clone() method, and there is no Clonable interface provided.

Garbage Collection & Finalization: Usually the JCVM does not implement a garbage collector, since objects once created will live “forever” in the card. Explicit dealloca-tion of object is forbidden, like in the regular version of Java. The methodfinalize() of the classes will not be necessarily called, and thus the developers should not rely on this behavior.

(40)

The main package of the JavaCard API is the javacard.framework. This package defines the interfaces, classes, and exceptions that compose the core JavaCard Framework. It defines important concepts such as the Personal Identification Number (PIN), the Application Protocol Data Unit (APDU), the JavaCard applet (Applet), the JavaCard System (JCSystem), and a utility class. It also defines various ISO7816 constants and various JavaCard-specific exceptions. Other packages that are related to the JavaCard are java.io,java.lang,java.rmi andjavacard.security. A complete list of these classes can be seen in [66].

The VM for the JavaCard platform is implemented in two parts, one external to the card and the other running inside the card itself. The on-card virtual machine is the JavaCard Runtime Environment (JCRE) and is responsible for interpreting the bytecode, managing classes and objects, and so on. The external part of the VM is a development tool, typically referred to as the JavaCard Converter tool, which loads, verifies, and further prepares the Java classes in a card applet for on-card execution. The output of the converter tool is a Converted Applet (CAP) file, which contains all the classes in a Java package in a loadable, executable binary representation. The converter is responsible for verifying if classes conform to the JavaCard specification [66].

After an applet has been developed and converted to the CAP format it is ready to be loaded into the card. The life cycle of an applet after loading in the card can be expressed by the methods it uses to communicate with the JCVM and the external world. Those methods are install, register, select, deselect and process. The install method is called when the applet is first downloaded in the card and its main function is to create an instance of the applet that will be used for the rest of the life of the card. The install function must call the method register, which is responsible for registering the applet inside the card, by assigning an AID (Applet IDentifier) to this instance. The AID is a unique number that identifies each applet inside a card [32].

The next methods deal with the communication of the card with the external world. As the JavaCard is an environment with multiple applications, each applet must be told explicitly when the communication starts and finishes. This is done using the methods select and deselect. When the reader wants to communicate with a certain applet, its select method is called and it must make any preparations to start communicating. When the communication ends the deselect method is called and the applet is no longer nec-essary. It is important to note that the applet is not destroyed and recreated at each call. The only time an object may be created in the card is during the execution of the install method, and then it is never destroyed. The communication itself is made using the method process, which has as parameter an APDU object coming from the reader. The applet receives this APDU, processes it, to find out which actions it needs to do, makes the necessary actions to fulfill its objective and then sends a response to the card using the method sendBytes of the APDU class.

2.2.3 A JavaCard example

Imagem

Figura 0.1. Esquema do workflow do Why.
Figura 0.2. Workflow do Krakatoa.
Figura 0.3. Um exemplo de arquivo do haRVey.
Figura 0.4. Nova sintaxe do haRVey.
+7

Referências

Documentos relacionados

O conhecimento dos processos que regulam a estabilização da matéria orgânica do solo (MOS) é necessário para predizer as alterações nos estoques de C com

didático e resolva as ​listas de exercícios (disponíveis no ​Classroom​) referentes às obras de Carlos Drummond de Andrade, João Guimarães Rosa, Machado de Assis,

i) A condutividade da matriz vítrea diminui com o aumento do tempo de tratamento térmico (Fig.. 241 pequena quantidade de cristais existentes na amostra já provoca um efeito

Peça de mão de alta rotação pneumática com sistema Push Button (botão para remoção de broca), podendo apresentar passagem dupla de ar e acoplamento para engate rápido

No campo, os efeitos da seca e da privatiza- ção dos recursos recaíram principalmente sobre agricultores familiares, que mobilizaram as comunidades rurais organizadas e as agências

Para tanto foi realizada uma pesquisa descritiva, utilizando-se da pesquisa documental, na Secretaria Nacional de Esporte de Alto Rendimento do Ministério do Esporte

Devido à grande diferença do prognóstico de uma hiperplasia nodular (que é frequentemente bom) e sua abordagem (que varia desde uma simples observação até uma

Ousasse apontar algumas hipóteses para a solução desse problema público a partir do exposto dos autores usados como base para fundamentação teórica, da análise dos dados