Blame Add-ability-to-run-tpm2_makecredential-without-a-TPM.patch

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