Escolar Documentos
Profissional Documentos
Cultura Documentos
Natal-RN
2012
U NIVERSIDADE F EDERAL DO R IO G RANDE DO N ORTE
C ENTRO DE C IÊNCIAS E XATAS E DA T ERRA
P ROGRAMA DE P ÓS - GRADUAÇÃO EM S ISTEMAS E C OMPUTAÇÃO
Orientador:
Prof. Dr. David Boris Paul Déharbe
Natal-RN
2012
Agradecimentos
A pesquisa que deu origem a este trabalho teve início no ano de 2005, quando tive a oportu-
nidade de ingressar como bolsista de iniciação científica, sob orientação de Anamaria Moreira
e colaboração de David Déharbe. A eles o meu especial agradecimento, pelo conhecimento ad-
quirido e pela amizade durante todos esses anos. Com eles aprendi bastante e amadureci como
pesquisador e como pessoa.
À Vanessa, minha esposa, que esteve ao meu lado desde o início, pelo companheirismo,
respeito e amor. Você pacientemente suportou meu mal-humor e, dia após dia, me deu forças
para seguir adiante, mesmo em face das dificuldades e angústias no decorrer da construção da
tese. Apesar de não compreender a parte técnica do trabalho, as suas revisões criteriosas no
texto foram de fundamental importância.
Agradeço também a todos os que colaboraram com o trabalho, dentre os quais destaco Kátia
Moraes, Thiago Dutra, Giuliano Vilela e Simone Santos. O auxílio e a troca de conhecimentos
com vocês foi inestimável.
Aos professores membros externos da banca, Augusto Sampaio, Marcel Oliveira e Rohit
Gheyi, pelas observações que ajudaram a melhorar o resultado final deste trabalho, e que servi-
rão de base para o seu aprimoramento daqui em diante.
Aos colegas (amigos) da pós-graduação, Cleverton, Plácido, Isaac, Macilon, Fred, dentre
tantos outros, pelos momentos de descontração, de compartilhamento de ideias e de ajuda em
diversos momentos. Em especial agradeço a Cleverton Hentz, pelo apoio no desenvolvimento
inicial da especificação da tradução em ASF+SDF.
Por fim, agradeço aos amigos e alunos do IFRN - câmpus Currais Novos. Nesses dois
anos e meio na instituição, conquistei a amizade e o respeito de todos e pude crescer como ser
humano e professor. Um abraço especial a Miguel Kolodiuk, Carlos “Stiff” Gustavo e Álvaro
Hermano, amigos com os quais sei que posso contar por toda a vida.
Resumo
As aplicações para smart cards representam um mercado que cresce a cada ano. Nor-
malmente, essas aplicações manipulam e armazenam informações que requerem garantias
de segurança, tais como valores monetários ou informações confidenciais. A qualidade e a
segurança do software para cartões inteligentes pode ser aprimorada através de um processo
de desenvolvimento rigoroso que empregue técnicas formais da engenharia de software. Neste
trabalho propomos o método BSmart, uma especialização do método formal B dedicada ao
desenvolvimento de aplicações para smart cards na linguagem Java Card. O método descreve,
em um conjunto de etapas, como uma aplicação smart card pode ser gerada a partir de
refinamentos em sua especificação formal. O desenvolvimento é suportado por um conjunto de
ferramentas, automatizando a geração de parte dos refinamentos e a tradução para as aplicações
Java Card cliente (host) e servidora (applet). Ressalta-se que o processo de especificação e re-
finamento descrito no método foi formalizado e verificado utilizando o próprio método B, com
o auxílio da ferramenta Atelier B [Cle12a]. Destaca-se que a aplicação Java Card é traduzida a
partir do último passo de refinamento, denominado de implementação. A especificação dessa
tradução foi feita na linguagem ASF+SDF [BKV08]. Inicialmente, descreveu-se as gramáticas
das linguagens B e Java (SDF) e, em uma etapa posterior, especificou-se as transformações
de B para Java Card através de regras de reescrita de termos (ASF). Essa abordagem foi um
importante auxílio durante o processo de tradução, além de servir ao propósito de documentá-
lo. Cumpre destacar a biblioteca KitSmart [Dut06, San12], componente essencial ao método
BSmart, que inclui modelos em B de todas as 93 classes/interfaces da API Java Card na
versão 2.2.2, dos tipos de dados Java e Java Card e de máquinas que podem ser úteis ao
especificador, mas que não estão presentes na API padrão. Tendo em vista validar o método,
seu conjunto de ferramentas e a biblioteca KitSmart, procedeu-se com o desenvolvimento, se-
guindo o método BSmart, de uma aplicação de passaporte eletrônico. Os resultados alcançados
neste trabalho contribuem para o desenvolvimento smart card, na medida em que possibi-
litam a geração de aplicações Java Card completas (cliente e servidor) e menos sujeitas a falhas.
Smart card applications represent a growing market. Usually this kind of application
manipulate and store critical information that requires some level of security, such as financial
or confidential information. The quality and trustworthiness of smart card software can
be improved through a rigorous development process that embraces formal techniques of
software engineering. In this work we propose the BSmart method, a specialization of the
B formal method dedicated to the development of smart card Java Card applications. The
method describes how a Java Card application can be generated from a B refinement process
of its formal abstract specification. The development is supported by a set of tools, which
automates the generation of some required refinements and the translation to Java Card client
(host) and server (applet) applications. With respect to verification, the method development
process was formalized and verified in the B method, using the Atelier B tool [Cle12a]. We
emphasize that the Java Card application is translated from the last stage of refinement, named
implementation. This translation process was specified in ASF+SDF [BKV08], describing the
grammar of both languages (SDF) and the code transformations through rewrite rules (ASF).
This specification was an important support during the translator development and contributes
to the tool documentation. We also emphasize the KitSmart library [Dut06, San12], an essential
component of BSmart, containing models of all 93 classes/interfaces of Java Card API 2.2.2,
of Java/Java Card data types and machines that can be useful for the specifier, but are not part
of the standard Java Card library. In other to validate the method, its tool support and the
KitSmart, we developed an electronic passport application following the BSmart method. We
believe that the results reached in this work contribute to Java Card development, allowing the
generation of complete (client and server components), and less subject to errors, Java Card
applications.
Keywords: Smart Cards, Java Card, B Formal Method, Refinement, Formal Development,
Code Generation.
Sumário
Lista de Figuras
1 Introdução p. 16
1.1 Justificativa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . p. 18
1.3 Objetivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . p. 21
2 Java Card p. 26
3 O Método Formal B p. 38
3.2.2 Implementação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . p. 50
4 O Método BSmart p. 56
5.1.1 Símbolos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . p. 88
5.2 ASF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . p. 91
5.3.3 Predicados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . p. 98
5.3.4 Termos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . p. 99
7.8 Verificação do Refinamento entre Especificação Abstrata e o Modelo Java Cardp. 155
Referências p. 182
2.3 Um applet Java Card APDU para bilhetagem eletrônica - definição de atri-
butos e métodos herdados da classe Applet. . . . . . . . . . . . . . . . . . . p. 31
4.2 Definição do tipo Java e das propriedades para a formalização dos compo-
nentes da especificação abstrata. . . . . . . . . . . . . . . . . . . . . . . . . p. 60
4.4 Uma visão dos artefatos que compõem o desenvolvimento da aplicação Java
Card do lado cartão (não inclui aplicação cliente). . . . . . . . . . . . . . . . p. 61
4.5 Versão “Java Card” da máquina J_App. . . . . . . . . . . . . . . . . . . . . p. 62
4.6 Definição do tipo Java Card e das propriedades para a formalização dos com-
ponentes da especificação concreta. . . . . . . . . . . . . . . . . . . . . . . p. 63
4.20 Retrenchment Java Card da especificação abstrata principal J_App (Fig. 4.2). p. 82
5.12 Regras de reescrita para uma sequência de zero ou mais cláusulas . . . . . . . p. 101
5.19 Regra auxiliar para tradução dos parâmetros das operações . . . . . . . . . . p. 105
5.22 Reescrita das instruções skip, begin-end e becomes equal to. . . . . . . . . . p. 106
5.23 Reescrita das instruções chamada de operação e definição de variável local. . p. 107
6.3 Definição do estado e algumas operações da biblioteca para sequência de byte. p. 115
6.4 Quantidade de classes por pacote na API 2.2.2. Fonte [San12]. . . . . . . . . p. 116
1 Introdução
Nos últimos anos, os serviços fornecidos pelas aplicações para smart cards vêm se tornando
cada vez mais presentes no cotidiano de boa parte da população mundial, em uma vasta gama
de setores, tais como, finanças, transporte público, Internet e aplicações governamentais. De
acordo com uma pesquisa conduzida pela Eurosmart [Eur12], uma associação de empresas
da indústria smart card que tem por objetivo propor e regular padrões para essa tecnologia,
no ano de 2011, cerca de 6, 3 bilhões de smart cards foram vendidos em todo o mundo. Em
sua maioria, esses cartões foram adquiridos pelos setores de telecomunicações (cartões para a
tecnologia GSM), finanças (cartões de crédito e pagamento) e governo (passaporte e assistência
à saúde). Para o ano de 2012, a associação Eurosmart estima que o número de cartões vendidos
possa ultrapassar a marca de 7 bilhões de unidades.
O passaporte eletrônico brasileiro vem sendo emitido desde o início do ano de 2011, se-
17
Outra interessante aplicação smart card é o registro de identidade civil (RIC), uma solução
segura que irá gradativamente substituir os documentos de identidade (RG). Cada brasileiro
será identificado por um número nacional único, gerado a partir dos seus dados biométricos.
Assim como o passaporte, o RIC contém elementos de identificação pessoal, biométrica e um
certificado digital pessoal no chip smart card. Esse novo documento irá possibilitar uma maior
segurança e menor burocracia na identificação pessoal, permitindo a assinatura de contratos e
documentos por meio eletrônico [dJ12], até mesmo sem a presença física do interessado.
Evidencia-se que uma das formas de se desenvolver aplicações para smart cards é utili-
zar a linguagem nativa do processador do cartão [RE03] ou uma linguagem de alto nível que
compile para um hardware específico. Essa abordagem possui como principal vantagem o fato
do programa desenvolvido ser capaz de ter acesso direto aos recursos do processador. Em
contrapartida, a aplicação mencionada não é diretamente portável para outras arquiteturas e,
normalmente, é mais difícil de codificar e manter do que aquelas desenvolvidas em linguagens
de alto nível.
Em comparação a linguagens nativas, Java Card gera aplicações que demandam um maior
tempo de execução e consomem maiores recursos de processamento e memória. Entretanto,
ela se beneficia das vantagens da linguagem Java padrão, como produtividade, portabilidade,
linguagem segura quanto a tipos, desenvolvimento orientado a objetos e a ampla variedade de
ferramentas disponíveis. O ambiente Java Card ainda fornece benefícios adicionais, dentre os
quais ressalta-se a abstração de toda a camada de protocolos de baixo nível do sistema smart
18
O restante desta introdução é divida nas seções descritas a seguir. A justificativa da tese é
apresentada na seção 1.1. Posteriormente, na seção 1.2, introduz-se o método BSmart. Por sua
vez, a seção 1.3 apresenta os objetivos da tese. Em seguida, a seção 1.4 descreve os trabalhos
que foram publicados durante o desenvolvimento do trabalho. Por fim, a seção 1.5, apresenta
um resumo dos capítulos que se seguem a esta introdução.
1.1 Justificativa
A importância econômica desse mercado em contínua expansão torna evidente uma preocu-
pação no domínio de aplicações para smart cards: a segurança das informações que encontram-
se armazenadas no cartão e que são enviadas ou recebidas no momento de uma transação. Essas
informações, se interceptadas, alteradas, ou removidas, podem causar prejuízos graves ao por-
tador do cartão, como perdas financeiras e a exposição de informações privilegiadas, como
elementos de identificação pessoal, histórico de saúde, etc. A natureza portável dos smart cards
os tornam ainda mais vulneráveis a ataques externos por software mal-intencionado. Essas apli-
cações podem ser instaladas em um cartão com o objetivo de explorar falhas no hardware ou
em qualquer software presente no cartão.
vimento de sistemas, tal como Z [Spi92], B [Abr96] ou Event-B [Abr10], não garante neces-
sariamente que o software desenvolvido (ou parte dele) estará completamente livre de defeitos.
Por outro lado, é um meio de assegurar a correção do seu comportamento de acordo com o que
foi especificado [BH94]. Destaca-se que outro importante incentivo à utilização desses méto-
dos formais reside no fato deles fornecerem um meio de documentação precisa adicional ao
sistema.
Nessa esteira, uma pesquisa conduzida por Lanet [Lan00] concluiu que as aplicações smart
cards constituem-se em um domínio ideal para a adoção de métodos formais. Ele aponta como
principais razões para isso o fato das aplicações e dos sistemas operacionais para smart cards
serem de pequeno porte, a necessidade de segurança e a possibilidade de instalação de múltiplas
aplicações em um mesmo cartão oferecida por tecnologias como Java Card ou MultOS [Mul10].
Conforme discutiu-se anteriormente, essa característica pode ser a porta de entrada para código
mal-intencionado.
Lanet argumenta que os métodos formais podem ser aplicados para reduzir erros no soft-
ware smart card, certificar partes da aplicação em um alto nível de confiabilidade, submetendo-
as a entidades que utilizam-se de processos de certificação como o Common Criteria [Com10],
e para reduzir a necessidade e o custo de testes. A pesquisa de Lanet também evidencia que
o desenvolvimento de componentes reutilizáveis, de metodologias e ferramentas, bem como
a integração de métodos formais com técnicas tradicionais, como a especificação em Unified
Modelling Language (UML), é um meio de minimizar algumas restrições a uso de métodos
formais, como o aumento do tempo de desenvolvimento e a sua adoção, em maior escala, na
indústria.
Nesse sentido, a Verified Software Initiative (VSI) [HMLS09] materializa-se em uma im-
portante contribuição na direção de fornecer maior maturidade aos métodos formais, visando
facilitar e disseminar a sua utilização em software de larga escala. Trata-se de um projeto de
longo prazo que convida toda a comunidade da engenharia de software e métodos formais, as-
sim como parceiros industriais, a contribuir com estudos de caso, teorias, técnicas e ferramentas
para o desenvolvimento de software confiável e, de forma ideal, livre de erros.
Evidencia-se que a presente tese utiliza o método formal B [Abr96] como fundamento
para um método de desenvolvimento de aplicações para smart cards na linguagem Java Card,
denominado de BSmart. O método B possui uma boa utilização, tanto na academia quanto na
indústria, no que concerne à especificação e ao desenvolvimento (com base em refinamentos) de
aplicações e partes de sistemas críticos. A base de ferramentas de suporte ao método também
é bastante rica, possibilitando a verificação de tipos, geração e verificação de obrigações de
prova, animação, geração de código, dentre outras funcionalidades. Além disso, B mostra-se
adequado ao desenvolvimento de aplicações Java Card, por elas serem aplicações de pequeno
porte e possuírem linguagem simples e enxuta.
1.3 Objetivos
O presente trabalho tem por objetivo contribuir com o método BSmart, uma especialização
do método formal B para o desenvolvimento de aplicações smart cards na linguagem Java
Card com maior segurança e confiabilidade. Visando atingir esses requisitos de qualidade, a
tese prioriza a melhoria do processo de desenvolvimento com método através das seguintes
ações:
4. Desenvolvimento de um estudo de caso de uma aplicação smart card “real” tendo em vista
23
Nesta seção descreve-se os trabalhos que foram publicados, desde o início do estudo, em
março de 2008, até o presente momento.
SBES-2008 [MdMJD+ 08]: A ferramenta Batcave para a verificação formal com o método
B A ferramenta Batcave foi desenvolvida por um estudante do grupo de métodos formais da
UFRN e tem por objetivo gerar as obrigações de prova de um módulo B em diversas notações.
Utilizando essa abordagem, o usuário da ferramenta não fica restrito a um provador específico,
de modo que obrigações de prova que poderiam ser trabalhosas de se verificar em um provador,
podem ser facilmente verificadas em outra ferramenta. Neste artigo, o autor desta tese colaborou
com a integração da ferramenta Batcave à primeira versão do ambiente de desenvolvimento
BSmart.
ABZ-2008 [DGM08]: BSmart: a tool for the rigorous development of Smart Card ap-
plications Apresentou-se a versão inicial da ferramenta BSmart na sessão de ferramentas da
conferência Abstract Machine, B and Z (ABZ).
ABZ-2010 [GDMM10] - Applying the B method for the Rigorous Development of Smart
Card Applications Este artigo, apresentado na conferência ABZ de 2010, descreve a for-
malização do método BSmart, a geração de código da API para a aplicação host e os módulos
24
Apresenta-se abaixo um resumo dos capítulos da tese que se seguem a esta introdução.
Capítulo 2: Java Card Este capítulo introduz os componentes do ambiente smart card e a
linguagem Java Card. Ao final, demonstra-se o desenvolvimento de uma aplicação Java
Card simples, porém completa. A aplicação cartão é desenvolvida tanto em Java Card
APDU, versão em que se manipulam diretamente os pacotes para troca de dados entre
as aplicações, quanto em Java Card RMI, em que a comunicação é feita por invocação
remota de métodos (RMI). No caso do cliente (aplicação host), utilizou-se a API smart
Card I/O para realizar a comunicação com a aplicação cartão.
Capítulo 7: Estudo de Caso O estudo de caso do passaporte eletrônico é descrito neste ca-
pítulo. Inicialmente, descreve-se a aplicação e os seus componentes mais importantes
(estrutura de dados e protocolos). Posteriormente, a especificação e desenvolvimento da
aplicação seguindo o método BSmart é detalhada.
Capítulo 8: Trabalhos Relacionados Os trabalhos que estão no escopo do tema da tese são
descritos e comparados. São relatados trabalhos em diversas áreas, tais como, verifica-
ção, geração de código, políticas de segurança e o estado da arte em ferramentas para
desenvolvimento formal de software.
2 Java Card
É importante observar que Java Card [Che00] é uma das principais linguagens utilizadas
para desenvolvimento de aplicações para smart cards. Java Card é uma versão restrita e otimi-
zada da plataforma Java, tendo em vista possibilitar que dispositivos com baixa capacidade de
processamento e memória possam armazenar e executar pequenas aplicações. O desenvolvedor
que usa Java Card beneficia-se de muitas das características de Java, tais quais portabilidade,
linguagem segura quanto a tipos, desenvolvimento orientado a objetos e disponibilidade de fer-
ramentas. Todo esse suporte possibilita uma maior rapidez no ciclo de desenvolvimento, teste
e instalação de aplicações. Dessa forma, é possível obter melhores ganhos quanto ao custo e ao
tempo na produção de software para smart cards.
O principal componente da plataforma Java Card (Figura 2.1) é o seu ambiente de exe-
cução, o Java Card Runtime Environment (JCRE), composto por uma Máquina Virtual Java
27
Card (JCVM), uma pequena API e, normalmente, por classes fornecidas pelo fabricante do
cartão [Che00]. O JCRE atua como um pequeno sistema operacional, sendo responsável pelo
controle do ciclo de vida da aplicação e de aspectos de segurança e gerenciamento de recursos.
Ressalta-se que este capítulo aborda os aspectos da plataforma Java Card relevantes ao
presente trabalho. Inicialmente, na seção 2.1, detalha-se a comunicação entre os componentes
do sistema smart card, com foco no protocolo APDU. O processo geral de desenvolvimento de
aplicações Java Card é apresentado na seção 2.2. A classe applet, componente que fornece os
serviços da aplicação, é descrita na seção 2.3. Por fim, a seção 2.4 apresenta a aplicação host
que utiliza os serviços do applet.
A aplicação smart card possui uma arquitetura cliente-servidor, sendo o componente ser-
vidor interno ao cartão, e o cliente, externo. A aplicação servidora, denominada applet, provê
os serviços que são requisitados pela aplicação cliente, conhecida na literatura como aplicação
host, que reside em um computador ou terminal eletrônico. Entre essas duas aplicações há um
dispositivo de hardware, chamado de leitor ou Card Acceptance Device (CAD), responsável
por fornecer energia ao chip do cartão e o meio físico para que o host e o applet possam se
28
comunicar [Ort03a], o que pode ser feito por contato elétrico (cartões por contato) ou por rádio
frequência (cartões sem contato).
A resposta APDU é dividida em um campo data para se enviar dados na resposta e dois
bytes SW1 e SW2, que são sempre retornados contendo o status do processamento do comando.
Uma execução sem falhas retorna o status 0x9000 (SW1=90 e SW2=00). Qualquer outro código
de status indica que ocorreu uma exceção durante o processamento da requisição.
Ressalta-se que uma aplicação Java Card pode ser desenvolvida de duas maneiras. Na
primeira, de mais baixo nível, o desenvolvedor tem que lidar diretamente com o aspecto de co-
municação smart card por meio do protocolo APDU. Na outra, a comunicação entre a aplicação
host e o applet é efetivada através de invocação remota de métodos (RMI), sendo o protocolo
APDU abstraído para o desenvolvedor, que tem que lidar apenas com objetos [Ort03b]. Para
diferenciar, daqui em diante no texto, os dois tipos de aplicações, denominar-se-á o primeiro de
29
O processo completo de desenvolvimento de uma aplicação Java Card, em suas duas ver-
sões, pode ser dividido em quatro etapas, a saber:
A compilação do applet é feita da mesma maneira que qualquer classe Java. A etapa de
teste é opcional e pode ser feita por meio de simuladores do ambiente de execução Java Card
disponibilizados pela Sun em seu Java Card Development Kit. No kit de desenvolvimento
também encontram-se conversores que empacotam o applet e suas classes em um formato para
ser instalado no cartão.
A seção 2.3 a seguir apresenta o desenvolvimento de aplicações Java Card nas versões
APDU e RMI através de um exemplo de aplicação de bilhetagem eletrônica. Posteriormente,
na seção 2.4, detalha-se o desenvolvimento da aplicação cliente.
Nas versões iniciais da plataforma existia apenas um único meio de se desenvolver um ap-
plet, no qual o desenvolvedor lidava diretamente com as estruturas do protocolo APDU. No
entanto, a partir da versão 2.2, foi disponibilizado um applet que utiliza a comunicação por
invocação remota de métodos (RMI), abstraindo os detalhes internos dos protocolos. Por intro-
duzir uma camada adicional, essa última versão costuma ser menos eficiente e, por este motivo,
ainda é menos utilizada que a versão APDU.
Nas subseções a seguir os modelos de aplicação APDU e RMI são exemplificados através
de uma aplicação de bilhetagem eletrônica. O usuário da aplicação dispõe de uma quantidade
de créditos em passagens (atributo balance) que são debitados a cada viagem. Observa-se
que há três tipos de cartão: gratuidade, passagem inteira e estudante, sendo essa informação
armazenada no atributo cardType. Foram implementados três métodos de serviço, são eles
addCredit, debit e getCredits. O primeiro adiciona créditos no cartão, o segundo debita o valor
de uma unidade de crédito de um cartão que não seja de gratuidade e o método getCredits pode
ser utilizado para consultar o saldo atual do cartão.
Nas figuras 2.3, 2.4 e 2.5 apresenta-se o código do applet na versão APDU para a aplicação
de bilhetagem eletrônica Transport. É importante destacar a função de alguns métodos herdados
da classe Applet e que são geralmente implementados na subclasse, são eles, install, process,
select e deselect. Desses, apenas process é de implementação obrigatória, por se tratar de
um método abstrato (abstract). No entanto, o método install, devido a sua importância para
a aplicação, também é normalmente sobrescrito. A introdução dos métodos select e deselect
na subclasse é opcional, uma vez que a implementação herdada é suficiente para permitir a
31
execução da aplicação.
O método install é chamado pelo Java Card Runtime Environment (JCRE) apenas na pri-
meira vez em que o applet é executado. Em uma implementação mínima, deve-se criar uma
instância da classe applet e registrá-la junto ao ambiente de execução, através da chamada a um
dos métodos de registro da classe Applet. Apenas uma instância do applet é registrada, sendo
a gerência dessa instância controlada pelo JCRE. Observa-se que o applet permanece em um
estado inativo após ser registrado, aguardando até que seja selecionado.
Figura 2.3: Um applet Java Card APDU para bilhetagem eletrônica - definição de atributos e
métodos herdados da classe Applet.
O método select é chamado sempre que um applet é requisitado para ser selecionado (apdu
SELECT FILE). A implementação padrão fornecida pela classe Applet retorna true, dessa forma
autorizando o acesso ao applet (a sua seleção para execução). Caso alguma restrição de acesso
tenha que ser imposta antes da seleção do applet, ela deve ser feita em select, que irá autorizar
32
ou não a seleção. Por sua vez, o método deselect do applet selecionado (caso haja algum) é
chamado sempre que um novo applet requisita ao JCRE a sua seleção. Dessa forma, ele pode
ser utilizado para alguma operação de limpeza de memória ou de alteração do estado de algum
atributo antes que o applet em execução seja retirado de seleção.
Uma vez selecionado, o applet encontra-se pronto para receber as requisições aos seus
serviços através do seu método process. Ele recebe do JCRE um objeto APDU, o que permite o
acesso ao buffer APDU, um array de bytes contendo os campos do comando que foram enviados
na requisição pela aplicação host. Cada elemento do array contém a informação de um campo
específico do comando APDU, sendo o índice desses campos no array facilmente acessado
através de constantes presentes na interface javacard.framework.ISO7816. Observa-se que, por
meio da instrução (INS) do buffer, a requisição é direcionada ao serviço apropriado, que obtém
os dados necessários para a sua execução diretamente dos campos p1, p2 ou data contidos no
array.
Um método que recebe algum dado encapsulado no campo data do comando APDU deve
invocar o método setIncomingAndReceive para que o JCRE torne esse dado adicional acessível
através do buffer APDU recebido. O número de bytes recebidos é retornado pelo método setIn-
comingAndReceive e pode ser usado para verificar se esse número é igual ao número de bytes
que se esperava receber. Como exemplo, na figura 2.4, tem-se a implementação do método
addCredit, que deve receber a informação da quantidade de créditos que serão adicionados ao
cartão.
p u b l i c v o i d a d d C r e d i t (APDU apdu ) {
b y t e [ ] b u f f e r = apdu . g e t B u f f e r ( ) ;
s h o r t c r = ( s h o r t ) U t i l . m a k e S h o r t ( ( b y t e ) b u f f e r [ ISO7816 . OFFSET_P1 ] ,
( b y t e ) b u f f e r [ ISO7816 . OFFSET_P2 ] ) ;
s h o r t sum = ( s h o r t ) ( b a l a n c e + c r ) ;
short c t = ( short ) cardType . getCardType ( ) ;
i f ( ! ( c t ! = GRATUITOUS_CARD ) ) {
I S O E x c e p t i o n . t h r o w I t ( EXCEPTIONS . CARD_TYPE_INVALID ) ;
} e l s e i f ( ! ( sum <= 3 2 7 6 7 ) ) {
I S O E x c e p t i o n . t h r o w I t ( EXCEPTIONS . BALANCE_EXCEEDED ) ;
} else i f ( !( cr > 0)) {
I S O E x c e p t i o n . t h r o w I t ( EXCEPTIONS . NEGATIVE_CREDIT ) ;
} else {
b a l a n c e = sum ;
}
}
Caso um método precise enviar alguma informação para a aplicação host ele deve, inicial-
mente, invocar o método setOutgoing, responsável por notificar o JCRE que algo será enviado
no campo data da resposta APDU. O método setOutgoing também retorna o tamanho do dado
que a aplicação host espera receber. Posteriormente, o método setOutgoingLength deve ser cha-
mado para informar o número de bytes a serem enviados. Por fim, deve-se inserir a informação
no buffer apdu. No método getCredits do exemplo (figura 2.5), a variável contendo a informa-
ção da quantidade de créditos restantes no cartão é inserida no buffer apdu através do método
setShort, da classe javacard.framework.Util. Finalmente, através da chamada a sendBytes, a
resposta é enviada.
p u b l i c v o i d g e t C r e d i t s (APDU apdu ) {
b y t e [ ] b u f f e r = apdu . g e t B u f f e r ( ) ;
s h o r t r e s = amount . g e t S h o r t V a l u e ( ) ;
s h o r t l e = apdu . s e t O u t g o i n g ( ) ;
apdu . s e t O u t g o i n g L e n g t h ( ( s h o r t ) 2 ) ;
U t i l . s e t S h o r t ( buffer , ( short ) 0 , ( short ) res ) ;
apdu . s e n d B y t e s ( ( s h o r t ) 0 , ( s h o r t ) 2 ) ;
}
Destaca-se que a API Java Card para Invocação Remota de Métodos (RMI) foi introduzida
somente na especificação Java Card 2.2, consistindo em um subconjunto da API RMI de Java
e classes RMI específicas para Java Card.
No modelo RMI, a aplicação servidora (o applet Java Card) cria e torna acessíveis objetos
que podem ser acessados remotamente através de uma interface pública. A aplicação cliente
pode obter as referências a esses objetos e então invocar os seus métodos [Ort03b].
A interface remota (figura 2.6) especifica os serviços que serão fornecidos pelo applet para
a aplicação host. Para tanto, ela deve estender a interface java.rmi.Remote. Observa-se que
os métodos da interface remota são exatamente os mesmos encontrados no applet APDU. A
diferença é que, agora, esses não serão mais implementados dentro da classe applet e que a
sua assinatura foi modificada para incluir o lançamento de exceções. A RemoteException é
exigência da interface Remote, sendo utilizada para reportar erros que por ventura ocorram
34
p u b l i c i n t e r f a c e T r a n s p o r t R e m o t e I n t e r f a c e e x t e n d s Remote {
p u b l i c v o i d a d d C r e d i t ( s h o r t c r ) throws R e m o t e E x c e p t i o n , U s e r E x c e p t i o n ;
p u b l i c v o i d d e b i t ( ) throws R e m o t e E x c e p t i o n , U s e r E x c e p t i o n ;
p u b l i c s h o r t g e t C r e d i t s ( ) throws R e m o t e E x c e p t i o n , U s e r E x c e p t i o n ;
}
i f ( ! ( c t ! = GRATUITOUS_CARD ) ) {
U s e r E x c e p t i o n . t h r o w I t ( EXCEPTIONS . CARD_TYPE_INVALID ) ;
} e l s e i f ( ! ( sum <= 3 2 7 6 7 ) ) {
U s e r E x c e p t i o n . t h r o w I t ( EXCEPTIONS . BALANCE_EXCEEDED ) ;
} else i f ( !( cr > 0)) {
U s e r E x c e p t i o n . t h r o w I t ( EXCEPTIONS . NEGATIVE_CREDIT ) ;
} else {
balance = ( short ) ( balance + cr ) ;
}
}
// ( ...)
p u b l i c s h o r t g e t C r e d i t s ( ) throws R e m o t e E x c e p t i o n , U s e r E x c e p t i o n {
return balance ;
}
}
Por fim, a figura 2.8 apresenta o código do applet Java Card na versão RMI. A estrutura
do applet não é modificada com relação ao APDU. A principal diferença é a instanciação de
classes específicas para implementação da comunicação por RMI. A classe Dispatcher regis-
tra um serviço remoto e encaminha todo comando APDU para a classe de serviço registrada.
Neste caso, temos a classe de serviço RMIService, que então recebe este APDU e o traduz em
chamadas de métodos do objeto remoto passado em seu construtor [Ort03b].
35
p r i v a t e T r a n s p o r t A p p l e t ( b y t e [ ] bArray , s h o r t b O f f s e t , b y t e b L e n g t h ) {
super ( ) ;
r e m o t e I m p l = new T r a n s p o r t R e m o t e I m p l e m e n t a t i o n ( ) ;
s e r v i c e = new R M I S e r v i c e ( r e m o t e I m p l ) ;
d i s p a t c h e r = new D i s p a t c h e r ( ( s h o r t ) 1 ) ;
d i s p a t c h e r . a d d S e r v i c e ( s e r v i c e , D i s p a t c h e r . PROCESS_COMMAND ) ;
}
p u b l i c s t a t i c v o i d i n s t a l l ( b y t e [ ] bArray , s h o r t b O f f s e t , b y t e b L e n g t h ) {
T r a n s p o r t A p p l e t t r a n s p o r t = new T r a n s p o r t A p p l e t ( bArray , b O f f s e t , b L e n g t h ) ;
transport . register ();
}
p u b l i c v o i d p r o c e s s (APDU apdu ) throws I S O E x c e p t i o n {
d i s p a t c h e r . p r o c e s s ( apdu ) ;
}
}
A compatibilidade entre um applet Java Card e um cartão será obtida desde que o applet
seja implementado de acordo com a versão da plataforma suportada pelo cartão. Todavia, a
ampla interoperabilidade entre aplicações Java Card será alcançada apenas se todo o sistema
smart card for compatível, incluindo cartões, leitores (CAD), protocolos e aplicação host. Nesse
sentido, surgiram algumas iniciativas formadas pela associação de fabricantes e interessados no
mercado smart card, tais como a PS/SC [PC/09] e a Global Platform [Glo09].
O grupo PC/SC, composto por empresas como Microsoft, IBM, HP, Gemplus, dentre ou-
tras, possui interesse na compatibilidade do hardware smart card com computadores pessoais.
Por sua vez, Global Platform é uma iniciativa da empresa Visa, com o objetivo de prover so-
luções seguras e interoperáveis para cartões smart card com múltiplas aplicações e terminais
eletrônicos de pagamento [HNS+ 02]. Do ponto de vista do desenvolvedor, ambas as platafor-
mas são soluções completas para inicializar os leitores e cartões e para gerenciar a comunicação
por meio do protocolo APDU, levando em consideração aspectos de segurança para o sistema
como um todo.
A API Smart Card I/O do Java 6 foi uma contribuição recente para permitir o desenvolvi-
mento de uma aplicação host simples, mas que atende à necessidade da maioria das aplicações e
é compatível com leitores (CAD) PS/SC. Na Figura 2.9, tem-se um exemplo de aplicação host,
implementada em Smart Card I/O, para comunicar-se com a aplicação de bilhetagem eletrônica
TransportApplet.
36
O segundo passo consiste em estabelecer a conexão com o cartão através do método con-
nect da referência ao leitor (linha 16). Esse método necessita da informação do protocolo de
transporte (T=0 ou T=1) que o cartão utiliza. Uma vez conectado ao cartão, deve-se obter um
canal de comunicação com ele, pela chamada ao método card.getBasicChannel do objeto que
representa o cartão (linha 18). A partir daí, é possível enviar e receber comandos APDU.
Um comando APDU pode então ser criado utilizando-se um dos construtores da classe
CommandAPDU. Inicialmente, enviou-se um comando APDU select para selecionar o applet
Transport (linha 21). Para tanto, utilizou-se o método transmit da classe CardChannel, respon-
sável por enviar o comando e retornar um objeto do tipo ResponseAPDU contendo o resultado
do processamento do comando. O segundo comando enviado correponde à chamada ao serviço
getCredits (linha 23). Uma vez que getCredits retorna dados na resposta (a quantidade de cré-
ditos armazenada), é necessário invocar o método getBytes da referência à resposta para obter
37
3 O Método Formal B
Ressalta-se que é possível introduzir vários níveis de refinamento tendo em vista diminuir
o comportamento não-determinístico em pequenos passos, bem como para facilitar o esforço
de verificação do desenvolvimento. O último estágio de refinamento, conhecido como imple-
mentação, é descrito em uma linguagem imperativa de comandos que pode ser traduzida em
linguagens de programação, tais quais C, Ada, Java ou Java Card, sendo essa última um resul-
tado desta tese.
É importante ressaltar que todo módulo B, seja ele uma máquina, refinamento ou imple-
39
mentação, é composto por diferentes cláusulas, especificadas através de uma notação denomi-
nada de Abstract Machine Notation (AMN). Essa notação estabelece o papel de cada cláusula,
possibilitando um melhor entendimento do seu funcionamento, bem como facilitando o apren-
dizado do formalismo. As diversas cláusulas relacionam-se a um aspecto específico em um
módulo, como a descrição de variáveis e a especificação do invariante. Nas seções a seguir será
enfatizado apenas o subconjunto da notação de máquina abstrata que é relevante para a com-
preensão deste trabalho. Uma apresentação mais completa e detalhada pode ser encontrada em
Abrial [Abr96].
Ressalta-se que a verificação suportada por ferramentas é o componente que torna o método
B um formalismo importante para a especificação e o desenvolvimento de software. Cada passo
do desenvolvimento em B é seguido por uma etapa de verificação formal através da verifica-
ção de obrigações de prova. O resultado positivo dessa verificação garante a consistência das
propriedades estabelecidas para o componente, bem como asseguram a correção das transições
de estado na inicialização e na aplicação das operações. Dessa forma, ao final do processo de
desenvolvimento utilizando-se o método B, assegura-se que o código gerado estará correto, de
acordo com a sua especificação abstrata inicial, assumindo-se a correção da ferramenta geradora
de código.
Evidencia-se que outro incentivo relevante para o emprego do método formal B é a sua
base de ferramentas acadêmicas e comerciais. O Atelier B [Cle12a] é um exemplo importante
de uma ferramenta comercial que fornece um ambiente completo para o desenvolvimento em
B, composto por verificador de tipos, gerador de obrigações de prova, provador, gerador de
código, dentre outras. A empresa Clearsy 1 , que desenvolve e comercializa o Atelier B, distribui
uma versão gratuita desse software para uso acadêmico, uma iniciativa que pode ajudar no
crescimento da utilização do formalismo B. Destacam-se diversas iniciativas acadêmicas de
suporte ao método. Nessa linha, tem-se o Pro-B [LBBP10], um programa para a animação (um
tipo de execução de um módulo B) e verificação de modelos em B e o Brillant [MC10], um
conjunto de programas open source que inclui muitas das ferramentas fornecidas pelo Atelier
B. O estado da arte em ferramentas de suporte ao método B é discutido em maiores detalhes no
capítulo 8 (seção 8.1).
Dividiu-se o presente capítulo como descrito a seguir. A seção 3.1 aborda os principais as-
pectos relacionados à especificação funcional como uma máquina abstrata B. Nela introduz-se
parte da notação B e as noções fundamentais de obrigação de prova e substituição. A seção 3.2
apresenta o refinamento, detalhando suas restrições, obrigações de prova e o módulo de imple-
mentação. Por fim, na seção 3.3, discute-se o formalismo Event-B e os motivos que levaram a
continuação do desenvolvimento deste trabalho em B.
MACHINE M(pm )
CONSTRAINTS Const(pm )
SETS T
CONSTANTS c
PROPERTIES Prop(c)
VARIABLES v
INVARIANT Inv(v)
INITIALISATION Init(v)
OPERATIONS
r ←− op(p) = b
PRE
Pre(v, p)
THEN
S(v, p, r)
END
END
SEES Um módulo B pode incluir (ver) qualquer outra máquina que lhe forneça informação
útil. Os conjuntos e constantes de uma máquina vista podem ser lidos, mas não modifica-
dos, na máquina que a inclui. A composição com SEES não permite nenhum acesso em
relação a variáveis e operações. Um refinamento deve incluir todas as máquinas vistas
pelo módulo abstrato sendo refinado.
INCLUDES Além dos conjuntos e constantes (acessíveis pela cláusula SEES), as operações
de uma máquina incluída podem ser utilizadas. As variáveis de uma máquina incluída
podem ser modificadas dentro da máquina que a inclui. No entanto, essa alteração pode
ser feita apenas através das operações da máquina incluída, garantindo assim que o in-
variante desta máquina não seja violado. É gerada uma obrigação de prova quando da
instanciação de uma máquina incluída para se verificar se as suas pré-condições são satis-
feitas pela máquina que a inclui. Se múltiplas instâncias da mesma máquina necessitam
ser acrescentadas, deve-se renomear cada instância com um prefixo seguido de um ponto
antes do nome da máquina.
PROMOTES Permite que uma ou mais operações de uma máquina incluída (INCLUDES) ou
importada (IMPORTS) tornem-se operações da máquina que a inclui (ou importa). A
importação de máquinas aplica-se apenas ao módulo B de implementação, descrito na se-
ção 3.2.2. As operações promovidas, mesmo definidas em outro módulo, passam a fazer
parte do conjunto de operações da máquina que inclui. Para promover uma operação é ne-
cessário apenas colocar o seu nome na cláusula PROMOTES. Ressalta-se que é possível
chamar uma operação promovida dentro de uma operação ou da inicialização da máquina
que a promoveu, o que não é permitido a operações da própria máquina.
43
Ressalta-se que as mudanças de estado em uma operação são definidas através de um con-
junto de substituições. Dessa forma, as substituições e o seu efeito perante o estado da máquina
(sobre o invariante) são a base para a geração e a verificação de obrigações de prova em B. Nesta
seção apresenta-se algumas dessas substituições, que permitem especificar a atualização do es-
tado de uma variável a partir de uma expressão, a aplicação não-determinística de substituições,
a aplicação de substituições condicionadas ao valor de um predicado, dentre outras.
A notação [S]P descreve a aplicação de uma substituição S sobre um predicado P que re-
presenta o estado após a aplicação de S. Essa transformação será válida (verdadeira) em um
determinado estado, quando ao se executar S sobre esse estado, atinge-se um estado final onde
P é válido [Sch01]. Observa-se que a notação S[P] é utilizada na definição das regras que re-
gem o efeito da aplicação de cada substituição presente em B, assim como na definição das
obrigações de prova em um módulo.
Por exemplo, considere a declaração de uma variável nomeada number, cujo tipo, especifi-
cado no invariante, é o tipo B inteiro (Z) restrito ao intervalo de 1 a 10. Suponha que number
seja inicializada com o valor 0 (zero). Em B, teríamos a representação abaixo:
[S]I
Ressalta-se que, geralmente, as operações de uma máquina abstrata possuem uma substitui-
45
ção de pré-condição que estabelece as restrições que devem ser respeitadas de modo a garantir
a aplicação correta da operação, de acordo com as restrições impostas pelo invariante. Na pró-
xima seção, detalha-se essa e outras importantes substituições generalizadas que podem ser
utilizadas em uma máquina B.
A noção de substituição simples pode ser estendida para substituições mais elaboradas.
O conjunto dessas novas substituições fornece ao especificador uma ferramenta poderosa para
descrição do comportamento da especificação.
Na presente seção podem ser vistas importantes substituições generalizadas. O termo “subs-
tituição generalizada” expressa a ideia de que a aplicabilidade de uma substituição pode ser ex-
pandida ou restrita para se descrever e se verificar diversos novos comportamentos. É possível,
por exemplo, impor restrições à aplicação de uma substituição e especificar a execução paralela
de substituições.
Sem efeito (skip) A substituição “sem efeito”, ou simplesmente skip, apesar do seu nome,
possui um papel importante. Ela é útil na definição de novas substituições, como no caso da
substituição condicional que não possui a parte ELSE, além de ser um meio para se adiar a
especificação do comportamento de uma operação. Assim, o comportamento é especificado
somente posteriormente, em um refinamento da operação.
Como ilustração, a substituição condicional, quando utilizada sem a parte ELSE, pode ser
definida do mesmo modo que a sua versão completa, apenas adicionando-se a substituição skip
na parte ELSE.
Não há regra específica para se obter a obrigação de prova para substituições sob o escopo
da substituição paralela. Dessa forma, deve-se reescrever as substituições envolvidas até que o
paralelismo seja removido [Sch01]. As regras básicas para a reescrita, sendo S e T substituições,
x e y variáveis e E e F expressões, são:
47
skip:
S k skip = S
Comutatividade:
SkT =T kS
Any Permite introduzir definições locais de variáveis em uma substituição. Seja v uma
lista de nomes de variáveis e Q um predicado contendo o tipo e as condições que devem ser
satisfeitas para a utilização das variáveis introduzidas. A substituição S estabelece o predicado
P, sempre que for possível escolher uma valoração para as variáveis v, sob as restrições de Q,
que tornem a substituição de S em P válida.
3.2 Refinamento
MACHINE MA REFINEMENT MR
VARIABLES vA REFINES MA
INVARIANT VARIABLES vR
InvA (vA ) INVARIANT
INITIALISATION InvR (vA , vR )
InitA (vA ) INITIALISATION
OPERATIONS InitR (vR )
rA ←− OPA (pA ) = b OPERATIONS
PRE rR ←− OPR (pR ) = b
PreA (vA , pA ) PRE
THEN PreR (vR , pR )
SA (vA , pA , rA ) THEN
END SR (vR , pR , rR )
END END
END
Salienta-se que as operações do refinamento estão sujeitas a regras restritivas que devem
ser obedecidas para possibilitar o refinamento, quais sejam, (i) o refinamento deve preservar
o mesmo número de operações do módulo refinado e (ii) a assinatura da operação abstrata
não pode ser modificada no refinamento. A restrição (ii) significa que o nome da operação
e a ordem, nome e tipo de seus parâmetros de entrada e valores de retorno não podem ser
modificados. Essas restrições podem trazer certas dificuldades ao desenvolvimento de software.
No capítulo 4, discute-se duas soluções para contornar a restrição de mudança de interface no
refinamento, o que beneficia diretamente o refinamento no método BSmart.
Observa-se, na obrigação de prova, as negações em (¬[InitA (vA )](¬InvR (vA , vR ))). Elas
atestam a possibilidade do invariante de ligação ser estabelecido apenas por “algumas” tran-
sições de estado abstratas. Ou seja, cada estado concreto deve estar relacionado a um estado
abstrato, no entanto, o contrário não precisa, necessariamente, ocorrer.
Ressalta-se que, para o caso das operações, como demonstrado no lado esquerdo da obri-
gação de prova, deve-se levar em consideração a validade do estado previamente modificado,
assim como o estabelecimento da pré-condição. Uma vez que essas premissas forem satisfeitas,
deve-se verificar se todos os estados que podem ser alcançados pelo refinamento podem tam-
bém ser atingidos pela aplicação da operação abstrata, de acordo com o que foi especificado no
invariante de ligação. De outro modo, utilizando-se o conceito de simulação, pode-se dizer que
o comportamento observado quando a operação concreta é aplicada poderá ser simulado pela
50
aplicação correspondente da operação abstrata, para os mesmos valores de entrada, sem que
haja diferença para o observador.
No que tange às pré-condições abstratas e concretas, vale salientar que a primeira não se
faz necessária na operação concreta, desde que ela seja suficiente para estabelecer as condições
para a correta aplicabilidade de ambas as operações. Entretanto, em alguns casos, pode ser útil
complementar a operação concreta com alguma informação de pré-condição. Nesses casos, a
operação concreta não deve contradizer o que foi estabelecido na operação abstrata, isto é, ela
deve ser válida sempre que a operação abstrata for válida. Em outras palavras, a pré-condição
concreta deve ser sempre mais fraca que a sua correspondente abstrata, tendo em vista evitar
um comportamento concreto mais restritivo que o abstrato.
3.2.2 Implementação
• Uma variável só pode ser modificada através das operações da máquina importada que a
51
IMPLEMENTATION MI
REFINES MR
IMPORTS MIMP
CONSTANTS c
PROPERTIES Prop(c)
VALUES Val(c)
CONCRETE_VARIABLES vC
INVARIANT Inv(vC , vR , vIMP )
INITIALISATION Init(vC , vIMP )
OPERATIONS
r ←− op(p) = b
BEGIN
S(vIMP , p, r)
END
END
define.
A presente seção tem por objetivo apresentar o formalismo Event-B e contextualizar os mo-
tivos pelos quais neste trabalho permanecemos com o uso do B clássico. Conforme apresentado
neste capítulo, o método formal B é voltado à especificação, desenvolvimento e verificação de
programas sequenciais como base em refinamentos. Observa-se que o método formal Event-
B [Abr10] é mais recente e recebe influência de B. No entanto, essa nova abordagem não deve
ser encarada como uma evolução do método formal B, como poderia-se supor, uma vez que o
foco de Event-B é diferente do B clássico, a saber, a modelagem e a verificação de sistemas re-
52
ativos concorrentes. Dessa forma, o comportamento de uma máquina Event-B, sua notação e as
obrigações de prova para verificação de máquinas e refinamentos são voltadas à especificação
dessa categoria de sistemas, diferenciando-se do B tradicional.
Como exemplo, o modelo Event-B da aplicação Java Card de bilhetagem eletrônica Trans-
port do capítulo 2 é exibido nas figuras 3.4 e 3.5. A figura 3.4 apresenta a declaração das
variáveis de estado e a especificação do invariante, no qual são inseridas as restrições de que o
cartão não deve ter saldo negativo (inv2) e, caso o cartão seja de gratuidade, o saldo deve ser
0 (inv4). Pode-se observar que cada restrição é inserida em uma linha separada, precedida por
uma marcação (inv1 .. inv4). Essas marcações são exigência da ferramenta Rodin [ABH+ 10],
utilizada na construção deste exemplo, para que ela possa gerenciar cada elemento da especifi-
cação, facilitando a localização de erros e a construção e exibição para o usuário de obrigações
de prova.
Ainda na figura 3.4, tem-se o módulo de contexto Transport_Constants, que declara o con-
junto CARDS, utilizado na máquina Transport. Os possíveis elementos do conjunto (especifi-
53
cado na cláusula AXIOMS) são as contantes gratuitous, entire e student, que correspondem aos
tipos de cartão que podem ser emitidos.
EVENTS
Initialisation
begin
act1 : balance := 0
act2 : card_type := entire
end
Event addCredit =
b
any
cr
where
grd1 : cr ∈ N
grd2 : cr > 0
grd3 : card_type 6= gratuitous
grd4 : balance + cr ≥ 0
grd5 : balance + cr ∈ N
then
act1 : balance := balance + cr
end
END
Observa-se pela figura 3.5 que na máquina Transport são definidos dois eventos, a saber,
o evento de inicialização e o evento addCredit que modela a adição de créditos em um cartão.
Ressalta-se que o evento de inicialização ocorre antes da ativação de qualquer outro evento para
estabelecer o estado inicial da máquina de forma consistente com o seu invariante.
Um evento pode ser especificado através de três formas [ABH+ 10], são elas:
1. evt =
b any t where P(t, v) then S(t, v) end
2. evt =
b where P(v) then S(v) end
3. evt =
b begin S(v) end
A primeira forma é a mais geral e define um evento que possui parâmetros de entrada (t),
uma guarda que atua sobre os parâmetros e as variáveis de estado (P(t, v)) e uma ação (S(t, v)).
A ação é o componente responsável pela mudança de estado do evento caso a sua guarda seja
estabelecida. As outras formas especificam, respectivamente, um evento sem parâmetros e um
evento apenas com ação. Neste último caso, considera-se que a guarda do evento é sempre
verdadeira.
substituições), conforme pode ser visto na figura 3.6. Essa característica, para o tipo de de-
senvolvimento requerido pelas aplicações smart card caracterizaria uma certa dificuldade na
especificação de um serviço. Por exemplo, caso necessitássemos especificar um serviço que
pode tomar mais de uma ação a partir da avaliação de condições, o que é comum em qualquer
aplicação, então teríamos que especificar cada ação em um evento distinto, com a sua condição
de aplicação definida como guarda.
Ressalta-se que Event-B é mais flexível que B no que diz respeito a mecanismos permitidos
para especificação e refinamento. Por exemplo, uma máquina pode ser decomposta em mais de
uma máquina para gerenciar a complexidade da especificação. Um evento, por sua vez, pode
ser refinado por mais de um evento. Finalmente, mais de um evento pode ser unido em um
evento único. É também possível introduzir novos eventos em um refinamento. Nesse caso, o
evento concreto implicitamente refina um evento abstrato contendo uma substituição skip em
seu corpo e o especificador deve assegurar o novo evento não leve a máquina a um estado de
deadlock.
Evidencia-se que na abordagem utilizada no método BSmart, as aplicações smart card são
traduzidas após serem especificadas, refinadas e implementadas em B. A composição de máqui-
nas e refinamentos em B, conforme demonstrado neste capítulo, é mais restritiva que Event-B.
Por outro lado, B oferece um ambiente mais adequado para se introduzir um estilo de desenvol-
vimento algorítmico, composto por diversas substituições, muitas delas possuindo uma relação
estrita com construções encontradas em linguagens, tais como C e Java. Além disso, ressalta-
se que o refinamento de implementação não está presente em Event-B. Como consequência,
as substituições determinísticas necessárias para a geração de código não são parte da notação
Event-B, tais como, condicional (IF), sequência (“;”), repetição (WHILE), etc.
Diante do exposto nesta seção, conclui-se que a especificação e refinamento de uma aplica-
ção Java Card, seguindo o método BSmart em Event-B traria um série de dificuldades, devido
ao paradigma de especificação em Event-B não ser adequado à especificação de sistemas se-
quenciais. As etapas de tradução também seriam prejudicadas, uma vez que não há em Event-B
um módulo de implementação, determinístico, a partir do qual as aplicações Java Card fossem
55
4 O Método BSmart
Observa-se que, apesar do sistema Java Card fornecer ao desenvolvedor instrumentos que
visam preservar informações e melhorar a segurança do ambiente smart card, erros podem ser
facilmente introduzidos em todas as fases do desenvolvimento de software. Isso normalmente
ocorre devido ao entendimento incorreto dos requisitos especificados, fazendo com que os erros
sejam propagados para as fases posteriores. Sendo um domínio de aplicação crítico, falhas em
uma aplicação smart card podem ter consequências inaceitáveis, tais como perdas financeiras
ou o acesso indevido a informações. Logo, o emprego de técnicas e ferramentas de apoio à en-
genharia de software rigorosa durante o processo de especificação e desenvolvimento, tal qual o
método proposto nesta tese, é um meio de melhorar a confiabilidade na aplicação implementada.
O presente capítulo é dividido conforme descrito a seguir. A seção 4.1 fornece uma visão
geral do método BSmart. A especificação abstrata que inicia o desenvolvimento é descrita na
seção 4.2. Em seguida, a seção 4.3 enfatiza o desenvolvimento da aplicação para o cartão e
a sua formalização em B. A seção 4.4 trata da verificação da mudança de interface entre o
componente abstrato inicial (Java) e o seu correspondente concreto (Java Card). A geração da
API de suporte à comunicação da aplicação cliente com o cartão é tratada na seção 4.5 e o estado
atual do suporte de ferramentas ao método é descrito na seção 4.6. Por sua vez, a seção 4.7
demonstra a aplicabilidade do retrenchment para a verificação apresentada na seção 4.4. Por
fim, a seção 4.8 avalia o método e enfatiza os desenvolvimentos futuros.
O desenvolvimento com base no método BSmart tem início com a especificação formal
abstrata do software smart card como uma máquina B. A partir dessa máquina, seguem-se duas
linhas de desenvolvimento (figura 4.1), uma delas corresponde ao applet que será instalado no
cartão, e a outra está relacionada à API de suporte à aplicação host. Ressalta-se que a ordem do
desenvolvimento, após a especificação inicial, é irrelevante, uma vez que a geração da API para
a aplicação cliente é independente do desenvolvimento do applet.
aplicação host Com respeito à tradução para o cliente, é importante observar que não é a apli-
cação host como um todo que está sendo gerada, tendo em vista ser impossível lidar com
a lógica de negócio que varia de uma aplicação para outra. O que se fornece é uma API,
gerada a partir da especificação inicial com o auxílio de ferramenta, que encapsula os
aspectos de baixo nível da comunicação entre as aplicações do sistema Java Card. As-
sim, ao usar a API, a aplicação host pode comunicar-se com o cartão em um nível mais
elevado, como se estivesse lidando com uma aplicação Java desktop comum, abstraindo
totalmente os detalhes dos protocolos do sistema smart card.
Nas próximas seções, serão detalhados os aspectos relacionados às duas linhas de desenvol-
vimento com o método BSmart. A formalização do refinamento do lado cartão é apresentada
na seção 4.3, enquanto que os componentes da API para o cliente são descritos na seção 4.5.
59
Ressalta-se que, na versão atual, não é possível que os modelos descritos sejam instanciados
de forma automática para gerar uma aplicação em particular. Ou seja, cada nova aplicação deve
seguir o desenvolvimento proposto, porém deverá verificar novamente, através de ferramenta,
as obrigações de prova requeridas em cada etapa.
Inicialmente, é importante apresentar o módulo J_Context (figura 4.2), que inclui as de-
finições abstratas para cada elemento significativo da máquina que representa a especificação
inicial do desenvolvimento. O conjunto J_TYPE representa um sistema de tipos compatível com
Java. Nesse sistema é possível ter, por exemplo, o tipo inteiro (int) ou qualquer conjunto repre-
sentando um tipo abstrato de dado. Na cláusula PROPERTIES, funções definem os elementos
relacionados à mudança de estado e à verificação da máquina. Na ordem em que aparecem na
figura 4.2, tem-se o invariante (j_inv), as pré-condições das operações (j_pre), a atualização do
estado (j_stf ) e o retorno de dados em uma operação (j_ouf ), bem como a pós-condição após
esse retorno (j_pos).
MACHINE J_Context
SETS J_TYPE
CONCRETE_CONSTANTS j_stf , j_ouf , j_inv , j_pre , j_pos
PROPERTIES
j_inv ∈ J_TYPE → BOOL ∧ j_pre ∈ J_TYPE → BOOL ∧
j_stf : ( J_TYPE × J_TYPE ) → 7 J_TYPE ∧ j_ouf : ( J_TYPE × J_TYPE ) →7 J_TYPE ∧
j_pos ∈ J_TYPE → BOOL ∧
∀ ( v1 , v2 ) . ( v1 ∈ J_TYPE ∧ v2 ∈ J_TYPE ∧ j_inv ( v1 ) = TRUE ∧
j_pre ( v2 ) = TRUE =⇒ v1 , v2 ∈ dom ( j_stf ) ) ∧
∀ ( v1 , v2 ) . ( v1 ∈ J_TYPE ∧ v2 ∈ J_TYPE ∧ j_inv ( v1 ) = TRUE ∧
j_pre ( v2 ) = TRUE =⇒ v1 , v2 ∈ dom ( j_ouf ) ) ∧
∀ ( v1 , v2 ) . ( v1 ∈ J_TYPE ∧ v2 ∈ J_TYPE ∧
v1 , v2 ∈ dom ( j_stf ) =⇒ j_inv ( j_stf ( v1 , v2 ) ) = TRUE ) ∧
∀ ( v1 , v2 ) . ( v1 ∈ J_TYPE ∧ v2 ∈ J_TYPE ∧
v1 , v2 ∈ dom ( j_ouf ) =⇒ j_pos ( j_ouf ( v1 , v2 ) ) = TRUE )
Figura 4.2: Definição do tipo Java e das propriedades para a formalização dos componentes da
especificação abstrata.
A máquina J_App inclui J_Context (SEES J_Context), dessa forma torna-se possível acessar
as propriedades definidas nesse módulo. O estado global da máquina J_App é representado pela
variável j_v, declarada no invariante como sendo do tipo Java (J_TYPE). Do mesmo modo,
recebem o tipo J_TYPE os parâmetros recebidos (j_param) e retornados (j_r) pela operação
(j_operation), indicando que a máquina abstrata possui um sistema de tipos compatível com
Java.
61
A figura 4.4 fornece uma visão geral do desenvolvimento com o método BSmart para a apli-
cação cartão e dos artefatos que são criados no decorrer desse processo. Após a especificação
inicial (J_App), ou de um refinamento posterior dela, deve-se desenvolver uma especificação
equivalente, mas que possua definições de tipos de dados compatíveis com Java Card. De
posse desse modelo (JC_App), é possível proceder com o seu refinamento em direção à aplica-
ção cartão.
Figura 4.4: Uma visão dos artefatos que compõem o desenvolvimento da aplicação Java Card
do lado cartão (não inclui aplicação cliente).
Ressalta-se que é possível refinar o componente JC_App em diversos níveis, com o objetivo
de gerenciar a complexidade ou reduzir o esforço de verificação do desenvolvimento B. No en-
tanto, ao menos um refinamento torna-se obrigatório (JC_App_FF_r, na figura 4.4), tendo por
62
objetivo possibilitar a especificação de condições de erro que são previamente conhecidas. Es-
sas situações de erro são retiradas das pré-condições das operações e inseridas em substituições
condicionais em seu corpo, em um estilo de especificação denominado de full function.
MACHINE JC_Context
SETS JC_TYPE
CONCRETE_CONSTANTS jc_c , jc_stf , jc_ouf , jc_inv , jc_pre , jc_pos
PROPERTIES
jc_c ∈ JC_TYPE ∧
jc_inv ∈ JC_TYPE → BOOL ∧ jc_pre ∈ JC_TYPE → BOOL ∧
jc_stf : ( JC_TYPE × JC_TYPE ) → 7 JC_TYPE ∧ jc_ouf : ( JC_TYPE × JC_TYPE ) →
7 JC_TYPE ∧
jc_pos ∈ JC_TYPE → BOOL ∧
∀ ( v1 , v2 ) . ( v1 ∈ JC_TYPE ∧ v2 ∈ JC_TYPE ∧ jc_inv ( v1 ) = TRUE ∧
jc_pre ( v2 ) = TRUE =⇒ v1 , v2 ∈ dom ( jc_stf ) ) ∧
∀ ( v1 , v2 ) . ( v1 ∈ JC_TYPE ∧ v2 ∈ JC_TYPE ∧ jc_inv ( v1 ) = TRUE ∧
jc_pre ( v2 ) = TRUE =⇒ v1 , v2 ∈ dom ( jc_ouf ) ) ∧
∀ ( v1 , v2 ) . ( v1 ∈ JC_TYPE ∧ v2 ∈ JC_TYPE ∧ v1 , v2 ∈
dom ( jc_stf ) =⇒ jc_inv ( jc_stf ( v1 , v2 ) ) = TRUE ) ∧
∀ ( v1 , v2 ) . ( v1 ∈ JC_TYPE ∧ v2 ∈ JC_TYPE ∧ v1 , v2 ∈
dom ( jc_ouf ) =⇒ jc_pos ( jc_ouf ( v1 , v2 ) ) = TRUE )
ASSERTIONS
∀ ( v1 , v2 ) . ( v1 ∈ JC_TYPE ∧ v2 ∈ JC_TYPE ∧ jc_inv ( v1 ) = TRUE ∧
jc_pre ( v2 ) = TRUE =⇒ jc_inv ( jc_stf ( v1 , v2 ) ) = TRUE ) ∧
∀ ( v1 , v2 ) . ( v1 ∈ JC_TYPE ∧ v2 ∈ JC_TYPE ∧ jc_inv ( v1 ) = TRUE ∧
jc_pre ( v2 ) = TRUE =⇒ jc_pos ( jc_ouf ( v1 , v2 ) ) = TRUE )
END
Figura 4.6: Definição do tipo Java Card e das propriedades para a formalização dos componen-
tes da especificação concreta.
duas propriedades, com o objetivo de auxiliar a ferramenta de verificação nas provas do mó-
dulo. Elas visam atestar que se o estado (jc_inv (v1) = TRUE) e os parâmetros de uma opera-
ção (jc_pre (v2) = TRUE) forem válidos antes da sua aplicação, então a aplicação da operação
(jc_inv (jc_stf (v1, v2)) = TRUE)) e os valores retornados (jc_pos (jc_ouf (v1, v2)) = TRUE))
por ela, devem levar a máquina para um estado posterior no qual o invariante continue verda-
deiro.
Embora apresentem interfaces distintas, cumpre enfatizar que esses modelos são equivalen-
tes, ou seja, são capazes de efetuar as mesmas transições entre estados através da aplicação de
suas operações. Conforme discutido na introdução deste capítulo, tendo em vista que a interface
das operações do desenvolvimento abstrato (Java) difere das suas correspondentes concretas
(Java Card), a verificação da equivalência entre esses modelos não pode ser demonstrada pelo
refinamento direto em B. A seção 4.4 apresenta uma abordagem de verificação, desenvolvida
nesta tese, que contorna essa restrição permanecendo no rigor do refinamento em B.
Card.
É interessante observar que, em uma máquina B, as restrições a uma operação são geral-
mente especificadas em sua pré-condição, devendo essas serem respeitadas antes da aplicação
da operação. Todavia, para que seja possível a tradução dessas pré-condições na forma de con-
dições de erro que, caso ocorram, devem ser reportados ao cliente, faz-se necessário oferecer
operações totais (full function).
O refinamento ora apresentado (figura 4.7) aplica o modelo de operação full function, no
qual as pré-condições são enfraquecidas, de forma que a pré-condição define apenas o tipo dos
parâmetros recebidos. As demais restrições são então tratadas no corpo da operação, através de
substituições condicionais, cuja não-satisfação da condição leva ao lançamento de uma exceção.
A máquina ISOException, parte da biblioteca KitSmart (capítulo 6), representa um modelo
simples da classe de exceção de mesmo nome presente na API Java Card. Se o refinamento full
function não fosse aplicado, não seria possível a geração de código para a verificação dessas
condições de erro no código Java Card gerado.
Figura 4.7: Versão full function de JC_App (esq.) e máquina de contexto (dir.).
Ressalta-se que nesta etapa também é definida uma máquina de contexto (lado direito
da figura 4.7), responsável por incluir informações estáticas úteis ao desenvolvimento. Ela
contém o identificador de cada condição de exceção (exception_id_x) e códigos de instrução
(jc_operation_x_INS) para identificar unicamente cada serviço. Quaisquer outras constantes
úteis à aplicação Java Card também podem ser inseridas neste módulo de contexto.
65
Observa-se que o prefixo jc_cvar define uma instância do componente JCType_lib. Caso
seja necessário incluir outras instâncias dessa máquina, o usuário deve atribuir um novo prefixo
para cada instância. O prefixo deve ser utilizado para referenciar variáveis e operações da
máquina, como no caso da operação init, responsável por inicializar a variável de estado jc_var
(INITIALISATION jc_cvar.init).
Destaca-se que no corpo da operação concreta devem ser preservadas as verificações ad-
vindas do modelo full function. Caso os dados recebidos pela operação satisfaçam essas res-
trições, deve-se proceder com a efetivação do serviço. No modelo de implementação dos
serviços, a transição do estado na operação jc_operation é representada pela linha result ←
jc_cvar.concrete_operation (jc_param).
É importante observar que uma operação de uma máquina não pode requisitar outra opera-
ção da mesma máquina em seu corpo. Contornar essa limitação foi uma das motivações para
separar o modelo do applet, que refina a máquina Applet da API, do modelo dos serviços que
a aplicação Java Card oferece. Nessa proposta, a implementação JC_Applet_i (figura 4.10)
importa a especificação JC_App, dessa forma tornando possível que as operações da especifica-
ção applet, tais como install, process, select e deselect, referenciem os métodos de serviço sem
interferir em seu estado interno.
dados através do buffer apdu sejam feitas pelo componente applet. Nesse caso, as informações
do buffer são decodificadas e enviadas aos parâmetros dos serviços, de modo semelhante ao que
é feito na operação process da figura 4.10.
IMPLEMENTATION JC_Applet_i
REFINES JC_Applet_r
SEES JByte, JShort, Apdu_Properties, JC_Context, InterfaceContext
IMPORTS app.JC_App, apdu.Apdu
OPERATIONS
install(bArray, bOffset, bLength) = BEGIN skip END;
process(apdu) =
VAR buffer, value, out
IN
buffer ← apdu.getBuffer;
value := jc_of_apdu(buffer);
IF jc_pre(jc_of_apdu(buffer)) = TRUE
THEN
out ← app.jc_operation (value)
END
END;
Destacam-se ainda outros benefícios da separação entre os modelos do applet e dos servi-
ços, a saber:
2. Evitar que o modelo concreto dos serviços contenha mais operações que o modelo abs-
trato, caso os métodos do applet fossem diretamente especificados no primeiro;
Cumpre ressaltar que foi preciso criar meios para tratar as limitações do refinamento em B,
tendo em vista possibilitar a verificação do modelo concreto da especificação Java Card quando
68
Observa-se que, em alguns casos, a mudança na interface concreta faz-se necessária, com
o objetivo de compatibilizar esse modelo com as limitações de Java Card ou representar a
recepção e envio de informações através do buffer adpu. Por exemplo, no caso da representação
do tipo inteiro (int) de Java, uma vez que não é garantida a sua implementação em Java Card,
deve-se representá-lo, no modelo concreto, como dois valores short ou como um array de bytes.
A seção 4.4.1 apresenta uma abordagem, desenvolvida nesta tese, que corresponde a uma
forma de composição de módulos que resolve o problema da adaptação de interface sem a
necessidade de se desviar do refinamento clássico de B. A título de ilustração, na seção 4.7,
demonstra-se o uso da técnica de retrenchment [BP98], solução inicial pesquisada para contor-
nar a restrição de mudança de interface. Trata-se de uma variante menos rigorosa do refinamento
tradicional, e, por esse motivo, não foi incorporada ao método.
Nesta seção apresenta-se uma técnica, desenvolvida na presente tese, para permitir a ve-
rificação da mudança de tipos e de interface entre um módulo abstrato e seu correspondente
concreto, sem no entanto sair do escopo do método B tradicional.
O módulo J_ App_r (figura 4.11) representa o modelo a ser seguido para utilizar a técnica
proposta. Para tanto, deve-se refinar a máquina abstrata Java (REFINES J_App) e incluir a
especificação concreta (INCLUDES JC_App). No invariante, deve-se relacionar os estados des-
ses modelos através de um invariante de ligação. No caso geral, em que a representação dos
tipos concretos e abstratos é distinta, são utilizadas funções para converter o estado concreto
no estado abstrato correspondente (na figura, j_v = java_of_jc ( jc_v )). Ressalta-se que deve
ser fornecida, para cada tipo relacionado, uma função que faz o trabalho inverso, ou seja, que
converte o estado abstrato em seu correspondente concreto (como jc_of_java (jc_param), no
corpo da operação). Nesse caso, as funções são bijetoras, sendo uma inversa da outra.
REFINEMENT J_ App_r
REFINES J_App
SEES J_Context, JC_Context, InterfaceContext
INCLUDES JC_App
INVARIANT
j_v = java_of_jc ( jc_v )
OPERATIONS
j_r ← j_operation ( j_param) =
PRE j_param ∈ J_TYPE ∧
j_pre ( j_param) = TRUE
THEN
VAR tmp
IN
tmp ← jc_operation ( jc_of_java ( j_param)) ;
j_r := java_of_jc (tmp)
END
END
END
Figura 4.11: Refinamento da especificação abstrata inicial para verificar a correção da mudança
de interface pelo módulo Java Card.
3. Por fim, o resultado da aplicação da operação Java Card é convertido para o tipo abstrato
e retornado (j_r := java_of _jc(tmp)).
70
Destaca-se também que, nesta proposta, uma vez que se tenha provado a equivalência dos
componentes abstratos e concretos para alguma representação de tipo, obtidas através da correta
verificação do refinamento J_App_r, torna-se possível reusar a abordagem para esses tipos em
outros desenvolvimentos semelhantes, sem a necessidade de verificá-los novamente.
Ressalta-se que, na versão atual do método, o desenvolvimento desta etapa é feito de forma
manual. Pretende-se automatizar esse processo através de uma ferramenta que gere (ao menos
em parte) o padrão de refinamento proposto a partir dos modelos Java e Java Card.
Inicialmente, cumpre observar que um primeiro protótipo desta parte do trabalho foi de-
senvolvido por Moraes [Mor07]. Na tese, a solução anterior foi totalmente remodelada visando
otimizar o reuso de código. Além disso, a implementação, antes desenvolvida em Java, foi
refeita utilizando a linguagem C++ e a API BCompiler [Cle12b], que fornece acesso aos ele-
mentos do código B, tornando possível a tradução para o código Java correspondente. Maiores
detalhes acerca do B Compiler podem ser encontrados na seção 4.6.
71
É importante observar que a proposta não é a geração da própria aplicação host, uma vez
que não há como prever a lógica de negócio e a interface da aplicação principal, mas sim de
um conjunto de classes que efetua todo o trabalho de comunicação com o cartão. Portanto, o
que se oferece é uma API contendo a abstração da chamada aos serviços oferecidos pelo cartão
e classes que implementam rotinas de tratamento de dados, como, por exemplo, conversões de
tipos entre o universo Java padrão da aplicação host e o universo Java Card do lado cartão.
O diagrama da figura 4.13 ilustra as classes e interfaces componentes da API. Dentre elas,
destacam-se duas classes essenciais para a comunicação com o applet, e que são geradas para
72
Figura 4.13: Diagrama de classes UML descrevendo os componentes da API para a aplicação
cliente.
A inclusão de uma nova API de comunicação com o smart card é bastante simples, sendo
necessário apenas implementar as interfaces I_APDUComm e I_CardConnector. Ressalta-se
que, neste trabalho, é fornecida a implementação das interfaces para a API Smart Card I/O. A
primeira, referenciada diretamente pela classe Proxy, descreve os métodos que devem ser im-
plementados para enviar e/ou receber as respostas advindas do componente cartão através de
uma API específica. A conexão efetiva com a API é realizada por intermédio da implementação
da interface I_CardConnector. Nesse caso, deve-se ao menos desenvolver os métodos para se
conectar ao cartão (cardInit) e obter a referência ao objeto que representa o cartão (getCardRe-
73
ference). Os demais métodos se referem ao que deve ser feito no momento em que o cartão é
inserido (cardInserted) e sempre que a seção de comunicação for interrompida (cardRemoved).
Ainda em relação aos componentes da API, destaca-se a classe HostUtil, que possui méto-
dos úteis às tarefas de conversão de dados entre as aplicações host e cartão, efetuadas na classe
AppProxy. Esses métodos permitem inserir valores byte, short, int e array no buffer apdu, assim
como converter o array de byte da resposta APDU em um dos tipos primitivos de Java.
public c l a s s TransportCommunication {
byte [ ] appletAID = nu ll ;
TransportProxy cardProxy = null ;
p u b l i c T r a n s p o r t C o m m u n i c a t i o n ( b y t e [ ] a i d ) throws E x c e p t i o n {
appletAID = aid ;
c a r d P r o x y = new T r a n s p o r t P r o x y ( a p p l e t A I D ) ;
}
public void a d d C r e d i t ( short cr , short c t ) { cardProxy . a d d C r e d i t ( cr , c t ) ; }
public void d e b i t ( ) { cardProxy . debit ( ) ; }
public short getBalance ( ) { return cardProxy . getBalance ( ) ; }
}
interface I_APDUComm para uma API específica. No caso do exemplo, implementou-se a API
smart card I/O (apdu = new SmartCardIOAPDUComm(aid)).
em ambos. Para os demais casos, os valores são armazenados diretamente no campo data, um
após o outro, na sequência em que aparecem na assinatura da operação. O controle da posição
de inserção do próximo valor no buffer é feito pela variável index, que inicialmente aponta para
a posição 0 (zero), sendo incrementada de acordo com o tamanho do último valor armazenado.
A recepção de valores através do buffer deve ser solicitada por um dos métodos sendCom-
mandAndGetResponse, como no caso da operação getBalance (figura 4.17), que espera receber
um valor short correspondente à quantidade de créditos armazenados no cartão. No exemplo,
um array de bytes é recebido (linha 5), e, posteriormente, é convertido em um short e retornado
para a operação correspondente da classe communication (linha 8), que por sua vez encaminha
o valor à aplicação cliente. Finalmente, no caso da operação debit, em que não há envio e recep-
ção de informações, o comando apdu enviado apenas requisita a execução do método da classe
applet, responsável por debitar o valor de uma unidade de crédito do cartão.
1 public void d e b i t ( ) {
2 apdu . sendCommand ( APPLET_CLA , d e b i t _ I N S , ( b y t e ) 0 , ( b y t e ) 0 ) ;
3 }
4 public short getBalance ( ) {
5 b y t e [ ] r e s = apdu . sendCommandAndGetResponse ( APPLET_CLA ,
6 getBalance_INS , ( byte ) 0 , ( byte ) 0 , 2 ) ;
7
8 return HostUtil . byteArrayToShort ( r e s ) ;
9 }
10 }
Observa-se que, na versão inicial dos programas, utilizou-se o software JBtools [Voi02]
para, através de uma biblioteca fornecida por essa ferramenta, ter acesso à árvore sintática dos
elementos da especificação e realizar as transformações de código para B ou Java. Apesar de
76
fornecer um meio ágil de desenvolvimento, a ferramenta JBtools [Voi02] apresenta alguns pro-
blemas. Dentre eles, pode-se destacar a exibição de mensagens de erro pouco esclarecedoras, o
tratamento inadequado da tradução de tipos para Java Card e a compatibilidade apenas com a
notação clássica da linguagem B, tal qual descrita no B-Book [Abr96].
Cumpre destacar que, ao invés de se modificar o JBtools ou criar um novo conjunto de soft-
ware a partir do zero, buscou-se uma outra API para a manipulação de máquinas e refinamentos
B. A solução encontrada foi a API BCompiler [Cle12b], que possui funcionalidade semelhante
ao JBtools, com as vantagens de ser sólida, estável e amplamente compatível com o Atelier
B [Cle12a], atualmente a ferramenta de referência para desenvolvimento com o método B.
Ressalta-se que a gramática B definida pelo Atelier B inclui construções que não são supor-
tadas pelo B clássico (struct e record, por exemplo) e apresenta divergências quanto à forma
sintática de alguns elementos. Nesse sentido, além de eliminar os problemas apresentados pelo
JBtools, a migração das ferramentas do BSmart para o BCompiler possibilita a sua integração
com o ambiente de desenvolvimento fornecido pelo Atelier B. Essa abordagem, além de mais
robusta que a anterior, proporciona maior agilidade e comodidade ao especificador, que possui,
em uma mesma IDE, todo o ambiente necessário para o desenvolvimento Java Card com o
método BSmart.
Cumpre enfatizar que o software BCompiler é utilizado em todos os componentes para ma-
nipular um módulo B tendo em vista geração de código para um módulo B (caso do refinamento
full function) ou para Java ou Java Card. Para tanto, antes de ser realizado o propósito de cada
ferramenta, é feita a verificação sintática e de tipos do módulo fornecido como entrada através
de chamadas a funções fornecidas pelo BCompiler. A resolução bem sucedida dessas verifica-
ções iniciais gera a árvore de parser para o módulo, tornando possível o acesso a cada elemento
desse.
ff_gen: Geração de módulos Java Card Possibilita a criação do refinamento full function e
da sua máquina de contexto, conforme descrito na seção 4.4.1. Deve-se fornecer como entrada
a máquina abstrata que inicia o desenvolvimento ou um refinamento dela. Para cada restrição
encontrada na pré-condição de uma operação é gerada uma constante na máquina de contexto,
correspondente à exceção a ser lançada, formada por um prefixo seguido do nome da operação
e de um número de sequência (por exemplo, ex_op_1, ex_op_2). Após gerado, a correção do
refinamento pode ser atestada por uma ferramenta de suporte ao método B, tal qual o Atelier B,
através da verificação de sintaxe, tipos e de obrigações de prova.
Observa-se que, no caso da tradução para Java Card, a ferramenta verifica se os módulos de
implementação satisfazem as restrições impostas pela versão 2.2.2. Tendo em vista possibilitar
a correta geração de código, são verificadas as propriedades a seguir descritas na especificação
Java Card [Ora11]:
78
• Uso do tipo inteiro (int), que até a versão Java Card 2.2.2 é de implementação opcional.
• Um módulo B pode declarar no máximo 255 operações que sejam traduzidas em métodos
públicos (public) ou protegidos (protected). Na tradução desenvolvida neste trabalho,
todos os métodos de serviço da aplicação Java Card são traduzidos com visibilidade
pública. A única exceção é o método construtor da classe applet, gerado com visibilidade
privada (private), uma vez que ele deve ser invocado somente dentro da classe, no corpo
do método init, para instanciação e registro do applet junto ao ambiente de execução.
• O número máximo de variáveis locais e parâmetros que podem ser declarados em uma
operação é de 255.
• Uma classe Java Card deve declarar apenas arrays de uma dimensão. Em B, um array
corresponde a uma função total mapeada de um intervalo inteiro para um conjunto ou a
uma sequência (seq) sobre um dado conjunto.
host_gen: Geração da API para a aplicação cliente Utiliza a biblioteca de tradução Java
(AMNPrinterJava) para gerar os componentes App_Communication e App_Proxy da API de
suporte para a aplicação host. Conforme descrito na seção 4.5, os demais componentes da API,
referenciados pelas duas classes geradas, não necessitam ser gerados para cada aplicação, sendo
fornecidos junto à ferramenta.
Na seção 4.4.1 descreveu-se uma técnica para possibilitar a verificação entre modelos abs-
tratos e concretos com interface distinta. Através de um refinamento alternativo de adaptação
de interfaces, foi possível que o método BSmart continuasse dentro do escopo de verificação
com o método B.
Nesta seção apresenta-se uma solução alternativa, utilizando a teoria de retrenchment, que
foi inicialmente aplicada visando contornar essa restrição de B. Uma vez que a abordagem
desenvolvida na tese é mais rigorosa, por continuar na teoria de refinamento em B, preferiu-se
incorporá-la ao método em detrimento ao retrenchment.
79
A técnica denominada retrenchment foi proposta por Banach e Poppleton [BP98], com
a motivação de estender a aplicabilidade do desenvolvimento formal para uma gama maior
de aplicações. O retrenchment impõe menos restrições, quando comparado ao refinamento
tradicional, devido a flexibilizar a conexão entre as operações abstratas e concretas.
Ressalte-se que, utilizando-se essa técnica, pode-se especificar e verificar situações que não
seriam permitidas ao refinamento. No retrenchment, é possível fortalecer a pré-condição de
uma operação e/ou enfraquecer a sua pós-condição. Dessa forma, torna-se possível modificar
a interface de uma operação, ou transferir parte do comportamento das variáveis de estado
para variáveis de entrada e saída, ou vice-versa. Por outro lado, os mecanismos que permitem
essa flexibilização, também tornam o retrenchment menos rigoroso em relação ao refinamento
tradicional, conforme será discutido posteriormente nesta seção.
Retrenchment em B
Observa-se que o retrenchment é uma máquina B com a adição de alguns outros compo-
nentes (figura 4.19), a saber, uma (1) cláusula RETRENCHES, contendo o nome da máquina
ou refinamento objeto do retrenchement, uma (2) cláusula RETRIEVES que especifica a rela-
ção entre os estados abstratos e concretos e (3) uma substituição generalizada composta pelas
cláusulas LVAR, WITHIN e CONCEDES, que estende a substituição no corpo de uma operação,
especificando as situações nas quais a operação concreta falha ao refinar a operação abstrata.
Percebe-se que, diferentemente do refinamento em B, onde o invariante local e a relação en-
tre os estados abstratos e concretos são ambos especificados no invariante do refinamento, no
retrenchment, o invariante somente se aplica ao estado concreto.
Com relação às clausulas introduzidas pelo retrenchment, observa-se que a cláusula LVAR
é opcional e deve ser utilizada apenas se for necessário declarar variáveis cujo escopo são as
cláusulas WITHIN e CONCEDES. Uma vez declaradas, essas variáveis devem receber tipo e
restrições aos seus valores em WITHIN.
80
Evidencia-se que a cláusula WITHIN também pode ser utilizada, se necessário, para espe-
cificar o fortalecimento da pré-condição de uma operação. Por sua vez, a cláusula CONCEDES
presta-se ao papel de enfraquecer a pós condição de uma operação. Essas cláusulas adicionais
podem ser precisamente descritas e compreendidas através da definição das obrigações de prova
do retrenchment, o que será feito na próxima seção. Posteriormente, ilustrar-se-á a aplicação do
retrenchment ao desenvolvimento BSmart de modo a permitir a verificação da mudança no tipo
e na interface das operações da máquina inicial para a sua representação Java Card.
Obrigações de prova
ções, quando elas são aplicadas a estados nos quais a pré-condição da operação é satisfeita. A
verificação dessas obrigações de prova garante a consistência interna do módulo.
Aspectos relacionados ao estado abstrato que não estão expressos na relação de retrench-
ment (Ret(vA , vR )) podem ser especificados na cláusula WITHIN (W (pA , pR , vA , vR , A)), sendo
também o lugar de se relacionar as entradas de uma operação abstrata com a sua correspon-
dente concreta, no caso, por exemplo, da mudança na interface entre elas. Por sua vez, no
consequente da obrigação de prova tem-se o predicado da cláusula CONCEDES (C(v_A, v_R,
r_A, r_R, R)). Ele permite especificar comportamentos adicionais relacionados aos estados
concretos e abstratos e aos valores de saída da operação em situações nas quais a relação
de retrenchment não seja satisfeita. Na obrigação de prova, esse comportamento é inse-
rido através da disjunção do predicado concedes com o predicado da relação de retrenchment
(Ret(v_A, v_R) ∨C(v_A, v_R, r_A, r_R, R)).
Figura 4.20: Retrenchment Java Card da especificação abstrata principal J_App (Fig. 4.2).
83
Ressalta-se que o retrenchment Java Card da figura 4.20 foi corretamente verificado utili-
zando a ferramenta Atelier B. Nesse caso, o arquivo de obrigação de prova para o refinamento
foi alterado de forma manual, de modo a acomodar o formato das obrigações de prova do re-
trenchment.
Inicialmente, cumpre destacar que, na tese, o método BSmart foi verificado através do
esquema genérico de desenvolvimento apresentado neste capítulo. Ele ainda foi aprimorado
em dois aspectos, a saber, a proposição do refinamento para verificar a mudança de interface
entre os modelos Java e Java Card e a separação das implementações dos serviços da aplicação
cartão e do modelo da classe applet.
Em suas versões anteriores, o método havia sido avaliado a partir de pequenas especifi-
cações, que por vezes não refletiam as necessidades e características de um desenvolvimento
smart card típico. Neste trabalho, o desenvolvimento do estudo de caso do passaporte eletrô-
nico (capítulo 7), uma aplicação Java Card “real” que utiliza diversas classes da API, foi de
suma importância para analisar e validar o processo de desenvolvimento com o método. A
partir dele, tomou-se a resolução de separar os modelos do applet e dos serviços, testou-se e
aprimorou-se modelos do KitSmart e foram testadas e corrigidas as ferramentas de suporte ao
84
método.
Pretende-se ampliar o método através do modelo do estado global do sistema, desde a codi-
ficação e envio dos parâmetros no cliente, a recepção no cartão, e, por fim, o envio da resposta
do cartão e a decodificação no cliente. Ou seja, o que se pretende é especificar o ambiente de
execução Java Card em uma perspectiva que fornece a verificação ampla do desenvolvimento.
Essa parte do método pode ser especificada utilizando-se o formalismo Event-B, por ser mais
adequado do que o B clássico para a especificação de sistemas.
Cumpre observar que ainda devem ser aprimoradas a abordagem para tratamento de exce-
ções e o modelo do controle de transações. No primeiro caso, a especificação Exception e do
KitSmart é utilizada para indicar o lançamento de uma exceção. No trecho de código correspon-
dente a ser gerado em Java Card, o método de lançamento de exceção é invocado caso aconteça
algum comportamento de exceção que pode ser previsto. Nesse caso, demarca-se o lançamento
de exceção em B. No entanto, ainda não é possível demarcar um trecho de código sob exceção
e verificar, através de obrigações de prova, os comportamentos que possam ser aplicados para o
casos em que a exceção pode ocorrer.
O trabalho de Burdy e Requet [BR03] propõe uma extensão ao método B incluindo cláu-
sulas para modelar o comportamento de exceção da forma como é tratado em linguagens tais
como Java ou C++. Esse trabalho, discutido na seção de trabalhos relacionados, é um ponto de
partida interessante a ser utilizado para aprimorar o mecanismo de exceção no método BSmart.
O controle de transações é outro tópico importante para o desenvolvimento Java Card, visto
que deve-se evitar que o estado da aplicação torne-se inconsistente caso a comunicação seja
interrompida de forma inesperada. Atualmente, as transações são tratadas de forma semelhante
à abordagem para exceções, com o uso de operações da especificação JCSystem para delimitar
o começo e o fim de um trecho de código sob transação. No entanto, além de analisar se esta é a
melhor forma de lidar com transações, é preciso uma maior análise sobre em que circunstâncias
ela deve ser aplicada, uma vez que colocar um código sob o controle de transação é algo custoso
para os recursos limitados do hardware smart card.
85
Cumpre ressaltar outra importante motivação para este ramo do trabalho, a saber, a docu-
mentação da gramática B utilizada na implementação, bem como da tradução de cada elemento
de B para o seu correspondente em Java Card. Assim, a especificação ASF+SDF é um docu-
mento conciso que descreve todo o processo de tradução, podendo ser consultado por aqueles
que forem utilizar ou estender a ferramenta geradora de código.
Salienta-se que, para o propósito da tese, outras abordagens semelhantes baseadas em ca-
samento de padrões e reescrita de termos poderiam ter sido utilizadas. Por exemplo, é possível
citar a linguagem TOM [BBK+ 07], que estende a linguagem Java com construções para casa-
mento de padrões, tipos de dados algébricos e reescrita, e a linguagem para meta-programação
Rascal [KvdSV09], desenvolvida pelo mesmo grupo de pesquisa do ASF+SDF. No entanto,
pesou na escolha de ASF+SDF o fato de alguns componentes do grupo de pesquisa do autor
desta tese já possuírem experiência prévia nesta notação. Nesse sentido, observa-se que a gra-
mática da implementação B utilizada neste trabalho foi inicialmente desenvolvida por Déharbe.
Apenas algumas intervenções tiveram que ser feitas, como a adição de produções, pequenas
correções em produções existentes, e modificações visando a eliminação de ambiguidades.
Este capítulo é dividido conforme descrito a seguir. As próximas duas seções apresentam a
fundamentação desta parte do trabalho, a saber, a descrição de linguagens com SDF (seção 5.1)
e a especificação de regras de reescrita na linguagem ASF (seção 5.2). O processo completo de
especificação da tradução é detalhado na seção 5.3. Por fim, as considerações finais são tecidas
na seção 5.4.
O Syntax Definition Formalism (SDF) [BKV07] é uma meta-linguagem que permite a des-
crição sintática de linguagens na forma de gramáticas livres de contexto e a geração de um
parser a partir dessa descrição. O parser de um programa na linguagem resulta em uma árvore
de parser, tornando possível a sua manipulação e análise por outras ferramentas.
No formalismo SDF, a linguagem é descrita de forma modular, sendo cada módulo res-
ponsável pela definição de parte da gramática. Esse aspecto facilita a tarefa da construção da
gramática e proporciona o reuso de definições em outros módulos, como se verá mais adiante
neste capítulo.
tarefa de especificação. Por sua vez, a descrição em SDF da linguagem Java, alvo da tradução,
foi obtida da biblioteca da ferramenta Meta-Environment.
Um módulo SDF é estruturado conforme o modelo da figura 5.2. O nome do módulo deve
ser inserido após a palavra-chave module. Na seção imports devem ser inseridos os identifica-
dores de outros módulos dos quais a definição atual depende. Na figura, o símbolo + se refere
a uma ou mais ocorrências. As seções que definem a gramática podem ser introduzidas em
exports ou hiddens. No primeiro caso, os elementos da gramática podem ser acessados caso
88
sejam importados por outro módulo. De outro modo, as definições inseridas em hiddens podem
ser vistas apenas dentro do módulo em que são declaradas.
5.1.1 Símbolos
Símbolos são os elementos básicos da gramática. SDF admite três classes de símbolos,
a saber, literal, sort e classes de caracteres. Os literais são utilizados na representação de
símbolos léxicos de tamanho fixo, compostos apenas por letras, correspondendo ao que seriam
os elementos terminais da gramática. Eles devem ser colocados entre aspas, dentro da seção
lexical syntax do módulo, como no exemplo abaixo:
lexical syntax
“true” -> TRUE “false” -> FALSE
Neste exemplo, definem-se duas produções simples para representar os terminais boolea-
nos true e false. O texto após o símbolo “->” corresponde ao identificador da produção.
Observa-se que as aspas duplas tornam os literais sensíveis à caixa. Se for necessário especi-
ficar que os literais podem ser formados por letras maiúsculas e minúsculas, deve-se inseri-los
entre aspas simples.
A tabela 5.1 destaca símbolos que podem ser utilizados na definição da gramática para
representar partes opcionais, sequências, repetições e alternativas.
89
module B−N o t a t i o n / L e x i c a l
i m p o r t s Common / I d e n t i f i e r
i m p o r t s Common / I n t e g e r
h i d d e n s s o r t s A s t e r i s k B−IDENTIFIER
exports
s o r t s B−ASTRING B o o l e a n L i t I n t e g e r L i t S e t I n t e g e r B 0 SetEmpty S e t I n t e g e r
L i s t I d e n t ListIdentComma S e l e c t e d I d e n t L i s t S e l e c t e d I d e n t
l e x i c a l syntax
[ \ " ] ~ [ \ " ] ∗ [ \ " ] −> B−ASTRING
[ \ \ t \ r \ n ] −> LAYOUT
[ \ ∗ ] −> A s t e r i s k
" / ∗ " ( A s t e r i s k | ~ [ \ ∗ ] ) ∗ " ∗ / " −> LAYOUT
"FALSE" −> B o o l e a n L i t
"TRUE" −> B o o l e a n L i t
I n t e g e r L i t e r a l −> I n t e g e r L i t
"MAXINT" −> I n t e g e r L i t
"MININT" −> I n t e g e r L i t
"NAT" −> S e t I n t e g e r B 0
"NAT1" −> S e t I n t e g e r B 0
" INT " −> S e t I n t e g e r B 0
"BOOL" −> S e t I n t e g e r B 0
" {} " −> SetEmpty
" INT " −> S e t I n t e g e r
"INTEGER" −> S e t I n t e g e r
"NAT" −> S e t I n t e g e r
"NAT1" −> S e t I n t e g e r
"STRING" −> S e t I n t e g e r
I n t e g e r L i t e r a l −> I d e n t i f i e r { r e j e c t }
IntegerLit −> I d e n t i f i e r { r e j e c t }
SetInteger −> I d e n t i f i e r { r e j e c t }
SetIntegerB0 −> I d e n t i f i e r { r e j e c t }
SetEmpty −> I d e n t i f i e r { r e j e c t }
BooleanLit −> I d e n t i f i e r { r e j e c t }
c o n t e x t −f r e e s y n t a x
I d e n t i f i e r −> L i s t I d e n t
" ( " { I d e n t i f i e r " , " }+ " ) " −> L i s t I d e n t
{ I d e n t i f i e r " , " }+ −> L i s t I d e n t C o m m a
{ I d e n t i f i e r " . " }+ −> S e l e c t e d I d e n t { a v o i d }
{ S e l e c t e d I d e n t " , " }+ −> L i s t S e l e c t e d I d e n t
lexical restrictions
A s t e r i s k −/− [ \ / ]
" < " −/− [ \ − ]
"<−" −/− [ \ − ]
LAYOUT? −/− [ \ \ t \ r \ n ]
LAYOUT? −/− [ \ / ] . [ \ ∗ ]
tos reject e avoid no módulo Lexical. O primeiro é um mecanismo para filtrar certas derivações
de um dado símbolo, removendo essas derivações da árvore de parser. Por exemplo, em Se-
tIntegerB0 -> Identifier {reject}, rejeita-se o reconhecimento, como identificadores, de uma
cadeia de caracteres correspondendo aos conjuntos inteiros B0. Por sua vez, o atributo avoid,
juntamente com o atributo prefer, também caracterizam-se como filtros sobre alguma produ-
ção. Nesses casos, se a partir de um nó da árvore for necessário fazer uma escolha entre mais
de uma derivação, aquela com prefer será a sub-árvore escolhida. Por outro lado, as derivações
demarcadas com avoid serão preteridas em relação a outras que não tenham avoid.
Ressalta-se que o módulo Instruction (figura 5.4) contém as produções para as substituições
permitidas ao módulo B de implementação, denominadas de instruções. Utiliza-se esse módulo
para exemplificar a definição de não-terminais mais elaborados que aqueles encontrados no
módulo Lexical. Em sua maioria, as instruções de mais alto nível (InstructionLevel1) podem
referenciar uma ou mais instruções internamente na parte THEN da substituição. Instruções
mais complexas, como a condicional, podem ser quebradas em mais de uma produção. O caso
geral do IF é a produção InstructionIf, definida como um ramo if seguido de zero ou mais elsif’s
(ElsifBranch) e opcionalmente por um else (ElseBranch).
5.2 ASF
module B−N o t a t i o n / I n s t r u c t i o n
i m p o r t s B−N o t a t i o n / L e x i c a l B−N o t a t i o n / C o n d i t i o n B−N o t a t i o n / Term
B−N o t a t i o n / C o n d i t i o n B−N o t a t i o n / P r e d i c a t e
exports
sorts I n s t r u c t i o n I n s t r u c t i o n L e v e l 1 I d e n t i t y ( . . . ) I n s t r u c t i o n B l o c k While
c o n t e x t −f r e e s y n t a x
I n s t r u c t i o n L e v e l 1 −> I n s t r u c t i o n { prefer }
I n s t r u c t i o n B l o c k −> I n s t r u c t i o n L e v e l 1 ( . . . )
While −> I n s t r u c t i o n L e v e l 1
( L i s t S e l e c t e d I d e n t "<−−" ) ? S e l e c t e d I d e n t (
" ( " ListTermComma " ) " ) −> I n s t r u c t i o n C a l l u p
L i s t S e l e c t e d I d e n t "<−−" S e l e c t e d I d e n t −> I n s t r u c t i o n C a l l u p
Nesta seção introduz-se uma noção básica de reescrita de termos, suficiente para a com-
preensão do seu uso pelo formalismo ASF. Uma visão mais detalhada sobre o assunto pode ser
encontrada em Terese [Ter03].
Inicialmente, cumpre destacar as noções básicas de termo e reescrita. Um termo (T) é uma
variável (v), uma constante (c) ou uma aplicação de função (f ) sobre termos [Vin05]. Uma regra
de reescrita é um par de termos (T1 → T2 ), sendo o termo T2 o resultado da reescrita de T1 .
pode mais ser simplificado. Nesse estado, diz-se que TF é a forma normal de TI .
2. Caso um redex seja obtido, as variáveis em T2 são substituídas pelos valores encontrados
no casamento do passo 1, resultando no termo T2 ’.
Em ASF as regras de reescrita são descritas através de equations. As equations podem es-
tender a reescrita com a aplicação de regras condicionais. Assim, caso no passo 2, o casamento
tenha ocorrido com uma regra precedida de premissas, o passo 3 será efetivado apenas se as
premissas forem atendidas.
Observa-se que a definição sintática de uma função no arquivo SDF é uma produção da
seguinte forma: <nome_função> (<Prodori >) -> <Proddest >. No caso da função ser utilizada
na transformação entre linguagens, como é o caso nesta tese, Prodori representa uma produção
na linguagem de origem e Proddest a sua correspondente na linguagem de destino. Por sua vez,
94
uma variável é associada a alguma produção nessas linguagens (sob a forma: <nome_variável>
-> <Prod>), recebendo o valor de um termo no casamento de padrões durante o processo de
reescrita, conforme explanado na seção 5.2.1.
Observa-se que, nas equações condicionais, antes que a reescrita possa ocorrer, devem ser
verificadas de forma bem-sucedida uma ou mais condições, que podem ser de três tipos, a saber:
As equações condicionais podem ser descritas de três formas, sintaticamente distintas, mas
com o mesmo significado. Abaixo, <C1 >, <C2 >, . . . , <CN > representam uma ou mais condições.
1. [< nome >] T1 = T2 when <C1 >, <C2 >, . . . , <CN >
Destaca-se, inicialmente, na Seção 5.3.1, a parte sintática (SDF) da tradução. Nela são es-
tabelecidas as assinaturas das funções de tradução que reduzem um termo na árvore B para o
termo correspondente na árvore Java. As implementações dessas funções são parte das equa-
ções (equations) de reescrita inseridas no arquivo ASF correspondente. Além disso, no arquivo
SDF, também são definidas as variáveis utilizadas em cada regra.
Em relação ao componente ASF, na Seção 5.3.2, são delineadas as equações de mais alto
nível. Nas demais seções são apresentadas as regras de tradução para cada construção da im-
plementação B.
É pertinente observar que, devido ao ASF não ter suporte nativo para inferência de tipos, se
escolheu short como o tipo padrão nas regras que referenciam elementos cujo tipo em B pode
ser obtido somente por inferência, como o tipo do retorno e dos parâmetros de uma operação.
Na tradução em si, através da API BCompiler [Cle12b] é possível obter os tipos corretos dessas
construções.
Cumpre ressaltar que os arquivos ASF+SDF, que especificam a tradução, podem ser con-
sultados no Apêndice B. A gramática SDF da linguagem Java pode ser encontrada na biblioteca
da ferramenta de desenvolvimento ASF+SDF Meta-environment [ME09].
P a c k a g e D e c l a r a t i o n ? I m p o r t D e c l a r a t i o n ∗ T y p e D e c l a r a t i o n + −> C o m p i l a t i o n U n i t
Observa-se que, na seção context-free syntax da figura 5.6, são descritas sintaticamente as
funções utilizadas nas regras de reescrita para realizar a tradução. A função de mais alto nível é
trd-bcomp, que recebe como entrada a árvore B contendo o cabeçalho da implementação e um
96
conjunto de 0 (zero) ou mais cláusulas e as reduz a uma árvore Java correspondente, a partir
da qual é gerado o código Java Card. As demais funções, detalhadas posteriormente neste
capítulo, relacionam-se à reescrita de cláusulas, instruções, termos, condições, tipos e demais
elementos de uma implementação B.
Por fim, são definidas, na seção variables, variáveis para representar os não-terminais refe-
renciados nas diversas regras. Conforme descrito anteriormente na seção 5.2.1, as variáveis são
utilizadas no momento do casamento de padrões entre o lado esquerdo da equação de reescrita
e o termo de entrada, sendo ligadas à produção correspondente nesse termo. Quando necessário
à tradução, as variáveis são reduzidas ao termo equivalente em Java. Nesse caso, variáveis re-
presentando não-terminais Java são utilizadas para receber o resultado da redução. Observa-se
que todas as variáveis foram prefixadas com um $. Além disso, as variáveis que representam
listas recebem o sufixo ∗, quando tratar-se de zero ou mais repetições, e o sufixo +, para uma
ou mais repetições.
Cumpre destacar que toda árvore de parser possui, implicitamente, uma produção start que
faz referência ao seu topo. Para ser capaz de iniciar o processo de tradução, deve-se inicialmente
97
realizar o casamento entre essas produções das gramáticas B0 e Java, através das suas funções
start, na regra nomeada como main na figura 5.7. A função start para a árvore B, no lado
esquerdo da regra, recebe a produção inicial Implementation e uma variável $BImpl que irá
receber a raiz da árvore sintática. Por sua vez, no lado direito de main, a função start para Java
recebe o termo inicial CompilationUnit. O parâmetro relacionado à árvore da gramática Java
irá resultar da reescrita de $BImpl por meio da função trd-bcomp.
A regra trd-component (fig. 5.7) usa a função trd-bcomp para iniciar efetivamente a tradu-
ção a partir dos termos iniciais da gramática. No lado esquerdo da regra (após o ===> e antes
do =) é estabelecido o padrão para uma implementação B válida, ou seja, o terminal IMPLE-
MENTATION seguido do nome da máquina ($BId0), da cláusula refines (variável $Refines), de
0 (zero) ou mais cláusulas ($ImpClause*0) e do terminal END.
[ main ]
s t a r t ( I m p l e m e n t a t i o n , $BImpl ) = s t a r t ( C o m p i l a t i o n U n i t , t r d −bcomp ( $BImpl ) )
[ t r d −component ]
$ C l a s s B o d y 1 ∗ : = t r d −c l a u s e s ( $ I m p C l a u s e ∗ 0 )
===>
t r d −bcomp (IMPLEMENTATION $BId0 $ R e f i n e s $ I m p C l a u s e ∗0 END) =
p u b l i c c l a s s $BId0 e x t e n d s j a v a x . f r a m e w o r k . A p p l e t {
$ClassBody1 ∗
}
Para que a reescrita no lado direito ocorra, ainda deve-se verificar a condição anterior à
regra, que no caso estabelece a redução das cláusulas em zero ou mais elementos de corpo de
classe (variável ClassBody1*). Um corpo de classe é definido na produção ClassBodyDeclara-
tion e pode ser qualquer construção em Java que possar estar inserida em um bloco de código
(entre { } abre-e-fecha chaves), tais como métodos, classes internas e declarações de variáveis.
Observa-se que as variáveis $BId0 (um identificador) e $Refines não necessitam ser referencia-
das na condição. No primeiro caso, deve-se ao fato de tratar-se da mesma produção, tanto em
B quanto em Java, não precisando portanto ser reduzida. De outro modo, o identificador do
módulo em $Refines é utilizado apenas no casamento de padrões, não sendo necessária a sua
tradução no código Java.
Evidencia-se que a reescrita irá resultar na classe Java Card da aplicação cartão. Inici-
almente, é inserido o cabeçalho, contendo o mesmo nome do módulo de implementação B,
recebido na variável $BId0, seguido da declaração de importação da classe Applet e do início
do bloco da classe ({). Em seguida, o corpo da classe é formado a partir da reescrita de cada
cláusula B em um elemento equivalente de corpo de classe (variável $ClassBody1*).
5.3.3 Predicados
Salienta-se que, de todo o conjunto de predicados de B, são traduzidos apenas aqueles rela-
cionados à definição de tipos (fig. 5.8), apresentados nesta seção, e os predicados denominados
de condições, descritos na seção 5.3.6. Para a resolução dos predicados de tipagem, são defini-
das as funções trd-pred-to-var-type e trd-pred-to-const-type. A primeira reescreve o predicado
em uma declaração de variável, e a segunda o traduz para uma declaração de constante em Java
(uma variável static final).
Ressalta-se que foram definidas regras que representam a tradução para os tipos inteiros de
Java Card, arrays e sequências (na figura 5.8, apenas a tradução para byte) e objetos. As regras
para reescrita de constantes são semelhantes àquelas para variáveis, acrescentando-se apenas o
prefixo static final à declaração. Por este motivo, elas foram suprimidas da figura 5.8.
[ t r d −p r e d −v a r −t p −p a r e n ] [ t r d −p r e d −v a r −t p −b o o l ]
$ C l a s s B o d y 1 ∗ : = t r d −p r e d −t o −v a r −t y p e ( $ P r e d 1 ) t r d −p r e d −t o −v a r −t y p e ( $BId0 : BOOL) =
===> b o o l e a n $BId0 ;
t r d −p r e d −t o −v a r −t y p e ( ( $ P r e d 1 ) ) =
$ClassBody1 ∗ [ t r d −p r e d −v a r −t p −b o o l −2]
$BId1 == JBOOLEAN
[ t r d −p r e d −v a r −t p −and ] ===>
$ C l a s s B o d y 1 ∗ : = t r d −p r e d −t o −v a r −t y p e ( $ P r e d 1 ) , t r d −p r e d −t o −v a r −t y p e ( $BId0 : $BId1 ) =
$ C l a s s B o d y 2 ∗ : = t r d −p r e d −t o −v a r −t y p e ( $ P r e d 2 ) b o o l e a n $BId0 ;
===>
t r d −p r e d −t o −v a r −t y p e ( $ P r e d 1 & $ P r e d 2 ) = [ t r d −p r e d −v a r −t p −a r r a y −b y t e ]
$ClassBody1 ∗ $BId2 == JBYTE
$ClassBody2 ∗ ===>
t r d −p r e d −t o −v a r −t y p e ( $BId0 : $BId1 −−> $BId2 ) =
[ t r d −p r e d −v a r −t p −o b j e c t ] b y t e [ ] $BId0 ;
t r d −p r e d −t o −v a r −t y p e ( $BId0 : $BId1 ) =
$BId1 $BId0 ; [ t r d −p r e d −c o n s t −t p −seq−b y t e ]
t r d −p r e d −t o −v a r −t y p e ( $BId0 : s e q ( JBYTE ) ) =
[ t r d −p r e d −v a r −t p −s h o r t ] p u b l i c b y t e [ ] $BId0 ;
$BId1 == JSHORT
===> [ t r d −p r e d −v a r −t p −seq1 −b y t e ]
t r d −p r e d −t o −v a r −t y p e ( $BId0 : $BId1 ) = t r d −p r e d −t o −v a r −t y p e ( $BId0 : s e q 1 ( JBYTE ) ) =
s h o r t $BId0 ; p u b l i c b y t e [ ] $BId0 ;
[ t r d −p r e d −v a r −t p −b y t e ]
$BId1 == JBYTE
===>
t r d −p r e d −t o −v a r −t y p e ( $BId0 : $BId1 ) =
b y t e $BId0 ;
5.3.4 Termos
Cumpre destacar que os termos são parte das expressões permitidas para a implementação
B, desde as elementares, tais como identificadores, literais inteiros e booleanos, até expressões
compostas, como as aritméticas. Observa-se que foram implementados o conjunto de termos
destacados nas equações de reescrita das figuras 5.9 a 5.11. Os termos relacionados a estruturas
(struct), recurso pertencente à linguagem B da ferramenta Atelier B, ainda não se encontram
implementados nesta versão.
Os termos básicos são apresentados na figura 5.9. Nela tem-se a definição de que um
SelectedIdent ({Identifier "."}+) é um termo, representado pela variável $SelId, sendo traduzido
para o mesmo identificador em Java Card. Também é trivial a tradução de um literal inteiro,
para o mesmo literal no código Java Card. O conjunto vazio ({}) e a sequência vazia ([]) são
traduzidos para a palavra-chave null em Java. As demais expressões básicas correspondem às
constantes para os valores máximos e mínimos do tipo inteiro e a tradução de um termo entre
parênteses. É importante observar que, na linguagem B0, o tipo inteiro disponível é finito, com
faixa de valores correspondente à faixa disponível para o inteiro de Java.
O último conjunto de expressões reescritas diz respeito às expressões aritméticas (fig. 5.11).
Esses termos são compostos por um ou dois operandos, ou seja, duas expressões ($BTerm0 e
$BTerm1) e um operador. Na condição de cada regra (omitidas da figura, exceto para pri-
meira) os operandos são reescritos nas expressões equivalentes em Java através das variáveis
$JPrExpr0 e $JPrExpr1. Por sua vez, os operadores são simplesmente os terminais correspon-
100
dentes em Java.
5.3.5 Cláusulas
A regra geral para a tradução de cláusulas é trd-clauses (figura 5.12). Caso não haja ne-
nhuma cláusula, a regra trd-clauses() = ; é aplicada. No caso geral, uma lista de cláusulas
casa com a regra nomeada trd-n-clauses. O padrão definido nessa regra é uma cláusula ($Imp-
Clause1) seguida de zero ou mais cláusulas ($ImpClause*). Cada cláusula individual é reduzida
em $ClassBody1* através da sua função trd-clause (sem “s”). Há pelo menos uma função trd-
clause para cada cláusula a ser traduzida, consoante apresentado posteriormente nesta seção. A
segunda variável de corpo de classe ($ClassBody2*) recebe a próxima cláusula a ser reduzida
através de uma nova chamada à função trd-clauses, em um processo que se repete até que todas
as cláusulas sejam traduzidas.
[ t r d −0− c l a u s e ] [ t r d −n−c l a u s e s ]
t r d −c l a u s e s ( ) = ; $ C l a s s B o d y 1 ∗ : = t r d −c l a u s e ( $ I m p C l a u s e 1 ) ,
$ C l a s s B o d y 2 ∗ : = t r d −c l a u s e s ( $ I m p C l a u s e ∗ )
===>
t r d −c l a u s e s ( $ I m p C l a u s e 1 $ I m p C l a u s e ∗ ) =
$ClassBody1 ∗
$ClassBody2 ∗
Figura 5.12: Regras de reescrita para uma sequência de zero ou mais cláusulas
Inclusão de máquinas
Apresentam-se na figura 5.13 as regras de tradução que regem as cláusulas que fazem re-
ferência a especificações externas, a saber, IMPORTS, SEES e PROMOTES. Apenas as equa-
ções que tratam da tradução de uma máquina individualmente são exibidas. No apêndice B
encontram-se as demais regras utilizadas para percorrer uma lista de módulos.
[ t r d −1−import ] [ t r d −s e e s −1]
t r d −i m p o r t s ( $BId0 . $BId1 ) = { t r d −s e e s ( $BId0 . $BId1 ) =
p u b l i c c l a s s $BId1 { } p u b l i c c l a s s $BId1 { }
r e t u r n $BId0 . $BId1 ( p r ) ;
}
No caso de uma máquina importada, deve ser gerada uma nova classe para a máquina
e, na classe applet, um atributo ($BId0) que referencia um objeto do módulo importado. Na
implementação da ferramenta a nova classe é gerada em um arquivo externo e o atributo é
instanciado no método INITIALISATION, que é chamado pelo método construtor da classe,
102
assegurando assim a otimização de que a instância é criada apenas uma vez, no momento da
primeira inicialização. Observa-se através da antecedente da regra (BId0.BId1) que o nome da
máquina importada deve ser obrigatoriamente prefixado com um identificador de instância, de
modo a possibilitar que ele seja traduzido no nome do atributo que será criado.
Ressalta-se que uma máquina vista (cláusula SEES) deve gerar uma classe correspondente.
No entanto, não é preciso criar uma referência a ela no applet, considerando que apenas con-
juntos (objetos) e constantes (variáveis final em Java) podem ser acessados. Dessa forma, esses
componentes, no momento da tradução, são prefixados com o nome da máquina a qual perten-
cem.
Conjuntos
As regras gerais para a reescrita de uma lista de conjuntos são demonstradas na figura 5.14.
A regra de partida é trd-clause que utiliza-se de trd-sets para percorrer a lista. Ressalta-se que
um conjunto em B define um novo tipo de dados. Tendo em vista manter essa semântica, um
conjunto é traduzido em uma classe Java.
[ t r d −c l a u s e −s e t s ] [ t r d −s e t s −n ]
$ C l a s s B o d y 1 + : = t r d −s e t s ( $ S e t s 1 + ) $ C l a s s B o d y 1 + : = t r d −s e t s ( $ S e t s 1 + ) ,
===> $ClassBody2+ : = t r d −s e t s ( $ S e t 1 )
t r d −c l a u s e ( SETS $ S e t s 1 + ) = ===>
$ClassBody1+ t r d −s e t s ( $ S e t s 1 + ; $ S e t 1 ) =
$ClassBody1+
$ClassBody2+
A figura 5.15 exibe as equações que regem a tradução dos conjuntos enumerados (trd-set-
enum) e adiados (trd-set-def ). Na regra trd-lid-to-stat-n, através da função trd-listid-to-stat,
cada elemento de um conjunto enumerado é traduzido em uma constante byte correspondente
no corpo da classe Java Card. Nesse caso, o mais adequado seria a tradução para um tipo
enumerado em Java. Entretanto, observa-se que este recurso não existe na versão Java 1.3, a
máxima permitida a Java Card 2.2.x. No caso dos conjuntos adiados, a nova classe gerada não
103
recebe implementação.
[ t r d −s e t −enum ] [ t r d −l i d −t o −s t a t i c −n ]
$ClassBody1+ := $ClassBody1+ :=
t r d − l i s t i d −t o −s t a t i c −c o n s t ( $ L i s t I d + ) t r d − l i s t i d −t o −s t a t i c −c o n s t ( $ L i s t I d + ) ,
===> $ClassBody2+ :=
t r d −s e t s ( $BId0 = { $ L i s t I d + } ) = t r d − l i s t i d −t o −s t a t i c −c o n s t ( $BId )
p u b l i c c l a s s $BId0 { ===>
$ClassBody1+ t r d − l i s t i d −t o −s t a t i c −c o n s t ( $ L i s t I d + , $BId ) =
} $ClassBody1+
$ClassBody2+
[ t r d −s e t −d e f ]
t r d −s e t s ( $BId0 ) = [ t r d −l i d −t o −s t a t i c −1]
c l a s s $BId0 { } t r d − l i s t i d −t o −s t a t i c −c o n s t ( $BId0 ) =
p u b l i c s t a t i c f i n a l b y t e $BId0 ;
[ t r d −c l a u s e −p r o p ] [ t r d −c l a u s e −v a l u e s ]
$ C l a s s B o d y 1 + : = t r d −p r e d −t o −c o n s t −t y p e ( $ P r e d ) $ C l a s s B o d y 1 + : = t r d −v a l u a t i o n ( $ V a l s 1 + )
===> ===>
t r d −c l a u s e ( PROPERTIES $ P r e d ) = $ C l a s s B o d y 1 + t r d −c l a u s e (VALUES $ V a l s 1 + ) =
$ClassBody1+
[ t r d −v a l u a t i o n −2]
$ J P r E x p r 0 : = t r d −t e r m ( $BTerm0 ) [ t r d −v a l u a t i o n −3]
===> $ J P r E x p r 0 : = t r d −c o n d i t i o n ( $BCond0 )
t r d −v a l u a t i o n ( $BId0 = $BTerm0 ) = ===>
static { t r d −v a l u a t i o n ( $BId0 = BOOL ( $BCond0 ) ) =
$BId0 = $ J P r E x p r 0 ; static {
} $BId0 = ( ( $ J P r E x p r 0 ) ? t r u e : f a l s e ) ;
}
Invariante e inicialização
dimento é semelhante ao que é feito para constantes, com a diferença que os atributos gerados
não são static final.
[ t r d −c l a u s e −i n v ] [ t r d −c l a u s e − i n i t i a l i s a t i o n ]
$ClassBody1+ := $JBlockSt1 + := t r d −i n s t r u c t i o n s ( $ B I n s t s 1 +)
t r d −p r e d −t o −v a r −t y p e ( $ P r e d ) ===>
===> t r d −c l a u s e ( INITIALISATION $ B I n s t s 1 + ) =
t r d −c l a u s e ( INVARIANT $ P r e d ) = v o i d INITIALISATION ( ) {
$ClassBody1+ $JBlockSt1+
}
Operações
Deve-se observar que, antes da efetivação da reescrita, há a redução de dois termos na regra,
um deles contendo a lista de parâmetros da operação ($ListIdComma1+) e outro a instrução
(substituição em B0) no corpo da operação ($BInstL). O primeiro termo é traduzido com o
105
auxílio da função trd-listid-to-param-list, nas equações de reescrita da figura 5.19, que efetiva a
tradução dos parâmetros da operação nos parâmetros equivalentes dos métodos. Por outro lado,
o corpo da operação é traduzido por meio da função trd-instructions, utilizada na reescrita de
cada uma das possíveis instruções em B em suas equivalentes Java.
[ t r d −l i d −param− l i s t −1]
t r d − l i s t i d −t o −param− l i s t ( $BId1 ) = s h o r t $BId1
[ t r d −l i d −param− l i s t −n ]
$FParams1 + : = t r d − l i s t i d −t o −param− l i s t ( $ListIdComma0 + ) ,
$FParams2 + : = t r d − l i s t i d −t o −param− l i s t ( $BId0 )
===>
t r d − l i s t i d −t o −param− l i s t ( $ListIdComma0 + , $BId0 ) =
$FParams1 + ,
$FParams2 +
Figura 5.19: Regra auxiliar para tradução dos parâmetros das operações
5.3.6 Condições
As condições correspondem aos predicados concretos que podem ser utilizados na imple-
mentação, além daqueles relacionados à definição de tipos. Cada sub-termo componente da
condição ($BTermSimp0) é reduzido a uma expressão em Java ($JPrExpr0). O resultado da
reescrita é a composição dessas expressões com o operador equivalente em Java.
5.3.7 Instruções
[ t r d −i n s t r −n ]
$JBlockSt1+ := t rd −i n s t r u c t i o n s ( $BInst0 ) ,
$JBlockSt2+ := t r d −i n s t r u c t i o n s ( $ B I n s t s 1 +)
===>
t r d −i n s t r u c t i o n s ( $BInst0 ; $ B I n s t s 1 +) =
$JBlockSt1+
$JBlockSt2+
[ t r d −i n s t r − i d e n t i t y ] [ t r d −i n s t r −bcmeq −1]
t r d −i n s t r u c t i o n s ( s k i p ) = ; $ J P r E x p r 0 : = t r d −t e r m ( $BTerm0 )
===>
[ t r d −i n s t r −b e g i n ] t r d − i n s t r u c t i o n s ( $ S e l I d : = $BTerm0 ) =
$JBlockSt1 + := t r d −i n s t r u c t i o n s ( $ B I n s t s 1 +) $SelId = $JPrExpr0 ;
===>
t r d − i n s t r u c t i o n s ( BEGIN $ B I n s t s 1 + END) =
{ $JBlockSt1+ }
Figura 5.22: Reescrita das instruções skip, begin-end e becomes equal to.
A chamada a uma operação (fig. 5.23) é reduzida a uma sentença semelhante em Java,
com o retorno da operação sendo recebido por um identificador do lado esquerdo da atribuição,
geralmente o nome de uma variável. Os parâmetros, uma lista de termos separados por vírgula,
são traduzidos em expressões através da função auxiliar trd-list-term-comma. A figura 5.23
também apresenta a reescrita de definições de variáveis locais (regra trd-inst-var). Neste caso,
a tradução da lista de variáveis é feita em duas etapas no código Java. Em primeiro lugar,
os identificadores das variáveis são reescritos em declarações de variáveis locais por meio da
107
[ t r d −i n s t r −v a r ] [ t r d −i n s t r −o p c a l l −1]
$JBlockSt1+ := $JPrExpr1+ :=
t r d − l i s t i d −t o −v a r −d e c l ( $ListIdComma1 + ) , t r d − l i s t −term −comma ( $LTermComma + )
$JBlockSt2 + := t r d −i n s t r u c t i o n s ( $ B I n s t s 1 +) ===>
===> t r d −i n s t r u c t i o n s (
t r d −i n s t r u c t i o n s ( $ S e l I d 0 <−− $ S e l I d 1 ( $LTermComma + ) ) =
VAR $ListIdComma1 + IN $ B I n s t s 1 + END) = $SelId0 = $SelId1 ( $JPrExpr1 + ) ;
$JBlockSt1+
$JBlockSt2+ [ t r d −i n s t r −o p c a l l −2]
t r d − i n s t r u c t i o n s ( $ S e l I d 0 <−− $ S e l I d 1 ) =
[ t r d −l i d −v a r d e c l −1] $SelId0 = $SelId1 ( ) ;
t r d − l i s t i d −t o −v a r −d e c l ( $BId1 ) = s h o r t $BId1 ;
[ t r d −i n s t r −o p c a l l −3]
$ J P r E x p r 1 + : = t r d − l i s t −term −comma ( $LTermComma1 + )
===>
t r d − i n s t r u c t i o n s ( $ S e l I d 1 ( $LTermComma1 + ) ) =
$SelId1 ( $JPrExpr1 + ) ;
Figura 5.23: Reescrita das instruções chamada de operação e definição de variável local.
A instrução condicional IF e suas variações são reescritas nas versões equivalentes do con-
dicional if da linguagem Java. Na figura 5.24 apresenta-se a versão do if com o else. A con-
dição de teste é traduzida em uma expressão condicional ou lógica (trd-condition($BCond0)).
Em seguida constrói-se o corpo executado caso a condição retorne verdadeiro e, por meio da
regra de reescrita trd-else-br, o corpo da parte else.
[ t r d −i n s t r −i f −e l s e ] [ t r d −e l s e −b r ]
$JPrExpr0 : = t r d −c o n d i t i o n ( $BCond0 ) , $JBlockSt1 + := t r d −i n s t r u c t i o n s ( $ B I n s t s 1 +)
$JBlockSt1 + := t rd −i n s t r u c t i o n s ( $ B I n s t s 1 +) , ===>
$ J B l o c k S t 2 ∗ : = t r d −e l s e ( $ E l s e ? ) t r d −e l s e ( ELSE $ B I n s t s 1 + ) =
===> $JBlockSt1+
t r d −i n s t r u c t i o n s (
I F $BCond0
THEN $ B I n s t s 1 +
$Else ?
END) =
i f ( $JPrExpr0 ) {
$JBlockSt1+
} else {
$JBlockSt2∗
}
Ressalta-se que a instrução case (fig. 5.26), açúcar sintático para o condicional if com
vários casos aninhados, possui a regra de tradução como o maior número de condições antes
108
[ t r d −i n s t r −i f −e l s i f −e l s e ] [ t r d −e l s i f −b r ]
$JPrExpr0 : = t r d −c o n d i t i o n ( $BCond0 ) , $JPrExpr0 : = t r d −c o n d i t i o n ( $BCond0 ) ,
$JBlockSt1 + := t rd −i n s t r u c t i o n s ( $ B I n s t s 1 +) , $JBlockSt1 + := t rd −i n s t r u c t i o n s ( $ B I n s t s 1 +) ,
$JBlockSt1 ∗ := trd −e l s i f s ( $ E l s i f 0 ∗) , $JBlockSt1 ∗ := trd −e l s i f s ( $ E l s i f 0 ∗)
$ J B l o c k S t 2 ∗ : = t r d −e l s e ( $ E l s e ? ) ===>
===> trd −e l s i f s (
t r d −i n s t r u c t i o n s ( ELSIF $BCond0
I F $BCond0 THEN $ B I n s t s 1 +
THEN $ B I n s t s 1 + $ E l s i f 0 ∗) =
$Elsif0∗ i f ( $JPrExpr0 ) {
$Else ? $JBlockSt1+
END) = } else {
i f ( $JPrExpr0 ) { $JBlockSt1∗
$JBlockSt1+ }
} else {
$JBlockSt1∗
$JBlockSt2∗
}
da efetiva aplicação da função trd-instructions que casa com o seu padrão. Caso as condições
sejam reduzidas corretamente e o casamento seja estabelecido, a reescrita resulta na instrução
switch de Java.
[ t r d −i n s t r −c a s e −e l s e ] [ t r d −c a s e −or−n ]
$JPrExpr0 : = t r d −t e r m ( $BTermSimp0 ) , $ J S w i t c h B l o c k 0 ∗ : = t r d −o r ( $Or ) ,
$JPrExpr1 : = t r d −t e r m ( $BTermSimp1 ) , $ J S w i t c h B l o c k 1 ∗ : = t r d −o r s ( $Or0 ∗ )
$JBlockSt1 + := t rd −i n s t r u c t i o n s ( $ B I n s t s 1 +) , ===>
$ J S w i t c h B l o c k 0 ∗ : = t r d −o r s ( $Or0 ∗ ) , t r d −o r s ( $Or $Or0 ∗ ) =
$ J B l o c k S t 2 + : = t r d −e l s e ( $ E l s e ? ) $JSwitchBlock0∗
===> $JSwitchBlock1∗
t r d −i n s t r u c t i o n s (
CASE $BTermSimp0 OF [ t r d −c a s e −o r ]
EITHER $BTermSimp1 $JPrExpr0 : = t r d −t e r m ( $BTermSimp0 ) ,
THEN $ B I n s t s 1 + $JBlockSt1 + := t r d −i n s t r u c t i o n s ( $ B I n s t s 1 +)
$Or0 ∗ ===>
$Else ? t r d −o r (OR $BTermSimp0 THEN $ B I n s t s 1 + ) =
END case $JPrExpr0 : {
END) = $JBlockSt1+
switch ( $JPrExpr0 ) { break ;
case $JPrExpr1 : { }
$JBlockSt1+
break ;
}
$JSwitchBlock0∗
default : {
$JBlockSt2+
break ;
}
}
se nenhum dos casos anteriores for satisfeito. Em Java, o termo CASE inicial é reescrito no
cabeçalho do switch, e a parte either no primeiro caso do switch. Os demais casos são tratados
pelas regras trd-or-n que percorre a lista de casos (parte OR) e trd-case-or, que reescreve efeti-
vamente cada OR em um caso correspondente no switch. A situação else é tratada pela mesma
regra de tradução utilizada no IF, sendo as instruções do corpo do ELSE em B inseridas na parte
default do switch.
Cumpre destacar ainda a tradução da instrução de repetição WHILE (fig. 5.27) no comando
while equivalente em Java. Observa-se que os componentes variante e invariante, úteis em B
para verificar a correta terminação do laço de repetição, não são traduzidos em Java.
[ t r d −i n s t r −w h i l e ]
$JPrExpr0 : = t r d −c o n d i t i o n ( $BCond0 ) ,
$JBlockSt1 + := t r d −i n s t r u c t i o n s ( $ B I n s t s 1 +)
===>
t r d −i n s t r u c t i o n s (
WHILE $BCond0 DO
$BInsts1+
INVARIANT $BCond1
VARIANT $BTerm0
END) =
while ( $JPrExpr0 ) {
$JBlockSt1+
}
Apesar do formalismo ASF+SDF contar com uma boa documentação sobre o seu fun-
cionamento e recursos oferecidos, durante o início do processo surgiram dificuldades quanto
ao entendimento de como aplicá-lo na especificação da transformação de linguagens. Nesse
momento, os exemplos fornecidos pela biblioteca da ferramenta Meta-Environment foram fun-
damentais, como o que demonstra a tradução de Pico, uma pequena linguagem criada pelos
desenvolvedores de ASF+SDF, para a linguagem assembly. Alguns bugs do ambiente Meta-
Environment, que por vezes fazem com que ela tenha que ser reiniciada para que volte a funci-
onar corretamente, também dificultaram o início da especificação, mas não comprometeram o
seu progresso.
Observa-se que a atribuição de tipo como um intervalo de inteiros e as estruturas ainda não
foram traduzidos. Um intervalo pode ser implementado por uma biblioteca em B que terá uma
classe equivalente em Java. Nesse caso teríamos uma máquina de biblioteca (e uma classe)
para cada intervalo inteiro permitido. As estruturas, recurso de B implementado pelo Atelier
B, equivalem à construção struct na linguagem C, podendo ser traduzidas para uma classe em
Java, sendo os elementos internos dessa estrutura atributos da classe. Além da inclusão desses
recursos, deve-se realizar, como trabalho futuro, uma revisão completa na gramática B e na
tradução tendo em vista verificar se a totalidade da gramática B de implementação que deve ser
traduzida está de fato sendo tratada.
111
É importante destacar que este ramo da tese teve início no trabalho de Dutra [Dut06], que
desenvolveu os primeiros protótipos dos módulos de tipos primitivos e modelos para lidar com
datas, unidades de medida, dentre outros. Posteriormente, durante os primeiros meses desta
tese, aprimorou-se as especificações para tipos e desenvolveu-se as primeiras versões de má-
quinas B que modelam componentes importantes da API Java Card, tais como as classes de
exceção e as classes APDU, Util e JCSystem.
112
O trabalho de especificação da API teve continuidade, em parceria com este estudo, na dis-
sertação de Santos [San12]. Nesse trabalho, especificou-se a totalidade das 93 classes/interfaces
da API para o Java Card 2.2.2, uma versão recente da API que é amplamente utilizada no mer-
cado. Outra contribuição importante dessa dissertação foi a elaboração de um guia de consulta
para usuários e desenvolvedores da API, indicando as melhores práticas, tipos de dados mais
adequados e exemplos de uso de diversos componentes.
Salienta-se que o estudo de caso do capítulo 7 fez uso de parte da API especificada
em [San12], dos modelos para tipos primitivos básicos e de bibliotecas que encapsulam o valor
de inteiros e sequências de byte em B. Com relação à API, o estudo do passaporte eletrônico
serviu ao seu aprimoramento e validação. Sempre que se verificava necessário em algum com-
ponente, modificava-se o estado e/ou a pré-condição das suas operações, visando compatibilizá-
lo à semântica esperada para a classe Java correspondente ou auxiliar a verificação do módulo
com as ferramentas de suporte ao método B.
O presente capítulo é dividido nas seções descritas a seguir. A seção 6.1 apresenta as
máquinas para tipos primitivos e outros componentes de biblioteca utilizados para encapsular
o estado da implementação. Em seguida, na seção 6.2, destacam-se os modelos das classes e
interfaces da API Java Card. Os módulos de tarefas úteis ao desenvolvimento Java Card são
apresentados na seção 6.3. Por fim, as considerações finais e desenvolvimentos futuros são
apresentadas na seção 6.4.
A biblioteca modela os tipos básicos byte, short e boolean, permitindo a correta atribuição
de tipos a variáveis e constantes e contendo um conjunto de operações sobre esses tipos que
podem ser verificadas quanto à sua correta utilização. O modelo do tipo int padrão também é
fornecido, podendo ser reutilizado pelo desenvolvedor da aplicação host.
É interessante observar que os tipos primitivos discutidos nesta seção possuem estrutura
similar, constituída por constantes que definem cada tipo e sua faixa de valores, assim como
por operações que resultam em valores dentro dessa faixa. Observa-se que tais “operações”,
em verdade, foram especificadas na forma de constantes funcionais na cláusula PROPERTIES
de cada máquina. Tal abordagem foi adotada em virtude do método B não permitir que, no
corpo de uma operação, uma outra operação definida em uma máquina externa seja requisitada
113
mais de uma vez. Portanto, ao utilizar funções ao invés de operações, elimina-se esse problema,
permitindo até mesmo o uso de expressões compostas, como, por exemplo, a soma da seguinte
forma: sum_byte(sum_byte(value,10),20).
Nesse sentido, tem-se como exemplo a figura 6.1, que exibe trechos do componente JShort,
modelo para a definição de variáveis short. Observa-se que, no apêndice A, é possível encontrar
o código completo da especificação JShort, assim como de parte das máquinas apresentadas
neste capítulo. Nessa máquina, a constante JSHORT define o inteiro curto, restrito ao intervalo
deste tipo em Java. Em qualquer máquina que inclua JShort, é possível declarar um novo
short através dessa constante (p.ex. quant ∈ JSHORT). As funções definidas nesse componente
realizam as operações aritméticas básicas, além do módulo, cast e comparações (igual, maior e
maior ou igual) entre dois short’s.
MACHINE JShort
CONCRETE_CONSTANTS
MAXSHORT , MINSHORT , JSHORT,
sum_short, subt_short, mult_short, div_short, mod_short,
cast_short, equal_short, gt_short, gte_short
PROPERTIES
MAXSHORT ∈ Z ∧ MAXSHORT = 32767 ∧
MINSHORT ∈ Z ∧ MINSHORT = -32768 ∧
JSHORT = MINSHORT .. MAXSHORT ∧
cast_short ∈ Z → JSHORT ∧
∀ ( s1 ) . ( s1 ∈ Z =⇒
(s1 = 0 =⇒ cast_short(s1) = 0) ∧
(s1 > 0 =⇒ cast_short(s1) = s1 mod 32767) ∧
(s1 < 0 =⇒ cast_short(s1) = −(−s1 mod 32767)) ) ∧
As máquinas para int (JInt) e byte (JByte) são similares a JShort, alterando-se apenas o
nome da constante que identifica o tipo, sua faixa de valores e o nome das funções, que recebem
o sufixo _jint ou _jbyte. No caso do componente que representa o tipo inteiro para Java Card
(JCInt), desenvolveu-se uma especificação que o implementa através de dois valores do tipo
short.
A especificação para o tipo primitivo boolean (fig. 6.2) define o conjunto JBOOLEAN em
114
função do tipo BOOL em B e as operações lógicas básicas sobre operandos booleanos, tais
como, conjunção, disjunção e negação.
MACHINE JBoolean
CONCRETE_CONSTANTS
JBOOLEAN, or_boolean, lor_boolean, and_boolean,
land_boolean, lnot_boolean, lxor_boolean
PROPERTIES
JBOOLEAN = BOOL ∧
Cumpre ressaltar que a especificação KitSmart para modelos básicos ainda inclui máquinas
de biblioteca para encapsular o estado da implementação. Foram definidos componentes para os
tipos básicos inteiros e sequências de bytes. No mínimo, cada um desses módulos deve possuir
operações para atribuir valores ao estado e para consultá-lo.
É possível que os módulos oferecidos sejam alterados para algum propósito particular. Por
exemplo, a figura 6.3 exibe a biblioteca para uma sequência de bytes, utilizada no estudo de
caso do passaporte eletrônico (capítulo 7). Nesse caso, a inicialização da máquina foi modi-
ficada para inicializar uma sequência de 8 bytes com o valor zero. Observa-se que além das
operações para inserir e obter uma sequência armazenada, outras operações úteis são forneci-
das, permitindo, por exemplo, a inserção de valores em um posição da sequência (addFirst, set
(ii, vv)), obter o seu tamanho (numberOfElements), e verificar se ela está cheia (isFull).
A versão atual desta parte do KitSmart foi desenvolvida tendo como guia principal a docu-
mentação da API Java Card 2.2.2 [SM10]. Outras referências importantes, descritas em maiores
115
MACHINE LM_SEQ_1
SEES JByte, JShort
CONSTANTS BT_maxsize
PROPERTIES BT_maxsize ∈ JSHORT ∧ BT_maxsize = MAXSHORT- 1
VARIABLES bt_seq
INVARIANT bt_seq ∈ seq(JBYTE) ∧ size(bt_seq) ≤ BT_maxsize
INITIALISATION bt_seq := [0, 0, 0, 0, 0, 0, 0, 0]
OPERATIONS
nn ← numberOfElements =
BEGIN nn := size(bt_seq) END ;
bb ← isFull =
BEGIN bb := bool(size(bt_seq) = BT_maxsize) END ;
vv ← get (ii) =
PRE ii ∈ JSHORT ∧ ii ∈ 1 .. size(bt_seq)
THEN vv := bt_seq(ii) END ;
vv ← getSeq =
BEGIN vv := bt_seq END;
addFirst (vv) =
PRE vv ∈ JBYTE ∧ size(bt_seq) < BT_maxsize
THEN bt_seq:= vv → bt_seq END ;
set (ii, vv) =
PRE ii ∈ JSHORT ∧ ii ∈ 1 .. size(bt_seq) ∧ vv ∈ JBYTE
THEN bt_seq(ii) := vv END ; (...)
END
Figura 6.3: Definição do estado e algumas operações da biblioteca para sequência de byte.
detalhes no capítulo 8, foram a especificação da classe APDU em JML [LC06], descrita no tra-
balho de Meijer e Poll [MP01] e o trabalho de mestrado de Larson [Lar03], que desenvolveu
a especificação de parte das classes da API 2.2.1 na linguagem Object Constraint Language
(OCL) [OMG10].
Na abordagem proposta nesta tese, os modelos da API Java Card aplicam-se a três propó-
sitos principais, a saber: (i) prover módulos B verificados de todas as classes e interfaces da
versão Java Card 2.2.2, (ii) permitir a verificação do uso adequado desses módulos em relação
aos dados recebidos e a dependências na chamada de uma operação e (iii) facilitar o trabalho da
ferramenta geradora de código de B para Java, que irá traduzir uma chamada de operação ou o
acesso a uma constante na construção equivalente em Java.
Inicialmente, durante o início da tese, foram criadas as primeiras versões dos modelos de
classes importantes da API, na versão 2.2.1, tais como APDU, JCSystem, Util e ISO7816, clas-
ses de exceção, dentre outras. A primeira é uma das classes mais importantes da API. Através
dela é possível acessar o buffer APDU para envio e recepção de informações na classe applet.
Já a classe JCSytem é responsável, dentre outras funções, por delimitar um trecho de código sob
controle de transação. A classe Util, por sua vez, contém operações diversas, tais como obter
um short a partir de um array de bytes e realizar a cópia de um array em outro. Com relação
às classes de exceção, havia sido especificado apenas o componente Exception, contendo um
116
Salienta-se que o trabalho de Santos [San12] contribuiu com a presente tese ao aprimorar
as máquinas desenvolvidas anteriormente, compatibilizando-as com a versão 2.2.2, revisando e
alterando (quando necessário) as especificações, em particular as pré-condições das operações.
As alterações eram motivadas pela experiência prática do uso e teste dessas especificações no
estudo de caso do capítulo 7. É importante destacar que em [San12] foram especificadas todas
as 93 classes/interfaces da API, divididas entre os pacotes da figura 6.4.
Figura 6.4: Quantidade de classes por pacote na API 2.2.2. Fonte [San12].
Nas seções seguintes são apresentadas as contribuições recentes à API. O modelo da classe
APDU (seção 6.2.2) será utilizado para ilustrar as abordagens da API para tratar diversas situ-
ações. Dentre elas, é possível destacar as exceções (seção 6.2.3), os tipos abstratos de dados
(seção 6.2.4) e os métodos sobrecarregados e sobrescritos (seção 6.2.5).
Nesta seção enfatizam-se algumas características comuns aos diversos módulos e diretrizes
gerais utilizadas na modelagem da API. Em primeiro lugar, nas operações de cada módulo,
decidiu-se por fornecer a especificação da interface, das pré-condições e uma implementação
mínima em seu corpo. Nesse último caso, são especificados o tipo esperado de retorno (quando
houver) e, em algumas máquinas (por exemplo, Apdu e JCSystem), a atualização no estado
da especificação. Essa especificação mínima em cada operação se deve ao fato da API já se
encontrar desenvolvida em Java, e da especificação das restrições e possíveis situações de erro
em sua pré-condição ser suficiente, na maioria dos modelos (exceto os que possuem estado
interno), para as verificações durante o uso de uma operação. Por esses mesmos motivos, as
máquinas que modelam a API não foram refinadas.
associar uma pré-condição a uma restrição observada no método, sendo as restrições, no có-
digo Java, normalmente relacionadas a um lançamento de exceção caso não sejam obedecidas.
Para aqueles comportamentos excepcionais que não podem ser antecipados, tais como exce-
ções associadas a erros durante a execução, por exemplo, durante uma interação com o JCRE,
os comentários inclusos servem para alertar ao usuário que elas podem ocorrer em determinadas
situações.
Como exemplo de especificação de uma classe da API, apresenta-se nesta seção a máquina
que modela a classe APDU. Consoante apresentado no capítulo 2 (seção 2.1), essa classe é
um dos principais componentes da API Java Card, sendo responsável por encapsular toda a
comunicação com a aplicação host. O seu modelo B é dividido entre as máquinas Apdu e
Apdu_Properties. Essa última, exibida na figura 6.5, contém as definições estáticas do módulo
Apdu, tais como as constantes que representam o estado em que a comunicação se encontra
(constantes que iniciam com STATE_).
MACHINE Apdu_Properties
SEES
JByte, JShort
SETS
/* Conjunto que representa o tipo APDU */
APDU
CONCRETE_CONSTANTS
STATE_INITIAL,
STATE_PARTIAL_INCOMING,
STATE_FULL_INCOMING,
STATE_OUTGOING,
STATE_OUTGOING_LENGTH_KNOWN,
STATE_PARTIAL_OUTGOING,
STATE_FULL_OUTGOING, (...)
BUFFER_LENGTH
PROPERTIES
STATE_INITIAL ∈ JBYTE ∧ STATE_INITIAL = 0 ∧
STATE_PARTIAL_INCOMING ∈ JBYTE ∧ STATE_PARTIAL_INCOMING = 1 ∧
STATE_FULL_INCOMING ∈ JBYTE ∧ STATE_FULL_INCOMING = 2 ∧
STATE_OUTGOING ∈ JBYTE ∧ STATE_OUTGOING = 3 ∧
STATE_OUTGOING_LENGTH_KNOWN ∈ JBYTE ∧ STATE_OUTGOING_LENGTH_KNOWN = 4 ∧
STATE_PARTIAL_OUTGOING ∈ JBYTE ∧ STATE_PARTIAL_OUTGOING = 5 ∧
STATE_FULL_OUTGOING ∈ JBYTE ∧ STATE_FULL_OUTGOING = 6 ∧ (...)
BUFFER_LENGTH ∈ JSHORT ∧
BUFFER_LENGTH ≥ 0 ∧ BUFFER_LENGTH ≤ 133
END
Cumpre observar que a divisão do componente APDU em duas especificações foi necessária
118
A figura 6.6 exibe a parte da máquina Apdu relacionada à definição das suas variáveis de
estado. A cláusula EXTENDS nesse módulo representa a hierarquia de herança para o compo-
nente APDU, que herda diretamente a classe Object. Vale relembrar que ao referenciar uma
máquina em EXTENDS, todas as suas operações tornam-se operações do módulo que a estende.
Em todos os outros módulos o mecanismo de extensão é utilizado, fazendo com que o modelo
se aproxime ainda mais da semântica que é encontrada na API Java Card.
A implementação no corpo das operações da API está relacionada à pós-condição que deve
ser observada após a sua aplicação. No caso do exemplo, modifica-se o estado da comunicação
entre as aplicações host e cartão através da variável state para o estado posterior à aplicação
da operação. Os valores esperados de retorno também são especificados, como no caso de
setOutgoing, que retorna o valor do tamanho esperado da resposta (le).
result ← setOutgoing =
PRE
(state = STATE_INITIAL ∨ state = STATE_PARTIAL_INCOMING ∨
state = STATE_FULL_INCOMING)
THEN
state := STATE_OUTGOING || result := le
END;
setOutgoingLength(len) =
PRE
len ∈ JSHORT ∧ len ≥ 0 ∧ len ≤ 256 ∧
state = STATE_OUTGOING
THEN
state := STATE_OUTGOING_LENGTH_KNOWN ||
lr := len
END;
sendBytes(bOff, len) =
PRE
bOff ∈ JSHORT ∧ bOff ≥ 0 ∧
len ∈ JSHORT ∧ len ≥ 0 ∧ len ≤ lr ∧
sum_short(bOff,len) ≤ BUFFER_LENGTH ∧
state = STATE_OUTGOING_LENGTH_KNOWN
THEN
CHOICE state := STATE_PARTIAL_OUTGOING
OR state := STATE_FULL_OUTGOING
END ||
lr := subt_short(lr, len)
END;
Neste trabalho, utiliza-se o modelo robusto de antecipar as exceções que podem ser pre-
vistas, conforme indicado na documentação oficial da API, incluindo-se na pré-condição um
predicado relacionado à exceção e o comentário associado que é encontrado na documentação.
Assim, a restrição adicionada irá gerar uma ou mais obrigações de prova quando a operação
for utilizada em algum módulo B, que deve então descartá-la de algum modo. Como exem-
plo, a figura 6.8 exibe a versão completa da operação setOutgoingLength, com os predicados
de exceção e seus comentários associados adicionados na pré-condição. Geralmente, em um
refinamento, um condicional é utilizado, contendo na condição de teste a(s) restrição(ões), fa-
zendo com que a operação seja aplicada apenas se elas forem atendidas. Em caso contrário,
normalmente reporta-se a exceção ao cliente.
setOutgoingLength(len) =
PRE
len ∈ JSHORT ∧
/*APDUException if ’len’ is negative*/
len ≥ 0 ∧
/* APDUException if ’len’ is greater than 256
and the currently selected applet does not implement
the javacardx.apdu.ExtendedLength interface */
len ≤ 256 ∧ state = STATE_OUTGOING
/* APDUException if setOutgoing() or setOutgoingNoChaining()
not called or if setOutgoingAndSend() already invoked,
or this method already invoked */
/* APDUException I/O error */
THEN
state := STATE_OUTGOING_LENGTH_KNOWN || lr := len
END;
É sabido que B não fornece suporte à declaração de tipos abstratos de dados que associem
um nome a uma estrutura contendo dados e operações relacionados, tal como uma classe em
Java. O mais próximo que se pode chegar em B é declarar uma variável como uma estrutura
(struct), recurso presente na linguagem B fornecida pelo Atelier B. Nesse caso, apenas o estado
do tipo é armazenado nos campos da estrutura, semelhante à struct de C.
121
Figura 6.9: Definição do estado da máquina APDU com uma estrutura representando o tipo
APDU.
Ocorre que o provador da ferramenta Atelier B, talvez por algum bug na versão 4.01 uti-
lizada no desenvolvimento do trabalho, não consegue provar, na implementação B, os lemmas
para estruturas. Dessa forma, preteriu-se essa solução pela representação do tipo abstrato como
um conjunto, conforme pode-se vislumbrar na figura 6.5, que contém a constante APDU para
representar o tipo APDU. Ressalta-se que essa abordagem ainda deve ser alvo de um estudo
mais aprofundado como trabalho futuro, incluindo-se a investigação da falha apresentada pela
ferramenta de verificação ao se trabalhar com estruturas.
IMPLEMENTATION JCApplet_imp
REFINES JCApplet_ref (...)
OPERATIONS (...)
process (apdu) =
VAR bf, cla, ins, p1, p2, lc, data_in, lr, data_out, apdu_state, res, res2
IN
bf ← apdu.getBuffer;
cla := cast_byte (0); ins := cast_byte (0); p1 := cast_byte (0); p2 := cast_byte (0); lc := cast_byte (0);
(...)
END
Os módulos destacados nesta seção visam fornecer ao KitSmart modelos que podem ser
úteis ao desenvolvimento smart card, que muitas vezes são parte de APIs para a linguagem
Java, mas que não encontram-se implementados na API Java Card padrão. Nessa categoria de
biblioteca é possível incluir componentes que lidam com tempo (data, hota, etc.), internaciona-
lização, unidades de medida, dentre outros.
O trabalho de Dutra desenvolveu versões iniciais dos módulos Date (fig. 6.12), contendo
operações com datas, Time, semelhante à anterior, mas aplicada a tempo (horas, minutos e se-
123
gundos), Measure, voltada à manipulação de medidas com números reais e Person, que trata do
armazenamento de informações pessoais (nome, cpf, endereço, etc.). Na abordagem utilizada,
cada modelo em B é acompanhado da sua classe correspondente em Java Card, geradas a partir
da sua implementação B com a ferramenta BSmart. Assim, asseguram-se as verificações com o
uso do módulo em B e o reuso da classe para aquele módulo no código gerado para Java, sem
a necessidade de sintetizá-lo novamente para cada nova aplicação.
MACHINE Date
SEES JShort, JBoolean
CONCRETE_VARIABLES day, month, year
INVARIANT
day ∈ JSHORT ∧ day ∈ 1 .. 31 ∧
month ∈ JSHORT ∧ month ∈ 1 .. 12 ∧
year ∈ JSHORT ∧ year ∈ 1 .. 30000
INITIALISATION day := 1 || month := 1 || year := 1
OPERATIONS
setDate(dd,mm,yy) =
PRE
dd ∈ JSHORT ∧ dd ∈ 1 .. 31 ∧
mm ∈ JSHORT ∧ mm ∈ 1 .. 12 ∧
yy ∈ JSHORT ∧ yy ∈ 1 .. 30000 ∧
(dd = 31 =⇒ mm ∈ {1,3,5,7,8,10,12}) ∧
(mm = 2 =⇒ (dd ≤ 28 ∨ (dd = 29 ∧ (mod_short(yy,400) = 0 ∨
(mod_short(yy,4) = 0 ∧ mod_short(yy,100) 6= 0)))))
THEN
day := dd || month := mm || year := yy
END;
res ← getDay =
BEGIN res := day END;
res ← getMonth =
BEGIN res := month END;
res ← getYear =
BEGIN res := year END; (...)
END
Devido ao tempo necessário requerido pela especificação da API Java Card, na dissertação
de Santos, os componentes de biblioteca foram apenas atualizados, o que compreendeu com-
patibilizar a sua sintaxe com o Atelier B e incluir as versões mais recentes das máquinas de
tipos.
Neste capítulo apresentou-se a biblioteca KitSmart, que disponibiliza modelos para tipos
de dados, componentes reutilizáveis com tarefas úteis ao desenvolvedor e máquinas correspon-
dentes a todas as classes da API Java Card na versão 2.2.2.
124
Sobre tópicos que devem ser melhor pesquisados, ressalta-se a representação de tipos de
dados abstratos (objetos), o que atualmente é feito através de conjuntos com o nome do tipo. A
abordagem de utilizar estruturas em B pode ser uma solução, apesar de ter apresentado falhas
no momento da verificação com a versão 4.01 da ferramenta. A investigação das causas dessa
falha também faz parte do trabalho, e poderá indicar a continuidade ou não da solução de utilizar
estruturas.
Enfatiza-se que, recentemente, foi lançada a especificação Java Card 3.0 [Ora12]. Nessa
nova versão, o desenvolvimento de que trata o presente trabalho é denominado de classic, sendo
apenas uma atualização da especificação 2.2.2. Como novidade, tem-se um modelo de desen-
volvimento denominado de connected, no qual a aplicação cartão pode ser implementada como
um servlet, recebendo e enviando informações via protocolo http. O Java Card connected
aproveita a capacidade de cartões recentes, com processadores de 32 bits (8 bits na 2.2.2) e
maior capacidade de memória volátil e não-volátil, o que permite o suporte a recursos recentes
da linguagem Java. Atualmente, é possível compilar para o Java 6, com suporte a execução
concorrente (threads), Strings, o tipo int, enum, generics, coleta de lixo, dentre outras. Como
trabalhos futuros deve-se fornecer a especificação para a API classic e investigar que contribui-
ções podem ser oferecidas ao Java Card 3.0 connected.
Com respeito ao suporte de bibliotecas para tarefas úteis ao desenvolvedor Java Card, é
importante enfatizar que, até o presente momento, eles ainda encontram-se tal qual implemen-
tados em [Dut06]. Em [San12], foram feitas apenas atualizações sintáticas para a notação do
Atelier B, bem como atualizou-se a referência às bibliotecas básicas de tipos. Na continuação
do desenvolvimento desse ramo do KitSmart, pretende-se investigar outros módulos que devem
ser inseridos, como por exemplo, um modelo para internacionalização (códigos de países, mo-
edas, etc.), possivelmente derivado de classes da API Java padrão. As máquinas, refinamentos,
e classes já implementadas devem passar por uma revisão e ser objeto de testes.
Outro ponto a ser observado diz respeito à interação do ambiente de execução Java Card
com alguns componentes, tais quais as classes APDU e JCSystem. Esse procedimento pode
ocorrer, por exemplo, quando a classe APDU recebe um comando a ser processado. É impor-
tante deixar claro que, na proposta deste trabalho, esses detalhes da interação das classes com
o ambiente de execução não foram modelados. Entretanto, deve-se pesquisar se essas intera-
ções devem ser especificadas (e a melhor forma de fazê-lo), tendo em vista que parte dos erros
(exceções) gerados durante a execução tem origem durante a comunicação do JCRE com as
aplicações.
125
Ressalte-se que, ao longos dos anos, diversos mecanismos físicos de segurança vêm sendo
incorporados aos passaportes, como marcas d’água, tintas especiais (fluorescentes, sensíveis a
infravermelho, etc.), adesivos holográficos, dentre outros. Essas tecnologias têm por objetivo
impedir (ou, ao menos, dificultar) falsificações, tais como a cópia não autorizada de partes do
documento, a simulação das técnicas de manufatura do passaporte visando reproduzí-lo e a
adulteração de um documento original válido, substituindo-se os dados pessoais do portador ou
a sua fotografia.
Com o objetivo de aprimorar ainda mais a segurança dos documentos de viagem, provendo
mecanismos que permitam maiores garantias de autenticidade e confidencialidade, a partir de
1998, a ICAO estabeleceu um grupo de trabalho que tem por missão o estudo e especificação
de novos sistemas de identificação biométrica e os meios de armazenamento seguro dessas in-
formações nos passaportes. O grupo de trabalho, denominado de New Technologies Working
Group (NTWG), ficou responsável por definir os mecanismos de identificação biométrica que
seriam incorporados ao documento, qual meio físico de armazenamento seria utilizado e, ainda,
a estrutura de dados que seria utilizada para a padronização global do armazenamento e recu-
peração de arquivos no passaporte.
Part I - Machine Readable Passports [ICA06], que contém as especificações oficiais do passa-
porte eletrônico.
É importante observar que apesar de não ser obrigatório que os passaportes emitidos sejam
eletrônicos, a adoção do sistema de dados biométricos armazenados de forma segura em um
cartão inteligente tem sido gradativamente implementada pelas nações ao redor do mundo para
aumentar a segurança na identificação, minimizar o risco de fraudes e agilizar os procedimentos
de controle migratório e expedição de outros documentos de viagem, como vistos. Atualmente,
diversos países já utilizam-se do passaporte eletrônico, como os países membros da União Eu-
ropéia, Estados Unidos e, a partir de fevereiro de 2011, o Brasil, com a implementação de um
modelo de passaporte eletrônico semelhante ao europeu.
Este capítulo é dividido conforme descrito a seguir. A seção 7.1 apresenta os principais
trabalhos e a documentação utilizada como referência para o estudo de caso. Na seção 7.2
detalha-se a aplicação de passaporte eletrônico, sua estrutura de armazenamento de dados e
seus protocolos de segurança. Na seção 7.3 é descrita a especificação textual dos requisitos
funcionais dos serviços do passaporte que foram implementados. O desenvolvimento formal
do passaporte tem início na seção 7.4, que descreve a máquina abstrata Passport. Por sua vez,
127
Outra referência importante é o trabalho de Erik Poll e do seu grupo de pesquisa da Univer-
sidade de Radboud [OOS11]. Eles desenvolveram uma implementação open source do passa-
porte eletrônico utilizando a linguagem Java Card com base na documentação da ICAO. Essa
implementação, denominada de Java Machine Readable Travel Document, implementa os pro-
tocolos presentes no modelo de passaporte europeu e permite a consulta aos dados armazenados
através de uma aplicação terminal desenvolvida em Java.
dos, como o que fazer em caso de falha na execução de um comando ou algumas das possíveis
combinações de protocolos.
O reconhecimento facial foi definido como o meio biométrico padrão para permitir a in-
teroperabilidade entre os sistemas de diversos países, tendo em vista que esse é um meio de
identificação amplamente utilizado e socialmente aceito. Os outros dois métodos podem ser
utilizados como elementos adicionais, dessa forma aumentando a segurança e a precisão na
identificação. No caso do passaporte brasileiro, o meio adicional utilizado é o armazenamento
da impressão digital de dois dedos do portador do documento.
A página de dados do passaporte (figura 7.1) contém informações que identificam o seu
portador, como o seu nome, número do passaporte, nacionalidade, data de expiração do docu-
mento, fotografia, dentre outras. Essas informações estão disponíveis em duas áreas distintas.
A primeira, denominada de Visual Inspection Zone (VIZ), ocupa a maior parte da página a par-
tir do topo é utilizada para a inspeção visual. A outra área, localizada em duas linhas de texto,
abaixo da página, é chamada de Machine Readable Zone (MRZ), sendo utilizada para acesso
através de dispositivos de leitura ótica (OCR).
A LDS é constituída por uma série de 19 grupos de dados (Data Groups (DG)) e por 3 ar-
quivos adicionais contendo informações sobre os Data Groups ou sobre os seus componentes,
denominados de Data Elements. Por exemplo, o primeiro data group (DG1) contém as infor-
mações da Machine Readable Zone, cada uma armazenada como um data element distinto (tipo
130
Desses 19 data groups, apenas o DG1 e o DG2 são obrigatórios. Caso estejam presentes,
o armazenamento de impressões digitais é feito no DG3 e as informações colhidas da íris, por
sua vez, no DG4. Ressalte-se que os grupos de 17, 18 e 19 são reservados para uso futuro, com
a intenção de permitir que a nação que está recebendo um indivíduo possa gravar informações
adicionais, tais como o visto e o registro de ocorrências durante a viagem. Observe-se que a ver-
são atual da especificação permite apenas operações de leitura após a emissão do documento.
Os arquivos adicionais que fazem parte da estrutura da LDS são os apresentados abaixo.
Maiores detalhes acerca desses componentes são fornecidos na parte IV do volume II da espe-
cificação, que trata dos protocolos componentes do passaporte.
EF.COM - Informação de versão da LDS e uma lista de tags que identifica cada elemento
componente da LDS.
Dos protocolos apresentados na seção 7.2.4, apenas o Passive Authentication (PA) é de im-
plementação obrigatória de acordo com a especificação. No entanto, os demais protocolos ge-
ralmente são utilizados para assegurar a autenticidade do documento, no que diz respeito ao país
ou entidade que o emitiu e a legitimidade das informações pessoais armazenadas. Evidencia-
se que o passaporte brasileiro [Pol10], assim como o modelo europeu, implementa todos os
protocolos de segurança descritos na seção 7.2.4.
Na criptografia assimétrica, um algoritmo é utilizado para emitir duas chaves e, com base
nelas, realizar os processos de cifragem e decifragem. Uma delas, a chave pública, pode ser
132
enviada a qualquer pessoa que deseje cifrar uma mensagem que será enviada e decodificada
apenas pelo destinatário, utilizando-se a outra chave do par, a chave privada. Nesse caso, pode-
se dizer que há confidencialidade na troca de informações, uma vez que somente o proprietário
da chave privada poderá decifrar as mensagens cifradas com a sua chave pública correspon-
dente. Assim, é essencial para preservar o sigilo e a confidencialidade na troca de mensagens
que a chave privada seja protegida e mantida em segredo pelo seu proprietário.
Ressalta-se que os algoritmos assimétricos são bem mais lentos e requerem maior capa-
cidade de processamento quando comparados aos simétricos. Dessa forma, geralmente essas
abordagens são utilizadas em conjunto, aproveitando o que há de mais vantajoso em cada uma.
Nessa abordagem, um algoritmo de chave simétrica é utilizado para encriptar os dados (a men-
sagem) e a chave pública do receptor é utilizada para encriptar a chave simétrica de sessão que
encriptou a mensagem. Ao chegar ao receptor, ele usa a chave privada para decriptar a chave de
sessão, que por sua vez é usada para decriptar a mensagem.
Se eles forem iguais, então pode-se dizer que o arquivo pertence ao emissor e não foi adulterado.
Certificação Digital
No sistema de passaporte eletrônico, cada Estado é independente para gerar as chaves que
serão utilizadas na assinatura digital de certificados. A proteção de chaves privadas é de res-
ponsabilidade da nação que as gerou, e as chaves públicas devem ser distribuídas entre todos os
Estados que utilizam o sistema de passaporte eletrônico.
A presente seção fornece uma visão geral dos protocolos que servem ao propósito de au-
tenticação e de restrição do acesso aos dados do passaporte apenas a terminais autorizados. Em
maior destaque encontram-se os protocolos Passive Authentication (PA) e Basic Access Control
(BAC), que são os dois protocolos tratados na versão atual da especificação apresentada neste
trabalho. Os demais serão acrescentados em uma versão futura do desenvolvimento.
PA (Passive Authentication)
1. Leitura do Document Security Object (SOD ). O SOD pode opcionalmente conter o Docu-
ment Signer Certificate (CDS ).
Caso as verificações feitas nos passos 3 e 4 estejam corretas, significa que o conteúdo do
SOD é confiável. Se o passo 7 for bem-sucedido assegura-se que os conteúdos dos data groups
não foram modificados.
O Basic Access Control (BAC) é o protocolo inicial para permitir a comunicação segura
entre a aplicação host e o chip. Uma implementação de passaporte que suporta o BAC nega o
acesso ao conteúdo do chip até que o sistema de inspeção (terminal de leitura) prove que está
autorizado a obter esse conteúdo.
O uso do BAC previne o acesso não autorizado ao chip, evitando duas violações de segu-
rança, são elas, o skimming e o eavesdropping. A primeira é a capacidade de leitura dos dados
contidos no chip por meio eletrônico sem a necessidade de abrir o documento, ou mesmo tê-lo
em mãos. Já a segunda diz respeito a escuta de uma comunicação não-criptografada entre a
aplicação terminal e o applet dentro de uma distância de alguns metros.
O protocolo BAC pode ser resumido a partir da execução das seguintes etapas:
AA (Active Authentication)
O protocolo Active Authentication (AA) tem por objetivo assegurar a autenticidade do chip
e das informações armazenadas no Document Security Object (SOD ). De outra forma, a verifi-
cação bem-sucedida com o AA garante que o chip e seus dados não foram clonados.
O chip deve possuir uma chave pública (KPuAA ) e uma chave privada (KPrAA ) específicas
para Active Authentication. A chave pública para AA (KPuAA ) é inserida no data group 15 da
LDS. A representação hash desse data group é autenticada pela assinatura digital do emissor do
passaporte, sendo armazenada no (SOD ). Por sua vez, a chave privada é armazenada de forma
protegida na memória do chip smart card.
1. Envio, pelo terminal, de uma mensagem (de tamanho recomendado de 8 bytes) para o
cartão.
2. A mensagem é recebida pelo cartão, assinada digitalmente com a chave privada KPrAA e
devolvida ao cliente.
Nesta seção é descrita a especificação textual dos serviços do passaporte eletrônico que
foram desenvolvidos neste estudo. Essa abordagem inicial tem por objetivo descrever os requi-
sitos funcionais e as restrições impostas por esses serviços de forma a facilitar a compreensão
da sua especificação formal em B, composta por diversos máquinas e refinamentos, em um
desenvolvimento seguindo o método BSmart.
É importante salientar que são especificados apenas os serviços fornecidos pela aplicação
cartão (applet), uma vez que essa aplicação é o foco principal do método BSmart, juntamente
com a geração da interface de comunicação dos serviços do applet fornecidos à aplicação cli-
ente. No entanto, observa-se que parte do serviço global da aplicação é processada pela aplica-
ção cliente, utilizando-se de APIs de terceiros para permitir, por exemplo, cifragem/decifragem
de informações, a geração de funções de resumo (hash) e a criação de chaves de segurança,
conforme requerido pelos protocolos da aplicação código-aberto JMRTD. Devido à complexi-
dade em se lidar com uma grande quantidade de código Java de terceiros, o processamento na
parte cliente não é tratado na versão atual do desenvolvimento.
Pré-requisitos:
1. O BAC não deve ter sido completado ainda, uma vez que esse protocolo necessita do
número randômico gerado pelo presente serviço.
Fluxo principal:
Descrição: A autenticação mútua é parte do protocolo BAC, sendo utilizada para o estabele-
cimento de chaves de encriptação (SKENC ) e de resumo (SKMAC ). Através do uso dessas chaves
é possível, após o BAC, utilizar o mecanismo de secure messaging, que consiste em realizar a
encriptação do canal de comunicação entre as aplicações host e cartão (SKENC ) e assegurar a
integridade das mensagens trocadas entre elas (SKMAC ).
Pré-requisitos:
1. Devem ter sido geradas previamente as chaves KENC e KMAC , derivadas a partir das infor-
mações da Machine Readable Zone (MRZ).
Fluxo principal:
1. Terminal (IFD)
(b) Uma chave KIFD (16 bytes) deve ser gerada a partir de RNDIFD . As chave KIFD e
KICC (gerada pelo cliente) serão utilizadas para derivar as chaves de seção KSENC e
KSMAC ;
(c) Deve ser feita a concatenação (símbolo “||”) dos números randômicos e a chave
(S = RNDIFD || RNDICC || KIFD );
(d) S deve ser encriptado utilizando a chave KENC (EIFD = enc[KENC ](S));
(e) Deve ser gerado o resumo do criptograma EIFD (MIFD = mac[KMAC ] (EIFD ));
(c) Deve-se extrair RNDICC de S e verificar se o terminal retornou o valor correto, com-
parando com o valor gerado e que foi enviado ao terminal anteriormente;
(d) A chave KICC (16 bytes) deve ser gerada a partir de RNDICC ;
(f) R deve ser encriptado utilizando a chave KENC (EICC = enc[KENC ](R));
(g) Deve-se computar o resumo do criptograma EICC (MICC = mac[KMAC ] (EICC ));
3. Terminal
(c) O terminal extrai RNDIFD de R e verifica se foi retornado o valor correto (o mesmo
valor que foi enviado ao cartão).
140
Fluxo alternativo:
1. fluxo principal, item 2. Em caso de falha em qualquer etapa, deve-se retornar um código
de erro para o terminal.
Pré-requisitos:
1. O cliente deve estar autenticado para que possa obter acesso aos arquivos. Neste caso, a
BAC deve ter sido feita previamente.
Fluxo principal:
Fluxo alternativo:
1. fluxo principal, item 2. No caso do identificador do arquivo não ser válido, nenhum
arquivo deve ser retornado. Ao invés disso, um código de erro deve ser enviado para o
cliente.
Ressalta-se que no código Java Card da aplicação de passaporte eletrônico, o estado per-
sistente é inicializado simplesmente com o valor 0 (zero). Na especificação B, criou-se o es-
tado PER_STATE_INIT para representar essa situação inicial. Apenas para deixá-la em um
estado consistente, a variável selectedFile recebeu o valor de um dos arquivos do passaporte
(EF_DG1_INDEX). A efetiva indicação de que um arquivo está autorizado para ser requi-
sitado depende do estado da variável volState. Na situação inicial, ela é inicializada com
NO_FILE_SELECTED, indicando que nenhum arquivo foi requisitado ainda para seleção. Por
fim, as sequências de byte rnd e ssc tem cada byte inicializado com o valor zero (0), uma vez
que elas recebem valores significativos apenas através da chamada às operações getChallenge
e processMutualAuthenticate, respectivamente.
ANY number
WHERE
number = seq1(JBYTE)
THEN
rnd :∈ number || rnd_val :∈ number
END
END;
As demais pré-condições que devem ser obedecidas para a correta aplicação da operação
processSelectFile dizem respeito aos estados volátil e persistente. A primeira delas (volState(1)
= MUTUAL_AUTHENTICATED) indica que é preciso que a autenticação entre o terminal e o
cartão tenha sido estabelecida, o que é feito através da chamada às operações getChallenge e
processMutualAuthenticate. Em relação ao estado persistente, o cartão não deve estar no estado
bloqueado (perState = LOCKED). No corpo da operação, em uma aplicação bem sucedida, o
144
Observa-se que os dados inseridos no campo data do buffer são recebidos no parâmetro
data_in e que os dados enviados na resposta ao cliente devem ser inseridos no array data_out.
Acrescentou-se à interface de todas as operações concretas o parâmetro apdu_p, que modela
145
Em relação ao invariante, a especificação dos componentes de estado não foi alterada, tendo
em vista que os tipos de dados utilizados na especificação inicial são compatíveis com a espe-
cificação cartão (byte, short, boolean e array de byte).
Observa-se pela figura 7.8 que o refinamento referencia, na cláusula SEES, a máquina de
contexto Passport_JC_FF_Context (figura 7.9), na qual estão definidas as constantes para re-
presentar os códigos de exceção identificados nas operações, bem como constantes que definem
o código de instrução (INS) de cada serviço do cartão. Também destaca-se a inclusão (cláu-
sula INCLUDES) da máquina ISOException, que modela a chamada à operação throwIt para o
lançamento de exceções em Java Card.
Conforme explanado na seção 4.3.1, o modelo full function das operações consiste em es-
pecificar as restrições da pré-condição abstrata na forma de substituições condicionais, dessa
146
MACHINE Passport_JC_FF_Context
SEES JByte, JShort
CONSTANTS
ex_processGetChallenge0, ex_processGetChallenge1, (. . . ), processMutualAuthenticate_INS
PROPERTIES
ex_processGetChallenge0 ∈ JSHORT ∧
ex_processGetChallenge1 ∈ JSHORT ∧
ex_processSelectFile0 ∈ JSHORT ∧ (. . . )
processReadBinary_INS ∈ JSHORT ∧
processMutualAuthenticate_INS ∈ JSHORT
END
forma permitindo que elas se tornem explícitas no código Java Card a ser gerado. Desse modo,
a funcionalidade da operação só será efetivamente aplicada se todas as restrições forem obede-
cidas, caso contrário um código de erro é retornado ao cliente, seguindo o modelo de exceção
em Java Card.
Observa-se que o corpo da operação é aplicado (após o else do primeiro condicional) caso
as restrições sejam obedecidas. Nesse caso, inicialmente especifica-se o recebimento do iden-
tificador do arquivo através do primeiro byte da sequência data_in (data_in(1)). O restante da
operação é semelhante ao modelo abstrato, tendo dois comportamentos possíveis, a saber, atri-
buir o identificador do arquivo a selectedfile e modificar o estado volátil para indicar a seleção
do arquivo, ou não selecionar nenhum arquivo, caso o identificador seja inválido.
147
A figura 7.11 apresenta uma visão geral das máquinas que compõem a implementação e as
suas principais dependências.
FileIndex e FileSystem FileIndex contém uma operação getFileIndex que, dado um identifica-
dor de arquivo, retorna o seu índice correspondente. O módulo FileSystem, por sua vez,
possui uma operação que modela o retorno de um arquivo, dado o seu identificador.
KeyStore Possui operações para armazenar e retornar as chaves KENC e KMAC necessárias ao
BAC.
148
PassportUtil implementa serviços diversos, que possibilitam, por exemplo, a troca dos valores
armazenados em duas sequências de bytes e o retorno do menor entre dois valores. É
utilizado pelo serviço processMutualAuthenticate.
da aplicação prévia de outras operações, como no caso das operações de recepção e envio de
dados da máquina Apdu. Dessa forma, ao ser gerado o código Java Card, os métodos serão
chamados com o tipos corretos e na ordem adequada.
bytes é gerada e armazenada na variável local jc_rnd, com o auxílio da operação generateData
da máquina RandomData (randomData.generateData (jc_rnd, 0, le_val)). O valor local é então
utilizado na atualização do estado global (jc_rnd_var.setSeq (jc_rnd)).
Observa-se que a cópia da variável jc_rnd no buffer apdu é o primeiro passo para retorná-la
ao cliente. Para tanto, utiliza-se a operação arrayCopyNonAtomic da máquina Util. Ela recebe o
valor de jc_rnd, o buffer apdu (bf ), os índices a partir dos quais a cópia dos valores é efetivada
(cast_short (0) e bf_offset) e quantos bytes serão copiados (le_val). Observe que o arquivo
só será copiado no buffer caso diversas restrições sejam atendidas, tais como o fato do buffer
não ser vazio (bf 6= []) e a quantidade de bytes inseridos a partir de bf_offset não ultrapassar
o tamanho do buffer (sum_short(bf _offset, le_val) ≤ size(bf )). A abordagem de antecipar os
erros que possam surgir pela aplicação de operações com valores incorretos é utilizada durante
toda implementação para assegurar a robustez do desenvolvimento.
Caso a geração tenha sido bem-sucedida, o estado global do passaporte é atualizado para
CHALLENGED (vol_state.set(CHALLENGED)) e o valor do número randômico é retornado
em data_out (data_out := jc_rnd). Destaca-se que o código de envio de data_out ao cliente,
comum a todas as operações que retornam informações, encontra-se inserido no método process
da implementação Applet.
processSelectFile (apdu_p, data_in) =
VAR v_st, per_st,bf, lc_data, fid, file
IN
v_st ← vol_state.getFirst; per_st ← per_state.get_num;
bf ← apdu.getBuffer;
vol_state.set(NO_FILE_SELECTED);
IF per_st = LOCKED
THEN ISOException.throwIt(ex_processSelectFile0)
ELSIF ¬ (v_st = MUTUAL_AUTHENTICATED)
THEN ISOException.throwIt(ex_processSelectFile1)
ELSE
fid := data_in(1);
lc_data := cast_byte(8);
IF (fid ≥ EF_DG1_INDEX ∧ fid ≤ SOS_LOG_INDEX)
THEN
file ← fileSystem.getFile(fid);
IF (file 6= [])
THEN
sel_file.set_num(fid);
vol_state.set(FILE_SELECTED)
ELSE ISOException.throwIt(SW_FILE_NOT_FOUND)
END
ELSE
ISOException.throwIt(SW_INTERNAL_ERROR)
END
END
END;
Ressalta-se que a operação processSelectFile (figura 7.14) não retorna nenhuma informação
por meio do buffer. Sua funcionalidade principal é atualizar o arquivo selecionado (a variável
151
de estado selectedFile) com o valor fornecido pela aplicação host. Em seu modelo concreto,
após as verificações de estado, o identificador do arquivo é obtido do primeiro byte do pa-
râmetro data_in (fid := data_in(1)). Na sequência do código de processSelectFile é feita a
leitura do arquivo, caso o identificador esteja na faixa correta (file ← fileSystem.getFile(fid), e
a atualização das informações do estado relativa à seleção do arquivo (sel_ f ile.set_num(fid) e
vol_state.set(FILE_SELECTED)).
Outro ponto a ser enfatizado na máquina Applet diz respeito à divisão de responsabilidades
entre os métodos process e processAPDU (fig. 7.16). O primeiro é um método abstrato da
classe Applet, devendo portanto manter a sua interface inalterada e, em Java, ser implementado
na subclasse. O método process é a porta de entrada para o applet, sendo essa característica
explorada no tratamento da recepção do buffer apdu e no retorno de dados ao cliente, conforme
detalhado posteriormente ao analisarmos a sua implementação B. Por outro lado, a operação
processAPDU foi acrescentada para realizar a interface entre o modelo abstrato dos serviços e
o seu correspondente concreto. Ela recebe em seus parâmetros os diversos campos do buffer
apdu, fornecidos pelo cliente, e retorna a sequência de bytes data_out com os dados retornados
pelas operações.
process(apdu) = PRE apdu ∈ APDU THEN skip END;
data_out ← processAPDU (apdu_p, cla, ins, p1, p2, lc, data_in, le) =
PRE apdu_p ∈ APDU ∧ cla ∈ JBYTE ∧ ins ∈ JBYTE ∧
p1 ∈ JBYTE ∧ p2 ∈ JBYTE ∧ lc ∈ JBYTE ∧ le ∈ JBYTE ∧
data_in ∈ seq(JBYTE) ∧ data_in 6= [] ∧ size (data_in) ≥ 1 ∧ size (data_in) ≤ 127
THEN
SELECT ins = processGetChallenge_INS ∧
app.jc_perState = HAS_MUTUAL_AUTHENTICATION_KEYS ∧
¬ (app.jc_volState(1) = MUTUAL_AUTHENTICATED)
THEN
data_out ← app.processGetChallenge(apdu_p, boolean_of_byte(p1), data_in ) (. . . )
ELSE
data_out :∈ seq(JBYTE)
END ||
perState := app.jc_perState ||
volState := app.jc_volState ||
selectedFile := app.jc_selectedFile ||
rnd := app.jc_rnd ||
ssc := app.jc_ssc
END;
Com o propósito de estabelecer que o applet a ser gerado advém de fato do modelo Applet,
deve-se proceder com o seu refinamento e, em última etapa, a sua implementação B. Devido a
semelhança do componente abstrato, omitiu-se desta seção o primeiro refinamento, que pode
ser consultado em apêndice. No modelo concreto JC_Applet_imp (implementação completa
no Apêndice C.7), deve-se fornecer a implementação definitiva das operações do applet. No
presente estudo de caso, implementou-se em maior detalhe os métodos process e processAPDU.
Observa-se que a implementação fornecida à operação process terá maior relevância apenas
durante a execução da aplicação Java Card. Dividiu-se a apresentação de process em três
partes, compreendendo as figuras 7.17 a 7.19. Inicialmente (fig. 7.17), foi inserido código para
recuperar o buffer apdu (bf ← apdu.getBuffer) e obter cada componente do buffer, tais como
o identificador de instrução (ins), os parâmetros (p1 e p2) e os dados do campo data, que são
copiados no array de dados data_in (Util.arrayCopyNonAtomic (bf, OFFSET_CDATA, data_in,
0, lc)).
process(apdu) =
VAR
bf, it cla, ins, p1, p2, lc, data_in, lr, data_out, apdu_state, res res2
IN
bf ← apdu.getBuffer; (...)
IF (size (bf) ≥ 6 ∧ (...)
bf(OFFSET_LC) ≤ MINBYTE ∧ bf(OFFSET_LC) ≥ MAXBYTE )
THEN
cla := bf(OFFSET_CLA);
ins := bf(OFFSET_INS);
p1 := bf(OFFSET_P1);
p2 := bf(OFFSET_P2);
lc := bf(OFFSET_LC)
ELSE
data_in := [0];
data_out := [0];
apdu_state ← apdu.getCurrentState;
IF (lc > 0)
THEN
IF (apdu_state = STATE_INITIAL)
THEN
res ← apdu.setIncomingAndReceive;
res2 ← Util.arrayCopyNonAtomic (bf, OFFSET_CDATA, data_in, 0, lc)
END
END; (...)
Destaca-se que a segunda tarefa a ser executada no método process consiste na chamada
ao método processAPDU (fig. 7.18). Para tanto, as informações obtidas do buffer devem ser
copiadas na interface de processAPDU, que então as repassa ao serviço requisitado na aplicação
(de acordo com o campo ins). No código de process, o acesso aprocessAPDU encontra-se
154
comentado devido ao método B não permitir que uma operação invoque outra operação da
mesma máquina (no caso JC_Applet_imp). Assim, após a geração de código, o usuário deve
retirar o comentário desse trecho de código, que já encontra-se na notação Java.
process(apdu) = (...)
lr := cast_byte(0);
/∗ ===> Uncomment here to call service operations <===
data_out = processAPDU ( apdu, cla, ins, p1, p2, lc, data_in, le );
lr = data_out.length ;
*/ (...)
A última etapa no código de process se refere ao envio de dados no buffer apdu (fig. 7.19), o
que irá ocorrer caso o número de bytes retornados em data_out seja maior que zero. Ressalta-se
que esse trecho de código é semelhante para qualquer operação que deseje realizar o retorno de
uma informação no buffer APDU. No caso, deve-se invocar, nessa ordem, as operações, setOut-
going, setOutgoingLength e sendBytes, da mesma forma como foi demonstrado no capítulo 2.
No código da implementação em B, assegura-se a correção na ordem em que as operações
devem ser chamadas através da verificação, na pré-condição de cada operação, do estado da
máquina APDU.
process(apdu) = (...)
IF lr > 0
THEN
apdu_state ← apdu.getCurrentState;
IF (lr ≥ 0 ∧ lr ≤ 256 ∧ sum_short(0, lr) ≤ BUFFER_LENGTH)
THEN
IF (apdu_state = STATE_INITIAL ∧ apdu_state 6= STATE_OUTGOING)
THEN res ← apdu.setOutgoing
ELSIF (apdu_state = STATE_OUTGOING ∧ apdu_state 6= STATE_OUTGOING_LENGTH_KNOWN)
THEN
apdu.setOutgoingLength(lr);
apdu.sendBytes (0, lr)
ELSE
ISOException.throwIt (SW_SECURITY_STATUS_NOT_SATISFIED)
END
ELSE
ISOException.throwIt (SW_SECURITY_STATUS_NOT_SATISFIED)
END
END
END
END;
Demais dados de entrada são obtidos de data_in e repassados ao parâmetro data_in do serviço.
Nos casos em que há saída de dados, essa é direciona à sequência de bytes de retorno data_out.
data_out ← processAPDU ( apdu_p, cla, ins, p1, p2, lc, data_in, le ) =
VAR
per_st, vol_st, protectedAPDU
IN
per_st ← app.getPersistentState;
vol_st ← app.getVolatileState;
protectedAPDU := FALSE;
IF ins = processGetChallenge_INS
THEN
IF per_st = HAS_MUTUAL_AUTHENTICATION_KEYS ∧ ¬ (vol_st = MUTUAL_AUTHENTICATED)
THEN
IF p1 = cast_byte (1) THEN protectedAPDU := TRUE END;
REFINEMENT Passport_ref
REFINES Passport
SEES JByte, JShort, JBoolean, ISO7816,Apdu_Properties,
Passport_Context, Passport_JC_FF_Context, FileSystem_Context, InterfaceContext
INCLUDES fileSystem.FileSystem, applet.Applet
INVARIANT
perState = applet.perState ∧
volState = applet.volState ∧
selectedFile = applet.selectedFile ∧
rnd = applet.rnd ∧
ssc = applet.ssc
INITIALISATION skip
tais como os campos p1, p2 e o array data_in, fornecidos à operação processAPDU. A partir
do código de instrução (campo ins), a operação processAPDU irá requisitar o serviço concreto
correspondente. O serviço é então realizado sob os dados fornecidos, alterando as variáveis de
estado e o estado global da aplicação, de modo equivalente ao realizado na operação abstrata.
Após a execução do serviço, os dados recebidos em data_out são retornados e convertidos para
o tipo correspondente na saída abstrata.
SELECT
size (data) ≥ 1 ∧
size (data) ≤ 127
THEN
data_out ← applet.processAPDU(apdu, cla, ins, p1, p2, lc, data, cast_byte(8));
rnd_val := data_out
END
END;
8 Trabalhos Relacionados
O presente trabalho teve início como parte do projeto Engineering of Smart Card Applica-
tions (SMART), que tem por objetivo o estudo e o desenvolvimento de técnicas e ferramentas
para a aplicação de engenharia de software rigorosa, baseada em métodos formais, ao desenvol-
vimento de aplicações para cartões inteligentes. Outros frutos desse projeto são apresentados
na dissertação de mestrado de Plácido Neto [Net07], bem como nas monografias de graduação
de Kátia Moraes [Mor07] e Thiago Dutra [Dut06].
Plácido Neto [Net07] realizou um estudo quanto à aplicabilidade de JML para a verificação
em tempo de execução de aplicações Java Card. O esforço inicial deste estudo consistiu na de-
finição de um subconjunto da notação JML contendo apenas construções compatíveis com Java
Card. Posteriormente, foi construída uma primeira versão de um compilador para esta nova
linguagem, denominada de Java Card Modelling Language (JCML). Utilizando-se o compila-
dor, é possível a geração de anotações em JCML no código de uma aplicação Java Card para a
verificação de pré-condição e de invariante.
O trabalho de Kátia Moraes [Mor07] desenvolveu o protótipo inicial para a geração da API
para a aplicação host. Nele definiu-se um conjunto de classes que efetuam de forma transpa-
rente para o usuário a comunicação com alguma API (Smart Card I/O, p. ex.) e que fazem a
conversão de tipos e montagem de comandos APDU. Na tese, essas classes foram remodeladas,
tendo em vista uma melhor distribuição de responsabilidades e promover o reuso de parte dos
componentes. Além disso, toda a implementação, antes desenvolvida em Java, foi refeita em
C++ utilizando a API B-Compiler [Cle12b].
em sua totalidade no trabalho de Simone Santos [San12], que também contribuiu com um guia
para uso e criação de novos componentes no Kit. O trabalho de Santos é descrito em maiores
detalhes no capítulo 6.
A ferramenta JBtools [Voi02] foi uma das primeiras abordagens acadêmicas a prover um
gerador de código da linguagem B para linguagens orientadas a objetos. No caso, as linguagens-
alvo escolhidas para a tradução foram Java e C# e, até certo ponto, conforme discutir-se-á
posteriormente, Java Card. Além de geração de código, o ambiente de desenvolvimento JBtools
fornece verificação de tipos em uma especificação B, geração de documentação em HTML e
uma biblioteca para a manipulação de um módulo B, denominada de B Object Library BOL.
definido pelo Brillant inclui parser, verificador de tipos, tradutor de código e um gerador de
obrigações de prova. O gerador ainda não está completo, mas implementa a maior parte das
construções e propriedades de prova descritas no B-Book [Abr96]. As obrigações de prova vêm
sendo geradas em um formato compatível com o provador de teoremas Coq [INR10]. De forma
similar ao que é feito para o JBtools, para permitir a integração das diversas ferramentas, um
formato intermediário em XML do desenvolvimento é gerado.
Cumpre observar que além das ferramentas mencionadas, o Atelier B, na sua versão mais
recente (4.1), inclui a ferramenta Bart e um gerador de código de B para C, denominado de
ComenC [Cle12c]. O software Bart possibilita a geração automatizada de refinamentos em
uma especificação ou refinamento B até a sua implementação. Inicialmente, deve-se especifi-
car o padrão de refinamento desejado para as variáveis, a inicialização e as substituições das
operações do módulo alvo do refinamento. Essa especificação é feita por meio de regras de
refinamento e submetida ao Bart, que tenta casar o padrão estabelecido nas regras com as cons-
truções do módulo a ser refinado. Sempre que um padrão é estabelecido, a regra de refinamento
associada é aplicada, resultando, ao final do processo, na implementação concreta do módulo
refinado. Observa-se que os refinamentos obtidos devem ser verificados, assim como qualquer
outro refinamento, usando as obrigações de prova padrão de B.
No que concerne a animação de uma especificação B, que pode ser entendido como o
processo de simulação da “execução” da especificação para fins de teste, destacam-se as fer-
ramentas ProB [LBBP10] e Brama [Ser07]. A ferramenta ProB permite, além da animação, a
verificação de modelos em uma especificação B ou Z. Em suas primeiras versões, ela utilizava
a biblioteca BOL provida pelo JBtools. Nas versões mais recentes do ProB, essa biblioteca foi
substituída por um parser e verificador de tipos B desenvolvidos pelos seus próprios autores.
Por sua vez, o software Brama é desenvolvido pela Clearsy, a empresa que fornece a ferramenta
Atelier B. Brama permite a construção de um modelo visual em Flash que conecta-se ao módulo
de animação da especificação, permitindo assim a execução de uma especificação de maneira
visualmente mais atrativa.
162
O projeto Deploy (anteriormente Rodin) 1 tem por objetivo a criação de técnicas e ferramen-
tas para o desenvolvimento de sistemas complexos de software, integrando métodos formais a
técnicas de desenvolvimento de sistemas tolerantes a falhas. O projeto vem sendo desenvol-
vido por grandes centros de ensino e pesquisa europeus, como Instituto Federal de Tecnologia
(ETH) de Zurique e a Universidade de Southampton, em parceria com empresas privadas, como
a Bosch, Siemens e a Space Systems Finland, que fornecem estudos de caso de sistemas de
grande porte e testam as técnicas e ferramentas propostas no projeto. Atualmente, a ferramenta
Rodin, que vem sendo desenvolvida no âmbito deste projeto, é a implementação de referência
para o formalismo Event-B [Abr10].
A ferramenta Rodin é composta por um kernel básico, distribuído como um plugin para a
plataforma Eclipse, e que serve de base para a integração de diversos plugins com ferramentas
específicas para suporte à metodologia, dentre os quais, destacam-se o plugin para o desenvol-
vimento básico com Event-B e outro que inclui o gerador de obrigações de prova e o provador
da ferramenta Atelier B. Ferramentas externas também podem ser integradas ao ambiente, tais
quais o ProB, Brama e o software UML-B, que permite a tradução de diagramas em uma nota-
ção similar à UML para especificações na linguagem B e Event-B. O Rodin é uma plataforma
aberta e extensível que vem sendo continuamente aprimorada e atualizada com novos plugins.
A versão estável atual do Rodin pode ser obtida no sítio http://www.event-b.org/install.html.
Observa-se que, com o uso do BCompiler, conseguiu-se uma solução estável para a verifi-
cação de tipos e a manipulação da especificação, com a vantagem de alinhar o desenvolvimento
com a linguagem B do Atelier B. Conforme delineado na seção 4.6, as ferramentas fornecidas
1 site do projeto Deploy: http://www.deploy-project.eu/
163
pelo BSmart compreendem um gerador de refinamento full function, um gerador para a apli-
cação host a partir da especificação inicial e o tradutor da implementação B para Java e Java
Card. Essa última também verifica se a implementação satisfaz as restrições observadas para
uma classe Java Card.
A Common Criteria é uma organização que tem por objetivo avaliar a segurança de produtos
de tecnologia, de acordo com diversos níveis de segurança (EALs). Um produto é classificado
em um certo nível (de 1 a 7) a partir da análise das técnicas de especificação e desenvolvimento
que foram empregadas na sua construção e da avaliação de que o produto cumpre com os re-
quisitos de segurança especificados. No nível mais alto de certificação, exigem-se a utilização
de métodos formais e o seu relacionamento com a especificação de políticas de segurança.
Nesse sentido, o trabalho de Motré e Terí [MT00] estabelece modelos de políticas de se-
gurança para o componente Java Card Runtime Environment (JCRE) da máquina virtual Java
Card visando atingir os níveis 4, 5 e 7 de certificação no Common Criteria. O nível 6 não foi
incluso por ser totalmente coberto pelo nível 7, o primeiro no qual se exige a aplicação de téc-
nicas de verificação formal. Como estudo de caso, especificou-se a execução de instruções de
bytecode geradas para um applet. O acesso a uma instrução de bytecode pelo interpretador Java
pode requerer a autorização do mecanismo de firewall para verificar, por exemplo, se o applet
possui as permissões necessárias para executá-la. Para o nível 4, o modelo de segurança foi
implementado utilizando-se um diagrama de estados UML. Visando atingir o nível 5, a política
de segurança anteriormente especificada foi formalizada como uma máquina B. Nesse caso, os
estados do diagrama UML foram associados às variáveis do modelo em B. Através do invariante
da máquina, foram descritas as possíveis transições entre os estados do modelo. Por fim, para
atingir o nível 7, é necessário atestar que os componentes funcionais do sistema relacionados
à política de segurança realmente a implementam. Dessa forma, as variáveis das funcionalida-
164
Na mesma linha do trabalho anterior, Dadeau et. al. [DLMP08, DPT08] definem polí-
ticas de segurança para controle de acesso em aplicações para smart cards. Inicialmente,
implementou-se, na linguagem B, o modelo da política de acesso a um objeto da aplicação
Java Card por um agente externo utilizando uma operação do modelo. A política de acesso foi
então mapeada para a implementação da operação em Java Card. A conformidade da operação
implementada com o modelo de segurança é verificada com referência a todo trace de execução
da implementação poder também ser executado pelo modelo de segurança. A base teórica da
abordagem é feita utilizando o método B, dessa forma, foi possível também verificar a correção
dos mapeamentos entre o modelo de segurança e a sua implementação através de obrigações de
prova.
Salienta-se que a especificação da API Java Card é uma área de aplicação de métodos
formais a Java Card que vem recebendo bastante destaque. Uma vez que o código fonte da
API normalmente não é fornecido, de uma forma geral, o objetivo desses trabalhos é permitir
que verificações sejam feitas nas classes Java Card que a utilizam, por meio da especificação
formal da API. Em Meijer [MP01] e Poll [PvdBJ01] pode-se vislumbrar a especificação, por
meio de anotações em Java Modelling Language (JML) [Gar06], das classes JCSystem e APDU,
respectivamente. O trabalho de Larsson [LM04] fornece como estudo de caso a especificação da
classe para autenticação OwnerPin em JML e Object Constraint Language (OCL), fazendo uma
comparação entre esses dois formalismos. Em sua dissertação de mestrado, Larsson [Lar03]
especifica quase a totalidade da API Java Card 2.2.1 utilizando o formalismo OCL. Os trabalhos
citados, bem como a especificação da API Java Card, foram utilizados como referência para a
criação dos modelos da API Java Card da biblioteca KitSmart.
A verificação do bytecode Java Card geralmente é efetuada fora do cartão para assegurar
que a aplicação a ser instalada segue a especificação Java Card e não compromete a segurança
da máquina virtual ou de outros applets instalados no cartão [Ort01]. Em [CBR02] foi desen-
volvido um verificador de bytecode gerado em linguagem C a partir da sua especificação em
165
A geração automática de testes baseada em métodos formais para aplicações Java Card é
também uma linha de pesquisa que vem recebendo certa atenção, como pode ser visto por meio
dos trabalhos de Martin e Bousquet [MdB01] e de Weelden [vWOF+ 05].
Em Weelden [vWOF+ 05] foi feito um estudo sobre a aplicabilidade de testes caixa preta
baseado em especificações formais em aplicações Java Card e foram feitas comparações com
outras abordagens de teste para Java Card. Para a geração dos dados, execução e análise dos
testes foi utilizada a ferramenta GAST [KATP02], que recebeu como entrada uma especificação
com as propriedades do sistema como funções na linguagem CLEAN 2 . Um estudo de caso de
carteira eletrônica foi utilizado na aplicação de testes de forma incremental. Uma membro
da equipe do projeto ficou responsável por desenvolver a especificação da aplicação e, uma
2 site da linguagem Clean: http://clean.cs.ru.nl/
166
Alguns trabalhos que são parte do grupo de pesquisa do autor desta tese enveredam por esta
área, tais quais os trabalhos de Fernanda Souza [Sou09] e de Ernesto Matos [dM12]. Até o
presente momento, ainda não incorporou-se testes ao BSmart. No entanto, é interessante avaliar
quais resultados desses trabalhos podem ser introduzidos no método.
É interessante ressaltar algumas otimizações propostas por Requet [RB00] com relação aos
elementos da notação B que são gerados. No caso das constantes, a tradução é feita para dire-
tivas de pré-processamento em C, de modo a evitar o consumo de memória por uma variável.
Operações que são chamadas apenas uma vez tem a chamada substituída pelo seu código (pro-
cesso de inlining), reduzindo assim o overhead na chamada de métodos. Máquinas que definem
apenas constantes e conjuntos enumerados são traduzidas em arquivos de cabeçalho. Ainda no
caso da tradução de máquinas, quando não há declaração de estado na implementação, não há
necessidade de criação de ponteiros para uma instância específica da máquina. No caso das
3 site do projeto BOM: http://lifc.univ-fcomte.fr/˜tatibouet/WEBBOM
168
variáveis, o tradutor procede com a tradução para um tipo inteiro menor, como byte ou short,
no momento em que elas são restritas para intervalos inteiros compatíveis com esses tipos.
Com relação à geração de código para Java Card no presente trabalho, é possível proceder
com otimizações semelhantes às do trabalho de Requet no código a ser gerado. Por exemplo,
pode-se substituir a referência a um atributo constante (static final) por seu valor declarado na
inicialização, ou substituir a chamada a um método final pelo seu código. No método BSmart,
os tipos de dados de variáveis e expressões são fornecidos através da utilização das máquinas
de biblioteca para os tipos primitivos de Java. Em cada biblioteca, tem-se a implementação de
conjuntos que definem cada tipo e de operações que atuam sob o intervalo de valores permitidos
para esse tipo. Dessa forma, o trabalho do tradutor consistirá apenas em gerar a implementação
Java/Java Card correspondente ao tipo da variável, constante ou expressão em B.
Bert et. al. [B+ 03] apresenta os resultados completos do trabalho anterior, já com uma
versão do tradutor de B para C desenvolvida. Um estudo de caso de especificação e geração
de código dos componentes Java Card Runtime Environment (JCRE) e intepretador de byte-
code da máquina virtual Java Card foi desenvolvido para validar a ferramenta e o impacto das
otimizações propostas. A especificação B foi composta de cerca de 10.000 linhas de código,
complementada por 5.000 linhas de código em C para interface com dispositivos de baixo ní-
vel, gerenciamento de memória, etc. A geração foi feita para as plataformas de hardware smart
cards Artmel AVR 8-bits e Smart MIPS 32-bits. Comparações com o tradutor da ferramenta Ate-
lier B [Cle12a] atestaram que o tradutor otimizado de Bert permite redução de 78% no tamanho
do código gerado para a plataforma AVR e de 58% no caso do código gerado para Smart MIPS.
O tradutor original da ferramenta BSmart foi implementado como uma extensão do trabalho
de Tatibouet [TRVH03, Voi02], que inclui as otimizações propostas no projeto BOM visando a
inclusão de código Java em smart cards. Na proposta de Tatibouet, uma classe compatível com
Java Card é gerada, mas a introdução dos aspectos específicos do applet deve ser feita de forma
manual.
Com relação à tradução na ferramenta Atelier B, a sua versão atual inclui um tradutor de
B para C. Ele recebe como entrada uma implementação B0 e os módulos abstratos dos quais a
implementação depende. O tradutor produz como saída, para cada implementação, um arquivo
de cabeçalho (.h) e um arquivo de código-fonte (.c). O cabeçalho contém as constantes e variá-
veis traduzidas, bem como a assinatura de cada função gerada a partir das operações do módulo
B0. A implementação dessas funções é fornecida no arquivo de código-fonte, assim como uma
operação contendo a inicialização das variáveis de estado da máquina. O processo de tradução
renomeia cada elemento declarado (constantes, variáveis e métodos) prefixando-os com o nome
do módulo B0. Esse processo é necessário para evitar conflito com elementos declarados em
outros módulos incluídos na implementação (cláusula IMPORTS) e com palavras reservadas da
linguagem C.
É interessante ressaltar que o tradutor do Atelier B possui uma linguagem B0 bastante res-
tritiva. Em virtude disso, não é possível a utilização do Atelier B para gerar código a partir das
implementações desenvolvidas para o BSmart (ainda que para a linguagem C). Dessa forma,
o tradutor do BSmart estabelece o seu próprio B0, permitindo a geração de código a partir de
elementos da notação que não são considerados no Atelier B.
A notação da linguagem B para geração de código não foi projetada tendo em vista a imple-
mentação dos conceitos de orientação a objetos, como herança, encapsulamento, classes, etc.
No entanto, diversos estudos vêm sendo desenvolvidos no que concerne a técnicas e ferramentas
para traduzir código B nessas linguagens e para a notação de diagramas em UML.
Com relação à tradução para linguagens orientadas a objetos, além da proposta da ferra-
menta JBtools, uma iniciativa recente foi o desenvolvimento de um método para permitir a
geração de código, inicialmente para Java, a partir de refinamentos em Event-B, descrita em
170
Edmunds e Butler [EB10]. Embora Event-B não seja a plataforma ideal para prover geração de
código, e esse não seja de fato o seu propósito inicial, os autores desenvolveram uma linguagem
intermediária, denominada de Object-Oriented Concurrent B (OCB), para a qual uma máquina
Event-B é traduzida antes da geração de código. A OCB define uma linguagem concreta, mais
próxima de Java, composta por processos (em uma sintaxe semelhante a uma classe Java) e da-
dos que podem ser compartilhados entre processos. Os eventos são traduzidos para operações
atômicas em cada processo, e ações nessas operações podem utilizar atribuição a dados locais
e chamadas de procedimentos.
É interessante observar que diversos estudos relacionam a tradução para diagramas em Uni-
fied Modeling Language (UML) a partir de B, como pode ser verificado por meio dos trabalhos
de Idani [IL04], Fekih [FJM04] e Tatibouet [THV02]. Esses trabalhos fornecem idéias interes-
santes quanto à tradução de elementos da notação B para linguagens orientadas a objetos que
podem ser diretamente aplicadas ao tradutor da ferramenta BSmart.
O trabalho de [IL04] propõe um método composto por duas etapas. Na etapa preliminar,
classes e associações são obtidas a partir dos conjuntos definidos no módulo B, sendo cada con-
junto do módulo B um candidato potencial a uma classe, e uma associação definida pela análise
do relacionamento entre dois conjuntos. A etapa seguinte determina se os conjuntos devem ser
traduzidos para atributos ou para classes e o mapeamento de cada operação do módulo para as
classes obtidas. Em [FJM04], a abordagem básica para a geração de classes determina que o
domínio de uma relação torna-se uma classe se ele for um conjunto. Esta solução também é
bastante simples, mas pode levar à geração de diagramas de classes incompletos. Na mesma li-
nha dos trabalhos anteriormente citados, no trabalho de [THV02] cada conjunto e cada módulo
B originam uma classe Java, em uma abordagem que também foi utilizada no trabalho deste
mesmo autor para a tradução de B para Java [TRVH03]. Com relação à UML, essa solução não
parece ser muito adequada, pois tende a gerar diagramas com muitas classes e associações.
Ainda nesta linha de trabalhos, foi desenvolvida a ferramenta UML-B [SB06], que provê
um ambiente para a criação de diagramas de modelagem, tendo por base parte da notação e da
semântica da UML e os conceitos dos formalismos B e Event-B [SB08]. Inicialmente, os auto-
res tentaram estender a UML utilizando perfis e estereótipos, no entanto, devido a uma maior
personalização requerida pelo UML-B, criou-se uma semântica nova para diagramas específi-
cos, visando a tradução do modelo para as linguagens B e Event-B. Em relação à tradução para
Event-B, que é o foco atual do projeto, foram projetados quatro diagramas, a saber, pacote (pac-
kage), contexto (context), classe (class) e máquina de estados (state machine). O diagrama de
pacotes pode ser utilizado para se visualizar a relação entre máquinas e contextos. O diagrama
171
9 Considerações Finais
As aplicações smart cards possuem certas características que as tornam candidatas ideais
à adoção de algum formalismo em seu desenvolvimento. Elas armazenam e fornecem infor-
mações que não podem ser violadas e devem permanecer em estado consistente entre as várias
ativações da aplicação, como valores monetários e dados pessoais. Além disso, o fato delas se-
rem aplicações de pequeno porte, que especificam uma pequena API com os serviços oferecidos
à aplicação cliente, facilita a sua especificação e verificação formal.
Salienta-se que o desenvolvimento deste trabalho teve início com a pesquisa de apli-
cações Java Card na literatura e da identificação da estrutura geral que elas apresentavam.
Desenvolveu-se então, como estudos de caso, uma aplicação de bilhetagem em transporte pú-
blico e outra de carteira eletrônica. O resultado desses desenvolvimentos iniciais originou a pri-
meira versão do método BSmart [GMD05, DGM06] e das suas ferramentas de apoio [DGM08],
a saber o tradutor de código de B para Java Card e o gerador de refinamentos, conforme apre-
173
O objetivo maior da tese é permitir, através do método BSmart, a geração da aplicação Java
Card completa, composta pelo applet que fornece os serviços no lado cartão e por uma API
para o acesso transparente aos serviços no cartão, possibilitando a correção de todo o processo
através das abordagens delineadas na seção 9.1.1. Espera-se que o método BSmart e as suas
ferramentas sejam o fundamento de um ambiente que possibilite a criação de aplicações Java
Card confiáveis e seguras, proporcionando que estas sejam geradas com menos erros e menor
probabilidade de falhas.
Nas seções a seguir evidenciam-se as contribuições desta tese (seção 9.1), analisa-se a ade-
quação do método B ao desenvolvimento formal de aplicações para Java Card (seção 9.2) e
delineiam-se os desenvolvimentos futuros deste trabalho (seção 9.3).
Destaca-se que parte das especificações e demais artefatos produzidos na tese, bem como
as ferramentas implementadas, podem ser obtidas no sítio http://code.google.com/p/bsmart/.
Nesse endereço também encontram-se as instruções de instalação e execução das ferramentas
de software.
174
III. Descrição das gramáticas das linguagens B0 e Java e o mapeamento da tradução entre
cada elemento dessas linguagens através de regras de reescrita de termos em ASF+SDF.
para futuros usuários e desenvolvedores. Ressalta-se que esse processo possibilita a verificação
através da inspeção de cada elemento e da simulação da transformação entre as linguagens
através da ferramenta Meta-Environment.
É importante enfatizar que o modelo em ASF+SDF não se configura em uma prova for-
mal da tradução. Para tanto, seria necessário a descrição formal da semântica de ambas as
linguagens e da transformação entre elas. Optou-se pela solução adotada ao se verificar que
o tempo disponível para a realização desta tese, com o atendimento dos seus outros objetivos,
não seria suficiente para concluir a tarefa de especificação semântica. Por outro lado, o trabalho
desenvolvido pode servir como uma referência inicial para uma futura criação do seu modelo
formal.
Observa-se que o software pode ser executado em linha de comando ou ser integrado à
interface gráfica fornecida pela ferramenta Atelier B. Deve-se preferir a segunda forma, tendo
em vista tornar o desenvolvimento mais ágil e possibilitar o uso de toda a gama de ferramentas
que o ambiente oferece.
Cumpre salientar que o estudo de caso do passaporte eletrônico do capítulo 7 foi um im-
portante auxílio à validação do método, da biblioteca KitSmart e do seu suporte de ferramentas.
No primeiro caso, seguiu-se os passos delineados no método para especificar e verificar cor-
retamente, até a implementação B, os métodos relacionados aos protocolos fundamentais do
passaporte (Passive Authentication e Basic Access Control).
176
Nesta seção tecemos algumas considerações sobre a experiência do uso do método formal
B neste trabalho, evidenciando as suas vantagens a este tipo de desenvolvimento, assim como
algumas situações que tiveram que ser contornadas devido a limitações ou características parti-
culares do método em sua versão clássica.
Inicialmente, evidencia-se que o método B, apesar das limitações listadas nesta seção,
mostra-se adequado à especificação e refinamento de aplicações Java Card. Para tanto, deve-se
destacar o fato do ambiente Java Card fornecer uma linguagem bem mais restrita se comparado
ao Java tradicional, o que resulta em desenvolvimento formal mais conciso, concentrando-se
em menos aspectos de linguagem e do ambiente de execução. Observa-se ainda que diversos
componentes da linguagem de implementação B encontram equivalência direta com elementos
da linguagem Java Card, dentre os quais pode-se elencar as instruções, os tipos de dados in-
teiros (nesse caso com o suporte dos módulos do KitSmart), as diversas expressões e, de certo
modo, a composição de máquinas, que pode ser reproduzida por meio do relacionamento entre
classes em Java Card.
o componente abstrato refinado inclui a máquina concreta, relacionam-se seus estados, e cada
mudança de estado abstrata é feita no corpo da operação através de chamadas às operações
concretas.
Observa-se que a restrição discutida anteriormente foi resolvida em Event-B, no qual uma
operação refinada pode modificar a interface, desde que faça referencia à operação abstrata que
está sendo refinada em uma cláusula no corpo da operação. Destaca-se que em Event-B as
operações também podem ser decompostas em mais de uma operação, ou o contrário. Infe-
lizmente, o método B tradicional não foi atualizado para incluir a flexibilidade de refinamento
apresentada por Event-B.
Apesar das dificuldades supracitadas, ressalta-se como vantagens do método B o seu su-
porte de ferramentas, dentre as quais destacam-se o Atelier B e o Pro-B, e a relativa facilidade
no aprendizado e desenvolvimento com o formalismo. No entanto, visando simplificar o traba-
lho do usuário, deve-se aumentar a automatização empregada ao método, bem como proceder
com a criação de um guia de melhores práticas que devem ser seguidas na especificação e refi-
namento com o método.
Destaca-se que deve ser realizado um estudo aprofundado do método formal Event-B e a
sua adequação à especificação de aspectos do sistema smart card, de modo que o método B
178
continue sendo utilizado com o foco em desenvolver o código da aplicação Java Card principal
e Event-B na especificação e verificação dos aspectos relacionados a comunicação entre os
componentes cliente e applet.
A extensão do método para uma gama maior de aplicações deve ser também explorada.
Inicialmente, deve-se pesquisar em maior profundidade o Java Card 3.0, e verificar de que
forma o método pode ser ampliado para atendê-lo.
Cumpre evidenciar que a expansão do método deve ser acompanhada da evolução das fer-
ramentas e da biblioteca KitSmart. No caso do KitSmart, ao se construir um modelo do JCRE,
deve-se destinar especial atenção à melhoria do tratamento de aspectos internos às aplicações,
como o controle de exceção e de trechos de código sob transação.
9.3.2 Ferramentas
Salienta-se que as ferramentas ainda serão aprimoradas, com destaque para a continuidade
dos testes e a adição de elementos de interface gráfica para permitir o melhor controle das
opções que elas oferecem.
• Um gerador do applet Java Card que irá gerar a implementação JC_Applet.imp, contendo
uma implementação padrão para o seu método process, que irá receber o APDU e chamar
as operações do módulo de serviço.
Na continuação deste trabalho, deve-se pesquisar otimizações que possam ser inseridas
diretamente sob forma de refinamento ao método BSmart, tais como a busca por padrões de
refinamento de instruções e otimizações na declaração de variáveis de estado e na definição
de variáveis locais. Observa-se que essas abordagens podem ser inicialmente descritas como
um guia, e, nos casos onde for possível, inseridos em ferramenta. Nas situações em que não
seja adequado introduzir em B, as otimizações serão acrescentadas durante a fase de tradução,
utilizando-se as ideias dos trabalhos descritos anteriormente. Nesse sentido, identifica-se como
otimização já aplicada ao tradutor, a criação de objetos persistentes dentro do método construtor
da aplicação Java Card. Deve-se também buscar soluções para minimizar a criação de classes,
180
que atualmente são geradas a partir dos módulos de implementação (principal e módulos im-
portados) e dos conjuntos adiados e enumerados.
9.3.4 KitSmart
Verificam-se diversas atividades que visam aprimorar o KitSmart, dentre elas, é possível
destacar:
I. Revisar e, eventualmente, corrigir ou modificar os módulos B para tarefas que podem ser
úteis ao desenvolvedor Java Card, tais como, internacionalização, manipulação de va-
lores numéricos reais, etc. Devido a esses modelos originarem classes correspondentes
em Java Card, deve-se refiná-los até o módulo de implementação e gerar a classe corres-
pondente. Essas classes podem ser utilizadas em diferentes desenvolvimentos Java Card,
contribuindo, portanto, para diminuir o retrabalho em verificação, tradução e compilação.
A tarefa de geração de código deve ser feita com a ferramenta tradutora do BSmart, dessa
forma tornando o desenvolvimento mais ágil e contribuindo para testar esse componente
de software.
II. Pesquisar a melhor forma de se representar a tipagem com tipos abstratos de dados, le-
vando em consideração a semântica de Java Card e o aspecto de verificação em B. Atual-
mente, uma classe é representada sob a forma de um conjunto de mesmo nome da classe
em Java. Uma subclasse em uma hierarquia de herança é tratada como um subconjunto do
conjunto que representa a superclasse. Outra abordagem tentada foi modelar uma classe
através de um struct em B, que corresponde a sua definição estática, e da instância de
classe através de um record, representando o componente dinâmico, ou o objeto Java. As
limitações dessa abordagem dizem respeito ao par struct/record lidar apenas com estado,
sem permitir a definição de funções, e a falhas no provador do Atelier B tentar verificar
corretamente as definições para uma estrutura. Uma primeira abordagem consiste em
identificar a causa e solucionar esta falha, tendo em vista possibilitar o uso corretos das
estruturas na representação de tipos.
III. Estudar toda a API Java Card para a versão Java Card 3.0 classic, evolução da API 2.2.2.
Posteriormente, adaptar os módulos já desenvolvidos e criar novos modelos de acordo de
modo a especificar a totalidade da API classic.
IV. Estudar a API Java Card 3.0 connected, verificando-se a viabilidade de fornecer a espe-
cificação para essa versão da API, que possui uma gama maior de bibliotecas e recursos
181
encontrados na linguagem Java, tais como threads múltiplos, Strings, o tipo int, enum,
generics e coleta de lixo.
O estudo de caso do passaporte eletrônico foi utilizado na validação do método, das biblio-
tecas e ferramentas. Com esse propósito, especificou-se as máquinas e refinamentos necessários
à implementação dos protocolos Basic Access Control (BAC) e Passive Authentication (PA),
fundamentais para a autenticação e o acesso inicial aos arquivos de dados básicos do portador
do documento armazenados no chip.
Como trabalho futuro espera-se desenvolver todos os recursos necessários requeridos pelos
demais protocolos, a saber o Active Authentication (AA) e o Extended Access Control (EAC).
Outro ponto a ser explorado diz respeito à especificação de parte da aplicação cliente. Nesse
sentido, deve-se identificar quais componentes dessa aplicação podem ser inseridos, de modo
a complementar a especificação e melhorar o aspecto de verificação global da aplicação. Com
essa abordagem, torna-se possível refinar o cliente até a sua implementação B e gerar o código
dessa parte da aplicação para Java.
182
Referências
[ABH+ 10] Jean-Raymond Abrial, Michael Butler, Stefan Hallerstede, Thai Son Hoang,
Farhad Mehta, and Laurent Voisin. Rodin: an open toolset for modelling and
reasoning in Event-B. STTT, 12(6):447–466, 2010.
[Abr96] J.-R. Abrial. The B-Book: Assigning Programs to Meanings. Cambridge Uni-
versity Press, 1996.
[Abr10] J.-R. Abrial. Modeling in Event-B: System and Software Engineering. Cam-
bridge University Press, 2010.
[B+ 03] Didier Bert et al. Adaptable translator of B specifications to embedded C pro-
grams. In FME, volume 2805 of LNCS, pages 94–113, September 2003.
[BBFM99] Patrick Behm, Paul Benoit, Alain Faivre, and Jean-Marc Meynadier. Météor: A
Successful Application of B in a Large Project. In Formal Methods 99, volume
1708 of LNCS, 1999.
[BBK+ 07] Emilie Balland, Paul Brauner, Radu Kopetz, Pierre-Etienne Moreau, and An-
toine Reilles. Tom: piggybacking rewriting on Java. In Proceedings of the 18th
international conference on Term rewriting and applications (RTA’07), pages
36–47, Berlin, 2007. Springer.
[BH94] J. P. Bowen and M. G. Hinchey. Seven more myths of formal methods: Dis-
pelling industrial prejudices. In M. Naftalin, T. Denvir, and M. Bertran, editors,
FME’94: Industrial Benefit of Formal Methods, pages 105–117. Springer, Ber-
lin, 1994.
[BKV07] Mark Van Den Brand, Paul Klint, and Jurgen Vinju. The syntax definition
formalism SDF, 2007. Available on: http://homepages.cwi.nl/˜daybuild/daily-
books/syntax/sdf/sdf.html.
[BKV08] Mark Van Den Brand, Paul Klint, and Jurgen Vinju. The
language specification formalism ASF+SDF, 2008. Availa-
ble on: http://homepages.cwi.nl/˜daybuild/daily-books/extraction-
transformation/asfsdf/asfsdf.html.
[BR03] Lilian Burdy and Antoine Requet. Extending B with control flow breaks. In
Proceedings of the 3rd international conference on Formal specification and
development in Z and B, ZB’03, pages 513–527, Berlin, 2003. Springer.
183
[BY07] Michael Butler and Divakar Yadav. An Incremental Development of the Mondex
System in Event-B. Formal Aspects of Computing, 20(1):61–77, 2007.
[CBR02] Ludovic Casset, Lilian Burdy, and Antoine Requet. Towards a full formal spe-
cification of the Java Card API. In International Conference on Dependable
Systems and Networks (DSN’02), pages 51–56. IEEE Computer Society, 2002.
[Che00] Zhiqun Chen. Java Card Technology for Smart Cards: Architecture and Pro-
grammer’s Guide. Addison Wesley, Boston, 2000.
[Cle12a] Clearsy. Atelier B tool. http://www.atelierb.eu/, 2012. Acesso em: 25 jun. 2012.
[CW96] Edmund M. Clarke and Jeannette M. Wing. Formal methods: State of the art
and future directions. ACM Computing Surveys, 28(4):626–643, 1996.
[DGM06] David Déharbe, Bruno Gomes, and Anamaria Moreira. Automation of Java
Card component development using the B method. In ICECCS, pages 259–268.
IEEE Comp. Soc., 2006.
[DGM08] David Déharbe, Bruno Gomes, and Anamaria Moreira. BSmart: A Tool for
the Development of Java Card Applications with the B Method. In ABZ, pages
351–352, 2008.
[DLMP08] Frédéric Dadeau, Julien Lamboley, Thierry Moutet, and Marie-Laure Potet. A
verifiable conformance relationship between smart card applets and B security
models. In Proceedings of the 1st international conference on Abstract State
Machines, B and Z (ABZ’08), pages 237–250, Berlin, 2008. Springer.
[dM12] Ernesto Brasil de Matos. Uma ferramenta para geração de testes de unidade a
partir de especificações B. Mestrado, Programa de Pós-graduação em Sistemas
e Computação, UFRN, Natal, 2012.
[DPT08] Frédéric Dadeau, Marie-Laure Potet, and Régis Tissot. A B formal framework
for security developments in the domain of smart card applications. In IFIP
23rd International Information Security, pages 141–155, 2008.
184
[Dut06] Thiago Dutra. KitSmart: Um kit de tipos e estruturas de dados projetados com
o método B para o desenvolvimento rigoroso em Java Card. Graduação, Depar-
tamento de Informática e Matemática Aplicada, Universidade Federal do Rio
Grande do Norte, Natal, 2006.
[EB10] Andy Edmunds and Michael Butler. Tool Support for Event-B Code Generation.
Workshop On Tool Building in Formal Methods, ABZ 2010, Orford, CA, 2010.
[Ecl10] Eclipse Foundation. Eclipse web site. www.eclipse.org. Last access: oct. 2010,
2010.
[FB07] Simon Fraser and Richard Banach. Configurable proof obligations in the Frog
toolkit. In Software Engineering and Formal Methods, pages 361–370, London,
UK, 2007. IEEE Computer Society.
[FFW07] Leo Freitas, Zheng Fu, and Jim Woodcock. POSIX file store in Z/Eves: an
experiment in the verified software repository. In Proceedings of the 12th IEEE
International Conference on Engineering Complex Computer Systems, pages
3–14, Washington, DC, USA, 2007. IEEE Computer Society.
[FJM04] Houda Fekih, Leila Jemmi, and Stephan Merz. Transformation des spécificati-
ons B en des diagrammes UML. In Proceedings of Approches Formelles dans
l’Assistance au Développement de Logiciels (AFADL’04), Besançon, June 2004.
[Fra08] Simon Fraser. Mechanized Support for Retrenchment. PhD in computer sci-
ence, Faculty of Engineering and Physical Sciences of University of Manches-
ter, Manchester, UK, 2008.
[Gar06] Gary Leavens and Yoonsik Cheon. Design by Contract with JML.
http://www.eecs.ucf.edu/˜leavens/JML/jmldbc.pdf, 2006.
[GDMM10] Bruno Gomes, David Déharbe, Anamaria Moreira, and Katia Moraes. Applying
the B Method for the Rigorous Development of Smart card Applications. In
Abstract State Machines, Alloy, B and Z (ABZ 2010), pages 203–216, Orford,
Canada, 2010. Springer.
[GMD05] Bruno Gomes, Anamaria Moreira, and David Déharbe. Developing Java Card
applications with B. In Brazilian Symposium on Formal Methods (SBMF), pages
63–77, 2005.
[GO09] Artur Gomes and Marcel Oliveira. Formal specification of a cardiac pacing
system. In Proceedings of the 2nd World Congress on Formal Methods, FM’09,
pages 692–707, Berlin, 2009. Springer.
185
[KvdSV09] Paul Klint, Tijs van der Storm, and Jurgen Vinju. Rascal: A domain specific
language for source code analysis and manipulation. Source Code Analysis and
Manipulation, IEEE International Workshop on, 0:168–177, 2009.
[Lan00] Jean Louis Lanet. Are smart cards the ideal domain for applying formal
methods? In ZB ’00: Proceedings of the First International Conference of B and
Z Users on Formal Specification and Development in Z and B, pages 363–373,
London, UK, 2000. Springer.
[Lar03] Daniel Larsson. OCL Specifications for the Java Card API. Master’s thesis,
School of Computer Science and Engineering, Göteborg University, 2003.
[LC06] Gary Leavens and Yoonsik Cheon. Design by contract with JML. Technical
report, University of Central Florida, 2006.
[LM04] Daniel Larsson and Wojciech Mostowski. Specifying Java Card API in OCL.
In Peter H. Schmitt, editor, OCL 2.0 Workshop at UML 2003, volume 102C of
ENTCS, pages 3–19. Elsevier, November 2004.
[LS07] Thierry Lecomte and Thierry Servant. Formal methods in safety-critical railway
systems. In 10th Brasilian Symposium on Formal Methods (SBMF2007), pages
1–, Ouro Preto, 2007.
[MC10] Georges Mariano and Samuel Colin. Brillant: an open source platform for B.
Workshop on Tool Building in Formal Methods, ABZ 2010, Orford, CA, 2010.
[MdB01] Hugues Martin and Lydie du Bousquet. Automatic test generation for Java-Card
applets. In JavaCard ’00: Revised Papers from the First International Workshop
on Java on Smart Cards: Programming and Security, pages 121–136, London,
UK, 2001. Springer.
[MdMJD+ 08] Éberton Marinho, Valério de Medeiros Júnior, David Déharbe, Bruno Gomes,
and Cláudia Tavares. A Ferramenta Batcave para a Verificação de Especifica-
ções Formais na Notação B. In XV Sessão de Ferramentas do XXII Simpósio
Brasileiro de Engenharia de Software, pages 1–6, Campinas, 2008.
[MLF08] Hugo Daniel Macedo, Peter Gorm Larsen, and John S. Fitzgerald. Incremental
development of a distributed real-time model of a cardiac pacing system using
VDM. In Formal Methods 2008 (FM’08), pages 181–197, 2008.
[MP01] H. Meijer and E. Poll. Towards a Full Formal Specification of the Java Card
API. In Smart Card Prog. and Security, volume 2140 of LNCS, pages 165–178.
Springer, 2001.
[MP10] Wojciech Mostowski and Erik Poll. Electronic Passports in a Nutshell. Tech-
nical Report ICIS–R10004, Radboud University Nijmegen, June 2010. Avai-
lable at https://pms.cs.ru.nl/iris-diglib/src/getContent.php?id=2010-Mostowski-
ElectronicNutshell.
[MT00] Stéphanie Motré and Corinne Téri. Using B Method to Formalize the Java Card
Runtime Security Policy for a Common Criteria Evaluation. In 23rd National
Information Systems Security Conference (NISSC 2000), pages 1–, 2000.
[Net07] Plácido Neto. Java card modelling language (JCML): Definição e Implemen-
tação. Master’s thesis, Universidade Federal do Rio Grande do Norte, Natal,
2007.
[OOS11] OOSTDIJK, M. et. al. JMRTD Project Web site. Disponível em:
http://jmrtd.org, 2011. Acesso em: 08 mar. 2011.
[PvdBJ01] Erik Poll, Joachim van den Berg, and Bart Jacobs. Formal Specification of the
Java Card API in JML: the APDU class. Computer Networks, 36(4):407–421,
2001.
[RB00] Antoine Requet and Gaëlle Bossu. Embedded formally proved code in a smart
card: Converting B to C. In ICFEM’00, pages 15–, York, UK, 2000. IEEE
Computer Society.
[RE03] Wolfgang Rankl and Wolfgang Effing. Smart Card Handbook. John Wiley,
Baffins Lane, 3rd. edition, 2003.
[SB06] Colin Snook and Michael Butler. UML-B: Formal modeling and design aided
by UML. ACM Trans. Softw. Eng. Methodol., 15(1):92–122, 2006.
[SB08] Colin Snook and Michael Butler. UML-B and Event-B: an integration of langua-
ges and tools. In Proceedings of the IASTED International Conference on Soft-
ware Engineering (SE’08), pages 336–341, Anaheim, CA, USA, 2008. ACTA
Press.
[SCW00] Susan Stepney, David Cooper, and Jim Woodcock. An electronic purse: Spe-
cification, refinement, and proof. Technical monograph PRG-126, Oxford Uni-
versity Computing Laboratory, jul 2000.
[Ser07] Thierry Servant. Brama: A new graphic animation tool for B models. In B 2007:
Formal Methods and Development in B, LNCS 4355, pages 274–276, Besançon,
France, 2007. Springer.
[SL99] Denis Sabatier and Pierre Lartigue. The use of the B formal method for the
design and the validation of the transaction mechanism for smart card applica-
tions. In FM’99 - Formal Methods: World Congress on Formal Methods in the
Development of Computing Systems, number 1708 in LNCS, pages 348–368,
Toulose, France, 1999. Springer.
[SM10] Sun Microsystems. Java card platform specification 2.2.2. Disponível em:
<http://java.sun.com/javacard/specs.html>, 2010. Acesso em: 03 ago. 2010.
[Ter03] Terese. Term Rewriting Systems. Cambridge University Press, 1st edition, 2003.
[TRVH03] B. Tatibouet, A. Requet, J. C. Voisinet, and A. Hammad. Java Card Code Gene-
ration from B Specifications. In ICFEM, volume 2885 of LNCS, pages 306–318,
2003.
[Vin05] Jurgen Vinju. Analysis and Transformation of Source Code by Parsing and
Rewriting. PhD thesis, University of Amsterdam, 2005.
[vWOF+ 05] Arjen van Weelden, Martijn Oostdijk, Lars Frantzen, Pieter W. M. Koopman,
and Jan Tretmans. On-the-fly formal testing of a smart card applet. In Security
and Privacy in the Age of Ubiquitous Computing, IFIP TC11 20th International
Conference on Information Security (SEC’05), pages 565–576, Chiba, Japan,
2005. Springer.
190
MACHINE JShort
CONCRETE_CONSTANTS
JSHORT, MAXSHORT , MINSHORT ,
sum_short, subt_short, mult_short, div_short, mod_short,
cast_short, equal_short, gt_short, gte_short
PROPERTIES
MAXSHORT ∈ Z ∧ MAXSHORT = 32767 ∧
MINSHORT ∈ Z ∧ MINSHORT = -32768 ∧
JSHORT = MINSHORT .. MAXSHORT ∧
cast_short ∈ Z → JSHORT ∧
∀ ( s1 ) . ( s1 ∈ Z =⇒
(s1 = 0 =⇒ cast_short(s1) = 0) ∧
(s1 > 0 =⇒ cast_short(s1) = s1 mod 32767) ∧
(s1 < 0 =⇒ cast_short(s1) = -(-s1 mod 32767)) ) ∧
equal_short ∈ JSHORT × JSHORT → BOOL ∧
∀ ( s1 , s2 ) . ( s1 ∈ JSHORT ∧ s2 ∈ JSHORT =⇒
( ( s1 = s2 ) =⇒ equal_short ( s1 7→ s2 ) = TRUE ) ∧
( ( s1 6= s2 ) =⇒ equal_short ( s1 7→ s2 ) = FALSE ) ) ∧
gt_short ∈ JSHORT × JSHORT → BOOL ∧
∀ ( s1 , s2 ) . ( s1 ∈ JSHORT ∧ s2 ∈ JSHORT =⇒
( ( s1 > s2 ) =⇒ gt_short ( s1 7→ s2 ) = TRUE ) ∧
( ( s1 ≤ s2 ) =⇒ gt_short ( s1 7→ s2 ) = FALSE ) ) ∧
gte_short ∈ JSHORT × JSHORT → BOOL ∧
∀ ( s1 , s2 ) . ( s1 ∈ JSHORT ∧ s2 ∈ JSHORT =⇒
( ( s1 ≥ s2 ) =⇒ gte_short ( s1 7→ s2 ) = TRUE ) ∧
( ( s1 < s2 ) =⇒ gte_short ( s1 7→ s2 ) = FALSE ) )
END
191
MACHINE JBoolean
CONCRETE_CONSTANTS
JBOOLEAN,
or_boolean, lor_boolean, and_boolean, land_boolean, lnot_boolean, lxor_boolean
PROPERTIES
JBOOLEAN = BOOL ∧
ASSERTIONS
lor_boolean ( TRUE 7→ TRUE ) = TRUE ;
lor_boolean ( TRUE 7→ FALSE ) = TRUE ;
lor_boolean ( FALSE 7→ TRUE ) = TRUE ;
lor_boolean ( FALSE 7→ FALSE ) = FALSE ;
land_boolean ( TRUE 7→ TRUE ) = TRUE ;
land_boolean ( TRUE 7→ FALSE) = FALSE ;
land_boolean ( FALSE 7→ TRUE ) = FALSE ;
land_boolean ( FALSE 7→ FALSE ) = FALSE ;
lnot_boolean (TRUE) = FALSE ;
lnot_boolean (FALSE) = TRUE ;
lxor_boolean ( TRUE 7→ TRUE ) = FALSE ;
lxor_boolean ( TRUE 7→ FALSE ) = TRUE ;
lxor_boolean ( FALSE 7→ TRUE ) = TRUE ;
lxor_boolean ( FALSE 7→ FALSE ) = FALSE ;
or_boolean ( TRUE 7→ TRUE ) = TRUE ;
or_boolean ( TRUE 7→ FALSE ) = TRUE ;
or_boolean ( FALSE 7→ TRUE ) = TRUE ;
or_boolean ( FALSE 7→ FALSE ) = FALSE ;
and_boolean ( TRUE 7→ TRUE ) = TRUE ;
and_boolean ( TRUE 7→ FALSE) = FALSE ;
and_boolean ( FALSE 7→ TRUE ) = FALSE ;
and_boolean ( FALSE 7→ FALSE ) = FALSE
END
192
result ← getCurrentState =
BEGIN result := state END;
blocksize ← getInBlockSize =
BEGIN blocksize : (blocksize ∈ JSHORT ∧ blocksize ≥ 0) END;
nad ← getNAD =
BEGIN nad :∈ JBYTE END;
blocksize ← getOutBlockSize =
BEGIN blocksize : (blocksize ∈ JSHORT ∧ blocksize ≥ 0) END;
protocol ← getProtocol =
CHOICE protocol := PROTOCOL_TO
OR protocol := PROTOCOL_T1
END;
result ← isCommandChainingCLA =
CHOICE result := TRUE /* this APDU is not the last APDU of a command chain */
OR result := FALSE
END;
result ← isISOInterindustryCLA =
CHOICE result := TRUE
OR result := FALSE
END;
result ← isSecureMessagingCLA =
CHOICE result := TRUE
OR result := FALSE
END;
lr := subt_short(lr, len)
END;
result ← setOutgoingNoChaining =
PRE
(state = STATE_INITIAL ∨ state = STATE_PARTIAL_INCOMING ∨
state = STATE_FULL_INCOMING)
/* APDUException if this method, or setOutgoing() method already invoked*/
/* APDUException I/O error */
THEN
state := STATE_OUTGOING ||
result := le
END;
B.1 B02Java.sdf
1 module B−N o t a t i o n / B02Java
2
3 i m p o r t s B−N o t a t i o n / C l a u s e
4 imports java / syntax / Java
5
6 exports
7 c o n t e x t −f r e e s t a r t −s y m b o l s
8 Implementation CompilationUnit
9
10 c o n t e x t −f r e e s y n t a x
11 t r d −bcomp ( I m p l e m e n t a t i o n ) −> C o m p i l a t i o n U n i t
12
13 t r d −c l a u s e s ( I m p l e m e n t a t i o n C l a u s e ∗ ) −> ClassBodyDeclaration∗
14 t r d −c l a u s e ( I m p l e m e n t a t i o n C l a u s e + ) −> ClassBodyDeclaration+
15 t r d −i m p o r t s ( { I m p o r t " , " } + ) −> ClassBodyDeclaration+
16 t r d −s e e s ( { S e l e c t e d I d e n t " , " } + ) −> ClassBodyDeclaration+
17 t r d −p r o m o t e s ( { S e l e c t e d I d e n t " , " } + ) −> ClassBodyDeclaration+
18 t r d −s e t s ( { S e t " ; " } + ) −> ClassBodyDeclaration+
19 t r d −v a l u a t i o n ( { V a l u a t i o n " ; " } + ) −> ClassBodyDeclaration+
20 t r d −o p e r a t i o n s ( { O p e r a t i o n B 0 " ; " } + ) −> ClassBodyDeclaration+
21 t r d −i n s t r u c t i o n s ({ I n s t r u c t i o n " ; " }+) −> BlockStatement+
22 trd −e l s i f s ( E l s i f B r a n c h ∗) −> BlockStatement∗
23 trd −e l s i f ( ElsifBranch ) −> BlockStatement
24 t r d −e l s e ( E l s e B r a n c h ? ) −> BlockStatement∗
25 t r d −o r s ( OrBranch ∗ ) −> SwitchBlockStatementGroup∗
26 t r d −o r ( OrBranch ) −> SwitchBlockStatementGroup
27 t r d −c o n d i t i o n ( C o n d i t i o n ) −> Primary
28 t r d −t e r m ( Term ) −> Primary
29 t r d − l i s t −term −comma ( { Term " , " } + ) −> { P r i m a r y " , " }+
30 t r d − l i s t i d −t o −s t a t i c −c o n s t ( L i s t I d e n t C o m m a ) −> ClassBodyDeclaration+
31 t r d − l i s t i d −t o −param− l i s t ( { I d e n t i f i e r " , " } + ) −> { F o r m a l P a r a m e t e r " , " }+
32 t r d − l i s t i d −t o −v a r −d e c l ( { I d e n t i f i e r " , " } + ) −> BlockStatement+
33 t r d −p r e d −t o −v a r −t y p e ( P r e d i c a t e ) −> ClassBodyDeclaration+
34 t r d −p r e d −t o −c o n s t −t y p e ( P r e d i c a t e ) −> ClassBodyDeclaration+
35
36 hiddens
37 variables
38 " $BImpl " [0 −9]∗ −> Implementation
39 " $Imps1 + " −> { I m p o r t " , " }+
40 " $Imp " [0 −9] −> Import
41 " $ListInstBO " −> ListInstanciationB0
42 " $ B I n s t " [0 −9]∗ −> Instruction
43 " $ B I n s t L " [0 −9]∗ −> InstructionLevel1
44 " $ J S t a t " [0 −9]∗ −> Statement
45 " $JStat1 ∗" −> Statement∗
46 " $JStat2 ∗" −> Statement∗
47 " $ J S t a t 1 p +" −> Statement+
48 " $ J S t a t 2 p +" −> Statement+
49 " $JBlockSt1∗" −> BlockStatement∗
50 " $JBlockSt2∗" −> BlockStatement∗
51 " $JBlockSt3∗" −> BlockStatement∗
197
B.2 B02Java.asf
B.2.2 Cláusulas
1 [ t r d −0−c l a u s e ]
2 t r d −c l a u s e s ( ) = ;
3
4
5 [ t r d −n−c l a u s e s ]
6 $ClassBody1∗ : = t r d −c l a u s e ( $ImpClause1 ) ,
7 $ClassBody2∗ : = t r d −c l a u s e s ( $ImpClause ∗ )
8 ===>
9 t r d −c l a u s e s ( $ImpClause1 $ImpClause ∗ ) =
10 $ClassBody1∗
11 $ClassBody2∗
12
13
14 [ t r d −n−sees−s e l i d ]
15 $ClassBody1+ : = t r d −sees ( $ L i s t S e l I d +) ,
16 $ClassBody2+ : = t r d −sees ( $ S e l I d )
17 ===>
18 t r d −sees ( $ L i s t S e l I d + , $ S e l I d ) =
19 $ClassBody1+
20 $ClassBody2+
21
22
23 [ t r d −sees −1]
24 t r d −sees ( $BId0 . $BId1 ) =
25 public class $BId1 {
26
27 }
28
29
30 [ t r d −sees −2]
31 t r d −sees ( $BId0 ) =
32 public class $BId0 {
33
34 }
35
36
37 [ t r d −clause−sees ]
38 $ClassBody1+ : = t r d −sees ( $ L i s t S e l I d +)
39 ===>
40 t r d −c l a u s e (SEES $ L i s t S e l I d +) =
41 $ClassBody1+
42
43
44 [ t r d −n−i m p o r t s ]
45 $ClassBody1+ : = t r d −i m p o r t s ( $Imp1 ) ,
46 $ClassBody2+ : = t r d −i m p o r t s ( $Imps1 +)
47 ===>
48 t r d −i m p o r t s ( $Imps1 + , $Imp1 ) =
49 $ClassBody1+
50 $ClassBody2+
51
52
53 [ t r d −1−import ]
54 t r d −i m p o r t s ( $BId0 . $BId1 ) = {
55 public class $BId1 {
56 }
57
58 $BId1 $BId0 = new $BId1 ( ) ;
59 }
199
60 [ t r d −clause−i m p o r t s ]
61 $ClassBody1+ : = t r d −i m p o r t s ( $Imps1 +)
62 ===>
63 t r d −c l a u s e (IMPORTS $Imps1 +) =
64 $ClassBody1+
65
66
67 [ t r d −n−promotes ]
68 $ClassBody1+ : = t r d −promotes ( $ L i s t S e l I d +) ,
69 $ClassBody2+ : = t r d −promotes ( $ S e l I d )
70 ===>
71 t r d −promotes ( $ L i s t S e l I d + , $ S e l I d ) =
72 $ClassBody1+
73 $ClassBody2+
74
75
76 [ t r d −1−promote ]
77 t r d −promotes ( $BId0 . $BId1 ) =
78 public short $BId1 ( short p r ) {
79 short $BId0 = new $BId0 ( p r ) ;
80
81 r e t u r n $BId0 . $BId1 ( p r ) ;
82 }
83
84
85 [ t r d −clause−promotes ]
86 $ClassBody1+ : = t r d −promotes ( $ L i s t S e l I d +)
87 ===>
88 t r d −c l a u s e (PROMOTES $ L i s t S e l I d +) =
89 $ClassBody1+
90
91
92 [ t r d −clause−extends ]
93 t r d −c l a u s e (EXTENDS $ L i s t S e l I d +) = ;
94
95
96 [ t r d −sets −n ]
97 $ClassBody1+ : = t r d −s e t s ( $Sets1 +) ,
98 $ClassBody2+ : = t r d −s e t s ( $Set1 )
99 ===>
100 t r d −s e t s ( $Sets1 + ; $Set1 ) =
101 $ClassBody1+
102 $ClassBody2+
103
104
105 [ t r d −set −1]
106 t r d −s e t s ( $BId0 ) =
107 class $BId0 {
108
109 }
110
111
112 [ t r d −l i d −to−s t a t i c −1]
113 t r d − l i s t i d −to−s t a t i c −const ( $BId0 ) =
114 public s t a t i c f i n a l byte $BId0 ;
115
116
117 [ t r d −l i d −to−s t a t i c −n ]
118 $ClassBody1+ : = t r d − l i s t i d −to−s t a t i c −const ( $ L i s t I d +) ,
119 $ClassBody2+ : = t r d − l i s t i d −to−s t a t i c −const ( $BId )
120 ===>
121 t r d − l i s t i d −to−s t a t i c −const ( $ L i s t I d + , $BId ) =
122 $ClassBody1+
123 $ClassBody2+
124
125
126 [ t r d −set −2]
127 $ClassBody1+ : = t r d − l i s t i d −to−s t a t i c −const ( $ L i s t I d +)
128 ===>
129 t r d −s e t s ( $BId0 = { $ L i s t I d + } ) =
130 public class $BId0 {
131 $ClassBody1+
132 }
133
134
135 [ t r d −clause−s e t s ]
136 $ClassBody1+ : = t r d −s e t s ( $Sets1 +)
137 ===>
138 t r d −c l a u s e (SETS $Sets1+ ) =
139 $ClassBody1+
140
141
142 [ t r d −clause−const ]
143 t r d −c l a u s e (CONSTANTS $ L i s t I d +) = ;
144
200
145 [ t r d −clause−c c o n s t ]
146 t r d −c l a u s e (CONCRETE_CONSTANTS $ L i s t I d +) = ;
147
148
149 [ t r d −clause−prop ]
150 $ClassBody1+ : = t r d −pred−to−const−t y p e ( $Pred )
151 ===>
152 t r d −c l a u s e (PROPERTIES $Pred ) = $ClassBody1+
153
154
155 [ t r d −clause−v a l u e s ]
156 $ClassBody1+ : = t r d −v a l u a t i o n ( $Vals1 +)
157 ===>
158 t r d −c l a u s e (VALUES $Vals1 +) =
159 $ClassBody1+
160
161
162 [ t r d −v a l u a t i o n −1]
163 $ClassBody1+ : = t r d −v a l u a t i o n ( $Vals1 +) ,
164 $ClassBody2+ : = t r d −v a l u a t i o n ( $Val1 )
165 ===>
166 t r d −v a l u a t i o n ( $Vals1 + ; $Val1 ) =
167 $ClassBody1+
168 $ClassBody2+
169
170
171 [ t r d −v a l u a t i o n −2]
172 $JPrExpr0 : = t r d −term ( $BTerm0 )
173 ===>
174 t r d −v a l u a t i o n ( $BId0 = $BTerm0 ) =
175 static {
176 $BId0 = $JPrExpr0 ;
177 }
178
179
180 [ t r d −v a l u a t i o n −3]
181 $JPrExpr0 : = t r d −c o n d i t i o n ( $BCond0 )
182 ===>
183 t r d −v a l u a t i o n ( $BId0 = BOOL ( $BCond0 ) ) =
184 static {
185 $BId0 = ( ( $JPrExpr0 ) ? t r u e : f a l s e ) ;
186 }
187
188
189 [ t r d −clause−v a r ]
190 t r d −c l a u s e (CONCRETE_VARIABLES $ L i s t I d +) = ;
191
192
193 [ t r d −clause−i n v ]
194 $ClassBody1+ : = t r d −pred−to−var−t y p e ( $Pred )
195 ===>
196 t r d −c l a u s e ( INVARIANT $Pred ) = $ClassBody1+
197
198
199 [ t r d −clause−a s s e r t ]
200 t r d −c l a u s e (ASSERTIONS $LPredSemi +) = ;
201
202
203 [ t r d −clause− i n i t i a l i s a t i o n ]
204 $JBlockSt1+ : = t r d −i n s t r u c t i o n s ( $ B I n s t s 1 +)
205 ===>
206 t r d −c l a u s e ( INITIALISATION $ B I n s t s 1 +) =
207 void INITIALISATION ( ) {
208 $JBlockSt1+
209 }
210
211
212 [ t r d −l i d −param− l i s t −1]
213 t r d − l i s t i d −to−param− l i s t ( $BId1 ) = short $BId1
214
215
216 [ t r d −l i d −param− l i s t −n ]
217 $FParams1+ : = t r d − l i s t i d −to−param− l i s t ( $ListIdComma1 +) ,
218 $FParams2+ : = t r d − l i s t i d −to−param− l i s t ( $BId0 )
219 ===>
220 t r d − l i s t i d −to−param− l i s t ( $ListIdComma1 + , $BId0 ) =
221 $FParams1 + ,
222 $FParams2+
223
224
225 [ t r d −clause−op ]
226 $ClassBody1+ : = t r d −o p e r a t i o n s ( $ListOp +)
227 ===>
228 t r d −c l a u s e (OPERATIONS $ListOp +) =
229 $ClassBody1+
201
230 [ t r d −b−oper−n ]
231 $ClassBody1+ : = t r d −o p e r a t i o n s ( $ListOp +) ,
232 $ClassBody2+ : = t r d −o p e r a t i o n s ( $Op1 )
233 ===>
234 t r d −o p e r a t i o n s ( $ListOp + ; $Op1 ) =
235 $ClassBody1+
236 $ClassBody2+
237
238
239 [ t r d −b−oper −1]
240 $FParams1+ : = t r d − l i s t i d −to−param− l i s t ( $ListIdComma1 +) ,
241 $JBlockSt1+ : = t r d −i n s t r u c t i o n s ( $ B I n s t L )
242 ===>
243 t r d −o p e r a t i o n s ( $BId0 <−− $BId1 ( $ListIdComma1 +) = $ B I n s t L ) =
244 public short $BId1 ( $FParams1 +) {
245 short $BId0 = 0 ;
246
247 $JBlockSt1+
248
249 r e t u r n $BId0 ;
250 }
251
252
253 [ t r d −b−oper −2]
254 $JBlockSt1+ : = t r d −i n s t r u c t i o n s ( $ B I n s t L )
255 ===>
256 t r d −o p e r a t i o n s ( $BId0 <−− $BId1 = $ B I n s t L ) =
257 public short $BId1 ( ) {
258 short $BId0 = 0 ;
259
260 $JBlockSt1+
261
262 r e t u r n $BId0 ;
263 }
264
265
266 [ t r d −b−oper −3]
267 $FParams1+ : = t r d − l i s t i d −to−param− l i s t ( $ListIdComma1 +) ,
268 $JBlockSt1+ : = t r d −i n s t r u c t i o n s ( $ B I n s t L )
269 ===>
270 t r d −o p e r a t i o n s ( $BId1 ( $ListIdComma1 +) = $ B I n s t L ) =
271 public void $BId1 ( $FParams1 +) {
272 $JBlockSt1+
273 }
274
275
276 [ t r d −b−oper −4]
277 $JBlockSt1+ : = t r d −i n s t r u c t i o n s ( $ B I n s t L )
278 ===>
279 t r d −o p e r a t i o n s ( $BId1 = $ B I n s t L ) =
280 public void $BId1 ( ) {
281 $JBlockSt1+
282 }
B.2.3 Instruções
1 [ t r d −i n s t r −n ]
2 $JBlockSt1+ : = t r d −i n s t r u c t i o n s ( $ B I n s t 0 ) ,
3 $JBlockSt2+ : = t r d −i n s t r u c t i o n s ( $ B I n s t s 1 +)
4 ===>
5 t r d −i n s t r u c t i o n s ( $ B I n s t 0 ; $ B I n s t s 1 +) =
6 $JBlockSt1+
7 $JBlockSt2+
8
9
10 [ t r d −i n s t r −i d e n t i t y ]
11 t r d −i n s t r u c t i o n s ( s k i p ) = ;
12
13
14 [ t r d −i n s t r −begin ]
15 $JBlockSt1+ : = t r d −i n s t r u c t i o n s ( $ B I n s t s 1 +)
16 ===>
17 t r d −i n s t r u c t i o n s ( BEGIN $ B I n s t s 1 + END) =
18 { $JBlockSt1+ }
19
20
21 [ t r d −i n s t r −bcmeq−1]
22 $JPrExpr0 : = t r d −term ( $BTerm0 )
23 ===>
24 t r d −i n s t r u c t i o n s ( $ S e l I d : = $BTerm0 ) =
25 $ S e l I d = $JPrExpr0 ;
202
26 [ t r d − l i s t −term−comma−1]
27 $JPrExpr1+ : = t r d −term ( $BTerm )
28 ===>
29 t r d − l i s t −term−comma( $BTerm ) = $JPrExpr1+
30
31
32 [ t r d −l t e r m −comma−n ]
33 $JPrExpr0 : = t r d −term ( $BTerm1 ) ,
34 $JPrExpr1+ : = t r d − l i s t −term−comma( $LTermComma1+)
35 ===>
36 t r d − l i s t −term−comma( $BTerm1 , $LTermComma1+) =
37 $JPrExpr0 , $JPrExpr1+
38
39
40 [ t r d −i n s t r −o p c a l l −1]
41 $JPrExpr1+ : = t r d − l i s t −term−comma( $LTermComma1+)
42 ===>
43 t r d −i n s t r u c t i o n s ( $ S e l I d 0 <−− $ S e l I d 1 ( $LTermComma1+) ) =
44 $ S e l I d 0 = $ S e l I d 1 ( $JPrExpr1 +) ;
45
46
47 [ t r d −i n s t r −o p c a l l −2]
48 t r d −i n s t r u c t i o n s ( $ S e l I d 0 <−− $ S e l I d 1 ) =
49 $SelId0 = $SelId1 ( ) ;
50
51
52 [ t r d −i n s t r −o p c a l l −3]
53 $JPrExpr1+ : = t r d − l i s t −term−comma( $LTermComma1+)
54 ===>
55 t r d −i n s t r u c t i o n s ( $ S e l I d 1 ( $LTermComma1+) ) =
56 $ S e l I d 1 ( $JPrExpr1 +) ;
57
58
59 [ t r d −l i d −v a r d e c l −1]
60 t r d − l i s t i d −to−var−d e c l ( $BId1 ) = short $BId1 ;
61
62
63 [ t r d −l i d −v a r d e c l −n ]
64 $JBlockSt1+ : = t r d − l i s t i d −to−var−d e c l ( $ListIdComma1 +) ,
65 $JBlockSt2+ : = t r d − l i s t i d −to−var−d e c l ( $BId0 )
66 ===>
67 t r d − l i s t i d −to−var−d e c l ( $ListIdComma1 + , $BId0 ) =
68 $JBlockSt1+
69 $JBlockSt2+
70
71
72 [ t r d −i n s t r −v a r ]
73 $JBlockSt1+ : = t r d − l i s t i d −to−var−d e c l ( $ListIdComma1 +) ,
74 $JBlockSt2+ : = t r d −i n s t r u c t i o n s ( $ B I n s t s 1 +)
75 ===>
76 t r d −i n s t r u c t i o n s (VAR $ListIdComma1+ IN $ B I n s t s 1 + END) =
77 $JBlockSt1+
78 $JBlockSt2+
79
80
81 [ t r d −i n s t r − i f ]
82 $JPrExpr0 : = t r d −c o n d i t i o n ( $BCond0 ) ,
83 $JBlockSt1+ : = t r d −i n s t r u c t i o n s ( $ B I n s t s 1 +)
84 ===>
85 t r d −i n s t r u c t i o n s (
86 I F $BCond0
87 THEN $ B I n s t s 1 +
88 END) =
89 i f ( $JPrExpr0 ) {
90 $JBlockSt1+
91 }
92 [ t r d −i n s t r −i f −else ]
93 $JPrExpr0 : = t r d −c o n d i t i o n ( $BCond0 ) ,
94 $JBlockSt1+ : = t r d −i n s t r u c t i o n s ( $ B I n s t s 1 +) ,
95 $JBlockSt2 ∗ : = t r d −else ( $Else ? )
96 ===>
97 t r d −i n s t r u c t i o n s (
98 I F $BCond0
99 THEN $ B I n s t s 1 +
100 $Else ?
101 END) =
102 i f ( $JPrExpr0 ) {
103 $JBlockSt1+
104 } else {
105 $JBlockSt2 ∗
106 }
107
108
203
109 [ t r d −i n s t r −i f − e l s i f ]
110 $JPrExpr0 : = t r d −c o n d i t i o n ( $BCond0 ) ,
111 $JBlockSt1+ : = t r d −i n s t r u c t i o n s ( $ B I n s t s 1 +) ,
112 $JBlockSt1 ∗ : = t r d −e l s i f s ( $ E l s i f 0 ∗ )
113 ===>
114 t r d −i n s t r u c t i o n s (
115 I F $BCond0
116 THEN $ B I n s t s 1 +
117 $Elsif0∗
118 END) =
119 i f ( $JPrExpr0 ) {
120 $JBlockSt1+
121 } else {
122 $JBlockSt1 ∗
123 }
124
125
126 [ t r d −i n s t r −i f −e l s i f −else ]
127 $JPrExpr0 : = t r d −c o n d i t i o n ( $BCond0 ) ,
128 $JBlockSt1+ : = t r d −i n s t r u c t i o n s ( $ B I n s t s 1 +) ,
129 $JBlockSt1 ∗ : = t r d −e l s i f s ( $ E l s i f 0 ∗ ) ,
130 $JBlockSt2 ∗ : = t r d −else ( $Else ? )
131 ===>
132 t r d −i n s t r u c t i o n s (
133 I F $BCond0
134 THEN $ B I n s t s 1 +
135 $Elsif0∗
136 $Else ?
137 END) =
138 i f ( $JPrExpr0 ) {
139 $JBlockSt1+
140 } else {
141 $JBlockSt1 ∗
142 $JBlockSt2 ∗
143 }
144
145
146 [ t r d −else−b r ]
147 $JBlockSt1+ : = t r d −i n s t r u c t i o n s ( $ B I n s t s 1 +)
148 ===>
149 t r d −else ( ELSE $ B I n s t s 1 +) = $JBlockSt1+
150
151
152 [ t r d −e l s i f −b r ]
153 $JPrExpr0 : = t r d −c o n d i t i o n ( $BCond0 ) ,
154 $JBlockSt1+ : = t r d −i n s t r u c t i o n s ( $ B I n s t s 1 +) ,
155 $JBlockSt1 ∗ : = t r d −e l s i f s ( $ E l s i f 0 ∗ )
156 ===>
157 t r d −e l s i f s ( ELSIF $BCond0 THEN $ B I n s t s 1 + $ E l s i f 0 ∗ ) =
158 i f ( $JPrExpr0 ) {
159 $JBlockSt1+
160 } else {
161 $JBlockSt1 ∗
162 }
163
164
165 [ t r d −e l s i f s −br −0]
166 t r d −e l s i f s ( ) =
167
168
169 [ t r d −e l s i f s −br−n ]
170 $JBlockSt1 ∗ : = t r d − e l s i f ( $ E l s i f 1 ) ,
171 $JBlockSt2 ∗ : = t r d −e l s i f s ( $ E l s i f 0 ∗ )
172 ===>
173 t r d −e l s i f s ( $ E l s i f 1 $ E l s i f 0 ∗ ) =
174 $JBlockSt1 ∗
175 $JBlockSt2 ∗
176
177
178 [ t r d −i n s t r −case−else ]
179 $JPrExpr0 : = t r d −term ( $BTermSimp0 ) ,
180 $JPrExpr1 : = t r d −term ( $BTermSimp1 ) ,
181 $JBlockSt1+ : = t r d −i n s t r u c t i o n s ( $ B I n s t s 1 +) ,
182 $JSwitchBlock0 ∗ : = t r d −o r s ( $Or0 ∗ ) ,
183 $JBlockSt2+ : = t r d −else ( $Else ? )
184 ===>
185 t r d −i n s t r u c t i o n s (
186 CASE $BTermSimp0
187 OF
188 EITHER $BTermSimp1
189 THEN $ B I n s t s 1 +
204
190 $Or0∗
191 $Else ?
192 END
193 END) =
194 switch ( $JPrExpr0 ) {
195 case $JPrExpr1 : {
196 $JBlockSt1+
197 break ;
198 }
199 $JSwitchBlock0 ∗
200 default : {
201 $JBlockSt2+
202 break ;
203 }
204 }
205
206
207 [ t r d −i n s t r −case−noelse ]
208 $JPrExpr0 : = t r d −term ( $BTermSimp0 ) ,
209 $JPrExpr1 : = t r d −term ( $BTermSimp1 ) ,
210 $JBlockSt1+ : = t r d −i n s t r u c t i o n s ( $ B I n s t s 1 +) ,
211 $JSwitchBlock0 ∗ : = t r d −o r s ( $Or0 ∗ )
212 ===>
213 t r d −i n s t r u c t i o n s (
214 CASE $BTermSimp0
215 OF
216 EITHER $BTermSimp1
217 THEN $ B I n s t s 1 +
218 $Or0∗
219 END
220 END) =
221 switch ( $JPrExpr0 ) {
222 case $JPrExpr1 : {
223 $JBlockSt1+
224 break ;
225 }
226 $JSwitchBlock0 ∗
227 }
228
229
230 [ t r d −case−or −0]
231 t r d −o r s ( ) =
232
233
234 [ t r d −case−or−n ]
235 $JSwitchBlock0 ∗ : = t r d −o r ( $Or ) ,
236 $JSwitchBlock1 ∗ : = t r d −o r s ( $Or0 ∗ )
237 ===>
238 t r d −o r s ( $Or $Or0 ∗ ) =
239 $JSwitchBlock0 ∗
240 $JSwitchBlock1 ∗
241
242
243 [ t r d −case−o r ]
244 $JPrExpr0 : = t r d −term ( $BTermSimp0 ) ,
245 $JBlockSt1+ : = t r d −i n s t r u c t i o n s ( $ B I n s t s 1 +)
246 ===>
247 t r d −o r (OR $BTermSimp0 THEN $ B I n s t s 1 +) =
248 case $JPrExpr0 : {
249 $JBlockSt1+
250 break ;
251 }
252
253
254 [ t r d −i n s t r −while ]
255 $JPrExpr0 : = t r d −c o n d i t i o n ( $BCond0 ) ,
256 $JBlockSt1+ : = t r d −i n s t r u c t i o n s ( $ B I n s t s 1 +)
257 ===>
258 t r d −i n s t r u c t i o n s (
259 WHILE $BCond0 DO
260 $BInsts1+
261 INVARIANT $BCond1
262 VARIANT $BTerm0
263 END) =
264 while ( $JPrExpr0 ) {
265 $JBlockSt1+
266 }
205
B.2.4 Termos
1 [ t r d −bterm−s e l i d −1]
2 t r d −term ( $ S e l I d ) = $ S e l I d
3
4
5 [ t r d −bterm−bool −1]
6 t r d −term (TRUE) = t r u e
7
8
9 [ t r d −bterm−bool −2]
10 t r d −term ( FALSE ) = f a l s e
11
12
13 [ t r d −bterm−i n t r −1]
14 t r d −term ( $ D e c I n t L i t ) = $ D e c I n t L i t
15
16
17 [ t r d −bterm−i n t r −2]
18 t r d −term ( MAXINT ) = I n t e g e r . MAX_VALUE
19
20
21 [ t r d −bterm−i n t r −3]
22 t r d −term ( MININT ) = I n t e g e r . MIN_VALUE
23
24
25 [ t r d −bterm−set−empty ]
26 t r d −term ( { } ) = n u l l
27
28
29 [ t r d −bterm−seq−empty ]
30 t r d −term ( [ ] ) = n u l l
31
32
33 [ t r d −bterm−paren ]
34 $JPrExpr0 : = t r d −term ( $BTerm0 )
35 ===>
36 t r d −term ( ( $BTerm0 ) ) = ( $JPrExpr0 )
37
38
39 [ t r d −bterm−op−res −1]
40 $JPrExpr : = t r d −c o n d i t i o n ( $BCond0 )
41 ===>
42 t r d −term ( b o o l ( $BCond0 ) ) = ( $JPrExpr ) ? t r u e : f a l s e
43
44
45 [ t r d −bterm−op−res −2]
46 $JPrExpr0 : = t r d −term ( $BTerm0 )
47 ===>
48 t r d −term ( succ ( $BTerm0 ) ) = ( ( $JPrExpr0 ) + 1 )
49
50
51 [ t r d −bterm−op−res −3]
52 $JPrExpr0 : = t r d −term ( $BTerm0 )
53 ===>
54 t r d −term ( pred ( $BTerm0 ) ) = ( ( $JPrExpr0 ) − 1 )
55
56
57 [ t r d −bterm−exp−ar −1]
58 $JPrExpr0 : = t r d −term ( $BTerm0 ) ,
59 $JPrExpr1 : = t r d −term ( $BTerm1 )
60 ===>
61 t r d −term ( $BTerm0 + $BTerm1 ) = $JPrExpr0 + $JPrExpr1
62
63
64 [ t r d −bterm−exp−ar −2]
65 $JPrExpr0 : = t r d −term ( $BTerm0 ) ,
66 $JPrExpr1 : = t r d −term ( $BTerm1 )
67 ===>
68 t r d −term ( $BTerm0 − $BTerm1 ) = $JPrExpr0 − $JPrExpr1
69
70
71 [ t r d −bterm−exp−ar −3]
72 $JPrExpr0 : = t r d −term ( $BTerm0 )
73 ===>
74 t r d −term (−$BTerm0 ) = −($JPrExpr0 )
75
76
77 [ t r d −bterm−exp−ar −4]
78 $JPrExpr0 : = t r d −term ( $BTerm0 ) ,
79 $JPrExpr1 : = t r d −term ( $BTerm1 )
80 ===>
81 t r d −term ( $BTerm0 ∗ $BTerm1 ) = $JPrExpr0 ∗ $JPrExpr1
82
83
84
85
86
206
87 [ t r d −bterm−exp−ar −5]
88 $JPrExpr0 : = t r d −term ( $BTerm0 ) ,
89 $JPrExpr1 : = t r d −term ( $BTerm1 )
90 ===>
91 t r d −term ( $BTerm0 / $BTerm1 ) = $JPrExpr0 / $JPrExpr1
92
93
94 [ t r d −bterm−exp−ar −6]
95 $JPrExpr0 : = t r d −term ( $BTerm0 ) ,
96 $JPrExpr1 : = t r d −term ( $BTerm1 )
97 ===>
98 t r d −term ( $BTerm0 mod $BTerm1 ) = $JPrExpr0 % $JPrExpr1
99
100
101 [ t r d −bterm−exp−ar −7]
102 $JPrExpr0 : = t r d −term ( $BTerm0 ) ,
103 $JPrExpr1 : = t r d −term ( $BTerm1 )
104 ===>
105 t r d −term ( $BTerm0 ∗∗ $BTerm1 ) = Math . pow ( $JPrExpr0 , $JPrExpr1 )
106
107
108 [ t r d −bterm−i n t e r v a l b 0 ]
109 $JPrExpr0 : = t r d −term ( $BTerm0 ) ,
110 $JPrExpr1 : = t r d −term ( $BTerm1 )
111 ===>
112 t r d −term ( $BTerm0 . . $BTerm1 ) = new B 0 I n t e r v a l ( $JPrExpr0 , $JPrExpr1 )
B.2.5 Condições
1 [ t r d −cond −1]
2 $JPrExpr0 : = t r d −term ( $BTermSimp0 ) ,
3 $JPrExpr1 : = t r d −term ( $BTermSimp1 )
4 ===>
5 t r d −c o n d i t i o n ( $BTermSimp0 = $BTermSimp1 ) =
6 $JPrExpr0 == $JPrExpr1
7
8
9 [ t r d −cond −2]
10 $JPrExpr0 : = t r d −term ( $BTermSimp0 ) ,
11 $JPrExpr1 : = t r d −term ( $BTermSimp1 )
12 ===>
13 t r d −c o n d i t i o n ( $BTermSimp0 / = $BTermSimp1 ) =
14 $JPrExpr0 ! = $JPrExpr1
15
16
17 [ t r d −cond −3]
18 $JPrExpr0 : = t r d −term ( $BTermSimp0 ) ,
19 $JPrExpr1 : = t r d −term ( $BTermSimp1 )
20 ===>
21 t r d −c o n d i t i o n ( $BTermSimp0 < $BTermSimp1 ) =
22 $JPrExpr0 < $JPrExpr1
23
24
25 [ t r d −cond −4]
26 $JPrExpr0 : = t r d −term ( $BTermSimp0 ) ,
27 $JPrExpr1 : = t r d −term ( $BTermSimp1 )
28 ===>
29 t r d −c o n d i t i o n ( $BTermSimp0 > $BTermSimp1 ) =
30 $JPrExpr0 > $JPrExpr1
31
32
33 [ t r d −cond −5]
34 $JPrExpr0 : = t r d −term ( $BTermSimp0 ) ,
35 $JPrExpr1 : = t r d −term ( $BTermSimp1 )
36 ===>
37 t r d −c o n d i t i o n ( $BTermSimp0 <= $BTermSimp1 ) =
38 $JPrExpr0 <= $JPrExpr1
39
40
41 [ t r d −cond −6]
42 $JPrExpr0 : = t r d −term ( $BTermSimp0 ) ,
43 $JPrExpr1 : = t r d −term ( $BTermSimp1 )
44 ===>
45 t r d −c o n d i t i o n ( $BTermSimp0 >= $BTermSimp1 ) = $JPrExpr0 >= $JPrExpr1
46
47
48 [ t r d −cond −7]
49 $JPrExpr0 : = t r d −c o n d i t i o n ( $BCond0 ) ,
50 $JPrExpr1 : = t r d −c o n d i t i o n ( $BCond1 )
51 ===>
52 t r d −c o n d i t i o n ( $BCond0 & $BCond1 ) = $JPrExpr0 && $JPrExpr1
53
207
54 [ t r d −cond −8]
55 $JPrExpr0 : = t r d −c o n d i t i o n ( $BCond0 ) ,
56 $JPrExpr1 : = t r d −c o n d i t i o n ( $BCond1 )
57 ===>
58 t r d −c o n d i t i o n ( $BCond0 o r $BCond1 ) = $JPrExpr0 | | $JPrExpr1
59
60
61 [ t r d −cond −9]
62 $JPrExpr0 : = t r d −c o n d i t i o n ( $BCond0 )
63 ===>
64 t r d −c o n d i t i o n ( n o t ( $BCond0 ) ) = ! ( $JPrExpr0 )
65
66
67 [ t r d −cond −10]
68 $JPrExpr0 : = t r d −c o n d i t i o n ( $BCond0 )
69 ===>
70 t r d −c o n d i t i o n ( ( $BCond0 ) ) = ( $JPrExpr0 )
B.2.6 Predicados
1 [ t r d −pred−var−tp−paren ]
2 $ClassBody1∗ : = t r d −pred−to−var−t y p e ( $Pred1 )
3 ===>
4 t r d −pred−to−var−t y p e ( ( $Pred1 ) ) = $ClassBody1∗
5
6
7 [ t r d −pred−var−tp−and ]
8 $ClassBody1∗ : = t r d −pred−to−var−t y p e ( $Pred1 ) ,
9 $ClassBody2∗ : = t r d −pred−to−var−t y p e ( $Pred2 )
10 ===>
11 t r d −pred−to−var−t y p e ( $Pred1 & $Pred2 ) =
12 $ClassBody1∗
13 $ClassBody2∗
14
15
16 [ t r d −pred−tp−i n t ]
17 t r d −pred−to−var−t y p e ( $BId0 : INT ) = i n t $BId0 ;
18
19
20 [ t r d −pred−tp−n a t ]
21 t r d −pred−to−var−t y p e ( $BId0 : NAT) = i n t $BId0 ;
22
23
24 [ t r d −pred−var−tp−short ]
25 $BId1 == JSHORT
26 ===>
27 t r d −pred−to−var−t y p e ( $BId0 : $BId1 ) = short $BId0 ;
28
29
30 [ t r d −pred−var−tp−byte ]
31 $BId1 == JBYTE
32 ===>
33 t r d −pred−to−var−t y p e ( $BId0 : $BId1 ) = byte $BId0 ;
34
35
36 [ t r d −pred−var−tp−bool −1]
37 $BId1 == JBOOLEAN
38 ===>
39 t r d −pred−to−var−t y p e ( $BId0 : $BId1 ) = boolean $BId0 ;
40
41
42 [ t r d −pred−var−tp−bool −2]
43 t r d −pred−to−var−t y p e ( $BId0 : BOOL) = boolean $BId0 ;
44
45
46 [ t r d −pred−var−tp−o b j e c t ]
47 t r d −pred−to−var−t y p e ( $BId0 : $BId1 ) = $BId1 $BId0 ;
48
49
50 [ t r d −pred−var−tp−a r r a y −byte ]
51 $BId2 == JBYTE
52 ===>
53 t r d −pred−to−var−t y p e ( $BId0 : $BId1 −−> $BId2 ) = byte [ ] $BId0 ;
54
55
56 [ t r d −pred−var−tp−a r r a y −short ]
57 $BId2 == JSHORT
58 ===>
59 t r d −pred−to−var−t y p e ( $BId0 : $BId1 −−> $BId2 ) = public short [ ] $BId0 ;
60
61
62
63 [ t r d −pred−var−tp−a r r a y −boolean ]
64 $BId2 == JBOOLEAN
65 ===>
208
MACHINE Passport
SEES JByte, JShort, JBoolean, Passport_Context, FileSystem_Context
INCLUDES fileSystem.FileSystem
VARIABLES
/* persistent state */
perState,
/* volatile state */
volState,
/* file that is current selected */
selectedFile,
/* a generated random number (for BAC) */
rnd,
/* sequence number for secure messaging */
ssc
INVARIANT
perState ∈ JBYTE ∧
volState ∈ seq1(JBYTE) ∧
size (volState) = 1 ∧
selectedFile ∈ EF_DG1_INDEX .. SOS_LOG_INDEX ∧
rnd ∈ seq1 (JBYTE) ∧
ssc ∈ seq1 (JBYTE)
INITIALISATION
perState := PER_STATE_INIT ||
volState := [NO_FILE_SELECTED] ||
selectedFile := EF_DG1_INDEX ||
rnd := [0, 0, 0, 0, 0, 0, 0, 0] ||
ssc := [0, 0, 0, 0, 0, 0, 0, 0]
OPERATIONS
/*Processes the first part of a request for a Passport stored file. It stores the ’id’ of the requested file in selectedFile state variable. After, The
client must call readBinary service to receive the file.
APDU = SELECT_FILE
@param fid - the id of the file to select. */
processSelectFile (fid)=
PRE
fid ∈ EF_DG1_INDEX .. SOS_LOG_INDEX ∧
volState(1) = MUTUAL_AUTHENTICATED ∧
¬ (perState = LOCKED)
THEN
CHOICE
selectedFile := fid ||
volState(1) := FILE_SELECTED
OR
volState(1) := NO_FILE_SELECTED
END
END;
211
/** Reads the current selected file and sends it back to the client.
* APDU = READ_BINARY
* @param le - the expected response length.
* @return file - the requested file
*/
file ← processReadBinary (protectedAPDU, le)=
PRE
protectedAPDU ∈ JBOOLEAN ∧
le ∈ JSHORT ∧
volState(1) = FILE_SELECTED
THEN
file ← fileSystem.getFile(selectedFile)
END;
/** Generates random sequence and stores it in ’rnd’ state variable. This random number is required for BAC and EAC protocols.
* APDU = GET_CHALENGE
* @param protectedAPDU - if secure messaging is used
* @param le - the expected length of response
* @return rnd_val - the generated random number */
rnd_val ← processGetChallenge (protectedAPDU, le) =
PRE
protectedAPDU ∈ JBOOLEAN ∧
le ∈ JSHORT ∧
perState = HAS_MUTUAL_AUTHENTICATION_KEYS ∧
¬ (volState(1) = MUTUAL_AUTHENTICATED)
THEN
volState(1) := CHALLENGED ||
ANY number
WHERE
number = seq1(JBYTE)
THEN
rnd :∈ number || rnd_val :∈ number
END
END;
key_data :∈ seq1(JBYTE)
END;
res ← getPersistentState =
BEGIN
res := perState
END;
res ← getVolatileState =
BEGIN
res := volState
END
END
212
MACHINE Passport_JC
SEES JByte, JShort,JBoolean, ISO7816,
Apdu_Properties, Passport_Context, FileSystem_Context
INCLUDES fileSystem.FileSystem, ISOException.ISOException
ABSTRACT_VARIABLES
jc_perState, jc_volState, jc_selectedFile, jc_rnd, jc_ssc
INVARIANT
jc_perState ∈ JBYTE ∧
jc_volState ∈ seq1(JBYTE) ∧ size (jc_volState) = 1 ∧
jc_selectedFile ∈ EF_DG1_INDEX .. SOS_LOG_INDEX ∧
jc_rnd ∈ seq1 (JBYTE) ∧
jc_ssc ∈ seq1 (JBYTE)
INITIALISATION
jc_perState := PER_STATE_INIT ||
jc_volState := [NO_FILE_SELECTED] ||
jc_selectedFile := EF_DG1_INDEX ||
jc_rnd := [0, 0, 0, 0, 0, 0, 0, 0] ||
jc_ssc := [0, 0, 0, 0, 0, 0, 0, 0]
OPERATIONS
ANY number
WHERE
number = seq1(JBYTE)
THEN
jc_rnd :∈ number || data_out :∈ number
END
END;
data_out :∈ seq1(JBYTE)
END;
res ← getPersistentState =
BEGIN
res := jc_perState
END;
res ← getVolatileState =
BEGIN
res := jc_volState(1)
END
END
214
REFINEMENT Passport_JC_FF_ref
REFINES Passport_JC
SEES JByte, JShort, JBoolean, ISO7816, Apdu_Properties,
Passport_Context, FileSystem_Context, Passport_JC_FF_Context
INCLUDES
fileSystem.FileSystem, ISOException.ISOException
ABSTRACT_VARIABLES
jc_perState, jc_volState, jc_selectedFile, jc_rnd, jc_ssc
INVARIANT
jc_perState ∈ JBYTE ∧
jc_volState ∈ seq1(JBYTE) ∧ size (jc_volState) = 1 ∧
jc_selectedFile ∈ EF_DG1_INDEX .. SOS_LOG_INDEX ∧
jc_rnd ∈ seq1(JBYTE) ∧
jc_ssc ∈ seq1(JBYTE)
INITIALISATION
jc_perState := PER_STATE_INIT ||
jc_volState := [NO_FILE_SELECTED] ||
jc_selectedFile := EF_DG1_INDEX ||
jc_rnd := [0, 0, 0, 0, 0, 0, 0, 0] ||
jc_ssc := [0, 0, 0, 0, 0, 0, 0, 0]
OPERATIONS
ANY number
WHERE
number = seq1(JBYTE)
THEN
jc_rnd :∈ number || data_out :∈ number
END
END;
215
data_out :∈ seq1(JBYTE)
END;
res ← getPersistentState =
BEGIN
res := jc_perState
END;
res ← getVolatileState =
BEGIN
res := jc_volState(1)
END
END
216
IMPLEMENTATION Passport_JC_imp
REFINES Passport_JC_FF_ref
SEES
JByte, JShort,JBoolean, Apdu_Properties, ISO7816,
Passport_Context, FileSystem_Context, Passport_JC_FF_Context
IMPORTS
per_state.LM_BYTE,
vol_state.LM_SEQ_0,
sel_file.LM_SHORT_FILE,
jc_rnd_var.LM_SEQ_1,
jc_ssc_var.LM_SEQ_1,
fileSystem.FileSystem,
passportUtil.PassportUtil,
ISOException.ISOException,
randomData.RandomData,
crypto.PassportCrypto, keyStore.KeyStore,
apdu.ApduUtil.Util
INVARIANT
jc_perState = per_state.num_byte ∧
jc_volState = vol_state.bt_seq ∧
jc_selectedFile = sel_file.num_short ∧
jc_rnd = jc_rnd_var.bt_seq ∧
jc_ssc = jc_ssc_var.bt_seq
OPERATIONS
vol_state.set(NO_FILE_SELECTED);
IF per_st = LOCKED
THEN
ISOException.throwIt(ex_processSelectFile0)
ELSIF ¬ (v_st = MUTUAL_AUTHENTICATED)
THEN
ISOException.throwIt(ex_processSelectFile1)
ELSE
fid := data_in(1);
IF (file 6= [])
THEN
sel_file.set_num(fid);
vol_state.set(FILE_SELECTED)
ELSE ISOException.throwIt(SW_FILE_NOT_FOUND)
END
ELSE
ISOException.throwIt(SW_INTERNAL_ERROR)
END
END
END;
217
IF ¬ (v_st = FILE_SELECTED)
THEN ISOException.throwIt(ex_processReadBinary0)
ELSE
p1 := cast_byte(0);
p2 := cast_byte(0);
IF (data_out = [])
THEN ISOException.throwIt (SW_FILE_NOT_FOUND)
ELSE
VAR
file_size, size_bf,bf_offset, out
IN
size_bf := cast_short (size(bf));
IF sum_short(cast_short(0), 2) ≤ size(data_in)
THEN
le ← Util.getShort(data_in, cast_short (0))
END;
file_size ← fileSystem.getFileSize(sel_file);
IF (size_bf ≥ 0 ∧ offset ≥ 0 ∧
subt_short(file_size, offset) ≥ 0 ∧
subt_short(size_bf, 37) ≥ 0 ∧
le ≥ 0)
THEN
len ← passportUtil.minimum(subt_short (size_bf, 37), subt_short (file_size, offset));
len ← passportUtil.minimum(len, size_bf);
len ← passportUtil.minimum(le, len);
bf_offset := 0;
IF (protectedAPDU = TRUE)
THEN
bf_offset ← crypto.getAPDUBufferOffset(len)
ELSE
IF sum_short(cast_short(0), len) ≤ size(data_out) ∧
sum_short(offset, len) ≤ size(data_out) ∧
bf_offset ≥ 0 ∧
bf 6= [] ∧
sum_short(bf_offset, len) ≤ size(bf)
THEN
out ← Util.arrayCopyNonAtomic ( data_out, offset, bf, bf_offset, len)
END
END
END
END
END
END
END
END;
218
IF v_st = MUTUAL_AUTHENTICATED
THEN
ISOException.throwIt(ex_processGetChallenge0)
ELSIF ¬ (per_st = HAS_MUTUAL_AUTHENTICATION_KEYS)
THEN
ISOException.throwIt(ex_processGetChallenge1)
ELSE
apdu_state ← apdu.getCurrentState;
le_val := cast_short (0);
IF size (data_in) ≥ 2
THEN
le_val ← Util.getShort(data_in, cast_short (0))
ELSIF (protectedAPDU = FALSE ∧
apdu_state = STATE_INITIAL)
THEN
le_val ← apdu.setOutgoing
ELSE
IF (le_val 6= 8)
THEN
ISOException.throwIt(SW_WRONG_LENGTH)
ELSE
randomData.generateData(jc_rnd, 0, le_val);
IF (protectedAPDU = TRUE)
THEN
bf_offset ← crypto.getAPDUBufferOffset(le_val)
ELSE
bf_offset := cast_short(0);
vol_state.set(CHALLENGED);
data_out := jc_rnd
END
END;
219
IF (apdu_state = STATE_INITIAL)
THEN out ← apdu.setIncomingAndReceive
ELSIF (apdu_state 6= STATE_FULL_INCOMING)
THEN ISOException.throwIt(SW_INTERNAL_ERROR);
IF (e_ifd_length ≥ 0 ∧ e_ifd_p ≥ 0 ∧ m_ifd_p ≥ 0 ∧ bf 6= [])
THEN crypto.initMac(MODE_VERIFY);
res := FALSE;
plaintex_len := cast_short (0);
res ← crypto.verifyMacFinal( bf, e_ifd_p, e_ifd_length, bf, m_ifd_p );
IF (res = FALSE)
THEN ISOException.throwIt(SW_SECURITY_STATUS_NOT_SATISFIED)
ELSE
crypto.decryptInit;
plaintex_len ← crypto.decryptFinal ( bf, e_ifd_p, e_ifd_length, bf, cast_short(0));
IF (plaintex_len 6= e_ifd_length)
THEN ISOException.throwIt(SW_INTERNAL_ERROR)
ELSE
jc_rnd_ifd_p := 0;
jc_rnd_icc_p := RND_LENGTH;
k_ifd_p := sum_short (jc_rnd_icc_p , RND_LENGTH);
k_icc_p := sum_short (k_ifd_p, KEYMATERIAL_LENGTH);
keySeed_p := sum_short (k_icc_p, KEYMATERIAL_LENGTH);
keys_p := sum_short (keySeed_p, KEYMATERIAL_LENGTH);
jc_rnd_val ← jc_rnd_var.getSeq;
out_array := cast_short(0);
IF (out_array 6= 0)
THEN ISOException.throwIt (SW_SECURITY_STATUS_NOT_SATISFIED)
ELSE
randomData.generateData (bf, k_icc_p, KEYMATERIAL_LENGTH);
passportUtil.xor (bf, k_ifd_p, bf, k_icc_p, bf, keySeed_p, KEYMATERIAL_LENGTH);
crypto.deriveKey(bf, keySeed_p, KEYMATERIAL_LENGTH, MAC_MODE, keys_p);
macKey_p := keys_p;
keys_p := sum_short (keys_p, KEY_LENGTH);
crypto.deriveKey(bf, keySeed_p, KEYMATERIAL_LENGTH, MAC_MODE, keys_p);
encKey_p := keys_p;
keys_p := sum_short (keys_p, KEY_LENGTH);
END;
220
MACHINE Applet
EXTENDS Object
SEES JByte, JShort, Shareable, Apdu_Properties, Passport_Context,
Passport_JC_FF_Context, InterfaceContext, FileSystem_Context
INCLUDES app.Passport_JC
CONCRETE_VARIABLES perState, volState, selectedFile, rnd, ssc
INVARIANT
perState ∈ JBYTE ∧
volState ∈ seq1(JBYTE) ∧
selectedFile ∈ EF_DG1_INDEX .. SOS_LOG_INDEX ∧
rnd ∈ seq1 (JBYTE) ∧
ssc ∈ seq1 (JBYTE) ∧
perState = app.jc_perState ∧
volState = app.jc_volState ∧
selectedFile = app.jc_selectedFile ∧
rnd = app.jc_rnd ∧
ssc = app.jc_ssc
INITIALISATION
perState := app.jc_perState ||
volState := app.jc_volState ||
selectedFile := app.jc_selectedFile ||
rnd := app.jc_rnd ||
ssc := app.jc_ssc
OPERATIONS
install(bArray, bOffset, bLength) =
PRE bArray ∈ seq(JBYTE) ∧ bOffset ∈ JSHORT ∧ bOffset ≥ 0 ∧
bLength ∈ JBYTE ∧ bLength ≥ 0 ∧ bLength ≤ 127
THEN skip END;
data_out ← processAPDU (apdu_p, cla, ins, p1, p2, lc, data_in, le) =
PRE
apdu_p ∈ APDU ∧ cla ∈ JBYTE ∧ ins ∈ JBYTE ∧ p1 ∈ JBYTE ∧ p2 ∈ JBYTE ∧ lc ∈ JBYTE ∧
data_in ∈ seq(JBYTE) ∧ data_in 6= [] ∧ size (data_in) ≥ 1 ∧ size (data_in) ≤ 127 ∧ le ∈ JBYTE
THEN
SELECT
ins = processSelectFile_INS ∧
app.jc_volState(1) = MUTUAL_AUTHENTICATED ∧
¬ (app.jc_perState = LOCKED) ∧
data_in(1) ∈ EF_DG1_INDEX .. SOS_LOG_INDEX
THEN
app.processSelectFile (apdu_p, data_in) ||
data_out :∈ seq(JBYTE)
WHEN
ins = processReadBinary_INS ∧
app.jc_volState(1) = FILE_SELECTED
THEN
data_out ← app.processReadBinary(apdu_p, boolean_of_byte(p1), data_in)
WHEN
ins = processGetChallenge_INS ∧
app.jc_perState = HAS_MUTUAL_AUTHENTICATION_KEYS ∧ ¬ (app.jc_volState(1) = MUTUAL_AUTHENTICATED)
THEN
data_out ← app.processGetChallenge(apdu_p, boolean_of_byte(p1), data_in )
WHEN
ins = processMutualAuthenticate_INS ∧
(app.jc_volState(1) = CHALLENGED ∧ ¬ (app.jc_volState(1) = MUTUAL_AUTHENTICATED))
THEN
data_out ← app.processMutualAuthenticate (apdu_p, boolean_of_byte(p1))
ELSE
data_out :∈ seq(JBYTE)
END ||
perState := app.jc_perState ||
volState := app.jc_volState ||
selectedFile := app.jc_selectedFile ||
rnd := app.jc_rnd ||
ssc := app.jc_ssc
END;
221
res ← select =
CHOICE res := FALSE
OR res := TRUE
END;
PRE
clientAID ∈ seq(JBYTE) ∧
parameter ∈ JBYTE
THEN interface :∈ JSHORT
END;
res ← selectingApplet =
CHOICE res := FALSE
OR res := TRUE
END
END
222
REFINEMENT JC_Applet_r
REFINES Applet
SEES JByte, JShort, Shareable, Apdu_Properties, Passport_Context,
INCLUDES app.Passport_JC
INVARIANT
perState ∈ JBYTE ∧ volState ∈ seq1(JBYTE) ∧
selectedFile ∈ EF_DG1_INDEX .. SOS_LOG_INDEX ∧ rnd ∈ seq1 (JBYTE) ∧ ssc ∈ seq1 (JBYTE) ∧
perState = app.jc_perState ∧ volState = app.jc_volState ∧
selectedFile = app.jc_selectedFile ∧ rnd = app.jc_rnd ∧ ssc = app.jc_ssc
INITIALISATION
perState := app.jc_perState || volState := app.jc_volState ||
selectedFile := app.jc_selectedFile || rnd := app.jc_rnd || ssc := app.jc_ssc
OPERATIONS
install (bArray, bOffset, bLength) = BEGIN skip END;
process(apdu) = BEGIN skip END;
data_out ← processAPDU (apdu_p, cla, ins, p1, p2, lc, data_in, le) =
VAR protectedAPDU
IN
protectedAPDU := FALSE;
END
223
IMPLEMENTATION JC_Applet_i
REFINES JC_Applet_r
SEES JByte, JShort, ISO7816, Shareable, Classes, Apdu_Properties,
Passport_Context, Passport_JC_FF_Context, InterfaceContext, FileSystem_Context
IMPORTS apdu.Apdu, ISOException.ISOException, Util.Util,
app.Passport_JC
INVARIANT
perState ∈ JBYTE ∧ volState ∈ seq1(JBYTE) ∧
selectedFile ∈ EF_DG1_INDEX .. SOS_LOG_INDEX ∧
rnd ∈ seq1 (JBYTE) ∧ ssc ∈ seq1 (JBYTE) ∧
perState = app.jc_perState ∧ volState = app.jc_volState ∧
selectedFile = app.jc_selectedFile ∧ rnd = app.jc_rnd ∧ ssc = app.jc_ssc
INITIALISATION
perState := PER_STATE_INIT;
volState := [NO_FILE_SELECTED];
selectedFile := EF_DG1_INDEX;
rnd := [0, 0, 0, 0, 0, 0, 0, 0];
ssc := [0, 0, 0, 0, 0, 0, 0, 0]
OPERATIONS
install ( bArray , bOffset , bLength ) = BEGIN skip END;
process(apdu) =
VAR bf, cla, ins, p1, p2, lc, data_in, lr, data_out, apdu_state, res, res2
IN
bf ← apdu.getBuffer;
cla := cast_byte (0); ins := cast_byte (0); p1 := cast_byte (0); p2 := cast_byte (0); lc := cast_byte (0);
IF (size (bf) ≥ 6 ∧
bf(OFFSET_CLA) ≤ MINBYTE ∧ bf(OFFSET_CLA) ≥ MAXBYTE ∧
bf(OFFSET_INS) ≤ MINBYTE ∧ bf(OFFSET_INS) ≥ MAXBYTE ∧
bf(OFFSET_P1) ≤ MINBYTE ∧ bf(OFFSET_P1) ≥ MAXBYTE ∧
bf(OFFSET_P2) ≤ MINBYTE ∧ bf(OFFSET_P2) ≥ MAXBYTE ∧
bf(OFFSET_LC) ≤ MINBYTE ∧ bf(OFFSET_LC) ≥ MAXBYTE )
THEN
cla := bf(OFFSET_CLA); ins := bf(OFFSET_INS);
p1 := bf(OFFSET_P1); p2 := bf(OFFSET_P2); lc := bf(OFFSET_LC)
ELSE
data_in := [0]; data_out := [0]; apdu_state ← apdu.getCurrentState;
IF (lc > 0)
THEN
IF (apdu_state = STATE_INITIAL)
THEN res ← apdu.setIncomingAndReceive;
res2 ← Util.arrayCopyNonAtomic (bf, OFFSET_CDATA, data_in, 0, lc)
END
END;
lr := cast_byte(0);
/∗ ===> Uncomment here to call service operations <===
data_out = processAPDU ( apdu, cla, ins, p1, p2, lc, data_in, le );
lr = data_out.length ;
*/ (...)
IF lr > 0
THEN apdu_state ← apdu.getCurrentState;
IF ins = processSelectFile_INS
THEN
IF vol_st = MUTUAL_AUTHENTICATED ∧ ¬ (per_st = LOCKED) ∧
data_in(1) ∈ EF_DG1_INDEX .. SOS_LOG_INDEX
THEN
app.processSelectFile (apdu_p, data_in)
END
ELSIF ins = processReadBinary_INS
THEN
IF vol_st = FILE_SELECTED
THEN
IF p1 = cast_byte (1) THEN protectedAPDU := TRUE END;
res ← select =
BEGIN res := TRUE END;
deselect =
BEGIN skip END;
register_1 =
BEGIN skip END;
res ← selectingApplet =
BEGIN res := TRUE END;
REFINEMENT Passport_ref
REFINES Passport
SEES
JByte, JShort, JBoolean, ISO7816,
Apdu_Properties, Passport_Context, Passport_JC_FF_Context,
FileSystem_Context, InterfaceContext
INCLUDES
fileSystem.FileSystem,
applet.Applet
INVARIANT
perState = applet.perState ∧
volState = applet.volState ∧
selectedFile = applet.selectedFile ∧
rnd = applet.rnd ∧
ssc = applet.ssc
INITIALISATION skip
OPERATIONS
processSelectFile (fid)=
VAR
apdu_p, cla, ins, p1, p2, lc, data, le, data_out
IN
apdu_p :∈ APDU;
cla := CLA_NUMBER;
ins := processSelectFile_INS;
p1 := cast_byte (0);
p2 := cast_byte (0);
lc := cast_byte (1);
data := seq_of_byte(fid);
le := cast_byte (0);
SELECT
size (data) ≥ 1 ∧ size (data) ≤ 127
THEN
data_out ← applet.processAPDU(apdu, cla, ins, p1, p2, lc, data, cast_byte(8));
file := data_out
END
END;
226
SELECT
size (data) ≥ 1 ∧
size (data) ≤ 127
THEN
data_out ← applet.processAPDU(apdu, cla, ins, p1, p2, lc, data, cast_byte(8));
rnd_val := data_out
END
END;
res ← getPersistentState =
BEGIN
res := applet.perState
END;
res ← getVolatileState =
BEGIN
res := applet.volState
END
END