From ee4b66fc281a959623a021d2ad49edca15c39b8f Mon Sep 17 00:00:00 2001 From: Manjeet Singh Date: Wed, 13 May 2026 13:49:07 +0530 Subject: [PATCH] TPM: configurable TPM key handles Make TPM key handles configurable instead of relying on hardcoded values. This allows platform integrators to supply environment-specific handle assignments, improves flexibility across TPM deployments, and prepares the codebase for cleaner configuration and testing of TPM-backed key operations. Signed-off-by: Manjeet Singh --- CMakeLists.txt | 14 ++ .../spdm_device_secret_lib_tpm/CMakeLists.txt | 8 ++ os_stub/spdm_device_secret_lib_tpm/csr.c | 16 ++- os_stub/spdm_device_secret_lib_tpm/keys.h | 25 ---- os_stub/spdm_device_secret_lib_tpm/keys.h.in | 28 ++++ .../read_pub_cert.c | 132 +++++++++++++----- os_stub/spdm_device_secret_lib_tpm/sign.c | 4 +- 7 files changed, 159 insertions(+), 68 deletions(-) delete mode 100644 os_stub/spdm_device_secret_lib_tpm/keys.h create mode 100644 os_stub/spdm_device_secret_lib_tpm/keys.h.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 0f2f8b6d4d2..0668cde6002 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,6 +40,20 @@ set(DEVICE ${DEVICE} CACHE STRING "Choose the test device: sample tpm, and defau option(LIBSPDM_TPM_SUPPORT "Add TPM support in crypt_ext" OFF) +# TPM Handle Configuration Options (slot-based configuration) +# Root and leaf certificates are extracted from certificate chains +# Requester handles +set(LIBSPDM_TPM_HANDLE_REQUESTER_HANDLE_SLOT_0 "handle:0x81000011" CACHE STRING "TPM Requester Handle String Slot 0") +set(LIBSPDM_TPM_HANDLE_REQUESTER_CERTCHAIN_SLOT_0 "0x1500011" CACHE STRING "TPM Requester Certificate Chain NV Index Slot 0") +set(LIBSPDM_TPM_HANDLE_REQUESTER_HANDLE_SLOT_1 "handle:0x81000012" CACHE STRING "TPM Requester Handle String Slot 1") +set(LIBSPDM_TPM_HANDLE_REQUESTER_CERTCHAIN_SLOT_1 "0x1500012" CACHE STRING "TPM Requester Certificate Chain NV Index Slot 1") + +# Responder handles +set(LIBSPDM_TPM_HANDLE_RESPONDER_HANDLE_SLOT_0 "handle:0x81000021" CACHE STRING "TPM Responder Handle String Slot 0") +set(LIBSPDM_TPM_HANDLE_RESPONDER_CERTCHAIN_SLOT_0 "0x1500021" CACHE STRING "TPM Responder Certificate Chain NV Index Slot 0") +set(LIBSPDM_TPM_HANDLE_RESPONDER_HANDLE_SLOT_1 "handle:0x81000022" CACHE STRING "TPM Responder Handle String Slot 1") +set(LIBSPDM_TPM_HANDLE_RESPONDER_CERTCHAIN_SLOT_1 "0x1500031" CACHE STRING "TPM Responder Certificate Chain NV Index Slot 1") + if(NOT GCOV) set(GCOV "OFF") endif() diff --git a/os_stub/spdm_device_secret_lib_tpm/CMakeLists.txt b/os_stub/spdm_device_secret_lib_tpm/CMakeLists.txt index 47748d12086..804f19aa24f 100644 --- a/os_stub/spdm_device_secret_lib_tpm/CMakeLists.txt +++ b/os_stub/spdm_device_secret_lib_tpm/CMakeLists.txt @@ -1,9 +1,17 @@ cmake_minimum_required(VERSION 3.5) +# Configure keys.h from template with CMake variables +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/keys.h.in + ${CMAKE_CURRENT_BINARY_DIR}/keys.h + @ONLY +) + add_library(spdm_device_secret_lib_tpm STATIC "") target_include_directories(spdm_device_secret_lib_tpm PRIVATE + ${CMAKE_CURRENT_BINARY_DIR} ${LIBSPDM_DIR}/os_stub/spdm_device_secret_lib_tpm ${LIBSPDM_DIR}/include ${LIBSPDM_DIR}/include/hal diff --git a/os_stub/spdm_device_secret_lib_tpm/csr.c b/os_stub/spdm_device_secret_lib_tpm/csr.c index f40297b4902..335d96cccb5 100644 --- a/os_stub/spdm_device_secret_lib_tpm/csr.c +++ b/os_stub/spdm_device_secret_lib_tpm/csr.c @@ -117,17 +117,27 @@ bool libspdm_gen_csr_without_reset(uint32_t base_hash_algo, uint32_t base_asym_a void *cert; void *x509_ca_cert; + size_t x509_ca_cert_len; + int8_t cert_count; size_t cert_size; - if (!libspdm_tpm_get_pvt_key_handle(TPM_RESP_HANDLE, &context)) { + if (!libspdm_tpm_get_pvt_key_handle(LIBSPDM_TPM_HANDLE_RESPONDER_HANDLE_SLOT_0, &context)) { return false; } - if (!libspdm_tpm_read_nv(TPM_RESP_CERT, &cert, &cert_size)) { + if (!libspdm_tpm_read_nv(LIBSPDM_TPM_HANDLE_RESPONDER_CERTCHAIN_SLOT_1, &cert, &cert_size)) { return false; } - if (!libspdm_x509_construct_certificate(cert, cert_size, (uint8_t**)&x509_ca_cert)) { + cert_count = libspdm_x509_get_cert_from_cert_chain(cert, cert_size, -1, NULL, NULL); + if (cert_count <= 0) { + free(cert); + return false; + } + + if (!libspdm_x509_get_cert_from_cert_chain(cert, cert_size, cert_count-1, (const uint8_t**) &x509_ca_cert, + &x509_ca_cert_len)) { + free(cert); return false; } diff --git a/os_stub/spdm_device_secret_lib_tpm/keys.h b/os_stub/spdm_device_secret_lib_tpm/keys.h deleted file mode 100644 index 34533f406b0..00000000000 --- a/os_stub/spdm_device_secret_lib_tpm/keys.h +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Copyright Notice: - * Copyright 2024-2025 DMTF. All rights reserved. - * License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md - **/ - -#pragma once - -#define TPM_ROOT_CTX 0x81000000 -#define TPM_ROOT_KEY 0x81000001 - -#define TPM_REQU_CTX 0x81000010 -#define TPM_REQU_KEY 0x81000011 -#define TPM_REQU_HANDLE "handle:0x81000011" - -#define TPM_RESP_CTX 0x81000020 -#define TPM_RESP_KEY 0x81000021 -#define TPM_RESP_HANDLE "handle:0x81000021" - -#define TPM_ROOT_CERT 0x1500000 -#define TPM_REQU_CERT 0x1500010 -#define TPM_RESP_CERT 0x1500020 - -#define TPM_REQU_CERT_CHAIN 0x1500011 -#define TPM_RESP_CERT_CHAIN 0x1500021 diff --git a/os_stub/spdm_device_secret_lib_tpm/keys.h.in b/os_stub/spdm_device_secret_lib_tpm/keys.h.in new file mode 100644 index 00000000000..5532c629313 --- /dev/null +++ b/os_stub/spdm_device_secret_lib_tpm/keys.h.in @@ -0,0 +1,28 @@ +/** + * Copyright Notice: + * Copyright 2024-2025 DMTF. All rights reserved. + * License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md + **/ + +#pragma once + +/* TPM Requester Handles - Slot 0 */ +#cmakedefine LIBSPDM_TPM_HANDLE_REQUESTER_HANDLE_SLOT_0 "@LIBSPDM_TPM_HANDLE_REQUESTER_HANDLE_SLOT_0@" +#cmakedefine LIBSPDM_TPM_HANDLE_REQUESTER_CERTCHAIN_SLOT_0 @LIBSPDM_TPM_HANDLE_REQUESTER_CERTCHAIN_SLOT_0@ + +/* TPM Requester Handles - Slot 1 */ +#cmakedefine LIBSPDM_TPM_HANDLE_REQUESTER_HANDLE_SLOT_1 "@LIBSPDM_TPM_HANDLE_REQUESTER_HANDLE_SLOT_1@" +#cmakedefine LIBSPDM_TPM_HANDLE_REQUESTER_CERTCHAIN_SLOT_1 @LIBSPDM_TPM_HANDLE_REQUESTER_CERTCHAIN_SLOT_1@ + +/* TPM Responder Handles - Slot 0 */ +#cmakedefine LIBSPDM_TPM_HANDLE_RESPONDER_HANDLE_SLOT_0 "@LIBSPDM_TPM_HANDLE_RESPONDER_HANDLE_SLOT_0@" +#cmakedefine LIBSPDM_TPM_HANDLE_RESPONDER_CERT_SLOT_0 @LIBSPDM_TPM_HANDLE_RESPONDER_CERT_SLOT_0@ +#cmakedefine LIBSPDM_TPM_HANDLE_RESPONDER_CERTCHAIN_SLOT_0 @LIBSPDM_TPM_HANDLE_RESPONDER_CERTCHAIN_SLOT_0@ + +/* TPM Responder Handles - Slot 1 */ +#cmakedefine LIBSPDM_TPM_HANDLE_RESPONDER_HANDLE_SLOT_1 "@LIBSPDM_TPM_HANDLE_RESPONDER_HANDLE_SLOT_1@" +#cmakedefine LIBSPDM_TPM_HANDLE_RESPONDER_CERT_SLOT_1 @LIBSPDM_TPM_HANDLE_RESPONDER_CERT_SLOT_1@ +#cmakedefine LIBSPDM_TPM_HANDLE_RESPONDER_CERTCHAIN_SLOT_1 @LIBSPDM_TPM_HANDLE_RESPONDER_CERTCHAIN_SLOT_1@ + +/* TPM Root Certificate (shared across slots) */ +#cmakedefine LIBSPDM_TPM_HANDLE_ROOT_CERT @LIBSPDM_TPM_HANDLE_ROOT_CERT@ \ No newline at end of file diff --git a/os_stub/spdm_device_secret_lib_tpm/read_pub_cert.c b/os_stub/spdm_device_secret_lib_tpm/read_pub_cert.c index 5c3a69a1b1b..e172830e5b0 100644 --- a/os_stub/spdm_device_secret_lib_tpm/read_pub_cert.c +++ b/os_stub/spdm_device_secret_lib_tpm/read_pub_cert.c @@ -20,47 +20,59 @@ #include "library/spdm_crypt_ext_lib.h" #include "keys.h" -static bool get_certificate(uint32_t index, uint32_t base_hash_algo, uint32_t base_asym_algo, void **data, - size_t *size, void **hash, size_t *hash_size) +static bool get_root_certificate_from_chain(uint32_t chain_index, uint32_t base_hash_algo, + uint32_t base_asym_algo, void **data, + size_t *size, void **hash, size_t *hash_size) { bool result; - void *cert; - size_t cert_size; - spdm_cert_chain_t *cert_chain; + void *cert_chain_data; size_t cert_chain_size; + const uint8_t *root_cert; + size_t root_cert_len; + spdm_cert_chain_t *cert_chain; + size_t output_cert_chain_size; size_t digest_size; if (!libspdm_tpm_device_init()) return false; - result = libspdm_tpm_read_nv(index, &cert, &cert_size); + result = libspdm_tpm_read_nv(chain_index, &cert_chain_data, &cert_chain_size); if (!result) return false; + /* Extract root certificate from chain */ + result = libspdm_x509_get_cert_from_cert_chain(cert_chain_data, cert_chain_size, 0, + &root_cert, &root_cert_len); + if (!result) { + free(cert_chain_data); + return false; + } + digest_size = libspdm_get_hash_size(base_hash_algo); - cert_chain_size = sizeof(spdm_cert_chain_t) + digest_size + cert_size; - cert_chain = (void *)malloc(cert_chain_size); + /* Create cert chain with just root cert */ + output_cert_chain_size = sizeof(spdm_cert_chain_t) + digest_size + root_cert_len; + cert_chain = (void *)malloc(output_cert_chain_size); if (cert_chain == NULL){ - result = false; - goto cleanup_cert; + free(cert_chain_data); + return false; } - cert_chain->length = (uint32_t)cert_chain_size; + cert_chain->length = (uint32_t)output_cert_chain_size; - result = libspdm_hash_all(base_hash_algo, cert, cert_size, + result = libspdm_hash_all(base_hash_algo, root_cert, root_cert_len, (uint8_t *)(cert_chain + 1)); if (!result){ - result = false; free(cert_chain); - goto cleanup_cert; + free(cert_chain_data); + return false; } libspdm_copy_mem((uint8_t *)cert_chain + sizeof(spdm_cert_chain_t) + digest_size, - cert_chain_size - (sizeof(spdm_cert_chain_t) + digest_size), - cert, cert_size); + output_cert_chain_size - (sizeof(spdm_cert_chain_t) + digest_size), + root_cert, root_cert_len); *data = cert_chain; - *size = cert_chain_size; + *size = output_cert_chain_size; if (hash != NULL) *hash = (cert_chain + 1); @@ -68,10 +80,55 @@ static bool get_certificate(uint32_t index, uint32_t base_hash_algo, uint32_t ba if (hash_size != NULL) *hash_size = digest_size; -cleanup_cert: - free(cert); + free(cert_chain_data); + return true; +} - return result; +static bool get_leaf_certificate_from_chain(uint32_t chain_index, uint32_t base_asym_algo, + void **data, size_t *size) +{ + bool result; + void *cert_chain_data; + size_t cert_chain_size; + const uint8_t *leaf_cert; + size_t leaf_cert_len; + int32_t cert_count; + + if (!libspdm_tpm_device_init()) + return false; + + result = libspdm_tpm_read_nv(chain_index, &cert_chain_data, &cert_chain_size); + if (!result) + return false; + + /* Get certificate count */ + cert_count = libspdm_x509_get_cert_from_cert_chain(cert_chain_data, cert_chain_size, -1, + NULL, NULL); + if (cert_count <= 0) { + free(cert_chain_data); + return false; + } + + /* Extract leaf certificate (last in chain) */ + result = libspdm_x509_get_cert_from_cert_chain(cert_chain_data, cert_chain_size, + cert_count - 1, &leaf_cert, &leaf_cert_len); + if (!result) { + free(cert_chain_data); + return false; + } + + /* Allocate and copy leaf cert */ + *data = malloc(leaf_cert_len); + if (*data == NULL) { + free(cert_chain_data); + return false; + } + + libspdm_copy_mem(*data, leaf_cert_len, leaf_cert, leaf_cert_len); + *size = leaf_cert_len; + + free(cert_chain_data); + return true; } static bool get_certificate_chain(uint32_t index, uint32_t base_hash_algo, uint32_t base_asym_algo, void **data, @@ -149,37 +206,29 @@ bool libspdm_read_requester_root_public_certificate(uint32_t base_hash_algo, void **hash, size_t *hash_size) { - return get_certificate(TPM_ROOT_CERT, base_hash_algo, base_asym_algo, data, size, hash, hash_size); + return get_root_certificate_from_chain(LIBSPDM_TPM_HANDLE_REQUESTER_CERTCHAIN_SLOT_0, + base_hash_algo, base_asym_algo, data, size, hash, hash_size); } bool libspdm_read_requester_public_certificate_chain( uint32_t base_hash_algo, uint16_t req_base_asym_alg, void **data, size_t *size, void **hash, size_t *hash_size) { - return get_certificate_chain(TPM_REQU_CERT_CHAIN, base_hash_algo, req_base_asym_alg, data, size, hash, + return get_certificate_chain(LIBSPDM_TPM_HANDLE_REQUESTER_CERTCHAIN_SLOT_0, base_hash_algo, req_base_asym_alg, data, + size, hash, hash_size, false, true); } bool libspdm_read_responder_certificate(uint32_t base_asym_algo, void **data, size_t *size) { - bool result; - void *cert; - size_t cert_size; - if (base_asym_algo != SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256){ LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR, "unsupported asym algo %d\n", base_asym_algo)); return false; } - if (!libspdm_tpm_device_init()) - return false; - - result = libspdm_tpm_read_nv(TPM_RESP_CERT, &cert, &cert_size); - if (!result) - return false; - - return true; + return get_leaf_certificate_from_chain(LIBSPDM_TPM_HANDLE_RESPONDER_CERTCHAIN_SLOT_0, + base_asym_algo, data, size); } bool libspdm_read_responder_root_public_certificate(uint32_t base_hash_algo, @@ -188,14 +237,16 @@ bool libspdm_read_responder_root_public_certificate(uint32_t base_hash_algo, void **hash, size_t *hash_size) { - return get_certificate(TPM_ROOT_CERT, base_hash_algo, base_asym_algo, data, size, hash, hash_size); + return get_root_certificate_from_chain(LIBSPDM_TPM_HANDLE_RESPONDER_CERTCHAIN_SLOT_0, + base_hash_algo, base_asym_algo, data, size, hash, hash_size); } bool libspdm_read_responder_public_certificate_chain( uint32_t base_hash_algo, uint32_t base_asym_algo, void **data, size_t *size, void **hash, size_t *hash_size) { - return get_certificate_chain(TPM_RESP_CERT_CHAIN, base_hash_algo, base_asym_algo, data, size, hash, hash_size, + return get_certificate_chain(LIBSPDM_TPM_HANDLE_RESPONDER_CERTCHAIN_SLOT_0, base_hash_algo, base_asym_algo, data, + size, hash, hash_size, false, true); } @@ -206,14 +257,19 @@ bool libspdm_read_responder_root_public_certificate_slot(uint8_t slot_id, void **hash, size_t *hash_size) { - return get_certificate(TPM_ROOT_CERT, base_hash_algo, base_asym_algo, data, size, hash, hash_size); + uint32_t chain_index = (slot_id == 0) ? LIBSPDM_TPM_HANDLE_RESPONDER_CERTCHAIN_SLOT_0 + : LIBSPDM_TPM_HANDLE_RESPONDER_CERTCHAIN_SLOT_1; + return get_root_certificate_from_chain(chain_index, base_hash_algo, base_asym_algo, + data, size, hash, hash_size); } bool libspdm_read_responder_public_certificate_chain_per_slot( uint8_t slot_id, uint32_t base_hash_algo, uint32_t base_asym_algo, void **data, size_t *size, void **hash, size_t *hash_size) { - return get_certificate_chain(TPM_RESP_CERT_CHAIN, base_hash_algo, base_asym_algo, data, size, hash, hash_size, + uint32_t chain_index = (slot_id == 0) ? LIBSPDM_TPM_HANDLE_RESPONDER_CERTCHAIN_SLOT_0 + : LIBSPDM_TPM_HANDLE_RESPONDER_CERTCHAIN_SLOT_1; + return get_certificate_chain(chain_index, base_hash_algo, base_asym_algo, data, size, hash, hash_size, false, true); } diff --git a/os_stub/spdm_device_secret_lib_tpm/sign.c b/os_stub/spdm_device_secret_lib_tpm/sign.c index dc7b0920802..ae68744956a 100644 --- a/os_stub/spdm_device_secret_lib_tpm/sign.c +++ b/os_stub/spdm_device_secret_lib_tpm/sign.c @@ -36,7 +36,7 @@ bool libspdm_requester_data_sign( LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Loading TPM device")); libspdm_tpm_device_init(); - result = libspdm_tpm_get_pvt_key_handle(TPM_REQU_HANDLE, &context); + result = libspdm_tpm_get_pvt_key_handle(LIBSPDM_TPM_HANDLE_REQUESTER_HANDLE_SLOT_0, &context); if (!result){ LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR, "Failed to load requester handle")); return false; @@ -70,7 +70,7 @@ bool libspdm_responder_data_sign( bool result = false; libspdm_tpm_device_init(); - result = libspdm_tpm_get_pvt_key_handle(TPM_RESP_HANDLE, &context); + result = libspdm_tpm_get_pvt_key_handle(LIBSPDM_TPM_HANDLE_RESPONDER_HANDLE_SLOT_0, &context); if (!result){ LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR, "Failed to load responder handle")); return false;