From 7662fc4c2557162dec80e6420326901047d4905d Mon Sep 17 00:00:00 2001 From: Peter Woolery Date: Mon, 13 Apr 2026 14:24:48 -0700 Subject: [PATCH] =?UTF-8?q?fix:=20HMAC=20module=20=E2=80=94=20mbedTLS=20er?= =?UTF-8?q?ror=20handling,=20hex=20guard,=20test=20docs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 4.6 --- firmware/lib/hmac/hmac.cpp | 16 +++++++++++----- firmware/test/test_native/test_hmac.cpp | 7 +++++++ 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/firmware/lib/hmac/hmac.cpp b/firmware/lib/hmac/hmac.cpp index 899f5f2..fee48d5 100644 --- a/firmware/lib/hmac/hmac.cpp +++ b/firmware/lib/hmac/hmac.cpp @@ -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) { + if (hex.size() % 2 != 0) return; // malformed — odd-length hex 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}; 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; const mbedtls_md_info_t* info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); 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_update(&ctx, data, len); mbedtls_md_finish(&ctx, out); mbedtls_md_free(&ctx); + return true; } HString hmac_sign(const HString& secret_hex, const HString& device_id, uint32_t timestamp, const HString& body) { // 1. SHA256(body) - uint8_t body_hash[32]; - sha256((const uint8_t*)body.c_str(), body.size(), body_hash); + uint8_t body_hash[32] = {}; + if (!sha256((const uint8_t*)body.c_str(), body.size(), body_hash)) { + return HString{}; + } HString body_hash_hex = bytes_to_hex(body_hash, 32); // 2. Build message @@ -54,7 +59,8 @@ HString hmac_sign(const HString& secret_hex, const HString& device_id, mbedtls_md_context_t ctx; const mbedtls_md_info_t* info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); 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_update(&ctx, (const uint8_t*)message.c_str(), message.size()); mbedtls_md_hmac_finish(&ctx, hmac_result); diff --git a/firmware/test/test_native/test_hmac.cpp b/firmware/test/test_native/test_hmac.cpp index 9173f30..5bd6779 100644 --- a/firmware/test/test_native/test_hmac.cpp +++ b/firmware/test/test_native/test_hmac.cpp @@ -5,6 +5,13 @@ void setUp(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() { HString secret = "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20"; HString device = "dc-0042";