GithubHelp home page GithubHelp logo

spdm-emu's Introduction

This spdm-emu is a sample SPDM emulator implementation using libspdm

Feature

  1. An SPDM requester emulator and a SPDM responder emulator that can run in OS environment.

Document

  1. User guide

    The user guide can be found at user_guide

Prerequisit

Build Tool

  1. Visual Studio (VS2015 or VS2019 or VS2022)

  2. GCC (above GCC5)

  3. LLVM (LLVM9)

    Download and install LLVM9. Ensure LLVM9 executable directory is in PATH environment variable.

Build

Git Submodule

spdm_emu uses submodules for libspdm.

To get a full buildable repo, please use git submodule update --init --recursive. If there is an update for submodules, please use git submodule update.

Windows Build with CMake

Use x86 command prompt for ARCH=ia32 and x64 command prompt for ARCH=x64. (TOOLCHAIN=VS2022|VS2019|VS2015|CLANG)

cd spdm_emu
mkdir build
cd build
cmake -G"NMake Makefiles" -DARCH=<x64|ia32> -DTOOLCHAIN=<toolchain> -DTARGET=<Debug|Release> -DCRYPTO=<mbedtls|openssl> ..
nmake copy_sample_key
nmake

Linux Build with CMake

(TOOLCHAIN=GCC|CLANG)

cd spdm_emu
mkdir build
cd build
cmake -DARCH=<x64|ia32|arm|aarch64|riscv32|riscv64|arc> -DTOOLCHAIN=<toolchain> -DTARGET=<Debug|Release> -DCRYPTO=<mbedtls|openssl> ..
make copy_sample_key
make

Run Test

Run spdm_emu

The spdm_emu output is at spdm_emu/build/bin. Open one command prompt at output dir to run spdm_responder_emu and another command prompt to run spdm_requester_emu.

Please refer to spdm_emu for detail.

Feature not implemented yet

  1. Please refer to issues for detail

Known limitation

This package is only the sample code to show the concept. It does not have a full validation such as robustness functional test and fuzzing test. It does not meet the production quality yet. Any codes including the API definition, the libary and the drivers are subject to change.

spdm-emu's People

Contributors

alistair23 avatar dhruva21 avatar ekohandel avatar jklmnn avatar jyao1 avatar lbbxsxlz avatar liron-himi-mvl avatar liuw1 avatar liyi77 avatar longlongyang avatar mahesh1kr avatar qizhangz avatar robertkeyes avatar steven-bellock avatar wenxing-hou avatar xiangfeima avatar xiaohanjlll avatar yaohuixguo avatar zhibinliintel avatar zhiqiang520 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

spdm-emu's Issues

spdm_device_secret_lib assert when --asym with ECDSA_P521 or RSAPSS_4096 or RSASSA_4096

Example:
use the command:
spdm_requester_emu.exe --asym ECDSA_P521
and spdm_responder_emu.exe --asym ECDSA_P521

spdm_responder_emu version 0.1
asym - 0x00000100
.......
Platform port Receive command: 00 00 00 01
Platform port Receive transport_type: 00 00 00 01
Platform port Receive size: 00 00 00 31
Platform port Receive buffer:
05 11 e3 04 00 30 00 01 00 00 01 00 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 20 1b 00 03 20 06 00 04 20 0f 00 05 20 01 00
SpdmReceiveRequest[.] ...
SpdmReceiveRequest[0] (0x30):
0000: 11 e3 04 00 30 00 01 00 00 01 00 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0020: 02 20 1b 00 03 20 06 00 04 20 0f 00 05 20 01 00
SpdmSendResponse[0] ...
ASSERT: D:\Test\spdm-emu\libspdm\os_stub\spdm_device_secret_lib\cert.c(229): ((boolean)(0 == 1))

[SpdmResponder] Memory leak of SpdmDataLocalPublicCertChain?

Issue from jyao1/openspdm#193

In SpdmServerConnectionStateCallback(), if connection state is SpdmConnectionStateNegotiated, a new SPDM_CERT_CHAIN will be allocated by ReadResponderPublicCertificateChain(), and then the allocated SPDM_CERT_CHAIN will be held in SpdmContext->LocalContext.LocalCertChainProvision.

That's a smart design but I didn't seem to see the code to free the newly allocated SPDM_CERT_CHAIN. Would you point me to where the buffer gets freed?

BTW, I think we don't need to compose the SPDM_CERT_CHAIN every time when the connection state reaches to Negotiated. We only need to recompose the SPDM_CERT_CHAIN only when the negotiated base hash algorithm changes.

caps is not initialized in function 'cxl_ide_km_process_session_message'

Line 271, caps is defined
Line 279, the address of caps is passed into function cxl_ide_km_query, but in function cxl_ide_km_query, the address of cap is not used.
Should caps be initialized or should the &caps parameter be removed from function cxl_ide_km_query

