diff options
author | James Bottomley <James.Bottomley@HansenPartnership.com> | 2020-01-02 16:00:53 -0800 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2020-01-26 08:50:43 -0800 |
commit | 84c3e0add62096e37fa0cd41f95e3d625c67c8f2 (patch) | |
tree | 6632036e172f8eb5de51411a5c59f31bf5525c1e | |
parent | 600da197e76940cfd654519734125131f6964798 (diff) | |
download | openssl_tpm2_engine-84c3e0add62096e37fa0cd41f95e3d625c67c8f2.tar.gz |
Add TPM data sealing and unsealing functions
This adds two commands and their manpages: seal_tpm2_data and
unseal_tpm2_data plus a new OID 2.23.133.10.1.5 to identify sealed
data. The object is to be interoperable with the new kernel sealed
data format.
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | Makefile.am | 16 | ||||
-rw-r--r-- | e_tpm2-ecc.c | 2 | ||||
-rw-r--r-- | e_tpm2-rsa.c | 2 | ||||
-rw-r--r-- | load_tpm2_key.c | 2 | ||||
-rw-r--r-- | seal_tpm2_data.1.in | 18 | ||||
-rw-r--r-- | seal_tpm2_data.c | 337 | ||||
-rw-r--r-- | tpm2-asn.h | 2 | ||||
-rw-r--r-- | tpm2-common.c | 18 | ||||
-rw-r--r-- | tpm2-common.h | 2 | ||||
-rw-r--r-- | unseal_tpm2_data.1.in | 18 | ||||
-rw-r--r-- | unseal_tpm2_data.c | 206 |
12 files changed, 612 insertions, 13 deletions
@@ -19,6 +19,8 @@ ltmain.sh missing create_tpm2_key load_tpm2_key +seal_tpm2_data +unseal_tpm2_data test-driver tests/*.log tests/*.trs diff --git a/Makefile.am b/Makefile.am index 734bfc5..33de0d9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,14 +1,16 @@ EXTRA_DIST = README openssl.cnf.sample if NATIVE_BUILD -EXTRA_DIST += create_tpm2_key.1 load_tpm2_key.1 -man1_MANS = create_tpm2_key.1 load_tpm2_key.1 +EXTRA_DIST += create_tpm2_key.1 load_tpm2_key.1 seal_tpm2_data.1 \ + unseal_tpm2_data.1 +man1_MANS = create_tpm2_key.1 load_tpm2_key.1 seal_tpm2_data.1 \ + unseal_tpm2_data.1 CLEANFILES = $(man1_MANS) endif openssl_engine_LTLIBRARIES=libtpm2.la -bin_PROGRAMS=create_tpm2_key load_tpm2_key +bin_PROGRAMS=create_tpm2_key load_tpm2_key seal_tpm2_data unseal_tpm2_data openssl_enginedir=@enginesdir@ libtpm2_la_LDFLAGS= -no-undefined -avoid-version @@ -24,6 +26,14 @@ load_tpm2_key_SOURCES=load_tpm2_key.c tpm2-common.c load_tpm2_key_LDADD=${DEPS_LIBS} load_tpm2_key_CFLAGS=${DEPS_CFLAGS} -Werror +seal_tpm2_data_SOURCES=seal_tpm2_data.c tpm2-common.c +seal_tpm2_data_LDADD=${DEPS_LIBS} +seal_tpm2_data_CFLAGS=${DEPS_CFLAGS} -Werror + +unseal_tpm2_data_SOURCES=unseal_tpm2_data.c tpm2-common.c +unseal_tpm2_data_LDADD=${DEPS_LIBS} +unseal_tpm2_data_CFLAGS=${DEPS_CFLAGS} -Werror + $(builddir)/%.1: $(srcdir)/%.1.in $(top_builddir)/% $(HELP2MAN) --no-info -i $< -o $@ $(top_builddir)/$* diff --git a/e_tpm2-ecc.c b/e_tpm2-ecc.c index 89e3762..0e4c905 100644 --- a/e_tpm2-ecc.c +++ b/e_tpm2-ecc.c @@ -87,7 +87,7 @@ static TPM_HANDLE tpm2_load_key_from_ecc(const EC_KEY *eck, *num_commands = app_data->num_commands; *nameAlg = app_data->name_alg; - return tpm2_load_key(tssContext, app_data, srk_auth); + return tpm2_load_key(tssContext, app_data, srk_auth, NULL); } void tpm2_bind_key_to_engine_ecc(EVP_PKEY *pkey, void *data) diff --git a/e_tpm2-rsa.c b/e_tpm2-rsa.c index 85be4a8..07fb075 100644 --- a/e_tpm2-rsa.c +++ b/e_tpm2-rsa.c @@ -119,7 +119,7 @@ static TPM_HANDLE tpm2_load_key_from_rsa(RSA *rsa, TSS_CONTEXT **tssContext, *num_commands = app_data->num_commands; *nameAlg = app_data->name_alg; - return tpm2_load_key(tssContext, app_data, srk_auth); + return tpm2_load_key(tssContext, app_data, srk_auth, NULL); } void tpm2_bind_key_to_engine_rsa(EVP_PKEY *pkey, void *data) diff --git a/load_tpm2_key.c b/load_tpm2_key.c index 244c9dc..defc1c4 100644 --- a/load_tpm2_key.c +++ b/load_tpm2_key.c @@ -148,7 +148,7 @@ int main(int argc, char **argv) goto out_free; } - ret = tpm2_load_key(&tssContext, app_data, auth); + ret = tpm2_load_key(&tssContext, app_data, auth, NULL); if (!ret) { ret = 1; goto out; diff --git a/seal_tpm2_data.1.in b/seal_tpm2_data.1.in new file mode 100644 index 0000000..b88510a --- /dev/null +++ b/seal_tpm2_data.1.in @@ -0,0 +1,18 @@ +[name] +seal_tpm2_data - seal a blob of data for a TPM + +[description] + +Used to create a sealed blob of data which can be unsealed via the +TPM. Possible uses for this blob of data include as a symmetric key, +which is the use in the linux kernel trusted key infrastructure. + +[examples] + +Create a sealed data blob to the storage parent (owner hierarchy) + + echo somedatatoseal | seal_tpm2_key -p owner seal.tpm + +Unseal the data + + unseal_tpm2_key seal.tpm diff --git a/seal_tpm2_data.c b/seal_tpm2_data.c new file mode 100644 index 0000000..a04f878 --- /dev/null +++ b/seal_tpm2_data.c @@ -0,0 +1,337 @@ +/* + * + * Copyright (C) 2019 James Bottomley <James.Bottomley@HansenPartnership.com> + * + * SPDX-License-Identifier: LGPL-2.1-only + */ + +#include <stdio.h> +#include <getopt.h> +#include <string.h> +#include <strings.h> +#include <errno.h> +#include <unistd.h> + +#include <openssl/evp.h> +#include <openssl/pem.h> +#include <openssl/ui.h> + +#define TSSINCLUDE(x) < TSS_INCLUDE/x > +#include TSSINCLUDE(tss.h) +#include TSSINCLUDE(tssutils.h) +#include TSSINCLUDE(tssmarshal.h) +#include TSSINCLUDE(Unmarshal_fp.h) +#include TSSINCLUDE(tsscrypto.h) +#include TSSINCLUDE(tsscryptoh.h) + +#include "tpm2-asn.h" +#include "tpm2-common.h" + +static TPM_ALG_ID name_alg = TPM_ALG_SHA256; + +static struct option long_options[] = { + {"auth", 0, 0, 'a'}, + {"auth-parent", 1, 0, 'b'}, + {"help", 0, 0, 'h'}, + {"parent-handle", 1, 0, 'p'}, + {"version", 0, 0, 'v'}, + {"password", 1, 0, 'k'}, + {"da", 0, 0, 'd'}, + {"policy", 1, 0, 'c'}, + {"nomigrate", 0, 0, 'm'}, + {"name-scheme", 1, 0, 'n'}, + {0, 0, 0, 0} +}; + +static void tpm2_public_template_seal(TPMT_PUBLIC *pub) +{ + pub->type = TPM_ALG_KEYEDHASH; + pub->nameAlg = name_alg; + pub->objectAttributes.val = + TPMA_OBJECT_USERWITHAUTH; + pub->authPolicy.t.size = 0; + pub->parameters.keyedHashDetail.scheme.scheme = TPM_ALG_NULL; + pub->unique.sym.t.size = 0; +} + +void +usage(char *argv0) +{ + fprintf(stdout, "Usage: %s [options] <filename>\n\n" + "Options:\n" + "\t-a, --auth The data blob requires authorization\n" + "\t-b, --auth-parent <pwd> Specify the parent key password\n" + "\t (default EmptyAuth)\n" + "\t-d, --da mark the key as having Dictionary Attack implications. This means that if\n" + "\t the key password is incorrectly presented too many times, the TPM may\n" + "\t Implement DA mitigation and refuse connections for a while\n" + "\t-h, --help print this help message\n" + "\t-p, --parent-handle <handle> parent for the key, can either be a\n" + "\t persistent key or a hierarchy.\n" + "\t the hierarchies can be 'platform',\n" + "\t 'owner', 'null' or 'endorsement'.\n" + "\t The seeds used for derivation are\n" + "\t platform, storage, null or endorsement\n" + "\t respectively\n" + "\t-v, --version print package version\n" + "\t-k, --password <pwd> use this password instead of prompting\n" + "\t-m,--nomigrate Create a sealed data bundle that can be\n" + " migrated to other systems.\n" + "\t-n, --name-scheme <scheme> name algorithm to use sha1 [sha256] sha384 sha512\n" + "\n" + "Report bugs to " PACKAGE_BUGREPORT "\n", + argv0); + exit(-1); +} + +int main(int argc, char **argv) +{ + int option_index, c; + int nomigrate = 0, parent = TPM_RH_OWNER; + char *data_auth = NULL, *parent_auth = NULL, *pass = NULL; + char *policyFilename = NULL; + char *filename; + uint32_t noda = TPMA_OBJECT_NODA, phandle; + TPM_RC rc; + TSS_CONTEXT *tssContext; + const char *dir; + const char *reason; + TPMT_HA digest; + uint32_t sizeInBytes; + TPM_HANDLE authHandle; + STACK_OF(TSSOPTPOLICY) *sk = NULL; + Create_In cin; + Create_Out cout; + TPMS_SENSITIVE_CREATE *s = &cin.inSensitive.sensitive; + TPMT_PUBLIC *p = &cin.inPublic.publicArea; + BYTE pubkey[sizeof(TPM2B_PUBLIC)]; + BYTE privkey[sizeof(TPM2B_PRIVATE)]; + BYTE *buffer; + int32_t size; + uint16_t pubkey_len, privkey_len; + + while (1) { + option_index = 0; + c = getopt_long(argc, argv, "ak:b:hp:vdsun", + long_options, &option_index); + if (c == -1) + break; + + switch (c) { + case 'a': + data_auth = malloc(128); + break; + case 'k': + pass = optarg; + if (strlen(pass) > 127) { + printf("password is too long\n"); + exit(1); + } + break; + case 'b': + parent_auth = optarg; + break; + case 'h': + usage(argv[0]); + break; + case 'n': + if (!strcasecmp("sha1", optarg)) { + name_alg = TPM_ALG_SHA1; + } else if (!strcasecmp("sha256", optarg)) { + /* default, do nothing */ + } else if (!strcasecmp("sha384", optarg)) { + name_alg = TPM_ALG_SHA384; +#ifdef TPM_ALG_SHA512 + } else if (!strcasecmp("sha512", optarg)) { + name_alg = TPM_ALG_SHA512; +#endif + } else { + usage(argv[0]); + } + break; + case 'p': + parent = tpm2_get_parent(optarg); + if (parent == 0) { + fprintf(stderr, "Invalid parent %s\n", optarg); + exit(1); + } + break; + case 'v': + fprintf(stdout, "%s " VERSION "\n" + "Copyright 2017 by James Bottomley\n" + "License LGPL-2.1-only\n" + "Written by James Bottomley <James.Bottomley@HansenPartnership.com>\n", + argv[0]); + exit(0); + case 'd': + noda = 0; + break; + case 'c': + policyFilename = optarg; + break; + case 'm': + nomigrate = 1; + break; + default: + printf("Unknown option '%c'\n", c); + usage(argv[0]); + break; + } + } + if (optind >= argc) { + printf("Too few arguments: Expected file name as last argument\n"); + usage(argv[0]); + } + + filename = argv[argc - 1]; + + if (optind < argc - 1) { + printf("Unexpected additional arguments\n"); + usage(argv[0]); + } + + digest.hashAlg = name_alg; + sizeInBytes = TSS_GetDigestSize(digest.hashAlg); + memset((uint8_t *)&digest.digest, 0, sizeInBytes); + + if (policyFilename) { + sk = sk_TSSOPTPOLICY_new_null(); + if (!sk) { + fprintf(stderr, "Failed to allocate policy stack\n"); + exit(1); + } + + rc = tpm2_parse_policy_file(policyFilename, sk, + data_auth, &digest); + if (rc) { + reason = "parse_policy_file"; + goto out_free_policy; + } + } + + if (data_auth) { + if (pass) { + /* key length already checked */ + strcpy(data_auth, pass); + } else { + if (EVP_read_pw_string(data_auth, 128, + "Enter TPM key authority: ", 1)) { + fprintf(stderr, "Passwords do not match\n"); + reason = "authorization"; + rc = NOT_TPM_ERROR; + goto out_free_auth; + } + } + } + + dir = tpm2_set_unique_tssdir(); + rc = tpm2_create(&tssContext, dir); + if (rc) { + reason = "TSS_Create"; + goto out_rmdir; + } + + if ((parent & 0xff000000) == 0x40000000) { + rc = tpm2_load_srk(tssContext, &phandle, parent_auth, + NULL, parent, 1); + if (rc) { + reason = "tpm2_load_srk"; + goto out_delete; + } + } else { + phandle = parent; + } + + tpm2_public_template_seal(p); + + cin.parentHandle = phandle; + cin.outsideInfo.t.size = 0; + cin.creationPCR.count = 0; + + if (policyFilename) { + p->objectAttributes.val &= + ~TPMA_OBJECT_USERWITHAUTH; + rc = TSS_TPM2B_Create( + &p->authPolicy.b, + (uint8_t *)&digest.digest, sizeInBytes, + sizeof(TPMU_HA)); + if (rc) { + reason = "set policy"; + goto out_flush; + } + } + + memset(s, 0, sizeof(*s)); + if (data_auth) { + int len = strlen(data_auth); + memcpy(s->userAuth.b.buffer, data_auth, len); + s->userAuth.b.size = len; + } + s->data.t.size = fread(s->data.t.buffer, 1, + MAX_SYM_DATA, stdin); + + /* set the NODA flag */ + p->objectAttributes.val |= noda; + + if (nomigrate) + p->objectAttributes.val |= + TPMA_OBJECT_FIXEDPARENT | + TPMA_OBJECT_FIXEDTPM; + + /* use salted parameter encryption to hide the key */ + rc = tpm2_get_session_handle(tssContext, &authHandle, phandle, + TPM_SE_HMAC, name_alg); + if (rc) { + reason = "get session handle"; + goto out_flush; + } + + rc = TSS_Execute(tssContext, + (RESPONSE_PARAMETERS *)&cout, + (COMMAND_PARAMETERS *)&cin, + NULL, + TPM_CC_Create, + authHandle, parent_auth, TPMA_SESSION_DECRYPT, + TPM_RH_NULL, NULL, 0); + if (rc) { + reason = "TPM2_Create"; + /* failure means auth handle is not flushed */ + tpm2_flush_handle(tssContext, authHandle); + goto out_flush; + } + + buffer = pubkey; + pubkey_len = 0; + size = sizeof(pubkey); + TSS_TPM2B_PUBLIC_Marshal(&cout.outPublic, &pubkey_len, + &buffer, &size); + buffer = privkey; + privkey_len = 0; + size = sizeof(privkey); + TSS_TPM2B_PRIVATE_Marshal(&cout.outPrivate, &privkey_len, + &buffer, &size); + tpm2_write_tpmfile(filename, pubkey, pubkey_len, + privkey, privkey_len, data_auth == NULL, + parent, sk, 2, NULL); + + + out_flush: + tpm2_flush_srk(tssContext, phandle); + out_delete: + TSS_Delete(tssContext); + out_rmdir: + rmdir(dir); + out_free_auth: + free(data_auth); + out_free_policy: + tpm2_free_policy(sk); + + if (rc) { + if (rc == NOT_TPM_ERROR) + fprintf(stderr, "%s failed\n", reason); + else + tpm2_error(rc, reason); + rc = 1; + } + exit(rc); +} @@ -98,7 +98,7 @@ typedef struct { #define OID_loadableKey "2.23.133.10.1.3" #define OID_importableKey "2.23.133.10.1.4" - +#define OID_sealedData "2.23.133.10.1.5" /* This is the PEM guard tag */ #define TSSLOADABLE_PEM_STRING "TSS2 KEY BLOB" diff --git a/tpm2-common.c b/tpm2-common.c index 95d5f7e..f346585 100644 --- a/tpm2-common.c +++ b/tpm2-common.c @@ -1117,6 +1117,8 @@ int tpm2_load_engine_file(const char *filename, struct app_data **app_data, goto err; } tpm2_type = TPM2_IMPORTABLE; + } else if (strcmp(OID_sealedData, oid) == 0){ + tpm2_type = TPM2_SEALED; } else { fprintf(stderr, "Unrecognised object type\n"); goto err; @@ -1300,7 +1302,7 @@ void tpm2_delete(struct app_data *app_data) } TPM_HANDLE tpm2_load_key(TSS_CONTEXT **tsscp, struct app_data *app_data, - const char *srk_auth) + const char *srk_auth, uint32_t *psrk) { TSS_CONTEXT *tssContext; Load_In in; @@ -1349,17 +1351,21 @@ TPM_HANDLE tpm2_load_key(TSS_CONTEXT **tsscp, struct app_data *app_data, if (rc) { tpm2_error(rc, "TPM2_Load"); tpm2_flush_handle(tssContext, session); - } - else + } else { key = out.objectHandle; + } out_flush_srk: - tpm2_flush_srk(tssContext, in.parentHandle); + if (key && psrk) + *psrk = in.parentHandle; + else + tpm2_flush_srk(tssContext, in.parentHandle); out: if (!key) TSS_Delete(tssContext); else *tsscp = tssContext; + return key; } @@ -1428,7 +1434,9 @@ int tpm2_write_tpmfile(const char *file, BYTE *pubkey, int pubkey_len, PEM_write_bio_TSSLOADABLE(outb, &k.tssl); } else { - if (secret) { + if (version == 2) { + k.tpk.type = OBJ_txt2obj(OID_sealedData, 1); + } else if (secret) { k.tpk.type = OBJ_txt2obj(OID_importableKey, 1); k.tpk.secret = ASN1_OCTET_STRING_new(); ASN1_STRING_set(k.tpk.secret, secret->t.secret, diff --git a/tpm2-common.h b/tpm2-common.h index 33cac4a..046761c 100644 --- a/tpm2-common.h +++ b/tpm2-common.h @@ -71,7 +71,7 @@ int tpm2_load_engine_file(const char *filename, struct app_data **app_data, EVP_PKEY **ppkey, UI_METHOD *ui, void *cb_data, const char *srk_auth, int get_key_auth); TPM_HANDLE tpm2_load_key(TSS_CONTEXT **tsscp, struct app_data *app_data, - const char *srk_auth); + const char *srk_auth, uint32_t *psession); void tpm2_unload_key(TSS_CONTEXT *tssContext, TPM_HANDLE key); void tpm2_delete(struct app_data *app_data); char *tpm2_get_auth(UI_METHOD *ui, char *input_string, void *cb_data); diff --git a/unseal_tpm2_data.1.in b/unseal_tpm2_data.1.in new file mode 100644 index 0000000..3533f13 --- /dev/null +++ b/unseal_tpm2_data.1.in @@ -0,0 +1,18 @@ +[name] +unseal_tpm2_data - unseal a blob of data using a TPM + +[description] + +Once a sealed data blob has been created, it may only be unsealed by +the TPM for which it was created. This command attempts that unseal +operation + +[examples] + +Create a sealed data blob to the storage parent (owner hierarchy) + + echo "somedatatoseal" seal_tpm2_key -a -k passw0rd -p owner seal.tpm + +Unseal the data + + unseal_tpm2_key -k passw0rd seal.tpm diff --git a/unseal_tpm2_data.c b/unseal_tpm2_data.c new file mode 100644 index 0000000..51f1246 --- /dev/null +++ b/unseal_tpm2_data.c @@ -0,0 +1,206 @@ +/* + * + * Copyright (C) 2019 James Bottomley <James.Bottomley@HansenPartnership.com> + * + * SPDX-License-Identifier: LGPL-2.1-only + */ + +#include <stdio.h> +#include <getopt.h> +#include <string.h> +#include <strings.h> +#include <errno.h> +#include <unistd.h> + +#include <openssl/evp.h> +#include <openssl/pem.h> +#include <openssl/ui.h> + +#define TSSINCLUDE(x) < TSS_INCLUDE/x > +#include TSSINCLUDE(tss.h) +#include TSSINCLUDE(tssutils.h) +#include TSSINCLUDE(tssmarshal.h) +#include TSSINCLUDE(Unmarshal_fp.h) +#include TSSINCLUDE(tsscrypto.h) +#include TSSINCLUDE(tsscryptoh.h) + +#include "tpm2-asn.h" +#include "tpm2-common.h" + +static TPM_ALG_ID name_alg = TPM_ALG_SHA256; + +static struct option long_options[] = { + {"auth-parent", 1, 0, 'b'}, + {"help", 0, 0, 'h'}, + {"version", 0, 0, 'v'}, + {"password", 1, 0, 'k'}, + {0, 0, 0, 0} +}; + +void +usage(char *argv0) +{ + fprintf(stdout, "Usage: %s [options] <filename>\n\n" + "Options:\n" + "\t-b, --auth-parent <pwd> Specify the parent key password\n" + "\t (default EmptyAuth)\n" + "\t-h, --help print this help message\n" + "\t-v, --version print package version\n" + "\t-k, --password <pwd> use this password instead of prompting\n" + "\n" + "Report bugs to " PACKAGE_BUGREPORT "\n", + argv0); + exit(-1); +} + +static int ui_read(UI *ui, UI_STRING *uis) +{ + char password[128]; + const char *pwd = UI_get0_user_data(ui); + + if (UI_get_string_type(uis) != UIT_PROMPT) + return 0; + + if (!pwd || pwd[0] == '\0') { + pwd = password; + EVP_read_pw_string(password, sizeof(password), "TPM Sealed Data Passphrase:", 0); + } + UI_set_result(ui, uis, pwd); + return 1; +} + +int main(int argc, char **argv) +{ + int option_index, c; + char *parent_auth = NULL, *pass = NULL; + char *filename; + TPM_RC rc; + TSS_CONTEXT *tssContext; + const char *reason; + Unseal_In uin; + Unseal_Out uout; + uint32_t parent, session; + UI_METHOD *ui = UI_create_method("unseal"); + struct app_data *app_data; + + while (1) { + option_index = 0; + c = getopt_long(argc, argv, "k:b:hv", + long_options, &option_index); + if (c == -1) + break; + + switch (c) { + case 'k': + pass = optarg; + if (strlen(pass) > 127) { + printf("password is too long\n"); + exit(1); + } + break; + case 'b': + parent_auth = optarg; + break; + case 'h': + usage(argv[0]); + break; + case 'v': + fprintf(stdout, "%s " VERSION "\n" + "Copyright 2017 by James Bottomley\n" + "License LGPL-2.1-only\n" + "Written by James Bottomley <James.Bottomley@HansenPartnership.com>\n", + argv[0]); + exit(0); + default: + printf("Unknown option '%c'\n", c); + usage(argv[0]); + break; + } + } + if (optind >= argc) { + printf("Too few arguments: Expected file name as last argument\n"); + usage(argv[0]); + } + + filename = argv[argc - 1]; + + if (optind < argc - 1) { + printf("Unexpected additional arguments\n"); + usage(argv[0]); + } + + if (!ui) { + fprintf(stderr, "Failed to allocate UI\n"); + exit(1); + } + + UI_method_set_reader(ui, ui_read); + rc = tpm2_load_engine_file(filename, &app_data, NULL, + ui, pass, parent_auth, 1); + if (!rc) { + reason = "tpm2_engine_load_file"; + rc = NOT_TPM_ERROR; + goto err; + } + + rc = tpm2_load_key(&tssContext, app_data, parent_auth, + &parent); + if (!rc) { + reason = "tpm2_load_key"; + rc = NOT_TPM_ERROR; + goto out_free_app_data; + } + + uin.itemHandle = rc; + + rc = tpm2_get_session_handle(tssContext, &session, parent, + app_data->req_policy_session ? + TPM_SE_POLICY : TPM_SE_HMAC, + name_alg); + tpm2_flush_handle(tssContext, parent); + if (rc) { + reason = "tpm2_get_session_handle"; + goto out_flush_data; + } + + if (app_data->req_policy_session) { + rc = tpm2_init_session(tssContext, session, + app_data->num_commands, + app_data->commands, name_alg); + if (rc) { + reason = "tpm2_init_session"; + goto out_flush_session; + } + } + + rc = TSS_Execute(tssContext, + (RESPONSE_PARAMETERS *)&uout, + (COMMAND_PARAMETERS *)&uin, + NULL, + TPM_CC_Unseal, + session, app_data->auth, TPMA_SESSION_ENCRYPT, + TPM_RH_NULL, NULL, 0); + if (rc) { + reason = "TPM2_Unseal"; + out_flush_session: + tpm2_flush_handle(tssContext, session); + } else { + fwrite(uout.outData.t.buffer, 1, uout.outData.t.size, stdout); + } + + out_flush_data: + tpm2_flush_handle(tssContext, uin.itemHandle); + out_free_app_data: + TSS_Delete(tssContext); + tpm2_delete(app_data); + + err: + if (rc) { + if (rc == NOT_TPM_ERROR) + fprintf(stderr, "%s failed\n", reason); + else + tpm2_error(rc, reason); + rc = 1; + } + exit(rc); +} |