Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Crypto] Add HMAC function using KeyHandle #30751

Merged
merged 5 commits into from
Dec 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/app/icd/ICDCheckInSender.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class ICDCheckInSender : public AddressResolve::NodeListener

Messaging::ExchangeManager * mExchangeManager = nullptr;

Crypto::Aes128BitsKeyHandle mKey = Crypto::Aes128BitsKeyHandle();
Crypto::Aes128KeyHandle mKey = Crypto::Aes128KeyHandle();

uint32_t mICDCounter = 0;
};
Expand Down
2 changes: 1 addition & 1 deletion src/app/icd/ICDMonitoringTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ struct ICDMonitoringEntry : public PersistentData<kICDMonitoringBufferSize>
chip::FabricIndex fabricIndex = kUndefinedFabricIndex;
chip::NodeId checkInNodeID = kUndefinedNodeId;
uint64_t monitoredSubject = static_cast<uint64_t>(0);
Crypto::Aes128BitsKeyHandle key = Crypto::Aes128BitsKeyHandle();
Crypto::Aes128KeyHandle key = Crypto::Aes128KeyHandle();
bool keyHandleValid = false;
uint16_t index = 0;
Crypto::SymmetricKeystore * symmetricKeystore = nullptr;
Expand Down
2 changes: 1 addition & 1 deletion src/app/icd/client/ICDClientInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ struct ICDClientInfo
uint32_t user_active_mode_trigger_hint = 0;
char user_active_mode_trigger_instruction[kUserActiveModeTriggerInstructionSize] = { 0 };
bool has_instruction = false;
Crypto::Aes128BitsKeyHandle shared_key = Crypto::Aes128BitsKeyHandle();
Crypto::Aes128KeyHandle shared_key = Crypto::Aes128KeyHandle();

ICDClientInfo() {}
ICDClientInfo(const ICDClientInfo & other) { *this = other; }
Expand Down
4 changes: 2 additions & 2 deletions src/credentials/GroupDataProviderImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -201,8 +201,8 @@ class GroupDataProviderImpl : public GroupDataProvider
protected:
GroupDataProviderImpl & mProvider;
uint16_t mKeyHash = 0;
Crypto::Aes128BitsKeyHandle mEncryptionKey;
Crypto::Aes128BitsKeyHandle mPrivacyKey;
Crypto::Aes128KeyHandle mEncryptionKey;
Crypto::Aes128KeyHandle mPrivacyKey;
};

class KeySetIteratorImpl : public KeySetIterator
Expand Down
7 changes: 1 addition & 6 deletions src/crypto/CHIPCryptoPAL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,11 +233,6 @@ CHIP_ERROR Find16BitUpperCaseHexAfterPrefix(const ByteSpan & buffer, const char

} // namespace

Symmetric128BitsKeyHandle::~Symmetric128BitsKeyHandle()
{
ClearSecretData(mContext.mOpaque);
}

using HKDF_sha_crypto = HKDF_sha;

CHIP_ERROR Spake2p::InternalHash(const uint8_t * in, size_t in_len)
Expand Down Expand Up @@ -784,7 +779,7 @@ CHIP_ERROR EcdsaAsn1SignatureToRaw(size_t fe_length_bytes, const ByteSpan & asn1
return CHIP_NO_ERROR;
}

