Repository: chipsalliance/caliptra-sw
Pull request #513 (2023-07-19 00:40:41)

[fix] Update RT SVN fuse to 128-bits


Patch:
diff --git a/drivers/src/fuse_bank.rs b/drivers/src/fuse_bank.rs
index e3a9983d..cbdf699e 100644
--- a/drivers/src/fuse_bank.rs
+++ b/drivers/src/fuse_bank.rs
@@ -14,11 +14,17 @@ Abstract:
 
 use crate::Array4x12;
 use caliptra_registers::soc_ifc::SocIfcReg;
+use zerocopy::AsBytes;
 
 pub struct FuseBank<'a> {
     pub(crate) soc_ifc: &'a SocIfcReg,
 }
 
+fn first_set_msbit(num_le: &[u32; 4]) -> u32 {
+    let fuse: u128 = u128::from_le_bytes(num_le.as_bytes().try_into().unwrap());
+    128 - fuse.leading_zeros()
+}
+
 pub enum X509KeyIdAlgo {
     Sha1 = 0,
     Sha256 = 1,
@@ -248,9 +254,7 @@ impl FuseBank<'_> {
     ///
     pub fn runtime_fuse_svn(&self) -> u32 {
         let soc_ifc_regs = self.soc_ifc.regs();
-        64 - ((soc_ifc_regs.fuse_runtime_svn().at(1).read() as u64) << 32
-            | soc_ifc_regs.fuse_runtime_svn().at(0).read() as u64)
-            .leading_zeros()
+        first_set_msbit(&soc_ifc_regs.fuse_runtime_svn().read())
     }
 
     /// Get the lms revocation bits.
@@ -285,3 +289,24 @@ impl FuseBank<'_> {
         }
     }
 }
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_first_set_msbit() {
+        let mut svn: u128 = 0;
+        let mut svn_arr: [u32; 4] = [0u32, 0u32, 0u32, 0u32];
+
+        for i in 0..128 {
+            for (idx, word) in svn_arr.iter_mut().enumerate() {
+                *word = u32::from_le_bytes(svn.as_bytes()[idx * 4..][..4].try_into().unwrap())
+            }
+            let result = first_set_msbit(&svn_arr);
+            assert_eq!(result, i);
+
+            svn = (svn << 1) | 1;
+        }
+    }
+}
diff --git a/image/verify/src/lib.rs b/image/verify/src/lib.rs
index ce8876ec..002d619f 100644
--- a/image/verify/src/lib.rs
+++ b/image/verify/src/lib.rs
@@ -21,6 +21,8 @@ use core::ops::Range;
 
 pub use verifier::ImageVerifier;
 
