Skip to content

Commit

Permalink
[nrf noup] Spake2+ alignments regarding the newest Oberon version
Browse files Browse the repository at this point in the history
Aligned Spake2+ algorithm to the Oberon PSA core v1.2.1.1
  • Loading branch information
ArekBalysNordic committed Feb 27, 2024
1 parent b745cdf commit efdae04
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 125 deletions.
7 changes: 1 addition & 6 deletions config/nrfconnect/chip-module/Kconfig.defaults
Original file line number Diff line number Diff line change
Expand Up @@ -297,9 +297,7 @@ config MBEDTLS_HEAP_SIZE

config CHIP_CRYPTO_PSA
default y if !CHIP_WIFI
imply PSA_WANT_ALG_SPAKE2P
# Set SPAKE2P to version 4 to be compatible with Matter specification.
imply PSA_CRYPTO_SPAKE2P_USE_VERSION_04
imply PSA_WANT_ALG_SPAKE2P_MATTER

if CHIP_CRYPTO_PSA

Expand All @@ -309,9 +307,6 @@ config PSA_CRYPTO_DRIVER_CC3XX
config PSA_WANT_ALG_SHA_224
default n

config PSA_WANT_ALG_SPAKE2P
default y

# Extend the maximum number of PSA key slots to fit Matter requirements
config MBEDTLS_PSA_KEY_SLOT_COUNT
default 64
Expand Down
49 changes: 14 additions & 35 deletions src/crypto/CHIPCryptoPALPSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -284,58 +284,37 @@ CHIP_ERROR PsaKdf::Init(const ByteSpan & secret, const ByteSpan & salt, const By
psa_reset_key_attributes(&attrs);
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);

PsaHkdfKeyHandle hkdfKeyHandle = { .mKeyId = mSecretKeyId, .mIsKeyId = true };

return InitOperation(hkdfKeyHandle, salt, info);
return InitOperation(mSecretKeyId, salt, info);
}

CHIP_ERROR PsaKdf::Init(const HkdfKeyHandle & hkdfKey, const ByteSpan & salt, const ByteSpan & info)
{
return InitOperation(hkdfKey.As<PsaHkdfKeyHandle>(), salt, info);
return InitOperation(hkdfKey.As<psa_key_id_t>(), salt, info);
}

CHIP_ERROR PsaKdf::InitOperation(PsaHkdfKeyHandle hkdfKey, const ByteSpan & salt, const ByteSpan & info)
CHIP_ERROR PsaKdf::InitOperation(psa_key_id_t hkdfKey, const ByteSpan & salt, const ByteSpan & info)
{
psa_status_t status;
if (hkdfKey.mIsKeyId)
{
status = psa_key_derivation_setup(&mOperation, PSA_ALG_HKDF(PSA_ALG_SHA_256));
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);

if (salt.size() > 0)
{
status = psa_key_derivation_input_bytes(&mOperation, PSA_KEY_DERIVATION_INPUT_SALT, salt.data(), salt.size());
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
}

status = psa_key_derivation_input_key(&mOperation, PSA_KEY_DERIVATION_INPUT_SECRET, hkdfKey.mKeyId);
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
psa_status_t status = psa_key_derivation_setup(&mOperation, PSA_ALG_HKDF(PSA_ALG_SHA_256));
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);

status = psa_key_derivation_input_bytes(&mOperation, PSA_KEY_DERIVATION_INPUT_INFO, info.data(), info.size());
if (salt.size() > 0)
{
status = psa_key_derivation_input_bytes(&mOperation, PSA_KEY_DERIVATION_INPUT_SALT, salt.data(), salt.size());
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);

mDerivationOperation = &mOperation;
}
else
{
mDerivationOperation = hkdfKey.mKeyDerivationOp;

if (salt.size() > 0)
{
status = psa_key_derivation_input_bytes(mDerivationOperation, PSA_KEY_DERIVATION_INPUT_SALT, salt.data(), salt.size());
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
}
status = psa_key_derivation_input_key(&mOperation, PSA_KEY_DERIVATION_INPUT_SECRET, hkdfKey);
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);

