tls

tls.git
git clone git://git.lenczewski.org/tls.git
Log | Files | Refs

commit b48f82e2e64faa4e74d62728984572b3af076030
parent 9b592418ccb31c6299973689031c5f40e5cc1a34
Author: MikoĊ‚aj Lenczewski <mikolaj@lenczewski.org>
Date:   Wed, 16 Sep 2026 19:57:56 +0100

Add hmac implementation

Diffstat:
Ahmac-sha2.c | 43+++++++++++++++++++++++++++++++++++++++++++
Ahmac-sha2.h | 14++++++++++++++
Ahmac.c | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ahmac.h | 45+++++++++++++++++++++++++++++++++++++++++++++
Atest/test-hmac.c | 45+++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 201 insertions(+), 0 deletions(-)

diff --git a/hmac-sha2.c b/hmac-sha2.c @@ -0,0 +1,43 @@ +#include "hmac-sha2.h" + +struct hmac_hash const hmac_sha256 = { + .init = (void *) sha256_init, + .push = (void *) sha256_push, + .dgst = (void *) sha256_dgst, + .digest_size = SHA256_DIGEST_SIZE, +}; + +struct hmac_hash const hmac_sha224 = { + .init = (void *) sha224_init, + .push = (void *) sha224_push, + .dgst = (void *) sha224_dgst, + .digest_size = SHA224_DIGEST_SIZE, +}; + +struct hmac_hash const hmac_sha512 = { + .init = (void *) sha512_init, + .push = (void *) sha512_push, + .dgst = (void *) sha512_dgst, + .digest_size = SHA512_DIGEST_SIZE, +}; + +struct hmac_hash const hmac_sha384 = { + .init = (void *) sha384_init, + .push = (void *) sha384_push, + .dgst = (void *) sha384_dgst, + .digest_size = SHA384_DIGEST_SIZE, +}; + +struct hmac_hash const hmac_sha512_224 = { + .init = (void *) sha512_224_init, + .push = (void *) sha512_224_push, + .dgst = (void *) sha512_224_dgst, + .digest_size = SHA512_224_DIGEST_SIZE, +}; + +struct hmac_hash const hmac_sha512_256 = { + .init = (void *) sha512_256_init, + .push = (void *) sha512_256_push, + .dgst = (void *) sha512_256_dgst, + .digest_size = SHA512_256_DIGEST_SIZE, +}; diff --git a/hmac-sha2.h b/hmac-sha2.h @@ -0,0 +1,14 @@ +#ifndef HMAC_SHA2_H +#define HMAC_SHA2_H + +#include "hmac.h" +#include "sha.h" + +extern struct hmac_hash const hmac_sha224; +extern struct hmac_hash const hmac_sha256; +extern struct hmac_hash const hmac_sha512; +extern struct hmac_hash const hmac_sha384; +extern struct hmac_hash const hmac_sha512_224; +extern struct hmac_hash const hmac_sha512_256; + +#endif /* HMAC_SHA2_H */ diff --git a/hmac.c b/hmac.c @@ -0,0 +1,54 @@ +#include "hmac.h" + +void +hmac_init(struct hmac_ctx *ctx, + struct hmac_hash const *hash, void *restrict hash_ctx, + void const *restrict key, size_t key_len) +{ + memset(ctx, 0, sizeof *ctx); + + ctx->hash = hash; + ctx->hash_ctx = hash_ctx; + + if (key_len <= HMAC_BLOCK_SIZE) { // can use the key directly + assert(key_len <= HMAC_BLOCK_SIZE); + memcpy(ctx->iv, key, key_len); + } else { // must hash the key first to generate the iv block + assert(hash->digest_size <= HMAC_BLOCK_SIZE); + hash->init(hash_ctx); + hash->push(hash_ctx, key, key_len); + hash->dgst(hash_ctx, ctx->iv); + } + + for (size_t i = 0; i < HMAC_BLOCK_SIZE; i++) { + ctx->ipad[i] = ctx->iv[i] ^ HMAC_IPAD_BYTE; + ctx->opad[i] = ctx->iv[i] ^ HMAC_OPAD_BYTE; + } +} + +void +hmac_hash(struct hmac_ctx *ctx, + void const *restrict buf, size_t buf_len, + void *restrict digest) +{ + ctx->hash->init(ctx->hash_ctx); + ctx->hash->push(ctx->hash_ctx, ctx->ipad, sizeof ctx->ipad); + ctx->hash->push(ctx->hash_ctx, buf, buf_len); + ctx->hash->dgst(ctx->hash_ctx, digest); + + ctx->hash->init(ctx->hash_ctx); + ctx->hash->push(ctx->hash_ctx, ctx->opad, sizeof ctx->opad); + ctx->hash->push(ctx->hash_ctx, digest, ctx->hash->digest_size); + ctx->hash->dgst(ctx->hash_ctx, digest); +} + +void +hmac(struct hmac_hash const *hash, void *restrict hash_ctx, + void const *restrict key, size_t key_len, + void const *restrict buf, size_t buf_len, + void *restrict digest) +{ + struct hmac_ctx ctx; + hmac_init(&ctx, hash, hash_ctx, key, key_len); + hmac_hash(&ctx, buf, buf_len, digest); +} diff --git a/hmac.h b/hmac.h @@ -0,0 +1,45 @@ +// hmac: https://datatracker.ietf.org/doc/html/rfc2104 + +#ifndef HMAC_H +#define HMAC_H + +#include <assert.h> +#include <stdint.h> +#include <string.h> + +#define HMAC_BLOCK_SIZE 64 +#define HMAC_IPAD_BYTE 0x36 +#define HMAC_OPAD_BYTE 0x5c + +struct hmac_hash { + void (*init)(void *ctx); + void (*push)(void *ctx, void const *buf, size_t len); + void (*dgst)(void *ctx, void *digest); + size_t digest_size; +}; + +struct hmac_ctx { + unsigned char iv[HMAC_BLOCK_SIZE]; + unsigned char opad[HMAC_BLOCK_SIZE]; + unsigned char ipad[HMAC_BLOCK_SIZE]; + + struct hmac_hash const *hash; + void *hash_ctx; +}; + +void +hmac_init(struct hmac_ctx *ctx, + struct hmac_hash const *hash, void *restrict hash_ctx, + void const *restrict key, size_t key_len); + +void +hmac_hash(struct hmac_ctx *ctx, + void const *restrict buf, size_t buf_len, + void *restrict digest); +void +hmac(struct hmac_hash const *hash, void *restrict hash_ctx, + void const *restrict key, size_t key_len, + void const *restrict buf, size_t buf_len, + void *restrict digest); + +#endif /* HMAC_H */ diff --git a/test/test-hmac.c b/test/test-hmac.c @@ -0,0 +1,45 @@ +#include "hmac-sha2.h" + +#include <stdio.h> + +int +main(void) +{ + char msg[] = "Hi There"; + + unsigned char key[] = { + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + }; + + struct sha256_ctx sha256_ctx; + uint8_t dgst[SHA256_DIGEST_SIZE]; + hmac(&hmac_sha256, &sha256_ctx, key, sizeof key, msg, strlen(msg), dgst); + + uint8_t expected[SHA256_DIGEST_SIZE] = { + 0x49, 0x2c, 0xe0, 0x20, 0xfe, 0x25, 0x34, 0xa5, + 0x78, 0x9d, 0xc3, 0x84, 0x88, 0x06, 0xc7, 0x8f, + 0x4f, 0x67, 0x11, 0x39, 0x7f, 0x08, 0xe7, 0xe7, + 0xa1, 0x2c, 0xa5, 0xa4, 0x48, 0x3c, 0x8a, 0xa6, + }; + + printf("msg: \"%.*s\" (%lu bytes)\n", sizeof msg, msg, strlen(msg)); + + printf("dgst: "); + for (size_t i = 0; i < sizeof dgst; i++) { + printf("%.2x", dgst[i]); + } + printf("\n"); + + printf("exp.: "); + for (size_t i = 0; i < sizeof expected; i++) { + printf("%.2x", expected[i]); + } + printf("\n"); + + return memcmp(expected, dgst, SHA224_DIGEST_SIZE); +} + +#include "hmac.c" +#include "hmac-sha2.c" +#include "sha.c"