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