]> git.meshlink.io Git - meshlink/blob - src/chacha-poly1305/chacha.c
Add support for encrypted storage.
[meshlink] / src / chacha-poly1305 / chacha.c
1 /*
2 chacha-merged.c version 20080118
3 D. J. Bernstein
4 Public domain.
5 */
6
7 #include "../system.h"
8
9 #include "chacha.h"
10
11 typedef struct chacha_ctx chacha_ctx;
12
13 #define U8C(v) (v##U)
14 #define U32C(v) (v##U)
15
16 #define U8V(v) ((uint8_t)(v) & U8C(0xFF))
17 #define U32V(v) ((uint32_t)(v) & U32C(0xFFFFFFFF))
18
19 #define ROTL32(v, n) \
20         (U32V((v) << (n)) | ((v) >> (32 - (n))))
21
22 #define U8TO32_LITTLE(p) \
23         (((uint32_t)((p)[0])      ) | \
24          ((uint32_t)((p)[1]) <<  8) | \
25          ((uint32_t)((p)[2]) << 16) | \
26          ((uint32_t)((p)[3]) << 24))
27
28 #define U32TO8_LITTLE(p, v) \
29         do { \
30                 (p)[0] = U8V((v)      ); \
31                 (p)[1] = U8V((v) >>  8); \
32                 (p)[2] = U8V((v) >> 16); \
33                 (p)[3] = U8V((v) >> 24); \
34         } while (0)
35
36 #define ROTATE(v,c) (ROTL32(v,c))
37 #define XOR(v,w) ((v) ^ (w))
38 #define PLUS(v,w) (U32V((v) + (w)))
39 #define PLUSONE(v) (PLUS((v),1))
40
41 #define QUARTERROUND(a,b,c,d) \
42         a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \
43         c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \
44         a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \
45         c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);
46
47 static const char sigma[16] = "expand 32-byte k";
48 static const char tau[16] = "expand 16-byte k";
49
50 void chacha_keysetup(chacha_ctx *x, const uint8_t *k, uint32_t kbits)
51 {
52         const char *constants;
53
54         x->input[4] = U8TO32_LITTLE(k + 0);
55         x->input[5] = U8TO32_LITTLE(k + 4);
56         x->input[6] = U8TO32_LITTLE(k + 8);
57         x->input[7] = U8TO32_LITTLE(k + 12);
58         if (kbits == 256) {     /* recommended */
59                 k += 16;
60                 constants = sigma;
61         } else {                /* kbits == 128 */
62                 constants = tau;
63         }
64         x->input[8] = U8TO32_LITTLE(k + 0);
65         x->input[9] = U8TO32_LITTLE(k + 4);
66         x->input[10] = U8TO32_LITTLE(k + 8);
67         x->input[11] = U8TO32_LITTLE(k + 12);
68         x->input[0] = U8TO32_LITTLE(constants + 0);
69         x->input[1] = U8TO32_LITTLE(constants + 4);
70         x->input[2] = U8TO32_LITTLE(constants + 8);
71         x->input[3] = U8TO32_LITTLE(constants + 12);
72 }
73
74 void chacha_ivsetup(chacha_ctx *x, const uint8_t *iv, const uint8_t *counter)
75 {
76         x->input[12] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 0);
77         x->input[13] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 4);
78         x->input[14] = U8TO32_LITTLE(iv + 0);
79         x->input[15] = U8TO32_LITTLE(iv + 4);
80 }
81
82 void chacha_ivsetup_96(chacha_ctx *x, const uint8_t *iv, const uint8_t *counter)
83 {
84         x->input[12] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 0);
85         x->input[13] = U8TO32_LITTLE(iv + 0);
86         x->input[14] = U8TO32_LITTLE(iv + 4);
87         x->input[15] = U8TO32_LITTLE(iv + 8);
88 }
89
90 void
91 chacha_encrypt_bytes(chacha_ctx *x, const uint8_t *m, uint8_t *c, uint32_t bytes)
92 {
93         uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
94         uint32_t j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
95         uint8_t *ctarget = NULL;
96         uint8_t tmp[64];
97         uint32_t i;
98
99         if (!bytes)
100                 return;
101
102         j0 = x->input[0];
103         j1 = x->input[1];
104         j2 = x->input[2];
105         j3 = x->input[3];
106         j4 = x->input[4];
107         j5 = x->input[5];
108         j6 = x->input[6];
109         j7 = x->input[7];
110         j8 = x->input[8];
111         j9 = x->input[9];
112         j10 = x->input[10];
113         j11 = x->input[11];
114         j12 = x->input[12];
115         j13 = x->input[13];
116         j14 = x->input[14];
117         j15 = x->input[15];
118
119         for (;;) {
120                 if (bytes < 64) {
121                         for (i = 0; i < bytes; ++i)
122                                 tmp[i] = m[i];
123                         m = tmp;
124                         ctarget = c;
125                         c = tmp;
126                 }
127                 x0 = j0;
128                 x1 = j1;
129                 x2 = j2;
130                 x3 = j3;
131                 x4 = j4;
132                 x5 = j5;
133                 x6 = j6;
134                 x7 = j7;
135                 x8 = j8;
136                 x9 = j9;
137                 x10 = j10;
138                 x11 = j11;
139                 x12 = j12;
140                 x13 = j13;
141                 x14 = j14;
142                 x15 = j15;
143                 for (i = 20; i > 0; i -= 2) {
144                         QUARTERROUND(x0, x4, x8, x12)
145                         QUARTERROUND(x1, x5, x9, x13)
146                         QUARTERROUND(x2, x6, x10, x14)
147                         QUARTERROUND(x3, x7, x11, x15)
148                         QUARTERROUND(x0, x5, x10, x15)
149                         QUARTERROUND(x1, x6, x11, x12)
150                         QUARTERROUND(x2, x7, x8, x13)
151                         QUARTERROUND(x3, x4, x9, x14)
152                 }
153                 x0 = PLUS(x0, j0);
154                 x1 = PLUS(x1, j1);
155                 x2 = PLUS(x2, j2);
156                 x3 = PLUS(x3, j3);
157                 x4 = PLUS(x4, j4);
158                 x5 = PLUS(x5, j5);
159                 x6 = PLUS(x6, j6);
160                 x7 = PLUS(x7, j7);
161                 x8 = PLUS(x8, j8);
162                 x9 = PLUS(x9, j9);
163                 x10 = PLUS(x10, j10);
164                 x11 = PLUS(x11, j11);
165                 x12 = PLUS(x12, j12);
166                 x13 = PLUS(x13, j13);
167                 x14 = PLUS(x14, j14);
168                 x15 = PLUS(x15, j15);
169
170                 x0 = XOR(x0, U8TO32_LITTLE(m + 0));
171                 x1 = XOR(x1, U8TO32_LITTLE(m + 4));
172                 x2 = XOR(x2, U8TO32_LITTLE(m + 8));
173                 x3 = XOR(x3, U8TO32_LITTLE(m + 12));
174                 x4 = XOR(x4, U8TO32_LITTLE(m + 16));
175                 x5 = XOR(x5, U8TO32_LITTLE(m + 20));
176                 x6 = XOR(x6, U8TO32_LITTLE(m + 24));
177                 x7 = XOR(x7, U8TO32_LITTLE(m + 28));
178                 x8 = XOR(x8, U8TO32_LITTLE(m + 32));
179                 x9 = XOR(x9, U8TO32_LITTLE(m + 36));
180                 x10 = XOR(x10, U8TO32_LITTLE(m + 40));
181                 x11 = XOR(x11, U8TO32_LITTLE(m + 44));
182                 x12 = XOR(x12, U8TO32_LITTLE(m + 48));
183                 x13 = XOR(x13, U8TO32_LITTLE(m + 52));
184                 x14 = XOR(x14, U8TO32_LITTLE(m + 56));
185                 x15 = XOR(x15, U8TO32_LITTLE(m + 60));
186
187                 j12 = PLUSONE(j12);
188                 if (!j12) {
189                         j13 = PLUSONE(j13);
190                         /* stopping at 2^70 bytes per nonce is user's responsibility */
191                 }
192
193                 U32TO8_LITTLE(c + 0, x0);
194                 U32TO8_LITTLE(c + 4, x1);
195                 U32TO8_LITTLE(c + 8, x2);
196                 U32TO8_LITTLE(c + 12, x3);
197                 U32TO8_LITTLE(c + 16, x4);
198                 U32TO8_LITTLE(c + 20, x5);
199                 U32TO8_LITTLE(c + 24, x6);
200                 U32TO8_LITTLE(c + 28, x7);
201                 U32TO8_LITTLE(c + 32, x8);
202                 U32TO8_LITTLE(c + 36, x9);
203                 U32TO8_LITTLE(c + 40, x10);
204                 U32TO8_LITTLE(c + 44, x11);
205                 U32TO8_LITTLE(c + 48, x12);
206                 U32TO8_LITTLE(c + 52, x13);
207                 U32TO8_LITTLE(c + 56, x14);
208                 U32TO8_LITTLE(c + 60, x15);
209
210                 if (bytes <= 64) {
211                         if (bytes < 64) {
212                                 for (i = 0; i < bytes; ++i)
213                                         ctarget[i] = c[i];
214                         }
215                         x->input[12] = j12;
216                         x->input[13] = j13;
217                         return;
218                 }
219                 bytes -= 64;
220                 c += 64;
221                 m += 64;
222         }
223 }