967015f275716163b199c026e3f6f005813c4e40
[trex.git] /
1
2 /* $OpenBSD: chacha.c,v 1.1 2013/11/21 00:45:44 djm Exp $ */
3
4 /*
5  chacha-merged.c version 20080118
6  D. J. Bernstein
7  Public domain.
8  */
9
10 #include <stdint.h>
11 #include <string.h>
12
13 #include "api.h"
14 #include "crypto_stream_chacha20.h"
15 #include "utils.h"
16
17 struct chacha_ctx {
18     uint32_t input[16];
19 };
20
21 typedef uint8_t  u8;
22 typedef uint32_t u32;
23
24 typedef struct chacha_ctx chacha_ctx;
25
26 #define U8C(v) (v##U)
27 #define U32C(v) (v##U)
28
29 #define U8V(v) ((u8)(v) & U8C(0xFF))
30 #define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF))
31
32 #define ROTL32(v, n) \
33   (U32V((v) << (n)) | ((v) >> (32 - (n))))
34
35 #define U8TO32_LITTLE(p) \
36   (((u32)((p)[0])      ) | \
37    ((u32)((p)[1]) <<  8) | \
38    ((u32)((p)[2]) << 16) | \
39    ((u32)((p)[3]) << 24))
40
41 #define U32TO8_LITTLE(p, v) \
42   do { \
43     (p)[0] = U8V((v)      ); \
44     (p)[1] = U8V((v) >>  8); \
45     (p)[2] = U8V((v) >> 16); \
46     (p)[3] = U8V((v) >> 24); \
47   } while (0)
48
49 #define ROTATE(v,c) (ROTL32(v,c))
50 #define XOR(v,w) ((v) ^ (w))
51 #define PLUS(v,w) (U32V((v) + (w)))
52 #define PLUSONE(v) (PLUS((v),1))
53
54 #define QUARTERROUND(a,b,c,d) \
55   a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \
56   c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \
57   a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \
58   c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);
59
60 static const unsigned char sigma[16] = {
61     'e', 'x', 'p', 'a', 'n', 'd', ' ', '3', '2', '-', 'b', 'y', 't', 'e', ' ', 'k'
62 };
63
64 static void
65 chacha_keysetup(chacha_ctx *x, const u8 *k)
66 {
67     const unsigned char *constants;
68
69     x->input[4] = U8TO32_LITTLE(k + 0);
70     x->input[5] = U8TO32_LITTLE(k + 4);
71     x->input[6] = U8TO32_LITTLE(k + 8);
72     x->input[7] = U8TO32_LITTLE(k + 12);
73     k += 16;
74     constants = sigma;
75     x->input[8] = U8TO32_LITTLE(k + 0);
76     x->input[9] = U8TO32_LITTLE(k + 4);
77     x->input[10] = U8TO32_LITTLE(k + 8);
78     x->input[11] = U8TO32_LITTLE(k + 12);
79     x->input[0] = U8TO32_LITTLE(constants + 0);
80     x->input[1] = U8TO32_LITTLE(constants + 4);
81     x->input[2] = U8TO32_LITTLE(constants + 8);
82     x->input[3] = U8TO32_LITTLE(constants + 12);
83 }
84
85 static void
86 chacha_ivsetup(chacha_ctx *x, const u8 *iv, const u8 *counter)
87 {
88     x->input[12] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 0);
89     x->input[13] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 4);
90     x->input[14] = U8TO32_LITTLE(iv + 0);
91     x->input[15] = U8TO32_LITTLE(iv + 4);
92 }
93
94 static void
95 chacha_encrypt_bytes(chacha_ctx *x, const u8 *m, u8 *c, unsigned long long bytes)
96 {
97     u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
98     u32 j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
99     u8 *ctarget = NULL;
100     u8 tmp[64];
101     unsigned int i;
102
103     if (!bytes) {
104         return; /* LCOV_EXCL_LINE */
105     }
106     j0 = x->input[0];
107     j1 = x->input[1];
108     j2 = x->input[2];
109     j3 = x->input[3];
110     j4 = x->input[4];
111     j5 = x->input[5];
112     j6 = x->input[6];
113     j7 = x->input[7];
114     j8 = x->input[8];
115     j9 = x->input[9];
116     j10 = x->input[10];
117     j11 = x->input[11];
118     j12 = x->input[12];
119     j13 = x->input[13];
120     j14 = x->input[14];
121     j15 = x->input[15];
122
123     for (;;) {
124         if (bytes < 64) {
125             for (i = 0; i < bytes; ++i) {
126                 tmp[i] = m[i];
127             }
128             m = tmp;
129             ctarget = c;
130             c = tmp;
131         }
132         x0 = j0;
133         x1 = j1;
134         x2 = j2;
135         x3 = j3;
136         x4 = j4;
137         x5 = j5;
138         x6 = j6;
139         x7 = j7;
140         x8 = j8;
141         x9 = j9;
142         x10 = j10;
143         x11 = j11;
144         x12 = j12;
145         x13 = j13;
146         x14 = j14;
147         x15 = j15;
148         for (i = 20; i > 0; i -= 2) {
149             QUARTERROUND(x0, x4, x8, x12)
150             QUARTERROUND(x1, x5, x9, x13)
151             QUARTERROUND(x2, x6, x10, x14)
152             QUARTERROUND(x3, x7, x11, x15)
153             QUARTERROUND(x0, x5, x10, x15)
154             QUARTERROUND(x1, x6, x11, x12)
155             QUARTERROUND(x2, x7, x8, x13)
156             QUARTERROUND(x3, x4, x9, x14)
157         }
158         x0 = PLUS(x0, j0);
159         x1 = PLUS(x1, j1);
160         x2 = PLUS(x2, j2);
161         x3 = PLUS(x3, j3);
162         x4 = PLUS(x4, j4);
163         x5 = PLUS(x5, j5);
164         x6 = PLUS(x6, j6);
165         x7 = PLUS(x7, j7);
166         x8 = PLUS(x8, j8);
167         x9 = PLUS(x9, j9);
168         x10 = PLUS(x10, j10);
169         x11 = PLUS(x11, j11);
170         x12 = PLUS(x12, j12);
171         x13 = PLUS(x13, j13);
172         x14 = PLUS(x14, j14);
173         x15 = PLUS(x15, j15);
174
175         x0 = XOR(x0, U8TO32_LITTLE(m + 0));
176         x1 = XOR(x1, U8TO32_LITTLE(m + 4));
177         x2 = XOR(x2, U8TO32_LITTLE(m + 8));
178         x3 = XOR(x3, U8TO32_LITTLE(m + 12));
179         x4 = XOR(x4, U8TO32_LITTLE(m + 16));
180         x5 = XOR(x5, U8TO32_LITTLE(m + 20));
181         x6 = XOR(x6, U8TO32_LITTLE(m + 24));
182         x7 = XOR(x7, U8TO32_LITTLE(m + 28));
183         x8 = XOR(x8, U8TO32_LITTLE(m + 32));
184         x9 = XOR(x9, U8TO32_LITTLE(m + 36));
185         x10 = XOR(x10, U8TO32_LITTLE(m + 40));
186         x11 = XOR(x11, U8TO32_LITTLE(m + 44));
187         x12 = XOR(x12, U8TO32_LITTLE(m + 48));
188         x13 = XOR(x13, U8TO32_LITTLE(m + 52));
189         x14 = XOR(x14, U8TO32_LITTLE(m + 56));
190         x15 = XOR(x15, U8TO32_LITTLE(m + 60));
191
192         j12 = PLUSONE(j12);
193         /* LCOV_EXCL_START */
194         if (!j12) {
195             j13 = PLUSONE(j13);
196         }
197         /* LCOV_EXCL_STOP */
198
199         U32TO8_LITTLE(c + 0, x0);
200         U32TO8_LITTLE(c + 4, x1);
201         U32TO8_LITTLE(c + 8, x2);
202         U32TO8_LITTLE(c + 12, x3);
203         U32TO8_LITTLE(c + 16, x4);
204         U32TO8_LITTLE(c + 20, x5);
205         U32TO8_LITTLE(c + 24, x6);
206         U32TO8_LITTLE(c + 28, x7);
207         U32TO8_LITTLE(c + 32, x8);
208         U32TO8_LITTLE(c + 36, x9);
209         U32TO8_LITTLE(c + 40, x10);
210         U32TO8_LITTLE(c + 44, x11);
211         U32TO8_LITTLE(c + 48, x12);
212         U32TO8_LITTLE(c + 52, x13);
213         U32TO8_LITTLE(c + 56, x14);
214         U32TO8_LITTLE(c + 60, x15);
215
216         if (bytes <= 64) {
217             if (bytes < 64) {
218                 for (i = 0; i < (unsigned int) bytes; ++i) {
219                     ctarget[i] = c[i];
220                 }
221             }
222             x->input[12] = j12;
223             x->input[13] = j13;
224             return;
225         }
226         bytes -= 64;
227         c += 64;
228         m += 64;
229     }
230 }
231
232 int
233 crypto_stream_chacha20_ref(unsigned char *c, unsigned long long clen,
234                            const unsigned char *n, const unsigned char *k)
235 {
236     struct chacha_ctx ctx;
237
238     if (!clen) {
239         return 0;
240     }
241     (void) sizeof(int[crypto_stream_chacha20_KEYBYTES == 256 / 8 ? 1 : -1]);
242     chacha_keysetup(&ctx, k);
243     chacha_ivsetup(&ctx, n, NULL);
244     memset(c, 0, clen);
245     chacha_encrypt_bytes(&ctx, c, c, clen);
246     sodium_memzero(&ctx, sizeof ctx);
247
248     return 0;
249 }
250
251 int
252 crypto_stream_chacha20_ref_xor_ic(unsigned char *c, const unsigned char *m,
253                                   unsigned long long mlen,
254                                   const unsigned char *n, uint64_t ic,
255                                   const unsigned char *k)
256 {
257     struct chacha_ctx ctx;
258     uint8_t           ic_bytes[8];
259     uint32_t          ic_high;
260     uint32_t          ic_low;
261
262     if (!mlen) {
263         return 0;
264     }
265     ic_high = U32V(ic >> 32);
266     ic_low = U32V(ic);
267     U32TO8_LITTLE(&ic_bytes[0], ic_low);
268     U32TO8_LITTLE(&ic_bytes[4], ic_high);
269     chacha_keysetup(&ctx, k);
270     chacha_ivsetup(&ctx, n, ic_bytes);
271     chacha_encrypt_bytes(&ctx, m, c, mlen);
272     sodium_memzero(&ctx, sizeof ctx);
273     sodium_memzero(ic_bytes, sizeof ic_bytes);
274
275     return 0;
276 }