Protezione della comunicazione tra sistemi embedded limitati
Attualmente sto cercando di rafforzare la comunicazione su un canale di comunicazione fisico limitato su un sistema embedded.
Lo scenario
Penso che il sistema sia piuttosto tipico per piccole applicazioni embedded:
I sistemi embedded coinvolti sono piccoli microcontrollori senza alcun sistema operativo, che si può presumere essere in un ambiente fisico sicuro. Il canale di connessione è fisicamente accessibile agli aggressori, possono interferire con i messaggi come desiderato.
Sono possibili diversi canali di comunicazione: es. RS485 o RS232. Esiste un protocollo grezzo che gestisce cose come indirizzamento e integrità grezza (ad esempio CRC16 per bitflip) su cui possiamo costruire. Consideralo un TCP lento.
Ogni partner di comunicazione conosce un certificato radice che può fungere da CA e dispone di un proprio certificato univoco (+ chiave) da esso firmato. I certificati sono autofirmati, curva ellittica prime256v1
La libreria mbedTLS è disponibile per questi sistemi (con DH, AES, ..).
La maggior parte delle volte non è disponibile Internet.
I sistemi possono mantenere il tempo e possono creare numeri casuali sufficienti
Voglio raggiungere privacy, autenticità e integrità.
Come potrebbe essere risolto
Una regola nei protocolli crittografici è di non implementarli mai da soli. Sfortunatamente non ho trovato nulla che corrisponda a questo caso d'uso.
Ho anche sfogliato le domande esistenti, ma nulla ha fornito la soluzione completa che stavo cercando.
Infine, in questa risposta, l' implementazione di un proprio protocollo è data come ultima opzione.
Questo è il motivo per cui ho trovato la soluzione descritta di seguito, ma non ne sono del tutto sicuro. Mi sono orientato su questa risposta su come autenticare uno scambio di chiavi Diffie-Hellmann , questa risposta su come controllare l'integrità e questo thread mi ha dato alcune idee su come implementare un tale protocollo .
Protocollo per proteggere la comunicazione
La prima cosa da fare è generare in modo casuale una chiave simmetrica K. La prima cosa inviata è un messaggio di stretta di mano. Ha i seguenti campi:
Campo | Descrizione |
---|---|
DH | Lo scambio di chiavi Diffie-Hellmann msg g K |
Cert | Il certificato (-chain) del dispositivo di invio |
MsgIdNonce | Un valore casuale a 64 bit |
Firma | Una firma del messaggio completo utilizzando la chiave privata di Cert |
Entrambi i dispositivi inviano (e ricevono) tale messaggio.
Quando si riceve un messaggio, si procede come segue:
- Controlla se il certificato è firmato dalla CA prevista (deve essere in catena)
- Controlla se msg è correttamente firmato con cert e la sua chiave
Quando questi controlli hanno esito positivo, i messaggi DH g K inviati e ricevuti vengono utilizzati per calcolare una chiave simmetrica.
Da questo punto in poi, le applicazioni possono inviare messaggi crittografati con AES-CBC. Poiché i messaggi potrebbero essere persi relativamente spesso, IV è sempre nel messaggio.
Questo è il formato del messaggio:
Campo | Descrizione | Crittografato |
---|---|---|
IV | Inizialmente IV casuale per AES | No |
MsgIdNonce | Stretta di mano / Last MsgIdNonce + 1 o + 2 | sì |
Dati dell'applicazione | I dati / comandi da proteggere | sì |
CMAC troncato a 64 bit | MAC per il controllo dell'integrità | sì |
Perché un messaggio sia accettato, deve
- Avere il MsgIdNonce atteso (1 o 2 sopra l'ultimo ricevuto uno) - prevenendo attacchi di replay, consentendo di perdere 1 messaggio
- Avere un CMAC valido per prevenire attacchi all'integrità
- Essere ricevuti max. T secondi dopo l'ultimo messaggio - prevenire attacchi ritardati
Se qualcosa non è come previsto, l'handshake viene inviato di nuovo, quindi il messaggio viene inviato di nuovo con i parametri appena scambiati.
Domande
Sono sulla strada giusta o dovrei provare qualcosa di completamente diverso?
Questo fornisce i miei obiettivi di sicurezza o mi mancano evidenti vulnerabilità qui?
Può funzionare?
Spero che tu possa aiutare me e altri ingegneri embedded ad affrontare problemi simili!
Risposte
Una regola nei protocolli crittografici è di non implementarli mai da soli. Sfortunatamente non ho trovato nulla che corrisponda a questo caso d'uso.
Hai considerato DTLS ? Questo cerca di risolvere lo stesso problema (tranne che per i timestamp; che potrebbero essere aggiunti inserendo il timestamp nel datagramma), e ha già pensato a tutto. Un'altra possibilità sarebbe IPsec; tuttavia DTLS sembra più vicino ad affrontare il problema che hai (a meno che il traffico dati che stai proteggendo non sia traffico IP).
Detto questo, ecco alcune riflessioni sul protocollo che hai delineato:
Cosa succede se due messaggi sequenziali vengono ignorati (ad es. Ricevuti in modo errato)? Le due parti si renderanno conto di ciò che è accaduto o procederanno a eliminare tutti i messaggi successivi (a causa della regola del 'nonce non deve aumentare di più di 2')?
Presumendo che tentino una nuova chiave, come viene coordinato? Se una parte pensa di non aver ancora codificato la chiave e l'altra pensa di sì, cosa succederà ai messaggi crittografati con la vecchia chiave? Troviamo generalmente utile includere un tag "quale chiave è codificata sotto" con il testo cifrato (in DTLS, questa è l '"epoca").
Il tuo canale di comunicazione può riordinare i messaggi? Sospetto che non sia possibile nel tuo caso, ma se può, dovresti pensare a come dovrebbe essere gestito.
Cosa succede se qualcuno inserisce un precedente messaggio di handshake (valido)? In che modo questo confonderà le cose?
Nel percorso di crittografia dei dati, si utilizza la crittografia CBC e l'integrità CMAC. Sebbene questa sia una soluzione praticabile, è soggetta a vari attacchi di imbottitura se non sono integrati correttamente. La moda attuale è quella di utilizzare una modalità AEAD (come GCM o Chacha20 / Poly1305) che fa entrambe le cose.
Il traffico crittografato è unidirezionale o bidirezionale? Se il traffico va in entrambe le direzioni, utilizzi lo stesso set di chiavi per proteggere entrambi i set di traffico?
"Se qualcosa non è come previsto, Handshake viene inviato di nuovo, quindi il messaggio viene inviato di nuovo con i parametri appena scambiati." - come funziona? Se il destinatario ha deciso che non gli è piaciuto il messaggio, come fa il mittente a sapere di inviarlo nuovamente?