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;
|
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,
|
const uint8_t *buf,
|
||||||
uint32_t size);
|
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 */
|
/* Size of work buffer sufficient for vb2_rsa_verify_digest() worst case */
|
||||||
#define VB2_VERIFY_DIGEST_WORKBUF_BYTES VB2_VERIFY_RSA_DIGEST_WORKBUF_BYTES
|
#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 */
|
/* Signature header doesn't fit */
|
||||||
VB2_ERROR_SIG_HEADER_SIZE,
|
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 */
|
/* Wrong amount of data signed */
|
||||||
VB2_ERROR_VDATA_SIZE,
|
VB2_ERROR_VDATA_SIZE,
|
||||||
|
|
||||||
|
|||||||
@@ -235,6 +235,73 @@ static void test_verify_data(struct vb2_packed_key *key1,
|
|||||||
free(sig2);
|
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)
|
int test_algorithm(int key_algorithm, const char *keys_dir)
|
||||||
{
|
{
|
||||||
char filename[1024];
|
char filename[1024];
|
||||||
@@ -272,6 +339,7 @@ int test_algorithm(int key_algorithm, const char *keys_dir)
|
|||||||
test_unpack_key(key1);
|
test_unpack_key(key1);
|
||||||
test_unpack_key2(key1);
|
test_unpack_key2(key1);
|
||||||
test_verify_data(key1, sig);
|
test_verify_data(key1, sig);
|
||||||
|
test_verify_signature(key1, sig);
|
||||||
|
|
||||||
if (key1)
|
if (key1)
|
||||||
free(key1);
|
free(key1);
|
||||||
|
|||||||
@@ -419,6 +419,32 @@ static void test_common_header_functions(void)
|
|||||||
"vb2_verify_common_subobject() size");
|
"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[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
test_memcmp();
|
test_memcmp();
|
||||||
@@ -427,6 +453,7 @@ int main(int argc, char* argv[])
|
|||||||
test_struct_packing();
|
test_struct_packing();
|
||||||
test_helper_functions();
|
test_helper_functions();
|
||||||
test_common_header_functions();
|
test_common_header_functions();
|
||||||
|
test_sig_size();
|
||||||
|
|
||||||
return gTestSuccess ? 0 : 255;
|
return gTestSuccess ? 0 : 255;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,3 +56,57 @@ struct vb2_packed_key2 *vb2_convert_packed_key2(
|
|||||||
/* Return the newly allocated buffer */
|
/* Return the newly allocated buffer */
|
||||||
return (struct vb2_packed_key2 *)kbuf;
|
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 key Packed key in vboot1 format
|
||||||
* @param desc Description of packed key
|
* @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
|
* @return a newly allocated buffer with the converted key. Caller is
|
||||||
* responsible for freeing this buffer.
|
* responsible for freeing this buffer.
|
||||||
*/
|
*/
|
||||||
@@ -33,4 +33,24 @@ struct vb2_packed_key2 *vb2_convert_packed_key2(
|
|||||||
const struct vb2_packed_key *key,
|
const struct vb2_packed_key *key,
|
||||||
const char *desc, uint32_t *out_size);
|
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_ */
|
#endif /* VBOOT_REFERENCE_VB2_CONVERT_STRUCTS_H_ */
|
||||||
|
|||||||
Reference in New Issue
Block a user