Skip to content

Commit ed08951

Browse files
committed
[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 <lukasz.duda@nordicsemi.no>
1 parent 0475f5d commit ed08951

File tree

3 files changed

+62
-22
lines changed

3 files changed

+62
-22
lines changed

src/core/crypto/crypto_platform_psa.cpp

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -451,9 +451,15 @@ OT_TOOL_WEAK otError otPlatCryptoHkdfExtract(otCryptoContext *aContext,
451451
uint16_t aSaltLength,
452452
const otCryptoKey *aInputKey)
453453
{
454-
Error error = kErrorNone;
455-
psa_status_t status = PSA_SUCCESS;
456-
psa_key_derivation_operation_t *operation;
454+
Error error = kErrorNone;
455+
psa_status_t status = PSA_SUCCESS;
456+
psa_key_derivation_operation_t *operation = nullptr;
457+
otCryptoKeyRef keyRef = PSA_KEY_ID_NULL;
458+
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
459+
psa_algorithm_t keyAlg = PSA_ALG_NONE;
460+
size_t keyLength = 0;
461+
constexpr size_t kBufferSize = 80;
462+
uint8_t keyBuffer[kBufferSize];
457463

458464
VerifyOrExit(checkContext(aContext, sizeof(psa_key_derivation_operation_t)), error = kErrorInvalidArgs);
459465
VerifyOrExit(aInputKey != nullptr, error = kErrorInvalidArgs);
@@ -463,10 +469,34 @@ OT_TOOL_WEAK otError otPlatCryptoHkdfExtract(otCryptoContext *aContext,
463469
status = psa_key_derivation_input_bytes(operation, PSA_KEY_DERIVATION_INPUT_SALT, aSalt, aSaltLength);
464470
SuccessOrExit(error = psaToOtError(status));
465471

466-
status = psa_key_derivation_input_key(operation, PSA_KEY_DERIVATION_INPUT_SECRET, aInputKey->mKeyRef);
472+
status = psa_get_key_attributes(aInputKey->mKeyRef, &attributes);
467473
SuccessOrExit(error = psaToOtError(status));
468474

475+
keyAlg = psa_get_key_algorithm(&attributes);
476+
477+
// The PSA API enforces a policy that restricts each key to a single algorithm.
478+
// If the key is already HKDF-SHA256, we can use it directly.
479+
// Otherwise, export and re-import it as a volatile HKDF key.
480+
if (keyAlg != toPsaAlgorithm(OT_CRYPTO_KEY_ALG_HKDF_SHA256))
481+
{
482+
SuccessOrExit(error = otPlatCryptoExportKey(aInputKey->mKeyRef, keyBuffer, sizeof(keyBuffer), &keyLength));
483+
SuccessOrExit(error = otPlatCryptoImportKey(&keyRef, OT_CRYPTO_KEY_TYPE_DERIVE, OT_CRYPTO_KEY_ALG_HKDF_SHA256,
484+
OT_CRYPTO_KEY_USAGE_DERIVE, OT_CRYPTO_KEY_STORAGE_VOLATILE,
485+
keyBuffer, keyLength));
486+
487+
status = psa_key_derivation_input_key(operation, PSA_KEY_DERIVATION_INPUT_SECRET, keyRef);
488+
SuccessOrExit(error = psaToOtError(status));
489+
}
490+
else
491+
{
492+
status = psa_key_derivation_input_key(operation, PSA_KEY_DERIVATION_INPUT_SECRET, aInputKey->mKeyRef);
493+
SuccessOrExit(error = psaToOtError(status));
494+
}
495+
469496
exit:
497+
psa_reset_key_attributes(&attributes);
498+
psa_destroy_key(keyRef);
499+
470500
return error;
471501
}
472502

src/core/thread/key_manager.cpp

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -311,17 +311,7 @@ void KeyManager::ComputeTrelKey(uint32_t aKeySequence, Mac::Key &aKey) const
311311
Crypto::Key cryptoKey;
312312

313313
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
314-
Crypto::Storage::KeyRef keyRef;
315-
NetworkKey networkKey;
316-
317-
GetNetworkKey(networkKey);
318-
319-
// Create temporary key to perform derive operation.
320-
SuccessOrAssert(Crypto::Storage::ImportKey(keyRef, Crypto::Storage::kKeyTypeDerive,
321-
Crypto::Storage::kKeyAlgorithmHkdfSha256, Crypto::Storage::kUsageDerive,
322-
Crypto::Storage::kTypeVolatile, networkKey.m8, NetworkKey::kSize));
323-
324-
cryptoKey.SetAsKeyRef(keyRef);
314+
cryptoKey.SetAsKeyRef(mNetworkKeyRef);
325315
#else
326316
cryptoKey.Set(mNetworkKey.m8, NetworkKey::kSize);
327317
#endif
@@ -331,10 +321,6 @@ void KeyManager::ComputeTrelKey(uint32_t aKeySequence, Mac::Key &aKey) const
331321

332322
hkdf.Extract(salt, sizeof(salt), cryptoKey);
333323
hkdf.Expand(kTrelInfoString, sizeof(kTrelInfoString), aKey.m8, Mac::Key::kSize);
334-
335-
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
336-
Crypto::Storage::DestroyKey(keyRef);
337-
#endif
338324
}
339325
#endif
340326

tests/unit/test_hkdf_sha256.cpp

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,11 @@ struct TestVector
5050
uint16_t mOutKeyLength;
5151
};
5252

