]> git.ipfire.org Git - thirdparty/nettle.git/blob - chacha-crypt.c
Add ChangeLog entry for nettle-3.10 release.
[thirdparty/nettle.git] / chacha-crypt.c
1 /* chacha-crypt.c
2
3 The crypt function in the ChaCha stream cipher.
4 Heavily based on the Salsa20 implementation in Nettle.
5
6 Copyright (C) 2014 Niels Möller
7 Copyright (C) 2013 Joachim Strömbergson
8 Copyright (C) 2012 Simon Josefsson
9
10 This file is part of GNU Nettle.
11
12 GNU Nettle is free software: you can redistribute it and/or
13 modify it under the terms of either:
14
15 * the GNU Lesser General Public License as published by the Free
16 Software Foundation; either version 3 of the License, or (at your
17 option) any later version.
18
19 or
20
21 * the GNU General Public License as published by the Free
22 Software Foundation; either version 2 of the License, or (at your
23 option) any later version.
24
25 or both in parallel, as here.
26
27 GNU Nettle is distributed in the hope that it will be useful,
28 but WITHOUT ANY WARRANTY; without even the implied warranty of
29 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
30 General Public License for more details.
31
32 You should have received copies of the GNU General Public License and
33 the GNU Lesser General Public License along with this program. If
34 not, see http://www.gnu.org/licenses/.
35 */
36
37 /* Based on:
38 chacha-ref.c version 2008.01.20.
39 D. J. Bernstein
40 Public domain.
41 */
42
43 #if HAVE_CONFIG_H
44 # include "config.h"
45 #endif
46
47 #include <string.h>
48
49 #include "chacha.h"
50 #include "chacha-internal.h"
51
52 #include "macros.h"
53 #include "memxor.h"
54
55 #define CHACHA_ROUNDS 20
56
57 #if HAVE_NATIVE_chacha_4core
58 #define _nettle_chacha_crypt_4core chacha_crypt
59 #define _nettle_chacha_crypt32_4core chacha_crypt32
60 #elif HAVE_NATIVE_chacha_3core
61 #define _nettle_chacha_crypt_3core chacha_crypt
62 #define _nettle_chacha_crypt32_3core chacha_crypt32
63 #elif !(HAVE_NATIVE_fat_chacha_4core || HAVE_NATIVE_fat_chacha_3core)
64 #define _nettle_chacha_crypt_1core chacha_crypt
65 #define _nettle_chacha_crypt32_1core chacha_crypt32
66 #endif
67
68 #if HAVE_NATIVE_chacha_4core || HAVE_NATIVE_fat_chacha_4core
69 void
70 _nettle_chacha_crypt_4core(struct chacha_ctx *ctx,
71 size_t length,
72 uint8_t *dst,
73 const uint8_t *src)
74 {
75 uint32_t x[4*_CHACHA_STATE_LENGTH];
76
77 if (!length)
78 return;
79
80 while (length > 2*CHACHA_BLOCK_SIZE)
81 {
82 _nettle_chacha_4core (x, ctx->state, CHACHA_ROUNDS);
83 if (length <= 4*CHACHA_BLOCK_SIZE)
84 {
85 uint32_t incr = 3 + (length > 3*CHACHA_BLOCK_SIZE);
86 ctx->state[12] += incr;
87 ctx->state[13] += (ctx->state[12] < incr);
88 memxor3 (dst, src, x, length);
89 return;
90 }
91 ctx->state[12] += 4;
92 ctx->state[13] += (ctx->state[12] < 4);
93 memxor3 (dst, src, x, 4*CHACHA_BLOCK_SIZE);
94
95 length -= 4*CHACHA_BLOCK_SIZE;
96 dst += 4*CHACHA_BLOCK_SIZE;
97 src += 4*CHACHA_BLOCK_SIZE;
98 }
99 if (length > CHACHA_BLOCK_SIZE)
100 {
101 _nettle_chacha_2core (x, ctx->state, CHACHA_ROUNDS);
102 ctx->state[12] += 2;
103 ctx->state[13] += (ctx->state[12] < 2);
104 }
105 else
106 {
107 _nettle_chacha_core (x, ctx->state, CHACHA_ROUNDS);
108 ctx->state[13] += (++ctx->state[12] == 0);
109 }
110 memxor3 (dst, src, x, length);
111 }
112 #endif
113
114 #if HAVE_NATIVE_chacha_3core || HAVE_NATIVE_fat_chacha_3core
115 void
116 _nettle_chacha_crypt_3core(struct chacha_ctx *ctx,
117 size_t length,
118 uint8_t *dst,
119 const uint8_t *src)
120 {
121 uint32_t x[3*_CHACHA_STATE_LENGTH];
122
123 if (!length)
124 return;
125
126 while (length > 2*CHACHA_BLOCK_SIZE)
127 {
128 _nettle_chacha_3core (x, ctx->state, CHACHA_ROUNDS);
129 ctx->state[12] += 3;
130 ctx->state[13] += (ctx->state[12] < 3);
131 if (length <= 3*CHACHA_BLOCK_SIZE)
132 {
133 memxor3 (dst, src, x, length);
134 return;
135 }
136 memxor3 (dst, src, x, 3*CHACHA_BLOCK_SIZE);
137
138 length -= 3*CHACHA_BLOCK_SIZE;
139 dst += 3*CHACHA_BLOCK_SIZE;
140 src += 3*CHACHA_BLOCK_SIZE;
141 }
142 if (length <= CHACHA_BLOCK_SIZE)
143 {
144 _nettle_chacha_core (x, ctx->state, CHACHA_ROUNDS);
145 ctx->state[13] += (++ctx->state[12] == 0);
146 }
147 else
148 {
149 _nettle_chacha_3core (x, ctx->state, CHACHA_ROUNDS);
150 ctx->state[12] += 2;
151 ctx->state[13] += (ctx->state[12] < 2);
152 }
153 memxor3 (dst, src, x, length);
154 }
155 #endif
156
157 #if !(HAVE_NATIVE_chacha_4core || HAVE_NATIVE_chacha_3core)
158 void
159 _nettle_chacha_crypt_1core(struct chacha_ctx *ctx,
160 size_t length,
161 uint8_t *dst,
162 const uint8_t *src)
163 {
164 if (!length)
165 return;
166
167 for (;;)
168 {
169 uint32_t x[_CHACHA_STATE_LENGTH];
170
171 _nettle_chacha_core (x, ctx->state, CHACHA_ROUNDS);
172
173 ctx->state[13] += (++ctx->state[12] == 0);
174
175 /* stopping at 2^70 length per nonce is user's responsibility */
176
177 if (length <= CHACHA_BLOCK_SIZE)
178 {
179 memxor3 (dst, src, x, length);
180 return;
181 }
182 memxor3 (dst, src, x, CHACHA_BLOCK_SIZE);
183
184 length -= CHACHA_BLOCK_SIZE;
185 dst += CHACHA_BLOCK_SIZE;
186 src += CHACHA_BLOCK_SIZE;
187 }
188 }
189 #endif
190
191 #if HAVE_NATIVE_chacha_4core || HAVE_NATIVE_fat_chacha_4core
192 void
193 _nettle_chacha_crypt32_4core(struct chacha_ctx *ctx,
194 size_t length,
195 uint8_t *dst,
196 const uint8_t *src)
197 {
198 uint32_t x[4*_CHACHA_STATE_LENGTH];
199
200 if (!length)
201 return;
202
203 while (length > 2*CHACHA_BLOCK_SIZE)
204 {
205 _nettle_chacha_4core32 (x, ctx->state, CHACHA_ROUNDS);
206 if (length <= 4*CHACHA_BLOCK_SIZE)
207 {
208 ctx->state[12] += 3 + (length > 3*CHACHA_BLOCK_SIZE);
209 memxor3 (dst, src, x, length);
210 return;
211 }
212 ctx->state[12] += 4;
213 memxor3 (dst, src, x, 4*CHACHA_BLOCK_SIZE);
214
215 length -= 4*CHACHA_BLOCK_SIZE;
216 dst += 4*CHACHA_BLOCK_SIZE;
217 src += 4*CHACHA_BLOCK_SIZE;
218 }
219 if (length > CHACHA_BLOCK_SIZE)
220 {
221 _nettle_chacha_2core32 (x, ctx->state, CHACHA_ROUNDS);
222 ctx->state[12] += 2;
223 }
224 else
225 {
226 _nettle_chacha_core (x, ctx->state, CHACHA_ROUNDS);
227 ++ctx->state[12];
228 }
229 memxor3 (dst, src, x, length);
230 }
231 #endif
232
233 #if HAVE_NATIVE_chacha_3core || HAVE_NATIVE_fat_chacha_3core
234 void
235 _nettle_chacha_crypt32_3core(struct chacha_ctx *ctx,
236 size_t length,
237 uint8_t *dst,
238 const uint8_t *src)
239 {
240 uint32_t x[3*_CHACHA_STATE_LENGTH];
241
242 if (!length)
243 return;
244
245 while (length > 2*CHACHA_BLOCK_SIZE)
246 {
247 _nettle_chacha_3core32 (x, ctx->state, CHACHA_ROUNDS);
248 ctx->state[12] += 3;
249 if (length <= 3*CHACHA_BLOCK_SIZE)
250 {
251 memxor3 (dst, src, x, length);
252 return;
253 }
254 memxor3 (dst, src, x, 3*CHACHA_BLOCK_SIZE);
255
256 length -= 3*CHACHA_BLOCK_SIZE;
257 dst += 3*CHACHA_BLOCK_SIZE;
258 src += 3*CHACHA_BLOCK_SIZE;
259 }
260 if (length <= CHACHA_BLOCK_SIZE)
261 {
262 _nettle_chacha_core (x, ctx->state, CHACHA_ROUNDS);
263 ++ctx->state[12];
264 }
265 else
266 {
267 _nettle_chacha_3core32 (x, ctx->state, CHACHA_ROUNDS);
268 ctx->state[12] += 2;
269 }
270 memxor3 (dst, src, x, length);
271 }
272 #endif
273
274 #if !(HAVE_NATIVE_chacha_4core || HAVE_NATIVE_chacha_3core)
275 void
276 _nettle_chacha_crypt32_1core(struct chacha_ctx *ctx,
277 size_t length,
278 uint8_t *dst,
279 const uint8_t *src)
280 {
281 if (!length)
282 return;
283
284 for (;;)
285 {
286 uint32_t x[_CHACHA_STATE_LENGTH];
287
288 _nettle_chacha_core (x, ctx->state, CHACHA_ROUNDS);
289
290 ++ctx->state[12];
291
292 /* stopping at 2^38 length per nonce is user's responsibility */
293
294 if (length <= CHACHA_BLOCK_SIZE)
295 {
296 memxor3 (dst, src, x, length);
297 return;
298 }
299 memxor3 (dst, src, x, CHACHA_BLOCK_SIZE);
300
301 length -= CHACHA_BLOCK_SIZE;
302 dst += CHACHA_BLOCK_SIZE;
303 src += CHACHA_BLOCK_SIZE;
304 }
305 }
306 #endif