SmartCard: conservare certificati e chiavi SSH
Dopo essere diventato notaio per StartSSL, mi sono reso conto di quanto sia scomodo collegarsi da un solo browser, e quanto possa essere insicuro installare il proprio client certificate su ogni browser che si intende usare. Mi sono così deciso a cercare una smartcard in grado di gestire internamente l'autenticazione, comoda da trasportare e sicura.
La scelta è ricaduta sulla MyEID di Aventra (sotto Smartcard), economica (meno di 10€ cad. se se ne prendono almeno 5) e versatile (80kB di memoria, supporta fino a 14 PIN!).
Dopo alcuni giorni di trepidante attesa, stamattina mi è arrivato il pacchetto. Ovviamente mi sono fiondato immediatamente a vedere come utilizzare le card.
Ero quasi completamente a digiuno del funzionamento del toolkit per PKCS15 (ho però studiato sia la crittografia a chiave pubblica -- per OpenAlarm -- che il funzionamento a basso livello delle card -- per un progetto collaterale mirato al "riciclaggio" di vecchie SIM -- ), quindi ci ho messo un po' a capire alcune cose che, effettivamente, sono logiche:
- I vari PIN sono indipendenti dagli altri oggetti memorizzati
- Ogni oggetto può essere "libero" o protetto da un PIN
- C'è un PIN che è riservato all'amministratore e non può essere usato per proteggere gli accessi agli oggetti
Nel seguito, copierò molto da OpenSC.org, a cui rimando per eventuali chiarimenti.
Per iniziare, è necessario disporre di un lettore compatibile PC/SC e supportato da OpenSC. Darò per scontata l'installazione dei pacchetti necessari (se ricordo bene, almeno libpcsc-lite, ccid, opensc-0.12.0 e libopensc3 -- con opensc-0.11.3 non sono riuscito a far funzionare le MyEID!).
Per verificare che il lettore sia supportato, si può usare :
$ pkcs11-tool -L Available slots: Slot 0 (0xffffffff): Virtual hotplug slot (empty) Slot 1 (0x1): Gemalto GemPC Twin 00 00 (empty) Slot 2 (0x2): Gemalto GemPC Twin 00 00 (empty) Slot 3 (0x3): Gemalto GemPC Twin 00 00 (empty) Slot 4 (0x4): Gemalto GemPC Twin 00 00 (empty) $ pkcs11-tool -L Available slots: Slot 0 (0xffffffff): Virtual hotplug slot (empty) Slot 1 (0x1): Gemalto GemPC Twin 00 00 (empty) Slot 2 (0x2): Gemalto GemPC Twin 00 00 (empty) Slot 3 (0x3): Gemalto GemPC Twin 00 00 (empty) Slot 4 (0x4): Gemalto GemPC Twin 00 00 (empty) Slot 5 (0x5): Gemalto GemPC Twin 01 00 (empty) Slot 6 (0x6): Gemalto GemPC Twin 01 00 (empty) Slot 7 (0x7): Gemalto GemPC Twin 01 00 (empty) Slot 8 (0x8): Gemalto GemPC Twin 01 00 (empty)
Qui ho fatto due prove, per vedere se erano previsti 4 lettori o se ogni lettore offre 4 slot. Buona la seconda. Ma devo ancora capire cosa questo implichi.
Ora che si sa che il lettore è compatibile, è necessario inizializzare la card:
$ pkcs15-init -C --pin 1111 --puk 1111 Using reader with a card: Gemalto GemPC Twin 00 00 New Security Officer PIN (Optional - press return for no PIN). Please enter Security Officer PIN: Please type again to verify: Unblock Code for New User PIN (Optional - press return for no PIN). Please enter User unblocking PIN (PUK): Please type again to verify:
Qui viene creata (-C) una nuova struttura PKCS15. PIN e PUK servono solo per evitare varie richieste a vuoto: PIN e PUK per il Security Officer (l'amministratore della card, praticamente l'account root, che ha accesso completo e può anche "riformattare" la card -- ma neppure il S.O. può accedere alle chiavi private!) vengono comunque chiesti da linea di comando. Il PIN del S.O. verrà poi richiesto per molte operazioni.
Poi si inizializzano i PIN/PUK necessari per le proprie esigenze. Io ne ho creati due: uno per l'autenticazione ed un altro per le firme. Se le vostre esigenze lo richiedono, potete crearne fino a 14 (su card MyEID... su altre potrebbe essere possibile crearne uno solo, o anche di più).
$ pkcs15-init -P -a 1 -l "Auth PIN" Using reader with a card: Gemalto GemPC Twin 00 00 New User PIN. Please enter User PIN: Please type again to verify: Unblock Code for New User PIN (Optional - press return for no PIN). Please enter User unblocking PIN (PUK): Please type again to verify: Security officer PIN [Security Officer PIN] required. Please enter Security officer PIN [Security Officer PIN]: $ pkcs15-init -P -a 2 -l "Sign PIN" Using reader with a card: Gemalto GemPC Twin 00 00 New User PIN. Please enter User PIN: Please type again to verify: Unblock Code for New User PIN (Optional - press return for no PIN). Please enter User unblocking PIN (PUK): Please type again to verify: Security officer PIN [Security Officer PIN] required. Please enter Security officer PIN [Security Officer PIN]:
Qui si crea un nuovo PIN (-P) in prima (e poi seconda) posizione (-a 1 / -a 2) e gli si assegna un'etichetta (utile poi per sapere quale PIN inserire più avanti). Come potete notare viene richiesto ogni volta anche il PIN del S.O., poiché si stanno modificando dati "base" della card.
Una volta creati i vari PIN, si può "finalizzare" la card. Questa operazione, in pratica, dovrebbe semplicemente attivare i controlli di accesso:
$ pkcs15-init -F Using reader with a card: Gemalto GemPC Twin 00 00
Da notare che non viene chiesto nulla.
Dopo aver esportato il mio certificato da Firefox (e dopo averlo collaudato su un altro Firefox, tanto per essere tranquillo) in startssl.p12, lo importo nella card:
$ pkcs15-init -S startssl.p12 -f PKCS12 -a 1 Using reader with a card: Gemalto GemPC Twin 00 00 error:23076071:PKCS12 routines:PKCS12_parse:mac verify failure Please enter passphrase to unlock secret key: Importing 3 certificates: 0: /description=******-****************/O=Persona Not Validated/CN=StartCom Free Certificate Member/emailAddress=*******@********* 1: /C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Certification Authority 2: /C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Class 1 Primary Intermediate Client CA User PIN [Auth PIN] required. Please enter User PIN [Auth PIN]:
Qui importo un certificato (-S file) in formato PKCS12 (-f PKCS12) e l'accesso alla chiave segreta richiede il pin n.1 ("Auth PIN").
Fatto questo, verifico che sulla card ci sia tutto:
$ pkcs15-tool -c -C --list-pins Using reader with a card: Gemalto GemPC Twin 00 00 X.509 Certificate [/description=******-****************/O=Persona Not Validated/CN=StartCom Free Certificate Member/emailAddress=*******@*********] Object Flags : [0x2], modifiable Authority : no Path : 3f0050154301 ID : 4a3ba138834****************335b31ed205b6 Encoded serial : 02 03 01**** X.509 Certificate [/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Certification Authority] Object Flags : [0x2], modifiable Authority : yes Path : 3f0050154302 ID : 509b7413aa02db7808cf0c378e61a7ecc4f29745 Encoded serial : 02 01 01 X.509 Certificate [/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Class 1 Primary Intermediate Client CA] Object Flags : [0x2], modifiable Authority : yes Path : 3f0050154303 ID : 6b4d6361e8c647c2ad9a055c051139ccdfdb1885 Encoded serial : 02 01 1E PIN [Security Officer PIN] Object Flags : [0x3], private, modifiable ID : ff Flags : [0xB0], initialized, needs-padding, soPin Length : min_len:4, max_len:8, stored_len:8 Pad char : 0xFF Reference : 3 Type : ascii-numeric Path : PIN [Auth PIN] Object Flags : [0x3], private, modifiable ID : 01 Flags : [0x30], initialized, needs-padding Length : min_len:4, max_len:8, stored_len:8 Pad char : 0xFF Reference : 1 Type : ascii-numeric Path : PIN [Sign PIN] Object Flags : [0x3], private, modifiable ID : 02 Flags : [0x30], initialized, needs-padding Length : min_len:4, max_len:8, stored_len:8 Pad char : 0xFF Reference : 2 Type : ascii-numeric Path :
Interessante l'indicazione del path degli oggetti: 3F00 (root) / 5015 (PKCS15) / 430x... Può tornare utile per accedere direttamente "a basso livello" alla card.
A questo punto, ho cancellato da Firefox il mio client certificate (BRRR!), ed ho caricato un nuovo "Dispositivo di sicurezza" (il modulo da usare, in Mandriva, è /usr/lib/opensc-pkcs11.so ).
A parte il fatto che autenticandomi sul sito di StartSSL mi chiede anche il PIN per la firma (ma posso non darlo, basta premere ESC o cliccare su "Annulla"), funziona perfettamente. A meno che non togliate e reinseriate la card: in tal caso, per Firefox la chiave sarà sbloccata, mentre per la card sarà bloccata. È sufficiente tornare nella schermata di gestione, selezionare il PIN erroneamente considerato "aperto" e cliccare "chiudi". Oppure chiudere e rilanciare Firefox. Potrebbe anche solo essere un bug in Firefox 4.0beta...
Visto che portarsi dietro una smart card è comodo, vorrei usarla anche per gestire l'autenticazione SSH. Decisamente l'appetito vien mangiando
Per questo inizio installando engine_pkcs11, richiesto da OpenSSL. Fatto questo:
$ pkcs15-init -G rsa/2048 -a 1 -u decrypt,sign -l SSH Using reader with a card: Gemalto GemPC Twin 00 00 User PIN [Auth PIN] required. Please enter User PIN [Auth PIN]:
Ho dovuto usare sia decrypt che sign poiché l'handshake di SSH li usa entrambi...
Questa fase può richiedere anche un minuto. Dipende dalla lunghezza scelta e, forse, anche dalla chiave (a volte ha impiegato 15s, altre 50s...).
Ora verifico che la chiave sia stata aggiunta:
$ pkcs15-tool -k --list-public-keys Using reader with a card: Gemalto GemPC Twin 00 00 Private RSA Key [Private Key] [...questa è quella del certificato per StartSSL...] Private RSA Key [SSH] Object Flags : [0x3], private, modifiable Usage : [0x2E], decrypt, sign, signRecover, unwrap Access Flags : [0x1D], sensitive, alwaysSensitive, neverExtract, local ModLength : 2048 Key ref : 2 Native : yes Path : 3f0050154b02 Auth ID : 01 ID : 9a1fa509c036d00e14fcd09e2cc4623d11254fcf Public RSA Key [SSH] Object Flags : [0x2], modifiable Usage : [0xD1], encrypt, wrap, verify, verifyRecover Access Flags : [0x0] ModLength : 2048 Key ref : 0 Native : no Path : 3f0050155501 ID : 9a1fa509c036d00e14fcd09e2cc4623d11254fcf
Da notare "sensitive" e "neverExtract": questa chiave privata non può lasciare la card per nessun motivo!
Se volete una sicurezza minore, potete usare rsa/1024. Oppure creare altre chiavi a sicurezza diversa. Con le label potete identificare facilmente quale ID corrisponde a quale chiave. L'ID della chiave privata è uguale all'ID della chiave pubblica, quindi potreste usare anche solo -k, senza --list-public-keys .
Le chiavi possono essere rimosse dalla card con pkcs15-init -D privkey --id 9a1f..fcf
e pkcs15-init -D pubkey --id 9a1f..fcf
.
Per permettere il login remoto, devo esportare la chiave pubblica per il mio ~/.ssh/authorized_keys sul server :
$ pkcs15-tool --read-ssh-key 9a1fa509c036d00e14fcd09e2cc4623d11254fcf Using reader with a card: Gemalto GemPC Twin 00 00 2048 65537 20015055298168735343931698895893302218606119627306143296144578697900435878107067996166978424908105742403196312097281539413963604832215491264596571713709758444518097915035505582970682318805600964172484283736281843760797737928237814880158105225499576427621754271639889630755296638945552141639374608813958108825889688667297632929536819638638784568467561167430780781902166352193640833129842893922376759333170787762102020743236028197425147611528143962684572073952632597099520281998089593667632722784516793213504400230962124961887995287708559823196657591893107543450761926218346768663627789322880040993394283130095613940773 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCejL5Jp5h2MblIY/DY2XvIMx/RhMaPTtq2bTA88DkcuWR8yR3BspUZ3VNHbhrnNpeUqDvmOipRBxATeHRY7m01qU2c4bMtYzp7RBjdG3pf10l15FqHv9qWfBcLFTqFhEf5+qBJANLiAkgERfcOTrZZg5Ize1tK8Bn0T4Kktp96Z9ruiSK1jTWywnPYWLKwWsq+qS6h4v7PERjjKN0bg081aVQEjPtmmqRUcetYgdqpIspKwmwTG+dLXeAJBzwhdNUVfKzsZfAknPcptD2GfJCkMmQrlmLNhdvNeSYZ0NQgVZ/SMUm1CDk65AY/LF1LzXYEQyYqnb/D6+4HpPu40pQl
La parte da mettere sul server è quella da ssh-rsa (compreso) in poi.
Ed ora il test:
$ ssh -o PKCS11Provider=/usr/lib/opensc-pkcs11.so pvs Enter PIN for 'MyEID (Auth PIN)': Linux pvs.csshl.org 2.6.26-2-486 #1 Thu Nov 25 01:49:20 UTC 2010 i686
FUNZIONA! Un pelo lento e chiede il PIN, ma FUNZIONA!
Per non dover inserire ogni volta -o PKCS11Provider=/usr/lib/opensc-pkcs11.so
, si può semplicemente usare:
$echo PKCS11Provider /usr/lib/opensc-pkcs11.so >> ~/.ssh/config
Il difetto di questo sistema è che non potete "rimbalzare" su un host remoto, a meno che a questo host remoto non sia collegato un altro lettore con un'altra card... Ma per questo si può sempre usare un id_rsa "standard" sul server! Un sistema non esclude l'altro.
Commenti
Alcune note
Capacità
La card è dichiarata da 80kB, ma se non ci si caricano applicazioni Java, alla fine se ne usano solo 32kB (la dimensione della "root", il massimo gestibile da una singola applicazione Java per SmartCard)! Quindi c'è posto almeno per un'altra applicazione che usi altri 32KB di dati + 16KB di codice... Ma questo è un mondo tutto da esplorare!
In questi mi pare strano che trovino posto solo due certificati a 2048bit, o un certificato e qualche chiave (ne ho aggiunte 4 da 2048bit e 2 da 1024 senza problemi).
Mi rimangono grossi dubbi sul significato di "slot": dalla documentazione in
/etc/opensc.conf
parrebbe che ogni slot gestisca una chiave, mapkcs11-tool -L
lista uno slot per ogni PIN definito... Comunque nella mia configurazione ho impostato :per gestire 4 lettori (e card) con 16 chiavi o PIN su ogni card, ma malgrado questo continuo a non riuscire a caricare più di due certificati... se sono in formato PKCS12. Ma sono riuscito a caricarmeli tutti convertendoli in PEM ed importando separatamente chiave privata e chiave pubblica:
openssl pkcs12 -in $CERTNAME.p12 -out $CERTNAME.pem
: converte il file PKCS12 in PEMpkcs15-init -a 2 -S $CERTNAME.pem --cert-label $CERTNAME
: importa la chiave segreta sulla card, protetta dal PIN2 (che ho chiamato "User Auth"; chiede il PIN1 che ho chiamato "Card Auth")pkcs15-init -X $CERTNAME.pem -l $CERTNAME
: importa la chiave pubblica ed il resto del certificato (chiede anche qui il PIN1)Peccato però che poi Firefox e Thunderbird non li riconoscano
Altro problema con questo sistema è che non ritrovo le label assegnate, quindi bisogna andare "a naso" per associare una chiave al suo certificato... Non è bello.
Uso dei PIN
Mi sono accorto che i PIN ha poco senso utilizzarli come li ho usati: una chiave (o un certificato) può avere molteplici usi. Quindi meglio legare un PIN ad una chiave (se volete la massima sicurezza) o proteggere tutte le chiavi con un solo PIN (per la massima semplicità con una sicurezza decente).
Sono anche possibili vari "giochi" sul PIN, compresa la possibilità di fornirlo "bloccato" così che l'utente sia costretto a cambiarlo al primo uso: utile se si devono fornire molte card e non si vuole essere a conoscenza di tutti i PIN.
Il PIN 1 viene chiesto per molte operazioni sulla card, come per es. la generazione di una nuova coppia di chiavi. Può quindi essere utile far usare normalmente agli utenti il PIN2, riservando l'1 ad un delegato del S.O. ... Caso strano il so-pin non viene quasi mai chiesto.
Attenzione però se volete usare Firefox come GUI per caricere i certificati sulla card: è possibile aggiungerli (fino a due), ma solo col PIN1. Almeno col 4.0b11... Pare però possibile usare tutti (entrambi... finché non riesco a caricarne di più) i certificati, ma vengono richiesti tutti i PIN, anche di quelli che non si vogliono usare o non referenziati da alcun certificato.
Aggiornamento
Sono riuscito a memorizzare fino a 16 coppie di chiavi generate con -G. 2048 o 1024 bit non influisce sul numero di chiavi memorizzabili. Più un certificato.
Questo coi valori di default in
/usr/share/pcsc/myeid.profile
. Ho provato modificando alcuni valori di default e facendo qualche esperimento.Da quanto ho capito, prkdf-size e pukdf-size definiscono la dimensione dei file che contengono rispettivamente metadati e puntatori ai dati delle chiavi private e delle relative chiavi pubbliche. Le chiavi effettive verranno memorizzate negli EF 4Bxx e 55xx.
Aumentando cdf-size aumenta il numero di certificati e di chiavi memorizzabili (pare essere una sorta di "directory" contenente i riferimenti alle chiavi). Portandolo a 4096 ho potuto memorizzare tutti e 4 i miei certificati, ed avanza anche del posto. I certificati vengono memorizzati negli EF 43xx, le loro chiavi segrete negli EF 4Bxx, come quelle generate on-card (infatti si può generare una chiave segreta on-card e mandare una CSR per la sua chiave pubblica).
Con queste impostazioni:
ho potuto generare 58 coppie di chiavi (invece delle 50 che avevo stimato, probabilmente perché ho usato label più corte) prima di riempire il CDF, ma poi ne vedo 'solo' 32 (limitazione di pkcs15-tool ... ed arriva ad avere problemi a cancellare le chiavi private)!
Mi sono basato su un riassunto delle specifiche... Con più tempo cercherò di ricavare più informazioni dalle specifiche complete (reperibili ma "dure" da interpretare). Sulla mailing list di OpenSC-devel sto cercando di capirne di più. Purtroppo per ogni variazione dei parametri è necessario riformattare la card, perdendo le chiavi generate...
Parametri soddisfacenti
Usando
opensc-explorer
ho potuto determinare esattamente lo spazio disponibile sulla card: 60405 (forse qualche byte in più, utilizzato per memorizzare i dati del DF 5015 e dell'EF 2F00. Il metodo usato è stato suggerito da Toni Sjoblom di Aventra (questo è customer support: un tecnico dell'azienda che frequenta le mailing list dove gli utenti pongono le domande! Tante aziende avrebbero da impararlo!): creare degli EF grossi (io ho usato 16K, non si possono creare file di 32K dato che il massimo è 32767 byte) fino a che la card non segnala "pieno". A questo si somma lo spazio già occupato dai file presenti e quello ancora libero.Quindi l'applicazione di Aventra è circa 20k.
Ogni coppia di chiavi di 2048 bit occupa 2048+270 byte in due nuovi EF (1024+140 per quelle a 1024 bit), più una novantina di byte nei file di indice.
Ogni certificato occupa 'circa' 2K, più la relativa chiave segreta (dipende principalmente dalle stringhe contenute, quindi è difficile fare una buona stima).
Caricando i miei certificati (4 chiavi segrete, 4 certificati per le relative chiavi pubbliche, un certificato per la "root CA" di StartSSL e 3 certificati di "intermediate CA"), mi rimane lo spazio per generare 15 coppie di chiavi a 2048 bit ed una a 1024 bit (dopo questo avanzano 880 byte). Non male!
I parametri usati sono:
Probabilmente riducendo un po'
prkdf-size
epukdf-size
si riesce a "stivare" la sedicesima (e magari perfino la diciasettesima) chiave a 2048 bit.pukdf-size
può essere ridotto più diprkdf-size
dato che le chiavi pubbliche importate coi certificati non occupano spazio nel file pukdf.Ma bisogna anche pensare che se si generano chiavi di 1024 bit, lo spazio negli EF si dimezza (quindi si arriva allegramente ad una trentina di coppie di chiavi), ma quello in prkdf e pukdf rimane uguale (e dipende dalla lunghezza delle label).
Posso quindi dire di essere discretamente soddisfatto dei parametri che ho ottenuto, che mi permettono un'ottima flessibilità tra certificati e chiavi on-card.
Stranezza con PIN ed SSH
Facendo tante prove, mi sono accorto di una stranezza: se sulla card metto più di un PIN, SSH va in errore.
E, se anche la chiave segreta viene creata con --insecure, il PIN viene richiesto lo stesso.
Mah!
Probabilmente un bug o in OpenSC o nell'app di Aventra... Problema già segnalato (link disperso nella migrazione), ma ancora nessuna risposta
Sblocco del SO-PIN
Questo lo metto in un commento tutto suo perché non è banale...
Per prima cosa è necessario determinare a quale PIN corrisponde il SO-PIN:
Quindi, per la MyEID il SO-PIN è il PIN con id FF.
A questo, conoscendo il SO-PUK, punto posso sbloccare la card con:
Ora potrò anche riformattare la card, usando il nuovo SO-PIN impostato.
Ovviamente il metodo vale anche per gli altri PIN, con la differenza che, finché si conosce il SO-PIN, è possibile recuperare la card (al limite a costo di riformattarla, ma almeno poi la si può riutilizzare), mentre se il SO-PIN è bloccato e si va a bloccare anche il SO-PUK, la card è da buttare (beh, quasi... se si hanno gli altri PIN si può continuare ad usarla, basta non avere necessità di riformattarla).
[edit]
In realtà la card è ancora recuperabile (a livello HW): se la si rimanda in Aventra, possono ricaricare la loro applet (che, comprensibilmente, non mandano in giro) e la card torna "vergine". Ovviamente l'operazione è analoga alla riformattazione di un hard disk: tutti i dati che erano sulla card sono definitivamente persi. Per una sola card non ne vale la pena, ma invece di buttarla conviene tenerla da parte e magari quando le card locked saranno varie ne varrà la pena.
Visto che mi è capitato di lockare il so-puk su una delle card (incomprensibile, dato che era inizializzata da uno script con PIN e PUK di prova... ma magari avevo fatto un test con un PUK che poi mi sono scordato...), ne approfitterò per tentare di realizzare una mia applet JavaCard che implementi la crittografia neurale abbinata ai metodi classici.
Tra l'altro, Aventra si è ulteriormente distinta per l'assistenza clienti a dir poco eccezionale: visto che ho contribuito al testing e suggerito vari miglioramenti, mi hanno inviato un paio di card in omaggio!
Ulteriori informazioni sulla card Aventra
Per i test di cui dicevo sopra, è necessario poter caricare un'altra applet.
Ma la cosa non è così banale.
Intanto alcuni dati che sono riuscito a recuperare:
Per tentare di caricare un'applet di test, ho usato scsh3 + gli script per poter seguire le istruzioni di installazione MuscleCard... Peccato che non funzioni: quando tento di autenticarmi alla card, ottengo un errore:
Quindi al momento sono di nuovo fermo Oltretutto bisogna fare molta attenzione, poiché dopo 10 tentativi di autenticazione il card manager si blocca e non sarà più possibile sostituire le applet caricate!
Edit: il sempre disponibilissimo Toni di Aventra mi ha confermato che hanno cambiato le chiavi per motivi di sicurezza. Quindi la card non si ricicla. Bisogna comprarne di nuove. Per esempio da Futako. Peccato che le card JCOP31 SIM-Size, anche se (potenzialmente) dual-interface, non abbiano una connessione standard per l'antenna...