[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.
This commit is contained in:
Abtin Keshavarzian
2020-12-12 11:09:54 -08:00
committed by GitHub
parent 89cc2ef432
commit 6b48c74787
14 changed files with 106 additions and 63 deletions
+25 -7
View File
@@ -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. * This function performs HMAC computation.
@@ -63,14 +81,14 @@ extern "C" {
* @param[in] aKeyLength The key length in bytes. * @param[in] aKeyLength The key length in bytes.
* @param[in] aBuf A pointer to the input buffer. * @param[in] aBuf A pointer to the input buffer.
* @param[in] aBufLength The length of @p aBuf in bytes. * @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, void otCryptoHmacSha256(const uint8_t * aKey,
uint16_t aKeyLength, uint16_t aKeyLength,
const uint8_t *aBuf, const uint8_t * aBuf,
uint16_t aBufLength, uint16_t aBufLength,
uint8_t * aHash); otCryptoSha256Hash *aHash);
/** /**
* This method performs AES CCM computation. * This method performs AES CCM computation.
+1 -1
View File
@@ -53,7 +53,7 @@ extern "C" {
* @note This number versions both OpenThread platform and user APIs. * @note This number versions both OpenThread platform and user APIs.
* *
*/ */
#define OPENTHREAD_API_VERSION (55) #define OPENTHREAD_API_VERSION (56)
/** /**
* @addtogroup api-instance * @addtogroup api-instance
+6 -6
View File
@@ -44,11 +44,11 @@
using namespace ot::Crypto; using namespace ot::Crypto;
void otCryptoHmacSha256(const uint8_t *aKey, void otCryptoHmacSha256(const uint8_t * aKey,
uint16_t aKeyLength, uint16_t aKeyLength,
const uint8_t *aBuf, const uint8_t * aBuf,
uint16_t aBufLength, uint16_t aBufLength,
uint8_t * aHash) otCryptoSha256Hash *aHash)
{ {
HmacSha256 hmac; HmacSha256 hmac;
@@ -56,7 +56,7 @@ void otCryptoHmacSha256(const uint8_t *aKey,
hmac.Start(aKey, aKeyLength); hmac.Start(aKey, aKeyLength);
hmac.Update(aBuf, aBufLength); hmac.Update(aBuf, aBufLength);
hmac.Finish(aHash); hmac.Finish(*static_cast<HmacSha256::Hash *>(aHash));
} }
void otCryptoAesCcm(const uint8_t *aKey, void otCryptoAesCcm(const uint8_t *aKey,
+7 -7
View File
@@ -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) void HkdfSha256::Expand(const uint8_t *aInfo, uint16_t aInfoLength, uint8_t *aOutputKey, uint16_t aOutputKeyLength)
{ {
HmacSha256 hmac; HmacSha256 hmac;
uint8_t hash[kHashSize]; HmacSha256::Hash hash;
uint8_t iter = 0; uint8_t iter = 0;
uint16_t copyLength; uint16_t copyLength;
// The aOutputKey is calculated as follows [RFC5889]: // 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) while (aOutputKeyLength > 0)
{ {
hmac.Start(mPrk, sizeof(mPrk)); hmac.Start(mPrk.GetBytes(), sizeof(mPrk));
if (iter != 0) if (iter != 0)
{ {
hmac.Update(hash, sizeof(hash)); hmac.Update(hash.GetBytes(), sizeof(hash));
} }
hmac.Update(aInfo, aInfoLength); 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; copyLength = (aOutputKeyLength > sizeof(hash)) ? sizeof(hash) : aOutputKeyLength;
memcpy(aOutputKey, hash, copyLength); memcpy(aOutputKey, hash.GetBytes(), copyLength);
aOutputKey += copyLength; aOutputKey += copyLength;
aOutputKeyLength -= copyLength; aOutputKeyLength -= copyLength;
} }
+2 -7
View File
@@ -37,7 +37,7 @@
#include "openthread-core-config.h" #include "openthread-core-config.h"
#include "hmac_sha256.hpp" #include "crypto/hmac_sha256.hpp"
namespace ot { namespace ot {
namespace Crypto { namespace Crypto {
@@ -84,12 +84,7 @@ public:
void Expand(const uint8_t *aInfo, uint16_t aInfoLength, uint8_t *aOutputKey, uint16_t aOutputKeyLength); void Expand(const uint8_t *aInfo, uint16_t aInfoLength, uint8_t *aOutputKey, uint16_t aOutputKeyLength);
private: private:
enum HmacSha256::Hash mPrk; // Pseudo-Random Key (derived from Extract step).
{
kHashSize = HmacSha256::kHashSize,
};
uint8_t mPrk[kHashSize]; // Pseudo-Random Key (derived from Extract step).
}; };
/** /**
+2 -2
View File
@@ -59,9 +59,9 @@ void HmacSha256::Update(const uint8_t *aBuf, uint16_t aBufLength)
mbedtls_md_hmac_update(&mContext, aBuf, 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 } // namespace Crypto
+9 -6
View File
@@ -40,6 +40,8 @@
#include <mbedtls/md.h> #include <mbedtls/md.h>
#include "crypto/sha256.hpp"
namespace ot { namespace ot {
namespace Crypto { namespace Crypto {
@@ -57,10 +59,11 @@ namespace Crypto {
class HmacSha256 class HmacSha256
{ {
public: public:
enum /**
{ * This type represents a HMAC SHA-256 hash.
kHashSize = 32, ///< SHA-256 hash size (bytes) *
}; */
typedef Sha256::Hash Hash;
/** /**
* Constructor for initialization of mbedtls_md_context_t. * Constructor for initialization of mbedtls_md_context_t.
@@ -95,10 +98,10 @@ public:
/** /**
* This method finalizes the hash computation. * 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: private:
mbedtls_md_context_t mContext; mbedtls_md_context_t mContext;
+2 -2
View File
@@ -56,9 +56,9 @@ void Sha256::Update(const uint8_t *aBuf, uint16_t aBufLength)
mbedtls_sha256_update_ret(&mContext, aBuf, 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 } // namespace Crypto
+28 -2
View File
@@ -40,6 +40,11 @@
#include <mbedtls/sha256.h> #include <mbedtls/sha256.h>
#include <openthread/crypto.h>
#include "common/clearable.hpp"
#include "common/equatable.hpp"
namespace ot { namespace ot {
namespace Crypto { namespace Crypto {
@@ -57,6 +62,27 @@ namespace Crypto {
class Sha256 class Sha256
{ {
public: public:
/**
* This type represents a SHA-256 hash.
*
*/
class Hash : public otCryptoSha256Hash, public Clearable<Hash>, public Equatable<Hash>
{
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 enum
{ {
kHashSize = 32, ///< SHA-256 hash size (bytes) kHashSize = 32, ///< SHA-256 hash size (bytes)
@@ -92,10 +118,10 @@ public:
/** /**
* This method finalizes the hash computation. * 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: private:
mbedtls_sha256_context mContext; mbedtls_sha256_context mContext;
+3 -3
View File
@@ -727,14 +727,14 @@ int Dtls::HandleMbedtlsExportKeys(const unsigned char *aMasterSecret,
{ {
OT_UNUSED_VARIABLE(aMasterSecret); OT_UNUSED_VARIABLE(aMasterSecret);
uint8_t kek[Crypto::Sha256::kHashSize]; Crypto::Sha256::Hash kek;
Crypto::Sha256 sha256; Crypto::Sha256 sha256;
sha256.Start(); sha256.Start();
sha256.Update(aKeyBlock, 2 * static_cast<uint16_t>(aMacLength + aKeyLength + aIvLength)); sha256.Update(aKeyBlock, 2 * static_cast<uint16_t>(aMacLength + aKeyLength + aIvLength));
sha256.Finish(kek); sha256.Finish(kek);
Get<KeyManager>().SetKek(kek); Get<KeyManager>().SetKek(kek.GetBytes());
if (mCipherSuites[0] == MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8) if (mCipherSuites[0] == MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8)
{ {
+3 -3
View File
@@ -287,14 +287,14 @@ bool SteeringData::DoesAllMatch(uint8_t aMatch) const
void ComputeJoinerId(const Mac::ExtAddress &aEui64, Mac::ExtAddress &aJoinerId) void ComputeJoinerId(const Mac::ExtAddress &aEui64, Mac::ExtAddress &aJoinerId)
{ {
Crypto::Sha256 sha256; Crypto::Sha256 sha256;
uint8_t hash[Crypto::Sha256::kHashSize]; Crypto::Sha256::Hash hash;
sha256.Start(); sha256.Start();
sha256.Update(aEui64.m8, sizeof(aEui64)); sha256.Update(aEui64.m8, sizeof(aEui64));
sha256.Finish(hash); sha256.Finish(hash);
memcpy(&aJoinerId, hash, sizeof(aJoinerId)); memcpy(&aJoinerId, hash.GetBytes(), sizeof(aJoinerId));
aJoinerId.SetLocal(true); aJoinerId.SetLocal(true);
} }
+2 -2
View File
@@ -517,8 +517,8 @@ private:
union HashKeys union HashKeys
{ {
uint8_t mHash[Crypto::HmacSha256::kHashSize]; Crypto::HmacSha256::Hash mHash;
Keys mKeys; Keys mKeys;
}; };
void ComputeKeys(uint32_t aKeySequence, HashKeys &aHashKeys); void ComputeKeys(uint32_t aKeySequence, HashKeys &aHashKeys);
+7 -7
View File
@@ -272,12 +272,12 @@ otError Slaac::GenerateIid(Ip6::NetifUnicastAddress &aAddress,
* *
*/ */
otError error = OT_ERROR_FAILED; otError error = OT_ERROR_FAILED;
const uint8_t netIface[] = {'w', 'p', 'a', 'n'}; const uint8_t netIface[] = {'w', 'p', 'a', 'n'};
uint8_t dadCounter = aDadCounter ? *aDadCounter : 0; uint8_t dadCounter = aDadCounter ? *aDadCounter : 0;
IidSecretKey secretKey; IidSecretKey secretKey;
Crypto::Sha256 sha256; Crypto::Sha256 sha256;
uint8_t hash[Crypto::Sha256::kHashSize]; Crypto::Sha256::Hash hash;
static_assert(sizeof(hash) >= Ip6::InterfaceIdentifier::kSize, static_assert(sizeof(hash) >= Ip6::InterfaceIdentifier::kSize,
"SHA-256 hash size is too small to use as IPv6 address IID"); "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.Update(secretKey.m8, sizeof(IidSecretKey));
sha256.Finish(hash); 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 the IID is reserved, try again with a new dadCounter
if (aAddress.GetAddress().GetIid().IsReserved()) if (aAddress.GetAddress().GetIid().IsReserved())
+9 -8
View File
@@ -38,17 +38,17 @@ void TestHmacSha256(void)
{ {
static const struct static const struct
{ {
const char *key; const char * key;
const char *data; const char * data;
uint8_t hash[ot::Crypto::HmacSha256::kHashSize]; otCryptoSha256Hash hash;
} tests[] = { } tests[] = {
{ {
"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
"Hi There", "Hi There",
{ {{
0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b, 0xf1, 0x2b, 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, 0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7,
}, }},
}, },
{ {
nullptr, nullptr,
@@ -61,8 +61,8 @@ void TestHmacSha256(void)
// Make sure hmac is destructed before freeing instance. // Make sure hmac is destructed before freeing instance.
{ {
ot::Crypto::HmacSha256 hmac; ot::Crypto::HmacSha256 hmac;
uint8_t hash[ot::Crypto::HmacSha256::kHashSize]; ot::Crypto::HmacSha256::Hash hash;
VerifyOrQuit(instance != nullptr, "Null OpenThread instance"); VerifyOrQuit(instance != nullptr, "Null OpenThread instance");
@@ -72,7 +72,8 @@ void TestHmacSha256(void)
hmac.Update(reinterpret_cast<const uint8_t *>(tests[i].data), static_cast<uint16_t>(strlen(tests[i].data))); hmac.Update(reinterpret_cast<const uint8_t *>(tests[i].data), static_cast<uint16_t>(strlen(tests[i].data)));
hmac.Finish(hash); hmac.Finish(hash);
VerifyOrQuit(memcmp(hash, tests[i].hash, sizeof(tests[i].hash)) == 0, "HMAC-SHA-256 failed"); VerifyOrQuit(hash == static_cast<const ot::Crypto::HmacSha256::Hash &>(tests[i].hash),
"HMAC-SHA-256 failed");
} }
} }