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 | |
50 | #define SALSA20_KEYSZ 32u | |
51 | #define SALSA20_OUTSZ 64u | |
52 | ||
53 | #define HSALSA20_INSZ 16u | |
54 | #define HSALSA20_OUTSZ 32u | |
55 | ||
56 | #define XSALSA20_NONCESZ 24u | |
57 | #define XSALSA20_KEYSZ SALSA20_KEYSZ | |
58 | #define XSALSA20_OUTSZ SALSA20_OUTSZ | |
59 | ||
60 | /*----- Data structures ---------------------------------------------------*/ | |
61 | ||
62 | typedef uint32 salsa20_matrix[16]; | |
63 | ||
64 | typedef struct salsa20_ctx { | |
65 | salsa20_matrix a; | |
66 | octet buf[SALSA20_OUTSZ]; | |
67 | size_t bufi; | |
68 | } salsa20_ctx; | |
69 | ||
70 | #define XSALSA20_DEFCTX(name) \ | |
71 | typedef struct name { salsa20_ctx s; salsa20_matrix k; } name | |
72 | XSALSA20_DEFCTX(xsalsa20_ctx); | |
73 | XSALSA20_DEFCTX(xsalsa2012_ctx); | |
74 | XSALSA20_DEFCTX(xsalsa208_ctx); | |
75 | ||
76 | /*----- The Salsa20 stream cipher -----------------------------------------*/ | |
77 | ||
78 | /* --- @salsa20_init@ --- * | |
79 | * | |
80 | * Arguments: @salsa20_ctx *ctx@ = context to fill in | |
81 | * @const void *key@ = pointer to key material | |
82 | * @size_t ksz@ = size of key (either 32 or 16) | |
83 | * @const void *nonce@ = initial nonce, or null | |
84 | * | |
85 | * Returns: --- | |
86 | * | |
87 | * Use: Initializes a Salsa20 context ready for use. | |
88 | */ | |
89 | ||
90 | extern void salsa20_init(salsa20_ctx */*ctx*/, | |
91 | const void */*key*/, size_t /*ksz*/, | |
92 | const void */*nonce*/); | |
93 | ||
94 | /* --- @salsa20_setnonce@ --- * | |
95 | * | |
96 | * Arguments: @salsa20_ctx *ctx@ = pointer to context | |
97 | * @const void *nonce@ = the nonce (@SALSA20_NONCESZ@ bytes) | |
98 | * | |
99 | * Returns: --- | |
100 | * | |
101 | * Use: Set a new nonce in the context @ctx@, e.g., for processing a | |
102 | * different message. The stream position is reset to zero (see | |
103 | * @salsa20_seek@ etc.). | |
104 | */ | |
105 | ||
106 | extern void salsa20_setnonce(salsa20_ctx */*ctx*/, const void */*nonce*/); | |
107 | ||
108 | /* --- @salsa20_seek@, @salsa20_seeku64@ --- * | |
109 | * | |
110 | * Arguments: @salsa20_ctx *ctx@ = pointer to context | |
111 | * @unsigned long i@, @kludge64 i@ = new position to set | |
112 | * | |
113 | * Returns: --- | |
114 | * | |
115 | * Use: Sets a new stream position, in units of Salsa20 output | |
116 | * blocks, which are @SALSA20_OUTSZ@ bytes each. Byte | |
117 | * granularity can be achieved by calling @salsa20_encrypt@ | |
118 | * appropriately. | |
119 | */ | |
120 | ||
121 | extern void salsa20_seek(salsa20_ctx */*ctx*/, unsigned long /*i*/); | |
122 | extern void salsa20_seeku64(salsa20_ctx */*ctx*/, kludge64 /*i*/); | |
123 | ||
124 | /* --- @salsa20_tell@, @salsa20_tellu64@ --- * | |
125 | * | |
126 | * Arguments: @salsa20_ctx *ctx@ = pointer to context | |
127 | * | |
128 | * Returns: The current position in the output stream, in blocks, | |
129 | * rounding upwards. | |
130 | */ | |
131 | ||
132 | extern unsigned long salsa20_tell(salsa20_ctx */*ctx*/); | |
133 | extern kludge64 salsa20_tellu64(salsa20_ctx */*ctx*/); | |
134 | ||
135 | /* --- @salsa20{,12,8}_encrypt@ --- * | |
136 | * | |
137 | * Arguments: @salsa20_ctx *ctx@ = pointer to context | |
138 | * @const void *src@ = source buffer (or null) | |
139 | * @void *dest@ = destination buffer (or null) | |
140 | * @size_t sz@ = size of the buffers | |
141 | * | |
142 | * Returns: --- | |
143 | * | |
144 | * Use: Encrypts or decrypts @sz@ bytes of data from @src@ to @dest@. | |
145 | * Salsa20 works by XORing plaintext with a keystream, so | |
146 | * encryption and decryption are the same operation. If @dest@ | |
147 | * is null then ignore @src@ and skip @sz@ bytes of the | |
148 | * keystream. If @src@ is null, then just write the keystream | |
149 | * to @dest@. | |
150 | */ | |
151 | ||
152 | extern void salsa20_encrypt(salsa20_ctx */*ctx*/, | |
153 | const void */*src*/, void */*dest*/, | |
154 | size_t /*sz*/); | |
155 | extern void salsa2012_encrypt(salsa20_ctx */*ctx*/, | |
156 | const void */*src*/, void */*dest*/, | |
157 | size_t /*sz*/); | |
158 | extern void salsa208_encrypt(salsa20_ctx */*ctx*/, | |
159 | const void */*src*/, void */*dest*/, | |
160 | size_t /*sz*/); | |
161 | ||
162 | /*----- The HSalsa20 pseudorandom function --------------------------------*/ | |
163 | ||
164 | /* --- @hsalsa20{,12,8}_prf@ --- * | |
165 | * | |
166 | * Arguments: @salsa20_ctx *ctx@ = pointer to context | |
167 | * @const void *src@ = the input (@HSALSA20_INSZ@ bytes) | |
168 | * @void *dest@ = the output (@HSALSA20_OUTSZ@ bytes) | |
169 | * | |
170 | * Returns: --- | |
171 | * | |
172 | * Use: Apply the HSalsa20/r pseudorandom function to @src@, writing | |
173 | * the result to @out@. | |
174 | */ | |
175 | ||
176 | extern void hsalsa20_prf(salsa20_ctx */*ctx*/, | |
177 | const void */*src*/, void */*dest*/); | |
178 | extern void hsalsa2012_prf(salsa20_ctx */*ctx*/, | |
179 | const void */*src*/, void */*dest*/); | |
180 | extern void hsalsa208_prf(salsa20_ctx */*ctx*/, | |
181 | const void */*src*/, void */*dest*/); | |
182 | ||
183 | /*----- The XSalsa20 stream cipher ----------------------------------------*/ | |
184 | ||
185 | /* --- @xsalsa20{,12,8}_init@ --- * | |
186 | * | |
187 | * Arguments: @xsalsa20R_ctx *ctx@ = the context to fill in | |
188 | * @const void *key@ = pointer to key material | |
189 | * @size_t ksz@ = size of key (either 32 or 16) | |
190 | * @const void *nonce@ = initial nonce, or null | |
191 | * | |
192 | * Returns: --- | |
193 | * | |
194 | * Use: Initializes an XSalsa20/r context ready for use. | |
195 | * | |
196 | * There is a different function for each number of rounds, | |
197 | * unlike for plain Salsa20. | |
198 | */ | |
199 | ||
200 | extern void xsalsa20_init(xsalsa20_ctx */*ctx*/, | |
201 | const void */*key*/, size_t /*ksz*/, | |
202 | const void */*nonce*/); | |
203 | extern void xsalsa2012_init(xsalsa2012_ctx */*ctx*/, | |
204 | const void */*key*/, size_t /*ksz*/, | |
205 | const void */*nonce*/); | |
206 | extern void xsalsa208_init(xsalsa208_ctx */*ctx*/, | |
207 | const void */*key*/, size_t /*ksz*/, | |
208 | const void */*nonce*/); | |
209 | ||
210 | /* --- @xsalsa20{,12,8}_setnonce@ --- * | |
211 | * | |
212 | * Arguments: @xsalsa20R_ctx *ctx@ = pointer to context | |
213 | * @const void *nonce@ = the nonce (@XSALSA20_NONCESZ@ bytes) | |
214 | * | |
215 | * Returns: --- | |
216 | * | |
217 | * Use: Set a new nonce in the context @ctx@, e.g., for processing a | |
218 | * different message. The stream position is reset to zero (see | |
219 | * @salsa20_seek@ etc.). | |
220 | * | |
221 | * There is a different function for each number of rounds, | |
222 | * unlike for plain Salsa20. | |
223 | */ | |
224 | ||
225 | extern void xsalsa20_setnonce(xsalsa20_ctx */*ctx*/, | |
226 | const void */*nonce*/); | |
227 | extern void xsalsa2012_setnonce(xsalsa2012_ctx */*ctx*/, | |
228 | const void */*nonce*/); | |
229 | extern void xsalsa208_setnonce(xsalsa208_ctx */*ctx*/, | |
230 | const void */*nonce*/); | |
231 | ||
232 | /* --- @xsalsa20{,12,8}_seek@, @xsalsa20{,12,8}_seeku64@ --- * | |
233 | * | |
234 | * Arguments: @xsalsa20R_ctx *ctx@ = pointer to context | |
235 | * @unsigned long i@, @kludge64 i@ = new position to set | |
236 | * | |
237 | * Returns: --- | |
238 | * | |
239 | * Use: Sets a new stream position, in units of Salsa20 output | |
240 | * blocks, which are @XSALSA20_OUTSZ@ bytes each. Byte | |
241 | * granularity can be achieved by calling @xsalsa20R_encrypt@ | |
242 | * appropriately. | |
243 | * | |
244 | * There is a different function for each number of rounds, | |
245 | * unlike for plain Salsa20, because the context structures are | |
246 | * different. | |
247 | */ | |
248 | ||
249 | extern void xsalsa20_seek(xsalsa20_ctx */*ctx*/, unsigned long /*i*/); | |
250 | extern void xsalsa2012_seek(xsalsa2012_ctx */*ctx*/, unsigned long /*i*/); | |
251 | extern void xsalsa208_seek(xsalsa208_ctx */*ctx*/, unsigned long /*i*/); | |
252 | extern void xsalsa20_seeku64(xsalsa20_ctx */*ctx*/, kludge64 /*i*/); | |
253 | extern void xsalsa2012_seeku64(xsalsa2012_ctx */*ctx*/, kludge64 /*i*/); | |
254 | extern void xsalsa208_seeku64(xsalsa208_ctx */*ctx*/, kludge64 /*i*/); | |
255 | ||
256 | /* --- @xsalsa20{,12,8}_tell@, @xsalsa20{,12,8}_tellu64@ --- * | |
257 | * | |
258 | * Arguments: @salsa20_ctx *ctx@ = pointer to context | |
259 | * | |
260 | * Returns: The current position in the output stream, in blocks, | |
261 | * rounding upwards. | |
262 | * | |
263 | * There is a different function for each number of rounds, | |
264 | * unlike for plain Salsa20, because the context structures are | |
265 | * different. | |
266 | */ | |
267 | ||
268 | extern unsigned long xsalsa20_tell(xsalsa20_ctx */*ctx*/); | |
269 | extern unsigned long xsalsa2012_tell(xsalsa2012_ctx */*ctx*/); | |
270 | extern unsigned long xsalsa208_tell(xsalsa208_ctx */*ctx*/); | |
271 | extern kludge64 xsalsa20_tellu64(xsalsa20_ctx */*ctx*/); | |
272 | extern kludge64 xsalsa2012_tellu64(xsalsa2012_ctx */*ctx*/); | |
273 | extern kludge64 xsalsa208_tellu64(xsalsa208_ctx */*ctx*/); | |
274 | ||
275 | /* --- @xsalsa20{,12,8}_encrypt@ --- * | |
276 | * | |
277 | * Arguments: @xsalsa20R_ctx *ctx@ = pointer to context | |
278 | * @const void *src@ = source buffer (or null) | |
279 | * @void *dest@ = destination buffer (or null) | |
280 | * @size_t sz@ = size of the buffers | |
281 | * | |
282 | * Returns: --- | |
283 | * | |
284 | * Use: Encrypts or decrypts @sz@ bytes of data from @src@ to @dest@. | |
285 | * XSalsa20 works by XORing plaintext with a keystream, so | |
286 | * encryption and decryption are the same operation. If @dest@ | |
287 | * is null then ignore @src@ and skip @sz@ bytes of the | |
288 | * keystream. If @src@ is null, then just write the keystream | |
289 | * to @dest@. | |
290 | */ | |
291 | ||
292 | extern void xsalsa20_encrypt(xsalsa20_ctx */*ctx*/, | |
293 | const void */*src*/, void */*dest*/, | |
294 | size_t /*sz*/); | |
295 | extern void xsalsa2012_encrypt(xsalsa2012_ctx */*ctx*/, | |
296 | const void */*src*/, void */*dest*/, | |
297 | size_t /*sz*/); | |
298 | extern void xsalsa208_encrypt(xsalsa208_ctx */*ctx*/, | |
299 | const void */*src*/, void */*dest*/, | |
300 | size_t /*sz*/); | |
301 | ||
302 | /*----- Generic cipher interface ------------------------------------------*/ | |
303 | ||
304 | extern const octet salsa20_keysz[]; | |
305 | #define salsa2012_keysz salsa20_keysz | |
306 | #define salsa208_keysz salsa20_keysz | |
307 | #define xsalsa20_keysz salsa20_keysz | |
308 | #define xsalsa2012_keysz salsa20_keysz | |
309 | #define xsalsa208_keysz salsa20_keysz | |
310 | ||
311 | const gccipher salsa20, salsa2012, salsa208; | |
312 | const gccipher xsalsa20, xsalsa2012, xsalsa208; | |
313 | ||
314 | /*----- Generic random number generator interface -------------------------*/ | |
315 | ||
316 | /* --- @salsa20{,12,8}_rand@, @xsalsa20{,12,8}_rand@ --- * | |
317 | * | |
318 | * Arguments: @const void *k@ = pointer to key material | |
319 | * @size_t ksz@ = size of key material | |
320 | * @const void *n@ = pointer to nonce or null | |
321 | * (@SALSA20_NONCESZ@ or @XSALSA20_NONCESZ@) | |
322 | * | |
323 | * Returns: Pointer to generic random number generator instance. | |
324 | * | |
325 | * Use: Creates a random number interface wrapper around | |
326 | * the Salsa20/r or XSalsa20/r stream ciphers. | |
327 | */ | |
328 | ||
329 | extern grand *salsa20_rand(const void */*k*/, size_t /*ksz*/, | |
330 | const void */*n*/); | |
331 | extern grand *salsa2012_rand(const void */*k*/, size_t /*ksz*/, | |
332 | const void */*n*/); | |
333 | extern grand *salsa208_rand(const void */*k*/, size_t /*ksz*/, | |
334 | const void */*n*/); | |
335 | extern grand *xsalsa20_rand(const void */*k*/, size_t /*ksz*/, | |
336 | const void */*n*/); | |
337 | extern grand *xsalsa2012_rand(const void */*k*/, size_t /*ksz*/, | |
338 | const void */*n*/); | |
339 | extern grand *xsalsa208_rand(const void */*k*/, size_t /*ksz*/, | |
340 | const void */*n*/); | |
341 | ||
342 | enum { | |
343 | SALSA20_SEEK = GRAND_SPECIFIC('S'), /* @unsigned long pos@ */ | |
344 | SALSA20_SEEKU64, /* @kludge64 pos@ */ | |
345 | SALSA20_TELL, /* @unsigned long *pos@ */ | |
346 | SALSA20_TELLU64 /* @kludge64 *pos@ */ | |
347 | }; | |
348 | ||
349 | /*----- That's all, folks -------------------------------------------------*/ | |
350 | ||
351 | #ifdef __cplusplus | |
352 | } | |
353 | #endif | |
354 | ||
355 | #endif |