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