blob: 0f4bf6fe9c0e9246528e852415752a054d9b9aca [file] [log] [blame]
/*
* Copyright 2021 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef PLATFORMS_SECURITY_TITAN_CR51_IMAGE_DESCRIPTOR_H_
#define PLATFORMS_SECURITY_TITAN_CR51_IMAGE_DESCRIPTOR_H_
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
/* _Static_assert is usually not enabled in C++ mode by compilers. */
#include <assert.h>
#define _Static_assert static_assert
#endif
/* This structure encodes a superset of what we have historically encoded in:
*
* Unless explicitly noted all fields are little-endian & offset/size fields
* are in bytes. This struct must reside in a IMAGE_REGION_STATIC region and
* must also reside on a 64K boundary. The size of the hashed/signed portion
* of the descriptor region can be determined solely by parsing the (fixed)
* image_descriptor struct.
*
* --------------------------------Flash layout--------------------------------
* | struct image_descriptor (signed) |
* | struct image_region[region_count] (signed) |
* ----------------------------------------------------------------------------
* | (optional: hash_type) struct hash_* (signed) |
* ----------------------------------------------------------------------------
* | (optional: denylist_size) struct denylist (signed) |
* | struct denylist_record[denylist_size] (signed) |
* ----------------------------------------------------------------------------
* | (optional: blob_size) struct blob (signed) |
* | uint8_t blob[blob_size] (signed) |
* ----------------------------------------------------------------------------
* | (optional: signature_scheme) struct signature_* (partially signed) |
* ----------------------------------------------------------------------------
* | (optional) struct key_rotation_records (not signed) |
* ----------------------------------------------------------------------------
*/
#define IMAGE_REGION_STATIC (1 << 0)
#define IMAGE_REGION_COMPRESSED (1 << 1)
#define IMAGE_REGION_WRITE_PROTECTED (1 << 2)
#define IMAGE_REGION_READ_PROTECTED (1 << 3)
#define IMAGE_REGION_PERSISTENT (1 << 4)
#define IMAGE_REGION_PERSISTENT_RELOCATABLE (1 << 5)
#define IMAGE_REGION_PERSISTENT_EXPANDABLE (1 << 6)
#define IMAGE_REGION_OVERRIDE (1 << 7)
#define IMAGE_REGION_OVERRIDE_ON_TRANSITION (1 << 8)
#define IMAGE_REGION_MAILBOX (1 << 9)
#define IMAGE_REGION_SKIP_BOOT_VALIDATION (1 << 10)
/* Little endian on flash. */
#define DESCRIPTOR_MAGIC 0x5f435344474d495f // "_IMGDSC_"
#define HASH_MAGIC 0x48534148 // "HASH"
#define DENYLIST_MAGIC 0x4b434c42 // "BLCK"
#define BLOB_MAGIC 0x424f4c42 // "BLOB"
#define SIGNATURE_MAGIC 0x4e474953 // "SIGN"
#define ROTATION_MAGIC 0x5254524b // "KRTR"
/* Indicates the type of the image. The type of the image also indicates the
* family of key that was used to sign the image.
*
* Note: if the image type is IMAGE_UNSIGNED_INTEGRITY, the signature_scheme has
* to be of type
* *_NO_SIGNATURE. Also, all other image types cannot transition to an image of
* type IMAGE_UNSIGNED_INTEGRITY.
*
* The way to verify an image of type IMAGE_UNSIGNED_INTEGRITY differs from
* other types of images as it is not signed with an asymmetric key. Instead,
* one can verify the integrity by computing the shasum over the descriptor.
*/
enum image_type
{
IMAGE_DEV = 0,
IMAGE_PROD = 1,
IMAGE_BREAKOUT = 2,
IMAGE_TEST = 3,
IMAGE_UNSIGNED_INTEGRITY = 4
};
enum hash_type
{
HASH_NONE = 0,
HASH_SHA2_224 = 1,
HASH_SHA2_256 = 2,
HASH_SHA2_384 = 3,
HASH_SHA2_512 = 4,
HASH_SHA3_224 = 5,
HASH_SHA3_256 = 6,
HASH_SHA3_384 = 7,
HASH_SHA3_512 = 8
};
/* Note: If the image is of type IMAGE_UNSIGNED_INTEGRITY, the signature_scheme
* has to be of type *_ONLY_NO_SIGNATURE.
*/
enum signature_scheme
{
SIGNATURE_NONE = 0,
SIGNATURE_RSA2048_PKCS15 = 1,
SIGNATURE_RSA3072_PKCS15 = 2,
SIGNATURE_RSA4096_PKCS15 = 3,
SIGNATURE_RSA4096_PKCS15_SHA512 = 4,
SHA256_ONLY_NO_SIGNATURE = 5
};
/* Payload image family. */
enum image_family
{
IMAGE_FAMILY_ALL = 0,
// values < 256 are reserved for Google-internal use
};
#define IMAGE_REGION_PROTECTED_ALIGNMENT (4096)
#define IMAGE_REGION_PROTECTED_PAGE_LENGTH (4096)
struct image_region
{
uint8_t region_name[32]; // null-terminated ASCII string
uint32_t region_offset; // read- and write- protected regions must be
// aligned to IMAGE_REGION_PROTECTED_ALIGNMENT.
// Other regions are also aligned which
// simplifies their implementation.
uint32_t region_size; // read- and write- protected regions must be a
// multiple of IMAGE_REGION_PROTECTED_PAGE_LENGTH.
/* Regions will not be persisted across different versions.
* This field is intended to flag potential incompatibilities in the
* context of data migration (e.g. the ELOG format changed between
* two BIOS releases).
*/
uint16_t region_version;
/* See IMAGE_REGION_* defines above. */
uint16_t region_attributes;
} __attribute__((__packed__));
/* Main structure (major=1, minor=0). Verification process:
* - Hash(image_descriptor + region_count * struct image_region +
* struct hash +
* struct denylist + denylist_size * struct denylist_record +
* struct blob + uint8_t blob[blob_size])
* - Verify the signature_* over the hash computed in the previous step
* - Compute the rolling hash of the regions marked IMAGE_REGION_STATIC
* - The image descriptor is excluded from the hash (descriptor_size bytes)
* - Compare the computed hash to the struct hash_*.hash
*/
struct image_descriptor
{
uint64_t descriptor_magic; // #define DESCRIPTOR_MAGIC
/* Major revisions of this structure are not backwards compatible. */
uint8_t descriptor_major;
/* Minor revisions of this structure are backwards compatible. */
uint8_t descriptor_minor;
/* Padding. */
uint16_t reserved_0;
/* This field allows us to mitigate a DOS vector if we end up
* scanning the image to discover the image descriptor. The offset
* and size are hashed with the rest of the descriptor to prevent
* an attacker from copying a valid descriptor to a different
* location.
*
* The offset is relative to the start of the image data.
*/
uint32_t descriptor_offset;
/* Includes this struct as well as the auxiliary structs (hash_*,
* signature_*, denylist, blob & key_rotation_records). This many bytes
* will be skipped when computing the hash of the region this struct
* resides in. Tail padding is allowed but must be all 0xff's.
*/
uint32_t descriptor_area_size;
/*** Image information. ***/
/* Null-terminated ASCII string. For BIOS this would be the platform
* family-genus-version-date (e.g. ixion-hsw-2.8.0-2017.10.03).
* Intended for consumption by system software that generates human
* readable output (e.g. gsys).
*/
uint8_t image_name[32];
/* Image transitions are enforced to be from/to the same family.
* 0 is treated as a wildcard (can upgrade to/from any image family).
* See image_family enum above.
*/
uint32_t image_family;
uint32_t image_major;
uint32_t image_minor;
uint32_t image_point;
uint32_t image_subpoint;
/* Seconds since epoch. */
uint64_t build_timestamp;
/* image_type enum { DEV, PROD, BREAKOUT, UNSIGNED_INTEGRITY} */
uint8_t image_type;
/* 0: no denylist struct, 1: watermark only, >1: watermark + denylist */
uint8_t denylist_size;
/* hash_type enum { NONE, SHA2_224, SHA2_256, ...} */
uint8_t hash_type;
/* signature_scheme enum { NONE, RSA2048_PKCS15, ...}
* If set, hash_type must be set as well (cannot be NONE).
*/
uint8_t signature_scheme;
/* struct image_region array size. */
uint8_t region_count;
uint8_t reserved_1;
uint16_t reserved_2;
/* The sum of the image_region.region_size fields must add up. */
uint32_t image_size;
/* Authenticated opaque data exposed to system software. Must be a multiple
* of 4 to maintain alignment. Does not include the blob struct magic.
*/
uint32_t blob_size;
/* The list is strictly ordered by region_offset.
* Must exhaustively describe the image.
*/
#ifndef OMIT_VARIABLE_ARRAYS
struct image_region image_regions[];
#endif
} __attribute__((__packed__));
/* Hash the static regions (IMAGE_REGION_STATIC) excluding this descriptor
* structure i.e. skipping image_descriptor.descriptor_size bytes (optional).
*/
struct hash_sha256
{
uint32_t hash_magic; // #define HASH_MAGIC
uint8_t hash[32];
} __attribute__((__packed__));
struct hash_sha512
{
uint32_t hash_magic; // #define HASH_MAGIC
uint8_t hash[64];
} __attribute__((__packed__));
struct denylist_record
{
uint32_t image_major;
uint32_t image_minor;
uint32_t image_point;
uint32_t image_subpoint;
} __attribute__((__packed__));
struct denylist
{
uint32_t denylist_magic; // #define DENYLIST_MAGIC
/* Deny list. The first entry is the watermark. All subsequent entries must
* be newer than the watermark.
*/
#ifndef OMIT_VARIABLE_ARRAYS
struct denylist_record denylist_record[];
#endif
} __attribute__((__packed__));
struct blob
{
uint32_t blob_magic; // #define BLOB_MAGIC
#ifndef OMIT_VARIABLE_ARRAYS
/* Array of blob_data structures - see blob_data below for details. */
uint8_t blobs[];
#endif
} __attribute__((__packed__));
/* If blobs[] is non-empty, it is expected to contain one more more instances
* of this struct. Each blob_data is followed by the minimum number of padding
* bytes (0-3) needed to maintain 4-byte alignment of blob_data structures.
* Padding bytes must be 0xFF and must be ignored by readers of blobs[].
*
* The ordering of the blob_data structures is undefined. Readers of blobs[]
* must locate expected blob_data by inspecting blob_type_magic of each
* blob_data. Readers are expected to ignore unknown blob_type_magic values,
* skipping over them to allow for future types.
*
* If blob_size is greater than zero but less than sizeof(struct blob_data), the
* blobs list is invalid. The blobs list is also invalid if there are multiple
* blob_data structures and the last one is truncated due to blob_size being too
* small to hold blob_payload_size. Readers must walk the entire length of the
* blob_data list to validate the list is well-formed. Any image with an
* invalid blobs list has an invalid descriptor and must be treated the same as
* an unsigned image.
*/
struct blob_data
{
/* BLOB_TYPE_MAGIC_* */
uint32_t blob_type_magic;
/* Size of the data contained in blob_payload. Need not be a multiple of 4
* bytes. Must have sizeof(struct blob_data) + blob_payload_size <=
* blob_size.
*/
uint32_t blob_payload_size;
#ifndef OMIT_VARIABLE_ARRAYS
uint8_t blob_payload[];
#endif
} __attribute__((__packed__));
/* Signature of the hash of the image_descriptor structure up to and including
* this struct but excluding the signature field (optional).
*/
struct signature_rsa2048_pkcs15
{
uint32_t signature_magic; // #define SIGNATURE_MAGIC
/* Monotonic index of the key used to sign the image (starts at 1). */
uint16_t key_index;
/* Used to revoke keys, persisted by the enforcer. */
uint16_t min_key_index;
uint32_t exponent; // little-endian
uint8_t modulus[256]; // big-endian
uint8_t signature[256]; // big-endian
} __attribute__((__packed__));
struct signature_rsa3072_pkcs15
{
uint32_t signature_magic; // #define SIGNATURE_MAGIC
/* Monotonic index of the key used to sign the image (starts at 1). */
uint16_t key_index;
/* Used to revoke keys, persisted by the enforcer. */
uint16_t min_key_index;
uint32_t exponent; // little-endian
uint8_t modulus[384]; // big-endian
uint8_t signature[384]; // big-endian
} __attribute__((__packed__));
struct signature_rsa4096_pkcs15
{
uint32_t signature_magic; // #define SIGNATURE_MAGIC
/* Monotonic index of the key used to sign the image (starts at 1). */
uint16_t key_index;
/* Used to revoke keys, persisted by the enforcer. */
uint16_t min_key_index;
uint32_t exponent; // little-endian
uint8_t modulus[512]; // big-endian
uint8_t signature[512]; // big-endian
} __attribute__((__packed__));
struct sha256_only_no_signature
{
uint32_t signature_magic; // #define SIGNATURE_MAGIC
uint8_t digest[32];
} __attribute__((__packed__));
/* Key rotation record (optional).
* Enables enforcers to verify images signed with newer (rotated) keys.
* The hash function, signature & padding schemes are currently pinned
* by image family. This struct is likely to evolve.
*/
struct record_rsa2048_pkcs15
{
uint16_t from_index;
uint16_t to_index;
uint32_t exponent; // exponent of the new key, little-endian
uint8_t modulus[256]; // modulus of the new key, big-endian
/* SIGN[K<from_index>](HASH(to_index (LE) | exponent (LE) | modulus (BE)))
*/
uint8_t signature[256]; // big-endian
} __attribute__((__packed__));
struct record_rsa3072_pkcs15
{
uint16_t from_index;
uint16_t to_index;
uint32_t exponent; // exponent of the new key, little-endian
uint8_t modulus[384]; // modulus of the new key, big-endian
/* SIGN[K<from_index>](HASH(to_index (LE) | exponent (LE) | modulus (BE)))
*/
uint8_t signature[384]; // big-endian
} __attribute__((__packed__));
struct record_rsa4096_pkcs15
{
uint16_t from_index;
uint16_t to_index;
uint32_t exponent; // exponent of the new key, little-endian
uint8_t modulus[512]; // modulus of the new key, big-endian
/* SIGN[K<from_index>](HASH(to_index (LE) | exponent (LE) | modulus (BE)))
*/
uint8_t signature[512]; // big-endian
} __attribute__((__packed__));
struct key_rotation_records_rsa2048_pkcs15
{
uint32_t rotation_magic; // #define ROTATION_MAGIC
uint16_t record_count;
uint16_t reserved_0;
#ifndef OMIT_VARIABLE_ARRAYS
struct record_rsa2048_pkcs15 records[];
#endif
} __attribute__((__packed__));
struct key_rotation_records_rsa3072_pkcs15
{
uint32_t rotation_magic; // #define ROTATION_MAGIC
uint16_t record_count;
uint16_t reserved_0;
#ifndef OMIT_VARIABLE_ARRAYS
struct record_rsa3072_pkcs15 records[];
#endif
} __attribute__((__packed__));
struct key_rotation_records_rsa4096_pkcs15
{
uint32_t rotation_magic; // #define ROTATION_MAGIC
uint16_t record_count;
uint16_t reserved_0;
#ifndef OMIT_VARIABLE_ARRAYS
struct record_rsa3072_pkcs15 records[];
#endif
} __attribute__((__packed__));
#endif // PLATFORMS_SECURITY_TITAN_CR51_IMAGE_DESCRIPTOR_H_