Software APIs
ecc.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 
6 
7 #include "sw/device/lib/crypto/drivers/entropy.h"
8 #include "sw/device/lib/crypto/drivers/hmac.h"
9 #include "sw/device/lib/crypto/impl/ecc/ecdh_p256.h"
10 #include "sw/device/lib/crypto/impl/ecc/ecdh_p384.h"
11 #include "sw/device/lib/crypto/impl/ecc/ecdsa_p256.h"
13 #include "sw/device/lib/crypto/impl/integrity.h"
14 #include "sw/device/lib/crypto/impl/keyblob.h"
16 
17 // Module ID for status codes.
18 #define MODULE_ID MAKE_MODULE_ID('e', 'c', 'c')
19 
21  const otcrypto_ecc_curve_t *elliptic_curve,
22  otcrypto_blinded_key_t *private_key, otcrypto_unblinded_key_t *public_key) {
23  HARDENED_TRY(otcrypto_ecdsa_keygen_async_start(elliptic_curve, private_key));
24  return otcrypto_ecdsa_keygen_async_finalize(elliptic_curve, private_key,
25  public_key);
26 }
27 
29  const otcrypto_blinded_key_t *private_key,
30  const otcrypto_hash_digest_t message_digest,
31  const otcrypto_ecc_curve_t *elliptic_curve,
32  otcrypto_word32_buf_t signature) {
33  HARDENED_TRY(otcrypto_ecdsa_sign_async_start(private_key, message_digest,
34  elliptic_curve));
35  return otcrypto_ecdsa_sign_async_finalize(elliptic_curve, signature);
36 }
37 
39  const otcrypto_unblinded_key_t *public_key,
40  const otcrypto_hash_digest_t message_digest,
42  const otcrypto_ecc_curve_t *elliptic_curve,
43  hardened_bool_t *verification_result) {
44  HARDENED_TRY(otcrypto_ecdsa_verify_async_start(public_key, message_digest,
45  signature, elliptic_curve));
46  return otcrypto_ecdsa_verify_async_finalize(elliptic_curve, signature,
47  verification_result);
48 }
49 
51  const otcrypto_ecc_curve_t *elliptic_curve,
52  otcrypto_blinded_key_t *private_key, otcrypto_unblinded_key_t *public_key) {
53  HARDENED_TRY(otcrypto_ecdh_keygen_async_start(elliptic_curve, private_key));
54  return otcrypto_ecdh_keygen_async_finalize(elliptic_curve, private_key,
55  public_key);
56 }
57 
59  const otcrypto_unblinded_key_t *public_key,
60  const otcrypto_ecc_curve_t *elliptic_curve,
61  otcrypto_blinded_key_t *shared_secret) {
62  HARDENED_TRY(
63  otcrypto_ecdh_async_start(private_key, public_key, elliptic_curve));
64  return otcrypto_ecdh_async_finalize(elliptic_curve, shared_secret);
65 }
66 
68  otcrypto_blinded_key_t *private_key, otcrypto_unblinded_key_t *public_key) {
69  // TODO: Ed25519 is not yet implemented.
70  return OTCRYPTO_NOT_IMPLEMENTED;
71 }
72 
74  const otcrypto_blinded_key_t *private_key,
75  otcrypto_const_byte_buf_t input_message,
77  // TODO: Ed25519 is not yet implemented.
78  return OTCRYPTO_NOT_IMPLEMENTED;
79 }
80 
82  const otcrypto_unblinded_key_t *public_key,
83  otcrypto_const_byte_buf_t input_message,
85  hardened_bool_t *verification_result) {
86  // TODO: Ed25519 is not yet implemented.
87  return OTCRYPTO_NOT_IMPLEMENTED;
88 }
89 
91  otcrypto_unblinded_key_t *public_key) {
92  // TODO: Connect X25519 operations to API.
93  return OTCRYPTO_NOT_IMPLEMENTED;
94 }
95 
97  const otcrypto_unblinded_key_t *public_key,
98  otcrypto_blinded_key_t *shared_secret) {
99  // TODO: Connect X25519 operations to API.
100  return OTCRYPTO_NOT_IMPLEMENTED;
101 }
102 
103 /**
104  * Calls keymgr to sideload key material into OTBN.
105  *
106  * This routine should only ever be called on hardware-backed keys.
107  *
108  * @param private_key Sideloaded key handle.
109  * @return OK or error.
110  */
112 static status_t sideload_key_seed(const otcrypto_blinded_key_t *private_key) {
113  keymgr_diversification_t diversification;
114  HARDENED_TRY(
115  keyblob_to_keymgr_diversification(private_key, &diversification));
116  return keymgr_generate_key_otbn(diversification);
117 }
118 
120  const otcrypto_ecc_curve_t *elliptic_curve,
121  const otcrypto_blinded_key_t *private_key) {
122  if (elliptic_curve == NULL || private_key == NULL ||
123  private_key->keyblob == NULL) {
124  return OTCRYPTO_BAD_ARGS;
125  }
126 
127  // Check the key mode.
128  if (launder32(private_key->config.key_mode) != kOtcryptoKeyModeEcdsa) {
129  return OTCRYPTO_BAD_ARGS;
130  }
131  HARDENED_CHECK_EQ(private_key->config.key_mode, kOtcryptoKeyModeEcdsa);
132 
133  // Check that the entropy complex is initialized.
134  HARDENED_TRY(entropy_complex_check());
135 
136  // Select the correct keygen operation and start it.
137  switch (launder32(elliptic_curve->curve_type)) {
138  case kOtcryptoEccCurveTypeNistP256:
139  HARDENED_CHECK_EQ(elliptic_curve->curve_type,
140  kOtcryptoEccCurveTypeNistP256);
141  if (launder32(private_key->config.hw_backed) == kHardenedBoolTrue) {
142  HARDENED_CHECK_EQ(private_key->config.hw_backed, kHardenedBoolTrue);
143  HARDENED_TRY(sideload_key_seed(private_key));
144  return ecdsa_p256_sideload_keygen_start();
145  } else if (launder32(private_key->config.hw_backed) ==
147  HARDENED_CHECK_EQ(private_key->config.hw_backed, kHardenedBoolFalse);
148  return ecdsa_p256_keygen_start();
149  } else {
150  return OTCRYPTO_BAD_ARGS;
151  }
152  return OTCRYPTO_OK;
153  case kOtcryptoEccCurveTypeNistP384:
154  HARDENED_CHECK_EQ(elliptic_curve->curve_type,
155  kOtcryptoEccCurveTypeNistP384);
156  if (launder32(private_key->config.hw_backed) == kHardenedBoolTrue) {
157  HARDENED_CHECK_EQ(private_key->config.hw_backed, kHardenedBoolTrue);
158  HARDENED_TRY(sideload_key_seed(private_key));
159  return ecdsa_p384_sideload_keygen_start();
160  } else if (launder32(private_key->config.hw_backed) ==
162  HARDENED_CHECK_EQ(private_key->config.hw_backed, kHardenedBoolFalse);
163  return ecdsa_p384_keygen_start();
164  } else {
165  return OTCRYPTO_BAD_ARGS;
166  }
167  return OTCRYPTO_OK;
168  case kEccCurveTypeBrainpoolP256R1:
170  case kOtcryptoEccCurveTypeCustom:
171  // TODO: Implement support for other curves.
172  return OTCRYPTO_NOT_IMPLEMENTED;
173  default:
174  return OTCRYPTO_BAD_ARGS;
175  }
176 
177  // Should never get here.
178  HARDENED_TRAP();
179  return OTCRYPTO_FATAL_ERR;
180 }
181 
182 /**
183  * Check the lengths of private keys for curve P-256.
184  *
185  * Checks the length of caller-allocated buffers for a P-256 private key. This
186  * function may be used for both ECDSA and ECDH keys, since the key structure
187  * is the same.
188  *
189  * If this check passes and `hw_backed` is false, it is safe to interpret
190  * `private_key->keyblob` as a `p256_masked_scalar_t *`.
191  *
192  * @param private_key Private key struct to check.
193  * @return OK if the lengths are correct or BAD_ARGS otherwise.
194  */
196 static status_t p256_private_key_length_check(
197  const otcrypto_blinded_key_t *private_key) {
198  if (private_key->keyblob == NULL) {
199  return OTCRYPTO_BAD_ARGS;
200  }
201 
202  if (launder32(private_key->config.hw_backed) == kHardenedBoolTrue) {
203  // Skip the length check in this case; if the salt is the wrong length, the
204  // keyblob library will catch it before we sideload the key.
205  return OTCRYPTO_OK;
206  }
207  HARDENED_CHECK_NE(private_key->config.hw_backed, kHardenedBoolTrue);
208 
209  // Check the unmasked length.
210  if (launder32(private_key->config.key_length) != kP256ScalarBytes) {
211  return OTCRYPTO_BAD_ARGS;
212  }
213  HARDENED_CHECK_EQ(private_key->config.key_length, kP256ScalarBytes);
214 
215  // Check the single-share length.
216  if (launder32(keyblob_share_num_words(private_key->config)) !=
217  kP256MaskedScalarShareWords) {
218  return OTCRYPTO_BAD_ARGS;
219  }
220  HARDENED_CHECK_EQ(keyblob_share_num_words(private_key->config),
221  kP256MaskedScalarShareWords);
222 
223  // Check the keyblob length.
224  if (launder32(private_key->keyblob_length) != sizeof(p256_masked_scalar_t)) {
225  return OTCRYPTO_BAD_ARGS;
226  }
227  HARDENED_CHECK_EQ(private_key->keyblob_length, sizeof(p256_masked_scalar_t));
228 
229  return OTCRYPTO_OK;
230 }
231 
232 /**
233  * Check the lengths of public keys for curve P-256.
234  *
235  * Checks the length of caller-allocated buffers for a P-256 public key. This
236  * function may be used for both ECDSA and ECDH keys, since the key structure
237  * is the same.
238  *
239  * If this check passes, it is safe to interpret public_key->key as a
240  * `p256_point_t *`.
241  *
242  * @param public_key Public key struct to check.
243  * @return OK if the lengths are correct or BAD_ARGS otherwise.
244  */
246 static status_t p256_public_key_length_check(
247  const otcrypto_unblinded_key_t *public_key) {
248  if (launder32(public_key->key_length) != sizeof(p256_point_t)) {
249  return OTCRYPTO_BAD_ARGS;
250  }
251  HARDENED_CHECK_EQ(public_key->key_length, sizeof(p256_point_t));
252  return OTCRYPTO_OK;
253 }
254 
255 /**
256  * Check the lengths of private keys for curve P-384.
257  *
258  * Checks the length of caller-allocated buffers for a P-384 private key. This
259  * function may be used for both ECDSA and ECDH keys, since the key structure
260  * is the same.
261  *
262  * If this check passes and `hw_backed` is false, it is safe to interpret
263  * `private_key->keyblob` as a `p384_masked_scalar_t *`.
264  *
265  * @param private_key Private key struct to check.
266  * @return OK if the lengths are correct or BAD_ARGS otherwise.
267  */
269 static status_t p384_private_key_length_check(
270  const otcrypto_blinded_key_t *private_key) {
271  if (private_key->keyblob == NULL) {
272  return OTCRYPTO_BAD_ARGS;
273  }
274 
275  if (launder32(private_key->config.hw_backed) == kHardenedBoolTrue) {
276  // Skip the length check in this case; if the salt is the wrong length, the
277  // keyblob library will catch it before we sideload the key.
278  return OTCRYPTO_OK;
279  }
280  HARDENED_CHECK_NE(private_key->config.hw_backed, kHardenedBoolTrue);
281 
282  // Check the unmasked length.
283  if (launder32(private_key->config.key_length) != kP384ScalarBytes) {
284  return OTCRYPTO_BAD_ARGS;
285  }
286  HARDENED_CHECK_EQ(private_key->config.key_length, kP384ScalarBytes);
287 
288  // Check the single-share length.
289  if (launder32(keyblob_share_num_words(private_key->config)) !=
290  kP384MaskedScalarShareWords) {
291  return OTCRYPTO_BAD_ARGS;
292  }
293  HARDENED_CHECK_EQ(keyblob_share_num_words(private_key->config),
294  kP384MaskedScalarShareWords);
295 
296  // Check the keyblob length.
297  if (launder32(private_key->keyblob_length) != sizeof(p384_masked_scalar_t)) {
298  return OTCRYPTO_BAD_ARGS;
299  }
300  HARDENED_CHECK_EQ(private_key->keyblob_length, sizeof(p384_masked_scalar_t));
301 
302  return OTCRYPTO_OK;
303 }
304 
305 /**
306  * Check the lengths of public keys for curve P-384.
307  *
308  * Checks the length of caller-allocated buffers for a P-384 public key. This
309  * function may be used for both ECDSA and ECDH keys, since the key structure
310  * is the same.
311  *
312  * If this check passes, it is safe to interpret public_key->key as a
313  * `p384_point_t *`.
314  *
315  * @param public_key Public key struct to check.
316  * @return OK if the lengths are correct or BAD_ARGS otherwise.
317  */
319 static status_t p384_public_key_length_check(
320  const otcrypto_unblinded_key_t *public_key) {
321  if (launder32(public_key->key_length) != sizeof(p384_point_t)) {
322  return OTCRYPTO_BAD_ARGS;
323  }
324  HARDENED_CHECK_EQ(public_key->key_length, sizeof(p384_point_t));
325  return OTCRYPTO_OK;
326 }
327 
328 /**
329  * Finalize an ECDSA key generation operation for curve P-256.
330  *
331  * This function assumes that space is already allocated for all key material
332  * and that the length parameters on the structs are set accordingly, in the
333  * same way as for `otcrypto_ecdsa_keygen_async_finalize`.
334  *
335  * @param[out] private_key Private key to populate.
336  * @param[out] public_key Public key to populate.
337  * @return OK or error.
338  */
340 static status_t internal_ecdsa_p256_keygen_finalize(
341  otcrypto_blinded_key_t *private_key, otcrypto_unblinded_key_t *public_key) {
342  // Check the lengths of caller-allocated buffers.
343  HARDENED_TRY(p256_private_key_length_check(private_key));
344  HARDENED_TRY(p256_public_key_length_check(public_key));
345 
346  // Interpret the key buffer as a P-256 point.
347  p256_point_t *pk = (p256_point_t *)public_key->key;
348 
349  if (launder32(private_key->config.hw_backed) == kHardenedBoolTrue) {
350  // Note: This operation wipes DMEM after retrieving the keys, so if an error
351  // occurs after this point then the keys would be unrecoverable. This should
352  // be the last potentially error-causing line before returning to the
353  // caller.
354  HARDENED_CHECK_EQ(private_key->config.hw_backed, kHardenedBoolTrue);
355  HARDENED_TRY(ecdsa_p256_sideload_keygen_finalize(pk));
356  } else if (launder32(private_key->config.hw_backed) == kHardenedBoolFalse) {
357  p256_masked_scalar_t *sk = (p256_masked_scalar_t *)private_key->keyblob;
358  // Note: This operation wipes DMEM after retrieving the keys, so if an error
359  // occurs after this point then the keys would be unrecoverable. This should
360  // be the last potentially error-causing line before returning to the
361  // caller.
362  HARDENED_CHECK_EQ(private_key->config.hw_backed, kHardenedBoolFalse);
363  HARDENED_TRY(ecdsa_p256_keygen_finalize(sk, pk));
364  private_key->checksum = integrity_blinded_checksum(private_key);
365  } else {
366  return OTCRYPTO_BAD_ARGS;
367  }
368 
369  public_key->checksum = integrity_unblinded_checksum(public_key);
370  return OTCRYPTO_OK;
371 }
372 
373 /**
374  * Finalize an ECDSA key generation operation for curve P-384.
375  *
376  * This function assumes that space is already allocated for all key material
377  * and that the length parameters on the structs are set accordingly, in the
378  * same way as for `otcrypto_ecdsa_keygen_async_finalize`.
379  *
380  * @param[out] private_key Private key to populate.
381  * @param[out] public_key Public key to populate.
382  * @return OK or error.
383  */
385 static status_t internal_ecdsa_p384_keygen_finalize(
386  otcrypto_blinded_key_t *private_key, otcrypto_unblinded_key_t *public_key) {
387  // Check the lengths of caller-allocated buffers.
388  HARDENED_TRY(p384_private_key_length_check(private_key));
389  HARDENED_TRY(p384_public_key_length_check(public_key));
390 
391  // Interpret the key buffer as a P-384 point.
392  p384_point_t *pk = (p384_point_t *)public_key->key;
393 
394  if (launder32(private_key->config.hw_backed) == kHardenedBoolTrue) {
395  // Note: This operation wipes DMEM after retrieving the keys, so if an error
396  // occurs after this point then the keys would be unrecoverable. This should
397  // be the last potentially error-causing line before returning to the
398  // caller.
399  HARDENED_CHECK_EQ(private_key->config.hw_backed, kHardenedBoolTrue);
400  HARDENED_TRY(ecdsa_p384_sideload_keygen_finalize(pk));
401  } else if (launder32(private_key->config.hw_backed) == kHardenedBoolFalse) {
402  p384_masked_scalar_t *sk = (p384_masked_scalar_t *)private_key->keyblob;
403  // Note: This operation wipes DMEM after retrieving the keys, so if an error
404  // occurs after this point then the keys would be unrecoverable. This should
405  // be the last potentially error-causing line before returning to the
406  // caller.
407  HARDENED_CHECK_EQ(private_key->config.hw_backed, kHardenedBoolFalse);
408  HARDENED_TRY(ecdsa_p384_keygen_finalize(sk, pk));
409  private_key->checksum = integrity_blinded_checksum(private_key);
410  } else {
411  return OTCRYPTO_BAD_ARGS;
412  }
413 
414  public_key->checksum = integrity_unblinded_checksum(public_key);
415  return OTCRYPTO_OK;
416 }
417 
419  const otcrypto_ecc_curve_t *elliptic_curve,
420  otcrypto_blinded_key_t *private_key, otcrypto_unblinded_key_t *public_key) {
421  // Check for any NULL pointers.
422  if (elliptic_curve == NULL || private_key == NULL || public_key == NULL ||
423  private_key->keyblob == NULL || public_key->key == NULL) {
424  return OTCRYPTO_BAD_ARGS;
425  }
426 
427  // Check the key modes.
428  if (launder32(private_key->config.key_mode) != kOtcryptoKeyModeEcdsa ||
429  launder32(public_key->key_mode) != kOtcryptoKeyModeEcdsa) {
430  return OTCRYPTO_BAD_ARGS;
431  }
432  HARDENED_CHECK_EQ(private_key->config.key_mode, kOtcryptoKeyModeEcdsa);
433  HARDENED_CHECK_EQ(public_key->key_mode, kOtcryptoKeyModeEcdsa);
434 
435  // Select the correct keygen operation and finalize it.
436  switch (launder32(elliptic_curve->curve_type)) {
437  case kOtcryptoEccCurveTypeNistP256:
438  HARDENED_CHECK_EQ(elliptic_curve->curve_type,
439  kOtcryptoEccCurveTypeNistP256);
440  HARDENED_TRY(
441  internal_ecdsa_p256_keygen_finalize(private_key, public_key));
442  break;
443  case kOtcryptoEccCurveTypeNistP384:
444  HARDENED_CHECK_EQ(elliptic_curve->curve_type,
445  kOtcryptoEccCurveTypeNistP384);
446  HARDENED_TRY(
447  internal_ecdsa_p384_keygen_finalize(private_key, public_key));
448  break;
449  case kEccCurveTypeBrainpoolP256R1:
451  case kOtcryptoEccCurveTypeCustom:
452  // TODO: Implement support for other curves.
453  return OTCRYPTO_NOT_IMPLEMENTED;
454  default:
455  return OTCRYPTO_BAD_ARGS;
456  }
457 
458  // Clear the OTBN sideload slot (in case the seed was sideloaded).
459  return keymgr_sideload_clear_otbn();
460 }
461 
462 /**
463  * Start an ECDSA signature generation operation for curve P-256.
464  *
465  * @param private_key Private key to sign with.
466  * @param message_digest Message digest to sign.
467  * @return OK or error.
468  */
470 static status_t internal_ecdsa_p256_sign_start(
471  const otcrypto_blinded_key_t *private_key,
472  const otcrypto_hash_digest_t message_digest) {
473  // Check the digest length.
474  if (launder32(message_digest.len) != kP256ScalarWords) {
475  return OTCRYPTO_BAD_ARGS;
476  }
477  HARDENED_CHECK_EQ(message_digest.len, kP256ScalarWords);
478 
479  // Check the key length.
480  HARDENED_TRY(p256_private_key_length_check(private_key));
481 
482  if (launder32(private_key->config.hw_backed) == kHardenedBoolFalse) {
483  // Start the asynchronous signature-generation routine.
484  HARDENED_CHECK_EQ(private_key->config.hw_backed, kHardenedBoolFalse);
485  p256_masked_scalar_t *sk = (p256_masked_scalar_t *)private_key->keyblob;
486  return ecdsa_p256_sign_start(message_digest.data, sk);
487  } else if (launder32(private_key->config.hw_backed) == kHardenedBoolTrue) {
488  // Load the key and start in sideloaded-key mode.
489  HARDENED_CHECK_EQ(private_key->config.hw_backed, kHardenedBoolTrue);
490  HARDENED_TRY(sideload_key_seed(private_key));
491  return ecdsa_p256_sideload_sign_start(message_digest.data);
492  }
493 
494  // Invalid value for private_key->hw_backed.
495  return OTCRYPTO_BAD_ARGS;
496 }
497 
498 /**
499  * Start an ECDSA signature generation operation for curve P-384.
500  *
501  * @param private_key Private key to sign with.
502  * @param message_digest Message digest to sign.
503  * @return OK or error.
504  */
506 static status_t internal_ecdsa_p384_sign_start(
507  const otcrypto_blinded_key_t *private_key,
508  const otcrypto_hash_digest_t message_digest) {
509  // Check the digest length.
510  if (launder32(message_digest.len) != kP384ScalarWords) {
511  return OTCRYPTO_BAD_ARGS;
512  }
513  HARDENED_CHECK_EQ(message_digest.len, kP384ScalarWords);
514 
515  // Check the key length.
516  HARDENED_TRY(p384_private_key_length_check(private_key));
517 
518  if (launder32(private_key->config.hw_backed) == kHardenedBoolFalse) {
519  // Start the asynchronous signature-generation routine.
520  HARDENED_CHECK_EQ(private_key->config.hw_backed, kHardenedBoolFalse);
521  p384_masked_scalar_t *sk = (p384_masked_scalar_t *)private_key->keyblob;
522  return ecdsa_p384_sign_start(message_digest.data, sk);
523  } else if (launder32(private_key->config.hw_backed) == kHardenedBoolTrue) {
524  // Load the key and start in sideloaded-key mode.
525  HARDENED_CHECK_EQ(private_key->config.hw_backed, kHardenedBoolTrue);
526  HARDENED_TRY(sideload_key_seed(private_key));
527  return ecdsa_p384_sideload_sign_start(message_digest.data);
528  }
529 
530  // Invalid value for private_key->hw_backed.
531  return OTCRYPTO_BAD_ARGS;
532 }
533 
535  const otcrypto_blinded_key_t *private_key,
536  const otcrypto_hash_digest_t message_digest,
537  const otcrypto_ecc_curve_t *elliptic_curve) {
538  if (private_key == NULL || private_key->keyblob == NULL ||
539  elliptic_curve == NULL || message_digest.data == NULL) {
540  return OTCRYPTO_BAD_ARGS;
541  }
542 
543  // Check the integrity of the private key.
544  if (launder32(integrity_blinded_key_check(private_key)) !=
546  return OTCRYPTO_BAD_ARGS;
547  }
548  HARDENED_CHECK_EQ(integrity_blinded_key_check(private_key),
550 
551  // Check the private key mode.
552  if (launder32(private_key->config.key_mode) != kOtcryptoKeyModeEcdsa) {
553  return OTCRYPTO_BAD_ARGS;
554  }
555  HARDENED_CHECK_EQ(private_key->config.key_mode, kOtcryptoKeyModeEcdsa);
556 
557  // Check that the entropy complex is initialized.
558  HARDENED_TRY(entropy_complex_check());
559 
560  // Select the correct signing operation and start it.
561  switch (launder32(elliptic_curve->curve_type)) {
562  case kOtcryptoEccCurveTypeNistP256:
563  HARDENED_CHECK_EQ(elliptic_curve->curve_type,
564  kOtcryptoEccCurveTypeNistP256);
565  HARDENED_TRY(internal_ecdsa_p256_sign_start(private_key, message_digest));
566  return OTCRYPTO_OK;
567  case kOtcryptoEccCurveTypeNistP384:
568  HARDENED_CHECK_EQ(elliptic_curve->curve_type,
569  kOtcryptoEccCurveTypeNistP384);
570  HARDENED_TRY(internal_ecdsa_p384_sign_start(private_key, message_digest));
571  return OTCRYPTO_OK;
572  case kEccCurveTypeBrainpoolP256R1:
574  case kOtcryptoEccCurveTypeCustom:
575  // TODO: Implement support for other curves.
576  return OTCRYPTO_NOT_IMPLEMENTED;
577  default:
578  return OTCRYPTO_BAD_ARGS;
579  }
580 
581  // Should never get here.
582  HARDENED_TRAP();
583  return OTCRYPTO_FATAL_ERR;
584 }
585 
586 /**
587  * Check the length of a signature buffer for ECDSA with P-256.
588  *
589  * If this check passes on `signature.len`, it is safe to interpret
590  * `signature.data` as `ecdsa_p256_signature_t *`.
591  *
592  * @param len Length to check.
593  * @return OK if the lengths are correct or BAD_ARGS otherwise.
594  */
596 static status_t p256_signature_length_check(size_t len) {
597  if (launder32(len) > UINT32_MAX / sizeof(uint32_t) ||
598  launder32(len) * sizeof(uint32_t) != sizeof(ecdsa_p256_signature_t)) {
599  return OTCRYPTO_BAD_ARGS;
600  }
601  HARDENED_CHECK_EQ(len * sizeof(uint32_t), sizeof(ecdsa_p256_signature_t));
602 
603  return OTCRYPTO_OK;
604 }
605 
606 /**
607  * Check the length of a signature buffer for ECDSA with P-384.
608  *
609  * If this check passes on `signature.len`, it is safe to interpret
610  * `signature.data` as `ecdsa_p384_signature_t *`.
611  *
612  * @param len Length to check.
613  * @return OK if the lengths are correct or BAD_ARGS otherwise.
614  */
616 static status_t p384_signature_length_check(size_t len) {
617  if (launder32(len) > UINT32_MAX / sizeof(uint32_t) ||
618  launder32(len) * sizeof(uint32_t) != sizeof(ecdsa_p384_signature_t)) {
619  return OTCRYPTO_BAD_ARGS;
620  }
621  HARDENED_CHECK_EQ(len * sizeof(uint32_t), sizeof(ecdsa_p384_signature_t));
622 
623  return OTCRYPTO_OK;
624 }
625 
627  const otcrypto_ecc_curve_t *elliptic_curve,
628  otcrypto_word32_buf_t signature) {
629  if (elliptic_curve == NULL || signature.data == NULL) {
630  return OTCRYPTO_BAD_ARGS;
631  }
632 
633  // Select the correct signing operation and finalize it.
634  switch (launder32(elliptic_curve->curve_type)) {
635  case kOtcryptoEccCurveTypeNistP256:
636  HARDENED_CHECK_EQ(elliptic_curve->curve_type,
637  kOtcryptoEccCurveTypeNistP256);
638  HARDENED_TRY(p256_signature_length_check(signature.len));
639  ecdsa_p256_signature_t *sig_p256 =
640  (ecdsa_p256_signature_t *)signature.data;
641  // Note: This operation wipes DMEM, so if an error occurs after this
642  // point then the signature would be unrecoverable. This should be the
643  // last potentially error-causing line before returning to the caller.
644  HARDENED_TRY(ecdsa_p256_sign_finalize(sig_p256));
645  break;
646  case kOtcryptoEccCurveTypeNistP384:
647  HARDENED_CHECK_EQ(elliptic_curve->curve_type,
648  kOtcryptoEccCurveTypeNistP384);
649  HARDENED_TRY(p384_signature_length_check(signature.len));
650  ecdsa_p384_signature_t *sig_p384 =
651  (ecdsa_p384_signature_t *)signature.data;
652  // Note: This operation wipes DMEM, so if an error occurs after this
653  // point then the signature would be unrecoverable. This should be the
654  // last potentially error-causing line before returning to the caller.
655  HARDENED_TRY(ecdsa_p384_sign_finalize(sig_p384));
656  break;
657  case kEccCurveTypeBrainpoolP256R1:
659  case kOtcryptoEccCurveTypeCustom:
660  // TODO: Implement support for other curves.
661  return OTCRYPTO_NOT_IMPLEMENTED;
662  default:
663  return OTCRYPTO_BAD_ARGS;
664  }
665 
666  // Clear the OTBN sideload slot (in case the key was sideloaded).
667  return keymgr_sideload_clear_otbn();
668 }
669 
670 /**
671  * Start an ECDSA signature verification operation for curve P-256.
672  *
673  * @param public_key Public key to check against.
674  * @param message_digest Message digest to check against.
675  * @param signature Signature to verify.
676  * @return OK or error.
677  */
679 static status_t internal_ecdsa_p256_verify_start(
680  const otcrypto_unblinded_key_t *public_key,
681  const otcrypto_hash_digest_t message_digest,
682  otcrypto_const_word32_buf_t signature) {
683  // Check the public key size.
684  HARDENED_TRY(p256_public_key_length_check(public_key));
685  p256_point_t *pk = (p256_point_t *)public_key->key;
686 
687  // Check the digest length.
688  if (launder32(message_digest.len) != kP256ScalarWords) {
689  return OTCRYPTO_BAD_ARGS;
690  }
691  HARDENED_CHECK_EQ(message_digest.len, kP256ScalarWords);
692 
693  // Check the signature lengths.
694  HARDENED_TRY(p256_signature_length_check(signature.len));
695  ecdsa_p256_signature_t *sig = (ecdsa_p256_signature_t *)signature.data;
696 
697  // Start the asynchronous signature-verification routine.
698  return ecdsa_p256_verify_start(sig, message_digest.data, pk);
699 }
700 
701 /**
702  * Start an ECDSA signature verification operation for curve P-384.
703  *
704  * @param public_key Public key to check against.
705  * @param message_digest Message digest to check against.
706  * @param signature Signature to verify.
707  * @return OK or error.
708  */
710 static status_t internal_ecdsa_p384_verify_start(
711  const otcrypto_unblinded_key_t *public_key,
712  const otcrypto_hash_digest_t message_digest,
713  otcrypto_const_word32_buf_t signature) {
714  // Check the public key size.
715  HARDENED_TRY(p384_public_key_length_check(public_key));
716  p384_point_t *pk = (p384_point_t *)public_key->key;
717 
718  // Check the digest length.
719  if (launder32(message_digest.len) != kP384ScalarWords) {
720  return OTCRYPTO_BAD_ARGS;
721  }
722  HARDENED_CHECK_EQ(message_digest.len, kP384ScalarWords);
723 
724  // Check the signature lengths.
725  HARDENED_TRY(p384_signature_length_check(signature.len));
726  ecdsa_p384_signature_t *sig = (ecdsa_p384_signature_t *)signature.data;
727 
728  // Start the asynchronous signature-verification routine.
729  return ecdsa_p384_verify_start(sig, message_digest.data, pk);
730 }
731 
733  const otcrypto_unblinded_key_t *public_key,
734  const otcrypto_hash_digest_t message_digest,
735  otcrypto_const_word32_buf_t signature,
736  const otcrypto_ecc_curve_t *elliptic_curve) {
737  if (public_key == NULL || elliptic_curve == NULL || signature.data == NULL ||
738  message_digest.data == NULL || public_key->key == NULL) {
739  return OTCRYPTO_BAD_ARGS;
740  }
741 
742  // Check the public key mode.
743  if (launder32(public_key->key_mode) != kOtcryptoKeyModeEcdsa) {
744  return OTCRYPTO_BAD_ARGS;
745  }
746  HARDENED_CHECK_EQ(public_key->key_mode, kOtcryptoKeyModeEcdsa);
747 
748  // Check the integrity of the public key.
749  if (launder32(integrity_unblinded_key_check(public_key)) !=
751  return OTCRYPTO_BAD_ARGS;
752  }
753  HARDENED_CHECK_EQ(integrity_unblinded_key_check(public_key),
755 
756  // Select the correct verification operation and start it.
757  switch (launder32(elliptic_curve->curve_type)) {
758  case kOtcryptoEccCurveTypeNistP256:
759  HARDENED_CHECK_EQ(elliptic_curve->curve_type,
760  kOtcryptoEccCurveTypeNistP256);
761  HARDENED_TRY(internal_ecdsa_p256_verify_start(public_key, message_digest,
762  signature));
763  return OTCRYPTO_OK;
764  case kOtcryptoEccCurveTypeNistP384:
765  HARDENED_CHECK_EQ(elliptic_curve->curve_type,
766  kOtcryptoEccCurveTypeNistP384);
767  HARDENED_TRY(internal_ecdsa_p384_verify_start(public_key, message_digest,
768  signature));
769  return OTCRYPTO_OK;
770  case kEccCurveTypeBrainpoolP256R1:
772  case kOtcryptoEccCurveTypeCustom:
773  // TODO: Implement support for other curves.
774  return OTCRYPTO_NOT_IMPLEMENTED;
775  default:
776  return OTCRYPTO_BAD_ARGS;
777  }
778 
779  // Should never get here.
780  HARDENED_TRAP();
781  return OTCRYPTO_FATAL_ERR;
782 }
783 
785  const otcrypto_ecc_curve_t *elliptic_curve,
786  otcrypto_const_word32_buf_t signature,
787  hardened_bool_t *verification_result) {
788  if (elliptic_curve == NULL || verification_result == NULL) {
789  return OTCRYPTO_BAD_ARGS;
790  }
791 
792  // Select the correct verification operation and finalize it.
793  switch (launder32(elliptic_curve->curve_type)) {
794  case kOtcryptoEccCurveTypeNistP256:
795  HARDENED_CHECK_EQ(elliptic_curve->curve_type,
796  kOtcryptoEccCurveTypeNistP256);
797  HARDENED_TRY(p256_signature_length_check(signature.len));
798  ecdsa_p256_signature_t *sig_p256 =
799  (ecdsa_p256_signature_t *)signature.data;
800  return ecdsa_p256_verify_finalize(sig_p256, verification_result);
801  case kOtcryptoEccCurveTypeNistP384:
802  HARDENED_CHECK_EQ(elliptic_curve->curve_type,
803  kOtcryptoEccCurveTypeNistP384);
804  HARDENED_TRY(p384_signature_length_check(signature.len));
805  ecdsa_p384_signature_t *sig_p384 =
806  (ecdsa_p384_signature_t *)signature.data;
807  return ecdsa_p384_verify_finalize(sig_p384, verification_result);
808  case kEccCurveTypeBrainpoolP256R1:
810  case kOtcryptoEccCurveTypeCustom:
811  // TODO: Implement support for other curves.
812  return OTCRYPTO_NOT_IMPLEMENTED;
813  default:
814  return OTCRYPTO_BAD_ARGS;
815  }
816 
817  // Should never get here.
818  HARDENED_TRAP();
819  return OTCRYPTO_FATAL_ERR;
820 }
821 
823  const otcrypto_ecc_curve_t *elliptic_curve,
824  const otcrypto_blinded_key_t *private_key) {
825  if (elliptic_curve == NULL || private_key == NULL ||
826  private_key->keyblob == NULL) {
827  return OTCRYPTO_BAD_ARGS;
828  }
829 
830  // Check the key mode.
831  if (launder32(private_key->config.key_mode) != kOtcryptoKeyModeEcdh) {
832  return OTCRYPTO_BAD_ARGS;
833  }
834  HARDENED_CHECK_EQ(private_key->config.key_mode, kOtcryptoKeyModeEcdh);
835 
836  // Check that the entropy complex is initialized.
837  HARDENED_TRY(entropy_complex_check());
838 
839  // Select the correct keygen operation and start it.
840  switch (launder32(elliptic_curve->curve_type)) {
841  case kOtcryptoEccCurveTypeNistP256:
842  HARDENED_CHECK_EQ(elliptic_curve->curve_type,
843  kOtcryptoEccCurveTypeNistP256);
844  if (launder32(private_key->config.hw_backed) == kHardenedBoolTrue) {
845  HARDENED_CHECK_EQ(private_key->config.hw_backed, kHardenedBoolTrue);
846  HARDENED_TRY(sideload_key_seed(private_key));
847  return ecdh_p256_sideload_keypair_start();
848  } else if (launder32(private_key->config.hw_backed) ==
850  return ecdh_p256_keypair_start();
851  }
852  return OTCRYPTO_BAD_ARGS;
853  case kOtcryptoEccCurveTypeNistP384:
854  HARDENED_CHECK_EQ(elliptic_curve->curve_type,
855  kOtcryptoEccCurveTypeNistP384);
856  if (launder32(private_key->config.hw_backed) == kHardenedBoolTrue) {
857  HARDENED_CHECK_EQ(private_key->config.hw_backed, kHardenedBoolTrue);
858  HARDENED_TRY(sideload_key_seed(private_key));
859  return ecdh_p384_sideload_keypair_start();
860  } else if (launder32(private_key->config.hw_backed) ==
862  HARDENED_CHECK_EQ(private_key->config.hw_backed, kHardenedBoolFalse);
863  return ecdh_p384_keypair_start();
864  }
865  return OTCRYPTO_BAD_ARGS;
866  case kEccCurveTypeBrainpoolP256R1:
868  case kOtcryptoEccCurveTypeCustom:
869  // TODO: Implement support for other curves.
870  return OTCRYPTO_NOT_IMPLEMENTED;
871  default:
872  return OTCRYPTO_BAD_ARGS;
873  }
874 
875  // Should never get here.
876  HARDENED_TRAP();
877  return OTCRYPTO_FATAL_ERR;
878 }
879 
880 /**
881  * Finalize an ECDH keypair generation operation for curve P-256.
882  *
883  * This function assumes that space is already allocated for all key material
884  * and that the length parameters on the structs are set accordingly, in the
885  * same way as for `otcrypto_ecdh_keygen_async_finalize`.
886  *
887  * @param[out] private_key Private key to populate.
888  * @param[out] public_key Public key to populate.
889  * @return OK or error.
890  */
892 static status_t internal_ecdh_p256_keygen_finalize(
893  otcrypto_blinded_key_t *private_key, otcrypto_unblinded_key_t *public_key) {
894  // Check the lengths of caller-allocated buffers.
895  HARDENED_TRY(p256_private_key_length_check(private_key));
896  HARDENED_TRY(p256_public_key_length_check(public_key));
897  p256_point_t *pk = (p256_point_t *)public_key->key;
898 
899  // Note: The `finalize` operations wipe DMEM after retrieving the keys, so if
900  // an error occurs after this point then the keys would be unrecoverable.
901  // The `finalize` call should be the last potentially error-causing line
902  // before returning to the caller.
903 
904  if (launder32(private_key->config.hw_backed) == kHardenedBoolTrue) {
905  HARDENED_CHECK_EQ(private_key->config.hw_backed, kHardenedBoolTrue);
906  HARDENED_TRY(ecdh_p256_sideload_keypair_finalize(pk));
907  } else if (launder32(private_key->config.hw_backed) == kHardenedBoolFalse) {
908  HARDENED_CHECK_EQ(private_key->config.hw_backed, kHardenedBoolFalse);
909  p256_masked_scalar_t *sk = (p256_masked_scalar_t *)private_key->keyblob;
910  HARDENED_TRY(ecdh_p256_keypair_finalize(sk, pk));
911  private_key->checksum = integrity_blinded_checksum(private_key);
912  } else {
913  return OTCRYPTO_BAD_ARGS;
914  }
915 
916  // Prepare the public key.
917  public_key->checksum = integrity_unblinded_checksum(public_key);
918 
919  // Clear the OTBN sideload slot (in case the seed was sideloaded).
920  return keymgr_sideload_clear_otbn();
921 }
922 
923 /**
924  * Finalize an ECDH keypair generation operation for curve P-384.
925  *
926  * This function assumes that space is already allocated for all key material
927  * and that the length parameters on the structs are set accordingly, in the
928  * same way as for `otcrypto_ecdh_keygen_async_finalize`.
929  *
930  * @param[out] private_key Private key to populate.
931  * @param[out] public_key Public key to populate.
932  * @return OK or error.
933  */
935 static status_t internal_ecdh_p384_keygen_finalize(
936  otcrypto_blinded_key_t *private_key, otcrypto_unblinded_key_t *public_key) {
937  // Check the lengths of caller-allocated buffers.
938  HARDENED_TRY(p384_private_key_length_check(private_key));
939  HARDENED_TRY(p384_public_key_length_check(public_key));
940  p384_point_t *pk = (p384_point_t *)public_key->key;
941 
942  // Note: The `finalize` operations wipe DMEM after retrieving the keys, so if
943  // an error occurs after this point then the keys would be unrecoverable.
944  // The `finalize` call should be the last potentially error-causing line
945  // before returning to the caller.
946 
947  if (launder32(private_key->config.hw_backed) == kHardenedBoolTrue) {
948  HARDENED_CHECK_EQ(private_key->config.hw_backed, kHardenedBoolTrue);
949  HARDENED_TRY(ecdh_p384_sideload_keypair_finalize(pk));
950  } else if (launder32(private_key->config.hw_backed) == kHardenedBoolFalse) {
951  HARDENED_CHECK_EQ(private_key->config.hw_backed, kHardenedBoolFalse);
952  p384_masked_scalar_t *sk = (p384_masked_scalar_t *)private_key->keyblob;
953  HARDENED_TRY(ecdh_p384_keypair_finalize(sk, pk));
954  private_key->checksum = integrity_blinded_checksum(private_key);
955  } else {
956  return OTCRYPTO_BAD_ARGS;
957  }
958 
959  // Prepare the public key.
960  public_key->checksum = integrity_unblinded_checksum(public_key);
961 
962  // Clear the OTBN sideload slot (in case the seed was sideloaded).
963  return keymgr_sideload_clear_otbn();
964 }
965 
967  const otcrypto_ecc_curve_t *elliptic_curve,
968  otcrypto_blinded_key_t *private_key, otcrypto_unblinded_key_t *public_key) {
969  // Check for any NULL pointers.
970  if (elliptic_curve == NULL || private_key == NULL || public_key == NULL ||
971  private_key->keyblob == NULL || public_key->key == NULL) {
972  return OTCRYPTO_BAD_ARGS;
973  }
974 
975  // Check the key modes.
976  if (launder32(public_key->key_mode) != kOtcryptoKeyModeEcdh ||
977  launder32(private_key->config.key_mode) != kOtcryptoKeyModeEcdh) {
978  return OTCRYPTO_BAD_ARGS;
979  }
980  HARDENED_CHECK_EQ(public_key->key_mode, kOtcryptoKeyModeEcdh);
981  HARDENED_CHECK_EQ(private_key->config.key_mode, kOtcryptoKeyModeEcdh);
982 
983  // Select the correct keygen operation and finalize it.
984  switch (launder32(elliptic_curve->curve_type)) {
985  case kOtcryptoEccCurveTypeNistP256:
986  HARDENED_CHECK_EQ(elliptic_curve->curve_type,
987  kOtcryptoEccCurveTypeNistP256);
988  HARDENED_TRY(internal_ecdh_p256_keygen_finalize(private_key, public_key));
989  break;
990  case kOtcryptoEccCurveTypeNistP384:
991  HARDENED_CHECK_EQ(elliptic_curve->curve_type,
992  kOtcryptoEccCurveTypeNistP384);
993  HARDENED_TRY(internal_ecdh_p384_keygen_finalize(private_key, public_key));
994  break;
995  case kEccCurveTypeBrainpoolP256R1:
997  case kOtcryptoEccCurveTypeCustom:
998  // TODO: Implement support for other curves.
999  return OTCRYPTO_NOT_IMPLEMENTED;
1000  default:
1001  return OTCRYPTO_BAD_ARGS;
1002  }
1003 
1004  // Clear the OTBN sideload slot (in case the key was sideloaded).
1005  return keymgr_sideload_clear_otbn();
1006 }
1007 
1008 /**
1009  * Start an ECDH shared key generation operation for curve P-256.
1010  *
1011  * @param private_key Private key for key exchange.
1012  * @param public_key Public key for key exchange.
1013  * @return OK or error.
1014  */
1016 static status_t internal_ecdh_p256_start(
1017  const otcrypto_blinded_key_t *private_key,
1018  const otcrypto_unblinded_key_t *public_key) {
1019  HARDENED_TRY(p256_private_key_length_check(private_key));
1020  HARDENED_TRY(p256_public_key_length_check(public_key));
1021  p256_point_t *pk = (p256_point_t *)public_key->key;
1022 
1023  if (launder32(private_key->config.hw_backed) == kHardenedBoolTrue) {
1024  HARDENED_CHECK_EQ(private_key->config.hw_backed, kHardenedBoolTrue);
1025  HARDENED_TRY(sideload_key_seed(private_key));
1026  return ecdh_p256_sideload_shared_key_start(pk);
1027  } else if (launder32(private_key->config.hw_backed) == kHardenedBoolFalse) {
1028  HARDENED_CHECK_EQ(private_key->config.hw_backed, kHardenedBoolFalse);
1029  p256_masked_scalar_t *sk = (p256_masked_scalar_t *)private_key->keyblob;
1030  return ecdh_p256_shared_key_start(sk, pk);
1031  }
1032 
1033  // Invalid value for `hw_backed`.
1034  return OTCRYPTO_BAD_ARGS;
1035 }
1036 
1037 /**
1038  * Start an ECDH shared key generation operation for curve P-384.
1039  *
1040  * @param private_key Private key for key exchange.
1041  * @param public_key Public key for key exchange.
1042  * @return OK or error.
1043  */
1045 static status_t internal_ecdh_p384_start(
1046  const otcrypto_blinded_key_t *private_key,
1047  const otcrypto_unblinded_key_t *public_key) {
1048  HARDENED_TRY(p384_private_key_length_check(private_key));
1049  HARDENED_TRY(p384_public_key_length_check(public_key));
1050  p384_point_t *pk = (p384_point_t *)public_key->key;
1051 
1052  if (launder32(private_key->config.hw_backed) == kHardenedBoolTrue) {
1053  HARDENED_CHECK_EQ(private_key->config.hw_backed, kHardenedBoolTrue);
1054  HARDENED_TRY(sideload_key_seed(private_key));
1055  return ecdh_p384_sideload_shared_key_start(pk);
1056  } else if (launder32(private_key->config.hw_backed) == kHardenedBoolFalse) {
1057  HARDENED_CHECK_EQ(private_key->config.hw_backed, kHardenedBoolFalse);
1058  p384_masked_scalar_t *sk = (p384_masked_scalar_t *)private_key->keyblob;
1059  return ecdh_p384_shared_key_start(sk, pk);
1060  }
1061 
1062  // Invalid value for `hw_backed`.
1063  return OTCRYPTO_BAD_ARGS;
1064 }
1065 
1067  const otcrypto_blinded_key_t *private_key,
1068  const otcrypto_unblinded_key_t *public_key,
1069  const otcrypto_ecc_curve_t *elliptic_curve) {
1070  if (private_key == NULL || public_key == NULL || elliptic_curve == NULL ||
1071  public_key->key == NULL || private_key->keyblob == NULL) {
1072  return OTCRYPTO_BAD_ARGS;
1073  }
1074 
1075  // Check the integrity of the keys.
1076  if (launder32(integrity_blinded_key_check(private_key)) !=
1078  launder32(integrity_unblinded_key_check(public_key)) !=
1080  return OTCRYPTO_BAD_ARGS;
1081  }
1082  HARDENED_CHECK_EQ(integrity_blinded_key_check(private_key),
1084  HARDENED_CHECK_EQ(integrity_unblinded_key_check(public_key),
1086 
1087  // Check the key modes.
1088  if (launder32(private_key->config.key_mode) != kOtcryptoKeyModeEcdh ||
1089  launder32(public_key->key_mode) != kOtcryptoKeyModeEcdh) {
1090  return OTCRYPTO_BAD_ARGS;
1091  }
1092  HARDENED_CHECK_EQ(private_key->config.key_mode, kOtcryptoKeyModeEcdh);
1093  HARDENED_CHECK_EQ(public_key->key_mode, kOtcryptoKeyModeEcdh);
1094 
1095  // Select the correct ECDH operation and start it.
1096  switch (launder32(elliptic_curve->curve_type)) {
1097  case kOtcryptoEccCurveTypeNistP256:
1098  HARDENED_CHECK_EQ(elliptic_curve->curve_type,
1099  kOtcryptoEccCurveTypeNistP256);
1100  HARDENED_TRY(internal_ecdh_p256_start(private_key, public_key));
1101  return OTCRYPTO_OK;
1102  case kOtcryptoEccCurveTypeNistP384:
1103  HARDENED_CHECK_EQ(elliptic_curve->curve_type,
1104  kOtcryptoEccCurveTypeNistP384);
1105  HARDENED_TRY(internal_ecdh_p384_start(private_key, public_key));
1106  return OTCRYPTO_OK;
1107  case kEccCurveTypeBrainpoolP256R1:
1109  case kOtcryptoEccCurveTypeCustom:
1110  // TODO: Implement support for other curves.
1111  return OTCRYPTO_NOT_IMPLEMENTED;
1112  default:
1113  return OTCRYPTO_BAD_ARGS;
1114  }
1115 
1116  // Should never get here.
1117  HARDENED_TRAP();
1118  return OTCRYPTO_FATAL_ERR;
1119 }
1120 
1121 /**
1122  * Finish an ECDH shared key generation operation for curve P-256.
1123  *
1124  * @param[out] shared_secret Resulting shared secret.
1125  * @return OK or error.
1126  */
1128 static status_t internal_ecdh_p256_finalize(
1129  otcrypto_blinded_key_t *shared_secret) {
1130  if (launder32(shared_secret->config.hw_backed) != kHardenedBoolFalse) {
1131  // Shared keys cannot be sideloaded because they are software-generated.
1132  return OTCRYPTO_BAD_ARGS;
1133  }
1134  HARDENED_CHECK_EQ(shared_secret->config.hw_backed, kHardenedBoolFalse);
1135 
1136  if (shared_secret->keyblob == NULL) {
1137  return OTCRYPTO_BAD_ARGS;
1138  }
1139 
1140  if (launder32(shared_secret->config.key_length) != kP256CoordBytes) {
1141  return OTCRYPTO_BAD_ARGS;
1142  }
1143  HARDENED_CHECK_EQ(shared_secret->config.key_length, kP256CoordBytes);
1144 
1145  if (launder32(shared_secret->keyblob_length) !=
1146  keyblob_num_words(shared_secret->config) * sizeof(uint32_t)) {
1147  return OTCRYPTO_BAD_ARGS;
1148  }
1150  shared_secret->keyblob_length,
1151  keyblob_num_words(shared_secret->config) * sizeof(uint32_t));
1152 
1153  // Note: This operation wipes DMEM after retrieving the keys, so if an error
1154  // occurs after this point then the keys would be unrecoverable. This should
1155  // be the last potentially error-causing line before returning to the caller.
1157  HARDENED_TRY(ecdh_p256_shared_key_finalize(&ss));
1158 
1159  keyblob_from_shares(ss.share0, ss.share1, shared_secret->config,
1160  shared_secret->keyblob);
1161 
1162  // Set the checksum.
1163  shared_secret->checksum = integrity_blinded_checksum(shared_secret);
1164 
1165  // Clear the OTBN sideload slot (in case the seed was sideloaded).
1166  return keymgr_sideload_clear_otbn();
1167 }
1168 
1169 /**
1170  * Finish an ECDH shared key generation operation for curve P-384.
1171  *
1172  * @param[out] shared_secret Resulting shared secret.
1173  * @return OK or error.
1174  */
1176 static status_t internal_ecdh_p384_finalize(
1177  otcrypto_blinded_key_t *shared_secret) {
1178  if (launder32(shared_secret->config.hw_backed) != kHardenedBoolFalse) {
1179  // Shared keys cannot be sideloaded because they are software-generated.
1180  return OTCRYPTO_BAD_ARGS;
1181  }
1182  HARDENED_CHECK_EQ(shared_secret->config.hw_backed, kHardenedBoolFalse);
1183 
1184  if (shared_secret->keyblob == NULL) {
1185  return OTCRYPTO_BAD_ARGS;
1186  }
1187 
1188  if (launder32(shared_secret->config.key_length) != kP384CoordBytes) {
1189  return OTCRYPTO_BAD_ARGS;
1190  }
1191  HARDENED_CHECK_EQ(shared_secret->config.key_length, kP384CoordBytes);
1192 
1193  if (launder32(shared_secret->keyblob_length) !=
1194  keyblob_num_words(shared_secret->config) * sizeof(uint32_t)) {
1195  return OTCRYPTO_BAD_ARGS;
1196  }
1198  shared_secret->keyblob_length,
1199  keyblob_num_words(shared_secret->config) * sizeof(uint32_t));
1200 
1201  // Note: This operation wipes DMEM after retrieving the keys, so if an error
1202  // occurs after this point then the keys would be unrecoverable. This should
1203  // be the last potentially error-causing line before returning to the caller.
1205  HARDENED_TRY(ecdh_p384_shared_key_finalize(&ss));
1206 
1207  keyblob_from_shares(ss.share0, ss.share1, shared_secret->config,
1208  shared_secret->keyblob);
1209 
1210  // Set the checksum.
1211  shared_secret->checksum = integrity_blinded_checksum(shared_secret);
1212 
1213  // Clear the OTBN sideload slot (in case the seed was sideloaded).
1214  return keymgr_sideload_clear_otbn();
1215 }
1216 
1218  const otcrypto_ecc_curve_t *elliptic_curve,
1219  otcrypto_blinded_key_t *shared_secret) {
1220  if (shared_secret == NULL || elliptic_curve == NULL) {
1221  return OTCRYPTO_BAD_ARGS;
1222  }
1223 
1224  // Select the correct ECDH operation and finalize it.
1225  switch (launder32(elliptic_curve->curve_type)) {
1226  case kOtcryptoEccCurveTypeNistP256:
1227  HARDENED_CHECK_EQ(elliptic_curve->curve_type,
1228  kOtcryptoEccCurveTypeNistP256);
1229  HARDENED_TRY(internal_ecdh_p256_finalize(shared_secret));
1230  break;
1231  case kOtcryptoEccCurveTypeNistP384:
1232  HARDENED_CHECK_EQ(elliptic_curve->curve_type,
1233  kOtcryptoEccCurveTypeNistP384);
1234  HARDENED_TRY(internal_ecdh_p384_finalize(shared_secret));
1235  break;
1236  case kEccCurveTypeBrainpoolP256R1:
1238  case kOtcryptoEccCurveTypeCustom:
1239  // TODO: Implement support for other curves.
1240  return OTCRYPTO_NOT_IMPLEMENTED;
1241  default:
1242  return OTCRYPTO_BAD_ARGS;
1243  }
1244 
1245  // Clear the OTBN sideload slot (in case the key was sideloaded).
1246  return keymgr_sideload_clear_otbn();
1247 }
1248 
1250  const otcrypto_blinded_key_t *private_key) {
1251  // TODO: Ed25519 is not yet implemented.
1252  return OTCRYPTO_NOT_IMPLEMENTED;
1253 }
1254 
1256  otcrypto_blinded_key_t *private_key, otcrypto_unblinded_key_t *public_key) {
1257  // TODO: Ed25519 is not yet implemented.
1258  return OTCRYPTO_NOT_IMPLEMENTED;
1259 }
1260 
1262  const otcrypto_blinded_key_t *private_key,
1263  otcrypto_const_byte_buf_t input_message,
1264  otcrypto_eddsa_sign_mode_t sign_mode, otcrypto_word32_buf_t signature) {
1265  // TODO: Ed25519 is not yet implemented.
1266  return OTCRYPTO_NOT_IMPLEMENTED;
1267 }
1268 
1270  otcrypto_word32_buf_t signature) {
1271  // TODO: Ed25519 is not yet implemented.
1272  return OTCRYPTO_NOT_IMPLEMENTED;
1273 }
1274 
1276  const otcrypto_unblinded_key_t *public_key,
1277  otcrypto_const_byte_buf_t input_message,
1278  otcrypto_eddsa_sign_mode_t sign_mode,
1279  otcrypto_const_word32_buf_t signature) {
1280  // TODO: Ed25519 is not yet implemented.
1281  return OTCRYPTO_NOT_IMPLEMENTED;
1282 }
1283 
1285  hardened_bool_t *verification_result) {
1286  // TODO: Ed25519 is not yet implemented.
1287  return OTCRYPTO_NOT_IMPLEMENTED;
1288 }
1289 
1291  const otcrypto_blinded_key_t *private_key) {
1292  // TODO: X25519 is not yet implemented.
1293  return OTCRYPTO_NOT_IMPLEMENTED;
1294 }
1295 
1297  otcrypto_blinded_key_t *private_key, otcrypto_unblinded_key_t *public_key) {
1298  // TODO: X25519 is not yet implemented.
1299  return OTCRYPTO_NOT_IMPLEMENTED;
1300 }
1301 
1303  const otcrypto_blinded_key_t *private_key,
1304  const otcrypto_unblinded_key_t *public_key) {
1305  // TODO: X25519 is not yet implemented.
1306  return OTCRYPTO_NOT_IMPLEMENTED;
1307 }
1308 
1310  otcrypto_blinded_key_t *shared_secret) {
1311  // TODO: X25519 is not yet implemented.
1312  return OTCRYPTO_NOT_IMPLEMENTED;
1313 }