[crypto] PSA API: support HKDF extraction with HMAC-SHA256 keys

The PSA platform now transparently handles HKDF operations when using
HMAC-SHA256 keys by exporting and re-importing them as volatile
HKDF-SHA256 keys. The export/import logic has been moved into the
platform layer. This change is required to support TREL and the PSA API
key usage restrictions.

Signed-off-by: Łukasz Duda <[email protected]>
This commit is contained in:
Łukasz Duda
2025-11-04 21:53:32 +01:00
parent b614af3a91
commit 2c0c3e84a3
3 changed files with 64 additions and 22 deletions
+36 -4
View File
@@ -451,9 +451,15 @@ OT_TOOL_WEAK otError otPlatCryptoHkdfExtract(otCryptoContext *aContext,
uint16_t aSaltLength,
const otCryptoKey *aInputKey)
{
Error error = kErrorNone;
psa_status_t status = PSA_SUCCESS;
psa_key_derivation_operation_t *operation;
Error error = kErrorNone;
psa_status_t status = PSA_SUCCESS;
psa_key_derivation_operation_t *operation = nullptr;
otCryptoKeyRef keyRef = PSA_KEY_ID_NULL;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_algorithm_t keyAlg = PSA_ALG_NONE;
size_t keyLength = 0;
constexpr size_t kBufferSize = 128;
uint8_t keyBuffer[kBufferSize];
VerifyOrExit(checkContext(aContext, sizeof(psa_key_derivation_operation_t)), error = kErrorInvalidArgs);
VerifyOrExit(aInputKey != nullptr, error = kErrorInvalidArgs);
@@ -463,10 +469,36 @@ OT_TOOL_WEAK otError otPlatCryptoHkdfExtract(otCryptoContext *aContext,
status = psa_key_derivation_input_bytes(operation, PSA_KEY_DERIVATION_INPUT_SALT, aSalt, aSaltLength);
SuccessOrExit(error = psaToOtError(status));
status = psa_key_derivation_input_key(operation, PSA_KEY_DERIVATION_INPUT_SECRET, aInputKey->mKeyRef);
status = psa_get_key_attributes(aInputKey->mKeyRef, &attributes);
SuccessOrExit(error = psaToOtError(status));
keyAlg = psa_get_key_algorithm(&attributes);
// The PSA API enforces a policy that restricts each key to a single algorithm.
// If the key is already HKDF-SHA256, we can use it directly.
// Otherwise, export and re-import it as a volatile HKDF key.
if (keyAlg != toPsaAlgorithm(OT_CRYPTO_KEY_ALG_HKDF_SHA256))
{
SuccessOrExit(error = otPlatCryptoExportKey(aInputKey->mKeyRef, keyBuffer, sizeof(keyBuffer), &keyLength));
SuccessOrExit(error = otPlatCryptoImportKey(&keyRef, OT_CRYPTO_KEY_TYPE_DERIVE, OT_CRYPTO_KEY_ALG_HKDF_SHA256,
OT_CRYPTO_KEY_USAGE_DERIVE, OT_CRYPTO_KEY_STORAGE_VOLATILE,
keyBuffer, keyLength));
status = psa_key_derivation_input_key(operation, PSA_KEY_DERIVATION_INPUT_SECRET, keyRef);
SuccessOrExit(error = psaToOtError(status));
}
else
{
status = psa_key_derivation_input_key(operation, PSA_KEY_DERIVATION_INPUT_SECRET, aInputKey->mKeyRef);
SuccessOrExit(error = psaToOtError(status));
}
exit:
if (keyRef != PSA_KEY_ID_NULL)
{
otPlatCryptoDestroyKey(keyRef);
}
return error;
}
+1 -15
View File
@@ -311,17 +311,7 @@ void KeyManager::ComputeTrelKey(uint32_t aKeySequence, Mac::Key &aKey) const
Crypto::Key cryptoKey;
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
Crypto::Storage::KeyRef keyRef;
NetworkKey networkKey;
GetNetworkKey(networkKey);
// Create temporary key to perform derive operation.
SuccessOrAssert(Crypto::Storage::ImportKey(keyRef, Crypto::Storage::kKeyTypeDerive,
Crypto::Storage::kKeyAlgorithmHkdfSha256, Crypto::Storage::kUsageDerive,
Crypto::Storage::kTypeVolatile, networkKey.m8, NetworkKey::kSize));
cryptoKey.SetAsKeyRef(keyRef);
cryptoKey.SetAsKeyRef(mNetworkKeyRef);
#else
cryptoKey.Set(mNetworkKey.m8, NetworkKey::kSize);
#endif
@@ -331,10 +321,6 @@ void KeyManager::ComputeTrelKey(uint32_t aKeySequence, Mac::Key &aKey) const
hkdf.Extract(salt, sizeof(salt), cryptoKey);
hkdf.Expand(kTrelInfoString, sizeof(kTrelInfoString), aKey.m8, Mac::Key::kSize);
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
Crypto::Storage::DestroyKey(keyRef);
#endif
}
#endif