diff --git a/script/fint-log-compiler.sh b/script/fint-log-compiler.sh index 7995c4303..d6cb30e6d 100755 --- a/script/fint-log-compiler.sh +++ b/script/fint-log-compiler.sh @@ -42,25 +42,6 @@ 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 INTERMEDCA_FILE=ca/intermed-ca/intermed-ca.cert ROOTCA_FILE=ca/root-ca/root-ca.cert @@ -72,6 +53,12 @@ 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 \ diff --git a/test/integration/main-fapi.c b/test/integration/main-fapi.c index 48692d153..038136f07 100644 --- a/test/integration/main-fapi.c +++ b/test/integration/main-fapi.c @@ -56,6 +56,15 @@ 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; @@ -268,7 +277,7 @@ 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, @@ -289,7 +298,7 @@ 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, @@ -310,7 +319,7 @@ 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, @@ -331,7 +340,7 @@ 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, @@ -350,7 +359,7 @@ 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 "", @@ -460,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); @@ -754,19 +765,12 @@ get_rsa_ek_public(TSS2_SYS_CONTEXT *sys_context, EVP_PKEY **evp_pub) /* Generate the EK key */ - 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); - if (rc != TSS2_RC_SUCCESS) { - LOG_ERROR("TPM CreatePrimary FAILED: 0x%"PRIx32, rc); - return rc; - } + 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); - rc = Tss2_Sys_FlushContext(sys_context, handle); - if (rc != TSS2_RC_SUCCESS) { - LOG_ERROR("TPM FlushContext FAILED: 0x%"PRIx32, rc); - return rc; - } + SYS_CALL(rc, Tss2_Sys_FlushContext, sys_context, handle); rc = rsa_pub_from_tpm(&out_public, evp_pub); if (rc != TPM2_RC_SUCCESS) { @@ -834,19 +838,13 @@ get_ecc_ek_public(TSS2_SYS_CONTEXT *sys_context, EVP_PKEY **evp_pub) TSS2L_SYS_AUTH_RESPONSE auth_rsp = { .count = 0 }; - 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); - if (rc != TSS2_RC_SUCCESS) { - LOG_ERROR("TPM CreatePrimary FAILED: 0x%"PRIx32, rc); - return rc; - } + 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); - rc = Tss2_Sys_FlushContext(sys_context, handle); - if (rc != TSS2_RC_SUCCESS) { - LOG_ERROR("TPM FlushContext FAILED: 0x%"PRIx32, rc); - return rc; - } + + SYS_CALL(rc, Tss2_Sys_FlushContext, sys_context, handle); rc = ecc_pub_from_tpm(&out_public, evp_pub); if (rc != TPM2_RC_SUCCESS) { @@ -918,12 +916,9 @@ nv_write(TSS2_SYS_CONTEXT *sys_context, TPMI_RH_NV_INDEX nvIndex, X509 *cert) LOG_WARNING("Define NV cert with nv index: %x", public_info.nvPublic.nvIndex); - rc = Tss2_Sys_NV_DefineSpace(sys_context, TPM2_RH_PLATFORM, &auth_cmd, - &nv_auth, &public_info, &auth_rsp); - if (rc != TSS2_RC_SUCCESS) { - LOG_ERROR("TPM NV DefineSpace FAILED: 0x%"PRIx32, rc); - return rc; - } + 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; @@ -931,19 +926,11 @@ nv_write(TSS2_SYS_CONTEXT *sys_context, TPMI_RH_NV_INDEX nvIndex, X509 *cert) buf2.size -= buf1.size; memcpy(&buf2.buffer[0], &buf1.buffer[buf1.size], buf2.size); - rc = Tss2_Sys_NV_Write(sys_context, TPM2_RH_PLATFORM, nvIndex, &auth_cmd, - &buf1, 0, &auth_rsp); - if (rc != TSS2_RC_SUCCESS) { - LOG_ERROR("TPM NV Write FAILED: 0x%"PRIx32, rc); - return rc; - } + SYS_CALL(rc, Tss2_Sys_NV_Write, sys_context, TPM2_RH_PLATFORM, nvIndex, &auth_cmd, + &buf1, 0, &auth_rsp); - rc = Tss2_Sys_NV_Write(sys_context, TPM2_RH_PLATFORM, nvIndex, &auth_cmd, - &buf2, buf1.size, &auth_rsp); - if (rc != TSS2_RC_SUCCESS) { - LOG_ERROR("TPM NV Write FAILED: 0x%"PRIx32, rc); - return rc; - } + SYS_CALL(rc, Tss2_Sys_NV_Write, sys_context, TPM2_RH_PLATFORM, nvIndex, &auth_cmd, + &buf2, buf1.size, &auth_rsp); return TSS2_RC_SUCCESS; } @@ -1105,6 +1092,147 @@ get_ek_certificate(EVP_PKEY *ca_key, X509 *ca_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) { @@ -1152,9 +1280,10 @@ init_ek_certificates(TSS2_SYS_CONTEXT *sys_ctx) goto error_cleanup; } - rc = nv_write(sys_ctx, 0x1c0000a, ecc_ek_cert); + rc = prepare_certificate(sys_ctx, ecc_ek_cert, 0x1c0000a, + "FAPI_TEST_CERTIFICATE_ECC"); if (rc != TSS2_RC_SUCCESS) { - LOG_ERROR("Failed to write ECC EK cert."); + LOG_ERROR("Failed to prepare ECC EK cert."); goto error_cleanup; } @@ -1176,9 +1305,10 @@ init_ek_certificates(TSS2_SYS_CONTEXT *sys_ctx) goto error_cleanup; } - rc = nv_write(sys_ctx, 0x1c00002, rsa_ek_cert); + rc = prepare_certificate(sys_ctx, rsa_ek_cert, 0x1c00002, + "FAPI_TEST_CERTIFICATE"); if (rc != TSS2_RC_SUCCESS) { - LOG_ERROR("Failed to write RSA EK cert."); + LOG_ERROR("Failed to prepare RSA EK cert."); goto error_cleanup; } @@ -1281,19 +1411,17 @@ main(int argc, char *argv[]) char *remove_cmd = NULL; TSS2_TEST_FAPI_CONTEXT *test_ctx = NULL; - ret = test_fapi_setup(&test_ctx); + TSS2_TEST_ESYS_CONTEXT *test_esys_ctx; + + ret = test_esys_setup(&test_esys_ctx); if (ret != 0) { - goto error; + return ret; } - -#if !defined(FAPI_NONTPM) && !defined(DLOPEN) -#ifdef SELF_GENERATED_CERTIFICATE +#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_ctx->fapi_ctx->esys, &sys_ctx); - + 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; @@ -1306,17 +1434,43 @@ main(int argc, char *argv[]) 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 - ret = test_fapi_checks_pre(test_ctx); + 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); + if (ret != 0) { + goto error; + } #endif ret = test_invoke_fapi(test_ctx->fapi_ctx); - LOG_INFO("Test returned %i", ret); if (ret) goto error; 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 */