6 #include "chacha-poly1305.h"
9 struct chacha_poly1305_ctx {
10 struct chacha_ctx main_ctx, header_ctx;
13 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)
24 bool chacha_poly1305_set_key(chacha_poly1305_ctx_t *ctx, const void *key)
26 chacha_keysetup(&ctx->main_ctx, key, 256);
27 chacha_keysetup(&ctx->header_ctx, (uint8_t *)key + 32, 256);
31 static void put_u64(void *vp, uint64_t v)
33 uint8_t *p = (uint8_t *) vp;
35 p[0] = (uint8_t) (v >> 56) & 0xff;
36 p[1] = (uint8_t) (v >> 48) & 0xff;
37 p[2] = (uint8_t) (v >> 40) & 0xff;
38 p[3] = (uint8_t) (v >> 32) & 0xff;
39 p[4] = (uint8_t) (v >> 24) & 0xff;
40 p[5] = (uint8_t) (v >> 16) & 0xff;
41 p[6] = (uint8_t) (v >> 8) & 0xff;
42 p[7] = (uint8_t) v & 0xff;
45 bool chacha_poly1305_encrypt(chacha_poly1305_ctx_t *ctx, uint64_t seqnr, const void *indata, size_t inlen, void *outdata, size_t *outlen) {
47 const uint8_t one[8] = { 1, 0, 0, 0, 0, 0, 0, 0 }; /* NB little-endian */
48 uint8_t poly_key[POLY1305_KEYLEN];
51 * Run ChaCha20 once to generate the Poly1305 key. The IV is the
52 * packet sequence number.
54 memset(poly_key, 0, sizeof(poly_key));
55 put_u64(seqbuf, seqnr);
56 chacha_ivsetup(&ctx->main_ctx, seqbuf, NULL);
57 chacha_encrypt_bytes(&ctx->main_ctx, poly_key, poly_key, sizeof(poly_key));
59 /* Set Chacha's block counter to 1 */
60 chacha_ivsetup(&ctx->main_ctx, seqbuf, one);
62 chacha_encrypt_bytes(&ctx->main_ctx, indata, outdata, inlen);
63 poly1305_auth((uint8_t *)outdata + inlen, outdata, inlen, poly_key);
66 *outlen = inlen + POLY1305_TAGLEN;
71 bool chacha_poly1305_verify(chacha_poly1305_ctx_t *ctx, uint64_t seqnr, const void *indata, size_t inlen) {
73 uint8_t expected_tag[POLY1305_TAGLEN], poly_key[POLY1305_KEYLEN];
76 * Run ChaCha20 once to generate the Poly1305 key. The IV is the
77 * packet sequence number.
79 memset(poly_key, 0, sizeof(poly_key));
80 put_u64(seqbuf, seqnr);
81 chacha_ivsetup(&ctx->main_ctx, seqbuf, NULL);
82 chacha_encrypt_bytes(&ctx->main_ctx, poly_key, poly_key, sizeof(poly_key));
84 /* Check tag before anything else */
85 inlen -= POLY1305_TAGLEN;
86 const uint8_t *tag = (const uint8_t *)indata + inlen;
88 poly1305_auth(expected_tag, indata, inlen, poly_key);
89 if (memcmp(expected_tag, tag, POLY1305_TAGLEN))
95 bool chacha_poly1305_decrypt(chacha_poly1305_ctx_t *ctx, uint64_t seqnr, const void *indata, size_t inlen, void *outdata, size_t *outlen) {
97 const uint8_t one[8] = { 1, 0, 0, 0, 0, 0, 0, 0 }; /* NB little-endian */
98 uint8_t expected_tag[POLY1305_TAGLEN], poly_key[POLY1305_KEYLEN];
101 * Run ChaCha20 once to generate the Poly1305 key. The IV is the
102 * packet sequence number.
104 memset(poly_key, 0, sizeof(poly_key));
105 put_u64(seqbuf, seqnr);
106 chacha_ivsetup(&ctx->main_ctx, seqbuf, NULL);
107 chacha_encrypt_bytes(&ctx->main_ctx, poly_key, poly_key, sizeof(poly_key));
109 /* Set Chacha's block counter to 1 */
110 chacha_ivsetup(&ctx->main_ctx, seqbuf, one);
112 /* Check tag before anything else */
113 inlen -= POLY1305_TAGLEN;
114 const uint8_t *tag = (const uint8_t *)indata + inlen;
116 poly1305_auth(expected_tag, indata, inlen, poly_key);
117 if (memcmp(expected_tag, tag, POLY1305_TAGLEN))
120 chacha_encrypt_bytes(&ctx->main_ctx, indata, outdata, inlen);
128 bool chacha_poly1305_encrypt_iv96(chacha_poly1305_ctx_t *ctx, const uint8_t *seqbuf, const void *indata, size_t inlen, void *outdata, size_t *outlen) {
129 const uint8_t one[4] = { 1, 0, 0, 0 }; /* NB little-endian */
130 uint8_t poly_key[POLY1305_KEYLEN];
133 * Run ChaCha20 once to generate the Poly1305 key. The IV is the
134 * packet sequence number.
136 memset(poly_key, 0, sizeof(poly_key));
137 chacha_ivsetup_96(&ctx->main_ctx, seqbuf, NULL);
138 chacha_encrypt_bytes(&ctx->main_ctx, poly_key, poly_key, sizeof(poly_key));
140 /* Set Chacha's block counter to 1 */
141 chacha_ivsetup_96(&ctx->main_ctx, seqbuf, one);
143 chacha_encrypt_bytes(&ctx->main_ctx, indata, outdata, inlen);
144 poly1305_auth((uint8_t *)outdata + inlen, outdata, inlen, poly_key);
147 *outlen = inlen + POLY1305_TAGLEN;
152 bool chacha_poly1305_decrypt_iv96(chacha_poly1305_ctx_t *ctx, const uint8_t *seqbuf, const void *indata, size_t inlen, void *outdata, size_t *outlen) {
153 const uint8_t one[4] = { 1, 0, 0, 0 }; /* NB little-endian */
154 uint8_t expected_tag[POLY1305_TAGLEN], poly_key[POLY1305_KEYLEN];
157 * Run ChaCha20 once to generate the Poly1305 key. The IV is the
158 * packet sequence number.
160 memset(poly_key, 0, sizeof(poly_key));
161 chacha_ivsetup_96(&ctx->main_ctx, seqbuf, NULL);
162 chacha_encrypt_bytes(&ctx->main_ctx, poly_key, poly_key, sizeof(poly_key));
164 /* Set Chacha's block counter to 1 */
165 chacha_ivsetup_96(&ctx->main_ctx, seqbuf, one);
167 /* Check tag before anything else */
168 inlen -= POLY1305_TAGLEN;
169 const uint8_t *tag = (const uint8_t *)indata + inlen;
171 poly1305_auth(expected_tag, indata, inlen, poly_key);
172 if (memcmp(expected_tag, tag, POLY1305_TAGLEN))
175 chacha_encrypt_bytes(&ctx->main_ctx, indata, outdata, inlen);