diff --git a/SecurityPkg/Hash2DxeCrypto/Hash2DxeCryptoAudit/Hash2DxeCryptoAudit.c b/SecurityPkg/Hash2DxeCrypto/Hash2DxeCryptoAudit/Hash2DxeCryptoAudit.c new file mode 100644 index 0000000000..db32654df4 --- /dev/null +++ b/SecurityPkg/Hash2DxeCrypto/Hash2DxeCryptoAudit/Hash2DxeCryptoAudit.c @@ -0,0 +1,334 @@ +// +// Uefi Shell based Application that Unit Tests and Audits the Hash2Protoco +// +// Copyright (C) Microsoft Corporation. All rights reserved. +// SPDX-License-Identifier: BSD-2-Clause-Patent +// + +#include <Uefi.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiLib.h> +#include <Library/UnitTestLib.h> +#include <Library/DebugLib.h> +#include <Protocol/Hash2.h> +#include <Protocol/ServiceBinding.h> + +#define UNIT_TEST_APP_NAME "Hash 2 Dxe Crypto Audit Tests" +#define UNIT_TEST_APP_VERSION "1.0" +// +// This is the handle for the Hash2ServiceBinding Protocol instance this driver produces +// if the platform does not provide one. +// +EFI_HANDLE mHash2ServiceHandle = NULL; + +STATIC +UNIT_TEST_STATUS +EFIAPI +TestLocateHash2Protocol ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + EFI_SERVICE_BINDING_PROTOCOL *Hash2ServiceBinding; + EFI_HASH2_PROTOCOL *Hash2Protocol; + + Status = gBS->LocateProtocol (&gEfiHash2ProtocolGuid, NULL, (VOID **)&Hash2Protocol); + if (EFI_ERROR (Status)) { + // + // If we can't find the Hashing protocol, then we need to create one. + // + + // + // Platform is expected to publish the hash service binding protocol to support TCP. + // + Status = gBS->LocateProtocol ( + &gEfiHash2ServiceBindingProtocolGuid, + NULL, + (VOID **)&Hash2ServiceBinding + ); + if (EFI_ERROR (Status) || (Hash2ServiceBinding == NULL) || (Hash2ServiceBinding->CreateChild == NULL)) { + UT_ASSERT_NOT_EFI_ERROR (Status); + } + + // + // Create an instance of the hash protocol for this controller. + // + Status = Hash2ServiceBinding->CreateChild (Hash2ServiceBinding, &mHash2ServiceHandle); + if (EFI_ERROR (Status)) { + UT_ASSERT_NOT_EFI_ERROR (Status); + } + + // + // Now that an instance is binded - should be able to locate the protocol + // + Status = gBS->LocateProtocol (&gEfiHash2ProtocolGuid, NULL, (VOID **)&Hash2Protocol); + } + + UT_ASSERT_NOT_EFI_ERROR (Status); + UT_ASSERT_NOT_NULL (Hash2Protocol); + + return UNIT_TEST_PASSED; +} + +STATIC +UNIT_TEST_STATUS +EFIAPI +TestHash2Md5 ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + EFI_HASH2_PROTOCOL *Hash2; + EFI_HASH2_OUTPUT Hash; + UINT8 Data[] = "Test Data"; + UINTN DataSize = sizeof (Data) - 1; + + Status = gBS->LocateProtocol (&gEfiHash2ProtocolGuid, NULL, (VOID **)&Hash2); + UT_ASSERT_NOT_EFI_ERROR (Status); + UT_ASSERT_NOT_NULL (Hash2); + + // + // MD5Sum is no longer supported and should return EFI_UNSUPPORTED + // *some* implementations have been known to crash when called + // + Status = Hash2->Hash (Hash2, &gEfiHashAlgorithmMD5Guid, Data, DataSize, &Hash); + UT_ASSERT_EQUAL (Status, EFI_UNSUPPORTED); + + return UNIT_TEST_PASSED; +} + +STATIC +UNIT_TEST_STATUS +EFIAPI +TestHash2Sha1 ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + EFI_HASH2_PROTOCOL *Hash2; + EFI_HASH2_OUTPUT Hash; + UINT8 Data[] = "Test Data"; + UINTN DataSize = sizeof (Data) - 1; + + Status = gBS->LocateProtocol (&gEfiHash2ProtocolGuid, NULL, (VOID **)&Hash2); + UT_ASSERT_NOT_EFI_ERROR (Status); + UT_ASSERT_NOT_NULL (Hash2); + + // + // Sha1 is no longer supported and should return EFI_UNSUPPORTED + // *some* implementations have been known to crash when called + // + Status = Hash2->Hash (Hash2, &gEfiHashAlgorithmSha1Guid, Data, DataSize, &Hash); + UT_ASSERT_EQUAL (Status, EFI_UNSUPPORTED); + + return UNIT_TEST_PASSED; +} + +STATIC +UNIT_TEST_STATUS +EFIAPI +TestHash2SHA256 ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + EFI_HASH2_PROTOCOL *Hash2; + EFI_HASH2_OUTPUT Hash; + UINT8 Data[] = "Test Data"; + UINTN DataSize = sizeof (Data) - 1; + UINT8 ExpectedHash[] = { + 0xBC, 0xFE, 0x67, 0x17, 0x2A, 0x6F, 0x40, 0x79, + 0xD6, 0x9F, 0xE2, 0xF2, 0x7A, 0x99, 0x60, 0xF9, + 0xD6, 0x2E, 0xDA, 0xE2, 0xFC, 0xD4, 0xBB, 0x5A, + 0x60, 0x6C, 0x2E, 0xBB, 0x74, 0xB3, 0xBA, 0x65 + }; + + Status = gBS->LocateProtocol (&gEfiHash2ProtocolGuid, NULL, (VOID **)&Hash2); + UT_ASSERT_NOT_EFI_ERROR (Status); + UT_ASSERT_NOT_NULL (Hash2); + + // + // Test SHA256 + // + Status = Hash2->Hash (Hash2, &gEfiHashAlgorithmSha256Guid, Data, DataSize, &Hash); + UT_ASSERT_NOT_EFI_ERROR (Status); + UT_ASSERT_MEM_EQUAL (Hash.Sha256Hash, ExpectedHash, sizeof (ExpectedHash)); + + // + // Test SHA256 INIT/UPDATE/FINAL + // + Status = Hash2->HashInit (Hash2, &gEfiHashAlgorithmSha256Guid); + UT_ASSERT_NOT_EFI_ERROR (Status); + + Status = Hash2->HashUpdate (Hash2, Data, DataSize); + UT_ASSERT_NOT_EFI_ERROR (Status); + + Status = Hash2->HashFinal (Hash2, &Hash); + UT_ASSERT_NOT_EFI_ERROR (Status); + UT_ASSERT_MEM_EQUAL (Hash.Sha256Hash, ExpectedHash, sizeof (ExpectedHash)); + + return UNIT_TEST_PASSED; +} + +STATIC +UNIT_TEST_STATUS +EFIAPI +TestHash2SHA384 ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + EFI_HASH2_PROTOCOL *Hash2; + EFI_HASH2_OUTPUT Hash; + UINT8 Data[] = "Test Data"; + UINTN DataSize = sizeof (Data) - 1; + UINT8 ExpectedHash[] = { + 0x18, 0x50, 0x0E, 0x64, 0x2F, 0xAA, 0x93, 0x32, + 0x3D, 0x8B, 0x94, 0xE2, 0x88, 0xAB, 0x0F, 0xBE, + 0x83, 0x5A, 0x40, 0x3F, 0x0D, 0xDF, 0x2E, 0xA0, + 0xAF, 0x04, 0x53, 0x78, 0x6D, 0x3F, 0x26, 0x16, + 0x23, 0x7D, 0x85, 0xD7, 0x42, 0x14, 0xEB, 0x20, + 0x7C, 0xAD, 0x29, 0xA7, 0x0B, 0xD9, 0xD4, 0xEB + }; + + Status = gBS->LocateProtocol (&gEfiHash2ProtocolGuid, NULL, (VOID **)&Hash2); + UT_ASSERT_NOT_EFI_ERROR (Status); + UT_ASSERT_NOT_NULL (Hash2); + + // + // Test SHA384 + // + Status = Hash2->Hash (Hash2, &gEfiHashAlgorithmSha384Guid, Data, DataSize, &Hash); + UT_ASSERT_NOT_EFI_ERROR (Status); + UT_ASSERT_MEM_EQUAL (Hash.Sha384Hash, ExpectedHash, sizeof (ExpectedHash)); + + // + // Test SHA384 INIT/UPDATE/FINAL + // + Status = Hash2->HashInit (Hash2, &gEfiHashAlgorithmSha384Guid); + UT_ASSERT_NOT_EFI_ERROR (Status); + + Status = Hash2->HashUpdate (Hash2, Data, DataSize); + UT_ASSERT_NOT_EFI_ERROR (Status); + + Status = Hash2->HashFinal (Hash2, &Hash); + UT_ASSERT_NOT_EFI_ERROR (Status); + UT_ASSERT_MEM_EQUAL (Hash.Sha384Hash, ExpectedHash, sizeof (ExpectedHash)); + + return UNIT_TEST_PASSED; +} + +STATIC +UNIT_TEST_STATUS +EFIAPI +TestHash2SHA512 ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + EFI_HASH2_PROTOCOL *Hash2; + EFI_HASH2_OUTPUT Hash; + UINT8 Data[] = "Test Data"; + UINTN DataSize = sizeof (Data) - 1; + UINT8 ExpectedHash[] = { + 0x43, 0x9E, 0x4C, 0xEE, 0xD9, 0x31, 0x2F, 0xEF, + 0x2E, 0x55, 0x40, 0x42, 0xC3, 0xD2, 0x7D, 0x6A, + 0xC3, 0x1D, 0xA9, 0xCF, 0x72, 0xBA, 0x86, 0x6B, + 0xA9, 0xB0, 0xE0, 0x03, 0x28, 0xD0, 0x62, 0x80, + 0x79, 0x74, 0x82, 0xBF, 0x2C, 0xD0, 0x07, 0xE0, + 0x80, 0x82, 0x96, 0xDB, 0x0B, 0x98, 0x7B, 0x73, + 0xFE, 0x1F, 0x95, 0x3E, 0x97, 0xE2, 0x58, 0x83, + 0x26, 0x3B, 0x97, 0x83, 0x51, 0x3C, 0x29, 0x49 + }; + + Status = gBS->LocateProtocol (&gEfiHash2ProtocolGuid, NULL, (VOID **)&Hash2); + UT_ASSERT_NOT_EFI_ERROR (Status); + UT_ASSERT_NOT_NULL (Hash2); + + // + // Test SHA512 + // + Status = Hash2->Hash (Hash2, &gEfiHashAlgorithmSha512Guid, Data, DataSize, &Hash); + UT_ASSERT_NOT_EFI_ERROR (Status); + UT_ASSERT_MEM_EQUAL (Hash.Sha384Hash, ExpectedHash, sizeof (ExpectedHash)); + + // + // Test SHA512 INIT/UPDATE/FINAL + // + Status = Hash2->HashInit (Hash2, &gEfiHashAlgorithmSha512Guid); + UT_ASSERT_NOT_EFI_ERROR (Status); + + Status = Hash2->HashUpdate (Hash2, Data, DataSize); + UT_ASSERT_NOT_EFI_ERROR (Status); + + Status = Hash2->HashFinal (Hash2, &Hash); + UT_ASSERT_NOT_EFI_ERROR (Status); + UT_ASSERT_MEM_EQUAL (Hash.Sha512Hash, ExpectedHash, sizeof (ExpectedHash)); + + return UNIT_TEST_PASSED; +} + +STATIC +UNIT_TEST_STATUS +EFIAPI +TestDestroyHash2ServiceBindingChild ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + EFI_SERVICE_BINDING_PROTOCOL *Hash2ServiceBinding; + + // Locate the Hash2 Service Binding Protocol + Status = gBS->LocateProtocol (&gEfiHash2ServiceBindingProtocolGuid, NULL, (VOID **)&Hash2ServiceBinding); + UT_ASSERT_NOT_EFI_ERROR (Status); + UT_ASSERT_NOT_NULL (Hash2ServiceBinding); + + if (mHash2ServiceHandle != NULL) { + // Destroy the child instance of the Hash2 Service Binding Protocol + Status = Hash2ServiceBinding->DestroyChild (Hash2ServiceBinding, mHash2ServiceHandle); + UT_ASSERT_NOT_EFI_ERROR (Status); + } + + return UNIT_TEST_PASSED; +} + +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + UNIT_TEST_FRAMEWORK_HANDLE Framework = NULL; + UNIT_TEST_SUITE_HANDLE Hash2AuditTests; + + DEBUG ((DEBUG_INFO, "%a v%a\n", UNIT_TEST_APP_NAME, UNIT_TEST_APP_VERSION)); + + Status = InitUnitTestFramework (&Framework, UNIT_TEST_APP_NAME, gEfiCallerBaseName, UNIT_TEST_APP_VERSION); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = CreateUnitTestSuite (&Hash2AuditTests, Framework, "Hash2AuditTests", "Hash2.Audit", NULL, NULL); + if (EFI_ERROR (Status)) { + return Status; + } + + // -----------Suite------------Description-------Class---------Test Function-Pre---Clean-Context + AddTestCase (Hash2AuditTests, "Test Locate Hash2 Protocol", "Hash2.Audit.TestLocateHash2Protocol", TestLocateHash2Protocol, NULL, NULL, NULL); + AddTestCase (Hash2AuditTests, "Test Hash2 MD5", "Hash2.Audit.TestHash2Md5", TestHash2Md5, NULL, NULL, NULL); + AddTestCase (Hash2AuditTests, "Test Hash2 SHA1", "Hash2.Audit.TestHash2Sha1", TestHash2Sha1, NULL, NULL, NULL); + AddTestCase (Hash2AuditTests, "Test Hash2 SHA256", "Hash2.Audit.TestHash2SHA256", TestHash2SHA256, NULL, NULL, NULL); + AddTestCase (Hash2AuditTests, "Test Hash2 SHA384", "Hash2.Audit.TestHash2SHA384", TestHash2SHA384, NULL, NULL, NULL); + AddTestCase (Hash2AuditTests, "Test Hash2 SHA512", "Hash2.Audit.TestHash2SHA512", TestHash2SHA512, NULL, NULL, NULL); + AddTestCase (Hash2AuditTests, "Test Destroy Hash2 Service Binding Child", "Hash2.Audit.TestDestroyHash2ServiceBindingChild", TestDestroyHash2ServiceBindingChild, NULL, NULL, NULL); + + Status = RunAllTestSuites (Framework); + + if (Framework) { + FreeUnitTestFramework (Framework); + } + + return Status; +} diff --git a/SecurityPkg/Hash2DxeCrypto/Hash2DxeCryptoAudit/Hash2DxeCryptoAudit.inf b/SecurityPkg/Hash2DxeCrypto/Hash2DxeCryptoAudit/Hash2DxeCryptoAudit.inf new file mode 100644 index 0000000000..dfb01bccd0 --- /dev/null +++ b/SecurityPkg/Hash2DxeCrypto/Hash2DxeCryptoAudit/Hash2DxeCryptoAudit.inf @@ -0,0 +1,53 @@ +## @file +# Uefi Shell based Application that Unit Tests and Audits the Hash2Protocol +# +# Copyright (C) Microsoft Corporation. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = Hash2DxeCryptoAudit + FILE_GUID = DC945964-672D-4FD9-B891-73FB0DB50F15 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = UefiMain + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 AA64 +# + +[Sources] + Hash2DxeCryptoAudit.c + +[Packages] + MsCorePkg/MsCorePkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + UefiApplicationEntryPoint + DebugLib + UnitTestLib + PrintLib + +[Protocols] + gEfiHash2ServiceBindingProtocolGuid + gEfiHash2ProtocolGuid + +[Guids] + gEfiHashAlgorithmMD5Guid ## CONSUMES + gEfiHashAlgorithmSha1Guid ## CONSUMES + gEfiHashAlgorithmSha256Guid ## CONSUMES + gEfiHashAlgorithmSha384Guid ## CONSUMES + gEfiHashAlgorithmSha512Guid ## CONSUMES + +[Depex] + +[FeaturePcd] + +[Pcd]