Le Smart Card (letteralmente carte intelligenti), rappresentano uno di quegli oggetti tecnologici guardati negli ultimi tempi con particolare attenzione a causa dell'impatto che possono e che stanno timidamente cominciando ad avere a livello di massa. Tutti sappiamo cosa sia una carta di credito; una smart card, nella forma è pressoché identica ad una di queste, con la differenza che inglobato nella carta si trova un chip siliceo con in vista dei contatti, generalmente dorati. Naturalmente è questo chip che fa la differenza, poiché apre una serie di nuovi utilizzi impensabili utilizzando le "vecchie" bande magnetiche. Intanto diciamo che esistono fondamentalmente due categorie di smart card: quelle a memoria e quelle a CPU (definite intelligenti). Le prime, prive di CPU, sono in grado di memorizzare dei dati ma non di elaborarli. Le più interessanti sono ovviamente le seconde, che possiedono sia memoria sia CPU, ed è su queste che ci soffermeremo. L'architettura di una smart card prevede quindi della memoria, che può essere: ROM, RAM o EEPROM (memoria a sola lettura cancellabile elettricamente fino a circa 100.000 volte) e in genere i tre tipi di memoria coesistono, abbiamo poi una CPU ed una interfaccia di comunicazione. Per gli sviluppatori comunemente abituati a lavorare su macchine con processori superveloci e quantità enormi di memoria, l'ingresso nel mondo delle smart card può essere piuttosto traumatico; processori a 8-bit, quantità di ram che possono essere inferiori a 1 kb e niente multi-tasking, limitazioni comunque giustificate dal supporto impiegato. Come detto, l'ultima componente di una smart card è l'interfaccia di comunicazione, rappresentata esternamente da piedini dorati. L'utilità di questi ultimi è quella di collegarsi al sistema di lettura. Infatti la card viene inserita all'interno di un lettore (CAD, Card Acceptance Device), e qui i contatti si collegano ai corrispondenti del dispositivo, permettendo lo scambio di dati. Oltre a questo, il CAD fornisce anche l'alimentazione alla card, che ne è sprovvista. I nuovi sviluppi tecnologici stanno portando verso la riduzione dell'utilizzo dei CAD, grazie ad un a tecnica di trasmissione a radiofrequenza integrata nella card, che la pone così in grado di comunicare con il lettore senza che ci sia contatto fisico fra i due. Questo naturalmente richiede un'alimentazione autonoma della card, ma anche questo problema pare ormai superato dai bassi consumi richiesti e dalle micro-pile ad alta resa. Lo scambio di dati fra la card e il lettore avviene mediante l'utilizzo di pacchetti di dati, definiti APDU (Application Protocol Data Unit). Il tipo di comunicazione che si instaura è definito comunicazione reattiva in quanto non è mai la card ad iniziare la conversazione, ma reagisce solo ad un inizio di conversazione da parte del lettore. Dopo questa fase si va avanti in modalità comando-risposta, con una delle due parti che invia un comando e l'altra che restituisce l'esito di quest'ultimo.Non a caso ci siamo soffermati un po’ sulle smart card, in quanto capire i meccanismi di queste significa automaticamente capire quelli delle Java Card.

Java Card Specifications

Le Java Card rappresentano la tecnologia delle smart card associata alla filosofia Java. In quest'ottica si tenta di sfruttare tutte le caratteristiche della piattaforma Java all'interno di un sistema embedded quale è una smart card, e se ci pensiamo un attimo la cosa non può meravigliare, visto che Java in origine era stato concepito come linguaggio per sistemi embedded. Ma in che cosa una Java card può essere considerata superiore ad una semplice smart card?Intanto una Java card permette la coesistenza di più applicazioni (applet) sulla stessa carta, autonome e protette dall'architettura "sand-box" Java. Poi la mai abbastanza citata indipendenza dalla piattaforma. Questo permette di poter implementare una certa applicazione su carte costruite da diversi produttori senza necessità di modifiche. Poi tutti i vantaggi offerti dalla architettura a oggetti di Java, molto utile in fase di sviluppo. Una cosa da non dimenticare è che la Java Card API è ISO7816 compatibile, quindi risponde a standard di mercato ben precisi. In genere su una Java card coesistono i tre tipi di memoria citati precedentemente. Un certo numero di produttori ha adottato il seguente schema: 24 K di ROM, 16 K di EEPROM, 512/1024 bytes di RAM. La Ram è utilizzata solo per i dati temporanei, mentre nella EEPROM ci sono gli applet e alcune estensioni proprietarie dei vari produttori. La struttura software di una card comprende i livelli descritti di seguito.

