]> git.proxmox.com Git - mirror_edk2.git/blobdiff - FmpDevicePkg/FmpDxe/DetectTestKey.c
FmpDevicePkg: Add FmpDxe module
[mirror_edk2.git] / FmpDevicePkg / FmpDxe / DetectTestKey.c
diff --git a/FmpDevicePkg/FmpDxe/DetectTestKey.c b/FmpDevicePkg/FmpDxe/DetectTestKey.c
new file mode 100644 (file)
index 0000000..0a6e37e
--- /dev/null
@@ -0,0 +1,166 @@
+/**  @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