diff --git a/hw/dv/sv/mem_bkdr_util/mem_bkdr_util.core b/hw/dv/sv/mem_bkdr_util/mem_bkdr_util.core index 553054a05aabcc..dcdb614771d8f0 100644 --- a/hw/dv/sv/mem_bkdr_util/mem_bkdr_util.core +++ b/hw/dv/sv/mem_bkdr_util/mem_bkdr_util.core @@ -15,16 +15,13 @@ filesets: - lowrisc:prim:cipher_pkg:0.1 - lowrisc:prim:secded:0.1 - lowrisc:ip:otp_ctrl_pkg:1.0 - - lowrisc:ip_interfaces:otp_ctrl_top_specific_pkg - lowrisc:ip_interfaces:flash_ctrl_pkg - lowrisc:dv:digestpp_dpi - lowrisc:ip:kmac_pkg files: - - otp_scrambler_pkg.sv - sram_scrambler_pkg.sv - mem_bkdr_util_pkg.sv - mem_bkdr_util.sv: {is_include_file: true} - - mem_bkdr_util__otp.sv: {is_include_file: true} - mem_bkdr_util__rom.sv: {is_include_file: true} - mem_bkdr_util__sram.sv: {is_include_file: true} - mem_bkdr_util__flash.sv: {is_include_file: true} diff --git a/hw/dv/sv/mem_bkdr_util/mem_bkdr_util.sv b/hw/dv/sv/mem_bkdr_util/mem_bkdr_util.sv index e11e3468590f98..88fa04b98cce56 100644 --- a/hw/dv/sv/mem_bkdr_util/mem_bkdr_util.sv +++ b/hw/dv/sv/mem_bkdr_util/mem_bkdr_util.sv @@ -579,9 +579,6 @@ class mem_bkdr_util extends uvm_object; addr, rw_data, err_mask, rw_data ^ err_mask), UVM_HIGH) endfunction - // Wrapper function for backdoor write OTP partitions. - `include "mem_bkdr_util__otp.sv" - // Wrapper functions for encrypted SRAM reads and writes. `include "mem_bkdr_util__sram.sv" diff --git a/hw/dv/sv/mem_bkdr_util/mem_bkdr_util__otp.sv b/hw/dv/sv/mem_bkdr_util/mem_bkdr_util__otp.sv deleted file mode 100644 index 3ce18e438e9ee0..00000000000000 --- a/hw/dv/sv/mem_bkdr_util/mem_bkdr_util__otp.sv +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright lowRISC contributors (OpenTitan project). -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -// Wrapper functions to write different partitions in OTP. -// This file is included in `mem_bkdr_util.sv` as a continuation of `mem_bkdr_util` class. - -virtual function void otp_write_lc_partition_state(lc_ctrl_state_pkg::lc_state_e lc_state); - for (int i = 0; i < LcStateSize; i += 4) begin - write32(i + LcStateOffset, lc_state[i*8+:32]); - end -endfunction : otp_write_lc_partition_state - -virtual function lc_ctrl_state_pkg::lc_state_e otp_read_lc_partition_state(); - lc_ctrl_state_pkg::lc_state_e lc_state; - for (int i = 0; i < LcStateSize; i += 4) begin - lc_state[i*8 +: 32] = read32(i + LcStateOffset); - end - - return lc_state; -endfunction : otp_read_lc_partition_state - -virtual function void otp_write_lc_partition_cnt(lc_ctrl_state_pkg::lc_cnt_e lc_cnt); - for (int i = 0; i < LcTransitionCntSize; i += 4) begin - write32(i + LcTransitionCntOffset, lc_cnt[i*8+:32]); - end -endfunction : otp_write_lc_partition_cnt - -function void otp_write_lc_partition(lc_ctrl_state_pkg::lc_cnt_e lc_cnt, - lc_ctrl_state_pkg::lc_state_e lc_state); - - otp_write_lc_partition_cnt(lc_cnt); - otp_write_lc_partition_state(lc_state); -endfunction : otp_write_lc_partition - -// The following steps are needed to backdoor write a secret partition: -// 1). Scramble the RAW input data. -// 2). Backdoor write the scrambled input data to OTP memory. -// 3). Calculate the correct digest for the secret partition. -// 4). Backdoor write digest data to OTP memory. -virtual function void otp_write_secret0_partition( - bit [TestUnlockTokenSize*8-1:0] unlock_token, - bit [TestExitTokenSize*8-1:0] exit_token); - bit [Secret0DigestSize*8-1:0] digest; - - bit [TestUnlockTokenSize*8-1:0] scrambled_unlock_token; - bit [TestExitTokenSize*8-1:0] scrambled_exit_token; - bit [bus_params_pkg::BUS_DW-1:0] secret_data[$]; - - for (int i = 0; i < TestUnlockTokenSize; i += 8) begin - scrambled_unlock_token[i*8+:64] = scramble_data(unlock_token[i*8+:64], Secret0Idx); - write64(i + TestUnlockTokenOffset, scrambled_unlock_token[i*8+:64]); - end - for (int i = 0; i < TestExitTokenSize; i += 8) begin - scrambled_exit_token[i*8+:64] = scramble_data(exit_token[i*8+:64], Secret0Idx); - write64(i + TestExitTokenOffset, scrambled_exit_token[i*8+:64]); - end - - secret_data = {<<32{scrambled_exit_token, scrambled_unlock_token}}; - digest = cal_digest(Secret0Idx, secret_data); - - write64(Secret0DigestOffset, digest); -endfunction - -virtual function void otp_write_secret1_partition( - bit [FlashAddrKeySeedSize*8-1:0] flash_addr_key_seed, - bit [FlashDataKeySeedSize*8-1:0] flash_data_key_seed, - bit [SramDataKeySeedSize*8-1:0] sram_data_key_seed); - bit [Secret1DigestSize*8-1:0] digest; - - bit [FlashAddrKeySeedSize*8-1:0] scrambled_flash_addr_key; - bit [FlashDataKeySeedSize*8-1:0] scrambled_flash_data_key; - bit [SramDataKeySeedSize*8-1:0] scrambled_sram_data_key; - bit [bus_params_pkg::BUS_DW-1:0] secret_data[$]; - - for (int i = 0; i < FlashAddrKeySeedSize; i += 8) begin - scrambled_flash_addr_key[i*8+:64] = scramble_data(flash_addr_key_seed[i*8+:64], Secret1Idx); - write64(i + FlashAddrKeySeedOffset, scrambled_flash_addr_key[i*8+:64]); - end - for (int i = 0; i < FlashDataKeySeedSize; i += 8) begin - scrambled_flash_data_key[i*8+:64] = scramble_data(flash_data_key_seed[i*8+:64], Secret1Idx); - write64(i + FlashDataKeySeedOffset, scrambled_flash_data_key[i*8+:64]); - end - for (int i = 0; i < SramDataKeySeedSize; i += 8) begin - scrambled_sram_data_key[i*8+:64] = scramble_data(sram_data_key_seed[i*8+:64], Secret1Idx); - write64(i + SramDataKeySeedOffset, scrambled_sram_data_key[i*8+:64]); - end - - secret_data = {<<32 {scrambled_sram_data_key, scrambled_flash_data_key, scrambled_flash_addr_key}}; - digest = cal_digest(Secret1Idx, secret_data); - - write64(Secret1DigestOffset, digest); -endfunction - -virtual function void otp_write_secret2_partition(bit [RmaTokenSize*8-1:0] rma_unlock_token, - bit [CreatorRootKeyShare0Size*8-1:0] creator_root_key0, - bit [CreatorRootKeyShare1Size*8-1:0] creator_root_key1 -); - - bit [Secret2DigestSize*8-1:0] digest; - - bit [RmaTokenSize*8-1:0] scrambled_unlock_token; - bit [CreatorRootKeyShare0Size*8-1:0] scrambled_root_key0; - bit [CreatorRootKeyShare1Size*8-1:0] scrambled_root_key1; - bit [bus_params_pkg::BUS_DW-1:0] secret_data[$]; - - for (int i = 0; i < RmaTokenSize; i+=8) begin - scrambled_unlock_token[i*8+:64] = scramble_data(rma_unlock_token[i*8+:64], Secret2Idx); - write64(i + RmaTokenOffset, scrambled_unlock_token[i*8+:64]); - end - for (int i = 0; i < CreatorRootKeyShare0Size; i+=8) begin - scrambled_root_key0[i*8+:64] = scramble_data(creator_root_key0[i*8+:64], Secret2Idx); - write64(i + CreatorRootKeyShare0Offset, scrambled_root_key0[i*8+:64]); - end - for (int i = 0; i < CreatorRootKeyShare1Size; i+=8) begin - scrambled_root_key1[i*8+:64] = scramble_data(creator_root_key1[i*8+:64], Secret2Idx); - write64(i + CreatorRootKeyShare1Offset, scrambled_root_key1[i*8+:64]); - end - - secret_data = {<<32 {scrambled_root_key1, scrambled_root_key0, scrambled_unlock_token}}; - digest = cal_digest(Secret2Idx, secret_data); - - write64(Secret2DigestOffset, digest); -endfunction - -virtual function void otp_write_hw_cfg0_partition( - bit [DeviceIdSize*8-1:0] device_id, bit [ManufStateSize*8-1:0] manuf_state); - bit [HwCfg0DigestSize*8-1:0] digest; - - bit [bus_params_pkg::BUS_DW-1:0] hw_cfg0_data[$]; - - for (int i = 0; i < DeviceIdSize; i += 4) begin - write32(i + DeviceIdOffset, device_id[i*8+:32]); - end - for (int i = 0; i < ManufStateSize; i += 4) begin - write32(i + ManufStateOffset, manuf_state[i*8+:32]); - end - - hw_cfg0_data = {<<32 {manuf_state, device_id}}; - digest = cal_digest(HwCfg0Idx, hw_cfg0_data); - - write64(HwCfg0DigestOffset, digest); -endfunction - -virtual function void otp_write_hw_cfg1_partition( - bit [EnCsrngSwAppReadSize*8-1:0] en_csrng_sw_app_read, - bit [EnSramIfetchSize*8-1:0] en_sram_ifetch, - bit [EnSramIfetchSize*8-1:0] dis_rv_dm_late_debug); - bit [HwCfg1DigestSize*8-1:0] digest; - - bit [bus_params_pkg::BUS_DW-1:0] hw_cfg1_data[$]; - - write32(EnSramIfetchOffset, {dis_rv_dm_late_debug, en_csrng_sw_app_read, en_sram_ifetch}); - - hw_cfg1_data = {<<32 {32'h0, dis_rv_dm_late_debug, en_csrng_sw_app_read, en_sram_ifetch}}; - digest = cal_digest(HwCfg1Idx, hw_cfg1_data); - - write64(HwCfg1DigestOffset, digest); -endfunction - -// Functions that clear the provisioning state of the buffered partitions. -// This is useful in tests that make front-door accesses for provisioning purposes. -virtual function void otp_clear_secret0_partition(); - for (int i = 0; i < Secret0Size; i += 4) begin - write32(i + Secret0Offset, 32'h0); - end -endfunction - -virtual function void otp_clear_secret1_partition(); - for (int i = 0; i < Secret1Size; i += 4) begin - write32(i + Secret1Offset, 32'h0); - end -endfunction - -virtual function void otp_clear_secret2_partition(); - for (int i = 0; i < Secret2Size; i += 4) begin - write32(i + Secret2Offset, 32'h0); - end -endfunction - -virtual function void otp_clear_hw_cfg0_partition(); - for (int i = 0; i < HwCfg0Size; i += 4) begin - write32(i + HwCfg0Offset, 32'h0); - end -endfunction diff --git a/hw/dv/sv/mem_bkdr_util/mem_bkdr_util_pkg.sv b/hw/dv/sv/mem_bkdr_util/mem_bkdr_util_pkg.sv index 42448d76cba619..75d573d9e923e3 100644 --- a/hw/dv/sv/mem_bkdr_util/mem_bkdr_util_pkg.sv +++ b/hw/dv/sv/mem_bkdr_util/mem_bkdr_util_pkg.sv @@ -10,7 +10,6 @@ package mem_bkdr_util_pkg; import otp_ctrl_part_pkg::*; import otp_ctrl_top_specific_pkg::*; import otp_ctrl_reg_pkg::*; - import otp_scrambler_pkg::*; import prim_secded_pkg::*; import sram_scrambler_pkg::*; import uvm_pkg::*; diff --git a/hw/ip_templates/otp_ctrl/dv/env/otp_ctrl_env.core.tpl b/hw/ip_templates/otp_ctrl/dv/env/otp_ctrl_env.core.tpl index a03ec7bcc37e33..000960282238b2 100644 --- a/hw/ip_templates/otp_ctrl/dv/env/otp_ctrl_env.core.tpl +++ b/hw/ip_templates/otp_ctrl/dv/env/otp_ctrl_env.core.tpl @@ -15,6 +15,7 @@ filesets: - lowrisc:dv:mem_bkdr_util - lowrisc:dv:crypto_dpi_present - lowrisc:dv:lc_ctrl_dv_utils + - ${instance_vlnv("lowrisc:dv:otp_ctrl_mem_bkdr_util:0.1")} files: - otp_ctrl_env_pkg.sv - otp_ctrl_if.sv diff --git a/hw/ip_templates/otp_ctrl/dv/env/otp_ctrl_mem_bkdr_util.core.tpl b/hw/ip_templates/otp_ctrl/dv/env/otp_ctrl_mem_bkdr_util.core.tpl new file mode 100644 index 00000000000000..51fdf33196534f --- /dev/null +++ b/hw/ip_templates/otp_ctrl/dv/env/otp_ctrl_mem_bkdr_util.core.tpl @@ -0,0 +1,25 @@ +CAPI=2: +# Copyright lowRISC contributors (OpenTitan project). +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: ${instance_vlnv("lowrisc:dv:otp_ctrl_mem_bkdr_util:0.1")} +description: "OTP_CTRL mem_bkdr_util support package" +virtual: + - lowrisc:ip_interfaces:otp_ctrl_mem_bkdr_util + +filesets: + files_dv: + depend: + - lowrisc:dv:mem_bkdr_util + - lowrisc:dv:crypto_dpi_present + - lowrisc:dv:lc_ctrl_dv_utils + - ${instance_vlnv("lowrisc:ip:otp_ctrl_top_specific_pkg:1.0")} + files: + - otp_scrambler_pkg.sv + - otp_ctrl_mem_bkdr_util_pkg.sv + file_type: systemVerilogSource + +targets: + default: + filesets: + - files_dv diff --git a/hw/ip_templates/otp_ctrl/dv/env/otp_ctrl_mem_bkdr_util_pkg.sv b/hw/ip_templates/otp_ctrl/dv/env/otp_ctrl_mem_bkdr_util_pkg.sv new file mode 100644 index 00000000000000..6d0ec4e0126eea --- /dev/null +++ b/hw/ip_templates/otp_ctrl/dv/env/otp_ctrl_mem_bkdr_util_pkg.sv @@ -0,0 +1,221 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// This package has functions that perform mem_bkdr_util accesses to different partitions in OTP. +// The functions take a handle to the otp_ctrl mem_bkdr_util class for reads and writes. + +package otp_ctrl_mem_bkdr_util_pkg; + + import otp_ctrl_part_pkg::*; + import otp_ctrl_reg_pkg::*; + import otp_scrambler_pkg::*; + + function automatic void otp_write_lc_partition_state( + mem_bkdr_util_pkg::mem_bkdr_util mem_bkdr_util_h, + lc_ctrl_state_pkg::lc_state_e lc_state + ); + for (int i = 0; i < LcStateSize; i += 4) begin + mem_bkdr_util_h.write32(i + LcStateOffset, lc_state[i*8+:32]); + end + endfunction : otp_write_lc_partition_state + + function automatic lc_ctrl_state_pkg::lc_state_e otp_read_lc_partition_state( + mem_bkdr_util_pkg::mem_bkdr_util mem_bkdr_util_h + ); + lc_ctrl_state_pkg::lc_state_e lc_state; + for (int i = 0; i < LcStateSize; i += 4) begin + lc_state[i*8 +: 32] = mem_bkdr_util_h.read32(i + LcStateOffset); + end + + return lc_state; + endfunction : otp_read_lc_partition_state + + function automatic void otp_write_lc_partition_cnt( + mem_bkdr_util_pkg::mem_bkdr_util mem_bkdr_util_h, + lc_ctrl_state_pkg::lc_cnt_e lc_cnt + ); + for (int i = 0; i < LcTransitionCntSize; i += 4) begin + mem_bkdr_util_h.write32(i + LcTransitionCntOffset, lc_cnt[i*8+:32]); + end + endfunction : otp_write_lc_partition_cnt + + function automatic void otp_write_lc_partition(mem_bkdr_util_pkg::mem_bkdr_util mem_bkdr_util_h, + lc_ctrl_state_pkg::lc_cnt_e lc_cnt, + lc_ctrl_state_pkg::lc_state_e lc_state); + + otp_write_lc_partition_cnt(mem_bkdr_util_h, lc_cnt); + otp_write_lc_partition_state(mem_bkdr_util_h, lc_state); + endfunction : otp_write_lc_partition + + // The following steps are needed to backdoor write a secret partition: + // 1). Scramble the RAW input data. + // 2). Backdoor write the scrambled input data to OTP memory. + // 3). Calculate the correct digest for the secret partition. + // 4). Backdoor write digest data to OTP memory. + function automatic void otp_write_secret0_partition( + mem_bkdr_util_pkg::mem_bkdr_util mem_bkdr_util_h, + bit [TestUnlockTokenSize*8-1:0] unlock_token, + bit [TestExitTokenSize*8-1:0] exit_token + ); + bit [Secret0DigestSize*8-1:0] digest; + + bit [TestUnlockTokenSize*8-1:0] scrambled_unlock_token; + bit [TestExitTokenSize*8-1:0] scrambled_exit_token; + bit [bus_params_pkg::BUS_DW-1:0] secret_data[$]; + + for (int i = 0; i < TestUnlockTokenSize; i += 8) begin + scrambled_unlock_token[i*8+:64] = scramble_data(unlock_token[i*8+:64], Secret0Idx); + mem_bkdr_util_h.write64(i + TestUnlockTokenOffset, scrambled_unlock_token[i*8+:64]); + end + for (int i = 0; i < TestExitTokenSize; i += 8) begin + scrambled_exit_token[i*8+:64] = scramble_data(exit_token[i*8+:64], Secret0Idx); + mem_bkdr_util_h.write64(i + TestExitTokenOffset, scrambled_exit_token[i*8+:64]); + end + + secret_data = {<<32{scrambled_exit_token, scrambled_unlock_token}}; + digest = cal_digest(Secret0Idx, secret_data); + + mem_bkdr_util_h.write64(Secret0DigestOffset, digest); + endfunction + + function automatic void otp_write_secret1_partition( + mem_bkdr_util_pkg::mem_bkdr_util mem_bkdr_util_h, + bit [FlashAddrKeySeedSize*8-1:0] flash_addr_key_seed, + bit [FlashDataKeySeedSize*8-1:0] flash_data_key_seed, + bit [SramDataKeySeedSize*8-1:0] sram_data_key_seed + ); + bit [Secret1DigestSize*8-1:0] digest; + + bit [FlashAddrKeySeedSize*8-1:0] scrambled_flash_addr_key; + bit [FlashDataKeySeedSize*8-1:0] scrambled_flash_data_key; + bit [SramDataKeySeedSize*8-1:0] scrambled_sram_data_key; + bit [bus_params_pkg::BUS_DW-1:0] secret_data[$]; + + for (int i = 0; i < FlashAddrKeySeedSize; i += 8) begin + scrambled_flash_addr_key[i*8+:64] = scramble_data(flash_addr_key_seed[i*8+:64], Secret1Idx); + mem_bkdr_util_h.write64(i + FlashAddrKeySeedOffset, scrambled_flash_addr_key[i*8+:64]); + end + for (int i = 0; i < FlashDataKeySeedSize; i += 8) begin + scrambled_flash_data_key[i*8+:64] = scramble_data(flash_data_key_seed[i*8+:64], Secret1Idx); + mem_bkdr_util_h.write64(i + FlashDataKeySeedOffset, scrambled_flash_data_key[i*8+:64]); + end + for (int i = 0; i < SramDataKeySeedSize; i += 8) begin + scrambled_sram_data_key[i*8+:64] = scramble_data(sram_data_key_seed[i*8+:64], Secret1Idx); + mem_bkdr_util_h.write64(i + SramDataKeySeedOffset, scrambled_sram_data_key[i*8+:64]); + end + + secret_data = {<<32 {scrambled_sram_data_key, scrambled_flash_data_key, + scrambled_flash_addr_key}}; + digest = cal_digest(Secret1Idx, secret_data); + + mem_bkdr_util_h.write64(Secret1DigestOffset, digest); + endfunction + + function automatic void otp_write_secret2_partition( + mem_bkdr_util_pkg::mem_bkdr_util mem_bkdr_util_h, + bit [RmaTokenSize*8-1:0] rma_unlock_token, + bit [CreatorRootKeyShare0Size*8-1:0] creator_root_key0, + bit [CreatorRootKeyShare1Size*8-1:0] creator_root_key1 + ); + + bit [Secret2DigestSize*8-1:0] digest; + + bit [RmaTokenSize*8-1:0] scrambled_unlock_token; + bit [CreatorRootKeyShare0Size*8-1:0] scrambled_root_key0; + bit [CreatorRootKeyShare1Size*8-1:0] scrambled_root_key1; + bit [bus_params_pkg::BUS_DW-1:0] secret_data[$]; + + for (int i = 0; i < RmaTokenSize; i+=8) begin + scrambled_unlock_token[i*8+:64] = scramble_data(rma_unlock_token[i*8+:64], Secret2Idx); + mem_bkdr_util_h.write64(i + RmaTokenOffset, scrambled_unlock_token[i*8+:64]); + end + for (int i = 0; i < CreatorRootKeyShare0Size; i+=8) begin + scrambled_root_key0[i*8+:64] = scramble_data(creator_root_key0[i*8+:64], Secret2Idx); + mem_bkdr_util_h.write64(i + CreatorRootKeyShare0Offset, scrambled_root_key0[i*8+:64]); + end + for (int i = 0; i < CreatorRootKeyShare1Size; i+=8) begin + scrambled_root_key1[i*8+:64] = scramble_data(creator_root_key1[i*8+:64], Secret2Idx); + mem_bkdr_util_h.write64(i + CreatorRootKeyShare1Offset, scrambled_root_key1[i*8+:64]); + end + + secret_data = {<<32 {scrambled_root_key1, scrambled_root_key0, scrambled_unlock_token}}; + digest = cal_digest(Secret2Idx, secret_data); + + mem_bkdr_util_h.write64(Secret2DigestOffset, digest); + endfunction + + function automatic void otp_write_hw_cfg0_partition( + mem_bkdr_util_pkg::mem_bkdr_util mem_bkdr_util_h, + bit [DeviceIdSize*8-1:0] device_id, bit [ManufStateSize*8-1:0] manuf_state + ); + bit [HwCfg0DigestSize*8-1:0] digest; + + bit [bus_params_pkg::BUS_DW-1:0] hw_cfg0_data[$]; + + for (int i = 0; i < DeviceIdSize; i += 4) begin + mem_bkdr_util_h.write32(i + DeviceIdOffset, device_id[i*8+:32]); + end + for (int i = 0; i < ManufStateSize; i += 4) begin + mem_bkdr_util_h.write32(i + ManufStateOffset, manuf_state[i*8+:32]); + end + + hw_cfg0_data = {<<32 {manuf_state, device_id}}; + digest = cal_digest(HwCfg0Idx, hw_cfg0_data); + + mem_bkdr_util_h.write64(HwCfg0DigestOffset, digest); + endfunction + + function automatic void otp_write_hw_cfg1_partition( + mem_bkdr_util_pkg::mem_bkdr_util mem_bkdr_util_h, + bit [EnCsrngSwAppReadSize*8-1:0] en_csrng_sw_app_read, + bit [EnSramIfetchSize*8-1:0] en_sram_ifetch, + bit [EnSramIfetchSize*8-1:0] dis_rv_dm_late_debug + ); + bit [HwCfg1DigestSize*8-1:0] digest; + + bit [bus_params_pkg::BUS_DW-1:0] hw_cfg1_data[$]; + + mem_bkdr_util_h.write32(EnSramIfetchOffset, + {dis_rv_dm_late_debug, en_csrng_sw_app_read, en_sram_ifetch}); + + hw_cfg1_data = {<<32 {32'h0, dis_rv_dm_late_debug, en_csrng_sw_app_read, en_sram_ifetch}}; + digest = cal_digest(HwCfg1Idx, hw_cfg1_data); + + mem_bkdr_util_h.write64(HwCfg1DigestOffset, digest); + endfunction + + // Functions that clear the provisioning state of the buffered partitions. + // This is useful in tests that make front-door accesses for provisioning purposes. + function automatic void otp_clear_secret0_partition( + mem_bkdr_util_pkg::mem_bkdr_util mem_bkdr_util_h + ); + for (int i = 0; i < Secret0Size; i += 4) begin + mem_bkdr_util_h.write32(i + Secret0Offset, 32'h0); + end + endfunction + + function automatic void otp_clear_secret1_partition( + mem_bkdr_util_pkg::mem_bkdr_util mem_bkdr_util_h + ); + for (int i = 0; i < Secret1Size; i += 4) begin + mem_bkdr_util_h.write32(i + Secret1Offset, 32'h0); + end + endfunction + + function automatic void otp_clear_secret2_partition( + mem_bkdr_util_pkg::mem_bkdr_util mem_bkdr_util_h + ); + for (int i = 0; i < Secret2Size; i += 4) begin + mem_bkdr_util_h.write32(i + Secret2Offset, 32'h0); + end + endfunction + + function automatic void otp_clear_hw_cfg0_partition( + mem_bkdr_util_pkg::mem_bkdr_util mem_bkdr_util_h + ); + for (int i = 0; i < HwCfg0Size; i += 4) begin + mem_bkdr_util_h.write32(i + HwCfg0Offset, 32'h0); + end + endfunction +endpackage : otp_ctrl_mem_bkdr_util_pkg diff --git a/hw/dv/sv/mem_bkdr_util/otp_scrambler_pkg.sv b/hw/ip_templates/otp_ctrl/dv/env/otp_scrambler_pkg.sv similarity index 100% rename from hw/dv/sv/mem_bkdr_util/otp_scrambler_pkg.sv rename to hw/ip_templates/otp_ctrl/dv/env/otp_scrambler_pkg.sv diff --git a/hw/top_darjeeling/ip_autogen/otp_ctrl/dv/env/otp_ctrl_env.core b/hw/top_darjeeling/ip_autogen/otp_ctrl/dv/env/otp_ctrl_env.core index c1325aa9f2c068..1745b6993e9bcd 100644 --- a/hw/top_darjeeling/ip_autogen/otp_ctrl/dv/env/otp_ctrl_env.core +++ b/hw/top_darjeeling/ip_autogen/otp_ctrl/dv/env/otp_ctrl_env.core @@ -15,6 +15,7 @@ filesets: - lowrisc:dv:mem_bkdr_util - lowrisc:dv:crypto_dpi_present - lowrisc:dv:lc_ctrl_dv_utils + - lowrisc:opentitan:top_darjeeling_otp_ctrl_mem_bkdr_util:0.1 files: - otp_ctrl_env_pkg.sv - otp_ctrl_if.sv diff --git a/hw/top_darjeeling/ip_autogen/otp_ctrl/dv/env/otp_ctrl_mem_bkdr_util.core b/hw/top_darjeeling/ip_autogen/otp_ctrl/dv/env/otp_ctrl_mem_bkdr_util.core new file mode 100644 index 00000000000000..e947715bd8a938 --- /dev/null +++ b/hw/top_darjeeling/ip_autogen/otp_ctrl/dv/env/otp_ctrl_mem_bkdr_util.core @@ -0,0 +1,25 @@ +CAPI=2: +# Copyright lowRISC contributors (OpenTitan project). +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: lowrisc:opentitan:top_darjeeling_otp_ctrl_mem_bkdr_util:0.1 +description: "OTP_CTRL mem_bkdr_util support package" +virtual: + - lowrisc:ip_interfaces:otp_ctrl_mem_bkdr_util + +filesets: + files_dv: + depend: + - lowrisc:dv:mem_bkdr_util + - lowrisc:dv:crypto_dpi_present + - lowrisc:dv:lc_ctrl_dv_utils + - lowrisc:opentitan:top_darjeeling_otp_ctrl_top_specific_pkg:1.0 + files: + - otp_scrambler_pkg.sv + - otp_ctrl_mem_bkdr_util_pkg.sv + file_type: systemVerilogSource + +targets: + default: + filesets: + - files_dv diff --git a/hw/top_darjeeling/ip_autogen/otp_ctrl/dv/env/otp_ctrl_mem_bkdr_util_pkg.sv b/hw/top_darjeeling/ip_autogen/otp_ctrl/dv/env/otp_ctrl_mem_bkdr_util_pkg.sv new file mode 100644 index 00000000000000..6d0ec4e0126eea --- /dev/null +++ b/hw/top_darjeeling/ip_autogen/otp_ctrl/dv/env/otp_ctrl_mem_bkdr_util_pkg.sv @@ -0,0 +1,221 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// This package has functions that perform mem_bkdr_util accesses to different partitions in OTP. +// The functions take a handle to the otp_ctrl mem_bkdr_util class for reads and writes. + +package otp_ctrl_mem_bkdr_util_pkg; + + import otp_ctrl_part_pkg::*; + import otp_ctrl_reg_pkg::*; + import otp_scrambler_pkg::*; + + function automatic void otp_write_lc_partition_state( + mem_bkdr_util_pkg::mem_bkdr_util mem_bkdr_util_h, + lc_ctrl_state_pkg::lc_state_e lc_state + ); + for (int i = 0; i < LcStateSize; i += 4) begin + mem_bkdr_util_h.write32(i + LcStateOffset, lc_state[i*8+:32]); + end + endfunction : otp_write_lc_partition_state + + function automatic lc_ctrl_state_pkg::lc_state_e otp_read_lc_partition_state( + mem_bkdr_util_pkg::mem_bkdr_util mem_bkdr_util_h + ); + lc_ctrl_state_pkg::lc_state_e lc_state; + for (int i = 0; i < LcStateSize; i += 4) begin + lc_state[i*8 +: 32] = mem_bkdr_util_h.read32(i + LcStateOffset); + end + + return lc_state; + endfunction : otp_read_lc_partition_state + + function automatic void otp_write_lc_partition_cnt( + mem_bkdr_util_pkg::mem_bkdr_util mem_bkdr_util_h, + lc_ctrl_state_pkg::lc_cnt_e lc_cnt + ); + for (int i = 0; i < LcTransitionCntSize; i += 4) begin + mem_bkdr_util_h.write32(i + LcTransitionCntOffset, lc_cnt[i*8+:32]); + end + endfunction : otp_write_lc_partition_cnt + + function automatic void otp_write_lc_partition(mem_bkdr_util_pkg::mem_bkdr_util mem_bkdr_util_h, + lc_ctrl_state_pkg::lc_cnt_e lc_cnt, + lc_ctrl_state_pkg::lc_state_e lc_state); + + otp_write_lc_partition_cnt(mem_bkdr_util_h, lc_cnt); + otp_write_lc_partition_state(mem_bkdr_util_h, lc_state); + endfunction : otp_write_lc_partition + + // The following steps are needed to backdoor write a secret partition: + // 1). Scramble the RAW input data. + // 2). Backdoor write the scrambled input data to OTP memory. + // 3). Calculate the correct digest for the secret partition. + // 4). Backdoor write digest data to OTP memory. + function automatic void otp_write_secret0_partition( + mem_bkdr_util_pkg::mem_bkdr_util mem_bkdr_util_h, + bit [TestUnlockTokenSize*8-1:0] unlock_token, + bit [TestExitTokenSize*8-1:0] exit_token + ); + bit [Secret0DigestSize*8-1:0] digest; + + bit [TestUnlockTokenSize*8-1:0] scrambled_unlock_token; + bit [TestExitTokenSize*8-1:0] scrambled_exit_token; + bit [bus_params_pkg::BUS_DW-1:0] secret_data[$]; + + for (int i = 0; i < TestUnlockTokenSize; i += 8) begin + scrambled_unlock_token[i*8+:64] = scramble_data(unlock_token[i*8+:64], Secret0Idx); + mem_bkdr_util_h.write64(i + TestUnlockTokenOffset, scrambled_unlock_token[i*8+:64]); + end + for (int i = 0; i < TestExitTokenSize; i += 8) begin + scrambled_exit_token[i*8+:64] = scramble_data(exit_token[i*8+:64], Secret0Idx); + mem_bkdr_util_h.write64(i + TestExitTokenOffset, scrambled_exit_token[i*8+:64]); + end + + secret_data = {<<32{scrambled_exit_token, scrambled_unlock_token}}; + digest = cal_digest(Secret0Idx, secret_data); + + mem_bkdr_util_h.write64(Secret0DigestOffset, digest); + endfunction + + function automatic void otp_write_secret1_partition( + mem_bkdr_util_pkg::mem_bkdr_util mem_bkdr_util_h, + bit [FlashAddrKeySeedSize*8-1:0] flash_addr_key_seed, + bit [FlashDataKeySeedSize*8-1:0] flash_data_key_seed, + bit [SramDataKeySeedSize*8-1:0] sram_data_key_seed + ); + bit [Secret1DigestSize*8-1:0] digest; + + bit [FlashAddrKeySeedSize*8-1:0] scrambled_flash_addr_key; + bit [FlashDataKeySeedSize*8-1:0] scrambled_flash_data_key; + bit [SramDataKeySeedSize*8-1:0] scrambled_sram_data_key; + bit [bus_params_pkg::BUS_DW-1:0] secret_data[$]; + + for (int i = 0; i < FlashAddrKeySeedSize; i += 8) begin + scrambled_flash_addr_key[i*8+:64] = scramble_data(flash_addr_key_seed[i*8+:64], Secret1Idx); + mem_bkdr_util_h.write64(i + FlashAddrKeySeedOffset, scrambled_flash_addr_key[i*8+:64]); + end + for (int i = 0; i < FlashDataKeySeedSize; i += 8) begin + scrambled_flash_data_key[i*8+:64] = scramble_data(flash_data_key_seed[i*8+:64], Secret1Idx); + mem_bkdr_util_h.write64(i + FlashDataKeySeedOffset, scrambled_flash_data_key[i*8+:64]); + end + for (int i = 0; i < SramDataKeySeedSize; i += 8) begin + scrambled_sram_data_key[i*8+:64] = scramble_data(sram_data_key_seed[i*8+:64], Secret1Idx); + mem_bkdr_util_h.write64(i + SramDataKeySeedOffset, scrambled_sram_data_key[i*8+:64]); + end + + secret_data = {<<32 {scrambled_sram_data_key, scrambled_flash_data_key, + scrambled_flash_addr_key}}; + digest = cal_digest(Secret1Idx, secret_data); + + mem_bkdr_util_h.write64(Secret1DigestOffset, digest); + endfunction + + function automatic void otp_write_secret2_partition( + mem_bkdr_util_pkg::mem_bkdr_util mem_bkdr_util_h, + bit [RmaTokenSize*8-1:0] rma_unlock_token, + bit [CreatorRootKeyShare0Size*8-1:0] creator_root_key0, + bit [CreatorRootKeyShare1Size*8-1:0] creator_root_key1 + ); + + bit [Secret2DigestSize*8-1:0] digest; + + bit [RmaTokenSize*8-1:0] scrambled_unlock_token; + bit [CreatorRootKeyShare0Size*8-1:0] scrambled_root_key0; + bit [CreatorRootKeyShare1Size*8-1:0] scrambled_root_key1; + bit [bus_params_pkg::BUS_DW-1:0] secret_data[$]; + + for (int i = 0; i < RmaTokenSize; i+=8) begin + scrambled_unlock_token[i*8+:64] = scramble_data(rma_unlock_token[i*8+:64], Secret2Idx); + mem_bkdr_util_h.write64(i + RmaTokenOffset, scrambled_unlock_token[i*8+:64]); + end + for (int i = 0; i < CreatorRootKeyShare0Size; i+=8) begin + scrambled_root_key0[i*8+:64] = scramble_data(creator_root_key0[i*8+:64], Secret2Idx); + mem_bkdr_util_h.write64(i + CreatorRootKeyShare0Offset, scrambled_root_key0[i*8+:64]); + end + for (int i = 0; i < CreatorRootKeyShare1Size; i+=8) begin + scrambled_root_key1[i*8+:64] = scramble_data(creator_root_key1[i*8+:64], Secret2Idx); + mem_bkdr_util_h.write64(i + CreatorRootKeyShare1Offset, scrambled_root_key1[i*8+:64]); + end + + secret_data = {<<32 {scrambled_root_key1, scrambled_root_key0, scrambled_unlock_token}}; + digest = cal_digest(Secret2Idx, secret_data); + + mem_bkdr_util_h.write64(Secret2DigestOffset, digest); + endfunction + + function automatic void otp_write_hw_cfg0_partition( + mem_bkdr_util_pkg::mem_bkdr_util mem_bkdr_util_h, + bit [DeviceIdSize*8-1:0] device_id, bit [ManufStateSize*8-1:0] manuf_state + ); + bit [HwCfg0DigestSize*8-1:0] digest; + + bit [bus_params_pkg::BUS_DW-1:0] hw_cfg0_data[$]; + + for (int i = 0; i < DeviceIdSize; i += 4) begin + mem_bkdr_util_h.write32(i + DeviceIdOffset, device_id[i*8+:32]); + end + for (int i = 0; i < ManufStateSize; i += 4) begin + mem_bkdr_util_h.write32(i + ManufStateOffset, manuf_state[i*8+:32]); + end + + hw_cfg0_data = {<<32 {manuf_state, device_id}}; + digest = cal_digest(HwCfg0Idx, hw_cfg0_data); + + mem_bkdr_util_h.write64(HwCfg0DigestOffset, digest); + endfunction + + function automatic void otp_write_hw_cfg1_partition( + mem_bkdr_util_pkg::mem_bkdr_util mem_bkdr_util_h, + bit [EnCsrngSwAppReadSize*8-1:0] en_csrng_sw_app_read, + bit [EnSramIfetchSize*8-1:0] en_sram_ifetch, + bit [EnSramIfetchSize*8-1:0] dis_rv_dm_late_debug + ); + bit [HwCfg1DigestSize*8-1:0] digest; + + bit [bus_params_pkg::BUS_DW-1:0] hw_cfg1_data[$]; + + mem_bkdr_util_h.write32(EnSramIfetchOffset, + {dis_rv_dm_late_debug, en_csrng_sw_app_read, en_sram_ifetch}); + + hw_cfg1_data = {<<32 {32'h0, dis_rv_dm_late_debug, en_csrng_sw_app_read, en_sram_ifetch}}; + digest = cal_digest(HwCfg1Idx, hw_cfg1_data); + + mem_bkdr_util_h.write64(HwCfg1DigestOffset, digest); + endfunction + + // Functions that clear the provisioning state of the buffered partitions. + // This is useful in tests that make front-door accesses for provisioning purposes. + function automatic void otp_clear_secret0_partition( + mem_bkdr_util_pkg::mem_bkdr_util mem_bkdr_util_h + ); + for (int i = 0; i < Secret0Size; i += 4) begin + mem_bkdr_util_h.write32(i + Secret0Offset, 32'h0); + end + endfunction + + function automatic void otp_clear_secret1_partition( + mem_bkdr_util_pkg::mem_bkdr_util mem_bkdr_util_h + ); + for (int i = 0; i < Secret1Size; i += 4) begin + mem_bkdr_util_h.write32(i + Secret1Offset, 32'h0); + end + endfunction + + function automatic void otp_clear_secret2_partition( + mem_bkdr_util_pkg::mem_bkdr_util mem_bkdr_util_h + ); + for (int i = 0; i < Secret2Size; i += 4) begin + mem_bkdr_util_h.write32(i + Secret2Offset, 32'h0); + end + endfunction + + function automatic void otp_clear_hw_cfg0_partition( + mem_bkdr_util_pkg::mem_bkdr_util mem_bkdr_util_h + ); + for (int i = 0; i < HwCfg0Size; i += 4) begin + mem_bkdr_util_h.write32(i + HwCfg0Offset, 32'h0); + end + endfunction +endpackage : otp_ctrl_mem_bkdr_util_pkg diff --git a/hw/top_darjeeling/ip_autogen/otp_ctrl/dv/env/otp_scrambler_pkg.sv b/hw/top_darjeeling/ip_autogen/otp_ctrl/dv/env/otp_scrambler_pkg.sv new file mode 100644 index 00000000000000..91812a0f0e23d9 --- /dev/null +++ b/hw/top_darjeeling/ip_autogen/otp_ctrl/dv/env/otp_scrambler_pkg.sv @@ -0,0 +1,88 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +///////////////////////////////////////////////// +// OTP secret data and digest scrambling logic // +///////////////////////////////////////////////// + +package otp_scrambler_pkg; + + import uvm_pkg::*; + import otp_ctrl_part_pkg::*; + import bus_params_pkg::*; + + `include "uvm_macros.svh" + + parameter int SCRAMBLE_DATA_SIZE = 64; + parameter int SCRAMBLE_KEY_SIZE = 128; + parameter int NUM_ROUND = 31; + string path = "otp_scrambler_pkg"; + + // When secret data write into otp_array, it will be scrambled. + function automatic bit [SCRAMBLE_DATA_SIZE-1:0] scramble_data( + bit [SCRAMBLE_DATA_SIZE-1:0] input_data, + int part_idx + ); + + int secret_idx = part_idx - Secret0Idx; + crypto_dpi_present_pkg::sv_dpi_present_encrypt(input_data, + RndCnstKey[secret_idx], + SCRAMBLE_KEY_SIZE, + NUM_ROUND, + scramble_data); + endfunction + + // When secret data read out of otp_array, it will be descrambled. + function automatic bit [SCRAMBLE_DATA_SIZE-1:0] descramble_data( + bit [SCRAMBLE_DATA_SIZE-1:0] input_data, + int part_idx + ); + + int secret_idx = part_idx - Secret0Idx; + + crypto_dpi_present_pkg::sv_dpi_present_decrypt(input_data, + RndCnstKey[secret_idx], + SCRAMBLE_KEY_SIZE, + NUM_ROUND, + descramble_data); + endfunction + + function automatic bit [SCRAMBLE_DATA_SIZE-1:0] cal_digest(int part_idx, + ref bit [BUS_DW-1:0] mem_q[$]); + int array_size = mem_q.size(); + real key_factor = SCRAMBLE_KEY_SIZE / BUS_DW; + bit [SCRAMBLE_DATA_SIZE-1:0] init_vec = RndCnstDigestIV[0]; + bit [SCRAMBLE_DATA_SIZE-1:0] enc_data; + bit [SCRAMBLE_DATA_SIZE-1:0] digest; + + for (int i = 0; i < $ceil(array_size / key_factor); i++) begin + bit [SCRAMBLE_DATA_SIZE-1:0] input_data = (i == 0) ? init_vec : digest; + bit [SCRAMBLE_KEY_SIZE-1:0] key; + + // Pad 32-bit partition data into 128-bit key input. + // Because the mem_q size is a multiple of 64-bit, so if the last round only has 64-bits key, + // it will repeat the last 64-bits twice. + for (int j = 0; j < key_factor; j++) begin + int index = i * key_factor + j; + key |= ((index >= array_size ? mem_q[index-2] : mem_q[index]) << (j * BUS_DW)); + end + + // Trigger 32 round of PRESENT encrypt. + crypto_dpi_present_pkg::sv_dpi_present_encrypt(input_data, key, SCRAMBLE_KEY_SIZE, + NUM_ROUND, enc_data); + // XOR the previous state into the digest result according to the Davies-Meyer scheme. + digest = enc_data ^ input_data; + end + + // Last 32 round of digest is calculated with a digest constant. + crypto_dpi_present_pkg::sv_dpi_present_encrypt(digest, + RndCnstDigestConst[0], + SCRAMBLE_KEY_SIZE, NUM_ROUND, + enc_data); + // XOR the previous state into the digest result according to the Davies-Meyer scheme. + digest ^= enc_data; + return digest; + endfunction + +endpackage diff --git a/hw/top_earlgrey/dv/env/chip_env.core b/hw/top_earlgrey/dv/env/chip_env.core index d67e749c998b5b..a31135286bc547 100644 --- a/hw/top_earlgrey/dv/env/chip_env.core +++ b/hw/top_earlgrey/dv/env/chip_env.core @@ -24,6 +24,7 @@ filesets: - lowrisc:dv:jtag_dmi_agent - lowrisc:dv:lc_ctrl_dv_utils - lowrisc:dv:mem_bkdr_util + - lowrisc:opentitan:top_earlgrey_otp_ctrl_mem_bkdr_util - lowrisc:dv:ralgen - lowrisc:dv:spi_agent - lowrisc:dv:spi_host_sva diff --git a/hw/top_earlgrey/dv/env/chip_env_pkg.sv b/hw/top_earlgrey/dv/env/chip_env_pkg.sv index d35be39fa7278b..ae33296fbc35ca 100644 --- a/hw/top_earlgrey/dv/env/chip_env_pkg.sv +++ b/hw/top_earlgrey/dv/env/chip_env_pkg.sv @@ -35,6 +35,7 @@ package chip_env_pkg; import lc_ctrl_state_pkg::*; import lc_ctrl_dv_utils_pkg::*; import mem_bkdr_util_pkg::*; + import otp_ctrl_mem_bkdr_util_pkg::*; import otp_ctrl_pkg::*; import spi_agent_pkg::*; import sram_ctrl_pkg::*; diff --git a/hw/top_earlgrey/dv/env/seq_lib/chip_base_vseq.sv b/hw/top_earlgrey/dv/env/seq_lib/chip_base_vseq.sv index fe206e374ead18..fa66163c01c40d 100644 --- a/hw/top_earlgrey/dv/env/seq_lib/chip_base_vseq.sv +++ b/hw/top_earlgrey/dv/env/seq_lib/chip_base_vseq.sv @@ -135,16 +135,16 @@ class chip_base_vseq #( void'($value$plusargs("otp_clear_secret1=%0d", otp_clear_secret1)); void'($value$plusargs("otp_clear_secret2=%0d", otp_clear_secret2)); if (otp_clear_hw_cfg0) begin - cfg.mem_bkdr_util_h[Otp].otp_clear_hw_cfg0_partition(); + otp_clear_hw_cfg0_partition(cfg.mem_bkdr_util_h[Otp]); end if (otp_clear_secret0) begin - cfg.mem_bkdr_util_h[Otp].otp_clear_secret0_partition(); + otp_clear_secret0_partition(cfg.mem_bkdr_util_h[Otp]); end if (otp_clear_secret1) begin - cfg.mem_bkdr_util_h[Otp].otp_clear_secret1_partition(); + otp_clear_secret1_partition(cfg.mem_bkdr_util_h[Otp]); end if (otp_clear_secret2) begin - cfg.mem_bkdr_util_h[Otp].otp_clear_secret2_partition(); + otp_clear_secret2_partition(cfg.mem_bkdr_util_h[Otp]); end initialize_otp_lc_state(); @@ -316,7 +316,7 @@ class chip_base_vseq #( logic [31:0] chk_vector; // Set rom_exec_en only when we are not in RAW state. - lc_state = cfg.mem_bkdr_util_h[Otp].otp_read_lc_partition_state(); + lc_state = otp_read_lc_partition_state(cfg.mem_bkdr_util_h[Otp]); // If we are already 1, we cannot set to 0. // This should probably be relocated to mem_bkdr_util eventually as an option for writes diff --git a/hw/top_earlgrey/dv/env/seq_lib/chip_prim_tl_access_vseq.sv b/hw/top_earlgrey/dv/env/seq_lib/chip_prim_tl_access_vseq.sv index 6e1718a68ce697..2081aeae627133 100644 --- a/hw/top_earlgrey/dv/env/seq_lib/chip_prim_tl_access_vseq.sv +++ b/hw/top_earlgrey/dv/env/seq_lib/chip_prim_tl_access_vseq.sv @@ -26,7 +26,7 @@ class chip_prim_tl_access_vseq extends chip_stub_cpu_base_vseq; `DV_CHECK_MEMBER_RANDOMIZE_FATAL(lc_state) `uvm_info(`gfn, $sformatf("Configuring via backdoor OTP: lc_state %0s", lc_state.name), UVM_LOW) - cfg.mem_bkdr_util_h[Otp].otp_write_lc_partition_state(lc_state); + otp_write_lc_partition_state(cfg.mem_bkdr_util_h[Otp], lc_state); endfunction virtual function void initialize_otp_lc_state(); diff --git a/hw/top_earlgrey/dv/env/seq_lib/chip_rv_dm_lc_disabled_vseq.sv b/hw/top_earlgrey/dv/env/seq_lib/chip_rv_dm_lc_disabled_vseq.sv index 9cfe7d8aec2b48..da11a19fc0e7a0 100644 --- a/hw/top_earlgrey/dv/env/seq_lib/chip_rv_dm_lc_disabled_vseq.sv +++ b/hw/top_earlgrey/dv/env/seq_lib/chip_rv_dm_lc_disabled_vseq.sv @@ -85,12 +85,13 @@ class chip_rv_dm_lc_disabled_vseq extends chip_stub_cpu_base_vseq; virtual function void backdoor_override_otp(); prim_mubi_pkg::mubi8_t dis_late_dbg = prim_mubi_pkg::MuBi8False; - cfg.mem_bkdr_util_h[Otp].otp_write_lc_partition_state(lc_state); + otp_write_lc_partition_state(cfg.mem_bkdr_util_h[Otp], lc_state); if (dis_late_debug_en_otp) begin dis_late_dbg = prim_mubi_pkg::MuBi8True; end - cfg.mem_bkdr_util_h[Otp].otp_write_hw_cfg1_partition( + otp_write_hw_cfg1_partition( + .mem_bkdr_util_h(cfg.mem_bkdr_util_h[Otp]), .en_sram_ifetch(prim_mubi_pkg::MuBi8False), .en_csrng_sw_app_read(prim_mubi_pkg::MuBi8True), .dis_rv_dm_late_debug(dis_late_dbg)); diff --git a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_csrng_lc_hw_debug_en_vseq.sv b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_csrng_lc_hw_debug_en_vseq.sv index 9b347d4fe4ea9c..1c08879d6312b0 100644 --- a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_csrng_lc_hw_debug_en_vseq.sv +++ b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_csrng_lc_hw_debug_en_vseq.sv @@ -44,9 +44,11 @@ class chip_sw_csrng_lc_hw_debug_en_vseq extends chip_sw_base_vseq; // Make sure entropy_src and csrng fuses are setup correctly independent // of which OTP image was loaded. The C portion of this test checks the // lc states across resets. - cfg.mem_bkdr_util_h[Otp].otp_write_hw_cfg0_partition( + otp_write_hw_cfg0_partition( + .mem_bkdr_util_h(cfg.mem_bkdr_util_h[Otp]), .device_id(DEVICE_ID), .manuf_state(MANUF_STATE)); - cfg.mem_bkdr_util_h[Otp].otp_write_hw_cfg1_partition( + otp_write_hw_cfg1_partition( + .mem_bkdr_util_h(cfg.mem_bkdr_util_h[Otp]), .en_sram_ifetch(MUBI8FALSE), .en_csrng_sw_app_read(MUBI8TRUE), .dis_rv_dm_late_debug(MUBI8TRUE)); endtask diff --git a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_entropy_src_fuse_vseq.sv b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_entropy_src_fuse_vseq.sv index d11acd1ebd500b..dca0969a7ee6db 100644 --- a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_entropy_src_fuse_vseq.sv +++ b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_entropy_src_fuse_vseq.sv @@ -20,9 +20,11 @@ class chip_sw_entropy_src_fuse_vseq extends chip_sw_base_vseq; virtual task dut_init(string reset_kind = "HARD"); super.dut_init(reset_kind); - cfg.mem_bkdr_util_h[Otp].otp_write_hw_cfg0_partition( + otp_write_hw_cfg0_partition( + .mem_bkdr_util_h(cfg.mem_bkdr_util_h[Otp]), .device_id(DEVICE_ID), .manuf_state(MANUF_STATE)); - cfg.mem_bkdr_util_h[Otp].otp_write_hw_cfg1_partition( + otp_write_hw_cfg1_partition( + .mem_bkdr_util_h(cfg.mem_bkdr_util_h[Otp]), .en_sram_ifetch(MUBI8FALSE), .en_csrng_sw_app_read(MUBI8TRUE), .dis_rv_dm_late_debug(MUBI8TRUE)); endtask @@ -36,9 +38,11 @@ class chip_sw_entropy_src_fuse_vseq extends chip_sw_base_vseq; 20_000_000) if (cfg.sw_logger_vif.printed_log == "Software resetting!") begin - cfg.mem_bkdr_util_h[Otp].otp_write_hw_cfg0_partition( + otp_write_hw_cfg0_partition( + .mem_bkdr_util_h(cfg.mem_bkdr_util_h[Otp]), .device_id(DEVICE_ID), .manuf_state(MANUF_STATE)); - cfg.mem_bkdr_util_h[Otp].otp_write_hw_cfg1_partition( + otp_write_hw_cfg1_partition( + .mem_bkdr_util_h(cfg.mem_bkdr_util_h[Otp]), .en_sram_ifetch(MUBI8FALSE), .en_csrng_sw_app_read(MUBI8FALSE), .dis_rv_dm_late_debug(MUBI8TRUE)); break; diff --git a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_exit_test_unlocked_bootstrap_vseq.sv b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_exit_test_unlocked_bootstrap_vseq.sv index ce308688fae9f9..c6d0d571eea88c 100644 --- a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_exit_test_unlocked_bootstrap_vseq.sv +++ b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_exit_test_unlocked_bootstrap_vseq.sv @@ -19,12 +19,11 @@ class chip_sw_exit_test_unlocked_bootstrap_vseq extends chip_sw_base_vseq; super.dut_init(reset_kind); // make sure we are in one of the unlocked states - cfg.mem_bkdr_util_h[Otp].otp_write_lc_partition_state(UnlockedStates[unlocked_idx].lc_state); + otp_write_lc_partition_state(cfg.mem_bkdr_util_h[Otp], UnlockedStates[unlocked_idx].lc_state); // backdoorload the otp tokens and associated digest otp_exit_token_bits = dec_otp_token_from_lc_csrs(lc_exit_token); - cfg.mem_bkdr_util_h[Otp].otp_write_secret0_partition( - '0, otp_exit_token_bits); + otp_write_secret0_partition(cfg.mem_bkdr_util_h[Otp], '0, otp_exit_token_bits); //ensure rom_exec_en is 0, so that flash is never reached cfg.mem_bkdr_util_h[Otp].write32(otp_ctrl_reg_pkg::CreatorSwCfgRomExecEnOffset, 0); diff --git a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_flash_ctrl_lc_rw_en_vseq.sv b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_flash_ctrl_lc_rw_en_vseq.sv index 48acab57345799..735655ec9e130c 100644 --- a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_flash_ctrl_lc_rw_en_vseq.sv +++ b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_flash_ctrl_lc_rw_en_vseq.sv @@ -19,7 +19,7 @@ class chip_sw_flash_ctrl_lc_rw_en_vseq extends chip_sw_base_vseq; virtual task dut_init(string reset_kind = "HARD"); super.dut_init(reset_kind); // Override the LC partition to TestLocked state. - cfg.mem_bkdr_util_h[Otp].otp_write_lc_partition_state(LcStTestLocked2); + otp_write_lc_partition_state(cfg.mem_bkdr_util_h[Otp], LcStTestLocked2); endtask virtual function lc_ctrl_pkg::lc_tx_t get_rw_en_signals(int rw_en_index); @@ -46,7 +46,7 @@ class chip_sw_flash_ctrl_lc_rw_en_vseq extends chip_sw_base_vseq; // LC state changed to Dev. and reset, CPU will now be enabled. - cfg.mem_bkdr_util_h[Otp].otp_write_lc_partition_state(LcStDev); + otp_write_lc_partition_state(cfg.mem_bkdr_util_h[Otp], LcStDev); apply_reset(); `DV_WAIT(cfg.sw_test_status_vif.sw_test_status == SwTestStatusInTest, 50_000_000) @@ -54,7 +54,7 @@ class chip_sw_flash_ctrl_lc_rw_en_vseq extends chip_sw_base_vseq; // LC state changed to Prod. - cfg.mem_bkdr_util_h[Otp].otp_write_lc_partition_state(LcStProd); + otp_write_lc_partition_state(cfg.mem_bkdr_util_h[Otp], LcStProd); apply_reset(); `DV_WAIT(cfg.sw_test_status_vif.sw_test_status == SwTestStatusInTest) @@ -62,7 +62,7 @@ class chip_sw_flash_ctrl_lc_rw_en_vseq extends chip_sw_base_vseq; // LC state changed to Scrap. CPU not enabled so do the checks directly. - cfg.mem_bkdr_util_h[Otp].otp_write_lc_partition_state(LcStScrap); + otp_write_lc_partition_state(cfg.mem_bkdr_util_h[Otp], LcStScrap); apply_reset(); for (int i = 0; i < 5; i++) begin diff --git a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_flash_init_vseq.sv b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_flash_init_vseq.sv index 5c9b145be4923b..cb52a7e9ce01da 100644 --- a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_flash_init_vseq.sv +++ b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_flash_init_vseq.sv @@ -125,7 +125,8 @@ class chip_sw_flash_init_vseq extends chip_sw_base_vseq; virtual task randomize_keys(); `DV_CHECK_STD_RANDOMIZE_FATAL(secret_flash_addr_key) `DV_CHECK_STD_RANDOMIZE_FATAL(secret_flash_data_key) - cfg.mem_bkdr_util_h[Otp].otp_write_secret1_partition( + otp_write_secret1_partition( + .mem_bkdr_util_h(cfg.mem_bkdr_util_h[Otp]), .flash_addr_key_seed(get_flash_otp_key(secret_flash_addr_key)), .flash_data_key_seed(get_flash_otp_key(secret_flash_data_key)), .sram_data_key_seed(get_sram_otp_key(secret_sram_key))); @@ -296,7 +297,7 @@ class chip_sw_flash_init_vseq extends chip_sw_base_vseq; join_none // Allow most test phases to write seed partition, but do not allow hardware to read - cfg.mem_bkdr_util_h[Otp].otp_write_lc_partition_state(LcStProd); + otp_write_lc_partition_state(cfg.mem_bkdr_util_h[Otp], LcStProd); cfg.mem_bkdr_util_h[Otp].write64(otp_ctrl_reg_pkg::Secret2DigestOffset, 0); // Looping through all test phases. @@ -331,7 +332,8 @@ class chip_sw_flash_init_vseq extends chip_sw_base_vseq; UVM_LOW) // The actual data is irrelevant as long as the partition becomes locked. - cfg.mem_bkdr_util_h[Otp].otp_write_secret2_partition( + otp_write_secret2_partition( + .mem_bkdr_util_h(cfg.mem_bkdr_util_h[Otp]), .rma_unlock_token('0), .creator_root_key0('0), .creator_root_key1('0)); end diff --git a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_flash_rma_unlocked_vseq.sv b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_flash_rma_unlocked_vseq.sv index fcd84d4335b1e3..10c7f3e9bbc07e 100644 --- a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_flash_rma_unlocked_vseq.sv +++ b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_flash_rma_unlocked_vseq.sv @@ -64,13 +64,15 @@ class chip_sw_flash_rma_unlocked_vseq extends chip_sw_base_vseq; // Flip a coin and either select Dev or Prod to start and override the state in OTP. if ($urandom_range(0, 1)) src_lc_state = DecLcStDev; else src_lc_state = DecLcStProd; - cfg.mem_bkdr_util_h[Otp].otp_write_lc_partition_state(encode_lc_state(src_lc_state)); + otp_write_lc_partition_state(cfg.mem_bkdr_util_h[Otp], encode_lc_state(src_lc_state)); // Override Device ID and Manufacturing state with random values. - cfg.mem_bkdr_util_h[Otp].otp_write_hw_cfg0_partition( + otp_write_hw_cfg0_partition( + .mem_bkdr_util_h(cfg.mem_bkdr_util_h[Otp]), .device_id(device_id), .manuf_state(manuf_state)); - cfg.mem_bkdr_util_h[Otp].otp_write_hw_cfg1_partition( + otp_write_hw_cfg1_partition( + .mem_bkdr_util_h(cfg.mem_bkdr_util_h[Otp]), // Use same default config as in otp_ctrl_img_hw_cfg.hjson .en_sram_ifetch(prim_mubi_pkg::MuBi8False), .en_csrng_sw_app_read(prim_mubi_pkg::MuBi8True), @@ -143,7 +145,8 @@ class chip_sw_flash_rma_unlocked_vseq extends chip_sw_base_vseq; virtual task provision_secret2_partition(); // Override the rma unlock token to match SW test's input token. - cfg.mem_bkdr_util_h[Otp].otp_write_secret2_partition( + otp_write_secret2_partition( + .mem_bkdr_util_h(cfg.mem_bkdr_util_h[Otp]), .rma_unlock_token(dec_otp_token_from_lc_csrs(rma_unlock_token)), .creator_root_key0(get_otp_key(creator_root_key0)), .creator_root_key1(get_otp_key(creator_root_key1))); diff --git a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_inject_scramble_seed_vseq.sv b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_inject_scramble_seed_vseq.sv index 9c510b06dddb32..0053db69537824 100644 --- a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_inject_scramble_seed_vseq.sv +++ b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_inject_scramble_seed_vseq.sv @@ -33,7 +33,7 @@ class chip_sw_inject_scramble_seed_vseq extends chip_sw_base_vseq; // make sure we are in prod state - cfg.mem_bkdr_util_h[Otp].otp_write_lc_partition_state(LcStProd); + otp_write_lc_partition_state(cfg.mem_bkdr_util_h[Otp], LcStProd); // Randomize the expected data and write it into flash. `DV_CHECK_STD_RANDOMIZE_FATAL(iso_part_data); diff --git a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_keymgr_key_derivation_vseq.sv b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_keymgr_key_derivation_vseq.sv index e5bd33e3738376..4462c5e3b9be63 100644 --- a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_keymgr_key_derivation_vseq.sv +++ b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_keymgr_key_derivation_vseq.sv @@ -104,7 +104,7 @@ class chip_sw_keymgr_key_derivation_vseq extends chip_sw_base_vseq; super.dut_init(reset_kind); void'($value$plusargs("lc_at_prod=%0d", lc_at_prod)); if (lc_at_prod) begin - cfg.mem_bkdr_util_h[Otp].otp_write_lc_partition_state(LcStProd); + otp_write_lc_partition_state(cfg.mem_bkdr_util_h[Otp], LcStProd); end endtask diff --git a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_lc_base_vseq.sv b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_lc_base_vseq.sv index 7264f8084ee4d6..21e2038d32b026 100644 --- a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_lc_base_vseq.sv +++ b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_lc_base_vseq.sv @@ -23,7 +23,8 @@ class chip_sw_lc_base_vseq extends chip_sw_base_vseq; virtual function void backdoor_override_otp(); // Override the LC partition to TestLocked1 state. if (init_lc_state != DecLcStInvalid) begin - cfg.mem_bkdr_util_h[Otp].otp_write_lc_partition_state( + otp_write_lc_partition_state( + cfg.mem_bkdr_util_h[Otp], lc_ctrl_dv_utils_pkg::encode_lc_state(init_lc_state)); end endfunction : backdoor_override_otp diff --git a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_lc_ctrl_scrap_vseq.sv b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_lc_ctrl_scrap_vseq.sv index bb93968fb3d461..85649dea932d65 100644 --- a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_lc_ctrl_scrap_vseq.sv +++ b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_lc_ctrl_scrap_vseq.sv @@ -51,7 +51,8 @@ class chip_sw_lc_ctrl_scrap_vseq extends chip_sw_lc_base_vseq; virtual function void backdoor_override_otp(); // Override the LC partition to TestLocked1 state. - cfg.mem_bkdr_util_h[Otp].otp_write_lc_partition_state( + otp_write_lc_partition_state( + cfg.mem_bkdr_util_h[Otp], lc_ctrl_dv_utils_pkg::encode_lc_state(src_state)); endfunction : backdoor_override_otp diff --git a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_lc_ctrl_transition_vseq.sv b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_lc_ctrl_transition_vseq.sv index ac89a1700040a2..eff1e0a3491614 100644 --- a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_lc_ctrl_transition_vseq.sv +++ b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_lc_ctrl_transition_vseq.sv @@ -19,10 +19,11 @@ class chip_sw_lc_ctrl_transition_vseq extends chip_sw_lc_base_vseq; virtual function void backdoor_override_otp(); // Override the LC partition to TestLocked1 state. - cfg.mem_bkdr_util_h[Otp].otp_write_lc_partition_state(LcStTestLocked1); + otp_write_lc_partition_state(cfg.mem_bkdr_util_h[Otp], LcStTestLocked1); // Override the test exit token to match SW test's input token. - cfg.mem_bkdr_util_h[Otp].otp_write_secret0_partition( + otp_write_secret0_partition( + .mem_bkdr_util_h(cfg.mem_bkdr_util_h[Otp]), .unlock_token(dec_otp_token_from_lc_csrs(lc_unlock_token)), .exit_token(dec_otp_token_from_lc_csrs(lc_exit_token))); endfunction diff --git a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_otp_ctrl_vendor_test_csr_access_vseq.sv b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_otp_ctrl_vendor_test_csr_access_vseq.sv index 87b661bd0af580..e508314ed4fe85 100644 --- a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_otp_ctrl_vendor_test_csr_access_vseq.sv +++ b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_otp_ctrl_vendor_test_csr_access_vseq.sv @@ -30,7 +30,7 @@ class chip_sw_otp_ctrl_vendor_test_csr_access_vseq extends chip_sw_base_vseq; endtask virtual function void backdoor_override_otp(); - cfg.mem_bkdr_util_h[Otp].otp_write_lc_partition_state(lc_state); + otp_write_lc_partition_state(cfg.mem_bkdr_util_h[Otp], lc_state); endfunction virtual task dut_init(string reset_kind = "HARD"); diff --git a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_rom_ctrl_integrity_check_vseq.sv b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_rom_ctrl_integrity_check_vseq.sv index 5a943bb554d6d6..99c8929fd05cf3 100644 --- a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_rom_ctrl_integrity_check_vseq.sv +++ b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_rom_ctrl_integrity_check_vseq.sv @@ -28,7 +28,7 @@ class chip_sw_rom_ctrl_integrity_check_vseq extends chip_sw_base_vseq; `DV_WAIT(cfg.sw_test_status_vif.sw_test_status == SwTestStatusInWfi) // Update the lc state to a production state and reboot the chip. - cfg.mem_bkdr_util_h[Otp].otp_write_lc_partition_state(lc_ctrl_state_pkg::LcStProd); + otp_write_lc_partition_state(cfg.mem_bkdr_util_h[Otp], lc_ctrl_state_pkg::LcStProd); apply_reset(); // At this point, a successful boot would be an error. We will start a parallel timeout thread diff --git a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_rom_e2e_asm_init_vseq.sv b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_rom_e2e_asm_init_vseq.sv index e9cdd3e1efbe05..a17e153b6c7522 100644 --- a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_rom_e2e_asm_init_vseq.sv +++ b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_rom_e2e_asm_init_vseq.sv @@ -26,7 +26,7 @@ class chip_sw_rom_e2e_asm_init_vseq extends chip_sw_base_vseq; endfunction virtual task body(); - lc_ctrl_state_pkg::lc_state_e lc_state = cfg.mem_bkdr_util_h[Otp].otp_read_lc_partition_state(); + lc_ctrl_state_pkg::lc_state_e lc_state = otp_read_lc_partition_state(cfg.mem_bkdr_util_h[Otp]); bit [31:0] otp_creator_sw_cfg_ast_init_en = 32'b0; bit [31:0] otp_creator_sw_cfg_jitter_en = 32'b0; diff --git a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_rom_e2e_shutdown_output_vseq.sv b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_rom_e2e_shutdown_output_vseq.sv index 9b4cd4971d02f7..454b9fd969816b 100644 --- a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_rom_e2e_shutdown_output_vseq.sv +++ b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_rom_e2e_shutdown_output_vseq.sv @@ -13,7 +13,7 @@ class chip_sw_rom_e2e_shutdown_output_vseq extends foreach (lc_state_2_rom_lcv[lc_state]) begin `uvm_info(`gfn, $sformatf("Backdoor overwriting the lifecycle state and applying POR ..."), UVM_LOW) - cfg.mem_bkdr_util_h[Otp].otp_write_lc_partition_state(lc_state); + otp_write_lc_partition_state(cfg.mem_bkdr_util_h[Otp], lc_state); apply_reset(); // Wait for retention SRAM initialization to be done before hooking up the UART agent to diff --git a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_rom_e2e_sigverify_always_a_bad_b_bad_vseq.sv b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_rom_e2e_sigverify_always_a_bad_b_bad_vseq.sv index 9a1c3abb2d6c20..ccdb46650047af 100644 --- a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_rom_e2e_sigverify_always_a_bad_b_bad_vseq.sv +++ b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_rom_e2e_sigverify_always_a_bad_b_bad_vseq.sv @@ -12,7 +12,7 @@ class chip_sw_rom_e2e_sigverify_always_a_bad_b_bad_vseq extends virtual task body(); super.body(); connect_rom_uart_agent(); - lc_state = cfg.mem_bkdr_util_h[Otp].otp_read_lc_partition_state(); + lc_state = otp_read_lc_partition_state(cfg.mem_bkdr_util_h[Otp]); check_uart_output_msg($sformatf("%0s\x0d\n", ROM_BANNER)); check_uart_output_msg( $sformatf("BFV:%0s\x0d\nLCV:%0s\x0d\n", ROM_BFV_BAD_ECDSA_SIGNATURE, diff --git a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_sram_ctrl_execution_main_vseq.sv b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_sram_ctrl_execution_main_vseq.sv index 34f7d6d3fce0b0..4162b0914781e0 100644 --- a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_sram_ctrl_execution_main_vseq.sv +++ b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_sram_ctrl_execution_main_vseq.sv @@ -21,11 +21,13 @@ class chip_sw_sram_ctrl_execution_main_vseq extends chip_sw_base_vseq; apply_reset(); if (set_prod_lc) begin - cfg.mem_bkdr_util_h[Otp].otp_write_lc_partition_state(LcStProd); + otp_write_lc_partition_state(cfg.mem_bkdr_util_h[Otp], LcStProd); end - cfg.mem_bkdr_util_h[Otp].otp_write_hw_cfg0_partition( + otp_write_hw_cfg0_partition( + .mem_bkdr_util_h(cfg.mem_bkdr_util_h[Otp]), .device_id(DEVICE_ID), .manuf_state(MANUF_STATE)); - cfg.mem_bkdr_util_h[Otp].otp_write_hw_cfg1_partition( + otp_write_hw_cfg1_partition( + .mem_bkdr_util_h(cfg.mem_bkdr_util_h[Otp]), .en_sram_ifetch(en_sram_ifetch), .en_csrng_sw_app_read(EN_CSRNG_SW_APP_READ), .dis_rv_dm_late_debug(DIS_RV_DM_LATE_DEBUG)); diff --git a/hw/top_earlgrey/dv/env/seq_lib/chip_tap_straps_vseq.sv b/hw/top_earlgrey/dv/env/seq_lib/chip_tap_straps_vseq.sv index 362f743619fa1e..9bd03b438a19b9 100644 --- a/hw/top_earlgrey/dv/env/seq_lib/chip_tap_straps_vseq.sv +++ b/hw/top_earlgrey/dv/env/seq_lib/chip_tap_straps_vseq.sv @@ -66,12 +66,12 @@ class chip_tap_straps_vseq extends chip_sw_base_vseq; super.dut_init(reset_kind); - cur_lc_state = cfg.mem_bkdr_util_h[Otp].otp_read_lc_partition_state(); + cur_lc_state = otp_read_lc_partition_state(cfg.mem_bkdr_util_h[Otp]); // in LcStProd, we can only select LC tap at boot. // If it's not LC tap, effectively, no tap is selected. if (cur_lc_state == LcStProd) begin - cfg.mem_bkdr_util_h[Otp].otp_write_lc_partition_state(LcStProd); + otp_write_lc_partition_state(cfg.mem_bkdr_util_h[Otp], LcStProd); // In Dev state, only pin0 of select_jtag is sampled. When it's set, select LC tap if (select_jtag[0] == 0) select_jtag = JtagTapNone; else select_jtag = JtagTapLc; diff --git a/hw/top_earlgrey/ip_autogen/otp_ctrl/dv/env/otp_ctrl_env.core b/hw/top_earlgrey/ip_autogen/otp_ctrl/dv/env/otp_ctrl_env.core index 7e4e044ac275b4..27832d434ac1ac 100644 --- a/hw/top_earlgrey/ip_autogen/otp_ctrl/dv/env/otp_ctrl_env.core +++ b/hw/top_earlgrey/ip_autogen/otp_ctrl/dv/env/otp_ctrl_env.core @@ -15,6 +15,7 @@ filesets: - lowrisc:dv:mem_bkdr_util - lowrisc:dv:crypto_dpi_present - lowrisc:dv:lc_ctrl_dv_utils + - lowrisc:opentitan:top_earlgrey_otp_ctrl_mem_bkdr_util:0.1 files: - otp_ctrl_env_pkg.sv - otp_ctrl_if.sv diff --git a/hw/top_earlgrey/ip_autogen/otp_ctrl/dv/env/otp_ctrl_mem_bkdr_util.core b/hw/top_earlgrey/ip_autogen/otp_ctrl/dv/env/otp_ctrl_mem_bkdr_util.core new file mode 100644 index 00000000000000..9ece5ffaf87b13 --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/otp_ctrl/dv/env/otp_ctrl_mem_bkdr_util.core @@ -0,0 +1,25 @@ +CAPI=2: +# Copyright lowRISC contributors (OpenTitan project). +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: lowrisc:opentitan:top_earlgrey_otp_ctrl_mem_bkdr_util:0.1 +description: "OTP_CTRL mem_bkdr_util support package" +virtual: + - lowrisc:ip_interfaces:otp_ctrl_mem_bkdr_util + +filesets: + files_dv: + depend: + - lowrisc:dv:mem_bkdr_util + - lowrisc:dv:crypto_dpi_present + - lowrisc:dv:lc_ctrl_dv_utils + - lowrisc:opentitan:top_earlgrey_otp_ctrl_top_specific_pkg:1.0 + files: + - otp_scrambler_pkg.sv + - otp_ctrl_mem_bkdr_util_pkg.sv + file_type: systemVerilogSource + +targets: + default: + filesets: + - files_dv diff --git a/hw/top_earlgrey/ip_autogen/otp_ctrl/dv/env/otp_ctrl_mem_bkdr_util_pkg.sv b/hw/top_earlgrey/ip_autogen/otp_ctrl/dv/env/otp_ctrl_mem_bkdr_util_pkg.sv new file mode 100644 index 00000000000000..6d0ec4e0126eea --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/otp_ctrl/dv/env/otp_ctrl_mem_bkdr_util_pkg.sv @@ -0,0 +1,221 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// This package has functions that perform mem_bkdr_util accesses to different partitions in OTP. +// The functions take a handle to the otp_ctrl mem_bkdr_util class for reads and writes. + +package otp_ctrl_mem_bkdr_util_pkg; + + import otp_ctrl_part_pkg::*; + import otp_ctrl_reg_pkg::*; + import otp_scrambler_pkg::*; + + function automatic void otp_write_lc_partition_state( + mem_bkdr_util_pkg::mem_bkdr_util mem_bkdr_util_h, + lc_ctrl_state_pkg::lc_state_e lc_state + ); + for (int i = 0; i < LcStateSize; i += 4) begin + mem_bkdr_util_h.write32(i + LcStateOffset, lc_state[i*8+:32]); + end + endfunction : otp_write_lc_partition_state + + function automatic lc_ctrl_state_pkg::lc_state_e otp_read_lc_partition_state( + mem_bkdr_util_pkg::mem_bkdr_util mem_bkdr_util_h + ); + lc_ctrl_state_pkg::lc_state_e lc_state; + for (int i = 0; i < LcStateSize; i += 4) begin + lc_state[i*8 +: 32] = mem_bkdr_util_h.read32(i + LcStateOffset); + end + + return lc_state; + endfunction : otp_read_lc_partition_state + + function automatic void otp_write_lc_partition_cnt( + mem_bkdr_util_pkg::mem_bkdr_util mem_bkdr_util_h, + lc_ctrl_state_pkg::lc_cnt_e lc_cnt + ); + for (int i = 0; i < LcTransitionCntSize; i += 4) begin + mem_bkdr_util_h.write32(i + LcTransitionCntOffset, lc_cnt[i*8+:32]); + end + endfunction : otp_write_lc_partition_cnt + + function automatic void otp_write_lc_partition(mem_bkdr_util_pkg::mem_bkdr_util mem_bkdr_util_h, + lc_ctrl_state_pkg::lc_cnt_e lc_cnt, + lc_ctrl_state_pkg::lc_state_e lc_state); + + otp_write_lc_partition_cnt(mem_bkdr_util_h, lc_cnt); + otp_write_lc_partition_state(mem_bkdr_util_h, lc_state); + endfunction : otp_write_lc_partition + + // The following steps are needed to backdoor write a secret partition: + // 1). Scramble the RAW input data. + // 2). Backdoor write the scrambled input data to OTP memory. + // 3). Calculate the correct digest for the secret partition. + // 4). Backdoor write digest data to OTP memory. + function automatic void otp_write_secret0_partition( + mem_bkdr_util_pkg::mem_bkdr_util mem_bkdr_util_h, + bit [TestUnlockTokenSize*8-1:0] unlock_token, + bit [TestExitTokenSize*8-1:0] exit_token + ); + bit [Secret0DigestSize*8-1:0] digest; + + bit [TestUnlockTokenSize*8-1:0] scrambled_unlock_token; + bit [TestExitTokenSize*8-1:0] scrambled_exit_token; + bit [bus_params_pkg::BUS_DW-1:0] secret_data[$]; + + for (int i = 0; i < TestUnlockTokenSize; i += 8) begin + scrambled_unlock_token[i*8+:64] = scramble_data(unlock_token[i*8+:64], Secret0Idx); + mem_bkdr_util_h.write64(i + TestUnlockTokenOffset, scrambled_unlock_token[i*8+:64]); + end + for (int i = 0; i < TestExitTokenSize; i += 8) begin + scrambled_exit_token[i*8+:64] = scramble_data(exit_token[i*8+:64], Secret0Idx); + mem_bkdr_util_h.write64(i + TestExitTokenOffset, scrambled_exit_token[i*8+:64]); + end + + secret_data = {<<32{scrambled_exit_token, scrambled_unlock_token}}; + digest = cal_digest(Secret0Idx, secret_data); + + mem_bkdr_util_h.write64(Secret0DigestOffset, digest); + endfunction + + function automatic void otp_write_secret1_partition( + mem_bkdr_util_pkg::mem_bkdr_util mem_bkdr_util_h, + bit [FlashAddrKeySeedSize*8-1:0] flash_addr_key_seed, + bit [FlashDataKeySeedSize*8-1:0] flash_data_key_seed, + bit [SramDataKeySeedSize*8-1:0] sram_data_key_seed + ); + bit [Secret1DigestSize*8-1:0] digest; + + bit [FlashAddrKeySeedSize*8-1:0] scrambled_flash_addr_key; + bit [FlashDataKeySeedSize*8-1:0] scrambled_flash_data_key; + bit [SramDataKeySeedSize*8-1:0] scrambled_sram_data_key; + bit [bus_params_pkg::BUS_DW-1:0] secret_data[$]; + + for (int i = 0; i < FlashAddrKeySeedSize; i += 8) begin + scrambled_flash_addr_key[i*8+:64] = scramble_data(flash_addr_key_seed[i*8+:64], Secret1Idx); + mem_bkdr_util_h.write64(i + FlashAddrKeySeedOffset, scrambled_flash_addr_key[i*8+:64]); + end + for (int i = 0; i < FlashDataKeySeedSize; i += 8) begin + scrambled_flash_data_key[i*8+:64] = scramble_data(flash_data_key_seed[i*8+:64], Secret1Idx); + mem_bkdr_util_h.write64(i + FlashDataKeySeedOffset, scrambled_flash_data_key[i*8+:64]); + end + for (int i = 0; i < SramDataKeySeedSize; i += 8) begin + scrambled_sram_data_key[i*8+:64] = scramble_data(sram_data_key_seed[i*8+:64], Secret1Idx); + mem_bkdr_util_h.write64(i + SramDataKeySeedOffset, scrambled_sram_data_key[i*8+:64]); + end + + secret_data = {<<32 {scrambled_sram_data_key, scrambled_flash_data_key, + scrambled_flash_addr_key}}; + digest = cal_digest(Secret1Idx, secret_data); + + mem_bkdr_util_h.write64(Secret1DigestOffset, digest); + endfunction + + function automatic void otp_write_secret2_partition( + mem_bkdr_util_pkg::mem_bkdr_util mem_bkdr_util_h, + bit [RmaTokenSize*8-1:0] rma_unlock_token, + bit [CreatorRootKeyShare0Size*8-1:0] creator_root_key0, + bit [CreatorRootKeyShare1Size*8-1:0] creator_root_key1 + ); + + bit [Secret2DigestSize*8-1:0] digest; + + bit [RmaTokenSize*8-1:0] scrambled_unlock_token; + bit [CreatorRootKeyShare0Size*8-1:0] scrambled_root_key0; + bit [CreatorRootKeyShare1Size*8-1:0] scrambled_root_key1; + bit [bus_params_pkg::BUS_DW-1:0] secret_data[$]; + + for (int i = 0; i < RmaTokenSize; i+=8) begin + scrambled_unlock_token[i*8+:64] = scramble_data(rma_unlock_token[i*8+:64], Secret2Idx); + mem_bkdr_util_h.write64(i + RmaTokenOffset, scrambled_unlock_token[i*8+:64]); + end + for (int i = 0; i < CreatorRootKeyShare0Size; i+=8) begin + scrambled_root_key0[i*8+:64] = scramble_data(creator_root_key0[i*8+:64], Secret2Idx); + mem_bkdr_util_h.write64(i + CreatorRootKeyShare0Offset, scrambled_root_key0[i*8+:64]); + end + for (int i = 0; i < CreatorRootKeyShare1Size; i+=8) begin + scrambled_root_key1[i*8+:64] = scramble_data(creator_root_key1[i*8+:64], Secret2Idx); + mem_bkdr_util_h.write64(i + CreatorRootKeyShare1Offset, scrambled_root_key1[i*8+:64]); + end + + secret_data = {<<32 {scrambled_root_key1, scrambled_root_key0, scrambled_unlock_token}}; + digest = cal_digest(Secret2Idx, secret_data); + + mem_bkdr_util_h.write64(Secret2DigestOffset, digest); + endfunction + + function automatic void otp_write_hw_cfg0_partition( + mem_bkdr_util_pkg::mem_bkdr_util mem_bkdr_util_h, + bit [DeviceIdSize*8-1:0] device_id, bit [ManufStateSize*8-1:0] manuf_state + ); + bit [HwCfg0DigestSize*8-1:0] digest; + + bit [bus_params_pkg::BUS_DW-1:0] hw_cfg0_data[$]; + + for (int i = 0; i < DeviceIdSize; i += 4) begin + mem_bkdr_util_h.write32(i + DeviceIdOffset, device_id[i*8+:32]); + end + for (int i = 0; i < ManufStateSize; i += 4) begin + mem_bkdr_util_h.write32(i + ManufStateOffset, manuf_state[i*8+:32]); + end + + hw_cfg0_data = {<<32 {manuf_state, device_id}}; + digest = cal_digest(HwCfg0Idx, hw_cfg0_data); + + mem_bkdr_util_h.write64(HwCfg0DigestOffset, digest); + endfunction + + function automatic void otp_write_hw_cfg1_partition( + mem_bkdr_util_pkg::mem_bkdr_util mem_bkdr_util_h, + bit [EnCsrngSwAppReadSize*8-1:0] en_csrng_sw_app_read, + bit [EnSramIfetchSize*8-1:0] en_sram_ifetch, + bit [EnSramIfetchSize*8-1:0] dis_rv_dm_late_debug + ); + bit [HwCfg1DigestSize*8-1:0] digest; + + bit [bus_params_pkg::BUS_DW-1:0] hw_cfg1_data[$]; + + mem_bkdr_util_h.write32(EnSramIfetchOffset, + {dis_rv_dm_late_debug, en_csrng_sw_app_read, en_sram_ifetch}); + + hw_cfg1_data = {<<32 {32'h0, dis_rv_dm_late_debug, en_csrng_sw_app_read, en_sram_ifetch}}; + digest = cal_digest(HwCfg1Idx, hw_cfg1_data); + + mem_bkdr_util_h.write64(HwCfg1DigestOffset, digest); + endfunction + + // Functions that clear the provisioning state of the buffered partitions. + // This is useful in tests that make front-door accesses for provisioning purposes. + function automatic void otp_clear_secret0_partition( + mem_bkdr_util_pkg::mem_bkdr_util mem_bkdr_util_h + ); + for (int i = 0; i < Secret0Size; i += 4) begin + mem_bkdr_util_h.write32(i + Secret0Offset, 32'h0); + end + endfunction + + function automatic void otp_clear_secret1_partition( + mem_bkdr_util_pkg::mem_bkdr_util mem_bkdr_util_h + ); + for (int i = 0; i < Secret1Size; i += 4) begin + mem_bkdr_util_h.write32(i + Secret1Offset, 32'h0); + end + endfunction + + function automatic void otp_clear_secret2_partition( + mem_bkdr_util_pkg::mem_bkdr_util mem_bkdr_util_h + ); + for (int i = 0; i < Secret2Size; i += 4) begin + mem_bkdr_util_h.write32(i + Secret2Offset, 32'h0); + end + endfunction + + function automatic void otp_clear_hw_cfg0_partition( + mem_bkdr_util_pkg::mem_bkdr_util mem_bkdr_util_h + ); + for (int i = 0; i < HwCfg0Size; i += 4) begin + mem_bkdr_util_h.write32(i + HwCfg0Offset, 32'h0); + end + endfunction +endpackage : otp_ctrl_mem_bkdr_util_pkg diff --git a/hw/top_earlgrey/ip_autogen/otp_ctrl/dv/env/otp_scrambler_pkg.sv b/hw/top_earlgrey/ip_autogen/otp_ctrl/dv/env/otp_scrambler_pkg.sv new file mode 100644 index 00000000000000..91812a0f0e23d9 --- /dev/null +++ b/hw/top_earlgrey/ip_autogen/otp_ctrl/dv/env/otp_scrambler_pkg.sv @@ -0,0 +1,88 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +///////////////////////////////////////////////// +// OTP secret data and digest scrambling logic // +///////////////////////////////////////////////// + +package otp_scrambler_pkg; + + import uvm_pkg::*; + import otp_ctrl_part_pkg::*; + import bus_params_pkg::*; + + `include "uvm_macros.svh" + + parameter int SCRAMBLE_DATA_SIZE = 64; + parameter int SCRAMBLE_KEY_SIZE = 128; + parameter int NUM_ROUND = 31; + string path = "otp_scrambler_pkg"; + + // When secret data write into otp_array, it will be scrambled. + function automatic bit [SCRAMBLE_DATA_SIZE-1:0] scramble_data( + bit [SCRAMBLE_DATA_SIZE-1:0] input_data, + int part_idx + ); + + int secret_idx = part_idx - Secret0Idx; + crypto_dpi_present_pkg::sv_dpi_present_encrypt(input_data, + RndCnstKey[secret_idx], + SCRAMBLE_KEY_SIZE, + NUM_ROUND, + scramble_data); + endfunction + + // When secret data read out of otp_array, it will be descrambled. + function automatic bit [SCRAMBLE_DATA_SIZE-1:0] descramble_data( + bit [SCRAMBLE_DATA_SIZE-1:0] input_data, + int part_idx + ); + + int secret_idx = part_idx - Secret0Idx; + + crypto_dpi_present_pkg::sv_dpi_present_decrypt(input_data, + RndCnstKey[secret_idx], + SCRAMBLE_KEY_SIZE, + NUM_ROUND, + descramble_data); + endfunction + + function automatic bit [SCRAMBLE_DATA_SIZE-1:0] cal_digest(int part_idx, + ref bit [BUS_DW-1:0] mem_q[$]); + int array_size = mem_q.size(); + real key_factor = SCRAMBLE_KEY_SIZE / BUS_DW; + bit [SCRAMBLE_DATA_SIZE-1:0] init_vec = RndCnstDigestIV[0]; + bit [SCRAMBLE_DATA_SIZE-1:0] enc_data; + bit [SCRAMBLE_DATA_SIZE-1:0] digest; + + for (int i = 0; i < $ceil(array_size / key_factor); i++) begin + bit [SCRAMBLE_DATA_SIZE-1:0] input_data = (i == 0) ? init_vec : digest; + bit [SCRAMBLE_KEY_SIZE-1:0] key; + + // Pad 32-bit partition data into 128-bit key input. + // Because the mem_q size is a multiple of 64-bit, so if the last round only has 64-bits key, + // it will repeat the last 64-bits twice. + for (int j = 0; j < key_factor; j++) begin + int index = i * key_factor + j; + key |= ((index >= array_size ? mem_q[index-2] : mem_q[index]) << (j * BUS_DW)); + end + + // Trigger 32 round of PRESENT encrypt. + crypto_dpi_present_pkg::sv_dpi_present_encrypt(input_data, key, SCRAMBLE_KEY_SIZE, + NUM_ROUND, enc_data); + // XOR the previous state into the digest result according to the Davies-Meyer scheme. + digest = enc_data ^ input_data; + end + + // Last 32 round of digest is calculated with a digest constant. + crypto_dpi_present_pkg::sv_dpi_present_encrypt(digest, + RndCnstDigestConst[0], + SCRAMBLE_KEY_SIZE, NUM_ROUND, + enc_data); + // XOR the previous state into the digest result according to the Davies-Meyer scheme. + digest ^= enc_data; + return digest; + endfunction + +endpackage