aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@HansenPartnership.com>2022-12-05 12:22:35 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2023-01-11 10:00:21 -0500
commitb85fe3b3baeef05682091f913ef1ec14f3e6f155 (patch)
tree2824e47a36c725be289f3167271b6705e52f94ff
parentf54d193ac23577e6dcf392bf1be27657276084e6 (diff)
downloadopenssl_tpm2_engine-b85fe3b3baeef05682091f913ef1ec14f3e6f155.tar.gz
tpm2-common.c: add processing of signed policy authorizations
This changes the way policies are stored in the key and processed. Since signed policies are chains of policies which may or may not work, an additional pols[] array is added to the app_data of the key, with pols[0] being what the prior policy would be and pols[1+] being where additional signed policy may be added or removed. Since a successful TPM2_PolicyAuthorize() invocation replaces the current policy hash with one derived from the key and the nonce, it makes no sense for TPM2_PolicyAuthorize() to be anywhere other than at the beginning of the standard policy or at the end of each of the signed policies. Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
-rw-r--r--e_tpm2-ecc.c37
-rw-r--r--e_tpm2-rsa.c33
-rw-r--r--load_tpm2_key.c3
-rw-r--r--tpm2-common.c233
-rw-r--r--tpm2-common.h14
-rw-r--r--unseal_tpm2_data.c3
6 files changed, 242 insertions, 81 deletions
diff --git a/e_tpm2-ecc.c b/e_tpm2-ecc.c
index a73a082..92ea12d 100644
--- a/e_tpm2-ecc.c
+++ b/e_tpm2-ecc.c
@@ -61,29 +61,26 @@ static int active_keys = 0;
static TPM_HANDLE tpm2_load_key_from_ecc(const EC_KEY *eck,
TSS_CONTEXT **tssContext, char **auth,
- TPM_SE *sessionType, int *num_commands,
- struct policy_command **commands,
+ TPM_SE *sessionType,
+ struct app_data **app_data,
TPM_ALG_ID *nameAlg)
{
#if OPENSSL_VERSION_NUMBER < 0x10100000
/* const mess up in openssl 1.0.2 */
- struct app_data *app_data = ECDSA_get_ex_data((EC_KEY *)eck,
- ec_app_data);
+ *app_data = ECDSA_get_ex_data((EC_KEY *)eck, ec_app_data);
#else
- struct app_data *app_data = EC_KEY_get_ex_data(eck, ec_app_data);
+ *app_data = EC_KEY_get_ex_data(eck, ec_app_data);
#endif
- if (!app_data)
+ if (!*app_data)
return 0;
- *auth = app_data->auth;
- *sessionType = app_data->req_policy_session ?
+ *auth = (*app_data)->auth;
+ *sessionType = (*app_data)->req_policy_session ?
TPM_SE_POLICY : TPM_SE_HMAC;
- *commands = app_data->commands;
- *num_commands = app_data->num_commands;
- *nameAlg = app_data->name_alg;
+ *nameAlg = (*app_data)->name_alg;
- return tpm2_load_key(tssContext, app_data, srk_auth, NULL);
+ return tpm2_load_key(tssContext, *app_data, srk_auth, NULL);
}
void tpm2_bind_key_to_engine_ecc(ENGINE *e, EVP_PKEY *pkey, struct app_data *data)
@@ -143,9 +140,8 @@ static ECDSA_SIG *tpm2_ecdsa_sign(const unsigned char *dgst, int dgst_len,
TPM_SE sessionType;
ECDSA_SIG *sig;
BIGNUM *r, *s;
- int num_commands;
- struct policy_command *commands;
TPM_ALG_ID nameAlg;
+ struct app_data *app_data;
/* The TPM insists on knowing the digest type, so
* calculate that from the size */
@@ -170,8 +166,7 @@ static ECDSA_SIG *tpm2_ecdsa_sign(const unsigned char *dgst, int dgst_len,
}
keyHandle = tpm2_load_key_from_ecc(eck, &tssContext, &auth,
- &sessionType, &num_commands,
- &commands, &nameAlg);
+ &sessionType, &app_data, &nameAlg);
if (keyHandle == 0) {
fprintf(stderr, "Failed to get Key Handle in TPM EC key routines\n");
return NULL;
@@ -189,7 +184,7 @@ static ECDSA_SIG *tpm2_ecdsa_sign(const unsigned char *dgst, int dgst_len,
if (sessionType == TPM_SE_POLICY) {
rc = tpm2_init_session(tssContext, authHandle,
- num_commands, commands, nameAlg);
+ app_data, nameAlg);
if (rc)
goto out;
}
@@ -236,14 +231,12 @@ static int tpm2_ecc_compute_key(unsigned char **psec, size_t *pseclen,
TPM_SE sessionType;
char *auth;
size_t len;
- int num_commands;
- struct policy_command *commands;
TPM_ALG_ID nameAlg;
+ struct app_data *app_data;
int ret;
keyHandle = tpm2_load_key_from_ecc(eck, &tssContext, &auth,
- &sessionType, &num_commands,
- &commands, &nameAlg);
+ &sessionType, &app_data, &nameAlg);
if (keyHandle == 0) {
fprintf(stderr, "Failed to get Key Handle in TPM EC key routines\n");
return 0;
@@ -260,7 +253,7 @@ static int tpm2_ecc_compute_key(unsigned char **psec, size_t *pseclen,
if (sessionType == TPM_SE_POLICY) {
rc = tpm2_init_session(tssContext, authHandle,
- num_commands, commands, nameAlg);
+ app_data, nameAlg);
if (rc)
goto out;
}
diff --git a/e_tpm2-rsa.c b/e_tpm2-rsa.c
index 3fb5d62..a886f96 100644
--- a/e_tpm2-rsa.c
+++ b/e_tpm2-rsa.c
@@ -98,23 +98,20 @@ static int tpm2_rsa_pub_enc(int flen,
static TPM_HANDLE tpm2_load_key_from_rsa(RSA *rsa, TSS_CONTEXT **tssContext,
char **auth, TPM_SE *sessionType,
- int *num_commands,
- struct policy_command **commands,
+ struct app_data **app_data,
TPM_ALG_ID *nameAlg)
{
- struct app_data *app_data = RSA_get_ex_data(rsa, ex_app_data);
+ *app_data = RSA_get_ex_data(rsa, ex_app_data);
- if (!app_data)
+ if (!*app_data)
return 0;
- *auth = app_data->auth;
- *sessionType = app_data->req_policy_session ?
+ *auth = (*app_data)->auth;
+ *sessionType = (*app_data)->req_policy_session ?
TPM_SE_POLICY : TPM_SE_HMAC;
- *commands = app_data->commands;
- *num_commands = app_data->num_commands;
- *nameAlg = app_data->name_alg;
+ *nameAlg = (*app_data)->name_alg;
- return tpm2_load_key(tssContext, app_data, srk_auth, NULL);
+ return tpm2_load_key(tssContext, *app_data, srk_auth, NULL);
}
void tpm2_bind_key_to_engine_rsa(ENGINE *e, EVP_PKEY *pkey, struct app_data *data)
@@ -172,13 +169,11 @@ static int tpm2_rsa_priv_dec(int flen,
char *auth;
TPM_HANDLE authHandle;
TPM_SE sessionType;
- int num_commands;
- struct policy_command *commands;
TPM_ALG_ID nameAlg;
+ struct app_data *app_data;
keyHandle = tpm2_load_key_from_rsa(rsa, &tssContext, &auth,
- &sessionType, &num_commands,
- &commands, &nameAlg);
+ &sessionType, &app_data, &nameAlg);
if (keyHandle == 0) {
fprintf(stderr, "Failed to get Key Handle in TPM RSA key routines\n");
@@ -210,7 +205,7 @@ static int tpm2_rsa_priv_dec(int flen,
if (sessionType == TPM_SE_POLICY) {
rc = tpm2_init_session(tssContext, authHandle,
- num_commands, commands, nameAlg);
+ app_data, nameAlg);
if (rc)
goto out;
}
@@ -249,9 +244,8 @@ static int tpm2_rsa_priv_enc(int flen,
char *auth;
TPM_HANDLE authHandle;
TPM_SE sessionType;
- int num_commands;
- struct policy_command *commands;
TPM_ALG_ID nameAlg;
+ struct app_data *app_data;
/* this is slightly paradoxical that we're doing a Decrypt
* operation: the only material difference between decrypt and
@@ -278,8 +272,7 @@ static int tpm2_rsa_priv_enc(int flen,
}
keyHandle = tpm2_load_key_from_rsa(rsa, &tssContext, &auth,
- &sessionType, &num_commands,
- &commands, &nameAlg);
+ &sessionType, &app_data, &nameAlg);
if (keyHandle == 0) {
fprintf(stderr, "Failed to get Key Handle in TPM RSA routines\n");
@@ -295,7 +288,7 @@ static int tpm2_rsa_priv_enc(int flen,
if (sessionType == TPM_SE_POLICY) {
rc = tpm2_init_session(tssContext, authHandle,
- num_commands, commands, nameAlg);
+ app_data, nameAlg);
if (rc)
goto out;
}
diff --git a/load_tpm2_key.c b/load_tpm2_key.c
index add7fd4..35dcdb2 100644
--- a/load_tpm2_key.c
+++ b/load_tpm2_key.c
@@ -124,8 +124,7 @@ int main(int argc, char **argv)
fprintf(stderr, "Failed to parse file %s\n", filename);
exit(1);
}
- if (app_data->commands && !force) {
- fprintf(stderr, "NUM COMMANDS=%d\n", app_data->num_commands);
+ if (app_data->pols && !force) {
fprintf(stderr, "Warning: key %s has associated policy\n"
"Policy keys are hard to use, specify --force if this is really what you want\n",
filename);
diff --git a/tpm2-common.c b/tpm2-common.c
index 5865b55..633acb7 100644
--- a/tpm2-common.c
+++ b/tpm2-common.c
@@ -17,6 +17,8 @@
#include <sys/types.h>
#include <sys/mman.h>
+#include <arpa/inet.h> /* htons */
+
#include <openssl/asn1.h>
#include <openssl/evp.h>
#include <openssl/rsa.h>
@@ -916,9 +918,9 @@ TPM_RC tpm2_get_session_handle(TSS_CONTEXT *tssContext, TPM_HANDLE *handle,
return rc;
}
-TPM_RC tpm2_init_session(TSS_CONTEXT *tssContext, TPM_HANDLE handle,
- int num_commands, struct policy_command *commands,
- TPM_ALG_ID name_alg)
+static TPM_RC tpm2_try_policy(TSS_CONTEXT *tssContext, TPM_HANDLE handle,
+ int num_commands, struct policy_command *commands,
+ TPM_ALG_ID name_alg, const char *prefix)
{
INT32 size;
BYTE *policy;
@@ -1006,11 +1008,61 @@ TPM_RC tpm2_init_session(TSS_CONTEXT *tssContext, TPM_HANDLE handle,
break;
}
+ case TPM_CC_PolicyAuthorize: {
+ TPM2B_PUBLIC pub;
+ DIGEST_2B nonce;
+ TPMT_SIGNATURE sig;
+ DIGEST_2B policyHash;
+ TPMT_HA sigHash;
+ DIGEST_2B sigDigest;
+ TPM_HANDLE sigkey;
+ TPMT_TK_VERIFIED ticket;
+ NAME_2B name;
+
+ rc = TPM2B_PUBLIC_Unmarshal(&pub, &policy, &size, FALSE);
+ if (rc)
+ goto unmarshal_failure;
+
+ rc = TPM2B_DIGEST_Unmarshal((TPM2B_DIGEST *)&nonce, &policy, &size);
+ if (rc)
+ goto unmarshal_failure;
+ rc = TPMT_SIGNATURE_Unmarshal(&sig, &policy, &size, FALSE);
+ if (rc)
+ goto unmarshal_failure;
+ rc = tpm2_PolicyGetDigest(tssContext, handle, &policyHash);
+ if (rc) {
+ sprintf(reason, "PolicyGetDigest");
+ break;
+ }
+ sigHash.hashAlg = name_alg;
+ TSS_Hash_Generate(&sigHash,
+ policyHash.size, policyHash.buffer,
+ nonce.size, nonce.buffer,
+ 0, NULL);
+ sigDigest.size = TSS_GetDigestSize(name_alg);
+ memcpy(sigDigest.buffer, &sigHash.digest, sigDigest.size);
+ rc = tpm2_LoadExternal(tssContext, NULL, &pub, TPM_RH_OWNER, &sigkey, &name);
+ if (rc) {
+ sprintf(reason, "LoadExternal");
+ break;
+ }
+ rc = tpm2_VerifySignature(tssContext, sigkey, &sigDigest, &sig, &ticket);
+ tpm2_flush_handle(tssContext, sigkey);
+ if (rc) {
+ sprintf(reason, "Signature Failed");
+ break;
+ }
+
+ rc = tpm2_PolicyAuthorize(tssContext, handle, &policyHash, &nonce, &name, &ticket);
+ if (rc)
+ sprintf(reason, "PolicyAuthorize failed");
+
+ break;
+ }
default:
- fprintf(stderr, "Unsupported policy command %d\n",
- commands[i].code);
- rc = TPM_RC_FAILURE;
- goto out_flush;
+ fprintf(stderr, "%sUnsupported policy command %d\n",
+ prefix, commands[i].code);
+ return TPM_RC_FAILURE;
}
if (rc) {
@@ -1024,21 +1076,76 @@ TPM_RC tpm2_init_session(TSS_CONTEXT *tssContext, TPM_HANDLE handle,
else
check_rc = rc;
- if (check_rc == reason_rc && reason[0])
- fprintf(stderr, "Policy Failure: %s\n", reason);
- else
- tpm2_error(rc, "policy command");
- goto out_flush;
+ if (check_rc == reason_rc && reason[0]) {
+ fprintf(stderr, "%sPolicy Failure: %s\n",
+ prefix, reason);
+ } else {
+ if (!reason[0])
+ sprintf(reason, "%spolicy command", prefix);
+ tpm2_error(rc, reason);
+ }
+ return rc;
}
}
-
- return TPM_RC_SUCCESS;
+ return rc;
unmarshal_failure:
- tpm2_error(rc, "unmarshal");
+ sprintf(reason, "%sunmarshal", prefix);
+ tpm2_error(rc, reason);
+ return rc;
+}
+
+TPM_RC tpm2_init_session(TSS_CONTEXT *tssContext, TPM_HANDLE handle,
+ struct app_data *app_data, TPM_ALG_ID name_alg)
+{
+ int num_commands;
+ struct policy_command *commands;
+ char prefix[128];
+ TPM_RC rc;
+
+ if (app_data->pols == NULL)
+ return TPM_RC_SUCCESS;
+
+ commands = app_data->pols[0].commands;
+ num_commands = app_data->pols[0].num_commands;
+
+ if (app_data->num_pols > 1 &&
+ commands[0].code == TPM_CC_PolicyAuthorize) {
+ int i;
+
+ commands++;
+ num_commands--;
+ for (i = 1; i < app_data->num_pols; i++) {
+ struct policies *pols = &app_data->pols[i];
+
+ if (pols->name)
+ sprintf(prefix, "Signed Policy %d (%s) ", i,
+ pols->name);
+ else
+ sprintf(prefix, "Signed policy %d ", i);
+
+ rc = tpm2_PolicyRestart(tssContext, handle);
+ if (rc != TPM_RC_SUCCESS)
+ break;
+ rc = tpm2_try_policy(tssContext, handle,
+ pols->num_commands,
+ pols->commands,
+ name_alg, prefix);
+ if (rc == TPM_RC_SUCCESS)
+ break;
+ }
+ if (rc != TPM_RC_SUCCESS)
+ goto out;
+
+ fprintf(stderr, "%ssucceeded\n", prefix);
+ }
+
+ rc = tpm2_try_policy(tssContext, handle, num_commands, commands,
+ name_alg, "");
+ out:
+ if (rc != TPM_RC_SUCCESS)
+ tpm2_flush_handle(tssContext, handle);
- out_flush:
- tpm2_flush_handle(tssContext, handle);
return rc;
}
@@ -1335,30 +1442,43 @@ static int tpm2_engine_load_key_policy(struct app_data *app_data,
{
struct policy_command *command;
TSSOPTPOLICY *policy;
- int i, commands_len;
+ int i, len;
+ int num_policies = 1, num_commands;
- app_data->num_commands = sk_TSSOPTPOLICY_num(st_policy);
- if (app_data->num_commands <= 0)
+ num_commands = sk_TSSOPTPOLICY_num(st_policy);
+ if (num_commands <= 0)
return 1;
policy = sk_TSSOPTPOLICY_value(st_policy, 0);
if (ASN1_INTEGER_get(policy->CommandCode) == TPM_CC_PolicyAuthorize
&& auth_policy == NULL) {
- fprintf(stderr, "Key requires signed policies but has none and is thus unusable\n");
+ fprintf(stderr, "Key unusable (no signed policies)\n");
return 0;
}
- commands_len = sizeof(struct policy_command) * app_data->num_commands;
- app_data->commands = OPENSSL_malloc(commands_len);
- if (!app_data->commands)
+ if (auth_policy)
+ num_policies += sk_TSSAUTHPOLICY_num(auth_policy);
+
+ app_data->num_pols = num_policies;
+
+ len = sizeof(*app_data->pols) * num_policies;
+ app_data->pols = OPENSSL_malloc(len);
+ if (!app_data->pols)
+ return 0;
+
+ len = sizeof(struct policy_command) * num_commands;
+ app_data->pols[0].num_commands = num_commands;
+ app_data->pols[0].commands = OPENSSL_malloc(len);
+ app_data->pols[0].name = NULL;
+ if (!app_data->pols[0].commands)
return 0;
- for (i = 0; i < app_data->num_commands; i++) {
+ for (i = 0; i < num_commands; i++) {
policy = sk_TSSOPTPOLICY_value(st_policy, i);
if (!policy)
return 0;
- command = app_data->commands + i;
+ command = app_data->pols[0].commands + i;
command->code = ASN1_INTEGER_get(policy->CommandCode);
command->size = policy->CommandPolicy->length;
command->policy = NULL;
@@ -1374,6 +1494,52 @@ static int tpm2_engine_load_key_policy(struct app_data *app_data,
command->size);
}
+ if (num_policies == 1)
+ return 1;
+
+ for (i = 1; i < num_policies; i++) {
+ int j;
+ TSSAUTHPOLICY *ap = sk_TSSAUTHPOLICY_value(auth_policy, i-1);
+ struct policies *pols = &app_data->pols[i];
+ if (!ap)
+ return 0;
+
+ if (ap->name) {
+ pols->name = OPENSSL_malloc(ap->name->length + 1);
+ if (!pols->name)
+ return 0;
+ memcpy(pols->name, ap->name->data, ap->name->length);
+ pols->name[ap->name->length] = '\0';
+ } else {
+ pols->name = NULL;
+ }
+
+ num_commands = sk_TSSOPTPOLICY_num(ap->policy);
+ len = sizeof(struct policy_command) * num_commands;
+ app_data->pols[i].num_commands = num_commands;
+ app_data->pols[i].commands = OPENSSL_malloc(len);
+ if (!app_data->pols[i].commands)
+ return 0;
+
+ for (j = 0; j < num_commands; j++) {
+ policy = sk_TSSOPTPOLICY_value(ap->policy, j);
+
+ command = app_data->pols[i].commands + j;
+ command->code = ASN1_INTEGER_get(policy->CommandCode);
+ command->size = policy->CommandPolicy->length;
+ command->policy = NULL;
+
+ if (!command->size)
+ continue;
+
+ command->policy = OPENSSL_malloc(command->size);
+ if (!command->policy)
+ return 0;
+
+ memcpy(command->policy, policy->CommandPolicy->data,
+ command->size);
+ }
+ }
return 1;
}
@@ -1668,13 +1834,18 @@ int tpm2_load_engine_file(const char *filename, struct app_data **app_data,
void tpm2_delete(struct app_data *app_data)
{
- int i;
+ int i, j;
+ struct policies *pols = app_data->pols;
- if (app_data->commands) {
- for (i = 0; i < app_data->num_commands; i++)
- OPENSSL_free(app_data->commands[i].policy);
+ if (pols) {
+ for (i = 0; i < app_data->num_pols; i++) {
+ for (j = 0; j < pols[i].num_commands; j++)
+ OPENSSL_free(pols[i].commands[j].policy);
- OPENSSL_free(app_data->commands);
+ OPENSSL_free(pols[i].commands);
+ OPENSSL_free(pols[i].name);
+ }
+ OPENSSL_free(app_data->pols);
}
OPENSSL_free(app_data->priv);
OPENSSL_free(app_data->pub);
diff --git a/tpm2-common.h b/tpm2-common.h
index 147d67c..da35155 100644
--- a/tpm2-common.h
+++ b/tpm2-common.h
@@ -25,6 +25,12 @@ enum tpm2_type {
TPM2_SEALED = 3,
};
+struct policies {
+ char *name;
+ int num_commands;
+ struct policy_command *commands;
+};
+
/* structure pointed to by the RSA object's app_data pointer */
struct app_data {
enum tpm2_type type;
@@ -39,9 +45,10 @@ struct app_data {
char *auth;
const char *dir;
int req_policy_session;
- int num_commands;
unsigned int name_alg;
- struct policy_command *commands;
+ /* pols[0] is key policy pols[1+] is authorized policy */
+ struct policies *pols;
+ int num_pols;
ENGINE *e;
};
@@ -55,8 +62,7 @@ TPM_RC tpm2_get_session_handle(TSS_CONTEXT *tssContext, TPM_HANDLE *handle,
TPM_HANDLE salt_key, TPM_SE sessionType,
TPM_ALG_ID name_alg);
TPM_RC tpm2_init_session(TSS_CONTEXT *tssContext, TPM_HANDLE handle,
- int num_commands, struct policy_command *commands,
- TPM_ALG_ID name_alg);
+ struct app_data *app_data, TPM_ALG_ID name_alg);
TPM_RC tpm2_get_bound_handle(TSS_CONTEXT *tssContext, TPM_HANDLE *handle,
TPM_HANDLE bind, const char *auth);
TPMI_ECC_CURVE tpm2_curve_name_to_TPMI(const char *name);
diff --git a/unseal_tpm2_data.c b/unseal_tpm2_data.c
index c8a3134..481c9ca 100644
--- a/unseal_tpm2_data.c
+++ b/unseal_tpm2_data.c
@@ -156,8 +156,7 @@ int main(int argc, char **argv)
if (app_data->req_policy_session) {
rc = tpm2_init_session(tssContext, session,
- app_data->num_commands,
- app_data->commands, name_alg);
+ app_data, name_alg);
if (rc) {
reason = "tpm2_init_session";
goto out_flush_session;