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