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