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