Software APIs
ecdsa.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 #include "sw/device/lib/base/status.h"
7 #include "sw/device/lib/crypto/impl/ecc/p256.h"
8 #include "sw/device/lib/crypto/impl/ecc/p384.h"
9 #include "sw/device/lib/crypto/impl/integrity.h"
10 #include "sw/device/lib/crypto/impl/keyblob.h"
15 #include "sw/device/lib/testing/test_framework/ujson_ottf.h"
16 #include "sw/device/lib/ujson/ujson.h"
17 #include "sw/device/tests/crypto/cryptotest/json/ecdsa_commands.h"
18 
19 // Copied from //sw/device/tests/crypto/ecdsa_p256_functest.c
20 enum {
21  /* Number of bytes in a P-256 private key. */
22  kP256PrivateKeyBytes = 256 / 8,
23  /* Number of bytes in a P-384 private key. */
24  kP384PrivateKeyBytes = 384 / 8,
25 };
26 
27 static const otcrypto_key_config_t kP256PrivateKeyConfig = {
28  .version = kOtcryptoLibVersion1,
29  .key_mode = kOtcryptoKeyModeEcdsaP256,
30  .key_length = kP256PrivateKeyBytes,
31  .hw_backed = kHardenedBoolFalse,
32  .security_level = kOtcryptoKeySecurityLevelLow,
33 };
34 
35 static const otcrypto_key_config_t kP384PrivateKeyConfig = {
36  .version = kOtcryptoLibVersion1,
37  .key_mode = kOtcryptoKeyModeEcdsaP384,
38  .key_length = kP384PrivateKeyBytes,
39  .hw_backed = kHardenedBoolFalse,
40  .security_level = kOtcryptoKeySecurityLevelLow,
41 };
42 
43 int set_nist_p256_params(cryptotest_ecdsa_coordinate_t uj_qx,
44  cryptotest_ecdsa_coordinate_t uj_qy,
45  cryptotest_ecdsa_signature_t uj_signature,
46  otcrypto_unblinded_key_t *public_key,
47  p256_ecdsa_signature_t *signature_p256,
48  p256_point_t *pub_p256,
49  otcrypto_word32_buf_t *signature_mut,
50  size_t *digest_len) {
51  if (uj_qx.coordinate_len > kP256CoordBytes) {
52  LOG_ERROR(
53  "Coordinate value qx too large for P256 (have = %d bytes, max = %d "
54  "bytes)",
55  uj_qx.coordinate_len, kP256CoordBytes);
56  return false;
57  }
58  if (uj_qy.coordinate_len > kP256CoordBytes) {
59  LOG_ERROR(
60  "Coordinate value qy too large for P256 (have = %d bytes, max = %d "
61  "bytes)",
62  uj_qy.coordinate_len, kP256CoordBytes);
63  return false;
64  }
65  memset(pub_p256->x, 0, kP256CoordBytes);
66  memcpy(pub_p256->x, uj_qx.coordinate, uj_qx.coordinate_len);
67  memset(pub_p256->y, 0, kP256CoordBytes);
68  memcpy(pub_p256->y, uj_qy.coordinate, uj_qy.coordinate_len);
69  public_key->key_mode = kOtcryptoKeyModeEcdsaP256;
70  public_key->key_length = sizeof(p256_point_t);
71  public_key->key = (uint32_t *)pub_p256;
72  *digest_len = kP256ScalarWords;
73  if (uj_signature.r_len > kP256ScalarBytes) {
74  LOG_ERROR(
75  "Signature r value too large for P256 (have = %d bytes, max = %d "
76  "bytes)",
77  uj_signature.r_len, kP256ScalarBytes);
78  return false;
79  }
80  if (uj_signature.s_len > kP256ScalarBytes) {
81  LOG_ERROR(
82  "Signature s value too large for P256 (have = %d bytes, max = %d "
83  "bytes)",
84  uj_signature.s_len, kP256ScalarBytes);
85  return false;
86  }
87  memset(signature_p256->r, 0, kP256ScalarBytes);
88  memcpy(signature_p256->r, uj_signature.r, uj_signature.r_len);
89  memset(signature_p256->s, 0, kP256ScalarBytes);
90  memcpy(signature_p256->s, uj_signature.s, uj_signature.s_len);
91  signature_mut->len = kP256ScalarWords * 2;
92  signature_mut->data = (uint32_t *)signature_p256;
93 
94  return true;
95 }
96 
97 int set_nist_p384_params(cryptotest_ecdsa_coordinate_t uj_qx,
98  cryptotest_ecdsa_coordinate_t uj_qy,
99  cryptotest_ecdsa_signature_t uj_signature,
100  otcrypto_unblinded_key_t *public_key,
101  p384_ecdsa_signature_t *signature_p384,
102  p384_point_t *pub_p384,
103  otcrypto_word32_buf_t *signature_mut,
104  size_t *digest_len) {
105  if (uj_qx.coordinate_len > kP384CoordBytes) {
106  LOG_ERROR(
107  "Coordinate value qx too large for P384 (have = %d bytes, max = %d "
108  "bytes)",
109  uj_qx.coordinate_len, kP384CoordBytes);
110  return false;
111  }
112  if (uj_qy.coordinate_len > kP384CoordBytes) {
113  LOG_ERROR(
114  "Coordinate value qy too large for P384 (have = %d bytes, max = %d "
115  "bytes)",
116  uj_qy.coordinate_len, kP384CoordBytes);
117  return false;
118  }
119  memset(pub_p384->x, 0, kP384CoordBytes);
120  memcpy(pub_p384->x, uj_qx.coordinate, uj_qx.coordinate_len);
121  memset(pub_p384->y, 0, kP384CoordBytes);
122  memcpy(pub_p384->y, uj_qy.coordinate, uj_qy.coordinate_len);
123  public_key->key_mode = kOtcryptoKeyModeEcdsaP384;
124  public_key->key_length = sizeof(p384_point_t);
125  public_key->key = (uint32_t *)pub_p384;
126  *digest_len = kP384ScalarWords;
127  if (uj_signature.r_len > kP384ScalarBytes) {
128  LOG_ERROR(
129  "Signature r value too large for P384 (have = %d bytes, max = %d "
130  "bytes)",
131  uj_signature.r_len, kP384ScalarBytes);
132  return false;
133  }
134  if (uj_signature.s_len > kP384ScalarBytes) {
135  LOG_ERROR(
136  "Signature s value too large for P384 (have = %d bytes, max = %d "
137  "bytes)",
138  uj_signature.s_len, kP384ScalarBytes);
139  return false;
140  }
141  memset(signature_p384->r, 0, kP384ScalarBytes);
142  memcpy(signature_p384->r, uj_signature.r, uj_signature.r_len);
143  memset(signature_p384->s, 0, kP384ScalarBytes);
144  memcpy(signature_p384->s, uj_signature.s, uj_signature.s_len);
145  signature_mut->len = kP384ScalarWords * 2;
146  signature_mut->data = (uint32_t *)signature_p384;
147 
148  return true;
149 }
150 
151 status_t interpret_verification_result(ujson_t *uj,
152  hardened_bool_t *verification_result) {
153  cryptotest_ecdsa_verify_output_t uj_output;
154  switch (*verification_result) {
155  case kHardenedBoolFalse:
156  uj_output = kCryptotestEcdsaVerifyOutputFailure;
157  break;
158  case kHardenedBoolTrue:
159  uj_output = kCryptotestEcdsaVerifyOutputSuccess;
160  break;
161  default:
162  LOG_ERROR("Unexpected result value from otcrypto_ecdsa_verify: %d",
163  verification_result);
164  return INTERNAL();
165  }
166  RESP_OK(ujson_serialize_cryptotest_ecdsa_verify_output_t, uj, &uj_output);
167  return OK_STATUS(0);
168 }
169 
170 status_t interpret_verify_status(ujson_t *uj, otcrypto_status_t status,
171  hardened_bool_t *verification_result) {
172  cryptotest_ecdsa_verify_output_t uj_output;
173  switch (status.value) {
174  case kOtcryptoStatusValueOk:
175  return interpret_verification_result(uj, verification_result);
176  case kOtcryptoStatusValueBadArgs:
177  // Some ECDSA test vectors test invalid inputs. If cryptolib
178  // returns an invalid input code, we simply respond with
179  // "validation failed". Otherwise, we error out.
180  uj_output = kCryptotestEcdsaVerifyOutputFailure;
181  RESP_OK(ujson_serialize_cryptotest_ecdsa_verify_output_t, uj, &uj_output);
182  return OK_STATUS(0);
183  default:
184  LOG_ERROR(
185  "Unexpected status value returned from otcrypto_ecdsa_verify: "
186  "0x%x",
187  status.value);
188  return INTERNAL();
189  }
190 }
191 
192 status_t p256_sign(ujson_t *uj, cryptotest_ecdsa_private_key_t *uj_private_key,
193  otcrypto_hash_digest_t message_digest,
194  otcrypto_word32_buf_t signature_mut,
195  cryptotest_ecdsa_signature_t *uj_signature) {
196  p256_masked_scalar_t private_key_masked;
197  otcrypto_blinded_key_t private_key = {
198  .config = kP256PrivateKeyConfig,
199  .keyblob_length = sizeof(private_key_masked),
200  .keyblob = (uint32_t *)&private_key_masked,
201  };
202  memset(private_key_masked.share0, 0, kP256MaskedScalarShareBytes);
203  memcpy(private_key_masked.share0, uj_private_key->d0, kP256ScalarBytes);
204  memset(private_key_masked.share1, 0, kP256MaskedScalarShareBytes);
205  memcpy(private_key_masked.share1, uj_private_key->d1, kP256ScalarBytes);
206  private_key.checksum = integrity_blinded_checksum(&private_key);
207 
209  otcrypto_ecdsa_p256_sign(&private_key, message_digest, signature_mut);
210  if (status.value != kOtcryptoStatusValueOk) {
211  return INTERNAL(status.value);
212  }
213 
214  memset(uj_signature->r, 0, ECDSA_CMD_MAX_SIGNATURE_SCALAR_BYTES);
215  memset(uj_signature->s, 0, ECDSA_CMD_MAX_SIGNATURE_SCALAR_BYTES);
216  p256_ecdsa_signature_t *signature_p256 =
217  (p256_ecdsa_signature_t *)signature_mut.data;
218  memcpy(uj_signature->r, signature_p256->r, kP256ScalarBytes);
219  uj_signature->r_len = kP256ScalarBytes;
220  memcpy(uj_signature->s, signature_p256->s, kP256ScalarBytes);
221  uj_signature->s_len = kP256ScalarBytes;
222  RESP_OK(ujson_serialize_cryptotest_ecdsa_signature_t, uj, uj_signature);
223 
224  return OK_STATUS(0);
225 }
226 
227 status_t p384_sign(ujson_t *uj, cryptotest_ecdsa_private_key_t *uj_private_key,
228  otcrypto_hash_digest_t message_digest,
229  otcrypto_word32_buf_t signature_mut,
230  cryptotest_ecdsa_signature_t *uj_signature) {
231  p384_masked_scalar_t private_key_masked;
232  otcrypto_blinded_key_t private_key = {
233  .config = kP384PrivateKeyConfig,
234  .keyblob_length = sizeof(private_key_masked),
235  .keyblob = (uint32_t *)&private_key_masked,
236  };
237  memset(private_key_masked.share0, 0, kP384MaskedScalarShareBytes);
238  memcpy(private_key_masked.share0, uj_private_key->d0, kP384ScalarBytes);
239  memset(private_key_masked.share1, 0, kP384MaskedScalarShareBytes);
240  memcpy(private_key_masked.share1, uj_private_key->d1, kP384ScalarBytes);
241  private_key.checksum = integrity_blinded_checksum(&private_key);
242 
244  otcrypto_ecdsa_p384_sign(&private_key, message_digest, signature_mut);
245  if (status.value != kOtcryptoStatusValueOk) {
246  return INTERNAL(status.value);
247  }
248 
249  memset(uj_signature->r, 0, ECDSA_CMD_MAX_SIGNATURE_SCALAR_BYTES);
250  memset(uj_signature->s, 0, ECDSA_CMD_MAX_SIGNATURE_SCALAR_BYTES);
251  p384_ecdsa_signature_t *signature_p384 =
252  (p384_ecdsa_signature_t *)signature_mut.data;
253  memcpy(uj_signature->r, signature_p384->r, kP384ScalarBytes);
254  uj_signature->r_len = kP384ScalarBytes;
255  memcpy(uj_signature->s, signature_p384->s, kP384ScalarBytes);
256  uj_signature->s_len = kP384ScalarBytes;
257  RESP_OK(ujson_serialize_cryptotest_ecdsa_signature_t, uj, uj_signature);
258 
259  return OK_STATUS(0);
260 }
261 
262 status_t handle_ecdsa(ujson_t *uj) {
263  // Declare ECDSA parameter ujson deserializer types
264  cryptotest_ecdsa_operation_t uj_op;
265  cryptotest_ecdsa_hash_alg_t uj_hash_alg;
266  cryptotest_ecdsa_curve_t uj_curve;
267  cryptotest_ecdsa_message_t uj_message;
268  cryptotest_ecdsa_signature_t uj_signature;
269  cryptotest_ecdsa_coordinate_t uj_qx;
270  cryptotest_ecdsa_coordinate_t uj_qy;
271  cryptotest_ecdsa_private_key_t uj_private_key;
272 
273  // Deserialize ujson byte stream into ECDSA parameters
274  TRY(ujson_deserialize_cryptotest_ecdsa_operation_t(uj, &uj_op));
275  TRY(ujson_deserialize_cryptotest_ecdsa_hash_alg_t(uj, &uj_hash_alg));
276  TRY(ujson_deserialize_cryptotest_ecdsa_curve_t(uj, &uj_curve));
277  TRY(ujson_deserialize_cryptotest_ecdsa_message_t(uj, &uj_message));
278  TRY(ujson_deserialize_cryptotest_ecdsa_signature_t(uj, &uj_signature));
279  TRY(ujson_deserialize_cryptotest_ecdsa_coordinate_t(uj, &uj_qx));
280  TRY(ujson_deserialize_cryptotest_ecdsa_coordinate_t(uj, &uj_qy));
281  TRY(ujson_deserialize_cryptotest_ecdsa_private_key_t(uj, &uj_private_key));
282 
283  otcrypto_unblinded_key_t public_key;
284  size_t digest_len;
285 
286  otcrypto_word32_buf_t signature_mut;
287  int success;
288  p256_ecdsa_signature_t signature_p256;
289  p384_ecdsa_signature_t signature_p384;
290  p256_point_t pub_p256;
291  p384_point_t pub_p384;
292  switch (uj_curve) {
293  case kCryptotestEcdsaCurveP256:
294  success = set_nist_p256_params(uj_qx, uj_qy, uj_signature, &public_key,
295  &signature_p256, &pub_p256, &signature_mut,
296  &digest_len);
297  if (!success) {
298  return INVALID_ARGUMENT();
299  }
300  break;
301  case kCryptotestEcdsaCurveP384:
302  success = set_nist_p384_params(uj_qx, uj_qy, uj_signature, &public_key,
303  &signature_p384, &pub_p384, &signature_mut,
304  &digest_len);
305  if (!success) {
306  return INVALID_ARGUMENT();
307  }
308  break;
309  default:
310  LOG_ERROR("Unsupported ECC curve: %d", uj_curve);
311  return INVALID_ARGUMENT();
312  }
313  public_key.checksum = integrity_unblinded_checksum(&public_key);
314  otcrypto_const_word32_buf_t signature = {
315  .len = signature_mut.len,
316  .data = signature_mut.data,
317  };
318 
320  switch (uj_hash_alg) {
321  case kCryptotestEcdsaHashAlgSha256:
322  mode = kOtcryptoHashModeSha256;
323  break;
324  case kCryptotestEcdsaHashAlgSha384:
325  mode = kOtcryptoHashModeSha384;
326  break;
327  case kCryptotestEcdsaHashAlgSha512:
328  mode = kOtcryptoHashModeSha512;
329  break;
330  case kCryptotestEcdsaHashAlgSha3_256:
331  mode = kOtcryptoHashModeSha3_256;
332  break;
333  case kCryptotestEcdsaHashAlgSha3_384:
334  mode = kOtcryptoHashModeSha3_384;
335  break;
336  case kCryptotestEcdsaHashAlgSha3_512:
337  mode = kOtcryptoHashModeSha3_512;
338  break;
339  default:
340  LOG_ERROR("Unrecognized ECDSA hash mode: %d", uj_hash_alg);
341  return INVALID_ARGUMENT();
342  }
343  uint8_t message_buf[ECDSA_CMD_MAX_MESSAGE_BYTES];
344  memset(message_buf, 0, digest_len * sizeof(uint32_t));
345  memcpy(message_buf, uj_message.input, uj_message.input_len);
346  const otcrypto_hash_digest_t message_digest = {
347  .mode = mode,
348  .len = digest_len,
349  .data = (uint32_t *)message_buf,
350  };
351 
352  switch (uj_op) {
353  case kCryptotestEcdsaOperationSign: {
354  switch (uj_curve) {
355  case kCryptotestEcdsaCurveP256: {
356  return p256_sign(uj, &uj_private_key, message_digest, signature_mut,
357  &uj_signature);
358  }
359  case kCryptotestEcdsaCurveP384: {
360  return p384_sign(uj, &uj_private_key, message_digest, signature_mut,
361  &uj_signature);
362  }
363  default:
364  LOG_ERROR("Unsupported ECC curve: %d", uj_curve);
365  return INVALID_ARGUMENT();
366  }
367  break;
368  }
369  case kCryptotestEcdsaOperationVerify: {
370  hardened_bool_t verification_result = kHardenedBoolFalse;
372  switch (uj_curve) {
373  case kCryptotestEcdsaCurveP256: {
374  status = otcrypto_ecdsa_p256_verify(&public_key, message_digest,
375  signature, &verification_result);
376  break;
377  }
378  case kCryptotestEcdsaCurveP384: {
379  status = otcrypto_ecdsa_p384_verify(&public_key, message_digest,
380  signature, &verification_result);
381  break;
382  }
383  default:
384  LOG_ERROR("Unsupported ECC curve: %d", uj_curve);
385  return INVALID_ARGUMENT();
386  }
387  return interpret_verify_status(uj, status, &verification_result);
388  }
389  default:
390  LOG_ERROR("Unrecognized ECDSA operation: %d", uj_op);
391  return INVALID_ARGUMENT();
392  }
393  return OK_STATUS(0);
394 }