diff options
| author | Soumya Sambu <soumya.sambu@windriver.com> | 2024-06-28 08:37:27 +0000 |
|---|---|---|
| committer | Steve Sakoman <steve@sakoman.com> | 2024-12-09 07:54:02 -0800 |
| commit | ecf0eb5229631497429dbbc91d885b93a94c38c9 (patch) | |
| tree | b76127e7aff8ac7536c62eefeed714fe46b1eff3 /meta | |
| parent | 0bffb5eed1e8c9469b9c6e0d77f959dc9ade9c6a (diff) | |
| download | poky-ecf0eb5229631497429dbbc91d885b93a94c38c9.tar.gz | |
ovmf: Fix CVE-2022-36763
EDK2 is susceptible to a vulnerability in the Tcg2MeasureGptTable()
function, allowing a user to trigger a heap buffer overflow via a local
network. Successful exploitation of this vulnerability may result in a
compromise of confidentiality, integrity, and/or availability.
References:
https://nvd.nist.gov/vuln/detail/CVE-2022-36763
Upstream-patches:
https://github.com/tianocore/edk2/commit/224446543206450ddb5830e6abd026d61d3c7f4b
https://github.com/tianocore/edk2/commit/4776a1b39ee08fc45c70c1eab5a0195f325000d3
https://github.com/tianocore/edk2/commit/1ddcb9fc6b4164e882687b031e8beacfcf7df29e
(From OE-Core rev: 26db24533f9f32c32189e4621102b628a9ea6729)
Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
Diffstat (limited to 'meta')
| -rw-r--r-- | meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0001.patch | 985 | ||||
| -rw-r--r-- | meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0002.patch | 889 | ||||
| -rw-r--r-- | meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0003.patch | 55 | ||||
| -rw-r--r-- | meta/recipes-core/ovmf/ovmf_git.bb | 3 |
4 files changed, 1932 insertions, 0 deletions
diff --git a/meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0001.patch b/meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0001.patch new file mode 100644 index 0000000000..93cefe7740 --- /dev/null +++ b/meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0001.patch | |||
| @@ -0,0 +1,985 @@ | |||
| 1 | From 224446543206450ddb5830e6abd026d61d3c7f4b Mon Sep 17 00:00:00 2001 | ||
| 2 | From: "Douglas Flick [MSFT]" <doug.edk2@gmail.com> | ||
| 3 | Date: Fri, 12 Jan 2024 02:16:01 +0800 | ||
| 4 | Subject: [PATCH] SecurityPkg: DxeTpm2MeasureBootLib: SECURITY PATCH 4117 - CVE | ||
| 5 | 2022-36763 | ||
| 6 | |||
| 7 | This commit contains the patch files and tests for DxeTpm2MeasureBootLib | ||
| 8 | CVE 2022-36763. | ||
| 9 | |||
| 10 | Cc: Jiewen Yao <jiewen.yao@intel.com> | ||
| 11 | |||
| 12 | Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com> | ||
| 13 | |||
| 14 | CVE: CVE-2022-36763 | ||
| 15 | |||
| 16 | Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/224446543206450ddb5830e6abd026d61d3c7f4b] | ||
| 17 | |||
| 18 | Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com> | ||
| 19 | --- | ||
| 20 | .../DxeTpm2MeasureBootLib.c | 69 ++-- | ||
| 21 | .../DxeTpm2MeasureBootLib.inf | 4 +- | ||
| 22 | .../DxeTpm2MeasureBootLibSanitization.c | 275 ++++++++++++++++ | ||
| 23 | .../DxeTpm2MeasureBootLibSanitization.h | 113 +++++++ | ||
| 24 | .../DxeTpm2MeasureBootLibSanitizationTest.c | 303 ++++++++++++++++++ | ||
| 25 | ...Tpm2MeasureBootLibSanitizationTestHost.inf | 28 ++ | ||
| 26 | SecurityPkg/SecurityPkg.ci.yaml | 1 + | ||
| 27 | 7 files changed, 763 insertions(+), 30 deletions(-) | ||
| 28 | create mode 100644 SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.c | ||
| 29 | create mode 100644 SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.h | ||
| 30 | create mode 100644 SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTest.c | ||
| 31 | create mode 100644 SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTestHost.inf | ||
| 32 | |||
| 33 | diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c | ||
| 34 | index 36a256a7af..0475103d6e 100644 | ||
| 35 | --- a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c | ||
| 36 | +++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c | ||
| 37 | @@ -20,6 +20,8 @@ Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR> | ||
| 38 | (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR> | ||
| 39 | SPDX-License-Identifier: BSD-2-Clause-Patent | ||
| 40 | |||
| 41 | +Copyright (c) Microsoft Corporation.<BR> | ||
| 42 | +SPDX-License-Identifier: BSD-2-Clause-Patent | ||
| 43 | **/ | ||
| 44 | |||
| 45 | #include <PiDxe.h> | ||
| 46 | @@ -44,6 +46,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent | ||
| 47 | #include <Library/HobLib.h> | ||
| 48 | #include <Protocol/CcMeasurement.h> | ||
| 49 | |||
| 50 | +#include "DxeTpm2MeasureBootLibSanitization.h" | ||
| 51 | + | ||
| 52 | typedef struct { | ||
| 53 | EFI_TCG2_PROTOCOL *Tcg2Protocol; | ||
| 54 | EFI_CC_MEASUREMENT_PROTOCOL *CcProtocol; | ||
| 55 | @@ -144,10 +148,11 @@ Tcg2MeasureGptTable ( | ||
| 56 | EFI_TCG2_EVENT *Tcg2Event; | ||
| 57 | EFI_CC_EVENT *CcEvent; | ||
| 58 | EFI_GPT_DATA *GptData; | ||
| 59 | - UINT32 EventSize; | ||
| 60 | + UINT32 TcgEventSize; | ||
| 61 | EFI_TCG2_PROTOCOL *Tcg2Protocol; | ||
| 62 | EFI_CC_MEASUREMENT_PROTOCOL *CcProtocol; | ||
| 63 | EFI_CC_MR_INDEX MrIndex; | ||
| 64 | + UINT32 AllocSize; | ||
| 65 | |||
| 66 | if (mTcg2MeasureGptCount > 0) { | ||
| 67 | return EFI_SUCCESS; | ||
| 68 | @@ -195,25 +200,22 @@ Tcg2MeasureGptTable ( | ||
| 69 | BlockIo->Media->BlockSize, | ||
| 70 | (UINT8 *)PrimaryHeader | ||
| 71 | ); | ||
| 72 | - if (EFI_ERROR (Status)) { | ||
| 73 | - DEBUG ((DEBUG_ERROR, "Failed to Read Partition Table Header!\n")); | ||
| 74 | + if (EFI_ERROR (Status) || EFI_ERROR (SanitizeEfiPartitionTableHeader (PrimaryHeader, BlockIo))) { | ||
| 75 | + DEBUG ((DEBUG_ERROR, "Failed to read Partition Table Header or invalid Partition Table Header!\n")); | ||
| 76 | FreePool (PrimaryHeader); | ||
| 77 | return EFI_DEVICE_ERROR; | ||
| 78 | } | ||
| 79 | |||
| 80 | // | ||
| 81 | - // PrimaryHeader->SizeOfPartitionEntry should not be zero | ||
| 82 | + // Read the partition entry. | ||
| 83 | // | ||
| 84 | - if (PrimaryHeader->SizeOfPartitionEntry == 0) { | ||
| 85 | - DEBUG ((DEBUG_ERROR, "SizeOfPartitionEntry should not be zero!\n")); | ||
| 86 | + Status = SanitizePrimaryHeaderAllocationSize (PrimaryHeader, &AllocSize); | ||
| 87 | + if (EFI_ERROR (Status)) { | ||
| 88 | FreePool (PrimaryHeader); | ||
| 89 | return EFI_BAD_BUFFER_SIZE; | ||
| 90 | } | ||
| 91 | |||
| 92 | - // | ||
| 93 | - // Read the partition entry. | ||
| 94 | - // | ||
| 95 | - EntryPtr = (UINT8 *)AllocatePool (PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry); | ||
| 96 | + EntryPtr = (UINT8 *)AllocatePool (AllocSize); | ||
| 97 | if (EntryPtr == NULL) { | ||
| 98 | FreePool (PrimaryHeader); | ||
| 99 | return EFI_OUT_OF_RESOURCES; | ||
| 100 | @@ -223,7 +225,7 @@ Tcg2MeasureGptTable ( | ||
| 101 | DiskIo, | ||
| 102 | BlockIo->Media->MediaId, | ||
| 103 | MultU64x32 (PrimaryHeader->PartitionEntryLBA, BlockIo->Media->BlockSize), | ||
| 104 | - PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry, | ||
| 105 | + AllocSize, | ||
| 106 | EntryPtr | ||
| 107 | ); | ||
| 108 | if (EFI_ERROR (Status)) { | ||
| 109 | @@ -248,16 +250,21 @@ Tcg2MeasureGptTable ( | ||
| 110 | // | ||
| 111 | // Prepare Data for Measurement (CcProtocol and Tcg2Protocol) | ||
| 112 | // | ||
| 113 | - EventSize = (UINT32)(sizeof (EFI_GPT_DATA) - sizeof (GptData->Partitions) | ||
| 114 | - + NumberOfPartition * PrimaryHeader->SizeOfPartitionEntry); | ||
| 115 | - EventPtr = (UINT8 *)AllocateZeroPool (EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event)); | ||
| 116 | + Status = SanitizePrimaryHeaderGptEventSize (PrimaryHeader, NumberOfPartition, &TcgEventSize); | ||
| 117 | + if (EFI_ERROR (Status)) { | ||
| 118 | + FreePool (PrimaryHeader); | ||
| 119 | + FreePool (EntryPtr); | ||
| 120 | + return EFI_DEVICE_ERROR; | ||
| 121 | + } | ||
| 122 | + | ||
| 123 | + EventPtr = (UINT8 *)AllocateZeroPool (TcgEventSize); | ||
| 124 | if (EventPtr == NULL) { | ||
| 125 | Status = EFI_OUT_OF_RESOURCES; | ||
| 126 | goto Exit; | ||
| 127 | } | ||
| 128 | |||
| 129 | Tcg2Event = (EFI_TCG2_EVENT *)EventPtr; | ||
| 130 | - Tcg2Event->Size = EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event); | ||
| 131 | + Tcg2Event->Size = TcgEventSize; | ||
| 132 | Tcg2Event->Header.HeaderSize = sizeof (EFI_TCG2_EVENT_HEADER); | ||
| 133 | Tcg2Event->Header.HeaderVersion = EFI_TCG2_EVENT_HEADER_VERSION; | ||
| 134 | Tcg2Event->Header.PCRIndex = 5; | ||
| 135 | @@ -310,7 +317,7 @@ Tcg2MeasureGptTable ( | ||
| 136 | CcProtocol, | ||
| 137 | 0, | ||
| 138 | (EFI_PHYSICAL_ADDRESS)(UINTN)(VOID *)GptData, | ||
| 139 | - (UINT64)EventSize, | ||
| 140 | + (UINT64)TcgEventSize - OFFSET_OF (EFI_TCG2_EVENT, Event), | ||
| 141 | CcEvent | ||
| 142 | ); | ||
| 143 | if (!EFI_ERROR (Status)) { | ||
| 144 | @@ -326,7 +333,7 @@ Tcg2MeasureGptTable ( | ||
| 145 | Tcg2Protocol, | ||
| 146 | 0, | ||
| 147 | (EFI_PHYSICAL_ADDRESS)(UINTN)(VOID *)GptData, | ||
| 148 | - (UINT64)EventSize, | ||
| 149 | + (UINT64)TcgEventSize - OFFSET_OF (EFI_TCG2_EVENT, Event), | ||
| 150 | Tcg2Event | ||
| 151 | ); | ||
| 152 | if (!EFI_ERROR (Status)) { | ||
| 153 | @@ -443,11 +450,13 @@ Tcg2MeasurePeImage ( | ||
| 154 | Tcg2Event->Header.PCRIndex = 2; | ||
| 155 | break; | ||
| 156 | default: | ||
| 157 | - DEBUG (( | ||
| 158 | - DEBUG_ERROR, | ||
| 159 | - "Tcg2MeasurePeImage: Unknown subsystem type %d", | ||
| 160 | - ImageType | ||
| 161 | - )); | ||
| 162 | + DEBUG ( | ||
| 163 | + ( | ||
| 164 | + DEBUG_ERROR, | ||
| 165 | + "Tcg2MeasurePeImage: Unknown subsystem type %d", | ||
| 166 | + ImageType | ||
| 167 | + ) | ||
| 168 | + ); | ||
| 169 | goto Finish; | ||
| 170 | } | ||
| 171 | |||
| 172 | @@ -515,7 +524,7 @@ Finish: | ||
| 173 | |||
| 174 | @param MeasureBootProtocols Pointer to the located measure boot protocol instances. | ||
| 175 | |||
| 176 | - @retval EFI_SUCCESS Sucessfully locate the measure boot protocol instances (at least one instance). | ||
| 177 | + @retval EFI_SUCCESS Successfully locate the measure boot protocol instances (at least one instance). | ||
| 178 | @retval EFI_UNSUPPORTED Measure boot is not supported. | ||
| 179 | **/ | ||
| 180 | EFI_STATUS | ||
| 181 | @@ -646,12 +655,14 @@ DxeTpm2MeasureBootHandler ( | ||
| 182 | return EFI_SUCCESS; | ||
| 183 | } | ||
| 184 | |||
| 185 | - DEBUG (( | ||
| 186 | - DEBUG_INFO, | ||
| 187 | - "Tcg2Protocol = %p, CcMeasurementProtocol = %p\n", | ||
| 188 | - MeasureBootProtocols.Tcg2Protocol, | ||
| 189 | - MeasureBootProtocols.CcProtocol | ||
| 190 | - )); | ||
| 191 | + DEBUG ( | ||
| 192 | + ( | ||
| 193 | + DEBUG_INFO, | ||
| 194 | + "Tcg2Protocol = %p, CcMeasurementProtocol = %p\n", | ||
| 195 | + MeasureBootProtocols.Tcg2Protocol, | ||
| 196 | + MeasureBootProtocols.CcProtocol | ||
| 197 | + ) | ||
| 198 | + ); | ||
| 199 | |||
| 200 | // | ||
| 201 | // Copy File Device Path | ||
| 202 | diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf | ||
| 203 | index 6dca79a20c..28995f438d 100644 | ||
| 204 | --- a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf | ||
| 205 | +++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf | ||
| 206 | @@ -37,6 +37,8 @@ | ||
| 207 | |||
| 208 | [Sources] | ||
| 209 | DxeTpm2MeasureBootLib.c | ||
| 210 | + DxeTpm2MeasureBootLibSanitization.c | ||
| 211 | + DxeTpm2MeasureBootLibSanitization.h | ||
| 212 | |||
| 213 | [Packages] | ||
| 214 | MdePkg/MdePkg.dec | ||
| 215 | @@ -46,6 +48,7 @@ | ||
| 216 | |||
| 217 | [LibraryClasses] | ||
| 218 | BaseMemoryLib | ||
| 219 | + SafeIntLib | ||
| 220 | DebugLib | ||
| 221 | MemoryAllocationLib | ||
| 222 | DevicePathLib | ||
| 223 | @@ -65,4 +68,3 @@ | ||
| 224 | gEfiFirmwareVolumeBlockProtocolGuid ## SOMETIMES_CONSUMES | ||
| 225 | gEfiBlockIoProtocolGuid ## SOMETIMES_CONSUMES | ||
| 226 | gEfiDiskIoProtocolGuid ## SOMETIMES_CONSUMES | ||
| 227 | - | ||
| 228 | diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.c b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.c | ||
| 229 | new file mode 100644 | ||
| 230 | index 0000000000..e2309655d3 | ||
| 231 | --- /dev/null | ||
| 232 | +++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.c | ||
| 233 | @@ -0,0 +1,275 @@ | ||
| 234 | +/** @file | ||
| 235 | + The library instance provides security service of TPM2 measure boot and | ||
| 236 | + Confidential Computing (CC) measure boot. | ||
| 237 | + | ||
| 238 | + Caution: This file requires additional review when modified. | ||
| 239 | + This library will have external input - PE/COFF image and GPT partition. | ||
| 240 | + This external input must be validated carefully to avoid security issue like | ||
| 241 | + buffer overflow, integer overflow. | ||
| 242 | + | ||
| 243 | + This file will pull out the validation logic from the following functions, in an | ||
| 244 | + attempt to validate the untrusted input in the form of unit tests | ||
| 245 | + | ||
| 246 | + These are those functions: | ||
| 247 | + | ||
| 248 | + DxeTpm2MeasureBootLibImageRead() function will make sure the PE/COFF image content | ||
| 249 | + read is within the image buffer. | ||
| 250 | + | ||
| 251 | + Tcg2MeasureGptTable() function will receive untrusted GPT partition table, and parse | ||
| 252 | + partition data carefully. | ||
| 253 | + | ||
| 254 | + Copyright (c) Microsoft Corporation.<BR> | ||
| 255 | + SPDX-License-Identifier: BSD-2-Clause-Patent | ||
| 256 | +**/ | ||
| 257 | +#include <Uefi.h> | ||
| 258 | +#include <Uefi/UefiSpec.h> | ||
| 259 | +#include <Library/SafeIntLib.h> | ||
| 260 | +#include <Library/UefiLib.h> | ||
| 261 | +#include <Library/DebugLib.h> | ||
| 262 | +#include <Library/BaseLib.h> | ||
| 263 | +#include <IndustryStandard/UefiTcgPlatform.h> | ||
| 264 | +#include <Protocol/BlockIo.h> | ||
| 265 | +#include <Library/MemoryAllocationLib.h> | ||
| 266 | + | ||
| 267 | +#include "DxeTpm2MeasureBootLibSanitization.h" | ||
| 268 | + | ||
| 269 | +#define GPT_HEADER_REVISION_V1 0x00010000 | ||
| 270 | + | ||
| 271 | +/** | ||
| 272 | + This function will validate the EFI_PARTITION_TABLE_HEADER structure is safe to parse | ||
| 273 | + However this function will not attempt to verify the validity of the GPT partition | ||
| 274 | + It will check the following: | ||
| 275 | + - Signature | ||
| 276 | + - Revision | ||
| 277 | + - AlternateLBA | ||
| 278 | + - FirstUsableLBA | ||
| 279 | + - LastUsableLBA | ||
| 280 | + - PartitionEntryLBA | ||
| 281 | + - NumberOfPartitionEntries | ||
| 282 | + - SizeOfPartitionEntry | ||
| 283 | + - BlockIo | ||
| 284 | + | ||
| 285 | + @param[in] PrimaryHeader | ||
| 286 | + Pointer to the EFI_PARTITION_TABLE_HEADER structure. | ||
| 287 | + | ||
| 288 | + @param[in] BlockIo | ||
| 289 | + Pointer to the EFI_BLOCK_IO_PROTOCOL structure. | ||
| 290 | + | ||
| 291 | + @retval EFI_SUCCESS | ||
| 292 | + The EFI_PARTITION_TABLE_HEADER structure is valid. | ||
| 293 | + | ||
| 294 | + @retval EFI_INVALID_PARAMETER | ||
| 295 | + The EFI_PARTITION_TABLE_HEADER structure is invalid. | ||
| 296 | +**/ | ||
| 297 | +EFI_STATUS | ||
| 298 | +EFIAPI | ||
| 299 | +SanitizeEfiPartitionTableHeader ( | ||
| 300 | + IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, | ||
| 301 | + IN CONST EFI_BLOCK_IO_PROTOCOL *BlockIo | ||
| 302 | + ) | ||
| 303 | +{ | ||
| 304 | + // | ||
| 305 | + // Verify that the input parameters are safe to use | ||
| 306 | + // | ||
| 307 | + if (PrimaryHeader == NULL) { | ||
| 308 | + DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header!\n")); | ||
| 309 | + return EFI_INVALID_PARAMETER; | ||
| 310 | + } | ||
| 311 | + | ||
| 312 | + if ((BlockIo == NULL) || (BlockIo->Media == NULL)) { | ||
| 313 | + DEBUG ((DEBUG_ERROR, "Invalid BlockIo!\n")); | ||
| 314 | + return EFI_INVALID_PARAMETER; | ||
| 315 | + } | ||
| 316 | + | ||
| 317 | + // | ||
| 318 | + // The signature must be EFI_PTAB_HEADER_ID ("EFI PART" in ASCII) | ||
| 319 | + // | ||
| 320 | + if (PrimaryHeader->Header.Signature != EFI_PTAB_HEADER_ID) { | ||
| 321 | + DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header!\n")); | ||
| 322 | + return EFI_DEVICE_ERROR; | ||
| 323 | + } | ||
| 324 | + | ||
| 325 | + // | ||
| 326 | + // The version must be GPT_HEADER_REVISION_V1 (0x00010000) | ||
| 327 | + // | ||
| 328 | + if (PrimaryHeader->Header.Revision != GPT_HEADER_REVISION_V1) { | ||
| 329 | + DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header Revision!\n")); | ||
| 330 | + return EFI_DEVICE_ERROR; | ||
| 331 | + } | ||
| 332 | + | ||
| 333 | + // | ||
| 334 | + // The HeaderSize must be greater than or equal to 92 and must be less than or equal to the logical block size | ||
| 335 | + // | ||
| 336 | + if ((PrimaryHeader->Header.HeaderSize < sizeof (EFI_PARTITION_TABLE_HEADER)) || (PrimaryHeader->Header.HeaderSize > BlockIo->Media->BlockSize)) { | ||
| 337 | + DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header HeaderSize!\n")); | ||
| 338 | + return EFI_DEVICE_ERROR; | ||
| 339 | + } | ||
| 340 | + | ||
| 341 | + // | ||
| 342 | + // The partition entries should all be before the first usable block | ||
| 343 | + // | ||
| 344 | + if (PrimaryHeader->FirstUsableLBA <= PrimaryHeader->PartitionEntryLBA) { | ||
| 345 | + DEBUG ((DEBUG_ERROR, "GPT PartitionEntryLBA is not less than FirstUsableLBA!\n")); | ||
| 346 | + return EFI_DEVICE_ERROR; | ||
| 347 | + } | ||
| 348 | + | ||
| 349 | + // | ||
| 350 | + // Check that the PartitionEntryLBA greater than the Max LBA | ||
| 351 | + // This will be used later for multiplication | ||
| 352 | + // | ||
| 353 | + if (PrimaryHeader->PartitionEntryLBA > DivU64x32 (MAX_UINT64, BlockIo->Media->BlockSize)) { | ||
| 354 | + DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header PartitionEntryLBA!\n")); | ||
| 355 | + return EFI_DEVICE_ERROR; | ||
| 356 | + } | ||
| 357 | + | ||
| 358 | + // | ||
| 359 | + // Check that the number of partition entries is greater than zero | ||
| 360 | + // | ||
| 361 | + if (PrimaryHeader->NumberOfPartitionEntries == 0) { | ||
| 362 | + DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header NumberOfPartitionEntries!\n")); | ||
| 363 | + return EFI_DEVICE_ERROR; | ||
| 364 | + } | ||
| 365 | + | ||
| 366 | + // | ||
| 367 | + // SizeOfPartitionEntry must be 128, 256, 512... improper size may lead to accessing uninitialized memory | ||
| 368 | + // | ||
| 369 | + if ((PrimaryHeader->SizeOfPartitionEntry < 128) || ((PrimaryHeader->SizeOfPartitionEntry & (PrimaryHeader->SizeOfPartitionEntry - 1)) != 0)) { | ||
| 370 | + DEBUG ((DEBUG_ERROR, "SizeOfPartitionEntry shall be set to a value of 128 x 2^n where n is an integer greater than or equal to zero (e.g., 128, 256, 512, etc.)!\n")); | ||
| 371 | + return EFI_DEVICE_ERROR; | ||
| 372 | + } | ||
| 373 | + | ||
| 374 | + // | ||
| 375 | + // This check is to prevent overflow when calculating the allocation size for the partition entries | ||
| 376 | + // This check will be used later for multiplication | ||
| 377 | + // | ||
| 378 | + if (PrimaryHeader->NumberOfPartitionEntries > DivU64x32 (MAX_UINT64, PrimaryHeader->SizeOfPartitionEntry)) { | ||
| 379 | + DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header NumberOfPartitionEntries!\n")); | ||
| 380 | + return EFI_DEVICE_ERROR; | ||
| 381 | + } | ||
| 382 | + | ||
| 383 | + return EFI_SUCCESS; | ||
| 384 | +} | ||
| 385 | + | ||
| 386 | +/** | ||
| 387 | + This function will validate that the allocation size from the primary header is sane | ||
| 388 | + It will check the following: | ||
| 389 | + - AllocationSize does not overflow | ||
| 390 | + | ||
| 391 | + @param[in] PrimaryHeader | ||
| 392 | + Pointer to the EFI_PARTITION_TABLE_HEADER structure. | ||
| 393 | + | ||
| 394 | + @param[out] AllocationSize | ||
| 395 | + Pointer to the allocation size. | ||
| 396 | + | ||
| 397 | + @retval EFI_SUCCESS | ||
| 398 | + The allocation size is valid. | ||
| 399 | + | ||
| 400 | + @retval EFI_OUT_OF_RESOURCES | ||
| 401 | + The allocation size is invalid. | ||
| 402 | +**/ | ||
| 403 | +EFI_STATUS | ||
| 404 | +EFIAPI | ||
| 405 | +SanitizePrimaryHeaderAllocationSize ( | ||
| 406 | + IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, | ||
| 407 | + OUT UINT32 *AllocationSize | ||
| 408 | + ) | ||
| 409 | +{ | ||
| 410 | + EFI_STATUS Status; | ||
| 411 | + | ||
| 412 | + if (PrimaryHeader == NULL) { | ||
| 413 | + return EFI_INVALID_PARAMETER; | ||
| 414 | + } | ||
| 415 | + | ||
| 416 | + if (AllocationSize == NULL) { | ||
| 417 | + return EFI_INVALID_PARAMETER; | ||
| 418 | + } | ||
| 419 | + | ||
| 420 | + // | ||
| 421 | + // Replacing logic: | ||
| 422 | + // PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry; | ||
| 423 | + // | ||
| 424 | + Status = SafeUint32Mult (PrimaryHeader->NumberOfPartitionEntries, PrimaryHeader->SizeOfPartitionEntry, AllocationSize); | ||
| 425 | + if (EFI_ERROR (Status)) { | ||
| 426 | + DEBUG ((DEBUG_ERROR, "Allocation Size would have overflowed!\n")); | ||
| 427 | + return EFI_BAD_BUFFER_SIZE; | ||
| 428 | + } | ||
| 429 | + | ||
| 430 | + return EFI_SUCCESS; | ||
| 431 | +} | ||
| 432 | + | ||
| 433 | +/** | ||
| 434 | + This function will validate that the Gpt Event Size calculated from the primary header is sane | ||
| 435 | + It will check the following: | ||
| 436 | + - EventSize does not overflow | ||
| 437 | + | ||
| 438 | + Important: This function includes the entire length of the allocated space, including | ||
| 439 | + (sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event)) . When hashing the buffer allocated with this | ||
| 440 | + size, the caller must subtract the size of the (sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event)) | ||
| 441 | + from the size of the buffer before hashing. | ||
| 442 | + | ||
| 443 | + @param[in] PrimaryHeader - Pointer to the EFI_PARTITION_TABLE_HEADER structure. | ||
| 444 | + @param[in] NumberOfPartition - Number of partitions. | ||
| 445 | + @param[out] EventSize - Pointer to the event size. | ||
| 446 | + | ||
| 447 | + @retval EFI_SUCCESS | ||
| 448 | + The event size is valid. | ||
| 449 | + | ||
| 450 | + @retval EFI_OUT_OF_RESOURCES | ||
| 451 | + Overflow would have occurred. | ||
| 452 | + | ||
| 453 | + @retval EFI_INVALID_PARAMETER | ||
| 454 | + One of the passed parameters was invalid. | ||
| 455 | +**/ | ||
| 456 | +EFI_STATUS | ||
| 457 | +SanitizePrimaryHeaderGptEventSize ( | ||
| 458 | + IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, | ||
| 459 | + IN UINTN NumberOfPartition, | ||
| 460 | + OUT UINT32 *EventSize | ||
| 461 | + ) | ||
| 462 | +{ | ||
| 463 | + EFI_STATUS Status; | ||
| 464 | + UINT32 SafeNumberOfPartitions; | ||
| 465 | + | ||
| 466 | + if (PrimaryHeader == NULL) { | ||
| 467 | + return EFI_INVALID_PARAMETER; | ||
| 468 | + } | ||
| 469 | + | ||
| 470 | + if (EventSize == NULL) { | ||
| 471 | + return EFI_INVALID_PARAMETER; | ||
| 472 | + } | ||
| 473 | + | ||
| 474 | + // | ||
| 475 | + // We shouldn't even attempt to perform the multiplication if the number of partitions is greater than the maximum value of UINT32 | ||
| 476 | + // | ||
| 477 | + Status = SafeUintnToUint32 (NumberOfPartition, &SafeNumberOfPartitions); | ||
| 478 | + if (EFI_ERROR (Status)) { | ||
| 479 | + DEBUG ((DEBUG_ERROR, "NumberOfPartition would have overflowed!\n")); | ||
| 480 | + return EFI_INVALID_PARAMETER; | ||
| 481 | + } | ||
| 482 | + | ||
| 483 | + // | ||
| 484 | + // Replacing logic: | ||
| 485 | + // (UINT32)(sizeof (EFI_GPT_DATA) - sizeof (GptData->Partitions) + NumberOfPartition * PrimaryHeader.SizeOfPartitionEntry); | ||
| 486 | + // | ||
| 487 | + Status = SafeUint32Mult (SafeNumberOfPartitions, PrimaryHeader->SizeOfPartitionEntry, EventSize); | ||
| 488 | + if (EFI_ERROR (Status)) { | ||
| 489 | + DEBUG ((DEBUG_ERROR, "Event Size would have overflowed!\n")); | ||
| 490 | + return EFI_BAD_BUFFER_SIZE; | ||
| 491 | + } | ||
| 492 | + | ||
| 493 | + // | ||
| 494 | + // Replacing logic: | ||
| 495 | + // *EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event); | ||
| 496 | + // | ||
| 497 | + Status = SafeUint32Add ( | ||
| 498 | + OFFSET_OF (EFI_TCG2_EVENT, Event) + OFFSET_OF (EFI_GPT_DATA, Partitions), | ||
| 499 | + *EventSize, | ||
| 500 | + EventSize | ||
| 501 | + ); | ||
| 502 | + if (EFI_ERROR (Status)) { | ||
| 503 | + DEBUG ((DEBUG_ERROR, "Event Size would have overflowed because of GPTData!\n")); | ||
| 504 | + return EFI_BAD_BUFFER_SIZE; | ||
| 505 | + } | ||
| 506 | + | ||
| 507 | + return EFI_SUCCESS; | ||
| 508 | +} | ||
| 509 | diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.h b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.h | ||
| 510 | new file mode 100644 | ||
| 511 | index 0000000000..048b738987 | ||
| 512 | --- /dev/null | ||
| 513 | +++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.h | ||
| 514 | @@ -0,0 +1,113 @@ | ||
| 515 | +/** @file | ||
| 516 | + This file includes the function prototypes for the sanitization functions. | ||
| 517 | + | ||
| 518 | + These are those functions: | ||
| 519 | + | ||
| 520 | + DxeTpm2MeasureBootLibImageRead() function will make sure the PE/COFF image content | ||
| 521 | + read is within the image buffer. | ||
| 522 | + | ||
| 523 | + Tcg2MeasureGptTable() function will receive untrusted GPT partition table, and parse | ||
| 524 | + partition data carefully. | ||
| 525 | + | ||
| 526 | + Copyright (c) Microsoft Corporation.<BR> | ||
| 527 | + SPDX-License-Identifier: BSD-2-Clause-Patent | ||
| 528 | + | ||
| 529 | +**/ | ||
| 530 | + | ||
| 531 | +#ifndef DXE_TPM2_MEASURE_BOOT_LIB_SANITATION_ | ||
| 532 | +#define DXE_TPM2_MEASURE_BOOT_LIB_SANITATION_ | ||
| 533 | + | ||
| 534 | +#include <Uefi.h> | ||
| 535 | +#include <Uefi/UefiSpec.h> | ||
| 536 | +#include <Protocol/BlockIo.h> | ||
| 537 | +#include <IndustryStandard/UefiTcgPlatform.h> | ||
| 538 | +#include <Protocol/Tcg2Protocol.h> | ||
| 539 | + | ||
| 540 | +/** | ||
| 541 | + This function will validate the EFI_PARTITION_TABLE_HEADER structure is safe to parse | ||
| 542 | + However this function will not attempt to verify the validity of the GPT partition | ||
| 543 | + It will check the following: | ||
| 544 | + - Signature | ||
| 545 | + - Revision | ||
| 546 | + - AlternateLBA | ||
| 547 | + - FirstUsableLBA | ||
| 548 | + - LastUsableLBA | ||
| 549 | + - PartitionEntryLBA | ||
| 550 | + - NumberOfPartitionEntries | ||
| 551 | + - SizeOfPartitionEntry | ||
| 552 | + - BlockIo | ||
| 553 | + | ||
| 554 | + @param[in] PrimaryHeader | ||
| 555 | + Pointer to the EFI_PARTITION_TABLE_HEADER structure. | ||
| 556 | + | ||
| 557 | + @param[in] BlockIo | ||
| 558 | + Pointer to the EFI_BLOCK_IO_PROTOCOL structure. | ||
| 559 | + | ||
| 560 | + @retval EFI_SUCCESS | ||
| 561 | + The EFI_PARTITION_TABLE_HEADER structure is valid. | ||
| 562 | + | ||
| 563 | + @retval EFI_INVALID_PARAMETER | ||
| 564 | + The EFI_PARTITION_TABLE_HEADER structure is invalid. | ||
| 565 | +**/ | ||
| 566 | +EFI_STATUS | ||
| 567 | +EFIAPI | ||
| 568 | +SanitizeEfiPartitionTableHeader ( | ||
| 569 | + IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, | ||
| 570 | + IN CONST EFI_BLOCK_IO_PROTOCOL *BlockIo | ||
| 571 | + ); | ||
| 572 | + | ||
| 573 | +/** | ||
| 574 | + This function will validate that the allocation size from the primary header is sane | ||
| 575 | + It will check the following: | ||
| 576 | + - AllocationSize does not overflow | ||
| 577 | + | ||
| 578 | + @param[in] PrimaryHeader | ||
| 579 | + Pointer to the EFI_PARTITION_TABLE_HEADER structure. | ||
| 580 | + | ||
| 581 | + @param[out] AllocationSize | ||
| 582 | + Pointer to the allocation size. | ||
| 583 | + | ||
| 584 | + @retval EFI_SUCCESS | ||
| 585 | + The allocation size is valid. | ||
| 586 | + | ||
| 587 | + @retval EFI_OUT_OF_RESOURCES | ||
| 588 | + The allocation size is invalid. | ||
| 589 | +**/ | ||
| 590 | +EFI_STATUS | ||
| 591 | +EFIAPI | ||
| 592 | +SanitizePrimaryHeaderAllocationSize ( | ||
| 593 | + IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, | ||
| 594 | + OUT UINT32 *AllocationSize | ||
| 595 | + ); | ||
| 596 | + | ||
| 597 | +/** | ||
| 598 | + This function will validate that the Gpt Event Size calculated from the primary header is sane | ||
| 599 | + It will check the following: | ||
| 600 | + - EventSize does not overflow | ||
| 601 | + | ||
| 602 | + Important: This function includes the entire length of the allocated space, including | ||
| 603 | + (sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event)) . When hashing the buffer allocated with this | ||
| 604 | + size, the caller must subtract the size of the (sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event)) | ||
| 605 | + from the size of the buffer before hashing. | ||
| 606 | + | ||
| 607 | + @param[in] PrimaryHeader - Pointer to the EFI_PARTITION_TABLE_HEADER structure. | ||
| 608 | + @param[in] NumberOfPartition - Number of partitions. | ||
| 609 | + @param[out] EventSize - Pointer to the event size. | ||
| 610 | + | ||
| 611 | + @retval EFI_SUCCESS | ||
| 612 | + The event size is valid. | ||
| 613 | + | ||
| 614 | + @retval EFI_OUT_OF_RESOURCES | ||
| 615 | + Overflow would have occurred. | ||
| 616 | + | ||
| 617 | + @retval EFI_INVALID_PARAMETER | ||
| 618 | + One of the passed parameters was invalid. | ||
| 619 | +**/ | ||
| 620 | +EFI_STATUS | ||
| 621 | +SanitizePrimaryHeaderGptEventSize ( | ||
| 622 | + IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, | ||
| 623 | + IN UINTN NumberOfPartition, | ||
| 624 | + OUT UINT32 *EventSize | ||
| 625 | + ); | ||
| 626 | + | ||
| 627 | +#endif // DXE_TPM2_MEASURE_BOOT_LIB_SANITATION_ | ||
| 628 | diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTest.c b/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTest.c | ||
| 629 | new file mode 100644 | ||
| 630 | index 0000000000..3eb9763e3c | ||
| 631 | --- /dev/null | ||
| 632 | +++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTest.c | ||
| 633 | @@ -0,0 +1,303 @@ | ||
| 634 | +/** @file | ||
| 635 | + This file includes the unit test cases for the DxeTpm2MeasureBootLibSanitizationTest.c. | ||
| 636 | + | ||
| 637 | + Copyright (c) Microsoft Corporation.<BR> | ||
| 638 | + SPDX-License-Identifier: BSD-2-Clause-Patent | ||
| 639 | +**/ | ||
| 640 | + | ||
| 641 | +#include <Uefi.h> | ||
| 642 | +#include <Library/UefiLib.h> | ||
| 643 | +#include <Library/DebugLib.h> | ||
| 644 | +#include <Library/UnitTestLib.h> | ||
| 645 | +#include <Protocol/BlockIo.h> | ||
| 646 | +#include <Library/MemoryAllocationLib.h> | ||
| 647 | +#include <Library/BaseMemoryLib.h> | ||
| 648 | +#include <IndustryStandard/UefiTcgPlatform.h> | ||
| 649 | +#include <Protocol/Tcg2Protocol.h> | ||
| 650 | + | ||
| 651 | +#include "../DxeTpm2MeasureBootLibSanitization.h" | ||
| 652 | + | ||
| 653 | +#define UNIT_TEST_NAME "DxeTpm2MeasureBootLibSanitizationTest" | ||
| 654 | +#define UNIT_TEST_VERSION "1.0" | ||
| 655 | + | ||
| 656 | +#define DEFAULT_PRIMARY_TABLE_HEADER_REVISION 0x00010000 | ||
| 657 | +#define DEFAULT_PRIMARY_TABLE_HEADER_NUMBER_OF_PARTITION_ENTRIES 1 | ||
| 658 | +#define DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY 128 | ||
| 659 | + | ||
| 660 | +/** | ||
| 661 | + This function tests the SanitizeEfiPartitionTableHeader function. | ||
| 662 | + It's intent is to test that a malicious EFI_PARTITION_TABLE_HEADER | ||
| 663 | + structure will not cause undefined or unexpected behavior. | ||
| 664 | + | ||
| 665 | + In general the TPM should still be able to measure the data, but | ||
| 666 | + be the header should be sanitized to prevent any unexpected behavior. | ||
| 667 | + | ||
| 668 | + @param[in] Context The unit test context. | ||
| 669 | + | ||
| 670 | + @retval UNIT_TEST_PASSED The test passed. | ||
| 671 | + @retval UNIT_TEST_ERROR_TEST_FAILED The test failed. | ||
| 672 | +**/ | ||
| 673 | +UNIT_TEST_STATUS | ||
| 674 | +EFIAPI | ||
| 675 | +TestSanitizeEfiPartitionTableHeader ( | ||
| 676 | + IN UNIT_TEST_CONTEXT Context | ||
| 677 | + ) | ||
| 678 | +{ | ||
| 679 | + EFI_STATUS Status; | ||
| 680 | + EFI_PARTITION_TABLE_HEADER PrimaryHeader; | ||
| 681 | + EFI_BLOCK_IO_PROTOCOL BlockIo; | ||
| 682 | + EFI_BLOCK_IO_MEDIA BlockMedia; | ||
| 683 | + | ||
| 684 | + // Generate EFI_BLOCK_IO_MEDIA test data | ||
| 685 | + BlockMedia.MediaId = 1; | ||
| 686 | + BlockMedia.RemovableMedia = FALSE; | ||
| 687 | + BlockMedia.MediaPresent = TRUE; | ||
| 688 | + BlockMedia.LogicalPartition = FALSE; | ||
| 689 | + BlockMedia.ReadOnly = FALSE; | ||
| 690 | + BlockMedia.WriteCaching = FALSE; | ||
| 691 | + BlockMedia.BlockSize = 512; | ||
| 692 | + BlockMedia.IoAlign = 1; | ||
| 693 | + BlockMedia.LastBlock = 0; | ||
| 694 | + | ||
| 695 | + // Generate EFI_BLOCK_IO_PROTOCOL test data | ||
| 696 | + BlockIo.Revision = 1; | ||
| 697 | + BlockIo.Media = &BlockMedia; | ||
| 698 | + BlockIo.Reset = NULL; | ||
| 699 | + BlockIo.ReadBlocks = NULL; | ||
| 700 | + BlockIo.WriteBlocks = NULL; | ||
| 701 | + BlockIo.FlushBlocks = NULL; | ||
| 702 | + | ||
| 703 | + // Geneate EFI_PARTITION_TABLE_HEADER test data | ||
| 704 | + PrimaryHeader.Header.Signature = EFI_PTAB_HEADER_ID; | ||
| 705 | + PrimaryHeader.Header.Revision = DEFAULT_PRIMARY_TABLE_HEADER_REVISION; | ||
| 706 | + PrimaryHeader.Header.HeaderSize = sizeof (EFI_PARTITION_TABLE_HEADER); | ||
| 707 | + PrimaryHeader.MyLBA = 1; | ||
| 708 | + PrimaryHeader.AlternateLBA = 2; | ||
| 709 | + PrimaryHeader.FirstUsableLBA = 3; | ||
| 710 | + PrimaryHeader.LastUsableLBA = 4; | ||
| 711 | + PrimaryHeader.PartitionEntryLBA = 5; | ||
| 712 | + PrimaryHeader.NumberOfPartitionEntries = DEFAULT_PRIMARY_TABLE_HEADER_NUMBER_OF_PARTITION_ENTRIES; | ||
| 713 | + PrimaryHeader.SizeOfPartitionEntry = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY; | ||
| 714 | + PrimaryHeader.PartitionEntryArrayCRC32 = 0; // Purposely invalid | ||
| 715 | + | ||
| 716 | + // Calculate the CRC32 of the PrimaryHeader | ||
| 717 | + PrimaryHeader.Header.CRC32 = CalculateCrc32 ((UINT8 *)&PrimaryHeader, PrimaryHeader.Header.HeaderSize); | ||
| 718 | + | ||
| 719 | + // Test that a normal PrimaryHeader passes validation | ||
| 720 | + Status = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo); | ||
| 721 | + UT_ASSERT_NOT_EFI_ERROR (Status); | ||
| 722 | + | ||
| 723 | + // Test that when number of partition entries is 0, the function returns EFI_DEVICE_ERROR | ||
| 724 | + // Should print "Invalid Partition Table Header NumberOfPartitionEntries!"" | ||
| 725 | + PrimaryHeader.NumberOfPartitionEntries = 0; | ||
| 726 | + Status = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo); | ||
| 727 | + UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR); | ||
| 728 | + PrimaryHeader.NumberOfPartitionEntries = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY; | ||
| 729 | + | ||
| 730 | + // Test that when the header size is too small, the function returns EFI_DEVICE_ERROR | ||
| 731 | + // Should print "Invalid Partition Table Header Size!" | ||
| 732 | + PrimaryHeader.Header.HeaderSize = 0; | ||
| 733 | + Status = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo); | ||
| 734 | + UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR); | ||
| 735 | + PrimaryHeader.Header.HeaderSize = sizeof (EFI_PARTITION_TABLE_HEADER); | ||
| 736 | + | ||
| 737 | + // Test that when the SizeOfPartitionEntry is too small, the function returns EFI_DEVICE_ERROR | ||
| 738 | + // should print: "SizeOfPartitionEntry shall be set to a value of 128 x 2^n where n is an integer greater than or equal to zero (e.g., 128, 256, 512, etc.)!" | ||
| 739 | + PrimaryHeader.SizeOfPartitionEntry = 1; | ||
| 740 | + Status = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo); | ||
| 741 | + UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR); | ||
| 742 | + | ||
| 743 | + DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__)); | ||
| 744 | + | ||
| 745 | + return UNIT_TEST_PASSED; | ||
| 746 | +} | ||
| 747 | + | ||
| 748 | +/** | ||
| 749 | + This function tests the SanitizePrimaryHeaderAllocationSize function. | ||
| 750 | + It's intent is to test that the untrusted input from a EFI_PARTITION_TABLE_HEADER | ||
| 751 | + structure will not cause an overflow when calculating the allocation size. | ||
| 752 | + | ||
| 753 | + @param[in] Context The unit test context. | ||
| 754 | + | ||
| 755 | + @retval UNIT_TEST_PASSED The test passed. | ||
| 756 | + @retval UNIT_TEST_ERROR_TEST_FAILED The test failed. | ||
| 757 | +**/ | ||
| 758 | +UNIT_TEST_STATUS | ||
| 759 | +EFIAPI | ||
| 760 | +TestSanitizePrimaryHeaderAllocationSize ( | ||
| 761 | + IN UNIT_TEST_CONTEXT Context | ||
| 762 | + ) | ||
| 763 | +{ | ||
| 764 | + UINT32 AllocationSize; | ||
| 765 | + | ||
| 766 | + EFI_STATUS Status; | ||
| 767 | + EFI_PARTITION_TABLE_HEADER PrimaryHeader; | ||
| 768 | + | ||
| 769 | + // Test that a normal PrimaryHeader passes validation | ||
| 770 | + PrimaryHeader.NumberOfPartitionEntries = 5; | ||
| 771 | + PrimaryHeader.SizeOfPartitionEntry = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY; | ||
| 772 | + | ||
| 773 | + Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); | ||
| 774 | + UT_ASSERT_NOT_EFI_ERROR (Status); | ||
| 775 | + | ||
| 776 | + // Test that the allocation size is correct compared to the existing logic | ||
| 777 | + UT_ASSERT_EQUAL (AllocationSize, PrimaryHeader.NumberOfPartitionEntries * PrimaryHeader.SizeOfPartitionEntry); | ||
| 778 | + | ||
| 779 | + // Test that an overflow is detected | ||
| 780 | + PrimaryHeader.NumberOfPartitionEntries = MAX_UINT32; | ||
| 781 | + PrimaryHeader.SizeOfPartitionEntry = 5; | ||
| 782 | + Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); | ||
| 783 | + UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); | ||
| 784 | + | ||
| 785 | + // Test the inverse | ||
| 786 | + PrimaryHeader.NumberOfPartitionEntries = 5; | ||
| 787 | + PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32; | ||
| 788 | + Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); | ||
| 789 | + UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); | ||
| 790 | + | ||
| 791 | + // Test the worst case scenario | ||
| 792 | + PrimaryHeader.NumberOfPartitionEntries = MAX_UINT32; | ||
| 793 | + PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32; | ||
| 794 | + Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); | ||
| 795 | + UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); | ||
| 796 | + | ||
| 797 | + DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__)); | ||
| 798 | + | ||
| 799 | + return UNIT_TEST_PASSED; | ||
| 800 | +} | ||
| 801 | + | ||
| 802 | +/** | ||
| 803 | + This function tests the SanitizePrimaryHeaderGptEventSize function. | ||
| 804 | + It's intent is to test that the untrusted input from a EFI_GPT_DATA structure | ||
| 805 | + will not cause an overflow when calculating the event size. | ||
| 806 | + | ||
| 807 | + @param[in] Context The unit test context. | ||
| 808 | + | ||
| 809 | + @retval UNIT_TEST_PASSED The test passed. | ||
| 810 | + @retval UNIT_TEST_ERROR_TEST_FAILED The test failed. | ||
| 811 | +**/ | ||
| 812 | +UNIT_TEST_STATUS | ||
| 813 | +EFIAPI | ||
| 814 | +TestSanitizePrimaryHeaderGptEventSize ( | ||
| 815 | + IN UNIT_TEST_CONTEXT Context | ||
| 816 | + ) | ||
| 817 | +{ | ||
| 818 | + UINT32 EventSize; | ||
| 819 | + UINT32 ExistingLogicEventSize; | ||
| 820 | + EFI_STATUS Status; | ||
| 821 | + EFI_PARTITION_TABLE_HEADER PrimaryHeader; | ||
| 822 | + UINTN NumberOfPartition; | ||
| 823 | + EFI_GPT_DATA *GptData; | ||
| 824 | + EFI_TCG2_EVENT *Tcg2Event; | ||
| 825 | + | ||
| 826 | + Tcg2Event = NULL; | ||
| 827 | + GptData = NULL; | ||
| 828 | + | ||
| 829 | + // Test that a normal PrimaryHeader passes validation | ||
| 830 | + PrimaryHeader.NumberOfPartitionEntries = 5; | ||
| 831 | + PrimaryHeader.SizeOfPartitionEntry = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY; | ||
| 832 | + | ||
| 833 | + // set the number of partitions | ||
| 834 | + NumberOfPartition = 13; | ||
| 835 | + | ||
| 836 | + // that the primary event size is correct | ||
| 837 | + Status = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, &EventSize); | ||
| 838 | + UT_ASSERT_NOT_EFI_ERROR (Status); | ||
| 839 | + | ||
| 840 | + // Calculate the existing logic event size | ||
| 841 | + ExistingLogicEventSize = (UINT32)(OFFSET_OF (EFI_TCG2_EVENT, Event) + OFFSET_OF (EFI_GPT_DATA, Partitions) | ||
| 842 | + + NumberOfPartition * PrimaryHeader.SizeOfPartitionEntry); | ||
| 843 | + | ||
| 844 | + // Check that the event size is correct | ||
| 845 | + UT_ASSERT_EQUAL (EventSize, ExistingLogicEventSize); | ||
| 846 | + | ||
| 847 | + // Tests that the primary event size may not overflow | ||
| 848 | + Status = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, MAX_UINT32, &EventSize); | ||
| 849 | + UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); | ||
| 850 | + | ||
| 851 | + // Test that the size of partition entries may not overflow | ||
| 852 | + PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32; | ||
| 853 | + Status = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, &EventSize); | ||
| 854 | + UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); | ||
| 855 | + | ||
| 856 | + DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__)); | ||
| 857 | + | ||
| 858 | + return UNIT_TEST_PASSED; | ||
| 859 | +} | ||
| 860 | + | ||
| 861 | +// *--------------------------------------------------------------------* | ||
| 862 | +// * Unit Test Code Main Function | ||
| 863 | +// *--------------------------------------------------------------------* | ||
| 864 | + | ||
| 865 | +/** | ||
| 866 | + This function acts as the entry point for the unit tests. | ||
| 867 | + | ||
| 868 | + @retval UNIT_TEST_PASSED The test passed. | ||
| 869 | + @retval UNIT_TEST_ERROR_TEST_FAILED The test failed. | ||
| 870 | + @retval others The test failed. | ||
| 871 | +**/ | ||
| 872 | +EFI_STATUS | ||
| 873 | +EFIAPI | ||
| 874 | +UefiTestMain ( | ||
| 875 | + VOID | ||
| 876 | + ) | ||
| 877 | +{ | ||
| 878 | + EFI_STATUS Status; | ||
| 879 | + UNIT_TEST_FRAMEWORK_HANDLE Framework; | ||
| 880 | + UNIT_TEST_SUITE_HANDLE Tcg2MeasureBootLibValidationTestSuite; | ||
| 881 | + | ||
| 882 | + Framework = NULL; | ||
| 883 | + | ||
| 884 | + DEBUG ((DEBUG_INFO, "%a: TestMain() - Start\n", UNIT_TEST_NAME)); | ||
| 885 | + | ||
| 886 | + Status = InitUnitTestFramework (&Framework, UNIT_TEST_NAME, gEfiCallerBaseName, UNIT_TEST_VERSION); | ||
| 887 | + if (EFI_ERROR (Status)) { | ||
| 888 | + DEBUG ((DEBUG_ERROR, "%a: Failed in InitUnitTestFramework. Status = %r\n", UNIT_TEST_NAME, Status)); | ||
| 889 | + goto EXIT; | ||
| 890 | + } | ||
| 891 | + | ||
| 892 | + Status = CreateUnitTestSuite (&Tcg2MeasureBootLibValidationTestSuite, Framework, "Tcg2MeasureBootLibValidationTestSuite", "Common.Tcg2MeasureBootLibValidation", NULL, NULL); | ||
| 893 | + if (EFI_ERROR (Status)) { | ||
| 894 | + DEBUG ((DEBUG_ERROR, "%s: Failed in CreateUnitTestSuite for Tcg2MeasureBootLibValidationTestSuite\n", UNIT_TEST_NAME)); | ||
| 895 | + Status = EFI_OUT_OF_RESOURCES; | ||
| 896 | + goto EXIT; | ||
| 897 | + } | ||
| 898 | + | ||
| 899 | + // -----------Suite---------------------------------Description----------------------------Class----------------------------------Test Function------------------------Pre---Clean-Context | ||
| 900 | + AddTestCase (Tcg2MeasureBootLibValidationTestSuite, "Tests Validating EFI Partition Table", "Common.Tcg2MeasureBootLibValidation", TestSanitizeEfiPartitionTableHeader, NULL, NULL, NULL); | ||
| 901 | + AddTestCase (Tcg2MeasureBootLibValidationTestSuite, "Tests Primary header gpt event checks for overflow", "Common.Tcg2MeasureBootLibValidation", TestSanitizePrimaryHeaderAllocationSize, NULL, NULL, NULL); | ||
| 902 | + AddTestCase (Tcg2MeasureBootLibValidationTestSuite, "Tests Primary header allocation size checks for overflow", "Common.Tcg2MeasureBootLibValidation", TestSanitizePrimaryHeaderGptEventSize, NULL, NULL, NULL); | ||
| 903 | + | ||
| 904 | + Status = RunAllTestSuites (Framework); | ||
| 905 | + | ||
| 906 | +EXIT: | ||
| 907 | + if (Framework != NULL) { | ||
| 908 | + FreeUnitTestFramework (Framework); | ||
| 909 | + } | ||
| 910 | + | ||
| 911 | + DEBUG ((DEBUG_INFO, "%a: TestMain() - End\n", UNIT_TEST_NAME)); | ||
| 912 | + return Status; | ||
| 913 | +} | ||
| 914 | + | ||
| 915 | +/// | ||
| 916 | +/// Avoid ECC error for function name that starts with lower case letter | ||
| 917 | +/// | ||
| 918 | +#define DxeTpm2MeasureBootLibUnitTestMain main | ||
| 919 | + | ||
| 920 | +/** | ||
| 921 | + Standard POSIX C entry point for host based unit test execution. | ||
| 922 | + | ||
| 923 | + @param[in] Argc Number of arguments | ||
| 924 | + @param[in] Argv Array of pointers to arguments | ||
| 925 | + | ||
| 926 | + @retval 0 Success | ||
| 927 | + @retval other Error | ||
| 928 | +**/ | ||
| 929 | +INT32 | ||
| 930 | +DxeTpm2MeasureBootLibUnitTestMain ( | ||
| 931 | + IN INT32 Argc, | ||
| 932 | + IN CHAR8 *Argv[] | ||
| 933 | + ) | ||
| 934 | +{ | ||
| 935 | + return (INT32)UefiTestMain (); | ||
| 936 | +} | ||
| 937 | diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTestHost.inf b/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTestHost.inf | ||
| 938 | new file mode 100644 | ||
| 939 | index 0000000000..2999aa2a44 | ||
| 940 | --- /dev/null | ||
| 941 | +++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTestHost.inf | ||
| 942 | @@ -0,0 +1,28 @@ | ||
| 943 | +## @file | ||
| 944 | +# This file builds the unit tests for DxeTpm2MeasureBootLib | ||
| 945 | +# | ||
| 946 | +# Copyright (C) Microsoft Corporation.<BR> | ||
| 947 | +# SPDX-License-Identifier: BSD-2-Clause-Patent | ||
| 948 | +## | ||
| 949 | + | ||
| 950 | +[Defines] | ||
| 951 | + INF_VERSION = 0x00010006 | ||
| 952 | + BASE_NAME = DxeTpm2MeasuredBootLibTest | ||
| 953 | + FILE_GUID = 144d757f-d423-484e-9309-a23695fad5bd | ||
| 954 | + MODULE_TYPE = HOST_APPLICATION | ||
| 955 | + VERSION_STRING = 1.0 | ||
| 956 | + ENTRY_POINT = main | ||
| 957 | + | ||
| 958 | +[Sources] | ||
| 959 | + DxeTpm2MeasureBootLibSanitizationTest.c | ||
| 960 | + ../DxeTpm2MeasureBootLibSanitization.c | ||
| 961 | + | ||
| 962 | +[Packages] | ||
| 963 | + MdePkg/MdePkg.dec | ||
| 964 | + | ||
| 965 | +[LibraryClasses] | ||
| 966 | + BaseLib | ||
| 967 | + DebugLib | ||
| 968 | + UnitTestLib | ||
| 969 | + PrintLib | ||
| 970 | + SafeIntLib | ||
| 971 | diff --git a/SecurityPkg/SecurityPkg.ci.yaml b/SecurityPkg/SecurityPkg.ci.yaml | ||
| 972 | index 7912142398..da811fdf93 100644 | ||
| 973 | --- a/SecurityPkg/SecurityPkg.ci.yaml | ||
| 974 | +++ b/SecurityPkg/SecurityPkg.ci.yaml | ||
| 975 | @@ -15,6 +15,7 @@ | ||
| 976 | ## "<ErrorID>", "<KeyWord>" | ||
| 977 | ## ] | ||
| 978 | "ExceptionList": [ | ||
| 979 | + "8001", "DxeTpm2MeasureBootLibUnitTestMain", | ||
| 980 | ], | ||
| 981 | ## Both file path and directory path are accepted. | ||
| 982 | "IgnoreFiles": [ | ||
| 983 | -- | ||
| 984 | 2.40.0 | ||
| 985 | |||
diff --git a/meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0002.patch b/meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0002.patch new file mode 100644 index 0000000000..6c20cc305e --- /dev/null +++ b/meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0002.patch | |||
| @@ -0,0 +1,889 @@ | |||
| 1 | From 4776a1b39ee08fc45c70c1eab5a0195f325000d3 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: "Douglas Flick [MSFT]" <doug.edk2@gmail.com> | ||
| 3 | Date: Fri, 12 Jan 2024 02:16:02 +0800 | ||
| 4 | Subject: [PATCH] SecurityPkg: DxeTpmMeasureBootLib: SECURITY PATCH 4117 - CVE | ||
| 5 | 2022-36763 | ||
| 6 | |||
| 7 | This commit contains the patch files and tests for DxeTpmMeasureBootLib | ||
| 8 | CVE 2022-36763. | ||
| 9 | |||
| 10 | Cc: Jiewen Yao <jiewen.yao@intel.com> | ||
| 11 | |||
| 12 | Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com> | ||
| 13 | Reviewed-by: Jiewen Yao <jiewen.yao@intel.com> | ||
| 14 | |||
| 15 | CVE: CVE-2022-36763 | ||
| 16 | |||
| 17 | Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/4776a1b39ee08fc45c70c1eab5a0195f325000d3] | ||
| 18 | |||
| 19 | Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com> | ||
| 20 | --- | ||
| 21 | .../DxeTpmMeasureBootLib.c | 40 ++- | ||
| 22 | .../DxeTpmMeasureBootLib.inf | 4 +- | ||
| 23 | .../DxeTpmMeasureBootLibSanitization.c | 241 ++++++++++++++ | ||
| 24 | .../DxeTpmMeasureBootLibSanitization.h | 114 +++++++ | ||
| 25 | .../DxeTpmMeasureBootLibSanitizationTest.c | 301 ++++++++++++++++++ | ||
| 26 | ...eTpmMeasureBootLibSanitizationTestHost.inf | 28 ++ | ||
| 27 | SecurityPkg/SecurityPkg.ci.yaml | 1 + | ||
| 28 | 7 files changed, 715 insertions(+), 14 deletions(-) | ||
| 29 | create mode 100644 SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c | ||
| 30 | create mode 100644 SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.h | ||
| 31 | create mode 100644 SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTest.c | ||
| 32 | create mode 100644 SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTestHost.inf | ||
| 33 | |||
| 34 | diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c | ||
| 35 | index 220393dd2b..669ab19134 100644 | ||
| 36 | --- a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c | ||
| 37 | +++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c | ||
| 38 | @@ -18,6 +18,8 @@ | ||
| 39 | Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR> | ||
| 40 | SPDX-License-Identifier: BSD-2-Clause-Patent | ||
| 41 | |||
| 42 | +Copyright (c) Microsoft Corporation.<BR> | ||
| 43 | +SPDX-License-Identifier: BSD-2-Clause-Patent | ||
| 44 | **/ | ||
| 45 | |||
| 46 | #include <PiDxe.h> | ||
| 47 | @@ -40,6 +42,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent | ||
| 48 | #include <Library/SecurityManagementLib.h> | ||
| 49 | #include <Library/HobLib.h> | ||
| 50 | |||
| 51 | +#include "DxeTpmMeasureBootLibSanitization.h" | ||
| 52 | + | ||
| 53 | // | ||
| 54 | // Flag to check GPT partition. It only need be measured once. | ||
| 55 | // | ||
| 56 | @@ -136,6 +140,9 @@ TcgMeasureGptTable ( | ||
| 57 | UINT32 EventSize; | ||
| 58 | UINT32 EventNumber; | ||
| 59 | EFI_PHYSICAL_ADDRESS EventLogLastEntry; | ||
| 60 | + UINT32 AllocSize; | ||
| 61 | + | ||
| 62 | + GptData = NULL; | ||
| 63 | |||
| 64 | if (mMeasureGptCount > 0) { | ||
| 65 | return EFI_SUCCESS; | ||
| 66 | @@ -166,8 +173,8 @@ TcgMeasureGptTable ( | ||
| 67 | BlockIo->Media->BlockSize, | ||
| 68 | (UINT8 *)PrimaryHeader | ||
| 69 | ); | ||
| 70 | - if (EFI_ERROR (Status)) { | ||
| 71 | - DEBUG ((DEBUG_ERROR, "Failed to Read Partition Table Header!\n")); | ||
| 72 | + if (EFI_ERROR (Status) || EFI_ERROR (SanitizeEfiPartitionTableHeader (PrimaryHeader, BlockIo))) { | ||
| 73 | + DEBUG ((DEBUG_ERROR, "Failed to read Partition Table Header or invalid Partition Table Header!\n")); | ||
| 74 | FreePool (PrimaryHeader); | ||
| 75 | return EFI_DEVICE_ERROR; | ||
| 76 | } | ||
| 77 | @@ -175,7 +182,13 @@ TcgMeasureGptTable ( | ||
| 78 | // | ||
| 79 | // Read the partition entry. | ||
| 80 | // | ||
| 81 | - EntryPtr = (UINT8 *)AllocatePool (PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry); | ||
| 82 | + Status = SanitizePrimaryHeaderAllocationSize (PrimaryHeader, &AllocSize); | ||
| 83 | + if (EFI_ERROR (Status)) { | ||
| 84 | + FreePool (PrimaryHeader); | ||
| 85 | + return EFI_DEVICE_ERROR; | ||
| 86 | + } | ||
| 87 | + | ||
| 88 | + EntryPtr = (UINT8 *)AllocatePool (AllocSize); | ||
| 89 | if (EntryPtr == NULL) { | ||
| 90 | FreePool (PrimaryHeader); | ||
| 91 | return EFI_OUT_OF_RESOURCES; | ||
| 92 | @@ -185,7 +198,7 @@ TcgMeasureGptTable ( | ||
| 93 | DiskIo, | ||
| 94 | BlockIo->Media->MediaId, | ||
| 95 | MultU64x32 (PrimaryHeader->PartitionEntryLBA, BlockIo->Media->BlockSize), | ||
| 96 | - PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry, | ||
| 97 | + AllocSize, | ||
| 98 | EntryPtr | ||
| 99 | ); | ||
| 100 | if (EFI_ERROR (Status)) { | ||
| 101 | @@ -210,9 +223,8 @@ TcgMeasureGptTable ( | ||
| 102 | // | ||
| 103 | // Prepare Data for Measurement | ||
| 104 | // | ||
| 105 | - EventSize = (UINT32)(sizeof (EFI_GPT_DATA) - sizeof (GptData->Partitions) | ||
| 106 | - + NumberOfPartition * PrimaryHeader->SizeOfPartitionEntry); | ||
| 107 | - TcgEvent = (TCG_PCR_EVENT *)AllocateZeroPool (EventSize + sizeof (TCG_PCR_EVENT_HDR)); | ||
| 108 | + Status = SanitizePrimaryHeaderGptEventSize (PrimaryHeader, NumberOfPartition, &EventSize); | ||
| 109 | + TcgEvent = (TCG_PCR_EVENT *)AllocateZeroPool (EventSize); | ||
| 110 | if (TcgEvent == NULL) { | ||
| 111 | FreePool (PrimaryHeader); | ||
| 112 | FreePool (EntryPtr); | ||
| 113 | @@ -221,7 +233,7 @@ TcgMeasureGptTable ( | ||
| 114 | |||
| 115 | TcgEvent->PCRIndex = 5; | ||
| 116 | TcgEvent->EventType = EV_EFI_GPT_EVENT; | ||
| 117 | - TcgEvent->EventSize = EventSize; | ||
| 118 | + TcgEvent->EventSize = EventSize - sizeof (TCG_PCR_EVENT_HDR); | ||
| 119 | GptData = (EFI_GPT_DATA *)TcgEvent->Event; | ||
| 120 | |||
| 121 | // | ||
| 122 | @@ -361,11 +373,13 @@ TcgMeasurePeImage ( | ||
| 123 | TcgEvent->PCRIndex = 2; | ||
| 124 | break; | ||
| 125 | default: | ||
| 126 | - DEBUG (( | ||
| 127 | - DEBUG_ERROR, | ||
| 128 | - "TcgMeasurePeImage: Unknown subsystem type %d", | ||
| 129 | - ImageType | ||
| 130 | - )); | ||
| 131 | + DEBUG ( | ||
| 132 | + ( | ||
| 133 | + DEBUG_ERROR, | ||
| 134 | + "TcgMeasurePeImage: Unknown subsystem type %d", | ||
| 135 | + ImageType | ||
| 136 | + ) | ||
| 137 | + ); | ||
| 138 | goto Finish; | ||
| 139 | } | ||
| 140 | |||
| 141 | diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.inf b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.inf | ||
| 142 | index ebab6f7c1e..414c654d15 100644 | ||
| 143 | --- a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.inf | ||
| 144 | +++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.inf | ||
| 145 | @@ -32,6 +32,8 @@ | ||
| 146 | |||
| 147 | [Sources] | ||
| 148 | DxeTpmMeasureBootLib.c | ||
| 149 | + DxeTpmMeasureBootLibSanitization.c | ||
| 150 | + DxeTpmMeasureBootLibSanitization.h | ||
| 151 | |||
| 152 | [Packages] | ||
| 153 | MdePkg/MdePkg.dec | ||
| 154 | @@ -41,6 +43,7 @@ | ||
| 155 | |||
| 156 | [LibraryClasses] | ||
| 157 | BaseMemoryLib | ||
| 158 | + SafeIntLib | ||
| 159 | DebugLib | ||
| 160 | MemoryAllocationLib | ||
| 161 | DevicePathLib | ||
| 162 | @@ -59,4 +62,3 @@ | ||
| 163 | gEfiFirmwareVolumeBlockProtocolGuid ## SOMETIMES_CONSUMES | ||
| 164 | gEfiBlockIoProtocolGuid ## SOMETIMES_CONSUMES | ||
| 165 | gEfiDiskIoProtocolGuid ## SOMETIMES_CONSUMES | ||
| 166 | - | ||
| 167 | diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c | ||
| 168 | new file mode 100644 | ||
| 169 | index 0000000000..a3fa46f5e6 | ||
| 170 | --- /dev/null | ||
| 171 | +++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c | ||
| 172 | @@ -0,0 +1,241 @@ | ||
| 173 | +/** @file | ||
| 174 | + The library instance provides security service of TPM2 measure boot and | ||
| 175 | + Confidential Computing (CC) measure boot. | ||
| 176 | + | ||
| 177 | + Caution: This file requires additional review when modified. | ||
| 178 | + This library will have external input - PE/COFF image and GPT partition. | ||
| 179 | + This external input must be validated carefully to avoid security issue like | ||
| 180 | + buffer overflow, integer overflow. | ||
| 181 | + | ||
| 182 | + This file will pull out the validation logic from the following functions, in an | ||
| 183 | + attempt to validate the untrusted input in the form of unit tests | ||
| 184 | + | ||
| 185 | + These are those functions: | ||
| 186 | + | ||
| 187 | + DxeTpmMeasureBootLibImageRead() function will make sure the PE/COFF image content | ||
| 188 | + read is within the image buffer. | ||
| 189 | + | ||
| 190 | + Tcg2MeasureGptTable() function will receive untrusted GPT partition table, and parse | ||
| 191 | + partition data carefully. | ||
| 192 | + | ||
| 193 | + Copyright (c) Microsoft Corporation.<BR> | ||
| 194 | + SPDX-License-Identifier: BSD-2-Clause-Patent | ||
| 195 | +**/ | ||
| 196 | +#include <Uefi.h> | ||
| 197 | +#include <Uefi/UefiSpec.h> | ||
| 198 | +#include <Library/SafeIntLib.h> | ||
| 199 | +#include <Library/UefiLib.h> | ||
| 200 | +#include <Library/DebugLib.h> | ||
| 201 | +#include <Library/BaseLib.h> | ||
| 202 | +#include <IndustryStandard/UefiTcgPlatform.h> | ||
| 203 | +#include <Protocol/BlockIo.h> | ||
| 204 | +#include <Library/MemoryAllocationLib.h> | ||
| 205 | + | ||
| 206 | +#include "DxeTpmMeasureBootLibSanitization.h" | ||
| 207 | + | ||
| 208 | +#define GPT_HEADER_REVISION_V1 0x00010000 | ||
| 209 | + | ||
| 210 | +/** | ||
| 211 | + This function will validate the EFI_PARTITION_TABLE_HEADER structure is safe to parse | ||
| 212 | + However this function will not attempt to verify the validity of the GPT partition | ||
| 213 | + It will check the following: | ||
| 214 | + - Signature | ||
| 215 | + - Revision | ||
| 216 | + - AlternateLBA | ||
| 217 | + - FirstUsableLBA | ||
| 218 | + - LastUsableLBA | ||
| 219 | + - PartitionEntryLBA | ||
| 220 | + - NumberOfPartitionEntries | ||
| 221 | + - SizeOfPartitionEntry | ||
| 222 | + - BlockIo | ||
| 223 | + | ||
| 224 | + @param[in] PrimaryHeader | ||
| 225 | + Pointer to the EFI_PARTITION_TABLE_HEADER structure. | ||
| 226 | + | ||
| 227 | + @param[in] BlockIo | ||
| 228 | + Pointer to the EFI_BLOCK_IO_PROTOCOL structure. | ||
| 229 | + | ||
| 230 | + @retval EFI_SUCCESS | ||
| 231 | + The EFI_PARTITION_TABLE_HEADER structure is valid. | ||
| 232 | + | ||
| 233 | + @retval EFI_INVALID_PARAMETER | ||
| 234 | + The EFI_PARTITION_TABLE_HEADER structure is invalid. | ||
| 235 | +**/ | ||
| 236 | +EFI_STATUS | ||
| 237 | +EFIAPI | ||
| 238 | +SanitizeEfiPartitionTableHeader ( | ||
| 239 | + IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, | ||
| 240 | + IN CONST EFI_BLOCK_IO_PROTOCOL *BlockIo | ||
| 241 | + ) | ||
| 242 | +{ | ||
| 243 | + // Verify that the input parameters are safe to use | ||
| 244 | + if (PrimaryHeader == NULL) { | ||
| 245 | + DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header!\n")); | ||
| 246 | + return EFI_INVALID_PARAMETER; | ||
| 247 | + } | ||
| 248 | + | ||
| 249 | + if ((BlockIo == NULL) || (BlockIo->Media == NULL)) { | ||
| 250 | + DEBUG ((DEBUG_ERROR, "Invalid BlockIo!\n")); | ||
| 251 | + return EFI_INVALID_PARAMETER; | ||
| 252 | + } | ||
| 253 | + | ||
| 254 | + // The signature must be EFI_PTAB_HEADER_ID ("EFI PART" in ASCII) | ||
| 255 | + if (PrimaryHeader->Header.Signature != EFI_PTAB_HEADER_ID) { | ||
| 256 | + DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header!\n")); | ||
| 257 | + return EFI_DEVICE_ERROR; | ||
| 258 | + } | ||
| 259 | + | ||
| 260 | + // The version must be GPT_HEADER_REVISION_V1 (0x00010000) | ||
| 261 | + if (PrimaryHeader->Header.Revision != GPT_HEADER_REVISION_V1) { | ||
| 262 | + DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header Revision!\n")); | ||
| 263 | + return EFI_DEVICE_ERROR; | ||
| 264 | + } | ||
| 265 | + | ||
| 266 | + // The HeaderSize must be greater than or equal to 92 and must be less than or equal to the logical block size | ||
| 267 | + if ((PrimaryHeader->Header.HeaderSize < sizeof (EFI_PARTITION_TABLE_HEADER)) || (PrimaryHeader->Header.HeaderSize > BlockIo->Media->BlockSize)) { | ||
| 268 | + DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header HeaderSize!\n")); | ||
| 269 | + return EFI_DEVICE_ERROR; | ||
| 270 | + } | ||
| 271 | + | ||
| 272 | + // check that the PartitionEntryLBA greater than the Max LBA | ||
| 273 | + // This will be used later for multiplication | ||
| 274 | + if (PrimaryHeader->PartitionEntryLBA > DivU64x32 (MAX_UINT64, BlockIo->Media->BlockSize)) { | ||
| 275 | + DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header PartitionEntryLBA!\n")); | ||
| 276 | + return EFI_DEVICE_ERROR; | ||
| 277 | + } | ||
| 278 | + | ||
| 279 | + // Check that the number of partition entries is greater than zero | ||
| 280 | + if (PrimaryHeader->NumberOfPartitionEntries == 0) { | ||
| 281 | + DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header NumberOfPartitionEntries!\n")); | ||
| 282 | + return EFI_DEVICE_ERROR; | ||
| 283 | + } | ||
| 284 | + | ||
| 285 | + // SizeOfPartitionEntry must be 128, 256, 512... improper size may lead to accessing uninitialized memory | ||
| 286 | + if ((PrimaryHeader->SizeOfPartitionEntry < 128) || ((PrimaryHeader->SizeOfPartitionEntry & (PrimaryHeader->SizeOfPartitionEntry - 1)) != 0)) { | ||
| 287 | + DEBUG ((DEBUG_ERROR, "SizeOfPartitionEntry shall be set to a value of 128 x 2^n where n is an integer greater than or equal to zero (e.g., 128, 256, 512, etc.)!\n")); | ||
| 288 | + return EFI_DEVICE_ERROR; | ||
| 289 | + } | ||
| 290 | + | ||
| 291 | + // This check is to prevent overflow when calculating the allocation size for the partition entries | ||
| 292 | + // This check will be used later for multiplication | ||
| 293 | + if (PrimaryHeader->NumberOfPartitionEntries > DivU64x32 (MAX_UINT64, PrimaryHeader->SizeOfPartitionEntry)) { | ||
| 294 | + DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header NumberOfPartitionEntries!\n")); | ||
| 295 | + return EFI_DEVICE_ERROR; | ||
| 296 | + } | ||
| 297 | + | ||
| 298 | + return EFI_SUCCESS; | ||
| 299 | +} | ||
| 300 | + | ||
| 301 | +/** | ||
| 302 | + This function will validate that the allocation size from the primary header is sane | ||
| 303 | + It will check the following: | ||
| 304 | + - AllocationSize does not overflow | ||
| 305 | + | ||
| 306 | + @param[in] PrimaryHeader | ||
| 307 | + Pointer to the EFI_PARTITION_TABLE_HEADER structure. | ||
| 308 | + | ||
| 309 | + @param[out] AllocationSize | ||
| 310 | + Pointer to the allocation size. | ||
| 311 | + | ||
| 312 | + @retval EFI_SUCCESS | ||
| 313 | + The allocation size is valid. | ||
| 314 | + | ||
| 315 | + @retval EFI_OUT_OF_RESOURCES | ||
| 316 | + The allocation size is invalid. | ||
| 317 | +**/ | ||
| 318 | +EFI_STATUS | ||
| 319 | +EFIAPI | ||
| 320 | +SanitizePrimaryHeaderAllocationSize ( | ||
| 321 | + IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, | ||
| 322 | + OUT UINT32 *AllocationSize | ||
| 323 | + ) | ||
| 324 | +{ | ||
| 325 | + EFI_STATUS Status; | ||
| 326 | + | ||
| 327 | + if (PrimaryHeader == NULL) { | ||
| 328 | + return EFI_INVALID_PARAMETER; | ||
| 329 | + } | ||
| 330 | + | ||
| 331 | + if (AllocationSize == NULL) { | ||
| 332 | + return EFI_INVALID_PARAMETER; | ||
| 333 | + } | ||
| 334 | + | ||
| 335 | + // Replacing logic: | ||
| 336 | + // PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry; | ||
| 337 | + Status = SafeUint32Mult (PrimaryHeader->NumberOfPartitionEntries, PrimaryHeader->SizeOfPartitionEntry, AllocationSize); | ||
| 338 | + if (EFI_ERROR (Status)) { | ||
| 339 | + DEBUG ((DEBUG_ERROR, "Allocation Size would have overflowed!\n")); | ||
| 340 | + return EFI_BAD_BUFFER_SIZE; | ||
| 341 | + } | ||
| 342 | + | ||
| 343 | + return EFI_SUCCESS; | ||
| 344 | +} | ||
| 345 | + | ||
| 346 | +/** | ||
| 347 | + This function will validate that the Gpt Event Size calculated from the primary header is sane | ||
| 348 | + It will check the following: | ||
| 349 | + - EventSize does not overflow | ||
| 350 | + | ||
| 351 | + Important: This function includes the entire length of the allocated space, including the | ||
| 352 | + TCG_PCR_EVENT_HDR. When hashing the buffer allocated with this size, the caller must subtract | ||
| 353 | + the size of the TCG_PCR_EVENT_HDR from the size of the buffer before hashing. | ||
| 354 | + | ||
| 355 | + @param[in] PrimaryHeader - Pointer to the EFI_PARTITION_TABLE_HEADER structure. | ||
| 356 | + @param[in] NumberOfPartition - Number of partitions. | ||
| 357 | + @param[out] EventSize - Pointer to the event size. | ||
| 358 | + | ||
| 359 | + @retval EFI_SUCCESS | ||
| 360 | + The event size is valid. | ||
| 361 | + | ||
| 362 | + @retval EFI_OUT_OF_RESOURCES | ||
| 363 | + Overflow would have occurred. | ||
| 364 | + | ||
| 365 | + @retval EFI_INVALID_PARAMETER | ||
| 366 | + One of the passed parameters was invalid. | ||
| 367 | +**/ | ||
| 368 | +EFI_STATUS | ||
| 369 | +SanitizePrimaryHeaderGptEventSize ( | ||
| 370 | + IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, | ||
| 371 | + IN UINTN NumberOfPartition, | ||
| 372 | + OUT UINT32 *EventSize | ||
| 373 | + ) | ||
| 374 | +{ | ||
| 375 | + EFI_STATUS Status; | ||
| 376 | + UINT32 SafeNumberOfPartitions; | ||
| 377 | + | ||
| 378 | + if (PrimaryHeader == NULL) { | ||
| 379 | + return EFI_INVALID_PARAMETER; | ||
| 380 | + } | ||
| 381 | + | ||
| 382 | + if (EventSize == NULL) { | ||
| 383 | + return EFI_INVALID_PARAMETER; | ||
| 384 | + } | ||
| 385 | + | ||
| 386 | + // We shouldn't even attempt to perform the multiplication if the number of partitions is greater than the maximum value of UINT32 | ||
| 387 | + Status = SafeUintnToUint32 (NumberOfPartition, &SafeNumberOfPartitions); | ||
| 388 | + if (EFI_ERROR (Status)) { | ||
| 389 | + DEBUG ((DEBUG_ERROR, "NumberOfPartition would have overflowed!\n")); | ||
| 390 | + return EFI_INVALID_PARAMETER; | ||
| 391 | + } | ||
| 392 | + | ||
| 393 | + // Replacing logic: | ||
| 394 | + // (UINT32)(sizeof (EFI_GPT_DATA) - sizeof (GptData->Partitions) + NumberOfPartition * PrimaryHeader.SizeOfPartitionEntry + sizeof (TCG_PCR_EVENT_HDR)); | ||
| 395 | + Status = SafeUint32Mult (SafeNumberOfPartitions, PrimaryHeader->SizeOfPartitionEntry, EventSize); | ||
| 396 | + if (EFI_ERROR (Status)) { | ||
| 397 | + DEBUG ((DEBUG_ERROR, "Event Size would have overflowed!\n")); | ||
| 398 | + return EFI_BAD_BUFFER_SIZE; | ||
| 399 | + } | ||
| 400 | + | ||
| 401 | + Status = SafeUint32Add ( | ||
| 402 | + sizeof (TCG_PCR_EVENT_HDR) + | ||
| 403 | + OFFSET_OF (EFI_GPT_DATA, Partitions), | ||
| 404 | + *EventSize, | ||
| 405 | + EventSize | ||
| 406 | + ); | ||
| 407 | + if (EFI_ERROR (Status)) { | ||
| 408 | + DEBUG ((DEBUG_ERROR, "Event Size would have overflowed because of GPTData!\n")); | ||
| 409 | + return EFI_BAD_BUFFER_SIZE; | ||
| 410 | + } | ||
| 411 | + | ||
| 412 | + return EFI_SUCCESS; | ||
| 413 | +} | ||
| 414 | diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.h b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.h | ||
| 415 | new file mode 100644 | ||
| 416 | index 0000000000..0d9d00c281 | ||
| 417 | --- /dev/null | ||
| 418 | +++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.h | ||
| 419 | @@ -0,0 +1,114 @@ | ||
| 420 | +/** @file | ||
| 421 | + This file includes the function prototypes for the sanitization functions. | ||
| 422 | + | ||
| 423 | + These are those functions: | ||
| 424 | + | ||
| 425 | + DxeTpmMeasureBootLibImageRead() function will make sure the PE/COFF image content | ||
| 426 | + read is within the image buffer. | ||
| 427 | + | ||
| 428 | + TcgMeasurePeImage() function will accept untrusted PE/COFF image and validate its | ||
| 429 | + data structure within this image buffer before use. | ||
| 430 | + | ||
| 431 | + TcgMeasureGptTable() function will receive untrusted GPT partition table, and parse | ||
| 432 | + partition data carefully. | ||
| 433 | + | ||
| 434 | + Copyright (c) Microsoft Corporation.<BR> | ||
| 435 | + SPDX-License-Identifier: BSD-2-Clause-Patent | ||
| 436 | + | ||
| 437 | +**/ | ||
| 438 | + | ||
| 439 | +#ifndef DXE_TPM_MEASURE_BOOT_LIB_VALIDATION_ | ||
| 440 | +#define DXE_TPM_MEASURE_BOOT_LIB_VALIDATION_ | ||
| 441 | + | ||
| 442 | +#include <Uefi.h> | ||
| 443 | +#include <Uefi/UefiSpec.h> | ||
| 444 | +#include <Protocol/BlockIo.h> | ||
| 445 | +#include <IndustryStandard/UefiTcgPlatform.h> | ||
| 446 | + | ||
| 447 | +/** | ||
| 448 | + This function will validate the EFI_PARTITION_TABLE_HEADER structure is safe to parse | ||
| 449 | + However this function will not attempt to verify the validity of the GPT partition | ||
| 450 | + It will check the following: | ||
| 451 | + - Signature | ||
| 452 | + - Revision | ||
| 453 | + - AlternateLBA | ||
| 454 | + - FirstUsableLBA | ||
| 455 | + - LastUsableLBA | ||
| 456 | + - PartitionEntryLBA | ||
| 457 | + - NumberOfPartitionEntries | ||
| 458 | + - SizeOfPartitionEntry | ||
| 459 | + - BlockIo | ||
| 460 | + | ||
| 461 | + @param[in] PrimaryHeader | ||
| 462 | + Pointer to the EFI_PARTITION_TABLE_HEADER structure. | ||
| 463 | + | ||
| 464 | + @param[in] BlockIo | ||
| 465 | + Pointer to the EFI_BLOCK_IO_PROTOCOL structure. | ||
| 466 | + | ||
| 467 | + @retval EFI_SUCCESS | ||
| 468 | + The EFI_PARTITION_TABLE_HEADER structure is valid. | ||
| 469 | + | ||
| 470 | + @retval EFI_INVALID_PARAMETER | ||
| 471 | + The EFI_PARTITION_TABLE_HEADER structure is invalid. | ||
| 472 | +**/ | ||
| 473 | +EFI_STATUS | ||
| 474 | +EFIAPI | ||
| 475 | +SanitizeEfiPartitionTableHeader ( | ||
| 476 | + IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, | ||
| 477 | + IN CONST EFI_BLOCK_IO_PROTOCOL *BlockIo | ||
| 478 | + ); | ||
| 479 | + | ||
| 480 | +/** | ||
| 481 | + This function will validate that the allocation size from the primary header is sane | ||
| 482 | + It will check the following: | ||
| 483 | + - AllocationSize does not overflow | ||
| 484 | + | ||
| 485 | + @param[in] PrimaryHeader | ||
| 486 | + Pointer to the EFI_PARTITION_TABLE_HEADER structure. | ||
| 487 | + | ||
| 488 | + @param[out] AllocationSize | ||
| 489 | + Pointer to the allocation size. | ||
| 490 | + | ||
| 491 | + @retval EFI_SUCCESS | ||
| 492 | + The allocation size is valid. | ||
| 493 | + | ||
| 494 | + @retval EFI_OUT_OF_RESOURCES | ||
| 495 | + The allocation size is invalid. | ||
| 496 | +**/ | ||
| 497 | +EFI_STATUS | ||
| 498 | +EFIAPI | ||
| 499 | +SanitizePrimaryHeaderAllocationSize ( | ||
| 500 | + IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, | ||
| 501 | + OUT UINT32 *AllocationSize | ||
| 502 | + ); | ||
| 503 | + | ||
| 504 | +/** | ||
| 505 | + This function will validate that the Gpt Event Size calculated from the primary header is sane | ||
| 506 | + It will check the following: | ||
| 507 | + - EventSize does not overflow | ||
| 508 | + | ||
| 509 | + Important: This function includes the entire length of the allocated space, including the | ||
| 510 | + TCG_PCR_EVENT_HDR. When hashing the buffer allocated with this size, the caller must subtract | ||
| 511 | + the size of the TCG_PCR_EVENT_HDR from the size of the buffer before hashing. | ||
| 512 | + | ||
| 513 | + @param[in] PrimaryHeader - Pointer to the EFI_PARTITION_TABLE_HEADER structure. | ||
| 514 | + @param[in] NumberOfPartition - Number of partitions. | ||
| 515 | + @param[out] EventSize - Pointer to the event size. | ||
| 516 | + | ||
| 517 | + @retval EFI_SUCCESS | ||
| 518 | + The event size is valid. | ||
| 519 | + | ||
| 520 | + @retval EFI_OUT_OF_RESOURCES | ||
| 521 | + Overflow would have occurred. | ||
| 522 | + | ||
| 523 | + @retval EFI_INVALID_PARAMETER | ||
| 524 | + One of the passed parameters was invalid. | ||
| 525 | +**/ | ||
| 526 | +EFI_STATUS | ||
| 527 | +SanitizePrimaryHeaderGptEventSize ( | ||
| 528 | + IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, | ||
| 529 | + IN UINTN NumberOfPartition, | ||
| 530 | + OUT UINT32 *EventSize | ||
| 531 | + ); | ||
| 532 | + | ||
| 533 | +#endif // DXE_TPM_MEASURE_BOOT_LIB_VALIDATION_ | ||
| 534 | diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTest.c b/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTest.c | ||
| 535 | new file mode 100644 | ||
| 536 | index 0000000000..eeb928cdb0 | ||
| 537 | --- /dev/null | ||
| 538 | +++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTest.c | ||
| 539 | @@ -0,0 +1,301 @@ | ||
| 540 | +/** @file | ||
| 541 | +This file includes the unit test cases for the DxeTpmMeasureBootLibSanitizationTest.c. | ||
| 542 | + | ||
| 543 | +Copyright (c) Microsoft Corporation.<BR> | ||
| 544 | +SPDX-License-Identifier: BSD-2-Clause-Patent | ||
| 545 | +**/ | ||
| 546 | + | ||
| 547 | +#include <Uefi.h> | ||
| 548 | +#include <Library/UefiLib.h> | ||
| 549 | +#include <Library/DebugLib.h> | ||
| 550 | +#include <Library/UnitTestLib.h> | ||
| 551 | +#include <Protocol/BlockIo.h> | ||
| 552 | +#include <Library/MemoryAllocationLib.h> | ||
| 553 | +#include <Library/BaseMemoryLib.h> | ||
| 554 | +#include <IndustryStandard/UefiTcgPlatform.h> | ||
| 555 | + | ||
| 556 | +#include "../DxeTpmMeasureBootLibSanitization.h" | ||
| 557 | + | ||
| 558 | +#define UNIT_TEST_NAME "DxeTpmMeasureBootLibSanitizationTest" | ||
| 559 | +#define UNIT_TEST_VERSION "1.0" | ||
| 560 | + | ||
| 561 | +#define DEFAULT_PRIMARY_TABLE_HEADER_REVISION 0x00010000 | ||
| 562 | +#define DEFAULT_PRIMARY_TABLE_HEADER_NUMBER_OF_PARTITION_ENTRIES 1 | ||
| 563 | +#define DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY 128 | ||
| 564 | + | ||
| 565 | +/** | ||
| 566 | + This function tests the SanitizeEfiPartitionTableHeader function. | ||
| 567 | + It's intent is to test that a malicious EFI_PARTITION_TABLE_HEADER | ||
| 568 | + structure will not cause undefined or unexpected behavior. | ||
| 569 | + | ||
| 570 | + In general the TPM should still be able to measure the data, but | ||
| 571 | + be the header should be sanitized to prevent any unexpected behavior. | ||
| 572 | + | ||
| 573 | + @param[in] Context The unit test context. | ||
| 574 | + | ||
| 575 | + @retval UNIT_TEST_PASSED The test passed. | ||
| 576 | + @retval UNIT_TEST_ERROR_TEST_FAILED The test failed. | ||
| 577 | +**/ | ||
| 578 | +UNIT_TEST_STATUS | ||
| 579 | +EFIAPI | ||
| 580 | +TestSanitizeEfiPartitionTableHeader ( | ||
| 581 | + IN UNIT_TEST_CONTEXT Context | ||
| 582 | + ) | ||
| 583 | +{ | ||
| 584 | + EFI_STATUS Status; | ||
| 585 | + EFI_PARTITION_TABLE_HEADER PrimaryHeader; | ||
| 586 | + EFI_BLOCK_IO_PROTOCOL BlockIo; | ||
| 587 | + EFI_BLOCK_IO_MEDIA BlockMedia; | ||
| 588 | + | ||
| 589 | + // Generate EFI_BLOCK_IO_MEDIA test data | ||
| 590 | + BlockMedia.MediaId = 1; | ||
| 591 | + BlockMedia.RemovableMedia = FALSE; | ||
| 592 | + BlockMedia.MediaPresent = TRUE; | ||
| 593 | + BlockMedia.LogicalPartition = FALSE; | ||
| 594 | + BlockMedia.ReadOnly = FALSE; | ||
| 595 | + BlockMedia.WriteCaching = FALSE; | ||
| 596 | + BlockMedia.BlockSize = 512; | ||
| 597 | + BlockMedia.IoAlign = 1; | ||
| 598 | + BlockMedia.LastBlock = 0; | ||
| 599 | + | ||
| 600 | + // Generate EFI_BLOCK_IO_PROTOCOL test data | ||
| 601 | + BlockIo.Revision = 1; | ||
| 602 | + BlockIo.Media = &BlockMedia; | ||
| 603 | + BlockIo.Reset = NULL; | ||
| 604 | + BlockIo.ReadBlocks = NULL; | ||
| 605 | + BlockIo.WriteBlocks = NULL; | ||
| 606 | + BlockIo.FlushBlocks = NULL; | ||
| 607 | + | ||
| 608 | + // Geneate EFI_PARTITION_TABLE_HEADER test data | ||
| 609 | + PrimaryHeader.Header.Signature = EFI_PTAB_HEADER_ID; | ||
| 610 | + PrimaryHeader.Header.Revision = DEFAULT_PRIMARY_TABLE_HEADER_REVISION; | ||
| 611 | + PrimaryHeader.Header.HeaderSize = sizeof (EFI_PARTITION_TABLE_HEADER); | ||
| 612 | + PrimaryHeader.MyLBA = 1; | ||
| 613 | + PrimaryHeader.AlternateLBA = 2; | ||
| 614 | + PrimaryHeader.FirstUsableLBA = 3; | ||
| 615 | + PrimaryHeader.LastUsableLBA = 4; | ||
| 616 | + PrimaryHeader.PartitionEntryLBA = 5; | ||
| 617 | + PrimaryHeader.NumberOfPartitionEntries = DEFAULT_PRIMARY_TABLE_HEADER_NUMBER_OF_PARTITION_ENTRIES; | ||
| 618 | + PrimaryHeader.SizeOfPartitionEntry = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY; | ||
| 619 | + PrimaryHeader.PartitionEntryArrayCRC32 = 0; // Purposely invalid | ||
| 620 | + | ||
| 621 | + // Calculate the CRC32 of the PrimaryHeader | ||
| 622 | + PrimaryHeader.Header.CRC32 = CalculateCrc32 ((UINT8 *)&PrimaryHeader, PrimaryHeader.Header.HeaderSize); | ||
| 623 | + | ||
| 624 | + // Test that a normal PrimaryHeader passes validation | ||
| 625 | + Status = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo); | ||
| 626 | + UT_ASSERT_NOT_EFI_ERROR (Status); | ||
| 627 | + | ||
| 628 | + // Test that when number of partition entries is 0, the function returns EFI_DEVICE_ERROR | ||
| 629 | + // Should print "Invalid Partition Table Header NumberOfPartitionEntries!"" | ||
| 630 | + PrimaryHeader.NumberOfPartitionEntries = 0; | ||
| 631 | + Status = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo); | ||
| 632 | + UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR); | ||
| 633 | + PrimaryHeader.NumberOfPartitionEntries = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY; | ||
| 634 | + | ||
| 635 | + // Test that when the header size is too small, the function returns EFI_DEVICE_ERROR | ||
| 636 | + // Should print "Invalid Partition Table Header Size!" | ||
| 637 | + PrimaryHeader.Header.HeaderSize = 0; | ||
| 638 | + Status = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo); | ||
| 639 | + UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR); | ||
| 640 | + PrimaryHeader.Header.HeaderSize = sizeof (EFI_PARTITION_TABLE_HEADER); | ||
| 641 | + | ||
| 642 | + // Test that when the SizeOfPartitionEntry is too small, the function returns EFI_DEVICE_ERROR | ||
| 643 | + // should print: "SizeOfPartitionEntry shall be set to a value of 128 x 2^n where n is an integer greater than or equal to zero (e.g., 128, 256, 512, etc.)!" | ||
| 644 | + PrimaryHeader.SizeOfPartitionEntry = 1; | ||
| 645 | + Status = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo); | ||
| 646 | + UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR); | ||
| 647 | + | ||
| 648 | + DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__)); | ||
| 649 | + | ||
| 650 | + return UNIT_TEST_PASSED; | ||
| 651 | +} | ||
| 652 | + | ||
| 653 | +/** | ||
| 654 | + This function tests the SanitizePrimaryHeaderAllocationSize function. | ||
| 655 | + It's intent is to test that the untrusted input from a EFI_PARTITION_TABLE_HEADER | ||
| 656 | + structure will not cause an overflow when calculating the allocation size. | ||
| 657 | + | ||
| 658 | + @param[in] Context The unit test context. | ||
| 659 | + | ||
| 660 | + @retval UNIT_TEST_PASSED The test passed. | ||
| 661 | + @retval UNIT_TEST_ERROR_TEST_FAILED The test failed. | ||
| 662 | +**/ | ||
| 663 | +UNIT_TEST_STATUS | ||
| 664 | +EFIAPI | ||
| 665 | +TestSanitizePrimaryHeaderAllocationSize ( | ||
| 666 | + IN UNIT_TEST_CONTEXT Context | ||
| 667 | + ) | ||
| 668 | +{ | ||
| 669 | + UINT32 AllocationSize; | ||
| 670 | + | ||
| 671 | + EFI_STATUS Status; | ||
| 672 | + EFI_PARTITION_TABLE_HEADER PrimaryHeader; | ||
| 673 | + | ||
| 674 | + // Test that a normal PrimaryHeader passes validation | ||
| 675 | + PrimaryHeader.NumberOfPartitionEntries = 5; | ||
| 676 | + PrimaryHeader.SizeOfPartitionEntry = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY; | ||
| 677 | + | ||
| 678 | + Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); | ||
| 679 | + UT_ASSERT_NOT_EFI_ERROR (Status); | ||
| 680 | + | ||
| 681 | + // Test that the allocation size is correct compared to the existing logic | ||
| 682 | + UT_ASSERT_EQUAL (AllocationSize, PrimaryHeader.NumberOfPartitionEntries * PrimaryHeader.SizeOfPartitionEntry); | ||
| 683 | + | ||
| 684 | + // Test that an overflow is detected | ||
| 685 | + PrimaryHeader.NumberOfPartitionEntries = MAX_UINT32; | ||
| 686 | + PrimaryHeader.SizeOfPartitionEntry = 5; | ||
| 687 | + Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); | ||
| 688 | + UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); | ||
| 689 | + | ||
| 690 | + // Test the inverse | ||
| 691 | + PrimaryHeader.NumberOfPartitionEntries = 5; | ||
| 692 | + PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32; | ||
| 693 | + Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); | ||
| 694 | + UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); | ||
| 695 | + | ||
| 696 | + // Test the worst case scenario | ||
| 697 | + PrimaryHeader.NumberOfPartitionEntries = MAX_UINT32; | ||
| 698 | + PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32; | ||
| 699 | + Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); | ||
| 700 | + UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); | ||
| 701 | + | ||
| 702 | + DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__)); | ||
| 703 | + | ||
| 704 | + return UNIT_TEST_PASSED; | ||
| 705 | +} | ||
| 706 | + | ||
| 707 | +/** | ||
| 708 | + This function tests the SanitizePrimaryHeaderGptEventSize function. | ||
| 709 | + It's intent is to test that the untrusted input from a EFI_GPT_DATA structure | ||
| 710 | + will not cause an overflow when calculating the event size. | ||
| 711 | + | ||
| 712 | + @param[in] Context The unit test context. | ||
| 713 | + | ||
| 714 | + @retval UNIT_TEST_PASSED The test passed. | ||
| 715 | + @retval UNIT_TEST_ERROR_TEST_FAILED The test failed. | ||
| 716 | +**/ | ||
| 717 | +UNIT_TEST_STATUS | ||
| 718 | +EFIAPI | ||
| 719 | +TestSanitizePrimaryHeaderGptEventSize ( | ||
| 720 | + IN UNIT_TEST_CONTEXT Context | ||
| 721 | + ) | ||
| 722 | +{ | ||
| 723 | + UINT32 EventSize; | ||
| 724 | + UINT32 ExistingLogicEventSize; | ||
| 725 | + EFI_STATUS Status; | ||
| 726 | + EFI_PARTITION_TABLE_HEADER PrimaryHeader; | ||
| 727 | + UINTN NumberOfPartition; | ||
| 728 | + EFI_GPT_DATA *GptData; | ||
| 729 | + | ||
| 730 | + GptData = NULL; | ||
| 731 | + | ||
| 732 | + // Test that a normal PrimaryHeader passes validation | ||
| 733 | + PrimaryHeader.NumberOfPartitionEntries = 5; | ||
| 734 | + PrimaryHeader.SizeOfPartitionEntry = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY; | ||
| 735 | + | ||
| 736 | + // set the number of partitions | ||
| 737 | + NumberOfPartition = 13; | ||
| 738 | + | ||
| 739 | + // that the primary event size is correct | ||
| 740 | + Status = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, &EventSize); | ||
| 741 | + UT_ASSERT_NOT_EFI_ERROR (Status); | ||
| 742 | + | ||
| 743 | + // Calculate the existing logic event size | ||
| 744 | + ExistingLogicEventSize = (UINT32)(sizeof (TCG_PCR_EVENT_HDR) + OFFSET_OF (EFI_GPT_DATA, Partitions) | ||
| 745 | + + NumberOfPartition * PrimaryHeader.SizeOfPartitionEntry); | ||
| 746 | + | ||
| 747 | + // Check that the event size is correct | ||
| 748 | + UT_ASSERT_EQUAL (EventSize, ExistingLogicEventSize); | ||
| 749 | + | ||
| 750 | + // Tests that the primary event size may not overflow | ||
| 751 | + Status = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, MAX_UINT32, &EventSize); | ||
| 752 | + UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); | ||
| 753 | + | ||
| 754 | + // Test that the size of partition entries may not overflow | ||
| 755 | + PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32; | ||
| 756 | + Status = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, &EventSize); | ||
| 757 | + UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); | ||
| 758 | + | ||
| 759 | + DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__)); | ||
| 760 | + | ||
| 761 | + return UNIT_TEST_PASSED; | ||
| 762 | +} | ||
| 763 | + | ||
| 764 | +// *--------------------------------------------------------------------* | ||
| 765 | +// * Unit Test Code Main Function | ||
| 766 | +// *--------------------------------------------------------------------* | ||
| 767 | + | ||
| 768 | +/** | ||
| 769 | + This function acts as the entry point for the unit tests. | ||
| 770 | + | ||
| 771 | + @param argc - The number of command line arguments | ||
| 772 | + @param argv - The command line arguments | ||
| 773 | + | ||
| 774 | + @return int - The status of the test | ||
| 775 | +**/ | ||
| 776 | +EFI_STATUS | ||
| 777 | +EFIAPI | ||
| 778 | +UefiTestMain ( | ||
| 779 | + VOID | ||
| 780 | + ) | ||
| 781 | +{ | ||
| 782 | + EFI_STATUS Status; | ||
| 783 | + UNIT_TEST_FRAMEWORK_HANDLE Framework; | ||
| 784 | + UNIT_TEST_SUITE_HANDLE TcgMeasureBootLibValidationTestSuite; | ||
| 785 | + | ||
| 786 | + Framework = NULL; | ||
| 787 | + | ||
| 788 | + DEBUG ((DEBUG_INFO, "%a: TestMain() - Start\n", UNIT_TEST_NAME)); | ||
| 789 | + | ||
| 790 | + Status = InitUnitTestFramework (&Framework, UNIT_TEST_NAME, gEfiCallerBaseName, UNIT_TEST_VERSION); | ||
| 791 | + if (EFI_ERROR (Status)) { | ||
| 792 | + DEBUG ((DEBUG_ERROR, "%a: Failed in InitUnitTestFramework. Status = %r\n", UNIT_TEST_NAME, Status)); | ||
| 793 | + goto EXIT; | ||
| 794 | + } | ||
| 795 | + | ||
| 796 | + Status = CreateUnitTestSuite (&TcgMeasureBootLibValidationTestSuite, Framework, "TcgMeasureBootLibValidationTestSuite", "Common.TcgMeasureBootLibValidation", NULL, NULL); | ||
| 797 | + if (EFI_ERROR (Status)) { | ||
| 798 | + DEBUG ((DEBUG_ERROR, "%s: Failed in CreateUnitTestSuite for TcgMeasureBootLibValidationTestSuite\n", UNIT_TEST_NAME)); | ||
| 799 | + Status = EFI_OUT_OF_RESOURCES; | ||
| 800 | + goto EXIT; | ||
| 801 | + } | ||
| 802 | + | ||
| 803 | + // -----------Suite---------------------------------Description----------------------------Class----------------------------------Test Function------------------------Pre---Clean-Context | ||
| 804 | + AddTestCase (TcgMeasureBootLibValidationTestSuite, "Tests Validating EFI Partition Table", "Common.TcgMeasureBootLibValidation", TestSanitizeEfiPartitionTableHeader, NULL, NULL, NULL); | ||
| 805 | + AddTestCase (TcgMeasureBootLibValidationTestSuite, "Tests Primary header gpt event checks for overflow", "Common.TcgMeasureBootLibValidation", TestSanitizePrimaryHeaderAllocationSize, NULL, NULL, NULL); | ||
| 806 | + AddTestCase (TcgMeasureBootLibValidationTestSuite, "Tests Primary header allocation size checks for overflow", "Common.TcgMeasureBootLibValidation", TestSanitizePrimaryHeaderGptEventSize, NULL, NULL, NULL); | ||
| 807 | + | ||
| 808 | + Status = RunAllTestSuites (Framework); | ||
| 809 | + | ||
| 810 | +EXIT: | ||
| 811 | + if (Framework != NULL) { | ||
| 812 | + FreeUnitTestFramework (Framework); | ||
| 813 | + } | ||
| 814 | + | ||
| 815 | + DEBUG ((DEBUG_INFO, "%a: TestMain() - End\n", UNIT_TEST_NAME)); | ||
| 816 | + return Status; | ||
| 817 | +} | ||
| 818 | + | ||
| 819 | +/// | ||
| 820 | +/// Avoid ECC error for function name that starts with lower case letter | ||
| 821 | +/// | ||
| 822 | +#define DxeTpmMeasureBootLibUnitTestMain main | ||
| 823 | + | ||
| 824 | +/** | ||
| 825 | + Standard POSIX C entry point for host based unit test execution. | ||
| 826 | + | ||
| 827 | + @param[in] Argc Number of arguments | ||
| 828 | + @param[in] Argv Array of pointers to arguments | ||
| 829 | + | ||
| 830 | + @retval 0 Success | ||
| 831 | + @retval other Error | ||
| 832 | +**/ | ||
| 833 | +INT32 | ||
| 834 | +DxeTpmMeasureBootLibUnitTestMain ( | ||
| 835 | + IN INT32 Argc, | ||
| 836 | + IN CHAR8 *Argv[] | ||
| 837 | + ) | ||
| 838 | +{ | ||
| 839 | + return (INT32)UefiTestMain (); | ||
| 840 | +} | ||
| 841 | diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTestHost.inf b/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTestHost.inf | ||
| 842 | new file mode 100644 | ||
| 843 | index 0000000000..47b0811b00 | ||
| 844 | --- /dev/null | ||
| 845 | +++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTestHost.inf | ||
| 846 | @@ -0,0 +1,28 @@ | ||
| 847 | +## @file | ||
| 848 | +# This file builds the unit tests for DxeTpmMeasureBootLib | ||
| 849 | +# | ||
| 850 | +# Copyright (C) Microsoft Corporation.<BR> | ||
| 851 | +# SPDX-License-Identifier: BSD-2-Clause-Patent | ||
| 852 | +## | ||
| 853 | + | ||
| 854 | +[Defines] | ||
| 855 | + INF_VERSION = 0x00010006 | ||
| 856 | + BASE_NAME = DxeTpmMeasuredBootLibTest | ||
| 857 | + FILE_GUID = eb01bc38-309c-4d3e-967e-9f078c90772f | ||
| 858 | + MODULE_TYPE = HOST_APPLICATION | ||
| 859 | + VERSION_STRING = 1.0 | ||
| 860 | + ENTRY_POINT = main | ||
| 861 | + | ||
| 862 | +[Sources] | ||
| 863 | + DxeTpmMeasureBootLibSanitizationTest.c | ||
| 864 | + ../DxeTpmMeasureBootLibSanitization.c | ||
| 865 | + | ||
| 866 | +[Packages] | ||
| 867 | + MdePkg/MdePkg.dec | ||
| 868 | + | ||
| 869 | +[LibraryClasses] | ||
| 870 | + BaseLib | ||
| 871 | + DebugLib | ||
| 872 | + UnitTestLib | ||
| 873 | + PrintLib | ||
| 874 | + SafeIntLib | ||
| 875 | diff --git a/SecurityPkg/SecurityPkg.ci.yaml b/SecurityPkg/SecurityPkg.ci.yaml | ||
| 876 | index da811fdf93..0e40eaa0fe 100644 | ||
| 877 | --- a/SecurityPkg/SecurityPkg.ci.yaml | ||
| 878 | +++ b/SecurityPkg/SecurityPkg.ci.yaml | ||
| 879 | @@ -16,6 +16,7 @@ | ||
| 880 | ## ] | ||
| 881 | "ExceptionList": [ | ||
| 882 | "8001", "DxeTpm2MeasureBootLibUnitTestMain", | ||
| 883 | + "8001", "DxeTpmMeasureBootLibUnitTestMain" | ||
| 884 | ], | ||
| 885 | ## Both file path and directory path are accepted. | ||
| 886 | "IgnoreFiles": [ | ||
| 887 | -- | ||
| 888 | 2.40.0 | ||
| 889 | |||
diff --git a/meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0003.patch b/meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0003.patch new file mode 100644 index 0000000000..59bd5c4910 --- /dev/null +++ b/meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0003.patch | |||
| @@ -0,0 +1,55 @@ | |||
| 1 | From 1ddcb9fc6b4164e882687b031e8beacfcf7df29e Mon Sep 17 00:00:00 2001 | ||
| 2 | From: "Douglas Flick [MSFT]" <doug.edk2@gmail.com> | ||
| 3 | Date: Fri, 12 Jan 2024 02:16:03 +0800 | ||
| 4 | Subject: [PATCH] SecurityPkg: : Adding CVE 2022-36763 to SecurityFixes.yaml | ||
| 5 | |||
| 6 | This creates / adds a security file that tracks the security fixes | ||
| 7 | found in this package and can be used to find the fixes that were | ||
| 8 | applied. | ||
| 9 | |||
| 10 | Cc: Jiewen Yao <jiewen.yao@intel.com> | ||
| 11 | |||
| 12 | Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com> | ||
| 13 | Reviewed-by: Jiewen Yao <jiewen.yao@intel.com> | ||
| 14 | |||
| 15 | CVE: CVE-2022-36763 | ||
| 16 | |||
| 17 | Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/1ddcb9fc6b4164e882687b031e8beacfcf7df29e] | ||
| 18 | |||
| 19 | Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com> | ||
| 20 | --- | ||
| 21 | SecurityPkg/SecurityFixes.yaml | 22 ++++++++++++++++++++++ | ||
| 22 | 1 file changed, 22 insertions(+) | ||
| 23 | create mode 100644 SecurityPkg/SecurityFixes.yaml | ||
| 24 | |||
| 25 | diff --git a/SecurityPkg/SecurityFixes.yaml b/SecurityPkg/SecurityFixes.yaml | ||
| 26 | new file mode 100644 | ||
| 27 | index 0000000000..f9e3e7be74 | ||
| 28 | --- /dev/null | ||
| 29 | +++ b/SecurityPkg/SecurityFixes.yaml | ||
| 30 | @@ -0,0 +1,22 @@ | ||
| 31 | +## @file | ||
| 32 | +# Security Fixes for SecurityPkg | ||
| 33 | +# | ||
| 34 | +# Copyright (c) Microsoft Corporation | ||
| 35 | +# SPDX-License-Identifier: BSD-2-Clause-Patent | ||
| 36 | +## | ||
| 37 | +CVE_2022_36763: | ||
| 38 | + commit_titles: | ||
| 39 | + - "SecurityPkg: DxeTpm2Measurement: SECURITY PATCH 4117 - CVE 2022-36763" | ||
| 40 | + - "SecurityPkg: DxeTpmMeasurement: SECURITY PATCH 4117 - CVE 2022-36763" | ||
| 41 | + - "SecurityPkg: : Adding CVE 2022-36763 to SecurityFixes.yaml" | ||
| 42 | + cve: CVE-2022-36763 | ||
| 43 | + date_reported: 2022-10-25 11:31 UTC | ||
| 44 | + description: (CVE-2022-36763) - Heap Buffer Overflow in Tcg2MeasureGptTable() | ||
| 45 | + note: This patch is related to and supersedes TCBZ2168 | ||
| 46 | + files_impacted: | ||
| 47 | + - Library\DxeTpm2MeasureBootLib\DxeTpm2MeasureBootLib.c | ||
| 48 | + - Library\DxeTpmMeasureBootLib\DxeTpmMeasureBootLib.c | ||
| 49 | + links: | ||
| 50 | + - https://bugzilla.tianocore.org/show_bug.cgi?id=4117 | ||
| 51 | + - https://bugzilla.tianocore.org/show_bug.cgi?id=2168 | ||
| 52 | + - https://bugzilla.tianocore.org/show_bug.cgi?id=1990 | ||
| 53 | -- | ||
| 54 | 2.40.0 | ||
| 55 | |||
diff --git a/meta/recipes-core/ovmf/ovmf_git.bb b/meta/recipes-core/ovmf/ovmf_git.bb index 84e3360a3a..78d86ad879 100644 --- a/meta/recipes-core/ovmf/ovmf_git.bb +++ b/meta/recipes-core/ovmf/ovmf_git.bb | |||
| @@ -27,6 +27,9 @@ SRC_URI = "gitsm://github.com/tianocore/edk2.git;branch=master;protocol=https \ | |||
| 27 | file://0006-reproducible.patch \ | 27 | file://0006-reproducible.patch \ |
| 28 | file://0001-BaseTools-fix-gcc12-warning.patch \ | 28 | file://0001-BaseTools-fix-gcc12-warning.patch \ |
| 29 | file://0001-BaseTools-fix-gcc12-warning-1.patch \ | 29 | file://0001-BaseTools-fix-gcc12-warning-1.patch \ |
| 30 | file://CVE-2022-36763-0001.patch \ | ||
| 31 | file://CVE-2022-36763-0002.patch \ | ||
| 32 | file://CVE-2022-36763-0003.patch \ | ||
| 30 | " | 33 | " |
| 31 | 34 | ||
| 32 | PV = "edk2-stable202202" | 35 | PV = "edk2-stable202202" |
