Autore: Evil Titolo: BSH: #2 Bluetooth authentication system Data: 21/04/2005 Http: www.eviltime.com Email: webmaster@eviltime.com ---Sommario------------------------------------------------------------------------- 1. Introduzione 1.1 BSH? 2. Autenticazione e processi di init 2.1 Crittazione 3. Codice utile (e0.c) 4. Problemi di sicurezza 5. Conclusioni 5.1 Referenze ---1. Introduzione------------------------------------------------------------------ In questo testo parlerò di Autenticazione e affini.. ovvero cosa avviene prima che due dispositivi entrino (a tutti gli effetti) in connessione tra loro, vedremo di affrontare le 3 fasi più importanti, gli algoritmi di crittazione usati, i controllori di validità, e i problemi di sicurezza che riguardano in particolare il pre-contatto.. ---1.1 BSH?------------------------------------------------------------------------- BSH è l'acronimo di Bluetooth Security Hacking, questo testo è infatti uno degli approfondimenti che ho in programma di fare sul mio primo testo trattante l'argomento.. * BSH: http://www.eviltime.com/download/my/tutorial/Evil-bluetooth-hacking.txt ---2 Autenticazione e processi di init---------------------------------------------- Prima di parlare della fase di autenticazione 'sicura', citiamo prima i 3 livelli di sicurezza che questa può assumere: 1. Nonsecure mode: Il dispositivo non inizializzerà alcun processo per rendere la connessione sicura, salterà completamente le fasi di autenticazione e crittazione.. 2. Service-level enforced security mode: In questo livello di sicurezza, L2CAP si occuperà di far negare o meno l'accesso ad un servizio da parte di un dispositivo, anche questo in assenza di crittazione dei dati.. 3. Link-level enforced security mode: Il dispositivo inizializza le procedure per la sicurezza ancora prima che la connessione al canale sia effettuata, passando per autenticazione e crittazione, basandosi su una "link key" segreta generata già quando i due dispositivi comunicano per la prima volta. Due dispositivi in processo di autenticazione, si distinguono per compiti, A è il dispositivo Bluetooth che valida l'identità di un altro dispositivo, e B è invece colui che prova la sua stessa identità ad A, questa verifica avviene via un sottoprocesso di init chiamato challenge-response, vediamo ora in modo schematico cosa sta succedendo ai 2 dispositivi: 1. B trasmette ad A un pacchetto di 48bit contenente il suo BD_ADDR 2. A risponde con una chiave random a 128bit chiamata AU_RAND e genera la 32bit SRES* 3. B risponde con la SRES appena calcolata 4. A compara la SRES di B con la sua 5. Se risultano uguali allora si può continuare per stabilire la connessione *SRES: chiave generata usando l'algoritmo di criptazione E1 che sfrutta per la generazione della chiave a 32bit, informazioni quali, il BD_ADDR la chiave di collegamento (link key) e dei valori randomizzati.. La link key, di cui tanto abbiamo parlato poche righe fa, è generata dall'algoritmo E2 in base al PIN inserito dall'utente, in seguito passata in pasto all'algoritmo E3 per la generazione della chiave di criptazione SRES. ---2.1 Criptazione ----------------------------------------------------------------- Il sistema di criptazione usato dal bluetooth, si occupa di criptare i payload di ogni pacchetto, questo algoritmo è chiamato E0 che è rinegoziato per ogni pacchetto scambiato, anche qui abbiamo 3 livelli di criptazione. Nel primo livello niente è criptato; nel secondo livello solo il traffico individuale è criptato escluso il broadcast; nel terzo tutto il traffico viene criptato con la Master Key.. E0 non è un algoritmo troppo difficile da rippare, proprio per questo esiste gia una sua implementazione in C, mi riservo dal spiegare altro su questo algoritmo in quanto credo che non ci possa essere migliore spiegazione di esso nell'articolo http://www.mics.org/micsPublicationsDetail.php?pubno=712 ---2.1 Codice utile (e0.c) --------------------------------------------------------- /* * e0.c * February 8, 2000 Markku-Juhani O. Saarinen * * A software implementation of the BlueTooth encryption algorithm E0. * Complies with test data from "Bluetooth Specification v 1.0 b" * (29 November 1999), Appendix IV. * * This implementation comes with absolutely no warranty. */ #include /* set this flag to get debug output */ #undef DEBUG /* * You may have to adjust these for your platform. */ typedef unsigned char uint8; typedef unsigned long long uint64; /* the finite state machine */ const uint8 e0_fsm[16][16] = { { 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 2 }, { 5, 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 7, 4, 7, 7, 7 }, { 11, 11, 11, 8, 11, 8, 8, 8, 11, 8, 8, 8, 8, 8, 8, 9 }, { 14, 13, 13, 13, 13, 13, 13, 12, 13, 13, 13, 12, 13, 12, 12, 12 }, { 3, 3, 3, 2, 3, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 1 }, { 6, 7, 7, 7, 7, 7, 7, 4, 7, 7, 7, 4, 7, 4, 4, 4 }, { 8, 8, 8, 11, 8, 11, 11, 11, 8, 11, 11, 11, 11, 11, 11, 10 }, { 13, 14, 14, 14, 14, 14, 14, 15, 14, 14, 14, 15, 14, 15, 15, 15 }, { 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 3 }, { 4, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 6, 5, 6, 6, 6 }, { 10, 10, 10, 9, 10, 9, 9, 9, 10, 9, 9, 9, 9, 9, 9, 8 }, { 15, 12, 12, 12, 12, 12, 12, 13, 12, 12, 12, 13, 12, 13, 13, 13 }, { 2, 2, 2, 3, 2, 3, 3, 3, 2, 3, 3, 3, 3, 3, 3, 0 }, { 7, 6, 6, 6, 6, 6, 6, 5, 6, 6, 6, 5, 6, 5, 5, 5 }, { 9, 9, 9, 10, 9, 10, 10, 10, 9, 10, 10, 10, 10, 10, 10, 11 }, { 12, 15, 15, 15, 15, 15, 15, 14, 15, 15, 15, 14, 15, 14, 14, 14 } }; /* the state vriables */ static uint64 e0_r1, e0_r2, e0_r3, e0_r4; static int e0_state, e0_x, e0_z; /* clock the LFSRs and return one bit of keystream */ int e0_clock() { int t; e0_r1 = ((e0_r1 << 1) & 0x1fffffe) | (((e0_r1 >> 7) ^ (e0_r1 >> 11) ^ (e0_r1 >> 19) ^ (e0_r1 >> 24)) & 1); e0_r2 = ((e0_r2 << 1) & 0x7ffffffe) | (((e0_r2 >> 11) ^ (e0_r2 >> 15) ^ (e0_r2 >> 23) ^ (e0_r2 >> 30)) & 1); e0_r3 = ((e0_r3 << 1) & 0x1fffffffell) | (((e0_r3 >> 32) ^ (e0_r3 >> 27) ^ (e0_r3 >> 23) ^ (e0_r3 >> 3)) & 1); e0_r4 = ((e0_r4 << 1) & 0x7ffffffffell) | (((e0_r4 >> 38) ^ (e0_r4 >> 35) ^ (e0_r4 >> 27) ^ (e0_r4 >> 3)) & 1); e0_x = ((e0_r1 >> 23) & 1) | ((e0_r2 >> 22) & 2) | ((e0_r3 >> 29) & 4) | ((e0_r4 >> 28) & 8); e0_state = e0_fsm[e0_state][e0_x]; t = e0_x ^ (e0_x >> 2); t ^= t >> 1; return (t ^ (e0_state >> 2)) & 1; } /* initialize e0 with a 128-bit key, 48-bit address and a 26-bit clock */ void e0_init(uint8 *kc, uint8 *adr, uint8 *cl) { int t, u, state_save; uint64 r1_input, r2_input, r3_input, r4_input; uint8 ztab[16]; /* arrange the keying data into temporary registers */ r1_input = (((uint64) adr[2]) << 41) | (((uint64) cl[1]) << 33) | (((uint64) kc[12]) << 25) | (((uint64) kc[8]) << 17) | (((uint64) kc[4]) << 9) | (((uint64) kc[0]) << 1) | ((((uint64) cl[3]) & 1)); r2_input = (((uint64) adr[3]) << 47) | (((uint64) adr[0]) << 39) | (((uint64) kc[13]) << 31) | (((uint64) kc[9]) << 23) | (((uint64) kc[5]) << 15) | (((uint64) kc[1]) << 7) | (((uint64) (cl[0] & 0x0f)) << 3) | 0x1llu; r3_input = (((uint64) adr[4]) << 41) | (((uint64) cl[2]) << 33) | (((uint64) kc[14]) << 25) | (((uint64) kc[10]) << 17) | (((uint64) kc[6]) << 9) | (((uint64) kc[2]) << 1) | (((uint64) cl[3]) >> 1); r4_input = (((uint64) adr[5]) << 47) | (((uint64) adr[1]) << 39) | (((uint64) kc[15]) << 31) | (((uint64) kc[11]) << 23) | (((uint64) kc[7]) << 15) | (((uint64) kc[3]) << 7) | ((((uint64) cl[0]) >> 4) << 3) | 0x7llu; /* reset the state of e0 */ e0_r1 = 0; e0_r2 = 0; e0_r3 = 0; e0_r4 = 0; e0_state = 0; u = 0; state_save = 0; /* feed in the data. extra input zeroes do not matter. */ for (t = 0; t < 240; t++) { #ifdef DEBUG printf("%3d %07llx %08llx %09llx %010llx " "%d %d %d %d %d %d%d %d%d\n", t, e0_r1, e0_r2, e0_r3, e0_r4, e0_x & 1, (e0_x >> 1) & 1, (e0_x >> 2) & 1, (e0_x >> 3) & 1, e0_z, (e0_state >> 1) & 1, e0_state & 1, (e0_state >> 3) & 1, (e0_state >> 2) & 1); #endif /* reset the state at t = 39 */ if (t < 39) e0_state = 0; /* save state for the key reload thing */ if (t == 238) state_save = e0_state; /* clock LFSRs */ e0_z = e0_clock(); /* the "switches".. feedback is disabled before LFSRs are full */ if (t < 25) e0_r1 ^= e0_r1 & 1; if (t < 31) e0_r2 ^= e0_r2 & 1; if (t < 33) e0_r3 ^= e0_r3 & 1; if (t < 39) e0_r4 ^= e0_r4 & 1; /* mix in the keying data */ e0_r1 ^= r1_input & 1; r1_input >>= 1; e0_r2 ^= r2_input & 1; r2_input >>= 1; e0_r3 ^= r3_input & 1; r3_input >>= 1; e0_r4 ^= r4_input & 1; r4_input >>= 1; /* get the z array.. */ if (t >= 111) { if ((t & 7) == 7) ztab[(t - 112) >> 3] = u & 0xff; u >>= 1; u |= e0_z << 7; } } /* arrange the output into the registers */ e0_r1 = ((uint64) ztab[0]) | (((uint64) ztab[4]) << 8) | (((uint64) ztab[8]) << 16) | ((((uint64) ztab[12]) & 1) << 24); e0_r2 = ((uint64) ztab[1]) | (((uint64) ztab[5]) << 8) | (((uint64) ztab[9]) << 16) | ((((uint64) ztab[12]) >> 1) << 24); e0_r3 = ((uint64) ztab[2]) | (((uint64) ztab[6]) << 8) | (((uint64) ztab[10]) << 16) | (((uint64) ztab[13]) << 24) | ((((uint64) ztab[15]) & 1) << 32); e0_r4 = ((uint64) ztab[3]) | (((uint64) ztab[7]) << 8) | (((uint64) ztab[11]) << 16) | (((uint64) ztab[14]) << 24) | ((((uint64) ztab[15]) >> 1) << 32); /* get the first output symbol.. don't clock! */ e0_x = ((e0_r1 >> 23) & 1) | ((e0_r2 >> 22) & 2) | ((e0_r3 >> 29) & 4) | ((e0_r4 >> 28) & 8); e0_state = e0_fsm[state_save][e0_x]; t = (e0_x >> 2) ^ e0_x; t ^= t >> 1; e0_z = (t ^ (e0_state >> 2)) & 1; } /* get one byte of data from keystream */ uint8 e0_getbyte() { int i, t; t = 0; for (i = 0; i < 8; i++) { #ifdef DEBUG printf(">>%d %07llx %08llx %09llx %010llx " "%d %d %d %d %d %d%d %d%d\n", i, e0_r1, e0_r2, e0_r3, e0_r4, e0_x & 1, (e0_x >> 1) & 1, (e0_x >> 2) & 1, (e0_x >> 3) & 1, e0_z, (e0_state >> 1) & 1, e0_state & 1, (e0_state >> 3) & 1, (e0_state >> 2) & 1); #endif t |= e0_z << i; e0_z = e0_clock(); } return t; } /* test the implementation */ int main(void) { int i, j, t, ok; typedef struct { uint8 kc[16], adr[6], clk[4], ks[16]; } TestSet; TestSet test[4] = { /* First Set of Sample Data (p. 905) */ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00, 0x00 }, { 0x62, 0x96, 0x72, 0x86, 0xc9, 0x2c, 0x3a, 0xe1, 0x8e, 0x18, 0x29, 0x49, 0xd8, 0xed, 0xb1, 0x05 } }, /* Second Set of Sample Data (p. 913) */ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00, 0x03 }, { 0x31, 0xc3, 0xd8, 0x9c, 0xa0, 0x6b, 0x54, 0x32, 0x6c, 0xb1, 0x5a, 0x4b, 0x52, 0xc2, 0x6c, 0x52 } }, /* Third Set of Sample Data (p. 921) */ { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, { 0xff, 0xff, 0xff, 0x03 }, { 0xd1, 0xff, 0xbf, 0x95, 0xb1, 0x6b, 0x9f, 0x9e, 0x43, 0x3d, 0xa6, 0x1a, 0xca, 0xe8, 0x21, 0x72 } }, /* Fourth Set of Sample Data (p. 929) */ { { 0x21, 0x87, 0xf0, 0x4a, 0xba, 0x90, 0x31, 0xd0, 0x78, 0x0d, 0x4c, 0x53, 0xe0, 0x15, 0x3a, 0x63 }, { 0x2c, 0x7f, 0x94, 0x56, 0x0f, 0x1b }, { 0x5f, 0x1a, 0x00, 0x02 }, { 0x94, 0x99, 0x6f, 0xe0, 0xbf, 0x07, 0x74, 0x25, 0x33, 0x39, 0xd8, 0xa1, 0xc0, 0xa5, 0x29, 0x94 } } }; for (i = 0; i < 4; i++) { printf("test set %d ", i + 1); e0_init(test[i].kc, test[i].adr, test[i].clk); ok = 1; for (j = 0; j < 16; j++) { t = e0_getbyte(); printf("%02x ", t); if (t != test[i].ks[j]) ok = 0; } if (ok) printf(" .. ok\n"); else printf(" .. fail\n"); } return 0; } ---4 Problemi di sicurezza --------------------------------------------------------- I problemi più conosciuti in campo sicurezza, riguardano l'algoritmo di criptazione e0, un algoritmo troppo scontato e semplice.. L'autenticazione può essere soggetta ad attacchi man-in-the-middle. Sono permessi i PIN a poche cifre. La link key è facilmente intercettabile, addirittura pubblica dopo il primo uso I tentativi di autenticazione sono infiniti, non ci sono infatti limiti di accessi negati. ---5 Conclusioni ------------------------------------------------------------------- Questo piccolo tutorial dovrebbe esservi stato d'aiuto per la comprensione del primo volume, o comunque per l'approfondimento.. Nessuna pretesa, spero solo che abbiate trovato qualcosa di interessante in questo primo Ext.. ---5.1 Referenze ------------------------------------------------------------------- http://islab.oregonstate.edu/koc/papers/c32relay.pdf http://www.eviltime.com/download/my/tutorial/Evil-bluetooth-hacking.txt