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