Introduzione

Ormai è una constatazione: il digitale con tutte le sue innovazioni sta penetrando in tutte le nostre vite e i nostri costumi. Provate solo a pensare a quante volte in un giorno utilizziamo un telefonino, il bancomat, la carta di credito, compact disc, e questo senza coinvolgere dispositivi prettamente informatici. Sotto la spinta di Internet, di Java (e di grandi compagnie quali Oracle, Sun) c'è il tentativo di globalizzare, coinvolgere e far dialogare tutti questi dispositivi digitali. In un contesto del genere si può intuire qual è uno dei grandi problemi connessi: la sicurezza.

Per ottenerla ciascun piccolo dispositivo deve possedere dei vincoli di accesso, magari una password, costringendo l'utente a impazzire di fronte al crescente numero di chiavi segrete. La smartcard e il JavaRing, fra le molte altre cose che sono in grado di fare, possono risolvere il problema memorizzando al proprio interno, in maniera inattaccabile, tutte le chiavi di accesso possibili.

Ma andiamo più nel dettaglio del JavaRing focalizzandoci proprio sulle sue possibilità di fare il login per un accesso a un qualunque dispositivo.

Il JavaRing è un singolo chip con un coprocessore matematico a 1024 bit e un clock; il tutto inserito in un involucro d'acciaio. Questo chip è dotato di una ROM, una RAM non volatile di circa 6K (dunque in grado di memorizzare dei dati) e tutte le API e JRE necessarie a eseguire applet Java al proprio interno. A differenza degli strati software utilizzati dalle vecchie smartcard (C/C++), il JavaRing utilizza Java per una maggiore portabilità, ideale anche per strutture e applicativi distribuiti tipici di Internet.

Da notare comunque che anche grosse compagnie produttrici di smartcard, come la Bull, si stanno orientando verso la tecnologia Java.

Attraverso il contatto elettrico rappresentato dal rivestimento, l'iButton comunica con l'esterno (PC, web kiosk o altro) mediante un cavo seriale detto "BlueDot". Si può intuire come la possibilità di memorizzare più applet consenta la coesistenza di programmi che svolgono diverse funzioni all'interno dello stesso piccolo dispositivo.

Concludendo l'introduzione, si possono così riassumere i quattro componenti fondamentali per ciascuna applicazione con l'iButton:

1. iButton; 2. un host system: questo può essere un PC, un laptop o un palmare; 3. un dispositivo reader/writer per comunicare con l'iButton; 4. uno strato software per interfacciare il JavaRing ai computer e produrre le informazioni desiderate nel formato desiderato.

Scopo dell'applicazione

Strutturalmente il JavaRing o iButton è stato costruito pensando di mantenere alta la riservatezza dei dati memorizzati al proprio interno e di poter velocemente risalire all'identità del possessore del Ring.

I procedimenti più significativi adottati in tal senso sono:

1. il rivestimento di acciaio per avere solidità, durata rispetto all'usura (è testato per 10 anni di utilizzo) e inattaccabilità rispetto a un tentativo esterno di appropriazione dei dati; 2. un numero di matricola unico per ciascun iButton costruito: l'ID ROM NUMBER; 3. l'uso del PIN (Personal Identification Number): in pratica, il dispositivo può essere reso inaccessibile impostando il commonPIN oppure bloccandolo completamente tramite un lock.

L'uso di tutti questi livelli di sicurezza, impostabili prima di creare una qualsiasi applicazione, consente accessi selezionati a seconda dell'utente.

In pratica, impostato il PIN, per accedere alle chiavi di accesso memorizzate bisogna sapere qualcosa (PIN) e portare qualcosa (RING).

Questo consente all'utente di utilizzare le chiavi di accesso in maniera trasparente, delegando all'applicativo la gestione di tutte le eventuali password che usa nella vita quotidiana.

Avendo come linea guida questa possibilità ci si può sbizzarrire nel trovare delle applicazioni che coinvolgano un qualunque tipo di accesso; addirittura si può pensare l'iButton come chiave per una porta o per l'accensione dell'automobile (da notare che applicazioni di questo genere esistono già).