uint8_t caps;
uint32_t ide_reg_block[CXL_IDE_KM_IDE_CAP_REG_BLOCK_MAX_COUNT];
uint32_t ide_reg_block_count;
cxl_ide_km_aes_256_gcm_key_buffer_t key_buffer;
uint8_t kp_ack_status;
bool result;
ide_reg_block_count = CXL_IDE_KM_IDE_CAP_REG_BLOCK_MAX_COUNT;
status = cxl_ide_km_query (m_pci_doe_context, spdm_context, &session_id,
0, &dev_func_num, &bus_num, &segment, &max_port_index,
&caps,
ide_reg_block, &ide_reg_block_count);
if (LIBSPDM_STATUS_IS_ERROR(status)) {
return status;
}
LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "max_port_index - 0x%02x\n", max_port_index));
LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "caps - 0x%02x\n", caps));

Potential unalignment access in libspdm_get_response_challenge_auth()

In libspdm_get_response_challenge_auth(), It seems that the code below might potentially cause unaligned access on certain CPUs.

*(uint16_t *)ptr = (uint16_t)spdm_context->local_context
.opaque_challenge_auth_rsp_size;

Not sure if there's any alignment assumption of the 'ptr' at this location by design.

need enable CI to test chunk

Current CI only covers both trans_size 42.

We need cross add cross check:

  1. test req trans_size 4096 + rsp trans_size 42
  2. test req trans_size 42 + rsp trans_size 4096

This can be done after DMTF/libspdm#1237

spdm communication between requester and responder

Hi,

I was looking through the code where responder exactly pickup the message from the platform -

