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