--- /dev/null
+/** @file\r
+ Detects if PcdFmpDevicePkcs7CertBufferXdr contains a test key.\r
+\r
+ Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>\r
+\r
+ Redistribution and use in source and binary forms, with or without\r
+ modification, are permitted provided that the following conditions are met:\r
+ 1. Redistributions of source code must retain the above copyright notice,\r
+ this list of conditions and the following disclaimer.\r
+ 2. Redistributions in binary form must reproduce the above copyright notice,\r
+ this list of conditions and the following disclaimer in the documentation\r
+ and/or other materials provided with the distribution.\r
+\r
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND\r
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\r
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,\r
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\r
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\r
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\r
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+\r
+**/\r
+\r
+#include <PiDxe.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/BaseCryptLib.h>\r
+\r
+/**\r
+ Check to see if any of the keys in PcdFmpDevicePkcs7CertBufferXdr matches\r
+ the test key. PcdFmpDeviceTestKeySha256Digest contains the SHA256 hash of\r
+ the test key. For each key in PcdFmpDevicePkcs7CertBufferXdr, compute the\r
+ SHA256 hash and compare it to PcdFmpDeviceTestKeySha256Digest. If the\r
+ SHA256 hash matches or there is then error computing the SHA256 hash, then\r
+ set PcdTestKeyUsed to TRUE. Skip this check if PcdTestKeyUsed is already\r
+ TRUE or PcdFmpDeviceTestKeySha256Digest is not exactly SHA256_DIGEST_SIZE\r
+ bytes.\r
+**/\r
+VOID\r
+DetectTestKey (\r
+ VOID\r
+ )\r
+{\r
+ BOOLEAN TestKeyUsed;\r
+ UINTN PublicKeyDataLength;\r
+ UINT8 *PublicKeyDataXdr;\r
+ UINT8 *PublicKeyDataXdrEnd;\r
+ VOID *HashContext;\r
+ UINT8 Digest[SHA256_DIGEST_SIZE];\r
+\r
+ //\r
+ // If PcdFmpDeviceTestKeySha256Digest is not exacty SHA256_DIGEST_SIZE bytes,\r
+ // then skip the test key detection.\r
+ //\r
+ if (PcdGetSize (PcdFmpDeviceTestKeySha256Digest) != SHA256_DIGEST_SIZE) {\r
+ return;\r
+ }\r
+\r
+ //\r
+ // If PcdTestKeyUsed is already TRUE, then skip test key detection\r
+ //\r
+ TestKeyUsed = PcdGetBool (PcdTestKeyUsed);\r
+ if (TestKeyUsed) {\r
+ return;\r
+ }\r
+\r
+ //\r
+ // If PcdFmpDevicePkcs7CertBufferXdr is invalid, then skip test key detection\r
+ //\r
+ PublicKeyDataXdr = PcdGetPtr (PcdFmpDevicePkcs7CertBufferXdr);\r
+ PublicKeyDataXdrEnd = PublicKeyDataXdr + PcdGetSize (PcdFmpDevicePkcs7CertBufferXdr);\r
+ if (PublicKeyDataXdr == NULL || PublicKeyDataXdr == PublicKeyDataXdrEnd) {\r
+ return;\r
+ }\r
+\r
+ //\r
+ // Allocate hash context buffer required for SHA 256\r
+ //\r
+ HashContext = AllocatePool (Sha256GetContextSize ());\r
+ if (HashContext == NULL) {\r
+ TestKeyUsed = TRUE;\r
+ }\r
+\r
+ //\r
+ // Loop through all keys in PcdFmpDevicePkcs7CertBufferXdr\r
+ //\r
+ while (!TestKeyUsed && PublicKeyDataXdr < PublicKeyDataXdrEnd) {\r
+ if (PublicKeyDataXdr + sizeof (UINT32) > PublicKeyDataXdrEnd) {\r
+ //\r
+ // Key data extends beyond end of PCD\r
+ //\r
+ break;\r
+ }\r
+ //\r
+ // Read key length stored in big endian format\r
+ //\r
+ PublicKeyDataLength = SwapBytes32 (*(UINT32 *)(PublicKeyDataXdr));\r
+ //\r
+ // Point to the start of the key data\r
+ //\r
+ PublicKeyDataXdr += sizeof (UINT32);\r
+ if (PublicKeyDataXdr + PublicKeyDataLength > PublicKeyDataXdrEnd) {\r
+ //\r
+ // Key data extends beyond end of PCD\r
+ //\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Hash public key from PcdFmpDevicePkcs7CertBufferXdr using SHA256.\r
+ // If error occurs computing SHA256, then assume test key is in use.\r
+ //\r
+ ZeroMem (Digest, SHA256_DIGEST_SIZE);\r
+ if (!Sha256Init (HashContext)) {\r
+ TestKeyUsed = TRUE;\r
+ break;\r
+ }\r
+ if (!Sha256Update (HashContext, PublicKeyDataXdr, PublicKeyDataLength)) {\r
+ TestKeyUsed = TRUE;\r
+ break;\r
+ }\r
+ if (!Sha256Final (HashContext, Digest)) {\r
+ TestKeyUsed = TRUE;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Check if SHA256 hash of public key matches SHA256 hash of test key\r
+ //\r
+ if (CompareMem (Digest, PcdGetPtr (PcdFmpDeviceTestKeySha256Digest), SHA256_DIGEST_SIZE) == 0) {\r
+ TestKeyUsed = TRUE;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Point to start of next key\r
+ //\r
+ PublicKeyDataXdr += PublicKeyDataLength;\r
+ PublicKeyDataXdr = (UINT8 *)ALIGN_POINTER (PublicKeyDataXdr, sizeof (UINT32));\r
+ }\r
+\r
+ //\r
+ // Free hash context buffer required for SHA 256\r
+ //\r
+ if (HashContext != NULL) {\r
+ FreePool (HashContext);\r
+ HashContext = NULL;\r
+ }\r
+\r
+ //\r
+ // If test key detected or an error occured checking for the test key, then\r
+ // set PcdTestKeyUsed to TRUE.\r
+ //\r
+ if (TestKeyUsed) {\r
+ DEBUG ((DEBUG_INFO, "FmpDxe: Test key detected in PcdFmpDevicePkcs7CertBufferXdr.\n"));\r
+ PcdSetBoolS (PcdTestKeyUsed, TRUE);\r
+ } else {\r
+ DEBUG ((DEBUG_INFO, "FmpDxe: No test key detected in PcdFmpDevicePkcs7CertBufferXdr.\n"));\r
+ }\r
+}\r