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