xref: /rk3399_rockchip-uboot/drivers/mmc/rpmb.c (revision ea6a84b6834a830883a492f3991ab4afefd038af)
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