From 750d763623fd1ff4a69d2e350310333dcbc19d4f Mon Sep 17 00:00:00 2001 From: Wenxing Hou Date: Thu, 18 Apr 2024 17:28:15 +0800 Subject: [PATCH] SecurityPkg: add DeviceSecurity support This patch implement the SpdmSecurityLib, which is the core of DeviceSecurity. And the SpdmSecurityLib include Device Authentication and Measurement. The other library is to support SpdmSecurityLib. Cc: Jiewen Yao Signed-off-by: Wenxing Hou Reviewed-by: Jiewen Yao --- .../OsStub/CryptlibWrapper/CryptlibWrapper.c | 970 ++++++++++++++++++ .../CryptlibWrapper/CryptlibWrapper.inf | 38 + .../OsStub/MemLibWrapper/MemLibWrapper.c | 177 ++++ .../OsStub/MemLibWrapper/MemLibWrapper.inf | 33 + .../PlatformLibWrapper/PlatformLibWrapper.c | 85 ++ .../PlatformLibWrapper/PlatformLibWrapper.inf | 33 + .../SpdmLib/Include/Stub/SpdmLibStub.h | 347 +++++++ .../SpdmLib/Include/hal/LibspdmStdBoolAlt.h | 23 + .../SpdmLib/Include/hal/LibspdmStdDefAlt.h | 16 + .../SpdmLib/Include/hal/LibspdmStdIntAlt.h | 25 + .../DeviceSecurity/SpdmLib/Include/hal/base.h | 94 ++ .../SpdmLib/Include/hal/library/debuglib.h | 39 + .../SpdmLib/Include/library/spdm_lib_config.h | 394 +++++++ .../DeviceSecurity/SpdmLib/SpdmCommonLib.inf | 47 + .../DeviceSecurity/SpdmLib/SpdmCryptLib.inf | 45 + .../SpdmLib/SpdmDeviceSecretLibNull.inf | 36 + .../SpdmLib/SpdmRequesterLib.inf | 59 ++ .../SpdmLib/SpdmResponderLib.inf | 61 ++ .../SpdmLib/SpdmSecuredMessageLib.inf | 44 + .../SpdmLib/SpdmTransportMctpLib.inf | 38 + .../SpdmLib/SpdmTransportPciDoeLib.inf | 38 + .../SpdmSecurityLib/SpdmAuthentication.c | 697 +++++++++++++ .../SpdmSecurityLib/SpdmConnectionInit.c | 481 +++++++++ .../SpdmSecurityLib/SpdmMeasurement.c | 714 +++++++++++++ .../SpdmSecurityLib/SpdmSecurityLib.c | 148 +++ .../SpdmSecurityLib/SpdmSecurityLib.inf | 54 + .../SpdmSecurityLib/SpdmSecurityLibInternal.h | 250 +++++ SecurityPkg/Include/Library/SpdmSecurityLib.h | 437 ++++++++ .../Include/Protocol/DeviceSecurityPolicy.h | 133 +++ SecurityPkg/SecurityPkg.ci.yaml | 17 +- SecurityPkg/SecurityPkg.dec | 13 +- SecurityPkg/SecurityPkg.dsc | 31 +- 32 files changed, 5611 insertions(+), 6 deletions(-) create mode 100644 SecurityPkg/DeviceSecurity/OsStub/CryptlibWrapper/CryptlibWrapper.c create mode 100644 SecurityPkg/DeviceSecurity/OsStub/CryptlibWrapper/CryptlibWrapper.inf create mode 100644 SecurityPkg/DeviceSecurity/OsStub/MemLibWrapper/MemLibWrapper.c create mode 100644 SecurityPkg/DeviceSecurity/OsStub/MemLibWrapper/MemLibWrapper.inf create mode 100644 SecurityPkg/DeviceSecurity/OsStub/PlatformLibWrapper/PlatformLibWrapper.c create mode 100644 SecurityPkg/DeviceSecurity/OsStub/PlatformLibWrapper/PlatformLibWrapper.inf create mode 100644 SecurityPkg/DeviceSecurity/SpdmLib/Include/Stub/SpdmLibStub.h create mode 100644 SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/LibspdmStdBoolAlt.h create mode 100644 SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/LibspdmStdDefAlt.h create mode 100644 SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/LibspdmStdIntAlt.h create mode 100644 SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/base.h create mode 100644 SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/library/debuglib.h create mode 100644 SecurityPkg/DeviceSecurity/SpdmLib/Include/library/spdm_lib_config.h create mode 100644 SecurityPkg/DeviceSecurity/SpdmLib/SpdmCommonLib.inf create mode 100644 SecurityPkg/DeviceSecurity/SpdmLib/SpdmCryptLib.inf create mode 100644 SecurityPkg/DeviceSecurity/SpdmLib/SpdmDeviceSecretLibNull.inf create mode 100644 SecurityPkg/DeviceSecurity/SpdmLib/SpdmRequesterLib.inf create mode 100644 SecurityPkg/DeviceSecurity/SpdmLib/SpdmResponderLib.inf create mode 100644 SecurityPkg/DeviceSecurity/SpdmLib/SpdmSecuredMessageLib.inf create mode 100644 SecurityPkg/DeviceSecurity/SpdmLib/SpdmTransportMctpLib.inf create mode 100644 SecurityPkg/DeviceSecurity/SpdmLib/SpdmTransportPciDoeLib.inf create mode 100644 SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmAuthentication.c create mode 100644 SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmConnectionInit.c create mode 100644 SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmMeasurement.c create mode 100644 SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmSecurityLib.c create mode 100644 SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmSecurityLib.inf create mode 100644 SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmSecurityLibInternal.h create mode 100644 SecurityPkg/Include/Library/SpdmSecurityLib.h create mode 100644 SecurityPkg/Include/Protocol/DeviceSecurityPolicy.h 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.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#include +#include +#include +#include +#include +#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.
+# +# 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.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#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.
+# +# 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.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#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.
+# +# 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.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __LIBSPDM_STUB_H__ +#define __LIBSPDM_STUB_H__ + +#include +#include +#include +#include +#include +#include + +#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.
+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.
+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.
+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.
+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 + +/* LIBSPDM_OPENSSL_STDINT_WORKAROUND */ + +/* This is a workaround for OpenSSL compilation problems when used with + * on Windows platforms built with Visual Studio. Including pulls in + * , 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 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 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 +#else + #include LIBSPDM_STDBOOL_ALT +#endif + +#ifndef LIBSPDM_STDDEF_ALT + #include +#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.
+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 + +#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.
+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.
+# +# 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.
+# +# 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.
+# +# 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.
+# +# 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.
+# +# 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.
+# +# 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.
+# +# 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.
+# +# 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/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.
+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.
+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.
+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.
+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.
+# +# 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.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef SPDM_SECURITY_LIB_INTERNAL_H_ +#define SPDM_SECURITY_LIB_INTERNAL_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#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 diff --git a/SecurityPkg/Include/Library/SpdmSecurityLib.h b/SecurityPkg/Include/Library/SpdmSecurityLib.h new file mode 100644 index 0000000000..96a7841381 --- /dev/null +++ b/SecurityPkg/Include/Library/SpdmSecurityLib.h @@ -0,0 +1,437 @@ +/** @file + EDKII Device Security library for SPDM device. + It follows the SPDM Specification. + +Copyright (c) 2024, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef SPDM_SECURITY_LIB_H_ +#define SPDM_SECURITY_LIB_H_ + +#include +#include + +/** + * Send an SPDM transport layer message to a device. + * + * The message is an SPDM message with transport layer wrapper, + * or a secured SPDM message with transport layer wrapper. + * + * For requester, the message is a transport layer SPDM request. + * For responder, the message is a transport layer SPDM response. + * + * @param spdm_context A pointer to the SPDM context. + * @param message_size size in bytes of the message data buffer. + * @param message A pointer to a destination buffer to store the message. + * The caller is responsible for having + * either implicit or explicit ownership of the buffer. + * The message pointer shall be inside of + * [msg_buf_ptr, msg_buf_ptr + max_msg_size] from + * acquired sender_buffer. + * @param timeout The timeout, in 100ns units, to use for the execution + * of the message. A timeout value of 0 + * means that this function will wait indefinitely for the + * message to execute. If timeout is greater + * than zero, then this function will return RETURN_TIMEOUT if the + * time required to execute the message is greater + * than timeout. + * + * @retval RETURN_SUCCESS The SPDM message is sent successfully. + * @retval RETURN_DEVICE_ERROR A device error occurs when the SPDM message is sent to the device. + * @retval RETURN_INVALID_PARAMETER The message is NULL or the message_size is zero. + * @retval RETURN_TIMEOUT A timeout occurred while waiting for the SPDM message + * to execute. + **/ +typedef + SPDM_RETURN +(*SPDM_DEVICE_SEND_MESSAGE_FUNC)( + IN VOID *SpdmContext, + IN UINTN MessageSize, + IN OUT CONST VOID *Message, + IN UINT64 Timeout + ); + +/** + * Receive an SPDM transport layer message from a device. + * + * The message is an SPDM message with transport layer wrapper, + * or a secured SPDM message with transport layer wrapper. + * + * For requester, the message is a transport layer SPDM response. + * For responder, the message is a transport layer SPDM request. + * + * @param spdm_context A pointer to the SPDM context. + * @param message_size size in bytes of the message data buffer. + * @param message A pointer to a destination buffer to store the message. + * The caller is responsible for having + * either implicit or explicit ownership of the buffer. + * On input, the message pointer shall be msg_buf_ptr from + * acquired receiver_buffer. + * On output, the message pointer shall be inside of + * [msg_buf_ptr, msg_buf_ptr + max_msg_size] from + * acquired receiver_buffer. + * @param timeout The timeout, in 100ns units, to use for the execution + * of the message. A timeout value of 0 + * means that this function will wait indefinitely for the + * message to execute. If timeout is greater + * than zero, then this function will return RETURN_TIMEOUT if the + * time required to execute the message is greater + * than timeout. + * + * @retval RETURN_SUCCESS The SPDM message is received successfully. + * @retval RETURN_DEVICE_ERROR A device error occurs when the SPDM message is received from the device. + * @retval RETURN_INVALID_PARAMETER The message is NULL, message_size is NULL or + * the *message_size is zero. + * @retval RETURN_TIMEOUT A timeout occurred while waiting for the SPDM message + * to execute. + **/ +typedef + SPDM_RETURN +(*SPDM_DEVICE_RECEIVE_MESSAGE_FUNC)( + IN VOID *SpdmContext, + IN OUT UINTN *MessageSize, + IN OUT VOID **Message, + IN UINT64 Timeout + ); + +/** + * Encode an SPDM or APP message to a transport layer message. + * + * For normal SPDM message, it adds the transport layer wrapper. + * For secured SPDM message, it encrypts a secured message then adds the transport layer wrapper. + * For secured APP message, it encrypts a secured message then adds the transport layer wrapper. + * + * The APP message is encoded to a secured message directly in SPDM session. + * The APP message format is defined by the transport layer. + * Take MCTP as example: APP message == MCTP header (MCTP_MESSAGE_TYPE_SPDM) + SPDM message + * + * @param spdm_context A pointer to the SPDM context. + * @param session_id Indicates if it is a secured message protected via SPDM session. + * If session_id is NULL, it is a normal message. + * If session_id is NOT NULL, it is a secured message. + * @param is_app_message Indicates if it is an APP message or SPDM message. + * @param is_requester Indicates if it is a requester message. + * @param message_size size in bytes of the message data buffer. + * @param message A pointer to a source buffer to store the message. + * For normal message, it shall point to the acquired sender buffer. + * For secured message, it shall point to the scratch buffer in spdm_context. + * @param transport_message_size size in bytes of the transport message data buffer. + * @param transport_message A pointer to a destination buffer to store the transport message. + * On input, it shall be msg_buf_ptr from sender buffer. + * On output, it will point to acquired sender buffer. + * + * @retval RETURN_SUCCESS The message is encoded successfully. + * @retval RETURN_INVALID_PARAMETER The message is NULL or the message_size is zero. + **/ +typedef + SPDM_RETURN +(*SPDM_TRANSPORT_ENCODE_MESSAGE_FUNC)( + IN VOID *SpdmContext, + IN OUT CONST UINT32 *SessionId, + IN BOOLEAN IsAppMessage, + IN BOOLEAN IsRequester, + IN UINTN MessageSize, + IN OUT VOID *Message, + IN OUT UINTN *TransportMessageSize, + IN VOID **TransportMessage + ); + +/** + * Decode an SPDM or APP message from a transport layer message. + * + * For normal SPDM message, it removes the transport layer wrapper, + * For secured SPDM message, it removes the transport layer wrapper, then decrypts and verifies a secured message. + * For secured APP message, it removes the transport layer wrapper, then decrypts and verifies a secured message. + * + * The APP message is decoded from a secured message directly in SPDM session. + * The APP message format is defined by the transport layer. + * Take MCTP as example: APP message == MCTP header (MCTP_MESSAGE_TYPE_SPDM) + SPDM message + * + * @param spdm_context A pointer to the SPDM context. + * @param session_id Indicates if it is a secured message protected via SPDM session. + * If *session_id is NULL, it is a normal message. + * If *session_id is NOT NULL, it is a secured message. + * @param is_app_message Indicates if it is an APP message or SPDM message. + * @param is_requester Indicates if it is a requester message. + * @param transport_message_size size in bytes of the transport message data buffer. + * @param transport_message A pointer to a source buffer to store the transport message. + * For normal message or secured message, it shall point to acquired receiver buffer. + * @param message_size size in bytes of the message data buffer. + * @param message A pointer to a destination buffer to store the message. + * On input, it shall point to the scratch buffer in spdm_context. + * On output, for normal message, it will point to the original receiver buffer. + * On output, for secured message, it will point to the scratch buffer in spdm_context. + * + * @retval RETURN_SUCCESS The message is decoded successfully. + * @retval RETURN_INVALID_PARAMETER The message is NULL or the message_size is zero. + * @retval RETURN_UNSUPPORTED The transport_message is unsupported. + **/ +typedef + SPDM_RETURN +(*SPDM_TRANSPORT_DECODE_MESSAGE_FUNC)( + IN VOID *SpdmContext, + IN OUT UINT32 **SessionId, + IN BOOLEAN *IsAppMessage, + IN BOOLEAN IsRequester, + IN UINTN TransportMessageSize, + IN OUT VOID *TransportMessage, + IN OUT UINTN *MessageSize, + IN OUT VOID **Message + ); + +/** + * Acquire a device sender buffer for transport layer message. + * + * The max_msg_size must be larger than + * MAX (non-secure Transport Message Header Size + + * SPDM_CAPABILITIES.DataTransferSize + + * max alignment pad size (transport specific), + * secure Transport Message Header Size + + * sizeof(spdm_secured_message_a_data_header1_t) + + * length of sequence_number (transport specific) + + * sizeof(spdm_secured_message_a_data_header2_t) + + * sizeof(spdm_secured_message_cipher_header_t) + + * App Message Header Size (transport specific) + + * SPDM_CAPABILITIES.DataTransferSize + + * maximum random data size (transport specific) + + * AEAD MAC size (16) + + * max alignment pad size (transport specific)) + * + * For MCTP, + * Transport Message Header Size = sizeof(mctp_message_header_t) + * length of sequence_number = 2 + * App Message Header Size = sizeof(mctp_message_header_t) + * maximum random data size = MCTP_MAX_RANDOM_NUMBER_COUNT + * max alignment pad size = 0 + * For PCI_DOE, + * Transport Message Header Size = sizeof(pci_doe_data_object_header_t) + * length of sequence_number = 0 + * App Message Header Size = 0 + * maximum random data size = 0 + * max alignment pad size = 3 + * + * @param context A pointer to the SPDM context. + * @param max_msg_size size in bytes of the maximum size of sender buffer. + * @param msg_buf_ptr A pointer to a sender buffer. + * + * @retval RETURN_SUCCESS The sender buffer is acquired. + **/ +typedef + SPDM_RETURN +(*SPDM_DEVICE_ACQUIRE_SENDER_BUFFER_FUNC)( + IN VOID *SpdmContext, + IN OUT VOID **MsgBufPtr + ); + +/** + * Release a device sender buffer for transport layer message. + * + * @param context A pointer to the SPDM context. + * @param msg_buf_ptr A pointer to a sender buffer. + * + * @retval RETURN_SUCCESS The sender buffer is Released. + **/ +typedef + VOID +(*SPDM_DEVICE_RELEASE_SENDER_BUFFER_FUNC)( + IN VOID *SpdmContext, + IN CONST VOID *MsgBufPtr + ); + +/** + * Acquire a device receiver buffer for transport layer message. + * + * The max_msg_size must be larger than + * MAX (non-secure Transport Message Header Size + + * SPDM_CAPABILITIES.DataTransferSize + + * max alignment pad size (transport specific), + * secure Transport Message Header Size + + * sizeof(spdm_secured_message_a_data_header1_t) + + * length of sequence_number (transport specific) + + * sizeof(spdm_secured_message_a_data_header2_t) + + * sizeof(spdm_secured_message_cipher_header_t) + + * App Message Header Size (transport specific) + + * SPDM_CAPABILITIES.DataTransferSize + + * maximum random data size (transport specific) + + * AEAD MAC size (16) + + * max alignment pad size (transport specific)) + * + * For MCTP, + * Transport Message Header Size = sizeof(mctp_message_header_t) + * length of sequence_number = 2 + * App Message Header Size = sizeof(mctp_message_header_t) + * maximum random data size = MCTP_MAX_RANDOM_NUMBER_COUNT + * max alignment pad size = 0 + * For PCI_DOE, + * Transport Message Header Size = sizeof(pci_doe_data_object_header_t) + * length of sequence_number = 0 + * App Message Header Size = 0 + * maximum random data size = 0 + * max alignment pad size = 3 + * + * @param context A pointer to the SPDM context. + * @param max_msg_size size in bytes of the maximum size of receiver buffer. + * @param msg_buf_pt A pointer to a receiver buffer. + * + * @retval RETURN_SUCCESS The receiver buffer is acquired. + **/ +typedef + SPDM_RETURN +(*SPDM_DEVICE_ACQUIRE_RECEIVER_BUFFER_FUNC)( + IN VOID *SpdmContext, + IN OUT VOID **MsgBufPtr + ); + +/** + * Release a device receiver buffer for transport layer message. + * + * @param context A pointer to the SPDM context. + * @param msg_buf_ptr A pointer to a receiver buffer. + * + * @retval RETURN_SUCCESS The receiver buffer is Released. + **/ +typedef + VOID +(*SPDM_DEVICE_RELEASE_RECEIVER_BUFFER_FUNC)( + IN VOID *SpdmContext, + IN CONST VOID *MsgBufPtr + ); + +typedef struct { + UINT32 Version; + // + // DeviceType is used to create TCG event log context_data. + // DeviceHandle is used to create TCG event log device_path information. + // + EDKII_DEVICE_IDENTIFIER *DeviceId; + + // + // TRUE means to use PCR 0 (code) / 1 (config). + // FALSE means to use PCR 2 (code) / 3 (config). + // + BOOLEAN IsEmbeddedDevice; + + // + // Below 9 APIs are used to send/receive SPDM request/response. + // + // The request flow is: + // |<--- SenderBufferSize --->| + // |<--- TransportRequestBufferSize --->| + // |<---MaxHeaderSize--->|<-SpdmRequestBufferSize ->| + // +--+------------------+==========================+----------------+--+ + // | | Transport Header | SPDM Message | Transport Tail | | + // +--+------------------+==========================+----------------+--+ + // ^ ^ ^ + // | | | SpdmRequestBuffer + // | | TransportRequestBuffer + // | SenderBuffer + // + // AcquireSenderBuffer (&SenderBuffer, &SenderBufferSize); + // SpdmRequestBuffer = SenderBuffer + TransportHeaderSize; + // /* build SPDM request in SpdmRequestBuffer */ + // TransportEncodeMessage (SpdmRequestBuffer, SpdmRequestBufferSize, + // &TransportRequestBuffer, &TransportRequestBufferSize); + // SendMessage (TransportRequestBuffer, TransportRequestBufferSize); + // ReleaseSenderBuffer (SenderBuffer); + // + // The response flow is: + // |<--- ReceiverBufferSize --->| + // |<--- TransportResponseBufferSize --->| + // |<-SpdmResponseBufferSize->| + // +--+------------------+==========================+----------------+--+ + // | | Transport Header | SPDM Message | Transport Tail | | + // +--+------------------+==========================+----------------+--+ + // ^ ^ ^ + // | | | SpdmResponseBuffer + // | | TransportResponseBuffer + // | ReceiverBuffer + // + // AcquireReceiverBuffer (&ReceiverBuffer, &ReceiverBufferSize); + // TransportResponseBuffer = ReceiverBuffer; + // ReceiveMessage (&TransportResponseBuffer, &TransportResponseBufferSize); + // TransportDecodeMessage (TransportResponseBuffer, TransportResponseBufferSize, + // &SpdmResponseBuffer, &SpdmResponseBufferSize); + // /* process SPDM response in SpdmResponseBuffer */ + // ReleaseReceiverBuffer (ReceiverBuffer); + // + + // + // API required by SpdmRegisterDeviceIoFunc in libspdm + // It is used to send/receive transport message (SPDM + transport header). + // + SPDM_DEVICE_SEND_MESSAGE_FUNC SendMessage; + SPDM_DEVICE_RECEIVE_MESSAGE_FUNC ReceiveMessage; + // + // API required by SpdmRegisterTransportLayerFunc in libspdm + // It is used to add/remove transport header for SPDM. + // + SPDM_TRANSPORT_ENCODE_MESSAGE_FUNC TransportEncodeMessage; + SPDM_TRANSPORT_DECODE_MESSAGE_FUNC TransportDecodeMessage; + // + // API required by SpdmRegisterDeviceBufferFunc in libspdm + // It is used to get the sender/receiver buffer for transport message (SPDM + transport header). + // The size MUST be big enough to send or receive one transport message (SPDM + transport header). + // Tthe sender/receiver buffer MAY be overlapped. + // + SPDM_DEVICE_ACQUIRE_SENDER_BUFFER_FUNC AcquireSenderBuffer; + SPDM_DEVICE_RELEASE_SENDER_BUFFER_FUNC ReleaseSenderBuffer; + SPDM_DEVICE_ACQUIRE_RECEIVER_BUFFER_FUNC AcquireReceiverBuffer; + SPDM_DEVICE_RELEASE_RECEIVER_BUFFER_FUNC ReleaseReceiverBuffer; + + // + // Preferred Algorithm List for SPDM negotiation. + // If it is none zero, it will be used directly. + // If it is zero, then the SpdmSecurityLib will set the default value. + // + UINT32 BaseHashAlgo; + UINT32 BaseAsymAlgo; + + // + // transfer size + // + UINT32 MaxSpdmMsgSize; + UINT32 TransportHeaderSize; + UINT32 TransportTailSize; + UINT32 SenderBufferSize; + UINT32 ReceiverBufferSize; + + EFI_GUID *SpdmIoProtocolGuid; +} EDKII_SPDM_DEVICE_INFO; + +/** + This function will send SPDM VCA, GET_CERTIFICATE, CHALLENGE, GET_MEASUREMENT, + The certificate and measurement will be extended to TPM PCR/NvIndex. +**/ +RETURN_STATUS +EFIAPI +SpdmDeviceAuthenticationAndMeasurement ( + IN EDKII_SPDM_DEVICE_INFO *SpdmDeviceInfo, + IN EDKII_DEVICE_SECURITY_POLICY *SecurityPolicy, + OUT EDKII_DEVICE_SECURITY_STATE *SecurityState + ); + +/** + This function will get SpdmIoProtocol via Context. +**/ +VOID * +EFIAPI +SpdmGetIoProtocolViaSpdmContext ( + IN VOID *SpdmContext + ); + +/** + Helper function to quickly determine whether device authentication boot is enabled. + + @retval TRUE device authentication boot is verifiably enabled. + @retval FALSE device authentication boot is either disabled or an error prevented checking. + +**/ +BOOLEAN +EFIAPI +IsDeviceAuthBootEnabled ( + VOID + ); + +#endif diff --git a/SecurityPkg/Include/Protocol/DeviceSecurityPolicy.h b/SecurityPkg/Include/Protocol/DeviceSecurityPolicy.h new file mode 100644 index 0000000000..69148badb6 --- /dev/null +++ b/SecurityPkg/Include/Protocol/DeviceSecurityPolicy.h @@ -0,0 +1,133 @@ +/** @file + Platform Device Security Policy Protocol definition + + Copyright (c) 2024, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef EDKII_DEVICE_SECURITY_POLICY_PROTOCOL_H_ +#define EDKII_DEVICE_SECURITY_POLICY_PROTOCOL_H_ + +#include +#include + +typedef struct _EDKII_DEVICE_SECURITY_POLICY_PROTOCOL EDKII_DEVICE_SECURITY_POLICY_PROTOCOL; + +// +// Revision The revision to which the DEVICE_SECURITY_POLICY protocol interface adheres. +// All future revisions must be backwards compatible. +// If a future version is not back wards compatible it is not the same GUID. +// +#define EDKII_DEVICE_SECURITY_POLICY_PROTOCOL_REVISION 0x00010000 + +// +// Revision The revision to which the DEVICE_SECURITY_POLICY structure adheres. +// All future revisions must be backwards compatible. +// +#define EDKII_DEVICE_SECURITY_POLICY_REVISION 0x00010000 + +/// +/// The macro for the policy defined in EDKII_DEVICE_SECURITY_POLICY +/// +#define EDKII_DEVICE_MEASUREMENT_REQUIRED BIT0 +#define EDKII_DEVICE_AUTHENTICATION_REQUIRED BIT0 + +/// +/// The device security policy data structure +/// +typedef struct { + UINT32 Revision; + UINT32 MeasurementPolicy; + UINT32 AuthenticationPolicy; +} EDKII_DEVICE_SECURITY_POLICY; + +// +// Revision The revision to which the DEVICE_SECURITY_STATE structure adheres. +// All future revisions must be backwards compatible. +// +#define EDKII_DEVICE_SECURITY_STATE_REVISION 0x00010000 + +/// +/// The macro for the state defined in EDKII_DEVICE_SECURITY_STATE +/// +#define EDKII_DEVICE_SECURITY_STATE_SUCCESS 0 +#define EDKII_DEVICE_SECURITY_STATE_ERROR BIT31 +#define EDKII_DEVICE_SECURITY_STATE_ERROR_UEFI_UNSUPPORTED (EDKII_DEVICE_SECURITY_STATE_ERROR + 0x0) +#define EDKII_DEVICE_SECURITY_STATE_ERROR_UEFI_GET_POLICY_PROTOCOL (EDKII_DEVICE_SECURITY_STATE_ERROR + 0x1) +#define EDKII_DEVICE_SECURITY_STATE_ERROR_UEFI_OUT_OF_RESOURCE (EDKII_DEVICE_SECURITY_STATE_ERROR + 0x2) +#define EDKII_DEVICE_SECURITY_STATE_ERROR_DEVICE_NO_CAPABILITIES (EDKII_DEVICE_SECURITY_STATE_ERROR + 0x10) +#define EDKII_DEVICE_SECURITY_STATE_ERROR_DEVICE_ERROR (EDKII_DEVICE_SECURITY_STATE_ERROR + 0x11) +#define EDKII_DEVICE_SECURITY_STATE_ERROR_TCG_EXTEND_TPM_PCR (EDKII_DEVICE_SECURITY_STATE_ERROR + 0x20) +#define EDKII_DEVICE_SECURITY_STATE_ERROR_MEASUREMENT_AUTH_FAILURE (EDKII_DEVICE_SECURITY_STATE_ERROR + 0x21) +#define EDKII_DEVICE_SECURITY_STATE_ERROR_CHALLENGE_FAILURE (EDKII_DEVICE_SECURITY_STATE_ERROR + 0x30) +#define EDKII_DEVICE_SECURITY_STATE_ERROR_CERTIFIACTE_FAILURE (EDKII_DEVICE_SECURITY_STATE_ERROR + 0x31) +#define EDKII_DEVICE_SECURITY_STATE_ERROR_NO_CERT_PROVISION (EDKII_DEVICE_SECURITY_STATE_ERROR + 0x32) + +/// +/// The device security state data structure +/// +typedef struct { + UINT32 Revision; + UINT32 MeasurementState; + UINT32 AuthenticationState; +} EDKII_DEVICE_SECURITY_STATE; + +/** + This function returns the device security policy associated with the device. + + The device security driver may call this interface to get the platform policy + for the specific device and determine if the measurement or authentication + is required. + + @param[in] This The protocol instance pointer. + @param[in] DeviceId The Identifier for the device. + @param[out] DeviceSecurityPolicy The Device Security Policy associated with the device. + + @retval EFI_SUCCESS The device security policy is returned + @retval EFI_UNSUPPORTED The function is unsupported for the specific Device. +**/ +typedef + EFI_STATUS +(EFIAPI *EDKII_DEVICE_SECURITY_GET_DEVICE_POLICY)( + IN EDKII_DEVICE_SECURITY_POLICY_PROTOCOL *This, + IN EDKII_DEVICE_IDENTIFIER *DeviceId, + OUT EDKII_DEVICE_SECURITY_POLICY *DeviceSecurityPolicy + ); + +/** + This function sets the device state based upon the authentication result. + + The device security driver may call this interface to give the platform + a notify based upon the measurement or authentication result. + If the authentication or measurement fails, the platform may choose: + 1) Do nothing. + 2) Disable this device or slot temporarily and continue boot. + 3) Reset the platform and retry again. + 4) Disable this device or slot permanently. + 5) Any other platform specific action. + + @param[in] This The protocol instance pointer. + @param[in] DeviceId The Identifier for the device. + @param[in] DeviceSecurityState The Device Security state associated with the device. + + @retval EFI_SUCCESS The device state is set. + @retval EFI_UNSUPPORTED The function is unsupported for the specific Device. +**/ +typedef + EFI_STATUS +(EFIAPI *EDKII_DEVICE_SECURITY_NOTIFY_DEVICE_STATE)( + IN EDKII_DEVICE_SECURITY_POLICY_PROTOCOL *This, + IN EDKII_DEVICE_IDENTIFIER *DeviceId, + IN EDKII_DEVICE_SECURITY_STATE *DeviceSecurityState + ); + +struct _EDKII_DEVICE_SECURITY_POLICY_PROTOCOL { + UINT32 Revision; + EDKII_DEVICE_SECURITY_GET_DEVICE_POLICY GetDevicePolicy; + EDKII_DEVICE_SECURITY_NOTIFY_DEVICE_STATE NotifyDeviceState; +}; + +extern EFI_GUID gEdkiiDeviceSecurityPolicyProtocolGuid; + +#endif diff --git a/SecurityPkg/SecurityPkg.ci.yaml b/SecurityPkg/SecurityPkg.ci.yaml index 53e5b1fd8e..2a4cbd3795 100644 --- a/SecurityPkg/SecurityPkg.ci.yaml +++ b/SecurityPkg/SecurityPkg.ci.yaml @@ -2,12 +2,14 @@ # CI configuration for SecurityPkg # # Copyright (c) Microsoft Corporation -# Copyright (c) 2020, Intel Corporation. All rights reserved.
+# Copyright (c) 2020 - 2024, Intel Corporation. All rights reserved.
# SPDX-License-Identifier: BSD-2-Clause-Patent ## { "LicenseCheck": { - "IgnoreFiles": [] + "IgnoreFiles": [ + "DeviceSecurity/SpdmLib/Include", + ] }, "EccCheck": { ## Exception sample looks like below: @@ -23,7 +25,10 @@ "IgnoreFiles": [ "Library/TcgStorageCoreLib/TcgStorageUtil.c", "Library/TcgStorageCoreLib/TcgStorageCore.c", - "Library/Tpm2CommandLib/Tpm2NVStorage.c" + "Library/Tpm2CommandLib/Tpm2NVStorage.c", + "DeviceSecurity/SpdmLib/Include", + "DeviceSecurity/SpdmLib/libspdm", + "DeviceSecurity/OsStub" ] }, "CompilerPlugin": { @@ -69,7 +74,11 @@ ] }, "LibraryClassCheck": { - "IgnoreHeaderFile": [] + "IgnoreHeaderFile": [ + "DeviceSecurity/SpdmLib/Include/library", + "DeviceSecurity/SpdmLib/libspdm/include/library", + ], + "skip": True }, ## options defined ci/Plugin/SpellCheck diff --git a/SecurityPkg/SecurityPkg.dec b/SecurityPkg/SecurityPkg.dec index 00c4ebdbed..a91e3ea028 100644 --- a/SecurityPkg/SecurityPkg.dec +++ b/SecurityPkg/SecurityPkg.dec @@ -5,7 +5,7 @@ # It also provides the definitions(including PPIs/PROTOCOLs/GUIDs and library classes) # and libraries instances, which are used for those features. # -# Copyright (c) 2009 - 2020, Intel Corporation. All rights reserved.
+# Copyright (c) 2009 - 2024, Intel Corporation. All rights reserved.
# (C) Copyright 2015 Hewlett Packard Enterprise Development LP
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: BSD-2-Clause-Patent @@ -23,6 +23,10 @@ Include Test/Mock/Include +[Includes.Common.Private] + DeviceSecurity/SpdmLib/Include + DeviceSecurity/SpdmLib/libspdm/include + [LibraryClasses] ## @libraryclass Provides hash interfaces from different implementations. # @@ -97,6 +101,10 @@ # PlatformPKProtectionLib|Include/Library/PlatformPKProtectionLib.h + ## @libraryclass Perform SPDM (following SPDM spec) and measure data to TPM (following TCG PFP spec). + ## + SpdmSecurityLib|Include/Library/SpdmSecurityLib.h + [Guids] ## Security package token space guid. # Include/Guid/SecurityPkgTokenSpace.h @@ -219,6 +227,9 @@ ## GUID used to specify section with default dbt content gDefaultdbtFileGuid = { 0x36c513ee, 0xa338, 0x4976, { 0xa0, 0xfb, 0x6d, 0xdb, 0xa3, 0xda, 0xfe, 0x87 } } + ## GUID used to generate Spdm Uid + gEfiDeviceSecuritySpdmUidGuid = {0xe37b5665, 0x5ef9, 0x4e7e, {0xb4, 0x91, 0xd6, 0x78, 0xab, 0xff, 0xfb, 0xcb }} + [Ppis] ## The PPI GUID for that TPM physical presence should be locked. # Include/Ppi/LockPhysicalPresence.h diff --git a/SecurityPkg/SecurityPkg.dsc b/SecurityPkg/SecurityPkg.dsc index 4923d88f79..70981da361 100644 --- a/SecurityPkg/SecurityPkg.dsc +++ b/SecurityPkg/SecurityPkg.dsc @@ -1,7 +1,7 @@ ## @file # Security Module Package for All Architectures. # -# Copyright (c) 2009 - 2021, Intel Corporation. All rights reserved.
+# Copyright (c) 2009 - 2024, Intel Corporation. All rights reserved.
# (C) Copyright 2015-2020 Hewlett Packard Enterprise Development LP
# Copyright (c) 2022, Loongson Technology Corporation Limited. All rights reserved.
# Copyright (c) 2021 - 2022, Arm Limited. All rights reserved.
@@ -76,6 +76,19 @@ TdxLib|MdePkg/Library/TdxLib/TdxLib.inf VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf + SpdmSecurityLib|SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmSecurityLib.inf + SpdmDeviceSecretLib|SecurityPkg/DeviceSecurity/SpdmLib/SpdmDeviceSecretLibNull.inf + SpdmCryptLib|SecurityPkg/DeviceSecurity/SpdmLib/SpdmCryptLib.inf + SpdmCommonLib|SecurityPkg/DeviceSecurity/SpdmLib/SpdmCommonLib.inf + SpdmRequesterLib|SecurityPkg/DeviceSecurity/SpdmLib/SpdmRequesterLib.inf + SpdmResponderLib|SecurityPkg/DeviceSecurity/SpdmLib/SpdmResponderLib.inf + SpdmSecuredMessageLib|SecurityPkg/DeviceSecurity/SpdmLib/SpdmSecuredMessageLib.inf + SpdmTransportMctpLib|SecurityPkg/DeviceSecurity/SpdmLib/SpdmTransportMctpLib.inf + SpdmTransportPciDoeLib|SecurityPkg/DeviceSecurity/SpdmLib/SpdmTransportPciDoeLib.inf + CryptlibWrapper|SecurityPkg/DeviceSecurity/OsStub/CryptlibWrapper/CryptlibWrapper.inf + PlatformLibWrapper|SecurityPkg/DeviceSecurity/OsStub/PlatformLibWrapper/PlatformLibWrapper.inf + MemLibWrapper|SecurityPkg/DeviceSecurity/OsStub/MemLibWrapper/MemLibWrapper.inf + [LibraryClasses.ARM, LibraryClasses.AARCH64] # # It is not possible to prevent the ARM compiler for generic intrinsic functions. @@ -287,6 +300,22 @@ # SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf + # + # SPDM + # + SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmSecurityLib.inf + SecurityPkg/DeviceSecurity/SpdmLib/SpdmDeviceSecretLibNull.inf + SecurityPkg/DeviceSecurity/SpdmLib/SpdmCryptLib.inf + SecurityPkg/DeviceSecurity/SpdmLib/SpdmCommonLib.inf + SecurityPkg/DeviceSecurity/SpdmLib/SpdmRequesterLib.inf + SecurityPkg/DeviceSecurity/SpdmLib/SpdmResponderLib.inf + SecurityPkg/DeviceSecurity/SpdmLib/SpdmSecuredMessageLib.inf + SecurityPkg/DeviceSecurity/SpdmLib/SpdmTransportMctpLib.inf + SecurityPkg/DeviceSecurity/SpdmLib/SpdmTransportPciDoeLib.inf + SecurityPkg/DeviceSecurity/OsStub/CryptlibWrapper/CryptlibWrapper.inf + SecurityPkg/DeviceSecurity/OsStub/PlatformLibWrapper/PlatformLibWrapper.inf + SecurityPkg/DeviceSecurity/OsStub/MemLibWrapper/MemLibWrapper.inf + [Components.IA32, Components.X64] SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf