xref: /rk3399_rockchip-uboot/drivers/mmc/rpmb.c (revision ea6a84b6834a830883a492f3991ab4afefd038af)
191fdabc6SPierre Aubert /*
291fdabc6SPierre Aubert  * Copyright 2014, Staubli Faverges
391fdabc6SPierre Aubert  * Pierre Aubert
491fdabc6SPierre Aubert  *
591fdabc6SPierre Aubert  * eMMC- Replay Protected Memory Block
691fdabc6SPierre Aubert  * According to JEDEC Standard No. 84-A441
791fdabc6SPierre Aubert  *
891fdabc6SPierre Aubert  * SPDX-License-Identifier:	GPL-2.0+
991fdabc6SPierre Aubert  */
1091fdabc6SPierre Aubert 
1191fdabc6SPierre Aubert #include <config.h>
1291fdabc6SPierre Aubert #include <common.h>
13cf92e05cSSimon Glass #include <memalign.h>
1491fdabc6SPierre Aubert #include <mmc.h>
152b9912e6SJeroen Hofstee #include <u-boot/sha256.h>
1691fdabc6SPierre Aubert #include "mmc_private.h"
1791fdabc6SPierre Aubert 
1891fdabc6SPierre Aubert /* Request codes */
1991fdabc6SPierre Aubert #define RPMB_REQ_KEY		1
2091fdabc6SPierre Aubert #define RPMB_REQ_WCOUNTER	2
2191fdabc6SPierre Aubert #define RPMB_REQ_WRITE_DATA	3
2291fdabc6SPierre Aubert #define RPMB_REQ_READ_DATA	4
2391fdabc6SPierre Aubert #define RPMB_REQ_STATUS		5
2491fdabc6SPierre Aubert 
2591fdabc6SPierre Aubert /* Response code */
2691fdabc6SPierre Aubert #define RPMB_RESP_KEY		0x0100
2791fdabc6SPierre Aubert #define RPMB_RESP_WCOUNTER	0x0200
2891fdabc6SPierre Aubert #define RPMB_RESP_WRITE_DATA	0x0300
2991fdabc6SPierre Aubert #define RPMB_RESP_READ_DATA	0x0400
3091fdabc6SPierre Aubert 
3191fdabc6SPierre Aubert /* Error codes */
3291fdabc6SPierre Aubert #define RPMB_OK			0
3391fdabc6SPierre Aubert #define RPMB_ERR_GENERAL	1
3491fdabc6SPierre Aubert #define RPMB_ERR_AUTH	2
3591fdabc6SPierre Aubert #define RPMB_ERR_COUNTER	3
3691fdabc6SPierre Aubert #define RPMB_ERR_ADDRESS	4
3791fdabc6SPierre Aubert #define RPMB_ERR_WRITE		5
3891fdabc6SPierre Aubert #define RPMB_ERR_READ		6
3991fdabc6SPierre Aubert #define RPMB_ERR_KEY		7
4091fdabc6SPierre Aubert #define RPMB_ERR_CNT_EXPIRED	0x80
4191fdabc6SPierre Aubert #define RPMB_ERR_MSK		0x7
4291fdabc6SPierre Aubert 
4391fdabc6SPierre Aubert #define SHA256_BLOCK_SIZE	64
4491fdabc6SPierre Aubert 
4591fdabc6SPierre Aubert /* Error messages */
4691fdabc6SPierre Aubert static const char * const rpmb_err_msg[] = {
4791fdabc6SPierre Aubert 	"",
4891fdabc6SPierre Aubert 	"General failure",
4991fdabc6SPierre Aubert 	"Authentication failure",
5091fdabc6SPierre Aubert 	"Counter failure",
5191fdabc6SPierre Aubert 	"Address failure",
5291fdabc6SPierre Aubert 	"Write failure",
5391fdabc6SPierre Aubert 	"Read failure",
5491fdabc6SPierre Aubert 	"Authentication key not yet programmed",
5591fdabc6SPierre Aubert };
5691fdabc6SPierre Aubert 
mmc_rpmb_request(struct mmc * mmc,const void * s,unsigned int count,bool is_rel_write)5797a8a900Shisping static int mmc_rpmb_request(struct mmc *mmc, const void *s,
5891fdabc6SPierre Aubert 			    unsigned int count, bool is_rel_write)
5991fdabc6SPierre Aubert {
6091fdabc6SPierre Aubert 	struct mmc_cmd cmd = {0};
6191fdabc6SPierre Aubert 	struct mmc_data data;
6291fdabc6SPierre Aubert 	int ret;
6391fdabc6SPierre Aubert 
6491fdabc6SPierre Aubert 	ret = mmc_set_blockcount(mmc, count, is_rel_write);
6591fdabc6SPierre Aubert 	if (ret) {
6691fdabc6SPierre Aubert #ifdef CONFIG_MMC_RPMB_TRACE
6791fdabc6SPierre Aubert 		printf("%s:mmc_set_blockcount-> %d\n", __func__, ret);
6891fdabc6SPierre Aubert #endif
6991fdabc6SPierre Aubert 		return 1;
7091fdabc6SPierre Aubert 	}
7191fdabc6SPierre Aubert 
7291fdabc6SPierre Aubert 	cmd.cmdidx = MMC_CMD_WRITE_MULTIPLE_BLOCK;
7391fdabc6SPierre Aubert 	cmd.cmdarg = 0;
74*a0bf35b5SJason Zhu 	cmd.resp_type = MMC_RSP_R1;
7591fdabc6SPierre Aubert 
7691fdabc6SPierre Aubert 	data.src = (const char *)s;
7797a8a900Shisping 	data.blocks = count;
7891fdabc6SPierre Aubert 	data.blocksize = MMC_MAX_BLOCK_LEN;
7991fdabc6SPierre Aubert 	data.flags = MMC_DATA_WRITE;
8091fdabc6SPierre Aubert 
8191fdabc6SPierre Aubert 	ret = mmc_send_cmd(mmc, &cmd, &data);
8291fdabc6SPierre Aubert 	if (ret) {
8391fdabc6SPierre Aubert #ifdef CONFIG_MMC_RPMB_TRACE
8491fdabc6SPierre Aubert 		printf("%s:mmc_send_cmd-> %d\n", __func__, ret);
8591fdabc6SPierre Aubert #endif
8691fdabc6SPierre Aubert 		return 1;
8791fdabc6SPierre Aubert 	}
8891fdabc6SPierre Aubert 	return 0;
8991fdabc6SPierre Aubert }
mmc_rpmb_response(struct mmc * mmc,struct s_rpmb * s,unsigned short expected,unsigned short cnt)9091fdabc6SPierre Aubert static int mmc_rpmb_response(struct mmc *mmc, struct s_rpmb *s,
9197a8a900Shisping 			     unsigned short expected, unsigned short cnt)
9291fdabc6SPierre Aubert {
9391fdabc6SPierre Aubert 	struct mmc_cmd cmd = {0};
9491fdabc6SPierre Aubert 	struct mmc_data data;
9591fdabc6SPierre Aubert 	int ret;
9691fdabc6SPierre Aubert 
9797a8a900Shisping 	ret = mmc_set_blockcount(mmc, cnt, false);
9891fdabc6SPierre Aubert 	if (ret) {
9991fdabc6SPierre Aubert #ifdef CONFIG_MMC_RPMB_TRACE
10091fdabc6SPierre Aubert 		printf("%s:mmc_set_blockcount-> %d\n", __func__, ret);
10191fdabc6SPierre Aubert #endif
10291fdabc6SPierre Aubert 		return -1;
10391fdabc6SPierre Aubert 	}
10491fdabc6SPierre Aubert 	cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK;
10591fdabc6SPierre Aubert 	cmd.cmdarg = 0;
10691fdabc6SPierre Aubert 	cmd.resp_type = MMC_RSP_R1;
10791fdabc6SPierre Aubert 
10891fdabc6SPierre Aubert 	data.dest = (char *)s;
10997a8a900Shisping 	data.blocks = cnt;
11091fdabc6SPierre Aubert 	data.blocksize = MMC_MAX_BLOCK_LEN;
11191fdabc6SPierre Aubert 	data.flags = MMC_DATA_READ;
11291fdabc6SPierre Aubert 
11391fdabc6SPierre Aubert 	ret = mmc_send_cmd(mmc, &cmd, &data);
11491fdabc6SPierre Aubert 	if (ret) {
11591fdabc6SPierre Aubert #ifdef CONFIG_MMC_RPMB_TRACE
11691fdabc6SPierre Aubert 		printf("%s:mmc_send_cmd-> %d\n", __func__, ret);
11791fdabc6SPierre Aubert #endif
11891fdabc6SPierre Aubert 		return -1;
11991fdabc6SPierre Aubert 	}
12091fdabc6SPierre Aubert 	/* Check the response and the status */
12191fdabc6SPierre Aubert 	if (be16_to_cpu(s->request) != expected) {
12291fdabc6SPierre Aubert #ifdef CONFIG_MMC_RPMB_TRACE
12391fdabc6SPierre Aubert 		printf("%s:response= %x\n", __func__,
12491fdabc6SPierre Aubert 		       be16_to_cpu(s->request));
12591fdabc6SPierre Aubert #endif
12691fdabc6SPierre Aubert 		return -1;
12791fdabc6SPierre Aubert 	}
12891fdabc6SPierre Aubert 	ret = be16_to_cpu(s->result);
12991fdabc6SPierre Aubert 	if (ret) {
13091fdabc6SPierre Aubert 		printf("%s %s\n", rpmb_err_msg[ret & RPMB_ERR_MSK],
13191fdabc6SPierre Aubert 		       (ret & RPMB_ERR_CNT_EXPIRED) ?
13291fdabc6SPierre Aubert 		       "Write counter has expired" : "");
13391fdabc6SPierre Aubert 	}
13491fdabc6SPierre Aubert 
13591fdabc6SPierre Aubert 	/* Return the status of the command */
13691fdabc6SPierre Aubert 	return ret;
13791fdabc6SPierre Aubert }
mmc_rpmb_status(struct mmc * mmc,unsigned short expected)13891fdabc6SPierre Aubert static int mmc_rpmb_status(struct mmc *mmc, unsigned short expected)
13991fdabc6SPierre Aubert {
14091fdabc6SPierre Aubert 	ALLOC_CACHE_ALIGN_BUFFER(struct s_rpmb, rpmb_frame, 1);
14191fdabc6SPierre Aubert 
14291fdabc6SPierre Aubert 	memset(rpmb_frame, 0, sizeof(struct s_rpmb));
14391fdabc6SPierre Aubert 	rpmb_frame->request = cpu_to_be16(RPMB_REQ_STATUS);
14491fdabc6SPierre Aubert 	if (mmc_rpmb_request(mmc, rpmb_frame, 1, false))
14591fdabc6SPierre Aubert 		return -1;
14691fdabc6SPierre Aubert 
14791fdabc6SPierre Aubert 	/* Read the result */
14897a8a900Shisping 	return mmc_rpmb_response(mmc, rpmb_frame, expected, 1);
14991fdabc6SPierre Aubert }
rpmb_hmac(unsigned char * key,unsigned char * buff,int len,unsigned char * output)15091fdabc6SPierre Aubert static void rpmb_hmac(unsigned char *key, unsigned char *buff, int len,
15191fdabc6SPierre Aubert 		      unsigned char *output)
15291fdabc6SPierre Aubert {
15391fdabc6SPierre Aubert 	sha256_context ctx;
15491fdabc6SPierre Aubert 	int i;
15591fdabc6SPierre Aubert 	unsigned char k_ipad[SHA256_BLOCK_SIZE];
15691fdabc6SPierre Aubert 	unsigned char k_opad[SHA256_BLOCK_SIZE];
15791fdabc6SPierre Aubert 
15891fdabc6SPierre Aubert 	sha256_starts(&ctx);
15991fdabc6SPierre Aubert 
16091fdabc6SPierre Aubert 	/* According to RFC 4634, the HMAC transform looks like:
16191fdabc6SPierre Aubert 	   SHA(K XOR opad, SHA(K XOR ipad, text))
16291fdabc6SPierre Aubert 
16391fdabc6SPierre Aubert 	   where K is an n byte key.
16491fdabc6SPierre Aubert 	   ipad is the byte 0x36 repeated blocksize times
16591fdabc6SPierre Aubert 	   opad is the byte 0x5c repeated blocksize times
16691fdabc6SPierre Aubert 	   and text is the data being protected.
16791fdabc6SPierre Aubert 	*/
16891fdabc6SPierre Aubert 
16991fdabc6SPierre Aubert 	for (i = 0; i < RPMB_SZ_MAC; i++) {
17091fdabc6SPierre Aubert 		k_ipad[i] = key[i] ^ 0x36;
17191fdabc6SPierre Aubert 		k_opad[i] = key[i] ^ 0x5c;
17291fdabc6SPierre Aubert 	}
17391fdabc6SPierre Aubert 	/* remaining pad bytes are '\0' XOR'd with ipad and opad values */
17491fdabc6SPierre Aubert 	for ( ; i < SHA256_BLOCK_SIZE; i++) {
17591fdabc6SPierre Aubert 		k_ipad[i] = 0x36;
17691fdabc6SPierre Aubert 		k_opad[i] = 0x5c;
17791fdabc6SPierre Aubert 	}
17891fdabc6SPierre Aubert 	sha256_update(&ctx, k_ipad, SHA256_BLOCK_SIZE);
17991fdabc6SPierre Aubert 	sha256_update(&ctx, buff, len);
18091fdabc6SPierre Aubert 	sha256_finish(&ctx, output);
18191fdabc6SPierre Aubert 
18291fdabc6SPierre Aubert 	/* Init context for second pass */
18391fdabc6SPierre Aubert 	sha256_starts(&ctx);
18491fdabc6SPierre Aubert 
18591fdabc6SPierre Aubert 	/* start with outer pad */
18691fdabc6SPierre Aubert 	sha256_update(&ctx, k_opad, SHA256_BLOCK_SIZE);
18791fdabc6SPierre Aubert 
18891fdabc6SPierre Aubert 	/* then results of 1st hash */
18991fdabc6SPierre Aubert 	sha256_update(&ctx, output, RPMB_SZ_MAC);
19091fdabc6SPierre Aubert 
19191fdabc6SPierre Aubert 	/* finish up 2nd pass */
19291fdabc6SPierre Aubert 	sha256_finish(&ctx, output);
19391fdabc6SPierre Aubert }
mmc_rpmb_get_counter(struct mmc * mmc,unsigned long * pcounter)19491fdabc6SPierre Aubert int mmc_rpmb_get_counter(struct mmc *mmc, unsigned long *pcounter)
19591fdabc6SPierre Aubert {
19691fdabc6SPierre Aubert 	int ret;
19791fdabc6SPierre Aubert 	ALLOC_CACHE_ALIGN_BUFFER(struct s_rpmb, rpmb_frame, 1);
19891fdabc6SPierre Aubert 
19991fdabc6SPierre Aubert 	/* Fill the request */
20091fdabc6SPierre Aubert 	memset(rpmb_frame, 0, sizeof(struct s_rpmb));
20191fdabc6SPierre Aubert 	rpmb_frame->request = cpu_to_be16(RPMB_REQ_WCOUNTER);
20291fdabc6SPierre Aubert 	if (mmc_rpmb_request(mmc, rpmb_frame, 1, false))
20391fdabc6SPierre Aubert 		return -1;
20491fdabc6SPierre Aubert 
20591fdabc6SPierre Aubert 	/* Read the result */
20697a8a900Shisping 	ret = mmc_rpmb_response(mmc, rpmb_frame, RPMB_RESP_WCOUNTER, 1);
20791fdabc6SPierre Aubert 	if (ret)
20891fdabc6SPierre Aubert 		return ret;
20991fdabc6SPierre Aubert 
21091fdabc6SPierre Aubert 	*pcounter = be32_to_cpu(rpmb_frame->write_counter);
21191fdabc6SPierre Aubert 	return 0;
21291fdabc6SPierre Aubert }
mmc_rpmb_set_key(struct mmc * mmc,void * key)21391fdabc6SPierre Aubert int mmc_rpmb_set_key(struct mmc *mmc, void *key)
21491fdabc6SPierre Aubert {
21591fdabc6SPierre Aubert 	ALLOC_CACHE_ALIGN_BUFFER(struct s_rpmb, rpmb_frame, 1);
21691fdabc6SPierre Aubert 	/* Fill the request */
21791fdabc6SPierre Aubert 	memset(rpmb_frame, 0, sizeof(struct s_rpmb));
21891fdabc6SPierre Aubert 	rpmb_frame->request = cpu_to_be16(RPMB_REQ_KEY);
21991fdabc6SPierre Aubert 	memcpy(rpmb_frame->mac, key, RPMB_SZ_MAC);
22091fdabc6SPierre Aubert 
22191fdabc6SPierre Aubert 	if (mmc_rpmb_request(mmc, rpmb_frame, 1, true))
22291fdabc6SPierre Aubert 		return -1;
22391fdabc6SPierre Aubert 
22491fdabc6SPierre Aubert 	/* read the operation status */
22591fdabc6SPierre Aubert 	return mmc_rpmb_status(mmc, RPMB_RESP_KEY);
22691fdabc6SPierre Aubert }
mmc_rpmb_read(struct mmc * mmc,void * addr,unsigned short blk,unsigned short cnt,unsigned char * key)22791fdabc6SPierre Aubert int mmc_rpmb_read(struct mmc *mmc, void *addr, unsigned short blk,
22891fdabc6SPierre Aubert 		  unsigned short cnt, unsigned char *key)
22991fdabc6SPierre Aubert {
23097a8a900Shisping 	ALLOC_CACHE_ALIGN_BUFFER
23197a8a900Shisping 		(char, rpmb_frame_data,
23297a8a900Shisping 		sizeof(struct s_rpmb) * cnt);
23397a8a900Shisping 	ALLOC_CACHE_ALIGN_BUFFER
23497a8a900Shisping 		(char, rpmb_frame_data_verify,
23597a8a900Shisping 		sizeof(struct s_rpmb_verify) * cnt);
23697a8a900Shisping 	struct s_rpmb *rpmb_frame;
23797a8a900Shisping 	struct s_rpmb_verify *rpmb_frame_vrify;
23891fdabc6SPierre Aubert 	int i;
23991fdabc6SPierre Aubert 
24097a8a900Shisping 	memset(rpmb_frame_data, 0, sizeof(struct s_rpmb) * cnt);
24197a8a900Shisping 	memset(rpmb_frame_data_verify, 0, sizeof(struct s_rpmb_verify) * cnt);
24297a8a900Shisping 	rpmb_frame = (struct s_rpmb *)rpmb_frame_data;
24397a8a900Shisping 	rpmb_frame->address = cpu_to_be16(blk);
24491fdabc6SPierre Aubert 	rpmb_frame->request = cpu_to_be16(RPMB_REQ_READ_DATA);
24597a8a900Shisping 	if (mmc_rpmb_request(mmc, rpmb_frame, 1, false)) {
24697a8a900Shisping 		printf("mmc_rpmb_read request error\n");
24797a8a900Shisping 		return -1;
24897a8a900Shisping 	}
24991fdabc6SPierre Aubert 
25097a8a900Shisping 	if (mmc_rpmb_response
25197a8a900Shisping 			(mmc,
25297a8a900Shisping 			(struct s_rpmb *)rpmb_frame_data,
25397a8a900Shisping 			RPMB_RESP_READ_DATA, cnt)) {
25497a8a900Shisping 		printf("mmc_rpmb_read response error\n");
25597a8a900Shisping 		return -1;
25697a8a900Shisping 	}
25791fdabc6SPierre Aubert 
25897a8a900Shisping 	for (i = 0; i < cnt; i++) {
25997a8a900Shisping 		rpmb_frame = (struct s_rpmb *)
26097a8a900Shisping 					(rpmb_frame_data +
26197a8a900Shisping 					i * sizeof(struct s_rpmb));
26297a8a900Shisping 
26397a8a900Shisping 		rpmb_frame_vrify = (struct s_rpmb_verify *)
26497a8a900Shisping 					(rpmb_frame_data_verify +
26597a8a900Shisping 					i * sizeof(struct s_rpmb_verify));
26697a8a900Shisping 		memcpy(addr + i * RPMB_SZ_DATA, rpmb_frame->data, RPMB_SZ_DATA);
26797a8a900Shisping 		memcpy(rpmb_frame_vrify->data, rpmb_frame->data, 284);
26897a8a900Shisping 	}
26997a8a900Shisping 
27091fdabc6SPierre Aubert 	if (key) {
27191fdabc6SPierre Aubert 		unsigned char ret_hmac[RPMB_SZ_MAC];
27297a8a900Shisping 		rpmb_hmac
27397a8a900Shisping 			(key, (unsigned char *)rpmb_frame_data_verify,
27497a8a900Shisping 			284 * cnt, ret_hmac);
27591fdabc6SPierre Aubert 		if (memcmp(ret_hmac, rpmb_frame->mac, RPMB_SZ_MAC)) {
27691fdabc6SPierre Aubert 			printf("MAC error on block #%d\n", i);
27797a8a900Shisping 			return -1;
27891fdabc6SPierre Aubert 		}
27991fdabc6SPierre Aubert 	}
28097a8a900Shisping 
28197a8a900Shisping 	return cnt;
28291fdabc6SPierre Aubert }
mmc_rpmb_write(struct mmc * mmc,void * addr,unsigned short blk,unsigned short cnt,unsigned char * key)28391fdabc6SPierre Aubert int mmc_rpmb_write(struct mmc *mmc, void *addr, unsigned short blk,
28491fdabc6SPierre Aubert 		  unsigned short cnt, unsigned char *key)
28591fdabc6SPierre Aubert {
28697a8a900Shisping 	struct s_rpmb *rpmb_frame;
28797a8a900Shisping 	struct s_rpmb_verify *rpmb_frame_vrify;
28897a8a900Shisping 	ALLOC_CACHE_ALIGN_BUFFER
28997a8a900Shisping 		(char, rpmb_frame_data,
29097a8a900Shisping 		sizeof(struct s_rpmb) * cnt);
29197a8a900Shisping 	ALLOC_CACHE_ALIGN_BUFFER
29297a8a900Shisping 		(char, rpmb_frame_data_verify,
29397a8a900Shisping 		sizeof(struct s_rpmb_verify) * cnt);
29491fdabc6SPierre Aubert 
29597a8a900Shisping 	unsigned long wcount;
29697a8a900Shisping 	unsigned short i;
29797a8a900Shisping 	unsigned short temp;
29897a8a900Shisping 
29997a8a900Shisping 	temp = cnt - 1;
30097a8a900Shisping 	memset(rpmb_frame_data, 0, sizeof(struct s_rpmb) * cnt);
30197a8a900Shisping 	memset(rpmb_frame_data_verify, 0, sizeof(struct s_rpmb_verify) * cnt);
30291fdabc6SPierre Aubert 	for (i = 0; i < cnt; i++) {
30397a8a900Shisping 		if (i == 0) {
30491fdabc6SPierre Aubert 			if (mmc_rpmb_get_counter(mmc, &wcount)) {
30591fdabc6SPierre Aubert 				printf("Cannot read RPMB write counter\n");
30691fdabc6SPierre Aubert 				break;
30791fdabc6SPierre Aubert 			}
30891fdabc6SPierre Aubert 		}
30997a8a900Shisping 
31097a8a900Shisping 		rpmb_frame = (struct s_rpmb *)
31197a8a900Shisping 			(rpmb_frame_data +
31297a8a900Shisping 			i * sizeof(struct s_rpmb));
31397a8a900Shisping 		rpmb_frame_vrify = (struct s_rpmb_verify *)
31497a8a900Shisping 			(rpmb_frame_data_verify +
31597a8a900Shisping 			i * sizeof(struct s_rpmb_verify));
31697a8a900Shisping 		memcpy(rpmb_frame->data, addr + i * RPMB_SZ_DATA, RPMB_SZ_DATA);
31797a8a900Shisping 		memcpy(rpmb_frame_vrify->data, addr +
31897a8a900Shisping 			i * RPMB_SZ_DATA, RPMB_SZ_DATA);
31997a8a900Shisping 		rpmb_frame->address = cpu_to_be16(blk);
32097a8a900Shisping 		rpmb_frame_vrify->address = cpu_to_be16(blk);
32197a8a900Shisping 		rpmb_frame->block_count = cpu_to_be16(cnt);
32297a8a900Shisping 		rpmb_frame_vrify->block_count = cpu_to_be16(cnt);
32397a8a900Shisping 		rpmb_frame->write_counter = cpu_to_be32(wcount);
32497a8a900Shisping 		rpmb_frame_vrify->write_counter = cpu_to_be32(wcount);
32597a8a900Shisping 		rpmb_frame->request = cpu_to_be16(RPMB_REQ_WRITE_DATA);
32697a8a900Shisping 		rpmb_frame_vrify->request = cpu_to_be16(RPMB_REQ_WRITE_DATA);
32797a8a900Shisping 		if (i == temp) {
32897a8a900Shisping 			rpmb_hmac
32997a8a900Shisping 				(key, (unsigned char *)rpmb_frame_data_verify,
33097a8a900Shisping 				284 * cnt, rpmb_frame->mac);
33197a8a900Shisping 		}
33297a8a900Shisping 	}
33397a8a900Shisping 	if (mmc_rpmb_request(mmc, rpmb_frame_data, cnt, true))
33497a8a900Shisping 		return -1;
33597a8a900Shisping 
33697a8a900Shisping 	if (mmc_rpmb_status(mmc, RPMB_RESP_WRITE_DATA))
33797a8a900Shisping 		return -1;
33897a8a900Shisping 	return cnt;
33991fdabc6SPierre Aubert }
340ea5fd1c6SHisping Lin 
read_counter(struct mmc * mmc,struct s_rpmb * requestpackets)341ea5fd1c6SHisping Lin int read_counter(struct mmc *mmc, struct s_rpmb *requestpackets)
342ea5fd1c6SHisping Lin {
343ea5fd1c6SHisping Lin 	if (mmc_rpmb_request(mmc, requestpackets, 1, false))
344ea5fd1c6SHisping Lin 		return -1;
345ea5fd1c6SHisping Lin 
346ea5fd1c6SHisping Lin 	if (mmc_rpmb_response(mmc, requestpackets, RPMB_RESP_WCOUNTER, 1))
347ea5fd1c6SHisping Lin 		return -1;
348ea5fd1c6SHisping Lin 
349ea5fd1c6SHisping Lin 	return 0;
350ea5fd1c6SHisping Lin }
351ea5fd1c6SHisping Lin 
program_key(struct mmc * mmc,struct s_rpmb * requestpackets)352ea5fd1c6SHisping Lin int program_key(struct mmc *mmc, struct s_rpmb *requestpackets)
353ea5fd1c6SHisping Lin {
354ea5fd1c6SHisping Lin 	if (mmc_rpmb_request(mmc, requestpackets, 1, true))
355ea5fd1c6SHisping Lin 		return -1;
356ea5fd1c6SHisping Lin 
357ea5fd1c6SHisping Lin 	memset(requestpackets, 0, sizeof(struct s_rpmb));
358ea5fd1c6SHisping Lin 
359ea5fd1c6SHisping Lin 	requestpackets->request = cpu_to_be16(RPMB_REQ_STATUS);
360ea5fd1c6SHisping Lin 
361ea5fd1c6SHisping Lin 	if (mmc_rpmb_request(mmc, requestpackets, 1, false))
362ea5fd1c6SHisping Lin 		return -1;
363ea5fd1c6SHisping Lin 
364ea5fd1c6SHisping Lin 	return mmc_rpmb_response(mmc, requestpackets, RPMB_RESP_KEY, 1);
365ea5fd1c6SHisping Lin }
366ea5fd1c6SHisping Lin 
authenticated_read(struct mmc * mmc,struct s_rpmb * requestpackets,uint16_t block_count)367ea5fd1c6SHisping Lin int authenticated_read(struct mmc *mmc,
368ea5fd1c6SHisping Lin 	struct s_rpmb *requestpackets, uint16_t block_count)
369ea5fd1c6SHisping Lin {
370ea5fd1c6SHisping Lin 	if (mmc_rpmb_request(mmc, requestpackets, 1, false))
371ea5fd1c6SHisping Lin 		return -1;
372ea5fd1c6SHisping Lin 
373ea5fd1c6SHisping Lin 	if (mmc_rpmb_response
374ea5fd1c6SHisping Lin 		(mmc, requestpackets, RPMB_RESP_READ_DATA, block_count))
375ea5fd1c6SHisping Lin 		return -1;
376ea5fd1c6SHisping Lin 
377ea5fd1c6SHisping Lin 	return 0;
378ea5fd1c6SHisping Lin }
379ea5fd1c6SHisping Lin 
authenticated_write(struct mmc * mmc,struct s_rpmb * requestpackets)380ea5fd1c6SHisping Lin int authenticated_write(struct mmc *mmc, struct s_rpmb *requestpackets)
381ea5fd1c6SHisping Lin {
382ea5fd1c6SHisping Lin 	if (mmc_rpmb_request(mmc, requestpackets, 1, true))
383ea5fd1c6SHisping Lin 		return -1;
384ea5fd1c6SHisping Lin 
385ea5fd1c6SHisping Lin 	memset(requestpackets, 0, sizeof(struct s_rpmb));
386ea5fd1c6SHisping Lin 
387ea5fd1c6SHisping Lin 	requestpackets->request = cpu_to_be16(RPMB_REQ_STATUS);
388ea5fd1c6SHisping Lin 
389ea5fd1c6SHisping Lin 	if (mmc_rpmb_request(mmc, requestpackets, 1, false))
390ea5fd1c6SHisping Lin 		return -1;
391ea5fd1c6SHisping Lin 
392ea5fd1c6SHisping Lin 	return mmc_rpmb_response(mmc, requestpackets, RPMB_RESP_WRITE_DATA, 1);
393ea5fd1c6SHisping Lin }
394ea5fd1c6SHisping Lin 
395