tools: add ability to specify creation data and pcrs Add a --creation-data <pcrs> option that specifies a possibly empty list of PCRs to be embedded in the greation data stored in the key file. Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
diff --git a/src/include/tpm2-common.h b/src/include/tpm2-common.h index ba27525..043bd69 100644 --- a/src/include/tpm2-common.h +++ b/src/include/tpm2-common.h
@@ -157,4 +157,8 @@ TPM_RC tpm2_pcrs_get_digests(TSS_CONTEXT *tssContext, TPML_PCR_SELECTION pcrread, TPM_ALG_ID hash_alg, DIGEST_2B *pcrDigest, TPML_DIGEST_VALUES *dv); +int tpm2_check_creation_pcrs(TSS_CONTEXT *tssContext, + TPML_PCR_SELECTION *creation_pcrs, + TPM2B_CREATION_DATA *creationData, + TPML_DIGEST_VALUES **pcrValues); #endif
diff --git a/src/libcommon/tpm2-common.c b/src/libcommon/tpm2-common.c index 2b31daa..7ec59f0 100644 --- a/src/libcommon/tpm2-common.c +++ b/src/libcommon/tpm2-common.c
@@ -3540,6 +3540,29 @@ return 0; } +/* returns true if the creation pcrs don't match the current values */ +int tpm2_check_creation_pcrs(TSS_CONTEXT *tssContext, + TPML_PCR_SELECTION *creation_pcrs, + TPM2B_CREATION_DATA *creationData, + TPML_DIGEST_VALUES **pcrValues) +{ + int count = tpm2_count_pcrs(creation_pcrs); + DIGEST_2B d; + + if (!creation_pcrs) + return 0; + + *pcrValues = malloc(sizeof((*pcrValues)->count) + + count*sizeof((*pcrValues)->digests[0])); + (*pcrValues)->count = 0; + tpm2_pcrs_get_digests(tssContext, *creation_pcrs, + name_alg, &d, *pcrValues); + if (memcmp(d.buffer, VAL_2B(creationData->creationData.pcrDigest, buffer), + VAL_2B(creationData->creationData.pcrDigest, size)) != 0) { + return 1; + } + return 0; +} static __attribute__((constructor)) void tpm2_init(void) { int fd;
diff --git a/src/tools/create_tpm2_key.c b/src/tools/create_tpm2_key.c index 14518e2..6aa0462 100644 --- a/src/tools/create_tpm2_key.c +++ b/src/tools/create_tpm2_key.c
@@ -32,6 +32,7 @@ #define OPT_LOCALITY 0x1fc #define OPT_SECRET 0x1fb #define OPT_DESCRIPTION 0x1fa +#define OPT_CREATION 0x1f9 static struct option long_options[] = { {"auth", 0, 0, 'a'}, @@ -55,6 +56,7 @@ {"restricted", 0, 0, OPT_RESTRICTED }, {"secret", 1, 0, OPT_SECRET }, {"description", 1, 0, OPT_DESCRIPTION}, + {"creation-data", 1, 0, OPT_CREATION}, /* * The option --deprecated allows us to create old format keys * for the purposes of testing. It should never be used in @@ -114,6 +116,8 @@ "\t Identified by <handle>.\n" "\t--description <desc> Specify a description string to be\n" "\t embedded in the key file\n" + "\t--creation-data <pcrs> request creation data with the given\n" + "\t pcr list" "\n" "Report bugs to " PACKAGE_BUGREPORT "\n", argv0); @@ -492,8 +496,12 @@ int restricted = 0; char *parent_str = NULL; TPML_PCR_SELECTION pcr_lock = { 0 }; + TPML_PCR_SELECTION *creation_pcrs = NULL, tmp_tpml = { 0 }; int has_policy = 0, has_locality = 0; UINT8 locality = 0; + TPM2B_CREATION_DATA creationData; + TPMT_TK_CREATION creationTicket; + TPML_DIGEST_VALUES *pcrValues = NULL; OpenSSL_add_all_digests(); /* may be needed to decrypt the key */ @@ -599,6 +607,10 @@ case OPT_DESCRIPTION: description = optarg; break; + case OPT_CREATION: + tpm2_get_pcr_lock(&tmp_tpml, optarg); + creation_pcrs = &tmp_tpml; + break; default: printf("Unknown option '%c'\n", c); usage(argv[0]); @@ -626,6 +638,11 @@ key_size = 2048; } + if (wrap && creation_pcrs) { + fprintf(stderr, "creation data can't be added to wrapped keys\n"); + usage(argv[0]); + } + if (rsa == 1 && ecc != TPM_ECC_NONE) { fprintf(stderr, "Cannot specify both --rsa and --ecc\n"); exit(1); @@ -947,7 +964,8 @@ rc = tpm2_Create(tssContext, phandle, &inSensitive, &objectPublic, &outPrivate, &outPublic, - authHandle, parent_auth, NULL, NULL, NULL); + authHandle, parent_auth, creation_pcrs, + &creationData, &creationTicket); if (rc) { reason = "TPM2_Create"; @@ -956,6 +974,13 @@ goto out_flush; } + if (tpm2_check_creation_pcrs(tssContext, creation_pcrs, + &creationData, &pcrValues)) { + rc = NOT_TPM_ERROR; + reason = "creation data PCR mismatch"; + goto out_flush; + } + pub = &outPublic; priv = &outPrivate; } @@ -978,7 +1003,7 @@ privkey, privkey_len, auth == NULL && secret_handle == 0, parent, sk, version, enc_secret, description, - NULL, NULL, NULL); + &creationData, &creationTicket, pcrValues); tpm2_free_policy(sk); exit(0);
diff --git a/src/tools/seal_tpm2_data.c b/src/tools/seal_tpm2_data.c index 33cf07b..4b37f5e 100644 --- a/src/tools/seal_tpm2_data.c +++ b/src/tools/seal_tpm2_data.c
@@ -25,6 +25,7 @@ #define OPT_LOCALITY 0x1fc #define OPT_SECRET 0x1fb #define OPT_DESCRIPTION 0x1fa +#define OPT_CREATION 0x1f9 static struct option long_options[] = { {"auth", 0, 0, 'a'}, @@ -43,6 +44,7 @@ {"name-scheme", 1, 0, 'n'}, {"import", 1, 0, 'i'}, {"description", 1, 0, OPT_DESCRIPTION }, + {"creation-data", 1, 0, OPT_CREATION}, {0, 0, 0, 0} }; @@ -97,6 +99,8 @@ "\t-c, --policy Specify a policy for unsealing the data\n" "\t--description <desc> Specify a description string to be\n" "\t embedded in the key file\n" + "\t--creation-data <pcrs> request creation data with the given\n" + "\t pcr list" "\n" "\n" "Report bugs to " PACKAGE_BUGREPORT "\n", @@ -158,6 +162,10 @@ char *signed_policy = NULL; ENCRYPTED_SECRET_2B secret, *enc_secret = NULL; int has_locality = 0, locality = 0; + TPML_PCR_SELECTION *creation_pcrs = NULL, tmp_tpml = { 0 }; + TPM2B_CREATION_DATA creationData; + TPMT_TK_CREATION creationTicket; + TPML_DIGEST_VALUES *pcrValues = NULL; pcr_lock.count = 0; @@ -239,6 +247,10 @@ case OPT_DESCRIPTION: description = optarg; break; + case OPT_CREATION: + tpm2_get_pcr_lock(&tmp_tpml, optarg); + creation_pcrs = &tmp_tpml; + break; default: printf("Unknown option '%c'\n", c); usage(argv[0]); @@ -267,6 +279,11 @@ exit(1); } + if (import && creation_pcrs) { + fprintf(stderr, "cannot get creation data when creating importable\n"); + exit(1); + } + if (has_locality && locality == 0) { fprintf(stderr, "zero is an illegal locality bitmap\n"); exit(1); @@ -439,7 +456,7 @@ rc = tpm2_Create(tssContext, phandle, &inSensitive, &inPublic, &outPrivate, &outPublic, authHandle, parent_auth, - NULL, NULL, NULL); + creation_pcrs, &creationData, &creationTicket); if (rc) { reason = "TPM2_Create"; @@ -448,6 +465,13 @@ goto out_flush; } + if (tpm2_check_creation_pcrs(tssContext, creation_pcrs, + &creationData, &pcrValues)) { + rc = NOT_TPM_ERROR; + reason = "creation data PCR mismatch"; + goto out_flush; + } + parent = tpm2_handle_ext(tssContext, parent); write_file: @@ -465,7 +489,7 @@ privkey, privkey_len, data_auth == NULL && secret_handle == 0, parent, sk, 2, enc_secret, description, - NULL, NULL, NULL); + &creationData, &creationTicket, pcrValues); out_flush: if (tssContext)