+pub const MAX_RUNTIME_SVN: u32 = 128;
+
 /// Image Verifification Executable Info
 #[derive(Default, Debug)]
 pub struct ImageSvnLogInfo {
diff --git a/image/verify/src/verifier.rs b/image/verify/src/verifier.rs
index e4906b98..ac510eb5 100644
--- a/image/verify/src/verifier.rs
+++ b/image/verify/src/verifier.rs
@@ -8,7 +8,7 @@ File Name:
 
 Abstract:
 
-    This file is the main implementaiton of Caliptra Image Verifier.
+    This file is the main implementation of Caliptra Image Verifier.
 
 --*/
 
@@ -675,7 +675,7 @@ impl<Env: ImageVerificationEnv> ImageVerifier<Env> {
         }
 
         if self.svn_check_required() {
-            if verify_info.svn > 64 {
+            if verify_info.svn > MAX_RUNTIME_SVN {
                 Err(CaliptraError::IMAGE_VERIFIER_ERR_RUNTIME_SVN_GREATER_THAN_MAX_SUPPORTED)?;
             }
 
diff --git a/rom/dev/README.md b/rom/dev/README.md
index 8955bb66..0a9f8fc3 100644
--- a/rom/dev/README.md
+++ b/rom/dev/README.md
@@ -101,7 +101,7 @@ Following are the main FUSE & Architectural Registers used by the Caliptra ROM f
 | FUSE_MANUFACTURER_PK_REVOCATION | 4            | Manufacturer Public Key Revocation Mask                 |
 | FUSE_OWNER_PK_HASH              | 384          | Owner Public Key Hash                                   |
 | FUSE_FMC_SVN                    | 32           | FMC Security Version Number                             |
-| FUSE_RUNTIME_SVN                | 64           | Runtime Security Version Number <br> *NOTE: Hardware reserves 128 fuse bits for this pupose. However, only 64 bits are supported by ROM at this time.* |
+| FUSE_RUNTIME_SVN                | 64           | Runtime Security Version Number                         |
 | FUSE_ANTI_ROLLBACK_DISABLE      | 1            | Disable SVN checking for FMC & Runtime when bit is set  |
 | FUSE_IDEVID_CERT_ATTR           | 768          | FUSE containing information for generating IDEVID CSR   |
 | CPTRA_DBG_MANUF_SERVICE_REG     | 32           | Manufacturing Services like IDEVID CSR upload           |


Test patch:
diff --git a/rom/dev/doc/test-coverage/test-coverage.md b/rom/dev/doc/test-coverage/test-coverage.md
index 469c1066..17f7ae6d 100644
--- a/rom/dev/doc/test-coverage/test-coverage.md
+++ b/rom/dev/doc/test-coverage/test-coverage.md
@@ -57,7 +57,7 @@ IMAGE_VERIFIER_ERR_VENDOR_LMS_PUBKEY_INDEX_OUT_OF_BOUNDS
 **test_runtime_invalid_entry_point_before_iccm** | Image Verification - RT | Checks if RT entry point is within ICCM range  | IMAGE_VERIFIER_ERR_RUNTIME_ENTRY_POINT_INVALID
 **test_runtime_invalid_entry_point_after_iccm** | Image Verification - RT | Checks if RT entry point is within ICCM range  | IMAGE_VERIFIER_ERR_RUNTIME_ENTRY_POINT_INVALID
 **test_runtime_entry_point_unaligned** | Image Verification - RT | Checks if RT entry point is DWORD aligned | IMAGE_VERIFIER_ERR_RUNTIME_ENTRY_POINT_UNALIGNED
-**test_runtime_svn_greater_than_64** | Image Verification - RT | Checks if RT SVN is greater than max (64) | IMAGE_VERIFIER_ERR_RUNTIME_SVN_GREATER_THAN_MAX_SUPPORTED
+**test_runtime_svn_greater_than_max** | Image Verification - RT | Checks if RT SVN is greater than max (128) | IMAGE_VERIFIER_ERR_RUNTIME_SVN_GREATER_THAN_MAX_SUPPORTED
 **test_runtime_svn_less_than_min_svn** | Image Verification - RT | Checks if RT SVN is less than toc_rt.min_svn | IMAGE_VERIFIER_ERR_RUNTIME_SVN_LESS_THAN_MIN_SUPPORTED
 **test_runtime_svn_less_than_fuse_svn** | Image Verification - RT | Checks if RT SVN is less than fuse svn | IMAGE_VERIFIER_ERR_RUNTIME_SVN_LESS_THAN_FUSE
 **cert_test** | DICE Cert | <Placeholder> | N/A
diff --git a/rom/dev/tests/test_image_validation.rs b/rom/dev/tests/test_image_validation.rs
index fbf26897..79aa395c 100644
--- a/rom/dev/tests/test_image_validation.rs
+++ b/rom/dev/tests/test_image_validation.rs
@@ -1521,7 +1521,7 @@ fn test_runtime_entry_point_unaligned() {
 }
 
 #[test]
-fn test_runtime_svn_greater_than_64() {
+fn test_runtime_svn_greater_than_max() {
     let gen = ImageGenerator::new(OsslCrypto::default());
     let (_hw, image_bundle) =
         helpers::build_hw_model_and_image_bundle(Fuses::default(), ImageOptions::default());
@@ -1536,7 +1536,7 @@ fn test_runtime_svn_greater_than_64() {
         ..Default::default()
     };
     let image_options = ImageOptions {
-        app_svn: 65,
+        app_svn: caliptra_image_verify::MAX_RUNTIME_SVN + 1,
         ..Default::default()
     };