Nella ROM troviamo il JCRE (Java Card Runtime Environment), che comprende la Java Card Virtual Machine, i metodi nativi I/O, allocazione della memoria, la API per l'uso del JCRE da parte di un applet e il Framework, l'insieme delle classi "core" ,più le estensioni specifiche del produttore. La Java Card Virtual Machine presenta alcune rilevanti differenze rispetto alla VM classica, infatti la possiamo considerare come divisa in due parti ben distinte . La prima parte si trova fisicamente al di fuori della card stessa, nel sistema di lettura, ed e' il Java Card Converter, che si occupa di convertire una classe .class in un file .cap . La parte di VM interna alla card è il Java Card Runtime Environment, che si occupa di eseguire il file .cap a runtime. Non e' supportato il caricamento dinamico delle classi a causa delle risorse limitate a disposizione , ma anche e soprattutto per ragioni di sicurezza; infatti quasi tutti i comportamenti dinamici del linguaggio sono proibiti, in quanto forieri di possibili buchi di sicurezza.Tra le altre limitazioni imposte abbiamo l'assenza del supporto dei thread e del garbage-collecting, sempre per mancanza di risorse. Sono invece presenti come distribuzione standard alcune classi specifiche per l'ambiente, come ad esempio la classe PIN, per la gestione dei codici di riconoscimento, ISO per conformità allo standard ISO 7816 e APDU. In più abbiamo estensioni per la criptografia, e la gestione dei file system.

Embedded System

I campi di applicazione delle Java card sono potenzialmente tutti quelli in cui ci sia un sistema embedded. La possibilità di potersi comportare contemporaneamente da memory-card e da intelligent-card, ne favorisce l'uso sia come portatrice che come elaboratrice di informazioni. Ad esempio potrebbe contenere i dati anagrafici del possessore, con tutti i codici dei documenti ad esso associati, dalla patente al codice fiscale. Mi è capitato di vedere qualche tempo fa un prototipo di questo tipo, in cui si simulava un posto di blocco da parte delle forze dell'ordine con in dotazione un lettore di Java card. Il possessore inseriva la card e digitava il suo codice. Questo consentiva l'esecuzione di un applet presente sulla carta che portava alla comunicazione dei dati del possessore al lettore. Da qui i dati passavano via modem ( in quel caso satellitare) verso una centrale operativa in grado di controllare i dati stessi e restituire la risposta agli agenti sul posto. Quell'unica card conteneva tutti i dati del possessore, comprese le pendenze penali. La possibilità di contenere più applet, consente di far coesistere diverse funzionalità su una sola carta per cui, ad esempio la stessa carta citata prima potrebbe essere portata in banca all'apertura di un nuovo conto, e la banca provvederebbe a caricarvi un proprio applet per l'utilizzo della carta come bancomat o carta di credito. In quest'ottica ci si è subito posti il problema della sicurezza , dato che i vari applet possono elaborare dati privati, ma non dimentichiamo che nella card c'è una Virtual Machine, e che l'accesso ad un applet qualsiasi presente sulla card può essere vincolato al ricevimento di un codice apposito che ne autorizzi l'uso. Quindi ogni entità che possegga un applet su una card del cliente è tutelata dal proprio codice di accesso all'applet stesso. Naturalmente la sicurezza assoluta non esiste, ma il sistema sembra dare un certo grado di garanzia. In ogni caso si stanno facendo grandi sforzi per eliminare i potenziali buchi di sicurezza che il mezzo presenta, ad esempio la possibilità di criptare il codice stesso presente sulla card. Supporto per la criptografia è offerto da due package di estensione: javacardx.crypto e javacardx.cryptoEnc , che però non facendo parte della distribuzione core della API , possono non essere presenti su alcune card.

Primi passi