bool platform_server(IN SOCKET socket)
{
bool result;
return_status status;
uint8_t response[PCI_DOE_MAX_NON_SPDM_MESSAGE_SIZE];
uintn response_size;

while (true) {
    **status = libspdm_responder_dispatch_message(m_spdm_context);**
    if (status == RETURN_SUCCESS) {
        /* success dispatch SPDM message*/
    }

libspdm_responder_dispatch_message() calls below to get the message from platform

spdm_context->receive_message(spdm_context, &request_size,
request, 0);

The problem I see here is there seems no synchronization here when receiving the message (i.e responder may run faster and try to recv the message but requester might not have posted the message still, causing responder to fail/exit) and it's possible that responder may get same message again which it read before already (as it's blindly trying to receive message from the platform in a while loop above). How this is syned actually ?

Thanks,
Manish

Can spdm-emu requester work with different responder (not exactly same spdm-emu responder) ?

Hi,

We are planning to implement our own responder lib (it will not be exact same libspdm but with quite of modifications as per our device implementation) which will be hooked up to spdm-emu responder. But spdm-emu requester would still be the same using vanilla libspdm beneath.

Is it some feasible approach ? Or there are some hidden considerations that the way spdm-emu requester and responder designed to work with only same vanilla libspdm ?

Thanks,
Manish

download libspdm code and its submodules twice

When use "git submodule update --init --recursive" command to get the full repo, the libspdm code and its submodules will download twice.

The files in SPDM-Responder-Validator/libspdm directory are not necessary to build the spdm-emu executable files.

need add non-0 slot-id for key exchange

currently slot-id 0 is used to do key exchange. It may hide bug in the implementation that assume the slot-id 0 is used.

We need add the case to use non-0 slot-id for key exchange. E.g. slot id 1.

Requester should determine the request command base on responder capabilities

In the testing, responder has set capabilities "not supporting" CHALLENGE.

However requester emu still send CHALLENGE command to responder.

When responder responds with an invalid request error, requester just end the communication.

Shouldn’t requester send the SPDM command base on responder supported capabilities/features?

SPDM_DATA_PEER_PUBLIC_ROOT_CERT’ undeclared

Hi
At first, thanks a lot for this open project spdm-emu, this give me a good topic to study SPDM spec.

And recently I try to build spdm-emu for ARM_GCC,
my code is clone from "8b193c1 revision", and after run "cmake -DARCH=arm =DTOOLCHAIN=ARM_GCC -DARGET=Debug -DCRYPTO=openssl .."

I found a error as following, could you check this? thank you.
_spdm-emu/spdm_emu/spdm_requester_emu/spdm_requester.c:268:11: error: ‘SPDM_DATA_PEER_PUBLIC_ROOT_CERT’ undeclared (first use in this function); did you mean ‘SPDM_DATA_PEER_PUBLIC_ROOT_CERT_HASH’? 268 | SPDM_DATA_PEER_PUBLIC_ROOT_CERT, | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | SPDM_DATA_PEER_PUBLIC_ROOT_CERT_HASH_

John

spdm_responder_emu will hang when run using --trans NONE

Version: 2.1.0
commit c94124d

compile command:
cmake -DARCH=x64 -DTOOLCHAIN=GCC -DTARGET=Release -DCRYPTO=mbedtls ..

responder:
./spdm_responder_emu --trans NONE

requester:
./spdm_requester_emu --trans NONE

responder log:
.....
Platform port Transmit command: 00 00 00 01
Platform port Transmit transport_type: 00 00 00 00
Platform port Transmit size: 00 00 00 34
Platform port Transmit buffer:
12 65 00 00 71 b3 36 fa 7e b9 35 ac 48 78 15 09 58 0f 24 77 4c 34 22 ca fb 1c 5d 4a 08 72 fe e6 84 3b ca 5c 7e 80 dc aa c5 e5 04 53 8c c5 78 c6 0e 16 6e a3
Platform port Receive command: 00 00 00 01
Platform port Receive transport_type: 00 00 00 00
Platform port Receive size: 00 00 00 1c
Platform port Receive buffer:
ff ff ff ff 16 00 d3 b7 4e bb 40 38 25 f1 ba 3e 50 40 a5 2b 6d 62 73 2e 61 cb 87 c9
SpdmReceiveRequest[.] ...
SpdmReceiveRequest[0] (0x1c):
0000: ff ff ff ff 16 00 d3 b7 4e bb 40 38 25 f1 ba 3e 50 40 a5 2b 6d 62 73 2e 61 cb 87 c9
SpdmSendResponse[0] ...
LIBSPDM_ASSERT: /home/binbin/workspace/SPDM/spdm-emu-2.1.0/libspdm/library/spdm_responder_lib/libspdm_rsp_receive_send.c(87): request_code != 0xFF

requester log:
....
libspdm_start_session - libspdm_send_receive_finish - (nil)
libspdm_send_spdm_request[ffffffff] (0x4):
0000: 12 e8 00 00
Platform port Transmit command: 00 00 00 01
Platform port Transmit transport_type: 00 00 00 00
Platform port Transmit size: 00 00 00 1c
Platform port Transmit buffer:
ff ff ff ff 16 00 d3 b7 4e bb 40 38 25 f1 ba 3e 50 40 a5 2b 6d 62 73 2e 61 cb 87 c9

core dumped when running spdm-emu (on linux server)

I built emu with below command -

cmake -DARCH=x64 -DTOOLCHAIN=GCC -DTARGET=Release -DCRYPTO=mbedtls ..
make copy_sample_key
make -j

/dev/shm/spdm-emu/build/bin# ./spdm_responder_emu > resp_log
free(): invalid next size (normal)
Aborted (core dumped)

/dev/shm/spdm-emu/build/bin# ./spdm_requester_emu > req_log

Responder Aborted and dumped the core. attached the logs for both req/resp.

Thanks,
Manish
logs.zip

a negative parameter being interpreted as unsigned.

  1. line 318 libspdm_read_responder_root_public_certificate function may change the value of data_size to zero.
    line 324 data_size - sizeof(spdm_cert_chain_t) - hash_size may be negative value.

res = libspdm_read_responder_root_public_certificate(m_use_hash_algo,
m_use_asym_algo,
&data, &data_size,
&hash, &hash_size);
libspdm_x509_get_cert_from_cert_chain(
(uint8_t *)data + sizeof(spdm_cert_chain_t) + hash_size,
data_size - sizeof(spdm_cert_chain_t) - hash_size, 0,
&root_cert, &root_cert_size);

if line 49 return false, data_size will be zero.
bool libspdm_read_responder_root_public_certificate( )
https://github.com/DMTF/libspdm/blob/5cf400da304b6682920158c2e583a2f9242027ec/os_stub/spdm_device_secret_lib_sample/cert.c#L39-L50
image
2. data1_size may be zero. same issue.
res = libspdm_read_responder_root_public_certificate_slot(1,
m_use_hash_algo,
m_use_asym_algo,
&data1, &data1_size,
&hash1, &hash1_size);
libspdm_x509_get_cert_from_cert_chain(
(uint8_t *)data1 + sizeof(spdm_cert_chain_t) + hash1_size,
data1_size - sizeof(spdm_cert_chain_t) - hash1_size, 0,
&root_cert1, &root_cert1_size);

Build fails with `extra tokens at end of #endif`

When I try to build with the latest main I get the following error:

spdm-emu/libspdm/library/spdm_requester_lib/get_digests.c:206:8: error: extra tokens at end of #endif directive [-Werror=endif-labels]
 #endif SPDM_ENABLE_CAPABILITY_CERT_CAP
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

spdm_requester_emu --cap have some unsupported flags

From the help message, spdm_requester_emu --cap support 'CACHE', 'MEAS_NO_SIG', 'MEAS_SIG', 'MEAS_FRESH', 'PSK_WITH_CONTEXT' those flags, but when we use those type, it directly report unsupported flag. we need to make the help message and the code behavior to align.

spdm_requester_emu [--trans MCTP|PCI_DOE]
[--cap CACHE|CERT|CHAL|MEAS_NO_SIG|MEAS_SIG|MEAS_FRESH|ENCRYPT|MAC|MUT_AUTH|KEY_EX|PSK|PSK_WITH_CONTEXT|ENCAP|HBEAT|KEY_UPD|HANDSHAKE_IN_CLEAR|PUB_KEY_ID]

$ ./spdm_requester_emu --cap CACHE
spdm_requester_emu version 0.1
unsupported flag - CACHE
invalid --cap CACHE

Some wrong function were called, when disable SPDM_ENABLE_CAPABILITY_***_CAP

SPDM_ENABLE_CAPABILITY_XXX_CAP is compile time optimization switches. The URL for the code is

#define SPDM_ENABLE_CAPABILITY_CERT_CAP 1
#define SPDM_ENABLE_CAPABILITY_CHAL_CAP 1
#define SPDM_ENABLE_CAPABILITY_MEAS_CAP 1

#define SPDM_ENABLE_CAPABILITY_KEY_EX_CAP   1
#define SPDM_ENABLE_CAPABILITY_PSK_EX_CAP   1

in spdm-emu\libspdm\include\library\spdm_lib_config.h

When disable the SPDM_ENABLE_CAPABILITY_XXX_CAP ,some build errors were found.

  • _spdm_requester_authentication.c.obj : error LNK2019: unresolved external symbol _libspdm_get_digest referenced in function _spdm_authentication
  • spdm_requester_authentication.c.obj : error LNK2019: unresolved external symbol _libspdm_get_certificate referenced in function _spdm_authentication
  • spdm_requester_authentication.c.obj : error LNK2019: unresolved external symbol _libspdm_challenge referenced in function _spdm_authentication
  • spdm_requester_measurement.c.obj : error LNK2019: unresolved external symbol _libspdm_get_measurement referenced in function _spdm_send_receive_get_measurement
  • ....\bin\spdm_requester_emu.exe : fatal error LNK1120: 4 unresolved externals

I find it is because that spdm-emu call the wrong function when disable SPDM_ENABLE_CAPABILITY_XXX_CAP.
These function is not definition when disable SPDM_ENABLE_CAPABILITY_XXX_CAP.

The default supported measurement hash algorithm SHA_256 is missed in code

  1. [--meas_hash] is measurement hash algorithm. By default, SHA_512,SHA_384,SHA_256 is used.

    printf(" [--meas_hash] is measurement hash algorithm. By default, SHA_512,SHA_384,SHA_256 is used.\n");

  2. but SHA_256 is missed in the following code.

    uint32 m_support_measurement_hash_algo =
    SPDM_ALGORITHMS_MEASUREMENT_HASH_ALGO_TPM_ALG_SHA_512 |
    SPDM_ALGORITHMS_MEASUREMENT_HASH_ALGO_TPM_ALG_SHA_384;

  3. here also mentioned the default supported measurement hash algorithm.
    https://github.com/DMTF/spdm-emu/blob/main/doc/spdm_emu.md

Build error because of spdm_version_number_t type changed

Because spdm_version_number_t have changed, the build error is found.

[ 89%] Building C object spdm_emu/spdm_requester_emu/CMakeFiles/spdm_requester_emu.dir/spdm_requester.c.obj
spdm_requester.c
C:\mywork\code\spdm-emu\spdm_emu\spdm_requester_emu\spdm_requester.c(143): error C2224: left of '.major_version' must have struct/union type
C:\mywork\code\spdm-emu\spdm_emu\spdm_requester_emu\spdm_requester.c(144): error C2224: left of '.minor_version' must have struct/union type
C:\mywork\code\spdm-emu\spdm_emu\spdm_requester_emu\spdm_requester.c(145): error C2224: left of '.alpha' must have struct/union type
C:\mywork\code\spdm-emu\spdm_emu\spdm_requester_emu\spdm_requester.c(146): error C2224: left of '.update_version_number' must have struct/union type
C:\mywork\code\spdm-emu\spdm_emu\spdm_requester_emu\spdm_requester.c(155): error C2224: left of '.major_version' must have struct/union type
C:\mywork\code\spdm-emu\spdm_emu\spdm_requester_emu\spdm_requester.c(157): error C2224: left of '.minor_version' must have struct/union type
C:\mywork\code\spdm-emu\spdm_emu\spdm_requester_emu\spdm_requester.c(159): error C2224: left of '.alpha' must have struct/union type
C:\mywork\code\spdm-emu\spdm_emu\spdm_requester_emu\spdm_requester.c(160): error C2224: left of '.update_version_number' must have struct/union type

Because the code is still old and still use the struct. We should update the code.

        spdm_version.major_version = (m_use_version >> 4) & 0xF;
        spdm_version.minor_version = m_use_version & 0xF;
        spdm_version.alpha = 0;
        spdm_version.update_version_number = 0;

When reading certificate fail, we should stop the communication between the requester and responder

Test at the commit 2c4ada8

The line 248, 264, and 278 just handle the case when res = TRUE, I think we should also handle the other case when res = FALSE.
When read certificate fail, we should stop the communication between the requester and responder, maybe just like the following three lines sample code(bold text).
free(m_spdm_context);
m_spdm_context = NULL;
return NULL;

res = read_responder_public_certificate_chain(m_use_hash_algo,
m_use_asym_algo,
&data, &data_size,
NULL, NULL);
if (res) {
zero_mem(&parameter, sizeof(parameter));
parameter.location = SPDM_DATA_LOCATION_LOCAL;
spdm_set_data(spdm_context,
SPDM_DATA_PEER_PUBLIC_CERT_CHAIN,
&parameter, data, data_size);
// Do not free it.
}
} else {
res = read_responder_root_public_certificate(m_use_hash_algo,
m_use_asym_algo,
&data, &data_size,
&hash, &hash_size);
x509_get_cert_from_cert_chain((uint8 *)data + sizeof(spdm_cert_chain_t) + hash_size,
data_size - sizeof(spdm_cert_chain_t) - hash_size, 0,
&root_cert, &root_cert_size);
if (res) {
zero_mem(&parameter, sizeof(parameter));
parameter.location = SPDM_DATA_LOCATION_LOCAL;
spdm_set_data(spdm_context,
SPDM_DATA_PEER_PUBLIC_ROOT_CERT,
&parameter, root_cert, root_cert_size);
// Do not free it.
}
}
res = read_requester_public_certificate_chain(m_use_hash_algo,
m_use_req_asym_algo,
&data, &data_size, NULL,
NULL);
if (res) {
zero_mem(&parameter, sizeof(parameter));
parameter.location = SPDM_DATA_LOCATION_LOCAL;
data8 = m_use_slot_count;
spdm_set_data(spdm_context, SPDM_DATA_LOCAL_SLOT_COUNT,
&parameter, &data8, sizeof(data8));
for (index = 0; index < m_use_slot_count; index++) {
parameter.additional_data[0] = index;
spdm_set_data(spdm_context,
SPDM_DATA_LOCAL_PUBLIC_CERT_CHAIN,
&parameter, data, data_size);
}
// do not free it
}

