Skip to content

Commit 9cfd6e1

Browse files
Damian-Nordicadigie
authored andcommitted
[nrf noup] Implement Spake2pVerifier for PSA crypto
When Spake2+ implementation for PSA crypto API is enabled: - do not build the generic Spake2p nor its subclasses - do not build Spake2pVerifier::Generate method that generates the verifier key out of the passcode, salt and iteration count. Instead, provide the implementation Spake2pVerifier::Generate that uses PSA crypto API. Note that using Spake2pVerifier::Generate requires setting CONFIG_PSA_WANT_ALG_PBKDF2_HMAC and CONFIG_PSA_WANT_KEY_TYPE_SPAKE2P_KEY_PAIR_DERIVE Kconfig options. Signed-off-by: Damian Krolik <damian.krolik@nordicsemi.no> (cherry picked from commit aa2e056) Signed-off-by: Adrian Gielniewski <adrian.gielniewski@nordicsemi.no>
1 parent 7aa947a commit 9cfd6e1

File tree

2 files changed

+88
-22
lines changed

2 files changed

+88
-22
lines changed

src/crypto/CHIPCryptoPAL.cpp

+26-22
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,8 @@ CHIP_ERROR Find16BitUpperCaseHexAfterPrefix(const ByteSpan & buffer, const char
238238

239239
using HKDF_sha_crypto = HKDF_sha;
240240

241+
#if !CHIP_CRYPTO_PSA_SPAKE2P
242+
241243
CHIP_ERROR Spake2p::InternalHash(const uint8_t * in, size_t in_len)
242244
{
243245
const uint64_t u64_len = in_len;
@@ -546,28 +548,6 @@ CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::ComputeW0(uint8_t * w0out, size_t * w0
546548
return CHIP_NO_ERROR;
547549
}
548550

549-
CHIP_ERROR Spake2pVerifier::Serialize(MutableByteSpan & outSerialized) const
550-
{
551-
VerifyOrReturnError(outSerialized.size() >= kSpake2p_VerifierSerialized_Length, CHIP_ERROR_INVALID_ARGUMENT);
552-
553-
memcpy(&outSerialized.data()[0], mW0, sizeof(mW0));
554-
memcpy(&outSerialized.data()[sizeof(mW0)], mL, sizeof(mL));
555-
556-
outSerialized.reduce_size(kSpake2p_VerifierSerialized_Length);
557-
558-
return CHIP_NO_ERROR;
559-
}
560-
561-
CHIP_ERROR Spake2pVerifier::Deserialize(const ByteSpan & inSerialized)
562-
{
563-
VerifyOrReturnError(inSerialized.size() >= kSpake2p_VerifierSerialized_Length, CHIP_ERROR_INVALID_ARGUMENT);
564-
565-
memcpy(mW0, &inSerialized.data()[0], sizeof(mW0));
566-
memcpy(mL, &inSerialized.data()[sizeof(mW0)], sizeof(mL));
567-
568-
return CHIP_NO_ERROR;
569-
}
570-
571551
CHIP_ERROR Spake2pVerifier::Generate(uint32_t pbkdf2IterCount, const ByteSpan & salt, uint32_t setupPin)
572552
{
573553
uint8_t serializedWS[kSpake2p_WS_Length * 2] = { 0 };
@@ -596,6 +576,30 @@ CHIP_ERROR Spake2pVerifier::Generate(uint32_t pbkdf2IterCount, const ByteSpan &
596576
return err;
597577
}
598578

579+
#endif // !CHIP_CRYPTO_PSA_SPAKE2P
580+
581+
CHIP_ERROR Spake2pVerifier::Serialize(MutableByteSpan & outSerialized) const
582+
{
583+
VerifyOrReturnError(outSerialized.size() >= kSpake2p_VerifierSerialized_Length, CHIP_ERROR_INVALID_ARGUMENT);
584+
585+
memcpy(&outSerialized.data()[0], mW0, sizeof(mW0));
586+
memcpy(&outSerialized.data()[sizeof(mW0)], mL, sizeof(mL));
587+
588+
outSerialized.reduce_size(kSpake2p_VerifierSerialized_Length);
589+
590+
return CHIP_NO_ERROR;
591+
}
592+
593+
CHIP_ERROR Spake2pVerifier::Deserialize(const ByteSpan & inSerialized)
594+
{
595+
VerifyOrReturnError(inSerialized.size() >= kSpake2p_VerifierSerialized_Length, CHIP_ERROR_INVALID_ARGUMENT);
596+
597+
memcpy(mW0, &inSerialized.data()[0], sizeof(mW0));
598+
memcpy(mL, &inSerialized.data()[sizeof(mW0)], sizeof(mL));
599+
600+
return CHIP_NO_ERROR;
601+
}
602+
599603
CHIP_ERROR Spake2pVerifier::ComputeWS(uint32_t pbkdf2IterCount, const ByteSpan & salt, uint32_t setupPin, uint8_t * ws,
600604
uint32_t ws_len)
601605
{

src/crypto/PSASpake2p.cpp

+62
Original file line numberDiff line numberDiff line change
@@ -197,5 +197,67 @@ CHIP_ERROR PSASpake2p_P256_SHA256_HKDF_HMAC::GetKeys(SessionKeystore & keystore,
197197
return CHIP_NO_ERROR;
198198
}
199199

200+
CHIP_ERROR Spake2pVerifier::Generate(uint32_t pbkdf2IterCount, const ByteSpan & salt, uint32_t setupPin)
201+
{
202+
psa_status_t status = PSA_SUCCESS;
203+
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
204+
psa_key_id_t passwordKey = PSA_KEY_ID_NULL;
205+
psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
206+
psa_key_id_t spakeKey = PSA_KEY_ID_NULL;
207+
uint8_t verifier[kP256_FE_Length + kP256_Point_Length];
208+
size_t verifierLen;
209+
210+
// Prepare password key
211+
uint8_t password[sizeof(uint32_t)];
212+
Encoding::LittleEndian::Put32(password, setupPin);
213+
214+
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE);
215+
psa_set_key_algorithm(&attributes, PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_256));
216+
psa_set_key_type(&attributes, PSA_KEY_TYPE_PASSWORD);
217+
218+
status = psa_import_key(&attributes, password, sizeof(password), &passwordKey);
219+
psa_reset_key_attributes(&attributes);
220+
VerifyOrExit(status == PSA_SUCCESS, );
221+
222+
// Run PBKDF
223+
status = psa_key_derivation_setup(&operation, PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_256));
224+
VerifyOrExit(status == PSA_SUCCESS, );
225+
226+
status = psa_key_derivation_input_integer(&operation, PSA_KEY_DERIVATION_INPUT_COST, pbkdf2IterCount);
227+
VerifyOrExit(status == PSA_SUCCESS, );
228+
229+
status = psa_key_derivation_input_bytes(&operation, PSA_KEY_DERIVATION_INPUT_SALT, salt.data(), salt.size());
230+
VerifyOrExit(status == PSA_SUCCESS, );
231+
232+
status = psa_key_derivation_input_key(&operation, PSA_KEY_DERIVATION_INPUT_PASSWORD, passwordKey);
233+
VerifyOrExit(status == PSA_SUCCESS, );
234+
235+
attributes = psa_key_attributes_init();
236+
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT);
237+
psa_set_key_algorithm(&attributes, PSA_ALG_SPAKE2P_MATTER);
238+
psa_set_key_type(&attributes, PSA_KEY_TYPE_SPAKE2P_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
239+
psa_set_key_bits(&attributes, kP256_FE_Length * 8);
240+
241+
status = psa_key_derivation_output_key(&attributes, &operation, &spakeKey);
242+
psa_reset_key_attributes(&attributes);
243+
VerifyOrExit(status == PSA_SUCCESS, );
244+
245+
// Export verifier as raw bytes
246+
status = psa_export_public_key(spakeKey, verifier, sizeof(verifier), &verifierLen);
247+
248+
exit:
249+
psa_key_derivation_abort(&operation);
250+
psa_destroy_key(passwordKey);
251+
psa_destroy_key(spakeKey);
252+
253+
if (status != PSA_SUCCESS)
254+
{
255+
ChipLogError(Crypto, "PSA error: %d", static_cast<int>(status));
256+
return CHIP_ERROR_INTERNAL;
257+
}
258+
259+
return Deserialize(ByteSpan(verifier, verifierLen));
260+
}
261+
200262
} // namespace Crypto
201263
} // namespace chip

0 commit comments

Comments
 (0)