• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 chacha-merged.c version 20080118
3 D. J. Bernstein
4 Public domain.
5 */
6 
7 #include <libwebsockets.h>
8 #include "lws-ssh.h"
9 
10 #include <string.h>
11 #include <stdlib.h>
12 
13 struct chacha_ctx {
14 	u_int input[16];
15 };
16 
17 #define CHACHA_MINKEYLEN 	16
18 #define CHACHA_NONCELEN		8
19 #define CHACHA_CTRLEN		8
20 #define CHACHA_STATELEN		(CHACHA_NONCELEN+CHACHA_CTRLEN)
21 #define CHACHA_BLOCKLEN		64
22 
23 typedef unsigned char u8;
24 typedef unsigned int u32;
25 
26 typedef struct chacha_ctx chacha_ctx;
27 
28 #define U8C(v) (v##U)
29 #define U32C(v) (v##U)
30 
31 #define U8V(v) ((u8)(v) & U8C(0xFF))
32 #define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF))
33 
34 #define ROTL32(v, n) \
35   (U32V((v) << (n)) | ((v) >> (32 - (n))))
36 
37 #define U8TO32_LITTLE(p) \
38   (((u32)((p)[0])      ) | \
39    ((u32)((p)[1]) <<  8) | \
40    ((u32)((p)[2]) << 16) | \
41    ((u32)((p)[3]) << 24))
42 
43 #define U32TO8_LITTLE(p, v) \
44   do { \
45     (p)[0] = U8V((v)      ); \
46     (p)[1] = U8V((v) >>  8); \
47     (p)[2] = U8V((v) >> 16); \
48     (p)[3] = U8V((v) >> 24); \
49   } while (0)
50 
51 #define ROTATE(v,c) (ROTL32(v,c))
52 #define XOR(v,w) ((v) ^ (w))
53 #define PLUS(v,w) (U32V((v) + (w)))
54 #define PLUSONE(v) (PLUS((v),1))
55 
56 #define QUARTERROUND(a,b,c,d) \
57   a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \
58   c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \
59   a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \
60   c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);
61 
62 static const char sigma[16] = "expand 32-byte k";
63 static const char tau[16] = "expand 16-byte k";
64 
65 void
chacha_keysetup(chacha_ctx * x,const u8 * k,u32 kbits)66 chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits)
67 {
68   const char *constants;
69 
70   x->input[4] = U8TO32_LITTLE(k + 0);
71   x->input[5] = U8TO32_LITTLE(k + 4);
72   x->input[6] = U8TO32_LITTLE(k + 8);
73   x->input[7] = U8TO32_LITTLE(k + 12);
74   if (kbits == 256) { /* recommended */
75     k += 16;
76     constants = sigma;
77   } else { /* kbits == 128 */
78     constants = tau;
79   }
80   x->input[8] = U8TO32_LITTLE(k + 0);
81   x->input[9] = U8TO32_LITTLE(k + 4);
82   x->input[10] = U8TO32_LITTLE(k + 8);
83   x->input[11] = U8TO32_LITTLE(k + 12);
84   x->input[0] = U8TO32_LITTLE(constants + 0);
85   x->input[1] = U8TO32_LITTLE(constants + 4);
86   x->input[2] = U8TO32_LITTLE(constants + 8);
87   x->input[3] = U8TO32_LITTLE(constants + 12);
88 }
89 
90 void
chacha_ivsetup(chacha_ctx * x,const u8 * iv,const u8 * counter)91 chacha_ivsetup(chacha_ctx *x, const u8 *iv, const u8 *counter)
92 {
93   x->input[12] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 0);
94   x->input[13] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 4);
95   x->input[14] = U8TO32_LITTLE(iv + 0);
96   x->input[15] = U8TO32_LITTLE(iv + 4);
97 }
98 
99 void
chacha_encrypt_bytes(chacha_ctx * x,const u8 * m,u8 * c,u32 bytes)100 chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes)
101 {
102   u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
103   u32 j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
104   u8 *ctarget = NULL;
105   u8 tmp[64];
106   u_int i;
107 
108   if (!bytes) return;
109 
110   j0 = x->input[0];
111   j1 = x->input[1];
112   j2 = x->input[2];
113   j3 = x->input[3];
114   j4 = x->input[4];
115   j5 = x->input[5];
116   j6 = x->input[6];
117   j7 = x->input[7];
118   j8 = x->input[8];
119   j9 = x->input[9];
120   j10 = x->input[10];
121   j11 = x->input[11];
122   j12 = x->input[12];
123   j13 = x->input[13];
124   j14 = x->input[14];
125   j15 = x->input[15];
126 
127   for (;;) {
128     if (bytes < 64) {
129       for (i = 0;i < bytes;++i) tmp[i] = m[i];
130       m = tmp;
131       ctarget = c;
132       c = tmp;
133     }
134     x0 = j0;
135     x1 = j1;
136     x2 = j2;
137     x3 = j3;
138     x4 = j4;
139     x5 = j5;
140     x6 = j6;
141     x7 = j7;
142     x8 = j8;
143     x9 = j9;
144     x10 = j10;
145     x11 = j11;
146     x12 = j12;
147     x13 = j13;
148     x14 = j14;
149     x15 = j15;
150     for (i = 20;i > 0;i -= 2) {
151       QUARTERROUND( x0, x4, x8,x12)
152       QUARTERROUND( x1, x5, x9,x13)
153       QUARTERROUND( x2, x6,x10,x14)
154       QUARTERROUND( x3, x7,x11,x15)
155       QUARTERROUND( x0, x5,x10,x15)
156       QUARTERROUND( x1, x6,x11,x12)
157       QUARTERROUND( x2, x7, x8,x13)
158       QUARTERROUND( x3, x4, x9,x14)
159     }
160     x0 = PLUS(x0,j0);
161     x1 = PLUS(x1,j1);
162     x2 = PLUS(x2,j2);
163     x3 = PLUS(x3,j3);
164     x4 = PLUS(x4,j4);
165     x5 = PLUS(x5,j5);
166     x6 = PLUS(x6,j6);
167     x7 = PLUS(x7,j7);
168     x8 = PLUS(x8,j8);
169     x9 = PLUS(x9,j9);
170     x10 = PLUS(x10,j10);
171     x11 = PLUS(x11,j11);
172     x12 = PLUS(x12,j12);
173     x13 = PLUS(x13,j13);
174     x14 = PLUS(x14,j14);
175     x15 = PLUS(x15,j15);
176 
177     x0 = XOR(x0,U8TO32_LITTLE(m + 0));
178     x1 = XOR(x1,U8TO32_LITTLE(m + 4));
179     x2 = XOR(x2,U8TO32_LITTLE(m + 8));
180     x3 = XOR(x3,U8TO32_LITTLE(m + 12));
181     x4 = XOR(x4,U8TO32_LITTLE(m + 16));
182     x5 = XOR(x5,U8TO32_LITTLE(m + 20));
183     x6 = XOR(x6,U8TO32_LITTLE(m + 24));
184     x7 = XOR(x7,U8TO32_LITTLE(m + 28));
185     x8 = XOR(x8,U8TO32_LITTLE(m + 32));
186     x9 = XOR(x9,U8TO32_LITTLE(m + 36));
187     x10 = XOR(x10,U8TO32_LITTLE(m + 40));
188     x11 = XOR(x11,U8TO32_LITTLE(m + 44));
189     x12 = XOR(x12,U8TO32_LITTLE(m + 48));
190     x13 = XOR(x13,U8TO32_LITTLE(m + 52));
191     x14 = XOR(x14,U8TO32_LITTLE(m + 56));
192     x15 = XOR(x15,U8TO32_LITTLE(m + 60));
193 
194     j12 = PLUSONE(j12);
195     if (!j12)
196       j13 = PLUSONE(j13);
197       /* stopping at 2^70 bytes per nonce is user's responsibility */
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 < bytes;++i) ctarget[i] = c[i];
219       }
220       x->input[12] = j12;
221       x->input[13] = j13;
222       return;
223     }
224     bytes -= 64;
225     c += 64;
226     m += 64;
227   }
228 }
229 
230 struct lws_cipher_chacha {
231 	struct chacha_ctx ccctx[2];
232 };
233 
234 #define K_1(_keys) &((struct lws_cipher_chacha *)_keys->cipher)->ccctx[0]
235 #define K_2(_keys) &((struct lws_cipher_chacha *)_keys->cipher)->ccctx[1]
236 
237 int
lws_chacha_activate(struct lws_ssh_keys * keys)238 lws_chacha_activate(struct lws_ssh_keys *keys)
239 {
240 	if (keys->cipher) {
241 		free(keys->cipher);
242 		keys->cipher = NULL;
243 	}
244 
245 	keys->cipher = malloc(sizeof(struct lws_cipher_chacha));
246 	if (!keys->cipher)
247 		return 1;
248 
249 	memset(keys->cipher, 0, sizeof(struct lws_cipher_chacha));
250 
251 	/* uses 2 x 256-bit keys, so 512 bits (64 bytes) needed */
252 	chacha_keysetup(K_2(keys), keys->key[SSH_KEYIDX_ENC], 256);
253 	chacha_keysetup(K_1(keys), &keys->key[SSH_KEYIDX_ENC][32], 256);
254 
255 	keys->valid = 1;
256 	keys->full_length = 1;
257 	keys->padding_alignment = 8; // CHACHA_BLOCKLEN;
258 	keys->MAC_length = POLY1305_TAGLEN;
259 
260 	return 0;
261 }
262 
263 void
lws_chacha_destroy(struct lws_ssh_keys * keys)264 lws_chacha_destroy(struct lws_ssh_keys *keys)
265 {
266 	if (keys->cipher) {
267 		free(keys->cipher);
268 		keys->cipher = NULL;
269 	}
270 }
271 
272 uint32_t
lws_chachapoly_get_length(struct lws_ssh_keys * keys,uint32_t seq,const uint8_t * in4)273 lws_chachapoly_get_length(struct lws_ssh_keys *keys, uint32_t seq,
274 			  const uint8_t *in4)
275 {
276         uint8_t buf[4], seqbuf[8];
277 
278 	/*
279 	 * When receiving a packet, the length must be decrypted first.  When 4
280 	 * bytes of ciphertext length have been received, they may be decrypted
281 	 * using the K_1 key, a nonce consisting of the packet sequence number
282 	 * encoded as a uint64 under the usual SSH wire encoding and a zero
283 	 * block counter to obtain the plaintext length.
284 	 */
285         POKE_U64(seqbuf, seq);
286 	chacha_ivsetup(K_1(keys), seqbuf, NULL);
287         chacha_encrypt_bytes(K_1(keys), in4, buf, 4);
288 
289 	return PEEK_U32(buf);
290 }
291 
292 /*
293  * chachapoly_crypt() operates as following:
294  * En/decrypt with header key 'aadlen' bytes from 'src', storing result
295  * to 'dest'. The ciphertext here is treated as additional authenticated
296  * data for MAC calculation.
297  * En/decrypt 'len' bytes at offset 'aadlen' from 'src' to 'dest'. Use
298  * POLY1305_TAGLEN bytes at offset 'len'+'aadlen' as the authentication
299  * tag. This tag is written on encryption and verified on decryption.
300  */
301 int
chachapoly_crypt(struct lws_ssh_keys * keys,u_int seqnr,u_char * dest,const u_char * src,u_int len,u_int aadlen,u_int authlen,int do_encrypt)302 chachapoly_crypt(struct lws_ssh_keys *keys, u_int seqnr, u_char *dest,
303     const u_char *src, u_int len, u_int aadlen, u_int authlen, int do_encrypt)
304 {
305         u_char seqbuf[8];
306         const u_char one[8] = { 1, 0, 0, 0, 0, 0, 0, 0 }; /* NB little-endian */
307         u_char expected_tag[POLY1305_TAGLEN], poly_key[POLY1305_KEYLEN];
308         int r = 1;
309 
310         /*
311          * Run ChaCha20 once to generate the Poly1305 key. The IV is the
312          * packet sequence number.
313          */
314         memset(poly_key, 0, sizeof(poly_key));
315         POKE_U64(seqbuf, seqnr);
316         chacha_ivsetup(K_2(keys), seqbuf, NULL);
317         chacha_encrypt_bytes(K_2(keys),
318             poly_key, poly_key, sizeof(poly_key));
319 
320         /* If decrypting, check tag before anything else */
321         if (!do_encrypt) {
322                 const u_char *tag = src + aadlen + len;
323 
324                 poly1305_auth(expected_tag, src, aadlen + len, poly_key);
325                 if (lws_timingsafe_bcmp(expected_tag, tag, POLY1305_TAGLEN)) {
326                         r = 2;
327                         goto out;
328                 }
329         }
330 
331         /* Crypt additional data */
332         if (aadlen) {
333                 chacha_ivsetup(K_1(keys), seqbuf, NULL);
334                 chacha_encrypt_bytes(K_1(keys), src, dest, aadlen);
335         }
336 
337         /* Set Chacha's block counter to 1 */
338         chacha_ivsetup(K_2(keys), seqbuf, one);
339         chacha_encrypt_bytes(K_2(keys), src + aadlen, dest + aadlen, len);
340 
341         /* If encrypting, calculate and append tag */
342         if (do_encrypt) {
343                 poly1305_auth(dest + aadlen + len, dest, aadlen + len,
344                     poly_key);
345         }
346         r = 0;
347  out:
348         lws_explicit_bzero(expected_tag, sizeof(expected_tag));
349         lws_explicit_bzero(seqbuf, sizeof(seqbuf));
350         lws_explicit_bzero(poly_key, sizeof(poly_key));
351         return r;
352 }
353 
354 int
lws_chacha_decrypt(struct lws_ssh_keys * keys,uint32_t seq,const uint8_t * ct,uint32_t len,uint8_t * pt)355 lws_chacha_decrypt(struct lws_ssh_keys *keys, uint32_t seq,
356 		   const uint8_t *ct, uint32_t len, uint8_t *pt)
357 {
358 	return chachapoly_crypt(keys, seq, pt, ct, len - POLY1305_TAGLEN - 4, 4,
359 			 POLY1305_TAGLEN, 0);
360 }
361 
362 int
lws_chacha_encrypt(struct lws_ssh_keys * keys,uint32_t seq,const uint8_t * ct,uint32_t len,uint8_t * pt)363 lws_chacha_encrypt(struct lws_ssh_keys *keys, uint32_t seq,
364 		   const uint8_t *ct, uint32_t len, uint8_t *pt)
365 {
366 	return chachapoly_crypt(keys, seq, pt, ct, len - 4, 4, 0, 1);
367 }
368 
369