1 /*
2 * Copyright (c) 2021 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <openthread/platform/crypto.h>
8
9 #include <psa/crypto.h>
10
11 #if defined(CONFIG_OPENTHREAD_ECDSA)
12 #include <string.h>
13 #include <zephyr/sys/__assert.h>
14 #endif
15
psaToOtError(psa_status_t aStatus)16 static otError psaToOtError(psa_status_t aStatus)
17 {
18 switch (aStatus) {
19 case PSA_SUCCESS:
20 return OT_ERROR_NONE;
21 case PSA_ERROR_INVALID_ARGUMENT:
22 return OT_ERROR_INVALID_ARGS;
23 case PSA_ERROR_BUFFER_TOO_SMALL:
24 return OT_ERROR_NO_BUFS;
25 default:
26 return OT_ERROR_FAILED;
27 }
28 }
29
toPsaKeyType(otCryptoKeyType aType)30 static psa_key_type_t toPsaKeyType(otCryptoKeyType aType)
31 {
32 switch (aType) {
33 case OT_CRYPTO_KEY_TYPE_RAW:
34 return PSA_KEY_TYPE_RAW_DATA;
35 case OT_CRYPTO_KEY_TYPE_AES:
36 return PSA_KEY_TYPE_AES;
37 case OT_CRYPTO_KEY_TYPE_HMAC:
38 return PSA_KEY_TYPE_HMAC;
39 default:
40 return PSA_KEY_TYPE_NONE;
41 }
42 }
43
toPsaAlgorithm(otCryptoKeyAlgorithm aAlgorithm)44 static psa_algorithm_t toPsaAlgorithm(otCryptoKeyAlgorithm aAlgorithm)
45 {
46 switch (aAlgorithm) {
47 case OT_CRYPTO_KEY_ALG_AES_ECB:
48 return PSA_ALG_ECB_NO_PADDING;
49 case OT_CRYPTO_KEY_ALG_HMAC_SHA_256:
50 return PSA_ALG_HMAC(PSA_ALG_SHA_256);
51 default:
52 /*
53 * There is currently no constant like PSA_ALG_NONE, but 0 is used
54 * to indicate an unknown algorithm.
55 */
56 return (psa_algorithm_t) 0;
57 }
58 }
59
toPsaKeyUsage(int aUsage)60 static psa_key_usage_t toPsaKeyUsage(int aUsage)
61 {
62 psa_key_usage_t usage = 0;
63
64 if (aUsage & OT_CRYPTO_KEY_USAGE_EXPORT) {
65 usage |= PSA_KEY_USAGE_EXPORT;
66 }
67
68 if (aUsage & OT_CRYPTO_KEY_USAGE_ENCRYPT) {
69 usage |= PSA_KEY_USAGE_ENCRYPT;
70 }
71
72 if (aUsage & OT_CRYPTO_KEY_USAGE_DECRYPT) {
73 usage |= PSA_KEY_USAGE_DECRYPT;
74 }
75
76 if (aUsage & OT_CRYPTO_KEY_USAGE_SIGN_HASH) {
77 usage |= PSA_KEY_USAGE_SIGN_HASH;
78 }
79
80 return usage;
81 }
82
checkKeyUsage(int aUsage)83 static bool checkKeyUsage(int aUsage)
84 {
85 /* Check if only supported flags have been passed */
86 int supported_flags = OT_CRYPTO_KEY_USAGE_EXPORT |
87 OT_CRYPTO_KEY_USAGE_ENCRYPT |
88 OT_CRYPTO_KEY_USAGE_DECRYPT |
89 OT_CRYPTO_KEY_USAGE_SIGN_HASH;
90
91 return (aUsage & ~supported_flags) == 0;
92 }
93
checkContext(otCryptoContext * aContext,size_t aMinSize)94 static bool checkContext(otCryptoContext *aContext, size_t aMinSize)
95 {
96 /* Verify that the passed context is initialized and points to a big enough buffer */
97 return aContext != NULL && aContext->mContext != NULL && aContext->mContextSize >= aMinSize;
98 }
99
ensureKeyIsLoaded(otCryptoKeyRef aKeyRef)100 static void ensureKeyIsLoaded(otCryptoKeyRef aKeyRef)
101 {
102 /*
103 * The workaround below will no longer be need after updating TF-M version used in Zephyr
104 * to 1.5.0 (see upstream commit 42e77b561fcfe19819ff1e63cb7c0b672ee8ba41).
105 * In the recent versions of TF-M the concept of key handles and psa_open_key()/
106 * psa_close_key() APIs have been being deprecated, but the version currently used in Zephyr
107 * is in the middle of that transition. Consequently, psa_destroy_key() and lots of other
108 * functions will fail when a key ID that they take as a parameter is not loaded from the
109 * persistent storage. That may occur when a given persistent key is created via
110 * psa_generate_key() or psa_import_key(), and then the device reboots.
111 *
112 * Use psa_open_key() when the key has not been loaded yet to work around the issue.
113 */
114 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
115 psa_status_t status = psa_get_key_attributes(aKeyRef, &attributes);
116 psa_key_id_t key_handle;
117
118 if (status == PSA_ERROR_INVALID_HANDLE) {
119 psa_open_key(aKeyRef, &key_handle);
120 }
121
122 psa_reset_key_attributes(&attributes);
123 }
124
otPlatCryptoInit(void)125 void otPlatCryptoInit(void)
126 {
127 psa_crypto_init();
128 }
129
otPlatCryptoImportKey(otCryptoKeyRef * aKeyRef,otCryptoKeyType aKeyType,otCryptoKeyAlgorithm aKeyAlgorithm,int aKeyUsage,otCryptoKeyStorage aKeyPersistence,const uint8_t * aKey,size_t aKeyLen)130 otError otPlatCryptoImportKey(otCryptoKeyRef *aKeyRef,
131 otCryptoKeyType aKeyType,
132 otCryptoKeyAlgorithm aKeyAlgorithm,
133 int aKeyUsage,
134 otCryptoKeyStorage aKeyPersistence,
135 const uint8_t *aKey,
136 size_t aKeyLen)
137 {
138 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
139 psa_status_t status;
140
141 if (aKeyRef == NULL || aKey == NULL || !checkKeyUsage(aKeyUsage)) {
142 return OT_ERROR_INVALID_ARGS;
143 }
144
145 psa_set_key_type(&attributes, toPsaKeyType(aKeyType));
146 psa_set_key_algorithm(&attributes, toPsaAlgorithm(aKeyAlgorithm));
147 psa_set_key_usage_flags(&attributes, toPsaKeyUsage(aKeyUsage));
148
149 switch (aKeyPersistence) {
150 case OT_CRYPTO_KEY_STORAGE_PERSISTENT:
151 psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_PERSISTENT);
152 psa_set_key_id(&attributes, *aKeyRef);
153 break;
154 case OT_CRYPTO_KEY_STORAGE_VOLATILE:
155 psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_VOLATILE);
156 break;
157 }
158
159 status = psa_import_key(&attributes, aKey, aKeyLen, aKeyRef);
160 psa_reset_key_attributes(&attributes);
161
162 return psaToOtError(status);
163 }
164
otPlatCryptoExportKey(otCryptoKeyRef aKeyRef,uint8_t * aBuffer,size_t aBufferLen,size_t * aKeyLen)165 otError otPlatCryptoExportKey(otCryptoKeyRef aKeyRef,
166 uint8_t *aBuffer,
167 size_t aBufferLen,
168 size_t *aKeyLen)
169 {
170 if (aBuffer == NULL) {
171 return OT_ERROR_INVALID_ARGS;
172 }
173
174 ensureKeyIsLoaded(aKeyRef);
175
176 return psaToOtError(psa_export_key(aKeyRef, aBuffer, aBufferLen, aKeyLen));
177 }
178
otPlatCryptoDestroyKey(otCryptoKeyRef aKeyRef)179 otError otPlatCryptoDestroyKey(otCryptoKeyRef aKeyRef)
180 {
181 ensureKeyIsLoaded(aKeyRef);
182
183 return psaToOtError(psa_destroy_key(aKeyRef));
184 }
185
otPlatCryptoHasKey(otCryptoKeyRef aKeyRef)186 bool otPlatCryptoHasKey(otCryptoKeyRef aKeyRef)
187 {
188 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
189 psa_status_t status;
190
191 ensureKeyIsLoaded(aKeyRef);
192 status = psa_get_key_attributes(aKeyRef, &attributes);
193 psa_reset_key_attributes(&attributes);
194
195 return status == PSA_SUCCESS;
196 }
197
otPlatCryptoHmacSha256Init(otCryptoContext * aContext)198 otError otPlatCryptoHmacSha256Init(otCryptoContext *aContext)
199 {
200 psa_mac_operation_t *operation;
201
202 if (!checkContext(aContext, sizeof(psa_mac_operation_t))) {
203 return OT_ERROR_INVALID_ARGS;
204 }
205
206 operation = aContext->mContext;
207 *operation = psa_mac_operation_init();
208
209 return OT_ERROR_NONE;
210 }
211
otPlatCryptoHmacSha256Deinit(otCryptoContext * aContext)212 otError otPlatCryptoHmacSha256Deinit(otCryptoContext *aContext)
213 {
214 psa_mac_operation_t *operation;
215
216 if (!checkContext(aContext, sizeof(psa_mac_operation_t))) {
217 return OT_ERROR_INVALID_ARGS;
218 }
219
220 operation = aContext->mContext;
221
222 return psaToOtError(psa_mac_abort(operation));
223 }
224
otPlatCryptoHmacSha256Start(otCryptoContext * aContext,const otCryptoKey * aKey)225 otError otPlatCryptoHmacSha256Start(otCryptoContext *aContext, const otCryptoKey *aKey)
226 {
227 psa_mac_operation_t *operation;
228 psa_status_t status;
229
230 if (aKey == NULL || !checkContext(aContext, sizeof(psa_mac_operation_t))) {
231 return OT_ERROR_INVALID_ARGS;
232 }
233
234 ensureKeyIsLoaded(aKey->mKeyRef);
235 operation = aContext->mContext;
236 status = psa_mac_sign_setup(operation, aKey->mKeyRef, PSA_ALG_HMAC(PSA_ALG_SHA_256));
237
238 return psaToOtError(status);
239 }
240
otPlatCryptoHmacSha256Update(otCryptoContext * aContext,const void * aBuf,uint16_t aBufLength)241 otError otPlatCryptoHmacSha256Update(otCryptoContext *aContext,
242 const void *aBuf,
243 uint16_t aBufLength)
244 {
245 psa_mac_operation_t *operation;
246
247 if (aBuf == NULL || !checkContext(aContext, sizeof(psa_mac_operation_t))) {
248 return OT_ERROR_INVALID_ARGS;
249 }
250
251 operation = aContext->mContext;
252
253 return psaToOtError(psa_mac_update(operation, (const uint8_t *) aBuf, aBufLength));
254 }
255
otPlatCryptoHmacSha256Finish(otCryptoContext * aContext,uint8_t * aBuf,size_t aBufLength)256 otError otPlatCryptoHmacSha256Finish(otCryptoContext *aContext, uint8_t *aBuf, size_t aBufLength)
257 {
258 psa_mac_operation_t *operation;
259 size_t mac_length;
260
261 if (aBuf == NULL || !checkContext(aContext, sizeof(psa_mac_operation_t))) {
262 return OT_ERROR_INVALID_ARGS;
263 }
264
265 operation = aContext->mContext;
266
267 return psaToOtError(psa_mac_sign_finish(operation, aBuf, aBufLength, &mac_length));
268 }
269
otPlatCryptoAesInit(otCryptoContext * aContext)270 otError otPlatCryptoAesInit(otCryptoContext *aContext)
271 {
272 psa_key_id_t *key_ref;
273
274 if (!checkContext(aContext, sizeof(psa_key_id_t))) {
275 return OT_ERROR_INVALID_ARGS;
276 }
277
278 key_ref = aContext->mContext;
279 *key_ref = (psa_key_id_t) 0; /* In TF-M 1.5.0 this can be replaced with PSA_KEY_ID_NULL */
280
281 return OT_ERROR_NONE;
282 }
283
otPlatCryptoAesSetKey(otCryptoContext * aContext,const otCryptoKey * aKey)284 otError otPlatCryptoAesSetKey(otCryptoContext *aContext, const otCryptoKey *aKey)
285 {
286 psa_key_id_t *key_ref;
287
288 if (aKey == NULL || !checkContext(aContext, sizeof(psa_key_id_t))) {
289 return OT_ERROR_INVALID_ARGS;
290 }
291
292 key_ref = aContext->mContext;
293 *key_ref = aKey->mKeyRef;
294
295 return OT_ERROR_NONE;
296 }
297
otPlatCryptoAesEncrypt(otCryptoContext * aContext,const uint8_t * aInput,uint8_t * aOutput)298 otError otPlatCryptoAesEncrypt(otCryptoContext *aContext, const uint8_t *aInput, uint8_t *aOutput)
299 {
300 const size_t block_size = PSA_BLOCK_CIPHER_BLOCK_LENGTH(PSA_KEY_TYPE_AES);
301 psa_status_t status = PSA_SUCCESS;
302 psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
303 psa_key_id_t *key_ref;
304 size_t cipher_length;
305
306 if (aInput == NULL || aOutput == NULL || !checkContext(aContext, sizeof(psa_key_id_t))) {
307 return OT_ERROR_INVALID_ARGS;
308 }
309
310 /*
311 * The code below can be simplified after updating TF-M version used in Zephyr to 1.5.0
312 * (see upstream commit: 045ec4abfc73152a0116684ba9127d0a97cc8d34), using
313 * psa_cipher_encrypt() function which will replace the setup-update-finish sequence below.
314 */
315 key_ref = aContext->mContext;
316 ensureKeyIsLoaded(*key_ref);
317 status = psa_cipher_encrypt_setup(&operation, *key_ref, PSA_ALG_ECB_NO_PADDING);
318
319 if (status != PSA_SUCCESS) {
320 goto out;
321 }
322
323 status = psa_cipher_update(&operation,
324 aInput,
325 block_size,
326 aOutput,
327 block_size,
328 &cipher_length);
329
330 if (status != PSA_SUCCESS) {
331 goto out;
332 }
333
334 status = psa_cipher_finish(&operation,
335 aOutput + cipher_length,
336 block_size - cipher_length,
337 &cipher_length);
338
339 out:
340 psa_cipher_abort(&operation);
341 return psaToOtError(status);
342 }
343
otPlatCryptoAesFree(otCryptoContext * aContext)344 otError otPlatCryptoAesFree(otCryptoContext *aContext)
345 {
346 return OT_ERROR_NONE;
347 }
348
otPlatCryptoSha256Init(otCryptoContext * aContext)349 otError otPlatCryptoSha256Init(otCryptoContext *aContext)
350 {
351 psa_hash_operation_t *operation;
352
353 if (!checkContext(aContext, sizeof(psa_hash_operation_t))) {
354 return OT_ERROR_INVALID_ARGS;
355 }
356
357 operation = aContext->mContext;
358 *operation = psa_hash_operation_init();
359
360 return OT_ERROR_NONE;
361 }
362
otPlatCryptoSha256Deinit(otCryptoContext * aContext)363 otError otPlatCryptoSha256Deinit(otCryptoContext *aContext)
364 {
365 psa_hash_operation_t *operation;
366
367 if (!checkContext(aContext, sizeof(psa_hash_operation_t))) {
368 return OT_ERROR_INVALID_ARGS;
369 }
370
371 operation = aContext->mContext;
372
373 return psaToOtError(psa_hash_abort(operation));
374 }
375
otPlatCryptoSha256Start(otCryptoContext * aContext)376 otError otPlatCryptoSha256Start(otCryptoContext *aContext)
377 {
378 psa_hash_operation_t *operation;
379
380 if (!checkContext(aContext, sizeof(psa_hash_operation_t))) {
381 return OT_ERROR_INVALID_ARGS;
382 }
383
384 operation = aContext->mContext;
385
386 return psaToOtError(psa_hash_setup(operation, PSA_ALG_SHA_256));
387 }
388
otPlatCryptoSha256Update(otCryptoContext * aContext,const void * aBuf,uint16_t aBufLength)389 otError otPlatCryptoSha256Update(otCryptoContext *aContext, const void *aBuf, uint16_t aBufLength)
390 {
391 psa_hash_operation_t *operation;
392
393 if (aBuf == NULL || !checkContext(aContext, sizeof(psa_hash_operation_t))) {
394 return OT_ERROR_INVALID_ARGS;
395 }
396
397 operation = aContext->mContext;
398
399 return psaToOtError(psa_hash_update(operation, (const uint8_t *) aBuf, aBufLength));
400 }
401
otPlatCryptoSha256Finish(otCryptoContext * aContext,uint8_t * aHash,uint16_t aHashSize)402 otError otPlatCryptoSha256Finish(otCryptoContext *aContext, uint8_t *aHash, uint16_t aHashSize)
403 {
404 psa_hash_operation_t *operation;
405 size_t hash_size;
406
407 if (aHash == NULL || !checkContext(aContext, sizeof(psa_hash_operation_t))) {
408 return OT_ERROR_INVALID_ARGS;
409 }
410
411 operation = aContext->mContext;
412
413 return psaToOtError(psa_hash_finish(operation, aHash, aHashSize, &hash_size));
414 }
415
otPlatCryptoRandomInit(void)416 void otPlatCryptoRandomInit(void)
417 {
418 }
419
otPlatCryptoRandomDeinit(void)420 void otPlatCryptoRandomDeinit(void)
421 {
422 }
423
otPlatCryptoRandomGet(uint8_t * aBuffer,uint16_t aSize)424 otError otPlatCryptoRandomGet(uint8_t *aBuffer, uint16_t aSize)
425 {
426 return psaToOtError(psa_generate_random(aBuffer, aSize));
427 }
428
429 #if defined(CONFIG_OPENTHREAD_ECDSA)
430
otPlatCryptoEcdsaGenerateKey(otPlatCryptoEcdsaKeyPair * aKeyPair)431 otError otPlatCryptoEcdsaGenerateKey(otPlatCryptoEcdsaKeyPair *aKeyPair)
432 {
433 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
434 psa_key_id_t key_id = 0;
435 psa_status_t status;
436 size_t exported_length;
437
438 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_EXPORT);
439 psa_set_key_algorithm(&attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256));
440 psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
441 psa_set_key_bits(&attributes, 256);
442
443 status = psa_generate_key(&attributes, &key_id);
444 if (status != PSA_SUCCESS) {
445 goto out;
446 }
447
448 status = psa_export_key(key_id, aKeyPair->mDerBytes, OT_CRYPTO_ECDSA_MAX_DER_SIZE,
449 &exported_length);
450 if (status != PSA_SUCCESS) {
451 goto out;
452 }
453 aKeyPair->mDerLength = exported_length;
454
455 out:
456 psa_reset_key_attributes(&attributes);
457 psa_destroy_key(key_id);
458
459 return psaToOtError(status);
460 }
461
otPlatCryptoEcdsaGetPublicKey(const otPlatCryptoEcdsaKeyPair * aKeyPair,otPlatCryptoEcdsaPublicKey * aPublicKey)462 otError otPlatCryptoEcdsaGetPublicKey(const otPlatCryptoEcdsaKeyPair *aKeyPair,
463 otPlatCryptoEcdsaPublicKey *aPublicKey)
464 {
465 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
466 psa_key_id_t key_id = 0;
467 psa_status_t status;
468 size_t exported_length;
469 uint8_t buffer[1 + OT_CRYPTO_ECDSA_PUBLIC_KEY_SIZE];
470
471 psa_set_key_algorithm(&attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256));
472 psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
473 psa_set_key_bits(&attributes, 256);
474
475 status = psa_import_key(&attributes, aKeyPair->mDerBytes, aKeyPair->mDerLength, &key_id);
476 if (status != PSA_SUCCESS) {
477 goto out;
478 }
479
480 status = psa_export_public_key(key_id, buffer, sizeof(buffer), &exported_length);
481 if (status != PSA_SUCCESS) {
482 goto out;
483 }
484 __ASSERT_NO_MSG(exported_length == sizeof(buffer));
485 memcpy(aPublicKey->m8, buffer + 1, OT_CRYPTO_ECDSA_PUBLIC_KEY_SIZE);
486
487 out:
488 psa_reset_key_attributes(&attributes);
489 psa_destroy_key(key_id);
490
491 return psaToOtError(status);
492 }
493
otPlatCryptoEcdsaSign(const otPlatCryptoEcdsaKeyPair * aKeyPair,const otPlatCryptoSha256Hash * aHash,otPlatCryptoEcdsaSignature * aSignature)494 otError otPlatCryptoEcdsaSign(const otPlatCryptoEcdsaKeyPair *aKeyPair,
495 const otPlatCryptoSha256Hash *aHash,
496 otPlatCryptoEcdsaSignature *aSignature)
497 {
498 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
499 psa_key_id_t key_id;
500 psa_status_t status;
501 size_t signature_length;
502
503 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH);
504 psa_set_key_algorithm(&attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256));
505 psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
506 psa_set_key_bits(&attributes, 256);
507
508 status = psa_import_key(&attributes, aKeyPair->mDerBytes, aKeyPair->mDerLength, &key_id);
509 if (status != PSA_SUCCESS) {
510 goto out;
511 }
512
513 status = psa_sign_hash(key_id, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256), aHash->m8,
514 OT_CRYPTO_SHA256_HASH_SIZE, aSignature->m8,
515 OT_CRYPTO_ECDSA_SIGNATURE_SIZE, &signature_length);
516 if (status != PSA_SUCCESS) {
517 goto out;
518 }
519
520 out:
521 psa_reset_key_attributes(&attributes);
522 psa_destroy_key(key_id);
523
524 return psaToOtError(status);
525 }
526
otPlatCryptoEcdsaVerify(const otPlatCryptoEcdsaPublicKey * aPublicKey,const otPlatCryptoSha256Hash * aHash,const otPlatCryptoEcdsaSignature * aSignature)527 otError otPlatCryptoEcdsaVerify(const otPlatCryptoEcdsaPublicKey *aPublicKey,
528 const otPlatCryptoSha256Hash *aHash,
529 const otPlatCryptoEcdsaSignature *aSignature)
530 {
531 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
532 psa_key_id_t key_id;
533 psa_status_t status;
534 uint8_t buffer[1 + OT_CRYPTO_ECDSA_PUBLIC_KEY_SIZE];
535
536 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH);
537 psa_set_key_algorithm(&attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256));
538 psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1));
539 psa_set_key_bits(&attributes, 256);
540
541 /*
542 * `psa_import_key` expects a key format as specified by SEC1 §2.3.3 for the
543 * uncompressed representation of the ECPoint.
544 */
545 buffer[0] = 0x04;
546 memcpy(buffer + 1, aPublicKey->m8, OT_CRYPTO_ECDSA_PUBLIC_KEY_SIZE);
547 status = psa_import_key(&attributes, buffer, sizeof(buffer), &key_id);
548 if (status != PSA_SUCCESS) {
549 goto out;
550 }
551
552 status = psa_verify_hash(key_id, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256), aHash->m8,
553 OT_CRYPTO_SHA256_HASH_SIZE, aSignature->m8,
554 OT_CRYPTO_ECDSA_SIGNATURE_SIZE);
555 if (status != PSA_SUCCESS) {
556 goto out;
557 }
558
559 out:
560 psa_reset_key_attributes(&attributes);
561 psa_destroy_key(key_id);
562
563 return psaToOtError(status);
564 }
565
otPlatCryptoEcdsaSignUsingKeyRef(otCryptoKeyRef aKeyRef,const otPlatCryptoSha256Hash * aHash,otPlatCryptoEcdsaSignature * aSignature)566 otError otPlatCryptoEcdsaSignUsingKeyRef(otCryptoKeyRef aKeyRef,
567 const otPlatCryptoSha256Hash *aHash,
568 otPlatCryptoEcdsaSignature *aSignature)
569 {
570 psa_status_t status;
571 size_t signature_length;
572
573 status = psa_sign_hash(aKeyRef, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256), aHash->m8,
574 OT_CRYPTO_SHA256_HASH_SIZE, aSignature->m8,
575 OT_CRYPTO_ECDSA_SIGNATURE_SIZE, &signature_length);
576 if (status != PSA_SUCCESS) {
577 goto out;
578 }
579
580 __ASSERT_NO_MSG(signature_length == OT_CRYPTO_ECDSA_SIGNATURE_SIZE);
581 out:
582 return psaToOtError(status);
583 }
584
otPlatCryptoEcdsaVerifyUsingKeyRef(otCryptoKeyRef aKeyRef,const otPlatCryptoSha256Hash * aHash,const otPlatCryptoEcdsaSignature * aSignature)585 otError otPlatCryptoEcdsaVerifyUsingKeyRef(otCryptoKeyRef aKeyRef,
586 const otPlatCryptoSha256Hash *aHash,
587 const otPlatCryptoEcdsaSignature *aSignature)
588 {
589 psa_status_t status;
590
591 status = psa_verify_hash(aKeyRef, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256), aHash->m8,
592 OT_CRYPTO_SHA256_HASH_SIZE, aSignature->m8,
593 OT_CRYPTO_ECDSA_SIGNATURE_SIZE);
594 if (status != PSA_SUCCESS) {
595 goto out;
596 }
597
598 out:
599 return psaToOtError(status);
600 }
601
otPlatCryptoEcdsaExportPublicKey(otCryptoKeyRef aKeyRef,otPlatCryptoEcdsaPublicKey * aPublicKey)602 otError otPlatCryptoEcdsaExportPublicKey(otCryptoKeyRef aKeyRef,
603 otPlatCryptoEcdsaPublicKey *aPublicKey)
604 {
605 psa_status_t status;
606 size_t exported_length;
607 uint8_t buffer[1 + OT_CRYPTO_ECDSA_PUBLIC_KEY_SIZE];
608
609 status = psa_export_public_key(aKeyRef, buffer, sizeof(buffer), &exported_length);
610 if (status != PSA_SUCCESS) {
611 goto out;
612 }
613
614 __ASSERT_NO_MSG(exported_length == sizeof(buffer));
615 memcpy(aPublicKey->m8, buffer + 1, OT_CRYPTO_ECDSA_PUBLIC_KEY_SIZE);
616
617 out:
618 return psaToOtError(status);
619 }
620
otPlatCryptoEcdsaGenerateAndImportKey(otCryptoKeyRef aKeyRef)621 otError otPlatCryptoEcdsaGenerateAndImportKey(otCryptoKeyRef aKeyRef)
622 {
623 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
624 psa_status_t status;
625 psa_key_id_t key_id = (psa_key_id_t)aKeyRef;
626
627 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_HASH);
628 psa_set_key_algorithm(&attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256));
629 psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
630 psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_PERSISTENT);
631 psa_set_key_id(&attributes, key_id);
632 psa_set_key_bits(&attributes, 256);
633
634 status = psa_generate_key(&attributes, &key_id);
635 if (status != PSA_SUCCESS) {
636 goto out;
637 }
638
639 out:
640 psa_reset_key_attributes(&attributes);
641
642 return psaToOtError(status);
643 }
644
645 #endif /* #if CONFIG_OPENTHREAD_ECDSA */
646