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