aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@HansenPartnership.com>2018-11-13 12:07:29 -0800
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2018-11-14 18:16:18 -0800
commitd81444b9dccc88ace6bdb4be37fff1318361b50b (patch)
tree4599b184f9d1a6cb0982c7a46f9df3e83d2837aa
parentd51dc40fdd4817dd610a9bd9e326bb23ddd2e7fa (diff)
downloadopenssl_tpm2_engine-d81444b9dccc88ace6bdb4be37fff1318361b50b.tar.gz
Add importable keys
Importable keys are a new type of key that can be created without access to the receiving TPM. The design of importable keys is that you "wrap" the key (encrypt with a derived key) in such a way that it can only be unwrapped by the TPM local parent key. To do this wrapping you only need to know the public key of the parent, which can be shipped in an ordinary openssl public key file. The key format of importable keys requires an additional encrypted secret parameter, which basically encodes the wrapping key using ECDH so it can be decrypted by the parent on import. Importable keys are designed to be used everywhere the current loadable keys are used, the only difference being that the TPM engine converts the importable key to loadable on first load and thereafter uses it identically to a loadable key. The new command line option of importable keys is create_tpm2_key --import <pubparent> --wrap <private key> tmp.key Where <pubparent> is the parent public key and <private key> is the key you are wrapping (obviously since you have no access to the TPM, this option can only be used to wrap existing private keys). Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
-rw-r--r--create_tpm2_key.1.in17
-rw-r--r--create_tpm2_key.c300
-rw-r--r--e_tpm2.c108
-rw-r--r--tpm2-asn.h3
4 files changed, 387 insertions, 41 deletions
diff --git a/create_tpm2_key.1.in b/create_tpm2_key.1.in
index 0e52d86..6ec5f25 100644
--- a/create_tpm2_key.1.in
+++ b/create_tpm2_key.1.in
@@ -7,6 +7,13 @@ Can be used to create a TPM loadable representation of a private key.
The key is either internal to the TPM or wrapped from an existing
private key.
+Note that this command can now create two different types of keys:
+importable and loadable (the default type being loadable). The
+difference between the two is that the creation of loadable keys
+requires the presence of the actual TPM the key will be loaded on. An
+importable key can be created without any TPM contact provided you
+have the public key of the parent the new key will be imported to.
+
[files]
Policy File Format
@@ -69,3 +76,13 @@ Create a self-signed cert using the TPM engine:
3. Test using openssl:
$ openssl s_server -cert <certfilename> -www -accept 4433 -keyform engine -engi
ne tpm -key <keyfilename>
+
+Creating an importable key:
+
+1. First get the public key of the storage primary seed (as an elliptic
+ curve key):
+ $ tsscreateprimary -ecc nistp256 -hi o -opem srk.pub
+
+2. Once you have this public key, you can export it anywhere and do the
+ key wrapping
+ $ create_tpm2_key --import srk.pub --wrap my_key.priv my_key.tpm
diff --git a/create_tpm2_key.c b/create_tpm2_key.c
index 899e434..1412cb7 100644
--- a/create_tpm2_key.c
+++ b/create_tpm2_key.c
@@ -58,6 +58,7 @@ static struct option long_options[] = {
{"list-curves", 0, 0, 'l'},
{"da", 0, 0, 'd'},
{"key-policy", 1, 0, 'c'},
+ {"import", 1, 0, 'i'},
/*
* The option --deprecated allows us to create old format keys
* for the purposes of testing. It should never be used in
@@ -98,6 +99,8 @@ usage(char *argv0)
"\t Supported curves are bnp256, nisp256, nisp384\n"
"\t-l, --list-curves List all the Elliptic Curves the TPM supports\n"
"\t-c, --key-policy Specify a policy for the TPM key\n"
+ "\t-i, --import <pubkey> Create an importable key with the outer\n"
+ " wrapper encrypted to <pubkey>\n"
"\n"
"Report bugs to " PACKAGE_BUGREPORT "\n",
argv0);
@@ -270,6 +273,141 @@ TPM_RC tpm2_innerwrap(TPMT_SENSITIVE *s,
return TPM_RC_SUCCESS;
}
+TPM_RC tpm2_outerwrap(EVP_PKEY *parent,
+ TPMT_SENSITIVE *s,
+ TPMT_PUBLIC *pub,
+ TPM2B_PRIVATE *p,
+ TPM2B_ENCRYPTED_SECRET *enc_secret)
+{
+ TPM2B_PRIVATE secret, seed;
+ /* amount of room in the buffer for the integrity TPM2B */
+ const int name_alg_size = TSS_GetDigestSize(pub->nameAlg);
+ const int integrity_skip = name_alg_size + 2;
+ // BYTE *integrity = p->t.buffer;
+ BYTE *sensitive = p->t.buffer + integrity_skip;
+ BYTE *buf;
+ TPM2B *t2b;
+ INT32 size;
+ size_t ssize;
+ UINT16 bsize, written = 0;
+ EVP_PKEY *ephemeral = NULL;
+ EVP_PKEY_CTX *ctx;
+ TPM2B_ECC_POINT pub_pt, ephemeral_pt;
+ EC_KEY *e_parent, *e_ephemeral;
+ const EC_GROUP *group;
+ unsigned char aeskey[T2_AES_KEY_BYTES];
+ /* hmac follows namealg, so set to max size */
+ TPM2B_KEY hmackey;
+ TPMT_HA hmac;
+ TPM2B_NAME name;
+ TPM2B_DIGEST digest;
+ unsigned char null_iv[AES_128_BLOCK_SIZE_BYTES];
+ TPM2B null_2b;
+
+ null_2b.size = 0;
+
+ if (EVP_PKEY_type(EVP_PKEY_id(parent)) != EVP_PKEY_EC) {
+ printf("Can only currently wrap to EC parent\n");
+ return TPM_RC_ASYMMETRIC;
+ }
+
+ e_parent = EVP_PKEY_get1_EC_KEY(parent);
+ group = EC_KEY_get0_group(e_parent);
+
+ /* marshal the sensitive into a TPM2B */
+ t2b = (TPM2B *)sensitive;
+ buf = t2b->buffer;
+ size = sizeof(p->t.buffer) - integrity_skip;
+ bsize = 0;
+ TSS_TPMT_SENSITIVE_Marshal(s, &bsize, &buf, &size);
+ buf = (BYTE *)&t2b->size;
+ size = 2;
+ TSS_UINT16_Marshal(&bsize, &written, &buf, &size);
+ /* set the total size of the private entity */
+ p->b.size = bsize + sizeof(UINT16) + integrity_skip;
+
+ /* compute the elliptic curve shared (and encrypted) secret */
+ ctx = EVP_PKEY_CTX_new(parent, NULL);
+ if (!ctx)
+ goto openssl_err;
+ if (EVP_PKEY_keygen_init(ctx) != 1)
+ goto openssl_err;
+ EVP_PKEY_keygen(ctx, &ephemeral);
+ if (!ephemeral)
+ goto openssl_err;
+ /* otherwise the ctx free will free the key */
+#if OPENSSL_VERSION_NUMBER < 0x10100000
+ CRYPTO_add(&ephemeral->references, 1, CRYPTO_LOCK_EVP_PKEY);
+#else
+ EVP_PKEY_up_ref(ephemeral);
+#endif
+ EVP_PKEY_CTX_free(ctx);
+
+ e_ephemeral = EVP_PKEY_get1_EC_KEY(ephemeral);
+
+ /* now begin again with the ephemeral private key because the
+ * context must be initialised with the private key */
+ ctx = EVP_PKEY_CTX_new(ephemeral, NULL);
+ if (!ctx)
+ goto openssl_err;
+ if (EVP_PKEY_derive_init(ctx) != 1)
+ goto openssl_err;
+ if (EVP_PKEY_derive_set_peer(ctx, parent) != 1)
+ goto openssl_err;
+ ssize = sizeof(secret.t.buffer);
+ if (EVP_PKEY_derive(ctx, secret.b.buffer, &ssize) != 1)
+ goto openssl_err;
+ secret.b.size = ssize;
+ EVP_PKEY_CTX_free(ctx);
+
+ tpm2_get_public_point(&pub_pt, group, EC_KEY_get0_public_key(e_parent));
+ tpm2_get_public_point(&ephemeral_pt, group,
+ EC_KEY_get0_public_key(e_ephemeral));
+ EC_KEY_free(e_parent);
+ EC_KEY_free(e_ephemeral);
+
+ /* now pass the secret through KDFe to get the shared secret
+ * The size is the size of the parent name algorithm which we
+ * assume to be sha256 */
+ TSS_KDFE(seed.b.buffer, pub->nameAlg, &secret.b, "DUPLICATE",
+ &ephemeral_pt.point.x.b, &pub_pt.point.x.b,
+ SHA256_DIGEST_LENGTH*8);
+ seed.b.size = SHA256_DIGEST_LENGTH;
+
+ /* and finally through KDFa to get the aes symmetric encryption key */
+ tpm2_ObjectPublic_GetName(&name, pub);
+ TSS_KDFA(aeskey, pub->nameAlg, &seed.b, "STORAGE", &name.b, &null_2b,
+ T2_AES_KEY_BITS);
+ /* and then the outer HMAC key */
+ hmackey.b.size = name_alg_size;
+ TSS_KDFA(hmackey.b.buffer, pub->nameAlg, &seed.b, "INTEGRITY",
+ &null_2b, &null_2b, name_alg_size * 8);
+ /* OK the ephermeral public point is now the encrypted secret */
+ size = sizeof(ephemeral_pt);
+ buf = enc_secret->b.buffer;
+ TSS_TPM2B_ECC_POINT_Marshal(&ephemeral_pt, &written,
+ &buf, &size);
+ enc_secret->b.size = written;
+ memset(null_iv, 0, sizeof(null_iv));
+ TSS_AES_EncryptCFB(sensitive, T2_AES_KEY_BITS, aeskey, null_iv,
+ p->t.size - integrity_skip, sensitive);
+ hmac.hashAlg = pub->nameAlg;
+ TSS_HMAC_Generate(&hmac, &hmackey,
+ p->t.size - integrity_skip, sensitive,
+ name.b.size, name.b.buffer,
+ 0, NULL);
+ digest.b.size = name_alg_size;
+ memcpy(digest.b.buffer, &hmac.digest, digest.b.size);
+ size = integrity_skip;
+ buf = p->t.buffer;
+ TSS_TPM2B_DIGEST_Marshal(&digest, &written, &buf, &size);
+ return TPM_RC_SUCCESS;
+
+ openssl_err:
+ ERR_print_errors_fp(stderr);
+ return TPM_RC_ASYMMETRIC;
+}
+
TPM_RC
parse_policy_file(const char *policy_file, STACK_OF(TSSOPTPOLICY) *sk,
char *auth, TPMT_HA *digest)
@@ -378,7 +516,7 @@ int
openssl_write_tpmfile(const char *file, BYTE *pubkey, int pubkey_len,
BYTE *privkey, int privkey_len, int empty_auth,
TPM_HANDLE parent, STACK_OF(TSSOPTPOLICY) *sk,
- int version)
+ int version, TPM2B_ENCRYPTED_SECRET *secret)
{
union {
TSSLOADABLE tssl;
@@ -406,7 +544,14 @@ openssl_write_tpmfile(const char *file, BYTE *pubkey, int pubkey_len,
PEM_write_bio_TSSLOADABLE(outb, &k.tssl);
} else {
- k.tpk.type = OBJ_txt2obj(OID_loadableKey, 1);
+ 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,
+ secret->t.size);
+ } else {
+ k.tpk.type = OBJ_txt2obj(OID_loadableKey, 1);
+ }
k.tpk.emptyAuth = empty_auth;
k.tpk.parent = ASN1_INTEGER_new();
ASN1_INTEGER_set(k.tpk.parent, parent);
@@ -445,6 +590,27 @@ openssl_read_key(char *filename)
return pkey;
}
+EVP_PKEY *
+openssl_read_public_key(char *filename)
+{
+ BIO *b = NULL;
+ EVP_PKEY *pkey;
+
+ b = BIO_new_file(filename, "r");
+ if (b == NULL) {
+ fprintf(stderr, "Error opening file for read: %s\n", filename);
+ return NULL;
+ }
+
+ if ((pkey = PEM_read_bio_PUBKEY(b, NULL, NULL, NULL)) == NULL) {
+ fprintf(stderr, "Reading key %s from disk failed.\n", filename);
+ openssl_print_errors();
+ }
+ BIO_free(b);
+
+ return pkey;
+}
+
void tpm2_public_template_rsa(TPMT_PUBLIC *pub)
{
pub->type = TPM_ALG_RSA;
@@ -784,7 +950,7 @@ int main(int argc, char **argv)
Create_Out cout;
TPM2B_PUBLIC *pub;
TPM2B_PRIVATE *priv;
- char *key = NULL, *parent_auth = NULL;
+ char *key = NULL, *parent_auth = NULL, *import = NULL;
TPMI_ECC_CURVE ecc = TPM_ECC_NONE;
int rsa = -1;
uint32_t noda = TPMA_OBJECT_NODA;
@@ -794,10 +960,15 @@ int main(int argc, char **argv)
int version = 1;
uint32_t sizeInBytes;
TPMT_HA digest;
+ TPM2B_ENCRYPTED_SECRET secret, *enc_secret = NULL;
+
+ OpenSSL_add_all_digests();
+ /* may be needed to decrypt the key */
+ OpenSSL_add_all_ciphers();
while (1) {
option_index = 0;
- c = getopt_long(argc, argv, "n:s:ab:p:hw:vk:re:ldc:",
+ c = getopt_long(argc, argv, "n:s:ab:p:hw:vk:re:ldc:i:",
long_options, &option_index);
if (c == -1)
break;
@@ -873,6 +1044,9 @@ int main(int argc, char **argv)
case 'c':
policyFilename = optarg;
break;
+ case 'i':
+ import = optarg;
+ break;
case OPT_DEPRECATED:
version = 0;
break;
@@ -910,21 +1084,9 @@ int main(int argc, char **argv)
rsa = 0;
}
- dir = tpm2_set_unique_tssdir();
- rc = tpm2_create(&tssContext, dir);
- if (rc) {
- reason = "TSS_Create";
- goto out_err;
- }
-
- if ((parent & 0xff000000) == 0x40000000) {
- rc = tpm2_load_srk(tssContext, &phandle, parent_auth, NULL, parent, version);
- if (rc) {
- reason = "tpm2_load_srk";
- goto out_delete;
- }
- } else {
- phandle = parent;
+ if (import && !wrap) {
+ fprintf(stderr, "Can only wrap importable keys\n");
+ exit(1);
}
digest.hashAlg = name_alg;
@@ -936,13 +1098,13 @@ int main(int argc, char **argv)
if (!sk) {
rc = NOT_TPM_ERROR;
reason="sk_TSSOPTPOLICY_new_null allocation";
- goto out_flush;
+ goto out_err;
}
rc = parse_policy_file(policyFilename, sk, auth, &digest);
if (rc) {
reason = "parse_policy_file";
- goto out_flush;
+ goto out_free_policy;
}
}
@@ -955,17 +1117,94 @@ int main(int argc, char **argv)
fprintf(stderr, "Passwords do not match\n");
reason = "authorization";
rc = NOT_TPM_ERROR;
- goto out_flush;
+ goto out_free_auth;
}
}
}
+ if (import) {
+ EVP_PKEY *p_pkey = openssl_read_public_key(import);
+ EVP_PKEY *pkey = openssl_read_key(wrap);
+ TPMT_SENSITIVE s;
+
+ /* steal existing private and public areas */
+ pub = &iin.objectPublic;
+ priv = &iout.outPrivate;
+
+ rc = NOT_TPM_ERROR;
+
+ if (!p_pkey || !pkey) {
+ reason = "read openssl key";
+ goto out_err;
+ }
+
+ /* FIXME: should do RSA as well, it's just more complex */
+ if (EVP_PKEY_type(EVP_PKEY_id(p_pkey)) != EVP_PKEY_EC) {
+ reason = "parent not EC key";
+ goto out_err;
+ }
+
+ rc = openssl_to_tpm_public(pub, pkey);
+ if (rc) {
+ reason = "openssl_to_tpm_public";
+ goto out_err;
+ }
+ if (policyFilename) {
+ pub->publicArea.objectAttributes.val &=
+ ~TPMA_OBJECT_USERWITHAUTH;
+ rc = TSS_TPM2B_Create(
+ &pub->publicArea.authPolicy.b,
+ (uint8_t *)&digest.digest, sizeInBytes,
+ sizeof(TPMU_HA));
+ if (rc) {
+ reason = "set policy";
+ goto out_err;
+ }
+ }
+
+ rc = wrap_key(&s, auth, pkey);
+ if (rc) {
+ reason = "wrap_key";
+ goto out_err;
+ }
+
+ /* set the NODA flag */
+ pub->publicArea.objectAttributes.val |= noda;
+
+ rc = tpm2_outerwrap(p_pkey, &s, &pub->publicArea,
+ priv, &secret);
+ if (rc) {
+ reason = "tpm2_outerwrap";
+ goto out_err;
+ }
+
+ enc_secret = &secret;
+
+ /* skip over all the TPM connection stuff */
+ goto write_key;
+ }
+
+ dir = tpm2_set_unique_tssdir();
+ rc = tpm2_create(&tssContext, dir);
+ if (rc) {
+ reason = "TSS_Create";
+ goto out_free_auth;
+ }
+
+ if ((parent & 0xff000000) == 0x40000000) {
+ rc = tpm2_load_srk(tssContext, &phandle, parent_auth, NULL, parent, version);
+ if (rc) {
+ reason = "tpm2_load_srk";
+ goto out_delete;
+ }
+ } else {
+ phandle = parent;
+ }
+
if (wrap) {
EVP_PKEY *pkey;
TPMT_SENSITIVE s;
- /* may be needed to decrypt the key */
- OpenSSL_add_all_ciphers();
pkey = openssl_read_key(wrap);
if (!pkey) {
rc = NOT_TPM_ERROR;
@@ -1113,6 +1352,10 @@ int main(int argc, char **argv)
priv = &cout.outPrivate;
}
tpm2_flush_srk(tssContext, phandle);
+ TSS_Delete(tssContext);
+ tpm2_rm_tssdir(dir, 0);
+
+ write_key:
buffer = pubkey;
pubkey_len = 0;
size = sizeof(pubkey);
@@ -1123,19 +1366,20 @@ int main(int argc, char **argv)
TSS_TPM2B_PRIVATE_Marshal(priv, &privkey_len, &buffer, &size);
openssl_write_tpmfile(filename, pubkey, pubkey_len,
privkey, privkey_len, auth == NULL, parent, sk,
- version);
+ version, enc_secret);
free_policy(sk);
- TSS_Delete(tssContext);
- tpm2_rm_tssdir(dir, 0);
exit(0);
out_flush:
tpm2_flush_srk(tssContext, phandle);
- free_policy(sk);
out_delete:
TSS_Delete(tssContext);
rmdir(dir);
+ out_free_auth:
+ free(auth);
+ out_free_policy:
+ free_policy(sk);
out_err:
if (rc == NOT_TPM_ERROR)
fprintf(stderr, "%s failed\n", reason);
diff --git a/e_tpm2.c b/e_tpm2.c
index 39026e9..84af5e5 100644
--- a/e_tpm2.c
+++ b/e_tpm2.c
@@ -316,7 +316,6 @@ static int tpm2_engine_load_key_core(ENGINE *e, EVP_PKEY **ppkey,
struct tpm_ui *ui, void *cb_data)
{
EVP_PKEY *pkey;
- TPM2B_PUBLIC p;
BIO *bf;
TSSLOADABLE *tssl = NULL;
TSSPRIVKEY *tpk = NULL;
@@ -331,6 +330,8 @@ static int tpm2_engine_load_key_core(ENGINE *e, EVP_PKEY **ppkey,
ASN1_OCTET_STRING *pubkey;
STACK_OF(TSSOPTPOLICY) *policy;
ASN1_OCTET_STRING *privkey;
+ ASN1_OCTET_STRING *secret = NULL;
+ Import_In iin;
if (!key_id && !bio) {
fprintf(stderr, "key_id or bio is NULL\n");
@@ -367,6 +368,7 @@ static int tpm2_engine_load_key_core(ENGINE *e, EVP_PKEY **ppkey,
pubkey = tpk->pubkey;
privkey = tpk->privkey;
policy = tpk->policy;
+ secret = tpk->secret;
} else {
BIO_seek(bf, 0);
tssl = PEM_read_bio_TSSLOADABLE(bf, NULL, NULL, NULL);
@@ -411,8 +413,10 @@ static int tpm2_engine_load_key_core(ENGINE *e, EVP_PKEY **ppkey,
goto err;
}
} else if (strcmp(OID_importableKey, oid) == 0) {
- fprintf(stderr, "Importable keys currently unsupported\n");
- goto err;
+ if (!secret) {
+ fprintf(stderr, "Importable keys require an encrypted secret\n");
+ goto err;
+ }
} else {
fprintf(stderr, "Unrecognised object type\n");
goto err;
@@ -435,23 +439,100 @@ static int tpm2_engine_load_key_core(ENGINE *e, EVP_PKEY **ppkey,
/* older keys have absent parent */
app_data->parent = TPM_RH_OWNER;
- app_data->priv = OPENSSL_malloc(privkey->length);
- if (!app_data->priv)
- goto err_free;
- app_data->priv_len = privkey->length;
- memcpy(app_data->priv, privkey->data, app_data->priv_len);
-
app_data->pub = OPENSSL_malloc(pubkey->length);
if (!app_data->pub)
goto err_free;
app_data->pub_len = pubkey->length;
memcpy(app_data->pub, pubkey->data, app_data->pub_len);
+
buffer = app_data->pub;
size = app_data->pub_len;
- TPM2B_PUBLIC_Unmarshal(&p, &buffer, &size, FALSE);
- app_data->name_alg = p.publicArea.nameAlg;
+ TPM2B_PUBLIC_Unmarshal(&iin.objectPublic, &buffer, &size, FALSE);
+ app_data->name_alg = iin.objectPublic.publicArea.nameAlg;
+
+ if (strcmp(OID_importableKey, oid) == 0) {
+ TPM_HANDLE session;
+ TSS_CONTEXT *tssContext;
+ TPM_RC rc;
+ const char *reason;
+ TPM2B_PRIVATE priv_2b;
+ BYTE *buf;
+ UINT16 written;
+ INT32 size;
+ Import_Out iout;
+
+ rc = tpm2_create(&tssContext, app_data->dir);
+ if (rc) {
+ reason="tpm2_create";
+ goto import_err;
+ }
+
+ if ((app_data->parent & 0xff000000) == 0x40000000) {
+ tpm2_load_srk(tssContext, &iin.parentHandle,
+ srk_auth, NULL, app_data->parent, 1);
+ } else {
+ iin.parentHandle = app_data->parent;
+ }
+ rc = tpm2_get_session_handle(tssContext, &session,
+ iin.parentHandle,
+ TPM_SE_HMAC,
+ iin.objectPublic.publicArea.nameAlg);
+ if (rc) {
+ reason="tpm2_get_session_handle";
+ goto import_err;
+ }
+
+ /* no inner encryption */
+ iin.encryptionKey.t.size = 0;
+ iin.symmetricAlg.algorithm = TPM_ALG_NULL;
+
+ /* for importable keys the private key is actually the
+ * outer wrapped duplicate structure */
+ buffer = privkey->data;
+ size = privkey->length;
+ TPM2B_PRIVATE_Unmarshal(&iin.duplicate, &buffer, &size);
+
+ buffer = secret->data;
+ size = secret->length;
+ TPM2B_ENCRYPTED_SECRET_Unmarshal(&iin.inSymSeed, &buffer, &size);
+ rc = TSS_Execute(tssContext,
+ (RESPONSE_PARAMETERS *)&iout,
+ (COMMAND_PARAMETERS *)&iin,
+ NULL,
+ TPM_CC_Import,
+ session, srk_auth, 0,
+ TPM_RH_NULL, NULL, 0);
+ if (rc)
+ tpm2_flush_handle(tssContext, session);
+ reason = "TPM2_Import";
+
+ import_err:
+ tpm2_flush_srk(tssContext, iin.parentHandle);
+ TSS_Delete(tssContext);
+ if (rc) {
+ tpm2_error(rc, reason);
+ goto err_free;
+ }
+ buf = priv_2b.t.buffer;
+ size = sizeof(priv_2b.t.buffer);
+ TSS_TPM2B_PRIVATE_Marshal(&iout.outPrivate, &written,
+ &buf, &size);
+ app_data->priv = OPENSSL_malloc(written);
+ if (!app_data->priv)
+ goto err_free;
+ app_data->priv_len = written;
+ memcpy(app_data->priv, priv_2b.t.buffer, written);
+ } else {
+ app_data->priv = OPENSSL_malloc(privkey->length);
+ if (!app_data->priv)
+ goto err_free;
+
+ app_data->priv_len = privkey->length;
+ memcpy(app_data->priv, privkey->data, app_data->priv_len);
+ }
+
/* create the new objects to return */
- pkey = tpm2_to_openssl_public(&p.publicArea);
+ pkey = tpm2_to_openssl_public(&iin.objectPublic.publicArea);
if (!pkey) {
fprintf(stderr, "Failed to allocate a new EVP_KEY\n");
goto err_free;
@@ -463,7 +544,8 @@ static int tpm2_engine_load_key_core(ENGINE *e, EVP_PKEY **ppkey,
goto err_free_key;
}
- if (!(p.publicArea.objectAttributes.val & TPMA_OBJECT_USERWITHAUTH))
+ if (!(iin.objectPublic.publicArea.objectAttributes.val &
+ TPMA_OBJECT_USERWITHAUTH))
app_data->req_policy_session = 1;
if (!tpm2_engine_load_key_policy(app_data, policy))
diff --git a/tpm2-asn.h b/tpm2-asn.h
index 15e0f84..82241be 100644
--- a/tpm2-asn.h
+++ b/tpm2-asn.h
@@ -65,6 +65,7 @@ DEFINE_STACK_OF(TSSOPTPOLICY);
* type OBJECT IDENTIFIER
* emptyAuth [0] EXPLICIT BOOLEAN OPTIONAL
* policy [1] EXPLICIT SEQUENCE OF TPMPolicy OPTIONAL
+ * secret [2] EXPLICIT OCTET STRING OPTIONAL
* parent INTEGER
* pubkey OCTET STRING
* privkey OCTET STRING
@@ -84,6 +85,7 @@ typedef struct {
ASN1_OBJECT *type;
ASN1_BOOLEAN emptyAuth;
STACK_OF(TSSOPTPOLICY) *policy;
+ ASN1_OCTET_STRING *secret;
ASN1_INTEGER *parent;
ASN1_OCTET_STRING *pubkey;
ASN1_OCTET_STRING *privkey;
@@ -120,6 +122,7 @@ ASN1_SEQUENCE(TSSPRIVKEY) = {
ASN1_SIMPLE(TSSPRIVKEY, type, ASN1_OBJECT),
ASN1_EXP_OPT(TSSPRIVKEY, emptyAuth, ASN1_BOOLEAN, 0),
ASN1_EXP_SEQUENCE_OF_OPT(TSSPRIVKEY, policy, TSSOPTPOLICY, 1),
+ ASN1_EXP_OPT(TSSPRIVKEY, secret, ASN1_OCTET_STRING, 2),
ASN1_SIMPLE(TSSPRIVKEY, parent, ASN1_INTEGER),
ASN1_SIMPLE(TSSPRIVKEY, pubkey, ASN1_OCTET_STRING),
ASN1_SIMPLE(TSSPRIVKEY, privkey, ASN1_OCTET_STRING)