gsctool: require exactly two hash sections for every board

The same Chrome OS device could have not only several released
firmware images, but also several variations of the GBB contents. Any
permutation of these two sets is possible, but both areas must match,
as modified GBB is no smaller problem than modified code or RO data.

With this patch the verifier will continue looking for board sections
in the descriptors database until the entire database has been
scanned. Only finding exactly two sections, and each section providing
proper matches will qualify the check as 'pass'.

BRANCH=none
BUG=b:73668125
TEST=verified that both single and dual section descriptions are
     processed properly, and that matching 1 and 3 sections triggers a
     return error.

Change-Id: I181655192246ce245c43e6ce7ba4768ac5c9e51a
Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/951864
Reviewed-by: Andrey Pronin <apronin@chromium.org>
This commit is contained in:
Vadim Bendebury
2018-03-06 11:31:08 -08:00
committed by chrome-bot
parent 9e95ac3e0a
commit ccbba8f968
2 changed files with 62 additions and 42 deletions

View File

@@ -18,6 +18,12 @@ static FILE *hash_file_;
static int line_count_;
static int section_count_;
/*
* This is used to verify consistency of the description database, namely that
* all hash sections include the same number of hash variants.
*/
static size_t variant_count;
/* Size of the retrieved string or negative OS error value. */
static ssize_t get_next_line(char *next_line, size_t line_size)
{
@@ -238,13 +244,6 @@ int parser_get_next_range(struct addr_range **range)
struct addr_range *new_range;
int rv;
/*
* This is used to verify consistency of the description database,
* namely that all hash sections include the same numger of hash
* variants.
*/
static size_t variant_count;
/*
* We come here after hash descriptor database file was opened and the
* current board's section has been found. Just in case check if the
@@ -308,11 +307,13 @@ int parser_find_board(const char *hash_file_name, const char *board_id)
char next_line[1000]; /* Should be enough for the largest descriptor. */
ssize_t id_len = strlen(board_id);
hash_file_ = fopen(hash_file_name, "r");
if (!hash_file_) {
fprintf(stderr, "Error:%s can not open file '%s'\n",
strerror(errno), hash_file_name);
return errno;
hash_file_ = fopen(hash_file_name, "r");
if (!hash_file_) {
fprintf(stderr, "Error:%s can not open file '%s'\n",
strerror(errno), hash_file_name);
return errno;
}
}
while (1) {
@@ -320,18 +321,17 @@ int parser_find_board(const char *hash_file_name, const char *board_id)
entry_size = get_next_line(next_line, sizeof(next_line));
if (entry_size < 0) {
fclose(hash_file_);
return entry_size;
}
if ((entry_size == id_len) &&
!memcmp(next_line, board_id, id_len))
!memcmp(next_line, board_id, id_len)) {
variant_count = 0;
return 0;
}
}
fclose(hash_file_);
hash_file_ = NULL;
return errno;
return -ENODATA;
}
void parser_done(void)

View File

@@ -15,6 +15,8 @@
#include "tpm_vendor_cmds.h"
#include "verify_ro.h"
/* Index of the matching hash variant. */
static ssize_t matching_variant;
/*
* Print out passed in buffer contents in hex, 16 bytes per line, each line
@@ -114,13 +116,12 @@ static int set_new_range(struct transfer_descriptor *td,
* pointer structure req has the range offset and size already initialized.
*
* Make sure that matching hashes are at the same index in the hash variants
* array in all hash sections.
* arrays within the same board section.
*/
static int verify_hash_section(struct transfer_descriptor *td,
struct vendor_cc_spi_hash_request *req,
struct addr_range *range)
{
static ssize_t matching_range = -1;
size_t i;
uint8_t response[sizeof(range->variants->expected_result)];
size_t response_size;
@@ -145,14 +146,14 @@ static int verify_hash_section(struct transfer_descriptor *td,
return -EINVAL;
}
if (matching_range < 0) {
if (matching_variant < 0) {
/* This is the first hash range to be processed. */
struct result_node *variant = range->variants;
for (i = 0; i < range->variant_count; i++) {
if (!memcmp(variant->expected_result,
response, response_size)) {
matching_range = i;
matching_variant = i;
return 0;
}
variant++;
@@ -163,7 +164,7 @@ static int verify_hash_section(struct transfer_descriptor *td,
return -EINVAL;
}
if (!memcmp(range->variants[matching_range].expected_result,
if (!memcmp(range->variants[matching_variant].expected_result,
response, response_size))
return 0;
@@ -286,21 +287,7 @@ static int process_descriptor_sections(struct transfer_descriptor *td)
if (range)
free(range);
parser_done();
if (rv)
return rv;
memset(&req, 0, sizeof(req));
req.subcmd = SPI_HASH_SUBCMD_DISABLE;
rv = send_vendor_command(td, VENDOR_CC_SPI_HASH, &req,
sizeof(req), 0, NULL);
if (rv) {
fprintf(stderr,
"%s: spi hash disable TPM error %d\n", __func__, rv);
return -EINVAL;
}
return 0;
return rv;
}
int verify_ro(struct transfer_descriptor *td,
@@ -309,6 +296,8 @@ int verify_ro(struct transfer_descriptor *td,
/* First find out board ID of the target. */
struct board_id bid;
char rlz_code[sizeof(bid.type) + 1];
int section_count = 0;
int rv = 0;
/*
* Find out what Board ID is the device we are talking to. This
@@ -329,12 +318,43 @@ int verify_ro(struct transfer_descriptor *td,
memcpy(rlz_code, &bid.type, sizeof(rlz_code) - 1);
rlz_code[sizeof(rlz_code) - 1] = '\0';
if (!parser_find_board(desc_file_name, rlz_code)) {
/* Opened the file and found descriptors for DUT. */
printf("Processing sections for board ID %s\n", rlz_code);
return process_descriptor_sections(td);
while (!parser_find_board(desc_file_name, rlz_code)) {
/*
* Each board section might have different index of the
* matching hash variant.
*/
matching_variant = -1;
section_count++;
rv = process_descriptor_sections(td);
if (rv)
break;
}
printf("No description for board ID %s found\n", rlz_code);
return -1;
if (section_count != 2) {
printf("Found wrong number of sections (%d) for board ID %s\n",
section_count, rlz_code);
rv = -EINVAL;
} else if (!rv) {
/*
* Check was successful, send command to exit verification
* mode.
*/
struct vendor_cc_spi_hash_request req;
memset(&req, 0, sizeof(req));
req.subcmd = SPI_HASH_SUBCMD_DISABLE;
rv = send_vendor_command(td, VENDOR_CC_SPI_HASH, &req,
sizeof(req), 0, NULL);
if (rv) {
fprintf(stderr,
"%s: spi hash disable TPM error %d\n",
__func__, rv);
rv = -EINVAL;
}
}
parser_done();
return rv;
}