1 /** @file
2 
3   This library registers CRC32 guided section handler
4   to parse CRC32 encapsulation section and extract raw data.
5   It uses UEFI boot service CalculateCrc32 to authenticate 32 bit CRC value.
6 
7 Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
8 SPDX-License-Identifier: BSD-2-Clause-Patent
9 
10 **/
11 
12 #include <PiDxe.h>
13 #include <Guid/Crc32GuidedSectionExtraction.h>
14 #include <Protocol/SecurityPolicy.h>
15 #include <Library/ExtractGuidedSectionLib.h>
16 #include <Library/DebugLib.h>
17 #include <Library/BaseMemoryLib.h>
18 #include <Library/UefiBootServicesTableLib.h>
19 
20 ///
21 /// CRC32 Guided Section header
22 ///
23 typedef struct {
24   EFI_GUID_DEFINED_SECTION  GuidedSectionHeader; ///< EFI guided section header
25   UINT32                    CRC32Checksum;       ///< 32bit CRC check sum
26 } CRC32_SECTION_HEADER;
27 
28 typedef struct {
29   EFI_GUID_DEFINED_SECTION2 GuidedSectionHeader; ///< EFI guided section header
30   UINT32                    CRC32Checksum;       ///< 32bit CRC check sum
31 } CRC32_SECTION2_HEADER;
32 
33 /**
34 
35   GetInfo gets raw data size and attribute of the input guided section.
36   It first checks whether the input guid section is supported.
37   If not, EFI_INVALID_PARAMETER will return.
38 
39   @param InputSection       Buffer containing the input GUIDed section to be processed.
40   @param OutputBufferSize   The size of OutputBuffer.
41   @param ScratchBufferSize  The size of ScratchBuffer.
42   @param SectionAttribute   The attribute of the input guided section.
43 
44   @retval EFI_SUCCESS            The size of destination buffer, the size of scratch buffer and
45                                  the attribute of the input section are successfully retrieved.
46   @retval EFI_INVALID_PARAMETER  The GUID in InputSection does not match this instance guid.
47 
48 **/
49 EFI_STATUS
50 EFIAPI
Crc32GuidedSectionGetInfo(IN CONST VOID * InputSection,OUT UINT32 * OutputBufferSize,OUT UINT32 * ScratchBufferSize,OUT UINT16 * SectionAttribute)51 Crc32GuidedSectionGetInfo (
52   IN  CONST VOID  *InputSection,
53   OUT UINT32      *OutputBufferSize,
54   OUT UINT32      *ScratchBufferSize,
55   OUT UINT16      *SectionAttribute
56   )
57 {
58   if (IS_SECTION2 (InputSection)) {
59     //
60     // Check whether the input guid section is recognized.
61     //
62     if (!CompareGuid (
63         &gEfiCrc32GuidedSectionExtractionGuid,
64         &(((EFI_GUID_DEFINED_SECTION2 *) InputSection)->SectionDefinitionGuid))) {
65       return EFI_INVALID_PARAMETER;
66     }
67     //
68     // Retrieve the size and attribute of the input section data.
69     //
70     *SectionAttribute  = ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->Attributes;
71     *ScratchBufferSize = 0;
72     *OutputBufferSize  = SECTION2_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset;
73   } else {
74     //
75     // Check whether the input guid section is recognized.
76     //
77     if (!CompareGuid (
78         &gEfiCrc32GuidedSectionExtractionGuid,
79         &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid))) {
80       return EFI_INVALID_PARAMETER;
81     }
82     //
83     // Retrieve the size and attribute of the input section data.
84     //
85     *SectionAttribute  = ((EFI_GUID_DEFINED_SECTION *) InputSection)->Attributes;
86     *ScratchBufferSize = 0;
87     *OutputBufferSize  = SECTION_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset;
88   }
89 
90   return EFI_SUCCESS;
91 }
92 
93 /**
94 
95   Extraction handler tries to extract raw data from the input guided section.
96   It also does authentication check for 32bit CRC value in the input guided section.
97   It first checks whether the input guid section is supported.
98   If not, EFI_INVALID_PARAMETER will return.
99 
100   @param InputSection    Buffer containing the input GUIDed section to be processed.
101   @param OutputBuffer    Buffer to contain the output raw data allocated by the caller.
102   @param ScratchBuffer   A pointer to a caller-allocated buffer for function internal use.
103   @param AuthenticationStatus A pointer to a caller-allocated UINT32 that indicates the
104                               authentication status of the output buffer.
105 
106   @retval EFI_SUCCESS            Section Data and Auth Status is extracted successfully.
107   @retval EFI_INVALID_PARAMETER  The GUID in InputSection does not match this instance guid.
108 
109 **/
110 EFI_STATUS
111 EFIAPI
Crc32GuidedSectionHandler(IN CONST VOID * InputSection,OUT VOID ** OutputBuffer,IN VOID * ScratchBuffer,OPTIONAL OUT UINT32 * AuthenticationStatus)112 Crc32GuidedSectionHandler (
113   IN CONST  VOID    *InputSection,
114   OUT       VOID    **OutputBuffer,
115   IN        VOID    *ScratchBuffer,        OPTIONAL
116   OUT       UINT32  *AuthenticationStatus
117   )
118 {
119   EFI_STATUS                Status;
120   UINT32                    SectionCrc32Checksum;
121   UINT32                    Crc32Checksum;
122   UINT32                    OutputBufferSize;
123   VOID                      *DummyInterface;
124 
125   if (IS_SECTION2 (InputSection)) {
126     //
127     // Check whether the input guid section is recognized.
128     //
129     if (!CompareGuid (
130         &gEfiCrc32GuidedSectionExtractionGuid,
131         &(((EFI_GUID_DEFINED_SECTION2 *) InputSection)->SectionDefinitionGuid))) {
132       return EFI_INVALID_PARAMETER;
133     }
134 
135     //
136     // Get section Crc32 checksum.
137     //
138     SectionCrc32Checksum = ((CRC32_SECTION2_HEADER *) InputSection)->CRC32Checksum;
139     *OutputBuffer      = (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset;
140     OutputBufferSize   = SECTION2_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset;
141 
142     //
143     // Implicitly CRC32 GUIDed section should have STATUS_VALID bit set
144     //
145     ASSERT (((EFI_GUID_DEFINED_SECTION2 *) InputSection)->Attributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID);
146     *AuthenticationStatus = EFI_AUTH_STATUS_IMAGE_SIGNED;
147   } else {
148     //
149     // Check whether the input guid section is recognized.
150     //
151     if (!CompareGuid (
152         &gEfiCrc32GuidedSectionExtractionGuid,
153         &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid))) {
154       return EFI_INVALID_PARAMETER;
155     }
156 
157     //
158     // Get section Crc32 checksum.
159     //
160     SectionCrc32Checksum = ((CRC32_SECTION_HEADER *) InputSection)->CRC32Checksum;
161     *OutputBuffer      = (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset;
162     OutputBufferSize   = SECTION_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset;
163 
164     //
165     // Implicitly CRC32 GUIDed section should have STATUS_VALID bit set
166     //
167     ASSERT (((EFI_GUID_DEFINED_SECTION *) InputSection)->Attributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID);
168     *AuthenticationStatus = EFI_AUTH_STATUS_IMAGE_SIGNED;
169   }
170 
171   //
172   // Init Checksum value to Zero.
173   //
174   Crc32Checksum = 0;
175 
176   //
177   // Check whether there exists EFI_SECURITY_POLICY_PROTOCOL_GUID.
178   //
179   Status = gBS->LocateProtocol (&gEfiSecurityPolicyProtocolGuid, NULL, &DummyInterface);
180   if (!EFI_ERROR (Status)) {
181     //
182     // If SecurityPolicy Protocol exist, AUTH platform override bit is set.
183     //
184     *AuthenticationStatus |= EFI_AUTH_STATUS_PLATFORM_OVERRIDE;
185   } else {
186     //
187     // Calculate CRC32 Checksum of Image
188     //
189     Status = gBS->CalculateCrc32 (*OutputBuffer, OutputBufferSize, &Crc32Checksum);
190     if (Status == EFI_SUCCESS) {
191       if (Crc32Checksum != SectionCrc32Checksum) {
192         //
193         // If Crc32 checksum is not matched, AUTH tested failed bit is set.
194         //
195         *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
196       }
197     } else {
198       //
199       // If Crc32 checksum is not calculated, AUTH not tested bit is set.
200       //
201       *AuthenticationStatus |= EFI_AUTH_STATUS_NOT_TESTED;
202     }
203   }
204 
205   return EFI_SUCCESS;
206 }
207 
208 /**
209   Register the handler to extract CRC32 guided section.
210 
211   @param  ImageHandle  ImageHandle of the loaded driver.
212   @param  SystemTable  Pointer to the EFI System Table.
213 
214   @retval  EFI_SUCCESS            Register successfully.
215   @retval  EFI_OUT_OF_RESOURCES   No enough memory to register this handler.
216 **/
217 EFI_STATUS
218 EFIAPI
DxeCrc32GuidedSectionExtractLibConstructor(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)219 DxeCrc32GuidedSectionExtractLibConstructor (
220   IN EFI_HANDLE        ImageHandle,
221   IN EFI_SYSTEM_TABLE  *SystemTable
222   )
223 {
224   return ExtractGuidedSectionRegisterHandlers (
225           &gEfiCrc32GuidedSectionExtractionGuid,
226           Crc32GuidedSectionGetInfo,
227           Crc32GuidedSectionHandler
228           );
229 }
230 
231