Hi,
I'm trying to implement chacha20-poly1305 as used by SSH
(https://datatracker.ietf.org/doc/html/draft-ietf-sshm-chacha20-poly1305-04),
which differs from RFC 8439's ChaCha-Poly1035 as implemented by Nettle.
While Nettle internally has the necessary building blocks, it lacks a
public API to directly use poly1305. I think this is fairly
straightforward to add one though. Please see below for my initial
attempt. If you think this is the right approach, I'd be happy to work
on a proper patch including tests and documentation.
#define POLY1305_KEY_SIZE 32
#define POLY1305_DIGEST_SIZE 16
struct poly1305_mac_ctx {
struct poly1305_ctx pctx;
union nettle_block16 s;
uint8_t block[POLY1305_BLOCK_SIZE];
unsigned index;
};
void
poly1305_set_key(struct poly1305_mac_ctx* ctx, const uint8_t *key)
{
_nettle_poly1305_set_key(&ctx->pctx, key);
memcpy(ctx->s.b, key + 16, 16);
ctx->index = 0;
}
void
poly1305_update(struct poly1305_mac_ctx* ctx, size_t length, const
uint8_t *data)
{
ctx->index = _nettle_poly1305_update(&ctx->pctx, ctx->block,
ctx->index, length, data);
}
/* After calling this function, context must be re-keyed before
calling poly1305_update/poly1305_digest again. */
void
poly1305_digest(struct poly1305_mac_ctx* ctx, uint8_t* digest)
{
if (ctx->index > 0)
{
ctx->block[ctx->index] = 1;
memset (ctx->block + ctx->index + 1,
0, POLY1305_BLOCK_SIZE - 1 - ctx->index);
_nettle_poly1305_block (&ctx->pctx, ctx->block, 0);
}
_nettle_poly1305_digest(&ctx->pctx, &ctx->s);
memcpy(digest, ctx->s.b, POLY1305_DIGEST_SIZE);
}
Regards,
Tim