status = psa_key_derivation_input_bytes(mDerivationOperation, PSA_KEY_DERIVATION_INPUT_INFO, info.data(), info.size());
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
}
status = psa_key_derivation_input_bytes(&mOperation, PSA_KEY_DERIVATION_INPUT_INFO, info.data(), info.size());
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);

return CHIP_NO_ERROR;
}

CHIP_ERROR PsaKdf::DeriveBytes(const MutableByteSpan & output)
{
psa_status_t status = psa_key_derivation_output_bytes(mDerivationOperation, output.data(), output.size());
psa_status_t status = psa_key_derivation_output_bytes(&mOperation, output.data(), output.size());

VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);

Expand All @@ -344,7 +323,7 @@ CHIP_ERROR PsaKdf::DeriveBytes(const MutableByteSpan & output)

CHIP_ERROR PsaKdf::DeriveKey(const psa_key_attributes_t & attributes, psa_key_id_t & keyId)
{
psa_status_t status = psa_key_derivation_output_key(&attributes, mDerivationOperation, &keyId);
psa_status_t status = psa_key_derivation_output_key(&attributes, &mOperation, &keyId);

VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);

Expand Down
18 changes: 3 additions & 15 deletions src/crypto/CHIPCryptoPALPSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,17 +95,6 @@ inline const PsaP256KeypairContext & ToConstPsaContext(const P256KeypairContext
return *SafePointerCast<const PsaP256KeypairContext *>(&context);
}

struct PsaHkdfKeyHandle
{
union
{
psa_key_id_t mKeyId;
psa_key_derivation_operation_t * mKeyDerivationOp;
};

bool mIsKeyId = true;
};

/**
* @brief Wrapper for PSA key derivation API.
*/
Expand Down Expand Up @@ -156,11 +145,10 @@ class PsaKdf
CHIP_ERROR DeriveKey(const psa_key_attributes_t & attributes, psa_key_id_t & keyId);

private:
CHIP_ERROR InitOperation(PsaHkdfKeyHandle hkdfKey, const ByteSpan & salt, const ByteSpan & info);
CHIP_ERROR InitOperation(psa_key_id_t hkdfKey, const ByteSpan & salt, const ByteSpan & info);

psa_key_id_t mSecretKeyId = PSA_KEY_ID_NULL;
psa_key_derivation_operation_t mOperation = PSA_KEY_DERIVATION_OPERATION_INIT;
psa_key_derivation_operation_t * mDerivationOperation = nullptr;
psa_key_id_t mSecretKeyId = PSA_KEY_ID_NULL;
psa_key_derivation_operation_t mOperation = PSA_KEY_DERIVATION_OPERATION_INIT;
};
} // namespace Crypto
} // namespace chip
14 changes: 3 additions & 11 deletions src/crypto/PSASessionKeystore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,18 +186,10 @@ void PSASessionKeystore::DestroyKey(Symmetric128BitsKeyHandle & key)

void PSASessionKeystore::DestroyKey(HkdfKeyHandle & key)
{
auto & keyHandle = key.AsMutable<PsaHkdfKeyHandle>();
auto & keyId = key.AsMutable<psa_key_id_t>();

if (keyHandle.mIsKeyId)
{
psa_destroy_key(keyHandle.mKeyId);
keyHandle.mKeyId = 0;
}
else
{
Platform::Delete(keyHandle.mKeyDerivationOp);
keyHandle.mKeyDerivationOp = nullptr;
}
psa_destroy_key(keyId);
keyId = PSA_KEY_ID_NULL;
}

} // namespace Crypto
Expand Down
102 changes: 46 additions & 56 deletions src/crypto/PSASpake2p.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,6 @@ CHIP_ERROR PSASpake2p_P256_SHA256_HKDF_HMAC::Init(const uint8_t * context, size_

VerifyOrReturnError(context_len <= sizeof(mContext), CHIP_ERROR_BUFFER_TOO_SMALL);

psa_pake_cipher_suite_t cs = PSA_PAKE_CIPHER_SUITE_INIT;
psa_pake_cs_set_algorithm(&cs, PSA_ALG_SPAKE2P);
psa_pake_cs_set_primitive(&cs, PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256));
psa_pake_cs_set_hash(&cs, PSA_ALG_SHA_256);

