| /** @file |
| The Miscellaneous Routines for TlsAuthConfigDxe driver. |
| |
| Copyright (c) 2016, 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 |
| ); |
| } |
| |
| /** |
| Convert a String to Guid Value. |
| |
| @param[in] Str Specifies the String to be converted. |
| @param[in] StrLen Number of Unicode Characters of String (exclusive \0) |
| @param[out] Guid Return the result Guid value. |
| |
| @retval EFI_SUCCESS The operation is finished successfully. |
| @retval EFI_NOT_FOUND Invalid string. |
| |
| **/ |
| EFI_STATUS |
| StringToGuid ( |
| IN CHAR16 *Str, |
| IN UINTN StrLen, |
| OUT EFI_GUID *Guid |
| ) |
| { |
| CHAR16 *PtrBuffer; |
| CHAR16 *PtrPosition; |
| UINT16 *Buffer; |
| UINTN Data; |
| UINTN Index; |
| UINT16 Digits[3]; |
| |
| Buffer = (CHAR16 *) AllocateZeroPool (sizeof (CHAR16) * (StrLen + 1)); |
| if (Buffer == NULL) { |
| return EFI_OUT_OF_RESOURCES; |
| } |
| |
| StrCpyS (Buffer, (StrLen + 1), Str); |
| |
| // |
| // Data1 |
| // |
| PtrBuffer = Buffer; |
| PtrPosition = PtrBuffer; |
| while (*PtrBuffer != L'\0') { |
| if (*PtrBuffer == L'-') { |
| break; |
| } |
| PtrBuffer++; |
| } |
| if (*PtrBuffer == L'\0') { |
| FreePool (Buffer); |
| return EFI_NOT_FOUND; |
| } |
| |
| *PtrBuffer = L'\0'; |
| Data = StrHexToUintn (PtrPosition); |
| Guid->Data1 = (UINT32)Data; |
| |
| // |
| // Data2 |
| // |
| PtrBuffer++; |
| PtrPosition = PtrBuffer; |
| while (*PtrBuffer != L'\0') { |
| if (*PtrBuffer == L'-') { |
| break; |
| } |
| PtrBuffer++; |
| } |
| if (*PtrBuffer == L'\0') { |
| FreePool (Buffer); |
| return EFI_NOT_FOUND; |
| } |
| *PtrBuffer = L'\0'; |
| Data = StrHexToUintn (PtrPosition); |
| Guid->Data2 = (UINT16)Data; |
| |
| // |
| // Data3 |
| // |
| PtrBuffer++; |
| PtrPosition = PtrBuffer; |
| while (*PtrBuffer != L'\0') { |
| if (*PtrBuffer == L'-') { |
| break; |
| } |
| PtrBuffer++; |
| } |
| if (*PtrBuffer == L'\0') { |
| FreePool (Buffer); |
| return EFI_NOT_FOUND; |
| } |
| *PtrBuffer = L'\0'; |
| Data = StrHexToUintn (PtrPosition); |
| Guid->Data3 = (UINT16)Data; |
| |
| // |
| // Data4[0..1] |
| // |
| for ( Index = 0 ; Index < 2 ; Index++) { |
| PtrBuffer++; |
| if ((*PtrBuffer == L'\0') || ( *(PtrBuffer + 1) == L'\0')) { |
| FreePool (Buffer); |
| return EFI_NOT_FOUND; |
| } |
| Digits[0] = *PtrBuffer; |
| PtrBuffer++; |
| Digits[1] = *PtrBuffer; |
| Digits[2] = L'\0'; |
| Data = StrHexToUintn (Digits); |
| Guid->Data4[Index] = (UINT8)Data; |
| } |
| |
| // |
| // skip the '-' |
| // |
| PtrBuffer++; |
| if ((*PtrBuffer != L'-' ) || ( *PtrBuffer == L'\0')) { |
| return EFI_NOT_FOUND; |
| } |
| |
| // |
| // Data4[2..7] |
| // |
| for ( ; Index < 8; Index++) { |
| PtrBuffer++; |
| if ((*PtrBuffer == L'\0') || ( *(PtrBuffer + 1) == L'\0')) { |
| FreePool (Buffer); |
| return EFI_NOT_FOUND; |
| } |
| Digits[0] = *PtrBuffer; |
| PtrBuffer++; |
| Digits[1] = *PtrBuffer; |
| Digits[2] = L'\0'; |
| Data = StrHexToUintn (Digits); |
| Guid->Data4[Index] = (UINT8)Data; |
| } |
| |
| FreePool (Buffer); |
| |
| return EFI_SUCCESS; |
| } |
| |
| |
| /** |
| 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] PrivateData 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 |
| ); |
| } |
| |
| |
| /** |
| Close an open file handle. |
| |
| @param[in] FileHandle The file handle to close. |
| |
| **/ |
| VOID |
| CloseFile ( |
| IN EFI_FILE_HANDLE FileHandle |
| ) |
| { |
| if (FileHandle != NULL) { |
| FileHandle->Close (FileHandle); |
| } |
| } |
| |
| /** |
| 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: |
| |
| CloseFile (Private->FileContext->FHandle); |
| if (Private->FileContext->FileName != NULL) { |
| FreePool(Private->FileContext->FileName); |
| Private->FileContext->FileName = NULL; |
| } |
| |
| Private->FileContext->FHandle = NULL; |
| |
| 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 |
| 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; |
| 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)) { |
| 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: |
| ChooseFile( NULL, NULL, (CHOOSE_HANDLER) UpdateCAFromFile, &File); |
| break; |
| |
| case KEY_TLS_AUTH_CONFIG_VALUE_SAVE_AND_EXIT: |
| Status = EnrollCertDatabase (Private, EFI_TLS_CA_CERTIFICATE_VARIABLE); |
| if (EFI_ERROR (Status)) { |
| CreatePopUp ( |
| EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, |
| &Key, |
| L"ERROR: Enroll Cert Failure!", |
| NULL |
| ); |
| } |
| break; |
| |
| case KEY_TLS_AUTH_CONFIG_VALUE_NO_SAVE_AND_EXIT: |
| if (Private->FileContext->FHandle != NULL) { |
| CloseFile (Private->FileContext->FHandle); |
| Private->FileContext->FHandle = NULL; |
| if (Private->FileContext->FileName!= NULL){ |
| FreePool(Private->FileContext->FileName); |
| Private->FileContext->FileName = NULL; |
| } |
| } |
| |
| 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); |
| Status = StringToGuid ( |
| IfrNvData->CertGuid, |
| StrLen (IfrNvData->CertGuid), |
| Private->CertGuid |
| ); |
| if (EFI_ERROR (Status)) { |
| break; |
| } |
| |
| *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY; |
| break; |
| default: |
| break; |
| } |
| } |
| |
| 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; |
| |
| } |