diff --git a/cmd/tpm.c b/cmd/tpm.c index 625fc43..91bd20d 100644 --- a/cmd/tpm.c +++ b/cmd/tpm.c @@ -592,6 +592,45 @@ static int do_tpm_oiap(cmd_tbl_t *cmdtp, int flag, return report_return_code(err); } +#ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1 +static int do_tpm_load_key_by_sha1(cmd_tbl_t *cmdtp, int flag, int argc, char * + const argv[]) +{ + uint32_t parent_handle = 0; + uint32_t key_len, key_handle, err; + uint8_t usage_auth[DIGEST_LENGTH]; + uint8_t parent_hash[DIGEST_LENGTH]; + void *key; + + if (argc < 5) + return CMD_RET_USAGE; + + parse_byte_string(argv[1], parent_hash, NULL); + key = (void *)simple_strtoul(argv[2], NULL, 0); + key_len = simple_strtoul(argv[3], NULL, 0); + if (strlen(argv[4]) != 2 * DIGEST_LENGTH) + return CMD_RET_FAILURE; + parse_byte_string(argv[4], usage_auth, NULL); + + err = tpm_find_key_sha1(usage_auth, parent_hash, &parent_handle); + if (err) { + printf("Could not find matching parent key (err = %d)\n", err); + return CMD_RET_FAILURE; + } + + printf("Found parent key %08x\n", parent_handle); + + err = tpm_load_key2_oiap(parent_handle, key, key_len, usage_auth, + &key_handle); + if (!err) { + printf("Key handle is 0x%x\n", key_handle); + setenv_hex("key_handle", key_handle); + } + + return report_return_code(err); +} +#endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */ + static int do_tpm_load_key2_oiap(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { @@ -756,6 +795,10 @@ static cmd_tbl_t tpm_commands[] = { do_tpm_end_oiap, "", ""), U_BOOT_CMD_MKENT(load_key2_oiap, 0, 1, do_tpm_load_key2_oiap, "", ""), +#ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1 + U_BOOT_CMD_MKENT(load_key_by_sha1, 0, 1, + do_tpm_load_key_by_sha1, "", ""), +#endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */ U_BOOT_CMD_MKENT(get_pub_key_oiap, 0, 1, do_tpm_get_pub_key_oiap, "", ""), #endif /* CONFIG_TPM_AUTH_SESSIONS */ @@ -826,6 +869,12 @@ U_BOOT_CMD(tpm, CONFIG_SYS_MAXARGS, 1, do_tpm, " - loads a key data from memory address , bytes\n" " into TPM using the parent key with authorization\n" " (20 bytes hex string).\n" +#ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1 +" load_key_by_sha1 parent_hash key_addr key_len usage_auth\n" +" - loads a key data from memory address , bytes\n" +" into TPM using the parent hash (20 bytes hex string)\n" +" with authorization (20 bytes hex string).\n" +#endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */ " get_pub_key_oiap key_handle usage_auth\n" " - get the public key portion of a loaded key using\n" " authorization (20 bytes hex string)\n" diff --git a/drivers/tpm/Kconfig b/drivers/tpm/Kconfig index 3490ee0..a54b6a9 100644 --- a/drivers/tpm/Kconfig +++ b/drivers/tpm/Kconfig @@ -88,4 +88,12 @@ config TPM_FLUSH_RESOURCES help Enable support to flush specific resources (e.g. keys) from the TPM. The functionality is available via the 'tpm' command as well. + +config TPM_LOAD_KEY_BY_SHA1 + bool "Enable TPM key loading by SHA1 support" + depends on TPM + help + Enable support to load keys into the TPM by identifying + their parent via the public key's SHA1 hash. + The functionality is available via the 'tpm' command as well. endmenu diff --git a/include/tpm.h b/include/tpm.h index 800f29c..f88388f 100644 --- a/include/tpm.h +++ b/include/tpm.h @@ -639,4 +639,16 @@ uint32_t tpm_get_permissions(uint32_t index, uint32_t *perm); */ uint32_t tpm_flush_specific(uint32_t key_handle, uint32_t resource_type); +#ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1 +/** + * Search for a key by usage AuthData and the hash of the parent's pub key. + * + * @param auth Usage auth of the key to search for + * @param pubkey_digest SHA1 hash of the pub key structure of the key + * @param[out] handle The handle of the key (Non-null iff found) + * @return 0 if key was found in TPM; != 0 if not. + */ +uint32_t tpm_find_key_sha1(const uint8_t auth[20], const uint8_t + pubkey_digest[20], uint32_t *handle); +#endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */ #endif /* __TPM_H */ diff --git a/lib/tpm.c b/lib/tpm.c index fb12214..cd7f88f 100644 --- a/lib/tpm.c +++ b/lib/tpm.c @@ -996,4 +996,44 @@ uint32_t tpm_get_pub_key_oiap(uint32_t key_handle, const void *usage_auth, return 0; } +#ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1 +uint32_t tpm_find_key_sha1(const uint8_t auth[20], const uint8_t + pubkey_digest[20], uint32_t *handle) +{ + uint16_t key_count; + uint32_t key_handles[10]; + uint8_t buf[288]; + uint8_t *ptr; + uint32_t err; + uint8_t digest[20]; + size_t buf_len; + unsigned int i; + + /* fetch list of already loaded keys in the TPM */ + err = tpm_get_capability(TPM_CAP_HANDLE, TPM_RT_KEY, buf, sizeof(buf)); + if (err) + return -1; + key_count = get_unaligned_be16(buf); + ptr = buf + 2; + for (i = 0; i < key_count; ++i, ptr += 4) + key_handles[i] = get_unaligned_be32(ptr); + + /* now search a(/ the) key which we can access with the given auth */ + for (i = 0; i < key_count; ++i) { + buf_len = sizeof(buf); + err = tpm_get_pub_key_oiap(key_handles[i], auth, buf, &buf_len); + if (err && err != TPM_AUTHFAIL) + return -1; + if (err) + continue; + sha1_csum(buf, buf_len, digest); + if (!memcmp(digest, pubkey_digest, 20)) { + *handle = key_handles[i]; + return 0; + } + } + return 1; +} +#endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */ + #endif /* CONFIG_TPM_AUTH_SESSIONS */