1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright 2014, Staubli Faverges
6 * eMMC- Replay Protected Memory Block
7 * According to JEDEC Standard No. 84-A441
16 #include <u-boot/sha256.h>
17 #include "mmc_private.h"
20 #define RPMB_REQ_KEY 1
21 #define RPMB_REQ_WCOUNTER 2
22 #define RPMB_REQ_WRITE_DATA 3
23 #define RPMB_REQ_READ_DATA 4
24 #define RPMB_REQ_STATUS 5
27 #define RPMB_RESP_KEY 0x0100
28 #define RPMB_RESP_WCOUNTER 0x0200
29 #define RPMB_RESP_WRITE_DATA 0x0300
30 #define RPMB_RESP_READ_DATA 0x0400
34 #define RPMB_ERR_GENERAL 1
35 #define RPMB_ERR_AUTH 2
36 #define RPMB_ERR_COUNTER 3
37 #define RPMB_ERR_ADDRESS 4
38 #define RPMB_ERR_WRITE 5
39 #define RPMB_ERR_READ 6
40 #define RPMB_ERR_KEY 7
41 #define RPMB_ERR_CNT_EXPIRED 0x80
42 #define RPMB_ERR_MSK 0x7
44 /* Sizes of RPMB data frame */
45 #define RPMB_SZ_STUFF 196
46 #define RPMB_SZ_MAC 32
47 #define RPMB_SZ_DATA 256
48 #define RPMB_SZ_NONCE 16
50 #define SHA256_BLOCK_SIZE 64
53 static const char * const rpmb_err_msg[] = {
56 "Authentication failure",
61 "Authentication key not yet programmed",
65 /* Structure of RPMB data frame. */
67 unsigned char stuff[RPMB_SZ_STUFF];
68 unsigned char mac[RPMB_SZ_MAC];
69 unsigned char data[RPMB_SZ_DATA];
70 unsigned char nonce[RPMB_SZ_NONCE];
71 unsigned int write_counter;
72 unsigned short address;
73 unsigned short block_count;
74 unsigned short result;
75 unsigned short request;
78 static int mmc_set_blockcount(struct mmc *mmc, unsigned int blockcount,
81 struct mmc_cmd cmd = {0};
83 cmd.cmdidx = MMC_CMD_SET_BLOCK_COUNT;
84 cmd.cmdarg = blockcount & 0x0000FFFF;
86 cmd.cmdarg |= 1 << 31;
87 cmd.resp_type = MMC_RSP_R1;
89 return mmc_send_cmd(mmc, &cmd, NULL);
91 static int mmc_rpmb_request(struct mmc *mmc, const struct s_rpmb *s,
92 unsigned int count, bool is_rel_write)
94 struct mmc_cmd cmd = {0};
96 struct sdhci_host *host = mmc->priv;
99 ret = mmc_set_blockcount(mmc, count, is_rel_write);
101 #ifdef CONFIG_MMC_RPMB_TRACE
102 printf("%s:mmc_set_blockcount-> %d\n", __func__, ret);
107 cmd.cmdidx = MMC_CMD_WRITE_MULTIPLE_BLOCK;
109 cmd.resp_type = MMC_RSP_R1;
111 if (host->quirks & SDHCI_QUIRK_BROKEN_R1B)
112 cmd.resp_type = MMC_RSP_R1;
114 data.src = (const char *)s;
116 data.blocksize = MMC_MAX_BLOCK_LEN;
117 data.flags = MMC_DATA_WRITE;
119 ret = mmc_send_cmd(mmc, &cmd, &data);
121 #ifdef CONFIG_MMC_RPMB_TRACE
122 printf("%s:mmc_send_cmd-> %d\n", __func__, ret);
128 static int mmc_rpmb_response(struct mmc *mmc, struct s_rpmb *s,
129 unsigned short expected)
131 struct mmc_cmd cmd = {0};
132 struct mmc_data data;
135 ret = mmc_set_blockcount(mmc, 1, false);
137 #ifdef CONFIG_MMC_RPMB_TRACE
138 printf("%s:mmc_set_blockcount-> %d\n", __func__, ret);
142 cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK;
144 cmd.resp_type = MMC_RSP_R1;
146 data.dest = (char *)s;
148 data.blocksize = MMC_MAX_BLOCK_LEN;
149 data.flags = MMC_DATA_READ;
151 ret = mmc_send_cmd(mmc, &cmd, &data);
153 #ifdef CONFIG_MMC_RPMB_TRACE
154 printf("%s:mmc_send_cmd-> %d\n", __func__, ret);
158 /* Check the response and the status */
159 if (be16_to_cpu(s->request) != expected) {
160 #ifdef CONFIG_MMC_RPMB_TRACE
161 printf("%s:response= %x\n", __func__,
162 be16_to_cpu(s->request));
166 ret = be16_to_cpu(s->result);
168 printf("%s %s\n", rpmb_err_msg[ret & RPMB_ERR_MSK],
169 (ret & RPMB_ERR_CNT_EXPIRED) ?
170 "Write counter has expired" : "");
173 /* Return the status of the command */
176 static int mmc_rpmb_status(struct mmc *mmc, unsigned short expected)
178 ALLOC_CACHE_ALIGN_BUFFER(struct s_rpmb, rpmb_frame, 1);
180 memset(rpmb_frame, 0, sizeof(struct s_rpmb));
181 rpmb_frame->request = cpu_to_be16(RPMB_REQ_STATUS);
182 if (mmc_rpmb_request(mmc, rpmb_frame, 1, false))
185 /* Read the result */
186 return mmc_rpmb_response(mmc, rpmb_frame, expected);
188 static void rpmb_hmac(unsigned char *key, unsigned char *buff, int len,
189 unsigned char *output)
193 unsigned char k_ipad[SHA256_BLOCK_SIZE];
194 unsigned char k_opad[SHA256_BLOCK_SIZE];
198 /* According to RFC 4634, the HMAC transform looks like:
199 SHA(K XOR opad, SHA(K XOR ipad, text))
201 where K is an n byte key.
202 ipad is the byte 0x36 repeated blocksize times
203 opad is the byte 0x5c repeated blocksize times
204 and text is the data being protected.
207 for (i = 0; i < RPMB_SZ_MAC; i++) {
208 k_ipad[i] = key[i] ^ 0x36;
209 k_opad[i] = key[i] ^ 0x5c;
211 /* remaining pad bytes are '\0' XOR'd with ipad and opad values */
212 for ( ; i < SHA256_BLOCK_SIZE; i++) {
216 sha256_update(&ctx, k_ipad, SHA256_BLOCK_SIZE);
217 sha256_update(&ctx, buff, len);
218 sha256_finish(&ctx, output);
220 /* Init context for second pass */
223 /* start with outer pad */
224 sha256_update(&ctx, k_opad, SHA256_BLOCK_SIZE);
226 /* then results of 1st hash */
227 sha256_update(&ctx, output, RPMB_SZ_MAC);
229 /* finish up 2nd pass */
230 sha256_finish(&ctx, output);
232 int mmc_rpmb_get_counter(struct mmc *mmc, unsigned long *pcounter)
235 ALLOC_CACHE_ALIGN_BUFFER(struct s_rpmb, rpmb_frame, 1);
237 /* Fill the request */
238 memset(rpmb_frame, 0, sizeof(struct s_rpmb));
239 rpmb_frame->request = cpu_to_be16(RPMB_REQ_WCOUNTER);
240 if (mmc_rpmb_request(mmc, rpmb_frame, 1, false))
243 /* Read the result */
244 ret = mmc_rpmb_response(mmc, rpmb_frame, RPMB_RESP_WCOUNTER);
248 *pcounter = be32_to_cpu(rpmb_frame->write_counter);
251 int mmc_rpmb_set_key(struct mmc *mmc, void *key)
253 ALLOC_CACHE_ALIGN_BUFFER(struct s_rpmb, rpmb_frame, 1);
254 /* Fill the request */
255 memset(rpmb_frame, 0, sizeof(struct s_rpmb));
256 rpmb_frame->request = cpu_to_be16(RPMB_REQ_KEY);
257 memcpy(rpmb_frame->mac, key, RPMB_SZ_MAC);
259 if (mmc_rpmb_request(mmc, rpmb_frame, 1, true))
262 /* read the operation status */
263 return mmc_rpmb_status(mmc, RPMB_RESP_KEY);
265 int mmc_rpmb_read(struct mmc *mmc, void *addr, unsigned short blk,
266 unsigned short cnt, unsigned char *key)
268 ALLOC_CACHE_ALIGN_BUFFER(struct s_rpmb, rpmb_frame, 1);
271 for (i = 0; i < cnt; i++) {
272 /* Fill the request */
273 memset(rpmb_frame, 0, sizeof(struct s_rpmb));
274 rpmb_frame->address = cpu_to_be16(blk + i);
275 rpmb_frame->request = cpu_to_be16(RPMB_REQ_READ_DATA);
276 if (mmc_rpmb_request(mmc, rpmb_frame, 1, false))
279 /* Read the result */
280 if (mmc_rpmb_response(mmc, rpmb_frame, RPMB_RESP_READ_DATA))
283 /* Check the HMAC if key is provided */
285 unsigned char ret_hmac[RPMB_SZ_MAC];
287 rpmb_hmac(key, rpmb_frame->data, 284, ret_hmac);
288 if (memcmp(ret_hmac, rpmb_frame->mac, RPMB_SZ_MAC)) {
289 printf("MAC error on block #%d\n", i);
294 memcpy(addr + i * RPMB_SZ_DATA, rpmb_frame->data, RPMB_SZ_DATA);
298 int mmc_rpmb_write(struct mmc *mmc, void *addr, unsigned short blk,
299 unsigned short cnt, unsigned char *key)
301 ALLOC_CACHE_ALIGN_BUFFER(struct s_rpmb, rpmb_frame, 1);
302 unsigned long wcount;
305 for (i = 0; i < cnt; i++) {
306 if (mmc_rpmb_get_counter(mmc, &wcount)) {
307 printf("Cannot read RPMB write counter\n");
311 /* Fill the request */
312 memset(rpmb_frame, 0, sizeof(struct s_rpmb));
313 memcpy(rpmb_frame->data, addr + i * RPMB_SZ_DATA, RPMB_SZ_DATA);
314 rpmb_frame->address = cpu_to_be16(blk + i);
315 rpmb_frame->block_count = cpu_to_be16(1);
316 rpmb_frame->write_counter = cpu_to_be32(wcount);
317 rpmb_frame->request = cpu_to_be16(RPMB_REQ_WRITE_DATA);
319 rpmb_hmac(key, rpmb_frame->data, 284, rpmb_frame->mac);
321 if (mmc_rpmb_request(mmc, rpmb_frame, 1, true))
325 if (mmc_rpmb_status(mmc, RPMB_RESP_WRITE_DATA))
331 static int send_write_mult_block(struct mmc *mmc, const struct s_rpmb *frm,
334 struct mmc_cmd cmd = {
335 .cmdidx = MMC_CMD_WRITE_MULTIPLE_BLOCK,
336 .resp_type = MMC_RSP_R1,
338 struct mmc_data data = {
339 .src = (const void *)frm,
341 .blocksize = sizeof(*frm),
342 .flags = MMC_DATA_WRITE,
345 return mmc_send_cmd(mmc, &cmd, &data);
348 static int send_read_mult_block(struct mmc *mmc, struct s_rpmb *frm,
351 struct mmc_cmd cmd = {
352 .cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK,
353 .resp_type = MMC_RSP_R1,
355 struct mmc_data data = {
358 .blocksize = sizeof(*frm),
359 .flags = MMC_DATA_READ,
362 return mmc_send_cmd(mmc, &cmd, &data);
365 static int rpmb_route_write_req(struct mmc *mmc, struct s_rpmb *req,
366 unsigned short req_cnt, struct s_rpmb *rsp,
367 unsigned short rsp_cnt)
372 * Send the write request.
374 ret = mmc_set_blockcount(mmc, req_cnt, true);
378 ret = send_write_mult_block(mmc, req, req_cnt);
383 * Read the result of the request.
385 ret = mmc_set_blockcount(mmc, 1, false);
389 memset(rsp, 0, sizeof(*rsp));
390 rsp->request = cpu_to_be16(RPMB_REQ_STATUS);
391 ret = send_write_mult_block(mmc, rsp, 1);
395 ret = mmc_set_blockcount(mmc, 1, false);
399 return send_read_mult_block(mmc, rsp, 1);
402 static int rpmb_route_read_req(struct mmc *mmc, struct s_rpmb *req,
403 unsigned short req_cnt, struct s_rpmb *rsp,
404 unsigned short rsp_cnt)
409 * Send the read request.
411 ret = mmc_set_blockcount(mmc, 1, false);
415 ret = send_write_mult_block(mmc, req, 1);
420 * Read the result of the request.
423 ret = mmc_set_blockcount(mmc, rsp_cnt, false);
427 return send_read_mult_block(mmc, rsp, rsp_cnt);
430 static int rpmb_route_frames(struct mmc *mmc, struct s_rpmb *req,
431 unsigned short req_cnt, struct s_rpmb *rsp,
432 unsigned short rsp_cnt)
437 * If multiple request frames are provided, make sure that all are
440 for (n = 1; n < req_cnt; n++)
441 if (req[n].request != req->request)
444 switch (be16_to_cpu(req->request)) {
446 if (req_cnt != 1 || rsp_cnt != 1)
448 return rpmb_route_write_req(mmc, req, req_cnt, rsp, rsp_cnt);
450 case RPMB_REQ_WRITE_DATA:
451 if (!req_cnt || rsp_cnt != 1)
453 return rpmb_route_write_req(mmc, req, req_cnt, rsp, rsp_cnt);
455 case RPMB_REQ_WCOUNTER:
456 if (req_cnt != 1 || rsp_cnt != 1)
458 return rpmb_route_read_req(mmc, req, req_cnt, rsp, rsp_cnt);
460 case RPMB_REQ_READ_DATA:
461 if (req_cnt != 1 || !req_cnt)
463 return rpmb_route_read_req(mmc, req, req_cnt, rsp, rsp_cnt);
466 debug("Unsupported message type: %d\n",
467 be16_to_cpu(req->request));
472 int mmc_rpmb_route_frames(struct mmc *mmc, void *req, unsigned long reqlen,
473 void *rsp, unsigned long rsplen)
476 * Whoever crafted the data supplied to this function knows how to
477 * format the PRMB frames and which response is expected. If
478 * there's some unexpected mismatch it's more helpful to report an
479 * error immediately than trying to guess what was the intention
480 * and possibly just delay an eventual error which will be harder
483 void *rpmb_data = NULL;
486 if (reqlen % sizeof(struct s_rpmb) || rsplen % sizeof(struct s_rpmb))
489 if (!IS_ALIGNED((uintptr_t)req, ARCH_DMA_MINALIGN)) {
490 /* Memory alignment is required by MMC driver */
491 rpmb_data = malloc(reqlen);
495 memcpy(rpmb_data, req, reqlen);
499 ret = rpmb_route_frames(mmc, req, reqlen / sizeof(struct s_rpmb),
500 rsp, rsplen / sizeof(struct s_rpmb));