CHIP_ERROR AES_CTR_crypt(const uint8_t * input, size_t input_length, const Aes128BitsKeyHandle & key, const uint8_t * nonce,
CHIP_ERROR AES_CTR_crypt(const uint8_t * input, size_t input_length, const Aes128KeyHandle & key, const uint8_t * nonce,
size_t nonce_length, uint8_t * output)
{
// Discard tag portion of CCM to apply only CTR mode encryption/decryption.
Expand Down
67 changes: 45 additions & 22 deletions src/crypto/CHIPCryptoPAL.h
Original file line number Diff line number Diff line change
Expand Up @@ -574,15 +574,11 @@ using Symmetric128BitsKeyByteArray = uint8_t[CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BY
*
* @note Symmetric128BitsKeyHandle is an abstract class to force child classes for each key handle type.
* Symmetric128BitsKeyHandle class implements all the necessary components for handles.
* Child classes only need to implement a constructor, implement a destructor and delete all the copy operators.
* Child classes only need to implement a constructor and delete all the copy operators.
*/
class Symmetric128BitsKeyHandle
{
public:
Symmetric128BitsKeyHandle() = default;
// Destructor is implemented in the .cpp. It is pure virtual only to force the class to be abstract.
virtual ~Symmetric128BitsKeyHandle() = 0;

Symmetric128BitsKeyHandle(const Symmetric128BitsKeyHandle &) = delete;
Symmetric128BitsKeyHandle(Symmetric128BitsKeyHandle &&) = delete;
void operator=(const Symmetric128BitsKeyHandle &) = delete;
Expand All @@ -606,6 +602,10 @@ class Symmetric128BitsKeyHandle
return *SafePointerCast<T *>(&mContext);
}

protected:
Symmetric128BitsKeyHandle() = default;
~Symmetric128BitsKeyHandle() { ClearSecretData(mContext.mOpaque); }

private:
static constexpr size_t kContextSize = CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES;

Expand All @@ -618,31 +618,29 @@ class Symmetric128BitsKeyHandle
/**
* @brief Platform-specific AES key handle
*/
class Aes128BitsKeyHandle : public Symmetric128BitsKeyHandle
class Aes128KeyHandle final : public Symmetric128BitsKeyHandle
{
public:
Aes128BitsKeyHandle() = default;
virtual ~Aes128BitsKeyHandle() {}
Aes128KeyHandle() = default;

Aes128BitsKeyHandle(const Aes128BitsKeyHandle &) = delete;
Aes128BitsKeyHandle(Aes128BitsKeyHandle &&) = delete;
void operator=(const Aes128BitsKeyHandle &) = delete;
void operator=(Aes128BitsKeyHandle &&) = delete;
Aes128KeyHandle(const Aes128KeyHandle &) = delete;
Aes128KeyHandle(Aes128KeyHandle &&) = delete;
void operator=(const Aes128KeyHandle &) = delete;
void operator=(Aes128KeyHandle &&) = delete;
};

/**
* @brief Platform-specific HMAC key handle
*/
class Hmac128BitsKeyHandle : public Symmetric128BitsKeyHandle
class Hmac128KeyHandle final : public Symmetric128BitsKeyHandle
{
public:
Hmac128BitsKeyHandle() = default;
virtual ~Hmac128BitsKeyHandle() {}
Hmac128KeyHandle() = default;

Hmac128BitsKeyHandle(const Hmac128BitsKeyHandle &) = delete;
Hmac128BitsKeyHandle(Hmac128BitsKeyHandle &&) = delete;
void operator=(const Hmac128BitsKeyHandle &) = delete;
void operator=(Hmac128BitsKeyHandle &&) = delete;
Hmac128KeyHandle(const Hmac128KeyHandle &) = delete;
Hmac128KeyHandle(Hmac128KeyHandle &&) = delete;
void operator=(const Hmac128KeyHandle &) = delete;
void operator=(Hmac128KeyHandle &&) = delete;
};

/**
Expand Down Expand Up @@ -732,7 +730,7 @@ CHIP_ERROR ConvertIntegerRawToDerWithoutTag(const ByteSpan & raw_integer, Mutabl
* @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
* */
CHIP_ERROR AES_CCM_encrypt(const uint8_t * plaintext, size_t plaintext_length, const uint8_t * aad, size_t aad_length,
const Aes128BitsKeyHandle & key, const uint8_t * nonce, size_t nonce_length, uint8_t * ciphertext,
const Aes128KeyHandle & key, const uint8_t * nonce, size_t nonce_length, uint8_t * ciphertext,
uint8_t * tag, size_t tag_length);

/**
Expand All @@ -756,7 +754,7 @@ CHIP_ERROR AES_CCM_encrypt(const uint8_t * plaintext, size_t plaintext_length, c
* @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
**/
CHIP_ERROR AES_CCM_decrypt(const uint8_t * ciphertext, size_t ciphertext_length, const uint8_t * aad, size_t aad_length,
const uint8_t * tag, size_t tag_length, const Aes128BitsKeyHandle & key, const uint8_t * nonce,
const uint8_t * tag, size_t tag_length, const Aes128KeyHandle & key, const uint8_t * nonce,
size_t nonce_length, uint8_t * plaintext);

/**
Expand All @@ -775,7 +773,7 @@ CHIP_ERROR AES_CCM_decrypt(const uint8_t * ciphertext, size_t ciphertext_length,
* @param output Buffer to write output into
* @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
**/
CHIP_ERROR AES_CTR_crypt(const uint8_t * input, size_t input_length, const Aes128BitsKeyHandle & key, const uint8_t * nonce,
CHIP_ERROR AES_CTR_crypt(const uint8_t * input, size_t input_length, const Aes128KeyHandle & key, const uint8_t * nonce,
size_t nonce_length, uint8_t * output);

/**
Expand Down Expand Up @@ -982,6 +980,31 @@ class HMAC_sha

virtual CHIP_ERROR HMAC_SHA256(const uint8_t * key, size_t key_length, const uint8_t * message, size_t message_length,
uint8_t * out_buffer, size_t out_length);

/**
* @brief A function that implements SHA-256 based HMAC per FIPS1981.
*
* This implements the CHIP_Crypto_HMAC() cryptographic primitive
* in the the specification.
*
* The `out_length` must be at least kSHA256_Hash_Length, and only
* kSHA256_Hash_Length bytes are written to out_buffer.
*
* Error values are:
* - CHIP_ERROR_INVALID_ARGUMENT: for any bad arguments or nullptr input on
* any pointer.
* - CHIP_ERROR_INTERNAL: for any unexpected error arising in the underlying
* cryptographic layers.
*
* @param key The HMAC Key handle to use for the HMAC operation
* @param message Message over which to compute the HMAC
* @param message_length Length of the message over which to compute the HMAC
* @param out_buffer Pointer to buffer into which to write the output.
* @param out_length Underlying size of the `out_buffer`.
* @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
**/
virtual CHIP_ERROR HMAC_SHA256(const Hmac128KeyHandle & key, const uint8_t * message, size_t message_length,
uint8_t * out_buffer, size_t out_length);
};

/**
Expand Down
11 changes: 9 additions & 2 deletions src/crypto/CHIPCryptoPALOpenSSL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ static int _compareDaysAndSeconds(const int days, const int seconds)
}

CHIP_ERROR AES_CCM_encrypt(const uint8_t * plaintext, size_t plaintext_length, const uint8_t * aad, size_t aad_length,
const Aes128BitsKeyHandle & key, const uint8_t * nonce, size_t nonce_length, uint8_t * ciphertext,
const Aes128KeyHandle & key, const uint8_t * nonce, size_t nonce_length, uint8_t * ciphertext,
uint8_t * tag, size_t tag_length)
{
#if CHIP_CRYPTO_BORINGSSL
Expand Down Expand Up @@ -282,7 +282,7 @@ CHIP_ERROR AES_CCM_encrypt(const uint8_t * plaintext, size_t plaintext_length, c
}

CHIP_ERROR AES_CCM_decrypt(const uint8_t * ciphertext, size_t ciphertext_length, const uint8_t * aad, size_t aad_length,
const uint8_t * tag, size_t tag_length, const Aes128BitsKeyHandle & key, const uint8_t * nonce,
const uint8_t * tag, size_t tag_length, const Aes128KeyHandle & key, const uint8_t * nonce,
size_t nonce_length, uint8_t * plaintext)
{
#if CHIP_CRYPTO_BORINGSSL
Expand Down Expand Up @@ -598,6 +598,13 @@ CHIP_ERROR HMAC_sha::HMAC_SHA256(const uint8_t * key, size_t key_length, const u
return error;
}

CHIP_ERROR HMAC_sha::HMAC_SHA256(const Hmac128KeyHandle & key, const uint8_t * message, size_t message_length, uint8_t * out_buffer,
size_t out_length)
{
return HMAC_SHA256(key.As<Symmetric128BitsKeyByteArray>(), sizeof(Symmetric128BitsKeyByteArray), message, message_length,
out_buffer, out_length);
}

CHIP_ERROR PBKDF2_sha256::pbkdf2_sha256(const uint8_t * password, size_t plen, const uint8_t * salt, size_t slen,
unsigned int iteration_count, uint32_t key_length, uint8_t * output)
{
Expand Down
19 changes: 17 additions & 2 deletions src/crypto/CHIPCryptoPALPSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ bool isValidTag(const uint8_t * tag, size_t tag_length)
} // namespace

CHIP_ERROR AES_CCM_encrypt(const uint8_t * plaintext, size_t plaintext_length, const uint8_t * aad, size_t aad_length,
const Aes128BitsKeyHandle & key, const uint8_t * nonce, size_t nonce_length, uint8_t * ciphertext,
const Aes128KeyHandle & key, const uint8_t * nonce, size_t nonce_length, uint8_t * ciphertext,
uint8_t * tag, size_t tag_length)
{
VerifyOrReturnError(isBufferNonEmpty(nonce, nonce_length), CHIP_ERROR_INVALID_ARGUMENT);
Expand Down Expand Up @@ -123,7 +123,7 @@ CHIP_ERROR AES_CCM_encrypt(const uint8_t * plaintext, size_t plaintext_length, c
}

CHIP_ERROR AES_CCM_decrypt(const uint8_t * ciphertext, size_t ciphertext_length, const uint8_t * aad, size_t aad_length,
const uint8_t * tag, size_t tag_length, const Aes128BitsKeyHandle & key, const uint8_t * nonce,
const uint8_t * tag, size_t tag_length, const Aes128KeyHandle & key, const uint8_t * nonce,
size_t nonce_length, uint8_t * plaintext)
{
VerifyOrReturnError(isBufferNonEmpty(nonce, nonce_length), CHIP_ERROR_INVALID_ARGUMENT);
Expand Down Expand Up @@ -364,6 +364,21 @@ CHIP_ERROR HMAC_sha::HMAC_SHA256(const uint8_t * key, size_t key_length, const u
return CHIP_NO_ERROR;
}

CHIP_ERROR HMAC_sha::HMAC_SHA256(const Hmac128KeyHandle & key, const uint8_t * message, size_t message_length, uint8_t * out_buffer,
size_t out_length)
{
VerifyOrReturnError(isBufferNonEmpty(message, message_length), CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(out_buffer != nullptr && out_length == PSA_HASH_LENGTH(PSA_ALG_SHA_256), CHIP_ERROR_INVALID_ARGUMENT);

const psa_algorithm_t algorithm = PSA_ALG_HMAC(PSA_ALG_SHA_256);
psa_status_t status = PSA_SUCCESS;

status = psa_mac_compute(key.As<psa_key_id_t>(), algorithm, message, message_length, out_buffer, out_length, &out_length);
mkardous-silabs marked this conversation as resolved.
Show resolved Hide resolved
VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);

return CHIP_NO_ERROR;
}

CHIP_ERROR PBKDF2_sha256::pbkdf2_sha256(const uint8_t * pass, size_t pass_length, const uint8_t * salt, size_t salt_length,
unsigned int iteration_count, uint32_t key_length, uint8_t * key)
{
Expand Down
11 changes: 9 additions & 2 deletions src/crypto/CHIPCryptoPALmbedTLS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ static bool _isValidTagLength(size_t tag_length)
}

CHIP_ERROR AES_CCM_encrypt(const uint8_t * plaintext, size_t plaintext_length, const uint8_t * aad, size_t aad_length,
const Aes128BitsKeyHandle & key, const uint8_t * nonce, size_t nonce_length, uint8_t * ciphertext,
const Aes128KeyHandle & key, const uint8_t * nonce, size_t nonce_length, uint8_t * ciphertext,
uint8_t * tag, size_t tag_length)
{
CHIP_ERROR error = CHIP_NO_ERROR;
Expand Down Expand Up @@ -113,7 +113,7 @@ CHIP_ERROR AES_CCM_encrypt(const uint8_t * plaintext, size_t plaintext_length, c
}

CHIP_ERROR AES_CCM_decrypt(const uint8_t * ciphertext, size_t ciphertext_len, const uint8_t * aad, size_t aad_len,
const uint8_t * tag, size_t tag_length, const Aes128BitsKeyHandle & key, const uint8_t * nonce,
const uint8_t * tag, size_t tag_length, const Aes128KeyHandle & key, const uint8_t * nonce,
size_t nonce_length, uint8_t * plaintext)
{
CHIP_ERROR error = CHIP_NO_ERROR;
Expand Down Expand Up @@ -325,6 +325,13 @@ CHIP_ERROR HMAC_sha::HMAC_SHA256(const uint8_t * key, size_t key_length, const u
return CHIP_NO_ERROR;
}

CHIP_ERROR HMAC_sha::HMAC_SHA256(const Hmac128KeyHandle & key, const uint8_t * message, size_t message_length, uint8_t * out_buffer,
size_t out_length)
{
return HMAC_SHA256(key.As<Symmetric128BitsKeyByteArray>(), sizeof(Symmetric128BitsKeyByteArray), message, message_length,
out_buffer, out_length);
}

CHIP_ERROR PBKDF2_sha256::pbkdf2_sha256(const uint8_t * password, size_t plen, const uint8_t * salt, size_t slen,
unsigned int iteration_count, uint32_t key_length, uint8_t * output)
{
Expand Down
10 changes: 5 additions & 5 deletions src/crypto/PSASessionKeystore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class HmacKeyAttributes
HmacKeyAttributes()
{
psa_set_key_type(&mAttrs, PSA_KEY_TYPE_HMAC);
psa_set_key_algorithm(&mAttrs, PSA_ALG_HMAC(PSA_ALG_ANY_HASH));
psa_set_key_algorithm(&mAttrs, PSA_ALG_HMAC(PSA_ALG_SHA_256));
psa_set_key_usage_flags(&mAttrs, PSA_KEY_USAGE_SIGN_MESSAGE);
psa_set_key_bits(&mAttrs, CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES * 8);
}
Expand All @@ -68,7 +68,7 @@ class HmacKeyAttributes

} // namespace

CHIP_ERROR PSASessionKeystore::CreateKey(const Symmetric128BitsKeyByteArray & keyMaterial, Aes128BitsKeyHandle & key)
CHIP_ERROR PSASessionKeystore::CreateKey(const Symmetric128BitsKeyByteArray & keyMaterial, Aes128KeyHandle & key)
{
// Destroy the old key if already allocated
psa_destroy_key(key.As<psa_key_id_t>());
Expand All @@ -81,7 +81,7 @@ CHIP_ERROR PSASessionKeystore::CreateKey(const Symmetric128BitsKeyByteArray & ke
return CHIP_NO_ERROR;
}

CHIP_ERROR PSASessionKeystore::CreateKey(const Symmetric128BitsKeyByteArray & keyMaterial, Hmac128BitsKeyHandle & key)
CHIP_ERROR PSASessionKeystore::CreateKey(const Symmetric128BitsKeyByteArray & keyMaterial, Hmac128KeyHandle & key)
{
// Destroy the old key if already allocated
psa_destroy_key(key.As<psa_key_id_t>());
Expand All @@ -96,7 +96,7 @@ CHIP_ERROR PSASessionKeystore::CreateKey(const Symmetric128BitsKeyByteArray & ke
}

CHIP_ERROR PSASessionKeystore::DeriveKey(const P256ECDHDerivedSecret & secret, const ByteSpan & salt, const ByteSpan & info,
Aes128BitsKeyHandle & key)
Aes128KeyHandle & key)
{
PsaKdf kdf;
ReturnErrorOnFailure(kdf.Init(PSA_ALG_HKDF(PSA_ALG_SHA_256), secret.Span(), salt, info));
Expand All @@ -107,7 +107,7 @@ CHIP_ERROR PSASessionKeystore::DeriveKey(const P256ECDHDerivedSecret & secret, c
}

CHIP_ERROR PSASessionKeystore::DeriveSessionKeys(const ByteSpan & secret, const ByteSpan & salt, const ByteSpan & info,
Aes128BitsKeyHandle & i2rKey, Aes128BitsKeyHandle & r2iKey,
Aes128KeyHandle & i2rKey, Aes128KeyHandle & r2iKey,
AttestationChallenge & attestationChallenge)
{
PsaKdf kdf;
Expand Down
11 changes: 5 additions & 6 deletions src/crypto/PSASessionKeystore.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,12 @@ namespace Crypto {
class PSASessionKeystore : public SessionKeystore
{
public:
CHIP_ERROR CreateKey(const Symmetric128BitsKeyByteArray & keyMaterial, Aes128BitsKeyHandle & key) override;
CHIP_ERROR CreateKey(const Symmetric128BitsKeyByteArray & keyMaterial, Hmac128BitsKeyHandle & key) override;
CHIP_ERROR CreateKey(const Symmetric128BitsKeyByteArray & keyMaterial, Aes128KeyHandle & key) override;
CHIP_ERROR CreateKey(const Symmetric128BitsKeyByteArray & keyMaterial, Hmac128KeyHandle & key) override;
CHIP_ERROR DeriveKey(const P256ECDHDerivedSecret & secret, const ByteSpan & salt, const ByteSpan & info,
Aes128BitsKeyHandle & key) override;
CHIP_ERROR DeriveSessionKeys(const ByteSpan & secret, const ByteSpan & salt, const ByteSpan & info,
Aes128BitsKeyHandle & i2rKey, Aes128BitsKeyHandle & r2iKey,
AttestationChallenge & attestationChallenge) override;
Aes128KeyHandle & key) override;
CHIP_ERROR DeriveSessionKeys(const ByteSpan & secret, const ByteSpan & salt, const ByteSpan & info, Aes128KeyHandle & i2rKey,
Aes128KeyHandle & r2iKey, AttestationChallenge & attestationChallenge) override;
void DestroyKey(Symmetric128BitsKeyHandle & key) override;
};

Expand Down
Loading
Loading