NetworkPkg/TlsAuthConfigDxe: preserve TlsCaCertificate variable attributes
[mirror_edk2.git] / NetworkPkg / TlsAuthConfigDxe / TlsAuthConfigImpl.c
1 /** @file
2 The Miscellaneous Routines for TlsAuthConfigDxe driver.
3
4 Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>
5
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include "TlsAuthConfigImpl.h"
17
18 VOID *mStartOpCodeHandle = NULL;
19 VOID *mEndOpCodeHandle = NULL;
20 EFI_IFR_GUID_LABEL *mStartLabel = NULL;
21 EFI_IFR_GUID_LABEL *mEndLabel = NULL;
22
23
24 CHAR16 mTlsAuthConfigStorageName[] = L"TLS_AUTH_CONFIG_IFR_NVDATA";
25
26 TLS_AUTH_CONFIG_PRIVATE_DATA *mTlsAuthPrivateData = NULL;
27
28 HII_VENDOR_DEVICE_PATH mTlsAuthConfigHiiVendorDevicePath = {
29 {
30 {
31 HARDWARE_DEVICE_PATH,
32 HW_VENDOR_DP,
33 {
34 (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
35 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
36 }
37 },
38 TLS_AUTH_CONFIG_GUID
39 },
40 {
41 END_DEVICE_PATH_TYPE,
42 END_ENTIRE_DEVICE_PATH_SUBTYPE,
43 {
44 (UINT8) (END_DEVICE_PATH_LENGTH),
45 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
46 }
47 }
48 };
49
50 //
51 // Possible DER-encoded certificate file suffixes, end with NULL pointer.
52 //
53 CHAR16* mDerPemEncodedSuffix[] = {
54 L".cer",
55 L".der",
56 L".crt",
57 L".pem",
58 NULL
59 };
60
61 /**
62 This code checks if the FileSuffix is one of the possible DER/PEM-encoded certificate suffix.
63
64 @param[in] FileSuffix The suffix of the input certificate file
65
66 @retval TRUE It's a DER/PEM-encoded certificate.
67 @retval FALSE It's NOT a DER/PEM-encoded certificate.
68
69 **/
70 BOOLEAN
71 IsDerPemEncodeCertificate (
72 IN CONST CHAR16 *FileSuffix
73 )
74 {
75 UINTN Index;
76 for (Index = 0; mDerPemEncodedSuffix[Index] != NULL; Index++) {
77 if (StrCmp (FileSuffix, mDerPemEncodedSuffix[Index]) == 0) {
78 return TRUE;
79 }
80 }
81 return FALSE;
82 }
83
84 /**
85 Worker function that prints an EFI_GUID into specified Buffer.
86
87 @param[in] Guid Pointer to GUID to print.
88 @param[in] Buffer Buffer to print Guid into.
89 @param[in] BufferSize Size of Buffer.
90
91 @retval Number of characters printed.
92
93 **/
94 UINTN
95 GuidToString (
96 IN EFI_GUID *Guid,
97 IN CHAR16 *Buffer,
98 IN UINTN BufferSize
99 )
100 {
101 return UnicodeSPrint (
102 Buffer,
103 BufferSize,
104 L"%g",
105 Guid
106 );
107 }
108
109 /**
110 List all cert in specified database by GUID in the page
111 for user to select and delete as needed.
112
113 @param[in] PrivateData Module's private data.
114 @param[in] VariableName The variable name of the vendor's signature database.
115 @param[in] VendorGuid A unique identifier for the vendor.
116 @param[in] LabelNumber Label number to insert opcodes.
117 @param[in] FormId Form ID of current page.
118 @param[in] QuestionIdBase Base question id of the signature list.
119
120 @retval EFI_SUCCESS Success to update the signature list page
121 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
122
123 **/
124 EFI_STATUS
125 UpdateDeletePage (
126 IN TLS_AUTH_CONFIG_PRIVATE_DATA *Private,
127 IN CHAR16 *VariableName,
128 IN EFI_GUID *VendorGuid,
129 IN UINT16 LabelNumber,
130 IN EFI_FORM_ID FormId,
131 IN EFI_QUESTION_ID QuestionIdBase
132 )
133 {
134 EFI_STATUS Status;
135 UINT32 Index;
136 UINTN CertCount;
137 UINTN GuidIndex;
138 VOID *StartOpCodeHandle;
139 VOID *EndOpCodeHandle;
140 EFI_IFR_GUID_LABEL *StartLabel;
141 EFI_IFR_GUID_LABEL *EndLabel;
142 UINTN DataSize;
143 UINT8 *Data;
144 EFI_SIGNATURE_LIST *CertList;
145 EFI_SIGNATURE_DATA *Cert;
146 UINT32 ItemDataSize;
147 CHAR16 *GuidStr;
148 EFI_STRING_ID GuidID;
149 EFI_STRING_ID Help;
150
151 Data = NULL;
152 CertList = NULL;
153 Cert = NULL;
154 GuidStr = NULL;
155 StartOpCodeHandle = NULL;
156 EndOpCodeHandle = NULL;
157
158 //
159 // Initialize the container for dynamic opcodes.
160 //
161 StartOpCodeHandle = HiiAllocateOpCodeHandle ();
162 if (StartOpCodeHandle == NULL) {
163 Status = EFI_OUT_OF_RESOURCES;
164 goto ON_EXIT;
165 }
166
167 EndOpCodeHandle = HiiAllocateOpCodeHandle ();
168 if (EndOpCodeHandle == NULL) {
169 Status = EFI_OUT_OF_RESOURCES;
170 goto ON_EXIT;
171 }
172
173 //
174 // Create Hii Extend Label OpCode.
175 //
176 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
177 StartOpCodeHandle,
178 &gEfiIfrTianoGuid,
179 NULL,
180 sizeof (EFI_IFR_GUID_LABEL)
181 );
182 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
183 StartLabel->Number = LabelNumber;
184
185 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
186 EndOpCodeHandle,
187 &gEfiIfrTianoGuid,
188 NULL,
189 sizeof (EFI_IFR_GUID_LABEL)
190 );
191 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
192 EndLabel->Number = LABEL_END;
193
194 //
195 // Read Variable.
196 //
197 DataSize = 0;
198 Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data);
199 if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {
200 goto ON_EXIT;
201 }
202
203 Data = (UINT8 *) AllocateZeroPool (DataSize);
204 if (Data == NULL) {
205 Status = EFI_OUT_OF_RESOURCES;
206 goto ON_EXIT;
207 }
208
209 Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data);
210 if (EFI_ERROR (Status)) {
211 goto ON_EXIT;
212 }
213
214 GuidStr = AllocateZeroPool (100);
215 if (GuidStr == NULL) {
216 Status = EFI_OUT_OF_RESOURCES;
217 goto ON_EXIT;
218 }
219
220 //
221 // Enumerate all data.
222 //
223 ItemDataSize = (UINT32) DataSize;
224 CertList = (EFI_SIGNATURE_LIST *) Data;
225 GuidIndex = 0;
226
227 while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {
228
229 if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {
230 Help = STRING_TOKEN (STR_CERT_TYPE_PCKS_GUID);
231 } else {
232 //
233 // The signature type is not supported in current implementation.
234 //
235 ItemDataSize -= CertList->SignatureListSize;
236 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
237 continue;
238 }
239
240 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
241 for (Index = 0; Index < CertCount; Index++) {
242 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList
243 + sizeof (EFI_SIGNATURE_LIST)
244 + CertList->SignatureHeaderSize
245 + Index * CertList->SignatureSize);
246 //
247 // Display GUID and help
248 //
249 GuidToString (&Cert->SignatureOwner, GuidStr, 100);
250 GuidID = HiiSetString (Private->RegisteredHandle, 0, GuidStr, NULL);
251 HiiCreateCheckBoxOpCode (
252 StartOpCodeHandle,
253 (EFI_QUESTION_ID) (QuestionIdBase + GuidIndex++),
254 0,
255 0,
256 GuidID,
257 Help,
258 EFI_IFR_FLAG_CALLBACK,
259 0,
260 NULL
261 );
262 }
263
264 ItemDataSize -= CertList->SignatureListSize;
265 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
266 }
267
268 ON_EXIT:
269 HiiUpdateForm (
270 Private->RegisteredHandle,
271 &gTlsAuthConfigGuid,
272 FormId,
273 StartOpCodeHandle,
274 EndOpCodeHandle
275 );
276
277 if (StartOpCodeHandle != NULL) {
278 HiiFreeOpCodeHandle (StartOpCodeHandle);
279 }
280
281 if (EndOpCodeHandle != NULL) {
282 HiiFreeOpCodeHandle (EndOpCodeHandle);
283 }
284
285 if (Data != NULL) {
286 FreePool (Data);
287 }
288
289 if (GuidStr != NULL) {
290 FreePool (GuidStr);
291 }
292
293 return EFI_SUCCESS;
294 }
295
296 /**
297 Delete one entry from cert database.
298
299 @param[in] Private Module's private data.
300 @param[in] VariableName The variable name of the database.
301 @param[in] VendorGuid A unique identifier for the vendor.
302 @param[in] LabelNumber Label number to insert opcodes.
303 @param[in] FormId Form ID of current page.
304 @param[in] QuestionIdBase Base question id of the cert list.
305 @param[in] DeleteIndex Cert index to delete.
306
307 @retval EFI_SUCCESS Delete siganture successfully.
308 @retval EFI_NOT_FOUND Can't find the signature item,
309 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
310 **/
311 EFI_STATUS
312 DeleteCert (
313 IN TLS_AUTH_CONFIG_PRIVATE_DATA *Private,
314 IN CHAR16 *VariableName,
315 IN EFI_GUID *VendorGuid,
316 IN UINT16 LabelNumber,
317 IN EFI_FORM_ID FormId,
318 IN EFI_QUESTION_ID QuestionIdBase,
319 IN UINTN DeleteIndex
320 )
321 {
322 EFI_STATUS Status;
323 UINTN DataSize;
324 UINT8 *Data;
325 UINT8 *OldData;
326 UINT32 Attr;
327 UINT32 Index;
328 EFI_SIGNATURE_LIST *CertList;
329 EFI_SIGNATURE_LIST *NewCertList;
330 EFI_SIGNATURE_DATA *Cert;
331 UINTN CertCount;
332 UINT32 Offset;
333 BOOLEAN IsItemFound;
334 UINT32 ItemDataSize;
335 UINTN GuidIndex;
336
337 Data = NULL;
338 OldData = NULL;
339 CertList = NULL;
340 Cert = NULL;
341 Attr = 0;
342
343 //
344 // Get original signature list data.
345 //
346 DataSize = 0;
347 Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, NULL);
348 if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {
349 goto ON_EXIT;
350 }
351
352 OldData = (UINT8 *) AllocateZeroPool (DataSize);
353 if (OldData == NULL) {
354 Status = EFI_OUT_OF_RESOURCES;
355 goto ON_EXIT;
356 }
357
358 Status = gRT->GetVariable (VariableName, VendorGuid, &Attr, &DataSize, OldData);
359 if (EFI_ERROR(Status)) {
360 goto ON_EXIT;
361 }
362
363 //
364 // Allocate space for new variable.
365 //
366 Data = (UINT8*) AllocateZeroPool (DataSize);
367 if (Data == NULL) {
368 Status = EFI_OUT_OF_RESOURCES;
369 goto ON_EXIT;
370 }
371
372 //
373 // Enumerate all data and erasing the target item.
374 //
375 IsItemFound = FALSE;
376 ItemDataSize = (UINT32) DataSize;
377 CertList = (EFI_SIGNATURE_LIST *) OldData;
378 Offset = 0;
379 GuidIndex = 0;
380 while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {
381 if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {
382 //
383 // Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list.
384 //
385 CopyMem (Data + Offset, CertList, (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize));
386 NewCertList = (EFI_SIGNATURE_LIST*) (Data + Offset);
387 Offset += (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
388 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
389 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
390 for (Index = 0; Index < CertCount; Index++) {
391 if (GuidIndex == DeleteIndex) {
392 //
393 // Find it! Skip it!
394 //
395 NewCertList->SignatureListSize -= CertList->SignatureSize;
396 IsItemFound = TRUE;
397 } else {
398 //
399 // This item doesn't match. Copy it to the Data buffer.
400 //
401 CopyMem (Data + Offset, (UINT8*)(Cert), CertList->SignatureSize);
402 Offset += CertList->SignatureSize;
403 }
404 GuidIndex++;
405 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);
406 }
407 } else {
408 //
409 // This List doesn't match. Just copy it to the Data buffer.
410 //
411 CopyMem (Data + Offset, (UINT8*)(CertList), CertList->SignatureListSize);
412 Offset += CertList->SignatureListSize;
413 }
414
415 ItemDataSize -= CertList->SignatureListSize;
416 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
417 }
418
419 if (!IsItemFound) {
420 //
421 // Doesn't find the signature Item!
422 //
423 Status = EFI_NOT_FOUND;
424 goto ON_EXIT;
425 }
426
427 //
428 // Delete the EFI_SIGNATURE_LIST header if there is no signature in the list.
429 //
430 ItemDataSize = Offset;
431 CertList = (EFI_SIGNATURE_LIST *) Data;
432 Offset = 0;
433 ZeroMem (OldData, ItemDataSize);
434 while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {
435 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
436 DEBUG ((DEBUG_INFO, " CertCount = %x\n", CertCount));
437 if (CertCount != 0) {
438 CopyMem (OldData + Offset, (UINT8*)(CertList), CertList->SignatureListSize);
439 Offset += CertList->SignatureListSize;
440 }
441 ItemDataSize -= CertList->SignatureListSize;
442 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
443 }
444
445 DataSize = Offset;
446
447 Status = gRT->SetVariable(
448 VariableName,
449 VendorGuid,
450 Attr,
451 DataSize,
452 OldData
453 );
454 if (EFI_ERROR (Status)) {
455 DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r\n", Status));
456 goto ON_EXIT;
457 }
458
459 ON_EXIT:
460 if (Data != NULL) {
461 FreePool(Data);
462 }
463
464 if (OldData != NULL) {
465 FreePool(OldData);
466 }
467
468 return UpdateDeletePage (
469 Private,
470 VariableName,
471 VendorGuid,
472 LabelNumber,
473 FormId,
474 QuestionIdBase
475 );
476 }
477
478
479 /**
480 Clean the file related resource.
481
482 @param[in] Private Module's private data.
483
484 **/
485 VOID
486 CleanFileContext (
487 IN TLS_AUTH_CONFIG_PRIVATE_DATA *Private
488 )
489 {
490 if (Private->FileContext->FHandle != NULL) {
491 Private->FileContext->FHandle->Close (Private->FileContext->FHandle);
492 Private->FileContext->FHandle = NULL;
493 if (Private->FileContext->FileName!= NULL){
494 FreePool(Private->FileContext->FileName);
495 Private->FileContext->FileName = NULL;
496 }
497 }
498 }
499
500 /**
501 Read file content into BufferPtr, the size of the allocate buffer
502 is *FileSize plus AddtionAllocateSize.
503
504 @param[in] FileHandle The file to be read.
505 @param[in, out] BufferPtr Pointers to the pointer of allocated buffer.
506 @param[out] FileSize Size of input file
507 @param[in] AddtionAllocateSize Addtion size the buffer need to be allocated.
508 In case the buffer need to contain others besides the file content.
509
510 @retval EFI_SUCCESS The file was read into the buffer.
511 @retval EFI_INVALID_PARAMETER A parameter was invalid.
512 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
513 @retval others Unexpected error.
514
515 **/
516 EFI_STATUS
517 ReadFileContent (
518 IN EFI_FILE_HANDLE FileHandle,
519 IN OUT VOID **BufferPtr,
520 OUT UINTN *FileSize,
521 IN UINTN AddtionAllocateSize
522 )
523
524 {
525 UINTN BufferSize;
526 UINT64 SourceFileSize;
527 VOID *Buffer;
528 EFI_STATUS Status;
529
530 if ((FileHandle == NULL) || (FileSize == NULL)) {
531 return EFI_INVALID_PARAMETER;
532 }
533
534 Buffer = NULL;
535
536 //
537 // Get the file size
538 //
539 Status = FileHandle->SetPosition (FileHandle, (UINT64) -1);
540 if (EFI_ERROR (Status)) {
541 goto ON_EXIT;
542 }
543
544 Status = FileHandle->GetPosition (FileHandle, &SourceFileSize);
545 if (EFI_ERROR (Status)) {
546 goto ON_EXIT;
547 }
548
549 Status = FileHandle->SetPosition (FileHandle, 0);
550 if (EFI_ERROR (Status)) {
551 goto ON_EXIT;
552 }
553
554 BufferSize = (UINTN) SourceFileSize + AddtionAllocateSize;
555 Buffer = AllocateZeroPool(BufferSize);
556 if (Buffer == NULL) {
557 return EFI_OUT_OF_RESOURCES;
558 }
559
560 BufferSize = (UINTN) SourceFileSize;
561 *FileSize = BufferSize;
562
563 Status = FileHandle->Read (FileHandle, &BufferSize, Buffer);
564 if (EFI_ERROR (Status) || BufferSize != *FileSize) {
565 FreePool (Buffer);
566 Buffer = NULL;
567 Status = EFI_BAD_BUFFER_SIZE;
568 goto ON_EXIT;
569 }
570
571 ON_EXIT:
572
573 *BufferPtr = Buffer;
574 return Status;
575 }
576
577 /**
578 This function will open a file or directory referenced by DevicePath.
579
580 This function opens a file with the open mode according to the file path. The
581 Attributes is valid only for EFI_FILE_MODE_CREATE.
582
583 @param[in, out] FilePath On input, the device path to the file.
584 On output, the remaining device path.
585 @param[out] FileHandle Pointer to the file handle.
586 @param[in] OpenMode The mode to open the file with.
587 @param[in] Attributes The file's file attributes.
588
589 @retval EFI_SUCCESS The information was set.
590 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
591 @retval EFI_UNSUPPORTED Could not open the file path.
592 @retval EFI_NOT_FOUND The specified file could not be found on the
593 device or the file system could not be found on
594 the device.
595 @retval EFI_NO_MEDIA The device has no medium.
596 @retval EFI_MEDIA_CHANGED The device has a different medium in it or the
597 medium is no longer supported.
598 @retval EFI_DEVICE_ERROR The device reported an error.
599 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
600 @retval EFI_WRITE_PROTECTED The file or medium is write protected.
601 @retval EFI_ACCESS_DENIED The file was opened read only.
602 @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the
603 file.
604 @retval EFI_VOLUME_FULL The volume is full.
605 **/
606 EFI_STATUS
607 EFIAPI
608 OpenFileByDevicePath (
609 IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath,
610 OUT EFI_FILE_HANDLE *FileHandle,
611 IN UINT64 OpenMode,
612 IN UINT64 Attributes
613 )
614 {
615 EFI_STATUS Status;
616 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *EfiSimpleFileSystemProtocol;
617 EFI_FILE_PROTOCOL *Handle1;
618 EFI_FILE_PROTOCOL *Handle2;
619 EFI_HANDLE DeviceHandle;
620
621 if ((FilePath == NULL || FileHandle == NULL)) {
622 return EFI_INVALID_PARAMETER;
623 }
624
625 Status = gBS->LocateDevicePath (
626 &gEfiSimpleFileSystemProtocolGuid,
627 FilePath,
628 &DeviceHandle
629 );
630 if (EFI_ERROR (Status)) {
631 return Status;
632 }
633
634 Status = gBS->OpenProtocol(
635 DeviceHandle,
636 &gEfiSimpleFileSystemProtocolGuid,
637 (VOID**)&EfiSimpleFileSystemProtocol,
638 gImageHandle,
639 NULL,
640 EFI_OPEN_PROTOCOL_GET_PROTOCOL
641 );
642 if (EFI_ERROR (Status)) {
643 return Status;
644 }
645
646 Status = EfiSimpleFileSystemProtocol->OpenVolume(EfiSimpleFileSystemProtocol, &Handle1);
647 if (EFI_ERROR (Status)) {
648 FileHandle = NULL;
649 return Status;
650 }
651
652 //
653 // go down directories one node at a time.
654 //
655 while (!IsDevicePathEnd (*FilePath)) {
656 //
657 // For file system access each node should be a file path component
658 //
659 if (DevicePathType (*FilePath) != MEDIA_DEVICE_PATH ||
660 DevicePathSubType (*FilePath) != MEDIA_FILEPATH_DP
661 ) {
662 FileHandle = NULL;
663 return (EFI_INVALID_PARAMETER);
664 }
665 //
666 // Open this file path node
667 //
668 Handle2 = Handle1;
669 Handle1 = NULL;
670
671 //
672 // Try to test opening an existing file
673 //
674 Status = Handle2->Open (
675 Handle2,
676 &Handle1,
677 ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,
678 OpenMode &~EFI_FILE_MODE_CREATE,
679 0
680 );
681
682 //
683 // see if the error was that it needs to be created
684 //
685 if ((EFI_ERROR (Status)) && (OpenMode != (OpenMode &~EFI_FILE_MODE_CREATE))) {
686 Status = Handle2->Open (
687 Handle2,
688 &Handle1,
689 ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,
690 OpenMode,
691 Attributes
692 );
693 }
694 //
695 // Close the last node
696 //
697 Handle2->Close (Handle2);
698
699 if (EFI_ERROR(Status)) {
700 return (Status);
701 }
702
703 //
704 // Get the next node
705 //
706 *FilePath = NextDevicePathNode (*FilePath);
707 }
708
709 //
710 // This is a weak spot since if the undefined SHELL_FILE_HANDLE format changes this must change also!
711 //
712 *FileHandle = (VOID*)Handle1;
713 return EFI_SUCCESS;
714 }
715
716 /**
717 This function converts an input device structure to a Unicode string.
718
719 @param[in] DevPath A pointer to the device path structure.
720
721 @return A new allocated Unicode string that represents the device path.
722
723 **/
724 CHAR16 *
725 EFIAPI
726 DevicePathToStr (
727 IN EFI_DEVICE_PATH_PROTOCOL *DevPath
728 )
729 {
730 return ConvertDevicePathToText (
731 DevPath,
732 FALSE,
733 TRUE
734 );
735 }
736
737
738 /**
739 Extract filename from device path. The returned buffer is allocated using AllocateCopyPool.
740 The caller is responsible for freeing the allocated buffer using FreePool(). If return NULL
741 means not enough memory resource.
742
743 @param DevicePath Device path.
744
745 @retval NULL Not enough memory resourece for AllocateCopyPool.
746 @retval Other A new allocated string that represents the file name.
747
748 **/
749 CHAR16 *
750 ExtractFileNameFromDevicePath (
751 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
752 )
753 {
754 CHAR16 *String;
755 CHAR16 *MatchString;
756 CHAR16 *LastMatch;
757 CHAR16 *FileName;
758 UINTN Length;
759
760 ASSERT(DevicePath != NULL);
761
762 String = DevicePathToStr(DevicePath);
763 MatchString = String;
764 LastMatch = String;
765 FileName = NULL;
766
767 while(MatchString != NULL){
768 LastMatch = MatchString + 1;
769 MatchString = StrStr(LastMatch,L"\\");
770 }
771
772 Length = StrLen(LastMatch);
773 FileName = AllocateCopyPool ((Length + 1) * sizeof(CHAR16), LastMatch);
774 if (FileName != NULL) {
775 *(FileName + Length) = 0;
776 }
777
778 FreePool(String);
779
780 return FileName;
781 }
782
783 /**
784 Enroll a new X509 certificate into Variable.
785
786 @param[in] PrivateData The module's private data.
787 @param[in] VariableName Variable name of CA database.
788
789 @retval EFI_SUCCESS New X509 is enrolled successfully.
790 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
791
792 **/
793 EFI_STATUS
794 EnrollX509toVariable (
795 IN TLS_AUTH_CONFIG_PRIVATE_DATA *Private,
796 IN CHAR16 *VariableName
797 )
798 {
799 EFI_STATUS Status;
800 UINTN X509DataSize;
801 VOID *X509Data;
802 EFI_SIGNATURE_LIST *CACert;
803 EFI_SIGNATURE_DATA *CACertData;
804 VOID *Data;
805 UINTN DataSize;
806 UINTN SigDataSize;
807 UINT32 Attr;
808
809 X509DataSize = 0;
810 SigDataSize = 0;
811 DataSize = 0;
812 X509Data = NULL;
813 CACert = NULL;
814 CACertData = NULL;
815 Data = NULL;
816 Attr = 0;
817
818 Status = ReadFileContent (
819 Private->FileContext->FHandle,
820 &X509Data,
821 &X509DataSize,
822 0
823 );
824 if (EFI_ERROR (Status)) {
825 goto ON_EXIT;
826 }
827 ASSERT (X509Data != NULL);
828
829 SigDataSize = sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize;
830
831 Data = AllocateZeroPool (SigDataSize);
832 if (Data == NULL) {
833 Status = EFI_OUT_OF_RESOURCES;
834 goto ON_EXIT;
835 }
836
837 //
838 // Fill Certificate Database parameters.
839 //
840 CACert = (EFI_SIGNATURE_LIST*) Data;
841 CACert->SignatureListSize = (UINT32) SigDataSize;
842 CACert->SignatureHeaderSize = 0;
843 CACert->SignatureSize = (UINT32) (sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize);
844 CopyGuid (&CACert->SignatureType, &gEfiCertX509Guid);
845
846 CACertData = (EFI_SIGNATURE_DATA*) ((UINT8* ) CACert + sizeof (EFI_SIGNATURE_LIST));
847 CopyGuid (&CACertData->SignatureOwner, Private->CertGuid);
848 CopyMem ((UINT8* ) (CACertData->SignatureData), X509Data, X509DataSize);
849
850 //
851 // Check if the signature database entry already exists. If it does, use the
852 // EFI_VARIABLE_APPEND_WRITE attribute to append the new signature data to
853 // the original variable, plus preserve the original variable attributes.
854 //
855 Status = gRT->GetVariable(
856 VariableName,
857 &gEfiTlsCaCertificateGuid,
858 &Attr,
859 &DataSize,
860 NULL
861 );
862 if (Status == EFI_BUFFER_TOO_SMALL) {
863 Attr |= EFI_VARIABLE_APPEND_WRITE;
864 } else if (Status == EFI_NOT_FOUND) {
865 Attr = TLS_AUTH_CONFIG_VAR_BASE_ATTR;
866 } else {
867 goto ON_EXIT;
868 }
869
870 Status = gRT->SetVariable(
871 VariableName,
872 &gEfiTlsCaCertificateGuid,
873 Attr,
874 SigDataSize,
875 Data
876 );
877 if (EFI_ERROR (Status)) {
878 goto ON_EXIT;
879 }
880
881 ON_EXIT:
882 CleanFileContext (Private);
883
884 if (Private->CertGuid != NULL) {
885 FreePool (Private->CertGuid);
886 Private->CertGuid = NULL;
887 }
888
889 if (Data != NULL) {
890 FreePool (Data);
891 }
892
893 if (X509Data != NULL) {
894 FreePool (X509Data);
895 }
896
897 return Status;
898 }
899
900 /**
901 Enroll Cert into TlsCaCertificate. The GUID will be Private->CertGuid.
902
903 @param[in] PrivateData The module's private data.
904 @param[in] VariableName Variable name of signature database.
905
906 @retval EFI_SUCCESS New Cert enrolled successfully.
907 @retval EFI_INVALID_PARAMETER The parameter is invalid.
908 @retval EFI_UNSUPPORTED The Cert file is unsupported type.
909 @retval others Fail to enroll Cert data.
910
911 **/
912 EFI_STATUS
913 EnrollCertDatabase (
914 IN TLS_AUTH_CONFIG_PRIVATE_DATA *Private,
915 IN CHAR16 *VariableName
916 )
917 {
918 UINT16* FilePostFix;
919 UINTN NameLength;
920
921 if ((Private->FileContext->FileName == NULL) || (Private->FileContext->FHandle == NULL) || (Private->CertGuid == NULL)) {
922 return EFI_INVALID_PARAMETER;
923 }
924
925 //
926 // Parse the file's postfix.
927 //
928 NameLength = StrLen (Private->FileContext->FileName);
929 if (NameLength <= 4) {
930 return EFI_INVALID_PARAMETER;
931 }
932 FilePostFix = Private->FileContext->FileName + NameLength - 4;
933
934 if (IsDerPemEncodeCertificate (FilePostFix)) {
935 //
936 // Supports DER-encoded X509 certificate.
937 //
938 return EnrollX509toVariable (Private, VariableName);
939 }
940
941 return EFI_UNSUPPORTED;
942 }
943
944 /**
945 Refresh the global UpdateData structure.
946
947 **/
948 VOID
949 RefreshUpdateData (
950 VOID
951 )
952 {
953 //
954 // Free current updated date
955 //
956 if (mStartOpCodeHandle != NULL) {
957 HiiFreeOpCodeHandle (mStartOpCodeHandle);
958 }
959
960 //
961 // Create new OpCode Handle
962 //
963 mStartOpCodeHandle = HiiAllocateOpCodeHandle ();
964
965 //
966 // Create Hii Extend Label OpCode as the start opcode
967 //
968 mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
969 mStartOpCodeHandle,
970 &gEfiIfrTianoGuid,
971 NULL,
972 sizeof (EFI_IFR_GUID_LABEL)
973 );
974 mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
975 }
976
977 /**
978 Clean up the dynamic opcode at label and form specified by both LabelId.
979
980 @param[in] LabelId It is both the Form ID and Label ID for opcode deletion.
981 @param[in] PrivateData Module private data.
982
983 **/
984 VOID
985 CleanUpPage (
986 IN UINT16 LabelId,
987 IN TLS_AUTH_CONFIG_PRIVATE_DATA *PrivateData
988 )
989 {
990 RefreshUpdateData ();
991
992 //
993 // Remove all op-codes from dynamic page
994 //
995 mStartLabel->Number = LabelId;
996 HiiUpdateForm (
997 PrivateData->RegisteredHandle,
998 &gTlsAuthConfigGuid,
999 LabelId,
1000 mStartOpCodeHandle, // Label LabelId
1001 mEndOpCodeHandle // LABEL_END
1002 );
1003 }
1004
1005 /**
1006 Update the form base on the selected file.
1007
1008 @param FilePath Point to the file path.
1009 @param FormId The form need to display.
1010
1011 @retval TRUE Exit caller function.
1012 @retval FALSE Not exit caller function.
1013
1014 **/
1015 BOOLEAN
1016 UpdatePage(
1017 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
1018 IN EFI_FORM_ID FormId
1019 )
1020 {
1021 CHAR16 *FileName;
1022 EFI_STRING_ID StringToken;
1023
1024 FileName = NULL;
1025
1026 if (FilePath != NULL) {
1027 FileName = ExtractFileNameFromDevicePath(FilePath);
1028 }
1029 if (FileName == NULL) {
1030 //
1031 // FileName = NULL has two case:
1032 // 1. FilePath == NULL, not select file.
1033 // 2. FilePath != NULL, but ExtractFileNameFromDevicePath return NULL not enough memory resource.
1034 // In these two case, no need to update the form, and exit the caller function.
1035 //
1036 return TRUE;
1037 }
1038 StringToken = HiiSetString (mTlsAuthPrivateData->RegisteredHandle, 0, FileName, NULL);
1039
1040 mTlsAuthPrivateData->FileContext->FileName = FileName;
1041
1042 OpenFileByDevicePath (
1043 &FilePath,
1044 &mTlsAuthPrivateData->FileContext->FHandle,
1045 EFI_FILE_MODE_READ,
1046 0
1047 );
1048 //
1049 // Create Subtitle op-code for the display string of the option.
1050 //
1051 RefreshUpdateData ();
1052 mStartLabel->Number = FormId;
1053
1054 HiiCreateSubTitleOpCode (
1055 mStartOpCodeHandle,
1056 StringToken,
1057 0,
1058 0,
1059 0
1060 );
1061
1062 HiiUpdateForm (
1063 mTlsAuthPrivateData->RegisteredHandle,
1064 &gTlsAuthConfigGuid,
1065 FormId,
1066 mStartOpCodeHandle, /// Label FormId
1067 mEndOpCodeHandle /// LABEL_END
1068 );
1069
1070 return TRUE;
1071 }
1072
1073 /**
1074 Update the form base on the input file path info.
1075
1076 @param FilePath Point to the file path.
1077
1078 @retval TRUE Exit caller function.
1079 @retval FALSE Not exit caller function.
1080 **/
1081 BOOLEAN
1082 EFIAPI
1083 UpdateCAFromFile (
1084 IN EFI_DEVICE_PATH_PROTOCOL *FilePath
1085 )
1086 {
1087 return UpdatePage(FilePath, TLS_AUTH_CONFIG_FORMID4_FORM);
1088 }
1089
1090 /**
1091 Unload the configuration form, this includes: delete all the configuration
1092 entries, uninstall the form callback protocol, and free the resources used.
1093
1094 @param[in] Private Pointer to the driver private data.
1095
1096 @retval EFI_SUCCESS The configuration form is unloaded.
1097 @retval Others Failed to unload the form.
1098
1099 **/
1100 EFI_STATUS
1101 TlsAuthConfigFormUnload (
1102 IN TLS_AUTH_CONFIG_PRIVATE_DATA *Private
1103 )
1104 {
1105 if (Private->DriverHandle != NULL) {
1106 //
1107 // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL
1108 //
1109 gBS->UninstallMultipleProtocolInterfaces (
1110 Private->DriverHandle,
1111 &gEfiDevicePathProtocolGuid,
1112 &mTlsAuthConfigHiiVendorDevicePath,
1113 &gEfiHiiConfigAccessProtocolGuid,
1114 &Private->ConfigAccess,
1115 NULL
1116 );
1117 Private->DriverHandle = NULL;
1118 }
1119
1120 if (Private->RegisteredHandle != NULL) {
1121 //
1122 // Remove HII package list
1123 //
1124 HiiRemovePackages (Private->RegisteredHandle);
1125 Private->RegisteredHandle = NULL;
1126 }
1127
1128 if (Private->CertGuid != NULL) {
1129 FreePool (Private->CertGuid);
1130 }
1131
1132 if (Private->FileContext != NULL) {
1133 FreePool (Private->FileContext);
1134 }
1135
1136 FreePool (Private);
1137
1138 if (mStartOpCodeHandle != NULL) {
1139 HiiFreeOpCodeHandle (mStartOpCodeHandle);
1140 }
1141
1142 if (mEndOpCodeHandle != NULL) {
1143 HiiFreeOpCodeHandle (mEndOpCodeHandle);
1144 }
1145
1146 return EFI_SUCCESS;
1147 }
1148
1149
1150 /**
1151 Initialize the configuration form.
1152
1153 @param[in] Private Pointer to the driver private data.
1154
1155 @retval EFI_SUCCESS The configuration form is initialized.
1156 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
1157
1158 **/
1159 EFI_STATUS
1160 TlsAuthConfigFormInit (
1161 IN TLS_AUTH_CONFIG_PRIVATE_DATA *Private
1162 )
1163 {
1164 EFI_STATUS Status;
1165
1166 Private->Signature = TLS_AUTH_CONFIG_PRIVATE_DATA_SIGNATURE;
1167
1168 Private->ConfigAccess.ExtractConfig = TlsAuthConfigAccessExtractConfig;
1169 Private->ConfigAccess.RouteConfig = TlsAuthConfigAccessRouteConfig;
1170 Private->ConfigAccess.Callback = TlsAuthConfigAccessCallback;
1171
1172 //
1173 // Install Device Path Protocol and Config Access protocol to driver handle.
1174 //
1175 Status = gBS->InstallMultipleProtocolInterfaces (
1176 &Private->DriverHandle,
1177 &gEfiDevicePathProtocolGuid,
1178 &mTlsAuthConfigHiiVendorDevicePath,
1179 &gEfiHiiConfigAccessProtocolGuid,
1180 &Private->ConfigAccess,
1181 NULL
1182 );
1183 if (EFI_ERROR (Status)) {
1184 return Status;
1185 }
1186
1187 //
1188 // Publish our HII data.
1189 //
1190 Private->RegisteredHandle = HiiAddPackages (
1191 &gTlsAuthConfigGuid,
1192 Private->DriverHandle,
1193 TlsAuthConfigDxeStrings,
1194 TlsAuthConfigVfrBin,
1195 NULL
1196 );
1197 if (Private->RegisteredHandle == NULL) {
1198 Status = EFI_OUT_OF_RESOURCES;
1199 goto Error;
1200 }
1201
1202 Private->FileContext = AllocateZeroPool (sizeof (TLS_AUTH_CONFIG_FILE_CONTEXT));
1203 if (Private->FileContext == NULL) {
1204 Status = EFI_OUT_OF_RESOURCES;
1205 goto Error;
1206 }
1207
1208 //
1209 // Init OpCode Handle and Allocate space for creation of Buffer
1210 //
1211 mStartOpCodeHandle = HiiAllocateOpCodeHandle ();
1212 if (mStartOpCodeHandle == NULL) {
1213 Status = EFI_OUT_OF_RESOURCES;
1214 goto Error;
1215 }
1216
1217 mEndOpCodeHandle = HiiAllocateOpCodeHandle ();
1218 if (mEndOpCodeHandle == NULL) {
1219 Status = EFI_OUT_OF_RESOURCES;
1220 goto Error;
1221 }
1222
1223 //
1224 // Create Hii Extend Label OpCode as the start opcode
1225 //
1226 mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
1227 mStartOpCodeHandle,
1228 &gEfiIfrTianoGuid,
1229 NULL,
1230 sizeof (EFI_IFR_GUID_LABEL)
1231 );
1232 mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
1233
1234 //
1235 // Create Hii Extend Label OpCode as the end opcode
1236 //
1237 mEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
1238 mEndOpCodeHandle,
1239 &gEfiIfrTianoGuid,
1240 NULL,
1241 sizeof (EFI_IFR_GUID_LABEL)
1242 );
1243 mEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
1244 mEndLabel->Number = LABEL_END;
1245
1246 return EFI_SUCCESS;
1247
1248 Error:
1249 TlsAuthConfigFormUnload (Private);
1250 return Status;
1251 }
1252
1253 /**
1254
1255 This function allows the caller to request the current
1256 configuration for one or more named elements. The resulting
1257 string is in <ConfigAltResp> format. Any and all alternative
1258 configuration strings shall also be appended to the end of the
1259 current configuration string. If they are, they must appear
1260 after the current configuration. They must contain the same
1261 routing (GUID, NAME, PATH) as the current configuration string.
1262 They must have an additional description indicating the type of
1263 alternative configuration the string represents,
1264 "ALTCFG=<StringToken>". That <StringToken> (when
1265 converted from Hex UNICODE to binary) is a reference to a
1266 string in the associated string pack.
1267
1268 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1269
1270 @param Request A null-terminated Unicode string in
1271 <ConfigRequest> format. Note that this
1272 includes the routing information as well as
1273 the configurable name / value pairs. It is
1274 invalid for this string to be in
1275 <MultiConfigRequest> format.
1276 If a NULL is passed in for the Request field,
1277 all of the settings being abstracted by this function
1278 will be returned in the Results field. In addition,
1279 if a ConfigHdr is passed in with no request elements,
1280 all of the settings being abstracted for that particular
1281 ConfigHdr reference will be returned in the Results Field.
1282
1283 @param Progress On return, points to a character in the
1284 Request string. Points to the string's null
1285 terminator if request was successful. Points
1286 to the most recent "&" before the first
1287 failing name / value pair (or the beginning
1288 of the string if the failure is in the first
1289 name / value pair) if the request was not
1290 successful.
1291
1292 @param Results A null-terminated Unicode string in
1293 <MultiConfigAltResp> format which has all values
1294 filled in for the names in the Request string.
1295 String to be allocated by the called function.
1296
1297 @retval EFI_SUCCESS The Results string is filled with the
1298 values corresponding to all requested
1299 names.
1300
1301 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
1302 parts of the results that must be
1303 stored awaiting possible future
1304 protocols.
1305
1306 @retval EFI_NOT_FOUND Routing data doesn't match any
1307 known driver. Progress set to the
1308 first character in the routing header.
1309 Note: There is no requirement that the
1310 driver validate the routing data. It
1311 must skip the <ConfigHdr> in order to
1312 process the names.
1313
1314 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set
1315 to most recent "&" before the
1316 error or the beginning of the
1317 string.
1318
1319 @retval EFI_INVALID_PARAMETER Unknown name. Progress points
1320 to the & before the name in
1321 question.
1322
1323 **/
1324 EFI_STATUS
1325 EFIAPI
1326 TlsAuthConfigAccessExtractConfig (
1327 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
1328 IN CONST EFI_STRING Request,
1329 OUT EFI_STRING *Progress,
1330 OUT EFI_STRING *Results
1331 )
1332 {
1333 EFI_STATUS Status;
1334 UINTN BufferSize;
1335 UINTN Size;
1336 EFI_STRING ConfigRequest;
1337 EFI_STRING ConfigRequestHdr;
1338 TLS_AUTH_CONFIG_PRIVATE_DATA *Private;
1339 BOOLEAN AllocatedRequest;
1340
1341 if (Progress == NULL || Results == NULL) {
1342 return EFI_INVALID_PARAMETER;
1343 }
1344
1345 AllocatedRequest = FALSE;
1346 ConfigRequestHdr = NULL;
1347 ConfigRequest = NULL;
1348 Size = 0;
1349
1350 Private = TLS_AUTH_CONFIG_PRIVATE_FROM_THIS (This);
1351
1352 BufferSize = sizeof (TLS_AUTH_CONFIG_IFR_NVDATA);
1353 ZeroMem (&Private->TlsAuthConfigNvData, BufferSize);
1354
1355 *Progress = Request;
1356
1357 if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gTlsAuthConfigGuid, mTlsAuthConfigStorageName)) {
1358 return EFI_NOT_FOUND;
1359 }
1360
1361 ConfigRequest = Request;
1362 if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
1363 //
1364 // Request is set to NULL or OFFSET is NULL, construct full request string.
1365 //
1366 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
1367 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
1368 //
1369 ConfigRequestHdr = HiiConstructConfigHdr (&gTlsAuthConfigGuid, mTlsAuthConfigStorageName, Private->DriverHandle);
1370 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
1371 ConfigRequest = AllocateZeroPool (Size);
1372 ASSERT (ConfigRequest != NULL);
1373 AllocatedRequest = TRUE;
1374 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
1375 FreePool (ConfigRequestHdr);
1376 ConfigRequestHdr = NULL;
1377 }
1378
1379 Status = gHiiConfigRouting->BlockToConfig (
1380 gHiiConfigRouting,
1381 ConfigRequest,
1382 (UINT8 *) &Private->TlsAuthConfigNvData,
1383 BufferSize,
1384 Results,
1385 Progress
1386 );
1387
1388 //
1389 // Free the allocated config request string.
1390 //
1391 if (AllocatedRequest) {
1392 FreePool (ConfigRequest);
1393 }
1394
1395 //
1396 // Set Progress string to the original request string.
1397 //
1398 if (Request == NULL) {
1399 *Progress = NULL;
1400 } else if (StrStr (Request, L"OFFSET") == NULL) {
1401 *Progress = Request + StrLen (Request);
1402 }
1403
1404 return Status;
1405 }
1406
1407 /**
1408
1409 This function applies changes in a driver's configuration.
1410 Input is a Configuration, which has the routing data for this
1411 driver followed by name / value configuration pairs. The driver
1412 must apply those pairs to its configurable storage. If the
1413 driver's configuration is stored in a linear block of data
1414 and the driver's name / value pairs are in <BlockConfig>
1415 format, it may use the ConfigToBlock helper function (above) to
1416 simplify the job.
1417
1418 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1419
1420 @param Configuration A null-terminated Unicode string in
1421 <ConfigString> format.
1422
1423 @param Progress A pointer to a string filled in with the
1424 offset of the most recent '&' before the
1425 first failing name / value pair (or the
1426 beginn ing of the string if the failure
1427 is in the first name / value pair) or
1428 the terminating NULL if all was
1429 successful.
1430
1431 @retval EFI_SUCCESS The results have been distributed or are
1432 awaiting distribution.
1433
1434 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
1435 parts of the results that must be
1436 stored awaiting possible future
1437 protocols.
1438
1439 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the
1440 Results parameter would result
1441 in this type of error.
1442
1443 @retval EFI_NOT_FOUND Target for the specified routing data
1444 was not found
1445
1446 **/
1447 EFI_STATUS
1448 EFIAPI
1449 TlsAuthConfigAccessRouteConfig (
1450 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
1451 IN CONST EFI_STRING Configuration,
1452 OUT EFI_STRING *Progress
1453 )
1454 {
1455 EFI_STATUS Status;
1456 UINTN BufferSize;
1457 TLS_AUTH_CONFIG_PRIVATE_DATA *Private;
1458
1459 if (Progress == NULL) {
1460 return EFI_INVALID_PARAMETER;
1461 }
1462 *Progress = Configuration;
1463
1464 if (Configuration == NULL) {
1465 return EFI_INVALID_PARAMETER;
1466 }
1467
1468 //
1469 // Check routing data in <ConfigHdr>.
1470 // Note: there is no name for Name/Value storage, only GUID will be checked
1471 //
1472 if (!HiiIsConfigHdrMatch (Configuration, &gTlsAuthConfigGuid, mTlsAuthConfigStorageName)) {
1473 return EFI_NOT_FOUND;
1474 }
1475
1476 Private = TLS_AUTH_CONFIG_PRIVATE_FROM_THIS (This);
1477
1478 BufferSize = sizeof (TLS_AUTH_CONFIG_IFR_NVDATA);
1479 ZeroMem (&Private->TlsAuthConfigNvData, BufferSize);
1480
1481 Status = gHiiConfigRouting->ConfigToBlock (
1482 gHiiConfigRouting,
1483 Configuration,
1484 (UINT8 *) &Private->TlsAuthConfigNvData,
1485 &BufferSize,
1486 Progress
1487 );
1488 if (EFI_ERROR (Status)) {
1489 return Status;
1490 }
1491
1492 return Status;
1493 }
1494
1495 /**
1496
1497 This function is called to provide results data to the driver.
1498 This data consists of a unique key that is used to identify
1499 which data is either being passed back or being asked for.
1500
1501 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1502 @param Action Specifies the type of action taken by the browser.
1503 @param QuestionId A unique value which is sent to the original
1504 exporting driver so that it can identify the type
1505 of data to expect. The format of the data tends to
1506 vary based on the opcode that generated the callback.
1507 @param Type The type of value for the question.
1508 @param Value A pointer to the data being sent to the original
1509 exporting driver.
1510 @param ActionRequest On return, points to the action requested by the
1511 callback function.
1512
1513 @retval EFI_SUCCESS The callback successfully handled the action.
1514 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
1515 variable and its data.
1516 @retval EFI_DEVICE_ERROR The variable could not be saved.
1517 @retval EFI_UNSUPPORTED The specified Action is not supported by the
1518 callback.
1519 **/
1520 EFI_STATUS
1521 EFIAPI
1522 TlsAuthConfigAccessCallback (
1523 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
1524 IN EFI_BROWSER_ACTION Action,
1525 IN EFI_QUESTION_ID QuestionId,
1526 IN UINT8 Type,
1527 IN OUT EFI_IFR_TYPE_VALUE *Value,
1528 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
1529 )
1530 {
1531 EFI_INPUT_KEY Key;
1532 EFI_STATUS Status;
1533 RETURN_STATUS RStatus;
1534 TLS_AUTH_CONFIG_PRIVATE_DATA *Private;
1535 UINTN BufferSize;
1536 TLS_AUTH_CONFIG_IFR_NVDATA *IfrNvData;
1537 UINT16 LabelId;
1538 EFI_DEVICE_PATH_PROTOCOL *File;
1539
1540 Status = EFI_SUCCESS;
1541 File = NULL;
1542
1543 if ((This == NULL) || (Value == NULL) || (ActionRequest == NULL)) {
1544 return EFI_INVALID_PARAMETER;
1545 }
1546
1547 Private = TLS_AUTH_CONFIG_PRIVATE_FROM_THIS (This);
1548
1549 mTlsAuthPrivateData = Private;
1550
1551 //
1552 // Retrieve uncommitted data from Browser
1553 //
1554 BufferSize = sizeof (TLS_AUTH_CONFIG_IFR_NVDATA);
1555 IfrNvData = AllocateZeroPool (BufferSize);
1556 if (IfrNvData == NULL) {
1557 return EFI_OUT_OF_RESOURCES;
1558 }
1559
1560 HiiGetBrowserData (&gTlsAuthConfigGuid, mTlsAuthConfigStorageName, BufferSize, (UINT8 *) IfrNvData);
1561
1562 if ((Action != EFI_BROWSER_ACTION_CHANGED) &&
1563 (Action != EFI_BROWSER_ACTION_CHANGING) &&
1564 (Action != EFI_BROWSER_ACTION_FORM_CLOSE)) {
1565 Status = EFI_UNSUPPORTED;
1566 goto EXIT;
1567 }
1568
1569 if (Action == EFI_BROWSER_ACTION_CHANGING) {
1570 switch (QuestionId) {
1571 case KEY_TLS_AUTH_CONFIG_CLIENT_CERT:
1572 case KEY_TLS_AUTH_CONFIG_SERVER_CA:
1573 //
1574 // Clear Cert GUID.
1575 //
1576 ZeroMem (IfrNvData->CertGuid, sizeof (IfrNvData->CertGuid));
1577 if (Private->CertGuid == NULL) {
1578 Private->CertGuid = (EFI_GUID *) AllocateZeroPool (sizeof (EFI_GUID));
1579 if (Private->CertGuid == NULL) {
1580 return EFI_OUT_OF_RESOURCES;
1581 }
1582 }
1583 if (QuestionId == KEY_TLS_AUTH_CONFIG_CLIENT_CERT) {
1584 LabelId = TLS_AUTH_CONFIG_FORMID3_FORM;
1585 } else {
1586 LabelId = TLS_AUTH_CONFIG_FORMID4_FORM;
1587 }
1588
1589 //
1590 // Refresh selected file.
1591 //
1592 CleanUpPage (LabelId, Private);
1593 break;
1594 case KEY_TLS_AUTH_CONFIG_ENROLL_CERT_FROM_FILE:
1595 //
1596 // If the file is already opened, clean the file related resource first.
1597 //
1598 CleanFileContext (Private);
1599
1600 ChooseFile( NULL, NULL, UpdateCAFromFile, &File);
1601 break;
1602
1603 case KEY_TLS_AUTH_CONFIG_VALUE_SAVE_AND_EXIT:
1604 Status = EnrollCertDatabase (Private, EFI_TLS_CA_CERTIFICATE_VARIABLE);
1605 if (EFI_ERROR (Status)) {
1606 CleanFileContext (Private);
1607
1608 CreatePopUp (
1609 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1610 &Key,
1611 L"ERROR: Enroll Cert Failure!",
1612 NULL
1613 );
1614 }
1615 break;
1616
1617 case KEY_TLS_AUTH_CONFIG_VALUE_NO_SAVE_AND_EXIT:
1618 CleanFileContext (Private);
1619
1620 if (Private->CertGuid!= NULL) {
1621 FreePool (Private->CertGuid);
1622 Private->CertGuid = NULL;
1623 }
1624 break;
1625
1626 case KEY_TLS_AUTH_CONFIG_DELETE_CERT:
1627 UpdateDeletePage (
1628 Private,
1629 EFI_TLS_CA_CERTIFICATE_VARIABLE,
1630 &gEfiTlsCaCertificateGuid,
1631 LABEL_CA_DELETE,
1632 TLS_AUTH_CONFIG_FORMID5_FORM,
1633 OPTION_DEL_CA_ESTION_ID
1634 );
1635 break;
1636
1637 default:
1638 if ((QuestionId >= OPTION_DEL_CA_ESTION_ID) &&
1639 (QuestionId < (OPTION_DEL_CA_ESTION_ID + OPTION_CONFIG_RANGE))) {
1640 DeleteCert (
1641 Private,
1642 EFI_TLS_CA_CERTIFICATE_VARIABLE,
1643 &gEfiTlsCaCertificateGuid,
1644 LABEL_CA_DELETE,
1645 TLS_AUTH_CONFIG_FORMID5_FORM,
1646 OPTION_DEL_CA_ESTION_ID,
1647 QuestionId - OPTION_DEL_CA_ESTION_ID
1648 );
1649 }
1650 break;
1651 }
1652 } else if (Action == EFI_BROWSER_ACTION_CHANGED) {
1653 switch (QuestionId) {
1654 case KEY_TLS_AUTH_CONFIG_CERT_GUID:
1655 ASSERT (Private->CertGuid != NULL);
1656 RStatus = StrToGuid (
1657 IfrNvData->CertGuid,
1658 Private->CertGuid
1659 );
1660 if (RETURN_ERROR (RStatus) || (IfrNvData->CertGuid[GUID_STRING_LENGTH] != L'\0')) {
1661 Status = EFI_INVALID_PARAMETER;
1662 break;
1663 }
1664
1665 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
1666 break;
1667 default:
1668 break;
1669 }
1670 } else if (Action == EFI_BROWSER_ACTION_FORM_CLOSE) {
1671 CleanFileContext (Private);
1672 }
1673
1674 EXIT:
1675
1676 if (!EFI_ERROR (Status)) {
1677 BufferSize = sizeof (TLS_AUTH_CONFIG_IFR_NVDATA);
1678 HiiSetBrowserData (&gTlsAuthConfigGuid, mTlsAuthConfigStorageName, BufferSize, (UINT8*) IfrNvData, NULL);
1679 }
1680
1681 FreePool (IfrNvData);
1682
1683 if (File != NULL){
1684 FreePool(File);
1685 File = NULL;
1686 }
1687
1688 return EFI_SUCCESS;
1689
1690 }
1691