diff options
author | James Bottomley <James.Bottomley@HansenPartnership.com> | 2023-01-11 11:20:22 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2023-01-12 16:41:35 -0500 |
commit | 23fbe121a6023af315a01db313f05c29d86e2e38 (patch) | |
tree | dbc3c8f4f5112fa772ada9c5b983cf058e49593f | |
parent | b0f6f1bede44467f1bff3a52a7e7adee18f011ec (diff) | |
download | openssl_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.c | 135 | ||||
-rw-r--r-- | tpm2-common.c | 135 | ||||
-rw-r--r-- | tpm2-common.h | 5 |
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 |