Crittografia in OpenBSD

Posted On 01 Gen 2008
Comment: Off

linuxtutorial

Tutorial Linux – Le origini di BSD.

Il termine BSD nasce attorno agli anni ‘80, quando Ken Thompson (inventore del linguaggio C) e i suoi due dottorandi dell’universita di Berkeley in California, Chuck Haley e Bill Joy (autori dell’editor vi), progettarono la prima versione della Berkeley System Distribution di Unix o, più semplicemente, BSD Unix, un sistema operativo libero basato su Unix. Nel corso degli anni BSD venne notevolmente migliorato, la seconda versione era pronta nel 1978, mentre la terza nel 1979. Proprio da quest’ultima versione nacquero diversi gruppi di sviluppo ed altrettante ramificazioni di BSD, le più importanti sono: FreeBSD, NetBSD, OpenBSD.


Il modello di sicurezza di OpenBSD
OpenBSD viene sviluppato in Canada da un team coordinato da Theo de Raadt, il Canada in particolare, grazie alla sua legislazione, permette l’esportazione di software crittografico in tutto il mondo. OpenBSD crede in un modello di sicurezza robusto, affiancato al modello di sviluppo aperto. Nel mondo dei sistemi operativi OpenBSD è stato forse il primo ad abbracciare il concetto di full disclosure, ovvero l’esposizione totale dei problemi legati a difetti o errori del software. Esiste, infatti, un team di audit composto da 6-12 membri che segue costantemente riga per riga il codice del sistema operativo cercando bug e vulnerabilità. Questo processo ha permesso di scoprire nuove categorie di problemi legati alla sicurezza facendo così scuola a tutti gli altri sistemi operativi. I risultati sono evidenti e hanno permesso di conferire ad OpenBSD l’appellativo di “sicuro di default”, d’altra parte ci si accorge di quanto il team tenga alla sicurezza già dalla visita della home page (http://www.openbsd.org), al centro della pagina, infatti, risalta all’occhio una scritta rossa: “Only one remote hole in the default install, in more than 7 years!”, un solo buco di sicurezza remota in più di sette anni è un ottimo biglietto da visita!


Tecniche crittografiche
Come dice Bruce Schneier, uno dei padri della crittografia applicata: “La sicurezza non è un prodotto, ma un processo. E’ molto di più di disegnare una forte crittografia all’interno di un sistema; è progettare l’intero sistema affinchè tutti i sistemi di sicurezza, inclusa la crittografia, lavorino insieme”. La crittografia quindi interpreta grandi ruoli nel sistema operativo OpenBSD, garantisce la segretezza e l’integrità delle informazioni che possono essere esposte ad attacchi, per esempio durante la trasmissione in rete, garantisce autenticazione locale e remota, permette l’uso della firma digitale verificando l’autorevolezza e l’autenticità di documenti. Con il termine meccanismo crittografico si intende un insieme di tecniche che permettono di realizzare, attraverso procedure matematiche, funzioni crittografiche. Le principali componenti di un meccanismo crittografico sono: la generazione di numeri pseudocasuali, le funzioni hash, le trasformazioni crittografiche.


Generazione di numeri pseudocasuali
Un generatore di numeri pseudocasuali è un algoritmo matematico che prende in input dei valori numerici e restituisce come output altri valori numerici dipendenti dall’input. Un PNRG (Pseudo Random Number Generator) deve garantire le seguenti proprietà matematiche:


 è impossibile predire l’output di un generatore di numeri pseudocasuali anche conoscendo i precedenti valori,
 i numeri pseudocasuali non devono avere un vero e proprio percorso di ripetizione, ciò significa che un PRNG deve avere una vasta lunghezza del ciclo di generazione dei valori numerici.


Per garantire queste proprietà OpenBSD trae casualità da alcune componenti di sistema:


 l’intervallo di pressione dei tasti in un terminale
 il tempo di arrivo di pacchetti in rete
 il tempo impiegato dal sistema per le richieste di dati al disco.


I numeri pseudocasuali sono utilizzati da OpenBSD per generare gli XID (Remote Procedure Call transaction ID), gli identificatori per chiamate di procedure remote che possono essere soggetti ad un attacco di predizione numerica, i valori degli inode utili, ad esempio, per proteggere file system distribuiti (NFS, Coda, ecc.) o per la generazione del salt nelle password.


Funzioni hash
Una funzione hash è una procedura matematica che prende in input un qualsiasi dato e ne restituisce una stringa di dimensione costante. Le funzioni hash sono, quindi, così definite:


h = H(M)


Dove M è il messaggio o dato, H la funzione hash e h la stringa di output. Devono, inoltre, essere verificate le seguenti proprietà:


 Dato M è facile calcolare h.
 Dato h è difficile calcolare M.
 Dato M è difficile trovare un altro messaggio M’ tale che H(M) = H(M’).


Questo tipo di funzioni sono anche chiamate one-way hash function. In OpenBSD vengono usate le seguenti funzioni hash: MD5, SHA1, RIPEMD-160. L’algoritmo MD5 usa quattro turni per applicare ogni volta un funzione non lineare ad ognuno dei sedici blocchi di 32 di un unico blocco di partenza di 512 bit, il risultato è una stringa di lunghezza fissa di 128 bit. L’algoritmo SHA1 produce una stringa di 160 bit ed è basato sull’algoritmo MD4 con l’aggiunta di alcune operazioni addizionali. RIPEMD-160 è una funzione a 160 bit ed è considerata un valida e sicura alternativa alle funzioni hash MD4 e MD5.


Trasformazioni crittografiche
Una funzione crittografica è formata da due componenti, una funzione E e una chiave K. Il messaggio cifrato risultante è indicato come {M}k , quindi possiamo definirla come:


E(K,M) = {M}k


La funzione crittografica E definisce un algoritmo che trasforma un testo in chiaro in un testo cifrato combinandolo con un chiave, in modo tale che la sicurezza dipenda esclusivamente dal possesso della chiave stessa. Al contrario delle funzioni hash esiste una funzione inversa che trasforma il testo cifrato nel testo originale:


D(K’,E(K,M)) = D(K’,{M}k) = M


Nel caso di chiave condivisa K=K’, perciò si parla spesso di crittografia simmetrica, mentre se è K?K’ si tratta di una coppia di chiavi pubblica/privata, la cosidetta crittografia asimmetrica. OpenBSD offre il supporto per le funzioni crittografiche DES, 3DES, Blowfish e Cast. DES mappa blocchi di 64 bit di un testo in chiaro in blocchi di 64 bit usando un chiave di 56 bit è dipendente da 16 turni di trasformazioni e rotazioni di bit. Nel Giugno del 1997 DES è stato violato con un attacco di tipo brute-force per questo venne megliorato con una tripla applicazione dello stesso algoritmo e chiamato 3DES. 3DES è così definito:


E3DES(K1,K2,M) = EDES(K1,DDES(K2,EDES(K1,M)))


Blowfish è un cifrario a blocchi di 64 bit, sviluppato da Bruce Schneier, che lavora con chiavi a lunghezza variabile fino a 448 bit. Questo algoritmo utilizza varie tecniche tra le quali le reti Feistel, le S-box e non esistono ancora possibili attacchi nei suoi confronti. Cast è un algoritmo con tre tipi di funzioni e 4 S-box l’algoritmo produce un output a 256 bit.


Crittografia nelle password
Molti schemi di autenticazione dipendono da password segrete. Con la crescita della potenza dei microprocessori è aumentata la rapidità dei software crittografici. Una crittografia rapida offre molte opportunità di rendere più sicuri i sistemi. Sfortunatamente l’entropia della lunghezza e la casualità delle parole scelte dagli utenti rimane costante nel tempo. Al contrario, la continua crescita della potenza hardware offre un supporto computazionale sempre più grande agli attacchi mirati alla forzatura di password. Si ottiene come risultato che il tradizionale schema Unix di autenticazione e gestione delle password decade con l’andar del tempo. Il desiderio è quello di ottenere un sistema nel quale la sicurezza delle password è legata alla velocità dell’hardware. In OpenBSD la gestione delle password è garantita da due grandi algoritmi adattabili ai costi: Blowfish e bcrypt. Questi algoritmi hanno profonde radici nella teoria della complessità computazionale e sono assicurati per adattarsi e garantire sicurezza per i prossimi 20 anni a venire.


Eksblowfish
Eksblowfish sta per “expensive key schedule blowfish” ed è la particolare implementazione di Blowfish in OpenBSD. Eksblowfish è stato progettato per matenere le password scelte dagli utenti come chiavi e resistere agli attacchi su quest’ultime. Come base si usa l’algoritmo Blowfish di Schneier un algoritmo molto ben testato. Blowfish è un algoritmo crittografico a blocchi di 64 bit strutturato come 16 turni di rete Feistel. Usa 18 sottochiavi a 32 bit, P1,…,P18, che ricava dalla chiave principale. Le sottochiavi sono conosciute collettivamente come
P-Array. Blowfish cifra il messaggio dividendo un blocco di 64 bit in input in due parti di 32 bit, La metà più significativa, L0, è messa in XOR con la sottochiave P0 e usata come input per la funzione F. Il risulatato di questa funzione è messo, a sua volta, in XOR con l’altra metà meno significativa, R0. Le due metà vengono, quindi, invertite e l’intero processo ripetuto 15 volte per un totale di 16 iterazioni. Quindi, per 1 ? i ? 16, considerando ⊕ l’operazione di XOR:


Ri = Li – 1 ⊕ Pi
Li = Ri – 1 ⊕ F(Ri )


Questo processo è illustrato in figura 1.

fig1


Figura 1 – L’algoritmo eksblowfish.


Bcrypt
La tradizionale gestione della password in ambiente Unix lascia spazio allo schema bcrypt applicato attraverso l’algoritmo di crittografia Blowfish. Bcrypt usa un salt di 128 bit e cifra un valore di 192 bit, traendo vantaggio dall’expansive key setup di eksblowfish. L’algoritmo bcrypt è eseguito in due fasi come mostrato in Figura 2. Nella prima fase, EksBlowfishSetup è invocato con il cost, il salt e la password per inizializzare lo stato di eksblowfish. La maggior parte del tempo di bcrypt è speso nel procedimento expensive key schedule. Il valore OrpheanBeholderScryBoubt di 192 bit è criptato 64 volte usando eksblowfish in modalità ECB con lo stato della fase precedente. L’output è il costo e 128 bit di salt concatenati con il risultato del ciclo di crittografia.
OpenBSD permette agli amministratori di scegliere lo schema di gestione delle password attraverso uno speciale file passwd.conf. Questo file permette il controllo dettagliato del tipo di password per un determinato utente o gruppo. Bcrypt permette, inoltre, di specificare il costo, permettendo, così agli utenti di impostare il tempo di calcolo delle password (il parametro cost) aumentando la sicurezza della stessa. Attualmente il valore standard del costo è 6 per un normale utente e 8 per root.


bcrypt (cost, salt, password)
      state := EksBlowfishSetup(cost, salt, key)
      ctext := OrpheanBeholderScryBoubt
      repeat (64)
             ctext := EncryptECB (state, ctext)
      return Concatenate(cost, salt, ctext)


 Esempio di algoritmo hash bcrypt per password Unix basato su eksblowfish.



Crittografia in rete
Con lo sviluppo del networking, il supporto per la sicurezza in un sistema operativo rappresenta un elemento di primaria importanza. Poiché ci sono diversi meccanismi e diversi livelli di applicazione della sicurezza, OpenBSD supporta una vasta quantità di modelli e protocolli di sicurezza, alcuni implementati proprio dal suo team di sviluppo. Uno dei punti di forza di queste applicazioni in OpenBSD è la totale trasparenza rispetto l’utente. Tra le più importanti applicazioni troviamo: SSL, IPSec,Kerberos, S/Key e OpenSSH. In OpenBSD libssl offre gli strumenti per il protocollo Secure Socket Layer (SSL v2/v3) e Transport Layer Security (TLS v1). Il Secure Socket Layer è utilizzato attualmente dai web server (p.e. Apache) e browser (p.e. Netscape Communicator, Mozilla, …), ma anche da applicazioni come telnet e ftp. IPsec è implementato come un’estensione della tabella di routing dove l’indirizzo sorgente/destinazione, il protocollo e le porte servono da selettori. Programmi come login, xdm e su per l’uso locale e rlogin, rsh e telnet per l’uso remoto contengono il codice necessario per l’autenticazione Kerberos e l’aspirazione futura è di includere il protocollo IPSec nelle applicazioni che già utilizzano Kerberos per una sicurezza ancora più efficiente. OpenSSH è stato sviluppato originariamente per OpenBSD e poi implementato per diversi sitemi operativi: NetBSD, FreeBSD, AIX, HP-UX, IRIX, Linux, NeXT, SCO, SNI/Reliant Unix, Solaris, Digital Unix/Tru64/OSF, MacOS X.



Crittografia nella memoria virtuale
Anche se molti sistemi operativi offrono il supporto per filesystem crittografici, OpenBSD, col suo spirito perfezionista, non vuole tralasciare la sicurezza dello spazio riservato alla memoria virtuale. Qualora un processo facesse uso di swap, qualsiasi dato letto, anche se originalmente cifrato, potrebbe essere trovato facilmente sotto forma di testo in chiaro nella memoria virtuale. E’ inoltre possibile che password e frasi segrete, dopo essere state digitate, risiedano per lungo tempo nella memoria swap, anche dopo reboot. La soluzione che è adottata in OpenBSD è quella di cifrare le pagine di memoria che sono desitante alla memoria swap. Tali pagine verranno decifrate al momento della richiesta di ingresso nella memoria fisica (pagefault). Quando un processo termina tutte le sue pagine memorizzate nella swap sarranno invalidate e nessuno sarà abilitato a decifrarle. Il tipico utilizzo della memoria virtuale è quello di incrementare lo spazio di indirizzamento della memoria fisica di un processo offrendo uno spazio riservato sul disco, chiamata secondary storage. Messa a confronto con la velocità della RAM la secondary storage appare molto lenta, al contrario è un tipo di memoria non volatile e i dati vi rimangono memorizzati anche dopo lo shutdown del sistema. Non si può quindi assumere che i dati privati di un processo siano cancellati dopo la sua terminazione. Lo dimostra il fatto che un’analisi presso il Center of Information Technology Integration ha rivelato che le partizioni di swap delle loro stesse macchine contenevano in chiaro password di login, frasi segrete di PGP, messaggi email, chiavi crittografiche dell’agente SSH, cronologie dei comandi shell, URL, ecc. Uno dei possibili approcci a tale problema è impedire totalmente l’uso della memoria swap, una soluzione drastica che impedirebbe l’esistenza a quei programmi che necessitano di una memoria virtuale molto più estesa della memoria fisica disponibile. Un’altra soluzione portebbe essere quella di utilizzare la funzione di sistema mlock() per prevenire la memorizzazione in swap delle pagine di memoria. Ciò comporta numerosi svantaggi. Tutte le applicazioni dovrebbero essere riscritte per usare mlock(), e, comunque non sarebbe semplice definire quali parti della memoria conterrebbero effettivamente dati confidenziali. Inoltre, tale meccanismo avrebbe un evidente impatto sulle performance del sistema. La soluzione più efficiente risulta essere quella di installare nel sistema uno swap pager specifico per rendere la memoria virtuale dipendente da tecniche crittografiche. La crittografia applicata nella memoria virtuale ha i seguenti vantaggi rispetto alla tradizione gestione:


 Cancellare i dati nel disco comporta un sostanziale aumento del tempo di I/O. In altre parole, con la crittografia il contenuto della pagina “sparisce” quando la rispettiva chiave è cancellata e, comunque, il costo dell’operazione di cifraggio è distribuito uniformemente nell’operazione di swapping.
 L’uso della crittografia protegge contro attacchi fisici. Anche lo stesso possesso del disco non garantisce la conoscenza del suo contenuto.
 L’effettiva cancellazione dei dati da supporti magnetici è difficile, problema che non esiste utilizzando dati cifrati.


Il funzionamento
La memoria virtuale viene divisa in sezioni di 512 KB e ad ognuna viene assegnata una chiave. La chiave crittografica consiste in una stringa di 128 bit, un contatore di richieste, e un tempo di scadenza. Per una partizione di swap di 256 MB sono richiesti 14 KB di memoria per le chiavi. Le chiavi a 128 bit delle sezioni sono create casualmente e il contatore impostato a 0. Ogni volta che una nuova pagina è stata cifrata con una determinata chiave il contatore associato sarà incrementato di 1. Quando una pagina viene rimossa il contatore viene decrementato, la chiave viene rimossa quando il contatore ritorna a 0. In tutti i modi la durata totale della chiave non supererà mai il tempo fissato tR. La figura 3 descrive il processo di paging nei passi che lo compongono e mostra come si inseriscono le operazioni crittografiche in questo panorama.


fig3



Figura 3 – Una visuale del processo di swapping


1 Richiesta di memoria da parte di un processo.
2 L’indirizzo richiesto è mappato in memoria fisica.
3 L’indirizzo richiesto è mappato nella swap (page fault).
4 Il pager legge la pagina richiesta.
5 La pagina viene decifrata.
6 La pagina viene inserita in memoria fisica.
7 Richiesta di swapping.
8 La pagina da inserire viene crittata. (8a) Se la sezione non ha ancora la chiave crittografica, viene creata dall’entropy pool del kernel.
9 La pagina viene inserita nella swap.



Conclusioni
Si è dimostrato che OpenBSD è un sistema operativo valido ed efficace nel campo della sicurezza, lo dimostra il fatto che molte compagnie e organizzazioni si affidano al suo modello di sicurezza. Tra gli usi non commericiali di OpenBSD si nota l’Istituto Nazionale Fisica Nucleare di Firenze che lo usa come server DNS e come firewall per la propria rete, l’università di Alberta e del Michigan lo usano come intrusion detection system. Molte grandi aziende utilizzano OpenBSD come firewall: Adobe System, SoftQuad Software Inc., Network Security Technologies Inc., e molti ISP come: Anonix, BS Web Serivices, Empire Net, IO Active, Hobbiton.org.



About the Author

Related Posts