Skip to content

Commit

Permalink
Add verify cert callback function for DiceTcbInfo.
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
Wenxing-hou committed Apr 29, 2024
1 parent 828ef62 commit 89ce60a
Show file tree
Hide file tree
Showing 6 changed files with 483 additions and 0 deletions.
10 changes: 10 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ SET(CRYPTO ${CRYPTO} CACHE STRING "Choose the crypto of build: mbedtls openssl"
SET(GCOV ${GCOV} CACHE STRING "Choose the target of Gcov: ON OFF, and default is OFF" FORCE)
SET(STACK_USAGE ${STACK_USAGE} CACHE STRING "Choose the target of STACK_USAGE: ON OFF, and default is OFF" FORCE)
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)
SET(X509_IGNORE_CRITICAL ${X509_IGNORE_CRITICAL} CACHE STRING "Choose if libspdm ignore unhandled critical cert extensions : ON OFF, and default is OFF" FORCE)

if(NOT GCOV)
SET(GCOV "OFF")
Expand All @@ -32,6 +33,10 @@ if(NOT BUILD_LINUX_SHARED_LIB)
SET(BUILD_LINUX_SHARED_LIB "OFF")
endif()

if(NOT X509_IGNORE_CRITICAL)
SET(X509_IGNORE_CRITICAL "OFF")
endif()

SET(LIBSPDM_DIR ${PROJECT_SOURCE_DIR})

#
Expand Down Expand Up @@ -164,6 +169,10 @@ else()
MESSAGE(FATAL_ERROR "Unknown CRYPTO")
endif()

if ((X509_IGNORE_CRITICAL STREQUAL "ON") AND (CRYPTO STREQUAL "openssl"))
add_definitions(-DOPENSSL_IGNORE_CRITICAL=1)
endif()

if(ENABLE_BINARY_BUILD STREQUAL "1")
if(NOT CRYPTO STREQUAL "openssl")
MESSAGE(FATAL_ERROR "enabling binary build not supported for non-openssl")
Expand Down Expand Up @@ -940,6 +949,7 @@ else()
ADD_SUBDIRECTORY(unit_test/test_spdm_fips)
ADD_SUBDIRECTORY(unit_test/test_spdm_secured_message)
ADD_SUBDIRECTORY(unit_test/test_spdm_vendor_cmds)
ADD_SUBDIRECTORY(unit_test/test_spdm_callback)
endif()

if((NOT TOOLCHAIN STREQUAL "ARM_DS2022") AND (NOT TOOLCHAIN STREQUAL "RISCV_XPACK"))
Expand Down
5 changes: 5 additions & 0 deletions os_stub/cryptlib_openssl/pk/x509.c
Original file line number Diff line number Diff line change
Expand Up @@ -1879,6 +1879,11 @@ bool libspdm_x509_verify_cert(const uint8_t *cert, size_t cert_size,
*/

X509_STORE_set_flags(cert_store, X509_V_FLAG_PARTIAL_CHAIN);

#if OPENSSL_IGNORE_CRITICAL
X509_STORE_set_flags(cert_store, X509_V_FLAG_IGNORE_CRITICAL);
#endif

#ifndef OPENSSL_CHECK_TIME
X509_STORE_set_flags(cert_store, X509_V_FLAG_NO_CHECK_TIME);
#endif
Expand Down
6 changes: 6 additions & 0 deletions unit_test/spdm_unit_test_common/spdm_unit_test.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,4 +161,10 @@ typedef enum
void libspdm_force_error (libspdm_error_target_t target);
void libspdm_release_error (libspdm_error_target_t target);

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 libspdm_verify_cert_dicetcbinfo(const void *cert, size_t cert_size, size_t *spdm_get_dice_tcb_info_size);
#endif
59 changes: 59 additions & 0 deletions unit_test/test_spdm_callback/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
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}/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_callback
test_spdm_callback.c
spdm_cert_verify_callback.c
${LIBSPDM_DIR}/unit_test/spdm_unit_test_common/support.c
${LIBSPDM_DIR}/unit_test/spdm_unit_test_common/algo.c
)

SET(test_spdm_callback_LIBRARY
memlib
debuglib
spdm_crypt_lib
${CRYPTO_LIB_PATHS}
cryptlib_${CRYPTO}
rnglib
malloclib
cmockalib
spdm_device_secret_lib_sample
spdm_crypt_ext_lib
spdm_common_lib
spdm_secured_message_lib
)

if(TOOLCHAIN STREQUAL "ARM_DS2022")
SET(test_spdm_callback_LIBRARY ${test_spdm_callback_LIBRARY} armbuild_lib)
endif()

if((TOOLCHAIN STREQUAL "KLEE") OR (TOOLCHAIN STREQUAL "CBMC"))
ADD_EXECUTABLE(test_spdm_callback
${src_test_spdm_callback}
$<TARGET_OBJECTS:memlib>
$<TARGET_OBJECTS:debuglib>
$<TARGET_OBJECTS:spdm_crypt_lib>
$<TARGET_OBJECTS:${CRYPTO_LIB_PATHS}>
$<TARGET_OBJECTS:rnglib>
$<TARGET_OBJECTS:cryptlib_${CRYPTO}>
$<TARGET_OBJECTS:malloclib>
)
else()
ADD_EXECUTABLE(test_spdm_callback ${src_test_spdm_callback})
TARGET_LINK_LIBRARIES(test_spdm_callback ${test_spdm_callback_LIBRARY})
endif()
264 changes: 264 additions & 0 deletions unit_test/test_spdm_callback/spdm_cert_verify_callback.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
/**
* 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 "spdm_unit_test.h"
#include "library/spdm_common_lib.h"
#include "spdm_crypt_ext_lib/spdm_crypt_ext_lib.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;

/*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) {
return false;
}
result = libspdm_asn1_get_tag(&ptr, end, &obj_len,
LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED);
if (!result) {
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;
}
/*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;
}
/*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;
}
/*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;
}
/*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;
}
/*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;
}
/*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_dice;

/*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_dice_tcb_info_size = 0;
cert_chain_have_dice = false;

while (ptr < end) {
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) {
return false;
} else {
if (cert_dice_tcb_info_size != 0) {
cert_chain_have_dice = true;
}
}
/* Move to next cert*/
ptr += obj_len;
}
}

if (m_libspdm_must_have_dice_tcb_info && !cert_chain_have_dice) {
return false;
}

if (ptr == end) {
return true;
} else {
return false;
}
}
Loading

0 comments on commit 89ce60a

Please sign in to comment.