mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-11-25 18:55:24 +00:00
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:
committed by
chrome-internal-fetch
parent
3c6ec76e32
commit
c0ce70b468
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
Reference in New Issue
Block a user