• Sonuç bulunamadı

3. BULGULAR YORUMLAR

3.10 Onuncu Alt Probleme İlişkin Bulgular ve Yorumlar

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.

Conforme discutido na seção anterior, o desenvolvimento da aplicação do lado cartão segue todo o processo de especificação e refinamento em B, sendo o applet gerado a partir do último nível de refinamento, denominado de implementação. No caso da geração de código da API para o lado host, na versão atual, decidiu-se gerá-lo apenas com base na máquina de especifi- cação inicial, em um processo totalmente automatizado. Isso deve-se ao fato das informações contidas na assinatura de cada operação B que especifica um serviço correspondente no cartão serem suficientes para a geração dos componentes de auxílio ao cliente. Dessa forma, é possível obter informações sobre cada parâmetro que será enviado, assim como os valores de retorno da operação.

Assim como apresentado no capítulo 2, para o desenvolvimento da aplicação host existem APIsque oferecem todos os recursos necessários para se estabelecer a comunicação com o car- tão e acessar seus serviços. Neste trabalho, é possível a geração de classes de comunicação com o cartão para as APIs Smart Card I/O e RMI Client. Essa última é uma API bastante simples, parte da especificação Java Card padrão, exclusiva para comunicação com applets RMI. Na versão inicial do trabalho, também encontrava-se implementada a API OpenCard Framework. No entanto, em virtude da sua descontinuidade, ela não foi incluída na versão atual do trabalho. Ressalta-se que o desenvolvedor pode facilmente fornecer a implementação para uma nova API de sua preferência, desde que implemente duas interfaces detalhadas a seguir nesta seção.

Cumpre destacar que o objetivo deste ramo do desenvolvimento do método é a geração de um conjunto de classes (fig. 4.13) que possibilitam a comunicação de forma transparente com a aplicação cartão. Sendo assim, livra-se o usuário da tarefa tediosa e propensa a erros de manipu- lar os detalhes de baixo-nível do sistema smart card. Para tanto, esses componentes gerenciam a conexão com os serviços da aplicação cartão, bem como a codificação e decodificação das informações enviadas e recebidas pelo applet. Dessa forma, o usuário da API é responsável apenas pela especificação dos aspectos funcionais da aplicação, tornando o desenvolvimento mais ágil e produtivo.

É 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

Figura 4.13: Diagrama de classes UML descrevendo os componentes da API para a aplicação cliente.

cada nova aplicação, denominadas de AppCommunication e AppProxy. É importante observar que os demais componentes podem ser reutilizados em diversos projetos, sem a necessidade que sejam gerados novamente a cada execução da aplicação de geração da API. Esse aprimoramento foi feito durante o trabalho da tese, após uma nova modelagem das classes da abordagem inicial desenvolvida por Moraes [Mor07].

Ressalta-se que a classe AppCommunication é diretamente acessada pela aplicação host e contém métodos Java de alto nível para requisitar cada serviço do applet. No caso de applets APDU, as chamadas aos serviços são encaminhadas para a classe AppProxy, que é a responsável por codificar os dados recebidos em um pacote no formato do comando APDU e enviá-lo ao applet. O componente AppProxy também decodifica a resposta retornada, enviando-a de volta à classe AppCommunication. Observa-se que esse componente não é necessário para a geração da API para o applet RMI, uma vez que, nesse caso, a comunicação é estabelecida em um nível mais alto que aquele para a aplicação APDU.

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-

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.

4.5.1 Exemplo de classes geradas

Nesta seção apresentam-se as classes AppCommunication e AppProxy geradas para a má- quina Transport, cujo código Java Card correspondente foi detalhado na seção 2.3. As opera- ções da especificação Transport (figura 4.14) exemplificam o envio de um valor short para o cartão (addCredit), o envio de um comando sem parâmetros e sem retorno, no caso o débito de uma unidade de crédito (debit), e, por fim, a recepção de um valor short (getBalance). Em addCredit, adicionou-se o parâmetro (ct) contendo o tipo do cartão, apenas para demonstrar o envio de mais de um parâmetro.

MACHINE Transport

SEES Transport_Constants, JShort VARIABLES balance, card_type

INVARIANT balance∈ JSHORT ∧ balance ≥ 0 ∧

card_type∈ CARD_TYPES ∧ (card_type = gratuitous_card =⇒ balance = 0) INITIALISATION balance:= 0 || card_type :∈ CARD_TYPES

OPERATIONS addCredit (cr, ct) =

PRE cr∈ JSHORT ∧ ct ∈ JSHORT ∧ cr> 0 ∧ card_type 6= gratuitous_card ∧

sum_short(balance, cr) ≥ 0 ∧ sum_short(balance, cr) ≤ MAXSHORT THEN balance:= sum_short(balance, cr)

END ; debit =

PRE card_type6= gratuitous_card ∧ subt_short(balance, 1) ≥ 0 THEN balance:= subt_short(balance, 1)

