5b4756f16b0c98414e68f4465348ded61a7fbfb4
[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]    PrivateData         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   Close an open file handle.
481
482   @param[in] FileHandle           The file handle to close.
483   
484 **/
485 VOID
486 CloseFile (
487   IN EFI_FILE_HANDLE   FileHandle
488   )
489 {
490   if (FileHandle != NULL) {
491     FileHandle->Close (FileHandle);  
492   }
493 }
494
495 /**
496   Read file content into BufferPtr, the size of the allocate buffer 
497   is *FileSize plus AddtionAllocateSize.
498
499   @param[in]       FileHandle            The file to be read.
500   @param[in, out]  BufferPtr             Pointers to the pointer of allocated buffer.
501   @param[out]      FileSize              Size of input file
502   @param[in]       AddtionAllocateSize   Addtion size the buffer need to be allocated. 
503                                          In case the buffer need to contain others besides the file content.
504   
505   @retval   EFI_SUCCESS                  The file was read into the buffer.
506   @retval   EFI_INVALID_PARAMETER        A parameter was invalid.
507   @retval   EFI_OUT_OF_RESOURCES         A memory allocation failed.
508   @retval   others                       Unexpected error.
509
510 **/
511 EFI_STATUS
512 ReadFileContent (
513   IN      EFI_FILE_HANDLE           FileHandle,
514   IN OUT  VOID                      **BufferPtr,
515      OUT  UINTN                     *FileSize,
516   IN      UINTN                     AddtionAllocateSize
517   )
518
519 {
520   UINTN      BufferSize;
521   UINT64     SourceFileSize;
522   VOID       *Buffer;
523   EFI_STATUS Status;
524
525   if ((FileHandle == NULL) || (FileSize == NULL)) {
526     return EFI_INVALID_PARAMETER;
527   }
528
529   Buffer = NULL;
530
531   //
532   // Get the file size
533   //
534   Status = FileHandle->SetPosition (FileHandle, (UINT64) -1);
535   if (EFI_ERROR (Status)) {
536     goto ON_EXIT;
537   }
538
539   Status = FileHandle->GetPosition (FileHandle, &SourceFileSize);
540   if (EFI_ERROR (Status)) {
541     goto ON_EXIT;
542   }
543   
544   Status = FileHandle->SetPosition (FileHandle, 0);
545   if (EFI_ERROR (Status)) {
546     goto ON_EXIT;
547   }
548
549   BufferSize = (UINTN) SourceFileSize + AddtionAllocateSize;
550   Buffer =  AllocateZeroPool(BufferSize);
551   if (Buffer == NULL) {
552     return EFI_OUT_OF_RESOURCES;
553   }
554
555   BufferSize = (UINTN) SourceFileSize;
556   *FileSize  = BufferSize;
557
558   Status = FileHandle->Read (FileHandle, &BufferSize, Buffer);
559   if (EFI_ERROR (Status) || BufferSize != *FileSize) {
560     FreePool (Buffer);
561     Buffer = NULL;
562     Status  = EFI_BAD_BUFFER_SIZE;
563     goto ON_EXIT;
564   }
565
566 ON_EXIT:
567   
568   *BufferPtr = Buffer;
569   return Status;
570 }
571
572 /**
573   This function will open a file or directory referenced by DevicePath.
574
575   This function opens a file with the open mode according to the file path. The
576   Attributes is valid only for EFI_FILE_MODE_CREATE.
577
578   @param[in, out]  FilePath        On input, the device path to the file.
579                                    On output, the remaining device path.
580   @param[out]      FileHandle      Pointer to the file handle.
581   @param[in]       OpenMode        The mode to open the file with.
582   @param[in]       Attributes      The file's file attributes.
583
584   @retval EFI_SUCCESS              The information was set.
585   @retval EFI_INVALID_PARAMETER    One of the parameters has an invalid value.
586   @retval EFI_UNSUPPORTED          Could not open the file path.
587   @retval EFI_NOT_FOUND            The specified file could not be found on the
588                                    device or the file system could not be found on
589                                    the device.
590   @retval EFI_NO_MEDIA             The device has no medium.
591   @retval EFI_MEDIA_CHANGED        The device has a different medium in it or the
592                                    medium is no longer supported.
593   @retval EFI_DEVICE_ERROR         The device reported an error.
594   @retval EFI_VOLUME_CORRUPTED     The file system structures are corrupted.
595   @retval EFI_WRITE_PROTECTED      The file or medium is write protected.
596   @retval EFI_ACCESS_DENIED        The file was opened read only.
597   @retval EFI_OUT_OF_RESOURCES     Not enough resources were available to open the
598                                    file.
599   @retval EFI_VOLUME_FULL          The volume is full.
600 **/
601 EFI_STATUS
602 EFIAPI
603 OpenFileByDevicePath (
604   IN OUT EFI_DEVICE_PATH_PROTOCOL     **FilePath,
605   OUT EFI_FILE_HANDLE                 *FileHandle,
606   IN UINT64                           OpenMode,
607   IN UINT64                           Attributes
608   )
609 {
610   EFI_STATUS                      Status;
611   EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *EfiSimpleFileSystemProtocol;
612   EFI_FILE_PROTOCOL               *Handle1;
613   EFI_FILE_PROTOCOL               *Handle2;
614   EFI_HANDLE                      DeviceHandle;
615
616   if ((FilePath == NULL || FileHandle == NULL)) {
617     return EFI_INVALID_PARAMETER;
618   }
619
620   Status = gBS->LocateDevicePath (
621                   &gEfiSimpleFileSystemProtocolGuid,
622                   FilePath,
623                   &DeviceHandle
624                   );
625   if (EFI_ERROR (Status)) {
626     return Status;
627   }
628
629   Status = gBS->OpenProtocol(
630                   DeviceHandle,
631                   &gEfiSimpleFileSystemProtocolGuid,
632                   (VOID**)&EfiSimpleFileSystemProtocol,
633                   gImageHandle,
634                   NULL,
635                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
636                   );
637   if (EFI_ERROR (Status)) {
638     return Status;
639   }
640
641   Status = EfiSimpleFileSystemProtocol->OpenVolume(EfiSimpleFileSystemProtocol, &Handle1);
642   if (EFI_ERROR (Status)) {
643     FileHandle = NULL;
644     return Status;
645   }
646
647   //
648   // go down directories one node at a time.
649   //
650   while (!IsDevicePathEnd (*FilePath)) {
651     //
652     // For file system access each node should be a file path component
653     //
654     if (DevicePathType    (*FilePath) != MEDIA_DEVICE_PATH ||
655         DevicePathSubType (*FilePath) != MEDIA_FILEPATH_DP
656        ) {
657       FileHandle = NULL;
658       return (EFI_INVALID_PARAMETER);
659     }
660     //
661     // Open this file path node
662     //
663     Handle2  = Handle1;
664     Handle1 = NULL;
665
666     //
667     // Try to test opening an existing file
668     //
669     Status = Handle2->Open (
670                         Handle2,
671                         &Handle1,
672                         ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,
673                         OpenMode &~EFI_FILE_MODE_CREATE,
674                         0
675                         );
676
677     //
678     // see if the error was that it needs to be created
679     //
680     if ((EFI_ERROR (Status)) && (OpenMode != (OpenMode &~EFI_FILE_MODE_CREATE))) {
681       Status = Handle2->Open (
682                           Handle2,
683                           &Handle1,
684                           ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,
685                           OpenMode,
686                           Attributes
687                           );
688     }
689     //
690     // Close the last node
691     //
692     Handle2->Close (Handle2);
693
694     if (EFI_ERROR(Status)) {
695       return (Status);
696     }
697
698     //
699     // Get the next node
700     //
701     *FilePath = NextDevicePathNode (*FilePath);
702   }
703
704   //
705   // This is a weak spot since if the undefined SHELL_FILE_HANDLE format changes this must change also!
706   //
707   *FileHandle = (VOID*)Handle1;
708   return EFI_SUCCESS;
709 }
710
711 /**
712   This function converts an input device structure to a Unicode string.
713
714   @param[in] DevPath                  A pointer to the device path structure.
715
716   @return A new allocated Unicode string that represents the device path.
717
718 **/
719 CHAR16 *
720 EFIAPI
721 DevicePathToStr (
722   IN EFI_DEVICE_PATH_PROTOCOL     *DevPath
723   )
724 {
725   return ConvertDevicePathToText (
726            DevPath,
727            FALSE,
728            TRUE
729            );
730 }
731
732
733 /**
734   Extract filename from device path. The returned buffer is allocated using AllocateCopyPool.
735   The caller is responsible for freeing the allocated buffer using FreePool(). If return NULL
736   means not enough memory resource.
737
738   @param DevicePath       Device path.
739
740   @retval NULL            Not enough memory resourece for AllocateCopyPool.
741   @retval Other           A new allocated string that represents the file name.
742
743 **/
744 CHAR16 *
745 ExtractFileNameFromDevicePath (
746   IN   EFI_DEVICE_PATH_PROTOCOL *DevicePath
747   )
748 {
749   CHAR16          *String;
750   CHAR16          *MatchString;
751   CHAR16          *LastMatch;
752   CHAR16          *FileName;
753   UINTN           Length;
754
755   ASSERT(DevicePath != NULL);
756
757   String = DevicePathToStr(DevicePath);
758   MatchString = String;
759   LastMatch   = String;
760   FileName    = NULL;
761
762   while(MatchString != NULL){
763     LastMatch   = MatchString + 1;
764     MatchString = StrStr(LastMatch,L"\\");
765   }
766
767   Length = StrLen(LastMatch);
768   FileName = AllocateCopyPool ((Length + 1) * sizeof(CHAR16), LastMatch);
769   if (FileName != NULL) {
770     *(FileName + Length) = 0;
771   }
772
773   FreePool(String);
774
775   return FileName;
776 }
777
778 /**
779   Enroll a new X509 certificate into Variable.
780
781   @param[in] PrivateData     The module's private data.
782   @param[in] VariableName    Variable name of CA database.
783
784   @retval   EFI_SUCCESS            New X509 is enrolled successfully.
785   @retval   EFI_OUT_OF_RESOURCES   Could not allocate needed resources.
786
787 **/
788 EFI_STATUS
789 EnrollX509toVariable (
790   IN TLS_AUTH_CONFIG_PRIVATE_DATA   *Private,
791   IN CHAR16                         *VariableName
792   )
793 {
794   EFI_STATUS                        Status;
795   UINTN                             X509DataSize;
796   VOID                              *X509Data;
797   EFI_SIGNATURE_LIST                *CACert;
798   EFI_SIGNATURE_DATA                *CACertData;
799   VOID                              *Data;
800   UINTN                             DataSize;
801   UINTN                             SigDataSize;
802   UINT32                            Attr;
803
804   X509DataSize  = 0;
805   SigDataSize   = 0;
806   DataSize      = 0;
807   X509Data      = NULL;
808   CACert        = NULL;
809   CACertData    = NULL;
810   Data          = NULL;
811
812   Status = ReadFileContent (
813              Private->FileContext->FHandle,
814              &X509Data,
815              &X509DataSize,
816              0
817              );
818   if (EFI_ERROR (Status)) {
819     goto ON_EXIT;
820   }
821   ASSERT (X509Data != NULL);
822
823   SigDataSize = sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize;
824
825   Data = AllocateZeroPool (SigDataSize);
826   if (Data == NULL) {
827     Status = EFI_OUT_OF_RESOURCES;
828     goto ON_EXIT;
829   }
830
831   //
832   // Fill Certificate Database parameters.
833   //
834   CACert = (EFI_SIGNATURE_LIST*) Data;
835   CACert->SignatureListSize   = (UINT32) SigDataSize;
836   CACert->SignatureHeaderSize = 0;
837   CACert->SignatureSize = (UINT32) (sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize);
838   CopyGuid (&CACert->SignatureType, &gEfiCertX509Guid);
839
840   CACertData = (EFI_SIGNATURE_DATA*) ((UINT8* ) CACert + sizeof (EFI_SIGNATURE_LIST));
841   CopyGuid (&CACertData->SignatureOwner, Private->CertGuid);
842   CopyMem ((UINT8* ) (CACertData->SignatureData), X509Data, X509DataSize);
843
844   //
845   // Check if signature database entry has been already existed.
846   // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
847   // new signature data to original variable
848   //
849   Attr = TLS_AUTH_CONFIG_VAR_BASE_ATTR;
850
851   Status = gRT->GetVariable(
852                   VariableName,
853                   &gEfiTlsCaCertificateGuid,
854                   NULL,
855                   &DataSize,
856                   NULL
857                   );
858   if (Status == EFI_BUFFER_TOO_SMALL) {
859     Attr |= EFI_VARIABLE_APPEND_WRITE;
860   } else if (Status != EFI_NOT_FOUND) {
861     goto ON_EXIT;
862   }
863
864   Status = gRT->SetVariable(
865                   VariableName,
866                   &gEfiTlsCaCertificateGuid,
867                   Attr,
868                   SigDataSize,
869                   Data
870                   );
871   if (EFI_ERROR (Status)) {
872     goto ON_EXIT;
873   }
874
875 ON_EXIT:
876
877   CloseFile (Private->FileContext->FHandle);
878   if (Private->FileContext->FileName != NULL) {
879     FreePool(Private->FileContext->FileName);
880     Private->FileContext->FileName = NULL;
881   }
882
883   Private->FileContext->FHandle = NULL;
884
885   if (Private->CertGuid != NULL) {
886     FreePool (Private->CertGuid);
887     Private->CertGuid = NULL;
888   }
889
890   if (Data != NULL) {
891     FreePool (Data);
892   }
893
894   if (X509Data != NULL) {
895     FreePool (X509Data);
896   }
897
898   return Status;
899 }
900
901 /**
902   Enroll Cert into TlsCaCertificate. The GUID will be Private->CertGuid.
903
904   @param[in] PrivateData     The module's private data.
905   @param[in] VariableName    Variable name of signature database.
906
907   @retval   EFI_SUCCESS            New Cert enrolled successfully.
908   @retval   EFI_INVALID_PARAMETER  The parameter is invalid.
909   @retval   EFI_UNSUPPORTED        The Cert file is unsupported type.
910   @retval   others                 Fail to enroll Cert data.
911
912 **/
913 EFI_STATUS
914 EnrollCertDatabase (
915   IN TLS_AUTH_CONFIG_PRIVATE_DATA  *Private,
916   IN CHAR16                        *VariableName
917   )
918 {
919   UINT16*      FilePostFix;
920   UINTN        NameLength;
921
922   if ((Private->FileContext->FileName == NULL) || (Private->FileContext->FHandle == NULL) || (Private->CertGuid == NULL)) {
923     return EFI_INVALID_PARAMETER;
924   }
925
926   //
927   // Parse the file's postfix.
928   //
929   NameLength = StrLen (Private->FileContext->FileName);
930   if (NameLength <= 4) {
931     return EFI_INVALID_PARAMETER;
932   }
933   FilePostFix = Private->FileContext->FileName + NameLength - 4;
934
935   if (IsDerPemEncodeCertificate (FilePostFix)) {
936     //
937     // Supports DER-encoded X509 certificate.
938     //
939     return EnrollX509toVariable (Private, VariableName);
940   }
941
942   return EFI_UNSUPPORTED;
943 }
944
945 /**
946   Refresh the global UpdateData structure.
947
948 **/
949 VOID
950 RefreshUpdateData (
951   VOID
952   )
953 {
954   //
955   // Free current updated date
956   //
957   if (mStartOpCodeHandle != NULL) {
958     HiiFreeOpCodeHandle (mStartOpCodeHandle);
959   }
960
961   //
962   // Create new OpCode Handle
963   //
964   mStartOpCodeHandle = HiiAllocateOpCodeHandle ();
965
966   //
967   // Create Hii Extend Label OpCode as the start opcode
968   //
969   mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
970                                          mStartOpCodeHandle,
971                                          &gEfiIfrTianoGuid,
972                                          NULL,
973                                          sizeof (EFI_IFR_GUID_LABEL)
974                                          );
975   mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
976 }
977
978 /**
979   Clean up the dynamic opcode at label and form specified by both LabelId.
980
981   @param[in] LabelId         It is both the Form ID and Label ID for opcode deletion.
982   @param[in] PrivateData     Module private data.
983
984 **/
985 VOID
986 CleanUpPage (
987   IN UINT16                           LabelId,
988   IN TLS_AUTH_CONFIG_PRIVATE_DATA     *PrivateData
989   )
990 {
991   RefreshUpdateData ();
992
993   //
994   // Remove all op-codes from dynamic page
995   //
996   mStartLabel->Number = LabelId;
997   HiiUpdateForm (
998     PrivateData->RegisteredHandle,
999     &gTlsAuthConfigGuid,
1000     LabelId,
1001     mStartOpCodeHandle, // Label LabelId
1002     mEndOpCodeHandle    // LABEL_END
1003     );
1004 }
1005
1006 /**
1007   Update the form base on the selected file.
1008
1009   @param FilePath   Point to the file path.
1010   @param FormId     The form need to display.
1011
1012   @retval TRUE   Exit caller function.
1013   @retval FALSE  Not exit caller function.
1014
1015 **/
1016 BOOLEAN
1017 UpdatePage(
1018   IN  EFI_DEVICE_PATH_PROTOCOL  *FilePath,
1019   IN  EFI_FORM_ID               FormId
1020   )
1021 {
1022   CHAR16                *FileName;
1023   EFI_STRING_ID         StringToken;
1024
1025   FileName = NULL;
1026
1027   if (FilePath != NULL) {
1028     FileName = ExtractFileNameFromDevicePath(FilePath);
1029   }
1030   if (FileName == NULL) {
1031     //
1032     // FileName = NULL has two case:
1033     // 1. FilePath == NULL, not select file.
1034     // 2. FilePath != NULL, but ExtractFileNameFromDevicePath return NULL not enough memory resource.
1035     // In these two case, no need to update the form, and exit the caller function.
1036     //
1037     return TRUE;
1038   }
1039   StringToken =  HiiSetString (mTlsAuthPrivateData->RegisteredHandle, 0, FileName, NULL);
1040
1041   mTlsAuthPrivateData->FileContext->FileName = FileName;
1042
1043   OpenFileByDevicePath (
1044     &FilePath,
1045     &mTlsAuthPrivateData->FileContext->FHandle,
1046     EFI_FILE_MODE_READ,
1047     0
1048     );
1049   //
1050   // Create Subtitle op-code for the display string of the option.
1051   //
1052   RefreshUpdateData ();
1053   mStartLabel->Number = FormId;
1054
1055   HiiCreateSubTitleOpCode (
1056     mStartOpCodeHandle,
1057     StringToken,
1058     0,
1059     0,
1060     0
1061    );
1062
1063   HiiUpdateForm (
1064     mTlsAuthPrivateData->RegisteredHandle,
1065     &gTlsAuthConfigGuid,
1066     FormId,
1067     mStartOpCodeHandle, /// Label FormId
1068     mEndOpCodeHandle    /// LABEL_END
1069     );
1070
1071   return TRUE;
1072 }
1073
1074 /**
1075   Update the form base on the input file path info.
1076
1077   @param FilePath    Point to the file path.
1078
1079   @retval TRUE   Exit caller function.
1080   @retval FALSE  Not exit caller function.
1081 **/
1082 BOOLEAN
1083 EFIAPI
1084 UpdateCAFromFile (
1085   IN EFI_DEVICE_PATH_PROTOCOL    *FilePath
1086   )
1087 {
1088   return UpdatePage(FilePath, TLS_AUTH_CONFIG_FORMID4_FORM);
1089 }
1090
1091 /**
1092   Unload the configuration form, this includes: delete all the configuration
1093   entries, uninstall the form callback protocol, and free the resources used.
1094
1095   @param[in]  Private             Pointer to the driver private data.
1096
1097   @retval EFI_SUCCESS             The configuration form is unloaded.
1098   @retval Others                  Failed to unload the form.
1099
1100 **/
1101 EFI_STATUS
1102 TlsAuthConfigFormUnload (
1103   IN TLS_AUTH_CONFIG_PRIVATE_DATA     *Private
1104   )
1105 {
1106   if (Private->DriverHandle != NULL) {
1107     //
1108     // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL
1109     //
1110     gBS->UninstallMultipleProtocolInterfaces (
1111            Private->DriverHandle,
1112            &gEfiDevicePathProtocolGuid,
1113            &mTlsAuthConfigHiiVendorDevicePath,
1114            &gEfiHiiConfigAccessProtocolGuid,
1115            &Private->ConfigAccess,
1116            NULL
1117            );
1118     Private->DriverHandle = NULL;
1119   }
1120
1121   if (Private->RegisteredHandle != NULL) {
1122     //
1123     // Remove HII package list
1124     //
1125     HiiRemovePackages (Private->RegisteredHandle);
1126     Private->RegisteredHandle = NULL;
1127   }
1128
1129   if (Private->CertGuid != NULL) {
1130     FreePool (Private->CertGuid);
1131   }
1132
1133   if (Private->FileContext != NULL) {
1134     FreePool (Private->FileContext);
1135   }
1136
1137   FreePool (Private);
1138
1139   if (mStartOpCodeHandle != NULL) {
1140     HiiFreeOpCodeHandle (mStartOpCodeHandle);
1141   }
1142
1143   if (mEndOpCodeHandle != NULL) {
1144     HiiFreeOpCodeHandle (mEndOpCodeHandle);
1145   }
1146
1147   return EFI_SUCCESS;
1148 }
1149
1150
1151 /**
1152   Initialize the configuration form.
1153
1154   @param[in]  Private             Pointer to the driver private data.
1155
1156   @retval EFI_SUCCESS             The configuration form is initialized.
1157   @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
1158
1159 **/
1160 EFI_STATUS
1161 TlsAuthConfigFormInit (
1162   IN TLS_AUTH_CONFIG_PRIVATE_DATA     *Private
1163   )
1164 {
1165   EFI_STATUS                        Status;
1166
1167   Private->Signature = TLS_AUTH_CONFIG_PRIVATE_DATA_SIGNATURE;
1168   
1169   Private->ConfigAccess.ExtractConfig = TlsAuthConfigAccessExtractConfig;
1170   Private->ConfigAccess.RouteConfig   = TlsAuthConfigAccessRouteConfig;
1171   Private->ConfigAccess.Callback      = TlsAuthConfigAccessCallback;
1172
1173   //
1174   // Install Device Path Protocol and Config Access protocol to driver handle.
1175   //
1176   Status = gBS->InstallMultipleProtocolInterfaces (
1177                   &Private->DriverHandle,
1178                   &gEfiDevicePathProtocolGuid,
1179                   &mTlsAuthConfigHiiVendorDevicePath,
1180                   &gEfiHiiConfigAccessProtocolGuid,
1181                   &Private->ConfigAccess,
1182                   NULL
1183                   );
1184   if (EFI_ERROR (Status)) {
1185     return Status;
1186   }
1187   
1188   //
1189   // Publish our HII data.
1190   //
1191   Private->RegisteredHandle = HiiAddPackages (
1192                                 &gTlsAuthConfigGuid,
1193                                 Private->DriverHandle,
1194                                 TlsAuthConfigDxeStrings,
1195                                 TlsAuthConfigVfrBin,
1196                                 NULL
1197                                 );
1198   if (Private->RegisteredHandle == NULL) {
1199     Status = EFI_OUT_OF_RESOURCES;
1200     goto Error;
1201   }
1202
1203   Private->FileContext = AllocateZeroPool (sizeof (TLS_AUTH_CONFIG_FILE_CONTEXT));
1204   if (Private->FileContext == NULL) {
1205     Status = EFI_OUT_OF_RESOURCES;
1206     goto Error;
1207   }
1208
1209   //
1210   // Init OpCode Handle and Allocate space for creation of Buffer
1211   //
1212   mStartOpCodeHandle = HiiAllocateOpCodeHandle ();
1213   if (mStartOpCodeHandle == NULL) {
1214     Status = EFI_OUT_OF_RESOURCES;
1215     goto Error;
1216   }
1217
1218   mEndOpCodeHandle = HiiAllocateOpCodeHandle ();
1219   if (mEndOpCodeHandle == NULL) {
1220     Status = EFI_OUT_OF_RESOURCES;
1221     goto Error;
1222   }
1223
1224   //
1225   // Create Hii Extend Label OpCode as the start opcode
1226   //
1227   mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
1228                                          mStartOpCodeHandle,
1229                                          &gEfiIfrTianoGuid,
1230                                          NULL,
1231                                          sizeof (EFI_IFR_GUID_LABEL)
1232                                          );
1233   mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
1234
1235   //
1236   // Create Hii Extend Label OpCode as the end opcode
1237   //
1238   mEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
1239                                        mEndOpCodeHandle,
1240                                        &gEfiIfrTianoGuid,
1241                                        NULL,
1242                                        sizeof (EFI_IFR_GUID_LABEL)
1243                                        );
1244   mEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
1245   mEndLabel->Number       = LABEL_END;
1246
1247   return EFI_SUCCESS;
1248   
1249 Error:
1250   TlsAuthConfigFormUnload (Private);
1251   return Status;
1252 }
1253
1254 /**
1255    
1256   This function allows the caller to request the current
1257   configuration for one or more named elements. The resulting
1258   string is in <ConfigAltResp> format. Any and all alternative
1259   configuration strings shall also be appended to the end of the
1260   current configuration string. If they are, they must appear
1261   after the current configuration. They must contain the same
1262   routing (GUID, NAME, PATH) as the current configuration string.
1263   They must have an additional description indicating the type of
1264   alternative configuration the string represents,
1265   "ALTCFG=<StringToken>". That <StringToken> (when
1266   converted from Hex UNICODE to binary) is a reference to a
1267   string in the associated string pack.
1268
1269   @param This       Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1270
1271   @param Request    A null-terminated Unicode string in
1272                     <ConfigRequest> format. Note that this
1273                     includes the routing information as well as
1274                     the configurable name / value pairs. It is
1275                     invalid for this string to be in
1276                     <MultiConfigRequest> format. 
1277                     If a NULL is passed in for the Request field, 
1278                     all of the settings being abstracted by this function 
1279                     will be returned in the Results field.  In addition, 
1280                     if a ConfigHdr is passed in with no request elements, 
1281                     all of the settings being abstracted for that particular 
1282                     ConfigHdr reference will be returned in the Results Field.
1283
1284   @param Progress   On return, points to a character in the
1285                     Request string. Points to the string's null
1286                     terminator if request was successful. Points
1287                     to the most recent "&" before the first
1288                     failing name / value pair (or the beginning
1289                     of the string if the failure is in the first
1290                     name / value pair) if the request was not
1291                     successful.
1292
1293   @param Results    A null-terminated Unicode string in
1294                     <MultiConfigAltResp> format which has all values
1295                     filled in for the names in the Request string.
1296                     String to be allocated by the called function.
1297
1298   @retval EFI_SUCCESS             The Results string is filled with the
1299                                   values corresponding to all requested
1300                                   names.
1301
1302   @retval EFI_OUT_OF_RESOURCES    Not enough memory to store the
1303                                   parts of the results that must be
1304                                   stored awaiting possible future
1305                                   protocols.
1306
1307   @retval EFI_NOT_FOUND           Routing data doesn't match any
1308                                   known driver. Progress set to the
1309                                   first character in the routing header.
1310                                   Note: There is no requirement that the
1311                                   driver validate the routing data. It
1312                                   must skip the <ConfigHdr> in order to
1313                                   process the names.
1314
1315   @retval EFI_INVALID_PARAMETER   Illegal syntax. Progress set
1316                                   to most recent "&" before the
1317                                   error or the beginning of the
1318                                   string.
1319
1320   @retval EFI_INVALID_PARAMETER   Unknown name. Progress points
1321                                   to the & before the name in
1322                                   question.
1323
1324 **/
1325 EFI_STATUS
1326 EFIAPI
1327 TlsAuthConfigAccessExtractConfig (
1328   IN CONST  EFI_HII_CONFIG_ACCESS_PROTOCOL  *This,
1329   IN CONST  EFI_STRING                      Request,
1330   OUT       EFI_STRING                      *Progress,
1331   OUT       EFI_STRING                      *Results
1332   )
1333 {
1334   EFI_STATUS                        Status;
1335   UINTN                             BufferSize;
1336   UINTN                             Size;
1337   EFI_STRING                        ConfigRequest;
1338   EFI_STRING                        ConfigRequestHdr;
1339   TLS_AUTH_CONFIG_PRIVATE_DATA      *Private;
1340   BOOLEAN                           AllocatedRequest;
1341
1342   if (Progress == NULL || Results == NULL) {
1343     return EFI_INVALID_PARAMETER;
1344   }
1345
1346   AllocatedRequest = FALSE;
1347   ConfigRequestHdr = NULL;
1348   ConfigRequest    = NULL;
1349   Size             = 0;
1350
1351   Private          = TLS_AUTH_CONFIG_PRIVATE_FROM_THIS (This);
1352
1353   BufferSize       = sizeof (TLS_AUTH_CONFIG_IFR_NVDATA);
1354   ZeroMem (&Private->TlsAuthConfigNvData, BufferSize);
1355   
1356   *Progress        = Request;
1357
1358   if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gTlsAuthConfigGuid, mTlsAuthConfigStorageName)) {
1359     return EFI_NOT_FOUND;
1360   }
1361   
1362   ConfigRequest = Request;
1363   if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
1364     //
1365     // Request is set to NULL or OFFSET is NULL, construct full request string.
1366     //
1367     // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
1368     // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
1369     //
1370     ConfigRequestHdr = HiiConstructConfigHdr (&gTlsAuthConfigGuid, mTlsAuthConfigStorageName, Private->DriverHandle);
1371     Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
1372     ConfigRequest = AllocateZeroPool (Size);
1373     ASSERT (ConfigRequest != NULL);
1374     AllocatedRequest = TRUE;
1375     UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
1376     FreePool (ConfigRequestHdr);
1377     ConfigRequestHdr = NULL;
1378   }
1379
1380   Status = gHiiConfigRouting->BlockToConfig (
1381                                 gHiiConfigRouting,
1382                                 ConfigRequest,
1383                                 (UINT8 *) &Private->TlsAuthConfigNvData,
1384                                 BufferSize,
1385                                 Results,
1386                                 Progress
1387                                 );
1388
1389   //
1390   // Free the allocated config request string.
1391   //
1392   if (AllocatedRequest) {
1393     FreePool (ConfigRequest);
1394   }
1395
1396   //
1397   // Set Progress string to the original request string.
1398   //
1399   if (Request == NULL) {
1400     *Progress = NULL;
1401   } else if (StrStr (Request, L"OFFSET") == NULL) {
1402     *Progress = Request + StrLen (Request);
1403   }
1404
1405   return Status;
1406 }
1407
1408 /**
1409    
1410   This function applies changes in a driver's configuration.
1411   Input is a Configuration, which has the routing data for this
1412   driver followed by name / value configuration pairs. The driver
1413   must apply those pairs to its configurable storage. If the
1414   driver's configuration is stored in a linear block of data
1415   and the driver's name / value pairs are in <BlockConfig>
1416   format, it may use the ConfigToBlock helper function (above) to
1417   simplify the job.
1418
1419   @param This           Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1420
1421   @param Configuration  A null-terminated Unicode string in
1422                         <ConfigString> format. 
1423   
1424   @param Progress       A pointer to a string filled in with the
1425                         offset of the most recent '&' before the
1426                         first failing name / value pair (or the
1427                         beginn ing of the string if the failure
1428                         is in the first name / value pair) or
1429                         the terminating NULL if all was
1430                         successful.
1431
1432   @retval EFI_SUCCESS             The results have been distributed or are
1433                                   awaiting distribution.
1434   
1435   @retval EFI_OUT_OF_RESOURCES    Not enough memory to store the
1436                                   parts of the results that must be
1437                                   stored awaiting possible future
1438                                   protocols.
1439   
1440   @retval EFI_INVALID_PARAMETERS  Passing in a NULL for the
1441                                   Results parameter would result
1442                                   in this type of error.
1443   
1444   @retval EFI_NOT_FOUND           Target for the specified routing data
1445                                   was not found
1446
1447 **/
1448 EFI_STATUS
1449 EFIAPI
1450 TlsAuthConfigAccessRouteConfig (
1451   IN CONST  EFI_HII_CONFIG_ACCESS_PROTOCOL  *This,
1452   IN CONST  EFI_STRING                      Configuration,
1453   OUT       EFI_STRING                      *Progress
1454   )
1455 {
1456   EFI_STATUS                       Status;
1457   UINTN                            BufferSize;
1458   TLS_AUTH_CONFIG_PRIVATE_DATA     *Private;
1459
1460   if (Progress == NULL) {
1461     return EFI_INVALID_PARAMETER;
1462   }
1463   *Progress = Configuration;
1464
1465   if (Configuration == NULL) {
1466     return EFI_INVALID_PARAMETER;
1467   }
1468
1469   //
1470   // Check routing data in <ConfigHdr>.
1471   // Note: there is no name for Name/Value storage, only GUID will be checked
1472   //
1473   if (!HiiIsConfigHdrMatch (Configuration, &gTlsAuthConfigGuid, mTlsAuthConfigStorageName)) {
1474     return EFI_NOT_FOUND;
1475   }
1476
1477   Private = TLS_AUTH_CONFIG_PRIVATE_FROM_THIS (This);
1478   
1479   BufferSize = sizeof (TLS_AUTH_CONFIG_IFR_NVDATA);
1480   ZeroMem (&Private->TlsAuthConfigNvData, BufferSize);
1481
1482   Status = gHiiConfigRouting->ConfigToBlock (
1483                                 gHiiConfigRouting,
1484                                 Configuration,
1485                                 (UINT8 *) &Private->TlsAuthConfigNvData,
1486                                 &BufferSize,
1487                                 Progress
1488                                 );
1489   if (EFI_ERROR (Status)) {
1490     return Status;
1491   }
1492
1493   return Status;
1494 }  
1495
1496 /**
1497    
1498   This function is called to provide results data to the driver.
1499   This data consists of a unique key that is used to identify
1500   which data is either being passed back or being asked for.
1501
1502   @param  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1503   @param  Action                 Specifies the type of action taken by the browser.
1504   @param  QuestionId             A unique value which is sent to the original
1505                                  exporting driver so that it can identify the type
1506                                  of data to expect. The format of the data tends to 
1507                                  vary based on the opcode that generated the callback.
1508   @param  Type                   The type of value for the question.
1509   @param  Value                  A pointer to the data being sent to the original
1510                                  exporting driver.
1511   @param  ActionRequest          On return, points to the action requested by the
1512                                  callback function.
1513
1514   @retval EFI_SUCCESS            The callback successfully handled the action.
1515   @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the
1516                                  variable and its data.
1517   @retval EFI_DEVICE_ERROR       The variable could not be saved.
1518   @retval EFI_UNSUPPORTED        The specified Action is not supported by the
1519                                  callback.
1520 **/
1521 EFI_STATUS
1522 EFIAPI
1523 TlsAuthConfigAccessCallback (
1524   IN     CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
1525   IN     EFI_BROWSER_ACTION                     Action,
1526   IN     EFI_QUESTION_ID                        QuestionId,
1527   IN     UINT8                                  Type,
1528   IN OUT EFI_IFR_TYPE_VALUE                     *Value,
1529   OUT    EFI_BROWSER_ACTION_REQUEST             *ActionRequest
1530   )
1531 {
1532   EFI_INPUT_KEY                   Key;
1533   EFI_STATUS                      Status;
1534   RETURN_STATUS                   RStatus;
1535   TLS_AUTH_CONFIG_PRIVATE_DATA    *Private;
1536   UINTN                           BufferSize;
1537   TLS_AUTH_CONFIG_IFR_NVDATA      *IfrNvData;
1538   UINT16                          LabelId;
1539   EFI_DEVICE_PATH_PROTOCOL        *File;
1540
1541   Status           = EFI_SUCCESS;
1542   File             = NULL;
1543
1544   if ((This == NULL) || (Value == NULL) || (ActionRequest == NULL)) {
1545     return EFI_INVALID_PARAMETER;
1546   }
1547   
1548   Private = TLS_AUTH_CONFIG_PRIVATE_FROM_THIS (This);
1549
1550   mTlsAuthPrivateData = Private;
1551
1552   //
1553   // Retrieve uncommitted data from Browser
1554   //
1555   BufferSize = sizeof (TLS_AUTH_CONFIG_IFR_NVDATA);
1556   IfrNvData = AllocateZeroPool (BufferSize);
1557   if (IfrNvData == NULL) {
1558     return EFI_OUT_OF_RESOURCES;
1559   }
1560
1561   HiiGetBrowserData (&gTlsAuthConfigGuid, mTlsAuthConfigStorageName, BufferSize, (UINT8 *) IfrNvData);
1562
1563   if ((Action != EFI_BROWSER_ACTION_CHANGED) &&
1564       (Action != EFI_BROWSER_ACTION_CHANGING)) {
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       ChooseFile( NULL, NULL, UpdateCAFromFile, &File);
1596       break;
1597
1598     case KEY_TLS_AUTH_CONFIG_VALUE_SAVE_AND_EXIT:
1599       Status = EnrollCertDatabase (Private, EFI_TLS_CA_CERTIFICATE_VARIABLE);
1600       if (EFI_ERROR (Status)) {
1601         CreatePopUp (
1602           EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1603           &Key,
1604           L"ERROR: Enroll Cert Failure!",
1605           NULL
1606           );
1607       }
1608       break;
1609
1610     case KEY_TLS_AUTH_CONFIG_VALUE_NO_SAVE_AND_EXIT:
1611       if (Private->FileContext->FHandle != NULL) {
1612         CloseFile (Private->FileContext->FHandle);
1613         Private->FileContext->FHandle = NULL;
1614         if (Private->FileContext->FileName!= NULL){
1615           FreePool(Private->FileContext->FileName);
1616           Private->FileContext->FileName = NULL;
1617         }
1618       }
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   }
1671   
1672 EXIT:
1673
1674   if (!EFI_ERROR (Status)) {
1675     BufferSize = sizeof (TLS_AUTH_CONFIG_IFR_NVDATA);
1676     HiiSetBrowserData (&gTlsAuthConfigGuid, mTlsAuthConfigStorageName, BufferSize, (UINT8*) IfrNvData, NULL);
1677   }
1678
1679   FreePool (IfrNvData);
1680
1681   if (File != NULL){
1682     FreePool(File);
1683     File = NULL;
1684   }
1685
1686   return EFI_SUCCESS;
1687
1688 }