psa_status_t status = psa_pake_setup(&mOperation, &cs);
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);

memcpy(mContext, context, context_len);
mContextLen = context_len;

Expand All @@ -64,33 +56,38 @@ CHIP_ERROR PSASpake2p_P256_SHA256_HKDF_HMAC::BeginVerifier(const uint8_t * my_id
VerifyOrReturnError(w0in_len <= kSpake2p_WS_Length, CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(Lin_len == kP256_Point_Length, CHIP_ERROR_INVALID_ARGUMENT);

mRole = PSA_PAKE_ROLE_SERVER;
psa_status_t status = psa_pake_set_role(&mOperation, PSA_PAKE_ROLE_SERVER);
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);

status = psa_pake_set_peer(&mOperation, peer_identity, peer_identity_len);
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);

status = psa_pake_set_user(&mOperation, my_identity, my_identity_len);
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);

uint8_t password[kSpake2p_WS_Length + kP256_Point_Length];
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_pake_cipher_suite_t cp = PSA_PAKE_CIPHER_SUITE_INIT;

psa_pake_cs_set_algorithm(&cp, PSA_ALG_SPAKE2P_MATTER);
psa_pake_cs_set_primitive(&cp, PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256));

memcpy(password + 0, w0in, w0in_len);
memcpy(password + w0in_len, Lin, Lin_len);
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE);
psa_set_key_algorithm(&attributes, PSA_ALG_SPAKE2P);
psa_set_key_type(&attributes, PSA_KEY_TYPE_PASSWORD);
psa_set_key_algorithm(&attributes, PSA_ALG_SPAKE2P_MATTER);
psa_set_key_type(&attributes, PSA_KEY_TYPE_SPAKE2P_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1));

psa_status_t status = psa_import_key(&attributes, password, w0in_len + Lin_len, &mKey);

status = psa_import_key(&attributes, password, w0in_len + Lin_len, &mKey);
psa_reset_key_attributes(&attributes);
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);

status = psa_pake_set_password_key(&mOperation, mKey);
status = psa_pake_setup(&mOperation, mKey, &cp);
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);

mRole = PSA_PAKE_ROLE_SERVER;
status = psa_pake_set_role(&mOperation, PSA_PAKE_ROLE_SERVER);
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);

status = psa_pake_input(&mOperation, PSA_PAKE_STEP_CONTEXT, mContext, mContextLen);
status = psa_pake_set_peer(&mOperation, peer_identity, peer_identity_len);
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);

status = psa_pake_set_user(&mOperation, my_identity, my_identity_len);
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);

status = psa_pake_set_context(&mOperation, mContext, mContextLen);
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);

return CHIP_NO_ERROR;
Expand All @@ -104,33 +101,38 @@ CHIP_ERROR PSASpake2p_P256_SHA256_HKDF_HMAC::BeginProver(const uint8_t * my_iden
VerifyOrReturnError(w0in_len <= kSpake2p_WS_Length, CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(w1in_len <= kSpake2p_WS_Length, CHIP_ERROR_INVALID_ARGUMENT);

mRole = PSA_PAKE_ROLE_CLIENT;
psa_status_t status = psa_pake_set_role(&mOperation, PSA_PAKE_ROLE_CLIENT);
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);

status = psa_pake_set_user(&mOperation, my_identity, my_identity_len);
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);

status = psa_pake_set_peer(&mOperation, peer_identity, peer_identity_len);
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);

uint8_t password[kSpake2p_WS_Length * 2];
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_pake_cipher_suite_t cp = PSA_PAKE_CIPHER_SUITE_INIT;

psa_pake_cs_set_algorithm(&cp, PSA_ALG_SPAKE2P_MATTER);
psa_pake_cs_set_primitive(&cp, PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256));

