
Prova di concetto che dimostra un attacco side-channel tramite analisi di potenza contro un'implementazione RSA vulnerabile su Arduino (Atmega328P), con configurazione hardware dettagliata e metodologia di misurazione.
Recentemente ho osservato persone che implementano la crittografia per Arduino da sole, come descritto in questo topic su stackoverflow:
https://stackoverflow.com/questions/39189065/rsa-encryption-decryption-functions-for-arduino
Diverse di queste implementazioni si trovano su Internet, alcune peraltro in librerie ben note.
Ho deciso di realizzare questa piccola PoC (Proof of concept) per mostrare perché è importante non solo non inventare il proprio algoritmo crittografico, ma anche utilizzare un'implementazione robusta di tali algoritmi.
Questa PoC esegue un attacco a canale laterale (attacco di analisi del consumo) contro una cattiva implementazione di una routine ausiliaria utilizzata nell'implementazione RSA (esponenziazione veloce).
Un attacco a canale laterale è un metodo per compromettere un sistema crittografico sfruttando la fuga indiretta di informazioni, piuttosto che attaccare direttamente l'algoritmo crittografico o il protocollo stesso.
Questo tipo di fuga può provenire da varie fonti come informazioni temporali, consumo energetico, emissioni elettromagnetiche o persino suoni.
Tali attacchi possono essere molto efficaci nel compromettere sistemi crittografici come RSA senza richiedere all'attaccante di risolvere i problemi matematici sottostanti che garantiscono la sicurezza dello schema crittografico (Kocher, Jaffe, & Jun, 1999).
Questo documento effettuerà un attacco di analisi del consumo su una nota vulnerabilità in un'implementazione dell'algoritmo RSA in un firmware per Arduino (Atmega328P).
Nota: l'ho fatto di fretta, per favore perdonate gli errori di ortografia/grammatica che eventualmente troverete.
Gli attacchi di analisi del consumo implicano la misurazione del consumo energetico di un dispositivo durante le operazioni crittografiche.
La Differential Power Analysis (DPA) prevede l'analisi statistica dei modelli di consumo energetico su più operazioni crittografiche per estrarre segreti, rendendola più sofisticata della Simple Power Analysis (SPA), che correla direttamente le fluttuazioni di potenza con specifiche operazioni crittografiche per dedurre segreti.
La Differential Power Analysis (DPA) e la Simple Power Analysis (SPA) possono essere utilizzate per estrarre chiavi private analizzando i modelli di consumo energetico durante i calcoli RSA.
Questi attacchi possono rivelare la chiave privata identificando modelli di consumo energetico distinti associati a diversi bit della chiave (Kocher, Jaffe, & Jun, 1999).
RSA (Rivest-Shamir-Adleman) è un algoritmo di crittografia a chiave pubblica ampiamente utilizzato, chiamato così dai suoi inventori: Ron Rivest, Adi Shamir e Leonard Adleman, che lo introdussero nel 1977 (Paar & Pelzl, 2010).
Rimane uno dei metodi più sicuri per trasmettere dati in modo sicuro su Internet.
Uno dei fondamenti della sicurezza di RSA risiede nella difficoltà di fattorizzare grandi numeri composti nei loro fattori primi (Menezes, van Oorschot, & Vanstone, 1996).
Questo problema, noto come problema della fattorizzazione, consiste nel trovare i numeri primi che moltiplicati insieme formano un dato numero grande.
La crittografia RSA si basa sul presupposto che questo problema di fattorizzazione sia computazionalmente abbastanza difficile da rendere impraticabile rompere la crittografia fattorizzando il modulo nei suoi fattori primi (Menezes, van Oorschot, & Vanstone, 1996).
La Figura 1 illustra il processo di crittografia e decrittografia RSA utilizzando un semplice esempio.

Figura 1 - Esempio RSA.
Si noti che in questo caso 3 e 33 sono pubblici. Il numero 7 nell'esempio è la chiave privata.
La funzione Phi (N), la funzione totient di Eulero, calcola tutti i numeri coprimi nell'intervallo da 1 a 33.
Il valore 33 si ottiene dalla moltiplicazione di P e Q; in questo caso, 11 moltiplicato per 3.
Il risultato della funzione Phi si ottiene moltiplicando (P - 1) per (Q - 1); in questo caso, 10 moltiplicato per 2.
L'operazione e<sup>-1</sup> mod 20 denota l'operazione di inverso modulare (Menezes, van Oorschot, & Vanstone, 1996).
Nota: Se si desidera approfondire RSA, cosa non necessaria per comprendere questo documento. Nel repository è presente una breve introduzione a queste operazioni di base della teoria dei numeri, il file number_theory.md. La spiegazione può migliorare la comprensione delle operazioni RSA.
L'esperimento ha utilizzato un oscilloscopio DS1102 (presentato nella Figura 2) prodotto da Rigol.
Il manuale dell'oscilloscopio si trova nei riferimenti (RIGOL Technologies, Inc., 2017).
È stato utilizzato anche un alimentatore generico (presentato nella Figura 3).

