SecurityPkg: add DeviceSecurity support

This patch implement the SpdmSecurityLib,
which is the core of DeviceSecurity.
And the SpdmSecurityLib include Device Authentication and Measurement.
The other library is to support SpdmSecurityLib.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Signed-off-by: Wenxing Hou <wenxing.hou@intel.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
This commit is contained in:
Wenxing Hou 2024-04-18 17:28:15 +08:00 committed by mergify[bot]
parent c3f615a1bd
commit 750d763623
32 changed files with 5611 additions and 6 deletions

View File

@ -0,0 +1,970 @@
/** @file
EDKII Device Security library for SPDM device.
It follows the SPDM Specification.
Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/BaseCryptLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include "hal/base.h"
#include "hal/library/cryptlib.h"
void *
libspdm_sha256_new (
void
)
{
size_t CtxSize;
void *HashCtx;
HashCtx = NULL;
CtxSize = Sha256GetContextSize ();
HashCtx = AllocatePool (CtxSize);
return HashCtx;
}
void
libspdm_sha256_free (
void *Sha256Ctx
)
{
if (Sha256Ctx != NULL) {
FreePool (Sha256Ctx);
Sha256Ctx = NULL;
}
}
bool
libspdm_sha256_init (
void *Sha256Ctx
)
{
return Sha256Init (Sha256Ctx);
}
bool
libspdm_sha256_duplicate (
const void *Sha256Context,
void *NewSha256Context
)
{
return Sha256Duplicate (Sha256Context, NewSha256Context);
}
bool
libspdm_sha256_update (
void *Sha256Context,
const void *Data,
size_t DataSize
)
{
return Sha256Update (Sha256Context, Data, DataSize);
}
bool
libspdm_sha256_final (
void *sha256_context,
uint8_t *hash_value
)
{
return Sha256Final (sha256_context, hash_value);
}
bool
libspdm_sha256_hash_all (
const void *data,
size_t data_size,
uint8_t *hash_value
)
{
return Sha256HashAll (data, data_size, hash_value);
}
void *
libspdm_sha384_new (
void
)
{
size_t CtxSize;
void *HashCtx;
HashCtx = NULL;
CtxSize = Sha384GetContextSize ();
HashCtx = AllocatePool (CtxSize);
return HashCtx;
}
void
libspdm_sha384_free (
void *Sha384Ctx
)
{
if (Sha384Ctx != NULL) {
FreePool (Sha384Ctx);
Sha384Ctx = NULL;
}
}
bool
libspdm_sha384_init (
void *sha384_context
)
{
return Sha384Init (sha384_context);
}
bool
libspdm_sha384_duplicate (
const void *sha384_context,
void *new_sha384_context
)
{
return Sha384Duplicate (sha384_context, new_sha384_context);
}
bool
libspdm_sha384_update (
void *sha384_context,
const void *data,
size_t data_size
)
{
return Sha384Update (sha384_context, data, data_size);
}
bool
libspdm_sha384_final (
void *sha384_context,
uint8_t *hash_value
)
{
return Sha384Final (sha384_context, hash_value);
}
bool
libspdm_sha384_hash_all (
const void *data,
size_t data_size,
uint8_t *hash_value
)
{
return Sha384HashAll (data, data_size, hash_value);
}
void *
libspdm_hmac_sha256_new (
void
)
{
return HmacSha256New ();
}
void
libspdm_hmac_sha256_free (
void *hmac_sha256_ctx
)
{
HmacSha256Free (hmac_sha256_ctx);
}
bool
libspdm_hmac_sha256_set_key (
void *hmac_sha256_ctx,
const uint8_t *key,
size_t key_size
)
{
return HmacSha256SetKey (hmac_sha256_ctx, key, key_size);
}
bool
libspdm_hmac_sha256_duplicate (
const void *hmac_sha256_ctx,
void *new_hmac_sha256_ctx
)
{
return HmacSha256Duplicate (hmac_sha256_ctx, new_hmac_sha256_ctx);
}
bool
libspdm_hmac_sha256_update (
void *hmac_sha256_ctx,
const void *data,
size_t data_size
)
{
return HmacSha256Update (hmac_sha256_ctx, data, data_size);
}
bool
libspdm_hmac_sha256_final (
void *hmac_sha256_ctx,
uint8_t *hmac_value
)
{
return HmacSha256Final (hmac_sha256_ctx, hmac_value);
}
bool
libspdm_hmac_sha256_all (
const void *data,
size_t data_size,
const uint8_t *key,
size_t key_size,
uint8_t *hmac_value
)
{
return HmacSha256All (data, data_size, key, key_size, hmac_value);
}
void *
libspdm_hmac_sha384_new (
void
)
{
return HmacSha384New ();
}
void
libspdm_hmac_sha384_free (
void *hmac_sha384_ctx
)
{
HmacSha384Free (hmac_sha384_ctx);
}
bool
libspdm_hmac_sha384_set_key (
void *hmac_sha384_ctx,
const uint8_t *key,
size_t key_size
)
{
return HmacSha384SetKey (hmac_sha384_ctx, key, key_size);
}
bool
libspdm_hmac_sha384_duplicate (
const void *hmac_sha384_ctx,
void *new_hmac_sha384_ctx
)
{
return HmacSha384Duplicate (hmac_sha384_ctx, new_hmac_sha384_ctx);
}
bool
libspdm_hmac_sha384_update (
void *hmac_sha384_ctx,
const void *data,
size_t data_size
)
{
return HmacSha384Update (hmac_sha384_ctx, data, data_size);
}
bool
libspdm_hmac_sha384_final (
void *hmac_sha384_ctx,
uint8_t *hmac_value
)
{
return HmacSha384Final (hmac_sha384_ctx, hmac_value);
}
bool
libspdm_hmac_sha384_all (
const void *data,
size_t data_size,
const uint8_t *key,
size_t key_size,
uint8_t *hmac_value
)
{
return HmacSha384All (data, data_size, key, key_size, hmac_value);
}
bool
libspdm_aead_aes_gcm_encrypt (
const uint8_t *key,
size_t key_size,
const uint8_t *iv,
size_t iv_size,
const uint8_t *a_data,
size_t a_data_size,
const uint8_t *data_in,
size_t data_in_size,
uint8_t *tag_out,
size_t tag_size,
uint8_t *data_out,
size_t *data_out_size
)
{
return AeadAesGcmEncrypt (
key,
key_size,
iv,
iv_size,
a_data,
a_data_size,
data_in,
data_in_size,
tag_out,
tag_size,
data_out,
data_out_size
);
}
bool
libspdm_aead_aes_gcm_decrypt (
const uint8_t *key,
size_t key_size,
const uint8_t *iv,
size_t iv_size,
const uint8_t *a_data,
size_t a_data_size,
const uint8_t *data_in,
size_t data_in_size,
const uint8_t *tag,
size_t tag_size,
uint8_t *data_out,
size_t *data_out_size
)
{
return AeadAesGcmDecrypt (
key,
key_size,
iv,
iv_size,
a_data,
a_data_size,
data_in,
data_in_size,
tag,
tag_size,
data_out,
data_out_size
);
}
void
libspdm_rsa_free (
void *rsa_context
)
{
RsaFree (rsa_context);
}
bool
libspdm_rsa_pkcs1_sign_with_nid (
void *rsa_context,
size_t hash_nid,
const uint8_t *message_hash,
size_t hash_size,
uint8_t *signature,
size_t *sig_size
)
{
switch (hash_nid) {
case CRYPTO_NID_SHA256:
if (hash_size != SHA256_DIGEST_SIZE) {
return FALSE;
}
break;
case CRYPTO_NID_SHA384:
if (hash_size != SHA384_DIGEST_SIZE) {
return FALSE;
}
break;
case CRYPTO_NID_SHA512:
if (hash_size != SHA512_DIGEST_SIZE) {
return FALSE;
}
break;
default:
return FALSE;
}
return RsaPkcs1Sign (
rsa_context,
message_hash,
hash_size,
signature,
sig_size
);
}
bool
libspdm_rsa_pkcs1_verify_with_nid (
void *rsa_context,
size_t hash_nid,
const uint8_t *message_hash,
size_t hash_size,
const uint8_t *signature,
size_t sig_size
)
{
switch (hash_nid) {
case CRYPTO_NID_SHA256:
if (hash_size != SHA256_DIGEST_SIZE) {
return false;
}
break;
case CRYPTO_NID_SHA384:
if (hash_size != SHA384_DIGEST_SIZE) {
return false;
}
break;
case CRYPTO_NID_SHA512:
if (hash_size != SHA512_DIGEST_SIZE) {
return false;
}
break;
default:
return false;
}
return RsaPkcs1Verify (
rsa_context,
message_hash,
hash_size,
signature,
sig_size
);
}
bool
libspdm_rsa_get_private_key_from_pem (
const uint8_t *pem_data,
size_t pem_size,
const char *password,
void **rsa_context
)
{
return RsaGetPrivateKeyFromPem (pem_data, pem_size, password, rsa_context);
}
bool
libspdm_rsa_get_public_key_from_x509 (
const uint8_t *cert,
size_t cert_size,
void **rsa_context
)
{
return RsaGetPublicKeyFromX509 (cert, cert_size, rsa_context);
}
bool
libspdm_ec_get_public_key_from_der (
const uint8_t *der_data,
size_t der_size,
void **ec_context
)
{
return false;
}
bool
libspdm_rsa_get_public_key_from_der (
const uint8_t *der_data,
size_t der_size,
void **rsa_context
)
{
return false;
}
bool
libspdm_ec_get_private_key_from_pem (
const uint8_t *pem_data,
size_t pem_size,
const char *password,
void **ec_context
)
{
return EcGetPrivateKeyFromPem (pem_data, pem_size, password, ec_context);
}
bool
libspdm_ec_get_public_key_from_x509 (
const uint8_t *cert,
size_t cert_size,
void **ec_context
)
{
return EcGetPublicKeyFromX509 (cert, cert_size, ec_context);
}
bool
libspdm_asn1_get_tag (
uint8_t **ptr,
const uint8_t *end,
size_t *length,
uint32_t tag
)
{
return Asn1GetTag (ptr, end, length, tag);
}
bool
libspdm_x509_get_subject_name (
const uint8_t *cert,
size_t cert_size,
uint8_t *cert_subject,
size_t *subject_size
)
{
return X509GetSubjectName (cert, cert_size, cert_subject, subject_size);
}
bool
libspdm_x509_get_common_name (
const uint8_t *cert,
size_t cert_size,
char *common_name,
size_t *common_name_size
)
{
EFI_STATUS Status;
Status = X509GetCommonName (cert, cert_size, common_name, common_name_size);
if (EFI_ERROR (Status)) {
return false;
} else {
return true;
}
}
bool
libspdm_x509_get_organization_name (
const uint8_t *cert,
size_t cert_size,
char *name_buffer,
size_t *name_buffer_size
)
{
EFI_STATUS Status;
Status = X509GetOrganizationName (cert, cert_size, name_buffer, name_buffer_size);
if (EFI_ERROR (Status)) {
return false;
} else {
return true;
}
}
bool
libspdm_x509_get_version (
const uint8_t *cert,
size_t cert_size,
size_t *version
)
{
return X509GetVersion (cert, cert_size, version);
}
bool
libspdm_x509_get_serial_number (
const uint8_t *cert,
size_t cert_size,
uint8_t *serial_number,
size_t *serial_number_size
)
{
return X509GetSerialNumber (cert, cert_size, serial_number, serial_number_size);
}
bool
libspdm_x509_get_issuer_name (
const uint8_t *cert,
size_t cert_size,
uint8_t *cert_issuer,
size_t *issuer_size
)
{
return X509GetIssuerName (cert, cert_size, cert_issuer, issuer_size);
}
bool
libspdm_x509_get_signature_algorithm (
const uint8_t *cert,
size_t cert_size,
uint8_t *oid,
size_t *oid_size
)
{
return X509GetSignatureAlgorithm (cert, cert_size, oid, oid_size);
}
bool
libspdm_x509_get_extension_data (
const uint8_t *cert,
size_t cert_size,
const uint8_t *oid,
size_t oid_size,
uint8_t *extension_data,
size_t *extension_data_size
)
{
return X509GetExtensionData (
cert,
cert_size,
oid,
oid_size,
extension_data,
extension_data_size
);
}
bool
libspdm_x509_get_validity (
const uint8_t *cert,
size_t cert_size,
uint8_t *from,
size_t *from_size,
uint8_t *to,
size_t *to_size
)
{
return X509GetValidity (cert, cert_size, from, from_size, to, to_size);
}
bool
libspdm_x509_set_date_time (
const char *date_time_str,
void *date_time,
size_t *date_time_size
)
{
return X509FormatDateTime (date_time_str, date_time, date_time_size);
}
int32_t
libspdm_x509_compare_date_time (
const void *date_time1,
const void *date_time2
)
{
return X509CompareDateTime (date_time1, date_time2);
}
bool
libspdm_x509_get_key_usage (
const uint8_t *cert,
size_t cert_size,
size_t *usage
)
{
return X509GetKeyUsage (cert, cert_size, usage);
}
bool
libspdm_x509_get_extended_key_usage (
const uint8_t *cert,
size_t cert_size,
uint8_t *usage,
size_t *usage_size
)
{
return X509GetExtendedKeyUsage (cert, cert_size, usage, usage_size);
}
bool
libspdm_x509_verify_cert (
const uint8_t *cert,
size_t cert_size,
const uint8_t *ca_cert,
size_t ca_cert_size
)
{
return X509VerifyCert (cert, cert_size, ca_cert, ca_cert_size);
}
bool
libspdm_x509_verify_cert_chain (
const uint8_t *root_cert,
size_t root_cert_length,
const uint8_t *cert_chain,
size_t cert_chain_length
)
{
return X509VerifyCertChain (root_cert, root_cert_length, cert_chain, cert_chain_length);
}
bool
libspdm_x509_get_cert_from_cert_chain (
const uint8_t *cert_chain,
size_t cert_chain_length,
const int32_t cert_index,
const uint8_t **cert,
size_t *cert_length
)
{
return X509GetCertFromCertChain (
cert_chain,
cert_chain_length,
cert_index,
cert,
cert_length
);
}
bool
libspdm_x509_construct_certificate (
const uint8_t *cert,
size_t cert_size,
uint8_t **single_x509_cert
)
{
return X509ConstructCertificate (cert, cert_size, single_x509_cert);
}
bool
libspdm_x509_get_extended_basic_constraints (
const uint8_t *cert,
size_t cert_size,
uint8_t *basic_constraints,
size_t *basic_constraints_size
)
{
return X509GetExtendedBasicConstraints (
cert,
cert_size,
basic_constraints,
basic_constraints_size
);
}
void *
libspdm_ec_new_by_nid (
size_t nid
)
{
return EcNewByNid (nid);
}
void
libspdm_ec_free (
void *ec_context
)
{
EcFree (ec_context);
}
bool
libspdm_ec_generate_key (
void *ec_context,
uint8_t *public_data,
size_t *public_size
)
{
return EcGenerateKey (ec_context, public_data, public_size);
}
bool
libspdm_ec_compute_key (
void *ec_context,
const uint8_t *peer_public,
size_t peer_public_size,
uint8_t *key,
size_t *key_size
)
{
return EcDhComputeKey (ec_context, peer_public, peer_public_size, NULL, key, key_size);
}
bool
libspdm_ecdsa_sign (
void *ec_context,
size_t hash_nid,
const uint8_t *message_hash,
size_t hash_size,
uint8_t *signature,
size_t *sig_size
)
{
return EcDsaSign (
ec_context,
hash_nid,
message_hash,
hash_size,
signature,
sig_size
);
}
bool
libspdm_ecdsa_verify (
void *ec_context,
size_t hash_nid,
const uint8_t *message_hash,
size_t hash_size,
const uint8_t *signature,
size_t sig_size
)
{
return EcDsaVerify (
ec_context,
hash_nid,
message_hash,
hash_size,
signature,
sig_size
);
}
bool
libspdm_random_bytes (
uint8_t *output,
size_t size
)
{
return RandomBytes (output, size);
}
bool
libspdm_hkdf_sha256_extract_and_expand (
const uint8_t *key,
size_t key_size,
const uint8_t *salt,
size_t salt_size,
const uint8_t *info,
size_t info_size,
uint8_t *out,
size_t out_size
)
{
return HkdfSha256ExtractAndExpand (
key,
key_size,
salt,
salt_size,
info,
info_size,
out,
out_size
);
}
bool
libspdm_hkdf_sha256_extract (
const uint8_t *key,
size_t key_size,
const uint8_t *salt,
size_t salt_size,
uint8_t *prk_out,
size_t prk_out_size
)
{
return HkdfSha256Extract (
key,
key_size,
salt,
salt_size,
prk_out,
prk_out_size
);
}
bool
libspdm_hkdf_sha256_expand (
const uint8_t *prk,
size_t prk_size,
const uint8_t *info,
size_t info_size,
uint8_t *out,
size_t out_size
)
{
return HkdfSha256Expand (
prk,
prk_size,
info,
info_size,
out,
out_size
);
}
bool
libspdm_hkdf_sha384_extract_and_expand (
const uint8_t *key,
size_t key_size,
const uint8_t *salt,
size_t salt_size,
const uint8_t *info,
size_t info_size,
uint8_t *out,
size_t out_size
)
{
return HkdfSha384ExtractAndExpand (
key,
key_size,
salt,
salt_size,
info,
info_size,
out,
out_size
);
}
bool
libspdm_hkdf_sha384_extract (
const uint8_t *key,
size_t key_size,
const uint8_t *salt,
size_t salt_size,
uint8_t *prk_out,
size_t prk_out_size
)
{
return HkdfSha384Extract (
key,
key_size,
salt,
salt_size,
prk_out,
prk_out_size
);
}
bool
libspdm_hkdf_sha384_expand (
const uint8_t *prk,
size_t prk_size,
const uint8_t *info,
size_t info_size,
uint8_t *out,
size_t out_size
)
{
return HkdfSha384Expand (
prk,
prk_size,
info,
info_size,
out,
out_size
);
}

View File

@ -0,0 +1,38 @@
## @file
# SPDM library.
#
# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = CryptlibWrapper
FILE_GUID = 156C1B1B-6C2F-496a-496A-0548D1A9ED5B
MODULE_TYPE = BASE
VERSION_STRING = 1.0
LIBRARY_CLASS = CryptlibWrapper
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 AARCH64
#
[Sources]
CryptlibWrapper.c
[Packages]
MdePkg/MdePkg.dec
SecurityPkg/SecurityPkg.dec
CryptoPkg/CryptoPkg.dec
[LibraryClasses]
BaseLib
BaseMemoryLib
MemoryAllocationLib
DebugLib
BaseCryptLib
RngLib

View File

@ -0,0 +1,177 @@
/** @file
EDKII Device Security library for SPDM device.
It follows the SPDM Specification.
Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
#include "hal/base.h"
#include "hal/library/memlib.h"
/**
* Copies bytes from a source buffer to a destination buffer.
*
* This function copies "src_len" bytes from "src_buf" to "dst_buf".
*
* Asserts and returns a non-zero value if any of the following are true:
* 1) "src_buf" or "dst_buf" are NULL.
* 2) "src_len" or "dst_len" is greater than (SIZE_MAX >> 1).
* 3) "src_len" is greater than "dst_len".
* 4) "src_buf" and "dst_buf" overlap.
*
* If any of these cases fail, a non-zero value is returned. Additionally if
* "dst_buf" points to a non-NULL value and "dst_len" is valid, then "dst_len"
* bytes of "dst_buf" are zeroed.
*
* This function follows the C11 cppreference description of memcpy_s.
* https://en.cppreference.com/w/c/string/byte/memcpy
* The cppreferece description does NOT allow the source or destination
* buffers to be NULL.
*
* This function differs from the Microsoft and Safeclib memcpy_s implementations
* in that the Microsoft and Safeclib implementations allow for NULL source and
* destinations pointers when the number of bytes to copy (src_len) is zero.
*
* In addition the Microsoft and Safeclib memcpy_s functions return different
* negative values on error. For best support, clients should generally check
* against zero for success or failure.
*
* @param dst_buf Destination buffer to copy to.
* @param dst_len Maximum length in bytes of the destination buffer.
* @param src_buf Source buffer to copy from.
* @param src_len The number of bytes to copy from the source buffer.
*
* @return 0 on success. non-zero on error.
*
**/
void
libspdm_copy_mem (
void *dst_buf,
size_t dst_len,
const void *src_buf,
size_t src_len
)
{
volatile uint8_t *dst;
const volatile uint8_t *src;
dst = (volatile uint8_t *)dst_buf;
src = (const volatile uint8_t *)src_buf;
/* Check for case where "dst" or "dst_len" may be invalid.
* Do not zero "dst" in this case. */
if ((dst == NULL) || (dst_len > (SIZE_MAX >> 1))) {
ASSERT (0);
}
/* Gaurd against invalid source. Zero "dst" in this case. */
if (src == NULL) {
ZeroMem (dst_buf, dst_len);
ASSERT (0);
}
/* Guard against overlap case. Zero "dst" in these cases. */
if (((src < dst) && (src + src_len > dst)) || ((dst < src) && (dst + src_len > src))) {
ZeroMem (dst_buf, dst_len);
ASSERT (0);
}
/* Guard against invalid lengths. Zero "dst" in these cases. */
if ((src_len > dst_len) ||
(src_len > (SIZE_MAX >> 1)))
{
ZeroMem (dst_buf, dst_len);
ASSERT (0);
}
while (src_len-- != 0) {
*(dst++) = *(src++);
}
}
/**
* Fills a target buffer with a byte value, and returns the target buffer.
*
* This function fills length bytes of buffer with value, and returns buffer.
*
* If length is greater than (MAX_ADDRESS - buffer + 1), then ASSERT().
*
* @param buffer The memory to set.
* @param length The number of bytes to set.
* @param value The value with which to fill length bytes of buffer.
*
* @return buffer.
*
**/
void
libspdm_set_mem (
void *buffer,
size_t length,
uint8_t value
)
{
SetMem (buffer, length, value);
}
/**
* Fills a target buffer with zeros, and returns the target buffer.
*
* This function fills length bytes of buffer with zeros, and returns buffer.
*
* If length > 0 and buffer is NULL, then ASSERT().
* If length is greater than (MAX_ADDRESS - buffer + 1), then ASSERT().
*
* @param buffer The pointer to the target buffer to fill with zeros.
* @param length The number of bytes in buffer to fill with zeros.
*
* @return buffer.
*
**/
void
libspdm_zero_mem (
void *buffer,
size_t length
)
{
ZeroMem (buffer, length);
}
/**
* Compares the contents of two buffers in const time.
*
* This function compares length bytes of source_buffer to length bytes of destination_buffer.
* If all length bytes of the two buffers are identical, then 0 is returned. Otherwise, the
* value returned is the first mismatched byte in source_buffer subtracted from the first
* mismatched byte in destination_buffer.
*
* If length > 0 and destination_buffer is NULL, then ASSERT().
* If length > 0 and source_buffer is NULL, then ASSERT().
* If length is greater than (MAX_ADDRESS - destination_buffer + 1), then ASSERT().
* If length is greater than (MAX_ADDRESS - source_buffer + 1), then ASSERT().
*
* @param destination_buffer A pointer to the destination buffer to compare.
* @param source_buffer A pointer to the source buffer to compare.
* @param length The number of bytes to compare.
*
* @return 0 All length bytes of the two buffers are identical.
* @retval Non-zero There is mismatched between source_buffer and destination_buffer.
*
**/
bool
libspdm_consttime_is_mem_equal (
const void *destination_buffer,
const void *source_buffer,
size_t length
)
{
if (CompareMem (destination_buffer, source_buffer, length) == 0) {
return true;
} else {
return false;
}
}

View File

@ -0,0 +1,33 @@
## @file
# SPDM library.
#
# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = MemLibWrapper
FILE_GUID = d97bb726-6640-47dc-ae00-0cf2fbfb60f0
MODULE_TYPE = BASE
VERSION_STRING = 1.0
LIBRARY_CLASS = MemLibWrapper
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 AARCH64
#
[Sources]
MemLibWrapper.c
[Packages]
MdePkg/MdePkg.dec
SecurityPkg/SecurityPkg.dec
[LibraryClasses]
BaseLib
DebugLib

View File

@ -0,0 +1,85 @@
/** @file
EDKII Device Security library for SPDM device.
It follows the SPDM Specification.
Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include "hal/base.h"
/**
* Suspends the execution of the current thread until the time-out interval elapses.
*
* @param milliseconds The time interval for which execution is to be suspended, in milliseconds.
*
**/
void
libspdm_sleep (
uint64_t milliseconds
)
{
return;
}
/**
* Suspends the execution of the current thread until the time-out interval elapses.
*
* @param microseconds The time interval for which execution is to be suspended, in milliseconds.
*
**/
void
libspdm_sleep_in_us (
uint64_t microseconds
)
{
return;
}
/**
* If no heartbeat arrives in seconds, the watchdog timeout event
* should terminate the session.
*
* @param session_id Indicate the SPDM session ID.
* @param seconds heartbeat period, in seconds.
*
**/
bool
libspdm_start_watchdog (
uint32_t session_id,
uint16_t seconds
)
{
return true;
}
/**
* stop watchdog.
*
* @param session_id Indicate the SPDM session ID.
*
**/
bool
libspdm_stop_watchdog (
uint32_t session_id
)
{
return true;
}
/**
* Reset the watchdog in heartbeat response.
*
* @param session_id Indicate the SPDM session ID.
*
**/
bool
libspdm_reset_watchdog (
uint32_t session_id
)
{
return true;
}