Vedremo ora un piccolo esempio di utilizzo della Java Card API. Analizzeremo un applet in grado semplicemente di leggere una stringa dalla card o di scriverne una. L'esempio e' abbastanza banale, ma ci permetterà di vedere in dettaglio lo scheletro di un applet per Java Card. Partendo da questo esempio è infatti possibile scrivere qualsiasi tipo di applet per gli usi più disparati.Intanto citiamo alcune peculiarità; i tipi primitivi disponibili sono: short, boolean e byte. Va diffondendosi nelle card a 32-bit l'introduzione anche di int. Gli array sono supportati ma solo quelli monodimensionali. Cosa mol,to importante, sono supportati tutti i costrutti per le eccezioni (try,catch,finally) in modo da poter testare a fondo un applet prima del suo rilascio. Ma passiamo al codice che trovate nel Listato 1.

Listato
1 Applet che legge e scrive una stringa da e su una Java Card
//
// Esempio
di applet in grado di leggere e scrivere
// una
stringa da e su una Java Card.
//
// l'oggetto
Applet appartiene al package javacard.framework
import
javacard.framework.*;
public
class Esempio extends Applet {
// definiamo
la classe in formato ISO
final
static byte Esempio_CLA=(byte)0x00;
// stessa
cosa per i metodi esposti
final
static byte LEGGI =(byte)0x10;
final
static byte SCRIVI=(byte)0x20;
byte dataBuffer[];
byte cardBuffer[];
// costruttore
private
Esempio () {
cardBuffer=new
byte[512];
register();
{
// ultimo
metodo richiamato dalla JCRE in fase
// di
installazione dell'applet
public
static void install(APDU apdu){
new Esempio();
}
// metodo
chiamato dalla JCRE per indicare
// che
questo applet è stato scelto
public
boolean select(){
return
true;
}
// una
volta installato l'applet, la JCRE
// invia
a questo metodo gli APDU in ingresso
public
void process(APDU apdu){
dataBuffer=apdu.getBuffer();
if(dataBuffer[ISO.OFFSET_CLA]!=Esempio_CLA)
ISOException.throwIt
(ISO.SW_CLA_NOT_SUPPORTED);
switch
(dataBuffer[ISO.OFFSET_INS] {
case SCRIVI:
ScriviStringa(apdu);
return;
case LEGGI:
LeggiStringa(apdu);
return;
default:
ISOException.throwIt(ISO.SW_INS_NOT_SUPPORTED);
}
private
void ScriviStringa(APDU apdu){
dataBuffer=apdu.getBuffer();
byte lunghezza=(byte)(apdu.setIncomingAndReceive());
byte indice;
cardBuffer[0]=lunghezza;
for (indice=0;indice<lunghezza;indice++)
cardBuffer[indice+1]=dataBuffer[ISO.OFFSET_CDATA
+indice];
return;
}
private
void LeggiStringa(APDU apdu){
dataBuffer=apdu.getBuffer();
byte numeroBytes=dataBuffer[ISO.OFFSET_LC];
if (numeroBytes==0){
ISOException.throwIt((short)(0x5000
+ cardBuffer[0]));
}
apdu.setOutgoing();
apdu.setOutgoingLength(numeroBytes);
byte indice;
for (indice=0;indice<=numeroBytes;indice++)
dataBuffer[indice]=cardBuffer[indice+1];
apdu.sendBytes((short)0,(short)numeroBytes);
return;
}
}

Nella implementazione della nostra classe, definiamo delle costanti rappresentanti la classe e i metodi esposti come byte. Questa notazione è quella richiesta dallo standard ISO 7816-4. Il motivo di questa notazione sta nella modalità di comunicazione dell'applet. Infatti, ricordiamo che lo scambio di dati avviene tramite APDU, costituiti da ben definite sequenze di byte. Esistono due tipi di APDU, aventi diversa struttura : APDU di comando e APDU di risposta. La struttura dei primi è la seguente:

CLA -
INS - P1 - P2 - Lc - Data - Le

con

CLA
- indica la classe
INS -
indica l'istruzione
P1,P2
- sono parametri addizionali
Lc - lunghezza
dei dati del comando
Data -
i dati veri e propri
Le - lunghezza
attesa della risposta

Mentre il formato di un APDU di risposta è:

Data
- SW1 - SW2

Con

Data
- dati effettivi di risposta
SW1 -
primo byte di una word di stato
SW2 -
secondo byte di una word di stato

SW1 e SW2 possono essere utilizzati per proprie necessità, dato che possono essere inviati al client tramite eccezioni, come vedremo nel metodo LeggiStringa.Questa panoramica sugli APDU era necessaria per comprendere alcuni passaggi dell'applet, come vedremo fra poco. Andiamo avanti. Definiamo due array di byte , dataBuffer e cardBuffer che conterranno i dati letti o scritti. Nel costruttore della classe, prima allochiamo uno degli array, che quindi conterrà i dati presenti nella memoria della card, e poi chiamiamo il metodo register(), che appunto registra l'applet nella JCRE. I tre metodi successivi (install, select e process) sono sempre presenti in un applet . Install è chiamato dalla JCRE come ultimo passo nell'installazione dell'applet stesso, mentre select è chiamato dalla JCRE quando l'applet viene selezionato. Infatti nella card possono essere presenti più applet , ma solo uno alla volta può essere selezionato. E' in questo metodo che sarebbe bene inserire le inizializzazioni necessarie per processare gli APDU in seguito. Di questo si occupa il metodo process, il quale viene invocato al momento della ricezione di un APDU, ed in realtà rappresenta il cuore dell'applet. Proprio per questo è bene analizzarlo in dettaglio. Dopo aver memorizzato il contenuto dell'APDU in un array di byte, controlla che l'APDU sia indirizzato alla classe giusta. E qui torna utile la spiegazione data prima sulla struttura degli APDU; ISO.OFFSETCLA indica la posizione del byte contenente l' identificativo della classe bersaglio dell'APDU,così come ISO.OFFSETINS indica la posizione del byte identificativo dell'istruzione inviata. In questo modo il metodo riesce a sapere quale metodo della classe deve essere invocato, e agisce di conseguenza. Non è proprio la massima eleganza, ma ricordiamo l'ambiente ristretto in cui si opera. In realtà , lo scheletro è tutto qui . Gli ultimi due metodi infatti sono quelli definiti dalla classe, che si occupano della lettura e scrittura di una stringa. In particolare , nel metodo LeggiStringa si è dovuti ricorrere ad un "trucco", in quanto un client che richieda una stringa memorizzata sulla card, non è in grado di sapere a priori quanto questa sia lunga. Per ovviare a questo, il client richiede una stringa di lunghezza zero e la card tratta questa situazione come un'eccezione, rispondendo con una word di stato pari a 0x50NN ad evidenziare la non corretta indicazione della lunghezza stringa richiesta, dove NN rappresenta l'effettiva lunghezza della stringa da richiedere. A questo punto il client è in grado di riformulare il comando, indicando questa volta la lunghezza giusta. L'esempio è volutamente semplice, ma ben si presta ad essere esteso ed ampliato. La documentazione messa a disposizione dalla Sun è abbastanza chiara ed esaustiva, e sviluppare applet risulta un procedimento di rapido apprendimento. Al riguardo è consigliabile scaricare dal sito www.javasoft.com la documentazione presente al solito in vari formati, che rappresenta veramente tutto ciò che serve sapere per poter sviluppare su piattaforma Java Card.

Conclusioni

Le potenzialità insite nella tecnologia in esame sono indubitabilmente notevoli. Sicuramente l'idea di concentrare su un'unica carta tutti i propri documenti rappresenterebbe una semplificazione anche burocratica non indifferente in quanto, la presenza di tutti i propri dati in formato elettronico comodamente accessibile eviterebbe ad esempio la necessità di compilazione di numerose richieste a livello di amministrazione pubblica. Naturalmente l'utilizzo della card è giustificato solo dall'abitudine che ormai abbiamo acquisito all'uso di un tal tipo di supporto, ma la tecnologia sta tutta su chip, per cui è plausibile pensare a qualsiasi altro tipo di "vettore". Nel resoconto di un convegno tenutosi di recente a San Francisco avente come argomento proprio Java Card, qualcuno ha addirittura vagheggiato l'ipotesi di impiantare il chip a livello cutaneo. Sorvolando sul buon gusto della cosa, sembra comunque che si avvicinino a ritmi sempre più incalzanti tutte quelle immagini tecnologiche che fino ad ora abbiamo visto solo al cinema. La tecnologia però deve sempre essere al servizio dell'uomo, e se delle Java Card verrà fatto un utilizzo corretto, sicuramente questa regola sarà stata rispettata.