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