@@ -44,6 +44,8 @@ static psa_key_type_t toPsaKeyType(otCryptoKeyType aType)
4444 return PSA_KEY_TYPE_HMAC ;
4545 case OT_CRYPTO_KEY_TYPE_ECDSA :
4646 return PSA_KEY_TYPE_ECC_KEY_PAIR (PSA_ECC_FAMILY_SECP_R1 );
47+ case OT_CRYPTO_KEY_TYPE_DERIVE :
48+ return PSA_KEY_TYPE_DERIVE ;
4749 default :
4850 return PSA_KEY_TYPE_NONE ;
4951 }
@@ -58,6 +60,8 @@ static psa_algorithm_t toPsaAlgorithm(otCryptoKeyAlgorithm aAlgorithm)
5860 return PSA_ALG_HMAC (PSA_ALG_SHA_256 );
5961 case OT_CRYPTO_KEY_ALG_ECDSA :
6062 return PSA_ALG_DETERMINISTIC_ECDSA (PSA_ALG_SHA_256 );
63+ case OT_CRYPTO_KEY_ALG_HKDF_SHA256 :
64+ return PSA_ALG_HKDF (PSA_ALG_SHA_256 );
6165 default :
6266 /*
6367 * There is currently no constant like PSA_ALG_NONE, but 0 is used
@@ -91,6 +95,10 @@ static psa_key_usage_t toPsaKeyUsage(int aUsage)
9195 usage |= PSA_KEY_USAGE_VERIFY_HASH ;
9296 }
9397
98+ if (aUsage & OT_CRYPTO_KEY_USAGE_DERIVE ) {
99+ usage |= PSA_KEY_USAGE_DERIVE ;
100+ }
101+
94102 return usage ;
95103}
96104
@@ -287,6 +295,143 @@ otError otPlatCryptoHmacSha256Finish(otCryptoContext *aContext, uint8_t *aBuf, s
287295 return psaToOtError (psa_mac_sign_finish (operation , aBuf , aBufLength , & mac_length ));
288296}
289297
298+
299+ otError otPlatCryptoHkdfInit (otCryptoContext * aContext )
300+ {
301+ psa_key_derivation_operation_t * operation ;
302+
303+ if (!checkContext (aContext , sizeof (psa_key_derivation_operation_t ))) {
304+ return OT_ERROR_INVALID_ARGS ;
305+ }
306+
307+ operation = aContext -> mContext ;
308+
309+ memset (operation , 0 , sizeof (psa_key_derivation_operation_t ));
310+
311+ return psaToOtError (psa_key_derivation_setup (operation , PSA_ALG_HKDF (PSA_ALG_SHA_256 )));
312+ }
313+
314+ otError otPlatCryptoHkdfExtract (otCryptoContext * aContext ,
315+ const uint8_t * aSalt ,
316+ uint16_t aSaltLength ,
317+ const otCryptoKey * aInputKey )
318+ {
319+ otError error = OT_ERROR_NONE ;
320+ psa_status_t status = PSA_SUCCESS ;
321+ psa_key_derivation_operation_t * operation = NULL ;
322+ otCryptoKeyRef key_ref = PSA_KEY_ID_NULL ;
323+ psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT ;
324+ psa_algorithm_t key_alg = PSA_ALG_NONE ;
325+ size_t key_length = 0 ;
326+ const size_t key_buffer_size = 16 ;
327+ uint8_t key_buffer [key_buffer_size ];
328+
329+ if (!checkContext (aContext , sizeof (psa_key_derivation_operation_t )) ||
330+ (aInputKey == NULL ) || (aSalt == NULL ) || (aSaltLength == 0 )) {
331+ return OT_ERROR_INVALID_ARGS ;
332+ }
333+
334+ operation = aContext -> mContext ;
335+
336+ status = psa_key_derivation_input_bytes (operation , PSA_KEY_DERIVATION_INPUT_SALT , aSalt ,
337+ aSaltLength );
338+ if (status != PSA_SUCCESS ) {
339+ error = psaToOtError (status );
340+ goto exit ;
341+ }
342+
343+ status = psa_get_key_attributes (aInputKey -> mKeyRef , & attributes );
344+ if (status != PSA_SUCCESS ) {
345+ error = psaToOtError (status );
346+ goto exit ;
347+ }
348+
349+ key_alg = psa_get_key_algorithm (& attributes );
350+
351+ /* The PSA API enforces a policy that restricts each key to a single algorithm.
352+ * If the key is already HKDF-SHA256, we can use it directly.
353+ * Otherwise, export and re-import it as a volatile HKDF key.
354+ */
355+ if (key_alg != toPsaAlgorithm (OT_CRYPTO_KEY_ALG_HKDF_SHA256 )) {
356+ error = otPlatCryptoExportKey (aInputKey -> mKeyRef , key_buffer , sizeof (key_buffer ),
357+ & key_length );
358+ if (error != OT_ERROR_NONE ) {
359+ goto exit ;
360+ }
361+ error = otPlatCryptoImportKey (& key_ref , OT_CRYPTO_KEY_TYPE_DERIVE ,
362+ OT_CRYPTO_KEY_ALG_HKDF_SHA256 ,
363+ OT_CRYPTO_KEY_USAGE_DERIVE ,
364+ OT_CRYPTO_KEY_STORAGE_VOLATILE ,
365+ key_buffer , key_length );
366+ if (error != OT_ERROR_NONE ) {
367+ goto exit ;
368+ }
369+
370+ status = psa_key_derivation_input_key (operation , PSA_KEY_DERIVATION_INPUT_SECRET ,
371+ key_ref );
372+ if (status != PSA_SUCCESS ) {
373+ error = psaToOtError (status );
374+ goto exit ;
375+ }
376+ } else {
377+ status = psa_key_derivation_input_key (operation , PSA_KEY_DERIVATION_INPUT_SECRET ,
378+ aInputKey -> mKeyRef );
379+ if (status != PSA_SUCCESS ) {
380+ error = psaToOtError (status );
381+ goto exit ;
382+ }
383+ }
384+
385+ exit :
386+ psa_reset_key_attributes (& attributes );
387+ otPlatCryptoDestroyKey (key_ref );
388+
389+ return error ;
390+ }
391+
392+ otError otPlatCryptoHkdfExpand (otCryptoContext * aContext ,
393+ const uint8_t * aInfo ,
394+ uint16_t aInfoLength ,
395+ uint8_t * aOutputKey ,
396+ uint16_t aOutputKeyLength )
397+ {
398+ psa_status_t status = PSA_SUCCESS ;
399+ psa_key_derivation_operation_t * operation ;
400+
401+ if (!checkContext (aContext , sizeof (psa_key_derivation_operation_t )) ||
402+ (aOutputKey == NULL ) || (aOutputKeyLength == 0 )) {
403+ return OT_ERROR_INVALID_ARGS ;
404+ }
405+
406+ operation = aContext -> mContext ;
407+
408+ status = psa_key_derivation_input_bytes (operation , PSA_KEY_DERIVATION_INPUT_INFO ,
409+ aInfo , aInfoLength );
410+ if (status != PSA_SUCCESS ) {
411+ return psaToOtError (status );
412+ }
413+
414+ status = psa_key_derivation_output_bytes (operation , aOutputKey , aOutputKeyLength );
415+ if (status != PSA_SUCCESS ) {
416+ return psaToOtError (status );
417+ }
418+
419+ return OT_ERROR_NONE ;
420+ }
421+
422+ otError otPlatCryptoHkdfDeinit (otCryptoContext * aContext )
423+ {
424+ psa_key_derivation_operation_t * operation ;
425+
426+ if (!checkContext (aContext , sizeof (psa_key_derivation_operation_t ))) {
427+ return OT_ERROR_INVALID_ARGS ;
428+ }
429+
430+ operation = aContext -> mContext ;
431+
432+ return psaToOtError (psa_key_derivation_abort (operation ));
433+ }
434+
290435otError otPlatCryptoAesInit (otCryptoContext * aContext )
291436{
292437 psa_key_id_t * key_ref ;
0 commit comments