1 | /** @file
|
---|
2 | FMP Authentication PKCS7 handler.
|
---|
3 | Provide generic FMP authentication functions for DXE/PEI post memory phase.
|
---|
4 |
|
---|
5 | Caution: This module requires additional review when modified.
|
---|
6 | This module will have external input - capsule image.
|
---|
7 | This external input must be validated carefully to avoid security issue like
|
---|
8 | buffer overflow, integer overflow.
|
---|
9 |
|
---|
10 | FmpAuthenticatedHandlerPkcs7(), AuthenticateFmpImage() will receive
|
---|
11 | untrusted input and do basic validation.
|
---|
12 |
|
---|
13 | Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>
|
---|
14 | SPDX-License-Identifier: BSD-2-Clause-Patent
|
---|
15 |
|
---|
16 | **/
|
---|
17 |
|
---|
18 | #include <Uefi.h>
|
---|
19 |
|
---|
20 | #include <Guid/SystemResourceTable.h>
|
---|
21 | #include <Guid/FirmwareContentsSigned.h>
|
---|
22 | #include <Guid/WinCertificate.h>
|
---|
23 |
|
---|
24 | #include <Library/BaseLib.h>
|
---|
25 | #include <Library/BaseMemoryLib.h>
|
---|
26 | #include <Library/DebugLib.h>
|
---|
27 | #include <Library/MemoryAllocationLib.h>
|
---|
28 | #include <Library/BaseCryptLib.h>
|
---|
29 | #include <Library/FmpAuthenticationLib.h>
|
---|
30 | #include <Library/PcdLib.h>
|
---|
31 | #include <Protocol/FirmwareManagement.h>
|
---|
32 | #include <Guid/SystemResourceTable.h>
|
---|
33 |
|
---|
34 | /**
|
---|
35 | The handler is used to do the authentication for FMP capsule based upon
|
---|
36 | EFI_FIRMWARE_IMAGE_AUTHENTICATION.
|
---|
37 |
|
---|
38 | Caution: This function may receive untrusted input.
|
---|
39 |
|
---|
40 | This function assumes the caller AuthenticateFmpImage()
|
---|
41 | already did basic validation for EFI_FIRMWARE_IMAGE_AUTHENTICATION.
|
---|
42 |
|
---|
43 | @param[in] Image Points to an FMP authentication image, started from EFI_FIRMWARE_IMAGE_AUTHENTICATION.
|
---|
44 | @param[in] ImageSize Size of the authentication image in bytes.
|
---|
45 | @param[in] PublicKeyData The public key data used to validate the signature.
|
---|
46 | @param[in] PublicKeyDataLength The length of the public key data.
|
---|
47 |
|
---|
48 | @retval RETURN_SUCCESS Authentication pass.
|
---|
49 | The LastAttemptStatus should be LAST_ATTEMPT_STATUS_SUCCESS.
|
---|
50 | @retval RETURN_SECURITY_VIOLATION Authentication fail.
|
---|
51 | The LastAttemptStatus should be LAST_ATTEMPT_STATUS_ERROR_AUTH_ERROR.
|
---|
52 | @retval RETURN_INVALID_PARAMETER The image is in an invalid format.
|
---|
53 | The LastAttemptStatus should be LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT.
|
---|
54 | @retval RETURN_OUT_OF_RESOURCES No Authentication handler associated with CertType.
|
---|
55 | The LastAttemptStatus should be LAST_ATTEMPT_STATUS_ERROR_INSUFFICIENT_RESOURCES.
|
---|
56 | **/
|
---|
57 | RETURN_STATUS
|
---|
58 | FmpAuthenticatedHandlerPkcs7 (
|
---|
59 | IN EFI_FIRMWARE_IMAGE_AUTHENTICATION *Image,
|
---|
60 | IN UINTN ImageSize,
|
---|
61 | IN CONST UINT8 *PublicKeyData,
|
---|
62 | IN UINTN PublicKeyDataLength
|
---|
63 | )
|
---|
64 | {
|
---|
65 | RETURN_STATUS Status;
|
---|
66 | BOOLEAN CryptoStatus;
|
---|
67 | VOID *P7Data;
|
---|
68 | UINTN P7Length;
|
---|
69 | VOID *TempBuffer;
|
---|
70 |
|
---|
71 | DEBUG ((DEBUG_INFO, "FmpAuthenticatedHandlerPkcs7 - Image: 0x%08x - 0x%08x\n", (UINTN)Image, (UINTN)ImageSize));
|
---|
72 |
|
---|
73 | P7Length = Image->AuthInfo.Hdr.dwLength - (OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData));
|
---|
74 | P7Data = Image->AuthInfo.CertData;
|
---|
75 |
|
---|
76 | // It is a signature across the variable data and the Monotonic Count value.
|
---|
77 | TempBuffer = AllocatePool (ImageSize - Image->AuthInfo.Hdr.dwLength);
|
---|
78 | if (TempBuffer == NULL) {
|
---|
79 | DEBUG ((DEBUG_ERROR, "FmpAuthenticatedHandlerPkcs7: TempBuffer == NULL\n"));
|
---|
80 | Status = RETURN_OUT_OF_RESOURCES;
|
---|
81 | goto Done;
|
---|
82 | }
|
---|
83 |
|
---|
84 | CopyMem (
|
---|
85 | TempBuffer,
|
---|
86 | (UINT8 *)Image + sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength,
|
---|
87 | ImageSize - sizeof (Image->MonotonicCount) - Image->AuthInfo.Hdr.dwLength
|
---|
88 | );
|
---|
89 | CopyMem (
|
---|
90 | (UINT8 *)TempBuffer + ImageSize - sizeof (Image->MonotonicCount) - Image->AuthInfo.Hdr.dwLength,
|
---|
91 | &Image->MonotonicCount,
|
---|
92 | sizeof (Image->MonotonicCount)
|
---|
93 | );
|
---|
94 | CryptoStatus = Pkcs7Verify (
|
---|
95 | P7Data,
|
---|
96 | P7Length,
|
---|
97 | PublicKeyData,
|
---|
98 | PublicKeyDataLength,
|
---|
99 | (UINT8 *)TempBuffer,
|
---|
100 | ImageSize - Image->AuthInfo.Hdr.dwLength
|
---|
101 | );
|
---|
102 | FreePool (TempBuffer);
|
---|
103 | if (!CryptoStatus) {
|
---|
104 | //
|
---|
105 | // If PKCS7 signature verification fails, AUTH tested failed bit is set.
|
---|
106 | //
|
---|
107 | DEBUG ((DEBUG_ERROR, "FmpAuthenticatedHandlerPkcs7: Pkcs7Verify() failed\n"));
|
---|
108 | Status = RETURN_SECURITY_VIOLATION;
|
---|
109 | goto Done;
|
---|
110 | }
|
---|
111 |
|
---|
112 | DEBUG ((DEBUG_INFO, "FmpAuthenticatedHandlerPkcs7: PASS verification\n"));
|
---|
113 |
|
---|
114 | Status = RETURN_SUCCESS;
|
---|
115 |
|
---|
116 | Done:
|
---|
117 | return Status;
|
---|
118 | }
|
---|
119 |
|
---|
120 | /**
|
---|
121 | The function is used to do the authentication for FMP capsule based upon
|
---|
122 | EFI_FIRMWARE_IMAGE_AUTHENTICATION.
|
---|
123 |
|
---|
124 | The FMP capsule image should start with EFI_FIRMWARE_IMAGE_AUTHENTICATION,
|
---|
125 | followed by the payload.
|
---|
126 |
|
---|
127 | If the return status is RETURN_SUCCESS, the caller may continue the rest
|
---|
128 | FMP update process.
|
---|
129 | If the return status is NOT RETURN_SUCCESS, the caller should stop the FMP
|
---|
130 | update process and convert the return status to LastAttemptStatus
|
---|
131 | to indicate that FMP update fails.
|
---|
132 | The LastAttemptStatus can be got from ESRT table or via
|
---|
133 | EFI_FIRMWARE_MANAGEMENT_PROTOCOL.GetImageInfo().
|
---|
134 |
|
---|
135 | Caution: This function may receive untrusted input.
|
---|
136 |
|
---|
137 | @param[in] Image Points to an FMP authentication image, started from EFI_FIRMWARE_IMAGE_AUTHENTICATION.
|
---|
138 | @param[in] ImageSize Size of the authentication image in bytes.
|
---|
139 | @param[in] PublicKeyData The public key data used to validate the signature.
|
---|
140 | @param[in] PublicKeyDataLength The length of the public key data.
|
---|
141 |
|
---|
142 | @retval RETURN_SUCCESS Authentication pass.
|
---|
143 | The LastAttemptStatus should be LAST_ATTEMPT_STATUS_SUCCESS.
|
---|
144 | @retval RETURN_SECURITY_VIOLATION Authentication fail.
|
---|
145 | The LastAttemptStatus should be LAST_ATTEMPT_STATUS_ERROR_AUTH_ERROR.
|
---|
146 | @retval RETURN_INVALID_PARAMETER The image is in an invalid format.
|
---|
147 | The LastAttemptStatus should be LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT.
|
---|
148 | @retval RETURN_UNSUPPORTED No Authentication handler associated with CertType.
|
---|
149 | The LastAttemptStatus should be LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT.
|
---|
150 | @retval RETURN_UNSUPPORTED Image or ImageSize is invalid.
|
---|
151 | The LastAttemptStatus should be LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT.
|
---|
152 | @retval RETURN_OUT_OF_RESOURCES No Authentication handler associated with CertType.
|
---|
153 | The LastAttemptStatus should be LAST_ATTEMPT_STATUS_ERROR_INSUFFICIENT_RESOURCES.
|
---|
154 | **/
|
---|
155 | RETURN_STATUS
|
---|
156 | EFIAPI
|
---|
157 | AuthenticateFmpImage (
|
---|
158 | IN EFI_FIRMWARE_IMAGE_AUTHENTICATION *Image,
|
---|
159 | IN UINTN ImageSize,
|
---|
160 | IN CONST UINT8 *PublicKeyData,
|
---|
161 | IN UINTN PublicKeyDataLength
|
---|
162 | )
|
---|
163 | {
|
---|
164 | GUID *CertType;
|
---|
165 | EFI_STATUS Status;
|
---|
166 |
|
---|
167 | if ((Image == NULL) || (ImageSize == 0)) {
|
---|
168 | return RETURN_UNSUPPORTED;
|
---|
169 | }
|
---|
170 |
|
---|
171 | if (ImageSize < sizeof (EFI_FIRMWARE_IMAGE_AUTHENTICATION)) {
|
---|
172 | DEBUG ((DEBUG_ERROR, "AuthenticateFmpImage - ImageSize too small\n"));
|
---|
173 | return RETURN_INVALID_PARAMETER;
|
---|
174 | }
|
---|
175 |
|
---|
176 | if (Image->AuthInfo.Hdr.dwLength <= OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData)) {
|
---|
177 | DEBUG ((DEBUG_ERROR, "AuthenticateFmpImage - dwLength too small\n"));
|
---|
178 | return RETURN_INVALID_PARAMETER;
|
---|
179 | }
|
---|
180 |
|
---|
181 | if ((UINTN)Image->AuthInfo.Hdr.dwLength > MAX_UINTN - sizeof (UINT64)) {
|
---|
182 | DEBUG ((DEBUG_ERROR, "AuthenticateFmpImage - dwLength too big\n"));
|
---|
183 | return RETURN_INVALID_PARAMETER;
|
---|
184 | }
|
---|
185 |
|
---|
186 | if (ImageSize <= sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength) {
|
---|
187 | DEBUG ((DEBUG_ERROR, "AuthenticateFmpImage - ImageSize too small\n"));
|
---|
188 | return RETURN_INVALID_PARAMETER;
|
---|
189 | }
|
---|
190 |
|
---|
191 | if (Image->AuthInfo.Hdr.wRevision != 0x0200) {
|
---|
192 | DEBUG ((DEBUG_ERROR, "AuthenticateFmpImage - wRevision: 0x%02x, expect - 0x%02x\n", (UINTN)Image->AuthInfo.Hdr.wRevision, (UINTN)0x0200));
|
---|
193 | return RETURN_INVALID_PARAMETER;
|
---|
194 | }
|
---|
195 |
|
---|
196 | if (Image->AuthInfo.Hdr.wCertificateType != WIN_CERT_TYPE_EFI_GUID) {
|
---|
197 | DEBUG ((DEBUG_ERROR, "AuthenticateFmpImage - wCertificateType: 0x%02x, expect - 0x%02x\n", (UINTN)Image->AuthInfo.Hdr.wCertificateType, (UINTN)WIN_CERT_TYPE_EFI_GUID));
|
---|
198 | return RETURN_INVALID_PARAMETER;
|
---|
199 | }
|
---|
200 |
|
---|
201 | CertType = &Image->AuthInfo.CertType;
|
---|
202 | DEBUG ((DEBUG_INFO, "AuthenticateFmpImage - CertType: %g\n", CertType));
|
---|
203 |
|
---|
204 | if (CompareGuid (&gEfiCertPkcs7Guid, CertType)) {
|
---|
205 | //
|
---|
206 | // Call the match handler to extract raw data for the input section data.
|
---|
207 | //
|
---|
208 | Status = FmpAuthenticatedHandlerPkcs7 (
|
---|
209 | Image,
|
---|
210 | ImageSize,
|
---|
211 | PublicKeyData,
|
---|
212 | PublicKeyDataLength
|
---|
213 | );
|
---|
214 | return Status;
|
---|
215 | }
|
---|
216 |
|
---|
217 | //
|
---|
218 | // Not found, the input guided section is not supported.
|
---|
219 | //
|
---|
220 | return RETURN_UNSUPPORTED;
|
---|
221 | }
|
---|