From 6b48c74787f3537f84f03bdeb2b9dd71e124f940 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Sat, 12 Dec 2020 11:09:54 -0800 Subject: [PATCH] [crypto] add 'Sha256::Hash' type (#5946) This commit adds new public type 'otCryptoSha256Hash' and its internal mirror `Sha256::Hash` type which represent a SHA-256 hash value. --- include/openthread/crypto.h | 32 +++++++++++++++++++++++++------- include/openthread/instance.h | 2 +- src/core/api/crypto_api.cpp | 12 ++++++------ src/core/crypto/hkdf_sha256.cpp | 14 +++++++------- src/core/crypto/hkdf_sha256.hpp | 9 ++------- src/core/crypto/hmac_sha256.cpp | 4 ++-- src/core/crypto/hmac_sha256.hpp | 15 +++++++++------ src/core/crypto/sha256.cpp | 4 ++-- src/core/crypto/sha256.hpp | 30 ++++++++++++++++++++++++++++-- src/core/meshcop/dtls.cpp | 6 +++--- src/core/meshcop/meshcop.cpp | 6 +++--- src/core/thread/key_manager.hpp | 4 ++-- src/core/utils/slaac_address.cpp | 14 +++++++------- tests/unit/test_hmac_sha256.cpp | 17 +++++++++-------- 14 files changed, 106 insertions(+), 63 deletions(-) diff --git a/include/openthread/crypto.h b/include/openthread/crypto.h index 0cf22e864..a1353991f 100644 --- a/include/openthread/crypto.h +++ b/include/openthread/crypto.h @@ -54,7 +54,25 @@ extern "C" { * */ -#define OT_CRYPTO_HMAC_SHA_HASH_SIZE 32 ///< Length of HMAC SHA (in bytes). +#define OT_CRYPTO_SHA256_HASH_SIZE 32 ///< Length of SHA256 hash (in bytes). + +/** + * @struct otCryptoSha256Hash + * + * This structure represents a SHA-256 hash. + * + */ +OT_TOOL_PACKED_BEGIN +struct otCryptoSha256Hash +{ + uint8_t m8[OT_CRYPTO_SHA256_HASH_SIZE]; ///< Hash bytes. +} OT_TOOL_PACKED_END; + +/** + * This structure represents a SHA-256 hash. + * + */ +typedef struct otCryptoSha256Hash otCryptoSha256Hash; /** * This function performs HMAC computation. @@ -63,14 +81,14 @@ extern "C" { * @param[in] aKeyLength The key length in bytes. * @param[in] aBuf A pointer to the input buffer. * @param[in] aBufLength The length of @p aBuf in bytes. - * @param[out] aHash A pointer to the output hash buffer. + * @param[out] aHash A pointer to a `otCryptoSha256Hash` structure to output the hash value. * */ -void otCryptoHmacSha256(const uint8_t *aKey, - uint16_t aKeyLength, - const uint8_t *aBuf, - uint16_t aBufLength, - uint8_t * aHash); +void otCryptoHmacSha256(const uint8_t * aKey, + uint16_t aKeyLength, + const uint8_t * aBuf, + uint16_t aBufLength, + otCryptoSha256Hash *aHash); /** * This method performs AES CCM computation. diff --git a/include/openthread/instance.h b/include/openthread/instance.h index 6de9df68c..b4fa5d26b 100644 --- a/include/openthread/instance.h +++ b/include/openthread/instance.h @@ -53,7 +53,7 @@ extern "C" { * @note This number versions both OpenThread platform and user APIs. * */ -#define OPENTHREAD_API_VERSION (55) +#define OPENTHREAD_API_VERSION (56) /** * @addtogroup api-instance diff --git a/src/core/api/crypto_api.cpp b/src/core/api/crypto_api.cpp index 9023a4b1c..0f5df3cc3 100644 --- a/src/core/api/crypto_api.cpp +++ b/src/core/api/crypto_api.cpp @@ -44,11 +44,11 @@ using namespace ot::Crypto; -void otCryptoHmacSha256(const uint8_t *aKey, - uint16_t aKeyLength, - const uint8_t *aBuf, - uint16_t aBufLength, - uint8_t * aHash) +void otCryptoHmacSha256(const uint8_t * aKey, + uint16_t aKeyLength, + const uint8_t * aBuf, + uint16_t aBufLength, + otCryptoSha256Hash *aHash) { HmacSha256 hmac; @@ -56,7 +56,7 @@ void otCryptoHmacSha256(const uint8_t *aKey, hmac.Start(aKey, aKeyLength); hmac.Update(aBuf, aBufLength); - hmac.Finish(aHash); + hmac.Finish(*static_cast(aHash)); } void otCryptoAesCcm(const uint8_t *aKey, diff --git a/src/core/crypto/hkdf_sha256.cpp b/src/core/crypto/hkdf_sha256.cpp index 3201fb1de..fd10befdb 100644 --- a/src/core/crypto/hkdf_sha256.cpp +++ b/src/core/crypto/hkdf_sha256.cpp @@ -51,10 +51,10 @@ void HkdfSha256::Extract(const uint8_t *aSalt, uint16_t aSaltLength, const uint8 void HkdfSha256::Expand(const uint8_t *aInfo, uint16_t aInfoLength, uint8_t *aOutputKey, uint16_t aOutputKeyLength) { - HmacSha256 hmac; - uint8_t hash[kHashSize]; - uint8_t iter = 0; - uint16_t copyLength; + HmacSha256 hmac; + HmacSha256::Hash hash; + uint8_t iter = 0; + uint16_t copyLength; // The aOutputKey is calculated as follows [RFC5889]: // @@ -71,11 +71,11 @@ void HkdfSha256::Expand(const uint8_t *aInfo, uint16_t aInfoLength, uint8_t *aOu while (aOutputKeyLength > 0) { - hmac.Start(mPrk, sizeof(mPrk)); + hmac.Start(mPrk.GetBytes(), sizeof(mPrk)); if (iter != 0) { - hmac.Update(hash, sizeof(hash)); + hmac.Update(hash.GetBytes(), sizeof(hash)); } hmac.Update(aInfo, aInfoLength); @@ -86,7 +86,7 @@ void HkdfSha256::Expand(const uint8_t *aInfo, uint16_t aInfoLength, uint8_t *aOu copyLength = (aOutputKeyLength > sizeof(hash)) ? sizeof(hash) : aOutputKeyLength; - memcpy(aOutputKey, hash, copyLength); + memcpy(aOutputKey, hash.GetBytes(), copyLength); aOutputKey += copyLength; aOutputKeyLength -= copyLength; } diff --git a/src/core/crypto/hkdf_sha256.hpp b/src/core/crypto/hkdf_sha256.hpp index 379ef45e0..648ba72f4 100644 --- a/src/core/crypto/hkdf_sha256.hpp +++ b/src/core/crypto/hkdf_sha256.hpp @@ -37,7 +37,7 @@ #include "openthread-core-config.h" -#include "hmac_sha256.hpp" +#include "crypto/hmac_sha256.hpp" namespace ot { namespace Crypto { @@ -84,12 +84,7 @@ public: void Expand(const uint8_t *aInfo, uint16_t aInfoLength, uint8_t *aOutputKey, uint16_t aOutputKeyLength); private: - enum - { - kHashSize = HmacSha256::kHashSize, - }; - - uint8_t mPrk[kHashSize]; // Pseudo-Random Key (derived from Extract step). + HmacSha256::Hash mPrk; // Pseudo-Random Key (derived from Extract step). }; /** diff --git a/src/core/crypto/hmac_sha256.cpp b/src/core/crypto/hmac_sha256.cpp index 0187d996f..e88a6c02f 100644 --- a/src/core/crypto/hmac_sha256.cpp +++ b/src/core/crypto/hmac_sha256.cpp @@ -59,9 +59,9 @@ void HmacSha256::Update(const uint8_t *aBuf, uint16_t aBufLength) mbedtls_md_hmac_update(&mContext, aBuf, aBufLength); } -void HmacSha256::Finish(uint8_t aHash[kHashSize]) +void HmacSha256::Finish(Hash &aHash) { - mbedtls_md_hmac_finish(&mContext, aHash); + mbedtls_md_hmac_finish(&mContext, aHash.m8); } } // namespace Crypto diff --git a/src/core/crypto/hmac_sha256.hpp b/src/core/crypto/hmac_sha256.hpp index ed3a84471..2d0d8d9d1 100644 --- a/src/core/crypto/hmac_sha256.hpp +++ b/src/core/crypto/hmac_sha256.hpp @@ -40,6 +40,8 @@ #include +#include "crypto/sha256.hpp" + namespace ot { namespace Crypto { @@ -57,10 +59,11 @@ namespace Crypto { class HmacSha256 { public: - enum - { - kHashSize = 32, ///< SHA-256 hash size (bytes) - }; + /** + * This type represents a HMAC SHA-256 hash. + * + */ + typedef Sha256::Hash Hash; /** * Constructor for initialization of mbedtls_md_context_t. @@ -95,10 +98,10 @@ public: /** * This method finalizes the hash computation. * - * @param[out] aHash A pointer to the output buffer. + * @param[out] aHash A reference to a `Hash` to output the calculated hash. * */ - void Finish(uint8_t aHash[kHashSize]); + void Finish(Hash &aHash); private: mbedtls_md_context_t mContext; diff --git a/src/core/crypto/sha256.cpp b/src/core/crypto/sha256.cpp index 5715192c7..340fe5548 100644 --- a/src/core/crypto/sha256.cpp +++ b/src/core/crypto/sha256.cpp @@ -56,9 +56,9 @@ void Sha256::Update(const uint8_t *aBuf, uint16_t aBufLength) mbedtls_sha256_update_ret(&mContext, aBuf, aBufLength); } -void Sha256::Finish(uint8_t aHash[kHashSize]) +void Sha256::Finish(Hash &aHash) { - mbedtls_sha256_finish_ret(&mContext, aHash); + mbedtls_sha256_finish_ret(&mContext, aHash.m8); } } // namespace Crypto diff --git a/src/core/crypto/sha256.hpp b/src/core/crypto/sha256.hpp index ab7ed6818..2534d007a 100644 --- a/src/core/crypto/sha256.hpp +++ b/src/core/crypto/sha256.hpp @@ -40,6 +40,11 @@ #include +#include + +#include "common/clearable.hpp" +#include "common/equatable.hpp" + namespace ot { namespace Crypto { @@ -57,6 +62,27 @@ namespace Crypto { class Sha256 { public: + /** + * This type represents a SHA-256 hash. + * + */ + class Hash : public otCryptoSha256Hash, public Clearable, public Equatable + { + public: + enum : uint8_t + { + kSize = OT_CRYPTO_SHA256_HASH_SIZE, ///< SHA-256 hash size (bytes) + }; + + /** + * This method returns a pointer to a byte array containing the hash value. + * + * @returns A pointer to a byte array containing the hash. + * + */ + const uint8_t *GetBytes(void) { return m8; } + }; + enum { kHashSize = 32, ///< SHA-256 hash size (bytes) @@ -92,10 +118,10 @@ public: /** * This method finalizes the hash computation. * - * @param[out] aHash A pointer to the output buffer. + * @param[out] aHash A reference to a `Hash` to output the calculated hash. * */ - void Finish(uint8_t aHash[kHashSize]); + void Finish(Hash &aHash); private: mbedtls_sha256_context mContext; diff --git a/src/core/meshcop/dtls.cpp b/src/core/meshcop/dtls.cpp index 7628bf960..e10096a51 100644 --- a/src/core/meshcop/dtls.cpp +++ b/src/core/meshcop/dtls.cpp @@ -727,14 +727,14 @@ int Dtls::HandleMbedtlsExportKeys(const unsigned char *aMasterSecret, { OT_UNUSED_VARIABLE(aMasterSecret); - uint8_t kek[Crypto::Sha256::kHashSize]; - Crypto::Sha256 sha256; + Crypto::Sha256::Hash kek; + Crypto::Sha256 sha256; sha256.Start(); sha256.Update(aKeyBlock, 2 * static_cast(aMacLength + aKeyLength + aIvLength)); sha256.Finish(kek); - Get().SetKek(kek); + Get().SetKek(kek.GetBytes()); if (mCipherSuites[0] == MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8) { diff --git a/src/core/meshcop/meshcop.cpp b/src/core/meshcop/meshcop.cpp index 1a5e3cd70..24e4c1f71 100644 --- a/src/core/meshcop/meshcop.cpp +++ b/src/core/meshcop/meshcop.cpp @@ -287,14 +287,14 @@ bool SteeringData::DoesAllMatch(uint8_t aMatch) const void ComputeJoinerId(const Mac::ExtAddress &aEui64, Mac::ExtAddress &aJoinerId) { - Crypto::Sha256 sha256; - uint8_t hash[Crypto::Sha256::kHashSize]; + Crypto::Sha256 sha256; + Crypto::Sha256::Hash hash; sha256.Start(); sha256.Update(aEui64.m8, sizeof(aEui64)); sha256.Finish(hash); - memcpy(&aJoinerId, hash, sizeof(aJoinerId)); + memcpy(&aJoinerId, hash.GetBytes(), sizeof(aJoinerId)); aJoinerId.SetLocal(true); } diff --git a/src/core/thread/key_manager.hpp b/src/core/thread/key_manager.hpp index 30ac02750..d73d9c047 100644 --- a/src/core/thread/key_manager.hpp +++ b/src/core/thread/key_manager.hpp @@ -517,8 +517,8 @@ private: union HashKeys { - uint8_t mHash[Crypto::HmacSha256::kHashSize]; - Keys mKeys; + Crypto::HmacSha256::Hash mHash; + Keys mKeys; }; void ComputeKeys(uint32_t aKeySequence, HashKeys &aHashKeys); diff --git a/src/core/utils/slaac_address.cpp b/src/core/utils/slaac_address.cpp index f9229028f..4222c3848 100644 --- a/src/core/utils/slaac_address.cpp +++ b/src/core/utils/slaac_address.cpp @@ -272,12 +272,12 @@ otError Slaac::GenerateIid(Ip6::NetifUnicastAddress &aAddress, * */ - otError error = OT_ERROR_FAILED; - const uint8_t netIface[] = {'w', 'p', 'a', 'n'}; - uint8_t dadCounter = aDadCounter ? *aDadCounter : 0; - IidSecretKey secretKey; - Crypto::Sha256 sha256; - uint8_t hash[Crypto::Sha256::kHashSize]; + otError error = OT_ERROR_FAILED; + const uint8_t netIface[] = {'w', 'p', 'a', 'n'}; + uint8_t dadCounter = aDadCounter ? *aDadCounter : 0; + IidSecretKey secretKey; + Crypto::Sha256 sha256; + Crypto::Sha256::Hash hash; static_assert(sizeof(hash) >= Ip6::InterfaceIdentifier::kSize, "SHA-256 hash size is too small to use as IPv6 address IID"); @@ -299,7 +299,7 @@ otError Slaac::GenerateIid(Ip6::NetifUnicastAddress &aAddress, sha256.Update(secretKey.m8, sizeof(IidSecretKey)); sha256.Finish(hash); - aAddress.GetAddress().GetIid().SetBytes(&hash[0]); + aAddress.GetAddress().GetIid().SetBytes(hash.GetBytes()); // If the IID is reserved, try again with a new dadCounter if (aAddress.GetAddress().GetIid().IsReserved()) diff --git a/tests/unit/test_hmac_sha256.cpp b/tests/unit/test_hmac_sha256.cpp index 056302862..676f966ef 100644 --- a/tests/unit/test_hmac_sha256.cpp +++ b/tests/unit/test_hmac_sha256.cpp @@ -38,17 +38,17 @@ void TestHmacSha256(void) { static const struct { - const char *key; - const char *data; - uint8_t hash[ot::Crypto::HmacSha256::kHashSize]; + const char * key; + const char * data; + otCryptoSha256Hash hash; } tests[] = { { "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", "Hi There", - { + {{ 0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b, 0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7, - }, + }}, }, { nullptr, @@ -61,8 +61,8 @@ void TestHmacSha256(void) // Make sure hmac is destructed before freeing instance. { - ot::Crypto::HmacSha256 hmac; - uint8_t hash[ot::Crypto::HmacSha256::kHashSize]; + ot::Crypto::HmacSha256 hmac; + ot::Crypto::HmacSha256::Hash hash; VerifyOrQuit(instance != nullptr, "Null OpenThread instance"); @@ -72,7 +72,8 @@ void TestHmacSha256(void) hmac.Update(reinterpret_cast(tests[i].data), static_cast(strlen(tests[i].data))); hmac.Finish(hash); - VerifyOrQuit(memcmp(hash, tests[i].hash, sizeof(tests[i].hash)) == 0, "HMAC-SHA-256 failed"); + VerifyOrQuit(hash == static_cast(tests[i].hash), + "HMAC-SHA-256 failed"); } }