Discover our 11 fault mitigation patterns
Hardware Fault Attacks are extremely powerful and have a high probability of success. In this paper, Riscure proposes 11 fault mitigation patterns, which are organized into three categories: Resist, Recover, and Respond. The first category increases code resistance to prevent disturbance of the program behavior. Recover patterns prevent insecure behavior after the fault took place. Lastly, to deter attackers of the fault Respond patterns are applied.
Fault Injection is a growing threat to devices and as the number of software vulnerabilities is raising, a systematic fault mitigation approach is necessary. As a leading security lab, Riscure has a long-standing experience and expertise in conducting Fault Injection testing and evaluation. Therefore, we are eager to share our knowledge on how to efficiently apply the patterns and protect the critical code by applying illustrative examples.
Pattern 1. FAULT.CONSTANT.CODING
Problem:
Sensitive data carrying a limited set of values (like phase and state variables) is manipulated by fault injection attacks if they use trivial constant coding (e.g. 0, 1, 0xFF, or -1).
Solution:
Do not use trivial constants for sensitive data. These constants should use nontrivial values with the maximal hamming distance that is unlikely to be set through fault injection. This includes avoiding booleans which are coded in a trivial way (0 / 1). Use complex symbolic constants instead
Example Constant Coding:
int INITIALIZED = 0x5A5A;
int AUTHENTICATED = 0x3EE3;
Pattern 2. FAULT.RANDOM.DELAY
Problem:
Attackers aim to manipulate a specific value or decision.
Solution:
Insert random-length delays throughout code making it much harder to hit a specific moment in software execution.
Example Random Delay:
void delay () { // wait random time
int loops = rand() & 0x3FF; // 10 bit entropy, 1024 possible values
while (–loops >= 0 ) {
loops++;
loops–; // loop counter changes avoid compiler removal of non-functional loop
}
}
3. Recover
Even when fault injection is successful, it is possible to make resilient code that would continue correct execution and prevent exploitation. This includes double-checking to verify value correctness and crypto results, but also double-checking conditional statements, branches, loops, and program flow.
Pattern 3. FAULT.VALUE.CHECK
Problem:
Sensitive data is manipulated by a fault injection attack at any time during program execution.
Solution:
Verify sensitive data. Sensitive data can, for instance, be protected by a checksum. Data protected in this way should be verified at regular intervals. Ideally, the integrity of sensitive data should be verified each time when used.
Example Value Check:
int result = SOME_VALUE; // sensitive value assigned
int checksum = ~ SOME_VALUE; // use complement as checksum
if (checksum == ~result) { // verify checksum //
continue critical code execution
}
Do you want to read the other 8 fault mitigation patterns?
Then download our white paper for free below.