summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormario.six@gdsys.cc <mario.six@gdsys.cc>2017-03-20 09:28:28 (GMT)
committerSimon Glass <sjg@chromium.org>2017-03-26 19:22:58 (GMT)
commit0f4b2ba1762d74c0b5520d99a58796d6ca78abf0 (patch)
tree28b6986105615b2a538e42cdaaf265955883bfd9
parent5efa1bfbfa871f5bc3f07357088e8cf3c19e6f61 (diff)
downloadu-boot-0f4b2ba1762d74c0b5520d99a58796d6ca78abf0.tar.xz
tpm: Add function to load keys via their parent's SHA1 hash
If we want to load a key into a TPM, we need to know the designated parent key's handle, so that the TPM is able to insert the key at the correct place in the key hierarchy. However, if we want to load a key whose designated parent key we also previously loaded ourselves, we first need to memorize this parent key's handle (since the handles for the key are chosen at random when they are inserted into the TPM). If we are, however, unable to do so, for example if the parent key is loaded into the TPM during production, and its child key during the actual boot, we must find a different mechanism to identify the parent key. To solve this problem, we add a function that allows U-Boot to load a key into the TPM using their designated parent key's SHA1 hash, and the corresponding auth data. Signed-off-by: Mario Six <mario.six@gdsys.cc> Reviewed-by: Simon Glass <sjg@chromium.org>
-rw-r--r--cmd/tpm.c49
-rw-r--r--drivers/tpm/Kconfig8
-rw-r--r--include/tpm.h12
-rw-r--r--lib/tpm.c40
4 files changed, 109 insertions, 0 deletions
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 <key_addr>, <key_len> bytes\n"
" into TPM using the parent key <parent_handle> with authorization\n"
" <usage_auth> (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 <key_addr>, <key_len> bytes\n"
+" into TPM using the parent hash <parent_hash> (20 bytes hex string)\n"
+" with authorization <usage_auth> (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 <key_handle> using\n"
" authorization <usage auth> (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 */