5 #include "sw/device/tests/penetrationtests/firmware/sca/ecc256_keygen_sca.h"
12 #include "sw/device/lib/testing/test_framework/ottf_test_config.h"
13 #include "sw/device/lib/testing/test_framework/ujson_ottf.h"
14 #include "sw/device/lib/ujson/ujson.h"
16 #include "sw/device/tests/penetrationtests/firmware/lib/pentest_lib.h"
17 #include "sw/device/tests/penetrationtests/json/otbn_sca_commands.h"
20 #include "otbn_regs.h"
26 kEcc256SeedNumBytes = 320 / 8,
30 kEcc256SeedNumWords = kEcc256SeedNumBytes /
sizeof(uint32_t),
34 kEcc256CoordNumBytes = 256 / 8,
38 kEcc256CoordNumWords = kEcc256CoordNumBytes /
sizeof(uint32_t),
42 kEcc256ModePrivateKeyOnly = 1,
46 kEcc256ModeKeypair = 2,
50 kNumBatchOpsMax = 256,
58 kIbexOtbnSleepCycles = 1100,
67 static const otbn_addr_t kOtbnVarMode =
69 static const otbn_addr_t kOtbnVarSeed0 =
71 static const otbn_addr_t kOtbnVarSeed1 =
73 static const otbn_addr_t kOtbnVarD0 =
75 static const otbn_addr_t kOtbnVarD1 =
81 uint32_t batch_share0[kNumBatchOpsMax][kEcc256SeedNumWords];
86 uint32_t batch_share1[kNumBatchOpsMax][kEcc256SeedNumWords];
92 uint32_t d0_batch[kEcc256SeedNumWords];
93 uint32_t d1_batch[kEcc256SeedNumWords];
101 static bool run_fixed =
true;
108 static bool en_masks =
false;
110 uint32_t ecc256_seed[kEcc256SeedNumWords];
112 uint32_t ecc256_C[kEcc256SeedNumWords];
114 uint32_t random_number[kEcc256CoordNumWords];
116 uint32_t ecc256_fixed_number[kEcc256CoordNumWords];
131 static void add_arrays(uint8_t *dest, uint8_t *source,
size_t dest_len,
135 for (
size_t i = 0; i < source_len; i++) {
136 temp += (uint16_t)source[i] + dest[i];
137 dest[i] = (uint8_t)(temp & 0x00FF);
141 for (
size_t i = source_len; i < dest_len; i++) {
142 temp += (uint16_t)dest[i];
143 dest[i] = (uint8_t)(temp & 0x00FF);
151 static void otbn_manual_trigger(
void) { otbn_execute(); }
163 static status_t p256_run_keygen(uint32_t mode,
const uint32_t *share0,
164 const uint32_t *share1) {
166 TRY(otbn_load_app(kOtbnAppP256KeyFromSeed));
169 TRY(otbn_dmem_write(1, &mode, kOtbnVarMode));
172 TRY(otbn_dmem_write(kEcc256SeedNumWords, share0, kOtbnVarSeed0));
173 TRY(otbn_dmem_write(kEcc256SeedNumWords, share1, kOtbnVarSeed1));
176 pentest_call_and_sleep(otbn_manual_trigger, kIbexOtbnSleepCycles,
true,
true);
181 status_t handle_otbn_sca_ecc256_ecdsa_keygen_fvsr_key_batch(
ujson_t *uj) {
182 penetrationtest_otbn_sca_num_traces_t uj_data;
183 TRY(ujson_deserialize_penetrationtest_otbn_sca_num_traces_t(uj, &uj_data));
185 uint32_t num_traces = uj_data.num_traces;
186 uint32_t batch_digest[kEcc256SeedNumWords];
188 if (num_traces > kNumBatchOpsMax) {
189 return OUT_OF_RANGE();
193 for (
size_t j = 0; j < kEcc256SeedNumWords; ++j) {
197 for (
size_t i = 0; i < num_traces; ++i) {
200 for (
size_t j = 0; j < kEcc256SeedNumWords; ++j) {
204 for (
size_t j = 0; j < kEcc256SeedNumWords; ++j) {
205 batch_share1[i][j] = 0;
212 memcpy(batch_share0[i], ecc256_seed, kEcc256SeedNumBytes);
216 memcpy(batch_share0[i], ecc256_C, kEcc256SeedNumBytes);
217 for (
size_t j = 0; j < kEcc256CoordNumWords; ++j) {
220 add_arrays((
unsigned char *)batch_share0[i],
221 (
unsigned char *)random_number, kEcc256SeedNumBytes,
222 kEcc256CoordNumBytes);
224 for (
size_t j = 0; j < kEcc256SeedNumWords; ++j) {
225 batch_share0[i][j] ^= batch_share1[i][j];
231 for (
size_t i = 0; i < num_traces; ++i) {
232 TRY(p256_run_keygen(kEcc256ModePrivateKeyOnly, batch_share0[i],
236 TRY(otbn_dmem_read(kEcc256SeedNumWords, kOtbnVarD0, d0_batch));
237 TRY(otbn_dmem_read(kEcc256SeedNumWords, kOtbnVarD1, d1_batch));
242 for (
size_t j = 0; j < kEcc256SeedNumWords; ++j) {
243 batch_digest[j] ^= d0_batch[j];
247 penetrationtest_otbn_sca_batch_digest_t uj_output;
248 memcpy(uj_output.batch_digest, (uint8_t *)batch_digest,
249 kEcc256SeedNumWords * 4);
250 RESP_OK(ujson_serialize_penetrationtest_otbn_sca_batch_digest_t, uj,
256 status_t handle_otbn_sca_ecc256_ecdsa_keygen_fvsr_seed_batch(
ujson_t *uj) {
257 penetrationtest_otbn_sca_num_traces_t uj_data;
258 TRY(ujson_deserialize_penetrationtest_otbn_sca_num_traces_t(uj, &uj_data));
260 uint32_t num_traces = uj_data.num_traces;
261 uint32_t batch_digest[kEcc256SeedNumWords];
263 if (num_traces > kNumBatchOpsMax) {
264 return OUT_OF_RANGE();
268 for (
size_t j = 0; j < kEcc256SeedNumWords; ++j) {
272 for (
size_t i = 0; i < num_traces; ++i) {
275 for (
size_t j = 0; j < kEcc256SeedNumWords; ++j) {
279 for (
size_t j = 0; j < kEcc256SeedNumWords; ++j) {
280 batch_share1[i][j] = 0;
287 memcpy(batch_share0[i], ecc256_seed, kEcc256SeedNumBytes);
289 for (
size_t j = 0; j < kEcc256SeedNumWords; ++j) {
294 for (
size_t j = 0; j < kEcc256SeedNumWords; ++j) {
295 batch_share0[i][j] ^= batch_share1[i][j];
300 for (
size_t i = 0; i < num_traces; ++i) {
301 TRY(p256_run_keygen(kEcc256ModePrivateKeyOnly, batch_share0[i],
305 TRY(otbn_dmem_read(kEcc256SeedNumWords, kOtbnVarD0, d0_batch));
306 TRY(otbn_dmem_read(kEcc256SeedNumWords, kOtbnVarD1, d1_batch));
311 for (
size_t j = 0; j < kEcc256SeedNumWords; ++j) {
312 batch_digest[j] ^= d0_batch[j];
317 penetrationtest_otbn_sca_batch_digest_t uj_output;
318 memcpy(uj_output.batch_digest, (uint8_t *)batch_digest,
319 kEcc256SeedNumWords * 4);
320 RESP_OK(ujson_serialize_penetrationtest_otbn_sca_batch_digest_t, uj,
327 penetrationtest_otbn_sca_en_masks_t uj_data;
328 TRY(ujson_deserialize_penetrationtest_otbn_sca_en_masks_t(uj, &uj_data));
329 if (uj_data.en_masks) {
338 penetrationtest_otbn_sca_constant_t uj_data;
339 TRY(ujson_deserialize_penetrationtest_otbn_sca_constant_t(uj, &uj_data));
341 memcpy(ecc256_C, uj_data.constant, kEcc256SeedNumBytes);
347 penetrationtest_otbn_sca_seed_t uj_data;
348 TRY(ujson_deserialize_penetrationtest_otbn_sca_seed_t(uj, &uj_data));
350 memcpy(ecc256_seed, uj_data.seed, kEcc256SeedNumBytes);