xref: /OK3568_Linux_fs/u-boot/drivers/mmc/rpmb.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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