UINT32 mPubKeyNumber;\r
UINT8 mCertDbStore[MAX_CERTDB_SIZE];\r
UINT32 mPlatformMode;\r
+UINT8 mVendorKeyState;\r
+\r
EFI_GUID mSignatureSupport[] = {EFI_CERT_SHA1_GUID, EFI_CERT_SHA256_GUID, EFI_CERT_RSA2048_GUID, EFI_CERT_X509_GUID};\r
//\r
// Public Exponent of RSA Key.\r
//\r
VOID *mHashCtx = NULL;\r
\r
-//\r
-// Pointer to runtime buffer.\r
-// For "Append" operation to an existing variable, a read/modify/write operation\r
-// is supported by firmware internally. Reserve runtime buffer to cache previous\r
-// variable data in runtime phase because memory allocation is forbidden in virtual mode.\r
-//\r
-VOID *mStorageArea = NULL;\r
-\r
//\r
// The serialization of the values of the VariableName, VendorGuid and Attributes\r
// parameters of the SetVariable() call and the TimeStamp component of the\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- //\r
- // Reserved runtime buffer for "Append" operation in virtual mode.\r
- //\r
- mStorageArea = AllocateRuntimePool (MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize)));\r
- if (mStorageArea == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
//\r
// Prepare runtime buffer for serialized data of time-based authenticated\r
// Variable, i.e. (VariableName, VendorGuid, Attributes, TimeStamp, Data).\r
}\r
\r
//\r
- // Create "SetupMode" varable with BS+RT attribute set.\r
+ // Create "SetupMode" variable with BS+RT attribute set.\r
//\r
FindVariable (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);\r
if (PkVariable.CurrPtr == NULL) {\r
}\r
\r
//\r
- // Create "SignatureSupport" varable with BS+RT attribute set.\r
+ // Create "SignatureSupport" variable with BS+RT attribute set.\r
//\r
FindVariable (EFI_SIGNATURE_SUPPORT_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);\r
Status = UpdateVariable (\r
}\r
\r
//\r
- // Create "SecureBoot" varable with BS+RT attribute set.\r
+ // Create "SecureBoot" variable with BS+RT attribute set.\r
//\r
if (SecureBootEnable == SECURE_BOOT_ENABLE && mPlatformMode == USER_MODE) {\r
SecureBootMode = SECURE_BOOT_MODE_ENABLE;\r
}\r
} \r
\r
+ //\r
+ // Check "VendorKeysNv" variable's existence and create "VendorKeys" variable accordingly.\r
+ //\r
+ FindVariable (EFI_VENDOR_KEYS_NV_VARIABLE_NAME, &gEfiVendorKeysNvGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);\r
+ if (Variable.CurrPtr != NULL) {\r
+ mVendorKeyState = *(GetVariableDataPtr (Variable.CurrPtr));\r
+ } else {\r
+ //\r
+ // "VendorKeysNv" not exist, initialize it in VENDOR_KEYS_VALID state.\r
+ //\r
+ mVendorKeyState = VENDOR_KEYS_VALID;\r
+ Status = UpdateVariable (\r
+ EFI_VENDOR_KEYS_NV_VARIABLE_NAME,\r
+ &gEfiVendorKeysNvGuid,\r
+ &mVendorKeyState,\r
+ sizeof (UINT8),\r
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS,\r
+ 0,\r
+ 0,\r
+ &Variable,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Create "VendorKeys" variable with BS+RT attribute set.\r
+ //\r
+ FindVariable (EFI_VENDOR_KEYS_VARIABLE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);\r
+ Status = UpdateVariable (\r
+ EFI_VENDOR_KEYS_VARIABLE_NAME,\r
+ &gEfiGlobalVariableGuid,\r
+ &mVendorKeyState,\r
+ sizeof (UINT8),\r
+ EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+ 0,\r
+ 0,\r
+ &Variable,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ DEBUG ((EFI_D_INFO, "Variable %s is %x\n", EFI_VENDOR_KEYS_VARIABLE_NAME, mVendorKeyState));\r
+\r
return Status;\r
}\r
\r
&mVariableModuleGlobal->NonVolatileLastVariableOffset,\r
FALSE,\r
NULL,\r
- TRUE,\r
+ NULL,\r
+ 0,\r
TRUE\r
);\r
if (EFI_ERROR (Status)) {\r
return EFI_SUCCESS;\r
}\r
\r
+/**\r
+ Update "VendorKeys" variable to record the out of band secure boot key modification.\r
+\r
+ @return EFI_SUCCESS Variable is updated successfully.\r
+ @return Others Failed to update variable.\r
+ \r
+**/\r
+EFI_STATUS\r
+VendorKeyIsModified (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ VARIABLE_POINTER_TRACK Variable;\r
+\r
+ if (mVendorKeyState == VENDOR_KEYS_MODIFIED) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ mVendorKeyState = VENDOR_KEYS_MODIFIED;\r
+ \r
+ FindVariable (EFI_VENDOR_KEYS_NV_VARIABLE_NAME, &gEfiVendorKeysNvGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);\r
+ Status = UpdateVariable (\r
+ EFI_VENDOR_KEYS_NV_VARIABLE_NAME,\r
+ &gEfiVendorKeysNvGuid,\r
+ &mVendorKeyState,\r
+ sizeof (UINT8),\r
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS,\r
+ 0,\r
+ 0,\r
+ &Variable,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ FindVariable (EFI_VENDOR_KEYS_VARIABLE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);\r
+ return UpdateVariable (\r
+ EFI_VENDOR_KEYS_VARIABLE_NAME,\r
+ &gEfiGlobalVariableGuid,\r
+ &mVendorKeyState,\r
+ sizeof (UINT8),\r
+ EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+ 0,\r
+ 0,\r
+ &Variable,\r
+ NULL\r
+ );\r
+}\r
+\r
/**\r
Process variable with platform key for verification.\r
\r
Variable,\r
&((EFI_VARIABLE_AUTHENTICATION_2 *) Data)->TimeStamp\r
);\r
+ if (EFI_ERROR(Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if ((mPlatformMode != SETUP_MODE) || IsPk) {\r
+ Status = VendorKeyIsModified ();\r
+ }\r
} else if (mPlatformMode == USER_MODE) {\r
//\r
// Verify against X509 Cert in PK database.\r
Variable,\r
&((EFI_VARIABLE_AUTHENTICATION_2 *) Data)->TimeStamp\r
);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (mPlatformMode != SETUP_MODE) {\r
+ Status = VendorKeyIsModified ();\r
+ }\r
}\r
\r
return Status;\r
\r
if (AuthVarType == AuthVarTypePk) {\r
//\r
- // Get platform key from variable.\r
+ // Verify that the signature has been made with the current Platform Key (no chaining for PK).\r
+ // First, get signer's certificates from SignedData.\r
+ //\r
+ VerifyStatus = Pkcs7GetSigners (\r
+ SigData,\r
+ SigDataSize,\r
+ &SignerCerts,\r
+ &CertStackSize,\r
+ &RootCert,\r
+ &RootCertSize\r
+ );\r
+ if (!VerifyStatus) {\r
+ goto Exit;\r
+ }\r
+\r
+ //\r
+ // Second, get the current platform key from variable. Check whether it's identical with signer's certificates\r
+ // in SignedData. If not, return error immediately.\r
//\r
Status = FindVariable (\r
EFI_PLATFORM_KEY_NAME,\r
FALSE\r
);\r
if (EFI_ERROR (Status)) {\r
- return Status;\r
+ VerifyStatus = FALSE;\r
+ goto Exit;\r
}\r
-\r
CertList = (EFI_SIGNATURE_LIST *) GetVariableDataPtr (PkVariable.CurrPtr);\r
Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
- RootCert = Cert->SignatureData;\r
- RootCertSize = CertList->SignatureSize - (sizeof (EFI_SIGNATURE_DATA) - 1);\r
-\r
+ if ((RootCertSize != (CertList->SignatureSize - (sizeof (EFI_SIGNATURE_DATA) - 1))) ||\r
+ (CompareMem (Cert->SignatureData, RootCert, RootCertSize) != 0)) {\r
+ VerifyStatus = FALSE;\r
+ goto Exit;\r
+ }\r
\r
//\r
// Verify Pkcs7 SignedData via Pkcs7Verify library.\r
\r
Exit:\r
\r
- if (AuthVarType == AuthVarTypePriv) {\r
+ if (AuthVarType == AuthVarTypePk || AuthVarType == AuthVarTypePriv) {\r
Pkcs7FreeSigners (RootCert);\r
Pkcs7FreeSigners (SignerCerts);\r
}\r