View File

@ -0,0 +1,33 @@
## @file
# SPDM library.
#
# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = PlatformLibWrapper
FILE_GUID = 2f8979d1-f9f0-4d51-9cbd-4f41dee59057
MODULE_TYPE = BASE
VERSION_STRING = 1.0
LIBRARY_CLASS = PlatformLibWrapper
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 AARCH64
#
[Sources]
PlatformLibWrapper.c
[Packages]
MdePkg/MdePkg.dec
SecurityPkg/SecurityPkg.dec
[LibraryClasses]
BaseLib
DebugLib

View File

@ -0,0 +1,347 @@
/** @file
Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef __LIBSPDM_STUB_H__
#define __LIBSPDM_STUB_H__
#include <library/spdm_common_lib.h>
#include <library/spdm_return_status.h>
#include <library/spdm_crypt_lib.h>
#include <library/spdm_requester_lib.h>
#include <library/spdm_responder_lib.h>
#include <library/spdm_transport_pcidoe_lib.h>
#pragma pack(1)
/* The layout of SPDM_RETURN is
* [31:28] - Severity
* [27:24] - Reserved
* [23:16] - Source
* [15:00] - Code
*/
typedef UINT32 SPDM_RETURN;
/*Interface of spdm.h*/
/* SPDM message header*/
typedef struct {
UINT8 SPDMVersion;
UINT8 RequestResponseCode;
UINT8 Param1;
UINT8 Param2;
} SPDM_MESSAGE_HEADER;
/* SPDM VERSION structure
* Bit[15:12] MajorVersion
* Bit[11:8] MinorVersion
* Bit[7:4] UpdateVersionNumber
* Bit[3:0] Alpha*/
typedef UINT16 SPDM_VERSION_NUMBER;
typedef struct {
/* Total length of the certificate chain, in bytes,
* including all fields in this table.*/
UINT16 Length;
UINT16 Reserved;
/* digest of the Root Certificate.
* Note that Root Certificate is ASN.1 DER-encoded for this digest.
* The hash size is determined by the SPDM device.*/
/*UINT8 RootHash[HashSize];*/
/* One or more ASN.1 DER-encoded X509v3 certificates where the first certificate is signed by the Root
* Certificate or is the Root Certificate itself and each subsequent certificate is signed by the preceding
* certificate. The last certificate is the Leaf Certificate.*/
/*UINT8 Certificates[length - 4 - HashSize];*/
} SPDM_CERT_CHAIN;
/* SPDM MEASUREMENTS block common header */
typedef struct {
UINT8 Index;
UINT8 MeasurementSpecification;
UINT16 MeasurementSize;
/*UINT8 Measurement[MeasurementSize];*/
} SPDM_MEASUREMENT_BLOCK_COMMON_HEADER;
/* SPDM MEASUREMENTS block DMTF header */
typedef struct {
UINT8 DMTFSpecMeasurementValueType;
UINT16 DMTFSpecMeasurementValueSize;
/*UINT8 DMTFSpecMeasurementValue[DMTFSpecMeasurementValueSize];*/
} SPDM_MEASUREMENT_BLOCK_DMTF_HEADER;
typedef struct {
SPDM_MEASUREMENT_BLOCK_COMMON_HEADER MeasurementBlockCommonHeader;
SPDM_MEASUREMENT_BLOCK_DMTF_HEADER MeasurementBlockDmtfHeader;
/*UINT8 HashValue[HashSize];*/
} SPDM_MEASUREMENT_BLOCK_DMTF;
#define SPDM_DATA_PARAMETER libspdm_data_parameter_t
typedef enum {
//
// SPDM parameter
//
SpdmDataSpdmVersion,
SpdmDataSecuredMessageVersion,
//
// SPDM capability
//
SpdmDataCapabilityFlags,
SpdmDataCapabilityCTExponent,
SpdmDataCapabilityRttUs,
SpdmDataCapabilityDataTransferSize,
SpdmDataCapabilityMaxSpdmMsgSize,
SpdmDataCapabilitySenderDataTransferSize,
//
// SPDM Algorithm setting
//
SpdmDataMeasurementSpec,
SpdmDataMeasurementHashAlgo,
SpdmDataBaseAsymAlgo,
SpdmDataBaseHashAlgo,
SpdmDataDHENameGroup,
SpdmDataAEADCipherSuite,
SpdmDataReqBaseAsymAlg,
SpdmDataKeySchedule,
SpdmDataOtherParamsSupport,
SpdmDataMelSpec,
//
// Connection State
//
SpdmDataConnectionState,
//
// ResponseState
//
SpdmDataResponseState,
//
// Certificate info
//
SpdmDataLocalPublicCertChain,
SpdmDataPeerPublicRootCert,
SpdmDataPeerPublicKey,
SpdmDataLocalPublicKey,
SpdmDataLocalSupportedSlotMask,
SpdmDataLocalKeyPairId,
SpdmDataLocalCertInfo,
SpdmDataLocalKeyUsageBitMask,
SpdmDataBasicMutAuthRequested,
SpdmDataMutAuthRequested,
SpdmDataHeartBeatPeriod,
//
// Negotiated result
//
SpdmDataPeerUsedCertChainBuffer,
SpdmDataPeerSlotMask,
SpdmDataPeerProvisionedSlotMask = SpdmDataPeerSlotMask,
SpdmDataPeerSupportedSlotMask,
SpdmDataPeerTotalDigestBuffer,
SpdmDataPeerKeyPairId,
SpdmDataPeerCertInfo,
SpdmDataPeerKeyUsageBitMask,
//
// Pre-shared Key Hint
// If PSK is present, then PSK_EXCHANGE is used.
// Otherwise, the KEY_EXCHANGE is used.
//
SpdmDataPskHint,
//
// SessionData
//
SpdmDataSessionUsePsk,
SpdmDataSessionMutAuthRequested,
SpdmDataSessionEndSessionAttributes,
SpdmDataSessionPolicy,
SpdmDataAppContextData,
SpdmDataHandleErrorReturnPolicy,
/* VCA cached for CACHE_CAP in 1.2 for transcript.*/
SpdmDataVcaCache,
/* if the context is for a requester. It only needs to be set in VCA cache.*/
SpdmDataIsRequester,
// If the Responder replies with a Busy `ERROR` response to a request
// then the Requester is free to retry sending the request.
// This value specifies the maximum number of times libspdm will retry
// sending the request before returning an error.
// If its value is 0 then libspdm will not send any retry requests.
SpdmDataRequestRetryTimes,
// If the Responder replies with a Busy `ERROR` response to a request
// then the Requester is free to retry sending the request.
// This value specifies the delay time in microseconds between each retry requests.
// If its value is 0 then libspdm will send retry request immediately.
SpdmDataRequestRetryDelayTime,
/* limit the number of DHE session and PSK session separately.*/
SpdmDataMaxDheSessionConut,
SpdmDataMaxPskSessionConut,
SpdmDataSessionSequenceNumberRspDir,
SpdmDataSessionSequenceNumberReqDir,
SpdmDataMaxSessionSequenceNumber,
/* For SPDM 1.0 and 1.1, allow signature verification in big, little, or both endians. */
SpdmDataSpdmVersion1011VerifySigatureEndian,
SpdmDataSequenceNumberEndian,
SpdmDataSessionSequenceNumberEndian,
SpdmDataMultiKeyConnReq,
SpdmDataMultiKeyConnRsp,
//
// MAX
//
SpdmDataMax,
} SPDM_DATA_TYPE;
typedef enum {
SpdmDataLocationLocal,
SpdmDataLocationConnection,
SpdmDataLocationSession,
SpdmDataLocationMax,
} SPDM_DATA_LOCATION;
typedef enum {
//
// Before GET_VERSION/VERSION
//
SpdmConnectionStateNotStarted,
//
// After GET_VERSION/VERSION
//
SpdmConnectionStateAfterVersion,
//
// After GET_CAPABILITIES/CAPABILITIES
//
SpdmConnectionStateAfterCapabilities,
//
// After NEGOTIATE_ALGORITHMS/ALGORITHMS
//
SpdmConnectionStateNegotiated,
//
// After GET_DIGESTS/DIGESTS
//
SpdmConnectionStateAfterDigests,
//
// After GET_CERTIFICATE/CERTIFICATE
//
SpdmConnectionStateAfterCertificate,
//
// After CHALLENGE/CHALLENGE_AUTH, and ENCAP CALLENGE/CHALLENG_AUTH if MUT_AUTH is enabled.
//
SpdmConnectionStateAuthenticated,
//
// MAX
//
SpdmConnectionStateMax,
} SPDM_CONNECTION_STATE;
typedef enum {
//
// Normal response.
//
SpdmResponseStateNormal,
//
// Other component is busy.
//
SpdmResponseStateBusy,
#if LIBSPDM_RESPOND_IF_READY_SUPPORT
//
// Hardware is not ready.
//
SpdmResponseStateNotReady,
#endif /* LIBSPDM_RESPOND_IF_READY_SUPPORT */
//
// Firmware Update is done. Need resync.
//
SpdmResponseStateNeedResync,
//
// Processing Encapsulated message.
//
SpdmResponseStateProcessingEncap,
//
// MAX
//
SpdmResponseStateMax,
} SPDM_RESPONSE_STATE;
/* DOE header*/
typedef struct {
UINT16 VendorId;
UINT8 DataObjectType;
UINT8 Reserved;
/* length of the data object being transfered in number of DW, including the header (2 DW)
* It only includes bit[0~17], bit[18~31] are reserved.
* A value of 00000h indicate 2^18 DW == 2^20 byte.*/
UINT32 Length;
/*UINT32 DataObjectDw[Length];*/
} PCI_DOE_DATA_OBJECT_HEADER;
#pragma pack()
/* FUNCTION */
#define SpdmSetData libspdm_set_data
#define SpdmGetData libspdm_get_data
#define SpdmInitContext libspdm_init_context
#define SpdmGetContextSize libspdm_get_context_size
#define SpdmRegisterDeviceIoFunc libspdm_register_device_io_func
#define SpdmRegisterTransportLayerFunc libspdm_register_transport_layer_func
#define SpdmGetSizeofRequiredScratchBuffer libspdm_get_sizeof_required_scratch_buffer
#define SpdmRegisterDeviceBufferFunc libspdm_register_device_buffer_func
#define SpdmSetScratchBuffer libspdm_set_scratch_buffer
#define SpdmGetHashSize libspdm_get_hash_size
#define SpdmHashAll libspdm_hash_all
#define SpdmGetMeasurementHashSize libspdm_get_measurement_hash_size
#define SpdmMeasurementHashAll libspdm_measurement_hash_all
#define SpdmHmacAll libspdm_hmac_all
#define SpdmHkdfExpand libspdm_hkdf_expand
#define SpdmAsymFree libspdm_asym_free
#define SpdmAsymGetPrivateKeyFromPem libspdm_asym_get_private_key_from_pem
#define SpdmAsymSign libspdm_asym_sign
#define SpdmAsymSignHash libspdm_asym_sign_hash
#define SpdmInitConnection libspdm_init_connection
#define SpdmGetDigest libspdm_get_digest
#define SpdmGetCertificate libspdm_get_certificate
#define SpdmGetCertificateEx libspdm_get_certificate_ex
#define SpdmChallenge libspdm_challenge
#define SpdmChallengeEx libspdm_challenge_ex
#define SpdmGetMeasurement libspdm_get_measurement
#define SpdmGetMeasurementEx libspdm_get_measurement_ex
#define SpdmStartSession libspdm_start_session
#define SpdmStopSession libspdm_stop_session
#define SpdmSendReceiveData libspdm_send_receive_data
#define SpdmRegisterGetResponseFunc libspdm_register_get_response_func
#define SpdmProcessRequest libspdm_process_request
#define SpdmBuildResponse libspdm_build_response
#define SpdmGenerateErrorResponse libspdm_generate_error_response
#define SpdmTransportPciDoeEncodeMessage libspdm_transport_pci_doe_encode_message
#define SpdmTransportPciDoeDecodeMessage libspdm_transport_pci_doe_decode_message
#define SpdmMeasurementCollectionFunc libspdm_measurement_collection
#define SpdmRequesterDataSignFunc libspdm_requester_data_sign
#define SpdmResponderDataSignFunc libspdm_responder_data_sign
#define SpdmGenerateMeasurementSummaryHash libspdm_generate_measurement_summary_hash
#define SpdmPskMasterSecretHkdfExpandFunc libspdm_psk_master_secret_hkdf_expand
#define SpdmPskHandshakeSecretHkdfExpandFunc libspdm_psk_handshake_secret_hkdf_expand
#define SpdmMeasurementOpaqueData libspdm_measurement_opaque_data
#define SpdmChallengeOpaqueData libspdm_challenge_opaque_data
#endif

View File

@ -0,0 +1,23 @@
/** @file
EDKII Device Security library for SPDM device.
It follows the SPDM Specification.
Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef LIBSPDM_STDBOOL_ALT_H
#define LIBSPDM_STDBOOL_ALT_H
typedef BOOLEAN bool;
#ifndef true
#define true TRUE
#endif
#ifndef false
#define false FALSE
#endif
#endif /* LIBSPDM_STDBOOL_ALT */

View File

@ -0,0 +1,16 @@
/** @file
EDKII Device Security library for SPDM device.
It follows the SPDM Specification.
Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef LIBSPDM_STD_DEF_ALT_H
#define LIBSPDM_STD_DEF_ALT_H
typedef UINTN size_t;
#define offsetof(type, member) OFFSET_OF(type,member)
#endif /* LIBSPDM_STDDEF_ALT */

View File

@ -0,0 +1,25 @@
/** @file
EDKII Device Security library for SPDM device.
It follows the SPDM Specification.
Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef LIBSPDM_STD_INT_ALT_H
#define LIBSPDM_STD_INT_ALT_H
typedef UINT64 uint64_t;
typedef INT64 int64_t;
typedef UINT32 uint32_t;
typedef INT32 int32_t;
typedef UINT16 uint16_t;
typedef INT16 int16_t;
typedef UINT8 uint8_t;
#ifndef SIZE_MAX
#define SIZE_MAX MAX_UINTN
#endif
#endif /* LIBSPDM_STDINT_ALT */

View File

@ -0,0 +1,94 @@
/** @file
EDKII Device Security library for SPDM device.
It follows the SPDM Specification.
Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef BASE_H
#define BASE_H
#define LIBSPDM_STDINT_ALT "hal/LibspdmStdIntAlt.h"
#define LIBSPDM_STDBOOL_ALT "hal/LibspdmStdBoolAlt.h"
#define LIBSPDM_STDDEF_ALT "hal/LibspdmStdDefAlt.h"
#ifndef LIBSPDM_STDINT_ALT
#include <stdint.h>
/* LIBSPDM_OPENSSL_STDINT_WORKAROUND */
/* This is a workaround for OpenSSL compilation problems when used with <stdint.h>
* on Windows platforms built with Visual Studio. Including <stdint.h> pulls in
* <vcruntime.h>, which causes the type size_t to be defined. The size_t type
* depends on if _WIN32 or _WIN64 is defined. The default if neither is defined
* is the 32-bit version of size_t. */
/* Our OpenSSL compilation requires _WIN32 and _WIN64 to NOT be defined.
* This will force the <vcruntime.h> to use the wrong 32-bit definition of size_t
* if we are compiling as 64-bit. This 32-bit definition then does not agree with
* the 64-bit definition defined in libspdm and generates compile errors. */
/* To workaround this issue, LIBSPDM_OPENSSL_STDINT_WORKAROUND was created
* that is only defined for compilation via tha makefile of the OpenSSL library
* portion of libspdm. */
/* This will lead to _WIN32 and _WIN64 to be NOT defined when reaching the OpenSSL
* portions of a compilation unit (header files + c file), thus meeting the
* no Win32/Win64 requirement for OpenSSL, but will still be defined when compiling
* the <vcruntime.h> file in the compilation unit (and getting the right size_t). */
/* In the future libspdm intends to use the Windows native compilation flags and defines,
* in place of the UEFI profile / personality. */
#ifdef LIBSPDM_OPENSSL_STDINT_WORKAROUND
#undef _WIN32
#undef _WIN64
#endif
#else /* LIBSPDM_STDINT_ALT */
#include LIBSPDM_STDINT_ALT
#endif /* LIBSPDM_STDINT_ALT */
#ifndef LIBSPDM_STDBOOL_ALT
#include <stdbool.h>
#else
#include LIBSPDM_STDBOOL_ALT
#endif
#ifndef LIBSPDM_STDDEF_ALT
#include <stddef.h>
#else
#include LIBSPDM_STDDEF_ALT
#endif
/**
* Return the minimum of two operands.
*
* This macro returns the minimal of two operand specified by a and b.
* Both a and b must be the same numerical types, signed or unsigned.
*
* @param a The first operand with any numerical type.
* @param b The second operand. It should be the same any numerical type with a.
*
* @return Minimum of two operands.
*
**/
#define LIBSPDM_MIN(a, b) (((a) < (b)) ? (a) : (b))
/**
* Return the number of elements in an array.
*
* @param array An object of array type. Array is only used as an argument to
* the sizeof operator, therefore Array is never evaluated. The
* caller is responsible for ensuring that Array's type is not
* incomplete; that is, Array must have known constant size.
*
* @return The number of elements in Array. The result has type size_t.
*
**/
#define LIBSPDM_ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
#endif /* BASE_H */

View File

@ -0,0 +1,39 @@
/** @file
EDKII Device Security library for SPDM device.
It follows the SPDM Specification.
Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
/** @file
Provides services to print debug and assert messages to a debug output device.
The Debug library supports debug print and asserts based on a combination of macros and code.
The debug library can be turned on and off so that the debug code does not increase the size of an image.
Note that a reserved macro named MDEPKG_NDEBUG is introduced for the intention
of size reduction when compiler optimization is disabled. If MDEPKG_NDEBUG is
defined, then debug and assert related macros wrapped by it are the NULL implementations.
**/
#ifndef DEBUG_LIB_H
#define DEBUG_LIB_H
#include <Library/DebugLib.h>
#define LIBSPDM_DEBUG_INFO DEBUG_INFO
#define LIBSPDM_DEBUG_VERBOSE DEBUG_VERBOSE
#define LIBSPDM_DEBUG_ERROR DEBUG_ERROR
#define LIBSPDM_DEBUG DEBUG
#define LIBSPDM_ASSERT ASSERT
#define LIBSPDM_ASSERT_RETURN_ERROR ASSERT_RETURN_ERROR
#define LIBSPDM_DEBUG_CODE_BEGIN DEBUG_CODE_BEGIN
#define LIBSPDM_DEBUG_CODE_END DEBUG_CODE_END
#define LIBSPDM_DEBUG_CODE DEBUG_CODE
#endif /* DEBUG_LIB_H */

View File

