From 30028257d5921486614fd06fcabf5a1f866cef6a Mon Sep 17 00:00:00 2001 From: Shrikant Temburwar Date: Mon, 13 Nov 2023 18:34:43 +0530 Subject: [PATCH 1/9] Add support to store device credentials and device status inside TPM NV storage Signed-off-by: Shrikant Temburwar --- app/blob.c | 1 + app/main.c | 21 +- cmake/blob_path.cmake | 16 +- lib/credentials_from_file.c | 299 +++++++++++++- lib/fdo.c | 5 +- lib/include/load_credentials.h | 8 + lib/prot/di/msg13.c | 5 + lib/prot/to2/msg70.c | 5 + network/network_if_linux.c | 21 +- storage/CMakeLists.txt | 6 + storage/include/storage_al.h | 9 + storage/include/tpm2_nv_storage.h | 64 +++ storage/linux/storage_if_linux.c | 504 ++++++++++++++++++++++++ storage/linux/tpm2_nv_storage.c | 633 ++++++++++++++++++++++++++++++ 14 files changed, 1573 insertions(+), 24 deletions(-) create mode 100644 storage/include/tpm2_nv_storage.h create mode 100644 storage/linux/tpm2_nv_storage.c diff --git a/app/blob.c b/app/blob.c index 55b75acc..7e12e434 100644 --- a/app/blob.c +++ b/app/blob.c @@ -36,6 +36,7 @@ #if defined(DEVICE_TPM20_ENABLED) #include "tpm20_Utils.h" #include "fdo_crypto.h" +#include "tpm2_nv_storage.h" #endif #if !defined(DEVICE_TPM20_ENABLED) diff --git a/app/main.c b/app/main.c index 695fe1ad..29ae2043 100644 --- a/app/main.c +++ b/app/main.c @@ -28,6 +28,10 @@ #include "cse_utils.h" #include "cse_tools.h" #endif +#if defined(DEVICE_TPM20_ENABLED) +#include "tpm20_Utils.h" +#include "fdo_crypto.h" +#endif #define STORAGE_NAMESPACE "storage" #define OWNERSHIP_TRANSFER_FILE "data/owner_transfer" @@ -273,13 +277,28 @@ int app_main(bool is_resale) #endif /* SECURE_ELEMENT */ #if !defined(DEVICE_CSE_ENABLED) - LOG(LOG_DEBUG, "CSE not enabled, Normal Blob Modules loaded!\n"); +#if defined(DEVICE_TPM20_ENABLED) + if (0 == is_valid_tpm_data_protection_key_present()) { + if (0 != fdo_generate_storage_hmac_key()) { + LOG(LOG_ERROR, "Failed to generate TPM data protection" + " key.\n"); + ret = -1; + goto end; + } + + LOG(LOG_DEBUG, + "TPM data protection key generated successfully.\n"); + } +#else + LOG(LOG_DEBUG, + "CSE and TPM not enabled, Normal Blob Modules loaded!\n"); if (-1 == configure_normal_blob()) { LOG(LOG_ERROR, "Provisioning Normal blob for the 1st time failed!\n"); ret = -1; goto end; } +#endif #endif /* List and Init all Sv_info modules */ diff --git a/cmake/blob_path.cmake b/cmake/blob_path.cmake index ec008ae1..0ec57d79 100644 --- a/cmake/blob_path.cmake +++ b/cmake/blob_path.cmake @@ -24,7 +24,7 @@ if(TARGET_OS MATCHES linux) -DDEVICE_CSE_ENABLED ) endif() - + if (${MTLS} MATCHES true) client_sdk_compile_definitions( -DSSL_CERT=\"${BLOB_PATH}/data/apiUser.pem\" @@ -176,9 +176,11 @@ if(TARGET_OS MATCHES linux) # Configure if needed at a later point # configure_file(${BLOB_PATH}/data/Normal.blob NEWLINE_STYLE DOS) -file(WRITE ${BLOB_PATH}/data/platform_iv.bin "") -file(WRITE ${BLOB_PATH}/data/platform_hmac_key.bin "") -file(WRITE ${BLOB_PATH}/data/platform_aes_key.bin "") -file(WRITE ${BLOB_PATH}/data/Normal.blob "") -file(WRITE ${BLOB_PATH}/data/Secure.blob "") -file(WRITE ${BLOB_PATH}/data/raw.blob "") +if (NOT ${DA} MATCHES tpm) + file(WRITE ${BLOB_PATH}/data/platform_iv.bin "") + file(WRITE ${BLOB_PATH}/data/platform_hmac_key.bin "") + file(WRITE ${BLOB_PATH}/data/platform_aes_key.bin "") + file(WRITE ${BLOB_PATH}/data/Normal.blob "") + file(WRITE ${BLOB_PATH}/data/Secure.blob "") + file(WRITE ${BLOB_PATH}/data/raw.blob "") +endif() diff --git a/lib/credentials_from_file.c b/lib/credentials_from_file.c index 597a4a0b..a7622361 100644 --- a/lib/credentials_from_file.c +++ b/lib/credentials_from_file.c @@ -21,10 +21,13 @@ #include "cse_utils.h" #include "cse_tools.h" #endif +#if defined(DEVICE_TPM20_ENABLED) +#include "tpm2_nv_storage.h" +#endif static bool validate_state(fdo_sdk_device_status current_status); -#if !defined(DEVICE_CSE_ENABLED) +#if !defined(DEVICE_CSE_ENABLED) && !defined(DEVICE_TPM20_ENABLED) /** * Write the Device Credentials blob, contains our state * @param dev_cred_file - pointer of type const char to which credentails are @@ -454,7 +457,6 @@ int store_credential(fdo_dev_cred_t *ocred) return -1; } -#if !defined(DEVICE_TPM20_ENABLED) /* Write in the file and save the Secure device credentials */ LOG(LOG_DEBUG, "Writing to %s blob\n", "Secure.blob"); if (!write_secure_device_credentials((char *)FDO_CRED_SECURE, @@ -462,8 +464,291 @@ int store_credential(fdo_dev_cred_t *ocred) LOG(LOG_ERROR, "Could not write to Secure Credentials blob\n"); return -1; } + + return 0; +} +#endif + +#if defined(DEVICE_TPM20_ENABLED) +/** + * Write the Device Credentials to nv, contains our state + * @param dev_cred_file - pointer of type const char to which credentails are + * to be written. + * @param flags + * @param ocred - pointer of type fdo_dev_cred_t, holds the credentials for + * writing to dev_cred_file. + * @return true if write and parsed correctly, otherwise false + */ + +bool write_tpm_device_credentials(uint32_t nv, fdo_sdk_blob_flags flags, + fdo_dev_cred_t *ocred) +{ + bool ret = true; + + if (!ocred || !nv) { + return false; + } +#ifndef NO_PERSISTENT_STORAGE + + fdow_t *fdow = fdo_alloc(sizeof(fdow_t)); + if (!fdow || !fdow_init(fdow) || + !fdo_block_alloc_with_size(&fdow->b, BUFF_SIZE_4K_BYTES) || + !fdow_encoder_init(fdow)) { + LOG(LOG_ERROR, "FDOW Initialization/Allocation failed!\n"); + ret = false; + goto end; + } + + /** + * Blob format: Complete DeviceCredential as per Section 3.4.1 of FDO + *Specification, except the DeviceCredential.DCHmacSecret, and addition + *of 'State'. DeviceCredential = [ State, DCActive, DCProtVer, + * DCDeviceInfo, + * DCGuid, + * DCRVInfo, + * DCPubKeyHash + * ] + */ + fdow_next_block(fdow, FDO_DI_SET_CREDENTIALS); + if (!fdow_start_array(fdow, 7)) { + ret = false; + goto end; + } + if (!fdow_signed_int(fdow, ocred->ST)) { + ret = false; + goto end; + } + if (!fdow_boolean(fdow, true)) { + ret = false; + goto end; + } + if (!fdow_signed_int(fdow, ocred->owner_blk->pv)) { + ret = false; + goto end; + } + + if (!fdow_text_string(fdow, ocred->mfg_blk->d->bytes, + ocred->mfg_blk->d->byte_sz)) { + ret = false; + goto end; + } + if (!fdow_byte_string(fdow, ocred->owner_blk->guid->bytes, + ocred->owner_blk->guid->byte_sz)) { + ret = false; + goto end; + } + if (!fdo_rendezvous_list_write(fdow, ocred->owner_blk->rvlst)) { + ret = false; + goto end; + } + if (!fdo_hash_write(fdow, ocred->owner_blk->pkh)) { + ret = false; + goto end; + } + if (!fdow_end_array(fdow)) { + ret = false; + goto end; + } + size_t encoded_cred_length = 0; + if (!fdow_encoded_length(fdow, &encoded_cred_length) || + encoded_cred_length == 0) { + LOG(LOG_ERROR, + "Failed to get DeviceCredential encoded length\n"); + ret = false; + goto end; + } + fdow->b.block_size = encoded_cred_length; + + if (fdo_blob_write_nv(nv, flags, fdow->b.block, fdow->b.block_size) == + -1) { + LOG(LOG_ERROR, "Failed to write DeviceCredential blob\n"); + ret = false; + goto end; + } + +end: + if (fdow) { + fdow_flush(fdow); + fdo_free(fdow); + } #endif + return ret; +} + +/** + * Read the Device Credentials blob from tpm nv, contains our state & owner_blk + * @param dev_cred_file - the blob the credentials are saved in + * @param flags - descriptor telling type of file + * @param our_dev_cred - pointer to the device credentials block, + * @return true if read and parsed correctly, otherwise false. + */ +bool read_tpm_device_credentials(uint32_t nv, fdo_sdk_blob_flags flags, + fdo_dev_cred_t *our_dev_cred) +{ + bool ret = false; + size_t dev_cred_len = 0; + fdor_t *fdor = NULL; + int dev_state = -1; + + if (!nv || !our_dev_cred) { + LOG(LOG_ERROR, "Invalid params\n"); + return false; + } + + if (our_dev_cred->owner_blk != NULL) { + fdo_cred_owner_free(our_dev_cred->owner_blk); + our_dev_cred->owner_blk = NULL; + } + + /* Memory allocating data.inside dev_cred. */ + our_dev_cred->owner_blk = fdo_cred_owner_alloc(); + if (!our_dev_cred->owner_blk) { + LOG(LOG_ERROR, "dev_cred's owner_blk allocation failed\n"); + goto end; + } + + dev_cred_len = fdo_blob_size_nv(nv, flags); + // Device has not yet been initialized. + // Since, Normal.blob is empty, the file size will be 0 + if (dev_cred_len == 0) { + LOG(LOG_DEBUG, + "DeviceCredential not found. Proceeding with DI\n"); + our_dev_cred->ST = FDO_DEVICE_STATE_PC; + return true; + } + + LOG(LOG_DEBUG, "Reading DeviceCredential blob of length %" PRIu64 "\n", + dev_cred_len); + + fdor = fdo_alloc(sizeof(fdor_t)); + if (!fdor || !fdor_init(fdor) || + !fdo_block_alloc_with_size(&fdor->b, dev_cred_len)) { + LOG(LOG_ERROR, "FDOR Initialization/Allocation failed!\n"); + goto end; + } + + if (fdo_blob_read_nv(nv, flags, fdor->b.block, fdor->b.block_size) == + -1) { + LOG(LOG_ERROR, + "Failed to read DeviceCredential blob : Normal.blob\n"); + goto end; + } + + if (!fdor_parser_init(fdor)) { + LOG(LOG_ERROR, "FDOR Parser Initialization failed!\n"); + goto end; + } + + if (!fdor_start_array(fdor)) { + LOG(LOG_ERROR, + "DeviceCredential read: Begin Array not found\n"); + goto end; + } + + if (!fdor_signed_int(fdor, &dev_state)) { + LOG(LOG_ERROR, "DeviceCredential read: ST not found\n"); + goto end; + } + our_dev_cred->ST = dev_state; + + if (!validate_state(our_dev_cred->ST)) { + LOG(LOG_ERROR, "DeviceCredential read: Invalid ST\n"); + goto end; + } + + if (!fdor_boolean(fdor, &our_dev_cred->dc_active)) { + LOG(LOG_ERROR, "DeviceCredential read: DCActive not found\n"); + goto end; + } + + if (!fdor_signed_int(fdor, &our_dev_cred->owner_blk->pv)) { + LOG(LOG_ERROR, "DeviceCredential read: DCProtVer not found\n"); + goto end; + } + + size_t device_info_length = 0; + if (!fdor_string_length(fdor, &device_info_length) || + device_info_length == 0) { + LOG(LOG_ERROR, + "DeviceCredential read: Invalid DCDeviceInfo length\n"); + goto end; + } + + our_dev_cred->mfg_blk = fdo_cred_mfg_alloc(); + if (!our_dev_cred->mfg_blk) { + LOG(LOG_ERROR, + "DeviceCredential read: Malloc for DCDeviceInfo failed"); + goto end; + } + + our_dev_cred->mfg_blk->d = fdo_string_alloc_size(device_info_length); + if (!our_dev_cred->mfg_blk->d || + !fdor_text_string(fdor, our_dev_cred->mfg_blk->d->bytes, + our_dev_cred->mfg_blk->d->byte_sz)) { + LOG(LOG_ERROR, + "DeviceCredential read: DCDeviceInfo not found\n"); + goto end; + } + our_dev_cred->mfg_blk->d->bytes[device_info_length] = '\0'; + + size_t guid_length = 0; + if (!fdor_string_length(fdor, &guid_length) || guid_length == 0) { + LOG(LOG_ERROR, + "DeviceCredential read: Invalid DCGuid length\n"); + goto end; + } + our_dev_cred->owner_blk->guid = fdo_byte_array_alloc(guid_length); + if (!our_dev_cred->owner_blk->guid || + !fdor_byte_string(fdor, our_dev_cred->owner_blk->guid->bytes, + our_dev_cred->owner_blk->guid->byte_sz)) { + LOG(LOG_ERROR, "DeviceCredential read: DCGuid not found\n"); + goto end; + } + + our_dev_cred->owner_blk->rvlst = fdo_rendezvous_list_alloc(); + if (!our_dev_cred->owner_blk->rvlst || + !fdo_rendezvous_list_read(fdor, our_dev_cred->owner_blk->rvlst)) { + LOG(LOG_ERROR, "DeviceCredential read: DCRVInfo not found\n"); + goto end; + } + + our_dev_cred->owner_blk->pkh = + fdo_hash_alloc(FDO_CRYPTO_HASH_TYPE_USED, FDO_SHA_DIGEST_SIZE_USED); + if (!our_dev_cred->owner_blk->pkh || + !fdo_hash_read(fdor, our_dev_cred->owner_blk->pkh)) { + LOG(LOG_ERROR, + "DeviceCredential read: DCPubKeyHash not found\n"); + goto end; + } + + if (!fdor_end_array(fdor)) { + LOG(LOG_ERROR, "DeviceCredential read: End Array not found\n"); + goto end; + } + ret = true; +end: + if (fdor) { + fdor_flush(fdor); + fdo_free(fdor); + } + return ret; +} +/** + * Write and save the device credentials passed as an parameter ocred of type + * fdo_dev_cred_t. + * @param ocred - Pointer of type fdo_dev_cred_t, credentials to be copied + * @return 0 if success, else -1 on failure. + */ +int store_tpm_credential(fdo_dev_cred_t *ocred) +{ + /* Write in the file and save the Normal device credentials */ + LOG(LOG_DEBUG, "Writing to TPm NV storage\n"); + if (!write_tpm_device_credentials(FDO_CRED_NORMAL_NV_IDX, + FDO_SDK_NORMAL_DATA, ocred)) { + LOG(LOG_ERROR, "Could not write to Normal Credentials blob\n"); + return -1; + } return 0; } #endif @@ -627,6 +912,13 @@ int load_credential(fdo_dev_cred_t *ocred) "Could not parse the Device Credentials form CSE\n"); return -1; } +#elif defined(DEVICE_TPM20_ENABLED) + /* Read in the blob and save the device credentials */ + if (!read_tpm_device_credentials(FDO_CRED_NORMAL_NV_IDX, + FDO_SDK_NORMAL_DATA, ocred)) { + LOG(LOG_ERROR, "Could not parse the Device Credentials blob\n"); + return -1; + } #else /* Read in the blob and save the device credentials */ if (!read_normal_device_credentials((char *)FDO_CRED_NORMAL, @@ -684,6 +976,9 @@ bool load_device_status(fdo_sdk_device_status *state) "DeviceCredential read: Unable to load file form CSE\n"); return false; } +#elif defined(DEVICE_TPM20_ENABLED) + size_t dev_cred_len = + fdo_blob_size_nv(FDO_CRED_NORMAL_NV_IDX, FDO_SDK_NORMAL_DATA); #else size_t dev_cred_len = fdo_blob_size((char *)FDO_CRED_NORMAL, FDO_SDK_NORMAL_DATA); diff --git a/lib/fdo.c b/lib/fdo.c index 737f9998..aefd0cba 100644 --- a/lib/fdo.c +++ b/lib/fdo.c @@ -1160,8 +1160,11 @@ fdo_sdk_status fdo_sdk_resale(void) LOG(LOG_ERROR, "Reading {Mfg|Secret} blob failied!\n"); return FDO_ERROR; } - +#if defined(DEVICE_TPM20_ENABLED) + ret = store_tpm_credential(g_fdo_data->devcred); +#else ret = store_credential(g_fdo_data->devcred); +#endif #endif if (!ret) { LOG(LOG_INFO, "Set Resale complete\n"); diff --git a/lib/include/load_credentials.h b/lib/include/load_credentials.h index 8e3ecd95..78877652 100644 --- a/lib/include/load_credentials.h +++ b/lib/include/load_credentials.h @@ -32,4 +32,12 @@ int store_credential(fdo_dev_cred_t *ocred); bool load_device_status(fdo_sdk_device_status *state); bool store_device_status(fdo_sdk_device_status *state); +#if defined(DEVICE_TPM20_ENABLED) +bool read_tpm_device_credentials(uint32_t nv, fdo_sdk_blob_flags flags, + fdo_dev_cred_t *our_dev_cred); +bool write_tpm_device_credentials(uint32_t nv, fdo_sdk_blob_flags flags, + fdo_dev_cred_t *our_dev_cred); +int store_tpm_credential(fdo_dev_cred_t *ocred); +#endif + #endif /* __LOAD_CREDENTIALS_H__ */ diff --git a/lib/prot/di/msg13.c b/lib/prot/di/msg13.c index 5d2fe429..5ff4bf0a 100644 --- a/lib/prot/di/msg13.c +++ b/lib/prot/di/msg13.c @@ -84,6 +84,11 @@ int32_t msg13(fdo_prot_t *ps) return -1; } LOG(LOG_DEBUG, "FDO OVH COMMIT succeeded %u\n", fdo_status); +#elif defined(DEVICE_TPM20_ENABLED) + if (store_tpm_credential(ps->dev_cred) != 0) { + LOG(LOG_ERROR, "TO2.Done: Failed to store new device creds\n"); + goto err; + } #else if (store_credential(ps->dev_cred) != 0) { LOG(LOG_ERROR, "Failed to store updated device credentials\n"); diff --git a/lib/prot/to2/msg70.c b/lib/prot/to2/msg70.c index b9e3e1c6..7be9e029 100644 --- a/lib/prot/to2/msg70.c +++ b/lib/prot/to2/msg70.c @@ -124,6 +124,11 @@ int32_t msg70(fdo_prot_t *ps) goto err; } LOG(LOG_DEBUG, "TO2.Done: FDO OVH COMMIT succeeded %u\n", fdo_status); +#elif defined(DEVICE_TPM20_ENABLED) + if (store_tpm_credential(ps->dev_cred) != 0) { + LOG(LOG_ERROR, "TO2.Done: Failed to store new device creds\n"); + goto err; + } #else if (store_credential(ps->dev_cred) != 0) { LOG(LOG_ERROR, "TO2.Done: Failed to store new device creds\n"); diff --git a/network/network_if_linux.c b/network/network_if_linux.c index 47658b85..74487900 100644 --- a/network/network_if_linux.c +++ b/network/network_if_linux.c @@ -365,7 +365,7 @@ int32_t fdo_curl_connect(fdo_ip_address_t *ip_addr, const char *dn, if (CURL_VERSION_SSL == (vinfo->features & CURL_VERSION_SSL)) { // SSL support enabled - LOG(LOG_INFO, "SSL support verified.\n"); + LOG(LOG_DEBUG, "SSL support verified.\n"); } // Add option to force the https TLS connection to TLS @@ -404,8 +404,8 @@ int32_t fdo_curl_connect(fdo_ip_address_t *ip_addr, const char *dn, "verify host.\n"); goto err; } - LOG(LOG_INFO, "Set connection for self signed " - "certificate usage.\n"); + LOG(LOG_DEBUG, "Set connection for self signed " + "certificate usage.\n"); } #endif curlCode = curl_easy_setopt(curl, CURLOPT_USE_SSL, @@ -471,8 +471,7 @@ int32_t fdo_curl_connect(fdo_ip_address_t *ip_addr, const char *dn, curlCode = curl_easy_setopt(curl, CURLOPT_URL, url); if (curlCode != CURLE_OK) { - LOG(LOG_ERROR, - "CURL_ERROR: Unable to pass url.\n"); + LOG(LOG_ERROR, "CURL_ERROR: Unable to pass url.\n"); goto err; } @@ -893,8 +892,7 @@ int32_t fdo_con_send_recv_message(uint32_t protocol_version, curlCode = curl_easy_setopt(curl, CURLOPT_SSLKEY, (char *)SSL_KEY); if (curlCode != CURLE_OK) { - LOG(LOG_ERROR, - "CURL_ERROR: Unable to select client key.\n"); + LOG(LOG_ERROR, "CURL_ERROR: Unable to select client key.\n"); goto err; } #endif @@ -925,8 +923,7 @@ int32_t fdo_con_send_recv_message(uint32_t protocol_version, curlCode = curl_easy_setopt(curl, CURLOPT_POSTFIELDS, buf); if (curlCode != CURLE_OK) { - LOG(LOG_ERROR, - "CURL_ERROR: Unable to pass POST data.\n"); + LOG(LOG_ERROR, "CURL_ERROR: Unable to pass POST data.\n"); goto err; } @@ -957,8 +954,7 @@ int32_t fdo_con_send_recv_message(uint32_t protocol_version, curlCode = curl_easy_setopt(curl, CURLOPT_HEADERDATA, (void *)&temp_header_buf); if (curlCode != CURLE_OK) { - LOG(LOG_ERROR, - "CURL_ERROR: Unable to pass header buffer.\n"); + LOG(LOG_ERROR, "CURL_ERROR: Unable to pass header buffer.\n"); goto err; } @@ -973,8 +969,7 @@ int32_t fdo_con_send_recv_message(uint32_t protocol_version, curlCode = curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&temp_body_buf); if (curlCode != CURLE_OK) { - LOG(LOG_ERROR, - "CURL_ERROR: Unable to pass body buffer.\n"); + LOG(LOG_ERROR, "CURL_ERROR: Unable to pass body buffer.\n"); goto err; } diff --git a/storage/CMakeLists.txt b/storage/CMakeLists.txt index 191ffdb6..94fab877 100644 --- a/storage/CMakeLists.txt +++ b/storage/CMakeLists.txt @@ -16,4 +16,10 @@ client_sdk_sources_with_lib( storage util.c ) +if (${DA} MATCHES tpm) + client_sdk_sources_with_lib( storage + linux/tpm2_nv_storage.c + ) +endif() + target_link_libraries(storage PUBLIC client_sdk_interface) diff --git a/storage/include/storage_al.h b/storage/include/storage_al.h index 7b2e7fa0..ae3f6523 100644 --- a/storage/include/storage_al.h +++ b/storage/include/storage_al.h @@ -46,6 +46,15 @@ size_t fdo_blob_size(const char *blob_name, fdo_sdk_blob_flags flags); int32_t create_hmac_normal_blob(void); +#if defined(DEVICE_TPM20_ENABLED) +int32_t fdo_blob_read_nv(uint32_t nv, fdo_sdk_blob_flags flags, uint8_t *buffer, + uint32_t length); + +int32_t fdo_blob_write_nv(uint32_t nv, fdo_sdk_blob_flags flags, + const uint8_t *buffer, uint32_t length); + +size_t fdo_blob_size_nv(uint32_t nv, fdo_sdk_blob_flags flags); +#endif #ifdef __cplusplus } // endof externc (CPP code) #endif diff --git a/storage/include/tpm2_nv_storage.h b/storage/include/tpm2_nv_storage.h new file mode 100644 index 00000000..6f8e1049 --- /dev/null +++ b/storage/include/tpm2_nv_storage.h @@ -0,0 +1,64 @@ +#include +#include +#include +#include +#include +#include + +#define FDO_CRED_NORMAL_NV_IDX 0x1000001 +#define FDO_CRED_SECURE_NV_IDX 0x1000002 + +#if defined(ECDSA256_DA) +#define FDO_TPM2_ALG_SHA TPM2_ALG_SHA256 +#else +#define FDO_TPM2_ALG_SHA TPM2_ALG_SHA384 +#endif + +/** Define space at NV index. + * + * @param[in] nv NV index to delete. + * @retval 0 on success. + * @retval -1 on undefined/general failure. + * @retval TSS2_RC response code for failures relayed from the TSS library. + */ +int fdo_tpm_nvdefine(uint32_t nv, size_t data_size); + +/** Store a data in a NV index. + * + * @param[in] data Key to store to NVRAM. + * @param[in] data_size Size of the data. + * @param[in] nv NV index to store the data. + * @retval 0 on success. + * @retval -1 on undefined/general failure. + * @retval TSS2_RC response code for failures relayed from the TSS library. + */ +int fdo_tpm_nvwrite(const uint8_t *data, size_t data_size, uint32_t nv); + +/** Load data size from a NV index. + * + * @param[in] nv NV index of the data. + * @retval data size on success. + * @retval -1 on undefined/general failure. + * @retval TSS2_RC response code for failures relayed from the TSS library. + */ +size_t fdo_tpm_nvread_size(uint32_t nv); + +/** Load a data from a NV index. + * + * @param[in] nv NV index of the data. + * @param[out] data Loaded data. + * @param[out] data_size Size of the data. + * @retval 0 on success. + * @retval -1 on undefined/general failure. + * @retval TSS2_RC response code for failures relayed from the TSS library. + */ +int fdo_tpm_nvread(uint32_t nv, size_t data_size, uint8_t **data); + +/** Delete data from a NV index. + * + * @param[in] nv NV index to delete. + * @retval 0 on success. + * @retval -1 on undefined/general failure. + * @retval TSS2_RC response code for failures relayed from the TSS library. + */ +int fdo_tpm_nvdel(uint32_t nv); \ No newline at end of file diff --git a/storage/linux/storage_if_linux.c b/storage/linux/storage_if_linux.c index 7c53bfe4..9859aedd 100644 --- a/storage/linux/storage_if_linux.c +++ b/storage/linux/storage_if_linux.c @@ -20,6 +20,9 @@ #include "fdo_crypto.h" #include "crypto_utils.h" #include "platform_utils.h" +#if defined(DEVICE_TPM20_ENABLED) +#include "tpm2_nv_storage.h" +#endif /**************************************************** * @@ -562,3 +565,504 @@ int32_t fdo_blob_write(const char *name, fdo_sdk_blob_flags flags, } return retval; } + +#if defined(DEVICE_TPM20_ENABLED) +/** + * fdo_blob_size Get specified FDO blob(file) size + * Note: FDO_SDK_OTP_DATA flag is not supported for this platform. + * @param nv - ptpm nv index + * @param flags - descriptor telling type of file + * @return file size on success, 0 if file does not exist or on other failure + */ + +size_t fdo_blob_size_nv(uint32_t nv, fdo_sdk_blob_flags flags) +{ + size_t retval = 0; + const size_t NORMAL_BLOB_OVERHEAD = + PLATFORM_HMAC_SIZE + BLOB_CONTENT_SIZE; + const size_t SECURE_BLOB_OVERHEAD = + AES_TAG_LEN + PLATFORM_IV_DEFAULT_LEN + BLOB_CONTENT_SIZE; + + if (!nv) { + LOG(LOG_ERROR, "Invalid parameters!\n"); + goto end; + } + + // Return 0 if the file is empty. + if (fdo_tpm_nvread_size(nv) == 0) { + LOG(LOG_DEBUG, "NV is empty!\n"); + retval = 0; + goto end; + } + + switch (flags) { + case FDO_SDK_RAW_DATA: + /* Raw Files are stored as plain files */ + retval = fdo_tpm_nvread_size(nv); + break; + case FDO_SDK_NORMAL_DATA: + /* Normal blob is stored as: + * [HMAC(32bytes)||data-content-size(4bytes)||data-content(?)] + */ + retval = fdo_tpm_nvread_size(nv); + + if (retval >= NORMAL_BLOB_OVERHEAD) { + retval -= NORMAL_BLOB_OVERHEAD; + } else { + /* File format is not correct, not enough data in the + * file */ + retval = 0; + } + break; + case FDO_SDK_SECURE_DATA: + /* Secure blob is stored as: + * [IV_data(12byte)||TAG(16bytes)|| + * data-content-size(4bytes)||data-content(?)] + */ + retval = fdo_tpm_nvread_size(nv); + if (retval >= SECURE_BLOB_OVERHEAD) { + retval -= SECURE_BLOB_OVERHEAD; + } else { + /* File format is not correct, not enough data in the + * file */ + retval = 0; + } + break; + default: + LOG(LOG_ERROR, "Invalid storage flag:%d!\n", flags); + goto end; + } + +end: + if (retval > R_MAX_SIZE) { + LOG(LOG_ERROR, "File size is more than R_MAX_SIZE\n"); + retval = 0; + } + return retval; +} + +/** + * fdo_blob_read Read FDO blob(file) into specified buffer, + * fdo_blob_read ensures authenticity & integrity for non-secure + * data & additionally confidentiality for secure data. + * Note: FDO_SDK_OTP_DATA flag is not supported for this platform. + * @param nv - tpm nv index + * @param flags - descriptor telling type of file + * @param buf - pointer to buf where data is read into + * @param n_bytes - length of data(in bytes) to be read + * @return num of bytes read if success, -1 on error + */ +int32_t fdo_blob_read_nv(uint32_t nv, fdo_sdk_blob_flags flags, uint8_t *buf, + uint32_t n_bytes) +{ + int retval = -1; + uint8_t *data = NULL; + uint32_t data_length = 0; + uint8_t *sealed_data = NULL; + uint32_t sealed_data_len = 0; + uint8_t *encrypted_data = NULL; + uint32_t encrypted_data_len = 0; + uint8_t stored_hmac[PLATFORM_HMAC_SIZE] = {0}; + uint8_t computed_hmac[PLATFORM_HMAC_SIZE] = {0}; + uint8_t stored_tag[AES_TAG_LEN] = {0}; + int strcmp_result = -1; + uint8_t iv[PLATFORM_IV_DEFAULT_LEN] = {0}; + uint8_t aes_key[PLATFORM_AES_KEY_DEFAULT_LEN] = {0}; + size_t dat_len_offst = 0; + + if (!nv || !buf || n_bytes == 0) { + LOG(LOG_ERROR, "Invalid parameters in %s!\n", __func__); + goto exit; + } + + if (n_bytes > R_MAX_SIZE) { + LOG(LOG_ERROR, + "file read buffer is more than R_MAX_SIZE in " + "%s!\n", + __func__); + goto exit; + } + + switch (flags) { + case FDO_SDK_RAW_DATA: + if (0 != fdo_tpm_nvread(nv, n_bytes, &buf)) { + LOG(LOG_ERROR, "Failed to read file!\n"); + goto exit; + } + break; + + case FDO_SDK_NORMAL_DATA: + /* HMAC-256 is being used to store files under + * FDO_SDK_NORMAL_DATA flag. + * File content to be stored as: + * [HMAC(32 bytes)||Sizeof_plaintext(4 bytes)||Plaintext(n_bytes + * bytes)] + */ + + sealed_data_len = + PLATFORM_HMAC_SIZE + BLOB_CONTENT_SIZE + n_bytes; + + sealed_data = fdo_alloc(sealed_data_len); + if (NULL == sealed_data) { + LOG(LOG_ERROR, "Malloc Failed in %s!\n", __func__); + goto exit; + } + + if (fdo_tpm_nvread(nv, sealed_data_len, &sealed_data)) { + LOG(LOG_ERROR, "Failed to read file!\n"); + goto exit; + } + + // get actual data length + data_length |= sealed_data[PLATFORM_HMAC_SIZE] << 24; + data_length |= sealed_data[PLATFORM_HMAC_SIZE + 1] << 16; + data_length |= sealed_data[PLATFORM_HMAC_SIZE + 2] << 8; + data_length |= + (sealed_data[PLATFORM_HMAC_SIZE + 3] & 0x000000FF); + + // check if input buffer is sufficient ? + if (n_bytes < data_length) { + LOG(LOG_ERROR, + "Failed to read data, Buffer is not enough, " + "buf_len:%d,\t Lengthstoredinfilesystem:%d\n", + n_bytes, data_length); + goto exit; + } + + if (memcpy_s(stored_hmac, PLATFORM_HMAC_SIZE, sealed_data, + PLATFORM_HMAC_SIZE) != 0) { + LOG(LOG_ERROR, + "Copying stored HMAC failed during " + "%s!\n", + __func__); + goto exit; + } + + data = sealed_data + PLATFORM_HMAC_SIZE + BLOB_CONTENT_SIZE; + + if (0 != fdo_compute_storage_hmac(data, data_length, + computed_hmac, + PLATFORM_HMAC_SIZE)) { + LOG(LOG_ERROR, + "HMAC computation dailed during" + " %s!\n", + __func__); + goto exit; + } + + // compare HMAC + if (memcmp_s(stored_hmac, PLATFORM_HMAC_SIZE, computed_hmac, + PLATFORM_HMAC_SIZE, &strcmp_result) != 0) { + LOG(LOG_ERROR, "Failed to compare HMAC\n"); + goto exit; + } + if (strcmp_result != 0) { + LOG(LOG_ERROR, "%s: HMACs do not compare!\n", __func__); + goto exit; + } + + // copy data into supplied buffer + if (memcpy_s(buf, n_bytes, data, data_length) != 0) { + LOG(LOG_ERROR, + "%s: Copying data into " + "buffer failed!\n", + __func__); + goto exit; + } + break; + + case FDO_SDK_SECURE_DATA: + /* AES GCM authenticated encryption is being used to store files + * under + * FDO_SDK_SECURE_DATA flag. File content to be stored as: + * [IV_data(12byte)||[AuthenticatedTAG(16 bytes)|| + * Sizeof_ciphertext(8 * bytes)||Ciphertet(n_bytes bytes)] + */ + + encrypted_data_len = PLATFORM_IV_DEFAULT_LEN + AES_TAG_LEN + + BLOB_CONTENT_SIZE + n_bytes; + + encrypted_data = fdo_alloc(encrypted_data_len); + if (NULL == encrypted_data) { + LOG(LOG_ERROR, "Malloc Failed in %s!\n", __func__); + goto exit; + } + + if (fdo_tpm_nvread(nv, encrypted_data_len, &encrypted_data)) { + LOG(LOG_ERROR, "Failed to read file!\n"); + goto exit; + } + + dat_len_offst = AES_TAG_LEN + PLATFORM_IV_DEFAULT_LEN; + // get actual data length + data_length |= encrypted_data[dat_len_offst] << 24; + data_length |= encrypted_data[dat_len_offst + 1] << 16; + data_length |= encrypted_data[dat_len_offst + 2] << 8; + data_length |= (encrypted_data[dat_len_offst + 3] & 0x000000FF); + + // check if input buffer is sufficient ? + if (n_bytes < data_length) { + LOG(LOG_ERROR, + "Failed to read data, Buffer is not enough, " + "buf_len:%d,\t Lengthstoredinfilesystem:%d\n", + n_bytes, data_length); + goto exit; + } + /* read the iv from blob */ + if (memcpy_s(iv, PLATFORM_IV_DEFAULT_LEN, encrypted_data, + PLATFORM_IV_DEFAULT_LEN) != 0) { + LOG(LOG_ERROR, + "Copying stored IV failed during " + "%s!\n", + __func__); + goto exit; + } + + if (memcpy_s(stored_tag, AES_TAG_LEN, + encrypted_data + PLATFORM_IV_DEFAULT_LEN, + AES_TAG_LEN) != 0) { + LOG(LOG_ERROR, + "Copying stored TAG failed during " + "%s!\n", + __func__); + goto exit; + } + + data = encrypted_data + PLATFORM_IV_DEFAULT_LEN + AES_TAG_LEN + + BLOB_CONTENT_SIZE; + + if (!get_platform_aes_key(aes_key, + PLATFORM_AES_KEY_DEFAULT_LEN)) { + LOG(LOG_ERROR, "Could not get platform AES Key!\n"); + goto exit; + } + + // decrypt and authenticate cipher-text content and fill the + // given buffer with clear-text + if (crypto_hal_aes_decrypt( + buf, &n_bytes, data, data_length, 16, iv, aes_key, + PLATFORM_AES_KEY_DEFAULT_LEN, stored_tag, AES_TAG_LEN, + NULL, 0) < 0) { + LOG(LOG_ERROR, "Decryption failed during Secure " + "Blob Read!\n"); + goto exit; + } + break; + + default: + LOG(LOG_ERROR, "Invalid FDO blob flag!!\n"); + goto exit; + } + + retval = (int32_t)n_bytes; + +exit: + if (sealed_data) { + fdo_free(sealed_data); + } + if (encrypted_data) { + fdo_free(encrypted_data); + } + if (memset_s(aes_key, PLATFORM_AES_KEY_DEFAULT_LEN, 0)) { + LOG(LOG_ERROR, "Failed to clear AES key\n"); + retval = -1; + } + return retval; +} + +/** + * fdo_blob_write Write FDO blob(file) from specified buffer + * fdo_blob_write ensures integrity & authenticity for non-secure + * data & additionally confidentiality for secure data. + * Note: FDO_SDK_OTP_DATA flag is not supported for this platform. + * @param nv - ptpm nv index + * @param flags - descriptor telling type of file + * @param buf - pointer to buf from where data is read and then written + * @param n_bytes - length of data(in bytes) to be written + * @return num of bytes write if success, -1 on error + */ + +int32_t fdo_blob_write_nv(uint32_t nv, fdo_sdk_blob_flags flags, + const uint8_t *buf, uint32_t n_bytes) +{ + int retval = -1; + FILE *f = NULL; + uint32_t write_context_len = 0; + uint32_t write_context_len_temp = 0; + uint8_t *write_context = NULL; + uint8_t tag[AES_TAG_LEN] = {0}; + uint8_t iv[PLATFORM_IV_DEFAULT_LEN] = {0}; + uint8_t aes_key[PLATFORM_AES_KEY_DEFAULT_LEN] = {0}; + size_t dat_len_offst = 0; + + if (!buf || !nv || n_bytes == 0) { + LOG(LOG_ERROR, "Invalid parameters in %s!\n", __func__); + goto exit; + } + + if (n_bytes > R_MAX_SIZE) { + LOG(LOG_ERROR, + "file write buffer is more than R_MAX_SIZE in " + "%s!\n", + __func__); + goto exit; + } + + switch (flags) { + case FDO_SDK_RAW_DATA: + // Raw Files are stored as plain files + write_context_len = n_bytes; + + write_context = fdo_alloc(write_context_len); + if (NULL == write_context) { + LOG(LOG_ERROR, "Malloc Failed in %s!\n", __func__); + goto exit; + } + + if (memcpy_s(write_context, write_context_len, buf, n_bytes) != + 0) { + LOG(LOG_ERROR, + "Copying data failed during RAW Blob write!\n"); + goto exit; + } + break; + + case FDO_SDK_NORMAL_DATA: + /* HMAC-256 is being used to store files under + * FDO_SDK_NORMAL_DATA flag. + * File content to be stored as: + * [HMAC(32 bytes)||Sizeof_plaintext(4 bytes)||Plaintext(n_bytes + * bytes)] + */ + write_context_len = + PLATFORM_HMAC_SIZE + BLOB_CONTENT_SIZE + n_bytes; + + write_context = fdo_alloc(write_context_len); + if (NULL == write_context) { + LOG(LOG_ERROR, "Malloc Failed in %s!\n", __func__); + goto exit; + } + + if (0 != fdo_compute_storage_hmac(buf, n_bytes, write_context, + PLATFORM_HMAC_SIZE)) { + LOG(LOG_ERROR, "Computing HMAC failed during Normal " + "Blob write!\n"); + goto exit; + } + + // copy plain-text size + write_context[PLATFORM_HMAC_SIZE + 3] = n_bytes >> 0; + write_context[PLATFORM_HMAC_SIZE + 2] = n_bytes >> 8; + write_context[PLATFORM_HMAC_SIZE + 1] = n_bytes >> 16; + write_context[PLATFORM_HMAC_SIZE + 0] = n_bytes >> 24; + + // copy plain-text content + if (memcpy_s(write_context + PLATFORM_HMAC_SIZE + + BLOB_CONTENT_SIZE, + (write_context_len - PLATFORM_HMAC_SIZE - + BLOB_CONTENT_SIZE), + buf, n_bytes) != 0) { + LOG(LOG_ERROR, + "Copying data failed during Normal Blob write!\n"); + goto exit; + } + break; + + case FDO_SDK_SECURE_DATA: + /* AES GCM authenticated encryption is being used to store files + * under + * FDO_SDK_SECURE_DATA flag. File content to be stored as: + * [IV_data(12byte)||[AuthenticatedTAG(16 bytes)|| + * Sizeof_ciphertext(8 * bytes)||Ciphertet(n_bytes bytes)] + */ + + write_context_len = PLATFORM_IV_DEFAULT_LEN + AES_TAG_LEN + + BLOB_CONTENT_SIZE + n_bytes; + + write_context = fdo_alloc(write_context_len); + if (NULL == write_context) { + LOG(LOG_ERROR, "Malloc Failed in %s!\n", __func__); + goto exit; + } + + if (!get_platform_iv(iv, PLATFORM_IV_DEFAULT_LEN, n_bytes)) { + LOG(LOG_ERROR, "Could not get platform IV!\n"); + goto exit; + } + + if (!get_platform_aes_key(aes_key, + PLATFORM_AES_KEY_DEFAULT_LEN)) { + LOG(LOG_ERROR, "Could not get platform AES Key!\n"); + goto exit; + } + + write_context_len_temp = + write_context_len - + (PLATFORM_IV_DEFAULT_LEN + AES_TAG_LEN + BLOB_CONTENT_SIZE); + // encrypt plain-text and copy cipher-text content + if (crypto_hal_aes_encrypt( + buf, n_bytes, + &write_context[PLATFORM_IV_DEFAULT_LEN + AES_TAG_LEN + + BLOB_CONTENT_SIZE], + &write_context_len_temp, 16, iv, aes_key, + PLATFORM_AES_KEY_DEFAULT_LEN, tag, AES_TAG_LEN, NULL, + 0) < 0) { + LOG(LOG_ERROR, "Encypting data failed during Secure " + "Blob write!\n"); + goto exit; + } + // copy used IV for encryption + if (memcpy_s(write_context, PLATFORM_IV_DEFAULT_LEN, iv, + PLATFORM_IV_DEFAULT_LEN) != 0) { + LOG(LOG_ERROR, "Copying TAG value failed during Secure " + "Blob write!\n"); + goto exit; + } + + // copy Authenticated TAG value + if (memcpy_s(write_context + PLATFORM_IV_DEFAULT_LEN, + write_context_len - PLATFORM_IV_DEFAULT_LEN, tag, + AES_TAG_LEN) != 0) { + LOG(LOG_ERROR, "Copying TAG value failed during Secure " + "Blob write!\n"); + goto exit; + } + + dat_len_offst = AES_TAG_LEN + PLATFORM_IV_DEFAULT_LEN; + /* copy cipher-text size; CT size= PT size (AES GCM uses AES CTR + * mode internally for encryption) + */ + write_context[dat_len_offst + 3] = n_bytes >> 0; + write_context[dat_len_offst + 2] = n_bytes >> 8; + write_context[dat_len_offst + 1] = n_bytes >> 16; + write_context[dat_len_offst + 0] = n_bytes >> 24; + break; + + default: + LOG(LOG_ERROR, "Invalid FDO blob flag!!\n"); + goto exit; + } + + if (fdo_tpm_nvwrite(write_context, write_context_len, nv)) { + LOG(LOG_ERROR, "Could not get platform AES Key!\n"); + goto exit; + } + + retval = (int32_t)n_bytes; + +exit: + if (write_context) { + fdo_free(write_context); + } + if (f) { + if (fclose(f) == EOF) { + LOG(LOG_ERROR, "fclose() Failed in %s\n", __func__); + } + } + if (memset_s(aes_key, PLATFORM_AES_KEY_DEFAULT_LEN, 0)) { + LOG(LOG_ERROR, "Failed to clear AES key\n"); + retval = -1; + } + return retval; +} +#endif \ No newline at end of file diff --git a/storage/linux/tpm2_nv_storage.c b/storage/linux/tpm2_nv_storage.c new file mode 100644 index 00000000..93609e1b --- /dev/null +++ b/storage/linux/tpm2_nv_storage.c @@ -0,0 +1,633 @@ +#include "util.h" +#include "tpm2_nv_storage.h" +#include "safe_lib.h" + +/** + * Initialize Esys context. + * + * @param esys_context : output Esys Context + * + * @return + * TPM2_RC_SUCCESS, on success + * -1, on failure + */ +static int32_t fdo_tpm_esys_context_init(ESYS_CONTEXT **esys_context) +{ + int ret = -1; + TSS2_TCTI_CONTEXT *tcti_context = NULL; + + if ((TSS2_RC_SUCCESS != + Tss2_TctiLdr_Initialize(TPM2_TCTI_TYPE, &tcti_context)) || + (!tcti_context)) { + LOG(LOG_ERROR, "TCTI Context initialization failed.\n"); + goto err; + } + + if (Esys_Initialize(esys_context, tcti_context, NULL) != + TPM2_RC_SUCCESS) { + LOG(LOG_ERROR, "Failed to intitialize Esys context.\n"); + goto err; + } + + return TPM2_RC_SUCCESS; + +err: + if (tcti_context) { + Tss2_TctiLdr_Finalize(&tcti_context); + } + return ret; +} + +/** + * Create HMAC based auth session for Esys Context + * + * @param esys_context : input Esys Context + * @param session_handle : output authentication session Handle + * + * @return + * TPM2_RC_SUCCESS, on success + * -1, on failure + */ +static int32_t fdo_tpm_esys_auth_session_init(ESYS_CONTEXT *esys_context, + ESYS_TR *session_handle) +{ + int ret = -1; + TSS2_RC rval; + TPMT_SYM_DEF symmetric = {.algorithm = TPM2_ALG_AES, + .keyBits = {.aes = 128}, + .mode = {.aes = TPM2_ALG_CFB}}; + + rval = Esys_StartAuthSession(esys_context, ESYS_TR_NONE, ESYS_TR_NONE, + ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, + NULL, TPM2_SE_HMAC, &symmetric, + FDO_TPM2_ALG_SHA, session_handle); + + if (rval != TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, "Failed to start the auth session.\n"); + return ret; + } + + rval = Esys_TRSess_SetAttributes(esys_context, *session_handle, + TPMA_SESSION_DECRYPT | + TPMA_SESSION_ENCRYPT | + TPMA_SESSION_CONTINUESESSION, + 0xff); + if (rval != TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, "Failed to Set session attributes.\n"); + return ret; + } + + return rval; +} + +/** + * Clear Esys, TCTI, contexts and Auth Session, Primary Key handles. + * + * @param esys_context : Esys Context to be cleared + * @param auth_session_handle : Auth session Handle to be flushed + * @param nv_handle : NV handle to be cleared + * @return + * 0, on success + * -1, on failure + */ +static int32_t fdo_tpm_context_clean_up(ESYS_CONTEXT **esys_context, + ESYS_TR *auth_session_handle, + ESYS_TR *nv_handle) +{ + int ret = -1, is_failed = 0; + TSS2_TCTI_CONTEXT *tcti_context = NULL; + TSS2_RC rc = TPM2_RC_FAILURE; + + if (!esys_context || !*esys_context) { + LOG(LOG_ERROR, "Invalid parameter received.\n"); + return ret; + } + + if (auth_session_handle && (*auth_session_handle != ESYS_TR_NONE)) { + if (Esys_FlushContext(*esys_context, *auth_session_handle) != + TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, + "Failed to flush auth session handle.\n"); + is_failed = 1; + } else { + LOG(LOG_DEBUG, + "Auth session handle flushed successfully.\n"); + *auth_session_handle = ESYS_TR_NONE; + } + } + + if (nv_handle && (*nv_handle != ESYS_TR_NONE)) { + if (Esys_TR_Close(*esys_context, nv_handle) != + TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, "Failed to flush primary key handle.\n"); + is_failed = 1; + } else { + LOG(LOG_DEBUG, + "Primary key handle flushed successfully.\n"); + *nv_handle = ESYS_TR_NONE; + } + } + + rc = Esys_GetTcti(*esys_context, &tcti_context); + if (rc != TPM2_RC_SUCCESS) { + LOG(LOG_ERROR, "Failed to cleanup TCTI.\n"); + is_failed = 1; + } + Esys_Finalize(esys_context); + + if (tcti_context) { + Tss2_TctiLdr_Finalize(&tcti_context); + if (tcti_context) { + LOG(LOG_ERROR, "Failed to finalize context.\n"); + is_failed = 1; + } + } + + if (is_failed) { + return ret; + } + + return 0; +} + +/** Define space at NV index. + * + * @param[in] nv NV index to delete. + * @retval 0 on success. + * @retval -1 on undefined/general failure. + * @retval TSS2_RC response code for failures relayed from the TSS library. + */ +int fdo_tpm_nvdefine(uint32_t nv, size_t data_size) +{ + + if (!nv) { + return -1; + } + + int ret = -1; + TSS2_RC rc; + ESYS_CONTEXT *ctx; + ESYS_TR nvHandle = ESYS_TR_NONE; + ESYS_TR auth_session_handle = ESYS_TR_NONE; + TPM2B_AUTH emptyAuth = { + .size = 0, + }; + + TPM2B_NV_PUBLIC publicInfo = { + .size = 0, + .nvPublic = { + .nvIndex = nv, + .nameAlg = FDO_TPM2_ALG_SHA, + .attributes = (TPMA_NV_OWNERWRITE | TPMA_NV_AUTHWRITE | + TPMA_NV_WRITE_STCLEAR | TPMA_NV_READ_STCLEAR | + TPMA_NV_AUTHREAD | TPMA_NV_OWNERREAD), + .authPolicy = + { + .size = 0, + .buffer = {0}, + }, + .dataSize = data_size, + }}; + + rc = fdo_tpm_esys_context_init(&ctx); + if (rc != TSS2_RC_SUCCESS || !ctx) { + LOG(LOG_ERROR, "Failed to intitialize Esys context.\n"); + goto err; + } + + rc = fdo_tpm_esys_auth_session_init(ctx, &auth_session_handle); + if (rc != TSS2_RC_SUCCESS || !auth_session_handle) { + LOG(LOG_ERROR, "Failed to create Auth Session for Esys API.\n"); + goto err; + } + + rc = Esys_Startup(ctx, TPM2_SU_CLEAR); + if (rc != TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, "Failed to start Esys context.\n"); + goto err; + } + + // Search the NV index + TPMS_CAPABILITY_DATA *capability_data = NULL; + rc = + Esys_GetCapability(ctx, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, + TPM2_CAP_HANDLES, nv, 1, NULL, &capability_data); + if (rc != TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, "Esys_GetCapability failed!\n"); + goto err; + } + + int exists = (capability_data->data.handles.count > 0 && + capability_data->data.handles.handle[0] == nv); + if (exists == 1) { + LOG(LOG_DEBUG, "NV index already exist.\n"); + ret = 0; + goto err; + } + + rc = Esys_NV_DefineSpace(ctx, ESYS_TR_RH_OWNER, auth_session_handle, + ESYS_TR_NONE, ESYS_TR_NONE, &emptyAuth, + &publicInfo, &nvHandle); + if (rc != TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, "Failed to define Esys NV space.\n"); + goto err; + } + + ret = 0; + +err: + + if (ctx && (0 != fdo_tpm_context_clean_up(&ctx, &auth_session_handle, + &nvHandle))) { + LOG(LOG_ERROR, "Failed to tear down all the TSS context.\n"); + ret = -1; + } + + return ret; +} + +/** Store a data in a NV index. + * + * @param[in] data Key to store to NVRAM. + * @param[in] data_size Size of the data. + * @param[in] nv NV index to store the data. + * @retval 0 on success. + * @retval -1 on undefined/general failure. + * @retval TSS2_RC response code for failures relayed from the TSS library. + */ +int fdo_tpm_nvwrite(const uint8_t *data, size_t data_size, uint32_t nv) +{ + if (!data || !nv) { + return -1; + } + + int ret = -1; + TSS2_RC rc; + ESYS_CONTEXT *ctx; + ESYS_TR nvHandle = ESYS_TR_NONE; + ESYS_TR auth_session_handle = ESYS_TR_NONE; + TPM2B_AUTH emptyAuth = { + .size = 0, + }; + + TPM2B_NV_PUBLIC publicInfo = { + .size = 0, + .nvPublic = { + .nvIndex = nv, + .nameAlg = FDO_TPM2_ALG_SHA, + .attributes = (TPMA_NV_OWNERWRITE | TPMA_NV_AUTHWRITE | + TPMA_NV_WRITE_STCLEAR | TPMA_NV_READ_STCLEAR | + TPMA_NV_AUTHREAD | TPMA_NV_OWNERREAD), + .authPolicy = + { + .size = 0, + .buffer = {0}, + }, + .dataSize = data_size, + }}; + + TPM2B_MAX_NV_BUFFER blob = {.size = data_size}; + if (blob.size > sizeof(blob.buffer)) { + LOG(LOG_ERROR, "Data too large.\n"); + return -1; + } + // memcpy(&blob.buffer[0], data, blob.size); + + if (memcpy_s(&blob.buffer[0], blob.size, data, data_size) != 0) { + LOG(LOG_ERROR, "Failed to copy data to blob!\n"); + goto err; + } + + rc = fdo_tpm_esys_context_init(&ctx); + if (rc != TSS2_RC_SUCCESS || !ctx) { + LOG(LOG_ERROR, "Failed to intitialize Esys context.\n"); + goto err; + } + + rc = fdo_tpm_esys_auth_session_init(ctx, &auth_session_handle); + if (rc != TSS2_RC_SUCCESS || !auth_session_handle) { + LOG(LOG_ERROR, "Failed to create Auth Session for Esys API.\n"); + goto err; + } + + rc = Esys_Startup(ctx, TPM2_SU_CLEAR); + if (rc != TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, "Failed to start Esys context.\n"); + goto err; + } + + // Search the NV index + TPMS_CAPABILITY_DATA *capability_data = NULL; + rc = + Esys_GetCapability(ctx, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, + TPM2_CAP_HANDLES, nv, 1, NULL, &capability_data); + if (rc != TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, "Esys_GetCapability failed!\n"); + goto err; + } + + int exists = (capability_data->data.handles.count > 0 && + capability_data->data.handles.handle[0] == nv); + if (exists == 1) { + LOG(LOG_DEBUG, "NV index already exist. Deleting it.\n"); + rc = Esys_TR_FromTPMPublic(ctx, nv, ESYS_TR_NONE, ESYS_TR_NONE, + ESYS_TR_NONE, &nvHandle); + if (rc != TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, + "Failed to constructs an ESYS_TR object.\n"); + goto err; + } + rc = Esys_NV_UndefineSpace(ctx, ESYS_TR_RH_OWNER, nvHandle, + auth_session_handle, ESYS_TR_NONE, + ESYS_TR_NONE); + if (rc != TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, "Failed to undefine Esys NV space.\n"); + goto err; + } + } + + rc = Esys_NV_DefineSpace(ctx, ESYS_TR_RH_OWNER, auth_session_handle, + ESYS_TR_NONE, ESYS_TR_NONE, &emptyAuth, + &publicInfo, &nvHandle); + if (rc != TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, "Failed to define Esys NV space.\n"); + goto err; + } + + rc = Esys_NV_Write(ctx, nvHandle, nvHandle, auth_session_handle, + ESYS_TR_NONE, ESYS_TR_NONE, &blob, 0 /*=offset*/); + if (rc != TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, "Failed to write in Esys NV space.\n"); + goto err; + } + + ret = 0; + +err: + + if (ctx && (0 != fdo_tpm_context_clean_up(&ctx, &auth_session_handle, + &nvHandle))) { + LOG(LOG_ERROR, "Failed to tear down all the TSS context.\n"); + ret = -1; + } + return ret; +} + +/** Load data size from a NV index. + * + * @param[in] nv NV index of the data. + * @retval data size on success. + * @retval -1 on undefined/general failure. + * @retval TSS2_RC response code for failures relayed from the TSS library. + */ +size_t fdo_tpm_nvread_size(uint32_t nv) +{ + int ret = -1; + TSS2_RC rc; + ESYS_CONTEXT *ctx; + ESYS_TR nvHandle = ESYS_TR_NONE; + ESYS_TR auth_session_handle = ESYS_TR_NONE; + TPM2B_NV_PUBLIC *publicInfo = NULL; + size_t data_size; + + if (!nv) { + return -1; + } + + rc = fdo_tpm_esys_context_init(&ctx); + if (rc != TSS2_RC_SUCCESS || !ctx) { + LOG(LOG_ERROR, "Failed to intitialize Esys context.\n"); + goto err; + } + + rc = fdo_tpm_esys_auth_session_init(ctx, &auth_session_handle); + if (rc != TSS2_RC_SUCCESS || !auth_session_handle) { + LOG(LOG_ERROR, "Failed to create Auth Session for Esys API.\n"); + goto err; + } + + rc = Esys_Startup(ctx, TPM2_SU_CLEAR); + if (rc != TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, "Failed to start Esys API.\n"); + goto err; + } + + // Search the NV index + TPMS_CAPABILITY_DATA *capability_data = NULL; + rc = + Esys_GetCapability(ctx, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, + TPM2_CAP_HANDLES, nv, 1, NULL, &capability_data); + if (rc != TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, "Esys_GetCapability failed!\n"); + goto err; + } + + int exists = (capability_data->data.handles.count > 0 && + capability_data->data.handles.handle[0] == nv); + if (exists != 1) { + LOG(LOG_DEBUG, "NV index doesn't exist.\n"); + ret = 0; + goto err; + } + + rc = Esys_TR_FromTPMPublic(ctx, nv, ESYS_TR_NONE, ESYS_TR_NONE, + ESYS_TR_NONE, &nvHandle); + if (rc != TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, "Failed to constructs an ESYS_TR object.\n"); + goto err; + } + + rc = Esys_NV_ReadPublic(ctx, nvHandle, ESYS_TR_NONE, ESYS_TR_NONE, + ESYS_TR_NONE, &publicInfo, NULL); + if (rc != TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, "Failed to read publicinfo from NV.\n"); + goto err; + } + + data_size = publicInfo->nvPublic.dataSize; + + ret = data_size; + +err: + + if (publicInfo) { + free(publicInfo); + } + + if (ctx && (0 != fdo_tpm_context_clean_up(&ctx, &auth_session_handle, + &nvHandle))) { + LOG(LOG_ERROR, "Failed to tear down all the TSS context.\n"); + ret = -1; + } + return ret; +} + +/** Load data from a NV index. + * + * @param[in] nv NV index of the data. + * @param[in] data_size Size of the data. + * @param[out] data Loaded data. + * @retval 0 on success. + * @retval -1 on undefined/general failure. + * @retval TSS2_RC response code for failures relayed from the TSS library. + */ +int fdo_tpm_nvread(uint32_t nv, size_t data_size, uint8_t **data) +{ + int ret = -1; + TSS2_RC rc; + ESYS_CONTEXT *ctx; + ESYS_TR nvHandle = ESYS_TR_NONE; + ESYS_TR auth_session_handle = ESYS_TR_NONE; + TPM2B_MAX_NV_BUFFER *blob; + TPM2B_NV_PUBLIC *publicInfo; + + if (!nv) { + return -1; + } + + rc = fdo_tpm_esys_context_init(&ctx); + if (rc != TSS2_RC_SUCCESS || !ctx) { + LOG(LOG_ERROR, "Failed to intitialize Esys context.\n"); + goto err; + } + + rc = fdo_tpm_esys_auth_session_init(ctx, &auth_session_handle); + if (rc != TSS2_RC_SUCCESS || !auth_session_handle) { + LOG(LOG_ERROR, "Failed to create Auth Session for Esys API.\n"); + goto err; + } + + rc = Esys_Startup(ctx, TPM2_SU_CLEAR); + if (rc != TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, "Failed to start Esys API.\n"); + goto err; + } + + rc = Esys_TR_FromTPMPublic(ctx, nv, ESYS_TR_NONE, ESYS_TR_NONE, + ESYS_TR_NONE, &nvHandle); + if (rc != TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, "Failed to constructs an ESYS_TR object.\n"); + goto err; + } + + rc = Esys_NV_ReadPublic(ctx, nvHandle, ESYS_TR_NONE, ESYS_TR_NONE, + ESYS_TR_NONE, &publicInfo, NULL); + if (rc != TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, "Failed to read publicinfo from NV.\n"); + goto err; + } + + rc = Esys_NV_Read(ctx, ESYS_TR_RH_OWNER, nvHandle, auth_session_handle, + ESYS_TR_NONE, ESYS_TR_NONE, data_size, 0 /*=offset*/, + &blob); + if (rc != TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, "Failed to read data from NV storage.\n"); + goto err; + } + + // *data_size = blob->size; + // *data = malloc(blob->size); + // memcpy(*data, &blob->buffer[0], blob->size); + if (memcpy_s(*data, data_size, &blob->buffer[0], blob->size) != 0) { + LOG(LOG_ERROR, "Failed to copy data to blob!\n"); + goto err; + } + + ret = 0; + +err: + + if (publicInfo) { + free(publicInfo); + } + + if (ctx && (0 != fdo_tpm_context_clean_up(&ctx, &auth_session_handle, + &nvHandle))) { + LOG(LOG_ERROR, "Failed to tear down all the TSS context.\n"); + ret = -1; + } + return ret; +} + +/** Delete data from a NV index. + * + * @param[in] nv NV index to delete. + * @retval 0 on success. + * @retval -1 on undefined/general failure. + * @retval TSS2_RC response code for failures relayed from the TSS library. + */ +int fdo_tpm_nvdel(uint32_t nv) +{ + int ret = -1; + TSS2_RC rc; + ESYS_CONTEXT *ctx; + ESYS_TR nvHandle = ESYS_TR_NONE; + ESYS_TR auth_session_handle = ESYS_TR_NONE; + + if (!nv) { + return -1; + } + + rc = fdo_tpm_esys_context_init(&ctx); + if (rc != TSS2_RC_SUCCESS || !ctx) { + LOG(LOG_ERROR, "Failed to intitialize Esys context.\n"); + goto err; + } + + rc = fdo_tpm_esys_auth_session_init(ctx, &auth_session_handle); + if (rc != TSS2_RC_SUCCESS || !auth_session_handle) { + LOG(LOG_ERROR, "Failed to create Auth Session for Esys API.\n"); + goto err; + } + + rc = Esys_Startup(ctx, TPM2_SU_CLEAR); + if (rc != TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, "Failed to start Esys API.\n"); + goto err; + } + + // Search the NV index + TPMS_CAPABILITY_DATA *capability_data = NULL; + rc = + Esys_GetCapability(ctx, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, + TPM2_CAP_HANDLES, nv, 1, NULL, &capability_data); + if (rc != TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, "Esys_GetCapability failed!\n"); + goto err; + } + + int exists = (capability_data->data.handles.count > 0 && + capability_data->data.handles.handle[0] == nv); + if (exists != 1) { + LOG(LOG_ERROR, "NV index doesn't exist.\n"); + goto err; + } + + rc = Esys_TR_FromTPMPublic(ctx, nv, ESYS_TR_NONE, ESYS_TR_NONE, + ESYS_TR_NONE, &nvHandle); + if (rc != TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, "Failed to constructs an ESYS_TR object.\n"); + goto err; + } + + rc = Esys_NV_UndefineSpace(ctx, ESYS_TR_RH_OWNER, nvHandle, + auth_session_handle, ESYS_TR_NONE, + ESYS_TR_NONE); + if (rc != TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, "Failed to undefine Esys NV space.\n"); + goto err; + } + nvHandle = ESYS_TR_NONE; + + ret = 0; + +err: + + if (ctx && (0 != fdo_tpm_context_clean_up(&ctx, &auth_session_handle, + &nvHandle))) { + LOG(LOG_ERROR, "Failed to tear down all the TSS context.\n"); + ret = -1; + } + + return ret; +} From c3ab532c43a69b6fbcf3554435022615c1497326 Mon Sep 17 00:00:00 2001 From: Shrikant Temburwar Date: Wed, 10 Jan 2024 12:37:15 +0530 Subject: [PATCH 2/9] Add support to store TPM private keys and device CSR inside TPM NV storage Signed-off-by: Shrikant Temburwar --- cmake/blob_path.cmake | 10 -- crypto/common/fdo_hmac.c | 26 +++-- crypto/include/tpm20_Utils.h | 7 +- crypto/openssl/tpm20_ECDSA_sign_routines.c | 41 ++++++-- crypto/openssl/tpm20_Utils.c | 112 ++++++++------------- include/fdomodules.h | 10 +- lib/credentials_from_file.c | 19 ++-- lib/m-string.c | 14 ++- storage/include/storage_al.h | 10 +- storage/include/tpm2_nv_storage.h | 15 ++- storage/linux/storage_if_linux.c | 69 ++++--------- storage/linux/tpm2_nv_storage.c | 3 +- utils/clear_tpm_nv.sh | 7 ++ utils/tpm_make_ready_ecdsa.sh | 37 ++++++- 14 files changed, 199 insertions(+), 181 deletions(-) create mode 100644 utils/clear_tpm_nv.sh diff --git a/cmake/blob_path.cmake b/cmake/blob_path.cmake index 0ec57d79..7d6d6b32 100644 --- a/cmake/blob_path.cmake +++ b/cmake/blob_path.cmake @@ -35,16 +35,6 @@ if(TARGET_OS MATCHES linux) if (${DA} MATCHES tpm) client_sdk_compile_definitions( -DDEVICE_TPM20_ENABLED - -DTPM_DEVICE_CSR=\"${BLOB_PATH}/data/tpm_device_csr\" - -DTPM_ECDSA_DEVICE_KEY=\"${BLOB_PATH}/data/tpm_ecdsa_priv_pub_blob.key\" - -DTPM_INPUT_DATA_TEMP_FILE=\"${BLOB_PATH}/data/tpm_input_data_temp_file\" - -DTPM_OUTPUT_DATA_TEMP_FILE=\"${BLOB_PATH}/data/tpm_output_data_temp_file\" - -DTPM_HMAC_PUB_KEY=\"${BLOB_PATH}/data/tpm_hmac_pub.key\" - -DTPM_HMAC_PRIV_KEY=\"${BLOB_PATH}/data/tpm_hmac_priv.key\" - -DTPM_HMAC_REPLACEMENT_PUB_KEY=\"${BLOB_PATH}/data/tpm_hmac_replacement_pub.key\" - -DTPM_HMAC_REPLACEMENT_PRIV_KEY=\"${BLOB_PATH}/data/tpm_hmac_replacement_priv.key\" - -DTPM_HMAC_DATA_PUB_KEY=\"${BLOB_PATH}/data/tpm_hmac_data_pub.key\" - -DTPM_HMAC_DATA_PRIV_KEY=\"${BLOB_PATH}/data/tpm_hmac_data_priv.key\" ) endif() diff --git a/crypto/common/fdo_hmac.c b/crypto/common/fdo_hmac.c index c347eb37..daee3e41 100644 --- a/crypto/common/fdo_hmac.c +++ b/crypto/common/fdo_hmac.c @@ -14,6 +14,7 @@ #if defined(DEVICE_TPM20_ENABLED) #include "tpm20_Utils.h" +#include "tpm2_nv_storage.h" #endif #if defined(DEVICE_CSE_ENABLED) @@ -151,15 +152,16 @@ int32_t fdo_device_ov_hmac(uint8_t *OVHdr, size_t OVHdr_len, uint8_t *hmac, if (is_replacement_hmac) { #if defined(DEVICE_TPM20_ENABLED) return fdo_tpm_get_hmac(OVHdr, OVHdr_len, hmac, hmac_len, - TPM_HMAC_REPLACEMENT_PUB_KEY, - TPM_HMAC_REPLACEMENT_PRIV_KEY); + TPM_HMAC_REPLACEMENT_PUB_KEY_NV_IDX, + TPM_HMAC_REPLACEMENT_PRIV_KEY_NV_IDX); #else keyset = get_replacement_OV_key(); #endif } else { #if defined(DEVICE_TPM20_ENABLED) return fdo_tpm_get_hmac(OVHdr, OVHdr_len, hmac, hmac_len, - TPM_HMAC_PUB_KEY, TPM_HMAC_PRIV_KEY); + TPM_HMAC_PUB_KEY_NV_IDX, + TPM_HMAC_PRIV_KEY_NV_IDX); #else keyset = get_OV_key(); #endif @@ -225,8 +227,8 @@ int32_t fdo_generate_ov_hmac_key(void) int32_t ret = -1; #if defined(DEVICE_TPM20_ENABLED) - if (0 != - fdo_tpm_generate_hmac_key(TPM_HMAC_PUB_KEY, TPM_HMAC_PRIV_KEY)) { + if (0 != fdo_tpm_generate_hmac_key(TPM_HMAC_PUB_KEY_NV_IDX, + TPM_HMAC_PRIV_KEY_NV_IDX)) { LOG(LOG_ERROR, "Failed to generate device HMAC key" " from TPM.\n"); return ret; @@ -270,8 +272,9 @@ int32_t fdo_generate_ov_replacement_hmac_key(void) int32_t ret = -1; #if defined(DEVICE_TPM20_ENABLED) - if (0 != fdo_tpm_generate_hmac_key(TPM_HMAC_REPLACEMENT_PUB_KEY, - TPM_HMAC_REPLACEMENT_PRIV_KEY)) { + if (0 != + fdo_tpm_generate_hmac_key(TPM_HMAC_REPLACEMENT_PUB_KEY_NV_IDX, + TPM_HMAC_REPLACEMENT_PRIV_KEY_NV_IDX)) { LOG(LOG_ERROR, "Failed to generate device replacement HMAC key" " from TPM.\n"); return ret; @@ -367,8 +370,9 @@ int32_t fdo_compute_storage_hmac(const uint8_t *data, uint32_t data_length, #if defined(DEVICE_TPM20_ENABLED) if (0 != fdo_tpm_get_hmac(data, data_length, computed_hmac, - computed_hmac_size, TPM_HMAC_DATA_PUB_KEY, - TPM_HMAC_DATA_PRIV_KEY)) { + computed_hmac_size, + TPM_HMAC_DATA_PUB_KEY_NV_IDX, + TPM_HMAC_DATA_PRIV_KEY_NV_IDX)) { LOG(LOG_ERROR, "TPM HMAC Computation failed!\n"); goto error; } @@ -420,8 +424,8 @@ int32_t fdo_generate_storage_hmac_key(void) return 0; #elif defined(DEVICE_TPM20_ENABLED) - if (0 != fdo_tpm_generate_hmac_key(TPM_HMAC_DATA_PUB_KEY, - TPM_HMAC_DATA_PRIV_KEY)) { + if (0 != fdo_tpm_generate_hmac_key(TPM_HMAC_DATA_PUB_KEY_NV_IDX, + TPM_HMAC_DATA_PRIV_KEY_NV_IDX)) { LOG(LOG_ERROR, "Failed to generate TPM data protection " "key.\n"); return ret; diff --git a/crypto/include/tpm20_Utils.h b/crypto/include/tpm20_Utils.h index fc4fde4d..889b1bb8 100644 --- a/crypto/include/tpm20_Utils.h +++ b/crypto/include/tpm20_Utils.h @@ -103,9 +103,10 @@ static const TPM2B_PUBLIC in_publicHMACKey_template = { }; int32_t fdo_tpm_get_hmac(const uint8_t *data, size_t data_length, uint8_t *hmac, - size_t hmac_length, char *tpmHMACPub_key, - char *tpmHMACPriv_key); -int32_t fdo_tpm_generate_hmac_key(char *tpmHMACPub_key, char *tpmHMACPriv_key); + size_t hmac_length, uint32_t tpmHMACPub_key_nv, + uint32_t tpmHMACPriv_key_nv); +int32_t fdo_tpm_generate_hmac_key(uint32_t tpmHMACPub_key_nv, + uint32_t tpmHMACPriv_key_nv); int32_t fdo_tpm_commit_replacement_hmac_key(void); void fdo_tpm_clear_replacement_hmac_key(void); int32_t is_valid_tpm_data_protection_key_present(void); diff --git a/crypto/openssl/tpm20_ECDSA_sign_routines.c b/crypto/openssl/tpm20_ECDSA_sign_routines.c index aa82bf25..169499b1 100644 --- a/crypto/openssl/tpm20_ECDSA_sign_routines.c +++ b/crypto/openssl/tpm20_ECDSA_sign_routines.c @@ -15,9 +15,12 @@ #include #include #include +#include #include "safe_lib.h" #include "util.h" #include "fdo_crypto_hal.h" +#include "tpm20_Utils.h" +#include "tpm2_nv_storage.h" /** * Sign a message using provided ECDSA Private Keys. @@ -45,6 +48,8 @@ int32_t crypto_hal_ecdsa_sign(const uint8_t *data, size_t data_len, EVP_MD_CTX *mdctx = NULL; OSSL_STORE_CTX *ctx = NULL; OSSL_STORE_INFO *info = NULL; + BIO *mem = NULL; + unsigned char *pri_key = NULL; if (!data || !data_len || !message_signature || !signature_length) { LOG(LOG_ERROR, "Invalid Parameters received."); @@ -58,23 +63,31 @@ int32_t crypto_hal_ecdsa_sign(const uint8_t *data, size_t data_len, } // Read the key - if ((ctx = OSSL_STORE_open(TPM_ECDSA_DEVICE_KEY, NULL, NULL, NULL, - NULL)) == NULL) { - LOG(LOG_ERROR, "Error during OSSL_STORE_open\n"); + size_t file_size = fdo_tpm_nvread_size(TPM_ECDSA_DEVICE_KEY_NV_IDX); + + pri_key = fdo_alloc(file_size); + if (!pri_key) { + LOG(LOG_ERROR, "Failed to allocate memory for private key.\n"); goto error; } - while (!OSSL_STORE_eof(ctx) && (info = OSSL_STORE_load(ctx)) != NULL) { - if (OSSL_STORE_INFO_get_type(info) == OSSL_STORE_INFO_PKEY) { - pkey = OSSL_STORE_INFO_get1_PKEY(info); - break; - } - OSSL_STORE_INFO_free(info); - info = NULL; + if (fdo_tpm_nvread(TPM_ECDSA_DEVICE_KEY_NV_IDX, file_size, &pri_key) == + -1) { + LOG(LOG_ERROR, + "Failed to load TPM HMAC Private Key into buffer.\n"); + goto error; } - if (!pkey) { + mem = BIO_new_mem_buf(pri_key, file_size); + if (mem == NULL) { + LOG(LOG_ERROR, "Failed to create memory BIO\n"); + goto error; + } + + pkey = PEM_read_bio_PrivateKey(mem, NULL, NULL, NULL); + if (pkey == NULL) { LOG(LOG_ERROR, "Error during reading Private key.\n"); + BIO_free(mem); goto error; } @@ -198,6 +211,12 @@ int32_t crypto_hal_ecdsa_sign(const uint8_t *data, size_t data_len, ret = 0; error: + if (pri_key) { + fdo_free(pri_key); + } + if (mem) { + BIO_free(mem); + } if (pkey) { EVP_PKEY_free(pkey); } diff --git a/crypto/openssl/tpm20_Utils.c b/crypto/openssl/tpm20_Utils.c index 7df8c004..461324c4 100644 --- a/crypto/openssl/tpm20_Utils.c +++ b/crypto/openssl/tpm20_Utils.c @@ -10,6 +10,7 @@ */ #include "util.h" #include "safe_lib.h" +#include "tpm2_nv_storage.h" #include "tpm20_Utils.h" #include "fdo_crypto_hal.h" #include "storage_al.h" @@ -39,8 +40,8 @@ static int32_t fdoTPMGenerate_primary_key_context(ESYS_CONTEXT **esys_context, * -1, on failure */ int32_t fdo_tpm_get_hmac(const uint8_t *data, size_t data_length, uint8_t *hmac, - size_t hmac_length, char *tpmHMACPub_key, - char *tpmHMACPriv_key) + size_t hmac_length, uint32_t tpmHMACPub_key_nv, + uint32_t tpmHMACPriv_key_nv) { int32_t ret = -1, ret_val = -1, file_size = 0; size_t hashed_length = 0; @@ -63,8 +64,9 @@ int32_t fdo_tpm_get_hmac(const uint8_t *data, size_t data_length, uint8_t *hmac, /* Validating all input parameters are passed in the function call*/ - if (!data || !data_length || !tpmHMACPub_key || !tpmHMACPriv_key || - !hmac || (hmac_length != PLATFORM_HMAC_SIZE)) { + if (!data || !data_length || !tpmHMACPub_key_nv || + !tpmHMACPriv_key_nv || !hmac || + (hmac_length != PLATFORM_HMAC_SIZE)) { LOG(LOG_ERROR, "Failed to generate HMAC from TPM, invalid parameter" " received.\n"); @@ -87,7 +89,7 @@ int32_t fdo_tpm_get_hmac(const uint8_t *data, size_t data_length, uint8_t *hmac, /* Unmarshalling the HMAC Private key from the HMAC Private key file*/ - file_size = get_file_size(tpmHMACPriv_key); + file_size = fdo_tpm_nvread_size(tpmHMACPriv_key_nv); if (file_size != TPM_HMAC_PRIV_KEY_CONTEXT_SIZE_128 && file_size != TPM_HMAC_PRIV_KEY_CONTEXT_SIZE) { @@ -98,10 +100,8 @@ int32_t fdo_tpm_get_hmac(const uint8_t *data, size_t data_length, uint8_t *hmac, LOG(LOG_DEBUG, "TPM HMAC Private Key file size retreived successfully.\n"); - ret_val = read_buffer_from_file(tpmHMACPriv_key, bufferTPMHMACPriv_key, - file_size); - - if (ret_val != 0) { + if (fdo_tpm_read_nv(tpmHMACPriv_key_nv, FDO_SDK_RAW_DATA, + bufferTPMHMACPriv_key, file_size) == -1) { LOG(LOG_ERROR, "Failed to load TPM HMAC Private Key into buffer.\n"); goto err; @@ -123,7 +123,7 @@ int32_t fdo_tpm_get_hmac(const uint8_t *data, size_t data_length, uint8_t *hmac, /* Unmarshalling the HMAC Public key from the HMAC public key file*/ - file_size = get_file_size(tpmHMACPub_key); + file_size = fdo_tpm_nvread_size(tpmHMACPub_key_nv); if (file_size != TPM_HMAC_PUB_KEY_CONTEXT_SIZE) { LOG(LOG_ERROR, "TPM HMAC Private Key file size incorrect.\n"); @@ -133,12 +133,10 @@ int32_t fdo_tpm_get_hmac(const uint8_t *data, size_t data_length, uint8_t *hmac, LOG(LOG_DEBUG, "TPM HMAC Public Key file size retreived successfully.\n"); - ret_val = read_buffer_from_file(tpmHMACPub_key, bufferTPMHMACPub_key, - file_size); - - if (ret_val != 0) { + if (fdo_tpm_read_nv(tpmHMACPub_key_nv, FDO_SDK_RAW_DATA, + bufferTPMHMACPub_key, file_size) == -1) { LOG(LOG_ERROR, - "Failed to load TPM HMAC Public key into buffer.\n"); + "Failed to load TPM HMAC Public Key into buffer.\n"); goto err; } @@ -353,7 +351,8 @@ int32_t fdo_tpm_get_hmac(const uint8_t *data, size_t data_length, uint8_t *hmac, * 0, on success * -1, on failure */ -int32_t fdo_tpm_generate_hmac_key(char *tpmHMACPub_key, char *tpmHMACPriv_key) +int32_t fdo_tpm_generate_hmac_key(uint32_t tpmHMACPub_key_nv, + uint32_t tpmHMACPriv_key_nv) { int32_t ret = -1; TSS2_RC ret_val = TPM2_RC_FAILURE; @@ -374,22 +373,12 @@ int32_t fdo_tpm_generate_hmac_key(char *tpmHMACPub_key, char *tpmHMACPriv_key) uint8_t buffer[TPM_HMAC_PRIV_KEY_CONTEXT_SIZE] = {0}; size_t offset = 0; - if (!tpmHMACPub_key || !tpmHMACPriv_key) { + if (!tpmHMACPub_key_nv || !tpmHMACPriv_key_nv) { LOG(LOG_ERROR, "Failed to generate HMAC Key," "invalid parameters received.\n"); goto err; } - if ((file_exists(tpmHMACPub_key) && !remove(tpmHMACPub_key)) && - (file_exists(tpmHMACPriv_key) && !remove(tpmHMACPriv_key))) { - LOG(LOG_DEBUG, "Successfully deleted old HMAC key.\n"); - } else if (file_exists(tpmHMACPub_key) || - file_exists(tpmHMACPriv_key)) { - LOG(LOG_DEBUG, "HMAC key generation failed," - "failed to delete the old HMAC key.\n"); - goto err; - } - if (0 != fdoTPMGenerate_primary_key_context(&esys_context, &primary_key_handle, &auth_session_handle)) { @@ -417,8 +406,9 @@ int32_t fdo_tpm_generate_hmac_key(char *tpmHMACPub_key, char *tpmHMACPriv_key) goto err; } - if ((int32_t)offset != - fdo_blob_write(tpmHMACPub_key, FDO_SDK_RAW_DATA, buffer, offset)) { + if ((int32_t)offset != fdo_tpm_write_nv(tpmHMACPub_key_nv, + FDO_SDK_RAW_DATA, buffer, + offset)) { LOG(LOG_ERROR, "Failed to save the public HMAC key context.\n"); goto err; } @@ -433,8 +423,9 @@ int32_t fdo_tpm_generate_hmac_key(char *tpmHMACPub_key, char *tpmHMACPriv_key) goto err; } - if ((int32_t)offset != - fdo_blob_write(tpmHMACPriv_key, FDO_SDK_RAW_DATA, buffer, offset)) { + if ((int32_t)offset != fdo_tpm_write_nv(tpmHMACPriv_key_nv, + FDO_SDK_RAW_DATA, buffer, + offset)) { LOG(LOG_ERROR, "Failed to save the private HMAC key context.\n"); goto err; @@ -689,23 +680,14 @@ static int32_t fdoTPMTSSContext_clean_up(ESYS_CONTEXT **esys_context, int32_t fdo_tpm_commit_replacement_hmac_key(void) { size_t file_size = 0; - // internal return value - int32_t ret_val = -1; // function return value int32_t ret = -1; uint8_t bufferTPMHMACPriv_key[TPM_HMAC_PRIV_KEY_CONTEXT_SIZE] = {0}; uint8_t bufferTPMHMACPub_key[TPM_HMAC_PUB_KEY_CONTEXT_SIZE] = {0}; - if (!file_exists(TPM_HMAC_PRIV_KEY) || !file_exists(TPM_HMAC_PUB_KEY) || - !file_exists(TPM_HMAC_REPLACEMENT_PRIV_KEY) || - !file_exists(TPM_HMAC_REPLACEMENT_PUB_KEY)) { - LOG(LOG_ERROR, "One or more HMAC objects are missing.\n"); - goto err; - } - // read TPM_HMAC_REPLACEMENT_PRIV_KEY contents and write it into // TPM_HMAC_PRIV_KEY - file_size = get_file_size(TPM_HMAC_REPLACEMENT_PRIV_KEY); + file_size = fdo_tpm_nvread_size(TPM_HMAC_REPLACEMENT_PRIV_KEY_NV_IDX); if (file_size != TPM_HMAC_PRIV_KEY_CONTEXT_SIZE_128 && file_size != TPM_HMAC_PRIV_KEY_CONTEXT_SIZE) { @@ -717,18 +699,17 @@ int32_t fdo_tpm_commit_replacement_hmac_key(void) LOG(LOG_DEBUG, "TPM HMAC Replacement Private Key file size retreived " "successfully.\n"); - ret_val = read_buffer_from_file(TPM_HMAC_REPLACEMENT_PRIV_KEY, - bufferTPMHMACPriv_key, file_size); - - if (ret_val != 0) { + if (fdo_tpm_read_nv(TPM_HMAC_REPLACEMENT_PRIV_KEY_NV_IDX, + FDO_SDK_RAW_DATA, bufferTPMHMACPriv_key, + file_size) == -1) { LOG(LOG_ERROR, "Failed to load TPM HMAC Replacement Private " "Key into buffer.\n"); goto err; } if ((int32_t)file_size != - fdo_blob_write(TPM_HMAC_PRIV_KEY, FDO_SDK_RAW_DATA, - bufferTPMHMACPriv_key, file_size)) { + fdo_tpm_write_nv(TPM_HMAC_PRIV_KEY_NV_IDX, FDO_SDK_RAW_DATA, + bufferTPMHMACPriv_key, file_size)) { LOG(LOG_ERROR, "Failed to save the private HMAC key context.\n"); goto err; @@ -736,7 +717,7 @@ int32_t fdo_tpm_commit_replacement_hmac_key(void) // now, read TPM_HMAC_REPLACEMENT_PUB_KEY contents and write it into // TPM_HMAC_PUB_KEY - file_size = get_file_size(TPM_HMAC_REPLACEMENT_PUB_KEY); + file_size = fdo_tpm_nvread_size(TPM_HMAC_REPLACEMENT_PUB_KEY_NV_IDX); if (file_size != TPM_HMAC_PUB_KEY_CONTEXT_SIZE) { LOG(LOG_ERROR, @@ -747,18 +728,17 @@ int32_t fdo_tpm_commit_replacement_hmac_key(void) LOG(LOG_DEBUG, "TPM HMAC Replacement Public Key file size retreived " "successfully.\n"); - ret_val = read_buffer_from_file(TPM_HMAC_REPLACEMENT_PUB_KEY, - bufferTPMHMACPub_key, file_size); - - if (ret_val != 0) { + if (fdo_tpm_read_nv(TPM_HMAC_REPLACEMENT_PUB_KEY_NV_IDX, + FDO_SDK_RAW_DATA, bufferTPMHMACPub_key, + file_size) == -1) { LOG(LOG_ERROR, "Failed to load TPM HMAC Replacement Public key " "into buffer.\n"); goto err; } if ((int32_t)file_size != - fdo_blob_write(TPM_HMAC_PUB_KEY, FDO_SDK_RAW_DATA, - bufferTPMHMACPub_key, file_size)) { + fdo_tpm_write_nv(TPM_HMAC_PUB_KEY_NV_IDX, FDO_SDK_RAW_DATA, + bufferTPMHMACPub_key, file_size)) { LOG(LOG_ERROR, "Failed to save the public HMAC key context.\n"); goto err; } @@ -774,15 +754,13 @@ int32_t fdo_tpm_commit_replacement_hmac_key(void) void fdo_tpm_clear_replacement_hmac_key(void) { // remove the files if they exist, else return - if (file_exists(TPM_HMAC_REPLACEMENT_PRIV_KEY)) { - if (0 != remove(TPM_HMAC_REPLACEMENT_PRIV_KEY)) { - LOG(LOG_ERROR, "Failed to cleanup private object\n"); - } + + if (0 != fdo_tpm_nvdel(TPM_HMAC_REPLACEMENT_PRIV_KEY_NV_IDX)) { + LOG(LOG_ERROR, "Failed to cleanup private object\n"); } - if (file_exists(TPM_HMAC_REPLACEMENT_PUB_KEY)) { - if (0 != remove(TPM_HMAC_REPLACEMENT_PUB_KEY)) { - LOG(LOG_ERROR, "Failed to cleanup public object\n"); - } + + if (0 != fdo_tpm_nvdel(TPM_HMAC_REPLACEMENT_PUB_KEY_NV_IDX)) { + LOG(LOG_ERROR, "Failed to cleanup public object\n"); } } @@ -795,12 +773,10 @@ void fdo_tpm_clear_replacement_hmac_key(void) */ int32_t is_valid_tpm_data_protection_key_present(void) { - return (file_exists(TPM_HMAC_DATA_PUB_KEY) && - (TPM_HMAC_PUB_KEY_CONTEXT_SIZE == - get_file_size(TPM_HMAC_DATA_PUB_KEY)) && - file_exists(TPM_HMAC_DATA_PRIV_KEY) && + return ((TPM_HMAC_PUB_KEY_CONTEXT_SIZE == + fdo_tpm_nvread_size(TPM_HMAC_DATA_PUB_KEY_NV_IDX)) && (TPM_HMAC_PRIV_KEY_CONTEXT_SIZE_128 == - get_file_size(TPM_HMAC_DATA_PRIV_KEY) || + fdo_tpm_nvread_size(TPM_HMAC_DATA_PRIV_KEY_NV_IDX) || TPM_HMAC_PRIV_KEY_CONTEXT_SIZE == - get_file_size(TPM_HMAC_DATA_PRIV_KEY))); + fdo_tpm_nvread_size(TPM_HMAC_DATA_PRIV_KEY_NV_IDX))); } diff --git a/include/fdomodules.h b/include/fdomodules.h index 00fed560..8a85d814 100644 --- a/include/fdomodules.h +++ b/include/fdomodules.h @@ -39,10 +39,12 @@ typedef enum { } fdo_sdk_si_type; // enum for Sv_info module CB return value -enum { FDO_SI_CONTENT_ERROR, - FDO_SI_INTERNAL_ERROR, - FDO_SI_SUCCESS, - FDO_SI_INVALID_MOD_ERROR }; +enum { + FDO_SI_CONTENT_ERROR, + FDO_SI_INTERNAL_ERROR, + FDO_SI_SUCCESS, + FDO_SI_INVALID_MOD_ERROR +}; typedef struct fdo_sdk_si_key_value { char *key; diff --git a/lib/credentials_from_file.c b/lib/credentials_from_file.c index a7622361..2866e112 100644 --- a/lib/credentials_from_file.c +++ b/lib/credentials_from_file.c @@ -559,7 +559,7 @@ bool write_tpm_device_credentials(uint32_t nv, fdo_sdk_blob_flags flags, } fdow->b.block_size = encoded_cred_length; - if (fdo_blob_write_nv(nv, flags, fdow->b.block, fdow->b.block_size) == + if (fdo_tpm_write_nv(nv, flags, fdow->b.block, fdow->b.block_size) == -1) { LOG(LOG_ERROR, "Failed to write DeviceCredential blob\n"); ret = false; @@ -607,7 +607,7 @@ bool read_tpm_device_credentials(uint32_t nv, fdo_sdk_blob_flags flags, goto end; } - dev_cred_len = fdo_blob_size_nv(nv, flags); + dev_cred_len = fdo_tpm_size_nv(nv); // Device has not yet been initialized. // Since, Normal.blob is empty, the file size will be 0 if (dev_cred_len == 0) { @@ -627,7 +627,7 @@ bool read_tpm_device_credentials(uint32_t nv, fdo_sdk_blob_flags flags, goto end; } - if (fdo_blob_read_nv(nv, flags, fdor->b.block, fdor->b.block_size) == + if (fdo_tpm_read_nv(nv, flags, fdor->b.block, fdor->b.block_size) == -1) { LOG(LOG_ERROR, "Failed to read DeviceCredential blob : Normal.blob\n"); @@ -744,8 +744,8 @@ int store_tpm_credential(fdo_dev_cred_t *ocred) { /* Write in the file and save the Normal device credentials */ LOG(LOG_DEBUG, "Writing to TPm NV storage\n"); - if (!write_tpm_device_credentials(FDO_CRED_NORMAL_NV_IDX, - FDO_SDK_NORMAL_DATA, ocred)) { + if (!write_tpm_device_credentials(FDO_CRED_NV_IDX, FDO_SDK_NORMAL_DATA, + ocred)) { LOG(LOG_ERROR, "Could not write to Normal Credentials blob\n"); return -1; } @@ -913,9 +913,9 @@ int load_credential(fdo_dev_cred_t *ocred) return -1; } #elif defined(DEVICE_TPM20_ENABLED) - /* Read in the blob and save the device credentials */ - if (!read_tpm_device_credentials(FDO_CRED_NORMAL_NV_IDX, - FDO_SDK_NORMAL_DATA, ocred)) { + /* Read and save the device credentials */ + if (!read_tpm_device_credentials(FDO_CRED_NV_IDX, FDO_SDK_NORMAL_DATA, + ocred)) { LOG(LOG_ERROR, "Could not parse the Device Credentials blob\n"); return -1; } @@ -977,8 +977,7 @@ bool load_device_status(fdo_sdk_device_status *state) return false; } #elif defined(DEVICE_TPM20_ENABLED) - size_t dev_cred_len = - fdo_blob_size_nv(FDO_CRED_NORMAL_NV_IDX, FDO_SDK_NORMAL_DATA); + size_t dev_cred_len = fdo_tpm_size_nv(FDO_CRED_NV_IDX); #else size_t dev_cred_len = fdo_blob_size((char *)FDO_CRED_NORMAL, FDO_SDK_NORMAL_DATA); diff --git a/lib/m-string.c b/lib/m-string.c index 4a62fb5e..df0f2338 100644 --- a/lib/m-string.c +++ b/lib/m-string.c @@ -20,6 +20,11 @@ #include "cse_utils.h" #include "cse_tools.h" #endif +#if defined(DEVICE_TPM20_ENABLED) +#include "tpm20_Utils.h" +#include "fdo_crypto.h" +#include "tpm2_nv_storage.h" +#endif #include @@ -247,7 +252,7 @@ int ps_get_m_string(fdo_prot_t *ps) /* Get the CSR data */ #if defined(DEVICE_TPM20_ENABLED) - size_t m_string_sz = get_file_size(TPM_DEVICE_CSR); + size_t m_string_sz = fdo_tpm_nvread_size(TPM_DEVICE_CSR_NV_IDX); csr = fdo_byte_array_alloc(m_string_sz); if (!csr) { @@ -256,11 +261,12 @@ int ps_get_m_string(fdo_prot_t *ps) goto err; } - ret = read_buffer_from_file(TPM_DEVICE_CSR, csr->bytes, csr->byte_sz); - if (0 != ret) { - LOG(LOG_ERROR, "Failed to read %s file!\n", TPM_DEVICE_CSR); + if (fdo_tpm_read_nv(TPM_DEVICE_CSR_NV_IDX, FDO_SDK_RAW_DATA, csr->bytes, + csr->byte_sz) == -1) { + LOG(LOG_ERROR, "Failed to load TPM DEVICE CSR into buffer.\n"); goto err; } + ret = 0; #elif defined(DEVICE_CSE_ENABLED) // CSR will be NULL for CSE csr = fdo_byte_array_alloc(0); diff --git a/storage/include/storage_al.h b/storage/include/storage_al.h index ae3f6523..70ca04fc 100644 --- a/storage/include/storage_al.h +++ b/storage/include/storage_al.h @@ -47,13 +47,13 @@ size_t fdo_blob_size(const char *blob_name, fdo_sdk_blob_flags flags); int32_t create_hmac_normal_blob(void); #if defined(DEVICE_TPM20_ENABLED) -int32_t fdo_blob_read_nv(uint32_t nv, fdo_sdk_blob_flags flags, uint8_t *buffer, - uint32_t length); +int32_t fdo_tpm_read_nv(uint32_t nv, fdo_sdk_blob_flags flags, uint8_t *buffer, + uint32_t length); -int32_t fdo_blob_write_nv(uint32_t nv, fdo_sdk_blob_flags flags, - const uint8_t *buffer, uint32_t length); +int32_t fdo_tpm_write_nv(uint32_t nv, fdo_sdk_blob_flags flags, + const uint8_t *buffer, uint32_t length); -size_t fdo_blob_size_nv(uint32_t nv, fdo_sdk_blob_flags flags); +size_t fdo_tpm_size_nv(uint32_t nv); #endif #ifdef __cplusplus } // endof externc (CPP code) diff --git a/storage/include/tpm2_nv_storage.h b/storage/include/tpm2_nv_storage.h index 6f8e1049..e0f59694 100644 --- a/storage/include/tpm2_nv_storage.h +++ b/storage/include/tpm2_nv_storage.h @@ -5,8 +5,19 @@ #include #include -#define FDO_CRED_NORMAL_NV_IDX 0x1000001 -#define FDO_CRED_SECURE_NV_IDX 0x1000002 +#define FDO_CRED_NV_IDX 0x1000001 + +#define TPM_HMAC_PUB_KEY_NV_IDX 0x1000002 +#define TPM_HMAC_PRIV_KEY_NV_IDX 0x1000003 + +#define TPM_HMAC_DATA_PUB_KEY_NV_IDX 0x1000004 +#define TPM_HMAC_DATA_PRIV_KEY_NV_IDX 0x1000005 + +#define TPM_HMAC_REPLACEMENT_PUB_KEY_NV_IDX 0x1000006 +#define TPM_HMAC_REPLACEMENT_PRIV_KEY_NV_IDX 0x1000007 + +#define TPM_ECDSA_DEVICE_KEY_NV_IDX 0x1000008 +#define TPM_DEVICE_CSR_NV_IDX 0x1000009 #if defined(ECDSA256_DA) #define FDO_TPM2_ALG_SHA TPM2_ALG_SHA256 diff --git a/storage/linux/storage_if_linux.c b/storage/linux/storage_if_linux.c index 9859aedd..75c7a1d7 100644 --- a/storage/linux/storage_if_linux.c +++ b/storage/linux/storage_if_linux.c @@ -568,69 +568,40 @@ int32_t fdo_blob_write(const char *name, fdo_sdk_blob_flags flags, #if defined(DEVICE_TPM20_ENABLED) /** - * fdo_blob_size Get specified FDO blob(file) size - * Note: FDO_SDK_OTP_DATA flag is not supported for this platform. + * fdo_tpm_size_nv Get specified FDO nv size * @param nv - ptpm nv index - * @param flags - descriptor telling type of file * @return file size on success, 0 if file does not exist or on other failure */ -size_t fdo_blob_size_nv(uint32_t nv, fdo_sdk_blob_flags flags) +size_t fdo_tpm_size_nv(uint32_t nv) { size_t retval = 0; - const size_t NORMAL_BLOB_OVERHEAD = + const size_t NORMAL_NV_OVERHEAD = PLATFORM_HMAC_SIZE + BLOB_CONTENT_SIZE; - const size_t SECURE_BLOB_OVERHEAD = - AES_TAG_LEN + PLATFORM_IV_DEFAULT_LEN + BLOB_CONTENT_SIZE; if (!nv) { LOG(LOG_ERROR, "Invalid parameters!\n"); goto end; } + /* Normal cred is stored as: + * [HMAC(32bytes)||data-content-size(4bytes)||data-content(?)] + */ + retval = fdo_tpm_nvread_size(nv); + // Return 0 if the file is empty. - if (fdo_tpm_nvread_size(nv) == 0) { + if (retval == 0) { LOG(LOG_DEBUG, "NV is empty!\n"); retval = 0; goto end; } - switch (flags) { - case FDO_SDK_RAW_DATA: - /* Raw Files are stored as plain files */ - retval = fdo_tpm_nvread_size(nv); - break; - case FDO_SDK_NORMAL_DATA: - /* Normal blob is stored as: - * [HMAC(32bytes)||data-content-size(4bytes)||data-content(?)] - */ - retval = fdo_tpm_nvread_size(nv); - - if (retval >= NORMAL_BLOB_OVERHEAD) { - retval -= NORMAL_BLOB_OVERHEAD; - } else { - /* File format is not correct, not enough data in the - * file */ - retval = 0; - } - break; - case FDO_SDK_SECURE_DATA: - /* Secure blob is stored as: - * [IV_data(12byte)||TAG(16bytes)|| - * data-content-size(4bytes)||data-content(?)] - */ - retval = fdo_tpm_nvread_size(nv); - if (retval >= SECURE_BLOB_OVERHEAD) { - retval -= SECURE_BLOB_OVERHEAD; - } else { - /* File format is not correct, not enough data in the - * file */ - retval = 0; - } - break; - default: - LOG(LOG_ERROR, "Invalid storage flag:%d!\n", flags); - goto end; + if (retval >= NORMAL_NV_OVERHEAD) { + retval -= NORMAL_NV_OVERHEAD; + } else { + /* File format is not correct, not enough data in the + * file */ + retval = 0; } end: @@ -652,8 +623,8 @@ size_t fdo_blob_size_nv(uint32_t nv, fdo_sdk_blob_flags flags) * @param n_bytes - length of data(in bytes) to be read * @return num of bytes read if success, -1 on error */ -int32_t fdo_blob_read_nv(uint32_t nv, fdo_sdk_blob_flags flags, uint8_t *buf, - uint32_t n_bytes) +int32_t fdo_tpm_read_nv(uint32_t nv, fdo_sdk_blob_flags flags, uint8_t *buf, + uint32_t n_bytes) { int retval = -1; uint8_t *data = NULL; @@ -882,8 +853,8 @@ int32_t fdo_blob_read_nv(uint32_t nv, fdo_sdk_blob_flags flags, uint8_t *buf, * @return num of bytes write if success, -1 on error */ -int32_t fdo_blob_write_nv(uint32_t nv, fdo_sdk_blob_flags flags, - const uint8_t *buf, uint32_t n_bytes) +int32_t fdo_tpm_write_nv(uint32_t nv, fdo_sdk_blob_flags flags, + const uint8_t *buf, uint32_t n_bytes) { int retval = -1; FILE *f = NULL; @@ -1044,7 +1015,7 @@ int32_t fdo_blob_write_nv(uint32_t nv, fdo_sdk_blob_flags flags, } if (fdo_tpm_nvwrite(write_context, write_context_len, nv)) { - LOG(LOG_ERROR, "Could not get platform AES Key!\n"); + LOG(LOG_ERROR, "Failed to write in TPM NV!\n"); goto exit; } diff --git a/storage/linux/tpm2_nv_storage.c b/storage/linux/tpm2_nv_storage.c index 93609e1b..7fef660f 100644 --- a/storage/linux/tpm2_nv_storage.c +++ b/storage/linux/tpm2_nv_storage.c @@ -599,7 +599,8 @@ int fdo_tpm_nvdel(uint32_t nv) int exists = (capability_data->data.handles.count > 0 && capability_data->data.handles.handle[0] == nv); if (exists != 1) { - LOG(LOG_ERROR, "NV index doesn't exist.\n"); + LOG(LOG_DEBUG, "NV index doesn't exist.\n"); + ret = 0; goto err; } diff --git a/utils/clear_tpm_nv.sh b/utils/clear_tpm_nv.sh new file mode 100644 index 00000000..ebf65e7d --- /dev/null +++ b/utils/clear_tpm_nv.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +for n in {1..9}; +do + tpm2_nvundefine $n +done +echo "TPM NV storage cleared!" diff --git a/utils/tpm_make_ready_ecdsa.sh b/utils/tpm_make_ready_ecdsa.sh index 3a9972a7..a0ca2839 100644 --- a/utils/tpm_make_ready_ecdsa.sh +++ b/utils/tpm_make_ready_ecdsa.sh @@ -106,19 +106,50 @@ execute_cmd_on_failure_exit "\$cmd" "\$success_string" "\$failure_string" 1 1 task="Load primary key inside persistance memory at $TPM_ENDORSEMENT_PRIMARY_KEY_PERSISTANT_HANDLE" cmd="tpm2_evictcontrol -C o $TPM_ENDORSEMENT_PRIMARY_KEY_PERSISTANT_HANDLE -c $tpm_endorsement_primary_key_ctx -V" -success_string="$task completed successfully at $TPM_ENDORSEMENT_PRIMARY_KEY_PERSISTANT_HANDLE !!" +success_string="$task completed successfully at!!" failure_string="$task failed" execute_cmd_on_failure_exit "\$cmd" "\$success_string" "\$failure_string" 1 1 task="TPM ECDSA key generation using $curve" cmd="$OPENSSL3_BIN/openssl genpkey -provider tpm2 -algorithm EC -pkeyopt group:P-$ecc -pkeyopt parent:$TPM_ENDORSEMENT_PRIMARY_KEY_PERSISTANT_HANDLE -out $tpm_device_key_file" -success_string="$task completed successfully at $tpm_device_key_file !!" +success_string="$task completed successfully!!" failure_string="$task failed" execute_cmd_on_failure_exit "\${cmd}" "\${success_string}" "\${failure_string}" 1 1 task="Device CSR generation from TPM" cmd="$OPENSSL3_BIN/openssl req -new -provider tpm2 -provider default -outform DER -out $device_csr_file -key $tpm_device_key_file -subj \"/CN=sdo-tpm-device\" -verbose" -success_string="$task completed successfully at $device_csr_file !!" +success_string="$task completed successfully!!" +failure_string="$task failed" +execute_cmd_on_failure_exit "\$cmd" "\$success_string" "\$failure_string" 1 1 + +# write tpm device key and device csr inside tpm +task="Define a TPM Non-Volatile (NV) index for TPM KEY" +key_size=$(wc -c < $tpm_device_key_file) +cmd="tpm2_nvdefine -Q 0x1000008 -C o -s $key_size -a \"ownerwrite|authwrite|write_stclear|ownerread|authread|read_stclear\"" +success_string="$task completed successfully!!" failure_string="$task failed" execute_cmd_on_failure_exit "\$cmd" "\$success_string" "\$failure_string" 1 1 +task="Define a TPM Non-Volatile (NV) index for TPM Device CSR" +csr_size=$(wc -c < $device_csr_file) +cmd="tpm2_nvdefine -Q 0x1000009 -C o -s $csr_size -a \"ownerwrite|authwrite|write_stclear|ownerread|authread|read_stclear\"" +success_string="$task completed successfully!!" +failure_string="$task failed" +execute_cmd_on_failure_exit "\$cmd" "\$success_string" "\$failure_string" 1 1 + +task="Write TPM ECDSA KEY to a Non-Volatile (NV) index" +cmd="tpm2_nvwrite -Q 0x1000008 -C o -i $tpm_device_key_file" +success_string="$task completed successfully!!" +failure_string="$task failed" +execute_cmd_on_failure_exit "\$cmd" "\$success_string" "\$failure_string" 1 1 + +task="Write TPM Device CSR to a Non-Volatile (NV) index" +cmd="tpm2_nvwrite -Q 0x1000009 -C o -i $device_csr_file" +success_string="$task completed successfully!!" +failure_string="$task failed" +execute_cmd_on_failure_exit "\$cmd" "\$success_string" "\$failure_string" 1 1 + +rm -f $tpm_device_key_file +rm -f $device_csr_file +rm -f $tpm_endorsement_primary_key_ctx + From 936a82483fd25cb5a8d4a71f626d96b31a31f79b Mon Sep 17 00:00:00 2001 From: Shrikant Temburwar Date: Thu, 11 Jan 2024 22:33:33 +0530 Subject: [PATCH 3/9] Add execution logs in clear_tpm_nv.sh Signed-off-by: Shrikant Temburwar --- utils/clear_tpm_nv.sh | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/utils/clear_tpm_nv.sh b/utils/clear_tpm_nv.sh index ebf65e7d..7e8d93ed 100644 --- a/utils/clear_tpm_nv.sh +++ b/utils/clear_tpm_nv.sh @@ -1,7 +1,28 @@ #!/bin/bash +execute_cmd_on_failure_exit() +{ + eval exec_cmd="$1" + eval success_msg="$2" + eval failure_msg="$3" + + echo -e "\e[2;33mExecuting :\e[0m ${exec_cmd}" + out=$(eval ${exec_cmd}" 2>&1") + if [ `echo $?` != 0 ]; then + echo -e "\e[2;31m${failure_msg}\e[0m" + else + echo -e "\e[2;32m${success_msg}\e[0m" + fi + + return 0 +} + for n in {1..9}; do - tpm2_nvundefine $n + task="Deleting a Non-Volatile (NV) index at 0x100000$n" + cmd="tpm2_nvundefine 0x100000$n" + success_string="$task completed successfully!!" + failure_string="Non-Volatile (NV) index at 0x100000$n is not defined!!" + execute_cmd_on_failure_exit "\$cmd" "\$success_string" "\$failure_string" done echo "TPM NV storage cleared!" From 1b92b86951ab64bc9f53469d715e38d08269094c Mon Sep 17 00:00:00 2001 From: Shrikant Temburwar Date: Fri, 19 Jan 2024 19:34:04 +0530 Subject: [PATCH 4/9] Update TPM code as per specs Signed-off-by: Shrikant Temburwar --- app/blob.c | 24 +- app/main.c | 16 +- crypto/common/fdo_crypto_common.c | 4 - crypto/common/fdo_hmac.c | 44 +-- crypto/include/tpm20_Utils.h | 10 +- crypto/openssl/tpm20_ECDSA_sign_routines.c | 8 +- crypto/openssl/tpm20_Utils.c | 340 +++++++-------------- lib/credentials_from_file.c | 18 +- lib/include/load_credentials.h | 6 +- lib/m-string.c | 4 +- storage/include/storage_al.h | 12 +- storage/include/tpm2_nv_storage.h | 27 +- storage/linux/storage_if_linux.c | 241 ++------------- storage/linux/tpm2_nv_storage.c | 26 +- utils/clear_tpm_nv.sh | 4 +- utils/tpm_make_ready_ecdsa.sh | 12 +- 16 files changed, 186 insertions(+), 610 deletions(-) diff --git a/app/blob.c b/app/blob.c index 7e12e434..269c680d 100644 --- a/app/blob.c +++ b/app/blob.c @@ -59,7 +59,6 @@ static int32_t gen_rdm_bytestream(uint8_t *random_buffer, size_t num_bytes) } return 0; } -#endif int32_t configure_normal_blob(void) { @@ -72,19 +71,6 @@ int32_t configure_normal_blob(void) uint8_t *signed_normal_blob = NULL; size_t signed_normal_blob_size = 0; int32_t ret = -1; - -#if defined(DEVICE_TPM20_ENABLED) - if (0 == is_valid_tpm_data_protection_key_present()) { - if (0 != fdo_generate_storage_hmac_key()) { - LOG(LOG_ERROR, "Failed to generate TPM data protection" - " key.\n"); - goto err; - } - - LOG(LOG_DEBUG, - "TPM data protection key generated successfully.\n"); - } -#else uint8_t hmac_key[PLATFORM_HMAC_KEY_DEFAULT_LEN] = {0}; size_t key_size_stored = @@ -115,7 +101,6 @@ int32_t configure_normal_blob(void) LOG(LOG_ERROR, "Failed to read plain Normal blob!\n"); goto err; } -#endif raw_normal_blob_size = fdo_blob_size((char *)FDO_CRED_NORMAL, FDO_SDK_RAW_DATA); @@ -159,13 +144,6 @@ int32_t configure_normal_blob(void) "Malloc Failed for sealed Normal Blob buffer!\n"); goto err; } -#if defined(DEVICE_TPM20_ENABLED) - if (0 != fdo_compute_storage_hmac(raw_normal_blob, raw_normal_blob_size, - signed_normal_blob, - PLATFORM_HMAC_SIZE)) { - goto err; - } -#else #if defined(USE_MBEDTLS) if (0 != mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), (const uint8_t *)hmac_key, @@ -179,7 +157,6 @@ int32_t configure_normal_blob(void) signed_normal_blob, NULL)) { goto err; } -#endif #endif // copy plain-text size signed_normal_blob[PLATFORM_HMAC_SIZE + 3] = raw_normal_blob_size >> 0; @@ -215,3 +192,4 @@ int32_t configure_normal_blob(void) } return ret; } +#endif \ No newline at end of file diff --git a/app/main.c b/app/main.c index 29ae2043..c457494e 100644 --- a/app/main.c +++ b/app/main.c @@ -276,20 +276,7 @@ int app_main(bool is_resale) } #endif /* SECURE_ELEMENT */ -#if !defined(DEVICE_CSE_ENABLED) -#if defined(DEVICE_TPM20_ENABLED) - if (0 == is_valid_tpm_data_protection_key_present()) { - if (0 != fdo_generate_storage_hmac_key()) { - LOG(LOG_ERROR, "Failed to generate TPM data protection" - " key.\n"); - ret = -1; - goto end; - } - - LOG(LOG_DEBUG, - "TPM data protection key generated successfully.\n"); - } -#else +#if !defined(DEVICE_CSE_ENABLED) && !defined(DEVICE_TPM20_ENABLED) LOG(LOG_DEBUG, "CSE and TPM not enabled, Normal Blob Modules loaded!\n"); if (-1 == configure_normal_blob()) { @@ -298,7 +285,6 @@ int app_main(bool is_resale) ret = -1; goto end; } -#endif #endif /* List and Init all Sv_info modules */ diff --git a/crypto/common/fdo_crypto_common.c b/crypto/common/fdo_crypto_common.c index edab0c43..9f357db8 100644 --- a/crypto/common/fdo_crypto_common.c +++ b/crypto/common/fdo_crypto_common.c @@ -114,10 +114,6 @@ int32_t fdo_crypto_close(void) ret = crypto_close(); /* CLeanup of context structs */ cleanup_ctx(); -#if defined(DEVICE_TPM20_ENABLED) - /* clear the replacement hmac key objects */ - fdo_tpm_clear_replacement_hmac_key(); -#endif return ret; } diff --git a/crypto/common/fdo_hmac.c b/crypto/common/fdo_hmac.c index daee3e41..56c4828c 100644 --- a/crypto/common/fdo_hmac.c +++ b/crypto/common/fdo_hmac.c @@ -152,16 +152,14 @@ int32_t fdo_device_ov_hmac(uint8_t *OVHdr, size_t OVHdr_len, uint8_t *hmac, if (is_replacement_hmac) { #if defined(DEVICE_TPM20_ENABLED) return fdo_tpm_get_hmac(OVHdr, OVHdr_len, hmac, hmac_len, - TPM_HMAC_REPLACEMENT_PUB_KEY_NV_IDX, - TPM_HMAC_REPLACEMENT_PRIV_KEY_NV_IDX); + TPM_PRIMARY_KEY_PERSISTANT_HANDLE); #else keyset = get_replacement_OV_key(); #endif } else { #if defined(DEVICE_TPM20_ENABLED) return fdo_tpm_get_hmac(OVHdr, OVHdr_len, hmac, hmac_len, - TPM_HMAC_PUB_KEY_NV_IDX, - TPM_HMAC_PRIV_KEY_NV_IDX); + TPM_PRIMARY_KEY_PERSISTANT_HANDLE); #else keyset = get_OV_key(); #endif @@ -227,8 +225,7 @@ int32_t fdo_generate_ov_hmac_key(void) int32_t ret = -1; #if defined(DEVICE_TPM20_ENABLED) - if (0 != fdo_tpm_generate_hmac_key(TPM_HMAC_PUB_KEY_NV_IDX, - TPM_HMAC_PRIV_KEY_NV_IDX)) { + if (0 != fdo_tpm_generate_hmac_key(TPM_PRIMARY_KEY_PERSISTANT_HANDLE)) { LOG(LOG_ERROR, "Failed to generate device HMAC key" " from TPM.\n"); return ret; @@ -272,9 +269,7 @@ int32_t fdo_generate_ov_replacement_hmac_key(void) int32_t ret = -1; #if defined(DEVICE_TPM20_ENABLED) - if (0 != - fdo_tpm_generate_hmac_key(TPM_HMAC_REPLACEMENT_PUB_KEY_NV_IDX, - TPM_HMAC_REPLACEMENT_PRIV_KEY_NV_IDX)) { + if (0 != fdo_tpm_generate_hmac_key(TPM_PRIMARY_KEY_PERSISTANT_HANDLE)) { LOG(LOG_ERROR, "Failed to generate device replacement HMAC key" " from TPM.\n"); return ret; @@ -319,12 +314,6 @@ int32_t fdo_commit_ov_replacement_hmac_key(void) int32_t ret = -1; #if defined(DEVICE_TPM20_ENABLED) - if (0 != fdo_tpm_commit_replacement_hmac_key()) { - LOG(LOG_ERROR, "Failed to commit device replacement HMAC key" - " for TPM.\n"); - return ret; - } - ret = 0; #else fdo_byte_array_t **secret = get_replacement_OV_key(); @@ -368,18 +357,6 @@ int32_t fdo_compute_storage_hmac(const uint8_t *data, uint32_t data_length, goto error; } -#if defined(DEVICE_TPM20_ENABLED) - if (0 != fdo_tpm_get_hmac(data, data_length, computed_hmac, - computed_hmac_size, - TPM_HMAC_DATA_PUB_KEY_NV_IDX, - TPM_HMAC_DATA_PRIV_KEY_NV_IDX)) { - LOG(LOG_ERROR, "TPM HMAC Computation failed!\n"); - goto error; - } - - LOG(LOG_DEBUG, "TPM HMAC computed successfully!\n"); - -#else uint8_t hmac_key[PLATFORM_HMAC_KEY_DEFAULT_LEN] = {0}; if (!get_platform_hmac_key(hmac_key, PLATFORM_HMAC_KEY_DEFAULT_LEN)) { @@ -407,7 +384,6 @@ int32_t fdo_compute_storage_hmac(const uint8_t *data, uint32_t data_length, #endif return ret; } -#endif /** * fdo_generate_storage_hmac_key function generates Storage HMAC key @@ -422,18 +398,6 @@ int32_t fdo_generate_storage_hmac_key(void) #if defined(TARGET_OS_OPTEE) return 0; - -#elif defined(DEVICE_TPM20_ENABLED) - if (0 != fdo_tpm_generate_hmac_key(TPM_HMAC_DATA_PUB_KEY_NV_IDX, - TPM_HMAC_DATA_PRIV_KEY_NV_IDX)) { - LOG(LOG_ERROR, "Failed to generate TPM data protection " - "key.\n"); - return ret; - } - - ret = 0; - LOG(LOG_DEBUG, "TPM data protection key generated successfully.\n"); - #else uint8_t hmac_key[PLATFORM_HMAC_KEY_DEFAULT_LEN] = {0}; diff --git a/crypto/include/tpm20_Utils.h b/crypto/include/tpm20_Utils.h index 889b1bb8..54032b35 100644 --- a/crypto/include/tpm20_Utils.h +++ b/crypto/include/tpm20_Utils.h @@ -103,12 +103,8 @@ static const TPM2B_PUBLIC in_publicHMACKey_template = { }; int32_t fdo_tpm_get_hmac(const uint8_t *data, size_t data_length, uint8_t *hmac, - size_t hmac_length, uint32_t tpmHMACPub_key_nv, - uint32_t tpmHMACPriv_key_nv); -int32_t fdo_tpm_generate_hmac_key(uint32_t tpmHMACPub_key_nv, - uint32_t tpmHMACPriv_key_nv); -int32_t fdo_tpm_commit_replacement_hmac_key(void); -void fdo_tpm_clear_replacement_hmac_key(void); -int32_t is_valid_tpm_data_protection_key_present(void); + size_t hmac_length, + TPMI_DH_PERSISTENT persistent_handle); +int32_t fdo_tpm_generate_hmac_key(TPMI_DH_PERSISTENT persistent_handle); #endif /* #ifndef __TPM20_UTILS_H__ */ diff --git a/crypto/openssl/tpm20_ECDSA_sign_routines.c b/crypto/openssl/tpm20_ECDSA_sign_routines.c index 169499b1..4ac0025d 100644 --- a/crypto/openssl/tpm20_ECDSA_sign_routines.c +++ b/crypto/openssl/tpm20_ECDSA_sign_routines.c @@ -63,22 +63,22 @@ int32_t crypto_hal_ecdsa_sign(const uint8_t *data, size_t data_len, } // Read the key - size_t file_size = fdo_tpm_nvread_size(TPM_ECDSA_DEVICE_KEY_NV_IDX); + size_t key_size = fdo_tpm_nvread_size(TPM_ECDSA_DEVICE_KEY_NV_IDX); - pri_key = fdo_alloc(file_size); + pri_key = fdo_alloc(key_size); if (!pri_key) { LOG(LOG_ERROR, "Failed to allocate memory for private key.\n"); goto error; } - if (fdo_tpm_nvread(TPM_ECDSA_DEVICE_KEY_NV_IDX, file_size, &pri_key) == + if (fdo_tpm_nvread(TPM_ECDSA_DEVICE_KEY_NV_IDX, key_size, &pri_key) == -1) { LOG(LOG_ERROR, "Failed to load TPM HMAC Private Key into buffer.\n"); goto error; } - mem = BIO_new_mem_buf(pri_key, file_size); + mem = BIO_new_mem_buf(pri_key, key_size); if (mem == NULL) { LOG(LOG_ERROR, "Failed to create memory BIO\n"); goto error; diff --git a/crypto/openssl/tpm20_Utils.c b/crypto/openssl/tpm20_Utils.c index 461324c4..ee911cc5 100644 --- a/crypto/openssl/tpm20_Utils.c +++ b/crypto/openssl/tpm20_Utils.c @@ -33,29 +33,23 @@ static int32_t fdoTPMGenerate_primary_key_context(ESYS_CONTEXT **esys_context, * @param hmac: output buffer to save the HMAC * @param hmac_length: length of the output HMAC buffer *hash length - * @param tpmHMACPub_key: File name of the TPM HMAC public key - * @param tpmHMACPriv_key: File name of the TPM HMAC private key + * @param persistent_handle: Persistent handle of the TPM HMAC public key * @return * 0, on success * -1, on failure */ int32_t fdo_tpm_get_hmac(const uint8_t *data, size_t data_length, uint8_t *hmac, - size_t hmac_length, uint32_t tpmHMACPub_key_nv, - uint32_t tpmHMACPriv_key_nv) + size_t hmac_length, + TPMI_DH_PERSISTENT persistent_handle) { - int32_t ret = -1, ret_val = -1, file_size = 0; + int32_t ret = -1, ret_val = -1; size_t hashed_length = 0; - size_t offset = 0; - uint8_t bufferTPMHMACPriv_key[TPM_HMAC_PRIV_KEY_CONTEXT_SIZE] = {0}; - uint8_t bufferTPMHMACPub_key[TPM_HMAC_PUB_KEY_CONTEXT_SIZE] = {0}; ESYS_CONTEXT *esys_context = NULL; ESYS_TR primary_key_handle = ESYS_TR_NONE; ESYS_TR auth_session_handle = ESYS_TR_NONE; ESYS_TR hmac_key_handle = ESYS_TR_NONE; ESYS_TR sequence_handle = ESYS_TR_NONE; TPMT_TK_HASHCHECK *validation = NULL; - TPM2B_PUBLIC unmarshalHMACPub_key = {0}; - TPM2B_PRIVATE unmarshalHMACPriv_key = {0}; TPM2B_DIGEST *outHMAC = NULL; TPM2B_MAX_BUFFER block = {0}; TPM2B_AUTH null_auth = {0}; @@ -64,8 +58,7 @@ int32_t fdo_tpm_get_hmac(const uint8_t *data, size_t data_length, uint8_t *hmac, /* Validating all input parameters are passed in the function call*/ - if (!data || !data_length || !tpmHMACPub_key_nv || - !tpmHMACPriv_key_nv || !hmac || + if (!data || !data_length || !persistent_handle || !hmac || (hmac_length != PLATFORM_HMAC_SIZE)) { LOG(LOG_ERROR, "Failed to generate HMAC from TPM, invalid parameter" @@ -87,82 +80,12 @@ int32_t fdo_tpm_get_hmac(const uint8_t *data, size_t data_length, uint8_t *hmac, LOG(LOG_DEBUG, "TPM Primary Key Context created successfully.\n"); - /* Unmarshalling the HMAC Private key from the HMAC Private key file*/ - - file_size = fdo_tpm_nvread_size(tpmHMACPriv_key_nv); - - if (file_size != TPM_HMAC_PRIV_KEY_CONTEXT_SIZE_128 && - file_size != TPM_HMAC_PRIV_KEY_CONTEXT_SIZE) { - LOG(LOG_ERROR, "TPM HMAC Private Key file size incorrect.\n"); - goto err; - } - - LOG(LOG_DEBUG, - "TPM HMAC Private Key file size retreived successfully.\n"); - - if (fdo_tpm_read_nv(tpmHMACPriv_key_nv, FDO_SDK_RAW_DATA, - bufferTPMHMACPriv_key, file_size) == -1) { - LOG(LOG_ERROR, - "Failed to load TPM HMAC Private Key into buffer.\n"); - goto err; - } - - LOG(LOG_DEBUG, "TPM HMAC Private Key file content copied successfully" - " to buffer.\n"); - - ret_val = Tss2_MU_TPM2B_PRIVATE_Unmarshal( - bufferTPMHMACPriv_key, file_size, &offset, &unmarshalHMACPriv_key); - - if (ret_val != TSS2_RC_SUCCESS) { - LOG(LOG_ERROR, "Failed to unmarshal TPM HMAC Private Key.\n"); - goto err; - } - - LOG(LOG_DEBUG, - "TPM HMAC Private Key Unmarshal complete successfully.\n"); - - /* Unmarshalling the HMAC Public key from the HMAC public key file*/ - - file_size = fdo_tpm_nvread_size(tpmHMACPub_key_nv); - - if (file_size != TPM_HMAC_PUB_KEY_CONTEXT_SIZE) { - LOG(LOG_ERROR, "TPM HMAC Private Key file size incorrect.\n"); - goto err; - } - - LOG(LOG_DEBUG, - "TPM HMAC Public Key file size retreived successfully.\n"); - - if (fdo_tpm_read_nv(tpmHMACPub_key_nv, FDO_SDK_RAW_DATA, - bufferTPMHMACPub_key, file_size) == -1) { - LOG(LOG_ERROR, - "Failed to load TPM HMAC Public Key into buffer.\n"); - goto err; - } - - LOG(LOG_DEBUG, "TPM HMAC Public Key file content copied successfully" - " to buffer.\n"); - - offset = 0; - - ret_val = Tss2_MU_TPM2B_PUBLIC_Unmarshal( - bufferTPMHMACPub_key, file_size, &offset, &unmarshalHMACPub_key); - - if (ret_val != TSS2_RC_SUCCESS) { - LOG(LOG_ERROR, "Failed to unmarshal TPM HMAC Public Key.\n"); - goto err; - } - - LOG(LOG_DEBUG, - "TPM HMAC Public Key Unmarshal complete successfully.\n"); - /* Loading the TPM Primary key, HMAC public key and HMAC Private Key to * generate the HMAC Key Context */ ret_val = - Esys_Load(esys_context, primary_key_handle, auth_session_handle, - ESYS_TR_NONE, ESYS_TR_NONE, &unmarshalHMACPriv_key, - &unmarshalHMACPub_key, &hmac_key_handle); + Esys_TR_FromTPMPublic(esys_context, persistent_handle, ESYS_TR_NONE, + ESYS_TR_NONE, ESYS_TR_NONE, &hmac_key_handle); if (ret_val != TSS2_RC_SUCCESS) { LOG(LOG_ERROR, "Failed to load HMAC Key Context.\n"); @@ -311,7 +234,7 @@ int32_t fdo_tpm_get_hmac(const uint8_t *data, size_t data_length, uint8_t *hmac, err: if (esys_context) { if (hmac_key_handle != ESYS_TR_NONE) { - if (Esys_FlushContext(esys_context, hmac_key_handle) != + if (Esys_TR_Close(esys_context, &hmac_key_handle) != TSS2_RC_SUCCESS) { LOG(LOG_ERROR, "Failed to flush HMAC key handle.\n"); @@ -334,10 +257,6 @@ int32_t fdo_tpm_get_hmac(const uint8_t *data, size_t data_length, uint8_t *hmac, } TPM2_ZEROISE_FREE(validation); TPM2_ZEROISE_FREE(outHMAC); - memset_s(&unmarshalHMACPriv_key, sizeof(unmarshalHMACPriv_key), 0); - memset_s(&unmarshalHMACPub_key, sizeof(unmarshalHMACPub_key), 0); - memset_s(bufferTPMHMACPriv_key, sizeof(bufferTPMHMACPriv_key), 0); - memset_s(bufferTPMHMACPub_key, sizeof(bufferTPMHMACPub_key), 0); return ret; } @@ -345,20 +264,21 @@ int32_t fdo_tpm_get_hmac(const uint8_t *data, size_t data_length, uint8_t *hmac, /** * Generates HMAC Key inside TPM * - * @param tpmHMACPub_key: File name of the TPM HMAC public key - * @param tpmHMACPriv_key: File name of the TPM HMAC private key + * @param persistent_handle: Persistent handle of the TPM HMAC key * @return * 0, on success * -1, on failure */ -int32_t fdo_tpm_generate_hmac_key(uint32_t tpmHMACPub_key_nv, - uint32_t tpmHMACPriv_key_nv) +int32_t fdo_tpm_generate_hmac_key(TPMI_DH_PERSISTENT persistent_handle) { int32_t ret = -1; TSS2_RC ret_val = TPM2_RC_FAILURE; ESYS_CONTEXT *esys_context = NULL; ESYS_TR primary_key_handle = ESYS_TR_NONE; ESYS_TR auth_session_handle = ESYS_TR_NONE; + ESYS_TR object_handle = ESYS_TR_NONE; + ESYS_TR pub_object_handle = ESYS_TR_NONE; + ESYS_TR persistentHandle = ESYS_TR_NONE; TPM2B_PUBLIC *out_public = NULL; TPM2B_PRIVATE *out_private = NULL; TPM2B_CREATION_DATA *creation_data = NULL; @@ -370,10 +290,8 @@ int32_t fdo_tpm_generate_hmac_key(uint32_t tpmHMACPub_key_nv, TPML_PCR_SELECTION creationPCR = {0}; /* Using same buffer for both public and private context, private context size > public context size */ - uint8_t buffer[TPM_HMAC_PRIV_KEY_CONTEXT_SIZE] = {0}; - size_t offset = 0; - if (!tpmHMACPub_key_nv || !tpmHMACPriv_key_nv) { + if (!persistent_handle) { LOG(LOG_ERROR, "Failed to generate HMAC Key," "invalid parameters received.\n"); goto err; @@ -398,40 +316,62 @@ int32_t fdo_tpm_generate_hmac_key(uint32_t tpmHMACPub_key_nv, goto err; } - ret_val = Tss2_MU_TPM2B_PUBLIC_Marshal(out_public, buffer, - sizeof(buffer), &offset); + ret_val = Esys_Load(esys_context, primary_key_handle, + auth_session_handle, ESYS_TR_NONE, ESYS_TR_NONE, + out_private, out_public, &object_handle); if (ret_val != TSS2_RC_SUCCESS) { - LOG(LOG_ERROR, - "Failed to serialize the public HMAC key context.\n"); + LOG(LOG_ERROR, "Esys_Load failed: 0x%x\n", ret_val); + Esys_Finalize(&esys_context); goto err; } - if ((int32_t)offset != fdo_tpm_write_nv(tpmHMACPub_key_nv, - FDO_SDK_RAW_DATA, buffer, - offset)) { - LOG(LOG_ERROR, "Failed to save the public HMAC key context.\n"); + // Search the persistent Handle + TPMS_CAPABILITY_DATA *capability_data = NULL; + ret_val = Esys_GetCapability( + esys_context, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, + TPM2_CAP_HANDLES, persistent_handle, 1, NULL, &capability_data); + if (ret_val != TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, "Esys_GetCapability failed!\n"); goto err; } - LOG(LOG_DEBUG, "Saved HMAC public key context of size %zu.\n", offset); - offset = 0; - ret_val = Tss2_MU_TPM2B_PRIVATE_Marshal(out_private, buffer, - sizeof(buffer), &offset); - if (ret_val != TSS2_RC_SUCCESS) { - LOG(LOG_ERROR, - "Failed to serialize the private HMAC key context.\n"); - goto err; + int exists = + (capability_data->data.handles.count > 0 && + capability_data->data.handles.handle[0] == persistent_handle); + if (exists == 1) { + ret_val = Esys_TR_FromTPMPublic( + esys_context, persistent_handle, ESYS_TR_NONE, ESYS_TR_NONE, + ESYS_TR_NONE, &persistentHandle); + + if (ret_val != TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, "Failed to load HMAC Key Context.\n"); + goto err; + } + + ret_val = Esys_EvictControl(esys_context, ESYS_TR_RH_OWNER, + persistentHandle, ESYS_TR_PASSWORD, + ESYS_TR_NONE, ESYS_TR_NONE, 0, + &pub_object_handle); + if (ret_val != TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, "Esys_EvictControl failed: 0x%x\n", + ret_val); + Esys_Finalize(&esys_context); + goto err; + } } - if ((int32_t)offset != fdo_tpm_write_nv(tpmHMACPriv_key_nv, - FDO_SDK_RAW_DATA, buffer, - offset)) { - LOG(LOG_ERROR, - "Failed to save the private HMAC key context.\n"); + ret_val = Esys_EvictControl( + esys_context, ESYS_TR_RH_OWNER, object_handle, ESYS_TR_PASSWORD, + ESYS_TR_NONE, ESYS_TR_NONE, persistent_handle, &pub_object_handle); + if (ret_val != TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, "Esys_EvictControl failed: 0x%x\n", ret_val); goto err; } - LOG(LOG_DEBUG, "Saved HMAC private key context of size %zu.\n", offset); + LOG(LOG_DEBUG, + "Saved HMAC private key context inside persistance memory at " + "%d.\n", + persistent_handle); LOG(LOG_DEBUG, "HMAC Key generated successfully!.\n"); ret = 0; @@ -443,10 +383,54 @@ int32_t fdo_tpm_generate_hmac_key(uint32_t tpmHMACPub_key_nv, TPM2_ZEROISE_FREE(creation_hash); TPM2_ZEROISE_FREE(creation_ticket); - if (esys_context && - (0 != fdoTPMTSSContext_clean_up(&esys_context, &auth_session_handle, - &primary_key_handle))) { - LOG(LOG_ERROR, "Failed to tear down all the TSS context.\n"); + if (esys_context) { + if (object_handle != ESYS_TR_NONE) { + if (Esys_TR_Close(esys_context, &object_handle) != + TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, + "Failed to flush object_handle.\n"); + ret = -1; + } else { + LOG(LOG_DEBUG, + "object_handle flushed successfully.\n"); + object_handle = ESYS_TR_NONE; + } + } + + if (pub_object_handle != ESYS_TR_NONE) { + if (Esys_TR_Close(esys_context, &pub_object_handle) != + TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, + "Failed to flush pub_object_handle.\n"); + ret = -1; + } else { + LOG(LOG_DEBUG, "pub_object_handle flushed " + "successfully.\n"); + pub_object_handle = ESYS_TR_NONE; + } + } + + if (persistentHandle != ESYS_TR_NONE) { + if (Esys_TR_Close(esys_context, &persistentHandle) != + TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, + "Failed to flush persistent handle.\n"); + ret = -1; + } else { + LOG(LOG_DEBUG, "persistent handle flushed " + "successfully.\n"); + persistentHandle = ESYS_TR_NONE; + } + } + if (0 != fdoTPMTSSContext_clean_up(&esys_context, + &auth_session_handle, + &primary_key_handle)) { + LOG(LOG_ERROR, + "Failed to tear down all the TSS context.\n"); + ret = -1; + } else { + LOG(LOG_DEBUG, "TSS context flushed successfully.\n"); + } } return ret; @@ -668,115 +652,3 @@ static int32_t fdoTPMTSSContext_clean_up(ESYS_CONTEXT **esys_context, return 0; } - -/** - * Replace the TPM_HMAC_PRIV_KEY with TPM_HMAC_REPLACEMENT_PRIV_KEY and - * TPM_HMAC_PUB_KEY with TPM_HMAC_REPLACEMENT_PUB_KEY. - * - * @return - * -1, error - * 0, success - */ -int32_t fdo_tpm_commit_replacement_hmac_key(void) -{ - size_t file_size = 0; - // function return value - int32_t ret = -1; - uint8_t bufferTPMHMACPriv_key[TPM_HMAC_PRIV_KEY_CONTEXT_SIZE] = {0}; - uint8_t bufferTPMHMACPub_key[TPM_HMAC_PUB_KEY_CONTEXT_SIZE] = {0}; - - // read TPM_HMAC_REPLACEMENT_PRIV_KEY contents and write it into - // TPM_HMAC_PRIV_KEY - file_size = fdo_tpm_nvread_size(TPM_HMAC_REPLACEMENT_PRIV_KEY_NV_IDX); - - if (file_size != TPM_HMAC_PRIV_KEY_CONTEXT_SIZE_128 && - file_size != TPM_HMAC_PRIV_KEY_CONTEXT_SIZE) { - LOG(LOG_ERROR, - "TPM HMAC Replacement Private Key file size incorrect.\n"); - goto err; - } - - LOG(LOG_DEBUG, "TPM HMAC Replacement Private Key file size retreived " - "successfully.\n"); - - if (fdo_tpm_read_nv(TPM_HMAC_REPLACEMENT_PRIV_KEY_NV_IDX, - FDO_SDK_RAW_DATA, bufferTPMHMACPriv_key, - file_size) == -1) { - LOG(LOG_ERROR, "Failed to load TPM HMAC Replacement Private " - "Key into buffer.\n"); - goto err; - } - - if ((int32_t)file_size != - fdo_tpm_write_nv(TPM_HMAC_PRIV_KEY_NV_IDX, FDO_SDK_RAW_DATA, - bufferTPMHMACPriv_key, file_size)) { - LOG(LOG_ERROR, - "Failed to save the private HMAC key context.\n"); - goto err; - } - - // now, read TPM_HMAC_REPLACEMENT_PUB_KEY contents and write it into - // TPM_HMAC_PUB_KEY - file_size = fdo_tpm_nvread_size(TPM_HMAC_REPLACEMENT_PUB_KEY_NV_IDX); - - if (file_size != TPM_HMAC_PUB_KEY_CONTEXT_SIZE) { - LOG(LOG_ERROR, - "TPM HMAC Replacement Public Key file size incorrect.\n"); - goto err; - } - - LOG(LOG_DEBUG, "TPM HMAC Replacement Public Key file size retreived " - "successfully.\n"); - - if (fdo_tpm_read_nv(TPM_HMAC_REPLACEMENT_PUB_KEY_NV_IDX, - FDO_SDK_RAW_DATA, bufferTPMHMACPub_key, - file_size) == -1) { - LOG(LOG_ERROR, "Failed to load TPM HMAC Replacement Public key " - "into buffer.\n"); - goto err; - } - - if ((int32_t)file_size != - fdo_tpm_write_nv(TPM_HMAC_PUB_KEY_NV_IDX, FDO_SDK_RAW_DATA, - bufferTPMHMACPub_key, file_size)) { - LOG(LOG_ERROR, "Failed to save the public HMAC key context.\n"); - goto err; - } - ret = 0; -err: - return ret; -} - -/** - * Clear the Replacement TPM HMAC key objects, if they exist. - * - */ -void fdo_tpm_clear_replacement_hmac_key(void) -{ - // remove the files if they exist, else return - - if (0 != fdo_tpm_nvdel(TPM_HMAC_REPLACEMENT_PRIV_KEY_NV_IDX)) { - LOG(LOG_ERROR, "Failed to cleanup private object\n"); - } - - if (0 != fdo_tpm_nvdel(TPM_HMAC_REPLACEMENT_PUB_KEY_NV_IDX)) { - LOG(LOG_ERROR, "Failed to cleanup public object\n"); - } -} - -/** - * Check whether valid data integrity protection HMAC key is present or not. - * - * @return - * 1, present - * 0, not present - */ -int32_t is_valid_tpm_data_protection_key_present(void) -{ - return ((TPM_HMAC_PUB_KEY_CONTEXT_SIZE == - fdo_tpm_nvread_size(TPM_HMAC_DATA_PUB_KEY_NV_IDX)) && - (TPM_HMAC_PRIV_KEY_CONTEXT_SIZE_128 == - fdo_tpm_nvread_size(TPM_HMAC_DATA_PRIV_KEY_NV_IDX) || - TPM_HMAC_PRIV_KEY_CONTEXT_SIZE == - fdo_tpm_nvread_size(TPM_HMAC_DATA_PRIV_KEY_NV_IDX))); -} diff --git a/lib/credentials_from_file.c b/lib/credentials_from_file.c index 2866e112..a7efa881 100644 --- a/lib/credentials_from_file.c +++ b/lib/credentials_from_file.c @@ -480,8 +480,7 @@ int store_credential(fdo_dev_cred_t *ocred) * @return true if write and parsed correctly, otherwise false */ -bool write_tpm_device_credentials(uint32_t nv, fdo_sdk_blob_flags flags, - fdo_dev_cred_t *ocred) +bool write_tpm_device_credentials(uint32_t nv, fdo_dev_cred_t *ocred) { bool ret = true; @@ -559,8 +558,7 @@ bool write_tpm_device_credentials(uint32_t nv, fdo_sdk_blob_flags flags, } fdow->b.block_size = encoded_cred_length; - if (fdo_tpm_write_nv(nv, flags, fdow->b.block, fdow->b.block_size) == - -1) { + if (fdo_tpm_write_nv(nv, fdow->b.block, fdow->b.block_size) == -1) { LOG(LOG_ERROR, "Failed to write DeviceCredential blob\n"); ret = false; goto end; @@ -582,8 +580,7 @@ bool write_tpm_device_credentials(uint32_t nv, fdo_sdk_blob_flags flags, * @param our_dev_cred - pointer to the device credentials block, * @return true if read and parsed correctly, otherwise false. */ -bool read_tpm_device_credentials(uint32_t nv, fdo_sdk_blob_flags flags, - fdo_dev_cred_t *our_dev_cred) +bool read_tpm_device_credentials(uint32_t nv, fdo_dev_cred_t *our_dev_cred) { bool ret = false; size_t dev_cred_len = 0; @@ -627,8 +624,7 @@ bool read_tpm_device_credentials(uint32_t nv, fdo_sdk_blob_flags flags, goto end; } - if (fdo_tpm_read_nv(nv, flags, fdor->b.block, fdor->b.block_size) == - -1) { + if (fdo_tpm_read_nv(nv, fdor->b.block, fdor->b.block_size) == -1) { LOG(LOG_ERROR, "Failed to read DeviceCredential blob : Normal.blob\n"); goto end; @@ -744,8 +740,7 @@ int store_tpm_credential(fdo_dev_cred_t *ocred) { /* Write in the file and save the Normal device credentials */ LOG(LOG_DEBUG, "Writing to TPm NV storage\n"); - if (!write_tpm_device_credentials(FDO_CRED_NV_IDX, FDO_SDK_NORMAL_DATA, - ocred)) { + if (!write_tpm_device_credentials(FDO_CRED_NV_IDX, ocred)) { LOG(LOG_ERROR, "Could not write to Normal Credentials blob\n"); return -1; } @@ -914,8 +909,7 @@ int load_credential(fdo_dev_cred_t *ocred) } #elif defined(DEVICE_TPM20_ENABLED) /* Read and save the device credentials */ - if (!read_tpm_device_credentials(FDO_CRED_NV_IDX, FDO_SDK_NORMAL_DATA, - ocred)) { + if (!read_tpm_device_credentials(FDO_CRED_NV_IDX, ocred)) { LOG(LOG_ERROR, "Could not parse the Device Credentials blob\n"); return -1; } diff --git a/lib/include/load_credentials.h b/lib/include/load_credentials.h index 78877652..2b21d2aa 100644 --- a/lib/include/load_credentials.h +++ b/lib/include/load_credentials.h @@ -33,10 +33,8 @@ bool load_device_status(fdo_sdk_device_status *state); bool store_device_status(fdo_sdk_device_status *state); #if defined(DEVICE_TPM20_ENABLED) -bool read_tpm_device_credentials(uint32_t nv, fdo_sdk_blob_flags flags, - fdo_dev_cred_t *our_dev_cred); -bool write_tpm_device_credentials(uint32_t nv, fdo_sdk_blob_flags flags, - fdo_dev_cred_t *our_dev_cred); +bool read_tpm_device_credentials(uint32_t nv, fdo_dev_cred_t *our_dev_cred); +bool write_tpm_device_credentials(uint32_t nv, fdo_dev_cred_t *our_dev_cred); int store_tpm_credential(fdo_dev_cred_t *ocred); #endif diff --git a/lib/m-string.c b/lib/m-string.c index df0f2338..e8e2a1a0 100644 --- a/lib/m-string.c +++ b/lib/m-string.c @@ -261,8 +261,8 @@ int ps_get_m_string(fdo_prot_t *ps) goto err; } - if (fdo_tpm_read_nv(TPM_DEVICE_CSR_NV_IDX, FDO_SDK_RAW_DATA, csr->bytes, - csr->byte_sz) == -1) { + if (fdo_tpm_read_nv(TPM_DEVICE_CSR_NV_IDX, csr->bytes, csr->byte_sz) == + -1) { LOG(LOG_ERROR, "Failed to load TPM DEVICE CSR into buffer.\n"); goto err; } diff --git a/storage/include/storage_al.h b/storage/include/storage_al.h index 70ca04fc..f6c7e699 100644 --- a/storage/include/storage_al.h +++ b/storage/include/storage_al.h @@ -17,6 +17,9 @@ #include #include #include +#if defined(DEVICE_TPM20_ENABLED) +#include "tpm2_nv_storage.h" +#endif // platform HMAC and blob size #if defined(DEVICE_TPM20_ENABLED) && defined(ECDSA384_DA) @@ -47,13 +50,12 @@ size_t fdo_blob_size(const char *blob_name, fdo_sdk_blob_flags flags); int32_t create_hmac_normal_blob(void); #if defined(DEVICE_TPM20_ENABLED) -int32_t fdo_tpm_read_nv(uint32_t nv, fdo_sdk_blob_flags flags, uint8_t *buffer, - uint32_t length); +int32_t fdo_tpm_read_nv(TPMI_RH_NV_INDEX nv, uint8_t *buffer, uint32_t length); -int32_t fdo_tpm_write_nv(uint32_t nv, fdo_sdk_blob_flags flags, - const uint8_t *buffer, uint32_t length); +int32_t fdo_tpm_write_nv(TPMI_RH_NV_INDEX nv, const uint8_t *buffer, + uint32_t length); -size_t fdo_tpm_size_nv(uint32_t nv); +size_t fdo_tpm_size_nv(TPMI_RH_NV_INDEX nv); #endif #ifdef __cplusplus } // endof externc (CPP code) diff --git a/storage/include/tpm2_nv_storage.h b/storage/include/tpm2_nv_storage.h index e0f59694..c84cfb5b 100644 --- a/storage/include/tpm2_nv_storage.h +++ b/storage/include/tpm2_nv_storage.h @@ -5,19 +5,10 @@ #include #include -#define FDO_CRED_NV_IDX 0x1000001 - -#define TPM_HMAC_PUB_KEY_NV_IDX 0x1000002 -#define TPM_HMAC_PRIV_KEY_NV_IDX 0x1000003 - -#define TPM_HMAC_DATA_PUB_KEY_NV_IDX 0x1000004 -#define TPM_HMAC_DATA_PRIV_KEY_NV_IDX 0x1000005 - -#define TPM_HMAC_REPLACEMENT_PUB_KEY_NV_IDX 0x1000006 -#define TPM_HMAC_REPLACEMENT_PRIV_KEY_NV_IDX 0x1000007 - -#define TPM_ECDSA_DEVICE_KEY_NV_IDX 0x1000008 -#define TPM_DEVICE_CSR_NV_IDX 0x1000009 +#define FDO_CRED_NV_IDX 0x01D10001 +#define TPM_PRIMARY_KEY_PERSISTANT_HANDLE 0x81020003 +#define TPM_ECDSA_DEVICE_KEY_NV_IDX 0x01D10004 +#define TPM_DEVICE_CSR_NV_IDX 0x01D10005 #if defined(ECDSA256_DA) #define FDO_TPM2_ALG_SHA TPM2_ALG_SHA256 @@ -32,7 +23,7 @@ * @retval -1 on undefined/general failure. * @retval TSS2_RC response code for failures relayed from the TSS library. */ -int fdo_tpm_nvdefine(uint32_t nv, size_t data_size); +int fdo_tpm_nvdefine(TPMI_RH_NV_INDEX nv, size_t data_size); /** Store a data in a NV index. * @@ -43,7 +34,7 @@ int fdo_tpm_nvdefine(uint32_t nv, size_t data_size); * @retval -1 on undefined/general failure. * @retval TSS2_RC response code for failures relayed from the TSS library. */ -int fdo_tpm_nvwrite(const uint8_t *data, size_t data_size, uint32_t nv); +int fdo_tpm_nvwrite(const uint8_t *data, size_t data_size, TPMI_RH_NV_INDEX nv); /** Load data size from a NV index. * @@ -52,7 +43,7 @@ int fdo_tpm_nvwrite(const uint8_t *data, size_t data_size, uint32_t nv); * @retval -1 on undefined/general failure. * @retval TSS2_RC response code for failures relayed from the TSS library. */ -size_t fdo_tpm_nvread_size(uint32_t nv); +size_t fdo_tpm_nvread_size(TPMI_RH_NV_INDEX nv); /** Load a data from a NV index. * @@ -63,7 +54,7 @@ size_t fdo_tpm_nvread_size(uint32_t nv); * @retval -1 on undefined/general failure. * @retval TSS2_RC response code for failures relayed from the TSS library. */ -int fdo_tpm_nvread(uint32_t nv, size_t data_size, uint8_t **data); +int fdo_tpm_nvread(TPMI_RH_NV_INDEX nv, size_t data_size, uint8_t **data); /** Delete data from a NV index. * @@ -72,4 +63,4 @@ int fdo_tpm_nvread(uint32_t nv, size_t data_size, uint8_t **data); * @retval -1 on undefined/general failure. * @retval TSS2_RC response code for failures relayed from the TSS library. */ -int fdo_tpm_nvdel(uint32_t nv); \ No newline at end of file +int fdo_tpm_nvdel(TPMI_RH_NV_INDEX nv); \ No newline at end of file diff --git a/storage/linux/storage_if_linux.c b/storage/linux/storage_if_linux.c index 75c7a1d7..fde1345a 100644 --- a/storage/linux/storage_if_linux.c +++ b/storage/linux/storage_if_linux.c @@ -21,7 +21,7 @@ #include "crypto_utils.h" #include "platform_utils.h" #if defined(DEVICE_TPM20_ENABLED) -#include "tpm2_nv_storage.h" +#include "tpm20_Utils.h" #endif /**************************************************** @@ -573,7 +573,7 @@ int32_t fdo_blob_write(const char *name, fdo_sdk_blob_flags flags, * @return file size on success, 0 if file does not exist or on other failure */ -size_t fdo_tpm_size_nv(uint32_t nv) +size_t fdo_tpm_size_nv(TPMI_RH_NV_INDEX nv) { size_t retval = 0; const size_t NORMAL_NV_OVERHEAD = @@ -623,23 +623,16 @@ size_t fdo_tpm_size_nv(uint32_t nv) * @param n_bytes - length of data(in bytes) to be read * @return num of bytes read if success, -1 on error */ -int32_t fdo_tpm_read_nv(uint32_t nv, fdo_sdk_blob_flags flags, uint8_t *buf, - uint32_t n_bytes) +int32_t fdo_tpm_read_nv(TPMI_RH_NV_INDEX nv, uint8_t *buf, uint32_t n_bytes) { int retval = -1; uint8_t *data = NULL; uint32_t data_length = 0; uint8_t *sealed_data = NULL; uint32_t sealed_data_len = 0; - uint8_t *encrypted_data = NULL; - uint32_t encrypted_data_len = 0; uint8_t stored_hmac[PLATFORM_HMAC_SIZE] = {0}; uint8_t computed_hmac[PLATFORM_HMAC_SIZE] = {0}; - uint8_t stored_tag[AES_TAG_LEN] = {0}; int strcmp_result = -1; - uint8_t iv[PLATFORM_IV_DEFAULT_LEN] = {0}; - uint8_t aes_key[PLATFORM_AES_KEY_DEFAULT_LEN] = {0}; - size_t dat_len_offst = 0; if (!nv || !buf || n_bytes == 0) { LOG(LOG_ERROR, "Invalid parameters in %s!\n", __func__); @@ -654,15 +647,7 @@ int32_t fdo_tpm_read_nv(uint32_t nv, fdo_sdk_blob_flags flags, uint8_t *buf, goto exit; } - switch (flags) { - case FDO_SDK_RAW_DATA: - if (0 != fdo_tpm_nvread(nv, n_bytes, &buf)) { - LOG(LOG_ERROR, "Failed to read file!\n"); - goto exit; - } - break; - - case FDO_SDK_NORMAL_DATA: + if (nv == FDO_CRED_NV_IDX) { /* HMAC-256 is being used to store files under * FDO_SDK_NORMAL_DATA flag. * File content to be stored as: @@ -711,9 +696,9 @@ int32_t fdo_tpm_read_nv(uint32_t nv, fdo_sdk_blob_flags flags, uint8_t *buf, data = sealed_data + PLATFORM_HMAC_SIZE + BLOB_CONTENT_SIZE; - if (0 != fdo_compute_storage_hmac(data, data_length, - computed_hmac, - PLATFORM_HMAC_SIZE)) { + if (0 != fdo_tpm_get_hmac(data, data_length, computed_hmac, + PLATFORM_HMAC_SIZE, + TPM_PRIMARY_KEY_PERSISTANT_HANDLE)) { LOG(LOG_ERROR, "HMAC computation dailed during" " %s!\n", @@ -740,104 +725,16 @@ int32_t fdo_tpm_read_nv(uint32_t nv, fdo_sdk_blob_flags flags, uint8_t *buf, __func__); goto exit; } - break; - - case FDO_SDK_SECURE_DATA: - /* AES GCM authenticated encryption is being used to store files - * under - * FDO_SDK_SECURE_DATA flag. File content to be stored as: - * [IV_data(12byte)||[AuthenticatedTAG(16 bytes)|| - * Sizeof_ciphertext(8 * bytes)||Ciphertet(n_bytes bytes)] - */ - - encrypted_data_len = PLATFORM_IV_DEFAULT_LEN + AES_TAG_LEN + - BLOB_CONTENT_SIZE + n_bytes; - - encrypted_data = fdo_alloc(encrypted_data_len); - if (NULL == encrypted_data) { - LOG(LOG_ERROR, "Malloc Failed in %s!\n", __func__); - goto exit; - } - - if (fdo_tpm_nvread(nv, encrypted_data_len, &encrypted_data)) { + } else { + if (0 != fdo_tpm_nvread(nv, n_bytes, &buf)) { LOG(LOG_ERROR, "Failed to read file!\n"); goto exit; } - - dat_len_offst = AES_TAG_LEN + PLATFORM_IV_DEFAULT_LEN; - // get actual data length - data_length |= encrypted_data[dat_len_offst] << 24; - data_length |= encrypted_data[dat_len_offst + 1] << 16; - data_length |= encrypted_data[dat_len_offst + 2] << 8; - data_length |= (encrypted_data[dat_len_offst + 3] & 0x000000FF); - - // check if input buffer is sufficient ? - if (n_bytes < data_length) { - LOG(LOG_ERROR, - "Failed to read data, Buffer is not enough, " - "buf_len:%d,\t Lengthstoredinfilesystem:%d\n", - n_bytes, data_length); - goto exit; - } - /* read the iv from blob */ - if (memcpy_s(iv, PLATFORM_IV_DEFAULT_LEN, encrypted_data, - PLATFORM_IV_DEFAULT_LEN) != 0) { - LOG(LOG_ERROR, - "Copying stored IV failed during " - "%s!\n", - __func__); - goto exit; - } - - if (memcpy_s(stored_tag, AES_TAG_LEN, - encrypted_data + PLATFORM_IV_DEFAULT_LEN, - AES_TAG_LEN) != 0) { - LOG(LOG_ERROR, - "Copying stored TAG failed during " - "%s!\n", - __func__); - goto exit; - } - - data = encrypted_data + PLATFORM_IV_DEFAULT_LEN + AES_TAG_LEN + - BLOB_CONTENT_SIZE; - - if (!get_platform_aes_key(aes_key, - PLATFORM_AES_KEY_DEFAULT_LEN)) { - LOG(LOG_ERROR, "Could not get platform AES Key!\n"); - goto exit; - } - - // decrypt and authenticate cipher-text content and fill the - // given buffer with clear-text - if (crypto_hal_aes_decrypt( - buf, &n_bytes, data, data_length, 16, iv, aes_key, - PLATFORM_AES_KEY_DEFAULT_LEN, stored_tag, AES_TAG_LEN, - NULL, 0) < 0) { - LOG(LOG_ERROR, "Decryption failed during Secure " - "Blob Read!\n"); - goto exit; - } - break; - - default: - LOG(LOG_ERROR, "Invalid FDO blob flag!!\n"); - goto exit; } retval = (int32_t)n_bytes; exit: - if (sealed_data) { - fdo_free(sealed_data); - } - if (encrypted_data) { - fdo_free(encrypted_data); - } - if (memset_s(aes_key, PLATFORM_AES_KEY_DEFAULT_LEN, 0)) { - LOG(LOG_ERROR, "Failed to clear AES key\n"); - retval = -1; - } return retval; } @@ -853,18 +750,12 @@ int32_t fdo_tpm_read_nv(uint32_t nv, fdo_sdk_blob_flags flags, uint8_t *buf, * @return num of bytes write if success, -1 on error */ -int32_t fdo_tpm_write_nv(uint32_t nv, fdo_sdk_blob_flags flags, - const uint8_t *buf, uint32_t n_bytes) +int32_t fdo_tpm_write_nv(TPMI_RH_NV_INDEX nv, const uint8_t *buf, + uint32_t n_bytes) { int retval = -1; - FILE *f = NULL; uint32_t write_context_len = 0; - uint32_t write_context_len_temp = 0; uint8_t *write_context = NULL; - uint8_t tag[AES_TAG_LEN] = {0}; - uint8_t iv[PLATFORM_IV_DEFAULT_LEN] = {0}; - uint8_t aes_key[PLATFORM_AES_KEY_DEFAULT_LEN] = {0}; - size_t dat_len_offst = 0; if (!buf || !nv || n_bytes == 0) { LOG(LOG_ERROR, "Invalid parameters in %s!\n", __func__); @@ -879,26 +770,7 @@ int32_t fdo_tpm_write_nv(uint32_t nv, fdo_sdk_blob_flags flags, goto exit; } - switch (flags) { - case FDO_SDK_RAW_DATA: - // Raw Files are stored as plain files - write_context_len = n_bytes; - - write_context = fdo_alloc(write_context_len); - if (NULL == write_context) { - LOG(LOG_ERROR, "Malloc Failed in %s!\n", __func__); - goto exit; - } - - if (memcpy_s(write_context, write_context_len, buf, n_bytes) != - 0) { - LOG(LOG_ERROR, - "Copying data failed during RAW Blob write!\n"); - goto exit; - } - break; - - case FDO_SDK_NORMAL_DATA: + if (nv == FDO_CRED_NV_IDX) { /* HMAC-256 is being used to store files under * FDO_SDK_NORMAL_DATA flag. * File content to be stored as: @@ -914,10 +786,10 @@ int32_t fdo_tpm_write_nv(uint32_t nv, fdo_sdk_blob_flags flags, goto exit; } - if (0 != fdo_compute_storage_hmac(buf, n_bytes, write_context, - PLATFORM_HMAC_SIZE)) { - LOG(LOG_ERROR, "Computing HMAC failed during Normal " - "Blob write!\n"); + if (0 != fdo_tpm_get_hmac(buf, n_bytes, write_context, + PLATFORM_HMAC_SIZE, + TPM_PRIMARY_KEY_PERSISTANT_HANDLE)) { + LOG(LOG_ERROR, "Computing HMAC failed!\n"); goto exit; } @@ -937,18 +809,8 @@ int32_t fdo_tpm_write_nv(uint32_t nv, fdo_sdk_blob_flags flags, "Copying data failed during Normal Blob write!\n"); goto exit; } - break; - - case FDO_SDK_SECURE_DATA: - /* AES GCM authenticated encryption is being used to store files - * under - * FDO_SDK_SECURE_DATA flag. File content to be stored as: - * [IV_data(12byte)||[AuthenticatedTAG(16 bytes)|| - * Sizeof_ciphertext(8 * bytes)||Ciphertet(n_bytes bytes)] - */ - - write_context_len = PLATFORM_IV_DEFAULT_LEN + AES_TAG_LEN + - BLOB_CONTENT_SIZE + n_bytes; + } else { + write_context_len = n_bytes; write_context = fdo_alloc(write_context_len); if (NULL == write_context) { @@ -956,62 +818,12 @@ int32_t fdo_tpm_write_nv(uint32_t nv, fdo_sdk_blob_flags flags, goto exit; } - if (!get_platform_iv(iv, PLATFORM_IV_DEFAULT_LEN, n_bytes)) { - LOG(LOG_ERROR, "Could not get platform IV!\n"); - goto exit; - } - - if (!get_platform_aes_key(aes_key, - PLATFORM_AES_KEY_DEFAULT_LEN)) { - LOG(LOG_ERROR, "Could not get platform AES Key!\n"); - goto exit; - } - - write_context_len_temp = - write_context_len - - (PLATFORM_IV_DEFAULT_LEN + AES_TAG_LEN + BLOB_CONTENT_SIZE); - // encrypt plain-text and copy cipher-text content - if (crypto_hal_aes_encrypt( - buf, n_bytes, - &write_context[PLATFORM_IV_DEFAULT_LEN + AES_TAG_LEN + - BLOB_CONTENT_SIZE], - &write_context_len_temp, 16, iv, aes_key, - PLATFORM_AES_KEY_DEFAULT_LEN, tag, AES_TAG_LEN, NULL, - 0) < 0) { - LOG(LOG_ERROR, "Encypting data failed during Secure " - "Blob write!\n"); - goto exit; - } - // copy used IV for encryption - if (memcpy_s(write_context, PLATFORM_IV_DEFAULT_LEN, iv, - PLATFORM_IV_DEFAULT_LEN) != 0) { - LOG(LOG_ERROR, "Copying TAG value failed during Secure " - "Blob write!\n"); - goto exit; - } - - // copy Authenticated TAG value - if (memcpy_s(write_context + PLATFORM_IV_DEFAULT_LEN, - write_context_len - PLATFORM_IV_DEFAULT_LEN, tag, - AES_TAG_LEN) != 0) { - LOG(LOG_ERROR, "Copying TAG value failed during Secure " - "Blob write!\n"); + if (memcpy_s(write_context, write_context_len, buf, n_bytes) != + 0) { + LOG(LOG_ERROR, + "Copying data failed during RAW Blob write!\n"); goto exit; } - - dat_len_offst = AES_TAG_LEN + PLATFORM_IV_DEFAULT_LEN; - /* copy cipher-text size; CT size= PT size (AES GCM uses AES CTR - * mode internally for encryption) - */ - write_context[dat_len_offst + 3] = n_bytes >> 0; - write_context[dat_len_offst + 2] = n_bytes >> 8; - write_context[dat_len_offst + 1] = n_bytes >> 16; - write_context[dat_len_offst + 0] = n_bytes >> 24; - break; - - default: - LOG(LOG_ERROR, "Invalid FDO blob flag!!\n"); - goto exit; } if (fdo_tpm_nvwrite(write_context, write_context_len, nv)) { @@ -1025,15 +837,6 @@ int32_t fdo_tpm_write_nv(uint32_t nv, fdo_sdk_blob_flags flags, if (write_context) { fdo_free(write_context); } - if (f) { - if (fclose(f) == EOF) { - LOG(LOG_ERROR, "fclose() Failed in %s\n", __func__); - } - } - if (memset_s(aes_key, PLATFORM_AES_KEY_DEFAULT_LEN, 0)) { - LOG(LOG_ERROR, "Failed to clear AES key\n"); - retval = -1; - } return retval; } #endif \ No newline at end of file diff --git a/storage/linux/tpm2_nv_storage.c b/storage/linux/tpm2_nv_storage.c index 7fef660f..4cb4c47e 100644 --- a/storage/linux/tpm2_nv_storage.c +++ b/storage/linux/tpm2_nv_storage.c @@ -157,7 +157,7 @@ static int32_t fdo_tpm_context_clean_up(ESYS_CONTEXT **esys_context, * @retval -1 on undefined/general failure. * @retval TSS2_RC response code for failures relayed from the TSS library. */ -int fdo_tpm_nvdefine(uint32_t nv, size_t data_size) +int fdo_tpm_nvdefine(TPMI_RH_NV_INDEX nv, size_t data_size) { if (!nv) { @@ -178,9 +178,9 @@ int fdo_tpm_nvdefine(uint32_t nv, size_t data_size) .nvPublic = { .nvIndex = nv, .nameAlg = FDO_TPM2_ALG_SHA, - .attributes = (TPMA_NV_OWNERWRITE | TPMA_NV_AUTHWRITE | - TPMA_NV_WRITE_STCLEAR | TPMA_NV_READ_STCLEAR | - TPMA_NV_AUTHREAD | TPMA_NV_OWNERREAD), + .attributes = + (TPMA_NV_OWNERWRITE | TPMA_NV_AUTHWRITE | TPMA_NV_AUTHREAD | + TPMA_NV_OWNERREAD | TPMA_NV_NO_DA), .authPolicy = { .size = 0, @@ -255,7 +255,7 @@ int fdo_tpm_nvdefine(uint32_t nv, size_t data_size) * @retval -1 on undefined/general failure. * @retval TSS2_RC response code for failures relayed from the TSS library. */ -int fdo_tpm_nvwrite(const uint8_t *data, size_t data_size, uint32_t nv) +int fdo_tpm_nvwrite(const uint8_t *data, size_t data_size, TPMI_RH_NV_INDEX nv) { if (!data || !nv) { return -1; @@ -275,9 +275,9 @@ int fdo_tpm_nvwrite(const uint8_t *data, size_t data_size, uint32_t nv) .nvPublic = { .nvIndex = nv, .nameAlg = FDO_TPM2_ALG_SHA, - .attributes = (TPMA_NV_OWNERWRITE | TPMA_NV_AUTHWRITE | - TPMA_NV_WRITE_STCLEAR | TPMA_NV_READ_STCLEAR | - TPMA_NV_AUTHREAD | TPMA_NV_OWNERREAD), + .attributes = + (TPMA_NV_OWNERWRITE | TPMA_NV_AUTHWRITE | TPMA_NV_AUTHREAD | + TPMA_NV_OWNERREAD | TPMA_NV_NO_DA), .authPolicy = { .size = 0, @@ -291,7 +291,6 @@ int fdo_tpm_nvwrite(const uint8_t *data, size_t data_size, uint32_t nv) LOG(LOG_ERROR, "Data too large.\n"); return -1; } - // memcpy(&blob.buffer[0], data, blob.size); if (memcpy_s(&blob.buffer[0], blob.size, data, data_size) != 0) { LOG(LOG_ERROR, "Failed to copy data to blob!\n"); @@ -380,7 +379,7 @@ int fdo_tpm_nvwrite(const uint8_t *data, size_t data_size, uint32_t nv) * @retval -1 on undefined/general failure. * @retval TSS2_RC response code for failures relayed from the TSS library. */ -size_t fdo_tpm_nvread_size(uint32_t nv) +size_t fdo_tpm_nvread_size(TPMI_RH_NV_INDEX nv) { int ret = -1; TSS2_RC rc; @@ -471,7 +470,7 @@ size_t fdo_tpm_nvread_size(uint32_t nv) * @retval -1 on undefined/general failure. * @retval TSS2_RC response code for failures relayed from the TSS library. */ -int fdo_tpm_nvread(uint32_t nv, size_t data_size, uint8_t **data) +int fdo_tpm_nvread(TPMI_RH_NV_INDEX nv, size_t data_size, uint8_t **data) { int ret = -1; TSS2_RC rc; @@ -525,9 +524,6 @@ int fdo_tpm_nvread(uint32_t nv, size_t data_size, uint8_t **data) goto err; } - // *data_size = blob->size; - // *data = malloc(blob->size); - // memcpy(*data, &blob->buffer[0], blob->size); if (memcpy_s(*data, data_size, &blob->buffer[0], blob->size) != 0) { LOG(LOG_ERROR, "Failed to copy data to blob!\n"); goto err; @@ -556,7 +552,7 @@ int fdo_tpm_nvread(uint32_t nv, size_t data_size, uint8_t **data) * @retval -1 on undefined/general failure. * @retval TSS2_RC response code for failures relayed from the TSS library. */ -int fdo_tpm_nvdel(uint32_t nv) +int fdo_tpm_nvdel(TPMI_RH_NV_INDEX nv) { int ret = -1; TSS2_RC rc; diff --git a/utils/clear_tpm_nv.sh b/utils/clear_tpm_nv.sh index 7e8d93ed..83c250e5 100644 --- a/utils/clear_tpm_nv.sh +++ b/utils/clear_tpm_nv.sh @@ -17,10 +17,10 @@ execute_cmd_on_failure_exit() return 0 } -for n in {1..9}; +for n in {1,4,5}; do task="Deleting a Non-Volatile (NV) index at 0x100000$n" - cmd="tpm2_nvundefine 0x100000$n" + cmd="tpm2_nvundefine 0x01D1000$n" success_string="$task completed successfully!!" failure_string="Non-Volatile (NV) index at 0x100000$n is not defined!!" execute_cmd_on_failure_exit "\$cmd" "\$success_string" "\$failure_string" diff --git a/utils/tpm_make_ready_ecdsa.sh b/utils/tpm_make_ready_ecdsa.sh index a0ca2839..dc5ecf97 100644 --- a/utils/tpm_make_ready_ecdsa.sh +++ b/utils/tpm_make_ready_ecdsa.sh @@ -6,7 +6,7 @@ DEVICE_CSR_FILE_INSIDE_DATA_DIR="tpm_device_csr" PARENT_DIR="" TPM_ENDORSEMENT_PRIMARY_KEY_CTX=tpm_primary_key.ctx -TPM_ENDORSEMENT_PRIMARY_KEY_PERSISTANT_HANDLE=0x81000001 +TPM_ENDORSEMENT_PRIMARY_KEY_PERSISTANT_HANDLE=0x81020002 found_path=0 verbose=0 @@ -106,7 +106,7 @@ execute_cmd_on_failure_exit "\$cmd" "\$success_string" "\$failure_string" 1 1 task="Load primary key inside persistance memory at $TPM_ENDORSEMENT_PRIMARY_KEY_PERSISTANT_HANDLE" cmd="tpm2_evictcontrol -C o $TPM_ENDORSEMENT_PRIMARY_KEY_PERSISTANT_HANDLE -c $tpm_endorsement_primary_key_ctx -V" -success_string="$task completed successfully at!!" +success_string="$task completed successfully!!" failure_string="$task failed" execute_cmd_on_failure_exit "\$cmd" "\$success_string" "\$failure_string" 1 1 @@ -125,26 +125,26 @@ execute_cmd_on_failure_exit "\$cmd" "\$success_string" "\$failure_string" 1 1 # write tpm device key and device csr inside tpm task="Define a TPM Non-Volatile (NV) index for TPM KEY" key_size=$(wc -c < $tpm_device_key_file) -cmd="tpm2_nvdefine -Q 0x1000008 -C o -s $key_size -a \"ownerwrite|authwrite|write_stclear|ownerread|authread|read_stclear\"" +cmd="tpm2_nvdefine -Q 0x01D10004 -C o -s $key_size -a \"ownerwrite|authwrite|ownerread|authread|no_da\"" success_string="$task completed successfully!!" failure_string="$task failed" execute_cmd_on_failure_exit "\$cmd" "\$success_string" "\$failure_string" 1 1 task="Define a TPM Non-Volatile (NV) index for TPM Device CSR" csr_size=$(wc -c < $device_csr_file) -cmd="tpm2_nvdefine -Q 0x1000009 -C o -s $csr_size -a \"ownerwrite|authwrite|write_stclear|ownerread|authread|read_stclear\"" +cmd="tpm2_nvdefine -Q 0x01D10005 -C o -s $csr_size -a \"ownerwrite|authwrite|ownerread|authread|no_da\"" success_string="$task completed successfully!!" failure_string="$task failed" execute_cmd_on_failure_exit "\$cmd" "\$success_string" "\$failure_string" 1 1 task="Write TPM ECDSA KEY to a Non-Volatile (NV) index" -cmd="tpm2_nvwrite -Q 0x1000008 -C o -i $tpm_device_key_file" +cmd="tpm2_nvwrite -Q 0x01D10004 -C o -i $tpm_device_key_file" success_string="$task completed successfully!!" failure_string="$task failed" execute_cmd_on_failure_exit "\$cmd" "\$success_string" "\$failure_string" 1 1 task="Write TPM Device CSR to a Non-Volatile (NV) index" -cmd="tpm2_nvwrite -Q 0x1000009 -C o -i $device_csr_file" +cmd="tpm2_nvwrite -Q 0x01D10005 -C o -i $device_csr_file" success_string="$task completed successfully!!" failure_string="$task failed" execute_cmd_on_failure_exit "\$cmd" "\$success_string" "\$failure_string" 1 1 From b2ba9606335939b60af2ccd516fb0873abcae06a Mon Sep 17 00:00:00 2001 From: Shrikant Temburwar Date: Sat, 20 Jan 2024 19:46:51 +0530 Subject: [PATCH 5/9] Update device key generation according to FDO TPM spec Signed-off-by: Shrikant Temburwar --- crypto/common/fdo_hmac.c | 8 +- crypto/include/tpm20_Utils.h | 134 ++++++------ crypto/openssl/tpm20_ECDSA_sign_routines.c | 240 +++++++-------------- crypto/openssl/tpm20_Utils.c | 28 +-- lib/include/fdoprot.h | 2 +- storage/include/tpm2_nv_storage.h | 4 +- storage/linux/storage_if_linux.c | 4 +- utils/clear_tpm_nv.sh | 6 +- utils/tpm_make_ready_ecdsa.sh | 50 ++--- 9 files changed, 189 insertions(+), 287 deletions(-) diff --git a/crypto/common/fdo_hmac.c b/crypto/common/fdo_hmac.c index 56c4828c..db82fa1c 100644 --- a/crypto/common/fdo_hmac.c +++ b/crypto/common/fdo_hmac.c @@ -152,14 +152,14 @@ int32_t fdo_device_ov_hmac(uint8_t *OVHdr, size_t OVHdr_len, uint8_t *hmac, if (is_replacement_hmac) { #if defined(DEVICE_TPM20_ENABLED) return fdo_tpm_get_hmac(OVHdr, OVHdr_len, hmac, hmac_len, - TPM_PRIMARY_KEY_PERSISTANT_HANDLE); + TPM_HMAC_KEY_PERSISTANT_HANDLE); #else keyset = get_replacement_OV_key(); #endif } else { #if defined(DEVICE_TPM20_ENABLED) return fdo_tpm_get_hmac(OVHdr, OVHdr_len, hmac, hmac_len, - TPM_PRIMARY_KEY_PERSISTANT_HANDLE); + TPM_HMAC_KEY_PERSISTANT_HANDLE); #else keyset = get_OV_key(); #endif @@ -225,7 +225,7 @@ int32_t fdo_generate_ov_hmac_key(void) int32_t ret = -1; #if defined(DEVICE_TPM20_ENABLED) - if (0 != fdo_tpm_generate_hmac_key(TPM_PRIMARY_KEY_PERSISTANT_HANDLE)) { + if (0 != fdo_tpm_generate_hmac_key(TPM_HMAC_KEY_PERSISTANT_HANDLE)) { LOG(LOG_ERROR, "Failed to generate device HMAC key" " from TPM.\n"); return ret; @@ -269,7 +269,7 @@ int32_t fdo_generate_ov_replacement_hmac_key(void) int32_t ret = -1; #if defined(DEVICE_TPM20_ENABLED) - if (0 != fdo_tpm_generate_hmac_key(TPM_PRIMARY_KEY_PERSISTANT_HANDLE)) { + if (0 != fdo_tpm_generate_hmac_key(TPM_HMAC_KEY_PERSISTANT_HANDLE)) { LOG(LOG_ERROR, "Failed to generate device replacement HMAC key" " from TPM.\n"); return ret; diff --git a/crypto/include/tpm20_Utils.h b/crypto/include/tpm20_Utils.h index 54032b35..32e5f125 100644 --- a/crypto/include/tpm20_Utils.h +++ b/crypto/include/tpm20_Utils.h @@ -36,75 +36,87 @@ static const TPM2B_PUBLIC in_public_primary_key_template = { .size = 0, - .publicArea = - { - .type = TPM2_ALG_ECC, - .nameAlg = FDO_TPM2_ALG_SHA, - .objectAttributes = - (TPMA_OBJECT_USERWITHAUTH | TPMA_OBJECT_RESTRICTED | - TPMA_OBJECT_DECRYPT | TPMA_OBJECT_FIXEDTPM | - TPMA_OBJECT_FIXEDPARENT | TPMA_OBJECT_SENSITIVEDATAORIGIN), - .authPolicy = - { - .size = 0, - }, + .publicArea = { + .type = TPM2_ALG_ECC, + .nameAlg = FDO_TPM2_ALG_SHA, + .objectAttributes = + (TPMA_OBJECT_USERWITHAUTH | TPMA_OBJECT_RESTRICTED | + TPMA_OBJECT_DECRYPT | TPMA_OBJECT_FIXEDTPM | + TPMA_OBJECT_FIXEDPARENT | TPMA_OBJECT_SENSITIVEDATAORIGIN), + .authPolicy = + { + .size = 0, + }, + .parameters + .eccDetail = {.symmetric = {.algorithm = TPM2_ALG_AES, + .keyBits.aes = TPM_AES_BITS, + .mode.aes = TPM2_ALG_CFB}, + .scheme = {.scheme = TPM2_ALG_NULL, .details = {{0}}}, + .curveID = FDO_TPM2_CURVE_ID, + .kdf = {.scheme = TPM2_ALG_NULL, .details = {{0}}}}, + .unique.ecc = {.x = {.size = 0, .buffer = {0}}, + .y = {.size = 0, .buffer = {0}}}}}; - .parameters.eccDetail = {.symmetric = - { - .algorithm = TPM2_ALG_AES, - .keyBits.aes = TPM_AES_BITS, - .mode.aes = TPM2_ALG_CFB, - }, - .scheme = - { - .scheme = TPM2_ALG_NULL, - .details = {{0}}, - }, - .curveID = FDO_TPM2_CURVE_ID, - .kdf = {.scheme = TPM2_ALG_NULL, - .details = {{0}}}}, - .unique.ecc = - { - .x = {.size = 0, .buffer = {0}}, - .y = {.size = 0, .buffer = {0}}, - }, - }, -}; +static const TPM2B_PUBLIC in_publicECKey_template = { + .size = 0, + .publicArea = { + .type = TPM2_ALG_ECC, + .nameAlg = FDO_TPM2_ALG_SHA, + .objectAttributes = + (TPMA_OBJECT_USERWITHAUTH | TPMA_OBJECT_SIGN_ENCRYPT | + TPMA_OBJECT_FIXEDTPM | TPMA_OBJECT_FIXEDPARENT | + TPMA_OBJECT_SENSITIVEDATAORIGIN), + .authPolicy = + { + .size = 0, + }, + .parameters.eccDetail = + {.symmetric = {.algorithm = TPM2_ALG_NULL, + .keyBits.aes = 0, + .mode.aes = 0}, + .scheme = {.scheme = TPM2_ALG_ECDSA, + .details = {.ecdsa = {.hashAlg = FDO_TPM2_ALG_SHA}}}, + .curveID = FDO_TPM2_CURVE_ID, + .kdf = {.scheme = TPM2_ALG_NULL, .details = {{0}}}}, + .unique.ecc = {.x = {.size = 0, .buffer = {0}}, + .y = {.size = 0, .buffer = {0}}}}}; static const TPM2B_PUBLIC in_publicHMACKey_template = { .size = 0, - .publicArea = - { - .type = TPM2_ALG_KEYEDHASH, - .nameAlg = FDO_TPM2_ALG_SHA, - .objectAttributes = - (TPMA_OBJECT_USERWITHAUTH | TPMA_OBJECT_DECRYPT | - TPMA_OBJECT_SIGN_ENCRYPT | TPMA_OBJECT_FIXEDTPM | - TPMA_OBJECT_FIXEDPARENT | TPMA_OBJECT_SENSITIVEDATAORIGIN), - .authPolicy = - { - .size = 0, - }, - - .parameters.keyedHashDetail = - { - .scheme = - { - .scheme = TPM2_ALG_NULL, - .details = {{0}}, - }, - }, - .unique.keyedHash = - { - .size = 0, - .buffer = {0}, - }, - }, -}; + .publicArea = { + .type = TPM2_ALG_KEYEDHASH, + .nameAlg = FDO_TPM2_ALG_SHA, + .objectAttributes = + (TPMA_OBJECT_USERWITHAUTH | TPMA_OBJECT_SIGN_ENCRYPT | + TPMA_OBJECT_FIXEDTPM | TPMA_OBJECT_FIXEDPARENT | + TPMA_OBJECT_SENSITIVEDATAORIGIN), + .authPolicy = + { + .size = 0, + }, + .parameters.keyedHashDetail = + {.scheme = {.scheme = TPM2_ALG_HMAC, + .details = {.hmac = {.hashAlg = FDO_TPM2_ALG_SHA}}}}, + .unique.keyedHash = + { + .size = 0, + .buffer = {0}, + }, + }}; int32_t fdo_tpm_get_hmac(const uint8_t *data, size_t data_length, uint8_t *hmac, size_t hmac_length, TPMI_DH_PERSISTENT persistent_handle); int32_t fdo_tpm_generate_hmac_key(TPMI_DH_PERSISTENT persistent_handle); +int32_t fdoTPMEsys_context_init(ESYS_CONTEXT **esys_context); +int32_t fdoTPMEsys_auth_session_init(ESYS_CONTEXT *esys_context, + ESYS_TR *session_handle); +int32_t fdoTPMTSSContext_clean_up(ESYS_CONTEXT **esys_context, + ESYS_TR *auth_session_handle, + ESYS_TR *primary_handle); +int32_t fdoTPMGenerate_primary_key_context(ESYS_CONTEXT **esys_context, + ESYS_TR *primary_handle, + ESYS_TR *auth_session_handle); + #endif /* #ifndef __TPM20_UTILS_H__ */ diff --git a/crypto/openssl/tpm20_ECDSA_sign_routines.c b/crypto/openssl/tpm20_ECDSA_sign_routines.c index 4ac0025d..0cdf91fe 100644 --- a/crypto/openssl/tpm20_ECDSA_sign_routines.c +++ b/crypto/openssl/tpm20_ECDSA_sign_routines.c @@ -35,219 +35,123 @@ int32_t crypto_hal_ecdsa_sign(const uint8_t *data, size_t data_len, unsigned char *message_signature, size_t *signature_length) { + int32_t ret = -1; - EVP_PKEY *pkey = NULL; - ECDSA_SIG *sig = NULL; - unsigned char *sig_r = NULL; + TSS2_RC ret_val = TPM2_RC_FAILURE; + ESYS_CONTEXT *esys_context = NULL; + ESYS_TR primary_key_handle = ESYS_TR_NONE; + ESYS_TR auth_session_handle = ESYS_TR_NONE; + ESYS_TR tpm_ec_key_handle = ESYS_TR_NONE; int sig_r_len = 0; - unsigned char *sig_s = NULL; int sig_s_len = 0; - unsigned char *der_sig = NULL; - size_t der_sig_len = 0; - OSSL_PROVIDER *prov = NULL; - EVP_MD_CTX *mdctx = NULL; - OSSL_STORE_CTX *ctx = NULL; - OSSL_STORE_INFO *info = NULL; - BIO *mem = NULL; - unsigned char *pri_key = NULL; + TPM2B_DIGEST *digest = NULL; + TPMT_TK_HASHCHECK *validation = NULL; + TPMT_SIGNATURE *signature = NULL; + TPM2B_MAX_BUFFER input_data; + // Set the signature scheme to ECDSA with SHA256 + TPMT_SIG_SCHEME inScheme = { + .scheme = TPM2_ALG_ECDSA, + .details = {.rsapss = {.hashAlg = FDO_TPM2_ALG_SHA}}}; if (!data || !data_len || !message_signature || !signature_length) { LOG(LOG_ERROR, "Invalid Parameters received."); goto error; } - // Load OpenSSL TPM provider - if ((prov = OSSL_PROVIDER_load(NULL, "tpm2")) == NULL) { - LOG(LOG_ERROR, "Failed to load tpm provider!\n"); - goto error; - } - - // Read the key - size_t key_size = fdo_tpm_nvread_size(TPM_ECDSA_DEVICE_KEY_NV_IDX); - - pri_key = fdo_alloc(key_size); - if (!pri_key) { - LOG(LOG_ERROR, "Failed to allocate memory for private key.\n"); - goto error; - } - - if (fdo_tpm_nvread(TPM_ECDSA_DEVICE_KEY_NV_IDX, key_size, &pri_key) == - -1) { - LOG(LOG_ERROR, - "Failed to load TPM HMAC Private Key into buffer.\n"); - goto error; - } - - mem = BIO_new_mem_buf(pri_key, key_size); - if (mem == NULL) { - LOG(LOG_ERROR, "Failed to create memory BIO\n"); - goto error; - } - - pkey = PEM_read_bio_PrivateKey(mem, NULL, NULL, NULL); - if (pkey == NULL) { - LOG(LOG_ERROR, "Error during reading Private key.\n"); - BIO_free(mem); - goto error; - } - - LOG(LOG_DEBUG, "Private key successfully loaded in TPM format.\n"); - - // Set EVP properties to use TPM provider - if (EVP_set_default_properties(NULL, "provider=tpm2") == 0) { - LOG(LOG_ERROR, "failed to load tpm provider!\n"); - goto error; - } - - // Create the Message Digest Context - mdctx = EVP_MD_CTX_create(); - if (!mdctx) { - LOG(LOG_ERROR, "Failed to create message digest context\n"); - goto error; - } - -#if defined(ECDSA256_DA) - if (1 != EVP_DigestSignInit(mdctx, NULL, EVP_sha256(), NULL, pkey)) { - LOG(LOG_ERROR, "EVP sign init failed \n"); - goto error; - } -#elif defined(ECDSA384_DA) - if (1 != EVP_DigestSignInit(mdctx, NULL, EVP_sha384(), NULL, pkey)) { - LOG(LOG_ERROR, "EVP sign init failed \n"); - goto error; - } -#endif - if (1 != EVP_DigestSignUpdate(mdctx, data, data_len)) { - LOG(LOG_ERROR, "EVP sign update failed \n"); - goto error; - } - // First call with NULL param to obtain the DER encoded signature length - if (1 != EVP_DigestSignFinal(mdctx, NULL, &der_sig_len)) { - LOG(LOG_ERROR, "EVP sign final for size failed \n"); + input_data.size = data_len; + if (memcpy_s(input_data.buffer, input_data.size, (char *)data, + (size_t)data_len) != 0) { + LOG(LOG_ERROR, "Memcpy Failed\n"); goto error; } - if (der_sig_len <= 0) { + if (0 != fdoTPMGenerate_primary_key_context(&esys_context, + &primary_key_handle, + &auth_session_handle)) { LOG(LOG_ERROR, - "EVP_DigestSignFinal returned invalid signature length.\n"); + "Failed to create primary key context from TPM.\n"); goto error; } - der_sig = fdo_alloc(der_sig_len); - if (!der_sig) { - LOG(LOG_ERROR, "Signature alloc Failed\n"); - goto error; - } - // second call with actual param to obtain the DEr encoded signature - if (1 != EVP_DigestSignFinal(mdctx, der_sig, &der_sig_len)) { - LOG(LOG_ERROR, "EVP sign final failed \n"); - goto error; - } + ret_val = Esys_TR_FromTPMPublic( + esys_context, TPM_DEVICE_KEY_PERSISTANT_HANDLE, ESYS_TR_NONE, + ESYS_TR_NONE, ESYS_TR_NONE, &tpm_ec_key_handle); - // Set EVP properties back to default. - if (EVP_set_default_properties(NULL, "provider=default") == 0) { - LOG(LOG_DEBUG, "failed to load tpm provider!\n"); + if (ret_val != TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, "Failed to load EC Key Context.\n"); goto error; } - // Decode DER encoded signature to convert to raw format - sig = ECDSA_SIG_new(); - const unsigned char *sig_input = der_sig; - if (!sig || d2i_ECDSA_SIG(&sig, &sig_input, der_sig_len) == NULL) { - LOG(LOG_ERROR, "DER to EC_KEY struct decoding failed!\n"); + ret_val = Esys_Hash(esys_context, ESYS_TR_NONE, ESYS_TR_NONE, + ESYS_TR_NONE, &input_data, FDO_TPM2_ALG_SHA, + ESYS_TR_RH_OWNER, &digest, &validation); + if (ret_val != TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, "Failed to create hash.\n"); goto error; } - - // both r and s are maintained by sig, no need to free explicitly - const BIGNUM *r = ECDSA_SIG_get0_r(sig); - const BIGNUM *s = ECDSA_SIG_get0_s(sig); - if (!r || !s) { - LOG(LOG_ERROR, "Failed to read r and/or s\n"); + ret_val = Esys_Sign(esys_context, tpm_ec_key_handle, + auth_session_handle, ESYS_TR_NONE, ESYS_TR_NONE, + digest, &inScheme, validation, &signature); + if (ret_val != TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, "Failed to create Sign Key.\n"); goto error; } - sig_r_len = BN_num_bytes(r); + sig_r_len = signature->signature.ecdsa.signatureR.size; if (sig_r_len <= 0) { LOG(LOG_ERROR, "Sig r len invalid\n"); goto error; } - sig_r = fdo_alloc(sig_r_len); - if (!sig_r) { - LOG(LOG_ERROR, "Sig r alloc Failed\n"); - goto error; - } - if (BN_bn2bin(r, sig_r) <= 0) { - LOG(LOG_ERROR, "Sig r conversion Failed\n"); - goto error; - } - sig_s_len = BN_num_bytes(s); + sig_s_len = signature->signature.ecdsa.signatureS.size; if (sig_r_len <= 0) { LOG(LOG_ERROR, "Sig s len invalid\n"); goto error; } - sig_s = fdo_alloc(sig_s_len); - if (!sig_s) { - LOG(LOG_ERROR, "Sig s alloc Failed\n"); - goto error; - } - if (BN_bn2bin(s, sig_s) <= 0) { - LOG(LOG_ERROR, "Sig s conversion Failed\n"); - goto error; - } *signature_length = sig_r_len + sig_s_len; - if (memcpy_s(message_signature, *signature_length, (char *)sig_r, + if (memcpy_s(message_signature, *signature_length, + (char *)signature->signature.ecdsa.signatureR.buffer, (size_t)sig_r_len) != 0) { LOG(LOG_ERROR, "Memcpy Failed\n"); goto error; } if (memcpy_s(message_signature + sig_r_len, *signature_length, - (char *)sig_s, (size_t)sig_s_len) != 0) { + (char *)signature->signature.ecdsa.signatureS.buffer, + (size_t)sig_s_len) != 0) { LOG(LOG_ERROR, "Memcpy Failed\n"); goto error; } - ret = 0; error: - if (pri_key) { - fdo_free(pri_key); - } - if (mem) { - BIO_free(mem); - } - if (pkey) { - EVP_PKEY_free(pkey); - } - if (sig) { - ECDSA_SIG_free(sig); - } - if (der_sig) { - fdo_free(der_sig); - sig_input = NULL; - } - if (sig_r) { - fdo_free(sig_r); - } - if (sig_s) { - fdo_free(sig_s); - } - if (prov) { - OSSL_PROVIDER_unload(prov); - prov = NULL; - } - if (mdctx) { - EVP_MD_CTX_free(mdctx); - mdctx = NULL; - } - if (ctx) { - OSSL_STORE_close(ctx); - ctx = NULL; - } - if (info) { - OSSL_STORE_INFO_free(info); - info = NULL; - } + if (esys_context) { + if (tpm_ec_key_handle != ESYS_TR_NONE) { + if (Esys_TR_Close(esys_context, &tpm_ec_key_handle) != + TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, + "Failed to flush HMAC key handle.\n"); + ret = -1; + } else { + LOG(LOG_DEBUG, + "HMAC key handle flushed successfully.\n"); + tpm_ec_key_handle = ESYS_TR_NONE; + } + } + if (0 != fdoTPMTSSContext_clean_up(&esys_context, + &auth_session_handle, + &primary_key_handle)) { + LOG(LOG_ERROR, + "Failed to tear down all the TSS context.\n"); + ret = -1; + } else { + LOG(LOG_DEBUG, "TSS context flushed successfully.\n"); + } + } + + TPM2_ZEROISE_FREE(digest); + TPM2_ZEROISE_FREE(validation); + TPM2_ZEROISE_FREE(signature); + return ret; -} +} \ No newline at end of file diff --git a/crypto/openssl/tpm20_Utils.c b/crypto/openssl/tpm20_Utils.c index ee911cc5..a6d80203 100644 --- a/crypto/openssl/tpm20_Utils.c +++ b/crypto/openssl/tpm20_Utils.c @@ -15,16 +15,6 @@ #include "fdo_crypto_hal.h" #include "storage_al.h" -static int32_t fdoTPMEsys_context_init(ESYS_CONTEXT **esys_context); -static int32_t fdoTPMEsys_auth_session_init(ESYS_CONTEXT *esys_context, - ESYS_TR *session_handle); -static int32_t fdoTPMTSSContext_clean_up(ESYS_CONTEXT **esys_context, - ESYS_TR *auth_session_handle, - ESYS_TR *primary_handle); -static int32_t fdoTPMGenerate_primary_key_context(ESYS_CONTEXT **esys_context, - ESYS_TR *primary_handle, - ESYS_TR *auth_session_handle); - /** * Generates HMAC using TPM * @@ -446,9 +436,9 @@ int32_t fdo_tpm_generate_hmac_key(TPMI_DH_PERSISTENT persistent_handle) * 0, on success * -1, on failure */ -static int32_t fdoTPMGenerate_primary_key_context(ESYS_CONTEXT **esys_context, - ESYS_TR *primary_key_handle, - ESYS_TR *auth_session_handle) +int32_t fdoTPMGenerate_primary_key_context(ESYS_CONTEXT **esys_context, + ESYS_TR *primary_key_handle, + ESYS_TR *auth_session_handle) { int ret = -1; TSS2_RC ret_val = TPM2_RC_FAILURE; @@ -519,7 +509,7 @@ static int32_t fdoTPMGenerate_primary_key_context(ESYS_CONTEXT **esys_context, * 0, on success * -1, on failure */ -static int32_t fdoTPMEsys_context_init(ESYS_CONTEXT **esys_context) +int32_t fdoTPMEsys_context_init(ESYS_CONTEXT **esys_context) { int ret = -1; TSS2_TCTI_CONTEXT *tcti_context = NULL; @@ -563,8 +553,8 @@ static int32_t fdoTPMEsys_context_init(ESYS_CONTEXT **esys_context) * 0, on success * -1, on failure */ -static int32_t fdoTPMEsys_auth_session_init(ESYS_CONTEXT *esys_context, - ESYS_TR *session_handle) +int32_t fdoTPMEsys_auth_session_init(ESYS_CONTEXT *esys_context, + ESYS_TR *session_handle) { int ret = -1; TPMT_SYM_DEF symmetric = {0}; @@ -593,9 +583,9 @@ static int32_t fdoTPMEsys_auth_session_init(ESYS_CONTEXT *esys_context, * 0, on success * -1, on failure */ -static int32_t fdoTPMTSSContext_clean_up(ESYS_CONTEXT **esys_context, - ESYS_TR *auth_session_handle, - ESYS_TR *primary_handle) +int32_t fdoTPMTSSContext_clean_up(ESYS_CONTEXT **esys_context, + ESYS_TR *auth_session_handle, + ESYS_TR *primary_handle) { int ret = -1, is_failed = 0; TSS2_TCTI_CONTEXT *tcti_context = NULL; diff --git a/lib/include/fdoprot.h b/lib/include/fdoprot.h index 2de18583..5b7c763c 100644 --- a/lib/include/fdoprot.h +++ b/lib/include/fdoprot.h @@ -152,7 +152,7 @@ typedef struct fdo_prot_s { fdo_dev_cred_t *dev_cred; fdo_public_key_t *owner_public_key; // Owner's public key fdo_service_info_t *service_info; // store System ServiceInfo - // (devmod+unsupported module list) + // (devmod+unsupported module list) fdo_byte_array_t *ext_service_info; // store External module // ServiceInfoVal (fdo_sys, for ex.) fdo_public_key_t *tls_key; // unused for now diff --git a/storage/include/tpm2_nv_storage.h b/storage/include/tpm2_nv_storage.h index c84cfb5b..70180110 100644 --- a/storage/include/tpm2_nv_storage.h +++ b/storage/include/tpm2_nv_storage.h @@ -6,8 +6,8 @@ #include #define FDO_CRED_NV_IDX 0x01D10001 -#define TPM_PRIMARY_KEY_PERSISTANT_HANDLE 0x81020003 -#define TPM_ECDSA_DEVICE_KEY_NV_IDX 0x01D10004 +#define TPM_DEVICE_KEY_PERSISTANT_HANDLE 0x81020002 +#define TPM_HMAC_KEY_PERSISTANT_HANDLE 0x81020003 #define TPM_DEVICE_CSR_NV_IDX 0x01D10005 #if defined(ECDSA256_DA) diff --git a/storage/linux/storage_if_linux.c b/storage/linux/storage_if_linux.c index fde1345a..1aaa2990 100644 --- a/storage/linux/storage_if_linux.c +++ b/storage/linux/storage_if_linux.c @@ -698,7 +698,7 @@ int32_t fdo_tpm_read_nv(TPMI_RH_NV_INDEX nv, uint8_t *buf, uint32_t n_bytes) if (0 != fdo_tpm_get_hmac(data, data_length, computed_hmac, PLATFORM_HMAC_SIZE, - TPM_PRIMARY_KEY_PERSISTANT_HANDLE)) { + TPM_HMAC_KEY_PERSISTANT_HANDLE)) { LOG(LOG_ERROR, "HMAC computation dailed during" " %s!\n", @@ -788,7 +788,7 @@ int32_t fdo_tpm_write_nv(TPMI_RH_NV_INDEX nv, const uint8_t *buf, if (0 != fdo_tpm_get_hmac(buf, n_bytes, write_context, PLATFORM_HMAC_SIZE, - TPM_PRIMARY_KEY_PERSISTANT_HANDLE)) { + TPM_HMAC_KEY_PERSISTANT_HANDLE)) { LOG(LOG_ERROR, "Computing HMAC failed!\n"); goto exit; } diff --git a/utils/clear_tpm_nv.sh b/utils/clear_tpm_nv.sh index 83c250e5..ea10b6bc 100644 --- a/utils/clear_tpm_nv.sh +++ b/utils/clear_tpm_nv.sh @@ -17,12 +17,12 @@ execute_cmd_on_failure_exit() return 0 } -for n in {1,4,5}; +for n in {1,5}; do - task="Deleting a Non-Volatile (NV) index at 0x100000$n" + task="Deleting a Non-Volatile (NV) index at 0x01D1000$n" cmd="tpm2_nvundefine 0x01D1000$n" success_string="$task completed successfully!!" - failure_string="Non-Volatile (NV) index at 0x100000$n is not defined!!" + failure_string="Non-Volatile (NV) index at 0x01D1000$n is not defined!!" execute_cmd_on_failure_exit "\$cmd" "\$success_string" "\$failure_string" done echo "TPM NV storage cleared!" diff --git a/utils/tpm_make_ready_ecdsa.sh b/utils/tpm_make_ready_ecdsa.sh index dc5ecf97..76530060 100644 --- a/utils/tpm_make_ready_ecdsa.sh +++ b/utils/tpm_make_ready_ecdsa.sh @@ -1,12 +1,14 @@ export TPM2TOOLS_TCTI="tabrmd" export OPENSSL3_BIN=/opt/openssl/bin -TPM_KEY_FILE_INSIDE_DATA_DIR="tpm_ecdsa_priv_pub_blob.key" +TPM_PUB_KEY_FILE_INSIDE_DATA_DIR="tpm_ecdsa_pub.key" +TPM_PRIV_KEY_FILE_INSIDE_DATA_DIR="tpm_ecdsa_priv.key" DEVICE_CSR_FILE_INSIDE_DATA_DIR="tpm_device_csr" PARENT_DIR="" TPM_ENDORSEMENT_PRIMARY_KEY_CTX=tpm_primary_key.ctx -TPM_ENDORSEMENT_PRIMARY_KEY_PERSISTANT_HANDLE=0x81020002 +TPM_ECDSA_KEY_CTX=tpm_ecdsa_key.ctx +TPM_DEVICE_KEY_PERSISTANT_HANDLE=0x81020002 found_path=0 verbose=0 @@ -84,17 +86,16 @@ echo "$TPM2TOOLS_TCTI in use as Resource Manager" #Prepare all files path tpm_endorsement_primary_key_ctx=$PARENT_DIR"/"$TPM_ENDORSEMENT_PRIMARY_KEY_CTX -tpm_device_key_file=$PARENT_DIR"/"$TPM_KEY_FILE_INSIDE_DATA_DIR +tpm_ecdsa_key_ctx=$PARENT_DIR"/"$TPM_ECDSA_KEY_CTX +tpm_device_pub_key_file=$PARENT_DIR"/"$TPM_PUB_KEY_FILE_INSIDE_DATA_DIR +tpm_device_priv_key_file=$PARENT_DIR"/"$TPM_PRIV_KEY_FILE_INSIDE_DATA_DIR device_csr_file=$PARENT_DIR"/"$DEVICE_CSR_FILE_INSIDE_DATA_DIR -echo "TPM Device Key file location : $tpm_device_key_file" -echo "TPM Device CSR file location : $device_csr_file" - rm -f $tpm_endorsement_primary_key_ctx task="Delete keys if exists from persistance memory" -cmd="tpm2_evictcontrol -C o -c $TPM_ENDORSEMENT_PRIMARY_KEY_PERSISTANT_HANDLE -V" -success_string="$task completed successfully at $TPM_ENDORSEMENT_PRIMARY_KEY_PERSISTANT_HANDLE !!" +cmd="tpm2_evictcontrol -C o -c $TPM_DEVICE_KEY_PERSISTANT_HANDLE -V" +success_string="$task completed successfully at $TPM_DEVICE_KEY_PERSISTANT_HANDLE !!" failure_string="$task failed [probably ignore it]" execute_cmd_on_failure_exit "\$cmd" "\$success_string" "\$failure_string" 1 0 @@ -104,32 +105,31 @@ success_string="$task completed successfully at $tpm_endorsement_primary_key_ctx failure_string="$task failed" execute_cmd_on_failure_exit "\$cmd" "\$success_string" "\$failure_string" 1 1 -task="Load primary key inside persistance memory at $TPM_ENDORSEMENT_PRIMARY_KEY_PERSISTANT_HANDLE" -cmd="tpm2_evictcontrol -C o $TPM_ENDORSEMENT_PRIMARY_KEY_PERSISTANT_HANDLE -c $tpm_endorsement_primary_key_ctx -V" -success_string="$task completed successfully!!" +task="TPM ECDSA keys generation" +cmd="tpm2_create -g sha$ecc -G ecc$ecc -u $tpm_device_pub_key_file -r $tpm_device_priv_key_file -C $tpm_endorsement_primary_key_ctx -a \"fixedtpm|sensitivedataorigin|fixedparent|sign|userwithauth\" -V" +success_string="$task completed successfully at $tpm_endorsement_primary_key_ctx !!" failure_string="$task failed" execute_cmd_on_failure_exit "\$cmd" "\$success_string" "\$failure_string" 1 1 -task="TPM ECDSA key generation using $curve" -cmd="$OPENSSL3_BIN/openssl genpkey -provider tpm2 -algorithm EC -pkeyopt group:P-$ecc -pkeyopt parent:$TPM_ENDORSEMENT_PRIMARY_KEY_PERSISTANT_HANDLE -out $tpm_device_key_file" +task="Load ECDSA keys" +cmd="tpm2_load -C $tpm_endorsement_primary_key_ctx -u $tpm_device_pub_key_file -r $tpm_device_priv_key_file -c $tpm_ecdsa_key_ctx -V" success_string="$task completed successfully!!" failure_string="$task failed" -execute_cmd_on_failure_exit "\${cmd}" "\${success_string}" "\${failure_string}" 1 1 +execute_cmd_on_failure_exit "\$cmd" "\$success_string" "\$failure_string" 1 1 -task="Device CSR generation from TPM" -cmd="$OPENSSL3_BIN/openssl req -new -provider tpm2 -provider default -outform DER -out $device_csr_file -key $tpm_device_key_file -subj \"/CN=sdo-tpm-device\" -verbose" +task="Copy ECDSA keys inside persistance memory at $TPM_DEVICE_KEY_PERSISTANT_HANDLE" +cmd="tpm2_evictcontrol -C o $TPM_DEVICE_KEY_PERSISTANT_HANDLE -c $tpm_ecdsa_key_ctx -V" success_string="$task completed successfully!!" failure_string="$task failed" execute_cmd_on_failure_exit "\$cmd" "\$success_string" "\$failure_string" 1 1 -# write tpm device key and device csr inside tpm -task="Define a TPM Non-Volatile (NV) index for TPM KEY" -key_size=$(wc -c < $tpm_device_key_file) -cmd="tpm2_nvdefine -Q 0x01D10004 -C o -s $key_size -a \"ownerwrite|authwrite|ownerread|authread|no_da\"" +task="Device CSR generation from TPM" +cmd="$OPENSSL3_BIN/openssl req -new -provider tpm2 -provider default -outform DER -out $device_csr_file -key handle:$TPM_DEVICE_KEY_PERSISTANT_HANDLE -subj \"/CN=fdo-tpm-device\" -verbose" success_string="$task completed successfully!!" failure_string="$task failed" execute_cmd_on_failure_exit "\$cmd" "\$success_string" "\$failure_string" 1 1 +# # write device csr inside tpm task="Define a TPM Non-Volatile (NV) index for TPM Device CSR" csr_size=$(wc -c < $device_csr_file) cmd="tpm2_nvdefine -Q 0x01D10005 -C o -s $csr_size -a \"ownerwrite|authwrite|ownerread|authread|no_da\"" @@ -137,19 +137,15 @@ success_string="$task completed successfully!!" failure_string="$task failed" execute_cmd_on_failure_exit "\$cmd" "\$success_string" "\$failure_string" 1 1 -task="Write TPM ECDSA KEY to a Non-Volatile (NV) index" -cmd="tpm2_nvwrite -Q 0x01D10004 -C o -i $tpm_device_key_file" -success_string="$task completed successfully!!" -failure_string="$task failed" -execute_cmd_on_failure_exit "\$cmd" "\$success_string" "\$failure_string" 1 1 - task="Write TPM Device CSR to a Non-Volatile (NV) index" cmd="tpm2_nvwrite -Q 0x01D10005 -C o -i $device_csr_file" success_string="$task completed successfully!!" failure_string="$task failed" execute_cmd_on_failure_exit "\$cmd" "\$success_string" "\$failure_string" 1 1 -rm -f $tpm_device_key_file +rm -f $tpm_device_pub_key_file +rm -f $tpm_device_priv_key_file rm -f $device_csr_file rm -f $tpm_endorsement_primary_key_ctx +rm -f $tpm_ecdsa_key_ctx From a3ed8faba1c97ef1fffa4fb6718608bcc4845269 Mon Sep 17 00:00:00 2001 From: Shrikant Temburwar Date: Mon, 22 Jan 2024 12:08:18 +0530 Subject: [PATCH 6/9] Update tpm scripts Signed-off-by: Shrikant Temburwar --- utils/clear_tpm_nv.sh | 7 +++++++ utils/tpm_make_ready_ecdsa.sh | 8 -------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/utils/clear_tpm_nv.sh b/utils/clear_tpm_nv.sh index ea10b6bc..8c42b9f8 100644 --- a/utils/clear_tpm_nv.sh +++ b/utils/clear_tpm_nv.sh @@ -1,4 +1,5 @@ #!/bin/bash +TPM_DEVICE_KEY_PERSISTANT_HANDLE=0x81020002 execute_cmd_on_failure_exit() { @@ -17,6 +18,12 @@ execute_cmd_on_failure_exit() return 0 } +task="Delete keys if exists from persistance memory" +cmd="tpm2_evictcontrol -C o -c $TPM_DEVICE_KEY_PERSISTANT_HANDLE -V" +success_string="$task completed successfully at $TPM_DEVICE_KEY_PERSISTANT_HANDLE !!" +failure_string="$task failed [probably ignore it]" +execute_cmd_on_failure_exit "\$cmd" "\$success_string" "\$failure_string" + for n in {1,5}; do task="Deleting a Non-Volatile (NV) index at 0x01D1000$n" diff --git a/utils/tpm_make_ready_ecdsa.sh b/utils/tpm_make_ready_ecdsa.sh index 76530060..08be787a 100644 --- a/utils/tpm_make_ready_ecdsa.sh +++ b/utils/tpm_make_ready_ecdsa.sh @@ -91,14 +91,6 @@ tpm_device_pub_key_file=$PARENT_DIR"/"$TPM_PUB_KEY_FILE_INSIDE_DATA_DIR tpm_device_priv_key_file=$PARENT_DIR"/"$TPM_PRIV_KEY_FILE_INSIDE_DATA_DIR device_csr_file=$PARENT_DIR"/"$DEVICE_CSR_FILE_INSIDE_DATA_DIR -rm -f $tpm_endorsement_primary_key_ctx - -task="Delete keys if exists from persistance memory" -cmd="tpm2_evictcontrol -C o -c $TPM_DEVICE_KEY_PERSISTANT_HANDLE -V" -success_string="$task completed successfully at $TPM_DEVICE_KEY_PERSISTANT_HANDLE !!" -failure_string="$task failed [probably ignore it]" -execute_cmd_on_failure_exit "\$cmd" "\$success_string" "\$failure_string" 1 0 - task="Primary key generation from endorsement seed" cmd="tpm2_createprimary -C e -g sha$ecc -G $primary_key_type -c $tpm_endorsement_primary_key_ctx -V" success_string="$task completed successfully at $tpm_endorsement_primary_key_ctx !!" From 4d35f2aff403f27e1ecb23cb869eec77e6a66ec6 Mon Sep 17 00:00:00 2001 From: Shrikant Temburwar Date: Tue, 23 Jan 2024 23:07:33 +0530 Subject: [PATCH 7/9] Add DCActive flag usecase as per FDO TPM spec Signed-off-by: Shrikant Temburwar --- app/main.c | 10 ++--- lib/credentials_from_file.c | 73 +++++++++++++++++++++++-------- lib/fdo.c | 8 +++- lib/prot/di/msg13.c | 2 + lib/prot/to2/msg70.c | 3 ++ storage/include/tpm2_nv_storage.h | 1 + utils/clear_tpm_nv.sh | 2 +- 7 files changed, 74 insertions(+), 25 deletions(-) diff --git a/app/main.c b/app/main.c index c457494e..1f4bcba7 100644 --- a/app/main.c +++ b/app/main.c @@ -204,19 +204,19 @@ static void print_device_status(void) status = fdo_sdk_get_status(); if (status == FDO_STATE_PRE_DI) { - LOG(LOG_DEBUG, "Device is ready for DI\n"); + LOG(LOG_INFO, "Device is ready for DI\n"); } if (status == FDO_STATE_PRE_TO1) { - LOG(LOG_DEBUG, "Device is ready for Ownership transfer\n"); + LOG(LOG_INFO, "Device is ready for Ownership transfer\n"); } if (status == FDO_STATE_IDLE) { - LOG(LOG_DEBUG, "Device Ownership transfer Done\n"); + LOG(LOG_INFO, "Device Ownership transfer Done\n"); } if (status == FDO_STATE_RESALE) { - LOG(LOG_DEBUG, "Device is ready for Ownership transfer\n"); + LOG(LOG_INFO, "Device is ready for Ownership transfer\n"); } if (status == FDO_STATE_ERROR) { - LOG(LOG_DEBUG, "Error in getting device status\n"); + LOG(LOG_ERROR, "Error in getting device status\n"); } } diff --git a/lib/credentials_from_file.c b/lib/credentials_from_file.c index a7efa881..3f9aaa56 100644 --- a/lib/credentials_from_file.c +++ b/lib/credentials_from_file.c @@ -501,7 +501,7 @@ bool write_tpm_device_credentials(uint32_t nv, fdo_dev_cred_t *ocred) /** * Blob format: Complete DeviceCredential as per Section 3.4.1 of FDO *Specification, except the DeviceCredential.DCHmacSecret, and addition - *of 'State'. DeviceCredential = [ State, DCActive, DCProtVer, + *of 'State'. DeviceCredential = [ State, DCProtVer, * DCDeviceInfo, * DCGuid, * DCRVInfo, @@ -509,7 +509,7 @@ bool write_tpm_device_credentials(uint32_t nv, fdo_dev_cred_t *ocred) * ] */ fdow_next_block(fdow, FDO_DI_SET_CREDENTIALS); - if (!fdow_start_array(fdow, 7)) { + if (!fdow_start_array(fdow, 6)) { ret = false; goto end; } @@ -517,10 +517,7 @@ bool write_tpm_device_credentials(uint32_t nv, fdo_dev_cred_t *ocred) ret = false; goto end; } - if (!fdow_boolean(fdow, true)) { - ret = false; - goto end; - } + if (!fdow_signed_int(fdow, ocred->owner_blk->pv)) { ret = false; goto end; @@ -652,11 +649,6 @@ bool read_tpm_device_credentials(uint32_t nv, fdo_dev_cred_t *our_dev_cred) goto end; } - if (!fdor_boolean(fdor, &our_dev_cred->dc_active)) { - LOG(LOG_ERROR, "DeviceCredential read: DCActive not found\n"); - goto end; - } - if (!fdor_signed_int(fdor, &our_dev_cred->owner_blk->pv)) { LOG(LOG_ERROR, "DeviceCredential read: DCProtVer not found\n"); goto end; @@ -739,9 +731,23 @@ bool read_tpm_device_credentials(uint32_t nv, fdo_dev_cred_t *our_dev_cred) int store_tpm_credential(fdo_dev_cred_t *ocred) { /* Write in the file and save the Normal device credentials */ - LOG(LOG_DEBUG, "Writing to TPm NV storage\n"); + LOG(LOG_DEBUG, "Writing to TPM NV storage\n"); + + const char *dc_active = (ocred->dc_active == true) ? "true" : "false"; + size_t dc_active_len = strnlen_s(dc_active, BUFF_SIZE_8_BYTES); + if (!dc_active_len || dc_active_len == BUFF_SIZE_8_BYTES) { + LOG(LOG_ERROR, "Strlen() failed!\n") + return -1; + } + + if (fdo_tpm_nvwrite((uint8_t *)(dc_active), dc_active_len, + FDO_DCActive_NV_IDX)) { + LOG(LOG_ERROR, "Failed to write DeviceCredential Active\n"); + return -1; + } + if (!write_tpm_device_credentials(FDO_CRED_NV_IDX, ocred)) { - LOG(LOG_ERROR, "Could not write to Normal Credentials blob\n"); + LOG(LOG_ERROR, "Could not write to Normal Credentials\n"); return -1; } return 0; @@ -909,10 +915,41 @@ int load_credential(fdo_dev_cred_t *ocred) } #elif defined(DEVICE_TPM20_ENABLED) /* Read and save the device credentials */ - if (!read_tpm_device_credentials(FDO_CRED_NV_IDX, ocred)) { - LOG(LOG_ERROR, "Could not parse the Device Credentials blob\n"); + u_int8_t *dc_active = NULL; + size_t dc_active_len = fdo_tpm_nvread_size(FDO_DCActive_NV_IDX); + if (dc_active_len == 0) { + LOG(LOG_ERROR, "DeviceCredential Active not found.\n"); + return -1; + } + + dc_active = fdo_alloc(dc_active_len + 1); + if (NULL == dc_active) { + LOG(LOG_ERROR, "Malloc Failed in %s!\n", __func__); return -1; } + + if (fdo_tpm_nvread(FDO_DCActive_NV_IDX, dc_active_len, &dc_active)) { + LOG(LOG_ERROR, "Failed to read file!\n"); + fdo_free(dc_active); + return -1; + } + int strcmp_res = -1; + if (!strcmp_s((char *)dc_active, dc_active_len, "true", &strcmp_res) && + !strcmp_res) { + ocred->dc_active = true; + if (!read_tpm_device_credentials(FDO_CRED_NV_IDX, ocred)) { + LOG(LOG_ERROR, + "Could not parse the Device Credentials blob\n"); + fdo_free(dc_active); + return -1; + } + } else { + ocred->dc_active = false; + } + + if (dc_active) { + fdo_free(dc_active); + } #else /* Read in the blob and save the device credentials */ if (!read_normal_device_credentials((char *)FDO_CRED_NORMAL, @@ -979,12 +1016,12 @@ bool load_device_status(fdo_sdk_device_status *state) // Device has not yet been initialized. // Since, Normal.blob is empty, the file size will be 0 if (dev_cred_len == 0) { - LOG(LOG_DEBUG, + LOG(LOG_INFO, "DeviceCredential is empty. Set state to run DI\n"); *state = FDO_DEVICE_STATE_PC; } else { - LOG(LOG_DEBUG, "DeviceCredential is non-empty. Set state to " - "run TO1/TO2\n"); + LOG(LOG_INFO, "DeviceCredential is non-empty. Set state to " + "run TO1/TO2\n"); // No Device state is being set currently } return true; diff --git a/lib/fdo.c b/lib/fdo.c index aefd0cba..464424b8 100644 --- a/lib/fdo.c +++ b/lib/fdo.c @@ -873,6 +873,12 @@ fdo_sdk_status fdo_sdk_init(fdo_sdk_errorCB error_handling_callback, } } + if (g_fdo_data->devcred->ST != FDO_DEVICE_STATE_PC && + g_fdo_data->devcred->dc_active == false) { + g_fdo_data->devcred->ST = FDO_DEVICE_STATE_IDLE; + return FDO_SUCCESS; + } + if ((num_modules == 0) || (num_modules > FDO_MAX_MODULES) || (module_information == NULL) || (module_information->service_info_callback == NULL)) { @@ -1177,7 +1183,7 @@ fdo_sdk_status fdo_sdk_resale(void) if (r == FDO_ERROR) { LOG(LOG_ERROR, "Failed to set Resale\n"); } else if (r == FDO_RESALE_NOT_READY) { - LOG(LOG_DEBUG, "Device is not ready for Resale\n"); + LOG(LOG_INFO, "Device is not ready for Resale\n"); } if (g_fdo_data->devcred) { fdo_dev_cred_free(g_fdo_data->devcred); diff --git a/lib/prot/di/msg13.c b/lib/prot/di/msg13.c index 5ff4bf0a..e3f9c80f 100644 --- a/lib/prot/di/msg13.c +++ b/lib/prot/di/msg13.c @@ -85,6 +85,8 @@ int32_t msg13(fdo_prot_t *ps) } LOG(LOG_DEBUG, "FDO OVH COMMIT succeeded %u\n", fdo_status); #elif defined(DEVICE_TPM20_ENABLED) + ps->dev_cred->dc_active = true; + if (store_tpm_credential(ps->dev_cred) != 0) { LOG(LOG_ERROR, "TO2.Done: Failed to store new device creds\n"); goto err; diff --git a/lib/prot/to2/msg70.c b/lib/prot/to2/msg70.c index 7be9e029..ed4dd9b5 100644 --- a/lib/prot/to2/msg70.c +++ b/lib/prot/to2/msg70.c @@ -58,14 +58,17 @@ int32_t msg70(fdo_prot_t *ps) fdo_public_key_free(ps->dev_cred->owner_blk->pk); ps->dev_cred->owner_blk->pk = ps->osc->pubkey; + ps->dev_cred->dc_active = false; if (ps->reuse_enabled && reuse_supported) { // Reuse scenario, moving to post DI state ps->dev_cred->ST = FDO_DEVICE_STATE_READY1; + ps->dev_cred->dc_active = true; } else if (resale_supported) { // Done with FIDO Device Onboard. // As of now moving to done state for resale ps->dev_cred->ST = FDO_DEVICE_STATE_IDLE; + ps->dev_cred->dc_active = true; // create new Owner's public key hash fdo_hash_free(ps->dev_cred->owner_blk->pkh); ps->dev_cred->owner_blk->pkh = diff --git a/storage/include/tpm2_nv_storage.h b/storage/include/tpm2_nv_storage.h index 70180110..d62a8a42 100644 --- a/storage/include/tpm2_nv_storage.h +++ b/storage/include/tpm2_nv_storage.h @@ -5,6 +5,7 @@ #include #include +#define FDO_DCActive_NV_IDX 0x01D10000 #define FDO_CRED_NV_IDX 0x01D10001 #define TPM_DEVICE_KEY_PERSISTANT_HANDLE 0x81020002 #define TPM_HMAC_KEY_PERSISTANT_HANDLE 0x81020003 diff --git a/utils/clear_tpm_nv.sh b/utils/clear_tpm_nv.sh index 8c42b9f8..92faf761 100644 --- a/utils/clear_tpm_nv.sh +++ b/utils/clear_tpm_nv.sh @@ -24,7 +24,7 @@ success_string="$task completed successfully at $TPM_DEVICE_KEY_PERSISTANT_HANDL failure_string="$task failed [probably ignore it]" execute_cmd_on_failure_exit "\$cmd" "\$success_string" "\$failure_string" -for n in {1,5}; +for n in {0,1,5}; do task="Deleting a Non-Volatile (NV) index at 0x01D1000$n" cmd="tpm2_nvundefine 0x01D1000$n" From dcbd2625944f4a1b6a0fdc399fdbe0c476353b4d Mon Sep 17 00:00:00 2001 From: Shrikant Temburwar Date: Thu, 25 Jan 2024 16:51:52 +0530 Subject: [PATCH 8/9] - Update DCActive value to bool - Add TPM2_NV_WriteLock/TPM2_NV_ReadLock support - Update readme for FDO TPM usage Signed-off-by: Shrikant Temburwar --- .gitignore | 8 ++ cmake/cli_input.cmake | 29 ++++++ cmake/extension.cmake | 4 + crypto/openssl/tpm20_Utils.c | 10 +- docs/build_conf.md | 9 +- docs/tpm.md | 64 ++++++++----- lib/credentials_from_file.c | 60 +++++++----- lib/include/fdoprot.h | 2 +- lib/m-string.c | 6 ++ storage/include/tpm2_nv_storage.h | 18 ++++ storage/linux/tpm2_nv_storage.c | 153 ++++++++++++++++++++++++++---- utils/tpm_make_ready_ecdsa.sh | 2 +- 12 files changed, 287 insertions(+), 78 deletions(-) diff --git a/.gitignore b/.gitignore index e421fc56..7d7a6df6 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,12 @@ *.so *.so.* *.a +*.blob +*.bin +*.pem +*.dat +*.ctx +*.key # Packages # ############ @@ -51,6 +57,7 @@ Thumbs.db ############### CMakeCache.txt CMakeFiles +Makefile CMakeScripts cmake_install.cmake install_manifest.txt @@ -92,6 +99,7 @@ buildNumber.properties .metadata *.iml *.ipr +.vscode # Visual Studio files # ####################### diff --git a/cmake/cli_input.cmake b/cmake/cli_input.cmake index 181e86e5..0a84923d 100644 --- a/cmake/cli_input.cmake +++ b/cmake/cli_input.cmake @@ -31,6 +31,7 @@ set (RESALE true) set (REUSE true) set (MTLS false) set (GET_DEV_SERIAL false) +set (LOCK_TPM true) #for CSE set (CSE_SHUTDOWN true) @@ -883,3 +884,31 @@ endif() set(CACHED_GET_DEV_SERIAL ${GET_DEV_SERIAL} CACHE STRING "Selected GET_DEV_SERIAL") message("Selected GET_DEV_SERIAL ${GET_DEV_SERIAL}") ########################################### +# FOR LOCK TPM +if (${DA} MATCHES tpm) + get_property(cached_lock_tpm_value CACHE LOCK_TPM PROPERTY VALUE) + + set(lock_tpm_cli_arg ${cached_lock_tpm_value}) + if(lock_tpm_cli_arg STREQUAL CACHED_LOCK_TPM) + unset(lock_tpm_cli_arg) + endif() + + set(lock_tpm_app_cmake_lists ${LOCK_TPM}) + if(cached_lock_tpm_value STREQUAL LOCK_TPM) + unset(lock_tpm_app_cmake_lists) + endif() + + if(DEFINED CACHED_LOCK_TPM) + if ((DEFINED lock_tpm_cli_arg) AND (NOT(CACHED_LOCK_TPM STREQUAL lock_tpm_cli_arg))) + message(WARNING "Need to do make pristine before cmake args can change.") + endif() + set(LOCK_TPM ${CACHED_LOCK_TPM}) + elseif(DEFINED lock_tpm_cli_arg) + set(LOCK_TPM ${lock_tpm_cli_arg}) + elseif(DEFINED lock_tpm_app_cmake_lists) + set(LOCK_TPM ${lock_tpm_app_cmake_lists}) + endif() + + set(CACHED_LOCK_TPM ${LOCK_TPM} CACHE STRING "Selected LOCK_TPM") + message("Selected LOCK_TPM ${LOCK_TPM}") +endif() \ No newline at end of file diff --git a/cmake/extension.cmake b/cmake/extension.cmake index 152715b5..cc5576ee 100644 --- a/cmake/extension.cmake +++ b/cmake/extension.cmake @@ -279,4 +279,8 @@ endif() if(${GET_DEV_SERIAL} STREQUAL true) client_sdk_compile_definitions(-DGET_DEV_SERIAL) endif() + +if(${LOCK_TPM} STREQUAL true) + client_sdk_compile_definitions(-DLOCK_TPM) +endif() ############################################################ diff --git a/crypto/openssl/tpm20_Utils.c b/crypto/openssl/tpm20_Utils.c index a6d80203..ed680caf 100644 --- a/crypto/openssl/tpm20_Utils.c +++ b/crypto/openssl/tpm20_Utils.c @@ -338,10 +338,10 @@ int32_t fdo_tpm_generate_hmac_key(TPMI_DH_PERSISTENT persistent_handle) goto err; } - ret_val = Esys_EvictControl(esys_context, ESYS_TR_RH_OWNER, - persistentHandle, ESYS_TR_PASSWORD, - ESYS_TR_NONE, ESYS_TR_NONE, 0, - &pub_object_handle); + ret_val = Esys_EvictControl( + esys_context, ESYS_TR_RH_OWNER, persistentHandle, + auth_session_handle, ESYS_TR_NONE, ESYS_TR_NONE, 0, + &pub_object_handle); if (ret_val != TSS2_RC_SUCCESS) { LOG(LOG_ERROR, "Esys_EvictControl failed: 0x%x\n", ret_val); @@ -351,7 +351,7 @@ int32_t fdo_tpm_generate_hmac_key(TPMI_DH_PERSISTENT persistent_handle) } ret_val = Esys_EvictControl( - esys_context, ESYS_TR_RH_OWNER, object_handle, ESYS_TR_PASSWORD, + esys_context, ESYS_TR_RH_OWNER, object_handle, auth_session_handle, ESYS_TR_NONE, ESYS_TR_NONE, persistent_handle, &pub_object_handle); if (ret_val != TSS2_RC_SUCCESS) { LOG(LOG_ERROR, "Esys_EvictControl failed: 0x%x\n", ret_val); diff --git a/docs/build_conf.md b/docs/build_conf.md index 49c2e368..512a3298 100644 --- a/docs/build_conf.md +++ b/docs/build_conf.md @@ -78,15 +78,14 @@ $ ./build/linux-client -ss ``` > ***WARN***: Accepting Self Signed Certificates is not recommended. If compromised, self-signed certificates can pose serious security risks. -``` - +```shell Option to enable SNI(Server Name Indication extension in client(device) msgs to server): SNI=true # SNI support is enabled. (default) SNI=false # SNI support is disabled. ``` > ***Note***: If you have server IP configured in no_proxy environment variable, also add the server name in that list for SNI enablement to work as expected. -``` +```shell Option to enable/disable mTLS connection: MTLS=true # mTLS connection enabled MTLS=false # mTLS connection disabled (default) @@ -105,6 +104,10 @@ Option to get device serial from system BIOS table: GET_DEV_SERIAL=true # get device serial enabled GET_DEV_SERIAL=false # get device serial disabled (default) +Option to lock TPM for futher reads and writes: +LOCK_TPM=true # TPM Locked for futher reads and writes (default) +LOCK_TPM=false # TPM not locked for futher reads and writes + List of options to clean targets: pristine # cleanup by remove generated files diff --git a/docs/tpm.md b/docs/tpm.md index db262774..e27d789e 100644 --- a/docs/tpm.md +++ b/docs/tpm.md @@ -387,41 +387,53 @@ After a successful compilation, the FDO Client SDK Linux device executable can b >``` > ***NOTE***: linux-client may require elevated privileges. Please use 'sudo' to execute. +> ***NOTE***: To do the DI again we need to clear the Device status from TPM storage. +> To clear the TPM storage, execute the clear TPM* script. Refer to [Clear TPM](../utils/clear_tpm_nv.sh). + +```shell +sudo utils/clear_tpm_nv.sh +``` + +> ***NOTE***: Enabling LOCK_TPM flag in cmake/cli_input.cmake will lock TPM for further reads/writes. +> This flag is enabled by default. But note that this may require the user to reboot the system before any consecutive execution of linux-client. ### 7.1 Prepare FDO Client SDK Data Folder - Persistent Storage Index in TPM* - Find a persistent storage index that is unused in the TPM* and note it down. It usually starts from 0x81000000. To see the indexes that are already being used, use the following command. FDO uses the 0x81000001 index for the following command examples. - - ```shell - sudo tpm2_getcap handles-persistent - ``` +Find a persistent storage index that is unused in the TPM* and note it down. It usually starts from 0x81000000. To see the indexes that are already being used, use the following command. FDO uses the 0x81020002 index for the following command examples. +```shell +sudo tpm2_getcap handles-persistent +``` - Primary Key Generation from Endorsement Hierarchy - ```shell - sudo tpm2_createprimary -C e -g sha256 -G ecc256:aes128cfb -c data/tpm_primary_key.ctx -V - ``` +```shell +sudo tpm2_createprimary -C e -g sha256 -G ecc256:aes128cfb -c data/tpm_primary_key.ctx -V +sudo tpm2_create -g sha256 -G ecc256 -u data/tpm_ecdsa_pub.key -r data/tpm_ecdsa_priv.key -C data/tpm_primary_key.ctx -a "fixedtpm|sensitivedataorigin|fixedparent|sign|userwithauth" -V +``` -- Load the Primary Key into TPM* Persistent Memory +- Device ECDSA Key-Pair Generation and Load the Primary Key into TPM* Persistent Memory - ```shell - sudo tpm2_evictcontrol -C o 0x81000001 -c data/tpm_primary_key.ctx -V - ``` +```shell +sudo tpm2_load -C data/tpm_primary_key.ctx -u data/tpm_ecdsa_pub.key -r data/tpm_ecdsa_priv.key -c data/tpm_ecdsa_key.ctx -V +sudo tpm2_evictcontrol -C o 0x81020002 -c data/tpm_primary_key.ctx -V +``` -- Device ECDSA Key-Pair Generation +- Generate Device MString - ```shell - sudo tpm2tss-genkey -a ecdsa -c nist_p256 data/tpm_ecdsa_priv_pub_blob.key -v -P 0x81000001 - ``` +```shell +sudo openssl req -new -provider tpm2 -provider default -outform DER -out data/tpm_device_csr -key handle:0x81020002 -subj "/CN=fdo-tpm-device" -verbose +``` -- Generate Device MString +- Define a TPM Non-Volatile (NV) index for TPM Device CSR and Write TPM Device CSR to a Non-Volatile (NV) index - ```shell - sudo openssl req -new -provider tpm2 -provider default -out data/device_mstring -key data/tpm_ecdsa_priv_pub_blob.key -subj "/CN=www.fdoDevice1.intel.com" -verbose; truncate -s -1 data/device_mstring; echo -n "13" > /tmp/m_string.txt; truncate -s +1 /tmp/m_string.txt; echo -n "intel-1234" >> /tmp/m_string.txt; truncate -s +1 /tmp/m_string.txt; echo -n "model-123456" >> /tmp/m_string.txt; truncate -s +1 /tmp/m_string.txt; cat data/device_mstring >> /tmp/m_string.txt; base64 -w 0 /tmp/m_string.txt > data/device_mstring; rm -f /tmp/m_string.txt - ``` +```shell +csr_size=$(wc -c < data/tpm_device_csr) +sudo tpm2_nvdefine -Q 0x01D10005 -C o -s csr_size -a "ownerwrite|authwrite|ownerread|authread|no_da|read_stclear|writedefine" +sudo tpm2_nvwrite -Q 0x01D10005 -C o -i data/tpm_device_csr +``` ## 8. Troubleshooting Details @@ -431,19 +443,19 @@ Clear TPM* from the BIOS. To run the TPM* enabled FDO Client SDK implementation, - Clear the Used Persistent Index in TPM*.
Use the tpm2_evictcontrol command to delete the content or clear TPM* from the BIOS. To run the TPM* based FDO implementation, the TPM* on the device should not be owned. To reset the TPM*, go to your device BIOS and clear the TPM*. To find the location of the option in the BIOS of your device, refer to your device manual. - Assuming that the index is 0x81000001, run the following command to delete the keys. +To clear the TPM storage, execute the clear TPM* script. Refer to [Clear TPM](../utils/clear_tpm_nv.sh). - ```shell - sudo tpm2_evictcontrol -C o -c 0x81000001 -V - ``` +```shell +sudo utils/clear_tpm_nv.sh +``` - OpenSSL* Toolkit Library Linking Related Error While Building FDO Client SDK.
There is a dependency on the OpenSSL* toolkit version 3.0.12 for building and running the FDO Client SDK. Check the version of the OpenSSL* toolkit installed in your machine with the command - ```shell +```shell openssl version - ``` +``` If the OpenSSL* toolkit version in your machine is earlier than version 3.0.12, follow the steps given in section 1 to update the OpenSSL* version to 3.0.12. diff --git a/lib/credentials_from_file.c b/lib/credentials_from_file.c index 3f9aaa56..754fe037 100644 --- a/lib/credentials_from_file.c +++ b/lib/credentials_from_file.c @@ -472,9 +472,7 @@ int store_credential(fdo_dev_cred_t *ocred) #if defined(DEVICE_TPM20_ENABLED) /** * Write the Device Credentials to nv, contains our state - * @param dev_cred_file - pointer of type const char to which credentails are - * to be written. - * @param flags + * @param nv - tpm nv index to be written. * @param ocred - pointer of type fdo_dev_cred_t, holds the credentials for * writing to dev_cred_file. * @return true if write and parsed correctly, otherwise false @@ -499,7 +497,7 @@ bool write_tpm_device_credentials(uint32_t nv, fdo_dev_cred_t *ocred) } /** - * Blob format: Complete DeviceCredential as per Section 3.4.1 of FDO + * Format: Complete DeviceCredential as per Section 3.4.1 of FDO *Specification, except the DeviceCredential.DCHmacSecret, and addition *of 'State'. DeviceCredential = [ State, DCProtVer, * DCDeviceInfo, @@ -556,7 +554,7 @@ bool write_tpm_device_credentials(uint32_t nv, fdo_dev_cred_t *ocred) fdow->b.block_size = encoded_cred_length; if (fdo_tpm_write_nv(nv, fdow->b.block, fdow->b.block_size) == -1) { - LOG(LOG_ERROR, "Failed to write DeviceCredential blob\n"); + LOG(LOG_ERROR, "Failed to write DeviceCredential in TPM\n"); ret = false; goto end; } @@ -571,9 +569,8 @@ bool write_tpm_device_credentials(uint32_t nv, fdo_dev_cred_t *ocred) } /** - * Read the Device Credentials blob from tpm nv, contains our state & owner_blk - * @param dev_cred_file - the blob the credentials are saved in - * @param flags - descriptor telling type of file + * Read the Device Credentials from tpm nv, contains our state & owner_blk + * @param nv - tpm nv index to be read. * @param our_dev_cred - pointer to the device credentials block, * @return true if read and parsed correctly, otherwise false. */ @@ -603,7 +600,6 @@ bool read_tpm_device_credentials(uint32_t nv, fdo_dev_cred_t *our_dev_cred) dev_cred_len = fdo_tpm_size_nv(nv); // Device has not yet been initialized. - // Since, Normal.blob is empty, the file size will be 0 if (dev_cred_len == 0) { LOG(LOG_DEBUG, "DeviceCredential not found. Proceeding with DI\n"); @@ -611,7 +607,7 @@ bool read_tpm_device_credentials(uint32_t nv, fdo_dev_cred_t *our_dev_cred) return true; } - LOG(LOG_DEBUG, "Reading DeviceCredential blob of length %" PRIu64 "\n", + LOG(LOG_DEBUG, "Reading DeviceCredential of length %" PRIu64 "\n", dev_cred_len); fdor = fdo_alloc(sizeof(fdor_t)); @@ -622,8 +618,7 @@ bool read_tpm_device_credentials(uint32_t nv, fdo_dev_cred_t *our_dev_cred) } if (fdo_tpm_read_nv(nv, fdor->b.block, fdor->b.block_size) == -1) { - LOG(LOG_ERROR, - "Failed to read DeviceCredential blob : Normal.blob\n"); + LOG(LOG_ERROR, "Failed to read TPM DeviceCredential\n"); goto end; } @@ -733,23 +728,41 @@ int store_tpm_credential(fdo_dev_cred_t *ocred) /* Write in the file and save the Normal device credentials */ LOG(LOG_DEBUG, "Writing to TPM NV storage\n"); - const char *dc_active = (ocred->dc_active == true) ? "true" : "false"; - size_t dc_active_len = strnlen_s(dc_active, BUFF_SIZE_8_BYTES); - if (!dc_active_len || dc_active_len == BUFF_SIZE_8_BYTES) { - LOG(LOG_ERROR, "Strlen() failed!\n") + uint8_t *dc_active = NULL; + size_t dc_active_len = sizeof(uint8_t); + dc_active = fdo_alloc(dc_active_len); + if (NULL == dc_active) { + LOG(LOG_ERROR, "Malloc Failed in %s!\n", __func__); return -1; } - if (fdo_tpm_nvwrite((uint8_t *)(dc_active), dc_active_len, - FDO_DCActive_NV_IDX)) { + *dc_active = ocred->dc_active; + + if (fdo_tpm_nvwrite(dc_active, dc_active_len, FDO_DCActive_NV_IDX)) { LOG(LOG_ERROR, "Failed to write DeviceCredential Active\n"); + fdo_free(dc_active); return -1; } + if (dc_active) { + fdo_free(dc_active); + } + if (!write_tpm_device_credentials(FDO_CRED_NV_IDX, ocred)) { LOG(LOG_ERROR, "Could not write to Normal Credentials\n"); return -1; } +#if defined(LOCK_TPM) + if (fdo_tpm_nvwrite_lock(FDO_CRED_NV_IDX)) { + LOG(LOG_ERROR, "Failed to lock file!\n"); + return -1; + } + + if (fdo_tpm_nvread_lock(FDO_CRED_NV_IDX)) { + LOG(LOG_ERROR, "Failed to lock file!\n"); + return -1; + } +#endif return 0; } #endif @@ -915,14 +928,14 @@ int load_credential(fdo_dev_cred_t *ocred) } #elif defined(DEVICE_TPM20_ENABLED) /* Read and save the device credentials */ - u_int8_t *dc_active = NULL; + uint8_t *dc_active = NULL; size_t dc_active_len = fdo_tpm_nvread_size(FDO_DCActive_NV_IDX); if (dc_active_len == 0) { LOG(LOG_ERROR, "DeviceCredential Active not found.\n"); return -1; } - dc_active = fdo_alloc(dc_active_len + 1); + dc_active = fdo_alloc(dc_active_len); if (NULL == dc_active) { LOG(LOG_ERROR, "Malloc Failed in %s!\n", __func__); return -1; @@ -933,13 +946,12 @@ int load_credential(fdo_dev_cred_t *ocred) fdo_free(dc_active); return -1; } - int strcmp_res = -1; - if (!strcmp_s((char *)dc_active, dc_active_len, "true", &strcmp_res) && - !strcmp_res) { + + if (*dc_active == 1) { ocred->dc_active = true; if (!read_tpm_device_credentials(FDO_CRED_NV_IDX, ocred)) { LOG(LOG_ERROR, - "Could not parse the Device Credentials blob\n"); + "Could not read the Device Credentials from TPM\n"); fdo_free(dc_active); return -1; } diff --git a/lib/include/fdoprot.h b/lib/include/fdoprot.h index 5b7c763c..2de18583 100644 --- a/lib/include/fdoprot.h +++ b/lib/include/fdoprot.h @@ -152,7 +152,7 @@ typedef struct fdo_prot_s { fdo_dev_cred_t *dev_cred; fdo_public_key_t *owner_public_key; // Owner's public key fdo_service_info_t *service_info; // store System ServiceInfo - // (devmod+unsupported module list) + // (devmod+unsupported module list) fdo_byte_array_t *ext_service_info; // store External module // ServiceInfoVal (fdo_sys, for ex.) fdo_public_key_t *tls_key; // unused for now diff --git a/lib/m-string.c b/lib/m-string.c index e8e2a1a0..7fba3aee 100644 --- a/lib/m-string.c +++ b/lib/m-string.c @@ -266,6 +266,12 @@ int ps_get_m_string(fdo_prot_t *ps) LOG(LOG_ERROR, "Failed to load TPM DEVICE CSR into buffer.\n"); goto err; } +#if defined(LOCK_TPM) + if (fdo_tpm_nvread_lock(TPM_DEVICE_CSR_NV_IDX)) { + LOG(LOG_ERROR, "Failed to lock file!\n"); + goto err; + } +#endif ret = 0; #elif defined(DEVICE_CSE_ENABLED) // CSR will be NULL for CSE diff --git a/storage/include/tpm2_nv_storage.h b/storage/include/tpm2_nv_storage.h index d62a8a42..2a833b24 100644 --- a/storage/include/tpm2_nv_storage.h +++ b/storage/include/tpm2_nv_storage.h @@ -37,6 +37,15 @@ int fdo_tpm_nvdefine(TPMI_RH_NV_INDEX nv, size_t data_size); */ int fdo_tpm_nvwrite(const uint8_t *data, size_t data_size, TPMI_RH_NV_INDEX nv); +/** Lock the NV index for further writes. + * + * @param[in] nv NV index to store the data. + * @retval 0 on success. + * @retval -1 on undefined/general failure. + * @retval TSS2_RC response code for failures relayed from the TSS library. + */ +int fdo_tpm_nvwrite_lock(TPMI_RH_NV_INDEX nv); + /** Load data size from a NV index. * * @param[in] nv NV index of the data. @@ -57,6 +66,15 @@ size_t fdo_tpm_nvread_size(TPMI_RH_NV_INDEX nv); */ int fdo_tpm_nvread(TPMI_RH_NV_INDEX nv, size_t data_size, uint8_t **data); +/** Lock the NV index for further reads. + * + * @param[in] nv NV index to store the data. + * @retval 0 on success. + * @retval -1 on undefined/general failure. + * @retval TSS2_RC response code for failures relayed from the TSS library. + */ +int fdo_tpm_nvread_lock(TPMI_RH_NV_INDEX nv); + /** Delete data from a NV index. * * @param[in] nv NV index to delete. diff --git a/storage/linux/tpm2_nv_storage.c b/storage/linux/tpm2_nv_storage.c index 4cb4c47e..9e67dca4 100644 --- a/storage/linux/tpm2_nv_storage.c +++ b/storage/linux/tpm2_nv_storage.c @@ -180,7 +180,8 @@ int fdo_tpm_nvdefine(TPMI_RH_NV_INDEX nv, size_t data_size) .nameAlg = FDO_TPM2_ALG_SHA, .attributes = (TPMA_NV_OWNERWRITE | TPMA_NV_AUTHWRITE | TPMA_NV_AUTHREAD | - TPMA_NV_OWNERREAD | TPMA_NV_NO_DA), + TPMA_NV_OWNERREAD | TPMA_NV_NO_DA | TPMA_NV_READ_STCLEAR | + TPMA_NV_WRITE_STCLEAR | TPMA_NV_WRITEDEFINE), .authPolicy = { .size = 0, @@ -277,7 +278,8 @@ int fdo_tpm_nvwrite(const uint8_t *data, size_t data_size, TPMI_RH_NV_INDEX nv) .nameAlg = FDO_TPM2_ALG_SHA, .attributes = (TPMA_NV_OWNERWRITE | TPMA_NV_AUTHWRITE | TPMA_NV_AUTHREAD | - TPMA_NV_OWNERREAD | TPMA_NV_NO_DA), + TPMA_NV_OWNERREAD | TPMA_NV_NO_DA | TPMA_NV_READ_STCLEAR | + TPMA_NV_WRITEDEFINE), .authPolicy = { .size = 0, @@ -329,8 +331,9 @@ int fdo_tpm_nvwrite(const uint8_t *data, size_t data_size, TPMI_RH_NV_INDEX nv) capability_data->data.handles.handle[0] == nv); if (exists == 1) { LOG(LOG_DEBUG, "NV index already exist. Deleting it.\n"); - rc = Esys_TR_FromTPMPublic(ctx, nv, ESYS_TR_NONE, ESYS_TR_NONE, - ESYS_TR_NONE, &nvHandle); + rc = Esys_TR_FromTPMPublic(ctx, nv, auth_session_handle, + ESYS_TR_NONE, ESYS_TR_NONE, + &nvHandle); if (rc != TSS2_RC_SUCCESS) { LOG(LOG_ERROR, "Failed to constructs an ESYS_TR object.\n"); @@ -372,6 +375,69 @@ int fdo_tpm_nvwrite(const uint8_t *data, size_t data_size, TPMI_RH_NV_INDEX nv) return ret; } +/** Lock the NV index for further writes. + * + * @param[in] nv NV index to store the data. + * @retval 0 on success. + * @retval -1 on undefined/general failure. + * @retval TSS2_RC response code for failures relayed from the TSS library. + */ +int fdo_tpm_nvwrite_lock(TPMI_RH_NV_INDEX nv) +{ + if (!nv) { + return -1; + } + + int ret = -1; + TSS2_RC rc; + ESYS_CONTEXT *ctx; + ESYS_TR nvHandle = ESYS_TR_NONE; + ESYS_TR auth_session_handle = ESYS_TR_NONE; + + rc = fdo_tpm_esys_context_init(&ctx); + if (rc != TSS2_RC_SUCCESS || !ctx) { + LOG(LOG_ERROR, "Failed to intitialize Esys context.\n"); + goto err; + } + + rc = fdo_tpm_esys_auth_session_init(ctx, &auth_session_handle); + if (rc != TSS2_RC_SUCCESS || !auth_session_handle) { + LOG(LOG_ERROR, "Failed to create Auth Session for Esys API.\n"); + goto err; + } + + rc = Esys_Startup(ctx, TPM2_SU_CLEAR); + if (rc != TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, "Failed to start Esys context.\n"); + goto err; + } + + rc = Esys_TR_FromTPMPublic(ctx, nv, auth_session_handle, ESYS_TR_NONE, + ESYS_TR_NONE, &nvHandle); + if (rc != TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, "Failed to constructs an ESYS_TR object.\n"); + goto err; + } + + rc = Esys_NV_WriteLock(ctx, ESYS_TR_RH_OWNER, nvHandle, + auth_session_handle, ESYS_TR_NONE, ESYS_TR_NONE); + if (rc != TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, "Failed to lock NV write.\n"); + goto err; + } + + ret = 0; + +err: + + if (ctx && (0 != fdo_tpm_context_clean_up(&ctx, &auth_session_handle, + &nvHandle))) { + LOG(LOG_ERROR, "Failed to tear down all the TSS context.\n"); + ret = -1; + } + return ret; +} + /** Load data size from a NV index. * * @param[in] nv NV index of the data. @@ -429,15 +495,15 @@ size_t fdo_tpm_nvread_size(TPMI_RH_NV_INDEX nv) goto err; } - rc = Esys_TR_FromTPMPublic(ctx, nv, ESYS_TR_NONE, ESYS_TR_NONE, + rc = Esys_TR_FromTPMPublic(ctx, nv, auth_session_handle, ESYS_TR_NONE, ESYS_TR_NONE, &nvHandle); if (rc != TSS2_RC_SUCCESS) { LOG(LOG_ERROR, "Failed to constructs an ESYS_TR object.\n"); goto err; } - rc = Esys_NV_ReadPublic(ctx, nvHandle, ESYS_TR_NONE, ESYS_TR_NONE, - ESYS_TR_NONE, &publicInfo, NULL); + rc = Esys_NV_ReadPublic(ctx, nvHandle, auth_session_handle, + ESYS_TR_NONE, ESYS_TR_NONE, &publicInfo, NULL); if (rc != TSS2_RC_SUCCESS) { LOG(LOG_ERROR, "Failed to read publicinfo from NV.\n"); goto err; @@ -478,7 +544,6 @@ int fdo_tpm_nvread(TPMI_RH_NV_INDEX nv, size_t data_size, uint8_t **data) ESYS_TR nvHandle = ESYS_TR_NONE; ESYS_TR auth_session_handle = ESYS_TR_NONE; TPM2B_MAX_NV_BUFFER *blob; - TPM2B_NV_PUBLIC *publicInfo; if (!nv) { return -1; @@ -502,20 +567,13 @@ int fdo_tpm_nvread(TPMI_RH_NV_INDEX nv, size_t data_size, uint8_t **data) goto err; } - rc = Esys_TR_FromTPMPublic(ctx, nv, ESYS_TR_NONE, ESYS_TR_NONE, + rc = Esys_TR_FromTPMPublic(ctx, nv, auth_session_handle, ESYS_TR_NONE, ESYS_TR_NONE, &nvHandle); if (rc != TSS2_RC_SUCCESS) { LOG(LOG_ERROR, "Failed to constructs an ESYS_TR object.\n"); goto err; } - rc = Esys_NV_ReadPublic(ctx, nvHandle, ESYS_TR_NONE, ESYS_TR_NONE, - ESYS_TR_NONE, &publicInfo, NULL); - if (rc != TSS2_RC_SUCCESS) { - LOG(LOG_ERROR, "Failed to read publicinfo from NV.\n"); - goto err; - } - rc = Esys_NV_Read(ctx, ESYS_TR_RH_OWNER, nvHandle, auth_session_handle, ESYS_TR_NONE, ESYS_TR_NONE, data_size, 0 /*=offset*/, &blob); @@ -533,10 +591,69 @@ int fdo_tpm_nvread(TPMI_RH_NV_INDEX nv, size_t data_size, uint8_t **data) err: - if (publicInfo) { - free(publicInfo); + if (ctx && (0 != fdo_tpm_context_clean_up(&ctx, &auth_session_handle, + &nvHandle))) { + LOG(LOG_ERROR, "Failed to tear down all the TSS context.\n"); + ret = -1; + } + return ret; +} + +/** Lock the NV index for further reads. + * + * @param[in] nv NV index to store the data. + * @retval 0 on success. + * @retval -1 on undefined/general failure. + * @retval TSS2_RC response code for failures relayed from the TSS library. + */ +int fdo_tpm_nvread_lock(TPMI_RH_NV_INDEX nv) +{ + if (!nv) { + return -1; + } + + int ret = -1; + TSS2_RC rc; + ESYS_CONTEXT *ctx; + ESYS_TR nvHandle = ESYS_TR_NONE; + ESYS_TR auth_session_handle = ESYS_TR_NONE; + + rc = fdo_tpm_esys_context_init(&ctx); + if (rc != TSS2_RC_SUCCESS || !ctx) { + LOG(LOG_ERROR, "Failed to intitialize Esys context.\n"); + goto err; + } + + rc = fdo_tpm_esys_auth_session_init(ctx, &auth_session_handle); + if (rc != TSS2_RC_SUCCESS || !auth_session_handle) { + LOG(LOG_ERROR, "Failed to create Auth Session for Esys API.\n"); + goto err; + } + + rc = Esys_Startup(ctx, TPM2_SU_CLEAR); + if (rc != TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, "Failed to start Esys context.\n"); + goto err; + } + + rc = Esys_TR_FromTPMPublic(ctx, nv, auth_session_handle, ESYS_TR_NONE, + ESYS_TR_NONE, &nvHandle); + if (rc != TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, "Failed to constructs an ESYS_TR object.\n"); + goto err; } + rc = Esys_NV_ReadLock(ctx, ESYS_TR_RH_OWNER, nvHandle, + auth_session_handle, ESYS_TR_NONE, ESYS_TR_NONE); + if (rc != TSS2_RC_SUCCESS) { + LOG(LOG_ERROR, "Failed to lock NV read.\n"); + goto err; + } + + ret = 0; + +err: + if (ctx && (0 != fdo_tpm_context_clean_up(&ctx, &auth_session_handle, &nvHandle))) { LOG(LOG_ERROR, "Failed to tear down all the TSS context.\n"); diff --git a/utils/tpm_make_ready_ecdsa.sh b/utils/tpm_make_ready_ecdsa.sh index 08be787a..c353131a 100644 --- a/utils/tpm_make_ready_ecdsa.sh +++ b/utils/tpm_make_ready_ecdsa.sh @@ -124,7 +124,7 @@ execute_cmd_on_failure_exit "\$cmd" "\$success_string" "\$failure_string" 1 1 # # write device csr inside tpm task="Define a TPM Non-Volatile (NV) index for TPM Device CSR" csr_size=$(wc -c < $device_csr_file) -cmd="tpm2_nvdefine -Q 0x01D10005 -C o -s $csr_size -a \"ownerwrite|authwrite|ownerread|authread|no_da\"" +cmd="tpm2_nvdefine -Q 0x01D10005 -C o -s $csr_size -a \"ownerwrite|authwrite|ownerread|authread|no_da|read_stclear|writedefine\"" success_string="$task completed successfully!!" failure_string="$task failed" execute_cmd_on_failure_exit "\$cmd" "\$success_string" "\$failure_string" 1 1 From 96650ccbb5d0fafd17ce1af91b9f3fdfb127d347 Mon Sep 17 00:00:00 2001 From: Shrikant Temburwar Date: Mon, 29 Jan 2024 11:23:51 +0530 Subject: [PATCH 9/9] Add command to lock the Device CSR Non-Volatile (NV) index for further writes Signed-off-by: Shrikant Temburwar --- utils/tpm_make_ready_ecdsa.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/utils/tpm_make_ready_ecdsa.sh b/utils/tpm_make_ready_ecdsa.sh index c353131a..45c51a61 100644 --- a/utils/tpm_make_ready_ecdsa.sh +++ b/utils/tpm_make_ready_ecdsa.sh @@ -135,6 +135,12 @@ success_string="$task completed successfully!!" failure_string="$task failed" execute_cmd_on_failure_exit "\$cmd" "\$success_string" "\$failure_string" 1 1 +task="Lock the Device CSR Non-Volatile (NV) index for further writes" +cmd="tpm2_nvwritelock -C o 0x01D10005" +success_string="$task completed successfully!!" +failure_string="$task failed" +execute_cmd_on_failure_exit "\$cmd" "\$success_string" "\$failure_string" 1 1 + rm -f $tpm_device_pub_key_file rm -f $tpm_device_priv_key_file rm -f $device_csr_file