Una volta che il Ring ha scaricato le chiavi sull'host, quest'ultimo, con un database interno o simile, verifica le password e consente l'accesso. Si potrebbero anche ipotizzare delle applicazioni che, utilizzando le chiavi dal JavaRing, si connettono a host remoti o a server protetti, il tutto, e lo ripeto, in maniera trasparente all'utente.

Codice

Ogni applicazione con il JavaRing deve almeno avere due parti: la prima, che gestisce i dati, nel Ring; la seconda, che interagisce con l'utente, sull'host system.

A seconda dell'aumento della complessità logica degli applicativi, la strutturazione delle classi e degli oggetti può essere più articolata, ma queste due parti devono sempre comparire nell'applicazione.

Ecco un esempio di applicazione in cui si leggono dal Ring due chiavi (login e password), la data dell'ultimo login e vi si memorizza la data attuale.

In aggiunta a tutto questo l'applet può memorizzare nuove login e password prima di leggerle. Per motivi di brevità non inserirò tutto il codice.

In generale la comunicazione tra host e Ring si sviluppa con il protocollo APDU: tramite una serie di pacchetti, nei cui header si specificano dei parametri propri per quei dati, l'applet raccoglie e interpreta le istruzioni come azioni da compiere. Tramite lo stesso protocollo il Ring rispedisce i risultati.

Applet inserito nel JavaRing

Gli applet dentro i Ring non iniziano con init(), ma in questo caso l'inizializzazione è divisa in due fasi.

1. Installazione

// questo è il costruttore
loginApp() {
  register();
  data_log_in = new byte[0];
  login = new byte[0];
  password = new byte[0];
}
public static void install(APDU apdu) {
  new loginApp();
}

2. Attivazione durante la comunicazione

public void process(APDU apdu) throws ISOException {
  [..]
  switch (buffer[ISO.OFFSET_INS]) {
    default:
      // Don't know what to do with this instruction
      throw new ISOException(ISO.SW_INS_NOT_SUPPORTED);
    case LAST_LOG_IN_STORE:
      loginAppStore(apdu);
      break;
    case LAST_LOG_IN_RETRIEVE:
      loginAppRetrieve(apdu);
      break;
    case LOG_PASWD_STORE:
      passwdAppStore(apdu);
      break;
    case LOG_PASWD_RETRIEVE:
      passwdAppRetrieve(apdu);
      break;
  }
}

Ciascun case attiva un metodo che espleta le richieste. Valutiamo ad esempio la lettura del login con loginAppRetrieve(apdu):

protected void loginAppRetrieve(APDU apdu) {
  temp = new byte[6 + data_log_in.length];
  int i = 0;
  int j = 0;
  for (i = 0; i < data_log_in.length; i++) {
    temp[j] = data_log_in[i];
    j++;
  }
  if (temp != null) {
    // questa è la normale sequenza di ritorno dei pacchetti
    // imposta il modo per spedire i dati
    apdu.setOutgoing();
    // imposta la lunghezza
    apdu.setOutgoingLength((short) temp.length);
    // imposta i dati, indice di inizio e offset finale
    apdu.sendBytesLong(temp, (short) 0, (short) temp.length);
  }
}

