mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-11-24 02:05:01 +00:00
Add hwid digest field to GBB header
This adds a field in the GBB header to store the sha256 digest of the HWID string, and updates gbb_utility so that it stores the digest when it modifies the HWID. Because this is a new field, the GBB_MINOR_VER is incremented. BUG=chromium:415227 BRANCH=ToT TEST=make runtests, VBOOT2=1 make runtests Since the GBB is in the RO firmware, there should be no side effects for existing devices (but even without that, they should handle a minor version change without complaint). Change-Id: Icdb2a0b564677b0b65e58df897d2ec5af3964998 Signed-off-by: Bill Richardson <wfrichar@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/221360
This commit is contained in:
committed by
chrome-internal-fetch
parent
8bb3689d42
commit
6df3e33912
2
Makefile
2
Makefile
@@ -175,7 +175,7 @@ endif
|
|||||||
|
|
||||||
# And a few more default utilities
|
# And a few more default utilities
|
||||||
LD = ${CC}
|
LD = ${CC}
|
||||||
CXX ?= g++ # HEY: really?
|
CXX ?= g++
|
||||||
PKG_CONFIG ?= pkg-config
|
PKG_CONFIG ?= pkg-config
|
||||||
|
|
||||||
# Determine QEMU architecture needed, if any
|
# Determine QEMU architecture needed, if any
|
||||||
|
|||||||
@@ -315,7 +315,8 @@ struct vb2_shared_data {
|
|||||||
|
|
||||||
/* VB2 GBB struct version */
|
/* VB2 GBB struct version */
|
||||||
#define VB2_GBB_MAJOR_VER 1
|
#define VB2_GBB_MAJOR_VER 1
|
||||||
#define VB2_GBB_MINOR_VER 1
|
#define VB2_GBB_MINOR_VER 2
|
||||||
|
/* v1.2 - added fields for sha256 digest of the HWID */
|
||||||
|
|
||||||
/* Flags for vb2_gbb_header.flags */
|
/* Flags for vb2_gbb_header.flags */
|
||||||
enum vb2_gbb_flag {
|
enum vb2_gbb_flag {
|
||||||
@@ -388,7 +389,13 @@ struct vb2_gbb_header {
|
|||||||
uint32_t recovery_key_offset; /* Recovery key */
|
uint32_t recovery_key_offset; /* Recovery key */
|
||||||
uint32_t recovery_key_size;
|
uint32_t recovery_key_size;
|
||||||
|
|
||||||
uint8_t pad[80]; /* To match GBB_HEADER_SIZE. Initialize to 0. */
|
/* Added in version 1.2 */
|
||||||
|
uint8_t hwid_digest[32]; /* sha256 */
|
||||||
|
|
||||||
|
uint8_t pad[48]; /* To match EXPECTED_GBB_HEADER_SIZE. Init to 0. */
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
/* The GBB is used outside of vboot_reference, so this size is important. */
|
||||||
|
#define EXPECTED_GBB_HEADER_SIZE 128
|
||||||
|
|
||||||
#endif /* VBOOT_REFERENCE_VBOOT_2STRUCT_H_ */
|
#endif /* VBOOT_REFERENCE_VBOOT_2STRUCT_H_ */
|
||||||
|
|||||||
@@ -26,7 +26,8 @@
|
|||||||
* return default values for those fields.
|
* return default values for those fields.
|
||||||
*/
|
*/
|
||||||
#define GBB_MAJOR_VER 1
|
#define GBB_MAJOR_VER 1
|
||||||
#define GBB_MINOR_VER 1
|
#define GBB_MINOR_VER 2
|
||||||
|
/* v1.2 - added field to hold sha256 digest of the HWID */
|
||||||
|
|
||||||
/* Maximum length of a HWID in bytes, counting terminating null. */
|
/* Maximum length of a HWID in bytes, counting terminating null. */
|
||||||
#define GBB_HWID_MAX_SIZE 256
|
#define GBB_HWID_MAX_SIZE 256
|
||||||
@@ -86,8 +87,10 @@ typedef struct GoogleBinaryBlockHeader
|
|||||||
uint32_t bmpfv_size;
|
uint32_t bmpfv_size;
|
||||||
uint32_t recovery_key_offset; /* Recovery key */
|
uint32_t recovery_key_offset; /* Recovery key */
|
||||||
uint32_t recovery_key_size;
|
uint32_t recovery_key_size;
|
||||||
|
/* Added in version 1.2 */
|
||||||
|
uint8_t hwid_digest[32]; /* sha256 */
|
||||||
|
|
||||||
uint8_t pad[80]; /* To match GBB_HEADER_SIZE. Initialize to 0. */
|
uint8_t pad[48]; /* To match GBB_HEADER_SIZE. Initialize to 0. */
|
||||||
} __attribute__((packed)) GoogleBinaryBlockHeader;
|
} __attribute__((packed)) GoogleBinaryBlockHeader;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ static void print_help(const char *prog)
|
|||||||
"with following options:\n"
|
"with following options:\n"
|
||||||
" --hwid \tReport hardware id (default).\n"
|
" --hwid \tReport hardware id (default).\n"
|
||||||
" --flags \tReport header flags.\n"
|
" --flags \tReport header flags.\n"
|
||||||
|
" --digest \tReport digest of hwid (>= v1.2)\n"
|
||||||
" -k, --rootkey=FILE \tFile name to export Root Key.\n"
|
" -k, --rootkey=FILE \tFile name to export Root Key.\n"
|
||||||
" -b, --bmpfv=FILE \tFile name to export Bitmap FV.\n"
|
" -b, --bmpfv=FILE \tFile name to export Bitmap FV.\n"
|
||||||
" -r --recoverykey=FILE\tFile name to export Recovery Key.\n"
|
" -r --recoverykey=FILE\tFile name to export Recovery Key.\n"
|
||||||
@@ -55,6 +56,10 @@ static void print_help(const char *prog)
|
|||||||
prog, prog, prog, prog);
|
prog, prog, prog, prog);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum {
|
||||||
|
OPT_DIGEST = 1000,
|
||||||
|
};
|
||||||
|
|
||||||
/* Command line options */
|
/* Command line options */
|
||||||
static const struct option long_opts[] = {
|
static const struct option long_opts[] = {
|
||||||
/* name hasarg *flag val */
|
/* name hasarg *flag val */
|
||||||
@@ -67,6 +72,7 @@ static const struct option long_opts[] = {
|
|||||||
{"recoverykey", 1, NULL, 'R'},
|
{"recoverykey", 1, NULL, 'R'},
|
||||||
{"hwid", 2, NULL, 'i'},
|
{"hwid", 2, NULL, 'i'},
|
||||||
{"flags", 2, NULL, 'L'},
|
{"flags", 2, NULL, 'L'},
|
||||||
|
{"digest", 0, NULL, OPT_DIGEST},
|
||||||
{NULL, 0, NULL, 0},
|
{NULL, 0, NULL, 0},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -340,6 +346,7 @@ static int do_gbb_utility(int argc, char *argv[])
|
|||||||
char *opt_hwid = NULL;
|
char *opt_hwid = NULL;
|
||||||
char *opt_flags = NULL;
|
char *opt_flags = NULL;
|
||||||
int sel_hwid = 0;
|
int sel_hwid = 0;
|
||||||
|
int sel_digest = 0;
|
||||||
int sel_flags = 0;
|
int sel_flags = 0;
|
||||||
uint8_t *inbuf = NULL;
|
uint8_t *inbuf = NULL;
|
||||||
off_t filesize;
|
off_t filesize;
|
||||||
@@ -386,6 +393,9 @@ static int do_gbb_utility(int argc, char *argv[])
|
|||||||
opt_flags = optarg;
|
opt_flags = optarg;
|
||||||
sel_flags = 1;
|
sel_flags = 1;
|
||||||
break;
|
break;
|
||||||
|
case OPT_DIGEST:
|
||||||
|
sel_digest = 1;
|
||||||
|
break;
|
||||||
case '?':
|
case '?':
|
||||||
errorcnt++;
|
errorcnt++;
|
||||||
if (optopt)
|
if (optopt)
|
||||||
@@ -437,7 +447,7 @@ static int do_gbb_utility(int argc, char *argv[])
|
|||||||
|
|
||||||
/* With no args, show the HWID */
|
/* With no args, show the HWID */
|
||||||
if (!opt_rootkey && !opt_bmpfv && !opt_recoverykey
|
if (!opt_rootkey && !opt_bmpfv && !opt_recoverykey
|
||||||
&& !sel_flags)
|
&& !sel_flags && !sel_digest)
|
||||||
sel_hwid = 1;
|
sel_hwid = 1;
|
||||||
|
|
||||||
inbuf = read_entire_file(infile, &filesize);
|
inbuf = read_entire_file(infile, &filesize);
|
||||||
@@ -457,6 +467,9 @@ static int do_gbb_utility(int argc, char *argv[])
|
|||||||
gbb->hwid_size ? (char *)(gbb_base +
|
gbb->hwid_size ? (char *)(gbb_base +
|
||||||
gbb->
|
gbb->
|
||||||
hwid_offset) : "");
|
hwid_offset) : "");
|
||||||
|
if (sel_digest)
|
||||||
|
print_hwid_digest(gbb, "digest: ", "\n");
|
||||||
|
|
||||||
if (sel_flags)
|
if (sel_flags)
|
||||||
printf("flags: 0x%08x\n", gbb->flags);
|
printf("flags: 0x%08x\n", gbb->flags);
|
||||||
if (opt_rootkey)
|
if (opt_rootkey)
|
||||||
@@ -540,6 +553,7 @@ static int do_gbb_utility(int argc, char *argv[])
|
|||||||
gbb->hwid_size);
|
gbb->hwid_size);
|
||||||
strcpy((char *)(gbb_base + gbb->hwid_offset),
|
strcpy((char *)(gbb_base + gbb->hwid_offset),
|
||||||
opt_hwid);
|
opt_hwid);
|
||||||
|
update_hwid_digest(gbb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -141,8 +141,8 @@ int futil_cb_show_gbb(struct futil_traverse_state_s *state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
printf("GBB content:\n");
|
printf("GBB content:\n");
|
||||||
printf(" HWID: %s\n",
|
printf(" HWID: %s\n", buf + gbb->hwid_offset);
|
||||||
(const char *)(buf + gbb->hwid_offset));
|
print_hwid_digest(gbb, " digest: ", "\n");
|
||||||
|
|
||||||
pubkey = (VbPublicKey *)(buf + gbb->rootkey_offset);
|
pubkey = (VbPublicKey *)(buf + gbb->rootkey_offset);
|
||||||
if (PublicKeyLooksOkay(pubkey, gbb->rootkey_size)) {
|
if (PublicKeyLooksOkay(pubkey, gbb->rootkey_size)) {
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ static void log_args(int argc, char *argv[])
|
|||||||
log_open();
|
log_open();
|
||||||
|
|
||||||
/* delimiter */
|
/* delimiter */
|
||||||
log_str(NULL, "##### HEY #####");
|
log_str(NULL, "##### LOG #####");
|
||||||
|
|
||||||
/* Can we tell who called us? */
|
/* Can we tell who called us? */
|
||||||
parent = getppid();
|
parent = getppid();
|
||||||
|
|||||||
@@ -71,6 +71,14 @@ int futil_looks_like_gbb(GoogleBinaryBlockHeader *gbb, uint32_t len);
|
|||||||
int futil_valid_gbb_header(GoogleBinaryBlockHeader *gbb, uint32_t len,
|
int futil_valid_gbb_header(GoogleBinaryBlockHeader *gbb, uint32_t len,
|
||||||
uint32_t *maxlen);
|
uint32_t *maxlen);
|
||||||
|
|
||||||
|
/* For GBB v1.2 and later, update the hwid_digest */
|
||||||
|
void update_hwid_digest(GoogleBinaryBlockHeader *gbb);
|
||||||
|
|
||||||
|
/* For GBB v1.2 and later, print the stored digest of the HWID (and whether
|
||||||
|
* it's correct). Return true if it is correct. */
|
||||||
|
int print_hwid_digest(GoogleBinaryBlockHeader *gbb,
|
||||||
|
const char *banner, const char *footer);
|
||||||
|
|
||||||
/* Copies a file or dies with an error message */
|
/* Copies a file or dies with an error message */
|
||||||
void futil_copy_file_or_die(const char *infile, const char *outfile);
|
void futil_copy_file_or_die(const char *infile, const char *outfile);
|
||||||
|
|
||||||
|
|||||||
@@ -114,6 +114,57 @@ int futil_valid_gbb_header(GoogleBinaryBlockHeader *gbb, uint32_t len,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* For GBB v1.2 and later, print the stored digest of the HWID (and whether
|
||||||
|
* it's correct). Return true if it is correct. */
|
||||||
|
int print_hwid_digest(GoogleBinaryBlockHeader *gbb,
|
||||||
|
const char *banner, const char *footer)
|
||||||
|
{
|
||||||
|
printf("%s", banner);
|
||||||
|
|
||||||
|
/* There isn't one for v1.1 and earlier, so assume it's good. */
|
||||||
|
if (gbb->minor_version < 2) {
|
||||||
|
printf("<none>%s", footer);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *buf = (uint8_t *)gbb;
|
||||||
|
char *hwid_str = (char *)(buf + gbb->hwid_offset);
|
||||||
|
int is_valid = 0;
|
||||||
|
uint8_t* digest = DigestBuf(buf + gbb->hwid_offset,
|
||||||
|
strlen(hwid_str),
|
||||||
|
SHA256_DIGEST_ALGORITHM);
|
||||||
|
if (digest) {
|
||||||
|
int i;
|
||||||
|
is_valid = 1;
|
||||||
|
/* print it, comparing as we go */
|
||||||
|
for (i = 0; i < SHA256_DIGEST_SIZE; i++) {
|
||||||
|
printf("%02x", gbb->hwid_digest[i]);
|
||||||
|
if (gbb->hwid_digest[i] != digest[i])
|
||||||
|
is_valid = 0;
|
||||||
|
}
|
||||||
|
free(digest);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(" %s", is_valid ? "valid" : "<invalid>");
|
||||||
|
printf("%s", footer);
|
||||||
|
return is_valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For GBB v1.2 and later, update the hwid_digest field. */
|
||||||
|
void update_hwid_digest(GoogleBinaryBlockHeader *gbb)
|
||||||
|
{
|
||||||
|
/* There isn't one for v1.1 and earlier */
|
||||||
|
if (gbb->minor_version < 2)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint8_t *buf = (uint8_t *)gbb;
|
||||||
|
char *hwid_str = (char *)(buf + gbb->hwid_offset);
|
||||||
|
uint8_t* digest = DigestBuf(buf + gbb->hwid_offset,
|
||||||
|
strlen(hwid_str),
|
||||||
|
SHA256_DIGEST_ALGORITHM);
|
||||||
|
memcpy(gbb->hwid_digest, digest, SHA256_DIGEST_SIZE);
|
||||||
|
free(digest);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TODO: All sorts of race conditions likely here, and everywhere this is used.
|
* TODO: All sorts of race conditions likely here, and everywhere this is used.
|
||||||
|
|||||||
@@ -201,6 +201,33 @@ cat ${TMP}.blob | ${REPLACE} 0x2c 0x00 > ${TMP}.blob.bad
|
|||||||
${FUTILITY} gbb_utility -g --recoverykey ${TMP}.read2 ${TMP}.blob.bad
|
${FUTILITY} gbb_utility -g --recoverykey ${TMP}.read2 ${TMP}.blob.bad
|
||||||
if ${FUTILITY} gbb_utility -s --recoverykey ${TMP}.data2 ${TMP}.blob.bad; then false; fi
|
if ${FUTILITY} gbb_utility -s --recoverykey ${TMP}.data2 ${TMP}.blob.bad; then false; fi
|
||||||
|
|
||||||
|
|
||||||
|
# GBB v1.2 adds a sha256 digest field in what was previously padding:
|
||||||
|
#
|
||||||
|
# hwid_digest: 0x0030 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
|
||||||
|
# 0x0040 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
|
||||||
|
# pad: 0x0050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||||
|
# 0x0060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||||
|
# 0x0070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||||
|
# (HWID) 0x0080 30 31 32 33 34 35 36 37 38 39 41 42 43 44 45 00
|
||||||
|
|
||||||
|
# See that the digest is updated properly.
|
||||||
|
hwid="123456789ABCDEF"
|
||||||
|
${FUTILITY} gbb_utility -s -i ${hwid} ${TMP}.blob
|
||||||
|
expect=$(echo -n "$hwid" | sha256sum | cut -d ' ' -f 1)
|
||||||
|
[ $(echo -n ${expect} | wc -c) == "64" ]
|
||||||
|
${FUTILITY} gbb_utility -g --digest ${TMP}.blob | grep ${expect}
|
||||||
|
|
||||||
|
# Garble the digest, see that it's noticed.
|
||||||
|
# (assuming these zeros aren't present)
|
||||||
|
cat ${TMP}.blob | ${REPLACE} 0x33 0x00 0x00 0x00 0x00 0x00 > ${TMP}.blob.bad
|
||||||
|
${FUTILITY} gbb_utility -g --digest ${TMP}.blob.bad | grep '0000000000'
|
||||||
|
${FUTILITY} gbb_utility -g --digest ${TMP}.blob.bad | grep 'invalid'
|
||||||
|
|
||||||
|
# Garble the HWID. The digest is unchanged, but now invalid.
|
||||||
|
cat ${TMP}.blob | ${REPLACE} 0x84 0x70 0x71 0x72 > ${TMP}.blob.bad
|
||||||
|
${FUTILITY} gbb_utility -g --digest ${TMP}.blob.bad | grep 'invalid'
|
||||||
|
|
||||||
# cleanup
|
# cleanup
|
||||||
rm -f ${TMP}*
|
rm -f ${TMP}*
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
@@ -1,15 +1,19 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
|
* Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
|
||||||
* Use of this source code is governed by a BSD-style license that can be
|
* Use of this source code is governed by a BSD-style license that can be
|
||||||
* found in the LICENSE file.
|
* found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include "gbb_header.h"
|
||||||
#include "test_common.h"
|
#include "test_common.h"
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
TEST_EQ(sizeof(GoogleBinaryBlockHeader),
|
||||||
|
GBB_HEADER_SIZE,
|
||||||
|
"sizeof(GoogleBinaryBlockHeader)");
|
||||||
|
|
||||||
TEST_EQ(0, 0, "Not Really A");
|
TEST_EQ(0, 0, "Not Really A");
|
||||||
|
|
||||||
return !gTestSuccess;
|
return !gTestSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -134,6 +134,10 @@ static void gbb_tests(void)
|
|||||||
|
|
||||||
struct vb2_gbb_header gbbdest;
|
struct vb2_gbb_header gbbdest;
|
||||||
|
|
||||||
|
TEST_EQ(sizeof(struct vb2_gbb_header),
|
||||||
|
EXPECTED_GBB_HEADER_SIZE,
|
||||||
|
"sizeof(struct vb2_gbb_header)");
|
||||||
|
|
||||||
reset_common_data();
|
reset_common_data();
|
||||||
|
|
||||||
/* Good contents */
|
/* Good contents */
|
||||||
|
|||||||
@@ -499,7 +499,7 @@ namespace vboot_reference {
|
|||||||
config_.header.minor_version = minor_version_;
|
config_.header.minor_version = minor_version_;
|
||||||
config_.header.number_of_localizations = config_.localizations.size();
|
config_.header.number_of_localizations = config_.localizations.size();
|
||||||
config_.header.number_of_screenlayouts = config_.localizations[0].size();
|
config_.header.number_of_screenlayouts = config_.localizations[0].size();
|
||||||
// HEY: this is part of the yaml consistency check
|
// NOTE: this is part of the yaml consistency check
|
||||||
for (unsigned int i = 1; i < config_.localizations.size(); ++i) {
|
for (unsigned int i = 1; i < config_.localizations.size(); ++i) {
|
||||||
assert(config_.header.number_of_screenlayouts ==
|
assert(config_.header.number_of_screenlayouts ==
|
||||||
config_.localizations[i].size());
|
config_.localizations[i].size());
|
||||||
|
|||||||
Reference in New Issue
Block a user