Skip to content

Tiny HMAC is a lightweight C library that supports all SHA and SHA-3 variants from my Tiny SHA implementation. It includes one-shot and incremental APIs, optional heap-based contexts, and a constant-time comparison function.

License

Notifications You must be signed in to change notification settings

0xNullll/tiny-hmac

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

15 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Tiny HMAC

Tiny HMAC is a lightweight, configurable C library for computing HMACs using all SHA and SHA3 variants.
It builds on Tiny SHA — also available as a standalone project at https://github.com/0xNullll/tiny-sha — and allows optional direct use of Tiny SHA functions.


Features

  • Header-only and portable across C/C++ compilers.
  • Configurable HMAC support for multiple hash algorithms:
    • SHA-1 / SHA-2: SHA1, SHA224, SHA256, SHA384, SHA512, SHA512/224, SHA512/256
    • SHA-3: SHA3-224, SHA3-256, SHA3-384, SHA3-512
  • One-shot HMAC computation or incremental update/finalize interface.
  • Context cloning and heap allocation support.
  • Function name prefixing for integration into larger projects.
  • Key size up to 512 bytes.
  • Safe Constant-time lexicographic HMAC comparison using 'HMAC_ConstTimeCompareOrder', returning -1/0/1 without leaking timing
  • Handles endianness automatically

SHA variants in Tiny SHA can also be used directly, but SHAKE and raw Keccak are disabled by default.


Configuration

Before including the header, users can configure feature flags:

#define ENABLE_SHA1       1   // enable SHA1 HMAC
#define ENABLE_SHA256     1   // enable SHA256 HMAC
#define ENABLE_SHA3_512   0   // disable SHA3-512 HMAC
#define TSHASH_PREFIX     mylib_ // optional prefix for exported functions

You can also define it via compiler flags:

gcc -DTSHASH_PREFIX=MyLib_ -DTINY_SHA_IMPLEMENTATION tiny_sha.c test_sha.c -o test_sha

⚠️ Note: TSHASH_PREFIX must be defined before including the header. If not defined, functions will have no prefix (default behavior).


Internal HMAC Table

The library uses an internal table to map HMAC algorithms to their properties and Tiny SHA function pointers:

static const struct _HMAC_TABLE {
    hmac_alg_t alg;                        // Algorithm identifier
    size_t digest_size;                     // Digest length in bytes
    size_t block_size;                      // Internal block size
    size_t ctx_size;                        // Size of hash context
    bool (*hash_init)(void*);               // Hash init function pointer
    bool (*hash_update)(void*, const uint8_t*, size_t);  // Hash update pointer
    bool (*hash_final)(void*, uint8_t*, size_t);         // Hash final pointer
    bool (*hash_squeeze)(void*, uint8_t*, size_t);       // Hash squeeze pointer
} HMAC_TABLE[];

This table is used internally by HMAC_Init to configure the context according to the selected algorithm.


Usage

Including the library

#include "tiny_hmac.h"

One-shot HMAC

uint8_t digest[64]; // max digest size
HMAC_Compute(HMAC_SHA256, key, key_len, data, data_len, digest, sizeof(digest));

Incremental HMAC

HMAC_CTX ctx;
HMAC_Init(&ctx, HMAC_SHA256, key, key_len);
HMAC_Update(&ctx, data_part1, len1);
HMAC_Update(&ctx, data_part2, len2);
HMAC_Final(&ctx, digest, sizeof(digest));
HMAC_Free(&ctx);

Heap-allocated context

HMAC_CTX *ctx = HMAC_InitAlloc(HMAC_SHA256, key, key_len);
HMAC_Update(ctx, data, data_len);
HMAC_Final(ctx, digest, sizeof(digest));
HMAC_FreeAlloc(&ctx);

API Reference

Types

typedef enum {
    HMAC_SHA1, HMAC_SHA224, HMAC_SHA256,
    HMAC_SHA384, HMAC_SHA512, HMAC_SHA512_224, HMAC_SHA512_256,
    HMAC_SHA3_224, HMAC_SHA3_256, HMAC_SHA3_384, HMAC_SHA3_512
} hmac_alg_t;

Output Sizes

Algorithm Digest Size
HMAC-SHA-1 20 bytes
HMAC-SHA-224 28 bytes
HMAC-SHA-256 32 bytes
HMAC-SHA-384 48 bytes
HMAC-SHA-512 64 bytes
HMAC-SHA-512/224 28 bytes
HMAC-SHA-512/256 32 bytes
HMAC-SHA3-224 28 bytes
HMAC-SHA3-256 32 bytes
HMAC-SHA3-384 48 bytes
HMAC-SHA3-512 64 bytes

Context Structure

typedef struct _HMAC_CTX {
    hmac_alg_t alg;
    void *ipad_ctx;
    void *opad_ctx;
    size_t ctx_buf_size;
    size_t ctx_block_size;
    size_t out_len;
    bool (*hash_init)(void*);
    bool (*hash_update)(void*, const uint8_t*, size_t);
    bool (*hash_final)(void*, uint8_t*, size_t);
    bool (*hash_squeeze)(void*, uint8_t*, size_t);
    uint8_t key[512];
    size_t key_len;
    int isFinalized;
    int isHeapAlloc;
} HMAC_CTX;

Functions

Function Description
HMAC_Init Initialize a pre-allocated HMAC context
HMAC_InitAlloc Initialize and allocate a heap HMAC context
HMAC_Update Feed data into the HMAC
HMAC_Final Finalize HMAC and write digest
HMAC_Free Free internal buffers for pre-allocated context
HMAC_FreeAlloc Free heap-allocated context
HMAC_Compute One-shot HMAC computation
HMAC_CloneCtx Clone an existing HMAC context into a destination context
HMAC_CloneCtxAlloc Clone an HMAC context into a new heap-allocated context
HMAC_ConstTimeCompareOrder Constant-time digest comparison returning ordering (-1,0,+1)
HMAC_DigestSize Get the digest size of a hash algorithm
HMAC_Name Get the human-readable name of the algorithm

Example

#include "tiny_hmac.h"
#include <stdio.h>

int main() {
    uint8_t key[] = "secret";
    uint8_t data[] = "hello world";
    uint8_t digest[SHA256_DIGEST_SIZE];

    if(HMAC_Compute(HMAC_SHA256, key, sizeof(key)-1, data, sizeof(data)-1, digest, sizeof(digest))) {
        printf("HMAC-SHA256 computed successfully!\n");
    } else {
        printf("HMAC computation failed\n");
    }
    return 0;
}

Sources


License

This project is released under the MIT License. See LICENSE for full text.

About

Tiny HMAC is a lightweight C library that supports all SHA and SHA-3 variants from my Tiny SHA implementation. It includes one-shot and incremental APIs, optional heap-based contexts, and a constant-time comparison function.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published