memcpy(password + 0, w0in, w0in_len);
memcpy(password + w0in_len, w1in, w1in_len);
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE);
psa_set_key_algorithm(&attributes, PSA_ALG_SPAKE2P);
psa_set_key_type(&attributes, PSA_KEY_TYPE_PASSWORD);
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_status_t status = psa_import_key(&attributes, password, w0in_len + w1in_len, &mKey);

status = psa_import_key(&attributes, password, w0in_len + w1in_len, &mKey);
psa_reset_key_attributes(&attributes);
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);

status = psa_pake_set_password_key(&mOperation, mKey);
status = psa_pake_setup(&mOperation, mKey, &cp);
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);

mRole = PSA_PAKE_ROLE_CLIENT;
status = psa_pake_set_role(&mOperation, PSA_PAKE_ROLE_CLIENT);
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);

status = psa_pake_input(&mOperation, PSA_PAKE_STEP_CONTEXT, mContext, mContextLen);
status = psa_pake_set_user(&mOperation, my_identity, my_identity_len);
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);

status = psa_pake_set_peer(&mOperation, peer_identity, peer_identity_len);
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);

status = psa_pake_set_context(&mOperation, mContext, mContextLen);
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);

return CHIP_NO_ERROR;
Expand Down Expand Up @@ -182,29 +184,17 @@ CHIP_ERROR PSASpake2p_P256_SHA256_HKDF_HMAC::KeyConfirm(const uint8_t * in, size

CHIP_ERROR PSASpake2p_P256_SHA256_HKDF_HMAC::GetKeys(SessionKeystore & keystore, HkdfKeyHandle & key)
{
/*
* TODO: use psa_pake_shared_secret() proposed in https://github.com/ARM-software/psa-api/issues/86
*/

psa_key_derivation_operation_t * kdf = Platform::New<psa_key_derivation_operation_t>();
Platform::UniquePtr<psa_key_derivation_operation_t> kdfPtr(kdf);

VerifyOrReturnError(kdfPtr, CHIP_ERROR_NO_MEMORY);
auto & keyId = key.AsMutable<psa_key_id_t>();

*kdfPtr = PSA_KEY_DERIVATION_OPERATION_INIT;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;

psa_status_t status = psa_key_derivation_setup(kdfPtr.get(), PSA_ALG_HKDF(PSA_ALG_SHA_256));
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
psa_set_key_type(&attributes, PSA_KEY_TYPE_DERIVE);
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE);
psa_set_key_algorithm(&attributes, PSA_ALG_HKDF(PSA_ALG_SHA_256));

status = psa_pake_get_implicit_key(&mOperation, kdfPtr.get());
psa_status_t status = psa_pake_get_shared_key(&mOperation, &attributes, &keyId);
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);

auto & hkdfKeyHandle = key.AsMutable<PsaHkdfKeyHandle>();
hkdfKeyHandle.mKeyDerivationOp = kdfPtr.get();
hkdfKeyHandle.mIsKeyId = false;

kdfPtr.release();

return CHIP_NO_ERROR;
}

Expand Down
3 changes: 1 addition & 2 deletions src/platform/nrfconnect/CHIPPlatformConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@

#ifdef CONFIG_CHIP_CRYPTO_PSA
#define CHIP_CONFIG_SHA256_CONTEXT_SIZE sizeof(psa_hash_operation_t)
// Alignment to sizeof(PsaHkdfKeyHandle) from crypto/CHIPCryptoPALPSA.h.
#define CHIP_CONFIG_HKDF_KEY_HANDLE_CONTEXT_SIZE (sizeof(psa_key_id_t) + sizeof(bool))
#define CHIP_CONFIG_HKDF_KEY_HANDLE_CONTEXT_SIZE sizeof(psa_key_id_t)
#elif defined(CONFIG_CC3XX_BACKEND)
// Size of the statically allocated context for SHA256 operations in CryptoPAL
// determined empirically.
Expand Down

0 comments on commit efdae04

Please sign in to comment.