ESPHome 2026.1.0-dev
Loading...
Searching...
No Matches
hmac_sha256.cpp
Go to the documentation of this file.
1#include <cstdio>
2#include <cstring>
3#include "hmac_sha256.h"
4#if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040) || defined(USE_LIBRETINY) || defined(USE_HOST)
6
8
9constexpr size_t SHA256_DIGEST_SIZE = 32;
10
11#if defined(USE_ESP32) || defined(USE_LIBRETINY)
12
13HmacSHA256::~HmacSHA256() { mbedtls_md_free(&this->ctx_); }
14
15void HmacSHA256::init(const uint8_t *key, size_t len) {
16 mbedtls_md_init(&this->ctx_);
17 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
18 mbedtls_md_setup(&this->ctx_, md_info, 1); // 1 = HMAC mode
19 mbedtls_md_hmac_starts(&this->ctx_, key, len);
20}
21
22void HmacSHA256::add(const uint8_t *data, size_t len) { mbedtls_md_hmac_update(&this->ctx_, data, len); }
23
24void HmacSHA256::calculate() { mbedtls_md_hmac_finish(&this->ctx_, this->digest_); }
25
26void HmacSHA256::get_bytes(uint8_t *output) { memcpy(output, this->digest_, SHA256_DIGEST_SIZE); }
27
28void HmacSHA256::get_hex(char *output) {
29 for (size_t i = 0; i < SHA256_DIGEST_SIZE; i++) {
30 sprintf(output + (i * 2), "%02x", this->digest_[i]);
31 }
32}
33
34bool HmacSHA256::equals_bytes(const uint8_t *expected) {
35 return memcmp(this->digest_, expected, SHA256_DIGEST_SIZE) == 0;
36}
37
38bool HmacSHA256::equals_hex(const char *expected) {
39 char hex_output[SHA256_DIGEST_SIZE * 2 + 1];
40 this->get_hex(hex_output);
41 hex_output[SHA256_DIGEST_SIZE * 2] = '\0';
42 return strncmp(hex_output, expected, SHA256_DIGEST_SIZE * 2) == 0;
43}
44
45#else
46
47HmacSHA256::~HmacSHA256() = default;
48
49// HMAC block size for SHA256 (RFC 2104)
50constexpr size_t HMAC_BLOCK_SIZE = 64;
51
52void HmacSHA256::init(const uint8_t *key, size_t len) {
53 uint8_t ipad[HMAC_BLOCK_SIZE], opad[HMAC_BLOCK_SIZE];
54
55 memset(ipad, 0, sizeof(ipad));
56 if (len > HMAC_BLOCK_SIZE) {
57 sha256::SHA256 keysha256;
58 keysha256.init();
59 keysha256.add(key, len);
60 keysha256.calculate();
61 keysha256.get_bytes(ipad);
62 } else {
63 memcpy(ipad, key, len);
64 }
65 memcpy(opad, ipad, sizeof(opad));
66
67 for (size_t i = 0; i < HMAC_BLOCK_SIZE; i++) {
68 ipad[i] ^= 0x36;
69 opad[i] ^= 0x5c;
70 }
71
72 this->ihash_.init();
73 this->ihash_.add(ipad, sizeof(ipad));
74
75 this->ohash_.init();
76 this->ohash_.add(opad, sizeof(opad));
77}
78
79void HmacSHA256::add(const uint8_t *data, size_t len) { this->ihash_.add(data, len); }
80
82 uint8_t ibytes[32];
83
84 this->ihash_.calculate();
85 this->ihash_.get_bytes(ibytes);
86
87 this->ohash_.add(ibytes, sizeof(ibytes));
88 this->ohash_.calculate();
89}
90
91void HmacSHA256::get_bytes(uint8_t *output) { this->ohash_.get_bytes(output); }
92
93void HmacSHA256::get_hex(char *output) { this->ohash_.get_hex(output); }
94
95bool HmacSHA256::equals_bytes(const uint8_t *expected) { return this->ohash_.equals_bytes(expected); }
96
97bool HmacSHA256::equals_hex(const char *expected) { return this->ohash_.equals_hex(expected); }
98
99#endif // USE_ESP32 || USE_LIBRETINY
100
101} // namespace esphome::hmac_sha256
102#endif
void get_hex(char *output)
Retrieve the hash as hex characters.
Definition hash_base.h:29
bool equals_hex(const char *expected)
Compare the hash against a provided hex-encoded hash.
Definition hash_base.h:41
bool equals_bytes(const uint8_t *expected)
Compare the hash against a provided byte-encoded hash.
Definition hash_base.h:38
void get_bytes(uint8_t *output)
Retrieve the hash as bytes.
Definition hash_base.h:26
bool equals_bytes(const uint8_t *expected)
Compare the digest against a provided byte-encoded digest (32 bytes).
mbedtls_md_context_t ctx_
Definition hmac_sha256.h:50
uint8_t digest_[SHA256_DIGEST_SIZE]
Definition hmac_sha256.h:51
static constexpr size_t SHA256_DIGEST_SIZE
Definition hmac_sha256.h:49
bool equals_hex(const char *expected)
Compare the digest against a provided hex-encoded digest (64 bytes).
void add(const uint8_t *data, size_t len)
Add bytes of data for the digest.
void get_hex(char *output)
Retrieve the HMAC-SHA256 digest as hex characters.
void get_bytes(uint8_t *output)
Retrieve the HMAC-SHA256 digest as bytes.
void calculate()
Compute the digest, based on the provided data.
void init(const uint8_t *key, size_t len)
Initialize a new HMAC-SHA256 digest computation.
void calculate() override
Definition sha256.cpp:55
void add(const uint8_t *data, size_t len) override
Definition sha256.cpp:53
void init() override
Definition sha256.cpp:48
constexpr size_t SHA256_DIGEST_SIZE
constexpr size_t HMAC_BLOCK_SIZE
std::string size_t len
Definition helpers.h:533