/** @file | |
The Miscellaneous Routines for TlsAuthConfigDxe driver. | |
Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR> | |
This program and the accompanying materials | |
are licensed and made available under the terms and conditions of the BSD License | |
which accompanies this distribution. The full text of the license may be found at | |
http://opensource.org/licenses/bsd-license.php | |
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
**/ | |
#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 siganture 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 will open a file or directory referenced by DevicePath. | |
This function opens a file with the open mode according to the file path. The | |
Attributes is valid only for EFI_FILE_MODE_CREATE. | |
@param[in, out] FilePath On input, the device path to the file. | |
On output, the remaining device path. | |
@param[out] FileHandle Pointer to the file handle. | |
@param[in] OpenMode The mode to open the file with. | |
@param[in] Attributes The file's file attributes. | |
@retval EFI_SUCCESS The information was set. | |
@retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. | |
@retval EFI_UNSUPPORTED Could not open the file path. | |
@retval EFI_NOT_FOUND The specified file could not be found on the | |
device or the file system could not be found on | |
the device. | |
@retval EFI_NO_MEDIA The device has no medium. | |
@retval EFI_MEDIA_CHANGED The device has a different medium in it or the | |
medium is no longer supported. | |
@retval EFI_DEVICE_ERROR The device reported an error. | |
@retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. | |
@retval EFI_WRITE_PROTECTED The file or medium is write protected. | |
@retval EFI_ACCESS_DENIED The file was opened read only. | |
@retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the | |
file. | |
@retval EFI_VOLUME_FULL The volume is full. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
OpenFileByDevicePath ( | |
IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath, | |
OUT EFI_FILE_HANDLE *FileHandle, | |
IN UINT64 OpenMode, | |
IN UINT64 Attributes | |
) | |
{ | |
EFI_STATUS Status; | |
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *EfiSimpleFileSystemProtocol; | |
EFI_FILE_PROTOCOL *Handle1; | |
EFI_FILE_PROTOCOL *Handle2; | |
EFI_HANDLE DeviceHandle; | |
if ((FilePath == NULL || FileHandle == NULL)) { | |
return EFI_INVALID_PARAMETER; | |
} | |
Status = gBS->LocateDevicePath ( | |
&gEfiSimpleFileSystemProtocolGuid, | |
FilePath, | |
&DeviceHandle | |
); | |
if (EFI_ERROR (Status)) { | |
return Status; | |
} | |
Status = gBS->OpenProtocol( | |
DeviceHandle, | |
&gEfiSimpleFileSystemProtocolGuid, | |
(VOID**)&EfiSimpleFileSystemProtocol, | |
gImageHandle, | |
NULL, | |
EFI_OPEN_PROTOCOL_GET_PROTOCOL | |
); | |
if (EFI_ERROR (Status)) { | |
return Status; | |
} | |
Status = EfiSimpleFileSystemProtocol->OpenVolume(EfiSimpleFileSystemProtocol, &Handle1); | |
if (EFI_ERROR (Status)) { | |
FileHandle = NULL; | |
return Status; | |
} | |
// | |
// go down directories one node at a time. | |
// | |
while (!IsDevicePathEnd (*FilePath)) { | |
// | |
// For file system access each node should be a file path component | |
// | |
if (DevicePathType (*FilePath) != MEDIA_DEVICE_PATH || | |
DevicePathSubType (*FilePath) != MEDIA_FILEPATH_DP | |
) { | |
FileHandle = NULL; | |
return (EFI_INVALID_PARAMETER); | |
} | |
// | |
// Open this file path node | |
// | |
Handle2 = Handle1; | |
Handle1 = NULL; | |
// | |
// Try to test opening an existing file | |
// | |
Status = Handle2->Open ( | |
Handle2, | |
&Handle1, | |
((FILEPATH_DEVICE_PATH*)*FilePath)->PathName, | |
OpenMode &~EFI_FILE_MODE_CREATE, | |
0 | |
); | |
// | |
// see if the error was that it needs to be created | |
// | |
if ((EFI_ERROR (Status)) && (OpenMode != (OpenMode &~EFI_FILE_MODE_CREATE))) { | |
Status = Handle2->Open ( | |
Handle2, | |
&Handle1, | |
((FILEPATH_DEVICE_PATH*)*FilePath)->PathName, | |
OpenMode, | |
Attributes | |
); | |
} | |
// | |
// Close the last node | |
// | |
Handle2->Close (Handle2); | |
if (EFI_ERROR(Status)) { | |
return (Status); | |
} | |
// | |
// Get the next node | |
// | |
*FilePath = NextDevicePathNode (*FilePath); | |
} | |
// | |
// This is a weak spot since if the undefined SHELL_FILE_HANDLE format changes this must change also! | |
// | |
*FileHandle = (VOID*)Handle1; | |
return EFI_SUCCESS; | |
} | |
/** | |
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 resourece 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; | |
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 signature database entry has been already existed. | |
// If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the | |
// new signature data to original variable | |
// | |
Attr = TLS_AUTH_CONFIG_VAR_BASE_ATTR; | |
Status = gRT->GetVariable( | |
VariableName, | |
&gEfiTlsCaCertificateGuid, | |
NULL, | |
&DataSize, | |
NULL | |
); | |
if (Status == EFI_BUFFER_TOO_SMALL) { | |
Attr |= EFI_VARIABLE_APPEND_WRITE; | |
} else if (Status != EFI_NOT_FOUND) { | |
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; | |
OpenFileByDevicePath ( | |
&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 | |
beginn ing 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_INPUT_KEY Key; | |
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; | |
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; | |
// | |
// 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); | |
CreatePopUp ( | |
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, | |
&Key, | |
L"ERROR: Enroll Cert Failure!", | |
NULL | |
); | |
} | |
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; | |
} | |