Repository: chipsalliance/caliptra-sw
Pull request #13 (2023-03-05 08:36:57)

[feat] Implement PCR hash extend
This change implements the PCR hash extension functionality in the emulator.
The change also contains updates to the firmware API to utilize the PCR hash extend functionality.


Patch:
diff --git a/drivers/src/kv_access.rs b/drivers/src/kv_access.rs
index 2350a934..ff20b1eb 100644
--- a/drivers/src/kv_access.rs
+++ b/drivers/src/kv_access.rs
@@ -14,7 +14,7 @@ Abstract:
 --*/
 
 use crate::array::Array4xN;
-use crate::{wait, CaliptraResult, KeyId, KeyUsage};
+use crate::{wait, CaliptraResult, KeyId, KeyUsage, PcrId};
 use caliptra_registers::enums::KvErrorE;
 use caliptra_registers::regs::{KvReadCtrlRegWriteVal, KvStatusRegReadVal, KvWriteCtrlRegWriteVal};
 use ureg::Mmio;
@@ -106,7 +106,7 @@ impl KvAccess {
     /// # Arguments
     ///
     /// * `reg` - Source register to copy from
-    /// * `arr` - Destination arry to copy the contents of reguster to
+    /// * `arr` - Destination array to copy the contents of register to
     pub(crate) fn end_copy_to_arr<
         const ARR_WORD_LEN: usize,
         const ARR_BYTE_LEN: usize,
@@ -224,4 +224,38 @@ impl KvAccess {
             _ => Err(KvAccessErr::Generic),
         }
     }
+
+    /// Hash extends the contents from pcr slot in pcr vault
+    ///
+    /// # Arguments
+    ///
+    /// * `pcr_id` - Pcr slot to hash extend
+    /// * `status_reg` - Status register
+    /// * `ctrl_reg` - Control register
+    pub(crate) fn extend_from_pv<
+        StatusReg: ureg::ReadableReg<ReadVal = KvStatusRegReadVal>,
+        CtrlReg: ureg::ResettableReg + ureg::WritableReg<WriteVal = KvReadCtrlRegWriteVal>,
+        TMmio: Mmio,
+    >(
+        pcr_id: PcrId,
+        status_reg: ureg::RegRef<StatusReg, TMmio>,
+        ctrl_reg: ureg::RegRef<CtrlReg, TMmio>,
+    ) -> Result<(), KvAccessErr> {
+        crate::wait::until(|| status_reg.read().ready());
+
+        ctrl_reg.write(|w| {
+            w.read_en(true)
+                .read_entry(pcr_id.into())
+                .pcr_hash_extend(true)
+        });
+
+        crate::wait::until(|| status_reg.read().valid());
+
+        match status_reg.read().error() {
+            KvErrorE::Success => Ok(()),
+            KvErrorE::KvReadFail => Err(KvAccessErr::KeyRead),
+            KvErrorE::KvWriteFail => Err(KvAccessErr::KeyWrite),
+            _ => Err(KvAccessErr::Generic),
+        }
+    }
 }
diff --git a/drivers/src/lib.rs b/drivers/src/lib.rs
index fd7d4238..f02ffe31 100644
--- a/drivers/src/lib.rs
+++ b/drivers/src/lib.rs
@@ -60,7 +60,7 @@ pub use pcr_bank::{PcrBank, PcrId};
 pub use reset::{ResetReason, ResetService};
 pub use sha1::{Sha1, Sha1Digest, Sha1DigestOp};
 pub use sha256::{Sha256, Sha256DigestOp};
-pub use sha384::{Sha384, Sha384Data, Sha384Digest, Sha384DigestOp};
+pub use sha384::{PcrHashExtendArgs, Sha384, Sha384Data, Sha384Digest, Sha384DigestOp};
 pub use sha384acc::{Sha384Acc, Sha384AccOp};
 pub use state::{DeviceState, Lifecycle};
 pub use status_reporter::{report_boot_status, report_flow_status};
diff --git a/drivers/src/sha384.rs b/drivers/src/sha384.rs
index 20048cf0..d75e7c0e 100644
--- a/drivers/src/sha384.rs
+++ b/drivers/src/sha384.rs
@@ -15,14 +15,14 @@ Abstract:
 use core::usize;
 
 use crate::kv_access::{KvAccess, KvAccessErr};
-use crate::{
-    array::Array4x32, caliptra_err_def, wait, Array4x12, CaliptraResult, KeyReadArgs, KeyWriteArgs,
-};
+use crate::PcrId;
+use crate::{array::Array4x32, caliptra_err_def, wait, Array4x12, CaliptraResult};
 use caliptra_registers::sha512;
 
 const SHA384_BLOCK_BYTE_SIZE: usize = 128;
 const SHA384_BLOCK_LEN_OFFSET: usize = 112;
 const SHA384_MAX_DATA_SIZE: usize = 1024 * 1024;
+const SHA384_HASH_SIZE: usize = 48;
 
 caliptra_err_def! {
     Sha384,
@@ -33,11 +33,6 @@ caliptra_err_def! {
         ReadDataKvWrite = 0x02,
         ReadDataKvUnknown = 0x3,
 
-        // Errors encountered while writing digest to key vault
-        WriteDigestKvRead = 0x04,
-        WriteDigestKvWrite = 0x05,
-        WriteDigestKvUnknown = 0x06,
-
         // Invalid State
         InvalidStateErr = 0x07,
 
@@ -61,8 +56,8 @@ pub enum Sha384Data<'a> {
     /// Array
     Slice(&'a [u8]),
 
-    /// Key
-    Key(KeyReadArgs),
+    /// PCR hash extend arguments
+    PcrHashExtend(PcrHashExtendArgs<'a>),
 }
 
 impl<'a> From<&'a [u8]> for Sha384Data<'a> {
@@ -79,10 +74,38 @@ impl<'a, const N: usize> From<&'a [u8; N]> for Sha384Data<'a> {
     }
 }
 
-impl From<KeyReadArgs> for Sha384Data<'_> {
+impl<'a> From<PcrHashExtendArgs<'a>> for Sha384Data<'a> {
     /// Converts to this type from the input type.
-    fn from(value: KeyReadArgs) -> Self {
-        Self::Key(value)
+    fn from(value: PcrHashExtendArgs<'a>) -> Self {
+        Self::PcrHashExtend(value)
+    }
+}
+
+/// Key read operation arguments
+#[derive(Debug, Clone, Copy)]
+pub struct PcrHashExtendArgs<'a> {
+    /// Array
+    pub slice: &'a [u8],
+
+    /// PCR hash extend
+    pub hash_extend: bool,
+
+    /// Pcr Id
+    pub id: PcrId,
+}
+
+impl<'a> PcrHashExtendArgs<'a> {
+    /// Create an instance of `KeyReadArgs`
+    ///
+    /// # Arguments
+    ///
+    /// * `id` - Key Id
+    pub fn new(slice: &'a [u8], hash_extend: bool, id: PcrId) -> Self {
+        Self {
+            slice,
+            hash_extend,
+            id,
+        }
     }
 }
 
@@ -91,9 +114,6 @@ impl From<KeyReadArgs> for Sha384Data<'_> {
 pub enum Sha384Digest<'a> {
     /// Array
     Array4x12(&'a mut Array4x12),
-
-    /// Key
-    Key(KeyWriteArgs),
 }
 
 impl<'a> From<&'a mut Array4x12> for Sha384Digest<'a> {
@@ -103,13 +123,6 @@ impl<'a> From<&'a mut Array4x12> for Sha384Digest<'a> {
     }
 }
 
-impl<'a> From<KeyWriteArgs> for Sha384Digest<'a> {
-    /// Converts to this type from the input type.
-    fn from(value: KeyWriteArgs) -> Self {
-        Self::Key(value)
-    }
-}
-
 #[derive(Default, Debug)]
 pub struct Sha384 {}
 
@@ -130,9 +143,6 @@ impl Sha384 {
             Sha384Digest::Array4x12(arr) => {
                 KvAccess::begin_copy_to_arr(sha.kv_wr_status(), sha.kv_wr_ctrl(), arr)?
             }
-            Sha384Digest::Key(key) => {
-                KvAccess::begin_copy_to_kv(sha.kv_wr_status(), sha.kv_wr_ctrl(), *key)?
-            }
         }
 
         let op = Sha384DigestOp {
@@ -161,15 +171,19 @@ impl Sha384 {
             Sha384Digest::Array4x12(arr) => {
                 KvAccess::begin_copy_to_arr(sha.kv_wr_status(), sha.kv_wr_ctrl(), arr)?
             }
-            Sha384Digest::Key(key) => {
-                KvAccess::begin_copy_to_kv(sha.kv_wr_status(), sha.kv_wr_ctrl(), *key)?
-            }
         }
 
-        // Calculate the digest
         match data {
-            Sha384Data::Slice(slice) => self.digest_buf(slice)?,
-            Sha384Data::Key(key) => self.digest_key(key)?,
+            Sha384Data::Slice(slice) => {
+                // Calculate the digest
+                self.digest_buf(slice, 0)?;
+            }
+            Sha384Data::PcrHashExtend(hash_extend) => {
+                self.retrieve_pcr(hash_extend.id)?;
+
+                // Calculate the digest
+                self.digest_buf(hash_extend.slice, SHA384_HASH_SIZE)?;
+            }
         }
 
         // Copy the digest to specified destination
@@ -177,8 +191,6 @@ impl Sha384 {
             Sha384Digest::Array4x12(arr) => {
                 KvAccess::end_copy_to_arr(sha.digest().truncate::<12>(), *arr)
             }
-            Sha384Digest::Key(key) => KvAccess::end_copy_to_kv(sha.kv_wr_status(), *key)
-                .map_err(|err| err.into_write_digest_err().into()),
         }
     }
 
