Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[sw/sca] Add batch mode for ecc256 keygen serial file #17416

Merged
merged 1 commit into from
Mar 6, 2023
Merged
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
121 changes: 119 additions & 2 deletions sw/device/sca/ecc256_keygen_serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "sw/device/lib/testing/entropy_testutils.h"
#include "sw/device/lib/testing/test_framework/ottf_main.h"
#include "sw/device/lib/testing/test_framework/ottf_test_config.h"
#include "sw/device/sca/lib/prng.h"
#include "sw/device/sca/lib/sca.h"
#include "sw/device/sca/lib/simple_serial.h"

Expand Down Expand Up @@ -55,8 +56,44 @@ enum {
* Mode option for the ECDSA keygen app (generates the full keypair).
*/
kEcc256ModeKeypair = 2,
/**
* Max number of traces per batch.
*/
kNumBatchOpsMax = 256,
wettermo marked this conversation as resolved.
Show resolved Hide resolved
};

/**
* An array of seeds to be used in a batch
*/
uint32_t batch_seeds[kNumBatchOpsMax][kEcc256SeedNumWords];

/**
* An array of masks to be used in a batch
*/
uint32_t batch_masks[kNumBatchOpsMax][kEcc256SeedNumWords];
wettermo marked this conversation as resolved.
Show resolved Hide resolved

/**
* Arrays for first and second share of masked private key d to be used in a
* batch
*/
uint32_t d0_batch[kEcc256SeedNumWords];
uint32_t d1_batch[kEcc256SeedNumWords];

/**
* Fixed-message indicator.
*
* Used in the 'b' (batch capture) command for indicating whether to use fixed
* or random message.
*/
static bool run_fixed = true;

/**
* Masking indicator.
*
* Used in the 'b' (batch capture) command for indicating whether to use masks.
*/
static bool en_masks = false;

OTBN_DECLARE_APP_SYMBOLS(p256_key_from_seed_sca);

OTBN_DECLARE_SYMBOL_ADDR(p256_key_from_seed_sca, mode);
Expand Down Expand Up @@ -91,18 +128,35 @@ static const otbn_addr_t kOtbnVarY =
* The default value corresponds to the test data in
* sw/otbn/crypto/test/p256_key_from_seed_test.s
*
* This default value can be overwritten via the simpleserial command `s`
* This default value can be overwritten via the simpleserial command `x`
* (see ecc256_set_seed)
*/
uint32_t ecc256_seed[kEcc256SeedNumWords] = {
0x016064e9, 0x11e3f4d6, 0xac3a6fa7, 0xaba11a1b, 0x8f9271d1,
0x22b79d5f, 0x1176f31d, 0xb5ac3a51, 0x99a082d7, 0x484eb366,
};

/**
* Simple serial 'm' (set masks enable) command handler.
*
* This can be used for batch mode.
*
* @param enable 1 => masks enabled, 0 => masks disabled.
* @param enable_len Length of sent enable value.
*/
static void ecc256_en_masks(const uint8_t *enable, size_t enable_len) {
SS_CHECK(enable_len == 1);
if (*enable) {
en_masks = true;
} else {
en_masks = false;
}
}

/**
* Simple serial 'x' (set seed) command handler.
*
* The key must be `kEcc256SeedNumBytes` bytes long.
* The seed must be `kEcc256SeedNumBytes` bytes long.
*
* @param seed Value for seed share.
* @param seed_len Length of seed share.
Expand Down Expand Up @@ -144,6 +198,65 @@ static void p256_run_keygen(uint32_t mode, const uint32_t *seed,
sca_set_trigger_low();
}

static void ecc256_ecdsa_secret_keygen_batch(const uint8_t *data,
size_t data_len) {
uint32_t num_traces = 0;
uint32_t out[kEcc256SeedNumWords];
uint32_t batch_digest[kEcc256SeedNumWords];
uint8_t dummy[kEcc256SeedNumBytes];
wettermo marked this conversation as resolved.
Show resolved Hide resolved
SS_CHECK(data_len == sizeof(num_traces));
num_traces = read_32(data);
wettermo marked this conversation as resolved.
Show resolved Hide resolved

if (num_traces > kNumBatchOpsMax) {
LOG_ERROR("Too many traces for one batch.");
return;
}

// zero the batch digest
for (uint32_t j = 0; j < kEcc256SeedNumWords; ++j) {
batch_digest[j] = 0;
}

for (uint32_t i = 0; i < num_traces; ++i) {
if (run_fixed) {
memcpy(batch_seeds[i], ecc256_seed, kEcc256SeedNumBytes);
} else {
prng_rand_bytes((unsigned char *)batch_seeds[i], kEcc256SeedNumBytes);
}
if (en_masks) {
prng_rand_bytes((unsigned char *)batch_masks[i], kEcc256SeedNumBytes);
} else {
for (uint32_t j = 0; j < kEcc256SeedNumWords; ++j) {
batch_masks[i][j] = 0;
}
}
// Another PRNG run to determine 'run_fixed' for the next cycle.
prng_rand_bytes(dummy, kEcc256SeedNumBytes);
run_fixed = dummy[0] & 0x1;
wettermo marked this conversation as resolved.
Show resolved Hide resolved
}

for (uint32_t i = 0; i < num_traces; ++i) {
p256_run_keygen(kEcc256ModePrivateKeyOnly, batch_seeds[i], batch_masks[i]);

// Read results.
SS_CHECK_STATUS_OK(
otbn_dmem_read(kEcc256SeedNumWords, kOtbnVarD0, d0_batch));
SS_CHECK_STATUS_OK(
otbn_dmem_read(kEcc256SeedNumWords, kOtbnVarD1, d1_batch));

// The correctness of each batch is verified by computing and sending
// the batch digest. This digest is computed by XORing all d0 shares of
// the batch.
for (uint32_t j = 0; j < kEcc256SeedNumWords; ++j) {
batch_digest[j] ^= d0_batch[j];
}
}

// Send the batch digest to the host for verification.
simple_serial_send_packet('r', (uint8_t *)batch_digest,
kEcc256SeedNumWords * 4);
}

/**
* Generates a secret key from a masked seed.
*
Expand Down Expand Up @@ -280,12 +393,16 @@ static void simple_serial_main(void) {
LOG_INFO("Initializing simple serial interface to capture board.");

simple_serial_init(sca_get_uart());
SS_CHECK(simple_serial_register_handler(
'b', ecc256_ecdsa_secret_keygen_batch) == kSimpleSerialOk);
SS_CHECK(simple_serial_register_handler('k', ecc256_ecdsa_secret_keygen) ==
kSimpleSerialOk);
SS_CHECK(simple_serial_register_handler('p', ecc256_ecdsa_gen_keypair) ==
kSimpleSerialOk);
SS_CHECK(simple_serial_register_handler('x', ecc256_set_seed) ==
kSimpleSerialOk);
SS_CHECK(simple_serial_register_handler('m', ecc256_en_masks) ==
kSimpleSerialOk);

LOG_INFO("Load p256 keygen from seed app into OTBN");
SS_CHECK_STATUS_OK(otbn_load_app(kOtbnAppP256KeyFromSeed));
Expand Down