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