From 1b61f57848681e80687800e07df72e14df5a3644 Mon Sep 17 00:00:00 2001 From: Juergen Repp Date: Wed, 22 Nov 2023 01:52:23 +0100 Subject: [PATCH] FAPI TEST: rework test certificate creation * A CA script for initializing the CA was added. * The EK, the EK certificate and the EK fingerprint is now created in main-fapi.c * The creation of the EK certificate was removed from fint-log-compiler.sh Signed-off-by: Juergen Repp --- Makefile-test.am | 1 + Makefile.am | 14 + configure.ac | 2 + script/ekca/init_ca.sh | 129 +++++ script/fint-log-compiler.sh | 132 +---- test/integration/main-fapi.c | 955 ++++++++++++++++++++++++++++++++- test/integration/test-common.c | 13 +- test/integration/test-common.h | 2 + test/integration/test-fapi.h | 1 - 9 files changed, 1110 insertions(+), 139 deletions(-) create mode 100755 script/ekca/init_ca.sh diff --git a/Makefile-test.am b/Makefile-test.am index 4a2a3c513..6eec9ea31 100644 --- a/Makefile-test.am +++ b/Makefile-test.am @@ -21,6 +21,7 @@ EXTRA_DIST += $(srcdir)/script/int-log-compiler.sh \ $(srcdir)/script/fint-log-compiler.sh \ $(srcdir)/script/int-log-compiler-common.sh \ $(srcdir)/script/ekca/create_ca.sh \ + $(srcdir)/script/ekca/init_ca.sh \ $(srcdir)/script/ekca/ek.cnf \ $(srcdir)/script/ekca/intermed-ca.cnf \ $(srcdir)/script/ekca/root-ca.cnf diff --git a/Makefile.am b/Makefile.am index 12de494fc..7cb0742dd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -966,11 +966,25 @@ install-data-hook: install-dirs fi uninstall-local: + -rm -r -f $(top_builddir)/ca -rm $(DESTDIR)$(udevrulesdir)/$(udevrulesprefix)tpm-udev.rules cd $(DESTDIR)$(man3dir) && \ [ -L Tss2_TctiLdr_Initialize_Ex.3 ] && \ rm -f Tss2_TctiLdr_Initialize_Ex.3 || true +clean-hook: + -rm -r -f $(top_builddir)/ca + +check-hook: + -rm -r -f $(top_builddir)/ca + +prepare-check: +if INIT_CI + $(top_srcdir)/script/ekca/init_ca.sh $(top_builddir) +endif + +check: prepare-check + EXTRA_DIST += \ doc/doxygen.dox \ doc/coding_standard_c.md \ diff --git a/configure.ac b/configure.ac index db4e99662..b05a71a82 100644 --- a/configure.ac +++ b/configure.ac @@ -640,6 +640,8 @@ AS_IF([test "x$enable_self_generated_certificate" = xyes], [AC_DEFINE([SELF_GENERATED_CERTIFICATE], [1], [Allow usage of self generated root certificate])], [AS_IF([test "x$integration_tcti" != "xdevice"], [AC_DEFINE([FAPI_TEST_EK_CERT_LESS], [1], [Perform integration tests without EK certificate verification])])]) +AM_CONDITIONAL([INIT_CI], [test "x$enable_self_generated_certificate" == xyes]) + AS_IF([test "x$enable_integration" = "xyes" && test "x$enable_self_generated_certificate" != "xyes" && test "x$integration_tcti" != "xdevice"], [AC_MSG_WARN([Running integration tests without EK certificate verification, use --enable-self-generated-certificate for full test coverage])]) diff --git a/script/ekca/init_ca.sh b/script/ekca/init_ca.sh new file mode 100755 index 000000000..e8c94bb4e --- /dev/null +++ b/script/ekca/init_ca.sh @@ -0,0 +1,129 @@ +#!/usr/bin/env bash + +#set -x + +#set -euf +OS=$(uname) +DATE_FMT_BEFORE="" +DATE_FMT_AFTER="" +SED_CMD="" + +if [ "$OS" == "Linux" ]; then + DATE_FMT_BEFORE="+%y%m%d000000Z -u -d -1day" + DATE_FMT_AFTER="+%y%m%d000000Z -u -d +10years+1day" + SED_CMD="sed -i" +elif [ "$OS" == "FreeBSD" ]; then + DATE_FMT_BEFORE="-u -v-1d +%y%m%d000000Z" + DATE_FMT_AFTER="-u -v+10y +%y%m%d000000Z" + SED_CMD="sed -i '' -e" +fi + +EKCADIR="$(dirname $(realpath ${0}))/" +CA_DIR="$1/ca" +if test -e $CA_DIR; then + exit +fi +mkdir -p $CA_DIR + +pushd "$CA_DIR" + +mkdir root-ca +pushd root-ca + +mkdir certreqs certs crl newcerts private +touch root-ca.index +echo 00 > root-ca.crlnum +echo 1000 > root-ca.serial +echo "123456" > pass.txt + +cp "${EKCADIR}/root-ca.cnf" ./ +export OPENSSL_CONF=./root-ca.cnf +ROOT_URL="file:$ROOTCRT" +${SED_CMD} "s|ROOTCRT|$ROOT_URL|g" $OPENSSL_CONF +ROOT_URL="file:$ROOTCRL" +${SED_CMD} "s|ROOTCRL|$ROOT_URL|g" $OPENSSL_CONF +openssl req -new -out root-ca.req.pem -passout file:pass.txt + +# +# Create self signed root certificate +# + +openssl ca -selfsign \ + -in root-ca.req.pem \ + -out root-ca.cert.pem \ + -extensions root-ca_ext \ + -startdate `date ${DATE_FMT_BEFORE}` \ + -enddate `date ${DATE_FMT_AFTER}` \ + -passin file:pass.txt -batch + +openssl x509 -outform der -in root-ca.cert.pem -out root-ca.cert.crt + +openssl verify -verbose -CAfile root-ca.cert.pem \ + root-ca.cert.pem + +openssl ca -gencrl -cert root-ca.cert.pem \ + -out root-ca.cert.crl.pem -passin file:pass.txt +openssl crl -in root-ca.cert.crl.pem -outform DER -out root-ca.cert.crl + +popd #root-ca + +# +# Create intermediate certificate +# +mkdir intermed-ca +pushd intermed-ca + +mkdir certreqs certs crl newcerts private +touch intermed-ca.index +echo 00 > intermed-ca.crlnum +echo 2000 > intermed-ca.serial +echo "abcdef" > pass.txt + +cp "${EKCADIR}/intermed-ca.cnf" ./ +export OPENSSL_CONF=./intermed-ca.cnf + +# Adapt CRT URL to current test directory +${SED_CMD} "s|ROOTCRT|$ROOT_URL|g" $OPENSSL_CONF + +openssl req -new -out intermed-ca.req.pem -passout file:pass.txt + +openssl rsa -inform PEM -in private/intermed-ca.key.pem \ + -outform DER -out private/intermed-ca.key.der -passin file:pass.txt + +cp intermed-ca.req.pem \ + ../root-ca/certreqs/ + +INTERMED_URL="file:$INTERMEDCRT" +${SED_CMD} "s|INTERMEDCRT|$INTERMED_URL|g" $OPENSSL_CONF + +pushd ../root-ca +export OPENSSL_CONF=./root-ca.cnf + +openssl ca \ + -in certreqs/intermed-ca.req.pem \ + -out certs/intermed-ca.cert.pem \ + -extensions intermed-ca_ext \ + -startdate `date ${DATE_FMT_BEFORE}` \ + -enddate `date ${DATE_FMT_AFTER}` \ + -passin file:pass.txt -batch + +openssl x509 -outform der -in certs/intermed-ca.cert.pem \ + -out certs/intermed-ca.cert.crt + +openssl verify -verbose -CAfile root-ca.cert.pem \ + certs/intermed-ca.cert.pem + +cp certs/intermed-ca.cert.pem \ + ../intermed-ca + +cp certs/intermed-ca.cert.crt \ + ../intermed-ca + +popd #root-ca + +export OPENSSL_CONF=./intermed-ca.cnf +openssl ca -gencrl -cert ../root-ca/certs/intermed-ca.cert.pem \ + -out intermed-ca.crl.pem -passin file:pass.txt +openssl crl -in intermed-ca.crl.pem -outform DER -out intermed-ca.crl + +popd #intermed-ca diff --git a/script/fint-log-compiler.sh b/script/fint-log-compiler.sh index 841ffe111..d6cb30e6d 100755 --- a/script/fint-log-compiler.sh +++ b/script/fint-log-compiler.sh @@ -42,109 +42,8 @@ echo "TPM20TEST_TCTI=${TPM20TEST_TCTI}" while true; do -if [[ ${TPM20TEST_TCTI} != *device* ]]; then - env TPM20TEST_TCTI="${TPM20TEST_TCTI}" \ - TCTI_PCAP_FILE="${TCTI_PCAP_FILE}" \ - G_MESSAGES_DEBUG=all ./test/helper/tpm_startup - if [ $? -ne 0 ]; then - echo "TPM_StartUp failed" - ret=99 - break - fi -else - env TPM20TEST_TCTI=${TPM20TEST_TCTI} \ - TCTI_PCAP_FILE="${TCTI_PCAP_FILE}" \ - G_MESSAGES_DEBUG=all ./test/helper/tpm_transientempty - if [ $? -ne 0 ]; then - echo "TPM transient area not empty => skipping" - ret=99 - break - fi -fi - -# Certificate generation for simulator tests -if [[ ${TPM20TEST_TCTI} != *device* ]]; then - EKPUB_FILE=${TEST_BIN}_ekpub.pem - EKCERT_FILE=${TEST_BIN}_ekcert.crt - EKCERT_PEM_FILE=${TEST_BIN}_ekcert.pem - - env TPM20TEST_TCTI="${TPM20TEST_TCTI}" \ - TCTI_PCAP_FILE="${TCTI_PCAP_FILE}" \ - G_MESSAGES_DEBUG=all ./test/helper/tpm_getek ${EKPUB_FILE} - if [ $? -ne 0 ]; then - echo "TPM_getek failed" - ret=99 - break - fi - - EKECCPUB_FILE=${TEST_BIN}_ekeccpub.pem - EKECCCERT_FILE=${TEST_BIN}_ekecccert.crt - EKECCCERT_PEM_FILE=${TEST_BIN}_ekecccert.pem - - env TPM20TEST_TCTI="${TPM20TEST_TCTI}" \ - TCTI_PCAP_FILE="${TCTI_PCAP_FILE}" \ - G_MESSAGES_DEBUG=all ./test/helper/tpm_getek_ecc ${EKECCPUB_FILE} - if [ $? -ne 0 ]; then - echo "TPM_getek_ecc failed" - ret=99 - break - fi - - INTERMEDCA_FILE=${TEST_BIN}_intermedecc-ca - ROOTCA_FILE=${TEST_BIN}_root-ca - - SCRIPTDIR="$(dirname $(realpath $0))/" - ${SCRIPTDIR}/ekca/create_ca.sh "${EKPUB_FILE}" "${EKECCPUB_FILE}" "${EKCERT_FILE}" \ - "${EKECCCERT_FILE}" "${INTERMEDCA_FILE}" "${ROOTCA_FILE}" >${TEST_BIN}_ca.log 2>&1 - if [ $? -ne 0 ]; then - echo "ek-cert ca failed" - ret=99 - break - fi - - # Determine the fingerprint of the RSA EK public. - FINGERPRINT=$(openssl pkey -pubin -inform PEM -in ${EKPUB_FILE} -outform DER | shasum -a 256 | cut -f 1 -d ' ') - export FAPI_TEST_FINGERPRINT=" { \"hashAlg\" : \"sha256\", \"digest\" : \"${FINGERPRINT}\" }" - openssl x509 -inform DER -in ${EKCERT_FILE} -outform PEM -out ${EKCERT_PEM_FILE} - export FAPI_TEST_CERTIFICATE="file:${EKCERT_PEM_FILE}" - - # Determine the fingerprint of the RSA EK public. - FINGERPRINT_ECC=$(openssl pkey -pubin -inform PEM -in ${EKECCPUB_FILE} -outform DER | shasum -a 256 | cut -f 1 -d ' ') - export FAPI_TEST_FINGERPRINT_ECC=" { \"hashAlg\" : \"sha256\", \"digest\" : \"${FINGERPRINT_ECC}\" }" - openssl x509 -inform DER -in ${EKECCCERT_FILE} -outform PEM -out ${EKECCCERT_PEM_FILE} - export FAPI_TEST_CERTIFICATE_ECC="file:${EKECCCERT_PEM_FILE}" - - cat $EKCERT_FILE | \ - env TPM20TEST_TCTI="${TPM20TEST_TCTI}" \ - TCTI_PCAP_FILE="${TCTI_PCAP_FILE}" \ - G_MESSAGES_DEBUG=all ./test/helper/tpm_writeekcert 1C00002 - if [ $? -ne 0 ]; then - echo "TPM_writeekcert failed" - ret=99 - break - fi - - cat $EKECCCERT_FILE | \ - env TPM20TEST_TCTI="${TPM20TEST_TCTI}" \ - TCTI_PCAP_FILE="${TCTI_PCAP_FILE}" \ - G_MESSAGES_DEBUG=all ./test/helper/tpm_writeekcert 1C0000A - if [ $? -ne 0 ]; then - echo "TPM_writeekcert failed" - ret=99 - fi -fi # certificate generation - -TPMSTATE_FILE1=${TEST_BIN}_state1 -TPMSTATE_FILE2=${TEST_BIN}_state2 - -env TPM20TEST_TCTI="${TPM20TEST_TCTI}" \ - TCTI_PCAP_FILE="${TCTI_PCAP_FILE}" \ - G_MESSAGES_DEBUG=all ./test/helper/tpm_dumpstate>${TPMSTATE_FILE1} -if [ $? -ne 0 ]; then - echo "Error during dumpstate" - ret=99 - break -fi +INTERMEDCA_FILE=ca/intermed-ca/intermed-ca.cert +ROOTCA_FILE=ca/root-ca/root-ca.cert echo "Execute the test script" if [[ ${TPM20TEST_TCTI} == *device* ]]; then @@ -154,34 +53,21 @@ if [[ ${TPM20TEST_TCTI} == *device* ]]; then G_MESSAGES_DEBUG=all ${@: -1} else # Run test with generated certificate. + + EKECCCERT_PEM_FILE=${TEST_BIN}_ekecccert.pem + export FAPI_TEST_CERTIFICATE_ECC="${EKECCCERT_PEM_FILE}" + EKCERT_PEM_FILE=${TEST_BIN}_ekcert.pem + export FAPI_TEST_CERTIFICATE="${EKCERT_PEM_FILE}" + env TPM20TEST_TCTI="${TPM20TEST_TCTI}" \ TCTI_PCAP_FILE="${TCTI_PCAP_FILE}" \ FAPI_TEST_ROOT_CERT=${ROOTCA_FILE}.pem \ + FAPI_TEST_INT_CERT=${INTERMEDCA_FILE}.pem \ G_MESSAGES_DEBUG=all ${@: -1} fi ret=$? echo "Script returned $ret" -#We check the state before a reboot to see if transients and NV were chagned. -env TPM20TEST_TCTI="${TPM20TEST_TCTI}" \ - TCTI_PCAP_FILE="${TCTI_PCAP_FILE}" \ - G_MESSAGES_DEBUG=all ./test/helper/tpm_dumpstate>${TPMSTATE_FILE2} -if [ $? -ne 0 ]; then - echo "Error during dumpstate" - ret=99 - break -fi - -if [ "$(cat ${TPMSTATE_FILE1})" != "$(cat ${TPMSTATE_FILE2})" ]; then - echo "TPM changed state during test" - echo "State before ($TPMSTATE_FILE1):" - cat ${TPMSTATE_FILE1} - echo "State after ($TPMSTATE_FILE2):" - cat ${TPMSTATE_FILE2} - ret=1 - break -fi - #TODO: Add a tpm-restart/reboot here break diff --git a/test/integration/main-fapi.c b/test/integration/main-fapi.c index 9d6d8a037..5650016bb 100644 --- a/test/integration/main-fapi.c +++ b/test/integration/main-fapi.c @@ -14,12 +14,25 @@ #include #include #include -#include + +#include +#include +#include +#if OPENSSL_VERSION_NUMBER < 0x30000000L +#include +#else +#include +#include +#include +#endif +#include +#include #include "tss2_esys.h" #include "tss2_fapi.h" #include "test-fapi.h" #include "fapi_int.h" +#include "tss2_rc.h" #define LOGDEFAULT LOGLEVEL_INFO #define LOGMODULE test @@ -28,6 +41,30 @@ #include "test-common.h" +#if OPENSSL_VERSION_NUMBER >= 0x10101000L +#define EC_POINT_set_affine_coordinates_tss(group, tpm_pub_key, bn_x, bn_y, dmy) \ + EC_POINT_set_affine_coordinates(group, tpm_pub_key, bn_x, bn_y, dmy) + +#define EC_POINT_get_affine_coordinates_tss(group, tpm_pub_key, bn_x, bn_y, dmy) \ + EC_POINT_get_affine_coordinates(group, tpm_pub_key, bn_x, bn_y, dmy) + +#else +#define EC_POINT_set_affine_coordinates_tss(group, tpm_pub_key, bn_x, bn_y, dmy) \ + EC_POINT_set_affine_coordinates_GFp(group, tpm_pub_key, bn_x, bn_y, dmy) + +#define EC_POINT_get_affine_coordinates_tss(group, tpm_pub_key, bn_x, bn_y, dmy) \ + EC_POINT_get_affine_coordinates_GFp(group, tpm_pub_key, bn_x, bn_y, dmy) +#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */ + +#define SYS_CALL(rc,fu,...) \ + do { \ + rc = fu(__VA_ARGS__); \ + } while (rc == TPM2_RC_YIELDED); \ + if (rc != TPM2_RC_SUCCESS) { \ + LOG_ERROR("%s FAILED: 0x%"PRIx32, #fu, rc); \ + return rc; \ + } + char *fapi_profile = NULL; TSS2_TEST_FAPI_CONTEXT *fapi_test_ctx = NULL; @@ -240,11 +277,11 @@ int init_fapi(char *profile, FAPI_CONTEXT **fapi_context) #if defined(FAPI_TEST_EK_CERT_LESS) " \"ek_cert_less\": \"yes\",\n" #else - " \"ek_fingerprint\": %s,\n" + " \"ek_fingerprint\": { \"hashAlg\": \"sha256\", \"digest\": \"%s\" },\n" #endif "}\n", profile, tmpdir, tmpdir, tmpdir, - getenv("TPM20TEST_TCTI") + getenv(ENV_TCTI) #if !defined(FAPI_TEST_EK_CERT_LESS) , getenv("FAPI_TEST_FINGERPRINT") #endif @@ -261,11 +298,11 @@ int init_fapi(char *profile, FAPI_CONTEXT **fapi_context) #if defined(FAPI_TEST_EK_CERT_LESS) " \"ek_cert_less\": \"yes\",\n" #else - " \"ek_cert_file\": \"%s\",\n" + " \"ek_cert_file\": \"file:%s\",\n" #endif "}\n", profile, tmpdir, tmpdir, tmpdir, - getenv("TPM20TEST_TCTI") + getenv(ENV_TCTI) #if !defined(FAPI_TEST_EK_CERT_LESS) , getenv("FAPI_TEST_CERTIFICATE") #endif @@ -282,11 +319,11 @@ int init_fapi(char *profile, FAPI_CONTEXT **fapi_context) #if defined(FAPI_TEST_EK_CERT_LESS) " \"ek_cert_less\": \"yes\",\n" #else - " \"ek_fingerprint\": %s,\n" + " \"ek_fingerprint\": { \"hashAlg\": \"sha256\", \"digest\": \"%s\" },\n" #endif "}\n", profile, tmpdir, tmpdir, tmpdir, - getenv("TPM20TEST_TCTI") + getenv(ENV_TCTI) #if !defined(FAPI_TEST_EK_CERT_LESS) , getenv("FAPI_TEST_FINGERPRINT_ECC") #endif @@ -303,11 +340,11 @@ int init_fapi(char *profile, FAPI_CONTEXT **fapi_context) #if defined(FAPI_TEST_EK_CERT_LESS) " \"ek_cert_less\": \"yes\",\n" #else - " \"ek_cert_file\": \"%s\",\n" + " \"ek_cert_file\": \"file:%s\",\n" #endif "}\n", profile, tmpdir, tmpdir, tmpdir, - getenv("TPM20TEST_TCTI") + getenv(ENV_TCTI) #if defined(FAPI_TEST_EK_CERT_LESS) #else , getenv("FAPI_TEST_CERTIFICATE_ECC") @@ -322,12 +359,12 @@ int init_fapi(char *profile, FAPI_CONTEXT **fapi_context) " \"system_pcrs\" : [],\n" " \"log_dir\" : \"%s\",\n" " \"tcti\": \"%s\",\n" -#if defined(FAPI_TEST_EK_CERT_LESS) +#if defined(FAPI_TEST_EK_CERT_LESS) || defined(DLOPEN) " \"ek_cert_less\": \"yes\",\n" #endif "", profile, tmpdir, tmpdir, tmpdir, - getenv("TPM20TEST_TCTI")); + getenv(ENV_TCTI)); #endif /* FAPI_NONTPM */ if (size < 0) { @@ -432,12 +469,14 @@ int init_fapi(char *profile, FAPI_CONTEXT **fapi_context) * Call FAPI ***********/ + rc = Fapi_Initialize(fapi_context, NULL); if (rc != TSS2_RC_SUCCESS) { LOG_ERROR("Esys_Initialize FAILED! Response Code : 0x%x", rc); ret = EXIT_FAILURE; goto error; } + fapi_test_ctx->fapi_ctx = *fapi_context; SAFE_FREE(config_env); SAFE_FREE(config); @@ -453,6 +492,848 @@ int init_fapi(char *profile, FAPI_CONTEXT **fapi_context) return ret; } +TSS2_RC +rsa_pub_from_tpm(const TPM2B_PUBLIC *tpmPublicKey, EVP_PKEY **evpPublicKey) +{ +#if OPENSSL_VERSION_NUMBER < 0x30000000L + RSA *rsa = NULL; +#else + OSSL_PARAM_BLD *build = NULL; + OSSL_PARAM *params = NULL; + EVP_PKEY_CTX *ctx = NULL; +#endif + + /* Check for NULL parameters */ + return_if_null(tpmPublicKey, "tpmPublicKey is NULL", TSS2_FAPI_RC_BAD_REFERENCE); + return_if_null(evpPublicKey, "evpPublicKey is NULL", TSS2_FAPI_RC_BAD_REFERENCE); + + TSS2_RC r = TSS2_RC_SUCCESS; + /* Initialize the RSA parameters */ + BIGNUM *e = NULL; + BIGNUM *n = BN_bin2bn(tpmPublicKey->publicArea.unique.rsa.buffer, + tpmPublicKey->publicArea.unique.rsa.size, NULL); + if (!n) { + goto_error(r, TSS2_FAPI_RC_MEMORY, "Out of memory", error_cleanup); + } + + uint32_t exp; + if (tpmPublicKey->publicArea.parameters.rsaDetail.exponent == 0) + exp = 65537; + else + exp = tpmPublicKey->publicArea.parameters.rsaDetail.exponent; + +#if OPENSSL_VERSION_NUMBER < 0x30000000L + if ((rsa = RSA_new()) == NULL) { + goto_error(r, TSS2_FAPI_RC_MEMORY, "Out of memory", error_cleanup); + } + + if ((e = BN_new()) == NULL) { + goto_error(r, TSS2_FAPI_RC_MEMORY, "Out of memory", error_cleanup); + } + if (1 != BN_set_word(e, exp)) { + goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, + "Could not set exponent.", error_cleanup); + } + + if (!RSA_set0_key(rsa, n, e, NULL)) { + goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, + "Could not set public key.", error_cleanup); + } + n = NULL; /* ownership transferred */ + e = NULL; + + *evpPublicKey = EVP_PKEY_new(); + goto_if_null2(*evpPublicKey, "Out of memory.", r, TSS2_FAPI_RC_MEMORY, error_cleanup); + + /* Assign the parameters to the key */ + if (!EVP_PKEY_assign_RSA(*evpPublicKey, rsa)) { + EVP_PKEY_free(*evpPublicKey); + goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Assign rsa key", + error_cleanup); + } + rsa = NULL; /* ownership transferred */ +error_cleanup: + OSSL_FREE(rsa, RSA); +#else /* OPENSSL_VERSION_NUMBER < 0x30000000L */ + if ((build = OSSL_PARAM_BLD_new()) == NULL + || !OSSL_PARAM_BLD_push_BN(build, OSSL_PKEY_PARAM_RSA_N, n) + || !OSSL_PARAM_BLD_push_uint32(build, OSSL_PKEY_PARAM_RSA_E, exp) + || (params = OSSL_PARAM_BLD_to_param(build)) == NULL) { + goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Create rsa key parameters", + error_cleanup); + } + + if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL)) == NULL + || EVP_PKEY_fromdata_init(ctx) <= 0 + || EVP_PKEY_fromdata(ctx, evpPublicKey, EVP_PKEY_PUBLIC_KEY, params) <= 0) { + goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Create rsa key", + error_cleanup); + } +error_cleanup: + OSSL_FREE(ctx, EVP_PKEY_CTX); + OSSL_FREE(params, OSSL_PARAM); + OSSL_FREE(build, OSSL_PARAM_BLD); +#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L */ + OSSL_FREE(e, BN); + OSSL_FREE(n, BN); + return r; +} + +TSS2_RC +ecc_pub_from_tpm(const TPM2B_PUBLIC *tpmPublicKey, EVP_PKEY **evpPublicKey) +{ + /* Check for NULL parameters */ + return_if_null(tpmPublicKey, "tpmPublicKey is NULL", TSS2_FAPI_RC_BAD_REFERENCE); + return_if_null(evpPublicKey, "evpPublicKey is NULL", TSS2_FAPI_RC_BAD_REFERENCE); + + TSS2_RC r = TSS2_RC_SUCCESS; + EC_GROUP *ecgroup = NULL; + int curveId; + BIGNUM *x = NULL, *y = NULL; + EC_POINT *ecPoint = NULL; +#if OPENSSL_VERSION_NUMBER < 0x30000000L + EC_KEY *ecKey = NULL; +#else + OSSL_PARAM_BLD *build = NULL; + OSSL_PARAM *params = NULL; + EVP_PKEY_CTX *ctx = NULL; + unsigned char *puboct = NULL; + size_t bsize; +#endif + + /* Find the curve of the ECC key */ + switch (tpmPublicKey->publicArea.parameters.eccDetail.curveID) { + case TPM2_ECC_NIST_P192: + curveId = NID_X9_62_prime192v1; + break; + case TPM2_ECC_NIST_P224: + curveId = NID_secp224r1; + break; + case TPM2_ECC_NIST_P256: + curveId = NID_X9_62_prime256v1; + break; + case TPM2_ECC_NIST_P384: + curveId = NID_secp384r1; + break; + case TPM2_ECC_NIST_P521: + curveId = NID_secp521r1; + break; +#ifdef NID_sm2 + case TPM2_ECC_SM2_P256: + curveId = NID_sm2; + break; +#endif + default: + return_error(TSS2_FAPI_RC_BAD_VALUE, + "ECC curve not implemented."); + } + + /* Initialize the OpenSSL ECC key with its group */ + ecgroup = EC_GROUP_new_by_curve_name(curveId); + goto_if_null(ecgroup, "new EC group.", TSS2_FAPI_RC_GENERAL_FAILURE, + error_cleanup); + + /* Set the ECC parameters in the OpenSSL key */ + x = BN_bin2bn(tpmPublicKey->publicArea.unique.ecc.x.buffer, + tpmPublicKey->publicArea.unique.ecc.x.size, NULL); + + y = BN_bin2bn(tpmPublicKey->publicArea.unique.ecc.y.buffer, + tpmPublicKey->publicArea.unique.ecc.y.size, NULL); + + if (!x || !y) { + goto_error(r, TSS2_FAPI_RC_MEMORY, "Out of memory", error_cleanup); + } + + if ((ecPoint = EC_POINT_new(ecgroup)) == NULL + || !EC_POINT_set_affine_coordinates_tss(ecgroup, ecPoint, x, y, NULL)) { + goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "EC_POINT_set_affine_coordinates", + error_cleanup); + } + +#if OPENSSL_VERSION_NUMBER < 0x30000000 + ecKey = EC_KEY_new(); + return_if_null(ecKey, "Out of memory.", TSS2_FAPI_RC_MEMORY); + + if (!EC_KEY_set_group(ecKey, ecgroup)) { + goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "EC_KEY_set_group", + error_cleanup); + } + + if (!EC_KEY_set_public_key(ecKey, ecPoint)) { + goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, + "EC_KEY_set_public_key", error_cleanup); + } + + *evpPublicKey = EVP_PKEY_new(); + goto_if_null2(*evpPublicKey, "Out of memory.", r, TSS2_FAPI_RC_MEMORY, error_cleanup); + + if (!EVP_PKEY_assign_EC_KEY(*evpPublicKey, ecKey)) { + EVP_PKEY_free(*evpPublicKey); + goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Assign ecc key", + error_cleanup); + } + ecKey = NULL; /* ownership transferred */ +error_cleanup: + OSSL_FREE(ecKey, EC_KEY); +#else + if ((build = OSSL_PARAM_BLD_new()) == NULL + || !OSSL_PARAM_BLD_push_utf8_string(build, OSSL_PKEY_PARAM_GROUP_NAME, + (char *)OBJ_nid2sn(curveId), 0) + || (bsize = EC_POINT_point2buf(ecgroup, ecPoint, + POINT_CONVERSION_COMPRESSED, + &puboct, NULL)) == 0 + || !OSSL_PARAM_BLD_push_octet_string(build, OSSL_PKEY_PARAM_PUB_KEY, + puboct, bsize) + || (params = OSSL_PARAM_BLD_to_param(build)) == NULL) { + goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Create ecc key parameters", + error_cleanup); + } + + if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL)) == NULL + || EVP_PKEY_fromdata_init(ctx) <= 0 + || EVP_PKEY_fromdata(ctx, evpPublicKey, EVP_PKEY_PUBLIC_KEY, params) <= 0) { + goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Create ecc key", + error_cleanup); + } +error_cleanup: + EVP_PKEY_CTX_free(ctx); + OSSL_PARAM_free(params); + OSSL_PARAM_BLD_free(build); + OPENSSL_free(puboct); +#endif + OSSL_FREE(ecPoint, EC_POINT); + OSSL_FREE(ecgroup, EC_GROUP); + OSSL_FREE(y, BN); + OSSL_FREE(x, BN); + return r; +} + +TPM2_RC +get_rsa_ek_public(TSS2_SYS_CONTEXT *sys_context, EVP_PKEY **evp_pub) +{ + TSS2_RC rc; + TSS2L_SYS_AUTH_COMMAND auth_cmd = { + .auths = {{ .sessionHandle = TPM2_RH_PW }}, + .count = 1 + }; + TPM2B_SENSITIVE_CREATE in_sensitive = { 0 }; + TPM2B_PUBLIC in_public = { + .publicArea = { + .type = TPM2_ALG_RSA, + .nameAlg = TPM2_ALG_SHA256, + .objectAttributes = ( + TPMA_OBJECT_FIXEDTPM | + TPMA_OBJECT_FIXEDPARENT | + TPMA_OBJECT_SENSITIVEDATAORIGIN | + TPMA_OBJECT_ADMINWITHPOLICY | + TPMA_OBJECT_RESTRICTED | + TPMA_OBJECT_DECRYPT + ), + .authPolicy = { + .size = 32, + .buffer = 0x83, 0x71, 0x97, 0x67, 0x44, 0x84, + 0xB3, 0xF8, 0x1A, 0x90, 0xCC, 0x8D, + 0x46, 0xA5, 0xD7, 0x24, 0xFD, 0x52, + 0xD7, 0x6E, 0x06, 0x52, 0x0B, 0x64, + 0xF2, 0xA1, 0xDA, 0x1B, 0x33, 0x14, + 0x69, 0xAA, + }, + .parameters.rsaDetail = { + .symmetric = { + .algorithm = TPM2_ALG_AES, + .keyBits.aes = 128, + .mode.aes = TPM2_ALG_CFB, + }, + .scheme = { + .scheme = TPM2_ALG_NULL, + }, + .keyBits = 2048, + .exponent = 0, + }, + .unique.rsa = { + .size = 256, + .buffer = {0}, + } + } + }; + TPML_PCR_SELECTION creation_pcr = { 0 }; + TPM2_HANDLE handle; + TPM2B_PUBLIC out_public = { 0 }; + TSS2L_SYS_AUTH_RESPONSE auth_rsp = { + .count = 0 + }; + + /* Generate the EK key */ + + SYS_CALL(rc, Tss2_Sys_CreatePrimary, + sys_context, TPM2_RH_ENDORSEMENT, &auth_cmd, + &in_sensitive, &in_public, NULL, &creation_pcr, + &handle, &out_public, NULL, NULL, NULL, NULL, &auth_rsp); + + SYS_CALL(rc, Tss2_Sys_FlushContext, sys_context, handle); + + rc = rsa_pub_from_tpm(&out_public, evp_pub); + if (rc != TPM2_RC_SUCCESS) { + LOG_ERROR("Failed to create EVP key from RSA EK: 0x%"PRIx32, rc); + return rc; + } + + return TSS2_RC_SUCCESS; +} + +TSS2_RC +get_ecc_ek_public(TSS2_SYS_CONTEXT *sys_context, EVP_PKEY **evp_pub) +{ + TSS2_RC rc; + TSS2L_SYS_AUTH_COMMAND auth_cmd = { + .auths = {{ .sessionHandle = TPM2_RH_PW }}, + .count = 1 + }; + TPM2B_SENSITIVE_CREATE in_sensitive = { 0 }; + TPM2B_PUBLIC in_public = { + .publicArea = { + .type = TPM2_ALG_ECC, + .nameAlg = TPM2_ALG_SHA256, + .objectAttributes = ( + TPMA_OBJECT_FIXEDTPM | + TPMA_OBJECT_FIXEDPARENT | + TPMA_OBJECT_SENSITIVEDATAORIGIN | + TPMA_OBJECT_ADMINWITHPOLICY | + TPMA_OBJECT_RESTRICTED | + TPMA_OBJECT_DECRYPT + ), + .authPolicy = { + .size = 32, + .buffer = 0x83, 0x71, 0x97, 0x67, 0x44, 0x84, + 0xB3, 0xF8, 0x1A, 0x90, 0xCC, 0x8D, + 0x46, 0xA5, 0xD7, 0x24, 0xFD, 0x52, + 0xD7, 0x6E, 0x06, 0x52, 0x0B, 0x64, + 0xF2, 0xA1, 0xDA, 0x1B, 0x33, 0x14, + 0x69, 0xAA, + }, + .parameters.eccDetail = { + .symmetric = { + .algorithm = TPM2_ALG_AES, + .keyBits.aes = 128, + .mode.aes = TPM2_ALG_CFB, + }, + .scheme = { + .scheme = TPM2_ALG_NULL, + .details = { 0 } + }, + .curveID = TPM2_ECC_NIST_P256, + .kdf = {.scheme = TPM2_ALG_NULL, + .details = { 0 } + } + }, + .unique.ecc = { + .x = {.size = 32,.buffer = { 0 }}, + .y = {.size = 32,.buffer = { 0 }} + } + } + }; + TPML_PCR_SELECTION creation_pcr = { 0 }; + TPM2_HANDLE handle; + TPM2B_PUBLIC out_public = { 0 }; + TSS2L_SYS_AUTH_RESPONSE auth_rsp = { + .count = 0 + }; + SYS_CALL(rc, Tss2_Sys_CreatePrimary, + sys_context, TPM2_RH_ENDORSEMENT, &auth_cmd, + &in_sensitive, &in_public, NULL, &creation_pcr, + &handle, &out_public, NULL, NULL, NULL, NULL, &auth_rsp); + + + SYS_CALL(rc, Tss2_Sys_FlushContext, sys_context, handle); + + rc = ecc_pub_from_tpm(&out_public, evp_pub); + if (rc != TPM2_RC_SUCCESS) { + LOG_ERROR("Failed to create EVP key from ECC EK: 0x%"PRIx32, rc); + return rc; + } + + return TSS2_RC_SUCCESS; + +} + +char pwd[6] = "abcdef"; + +int pass_cb(char *buf, int size, int rwflag, void *u) +{ + (void)rwflag; + memcpy(buf, &pwd[0], 6); + return 6; +} + +TSS2_RC +nv_write(TSS2_SYS_CONTEXT *sys_context, TPMI_RH_NV_INDEX nvIndex, X509 *cert) +{ + TSS2_RC rc; + TSS2L_SYS_AUTH_COMMAND auth_cmd = { + .auths = {{ .sessionHandle = TPM2_RH_PW }}, + .count = 1 + }; + + if (!nvIndex) { + nvIndex = 0x01c00002; + } + + TPM2B_AUTH nv_auth = { 0 }; + TPM2B_NV_PUBLIC public_info = { + .nvPublic = { + .nameAlg = TPM2_ALG_SHA1, + .attributes = TPMA_NV_PPWRITE | TPMA_NV_AUTHREAD | TPMA_NV_OWNERREAD | + TPMA_NV_PLATFORMCREATE | TPMA_NV_NO_DA, + .dataSize = 0, + .nvIndex = nvIndex, + }, + }; + + TSS2L_SYS_AUTH_RESPONSE auth_rsp = { + .count = 0 + }; + TPM2B_MAX_NV_BUFFER buf1 = { 0 }; + TPM2B_MAX_NV_BUFFER buf2 = { 0 }; + unsigned char *cert_buf = NULL; + int cert_size; + + cert_size = i2d_X509(cert, &cert_buf); + if (cert_size < 0) { + LOG_ERROR("Certificate buffer can't be created."); + return TSS2_FAPI_RC_GENERAL_FAILURE; + } + if (buf1.size >= sizeof(buf1.buffer)) { + LOG_ERROR("Certificate to large"); + return TSS2_FAPI_RC_GENERAL_FAILURE; + } + buf1.size = cert_size; + memcpy(&buf1.buffer[0], cert_buf, cert_size); + free(cert_buf); + + /* First make sure that not EK certificate is currently loaded */ + LOG_WARNING("Cert input size is %"PRIu16, buf1.size); + public_info.nvPublic.dataSize = buf1.size; + + LOG_WARNING("Define NV cert with nv index: %x", public_info.nvPublic.nvIndex); + + SYS_CALL(rc, Tss2_Sys_NV_DefineSpace, + sys_context, TPM2_RH_PLATFORM, &auth_cmd, + &nv_auth, &public_info, &auth_rsp); + + /* Split the input buffer into 2 chunks */ + buf2.size = buf1.size; + buf1.size /= 2; + buf2.size -= buf1.size; + memcpy(&buf2.buffer[0], &buf1.buffer[buf1.size], buf2.size); + + SYS_CALL(rc, Tss2_Sys_NV_Write, sys_context, TPM2_RH_PLATFORM, nvIndex, &auth_cmd, + &buf1, 0, &auth_rsp); + + SYS_CALL(rc, Tss2_Sys_NV_Write, sys_context, TPM2_RH_PLATFORM, nvIndex, &auth_cmd, + &buf2, buf1.size, &auth_rsp); + + return TSS2_RC_SUCCESS; +} + +TSS2_RC +load_intermed_cert_and_key(const char *ca_key_path, EVP_PKEY **ca_key, + const char *ca_cert_path, X509 **ca_crt) +{ + BIO *bio = NULL; + *ca_crt = NULL; + *ca_key = NULL; + + /* Load the intermediate certificate */ + bio = BIO_new(BIO_s_file()); + if (!bio || !BIO_read_filename(bio, ca_cert_path)) { + LOG_ERROR("Failure in BIO_read_filename %s", ca_cert_path); + goto error_cleanup; + } + *ca_crt = PEM_read_bio_X509(bio, NULL, NULL, NULL); + if (!*ca_crt) { + LOG_ERROR("Could not read intermediate cert %s", ca_cert_path); + goto error_cleanup; + } + BIO_free_all(bio); + + /* Load the intermediate key. */ + bio = BIO_new(BIO_s_file()); + if (!bio || !BIO_read_filename(bio, ca_key_path)) { + LOG_ERROR("Failure in BIO_read_filename %s", ca_key_path); + goto error_cleanup; + } + *ca_key = PEM_read_bio_PrivateKey(bio, NULL, pass_cb, NULL); + if (!*ca_key) { + LOG_ERROR("Could not read intermediate key %s", ca_key_path); + goto error_cleanup; + } + BIO_free_all(bio); + return TSS2_RC_SUCCESS; + + error_cleanup: + BIO_free_all(bio); + X509_free(*ca_crt); + EVP_PKEY_free(*ca_key); + return TSS2_FAPI_RC_GENERAL_FAILURE; +} + +TSS2_RC +get_dummy_csr(EVP_PKEY **dmy_key, X509_REQ **req) +{ + *dmy_key = NULL; + *req = NULL; + EVP_PKEY_CTX *ctx = NULL; + + *dmy_key = NULL; + *req = X509_REQ_new(); + if (!*req) { + LOG_ERROR("Failed to allocate Memory for request"); + goto error_cleanup; + } + + ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL); + if (!ctx) { + LOG_ERROR("Failed to allocate Memory for PKEY context"); + goto error_cleanup; + } + + /* Create dummy key */ + + if (EVP_PKEY_keygen_init(ctx) <= 0 || + EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 2048) <= 0 || + EVP_PKEY_keygen(ctx, dmy_key) <= 0) { + LOG_ERROR("Failed to create key"); + goto error_cleanup; + } + + X509_REQ_set_pubkey(*req, *dmy_key); + + /* Self-sign the request to prove that we posses the key. */ + if (!X509_REQ_sign(*req, *dmy_key, EVP_sha256())) { + LOG_ERROR("Failed to sign request."); + goto error_cleanup; + } + EVP_PKEY_CTX_free(ctx); + return TSS2_RC_SUCCESS; + + error_cleanup: + if (dmy_key) + EVP_PKEY_free(*dmy_key); + if (req) + X509_REQ_free(*req); + if (ctx) + EVP_PKEY_CTX_free(ctx); + return TSS2_FAPI_RC_GENERAL_FAILURE; +} + +TSS2_RC +get_ek_certificate(EVP_PKEY *ca_key, X509 *ca_cert, + X509_REQ *req, + EVP_PKEY *ek, X509 **ek_cert) +{ + BIGNUM *bn = NULL; + unsigned char serial_ary[5] = { 0x01, 0x02, 0x03, 0x04, 0x05 }; + ASN1_INTEGER *serial_asn1 = NULL; + + *ek_cert = X509_new(); + if (!*ek_cert) { + LOG_ERROR("Failed to allocate Memory for PKEY context"); + goto error_cleanup; + } + if (X509_set_version(*ek_cert, 2) <= 0) goto error_cleanup; + bn = BN_new(); + if (!bn) { + LOG_ERROR("Failed to allocate BN"); + goto error_cleanup; + } + BN_bin2bn(&serial_ary[0], sizeof(serial_ary), bn); + serial_asn1 = ASN1_INTEGER_new(); + if (!serial_asn1) { + LOG_ERROR("Failed to allocate ASN1 serial."); + goto error_cleanup; + } + + BN_to_ASN1_INTEGER(bn, serial_asn1); + + if (X509_set_serialNumber(*ek_cert, serial_asn1) <= 0 || + X509_set_issuer_name(*ek_cert, X509_get_subject_name(ca_cert)) <= 0) { + LOG_ERROR("Failed to initialize EK cert."); + goto error_cleanup; + } + + X509_gmtime_adj(X509_get_notBefore(*ek_cert), 0); + X509_gmtime_adj(X509_get_notAfter(*ek_cert), (long)3*365*24*3600); + + ASN1_INTEGER_free(serial_asn1); + BN_free(bn); + + EVP_PKEY *req_pubkey = X509_REQ_get_pubkey(req); + if (X509_set_pubkey(*ek_cert, ek) <= 0) { + LOG_ERROR("Failed to set pubkey of EK cert."); + goto error_cleanup; + } + EVP_PKEY_free(req_pubkey); + + if (X509_sign(*ek_cert, ca_key, EVP_sha256()) == 0) { + LOG_ERROR("Failed to sign certificate."); + goto error_cleanup; + } + X509_REQ_free(req); + return TSS2_RC_SUCCESS; + + error_cleanup: + X509_REQ_free(req); + if (bn) + BN_free(bn); + if (serial_asn1) + ASN1_INTEGER_free(serial_asn1); + if (*ek_cert) + X509_free(*ek_cert); + return TSS2_FAPI_RC_GENERAL_FAILURE; +} + +TSS2_RC +get_pubkey_fingerprint(EVP_PKEY *key, char **fingerprint) +{ + TPM2_RC rc = TSS2_FAPI_RC_GENERAL_FAILURE; + size_t size_der_pub; + unsigned char *der_key = NULL; + BUF_MEM *bio_mem_data = NULL; +#if OPENSSL_VERSION_NUMBER < 0x30000000L + SHA256_CTX sha256_context; +#else + size_t size_hash; +#endif + unsigned char fingerprint_digest[TPM2_SHA256_DIGEST_SIZE]; + + BIO *bio_mem = BIO_new(BIO_s_mem()); + if (!bio_mem) { + LOG_ERROR("Failed to allocate BIO."); + return TSS2_FAPI_RC_GENERAL_FAILURE; + } + if (i2d_PUBKEY_bio(bio_mem, key) == 0) { + LOG_ERROR("Failed to get public key."); + return TSS2_FAPI_RC_GENERAL_FAILURE; + } + BIO_get_mem_ptr(bio_mem, &bio_mem_data); + der_key = (unsigned char *)bio_mem_data->data; + size_der_pub = bio_mem_data->length; + +#if OPENSSL_VERSION_NUMBER < 0x30000000L + if (SHA256_Init(&sha256_context) == 0 || + SHA256_Update(&sha256_context, der_key, size_der_pub) == 0 || + SHA256_Final(&fingerprint_digest[0], &sha256_context) == 0) { + LOG_ERROR("sha256 update failed."); + goto error_cleanup; + } +#else + if (EVP_Q_digest(NULL, "sha256", NULL, der_key, size_der_pub, + &fingerprint_digest[0], &size_hash) == 0) { + LOG_ERROR("sha256 update failed."); + goto error_cleanup; + } +#endif + *fingerprint = calloc(TPM2_SHA256_DIGEST_SIZE * 2 + 1, 1); + if (!(*fingerprint)) { + LOG_ERROR("Failed to allocate fingerprint."); + goto error_cleanup; + } + char *pf = &(*fingerprint)[0]; + for (size_t i = 0; i < TPM2_SHA256_DIGEST_SIZE; i++) { + pf += sprintf(pf, "%.2x", fingerprint_digest[i]); + } + rc = TSS2_RC_SUCCESS; + + error_cleanup: + if (bio_mem) + BIO_free_all(bio_mem); + return rc; + } + +TSS2_RC +get_ek_fingerprints(TSS2_SYS_CONTEXT *sys_ctx, + char **rsa_fingerprint, char **ecc_fingerprint) +{ + TSS2_RC rc; + EVP_PKEY *ecc_ek_key_pub = NULL; + EVP_PKEY *rsa_ek_key_pub = NULL; + + rc = get_ecc_ek_public(sys_ctx, &ecc_ek_key_pub); + if (rc != TSS2_RC_SUCCESS) { + LOG_ERROR("Failed to get ECC EK: %s\n", Tss2_RC_Decode(rc)); + goto error_cleanup; + } + rc = get_pubkey_fingerprint(ecc_ek_key_pub, ecc_fingerprint); + if (rc != TSS2_RC_SUCCESS) { + goto error_cleanup; + } + + rc = get_rsa_ek_public(sys_ctx, &rsa_ek_key_pub); + if (rc != TSS2_RC_SUCCESS) { + LOG_ERROR("Failed to get RSA EK: %s\n", Tss2_RC_Decode(rc)); + goto error_cleanup; + } + + rc = get_pubkey_fingerprint(rsa_ek_key_pub, rsa_fingerprint); + if (rc != TSS2_RC_SUCCESS) { + SAFE_FREE(*ecc_fingerprint); + goto error_cleanup; + } + + error_cleanup: + if (ecc_ek_key_pub) + EVP_PKEY_free(ecc_ek_key_pub); + if (rsa_ek_key_pub) + EVP_PKEY_free(rsa_ek_key_pub); + return rc; +} + +TSS2_RC +prepare_certificate(TSS2_SYS_CONTEXT *sys_ctx, X509 *ek_cert, + TPM2_NV_INDEX nv_index, char* env_var) { + TSS2_RC rc; + +#if defined(FAPI_TEST_CERTIFICATE) || defined(FAPI_TEST_CERTIFICATE_ECC) + char *pem_filename; + FILE *output_file; + // (void)nv_idex; + (void)sys_ctx; + + pem_filename = getenv(env_var); + if (!pem_filename) { + LOG_ERROR("Environment variable FAPI_TEST_CERTIFICATE_ECC not set."); + rc = TSS2_FAPI_RC_GENERAL_FAILURE; + goto error_cleanup; + } + output_file = fopen(pem_filename, "w"); + if (!output_file) { + LOG_ERROR("Error opening output file: %s", pem_filename); + rc = TSS2_FAPI_RC_GENERAL_FAILURE; + goto error_cleanup; + } + if (PEM_write_X509(output_file, ek_cert) != 1) { + perror("Error writing X.509 certificate to file"); + fclose(output_file); + rc = TSS2_FAPI_RC_GENERAL_FAILURE; + goto error_cleanup; + } + fclose(output_file); +#else + // (void)env_var; + + rc = nv_write(sys_ctx, nv_index, ek_cert); + if (rc != TSS2_RC_SUCCESS) { + LOG_ERROR("Failed to write ECC EK cert."); + goto error_cleanup; + } +#endif + rc = TSS2_RC_SUCCESS; + + error_cleanup: + return rc; +} + +TSS2_RC +init_ek_certificates(TSS2_SYS_CONTEXT *sys_ctx) +{ + TSS2_RC rc; + X509_REQ *req = NULL; + EVP_PKEY *dmy_key = NULL; + X509 *ecc_ek_cert = NULL; + EVP_PKEY *ecc_ek_key_pub = NULL; + X509 *rsa_ek_cert = NULL; + EVP_PKEY *rsa_ek_key_pub = NULL; + X509 *intermed_cert = NULL; + EVP_PKEY *intermed_key = NULL; + + rc = get_ecc_ek_public(sys_ctx, &ecc_ek_key_pub); + if (rc != TSS2_RC_SUCCESS) { + LOG_ERROR("Failed to get ECC EK: %s\n", Tss2_RC_Decode(rc)); + goto error_cleanup; + } + + rc = get_rsa_ek_public(sys_ctx, &rsa_ek_key_pub); + if (rc != TSS2_RC_SUCCESS) { + LOG_ERROR("Failed to get RSA EK: %s\n", Tss2_RC_Decode(rc)); + goto error_cleanup; + } + + rc = load_intermed_cert_and_key("ca/intermed-ca/private/intermed-ca.key.pem", + &intermed_key, + "ca/intermed-ca/intermed-ca.cert.pem", + &intermed_cert); + if (rc != TSS2_RC_SUCCESS) { + LOG_ERROR("Failed to load intermediate key and cert %s\n", Tss2_RC_Decode(rc)); + goto error_cleanup; + } + + rc = get_dummy_csr(&dmy_key, &req); + if (rc != TSS2_RC_SUCCESS) { + LOG_ERROR("Failed to get req: %s\n", Tss2_RC_Decode(rc)); + goto error_cleanup; + } + + rc = get_ek_certificate(intermed_key, intermed_cert, req, + ecc_ek_key_pub, &ecc_ek_cert); + if (rc != TSS2_RC_SUCCESS) { + LOG_ERROR("Failed to get ECC EK cert."); + goto error_cleanup; + } + + rc = prepare_certificate(sys_ctx, ecc_ek_cert, 0x1c0000a, + "FAPI_TEST_CERTIFICATE_ECC"); + if (rc != TSS2_RC_SUCCESS) { + LOG_ERROR("Failed to prepare ECC EK cert."); + goto error_cleanup; + } + + EVP_PKEY_free(dmy_key); + dmy_key = NULL; + X509_REQ_free(req); + req = NULL; + + rc = get_dummy_csr(&dmy_key, &req); + if (rc != TSS2_RC_SUCCESS) { + LOG_ERROR("Failed to get req: %s\n", Tss2_RC_Decode(rc)); + goto error_cleanup; + } + + rc = get_ek_certificate(intermed_key, intermed_cert, req, + rsa_ek_key_pub, &rsa_ek_cert); + if (rc != TSS2_RC_SUCCESS) { + LOG_ERROR("Failed to get RSA EK cert."); + goto error_cleanup; + } + + rc = prepare_certificate(sys_ctx, rsa_ek_cert, 0x1c00002, + "FAPI_TEST_CERTIFICATE"); + if (rc != TSS2_RC_SUCCESS) { + LOG_ERROR("Failed to prepare RSA EK cert."); + goto error_cleanup; + } + + rc = TSS2_RC_SUCCESS; + + error_cleanup: + if (req) + X509_REQ_free(req); + if (rsa_ek_cert) + X509_free(rsa_ek_cert); + if (ecc_ek_cert) + X509_free(ecc_ek_cert); + if (dmy_key) + EVP_PKEY_free(dmy_key); + if (ecc_ek_key_pub) + EVP_PKEY_free(ecc_ek_key_pub); + if (rsa_ek_key_pub) + EVP_PKEY_free(rsa_ek_key_pub); + if (intermed_cert) + X509_free(intermed_cert); + if (intermed_key) + EVP_PKEY_free(intermed_key); + + return rc; +} int test_fapi_setup(TSS2_TEST_FAPI_CONTEXT **test_ctx) @@ -530,20 +1411,67 @@ main(int argc, char *argv[]) char *remove_cmd = NULL; TSS2_TEST_FAPI_CONTEXT *test_ctx = NULL; + TSS2_TEST_ESYS_CONTEXT *test_esys_ctx; + + ret = test_esys_setup(&test_esys_ctx); + if (ret != 0) { + return ret; + } +#if !defined(FAPI_NONTPM) && !defined(DLOPEN) && defined(SELF_GENERATED_CERTIFICATE) && \ + !defined(FAPI_TEST_FINGERPRINT) && !defined(FAPI_TEST_FINGERPRINT_ECC) + TSS2_SYS_CONTEXT *sys_ctx; + TSS2_RC rc; + + rc = Esys_GetSysContext(test_esys_ctx->esys_ctx, &sys_ctx); + if (rc != TSS2_RC_SUCCESS) { + LOG_ERROR("Failed to get SysContext: %s\n", Tss2_RC_Decode(rc)); + ret = 1; + goto error; + } + rc = init_ek_certificates(sys_ctx); + if (rc != TSS2_RC_SUCCESS) { + LOG_ERROR("Failed to initialize EK certificates: %s\n", + Tss2_RC_Decode(rc)); + ret = 1; + goto error; + } +#else + char *ecc_fingerprint = NULL; + char *rsa_fingerprint = NULL; + TSS2_SYS_CONTEXT *sys_ctx; + TSS2_RC rc; + + rc = Esys_GetSysContext(test_esys_ctx->esys_ctx, &sys_ctx); + if (rc != TSS2_RC_SUCCESS) { + LOG_ERROR("Failed to get SysContext: %s\n", Tss2_RC_Decode(rc)); + return EXIT_ERROR; + } + + rc = get_ek_fingerprints(sys_ctx, &rsa_fingerprint, &ecc_fingerprint); + if (rc != TSS2_RC_SUCCESS) { + return EXIT_ERROR; + } + setenv("FAPI_TEST_FINGERPRINT", rsa_fingerprint, 1); + setenv("FAPI_TEST_FINGERPRINT_ECC", ecc_fingerprint, 1); + free(rsa_fingerprint); + free(ecc_fingerprint); +#endif + + test_esys_teardown(test_esys_ctx); + ret = test_fapi_setup(&test_ctx); if (ret != 0) { goto error; } #if !defined(FAPI_NONTPM) && !defined(DLOPEN) - ret = test_fapi_checks_pre(test_ctx); + ret = test_fapi_checks_pre(test_ctx); if (ret != 0) { goto error; } #endif ret = test_invoke_fapi(test_ctx->fapi_ctx); - LOG_INFO("Test returned %i", ret); if (ret) goto error; @@ -553,6 +1481,7 @@ main(int argc, char *argv[]) if (ret != 0) { goto error; } + #endif size = asprintf(&remove_cmd, "rm -r -f %s", test_ctx->tmpdir); diff --git a/test/integration/test-common.c b/test/integration/test-common.c index ba2ded1e6..304b5595c 100644 --- a/test/integration/test-common.c +++ b/test/integration/test-common.c @@ -568,8 +568,6 @@ test_fapi_checks_post(TSS2_TEST_FAPI_CONTEXT *test_ctx) return test_esys_checks_post(&test_ctx->test_esys_ctx); } - - void test_esys_teardown(TSS2_TEST_ESYS_CONTEXT *test_ctx) { @@ -582,3 +580,14 @@ test_esys_teardown(TSS2_TEST_ESYS_CONTEXT *test_ctx) free(test_ctx); } } + +void +test_fapi_esys_teardown(TSS2_TEST_ESYS_CONTEXT *test_ctx) +{ + if (test_ctx) { + Esys_Finalize(&test_ctx->esys_ctx); + Tss2_Tcti_Finalize(test_ctx->tcti_proxy_ctx); + free(test_ctx->tcti_proxy_ctx); + Tss2_TctiLdr_Finalize(&test_ctx->tcti_ctx); + } +} diff --git a/test/integration/test-common.h b/test/integration/test-common.h index ca1a65543..8c16b897f 100644 --- a/test/integration/test-common.h +++ b/test/integration/test-common.h @@ -67,5 +67,7 @@ int test_fapi_setup(TSS2_TEST_FAPI_CONTEXT **test_ctx); int test_fapi_checks_pre(TSS2_TEST_FAPI_CONTEXT *test_ctx); int test_fapi_checks_post(TSS2_TEST_FAPI_CONTEXT *test_ctx); void test_fapi_teardown(TSS2_TEST_FAPI_CONTEXT *test_ctx); +void test_esys_teardown(TSS2_TEST_ESYS_CONTEXT *test_ctx); + #endif /* TEST_COMMON_H */ diff --git a/test/integration/test-fapi.h b/test/integration/test-fapi.h index d654bd2fd..64fd972a0 100644 --- a/test/integration/test-fapi.h +++ b/test/integration/test-fapi.h @@ -21,7 +21,6 @@ #define ASSERT_SIZE 10 /* sanity check value for string outputs of Fapi commands */ - #define ASSERT(EXPR) \ if (!(EXPR)) { \ LOG_ERROR("Failed assertion: " #EXPR); \