Figura 2 - Oscilloscopio utilizzato nell'esperimento.

Figura 3 - Alimentatore utilizzato nell'esperimento.
La legge di Ohm è un principio fondamentale nel campo dell'ingegneria elettrica e della fisica.
Essa afferma che la corrente che scorre attraverso un conduttore tra due punti è direttamente proporzionale alla tensione tra i due punti e inversamente proporzionale alla resistenza tra di essi (Boylestad, 2015).
La Figura 4 mostra un circuito e la legge di Ohm.

Figura 4 - Illustrazione della legge di Ohm.
La legge di Ohm implica che se si aumenta la tensione attraverso un conduttore, la corrente aumenterà, a condizione che la resistenza rimanga costante (Johnson & Hilburn, 2013). La Figura 5 presenta un esempio di applicazione della legge di Ohm il cui obiettivo è trovare la corrente nel circuito.

Figura 5 - Esempio della legge di Ohm.
La legge di Kirchhoff delle tensioni (KVL) è un principio fondamentale nell'ingegneria elettrica e nella fisica (Boylestad, 2015).
Essa afferma che la somma di tutte le differenze di potenziale elettrico (tensioni) attorno a qualsiasi rete chiusa o anello è zero (Boylestad, 2015).
La Figura 6 illustra la legge di Kirchhoff delle tensioni.

Figura 6 - Illustrazione della legge di Kirchhoff.
Un esempio di applicazione della legge di Kirchhoff è mostrato nella Figura 7 per trovare la corrente attraverso i resistori R1 e R2.

Figura 7 - Esempio della legge di Kirchhoff.
Il partitore di tensione è una conseguenza della legge di Kirchhoff delle tensioni (KVL) e fornisce un modo per calcolare la Vout, che è la tensione tra il resistore R1 e R2.
La formula del partitore di tensione è presentata nella Figura 8.
Un esempio di applicazione del partitore di tensione è mostrato nella Figura 9.

Figura 8 - Illustrazione del partitore di tensione.

Figura 9 - Esempio di partitore di tensione.
Un resistore shunt è un resistore di basso valore posto in serie con l'alimentazione del circuito per misurare la corrente che scorre attraverso il circuito.
L'uso di uno shunt per misurare la corrente è una delle tecniche utilizzate nei moderni multimetri (Boylestad, 2015).
Misurando la caduta di tensione attraverso il resistore shunt e conoscendo la sua resistenza, si hanno informazioni sufficienti per calcolare la corrente utilizzando la legge di Ohm.
Per misurare il consumo di corrente di un dispositivo Arduino, è necessario posizionare un resistore shunt in serie con VCC (positivo).
Il modo in cui verrà collegato è presentato nella Figura 10.
Nota 1: Si noti che in questa PoC, invece di utilizzare la scheda Arduino Uno, il target (microcontrollore atmega328p) viene trasferito su una breadboard separata, come presentato nella Figura 11. Ciò consente di manipolare più facilmente i pin del microcontrollore senza necessità di saldatura.
Nota 2: Se non sai come fare, il mio articolo precedente che mostra come funziona il glitching insegna come farlo e può essere trovato su https://github.com/lord-feistel/hardware_hacking_lab)

Figura 10 - Shunt con Arduino.

Figura 11 - Circuito dello shunt sulla breadboard.
Per dimostrare la misurazione del consumo di corrente utilizzando un resistore shunt, un LED (Sedra & Smith, 2014) verrà collegato al GPIO del microcontrollore (Figura 12) e l'oscilloscopio verrà utilizzato per osservare come ciò influisce sul consumo energetico attraverso il resistore shunt nelle situazioni in cui il LED è acceso o spento.
Si osservi che per estrarre la chiave o osservare l'effetto del carico sul consumo energetico non è necessario utilizzare la legge di Ohm per ottenere la corrente, ma è già sufficiente la sola caduta di tensione (Johnson & Hilburn, 2013).

Figura 12 - Misurazione della potenza.
Per osservarlo meglio, si prega di controllare il Video 1 che mostra la caduta di tensione quando il LED è acceso.
Video 1 - Caduta di tensione dovuta al consumo del LED.
Il seguente codice è stato utilizzato per far lampeggiare il LED. Si trova anche in questo repository.```C const int PIN_CHARGE = 9 ; void setup() { pinMode(PIN_CHARGE, OUTPUT);
}
void loop() {
digitalWrite(PIN_CHARGE, HIGH);
delay(10);
digitalWrite(PIN_CHARGE, LOW);
delay(10);
}
È importante sottolineare che questa caduta di tensione si verifica anche quando viene eseguito un calcolo complesso (Kocher, Jaffe, & Jun, 1999).
Il seguente codice causa la caduta di tensione presentata nella **Figura 13**```C
void setup() {
}
void loop() {
volatile unsigned long i = 0;
i = ((i + 1) * (i - 1) + (i * i) - (i / 2) * (i % 3) + (i * i * i * i)) * ((i + 2) * (i - 2) + (i * i) - (i / 3) * (i % 5) + (i * i * i * i));
delayMicroseconds(100);
}
Se la caduta di tensione riflette il calcolo, può quindi essere utilizzata per determinare i dati in fase di elaborazione.

