aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@HansenPartnership.com>2023-12-15 17:56:26 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2023-12-17 10:49:38 -0500
commit5721b68a89100ca42565a686df332c06f5754c4a (patch)
tree6f1ef341038e49c3ace571e4e6ce7d3831e861fa
parent3ec82b70ac2985cbf97a2b3ae7d4cec17a3a5c17 (diff)
downloadopenssl_tpm2_engine-5721b68a89100ca42565a686df332c06f5754c4a.tar.gz
tools: add policy secret option
Adds the option --secret <handle> to insert a reliance on the authorization of the object named by <handle> in the policy. This has implications for emptyAuth because if the PolicySecret statement appears in the policy, it must be set (meaning we can no longer condition this on auth being NULL). Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
-rw-r--r--src/include/tpm2-common.h4
-rw-r--r--src/libcommon/tpm2-common.c59
-rw-r--r--src/tools/create_tpm2_key.1.in12
-rw-r--r--src/tools/create_tpm2_key.c17
-rw-r--r--src/tools/seal_tpm2_data.1.in12
-rw-r--r--src/tools/seal_tpm2_data.c17
-rw-r--r--src/tools/signed_tpm2_policy.1.in12
-rw-r--r--src/tools/signed_tpm2_policy.c34
8 files changed, 160 insertions, 7 deletions
diff --git a/src/include/tpm2-common.h b/src/include/tpm2-common.h
index 8939ebc..c9b07ea 100644
--- a/src/include/tpm2-common.h
+++ b/src/include/tpm2-common.h
@@ -117,7 +117,9 @@ TPM_RC tpm2_ObjectPublic_GetName(NAME_2B *name, TPMT_PUBLIC *tpmtPublic);
TPM_RC tpm2_add_signed_policy(STACK_OF(TSSOPTPOLICY) *sk, char *key_file,
TPMT_HA *digest);
TPM_RC tpm2_new_signed_policy(char *tpmkey, char *policykey, char *engine,
- TSSAUTHPOLICY *ap, TPMT_HA *digest);
+ TSSAUTHPOLICY *ap, TPMT_HA *digest, int need_auth);
+TPM_RC tpm2_add_policy_secret(TSS_CONTEXT *tssContext, STACK_OF(TSSOPTPOLICY) *sk,
+ TPM_HANDLE handle, TPMT_HA *digest);
TPM_RC tpm2_outerwrap(EVP_PKEY *parent,
TPMT_SENSITIVE *s,
TPMT_PUBLIC *pub,
diff --git a/src/libcommon/tpm2-common.c b/src/libcommon/tpm2-common.c
index b8fe7f5..2ef8a27 100644
--- a/src/libcommon/tpm2-common.c
+++ b/src/libcommon/tpm2-common.c
@@ -981,6 +981,15 @@ TPM_RC tpm2_readpublic(TSS_CONTEXT *tssContext, TPM_HANDLE handle,
return tpm2_ReadPublic(tssContext, handle, pub, TPM_RH_NULL, NULL);
}
+static TPM_RC tpm2_readname(TSS_CONTEXT *tssContext, TPM_HANDLE handle,
+ NAME_2B *name)
+{
+ if (tpm2_handle_mso(tssContext, handle, TPM_HT_NV_INDEX))
+ return tpm2_NV_ReadPublic(tssContext, handle, name);
+ else
+ return tpm2_ReadPublic(tssContext, handle, NULL, TPM_RH_NULL, name);
+}
+
TPM_RC tpm2_get_bound_handle(TSS_CONTEXT *tssContext, TPM_HANDLE *handle,
TPM_HANDLE bind, const char *auth)
{
@@ -2474,7 +2483,7 @@ int tpm2_get_signed_policy(char *tpmkey, STACK_OF(TSSAUTHPOLICY) **sk)
}
TPM_RC tpm2_new_signed_policy(char *tpmkey, char *policykey, char *engine,
- TSSAUTHPOLICY *ap, TPMT_HA *digest)
+ TSSAUTHPOLICY *ap, TPMT_HA *digest, int need_auth)
{
BIO *bf;
TSSPRIVKEY *tpk;
@@ -2501,6 +2510,10 @@ TPM_RC tpm2_new_signed_policy(char *tpmkey, char *policykey, char *engine,
goto err_free_tpmkey;
}
+ /* remove the emptyAuth attribut if set and we need authorization */
+ if (tpk->emptyAuth != -1 && need_auth)
+ tpk->emptyAuth = -1;
+
policy = sk_TSSOPTPOLICY_value(tpk->policy, 0);
if (ASN1_INTEGER_get(policy->CommandCode) != TPM_CC_PolicyAuthorize) {
fprintf(stderr, "TPM Key has no signed policy\n");
@@ -2891,6 +2904,50 @@ TPM_RC tpm2_add_signed_policy(STACK_OF(TSSOPTPOLICY) *sk, char *key_file,
return TPM_RC_SUCCESS;
}
+TPM_RC
+tpm2_add_policy_secret(TSS_CONTEXT *tssContext, STACK_OF(TSSOPTPOLICY) *sk,
+ TPM_HANDLE handle, TPMT_HA *digest)
+{
+ TSSOPTPOLICY *policy;
+ BYTE buf[1024];
+ BYTE *buffer = buf;
+ UINT16 written = 0;
+ INT32 size = sizeof(buf);
+ const TPM_CC cc = TPM_CC_PolicySecret;
+ NAME_2B name;
+ DIGEST_2B policyRef = {0};
+ TPM_RC rc;
+ TPM_HANDLE intHandle = tpm2_handle_int(tssContext, handle);
+
+ rc = tpm2_readname(tssContext, intHandle, &name);
+ if (rc)
+ return rc;
+ policy = TSSOPTPOLICY_new();
+ TSS_TPM_CC_Marshal(&cc, &written, &buffer, &size);
+ TSS_UINT32_Marshal(&handle, &written, &buffer, &size);
+ TSS_TPM2B_NAME_Marshal((TPM2B_NAME *)&name, &written, &buffer, &size);
+ TSS_TPM2B_DIGEST_Marshal((TPM2B_DIGEST *)&policyRef, &written, &buffer, &size);
+
+ ASN1_INTEGER_set(policy->CommandCode, cc);
+ ASN1_STRING_set(policy->CommandPolicy, buf + 4, written - 4);
+ sk_TSSOPTPOLICY_push(sk, policy);
+
+ TSS_Hash_Generate(digest,
+ TSS_GetDigestSize(digest->hashAlg),
+ (uint8_t *)&digest->digest,
+ 4, buf, /* CC */
+ name.size, name.name, /* name */
+ 0, NULL);
+ TSS_Hash_Generate(digest,
+ TSS_GetDigestSize(digest->hashAlg),
+ (uint8_t *)&digest->digest, /* intermediate digest */
+ policyRef.size, policyRef.buffer,
+ 0, NULL);
+
+
+ return TPM_RC_SUCCESS;
+}
+
EVP_PKEY *
openssl_read_public_key(char *filename)
{
diff --git a/src/tools/create_tpm2_key.1.in b/src/tools/create_tpm2_key.1.in
index bbdfa9a..c9f1cdc 100644
--- a/src/tools/create_tpm2_key.1.in
+++ b/src/tools/create_tpm2_key.1.in
@@ -64,6 +64,18 @@ Note that certain parameters must be assumed about a parent when it is
wrapped, like the template (must be standard restricted decryption
key) and the name hash (must be sha256).
+[Secrets in Other Objects]
+
+When the option --secrets <handle> is used, it creates a key whose
+authorization password is conditioned on the password of a different
+object identified by <handle>. Usually this is a permanent NV index,
+but could be any object. The design of this policy is to allow the
+password to be changed without updating the key (simply by changing
+the authorization of the other object). Because OpenSSL can only
+request a single password, keys with a --secret policy may not
+additionally have an --auth option to also require passing in the
+password embedded in the key.
+
[Signed Policies]
When the option --signed-policy <key> is used, it creates a key whose
diff --git a/src/tools/create_tpm2_key.c b/src/tools/create_tpm2_key.c
index 9271a9b..809b9f9 100644
--- a/src/tools/create_tpm2_key.c
+++ b/src/tools/create_tpm2_key.c
@@ -30,6 +30,7 @@
#define OPT_RESTRICTED 0x1fe
#define OPT_SIGNED_POLICY 0x1fd
#define OPT_LOCALITY 0x1fc
+#define OPT_SECRET 0x1fb
static struct option long_options[] = {
{"auth", 0, 0, 'a'},
@@ -51,6 +52,7 @@ static struct option long_options[] = {
{"key-policy", 1, 0, 'c'},
{"import", 1, 0, 'i'},
{"restricted", 0, 0, OPT_RESTRICTED },
+ {"secret", 1, 0, OPT_SECRET },
/*
* The option --deprecated allows us to create old format keys
* for the purposes of testing. It should never be used in
@@ -105,6 +107,9 @@ usage(char *argv0)
"\t--signed-policy <key> Add a signed policy directive that allows\n"
"\t policies signed by the specified public <key>\n"
"\t to authorize use of the key\n"
+ "\t--secret <handle> Tie authorization of the key to the\n"
+ "\t Authorization of a different object\n"
+ "\t Identified by <handle>.\n"
"\n"
"Report bugs to " PACKAGE_BUGREPORT "\n",
argv0);
@@ -452,7 +457,7 @@ int main(int argc, char **argv)
int option_index, c;
const char *reason;
TSS_CONTEXT *tssContext = NULL;
- TPM_HANDLE parent = TPM_RH_OWNER, phandle;
+ TPM_HANDLE parent = TPM_RH_OWNER, phandle, secret_handle = 0;
TPM_RC rc;
BYTE pubkey[sizeof(TPM2B_PUBLIC)],privkey[sizeof(TPM2B_PRIVATE)], *buffer;
uint16_t pubkey_len, privkey_len;
@@ -582,6 +587,10 @@ int main(int argc, char **argv)
has_locality = 1;
locality = strtol(optarg, NULL, 0);
break;
+ case OPT_SECRET:
+ secret_handle = strtol(optarg, NULL, 0);
+ has_policy = 1;
+ break;
default:
printf("Unknown option '%c'\n", c);
usage(argv[0]);
@@ -780,6 +789,9 @@ int main(int argc, char **argv)
}
}
+ if (secret_handle)
+ tpm2_add_policy_secret(tssContext, sk, secret_handle, &digest);
+
if (parent_str) {
parent = tpm2_get_parent(tssContext, parent_str);
if (parent == 0) {
@@ -965,7 +977,8 @@ int main(int argc, char **argv)
size = sizeof(privkey);
TSS_TPM2B_PRIVATE_Marshal((TPM2B_PRIVATE *)priv, &privkey_len, &buffer, &size);
tpm2_write_tpmfile(filename, pubkey, pubkey_len,
- privkey, privkey_len, auth == NULL, parent, sk,
+ privkey, privkey_len,
+ auth == NULL && secret_handle == 0, parent, sk,
version, enc_secret);
tpm2_free_policy(sk);
diff --git a/src/tools/seal_tpm2_data.1.in b/src/tools/seal_tpm2_data.1.in
index fe7b7c4..101bfb2 100644
--- a/src/tools/seal_tpm2_data.1.in
+++ b/src/tools/seal_tpm2_data.1.in
@@ -40,6 +40,18 @@ Note that certain parameters must be assumed about a parent when it is
wrapped, like the template (must be standard restricted decryption
key) and the name hash (must be sha256).
+[Secrets in Other Objects]
+
+When the option --secrets <handle> is used, it creates a sealed blob
+whose authorization password is conditioned on the password of a
+different object identified by <handle>. Usually this is a permanent
+NV index, but could be any object. The design of this policy is to
+allow the password to be changed without updating the sealed blob
+(simply by changing the authorization of the other object). Because
+most unseal applications can only request a single password, blobs
+with a --secret policy may not additionally have an --auth option to
+also require passing in the password embedded in the blob.
+
[Signed Policies]
When the option --signed-policy <key> is used, it creates a sealed
diff --git a/src/tools/seal_tpm2_data.c b/src/tools/seal_tpm2_data.c
index c9c66bc..48d519d 100644
--- a/src/tools/seal_tpm2_data.c
+++ b/src/tools/seal_tpm2_data.c
@@ -23,6 +23,7 @@
#define OPT_SIGNED_POLICY 0x1fd
#define OPT_LOCALITY 0x1fc
+#define OPT_SECRET 0x1fb
static struct option long_options[] = {
{"auth", 0, 0, 'a'},
@@ -32,6 +33,7 @@ static struct option long_options[] = {
{"pcr-lock", 1, 0, 'x'},
{"locality", 1, 0, OPT_LOCALITY },
{"signed-policy", 1, 0, OPT_SIGNED_POLICY },
+ {"secret", 1, 0, OPT_SECRET },
{"version", 0, 0, 'v'},
{"password", 1, 0, 'k'},
{"da", 0, 0, 'd'},
@@ -85,6 +87,9 @@ usage(char *argv0)
"\t--signed-policy <key> Add a signed policy directive that allows\n"
"\t policies signed by the specified public <key>\n"
"\t to authorize unsealing\n"
+ "\t--secret <handle> Tie authorization of the key to the\n"
+ "\t Authorization of a different object\n"
+ "\t Identified by <handle>.\n"
"\t-i, --import <pubkey> Create an importable key with the outer\n"
" wrapper encrypted to <pubkey>\n"
"\t-c, --policy Specify a policy for unsealing the data\n"
@@ -127,7 +132,7 @@ int main(int argc, char **argv)
const char *reason = ""; /* gcc 4.8.5 gives spurious uninitialized warning without this */
TPMT_HA digest;
uint32_t sizeInBytes;
- TPM_HANDLE authHandle;
+ TPM_HANDLE authHandle, secret_handle = 0;
STACK_OF(TSSOPTPOLICY) *sk = NULL;
TPM2B_SENSITIVE_CREATE inSensitive;
TPM2B_PUBLIC inPublic;
@@ -222,6 +227,10 @@ int main(int argc, char **argv)
has_locality = 1;
locality = strtol(optarg, NULL, 0);
break;
+ case OPT_SECRET:
+ has_policy = 1;
+ secret_handle = strtol(optarg, NULL, 0);
+ break;
default:
printf("Unknown option '%c'\n", c);
usage(argv[0]);
@@ -340,6 +349,9 @@ int main(int argc, char **argv)
if (has_locality)
tpm2_add_locality(sk, locality, &digest);
+ if (secret_handle)
+ tpm2_add_policy_secret(tssContext, sk, secret_handle, &digest);
+
tpm2_public_template_seal(p);
if (has_policy) {
@@ -445,7 +457,8 @@ int main(int argc, char **argv)
TSS_TPM2B_PRIVATE_Marshal((TPM2B_PRIVATE *)&outPrivate, &privkey_len,
&buffer, &size);
tpm2_write_tpmfile(filename, pubkey, pubkey_len,
- privkey, privkey_len, data_auth == NULL,
+ privkey, privkey_len,
+ data_auth == NULL && secret_handle == 0,
parent, sk, 2, enc_secret);
out_flush:
diff --git a/src/tools/signed_tpm2_policy.1.in b/src/tools/signed_tpm2_policy.1.in
index a299d94..78207a9 100644
--- a/src/tools/signed_tpm2_policy.1.in
+++ b/src/tools/signed_tpm2_policy.1.in
@@ -22,6 +22,18 @@ well as comma separated ranges. So
sha512:1,3-5 means PCRs 1,3,4 and 5 in the sha512 bank
+[Secrets in Other Objects]
+
+When the option --secrets <handle> is used, it creates a key whose
+authorization password is conditioned on the password of a different
+object identified by <handle>. Usually this is a permanent NV index,
+but could be any object. The design of this policy is to allow the
+password to be changed without updating the key (simply by changing
+the authorization of the other object). Because OpenSSL can only
+request a single password, keys with a --secret policy may not
+additionally have an --auth option to also require passing in the
+password embedded in the key.
+
[examples]
list all signed policies:
diff --git a/src/tools/signed_tpm2_policy.c b/src/tools/signed_tpm2_policy.c
index e42db63..06ea73e 100644
--- a/src/tools/signed_tpm2_policy.c
+++ b/src/tools/signed_tpm2_policy.c
@@ -28,6 +28,7 @@
#define OPT_SIGNED_POLICY 0x1fd
#define OPT_LOCALITY 0x1fc
+#define OPT_SECRET 0x1fb
static struct option long_options[] = {
{"auth", 0, 0, 'a'},
@@ -35,6 +36,7 @@ static struct option long_options[] = {
{"pcr-lock", 1, 0, 'x'},
{"locality", 1, 0, OPT_LOCALITY },
{"signed-policy", 1, 0, OPT_SIGNED_POLICY },
+ {"secret", 1, 0, OPT_SECRET},
{"version", 0, 0, 'v'},
{"key-policy", 1, 0, 'c'},
{"engine", 1, 0, 'e'},
@@ -60,6 +62,9 @@ usage(char *argv0)
"\t--signed-policy <key> Add a signed policy directive that allows\n"
"\t policies signed by the specified public <key>\n"
"\t to authorize use of the key\n"
+ "\t--secret <handle> Tie authorization of the key to the\n"
+ "\t Authorization of a different object\n"
+ "\t Identified by <handle>.\n"
"\t-n, --policy-name <name> Optional name to annotate the policy with\n"
"\n"
"Report bugs to " PACKAGE_BUGREPORT "\n",
@@ -115,6 +120,7 @@ int main(int argc, char **argv)
TPML_PCR_SELECTION pcr_lock = { 0 };
int has_locality = 0;
int locality = 0;
+ int secret_handle = 0;
STACK_OF(TSSAUTHPOLICY) *sk;
enum cmd {
CMD_ADD = 0,
@@ -186,6 +192,9 @@ int main(int argc, char **argv)
has_locality = 1;
locality = strtol(optarg, NULL, 0);
break;
+ case OPT_SECRET:
+ secret_handle = strtol(optarg, NULL, 0);
+ break;
default:
printf("Unknown option '%c'\n", c);
usage(argv0);
@@ -271,8 +280,31 @@ int main(int argc, char **argv)
if (has_locality)
tpm2_add_locality(ap->policy, locality, &digest);
+ if (secret_handle) {
+ TSS_CONTEXT *tssContext = NULL;
+ const char *dir;
+
+ dir = tpm2_set_unique_tssdir();
+ rc = tpm2_create(&tssContext, dir);
+ if (rc) {
+ reason = "TSS_Create";
+ goto out_free_policy;
+ }
+
+ rc = tpm2_add_policy_secret(tssContext, ap->policy,
+ secret_handle, &digest);
+ TSS_Delete(tssContext);
+ tpm2_rm_tssdir(dir);
+ if (rc) {
+ reason = "create object authorization policy";
+ goto out_free_policy;
+ }
+ }
+
+
rc = tpm2_new_signed_policy(filename, policy_signing_key,
- engine, ap, &digest);
+ engine, ap, &digest,
+ auth || secret_handle);
if (rc == 0)
exit(0);