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