Software APIs
ecc384_serial.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 
7 #include "sw/device/lib/crypto/drivers/otbn.h"
10 #include "sw/device/lib/testing/entropy_testutils.h"
12 #include "sw/device/lib/testing/test_framework/ottf_test_config.h"
14 #include "sw/device/tests/penetrationtests/firmware/lib/pentest_lib.h"
15 
17 #include "otbn_regs.h"
18 
19 /**
20  * OpenTitan program for OTBN ECDSA-P384 side-channel analysis.
21  *
22  * This program implements the following simple serial commands:
23  * - Set ephemeral secret key ('k')*,
24  * - Set private key ('d')*,
25  * - Set message ('n')*,
26  * - Start signing ('p')*
27  * - Version ('v')+,
28  * - Seed PRNG ('s')+,
29  * Commands marked with * are implemented in this file. Those marked with + are
30  * implemented in the simple serial library.
31  * See https://wiki.newae.com/SimpleSerial for details on the protocol.
32  *
33  */
34 
35 OTTF_DEFINE_TEST_CONFIG();
36 
37 enum {
38  /**
39  * Number of bytes for ECDSA P-384 private keys, message digests, and point
40  * coordinates.
41  */
42  kEcc384NumBytes = 384 / 8,
43  /**
44  * Number of 32b words for ECDSA P-384 private keys, message digests, and
45  * point coordinates.
46  *
47  * Note: Since this is not an even multiple of `kOtbnWideWordNumWords`, the
48  * caller needs to write zeroes to OTBN to fill out the last wide word.
49  * Otherwise, OTBN will encounter an error when it tries to read the
50  * uninitialized data.
51  */
52  kEcc384NumWords = kEcc384NumBytes / sizeof(uint32_t),
53 };
54 
55 /**
56  * Two shares of the ephemeral secret key k
57  * k = k0 + k1
58  * k0 = ecc384_secret_k[0:11] (0x00000000...ffffffff)
59  * k1 = ecc384_secret_k[12:23] (0x00000000...00000000)
60  *
61  * The default values can be overwritten via
62  * the simpleserial command `k` (see ecc384_set_private_key_d)
63  */
64 uint32_t ecc384_secret_k[2 * kEcc384NumWords] = {
65  0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
66  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
67  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
68  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
69 };
70 
71 /**
72  * Private key d
73  * I took this from here: https://www.rfc-editor.org/rfc/rfc6979#page-33
74  * The endianness may need to be fixed.
75  *
76  * Delivered as 2 shares. The second share is set to all-zero by default.
77  *
78  * The value of this variable can be overwritten via the simpleserial command
79  * `d` (see ecc384_set_private_key_d)
80  */
81 uint32_t ecc384_private_key_d[2 * kEcc384NumWords] = {
82  0xAD3D9D6B, 0x1C8C1B2E, 0x7598B105, 0x4D9F65B6, 0x663B3CE2, 0xBA97F27B,
83  0x4077A49A, 0xD8377178, 0x4E72D596, 0x25A8704C, 0xEAC972F8, 0xF5EDD260,
84  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
85  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
86 };
87 
88 /**
89  * Message to sign
90  * The value of this variable can be overwritten via the simpleserial command
91  * `n` (see ecc384_set_msg).
92  */
93 uint32_t ecc384_msg[kEcc384NumWords] = {
94  0x48656c6c, // 'Hell'
95  0x6f204f54, // 'o OT'
96  0x424e0000, // 'BN'
97 };
98 
99 // p384_ecdsa_sca has randomnization removed.
100 OTBN_DECLARE_APP_SYMBOLS(p384_ecdsa_sca);
101 
102 OTBN_DECLARE_SYMBOL_ADDR(p384_ecdsa_sca, mode);
103 OTBN_DECLARE_SYMBOL_ADDR(p384_ecdsa_sca, msg);
104 OTBN_DECLARE_SYMBOL_ADDR(p384_ecdsa_sca, r);
105 OTBN_DECLARE_SYMBOL_ADDR(p384_ecdsa_sca, s);
106 OTBN_DECLARE_SYMBOL_ADDR(p384_ecdsa_sca, x);
107 OTBN_DECLARE_SYMBOL_ADDR(p384_ecdsa_sca, y);
108 OTBN_DECLARE_SYMBOL_ADDR(p384_ecdsa_sca, d0);
109 OTBN_DECLARE_SYMBOL_ADDR(p384_ecdsa_sca, d1);
110 OTBN_DECLARE_SYMBOL_ADDR(p384_ecdsa_sca, k0);
111 OTBN_DECLARE_SYMBOL_ADDR(p384_ecdsa_sca, k1);
112 
113 static const otbn_app_t kOtbnAppP384Ecdsa = OTBN_APP_T_INIT(p384_ecdsa_sca);
114 
115 static const otbn_addr_t kOtbnVarMode = OTBN_ADDR_T_INIT(p384_ecdsa_sca, mode);
116 static const otbn_addr_t kOtbnVarMsg = OTBN_ADDR_T_INIT(p384_ecdsa_sca, msg);
117 static const otbn_addr_t kOtbnVarR = OTBN_ADDR_T_INIT(p384_ecdsa_sca, r);
118 static const otbn_addr_t kOtbnVarS = OTBN_ADDR_T_INIT(p384_ecdsa_sca, s);
119 static const otbn_addr_t kOtbnVarX = OTBN_ADDR_T_INIT(p384_ecdsa_sca, x);
120 static const otbn_addr_t kOtbnVarY = OTBN_ADDR_T_INIT(p384_ecdsa_sca, y);
121 static const otbn_addr_t kOtbnVarD0 = OTBN_ADDR_T_INIT(p384_ecdsa_sca, d0);
122 static const otbn_addr_t kOtbnVarD1 = OTBN_ADDR_T_INIT(p384_ecdsa_sca, d1);
123 static const otbn_addr_t kOtbnVarK0 = OTBN_ADDR_T_INIT(p384_ecdsa_sca, k0);
124 static const otbn_addr_t kOtbnVarK1 = OTBN_ADDR_T_INIT(p384_ecdsa_sca, k1);
125 
126 /**
127  * Simple serial 'k' (set ephemeral key) command handler.
128  *
129  * This function sets both shares of the secret scalar k.
130  * The first 48 bytes (i.e, kEcc384NumBytes) are used as k0, and
131  * The last 48 bytes (i.e, kEcc384NumBytes) are used as k1.
132  *
133  * Any of the shares can be set to all zeros to simplify the SCA.
134  *
135  * As this function sets both shares,
136  * the data length must be `2*kEcc384NumBytes`.
137  *
138  * @param secret_k Key.
139  * @param secret_k_len Key length.
140  */
141 static void ecc384_set_secret_key_k(const uint8_t *secret_k,
142  size_t secret_k_len) {
143  SS_CHECK(secret_k_len == 2 * kEcc384NumBytes);
144  memcpy(ecc384_secret_k, secret_k, secret_k_len);
145 }
146 
147 /**
148  * Simple serial 'd' (set private key) command handler.
149  *
150  * This function sets both shares of the private key d.
151  * The first 48 bytes (i.e, kEcc384NumBytes) are used as d0, and
152  * The last 48 bytes (i.e, kEcc384NumBytes) are used as d1.
153  *
154  * Any of the shares can be set to all zeros to simplify the SCA.
155  *
156  * As this function sets both shares,
157  * the data length must be `2*kEcc384NumBytes`.
158  *
159  * @param key_d Key.
160  * @param key_d_len Key length.
161  */
162 static void ecc_384_set_private_key_d(const uint8_t *key_d, size_t key_d_len) {
163  SS_CHECK(key_d_len == 2 * kEcc384NumBytes);
164  memcpy(ecc384_private_key_d, key_d, key_d_len);
165 }
166 
167 /**
168  * Simple serial 'n' (set message) command handler.
169  *
170  * This implementation skips hashing the message to simplify side-channel
171  * analysis, so the message must not be longer than `kEcc384NumBytes` bytes
172  * long.
173  *
174  * @param msg Message to sign.
175  * @param msg_len Message length.
176  */
177 static void ecc384_set_msg(const uint8_t *msg, size_t msg_len) {
178  SS_CHECK(msg_len <= kEcc384NumBytes);
179  // Reset to zero before copying (in case of a short message).
180  memset(ecc384_msg, 0, kEcc384NumBytes);
181  memcpy(ecc384_msg, msg, msg_len);
182 }
183 
184 /**
185  * Write a 384-bit value to OTBN.
186  *
187  * This function actually writes 512 bits -- 384 bits with the real data and
188  * the rest with zeroes -- to avoid read-of-uninitialized-data errors during
189  * OTBN execution.
190  */
191 static void p384_dmem_write(const uint32_t src[kEcc384NumWords],
192  const otbn_addr_t dest) {
193  static const uint32_t zero[kEcc384NumWords % kOtbnWideWordNumWords] = {0};
194  SS_CHECK_STATUS_OK(otbn_dmem_write(kEcc384NumWords, src, dest));
195  SS_CHECK_STATUS_OK(otbn_dmem_write(ARRAYSIZE(zero), zero, dest));
196 }
197 
198 /**
199  * Signs a message with ECDSA using the P-384 curve.
200  *
201  * R = k*G
202  * r = x-coordinate of R
203  * s = k^(-1)(msg + r*d) mod n
204  *
205  * @param otbn_ctx The OTBN context object.
206  * @param msg The message to sign, msg (48B).
207  * @param private_key_d The private key d (48B).
208  * @param k The ephemeral key k (random scalar) (48B).
209  * @param[out] signature_r Signature component r (the x-coordinate of R).
210  * Provide a pre-allocated 48B buffer.
211  * @param[out] signature_s Signature component s (the proof).
212  * Provide a pre-allocated 48B buffer.
213  */
214 static void p384_ecdsa_sign(const uint32_t *msg, const uint32_t *private_key_d,
215  uint32_t *signature_r, uint32_t *signature_s,
216  const uint32_t *k) {
217  uint32_t mode = 1; // mode 1 => sign
218  // LOG_INFO("Copy data");
219  SS_CHECK_STATUS_OK(otbn_dmem_write(/*num_words=*/1, &mode, kOtbnVarMode));
220  p384_dmem_write(msg, kOtbnVarMsg);
221  p384_dmem_write(private_key_d, kOtbnVarD0);
222  p384_dmem_write(private_key_d + kEcc384NumWords, kOtbnVarD1);
223 
224  SS_CHECK_STATUS_OK(otbn_dmem_write(kEcc384NumWords, k, kOtbnVarK0));
226  otbn_dmem_write(kEcc384NumWords, k + kEcc384NumWords, kOtbnVarK1));
227 
228  SS_CHECK_STATUS_OK(otbn_execute());
229  SS_CHECK_STATUS_OK(otbn_busy_wait_for_done());
230 
231  SS_CHECK_STATUS_OK(otbn_dmem_read(kEcc384NumWords, kOtbnVarR, signature_r));
232  SS_CHECK_STATUS_OK(otbn_dmem_read(kEcc384NumWords, kOtbnVarS, signature_s));
233 }
234 
235 /**
236  * Simple serial 'p' (sign) command handler.
237  *
238  * Takes the scalar value from the simple serial UART and triggers
239  * OTBN_P384_sign operation.
240  *
241  * To overwrite the message, use the simpleserial command 'n'
242  * To overwrite the private key value, use the simpleserial command 'd'
243  *
244  * @param ecc384_secret_k the ephemeral key/scalar provided via simpleserial
245  * UART.
246  * @param secret_k_len Length of the ephemeral key.
247  */
248 static void ecc384_ecdsa(const uint8_t *ecc384_secret_k_bytes,
249  size_t secret_k_len) {
250  LOG_INFO("SSECDSA starting...");
251  SS_CHECK_STATUS_OK(otbn_load_app(kOtbnAppP384Ecdsa));
252  LOG_INFO("otbn_status: 0x%08x", abs_mmio_read32(TOP_EARLGREY_OTBN_BASE_ADDR +
253  OTBN_STATUS_REG_OFFSET));
254 
255  uint32_t ecc384_signature_r[kEcc384NumWords];
256  uint32_t ecc384_signature_s[kEcc384NumWords];
257 
258  LOG_INFO("Signing");
259  pentest_set_trigger_high();
260  p384_ecdsa_sign(ecc384_msg, ecc384_private_key_d, ecc384_signature_r,
261  ecc384_signature_s, ecc384_secret_k);
262  pentest_set_trigger_low();
263 
264  // Copy r and s into byte buffers to avoid strict-aliasing violations.
265  uint8_t ecc384_signature_r_bytes[kEcc384NumBytes];
266  memcpy(ecc384_signature_r_bytes, ecc384_signature_r,
267  sizeof(ecc384_signature_r));
268  uint8_t ecc384_signature_s_bytes[kEcc384NumBytes];
269  memcpy(ecc384_signature_s_bytes, ecc384_signature_s,
270  sizeof(ecc384_signature_s));
271 
272  /**
273  * Send the signature_r and signature_s back to host
274  *
275  * TODO: Remove them if they are not necessary for the side-channel analysis.
276  */
277  simple_serial_send_packet('r', ecc384_signature_r_bytes, kEcc384NumBytes);
278  simple_serial_send_packet('r', ecc384_signature_s_bytes, kEcc384NumBytes);
279 
280  // Clear OTBN memory
281  SS_CHECK_STATUS_OK(otbn_dmem_sec_wipe());
282  SS_CHECK_STATUS_OK(otbn_imem_sec_wipe());
283 }
284 
285 /**
286  * Initializes peripherals and processes simple serial packets received over
287  * UART.
288  */
289 static void simple_serial_main(void) {
290  SS_CHECK_STATUS_OK(entropy_testutils_auto_mode_init());
291 
292  pentest_init(kPentestTriggerSourceOtbn,
293  kPentestPeripheralEntropy | kPentestPeripheralIoDiv4 |
294  kPentestPeripheralOtbn | kPentestPeripheralCsrng |
295  kPentestPeripheralEdn | kPentestPeripheralHmac);
296 
297  LOG_INFO("Running ECC serial");
298  LOG_INFO("Initializing simple serial interface to capture board.");
299  simple_serial_init(pentest_get_uart());
300 
301  SS_CHECK(simple_serial_register_handler('p', ecc384_ecdsa) ==
302  kSimpleSerialOk);
303  SS_CHECK(simple_serial_register_handler('k', ecc384_set_secret_key_k) ==
304  kSimpleSerialOk);
305  SS_CHECK(simple_serial_register_handler('d', ecc_384_set_private_key_d) ==
306  kSimpleSerialOk);
307  SS_CHECK(simple_serial_register_handler('n', ecc384_set_msg) ==
308  kSimpleSerialOk);
309 
310  LOG_INFO("Starting simple serial packet handling.");
311  while (true) {
313  }
314 }
315 
316 bool test_main(void) {
317  (void)kOtbnVarX;
318  (void)kOtbnVarY;
319 
320  simple_serial_main();
321  return true;
322 }