Branch data Line data Source code
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 : : #define U8C(v) (v##U)
18 : : #define U32C(v) (v##U)
19 : :
20 : : #define U8V(v) ((u8)(v) & U8C(0xFF))
21 : : #define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF))
22 : :
23 : : #define ROTL32(v, n) \
24 : : (U32V((v) << (n)) | ((v) >> (32 - (n))))
25 : :
26 : : #define U8TO32_LITTLE(p) \
27 : : (((u32)((p)[0]) ) | \
28 : : ((u32)((p)[1]) << 8) | \
29 : : ((u32)((p)[2]) << 16) | \
30 : : ((u32)((p)[3]) << 24))
31 : :
32 : : #define U32TO8_LITTLE(p, v) \
33 : : do { \
34 : : (p)[0] = U8V((v) ); \
35 : : (p)[1] = U8V((v) >> 8); \
36 : : (p)[2] = U8V((v) >> 16); \
37 : : (p)[3] = U8V((v) >> 24); \
38 : : } while (0)
39 : :
40 : : #define ROTATE(v,c) (ROTL32(v,c))
41 : : #define XOR(v,w) ((v) ^ (w))
42 : : #define PLUS(v,w) (U32V((v) + (w)))
43 : : #define PLUSONE(v) (PLUS((v),1))
44 : :
45 : : #define QUARTERROUND(a,b,c,d) \
46 : : a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \
47 : : c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \
48 : : a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \
49 : : 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 : 13692 : chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits,u32 ivbits)
56 : : {
57 : : const char *constants;
58 : :
59 : 6846 : x->input[4] = U8TO32_LITTLE(k + 0);
60 : 6846 : x->input[5] = U8TO32_LITTLE(k + 4);
61 : 6846 : x->input[6] = U8TO32_LITTLE(k + 8);
62 : 6846 : x->input[7] = U8TO32_LITTLE(k + 12);
63 [ + - ]: 6846 : if (kbits == 256) { /* recommended */
64 : 6846 : k += 16;
65 : 6846 : constants = sigma;
66 : : } else { /* kbits == 128 */
67 : : constants = tau;
68 : : }
69 : 6846 : x->input[8] = U8TO32_LITTLE(k + 0);
70 : 6846 : x->input[9] = U8TO32_LITTLE(k + 4);
71 : 6846 : x->input[10] = U8TO32_LITTLE(k + 8);
72 : 6846 : x->input[11] = U8TO32_LITTLE(k + 12);
73 : 6846 : x->input[0] = U8TO32_LITTLE(constants + 0);
74 : 6846 : x->input[1] = U8TO32_LITTLE(constants + 4);
75 : 6846 : x->input[2] = U8TO32_LITTLE(constants + 8);
76 : 6846 : x->input[3] = U8TO32_LITTLE(constants + 12);
77 : 6846 : }
78 : :
79 : : static void
80 : 6846 : chacha_ivsetup(chacha_ctx *x,const u8 *iv)
81 : : {
82 : 6846 : x->input[12] = 0;
83 : 6846 : x->input[13] = 0;
84 : 6846 : x->input[14] = U8TO32_LITTLE(iv + 0);
85 : 6846 : x->input[15] = U8TO32_LITTLE(iv + 4);
86 : 6846 : }
87 : :
88 : : static void
89 : 4475 : chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes)
90 : : {
91 : : u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
92 : : u32 j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
93 : 4475 : u8 *ctarget = NULL;
94 : : u8 tmp[64];
95 : : u_int i;
96 : :
97 [ + - ]: 4475 : if (!bytes) return;
98 : :
99 : 4475 : j0 = x->input[0];
100 : 4475 : j1 = x->input[1];
101 : 4475 : j2 = x->input[2];
102 : 4475 : j3 = x->input[3];
103 : 4475 : j4 = x->input[4];
104 : 4475 : j5 = x->input[5];
105 : 4475 : j6 = x->input[6];
106 : 4475 : j7 = x->input[7];
107 : 4475 : j8 = x->input[8];
108 : 4475 : j9 = x->input[9];
109 : 4475 : j10 = x->input[10];
110 : 4475 : j11 = x->input[11];
111 : 4475 : j12 = x->input[12];
112 : 4475 : j13 = x->input[13];
113 : 4475 : j14 = x->input[14];
114 : 4475 : j15 = x->input[15];
115 : :
116 : : for (;;) {
117 [ - + ]: 71600 : if (bytes < 64) {
118 [ # # ]: 0 : for (i = 0;i < bytes;++i) tmp[i] = m[i];
119 : : m = tmp;
120 : : ctarget = c;
121 : : c = tmp;
122 : : }
123 : 71600 : x0 = j0;
124 : 71600 : x1 = j1;
125 : 71600 : x2 = j2;
126 : 71600 : x3 = j3;
127 : 71600 : x4 = j4;
128 : 71600 : x5 = j5;
129 : 71600 : x6 = j6;
130 : 71600 : x7 = j7;
131 : 71600 : x8 = j8;
132 : 71600 : x9 = j9;
133 : 71600 : x10 = j10;
134 : 71600 : x11 = j11;
135 : 71600 : x12 = j12;
136 : 71600 : x13 = j13;
137 : 71600 : x14 = j14;
138 : 71600 : x15 = j15;
139 [ + + ]: 787600 : for (i = 20;i > 0;i -= 2) {
140 : 716000 : QUARTERROUND( x0, x4, x8,x12)
141 : 716000 : QUARTERROUND( x1, x5, x9,x13)
142 : 716000 : QUARTERROUND( x2, x6,x10,x14)
143 : 716000 : QUARTERROUND( x3, x7,x11,x15)
144 : 716000 : QUARTERROUND( x0, x5,x10,x15)
145 : 716000 : QUARTERROUND( x1, x6,x11,x12)
146 : 716000 : QUARTERROUND( x2, x7, x8,x13)
147 : 716000 : QUARTERROUND( x3, x4, x9,x14)
148 : : }
149 : 71600 : x0 = PLUS(x0,j0);
150 : 71600 : x1 = PLUS(x1,j1);
151 : 71600 : x2 = PLUS(x2,j2);
152 : 71600 : x3 = PLUS(x3,j3);
153 : 71600 : x4 = PLUS(x4,j4);
154 : 71600 : x5 = PLUS(x5,j5);
155 : 71600 : x6 = PLUS(x6,j6);
156 : 71600 : x7 = PLUS(x7,j7);
157 : 71600 : x8 = PLUS(x8,j8);
158 : 71600 : x9 = PLUS(x9,j9);
159 : 71600 : x10 = PLUS(x10,j10);
160 : 71600 : x11 = PLUS(x11,j11);
161 : 71600 : x12 = PLUS(x12,j12);
162 : 71600 : x13 = PLUS(x13,j13);
163 : 71600 : x14 = PLUS(x14,j14);
164 : 71600 : 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 : 71600 : j12 = PLUSONE(j12);
186 [ - + ]: 71600 : if (!j12) {
187 : 0 : j13 = PLUSONE(j13);
188 : : /* stopping at 2^70 bytes per nonce is user's responsibility */
189 : : }
190 : :
191 : 71600 : U32TO8_LITTLE(c + 0,x0);
192 : 71600 : U32TO8_LITTLE(c + 4,x1);
193 : 71600 : U32TO8_LITTLE(c + 8,x2);
194 : 71600 : U32TO8_LITTLE(c + 12,x3);
195 : 71600 : U32TO8_LITTLE(c + 16,x4);
196 : 71600 : U32TO8_LITTLE(c + 20,x5);
197 : 71600 : U32TO8_LITTLE(c + 24,x6);
198 : 71600 : U32TO8_LITTLE(c + 28,x7);
199 : 71600 : U32TO8_LITTLE(c + 32,x8);
200 : 71600 : U32TO8_LITTLE(c + 36,x9);
201 : 71600 : U32TO8_LITTLE(c + 40,x10);
202 : 71600 : U32TO8_LITTLE(c + 44,x11);
203 : 71600 : U32TO8_LITTLE(c + 48,x12);
204 : 71600 : U32TO8_LITTLE(c + 52,x13);
205 : 71600 : U32TO8_LITTLE(c + 56,x14);
206 : 71600 : U32TO8_LITTLE(c + 60,x15);
207 : :
208 [ + + ]: 71600 : if (bytes <= 64) {
209 [ - + ]: 4475 : if (bytes < 64) {
210 [ # # ]: 0 : for (i = 0;i < bytes;++i) ctarget[i] = c[i];
211 : : }
212 : 4475 : x->input[12] = j12;
213 : 4475 : x->input[13] = j13;
214 : 4475 : return;
215 : : }
216 : 67125 : bytes -= 64;
217 : 67125 : c += 64;
218 : : #ifndef KEYSTREAM_ONLY
219 : : m += 64;
220 : : #endif
221 : 67125 : }
222 : : }
|