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