af88e806f0
This change adds the backported tpm2_pcrreset and tpm2_checkquote tools and also the support to allow tpm2_makecredential tool to run off-TPM. Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
1306 lines
44 KiB
Diff
1306 lines
44 KiB
Diff
From d74b094191f2e09b29cfad4f03322e0cd64497ab Mon Sep 17 00:00:00 2001
|
|
From: jetwhiz <charles.munson@ll.mit.edu>
|
|
Date: Tue, 5 Feb 2019 17:24:44 -0500
|
|
Subject: [PATCH] Add ability to run tpm2_makecredential without a TPM
|
|
|
|
Used some functions from tpm2_import for off-TPM functionality
|
|
- Move needed, overlap code into tpm2_identity_util
|
|
Add new global -X/--openssl-backend option for any tools that can operate w/o TPM
|
|
|
|
Signed-off-by: jetwhiz <Charles.Munson@ll.mit.edu>
|
|
---
|
|
Makefile.am | 6 +-
|
|
lib/tpm2_identity_util.c | 480 ++++++++++++++++++++++++
|
|
lib/tpm2_identity_util.h | 141 +++++++
|
|
lib/tpm2_openssl.c | 162 ++++++++
|
|
lib/tpm2_openssl.h | 108 ++++++
|
|
lib/tpm2_options.c | 36 +-
|
|
lib/tpm2_options.h | 1 +
|
|
man/common/tcti.md | 4 +
|
|
man/tpm2_activatecredential.1.md | 2 +-
|
|
man/tpm2_certify.1.md | 2 +-
|
|
man/tpm2_create.1.md | 2 +-
|
|
man/tpm2_encryptdecrypt.1.md | 2 +-
|
|
man/tpm2_getpubak.1.md | 2 +-
|
|
man/tpm2_makecredential.1.md | 3 +-
|
|
test/system/test_tpm2_makecredential.sh | 2 +
|
|
tools/tpm2_makecredential.c | 103 ++++-
|
|
16 files changed, 1033 insertions(+), 23 deletions(-)
|
|
create mode 100644 lib/tpm2_identity_util.c
|
|
create mode 100644 lib/tpm2_identity_util.h
|
|
create mode 100644 lib/tpm2_openssl.c
|
|
create mode 100644 lib/tpm2_openssl.h
|
|
|
|
diff --git a/Makefile.am b/Makefile.am
|
|
index ffe22f383e3..2195537ce01 100644
|
|
--- a/Makefile.am
|
|
+++ b/Makefile.am
|
|
@@ -119,7 +119,11 @@ lib_libcommon_a_SOURCES = \
|
|
lib/tpm2_errata.c \
|
|
lib/tpm2_errata.h \
|
|
lib/tpm2_header.h \
|
|
+ lib/tpm2_identity_util.c \
|
|
+ lib/tpm2_identity_util.h \
|
|
lib/tpm2_nv_util.h \
|
|
+ lib/tpm2_openssl.c \
|
|
+ lib/tpm2_openssl.h \
|
|
lib/tpm2_password_util.c \
|
|
lib/tpm2_password_util.h \
|
|
lib/tpm2_policy.c \
|
|
@@ -347,4 +351,4 @@ man/man1/%.1 : man/%.1.md $(MARKDOWN_COMMON_DEPS)
|
|
-e '/\[object attribute specifiers\]/d' \
|
|
< $< | pandoc -s -t man > $@
|
|
|
|
-CLEANFILES = $(man1_MANS)
|
|
+CLEANFILES = $(man1_MANS)
|
|
\ No newline at end of file
|
|
diff --git a/lib/tpm2_identity_util.c b/lib/tpm2_identity_util.c
|
|
new file mode 100644
|
|
index 00000000000..70bf03647eb
|
|
--- /dev/null
|
|
+++ b/lib/tpm2_identity_util.c
|
|
@@ -0,0 +1,480 @@
|
|
+//**********************************************************************;
|
|
+// Copyright (c) 2017, Intel Corporation
|
|
+// Copyright (c) 2019 Massachusetts Institute of Technology
|
|
+// All rights reserved.
|
|
+//
|
|
+// Redistribution and use in source and binary forms, with or without
|
|
+// modification, are permitted provided that the following conditions are met:
|
|
+//
|
|
+// 1. Redistributions of source code must retain the above copyright notice,
|
|
+// this list of conditions and the following disclaimer.
|
|
+//
|
|
+// 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
+// this list of conditions and the following disclaimer in the documentation
|
|
+// and/or other materials provided with the distribution.
|
|
+//
|
|
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
+// THE POSSIBILITY OF SUCH DAMAGE.
|
|
+//**********************************************************************
|
|
+
|
|
+#include <errno.h>
|
|
+#include <stdint.h>
|
|
+#include <string.h>
|
|
+
|
|
+#include <openssl/aes.h>
|
|
+#include <openssl/bn.h>
|
|
+#include <openssl/evp.h>
|
|
+#include <openssl/err.h>
|
|
+#include <openssl/hmac.h>
|
|
+#include <openssl/obj_mac.h>
|
|
+#include <openssl/pem.h>
|
|
+#include <openssl/rand.h>
|
|
+#include <openssl/rsa.h>
|
|
+
|
|
+#include <tss2/tss2_mu.h>
|
|
+#include <tss2/tss2_sys.h>
|
|
+
|
|
+#include "files.h"
|
|
+#include "log.h"
|
|
+#include "tpm2_alg_util.h"
|
|
+#include "tpm_kdfa.h"
|
|
+#include "tpm2_openssl.h"
|
|
+#include "tpm2_identity_util.h"
|
|
+#include "tpm2_util.h"
|
|
+
|
|
+
|
|
+// Identity-related functionality that the TPM normally does, but using OpenSSL
|
|
+
|
|
+#if defined(LIBRESSL_VERSION_NUMBER)
|
|
+static int RSA_padding_add_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
|
|
+ const unsigned char *from, int flen, const unsigned char *param, int plen,
|
|
+ const EVP_MD *md, const EVP_MD *mgf1md) {
|
|
+
|
|
+ int ret = 0;
|
|
+ int i, emlen = tlen - 1;
|
|
+ unsigned char *db, *seed;
|
|
+ unsigned char *dbmask, seedmask[EVP_MAX_MD_SIZE];
|
|
+ int mdlen;
|
|
+
|
|
+ if (md == NULL)
|
|
+ md = EVP_sha1();
|
|
+ if (mgf1md == NULL)
|
|
+ mgf1md = md;
|
|
+
|
|
+ mdlen = EVP_MD_size(md);
|
|
+
|
|
+ if (flen > emlen - 2 * mdlen - 1) {
|
|
+ RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP,
|
|
+ RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if (emlen < 2 * mdlen + 1) {
|
|
+ RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP,
|
|
+ RSA_R_KEY_SIZE_TOO_SMALL);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ to[0] = 0;
|
|
+ seed = to + 1;
|
|
+ db = to + mdlen + 1;
|
|
+
|
|
+ if (!EVP_Digest((void *)param, plen, db, NULL, md, NULL))
|
|
+ return 0;
|
|
+ memset(db + mdlen, 0, emlen - flen - 2 * mdlen - 1);
|
|
+ db[emlen - flen - mdlen - 1] = 0x01;
|
|
+ memcpy(db + emlen - flen - mdlen, from, (unsigned int)flen);
|
|
+ if (RAND_bytes(seed, mdlen) <= 0)
|
|
+ return 0;
|
|
+
|
|
+ dbmask = OPENSSL_malloc(emlen - mdlen);
|
|
+ if (dbmask == NULL) {
|
|
+ RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, ERR_R_MALLOC_FAILURE);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if (PKCS1_MGF1(dbmask, emlen - mdlen, seed, mdlen, mgf1md) < 0)
|
|
+ goto err;
|
|
+ for (i = 0; i < emlen - mdlen; i++)
|
|
+ db[i] ^= dbmask[i];
|
|
+
|
|
+ if (PKCS1_MGF1(seedmask, mdlen, db, emlen - mdlen, mgf1md) < 0)
|
|
+ goto err;
|
|
+ for (i = 0; i < mdlen; i++)
|
|
+ seed[i] ^= seedmask[i];
|
|
+
|
|
+ ret = 1;
|
|
+
|
|
+ err:
|
|
+ OPENSSL_free(dbmask);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+#endif
|
|
+
|
|
+static TPM2_KEY_BITS get_pub_asym_key_bits(TPM2B_PUBLIC *public) {
|
|
+
|
|
+ TPMU_PUBLIC_PARMS *p = &public->publicArea.parameters;
|
|
+ switch(public->publicArea.type) {
|
|
+ case TPM2_ALG_ECC:
|
|
+ /* fall-thru */
|
|
+ case TPM2_ALG_RSA:
|
|
+ return p->asymDetail.symmetric.keyBits.sym;
|
|
+ /* no default */
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static bool encrypt_seed_with_tpm2_rsa_public_key(TPM2B_DIGEST *protection_seed,
|
|
+ TPM2B_PUBLIC *parent_pub, unsigned char *label, int labelLen,
|
|
+ TPM2B_ENCRYPTED_SECRET *encrypted_protection_seed) {
|
|
+ bool rval = false;
|
|
+ RSA *rsa = NULL;
|
|
+
|
|
+ // Public modulus (RSA-only!)
|
|
+ TPMI_RSA_KEY_BITS mod_size_bits = parent_pub->publicArea.parameters.rsaDetail.keyBits;
|
|
+ UINT16 mod_size = mod_size_bits / 8;
|
|
+ TPM2B *pub_key_val = (TPM2B *)&parent_pub->publicArea.unique.rsa;
|
|
+ unsigned char *pub_modulus = malloc(mod_size);
|
|
+ if (pub_modulus == NULL) {
|
|
+ LOG_ERR("Failed to allocate memory to store public key's modulus.");
|
|
+ return false;
|
|
+ }
|
|
+ memcpy(pub_modulus, pub_key_val->buffer, mod_size);
|
|
+
|
|
+ TPMI_ALG_HASH parent_name_alg = parent_pub->publicArea.nameAlg;
|
|
+
|
|
+ /*
|
|
+ * This is the biggest buffer value, so it should always be sufficient.
|
|
+ */
|
|
+ unsigned char encoded[TPM2_MAX_DIGEST_BUFFER];
|
|
+ int return_code = RSA_padding_add_PKCS1_OAEP_mgf1(encoded,
|
|
+ mod_size, protection_seed->buffer, protection_seed->size, label, labelLen,
|
|
+ tpm2_openssl_halg_from_tpmhalg(parent_name_alg), NULL);
|
|
+ if (return_code != 1) {
|
|
+ LOG_ERR("Failed RSA_padding_add_PKCS1_OAEP_mgf1\n");
|
|
+ goto error;
|
|
+ }
|
|
+ BIGNUM* bne = BN_new();
|
|
+ if (!bne) {
|
|
+ LOG_ERR("BN_new for bne failed\n");
|
|
+ goto error;
|
|
+ }
|
|
+ return_code = BN_set_word(bne, RSA_F4);
|
|
+ if (return_code != 1) {
|
|
+ LOG_ERR("BN_set_word failed\n");
|
|
+ BN_free(bne);
|
|
+ goto error;
|
|
+ }
|
|
+ rsa = RSA_new();
|
|
+ if (!rsa) {
|
|
+ LOG_ERR("RSA_new failed\n");
|
|
+ BN_free(bne);
|
|
+ goto error;
|
|
+ }
|
|
+ return_code = RSA_generate_key_ex(rsa, mod_size_bits, bne, NULL);
|
|
+ BN_free(bne);
|
|
+ if (return_code != 1) {
|
|
+ LOG_ERR("RSA_generate_key_ex failed\n");
|
|
+ goto error;
|
|
+ }
|
|
+ BIGNUM *n = BN_bin2bn(pub_modulus, mod_size, NULL);
|
|
+ if (n == NULL) {
|
|
+ LOG_ERR("BN_bin2bn failed\n");
|
|
+ goto error;
|
|
+ }
|
|
+ if (!RSA_set0_key(rsa, n, NULL, NULL)) {
|
|
+ LOG_ERR("RSA_set0_key failed\n");
|
|
+ BN_free(n);
|
|
+ goto error;
|
|
+ }
|
|
+ // Encrypting
|
|
+ encrypted_protection_seed->size = mod_size;
|
|
+ return_code = RSA_public_encrypt(mod_size, encoded,
|
|
+ encrypted_protection_seed->secret, rsa, RSA_NO_PADDING);
|
|
+ if (return_code < 0) {
|
|
+ LOG_ERR("Failed RSA_public_encrypt\n");
|
|
+ goto error;
|
|
+ }
|
|
+
|
|
+ rval = true;
|
|
+
|
|
+error:
|
|
+ free(pub_modulus);
|
|
+ RSA_free(rsa);
|
|
+ return rval;
|
|
+}
|
|
+
|
|
+bool tpm2_identity_util_calc_outer_integrity_hmac_key_and_dupsensitive_enc_key(
|
|
+ TPM2B_PUBLIC *parent_pub,
|
|
+ TPM2B_NAME *pubname,
|
|
+ TPM2B_DIGEST *protection_seed,
|
|
+ TPM2B_MAX_BUFFER *protection_hmac_key,
|
|
+ TPM2B_MAX_BUFFER *protection_enc_key) {
|
|
+
|
|
+ TPM2B null_2b = { .size = 0 };
|
|
+
|
|
+ TPMI_ALG_HASH parent_alg = parent_pub->publicArea.nameAlg;
|
|
+ UINT16 parent_hash_size = tpm2_alg_util_get_hash_size(parent_alg);
|
|
+
|
|
+ TSS2_RC rval = tpm_kdfa(parent_alg, (TPM2B *)protection_seed, "INTEGRITY",
|
|
+ &null_2b, &null_2b, parent_hash_size * 8, protection_hmac_key);
|
|
+ if (rval != TPM2_RC_SUCCESS) {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ TPM2_KEY_BITS pub_key_bits = get_pub_asym_key_bits(parent_pub);
|
|
+
|
|
+ rval = tpm_kdfa(parent_alg, (TPM2B *)protection_seed, "STORAGE",
|
|
+ (TPM2B *)pubname, &null_2b, pub_key_bits,
|
|
+ protection_enc_key);
|
|
+ if (rval != TPM2_RC_SUCCESS) {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+
|
|
+bool tpm2_identity_util_encrypt_seed_with_public_key(TPM2B_DIGEST *protection_seed,
|
|
+ TPM2B_PUBLIC *parent_pub, unsigned char *label, int labelLen,
|
|
+ TPM2B_ENCRYPTED_SECRET *encrypted_protection_seed) {
|
|
+ bool result = false;
|
|
+ TPMI_ALG_PUBLIC alg = parent_pub->publicArea.type;
|
|
+
|
|
+ switch (alg) {
|
|
+ case TPM2_ALG_RSA:
|
|
+ result = encrypt_seed_with_tpm2_rsa_public_key(protection_seed,
|
|
+ parent_pub, label, labelLen, encrypted_protection_seed);
|
|
+ break;
|
|
+ case TPM2_ALG_ECC:
|
|
+ LOG_ERR("Algorithm '%s' not supported yet", tpm2_alg_util_algtostr(alg));
|
|
+ result = false;
|
|
+ break;
|
|
+ default:
|
|
+ LOG_ERR("Cannot handle algorithm, got: %s", tpm2_alg_util_algtostr(alg));
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+static const EVP_CIPHER *tpm_alg_to_ossl(TPMT_SYM_DEF_OBJECT *sym) {
|
|
+
|
|
+ switch(sym->algorithm) {
|
|
+ case TPM2_ALG_AES: {
|
|
+ switch (sym->keyBits.aes) {
|
|
+ case 128:
|
|
+ return EVP_aes_128_cfb();
|
|
+ case 256:
|
|
+ return EVP_aes_256_cfb();
|
|
+ /* no default */
|
|
+ }
|
|
+ }
|
|
+ /* no default */
|
|
+ }
|
|
+
|
|
+ LOG_ERR("Unsupported parent key symmetric parameters");
|
|
+
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+static bool aes_encrypt_buffers(TPMT_SYM_DEF_OBJECT *sym, uint8_t *encryption_key,
|
|
+ uint8_t *buf1, size_t buf1_len,
|
|
+ uint8_t *buf2, size_t buf2_len,
|
|
+ TPM2B_MAX_BUFFER *cipher_text) {
|
|
+
|
|
+ bool result = false;
|
|
+
|
|
+ unsigned offset = 0;
|
|
+ size_t total_len = buf1_len + buf2_len;
|
|
+
|
|
+ if (total_len > sizeof(cipher_text->buffer)) {
|
|
+ LOG_ERR("Plaintext too big, got %zu, expected less then %zu",
|
|
+ total_len, sizeof(cipher_text->buffer));
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ const EVP_CIPHER *cipher = tpm_alg_to_ossl(sym);
|
|
+ if (!cipher) {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ const unsigned char iv[512] = { 0 };
|
|
+
|
|
+ if (((unsigned long)EVP_CIPHER_iv_length(cipher)) > sizeof(iv)) {
|
|
+ LOG_ERR("IV size is bigger then IV buffer size");
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ EVP_CIPHER_CTX *ctx = tpm2_openssl_cipher_new();
|
|
+
|
|
+ int rc = EVP_EncryptInit_ex(ctx, cipher, NULL, encryption_key, iv);
|
|
+ if (!rc) {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ EVP_CIPHER_CTX_set_padding(ctx, 0);
|
|
+
|
|
+ uint8_t *bufs[2] = {
|
|
+ buf1,
|
|
+ buf2
|
|
+ };
|
|
+
|
|
+ size_t lens[ARRAY_LEN(bufs)] = {
|
|
+ buf1_len,
|
|
+ buf2_len
|
|
+ };
|
|
+
|
|
+ unsigned i;
|
|
+ for (i=0; i < ARRAY_LEN(bufs); i++) {
|
|
+
|
|
+ uint8_t *b = bufs[i];
|
|
+ size_t l = lens[i];
|
|
+
|
|
+ if (!b) {
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ int output_len = total_len - offset;
|
|
+
|
|
+ rc = EVP_EncryptUpdate(ctx, &cipher_text->buffer[offset], &output_len, b, l);
|
|
+ if (!rc) {
|
|
+ LOG_ERR("Encrypt failed");
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ offset += l;
|
|
+ }
|
|
+
|
|
+ int tmp_len = 0;
|
|
+ rc = EVP_EncryptFinal_ex(ctx, NULL, &tmp_len);
|
|
+ if (!rc) {
|
|
+ LOG_ERR("Encrypt failed");
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ cipher_text->size = total_len;
|
|
+
|
|
+ result = true;
|
|
+
|
|
+out:
|
|
+ tpm2_openssl_cipher_free(ctx);
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+static void hmac_outer_integrity(
|
|
+ TPMI_ALG_HASH parent_name_alg,
|
|
+ uint8_t *buffer1, uint16_t buffer1_size,
|
|
+ uint8_t *buffer2, uint16_t buffer2_size, uint8_t *hmac_key,
|
|
+ TPM2B_DIGEST *outer_integrity_hmac) {
|
|
+
|
|
+ uint8_t to_hmac_buffer[TPM2_MAX_DIGEST_BUFFER];
|
|
+ memcpy(to_hmac_buffer, buffer1, buffer1_size);
|
|
+ memcpy(to_hmac_buffer + buffer1_size, buffer2, buffer2_size);
|
|
+ uint32_t size = 0;
|
|
+
|
|
+ UINT16 hash_size = tpm2_alg_util_get_hash_size(parent_name_alg);
|
|
+
|
|
+ HMAC(tpm2_openssl_halg_from_tpmhalg(parent_name_alg), hmac_key, hash_size, to_hmac_buffer,
|
|
+ buffer1_size + buffer2_size, outer_integrity_hmac->buffer, &size);
|
|
+ outer_integrity_hmac->size = size;
|
|
+}
|
|
+
|
|
+bool tpm2_identity_util_calculate_inner_integrity(
|
|
+ TPMI_ALG_HASH name_alg,
|
|
+ TPM2B_SENSITIVE *sensitive,
|
|
+ TPM2B_NAME *pubname,
|
|
+ TPM2B_DATA *enc_sensitive_key,
|
|
+ TPMT_SYM_DEF_OBJECT *sym_alg,
|
|
+ TPM2B_MAX_BUFFER *encrypted_inner_integrity) {
|
|
+
|
|
+ //Marshal sensitive area
|
|
+ uint8_t buffer_marshalled_sensitiveArea[TPM2_MAX_DIGEST_BUFFER] = { 0 };
|
|
+ size_t marshalled_sensitive_size = 0;
|
|
+ Tss2_MU_TPMT_SENSITIVE_Marshal(&sensitive->sensitiveArea,
|
|
+ buffer_marshalled_sensitiveArea + sizeof(uint16_t), TPM2_MAX_DIGEST_BUFFER,
|
|
+ &marshalled_sensitive_size);
|
|
+ size_t marshalled_sensitive_size_info = 0;
|
|
+ Tss2_MU_UINT16_Marshal(marshalled_sensitive_size, buffer_marshalled_sensitiveArea,
|
|
+ sizeof(uint16_t), &marshalled_sensitive_size_info);
|
|
+
|
|
+ //concatenate NAME
|
|
+ memcpy(
|
|
+ buffer_marshalled_sensitiveArea + marshalled_sensitive_size
|
|
+ + marshalled_sensitive_size_info,
|
|
+ pubname->name,
|
|
+ pubname->size);
|
|
+
|
|
+ //Digest marshalled-sensitive || name
|
|
+ uint8_t *marshalled_sensitive_and_name_digest =
|
|
+ buffer_marshalled_sensitiveArea + marshalled_sensitive_size
|
|
+ + marshalled_sensitive_size_info
|
|
+ + pubname->size;
|
|
+ size_t digest_size_info = 0;
|
|
+ UINT16 hash_size = tpm2_alg_util_get_hash_size(name_alg);
|
|
+ Tss2_MU_UINT16_Marshal(hash_size, marshalled_sensitive_and_name_digest,
|
|
+ sizeof(uint16_t), &digest_size_info);
|
|
+
|
|
+ digester d = tpm2_openssl_halg_to_digester(name_alg);
|
|
+ d(buffer_marshalled_sensitiveArea,
|
|
+ marshalled_sensitive_size_info + marshalled_sensitive_size
|
|
+ + pubname->size,
|
|
+ marshalled_sensitive_and_name_digest + digest_size_info);
|
|
+
|
|
+ //Inner integrity
|
|
+ encrypted_inner_integrity->size = marshalled_sensitive_size_info
|
|
+ + marshalled_sensitive_size + pubname->size;
|
|
+
|
|
+ return aes_encrypt_buffers(
|
|
+ sym_alg,
|
|
+ enc_sensitive_key->buffer,
|
|
+ marshalled_sensitive_and_name_digest,
|
|
+ hash_size + digest_size_info,
|
|
+ buffer_marshalled_sensitiveArea,
|
|
+ marshalled_sensitive_size_info + marshalled_sensitive_size,
|
|
+ encrypted_inner_integrity);
|
|
+}
|
|
+
|
|
+void tpm2_identity_util_calculate_outer_integrity(
|
|
+ TPMI_ALG_HASH parent_name_alg,
|
|
+ TPM2B_NAME *pubname,
|
|
+ TPM2B_MAX_BUFFER *marshalled_sensitive,
|
|
+ TPM2B_MAX_BUFFER *protection_hmac_key,
|
|
+ TPM2B_MAX_BUFFER *protection_enc_key,
|
|
+ TPMT_SYM_DEF_OBJECT *sym_alg,
|
|
+ TPM2B_MAX_BUFFER *encrypted_duplicate_sensitive,
|
|
+ TPM2B_DIGEST *outer_hmac) {
|
|
+
|
|
+ //Calculate dupSensitive
|
|
+ encrypted_duplicate_sensitive->size =
|
|
+ marshalled_sensitive->size;
|
|
+
|
|
+ aes_encrypt_buffers(
|
|
+ sym_alg,
|
|
+ protection_enc_key->buffer,
|
|
+ marshalled_sensitive->buffer,
|
|
+ marshalled_sensitive->size,
|
|
+ NULL, 0,
|
|
+ encrypted_duplicate_sensitive);
|
|
+ //Calculate outerHMAC
|
|
+ hmac_outer_integrity(
|
|
+ parent_name_alg,
|
|
+ encrypted_duplicate_sensitive->buffer,
|
|
+ encrypted_duplicate_sensitive->size,
|
|
+ pubname->name,
|
|
+ pubname->size,
|
|
+ protection_hmac_key->buffer,
|
|
+ outer_hmac);
|
|
+}
|
|
diff --git a/lib/tpm2_identity_util.h b/lib/tpm2_identity_util.h
|
|
new file mode 100644
|
|
index 00000000000..49f231a3347
|
|
--- /dev/null
|
|
+++ b/lib/tpm2_identity_util.h
|
|
@@ -0,0 +1,141 @@
|
|
+//**********************************************************************;
|
|
+// Copyright (c) 2017, Intel Corporation
|
|
+// Copyright (c) 2019 Massachusetts Institute of Technology
|
|
+// All rights reserved.
|
|
+//
|
|
+// Redistribution and use in source and binary forms, with or without
|
|
+// modification, are permitted provided that the following conditions are met:
|
|
+//
|
|
+// 1. Redistributions of source code must retain the above copyright notice,
|
|
+// this list of conditions and the following disclaimer.
|
|
+//
|
|
+// 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
+// this list of conditions and the following disclaimer in the documentation
|
|
+// and/or other materials provided with the distribution.
|
|
+//
|
|
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
+// THE POSSIBILITY OF SUCH DAMAGE.
|
|
+//**********************************************************************
|
|
+
|
|
+#ifndef LIB_TPM2_IDENTITY_UTIL_H_
|
|
+#define LIB_TPM2_IDENTITY_UTIL_H_
|
|
+
|
|
+#include <tss2/tss2_sys.h>
|
|
+
|
|
+#include <openssl/err.h>
|
|
+#include <openssl/hmac.h>
|
|
+#include <openssl/rsa.h>
|
|
+
|
|
+
|
|
+/**
|
|
+ * Generates HMAC integrity and symmetric encryption keys for TPM2 identies.
|
|
+ *
|
|
+ * @param parent_pub
|
|
+ * The public key used for seed generation and protection.
|
|
+ * @param pubname
|
|
+ * The Name object associated with the parent_pub credential.
|
|
+ * @param protection_seed
|
|
+ * The symmetric seed value used to generate protection keys.
|
|
+ * @param protection_hmac_key
|
|
+ * The HMAC integrity key to populate.
|
|
+ * @param protection_enc_key
|
|
+ * The symmetric encryption key to populate.
|
|
+ * @return
|
|
+ * True on success, false on failure.
|
|
+ */
|
|
+bool tpm2_identity_util_calc_outer_integrity_hmac_key_and_dupsensitive_enc_key(
|
|
+ TPM2B_PUBLIC *parent_pub,
|
|
+ TPM2B_NAME *pubname,
|
|
+ TPM2B_DIGEST *protection_seed,
|
|
+ TPM2B_MAX_BUFFER *protection_hmac_key,
|
|
+ TPM2B_MAX_BUFFER *protection_enc_key);
|
|
+
|
|
+/**
|
|
+ * Encrypts seed with parent public key for TPM2 credential protection process.
|
|
+ *
|
|
+ * @param protection_seed
|
|
+ * The identity structure protection seed that is to be encrypted.
|
|
+ * @param parent_pub
|
|
+ * The public key used for encryption.
|
|
+ * @param label
|
|
+ * Indicates label for the seed, such as "IDENTITY" or "DUPLICATE".
|
|
+ * @param labelLen
|
|
+ * Length of label.
|
|
+ * @param encrypted_protection_seed
|
|
+ * The encrypted protection seed to populate.
|
|
+ * @return
|
|
+ * True on success, false on failure.
|
|
+ */
|
|
+bool tpm2_identity_util_encrypt_seed_with_public_key(
|
|
+ TPM2B_DIGEST *protection_seed,
|
|
+ TPM2B_PUBLIC *parent_pub,
|
|
+ unsigned char *label,
|
|
+ int labelLen,
|
|
+ TPM2B_ENCRYPTED_SECRET *encrypted_protection_seed);
|
|
+
|
|
+/**
|
|
+ * Marshalls Credential Value and encrypts it with the symmetric encryption key.
|
|
+ *
|
|
+ * @param name_alg
|
|
+ * Hash algorithm used to compute Name of the public key.
|
|
+ * @param sensitive
|
|
+ * The Credential Value to be marshalled and encrypted with symmetric key.
|
|
+ * @param pubname
|
|
+ * The Name object corresponding to the public key.
|
|
+ * @param enc_sensitive_key
|
|
+ * The symmetric encryption key.
|
|
+ * @param sym_alg
|
|
+ * The algorithm used for the symmetric encryption key.
|
|
+ * @param encrypted_inner_integrity
|
|
+ * The encrypted, marshalled Credential Value to populate.
|
|
+ * @return
|
|
+ * True on success, false on failure.
|
|
+ */
|
|
+bool tpm2_identity_util_calculate_inner_integrity(
|
|
+ TPMI_ALG_HASH name_alg,
|
|
+ TPM2B_SENSITIVE *sensitive,
|
|
+ TPM2B_NAME *pubname,
|
|
+ TPM2B_DATA *enc_sensitive_key,
|
|
+ TPMT_SYM_DEF_OBJECT *sym_alg,
|
|
+ TPM2B_MAX_BUFFER *encrypted_inner_integrity);
|
|
+
|
|
+/**
|
|
+ * Encrypts Credential Value with enc key and calculates HMAC with hmac key.
|
|
+ *
|
|
+ * @param parent_name_alg
|
|
+ * Hash algorithm used to compute Name of the public key.
|
|
+ * @param pubname
|
|
+ * The Name object corresponding to the public key.
|
|
+ * @param marshalled_sensitive
|
|
+ * Marshalled Credential Value to be encrypted with symmetric encryption key.
|
|
+ * @param protection_hmac_key
|
|
+ * The HMAC integrity key.
|
|
+ * @param protection_enc_key
|
|
+ * The symmetric encryption key.
|
|
+ * @param sym_alg
|
|
+ * The algorithm used for the symmetric encryption key.
|
|
+ * @param encrypted_duplicate_sensitive
|
|
+ * The encrypted Credential Value to populate.
|
|
+ * @param outer_hmac
|
|
+ * The outer HMAC structure to populate.
|
|
+ */
|
|
+void tpm2_identity_util_calculate_outer_integrity(
|
|
+ TPMI_ALG_HASH parent_name_alg,
|
|
+ TPM2B_NAME *pubname,
|
|
+ TPM2B_MAX_BUFFER *marshalled_sensitive,
|
|
+ TPM2B_MAX_BUFFER *protection_hmac_key,
|
|
+ TPM2B_MAX_BUFFER *protection_enc_key,
|
|
+ TPMT_SYM_DEF_OBJECT *sym_alg,
|
|
+ TPM2B_MAX_BUFFER *encrypted_duplicate_sensitive,
|
|
+ TPM2B_DIGEST *outer_hmac);
|
|
+
|
|
+#endif /* LIB_TPM2_IDENTITY_UTIL_H_ */
|
|
diff --git a/lib/tpm2_openssl.c b/lib/tpm2_openssl.c
|
|
new file mode 100644
|
|
index 00000000000..0bfc95bd1ef
|
|
--- /dev/null
|
|
+++ b/lib/tpm2_openssl.c
|
|
@@ -0,0 +1,162 @@
|
|
+//**********************************************************************;
|
|
+// Copyright (c) 2017, Intel Corporation
|
|
+// All rights reserved.
|
|
+//
|
|
+// Redistribution and use in source and binary forms, with or without
|
|
+// modification, are permitted provided that the following conditions are met:
|
|
+//
|
|
+// 1. Redistributions of source code must retain the above copyright notice,
|
|
+// this list of conditions and the following disclaimer.
|
|
+//
|
|
+// 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
+// this list of conditions and the following disclaimer in the documentation
|
|
+// and/or other materials provided with the distribution.
|
|
+//
|
|
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
+// THE POSSIBILITY OF SUCH DAMAGE.
|
|
+//**********************************************************************
|
|
+
|
|
+#include <errno.h>
|
|
+#include <stdint.h>
|
|
+#include <string.h>
|
|
+
|
|
+#include <openssl/aes.h>
|
|
+#include <openssl/bn.h>
|
|
+#include <openssl/evp.h>
|
|
+#include <openssl/err.h>
|
|
+#include <openssl/hmac.h>
|
|
+#include <openssl/obj_mac.h>
|
|
+#include <openssl/pem.h>
|
|
+#include <openssl/rand.h>
|
|
+#include <openssl/rsa.h>
|
|
+
|
|
+#include <tss2/tss2_sys.h>
|
|
+
|
|
+#include "files.h"
|
|
+#include "log.h"
|
|
+#include "tpm2_alg_util.h"
|
|
+#include "tpm2_openssl.h"
|
|
+#include "tpm2_util.h"
|
|
+
|
|
+
|
|
+const EVP_MD *tpm2_openssl_halg_from_tpmhalg(TPMI_ALG_HASH algorithm) {
|
|
+
|
|
+ switch (algorithm) {
|
|
+ case TPM2_ALG_SHA1:
|
|
+ return EVP_sha1();
|
|
+ case TPM2_ALG_SHA256:
|
|
+ return EVP_sha256();
|
|
+ case TPM2_ALG_SHA384:
|
|
+ return EVP_sha384();
|
|
+ case TPM2_ALG_SHA512:
|
|
+ return EVP_sha512();
|
|
+ default:
|
|
+ return NULL;
|
|
+ }
|
|
+ /* no return, not possible */
|
|
+}
|
|
+
|
|
+#if defined(LIB_TPM2_OPENSSL_OPENSSL_PRE11)
|
|
+int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) {
|
|
+
|
|
+ if ((r->n == NULL && n == NULL) || (r->e == NULL && e == NULL)) {
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if (n != NULL) {
|
|
+ BN_free(r->n);
|
|
+ r->n = n;
|
|
+ }
|
|
+
|
|
+ if (e != NULL) {
|
|
+ BN_free(r->e);
|
|
+ r->e = e;
|
|
+ }
|
|
+
|
|
+ if (d != NULL) {
|
|
+ BN_free(r->d);
|
|
+ r->d = d;
|
|
+ }
|
|
+
|
|
+ return 1;
|
|
+}
|
|
+#endif
|
|
+
|
|
+static inline const char *get_openssl_err(void) {
|
|
+ return ERR_error_string(ERR_get_error(), NULL);
|
|
+}
|
|
+
|
|
+
|
|
+EVP_CIPHER_CTX *tpm2_openssl_cipher_new(void) {
|
|
+ EVP_CIPHER_CTX *ctx;
|
|
+#if defined(LIB_TPM2_OPENSSL_OPENSSL_PRE11)
|
|
+ ctx = malloc(sizeof(*ctx));
|
|
+#else
|
|
+ ctx = EVP_CIPHER_CTX_new();
|
|
+#endif
|
|
+ if (!ctx)
|
|
+ return NULL;
|
|
+
|
|
+#if defined(LIB_TPM2_OPENSSL_OPENSSL_PRE11)
|
|
+ EVP_CIPHER_CTX_init(ctx);
|
|
+#endif
|
|
+
|
|
+ return ctx;
|
|
+}
|
|
+
|
|
+void tpm2_openssl_cipher_free(EVP_CIPHER_CTX *ctx) {
|
|
+#if defined(LIB_TPM2_OPENSSL_OPENSSL_PRE11)
|
|
+ EVP_CIPHER_CTX_cleanup(ctx);
|
|
+ free(ctx);
|
|
+#else
|
|
+ EVP_CIPHER_CTX_free(ctx);
|
|
+#endif
|
|
+}
|
|
+
|
|
+digester tpm2_openssl_halg_to_digester(TPMI_ALG_HASH halg) {
|
|
+
|
|
+ switch(halg) {
|
|
+ case TPM2_ALG_SHA1:
|
|
+ return SHA1;
|
|
+ case TPM2_ALG_SHA256:
|
|
+ return SHA256;
|
|
+ case TPM2_ALG_SHA384:
|
|
+ return SHA384;
|
|
+ case TPM2_ALG_SHA512:
|
|
+ return SHA512;
|
|
+ /* no default */
|
|
+ }
|
|
+
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Per man openssl(1), handle the following --passin formats:
|
|
+ * pass:password
|
|
+ * the actual password is password. Since the password is visible to utilities (like 'ps' under Unix) this form should only be used where security is not
|
|
+ * important.
|
|
+ *
|
|
+ * env:var obtain the password from the environment variable var. Since the environment of other processes is visible on certain platforms (e.g. ps under certain
|
|
+ * Unix OSes) this option should be used with caution.
|
|
+ *
|
|
+ * file:pathname
|
|
+ * the first line of pathname is the password. If the same pathname argument is supplied to -passin and -passout arguments then the first line will be used
|
|
+ * for the input password and the next line for the output password. pathname need not refer to a regular file: it could for example refer to a device or
|
|
+ * named pipe.
|
|
+ *
|
|
+ * fd:number read the password from the file descriptor number. This can be used to send the data via a pipe for example.
|
|
+ *
|
|
+ * stdin read the password from standard input.
|
|
+ *
|
|
+ */
|
|
+
|
|
+typedef bool (*pfn_ossl_pw_handler)(const char *passin, char **pass);
|
|
diff --git a/lib/tpm2_openssl.h b/lib/tpm2_openssl.h
|
|
new file mode 100644
|
|
index 00000000000..d749cb350ac
|
|
--- /dev/null
|
|
+++ b/lib/tpm2_openssl.h
|
|
@@ -0,0 +1,108 @@
|
|
+//**********************************************************************;
|
|
+// Copyright (c) 2017, Intel Corporation
|
|
+// All rights reserved.
|
|
+//
|
|
+// Redistribution and use in source and binary forms, with or without
|
|
+// modification, are permitted provided that the following conditions are met:
|
|
+//
|
|
+// 1. Redistributions of source code must retain the above copyright notice,
|
|
+// this list of conditions and the following disclaimer.
|
|
+//
|
|
+// 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
+// this list of conditions and the following disclaimer in the documentation
|
|
+// and/or other materials provided with the distribution.
|
|
+//
|
|
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
+// THE POSSIBILITY OF SUCH DAMAGE.
|
|
+//**********************************************************************
|
|
+
|
|
+#ifndef LIB_TPM2_OPENSSL_H_
|
|
+#define LIB_TPM2_OPENSSL_H_
|
|
+
|
|
+#include <tss2/tss2_sys.h>
|
|
+
|
|
+#include <openssl/err.h>
|
|
+#include <openssl/hmac.h>
|
|
+#include <openssl/rsa.h>
|
|
+
|
|
+#if (OPENSSL_VERSION_NUMBER < 0x1010000fL && !defined(LIBRESSL_VERSION_NUMBER)) || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L) /* OpenSSL 1.1.0 */
|
|
+#define LIB_TPM2_OPENSSL_OPENSSL_PRE11
|
|
+#endif
|
|
+
|
|
+
|
|
+#if defined(LIB_TPM2_OPENSSL_OPENSSL_PRE11)
|
|
+int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d);
|
|
+#endif
|
|
+
|
|
+
|
|
+/**
|
|
+ * Function prototype for a hashing routine.
|
|
+ *
|
|
+ * This is a wrapper around OSSL SHA256|384 and etc digesters.
|
|
+ *
|
|
+ * @param d
|
|
+ * The data to digest.
|
|
+ * @param n
|
|
+ * The length of the data to digest.
|
|
+ * @param md
|
|
+ * The output message digest.
|
|
+ * @return
|
|
+ * A pointer to the digest or NULL on error.
|
|
+ */
|
|
+typedef unsigned char *(*digester)(const unsigned char *d, size_t n, unsigned char *md);
|
|
+
|
|
+/**
|
|
+ * Get an openssl message digest from a tpm hashing algorithm.
|
|
+ * @param algorithm
|
|
+ * The tpm algorithm to get the corresponding openssl version of.
|
|
+ * @return
|
|
+ * A pointer to a message digester or NULL on failure.
|
|
+ */
|
|
+const EVP_MD *tpm2_openssl_halg_from_tpmhalg(TPMI_ALG_HASH algorithm);
|
|
+
|
|
+/**
|
|
+ * Obtains an OpenSSL EVP_CIPHER_CTX dealing with version
|
|
+ * API changes in OSSL.
|
|
+ *
|
|
+ * @return
|
|
+ * An Initialized OpenSSL EVP_CIPHER_CTX.
|
|
+ */
|
|
+EVP_CIPHER_CTX *tpm2_openssl_cipher_new(void);
|
|
+
|
|
+/**
|
|
+ * Free's an EVP_CIPHER_CTX obtained via tpm2_openssl_cipher_new()
|
|
+ * dealing with OSSL API version changes.
|
|
+ * @param ctx
|
|
+ * The EVP_CIPHER_CTX to free.
|
|
+ */
|
|
+void tpm2_openssl_cipher_free(EVP_CIPHER_CTX *ctx);
|
|
+
|
|
+/**
|
|
+ * Returns a function pointer capable of performing the
|
|
+ * given digest from a TPMI_HASH_ALG.
|
|
+ *
|
|
+ * @param halg
|
|
+ * The hashing algorithm to use.
|
|
+ * @return
|
|
+ * NULL on failure or a valid digester on success.
|
|
+ */
|
|
+digester tpm2_openssl_halg_to_digester(TPMI_ALG_HASH halg);
|
|
+
|
|
+typedef enum tpm2_openssl_load_rc tpm2_openssl_load_rc;
|
|
+enum tpm2_openssl_load_rc {
|
|
+ lprc_error = 0, /* an error has occurred */
|
|
+ lprc_private = 1 << 0, /* successfully loaded a private portion of object */
|
|
+ lprc_public = 1 << 1, /* successfully loaded a public portion of object */
|
|
+};
|
|
+
|
|
+
|
|
+#endif /* LIB_TPM2_OPENSSL_H_ */
|
|
diff --git a/lib/tpm2_options.c b/lib/tpm2_options.c
|
|
index c2962ee95d4..8c3f36cacea 100644
|
|
--- a/lib/tpm2_options.c
|
|
+++ b/lib/tpm2_options.c
|
|
@@ -268,9 +268,8 @@ static char* parse_socket_tcti(void) {
|
|
|
|
static tcti_conf tcti_get_config(const char *optstr) {
|
|
|
|
- tcti_conf conf = {
|
|
- .name = NULL
|
|
- };
|
|
+ /* set up the default configuration */
|
|
+ tcti_conf conf = { 0 };
|
|
|
|
/* no tcti config supplied, get it from env */
|
|
if (!optstr) {
|
|
@@ -294,6 +293,11 @@ static tcti_conf tcti_get_config(const char *optstr) {
|
|
}
|
|
}
|
|
} else {
|
|
+ /* handle case of TCTI set as "-T none" */
|
|
+ if (!strcmp(optstr, "none")) {
|
|
+ return conf;
|
|
+ }
|
|
+
|
|
parse_env_tcti(optstr, &conf);
|
|
}
|
|
|
|
@@ -400,7 +404,7 @@ tpm2_option_code tpm2_handle_options (int argc, char **argv,
|
|
* grep -rn case\ \'[a-zA-Z]\' | awk '{print $3}' | sed s/\'//g | sed s/\://g | sort | uniq | less
|
|
*/
|
|
struct option long_options [] = {
|
|
- { "tcti", required_argument, NULL, 'T' },
|
|
+ { "tcti", optional_argument, NULL, 'T' },
|
|
{ "help", no_argument, NULL, 'h' },
|
|
{ "verbose", no_argument, NULL, 'V' },
|
|
{ "quiet", no_argument, NULL, 'Q' },
|
|
@@ -492,17 +496,23 @@ tpm2_option_code tpm2_handle_options (int argc, char **argv,
|
|
if (!tool_opts || !(tool_opts->flags & TPM2_OPTIONS_NO_SAPI)) {
|
|
tcti_conf conf = tcti_get_config(tcti_conf_option);
|
|
|
|
- *tcti = tpm2_tcti_ldr_load(conf.name, conf.opts);
|
|
- if (!*tcti) {
|
|
- LOG_ERR("Could not load tcti, got: \"%s\"", conf.name);
|
|
- goto out;
|
|
- }
|
|
+ /* name can be NULL for optional SAPI tools */
|
|
+ if (conf.name) {
|
|
+ *tcti = tpm2_tcti_ldr_load(conf.name, conf.opts);
|
|
+ if (!*tcti) {
|
|
+ LOG_ERR("Could not load tcti, got: \"%s\"", conf.name);
|
|
+ goto out;
|
|
+ }
|
|
|
|
- if (!flags->enable_errata) {
|
|
- flags->enable_errata = !!getenv (TPM2TOOLS_ENV_ENABLE_ERRATA);
|
|
+ if (!flags->enable_errata) {
|
|
+ flags->enable_errata = !!getenv (TPM2TOOLS_ENV_ENABLE_ERRATA);
|
|
+ }
|
|
+ free(conf.name);
|
|
+ free(conf.opts);
|
|
+ } else if (!tool_opts || !(tool_opts->flags & TPM2_OPTIONS_OPTIONAL_SAPI)) {
|
|
+ LOG_ERR("Requested no tcti, but tool requires TCTI.");
|
|
+ goto out;
|
|
}
|
|
- free(conf.name);
|
|
- free(conf.opts);
|
|
}
|
|
|
|
rc = tpm2_option_code_continue;
|
|
diff --git a/lib/tpm2_options.h b/lib/tpm2_options.h
|
|
index 860d9b0deee..e16c5205044 100644
|
|
--- a/lib/tpm2_options.h
|
|
+++ b/lib/tpm2_options.h
|
|
@@ -105,6 +105,7 @@ typedef bool (*tpm2_arg_handler)(int argc, char **argv);
|
|
*/
|
|
#define TPM2_OPTIONS_SHOW_USAGE 0x1
|
|
#define TPM2_OPTIONS_NO_SAPI 0x2
|
|
+#define TPM2_OPTIONS_OPTIONAL_SAPI 0x4
|
|
|
|
struct tpm2_options {
|
|
struct {
|
|
diff --git a/man/common/tcti.md b/man/common/tcti.md
|
|
index fd5f1683dfe..0cb06e3c403 100644
|
|
--- a/man/common/tcti.md
|
|
+++ b/man/common/tcti.md
|
|
@@ -18,6 +18,10 @@ The variables respected depend on how the software was configured.
|
|
* socket - Typically used with the old resource manager, or talking directly to
|
|
a simulator.
|
|
* device - Used when talking directly to a TPM device file.
|
|
+ * none - Do not initialize a connection with the TPM. Some tools allow for off-tpm
|
|
+ options and thus support not using a TCTI. Tools that do not support it
|
|
+ will error when attempted to be used without a TCTI connection. Does not
|
|
+ support *ANY* options and *MUST BE* presented as the exact text of "none".
|
|
|
|
* _TPM2TOOLS\_DEVICE\_FILE_:
|
|
When using the device TCTI, specify the TPM device file. The default is
|
|
diff --git a/man/tpm2_activatecredential.1.md b/man/tpm2_activatecredential.1.md
|
|
index 25478790baf..b15569ae5cf 100644
|
|
--- a/man/tpm2_activatecredential.1.md
|
|
+++ b/man/tpm2_activatecredential.1.md
|
|
@@ -56,7 +56,7 @@ These options control the object verification:
|
|
```
|
|
tpm2_activatecredential -H 0x81010002 -k 0x81010001 -P abc123 -e abc123 -f <filePath> -o <filePath>
|
|
tpm2_activatecredential -c ak.context -C ek.context -P abc123 -e abc123 -f <filePath> -o <filePath>
|
|
-tpm2_activatecredential -H 0x81010002 -k 0x81010001 -P 123abc -e 1a1b1c -X -f <filePath> -o <filePath>
|
|
+tpm2_activatecredential -H 0x81010002 -k 0x81010001 -P 123abc -e 1a1b1c -f <filePath> -o <filePath>
|
|
```
|
|
|
|
# RETURNS
|
|
diff --git a/man/tpm2_certify.1.md b/man/tpm2_certify.1.md
|
|
index fba4a8f7c65..f4a78c70c00 100644
|
|
--- a/man/tpm2_certify.1.md
|
|
+++ b/man/tpm2_certify.1.md
|
|
@@ -71,7 +71,7 @@ These options control the ceritifcation:
|
|
```
|
|
tpm2_certify -H 0x81010002 -k 0x81010001 -P 0x0011 -K 0x00FF -g 0x00B -a <fileName> -s <fileName>
|
|
tpm2_certify -C obj.context -c key.context -P 0x0011 -K 0x00FF -g 0x00B -a <fileName> -s <fileName>
|
|
-tpm2_certify -H 0x81010002 -k 0x81010001 -P 0011 -K 00FF -X -g 0x00B -a <fileName> -s <fileName>
|
|
+tpm2_certify -H 0x81010002 -k 0x81010001 -P 0011 -K 00FF -g 0x00B -a <fileName> -s <fileName>
|
|
```
|
|
|
|
# RETURNS
|
|
diff --git a/man/tpm2_create.1.md b/man/tpm2_create.1.md
|
|
index f6aed4a7756..51d71db2c75 100644
|
|
--- a/man/tpm2_create.1.md
|
|
+++ b/man/tpm2_create.1.md
|
|
@@ -86,7 +86,7 @@ These options for creating the tpm entity:
|
|
```
|
|
tpm2_create -H 0x81010001 -P abc123 -K def456 -g sha256 -G keyedhash-I data.File
|
|
tpm2_create -c parent.context -P abc123 -K def456 -g sha256 -G keyedhash -I data.File
|
|
-tpm2_create -H 0x81010001 -P 123abc -K 456def -X -g sha256 -G keyedhash -I data.File
|
|
+tpm2_create -H 0x81010001 -P 123abc -K 456def -g sha256 -G keyedhash -I data.File
|
|
```
|
|
|
|
# RETURNS
|
|
diff --git a/man/tpm2_encryptdecrypt.1.md b/man/tpm2_encryptdecrypt.1.md
|
|
index ea349bec1e8..350737182dd 100644
|
|
--- a/man/tpm2_encryptdecrypt.1.md
|
|
+++ b/man/tpm2_encryptdecrypt.1.md
|
|
@@ -48,7 +48,7 @@ specified symmetric key.
|
|
```
|
|
tpm2_encryptdecrypt -k 0x81010001 -P abc123 -D NO -I <filePath> -o <filePath>
|
|
tpm2_encryptdecrypt -c key.context -P abc123 -D NO -I <filePath> -o <filePath>
|
|
-tpm2_encryptdecrypt -k 0x81010001 -P 123abca -X -D NO -I <filePath> -o <filePath>
|
|
+tpm2_encryptdecrypt -k 0x81010001 -P 123abca -D NO -I <filePath> -o <filePath>
|
|
```
|
|
|
|
# RETURNS
|
|
diff --git a/man/tpm2_getpubak.1.md b/man/tpm2_getpubak.1.md
|
|
index 22ade8f0b33..1a71b49c110 100644
|
|
--- a/man/tpm2_getpubak.1.md
|
|
+++ b/man/tpm2_getpubak.1.md
|
|
@@ -80,7 +80,7 @@ loaded-key:
|
|
|
|
```
|
|
tpm2_getpubak -e abc123 -P abc123 -o passwd -E 0x81010001 -k 0x81010002 -f ./ak.pub -n ./ak.name
|
|
-tpm2_getpubak -e 1a1b1c -P 123abc -o 1a1b1c -X -E 0x81010001 -k 0x81010002 -f ./ak.pub -n ./ak.name
|
|
+tpm2_getpubak -e 1a1b1c -P 123abc -o 1a1b1c -E 0x81010001 -k 0x81010002 -f ./ak.pub -n ./ak.name
|
|
```
|
|
|
|
# RETURNS
|
|
diff --git a/man/tpm2_makecredential.1.md b/man/tpm2_makecredential.1.md
|
|
index 736ead591b8..1008682fe7f 100644
|
|
--- a/man/tpm2_makecredential.1.md
|
|
+++ b/man/tpm2_makecredential.1.md
|
|
@@ -14,7 +14,8 @@ TPM.
|
|
# DESCRIPTION
|
|
|
|
**tpm2_makecredential**(1) - Use a TPM public key to protect a secret that is used
|
|
-to encrypt the AK certififcate.
|
|
+to encrypt the AK certificate. This can be used without a TPM by using
|
|
+the **none** TCTI option.
|
|
|
|
# OPTIONS
|
|
|
|
diff --git a/test/system/test_tpm2_makecredential.sh b/test/system/test_tpm2_makecredential.sh
|
|
index cc920ccae07..84f77b3647b 100755
|
|
--- a/test/system/test_tpm2_makecredential.sh
|
|
+++ b/test/system/test_tpm2_makecredential.sh
|
|
@@ -72,4 +72,6 @@ Loadkeyname=`cat $output_ak_pub_name | xxd -p -c $file_size`
|
|
|
|
tpm2_makecredential -Q -e $output_ek_pub -s $file_input_data -n $Loadkeyname -o $output_mkcredential
|
|
|
|
+tpm2_makecredential -T none -Q -e $output_ek_pub -s $file_input_data -n $Loadkeyname -o $output_mkcredential
|
|
+
|
|
exit 0
|
|
diff --git a/tools/tpm2_makecredential.c b/tools/tpm2_makecredential.c
|
|
index c8f49fe0207..259d39f30f3 100644
|
|
--- a/tools/tpm2_makecredential.c
|
|
+++ b/tools/tpm2_makecredential.c
|
|
@@ -1,5 +1,6 @@
|
|
//**********************************************************************;
|
|
// Copyright (c) 2015-2018, Intel Corporation
|
|
+// Copyright (c) 2019 Massachusetts Institute of Technology
|
|
// All rights reserved.
|
|
//
|
|
// Redistribution and use in source and binary forms, with or without
|
|
@@ -38,12 +39,15 @@
|
|
|
|
#include <tss2/tss2_sys.h>
|
|
#include <tss2/tss2_mu.h>
|
|
+#include <openssl/rand.h>
|
|
|
|
#include "files.h"
|
|
#include "tpm2_options.h"
|
|
#include "log.h"
|
|
#include "files.h"
|
|
-#include "tpm2_options.h"
|
|
+#include "tpm2_alg_util.h"
|
|
+#include "tpm2_openssl.h"
|
|
+#include "tpm2_identity_util.h"
|
|
#include "tpm2_tool.h"
|
|
#include "tpm2_util.h"
|
|
|
|
@@ -117,6 +121,93 @@ out:
|
|
return result;
|
|
}
|
|
|
|
+static bool make_external_credential_and_save() {
|
|
+
|
|
+ /*
|
|
+ * Get name_alg from the public key
|
|
+ */
|
|
+ TPMI_ALG_HASH name_alg = ctx.public.publicArea.nameAlg;
|
|
+
|
|
+
|
|
+ /*
|
|
+ * Generate and encrypt seed
|
|
+ */
|
|
+ TPM2B_DIGEST seed = TPM2B_TYPE_INIT(TPM2B_DIGEST, buffer);
|
|
+ seed.size = tpm2_alg_util_get_hash_size(name_alg);
|
|
+ RAND_bytes(seed.buffer, seed.size);
|
|
+
|
|
+ TPM2B_ENCRYPTED_SECRET encrypted_seed = TPM2B_EMPTY_INIT;
|
|
+ unsigned char label[10] = { 'I', 'D', 'E', 'N', 'T', 'I', 'T', 'Y', 0 };
|
|
+ bool res = tpm2_identity_util_encrypt_seed_with_public_key(&seed,
|
|
+ &ctx.public, label, 9,
|
|
+ &encrypted_seed);
|
|
+ if (!res) {
|
|
+ LOG_ERR("Failed Seed Encryption\n");
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Perform identity structure calculations (off of the TPM)
|
|
+ */
|
|
+ TPM2B_MAX_BUFFER hmac_key;
|
|
+ TPM2B_MAX_BUFFER enc_key;
|
|
+ tpm2_identity_util_calc_outer_integrity_hmac_key_and_dupsensitive_enc_key(
|
|
+ &ctx.public,
|
|
+ &ctx.object_name,
|
|
+ &seed,
|
|
+ &hmac_key,
|
|
+ &enc_key);
|
|
+
|
|
+ /*
|
|
+ * The ctx.credential needs to be marshalled into struct with
|
|
+ * both size and contents together (to be encrypted as a block)
|
|
+ */
|
|
+ TPM2B_MAX_BUFFER marshalled_inner_integrity = TPM2B_EMPTY_INIT;
|
|
+ marshalled_inner_integrity.size = ctx.credential.size + sizeof(ctx.credential.size);
|
|
+ UINT16 credSize = ctx.credential.size;
|
|
+ if (!tpm2_util_is_big_endian()) {
|
|
+ credSize = tpm2_util_endian_swap_16(credSize);
|
|
+ }
|
|
+ memcpy(marshalled_inner_integrity.buffer, &credSize, sizeof(credSize));
|
|
+ memcpy(&marshalled_inner_integrity.buffer[2], ctx.credential.buffer, ctx.credential.size);
|
|
+
|
|
+ /*
|
|
+ * Perform inner encryption (encIdentity) and outer HMAC (outerHMAC)
|
|
+ */
|
|
+ TPM2B_DIGEST outer_hmac = TPM2B_EMPTY_INIT;
|
|
+ TPM2B_MAX_BUFFER encrypted_sensitive = TPM2B_EMPTY_INIT;
|
|
+ tpm2_identity_util_calculate_outer_integrity(
|
|
+ name_alg,
|
|
+ &ctx.object_name,
|
|
+ &marshalled_inner_integrity,
|
|
+ &hmac_key,
|
|
+ &enc_key,
|
|
+ &ctx.public.publicArea.parameters.rsaDetail.symmetric,
|
|
+ &encrypted_sensitive,
|
|
+ &outer_hmac);
|
|
+
|
|
+ /*
|
|
+ * Package up the info to save
|
|
+ * cred_bloc = outer_hmac || encrypted_sensitive
|
|
+ * secret = encrypted_seed (with pubEK)
|
|
+ */
|
|
+ TPM2B_ID_OBJECT cred_blob = TPM2B_TYPE_INIT(TPM2B_ID_OBJECT, credential);
|
|
+
|
|
+ UINT16 outer_hmac_size = outer_hmac.size;
|
|
+ if (!tpm2_util_is_big_endian()) {
|
|
+ outer_hmac_size = tpm2_util_endian_swap_16(outer_hmac_size);
|
|
+ }
|
|
+ int offset = 0;
|
|
+ memcpy(cred_blob.credential + offset, &outer_hmac_size, sizeof(outer_hmac.size));offset += sizeof(outer_hmac.size);
|
|
+ memcpy(cred_blob.credential + offset, outer_hmac.buffer, outer_hmac.size);offset += outer_hmac.size;
|
|
+ //NOTE: do NOT include the encrypted_sensitive size, since it is encrypted with the blob!
|
|
+ memcpy(cred_blob.credential + offset, encrypted_sensitive.buffer, encrypted_sensitive.size);
|
|
+
|
|
+ cred_blob.size = outer_hmac.size + encrypted_sensitive.size + sizeof(outer_hmac.size);
|
|
+
|
|
+ return write_cred_and_secret(ctx.out_file_path, &cred_blob, &encrypted_seed);
|
|
+}
|
|
+
|
|
static bool make_credential_and_save(TSS2_SYS_CONTEXT *sapi_context)
|
|
{
|
|
TSS2L_SYS_AUTH_RESPONSE sessions_data_out;
|
|
@@ -198,7 +289,8 @@ bool tpm2_tool_onstart(tpm2_options **opts) {
|
|
};
|
|
|
|
*opts = tpm2_options_new("e:s:n:o:", ARRAY_LEN(topts), topts,
|
|
- on_option, NULL, TPM2_OPTIONS_SHOW_USAGE);
|
|
+ on_option, NULL,
|
|
+ TPM2_OPTIONS_SHOW_USAGE | TPM2_OPTIONS_OPTIONAL_SAPI);
|
|
|
|
return *opts != NULL;
|
|
}
|
|
@@ -212,5 +304,10 @@ int tpm2_tool_onrun(TSS2_SYS_CONTEXT *sapi_context, tpm2_option_flags flags) {
|
|
return false;
|
|
}
|
|
|
|
- return make_credential_and_save(sapi_context) != true;
|
|
+ printf("make credential has SAPI CTX: %p", sapi_context);
|
|
+
|
|
+ bool result = sapi_context ? make_credential_and_save(sapi_context) :
|
|
+ make_external_credential_and_save();
|
|
+
|
|
+ return result != true;
|
|
}
|
|
--
|
|
2.21.0
|
|
|