'[--slot <0~7|0xFF>]' in the help information of spdm_responder_emu is not supported

C:\spdm-emu\build\bin>spdm_responder_emu.exe --slot 0
spdm_responder_emu version 0.1
invalid --slot

The '--slot' in Line 44 does not match the '--slot_id' in Line 75, I think the '--slot' in Line 44 should be '--slot_id'.

printf(" [--slot <0~7|0xFF>]\n");

printf(" [--slot_id] is to select the peer slot ID in GET_MEASUREMENT, CHALLENGE_AUTH, KEY_EXCHANGE and FINISH. By default, 0 is used.\n");
printf(" 0xFF can be used to indicate provisioned certificate chain. No GET_CERTIFICATE is needed.\n");
printf(" 0xFF must be used to if PUB_KEY_ID is set. No GET_DIGEST/GET_CERTIFICATE is sent.\n");

Validation of Chunk support

Hi,
I could not find any code changes as part of spdm-emu which can validate the newly added chunk mechanism feature. So any idea how to test the chunk feature?

Thanks in advance,

Best Regards
Ranjan

How to integrate SPDM-emu to openbmc?

Hi
I appreciated the spdm-emu project, but we want to integrate spdm-emu to openbmc project to do some evaluation on qemu,

So could you share any hint how to write a recipe to integrate spdm-emu into openbmc(maybe romulus or ast2600evb)?
And could you share how to build spdm-emu for static linking based on ARM_GCC toolchain?