@ -0,0 +1,394 @@
/** @file
EDKII Device Security library for SPDM device.
It follows the SPDM Specification.
Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef SPDM_LIB_CONFIG_H
#define SPDM_LIB_CONFIG_H
/* Enables assertions and debug printing. When `LIBSPDM_DEBUG_ENABLE` is defined it overrides or
* sets the values of `LIBSPDM_DEBUG_PRINT_ENABLE`, `LIBSPDM_DEBUG_ASSERT_ENABLE`, and
* `LIBSPDM_BLOCK_ENABLE` to the value of `LIBSPDM_DEBUG_ENABLE`.
*
* Note that if this file is used with CMake and `DTARGET=Release` is defined, then all debugging
* is disabled.
*/
#ifndef LIBSPDM_DEBUG_ENABLE
#define LIBSPDM_DEBUG_ENABLE 1
#endif
/* The SPDM specification allows a Responder to return up to 256 version entries in the `VERSION`
* response to the Requester, including duplicate entries. For a Requester this value specifies the
* maximum number of entries that libspdm will tolerate in a `VERSION` response before returning an
* error. A similiar macro, `SPDM_MAX_VERSION_COUNT`, exists for the Responder. However this macro
* is not meant to be configured by the integrator.
*/
#ifndef LIBSPDM_MAX_VERSION_COUNT
#define LIBSPDM_MAX_VERSION_COUNT 5
#endif
/* This value specifies the maximum size, in bytes, of the `PSK_EXCHANGE.RequesterContext` and,
* if supported by the Responder, `PSK_EXCHANGE_RSP.ResponderContext` fields. The fields are
* typically random or monotonically increasing numbers.
*/
#ifndef LIBSPDM_PSK_CONTEXT_LENGTH
#define LIBSPDM_PSK_CONTEXT_LENGTH LIBSPDM_MAX_HASH_SIZE
#endif
/* This value specifies the maximum size, in bytes, of the `PSK_EXCHANGE.PSKHint` field.*/
#ifndef LIBSPDM_PSK_MAX_HINT_LENGTH
#define LIBSPDM_PSK_MAX_HINT_LENGTH 16
#endif
/* libspdm allows an integrator to specify multiple root certificates as trust anchors when
* verifying certificate chains from an endpoint. This value specifies the maximum number of root
* certificates that libspdm can support.
*/
#ifndef LIBSPDM_MAX_ROOT_CERT_SUPPORT
#define LIBSPDM_MAX_ROOT_CERT_SUPPORT 10
#endif
/* If the Responder supports it a Requester is allowed to establish multiple secure sessions with
* the Responder. This value specifies the maximum number of sessions libspdm can support.
*/
#ifndef LIBSPDM_MAX_SESSION_COUNT
#define LIBSPDM_MAX_SESSION_COUNT 4
#endif
/* This value specifies the maximum size, in bytes, of a certificate chain that can be stored in a
* libspdm context.
*/
#ifndef LIBSPDM_MAX_CERT_CHAIN_SIZE
#define LIBSPDM_MAX_CERT_CHAIN_SIZE 0x1000
#endif
#ifndef LIBSPDM_MAX_MEASUREMENT_RECORD_SIZE
#define LIBSPDM_MAX_MEASUREMENT_RECORD_SIZE 0x1000
#endif
/* Partial certificates can be retrieved from a Requester or Responder and through multiple messages
* the complete certificate chain can be constructed. This value specifies the maximum size,
* in bytes, of a partial certificate that can be sent or received.
*/
#ifndef LIBSPDM_MAX_CERT_CHAIN_BLOCK_LEN
#define LIBSPDM_MAX_CERT_CHAIN_BLOCK_LEN 1024
#endif
/* To ensure integrity in communication between the Requester and the Responder libspdm calculates
* cryptographic digests and signatures over multiple requests and responses. This value specifies
* whether libspdm will use a running calculation over the transcript, where requests and responses
* are discarded as they are cryptographically consumed, or whether libspdm will buffer the entire
* transcript before calculating the digest or signature.
*/
#ifndef LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
#define LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT 0
#endif
/* Cryptography Configuration
* In each category, at least one should be selected.
* NOTE: Not all combination can be supported. E.g. Don't mix NIST algo with SMx.*/
#ifndef LIBSPDM_RSA_SSA_2048_SUPPORT
#define LIBSPDM_RSA_SSA_2048_SUPPORT 1
#endif
#ifndef LIBSPDM_RSA_SSA_3072_SUPPORT
#define LIBSPDM_RSA_SSA_3072_SUPPORT 1
#endif
#ifndef LIBSPDM_RSA_SSA_4096_SUPPORT
#define LIBSPDM_RSA_SSA_4096_SUPPORT 1
#endif
#ifndef LIBSPDM_RSA_PSS_2048_SUPPORT
#define LIBSPDM_RSA_PSS_2048_SUPPORT 0
#endif
#ifndef LIBSPDM_RSA_PSS_3072_SUPPORT
#define LIBSPDM_RSA_PSS_3072_SUPPORT 0
#endif
#ifndef LIBSPDM_RSA_PSS_4096_SUPPORT
#define LIBSPDM_RSA_PSS_4096_SUPPORT 0
#endif
#ifndef LIBSPDM_ECDSA_P256_SUPPORT
#define LIBSPDM_ECDSA_P256_SUPPORT 1
#endif
#ifndef LIBSPDM_ECDSA_P384_SUPPORT
#define LIBSPDM_ECDSA_P384_SUPPORT 1
#endif
#ifndef LIBSPDM_ECDSA_P521_SUPPORT
#define LIBSPDM_ECDSA_P521_SUPPORT 1
#endif
#ifndef LIBSPDM_SM2_DSA_P256_SUPPORT
#define LIBSPDM_SM2_DSA_P256_SUPPORT 0
#endif
#ifndef LIBSPDM_EDDSA_ED25519_SUPPORT
#define LIBSPDM_EDDSA_ED25519_SUPPORT 0
#endif
#ifndef LIBSPDM_EDDSA_ED448_SUPPORT
#define LIBSPDM_EDDSA_ED448_SUPPORT 0
#endif
#ifndef LIBSPDM_FFDHE_2048_SUPPORT
#define LIBSPDM_FFDHE_2048_SUPPORT 0
#endif
#ifndef LIBSPDM_FFDHE_3072_SUPPORT
#define LIBSPDM_FFDHE_3072_SUPPORT 0
#endif
#ifndef LIBSPDM_FFDHE_4096_SUPPORT
#define LIBSPDM_FFDHE_4096_SUPPORT 0
#endif
#ifndef LIBSPDM_ECDHE_P256_SUPPORT
#define LIBSPDM_ECDHE_P256_SUPPORT 1
#endif
#ifndef LIBSPDM_ECDHE_P384_SUPPORT
#define LIBSPDM_ECDHE_P384_SUPPORT 1
#endif
#ifndef LIBSPDM_ECDHE_P521_SUPPORT
#define LIBSPDM_ECDHE_P521_SUPPORT 1
#endif
#ifndef LIBSPDM_SM2_KEY_EXCHANGE_P256_SUPPORT
#define LIBSPDM_SM2_KEY_EXCHANGE_P256_SUPPORT 0
#endif
#ifndef LIBSPDM_AEAD_AES_128_GCM_SUPPORT
#define LIBSPDM_AEAD_AES_128_GCM_SUPPORT 1
#endif
#ifndef LIBSPDM_AEAD_AES_256_GCM_SUPPORT
#define LIBSPDM_AEAD_AES_256_GCM_SUPPORT 1
#endif
#ifndef LIBSPDM_AEAD_CHACHA20_POLY1305_SUPPORT
#define LIBSPDM_AEAD_CHACHA20_POLY1305_SUPPORT 0
#endif
#ifndef LIBSPDM_AEAD_SM4_128_GCM_SUPPORT
#define LIBSPDM_AEAD_SM4_128_GCM_SUPPORT 0
#endif
#ifndef LIBSPDM_SHA256_SUPPORT
#define LIBSPDM_SHA256_SUPPORT 1
#endif
#ifndef LIBSPDM_SHA384_SUPPORT
#define LIBSPDM_SHA384_SUPPORT 1
#endif
#ifndef LIBSPDM_SHA512_SUPPORT
#define LIBSPDM_SHA512_SUPPORT 0
#endif
#ifndef LIBSPDM_SHA3_256_SUPPORT
#define LIBSPDM_SHA3_256_SUPPORT 0
#endif
#ifndef LIBSPDM_SHA3_384_SUPPORT
#define LIBSPDM_SHA3_384_SUPPORT 0
#endif
#ifndef LIBSPDM_SHA3_512_SUPPORT
#define LIBSPDM_SHA3_512_SUPPORT 0
#endif
#ifndef LIBSPDM_SM3_256_SUPPORT
#define LIBSPDM_SM3_256_SUPPORT 0
#endif
/* This can be set to 0 for the device which does not need X509 parser.*/
#ifndef LIBSPDM_CERT_PARSE_SUPPORT
#define LIBSPDM_CERT_PARSE_SUPPORT 1
#endif
/* Code space optimization for Optional request/response messages.*/
/* Consumers of libspdm may wish to not fully implement all of the optional
* SPDM request/response messages. Therefore we have provided these
* SPDM_ENABLE_CAPABILITY_***_CAP compile time switches as an optimization
* disable the code (#if 0) related to said optional capability, thereby
* reducing the code space used in the image.*/
/* A single switch may enable/disable a single capability or group of related
* capabilities.*/
/* LIBSPDM_ENABLE_CAPABILITY_CERT_CAP - Enable/Disable single CERT capability.
* LIBSPDM_ENABLE_CAPABILITY_CHAL_CAP - Enable/Disable single CHAL capability.
* LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP - Enable/Disables multiple MEAS capabilities:
* (MEAS_CAP_NO_SIG, MEAS_CAP_SIG, MEAS_FRESH_CAP)*/
/* LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP - Enable/Disable single Key Exchange capability.
* LIBSPDM_ENABLE_CAPABILITY_PSK_EX_CAP - Enable/Disable PSK_EX and PSK_FINISH.*/
/* LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP - Enable/Disable mutual authentication.
* LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP - Enable/Disable encapsulated message.*/
/* LIBSPDM_ENABLE_CAPABILITY_CSR_CAP - Enable/Disable get csr capability.
* LIBSPDM_ENABLE_CAPABILITY_SET_CERT_CAP - Enable/Disable set certificate capability. */
#ifndef LIBSPDM_ENABLE_CAPABILITY_CERT_CAP
#define LIBSPDM_ENABLE_CAPABILITY_CERT_CAP 1
#endif
#ifndef LIBSPDM_ENABLE_CAPABILITY_CHAL_CAP
#define LIBSPDM_ENABLE_CAPABILITY_CHAL_CAP 1
#endif
#ifndef LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP
#define LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP 1
#endif
#ifndef LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP
#define LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP 0
#endif
#ifndef LIBSPDM_ENABLE_CAPABILITY_PSK_EX_CAP
#define LIBSPDM_ENABLE_CAPABILITY_PSK_EX_CAP 0
#endif
#ifndef LIBSPDM_ENABLE_CAPABILITY_HBEAT_CAP
#define LIBSPDM_ENABLE_CAPABILITY_HBEAT_CAP 0
#endif
#ifndef LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP
#define LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP 0
#endif
#ifndef LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP
#define LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP 0
#endif
#ifndef LIBSPDM_ENABLE_CAPABILITY_CSR_CAP
#define LIBSPDM_ENABLE_CAPABILITY_CSR_CAP 0
#endif
#ifndef LIBSPDM_ENABLE_CAPABILITY_SET_CERT_CAP
#define LIBSPDM_ENABLE_CAPABILITY_SET_CERT_CAP 0
#endif
#ifndef LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP
#define LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP 0
#endif
/* If 1 then endpoint supports sending GET_CERTIFICATE and GET_DIGESTS requests.
* If enabled and endpoint is a Responder then LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP
* must also be enabled.
*/
#ifndef LIBSPDM_SEND_GET_CERTIFICATE_SUPPORT
#define LIBSPDM_SEND_GET_CERTIFICATE_SUPPORT 1
#endif
/* If 1 then endpoint supports sending CHALLENGE request.
* If enabled and endpoint is a Responder then LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP
* must also be enabled.
*/
#ifndef LIBSPDM_SEND_CHALLENGE_SUPPORT
#define LIBSPDM_SEND_CHALLENGE_SUPPORT 1
#endif
/* When LIBSPDM_RESPOND_IF_READY_SUPPORT is 0 then
* - For a Requester, if the Responder sends a ResponseNotReady ERROR response then the error
* is immediately returned to the Integrator. The Requester cannot send a RESPOND_IF_READY
* request.
* - For a Responder, it cannot send a RESPOND_IF_READY ERROR response and does not support
* RESPOND_IF_READY.
* When LIBSPDM_RESPOND_IF_READY_SUPPORT is 1 then
* - For a Requester, if the Responder sends a ResponseNotReady ERROR response then libspdm
* waits an amount of time, as specified by the RDTExponent parameter, before sending
* RESPOND_IF_READY.
* - For a Responder, if its response state is NOT_READY then it will send a ResponseNotReady
* ERROR response to the Requester, and will accept a subsequent RESPOND_IF_READY request.
*/
#ifndef LIBSPDM_RESPOND_IF_READY_SUPPORT
#define LIBSPDM_RESPOND_IF_READY_SUPPORT 1
#endif
/*
* MinDataTransferSize = 42
*
* H = HashLen = HmacLen = [32, 64]
* S = SigLen = [64, 512]
* D = ExchangeDataLen = [64, 512]
* R = RequesterContextLen >= 32
* R = ResponderContextLen >= 0
* O = OpaqueDataLen <= 1024
*
* Max Chunk No = 1, if (message size <= 42)
* Max Chunk No = [(message size + 4) / 30] roundup, if (message size > 42)
*
* +==========================+==========================================+=========+
* | Command | Size |MaxChunk |
* +==========================+==========================================+=========+
* | GET_VERSION | 4 | 1 |
* | VERSION {1.0, 1.1, 1.2} | 6 + 2 * 3 = 12 | 1 |
* +--------------------------+------------------------------------------+---------+
* | GET_CAPABILITIES 1.2 | 20 | 1 |
* | CAPABILITIES 1.2 | 20 | 1 |
* +--------------------------+------------------------------------------+---------+
* | ERROR | 4 | 1 |
* | ERROR(ResponseTooLarge) | 4 + 4 = 8 | 1 |
* | ERROR(LargeResponse) | 4 + 1 = 5 | 1 |
* | ERROR(ResponseNotReady) | 4 + 4 = 8 | 1 |
* +--------------------------+------------------------------------------+---------+
* | CHUNK_SEND header | 12 + L0 (0 or 4) | 1 |
* | CHUNK_RESPONSE header | 12 + L0 (0 or 4) | 1 |
* +==========================+==========================================+=========+
* | NEGOTIATE_ALGORITHMS 1.2 | 32 + 4 * 4 = 48 | 2 |
* | ALGORITHMS 1.2 | 36 + 4 * 4 = 52 | 2 |
* +--------------------------+------------------------------------------+---------+
* | GET_DIGESTS 1.2 | 4 | 1 |
* | DIGESTS 1.2 | 4 + H * SlotNum = [36, 516] | [1, 18] |
* +--------------------------+------------------------------------------+---------+
* | GET_CERTIFICATE 1.2 | 8 | 1 |
* | CERTIFICATE 1.2 | 8 + PortionLen | [1, ] |
* +--------------------------+------------------------------------------+---------+
* | CHALLENGE 1.2 | 40 | 1 |
* | CHALLENGE_AUTH 1.2 | 38 + H * 2 + S [+ O] = [166, 678] | [6, 23] |
* +--------------------------+------------------------------------------+---------+
* | GET_MEASUREMENTS 1.2 | 5 + Nonce (0 or 32) | 1 |
* | MEASUREMENTS 1.2 | 42 + MeasRecLen (+ S) [+ O] = [106, 554] | [4, 19] |
* +--------------------------+------------------------------------------+---------+
* | KEY_EXCHANGE 1.2 | 42 + D [+ O] = [106, 554] | [4, 19] |
* | KEY_EXCHANGE_RSP 1.2 | 42 + D + H + S (+ H) [+ O] = [234, 1194] | [8, 40] |
* +--------------------------+------------------------------------------+---------+
* | FINISH 1.2 | 4 (+ S) + H = [100, 580] | [4, 20] |
* | FINISH_RSP 1.2 | 4 (+ H) = [36, 69] | [1, 3] |
* +--------------------------+------------------------------------------+---------+
* | PSK_EXCHANGE 1.2 | 12 [+ PSKHint] + R [+ O] = 44 | 2 |
* | PSK_EXCHANGE_RSP 1.2 | 12 + R + H (+ H) [+ O] = [108, 172] | [4, 6] |
* +--------------------------+------------------------------------------+---------+
* | PSK_FINISH 1.2 | 4 + H = [36, 68] | [1, 3] |
* | PSK_FINISH_RSP 1.2 | 4 | 1 |
* +--------------------------+------------------------------------------+---------+
* | GET_CSR 1.2 | 8 + RequesterInfoLen [+ O] | [1, ] |
* | CSR 1.2 | 8 + CSRLength | [1, ] |
* +--------------------------+------------------------------------------+---------+
* | SET_CERTIFICATE 1.2 | 4 + CertChainLen | [1, ] |
* | SET_CERTIFICATE_RSP 1.2 | 4 | 1 |
* +==========================+==========================================+=========+
*/
/* Required sender/receive buffer in device io.
* NOTE: This is transport specific. Below configuration is just an example.
* +-------+--------+---------------------------+------+--+------+---+--------+-----+
* | TYPE |TransHdr| EncryptionHeader |AppHdr| |Random|MAC|AlignPad|FINAL|
* | | |SessionId|SeqNum|Len|AppLen| | | | | | |
* +-------+--------+---------------------------+------+ +------+---+--------+-----+
* | MCTP | 1 | 4 | 2 | 2 | 2 | 1 | | 32 | 12| 0 | 56 |
* |PCI_DOE| 8 | 4 | 0 | 2 | 2 | 0 | | 0 | 12| 3 | 31 |
* +-------+--------+---------------------------+------+--+------+---+--------+-----+
*/
/* Enable message logging.
* See https://github.com/DMTF/libspdm/blob/main/doc/user_guide.md#message-logging
* for more information */
#ifndef LIBSPDM_ENABLE_MSG_LOG
#define LIBSPDM_ENABLE_MSG_LOG 1
#endif
/* Enable macro checking during compilation. */
#ifndef LIBSPDM_CHECK_MACRO
#define LIBSPDM_CHECK_MACRO 0
#endif
/* Enable checks to the SPDM context during runtime. */
#ifndef LIBSPDM_CHECK_SPDM_CONTEXT
#define LIBSPDM_CHECK_SPDM_CONTEXT 1
#endif
#endif /* SPDM_LIB_CONFIG_H */

View File

@ -0,0 +1,47 @@
## @file
# SPDM library.
#
# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = SpdmCommonLib
FILE_GUID = 4D42800D-2197-46EC-8E04-6B41BFD60687
MODULE_TYPE = BASE
VERSION_STRING = 1.0
LIBRARY_CLASS = SpdmCommonLib
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 AARCH64
#
[Sources]
libspdm/library/spdm_common_lib/libspdm_com_context_data.c
libspdm/library/spdm_common_lib/libspdm_com_context_data_session.c
libspdm/library/spdm_common_lib/libspdm_com_crypto_service.c
libspdm/library/spdm_common_lib/libspdm_com_crypto_service_session.c
libspdm/library/spdm_common_lib/libspdm_com_opaque_data.c
libspdm/library/spdm_common_lib/libspdm_com_support.c
libspdm/library/spdm_common_lib/libspdm_com_msg_log.c
[Packages]
MdePkg/MdePkg.dec
SecurityPkg/SecurityPkg.dec
CryptoPkg/CryptoPkg.dec
[LibraryClasses]
BaseLib
BaseMemoryLib
DebugLib
BaseCryptLib
RngLib
SpdmCryptLib
SpdmDeviceSecretLib
MemLibWrapper
CryptlibWrapper

View File

@ -0,0 +1,45 @@
## @file
# SPDM library.
#
# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = SpdmCryptLib
FILE_GUID = 2FF3E7F6-D95A-48A2-B418-9B6D585C1D7E
MODULE_TYPE = BASE
VERSION_STRING = 1.0
LIBRARY_CLASS = SpdmCryptLib
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 AARCH64
#
[Sources]
libspdm/library/spdm_crypt_lib/libspdm_crypt_aead.c
libspdm/library/spdm_crypt_lib/libspdm_crypt_asym.c
libspdm/library/spdm_crypt_lib/libspdm_crypt_cert.c
libspdm/library/spdm_crypt_lib/libspdm_crypt_dhe.c
libspdm/library/spdm_crypt_lib/libspdm_crypt_hash.c
libspdm/library/spdm_crypt_lib/libspdm_crypt_hkdf.c
libspdm/library/spdm_crypt_lib/libspdm_crypt_hmac.c
libspdm/library/spdm_crypt_lib/libspdm_crypt_rng.c
[Packages]
MdePkg/MdePkg.dec
SecurityPkg/SecurityPkg.dec
CryptoPkg/CryptoPkg.dec
[LibraryClasses]
BaseLib
BaseMemoryLib
DebugLib
BaseCryptLib
RngLib
MemLibWrapper

View File

@ -0,0 +1,36 @@
## @file
# SPDM library.
#
# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = SpdmDeviceSecretLibNull
FILE_GUID = E2FFA5F9-CD19-4B63-AE3E-7EA288243EED
MODULE_TYPE = BASE
VERSION_STRING = 1.0
LIBRARY_CLASS = SpdmDeviceSecretLib
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 AARCH64
#
[Sources]
libspdm/os_stub/spdm_device_secret_lib_null/lib.c
[Packages]
MdePkg/MdePkg.dec
SecurityPkg/SecurityPkg.dec
CryptoPkg/CryptoPkg.dec
[LibraryClasses]
BaseLib
BaseMemoryLib
DebugLib
MemLibWrapper

View File

@ -0,0 +1,59 @@
## @file
# SPDM library.
#
# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = SpdmRequesterLib
FILE_GUID = 8B6024A3-270A-410F-91AB-9E99F05C2A58
MODULE_TYPE = BASE
VERSION_STRING = 1.0
LIBRARY_CLASS = SpdmRequesterLib
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 AARCH64
#
[Sources]
libspdm/library/spdm_requester_lib/libspdm_req_challenge.c
libspdm/library/spdm_requester_lib/libspdm_req_common.c
libspdm/library/spdm_requester_lib/libspdm_req_communication.c
libspdm/library/spdm_requester_lib/libspdm_req_encap_certificate.c
libspdm/library/spdm_requester_lib/libspdm_req_encap_challenge_auth.c
libspdm/library/spdm_requester_lib/libspdm_req_encap_digests.c
libspdm/library/spdm_requester_lib/libspdm_req_encap_error.c
libspdm/library/spdm_requester_lib/libspdm_req_encap_key_update.c
libspdm/library/spdm_requester_lib/libspdm_req_encap_request.c
libspdm/library/spdm_requester_lib/libspdm_req_end_session.c
libspdm/library/spdm_requester_lib/libspdm_req_finish.c
libspdm/library/spdm_requester_lib/libspdm_req_get_capabilities.c
libspdm/library/spdm_requester_lib/libspdm_req_get_certificate.c
libspdm/library/spdm_requester_lib/libspdm_req_get_digests.c
libspdm/library/spdm_requester_lib/libspdm_req_get_measurements.c
libspdm/library/spdm_requester_lib/libspdm_req_get_version.c
libspdm/library/spdm_requester_lib/libspdm_req_handle_error_response.c
libspdm/library/spdm_requester_lib/libspdm_req_heartbeat.c
libspdm/library/spdm_requester_lib/libspdm_req_key_exchange.c
libspdm/library/spdm_requester_lib/libspdm_req_key_update.c
libspdm/library/spdm_requester_lib/libspdm_req_negotiate_algorithms.c
libspdm/library/spdm_requester_lib/libspdm_req_psk_exchange.c
libspdm/library/spdm_requester_lib/libspdm_req_psk_finish.c
libspdm/library/spdm_requester_lib/libspdm_req_send_receive.c
[Packages]
MdePkg/MdePkg.dec
SecurityPkg/SecurityPkg.dec
CryptoPkg/CryptoPkg.dec
[LibraryClasses]
SpdmCommonLib
SpdmSecuredMessageLib
PlatformLibWrapper
MemLibWrapper

View File

@ -0,0 +1,61 @@
## @file
# SPDM library.
#
# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = SpdmResponderLib
FILE_GUID = 9005B3A3-45F1-4DE9-93FF-2512D4B9CCFA
MODULE_TYPE = BASE
VERSION_STRING = 1.0
LIBRARY_CLASS = SpdmResponderLib
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 AARCH64
#
[Sources]
libspdm/library/spdm_responder_lib/libspdm_rsp_algorithms.c
libspdm/library/spdm_responder_lib/libspdm_rsp_capabilities.c
libspdm/library/spdm_responder_lib/libspdm_rsp_certificate.c
libspdm/library/spdm_responder_lib/libspdm_rsp_challenge_auth.c
libspdm/library/spdm_responder_lib/libspdm_rsp_common.c
libspdm/library/spdm_responder_lib/libspdm_rsp_communication.c
libspdm/library/spdm_responder_lib/libspdm_rsp_digests.c
libspdm/library/spdm_responder_lib/libspdm_rsp_encap_challenge.c
libspdm/library/spdm_responder_lib/libspdm_rsp_encap_get_certificate.c
libspdm/library/spdm_responder_lib/libspdm_rsp_encap_get_digests.c
libspdm/library/spdm_responder_lib/libspdm_rsp_encap_key_update.c
libspdm/library/spdm_responder_lib/libspdm_rsp_encap_response.c
libspdm/library/spdm_responder_lib/libspdm_rsp_end_session.c
libspdm/library/spdm_responder_lib/libspdm_rsp_error.c
libspdm/library/spdm_responder_lib/libspdm_rsp_finish.c
libspdm/library/spdm_responder_lib/libspdm_rsp_handle_response_state.c
libspdm/library/spdm_responder_lib/libspdm_rsp_heartbeat.c
libspdm/library/spdm_responder_lib/libspdm_rsp_key_exchange.c
libspdm/library/spdm_responder_lib/libspdm_rsp_key_update.c
libspdm/library/spdm_responder_lib/libspdm_rsp_measurements.c
libspdm/library/spdm_responder_lib/libspdm_rsp_psk_exchange.c
libspdm/library/spdm_responder_lib/libspdm_rsp_psk_finish.c
libspdm/library/spdm_responder_lib/libspdm_rsp_receive_send.c
libspdm/library/spdm_responder_lib/libspdm_rsp_respond_if_ready.c
libspdm/library/spdm_responder_lib/libspdm_rsp_version.c
libspdm/library/spdm_responder_lib/libspdm_rsp_csr.c
[Packages]
MdePkg/MdePkg.dec
SecurityPkg/SecurityPkg.dec
CryptoPkg/CryptoPkg.dec
[LibraryClasses]
SpdmCommonLib
SpdmSecuredMessageLib
PlatformLibWrapper
MemLibWrapper

View File

@ -0,0 +1,44 @@
## @file
# SPDM library.
#
# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = SpdmSecuredMessageLib
FILE_GUID = C5E91542-9B57-4BC4-988C-2DEB0B17D381
MODULE_TYPE = BASE
VERSION_STRING = 1.0
LIBRARY_CLASS = SpdmSecuredMessageLib
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 AARCH64
#
[Sources]
libspdm/library/spdm_secured_message_lib/libspdm_secmes_context_data.c
libspdm/library/spdm_secured_message_lib/libspdm_secmes_encode_decode.c
libspdm/library/spdm_secured_message_lib/libspdm_secmes_encode_decode.c
libspdm/library/spdm_secured_message_lib/libspdm_secmes_key_exchange.c
libspdm/library/spdm_secured_message_lib/libspdm_secmes_session.c
[Packages]
MdePkg/MdePkg.dec
SecurityPkg/SecurityPkg.dec
CryptoPkg/CryptoPkg.dec
[LibraryClasses]
BaseLib
BaseMemoryLib
DebugLib
BaseCryptLib
RngLib
SpdmCryptLib
SpdmDeviceSecretLib
MemLibWrapper

View File

@ -0,0 +1,38 @@
## @file
# SPDM library.
#
# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = SpdmTransportMctpLib
FILE_GUID = C6ED3DB8-852A-40A8-8099-9D87D93669C4
MODULE_TYPE = BASE
VERSION_STRING = 1.0
LIBRARY_CLASS = SpdmTransportMctpLib
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 AARCH64
#
[Sources]
libspdm/library/spdm_transport_mctp_lib/libspdm_mctp_common.c
libspdm/library/spdm_transport_mctp_lib/libspdm_mctp_mctp.c
[Packages]
MdePkg/MdePkg.dec
SecurityPkg/SecurityPkg.dec
CryptoPkg/CryptoPkg.dec
[LibraryClasses]
BaseLib
BaseMemoryLib
DebugLib
SpdmSecuredMessageLib
MemLibWrapper

View File

@ -0,0 +1,38 @@
## @file
# SPDM library.
#
# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = SpdmTransportPciDoeLib
FILE_GUID = 21094151-1A91-4261-8EB7-C94453491FF8
MODULE_TYPE = BASE
VERSION_STRING = 1.0
LIBRARY_CLASS = SpdmTransportPciDoeLib
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 AARCH64
#
[Sources]
libspdm/library/spdm_transport_pcidoe_lib/libspdm_doe_common.c
libspdm/library/spdm_transport_pcidoe_lib/libspdm_doe_pcidoe.c
[Packages]
MdePkg/MdePkg.dec
SecurityPkg/SecurityPkg.dec
CryptoPkg/CryptoPkg.dec
[LibraryClasses]
BaseLib
BaseMemoryLib
DebugLib
SpdmSecuredMessageLib
MemLibWrapper

View File