Figura 13 - Consumo energetico nel calcolo pesante.
Il metodo convenzionale per eseguire l'operazione di potenza è moltiplicare la base n volte.
Supponiamo che 23 dia come risultato 2*2*2 poiché 2 è la base e 3 è n.
Funziona molto bene, ma non in modo sufficientemente efficiente per rendere fattibile RSA.
Per ottenere una tale implementazione si utilizza l'algoritmo di esponenziazione veloce.
L'esponenziazione veloce, nota anche come esponenziazione per quadratura, è un metodo efficiente per elevare un numero a potenza.
Di seguito si può trovare lo pseudo-codice per l'esponenziazione veloce.```C
function fast_exponentiation(a, b): result = 1 base = a exponent = b
while exponent > 0:
if (exponent % 2 == 1): // If exponent is odd
result = result * base
base = base * base // Square the base
exponent = exponent // 2 // Divide exponent by 2
return result
.
I passi dell'esponenziazione veloce di 2<sup>4</sup> si trovano nella **Tabella 1**
| Iterazione | Valore base | Esponente in binario | Operazione | Risultato |
|-----------|--------------|----------------------------|-----------|---------------------------|
| Iniziale | 2 | 100 | Inizio | 1 |
| 1 | 4 | 010 | Quadrato | 1 |
| 2 | 16 | 001 | Quadrato | 1 |
| 3 | 256 | 000 | Moltiplica | 16 |
| Finale | - | - | Fine | 16 |
**Tabella 1** - Iterazioni dell'esponenziazione veloce di 2<sup>4</sup>.
Di seguito viene spiegato il processo:```
- **Initialization:**
Start with base = 2 , exponent = 4 ( binary 100) , result = 1.
- **Iteration 1:** exponent = 4 (binary 100, even)
Square base to get 4 .
result remains 1.
- **Iteration 2:** exponent = 2 (binary 010, even)
Square base to get 16 .
result remains 1.
- **Iteration 3:** exponent = 1 (binary: 001, odd)
Multiply result by a = 16 to get 16.
result becomes 16.
- **Final:** n = 0 (binary: 000)
The loop ends with result = 16.
Nota che per numeri più piccoli non cambia nulla o peggiora, tuttavia per numeri grandi si ottiene un miglioramento significativo nell'efficienza.
Riduce il numero di operazioni moltiplicative rispetto all'approccio ingenuo, il che è particolarmente utile per esponenti grandi.
Tabella 2 mostra un confronto delle iterazioni per un tale numero usando l'esponenziazione ingenua e l'esponenziazione veloce.
L'esponenziazione veloce è fondamentale in RSA sia per i processi di cifratura che di decifratura, poiché questi processi implicano l'elevamento di grandi numeri a grandi potenze modulo qualche altro grande numero (Paar & Pelzl, 2010).
Come presentato nella sezione esempio RSA, la chiave è l'esponente e di solito sarà un numero molto grande.
Tabella 2 - Confronto dell'efficienza tra esponenziazione convenzionale ed esponenziazione veloce.
Un'esponenziazione veloce è stata implementata in Arduino e caricata nell'Atmega328P. Trattandosi di un PoC, l'abbiamo implementata nel modo più semplice per essere visualizzata.
Ad esempio, di solito si utilizza l'operazione di shift su una variabile intera, ma abbiamo implementato l'esponente come array per essere meglio compreso.
Si noti che l'esponente che rappresenta la chiave è l'array {0, 1, 0, 1, 0, 1, 0, 1} che creerà un pattern nella misura acquisita dall'oscilloscopio come prova del suo funzionamento.```C
#include <Arduino.h>
volatile long long dumb_vulnerableExponentiation(volatile long long base, const volatile int* exponentArray, volatile int arrayLength, volatile long long modulo) { volatile long long result = 1; base %= modulo;
for (volatile int i = 0; i < arrayLength; ++i) {
result = (result * result) % modulo;
if (exponentArray[i] == 1) {
result = (result * base) % modulo;
}
}
return result;
}
void setup() { }
void loop() { volatile long long base = 3; volatile long long modulo = 1000000007; const volatile int exponentArray[] = {0, 1, 0, 1, 0, 1, 0, 1}; volatile int arrayLength = sizeof(exponentArray) / sizeof(exponentArray[0]); delay(2); volatile long long result = dumb_vulnerableExponentiation(base, exponentArray, arrayLength, modulo); }
### Risultati
Come presentato all'inizio, per l'operazione di cifratura e decifratura la chiave è l'esponente, quindi scoprendo l'esponente la chiave RSA viene esposta.
Utilizzando l'hardware menzionato in precedenza è possibile vedere lo spettro del consumo energetico sull'oscilloscopio come presentato in **Figura* 14* e **Figura 15**
I periodi in cui la tensione scende per un lungo periodo significano che il bit `1`di della chiave è in elaborazione, altrimenti è il bit `0`.
Si noti che quando l'esponente è pari, c'è una moltiplicazione extra che fa sì che il calo di energia richieda più tempo, esponendo informazioni sulla chiave.
**Video 2** mostra l'acquisizione della chiave. Per capire come regolare il periodo e l'ampiezza, fare riferimento al manuale dell'oscilloscopio.

