Commit | Line | Data |
---|---|---|
194e93f2 MW |
1 | /* -*-c-*- |
2 | * | |
3 | * Salsa20 stream cipher | |
4 | * | |
5 | * (c) 2015 Straylight/Edgeware | |
6 | */ | |
7 | ||
0a847b11 MW |
8 | /*----- Licensing notice --------------------------------------------------* |
9 | * | |
10 | * This file is part of Catacomb. | |
11 | * | |
12 | * Catacomb is free software; you can redistribute it and/or modify | |
13 | * it under the terms of the GNU Library General Public License as | |
14 | * published by the Free Software Foundation; either version 2 of the | |
15 | * License, or (at your option) any later version. | |
16 | * | |
17 | * Catacomb is distributed in the hope that it will be useful, | |
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
20 | * GNU Library General Public License for more details. | |
21 | * | |
22 | * You should have received a copy of the GNU Library General Public | |
23 | * License along with Catacomb; if not, write to the Free | |
24 | * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, | |
25 | * MA 02111-1307, USA. | |
26 | */ | |
27 | ||
194e93f2 MW |
28 | #ifndef CATACOMB_SALSA20_H |
29 | #define CATACOMB_SALSA20_H | |
30 | ||
31 | #ifdef __cplusplus | |
32 | extern "C" { | |
33 | #endif | |
34 | ||
35 | /*----- Header files ------------------------------------------------------*/ | |
36 | ||
37 | #include <mLib/bits.h> | |
38 | ||
39 | #ifndef CATACOMB_GCIPHER_H | |
40 | # include "gcipher.h" | |
41 | #endif | |
42 | ||
43 | #ifndef CATACOMB_GRAND_H | |
44 | # include "grand.h" | |
45 | #endif | |
46 | ||
47 | /*----- Constants ---------------------------------------------------------*/ | |
48 | ||
49 | #define SALSA20_NONCESZ 8u | |
1778ca95 | 50 | #define SALSA20_IETF_NONCESZ 12u |
194e93f2 MW |
51 | #define SALSA20_KEYSZ 32u |
52 | #define SALSA20_OUTSZ 64u | |
53 | ||
54 | #define HSALSA20_INSZ 16u | |
55 | #define HSALSA20_OUTSZ 32u | |
56 | ||
57 | #define XSALSA20_NONCESZ 24u | |
58 | #define XSALSA20_KEYSZ SALSA20_KEYSZ | |
59 | #define XSALSA20_OUTSZ SALSA20_OUTSZ | |
60 | ||
61 | /*----- Data structures ---------------------------------------------------*/ | |
62 | ||
63 | typedef uint32 salsa20_matrix[16]; | |
64 | ||
65 | typedef struct salsa20_ctx { | |
66 | salsa20_matrix a; | |
67 | octet buf[SALSA20_OUTSZ]; | |
68 | size_t bufi; | |
69 | } salsa20_ctx; | |
70 | ||
71 | #define XSALSA20_DEFCTX(name) \ | |
72 | typedef struct name { salsa20_ctx s; salsa20_matrix k; } name | |
73 | XSALSA20_DEFCTX(xsalsa20_ctx); | |
74 | XSALSA20_DEFCTX(xsalsa2012_ctx); | |
75 | XSALSA20_DEFCTX(xsalsa208_ctx); | |
76 | ||
77 | /*----- The Salsa20 stream cipher -----------------------------------------*/ | |
78 | ||
79 | /* --- @salsa20_init@ --- * | |
80 | * | |
81 | * Arguments: @salsa20_ctx *ctx@ = context to fill in | |
82 | * @const void *key@ = pointer to key material | |
83 | * @size_t ksz@ = size of key (either 32 or 16) | |
84 | * @const void *nonce@ = initial nonce, or null | |
85 | * | |
86 | * Returns: --- | |
87 | * | |
88 | * Use: Initializes a Salsa20 context ready for use. | |
89 | */ | |
90 | ||
91 | extern void salsa20_init(salsa20_ctx */*ctx*/, | |
92 | const void */*key*/, size_t /*ksz*/, | |
93 | const void */*nonce*/); | |
94 | ||
1778ca95 | 95 | /* --- @salsa20_setnonce{,_ietf}@ --- * |
194e93f2 MW |
96 | * |
97 | * Arguments: @salsa20_ctx *ctx@ = pointer to context | |
1778ca95 MW |
98 | * @const void *nonce@ = the nonce (@SALSA20_NONCESZ@ or |
99 | * @SALSA20_IETF_NONCESZ@ bytes) | |
194e93f2 MW |
100 | * |
101 | * Returns: --- | |
102 | * | |
103 | * Use: Set a new nonce in the context @ctx@, e.g., for processing a | |
104 | * different message. The stream position is reset to zero (see | |
105 | * @salsa20_seek@ etc.). | |
106 | */ | |
107 | ||
108 | extern void salsa20_setnonce(salsa20_ctx */*ctx*/, const void */*nonce*/); | |
1778ca95 MW |
109 | extern void salsa20_setnonce_ietf(salsa20_ctx */*ctx*/, |
110 | const void */*nonce*/); | |
194e93f2 | 111 | |
1778ca95 | 112 | /* --- @salsa20_seek{,u64,_ietf}@ --- * |
194e93f2 MW |
113 | * |
114 | * Arguments: @salsa20_ctx *ctx@ = pointer to context | |
115 | * @unsigned long i@, @kludge64 i@ = new position to set | |
116 | * | |
117 | * Returns: --- | |
118 | * | |
119 | * Use: Sets a new stream position, in units of Salsa20 output | |
120 | * blocks, which are @SALSA20_OUTSZ@ bytes each. Byte | |
121 | * granularity can be achieved by calling @salsa20_encrypt@ | |
122 | * appropriately. | |
123 | */ | |
124 | ||
125 | extern void salsa20_seek(salsa20_ctx */*ctx*/, unsigned long /*i*/); | |
126 | extern void salsa20_seeku64(salsa20_ctx */*ctx*/, kludge64 /*i*/); | |
1778ca95 | 127 | extern void salsa20_seek_ietf(salsa20_ctx */*ctx*/, uint32 /*i*/); |
194e93f2 | 128 | |
1778ca95 | 129 | /* --- @salsa20_tell{,u64,_ietf}@ --- * |
194e93f2 MW |
130 | * |
131 | * Arguments: @salsa20_ctx *ctx@ = pointer to context | |
132 | * | |
133 | * Returns: The current position in the output stream, in blocks, | |
134 | * rounding upwards. | |
135 | */ | |
136 | ||
137 | extern unsigned long salsa20_tell(salsa20_ctx */*ctx*/); | |
138 | extern kludge64 salsa20_tellu64(salsa20_ctx */*ctx*/); | |
1778ca95 | 139 | extern uint32 salsa20_tell_ietf(salsa20_ctx */*ctx*/); |
194e93f2 MW |
140 | |
141 | /* --- @salsa20{,12,8}_encrypt@ --- * | |
142 | * | |
143 | * Arguments: @salsa20_ctx *ctx@ = pointer to context | |
144 | * @const void *src@ = source buffer (or null) | |
145 | * @void *dest@ = destination buffer (or null) | |
146 | * @size_t sz@ = size of the buffers | |
147 | * | |
148 | * Returns: --- | |
149 | * | |
150 | * Use: Encrypts or decrypts @sz@ bytes of data from @src@ to @dest@. | |
151 | * Salsa20 works by XORing plaintext with a keystream, so | |
152 | * encryption and decryption are the same operation. If @dest@ | |
153 | * is null then ignore @src@ and skip @sz@ bytes of the | |
154 | * keystream. If @src@ is null, then just write the keystream | |
155 | * to @dest@. | |
156 | */ | |
157 | ||
158 | extern void salsa20_encrypt(salsa20_ctx */*ctx*/, | |
159 | const void */*src*/, void */*dest*/, | |
160 | size_t /*sz*/); | |
161 | extern void salsa2012_encrypt(salsa20_ctx */*ctx*/, | |
162 | const void */*src*/, void */*dest*/, | |
163 | size_t /*sz*/); | |
164 | extern void salsa208_encrypt(salsa20_ctx */*ctx*/, | |
165 | const void */*src*/, void */*dest*/, | |
166 | size_t /*sz*/); | |
167 | ||
168 | /*----- The HSalsa20 pseudorandom function --------------------------------*/ | |
169 | ||
170 | /* --- @hsalsa20{,12,8}_prf@ --- * | |
171 | * | |
172 | * Arguments: @salsa20_ctx *ctx@ = pointer to context | |
173 | * @const void *src@ = the input (@HSALSA20_INSZ@ bytes) | |
174 | * @void *dest@ = the output (@HSALSA20_OUTSZ@ bytes) | |
175 | * | |
176 | * Returns: --- | |
177 | * | |
178 | * Use: Apply the HSalsa20/r pseudorandom function to @src@, writing | |
179 | * the result to @out@. | |
180 | */ | |
181 | ||
182 | extern void hsalsa20_prf(salsa20_ctx */*ctx*/, | |
183 | const void */*src*/, void */*dest*/); | |
184 | extern void hsalsa2012_prf(salsa20_ctx */*ctx*/, | |
185 | const void */*src*/, void */*dest*/); | |
186 | extern void hsalsa208_prf(salsa20_ctx */*ctx*/, | |
187 | const void */*src*/, void */*dest*/); | |
188 | ||
189 | /*----- The XSalsa20 stream cipher ----------------------------------------*/ | |
190 | ||
191 | /* --- @xsalsa20{,12,8}_init@ --- * | |
192 | * | |
193 | * Arguments: @xsalsa20R_ctx *ctx@ = the context to fill in | |
194 | * @const void *key@ = pointer to key material | |
195 | * @size_t ksz@ = size of key (either 32 or 16) | |
196 | * @const void *nonce@ = initial nonce, or null | |
197 | * | |
198 | * Returns: --- | |
199 | * | |
200 | * Use: Initializes an XSalsa20/r context ready for use. | |
201 | * | |
202 | * There is a different function for each number of rounds, | |
203 | * unlike for plain Salsa20. | |
204 | */ | |
205 | ||
206 | extern void xsalsa20_init(xsalsa20_ctx */*ctx*/, | |
207 | const void */*key*/, size_t /*ksz*/, | |
208 | const void */*nonce*/); | |
209 | extern void xsalsa2012_init(xsalsa2012_ctx */*ctx*/, | |
210 | const void */*key*/, size_t /*ksz*/, | |
211 | const void */*nonce*/); | |
212 | extern void xsalsa208_init(xsalsa208_ctx */*ctx*/, | |
213 | const void */*key*/, size_t /*ksz*/, | |
214 | const void */*nonce*/); | |
215 | ||
216 | /* --- @xsalsa20{,12,8}_setnonce@ --- * | |
217 | * | |
218 | * Arguments: @xsalsa20R_ctx *ctx@ = pointer to context | |
219 | * @const void *nonce@ = the nonce (@XSALSA20_NONCESZ@ bytes) | |
220 | * | |
221 | * Returns: --- | |
222 | * | |
223 | * Use: Set a new nonce in the context @ctx@, e.g., for processing a | |
224 | * different message. The stream position is reset to zero (see | |
225 | * @salsa20_seek@ etc.). | |
226 | * | |
227 | * There is a different function for each number of rounds, | |
228 | * unlike for plain Salsa20. | |
229 | */ | |
230 | ||
231 | extern void xsalsa20_setnonce(xsalsa20_ctx */*ctx*/, | |
232 | const void */*nonce*/); | |
233 | extern void xsalsa2012_setnonce(xsalsa2012_ctx */*ctx*/, | |
234 | const void */*nonce*/); | |
235 | extern void xsalsa208_setnonce(xsalsa208_ctx */*ctx*/, | |
236 | const void */*nonce*/); | |
237 | ||
1778ca95 | 238 | /* --- @xsalsa20{,12,8}_seek@, @xsalsa20{,12,8}_seeku64@ --- * |
194e93f2 MW |
239 | * |
240 | * Arguments: @xsalsa20R_ctx *ctx@ = pointer to context | |
241 | * @unsigned long i@, @kludge64 i@ = new position to set | |
242 | * | |
243 | * Returns: --- | |
244 | * | |
245 | * Use: Sets a new stream position, in units of Salsa20 output | |
246 | * blocks, which are @XSALSA20_OUTSZ@ bytes each. Byte | |
247 | * granularity can be achieved by calling @xsalsa20R_encrypt@ | |
248 | * appropriately. | |
249 | * | |
250 | * There is a different function for each number of rounds, | |
251 | * unlike for plain Salsa20, because the context structures are | |
252 | * different. | |
253 | */ | |
254 | ||
255 | extern void xsalsa20_seek(xsalsa20_ctx */*ctx*/, unsigned long /*i*/); | |
256 | extern void xsalsa2012_seek(xsalsa2012_ctx */*ctx*/, unsigned long /*i*/); | |
257 | extern void xsalsa208_seek(xsalsa208_ctx */*ctx*/, unsigned long /*i*/); | |
258 | extern void xsalsa20_seeku64(xsalsa20_ctx */*ctx*/, kludge64 /*i*/); | |
259 | extern void xsalsa2012_seeku64(xsalsa2012_ctx */*ctx*/, kludge64 /*i*/); | |
260 | extern void xsalsa208_seeku64(xsalsa208_ctx */*ctx*/, kludge64 /*i*/); | |
261 | ||
1778ca95 | 262 | /* --- @xsalsa20{,12,8}_tell@, @xsalsa20{,12,8}_tellu64@ --- * |
194e93f2 MW |
263 | * |
264 | * Arguments: @salsa20_ctx *ctx@ = pointer to context | |
265 | * | |
266 | * Returns: The current position in the output stream, in blocks, | |
267 | * rounding upwards. | |
268 | * | |
269 | * There is a different function for each number of rounds, | |
270 | * unlike for plain Salsa20, because the context structures are | |
271 | * different. | |
272 | */ | |
273 | ||
274 | extern unsigned long xsalsa20_tell(xsalsa20_ctx */*ctx*/); | |
275 | extern unsigned long xsalsa2012_tell(xsalsa2012_ctx */*ctx*/); | |
276 | extern unsigned long xsalsa208_tell(xsalsa208_ctx */*ctx*/); | |
277 | extern kludge64 xsalsa20_tellu64(xsalsa20_ctx */*ctx*/); | |
278 | extern kludge64 xsalsa2012_tellu64(xsalsa2012_ctx */*ctx*/); | |
279 | extern kludge64 xsalsa208_tellu64(xsalsa208_ctx */*ctx*/); | |
280 | ||
281 | /* --- @xsalsa20{,12,8}_encrypt@ --- * | |
282 | * | |
283 | * Arguments: @xsalsa20R_ctx *ctx@ = pointer to context | |
284 | * @const void *src@ = source buffer (or null) | |
285 | * @void *dest@ = destination buffer (or null) | |
286 | * @size_t sz@ = size of the buffers | |
287 | * | |
288 | * Returns: --- | |
289 | * | |
290 | * Use: Encrypts or decrypts @sz@ bytes of data from @src@ to @dest@. | |
291 | * XSalsa20 works by XORing plaintext with a keystream, so | |
292 | * encryption and decryption are the same operation. If @dest@ | |
293 | * is null then ignore @src@ and skip @sz@ bytes of the | |
294 | * keystream. If @src@ is null, then just write the keystream | |
295 | * to @dest@. | |
296 | */ | |
297 | ||
298 | extern void xsalsa20_encrypt(xsalsa20_ctx */*ctx*/, | |
299 | const void */*src*/, void */*dest*/, | |
300 | size_t /*sz*/); | |
301 | extern void xsalsa2012_encrypt(xsalsa2012_ctx */*ctx*/, | |
302 | const void */*src*/, void */*dest*/, | |
303 | size_t /*sz*/); | |
304 | extern void xsalsa208_encrypt(xsalsa208_ctx */*ctx*/, | |
305 | const void */*src*/, void */*dest*/, | |
306 | size_t /*sz*/); | |
307 | ||
308 | /*----- Generic cipher interface ------------------------------------------*/ | |
309 | ||
310 | extern const octet salsa20_keysz[]; | |
311 | #define salsa2012_keysz salsa20_keysz | |
312 | #define salsa208_keysz salsa20_keysz | |
1778ca95 MW |
313 | #define salsa20_ietf_keysz salsa20_keysz |
314 | #define salsa2012_ietf_keysz salsa20_keysz | |
315 | #define salsa208_ietf_keysz salsa20_keysz | |
194e93f2 MW |
316 | #define xsalsa20_keysz salsa20_keysz |
317 | #define xsalsa2012_keysz salsa20_keysz | |
318 | #define xsalsa208_keysz salsa20_keysz | |
319 | ||
6a265416 MW |
320 | extern const gccipher salsa20, salsa2012, salsa208; |
321 | extern const gccipher salsa20_ietf, salsa2012_ietf, salsa208_ietf; | |
322 | extern const gccipher xsalsa20, xsalsa2012, xsalsa208; | |
194e93f2 MW |
323 | |
324 | /*----- Generic random number generator interface -------------------------*/ | |
325 | ||
1778ca95 | 326 | /* --- @salsa20{,12,8}{,_ietf}_rand@, @xsalsa20{,12,8}{,_ietf}_rand@ --- * |
194e93f2 MW |
327 | * |
328 | * Arguments: @const void *k@ = pointer to key material | |
329 | * @size_t ksz@ = size of key material | |
330 | * @const void *n@ = pointer to nonce or null | |
1778ca95 MW |
331 | * (@SALSA20_NONCESZ@, @SALSA20_IETF_NONCESZ@, |
332 | * or @XSALSA20_NONCESZ@) | |
194e93f2 MW |
333 | * |
334 | * Returns: Pointer to generic random number generator instance. | |
335 | * | |
336 | * Use: Creates a random number interface wrapper around | |
337 | * the Salsa20/r or XSalsa20/r stream ciphers. | |
338 | */ | |
339 | ||
340 | extern grand *salsa20_rand(const void */*k*/, size_t /*ksz*/, | |
341 | const void */*n*/); | |
342 | extern grand *salsa2012_rand(const void */*k*/, size_t /*ksz*/, | |
343 | const void */*n*/); | |
344 | extern grand *salsa208_rand(const void */*k*/, size_t /*ksz*/, | |
345 | const void */*n*/); | |
1778ca95 MW |
346 | extern grand *salsa20_ietf_rand(const void */*k*/, size_t /*ksz*/, |
347 | const void */*n*/); | |
348 | extern grand *salsa2012_ietf_rand(const void */*k*/, size_t /*ksz*/, | |
349 | const void */*n*/); | |
350 | extern grand *salsa208_ietf_rand(const void */*k*/, size_t /*ksz*/, | |
351 | const void */*n*/); | |
194e93f2 MW |
352 | extern grand *xsalsa20_rand(const void */*k*/, size_t /*ksz*/, |
353 | const void */*n*/); | |
354 | extern grand *xsalsa2012_rand(const void */*k*/, size_t /*ksz*/, | |
355 | const void */*n*/); | |
356 | extern grand *xsalsa208_rand(const void */*k*/, size_t /*ksz*/, | |
357 | const void */*n*/); | |
358 | ||
359 | enum { | |
360 | SALSA20_SEEK = GRAND_SPECIFIC('S'), /* @unsigned long pos@ */ | |
361 | SALSA20_SEEKU64, /* @kludge64 pos@ */ | |
362 | SALSA20_TELL, /* @unsigned long *pos@ */ | |
363 | SALSA20_TELLU64 /* @kludge64 *pos@ */ | |
364 | }; | |
365 | ||
366 | /*----- That's all, folks -------------------------------------------------*/ | |
367 | ||
368 | #ifdef __cplusplus | |
369 | } | |
370 | #endif | |
371 | ||
372 | #endif |