1 /*
2 * Copyright 2014, Staubli Faverges
3 * Pierre Aubert
4 *
5 * eMMC- Replay Protected Memory Block
6 * According to JEDEC Standard No. 84-A441
7 *
8 * SPDX-License-Identifier: GPL-2.0+
9 */
10
11 #include <config.h>
12 #include <common.h>
13 #include <memalign.h>
14 #include <mmc.h>
15 #include <u-boot/sha256.h>
16 #include "mmc_private.h"
17
18 /* Request codes */
19 #define RPMB_REQ_KEY 1
20 #define RPMB_REQ_WCOUNTER 2
21 #define RPMB_REQ_WRITE_DATA 3
22 #define RPMB_REQ_READ_DATA 4
23 #define RPMB_REQ_STATUS 5
24
25 /* Response code */
26 #define RPMB_RESP_KEY 0x0100
27 #define RPMB_RESP_WCOUNTER 0x0200
28 #define RPMB_RESP_WRITE_DATA 0x0300
29 #define RPMB_RESP_READ_DATA 0x0400
30
31 /* Error codes */
32 #define RPMB_OK 0
33 #define RPMB_ERR_GENERAL 1
34 #define RPMB_ERR_AUTH 2
35 #define RPMB_ERR_COUNTER 3
36 #define RPMB_ERR_ADDRESS 4
37 #define RPMB_ERR_WRITE 5
38 #define RPMB_ERR_READ 6
39 #define RPMB_ERR_KEY 7
40 #define RPMB_ERR_CNT_EXPIRED 0x80
41 #define RPMB_ERR_MSK 0x7
42
43 #define SHA256_BLOCK_SIZE 64
44
45 /* Error messages */
46 static const char * const rpmb_err_msg[] = {
47 "",
48 "General failure",
49 "Authentication failure",
50 "Counter failure",
51 "Address failure",
52 "Write failure",
53 "Read failure",
54 "Authentication key not yet programmed",
55 };
56
mmc_set_blockcount(struct mmc * mmc,unsigned int blockcount,bool is_rel_write)57 static int mmc_set_blockcount(struct mmc *mmc, unsigned int blockcount,
58 bool is_rel_write)
59 {
60 struct mmc_cmd cmd = {0};
61
62 cmd.cmdidx = MMC_CMD_SET_BLOCK_COUNT;
63 cmd.cmdarg = blockcount & 0x0000FFFF;
64 if (is_rel_write)
65 cmd.cmdarg |= 1 << 31;
66 cmd.resp_type = MMC_RSP_R1;
67
68 return mmc_send_cmd(mmc, &cmd, NULL);
69 }
mmc_rpmb_request(struct mmc * mmc,const void * s,unsigned int count,bool is_rel_write)70 static int mmc_rpmb_request(struct mmc *mmc, const void *s,
71 unsigned int count, bool is_rel_write)
72 {
73 struct mmc_cmd cmd = {0};
74 struct mmc_data data;
75 int ret;
76
77 ret = mmc_set_blockcount(mmc, count, is_rel_write);
78 if (ret) {
79 #ifdef CONFIG_MMC_RPMB_TRACE
80 printf("%s:mmc_set_blockcount-> %d\n", __func__, ret);
81 #endif
82 return 1;
83 }
84
85 cmd.cmdidx = MMC_CMD_WRITE_MULTIPLE_BLOCK;
86 cmd.cmdarg = 0;
87 cmd.resp_type = MMC_RSP_R1;
88
89 data.src = (const char *)s;
90 data.blocks = count;
91 data.blocksize = MMC_MAX_BLOCK_LEN;
92 data.flags = MMC_DATA_WRITE;
93
94 ret = mmc_send_cmd(mmc, &cmd, &data);
95 if (ret) {
96 #ifdef CONFIG_MMC_RPMB_TRACE
97 printf("%s:mmc_send_cmd-> %d\n", __func__, ret);
98 #endif
99 return 1;
100 }
101 return 0;
102 }
mmc_rpmb_response(struct mmc * mmc,struct s_rpmb * s,unsigned short expected,unsigned short cnt)103 static int mmc_rpmb_response(struct mmc *mmc, struct s_rpmb *s,
104 unsigned short expected, unsigned short cnt)
105 {
106 struct mmc_cmd cmd = {0};
107 struct mmc_data data;
108 int ret;
109
110 ret = mmc_set_blockcount(mmc, cnt, false);
111 if (ret) {
112 #ifdef CONFIG_MMC_RPMB_TRACE
113 printf("%s:mmc_set_blockcount-> %d\n", __func__, ret);
114 #endif
115 return -1;
116 }
117 cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK;
118 cmd.cmdarg = 0;
119 cmd.resp_type = MMC_RSP_R1;
120
121 data.dest = (char *)s;
122 data.blocks = cnt;
123 data.blocksize = MMC_MAX_BLOCK_LEN;
124 data.flags = MMC_DATA_READ;
125
126 ret = mmc_send_cmd(mmc, &cmd, &data);
127 if (ret) {
128 #ifdef CONFIG_MMC_RPMB_TRACE
129 printf("%s:mmc_send_cmd-> %d\n", __func__, ret);
130 #endif
131 return -1;
132 }
133 /* Check the response and the status */
134 if (be16_to_cpu(s->request) != expected) {
135 #ifdef CONFIG_MMC_RPMB_TRACE
136 printf("%s:response= %x\n", __func__,
137 be16_to_cpu(s->request));
138 #endif
139 return -1;
140 }
141 ret = be16_to_cpu(s->result);
142 if (ret) {
143 printf("%s %s\n", rpmb_err_msg[ret & RPMB_ERR_MSK],
144 (ret & RPMB_ERR_CNT_EXPIRED) ?
145 "Write counter has expired" : "");
146 }
147
148 /* Return the status of the command */
149 return ret;
150 }
mmc_rpmb_status(struct mmc * mmc,unsigned short expected)151 static int mmc_rpmb_status(struct mmc *mmc, unsigned short expected)
152 {
153 ALLOC_CACHE_ALIGN_BUFFER(struct s_rpmb, rpmb_frame, 1);
154
155 memset(rpmb_frame, 0, sizeof(struct s_rpmb));
156 rpmb_frame->request = cpu_to_be16(RPMB_REQ_STATUS);
157 if (mmc_rpmb_request(mmc, rpmb_frame, 1, false))
158 return -1;
159
160 /* Read the result */
161 return mmc_rpmb_response(mmc, rpmb_frame, expected, 1);
162 }
rpmb_hmac(unsigned char * key,unsigned char * buff,int len,unsigned char * output)163 static void rpmb_hmac(unsigned char *key, unsigned char *buff, int len,
164 unsigned char *output)
165 {
166 sha256_context ctx;
167 int i;
168 unsigned char k_ipad[SHA256_BLOCK_SIZE];
169 unsigned char k_opad[SHA256_BLOCK_SIZE];
170
171 sha256_starts(&ctx);
172
173 /* According to RFC 4634, the HMAC transform looks like:
174 SHA(K XOR opad, SHA(K XOR ipad, text))
175
176 where K is an n byte key.
177 ipad is the byte 0x36 repeated blocksize times
178 opad is the byte 0x5c repeated blocksize times
179 and text is the data being protected.
180 */
181
182 for (i = 0; i < RPMB_SZ_MAC; i++) {
183 k_ipad[i] = key[i] ^ 0x36;
184 k_opad[i] = key[i] ^ 0x5c;
185 }
186 /* remaining pad bytes are '\0' XOR'd with ipad and opad values */
187 for ( ; i < SHA256_BLOCK_SIZE; i++) {
188 k_ipad[i] = 0x36;
189 k_opad[i] = 0x5c;
190 }
191 sha256_update(&ctx, k_ipad, SHA256_BLOCK_SIZE);
192 sha256_update(&ctx, buff, len);
193 sha256_finish(&ctx, output);
194
195 /* Init context for second pass */
196 sha256_starts(&ctx);
197
198 /* start with outer pad */
199 sha256_update(&ctx, k_opad, SHA256_BLOCK_SIZE);
200
201 /* then results of 1st hash */
202 sha256_update(&ctx, output, RPMB_SZ_MAC);
203
204 /* finish up 2nd pass */
205 sha256_finish(&ctx, output);
206 }
mmc_rpmb_get_counter(struct mmc * mmc,unsigned long * pcounter)207 int mmc_rpmb_get_counter(struct mmc *mmc, unsigned long *pcounter)
208 {
209 int ret;
210 ALLOC_CACHE_ALIGN_BUFFER(struct s_rpmb, rpmb_frame, 1);
211
212 /* Fill the request */
213 memset(rpmb_frame, 0, sizeof(struct s_rpmb));
214 rpmb_frame->request = cpu_to_be16(RPMB_REQ_WCOUNTER);
215 if (mmc_rpmb_request(mmc, rpmb_frame, 1, false))
216 return -1;
217
218 /* Read the result */
219 ret = mmc_rpmb_response(mmc, rpmb_frame, RPMB_RESP_WCOUNTER, 1);
220 if (ret)
221 return ret;
222
223 *pcounter = be32_to_cpu(rpmb_frame->write_counter);
224 return 0;
225 }
mmc_rpmb_set_key(struct mmc * mmc,void * key)226 int mmc_rpmb_set_key(struct mmc *mmc, void *key)
227 {
228 ALLOC_CACHE_ALIGN_BUFFER(struct s_rpmb, rpmb_frame, 1);
229 /* Fill the request */
230 memset(rpmb_frame, 0, sizeof(struct s_rpmb));
231 rpmb_frame->request = cpu_to_be16(RPMB_REQ_KEY);
232 memcpy(rpmb_frame->mac, key, RPMB_SZ_MAC);
233
234 if (mmc_rpmb_request(mmc, rpmb_frame, 1, true))
235 return -1;
236
237 /* read the operation status */
238 return mmc_rpmb_status(mmc, RPMB_RESP_KEY);
239 }
mmc_rpmb_read(struct mmc * mmc,void * addr,unsigned short blk,unsigned short cnt,unsigned char * key)240 int mmc_rpmb_read(struct mmc *mmc, void *addr, unsigned short blk,
241 unsigned short cnt, unsigned char *key)
242 {
243 ALLOC_CACHE_ALIGN_BUFFER
244 (char, rpmb_frame_data,
245 sizeof(struct s_rpmb) * cnt);
246 ALLOC_CACHE_ALIGN_BUFFER
247 (char, rpmb_frame_data_verify,
248 sizeof(struct s_rpmb_verify) * cnt);
249 struct s_rpmb *rpmb_frame;
250 struct s_rpmb_verify *rpmb_frame_vrify;
251 int i;
252
253 memset(rpmb_frame_data, 0, sizeof(struct s_rpmb) * cnt);
254 memset(rpmb_frame_data_verify, 0, sizeof(struct s_rpmb_verify) * cnt);
255 rpmb_frame = (struct s_rpmb *)rpmb_frame_data;
256 rpmb_frame->address = cpu_to_be16(blk);
257 rpmb_frame->request = cpu_to_be16(RPMB_REQ_READ_DATA);
258 if (mmc_rpmb_request(mmc, rpmb_frame, 1, false)) {
259 printf("mmc_rpmb_read request error\n");
260 return -1;
261 }
262
263 if (mmc_rpmb_response
264 (mmc,
265 (struct s_rpmb *)rpmb_frame_data,
266 RPMB_RESP_READ_DATA, cnt)) {
267 printf("mmc_rpmb_read response error\n");
268 return -1;
269 }
270
271 for (i = 0; i < cnt; i++) {
272 rpmb_frame = (struct s_rpmb *)
273 (rpmb_frame_data +
274 i * sizeof(struct s_rpmb));
275
276 rpmb_frame_vrify = (struct s_rpmb_verify *)
277 (rpmb_frame_data_verify +
278 i * sizeof(struct s_rpmb_verify));
279 memcpy(addr + i * RPMB_SZ_DATA, rpmb_frame->data, RPMB_SZ_DATA);
280 memcpy(rpmb_frame_vrify->data, rpmb_frame->data, 284);
281 }
282
283 if (key) {
284 unsigned char ret_hmac[RPMB_SZ_MAC];
285 rpmb_hmac
286 (key, (unsigned char *)rpmb_frame_data_verify,
287 284 * cnt, ret_hmac);
288 if (memcmp(ret_hmac, rpmb_frame->mac, RPMB_SZ_MAC)) {
289 printf("MAC error on block #%d\n", i);
290 return -1;
291 }
292 }
293
294 return cnt;
295 }
mmc_rpmb_write(struct mmc * mmc,void * addr,unsigned short blk,unsigned short cnt,unsigned char * key)296 int mmc_rpmb_write(struct mmc *mmc, void *addr, unsigned short blk,
297 unsigned short cnt, unsigned char *key)
298 {
299 struct s_rpmb *rpmb_frame;
300 struct s_rpmb_verify *rpmb_frame_vrify;
301 ALLOC_CACHE_ALIGN_BUFFER
302 (char, rpmb_frame_data,
303 sizeof(struct s_rpmb) * cnt);
304 ALLOC_CACHE_ALIGN_BUFFER
305 (char, rpmb_frame_data_verify,
306 sizeof(struct s_rpmb_verify) * cnt);
307
308 unsigned long wcount;
309 unsigned short i;
310 unsigned short temp;
311
312 temp = cnt - 1;
313 memset(rpmb_frame_data, 0, sizeof(struct s_rpmb) * cnt);
314 memset(rpmb_frame_data_verify, 0, sizeof(struct s_rpmb_verify) * cnt);
315 for (i = 0; i < cnt; i++) {
316 if (i == 0) {
317 if (mmc_rpmb_get_counter(mmc, &wcount)) {
318 printf("Cannot read RPMB write counter\n");
319 break;
320 }
321 }
322
323 rpmb_frame = (struct s_rpmb *)
324 (rpmb_frame_data +
325 i * sizeof(struct s_rpmb));
326 rpmb_frame_vrify = (struct s_rpmb_verify *)
327 (rpmb_frame_data_verify +
328 i * sizeof(struct s_rpmb_verify));
329 memcpy(rpmb_frame->data, addr + i * RPMB_SZ_DATA, RPMB_SZ_DATA);
330 memcpy(rpmb_frame_vrify->data, addr +
331 i * RPMB_SZ_DATA, RPMB_SZ_DATA);
332 rpmb_frame->address = cpu_to_be16(blk);
333 rpmb_frame_vrify->address = cpu_to_be16(blk);
334 rpmb_frame->block_count = cpu_to_be16(cnt);
335 rpmb_frame_vrify->block_count = cpu_to_be16(cnt);
336 rpmb_frame->write_counter = cpu_to_be32(wcount);
337 rpmb_frame_vrify->write_counter = cpu_to_be32(wcount);
338 rpmb_frame->request = cpu_to_be16(RPMB_REQ_WRITE_DATA);
339 rpmb_frame_vrify->request = cpu_to_be16(RPMB_REQ_WRITE_DATA);
340 if (i == temp) {
341 rpmb_hmac
342 (key, (unsigned char *)rpmb_frame_data_verify,
343 284 * cnt, rpmb_frame->mac);
344 }
345 }
346 if (mmc_rpmb_request(mmc, rpmb_frame_data, cnt, true))
347 return -1;
348
349 if (mmc_rpmb_status(mmc, RPMB_RESP_WRITE_DATA))
350 return -1;
351 return cnt;
352 }
353
read_counter(struct mmc * mmc,struct s_rpmb * requestpackets)354 int read_counter(struct mmc *mmc, struct s_rpmb *requestpackets)
355 {
356 if (mmc_rpmb_request(mmc, requestpackets, 1, false))
357 return -1;
358
359 if (mmc_rpmb_response(mmc, requestpackets, RPMB_RESP_WCOUNTER, 1))
360 return -1;
361
362 return 0;
363 }
364
program_key(struct mmc * mmc,struct s_rpmb * requestpackets)365 int program_key(struct mmc *mmc, struct s_rpmb *requestpackets)
366 {
367 if (mmc_rpmb_request(mmc, requestpackets, 1, true))
368 return -1;
369
370 memset(requestpackets, 0, sizeof(struct s_rpmb));
371
372 requestpackets->request = cpu_to_be16(RPMB_REQ_STATUS);
373
374 if (mmc_rpmb_request(mmc, requestpackets, 1, false))
375 return -1;
376
377 return mmc_rpmb_response(mmc, requestpackets, RPMB_RESP_KEY, 1);
378 }
379
authenticated_read(struct mmc * mmc,struct s_rpmb * requestpackets,uint16_t block_count)380 int authenticated_read(struct mmc *mmc,
381 struct s_rpmb *requestpackets, uint16_t block_count)
382 {
383 if (mmc_rpmb_request(mmc, requestpackets, 1, false))
384 return -1;
385
386 if (mmc_rpmb_response
387 (mmc, requestpackets, RPMB_RESP_READ_DATA, block_count))
388 return -1;
389
390 return 0;
391 }
392
authenticated_write(struct mmc * mmc,struct s_rpmb * requestpackets)393 int authenticated_write(struct mmc *mmc, struct s_rpmb *requestpackets)
394 {
395 if (mmc_rpmb_request(mmc, requestpackets, 1, true))
396 return -1;
397
398 memset(requestpackets, 0, sizeof(struct s_rpmb));
399
400 requestpackets->request = cpu_to_be16(RPMB_REQ_STATUS);
401
402 if (mmc_rpmb_request(mmc, requestpackets, 1, false))
403 return -1;
404
405 return mmc_rpmb_response(mmc, requestpackets, RPMB_RESP_WRITE_DATA, 1);
406 }
407
408