summaryrefslogtreecommitdiff
path: root/host/lib21
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib21')
-rw-r--r--host/lib21/host_common.c303
-rw-r--r--host/lib21/host_key.c61
-rw-r--r--host/lib21/host_misc.c4
-rw-r--r--host/lib21/host_signature.c6
-rw-r--r--host/lib21/include/host_common21.h124
-rw-r--r--host/lib21/include/host_key21.h (renamed from host/lib21/include/host_key2.h)14
-rw-r--r--host/lib21/include/host_misc21.h (renamed from host/lib21/include/host_misc2.h)0
-rw-r--r--host/lib21/include/host_signature21.h (renamed from host/lib21/include/host_signature2.h)0
-rw-r--r--host/lib21/include/host_struct21.h233
9 files changed, 738 insertions, 7 deletions
diff --git a/host/lib21/host_common.c b/host/lib21/host_common.c
new file mode 100644
index 00000000..245b1885
--- /dev/null
+++ b/host/lib21/host_common.c
@@ -0,0 +1,303 @@
+/* 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
+ * found in the LICENSE file.
+ *
+ * Signature validation functions
+ */
+
+#include "2common.h"
+#include "2rsa.h"
+#include "2sha.h"
+#include "2sysincludes.h"
+#include "host_common21.h"
+
+const char *vb21_common_desc(const void *buf)
+{
+ const struct vb21_struct_common *c = buf;
+
+ return c->desc_size ? (const char *)c + c->fixed_size : "";
+}
+
+vb2_error_t vb21_verify_common_header(const void *parent, uint32_t parent_size)
+{
+ const struct vb21_struct_common *c = parent;
+
+ /* Parent buffer size must be at least the claimed total size */
+ if (parent_size < c->total_size)
+ return VB2_ERROR_COMMON_TOTAL_SIZE;
+
+ /*
+ * And big enough for the fixed size, which itself must be at least as
+ * big as the common struct header.
+ */
+ if (c->total_size < c->fixed_size || c->fixed_size < sizeof(*c))
+ return VB2_ERROR_COMMON_FIXED_SIZE;
+
+ /* Make sure sizes are all multiples of 32 bits */
+ if (!vb2_aligned(c->total_size, sizeof(uint32_t)))
+ return VB2_ERROR_COMMON_TOTAL_UNALIGNED;
+ if (!vb2_aligned(c->fixed_size, sizeof(uint32_t)))
+ return VB2_ERROR_COMMON_FIXED_UNALIGNED;
+ if (!vb2_aligned(c->desc_size, sizeof(uint32_t)))
+ return VB2_ERROR_COMMON_DESC_UNALIGNED;
+
+ /* Check description */
+ if (c->desc_size > 0) {
+ /* Make sure description fits and doesn't wrap */
+ if (c->fixed_size + c->desc_size < c->fixed_size)
+ return VB2_ERROR_COMMON_DESC_WRAPS;
+ if (c->fixed_size + c->desc_size > c->total_size)
+ return VB2_ERROR_COMMON_DESC_SIZE;
+
+ /* Description must be null-terminated */
+ if (vb21_common_desc(c)[c->desc_size - 1] != 0)
+ return VB2_ERROR_COMMON_DESC_TERMINATOR;
+ }
+
+ return VB2_SUCCESS;
+}
+
+vb2_error_t vb21_verify_common_member(const void *parent, uint32_t *min_offset,
+ uint32_t member_offset,
+ uint32_t member_size)
+{
+ const struct vb21_struct_common *c = parent;
+ uint32_t member_end = member_offset + member_size;
+
+ /* Make sure member doesn't wrap */
+ if (member_end < member_offset)
+ return VB2_ERROR_COMMON_MEMBER_WRAPS;
+
+ /* Member offset and size must be 32-bit aligned */
+ if (!vb2_aligned(member_offset, sizeof(uint32_t)) ||
+ !vb2_aligned(member_size, sizeof(uint32_t)))
+ return VB2_ERROR_COMMON_MEMBER_UNALIGNED;
+
+ /* Initialize minimum offset if necessary */
+ if (!*min_offset)
+ *min_offset = c->fixed_size + c->desc_size;
+
+ /* Member must be after minimum offset */
+ if (member_offset < *min_offset)
+ return VB2_ERROR_COMMON_MEMBER_OVERLAP;
+
+ /* Member must end before total size */
+ if (member_end > c->total_size)
+ return VB2_ERROR_COMMON_MEMBER_SIZE;
+
+ /* Update minimum offset for subsequent checks */
+ *min_offset = member_end;
+
+ return VB2_SUCCESS;
+}
+
+vb2_error_t vb21_verify_common_subobject(const void *parent,
+ uint32_t *min_offset,
+ uint32_t member_offset)
+{
+ const struct vb21_struct_common *p = parent;
+ const struct vb21_struct_common *m =
+ (const struct vb21_struct_common *)
+ ((const uint8_t *)parent + member_offset);
+ vb2_error_t rv;
+
+ /*
+ * Verify the parent has space at the member offset for the common
+ * header.
+ */
+ rv = vb21_verify_common_member(parent, min_offset, member_offset,
+ sizeof(*m));
+ if (rv)
+ return rv;
+
+ /*
+ * Now it's safe to look at the member's header, and verify any
+ * additional data for the object past its common header fits in the
+ * parent.
+ */
+ rv = vb21_verify_common_header(m, p->total_size - member_offset);
+ if (rv)
+ return rv;
+
+ /* Advance the min offset to the end of the subobject */
+ *min_offset = member_offset + m->total_size;
+
+ 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);
+}
+
+const struct vb2_id *vb2_hash_id(enum vb2_hash_algorithm hash_alg)
+{
+ switch(hash_alg) {
+#ifdef VB2_SUPPORT_SHA1
+ case VB2_HASH_SHA1:
+ {
+ static const struct vb2_id id = VB2_ID_NONE_SHA1;
+ return &id;
+ }
+#endif
+#ifdef VB2_SUPPORT_SHA256
+ case VB2_HASH_SHA256:
+ {
+ static const struct vb2_id id = VB2_ID_NONE_SHA256;
+ return &id;
+ }
+#endif
+#ifdef VB2_SUPPORT_SHA512
+ case VB2_HASH_SHA512:
+ {
+ static const struct vb2_id id = VB2_ID_NONE_SHA512;
+ return &id;
+ }
+#endif
+ default:
+ return NULL;
+ }
+}
+
+vb2_error_t vb21_verify_signature(const struct vb21_signature *sig,
+ uint32_t size)
+{
+ uint32_t min_offset = 0;
+ uint32_t expect_sig_size;
+ vb2_error_t rv;
+
+ /* Check magic number */
+ if (sig->c.magic != VB21_MAGIC_SIGNATURE)
+ return VB2_ERROR_SIG_MAGIC;
+
+ /* Make sure common header is good */
+ rv = vb21_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 != VB21_SIGNATURE_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 = vb21_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;
+}
+
+/**
+ * Return the signature data for a signature
+ */
+static uint8_t *vb21_signature_data(struct vb21_signature *sig)
+{
+ return (uint8_t *)sig + sig->sig_offset;
+}
+
+vb2_error_t vb21_verify_digest(const struct vb2_public_key *key,
+ struct vb21_signature *sig,
+ const uint8_t *digest,
+ const struct vb2_workbuf *wb)
+{
+ uint32_t key_sig_size = vb2_sig_size(key->sig_alg, key->hash_alg);
+
+ /* If we can't figure out the signature size, key algorithm was bad */
+ if (!key_sig_size)
+ return VB2_ERROR_VDATA_ALGORITHM;
+
+ /* Make sure the signature and key algorithms match */
+ if (key->sig_alg != sig->sig_alg || key->hash_alg != sig->hash_alg)
+ return VB2_ERROR_VDATA_ALGORITHM_MISMATCH;
+
+ if (sig->sig_size != key_sig_size)
+ return VB2_ERROR_VDATA_SIG_SIZE;
+
+ if (key->sig_alg == VB2_SIG_NONE) {
+ /* Bare hash */
+ if (vb2_safe_memcmp(vb21_signature_data(sig),
+ digest, key_sig_size))
+ return VB2_ERROR_VDATA_VERIFY_DIGEST;
+
+ return VB2_SUCCESS;
+ } else {
+ /* RSA-signed digest */
+ return vb2_rsa_verify_digest(key,
+ vb21_signature_data(sig),
+ digest, wb);
+ }
+}
+
+vb2_error_t vb21_verify_data(const void *data, uint32_t size,
+ struct vb21_signature *sig,
+ const struct vb2_public_key *key,
+ const struct vb2_workbuf *wb)
+{
+ struct vb2_workbuf wblocal = *wb;
+ struct vb2_digest_context *dc;
+ uint8_t *digest;
+ uint32_t digest_size;
+ vb2_error_t rv;
+
+ if (sig->data_size != size) {
+ VB2_DEBUG("Wrong amount of data signed.\n");
+ return VB2_ERROR_VDATA_SIZE;
+ }
+
+ /* Digest goes at start of work buffer */
+ digest_size = vb2_digest_size(key->hash_alg);
+ if (!digest_size)
+ return VB2_ERROR_VDATA_DIGEST_SIZE;
+
+ digest = vb2_workbuf_alloc(&wblocal, digest_size);
+ if (!digest)
+ return VB2_ERROR_VDATA_WORKBUF_DIGEST;
+
+ /* Hashing requires temp space for the context */
+ dc = vb2_workbuf_alloc(&wblocal, sizeof(*dc));
+ if (!dc)
+ return VB2_ERROR_VDATA_WORKBUF_HASHING;
+
+ rv = vb2_digest_init(dc, key->hash_alg);
+ if (rv)
+ return rv;
+
+ rv = vb2_digest_extend(dc, data, size);
+ if (rv)
+ return rv;
+
+ rv = vb2_digest_finalize(dc, digest, digest_size);
+ if (rv)
+ return rv;
+
+ vb2_workbuf_free(&wblocal, sizeof(*dc));
+
+ return vb21_verify_digest(key, sig, digest, &wblocal);
+}
diff --git a/host/lib21/host_key.c b/host/lib21/host_key.c
index 34e5a633..6e3a2765 100644
--- a/host/lib21/host_key.c
+++ b/host/lib21/host_key.c
@@ -14,10 +14,10 @@
#include "2sha.h"
#include "2sysincludes.h"
#include "host_common.h"
-#include "host_key2.h"
+#include "host_common21.h"
+#include "host_key21.h"
#include "host_misc.h"
#include "openssl_compat.h"
-#include "vb21_common.h"
const struct vb2_text_vs_enum vb2_text_vs_sig[] = {
{"RSA1024", VB2_SIG_RSA1024},
@@ -651,3 +651,60 @@ vb2_error_t vb21_public_key_write(const struct vb2_public_key *key,
free(pkey);
return ret;
}
+
+vb2_error_t vb21_unpack_key(struct vb2_public_key *key, const uint8_t *buf,
+ uint32_t size)
+{
+ const struct vb21_packed_key *pkey =
+ (const struct vb21_packed_key *)buf;
+ uint32_t sig_size;
+ uint32_t min_offset = 0;
+ vb2_error_t rv;
+
+ /* Check magic number */
+ if (pkey->c.magic != VB21_MAGIC_PACKED_KEY)
+ return VB2_ERROR_UNPACK_KEY_MAGIC;
+
+ rv = vb21_verify_common_header(buf, size);
+ if (rv)
+ return rv;
+
+ /* Make sure key data is inside */
+ rv = vb21_verify_common_member(pkey, &min_offset,
+ pkey->key_offset, pkey->key_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 (pkey->c.struct_version_major != VB21_PACKED_KEY_VERSION_MAJOR)
+ return VB2_ERROR_UNPACK_KEY_STRUCT_VERSION;
+
+ /* Copy key algorithms */
+ key->hash_alg = pkey->hash_alg;
+ if (!vb2_digest_size(key->hash_alg))
+ return VB2_ERROR_UNPACK_KEY_HASH_ALGORITHM;
+
+ key->sig_alg = pkey->sig_alg;
+ if (key->sig_alg != VB2_SIG_NONE) {
+ sig_size = vb2_rsa_sig_size(key->sig_alg);
+ if (!sig_size)
+ return VB2_ERROR_UNPACK_KEY_SIG_ALGORITHM;
+ rv = vb2_unpack_key_data(
+ key,
+ (const uint8_t *)pkey + pkey->key_offset,
+ pkey->key_size);
+ if (rv)
+ return rv;
+ }
+
+ /* Key description */
+ key->desc = vb21_common_desc(pkey);
+ key->version = pkey->key_version;
+ key->id = &pkey->id;
+
+ return VB2_SUCCESS;
+}
diff --git a/host/lib21/host_misc.c b/host/lib21/host_misc.c
index 71a77c5d..ebc4eac5 100644
--- a/host/lib21/host_misc.c
+++ b/host/lib21/host_misc.c
@@ -14,8 +14,8 @@
#include "2sha.h"
#include "2sysincludes.h"
#include "host_common.h"
-#include "host_misc2.h"
-#include "vb21_common.h"
+#include "host_common21.h"
+#include "host_misc21.h"
vb2_error_t vb2_read_file(const char *filename, uint8_t **data_ptr,
uint32_t *size_ptr)
diff --git a/host/lib21/host_signature.c b/host/lib21/host_signature.c
index e4dead01..77ee448a 100644
--- a/host/lib21/host_signature.c
+++ b/host/lib21/host_signature.c
@@ -12,10 +12,10 @@
#include "2sha.h"
#include "2sysincludes.h"
#include "host_common.h"
-#include "host_key2.h"
+#include "host_common21.h"
+#include "host_key21.h"
#include "host_misc.h"
-#include "host_signature2.h"
-#include "vb21_common.h"
+#include "host_signature21.h"
vb2_error_t vb2_digest_info(enum vb2_hash_algorithm hash_alg,
const uint8_t **buf_ptr, uint32_t *size_ptr)
diff --git a/host/lib21/include/host_common21.h b/host/lib21/include/host_common21.h
new file mode 100644
index 00000000..fa8086b8
--- /dev/null
+++ b/host/lib21/include/host_common21.h
@@ -0,0 +1,124 @@
+/* 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
+ * found in the LICENSE file.
+ *
+ * Common functions between firmware and kernel verified boot.
+ */
+
+#ifndef VBOOT_REFERENCE_VB21_COMMON_H_
+#define VBOOT_REFERENCE_VB21_COMMON_H_
+
+#include "2common.h"
+#include "2return_codes.h"
+#include "2struct.h"
+#include "host_struct21.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * Return the description of an object starting with a vb21_struct_common
+ * header.
+ *
+ * Does not sanity-check the buffer; merely returns the pointer.
+ *
+ * @param buf Pointer to common object
+ * @return A pointer to description or an empty string if none.
+ */
+const char *vb21_common_desc(const void *buf);
+
+/**
+ * Verify the common struct header is fully contained in its parent data
+ *
+ * Also verifies the description is either zero-length or null-terminated.
+ *
+ * @param parent Parent data
+ * @param parent_size Parent size in bytes
+ * @return VB2_SUCCESS, or non-zero if error.
+ */
+vb2_error_t vb21_verify_common_header(const void *parent, uint32_t parent_size);
+
+/**
+ * Verify a member is within the data for a parent object
+ *
+ * @param parent Parent data (starts with struct vb21_struct_common)
+ * @param min_offset Pointer to minimum offset where member can be located.
+ * If this offset is 0 on input, uses the size of the
+ * fixed header (and description, if any). This will be
+ * updated on return to the end of the passed member. On
+ * error, the value of min_offset is undefined.
+ * @param member_offset Offset of member data from start of parent, in bytes
+ * @param member_size Size of member data, in bytes
+ * @return VB2_SUCCESS, or non-zero if error.
+ */
+vb2_error_t vb21_verify_common_member(const void *parent, uint32_t *min_offset,
+ uint32_t member_offset,
+ uint32_t member_size);
+
+/**
+ * Verify a member which starts with a common header is within the parent
+ *
+ * This does not verify the contents of the member or its header, only that the
+ * member's claimed total size fits within the parent's claimed total size at
+ * the specified offset.
+ *
+ * @param parent Parent data (starts with struct vb21_struct_common)
+ * @param min_offset Pointer to minimum offset where member can be located.
+ * If this offset is 0 on input, uses the size of the
+ * fixed header (and description, if any). This will be
+ * updated on return to the end of the passed member. On
+ * error, the value of min_offset is undefined.
+ * @param member_offset Offset of member data from start of parent, in bytes.
+ * This should be the start of the common header of the
+ * member.
+ * @return VB2_SUCCESS, or non-zero if error.
+ */
+vb2_error_t vb21_verify_common_subobject(const void *parent,
+ uint32_t *min_offset,
+ uint32_t member_offset);
+
+/**
+ * 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.
+ */
+vb2_error_t vb21_verify_signature(const struct vb21_signature *sig,
+ uint32_t size);
+
+/**
+ * Verify a signature against an expected hash digest.
+ *
+ * @param key Key to use in signature verification
+ * @param sig Signature to verify (may be destroyed in process)
+ * @param digest Digest of signed data
+ * @param wb Work buffer
+ * @return VB2_SUCCESS, or non-zero if error.
+ */
+vb2_error_t vb21_verify_digest(const struct vb2_public_key *key,
+ struct vb21_signature *sig,
+ const uint8_t *digest,
+ const struct vb2_workbuf *wb);
+
+/**
+ * Verify data matches signature.
+ *
+ * @param data Data to verify
+ * @param size Size of data buffer. Note that amount of data to
+ * actually validate is contained in sig->data_size.
+ * @param sig Signature of data (destroyed in process)
+ * @param key Key to use to validate signature
+ * @param wb Work buffer
+ * @return VB2_SUCCESS, or non-zero error code if error.
+ */
+vb2_error_t vb21_verify_data(const void *data, uint32_t size,
+ struct vb21_signature *sig,
+ const struct vb2_public_key *key,
+ const struct vb2_workbuf *wb);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* VBOOT_REFERENCE_VB21_COMMON_H_ */
diff --git a/host/lib21/include/host_key2.h b/host/lib21/include/host_key21.h
index d8a90f5f..219e98ab 100644
--- a/host/lib21/include/host_key2.h
+++ b/host/lib21/include/host_key21.h
@@ -267,4 +267,18 @@ enum vb2_signature_algorithm vb2_rsa_sig_alg(struct rsa_st *rsa);
vb2_error_t vb21_public_key_write(const struct vb2_public_key *key,
const char *filename);
+/**
+ * Unpack a key for use in verification
+ *
+ * The elements of the unpacked key will point into the source buffer, so don't
+ * free the source buffer until you're done with the key.
+ *
+ * @param key Destintion for unpacked key
+ * @param buf Source buffer containing packed key
+ * @param size Size of buffer in bytes
+ * @return VB2_SUCCESS, or non-zero error code if error.
+ */
+vb2_error_t vb21_unpack_key(struct vb2_public_key *key, const uint8_t *buf,
+ uint32_t size);
+
#endif /* VBOOT_REFERENCE_HOST_KEY2_H_ */
diff --git a/host/lib21/include/host_misc2.h b/host/lib21/include/host_misc21.h
index 795ebb23..795ebb23 100644
--- a/host/lib21/include/host_misc2.h
+++ b/host/lib21/include/host_misc21.h
diff --git a/host/lib21/include/host_signature2.h b/host/lib21/include/host_signature21.h
index 0b1784af..0b1784af 100644
--- a/host/lib21/include/host_signature2.h
+++ b/host/lib21/include/host_signature21.h
diff --git a/host/lib21/include/host_struct21.h b/host/lib21/include/host_struct21.h
new file mode 100644
index 00000000..6f91e36c
--- /dev/null
+++ b/host/lib21/include/host_struct21.h
@@ -0,0 +1,233 @@
+/* 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
+ * found in the LICENSE file.
+ *
+ * Vboot 2.1 data structures
+ *
+ * Offsets should be padded to 32-bit boundaries, since some architectures
+ * have trouble with accessing unaligned integers.
+ */
+
+#ifndef VBOOT_REFERENCE_VB21_STRUCT_H_
+#define VBOOT_REFERENCE_VB21_STRUCT_H_
+
+#include "2id.h"
+#include "2sysincludes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * Magic numbers used by vb21_struct_common.magic.
+ *
+ * All valid numbers should be listed here to avoid accidental overlap.
+ * Numbers start at a large value, so that previous parsers (which stored
+ * things like lengths and offsets at that field) will detect and reject new
+ * structs as invalid.
+ */
+enum vb21_struct_common_magic {
+ /* "Vb2I" = vb21_packed_private_key.c.magic */
+ VB21_MAGIC_PACKED_PRIVATE_KEY = 0x49326256,
+
+ /* "Vb2P" = vb21_packed_key.c.magic */
+ VB21_MAGIC_PACKED_KEY = 0x50326256,
+
+ /* "Vb2S" = vb21_signature.c.magic */
+ VB21_MAGIC_SIGNATURE = 0x53326256,
+};
+
+
+/*
+ * Generic struct header for all vboot2.1 structs. This makes it easy to
+ * automatically parse and identify vboot structs (e.g., in futility). This
+ * must be the first member of the parent vboot2.1 struct.
+ */
+struct vb21_struct_common {
+ /* Magic number; see vb21_struct_common_magic for expected values */
+ uint32_t magic;
+
+ /*
+ * Parent struct version; see each struct for the expected value.
+ *
+ * How to handle struct version mismatches, if the parser is version
+ * A.b and the data is version C.d:
+ * 1) If A.b == C.d, we're good.
+ * 2) If A != C, the data cannot be parsed at all.
+ * 3) If b < d, C.d is a newer version of data which is backwards-
+ * compatible to old parsers. We're good.
+ * 4) If b > d, C.d is an older version of data. The parser should
+ * use default values for fields added after version d. We're
+ * good.
+ *
+ * Struct versions start at 3.0, since the highest version of the old
+ * structures was 2.1. This way, there is no possibility of collision
+ * for old code which depends on the version number.
+ */
+ uint16_t struct_version_major;
+ uint16_t struct_version_minor;
+
+ /*
+ * Size of the parent structure and all its data, including the
+ * description and any necessary padding. That is, all data must lie
+ * in a contiguous region of <total_size> bytes starting at the first
+ * byte of this header.
+ */
+ uint32_t total_size;
+
+ /*
+ * Size of the fixed portion of the parent structure. If a description
+ * is present, it must start at this offset.
+ */
+ uint32_t fixed_size;
+
+ /*
+ * The object may contain an ASCII description following the fixed
+ * portion of the structure. If it is present, it must be
+ * null-terminated, and padded with 0 (null) bytes to a multiple of 32
+ * bits.
+ *
+ * Size of ASCII description in bytes, counting null terminator and
+ * padding (if any). Set 0 if no description is present. If non-zero,
+ * there must be a null terminator (0) at offset (fixed_size +
+ * desc_size - 1).
+ */
+ uint32_t desc_size;
+} __attribute__((packed));
+
+#define EXPECTED_VB21_STRUCT_COMMON_SIZE 20
+
+/* Current version of vb21_packed_key struct */
+#define VB21_PACKED_KEY_VERSION_MAJOR 3
+#define VB21_PACKED_KEY_VERSION_MINOR 0
+
+/*
+ * Packed public key data
+ *
+ * The key data must be arranged like this:
+ * 1) vb21_packed_key header struct h
+ * 2) Key description (pointed to by h.c.fixed_size)
+ * 3) Key data key (pointed to by h.key_offset)
+ */
+struct vb21_packed_key {
+ /* Common header fields */
+ struct vb21_struct_common c;
+
+ /* Offset of key data from start of this struct */
+ uint32_t key_offset;
+
+ /* Size of key data in bytes (NOT strength of key in bits) */
+ uint32_t key_size;
+
+ /* Signature algorithm used by the key (enum vb2_signature_algorithm) */
+ uint16_t sig_alg;
+
+ /*
+ * Hash digest algorithm used with the key (enum vb2_hash_algorithm).
+ * This is explicitly specified as part of the key to prevent use of a
+ * strong key with a weak hash.
+ */
+ uint16_t hash_alg;
+
+ /* Key version */
+ uint32_t key_version;
+
+ /* Key ID */
+ struct vb2_id id;
+} __attribute__((packed));
+
+#define EXPECTED_VB21_PACKED_KEY_SIZE \
+ (EXPECTED_VB21_STRUCT_COMMON_SIZE + 16 + EXPECTED_ID_SIZE)
+
+/* Current version of vb21_packed_private_key struct */
+#define VB21_PACKED_PRIVATE_KEY_VERSION_MAJOR 3
+#define VB21_PACKED_PRIVATE_KEY_VERSION_MINOR 0
+
+/*
+ * Packed private key data
+ *
+ * The key data must be arranged like this:
+ * 1) vb21_packed_private_key header struct h
+ * 2) Key description (pointed to by h.c.fixed_size)
+ * 3) Key data key (pointed to by h.key_offset)
+ */
+struct vb21_packed_private_key {
+ /* Common header fields */
+ struct vb21_struct_common c;
+
+ /* Offset of key data from start of this struct */
+ uint32_t key_offset;
+
+ /* Size of key data in bytes (NOT strength of key in bits) */
+ uint32_t key_size;
+
+ /* Signature algorithm used by the key (enum vb2_signature_algorithm) */
+ uint16_t sig_alg;
+
+ /*
+ * Hash digest algorithm used with the key (enum vb2_hash_algorithm).
+ * This is explicitly specified as part of the key to prevent use of a
+ * strong key with a weak hash.
+ */
+ uint16_t hash_alg;
+
+ /* Key ID */
+ struct vb2_id id;
+} __attribute__((packed));
+
+#define EXPECTED_VB21_PACKED_PRIVATE_KEY_SIZE \
+ (EXPECTED_VB21_STRUCT_COMMON_SIZE + 12 + EXPECTED_ID_SIZE)
+
+/* Current version of vb21_signature struct */
+#define VB21_SIGNATURE_VERSION_MAJOR 3
+#define VB21_SIGNATURE_VERSION_MINOR 0
+
+/*
+ * Signature data
+ *
+ * The signature data must be arranged like this:
+ * 1) vb21_signature header struct h
+ * 2) Signature description (pointed to by h.c.fixed_size)
+ * 3) Signature data (pointed to by h.sig_offset)
+ */
+struct vb21_signature {
+ /* Common header fields */
+ struct vb21_struct_common c;
+
+ /* Offset of signature data from start of this struct */
+ uint32_t sig_offset;
+
+ /* Size of signature data in bytes */
+ uint32_t sig_size;
+
+ /* Size of the data block which was signed in bytes */
+ uint32_t data_size;
+
+ /* Signature algorithm used (enum vb2_signature_algorithm) */
+ uint16_t sig_alg;
+
+ /* Hash digest algorithm used (enum vb2_hash_algorithm) */
+ uint16_t hash_alg;
+
+ /*
+ * ID for the signature.
+ *
+ * If this is a keyblock signature entry, this is the ID of the key
+ * used to generate this signature. This allows the firmware to
+ * quickly determine which signature block (if any) goes with the key
+ * being used by the firmware.
+ *
+ * If this is a preamble hash entry, this is the ID of the data type
+ * being hashed. There is no key ID, because sig_alg=VB2_ALG_NONE.
+ */
+ struct vb2_id id;
+} __attribute__((packed));
+
+#define EXPECTED_VB21_SIGNATURE_SIZE \
+ (EXPECTED_VB21_STRUCT_COMMON_SIZE + 16 + EXPECTED_ID_SIZE)
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* VBOOT_REFERENCE_VB21_STRUCT_H_ */