| /** @file | |
| Detects if PcdFmpDevicePkcs7CertBufferXdr contains a test key. | |
| Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR> | |
| SPDX-License-Identifier: BSD-2-Clause-Patent | |
| **/ | |
| #include "FmpDxe.h" | |
| /** | |
| Check to see if any of the keys in PcdFmpDevicePkcs7CertBufferXdr matches | |
| the test key. PcdFmpDeviceTestKeySha256Digest contains the SHA256 hash of | |
| the test key. For each key in PcdFmpDevicePkcs7CertBufferXdr, compute the | |
| SHA256 hash and compare it to PcdFmpDeviceTestKeySha256Digest. If the | |
| SHA256 hash matches or there is then error computing the SHA256 hash, then | |
| set PcdTestKeyUsed to TRUE. Skip this check if PcdTestKeyUsed is already | |
| TRUE or PcdFmpDeviceTestKeySha256Digest is not exactly SHA256_DIGEST_SIZE | |
| bytes. | |
| **/ | |
| VOID | |
| DetectTestKey ( | |
| VOID | |
| ) | |
| { | |
| BOOLEAN TestKeyUsed; | |
| UINTN PublicKeyDataLength; | |
| UINT8 *PublicKeyDataXdr; | |
| UINT8 *PublicKeyDataXdrEnd; | |
| VOID *HashContext; | |
| UINT8 Digest[SHA256_DIGEST_SIZE]; | |
| UINTN TestKeyDigestSize; | |
| // | |
| // If PcdFmpDeviceTestKeySha256Digest is not exactly SHA256_DIGEST_SIZE bytes, | |
| // then skip the test key detection. | |
| // | |
| TestKeyDigestSize = PcdGetSize (PcdFmpDeviceTestKeySha256Digest); | |
| if (TestKeyDigestSize != SHA256_DIGEST_SIZE) { | |
| return; | |
| } | |
| // | |
| // If PcdTestKeyUsed is already TRUE, then skip test key detection | |
| // | |
| TestKeyUsed = PcdGetBool (PcdTestKeyUsed); | |
| if (TestKeyUsed) { | |
| return; | |
| } | |
| // | |
| // If PcdFmpDevicePkcs7CertBufferXdr is invalid, then skip test key detection | |
| // | |
| PublicKeyDataXdr = PcdGetPtr (PcdFmpDevicePkcs7CertBufferXdr); | |
| PublicKeyDataXdrEnd = PublicKeyDataXdr + PcdGetSize (PcdFmpDevicePkcs7CertBufferXdr); | |
| if ((PublicKeyDataXdr == NULL) || (PublicKeyDataXdr == PublicKeyDataXdrEnd)) { | |
| return; | |
| } | |
| // | |
| // Allocate hash context buffer required for SHA 256 | |
| // | |
| HashContext = AllocatePool (Sha256GetContextSize ()); | |
| if (HashContext == NULL) { | |
| TestKeyUsed = TRUE; | |
| } | |
| // | |
| // Loop through all keys in PcdFmpDevicePkcs7CertBufferXdr | |
| // | |
| while (!TestKeyUsed && PublicKeyDataXdr < PublicKeyDataXdrEnd) { | |
| if (PublicKeyDataXdr + sizeof (UINT32) > PublicKeyDataXdrEnd) { | |
| // | |
| // Key data extends beyond end of PCD | |
| // | |
| break; | |
| } | |
| // | |
| // Read key length stored in big endian format | |
| // | |
| PublicKeyDataLength = SwapBytes32 (*(UINT32 *)(PublicKeyDataXdr)); | |
| // | |
| // Point to the start of the key data | |
| // | |
| PublicKeyDataXdr += sizeof (UINT32); | |
| if (PublicKeyDataXdr + PublicKeyDataLength > PublicKeyDataXdrEnd) { | |
| // | |
| // Key data extends beyond end of PCD | |
| // | |
| break; | |
| } | |
| // | |
| // Hash public key from PcdFmpDevicePkcs7CertBufferXdr using SHA256. | |
| // If error occurs computing SHA256, then assume test key is in use. | |
| // | |
| ZeroMem (Digest, SHA256_DIGEST_SIZE); | |
| if (!Sha256Init (HashContext)) { | |
| TestKeyUsed = TRUE; | |
| break; | |
| } | |
| if (!Sha256Update (HashContext, PublicKeyDataXdr, PublicKeyDataLength)) { | |
| TestKeyUsed = TRUE; | |
| break; | |
| } | |
| if (!Sha256Final (HashContext, Digest)) { | |
| TestKeyUsed = TRUE; | |
| break; | |
| } | |
| // | |
| // Check if SHA256 hash of public key matches SHA256 hash of test key | |
| // | |
| if (CompareMem (Digest, PcdGetPtr (PcdFmpDeviceTestKeySha256Digest), SHA256_DIGEST_SIZE) == 0) { | |
| TestKeyUsed = TRUE; | |
| break; | |
| } | |
| // | |
| // Point to start of next key | |
| // | |
| PublicKeyDataXdr += PublicKeyDataLength; | |
| PublicKeyDataXdr = (UINT8 *)ALIGN_POINTER (PublicKeyDataXdr, sizeof (UINT32)); | |
| } | |
| // | |
| // Free hash context buffer required for SHA 256 | |
| // | |
| if (HashContext != NULL) { | |
| FreePool (HashContext); | |
| HashContext = NULL; | |
| } | |
| // | |
| // If test key detected or an error occurred checking for the test key, then | |
| // set PcdTestKeyUsed to TRUE. | |
| // | |
| if (TestKeyUsed) { | |
| DEBUG ((DEBUG_INFO, "FmpDxe(%s): Test key detected in PcdFmpDevicePkcs7CertBufferXdr.\n", mImageIdName)); | |
| PcdSetBoolS (PcdTestKeyUsed, TRUE); | |
| } else { | |
| DEBUG ((DEBUG_INFO, "FmpDxe(%s): No test key detected in PcdFmpDevicePkcs7CertBufferXdr.\n", mImageIdName)); | |
| } | |
| } |