Skip to content

Commit 42d062e

Browse files
committed
Added TPM support
Signed-off-by: Manjeet Singh <[email protected]>
1 parent 5bb9df0 commit 42d062e

File tree

52 files changed

+4196
-263
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+4196
-263
lines changed

CMakeLists.txt

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ set(GCOV ${GCOV} CACHE STRING "Choose the target of Gcov: ON OFF, and default i
3636
set(STACK_USAGE ${STACK_USAGE} CACHE STRING "Choose the target of STACK_USAGE: ON OFF, and default is OFF" FORCE)
3737
set(BUILD_LINUX_SHARED_LIB ${BUILD_LINUX_SHARED_LIB} CACHE STRING "Choose if libspdm shared library should be built for linux: ON OFF, and default is OFF" FORCE)
3838
set(X509_IGNORE_CRITICAL ${X509_IGNORE_CRITICAL} CACHE STRING "Choose if libspdm-provided cryptography libraries (OpenSSL and MbedTLS) ignore unsupported critical extensions in certificates : ON OFF, and default is OFF" FORCE)
39+
set(DEVICE ${DEVICE} CACHE STRING "Choose the test device: sample tpm, and default is sample" FORCE)
3940

4041
if(NOT GCOV)
4142
set(GCOV "OFF")
@@ -53,6 +54,11 @@ if(NOT X509_IGNORE_CRITICAL)
5354
set(X509_IGNORE_CRITICAL "OFF")
5455
endif()
5556

57+
if (NOT DEVICE)
58+
set(DEVICE "sample")
59+
endif()
60+
61+
5662
set(LIBSPDM_DIR ${PROJECT_SOURCE_DIR})
5763

5864
#
@@ -62,6 +68,7 @@ set(COMPILED_LIBCRYPTO_PATH ${COMPILED_LIBCRYPTO_PATH} CACHE STRING "Optionally
6268
set(COMPILED_LIBSSL_PATH ${COMPILED_LIBSSL_PATH} CACHE STRING "Optionally provide a path to libssl" FORCE)
6369

6470
message("CMAKE_GENERATOR = ${CMAKE_GENERATOR}")
71+
message("DEVICE = ${DEVICE}")
6572

6673
if(ARCH STREQUAL "x64")
6774
message("ARCH = x64")
@@ -981,7 +988,7 @@ if(ENABLE_CODEQL STREQUAL "ON")
981988
add_subdirectory(os_stub/platform_lib)
982989
add_subdirectory(os_stub/platform_lib_null)
983990
add_subdirectory(os_stub/malloclib)
984-
add_subdirectory(os_stub/spdm_device_secret_lib_sample)
991+
add_subdirectory(os_stub/spdm_device_secret_lib_${DEVICE})
985992
add_subdirectory(os_stub/spdm_device_secret_lib_null)
986993
add_subdirectory(os_stub/spdm_cert_verify_callback_sample)
987994
add_subdirectory(os_stub/cryptlib_null)
@@ -1020,7 +1027,7 @@ else()
10201027
add_subdirectory(os_stub/platform_lib)
10211028
add_subdirectory(os_stub/platform_lib_null)
10221029
add_subdirectory(os_stub/malloclib)
1023-
add_subdirectory(os_stub/spdm_device_secret_lib_sample)
1030+
add_subdirectory(os_stub/spdm_device_secret_lib_${DEVICE})
10241031
add_subdirectory(os_stub/spdm_device_secret_lib_null)
10251032
add_subdirectory(os_stub/spdm_cert_verify_callback_sample)
10261033

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/**
2+
* Copyright Notice:
3+
* Copyright 2021-2026 DMTF. All rights reserved.
4+
* License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
5+
**/
6+
7+
#ifndef __CRYPTLIB_TPM_H__
8+
#define __CRYPTLIB_TPM_H__
9+
10+
#include <stdbool.h>
11+
12+
bool libspdm_tpm_device_init();
13+
14+
bool libspdm_tpm_get_private_key(void *handle, void **context);
15+
16+
bool libspdm_tpm_get_public_key(void *handle, void **context);
17+
18+
bool libspdm_tpm_get_certificate(void *handle, void **context);
19+
20+
bool libspdm_tpm_dump_certificate(void *context, void **buffer, size_t *size);
21+
22+
bool libspdm_tpm_read_pcr(uint32_t hash_algo, uint32_t index, void *buffer, size_t *size);
23+
24+
#endif

os_stub/cryptlib_openssl/CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,10 @@ target_sources(cryptlib_openssl
4848
target_compile_options(cryptlib_openssl PRIVATE ${OPENSSL_FLAGS})
4949

5050
target_link_libraries(cryptlib_openssl PUBLIC openssllib memlib)
51+
52+
if (${DEVICE} STREQUAL "tpm")
53+
target_sources(cryptlib_openssl PRIVATE
54+
tpm/tpm.c
55+
)
56+
target_link_libraries(cryptlib_openssl PUBLIC tss2-esys tss2-tctildr)
57+
endif()

os_stub/cryptlib_openssl/pk/x509.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2036,7 +2036,6 @@ bool libspdm_x509_verify_cert_chain(const uint8_t *root_cert, size_t root_cert_l
20362036

20372037

20382038
/* Verify current_cert with preceding cert;*/
2039-
20402039
verify_flag =
20412040
libspdm_x509_verify_cert(current_cert, current_cert_len,
20422041
preceding_cert, preceding_cert_len);
@@ -2458,6 +2457,7 @@ bool libspdm_gen_x509_csr_with_pqc(
24582457
X509_NAME *x509_name;
24592458
EVP_PKEY *private_key;
24602459
EVP_PKEY *public_key;
2460+
bool owned_keys = false;
24612461
EVP_MD *md;
24622462
uint8_t *csr_p;
24632463
STACK_OF(X509_EXTENSION) *exts;
@@ -2536,11 +2536,13 @@ bool libspdm_gen_x509_csr_with_pqc(
25362536
EVP_PKEY_free(private_key);
25372537
EVP_PKEY_free(public_key);
25382538

2539-
private_key = EVP_PKEY_dup(ec_pkey);
2540-
public_key = EVP_PKEY_dup(ec_pkey);
2539+
// Can't DUP hardware backed keys
2540+
private_key = ec_pkey;
2541+
public_key = ec_pkey;
25412542
if (private_key == NULL || public_key == NULL) {
25422543
goto free_all;
25432544
}
2545+
owned_keys = true;
25442546
break;
25452547
}
25462548
case LIBSPDM_CRYPTO_NID_SM2_DSA_P256: {
@@ -2763,8 +2765,10 @@ bool libspdm_gen_x509_csr_with_pqc(
27632765
EVP_MD_free((EVP_MD *)md);
27642766
}
27652767
X509_REQ_free(x509_req);
2766-
EVP_PKEY_free(private_key);
2767-
EVP_PKEY_free(public_key);
2768+
if (!owned_keys) {
2769+
EVP_PKEY_free(private_key);
2770+
EVP_PKEY_free(public_key);
2771+
}
27682772

27692773
return (ret != 0);
27702774
}

os_stub/cryptlib_openssl/tpm/tpm.c

Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
/**
2+
* Copyright Notice:
3+
* Copyright 2021-2025 DMTF. All rights reserved.
4+
* License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
5+
**/
6+
7+
#include <complex.h>
8+
#include <openssl/err.h>
9+
#include <tss2/tss2_common.h>
10+
#include <tss2/tss2_esys.h>
11+
#include <tss2/tss2_tctildr.h>
12+
13+
#include <openssl/provider.h>
14+
#include <openssl/store.h>
15+
#include <tss2/tss2_tcti.h>
16+
#include <tss2/tss2_tpm2_types.h>
17+
#include "library/cryptlib/cryptlib_tpm.h"
18+
#include "internal/libspdm_crypt_lib.h"
19+
20+
#include "key_context.h"
21+
22+
bool g_tpm_device_initialized = false;
23+
24+
static libspdm_key_context *create_key_context(EVP_PKEY *pkey)
25+
{
26+
libspdm_key_context *context = (libspdm_key_context *)malloc(sizeof(libspdm_key_context));
27+
context->evp_pkey = pkey;
28+
return context;
29+
}
30+
31+
bool libspdm_tpm_device_init()
32+
{
33+
OSSL_PROVIDER *tpm_provider = NULL;
34+
35+
if (g_tpm_device_initialized)
36+
return true;
37+
38+
tpm_provider = OSSL_PROVIDER_load(NULL, "tpm2");
39+
if (tpm_provider == NULL)
40+
{
41+
LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR, "failed to load tpm2\n"));
42+
return false;
43+
}
44+
45+
OSSL_PROVIDER_load(NULL, "default");
46+
OSSL_PROVIDER_load(NULL, "legacy");
47+
48+
g_tpm_device_initialized = true;
49+
return true;
50+
}
51+
52+
static bool get_keyinfo(const char *handle, void **context, int keyinfo_type)
53+
{
54+
OSSL_STORE_CTX *store_ctx = NULL;
55+
OSSL_STORE_INFO *info = NULL;
56+
57+
/* handle must look like: "tpm2tss:0x81010002" */
58+
store_ctx = OSSL_STORE_open_ex(handle, NULL, "provider=tpm2", NULL, NULL, NULL, NULL, NULL);
59+
if (!store_ctx)
60+
{
61+
return false;
62+
}
63+
64+
while ((info = OSSL_STORE_load(store_ctx)) != NULL)
65+
{
66+
if (OSSL_STORE_INFO_get_type(info) == keyinfo_type)
67+
{
68+
switch (keyinfo_type)
69+
{
70+
case OSSL_STORE_INFO_PKEY:
71+
*context = OSSL_STORE_INFO_get1_PKEY(info);
72+
break;
73+
case OSSL_STORE_INFO_PUBKEY:
74+
*context = OSSL_STORE_INFO_get1_PUBKEY(info);
75+
break;
76+
case OSSL_STORE_INFO_CERT:
77+
*context = OSSL_STORE_INFO_get1_CERT(info);
78+
break;
79+
}
80+
break;
81+
}
82+
OSSL_STORE_INFO_free(info);
83+
}
84+
85+
OSSL_STORE_close(store_ctx);
86+
87+
if (*context == NULL)
88+
{
89+
LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR, "no keyinfo %d foun on handle %s\n", keyinfo_type, handle));
90+
return false;
91+
}
92+
93+
return true;
94+
}
95+
96+
bool libspdm_tpm_get_private_key(void *handle, void **context)
97+
{
98+
EVP_PKEY *pkey = NULL;
99+
if (!get_keyinfo((const char *)handle, (void **)&pkey, OSSL_STORE_INFO_PKEY))
100+
{
101+
return false;
102+
}
103+
*context = create_key_context(pkey);
104+
return true;
105+
}
106+
107+
bool libspdm_tpm_get_public_key(void *handle, void **context)
108+
{
109+
EVP_PKEY *pkey = NULL;
110+
if (!get_keyinfo((const char *)handle, (void **)&pkey, OSSL_STORE_INFO_PUBKEY))
111+
{
112+
return false;
113+
}
114+
*context = create_key_context(pkey);
115+
return true;
116+
}
117+
118+
bool libspdm_tpm_get_certificate(void *handle, void **context)
119+
{
120+
return get_keyinfo((const char *)handle, context, OSSL_STORE_INFO_CERT);
121+
}
122+
123+
bool libspdm_tpm_dump_certificate(void *context, void **buffer, size_t *size)
124+
{
125+
int len = 0;
126+
len = i2d_X509((X509 *)context, NULL);
127+
if (len < 0)
128+
return false;
129+
130+
void *cert = OPENSSL_malloc(len);
131+
if (cert == NULL)
132+
{
133+
return false;
134+
}
135+
*buffer = cert;
136+
len = i2d_X509((X509 *)context, (unsigned char **)&cert);
137+
if (len < 0)
138+
{
139+
free(*buffer);
140+
*buffer = NULL;
141+
return false;
142+
}
143+
*size = len;
144+
return true;
145+
}
146+
147+
bool libspdm_tpm_read_pcr(uint32_t hash_algo, uint32_t index, void *buffer, size_t *size)
148+
{
149+
TSS2_RC result;
150+
TSS2_TCTI_CONTEXT *tcti_context = NULL;
151+
ESYS_CONTEXT *context = NULL;
152+
153+
TPML_PCR_SELECTION sel = {
154+
.count = 1,
155+
.pcrSelections = {
156+
{
157+
.sizeofSelect = 3,
158+
.pcrSelect = {0x00, 0x00, 0x00, 0x00},
159+
},
160+
}};
161+
162+
*size = 0;
163+
switch (hash_algo)
164+
{
165+
case SPDM_ALGORITHMS_MEASUREMENT_HASH_ALGO_TPM_ALG_SHA_256:
166+
case SPDM_ALGORITHMS_MEASUREMENT_HASH_ALGO_TPM_ALG_SHA3_256:
167+
case SPDM_ALGORITHMS_MEASUREMENT_HASH_ALGO_TPM_ALG_SM3_256:
168+
sel.pcrSelections[0].hash = TPM2_ALG_SHA256;
169+
*size = 32;
170+
break;
171+
case SPDM_ALGORITHMS_MEASUREMENT_HASH_ALGO_TPM_ALG_SHA_384:
172+
case SPDM_ALGORITHMS_MEASUREMENT_HASH_ALGO_TPM_ALG_SHA3_384:
173+
sel.pcrSelections[0].hash = TPM2_ALG_SHA384;
174+
*size = 48;
175+
break;
176+
case SPDM_ALGORITHMS_MEASUREMENT_HASH_ALGO_TPM_ALG_SHA_512:
177+
case SPDM_ALGORITHMS_MEASUREMENT_HASH_ALGO_TPM_ALG_SHA3_512:
178+
sel.pcrSelections[0].hash = TPM2_ALG_SHA512;
179+
*size = 64;
180+
break;
181+
default:
182+
LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR, "unsupported measurement hash algo %d\n", hash_algo));
183+
return false;
184+
}
185+
sel.pcrSelections[0].pcrSelect[(index - 1) / 8] |= 1 << ((index - 1) % 8);
186+
187+
UINT32 uc;
188+
TPML_PCR_SELECTION *out = NULL;
189+
TPML_DIGEST *values = NULL;
190+
191+
const char *tssconf = getenv("TPM2TOOLS_TCTI");
192+
if ((result = Tss2_TctiLdr_Initialize(tssconf, &tcti_context)) != TSS2_RC_SUCCESS)
193+
{
194+
goto finish;
195+
}
196+
197+
// TODO: abi version check
198+
if ((result = Esys_Initialize(&context, tcti_context, NULL)) != TSS2_RC_SUCCESS)
199+
{
200+
goto cleanup_tcti;
201+
}
202+
203+
if ((result = Esys_PCR_Read(context, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, &sel, &uc, &out, &values)) != TSS2_RC_SUCCESS)
204+
{
205+
goto cleanup_esys;
206+
}
207+
208+
memcpy(buffer, values->digests[0].buffer, *size);
209+
210+
cleanup_esys:
211+
Esys_Finalize(&context);
212+
213+
cleanup_tcti:
214+
Tss2_TctiLdr_Finalize(&tcti_context);
215+
216+
finish:
217+
return result == TSS2_RC_SUCCESS;
218+
}

0 commit comments

Comments
 (0)