@@ -187,24 +199,42 @@ impl Sha384 {
     /// # Arguments
     ///
     /// * `buf` - Buffer to calculate the digest over
-    fn digest_buf(&self, buf: &[u8]) -> CaliptraResult<()> {
+    /// * `pcr_hash_extend` - Indicates if pcr is to be hash extended.
+    fn digest_buf(&self, buf: &[u8], prepad_byte_count_in: usize) -> CaliptraResult<()> {
+        let mut prepad_byte_count = prepad_byte_count_in;
+        let total_bytes = prepad_byte_count_in + buf.len();
+
         // Check if the buffer is not large
-        if buf.len() > SHA384_MAX_DATA_SIZE {
+        if total_bytes > SHA384_MAX_DATA_SIZE {
             raise_err!(MaxDataErr)
         }
 
         let mut first = true;
-        let mut bytes_remaining = buf.len();
+        let mut bytes_remaining = total_bytes;
+        let mut block = [0u8; SHA384_BLOCK_BYTE_SIZE];
 
         loop {
-            let offset = buf.len() - bytes_remaining;
+            let offset = (buf.len() + prepad_byte_count) - bytes_remaining;
             match bytes_remaining {
                 0..=127 => {
-                    // PANIC-FREE: Use buf.get() instead if buf[] as the compiler
+                    // PANIC-FREE: Use buf.get() instead of buf[] as the compiler
                     // cannot reason about `offset` parameter to optimize out
                     // the panic.
-                    if let Some(slice) = buf.get(offset..) {
-                        self.digest_partial_block(slice, first, buf.len())?;
+                    if let Some(mut slice) = buf.get(offset..) {
+                        // If this is the first block, create a block with the prepad.
+                        if first && prepad_byte_count > 0 {
+                            // PANIC-FREE: Following check optimizes the out of bounds
+                            // panic in copy_from_slice
+                            if block.len() < bytes_remaining
+                                || buf.len() > (bytes_remaining - prepad_byte_count)
+                            {
+                                raise_err!(IndexOutOfBounds)
+                            }
+
+                            block[prepad_byte_count..bytes_remaining].copy_from_slice(buf);
+                            slice = block.get(..bytes_remaining).unwrap();
+                        }
+                        self.digest_partial_block(slice, first, total_bytes)?;
                         break;
                     } else {
                         raise_err!(InvalidSlice)
@@ -214,7 +244,19 @@ impl Sha384 {
                     // PANIC-FREE: Use buf.get() instead if buf[] as the compiler
                     // cannot reason about `offset` parameter to optimize out
                     // the panic call.
-                    if let Some(slice) = buf.get(offset..offset + SHA384_BLOCK_BYTE_SIZE) {
+                    if let Some(mut slice) =
+                        buf.get(offset..offset + (SHA384_BLOCK_BYTE_SIZE - prepad_byte_count))
+                    {
+                        // If this is the first block, create a block with the prepad.
+                        if first && prepad_byte_count > 0 {
+                            block[prepad_byte_count..].copy_from_slice(
+                                buf.get(..(SHA384_BLOCK_BYTE_SIZE - prepad_byte_count))
+                                    .unwrap(),
+                            );
+                            slice = &block;
+                            prepad_byte_count = 0;
+                        }
+
                         let block = <&[u8; SHA384_BLOCK_BYTE_SIZE]>::try_from(slice).unwrap();
                         self.digest_block(block, first, false)?;
                         bytes_remaining -= SHA384_BLOCK_BYTE_SIZE;
@@ -229,18 +271,19 @@ impl Sha384 {
         Ok(())
     }
 
-    /// Calculate digest of a key in the Key Vault
+    /// Waits for the PCR to be retrieved from the PCR vault
+    /// and copied to the block registers.
     ///
     /// # Arguments
     ///
-    /// * `key` - Key to calculate digest for
-    fn digest_key(&self, key: KeyReadArgs) -> CaliptraResult<()> {
+    /// * `pcr_id` - PCR to hash extend
+    fn retrieve_pcr(&self, pcr_id: PcrId) -> CaliptraResult<()> {
         let sha = sha512::RegisterBlock::sha512_reg();
 
-        KvAccess::copy_from_kv(key, sha.vault_rd_status(), sha.vault_rd_ctrl())
+        KvAccess::extend_from_pv(pcr_id, sha.vault_rd_status(), sha.vault_rd_ctrl())
             .map_err(|err| err.into_read_data_err())?;
 
-        self.digest_op(true, true)
+        Ok(())
     }
 
     /// Calculate the digest of the last block
@@ -431,8 +474,6 @@ impl<'a> Sha384DigestOp<'a> {
             Sha384Digest::Array4x12(arr) => {
                 KvAccess::end_copy_to_arr(sha.digest().truncate::<12>(), *arr)
             }
-            Sha384Digest::Key(key) => KvAccess::end_copy_to_kv(sha.kv_wr_status(), *key)
-                .map_err(|err| err.into_write_digest_err().into()),
         }
     }
 
@@ -453,9 +494,6 @@ impl<'a> Sha384DigestOp<'a> {
 trait Sha384KeyAccessErr {
     /// Convert to read data operation error
     fn into_read_data_err(self) -> Sha384Err;
-
-    /// Convert to write digest operation error
-    fn into_write_digest_err(self) -> Sha384Err;
 }
 
 impl Sha384KeyAccessErr for KvAccessErr {
@@ -467,13 +505,4 @@ impl Sha384KeyAccessErr for KvAccessErr {
             KvAccessErr::Generic => Sha384Err::ReadDataKvUnknown,
         }
     }
-
-    /// Convert to write digest operation error
-    fn into_write_digest_err(self) -> Sha384Err {
-        match self {
-            KvAccessErr::KeyRead => Sha384Err::WriteDigestKvRead,
-            KvAccessErr::KeyWrite => Sha384Err::WriteDigestKvWrite,
-            KvAccessErr::Generic => Sha384Err::WriteDigestKvUnknown,
-        }
-    }
 }
diff --git a/sw-emulator/lib/crypto/src/sha512.rs b/sw-emulator/lib/crypto/src/sha512.rs
index 4fcd717b..a48f2f4a 100644
--- a/sw-emulator/lib/crypto/src/sha512.rs
+++ b/sw-emulator/lib/crypto/src/sha512.rs
@@ -25,6 +25,13 @@ pub enum Sha512Mode {
     Sha512,
 }
 
+impl From<Sha512Mode> for u32 {
+    /// Converts to this type from the input type.
+    fn from(sha_mode: Sha512Mode) -> Self {
+        sha_mode as Self
+    }
+}
+
 /// SHA-512
 pub struct Sha512 {
     /// Hash
diff --git a/sw-emulator/lib/periph/src/asym_ecc384.rs b/sw-emulator/lib/periph/src/asym_ecc384.rs
index 6df971f9..26cb1289 100644
--- a/sw-emulator/lib/periph/src/asym_ecc384.rs
+++ b/sw-emulator/lib/periph/src/asym_ecc384.rs
@@ -98,14 +98,14 @@ register_bitfields! [
     ],
 ];
 
-fn words_from_bytes_le(arr: &[u8; 48]) -> [u32; 12] {
+pub fn words_from_bytes_le(arr: &[u8; 48]) -> [u32; 12] {
     let mut result = [0u32; 12];
     for i in 0..result.len() {
         result[i] = u32::from_le_bytes(arr[i * 4..][..4].try_into().unwrap())
     }
     result
 }
-fn bytes_from_words_le(arr: &[u32; 12]) -> [u8; 48] {
+pub fn bytes_from_words_le(arr: &[u32; 12]) -> [u8; 48] {
     let mut result = [0u8; 48];
     for i in 0..arr.len() {
         result[i * 4..][..4].copy_from_slice(&arr[i].to_le_bytes());
diff --git a/sw-emulator/lib/periph/src/hash_sha512.rs b/sw-emulator/lib/periph/src/hash_sha512.rs
index 125c5305..c11ade8e 100644
--- a/sw-emulator/lib/periph/src/hash_sha512.rs
+++ b/sw-emulator/lib/periph/src/hash_sha512.rs
@@ -12,11 +12,11 @@ Abstract:
 
 --*/
 
+use crate::asym_ecc384::words_from_bytes_le;
 use crate::key_vault::KeyUsage;
 use crate::KeyVault;
 use caliptra_emu_bus::{
-    BusError, Clock, ReadOnlyMemory, ReadOnlyRegister, ReadWriteMemory, ReadWriteRegister, Timer,
-    TimerAction,
+    BusError, Clock, ReadOnlyMemory, ReadOnlyRegister, ReadWriteRegister, Timer, TimerAction,
 };
 use caliptra_emu_crypto::EndianessTransform;
 use caliptra_emu_crypto::{Sha512, Sha512Mode};
@@ -87,6 +87,7 @@ register_bitfields! [
 ];
 
 const SHA512_BLOCK_SIZE: usize = 128;
+const SHA512_BLOCK_SIZE_WORDS: usize = 128 >> 2;
 
 const SHA512_HASH_SIZE: usize = 64;
 
@@ -99,6 +100,25 @@ const UPDATE_TICKS: u64 = 1000;
 /// The number of CPU clock cycles read and write keys from key vault
 const KEY_RW_TICKS: u64 = 100;
 
+fn sha512_block_words_from_bytes_le(
+    arr: &[u8; SHA512_BLOCK_SIZE],
+) -> [u32; SHA512_BLOCK_SIZE_WORDS] {
+    let mut result = [0u32; SHA512_BLOCK_SIZE_WORDS];
+    for i in 0..result.len() {
+        result[i] = u32::from_le_bytes(arr[i * 4..][..4].try_into().unwrap())
+    }
+    result
+}
+fn sha512_block_bytes_from_words_le(
+    arr: &[u32; SHA512_BLOCK_SIZE_WORDS],
+) -> [u8; SHA512_BLOCK_SIZE] {
+    let mut result = [0u8; SHA512_BLOCK_SIZE];
+    for i in 0..arr.len() {
+        result[i * 4..][..4].copy_from_slice(&arr[i].to_le_bytes());
+    }
+    result
+}
+
 /// SHA-512 Peripheral
 #[derive(Bus)]
 #[poll_fn(poll)]
@@ -128,8 +148,8 @@ pub struct HashSha512 {
     status: ReadOnlyRegister<u32, Status::Register>,
 
     /// SHA512 Block Memory
-    #[peripheral(offset = 0x0000_0080, mask = 0x0000_007f)]
-    block: ReadWriteMemory<SHA512_BLOCK_SIZE>,
+    #[register_array(offset = 0x0000_0080, write_fn = write_block)]
+    block: [u32; SHA512_BLOCK_SIZE_WORDS],
 
     /// SHA512 Hash Memory
     #[peripheral(offset = 0x0000_0100, mask = 0x0000_00ff)]
@@ -196,7 +216,7 @@ impl HashSha512 {
             block_read_status: ReadOnlyRegister::new(BlockReadStatus::READY::SET.value),
             hash_write_ctrl: ReadWriteRegister::new(0),
             hash_write_status: ReadOnlyRegister::new(HashWriteStatus::READY::SET.value),
-            block: ReadWriteMemory::new(),
+            block: Default::default(),
             hash: ReadOnlyMemory::new(),
             key_vault,
             timer: Timer::new(clock),
@@ -254,13 +274,15 @@ impl HashSha512 {
             self.sha512.reset(mode);
 
             // Update the SHA512 engine with a new block
-            self.sha512.update(self.block.data());
+            self.sha512
+                .update(&sha512_block_bytes_from_words_le(&self.block));
 
             // Schedule a future call to poll() complete the operation.
             self.op_complete_action = Some(self.timer.schedule_poll_in(INIT_TICKS));
         } else if self.control.reg.is_set(Control::NEXT) {
             // Update the SHA512 engine with a new block
-            self.sha512.update(self.block.data());
+            self.sha512
+                .update(&sha512_block_bytes_from_words_le(&self.block));
 
             // Schedule a future call to poll() complete the operation.
             self.op_complete_action = Some(self.timer.schedule_poll_in(UPDATE_TICKS));
@@ -269,6 +291,30 @@ impl HashSha512 {
         Ok(())
     }
 
+    /// On Write callback for `block` registers
+    ///
+    /// # Arguments
+    ///
+    /// * `size` - Size of the write
+    /// * `val` - Data to write
+    ///
+    /// # Error
+    ///
+    /// * `BusError` - Exception with cause `BusError::StoreAccessFault` or `BusError::StoreAddrMisaligned`
+    fn write_block(&mut self, _size: RvSize, word_index: usize, val: u32) -> Result<(), BusError> {
+        let pcr_hash_extend = self
+            .block_read_ctrl
+            .reg
+            .read(BlockReadControl::PCR_HASH_EXTEND);
+
+        // If PCR_HASH_EXTEND bit is set, skip updating the first 48 bytes in the block registers
+        // as these contain the PCR retrieved from the PCR vault.
+        if pcr_hash_extend == 0 || word_index >= 12 {
+            self.block[word_index] = val;
+        }
+        Ok(())
+    }
+
     /// On Write callback for `block_read_control` register
     ///
     /// # Arguments
@@ -294,7 +340,9 @@ impl HashSha512 {
 
         self.block_read_ctrl.reg.modify(
             BlockReadControl::KEY_READ_EN.val(block_read_ctrl.read(BlockReadControl::KEY_READ_EN))
-                + BlockReadControl::KEY_ID.val(block_read_ctrl.read(BlockReadControl::KEY_ID)),
+                + BlockReadControl::KEY_ID.val(block_read_ctrl.read(BlockReadControl::KEY_ID))
+                + BlockReadControl::PCR_HASH_EXTEND
+                    .val(block_read_ctrl.read(BlockReadControl::PCR_HASH_EXTEND)),
         );
 
         if block_read_ctrl.is_set(BlockReadControl::KEY_READ_EN) {
@@ -371,24 +419,42 @@ impl HashSha512 {
             );
 
             self.op_hash_write_complete_action = Some(self.timer.schedule_poll_in(KEY_RW_TICKS));
+        } else if self.control.reg.is_set(Control::LAST) {
+            let pcr_id = self.block_read_ctrl.reg.read(BlockReadControl::KEY_ID);
+            self.key_vault
+                .write_pcr(pcr_id, array_ref![self.hash.data(), 0, KeyVault::KEY_SIZE])
+                .unwrap();
         }
 
         // Update Ready and Valid status bits
         self.status
             .reg
             .modify(Status::READY::SET + Status::VALID::SET);
+
+        // Reset the pcr_hash_extend bit. This is done so the next round
+        // of block copy operation does not skip the first 48 bytes.
+        self.block_read_ctrl
+            .reg
+            .modify(BlockReadControl::PCR_HASH_EXTEND::CLEAR);
     }
 
     fn block_read_complete(&mut self) {
         let key_id = self.block_read_ctrl.reg.read(BlockReadControl::KEY_ID);
+        let pcr_hash_extend = self
+            .block_read_ctrl
+            .reg
+            .read(BlockReadControl::PCR_HASH_EXTEND);
 
         // Clear the block
-        self.block.data_mut().fill(0);
+        self.block.fill(0);
 
-        let mut key_usage = KeyUsage::default();
-        key_usage.set_sha_data(true);
-
-        let result = self.key_vault.read_key(key_id, key_usage);
+        let result: Result<[u8; KeyVault::KEY_SIZE], BusError> = if pcr_hash_extend == 0 {
+            let mut key_usage = KeyUsage::default();
+            key_usage.set_sha_data(true);
+            self.key_vault.read_key(key_id, key_usage)
+        } else {
+            Ok(self.key_vault.read_pcr(key_id))
+        };
         let (block_read_result, data) = match result.err() {
             Some(BusError::LoadAccessFault) | Some(BusError::LoadAddrMisaligned) => {
                 (BlockReadStatus::ERROR::KV_READ_FAIL.value, None)
@@ -399,8 +465,15 @@ impl HashSha512 {
             None => (BlockReadStatus::ERROR::KV_SUCCESS.value, result.ok()),
         };
 
-        if let Some(data) = &data {
-            self.format_block(data);
+        if let Some(data) = data {
+            if pcr_hash_extend != 0 {
+                // Copy the PCR (48 bytes) to the block registers.
+                self.block[..KeyVault::KEY_SIZE / 4].copy_from_slice(&words_from_bytes_le(
+                    &data[..KeyVault::KEY_SIZE].try_into().unwrap(),
+                ));
+            } else {
+                self.format_block(&data);
+            }
         }
 
         self.block_read_status.reg.modify(
@@ -435,7 +508,7 @@ impl HashSha512 {
         block_arr[SHA512_BLOCK_SIZE - 16..].copy_from_slice(&len.to_be_bytes());
 
         block_arr.to_big_endian();
-        self.block.data_mut().copy_from_slice(&block_arr);
+        self.block = sha512_block_words_from_bytes_le(&block_arr[..].try_into().unwrap());
     }
 
     fn hash_write_complete(&mut self) {
@@ -564,20 +637,20 @@ mod tests {
         HashWriteFailTest(bool),
     }
 
+    fn make_word(idx: usize, arr: &[u8]) -> RvData {
+        let mut res: RvData = 0;
+        for i in 0..4 {
+            res |= (arr[idx + i] as RvData) << (i * 8);
+        }
+        res
+    }
+
     fn test_sha(
         data: &[u8],
         expected: &[u8],
         mode: Sha512Mode,
         keyvault_actions: &[KeyVaultAction],
     ) {
-        fn make_word(idx: usize, arr: &[u8]) -> RvData {
-            let mut res: RvData = 0;
-            for i in 0..4 {
-                res |= (arr[idx + i] as RvData) << (i * 8);
-            }
-            res
-        }
-
         let mut block_via_kv: bool = false;
         let mut block_id: u32 = u32::MAX;
         let mut hash_to_kv: bool = false;
@@ -1064,4 +1137,167 @@ mod tests {
             );
         }
     }
+
+    fn test_pcr_hash_extend(data: &[u8], pcr_data: &mut [u8; KeyVault::KEY_SIZE], expected: &[u8]) {
+        // Prime the PCR vault.
+        let clock = Clock::new();
+        let pcr_id = 0;
+        let mut key_vault = KeyVault::new();
+        pcr_data.change_endianess();
+        assert!(key_vault.write_pcr(pcr_id, pcr_data).is_ok());
+        pcr_data.change_endianess();
+
+        let mut sha512 = HashSha512::new(&clock, key_vault);
+        // Enable pcr hash extend.
+        let block_ctrl = InMemoryRegister::<u32, BlockReadControl::Register>::new(0);
+        block_ctrl.modify(
+            BlockReadControl::KEY_ID.val(pcr_id)
+                + BlockReadControl::KEY_READ_EN.val(1)
+                + BlockReadControl::PCR_HASH_EXTEND.val(1),
+        );
+        assert_eq!(
+            sha512
+                .write(RvSize::Word, OFFSET_BLOCK_CONTROL, block_ctrl.get())
+                .ok(),
+            Some(())
+        );
+        // Wait for sha512 periph to retrieve the pcr from the key-vault.
+        loop {
+            let block_read_status = InMemoryRegister::<u32, BlockReadStatus::Register>::new(
+                sha512.read(RvSize::Word, OFFSET_BLOCK_STATUS).unwrap(),
+            );
+            if block_read_status.is_set(BlockReadStatus::VALID) {
+                break;
+            }
+            clock.increment_and_poll(1, &mut sha512);
+        }
+
+        // Transfer the data to the block registers
+        let actual_data_length = data.len() + pcr_data.len();
+        let totalblocks = ((actual_data_length + 16) + SHA512_BLOCK_SIZE) / SHA512_BLOCK_SIZE;
+        let totalbytes = totalblocks * SHA512_BLOCK_SIZE;
+        let mut block_arr = vec![0; totalbytes];
+
+        block_arr[..pcr_data.len()].copy_from_slice(pcr_data);
+        block_arr[pcr_data.len()..actual_data_length].copy_from_slice(data);
+        block_arr[data.len() + pcr_data.len()] = 1 << 7;
+        let len: u128 = actual_data_length as u128;
+        let len = len * 8;
+        block_arr[totalbytes - 16..].copy_from_slice(&len.to_be_bytes());
+        block_arr.to_big_endian();
+        let mut last_block = false;
+        for idx in 0..totalblocks {
+            for i in (0..SHA512_BLOCK_SIZE).step_by(4) {
+                assert_eq!(
+                    sha512
+                        .write(
+                            RvSize::Word,
+                            OFFSET_BLOCK + i as RvAddr,
+                            make_word((idx * SHA512_BLOCK_SIZE) + i, &block_arr)
+                        )
+                        .ok(),
+                    Some(())
+                );
+            }
+
+            if idx == (totalblocks - 1) {
+                last_block = true;
+            }
+
+            if idx == 0 {
+                let control: ReadWriteRegister<u32, Control::Register> = ReadWriteRegister::new(0);
+                control.reg.modify(
+                    Control::MODE.val(Sha512Mode::Sha384.into())
+                        + Control::INIT.val(1)
+                        + Control::LAST.val(last_block as u32),
+                );
+                assert_eq!(
+                    sha512
+                        .write(RvSize::Word, OFFSET_CONTROL, control.reg.get())
+                        .ok(),
+                    Some(())
+                );
+            } else {
+                let control: ReadWriteRegister<u32, Control::Register> = ReadWriteRegister::new(0);
+                control
+                    .reg
+                    .modify(Control::NEXT.val(1) + Control::LAST.val(last_block as u32));
+
+                assert_eq!(
+                    sha512
+                        .write(RvSize::Word, OFFSET_CONTROL, control.reg.get())
+                        .ok(),
+                    Some(())
+                );
+            }
+
+            loop {
+                let status = InMemoryRegister::<u32, Status::Register>::new(
+                    sha512.read(RvSize::Word, OFFSET_STATUS).unwrap(),
+                );
+                if status.is_set(Status::VALID) && status.is_set(Status::READY) {
+                    break;
+                }
+                clock.increment_and_poll(1, &mut sha512);
+            }
+        }
+
+        // Read the hash from the PCR vault.
+        let mut hash_le: [u8; SHA384_HASH_SIZE];
+        hash_le = sha512.key_vault.read_pcr(pcr_id);
+        hash_le.to_little_endian();
+        assert_eq!(&hash_le[0..sha512.hash().len()], expected);
+    }
+
+    #[test]
+    fn test_sha384_pcr_hash_extend_single_block() {
+        let data: [u8; 48] = [
+            0x9c, 0x2f, 0x48, 0x76, 0x0d, 0x13, 0xac, 0x42, 0xea, 0xd1, 0x96, 0xe5, 0x4d, 0xcb,
+            0xaa, 0x5e, 0x58, 0x72, 0x06, 0x62, 0xa9, 0x6b, 0x91, 0x94, 0xe9, 0x81, 0x33, 0x29,
+            0xbd, 0xb6, 0x27, 0xc7, 0xc1, 0xca, 0x77, 0x15, 0x31, 0x16, 0x32, 0xc1, 0x39, 0xe7,
+            0xa3, 0x59, 0x14, 0xfc, 0x1e, 0xcd,
+        ];
+        let mut pcr_data: [u8; 48] = [
+            0x9c, 0x2f, 0x48, 0x76, 0x0d, 0x13, 0xac, 0x42, 0xea, 0xd1, 0x96, 0xe5, 0x4d, 0xcb,
+            0xaa, 0x5e, 0x58, 0x72, 0x06, 0x62, 0xa9, 0x6b, 0x91, 0x94, 0xe9, 0x81, 0x33, 0x29,
+            0xbd, 0xb6, 0x27, 0xc7, 0xc1, 0xca, 0x77, 0x15, 0x31, 0x16, 0x32, 0xc1, 0x39, 0xe7,
+            0xa3, 0x59, 0x14, 0xfc, 0x1e, 0xcd,
+        ];
+        let expected: [u8; 48] = [
+            0x13, 0x77, 0x93, 0x7b, 0x0, 0x6b, 0x72, 0xab, 0x18, 0xc1, 0x26, 0x4d, 0x2, 0xa4, 0xd6,
+            0xe2, 0xd9, 0xb6, 0x7e, 0xec, 0x63, 0x52, 0x52, 0x41, 0x30, 0x56, 0x51, 0x14, 0x8d,
+            0xca, 0x13, 0xd1, 0x2b, 0x8f, 0xca, 0x88, 0xeb, 0x5, 0x5e, 0x20, 0x66, 0x5e, 0xa8,
+            0x90, 0xa3, 0x1b, 0x8c, 0x8,
+        ];
+
+        test_pcr_hash_extend(&data, &mut pcr_data, &expected);
+    }
+
+    #[test]
+    fn test_sha384_pcr_hash_extend_multi_block() {
+        let data: [u8; 82] = [
+            0x77, 0x78, 0x79, 0x7A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A,
+            0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+            0x79, 0x7A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C,
+            0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A,
+            0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E,
+            0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A,
+        ];
+
+        let mut pcr_data: [u8; 48] = [
+            0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E,
+            0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x61, 0x62,
+            0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
+            0x71, 0x72, 0x73, 0x74, 0x75, 0x76,
+        ];
+
+        let expected: [u8; SHA384_HASH_SIZE] = [
+            0x9c, 0x2f, 0x48, 0x76, 0xd, 0x13, 0xac, 0x42, 0xea, 0xd1, 0x96, 0xe5, 0x4d, 0xcb,
+            0xaa, 0x5e, 0x58, 0x72, 0x6, 0x62, 0xa9, 0x6b, 0x91, 0x94, 0xe9, 0x81, 0x33, 0x29,
+            0xbd, 0xb6, 0x27, 0xc7, 0xc1, 0xca, 0x77, 0x15, 0x31, 0x16, 0x32, 0xc1, 0x39, 0xe7,
+            0xa3, 0x59, 0x14, 0xfc, 0x1e, 0xcd,
+        ];
+
+        test_pcr_hash_extend(&data, &mut pcr_data, &expected);
+    }
 }


Test patch:
diff --git a/drivers/test-fw/src/bin/hmac384_tests.rs b/drivers/test-fw/src/bin/hmac384_tests.rs
index b1982219..628994c4 100755
--- a/drivers/test-fw/src/bin/hmac384_tests.rs
+++ b/drivers/test-fw/src/bin/hmac384_tests.rs
@@ -16,7 +16,10 @@ Abstract:
 #![no_main]
 
 use caliptra_kat::Hmac384Kat;
-use caliptra_lib::{Array4x12, Hmac384, KeyId, KeyReadArgs, KeyUsage, KeyWriteArgs, Sha384};
+use caliptra_lib::{
+    Array4x12, Ecc384, Ecc384PrivKeyOut, Ecc384Scalar, Ecc384Seed, Hmac384, KeyId, KeyReadArgs,
+    KeyUsage, KeyWriteArgs,
+};
 
 mod harness;
 
@@ -83,30 +86,32 @@ fn test_hmac3() {
     //
     // Step 1: Place a key in the key-vault.
     //
-    let data = &[];
-    let mut usage = KeyUsage(0);
-    usage.set_hmac_key(true);
+    let seed = [0u8; 48];
+    let mut key_usage = KeyUsage::default();
+    key_usage.set_hmac_key(true);
     let key_out_1 = KeyWriteArgs {
         id: KeyId::KeyId0,
-        usage,
+        usage: key_usage, // hmac_key
     };
-    let result = Sha384::default().digest((data).into(), key_out_1.into());
+    let result = Ecc384::default().key_pair(
+        Ecc384Seed::from(&Ecc384Scalar::from(seed)),
+        Ecc384PrivKeyOut::from(key_out_1),
+    );
     assert!(result.is_ok());
 
     //
     // Step 2: Hash the data with the key from key-vault.
-    // Key is [0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38, 0x4c, 0xd9, 0x32, 0x7e, 0xb1, 0xb1, 0xe3,
-    //         0x6a, 0x21, 0xfd, 0xb7, 0x11, 0x14, 0xbe, 0x07, 0x43, 0x4c, 0x0c, 0xc7, 0xbf, 0x63, 0xf6,
-    //         0xe1, 0xda, 0x27, 0x4e, 0xde, 0xbf, 0xe7, 0x6f, 0x65, 0xfb, 0xd5, 0x1a, 0xd2, 0xf1, 0x48,
-    //         0x98, 0xb9, 0x5b,];
+    // Key is [0xc9, 0x8, 0x58, 0x5a, 0x48, 0x6c, 0x3b, 0x3d, 0x8b, 0xbe, 0x50, 0xeb, 0x7d, 0x2e, 0xb8, 0xa0,
+    //         0x3a, 0xa0, 0x4e, 0x3d, 0x8b, 0xde, 0x2c, 0x31, 0xa8, 0xa2, 0xa1, 0xe3, 0x34, 0x9d, 0xc2, 0x1c,
+    //         0xbb, 0xe6, 0xc9, 0xa, 0xe2, 0xf7, 0x49, 0x12, 0x88, 0x84, 0xb6, 0x22, 0xbb, 0x72, 0xb4, 0xc5,];
     //
     let data: [u8; 8] = [0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65];
 
     let result: [u8; 48] = [
-        0x4c, 0x6d, 0x04, 0xc9, 0xac, 0xf8, 0x58, 0x76, 0x2b, 0x60, 0x1e, 0xb2, 0xf4, 0xb8, 0x43,
-        0x45, 0xbc, 0xd2, 0x4b, 0x3b, 0x57, 0xca, 0xb6, 0x9b, 0x62, 0xf2, 0x0f, 0x64, 0x4e, 0xca,
-        0xbb, 0xf4, 0xdf, 0x53, 0xf0, 0x0b, 0x0c, 0xf0, 0x80, 0x05, 0x6f, 0x4b, 0xf0, 0xb3, 0x8d,
-        0x81, 0xe7, 0x37,
+        0xe2, 0xde, 0x61, 0x3, 0xea, 0x5b, 0x70, 0x8d, 0x3e, 0xa1, 0x84, 0xd, 0x69, 0xc0, 0xd7,
+        0x18, 0xf8, 0xbb, 0x67, 0x4e, 0x42, 0x31, 0x97, 0x8c, 0xf1, 0x59, 0xf3, 0x53, 0x62, 0xc5,
+        0xef, 0x29, 0xb0, 0xbe, 0x32, 0x9, 0x74, 0x92, 0x47, 0x89, 0x8e, 0x10, 0x11, 0xc, 0x9d,
+        0x64, 0x2d, 0xb7,
     ];
 
     let mut out_tag = Array4x12::default();
@@ -121,22 +126,24 @@ fn test_hmac4() {
     //
     // Step 1: Place a key in the key-vault.
     //
-    let data = &[];
-    let mut usage = KeyUsage(0);
-    usage.set_hmac_key(true);
+    let seed = [0u8; 48];
+    let mut key_usage = KeyUsage::default();
+    key_usage.set_hmac_key(true);
     let key_out_1 = KeyWriteArgs {
         id: KeyId::KeyId0,
-        usage,
+        usage: key_usage, // hmac_key
     };
-    let result = Sha384::default().digest((data).into(), key_out_1.into());
+    let result = Ecc384::default().key_pair(
+        Ecc384Seed::from(&Ecc384Scalar::from(seed)),
+        Ecc384PrivKeyOut::from(key_out_1),
+    );
     assert!(result.is_ok());
 
     //
     // Step 2: Hash the data with the key from key-vault.
-    // Key is [0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38, 0x4c, 0xd9, 0x32, 0x7e, 0xb1, 0xb1, 0xe3,
-    //         0x6a, 0x21, 0xfd, 0xb7, 0x11, 0x14, 0xbe, 0x07, 0x43, 0x4c, 0x0c, 0xc7, 0xbf, 0x63, 0xf6,
-    //         0xe1, 0xda, 0x27, 0x4e, 0xde, 0xbf, 0xe7, 0x6f, 0x65, 0xfb, 0xd5, 0x1a, 0xd2, 0xf1, 0x48,
-    //         0x98, 0xb9, 0x5b,];
+    // Key is [0xc9, 0x8, 0x58, 0x5a, 0x48, 0x6c, 0x3b, 0x3d, 0x8b, 0xbe, 0x50, 0xeb, 0x7d, 0x2e, 0xb8, 0xa0,
+    //         0x3a, 0xa0, 0x4e, 0x3d, 0x8b, 0xde, 0x2c, 0x31, 0xa8, 0xa2, 0xa1, 0xe3, 0x34, 0x9d, 0xc2, 0x1c,
+    //         0xbb, 0xe6, 0xc9, 0xa, 0xe2, 0xf7, 0x49, 0x12, 0x88, 0x84, 0xb6, 0x22, 0xbb, 0x72, 0xb4, 0xc5,];
     //
 
     let data: [u8; 28] = [
@@ -145,10 +152,10 @@ fn test_hmac4() {
     ];
 
     let result: [u8; 48] = [
-        0xc9, 0x33, 0x1d, 0x20, 0x41, 0xff, 0x24, 0xf, 0x1d, 0xa1, 0xa0, 0x4a, 0x57, 0xb0, 0x7c,
-        0xb1, 0xf9, 0x5c, 0xb7, 0x1e, 0xca, 0xb7, 0x94, 0xf1, 0xb6, 0x1c, 0xb8, 0x1b, 0x35, 0x80,
-        0x2, 0x38, 0x8a, 0xfa, 0x3d, 0x16, 0x1e, 0x3e, 0x89, 0x35, 0x7d, 0x74, 0x6f, 0x95, 0x56,
-        0xe6, 0xfb, 0xe1,
+        0x7c, 0x5c, 0xc4, 0x65, 0x5, 0x61, 0x61, 0x18, 0x31, 0x64, 0x75, 0xc7, 0x12, 0x7d, 0x40,
+        0xa, 0xf1, 0xfb, 0x85, 0x9, 0xbc, 0x8a, 0xc7, 0xda, 0xd7, 0x25, 0xb9, 0x6a, 0x6d, 0x26,
+        0x99, 0xeb, 0x63, 0x1c, 0x44, 0xac, 0x99, 0xb6, 0x6f, 0x34, 0x47, 0xad, 0xc5, 0x1e, 0x5a,
+        0x3a, 0xb6, 0x43,
     ];
 
     let mut out_tag = Array4x12::default();
@@ -164,22 +171,24 @@ fn test_hmac5() {
     //
     // Step 1: Place a key in the key-vault.
     //
-    let data = &[];
-    let mut usage = KeyUsage(0);
-    usage.set_hmac_key(true);
+    let seed = [0u8; 48];
+    let mut key_usage = KeyUsage::default();
+    key_usage.set_hmac_key(true);
     let key_out_1 = KeyWriteArgs {
         id: KeyId::KeyId0,
-        usage,
+        usage: key_usage, // hmac_key
     };
-    let result = Sha384::default().digest((data).into(), key_out_1.into());
+    let result = Ecc384::default().key_pair(
+        Ecc384Seed::from(&Ecc384Scalar::from(seed)),
+        Ecc384PrivKeyOut::from(key_out_1),
+    );
     assert!(result.is_ok());
 
     //
     // Step 2: Hash the data with the key from key-vault.
-    // Key is [0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38, 0x4c, 0xd9, 0x32, 0x7e, 0xb1, 0xb1, 0xe3,
-    //         0x6a, 0x21, 0xfd, 0xb7, 0x11, 0x14, 0xbe, 0x07, 0x43, 0x4c, 0x0c, 0xc7, 0xbf, 0x63, 0xf6,
-    //         0xe1, 0xda, 0x27, 0x4e, 0xde, 0xbf, 0xe7, 0x6f, 0x65, 0xfb, 0xd5, 0x1a, 0xd2, 0xf1, 0x48,
-    //         0x98, 0xb9, 0x5b,];
+    // Key is [0xc9, 0x8, 0x58, 0x5a, 0x48, 0x6c, 0x3b, 0x3d, 0x8b, 0xbe, 0x50, 0xeb, 0x7d, 0x2e, 0xb8, 0xa0,
+    //         0x3a, 0xa0, 0x4e, 0x3d, 0x8b, 0xde, 0x2c, 0x31, 0xa8, 0xa2, 0xa1, 0xe3, 0x34, 0x9d, 0xc2, 0x1c,
+    //         0xbb, 0xe6, 0xc9, 0xa, 0xe2, 0xf7, 0x49, 0x12, 0x88, 0x84, 0xb6, 0x22, 0xbb, 0x72, 0xb4, 0xc5,];
     //
     let data: [u8; 48] = [
         0xe9, 0x54, 0x51, 0x9b, 0xd1, 0x02, 0xfc, 0xe1, 0x94, 0xf3, 0xf9, 0x12, 0x60, 0xcc, 0x3d,
@@ -189,10 +198,10 @@ fn test_hmac5() {
     ];
 
     let result: [u8; 48] = [
-        0x47, 0x29, 0xe, 0x2, 0xc4, 0xf3, 0xbe, 0x4f, 0x56, 0xe9, 0xc0, 0x80, 0xac, 0x3c, 0x1b,
-        0xf5, 0xa5, 0xa3, 0xcb, 0x7e, 0x71, 0x6b, 0x91, 0xc7, 0x82, 0x6e, 0xa3, 0xf3, 0xe4, 0xad,
-        0x7f, 0x2, 0xd4, 0x3c, 0xc6, 0x7e, 0xb, 0xe5, 0x33, 0xc5, 0x6c, 0x22, 0x68, 0x43, 0x20,
-        0x1d, 0x37, 0xbe,
+        0xce, 0x29, 0xfb, 0x40, 0x47, 0xa2, 0x2a, 0xdf, 0x85, 0x3c, 0x73, 0x30, 0xa3, 0xae, 0xa5,
+        0x6f, 0x29, 0x96, 0x88, 0xd0, 0x5c, 0x36, 0xdb, 0x5e, 0xe6, 0xa4, 0xd1, 0xde, 0xaa, 0x4f,
+        0x78, 0x1, 0x86, 0xa5, 0x47, 0xa0, 0x85, 0x84, 0xfb, 0x89, 0xc7, 0x12, 0xdd, 0xe6, 0x5f,
+        0x57, 0x7f, 0xff,
     ];
 
     let mut out_tag = Array4x12::default();
@@ -221,19 +230,21 @@ fn test_hmac6() {
     //
     // Step 1: Place a key in the key-vault.
     //
-    // Key is [0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38, 0x4c, 0xd9, 0x32, 0x7e, 0xb1, 0xb1, 0xe3,
-    //         0x6a, 0x21, 0xfd, 0xb7, 0x11, 0x14, 0xbe, 0x07, 0x43, 0x4c, 0x0c, 0xc7, 0xbf, 0x63, 0xf6,
-    //         0xe1, 0xda, 0x27, 0x4e, 0xde, 0xbf, 0xe7, 0x6f, 0x65, 0xfb, 0xd5, 0x1a, 0xd2, 0xf1, 0x48,
-    //         0x98, 0xb9, 0x5b,];
+    // Key is [0xc9, 0x8, 0x58, 0x5a, 0x48, 0x6c, 0x3b, 0x3d, 0x8b, 0xbe, 0x50, 0xeb, 0x7d, 0x2e, 0xb8, 0xa0,
+    //         0x3a, 0xa0, 0x4e, 0x3d, 0x8b, 0xde, 0x2c, 0x31, 0xa8, 0xa2, 0xa1, 0xe3, 0x34, 0x9d, 0xc2, 0x1c,
+    //         0xbb, 0xe6, 0xc9, 0xa, 0xe2, 0xf7, 0x49, 0x12, 0x88, 0x84, 0xb6, 0x22, 0xbb, 0x72, 0xb4, 0xc5,];
     //
-    let data = &[];
+    let seed = [0u8; 48];
     let mut key_usage = KeyUsage::default();
     key_usage.set_hmac_key(true);
     let key_out_1 = KeyWriteArgs {
         id: KeyId::KeyId0,
-        usage: key_usage,
+        usage: key_usage, // hmac_key
     };
-    let result = Sha384::default().digest((data).into(), key_out_1.into());
+    let result = Ecc384::default().key_pair(
+        Ecc384Seed::from(&Ecc384Scalar::from(seed)),
+        Ecc384PrivKeyOut::from(key_out_1),
+    );
     assert!(result.is_ok());
 
     // Key vault key to be used for all the operations. This is a constant
@@ -245,10 +256,10 @@ fn test_hmac6() {
     ];
 
     let result: [u8; 48] = [
-        0xc9, 0x33, 0x1d, 0x20, 0x41, 0xff, 0x24, 0xf, 0x1d, 0xa1, 0xa0, 0x4a, 0x57, 0xb0, 0x7c,
-        0xb1, 0xf9, 0x5c, 0xb7, 0x1e, 0xca, 0xb7, 0x94, 0xf1, 0xb6, 0x1c, 0xb8, 0x1b, 0x35, 0x80,
-        0x2, 0x38, 0x8a, 0xfa, 0x3d, 0x16, 0x1e, 0x3e, 0x89, 0x35, 0x7d, 0x74, 0x6f, 0x95, 0x56,
-        0xe6, 0xfb, 0xe1,
+        0x7c, 0x5c, 0xc4, 0x65, 0x5, 0x61, 0x61, 0x18, 0x31, 0x64, 0x75, 0xc7, 0x12, 0x7d, 0x40,
+        0xa, 0xf1, 0xfb, 0x85, 0x9, 0xbc, 0x8a, 0xc7, 0xda, 0xd7, 0x25, 0xb9, 0x6a, 0x6d, 0x26,
+        0x99, 0xeb, 0x63, 0x1c, 0x44, 0xac, 0x99, 0xb6, 0x6f, 0x34, 0x47, 0xad, 0xc5, 0x1e, 0x5a,
+        0x3a, 0xb6, 0x43,
     ];
 
     // Take the Data Generate the Tag in buffer
@@ -258,13 +269,13 @@ fn test_hmac6() {
     assert_eq!(out_tag, Array4x12::from(result));
 
     let step_1_result_expected: [u8; 48] = [
-        0x6e, 0xf3, 0x6f, 0xc4, 0x87, 0xbd, 0x4a, 0xec, 0x99, 0xf0, 0xfb, 0x2a, 0xc3, 0x8e, 0x73,
-        0x41, 0x47, 0xbc, 0x2c, 0x94, 0x59, 0x59, 0x97, 0xbe, 0x2d, 0xa3, 0x90, 0xe6, 0xb4, 0xc6,
-        0x3c, 0x6a, 0xee, 0x23, 0x35, 0xa2, 0xe8, 0xef, 0x18, 0x51, 0x2d, 0xc, 0xa6, 0x7b, 0x95,
-        0x3, 0xd1, 0xfd,
+        0x64, 0xb9, 0x45, 0x33, 0x5e, 0xc6, 0xee, 0x43, 0xd1, 0xb2, 0xfc, 0xea, 0xde, 0x9c, 0xb9,
+        0xe5, 0x7, 0xaa, 0xa1, 0x46, 0x6a, 0xe4, 0x5a, 0xf6, 0x72, 0x36, 0x3a, 0x79, 0x2b, 0x97,
+        0xe7, 0xe, 0x2, 0xef, 0xf6, 0xe, 0xa8, 0xf7, 0xaa, 0xe7, 0x90, 0x64, 0xc8, 0xaa, 0xc7,
+        0xe5, 0x45, 0xe,
     ];
 
-    // Generate the HAMC of the Tag in to a hmac_step_1
+    // Generate the HMAC of the Tag in to a hmac_step_1
     let mut hmac_step_1 = Array4x12::default();
     let actual = Hmac384::default().hmac(key.into(), (&result).into(), (&mut hmac_step_1).into());
     assert!(actual.is_ok());
diff --git a/drivers/test-fw/src/bin/sha384_tests.rs b/drivers/test-fw/src/bin/sha384_tests.rs
index eb35e390..f5b725ab 100644
--- a/drivers/test-fw/src/bin/sha384_tests.rs
+++ b/drivers/test-fw/src/bin/sha384_tests.rs
@@ -16,21 +16,10 @@ Abstract:
 #![no_main]
 
 use caliptra_kat::Sha384Kat;
-use caliptra_lib::{Array4x12, KeyId, KeyReadArgs, KeyUsage, KeyWriteArgs, Sha384};
+use caliptra_lib::{Array4x12, PcrBank, PcrHashExtendArgs, PcrId, Sha384};
 
 mod harness;
 
-const KEY_IDS: [KeyId; 8] = [
-    KeyId::KeyId0,
-    KeyId::KeyId1,
-    KeyId::KeyId2,
-    KeyId::KeyId3,
-    KeyId::KeyId4,
-    KeyId::KeyId5,
-    KeyId::KeyId6,
-    KeyId::KeyId7,
-];
-
 fn test_digest0() {
     let expected: [u8; 48] = [
         0x38, 0xB0, 0x60, 0xA7, 0x51, 0xAC, 0x96, 0x38, 0x4C, 0xD9, 0x32, 0x7E, 0xB1, 0xB1, 0xE3,
@@ -246,68 +235,204 @@ fn test_op8() {
     assert_eq!(digest, Array4x12::from(expected));
 }
 
-fn test_kv() {
-    let expected: [u8; 48] = [
-        0x31, 0x15, 0x4d, 0x09, 0x2c, 0x9e, 0xf4, 0xc7, 0x23, 0x0c, 0xeb, 0x5d, 0x32, 0x65, 0x7f,
-        0x11, 0x51, 0x79, 0xdb, 0x40, 0x30, 0xc0, 0x16, 0x71, 0x1e, 0x2a, 0xd2, 0x85, 0xb3, 0x66,
-        0xaa, 0x5f, 0x78, 0x3a, 0xac, 0x7b, 0x3f, 0x71, 0xc3, 0xe0, 0x0e, 0xb9, 0x9b, 0xc5, 0x0e,
-        0x75, 0x60, 0x64,
+// fn test_kv() {
+//     let expected: [u8; 48] = [
+//         0x31, 0x15, 0x4d, 0x09, 0x2c, 0x9e, 0xf4, 0xc7, 0x23, 0x0c, 0xeb, 0x5d, 0x32, 0x65, 0x7f,
+//         0x11, 0x51, 0x79, 0xdb, 0x40, 0x30, 0xc0, 0x16, 0x71, 0x1e, 0x2a, 0xd2, 0x85, 0xb3, 0x66,
+//         0xaa, 0x5f, 0x78, 0x3a, 0xac, 0x7b, 0x3f, 0x71, 0xc3, 0xe0, 0x0e, 0xb9, 0x9b, 0xc5, 0x0e,
+//         0x75, 0x60, 0x64,
+//     ];
+
+//     let data: [u8; 48] = [
+//         0x9c, 0x2f, 0x48, 0x76, 0x0d, 0x13, 0xac, 0x42, 0xea, 0xd1, 0x96, 0xe5, 0x4d, 0xcb, 0xaa,
+//         0x5e, 0x58, 0x72, 0x06, 0x62, 0xa9, 0x6b, 0x91, 0x94, 0xe9, 0x81, 0x33, 0x29, 0xbd, 0xb6,
+//         0x27, 0xc7, 0xc1, 0xca, 0x77, 0x15, 0x31, 0x16, 0x32, 0xc1, 0x39, 0xe7, 0xa3, 0x59, 0x14,
+//         0xfc, 0x1e, 0xcd,
+//     ];
+
+//     //
+//     // Step 1: Hash a buffer from input and store the hash into key-vault slot 0.
+//     //
+//     let mut usage = KeyUsage(0);
+//     usage.set_sha_data(true);
+//     let key_out_1 = KeyWriteArgs {
+//         id: KeyId::KeyId0,
+//         usage,
+//     };
+//     let mut result = Sha384::default().digest((&data).into(), key_out_1.into());
+//     assert!(result.is_ok());
+
+//     //
+//     // Step 2: Hash the hash generated in step 1.
+//     // Success indicates hash was correctly stored in the key-vault in step 1.
+//     // Success also indicates buffer was correctly retrieved from the key-vault.
+//     //
+//     let mut digest = Array4x12::default();
+//     let key_in_2 = KeyReadArgs::new(KeyId::KeyId0);
+//     result = Sha384::default().digest(key_in_2.into(), (&mut digest).into());
+//     assert!(result.is_ok());
+//     assert_eq!(digest, Array4x12::from(expected));
+// }
+
+// fn test_kv_incorrect_key_acl() {
+//     let data = &[];
+//     let mut usage = KeyUsage(0);
+//     usage.set_sha_data(false);
+
+//     for key_id in KEY_IDS {
+//         //
+//         // Step 1: Hash a buffer from input and store the hash into key-vault slot 0.
+//         // Prevent the key to be used as sha data.
+//         //
+//         let key_out_1 = KeyWriteArgs { id: key_id, usage };
+//         let mut result = Sha384::default().digest((data).into(), key_out_1.into());
+//         assert!(result.is_ok());
+
+//         //
+//         // Step 2: Use the key generated in step 1 as SHA data.
+//         // This should fail since acl set on key should prevent it's usage as SHA data.
+//         //
+//         let mut digest = Array4x12::default();
+//         let key_in_2 = KeyReadArgs::new(key_id);
+//         result = Sha384::default().digest(key_in_2.into(), (&mut digest).into());
+//         assert!(result.is_err());
+//     }
+// }
+
+fn test_pcr_hash_extend_single_block() {
+    let expected_round_1: [u8; 48] = [
+        0x4d, 0xca, 0xf1, 0x2f, 0xab, 0xaa, 0x55, 0x47, 0xf4, 0x6c, 0x32, 0x64, 0xb1, 0xe4, 0x5b,
+        0xc4, 0x5, 0x5c, 0x0, 0xe, 0x66, 0x2c, 0x6c, 0x8a, 0x2c, 0xca, 0x71, 0x2b, 0x44, 0x2d,
+        0x82, 0x6a, 0xf0, 0xbc, 0x35, 0x96, 0x2b, 0x59, 0x45, 0x17, 0xb3, 0x2f, 0xe1, 0x66, 0x73,
+        0xd1, 0x20, 0x30,
+    ];
+    let expected_round_2: [u8; 48] = [
+        0xe0, 0x4, 0x44, 0x8, 0xb7, 0x28, 0xe8, 0xcc, 0x18, 0x76, 0x1e, 0x30, 0xde, 0x50, 0xb0,
+        0xa5, 0x30, 0xd7, 0xfa, 0x58, 0x78, 0x62, 0x8, 0xc2, 0xb1, 0x75, 0xa9, 0x7c, 0x6c, 0x25,
+        0x50, 0x50, 0x4, 0x4c, 0x6c, 0x2f, 0xcf, 0xc6, 0x40, 0x46, 0xcc, 0xea, 0x1c, 0x3a, 0xe1,
+        0x2e, 0xe6, 0x72,
     ];
-
     let data: [u8; 48] = [
         0x9c, 0x2f, 0x48, 0x76, 0x0d, 0x13, 0xac, 0x42, 0xea, 0xd1, 0x96, 0xe5, 0x4d, 0xcb, 0xaa,
         0x5e, 0x58, 0x72, 0x06, 0x62, 0xa9, 0x6b, 0x91, 0x94, 0xe9, 0x81, 0x33, 0x29, 0xbd, 0xb6,
         0x27, 0xc7, 0xc1, 0xca, 0x77, 0x15, 0x31, 0x16, 0x32, 0xc1, 0x39, 0xe7, 0xa3, 0x59, 0x14,
         0xfc, 0x1e, 0xcd,
     ];
+    let mut pcr_bank = PcrBank::default();
+    pcr_bank.erase_all_pcrs();
 
-    //
-    // Step 1: Hash a buffer from input and store the hash into key-vault slot 0.
-    //
-    let mut usage = KeyUsage(0);
-    usage.set_sha_data(true);
-    let key_out_1 = KeyWriteArgs {
-        id: KeyId::KeyId0,
-        usage,
+    // Round 1: PCR is all zeros.
+    let mut digest = Array4x12::default();
+    let pcr_hash_extend_args = PcrHashExtendArgs {
+        slice: &data,
+        hash_extend: true,
+        id: PcrId::PcrId0,
     };
-    let mut result = Sha384::default().digest((&data).into(), key_out_1.into());
+    let result = Sha384::default().digest(pcr_hash_extend_args.into(), (&mut digest).into());
     assert!(result.is_ok());
+    assert_eq!(digest, Array4x12::from(expected_round_1));
 
-    //
-    // Step 2: Hash the hash generated in step 1.
-    // Success indicates hash was correctly stored in the key-vault in step 1.
-    // Success also indicates buffer was correctly retrieved from the key-vault.
-    //
+    // Round 2: PCR is expected_round_1
     let mut digest = Array4x12::default();
-    let key_in_2 = KeyReadArgs::new(KeyId::KeyId0);
-    result = Sha384::default().digest(key_in_2.into(), (&mut digest).into());
+    let result = Sha384::default().digest(pcr_hash_extend_args.into(), (&mut digest).into());
     assert!(result.is_ok());
-    assert_eq!(digest, Array4x12::from(expected));
+    assert_eq!(digest, Array4x12::from(expected_round_2));
 }
 
-fn test_kv_incorrect_key_acl() {
-    let data = &[];
-    let mut usage = KeyUsage(0);
-    usage.set_sha_data(false);
-
-    for key_id in KEY_IDS {
-        //
-        // Step 1: Hash a buffer from input and store the hash into key-vault slot 0.
-        // Prevent the key to be used as sha data.
-        //
-        let key_out_1 = KeyWriteArgs { id: key_id, usage };
-        let mut result = Sha384::default().digest((data).into(), key_out_1.into());
-        assert!(result.is_ok());
-
-        //
-        // Step 2: Use the key generated in step 1 as SHA data.
-        // This should fail since acl set on key should prevent it's usage as SHA data.
-        //
-        let mut digest = Array4x12::default();
-        let key_in_2 = KeyReadArgs::new(key_id);
-        result = Sha384::default().digest(key_in_2.into(), (&mut digest).into());
-        assert!(result.is_err());
-    }
+fn test_pcr_hash_extend_multi_block() {
+    let expected_round_1: [u8; 48] = [
+        0xb1, 0x6c, 0xce, 0x6c, 0x70, 0x51, 0x9c, 0x96, 0x58, 0xe3, 0xeb, 0x3e, 0xe1, 0xbd, 0x36,
+        0x96, 0x33, 0x85, 0xed, 0x38, 0xa2, 0x95, 0xe1, 0x85, 0x6c, 0xc, 0x44, 0x4d, 0x48, 0xd7,
+        0x76, 0x74, 0x73, 0x78, 0x3e, 0x29, 0x5a, 0x33, 0x59, 0x1c, 0x2e, 0xe6, 0xd2, 0x44, 0x36,
+        0xa0, 0xa6, 0x6b,
+    ];
+    let expected_round_2: [u8; 48] = [
+        0xde, 0x46, 0xdd, 0xc9, 0x47, 0x0, 0x89, 0x2a, 0x74, 0x6f, 0x50, 0xc9, 0xf9, 0xb2, 0xa7,
+        0xab, 0x36, 0x87, 0x62, 0xf7, 0x12, 0x0, 0x2f, 0xf4, 0xed, 0xcb, 0x8b, 0x75, 0x9, 0x86,
+        0xca, 0x3d, 0xb0, 0x4b, 0x56, 0xbd, 0x79, 0x4d, 0x26, 0x50, 0xb5, 0x9a, 0xc5, 0x90, 0x89,
+        0xa4, 0x5e, 0xf9,
+    ];
+    let data: [u8; 82] = [
+        0x77, 0x78, 0x79, 0x7A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B,
+        0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A,
+        0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
+        0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x61, 0x62, 0x63, 0x64,
+        0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73,
+        0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A,
+    ];
+    let mut pcr_bank = PcrBank::default();
+    pcr_bank.erase_all_pcrs();
+
+    // Round 1: PCR is all zeros.
+    let mut digest = Array4x12::default();
+    let pcr_hash_extend_args = PcrHashExtendArgs {
+        slice: &data,
+        hash_extend: true,
+        id: PcrId::PcrId1,
+    };
+    let result = Sha384::default().digest(pcr_hash_extend_args.into(), (&mut digest).into());
+    assert!(result.is_ok());
+    assert_eq!(digest, Array4x12::from(expected_round_1));
+
+    // Round 2: PCR is expected_round_1
+    let mut digest = Array4x12::default();
+    let result = Sha384::default().digest(pcr_hash_extend_args.into(), (&mut digest).into());
+    assert!(result.is_ok());
+    assert_eq!(digest, Array4x12::from(expected_round_2));
+}
+
+fn test_pcr_hash_extend_multi_block_2() {
+    let expected_round_1: [u8; 48] = [
+        0x69, 0x98, 0x44, 0x57, 0xe9, 0xbc, 0xf2, 0xe2, 0xa, 0xe6, 0x68, 0xdb, 0x87, 0xf8, 0x95,
+        0x63, 0xf, 0x18, 0x3a, 0xe, 0x21, 0xa8, 0x15, 0x27, 0x83, 0x65, 0xfe, 0xc0, 0xf9, 0x51,
+        0xbb, 0x9a, 0xdf, 0x3e, 0x5d, 0x3e, 0x6a, 0x2f, 0x74, 0xd2, 0x98, 0xa4, 0xbe, 0xbc, 0x10,
+        0x41, 0x99, 0x38,
+    ];
+    let expected_round_2: [u8; 48] = [
+        0xb, 0xed, 0x91, 0x11, 0xb0, 0xcf, 0xa2, 0x18, 0xa1, 0x4b, 0x27, 0x41, 0xeb, 0x75, 0x6c,
+        0xf8, 0x3c, 0x5a, 0x6, 0xd8, 0xce, 0xf1, 0x58, 0x25, 0x77, 0x16, 0xf2, 0xa6, 0x8, 0x77,
+        0xba, 0xb2, 0x75, 0x44, 0xc0, 0xd6, 0x48, 0x6e, 0xa9, 0xca, 0xfd, 0x44, 0x4e, 0x6b, 0xe3,
+        0xbe, 0x43, 0x77,
+    ];
+    let data: [u8; 256] = [
+        0x77, 0x78, 0x79, 0x7A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B,
+        0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A,
+        0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
+        0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x61, 0x62, 0x63, 0x64,
+        0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73,
+        0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x77, 0x78, 0x79, 0x7A, 0x61, 0x62, 0x63, 0x64,
+        0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73,
+        0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+        0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+        0x78, 0x79, 0x7A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C,
+        0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x77,
+        0x78, 0x79, 0x7A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C,
+        0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x61,
+        0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
+        0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
+        0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
+        0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
+        0x70,
+    ];
+    let mut pcr_bank = PcrBank::default();
+    pcr_bank.erase_all_pcrs();
+
+    // Round 1: PCR is all zeros.
+    let mut digest = Array4x12::default();
+    let pcr_hash_extend_args = PcrHashExtendArgs {
+        slice: &data,
+        hash_extend: true,
+        id: PcrId::PcrId2,
+    };
+    let result = Sha384::default().digest(pcr_hash_extend_args.into(), (&mut digest).into());
+    assert!(result.is_ok());
+    assert_eq!(digest, Array4x12::from(expected_round_1));
+
+    // Round 2: PCR is expected_round_1
+    let mut digest = Array4x12::default();
+    let result = Sha384::default().digest(pcr_hash_extend_args.into(), (&mut digest).into());
+    assert!(result.is_ok());
+    assert_eq!(digest, Array4x12::from(expected_round_2));
 }
 
 fn test_kat() {
@@ -329,6 +454,7 @@ test_suite! {
     test_op6,
     test_op7,
     test_op8,
-    test_kv,
-    test_kv_incorrect_key_acl,
+    test_pcr_hash_extend_single_block,
+    test_pcr_hash_extend_multi_block,
+    test_pcr_hash_extend_multi_block_2,
 }