They will do basic validation for authentication data structure, then call crypto library\r
to verify the signature.\r
\r
-Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.<BR>\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
which accompanies this distribution. The full text of the license may be found at\r
///\r
UINT8 mPubKeyStore[MAX_KEYDB_SIZE];\r
UINT32 mPubKeyNumber;\r
+UINT8 mCertDbStore[MAX_CERTDB_SIZE];\r
UINT32 mPlatformMode;\r
EFI_GUID mSignatureSupport[] = {EFI_CERT_SHA1_GUID, EFI_CERT_SHA256_GUID, EFI_CERT_RSA2048_GUID, EFI_CERT_X509_GUID};\r
//\r
\r
if (Variable.CurrPtr == NULL) {\r
VarAttr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;\r
- ListSize = 0;\r
+ ListSize = sizeof (UINT32);\r
Status = UpdateVariable (\r
EFI_CERT_DB_NAME,\r
&gEfiCertDbGuid,\r
&Variable,\r
NULL\r
);\r
-\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
} \r
\r
return Status;\r
UINT32 Index;\r
VARIABLE_POINTER_TRACK Variable;\r
UINT8 *Ptr;\r
+ UINT8 *Data;\r
+ UINTN DataSize;\r
\r
if (PubKey == NULL) {\r
return 0;\r
//\r
if (mPubKeyNumber == MAX_KEY_NUM) {\r
//\r
- // Notes: Database is full, need enhancement here, currently just return 0.\r
+ // Public key dadatase is full, try to reclaim invalid key.\r
//\r
- return 0;\r
+ if (AtRuntime ()) {\r
+ //\r
+ // NV storage can't reclaim at runtime.\r
+ //\r
+ return 0;\r
+ }\r
+ \r
+ Status = Reclaim (\r
+ mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,\r
+ &mVariableModuleGlobal->NonVolatileLastVariableOffset,\r
+ FALSE,\r
+ NULL,\r
+ TRUE,\r
+ TRUE\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return 0;\r
+ }\r
+\r
+ Status = FindVariable (\r
+ AUTHVAR_KEYDB_NAME,\r
+ &gEfiAuthenticatedVariableGuid,\r
+ &Variable,\r
+ &mVariableModuleGlobal->VariableGlobal,\r
+ FALSE\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ DataSize = DataSizeOfVariable (Variable.CurrPtr);\r
+ Data = GetVariableDataPtr (Variable.CurrPtr);\r
+ ASSERT ((DataSize != 0) && (Data != NULL));\r
+ CopyMem (mPubKeyStore, (UINT8 *) Data, DataSize);\r
+ mPubKeyNumber = (UINT32) (DataSize / EFI_CERT_TYPE_RSA2048_SIZE);\r
+\r
+ if (mPubKeyNumber == MAX_KEY_NUM) {\r
+ return 0;\r
+ } \r
}\r
\r
CopyMem (mPubKeyStore + mPubKeyNumber * EFI_CERT_TYPE_RSA2048_SIZE, PubKey, EFI_CERT_TYPE_RSA2048_SIZE);\r
EFI_CERT_BLOCK_RSA_2048_SHA256 *CertBlock;\r
UINT8 Digest[SHA256_DIGEST_SIZE];\r
VOID *Rsa;\r
-\r
+ UINTN PayloadSize;\r
+ \r
+ PayloadSize = DataSize - AUTHINFO_SIZE;\r
Rsa = NULL;\r
CertData = NULL;\r
CertBlock = NULL;\r
if (!Status) {\r
goto Done;\r
}\r
- Status = Sha256Update (mHashCtx, Data + AUTHINFO_SIZE, (UINTN) (DataSize - AUTHINFO_SIZE));\r
+ Status = Sha256Update (mHashCtx, Data + AUTHINFO_SIZE, PayloadSize);\r
+ if (!Status) {\r
+ goto Done;\r
+ }\r
+ //\r
+ // Hash Size.\r
+ //\r
+ Status = Sha256Update (mHashCtx, &PayloadSize, sizeof (UINTN));\r
if (!Status) {\r
goto Done;\r
}\r
}\r
\r
/**\r
- Check input data form to make sure it is a valid EFI_SIGNATURE_LIST for PK/KEK variable.\r
+ Check input data form to make sure it is a valid EFI_SIGNATURE_LIST for PK/KEK/db/dbx variable.\r
\r
@param[in] VariableName Name of Variable to be check.\r
@param[in] VendorGuid Variable vendor GUID.\r
UINT32 Index;\r
UINT32 SigCount;\r
BOOLEAN IsPk;\r
+ VOID *RsaContext;\r
+ EFI_SIGNATURE_DATA *CertData;\r
+ UINTN CertLen;\r
\r
if (DataSize == 0) {\r
return EFI_SUCCESS;\r
\r
if (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp (VariableName, EFI_PLATFORM_KEY_NAME) == 0)){\r
IsPk = TRUE;\r
- } else if (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp (VariableName, EFI_KEY_EXCHANGE_KEY_NAME) == 0)) {\r
+ } else if ((CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && StrCmp (VariableName, EFI_KEY_EXCHANGE_KEY_NAME) == 0) ||\r
+ (CompareGuid (VendorGuid, &gEfiImageSecurityDatabaseGuid) && \r
+ (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE) == 0 || StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE1) == 0))){\r
IsPk = FALSE;\r
} else {\r
return EFI_SUCCESS;\r
SigCount = 0;\r
SigList = (EFI_SIGNATURE_LIST *) Data;\r
SigDataSize = DataSize;\r
+ RsaContext = NULL;\r
\r
//\r
// Walk throuth the input signature list and check the data format.\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
+ if (CompareGuid (&SigList->SignatureType, &gEfiCertX509Guid)) {\r
+ //\r
+ // Try to retrieve the RSA public key from the X.509 certificate.\r
+ // If this operation fails, it's not a valid certificate.\r
+ //\r
+ RsaContext = RsaNew ();\r
+ if (RsaContext == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ CertData = (EFI_SIGNATURE_DATA *) ((UINT8 *) SigList + sizeof (EFI_SIGNATURE_LIST) + SigList->SignatureHeaderSize);\r
+ CertLen = SigList->SignatureSize - sizeof (EFI_GUID);\r
+ if (!RsaGetPublicKeyFromX509 (CertData->SignatureData, CertLen, &RsaContext)) {\r
+ RsaFree (RsaContext);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ RsaFree (RsaContext);\r
+ }\r
+\r
if ((SigList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - SigList->SignatureHeaderSize) % SigList->SignatureSize != 0) {\r
return EFI_INVALID_PARAMETER;\r
}\r
Payload = (UINT8 *) Data + AUTHINFO2_SIZE (Data);\r
PayloadSize = DataSize - AUTHINFO2_SIZE (Data);\r
\r
+ Status = CheckSignatureListFormat(VariableName, VendorGuid, Payload, PayloadSize);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ \r
Status = UpdateVariable (\r
VariableName,\r
VendorGuid,\r
@return EFI_INVALID_PARAMETER Invalid parameter.\r
@return EFI_WRITE_PROTECTED Variable is write-protected and needs authentication with\r
EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.\r
+ @return EFI_OUT_OF_RESOURCES The Database to save the public key is full.\r
@return EFI_SECURITY_VIOLATION The variable is with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS\r
set, but the AuthInfo does NOT pass the validation\r
check carried out by the firmware.\r
return EFI_SECURITY_VIOLATION;\r
}\r
\r
+ //\r
+ // A time-based authenticated variable and a count-based authenticated variable\r
+ // can't be updated by each other.\r
+ // \r
+ if (Variable->CurrPtr != NULL) { \r
+ if (((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) &&\r
+ ((Variable->CurrPtr->Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0)) {\r
+ return EFI_SECURITY_VIOLATION; \r
+ }\r
+ \r
+ if (((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) && \r
+ ((Variable->CurrPtr->Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0)) {\r
+ return EFI_SECURITY_VIOLATION; \r
+ }\r
+ }\r
+ \r
//\r
// Process Time-based Authenticated variable.\r
//\r
//\r
KeyIndex = AddPubKeyInStore (PubKey);\r
if (KeyIndex == 0) {\r
- return EFI_SECURITY_VIOLATION;\r
+ return EFI_OUT_OF_RESOURCES;\r
}\r
}\r
\r
} else if (FirstTime->Hour != SecondTime->Hour) {\r
return (BOOLEAN) (FirstTime->Hour < SecondTime->Hour);\r
} else if (FirstTime->Minute != SecondTime->Minute) {\r
- return (BOOLEAN) (FirstTime->Minute < FirstTime->Minute);\r
+ return (BOOLEAN) (FirstTime->Minute < SecondTime->Minute);\r
}\r
\r
return (BOOLEAN) (FirstTime->Second <= SecondTime->Second);\r
// Construct new data content of variable "certdb".\r
//\r
NewCertDbSize = (UINT32) DataSize - CertNodeSize;\r
- NewCertDb = AllocateZeroPool (NewCertDbSize);\r
- if (NewCertDb == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
+ NewCertDb = (UINT8*) mCertDbStore;\r
\r
//\r
// Copy the DB entries before deleting node.\r
NULL\r
);\r
\r
- FreePool (NewCertDb);\r
return Status;\r
}\r
\r
//\r
NameSize = (UINT32) StrLen (VariableName);\r
CertNodeSize = sizeof (AUTH_CERT_DB_DATA) + (UINT32) CertDataSize + NameSize * sizeof (CHAR16); \r
- NewCertDbSize = (UINT32) DataSize + CertNodeSize; \r
- NewCertDb = AllocateZeroPool (NewCertDbSize);\r
- if (NewCertDb == NULL) {\r
+ NewCertDbSize = (UINT32) DataSize + CertNodeSize;\r
+ if (NewCertDbSize > MAX_CERTDB_SIZE) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
+ NewCertDb = (UINT8*) mCertDbStore;\r
\r
//\r
// Copy the DB entries before deleting node.\r
NULL\r
);\r
\r
- FreePool (NewCertDb);\r
return Status;\r
}\r
\r
//\r
// Delete signer's certificates when delete the common authenticated variable.\r
//\r
- if ((PayloadSize == 0) && (Variable->CurrPtr != NULL)) {\r
+ if ((PayloadSize == 0) && (Variable->CurrPtr != NULL) && ((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0)) {\r
Status = DeleteCertsFromDb (VariableName, VendorGuid);\r
if (EFI_ERROR (Status)) {\r
VerifyStatus = FALSE;\r
goto Exit;\r
}\r
- } else if (Variable->CurrPtr == NULL) {\r
+ } else if (Variable->CurrPtr == NULL && PayloadSize != 0) {\r
//\r
// Insert signer's certificates when adding a new common authenticated variable.\r
//\r