xref: /openbmc/u-boot/drivers/mmc/rpmb.c (revision baefb63a)
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 /* Sizes of RPMB data frame */
44 #define RPMB_SZ_STUFF		196
45 #define RPMB_SZ_MAC		32
46 #define RPMB_SZ_DATA		256
47 #define RPMB_SZ_NONCE		16
48 
49 #define SHA256_BLOCK_SIZE	64
50 
51 /* Error messages */
52 static const char * const rpmb_err_msg[] = {
53 	"",
54 	"General failure",
55 	"Authentication failure",
56 	"Counter failure",
57 	"Address failure",
58 	"Write failure",
59 	"Read failure",
60 	"Authentication key not yet programmed",
61 };
62 
63 
64 /* Structure of RPMB data frame. */
65 struct s_rpmb {
66 	unsigned char stuff[RPMB_SZ_STUFF];
67 	unsigned char mac[RPMB_SZ_MAC];
68 	unsigned char data[RPMB_SZ_DATA];
69 	unsigned char nonce[RPMB_SZ_NONCE];
70 	unsigned int write_counter;
71 	unsigned short address;
72 	unsigned short block_count;
73 	unsigned short result;
74 	unsigned short request;
75 };
76 
77 static int mmc_set_blockcount(struct mmc *mmc, unsigned int blockcount,
78 			      bool is_rel_write)
79 {
80 	struct mmc_cmd cmd = {0};
81 
82 	cmd.cmdidx = MMC_CMD_SET_BLOCK_COUNT;
83 	cmd.cmdarg = blockcount & 0x0000FFFF;
84 	if (is_rel_write)
85 		cmd.cmdarg |= 1 << 31;
86 	cmd.resp_type = MMC_RSP_R1;
87 
88 	return mmc_send_cmd(mmc, &cmd, NULL);
89 }
90 static int mmc_rpmb_request(struct mmc *mmc, const struct s_rpmb *s,
91 			    unsigned int count, bool is_rel_write)
92 {
93 	struct mmc_cmd cmd = {0};
94 	struct mmc_data data;
95 	int ret;
96 
97 	ret = mmc_set_blockcount(mmc, count, is_rel_write);
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 
105 	cmd.cmdidx = MMC_CMD_WRITE_MULTIPLE_BLOCK;
106 	cmd.cmdarg = 0;
107 	cmd.resp_type = MMC_RSP_R1b;
108 
109 	data.src = (const char *)s;
110 	data.blocks = 1;
111 	data.blocksize = MMC_MAX_BLOCK_LEN;
112 	data.flags = MMC_DATA_WRITE;
113 
114 	ret = mmc_send_cmd(mmc, &cmd, &data);
115 	if (ret) {
116 #ifdef CONFIG_MMC_RPMB_TRACE
117 		printf("%s:mmc_send_cmd-> %d\n", __func__, ret);
118 #endif
119 		return 1;
120 	}
121 	return 0;
122 }
123 static int mmc_rpmb_response(struct mmc *mmc, struct s_rpmb *s,
124 			     unsigned short expected)
125 {
126 	struct mmc_cmd cmd = {0};
127 	struct mmc_data data;
128 	int ret;
129 
130 	ret = mmc_set_blockcount(mmc, 1, false);
131 	if (ret) {
132 #ifdef CONFIG_MMC_RPMB_TRACE
133 		printf("%s:mmc_set_blockcount-> %d\n", __func__, ret);
134 #endif
135 		return -1;
136 	}
137 	cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK;
138 	cmd.cmdarg = 0;
139 	cmd.resp_type = MMC_RSP_R1;
140 
141 	data.dest = (char *)s;
142 	data.blocks = 1;
143 	data.blocksize = MMC_MAX_BLOCK_LEN;
144 	data.flags = MMC_DATA_READ;
145 
146 	ret = mmc_send_cmd(mmc, &cmd, &data);
147 	if (ret) {
148 #ifdef CONFIG_MMC_RPMB_TRACE
149 		printf("%s:mmc_send_cmd-> %d\n", __func__, ret);
150 #endif
151 		return -1;
152 	}
153 	/* Check the response and the status */
154 	if (be16_to_cpu(s->request) != expected) {
155 #ifdef CONFIG_MMC_RPMB_TRACE
156 		printf("%s:response= %x\n", __func__,
157 		       be16_to_cpu(s->request));
158 #endif
159 		return -1;
160 	}
161 	ret = be16_to_cpu(s->result);
162 	if (ret) {
163 		printf("%s %s\n", rpmb_err_msg[ret & RPMB_ERR_MSK],
164 		       (ret & RPMB_ERR_CNT_EXPIRED) ?
165 		       "Write counter has expired" : "");
166 	}
167 
168 	/* Return the status of the command */
169 	return ret;
170 }
171 static int mmc_rpmb_status(struct mmc *mmc, unsigned short expected)
172 {
173 	ALLOC_CACHE_ALIGN_BUFFER(struct s_rpmb, rpmb_frame, 1);
174 
175 	memset(rpmb_frame, 0, sizeof(struct s_rpmb));
176 	rpmb_frame->request = cpu_to_be16(RPMB_REQ_STATUS);
177 	if (mmc_rpmb_request(mmc, rpmb_frame, 1, false))
178 		return -1;
179 
180 	/* Read the result */
181 	return mmc_rpmb_response(mmc, rpmb_frame, expected);
182 }
183 static void rpmb_hmac(unsigned char *key, unsigned char *buff, int len,
184 		      unsigned char *output)
185 {
186 	sha256_context ctx;
187 	int i;
188 	unsigned char k_ipad[SHA256_BLOCK_SIZE];
189 	unsigned char k_opad[SHA256_BLOCK_SIZE];
190 
191 	sha256_starts(&ctx);
192 
193 	/* According to RFC 4634, the HMAC transform looks like:
194 	   SHA(K XOR opad, SHA(K XOR ipad, text))
195 
196 	   where K is an n byte key.
197 	   ipad is the byte 0x36 repeated blocksize times
198 	   opad is the byte 0x5c repeated blocksize times
199 	   and text is the data being protected.
200 	*/
201 
202 	for (i = 0; i < RPMB_SZ_MAC; i++) {
203 		k_ipad[i] = key[i] ^ 0x36;
204 		k_opad[i] = key[i] ^ 0x5c;
205 	}
206 	/* remaining pad bytes are '\0' XOR'd with ipad and opad values */
207 	for ( ; i < SHA256_BLOCK_SIZE; i++) {
208 		k_ipad[i] = 0x36;
209 		k_opad[i] = 0x5c;
210 	}
211 	sha256_update(&ctx, k_ipad, SHA256_BLOCK_SIZE);
212 	sha256_update(&ctx, buff, len);
213 	sha256_finish(&ctx, output);
214 
215 	/* Init context for second pass */
216 	sha256_starts(&ctx);
217 
218 	/* start with outer pad */
219 	sha256_update(&ctx, k_opad, SHA256_BLOCK_SIZE);
220 
221 	/* then results of 1st hash */
222 	sha256_update(&ctx, output, RPMB_SZ_MAC);
223 
224 	/* finish up 2nd pass */
225 	sha256_finish(&ctx, output);
226 }
227 int mmc_rpmb_get_counter(struct mmc *mmc, unsigned long *pcounter)
228 {
229 	int ret;
230 	ALLOC_CACHE_ALIGN_BUFFER(struct s_rpmb, rpmb_frame, 1);
231 
232 	/* Fill the request */
233 	memset(rpmb_frame, 0, sizeof(struct s_rpmb));
234 	rpmb_frame->request = cpu_to_be16(RPMB_REQ_WCOUNTER);
235 	if (mmc_rpmb_request(mmc, rpmb_frame, 1, false))
236 		return -1;
237 
238 	/* Read the result */
239 	ret = mmc_rpmb_response(mmc, rpmb_frame, RPMB_RESP_WCOUNTER);
240 	if (ret)
241 		return ret;
242 
243 	*pcounter = be32_to_cpu(rpmb_frame->write_counter);
244 	return 0;
245 }
246 int mmc_rpmb_set_key(struct mmc *mmc, void *key)
247 {
248 	ALLOC_CACHE_ALIGN_BUFFER(struct s_rpmb, rpmb_frame, 1);
249 	/* Fill the request */
250 	memset(rpmb_frame, 0, sizeof(struct s_rpmb));
251 	rpmb_frame->request = cpu_to_be16(RPMB_REQ_KEY);
252 	memcpy(rpmb_frame->mac, key, RPMB_SZ_MAC);
253 
254 	if (mmc_rpmb_request(mmc, rpmb_frame, 1, true))
255 		return -1;
256 
257 	/* read the operation status */
258 	return mmc_rpmb_status(mmc, RPMB_RESP_KEY);
259 }
260 int mmc_rpmb_read(struct mmc *mmc, void *addr, unsigned short blk,
261 		  unsigned short cnt, unsigned char *key)
262 {
263 	ALLOC_CACHE_ALIGN_BUFFER(struct s_rpmb, rpmb_frame, 1);
264 	int i;
265 
266 	for (i = 0; i < cnt; i++) {
267 		/* Fill the request */
268 		memset(rpmb_frame, 0, sizeof(struct s_rpmb));
269 		rpmb_frame->address = cpu_to_be16(blk + i);
270 		rpmb_frame->request = cpu_to_be16(RPMB_REQ_READ_DATA);
271 		if (mmc_rpmb_request(mmc, rpmb_frame, 1, false))
272 			break;
273 
274 		/* Read the result */
275 		if (mmc_rpmb_response(mmc, rpmb_frame, RPMB_RESP_READ_DATA))
276 			break;
277 
278 		/* Check the HMAC if key is provided */
279 		if (key) {
280 			unsigned char ret_hmac[RPMB_SZ_MAC];
281 
282 			rpmb_hmac(key, rpmb_frame->data, 284, ret_hmac);
283 			if (memcmp(ret_hmac, rpmb_frame->mac, RPMB_SZ_MAC)) {
284 				printf("MAC error on block #%d\n", i);
285 				break;
286 			}
287 		}
288 		/* Copy data */
289 		memcpy(addr + i * RPMB_SZ_DATA, rpmb_frame->data, RPMB_SZ_DATA);
290 	}
291 	return i;
292 }
293 int mmc_rpmb_write(struct mmc *mmc, void *addr, unsigned short blk,
294 		  unsigned short cnt, unsigned char *key)
295 {
296 	ALLOC_CACHE_ALIGN_BUFFER(struct s_rpmb, rpmb_frame, 1);
297 	unsigned long wcount;
298 	int i;
299 
300 	for (i = 0; i < cnt; i++) {
301 		if (mmc_rpmb_get_counter(mmc, &wcount)) {
302 			printf("Cannot read RPMB write counter\n");
303 			break;
304 		}
305 
306 		/* Fill the request */
307 		memset(rpmb_frame, 0, sizeof(struct s_rpmb));
308 		memcpy(rpmb_frame->data, addr + i * RPMB_SZ_DATA, RPMB_SZ_DATA);
309 		rpmb_frame->address = cpu_to_be16(blk + i);
310 		rpmb_frame->block_count = cpu_to_be16(1);
311 		rpmb_frame->write_counter = cpu_to_be32(wcount);
312 		rpmb_frame->request = cpu_to_be16(RPMB_REQ_WRITE_DATA);
313 		/* Computes HMAC */
314 		rpmb_hmac(key, rpmb_frame->data, 284, rpmb_frame->mac);
315 
316 		if (mmc_rpmb_request(mmc, rpmb_frame, 1, true))
317 			break;
318 
319 		/* Get status */
320 		if (mmc_rpmb_status(mmc, RPMB_RESP_WRITE_DATA))
321 			break;
322 	}
323 	return i;
324 }
325