7 #include "chacha-poly1305.h"
10 struct chacha_poly1305_ctx {
11 struct chacha_ctx main_ctx, header_ctx;
14 chacha_poly1305_ctx_t *chacha_poly1305_init(void) {
15 chacha_poly1305_ctx_t *ctx = xzalloc(sizeof(*ctx));
19 void chacha_poly1305_exit(chacha_poly1305_ctx_t *ctx) {
23 bool chacha_poly1305_set_key(chacha_poly1305_ctx_t *ctx, const void *vkey) {
24 const uint8_t *key = vkey;
25 chacha_keysetup(&ctx->main_ctx, key, 256);
26 chacha_keysetup(&ctx->header_ctx, key + 32, 256);
30 static void put_u64(void *vp, uint64_t v) {
31 uint8_t *p = (uint8_t *) vp;
33 p[0] = (uint8_t)(v >> 56) & 0xff;
34 p[1] = (uint8_t)(v >> 48) & 0xff;
35 p[2] = (uint8_t)(v >> 40) & 0xff;
36 p[3] = (uint8_t)(v >> 32) & 0xff;
37 p[4] = (uint8_t)(v >> 24) & 0xff;
38 p[5] = (uint8_t)(v >> 16) & 0xff;
39 p[6] = (uint8_t)(v >> 8) & 0xff;
40 p[7] = (uint8_t) v & 0xff;
43 bool chacha_poly1305_encrypt(chacha_poly1305_ctx_t *ctx, uint64_t seqnr, const void *indata, size_t inlen, void *voutdata, size_t *outlen) {
45 const uint8_t one[8] = { 1, 0, 0, 0, 0, 0, 0, 0 }; /* NB little-endian */
46 uint8_t poly_key[POLY1305_KEYLEN];
47 uint8_t *outdata = voutdata;
50 * Run ChaCha20 once to generate the Poly1305 key. The IV is the
51 * packet sequence number.
53 memset(poly_key, 0, sizeof(poly_key));
54 put_u64(seqbuf, seqnr);
55 chacha_ivsetup(&ctx->main_ctx, seqbuf, NULL);
56 chacha_encrypt_bytes(&ctx->main_ctx, poly_key, poly_key, sizeof(poly_key));
58 /* Set Chacha's block counter to 1 */
59 chacha_ivsetup(&ctx->main_ctx, seqbuf, one);
61 chacha_encrypt_bytes(&ctx->main_ctx, indata, outdata, inlen);
62 poly1305_auth(outdata + inlen, outdata, inlen, poly_key);
65 *outlen = inlen + POLY1305_TAGLEN;
71 bool chacha_poly1305_decrypt(chacha_poly1305_ctx_t *ctx, uint64_t seqnr, const void *vindata, size_t inlen, void *outdata, size_t *outlen) {
73 const uint8_t one[8] = { 1, 0, 0, 0, 0, 0, 0, 0 }; /* NB little-endian */
74 uint8_t expected_tag[POLY1305_TAGLEN], poly_key[POLY1305_KEYLEN];
75 const uint8_t *indata = vindata;
78 * Run ChaCha20 once to generate the Poly1305 key. The IV is the
79 * packet sequence number.
81 memset(poly_key, 0, sizeof(poly_key));
82 put_u64(seqbuf, seqnr);
83 chacha_ivsetup(&ctx->main_ctx, seqbuf, NULL);
84 chacha_encrypt_bytes(&ctx->main_ctx, poly_key, poly_key, sizeof(poly_key));
86 /* Set Chacha's block counter to 1 */
87 chacha_ivsetup(&ctx->main_ctx, seqbuf, one);
89 /* Check tag before anything else */
90 inlen -= POLY1305_TAGLEN;
91 const uint8_t *tag = indata + inlen;
93 poly1305_auth(expected_tag, indata, inlen, poly_key);
95 if(memcmp(expected_tag, tag, POLY1305_TAGLEN)) {
99 chacha_encrypt_bytes(&ctx->main_ctx, indata, outdata, inlen);