cache_security.html
5.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
<html>
<head>
<title>SK Cache Gatekeeping</title>
</head>
<body>
<center>
<h1>SK Cache Gatekeeping</h1>
</center>
<h2>Overview</h2>
The cache handling on SK entrance and exit plays an essential role in
the overall security scheme. Without proper cache handling an attacker
could take control of the secure-mode execution, which would break our
fundamental security assumptions.
<p>
On the flip-side, the cache management for entry and exit is the
costliest portion of SK entry and exit. This document will describe the
rational behind measures taken to insure the cache cannot be used
to compromise the system. Tradeoffs may then be considered between
security risk vs. entry/exit cpu cost to determine exactly what is
implemented.
<h2>Cache Gatekeeping</h2>
The lists below summarize the cache gatekeeping under consideration.
<p>
<b>I-Cache on SK Entry</b><br>
<ul>
<li><i>Security Risk:</i> Running rogue code. <p>
An attacker could fill the icache with arbitrary code using
the cache "fill" instruction, then use cache "index-store-tag"
to provide an internal sram address for the code. Once running
in the SK, some future fetch from icache would result in the
arbitrary code being executed, and this code could dump internal
sram data to dram. (we do eventually switch to
cached execution upon NMI entrance to SK).
<li><i>Resolution:</i>
Issue cache "index-store-tag" (with C0_TAGLO zero'd) over every
icache line to insure all internal code is initially loaded
from memory instead of the cache.
<li><i>CPU cost:</i>
~86usec @ 62.5MHz sysclk.
</ul>
<p>
<b>D-Cache on SK Entry</b><br>
<ul>
<li><i>Security Risk:</i> Running rogue code. <p>
An attacker could fill dcache lines with arbitrary data (which
could be executable code) by first loading the data from main
memory to cache based on index, then using cache "index-store-tag"
to make the data appear to reside in internal sram. This data
may then be used to replace data the SK relies on, or to place
a code snippet into the execution path. The latter could be
accomplished by supplying a physical tag that would cause the
line to be written-back to an executable area. (i.e., some
internal load causing a cache miss would force the write-back
to an address arbitrarily chosen by the attacker).
<li><i>Resolution:</i>
Over every dcache line, check if the line is valid, and then if
the associated tag determines an internal address. If so, zero
the C0_TAGLO register and use cache "index-store-tag" to
invalidate the line.
<li><i>CPU cost:</i>
~260usec @ 62.5MHz sysclk.
</ul>
<p>
<b>I-Cache on SK Exit</b><br>
<ul>
<li><i>Security Risk:</i> Plaintext visible SK code. <p>
If snippets of SK code are left in the icache an attacker could
obtain these in plaintext form. This can be accomplished by
using cache "index-load-tag" to determine the code location
internally, cache "index-store-tag" to set the tag to reference
dram, then cache "hit-write-back" to cause the line to be
written to where the tag points (dram).
<li><i>Resolution:</i>
Issue cache "fill" to every icache line to overwrite sk code
with zeros, then "index-invalidate" over every icache line.
<p>
<i>For now we have decided not to perform this step.</i>
<p>
<li><i>CPU cost:</i>
~86usec @ 62.5MHz sysclk.
</ul>
<p>
<b>D-Cache on SK Exit</b><br>
<ul>
<li><i>Security Risk:</i> Sensitive internal data visible. <p>
The security risk is that any sensitive data in the dcache
would be readable once secure mode is exited (by using
cache "index-store-tag" to tag the line to dram, then
cache "hit-write-back-invalidate" to store to dram).
<li><i>Resolution:</i>
In this case, we cannot simply insure all the dcache
lines are invalidated, since the cache "index-store-tag"
could always be used to set the state back to dirty.
<p>
Since we need to srub (i.e., zero) the iram whenever
the application has iram access, and since all valid internal
dram cache lines must be written back in case they hold
peristant state, the iram scrub is used to force a writeback
of all dcache lines. This works because the chunk of iram
that must be scrubbed is larger than the dcache.
<p>
So, iram is first written with zeros, then the entire
dcache is "index-write-back-invalidate" to writeback
the iram zeros and invalidate the cache lines.
<p>
Just for completeness, here is another method of resolving
this issue (WE DID NOT USE THIS METHOD!). harcode kseg1
addresses for all sensitive (key) data used in the SK (to
insure it does not end up in the dcache). It is dificult to
insure this really hides that data, however, since many api
calls will first copy data to a cached address as part of
setting up calls to lower-level apis. Also, there is still the
possibility that dcache data generated during the computations
performed that use the sensitive kseg1 data could be
sensitive, but this mapping is dificult to predict. Here we
would need to be careful not to slow execution too much by
placing too much data in non-cached storage.
<li><i>CPU cost (for both the "index-write-back-invalidate" and
dword writes to fill the line with zeroes, over each internally
tagged line):</i><br>
~200usec @ 62.5MHz.
</ul>
<p>
Note that because the cost of dcache cleanup on exit is so high, we
may choose to insure this is not needed for timer handling exits.
<p>
Another bit of gatekeeping is that the C0_SR[BEV] bit cannot be set
back to point to external exception vectors until we have actually
issued the write to exit secure mode. Otherwise, and ill-timed
exception would allow arbitrary code in dram to run in secure mode.
WE DECIDED SUCH AN EXCEPTION CAN NOT REASONABLY BE CREATED, SO IGNORE
THIS ISSUE.
</body>
</html>