summaryrefslogtreecommitdiffstats
path: root/SecurityPkg/DeviceSecurity
diff options
context:
space:
mode:
Diffstat (limited to 'SecurityPkg/DeviceSecurity')
-rw-r--r--SecurityPkg/DeviceSecurity/OsStub/CryptlibWrapper/CryptlibWrapper.c970
-rw-r--r--SecurityPkg/DeviceSecurity/OsStub/CryptlibWrapper/CryptlibWrapper.inf38
-rw-r--r--SecurityPkg/DeviceSecurity/OsStub/MemLibWrapper/MemLibWrapper.c177
-rw-r--r--SecurityPkg/DeviceSecurity/OsStub/MemLibWrapper/MemLibWrapper.inf33
-rw-r--r--SecurityPkg/DeviceSecurity/OsStub/PlatformLibWrapper/PlatformLibWrapper.c85
-rw-r--r--SecurityPkg/DeviceSecurity/OsStub/PlatformLibWrapper/PlatformLibWrapper.inf33
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmLib/Include/Stub/SpdmLibStub.h347
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/LibspdmStdBoolAlt.h23
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/LibspdmStdDefAlt.h16
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/LibspdmStdIntAlt.h25
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/base.h94
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/library/debuglib.h39
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmLib/Include/library/spdm_lib_config.h394
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmLib/SpdmCommonLib.inf47
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmLib/SpdmCryptLib.inf45
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmLib/SpdmDeviceSecretLibNull.inf36
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmLib/SpdmRequesterLib.inf59
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmLib/SpdmResponderLib.inf61
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmLib/SpdmSecuredMessageLib.inf44
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmLib/SpdmTransportMctpLib.inf38
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmLib/SpdmTransportPciDoeLib.inf38
m---------SecurityPkg/DeviceSecurity/SpdmLib/libspdm0
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmAuthentication.c697
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmConnectionInit.c481
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmMeasurement.c714
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmSecurityLib.c148
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmSecurityLib.inf54
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmSecurityLibInternal.h250
28 files changed, 4986 insertions, 0 deletions
diff --git a/SecurityPkg/DeviceSecurity/OsStub/CryptlibWrapper/CryptlibWrapper.c b/SecurityPkg/DeviceSecurity/OsStub/CryptlibWrapper/CryptlibWrapper.c
new file mode 100644
index 0000000000..64db9750ff
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/OsStub/CryptlibWrapper/CryptlibWrapper.c
@@ -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
+ );
+}
diff --git a/SecurityPkg/DeviceSecurity/OsStub/CryptlibWrapper/CryptlibWrapper.inf b/SecurityPkg/DeviceSecurity/OsStub/CryptlibWrapper/CryptlibWrapper.inf
new file mode 100644
index 0000000000..0b64ab0f4f
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/OsStub/CryptlibWrapper/CryptlibWrapper.inf
@@ -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
diff --git a/SecurityPkg/DeviceSecurity/OsStub/MemLibWrapper/MemLibWrapper.c b/SecurityPkg/DeviceSecurity/OsStub/MemLibWrapper/MemLibWrapper.c
new file mode 100644
index 0000000000..42eeecd68c
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/OsStub/MemLibWrapper/MemLibWrapper.c
@@ -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;
+ }
+}
diff --git a/SecurityPkg/DeviceSecurity/OsStub/MemLibWrapper/MemLibWrapper.inf b/SecurityPkg/DeviceSecurity/OsStub/MemLibWrapper/MemLibWrapper.inf
new file mode 100644
index 0000000000..f5b92aae6b
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/OsStub/MemLibWrapper/MemLibWrapper.inf
@@ -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
diff --git a/SecurityPkg/DeviceSecurity/OsStub/PlatformLibWrapper/PlatformLibWrapper.c b/SecurityPkg/DeviceSecurity/OsStub/PlatformLibWrapper/PlatformLibWrapper.c
new file mode 100644
index 0000000000..6e9256e6ea
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/OsStub/PlatformLibWrapper/PlatformLibWrapper.c
@@ -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;
+}
diff --git a/SecurityPkg/DeviceSecurity/OsStub/PlatformLibWrapper/PlatformLibWrapper.inf b/SecurityPkg/DeviceSecurity/OsStub/PlatformLibWrapper/PlatformLibWrapper.inf
new file mode 100644
index 0000000000..269b4bfbe1
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/OsStub/PlatformLibWrapper/PlatformLibWrapper.inf
@@ -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
diff --git a/SecurityPkg/DeviceSecurity/SpdmLib/Include/Stub/SpdmLibStub.h b/SecurityPkg/DeviceSecurity/SpdmLib/Include/Stub/SpdmLibStub.h
new file mode 100644
index 0000000000..8ec6e61675
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmLib/Include/Stub/SpdmLibStub.h
@@ -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
diff --git a/SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/LibspdmStdBoolAlt.h b/SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/LibspdmStdBoolAlt.h
new file mode 100644
index 0000000000..08af7296d0
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/LibspdmStdBoolAlt.h
@@ -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 */
diff --git a/SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/LibspdmStdDefAlt.h b/SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/LibspdmStdDefAlt.h
new file mode 100644
index 0000000000..3b31c23722
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/LibspdmStdDefAlt.h
@@ -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 */
diff --git a/SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/LibspdmStdIntAlt.h b/SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/LibspdmStdIntAlt.h
new file mode 100644
index 0000000000..e63e17f8c6
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/LibspdmStdIntAlt.h
@@ -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 */
diff --git a/SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/base.h b/SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/base.h
new file mode 100644
index 0000000000..09cef567c6
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/base.h
@@ -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 */
diff --git a/SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/library/debuglib.h b/SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/library/debuglib.h
new file mode 100644
index 0000000000..9b31df4ad8
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/library/debuglib.h
@@ -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 */
diff --git a/SecurityPkg/DeviceSecurity/SpdmLib/Include/library/spdm_lib_config.h b/SecurityPkg/DeviceSecurity/SpdmLib/Include/library/spdm_lib_config.h
new file mode 100644
index 0000000000..51dfd3c8fc
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmLib/Include/library/spdm_lib_config.h
@@ -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 */
diff --git a/SecurityPkg/DeviceSecurity/SpdmLib/SpdmCommonLib.inf b/SecurityPkg/DeviceSecurity/SpdmLib/SpdmCommonLib.inf
new file mode 100644
index 0000000000..a0c62bbad0
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmLib/SpdmCommonLib.inf
@@ -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
diff --git a/SecurityPkg/DeviceSecurity/SpdmLib/SpdmCryptLib.inf b/SecurityPkg/DeviceSecurity/SpdmLib/SpdmCryptLib.inf
new file mode 100644
index 0000000000..5e91968576
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmLib/SpdmCryptLib.inf
@@ -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
diff --git a/SecurityPkg/DeviceSecurity/SpdmLib/SpdmDeviceSecretLibNull.inf b/SecurityPkg/DeviceSecurity/SpdmLib/SpdmDeviceSecretLibNull.inf
new file mode 100644
index 0000000000..47f9fe9fe5
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmLib/SpdmDeviceSecretLibNull.inf
@@ -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
diff --git a/SecurityPkg/DeviceSecurity/SpdmLib/SpdmRequesterLib.inf b/SecurityPkg/DeviceSecurity/SpdmLib/SpdmRequesterLib.inf
new file mode 100644
index 0000000000..4fcefe32dc
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmLib/SpdmRequesterLib.inf
@@ -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
diff --git a/SecurityPkg/DeviceSecurity/SpdmLib/SpdmResponderLib.inf b/SecurityPkg/DeviceSecurity/SpdmLib/SpdmResponderLib.inf
new file mode 100644
index 0000000000..61528a80ab
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmLib/SpdmResponderLib.inf
@@ -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
diff --git a/SecurityPkg/DeviceSecurity/SpdmLib/SpdmSecuredMessageLib.inf b/SecurityPkg/DeviceSecurity/SpdmLib/SpdmSecuredMessageLib.inf
new file mode 100644
index 0000000000..062bf77158
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmLib/SpdmSecuredMessageLib.inf
@@ -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
diff --git a/SecurityPkg/DeviceSecurity/SpdmLib/SpdmTransportMctpLib.inf b/SecurityPkg/DeviceSecurity/SpdmLib/SpdmTransportMctpLib.inf
new file mode 100644
index 0000000000..a597d35913
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmLib/SpdmTransportMctpLib.inf
@@ -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
diff --git a/SecurityPkg/DeviceSecurity/SpdmLib/SpdmTransportPciDoeLib.inf b/SecurityPkg/DeviceSecurity/SpdmLib/SpdmTransportPciDoeLib.inf
new file mode 100644
index 0000000000..a0f47d6c7d
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmLib/SpdmTransportPciDoeLib.inf
@@ -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
diff --git a/SecurityPkg/DeviceSecurity/SpdmLib/libspdm b/SecurityPkg/DeviceSecurity/SpdmLib/libspdm
new file mode 160000
+Subproject 50924a4c8145fc721e17208f55814d2b38766fe
diff --git a/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmAuthentication.c b/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmAuthentication.c
new file mode 100644
index 0000000000..86cf9b225c
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmAuthentication.c
@@ -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;
+}
diff --git a/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmConnectionInit.c b/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmConnectionInit.c
new file mode 100644
index 0000000000..d61aa01698
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmConnectionInit.c
@@ -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);
+}
diff --git a/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmMeasurement.c b/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmMeasurement.c
new file mode 100644
index 0000000000..f94ec1e7bf
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmMeasurement.c
@@ -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;
+}
diff --git a/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmSecurityLib.c b/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmSecurityLib.c
new file mode 100644
index 0000000000..f438c16563
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmSecurityLib.c
@@ -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);
+}
diff --git a/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmSecurityLib.inf b/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmSecurityLib.inf
new file mode 100644
index 0000000000..4f77020bd8
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmSecurityLib.inf
@@ -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
diff --git a/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmSecurityLibInternal.h b/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmSecurityLibInternal.h
new file mode 100644
index 0000000000..611274cb7d
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmSecurityLibInternal.h
@@ -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