mirror of
https://github.com/espressif/openthread.git
synced 2026-09-15 13:40:06 +00:00
[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:
@@ -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.
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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).
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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())
|
||||||
|
|||||||
@@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user