[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()
     };