macros.h replaced with smaller headers, U8TO*_?E() renamed and converted to static...
[rofl0r-kripto.git] / lib / stream / chacha.c
blob3a7d50d59d2d0c018383fcd1d0741220e172272d
1 /*
2 * Copyright (C) 2011-2013 Gregor Pintar <grpintar@gmail.com>
4 * Permission is granted to deal in this work without any restriction,
5 * including unlimited rights to use, publicly perform, publish,
6 * reproduce, relicence, modify, merge, and/or distribute in any form,
7 * for any purpose, with or without fee, and by any means.
9 * This work is provided "AS IS" and WITHOUT WARRANTY of any kind,
10 * to the utmost extent permitted by applicable law. In no event
11 * shall a licensor, author or contributor be held liable for any
12 * issues arising in any way out of dealing in the work.
15 #include <stdint.h>
16 #include <stdlib.h>
17 #include <limits.h>
19 #include <kripto/loadstore.h>
20 #include <kripto/rotate.h>
21 #include <kripto/memwipe.h>
22 #include <kripto/stream.h>
23 #include <kripto/desc/stream.h>
25 #include <kripto/stream/chacha.h>
27 struct kripto_stream
29 const kripto_stream_desc *desc;
30 unsigned int r;
31 uint32_t x[16];
32 uint8_t buf[64];
33 unsigned int used;
36 #define QR(A, B, C, D) \
37 { \
38 A += B; D = ROL32(D ^ A, 16); \
39 C += D; B = ROL32(B ^ C, 12); \
40 A += B; D = ROL32(D ^ A, 8); \
41 C += D; B = ROL32(B ^ C, 7); \
44 static void chacha_core
46 unsigned int r,
47 const uint32_t *x,
48 void *out
51 unsigned int i;
53 uint32_t x0 = x[0];
54 uint32_t x1 = x[1];
55 uint32_t x2 = x[2];
56 uint32_t x3 = x[3];
57 uint32_t x4 = x[4];
58 uint32_t x5 = x[5];
59 uint32_t x6 = x[6];
60 uint32_t x7 = x[7];
61 uint32_t x8 = x[8];
62 uint32_t x9 = x[9];
63 uint32_t x10 = x[10];
64 uint32_t x11 = x[11];
65 uint32_t x12 = x[12];
66 uint32_t x13 = x[13];
67 uint32_t x14 = x[14];
68 uint32_t x15 = x[15];
70 for(i = 0; i < r; i++)
72 QR(x0, x4, x8, x12);
73 QR(x1, x5, x9, x13);
74 QR(x2, x6, x10, x14);
75 QR(x3, x7, x11, x15);
77 if(++i == r) break;
79 QR(x0, x5, x10, x15);
80 QR(x1, x6, x11, x12);
81 QR(x2, x7, x8, x13);
82 QR(x3, x4, x9, x14);
85 x0 += x[0];
86 x1 += x[1];
87 x2 += x[2];
88 x3 += x[3];
89 x4 += x[4];
90 x5 += x[5];
91 x6 += x[6];
92 x7 += x[7];
93 x8 += x[8];
94 x9 += x[9];
95 x10 += x[10];
96 x11 += x[11];
97 x12 += x[12];
98 x13 += x[13];
99 x14 += x[14];
100 x15 += x[15];
102 STORE32L(x0, U8(out));
103 STORE32L(x1, U8(out) + 4);
104 STORE32L(x2, U8(out) + 8);
105 STORE32L(x3, U8(out) + 12);
106 STORE32L(x4, U8(out) + 16);
107 STORE32L(x5, U8(out) + 20);
108 STORE32L(x6, U8(out) + 24);
109 STORE32L(x7, U8(out) + 28);
110 STORE32L(x8, U8(out) + 32);
111 STORE32L(x9, U8(out) + 36);
112 STORE32L(x10, U8(out) + 40);
113 STORE32L(x11, U8(out) + 44);
114 STORE32L(x12, U8(out) + 48);
115 STORE32L(x13, U8(out) + 52);
116 STORE32L(x14, U8(out) + 56);
117 STORE32L(x15, U8(out) + 60);
120 static void chacha_crypt
122 kripto_stream *s,
123 const void *in,
124 void *out,
125 size_t len
128 size_t i;
130 for(i = 0; i < len; i++)
132 if(s->used == 64)
134 chacha_core(s->r, s->x, s->buf);
135 s->used = 0;
137 if(!++s->x[12])
138 ++s->x[13];
141 U8(out)[i] = CU8(in)[i] ^ s->buf[s->used++];
145 static void chacha_prng
147 kripto_stream *s,
148 void *out,
149 size_t len
152 size_t i;
154 for(i = 0; i < len; i++)
156 if(s->used == 64)
158 chacha_core(s->r, s->x, s->buf);
159 s->used = 0;
161 if(!++s->x[12])
162 ++s->x[13];
165 U8(out)[i] = s->buf[s->used++];
169 static kripto_stream *chacha_recreate
171 kripto_stream *s,
172 unsigned int r,
173 const void *key,
174 unsigned int key_len,
175 const void *iv,
176 unsigned int iv_len
179 unsigned int i;
180 unsigned int j = 0;
181 uint8_t constant[16] = "expand 00-byte k";
183 constant[7] += key_len / 10;
184 constant[8] += key_len % 10;
186 s->x[0] = LOAD32L(constant);
187 s->x[1] = LOAD32L(constant + 4);
188 s->x[2] = LOAD32L(constant + 8);
189 s->x[3] = LOAD32L(constant + 12);
191 for(i = 4; i < 12; i++)
193 s->x[i] = 0;
195 s->x[i] = (s->x[i] >> 8) | (CU8(key)[j++] << 24);
196 if(j == key_len) j = 0;
198 s->x[i] = (s->x[i] >> 8) | (CU8(key)[j++] << 24);
199 if(j == key_len) j = 0;
201 s->x[i] = (s->x[i] >> 8) | (CU8(key)[j++] << 24);
202 if(j == key_len) j = 0;
204 s->x[i] = (s->x[i] >> 8) | (CU8(key)[j++] << 24);
205 if(j == key_len) j = 0;
208 /* IV */
209 s->x[12] = s->x[13] = s->x[14] = s->x[15] = 0;
211 if(iv_len > 8) i = 48; /* XChaCha */
212 else i = 56;
214 for(; i < 64 && j < iv_len; i++, j++)
215 s->x[i >> 2] = (s->x[i >> 2] >> 8) | (CU8(iv)[j] << 24);
217 s->r = r;
218 if(!s->r) s->r = 20;
220 if(iv_len > 8) /* XChaCha */
222 for(i = 0; i < s->r; i++)
224 QR(s->x[0], s->x[4], s->x[8], s->x[12]);
225 QR(s->x[1], s->x[5], s->x[9], s->x[13]);
226 QR(s->x[2], s->x[6], s->x[10], s->x[14]);
227 QR(s->x[3], s->x[7], s->x[11], s->x[15]);
229 if(++i == s->r) break;
231 QR(s->x[0], s->x[5], s->x[10], s->x[15]);
232 QR(s->x[1], s->x[6], s->x[11], s->x[12]);
233 QR(s->x[2], s->x[7], s->x[8], s->x[13]);
234 QR(s->x[3], s->x[4], s->x[9], s->x[14]);
237 s->x[4] = s->x[0]; s->x[0] = LOAD32L(constant);
238 s->x[5] = s->x[1]; s->x[1] = LOAD32L(constant + 4);
239 s->x[6] = s->x[2]; s->x[2] = LOAD32L(constant + 8);
240 s->x[7] = s->x[3]; s->x[3] = LOAD32L(constant + 12);
242 s->x[8] = s->x[12]; s->x[12] = 0;
243 s->x[9] = s->x[13]; s->x[13] = 0;
244 s->x[10] = s->x[14]; s->x[14] = 0;
245 s->x[11] = s->x[15]; s->x[15] = 0;
247 for(i = 56; i < 64 && j < iv_len; i++, j++)
248 s->x[i >> 2] = (s->x[i >> 2] >> 8) | (CU8(iv)[j] << 24);
251 s->used = 64;
253 return s;
256 static kripto_stream *chacha_create
258 const kripto_stream_desc *desc,
259 unsigned int r,
260 const void *key,
261 unsigned int key_len,
262 const void *iv,
263 unsigned int iv_len
266 kripto_stream *s;
268 (void)desc;
270 s = malloc(sizeof(kripto_stream));
271 if(!s) return 0;
273 s->desc = kripto_stream_chacha;
275 (void)chacha_recreate(s, r, key, key_len, iv, iv_len);
277 return s;
280 static void chacha_destroy(kripto_stream *s)
282 kripto_memwipe(s, sizeof(kripto_stream));
283 free(s);
286 static const struct kripto_stream_desc chacha =
288 &chacha_create,
289 &chacha_recreate,
290 &chacha_crypt,
291 &chacha_crypt,
292 &chacha_prng,
293 &chacha_destroy,
295 32, /* max key */
296 24 /* max iv */
299 const kripto_stream_desc *const kripto_stream_chacha = &chacha;