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