1 /* 2 * (C) Copyright 2013 3 * Reinhard Pfau, Guntermann & Drunck GmbH, reinhard.pfau@gdsys.cc 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <common.h> 9 #include <malloc.h> 10 #include <fs.h> 11 #include <i2c.h> 12 #include <mmc.h> 13 #include <tpm.h> 14 #include <u-boot/sha1.h> 15 #include <asm/byteorder.h> 16 #include <asm/unaligned.h> 17 #include <pca9698.h> 18 19 #include "hre.h" 20 21 /* other constants */ 22 enum { 23 ESDHC_BOOT_IMAGE_SIG_OFS = 0x40, 24 ESDHC_BOOT_IMAGE_SIZE_OFS = 0x48, 25 ESDHC_BOOT_IMAGE_ADDR_OFS = 0x50, 26 ESDHC_BOOT_IMAGE_TARGET_OFS = 0x58, 27 ESDHC_BOOT_IMAGE_ENTRY_OFS = 0x60, 28 }; 29 30 enum { 31 I2C_SOC_0 = 0, 32 I2C_SOC_1 = 1, 33 }; 34 35 enum access_mode { 36 HREG_NONE = 0, 37 HREG_RD = 1, 38 HREG_WR = 2, 39 HREG_RDWR = 3, 40 }; 41 42 /* register constants */ 43 enum { 44 FIX_HREG_DEVICE_ID_HASH = 0, 45 FIX_HREG_UNUSED1 = 1, 46 FIX_HREG_UNUSED2 = 2, 47 FIX_HREG_VENDOR = 3, 48 COUNT_FIX_HREGS 49 }; 50 51 static struct h_reg pcr_hregs[24]; 52 static struct h_reg fix_hregs[COUNT_FIX_HREGS]; 53 static struct h_reg var_hregs[8]; 54 55 /* hre opcodes */ 56 enum { 57 /* opcodes w/o data */ 58 HRE_NOP = 0x00, 59 HRE_SYNC = HRE_NOP, 60 HRE_CHECK0 = 0x01, 61 /* opcodes w/o data, w/ sync dst */ 62 /* opcodes w/ data */ 63 HRE_LOAD = 0x81, 64 /* opcodes w/data, w/sync dst */ 65 HRE_XOR = 0xC1, 66 HRE_AND = 0xC2, 67 HRE_OR = 0xC3, 68 HRE_EXTEND = 0xC4, 69 HRE_LOADKEY = 0xC5, 70 }; 71 72 /* hre errors */ 73 enum { 74 HRE_E_OK = 0, 75 HRE_E_TPM_FAILURE, 76 HRE_E_INVALID_HREG, 77 }; 78 79 static uint64_t device_id; 80 static uint64_t device_cl; 81 static uint64_t device_type; 82 83 static uint32_t platform_key_handle; 84 85 static uint32_t hre_tpm_err; 86 static int hre_err = HRE_E_OK; 87 88 #define IS_PCR_HREG(spec) ((spec) & 0x20) 89 #define IS_FIX_HREG(spec) (((spec) & 0x38) == 0x08) 90 #define IS_VAR_HREG(spec) (((spec) & 0x38) == 0x10) 91 #define HREG_IDX(spec) ((spec) & (IS_PCR_HREG(spec) ? 0x1f : 0x7)) 92 93 static const uint8_t vendor[] = "Guntermann & Drunck"; 94 95 /** 96 * @brief get the size of a given (TPM) NV area 97 * @param index NV index of the area to get size for 98 * @param size pointer to the size 99 * @return 0 on success, != 0 on error 100 */ 101 static int get_tpm_nv_size(uint32_t index, uint32_t *size) 102 { 103 uint32_t err; 104 uint8_t info[72]; 105 uint8_t *ptr; 106 uint16_t v16; 107 108 err = tpm_get_capability(TPM_CAP_NV_INDEX, index, 109 info, sizeof(info)); 110 if (err) { 111 printf("tpm_get_capability(CAP_NV_INDEX, %08x) failed: %u\n", 112 index, err); 113 return 1; 114 } 115 116 /* skip tag and nvIndex */ 117 ptr = info + 6; 118 /* skip 2 pcr info fields */ 119 v16 = get_unaligned_be16(ptr); 120 ptr += 2 + v16 + 1 + 20; 121 v16 = get_unaligned_be16(ptr); 122 ptr += 2 + v16 + 1 + 20; 123 /* skip permission and flags */ 124 ptr += 6 + 3; 125 126 *size = get_unaligned_be32(ptr); 127 return 0; 128 } 129 130 /** 131 * @brief search for a key by usage auth and pub key hash. 132 * @param auth usage auth of the key to search for 133 * @param pubkey_digest (SHA1) hash of the pub key structure of the key 134 * @param[out] handle the handle of the key iff found 135 * @return 0 if key was found in TPM; != 0 if not. 136 */ 137 static int find_key(const uint8_t auth[20], const uint8_t pubkey_digest[20], 138 uint32_t *handle) 139 { 140 uint16_t key_count; 141 uint32_t key_handles[10]; 142 uint8_t buf[288]; 143 uint8_t *ptr; 144 uint32_t err; 145 uint8_t digest[20]; 146 size_t buf_len; 147 unsigned int i; 148 149 /* fetch list of already loaded keys in the TPM */ 150 err = tpm_get_capability(TPM_CAP_HANDLE, TPM_RT_KEY, buf, sizeof(buf)); 151 if (err) 152 return -1; 153 key_count = get_unaligned_be16(buf); 154 ptr = buf + 2; 155 for (i = 0; i < key_count; ++i, ptr += 4) 156 key_handles[i] = get_unaligned_be32(ptr); 157 158 /* now search a(/ the) key which we can access with the given auth */ 159 for (i = 0; i < key_count; ++i) { 160 buf_len = sizeof(buf); 161 err = tpm_get_pub_key_oiap(key_handles[i], auth, buf, &buf_len); 162 if (err && err != TPM_AUTHFAIL) 163 return -1; 164 if (err) 165 continue; 166 sha1_csum(buf, buf_len, digest); 167 if (!memcmp(digest, pubkey_digest, 20)) { 168 *handle = key_handles[i]; 169 return 0; 170 } 171 } 172 return 1; 173 } 174 175 /** 176 * @brief read CCDM common data from TPM NV 177 * @return 0 if CCDM common data was found and read, !=0 if something failed. 178 */ 179 static int read_common_data(void) 180 { 181 uint32_t size = 0; 182 uint32_t err; 183 uint8_t buf[256]; 184 sha1_context ctx; 185 186 if (get_tpm_nv_size(NV_COMMON_DATA_INDEX, &size) || 187 size < NV_COMMON_DATA_MIN_SIZE) 188 return 1; 189 err = tpm_nv_read_value(NV_COMMON_DATA_INDEX, 190 buf, min(sizeof(buf), size)); 191 if (err) { 192 printf("tpm_nv_read_value() failed: %u\n", err); 193 return 1; 194 } 195 196 device_id = get_unaligned_be64(buf); 197 device_cl = get_unaligned_be64(buf + 8); 198 device_type = get_unaligned_be64(buf + 16); 199 200 sha1_starts(&ctx); 201 sha1_update(&ctx, buf, 24); 202 sha1_finish(&ctx, fix_hregs[FIX_HREG_DEVICE_ID_HASH].digest); 203 fix_hregs[FIX_HREG_DEVICE_ID_HASH].valid = true; 204 205 platform_key_handle = get_unaligned_be32(buf + 24); 206 207 return 0; 208 } 209 210 /** 211 * @brief get pointer to hash register by specification 212 * @param spec specification of a hash register 213 * @return pointer to hash register or NULL if @a spec does not qualify a 214 * valid hash register; NULL else. 215 */ 216 static struct h_reg *get_hreg(uint8_t spec) 217 { 218 uint8_t idx; 219 220 idx = HREG_IDX(spec); 221 if (IS_FIX_HREG(spec)) { 222 if (idx < ARRAY_SIZE(fix_hregs)) 223 return fix_hregs + idx; 224 hre_err = HRE_E_INVALID_HREG; 225 } else if (IS_PCR_HREG(spec)) { 226 if (idx < ARRAY_SIZE(pcr_hregs)) 227 return pcr_hregs + idx; 228 hre_err = HRE_E_INVALID_HREG; 229 } else if (IS_VAR_HREG(spec)) { 230 if (idx < ARRAY_SIZE(var_hregs)) 231 return var_hregs + idx; 232 hre_err = HRE_E_INVALID_HREG; 233 } 234 return NULL; 235 } 236 237 /** 238 * @brief get pointer of a hash register by specification and usage. 239 * @param spec specification of a hash register 240 * @param mode access mode (read or write or read/write) 241 * @return pointer to hash register if found and valid; NULL else. 242 * 243 * This func uses @a get_reg() to determine the hash register for a given spec. 244 * If a register is found it is validated according to the desired access mode. 245 * The value of automatic registers (PCR register and fixed registers) is 246 * loaded or computed on read access. 247 */ 248 static struct h_reg *access_hreg(uint8_t spec, enum access_mode mode) 249 { 250 struct h_reg *result; 251 252 result = get_hreg(spec); 253 if (!result) 254 return NULL; 255 256 if (mode & HREG_WR) { 257 if (IS_FIX_HREG(spec)) { 258 hre_err = HRE_E_INVALID_HREG; 259 return NULL; 260 } 261 } 262 if (mode & HREG_RD) { 263 if (!result->valid) { 264 if (IS_PCR_HREG(spec)) { 265 hre_tpm_err = tpm_pcr_read(HREG_IDX(spec), 266 result->digest, 20); 267 result->valid = (hre_tpm_err == TPM_SUCCESS); 268 } else if (IS_FIX_HREG(spec)) { 269 switch (HREG_IDX(spec)) { 270 case FIX_HREG_DEVICE_ID_HASH: 271 read_common_data(); 272 break; 273 case FIX_HREG_VENDOR: 274 memcpy(result->digest, vendor, 20); 275 result->valid = true; 276 break; 277 } 278 } else { 279 result->valid = true; 280 } 281 } 282 if (!result->valid) { 283 hre_err = HRE_E_INVALID_HREG; 284 return NULL; 285 } 286 } 287 288 return result; 289 } 290 291 static void *compute_and(void *_dst, const void *_src, size_t n) 292 { 293 uint8_t *dst = _dst; 294 const uint8_t *src = _src; 295 size_t i; 296 297 for (i = n; i-- > 0; ) 298 *dst++ &= *src++; 299 300 return _dst; 301 } 302 303 static void *compute_or(void *_dst, const void *_src, size_t n) 304 { 305 uint8_t *dst = _dst; 306 const uint8_t *src = _src; 307 size_t i; 308 309 for (i = n; i-- > 0; ) 310 *dst++ |= *src++; 311 312 return _dst; 313 } 314 315 static void *compute_xor(void *_dst, const void *_src, size_t n) 316 { 317 uint8_t *dst = _dst; 318 const uint8_t *src = _src; 319 size_t i; 320 321 for (i = n; i-- > 0; ) 322 *dst++ ^= *src++; 323 324 return _dst; 325 } 326 327 static void *compute_extend(void *_dst, const void *_src, size_t n) 328 { 329 uint8_t digest[20]; 330 sha1_context ctx; 331 332 sha1_starts(&ctx); 333 sha1_update(&ctx, _dst, n); 334 sha1_update(&ctx, _src, n); 335 sha1_finish(&ctx, digest); 336 memcpy(_dst, digest, min(n, sizeof(digest))); 337 338 return _dst; 339 } 340 341 static int hre_op_loadkey(struct h_reg *src_reg, struct h_reg *dst_reg, 342 const void *key, size_t key_size) 343 { 344 uint32_t parent_handle; 345 uint32_t key_handle; 346 347 if (!src_reg || !dst_reg || !src_reg->valid || !dst_reg->valid) 348 return -1; 349 if (find_key(src_reg->digest, dst_reg->digest, &parent_handle)) 350 return -1; 351 hre_tpm_err = tpm_load_key2_oiap(parent_handle, key, key_size, 352 src_reg->digest, &key_handle); 353 if (hre_tpm_err) { 354 hre_err = HRE_E_TPM_FAILURE; 355 return -1; 356 } 357 358 return 0; 359 } 360 361 /** 362 * @brief executes the next opcode on the hash register engine. 363 * @param[in,out] ip pointer to the opcode (instruction pointer) 364 * @param[in,out] code_size (remaining) size of the code 365 * @return new instruction pointer on success, NULL on error. 366 */ 367 static const uint8_t *hre_execute_op(const uint8_t **ip, size_t *code_size) 368 { 369 bool dst_modified = false; 370 uint32_t ins; 371 uint8_t opcode; 372 uint8_t src_spec; 373 uint8_t dst_spec; 374 uint16_t data_size; 375 struct h_reg *src_reg, *dst_reg; 376 uint8_t buf[20]; 377 const uint8_t *src_buf, *data; 378 uint8_t *ptr; 379 int i; 380 void * (*bin_func)(void *, const void *, size_t); 381 382 if (*code_size < 4) 383 return NULL; 384 385 ins = get_unaligned_be32(*ip); 386 opcode = **ip; 387 data = *ip + 4; 388 src_spec = (ins >> 18) & 0x3f; 389 dst_spec = (ins >> 12) & 0x3f; 390 data_size = (ins & 0x7ff); 391 392 debug("HRE: ins=%08x (op=%02x, s=%02x, d=%02x, L=%d)\n", ins, 393 opcode, src_spec, dst_spec, data_size); 394 395 if ((opcode & 0x80) && (data_size + 4) > *code_size) 396 return NULL; 397 398 src_reg = access_hreg(src_spec, HREG_RD); 399 if (hre_err || hre_tpm_err) 400 return NULL; 401 dst_reg = access_hreg(dst_spec, (opcode & 0x40) ? HREG_RDWR : HREG_WR); 402 if (hre_err || hre_tpm_err) 403 return NULL; 404 405 switch (opcode) { 406 case HRE_NOP: 407 goto end; 408 case HRE_CHECK0: 409 if (src_reg) { 410 for (i = 0; i < 20; ++i) { 411 if (src_reg->digest[i]) 412 return NULL; 413 } 414 } 415 break; 416 case HRE_LOAD: 417 bin_func = memcpy; 418 goto do_bin_func; 419 case HRE_XOR: 420 bin_func = compute_xor; 421 goto do_bin_func; 422 case HRE_AND: 423 bin_func = compute_and; 424 goto do_bin_func; 425 case HRE_OR: 426 bin_func = compute_or; 427 goto do_bin_func; 428 case HRE_EXTEND: 429 bin_func = compute_extend; 430 do_bin_func: 431 if (!dst_reg) 432 return NULL; 433 if (src_reg) { 434 src_buf = src_reg->digest; 435 } else { 436 if (!data_size) { 437 memset(buf, 0, 20); 438 src_buf = buf; 439 } else if (data_size == 1) { 440 memset(buf, *data, 20); 441 src_buf = buf; 442 } else if (data_size >= 20) { 443 src_buf = data; 444 } else { 445 src_buf = buf; 446 for (ptr = (uint8_t *)src_buf, i = 20; i > 0; 447 i -= data_size, ptr += data_size) 448 memcpy(ptr, data, 449 min_t(size_t, i, data_size)); 450 } 451 } 452 bin_func(dst_reg->digest, src_buf, 20); 453 dst_reg->valid = true; 454 dst_modified = true; 455 break; 456 case HRE_LOADKEY: 457 if (hre_op_loadkey(src_reg, dst_reg, data, data_size)) 458 return NULL; 459 break; 460 default: 461 return NULL; 462 } 463 464 if (dst_reg && dst_modified && IS_PCR_HREG(dst_spec)) { 465 hre_tpm_err = tpm_extend(HREG_IDX(dst_spec), dst_reg->digest, 466 dst_reg->digest); 467 if (hre_tpm_err) { 468 hre_err = HRE_E_TPM_FAILURE; 469 return NULL; 470 } 471 } 472 end: 473 *ip += 4; 474 *code_size -= 4; 475 if (opcode & 0x80) { 476 *ip += data_size; 477 *code_size -= data_size; 478 } 479 480 return *ip; 481 } 482 483 /** 484 * @brief runs a program on the hash register engine. 485 * @param code pointer to the (HRE) code. 486 * @param code_size size of the code (in bytes). 487 * @return 0 on success, != 0 on failure. 488 */ 489 int hre_run_program(const uint8_t *code, size_t code_size) 490 { 491 size_t code_left; 492 const uint8_t *ip = code; 493 494 code_left = code_size; 495 hre_tpm_err = 0; 496 hre_err = HRE_E_OK; 497 while (code_left > 0) 498 if (!hre_execute_op(&ip, &code_left)) 499 return -1; 500 501 return hre_err; 502 } 503 504 int hre_verify_program(struct key_program *prg) 505 { 506 uint32_t crc; 507 508 crc = crc32(0, prg->code, prg->code_size); 509 510 if (crc != prg->code_crc) { 511 printf("HRC crc mismatch: %08x != %08x\n", 512 crc, prg->code_crc); 513 return 1; 514 } 515 return 0; 516 } 517