From f40a9d7ca93a25cbdcfc6f6ce3040ee7955123bb Mon Sep 17 00:00:00 2001 From: Wenxing Hou Date: Fri, 10 May 2024 09:41:50 +0800 Subject: [PATCH] Add verify cert callback function for DiceTcbInfo. Refer the spec https://trustedcomputinggroup.org/resource/dice-attestation-architecture/ add verify cert callback function for Cert extentison DiceTcbInfo check. Signed-off-by: Wenxing Hou --- CMakeLists.txt | 3 + .../CMakeLists.txt | 17 + .../README.md | 37 +++ .../spdm_cert_verify_callback.c | 295 ++++++++++++++++++ .../spdm_cert_verify_callback_internal.h | 48 +++ unit_test/test_spdm_sample/CMakeLists.txt | 60 ++++ unit_test/test_spdm_sample/test_spdm_sample.c | 140 +++++++++ 7 files changed, 600 insertions(+) create mode 100644 os_stub/spdm_cert_verify_callback_sample/CMakeLists.txt create mode 100644 os_stub/spdm_cert_verify_callback_sample/README.md create mode 100644 os_stub/spdm_cert_verify_callback_sample/spdm_cert_verify_callback.c create mode 100644 os_stub/spdm_cert_verify_callback_sample/spdm_cert_verify_callback_internal.h create mode 100644 unit_test/test_spdm_sample/CMakeLists.txt create mode 100644 unit_test/test_spdm_sample/test_spdm_sample.c diff --git a/CMakeLists.txt b/CMakeLists.txt index f85a8c4317b..1bcd187ddd0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -900,6 +900,7 @@ if(ENABLE_CODEQL STREQUAL "ON") ADD_SUBDIRECTORY(os_stub/malloclib) ADD_SUBDIRECTORY(os_stub/spdm_device_secret_lib_sample) ADD_SUBDIRECTORY(os_stub/spdm_device_secret_lib_null) + ADD_SUBDIRECTORY(os_stub/spdm_cert_verify_callback_sample) ADD_SUBDIRECTORY(os_stub/cryptlib_null) ADD_SUBDIRECTORY(os_stub/cryptlib_mbedtls) ADD_SUBDIRECTORY(os_stub/cryptlib_openssl) @@ -936,6 +937,7 @@ else() ADD_SUBDIRECTORY(os_stub/malloclib) ADD_SUBDIRECTORY(os_stub/spdm_device_secret_lib_sample) ADD_SUBDIRECTORY(os_stub/spdm_device_secret_lib_null) + ADD_SUBDIRECTORY(os_stub/spdm_cert_verify_callback_sample) if(NOT DISABLE_TESTS STREQUAL "1") ADD_SUBDIRECTORY(unit_test/spdm_transport_test_lib) @@ -952,6 +954,7 @@ else() ADD_SUBDIRECTORY(unit_test/test_spdm_crypt) ADD_SUBDIRECTORY(unit_test/test_spdm_fips) ADD_SUBDIRECTORY(unit_test/test_spdm_secured_message) + ADD_SUBDIRECTORY(unit_test/test_spdm_sample) endif() if((NOT TOOLCHAIN STREQUAL "ARM_DS2022") AND (NOT TOOLCHAIN STREQUAL "RISCV_XPACK")) diff --git a/os_stub/spdm_cert_verify_callback_sample/CMakeLists.txt b/os_stub/spdm_cert_verify_callback_sample/CMakeLists.txt new file mode 100644 index 00000000000..2798866f6b1 --- /dev/null +++ b/os_stub/spdm_cert_verify_callback_sample/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 2.8.12) + +INCLUDE_DIRECTORIES(${LIBSPDM_DIR}/os_stub/spdm_cert_verify_callback_sample + ${LIBSPDM_DIR}/include + ${LIBSPDM_DIR}/include/hal + ${LIBSPDM_DIR}/os_stub +) + +SET(src_spdm_cert_verify_callback_sample + spdm_cert_verify_callback.c +) + +if ((ARCH STREQUAL "arm") OR (ARCH STREQUAL "aarch64")) + ADD_COMPILE_OPTIONS(-DLIBSPDM_CPU_ARM) +endif() + +ADD_LIBRARY(spdm_cert_verify_callback_sample STATIC ${src_spdm_cert_verify_callback_sample}) diff --git a/os_stub/spdm_cert_verify_callback_sample/README.md b/os_stub/spdm_cert_verify_callback_sample/README.md new file mode 100644 index 00000000000..fdc860eba82 --- /dev/null +++ b/os_stub/spdm_cert_verify_callback_sample/README.md @@ -0,0 +1,37 @@ +## This is reference implementation to verify CertChain DiceTcbInfo extension. + +### DiceTcbInfo extension Spec +[DICE Attestation Architecture](https://trustedcomputinggroup.org/wp-content/uploads/DICE-Attestation-Architecture-Version-1.1-Revision-18_pub.pdf) + +### Implementation Assumption + 1) **Reference TcbInfo.** + + - Only one reference TcbInfo entry is provided by the integrator. (Multiple reference TcbInfo is NOT supported in this Implementation.) + 2) **Reported TcbInfo** + + - The number of reported TcbInfo must match the number of reference TcbInfo. + 3) **TcbInfo Matching** + + - Each of the reported TcbInfo must fully match each of the reference TcbInfo with same order. + 4) **TcbInfo Field** + + - The reported TcbInfo must include all fields in the reference TcbInfo. If a field in the reference TcbInfo does not exist in the reported TcbInfo, the verification must fail. + - The reported TcbInfo could include more fields which do not exist in the reference TcbInfo. The extra fields in the reported TcbInfo must be ignored and NOT validated, and they must not impact the final result. + + +### Note + 1) To verify the CertChain DiceTcbInfo extension, please use the following command to build. + ``` + cmake -G"NMake Makefiles" -DARCH=x64 -DTOOLCHAIN=VS2019 -DTARGET=Debug -DCRYPTO=openssl -DX509_IGNORE_CRITICAL=ON .. + ``` + + ``` + cmake -G"NMake Makefiles" -DARCH=x64 -DTOOLCHAIN=VS2019 -DTARGET=Release -DCRYPTO=openssl -DX509_IGNORE_CRITICAL=ON .. + ``` + ``` + cmake -G"NMake Makefiles" -DARCH=x64 -DTOOLCHAIN=VS2019 -DTARGET=Debug -DCRYPTO=mbedtls -DX509_IGNORE_CRITICAL=ON .. + ``` + + ``` + cmake -G"NMake Makefiles" -DARCH=x64 -DTOOLCHAIN=VS2019 -DTARGET=Release -DCRYPTO=mbedtls -DX509_IGNORE_CRITICAL=ON .. + ``` diff --git a/os_stub/spdm_cert_verify_callback_sample/spdm_cert_verify_callback.c b/os_stub/spdm_cert_verify_callback_sample/spdm_cert_verify_callback.c new file mode 100644 index 00000000000..0f66fdc51c0 --- /dev/null +++ b/os_stub/spdm_cert_verify_callback_sample/spdm_cert_verify_callback.c @@ -0,0 +1,295 @@ +/** + * Copyright Notice: + * Copyright 2024 DMTF. All rights reserved. + * License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md + **/ + +#include +#include "spdm_cert_verify_callback_internal.h" + +/** + * tcg-dice-TcbInfo OID: 2.23.133.5.4.1 + * https://trustedcomputinggroup.org/wp-content/uploads/DICE-Attestation-Architecture-Version-1.1-Revision-18_pub.pdf + **/ +uint8_t m_libspdm_tcg_dice_tcbinfo_oid[] = {0x67, 0x81, 0x05, 0x05, 0x04, 0x01}; + +/*the cert chain must have a or more cert with DiceTcbInfo extension*/ +bool m_libspdm_must_have_dice_tcb_info = true; + +/*the reference cert number with DiceTcbinfo in the cert chain*/ +uint8_t m_libspdm_dice_tcb_info_number = 1; + +/*reference DiceTcbinfo*/ + +/*vendor: INTC*/ +uint8_t m_libspdm_dice_tcbinfo_vendor[] = {0x49, 0x4E, 0x54, 0x43}; +/*model: S3M GNR*/ +uint8_t m_libspdm_dice_tcbinfo_model[] = {0x53, 0x33, 0x4D, 0x20, 0x47, 0x4E, 0x52}; +/*version: 000200000000008B*/ +uint8_t m_libspdm_dice_tcbinfo_version[] = {0x30, 0x30, 0x30, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x38, 0x42}; +/*svn*/ +uint8_t m_libspdm_dice_tcbinfo_svn[] = {0x01}; +/*layer*/ +uint8_t m_libspdm_dice_tcbinfo_layer[] = {0x01}; +/*fwids*/ +uint8_t m_libspdm_dice_tcbinfo_fwids[] = {0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, + 0x02, 0x02, 0x04, 0x30, 0x6B, 0x44, 0x7B, 0x5E, 0x99, + 0x21, 0x0A, 0x58, 0x8A, 0x7B, 0x31, 0x7D, 0xBA, 0x2D, + 0x4A, 0x7F, 0x75, 0xE6, 0x97, 0xF2, 0x07, 0xE0, 0xC2, + 0x99, 0x78, 0xF3, 0xF6, 0x2B, 0x53, 0xF5, 0xBE, 0xEB, + 0x73, 0xF0, 0x37, 0xB8, 0x79, 0xC1, 0xFF, 0x76, 0x2A, + 0x3A, 0x39, 0xCA, 0xE2, 0x8C, 0xF0, 0x56}; +/*type*/ +uint8_t m_libspdm_dice_tcbinfo_type[] = {0x46, 0x69, 0x72, 0x6D, 0x77, 0x61, 0x72, 0x65, 0x20, + 0x44, 0x69, 0x67, 0x65, 0x73, 0x74}; + +/*verify cert DiceTcbInfo extension*/ +bool libspdm_verify_cert_dicetcbinfo(const void *cert, size_t cert_size, + size_t *spdm_get_dice_tcb_info_size) { + bool result; + uint8_t spdm_dice_tcb_info[256]; + size_t spdm_dice_tcb_info_size; + uint8_t *ptr; + int32_t length; + size_t obj_len; + uint8_t *end; + + spdm_dice_tcb_info_size = 256; + *spdm_get_dice_tcb_info_size = 0; + result = libspdm_x509_get_extension_data(cert, cert_size, + m_libspdm_tcg_dice_tcbinfo_oid, + sizeof(m_libspdm_tcg_dice_tcbinfo_oid), + spdm_dice_tcb_info, &spdm_dice_tcb_info_size); + if (!result) { + return false; + } else if (spdm_dice_tcb_info_size == 0) { + return true; + } + + *spdm_get_dice_tcb_info_size = spdm_dice_tcb_info_size; + length = (int32_t)spdm_dice_tcb_info_size; + ptr = (uint8_t*)(size_t)spdm_dice_tcb_info; + obj_len = 0; + end = ptr + length; + + /*get DiceTcbInfo*/ + result = libspdm_asn1_get_tag(&ptr, end, &obj_len, + LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED); + if (!result) { + *spdm_get_dice_tcb_info_size = 0; + return false; + } + result = libspdm_asn1_get_tag(&ptr, end, &obj_len, + LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED); + if (!result) { + *spdm_get_dice_tcb_info_size = 0; + return false; + } + + /*vendor*/ + result = libspdm_asn1_get_tag(&ptr, end, &obj_len, + LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC); + if (result) { + if ((obj_len != sizeof(m_libspdm_dice_tcbinfo_vendor)) || + (!libspdm_consttime_is_mem_equal(ptr, m_libspdm_dice_tcbinfo_vendor, obj_len))) { + return false; + } + ptr += obj_len; + } else { + return false; + } + /*model*/ + result = libspdm_asn1_get_tag(&ptr, end, &obj_len, + LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC + 1); + if (result) { + if ((obj_len != sizeof(m_libspdm_dice_tcbinfo_model)) || + (!libspdm_consttime_is_mem_equal(ptr, m_libspdm_dice_tcbinfo_model, obj_len))) { + return false; + } + ptr += obj_len; + } else { + return false; + } + /*version*/ + result = libspdm_asn1_get_tag(&ptr, end, &obj_len, + LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC + 2); + if (result) { + if ((obj_len != sizeof(m_libspdm_dice_tcbinfo_version)) || + (!libspdm_consttime_is_mem_equal(ptr, m_libspdm_dice_tcbinfo_version, obj_len))) { + return false; + } + ptr += obj_len; + } else { + return false; + } + /*svn*/ + result = libspdm_asn1_get_tag(&ptr, end, &obj_len, + LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC + 3); + if (result) { + if ((obj_len != sizeof(m_libspdm_dice_tcbinfo_svn)) || + (!libspdm_consttime_is_mem_equal(ptr, m_libspdm_dice_tcbinfo_svn, obj_len))) { + return false; + } + ptr += obj_len; + } else { + return false; + } + /*layer*/ + result = libspdm_asn1_get_tag(&ptr, end, &obj_len, + LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC + 4); + if (result) { + if ((obj_len != sizeof(m_libspdm_dice_tcbinfo_layer)) || + (!libspdm_consttime_is_mem_equal(ptr, m_libspdm_dice_tcbinfo_layer, obj_len))) { + return false; + } + ptr += obj_len; + } + /*index*/ + result = libspdm_asn1_get_tag(&ptr, end, &obj_len, + LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC + 5); + if (result) { + ptr += obj_len; + } + /*fwids*/ + result = libspdm_asn1_get_tag(&ptr, end, &obj_len, + (LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC | + LIBSPDM_CRYPTO_ASN1_CONSTRUCTED) + 6); + if (result) { + if ((obj_len != sizeof(m_libspdm_dice_tcbinfo_fwids)) || + (!libspdm_consttime_is_mem_equal(ptr, m_libspdm_dice_tcbinfo_fwids, obj_len))) { + return false; + } + ptr += obj_len; + } else { + return false; + } + /*flags*/ + result = libspdm_asn1_get_tag(&ptr, end, &obj_len, + LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC + 7); + if (result) { + ptr += obj_len; + } + /*vendorInfo*/ + result = libspdm_asn1_get_tag(&ptr, end, &obj_len, + LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC + 8); + if (result) { + ptr += obj_len; + } + /*type*/ + result = libspdm_asn1_get_tag(&ptr, end, &obj_len, + LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC + 9); + if (result) { + if ((obj_len != sizeof(m_libspdm_dice_tcbinfo_type)) || + (!libspdm_consttime_is_mem_equal(ptr, m_libspdm_dice_tcbinfo_type, obj_len))) { + return false; + } + ptr += obj_len; + } else { + return false; + } + /*flagMask*/ + result = libspdm_asn1_get_tag(&ptr, end, &obj_len, + LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC + 10); + if (result) { + ptr += obj_len; + } + + if (ptr == end) { + return true; + } else { + return false; + } +} + +/*callback function for verifying cert_chain DiceTcbInfo extension*/ +bool libspdm_verify_spdm_cert_chain_with_dice(void *spdm_context, uint8_t slot_id, + size_t cert_chain_size, const void *cert_chain, + const void **trust_anchor, + size_t *trust_anchor_size) +{ + bool result; + libspdm_context_t *context; + const uint8_t *cert_chain_data; + size_t cert_chain_data_size; + size_t hash_size; + uint8_t *ptr; + uint8_t *tem_ptr; + int32_t length; + size_t obj_len; + uint8_t *end; + size_t cert_dice_tcb_info_size; + bool cert_chain_have_matched_dice; + uint8_t number_dice_tcb_info; + + /*verify peer cert chain integrity*/ + result = libspdm_verify_peer_cert_chain_buffer_integrity(spdm_context, cert_chain, + cert_chain_size); + if (!result) { + return false; + } + + /*verify peer cert chain authority*/ + result = libspdm_verify_peer_cert_chain_buffer_authority(spdm_context, cert_chain, + cert_chain_size, trust_anchor, + trust_anchor_size); + if (!result) { + return false; + } + + context = spdm_context; + hash_size = libspdm_get_hash_size(context->connection_info.algorithm.base_hash_algo); + + cert_chain_data = (const uint8_t *)cert_chain + sizeof(spdm_cert_chain_t) + hash_size; + cert_chain_data_size = cert_chain_size - sizeof(spdm_cert_chain_t) - hash_size; + + length = (int32_t)cert_chain_data_size; + ptr = (uint8_t*)(size_t)cert_chain_data; + obj_len = 0; + end = ptr + length; + cert_chain_have_matched_dice = false; + number_dice_tcb_info = 0; + + while (ptr < end) { + cert_dice_tcb_info_size = 0; + tem_ptr = ptr; + result = libspdm_asn1_get_tag(&ptr, end, &obj_len, + LIBSPDM_CRYPTO_ASN1_SEQUENCE | + LIBSPDM_CRYPTO_ASN1_CONSTRUCTED); + if (result) { + /*verify Dice TCB info*/ + result = libspdm_verify_cert_dicetcbinfo(tem_ptr, obj_len + (ptr - tem_ptr), + &cert_dice_tcb_info_size); + if (!result) { + if (cert_dice_tcb_info_size == 0) { + return false; + } + number_dice_tcb_info++; + } else { + if (cert_dice_tcb_info_size != 0) { + cert_chain_have_matched_dice = true; + number_dice_tcb_info++; + } + } + /* Move to next cert*/ + ptr += obj_len; + } else { + return false; + } + } + + if (m_libspdm_must_have_dice_tcb_info && !cert_chain_have_matched_dice) { + return false; + } + + /*check the number of cert with DiceTcbinfo in cert chain*/ + if (number_dice_tcb_info != m_libspdm_dice_tcb_info_number) { + return false; + } + + if (ptr == end) { + return true; + } else { + return false; + } +} diff --git a/os_stub/spdm_cert_verify_callback_sample/spdm_cert_verify_callback_internal.h b/os_stub/spdm_cert_verify_callback_sample/spdm_cert_verify_callback_internal.h new file mode 100644 index 00000000000..633679a664d --- /dev/null +++ b/os_stub/spdm_cert_verify_callback_sample/spdm_cert_verify_callback_internal.h @@ -0,0 +1,48 @@ +/** + * Copyright Notice: + * Copyright 2024 DMTF. All rights reserved. + * License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md + **/ + +#ifndef SPDM_CERT_VERIFY_CALLBACK_INTERNAL_H +#define SPDM_CERT_VERIFY_CALLBACK_INTERNAL_H + +#include "internal/libspdm_common_lib.h" + +/** + * The callback function for verifying cert_chain DiceTcbInfo extension. + * + * @param spdm_context A pointer to the SPDM context. + * @param slot_id The number of slot for the certificate chain. + * This params is not uesed, just for compatible in this function. + * @param cert_chain_size size in bytes of the certificate chain buffer. + * @param cert_chain Certificate chain buffer including spdm_cert_chain_t header. + * @param trust_anchor A buffer to hold the trust_anchor which is used to validate the peer certificate, if not NULL. + * @param trust_anchor_size A buffer to hold the trust_anchor_size, if not NULL. + * + * @retval true The certificate chain buffer DiceTcbInfo extension verification passed. + * @retval false The certificate chain buffer DiceTcbInfo extension verification failed. + **/ +bool libspdm_verify_spdm_cert_chain_with_dice(void *spdm_context, uint8_t slot_id, + size_t cert_chain_size, const void *cert_chain, + const void **trust_anchor, + size_t *trust_anchor_size); + +/** + * verify cert DiceTcbInfo extension. + * + * @param[in] cert Pointer to the DER-encoded X509 certificate. + * @param[in] cert_size Size of the X509 certificate in bytes. + * @param[in, out] spdm_get_dice_tcb_info_size DiceTcbInfo Extension bytes size. + * + * @retval true If the returned spdm_get_dice_tcb_info_size == 0, it means that cert is valid, but cert doesn't have DiceTcbInfo extension; + * If the returned spdm_get_dice_tcb_info_size != 0, it means that cert is valid, and the DiceTcbInfo extension is found; + * And the cert DiceTcbInfo extension includes all fields in the reference TcbInfo. + * @retval false If the returned spdm_get_dice_tcb_info_size == 0, it means that cert are invalid; + * If the returned spdm_get_dice_tcb_info_size != 0, it means that cert is valid, and the DiceTcbInfo extension is found; + * But the cert DiceTcbInfo extension doesn't include all fields in the reference TcbInfo. + **/ +bool libspdm_verify_cert_dicetcbinfo(const void *cert, size_t cert_size, + size_t *spdm_get_dice_tcb_info_size); + +#endif diff --git a/unit_test/test_spdm_sample/CMakeLists.txt b/unit_test/test_spdm_sample/CMakeLists.txt new file mode 100644 index 00000000000..89d7464c852 --- /dev/null +++ b/unit_test/test_spdm_sample/CMakeLists.txt @@ -0,0 +1,60 @@ +cmake_minimum_required(VERSION 2.8.12) + +INCLUDE_DIRECTORIES(${LIBSPDM_DIR}/include + ${LIBSPDM_DIR}/unit_test/include + ${LIBSPDM_DIR}/os_stub/spdm_device_secret_lib_sample + ${LIBSPDM_DIR}/os_stub/spdm_cert_verify_callback_sample + ${LIBSPDM_DIR}/unit_test/cmockalib/cmocka/include + ${LIBSPDM_DIR}/unit_test/cmockalib/cmocka/include/cmockery + ${LIBSPDM_DIR}/unit_test/spdm_unit_test_common + ${LIBSPDM_DIR}/os_stub/include + ${LIBSPDM_DIR}/os_stub +) + +if(CMAKE_SYSTEM_NAME MATCHES "Windows") + if((TOOLCHAIN STREQUAL "VS2015") OR (TOOLCHAIN STREQUAL "VS2019") OR (TOOLCHAIN STREQUAL "VS2022")) + ADD_COMPILE_OPTIONS(/wd4819) + endif() +endif() + +SET(src_test_spdm_sample + test_spdm_sample.c + ${LIBSPDM_DIR}/unit_test/spdm_unit_test_common/support.c + ${LIBSPDM_DIR}/unit_test/spdm_unit_test_common/algo.c +) + +SET(test_spdm_sample_LIBRARY + memlib + debuglib + spdm_crypt_lib + ${CRYPTO_LIB_PATHS} + cryptlib_${CRYPTO} + rnglib + malloclib + cmockalib + spdm_device_secret_lib_sample + spdm_cert_verify_callback_sample + spdm_crypt_ext_lib + spdm_common_lib + spdm_secured_message_lib +) + +if(TOOLCHAIN STREQUAL "ARM_DS2022") + SET(test_spdm_sample_LIBRARY ${test_spdm_sample_LIBRARY} armbuild_lib) +endif() + +if((TOOLCHAIN STREQUAL "KLEE") OR (TOOLCHAIN STREQUAL "CBMC")) + ADD_EXECUTABLE(test_spdm_sample + ${src_test_spdm_sample} + $ + $ + $ + $ + $ + $ + $ + ) +else() + ADD_EXECUTABLE(test_spdm_sample ${src_test_spdm_sample}) + TARGET_LINK_LIBRARIES(test_spdm_sample ${test_spdm_sample_LIBRARY}) +endif() diff --git a/unit_test/test_spdm_sample/test_spdm_sample.c b/unit_test/test_spdm_sample/test_spdm_sample.c new file mode 100644 index 00000000000..045e43007ee --- /dev/null +++ b/unit_test/test_spdm_sample/test_spdm_sample.c @@ -0,0 +1,140 @@ +/** + * Copyright Notice: + * Copyright 2024 DMTF. All rights reserved. + * License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md + **/ + +#define LIBSPDM_MAX_CERT_CHAIN_SIZE 0x2000 + +#include "spdm_unit_test.h" +#include "library/spdm_common_lib.h" +#include "spdm_crypt_ext_lib/spdm_crypt_ext_lib.h" +#include "spdm_cert_verify_callback_sample/spdm_cert_verify_callback_internal.h" + +/*read cert chain or root cert with dice extension*/ +bool libspdm_read_dice_certificate_chain( + void **data, size_t *size, bool is_cert_chain) +{ + bool res; + void *file_data; + size_t file_size; + char *file; + + *data = NULL; + *size = 0; + + if (is_cert_chain) { + file = "dice_cert/dice_cert_chain.bin"; + } else { + file = "dice_cert/dice_root_cert.der"; + } + + res = libspdm_read_input_file(file, &file_data, &file_size); + if (!res) { + return res; + } + + *data = file_data; + *size = file_size; + + return true; +} + +void libspdm_test_spdm_verify_cert_chain_callback_function(void **state) +{ + bool status; + libspdm_context_t *spdm_context; + uint8_t slot_id; + void *spdm_cert_chain_with_dicetcbinfo; + size_t spdm_cert_chain_size_with_dicetcbinfo; + void *spdm_root_cert_for_dicetcbinfo; + size_t spdm_root_cert_size_for_dicetcbinfo; + + spdm_context = (void *)malloc(libspdm_get_context_size()); + if (spdm_context == NULL) { + assert_true(false); + } + libspdm_init_context(spdm_context); + spdm_context->local_context.is_requester = true; + spdm_context->connection_info.algorithm.base_hash_algo = + SPDM_ALGORITHMS_BASE_HASH_ALGO_TPM_ALG_SHA_384; + spdm_context->connection_info.algorithm.base_asym_algo = + SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P384; + slot_id = 0; + + status = libspdm_read_dice_certificate_chain(&spdm_root_cert_for_dicetcbinfo, + &spdm_root_cert_size_for_dicetcbinfo, false); + assert_true(status); + spdm_context->local_context.peer_root_cert_provision_size[0] = + spdm_root_cert_size_for_dicetcbinfo; + spdm_context->local_context.peer_root_cert_provision[0] = + (uint8_t *)spdm_root_cert_for_dicetcbinfo; + + status = libspdm_read_dice_certificate_chain(&spdm_cert_chain_with_dicetcbinfo, + &spdm_cert_chain_size_with_dicetcbinfo, true); + assert_true(status); + + /*verify dice cert chain by using call back function*/ + status = libspdm_verify_spdm_cert_chain_with_dice(spdm_context, slot_id, + spdm_cert_chain_size_with_dicetcbinfo, + spdm_cert_chain_with_dicetcbinfo, NULL, NULL); + assert_true(status); + + free(spdm_root_cert_for_dicetcbinfo); + free(spdm_cert_chain_with_dicetcbinfo); + free(spdm_context); +} + +void libspdm_test_spdm_verify_cert_dicetcdinfo(void **state) +{ + bool status; + void *file_data; + size_t file_size; + char *file; + size_t cert_dice_tcb_info_size; + + file = "dice_cert/dice_cert.bin"; + cert_dice_tcb_info_size = 0; + + libspdm_read_input_file(file, &file_data, &file_size); + + /*verify dice cert*/ + status = libspdm_verify_cert_dicetcbinfo(file_data, file_size, &cert_dice_tcb_info_size); + assert_true(status); + free(file_data); +} + +int libspdm_crypt_lib_setup(void **state) +{ + return 0; +} + +int libspdm_crypt_lib_teardown(void **state) +{ + return 0; +} + +int libspdm_crypt_lib_test_main(void) +{ + const struct CMUnitTest spdm_crypt_lib_tests[] = { + cmocka_unit_test( + libspdm_test_spdm_verify_cert_chain_callback_function), + cmocka_unit_test( + libspdm_test_spdm_verify_cert_dicetcdinfo), + }; + + return cmocka_run_group_tests(spdm_crypt_lib_tests, + libspdm_crypt_lib_setup, + libspdm_crypt_lib_teardown); +} + +int main(void) +{ + int return_value = 0; + + if (libspdm_crypt_lib_test_main() != 0) { + return_value = 1; + } + + return return_value; +}