-/**\r
- Verify certificate in WIN_CERT_TYPE_PKCS_SIGNED_DATA format.\r
-\r
- @retval EFI_SUCCESS Image pass verification.\r
- @retval EFI_SECURITY_VIOLATION Image fail verification.\r
-\r
-**/\r
-EFI_STATUS\r
-VerifyCertPkcsSignedData (\r
- VOID\r
- )\r
-{\r
- //\r
- // 1: Find certificate from DBX forbidden database for revoked certificate.\r
- //\r
- if (IsPkcsSignedDataVerifiedBySignatureList (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid)) {\r
- //\r
- // DBX is forbidden database, if Authenticode verification pass with\r
- // one of the certificate in DBX, this image should be rejected.\r
- //\r
- return EFI_SECURITY_VIOLATION;\r
- }\r
-\r
- //\r
- // 2: Find certificate from KEK database and try to verify authenticode struct.\r
- //\r
- if (IsPkcsSignedDataVerifiedBySignatureList (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid)) {\r
- return EFI_SUCCESS;\r
- }\r
-\r
- //\r
- // 3: Find certificate from DB database and try to verify authenticode struct.\r
- //\r
- if (IsPkcsSignedDataVerifiedBySignatureList (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid)) {\r
- return EFI_SUCCESS;\r
- } else {\r
- return EFI_SECURITY_VIOLATION;\r
- }\r
-}\r
-\r
-/**\r
- Verify certificate in WIN_CERTIFICATE_UEFI_GUID format.\r
-\r
- @retval EFI_SUCCESS Image pass verification.\r
- @retval EFI_SECURITY_VIOLATION Image fail verification.\r
- @retval other error value\r
-\r
-**/\r
-EFI_STATUS\r
-VerifyCertUefiGuid (\r
- VOID\r
- )\r
-{\r
- BOOLEAN Status;\r
- WIN_CERTIFICATE_UEFI_GUID *EfiCert;\r
- EFI_SIGNATURE_LIST *KekList;\r
- EFI_SIGNATURE_DATA *KekItem;\r
- EFI_CERT_BLOCK_RSA_2048_SHA256 *CertBlock;\r
- VOID *Rsa;\r
- UINTN KekCount;\r
- UINTN Index;\r
- UINTN KekDataSize;\r
- BOOLEAN IsFound;\r
- EFI_STATUS Result;\r
-\r
- EfiCert = NULL;\r
- KekList = NULL;\r
- KekItem = NULL;\r
- CertBlock = NULL;\r
- Rsa = NULL;\r
- Status = FALSE;\r
- IsFound = FALSE;\r
- KekDataSize = 0;\r
-\r
- EfiCert = (WIN_CERTIFICATE_UEFI_GUID *) (mImageBase + mSecDataDir->VirtualAddress);\r
- CertBlock = (EFI_CERT_BLOCK_RSA_2048_SHA256 *) EfiCert->CertData;\r
- if (!CompareGuid (&EfiCert->CertType, &gEfiCertTypeRsa2048Sha256Guid)) {\r
- //\r
- // Invalid Certificate Data Type.\r
- //\r
- return EFI_SECURITY_VIOLATION;\r
- }\r
-\r
- //\r
- // Get KEK database variable data size\r
- //\r
- Result = gRT->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, NULL, &KekDataSize, NULL);\r
- if (Result != EFI_BUFFER_TOO_SMALL) {\r
- return EFI_SECURITY_VIOLATION;\r
- }\r
-\r
- //\r
- // Get KEK database variable.\r
- //\r
- KekList = GetEfiGlobalVariable (EFI_KEY_EXCHANGE_KEY_NAME);\r
- if (KekList == NULL) {\r
- return EFI_SECURITY_VIOLATION;\r
- }\r
-\r
- //\r
- // Enumerate all Kek items in this list to verify the variable certificate data.\r
- // If anyone is authenticated successfully, it means the variable is correct!\r
- //\r
- while ((KekDataSize > 0) && (KekDataSize >= KekList->SignatureListSize)) {\r
- if (CompareGuid (&KekList->SignatureType, &gEfiCertRsa2048Guid)) {\r
- KekItem = (EFI_SIGNATURE_DATA *) ((UINT8 *) KekList + sizeof (EFI_SIGNATURE_LIST) + KekList->SignatureHeaderSize);\r
- KekCount = (KekList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - KekList->SignatureHeaderSize) / KekList->SignatureSize;\r
- for (Index = 0; Index < KekCount; Index++) {\r
- if (CompareMem (KekItem->SignatureData, CertBlock->PublicKey, EFI_CERT_TYPE_RSA2048_SIZE) == 0) {\r
- IsFound = TRUE;\r
- break;\r
- }\r
- KekItem = (EFI_SIGNATURE_DATA *) ((UINT8 *) KekItem + KekList->SignatureSize);\r
- }\r
- }\r
- KekDataSize -= KekList->SignatureListSize;\r
- KekList = (EFI_SIGNATURE_LIST *) ((UINT8 *) KekList + KekList->SignatureListSize);\r
- }\r
-\r
- if (!IsFound) {\r
- //\r
- // Signed key is not a trust one.\r
- //\r
- goto Done;\r
- }\r
-\r
- //\r
- // Now, we found the corresponding security policy.\r
- // Verify the data payload.\r
- //\r
- Rsa = RsaNew ();\r
- if (Rsa == NULL) {\r
- Status = FALSE;\r
- goto Done;\r
- }\r
-\r
- //\r
- // Set RSA Key Components.\r
- // NOTE: Only N and E are needed to be set as RSA public key for signature verification.\r
- //\r
- Status = RsaSetKey (Rsa, RsaKeyN, CertBlock->PublicKey, EFI_CERT_TYPE_RSA2048_SIZE);\r
- if (!Status) {\r
- goto Done;\r
- }\r
- Status = RsaSetKey (Rsa, RsaKeyE, mRsaE, sizeof (mRsaE));\r
- if (!Status) {\r
- goto Done;\r
- }\r
- //\r
- // Verify the signature.\r
- //\r
- Status = RsaPkcs1Verify (\r
- Rsa,\r
- mImageDigest,\r
- mImageDigestSize,\r
- CertBlock->Signature,\r
- EFI_CERT_TYPE_RSA2048_SHA256_SIZE\r
- );\r
-\r
-Done:\r
- if (KekList != NULL) {\r
- FreePool (KekList);\r
- }\r
- if (Rsa != NULL ) {\r
- RsaFree (Rsa);\r
- }\r
- if (Status) {\r
- return EFI_SUCCESS;\r
- } else {\r
- return EFI_SECURITY_VIOLATION;\r
- }\r
-}\r
-\r