@ -0,0 +1,697 @@
/** @file
EDKII Device Security library for SPDM device.
It follows the SPDM Specification.
Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "SpdmSecurityLibInternal.h"
/**
Measure and log an EFI variable, and extend the measurement result into a specific PCR.
@param[in] PcrIndex PCR Index.
@param[in] EventType Event type.
@param[in] VarName A Null-terminated string that is the name of the vendor's variable.
@param[in] VendorGuid A unique identifier for the vendor.
@param[in] VarData The content of the variable data.
@param[in] VarSize The size of the variable data.
@retval EFI_SUCCESS Operation completed successfully.
@retval EFI_OUT_OF_RESOURCES Out of memory.
@retval EFI_DEVICE_ERROR The operation was unsuccessful.
**/
EFI_STATUS
EFIAPI
MeasureVariable (
IN UINT32 PcrIndex,
IN UINT32 EventType,
IN CHAR16 *VarName,
IN EFI_GUID *VendorGuid,
IN VOID *VarData,
IN UINTN VarSize
)
{
EFI_STATUS Status;
UINTN VarNameLength;
UEFI_VARIABLE_DATA *VarLog;
UINT32 VarLogSize;
if (!(((VarSize == 0) && (VarData == NULL)) || ((VarSize != 0) && (VarData != NULL)))) {
ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
return EFI_INVALID_PARAMETER;
}
VarNameLength = StrLen (VarName);
VarLogSize = (UINT32)(sizeof (*VarLog) + VarNameLength * sizeof (*VarName) + VarSize
- sizeof (VarLog->UnicodeName) - sizeof (VarLog->VariableData));
VarLog = (UEFI_VARIABLE_DATA *)AllocateZeroPool (VarLogSize);
if (VarLog == NULL) {
return EFI_OUT_OF_RESOURCES;
}
CopyMem (&VarLog->VariableName, VendorGuid, sizeof (VarLog->VariableName));
VarLog->UnicodeNameLength = VarNameLength;
VarLog->VariableDataLength = VarSize;
CopyMem (
VarLog->UnicodeName,
VarName,
VarNameLength * sizeof (*VarName)
);
if (VarSize != 0) {
CopyMem (
(CHAR16 *)VarLog->UnicodeName + VarNameLength,
VarData,
VarSize
);
}
DEBUG ((DEBUG_INFO, "VariableDxe: MeasureVariable (Pcr - %x, EventType - %x, ", (UINTN)PcrIndex, (UINTN)EventType));
DEBUG ((DEBUG_INFO, "VariableName - %s, VendorGuid - %g)\n", VarName, VendorGuid));
Status = TpmMeasureAndLogData (
PcrIndex,
EventType,
VarLog,
VarLogSize,
VarLog,
VarLogSize
);
FreePool (VarLog);
return Status;
}
/**
Extend Certicate and auth state to NV Index and measure trust anchor to PCR.
@param[in] SpdmDeviceContext The SPDM context for the device.
@param[in] AuthState The auth state of this deice.
@param[in] CertChainSize The size of cert chain.
@param[in] CertChain A pointer to a destination buffer to store the certificate chain.
@param[in] TrustAnchor A buffer to hold the trust_anchor which is used to validate the peer
certificate, if not NULL.
@param[in] TrustAnchorSize A buffer to hold the trust_anchor_size, if not NULL..
@param[in] SlotId The number of slot for the certificate chain.
@param[out] SecurityState A pointer to the security state of the requester.
@retval EFI_SUCCESS Operation completed successfully.
@retval EFI_OUT_OF_RESOURCES Out of memory.
@retval EFI_DEVICE_ERROR The operation was unsuccessful.
**/
EFI_STATUS
ExtendCertificate (
IN SPDM_DEVICE_CONTEXT *SpdmDeviceContext,
IN UINT8 AuthState,
IN UINTN CertChainSize,
IN UINT8 *CertChain,
IN VOID *TrustAnchor,
IN UINTN TrustAnchorSize,
IN UINT8 SlotId,
OUT EDKII_DEVICE_SECURITY_STATE *SecurityState
)
{
VOID *EventLog;
UINT32 EventLogSize;
UINT8 *EventLogPtr;
TCG_NV_INDEX_INSTANCE_EVENT_LOG_STRUCT *NvIndexInstance;
TCG_DEVICE_SECURITY_EVENT_DATA_HEADER2 *EventData2;
TCG_DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_CERT_CHAIN *TcgSpdmCertChain;
VOID *DeviceContext;
UINTN DeviceContextSize;
EFI_STATUS Status;
UINTN DevicePathSize;
UINT32 BaseHashAlgo;
UINTN DataSize;
VOID *SpdmContext;
SPDM_DATA_PARAMETER Parameter;
EFI_SIGNATURE_DATA *SignatureData;
UINTN SignatureDataSize;
SpdmContext = SpdmDeviceContext->SpdmContext;
EventLog = NULL;
ZeroMem (&Parameter, sizeof (Parameter));
Parameter.location = SpdmDataLocationConnection;
DataSize = sizeof (BaseHashAlgo);
Status = SpdmGetData (SpdmContext, SpdmDataBaseHashAlgo, &Parameter, &BaseHashAlgo, &DataSize);
ASSERT_EFI_ERROR (Status);
DeviceContextSize = GetDeviceMeasurementContextSize (SpdmDeviceContext);
DevicePathSize = GetDevicePathSize (SpdmDeviceContext->DevicePath);
switch (AuthState) {
case TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_SUCCESS:
case TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_NO_AUTH:
case TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_NO_BINDING:
EventLogSize = (UINT32)(sizeof (TCG_NV_INDEX_INSTANCE_EVENT_LOG_STRUCT) +
sizeof (TCG_DEVICE_SECURITY_EVENT_DATA_HEADER2) +
sizeof (UINT64) + DevicePathSize +
sizeof (TCG_DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_CERT_CHAIN) +
CertChainSize +
DeviceContextSize);
EventLog = AllocatePool (EventLogSize);
if (EventLog == NULL) {
SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_UEFI_OUT_OF_RESOURCE;
return EFI_OUT_OF_RESOURCES;
}
EventLogPtr = EventLog;
NvIndexInstance = (VOID *)EventLogPtr;
CopyMem (NvIndexInstance->Signature, TCG_NV_EXTEND_INDEX_FOR_INSTANCE_SIGNATURE, sizeof (TCG_NV_EXTEND_INDEX_FOR_INSTANCE_SIGNATURE));
NvIndexInstance->Version = TCG_NV_INDEX_INSTANCE_EVENT_LOG_STRUCT_VERSION;
ZeroMem (NvIndexInstance->Reserved, sizeof (NvIndexInstance->Reserved));
EventLogPtr += sizeof (TCG_NV_INDEX_INSTANCE_EVENT_LOG_STRUCT);
EventData2 = (VOID *)EventLogPtr;
CopyMem (EventData2->Signature, TCG_DEVICE_SECURITY_EVENT_DATA_SIGNATURE_2, sizeof (EventData2->Signature));
EventData2->Version = TCG_DEVICE_SECURITY_EVENT_DATA_VERSION_2;
EventData2->AuthState = AuthState;
EventData2->Reserved = 0;
EventData2->Length = (UINT32)EventLogSize;
EventData2->DeviceType = GetSpdmDeviceType (SpdmDeviceContext);
EventData2->SubHeaderType = TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_SUB_HEADER_TYPE_SPDM_CERT_CHAIN;
EventData2->SubHeaderLength = (UINT32)(sizeof (TCG_DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_CERT_CHAIN) + CertChainSize);
EventData2->SubHeaderUID = SpdmDeviceContext->DeviceUID;
EventLogPtr = (VOID *)(EventData2 + 1);
*(UINT64 *)EventLogPtr = (UINT64)DevicePathSize;
EventLogPtr += sizeof (UINT64);
CopyMem (EventLogPtr, SpdmDeviceContext->DevicePath, DevicePathSize);
EventLogPtr += DevicePathSize;
TcgSpdmCertChain = (VOID *)EventLogPtr;
TcgSpdmCertChain->SpdmVersion = SpdmDeviceContext->SpdmVersion;
TcgSpdmCertChain->SpdmSlotId = SlotId;
TcgSpdmCertChain->Reserved = 0;
TcgSpdmCertChain->SpdmHashAlgo = BaseHashAlgo;
EventLogPtr += sizeof (TCG_DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_CERT_CHAIN);
CopyMem (EventLogPtr, CertChain, CertChainSize);
EventLogPtr += CertChainSize;
if (DeviceContextSize != 0) {
DeviceContext = (VOID *)EventLogPtr;
Status = CreateDeviceMeasurementContext (SpdmDeviceContext, DeviceContext, DeviceContextSize);
if (Status != EFI_SUCCESS) {
SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_DEVICE_ERROR;
Status = EFI_DEVICE_ERROR;
goto Exit;
}
}
Status = TpmMeasureAndLogData (
TCG_NV_EXTEND_INDEX_FOR_INSTANCE,
EV_NO_ACTION,
EventLog,
EventLogSize,
EventLog,
EventLogSize
);
if (EFI_ERROR (Status)) {
SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_TCG_EXTEND_TPM_PCR;
}
DEBUG ((DEBUG_INFO, "TpmMeasureAndLogData (Instance) - %r\n", Status));
break;
case TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_FAIL_INVALID:
EventLogSize = (UINT32)(sizeof (TCG_NV_INDEX_INSTANCE_EVENT_LOG_STRUCT) +
sizeof (TCG_DEVICE_SECURITY_EVENT_DATA_HEADER2) +
sizeof (UINT64) + DevicePathSize +
sizeof (TCG_DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_CERT_CHAIN) +
DeviceContextSize);
EventLog = AllocatePool (EventLogSize);
if (EventLog == NULL) {
SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_UEFI_OUT_OF_RESOURCE;
return EFI_OUT_OF_RESOURCES;
}
EventLogPtr = EventLog;
NvIndexInstance = (VOID *)EventLogPtr;
CopyMem (NvIndexInstance->Signature, TCG_NV_EXTEND_INDEX_FOR_INSTANCE_SIGNATURE, sizeof (TCG_NV_EXTEND_INDEX_FOR_INSTANCE_SIGNATURE));
NvIndexInstance->Version = TCG_NV_INDEX_INSTANCE_EVENT_LOG_STRUCT_VERSION;
ZeroMem (NvIndexInstance->Reserved, sizeof (NvIndexInstance->Reserved));
EventLogPtr += sizeof (TCG_NV_INDEX_INSTANCE_EVENT_LOG_STRUCT);
EventData2 = (VOID *)EventLogPtr;
CopyMem (EventData2->Signature, TCG_DEVICE_SECURITY_EVENT_DATA_SIGNATURE_2, sizeof (EventData2->Signature));
EventData2->Version = TCG_DEVICE_SECURITY_EVENT_DATA_VERSION_2;
EventData2->AuthState = AuthState;
EventData2->Reserved = 0;
EventData2->Length = (UINT32)EventLogSize;
EventData2->DeviceType = GetSpdmDeviceType (SpdmDeviceContext);
EventData2->SubHeaderType = TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_SUB_HEADER_TYPE_SPDM_CERT_CHAIN;
EventData2->SubHeaderLength = sizeof (TCG_DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_CERT_CHAIN);
EventData2->SubHeaderUID = SpdmDeviceContext->DeviceUID;
EventLogPtr = (VOID *)(EventData2 + 1);
*(UINT64 *)EventLogPtr = (UINT64)DevicePathSize;
EventLogPtr += sizeof (UINT64);
CopyMem (EventLogPtr, SpdmDeviceContext->DevicePath, DevicePathSize);
EventLogPtr += DevicePathSize;
TcgSpdmCertChain = (VOID *)EventLogPtr;
TcgSpdmCertChain->SpdmVersion = SpdmDeviceContext->SpdmVersion;
TcgSpdmCertChain->SpdmSlotId = SlotId;
TcgSpdmCertChain->Reserved = 0;
TcgSpdmCertChain->SpdmHashAlgo = BaseHashAlgo;
EventLogPtr += sizeof (TCG_DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_CERT_CHAIN);
if (DeviceContextSize != 0) {
DeviceContext = (VOID *)EventLogPtr;
Status = CreateDeviceMeasurementContext (SpdmDeviceContext, DeviceContext, DeviceContextSize);
if (Status != EFI_SUCCESS) {
SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_DEVICE_ERROR;
Status = EFI_DEVICE_ERROR;
goto Exit;
}
}
Status = TpmMeasureAndLogData (
TCG_NV_EXTEND_INDEX_FOR_INSTANCE,
EV_NO_ACTION,
EventLog,
EventLogSize,
EventLog,
EventLogSize
);
if (EFI_ERROR (Status)) {
SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_TCG_EXTEND_TPM_PCR;
}
DEBUG ((DEBUG_INFO, "TpmMeasureAndLogData (Instance) - %r\n", Status));
goto Exit;
case TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_FAIL_NO_SIG:
case TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_NO_SPDM:
EventLogSize = (UINT32)(sizeof (TCG_NV_INDEX_INSTANCE_EVENT_LOG_STRUCT) +
sizeof (TCG_DEVICE_SECURITY_EVENT_DATA_HEADER2) +
sizeof (UINT64) + DevicePathSize +
DeviceContextSize);
EventLog = AllocatePool (EventLogSize);
if (EventLog == NULL) {
SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_UEFI_OUT_OF_RESOURCE;
return EFI_OUT_OF_RESOURCES;
}
EventLogPtr = EventLog;
NvIndexInstance = (VOID *)EventLogPtr;
CopyMem (NvIndexInstance->Signature, TCG_NV_EXTEND_INDEX_FOR_INSTANCE_SIGNATURE, sizeof (TCG_NV_EXTEND_INDEX_FOR_INSTANCE_SIGNATURE));
NvIndexInstance->Version = TCG_NV_INDEX_INSTANCE_EVENT_LOG_STRUCT_VERSION;
ZeroMem (NvIndexInstance->Reserved, sizeof (NvIndexInstance->Reserved));
EventLogPtr += sizeof (TCG_NV_INDEX_INSTANCE_EVENT_LOG_STRUCT);
EventData2 = (VOID *)EventLogPtr;
CopyMem (EventData2->Signature, TCG_DEVICE_SECURITY_EVENT_DATA_SIGNATURE_2, sizeof (EventData2->Signature));
EventData2->Version = TCG_DEVICE_SECURITY_EVENT_DATA_VERSION_2;
EventData2->AuthState = AuthState;
EventData2->Reserved = 0;
EventData2->Length = (UINT32)EventLogSize;
EventData2->DeviceType = GetSpdmDeviceType (SpdmDeviceContext);
EventData2->SubHeaderType = TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_SUB_HEADER_TYPE_SPDM_CERT_CHAIN;
EventData2->SubHeaderLength = 0;
EventData2->SubHeaderUID = SpdmDeviceContext->DeviceUID;
EventLogPtr = (VOID *)(EventData2 + 1);
*(UINT64 *)EventLogPtr = (UINT64)DevicePathSize;
EventLogPtr += sizeof (UINT64);
CopyMem (EventLogPtr, SpdmDeviceContext->DevicePath, DevicePathSize);
EventLogPtr += DevicePathSize;
if (DeviceContextSize != 0) {
DeviceContext = (VOID *)EventLogPtr;
Status = CreateDeviceMeasurementContext (SpdmDeviceContext, DeviceContext, DeviceContextSize);
if (Status != EFI_SUCCESS) {
SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_DEVICE_ERROR;
Status = EFI_DEVICE_ERROR;
goto Exit;
}
}
Status = TpmMeasureAndLogData (
TCG_NV_EXTEND_INDEX_FOR_INSTANCE,
EV_NO_ACTION,
EventLog,
EventLogSize,
EventLog,
EventLogSize
);
if (EFI_ERROR (Status)) {
SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_TCG_EXTEND_TPM_PCR;
}
DEBUG ((DEBUG_INFO, "TpmMeasureAndLogData (Instance) - %r\n", Status));
goto Exit;
default:
SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_UEFI_UNSUPPORTED;
return EFI_UNSUPPORTED;
}
if ((TrustAnchor != NULL) && (TrustAnchorSize != 0)) {
SignatureDataSize = sizeof (EFI_GUID) + TrustAnchorSize;
SignatureData = AllocateZeroPool (SignatureDataSize);
if (SignatureData == NULL) {
ASSERT (SignatureData != NULL);
SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_UEFI_OUT_OF_RESOURCE;
Status = EFI_OUT_OF_RESOURCES;
goto Exit;
}
CopyGuid (&SignatureData->SignatureOwner, &gEfiCallerIdGuid);
CopyMem (
(UINT8 *)SignatureData + sizeof (EFI_GUID),
TrustAnchor,
TrustAnchorSize
);
MeasureVariable (
PCR_INDEX_FOR_SIGNATURE_DB,
EV_EFI_SPDM_DEVICE_AUTHORITY,
EFI_DEVICE_SECURITY_DATABASE,
&gEfiDeviceSignatureDatabaseGuid,
SignatureData,
SignatureDataSize
);
FreePool (SignatureData);
}
Exit:
if (EventLog != NULL) {
FreePool (EventLog);
}
return Status;
}
/**
Measure and log Auth state and Requester and responder Nonce into NV Index.
@param[in] SpdmDeviceContext The SPDM context for the device.
@param[in] AuthState The auth state of this deice.
@param[in] RequesterNonce A buffer to hold the requester nonce (32 bytes), if not NULL.
@param[in] ResponderNonce A buffer to hold the responder nonce (32 bytes), if not NULL.
@param[out] SecurityState A pointer to the security state of the requester.
@retval EFI_SUCCESS Operation completed successfully.
@retval EFI_OUT_OF_RESOURCES Out of memory.
@retval EFI_DEVICE_ERROR The operation was unsuccessful.
**/
EFI_STATUS
ExtendAuthentication (
IN SPDM_DEVICE_CONTEXT *SpdmDeviceContext,
IN UINT8 AuthState,
IN UINT8 *RequesterNonce,
IN UINT8 *ResponderNonce,
OUT EDKII_DEVICE_SECURITY_STATE *SecurityState
)
{
EFI_STATUS Status;
{
TCG_NV_INDEX_DYNAMIC_EVENT_LOG_STRUCT_SPDM_CHALLENGE DynamicEventLogSpdmChallengeEvent;
TCG_NV_INDEX_DYNAMIC_EVENT_LOG_STRUCT_SPDM_CHALLENGE_AUTH DynamicEventLogSpdmChallengeAuthEvent;
CopyMem (DynamicEventLogSpdmChallengeEvent.Header.Signature, TCG_NV_EXTEND_INDEX_FOR_DYNAMIC_SIGNATURE, sizeof (TCG_NV_EXTEND_INDEX_FOR_DYNAMIC_SIGNATURE));
DynamicEventLogSpdmChallengeEvent.Header.Version = TCG_NV_INDEX_DYNAMIC_EVENT_LOG_STRUCT_VERSION;
ZeroMem (DynamicEventLogSpdmChallengeEvent.Header.Reserved, sizeof (DynamicEventLogSpdmChallengeEvent.Header.Reserved));
DynamicEventLogSpdmChallengeEvent.Header.Uid = SpdmDeviceContext->DeviceUID;
DynamicEventLogSpdmChallengeEvent.DescriptionSize = sizeof (TCG_SPDM_CHALLENGE_DESCRIPTION);
CopyMem (DynamicEventLogSpdmChallengeEvent.Description, TCG_SPDM_CHALLENGE_DESCRIPTION, sizeof (TCG_SPDM_CHALLENGE_DESCRIPTION));
DynamicEventLogSpdmChallengeEvent.DataSize = SPDM_NONCE_SIZE;
CopyMem (DynamicEventLogSpdmChallengeEvent.Data, RequesterNonce, SPDM_NONCE_SIZE);
Status = TpmMeasureAndLogData (
TCG_NV_EXTEND_INDEX_FOR_DYNAMIC,
EV_NO_ACTION,
&DynamicEventLogSpdmChallengeEvent,
sizeof (DynamicEventLogSpdmChallengeEvent),
&DynamicEventLogSpdmChallengeEvent,
sizeof (DynamicEventLogSpdmChallengeEvent)
);
if (EFI_ERROR (Status)) {
SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_TCG_EXTEND_TPM_PCR;
}
DEBUG ((DEBUG_INFO, "TpmMeasureAndLogData (Dynamic) - %r\n", Status));
CopyMem (DynamicEventLogSpdmChallengeAuthEvent.Header.Signature, TCG_NV_EXTEND_INDEX_FOR_DYNAMIC_SIGNATURE, sizeof (TCG_NV_EXTEND_INDEX_FOR_DYNAMIC_SIGNATURE));
DynamicEventLogSpdmChallengeAuthEvent.Header.Version = TCG_NV_INDEX_DYNAMIC_EVENT_LOG_STRUCT_VERSION;
ZeroMem (DynamicEventLogSpdmChallengeAuthEvent.Header.Reserved, sizeof (DynamicEventLogSpdmChallengeAuthEvent.Header.Reserved));
DynamicEventLogSpdmChallengeAuthEvent.Header.Uid = SpdmDeviceContext->DeviceUID;
DynamicEventLogSpdmChallengeAuthEvent.DescriptionSize = sizeof (TCG_SPDM_CHALLENGE_AUTH_DESCRIPTION);
CopyMem (DynamicEventLogSpdmChallengeAuthEvent.Description, TCG_SPDM_CHALLENGE_AUTH_DESCRIPTION, sizeof (TCG_SPDM_CHALLENGE_AUTH_DESCRIPTION));
DynamicEventLogSpdmChallengeAuthEvent.DataSize = SPDM_NONCE_SIZE;
CopyMem (DynamicEventLogSpdmChallengeAuthEvent.Data, ResponderNonce, SPDM_NONCE_SIZE);
Status = TpmMeasureAndLogData (
TCG_NV_EXTEND_INDEX_FOR_DYNAMIC,
EV_NO_ACTION,
&DynamicEventLogSpdmChallengeAuthEvent,
sizeof (DynamicEventLogSpdmChallengeAuthEvent),
&DynamicEventLogSpdmChallengeAuthEvent,
sizeof (DynamicEventLogSpdmChallengeAuthEvent)
);
if (EFI_ERROR (Status)) {
SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_TCG_EXTEND_TPM_PCR;
}
DEBUG ((DEBUG_INFO, "TpmMeasureAndLogData (Dynamic) - %r\n", Status));
}
return Status;
}
/**
This function gets SPDM digest and certificates.
@param[in] SpdmDeviceContext The SPDM context for the device.
@param[out] AuthState The auth state of the devices.
@param[out] ValidSlotId The number of slot for the certificate chain.
@param[out] SecurityState The security state of the requester.
@param[out] IsValidCertChain The validity of the certificate chain.
@param[out] RootCertMatch The authority of the certificate chain.
@retval EFI_SUCCESS Operation completed successfully.
@retval EFI_OUT_OF_RESOURCES Out of memory.
@retval EFI_DEVICE_ERROR The operation was unsuccessful.
**/
EFI_STATUS
EFIAPI
DoDeviceCertificate (
IN SPDM_DEVICE_CONTEXT *SpdmDeviceContext,
OUT UINT8 *AuthState,
OUT UINT8 *ValidSlotId,
OUT EDKII_DEVICE_SECURITY_STATE *SecurityState,
OUT BOOLEAN *IsValidCertChain,
OUT BOOLEAN *RootCertMatch
)
{
EFI_STATUS Status;
SPDM_RETURN SpdmReturn;
VOID *SpdmContext;
UINT32 CapabilityFlags;
UINTN DataSize;
SPDM_DATA_PARAMETER Parameter;
UINT8 SlotMask;
UINT8 TotalDigestBuffer[LIBSPDM_MAX_HASH_SIZE * SPDM_MAX_SLOT_COUNT];
UINTN CertChainSize;
UINT8 CertChain[LIBSPDM_MAX_CERT_CHAIN_SIZE];
VOID *TrustAnchor;
UINTN TrustAnchorSize;
UINT8 SlotId;
SpdmContext = SpdmDeviceContext->SpdmContext;
ZeroMem (&Parameter, sizeof (Parameter));
Parameter.location = SpdmDataLocationConnection;
DataSize = sizeof (CapabilityFlags);
SpdmReturn = SpdmGetData (SpdmContext, SpdmDataCapabilityFlags, &Parameter, &CapabilityFlags, &DataSize);
if (LIBSPDM_STATUS_IS_ERROR (SpdmReturn)) {
SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_DEVICE_ERROR;
return EFI_DEVICE_ERROR;
}
*IsValidCertChain = FALSE;
*RootCertMatch = FALSE;
CertChainSize = sizeof (CertChain);
ZeroMem (CertChain, sizeof (CertChain));
TrustAnchor = NULL;
TrustAnchorSize = 0;
//
// Init *ValidSlotId to invalid slot_id
//
*ValidSlotId = SPDM_MAX_SLOT_COUNT;
if ((CapabilityFlags & SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CERT_CAP) == 0) {
*AuthState = TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_FAIL_NO_SIG;
SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_DEVICE_NO_CAPABILITIES;
Status = ExtendCertificate (SpdmDeviceContext, *AuthState, 0, NULL, NULL, 0, 0, SecurityState);
return Status;
} else {
ZeroMem (TotalDigestBuffer, sizeof (TotalDigestBuffer));
SpdmReturn = SpdmGetDigest (SpdmContext, NULL, &SlotMask, TotalDigestBuffer);
if ((LIBSPDM_STATUS_IS_ERROR (SpdmReturn)) || ((SlotMask & 0x01) == 0)) {
*AuthState = TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_FAIL_INVALID;
SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_CERTIFIACTE_FAILURE;
SlotId = 0;
Status = ExtendCertificate (SpdmDeviceContext, *AuthState, 0, NULL, NULL, 0, SlotId, SecurityState);
return Status;
}
for (SlotId = 0; SlotId < SPDM_MAX_SLOT_COUNT; SlotId++) {
if (((SlotMask >> SlotId) & 0x01) == 0) {
continue;
}
CertChainSize = sizeof (CertChain);
ZeroMem (CertChain, sizeof (CertChain));
SpdmReturn = SpdmGetCertificateEx (SpdmContext, NULL, SlotId, &CertChainSize, CertChain, (CONST VOID **)&TrustAnchor, &TrustAnchorSize);
if (LIBSPDM_STATUS_IS_SUCCESS (SpdmReturn)) {
*IsValidCertChain = TRUE;
break;
} else if (SpdmReturn == LIBSPDM_STATUS_VERIF_FAIL) {
*IsValidCertChain = FALSE;
*AuthState = TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_FAIL_INVALID;
SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_CERTIFIACTE_FAILURE;
Status = ExtendCertificate (SpdmDeviceContext, *AuthState, 0, NULL, NULL, 0, SlotId, SecurityState);
} else if (SpdmReturn == LIBSPDM_STATUS_VERIF_NO_AUTHORITY) {
*IsValidCertChain = TRUE;
*AuthState = TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_NO_AUTH;
SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_CERTIFIACTE_FAILURE;
*ValidSlotId = SlotId;
}
}
if ((SlotId >= SPDM_MAX_SLOT_COUNT) && (*ValidSlotId == SPDM_MAX_SLOT_COUNT)) {
SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_DEVICE_ERROR;
return EFI_DEVICE_ERROR;
}
if (TrustAnchor != NULL) {
*RootCertMatch = TRUE;
*ValidSlotId = SlotId;
} else {
*ValidSlotId = 0;
}
DEBUG ((DEBUG_INFO, "SpdmGetCertificateEx - SpdmReturn %p, TrustAnchorSize 0x%x, RootCertMatch %d\n", SpdmReturn, TrustAnchorSize, *RootCertMatch));
return EFI_SUCCESS;
}
}
/**
This function does authentication.
@param[in] SpdmDeviceContext The SPDM context for the device.
@param[out] AuthState The auth state of the devices.
@param[in] ValidSlotId The number of slot for the certificate chain.
@param[in] IsValidCertChain Indicate the validity of CertChain
@param[in] RootCertMatch Indicate the match or mismatch for Rootcert
@param[out] SecurityState The security state of the requester.
@retval EFI_SUCCESS Operation completed successfully.
@retval EFI_OUT_OF_RESOURCES Out of memory.
@retval EFI_DEVICE_ERROR The operation was unsuccessful.
**/
EFI_STATUS
EFIAPI
DoDeviceAuthentication (
IN SPDM_DEVICE_CONTEXT *SpdmDeviceContext,
OUT UINT8 *AuthState,
IN UINT8 ValidSlotId,
IN BOOLEAN IsValidCertChain,
IN BOOLEAN RootCertMatch,
OUT EDKII_DEVICE_SECURITY_STATE *SecurityState
)
{
EFI_STATUS Status;
SPDM_RETURN SpdmReturn;
VOID *SpdmContext;
UINT32 CapabilityFlags;
UINTN DataSize;
SPDM_DATA_PARAMETER Parameter;
UINTN CertChainSize;
UINT8 CertChain[LIBSPDM_MAX_CERT_CHAIN_SIZE];
UINT8 RequesterNonce[SPDM_NONCE_SIZE];
UINT8 ResponderNonce[SPDM_NONCE_SIZE];
VOID *TrustAnchor;
UINTN TrustAnchorSize;
BOOLEAN IsValidChallengeAuthSig;
SpdmContext = SpdmDeviceContext->SpdmContext;
ZeroMem (&Parameter, sizeof (Parameter));
Parameter.location = SpdmDataLocationConnection;
DataSize = sizeof (CapabilityFlags);
SpdmReturn = SpdmGetData (SpdmContext, SpdmDataCapabilityFlags, &Parameter, &CapabilityFlags, &DataSize);
if (LIBSPDM_STATUS_IS_ERROR (SpdmReturn)) {
SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_DEVICE_ERROR;
return EFI_DEVICE_ERROR;
}
IsValidChallengeAuthSig = FALSE;
// get the valid CertChain
CertChainSize = sizeof (CertChain);
ZeroMem (CertChain, sizeof (CertChain));
SpdmReturn = SpdmGetCertificateEx (SpdmContext, NULL, ValidSlotId, &CertChainSize, CertChain, (CONST VOID **)&TrustAnchor, &TrustAnchorSize);
if ((!LIBSPDM_STATUS_IS_SUCCESS (SpdmReturn)) && (!(SpdmReturn == LIBSPDM_STATUS_VERIF_NO_AUTHORITY))) {
return EFI_DEVICE_ERROR;
}
if ((CapabilityFlags & SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CHAL_CAP) == 0) {
*AuthState = TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_NO_BINDING;
SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_DEVICE_NO_CAPABILITIES;
Status = ExtendCertificate (SpdmDeviceContext, *AuthState, CertChainSize, CertChain, NULL, 0, ValidSlotId, SecurityState);
return Status;
} else {
ZeroMem (RequesterNonce, sizeof (RequesterNonce));
ZeroMem (ResponderNonce, sizeof (ResponderNonce));
SpdmReturn = SpdmChallengeEx (SpdmContext, NULL, ValidSlotId, SPDM_CHALLENGE_REQUEST_NO_MEASUREMENT_SUMMARY_HASH, NULL, NULL, NULL, RequesterNonce, ResponderNonce, NULL, 0);
if (SpdmReturn == LIBSPDM_STATUS_SUCCESS) {
IsValidChallengeAuthSig = TRUE;
} else if ((LIBSPDM_STATUS_IS_ERROR (SpdmReturn))) {
IsValidChallengeAuthSig = FALSE;
*AuthState = TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_FAIL_INVALID;
SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_CHALLENGE_FAILURE;
Status = ExtendCertificate (SpdmDeviceContext, *AuthState, 0, NULL, NULL, 0, ValidSlotId, SecurityState);
return Status;
} else {
return EFI_DEVICE_ERROR;
}
if (IsValidCertChain && IsValidChallengeAuthSig && !RootCertMatch) {
*AuthState = TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_NO_AUTH;
SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_NO_CERT_PROVISION;
Status = ExtendCertificate (SpdmDeviceContext, *AuthState, CertChainSize, CertChain, NULL, 0, ValidSlotId, SecurityState);
} else if (IsValidCertChain && IsValidChallengeAuthSig && RootCertMatch) {
*AuthState = TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_SUCCESS;
SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_SUCCESS;
Status = ExtendCertificate (SpdmDeviceContext, *AuthState, CertChainSize, CertChain, TrustAnchor, TrustAnchorSize, ValidSlotId, SecurityState);
}
Status = ExtendAuthentication (SpdmDeviceContext, *AuthState, RequesterNonce, ResponderNonce, SecurityState);
}
return Status;
}

