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 &sect;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