RAM memory looses its contents when it's powered off. However, this
natural erasure process is not instantaneous: it can take several
seconds, or even minutes. It has been demonstrated that cooling down a
memory chip can extend its data retention time to hours, which enables
a type of attack known as cold boot
attack.
This type of attack has been studied mostly on DRAM computer modules.
The Arduino memory, however, is based on SRAM, which is physically very
different from DRAM (a transistor feedback loop vs. a capacitor). There
seems to be very little research on cold boot attacks against SRAM. I
found nonetheless a technical report from the computer laboratory of the
University of Cambridge: Low temperature data remanence in static
RAM, by Sergei
Skorobogatov. Quoting from the conclusion:
Contrary to the established wisdom, there are several chips that
retain data for dangerous periods of time at temperatures above −20°C.
The temperature at which 80% of the data are retained for one minute
varies widely between devices. Some require cooling to at least −50°C,
while others retain data for this period at room temperature.
Retention times can be significantly reduced by shorting VCC to ground
rather than by leaving it floating.
From this perspective I would say that, although the attack seems non
obvious, your secret key is not completely safe even in SRAM. Since the
data retention time varies widely between devices, it could be worth
testing on your Arduino. If possible, I would suggest you overwrite the
key after the signing operation.
Update: I did a quick test on my Arduino Uno, at room temperature,
by just unplugging and plugging back the board. Here is my test code:
// This memory buffer will not be zeroed at startup by the C runtime.
uint8_t __attribute__((section(".noinit"))) buffer[1024];
void setup()
{
Serial.begin(9600);
Serial.println(F("Program started."));
}
void loop()
{
switch (Serial.read()) {
case 'i': // Initialize the buffer with pseudo-random bits.
srand(42);
for (size_t i = 0; i < sizeof buffer; i++)
buffer[i] = rand();
Serial.println(F("Buffer initialized."));
break;
case 'f': // Report number of flipped bits.
int count = 0;
srand(42);
for (size_t i = 0; i < sizeof buffer; i++) {
uint8_t mask = buffer[i] ^ rand();
while (mask) {
count += mask & 1;
mask >>= 1;
}
}
Serial.print(F("Flipped bits: "));
Serial.print(count);
Serial.print(F(" / "));
Serial.println(8 * sizeof buffer);
}
}
And this is the output, with my comments on the right:
Program started. ← fresh boot
Buffer initialized. ← pressed 'i'
Program started. ← pressed the reset button
Flipped bits: 0 / 8192 ← pressed 'f'
Program started. ← unplugged and plugged back
Flipped bits: 4166 / 8192 ← pressed 'f'
It appears the RAM is preserved across a warm reboot (pressing the reset
button), but it is completely lost after a power cycle: half the bits
flipped is a total loss of information. I tried to do this as fast as I
could, which is slightly less than one second. It would seem the SRAM in
the ATmega chips decays pretty fast, at least at room temperature.
Update 2: I found an enlightening story about an unpowered AVR
keeping data in RAM for more than 10 minutes, but only on mornings:
The mystery of the Zombie
RAM.