forked from oasis-tcs/virtio-spec
-
Notifications
You must be signed in to change notification settings - Fork 0
/
virtio-rpmb.tex
290 lines (220 loc) · 12.7 KB
/
virtio-rpmb.tex
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
\section{RPMB Device}\label{sec:Device Types / RPMB Device}
virtio-rpmb is a virtio based RPMB (Replay Protected Memory Block)
device. It is used as a tamper-resistant and anti-replay storage.
The device is driven via requests including read, write, get write
counter and program key, which are submitted via a request queue.
This section relies on definitions from paragraph 6.6.22 of
\hyperref[intro:eMMC]{eMMC}.
\subsection{Device ID}\label{sec:Device Types / RPMB Device / Device ID}
28
\subsection{Virtqueues}\label{sec:Device Types / RPMB Device / Virtqueues}
\begin{description}
\item[0] requestq
\end{description}
\subsection{Feature bits}\label{sec:Device Types / RPMB Device / Feature bits}
None.
\subsection{Device configuration layout}\label{sec:Device Types / RPMB Device / Device configuration layout}
All fields of this configuration are always available and read-only for the driver.
\begin{lstlisting}
struct virtio_rpmb_config {
u8 capacity;
u8 max_wr_cnt;
u8 max_rd_cnt;
}
\end{lstlisting}
\begin{description}
\item[\field{capacity}] is the capacity of the device (expressed in 128KB units).
The values MUST range between 0x00 and 0x80 inclusive.
\item[\field{max_wr_cnt and max_rd_cnt}] are the maximum numbers of RPMB
block count (256B) that can be performed to device in one request. 0 implies
no limitation.
\end{description}
\devicenormative{\subsection}{Device Initialization}{Device Types / RPMB Device / Device Initialization}
\begin{enumerate}
\item The virtqueue is initialized.
\item The device capacity MUST be initialized to a multiple of 128Kbytes and up to
16Mbytes.
\end{enumerate}
\subsection{Device Operation}\label{sec:Device Types / RPMB Device / Device Operation}
The operation of a virtio RPMB device is driven by the requests placed on the virtqueue.
The type of request can be program key (VIRTIO_RPMB_REQ_PROGRAM_KEY),
get write counter (VIRTIO_RPMB_REQ_GET_WRITE_COUNTER),
write (VIRTIO_RPMB_REQ_DATA_WRITE), and read (VIRTIO_RPMB_REQ_DATA_READ).
A program key or write request can also combine with a
result read (VIRTIO_RPMB_REQ_RESULT_READ) for a returned result.
\begin{lstlisting}
/* RPMB Request Types */
#define VIRTIO_RPMB_REQ_PROGRAM_KEY 0x0001
#define VIRTIO_RPMB_REQ_GET_WRITE_COUNTER 0x0002
#define VIRTIO_RPMB_REQ_DATA_WRITE 0x0003
#define VIRTIO_RPMB_REQ_DATA_READ 0x0004
#define VIRTIO_RPMB_REQ_RESULT_READ 0x0005
/* RPMB Response Types */
#define VIRTIO_RPMB_RESP_PROGRAM_KEY 0x0100
#define VIRTIO_RPMB_RESP_GET_COUNTER 0x0200
#define VIRTIO_RPMB_RESP_DATA_WRITE 0x0300
#define VIRTIO_RPMB_RESP_DATA_READ 0x0400
\end{lstlisting}
\begin{description}
\item[\field{VIRTIO_RPMB_REQ_PROGRAM_KEY}] requests for authentication key programming.
If VIRTIO_RPMB_REQ_RESULT_READ is requested, the device returns the RPMB frame with
the response (VIRTIO_RPMB_RESP_PROGRAM_KEY), the calculated MAC and the result.
\item[\field{VIRTIO_RPMB_REQ_GET_WRITE_COUNTER}] requests for reading the write counter.
The device returns the RPMB frame with the response (VIRTIO_RPMB_RESP_GET_COUNTER),
the writer counter, a copy of the nonce received in the request, the calculated
MAC and the result.
\item[\field{VIRTIO_RPMB_REQ_DATA_WRITE}] requests for authenticated data write.
If VIRTIO_RPMB_REQ_RESULT_READ is requested, the device returns the RPMB data
frame with the response (VIRTIO_RPMB_RESP_DATA_WRITE), the incremented counter value,
the data address, the calculated MAC and the result.
\item[\field{VIRTIO_RPMB_REQ_DATA_READ}] requests for authenticated data read.
The device returns the RPMB frame with the response (VIRTIO_RPMB_RESP_DATA_READ),
the block count, a copy of the nonce received in the request, the address,
the data, the calculated MAC and the result.
\item[\field{VIRTIO_RPMB_REQ_RESULT_READ}] requests for a returned result.
It is used following with VIRTIO_RPMB_REQ_PROGRAM_KEY or VIRTIO_RPMB_REQ_DATA_WRITE
request types for a returned result in one or multiple RPMB frames. If it's not
requested, the device will not return result frame to the driver.
\end{description}
\subsubsection{Device Operation: Request Queue}\label{sec:Device Types / RPMB Device / Device Operation / Device Operation: Request Queue}
The request information is delivered in RPMB frame.
The frame is in size of 512B.
\begin{lstlisting}
struct virtio_rpmb_frame {
u8 stuff[196];
u8 key_mac[32];
u8 data[256];
u8 nonce[16];
be32 write_counter;
be16 address;
be16 block_count;
be16 result;
be16 req_resp;
};
/* RPMB Operation Results */
#define VIRTIO_RPMB_RES_OK 0x0000
#define VIRTIO_RPMB_RES_GENERAL_FAILURE 0x0001
#define VIRTIO_RPMB_RES_AUTH_FAILURE 0x0002
#define VIRTIO_RPMB_RES_COUNT_FAILURE 0x0003
#define VIRTIO_RPMB_RES_ADDR_FAILURE 0x0004
#define VIRTIO_RPMB_RES_WRITE_FAILURE 0x0005
#define VIRTIO_RPMB_RES_READ_FAILURE 0x0006
#define VIRTIO_RPMB_RES_NO_AUTH_KEY 0x0007
#define VIRTIO_RPMB_RES_WRITE_COUNTER_EXPIRED 0x0080
\end{lstlisting}
\begin{description}
\item[\field{stuff}] Padding for the frame.
\item[\field{key_mac}] is the authentication key or the message
authentication code (MAC) depending on the request/response type.
If the request is VIRTIO_RPMB_REQ_PROGRAM_KEY, it's used as an
authentication key. Otherwise, it's used as MAC. The MAC is calculated
using HMAC SHA-256. It takes as input a key and a message. The key
used for the MAC calculation is always the 256-bit RPMB authentication
key. The message used as input to the MAC calculation is the
concatenation of the fields in the RPMB frames excluding stuff bytes
and the MAC itself.
\item[\field{data}] is used to be written or read via authenticated
read/write access. It's fixed 256B.
\item[\field{nonce}] is a random number generated by the user for the read
or get write counter requests and copied to the response by the device.
It's used for anti-replay protection.
\item[\field{writer_counter}] is the counter value for the total amount of
the successful authenticated data write requests.
\item[\field{address}] is the address of the data to be written to or read
from the RPMB virtio device. It is the number of the accessed
half sector (256B).
\item[\field{block_count}] is the number of blocks (256B) requested to be
read/written. It's limited by \field{max_wr_cnt} or \field{max_rd_cnt}.
For RPMB read request, one virtio buffer including request command and
the subsequent [\field{block_count}] virtio buffers for response data
are placed in the queue.
For RPMB write request, [\field{block_count}] virtio buffers including
request command and data are placed in the queue.
\item[\field{result}] includes information about the status of access made
to the device. It is written by the device.
\item[\field{req_resp}] is the type of request or response, to/from the device.
\end{description}
\devicenormative{\paragraph}{Device Operation: Program Key}{Device Types / RPMB Device / Device Operation / Device Operation: Program Key}
If VIRTIO_RPMB_REQ_RESULT_READ is requested, the device SHOULD return the
RPMB frame with the response, the calculated MAC and the result:
\begin{enumerate}
\item If the \field{block_count} is not set to 1 then
VIRTIO_RPMB_RES_GENERAL_FAILURE SHOULD be responded as \field{result}.
\item If the programming of authentication key fails,
then VIRTIO_RPMB_RES_WRITE_FAILURE SHOULD be responded as \field{result}.
\item If some other error occurs then returned result
VIRTIO_RPMB_RES_GENERAL_FAILURE SHOULD be responded as \field{result}.
\item The \field{req_resp} value VIRTIO_RPMB_RESP_PROGRAM_KEY SHOULD be responded.
\end{enumerate}
\devicenormative{\paragraph}{Device Operation: Get Write Counter}{Device Types / RPMB Device / Device Operation / Device Operation: Get Write Counter}
If the authentication key is not yet programmed then VIRTIO_RPMB_RES_NO_AUTH_KEY
SHOULD be returned in \field{result}.
If block count has not been set to 1 then VIRTIO_RPMB_RES_GENERAL_FAILURE
SHOULD be responded as \field{result}.
The \field{req_resp} value VIRTIO_RPMB_RESP_GET_COUNTER SHOULD be responded.
\devicenormative{\paragraph}{Device Operation: Data Write}{Device Types / RPMB Device / Device Operation / Device Operation: Data Write}
If VIRTIO_RPMB_REQ_RESULT_READ is requested, the device SHOULD return the RPMB data
frame with the response VIRTIO_RPMB_RESP_DATA_WRITE, the incremented counter value,
the data address, the calculated MAC and the result:
\begin{enumerate}
\item If the authentication key is not yet programmed,
then VIRTIO_RPMB_RES_NO_AUTH_KEY SHOULD be returned in \field{result}.
\item If block count is zero or greater than \field{max_wr_cnt} then
VIRTIO_RPMB_RES_GENERAL_FAILURE SHOULD be responded.
\item The device MUST check whether the write counter has expired.
If the write counter is expired then the \field{result} SHOULD be set to
VIRTIO_RPMB_RES_WRITE_COUNTER_EXPIRED.
\item If there is an error in the address (out of range) then the \field{result}
SHOULD be set to VIRTIO_RPMB_RES_ADDR_FAILURE.
\item The device MUST calculate the MAC taking authentication key and frame as input,
and compare this with the MAC in the request. If the two MAC’s are different
then VIRTIO_RPMB_RES_AUTH_FAILURE SHOULD be returned in \field{result}.
\item If the writer counter in the request is different from the one maintained
by the device then VIRTIO_RPMB_RES_COUNT_FAILURE SHOULD be returned in \field{result}.
\item If the MAC and write counter comparisons are matched then the write request
is considered to be authenticated. The data from the request SHOULD be written to the
address indicated in the request and the write counter SHOULD be incremented by 1.
\item If the write fails then the \field{result} SHOULD be VIRTIO_RPMB_RES_WRITE_FAILURE.
\item If some other error occurs during the writing procedure then the \field{result}
SHOULD be VIRTIO_RPMB_RES_GENERAL_FAILURE.
\item The \field{req_resp} value VIRTIO_RPMB_RESP_DATA_WRITE SHOULD be responded.
\end{enumerate}
\devicenormative{\paragraph}{Device Operation: Data Read}{Device Types / RPMB Device / Device Operation / Device Operation: Data Read}
\begin{enumerate}
\item If the authentication key is not yet programmed then
VIRTIO_RPMB_RES_NO_AUTH_KEY SHOULD be returned in \field{result}.
\item If block count is zero or greater than \field{max_rd_cnt} then
VIRTIO_RPMB_RES_GENERAL_FAILURE SHOULD be responded as \field{result}.
\item If there is an error in the address (out of range) then the
\field{result} SHOULD be set to VIRTIO_RPMB_RES_ADDR_FAILURE.
\item If data fetch from addressed location inside the device fails
then the \field{result} SHOULD be VIRTIO_RPMB_RES_READ_FAILURE.
\item If some other error occurs during the read procedure then the
\field{result} SHOULD be VIRTIO_RPMB_RES_GENERAL_FAILURE.
\item The device SHOULD respond with \field{block_count} frames containing the data and \field{req_resp} value set to VIRTIO_RPMB_RESP_DATA_READ.
\end{enumerate}
\devicenormative{\paragraph}{Device Operation: Result Read}{Device Types / RPMB Device / Device Operation / Device Operation: Result Read}
If the \field{block_count} has not been set to 1 of VIRTIO_RPMB_REQ_RESULT_READ
request then VIRTIO_RPMB_RES_GENERAL_FAILURE SHOULD be responded as \field{result}.
\drivernormative{\subsubsection}{Device Operation}{Device Types / RPMB Device / Device Operation}
The RPMB frames MUST not be packed by the driver.
The driver MUST configure, initialize and format virtqueue for the RPMB requests received from its caller then send it to the device.
\devicenormative{\subsubsection}{Device Operation}{Device Types / RPMB Device / Device Operation}
The virtio-rpmb device could be backed in a number of ways. It SHOULD
keep consistent behaviors with hardware as described in paragraph
6.6.22 of \hyperref[intro:eMMC]{eMMC}.
Some elements are maintained by the device:
\begin{enumerate}
\item The device MUST maintain a one-time programmable authentication key.
It cannot be overwritten, erased or read. The key is used to
authenticate the accesses when MAC is calculated. This key MUST be
kept regardless of device reset or reboot.
\item The device MUST maintain a read-only monotonic write counter. It
MUST be initialized to zero and added by one automatically along with
successful write operation. The value cannot be reset. After
the counter has reached its maximum value 0xFFFF FFFF, it will
not be incremented anymore. This counter MUST be kept regardless
of device reset or reboot.
\item The device MUST maintain the data for read/write via authenticated
access.
\end{enumerate}