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