3 * Salsa20 stream cipher
5 * (c) 2015 Straylight/Edgeware
8 /*----- Licensing notice --------------------------------------------------*
10 * This file is part of Catacomb.
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.
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.
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,
28 #ifndef CATACOMB_SALSA20_H
29 #define CATACOMB_SALSA20_H
35 /*----- Header files ------------------------------------------------------*/
37 #include <mLib/bits.h>
39 #ifndef CATACOMB_GCIPHER_H
43 #ifndef CATACOMB_GRAND_H
47 /*----- Constants ---------------------------------------------------------*/
49 #define SALSA20_NONCESZ 8u
50 #define SALSA20_KEYSZ 32u
51 #define SALSA20_OUTSZ 64u
53 #define HSALSA20_INSZ 16u
54 #define HSALSA20_OUTSZ 32u
56 #define XSALSA20_NONCESZ 24u
57 #define XSALSA20_KEYSZ SALSA20_KEYSZ
58 #define XSALSA20_OUTSZ SALSA20_OUTSZ
60 /*----- Data structures ---------------------------------------------------*/
62 typedef uint32 salsa20_matrix
[16];
64 typedef struct salsa20_ctx
{
66 octet buf
[SALSA20_OUTSZ
];
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
);
76 /*----- The Salsa20 stream cipher -----------------------------------------*/
78 /* --- @salsa20_init@ --- *
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
87 * Use: Initializes a Salsa20 context ready for use.
90 extern void salsa20_init(salsa20_ctx */
*ctx*/
,
91 const void */
*key*/
, size_t /*ksz*/,
92 const void */
*nonce*/
);
94 /* --- @salsa20_setnonce@ --- *
96 * Arguments: @salsa20_ctx *ctx@ = pointer to context
97 * @const void *nonce@ = the nonce (@SALSA20_NONCESZ@ bytes)
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.).
106 extern void salsa20_setnonce(salsa20_ctx */
*ctx*/
, const void */
*nonce*/
);
108 /* --- @salsa20_seek@, @salsa20_seeku64@ --- *
110 * Arguments: @salsa20_ctx *ctx@ = pointer to context
111 * @unsigned long i@, @kludge64 i@ = new position to set
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@
121 extern void salsa20_seek(salsa20_ctx */
*ctx*/
, unsigned long /*i*/);
122 extern void salsa20_seeku64(salsa20_ctx */
*ctx*/
, kludge64
/*i*/);
124 /* --- @salsa20_tell@, @salsa20_tellu64@ --- *
126 * Arguments: @salsa20_ctx *ctx@ = pointer to context
128 * Returns: The current position in the output stream, in blocks,
132 extern unsigned long salsa20_tell(salsa20_ctx */
*ctx*/
);
133 extern kludge64
salsa20_tellu64(salsa20_ctx */
*ctx*/
);
135 /* --- @salsa20{,12,8}_encrypt@ --- *
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
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
152 extern void salsa20_encrypt(salsa20_ctx */
*ctx*/
,
153 const void */
*src*/
, void */
*dest*/
,
155 extern void salsa2012_encrypt(salsa20_ctx */
*ctx*/
,
156 const void */
*src*/
, void */
*dest*/
,
158 extern void salsa208_encrypt(salsa20_ctx */
*ctx*/
,
159 const void */
*src*/
, void */
*dest*/
,
162 /*----- The HSalsa20 pseudorandom function --------------------------------*/
164 /* --- @hsalsa20{,12,8}_prf@ --- *
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)
172 * Use: Apply the HSalsa20/r pseudorandom function to @src@, writing
173 * the result to @out@.
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*/
);
183 /*----- The XSalsa20 stream cipher ----------------------------------------*/
185 /* --- @xsalsa20{,12,8}_init@ --- *
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
194 * Use: Initializes an XSalsa20/r context ready for use.
196 * There is a different function for each number of rounds,
197 * unlike for plain Salsa20.
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*/
);
210 /* --- @xsalsa20{,12,8}_setnonce@ --- *
212 * Arguments: @xsalsa20R_ctx *ctx@ = pointer to context
213 * @const void *nonce@ = the nonce (@XSALSA20_NONCESZ@ bytes)
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.).
221 * There is a different function for each number of rounds,
222 * unlike for plain Salsa20.
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*/
);
232 /* --- @xsalsa20{,12,8}_seek@, @xsalsa20{,12,8}_seeku64@ --- *
234 * Arguments: @xsalsa20R_ctx *ctx@ = pointer to context
235 * @unsigned long i@, @kludge64 i@ = new position to set
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@
244 * There is a different function for each number of rounds,
245 * unlike for plain Salsa20, because the context structures are
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*/);
256 /* --- @xsalsa20{,12,8}_tell@, @xsalsa20{,12,8}_tellu64@ --- *
258 * Arguments: @salsa20_ctx *ctx@ = pointer to context
260 * Returns: The current position in the output stream, in blocks,
263 * There is a different function for each number of rounds,
264 * unlike for plain Salsa20, because the context structures are
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*/
);
275 /* --- @xsalsa20{,12,8}_encrypt@ --- *
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
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
292 extern void xsalsa20_encrypt(xsalsa20_ctx */
*ctx*/
,
293 const void */
*src*/
, void */
*dest*/
,
295 extern void xsalsa2012_encrypt(xsalsa2012_ctx */
*ctx*/
,
296 const void */
*src*/
, void */
*dest*/
,
298 extern void xsalsa208_encrypt(xsalsa208_ctx */
*ctx*/
,
299 const void */
*src*/
, void */
*dest*/
,
302 /*----- Generic cipher interface ------------------------------------------*/
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
311 const gccipher salsa20
, salsa2012
, salsa208
;
312 const gccipher xsalsa20
, xsalsa2012
, xsalsa208
;
314 /*----- Generic random number generator interface -------------------------*/
316 /* --- @salsa20{,12,8}_rand@, @xsalsa20{,12,8}_rand@ --- *
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@)
323 * Returns: Pointer to generic random number generator instance.
325 * Use: Creates a random number interface wrapper around
326 * the Salsa20/r or XSalsa20/r stream ciphers.
329 extern grand
*salsa20_rand(const void */
*k*/
, size_t /*ksz*/,
331 extern grand
*salsa2012_rand(const void */
*k*/
, size_t /*ksz*/,
333 extern grand
*salsa208_rand(const void */
*k*/
, size_t /*ksz*/,
335 extern grand
*xsalsa20_rand(const void */
*k*/
, size_t /*ksz*/,
337 extern grand
*xsalsa2012_rand(const void */
*k*/
, size_t /*ksz*/,
339 extern grand
*xsalsa208_rand(const void */
*k*/
, size_t /*ksz*/,
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@ */
349 /*----- That's all, folks -------------------------------------------------*/