Merge changes from topic "part_crc" into integration

* changes:
  feat(gpt): validate CRC of GPT partition entries
  refactor(gpt): return header instead of part_lba
This commit is contained in:
Manish V Badarkhe 2024-02-28 11:24:41 +01:00 committed by TrustedFirmware Code Review
commit 92c36b31a1

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2016-2023, Arm Limited and Contributors. All rights reserved. * Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved.
* *
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
@ -94,9 +94,8 @@ static int load_mbr_header(uintptr_t image_handle, mbr_entry_t *mbr_entry)
* If partition numbers could be found, check & update it. * If partition numbers could be found, check & update it.
*/ */
static int load_gpt_header(uintptr_t image_handle, size_t header_offset, static int load_gpt_header(uintptr_t image_handle, size_t header_offset,
unsigned long long *part_lba) gpt_header_t *header)
{ {
gpt_header_t header;
size_t bytes_read; size_t bytes_read;
int result; int result;
uint32_t header_crc, calc_crc; uint32_t header_crc, calc_crc;
@ -107,7 +106,7 @@ static int load_gpt_header(uintptr_t image_handle, size_t header_offset,
header_offset); header_offset);
return result; return result;
} }
result = io_read(image_handle, (uintptr_t)&header, result = io_read(image_handle, (uintptr_t)header,
sizeof(gpt_header_t), &bytes_read); sizeof(gpt_header_t), &bytes_read);
if ((result != 0) || (sizeof(gpt_header_t) != bytes_read)) { if ((result != 0) || (sizeof(gpt_header_t) != bytes_read)) {
VERBOSE("GPT header read error(%i) or read mismatch occurred," VERBOSE("GPT header read error(%i) or read mismatch occurred,"
@ -115,8 +114,8 @@ static int load_gpt_header(uintptr_t image_handle, size_t header_offset,
sizeof(gpt_header_t), bytes_read); sizeof(gpt_header_t), bytes_read);
return result; return result;
} }
if (memcmp(header.signature, GPT_SIGNATURE, if (memcmp(header->signature, GPT_SIGNATURE,
sizeof(header.signature)) != 0) { sizeof(header->signature)) != 0) {
VERBOSE("GPT header signature failure\n"); VERBOSE("GPT header signature failure\n");
return -EINVAL; return -EINVAL;
} }
@ -126,25 +125,24 @@ static int load_gpt_header(uintptr_t image_handle, size_t header_offset,
* computed by setting this field to 0, and computing the * computed by setting this field to 0, and computing the
* 32-bit CRC for HeaderSize bytes. * 32-bit CRC for HeaderSize bytes.
*/ */
header_crc = header.header_crc; header_crc = header->header_crc;
header.header_crc = 0U; header->header_crc = 0U;
calc_crc = tf_crc32(0U, (uint8_t *)&header, sizeof(gpt_header_t)); calc_crc = tf_crc32(0U, (uint8_t *)header, sizeof(gpt_header_t));
if (header_crc != calc_crc) { if (header_crc != calc_crc) {
ERROR("Invalid GPT Header CRC: Expected 0x%x but got 0x%x.\n", ERROR("Invalid GPT Header CRC: Expected 0x%x but got 0x%x.\n",
header_crc, calc_crc); header_crc, calc_crc);
return -EINVAL; return -EINVAL;
} }
header.header_crc = header_crc; header->header_crc = header_crc;
/* partition numbers can't exceed PLAT_PARTITION_MAX_ENTRIES */ /* partition numbers can't exceed PLAT_PARTITION_MAX_ENTRIES */
list.entry_count = header.list_num; list.entry_count = header->list_num;
if (list.entry_count > PLAT_PARTITION_MAX_ENTRIES) { if (list.entry_count > PLAT_PARTITION_MAX_ENTRIES) {
list.entry_count = PLAT_PARTITION_MAX_ENTRIES; list.entry_count = PLAT_PARTITION_MAX_ENTRIES;
} }
*part_lba = header.part_lba;
return 0; return 0;
} }
@ -231,12 +229,13 @@ static int load_gpt_entry(uintptr_t image_handle, gpt_entry_t *entry)
* Retrieve each entry in the partition table, parse the data from each * Retrieve each entry in the partition table, parse the data from each
* entry and store them in the list of partition table entries. * entry and store them in the list of partition table entries.
*/ */
static int load_partition_gpt(uintptr_t image_handle, static int load_partition_gpt(uintptr_t image_handle, gpt_header_t header)
unsigned long long part_lba)
{ {
const signed long long gpt_entry_offset = LBA(part_lba); const signed long long gpt_entry_offset = LBA(header.part_lba);
gpt_entry_t entry; gpt_entry_t entry;
int result, i; int result;
unsigned int i;
uint32_t calc_crc = 0U;
result = io_seek(image_handle, IO_SEEK_SET, gpt_entry_offset); result = io_seek(image_handle, IO_SEEK_SET, gpt_entry_offset);
if (result != 0) { if (result != 0) {
@ -245,23 +244,36 @@ static int load_partition_gpt(uintptr_t image_handle,
return result; return result;
} }
for (i = 0; i < list.entry_count; i++) { for (i = 0; i < (unsigned int)list.entry_count; i++) {
result = load_gpt_entry(image_handle, &entry); result = load_gpt_entry(image_handle, &entry);
if (result != 0) { if (result != 0) {
VERBOSE("Failed to load gpt entry data(%i) error is (%i)\n", VERBOSE("Failed to load gpt entry data(%u) error is (%i)\n",
i, result); i, result);
return result; return result;
} }
result = parse_gpt_entry(&entry, &list.list[i]); result = parse_gpt_entry(&entry, &list.list[i]);
if (result != 0) { if (result != 0) {
result = io_seek(image_handle, IO_SEEK_SET,
(gpt_entry_offset + (i * sizeof(gpt_entry_t))));
if (result != 0) {
VERBOSE("Failed to seek (%i)\n", result);
return result;
}
break; break;
} }
/*
* Calculate CRC of Partition entry array to compare with CRC
* value in header
*/
calc_crc = tf_crc32(calc_crc, (uint8_t *)&entry, sizeof(gpt_entry_t));
} }
if (i == 0) { if (i == 0) {
VERBOSE("No Valid GPT Entries found\n"); VERBOSE("No Valid GPT Entries found\n");
return -EINVAL; return -EINVAL;
} }
/* /*
* Only records the valid partition number that is loaded from * Only records the valid partition number that is loaded from
* partition table. * partition table.
@ -269,6 +281,29 @@ static int load_partition_gpt(uintptr_t image_handle,
list.entry_count = i; list.entry_count = i;
dump_entries(list.entry_count); dump_entries(list.entry_count);
/*
* If there are less valid entries than the possible number of entries
* from the header, continue to load the partition entry table to
* calculate the full CRC in order to check against the partition CRC
* from the header for validation.
*/
for (; i < header.list_num; i++) {
result = load_gpt_entry(image_handle, &entry);
if (result != 0) {
VERBOSE("Failed to load gpt entry data(%u) error is (%i)\n",
i, result);
return result;
}
calc_crc = tf_crc32(calc_crc, (uint8_t *)&entry, sizeof(gpt_entry_t));
}
if (header.part_crc != calc_crc) {
ERROR("Invalid GPT Partition Array Entry CRC: Expected 0x%x"
" but got 0x%x.\n", header.part_crc, calc_crc);
return -EINVAL;
}
return 0; return 0;
} }
@ -279,7 +314,7 @@ static int load_partition_gpt(uintptr_t image_handle,
static int load_backup_gpt(unsigned int image_id, unsigned int sector_nums) static int load_backup_gpt(unsigned int image_id, unsigned int sector_nums)
{ {
int result; int result;
unsigned long long part_lba = 0; gpt_header_t header;
size_t gpt_header_offset; size_t gpt_header_offset;
uintptr_t dev_handle, image_spec, image_handle; uintptr_t dev_handle, image_spec, image_handle;
io_block_spec_t *block_spec; io_block_spec_t *block_spec;
@ -316,8 +351,8 @@ static int load_backup_gpt(unsigned int image_id, unsigned int sector_nums)
INFO("Trying to retrieve back-up GPT header\n"); INFO("Trying to retrieve back-up GPT header\n");
/* Last block is backup-GPT header, after the end of GPT entries */ /* Last block is backup-GPT header, after the end of GPT entries */
gpt_header_offset = LBA(part_num_entries); gpt_header_offset = LBA(part_num_entries);
result = load_gpt_header(image_handle, gpt_header_offset, &part_lba); result = load_gpt_header(image_handle, gpt_header_offset, &header);
if ((result != 0) || (part_lba == 0)) { if ((result != 0) || (header.part_lba == 0)) {
ERROR("Failed to retrieve Backup GPT header," ERROR("Failed to retrieve Backup GPT header,"
"Partition maybe corrupted\n"); "Partition maybe corrupted\n");
goto out; goto out;
@ -327,7 +362,8 @@ static int load_backup_gpt(unsigned int image_id, unsigned int sector_nums)
* Note we mapped last 33 blocks(LBA-33), first block here starts with * Note we mapped last 33 blocks(LBA-33), first block here starts with
* entries while last block was header. * entries while last block was header.
*/ */
result = load_partition_gpt(image_handle, 0); header.part_lba = 0;
result = load_partition_gpt(image_handle, header);
out: out:
io_close(image_handle); io_close(image_handle);
@ -342,19 +378,19 @@ out:
static int load_primary_gpt(uintptr_t image_handle, unsigned int first_lba) static int load_primary_gpt(uintptr_t image_handle, unsigned int first_lba)
{ {
int result; int result;
unsigned long long part_lba;
size_t gpt_header_offset; size_t gpt_header_offset;
gpt_header_t header;
/* Try to load Primary GPT header from LBA1 */ /* Try to load Primary GPT header from LBA1 */
gpt_header_offset = LBA(first_lba); gpt_header_offset = LBA(first_lba);
result = load_gpt_header(image_handle, gpt_header_offset, &part_lba); result = load_gpt_header(image_handle, gpt_header_offset, &header);
if ((result != 0) || (part_lba == 0)) { if ((result != 0) || (header.part_lba == 0)) {
VERBOSE("Failed to retrieve Primary GPT header," VERBOSE("Failed to retrieve Primary GPT header,"
"trying to retrieve back-up GPT header\n"); "trying to retrieve back-up GPT header\n");
return result; return result;
} }
return load_partition_gpt(image_handle, part_lba); return load_partition_gpt(image_handle, header);
} }
/* /*