Thanks
John

Build error for variables redefinition

Because some variables redefine, emu build error:

mctp_send_receive.c
C:\mywork\code\spdm-emu\include\library/mctp_common_lib.h(31): error C2371: 'pldm_get_tid_request_t': redefinition; different basic types
C:\mywork\code\spdm-emu\libspdm\include\industry_standard/pldm.h(66): note: see declaration of 'pldm_get_tid_request_t'
C:\mywork\code\spdm-emu\include\library/mctp_common_lib.h(39): error C2371: 'pldm_get_tid_response_t': redefinition; different basic types
C:\mywork\code\spdm-emu\libspdm\include\industry_standard/pldm.h(74): note: see declaration of 'pldm_get_tid_response_t'

pci_doe_req_discovery.c
C:\mywork\code\spdm-emu\include\library/pci_doe_common_lib.h(26): error C2371: 'pci_doe_spdm_vendor_defined_request_t': redefinition; different basic types
C:\mywork\code\spdm-emu\libspdm\include\industry_standard/pcidoe.h(78): note: see declaration of 'pci_doe_spdm_vendor_defined_request_t'
C:\mywork\code\spdm-emu\include\library/pci_doe_common_lib.h(37): error C2371: 'pci_doe_spdm_vendor_defined_response_t': redefinition; different basic types
C:\mywork\code\spdm-emu\libspdm\include\industry_standard/pcidoe.h(94): note: see declaration of 'pci_doe_spdm_vendor_defined_response_t'

