mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-11-25 18:55:24 +00:00
vboot2: Add code and tests for verifying vb2_fw_preamble2
This is the last low-level data structure verification code for the new data structures. Subsequent changes are the next level up the food chain. BUG=chromium:423882 BRANCH=none TEST=VBOOT2=1 make runtests Change-Id: I2e45106c27447eb624c1ed562e40b98088249742 Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/228360 Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org>
This commit is contained in:
committed by
chrome-internal-fetch
parent
054c114798
commit
43e0a9ed6c
@@ -366,3 +366,73 @@ int vb2_verify_keyblock2(struct vb2_keyblock2 *block,
|
||||
/* If we're still here, no signature matched the key GUID */
|
||||
return VB2_ERROR_KEYBLOCK_SIG_GUID;
|
||||
}
|
||||
|
||||
int vb2_verify_fw_preamble2(struct vb2_fw_preamble2 *preamble,
|
||||
uint32_t size,
|
||||
const struct vb2_public_key *key,
|
||||
const struct vb2_workbuf *wb)
|
||||
{
|
||||
struct vb2_signature2 *sig;
|
||||
uint32_t min_offset = 0, hash_offset;
|
||||
int rv, i;
|
||||
|
||||
/* Check magic number */
|
||||
if (preamble->c.magic != VB2_MAGIC_FW_PREAMBLE2)
|
||||
return VB2_ERROR_PREAMBLE_MAGIC;
|
||||
|
||||
/* Make sure common header is good */
|
||||
rv = vb2_verify_common_header(preamble, size);
|
||||
if (rv)
|
||||
return rv;
|
||||
|
||||
/*
|
||||
* Check for compatible version. No need to check minor version, since
|
||||
* that's compatible across readers matching the major version, and we
|
||||
* haven't added any new fields.
|
||||
*/
|
||||
if (preamble->c.struct_version_major != VB2_FW_PREAMBLE2_VERSION_MAJOR)
|
||||
return VB2_ERROR_PREAMBLE_HEADER_VERSION;
|
||||
|
||||
/* Make sure header is big enough */
|
||||
if (preamble->c.fixed_size < sizeof(*preamble))
|
||||
return VB2_ERROR_PREAMBLE_SIZE;
|
||||
|
||||
/* Make sure all hash signatures are inside */
|
||||
hash_offset = preamble->hash_offset;
|
||||
for (i = 0; i < preamble->hash_count; i++, hash_offset = min_offset) {
|
||||
/* Make sure signature is inside preamble */
|
||||
rv = vb2_verify_common_subobject(preamble, &min_offset,
|
||||
hash_offset);
|
||||
if (rv)
|
||||
return rv;
|
||||
|
||||
sig = (struct vb2_signature2 *)
|
||||
((uint8_t *)preamble + hash_offset);
|
||||
|
||||
/* Verify the signature integrity */
|
||||
rv = vb2_verify_signature2(
|
||||
sig, preamble->c.total_size - hash_offset);
|
||||
if (rv)
|
||||
return rv;
|
||||
|
||||
/* Hashes must all be unsigned */
|
||||
if (sig->sig_alg != VB2_SIG_NONE)
|
||||
return VB2_ERROR_PREAMBLE_HASH_SIGNED;
|
||||
}
|
||||
|
||||
/* Make sure signature is inside preamble */
|
||||
rv = vb2_verify_common_subobject(preamble, &min_offset,
|
||||
preamble->sig_offset);
|
||||
if (rv)
|
||||
return rv;
|
||||
|
||||
/* Verify preamble signature */
|
||||
sig = (struct vb2_signature2 *)((uint8_t *)preamble +
|
||||
preamble->sig_offset);
|
||||
|
||||
rv = vb2_verify_data2(preamble, preamble->sig_offset, sig, key, wb);
|
||||
if (rv)
|
||||
return rv;
|
||||
|
||||
return VB2_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -410,7 +410,10 @@ int vb2_verify_keyblock2(struct vb2_keyblock2 *block,
|
||||
const struct vb2_public_key *key,
|
||||
const struct vb2_workbuf *wb);
|
||||
|
||||
/* Size of work buffer sufficient for vb2_verify_fw_preamble() worst case */
|
||||
/*
|
||||
* Size of work buffer sufficient for vb2_verify_fw_preamble() or
|
||||
* vb2_verify_fw_preamble2() worst case.
|
||||
*/
|
||||
#define VB2_VERIFY_FIRMWARE_PREAMBLE_WORKBUF_BYTES VB2_VERIFY_DATA_WORKBUF_BYTES
|
||||
|
||||
/**
|
||||
@@ -429,4 +432,9 @@ int vb2_verify_fw_preamble(struct vb2_fw_preamble *preamble,
|
||||
const struct vb2_public_key *key,
|
||||
const struct vb2_workbuf *wb);
|
||||
|
||||
int vb2_verify_fw_preamble2(struct vb2_fw_preamble2 *preamble,
|
||||
uint32_t size,
|
||||
const struct vb2_public_key *key,
|
||||
const struct vb2_workbuf *wb);
|
||||
|
||||
#endif /* VBOOT_REFERENCE_VBOOT_2COMMON_H_ */
|
||||
|
||||
@@ -302,6 +302,12 @@ enum vb2_return_code {
|
||||
/* Kernel subkey outside preamble */
|
||||
VB2_ERROR_PREAMBLE_KERNEL_SUBKEY_OUTSIDE,
|
||||
|
||||
/* Bad magic number */
|
||||
VB2_ERROR_PREAMBLE_MAGIC,
|
||||
|
||||
/* Hash is signed */
|
||||
VB2_ERROR_PREAMBLE_HASH_SIGNED,
|
||||
|
||||
/**********************************************************************
|
||||
* Misc higher-level code errors
|
||||
*/
|
||||
|
||||
@@ -491,9 +491,9 @@ struct vb2_keyblock2 {
|
||||
#define EXPECTED_VB2_KEYBLOCK2_SIZE (EXPECTED_VB2_STRUCT_COMMON_SIZE + 16)
|
||||
|
||||
|
||||
/* Current version of vb2_preamble2 struct */
|
||||
#define VB2_PREAMBLE2_VERSION_MAJOR 3
|
||||
#define VB2_PREAMBLE2_VERSION_MINOR 0
|
||||
/* Current version of vb2_fw_preamble2 struct */
|
||||
#define VB2_FW_PREAMBLE2_VERSION_MAJOR 3
|
||||
#define VB2_FW_PREAMBLE2_VERSION_MINOR 0
|
||||
|
||||
/*
|
||||
* Firmware preamble
|
||||
@@ -501,7 +501,7 @@ struct vb2_keyblock2 {
|
||||
* The preamble data must be arranged like this:
|
||||
* 1) vb2_fw_preamble2 header struct h
|
||||
* 2) Preamble description (pointed to by h.c.fixed_size)
|
||||
* 3) Hash table (pointed to by h.hash_table_offset)
|
||||
* 3) Hashes (pointed to by h.hash_offset)
|
||||
* 4) Signature (pointed to by h.sig_offset)
|
||||
*
|
||||
* The signature 4) must cover all the data from 1), 2), 3).
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
|
||||
#include "test_common.h"
|
||||
|
||||
static const uint8_t test_data[] = "This is some test data to sign.";
|
||||
|
||||
/**
|
||||
* Test memory compare functions
|
||||
*/
|
||||
@@ -449,7 +451,6 @@ static void test_sig_size(void)
|
||||
*/
|
||||
static void test_verify_hash(void)
|
||||
{
|
||||
static const uint8_t test_data[] = "This is some test data to sign.";
|
||||
struct vb2_signature2 *sig;
|
||||
struct vb2_public_key pubk = {
|
||||
.sig_alg = VB2_SIG_NONE,
|
||||
@@ -535,12 +536,12 @@ static void test_verify_keyblock(void)
|
||||
*/
|
||||
kb.c.total_size = kb.sig_offset;
|
||||
|
||||
sig = vb2_create_hash_sig((const uint8_t *)desc, sizeof(desc),
|
||||
sig = vb2_create_hash_sig(test_data, sizeof(test_data),
|
||||
VB2_HASH_SHA256);
|
||||
kb.c.total_size += sig->c.total_size;
|
||||
free(sig);
|
||||
|
||||
sig = vb2_create_hash_sig((const uint8_t *)desc, sizeof(desc),
|
||||
sig = vb2_create_hash_sig(test_data, sizeof(test_data),
|
||||
VB2_HASH_SHA512);
|
||||
kb.c.total_size += sig->c.total_size;
|
||||
free(sig);
|
||||
@@ -587,19 +588,19 @@ static void test_verify_keyblock(void)
|
||||
|
||||
memcpy(buf, buf2, buf_size);
|
||||
kbuf->c.magic = VB2_MAGIC_PACKED_KEY2;
|
||||
TEST_EQ(vb2_verify_keyblock2(kbuf, buf_size, &pubk_not_present, &wb),
|
||||
TEST_EQ(vb2_verify_keyblock2(kbuf, buf_size, &pubk, &wb),
|
||||
VB2_ERROR_KEYBLOCK_MAGIC,
|
||||
"vb2_verify_keyblock2() magic");
|
||||
|
||||
memcpy(buf, buf2, buf_size);
|
||||
kbuf->c.fixed_size++;
|
||||
TEST_EQ(vb2_verify_keyblock2(kbuf, buf_size, &pubk_not_present, &wb),
|
||||
TEST_EQ(vb2_verify_keyblock2(kbuf, buf_size, &pubk, &wb),
|
||||
VB2_ERROR_COMMON_FIXED_UNALIGNED,
|
||||
"vb2_verify_keyblock2() header");
|
||||
|
||||
memcpy(buf, buf2, buf_size);
|
||||
kbuf->c.struct_version_major++;
|
||||
TEST_EQ(vb2_verify_keyblock2(kbuf, buf_size, &pubk_not_present, &wb),
|
||||
TEST_EQ(vb2_verify_keyblock2(kbuf, buf_size, &pubk, &wb),
|
||||
VB2_ERROR_KEYBLOCK_HEADER_VERSION,
|
||||
"vb2_verify_keyblock2() major version");
|
||||
|
||||
@@ -656,6 +657,186 @@ static void test_verify_keyblock(void)
|
||||
free(buf2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify firmware preamble
|
||||
*/
|
||||
static void test_verify_fw_preamble(void)
|
||||
{
|
||||
const char desc[16] = "test preamble";
|
||||
struct vb2_signature2 *sig;
|
||||
struct vb2_fw_preamble2 *pre;
|
||||
uint32_t buf_size;
|
||||
uint8_t *buf, *buf2, *bnext;
|
||||
|
||||
uint8_t workbuf[VB2_VERIFY_FIRMWARE_PREAMBLE_WORKBUF_BYTES];
|
||||
struct vb2_workbuf wb;
|
||||
|
||||
/*
|
||||
* Preambles will usually be signed with a real key not a bare hash,
|
||||
* but the call to vb2_verify_data2() inside the preamble check is the
|
||||
* same (and its functionality is verified separately), and using a
|
||||
* bare hash here saves us from needing to have a private key to do
|
||||
* this test.
|
||||
*/
|
||||
const struct vb2_public_key pubk = {
|
||||
.sig_alg = VB2_SIG_NONE,
|
||||
.hash_alg = VB2_HASH_SHA256,
|
||||
.guid = vb2_hash_guid(VB2_HASH_SHA256)
|
||||
};
|
||||
|
||||
struct vb2_fw_preamble2 fp = {
|
||||
.c.magic = VB2_MAGIC_FW_PREAMBLE2,
|
||||
.c.struct_version_major = VB2_FW_PREAMBLE2_VERSION_MAJOR,
|
||||
.c.struct_version_minor = VB2_FW_PREAMBLE2_VERSION_MAJOR,
|
||||
.c.fixed_size = sizeof(fp),
|
||||
.c.desc_size = sizeof(desc),
|
||||
.flags = 0,
|
||||
.hash_count = 3,
|
||||
};
|
||||
|
||||
fp.hash_offset = fp.c.fixed_size + fp.c.desc_size;
|
||||
|
||||
/* Create some hashes so we can calculate their sizes */
|
||||
fp.c.total_size = fp.hash_offset;
|
||||
|
||||
sig = vb2_create_hash_sig(test_data, sizeof(test_data),
|
||||
VB2_HASH_SHA512);
|
||||
fp.c.total_size += sig->c.total_size;
|
||||
free(sig);
|
||||
|
||||
sig = vb2_create_hash_sig(test_data, sizeof(test_data),
|
||||
VB2_HASH_SHA256);
|
||||
fp.c.total_size += 2 * sig->c.total_size;
|
||||
|
||||
/* Preamble signature goes after that */
|
||||
fp.sig_offset = fp.c.total_size;
|
||||
fp.c.total_size += sig->c.total_size;
|
||||
free(sig);
|
||||
|
||||
/* Now that the total size is known, create the real preamble */
|
||||
buf_size = fp.c.total_size;
|
||||
buf = malloc(buf_size);
|
||||
memset(buf, 0, buf_size);
|
||||
memcpy(buf, &fp, sizeof(fp));
|
||||
memcpy(buf + fp.c.fixed_size, desc, sizeof(desc));
|
||||
|
||||
/* And copy in the component hashes (use parts of test data) */
|
||||
bnext = buf + fp.hash_offset;
|
||||
|
||||
sig = vb2_create_hash_sig(test_data, sizeof(test_data),
|
||||
VB2_HASH_SHA256);
|
||||
memset(&sig->guid, 0x01, sizeof(sig->guid));
|
||||
memcpy(bnext, sig, sig->c.total_size);
|
||||
bnext += sig->c.total_size;
|
||||
free(sig);
|
||||
|
||||
sig = vb2_create_hash_sig(test_data, sizeof(test_data),
|
||||
VB2_HASH_SHA512);
|
||||
memset(&sig->guid, 0x03, sizeof(sig->guid));
|
||||
memcpy(bnext, sig, sig->c.total_size);
|
||||
bnext += sig->c.total_size;
|
||||
free(sig);
|
||||
|
||||
sig = vb2_create_hash_sig(test_data, sizeof(test_data) - 4,
|
||||
VB2_HASH_SHA256);
|
||||
memset(&sig->guid, 0x02, sizeof(sig->guid));
|
||||
memcpy(bnext, sig, sig->c.total_size);
|
||||
bnext += sig->c.total_size;
|
||||
free(sig);
|
||||
|
||||
/* Now sign the preamble */
|
||||
sig = vb2_create_hash_sig(buf, fp.sig_offset, VB2_HASH_SHA256);
|
||||
memcpy(buf + fp.sig_offset, sig, sig->c.total_size);
|
||||
free(sig);
|
||||
|
||||
/* Make a copy of the buffer, so we can mangle it for tests */
|
||||
buf2 = malloc(buf_size);
|
||||
memcpy(buf2, buf, buf_size);
|
||||
|
||||
vb2_workbuf_init(&wb, workbuf, sizeof(workbuf));
|
||||
pre = (struct vb2_fw_preamble2 *)buf;
|
||||
|
||||
TEST_SUCC(vb2_verify_fw_preamble2(pre, buf_size, &pubk, &wb),
|
||||
"vb2_verify_fw_preamble2()");
|
||||
|
||||
memcpy(buf, buf2, buf_size);
|
||||
pre->c.magic = VB2_MAGIC_PACKED_KEY2;
|
||||
TEST_EQ(vb2_verify_fw_preamble2(pre, buf_size, &pubk, &wb),
|
||||
VB2_ERROR_PREAMBLE_MAGIC,
|
||||
"vb2_verify_fw_preamble2() magic");
|
||||
|
||||
memcpy(buf, buf2, buf_size);
|
||||
pre->c.fixed_size++;
|
||||
TEST_EQ(vb2_verify_fw_preamble2(pre, buf_size, &pubk, &wb),
|
||||
VB2_ERROR_COMMON_FIXED_UNALIGNED,
|
||||
"vb2_verify_fw_preamble2() header");
|
||||
|
||||
memcpy(buf, buf2, buf_size);
|
||||
pre->c.struct_version_major++;
|
||||
TEST_EQ(vb2_verify_fw_preamble2(pre, buf_size, &pubk, &wb),
|
||||
VB2_ERROR_PREAMBLE_HEADER_VERSION,
|
||||
"vb2_verify_fw_preamble2() major version");
|
||||
|
||||
memcpy(buf, buf2, buf_size);
|
||||
pre->c.struct_version_minor++;
|
||||
/* That changes the signature, so resign the fw_preamble */
|
||||
sig = vb2_create_hash_sig(buf, fp.sig_offset, VB2_HASH_SHA256);
|
||||
memcpy(buf + pre->sig_offset, sig, sig->c.total_size);
|
||||
free(sig);
|
||||
TEST_SUCC(vb2_verify_fw_preamble2(pre, buf_size, &pubk, &wb),
|
||||
"vb2_verify_fw_preamble2() minor version");
|
||||
|
||||
memcpy(buf, buf2, buf_size);
|
||||
pre->c.fixed_size -= 4;
|
||||
pre->c.desc_size += 4;
|
||||
TEST_EQ(vb2_verify_fw_preamble2(pre, buf_size, &pubk, &wb),
|
||||
VB2_ERROR_PREAMBLE_SIZE,
|
||||
"vb2_verify_fw_preamble2() header size");
|
||||
|
||||
memcpy(buf, buf2, buf_size);
|
||||
sig = (struct vb2_signature2 *)(buf + fp.hash_offset);
|
||||
sig->c.total_size += fp.c.total_size;
|
||||
TEST_EQ(vb2_verify_fw_preamble2(pre, buf_size, &pubk, &wb),
|
||||
VB2_ERROR_COMMON_TOTAL_SIZE,
|
||||
"vb2_verify_fw_preamble2() hash size");
|
||||
|
||||
memcpy(buf, buf2, buf_size);
|
||||
sig = (struct vb2_signature2 *)(buf + fp.hash_offset);
|
||||
sig->sig_size /= 2;
|
||||
TEST_EQ(vb2_verify_fw_preamble2(pre, buf_size, &pubk, &wb),
|
||||
VB2_ERROR_SIG_SIZE,
|
||||
"vb2_verify_fw_preamble2() hash integrity");
|
||||
|
||||
memcpy(buf, buf2, buf_size);
|
||||
pre->hash_count++;
|
||||
TEST_EQ(vb2_verify_fw_preamble2(pre, buf_size, &pubk, &wb),
|
||||
VB2_ERROR_COMMON_MEMBER_OVERLAP,
|
||||
"vb2_verify_fw_preamble2() hash count");
|
||||
|
||||
memcpy(buf, buf2, buf_size);
|
||||
sig = (struct vb2_signature2 *)(buf + fp.sig_offset);
|
||||
sig->c.total_size += 4;
|
||||
TEST_EQ(vb2_verify_fw_preamble2(pre, buf_size, &pubk, &wb),
|
||||
VB2_ERROR_COMMON_TOTAL_SIZE,
|
||||
"vb2_verify_fw_preamble2() sig inside");
|
||||
|
||||
memcpy(buf, buf2, buf_size);
|
||||
sig = (struct vb2_signature2 *)(buf + fp.sig_offset);
|
||||
buf[fp.sig_offset + sig->sig_offset]++;
|
||||
TEST_EQ(vb2_verify_fw_preamble2(pre, buf_size, &pubk, &wb),
|
||||
VB2_ERROR_VDATA_VERIFY_DIGEST,
|
||||
"vb2_verify_fw_preamble2() sig corrupt");
|
||||
|
||||
memcpy(buf, buf2, buf_size);
|
||||
pre->flags++;
|
||||
TEST_EQ(vb2_verify_fw_preamble2(pre, buf_size, &pubk, &wb),
|
||||
VB2_ERROR_VDATA_VERIFY_DIGEST,
|
||||
"vb2_verify_fw_preamble2() preamble corrupt");
|
||||
|
||||
free(buf);
|
||||
free(buf2);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
test_memcmp();
|
||||
@@ -667,6 +848,7 @@ int main(int argc, char* argv[])
|
||||
test_sig_size();
|
||||
test_verify_hash();
|
||||
test_verify_keyblock();
|
||||
test_verify_fw_preamble();
|
||||
|
||||
return gTestSuccess ? 0 : 255;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user