Nota: queste sono le variabili (sono uguali anche sull'host):

final static byte LOGIN_CLA = (byte) 0x80;
final static byte LAST_LOG_IN_STORE = (byte) 0x10;
final static byte LAST_LOG_IN_RETRIEVE = (byte) 0x20;
final static byte LOG_PASWD_STORE = (byte) 0x30;
final static byte LOG_PASWD_RETRIEVE = (byte) 0x40;
final static byte SELECT_LOGIN_CLA = 0x01;
final static byte SELECT_LOGIN_INS = (byte) 0xA5;
// parametri per gli inserimenti
final static byte BC_P1_SET_LENGTH = 0x01;
final static byte BC_P1_NEXT_PACKET = 0x02;
final static byte BC_P1_LAST_PACKET = 0x03;
final static short SW_BAD_INS_SEQUENCE = (short) 0x9101;
byte[] data_log_in;
byte[] login;
byte[] password;
short offset;
int totalLength;
byte[] temp;

Applet (o applicazione) caricato da un browser

Attraverso vari tipi di interfacce e strati software, sia open source sia specifici del costruttore dell'iButton, l'applet nel browser "sente" il Ring, nel senso che si accorge se il JavaRing è collegato o meno alla seriale, permettendo all'utente di interagire con esso naturalmente anche attraverso l'implementazione di una GUI.

Vediamo quali sono i punti fondamentali: per prima cosa l'aspetto legato alle classi che "ascoltano".

// sente che l'anello è inserito
public void cardInserted(CardTerminalEvent event) {
  System.out.println("Java iButton inserted");
  blueDot = event.getSlot();
  channel = blueDot.getCardTerminal().openSlotChannel(blueDot);
  terminal = (iButtonCardTerminal) channel.getCardTerminal();
  iButtonInserted = true;
  // qui si attuano le chiamate per il Ring
  [..]
}
// sente che l'anello è stato rimosso
public void cardRemoved(CardTerminalEvent event) {
  System.out.println("Java iButton removed");
  blueDot = event.getSlot();
  if (blueDot.getSlotID() != 0)
    return;
  iButtonInserted = false;
  blueDot = null;
  terminal = null;
}

Registrazione

// registra l'anello e imposta le seriali che utilizza
protected void startPolling(String nativeDevString) {
  try {
    SmartCard.start();
    CardTerminalRegistry registry = CardTerminalRegistry.getRegistry();
    registry.addCTListener(this);
  } catch (Exception e) {
    e.printStackTrace();
  }
}

Lettura

public void read() throws loginException {
  byte[] buffer = new byte[0];
  try {
    // costruisce il CommandAPDU, cioè il contenitore per dati e parametri
    CommandAPDU businessCardAPDU = new CommandAPDU(
      (byte) LOGIN_CLA,
      (byte) LAST_LOG_IN_RETRIEVE,
      (byte) 0,
      (byte) 0,
      buffer,
      (byte) 0
    );
    // cattura il ResponseAPDU, l'oggetto al cui interno vi sono i dati letti
    ResponseAPDU response = channel.sendAPDU(businessCardAPDU);
    // ba[] rappresenta i dati
    byte[] ba = response.data();
    [...]
  } catch (CardTerminalException e) {
    System.out.println("non riesco a comunicare con la card" + e.statusWord());
  }
}

Alcune considerazioni sugli strati software utilizzati

Come si può valutare dagli import immessi nel codice Java implementato, tutte le API provengono da tre pacchetti:

1. jibapi: questo pacchetto è quello fornitomi dal costruttore del Ring; ha delle funzioni specifiche che permettono la comunicazione con il JavaRing, quali l'inizializzazione del PIN o l'azionamento del garbage collector per le classi Java. La Dallas Semiconductor fornisce anche, per un maggior controllo del dispositivo, un'interfaccia GUI apduSender che utilizza direttamente queste API. 2. opencard framework: è principalmente preposto alla comunicazione fra l'ambiente esterno e il JavaRing attraverso lo standard APDU (Application Protocol Data Unit). Nonostante l'alto livello di astrazione delle classi del pacchetto OpenCard Framework, il formato dei pacchetti durante la comunicazione è un array di byte, cosa che rende più ardua la lettura e scrittura nel Ring rispetto ai più comodi InputStream. La scelta del formato dei pacchetti è obbligata dalla memoria disponibile nel Ring, ad oggi ancora abbastanza limitata. 3. javacard2.0 framework: è il motore che fa "girare" gli applet all'interno del Ring e fa anch'esso parte di uno standard verificato da Sun. Eccettuato il primo pacchetto, gli altri due sono standard utilizzati anche per lo sviluppo delle smartcard (che utilizzano Java, naturalmente) e questo rende eventualmente abbastanza agevole il passaggio tra questo dispositivo e il JavaRing e viceversa. L'ultima considerazione riguarda l'inserimento dell'applet nel Ring (ma la stessa cosa avviene per le smartcard): eccone uno schema.

In pratica i file .class vengono "macinati" da un opportuno convertitore che li formatta in maniera accettabile per la JVM del Ring. Nel caso dell'iButton tale convertitore è dato dal programma Java BuildJiBlet.