Skip to content

File syn_blake2s.h

File List > crypto > syn_blake2s.h

Go to the documentation of this file

#ifndef SYN_BLAKE2S_H
#define SYN_BLAKE2S_H

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

#if !defined(SYN_USE_BLAKE2S) || SYN_USE_BLAKE2S

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

#ifdef __cplusplus
extern "C" {
#endif

/* ── Constants ──────────────────────────────────────────────────────────── */

#define SYN_BLAKE2S_BLOCK_SIZE 64 
#define SYN_BLAKE2S_MAX_DIGEST 32 
#define SYN_BLAKE2S_MAX_KEY 32    
/* ── Context ────────────────────────────────────────────────────────────── */

typedef struct {
    uint32_t h[8];                       
    uint32_t t[2];                       
    uint8_t buf[SYN_BLAKE2S_BLOCK_SIZE]; 
    uint8_t buflen;                      
    uint8_t outlen;                      
} SYN_BLAKE2s;

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

void syn_blake2s_init(SYN_BLAKE2s *ctx, size_t outlen);

void syn_blake2s_init_keyed(SYN_BLAKE2s *ctx, const void *key, size_t keylen, size_t outlen);

void syn_blake2s_update(SYN_BLAKE2s *ctx, const void *data, size_t len);

void syn_blake2s_final(SYN_BLAKE2s *ctx, uint8_t *out);

/* ── Convenience ────────────────────────────────────────────────────────── */

static inline void syn_blake2s(const void *data, size_t len, uint8_t *out, size_t outlen)
{
    SYN_BLAKE2s ctx;
    syn_blake2s_init(&ctx, outlen);
    syn_blake2s_update(&ctx, data, len);
    syn_blake2s_final(&ctx, out);
}

static inline void syn_blake2s_mac(const void *key, size_t keylen, const void *data, size_t len,
                                   uint8_t *out, size_t outlen)
{
    SYN_BLAKE2s ctx;
    syn_blake2s_init_keyed(&ctx, key, keylen, outlen);
    syn_blake2s_update(&ctx, data, len);
    syn_blake2s_final(&ctx, out);
}

/* ── HMAC-BLAKE2s (for HKDF) ───────────────────────────────────────────── */

typedef struct {
    SYN_BLAKE2s inner;                         
    uint8_t o_key_pad[SYN_BLAKE2S_BLOCK_SIZE]; 
} SYN_HMAC_BLAKE2s;

static inline void syn_hmac_blake2s_init(SYN_HMAC_BLAKE2s *ctx, const void *key, size_t keylen)
{
    uint8_t k_buf[SYN_BLAKE2S_BLOCK_SIZE];
    uint8_t i_key_pad[SYN_BLAKE2S_BLOCK_SIZE];
    unsigned i;

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

    if (keylen > SYN_BLAKE2S_BLOCK_SIZE) {
        syn_blake2s(key, keylen, k_buf, SYN_BLAKE2S_MAX_DIGEST);
    } else {
        memcpy(k_buf, key, keylen);
    }

    for (i = 0; i < SYN_BLAKE2S_BLOCK_SIZE; i++) {
        i_key_pad[i] = k_buf[i] ^ 0x36u;
        ctx->o_key_pad[i] = k_buf[i] ^ 0x5Cu;
    }

    syn_blake2s_init(&ctx->inner, SYN_BLAKE2S_MAX_DIGEST);
    syn_blake2s_update(&ctx->inner, i_key_pad, SYN_BLAKE2S_BLOCK_SIZE);
}

static inline void syn_hmac_blake2s_update(SYN_HMAC_BLAKE2s *ctx, const void *data, size_t len)
{
    syn_blake2s_update(&ctx->inner, data, len);
}

static inline void syn_hmac_blake2s_final(SYN_HMAC_BLAKE2s *ctx,
                                          uint8_t mac[SYN_BLAKE2S_MAX_DIGEST])
{
    uint8_t inner_hash[SYN_BLAKE2S_MAX_DIGEST];

    syn_blake2s_final(&ctx->inner, inner_hash);

    SYN_BLAKE2s outer;
    syn_blake2s_init(&outer, SYN_BLAKE2S_MAX_DIGEST);
    syn_blake2s_update(&outer, ctx->o_key_pad, SYN_BLAKE2S_BLOCK_SIZE);
    syn_blake2s_update(&outer, inner_hash, SYN_BLAKE2S_MAX_DIGEST);
    syn_blake2s_final(&outer, mac);
}

static inline void syn_hmac_blake2s(const void *key, size_t keylen, const void *data,
                                    size_t datalen, uint8_t mac[SYN_BLAKE2S_MAX_DIGEST])
{
    SYN_HMAC_BLAKE2s ctx;
    syn_hmac_blake2s_init(&ctx, key, keylen);
    syn_hmac_blake2s_update(&ctx, data, datalen);
    syn_hmac_blake2s_final(&ctx, mac);
}

#ifdef __cplusplus
}
#endif

#endif /* SYN_USE_BLAKE2S */

#endif /* SYN_BLAKE2S_H */