Skip to content

Commit

Permalink
[nrf noup] Implement Spake2pVerifier for PSA crypto
Browse files Browse the repository at this point in the history
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 <[email protected]>
(cherry picked from commit aa2e056)
Signed-off-by: Adrian Gielniewski <[email protected]>
  • Loading branch information
Damian-Nordic authored and adigie committed Nov 28, 2024
1 parent 7aa947a commit 9cfd6e1
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 22 deletions.
48 changes: 26 additions & 22 deletions src/crypto/CHIPCryptoPAL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,8 @@ CHIP_ERROR Find16BitUpperCaseHexAfterPrefix(const ByteSpan & buffer, const char

using HKDF_sha_crypto = HKDF_sha;

#if !CHIP_CRYPTO_PSA_SPAKE2P

CHIP_ERROR Spake2p::InternalHash(const uint8_t * in, size_t in_len)
{
const uint64_t u64_len = in_len;
Expand Down Expand Up @@ -546,28 +548,6 @@ CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::ComputeW0(uint8_t * w0out, size_t * w0
return CHIP_NO_ERROR;
}

CHIP_ERROR Spake2pVerifier::Serialize(MutableByteSpan & outSerialized) const
{
VerifyOrReturnError(outSerialized.size() >= kSpake2p_VerifierSerialized_Length, CHIP_ERROR_INVALID_ARGUMENT);

memcpy(&outSerialized.data()[0], mW0, sizeof(mW0));
memcpy(&outSerialized.data()[sizeof(mW0)], mL, sizeof(mL));

outSerialized.reduce_size(kSpake2p_VerifierSerialized_Length);

return CHIP_NO_ERROR;
}

CHIP_ERROR Spake2pVerifier::Deserialize(const ByteSpan & inSerialized)
{
VerifyOrReturnError(inSerialized.size() >= kSpake2p_VerifierSerialized_Length, CHIP_ERROR_INVALID_ARGUMENT);

memcpy(mW0, &inSerialized.data()[0], sizeof(mW0));
memcpy(mL, &inSerialized.data()[sizeof(mW0)], sizeof(mL));

return CHIP_NO_ERROR;
}

CHIP_ERROR Spake2pVerifier::Generate(uint32_t pbkdf2IterCount, const ByteSpan & salt, uint32_t setupPin)
{
uint8_t serializedWS[kSpake2p_WS_Length * 2] = { 0 };
Expand Down Expand Up @@ -596,6 +576,30 @@ CHIP_ERROR Spake2pVerifier::Generate(uint32_t pbkdf2IterCount, const ByteSpan &
return err;
}

#endif // !CHIP_CRYPTO_PSA_SPAKE2P

CHIP_ERROR Spake2pVerifier::Serialize(MutableByteSpan & outSerialized) const
{
VerifyOrReturnError(outSerialized.size() >= kSpake2p_VerifierSerialized_Length, CHIP_ERROR_INVALID_ARGUMENT);

memcpy(&outSerialized.data()[0], mW0, sizeof(mW0));
memcpy(&outSerialized.data()[sizeof(mW0)], mL, sizeof(mL));

outSerialized.reduce_size(kSpake2p_VerifierSerialized_Length);

return CHIP_NO_ERROR;
}

CHIP_ERROR Spake2pVerifier::Deserialize(const ByteSpan & inSerialized)
{
VerifyOrReturnError(inSerialized.size() >= kSpake2p_VerifierSerialized_Length, CHIP_ERROR_INVALID_ARGUMENT);

memcpy(mW0, &inSerialized.data()[0], sizeof(mW0));
memcpy(mL, &inSerialized.data()[sizeof(mW0)], sizeof(mL));

return CHIP_NO_ERROR;
}

CHIP_ERROR Spake2pVerifier::ComputeWS(uint32_t pbkdf2IterCount, const ByteSpan & salt, uint32_t setupPin, uint8_t * ws,
uint32_t ws_len)
{
Expand Down
62 changes: 62 additions & 0 deletions src/crypto/PSASpake2p.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,5 +197,67 @@ CHIP_ERROR PSASpake2p_P256_SHA256_HKDF_HMAC::GetKeys(SessionKeystore & keystore,
return CHIP_NO_ERROR;
}

CHIP_ERROR Spake2pVerifier::Generate(uint32_t pbkdf2IterCount, const ByteSpan & salt, uint32_t setupPin)
{
psa_status_t status = PSA_SUCCESS;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t passwordKey = PSA_KEY_ID_NULL;
psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
psa_key_id_t spakeKey = PSA_KEY_ID_NULL;
uint8_t verifier[kP256_FE_Length + kP256_Point_Length];
size_t verifierLen;

// Prepare password key
uint8_t password[sizeof(uint32_t)];
Encoding::LittleEndian::Put32(password, setupPin);

psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE);
psa_set_key_algorithm(&attributes, PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_256));
psa_set_key_type(&attributes, PSA_KEY_TYPE_PASSWORD);

status = psa_import_key(&attributes, password, sizeof(password), &passwordKey);
psa_reset_key_attributes(&attributes);
VerifyOrExit(status == PSA_SUCCESS, );

// Run PBKDF
status = psa_key_derivation_setup(&operation, PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_256));
VerifyOrExit(status == PSA_SUCCESS, );

status = psa_key_derivation_input_integer(&operation, PSA_KEY_DERIVATION_INPUT_COST, pbkdf2IterCount);
VerifyOrExit(status == PSA_SUCCESS, );

status = psa_key_derivation_input_bytes(&operation, PSA_KEY_DERIVATION_INPUT_SALT, salt.data(), salt.size());
VerifyOrExit(status == PSA_SUCCESS, );

status = psa_key_derivation_input_key(&operation, PSA_KEY_DERIVATION_INPUT_PASSWORD, passwordKey);
VerifyOrExit(status == PSA_SUCCESS, );

attributes = psa_key_attributes_init();
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT);
psa_set_key_algorithm(&attributes, PSA_ALG_SPAKE2P_MATTER);
psa_set_key_type(&attributes, PSA_KEY_TYPE_SPAKE2P_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
psa_set_key_bits(&attributes, kP256_FE_Length * 8);

status = psa_key_derivation_output_key(&attributes, &operation, &spakeKey);
psa_reset_key_attributes(&attributes);
VerifyOrExit(status == PSA_SUCCESS, );

// Export verifier as raw bytes
status = psa_export_public_key(spakeKey, verifier, sizeof(verifier), &verifierLen);

exit:
psa_key_derivation_abort(&operation);
psa_destroy_key(passwordKey);
psa_destroy_key(spakeKey);

if (status != PSA_SUCCESS)
{
ChipLogError(Crypto, "PSA error: %d", static_cast<int>(status));
return CHIP_ERROR_INTERNAL;
}

return Deserialize(ByteSpan(verifier, verifierLen));
}

} // namespace Crypto
} // namespace chip

0 comments on commit 9cfd6e1

Please sign in to comment.