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