Software APIs
otp_ctrl_descrambling_test.c
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 
5 #include <stdbool.h>
6 
9 #include "sw/device/lib/testing/otp_ctrl_testutils.h"
11 
13 #include "otp_ctrl_regs.h"
14 
15 OTTF_DEFINE_TEST_CONFIG();
16 
17 typedef struct partition_data {
18  dif_otp_ctrl_partition_t partition;
19  size_t size;
21 
22 static const partition_data_t kPartitions[] = {
23  {
24  .partition = kDifOtpCtrlPartitionSecret0,
25  .size =
26  (OTP_CTRL_PARAM_SECRET0_SIZE - OTP_CTRL_PARAM_SECRET0_DIGEST_SIZE) /
27  sizeof(uint64_t),
28  },
29  {
30  .partition = kDifOtpCtrlPartitionSecret1,
31  .size =
32  (OTP_CTRL_PARAM_SECRET1_SIZE - OTP_CTRL_PARAM_SECRET1_DIGEST_SIZE) /
33  sizeof(uint64_t),
34  },
35  {
36  .partition = kDifOtpCtrlPartitionSecret2,
37  .size =
38  (OTP_CTRL_PARAM_SECRET2_SIZE - OTP_CTRL_PARAM_SECRET2_DIGEST_SIZE) /
39  sizeof(uint64_t),
40  },
41 };
42 
43 static inline uint32_t lower(uint64_t dword) { return (uint32_t)dword; }
44 
45 static inline uint32_t upper(uint64_t dword) { return (uint32_t)(dword >> 32); }
46 
47 size_t compare_dword(const uint64_t *actual_arr, uint32_t part_idx,
48  uint32_t dword_idx, uint64_t expected) {
49  const uint64_t actual = actual_arr[dword_idx];
50  if (actual == expected) {
51  return 0;
52  } else {
53  LOG_WARNING("SECRET%0d, dword %0d: 0x%08x%08x != 0x%08x%08x", part_idx,
54  dword_idx, upper(actual), lower(actual), upper(expected),
55  lower(expected));
56  return 1;
57  }
58 }
59 
60 bool test_main(void) {
61  dif_otp_ctrl_t otp_ctrl;
62 
63  CHECK_DIF_OK(dif_otp_ctrl_init(
65 
66  // Number of 64-bit words that differ from the expected value; used to
67  // determine overall test pass or failure.
68  size_t dwords_diff = 0;
69 
70  // Iterate over the partitions that are scrambled and read them out via the
71  // DAI. This SW-based access is only possible because the partitions have not
72  // been locked in/before this test.
73  for (uint32_t i = 0; i < ARRAYSIZE(kPartitions); ++i) {
74  const partition_data_t *partition = &kPartitions[i];
75  uint64_t readout[partition->size];
76 
77  LOG_INFO("Checking partition SECRET%0d.", i);
78  CHECK_STATUS_OK(otp_ctrl_testutils_dai_read64_array(
79  &otp_ctrl, partition->partition, 0, readout, ARRAYSIZE(readout)));
80 
81  // Compare values read from OTP to expected values stored in the OTP image.
82  switch (i) {
83  case 0:
84  dwords_diff += compare_dword(readout, 0, 0, 0x749f1cb4a7daf4f5);
85  dwords_diff += compare_dword(readout, 0, 1, 0x117dbd7aca3f7de6);
86  dwords_diff += compare_dword(readout, 0, 2, 0xd6313735da1740e4);
87  dwords_diff += compare_dword(readout, 0, 3, 0x1dc4b32c25ef2c31);
88  CHECK(partition->size == 4, "Unexpected size of SECRET0 partition!");
89  break;
90 
91  case 1:
92  dwords_diff += compare_dword(readout, 1, 0, 0x8ed040844dde2dca);
93  dwords_diff += compare_dword(readout, 1, 1, 0x8251c8921ed1a7fc);
94  dwords_diff += compare_dword(readout, 1, 2, 0x038c1b4e7bd7394c);
95  dwords_diff += compare_dword(readout, 1, 3, 0x434677540fdc9956);
96  dwords_diff += compare_dword(readout, 1, 4, 0x5cc32c34646c9a9f);
97  dwords_diff += compare_dword(readout, 1, 5, 0x871b3d2726a67336);
98  dwords_diff += compare_dword(readout, 1, 6, 0xdcc70e44beeff5f4);
99  dwords_diff += compare_dword(readout, 1, 7, 0x7cdb1a9d39c20016);
100  dwords_diff += compare_dword(readout, 1, 8, 0x0e83fabc03c68203);
101  dwords_diff += compare_dword(readout, 1, 9, 0x57f20b5b2e200c01);
102  CHECK(partition->size == 10, "Unexpected size of SECRET1 partition!");
103  break;
104 
105  case 2:
106  dwords_diff += compare_dword(readout, 2, 0, 0xbed4fd235f6b24d4);
107  dwords_diff += compare_dword(readout, 2, 1, 0x6ef5b95acb3ded39);
108  dwords_diff += compare_dword(readout, 2, 2, 0xa9398fab0bba1e23);
109  dwords_diff += compare_dword(readout, 2, 3, 0x196906bfe0051fa8);
110  dwords_diff += compare_dword(readout, 2, 4, 0xea9f54f370a2fdf8);
111  dwords_diff += compare_dword(readout, 2, 5, 0xf915734729d70391);
112  dwords_diff += compare_dword(readout, 2, 6, 0xd3bd2ecfc0fc7581);
113  dwords_diff += compare_dword(readout, 2, 7, 0xbaa7bc074a97c885);
114  dwords_diff += compare_dword(readout, 2, 8, 0xdda3ceb51b6cbc3b);
115  dwords_diff += compare_dword(readout, 2, 9, 0xe889c1ccf0f57d6d);
116  CHECK(partition->size == 10, "Unexpected size of SECRET2 partition!");
117  break;
118 
119  default:
120  OT_UNREACHABLE();
121  break;
122  }
123  }
124 
125  // Test succeeds if no value read from OTP differed from the expected value.
126  return dwords_diff == 0;
127 }