View File

@ -0,0 +1,481 @@
/** @file
EDKII Device Security library for SPDM device.
It follows the SPDM Specification.
Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "SpdmSecurityLibInternal.h"
LIST_ENTRY mSpdmDeviceContextList = INITIALIZE_LIST_HEAD_VARIABLE (mSpdmDeviceContextList);
#define CONNECTUIN_FAILURE_GET_SPDM_UID_FAILED "Fail to get Spdm Uid"
#define CONNECTUIN_FAILURE_STGNATURE_DB_FUL_STRING "The Signature database devdb is full"
/**
record Spdm Io protocol into the context list.
@param[in] SpdmDeviceContext The SPDM context of the device.
**/
VOID
RecordSpdmDeviceContextInList (
IN SPDM_DEVICE_CONTEXT *SpdmDeviceContext
)
{
SPDM_DEVICE_CONTEXT_INSTANCE *NewSpdmDeviceContext;
LIST_ENTRY *SpdmDeviceContextList;
SpdmDeviceContextList = &mSpdmDeviceContextList;
NewSpdmDeviceContext = AllocateZeroPool (sizeof (*NewSpdmDeviceContext));
if (NewSpdmDeviceContext == NULL) {
ASSERT (NewSpdmDeviceContext != NULL);
return;
}
NewSpdmDeviceContext->Signature = SPDM_DEVICE_CONTEXT_INSTANCE_SIGNATURE;
NewSpdmDeviceContext->SpdmDeviceContext = SpdmDeviceContext;
InsertTailList (SpdmDeviceContextList, &NewSpdmDeviceContext->Link);
}
/**
get Spdm Io protocol from Context list via spdm context.
@param[in] SpdmContext The SPDM context of the requester.
return a pointer to the Spdm Io protocol.
**/
VOID *
EFIAPI
GetSpdmIoProtocolViaSpdmContext (
IN VOID *SpdmContext
)
{
LIST_ENTRY *Link;
SPDM_DEVICE_CONTEXT_INSTANCE *CurrentSpdmDeviceContext;
LIST_ENTRY *SpdmDeviceContextList;
SpdmDeviceContextList = &mSpdmDeviceContextList;
Link = GetFirstNode (SpdmDeviceContextList);
while (!IsNull (SpdmDeviceContextList, Link)) {
CurrentSpdmDeviceContext = SPDM_DEVICE_CONTEXT_INSTANCE_FROM_LINK (Link);
if (CurrentSpdmDeviceContext->SpdmDeviceContext->SpdmContext == SpdmContext) {
return CurrentSpdmDeviceContext->SpdmDeviceContext->SpdmIoProtocol;
}
Link = GetNextNode (SpdmDeviceContextList, Link);
}
return NULL;
}
/**
creates and returns Spdm Uid from the volatile variable.
@param[in] SpdmUid A pointer to Spdm Uid.
@retval EFI_SUCCESS Operation completed successfully.
@retval EFI_OUT_OF_RESOURCES Out of memory.
@retval EFI_DEVICE_ERROR The operation was unsuccessful.
**/
EFI_STATUS
GetSpdmUid (
UINT64 *SpdmUid
)
{
EFI_STATUS Status;
UINTN VarSize;
UINT64 Uid;
VarSize = sizeof (*SpdmUid);
Status = gRT->GetVariable (
L"SpdmUid",
&gEfiDeviceSecuritySpdmUidGuid,
NULL,
&VarSize,
&Uid
);
if (Status == EFI_NOT_FOUND) {
Uid = 0;
} else if (EFI_ERROR (Status)) {
return Status;
}
*SpdmUid = Uid++;
Status = gRT->SetVariable (
L"SpdmUid",
&gEfiDeviceSecuritySpdmUidGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS,
sizeof (Uid),
&Uid
);
return Status;
}
/**
Record and log the connection failure string to PCR1.
@param[in] FailureString The failure string.
@param[in] StringLen The length of the string.
@retval EFI_SUCCESS Operation completed successfully.
@retval EFI_OUT_OF_RESOURCES Out of memory.
@retval EFI_DEVICE_ERROR The operation was unsuccessful.
**/
EFI_STATUS
RecordConnectionFailureStatus (
IN CHAR8 *FailureString,
IN UINT32 StringLen
)
{
EFI_STATUS Status;
Status = TpmMeasureAndLogData (
1,
EV_PLATFORM_CONFIG_FLAGS,
FailureString,
StringLen,
FailureString,
StringLen
);
DEBUG ((DEBUG_INFO, "RecordConnectionFailureStatus %r\n", Status));
return Status;
}
/**
This function creates the spdm device context and init connection to the
responder with the device info.
@param[in] SpdmDeviceInfo A pointer to device info.
@param[out] SecurityState A pointer to the security state of the requester.
@return the spdm device conext after the init connection succeeds.
**/
SPDM_DEVICE_CONTEXT *
EFIAPI
CreateSpdmDeviceContext (
IN EDKII_SPDM_DEVICE_INFO *SpdmDeviceInfo,
OUT EDKII_DEVICE_SECURITY_STATE *SecurityState
)
{
SPDM_DEVICE_CONTEXT *SpdmDeviceContext;
VOID *SpdmContext;
UINTN SpdmContextSize;
VOID *ScratchBuffer;
UINTN ScratchBufferSize;
EFI_STATUS Status;
SPDM_RETURN SpdmReturn;
EFI_SIGNATURE_LIST *DbList;
EFI_SIGNATURE_DATA *Cert;
UINTN CertCount;
UINTN Index;
UINTN SiglistHeaderSize;
UINTN DbSize;
VOID *Data;
UINTN DataSize;
SPDM_DATA_PARAMETER Parameter;
UINT8 Data8;
UINT16 Data16;
UINT32 Data32;
UINT8 AuthState;
SpdmDeviceContext = AllocateZeroPool (sizeof (*SpdmDeviceContext));
if (SpdmDeviceContext == NULL) {
ASSERT (SpdmDeviceContext != NULL);
return NULL;
}
SpdmDeviceContext->Signature = SPDM_DEVICE_CONTEXT_SIGNATURE;
CopyMem (&SpdmDeviceContext->DeviceId, SpdmDeviceInfo->DeviceId, sizeof (EDKII_DEVICE_IDENTIFIER));
SpdmDeviceContext->IsEmbeddedDevice = SpdmDeviceInfo->IsEmbeddedDevice;
SpdmContextSize = SpdmGetContextSize ();
SpdmContext = AllocateZeroPool (SpdmContextSize);
if (SpdmContext == NULL) {
ASSERT (SpdmContext != NULL);
goto Error;
}
SpdmReturn = SpdmInitContext (SpdmContext);
if (LIBSPDM_STATUS_IS_ERROR (SpdmReturn)) {
goto Error;
}
SpdmRegisterDeviceIoFunc (
SpdmContext,
SpdmDeviceInfo->SendMessage,
SpdmDeviceInfo->ReceiveMessage
);
SpdmRegisterTransportLayerFunc (
SpdmContext,
SpdmDeviceInfo->MaxSpdmMsgSize,
SpdmDeviceInfo->TransportHeaderSize,
SpdmDeviceInfo->TransportTailSize,
SpdmDeviceInfo->TransportEncodeMessage,
SpdmDeviceInfo->TransportDecodeMessage
);
SpdmRegisterDeviceBufferFunc (
SpdmContext,
SpdmDeviceInfo->SenderBufferSize,
SpdmDeviceInfo->ReceiverBufferSize,
SpdmDeviceInfo->AcquireSenderBuffer,
SpdmDeviceInfo->ReleaseSenderBuffer,
SpdmDeviceInfo->AcquireReceiverBuffer,
SpdmDeviceInfo->ReleaseReceiverBuffer
);
ScratchBufferSize = SpdmGetSizeofRequiredScratchBuffer (SpdmContext);
ScratchBuffer = AllocateZeroPool (ScratchBufferSize);
if (ScratchBuffer == NULL) {
ASSERT (ScratchBuffer != NULL);
goto Error;
}
SpdmSetScratchBuffer (SpdmContext, ScratchBuffer, ScratchBufferSize);
SpdmDeviceContext->SpdmContextSize = SpdmContextSize;
SpdmDeviceContext->SpdmContext = SpdmContext;
SpdmDeviceContext->ScratchBufferSize = ScratchBufferSize;
SpdmDeviceContext->ScratchBuffer = ScratchBuffer;
Status = gBS->HandleProtocol (
SpdmDeviceContext->DeviceId.DeviceHandle,
&gEfiDevicePathProtocolGuid,
(VOID **)&SpdmDeviceContext->DevicePath
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "Locate - DevicePath - %r\n", Status));
goto Error;
}
Status = gBS->HandleProtocol (
SpdmDeviceContext->DeviceId.DeviceHandle,
&SpdmDeviceContext->DeviceId.DeviceType,
(VOID **)&SpdmDeviceContext->DeviceIo
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "Locate - DeviceIo - %r\n", Status));
// This is optional, only check known device type later.
}
if (SpdmDeviceInfo->SpdmIoProtocolGuid != NULL) {
Status = gBS->HandleProtocol (
SpdmDeviceContext->DeviceId.DeviceHandle,
SpdmDeviceInfo->SpdmIoProtocolGuid,
(VOID **)&SpdmDeviceContext->SpdmIoProtocol
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "Locate - SpdmIoProtocol - %r\n", Status));
goto Error;
}
}
if (CompareGuid (&SpdmDeviceContext->DeviceId.DeviceType, &gEdkiiDeviceIdentifierTypePciGuid)) {
if (SpdmDeviceContext->DeviceIo == NULL) {
DEBUG ((DEBUG_ERROR, "Locate - PciIo - %r\n", Status));
goto Error;
}
}
Status = GetSpdmUid (&SpdmDeviceContext->DeviceUID);
if (EFI_ERROR (Status)) {
Status = RecordConnectionFailureStatus (
CONNECTUIN_FAILURE_GET_SPDM_UID_FAILED,
sizeof (CONNECTUIN_FAILURE_GET_SPDM_UID_FAILED)
);
if (EFI_ERROR (Status)) {
goto Error;
}
ASSERT (FALSE);
DEBUG ((DEBUG_ERROR, "Fail to get UID - %r\n", Status));
goto Error;
}
RecordSpdmDeviceContextInList (SpdmDeviceContext);
Status = GetVariable2 (
EFI_DEVICE_SECURITY_DATABASE,
&gEfiDeviceSignatureDatabaseGuid,
(VOID **)&SpdmDeviceContext->SignatureList,
&SpdmDeviceContext->SignatureListSize
);
if ((!EFI_ERROR (Status)) && (SpdmDeviceContext->SignatureList != NULL)) {
DbList = SpdmDeviceContext->SignatureList;
DbSize = SpdmDeviceContext->SignatureListSize;
while ((DbSize > 0) && (SpdmDeviceContext->SignatureListSize >= DbList->SignatureListSize)) {
if (DbList->SignatureListSize == 0) {
break;
}
if ( (!CompareGuid (&DbList->SignatureType, &gEfiCertX509Guid))
|| (DbList->SignatureHeaderSize != 0)
|| (DbList->SignatureSize < sizeof (EFI_SIGNATURE_DATA)))
{
DbSize -= DbList->SignatureListSize;
DbList = (EFI_SIGNATURE_LIST *)((UINT8 *)DbList + DbList->SignatureListSize);
continue;
}
SiglistHeaderSize = sizeof (EFI_SIGNATURE_LIST) + DbList->SignatureHeaderSize;
Cert = (EFI_SIGNATURE_DATA *)((UINT8 *)DbList + SiglistHeaderSize);
CertCount = (DbList->SignatureListSize - SiglistHeaderSize) / DbList->SignatureSize;
for (Index = 0; Index < CertCount; Index++) {
Data = Cert->SignatureData;
DataSize = DbList->SignatureSize - sizeof (EFI_GUID);
ZeroMem (&Parameter, sizeof (Parameter));
Parameter.location = SpdmDataLocationLocal;
SpdmReturn = SpdmSetData (SpdmContext, SpdmDataPeerPublicRootCert, &Parameter, Data, DataSize);
if (LIBSPDM_STATUS_IS_ERROR (SpdmReturn)) {
if (SpdmReturn == LIBSPDM_STATUS_BUFFER_FULL) {
Status = RecordConnectionFailureStatus (
CONNECTUIN_FAILURE_STGNATURE_DB_FUL_STRING,
sizeof (CONNECTUIN_FAILURE_STGNATURE_DB_FUL_STRING)
);
if (EFI_ERROR (Status)) {
goto Error;
}
ASSERT (FALSE);
}
goto Error;
}
Cert = (EFI_SIGNATURE_DATA *)((UINT8 *)Cert + DbList->SignatureSize);
}
DbSize -= DbList->SignatureListSize;
DbList = (EFI_SIGNATURE_LIST *)((UINT8 *)DbList + DbList->SignatureListSize);
}
}
Data8 = 0;
ZeroMem (&Parameter, sizeof (Parameter));
Parameter.location = SpdmDataLocationLocal;
SpdmReturn = SpdmSetData (SpdmContext, SpdmDataCapabilityCTExponent, &Parameter, &Data8, sizeof (Data8));
if (LIBSPDM_STATUS_IS_ERROR (SpdmReturn)) {
ASSERT (FALSE);
goto Error;
}
Data32 = 0;
SpdmReturn = SpdmSetData (SpdmContext, SpdmDataCapabilityFlags, &Parameter, &Data32, sizeof (Data32));
if (LIBSPDM_STATUS_IS_ERROR (SpdmReturn)) {
ASSERT (FALSE);
goto Error;
}
Data8 = SPDM_MEASUREMENT_SPECIFICATION_DMTF;
SpdmReturn = SpdmSetData (SpdmContext, SpdmDataMeasurementSpec, &Parameter, &Data8, sizeof (Data8));
if (LIBSPDM_STATUS_IS_ERROR (SpdmReturn)) {
ASSERT (FALSE);
goto Error;
}
if (SpdmDeviceInfo->BaseAsymAlgo != 0) {
Data32 = SpdmDeviceInfo->BaseAsymAlgo;
} else {
Data32 = SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_2048 |
SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_3072 |
SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_4096 |
SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256 |
SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P384 |
SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P521;
}
SpdmReturn = SpdmSetData (SpdmContext, SpdmDataBaseAsymAlgo, &Parameter, &Data32, sizeof (Data32));
if (LIBSPDM_STATUS_IS_ERROR (SpdmReturn)) {
ASSERT (FALSE);
goto Error;
}
if (SpdmDeviceInfo->BaseHashAlgo != 0) {
Data32 = SpdmDeviceInfo->BaseHashAlgo;
} else {
Data32 = SPDM_ALGORITHMS_BASE_HASH_ALGO_TPM_ALG_SHA_256 |
SPDM_ALGORITHMS_BASE_HASH_ALGO_TPM_ALG_SHA_384 |
SPDM_ALGORITHMS_BASE_HASH_ALGO_TPM_ALG_SHA_512;
}
SpdmReturn = SpdmSetData (SpdmContext, SpdmDataBaseHashAlgo, &Parameter, &Data32, sizeof (Data32));
if (LIBSPDM_STATUS_IS_ERROR (SpdmReturn)) {
ASSERT (FALSE);
goto Error;
}
SpdmReturn = SpdmInitConnection (SpdmContext, FALSE);
if (LIBSPDM_STATUS_IS_ERROR (SpdmReturn)) {
DEBUG ((DEBUG_ERROR, "SpdmInitConnection - %p\n", SpdmReturn));
AuthState = TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_NO_SPDM;
SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_DEVICE_NO_CAPABILITIES;
Status = ExtendCertificate (SpdmDeviceContext, AuthState, 0, NULL, NULL, 0, 0, SecurityState);
if (Status != EFI_SUCCESS) {
DEBUG ((DEBUG_ERROR, "ExtendCertificate AUTH_STATE_NO_SPDM failed\n"));
}
goto Error;
}
ZeroMem (&Parameter, sizeof (Parameter));
Parameter.location = SpdmDataLocationConnection;
DataSize = sizeof (Data16);
SpdmReturn = SpdmGetData (SpdmContext, SpdmDataSpdmVersion, &Parameter, &Data16, &DataSize);
if (LIBSPDM_STATUS_IS_ERROR (SpdmReturn)) {
DEBUG ((DEBUG_ERROR, "SpdmGetData - %p\n", SpdmReturn));
goto Error;
}
SpdmDeviceContext->SpdmVersion = (Data16 >> SPDM_VERSION_NUMBER_SHIFT_BIT);
return SpdmDeviceContext;
Error:
DestroySpdmDeviceContext (SpdmDeviceContext);
return NULL;
}
/**
This function destories the spdm device context.
@param[in] SpdmDeviceContext A pointer to device info.
**/
VOID
EFIAPI
DestroySpdmDeviceContext (
IN SPDM_DEVICE_CONTEXT *SpdmDeviceContext
)
{
// need zero memory in case of secret in memory.
if (SpdmDeviceContext->SpdmContext != NULL) {
ZeroMem (SpdmDeviceContext->SpdmContext, SpdmDeviceContext->SpdmContextSize);
FreePool (SpdmDeviceContext->SpdmContext);
}
if (SpdmDeviceContext->ScratchBuffer != NULL) {
ZeroMem (SpdmDeviceContext->ScratchBuffer, SpdmDeviceContext->ScratchBufferSize);
FreePool (SpdmDeviceContext->ScratchBuffer);
}
if (SpdmDeviceContext->SignatureList != NULL) {
ZeroMem (SpdmDeviceContext->SignatureList, SpdmDeviceContext->SignatureListSize);
FreePool (SpdmDeviceContext->SignatureList);
}
FreePool (SpdmDeviceContext);
}

View File

