testutils.c: Fix high bits of the mpz_urandomb used with mini-gmp.
[gd/nettle] / chacha-poly1305.c
1 /* chacha-poly1305.c
2
3    AEAD mechanism based on chacha and poly1305.
4
5    Copyright (C) 2014, 2015 Niels Möller
6
7    This file is part of GNU Nettle.
8
9    GNU Nettle is free software: you can redistribute it and/or
10    modify it under the terms of either:
11
12      * the GNU Lesser General Public License as published by the Free
13        Software Foundation; either version 3 of the License, or (at your
14        option) any later version.
15
16    or
17
18      * the GNU General Public License as published by the Free
19        Software Foundation; either version 2 of the License, or (at your
20        option) any later version.
21
22    or both in parallel, as here.
23
24    GNU Nettle is distributed in the hope that it will be useful,
25    but WITHOUT ANY WARRANTY; without even the implied warranty of
26    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
27    General Public License for more details.
28
29    You should have received copies of the GNU General Public License and
30    the GNU Lesser General Public License along with this program.  If
31    not, see http://www.gnu.org/licenses/.
32 */
33
34 /* This implements chacha-poly1305 according to
35    draft-irtf-cfrg-chacha20-poly1305-08. The inputs to poly1305 are:
36
37      associated data
38      zero padding
39      ciphertext
40      zero padding
41      length of associated data (64-bit, little endian)
42      length of ciphertext (64-bit, little endian)
43
44    where the padding fields are 0-15 zero bytes, filling up to a
45    16-byte boundary.
46 */
47
48 #if HAVE_CONFIG_H
49 # include "config.h"
50 #endif
51
52 #include <assert.h>
53 #include <string.h>
54
55 #include "chacha-poly1305.h"
56
57 #include "macros.h"
58
59 #define CHACHA_ROUNDS 20
60
61 /* FIXME: Also set nonce to zero, and implement nonce
62    auto-increment? */
63 void
64 chacha_poly1305_set_key (struct chacha_poly1305_ctx *ctx,
65                          const uint8_t *key)
66 {
67   chacha_set_key (&ctx->chacha, key);
68 }
69
70 void
71 chacha_poly1305_set_nonce (struct chacha_poly1305_ctx *ctx,
72                            const uint8_t *nonce)
73 {
74   union {
75     uint32_t x[_CHACHA_STATE_LENGTH];
76     uint8_t subkey[32];
77   } u;
78
79   chacha_set_nonce96 (&ctx->chacha, nonce);
80   /* Generate authentication key */
81   _chacha_core (u.x, ctx->chacha.state, CHACHA_ROUNDS);
82   poly1305_set_key (&ctx->poly1305, u.subkey);  
83   /* For final poly1305 processing */
84   memcpy (ctx->s.b, u.subkey + 16, 16);
85   /* Increment block count */
86   ctx->chacha.state[12] = 1;
87
88   ctx->auth_size = ctx->data_size = ctx->index = 0;
89 }
90
91 /* FIXME: Duplicated in poly1305-aes128.c */
92 #define COMPRESS(ctx, data) _poly1305_block(&(ctx)->poly1305, (data), 1)
93
94 static void
95 poly1305_update (struct chacha_poly1305_ctx *ctx,
96                  size_t length, const uint8_t *data)
97 {
98   MD_UPDATE (ctx, length, data, COMPRESS, (void) 0);
99 }
100
101 static void
102 poly1305_pad (struct chacha_poly1305_ctx *ctx)
103 {
104   if (ctx->index)
105     {
106       memset (ctx->block + ctx->index, 0,
107               POLY1305_BLOCK_SIZE - ctx->index);
108       _poly1305_block(&ctx->poly1305, ctx->block, 1);
109       ctx->index = 0;
110     }
111 }
112 void
113 chacha_poly1305_update (struct chacha_poly1305_ctx *ctx,
114                         size_t length, const uint8_t *data)
115 {
116   assert (ctx->data_size == 0);  
117   poly1305_update (ctx, length, data);
118   ctx->auth_size += length;
119 }
120
121
122 void
123 chacha_poly1305_encrypt (struct chacha_poly1305_ctx *ctx,
124                          size_t length, uint8_t *dst, const uint8_t *src)
125 {
126   if (!length)
127     return;
128
129   assert (ctx->data_size % CHACHA_POLY1305_BLOCK_SIZE == 0);
130   poly1305_pad (ctx);
131
132   chacha_crypt (&ctx->chacha, length, dst, src);
133   poly1305_update (ctx, length, dst);
134   ctx->data_size += length;
135 }
136                          
137 void
138 chacha_poly1305_decrypt (struct chacha_poly1305_ctx *ctx,
139                          size_t length, uint8_t *dst, const uint8_t *src)
140 {
141   if (!length)
142     return;
143
144   assert (ctx->data_size % CHACHA_POLY1305_BLOCK_SIZE == 0);
145   poly1305_pad (ctx);
146
147   poly1305_update (ctx, length, src);
148   chacha_crypt (&ctx->chacha, length, dst, src);
149   ctx->data_size += length;
150 }
151                          
152 void
153 chacha_poly1305_digest (struct chacha_poly1305_ctx *ctx,
154                         size_t length, uint8_t *digest)
155 {
156   uint8_t buf[16];
157
158   poly1305_pad (ctx);
159   LE_WRITE_UINT64 (buf, ctx->auth_size);
160   LE_WRITE_UINT64 (buf + 8, ctx->data_size);
161
162   _poly1305_block (&ctx->poly1305, buf, 1);
163
164   poly1305_digest (&ctx->poly1305, &ctx->s);
165   memcpy (digest, &ctx->s.b, length);
166 }