Skip to content

File syn_hmac.h

File List > src > syntropic > util > syn_hmac.h

Go to the documentation of this file

#ifndef SYN_HMAC_H
#define SYN_HMAC_H

#if __has_include("syn_config.h")
#include "syn_config.h"
#endif

#if !defined(SYN_USE_SHA256) || SYN_USE_SHA256

#include "syn_sha256.h"

#include <stddef.h>
#include <stdint.h>
#include <string.h>

#ifdef __cplusplus
extern "C" {
#endif

#define SYN_HMAC_SHA256_SIZE SYN_SHA256_DIGEST_SIZE

/* ── Context ────────────────────────────────────────────────────────────── */

typedef struct {
    SYN_SHA256 inner;                         
    uint8_t o_key_pad[SYN_SHA256_BLOCK_SIZE]; 
} SYN_HMAC_SHA256;

/* ── API ────────────────────────────────────────────────────────────────── */

static inline void syn_hmac_sha256_init(SYN_HMAC_SHA256 *ctx, const void *key, size_t key_len)
{
    uint8_t k_buf[SYN_SHA256_BLOCK_SIZE];
    unsigned i;

    memset(k_buf, 0, sizeof(k_buf));

    if (key_len > SYN_SHA256_BLOCK_SIZE) {
        /* Keys longer than block size are hashed first */
        syn_sha256(key, key_len, k_buf);
    } else {
        memcpy(k_buf, key, key_len);
    }

    /* Compute i_key_pad = K ⊕ 0x36  and  o_key_pad = K ⊕ 0x5C */
    uint8_t i_key_pad[SYN_SHA256_BLOCK_SIZE];
    for (i = 0; i < SYN_SHA256_BLOCK_SIZE; i++) {
        i_key_pad[i] = k_buf[i] ^ 0x36u;
        ctx->o_key_pad[i] = k_buf[i] ^ 0x5Cu;
    }

    /* Inner hash: SHA-256(i_key_pad || message...) */
    syn_sha256_init(&ctx->inner);
    syn_sha256_update(&ctx->inner, i_key_pad, SYN_SHA256_BLOCK_SIZE);
}

static inline void syn_hmac_sha256_update(SYN_HMAC_SHA256 *ctx, const void *data, size_t len)
{
    syn_sha256_update(&ctx->inner, data, len);
}

static inline void syn_hmac_sha256_final(SYN_HMAC_SHA256 *ctx, uint8_t mac[SYN_HMAC_SHA256_SIZE])
{
    uint8_t inner_hash[SYN_SHA256_DIGEST_SIZE];

    /* Finalize inner hash */
    syn_sha256_final(&ctx->inner, inner_hash);

    /* Outer hash: SHA-256(o_key_pad || inner_hash) */
    SYN_SHA256 outer;
    syn_sha256_init(&outer);
    syn_sha256_update(&outer, ctx->o_key_pad, SYN_SHA256_BLOCK_SIZE);
    syn_sha256_update(&outer, inner_hash, SYN_SHA256_DIGEST_SIZE);
    syn_sha256_final(&outer, mac);
}

static inline void syn_hmac_sha256(const void *key, size_t key_len, const void *data,
                                   size_t data_len, uint8_t mac[SYN_HMAC_SHA256_SIZE])
{
    SYN_HMAC_SHA256 ctx;
    syn_hmac_sha256_init(&ctx, key, key_len);
    syn_hmac_sha256_update(&ctx, data, data_len);
    syn_hmac_sha256_final(&ctx, mac);
}

#ifdef __cplusplus
}
#endif

#endif /* SYN_USE_SHA256 */

#endif /* SYN_HMAC_H */