@ -0,0 +1,714 @@
/** @file
EDKII Device Security library for SPDM device.
It follows the SPDM Specification.
Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "SpdmSecurityLibInternal.h"
/**
This function returns the SPDM device type for TCG SPDM event.
@param[in] SpdmDeviceContext The SPDM context for the device.
@return TCG SPDM device type
**/
UINT32
EFIAPI
GetSpdmDeviceType (
IN SPDM_DEVICE_CONTEXT *SpdmDeviceContext
)
{
if (CompareGuid (&SpdmDeviceContext->DeviceId.DeviceType, &gEdkiiDeviceIdentifierTypePciGuid)) {
return TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_TYPE_PCI;
}
if (CompareGuid (&SpdmDeviceContext->DeviceId.DeviceType, &gEdkiiDeviceIdentifierTypeUsbGuid)) {
return TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_TYPE_USB;
}
return TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_TYPE_NULL;
}
/**
This function returns the SPDM device measurement context size for TCG SPDM event.
@param[in] SpdmDeviceContext The SPDM context for the device.
@return TCG SPDM device measurement context size
**/
UINTN
EFIAPI
GetDeviceMeasurementContextSize (
IN SPDM_DEVICE_CONTEXT *SpdmDeviceContext
)
{
if (CompareGuid (&SpdmDeviceContext->DeviceId.DeviceType, &gEdkiiDeviceIdentifierTypePciGuid)) {
return sizeof (TCG_DEVICE_SECURITY_EVENT_DATA_PCI_CONTEXT);
}
if (CompareGuid (&SpdmDeviceContext->DeviceId.DeviceType, &gEdkiiDeviceIdentifierTypeUsbGuid)) {
// TBD - usb context
return 0;
}
return 0;
}
/**
This function creates the SPDM PCI device measurement context for TCG SPDM event.
@param[in] SpdmDeviceContext The SPDM context for the device.
@param[in, out] DeviceContext The TCG SPDM PCI device measurement context.
@param[in] DeviceContextSize The size of TCG SPDM PCI device measurement context.
@retval EFI_SUCCESS The TCG SPDM PCI device measurement context is returned.
**/
EFI_STATUS
CreatePciDeviceMeasurementContext (
IN SPDM_DEVICE_CONTEXT *SpdmDeviceContext,
IN OUT VOID *DeviceContext,
IN UINTN DeviceContextSize
)
{
TCG_DEVICE_SECURITY_EVENT_DATA_PCI_CONTEXT *PciContext;
PCI_TYPE00 PciData;
EFI_PCI_IO_PROTOCOL *PciIo;
EFI_STATUS Status;
if (DeviceContextSize != sizeof (*PciContext)) {
return EFI_BUFFER_TOO_SMALL;
}
PciIo = SpdmDeviceContext->DeviceIo;
Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0, sizeof (PciData), &PciData);
ASSERT_EFI_ERROR (Status);
PciContext = DeviceContext;
PciContext->Version = TCG_DEVICE_SECURITY_EVENT_DATA_PCI_CONTEXT_VERSION;
PciContext->Length = sizeof (*PciContext);
PciContext->VendorId = PciData.Hdr.VendorId;
PciContext->DeviceId = PciData.Hdr.DeviceId;
PciContext->RevisionID = PciData.Hdr.RevisionID;
PciContext->ClassCode[0] = PciData.Hdr.ClassCode[0];
PciContext->ClassCode[1] = PciData.Hdr.ClassCode[1];
PciContext->ClassCode[2] = PciData.Hdr.ClassCode[2];
if ((PciData.Hdr.HeaderType & HEADER_LAYOUT_CODE) == HEADER_TYPE_DEVICE) {
PciContext->SubsystemVendorID = PciData.Device.SubsystemVendorID;
PciContext->SubsystemID = PciData.Device.SubsystemID;
} else {
PciContext->SubsystemVendorID = 0;
PciContext->SubsystemID = 0;
}
return EFI_SUCCESS;
}
/**
This function creates the SPDM device measurement context for TCG SPDM event.
@param[in] SpdmDeviceContext The SPDM context for the device.
@param[in, out] DeviceContext The TCG SPDM device measurement context.
@param[in] DeviceContextSize The size of TCG SPDM device measurement context.
@retval EFI_SUCCESS The TCG SPDM device measurement context is returned.
@retval EFI_UNSUPPORTED The TCG SPDM device measurement context is unsupported.
**/
EFI_STATUS
EFIAPI
CreateDeviceMeasurementContext (
IN SPDM_DEVICE_CONTEXT *SpdmDeviceContext,
IN OUT VOID *DeviceContext,
IN UINTN DeviceContextSize
)
{
if (CompareGuid (&SpdmDeviceContext->DeviceId.DeviceType, &gEdkiiDeviceIdentifierTypePciGuid)) {
return CreatePciDeviceMeasurementContext (SpdmDeviceContext, DeviceContext, DeviceContextSize);
}
if (CompareGuid (&SpdmDeviceContext->DeviceId.DeviceType, &gEdkiiDeviceIdentifierTypeUsbGuid)) {
return EFI_UNSUPPORTED;
}
return EFI_UNSUPPORTED;
}
/**
This function dumps data.
@param[in] Data A pointer to Data.
@param[in] Size The size of Data.
**/
VOID
EFIAPI
InternalDumpData (
CONST UINT8 *Data,
UINTN Size
)
{
UINTN Index;
for (Index = 0; Index < Size; Index++) {
DEBUG ((DEBUG_INFO, "%02x ", (UINTN)Data[Index]));
}
}
/**
This function extend the PCI digest from the DvSec register.
@param[in] SpdmDeviceContext The SPDM context for the device.
@param[in] AuthState The auth state of the device.
@param[in] MeasurementRecordLength The length of the SPDM measurement record
@param[in] MeasurementRecord The SPDM measurement record
@param[in] RequesterNonce A buffer to hold the requester nonce (32 bytes), if not NULL.
@param[in] ResponderNonce A buffer to hold the responder nonce (32 bytes), if not NULL.
@param[out] SecurityState The Device Security state associated with the device.
@retval EFI_SUCCESS Operation completed successfully.
@retval EFI_OUT_OF_RESOURCES Out of memory.
@retval EFI_DEVICE_ERROR The operation was unsuccessful.
**/
EFI_STATUS
ExtendMeasurement (
IN SPDM_DEVICE_CONTEXT *SpdmDeviceContext,
IN UINT8 AuthState,
IN UINT32 MeasurementRecordLength,
IN UINT8 *MeasurementRecord,
IN UINT8 *RequesterNonce,
IN UINT8 *ResponderNonce,
OUT EDKII_DEVICE_SECURITY_STATE *SecurityState
)
{
UINT32 PcrIndex;
UINT32 EventType;
VOID *EventLog;
UINT32 EventLogSize;
UINT8 *EventLogPtr;
TCG_DEVICE_SECURITY_EVENT_DATA_HEADER2 *EventData2;
TCG_DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_MEASUREMENT_BLOCK *TcgSpdmMeasurementBlock;
VOID *DeviceContext;
UINTN DeviceContextSize;
EFI_STATUS Status;
SPDM_MEASUREMENT_BLOCK_COMMON_HEADER *SpdmMeasurementBlockCommonHeader;
SPDM_MEASUREMENT_BLOCK_DMTF_HEADER *SpdmMeasurementBlockDmtfHeader;
VOID *Digest;
UINTN DigestSize;
UINTN DevicePathSize;
UINT32 MeasurementHashAlgo;
UINTN DataSize;
VOID *SpdmContext;
SPDM_DATA_PARAMETER Parameter;
SpdmContext = SpdmDeviceContext->SpdmContext;
EventLog = NULL;
ZeroMem (&Parameter, sizeof (Parameter));
Parameter.location = SpdmDataLocationConnection;
DataSize = sizeof (MeasurementHashAlgo);
Status = SpdmGetData (SpdmContext, SpdmDataMeasurementHashAlgo, &Parameter, &MeasurementHashAlgo, &DataSize);
ASSERT_EFI_ERROR (Status);
if (MeasurementRecord != NULL) {
SpdmMeasurementBlockCommonHeader = (VOID *)MeasurementRecord;
SpdmMeasurementBlockDmtfHeader = (VOID *)(SpdmMeasurementBlockCommonHeader + 1);
Digest = (SpdmMeasurementBlockDmtfHeader + 1);
DigestSize = MeasurementRecordLength - sizeof (SPDM_MEASUREMENT_BLOCK_DMTF);
DEBUG ((DEBUG_INFO, "SpdmMeasurementBlockCommonHeader\n"));
DEBUG ((DEBUG_INFO, " Index - 0x%02x\n", SpdmMeasurementBlockCommonHeader->Index));
DEBUG ((DEBUG_INFO, " MeasurementSpecification - 0x%02x\n", SpdmMeasurementBlockCommonHeader->MeasurementSpecification));
DEBUG ((DEBUG_INFO, " MeasurementSize - 0x%04x\n", SpdmMeasurementBlockCommonHeader->MeasurementSize));
DEBUG ((DEBUG_INFO, "SpdmMeasurementBlockDmtfHeader\n"));
DEBUG ((DEBUG_INFO, " DMTFSpecMeasurementValueType - 0x%02x\n", SpdmMeasurementBlockDmtfHeader->DMTFSpecMeasurementValueType));
DEBUG ((DEBUG_INFO, " DMTFSpecMeasurementValueSize - 0x%04x\n", SpdmMeasurementBlockDmtfHeader->DMTFSpecMeasurementValueSize));
DEBUG ((DEBUG_INFO, "Measurement - "));
InternalDumpData (Digest, DigestSize);
DEBUG ((DEBUG_INFO, "\n"));
if (MeasurementRecordLength <= sizeof (SPDM_MEASUREMENT_BLOCK_COMMON_HEADER) + sizeof (SPDM_MEASUREMENT_BLOCK_DMTF_HEADER)) {
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_ERROR_MEASUREMENT_AUTH_FAILURE;
return EFI_SECURITY_VIOLATION;
}
if ((SpdmMeasurementBlockCommonHeader->MeasurementSpecification & SPDM_MEASUREMENT_SPECIFICATION_DMTF) == 0) {
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_ERROR_MEASUREMENT_AUTH_FAILURE;
return EFI_SECURITY_VIOLATION;
}
if (SpdmMeasurementBlockCommonHeader->MeasurementSize != MeasurementRecordLength - sizeof (SPDM_MEASUREMENT_BLOCK_COMMON_HEADER)) {
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_ERROR_MEASUREMENT_AUTH_FAILURE;
return EFI_SECURITY_VIOLATION;
}
if (SpdmMeasurementBlockDmtfHeader->DMTFSpecMeasurementValueSize != SpdmMeasurementBlockCommonHeader->MeasurementSize - sizeof (SPDM_MEASUREMENT_BLOCK_DMTF_HEADER)) {
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_ERROR_MEASUREMENT_AUTH_FAILURE;
return EFI_SECURITY_VIOLATION;
}
//
// Use PCR 2 for Firmware Blob code.
//
switch (SpdmMeasurementBlockDmtfHeader->DMTFSpecMeasurementValueType & 0x7F) {
case SPDM_MEASUREMENT_BLOCK_MEASUREMENT_TYPE_IMMUTABLE_ROM:
case SPDM_MEASUREMENT_BLOCK_MEASUREMENT_TYPE_MUTABLE_FIRMWARE:
case SPDM_MEASUREMENT_BLOCK_MEASUREMENT_TYPE_VERSION:
case SPDM_MEASUREMENT_BLOCK_MEASUREMENT_TYPE_SECURE_VERSION_NUMBER:
if (SpdmDeviceContext->IsEmbeddedDevice) {
PcrIndex = 0;
} else {
PcrIndex = 2;
}
EventType = EV_EFI_SPDM_FIRMWARE_BLOB;
break;
case SPDM_MEASUREMENT_BLOCK_MEASUREMENT_TYPE_HARDWARE_CONFIGURATION:
case SPDM_MEASUREMENT_BLOCK_MEASUREMENT_TYPE_FIRMWARE_CONFIGURATION:
case SPDM_MEASUREMENT_BLOCK_MEASUREMENT_TYPE_DEVICE_MODE:
if (SpdmDeviceContext->IsEmbeddedDevice) {
PcrIndex = 1;
} else {
PcrIndex = 3;
}
EventType = EV_EFI_SPDM_FIRMWARE_CONFIG;
break;
case SPDM_MEASUREMENT_BLOCK_MEASUREMENT_TYPE_MEASUREMENT_MANIFEST:
// skip manifest, because manifest doesn't belong to the EV_EFI_SPDM_FIRMWARE_BLOB and EV_EFI_SPDM_FIRMWARE_CONFIG
default:
return EFI_SUCCESS;
}
} else {
if (SpdmDeviceContext->IsEmbeddedDevice) {
PcrIndex = 0;
} else {
PcrIndex = 2;
}
EventType = EV_EFI_SPDM_FIRMWARE_BLOB;
}
DeviceContextSize = GetDeviceMeasurementContextSize (SpdmDeviceContext);
DevicePathSize = GetDevicePathSize (SpdmDeviceContext->DevicePath);
switch (AuthState) {
case TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_SUCCESS:
EventLogSize = (UINT32)(sizeof (TCG_DEVICE_SECURITY_EVENT_DATA_HEADER2) +
sizeof (UINT64) + DevicePathSize +
sizeof (TCG_DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_MEASUREMENT_BLOCK) +
MeasurementRecordLength +
DeviceContextSize);
EventLog = AllocatePool (EventLogSize);
if (EventLog == NULL) {
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_ERROR_UEFI_OUT_OF_RESOURCE;
return EFI_OUT_OF_RESOURCES;
}
EventLogPtr = EventLog;
EventData2 = (VOID *)EventLogPtr;
CopyMem (EventData2->Signature, TCG_DEVICE_SECURITY_EVENT_DATA_SIGNATURE_2, sizeof (EventData2->Signature));
EventData2->Version = TCG_DEVICE_SECURITY_EVENT_DATA_VERSION_2;
EventData2->AuthState = AuthState;
EventData2->Reserved = 0;
EventData2->Length = (UINT32)EventLogSize;
EventData2->DeviceType = GetSpdmDeviceType (SpdmDeviceContext);
EventData2->SubHeaderType = TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_SUB_HEADER_TYPE_SPDM_MEASUREMENT_BLOCK;
EventData2->SubHeaderLength = sizeof (TCG_DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_MEASUREMENT_BLOCK) + MeasurementRecordLength;
EventData2->SubHeaderUID = SpdmDeviceContext->DeviceUID;
EventLogPtr = (VOID *)(EventData2 + 1);
*(UINT64 *)EventLogPtr = (UINT64)DevicePathSize;
EventLogPtr += sizeof (UINT64);
CopyMem (EventLogPtr, SpdmDeviceContext->DevicePath, DevicePathSize);
EventLogPtr += DevicePathSize;
TcgSpdmMeasurementBlock = (VOID *)EventLogPtr;
TcgSpdmMeasurementBlock->SpdmVersion = SpdmDeviceContext->SpdmVersion;
TcgSpdmMeasurementBlock->SpdmMeasurementBlockCount = 1;
TcgSpdmMeasurementBlock->Reserved = 0;
TcgSpdmMeasurementBlock->SpdmMeasurementHashAlgo = MeasurementHashAlgo;
EventLogPtr += sizeof (TCG_DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_MEASUREMENT_BLOCK);
if ((MeasurementRecord != NULL) && (MeasurementRecordLength != 0)) {
CopyMem (EventLogPtr, MeasurementRecord, MeasurementRecordLength);
EventLogPtr += MeasurementRecordLength;
}
if (DeviceContextSize != 0) {
DeviceContext = (VOID *)EventLogPtr;
Status = CreateDeviceMeasurementContext (SpdmDeviceContext, DeviceContext, DeviceContextSize);
if (Status != EFI_SUCCESS) {
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_ERROR_DEVICE_ERROR;
Status = EFI_DEVICE_ERROR;
goto Exit;
}
}
Status = TpmMeasureAndLogData (
PcrIndex,
EventType,
EventLog,
EventLogSize,
EventLog,
EventLogSize
);
if (EFI_ERROR (Status)) {
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_ERROR_TCG_EXTEND_TPM_PCR;
}
DEBUG ((DEBUG_INFO, "TpmMeasureAndLogData (Measurement) - %r\n", Status));
break;
case TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_FAIL_INVALID:
EventLogSize = (UINT32)(sizeof (TCG_DEVICE_SECURITY_EVENT_DATA_HEADER2) +
sizeof (UINT64) + DevicePathSize +
DeviceContextSize);
EventLog = AllocatePool (EventLogSize);
if (EventLog == NULL) {
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_ERROR_UEFI_OUT_OF_RESOURCE;
return EFI_OUT_OF_RESOURCES;
}
EventLogPtr = EventLog;
EventData2 = (VOID *)EventLogPtr;
CopyMem (EventData2->Signature, TCG_DEVICE_SECURITY_EVENT_DATA_SIGNATURE_2, sizeof (EventData2->Signature));
EventData2->Version = TCG_DEVICE_SECURITY_EVENT_DATA_VERSION_2;
EventData2->AuthState = AuthState;
EventData2->Reserved = 0;
EventData2->Length = (UINT32)EventLogSize;
EventData2->DeviceType = GetSpdmDeviceType (SpdmDeviceContext);
EventData2->SubHeaderType = TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_SUB_HEADER_TYPE_SPDM_MEASUREMENT_BLOCK;
EventData2->SubHeaderLength = 0;
EventData2->SubHeaderUID = SpdmDeviceContext->DeviceUID;
EventLogPtr = (VOID *)(EventData2 + 1);
*(UINT64 *)EventLogPtr = (UINT64)DevicePathSize;
EventLogPtr += sizeof (UINT64);
CopyMem (EventLogPtr, SpdmDeviceContext->DevicePath, DevicePathSize);
EventLogPtr += DevicePathSize;
if (DeviceContextSize != 0) {
DeviceContext = (VOID *)EventLogPtr;
Status = CreateDeviceMeasurementContext (SpdmDeviceContext, DeviceContext, DeviceContextSize);
if (Status != EFI_SUCCESS) {
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_ERROR_DEVICE_ERROR;
Status = EFI_DEVICE_ERROR;
goto Exit;
}
}
Status = TpmMeasureAndLogData (
PcrIndex,
EventType,
EventLog,
EventLogSize,
EventLog,
EventLogSize
);
if (EFI_ERROR (Status)) {
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_ERROR_TCG_EXTEND_TPM_PCR;
}
DEBUG ((DEBUG_INFO, "TpmMeasureAndLogData (Measurement) - %r\n", Status));
goto Exit;
default:
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_ERROR_UEFI_UNSUPPORTED;
return EFI_UNSUPPORTED;
}
if (RequesterNonce != NULL) {
TCG_NV_INDEX_DYNAMIC_EVENT_LOG_STRUCT_SPDM_GET_MEASUREMENTS DynamicEventLogSpdmGetMeasurementsEvent;
CopyMem (DynamicEventLogSpdmGetMeasurementsEvent.Header.Signature, TCG_NV_EXTEND_INDEX_FOR_DYNAMIC_SIGNATURE, sizeof (TCG_NV_EXTEND_INDEX_FOR_DYNAMIC_SIGNATURE));
DynamicEventLogSpdmGetMeasurementsEvent.Header.Version = TCG_NV_INDEX_DYNAMIC_EVENT_LOG_STRUCT_VERSION;
ZeroMem (DynamicEventLogSpdmGetMeasurementsEvent.Header.Reserved, sizeof (DynamicEventLogSpdmGetMeasurementsEvent.Header.Reserved));
DynamicEventLogSpdmGetMeasurementsEvent.Header.Uid = SpdmDeviceContext->DeviceUID;
DynamicEventLogSpdmGetMeasurementsEvent.DescriptionSize = sizeof (TCG_SPDM_GET_MEASUREMENTS_DESCRIPTION);
CopyMem (DynamicEventLogSpdmGetMeasurementsEvent.Description, TCG_SPDM_GET_MEASUREMENTS_DESCRIPTION, sizeof (TCG_SPDM_GET_MEASUREMENTS_DESCRIPTION));
DynamicEventLogSpdmGetMeasurementsEvent.DataSize = SPDM_NONCE_SIZE;
CopyMem (DynamicEventLogSpdmGetMeasurementsEvent.Data, RequesterNonce, SPDM_NONCE_SIZE);
Status = TpmMeasureAndLogData (
TCG_NV_EXTEND_INDEX_FOR_DYNAMIC,
EV_NO_ACTION,
&DynamicEventLogSpdmGetMeasurementsEvent,
sizeof (DynamicEventLogSpdmGetMeasurementsEvent),
&DynamicEventLogSpdmGetMeasurementsEvent,
sizeof (DynamicEventLogSpdmGetMeasurementsEvent)
);
if (EFI_ERROR (Status)) {
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_ERROR_TCG_EXTEND_TPM_PCR;
}
DEBUG ((DEBUG_INFO, "TpmMeasureAndLogData (Dynamic) - %r\n", Status));
}
if (ResponderNonce != NULL) {
TCG_NV_INDEX_DYNAMIC_EVENT_LOG_STRUCT_SPDM_MEASUREMENTS DynamicEventLogSpdmMeasurementsEvent;
CopyMem (DynamicEventLogSpdmMeasurementsEvent.Header.Signature, TCG_NV_EXTEND_INDEX_FOR_DYNAMIC_SIGNATURE, sizeof (TCG_NV_EXTEND_INDEX_FOR_DYNAMIC_SIGNATURE));
DynamicEventLogSpdmMeasurementsEvent.Header.Version = TCG_NV_INDEX_DYNAMIC_EVENT_LOG_STRUCT_VERSION;
ZeroMem (DynamicEventLogSpdmMeasurementsEvent.Header.Reserved, sizeof (DynamicEventLogSpdmMeasurementsEvent.Header.Reserved));
DynamicEventLogSpdmMeasurementsEvent.Header.Uid = SpdmDeviceContext->DeviceUID;
DynamicEventLogSpdmMeasurementsEvent.DescriptionSize = sizeof (TCG_SPDM_MEASUREMENTS_DESCRIPTION);
CopyMem (DynamicEventLogSpdmMeasurementsEvent.Description, TCG_SPDM_MEASUREMENTS_DESCRIPTION, sizeof (TCG_SPDM_MEASUREMENTS_DESCRIPTION));
DynamicEventLogSpdmMeasurementsEvent.DataSize = SPDM_NONCE_SIZE;
CopyMem (DynamicEventLogSpdmMeasurementsEvent.Data, ResponderNonce, SPDM_NONCE_SIZE);
Status = TpmMeasureAndLogData (
TCG_NV_EXTEND_INDEX_FOR_DYNAMIC,
EV_NO_ACTION,
&DynamicEventLogSpdmMeasurementsEvent,
sizeof (DynamicEventLogSpdmMeasurementsEvent),
&DynamicEventLogSpdmMeasurementsEvent,
sizeof (DynamicEventLogSpdmMeasurementsEvent)
);
if (EFI_ERROR (Status)) {
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_ERROR_TCG_EXTEND_TPM_PCR;
}
DEBUG ((DEBUG_INFO, "TpmMeasureAndLogData (Dynamic) - %r\n", Status));
}
Exit:
if (EventLog != NULL) {
FreePool (EventLog);
}
return Status;
}
/**
This function gets SPDM measurement and extend to TPM.
@param[in] SpdmDeviceContext The SPDM context for the device.
@param[in] SlotId The number of slot id of the certificate.
@param[out] SecurityState A poniter to security state of the requester.
@retval EFI_SUCCESS Operation completed successfully.
@retval EFI_OUT_OF_RESOURCES Out of memory.
@retval EFI_DEVICE_ERROR The operation was unsuccessful.
**/
EFI_STATUS
EFIAPI
DoDeviceMeasurement (
IN SPDM_DEVICE_CONTEXT *SpdmDeviceContext,
IN UINT8 SlotId,
OUT EDKII_DEVICE_SECURITY_STATE *SecurityState
)
{
EFI_STATUS Status;
SPDM_RETURN SpdmReturn;
VOID *SpdmContext;
UINT32 CapabilityFlags;
UINTN DataSize;
SPDM_DATA_PARAMETER Parameter;
UINT8 NumberOfBlocks;
UINT32 MeasurementRecordLength;
UINT8 MeasurementRecord[LIBSPDM_MAX_MEASUREMENT_RECORD_SIZE];
UINT8 Index;
UINT8 RequesterNonce[SPDM_NONCE_SIZE];
UINT8 ResponderNonce[SPDM_NONCE_SIZE];
UINT8 RequestAttribute;
UINT32 MeasurementsBlockSize;
SPDM_MEASUREMENT_BLOCK_DMTF *MeasurementBlock;
UINT8 NumberOfBlock;
UINT8 ReceivedNumberOfBlock;
UINT8 AuthState;
UINT8 ContentChanged;
UINT8 ContentChangedCount;
SpdmContext = SpdmDeviceContext->SpdmContext;
ZeroMem (&Parameter, sizeof (Parameter));
Parameter.location = SpdmDataLocationConnection;
DataSize = sizeof (CapabilityFlags);
SpdmGetData (SpdmContext, SpdmDataCapabilityFlags, &Parameter, &CapabilityFlags, &DataSize);
if ((CapabilityFlags & SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP_SIG) == 0) {
AuthState = TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_FAIL_NO_SIG;
Status = ExtendCertificate (SpdmDeviceContext, AuthState, 0, NULL, NULL, 0, 0, SecurityState);
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_ERROR_DEVICE_NO_CAPABILITIES;
if (Status != EFI_SUCCESS) {
return Status;
} else {
return EFI_UNSUPPORTED;
}
}
RequestAttribute = 0;
RequestAttribute |= SPDM_GET_MEASUREMENTS_REQUEST_ATTRIBUTES_GENERATE_SIGNATURE;
MeasurementRecordLength = sizeof (MeasurementRecord);
ZeroMem (RequesterNonce, sizeof (RequesterNonce));
ZeroMem (ResponderNonce, sizeof (ResponderNonce));
//
// get all measurement once, with signature.
//
SpdmReturn = SpdmGetMeasurementEx (
SpdmContext,
NULL,
RequestAttribute,
SPDM_GET_MEASUREMENTS_REQUEST_MEASUREMENT_OPERATION_ALL_MEASUREMENTS,
SlotId,
NULL,
&NumberOfBlocks,
&MeasurementRecordLength,
MeasurementRecord,
NULL,
RequesterNonce,
ResponderNonce,
NULL,
0
);
if (LIBSPDM_STATUS_IS_SUCCESS (SpdmReturn)) {
DEBUG ((DEBUG_INFO, "NumberOfBlocks %d\n", NumberOfBlocks));
MeasurementBlock = (VOID *)MeasurementRecord;
for (Index = 0; Index < NumberOfBlocks; Index++) {
MeasurementsBlockSize =
sizeof (SPDM_MEASUREMENT_BLOCK_DMTF) +
MeasurementBlock
->MeasurementBlockDmtfHeader
.DMTFSpecMeasurementValueSize;
AuthState = TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_SUCCESS;
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_SUCCESS;
if (Index == NumberOfBlocks - 1) {
Status = ExtendMeasurement (SpdmDeviceContext, AuthState, MeasurementsBlockSize, (UINT8 *)MeasurementBlock, RequesterNonce, ResponderNonce, SecurityState);
} else {
Status = ExtendMeasurement (SpdmDeviceContext, AuthState, MeasurementsBlockSize, (UINT8 *)MeasurementBlock, NULL, NULL, SecurityState);
}
MeasurementBlock = (VOID *)((size_t)MeasurementBlock + MeasurementsBlockSize);
if (Status != EFI_SUCCESS) {
return Status;
}
}
} else if (SpdmReturn == LIBSPDM_STATUS_VERIF_FAIL) {
AuthState = TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_FAIL_INVALID;
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_ERROR_MEASUREMENT_AUTH_FAILURE;
Status = ExtendMeasurement (SpdmDeviceContext, AuthState, 0, NULL, NULL, NULL, SecurityState);
return Status;
} else {
ContentChangedCount = 0;
ContentChangedFlag:
RequestAttribute = 0;
ContentChanged = SPDM_MEASUREMENTS_RESPONSE_CONTENT_NO_CHANGE_DETECTED;
ReceivedNumberOfBlock = 0;
//
// 1. Query the total number of measurements available.
//
SpdmReturn = SpdmGetMeasurement (
SpdmContext,
NULL,
RequestAttribute,
SPDM_GET_MEASUREMENTS_REQUEST_MEASUREMENT_OPERATION_TOTAL_NUMBER_OF_MEASUREMENTS,
SlotId,
NULL,
&NumberOfBlocks,
NULL,
NULL
);
if (LIBSPDM_STATUS_IS_ERROR (SpdmReturn)) {
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_ERROR_DEVICE_ERROR;
return EFI_DEVICE_ERROR;
}
DEBUG ((DEBUG_INFO, "NumberOfBlocks - 0x%x\n", NumberOfBlocks));
ReceivedNumberOfBlock = 0;
for (Index = 1; Index <= 0xFE; Index++) {
if (ReceivedNumberOfBlock == NumberOfBlocks) {
break;
}
DEBUG ((DEBUG_INFO, "Index - 0x%x\n", Index));
//
// 2. query measurement one by one
// get signature in last message only.
//
if (ReceivedNumberOfBlock == NumberOfBlocks - 1) {
RequestAttribute |= SPDM_GET_MEASUREMENTS_REQUEST_ATTRIBUTES_GENERATE_SIGNATURE;
}
MeasurementRecordLength = sizeof (MeasurementRecord);
ZeroMem (RequesterNonce, sizeof (RequesterNonce));
ZeroMem (ResponderNonce, sizeof (ResponderNonce));
SpdmReturn = SpdmGetMeasurementEx (
SpdmContext,
NULL,
RequestAttribute,
Index,
SlotId,
&ContentChanged,
&NumberOfBlock,
&MeasurementRecordLength,
MeasurementRecord,
NULL,
RequesterNonce,
ResponderNonce,
NULL,
0
);
if (LIBSPDM_STATUS_IS_ERROR (SpdmReturn)) {
if (SpdmReturn == LIBSPDM_STATUS_VERIF_FAIL) {
AuthState = TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_FAIL_INVALID;
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_ERROR_DEVICE_ERROR;
Status = ExtendMeasurement (SpdmDeviceContext, AuthState, 0, NULL, NULL, NULL, SecurityState);
return Status;
} else {
continue;
}
}
if ((ReceivedNumberOfBlock == NumberOfBlocks - 1) &&
(ContentChanged == SPDM_MEASUREMENTS_RESPONSE_CONTENT_CHANGE_DETECTED))
{
if (ContentChangedCount == 0) {
ContentChangedCount++;
goto ContentChangedFlag;
} else {
AuthState = TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_FAIL_INVALID;
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_ERROR_DEVICE_ERROR;
Status = ExtendMeasurement (SpdmDeviceContext, AuthState, 0, NULL, NULL, NULL, SecurityState);
return Status;
}
}
DEBUG ((DEBUG_INFO, "ExtendMeasurement...\n"));
AuthState = TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_SUCCESS;
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_SUCCESS;
if (ReceivedNumberOfBlock == NumberOfBlocks - 1) {
Status = ExtendMeasurement (SpdmDeviceContext, AuthState, MeasurementRecordLength, MeasurementRecord, RequesterNonce, ResponderNonce, SecurityState);
} else {
Status = ExtendMeasurement (SpdmDeviceContext, AuthState, MeasurementRecordLength, MeasurementRecord, NULL, ResponderNonce, SecurityState);
}
if (Status != EFI_SUCCESS) {
return Status;
}
ReceivedNumberOfBlock += 1;
}
if (ReceivedNumberOfBlock != NumberOfBlocks) {
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_ERROR_MEASUREMENT_AUTH_FAILURE;
return EFI_DEVICE_ERROR;
}
}
return EFI_SUCCESS;
}

