aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@HansenPartnership.com>2018-08-10 20:14:56 -0700
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2018-08-12 07:58:57 -0700
commited4ed23bc8990575345ad007bd944c8b79b6aaae (patch)
treef123d854a03a5d6102b2feea1e01f4312f0fd31a
parentb82de3cc6126d719a25487815c74b7ec5e7baf94 (diff)
downloadopenssl_tpm2_engine-ed4ed23bc8990575345ad007bd944c8b79b6aaae.tar.gz
policy: add the ability to have time limited keys
Implement TPM2_PolicyCounterTimer which allows comparison of the current counter and timer values. There is a problem with the policy file in that traditionally the policy file is simply hashed to make the final policy, but CounterTimer is different: the necessary information has to be hashed and then that hash is hashed into the policy meaning that we have to special case the TPM_CC_PolicyCounterTimer in the computation of the hash. Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
-rw-r--r--create_tpm2_key.c31
-rw-r--r--tests/Makefile.am1
-rwxr-xr-xtests/check_counter_timer.sh51
-rw-r--r--tpm2-common.c51
4 files changed, 126 insertions, 8 deletions
diff --git a/create_tpm2_key.c b/create_tpm2_key.c
index 9845520..f624acb 100644
--- a/create_tpm2_key.c
+++ b/create_tpm2_key.c
@@ -160,6 +160,10 @@ parse_policy_file(const char *policy_file, STACK_OF(TSSOPTPOLICY) *sk,
}
while ((data_ptr = strsep(&data, "\n"))) {
+ TPMT_HA hash_digest;
+ unsigned char *hash = (unsigned char *)hash_digest.digest.tssmax;
+ INT32 hash_len;
+
buf_ptr = buf;
buf_len = strlen(data_ptr) / 2;
if (buf_len > sizeof(buf)) {
@@ -178,18 +182,31 @@ parse_policy_file(const char *policy_file, STACK_OF(TSSOPTPOLICY) *sk,
goto out_munmap;
}
- rc = TSS_Hash_Generate(digest,
- TSS_GetDigestSize(digest->hashAlg),
- (uint8_t *)&digest->digest,
- buf_len, buf_ptr, 0, NULL);
+ rc = TPM_CC_Unmarshal(&code, &buf_ptr, &buf_len);
if (rc) {
- fprintf(stderr, "TSS_Hash_Generate() failed\n");
+ fprintf(stderr, "TPM_CC_Unmarshal() failed\n");
goto out_munmap;
}
- rc = TPM_CC_Unmarshal(&code, &buf_ptr, &buf_len);
+ if (code == TPM_CC_PolicyCounterTimer) {
+ /* for a countertimer, the policy is a hash of the hash */
+ hash_digest.hashAlg = digest->hashAlg;
+ hash_len = TSS_GetDigestSize(digest->hashAlg);
+ TSS_Hash_Generate(&hash_digest, buf_len, buf_ptr, 0, NULL);
+ hash = hash_digest.digest.tssmax;
+ } else {
+ hash = buf_ptr;
+ hash_len = buf_len;
+ }
+
+ rc = TSS_Hash_Generate(digest,
+ TSS_GetDigestSize(digest->hashAlg),
+ (uint8_t *)&digest->digest,
+ /* the command code */
+ 4, buf_ptr - 4,
+ hash_len, hash, 0, NULL);
if (rc) {
- fprintf(stderr, "TPM_CC_Unmarshal() failed\n");
+ fprintf(stderr, "TSS_Hash_Generate() failed\n");
goto out_munmap;
}
diff --git a/tests/Makefile.am b/tests/Makefile.am
index d9713d1..499ba20 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -15,6 +15,7 @@ TESTS = fail_connect.sh \
da_check.sh \
test_nv_key.sh \
check_enhanced_auth.sh \
+ check_counter_timer.sh \
stop_sw_tpm.sh
AM_TESTS_ENVIRONMENT = TPM_INTERFACE_TYPE=socsim; \
diff --git a/tests/check_counter_timer.sh b/tests/check_counter_timer.sh
new file mode 100755
index 0000000..987eaf0
--- /dev/null
+++ b/tests/check_counter_timer.sh
@@ -0,0 +1,51 @@
+#!/bin/bash
+
+bindir=${srcdir}/..
+
+##
+# create a policy based on the tpm current clock the failing policy
+# compares to current time and the passing one current time plus 10
+# minutes (provided it doesn't take 10 minutes to get to the test)
+##
+# get current TPM clock value
+clock=$(tssreadclock|awk '/TPMS_CLOCK_INFO clock/{print $3}')
+# add 10 minutes in ms
+clock=$[$clock + 600000]
+# TPM_CC_PolicyAuthValue
+echo "0000016b" > policy.txt
+# the TPM_CC_PolicyCounterTimer
+echo -n "0000016d" >> policy.txt
+# time value as a 8 byte number
+printf "%016x" $clock >> policy.txt
+# the offset of the clock and the <= unsigned operator
+echo "00080009" >> policy.txt
+
+##
+# test is
+# 1. create TPM internal private key with PolicyCounterTimer
+# 2. get the corresponding public key from the engine
+# 3. encode a message using the TPM key
+# 4. verify the message through the public key
+##
+${bindir}/create_tpm2_key key.tpm -a -k paSSW0RD -c policy.txt && \
+openssl rsa -engine tpm2 -inform engine -passin pass:paSSW0RD -in key.tpm -pubout -out key.pub && \
+echo "policy counter timer" | openssl rsautl -sign -passin pass:paSSW0RD -engine tpm2 -engine tpm2 -keyform engine -inkey key.tpm -out tmp.msg && \
+openssl rsautl -verify -in tmp.msg -inkey key.pub -pubin || exit 1
+
+##
+# advance the TPM clock by ten minutes and a second which should make
+# the policy fail and try the same test again
+##
+echo "Advance clock to expire key"
+clock=$[$clock+1000]
+tssclockset -hi o -clock ${clock} || exit 1
+
+##
+# now the signing operation should fail
+##
+echo "Check key failure due to counter timer policy"
+echo "policy fail counter timer" | openssl rsautl -sign -passin pass:paSSW0RD -engine tpm2 -engine tpm2 -keyform engine -inkey key.tpm -out tmp.msg 2> tmp.txt && exit 1
+# check we got the right failure message
+grep "Policy Failure: Counter Timer at offset 8 is not <=" tmp.txt
+
+
diff --git a/tpm2-common.c b/tpm2-common.c
index 0b704f2..d0f0831 100644
--- a/tpm2-common.c
+++ b/tpm2-common.c
@@ -616,7 +616,9 @@ TPM_RC tpm2_init_session(TSS_CONTEXT *tssContext, TPM_HANDLE handle,
TPM_RC rc = 0;
COMMAND_PARAMETERS in;
int i;
+ char reason[256];
+ reason[0] = '\0';
((PolicyPCR_In *)&in)->policySession = handle;
for (i = 0; i < num_commands; i++) {
@@ -631,6 +633,50 @@ TPM_RC tpm2_init_session(TSS_CONTEXT *tssContext, TPM_HANDLE handle,
break;
case TPM_CC_PolicyAuthValue:
break;
+ case TPM_CC_PolicyCounterTimer: {
+ PolicyCounterTimer_In *pctin = &in.PolicyCounterTimer;
+ BYTE *p_buffer;
+ INT32 p_size;
+ int i, c;
+ const char *const operand[] = {
+ [TPM_EO_EQ] = "==",
+ [TPM_EO_NEQ] = "!=",
+ [TPM_EO_SIGNED_GT] = ">(s)",
+ [TPM_EO_UNSIGNED_GT] = ">",
+ [TPM_EO_SIGNED_LT] = "<(s)",
+ [TPM_EO_UNSIGNED_LT] = "<",
+ [TPM_EO_SIGNED_GE] = ">=(s)",
+ [TPM_EO_UNSIGNED_GE] = ">=",
+ [TPM_EO_SIGNED_LE] = "<=(s)",
+ [TPM_EO_UNSIGNED_LE] = "<=",
+ [TPM_EO_BITSET] = "bitset",
+ [TPM_EO_BITCLEAR] = "bitclear",
+ };
+
+ /* last UINT16 is the operand */
+ p_buffer = policy + size - 2;
+ p_size = 2;
+ TPM_EO_Unmarshal(&pctin->operation, &p_buffer,
+ &p_size);
+ /* second to last UINT16 is the offset */
+ p_buffer = policy + size - 4;
+ p_size = 2;
+ UINT16_Unmarshal(&pctin->offset, &p_buffer, &p_size);
+
+ /* and the rest is the OperandB */
+ pctin->operandB.b.size = size - 4;
+ memcpy(pctin->operandB.b.buffer, policy, size - 4);
+
+ c = sprintf(reason,
+ "Counter Timer at offset %d is not %s ",
+ pctin->offset, operand[pctin->operation]);
+ for (i = 0; i < size - 4; i++)
+ c += sprintf(&reason[c], "%02x", policy[i]);
+
+ reason[c] = '\0';
+
+ break;
+ }
default:
fprintf(stderr, "Unsupported policy command %d\n",
commands[i].code);
@@ -650,7 +696,10 @@ TPM_RC tpm2_init_session(TSS_CONTEXT *tssContext, TPM_HANDLE handle,
commands[i].code,
TPM_RH_NULL, NULL, 0);
if (rc) {
- tpm2_error(rc, "policy command");
+ if (rc == TPM_RC_POLICY && reason[0])
+ fprintf(stderr, "Policy Failure: %s\n", reason);
+ else
+ tpm2_error(rc, "policy command");
goto out_flush;
}
}