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