View File

@ -0,0 +1,148 @@
/** @file
EDKII Device Security library for SPDM device.
It follows the SPDM Specification.
Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "SpdmSecurityLibInternal.h"
/**
Helper function to quickly determine whether device authentication boot is enabled.
@retval TRUE device authentication boot is verifiably enabled.
@retval FALSE device authentication boot is either disabled or an error prevented checking.
**/
BOOLEAN
EFIAPI
IsDeviceAuthBootEnabled (
VOID
)
{
EFI_STATUS Status;
UINT8 *DeviceAuthBootMode;
DeviceAuthBootMode = NULL;
Status = GetEfiGlobalVariable2 (EFI_DEVICE_AUTH_BOOT_MODE_NAME, (VOID **)&DeviceAuthBootMode, NULL);
//
// Skip verification if DeviceAuthBootMode variable doesn't exist.
//
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "Cannot check DeviceAuthBootMode variable %r \n ", Status));
return FALSE;
}
//
// Skip verification if DeviceAuthBootMode is disabled but not AuditMode
//
if (*DeviceAuthBootMode == DEVICE_AUTH_BOOT_MODE_DISABLE) {
FreePool (DeviceAuthBootMode);
return FALSE;
} else {
FreePool (DeviceAuthBootMode);
return TRUE;
}
}
/**
The device driver uses this service to authenticate and measure an SPDM device.
@param[in] SpdmDeviceInfo The SPDM context for the device.
@param[in] SecurityPolicy The security policy of this device.
@param[out] SecurityState A pointer to security state if this device.
@retval EFI_SUCCESS The TCG SPDM device measurement context is returned.
@retval EFI_UNSUPPORTED The TCG SPDM device measurement context is unsupported.
**/
EFI_STATUS
EFIAPI
SpdmDeviceAuthenticationAndMeasurement (
IN EDKII_SPDM_DEVICE_INFO *SpdmDeviceInfo,
IN EDKII_DEVICE_SECURITY_POLICY *SecurityPolicy,
OUT EDKII_DEVICE_SECURITY_STATE *SecurityState
)
{
EFI_STATUS Status;
SPDM_DEVICE_CONTEXT *SpdmDeviceContext;
UINT8 AuthState;
UINT8 SlotId;
BOOLEAN IsValidCertChain;
BOOLEAN RootCertMatch;
if ((PcdGet32 (PcdTcgPfpMeasurementRevision) < TCG_EfiSpecIDEventStruct_SPEC_ERRATA_TPM2_REV_106) ||
(PcdGet8 (PcdEnableSpdmDeviceAuthentication) == 0))
{
return EFI_UNSUPPORTED;
}
SpdmDeviceContext = CreateSpdmDeviceContext (SpdmDeviceInfo, SecurityState);
if (SpdmDeviceContext == NULL) {
return EFI_UNSUPPORTED;
}
Status = EFI_SUCCESS;
AuthState = TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_SUCCESS;
SlotId = 0;
IsValidCertChain = FALSE;
RootCertMatch = FALSE;
if (((SecurityPolicy->AuthenticationPolicy & EDKII_DEVICE_AUTHENTICATION_REQUIRED) != 0) ||
((SecurityPolicy->MeasurementPolicy & EDKII_DEVICE_MEASUREMENT_REQUIRED) != 0))
{
Status = DoDeviceCertificate (SpdmDeviceContext, &AuthState, &SlotId, SecurityState, &IsValidCertChain, &RootCertMatch);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "DoDeviceCertificate failed - %r\n", Status));
goto Ret;
} else if ((AuthState == TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_FAIL_NO_SIG) ||
(AuthState == TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_FAIL_INVALID))
{
goto Ret;
}
}
if (((SecurityPolicy->AuthenticationPolicy & EDKII_DEVICE_AUTHENTICATION_REQUIRED) != 0) && (IsDeviceAuthBootEnabled ())) {
Status = DoDeviceAuthentication (SpdmDeviceContext, &AuthState, SlotId, IsValidCertChain, RootCertMatch, SecurityState);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "DoDeviceAuthentication failed - %r\n", Status));
goto Ret;
} else if ((AuthState == TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_FAIL_NO_SIG) ||
(AuthState == TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_FAIL_INVALID))
{
goto Ret;
}
}
if ((SecurityPolicy->MeasurementPolicy & EDKII_DEVICE_MEASUREMENT_REQUIRED) != 0) {
Status = DoDeviceMeasurement (SpdmDeviceContext, SlotId, SecurityState);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "DoDeviceMeasurement failed - %r\n", Status));
}
}
Ret:
DestroySpdmDeviceContext (SpdmDeviceContext);
return Status;
}
/**
This function will get SpdmIoProtocol via Context.
@param[in] SpdmContext The SPDM context for the device.
return the pointer of Spdm Io protocol
**/
VOID *
EFIAPI
SpdmGetIoProtocolViaSpdmContext (
IN VOID *SpdmContext
)
{
return GetSpdmIoProtocolViaSpdmContext (SpdmContext);
}

View File

@ -0,0 +1,54 @@
## @file
# SPDM library.
#
# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = SpdmSecurityLib
FILE_GUID = 77D7770D-158E-4354-B813-B8792A0E982D
MODULE_TYPE = BASE
VERSION_STRING = 1.0
LIBRARY_CLASS = SpdmSecurityLib
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 AARCH64
#
[Sources]
SpdmSecurityLibInternal.h
SpdmSecurityLib.c
SpdmConnectionInit.c
SpdmMeasurement.c
SpdmAuthentication.c
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
SecurityPkg/SecurityPkg.dec
CryptoPkg/CryptoPkg.dec
[LibraryClasses]
BaseLib
BaseMemoryLib
DebugLib
BaseCryptLib
RngLib
TpmMeasurementLib
SpdmRequesterLib
SpdmCommonLib
[Guids]
gEfiDeviceSignatureDatabaseGuid ## CONSUMES
gEfiCertX509Guid ## CONSUMES
gEfiDeviceSecuritySpdmUidGuid ## PRODUCES AND CONSUMES
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdTcgPfpMeasurementRevision ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdEnableSpdmDeviceAuthentication ## CONSUMES

View File

@ -0,0 +1,250 @@
/** @file
EDKII Device Security library for SPDM device.
It follows the SPDM Specification.
Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef SPDM_SECURITY_LIB_INTERNAL_H_
#define SPDM_SECURITY_LIB_INTERNAL_H_
#include <Uefi.h>
#include <hal/base.h>
#include <Stub/SpdmLibStub.h>
#include <industry_standard/spdm.h>
#include <industry_standard/spdm_secured_message.h>
#include <IndustryStandard/Pci.h>
#include <IndustryStandard/Tpm20.h>
#include <IndustryStandard/UefiTcgPlatform.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/DevicePathLib.h>
#include <Library/UefiLib.h>
#include <Library/TpmMeasurementLib.h>
#include <Library/RngLib.h>
#include <Library/BaseCryptLib.h>
#include <library/spdm_requester_lib.h>
#include <Guid/DeviceAuthentication.h>
#include <Guid/ImageAuthentication.h>
#include <Protocol/PciIo.h>
#include <Library/SpdmSecurityLib.h>
#include "library/spdm_crypt_lib.h"
#define SPDM_DEVICE_CONTEXT_SIGNATURE SIGNATURE_32 ('S', 'P', 'D', 'C')
typedef struct {
UINT32 Signature;
// UEFI Context
EDKII_DEVICE_IDENTIFIER DeviceId;
BOOLEAN IsEmbeddedDevice;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
VOID *DeviceIo;
UINT64 DeviceUID;
// SPDM Context
UINTN SpdmContextSize;
VOID *SpdmContext;
UINTN ScratchBufferSize;
VOID *ScratchBuffer;
UINT8 SpdmVersion;
VOID *SpdmIoProtocol;
EFI_SIGNATURE_LIST *SignatureList;
UINTN SignatureListSize;
} SPDM_DEVICE_CONTEXT;
typedef struct {
UINTN Signature;
LIST_ENTRY Link;
SPDM_DEVICE_CONTEXT *SpdmDeviceContext;
} SPDM_DEVICE_CONTEXT_INSTANCE;
#define SPDM_DEVICE_CONTEXT_INSTANCE_SIGNATURE SIGNATURE_32 ('S', 'D', 'C', 'S')
#define SPDM_DEVICE_CONTEXT_INSTANCE_FROM_LINK(a) CR (a, SPDM_DEVICE_CONTEXT_INSTANCE, Link, SPDM_DEVICE_CONTEXT_INSTANCE_SIGNATURE)
VOID *
EFIAPI
GetSpdmIoProtocolViaSpdmContext (
IN VOID *SpdmContext
);
/**
This function creates the spdm device context and init connection to the
responder with the device info.
@param[in] SpdmDeviceInfo A pointer to device info.
@param[out] SecurityState A pointer to the security state of the requester.
@return the spdm device conext after the init connection succeeds.
**/
SPDM_DEVICE_CONTEXT *
EFIAPI
CreateSpdmDeviceContext (
IN EDKII_SPDM_DEVICE_INFO *SpdmDeviceInfo,
OUT EDKII_DEVICE_SECURITY_STATE *SecurityState
);
VOID
EFIAPI
DestroySpdmDeviceContext (
IN SPDM_DEVICE_CONTEXT *SpdmDeviceContext
);
/**
This function returns the SPDM device type for TCG SPDM event.
@param[in] SpdmDeviceContext The SPDM context for the device.
@return TCG SPDM device type
**/
UINT32
EFIAPI
GetSpdmDeviceType (
IN SPDM_DEVICE_CONTEXT *SpdmDeviceContext
);
/**
This function returns the SPDM device measurement context size for TCG SPDM event.
@param[in] SpdmDeviceContext The SPDM context for the device.
@return TCG SPDM device measurement context size
**/
UINTN
EFIAPI
GetDeviceMeasurementContextSize (
IN SPDM_DEVICE_CONTEXT *SpdmDeviceContext
);
/**
This function creates the SPDM device measurement context for TCG SPDM event.
@param[in] SpdmDeviceContext The SPDM context for the device.
@param[in, OUT] DeviceContext The TCG SPDM device measurement context.
@param[in] DeviceContextSize The size of TCG SPDM device measurement context.
@retval EFI_SUCCESS The TCG SPDM device measurement context is returned.
@retval EFI_UNSUPPORTED The TCG SPDM device measurement context is unsupported.
**/
EFI_STATUS
EFIAPI
CreateDeviceMeasurementContext (
IN SPDM_DEVICE_CONTEXT *SpdmDeviceContext,
IN OUT VOID *DeviceContext,
IN UINTN DeviceContextSize
);
/**
Extend Certicate and auth state to NV Index and measure trust anchor to PCR.
@param[in] SpdmDeviceContext The SPDM context for the device.
@param[in] AuthState The auth state of this deice.
@param[in] CertChainSize The size of cert chain.
@param[in] CertChain A pointer to a destination buffer to store the certificate chain.
@param[in] TrustAnchor A buffer to hold the trust_anchor which is used to validate the peer
certificate, if not NULL.
@param[in] TrustAnchorSize A buffer to hold the trust_anchor_size, if not NULL..
@param[in] SlotId The number of slot for the certificate chain.
@param[out] SecurityState A pointer to the security state of the requester.
@retval EFI_SUCCESS Operation completed successfully.
@retval EFI_OUT_OF_RESOURCES Out of memory.
@retval EFI_DEVICE_ERROR The operation was unsuccessful.
**/
EFI_STATUS
ExtendCertificate (
IN SPDM_DEVICE_CONTEXT *SpdmDeviceContext,
IN UINT8 AuthState,
IN UINTN CertChainSize,
IN UINT8 *CertChain,
IN VOID *TrustAnchor,
IN UINTN TrustAnchorSize,
IN UINT8 SlotId,
OUT EDKII_DEVICE_SECURITY_STATE *SecurityState
);
/**
This function executes SPDM measurement and extend to TPM.
@param[in] SpdmDeviceContext The SPDM context for the device.
**/
EFI_STATUS
EFIAPI
DoDeviceMeasurement (
IN SPDM_DEVICE_CONTEXT *SpdmDeviceContext,
IN UINT8 SlotId,
OUT EDKII_DEVICE_SECURITY_STATE *SecurityState
);
/**
This function gets SPDM digest and certificates.
@param[in] SpdmDeviceContext The SPDM context for the device.
@param[out] AuthState The auth state of the devices.
@param[out] ValidSlotId The number of slot for the certificate chain.
@param[out] SecurityState The security state of the requester.
@param[out] IsValidCertChain The validity of the certificate chain.
@param[out] RootCertMatch The authority of the certificate chain.
@retval EFI_SUCCESS Operation completed successfully.
@retval EFI_OUT_OF_RESOURCES Out of memory.
@retval EFI_DEVICE_ERROR The operation was unsuccessful.
**/
EFI_STATUS
EFIAPI
DoDeviceCertificate (
IN SPDM_DEVICE_CONTEXT *SpdmDeviceContext,
OUT UINT8 *AuthState,
OUT UINT8 *ValidSlotId,
OUT EDKII_DEVICE_SECURITY_STATE *SecurityState,
OUT BOOLEAN *IsValidCertChain,
OUT BOOLEAN *RootCertMatch
);
/**
This function does authentication.
@param[in] SpdmDeviceContext The SPDM context for the device.
@param[out] AuthState The auth state of the devices.
@param[in] ValidSlotId The number of slot for the certificate chain.
@param[out] SecurityState The security state of the requester.
@retval EFI_SUCCESS Operation completed successfully.
@retval EFI_OUT_OF_RESOURCES Out of memory.
@retval EFI_DEVICE_ERROR The operation was unsuccessful.
**/
EFI_STATUS
EFIAPI
DoDeviceAuthentication (
IN SPDM_DEVICE_CONTEXT *SpdmDeviceContext,
OUT UINT8 *AuthState,
IN UINT8 ValidSlotId,
IN BOOLEAN IsValidCertChain,
IN BOOLEAN RootCertMatch,
OUT EDKII_DEVICE_SECURITY_STATE *SecurityState
);
/**
* This function dump raw data.
*
* @param data raw data
* @param size raw data size
**/
VOID
EFIAPI
InternalDumpData (
CONST UINT8 *Data,
UINTN Size
);
#endif

View File

