/src/nettle-with-libgmp/chacha-poly1305.c
Line | Count | Source |
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-internal.h" |
56 | | #include "chacha-poly1305.h" |
57 | | #include "poly1305-internal.h" |
58 | | |
59 | | #include "macros.h" |
60 | | |
61 | 414 | #define CHACHA_ROUNDS 20 |
62 | | |
63 | | /* FIXME: Also set nonce to zero, and implement nonce |
64 | | auto-increment? */ |
65 | | void |
66 | | chacha_poly1305_set_key (struct chacha_poly1305_ctx *ctx, |
67 | | const uint8_t *key) |
68 | 414 | { |
69 | 414 | chacha_set_key (&ctx->chacha, key); |
70 | 414 | } |
71 | | |
72 | | void |
73 | | chacha_poly1305_set_nonce (struct chacha_poly1305_ctx *ctx, |
74 | | const uint8_t *nonce) |
75 | 414 | { |
76 | 414 | union { |
77 | 414 | uint32_t x[_CHACHA_STATE_LENGTH]; |
78 | 414 | uint8_t subkey[32]; |
79 | 414 | } u; |
80 | | |
81 | 414 | chacha_set_nonce96 (&ctx->chacha, nonce); |
82 | | /* Generate authentication key */ |
83 | 414 | _nettle_chacha_core (u.x, ctx->chacha.state, CHACHA_ROUNDS); |
84 | 414 | _nettle_poly1305_set_key (&ctx->poly1305, u.subkey); |
85 | | /* For final poly1305 processing */ |
86 | 414 | memcpy (ctx->s.b, u.subkey + 16, 16); |
87 | | /* Increment block count */ |
88 | 414 | ctx->chacha.state[12] = 1; |
89 | | |
90 | 414 | ctx->auth_size = ctx->data_size = ctx->index = 0; |
91 | 414 | } |
92 | | |
93 | | /* FIXME: Duplicated in poly1305-aes128.c */ |
94 | | #define COMPRESS(ctx, data) _nettle_poly1305_block(&(ctx)->poly1305, (data), 1) |
95 | | |
96 | | static void |
97 | | poly1305_update (struct chacha_poly1305_ctx *ctx, |
98 | | size_t length, const uint8_t *data) |
99 | 1.53k | { |
100 | 1.53k | ctx->index = _nettle_poly1305_update (&(ctx)->poly1305, |
101 | 1.53k | ctx->block, ctx->index, length, data); |
102 | 1.53k | } |
103 | | |
104 | | static void |
105 | | poly1305_pad (struct chacha_poly1305_ctx *ctx) |
106 | 914 | { |
107 | 914 | if (ctx->index) |
108 | 280 | { |
109 | 280 | memset (ctx->block + ctx->index, 0, |
110 | 280 | POLY1305_BLOCK_SIZE - ctx->index); |
111 | 280 | _nettle_poly1305_block(&ctx->poly1305, ctx->block, 1); |
112 | 280 | ctx->index = 0; |
113 | 280 | } |
114 | 914 | } |
115 | | void |
116 | | chacha_poly1305_update (struct chacha_poly1305_ctx *ctx, |
117 | | size_t length, const uint8_t *data) |
118 | 1.03k | { |
119 | 1.03k | assert (ctx->data_size == 0); |
120 | 1.03k | poly1305_update (ctx, length, data); |
121 | 1.03k | ctx->auth_size += length; |
122 | 1.03k | } |
123 | | |
124 | | |
125 | | void |
126 | | chacha_poly1305_encrypt (struct chacha_poly1305_ctx *ctx, |
127 | | size_t length, uint8_t *dst, const uint8_t *src) |
128 | 823 | { |
129 | 823 | if (!length) |
130 | 627 | return; |
131 | | |
132 | 196 | assert (ctx->data_size % CHACHA_POLY1305_BLOCK_SIZE == 0); |
133 | 196 | poly1305_pad (ctx); |
134 | | |
135 | 196 | chacha_crypt32 (&ctx->chacha, length, dst, src); |
136 | 196 | poly1305_update (ctx, length, dst); |
137 | 196 | ctx->data_size += length; |
138 | 196 | } |
139 | | |
140 | | void |
141 | | chacha_poly1305_decrypt (struct chacha_poly1305_ctx *ctx, |
142 | | size_t length, uint8_t *dst, const uint8_t *src) |
143 | 798 | { |
144 | 798 | if (!length) |
145 | 494 | return; |
146 | | |
147 | 304 | assert (ctx->data_size % CHACHA_POLY1305_BLOCK_SIZE == 0); |
148 | 304 | poly1305_pad (ctx); |
149 | | |
150 | 304 | poly1305_update (ctx, length, src); |
151 | 304 | chacha_crypt32 (&ctx->chacha, length, dst, src); |
152 | 304 | ctx->data_size += length; |
153 | 304 | } |
154 | | |
155 | | void |
156 | | chacha_poly1305_digest (struct chacha_poly1305_ctx *ctx, |
157 | | size_t length, uint8_t *digest) |
158 | 414 | { |
159 | 414 | uint8_t buf[16]; |
160 | | |
161 | 414 | poly1305_pad (ctx); |
162 | 414 | LE_WRITE_UINT64 (buf, ctx->auth_size); |
163 | 414 | LE_WRITE_UINT64 (buf + 8, ctx->data_size); |
164 | | |
165 | 414 | _nettle_poly1305_block (&ctx->poly1305, buf, 1); |
166 | | |
167 | 414 | _nettle_poly1305_digest (&ctx->poly1305, &ctx->s); |
168 | 414 | memcpy (digest, &ctx->s.b, length); |
169 | 414 | } |