[sw/silicon_creator] Add security_version to manifest and rearrange fields
This change adds the security_version field to the manifest and
rearranges fields so that related fields are grouped together and they
are defined roughly in the order that they are used.
Signed-off-by: Alphan Ulusoy <alphan@google.com>
diff --git a/sw/device/silicon_creator/lib/manifest.h b/sw/device/silicon_creator/lib/manifest.h
index 90855b6..fe72d94 100644
--- a/sw/device/silicon_creator/lib/manifest.h
+++ b/sw/device/silicon_creator/lib/manifest.h
@@ -37,38 +37,54 @@
*/
typedef struct manifest {
/**
- * Manifest identifier.
- */
- uint32_t identifier;
- /**
* Image signature.
*
- * The signed region of an image starts at `image_length` and ends at the
- * end of the image. The start and the length of the signed region can be
- * obtained using `manifest_signed_region_get`.
+ * RSASSA-PKCS1-v1_5 signature of the image generated using a 3072-bit RSA
+ * private key and the SHA-256 hash function. The signed region of an image
+ * starts immediately after this field and ends at the end of the image. The
+ * start and the length of the signed region can be obtained using
+ * `manifest_signed_region_get`.
*/
sigverify_rsa_buffer_t signature;
/**
- * Image length in bytes.
+ * Modulus of the signer's 3072-bit RSA public key.
*/
- uint32_t image_length;
- /**
- * Image major version.
- */
- uint32_t image_major_version;
- /**
- * Image minor version.
- */
- uint32_t image_minor_version;
- /**
- * Image timestamp.
- */
- uint64_t image_timestamp;
+ sigverify_rsa_buffer_t modulus;
/**
* Exponent of the signer's RSA public key.
*/
uint32_t exponent;
/**
+ * Manifest identifier.
+ */
+ uint32_t identifier;
+ /**
+ * Length of the image including the manifest in bytes.
+ *
+ * Note that the length includes the signature but the signature is excluded
+ * from the signed region.
+ */
+ uint32_t length;
+ /**
+ * Image major version.
+ */
+ uint32_t version_major;
+ /**
+ * Image minor version.
+ */
+ uint32_t version_minor;
+ /**
+ * Security version of the image used for anti-rollback protection.
+ */
+ uint32_t security_version;
+ /**
+ * Image timestamp.
+ *
+ * Unix timestamp that gives the creation time of the image, seconds since
+ * 00:00:00 on January 1, 1970 UTC (the Unix Epoch).
+ */
+ uint64_t timestamp;
+ /**
* Binding value used by key manager to derive secret values.
*
* A change in this value changes the secret value of key manager, and
@@ -81,10 +97,6 @@
*/
uint32_t max_key_version;
/**
- * Modulus of the signer's RSA public key.
- */
- sigverify_rsa_buffer_t modulus;
- /**
* Offset of the start of the executable region of the image from the start
* of the manifest in bytes.
*/
@@ -99,26 +111,22 @@
* the manifest in bytes.
*/
uint32_t entry_point;
- /**
- * Trailing padding (due to image_timestamp and the size of the struct).
- */
- uint32_t padding;
} manifest_t;
-OT_ASSERT_MEMBER_OFFSET(manifest_t, identifier, 0);
-OT_ASSERT_MEMBER_OFFSET(manifest_t, signature, 4);
-OT_ASSERT_MEMBER_OFFSET(manifest_t, image_length, 388);
-OT_ASSERT_MEMBER_OFFSET(manifest_t, image_major_version, 392);
-OT_ASSERT_MEMBER_OFFSET(manifest_t, image_minor_version, 396);
-OT_ASSERT_MEMBER_OFFSET(manifest_t, image_timestamp, 400);
-OT_ASSERT_MEMBER_OFFSET(manifest_t, exponent, 408);
-OT_ASSERT_MEMBER_OFFSET(manifest_t, binding_value, 412);
-OT_ASSERT_MEMBER_OFFSET(manifest_t, max_key_version, 444);
-OT_ASSERT_MEMBER_OFFSET(manifest_t, modulus, 448);
-OT_ASSERT_MEMBER_OFFSET(manifest_t, code_start, 832);
-OT_ASSERT_MEMBER_OFFSET(manifest_t, code_end, 836);
-OT_ASSERT_MEMBER_OFFSET(manifest_t, entry_point, 840);
-OT_ASSERT_MEMBER_OFFSET(manifest_t, padding, 844);
+OT_ASSERT_MEMBER_OFFSET(manifest_t, signature, 0);
+OT_ASSERT_MEMBER_OFFSET(manifest_t, modulus, 384);
+OT_ASSERT_MEMBER_OFFSET(manifest_t, exponent, 768);
+OT_ASSERT_MEMBER_OFFSET(manifest_t, identifier, 772);
+OT_ASSERT_MEMBER_OFFSET(manifest_t, length, 776);
+OT_ASSERT_MEMBER_OFFSET(manifest_t, version_major, 780);
+OT_ASSERT_MEMBER_OFFSET(manifest_t, version_minor, 784);
+OT_ASSERT_MEMBER_OFFSET(manifest_t, security_version, 788);
+OT_ASSERT_MEMBER_OFFSET(manifest_t, timestamp, 792);
+OT_ASSERT_MEMBER_OFFSET(manifest_t, binding_value, 800);
+OT_ASSERT_MEMBER_OFFSET(manifest_t, max_key_version, 832);
+OT_ASSERT_MEMBER_OFFSET(manifest_t, code_start, 836);
+OT_ASSERT_MEMBER_OFFSET(manifest_t, code_end, 840);
+OT_ASSERT_MEMBER_OFFSET(manifest_t, entry_point, 844);
OT_ASSERT_SIZE(manifest_t, MANIFEST_SIZE);
/**
@@ -136,12 +144,12 @@
} manifest_signed_region_t;
/**
- * Allowed bounds for the `image_length` field.
+ * Allowed bounds for the `length` field.
*/
enum {
// FIXME: Update min value after we have a fairly representative ROM_EXT.
- kManifestImageLengthMin = sizeof(manifest_t),
- kManifestImageLengthMax = 64 * 1024,
+ kManifestLengthMin = sizeof(manifest_t),
+ kManifestLengthMax = 64 * 1024,
};
/**
@@ -156,13 +164,13 @@
*/
inline rom_error_t manifest_signed_region_get(
const manifest_t *manifest, manifest_signed_region_t *signed_region) {
- if (manifest->image_length < kManifestImageLengthMin ||
- manifest->image_length > kManifestImageLengthMax) {
+ if (manifest->length < kManifestLengthMin ||
+ manifest->length > kManifestLengthMax) {
return kErrorManifestBadLength;
}
*signed_region = (manifest_signed_region_t){
- .start = &manifest->image_length,
- .length = manifest->image_length - offsetof(manifest_t, image_length),
+ .start = (const char *)manifest + sizeof(manifest->signature),
+ .length = manifest->length - sizeof(manifest->signature),
};
return kErrorOk;
}
@@ -181,7 +189,7 @@
epmp_region_t *code_region) {
if (manifest->code_start >= manifest->code_end ||
manifest->code_start < sizeof(manifest_t) ||
- manifest->code_end > manifest->image_length ||
+ manifest->code_end > manifest->length ||
// FIXME: Replace this when we have a function/macro for alignment checks.
(manifest->code_start & 0x3) != 0 || (manifest->code_end & 0x3) != 0) {
return kErrorManifestBadCodeRegion;
@@ -212,7 +220,7 @@
uintptr_t *entry_point) {
if (manifest->entry_point < manifest->code_start ||
manifest->entry_point >= manifest->code_end ||
- manifest->entry_point >= manifest->image_length ||
+ manifest->entry_point >= manifest->length ||
// FIXME: Replace this when we have a function/macro for alignment checks.
(manifest->entry_point & 0x3) != 0) {
return kErrorManifestBadEntryPoint;
diff --git a/sw/device/silicon_creator/lib/manifest_unittest.cc b/sw/device/silicon_creator/lib/manifest_unittest.cc
index 0901ad3..9093415 100644
--- a/sw/device/silicon_creator/lib/manifest_unittest.cc
+++ b/sw/device/silicon_creator/lib/manifest_unittest.cc
@@ -12,13 +12,13 @@
TEST(Manifest, SignedRegionGet) {
manifest_t manifest{};
- manifest.image_length = 4096;
+ manifest.length = 4096;
manifest_signed_region_t signed_region;
EXPECT_EQ(manifest_signed_region_get(&manifest, &signed_region), kErrorOk);
- // Signed region starts at `image_length` and ends at the end of the image.
- EXPECT_EQ(&manifest.image_length, signed_region.start);
- EXPECT_EQ(manifest.image_length - offsetof(manifest_t, image_length),
+ // Signed region starts at `modulus` and ends at the end of the image.
+ EXPECT_EQ(&manifest.modulus, signed_region.start);
+ EXPECT_EQ(manifest.length - offsetof(manifest_t, modulus),
signed_region.length);
}
@@ -26,18 +26,18 @@
manifest_t manifest{};
manifest_signed_region_t signed_region;
- manifest.image_length = kManifestImageLengthMax + 1;
+ manifest.length = kManifestLengthMax + 1;
EXPECT_EQ(manifest_signed_region_get(&manifest, &signed_region),
kErrorManifestBadLength);
- manifest.image_length = kManifestImageLengthMin - 1;
+ manifest.length = kManifestLengthMin - 1;
EXPECT_EQ(manifest_signed_region_get(&manifest, &signed_region),
kErrorManifestBadLength);
}
TEST(Manifest, CodeRegionGet) {
manifest_t manifest{};
- manifest.image_length = 0x1000;
+ manifest.length = 0x1000;
manifest.code_start = 0x400;
manifest.code_end = 0x800;
epmp_region_t code_region;
@@ -57,7 +57,7 @@
kErrorManifestBadCodeRegion);
// Code region must be inside the image.
manifest.code_start = 0x400;
- manifest.code_end = manifest.image_length + 1;
+ manifest.code_end = manifest.length + 1;
EXPECT_EQ(manifest_code_region_get(&manifest, &code_region),
kErrorManifestBadCodeRegion);
// Start and end offsets must be word aligned.
@@ -73,7 +73,7 @@
TEST(Manifest, EntryPointGet) {
manifest_t manifest{};
- manifest.image_length = 0x1000;
+ manifest.length = 0x1000;
manifest.code_start = 0x400;
manifest.entry_point = 0x500;
manifest.code_end = 0x800;
@@ -91,7 +91,7 @@
EXPECT_EQ(manifest_entry_point_get(&manifest, &entry_point),
kErrorManifestBadEntryPoint);
// entry_point must be before the end of the image.
- manifest.entry_point = manifest.image_length;
+ manifest.entry_point = manifest.length;
EXPECT_EQ(manifest_entry_point_get(&manifest, &entry_point),
kErrorManifestBadEntryPoint);
// entry_point must be word aligned.
diff --git a/sw/host/rom_ext_image_tools/signer/image/src/image.rs b/sw/host/rom_ext_image_tools/signer/image/src/image.rs
index e55e9ee..a30e2fc 100644
--- a/sw/host/rom_ext_image_tools/signer/image/src/image.rs
+++ b/sw/host/rom_ext_image_tools/signer/image/src/image.rs
@@ -10,7 +10,6 @@
use std::ops::Deref;
use std::ops::DerefMut;
-use memoffset::offset_of;
use thiserror::Error;
use zerocopy::AsBytes;
use zerocopy::LayoutVerified;
@@ -46,7 +45,7 @@
}
pub fn signed_bytes(&self) -> Vec<u8> {
- self.bytes().split_off(offset_of!(Manifest, image_length))
+ self.bytes().split_off(self.manifest.signature.as_bytes().len())
}
}
diff --git a/sw/host/rom_ext_image_tools/signer/image/src/manifest.rs b/sw/host/rom_ext_image_tools/signer/image/src/manifest.rs
index 539ec92..a5539a2 100644
--- a/sw/host/rom_ext_image_tools/signer/image/src/manifest.rs
+++ b/sw/host/rom_ext_image_tools/signer/image/src/manifest.rs
@@ -32,20 +32,20 @@
#[repr(C)]
#[derive(FromBytes, AsBytes, Debug, Default)]
pub struct Manifest {
- pub identifier: u32,
pub signature: SigverifyRsaBuffer,
- pub image_length: u32,
- pub image_major_version: u32,
- pub image_minor_version: u32,
- pub image_timestamp: u64,
+ pub modulus: SigverifyRsaBuffer,
pub exponent: u32,
+ pub identifier: u32,
+ pub length: u32,
+ pub version_major: u32,
+ pub version_minor: u32,
+ pub security_version: u32,
+ pub timestamp: u64,
pub binding_value: KeymgrBindingValue,
pub max_key_version: u32,
- pub modulus: SigverifyRsaBuffer,
pub code_start: u32,
pub code_end: u32,
pub entry_point: u32,
- pub padding: u32,
}
/// A type that holds 96 32-bit words for RSA-3072.
@@ -73,19 +73,19 @@
/// requires a nightly compiler.
/// TODO(#6915): Convert this to a unit test after we start running rust tests during our builds.
pub fn check_manifest_layout() {
- assert_eq!(offset_of!(Manifest, identifier), 0);
- assert_eq!(offset_of!(Manifest, signature), 4);
- assert_eq!(offset_of!(Manifest, image_length), 388);
- assert_eq!(offset_of!(Manifest, image_major_version), 392);
- assert_eq!(offset_of!(Manifest, image_minor_version), 396);
- assert_eq!(offset_of!(Manifest, image_timestamp), 400);
- assert_eq!(offset_of!(Manifest, exponent), 408);
- assert_eq!(offset_of!(Manifest, binding_value), 412);
- assert_eq!(offset_of!(Manifest, max_key_version), 444);
- assert_eq!(offset_of!(Manifest, modulus), 448);
- assert_eq!(offset_of!(Manifest, code_start), 832);
- assert_eq!(offset_of!(Manifest, code_end), 836);
- assert_eq!(offset_of!(Manifest, entry_point), 840);
- assert_eq!(offset_of!(Manifest, padding), 844);
+ assert_eq!(offset_of!(Manifest, signature), 0);
+ assert_eq!(offset_of!(Manifest, modulus), 384);
+ assert_eq!(offset_of!(Manifest, exponent), 768);
+ assert_eq!(offset_of!(Manifest, identifier), 772);
+ assert_eq!(offset_of!(Manifest, length), 776);
+ assert_eq!(offset_of!(Manifest, version_major), 780);
+ assert_eq!(offset_of!(Manifest, version_minor), 784);
+ assert_eq!(offset_of!(Manifest, security_version), 788);
+ assert_eq!(offset_of!(Manifest, timestamp), 792);
+ assert_eq!(offset_of!(Manifest, binding_value), 800);
+ assert_eq!(offset_of!(Manifest, max_key_version), 832);
+ assert_eq!(offset_of!(Manifest, code_start), 836);
+ assert_eq!(offset_of!(Manifest, code_end), 840);
+ assert_eq!(offset_of!(Manifest, entry_point), 844);
assert_eq!(size_of::<Manifest>(), MANIFEST_SIZE as usize);
}
diff --git a/sw/host/rom_ext_image_tools/signer/src/main.rs b/sw/host/rom_ext_image_tools/signer/src/main.rs
index f5d49c7..d574606 100644
--- a/sw/host/rom_ext_image_tools/signer/src/main.rs
+++ b/sw/host/rom_ext_image_tools/signer/src/main.rs
@@ -95,11 +95,7 @@
*image.manifest = Manifest {
identifier: 0x4552544f,
- image_length: u32::try_from(image.bytes().len())?,
- entry_point: {
- let addr = u32::try_from(elf.entry())?;
- addr.checked_sub(manifest_addr).context("Overflow")?
- },
+ length: u32::try_from(image.bytes().len())?,
code_start: {
let addr = u32::try_from(
elf.section_by_name(".vectors")
@@ -119,6 +115,10 @@
)?;
addr.checked_sub(manifest_addr).context("Overflow")?
},
+ entry_point: {
+ let addr = u32::try_from(elf.entry())?;
+ addr.checked_sub(manifest_addr).context("Overflow")?
+ },
..Default::default()
};