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