**Figura 14** - Acquisizione della chiave

**Figura 15** - Esposizione degli 0 e 1 della chiave utilizzando l'oscilloscopio
[](https://youtu.be/MBZ1abtTN_k)
**Video 2** - Acquisizione della chiave con oscilloscopio.
Un tale attacco può essere utilizzato in uno scenario in cui il microcontrollore utilizza una libreria ben nota, tuttavia il firmware è bloccato, non permettendo all'attaccante di ottenere la chiave direttamente dalla memoria.
Questo tipo di attacco può essere utilizzato anche contro l'hardware.
### Conclusione
Implementare un proprio sistema di cifratura RSA (Rivest-Shamir-Adleman) è fortemente sconsigliato per diverse ragioni critiche, in particolare la vulnerabilità ad attacchi sofisticati come gli attacchi di analisi del consumo energetico.
La cifratura RSA, sebbene matematicamente robusta quando implementata correttamente, richiede un'attenzione meticolosa ai dettagli nella sua implementazione per garantire la sicurezza.
Anche piccoli difetti o sviste nell'implementazione possono inavvertitamente divulgare informazioni sulla chiave privata, compromettendo l'intera sicurezza del sistema.
Inoltre, le librerie e i framework crittografici consolidati sono sottoposti a un rigoroso esame e test da parte della comunità di sicurezza, garantendo che siano resistenti contro attacchi e vulnerabilità noti. L'utilizzo di queste librerie verificate non solo fa risparmiare tempo e sforzo, ma riduce anche significativamente il rischio di introdurre involontariamente vulnerabilità nel sistema.
### Riferimenti
1. Understanding Cryptography - Paar, C., & Pelzl, J. (2010). **Understanding Cryptography**. Springer.
2. Handbook of Applied Cryptography - Menezes, A. J., van Oorschot, P. C., & Vanstone, S. A. (1996). **Handbook of Applied Cryptography**. CRC Press.
3. Differential Power Analysis - Kocher, P., Jaffe, J., & Jun, B. (1999). **Differential Power Analysis**. Proceedings of CRYPTO '99, Lecture Notes in Computer Science, vol 1666. Springer, Berlin, Heidelberg. DOI: 10.1007/3-540-48405-1_25.
4. DS1102 Oscilloscope Datasheet - RIGOL Technologies, Inc. (2017). **DS1000E, DS1000D Series Digital Oscilloscope Datasheet**. Recuperato da [RIGOL Datasheet](https://beyondmeasure.rigoltech.com/acton/attachment/1579/f-03b8/1/-/-/-/-/DS1000E_DS1000D_DataSheet_EN.pdf)
5. Introductory Circuit Analysis - Boylestad, R. L. (2015). **Introductory Circuit Analysis** (13th ed.). Pearson.
6. Fundamentals of Electrical Circuits - Johnson, D., & Hilburn, J. L. (2013). **Fundamentals of Electrical Circuits**. McGraw-Hill Education.
7. Microelectronic Circuits - Sedra, A. S., & Smith, K. C. (2014). **Microelectronic Circuits** (7th ed.). Oxford University Press.
| Esponente (b) | Binario (b) | Operazioni di esponenziazione convenzionale | Operazioni di esponenziazione veloce |
|---|
| 1 | 1 | 1 | 1 |
| 2 | 10 | 1 | 1 |
| 4 | 100 | 3 | 2 |
| 8 | 1000 | 7 | 3 |
| 16 | 10000 | 15 | 4 |
| 32 | 100000 | 31 | 5 |
| 64 | 1000000 | 63 | 6 |
| 128 | 10000000 | 127 | 7 |
| 256 | 100000000 | 255 | 8 |
| 512 | 1000000000 | 511 | 9 |
| 1024 | 10000000000 | 1023 | 10 |