Repository: chipsalliance/caliptra-sw
Pull request #512 (2023-07-19 00:16:32)

sw-emulator: clear `PCR_HASH_EXTEND` after copying results to PCR bank.
This prevents subsequent hash operations from also copying results to the bank.


Patch:
diff --git a/Cargo.lock b/Cargo.lock
index 96e931ca..fb995aef 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -354,6 +354,7 @@ dependencies = [
 name = "caliptra-hw-model-test-fw"
 version = "0.1.0"
 dependencies = [
+ "caliptra-drivers",
  "caliptra-registers",
  "caliptra-test-harness",
 ]
diff --git a/sw-emulator/lib/periph/src/hash_sha512.rs b/sw-emulator/lib/periph/src/hash_sha512.rs
index 7318482a..f5f47ee9 100644
--- a/sw-emulator/lib/periph/src/hash_sha512.rs
+++ b/sw-emulator/lib/periph/src/hash_sha512.rs
@@ -449,6 +449,10 @@ impl HashSha512 {
             self.key_vault
                 .write_pcr(pcr_id, array_ref![self.hash.data(), 0, KeyVault::KEY_SIZE])
                 .unwrap();
+
+            self.block_read_ctrl
+                .reg
+                .modify(BlockReadControl::PCR_HASH_EXTEND::CLEAR);
         }
 
         // Update Ready and Valid status bits


Test patch:
diff --git a/hw-model/test-fw/Cargo.toml b/hw-model/test-fw/Cargo.toml
index 67be0e4e..ca7f2bfd 100644
--- a/hw-model/test-fw/Cargo.toml
+++ b/hw-model/test-fw/Cargo.toml
@@ -13,6 +13,7 @@ emu = ["caliptra-test-harness/emu"]
 [dependencies]
 caliptra-test-harness = { path = "../../test-harness" }
 caliptra-registers = { path = "../../registers" }
+caliptra-drivers = { path = "../../drivers" }
 
 [[bin]]
 name = "test_iccm_unaligned_write"
@@ -61,3 +62,7 @@ name = "test_dccm_double_bit_ecc"
 path = "test_dccm_double_bit_ecc.rs"
 required-features = ["riscv"]
 
+[[bin]]
+name = "test_pcr_extend"
+path = "test_pcr_extend.rs"
+required-features = ["riscv"]
diff --git a/hw-model/test-fw/test_pcr_extend.rs b/hw-model/test-fw/test_pcr_extend.rs
new file mode 100644
index 00000000..fe8c48b8
--- /dev/null
+++ b/hw-model/test-fw/test_pcr_extend.rs
@@ -0,0 +1,53 @@
+// Licensed under the Apache-2.0 license
+
+//! A very simple program that extends to a PCR and then computes a hash.
+
+#![no_main]
+#![no_std]
+
+use caliptra_drivers::{Array4x12, PcrBank, PcrId, Sha384};
+use caliptra_registers::{pv::PvReg, sha512::Sha512Reg};
+#[allow(unused)]
+use caliptra_test_harness::println;
+
+#[panic_handler]
+pub fn panic(_info: &core::panic::PanicInfo) -> ! {
+    caliptra_drivers::ExitCtrl::exit(1)
+}
+
+#[no_mangle]
+extern "C" fn main() {
+    let mut sha384 = unsafe { Sha384::new(Sha512Reg::new()) };
+    let pcr_bank = unsafe { PcrBank::new(PvReg::new()) };
+
+    pcr_bank
+        .extend_pcr(PcrId::PcrId1, &mut sha384, &[0_u8; 4])
+        .unwrap();
+
+    let pcr1 = pcr_bank.read_pcr(PcrId::PcrId1);
+
+    let expected_pcr1 = [
+        0x1a, 0xe0, 0x93, 0xc2, 0xc1, 0x3b, 0xbe, 0xea, 0x8a, 0xbe, 0x39, 0xe0, 0xfc, 0x3a, 0x03,
+        0x40, 0xbd, 0xaf, 0x0a, 0x0b, 0x55, 0xf0, 0x93, 0x61, 0x66, 0xfd, 0x32, 0x5b, 0x2d, 0x4c,
+        0xbf, 0x7a, 0x95, 0x25, 0xf9, 0x3a, 0x92, 0x60, 0x38, 0xf7, 0x0a, 0x1a, 0xc5, 0x7d, 0x32,
+        0x86, 0xff, 0xab,
+    ];
+
+    assert_eq!(pcr1, Array4x12::from(expected_pcr1));
+
+    let digest = sha384.digest(&expected_pcr1).unwrap();
+
+    let expected_digest = [
+        0x5f, 0xeb, 0xea, 0xe8, 0x58, 0x75, 0x73, 0x40, 0x29, 0x58, 0xa9, 0x24, 0xba, 0x75, 0xc7,
+        0x50, 0x39, 0x73, 0xee, 0x94, 0x76, 0xfb, 0xac, 0xb5, 0xba, 0xfe, 0x69, 0x53, 0xbf, 0xde,
+        0x06, 0xa2, 0xdf, 0x89, 0x5e, 0xff, 0xd8, 0x13, 0xc5, 0x38, 0x9a, 0x4b, 0xed, 0x4b, 0x37,
+        0x11, 0x03, 0xc1,
+    ];
+
+    assert_eq!(digest, Array4x12::from(expected_digest));
+
+    // Assert PCR1 is still the expected value.
+    let pcr1 = pcr_bank.read_pcr(PcrId::PcrId1);
+
+    assert_eq!(pcr1, Array4x12::from(expected_pcr1));
+}
diff --git a/hw-model/tests/model_tests.rs b/hw-model/tests/model_tests.rs
index 4a32c4ac..69351295 100644
--- a/hw-model/tests/model_tests.rs
+++ b/hw-model/tests/model_tests.rs
@@ -180,3 +180,16 @@ fn test_dccm_double_bit_ecc_nmi_failure() {
     let ext_info = harness::ExtErrorInfo::from(soc_ifc.cptra_fw_extended_error_info().read());
     assert_eq!(ext_info.mcause, harness::EXCEPTION_CAUSE_LOAD_ACCESS_FAULT);
 }
+
+#[test]
+fn test_pcr_extend() {
+    let elf = caliptra_builder::build_firmware_elf(&FwId {
+        bin_name: "test_pcr_extend",
+        ..BASE_FWID
+    })
+    .unwrap();
+
+    let mut model = run_fw_elf(&elf);
+
+    model.step_until_exit_success().unwrap();
+}