Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 37 additions & 9 deletions hw/opentitan/ot_otp_dj.c
Original file line number Diff line number Diff line change
Expand Up @@ -2058,6 +2058,21 @@ static int ot_otp_dj_dai_write_u64(OtOTPDjState *s, unsigned address)
uint32_t lo = s->regs[R_DIRECT_ACCESS_WDATA_0];
uint32_t hi = s->regs[R_DIRECT_ACCESS_WDATA_1];

unsigned part_ix = (unsigned)s->dai->partition;
bool is_secret = ot_otp_dj_is_secret(part_ix);
bool is_zer = ot_otp_dj_is_part_zer_offset(part_ix, address);

if (is_secret && !is_zer) {
const uint8_t *scrambling_key = s->otp_scramble_keys[part_ix];
uint64_t data = ((uint64_t)hi << 32u) | lo;
g_assert(scrambling_key);
OtPresentState *ps = ot_present_new();
ot_present_init(ps, scrambling_key);
ot_present_encrypt(ps, data, &data);
lo = (uint32_t)data;
hi = (uint32_t)(data >> 32u);
}

if ((dst_lo & ~lo) || (dst_hi & ~hi)) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: Cannot clear OTP bits\n",
__func__, s->ot_id);
Expand Down Expand Up @@ -2486,27 +2501,31 @@ static uint64_t ot_otp_dj_reg_read(void *opaque, hwaddr addr, unsigned size)
case R_DIRECT_ACCESS_RDATA_1:
case R_DIRECT_ACCESS_ADDRESS:
case R_VENDOR_TEST_READ_LOCK ... R_ROM_PATCH_READ_LOCK:
case R_CHECK_TRIGGER_REGWEN:
case R_CHECK_REGWEN:
val32 = s->regs[reg];
break;
case R_STATUS:
val32 = ot_otp_dj_get_status(s);
break;
case R_DIRECT_ACCESS_REGWEN:
val32 = FIELD_DP32(0, DIRECT_ACCESS_REGWEN, REGWEN,
(uint32_t)!ot_otp_dj_dai_is_busy(s));
/* disabled either if SW locked, or if DAI is busy. */
val32 = s->regs[reg];
val32 &= FIELD_DP32(0u, DIRECT_ACCESS_REGWEN, REGWEN,
(uint32_t)!ot_otp_dj_dai_is_busy(s));
break;
/* NOLINTNEXTLINE */
case R_DIRECT_ACCESS_CMD:
case R_CHECK_TRIGGER:
val32 = 0; /* R0W1C */
break;
case R_CHECK_TRIGGER_REGWEN:
case R_CHECK_TRIGGER:
case R_CHECK_REGWEN:
case R_CHECK_TIMEOUT:
case R_INTEGRITY_CHECK_PERIOD:
case R_CONSISTENCY_CHECK_PERIOD:
/* @todo not yet implemented */
val32 = 0;
/* @todo: not yet implemented, but these are R/W registers */
qemu_log_mask(LOG_UNIMP, "%s: %s: %s is not supported\n", __func__,
s->ot_id, REG_NAME(reg));
val32 = s->regs[reg];
break;
case R_VENDOR_TEST_DIGEST_0 ... R_SECRET3_DIGEST_1:
/*
Expand Down Expand Up @@ -2589,7 +2608,6 @@ static void ot_otp_dj_reg_write(void *opaque, hwaddr addr, uint64_t value,
break;
case R_STATUS:
case R_ERR_CODE_0 ... R_ERR_CODE_23:
case R_DIRECT_ACCESS_REGWEN:
case R_DIRECT_ACCESS_RDATA_0:
case R_DIRECT_ACCESS_RDATA_1:
case R_VENDOR_TEST_DIGEST_0 ... R_SECRET3_DIGEST_1:
Expand Down Expand Up @@ -2622,6 +2640,10 @@ static void ot_otp_dj_reg_write(void *opaque, hwaddr addr, uint64_t value,
s->regs[reg] = val32;
ot_otp_dj_update_alerts(s);
break;
case R_DIRECT_ACCESS_REGWEN:
val32 &= R_DIRECT_ACCESS_REGWEN_REGWEN_MASK;
s->regs[reg] &= val32; /* RW0C */
break;
case R_DIRECT_ACCESS_CMD:
if (FIELD_EX32(val32, DIRECT_ACCESS_CMD, RD)) {
ot_otp_dj_dai_read(s);
Expand All @@ -2644,8 +2666,14 @@ static void ot_otp_dj_reg_write(void *opaque, hwaddr addr, uint64_t value,
s->regs[reg] &= val32; /* RW0C */
break;
case R_CHECK_TRIGGER_REGWEN:
case R_CHECK_TRIGGER:
val32 &= R_CHECK_TRIGGER_REGWEN_REGWEN_MASK;
s->regs[reg] &= val32; /* RW0C */
break;
case R_CHECK_REGWEN:
val32 &= R_CHECK_REGWEN_REGWEN_MASK;
s->regs[reg] &= val32; /* RW0C */
break;
case R_CHECK_TRIGGER:
case R_CHECK_TIMEOUT:
case R_INTEGRITY_CHECK_PERIOD:
case R_CONSISTENCY_CHECK_PERIOD:
Expand Down
45 changes: 36 additions & 9 deletions hw/opentitan/ot_otp_eg.c
Original file line number Diff line number Diff line change
Expand Up @@ -1939,6 +1939,20 @@ static int ot_otp_eg_dai_write_u64(OtOTPEgState *s, unsigned address)
uint32_t lo = s->regs[R_DIRECT_ACCESS_WDATA_0];
uint32_t hi = s->regs[R_DIRECT_ACCESS_WDATA_1];

unsigned part_ix = (unsigned)s->dai->partition;
bool is_secret = ot_otp_eg_is_secret(part_ix);

if (is_secret) {
const uint8_t *scrambling_key = s->otp_scramble_keys[part_ix];
uint64_t data = ((uint64_t)hi << 32u) | lo;
g_assert(scrambling_key);
OtPresentState *ps = ot_present_new();
ot_present_init(ps, scrambling_key);
ot_present_encrypt(ps, data, &data);
lo = (uint32_t)data;
hi = (uint32_t)(data >> 32u);
}

if ((dst_lo & ~lo) || (dst_hi & ~hi)) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: Cannot clear OTP bits\n",
__func__, s->ot_id);
Expand Down Expand Up @@ -2367,27 +2381,31 @@ static uint64_t ot_otp_eg_reg_read(void *opaque, hwaddr addr, unsigned size)
case R_DIRECT_ACCESS_RDATA_1:
case R_DIRECT_ACCESS_ADDRESS:
case R_VENDOR_TEST_READ_LOCK ... R_ROT_CREATOR_AUTH_STATE_READ_LOCK:
case R_CHECK_TRIGGER_REGWEN:
case R_CHECK_REGWEN:
val32 = s->regs[reg];
break;
case R_STATUS:
val32 = ot_otp_eg_get_status(s);
break;
case R_DIRECT_ACCESS_REGWEN:
val32 = FIELD_DP32(0, DIRECT_ACCESS_REGWEN, REGWEN,
(uint32_t)!ot_otp_eg_dai_is_busy(s));
/* disabled either if SW locked, or if DAI is busy. */
val32 = s->regs[reg];
val32 &= FIELD_DP32(0u, DIRECT_ACCESS_REGWEN, REGWEN,
(uint32_t)!ot_otp_eg_dai_is_busy(s));
break;
/* NOLINTNEXTLINE */
case R_DIRECT_ACCESS_CMD:
case R_CHECK_TRIGGER:
val32 = 0; /* R0W1C */
break;
case R_CHECK_TRIGGER_REGWEN:
case R_CHECK_TRIGGER:
case R_CHECK_REGWEN:
case R_CHECK_TIMEOUT:
case R_INTEGRITY_CHECK_PERIOD:
case R_CONSISTENCY_CHECK_PERIOD:
/* TODO: not yet implemented */
val32 = 0;
/* @todo: not yet implemented, but these are R/W registers */
qemu_log_mask(LOG_UNIMP, "%s: %s: %s is not supported\n", __func__,
s->ot_id, REG_NAME(reg));
val32 = s->regs[reg];
break;
case R_VENDOR_TEST_DIGEST_0 ... R_SECRET2_DIGEST_1:
/*
Expand Down Expand Up @@ -2470,7 +2488,6 @@ static void ot_otp_eg_reg_write(void *opaque, hwaddr addr, uint64_t value,
break;
case R_STATUS:
case R_ERR_CODE_0 ... R_ERR_CODE_12:
case R_DIRECT_ACCESS_REGWEN:
case R_DIRECT_ACCESS_RDATA_0:
case R_DIRECT_ACCESS_RDATA_1:
case R_VENDOR_TEST_DIGEST_0 ... R_SECRET2_DIGEST_1:
Expand Down Expand Up @@ -2503,6 +2520,10 @@ static void ot_otp_eg_reg_write(void *opaque, hwaddr addr, uint64_t value,
s->regs[reg] = val32;
ot_otp_eg_update_alerts(s);
break;
case R_DIRECT_ACCESS_REGWEN:
val32 &= R_DIRECT_ACCESS_REGWEN_REGWEN_MASK;
s->regs[reg] &= val32; /* RW0C */
break;
case R_DIRECT_ACCESS_CMD:
if (FIELD_EX32(val32, DIRECT_ACCESS_CMD, RD)) {
ot_otp_eg_dai_read(s);
Expand All @@ -2525,8 +2546,14 @@ static void ot_otp_eg_reg_write(void *opaque, hwaddr addr, uint64_t value,
s->regs[reg] &= val32; /* RW0C */
break;
case R_CHECK_TRIGGER_REGWEN:
case R_CHECK_TRIGGER:
val32 &= R_CHECK_TRIGGER_REGWEN_REGWEN_MASK;
s->regs[reg] &= val32; /* RW0C */
break;
case R_CHECK_REGWEN:
val32 &= R_CHECK_REGWEN_REGWEN_MASK;
s->regs[reg] &= val32; /* RW0C */
break;
case R_CHECK_TRIGGER:
case R_CHECK_TIMEOUT:
case R_INTEGRITY_CHECK_PERIOD:
case R_CONSISTENCY_CHECK_PERIOD:
Expand Down
5 changes: 5 additions & 0 deletions tests/opentitan/data/earlgrey-tests.txt
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,8 @@ pass: //sw/device/tests:kmac_mode_kmac_test_sim_qemu_rom_with_fake_keys
pass: //sw/device/tests:kmac_mode_kmac_test_sim_qemu_sival_rom_ext
pass: //sw/device/tests:kmac_smoketest_sim_qemu_rom_with_fake_keys
pass: //sw/device/tests:kmac_smoketest_sim_qemu_sival_rom_ext
pass: //sw/device/tests:lc_ctrl_otp_hw_cfg0_test_sim_qemu_rom_with_fake_keys
pass: //sw/device/tests:lc_ctrl_otp_hw_cfg0_test_sim_qemu_sival_rom_ext
pass: //sw/device/tests:otbn_ecdsa_op_irq_test_sim_qemu_rom_with_fake_keys
pass: //sw/device/tests:otbn_ecdsa_op_irq_test_sim_qemu_sival_rom_ext
pass: //sw/device/tests:otbn_irq_test_sim_qemu_rom_with_fake_keys
Expand All @@ -497,6 +499,7 @@ pass: //sw/device/tests:otbn_rsa_test_sim_qemu_rom_with_fake_keys
pass: //sw/device/tests:otbn_rsa_test_sim_qemu_sival_rom_ext
pass: //sw/device/tests:otbn_smoketest_sim_qemu_rom_with_fake_keys
pass: //sw/device/tests:otbn_smoketest_sim_qemu_sival_rom_ext
pass: //sw/device/tests:otp_ctrl_descrambling_test_sim_qemu_rom_with_fake_keys
pass: //sw/device/tests:plic_sw_irq_test_sim_qemu_rom_with_fake_keys
pass: //sw/device/tests:plic_sw_irq_test_sim_qemu_sival_rom_ext
pass: //sw/device/tests:pmp_smoketest_napot_sim_qemu_rom_with_fake_keys
Expand Down Expand Up @@ -541,6 +544,8 @@ pass: //sw/device/tests:uart_smoketest_sim_qemu_rom_with_fake_keys
pass: //sw/device/tests:uart_smoketest_sim_qemu_sival_rom_ext
pass: //sw/device/tests:usbdev_mem_test_sim_qemu_rom_with_fake_keys
pass: //sw/device/tests:usbdev_mem_test_sim_qemu_sival_rom_ext
pass: //sw/device/tests:usbdev_vbus_test_sim_qemu_rom_with_fake_keys
pass: //sw/device/tests:usbdev_vbus_test_sim_qemu_sival_rom_ext
pass: //third_party/coremark/top_earlgrey:coremark_test_sim_qemu_rom_with_fake_keys
pass: //third_party/coremark/top_earlgrey:coremark_test_sim_qemu_sival_rom_ext
pass: //third_party/riscv-compliance:C-ADDI16SP_sim_qemu_rom_with_fake_keys
Expand Down
Loading