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