1 /** @file
2   The header file of HII Config Access protocol implementation of SecureBoot
3   configuration module.
4 
5 Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.<BR>
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 #ifndef __SECUREBOOT_CONFIG_IMPL_H__
17 #define __SECUREBOOT_CONFIG_IMPL_H__
18 
19 #include <Uefi.h>
20 
21 #include <Protocol/HiiConfigAccess.h>
22 #include <Protocol/HiiConfigRouting.h>
23 #include <Protocol/SimpleFileSystem.h>
24 #include <Protocol/BlockIo.h>
25 #include <Protocol/DevicePath.h>
26 #include <Protocol/DebugPort.h>
27 #include <Protocol/LoadFile.h>
28 
29 #include <Library/BaseLib.h>
30 #include <Library/BaseMemoryLib.h>
31 #include <Library/DebugLib.h>
32 #include <Library/MemoryAllocationLib.h>
33 #include <Library/UefiBootServicesTableLib.h>
34 #include <Library/UefiRuntimeServicesTableLib.h>
35 #include <Library/UefiHiiServicesLib.h>
36 #include <Library/UefiLib.h>
37 #include <Library/HiiLib.h>
38 #include <Library/DevicePathLib.h>
39 #include <Library/PrintLib.h>
40 #include <Library/PlatformSecureLib.h>
41 #include <Library/BaseCryptLib.h>
42 #include <Guid/MdeModuleHii.h>
43 #include <Guid/AuthenticatedVariableFormat.h>
44 #include <Guid/FileSystemVolumeLabelInfo.h>
45 #include <Guid/ImageAuthentication.h>
46 #include <Guid/FileInfo.h>
47 
48 #include "SecureBootConfigNvData.h"
49 
50 //
51 // Tool generated IFR binary data and String package data
52 //
53 extern  UINT8                      SecureBootConfigBin[];
54 extern  UINT8                      SecureBootConfigDxeStrings[];
55 
56 //
57 // Shared IFR form update data
58 //
59 extern  VOID                       *mStartOpCodeHandle;
60 extern  VOID                       *mEndOpCodeHandle;
61 extern  EFI_IFR_GUID_LABEL         *mStartLabel;
62 extern  EFI_IFR_GUID_LABEL         *mEndLabel;
63 
64 #define MAX_CHAR              480
65 #define TWO_BYTE_ENCODE       0x82
66 
67 //
68 // SHA-1 digest size in bytes.
69 //
70 #define SHA1_DIGEST_SIZE    20
71 //
72 // SHA-256 digest size in bytes
73 //
74 #define SHA256_DIGEST_SIZE  32
75 //
76 // SHA-384 digest size in bytes
77 //
78 #define SHA384_DIGEST_SIZE  48
79 //
80 // SHA-512 digest size in bytes
81 //
82 #define SHA512_DIGEST_SIZE  64
83 
84 //
85 // Set max digest size as SHA512 Output (64 bytes) by far
86 //
87 #define MAX_DIGEST_SIZE    SHA512_DIGEST_SIZE
88 
89 #define WIN_CERT_UEFI_RSA2048_SIZE               256
90 
91 //
92 // Support hash types
93 //
94 #define HASHALG_SHA1                           0x00000000
95 #define HASHALG_SHA224                         0x00000001
96 #define HASHALG_SHA256                         0x00000002
97 #define HASHALG_SHA384                         0x00000003
98 #define HASHALG_SHA512                         0x00000004
99 #define HASHALG_RAW                            0x00000005
100 #define HASHALG_MAX                            0x00000005
101 
102 
103 #define SECUREBOOT_MENU_OPTION_SIGNATURE   SIGNATURE_32 ('S', 'b', 'M', 'u')
104 #define SECUREBOOT_MENU_ENTRY_SIGNATURE    SIGNATURE_32 ('S', 'b', 'M', 'r')
105 
106 typedef struct {
107   EFI_DEVICE_PATH_PROTOCOL  Header;
108   EFI_GUID                  Guid;
109   UINT8                     VendorDefinedData[1];
110 } VENDOR_DEVICE_PATH_WITH_DATA;
111 
112 typedef struct {
113   EFI_DEVICE_PATH_PROTOCOL  Header;
114   UINT16                    NetworkProtocol;
115   UINT16                    LoginOption;
116   UINT64                    Lun;
117   UINT16                    TargetPortalGroupTag;
118   CHAR16                    TargetName[1];
119 } ISCSI_DEVICE_PATH_WITH_NAME;
120 
121 typedef enum _FILE_EXPLORER_DISPLAY_CONTEXT {
122   FileExplorerDisplayFileSystem,
123   FileExplorerDisplayDirectory,
124   FileExplorerDisplayUnknown
125 } FILE_EXPLORER_DISPLAY_CONTEXT;
126 
127 typedef enum _FILE_EXPLORER_STATE {
128   FileExplorerStateInActive                      = 0,
129   FileExplorerStateEnrollPkFile,
130   FileExplorerStateEnrollKekFile,
131   FileExplorerStateEnrollSignatureFileToDb,
132   FileExplorerStateEnrollSignatureFileToDbx,
133   FileExplorerStateEnrollSignatureFileToDbt,
134   FileExplorerStateUnknown
135 } FILE_EXPLORER_STATE;
136 
137 typedef struct {
138   CHAR16  *Str;
139   UINTN   Len;
140   UINTN   Maxlen;
141 } POOL_PRINT;
142 
143 typedef
144 VOID
145 (*DEV_PATH_FUNCTION) (
146   IN OUT POOL_PRINT       *Str,
147   IN VOID                 *DevPath
148   );
149 
150 typedef struct {
151   UINT8             Type;
152   UINT8             SubType;
153   DEV_PATH_FUNCTION Function;
154 } DEVICE_PATH_STRING_TABLE;
155 
156 typedef struct {
157   UINTN             Signature;
158   LIST_ENTRY        Head;
159   UINTN             MenuNumber;
160 } SECUREBOOT_MENU_OPTION;
161 
162 extern  SECUREBOOT_MENU_OPTION     FsOptionMenu;
163 extern  SECUREBOOT_MENU_OPTION     DirectoryMenu;
164 
165 typedef struct {
166   UINTN             Signature;
167   LIST_ENTRY        Link;
168   UINTN             OptionNumber;
169   UINT16            *DisplayString;
170   UINT16            *HelpString;
171   EFI_STRING_ID     DisplayStringToken;
172   EFI_STRING_ID     HelpStringToken;
173   VOID              *FileContext;
174 } SECUREBOOT_MENU_ENTRY;
175 
176 typedef struct {
177   EFI_HANDLE                        Handle;
178   EFI_DEVICE_PATH_PROTOCOL          *DevicePath;
179   EFI_FILE_HANDLE                   FHandle;
180   UINT16                            *FileName;
181   EFI_FILE_SYSTEM_VOLUME_LABEL      *Info;
182 
183   BOOLEAN                           IsRoot;
184   BOOLEAN                           IsDir;
185   BOOLEAN                           IsRemovableMedia;
186   BOOLEAN                           IsLoadFile;
187   BOOLEAN                           IsBootLegacy;
188 } SECUREBOOT_FILE_CONTEXT;
189 
190 
191 //
192 // We define another format of 5th directory entry: security directory
193 //
194 typedef struct {
195   UINT32               Offset;      // Offset of certificate
196   UINT32               SizeOfCert;  // size of certificate appended
197 } EFI_IMAGE_SECURITY_DATA_DIRECTORY;
198 
199 typedef enum{
200   ImageType_IA32,
201   ImageType_X64
202 } IMAGE_TYPE;
203 
204 ///
205 /// HII specific Vendor Device Path definition.
206 ///
207 typedef struct {
208   VENDOR_DEVICE_PATH                VendorDevicePath;
209   EFI_DEVICE_PATH_PROTOCOL          End;
210 } HII_VENDOR_DEVICE_PATH;
211 
212 typedef struct {
213   UINTN                             Signature;
214 
215   EFI_HII_CONFIG_ACCESS_PROTOCOL    ConfigAccess;
216   EFI_HII_HANDLE                    HiiHandle;
217   EFI_HANDLE                        DriverHandle;
218 
219   FILE_EXPLORER_STATE               FeCurrentState;
220   FILE_EXPLORER_DISPLAY_CONTEXT     FeDisplayContext;
221 
222   SECUREBOOT_MENU_ENTRY             *MenuEntry;
223   SECUREBOOT_FILE_CONTEXT           *FileContext;
224 
225   EFI_GUID                          *SignatureGUID;
226 } SECUREBOOT_CONFIG_PRIVATE_DATA;
227 
228 extern SECUREBOOT_CONFIG_PRIVATE_DATA      mSecureBootConfigPrivateDateTemplate;
229 
230 #define SECUREBOOT_CONFIG_PRIVATE_DATA_SIGNATURE     SIGNATURE_32 ('S', 'E', 'C', 'B')
231 #define SECUREBOOT_CONFIG_PRIVATE_FROM_THIS(a)  CR (a, SECUREBOOT_CONFIG_PRIVATE_DATA, ConfigAccess, SECUREBOOT_CONFIG_PRIVATE_DATA_SIGNATURE)
232 
233 //
234 // Cryptograhpic Key Information
235 //
236 #pragma pack(1)
237 typedef struct _CPL_KEY_INFO {
238   UINT32        KeyLengthInBits;    // Key Length In Bits
239   UINT32        BlockSize;          // Operation Block Size in Bytes
240   UINT32        CipherBlockSize;    // Output Cipher Block Size in Bytes
241   UINT32        KeyType;            // Key Type
242   UINT32        CipherMode;         // Cipher Mode for Symmetric Algorithm
243   UINT32        Flags;              // Additional Key Property Flags
244 } CPL_KEY_INFO;
245 #pragma pack()
246 
247 
248 /**
249   Retrieves the size, in bytes, of the context buffer required for hash operations.
250 
251   @return  The size, in bytes, of the context buffer required for hash operations.
252 
253 **/
254 typedef
255 EFI_STATUS
256 (EFIAPI *HASH_GET_CONTEXT_SIZE)(
257   VOID
258   );
259 
260 /**
261   Initializes user-supplied memory pointed by HashContext as hash context for
262   subsequent use.
263 
264   If HashContext is NULL, then ASSERT().
265 
266   @param[in, out]  HashContext  Pointer to  Context being initialized.
267 
268   @retval TRUE   HASH context initialization succeeded.
269   @retval FALSE  HASH context initialization failed.
270 
271 **/
272 typedef
273 BOOLEAN
274 (EFIAPI *HASH_INIT)(
275   IN OUT  VOID  *HashContext
276   );
277 
278 
279 /**
280   Performs digest on a data buffer of the specified length. This function can
281   be called multiple times to compute the digest of long or discontinuous data streams.
282 
283   If HashContext is NULL, then ASSERT().
284 
285   @param[in, out]  HashContext  Pointer to the MD5 context.
286   @param[in]       Data        Pointer to the buffer containing the data to be hashed.
287   @param[in]       DataLength  Length of Data buffer in bytes.
288 
289   @retval TRUE   HASH data digest succeeded.
290   @retval FALSE  Invalid HASH context. After HashFinal function has been called, the
291                  HASH context cannot be reused.
292 
293 **/
294 typedef
295 BOOLEAN
296 (EFIAPI *HASH_UPDATE)(
297   IN OUT  VOID        *HashContext,
298   IN      CONST VOID  *Data,
299   IN      UINTN       DataLength
300   );
301 
302 /**
303   Completes hash computation and retrieves the digest value into the specified
304   memory. After this function has been called, the context cannot be used again.
305 
306   If HashContext is NULL, then ASSERT().
307   If HashValue is NULL, then ASSERT().
308 
309   @param[in, out]  HashContext  Pointer to the MD5 context
310   @param[out]      HashValue   Pointer to a buffer that receives the HASH digest
311                                value (16 bytes).
312 
313   @retval TRUE   HASH digest computation succeeded.
314   @retval FALSE  HASH digest computation failed.
315 
316 **/
317 typedef
318 BOOLEAN
319 (EFIAPI *HASH_FINAL)(
320   IN OUT  VOID   *HashContext,
321   OUT     UINT8  *HashValue
322   );
323 
324 //
325 // Hash Algorithm Table
326 //
327 typedef struct {
328   CHAR16                   *Name;           ///< Name for Hash Algorithm
329   UINTN                    DigestLength;    ///< Digest Length
330   UINT8                    *OidValue;       ///< Hash Algorithm OID ASN.1 Value
331   UINTN                    OidLength;       ///< Length of Hash OID Value
332   HASH_GET_CONTEXT_SIZE    GetContextSize;  ///< Pointer to Hash GetContentSize function
333   HASH_INIT                HashInit;        ///< Pointer to Hash Init function
334   HASH_UPDATE              HashUpdate;      ///< Pointer to Hash Update function
335   HASH_FINAL               HashFinal;       ///< Pointer to Hash Final function
336 } HASH_TABLE;
337 
338 typedef struct {
339   WIN_CERTIFICATE Hdr;
340   UINT8           CertData[1];
341 } WIN_CERTIFICATE_EFI_PKCS;
342 
343 
344 /**
345   This function publish the SecureBoot configuration Form.
346 
347   @param[in, out]  PrivateData   Points to SecureBoot configuration private data.
348 
349   @retval EFI_SUCCESS            HII Form is installed successfully.
350   @retval EFI_OUT_OF_RESOURCES   Not enough resource for HII Form installation.
351   @retval Others                 Other errors as indicated.
352 
353 **/
354 EFI_STATUS
355 InstallSecureBootConfigForm (
356   IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA  *PrivateData
357   );
358 
359 
360 /**
361   This function removes SecureBoot configuration Form.
362 
363   @param[in, out]  PrivateData   Points to SecureBoot configuration private data.
364 
365 **/
366 VOID
367 UninstallSecureBootConfigForm (
368   IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA    *PrivateData
369   );
370 
371 
372 /**
373   This function allows a caller to extract the current configuration for one
374   or more named elements from the target driver.
375 
376   @param[in]   This              Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
377   @param[in]   Request           A null-terminated Unicode string in
378                                  <ConfigRequest> format.
379   @param[out]  Progress          On return, points to a character in the Request
380                                  string. Points to the string's null terminator if
381                                  request was successful. Points to the most recent
382                                  '&' before the first failing name/value pair (or
383                                  the beginning of the string if the failure is in
384                                  the first name/value pair) if the request was not
385                                  successful.
386   @param[out]  Results           A null-terminated Unicode string in
387                                  <ConfigAltResp> format which has all values filled
388                                  in for the names in the Request string. String to
389                                  be allocated by the called function.
390 
391   @retval EFI_SUCCESS            The Results is filled with the requested values.
392   @retval EFI_OUT_OF_RESOURCES   Not enough memory to store the results.
393   @retval EFI_INVALID_PARAMETER  Request is illegal syntax, or unknown name.
394   @retval EFI_NOT_FOUND          Routing data doesn't match any storage in this
395                                  driver.
396 
397 **/
398 EFI_STATUS
399 EFIAPI
400 SecureBootExtractConfig (
401   IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL        *This,
402   IN CONST EFI_STRING                            Request,
403        OUT EFI_STRING                            *Progress,
404        OUT EFI_STRING                            *Results
405   );
406 
407 
408 /**
409   This function processes the results of changes in configuration.
410 
411   @param[in]  This               Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
412   @param[in]  Configuration      A null-terminated Unicode string in <ConfigResp>
413                                  format.
414   @param[out] Progress           A pointer to a string filled in with the offset of
415                                  the most recent '&' before the first failing
416                                  name/value pair (or the beginning of the string if
417                                  the failure is in the first name/value pair) or
418                                  the terminating NULL if all was successful.
419 
420   @retval EFI_SUCCESS            The Results is processed successfully.
421   @retval EFI_INVALID_PARAMETER  Configuration is NULL.
422   @retval EFI_NOT_FOUND          Routing data doesn't match any storage in this
423                                  driver.
424 
425 **/
426 EFI_STATUS
427 EFIAPI
428 SecureBootRouteConfig (
429   IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL      *This,
430   IN CONST EFI_STRING                          Configuration,
431        OUT EFI_STRING                          *Progress
432   );
433 
434 
435 /**
436   This function processes the results of changes in configuration.
437 
438   @param[in]  This               Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
439   @param[in]  Action             Specifies the type of action taken by the browser.
440   @param[in]  QuestionId         A unique value which is sent to the original
441                                  exporting driver so that it can identify the type
442                                  of data to expect.
443   @param[in]  Type               The type of value for the question.
444   @param[in]  Value              A pointer to the data being sent to the original
445                                  exporting driver.
446   @param[out] ActionRequest      On return, points to the action requested by the
447                                  callback function.
448 
449   @retval EFI_SUCCESS            The callback successfully handled the action.
450   @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the
451                                  variable and its data.
452   @retval EFI_DEVICE_ERROR       The variable could not be saved.
453   @retval EFI_UNSUPPORTED        The specified Action is not supported by the
454                                  callback.
455 
456 **/
457 EFI_STATUS
458 EFIAPI
459 SecureBootCallback (
460   IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL      *This,
461   IN     EFI_BROWSER_ACTION                    Action,
462   IN     EFI_QUESTION_ID                       QuestionId,
463   IN     UINT8                                 Type,
464   IN     EFI_IFR_TYPE_VALUE                    *Value,
465      OUT EFI_BROWSER_ACTION_REQUEST            *ActionRequest
466   );
467 
468 
469 /**
470   This function converts an input device structure to a Unicode string.
471 
472   @param[in] DevPath                  A pointer to the device path structure.
473 
474   @return A new allocated Unicode string that represents the device path.
475 
476 **/
477 CHAR16 *
478 EFIAPI
479 DevicePathToStr (
480   IN EFI_DEVICE_PATH_PROTOCOL     *DevPath
481   );
482 
483 
484 /**
485   Clean up the dynamic opcode at label and form specified by both LabelId.
486 
487   @param[in] LabelId         It is both the Form ID and Label ID for opcode deletion.
488   @param[in] PrivateData     Module private data.
489 
490 **/
491 VOID
492 CleanUpPage (
493   IN UINT16                           LabelId,
494   IN SECUREBOOT_CONFIG_PRIVATE_DATA   *PrivateData
495   );
496 
497 
498 /**
499   Update the file explorer page with the refreshed file system.
500 
501   @param[in] PrivateData     Module private data.
502   @param[in] KeyValue        Key value to identify the type of data to expect.
503 
504   @retval  TRUE           Inform the caller to create a callback packet to exit file explorer.
505   @retval  FALSE          Indicate that there is no need to exit file explorer.
506 
507 **/
508 BOOLEAN
509 UpdateFileExplorer (
510   IN SECUREBOOT_CONFIG_PRIVATE_DATA   *PrivateData,
511   IN UINT16                           KeyValue
512   );
513 
514 
515 /**
516   Free resources allocated in Allocate Rountine.
517 
518   @param[in, out]  MenuOption        Menu to be freed
519 
520 **/
521 VOID
522 FreeMenu (
523   IN OUT SECUREBOOT_MENU_OPTION        *MenuOption
524   );
525 
526 
527 /**
528   Read file content into BufferPtr, the size of the allocate buffer
529   is *FileSize plus AddtionAllocateSize.
530 
531   @param[in]       FileHandle            The file to be read.
532   @param[in, out]  BufferPtr             Pointers to the pointer of allocated buffer.
533   @param[out]      FileSize              Size of input file
534   @param[in]       AddtionAllocateSize   Addtion size the buffer need to be allocated.
535                                          In case the buffer need to contain others besides the file content.
536 
537   @retval   EFI_SUCCESS                  The file was read into the buffer.
538   @retval   EFI_INVALID_PARAMETER        A parameter was invalid.
539   @retval   EFI_OUT_OF_RESOURCES         A memory allocation failed.
540   @retval   others                       Unexpected error.
541 
542 **/
543 EFI_STATUS
544 ReadFileContent (
545   IN      EFI_FILE_HANDLE           FileHandle,
546   IN OUT  VOID                      **BufferPtr,
547      OUT  UINTN                     *FileSize,
548   IN      UINTN                     AddtionAllocateSize
549   );
550 
551 
552 /**
553   Close an open file handle.
554 
555   @param[in] FileHandle           The file handle to close.
556 
557 **/
558 VOID
559 CloseFile (
560   IN EFI_FILE_HANDLE   FileHandle
561   );
562 
563 
564 /**
565   Converts a nonnegative integer to an octet string of a specified length.
566 
567   @param[in]   Integer          Pointer to the nonnegative integer to be converted
568   @param[in]   IntSizeInWords   Length of integer buffer in words
569   @param[out]  OctetString      Converted octet string of the specified length
570   @param[in]   OSSizeInBytes    Intended length of resulting octet string in bytes
571 
572 Returns:
573 
574   @retval   EFI_SUCCESS            Data conversion successfully
575   @retval   EFI_BUFFER_TOOL_SMALL  Buffer is too small for output string
576 
577 **/
578 EFI_STATUS
579 EFIAPI
580 Int2OctStr (
581   IN     CONST UINTN       *Integer,
582   IN     UINTN             IntSizeInWords,
583      OUT UINT8             *OctetString,
584   IN     UINTN             OSSizeInBytes
585   );
586 
587 
588 /**
589   Convert a String to Guid Value.
590 
591   @param[in]   Str        Specifies the String to be converted.
592   @param[in]   StrLen     Number of Unicode Characters of String (exclusive \0)
593   @param[out]  Guid       Return the result Guid value.
594 
595   @retval    EFI_SUCCESS           The operation is finished successfully.
596   @retval    EFI_NOT_FOUND         Invalid string.
597 
598 **/
599 EFI_STATUS
600 StringToGuid (
601   IN   CHAR16           *Str,
602   IN   UINTN            StrLen,
603   OUT  EFI_GUID         *Guid
604   );
605 
606 
607 /**
608   Worker function that prints an EFI_GUID into specified Buffer.
609 
610   @param[in]     Guid          Pointer to GUID to print.
611   @param[in]     Buffer        Buffer to print Guid into.
612   @param[in]     BufferSize    Size of Buffer.
613 
614   @retval    Number of characters printed.
615 
616 **/
617 UINTN
618 GuidToString (
619   IN  EFI_GUID  *Guid,
620   IN  CHAR16    *Buffer,
621   IN  UINTN     BufferSize
622   );
623 
624 #endif
625