We should update the libspdm version and fix the build error.

ASSERT when running 'spdm_responder_emu.exe --cap CACHE'

Test at the commit 2c4ada8

Open one command prompt to run :
C:\spdm-emu\build\bin>spdm_responder_emu.exe --cap CACHE
spdm_responder_emu version 0.1
cap - 0x00000001
context_size - 0x7080
ASSERT: C:\spdm-emu\libspdm\library\spdm_common_lib\context_data.c(136): (*(uint32 *)data) & 0x00000002

'VerifyCertificateChainData - FAIL' when running spdm_responder_emu and spdm_requester_emu without any parameter

Test at the commit 2c4ada8

  1. Open one command prompt to run
    C:\spdm-emu1011\build\bin>spdm_responder_emu.exe > responder.log

  2. Open another command prompt to run
    C:\spdm-emu1011\build\bin>spdm_requester_emu.exe > requester.log

  3. check the 'requester.log', there is a fail at line 59 as following:
    !!! VerifyCertificateChainData - FAIL (cert chain verify failed)!!!

  4. Please refer to the attached 'requester.log'.
    requester.log
    .

status may not be initialized

libspdm_return_t status;
if (m_use_transport_layer == SOCKET_TRANSPORT_TYPE_PCI_DOE) {
LIBSPDM_ASSERT(!is_app_message);
status = pci_doe_get_response_spdm_vendor_defined_request (
m_pci_doe_context, spdm_context, session_id,
request, request_size, response, response_size);
}
if (m_use_transport_layer == SOCKET_TRANSPORT_TYPE_MCTP) {
LIBSPDM_ASSERT(is_app_message);
status = mctp_get_response_secured_app_request (
m_mctp_context, spdm_context, session_id,
request, request_size, response, response_size);
}
if (LIBSPDM_STATUS_IS_ERROR(status)) {
libspdm_generate_error_response(spdm_context,
SPDM_ERROR_CODE_INVALID_REQUEST, 0,
response_size, response);
}

Line 39 defines status, but when line 41 and line 48 if are false, status is not initialized and is used in line 55.

build failed: warning C4702: unreachable code is treated as an error

[ 80%] Building C object out/spdm_common_lib.out/CMakeFiles/spdm_common_lib.dir/libspdm_com_opaque_data.c.obj
libspdm_com_opaque_data.c
C:\Workspace\project\mine\spdm-emu\libspdm\library\spdm_common_lib\libspdm_com_opaque_data.c(396) : error C2220: the following warning is treated as an error
C:\Workspace\project\mine\spdm-emu\libspdm\library\spdm_common_lib\libspdm_com_opaque_data.c(396) : warning C4702: unreachable code
NMAKE : fatal error U1077: 'C:\PROGRA2\MIB0551\2019\BUILDT1\VC\Tools\MSVC\14281.293\bin\Hostx64\x64\cl.exe' : return code '0x2'
Stop.
NMAKE : fatal error U1077: '"C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.28.29333\bin\HostX64\x64\nmake.exe"' : return code '0x2'
Stop.
NMAKE : fatal error U1077: '"C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.28.29333\bin\HostX64\x64\nmake.exe"' : return code '0x2'
Stop.

Resource acquired to 'client_socket' may be lost

  1. Resource acquired to client_socket at line 50 may be lost at line 59 return false;. I'm not 100% sure whether it is an issue.
    client_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (client_socket == INVALID_SOCKET) {
    printf("Create socket Failed - %x\n",
    #ifdef _MSC_VER
    WSAGetLastError()
    #else
    errno
    #endif
    );
    return false;
    }
  2. Three similar cases:
    *listen_socket = socket(PF_INET, SOCK_STREAM, 0);
    if (INVALID_SOCKET == *listen_socket) {
    printf("Cannot create server listen socket. Error is 0x%x\n",
    #ifdef _MSC_VER
    WSAGetLastError()
    #else
    errno
    #endif
    );
    return false;
    }

    client_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (client_socket == INVALID_SOCKET) {
    printf("Create socket Failed - %x\n",
    #ifdef _MSC_VER
    WSAGetLastError()
    #else
    errno
    #endif
    );
    return false;
    }

    client_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (client_socket == INVALID_SOCKET) {
    printf("Create socket Failed - %x\n",
    #ifdef _MSC_VER
    WSAGetLastError()
    #else
    errno
    #endif
    );
    return false;
    }

return status of spdm_load_negotiated_state() is not checked

  1. Take responder for example (same for the requester),
    spdm_load_negotiated_state(spdm_context, FALSE);

Current code didn't check return status of spdm_load_negotiated_state but logically spdm_load_negotiated_state could fail with some values left in spdm_context.

Maybe we could call spdm_load_negotiated_state immediately after spdm_init_context and re-init the context in case of load failures.

	spdm_init_context(spdm_context);
	if (m_load_state_file_name != NULL) {
		if (spdm_load_negotiated_state(spdm_context, FALSE) != RETURN_SUCCESS) {
			/* re-init spdm context */
			spdm_init_context(spdm_context);
		}
	}
	spdm_register_device_io_func(spdm_context, spdm_device_send_message,
				     spdm_device_receive_message);
  1. spdm_clear_negotiated_state has nothing to do with spdm_context. Suggest to take out the input parameter.
    return_status spdm_clear_negotiated_state(IN void *spdm_context)

Questions about spdm_authentication()

if ((m_exe_connection & EXE_CONNECTION_DIGEST) != 0) {
status = libspdm_get_digest(context, slot_mask,
total_digest_buffer);
if (LIBSPDM_STATUS_IS_ERROR(status)) {
return status;
}
}
if ((m_exe_connection & EXE_CONNECTION_CERT) != 0) {
if (slot_id != 0xFF) {
status = libspdm_get_certificate(
context, slot_id, cert_chain_size, cert_chain);
if (LIBSPDM_STATUS_IS_ERROR(status)) {
return status;
}
}
}
if ((m_exe_connection & EXE_CONNECTION_DIGEST) != 0) {
status = libspdm_get_digest(context, slot_mask,
total_digest_buffer);
if (LIBSPDM_STATUS_IS_ERROR(status)) {
return status;
}
}

Hi,

I am not pretty sure but these lines seem to verify the recent changes of allowing GET_DIGESTS/GET_CERTIFICATE after CHALLENGE.
Would you help take them out if they are not supposed to be part of a typical authentication procedure?

Thanks!

the handle *listen_socket is lost in create_socket( ) function

  1. opens handle stored into *listen_socket in Line 35.
    *listen_socket = socket(PF_INET, SOCK_STREAM, 0);
  2. return false; in Line 61, then the handle *listen_socket is lost.
    if (setsockopt(*listen_socket, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)) < 0) {
    printf("Cannot configure server listen socket. Error is 0x%x\n",
    #ifdef _MSC_VER
    WSAGetLastError()
    #else
    errno
    #endif
    );
    return false;
    }
  3. Maybe we should closesocket(*listen_socket); before return false; in Line 61.

'spdm_responder_emu.exe --cap' will fail when adding one or more space between the multiple flags

Test at the commit 2c4ada8

[--cap CACHE|CERT|CHAL|MEAS_NO_SIG|MEAS_SIG|MEAS_FRESH|ENCRYPT|MAC|MUT_AUTH|KEY_EX|PSK|PSK_WITH_CONTEXT|ENCAP|HBEAT|KEY_UPD|HANDSHAKE_IN_CLEAR|PUB_KEY_ID]
[--cap] is capability flags. Multiple flags can be set together. Please use ',' for them.

Open one command prompt to run :
Fail scenario (There is a space after the comma)
C:\spdm-emu\build\bin>spdm_responder_emu.exe --cap CERT, CHAL
spdm_responder_emu version 0.1
cap - 0x00000002
invalid CHAL

Pass scenario (There is no any space after the comma)
C:\spdm-emu\build\bin>spdm_responder_emu.exe --cap CERT,CHAL
spdm_responder_emu version 0.1
cap - 0x00000006
context_size - 0x7080

"*kp_ack_status" parameter usage mismatch

Line 27 parameter uint8_t *kp_ack_status does not match the usage of line 49.
Maybe *kp_ack_status = PCI_IDE_KM_KP_ACK_STATUS_SUCCESS;

libspdm_return_t pci_ide_km_device_key_prog (const void *pci_doe_context,
const void *spdm_context, const uint32_t *session_id,
uint8_t stream_id, uint8_t key_sub_stream, uint8_t port_index,
uint8_t *kp_ack_status,
const pci_ide_km_aes_256_gcm_key_buffer_t *key_buffer)
{
libidekm_device_port_context *device_port_context;
uint8_t index;
device_port_context = libidekm_get_device_port_context (port_index);
if (device_port_context == NULL) {
return LIBSPDM_STATUS_INVALID_MSG_FIELD;
}
index = key_sub_stream & (PCI_IDE_KM_KEY_SET_MASK | PCI_IDE_KM_KEY_DIRECTION_MASK);
/* program key */
libspdm_copy_mem (&device_port_context->key_buffer[index],
sizeof(device_port_context->key_buffer[index]),
key_buffer,
sizeof(pci_ide_km_aes_256_gcm_key_buffer_t)
);
device_port_context->is_key_prog[index] = true;
kp_ack_status = PCI_IDE_KM_KP_ACK_STATUS_SUCCESS;
return LIBSPDM_STATUS_SUCCESS;
}

Does spdm-emu tool works over SMBUS/I2C lines?

If it works over SMBUS/I2C lines, could you please provide the patch so that it will be helpful for me to run that tool inside Raspberry PI 3 Model B+ and we should be able to send and receive data over SMBUS/I2C lines between requester and responder.

spdm_get_measurements returning spdm_error (ErrCode=0x01)

When running the default setting of the spdm emulator, it appears that spdm runs the SPDM_GET_MEASUREMENTS command for each certificate in the slot id (MeasOp=0x00 through MeasOp=0xfe). However, for the majority of the get_measurement operations, the responder returns the SPDM_ERROR message (i.e. lines 52, 54, 56).

41 (1664917952) MCTP(5) REQ->RSP SPDM(12, 0xe0) SPDM_GET_MEASUREMENTS (Attr=0x00(), MeasOp=0x00(TotalNum))
42 (1664917952) MCTP(5) RSP->REQ SPDM(12, 0x60) SPDM_MEASUREMENTS (TotalMeasIndex=0x07)
43 (1664917952) MCTP(5) REQ->RSP SPDM(12, 0xe0) SPDM_GET_MEASUREMENTS (Attr=0x00(), MeasOp=0x01)
44 (1664917952) MCTP(5) RSP->REQ SPDM(12, 0x60) SPDM_MEASUREMENTS (NumOfBlocks=0x1, MeasRecordLen=0x47)
45 (1664917952) MCTP(5) REQ->RSP SPDM(12, 0xe0) SPDM_GET_MEASUREMENTS (Attr=0x00(), MeasOp=0x02)
46 (1664917952) MCTP(5) RSP->REQ SPDM(12, 0x60) SPDM_MEASUREMENTS (NumOfBlocks=0x1, MeasRecordLen=0x47)
47 (1664917952) MCTP(5) REQ->RSP SPDM(12, 0xe0) SPDM_GET_MEASUREMENTS (Attr=0x00(), MeasOp=0x03)
48 (1664917952) MCTP(5) RSP->REQ SPDM(12, 0x60) SPDM_MEASUREMENTS (NumOfBlocks=0x1, MeasRecordLen=0x47)
49 (1664917952) MCTP(5) REQ->RSP SPDM(12, 0xe0) SPDM_GET_MEASUREMENTS (Attr=0x00(), MeasOp=0x04)
50 (1664917952) MCTP(5) RSP->REQ SPDM(12, 0x60) SPDM_MEASUREMENTS (NumOfBlocks=0x1, MeasRecordLen=0x47)
51 (1664917952) MCTP(5) REQ->RSP SPDM(12, 0xe0) SPDM_GET_MEASUREMENTS (Attr=0x00(), MeasOp=0x05)
52 (1664917952) MCTP(5) RSP->REQ SPDM(12, 0x7f) SPDM_ERROR (ErrCode=0x01, ErrData=0x00)
53 (1664917952) MCTP(5) REQ->RSP SPDM(12, 0xe0) SPDM_GET_MEASUREMENTS (Attr=0x00(), MeasOp=0x06)
54 (1664917952) MCTP(5) RSP->REQ SPDM(12, 0x7f) SPDM_ERROR (ErrCode=0x01, ErrData=0x00)
55 (1664917952) MCTP(5) REQ->RSP SPDM(12, 0xe0) SPDM_GET_MEASUREMENTS (Attr=0x00(), MeasOp=0x07)
56 (1664917952) MCTP(5) RSP->REQ SPDM(12, 0x7f) SPDM_ERROR (ErrCode=0x01, ErrData=0x00)

I have a few concerns regarding this issue. What is ErrCode 0x01 and why is the responder returning the SPDM_ERROR message? Also, based on my understanding of the SPDM spec, the protocol should be able to retrieve a specific measurement in the slot id. Is there a command in the user tools to do this, and if not, is there a reason why the emulator retrieves all of the measurements?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.