-
Use static linking (Library) when there is one instance that can be linked to the device. For example, cryptography engine.
-
Use dynamic linking (function registration) when there are multiple instances that can be linked to the device. For example, transport layer.
+================+ +================+
| SPDM Requester | | SPDM Responder | // PCI Component Measurement and Authentication (CMA)
| Device Driver | | Device Driver | // PCI Integrity and Data Encryption (IDE)
+================+ +================+
| spdm_send_receive_data ^ spdm_get_response_func
=============================================================
V |
+------------------+ +---------------+ +------------------+
|spdm_requester_lib|->|spdm_common_lib|<-|spdm_responder_lib| // DSP0274 - SPDM
+------------------+ +---------------+ +------------------+
| | | | | V | | |
| | | | | +-----------+ | | |
| | | | | |asymsignlib| | | | // HAL: Device Secret handling (PrivateKey)
| | | | V +-----------+ | | |
| | | | +--------------+ | | |
| | | | |spdm_crypt_lib| | | | // SPDM related crypto
| | | V +--------------+ | | |
| | | +------------------------+ | | |
| | ----->|spdm_secured_message_lib|<------ | | // DSP0277 - Secured Message in SPDM session
| | +------------------------+ | |
| | ^ V | |
| | | +--------+ | |
| | | | psklib | | | // HAL: Device Secret handling (PSK)
| | | +--------+ | |
=============================================================
| | | | |
| | +----------------------+ | |
| -------->|spdm_transport_xxx_lib|<--------- | // DSP0275/DSP0276 - SPDM/SecuredMessage over MCTP
| | (XXX = mctp, pcidoe) | | // PCI Data Object Exchange (DOE) message
| +----------------------+ |
| spdm_transport_encode/decode_message_func |
| |
=============================================================
| |
| spdm_device_send/receive_message_func |
| +----------------+ |
------------->| SPDM Device IO |<-------------- // DSP0237 - MCTP over SMBus
| (SMBus, PciDoe)| // DSP0238 - MCTP over PCIeVDM
+----------------+ // PCI DOE - PCI DOE message over PCI DOE mailbox.
-
spdm_requester_lib (follows DSP0274)
This library is linked for an SPDM Requester.
-
spdm_responder_lib (follows DSP0274)
This library is linked for an SPDM Responder.
-
spdm_common_lib (follows DSP0274)
This library provides common services for
spdm_requester_lib
andspdm_responder_lib
. -
spdm_secured_message_lib (follows DSP0277)
This library handles the session key generation and secured message encryption and decryption.
This can be implemented in a secure environment if the session keys are considered a secret.
-
This library provides SPDM-related cryptography functions.
-
Transport layer encode/decode
6.1) spdm_transport_mctp_lib (follows DSP0275 and DSP0276)
This library encodes and decodes MCTP message header.
SPDM Requester / Responder needs to register max_spdm_msg_size
, LIBSPDM_MCTP_TRANSPORT_HEADER_SIZE
, LIBSPDM_MCTP_TRANSPORT_TAIL_SIZE
, libspdm_transport_mctp_encode_message
and libspdm_transport_mctp_decode_message
to the spdm_requester_lib
/ spdm_responder_lib
via libspdm_register_transport_layer_func
.
These APIs encode and decode transport layer messages to or from a SPDM device.
6.2) spdm_transport_pcidoe_lib (follows PCI DOE)
This library encodes and decodes PCI DOE message header.
SPDM Requester / Responders need to register max_spdm_msg_size
, LIBSPDM_PCI_DOE_TRANSPORT_HEADER_SIZE
, LIBSPDM_PCI_DOE_TRANSPORT_TAIL_SIZE
, libspdm_transport_pci_doe_encode_message
and libspdm_transport_pci_doe_decode_message
to the spdm_requester_lib
/ spdm_responder_lib
via libspdm_register_transport_layer_func
.
These APIs encode and decode transport layer messages to or from a SPDM device.
-
Device IO
SPDM Requester / Responder needs to register
libspdm_device_send_message_func
andlibspdm_device_receive_message_func
to thespdm_requester_lib
/spdm_responder_lib
vialibspdm_register_device_io_func
.SPDM Requester / Responder needs to register
sender_buffer_size
,receiver_buffer_size
,libspdm_device_acquire_sender_buffer_func
,libspdm_device_release_sender_buffer_func
,libspdm_device_acquire_receiver_buffer_func
, andlibspdm_device_release_receiver_buffer_func
to thespdm_requester_lib
/spdm_responder_lib
vialibspdm_register_device_buffer_func
.These APIs send and receive transport layer messages to and from an SPDM device.
The size of scratch buffer can be got via
libspdm_get_sizeof_required_scratch_buffer
at runtime or pre-calculated vialibspdm_get_scratch_buffer_capacity
statically.The sender flow is: { libspdm_acquire_sender_buffer (&sender_buffer, &sender_buffer_size); spdm_message_buffer = sender_buffer + transport_header_size; /* build SPDM request/response in spdm_message_buffer */ transport_encode_message (spdm_message_buffer, spdm_message_buffer_size, &transport_message_buffer, &transport_message_buffer_size); send_message (transport_message_buffer, transport_message_buffer_size); libspdm_release_sender_buffer (sender_buffer); } The buffer usage of sender buffer is: ===== : SPDM message (max_header_size must be reserved before message) |<--- sender_buffer_size --->| |<--- transport_message_buffer_size --->| |<-transport_header_size->|<-spdm_message_buffer_size->|<-transport_tail_size->| +-----+-------------------+============================+----------------+------+ | | transport header | SPDM message | transport tail | | +-----+-------------------+============================+----------------+------+ ^ ^ ^ | | | spdm_message_buffer | | transport_message_buffer | sender_buffer For secured messages the scratch_buffer is used to store plain text and the final cipher text will be in sender_buffer. libspdm_transport_xx_encode_message(spdm_message_buffer, &transport_message_buffer) { /* spdm_message_buffer is inside of scratch_buffer. * transport_message_buffer is inside of sender_buffer. */ libspdm_xxx_encode_message (spdm_message_buffer, spdm_message_buffer_size, &app_message_buffer, &app_message_buffer_size); secured_message_buffer = transport_message_buffer + transport_header_size; libspdm_encode_secured_message (app_message_buffer, app_message_buffer_size, secured_message_buffer, &secured_message_buffer_size); libspdm_xxx_encode_message (secured_message_buffer, secured_message_buffer_size, &transport_message_buffer, &transport_message_buffer_size); } The buffer usage of sender_buffer and scratch_buffer is: ===== : SPDM message (max_header_size must be reserved before message, for sender_buffer and scratch_buffer) ***** : encrypted data $$$$$ : additional authenticated data (AAD) &&&&& : message authentication code (MAC) / TAG |<--- sender_buffer_size --->| |<--- transport_message_buffer_size --->| |sec_trans_header_size|<--- secured_message_buffer_size --->| |<--- transport_header_size --->|<spdm>|<-transport_tail_size->| +---------+-----------+$$$$$$$$$$$$$$$$$$$$+***************************+&&&+--------+---+ | | TransHdr | EncryptionHeader |AppHdr| SPDM |Random|MAC|AlignPad| | | | |SessionId|SeqNum|Len|AppLen| | | | | | | +---------+-----------+$$$$$$$$$$$$$$$$$$$$+***************************+&&&+--------+---+ ^ ^ ^ | | | secured_message_buffer | | transport_message_buffer | sender_buffer |<--- scratch_buffer_size --->| |<--- plain text size --->| |<-app_msg_s->| |<--- transport_header_size --->|<spdm>|<-transport_tail_size->| +------------------------------------------+-------------+======+------+----------------+ | |EncHdr|AppHdr| SPDM |Random| | | |AppLen| | | | | +------------------------------------------+-------------+======+------+----------------+ ^ ^ ^ ^ | | | | spdm_message_buffer | | | app_message_buffer | | plain text | scratch_buffer
The receiver flow is: { libspdm_acquire_receiver_buffer (&receiver_buffer, &receiver_buffer_size); transport_message_buffer = receiver_buffer; receive_message (&transport_message_buffer, &transport_message_buffer_size); transport_decode_message (transport_message_buffer, transport_message_buffer_size, &spdm_message_buffer, &spdm_message_buffer_size); /* process SPDM request/response in spdm_message_buffer */ libspdm_release_receiver_buffer (receiver_buffer); } The buffer usage of sender buffer is: ===== : SPDM message |<--- receiver_buffer_size --->| |<--- transport_message_buffer_size --->| |<-spdm_message_buffer_size->| +--+-------------------+============================+----------------+--+ | | transport header | SPDM message | transport tail | | +--+-------------------+============================+----------------+--+ ^ ^ ^ | | | spdm_message_buffer | | transport_message_buffer | receiver_buffer For secured messages the scratch_buffer will be used to store plain text and the cipher text is in receiver_buffer. libspdm_transport_xxx_decode_message(transport_message_buffer, &spdm_message_buffer) { /* transport_message_buffer is inside of receiver_buffer. * spdm_message_buffer is inside of scratch_buffer. */ libspdm_xxx_decode_message (transport_message_buffer, transport_message_buffer_size, &secured_message_buffer, &secured_message_buffer_size); app_message_buffer = spdm_message_buffer libspdm_decode_secured_message (secured_message_buffer, secured_message_buffer_size, &app_message_buffer, &app_message_buffer_size); libspdm_xxx_decode_message (app_message_buffer, app_message_buffer_size, &spdm_message_buffer, &spdm_message_buffer_size); } The buffer usage of receiver_buffer and scratch_buffer is: ===== : SPDM message ***** : encrypted data $$$$$ : additional authenticated data (AAD) &&&&& : message authentication code (MAC) / TAG |<--- receiver_buffer_size --->| |<--- transport_message_buffer_size --->| |<--- secured_message_buffer_size --->| +--+-------------+$$$$$$$$$$$$$$$$$$$$+***************************+&&&+--------+--+ | | TransHdr | EncryptionHeader |AppHdr| SPDM |Random|MAC|AlignPad| | | | |SessionId|SeqNum|Len|AppLen| | | | | | | +--+-------------+$$$$$$$$$$$$$$$$$$$$+***************************+&&&+--------+--+ ^ ^ ^ | | | secured_message_buffer | | transport_message_buffer | receiver_buffer |<--- scratch_buffer_size --->| |<--- plain text size --->| |<-app_msg_s->| |<spdm>| +-------------------------------------+-------------+======+------+---------------+ | |EncHdr|AppHdr| SPDM |Random| | | |AppLen| | | | | +-------------------------------------+-------------+======+------+---------------+ ^ ^ ^ ^ | | | | spdm_message_buffer | | | app_message_buffer | | plain text | scratch_buffer
The buffers have the following properties:
- libspdm never writes data to the receive buffer so the buffer may be read-only.
- libspdm both reads from and writes to the send buffer. Note that in a future release libspdm may never read from the send buffer, allowing it to be write-only.
- libspdm always releases the send buffer before acquiring the receive buffer and releases the receive buffer before acquiring the send buffer. Because of this the send buffer and receive buffer may overlap or be the same buffer.
- libspdm assumes that, when populating the send buffer or parsing the receive buffer, both buffers cannot be modified by external agents. It is the library Integrator's responsibility to ensure that the buffers cannot be tampered with while libspdm is accessing them.
- If the buffers contain data that should not be shared with libspdm, the Integrator must erase or zeroize the buffers before granting access to libspdm.
-
spdm_lib_config.h provides an example of the configuration macros used in the libspdm library.
The Integrator can override the use of this file by defining the
LIBSPDM_CONFIG
macro. -
SPDM library depends upon the HAL library.
Sample implementations can be found at os_stub
10.1) cryptlib provides cryptography functions.
10.2) memlib provides memory operations.
10.3) debuglib provides debug functions.
10.4) requester library
10.4.1) timelib provides sleep function.
10.4.2) reqasymsignlib provides private key signing in a secure environment.
10.4.3) psklib provides PSK HMAC operation in a secure environment.
10.5) responder library
10.5.1) watchdoglib provides watchdog function.
10.5.2) asymsignlib provides private key signing in a secure environment.
10.5.3) psklib provides PSK HMAC operation in a secure environment.
10.5.4) measlib provides measurement collection.
10.5.5) csrlib provides CSR signing.
10.5.6) setcertlib provides certificate chain setting function.