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