@ -0,0 +1,437 @@
/** @file
EDKII Device Security library for SPDM device.
It follows the SPDM Specification.
Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef SPDM_SECURITY_LIB_H_
#define SPDM_SECURITY_LIB_H_
#include <Protocol/DeviceSecurity.h>
#include <Protocol/DeviceSecurityPolicy.h>
/**
* Send an SPDM transport layer message to a device.
*
* The message is an SPDM message with transport layer wrapper,
* or a secured SPDM message with transport layer wrapper.
*
* For requester, the message is a transport layer SPDM request.
* For responder, the message is a transport layer SPDM response.
*
* @param spdm_context A pointer to the SPDM context.
* @param message_size size in bytes of the message data buffer.
* @param message A pointer to a destination buffer to store the message.
* The caller is responsible for having
* either implicit or explicit ownership of the buffer.
* The message pointer shall be inside of
* [msg_buf_ptr, msg_buf_ptr + max_msg_size] from
* acquired sender_buffer.
* @param timeout The timeout, in 100ns units, to use for the execution
* of the message. A timeout value of 0
* means that this function will wait indefinitely for the
* message to execute. If timeout is greater
* than zero, then this function will return RETURN_TIMEOUT if the
* time required to execute the message is greater
* than timeout.
*
* @retval RETURN_SUCCESS The SPDM message is sent successfully.
* @retval RETURN_DEVICE_ERROR A device error occurs when the SPDM message is sent to the device.
* @retval RETURN_INVALID_PARAMETER The message is NULL or the message_size is zero.
* @retval RETURN_TIMEOUT A timeout occurred while waiting for the SPDM message
* to execute.
**/
typedef
SPDM_RETURN
(*SPDM_DEVICE_SEND_MESSAGE_FUNC)(
IN VOID *SpdmContext,
IN UINTN MessageSize,
IN OUT CONST VOID *Message,
IN UINT64 Timeout
);
/**
* Receive an SPDM transport layer message from a device.
*
* The message is an SPDM message with transport layer wrapper,
* or a secured SPDM message with transport layer wrapper.
*
* For requester, the message is a transport layer SPDM response.
* For responder, the message is a transport layer SPDM request.
*
* @param spdm_context A pointer to the SPDM context.
* @param message_size size in bytes of the message data buffer.
* @param message A pointer to a destination buffer to store the message.
* The caller is responsible for having
* either implicit or explicit ownership of the buffer.
* On input, the message pointer shall be msg_buf_ptr from
* acquired receiver_buffer.
* On output, the message pointer shall be inside of
* [msg_buf_ptr, msg_buf_ptr + max_msg_size] from
* acquired receiver_buffer.
* @param timeout The timeout, in 100ns units, to use for the execution
* of the message. A timeout value of 0
* means that this function will wait indefinitely for the
* message to execute. If timeout is greater
* than zero, then this function will return RETURN_TIMEOUT if the
* time required to execute the message is greater
* than timeout.
*
* @retval RETURN_SUCCESS The SPDM message is received successfully.
* @retval RETURN_DEVICE_ERROR A device error occurs when the SPDM message is received from the device.
* @retval RETURN_INVALID_PARAMETER The message is NULL, message_size is NULL or
* the *message_size is zero.
* @retval RETURN_TIMEOUT A timeout occurred while waiting for the SPDM message
* to execute.
**/
typedef
SPDM_RETURN
(*SPDM_DEVICE_RECEIVE_MESSAGE_FUNC)(
IN VOID *SpdmContext,
IN OUT UINTN *MessageSize,
IN OUT VOID **Message,
IN UINT64 Timeout
);
/**
* Encode an SPDM or APP message to a transport layer message.
*
* For normal SPDM message, it adds the transport layer wrapper.
* For secured SPDM message, it encrypts a secured message then adds the transport layer wrapper.
* For secured APP message, it encrypts a secured message then adds the transport layer wrapper.
*
* The APP message is encoded to a secured message directly in SPDM session.
* The APP message format is defined by the transport layer.
* Take MCTP as example: APP message == MCTP header (MCTP_MESSAGE_TYPE_SPDM) + SPDM message
*
* @param spdm_context A pointer to the SPDM context.
* @param session_id Indicates if it is a secured message protected via SPDM session.
* If session_id is NULL, it is a normal message.
* If session_id is NOT NULL, it is a secured message.
* @param is_app_message Indicates if it is an APP message or SPDM message.
* @param is_requester Indicates if it is a requester message.
* @param message_size size in bytes of the message data buffer.
* @param message A pointer to a source buffer to store the message.
* For normal message, it shall point to the acquired sender buffer.
* For secured message, it shall point to the scratch buffer in spdm_context.
* @param transport_message_size size in bytes of the transport message data buffer.
* @param transport_message A pointer to a destination buffer to store the transport message.
* On input, it shall be msg_buf_ptr from sender buffer.
* On output, it will point to acquired sender buffer.
*
* @retval RETURN_SUCCESS The message is encoded successfully.
* @retval RETURN_INVALID_PARAMETER The message is NULL or the message_size is zero.
**/
typedef
SPDM_RETURN
(*SPDM_TRANSPORT_ENCODE_MESSAGE_FUNC)(
IN VOID *SpdmContext,
IN OUT CONST UINT32 *SessionId,
IN BOOLEAN IsAppMessage,
IN BOOLEAN IsRequester,
IN UINTN MessageSize,
IN OUT VOID *Message,
IN OUT UINTN *TransportMessageSize,
IN VOID **TransportMessage
);
/**
* Decode an SPDM or APP message from a transport layer message.
*
* For normal SPDM message, it removes the transport layer wrapper,
* For secured SPDM message, it removes the transport layer wrapper, then decrypts and verifies a secured message.
* For secured APP message, it removes the transport layer wrapper, then decrypts and verifies a secured message.
*
* The APP message is decoded from a secured message directly in SPDM session.
* The APP message format is defined by the transport layer.
* Take MCTP as example: APP message == MCTP header (MCTP_MESSAGE_TYPE_SPDM) + SPDM message
*
* @param spdm_context A pointer to the SPDM context.
* @param session_id Indicates if it is a secured message protected via SPDM session.
* If *session_id is NULL, it is a normal message.
* If *session_id is NOT NULL, it is a secured message.
* @param is_app_message Indicates if it is an APP message or SPDM message.
* @param is_requester Indicates if it is a requester message.
* @param transport_message_size size in bytes of the transport message data buffer.
* @param transport_message A pointer to a source buffer to store the transport message.
* For normal message or secured message, it shall point to acquired receiver buffer.
* @param message_size size in bytes of the message data buffer.
* @param message A pointer to a destination buffer to store the message.
* On input, it shall point to the scratch buffer in spdm_context.
* On output, for normal message, it will point to the original receiver buffer.
* On output, for secured message, it will point to the scratch buffer in spdm_context.
*
* @retval RETURN_SUCCESS The message is decoded successfully.
* @retval RETURN_INVALID_PARAMETER The message is NULL or the message_size is zero.
* @retval RETURN_UNSUPPORTED The transport_message is unsupported.
**/
typedef
SPDM_RETURN
(*SPDM_TRANSPORT_DECODE_MESSAGE_FUNC)(
IN VOID *SpdmContext,
IN OUT UINT32 **SessionId,
IN BOOLEAN *IsAppMessage,
IN BOOLEAN IsRequester,
IN UINTN TransportMessageSize,
IN OUT VOID *TransportMessage,
IN OUT UINTN *MessageSize,
IN OUT VOID **Message
);
/**
* Acquire a device sender buffer for transport layer message.
*
* The max_msg_size must be larger than
* MAX (non-secure Transport Message Header Size +
* SPDM_CAPABILITIES.DataTransferSize +
* max alignment pad size (transport specific),
* secure Transport Message Header Size +
* sizeof(spdm_secured_message_a_data_header1_t) +
* length of sequence_number (transport specific) +
* sizeof(spdm_secured_message_a_data_header2_t) +
* sizeof(spdm_secured_message_cipher_header_t) +
* App Message Header Size (transport specific) +
* SPDM_CAPABILITIES.DataTransferSize +
* maximum random data size (transport specific) +
* AEAD MAC size (16) +
* max alignment pad size (transport specific))
*
* For MCTP,
* Transport Message Header Size = sizeof(mctp_message_header_t)
* length of sequence_number = 2
* App Message Header Size = sizeof(mctp_message_header_t)
* maximum random data size = MCTP_MAX_RANDOM_NUMBER_COUNT
* max alignment pad size = 0
* For PCI_DOE,
* Transport Message Header Size = sizeof(pci_doe_data_object_header_t)
* length of sequence_number = 0
* App Message Header Size = 0
* maximum random data size = 0
* max alignment pad size = 3
*
* @param context A pointer to the SPDM context.
* @param max_msg_size size in bytes of the maximum size of sender buffer.
* @param msg_buf_ptr A pointer to a sender buffer.
*
* @retval RETURN_SUCCESS The sender buffer is acquired.
**/
typedef
SPDM_RETURN
(*SPDM_DEVICE_ACQUIRE_SENDER_BUFFER_FUNC)(
IN VOID *SpdmContext,
IN OUT VOID **MsgBufPtr
);
/**
* Release a device sender buffer for transport layer message.
*
* @param context A pointer to the SPDM context.
* @param msg_buf_ptr A pointer to a sender buffer.
*
* @retval RETURN_SUCCESS The sender buffer is Released.
**/
typedef
VOID
(*SPDM_DEVICE_RELEASE_SENDER_BUFFER_FUNC)(
IN VOID *SpdmContext,
IN CONST VOID *MsgBufPtr
);
/**
* Acquire a device receiver buffer for transport layer message.
*
* The max_msg_size must be larger than
* MAX (non-secure Transport Message Header Size +
* SPDM_CAPABILITIES.DataTransferSize +
* max alignment pad size (transport specific),
* secure Transport Message Header Size +
* sizeof(spdm_secured_message_a_data_header1_t) +
* length of sequence_number (transport specific) +
* sizeof(spdm_secured_message_a_data_header2_t) +
* sizeof(spdm_secured_message_cipher_header_t) +
* App Message Header Size (transport specific) +
* SPDM_CAPABILITIES.DataTransferSize +
* maximum random data size (transport specific) +
* AEAD MAC size (16) +
* max alignment pad size (transport specific))
*
* For MCTP,
* Transport Message Header Size = sizeof(mctp_message_header_t)
* length of sequence_number = 2
* App Message Header Size = sizeof(mctp_message_header_t)
* maximum random data size = MCTP_MAX_RANDOM_NUMBER_COUNT
* max alignment pad size = 0
* For PCI_DOE,
* Transport Message Header Size = sizeof(pci_doe_data_object_header_t)
* length of sequence_number = 0
* App Message Header Size = 0
* maximum random data size = 0
* max alignment pad size = 3
*
* @param context A pointer to the SPDM context.
* @param max_msg_size size in bytes of the maximum size of receiver buffer.
* @param msg_buf_pt A pointer to a receiver buffer.
*
* @retval RETURN_SUCCESS The receiver buffer is acquired.
**/
typedef
SPDM_RETURN
(*SPDM_DEVICE_ACQUIRE_RECEIVER_BUFFER_FUNC)(
IN VOID *SpdmContext,
IN OUT VOID **MsgBufPtr
);
/**
* Release a device receiver buffer for transport layer message.
*
* @param context A pointer to the SPDM context.
* @param msg_buf_ptr A pointer to a receiver buffer.
*
* @retval RETURN_SUCCESS The receiver buffer is Released.
**/
typedef
VOID
(*SPDM_DEVICE_RELEASE_RECEIVER_BUFFER_FUNC)(
IN VOID *SpdmContext,
IN CONST VOID *MsgBufPtr
);
typedef struct {
UINT32 Version;
//
// DeviceType is used to create TCG event log context_data.
// DeviceHandle is used to create TCG event log device_path information.
//
EDKII_DEVICE_IDENTIFIER *DeviceId;
//
// TRUE means to use PCR 0 (code) / 1 (config).
// FALSE means to use PCR 2 (code) / 3 (config).
//
BOOLEAN IsEmbeddedDevice;
//
// Below 9 APIs are used to send/receive SPDM request/response.
//
// The request flow is:
// |<--- SenderBufferSize --->|
// |<--- TransportRequestBufferSize --->|
// |<---MaxHeaderSize--->|<-SpdmRequestBufferSize ->|
// +--+------------------+==========================+----------------+--+
// | | Transport Header | SPDM Message | Transport Tail | |
// +--+------------------+==========================+----------------+--+
// ^ ^ ^
// | | | SpdmRequestBuffer
// | | TransportRequestBuffer
// | SenderBuffer
//
// AcquireSenderBuffer (&SenderBuffer, &SenderBufferSize);
// SpdmRequestBuffer = SenderBuffer + TransportHeaderSize;
// /* build SPDM request in SpdmRequestBuffer */
// TransportEncodeMessage (SpdmRequestBuffer, SpdmRequestBufferSize,
// &TransportRequestBuffer, &TransportRequestBufferSize);
// SendMessage (TransportRequestBuffer, TransportRequestBufferSize);
// ReleaseSenderBuffer (SenderBuffer);
//
// The response flow is:
// |<--- ReceiverBufferSize --->|
// |<--- TransportResponseBufferSize --->|
// |<-SpdmResponseBufferSize->|
// +--+------------------+==========================+----------------+--+
// | | Transport Header | SPDM Message | Transport Tail | |
// +--+------------------+==========================+----------------+--+
// ^ ^ ^
// | | | SpdmResponseBuffer
// | | TransportResponseBuffer
// | ReceiverBuffer
//
// AcquireReceiverBuffer (&ReceiverBuffer, &ReceiverBufferSize);
// TransportResponseBuffer = ReceiverBuffer;
// ReceiveMessage (&TransportResponseBuffer, &TransportResponseBufferSize);
// TransportDecodeMessage (TransportResponseBuffer, TransportResponseBufferSize,
// &SpdmResponseBuffer, &SpdmResponseBufferSize);
// /* process SPDM response in SpdmResponseBuffer */
// ReleaseReceiverBuffer (ReceiverBuffer);
//
//
// API required by SpdmRegisterDeviceIoFunc in libspdm
// It is used to send/receive transport message (SPDM + transport header).
//
SPDM_DEVICE_SEND_MESSAGE_FUNC SendMessage;
SPDM_DEVICE_RECEIVE_MESSAGE_FUNC ReceiveMessage;
//
// API required by SpdmRegisterTransportLayerFunc in libspdm
// It is used to add/remove transport header for SPDM.
//
SPDM_TRANSPORT_ENCODE_MESSAGE_FUNC TransportEncodeMessage;
SPDM_TRANSPORT_DECODE_MESSAGE_FUNC TransportDecodeMessage;
//
// API required by SpdmRegisterDeviceBufferFunc in libspdm
// It is used to get the sender/receiver buffer for transport message (SPDM + transport header).
// The size MUST be big enough to send or receive one transport message (SPDM + transport header).
// Tthe sender/receiver buffer MAY be overlapped.
//
SPDM_DEVICE_ACQUIRE_SENDER_BUFFER_FUNC AcquireSenderBuffer;
SPDM_DEVICE_RELEASE_SENDER_BUFFER_FUNC ReleaseSenderBuffer;
SPDM_DEVICE_ACQUIRE_RECEIVER_BUFFER_FUNC AcquireReceiverBuffer;
SPDM_DEVICE_RELEASE_RECEIVER_BUFFER_FUNC ReleaseReceiverBuffer;
//
// Preferred Algorithm List for SPDM negotiation.
// If it is none zero, it will be used directly.
// If it is zero, then the SpdmSecurityLib will set the default value.
//
UINT32 BaseHashAlgo;
UINT32 BaseAsymAlgo;
//
// transfer size
//
UINT32 MaxSpdmMsgSize;
UINT32 TransportHeaderSize;
UINT32 TransportTailSize;
UINT32 SenderBufferSize;
UINT32 ReceiverBufferSize;
EFI_GUID *SpdmIoProtocolGuid;
} EDKII_SPDM_DEVICE_INFO;
/**
This function will send SPDM VCA, GET_CERTIFICATE, CHALLENGE, GET_MEASUREMENT,
The certificate and measurement will be extended to TPM PCR/NvIndex.
**/
RETURN_STATUS
EFIAPI
SpdmDeviceAuthenticationAndMeasurement (
IN EDKII_SPDM_DEVICE_INFO *SpdmDeviceInfo,
IN EDKII_DEVICE_SECURITY_POLICY *SecurityPolicy,
OUT EDKII_DEVICE_SECURITY_STATE *SecurityState
);
/**
This function will get SpdmIoProtocol via Context.
**/
VOID *
EFIAPI
SpdmGetIoProtocolViaSpdmContext (
IN VOID *SpdmContext
);
/**
Helper function to quickly determine whether device authentication boot is enabled.
@retval TRUE device authentication boot is verifiably enabled.
@retval FALSE device authentication boot is either disabled or an error prevented checking.
**/
BOOLEAN
EFIAPI
IsDeviceAuthBootEnabled (
VOID
);
#endif

View File

@ -0,0 +1,133 @@
/** @file
Platform Device Security Policy Protocol definition
Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef EDKII_DEVICE_SECURITY_POLICY_PROTOCOL_H_
#define EDKII_DEVICE_SECURITY_POLICY_PROTOCOL_H_
#include <Uefi.h>
#include <Protocol/DeviceSecurity.h>
typedef struct _EDKII_DEVICE_SECURITY_POLICY_PROTOCOL EDKII_DEVICE_SECURITY_POLICY_PROTOCOL;
//
// Revision The revision to which the DEVICE_SECURITY_POLICY protocol interface adheres.
// All future revisions must be backwards compatible.
// If a future version is not back wards compatible it is not the same GUID.
//
#define EDKII_DEVICE_SECURITY_POLICY_PROTOCOL_REVISION 0x00010000
//
// Revision The revision to which the DEVICE_SECURITY_POLICY structure adheres.
// All future revisions must be backwards compatible.
//
#define EDKII_DEVICE_SECURITY_POLICY_REVISION 0x00010000
///
/// The macro for the policy defined in EDKII_DEVICE_SECURITY_POLICY
///
#define EDKII_DEVICE_MEASUREMENT_REQUIRED BIT0
#define EDKII_DEVICE_AUTHENTICATION_REQUIRED BIT0
///
/// The device security policy data structure
///
typedef struct {
UINT32 Revision;
UINT32 MeasurementPolicy;
UINT32 AuthenticationPolicy;
} EDKII_DEVICE_SECURITY_POLICY;
//
// Revision The revision to which the DEVICE_SECURITY_STATE structure adheres.
// All future revisions must be backwards compatible.
//
#define EDKII_DEVICE_SECURITY_STATE_REVISION 0x00010000
///
/// The macro for the state defined in EDKII_DEVICE_SECURITY_STATE
///
#define EDKII_DEVICE_SECURITY_STATE_SUCCESS 0
#define EDKII_DEVICE_SECURITY_STATE_ERROR BIT31
#define EDKII_DEVICE_SECURITY_STATE_ERROR_UEFI_UNSUPPORTED (EDKII_DEVICE_SECURITY_STATE_ERROR + 0x0)
#define EDKII_DEVICE_SECURITY_STATE_ERROR_UEFI_GET_POLICY_PROTOCOL (EDKII_DEVICE_SECURITY_STATE_ERROR + 0x1)
#define EDKII_DEVICE_SECURITY_STATE_ERROR_UEFI_OUT_OF_RESOURCE (EDKII_DEVICE_SECURITY_STATE_ERROR + 0x2)
#define EDKII_DEVICE_SECURITY_STATE_ERROR_DEVICE_NO_CAPABILITIES (EDKII_DEVICE_SECURITY_STATE_ERROR + 0x10)
#define EDKII_DEVICE_SECURITY_STATE_ERROR_DEVICE_ERROR (EDKII_DEVICE_SECURITY_STATE_ERROR + 0x11)
#define EDKII_DEVICE_SECURITY_STATE_ERROR_TCG_EXTEND_TPM_PCR (EDKII_DEVICE_SECURITY_STATE_ERROR + 0x20)
#define EDKII_DEVICE_SECURITY_STATE_ERROR_MEASUREMENT_AUTH_FAILURE (EDKII_DEVICE_SECURITY_STATE_ERROR + 0x21)
#define EDKII_DEVICE_SECURITY_STATE_ERROR_CHALLENGE_FAILURE (EDKII_DEVICE_SECURITY_STATE_ERROR + 0x30)
#define EDKII_DEVICE_SECURITY_STATE_ERROR_CERTIFIACTE_FAILURE (EDKII_DEVICE_SECURITY_STATE_ERROR + 0x31)
#define EDKII_DEVICE_SECURITY_STATE_ERROR_NO_CERT_PROVISION (EDKII_DEVICE_SECURITY_STATE_ERROR + 0x32)
///
/// The device security state data structure
///
typedef struct {
UINT32 Revision;
UINT32 MeasurementState;
UINT32 AuthenticationState;
} EDKII_DEVICE_SECURITY_STATE;
/**
This function returns the device security policy associated with the device.
The device security driver may call this interface to get the platform policy
for the specific device and determine if the measurement or authentication
is required.
@param[in] This The protocol instance pointer.
@param[in] DeviceId The Identifier for the device.
@param[out] DeviceSecurityPolicy The Device Security Policy associated with the device.
@retval EFI_SUCCESS The device security policy is returned
@retval EFI_UNSUPPORTED The function is unsupported for the specific Device.
**/
typedef
EFI_STATUS
(EFIAPI *EDKII_DEVICE_SECURITY_GET_DEVICE_POLICY)(
IN EDKII_DEVICE_SECURITY_POLICY_PROTOCOL *This,
IN EDKII_DEVICE_IDENTIFIER *DeviceId,
OUT EDKII_DEVICE_SECURITY_POLICY *DeviceSecurityPolicy
);
/**
This function sets the device state based upon the authentication result.
The device security driver may call this interface to give the platform
a notify based upon the measurement or authentication result.
If the authentication or measurement fails, the platform may choose:
1) Do nothing.
2) Disable this device or slot temporarily and continue boot.
3) Reset the platform and retry again.
4) Disable this device or slot permanently.
5) Any other platform specific action.
@param[in] This The protocol instance pointer.
@param[in] DeviceId The Identifier for the device.
@param[in] DeviceSecurityState The Device Security state associated with the device.
@retval EFI_SUCCESS The device state is set.
@retval EFI_UNSUPPORTED The function is unsupported for the specific Device.
**/
typedef
EFI_STATUS
(EFIAPI *EDKII_DEVICE_SECURITY_NOTIFY_DEVICE_STATE)(
IN EDKII_DEVICE_SECURITY_POLICY_PROTOCOL *This,
IN EDKII_DEVICE_IDENTIFIER *DeviceId,
IN EDKII_DEVICE_SECURITY_STATE *DeviceSecurityState
);
struct _EDKII_DEVICE_SECURITY_POLICY_PROTOCOL {
UINT32 Revision;
EDKII_DEVICE_SECURITY_GET_DEVICE_POLICY GetDevicePolicy;
EDKII_DEVICE_SECURITY_NOTIFY_DEVICE_STATE NotifyDeviceState;
};
extern EFI_GUID gEdkiiDeviceSecurityPolicyProtocolGuid;
#endif

View File

@ -2,12 +2,14 @@
# CI configuration for SecurityPkg # CI configuration for SecurityPkg
# #
# Copyright (c) Microsoft Corporation # Copyright (c) Microsoft Corporation
# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR> # Copyright (c) 2020 - 2024, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent # SPDX-License-Identifier: BSD-2-Clause-Patent
## ##
{ {
"LicenseCheck": { "LicenseCheck": {
"IgnoreFiles": [] "IgnoreFiles": [
"DeviceSecurity/SpdmLib/Include",
]
}, },
"EccCheck": { "EccCheck": {
## Exception sample looks like below: ## Exception sample looks like below:
@ -23,7 +25,10 @@
"IgnoreFiles": [ "IgnoreFiles": [
"Library/TcgStorageCoreLib/TcgStorageUtil.c", "Library/TcgStorageCoreLib/TcgStorageUtil.c",
"Library/TcgStorageCoreLib/TcgStorageCore.c", "Library/TcgStorageCoreLib/TcgStorageCore.c",
"Library/Tpm2CommandLib/Tpm2NVStorage.c" "Library/Tpm2CommandLib/Tpm2NVStorage.c",
"DeviceSecurity/SpdmLib/Include",
"DeviceSecurity/SpdmLib/libspdm",
"DeviceSecurity/OsStub"
] ]
}, },
"CompilerPlugin": { "CompilerPlugin": {
@ -69,7 +74,11 @@
] ]
}, },
"LibraryClassCheck": { "LibraryClassCheck": {
"IgnoreHeaderFile": [] "IgnoreHeaderFile": [
"DeviceSecurity/SpdmLib/Include/library",
"DeviceSecurity/SpdmLib/libspdm/include/library",
],
"skip": True
}, },
## options defined ci/Plugin/SpellCheck ## options defined ci/Plugin/SpellCheck

View File

@ -5,7 +5,7 @@
# It also provides the definitions(including PPIs/PROTOCOLs/GUIDs and library classes) # It also provides the definitions(including PPIs/PROTOCOLs/GUIDs and library classes)
# and libraries instances, which are used for those features. # and libraries instances, which are used for those features.
# #
# Copyright (c) 2009 - 2020, Intel Corporation. All rights reserved.<BR> # Copyright (c) 2009 - 2024, Intel Corporation. All rights reserved.<BR>
# (C) Copyright 2015 Hewlett Packard Enterprise Development LP <BR> # (C) Copyright 2015 Hewlett Packard Enterprise Development LP <BR>
# Copyright (c) Microsoft Corporation.<BR> # Copyright (c) Microsoft Corporation.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent # SPDX-License-Identifier: BSD-2-Clause-Patent
@ -23,6 +23,10 @@
Include Include
Test/Mock/Include Test/Mock/Include
[Includes.Common.Private]
DeviceSecurity/SpdmLib/Include
DeviceSecurity/SpdmLib/libspdm/include
[LibraryClasses] [LibraryClasses]
## @libraryclass Provides hash interfaces from different implementations. ## @libraryclass Provides hash interfaces from different implementations.
# #
@ -97,6 +101,10 @@
# #
PlatformPKProtectionLib|Include/Library/PlatformPKProtectionLib.h PlatformPKProtectionLib|Include/Library/PlatformPKProtectionLib.h
## @libraryclass Perform SPDM (following SPDM spec) and measure data to TPM (following TCG PFP spec).
##
SpdmSecurityLib|Include/Library/SpdmSecurityLib.h
[Guids] [Guids]
## Security package token space guid. ## Security package token space guid.
# Include/Guid/SecurityPkgTokenSpace.h # Include/Guid/SecurityPkgTokenSpace.h
@ -219,6 +227,9 @@
## GUID used to specify section with default dbt content ## GUID used to specify section with default dbt content
gDefaultdbtFileGuid = { 0x36c513ee, 0xa338, 0x4976, { 0xa0, 0xfb, 0x6d, 0xdb, 0xa3, 0xda, 0xfe, 0x87 } } gDefaultdbtFileGuid = { 0x36c513ee, 0xa338, 0x4976, { 0xa0, 0xfb, 0x6d, 0xdb, 0xa3, 0xda, 0xfe, 0x87 } }
## GUID used to generate Spdm Uid
gEfiDeviceSecuritySpdmUidGuid = {0xe37b5665, 0x5ef9, 0x4e7e, {0xb4, 0x91, 0xd6, 0x78, 0xab, 0xff, 0xfb, 0xcb }}
[Ppis] [Ppis]
## The PPI GUID for that TPM physical presence should be locked. ## The PPI GUID for that TPM physical presence should be locked.
# Include/Ppi/LockPhysicalPresence.h # Include/Ppi/LockPhysicalPresence.h

View File

@ -1,7 +1,7 @@
## @file ## @file
# Security Module Package for All Architectures. # Security Module Package for All Architectures.
# #
# Copyright (c) 2009 - 2021, Intel Corporation. All rights reserved.<BR> # Copyright (c) 2009 - 2024, Intel Corporation. All rights reserved.<BR>
# (C) Copyright 2015-2020 Hewlett Packard Enterprise Development LP<BR> # (C) Copyright 2015-2020 Hewlett Packard Enterprise Development LP<BR>
# Copyright (c) 2022, Loongson Technology Corporation Limited. All rights reserved.<BR> # Copyright (c) 2022, Loongson Technology Corporation Limited. All rights reserved.<BR>
# Copyright (c) 2021 - 2022, Arm Limited. All rights reserved.<BR> # Copyright (c) 2021 - 2022, Arm Limited. All rights reserved.<BR>
@ -76,6 +76,19 @@
TdxLib|MdePkg/Library/TdxLib/TdxLib.inf TdxLib|MdePkg/Library/TdxLib/TdxLib.inf
VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
SpdmSecurityLib|SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmSecurityLib.inf
SpdmDeviceSecretLib|SecurityPkg/DeviceSecurity/SpdmLib/SpdmDeviceSecretLibNull.inf
SpdmCryptLib|SecurityPkg/DeviceSecurity/SpdmLib/SpdmCryptLib.inf
SpdmCommonLib|SecurityPkg/DeviceSecurity/SpdmLib/SpdmCommonLib.inf
SpdmRequesterLib|SecurityPkg/DeviceSecurity/SpdmLib/SpdmRequesterLib.inf
SpdmResponderLib|SecurityPkg/DeviceSecurity/SpdmLib/SpdmResponderLib.inf
SpdmSecuredMessageLib|SecurityPkg/DeviceSecurity/SpdmLib/SpdmSecuredMessageLib.inf
SpdmTransportMctpLib|SecurityPkg/DeviceSecurity/SpdmLib/SpdmTransportMctpLib.inf
SpdmTransportPciDoeLib|SecurityPkg/DeviceSecurity/SpdmLib/SpdmTransportPciDoeLib.inf
CryptlibWrapper|SecurityPkg/DeviceSecurity/OsStub/CryptlibWrapper/CryptlibWrapper.inf
PlatformLibWrapper|SecurityPkg/DeviceSecurity/OsStub/PlatformLibWrapper/PlatformLibWrapper.inf
MemLibWrapper|SecurityPkg/DeviceSecurity/OsStub/MemLibWrapper/MemLibWrapper.inf
[LibraryClasses.ARM, LibraryClasses.AARCH64] [LibraryClasses.ARM, LibraryClasses.AARCH64]
# #
# It is not possible to prevent the ARM compiler for generic intrinsic functions. # It is not possible to prevent the ARM compiler for generic intrinsic functions.
@ -287,6 +300,22 @@
# #
SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
#
# SPDM
#
SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmSecurityLib.inf
SecurityPkg/DeviceSecurity/SpdmLib/SpdmDeviceSecretLibNull.inf
SecurityPkg/DeviceSecurity/SpdmLib/SpdmCryptLib.inf
SecurityPkg/DeviceSecurity/SpdmLib/SpdmCommonLib.inf
SecurityPkg/DeviceSecurity/SpdmLib/SpdmRequesterLib.inf
SecurityPkg/DeviceSecurity/SpdmLib/SpdmResponderLib.inf
SecurityPkg/DeviceSecurity/SpdmLib/SpdmSecuredMessageLib.inf
SecurityPkg/DeviceSecurity/SpdmLib/SpdmTransportMctpLib.inf
SecurityPkg/DeviceSecurity/SpdmLib/SpdmTransportPciDoeLib.inf
SecurityPkg/DeviceSecurity/OsStub/CryptlibWrapper/CryptlibWrapper.inf
SecurityPkg/DeviceSecurity/OsStub/PlatformLibWrapper/PlatformLibWrapper.inf
SecurityPkg/DeviceSecurity/OsStub/MemLibWrapper/MemLibWrapper.inf
[Components.IA32, Components.X64] [Components.IA32, Components.X64]
SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf