Skip to content

Commit

Permalink
[otbn/sca] Add new sca features for otbn_ecdsa_256
Browse files Browse the repository at this point in the history
Enable OTBNsim simulation of p256_ecdsa_sca.s, and enable receiving of
all secret input shares(k0, k1, d0, d1) from the host-side Python code.

*.s file:
   - Change file to enable OTBNsim simulation.
   - Set default values for k0, k1, msg, x, y, d0, d1.
   - This values can be modified to compare the OTBNsim results to FPGA
     results.

*.c file:
   - Remove all the LOG_INFO between the two triggers to make sure the
     measured ECDSA operation's timing will be same for all runsi.
   - Enable receiving of k0, k1, d0, d1 from the host-side Python code.
   - Add a new simpleserial command ('k') to separate the
     start_ecdsa,'p', and set secret scalar 'k'.

Signed-off-by: Bilgiday Yuce <bilgiday@google.com>
  • Loading branch information
bilgiday committed Jan 17, 2023
1 parent d1f1f9c commit 58b32ca
Show file tree
Hide file tree
Showing 2 changed files with 151 additions and 50 deletions.
109 changes: 68 additions & 41 deletions sw/device/sca/ecc_serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,14 @@
* OpenTitan program for OTBN ECDSA-P384 side-channel analysis.
*
* This program implements the following simple serial commands:
* - Set ephemeral secret key and sign ('p')*,
* - Set ephemeral secret key ('k')*,
* - Set private key ('d')*,
* - Set message ('n')*,
* - Start signing ('p')*
* - Version ('v')+,
* - Seed PRNG ('s')+,
* Commands marked with * are implemented in this file. Those marked with + are
* implemented in the simple serial library.
* See https://wiki.newae.com/SimpleSerial for details on the protocol.
*
* The OTBN-related code was developed based on
Expand All @@ -49,6 +52,21 @@ enum {
kEcc256NumWords = kEcc256NumBytes / sizeof(uint32_t),
};

/**
* Two shares of the ephemeral secret key k
* k = k0 + k1
* k0 = ecc256_secret_k[0:7] (0x00000000...ffffffff)
* k1 = ecc256_secret_k[8:15] (0x00000000...00000000)
*
* The default values can be overwritten via
* the simpleserial command `k` (see ecc256_set_private_key_d)
*/
uint32_t ecc256_secret_k[2 * kEcc256NumWords] = {
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
};

/**
* Private key d
* This is the default value used by NewAE in their experiments
Expand All @@ -60,9 +78,10 @@ enum {
* The value of this variable can be overwritten via
* the simpleserial command `d` (see ecc256_set_private_key_d)
*/
uint32_t ecc256_private_key_d[8] = {
0xaf57b4cd, 0x744c9f1c, 0x8b7e0c02, 0x283e93e9,
0x0d18f00c, 0xda0b6cf4, 0x8fe6bb7a, 0x5545a0b7,
uint32_t ecc256_private_key_d[2 * kEcc256NumWords] = {
0xaf57b4cd, 0x744c9f1c, 0x8b7e0c02, 0x283e93e9, 0x0d18f00c, 0xda0b6cf4,
0x8fe6bb7a, 0x5545a0b7, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
};

/**
Expand All @@ -71,7 +90,7 @@ uint32_t ecc256_private_key_d[8] = {
* The value of this variable can be overwritten via the simpleserial command
* `n` (see ecc256_set_msg).
*/
uint32_t ecc256_msg[8] = {
uint32_t ecc256_msg[kEcc256NumWords] = {
0x48656c6c, // 'Hell'
0x6f204f54, // 'o OT'
0x424e0000, // 'BN'
Expand Down Expand Up @@ -106,17 +125,44 @@ static const otbn_addr_t kOtbnVarXR = OTBN_ADDR_T_INIT(p256_ecdsa_sca, x_r);
static const otbn_addr_t kOtbnVarK0 = OTBN_ADDR_T_INIT(p256_ecdsa_sca, k0);
static const otbn_addr_t kOtbnVarK1 = OTBN_ADDR_T_INIT(p256_ecdsa_sca, k1);

/**
* Simple serial 'k' (set ephemeral key) command handler.
*
* This function sets both shares of the secret scalar k.
* The first 32 bytes (i.e, kEcc256NumBytes) are used as k0, and
* The last 32 bytes (i.e, kEcc256NumBytes) are used as k1.
*
* Any of the shares can be set to all zeros to simplify the SCA.
*
* As this function sets both shares,
* the data length must be `2*kEcc256NumBytes`.
*
* @param secret_k Key.
* @param secret_k_len Key length.
*/
static void ecc256_set_secret_key_k(const uint8_t *secret_k,
size_t secret_k_len) {
SS_CHECK(secret_k_len == 2 * kEcc256NumBytes);
memcpy(ecc256_secret_k, secret_k, secret_k_len);
}

/**
* Simple serial 'd' (set private key) command handler.
*
* This function does not use key shares to simplify side-channel analysis.
* The key must be `kEcc256NumBytes` bytes long.
* This function sets both shares of the private key d.
* The first 32 bytes (i.e, kEcc256NumBytes) are used as d0, and
* The last 32 bytes (i.e, kEcc256NumBytes) are used as d1.
*
* Any of the shares can be set to all zeros to simplify the SCA.
*
* As this function sets both shares,
* the data length must be `2*kEcc256NumBytes`.
*
* @param key_d Key.
* @param key_d_len Key length.
*/
static void ecc256_set_private_key_d(const uint8_t *key_d, size_t key_d_len) {
SS_CHECK(key_d_len == kEcc256NumBytes);
SS_CHECK(key_d_len == 2 * kEcc256NumBytes);
memcpy(ecc256_private_key_d, key_d, key_d_len);
}

Expand Down Expand Up @@ -157,60 +203,39 @@ static void p256_ecdsa_sign(const uint32_t *msg, const uint32_t *private_key_d,
uint32_t *signature_r, uint32_t *signature_s,
const uint32_t *k) {
uint32_t mode = 1; // mode 1 => sign
LOG_INFO("Copy data");
// Send operation mode to OTBN
SS_CHECK(otbn_dmem_write(/*num_words=*/1, &mode, kOtbnVarMode) ==
kOtbnErrorOk);
// Send Msg to OTBN
SS_CHECK(otbn_dmem_write(kEcc256NumWords, msg, kOtbnVarMsg) == kOtbnErrorOk);
// Send two shares of private_key_d to OTBN
SS_CHECK(otbn_dmem_write(kEcc256NumWords, private_key_d, kOtbnVarD0) ==
kOtbnErrorOk);
SS_CHECK(otbn_dmem_write(kEcc256NumWords, private_key_d + kEcc256NumWords,
kOtbnVarD1) == kOtbnErrorOk);
// Send two shares of secret_k to OTBN
SS_CHECK(otbn_dmem_write(kEcc256NumWords, k, kOtbnVarK0) == kOtbnErrorOk);
SS_CHECK(otbn_dmem_write(kEcc256NumWords, k + kEcc256NumWords, kOtbnVarK1) ==
kOtbnErrorOk);

// Copy zeroes for second shares of d and k to simplify side-channel
// analysis.
uint32_t zero[kEcc256NumWords];
memset(zero, 0, kEcc256NumBytes);
SS_CHECK(otbn_dmem_write(kEcc256NumWords, zero, kOtbnVarD1) == kOtbnErrorOk);
SS_CHECK(otbn_dmem_write(kEcc256NumWords, zero, kOtbnVarK1) == kOtbnErrorOk);

LOG_INFO("Execute");
// Start OTBN execution
SS_CHECK(otbn_execute() == kOtbnErrorOk);
LOG_INFO("Wait for done");
SS_CHECK(otbn_busy_wait_for_done() == kOtbnErrorOk);

LOG_INFO("Get results");
// Read the results back (sig_r, sig_s)
SS_CHECK(otbn_dmem_read(kEcc256NumWords, kOtbnVarR, signature_r) ==
kOtbnErrorOk);
SS_CHECK(otbn_dmem_read(kEcc256NumWords, kOtbnVarS, signature_s) ==
kOtbnErrorOk);
LOG_INFO("r[0]: 0x%08x", signature_r[0]);
LOG_INFO("s[0]: 0x%08x", signature_s[0]);
}

/**
* Simple serial 'p' (sign) command handler.
*
* Takes the scalar value from the simple serial UART
* and triggers OTBN_P256_sign operation.
* Uses a fixed message and private key value
*
* To overwrite the message, use the simpleserial command 'n'
* To overwrite the private key value, use the simpleserial command 'd'
* Triggers OTBN_P256_sign operation.
*
* @param ecc256_secret_k the ephemeral key/scalar provided via simpleserial
* UART.
* @param secret_k_len Length of the ephemeral key.
*/
static void ecc256_ecdsa(const uint8_t *ecc256_secret_k_bytes,
size_t secret_k_len) {
if (secret_k_len != kEcc256NumBytes) {
LOG_INFO("Invalid data length %hu", (uint8_t)secret_k_len);
return;
}

// Copy k to an aligned buffer.
uint32_t ecc256_secret_k[kEcc256NumWords];
memcpy(ecc256_secret_k, ecc256_secret_k_bytes, kEcc256NumBytes);

static void ecc256_ecdsa() {
LOG_INFO("SSECDSA starting...");
SS_CHECK(otbn_load_app(kOtbnAppP256Ecdsa) == kOtbnErrorOk);
LOG_INFO("otbn_status: 0x%08x", abs_mmio_read32(TOP_EARLGREY_OTBN_BASE_ADDR +
Expand Down Expand Up @@ -259,6 +284,8 @@ static void simple_serial_main(void) {
simple_serial_init(sca_get_uart());
SS_CHECK(simple_serial_register_handler('p', ecc256_ecdsa) ==
kSimpleSerialOk);
SS_CHECK(simple_serial_register_handler('k', ecc256_set_secret_key_k) ==
kSimpleSerialOk);
SS_CHECK(simple_serial_register_handler('d', ecc256_set_private_key_d) ==
kSimpleSerialOk);
SS_CHECK(simple_serial_register_handler('n', ecc256_set_msg) ==
Expand Down
92 changes: 83 additions & 9 deletions sw/otbn/crypto/p256_ecdsa_sca.s
Original file line number Diff line number Diff line change
Expand Up @@ -33,33 +33,66 @@ p256_ecdsa_verify:
jal x1, p256_verify
ecall

.bss
.data

/* Freely available DMEM space. */

/* Operation mode (1 = sign; 2 = verify) */
.globl mode
.balign 4
mode:
.zero 4
.word 0x1

/* All constants below must be 256b-aligned. */

/* random scalar k (in two shares) */
.global k0
.balign 32
k0:
.zero 32
/* Word-order: The word with the lowest index is last */
/* Byte order in a word: little-endian */
/* i.e., k0 = 0x0000000...ffffffff. */
.word 0xffffffff
.word 0xffffffff
.word 0xffffffff
.word 0xffffffff
.word 0x00000000
.word 0x00000000
.word 0x00000000
.word 0x00000000

.global k1
.balign 32
k1:
.zero 32
/* Word-order: The word with the lowest index is last */
/* Byte order in a word: little-endian */
/* i.e., k1= 0x0000000...ffffffff. */
.word 0x00000000
.word 0x00000000
.word 0x00000000
.word 0x00000000
.word 0x00000000
.word 0x00000000
.word 0x00000000
.word 0x00000000


/* message digest */
.globl msg
.balign 32
msg:
.zero 32
/*"Hello OTBN."*/
/* Word-order: The word with the lowest index is last */
/* Byte order in a word: little-endian */
/* i.e., msg = 0x06d71207...4456fd21. */
.word 0x4456fd21
.word 0x400bdd7d
.word 0xb54d7452
.word 0x17d015f1
.word 0x90d4d90b
.word 0xb028ad8a
.word 0x6ce90fef
.word 0x06d71207

/* signature R */
.globl r
Expand All @@ -77,23 +110,64 @@ s:
.globl x
.balign 32
x:
.zero 32
/* Word-order: The word with the lowest index is last */
/* Byte order in a word: little-endian */
/* i.e., x = 0x6b17d1f2...d898c296. */
.word 0xd898c296
.word 0xf4a13945
.word 0x2deb33a0
.word 0x77037d81
.word 0x63a440f2
.word 0xf8bce6e5
.word 0xe12c4247
.word 0x6b17d1f2

/* public key y-coordinate */
.globl y
.balign 32
y:
.zero 32
/* Word-order: The word with the lowest index is last */
/* Byte order in a word: little-endian */
/* i.e., y= 0x4fe342e2...37bf51f5. */
.word 0x37bf51f5
.word 0xcbb64068
.word 0x6b315ece
.word 0x2bce3357
.word 0x7c0f9e16
.word 0x8ee7eb4a
.word 0xfe1a7f9b
.word 0x4fe342e2

/* private key d (in two shares) */
.globl d0
.balign 32
d0:
.zero 32
/* Word-order: The word with the lowest index is last */
/* Byte order in a word: little-endian */
/* i.e., d0= 0x5545a0b7...af57b4cd */
.word 0xaf57b4cd
.word 0x744c9f1c
.word 0x8b7e0c02
.word 0x283e93e9
.word 0x0d18f00c
.word 0xda0b6cf4
.word 0x8fe6bb7a
.word 0x5545a0b7

.globl d1
.balign 32
d1:
.zero 32
/* Word-order: The word with the lowest index is last */
/* Byte order in a word: little-endian */
/* i.e., d1 = 0x00000000...00000000 */
.word 0x00000000
.word 0x00000000
.word 0x00000000
.word 0x00000000
.word 0x00000000
.word 0x00000000
.word 0x00000000
.word 0x00000000

/* verification result x_r (aka x_1) */
.globl x_r
Expand Down

0 comments on commit 58b32ca

Please sign in to comment.