Advances in Microarchitectural Attacks
Yuval Yarom
Flush+Reload on Square-and-Multiply
40ns
Clock-based countermeasures
3
Clock-based countermeasures
4
Reducing Timer Resolution
5
Measure this
With this
Reducing Timer Resolution
6
Alternative clocks
7
Low resolution clocks
8
[SMGM17] M. Schwarz et al. “Fantastic timers and where to find them …”, FC 2017
[SAO+21] A. Shusterman et al. “Prime+Probe 1, JavaScript 0 …”, USENIX Sec 2021
[KS16] D. Kohlbrenner and H. Shacham, “Trusted browsers for uncertain times”, USENIX Sec 2016
Problem: Reduced timer resolution
9
40 ns
25 μs
Problem: Reduced timer resolution
10
Detection
Rate
Logical State of Cache
11
F F F T F F F F T F F F F
Processor
Memory
Cache
F
T
Conditional access
12
Make sure *in is 0
if (*in == 0)
return;
a = *out
Speculative execution
13
if (*in == 0)
return;
a = *out
May be executed even if *in == 0
Make sure *in is 0
Train branch to mispredict
Conditional Speculative �Execution
14
if (*in == 0)
return;
a = *out
*in | *out |
TRUE | FALSE |
FALSE | TRUE |
out 🡨 NOT(in)
Make sure *in is 0
Train branch to mispredict
Other functions
if (*in1 + *in2 == 0)
return;
a = *out
*in1 | *in2 | *out |
FALSE | FALSE | TRUE |
FALSE | TRUE | TRUE |
TRUE | FALSE | TRUE |
TRUE | TRUE | FALSE |
if (*in1 == 0)
return;
if (*in2 == 0)
return;
a = *out
*in1 | *in2 | *out |
FALSE | FALSE | TRUE |
FALSE | TRUE | FALSE |
TRUE | FALSE | FALSE |
TRUE | TRUE | FALSE |
out 🡨 NOR(in1, in2)
out 🡨 NAND(in1, in2)
Multiple outputs
16
if (*in == 0)
return;
a = *out1 + *out2
Minority Report
17
if (*in1 + *in2 == 0)
return;
if (*in2 + *in3 == 0)
return;
if (*in1 + *in3 == 0)
return;
a = *out
*in1 | *in2 | *in3 | *out |
FALSE | FALSE | FALSE | TRUE |
FALSE | FALSE | TRUE | TRUE |
FALSE | TRUE | FALSE | TRUE |
FALSE | TRUE | TRUE | FALSE |
TRUE | FALSE | FALSE | TRUE |
TRUE | FALSE | TRUE | FALSE |
TRUE | TRUE | FALSE | FALSE |
TRUE | TRUE | TRUE | FALSE |
Circuits
18
Amplification
19
if (*in == 0)
return;
a = *out1 + *out2 +
*out3 + *out4 +
*out5 + *out6 +
*out7 + *out8;
High Resolution Prime+Probe
20
Crypto and Speculative Execution
21
Background
22
Background
23
Motivating Example
key = ...�state = message�for (i from 0 to 8) {� bit = 1 << i� if (key & bit) { state ^= bit }�}�ciphertext = state
24
Motivating Example
key = ...�state = message�for (i from 0 to 8) {� bit = 1 << i� if (key & bit) { state ^= bit }�}�ciphertext = state
25
Applies a one-time-pad one bit a time
Motivating Example
key = ...�state = message�for (i from 0 to 8) {� bit = 1 << i� if (key & bit) { state ^= bit }�}�ciphertext = state
26
Applies a one-time-pad one bit a time
Branches on key material
Background
27
Influences
Background
28
Influences
Infer
Constant-Time Programming
29
Motivating Example
key = ...�state = message�for (i from 0 to 8) {� bit = 1 << i� state ^= (key & bit)�}�ciphertext = state
30
No longer uses a branch
Motivating Example
secret key = ...�secret state = message�for (i from 0 to 8) {� public bit = 1 << i� state ^= (key & bit)�}�public ciphertext = state
31
Motivating Example
secret key = ...�secret state = message�for (i from 0 to 8) {� public bit = 1 << i� if (key & bit) { state ^= bit }�}�public ciphertext = state
32
Motivating Example
secret key = ...�secret state = message�for (i from 0 to 8) {� public bit = 1 << i� if (key & bit) { state ^= bit }�}�public ciphertext = state
33
Motivating Example
secret key = ...�secret state = message�for (i from 0 to 8) {� public bit = 1 << i� state ^= (key & bit)�}�public ciphertext = state
34
Flow of Values
Public-Typed Values
Secret-Typed Values
35
Don’t care
Constant Time
Outside World
Declassification
secret key = ...�secret state = message�for (i from 0 to 8) {� public bit = 1 << i� state ^= (key & bit)�}�public ciphertext = state
36
Declassification
secret key = ...�secret state = message�for (i from 0 to 8) {� public bit = 1 << i� state ^= (key & bit)�}�public ciphertext = state
37
Declassification
secret key = ...�secret state = message�for (i from 0 to 8) {� public bit = 1 << i� state ^= (key & bit)�}�public ciphertext = state
38
Declassification
secret key = ...�secret state = message�for (i from 0 to 8) {� public bit = 1 << i� state ^= (key & bit)�}�public ciphertext = declassify(state)
39
Flow of Values
Public-Typed Values
Secret-Typed Values
40
Constant Time
Outside World
Flow of Values
Public-Typed Values
Secret-Typed Values
41
Constant Time
Outside World
declassify
Flow of Values
Public-Typed Values
Secret-Typed Values
42
Constant Time
Outside World
declassify
43
Spectre Variant 1
if (index < array.length) {
public value = array[index]
leak(value)
}
44
Spectre Variant 1
if (index < array.length) {
public value = array[index]
leak(value)
}
45
Body executed even if condition is false
Spectre Variant 1
if (index < array.length) {
public value = array[index]
leak(value)
}
46
Could load a secret
Body executed even if condition is false
Spectre Variant 1
if (index < array.length) {
public value = array[index]
leak(value)
}
47
Could load a secret
Can leak
Body executed even if condition is false
Flow of Values
Public-Typed Values
Secret-Typed Values
48
48
declassify
Constant Time
Outside World
Flow of Values
Public-Typed Values
Secret-Typed Values
49
49
declassify
Constant Time
Outside World
Speculative Load Hardening
50
Speculative Load Hardening
if (index < array.length) {
public value = array[index]
leak(value)
}
51
Speculative Load Hardening
mask = 0
if (index < array.length) {
mask = index < array.length ? mask : -1
public value = array[index] | mask
leak(value)
}
52
Flow of Values
Public-Typed Values
Secret-Typed Values
53
53
declassify
SLH
Constant Time
Outside World
Flow of Values
Public-Typed Values
Secret-Typed Values
54
54
declassify
SLH
Constant Time
Outside World
Speculative Declassification
secret key = ...�secret state = message�for (i from 0 to 8) {� public bit = 1 << i� state ^= (key & bit)�}�public ciphertext = declassify(state)
55
Speculative Declassification
secret key = ...�secret state = message�for (i from 0 to 8) {� public bit = 1 << i� state ^= (key & bit)�}�public ciphertext = declassify(state)
56
Skipped
Speculative Declassification
secret key = ...�secret state = message�for (i from 0 to 8) {� public bit = 1 << i� state ^= (key & bit)�}�public ciphertext = declassify(state)
57
Skipped
Unencrypted
Speculative Declassification
secret key = ...�secret state = message�for (i from 0 to 8) {� public bit = 1 << i� state ^= (key & bit)�}�public ciphertext = declassify(state)
58
Skipped
Unencrypted
Flow of Values
Public-Typed Values
Secret-Typed Values
59
Speculative declassify
SLH
🕑
Constant Time
Outside World
Flow of Values
Public-Typed Values
Secret-Typed Values
60
Speculative declassify
SLH
🕑
Constant Time
Outside World
Real-World Example
secret state = plaintext
state = aes_round(state, *key++)� ...�state = aes_round(state, *key++)�if (rounds == 12) {� ...
}�state = aes_last_round(state, *key++)
public ciphertext = declassify(state)
61
Real-World Example
secret state = plaintext
state = aes_round(state, *key++)� ...�state = aes_round(state, *key++)�if (rounds == 12) {� ...
}�state = aes_last_round(state, *key++)
public ciphertext = declassify(state)
62
Skipped
Real-World Example
secret state = plaintext
state = aes_round(state, *key++)� ...�state = aes_round(state, *key++)�if (rounds == 12) {� ...
}�state = aes_last_round(state, *key++)
public ciphertext = declassify(state)
63
Skipped
Incorrectly encrypted
Real-World Example
secret state = plaintext
state = aes_round(state, *key++)� ...�state = aes_round(state, *key++)�if (rounds == 12) {� ...
}�state = aes_last_round(state, *key++)
public ciphertext = declassify(state)
64
Skipped
Incorrectly encrypted
Countermeasure
secret key = ...�secret state = message�for (i from 0 to 8) {� public bit = 1 << i� state ^= (key & bit)�}�public ciphertext = declassify(state)
65
Countermeasure
secret key = ...�secret state = message�for (i from 0 to 8) {� public bit = 1 << i� state ^= (key & bit)�}�public ciphertext = declassify(state)
66
Insert speculation fence
Countermeasure
secret key = ...�secret state = message�for (i from 0 to 8) {� public bit = 1 << i� state ^= (key & bit)�}�public ciphertext = declassify(state)
67
Insert speculation fence
Earlier instructions
must execute correctly
Flow of Values
Public-Typed Values
Secret-Typed Values
68
SLH
Constant Time
Outside World
Fenced declassify
Flow of Values
Public-Typed Values
Secret-Typed Values
69
SLH
Constant Time
Outside World
Fenced declassify
Performance
Impact
70
Selective SLH
public array[]
�if (index < array.length) {
...
public value = array[index]
...
leak(value)
}
71
Selective SLH
public array[]
mask = 0�if (index < array.length) {
mask = index < array.length ? mask : -1
...
public value = array[index] | mask
...
leak(value)
}
72
Selective SLH
secret array[]
mask = 0�if (index < array.length) {
mask = index < array.length ? mask : -1
...
secret value = array[index] | mask
...
leak(value)
}
73
Selective SLH
secret array[]
mask = 0�if (index < array.length) {
mask = index < array.length ? mask : -1
...
secret value = array[index] | mask
...
leak(value)
}
74
Selective SLH
secret array[]
mask = 0�if (index < array.length) {
mask = index < array.length ? mask : -1
...
secret value = array[index] | mask
...
leak(value)
}
75
Out of bounds access
Selective SLH
secret array[]
mask = 0�if (index < array.length) {
mask = index < array.length ? mask : -1
...
secret value = array[index] | mask
...
leak(value)
}
76
Out of bounds access
Selective SLH
public array[]
�if (index < array.length) {
...
public value = array[index]
...
leak(value)
}
77
Selective SLH
public array[]
mask = 0�if (index < array.length) {
mask = index < array.length ? mask : -1
...
public value = array[index] | mask
...
leak(value)
}
78
What if (public) array never leaks?
Selective SLH
secret array[]
�if (index < array.length) {
...
secret value = array[index]
...
leak(value)
}
79
Tagging public values that do not leak as secret reduces overhead!!!
Selective SLH
80
Algorithm | SLH Masking Removed |
ChaCha20 (1024B) | ~80% |
Donna-c64 | ~95% |
What if we do not have secret types?
81
Exorcising Spectres
82
Patrignani and Guarnieri, Exorcising Spectres with Secure Compilers, CCS 2021
Spectre - Recap
if (index < array.length) {
value = array[index]
leak(value)
}�secret = recover()
83
Enter speculative execution
Obtain a secret
Leak secret
Recover secret
Speculative�Barriers
if (index < array.length) {
lfence
value = array[index]
leak(value)
}�secret = recover()
84
Enter speculative execution
Obtain a secret
Leak secret
Recover secret
SLH - Recap
if (index < array.length) {
mask = index < array.length ? mask : -1
value = array[index] | mask
leak(value)
}�secret = recover()
85
Enter speculative execution
Obtain a secret
Leak secret
Recover secret
Speculative secrets
86
Type confusion leaks
value = …
isPublic = …
if (isPublic) {
leak(value)
}�secret = recover()
87
Enter speculative execution
Obtain a secret
Leak secret
Recover secret
A concrete example
if (isPublic) {
x = array[value]
}
88
A concrete example – with SLH
if (isPublic) {
mask = isPublic ? mask : -1
x = array[value] | mask
}
89
Still leaks
A concrete example – with SSLH [PG21]
if (isPublic) {
mask = isPublic ? mask : -1
x = *((array + value) | mask)
}
90
*(array+value)�is the same as�array[value]
Supported in LLVM SLH
More SSLH
if (isPublic) {
mask = isPublic ? mask : -1
if (value | mask) {…}
}
91
More SSLH
if (isPublic) {
mask = isPublic ? mask : -1
if (value | mask) {…}
}
92
Observation
93
| LLVM SLH | SSLH | USLH |
Memory Access | | | |
Control Flow | | | |
Instruction Timing | | | |
Observation
94
| LLVM SLH | SSLH | USLH |
Memory Access | ✔ | ✔ | |
Control Flow | — | ✔ | |
Instruction Timing | — | — | |
Leaking instruction timing
95
if (isPublic) {
value = sqrt(value)
value = value*value
value = sqrt(value)
value = value*value
…
}
On i7-10710U:
Sqrtsd + mulsd take:
Leaking speculative instruction timing
96
if (isPublic) {
value = sqrt(value)
value = value*value
value = sqrt(value)
value = value*value
…
}
On i7-10710U:
Sqrtsd + mulsd take:
Misspeculation time is independent of misspeculated code.
Leaking speculative instruction timing
97
if (isPublic) {
value = sqrt(value)
value = value*value
value = sqrt(value)
value = value*value
…
load(fixedAddress)
}
On i7-10710U:
Sqrtsd + mulsd take:
Misspeculation time is independent of misspeculated code.
No dependency?
Load “waits” for a reservation station. Release time depends on prior instructions.
Race between branch resolution and load time.
With 45 pairs, load execution probability is:
Ultimate SLH
98
| LLVM SLH | SSLH | USLH |
Memory Access | ✔ | ✔ | ✔ |
Control Flow | — | ✔ | ✔ |
Instruction Timing | — | — | ✔ |
Countermeasure
99
if (isPublic) {
mask = isPublic ? mask : -1
value = sqrt(value | mask)
value = value*value
value = sqrt(value)
value = value*value
…
load(fixedAddress)
}
Performance
100
Time Cost Normalisation