END;

res← getBalance = BEGIN res := balance END END

Figura 4.14: Especificação abstrata Transport.

A figura 4.15 exibe a classe TransportCommunication, criada de forma automatizada com o auxílio da ferramenta de geração da API (seção 4.6.1), a partir da assinatura das operações da máquina Transport. Perceba que ela fornece, à aplicação que irá utilizar a API, uma interface Java de alto nível, encapsulando todos os aspectos de conversão de dados e da comunicação com o cartão nos demais componentes.

Os valores recebidos da classe TransportCommunication são tratados pela classe Trans- portProxy(figuras 4.16 e 4.17), tendo em vista enviá-los ao cartão através da implementação da

p u b l i c c l a s s T r a n s p o r t C o m m u n i c a t i o n { by te [ ] a p p l e t A I D = n u l l ; T r a n s p o r t P r o x y c a r d P r o x y = n u l l ; 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 ( by te [ ] a i d ) throws E x c e p t i o n { a p p l e t A I D = a i d ; 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 ) ; } p u b l i c voi d a d d C r e d i t ( s h o r t cr , s h o r t c t ) { c a r d P r o x y . a d d C r e d i t ( cr , c t ) ; } p u b l i c voi d d e b i t ( ) { c a r d P r o x y . d e b i t ( ) ; } p u b l i c s h o r t g e t B a l a n c e ( ) { r e t u r n c a r d P r o x y . g e t B a l a n c e ( ) ; } }

Figura 4.15: Classe TransportCommunication.

interface I_APDUComm para uma API específica. No caso do exemplo, implementou-se a API smart card I/O(apdu = new SmartCardIOAPDUComm(aid)).

Na classe proxy, todo parâmetro de tipo primitivo é convertido em um valor byte ou em um arrayde bytes, através das funções de conversão da classe HostUtil. Como exemplo, tem-se o método addCredit, que necessita enviar dois valores short ao cartão. O primeiro, a quantidade de créditos (cr), é convertido em dois bytes, armazenados nas variáveis locais p1 e p2 (linhas 11 e 13). Por outro lado, o tipo do cartão (ct) é convertido em um array de byte (2 bytes) e armazenado na variável data. O efetivo envio dos parâmetros é feito através de um dos métodos sendCommandda interface I_APDUComm (linha 17). No caso, deve-se informar a classe de instrução (APPLET_CLA), o código do serviço requisitado (addCredit_INS) e os parâmetros que serão enviados em p1, p2 e no campo data do comando apdu.

1 p u b l i c c l a s s T r a n s p o r t P r o x y {

2 s t a t i c f i n a l b yt e APPLET_CLA = ( by te ) 0 x80 ;

3 s t a t i c f i n a l b yt e a d d C r e d i t _ I N S = ( by te ) 0 x10 ; ( . . . )

4 p r i v a t e I_APDUComm apdu ;

5

6 p u b l i c T r a n s p o r t P r o x y ( by te [ ] a i d ) { apdu = new SmartCardIOAPDUComm ( a i d ) ; } 7 p u b l i c vo id a d d C r e d i t ( s h o r t cr , s h o r t c t ) { 8 by te [ ] d a t a = new by te [ 1 2 7 ] ; 9 i n t i n d e x = 0 ; 10 11 by te [ ] sh = H o s t U t i l . s h o r t T o B y t e A r r a y ( c r ) ; 12 by te p1 = ( by te ) sh [ 0 ] ; 13 by te p2 = ( by te ) sh [ 1 ] ; 14 15 H o s t U t i l . s h o r t T o B y t e A r r a y ( d a t a , c t , i n d e x ) ; 16 i n d e x += 2 ;

17 apdu . sendCommand ( APPLET_CLA , a d d C r e d i t _ I N S , p1 , p2 , d a t a ) ;

18 } ( . . . )

Figura 4.16: Classe TransportProxy - operação addCredit.

É importante ressaltar que o procedimento de envio de informações nos campos p1 e p2 é comumente adotado em um desenvolvimento Java Card, tendo em vista otimizar o espaço de armazenamento. Nessa abordagem, sempre que, nos primeiros parâmetros a serem enviados, há um ou dois valores de até dois bytes (byte, boolean ou short), eles serão inseridos em p1, p2 ou

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 p u b l i c voi d 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 p u b l i c s h o r t g e t B a l a n c e ( ) {

5 by te [ ] r e s = apdu . sendCommandAndGetResponse ( APPLET_CLA ,

6 g e t B a l a n c e _ I N S , ( b y t e ) 0 , ( b y t e ) 0 , 2 ) ;

7

8 r e t u r n H o s t U t i l . b y t e A r r a y T o S h o r t ( r e s ) ;

9 }

10 }

Figura 4.17: Classe TransportProxy - operações debit e getBalance.