fix: HMAC module — mbedTLS error handling, hex guard, test docs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-13 14:24:48 -07:00
parent 47f3f6afef
commit 7662fc4c25
2 changed files with 18 additions and 5 deletions

View File

@@ -15,28 +15,33 @@ static HString bytes_to_hex(const uint8_t* bytes, size_t len) {
} }
static void hex_to_bytes(const HString& hex, uint8_t* out, size_t out_len) { static void hex_to_bytes(const HString& hex, uint8_t* out, size_t out_len) {
if (hex.size() % 2 != 0) return; // malformed — odd-length hex
for (size_t i = 0; i < out_len && (i * 2 + 1) < hex.size(); i++) { for (size_t i = 0; i < out_len && (i * 2 + 1) < hex.size(); i++) {
char byte_str[3] = {hex[i*2], hex[i*2+1], 0}; char byte_str[3] = {hex[i*2], hex[i*2+1], 0};
out[i] = (uint8_t)strtol(byte_str, nullptr, 16); out[i] = (uint8_t)strtol(byte_str, nullptr, 16);
} }
} }
static void sha256(const uint8_t* data, size_t len, uint8_t out[32]) { static bool sha256(const uint8_t* data, size_t len, uint8_t out[32]) {
mbedtls_md_context_t ctx; mbedtls_md_context_t ctx;
const mbedtls_md_info_t* info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); const mbedtls_md_info_t* info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
mbedtls_md_init(&ctx); mbedtls_md_init(&ctx);
mbedtls_md_setup(&ctx, info, 0); int ret = mbedtls_md_setup(&ctx, info, 0);
if (ret != 0) { mbedtls_md_free(&ctx); return false; }
mbedtls_md_starts(&ctx); mbedtls_md_starts(&ctx);
mbedtls_md_update(&ctx, data, len); mbedtls_md_update(&ctx, data, len);
mbedtls_md_finish(&ctx, out); mbedtls_md_finish(&ctx, out);
mbedtls_md_free(&ctx); mbedtls_md_free(&ctx);
return true;
} }
HString hmac_sign(const HString& secret_hex, const HString& device_id, HString hmac_sign(const HString& secret_hex, const HString& device_id,
uint32_t timestamp, const HString& body) { uint32_t timestamp, const HString& body) {
// 1. SHA256(body) // 1. SHA256(body)
uint8_t body_hash[32]; uint8_t body_hash[32] = {};
sha256((const uint8_t*)body.c_str(), body.size(), body_hash); if (!sha256((const uint8_t*)body.c_str(), body.size(), body_hash)) {
return HString{};
}
HString body_hash_hex = bytes_to_hex(body_hash, 32); HString body_hash_hex = bytes_to_hex(body_hash, 32);
// 2. Build message // 2. Build message
@@ -54,7 +59,8 @@ HString hmac_sign(const HString& secret_hex, const HString& device_id,
mbedtls_md_context_t ctx; mbedtls_md_context_t ctx;
const mbedtls_md_info_t* info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); const mbedtls_md_info_t* info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
mbedtls_md_init(&ctx); mbedtls_md_init(&ctx);
mbedtls_md_setup(&ctx, info, 1); int ret2 = mbedtls_md_setup(&ctx, info, 1);
if (ret2 != 0) { mbedtls_md_free(&ctx); return HString{}; }
mbedtls_md_hmac_starts(&ctx, secret, secret_len); mbedtls_md_hmac_starts(&ctx, secret, secret_len);
mbedtls_md_hmac_update(&ctx, (const uint8_t*)message.c_str(), message.size()); mbedtls_md_hmac_update(&ctx, (const uint8_t*)message.c_str(), message.size());
mbedtls_md_hmac_finish(&ctx, hmac_result); mbedtls_md_hmac_finish(&ctx, hmac_result);

View File

@@ -5,6 +5,13 @@
void setUp(void) {} void setUp(void) {}
void tearDown(void) {} void tearDown(void) {}
// Expected value derived via:
// import hmac, hashlib
// secret = bytes.fromhex("0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20")
// body = '{"location_id":"retailer-123","records":[]}'
// body_hash = hashlib.sha256(body.encode()).hexdigest()
// msg = f"dc-0042:1712000000:{body_hash}"
// hmac.new(secret, msg.encode(), hashlib.sha256).hexdigest()
void test_hmac_known_vector() { void test_hmac_known_vector() {
HString secret = "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20"; HString secret = "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20";
HString device = "dc-0042"; HString device = "dc-0042";