53+
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
54+
void TestHkdfSha256(Crypto::Storage::KeyAlgorithm aAlgorithm)
55+
#else
5356
void TestHkdfSha256(void)
57+
#endif
5458
{
5559
enum
5660
{
@@ -147,9 +151,23 @@ void TestHkdfSha256(void)
147151
memset(outKey, kFillByte, sizeof(outKey));
148152

149153
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
150-
SuccessOrQuit(Crypto::Storage::ImportKey(
151-
keyRef, Crypto::Storage::kKeyTypeDerive, Crypto::Storage::kKeyAlgorithmHkdfSha256,
152-
Crypto::Storage::kUsageDerive, Crypto::Storage::kTypeVolatile, test->mInKey, test->mInKeyLength));
154+
if (aAlgorithm == Crypto::Storage::kKeyAlgorithmHkdfSha256)
155+
{
156+
SuccessOrQuit(Crypto::Storage::ImportKey(
157+
keyRef, Crypto::Storage::kKeyTypeDerive, Crypto::Storage::kKeyAlgorithmHkdfSha256,
158+
Crypto::Storage::kUsageDerive, Crypto::Storage::kTypeVolatile, test->mInKey, test->mInKeyLength));
159+
}
160+
else if (aAlgorithm == Crypto::Storage::kKeyAlgorithmHmacSha256)
161+
{
162+
SuccessOrQuit(Crypto::Storage::ImportKey(keyRef, Crypto::Storage::kKeyTypeHmac,
163+
Crypto::Storage::kKeyAlgorithmHmacSha256,
164+
Crypto::Storage::kUsageSignHash | Crypto::Storage::kUsageExport,
165+
Crypto::Storage::kTypeVolatile, test->mInKey, test->mInKeyLength));
166+
}
167+
else
168+
{
169+
VerifyOrQuit(false);
170+
}
153171

154172
testInputKey.SetAsKeyRef(keyRef);
155173
#else
@@ -180,7 +198,13 @@ void TestHkdfSha256(void)
180198

181199
int main(void)
182200
{
201+
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
202+
ot::TestHkdfSha256(ot::Crypto::Storage::kKeyAlgorithmHkdfSha256);
203+
ot::TestHkdfSha256(ot::Crypto::Storage::kKeyAlgorithmHmacSha256);
204+
#else
183205
ot::TestHkdfSha256();
206+
#endif
207+
184208
printf("All tests passed\n");
185209
return 0;
186210
}

0 commit comments

Comments
 (0)