aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@HansenPartnership.com>2023-01-11 11:20:22 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2023-01-12 16:41:35 -0500
commit23fbe121a6023af315a01db313f05c29d86e2e38 (patch)
treedbc3c8f4f5112fa772ada9c5b983cf058e49593f
parentb0f6f1bede44467f1bff3a52a7e7adee18f011ec (diff)
downloadopenssl_tpm2_engine-23fbe121a6023af315a01db313f05c29d86e2e38.tar.gz
Move tpm2_outerwrap to common
So it can be reused in seal_tpm2_key by adding an --import option Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
-rw-r--r--create_tpm2_key.c135
-rw-r--r--tpm2-common.c135
-rw-r--r--tpm2-common.h5
3 files changed, 140 insertions, 135 deletions
diff --git a/create_tpm2_key.c b/create_tpm2_key.c
index edb8668..f701a93 100644
--- a/create_tpm2_key.c
+++ b/create_tpm2_key.c
@@ -204,141 +204,6 @@ TPM_RC tpm2_innerwrap(TPMT_SENSITIVE *s,
return TPM_RC_SUCCESS;
}
-TPM_RC tpm2_outerwrap(EVP_PKEY *parent,
- TPMT_SENSITIVE *s,
- TPMT_PUBLIC *pub,
- PRIVATE_2B *p,
- ENCRYPTED_SECRET_2B *enc_secret)
-{
- PRIVATE_2B 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->buffer;
- BYTE *sensitive = p->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 */
- KEY_2B hmackey;
- TPMT_HA hmac;
- NAME_2B name;
- DIGEST_2B 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->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->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.buffer);
- if (EVP_PKEY_derive(ctx, secret.buffer, &ssize) != 1)
- goto openssl_err;
- secret.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.buffer, pub->nameAlg, (TPM2B *)&secret, "DUPLICATE",
- (TPM2B *)&ephemeral_pt.point.x, (TPM2B *)&pub_pt.point.x,
- SHA256_DIGEST_LENGTH*8);
- seed.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, (TPM2B *)&seed, "STORAGE",
- (TPM2B *)&name, &null_2b, T2_AES_KEY_BITS);
- /* and then the outer HMAC key */
- hmackey.size = name_alg_size;
- TSS_KDFA(hmackey.buffer, pub->nameAlg, (TPM2B *)&seed, "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->secret;
- TSS_TPM2B_ECC_POINT_Marshal(&ephemeral_pt, &written,
- &buf, &size);
- enc_secret->size = written;
- memset(null_iv, 0, sizeof(null_iv));
- TSS_AES_EncryptCFB(sensitive, T2_AES_KEY_BITS, aeskey, null_iv,
- p->size - integrity_skip, sensitive);
- hmac.hashAlg = pub->nameAlg;
- TSS_HMAC_Generate(&hmac, (TPM2B_KEY *)&hmackey,
- p->size - integrity_skip, sensitive,
- name.size, name.name,
- 0, NULL);
- digest.size = name_alg_size;
- memcpy(digest.buffer, &hmac.digest, digest.size);
- size = integrity_skip;
- buf = p->buffer;
- TSS_TPM2B_DIGEST_Marshal((TPM2B_DIGEST *)&digest, &written, &buf, &size);
- return TPM_RC_SUCCESS;
-
- openssl_err:
- ERR_print_errors_fp(stderr);
- return TPM_RC_ASYMMETRIC;
-}
-
EVP_PKEY *
openssl_read_key(char *filename)
{
diff --git a/tpm2-common.c b/tpm2-common.c
index cc57595..7a31da4 100644
--- a/tpm2-common.c
+++ b/tpm2-common.c
@@ -2795,6 +2795,141 @@ TPM_RC openssl_to_tpm_public(TPM2B_PUBLIC *pub, EVP_PKEY *pkey)
return TPM_RC_ASYMMETRIC;
}
+TPM_RC tpm2_outerwrap(EVP_PKEY *parent,
+ TPMT_SENSITIVE *s,
+ TPMT_PUBLIC *pub,
+ PRIVATE_2B *p,
+ ENCRYPTED_SECRET_2B *enc_secret)
+{
+ PRIVATE_2B 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->buffer;
+ BYTE *sensitive = p->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 */
+ KEY_2B hmackey;
+ TPMT_HA hmac;
+ NAME_2B name;
+ DIGEST_2B 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->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->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.buffer);
+ if (EVP_PKEY_derive(ctx, secret.buffer, &ssize) != 1)
+ goto openssl_err;
+ secret.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.buffer, pub->nameAlg, (TPM2B *)&secret, "DUPLICATE",
+ (TPM2B *)&ephemeral_pt.point.x, (TPM2B *)&pub_pt.point.x,
+ SHA256_DIGEST_LENGTH*8);
+ seed.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, (TPM2B *)&seed, "STORAGE",
+ (TPM2B *)&name, &null_2b, T2_AES_KEY_BITS);
+ /* and then the outer HMAC key */
+ hmackey.size = name_alg_size;
+ TSS_KDFA(hmackey.buffer, pub->nameAlg, (TPM2B *)&seed, "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->secret;
+ TSS_TPM2B_ECC_POINT_Marshal(&ephemeral_pt, &written,
+ &buf, &size);
+ enc_secret->size = written;
+ memset(null_iv, 0, sizeof(null_iv));
+ TSS_AES_EncryptCFB(sensitive, T2_AES_KEY_BITS, aeskey, null_iv,
+ p->size - integrity_skip, sensitive);
+ hmac.hashAlg = pub->nameAlg;
+ TSS_HMAC_Generate(&hmac, (TPM2B_KEY *)&hmackey,
+ p->size - integrity_skip, sensitive,
+ name.size, name.name,
+ 0, NULL);
+ digest.size = name_alg_size;
+ memcpy(digest.buffer, &hmac.digest, digest.size);
+ size = integrity_skip;
+ buf = p->buffer;
+ TSS_TPM2B_DIGEST_Marshal((TPM2B_DIGEST *)&digest, &written, &buf, &size);
+ return TPM_RC_SUCCESS;
+
+ openssl_err:
+ ERR_print_errors_fp(stderr);
+ return TPM_RC_ASYMMETRIC;
+}
+
void
openssl_print_errors()
{
diff --git a/tpm2-common.h b/tpm2-common.h
index 5abb8fc..526591c 100644
--- a/tpm2-common.h
+++ b/tpm2-common.h
@@ -115,4 +115,9 @@ 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);
+TPM_RC tpm2_outerwrap(EVP_PKEY *parent,
+ TPMT_SENSITIVE *s,
+ TPMT_PUBLIC *pub,
+ PRIVATE_2B *p,
+ ENCRYPTED_SECRET_2B *enc_secret);
#endif