/** @file | |
The Miscellaneous Routines for TlsAuthConfigDxe driver. | |
Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR> | |
SPDX-License-Identifier: BSD-2-Clause-Patent | |
**/ | |
#include "TlsAuthConfigImpl.h" | |
VOID *mStartOpCodeHandle = NULL; | |
VOID *mEndOpCodeHandle = NULL; | |
EFI_IFR_GUID_LABEL *mStartLabel = NULL; | |
EFI_IFR_GUID_LABEL *mEndLabel = NULL; | |
CHAR16 mTlsAuthConfigStorageName[] = L"TLS_AUTH_CONFIG_IFR_NVDATA"; | |
TLS_AUTH_CONFIG_PRIVATE_DATA *mTlsAuthPrivateData = NULL; | |
HII_VENDOR_DEVICE_PATH mTlsAuthConfigHiiVendorDevicePath = { | |
{ | |
{ | |
HARDWARE_DEVICE_PATH, | |
HW_VENDOR_DP, | |
{ | |
(UINT8)(sizeof (VENDOR_DEVICE_PATH)), | |
(UINT8)((sizeof (VENDOR_DEVICE_PATH)) >> 8) | |
} | |
}, | |
TLS_AUTH_CONFIG_GUID | |
}, | |
{ | |
END_DEVICE_PATH_TYPE, | |
END_ENTIRE_DEVICE_PATH_SUBTYPE, | |
{ | |
(UINT8)(END_DEVICE_PATH_LENGTH), | |
(UINT8)((END_DEVICE_PATH_LENGTH) >> 8) | |
} | |
} | |
}; | |
// | |
// Possible DER-encoded certificate file suffixes, end with NULL pointer. | |
// | |
CHAR16 *mDerPemEncodedSuffix[] = { | |
L".cer", | |
L".der", | |
L".crt", | |
L".pem", | |
NULL | |
}; | |
/** | |
This code checks if the FileSuffix is one of the possible DER/PEM-encoded certificate suffix. | |
@param[in] FileSuffix The suffix of the input certificate file | |
@retval TRUE It's a DER/PEM-encoded certificate. | |
@retval FALSE It's NOT a DER/PEM-encoded certificate. | |
**/ | |
BOOLEAN | |
IsDerPemEncodeCertificate ( | |
IN CONST CHAR16 *FileSuffix | |
) | |
{ | |
UINTN Index; | |
for (Index = 0; mDerPemEncodedSuffix[Index] != NULL; Index++) { | |
if (StrCmp (FileSuffix, mDerPemEncodedSuffix[Index]) == 0) { | |
return TRUE; | |
} | |
} | |
return FALSE; | |
} | |
/** | |
Worker function that prints an EFI_GUID into specified Buffer. | |
@param[in] Guid Pointer to GUID to print. | |
@param[in] Buffer Buffer to print Guid into. | |
@param[in] BufferSize Size of Buffer. | |
@retval Number of characters printed. | |
**/ | |
UINTN | |
GuidToString ( | |
IN EFI_GUID *Guid, | |
IN CHAR16 *Buffer, | |
IN UINTN BufferSize | |
) | |
{ | |
return UnicodeSPrint ( | |
Buffer, | |
BufferSize, | |
L"%g", | |
Guid | |
); | |
} | |
/** | |
List all cert in specified database by GUID in the page | |
for user to select and delete as needed. | |
@param[in] PrivateData Module's private data. | |
@param[in] VariableName The variable name of the vendor's signature database. | |
@param[in] VendorGuid A unique identifier for the vendor. | |
@param[in] LabelNumber Label number to insert opcodes. | |
@param[in] FormId Form ID of current page. | |
@param[in] QuestionIdBase Base question id of the signature list. | |
@retval EFI_SUCCESS Success to update the signature list page | |
@retval EFI_OUT_OF_RESOURCES Unable to allocate required resources. | |
**/ | |
EFI_STATUS | |
UpdateDeletePage ( | |
IN TLS_AUTH_CONFIG_PRIVATE_DATA *Private, | |
IN CHAR16 *VariableName, | |
IN EFI_GUID *VendorGuid, | |
IN UINT16 LabelNumber, | |
IN EFI_FORM_ID FormId, | |
IN EFI_QUESTION_ID QuestionIdBase | |
) | |
{ | |
EFI_STATUS Status; | |
UINT32 Index; | |
UINTN CertCount; | |
UINTN GuidIndex; | |
VOID *StartOpCodeHandle; | |
VOID *EndOpCodeHandle; | |
EFI_IFR_GUID_LABEL *StartLabel; | |
EFI_IFR_GUID_LABEL *EndLabel; | |
UINTN DataSize; | |
UINT8 *Data; | |
EFI_SIGNATURE_LIST *CertList; | |
EFI_SIGNATURE_DATA *Cert; | |
UINT32 ItemDataSize; | |
CHAR16 *GuidStr; | |
EFI_STRING_ID GuidID; | |
EFI_STRING_ID Help; | |
Data = NULL; | |
CertList = NULL; | |
Cert = NULL; | |
GuidStr = NULL; | |
StartOpCodeHandle = NULL; | |
EndOpCodeHandle = NULL; | |
// | |
// Initialize the container for dynamic opcodes. | |
// | |
StartOpCodeHandle = HiiAllocateOpCodeHandle (); | |
if (StartOpCodeHandle == NULL) { | |
Status = EFI_OUT_OF_RESOURCES; | |
goto ON_EXIT; | |
} | |
EndOpCodeHandle = HiiAllocateOpCodeHandle (); | |
if (EndOpCodeHandle == NULL) { | |
Status = EFI_OUT_OF_RESOURCES; | |
goto ON_EXIT; | |
} | |
// | |
// Create Hii Extend Label OpCode. | |
// | |
StartLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode ( | |
StartOpCodeHandle, | |
&gEfiIfrTianoGuid, | |
NULL, | |
sizeof (EFI_IFR_GUID_LABEL) | |
); | |
StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; | |
StartLabel->Number = LabelNumber; | |
EndLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode ( | |
EndOpCodeHandle, | |
&gEfiIfrTianoGuid, | |
NULL, | |
sizeof (EFI_IFR_GUID_LABEL) | |
); | |
EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; | |
EndLabel->Number = LABEL_END; | |
// | |
// Read Variable. | |
// | |
DataSize = 0; | |
Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data); | |
if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) { | |
goto ON_EXIT; | |
} | |
Data = (UINT8 *)AllocateZeroPool (DataSize); | |
if (Data == NULL) { | |
Status = EFI_OUT_OF_RESOURCES; | |
goto ON_EXIT; | |
} | |
Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data); | |
if (EFI_ERROR (Status)) { | |
goto ON_EXIT; | |
} | |
GuidStr = AllocateZeroPool (100); | |
if (GuidStr == NULL) { | |
Status = EFI_OUT_OF_RESOURCES; | |
goto ON_EXIT; | |
} | |
// | |
// Enumerate all data. | |
// | |
ItemDataSize = (UINT32)DataSize; | |
CertList = (EFI_SIGNATURE_LIST *)Data; | |
GuidIndex = 0; | |
while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) { | |
if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) { | |
Help = STRING_TOKEN (STR_CERT_TYPE_PCKS_GUID); | |
} else { | |
// | |
// The signature type is not supported in current implementation. | |
// | |
ItemDataSize -= CertList->SignatureListSize; | |
CertList = (EFI_SIGNATURE_LIST *)((UINT8 *)CertList + CertList->SignatureListSize); | |
continue; | |
} | |
CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize; | |
for (Index = 0; Index < CertCount; Index++) { | |
Cert = (EFI_SIGNATURE_DATA *)((UINT8 *)CertList | |
+ sizeof (EFI_SIGNATURE_LIST) | |
+ CertList->SignatureHeaderSize | |
+ Index * CertList->SignatureSize); | |
// | |
// Display GUID and help | |
// | |
GuidToString (&Cert->SignatureOwner, GuidStr, 100); | |
GuidID = HiiSetString (Private->RegisteredHandle, 0, GuidStr, NULL); | |
HiiCreateCheckBoxOpCode ( | |
StartOpCodeHandle, | |
(EFI_QUESTION_ID)(QuestionIdBase + GuidIndex++), | |
0, | |
0, | |
GuidID, | |
Help, | |
EFI_IFR_FLAG_CALLBACK, | |
0, | |
NULL | |
); | |
} | |
ItemDataSize -= CertList->SignatureListSize; | |
CertList = (EFI_SIGNATURE_LIST *)((UINT8 *)CertList + CertList->SignatureListSize); | |
} | |
ON_EXIT: | |
HiiUpdateForm ( | |
Private->RegisteredHandle, | |
&gTlsAuthConfigGuid, | |
FormId, | |
StartOpCodeHandle, | |
EndOpCodeHandle | |
); | |
if (StartOpCodeHandle != NULL) { | |
HiiFreeOpCodeHandle (StartOpCodeHandle); | |
} | |
if (EndOpCodeHandle != NULL) { | |
HiiFreeOpCodeHandle (EndOpCodeHandle); | |
} | |
if (Data != NULL) { | |
FreePool (Data); | |
} | |
if (GuidStr != NULL) { | |
FreePool (GuidStr); | |
} | |
return EFI_SUCCESS; | |
} | |
/** | |
Delete one entry from cert database. | |
@param[in] Private Module's private data. | |
@param[in] VariableName The variable name of the database. | |
@param[in] VendorGuid A unique identifier for the vendor. | |
@param[in] LabelNumber Label number to insert opcodes. | |
@param[in] FormId Form ID of current page. | |
@param[in] QuestionIdBase Base question id of the cert list. | |
@param[in] DeleteIndex Cert index to delete. | |
@retval EFI_SUCCESS Delete signature successfully. | |
@retval EFI_NOT_FOUND Can't find the signature item, | |
@retval EFI_OUT_OF_RESOURCES Could not allocate needed resources. | |
**/ | |
EFI_STATUS | |
DeleteCert ( | |
IN TLS_AUTH_CONFIG_PRIVATE_DATA *Private, | |
IN CHAR16 *VariableName, | |
IN EFI_GUID *VendorGuid, | |
IN UINT16 LabelNumber, | |
IN EFI_FORM_ID FormId, | |
IN EFI_QUESTION_ID QuestionIdBase, | |
IN UINTN DeleteIndex | |
) | |
{ | |
EFI_STATUS Status; | |
UINTN DataSize; | |
UINT8 *Data; | |
UINT8 *OldData; | |
UINT32 Attr; | |
UINT32 Index; | |
EFI_SIGNATURE_LIST *CertList; | |
EFI_SIGNATURE_LIST *NewCertList; | |
EFI_SIGNATURE_DATA *Cert; | |
UINTN CertCount; | |
UINT32 Offset; | |
BOOLEAN IsItemFound; | |
UINT32 ItemDataSize; | |
UINTN GuidIndex; | |
Data = NULL; | |
OldData = NULL; | |
CertList = NULL; | |
Cert = NULL; | |
Attr = 0; | |
// | |
// Get original signature list data. | |
// | |
DataSize = 0; | |
Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, NULL); | |
if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) { | |
goto ON_EXIT; | |
} | |
OldData = (UINT8 *)AllocateZeroPool (DataSize); | |
if (OldData == NULL) { | |
Status = EFI_OUT_OF_RESOURCES; | |
goto ON_EXIT; | |
} | |
Status = gRT->GetVariable (VariableName, VendorGuid, &Attr, &DataSize, OldData); | |
if (EFI_ERROR (Status)) { | |
goto ON_EXIT; | |
} | |
// | |
// Allocate space for new variable. | |
// | |
Data = (UINT8 *)AllocateZeroPool (DataSize); | |
if (Data == NULL) { | |
Status = EFI_OUT_OF_RESOURCES; | |
goto ON_EXIT; | |
} | |
// | |
// Enumerate all data and erasing the target item. | |
// | |
IsItemFound = FALSE; | |
ItemDataSize = (UINT32)DataSize; | |
CertList = (EFI_SIGNATURE_LIST *)OldData; | |
Offset = 0; | |
GuidIndex = 0; | |
while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) { | |
if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) { | |
// | |
// Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list. | |
// | |
CopyMem (Data + Offset, CertList, (sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize)); | |
NewCertList = (EFI_SIGNATURE_LIST *)(Data + Offset); | |
Offset += (sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize); | |
Cert = (EFI_SIGNATURE_DATA *)((UINT8 *)CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize); | |
CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize; | |
for (Index = 0; Index < CertCount; Index++) { | |
if (GuidIndex == DeleteIndex) { | |
// | |
// Find it! Skip it! | |
// | |
NewCertList->SignatureListSize -= CertList->SignatureSize; | |
IsItemFound = TRUE; | |
} else { | |
// | |
// This item doesn't match. Copy it to the Data buffer. | |
// | |
CopyMem (Data + Offset, (UINT8 *)(Cert), CertList->SignatureSize); | |
Offset += CertList->SignatureSize; | |
} | |
GuidIndex++; | |
Cert = (EFI_SIGNATURE_DATA *)((UINT8 *)Cert + CertList->SignatureSize); | |
} | |
} else { | |
// | |
// This List doesn't match. Just copy it to the Data buffer. | |
// | |
CopyMem (Data + Offset, (UINT8 *)(CertList), CertList->SignatureListSize); | |
Offset += CertList->SignatureListSize; | |
} | |
ItemDataSize -= CertList->SignatureListSize; | |
CertList = (EFI_SIGNATURE_LIST *)((UINT8 *)CertList + CertList->SignatureListSize); | |
} | |
if (!IsItemFound) { | |
// | |
// Doesn't find the signature Item! | |
// | |
Status = EFI_NOT_FOUND; | |
goto ON_EXIT; | |
} | |
// | |
// Delete the EFI_SIGNATURE_LIST header if there is no signature in the list. | |
// | |
ItemDataSize = Offset; | |
CertList = (EFI_SIGNATURE_LIST *)Data; | |
Offset = 0; | |
ZeroMem (OldData, ItemDataSize); | |
while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) { | |
CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize; | |
DEBUG ((DEBUG_INFO, " CertCount = %x\n", CertCount)); | |
if (CertCount != 0) { | |
CopyMem (OldData + Offset, (UINT8 *)(CertList), CertList->SignatureListSize); | |
Offset += CertList->SignatureListSize; | |
} | |
ItemDataSize -= CertList->SignatureListSize; | |
CertList = (EFI_SIGNATURE_LIST *)((UINT8 *)CertList + CertList->SignatureListSize); | |
} | |
DataSize = Offset; | |
Status = gRT->SetVariable ( | |
VariableName, | |
VendorGuid, | |
Attr, | |
DataSize, | |
OldData | |
); | |
if (EFI_ERROR (Status)) { | |
DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r\n", Status)); | |
goto ON_EXIT; | |
} | |
ON_EXIT: | |
if (Data != NULL) { | |
FreePool (Data); | |
} | |
if (OldData != NULL) { | |
FreePool (OldData); | |
} | |
return UpdateDeletePage ( | |
Private, | |
VariableName, | |
VendorGuid, | |
LabelNumber, | |
FormId, | |
QuestionIdBase | |
); | |
} | |
/** | |
Clean the file related resource. | |
@param[in] Private Module's private data. | |
**/ | |
VOID | |
CleanFileContext ( | |
IN TLS_AUTH_CONFIG_PRIVATE_DATA *Private | |
) | |
{ | |
if (Private->FileContext->FHandle != NULL) { | |
Private->FileContext->FHandle->Close (Private->FileContext->FHandle); | |
Private->FileContext->FHandle = NULL; | |
if (Private->FileContext->FileName != NULL) { | |
FreePool (Private->FileContext->FileName); | |
Private->FileContext->FileName = NULL; | |
} | |
} | |
} | |
/** | |
Read file content into BufferPtr, the size of the allocate buffer | |
is *FileSize plus AddtionAllocateSize. | |
@param[in] FileHandle The file to be read. | |
@param[in, out] BufferPtr Pointers to the pointer of allocated buffer. | |
@param[out] FileSize Size of input file | |
@param[in] AddtionAllocateSize Addtion size the buffer need to be allocated. | |
In case the buffer need to contain others besides the file content. | |
@retval EFI_SUCCESS The file was read into the buffer. | |
@retval EFI_INVALID_PARAMETER A parameter was invalid. | |
@retval EFI_OUT_OF_RESOURCES A memory allocation failed. | |
@retval others Unexpected error. | |
**/ | |
EFI_STATUS | |
ReadFileContent ( | |
IN EFI_FILE_HANDLE FileHandle, | |
IN OUT VOID **BufferPtr, | |
OUT UINTN *FileSize, | |
IN UINTN AddtionAllocateSize | |
) | |
{ | |
UINTN BufferSize; | |
UINT64 SourceFileSize; | |
VOID *Buffer; | |
EFI_STATUS Status; | |
if ((FileHandle == NULL) || (FileSize == NULL)) { | |
return EFI_INVALID_PARAMETER; | |
} | |
Buffer = NULL; | |
// | |
// Get the file size | |
// | |
Status = FileHandle->SetPosition (FileHandle, (UINT64)-1); | |
if (EFI_ERROR (Status)) { | |
goto ON_EXIT; | |
} | |
Status = FileHandle->GetPosition (FileHandle, &SourceFileSize); | |
if (EFI_ERROR (Status)) { | |
goto ON_EXIT; | |
} | |
Status = FileHandle->SetPosition (FileHandle, 0); | |
if (EFI_ERROR (Status)) { | |
goto ON_EXIT; | |
} | |
BufferSize = (UINTN)SourceFileSize + AddtionAllocateSize; | |
Buffer = AllocateZeroPool (BufferSize); | |
if (Buffer == NULL) { | |
return EFI_OUT_OF_RESOURCES; | |
} | |
BufferSize = (UINTN)SourceFileSize; | |
*FileSize = BufferSize; | |
Status = FileHandle->Read (FileHandle, &BufferSize, Buffer); | |
if (EFI_ERROR (Status) || (BufferSize != *FileSize)) { | |
FreePool (Buffer); | |
Buffer = NULL; | |
Status = EFI_BAD_BUFFER_SIZE; | |
goto ON_EXIT; | |
} | |
ON_EXIT: | |
*BufferPtr = Buffer; | |
return Status; | |
} | |
/** | |
This function converts an input device structure to a Unicode string. | |
@param[in] DevPath A pointer to the device path structure. | |
@return A new allocated Unicode string that represents the device path. | |
**/ | |
CHAR16 * | |
EFIAPI | |
DevicePathToStr ( | |
IN EFI_DEVICE_PATH_PROTOCOL *DevPath | |
) | |
{ | |
return ConvertDevicePathToText ( | |
DevPath, | |
FALSE, | |
TRUE | |
); | |
} | |
/** | |
Extract filename from device path. The returned buffer is allocated using AllocateCopyPool. | |
The caller is responsible for freeing the allocated buffer using FreePool(). If return NULL | |
means not enough memory resource. | |
@param DevicePath Device path. | |
@retval NULL Not enough memory resource for AllocateCopyPool. | |
@retval Other A new allocated string that represents the file name. | |
**/ | |
CHAR16 * | |
ExtractFileNameFromDevicePath ( | |
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
) | |
{ | |
CHAR16 *String; | |
CHAR16 *MatchString; | |
CHAR16 *LastMatch; | |
CHAR16 *FileName; | |
UINTN Length; | |
ASSERT (DevicePath != NULL); | |
String = DevicePathToStr (DevicePath); | |
MatchString = String; | |
LastMatch = String; | |
FileName = NULL; | |
while (MatchString != NULL) { | |
LastMatch = MatchString + 1; | |
MatchString = StrStr (LastMatch, L"\\"); | |
} | |
Length = StrLen (LastMatch); | |
FileName = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), LastMatch); | |
if (FileName != NULL) { | |
*(FileName + Length) = 0; | |
} | |
FreePool (String); | |
return FileName; | |
} | |
/** | |
Enroll a new X509 certificate into Variable. | |
@param[in] PrivateData The module's private data. | |
@param[in] VariableName Variable name of CA database. | |
@retval EFI_SUCCESS New X509 is enrolled successfully. | |
@retval EFI_OUT_OF_RESOURCES Could not allocate needed resources. | |
**/ | |
EFI_STATUS | |
EnrollX509toVariable ( | |
IN TLS_AUTH_CONFIG_PRIVATE_DATA *Private, | |
IN CHAR16 *VariableName | |
) | |
{ | |
EFI_STATUS Status; | |
UINTN X509DataSize; | |
VOID *X509Data; | |
EFI_SIGNATURE_LIST *CACert; | |
EFI_SIGNATURE_DATA *CACertData; | |
VOID *Data; | |
UINTN DataSize; | |
UINTN SigDataSize; | |
UINT32 Attr; | |
X509DataSize = 0; | |
SigDataSize = 0; | |
DataSize = 0; | |
X509Data = NULL; | |
CACert = NULL; | |
CACertData = NULL; | |
Data = NULL; | |
Attr = 0; | |
Status = ReadFileContent ( | |
Private->FileContext->FHandle, | |
&X509Data, | |
&X509DataSize, | |
0 | |
); | |
if (EFI_ERROR (Status)) { | |
goto ON_EXIT; | |
} | |
ASSERT (X509Data != NULL); | |
SigDataSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + X509DataSize; | |
Data = AllocateZeroPool (SigDataSize); | |
if (Data == NULL) { | |
Status = EFI_OUT_OF_RESOURCES; | |
goto ON_EXIT; | |
} | |
// | |
// Fill Certificate Database parameters. | |
// | |
CACert = (EFI_SIGNATURE_LIST *)Data; | |
CACert->SignatureListSize = (UINT32)SigDataSize; | |
CACert->SignatureHeaderSize = 0; | |
CACert->SignatureSize = (UINT32)(sizeof (EFI_SIGNATURE_DATA) - 1 + X509DataSize); | |
CopyGuid (&CACert->SignatureType, &gEfiCertX509Guid); | |
CACertData = (EFI_SIGNATURE_DATA *)((UINT8 *)CACert + sizeof (EFI_SIGNATURE_LIST)); | |
CopyGuid (&CACertData->SignatureOwner, Private->CertGuid); | |
CopyMem ((UINT8 *)(CACertData->SignatureData), X509Data, X509DataSize); | |
// | |
// Check if the signature database entry already exists. If it does, use the | |
// EFI_VARIABLE_APPEND_WRITE attribute to append the new signature data to | |
// the original variable, plus preserve the original variable attributes. | |
// | |
Status = gRT->GetVariable ( | |
VariableName, | |
&gEfiTlsCaCertificateGuid, | |
&Attr, | |
&DataSize, | |
NULL | |
); | |
if (Status == EFI_BUFFER_TOO_SMALL) { | |
Attr |= EFI_VARIABLE_APPEND_WRITE; | |
} else if (Status == EFI_NOT_FOUND) { | |
Attr = TLS_AUTH_CONFIG_VAR_BASE_ATTR; | |
} else { | |
goto ON_EXIT; | |
} | |
Status = gRT->SetVariable ( | |
VariableName, | |
&gEfiTlsCaCertificateGuid, | |
Attr, | |
SigDataSize, | |
Data | |
); | |
if (EFI_ERROR (Status)) { | |
goto ON_EXIT; | |
} | |
ON_EXIT: | |
CleanFileContext (Private); | |
if (Private->CertGuid != NULL) { | |
FreePool (Private->CertGuid); | |
Private->CertGuid = NULL; | |
} | |
if (Data != NULL) { | |
FreePool (Data); | |
} | |
if (X509Data != NULL) { | |
FreePool (X509Data); | |
} | |
return Status; | |
} | |
/** | |
Enroll Cert into TlsCaCertificate. The GUID will be Private->CertGuid. | |
@param[in] PrivateData The module's private data. | |
@param[in] VariableName Variable name of signature database. | |
@retval EFI_SUCCESS New Cert enrolled successfully. | |
@retval EFI_INVALID_PARAMETER The parameter is invalid. | |
@retval EFI_UNSUPPORTED The Cert file is unsupported type. | |
@retval others Fail to enroll Cert data. | |
**/ | |
EFI_STATUS | |
EnrollCertDatabase ( | |
IN TLS_AUTH_CONFIG_PRIVATE_DATA *Private, | |
IN CHAR16 *VariableName | |
) | |
{ | |
UINT16 *FilePostFix; | |
UINTN NameLength; | |
if ((Private->FileContext->FileName == NULL) || (Private->FileContext->FHandle == NULL) || (Private->CertGuid == NULL)) { | |
return EFI_INVALID_PARAMETER; | |
} | |
// | |
// Parse the file's postfix. | |
// | |
NameLength = StrLen (Private->FileContext->FileName); | |
if (NameLength <= 4) { | |
return EFI_INVALID_PARAMETER; | |
} | |
FilePostFix = Private->FileContext->FileName + NameLength - 4; | |
if (IsDerPemEncodeCertificate (FilePostFix)) { | |
// | |
// Supports DER-encoded X509 certificate. | |
// | |
return EnrollX509toVariable (Private, VariableName); | |
} | |
return EFI_UNSUPPORTED; | |
} | |
/** | |
Refresh the global UpdateData structure. | |
**/ | |
VOID | |
RefreshUpdateData ( | |
VOID | |
) | |
{ | |
// | |
// Free current updated date | |
// | |
if (mStartOpCodeHandle != NULL) { | |
HiiFreeOpCodeHandle (mStartOpCodeHandle); | |
} | |
// | |
// Create new OpCode Handle | |
// | |
mStartOpCodeHandle = HiiAllocateOpCodeHandle (); | |
// | |
// Create Hii Extend Label OpCode as the start opcode | |
// | |
mStartLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode ( | |
mStartOpCodeHandle, | |
&gEfiIfrTianoGuid, | |
NULL, | |
sizeof (EFI_IFR_GUID_LABEL) | |
); | |
mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; | |
} | |
/** | |
Clean up the dynamic opcode at label and form specified by both LabelId. | |
@param[in] LabelId It is both the Form ID and Label ID for opcode deletion. | |
@param[in] PrivateData Module private data. | |
**/ | |
VOID | |
CleanUpPage ( | |
IN UINT16 LabelId, | |
IN TLS_AUTH_CONFIG_PRIVATE_DATA *PrivateData | |
) | |
{ | |
RefreshUpdateData (); | |
// | |
// Remove all op-codes from dynamic page | |
// | |
mStartLabel->Number = LabelId; | |
HiiUpdateForm ( | |
PrivateData->RegisteredHandle, | |
&gTlsAuthConfigGuid, | |
LabelId, | |
mStartOpCodeHandle, // Label LabelId | |
mEndOpCodeHandle // LABEL_END | |
); | |
} | |
/** | |
Update the form base on the selected file. | |
@param FilePath Point to the file path. | |
@param FormId The form need to display. | |
@retval TRUE Exit caller function. | |
@retval FALSE Not exit caller function. | |
**/ | |
BOOLEAN | |
UpdatePage ( | |
IN EFI_DEVICE_PATH_PROTOCOL *FilePath, | |
IN EFI_FORM_ID FormId | |
) | |
{ | |
CHAR16 *FileName; | |
EFI_STRING_ID StringToken; | |
FileName = NULL; | |
if (FilePath != NULL) { | |
FileName = ExtractFileNameFromDevicePath (FilePath); | |
} | |
if (FileName == NULL) { | |
// | |
// FileName = NULL has two case: | |
// 1. FilePath == NULL, not select file. | |
// 2. FilePath != NULL, but ExtractFileNameFromDevicePath return NULL not enough memory resource. | |
// In these two case, no need to update the form, and exit the caller function. | |
// | |
return TRUE; | |
} | |
StringToken = HiiSetString (mTlsAuthPrivateData->RegisteredHandle, 0, FileName, NULL); | |
mTlsAuthPrivateData->FileContext->FileName = FileName; | |
EfiOpenFileByDevicePath ( | |
&FilePath, | |
&mTlsAuthPrivateData->FileContext->FHandle, | |
EFI_FILE_MODE_READ, | |
0 | |
); | |
// | |
// Create Subtitle op-code for the display string of the option. | |
// | |
RefreshUpdateData (); | |
mStartLabel->Number = FormId; | |
HiiCreateSubTitleOpCode ( | |
mStartOpCodeHandle, | |
StringToken, | |
0, | |
0, | |
0 | |
); | |
HiiUpdateForm ( | |
mTlsAuthPrivateData->RegisteredHandle, | |
&gTlsAuthConfigGuid, | |
FormId, | |
mStartOpCodeHandle, /// Label FormId | |
mEndOpCodeHandle /// LABEL_END | |
); | |
return TRUE; | |
} | |
/** | |
Update the form base on the input file path info. | |
@param FilePath Point to the file path. | |
@retval TRUE Exit caller function. | |
@retval FALSE Not exit caller function. | |
**/ | |
BOOLEAN | |
EFIAPI | |
UpdateCAFromFile ( | |
IN EFI_DEVICE_PATH_PROTOCOL *FilePath | |
) | |
{ | |
return UpdatePage (FilePath, TLS_AUTH_CONFIG_FORMID4_FORM); | |
} | |
/** | |
Unload the configuration form, this includes: delete all the configuration | |
entries, uninstall the form callback protocol, and free the resources used. | |
@param[in] Private Pointer to the driver private data. | |
@retval EFI_SUCCESS The configuration form is unloaded. | |
@retval Others Failed to unload the form. | |
**/ | |
EFI_STATUS | |
TlsAuthConfigFormUnload ( | |
IN TLS_AUTH_CONFIG_PRIVATE_DATA *Private | |
) | |
{ | |
if (Private->DriverHandle != NULL) { | |
// | |
// Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL | |
// | |
gBS->UninstallMultipleProtocolInterfaces ( | |
Private->DriverHandle, | |
&gEfiDevicePathProtocolGuid, | |
&mTlsAuthConfigHiiVendorDevicePath, | |
&gEfiHiiConfigAccessProtocolGuid, | |
&Private->ConfigAccess, | |
NULL | |
); | |
Private->DriverHandle = NULL; | |
} | |
if (Private->RegisteredHandle != NULL) { | |
// | |
// Remove HII package list | |
// | |
HiiRemovePackages (Private->RegisteredHandle); | |
Private->RegisteredHandle = NULL; | |
} | |
if (Private->CertGuid != NULL) { | |
FreePool (Private->CertGuid); | |
} | |
if (Private->FileContext != NULL) { | |
FreePool (Private->FileContext); | |
} | |
FreePool (Private); | |
if (mStartOpCodeHandle != NULL) { | |
HiiFreeOpCodeHandle (mStartOpCodeHandle); | |
} | |
if (mEndOpCodeHandle != NULL) { | |
HiiFreeOpCodeHandle (mEndOpCodeHandle); | |
} | |
return EFI_SUCCESS; | |
} | |
/** | |
Initialize the configuration form. | |
@param[in] Private Pointer to the driver private data. | |
@retval EFI_SUCCESS The configuration form is initialized. | |
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory. | |
**/ | |
EFI_STATUS | |
TlsAuthConfigFormInit ( | |
IN TLS_AUTH_CONFIG_PRIVATE_DATA *Private | |
) | |
{ | |
EFI_STATUS Status; | |
Private->Signature = TLS_AUTH_CONFIG_PRIVATE_DATA_SIGNATURE; | |
Private->ConfigAccess.ExtractConfig = TlsAuthConfigAccessExtractConfig; | |
Private->ConfigAccess.RouteConfig = TlsAuthConfigAccessRouteConfig; | |
Private->ConfigAccess.Callback = TlsAuthConfigAccessCallback; | |
// | |
// Install Device Path Protocol and Config Access protocol to driver handle. | |
// | |
Status = gBS->InstallMultipleProtocolInterfaces ( | |
&Private->DriverHandle, | |
&gEfiDevicePathProtocolGuid, | |
&mTlsAuthConfigHiiVendorDevicePath, | |
&gEfiHiiConfigAccessProtocolGuid, | |
&Private->ConfigAccess, | |
NULL | |
); | |
if (EFI_ERROR (Status)) { | |
return Status; | |
} | |
// | |
// Publish our HII data. | |
// | |
Private->RegisteredHandle = HiiAddPackages ( | |
&gTlsAuthConfigGuid, | |
Private->DriverHandle, | |
TlsAuthConfigDxeStrings, | |
TlsAuthConfigVfrBin, | |
NULL | |
); | |
if (Private->RegisteredHandle == NULL) { | |
Status = EFI_OUT_OF_RESOURCES; | |
goto Error; | |
} | |
Private->FileContext = AllocateZeroPool (sizeof (TLS_AUTH_CONFIG_FILE_CONTEXT)); | |
if (Private->FileContext == NULL) { | |
Status = EFI_OUT_OF_RESOURCES; | |
goto Error; | |
} | |
// | |
// Init OpCode Handle and Allocate space for creation of Buffer | |
// | |
mStartOpCodeHandle = HiiAllocateOpCodeHandle (); | |
if (mStartOpCodeHandle == NULL) { | |
Status = EFI_OUT_OF_RESOURCES; | |
goto Error; | |
} | |
mEndOpCodeHandle = HiiAllocateOpCodeHandle (); | |
if (mEndOpCodeHandle == NULL) { | |
Status = EFI_OUT_OF_RESOURCES; | |
goto Error; | |
} | |
// | |
// Create Hii Extend Label OpCode as the start opcode | |
// | |
mStartLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode ( | |
mStartOpCodeHandle, | |
&gEfiIfrTianoGuid, | |
NULL, | |
sizeof (EFI_IFR_GUID_LABEL) | |
); | |
mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; | |
// | |
// Create Hii Extend Label OpCode as the end opcode | |
// | |
mEndLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode ( | |
mEndOpCodeHandle, | |
&gEfiIfrTianoGuid, | |
NULL, | |
sizeof (EFI_IFR_GUID_LABEL) | |
); | |
mEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; | |
mEndLabel->Number = LABEL_END; | |
return EFI_SUCCESS; | |
Error: | |
TlsAuthConfigFormUnload (Private); | |
return Status; | |
} | |
/** | |
This function allows the caller to request the current | |
configuration for one or more named elements. The resulting | |
string is in <ConfigAltResp> format. Any and all alternative | |
configuration strings shall also be appended to the end of the | |
current configuration string. If they are, they must appear | |
after the current configuration. They must contain the same | |
routing (GUID, NAME, PATH) as the current configuration string. | |
They must have an additional description indicating the type of | |
alternative configuration the string represents, | |
"ALTCFG=<StringToken>". That <StringToken> (when | |
converted from Hex UNICODE to binary) is a reference to a | |
string in the associated string pack. | |
@param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. | |
@param Request A null-terminated Unicode string in | |
<ConfigRequest> format. Note that this | |
includes the routing information as well as | |
the configurable name / value pairs. It is | |
invalid for this string to be in | |
<MultiConfigRequest> format. | |
If a NULL is passed in for the Request field, | |
all of the settings being abstracted by this function | |
will be returned in the Results field. In addition, | |
if a ConfigHdr is passed in with no request elements, | |
all of the settings being abstracted for that particular | |
ConfigHdr reference will be returned in the Results Field. | |
@param Progress On return, points to a character in the | |
Request string. Points to the string's null | |
terminator if request was successful. Points | |
to the most recent "&" before the first | |
failing name / value pair (or the beginning | |
of the string if the failure is in the first | |
name / value pair) if the request was not | |
successful. | |
@param Results A null-terminated Unicode string in | |
<MultiConfigAltResp> format which has all values | |
filled in for the names in the Request string. | |
String to be allocated by the called function. | |
@retval EFI_SUCCESS The Results string is filled with the | |
values corresponding to all requested | |
names. | |
@retval EFI_OUT_OF_RESOURCES Not enough memory to store the | |
parts of the results that must be | |
stored awaiting possible future | |
protocols. | |
@retval EFI_NOT_FOUND Routing data doesn't match any | |
known driver. Progress set to the | |
first character in the routing header. | |
Note: There is no requirement that the | |
driver validate the routing data. It | |
must skip the <ConfigHdr> in order to | |
process the names. | |
@retval EFI_INVALID_PARAMETER Illegal syntax. Progress set | |
to most recent "&" before the | |
error or the beginning of the | |
string. | |
@retval EFI_INVALID_PARAMETER Unknown name. Progress points | |
to the & before the name in | |
question. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
TlsAuthConfigAccessExtractConfig ( | |
IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, | |
IN CONST EFI_STRING Request, | |
OUT EFI_STRING *Progress, | |
OUT EFI_STRING *Results | |
) | |
{ | |
EFI_STATUS Status; | |
UINTN BufferSize; | |
UINTN Size; | |
EFI_STRING ConfigRequest; | |
EFI_STRING ConfigRequestHdr; | |
TLS_AUTH_CONFIG_PRIVATE_DATA *Private; | |
BOOLEAN AllocatedRequest; | |
if ((Progress == NULL) || (Results == NULL)) { | |
return EFI_INVALID_PARAMETER; | |
} | |
AllocatedRequest = FALSE; | |
ConfigRequestHdr = NULL; | |
ConfigRequest = NULL; | |
Size = 0; | |
Private = TLS_AUTH_CONFIG_PRIVATE_FROM_THIS (This); | |
BufferSize = sizeof (TLS_AUTH_CONFIG_IFR_NVDATA); | |
ZeroMem (&Private->TlsAuthConfigNvData, BufferSize); | |
*Progress = Request; | |
if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gTlsAuthConfigGuid, mTlsAuthConfigStorageName)) { | |
return EFI_NOT_FOUND; | |
} | |
ConfigRequest = Request; | |
if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) { | |
// | |
// Request is set to NULL or OFFSET is NULL, construct full request string. | |
// | |
// Allocate and fill a buffer large enough to hold the <ConfigHdr> template | |
// followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator | |
// | |
ConfigRequestHdr = HiiConstructConfigHdr (&gTlsAuthConfigGuid, mTlsAuthConfigStorageName, Private->DriverHandle); | |
Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16); | |
ConfigRequest = AllocateZeroPool (Size); | |
ASSERT (ConfigRequest != NULL); | |
AllocatedRequest = TRUE; | |
UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize); | |
FreePool (ConfigRequestHdr); | |
ConfigRequestHdr = NULL; | |
} | |
Status = gHiiConfigRouting->BlockToConfig ( | |
gHiiConfigRouting, | |
ConfigRequest, | |
(UINT8 *)&Private->TlsAuthConfigNvData, | |
BufferSize, | |
Results, | |
Progress | |
); | |
// | |
// Free the allocated config request string. | |
// | |
if (AllocatedRequest) { | |
FreePool (ConfigRequest); | |
} | |
// | |
// Set Progress string to the original request string. | |
// | |
if (Request == NULL) { | |
*Progress = NULL; | |
} else if (StrStr (Request, L"OFFSET") == NULL) { | |
*Progress = Request + StrLen (Request); | |
} | |
return Status; | |
} | |
/** | |
This function applies changes in a driver's configuration. | |
Input is a Configuration, which has the routing data for this | |
driver followed by name / value configuration pairs. The driver | |
must apply those pairs to its configurable storage. If the | |
driver's configuration is stored in a linear block of data | |
and the driver's name / value pairs are in <BlockConfig> | |
format, it may use the ConfigToBlock helper function (above) to | |
simplify the job. | |
@param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. | |
@param Configuration A null-terminated Unicode string in | |
<ConfigString> format. | |
@param Progress A pointer to a string filled in with the | |
offset of the most recent '&' before the | |
first failing name / value pair (or the | |
beginning of the string if the failure | |
is in the first name / value pair) or | |
the terminating NULL if all was | |
successful. | |
@retval EFI_SUCCESS The results have been distributed or are | |
awaiting distribution. | |
@retval EFI_OUT_OF_RESOURCES Not enough memory to store the | |
parts of the results that must be | |
stored awaiting possible future | |
protocols. | |
@retval EFI_INVALID_PARAMETERS Passing in a NULL for the | |
Results parameter would result | |
in this type of error. | |
@retval EFI_NOT_FOUND Target for the specified routing data | |
was not found | |
**/ | |
EFI_STATUS | |
EFIAPI | |
TlsAuthConfigAccessRouteConfig ( | |
IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, | |
IN CONST EFI_STRING Configuration, | |
OUT EFI_STRING *Progress | |
) | |
{ | |
EFI_STATUS Status; | |
UINTN BufferSize; | |
TLS_AUTH_CONFIG_PRIVATE_DATA *Private; | |
if (Progress == NULL) { | |
return EFI_INVALID_PARAMETER; | |
} | |
*Progress = Configuration; | |
if (Configuration == NULL) { | |
return EFI_INVALID_PARAMETER; | |
} | |
// | |
// Check routing data in <ConfigHdr>. | |
// Note: there is no name for Name/Value storage, only GUID will be checked | |
// | |
if (!HiiIsConfigHdrMatch (Configuration, &gTlsAuthConfigGuid, mTlsAuthConfigStorageName)) { | |
return EFI_NOT_FOUND; | |
} | |
Private = TLS_AUTH_CONFIG_PRIVATE_FROM_THIS (This); | |
BufferSize = sizeof (TLS_AUTH_CONFIG_IFR_NVDATA); | |
ZeroMem (&Private->TlsAuthConfigNvData, BufferSize); | |
Status = gHiiConfigRouting->ConfigToBlock ( | |
gHiiConfigRouting, | |
Configuration, | |
(UINT8 *)&Private->TlsAuthConfigNvData, | |
&BufferSize, | |
Progress | |
); | |
if (EFI_ERROR (Status)) { | |
return Status; | |
} | |
return Status; | |
} | |
/** | |
This function is called to provide results data to the driver. | |
This data consists of a unique key that is used to identify | |
which data is either being passed back or being asked for. | |
@param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. | |
@param Action Specifies the type of action taken by the browser. | |
@param QuestionId A unique value which is sent to the original | |
exporting driver so that it can identify the type | |
of data to expect. The format of the data tends to | |
vary based on the opcode that generated the callback. | |
@param Type The type of value for the question. | |
@param Value A pointer to the data being sent to the original | |
exporting driver. | |
@param ActionRequest On return, points to the action requested by the | |
callback function. | |
@retval EFI_SUCCESS The callback successfully handled the action. | |
@retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the | |
variable and its data. | |
@retval EFI_DEVICE_ERROR The variable could not be saved. | |
@retval EFI_UNSUPPORTED The specified Action is not supported by the | |
callback. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
TlsAuthConfigAccessCallback ( | |
IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, | |
IN EFI_BROWSER_ACTION Action, | |
IN EFI_QUESTION_ID QuestionId, | |
IN UINT8 Type, | |
IN OUT EFI_IFR_TYPE_VALUE *Value, | |
OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest | |
) | |
{ | |
EFI_STATUS Status; | |
RETURN_STATUS RStatus; | |
TLS_AUTH_CONFIG_PRIVATE_DATA *Private; | |
UINTN BufferSize; | |
TLS_AUTH_CONFIG_IFR_NVDATA *IfrNvData; | |
UINT16 LabelId; | |
EFI_DEVICE_PATH_PROTOCOL *File; | |
EFI_HII_POPUP_PROTOCOL *HiiPopUp; | |
EFI_HII_POPUP_SELECTION PopUpSelect; | |
Status = EFI_SUCCESS; | |
File = NULL; | |
if ((This == NULL) || (Value == NULL) || (ActionRequest == NULL)) { | |
return EFI_INVALID_PARAMETER; | |
} | |
Private = TLS_AUTH_CONFIG_PRIVATE_FROM_THIS (This); | |
mTlsAuthPrivateData = Private; | |
Status = gBS->LocateProtocol (&gEfiHiiPopupProtocolGuid, NULL, (VOID **)&HiiPopUp); | |
if (EFI_ERROR (Status)) { | |
DEBUG ((DEBUG_ERROR, "Can't find Form PopUp protocol. Exit (%r)\n", Status)); | |
return Status; | |
} | |
// | |
// Retrieve uncommitted data from Browser | |
// | |
BufferSize = sizeof (TLS_AUTH_CONFIG_IFR_NVDATA); | |
IfrNvData = AllocateZeroPool (BufferSize); | |
if (IfrNvData == NULL) { | |
return EFI_OUT_OF_RESOURCES; | |
} | |
HiiGetBrowserData (&gTlsAuthConfigGuid, mTlsAuthConfigStorageName, BufferSize, (UINT8 *)IfrNvData); | |
if ((Action != EFI_BROWSER_ACTION_CHANGED) && | |
(Action != EFI_BROWSER_ACTION_CHANGING) && | |
(Action != EFI_BROWSER_ACTION_FORM_CLOSE)) | |
{ | |
Status = EFI_UNSUPPORTED; | |
goto EXIT; | |
} | |
if (Action == EFI_BROWSER_ACTION_CHANGING) { | |
switch (QuestionId) { | |
case KEY_TLS_AUTH_CONFIG_CLIENT_CERT: | |
case KEY_TLS_AUTH_CONFIG_SERVER_CA: | |
// | |
// Clear Cert GUID. | |
// | |
ZeroMem (IfrNvData->CertGuid, sizeof (IfrNvData->CertGuid)); | |
if (Private->CertGuid == NULL) { | |
Private->CertGuid = (EFI_GUID *)AllocateZeroPool (sizeof (EFI_GUID)); | |
if (Private->CertGuid == NULL) { | |
return EFI_OUT_OF_RESOURCES; | |
} | |
} | |
if (QuestionId == KEY_TLS_AUTH_CONFIG_CLIENT_CERT) { | |
LabelId = TLS_AUTH_CONFIG_FORMID3_FORM; | |
} else { | |
LabelId = TLS_AUTH_CONFIG_FORMID4_FORM; | |
} | |
// | |
// Refresh selected file. | |
// | |
CleanUpPage (LabelId, Private); | |
break; | |
case KEY_TLS_AUTH_CONFIG_ENROLL_CERT_FROM_FILE: | |
// | |
// If the file is already opened, clean the file related resource first. | |
// | |
CleanFileContext (Private); | |
ChooseFile (NULL, NULL, UpdateCAFromFile, &File); | |
break; | |
case KEY_TLS_AUTH_CONFIG_VALUE_SAVE_AND_EXIT: | |
Status = EnrollCertDatabase (Private, EFI_TLS_CA_CERTIFICATE_VARIABLE); | |
if (EFI_ERROR (Status)) { | |
CleanFileContext (Private); | |
HiiPopUp->CreatePopup ( | |
HiiPopUp, | |
EfiHiiPopupStyleError, | |
EfiHiiPopupTypeOk, | |
Private->RegisteredHandle, | |
STRING_TOKEN (STR_TLS_AUTH_ENROLL_CERT_FAILURE), | |
&PopUpSelect | |
); | |
} | |
break; | |
case KEY_TLS_AUTH_CONFIG_VALUE_NO_SAVE_AND_EXIT: | |
CleanFileContext (Private); | |
if (Private->CertGuid != NULL) { | |
FreePool (Private->CertGuid); | |
Private->CertGuid = NULL; | |
} | |
break; | |
case KEY_TLS_AUTH_CONFIG_DELETE_CERT: | |
UpdateDeletePage ( | |
Private, | |
EFI_TLS_CA_CERTIFICATE_VARIABLE, | |
&gEfiTlsCaCertificateGuid, | |
LABEL_CA_DELETE, | |
TLS_AUTH_CONFIG_FORMID5_FORM, | |
OPTION_DEL_CA_ESTION_ID | |
); | |
break; | |
default: | |
if ((QuestionId >= OPTION_DEL_CA_ESTION_ID) && | |
(QuestionId < (OPTION_DEL_CA_ESTION_ID + OPTION_CONFIG_RANGE))) | |
{ | |
DeleteCert ( | |
Private, | |
EFI_TLS_CA_CERTIFICATE_VARIABLE, | |
&gEfiTlsCaCertificateGuid, | |
LABEL_CA_DELETE, | |
TLS_AUTH_CONFIG_FORMID5_FORM, | |
OPTION_DEL_CA_ESTION_ID, | |
QuestionId - OPTION_DEL_CA_ESTION_ID | |
); | |
} | |
break; | |
} | |
} else if (Action == EFI_BROWSER_ACTION_CHANGED) { | |
switch (QuestionId) { | |
case KEY_TLS_AUTH_CONFIG_CERT_GUID: | |
ASSERT (Private->CertGuid != NULL); | |
RStatus = StrToGuid ( | |
IfrNvData->CertGuid, | |
Private->CertGuid | |
); | |
if (RETURN_ERROR (RStatus) || (IfrNvData->CertGuid[GUID_STRING_LENGTH] != L'\0')) { | |
Status = EFI_INVALID_PARAMETER; | |
break; | |
} | |
*ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY; | |
break; | |
default: | |
break; | |
} | |
} else if (Action == EFI_BROWSER_ACTION_FORM_CLOSE) { | |
CleanFileContext (Private); | |
} | |
EXIT: | |
if (!EFI_ERROR (Status)) { | |
BufferSize = sizeof (TLS_AUTH_CONFIG_IFR_NVDATA); | |
HiiSetBrowserData (&gTlsAuthConfigGuid, mTlsAuthConfigStorageName, BufferSize, (UINT8 *)IfrNvData, NULL); | |
} | |
FreePool (IfrNvData); | |
if (File != NULL) { | |
FreePool (File); | |
File = NULL; | |
} | |
return EFI_SUCCESS; | |
} |