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