vboot2: add support for new vb2_signature2 struct

And assocated unit tests.

BUG=chromium:423882
BRANCH=none
TEST=VBOOT2=1 make runtests

Change-Id: I37fccafd8ccee5c0d55e3746c1611a8dff73145a
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/226939
Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org>
This commit is contained in:
Randall Spangler
2014-10-31 11:19:14 -07:00
committed by chrome-internal-fetch
parent 3c6ec76e32
commit c0ce70b468
7 changed files with 255 additions and 1 deletions

View File

@@ -118,3 +118,63 @@ int vb2_verify_common_subobject(const void *parent,
return VB2_SUCCESS;
}
uint32_t vb2_sig_size(enum vb2_signature_algorithm sig_alg,
enum vb2_hash_algorithm hash_alg)
{
uint32_t digest_size = vb2_digest_size(hash_alg);
/* Fail if we don't support the hash algorithm */
if (!digest_size)
return 0;
/* Handle unsigned hashes */
if (sig_alg == VB2_SIG_NONE)
return digest_size;
return vb2_rsa_sig_size(sig_alg);
}
int vb2_verify_signature2(const struct vb2_signature2 *sig,
uint32_t size)
{
uint32_t min_offset = 0;
uint32_t expect_sig_size;
int rv;
/* Check magic number */
if (sig->c.magic != VB2_MAGIC_SIGNATURE2)
return VB2_ERROR_SIG_MAGIC;
/* Make sure common header is good */
rv = vb2_verify_common_header(sig, 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 (sig->c.struct_version_major != VB2_SIGNATURE2_VERSION_MAJOR)
return VB2_ERROR_SIG_VERSION;
/* Make sure header is big enough for signature */
if (sig->c.fixed_size < sizeof(*sig))
return VB2_ERROR_SIG_HEADER_SIZE;
/* Make sure signature data is inside */
rv = vb2_verify_common_member(sig, &min_offset,
sig->sig_offset, sig->sig_size);
if (rv)
return rv;
/* Make sure signature size is correct for the algorithm */
expect_sig_size = vb2_sig_size(sig->sig_alg, sig->hash_alg);
if (!expect_sig_size)
return VB2_ERROR_SIG_ALGORITHM;
if (sig->sig_size != expect_sig_size)
return VB2_ERROR_SIG_SIZE;
return VB2_SUCCESS;
}

View File

@@ -281,6 +281,25 @@ int vb2_unpack_key2(struct vb2_public_key *key,
const uint8_t *buf,
uint32_t size);
/**
* Return expected signature size for a signature/hash algorithm pair
*
* @param sig_alg Signature algorithm
* @param hash_alg Hash algorithm
* @return The signature size, or zero if error / unsupported algorithm.
*/
uint32_t vb2_sig_size(enum vb2_signature_algorithm sig_alg,
enum vb2_hash_algorithm hash_alg);
/**
* Verify the integrity of a signature struct
* @param sig Signature struct
* @param size Size of buffer containing signature struct
* @return VB2_SUCCESS, or non-zero if error.
*/
int vb2_verify_signature2(const struct vb2_signature2 *sig,
uint32_t size);
/* Size of work buffer sufficient for vb2_rsa_verify_digest() worst case */
#define VB2_VERIFY_DIGEST_WORKBUF_BYTES VB2_VERIFY_RSA_DIGEST_WORKBUF_BYTES

View File

@@ -211,6 +211,12 @@ enum vb2_return_code {
/* Signature header doesn't fit */
VB2_ERROR_SIG_HEADER_SIZE,
/* Signature unsupported algorithm */
VB2_ERROR_SIG_ALGORITHM,
/* Signature bad size for algorithm */
VB2_ERROR_SIG_SIZE,
/* Wrong amount of data signed */
VB2_ERROR_VDATA_SIZE,

View File

@@ -235,6 +235,73 @@ static void test_verify_data(struct vb2_packed_key *key1,
free(sig2);
}
static void test_verify_signature(const struct vb2_packed_key *key1,
const struct vb2_signature *sig1)
{
struct vb2_public_key pubk;
struct vb2_packed_key2 *key2;
struct vb2_signature2 *sig2;
uint8_t *buf2good, *buf2;
uint32_t size;
/* Unpack and convert the public key */
TEST_SUCC(vb2_unpack_key2(&pubk, (uint8_t *)key1,
key1->key_offset + key1->key_size),
"verify_sig vb2_unpack_key2() passthru");
key2 = vb2_convert_packed_key2(key1, "Test key", &size);
TEST_PTR_NEQ(key2, 0, "verify_sig convert pub key");
buf2good = (uint8_t *)
vb2_convert_signature2(sig1, "test desc", key2, &size);
buf2 = malloc(size);
sig2 = (struct vb2_signature2 *)buf2;
memcpy(buf2, buf2good, size);
TEST_PTR_NEQ(sig1, 0, "verify_sig convert signature");
TEST_SUCC(vb2_verify_signature2(sig2, size), "verify_sig ok");
sig2->c.magic = VB2_MAGIC_PACKED_KEY2;
TEST_EQ(vb2_verify_signature2(sig2, size), VB2_ERROR_SIG_MAGIC,
"verify_sig magic");
memcpy(buf2, buf2good, size);
sig2->c.total_size += 4;
TEST_EQ(vb2_verify_signature2(sig2, size), VB2_ERROR_COMMON_TOTAL_SIZE,
"verify_sig common header");
memcpy(buf2, buf2good, size);
sig2->c.struct_version_minor++;
TEST_SUCC(vb2_verify_signature2(sig2, size), "verify_sig minor ver");
sig2->c.struct_version_major++;
TEST_EQ(vb2_verify_signature2(sig2, size), VB2_ERROR_SIG_VERSION,
"verify_sig major ver");
memcpy(buf2, buf2good, size);
sig2->c.fixed_size -= 4;
sig2->c.desc_size += 4;
TEST_EQ(vb2_verify_signature2(sig2, size), VB2_ERROR_SIG_HEADER_SIZE,
"verify_sig header size");
memcpy(buf2, buf2good, size);
sig2->sig_size += 4;
TEST_EQ(vb2_verify_signature2(sig2, size), VB2_ERROR_COMMON_MEMBER_SIZE,
"verify_sig sig size");
memcpy(buf2, buf2good, size);
sig2->sig_alg = VB2_SIG_INVALID;
TEST_EQ(vb2_verify_signature2(sig2, size), VB2_ERROR_SIG_ALGORITHM,
"verify_sig sig alg");
memcpy(buf2, buf2good, size);
sig2->sig_alg = (sig2->sig_alg == VB2_SIG_NONE ?
VB2_SIG_RSA1024 : VB2_SIG_NONE);
TEST_EQ(vb2_verify_signature2(sig2, size), VB2_ERROR_SIG_SIZE,
"verify_sig sig size");
free(buf2);
free(buf2good);
free(key2);
}
int test_algorithm(int key_algorithm, const char *keys_dir)
{
char filename[1024];
@@ -272,6 +339,7 @@ int test_algorithm(int key_algorithm, const char *keys_dir)
test_unpack_key(key1);
test_unpack_key2(key1);
test_verify_data(key1, sig);
test_verify_signature(key1, sig);
if (key1)
free(key1);

View File

@@ -419,6 +419,32 @@ static void test_common_header_functions(void)
"vb2_verify_common_subobject() size");
}
/**
* Signature size
*/
static void test_sig_size(void)
{
TEST_EQ(vb2_sig_size(VB2_SIG_INVALID, VB2_HASH_SHA256), 0,
"vb2_sig_size() sig invalid");
TEST_EQ(vb2_sig_size(VB2_SIG_RSA2048, VB2_HASH_INVALID), 0,
"vb2_sig_size() hash invalid");
TEST_EQ(vb2_sig_size(VB2_SIG_RSA2048, VB2_HASH_SHA256), 2048 / 8,
"vb2_sig_size() RSA2048");
TEST_EQ(vb2_sig_size(VB2_SIG_RSA4096, VB2_HASH_SHA256), 4096 / 8,
"vb2_sig_size() RSA4096");
TEST_EQ(vb2_sig_size(VB2_SIG_RSA8192, VB2_HASH_SHA512), 8192 / 8,
"vb2_sig_size() RSA8192");
TEST_EQ(vb2_sig_size(VB2_SIG_NONE, VB2_HASH_SHA1),
VB2_SHA1_DIGEST_SIZE, "vb2_sig_size() SHA1");
TEST_EQ(vb2_sig_size(VB2_SIG_NONE, VB2_HASH_SHA256),
VB2_SHA256_DIGEST_SIZE, "vb2_sig_size() SHA256");
TEST_EQ(vb2_sig_size(VB2_SIG_NONE, VB2_HASH_SHA512),
VB2_SHA512_DIGEST_SIZE, "vb2_sig_size() SHA512");
}
int main(int argc, char* argv[])
{
test_memcmp();
@@ -427,6 +453,7 @@ int main(int argc, char* argv[])
test_struct_packing();
test_helper_functions();
test_common_header_functions();
test_sig_size();
return gTestSuccess ? 0 : 255;
}

View File

@@ -56,3 +56,57 @@ struct vb2_packed_key2 *vb2_convert_packed_key2(
/* Return the newly allocated buffer */
return (struct vb2_packed_key2 *)kbuf;
}
struct vb2_signature2 *vb2_convert_signature2(
const struct vb2_signature *sig,
const char *desc,
const struct vb2_packed_key2 *key,
uint32_t *out_size)
{
struct vb2_signature2 s2 = {
.c.magic = VB2_MAGIC_SIGNATURE2,
.c.struct_version_major = VB2_SIGNATURE2_VERSION_MAJOR,
.c.struct_version_minor = VB2_SIGNATURE2_VERSION_MINOR,
};
uint8_t *buf;
/* Calculate description size */
s2.c.fixed_size = sizeof(s2);
s2.c.desc_size = roundup32(strlen(desc) + 1);
/* Copy/initialize fields */
s2.sig_offset = s2.c.fixed_size + s2.c.desc_size;
s2.sig_size = sig->sig_size;
s2.c.total_size = s2.sig_offset + s2.sig_size;
s2.data_size = sig->data_size;
/* Copy fields from key if present */
if (key) {
s2.sig_alg = key->sig_alg;
s2.hash_alg = key->hash_alg;
memcpy(&s2.key_guid, &key->key_guid, GUID_SIZE);
} else {
s2.sig_alg = VB2_SIG_INVALID;
s2.hash_alg = VB2_HASH_INVALID;
memset(&s2.key_guid, 0, GUID_SIZE);
}
/* Allocate the new buffer */
*out_size = s2.sig_offset + s2.sig_size;
buf = malloc(*out_size);
memset(buf, 0, *out_size);
/* Copy data into the buffer */
memcpy(buf, &s2, sizeof(s2));
/* strcpy() is safe because we allocated above based on strlen() */
strcpy((char *)(buf + s2.c.fixed_size), desc);
buf[s2.c.fixed_size + s2.c.desc_size - 1] = 0;
memcpy(buf + s2.sig_offset,
(const uint8_t *)sig + sig->sig_offset,
sig->sig_size);
/* Return the newly allocated buffer */
return (struct vb2_signature2 *)buf;
}

View File

@@ -25,7 +25,7 @@ static __inline const uint32_t roundup32(uint32_t v)
*
* @param key Packed key in vboot1 format
* @param desc Description of packed key
* @param out_size Size of the newly allocated buffer
* @param out_size Destination for size of the newly allocated buffer
* @return a newly allocated buffer with the converted key. Caller is
* responsible for freeing this buffer.
*/
@@ -33,4 +33,24 @@ struct vb2_packed_key2 *vb2_convert_packed_key2(
const struct vb2_packed_key *key,
const char *desc, uint32_t *out_size);
/**
* Convert a signature from vboot data format to vboot2 data format.
*
* Intended for use by unit tests. Does NOT validate the original struct
* contents, just copies them.
*
* @param sig Signature in vboot1 format
* @param desc Description of signature
* @param key Key to take algorithms and GUID from. If NULL, those
* fields are left uninitialized.
* @param out_size Destination for size of the newly allocated buffer
* @return a newly allocated buffer with the converted signature. Caller is
* responsible for freeing this buffer.
*/
struct vb2_signature2 *vb2_convert_signature2(
const struct vb2_signature *sig,
const char *desc,
const struct vb2_packed_key2 *key,
uint32_t *out_size);
#endif /* VBOOT_REFERENCE_VB2_CONVERT_STRUCTS_H_ */