| /* SPDX-License-Identifier: BSD-2-Clause */ |
| /******************************************************************************* |
| * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG |
| * All rights reserved. |
| *******************************************************************************/ |
| |
| #ifdef HAVE_CONFIG_H |
| #include <config.h> |
| #endif |
| |
| #include <stdlib.h> |
| #if (MAXLOGLEVEL == 0 && defined(NDEBUG)) |
| /* Need one of the other as some local variables |
| * are used in debug prints or assert calls only */ |
| #undef NDEBUG |
| #endif |
| |
| #include "tss2_esys.h" |
| #include "tss2_fapi.h" |
| |
| #include "test-fapi.h" |
| #include "fapi_util.h" |
| |
| #define LOGMODULE test |
| #include "util/log.h" |
| #include "util/aux_util.h" |
| |
| #define MIN_PLATFORM_CERT_HANDLE 0x01C08000 |
| #define CERTIFICATE_SIZE 15 |
| |
| /** Test the FAPI functions for platform certificates. |
| * |
| * Tested FAPI commands: |
| * - Fapi_Provision() |
| * - Fapi_GetPlatformCertificates() |
| * - Fapi_Delete() |
| * |
| * @param[in,out] context The FAPI_CONTEXT. |
| * @retval EXIT_FAILURE |
| * @retval EXIT_SUCCESS |
| */ |
| int |
| test_fapi_platform_certificates(FAPI_CONTEXT *context) |
| { |
| TSS2_RC r; |
| ESYS_TR nvHandle = ESYS_TR_NONE; |
| uint8_t *certs = NULL; |
| size_t certsSize = 0; |
| /* In case NV was already defined, do not delete it in clean up */ |
| bool nv_already_defined = false; |
| bool nv_newly_defined = false; |
| size_t nv_size = CERTIFICATE_SIZE; |
| |
| r = Fapi_Provision(context, NULL, NULL, NULL); |
| goto_if_error(r, "Error Fapi_Provision", error); |
| |
| TPM2_CAP capability = TPM2_CAP_HANDLES; |
| INT32 property = 0x1000000; |
| |
| UINT32 propertyCount = 254; |
| TPMI_YES_NO moreDataAvailable; |
| TPMS_CAPABILITY_DATA *capabilityData; |
| |
| capabilityData = NULL; |
| r = Esys_GetCapability(context->esys, |
| ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, |
| capability, property, |
| propertyCount, |
| &moreDataAvailable, |
| &capabilityData); |
| goto_if_error(r, "Error Esys_GetCapability", error); |
| |
| int count = capabilityData->data.handles.count; |
| for(int i = 0; i < count; i++){ |
| if(capabilityData->data.handles.handle[i] == MIN_PLATFORM_CERT_HANDLE){ |
| nv_already_defined = true; |
| break; |
| } |
| } |
| SAFE_FREE(capabilityData); |
| |
| if(nv_already_defined){ |
| TPM2B_NV_PUBLIC *nvPublic = NULL; |
| TPM2B_NAME *nvName = NULL; |
| r = Esys_NV_ReadPublic(context->esys, |
| nvHandle, |
| ESYS_TR_NONE, |
| ESYS_TR_NONE, |
| ESYS_TR_NONE, |
| &nvPublic, |
| &nvName); |
| goto_if_error(r, "Error: nv read public", error); |
| |
| LOG_INFO("nvPublic Size %d\n", nvPublic->nvPublic.dataSize); |
| |
| nv_size = nvPublic->nvPublic.dataSize; |
| LOG_INFO("NV size: %zu", nv_size); |
| } |
| |
| if(!nv_already_defined){ |
| |
| TPM2B_AUTH auth = { 0 }; |
| |
| TPM2B_NV_PUBLIC publicInfo = { |
| .nvPublic = { |
| .nameAlg = TPM2_ALG_SHA256, |
| .attributes = TPMA_NV_PPWRITE | TPMA_NV_AUTHREAD | |
| TPMA_NV_OWNERREAD | TPMA_NV_PLATFORMCREATE | TPMA_NV_NO_DA, |
| .dataSize = CERTIFICATE_SIZE, |
| .nvIndex = MIN_PLATFORM_CERT_HANDLE, |
| }, |
| }; |
| |
| r = Esys_NV_DefineSpace(context->esys, |
| ESYS_TR_RH_PLATFORM, |
| ESYS_TR_PASSWORD, |
| ESYS_TR_NONE, |
| ESYS_TR_NONE, |
| &auth, |
| &publicInfo, |
| &nvHandle); |
| |
| if (number_rc(r) == TPM2_RC_BAD_AUTH || |
| number_rc(r) == TPM2_RC_HIERARCHY) { |
| /* Platform authorization not possible test will be skipped */ |
| LOG_WARNING("Platform authorization not possible."); |
| goto skip; |
| } |
| |
| goto_if_error(r, "Error Esys_NV_DefineSpace", error); |
| |
| nv_newly_defined = true; |
| |
| TPM2B_MAX_NV_BUFFER nv_test_data = { .size = CERTIFICATE_SIZE, |
| .buffer={0x61, 0x61, 0x61, 0x61, 0x61, |
| 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, |
| 0x61, 0x61, 0x61, 0x61}}; |
| |
| r = Esys_NV_Write(context->esys, |
| ESYS_TR_RH_PLATFORM, |
| nvHandle, |
| ESYS_TR_PASSWORD, |
| ESYS_TR_NONE, |
| ESYS_TR_NONE, |
| &nv_test_data, |
| 0); |
| goto_if_error(r, "Error Esys_NV_Write", error); |
| } |
| |
| r = Fapi_GetPlatformCertificates(context, &certs, &certsSize); |
| if (r == TSS2_FAPI_RC_NO_CERT) |
| goto skip; |
| goto_if_error(r, "Error Fapi_GetPlatformCertificates", error); |
| ASSERT(certs != NULL); |
| ASSERT(certsSize == nv_size); |
| |
| Fapi_Free(certs); |
| |
| if(nv_newly_defined){ |
| r = Esys_NV_UndefineSpace(context->esys, |
| ESYS_TR_RH_PLATFORM, |
| nvHandle, |
| ESYS_TR_PASSWORD, |
| ESYS_TR_NONE, |
| ESYS_TR_NONE |
| ); |
| goto_if_error(r, "Error: NV_UndefineSpace", error); |
| } |
| |
| /* Cleanup */ |
| r = Fapi_Delete(context, "/"); |
| goto_if_error(r, "Error Fapi_Delete", error); |
| |
| return EXIT_SUCCESS; |
| |
| error: |
| if(nv_newly_defined){ |
| Esys_NV_UndefineSpace(context->esys, |
| ESYS_TR_RH_PLATFORM, nvHandle, |
| ESYS_TR_PASSWORD, ESYS_TR_NONE, |
| ESYS_TR_NONE); |
| } |
| Fapi_Delete(context, "/"); |
| return EXIT_FAILURE; |
| |
| skip: |
| if(nv_newly_defined){ |
| Esys_NV_UndefineSpace(context->esys, |
| ESYS_TR_RH_PLATFORM, nvHandle, |
| ESYS_TR_PASSWORD, ESYS_TR_NONE, |
| ESYS_TR_NONE); |
| } |
| Fapi_Delete(context, "/"); |
| return EXIT_SKIP; |
| } |
| |
| int |
| test_invoke_fapi(FAPI_CONTEXT *fapi_context) |
| { |
| return test_fapi_platform_certificates(fapi_context); |
| } |