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