3 * Salsa20 stream cipher
5 * (c) 2015 Straylight/Edgeware
8 #ifndef CATACOMB_SALSA20_H
9 #define CATACOMB_SALSA20_H
15 /*----- Header files ------------------------------------------------------*/
17 #include <mLib/bits.h>
19 #ifndef CATACOMB_GCIPHER_H
23 #ifndef CATACOMB_GRAND_H
27 /*----- Constants ---------------------------------------------------------*/
29 #define SALSA20_NONCESZ 8u
30 #define SALSA20_KEYSZ 32u
31 #define SALSA20_OUTSZ 64u
33 #define HSALSA20_INSZ 16u
34 #define HSALSA20_OUTSZ 32u
36 #define XSALSA20_NONCESZ 24u
37 #define XSALSA20_KEYSZ SALSA20_KEYSZ
38 #define XSALSA20_OUTSZ SALSA20_OUTSZ
40 /*----- Data structures ---------------------------------------------------*/
42 typedef uint32 salsa20_matrix[16];
44 typedef struct salsa20_ctx {
46 octet buf[SALSA20_OUTSZ];
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);
56 /*----- The Salsa20 stream cipher -----------------------------------------*/
58 /* --- @salsa20_init@ --- *
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
67 * Use: Initializes a Salsa20 context ready for use.
70 extern void salsa20_init(salsa20_ctx */*ctx*/,
71 const void */*key*/, size_t /*ksz*/,
72 const void */*nonce*/);
74 /* --- @salsa20_setnonce@ --- *
76 * Arguments: @salsa20_ctx *ctx@ = pointer to context
77 * @const void *nonce@ = the nonce (@SALSA20_NONCESZ@ bytes)
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.).
86 extern void salsa20_setnonce(salsa20_ctx */*ctx*/, const void */*nonce*/);
88 /* --- @salsa20_seek@, @salsa20_seeku64@ --- *
90 * Arguments: @salsa20_ctx *ctx@ = pointer to context
91 * @unsigned long i@, @kludge64 i@ = new position to set
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@
101 extern void salsa20_seek(salsa20_ctx */*ctx*/, unsigned long /*i*/);
102 extern void salsa20_seeku64(salsa20_ctx */*ctx*/, kludge64 /*i*/);
104 /* --- @salsa20_tell@, @salsa20_tellu64@ --- *
106 * Arguments: @salsa20_ctx *ctx@ = pointer to context
108 * Returns: The current position in the output stream, in blocks,
112 extern unsigned long salsa20_tell(salsa20_ctx */*ctx*/);
113 extern kludge64 salsa20_tellu64(salsa20_ctx */*ctx*/);
115 /* --- @salsa20{,12,8}_encrypt@ --- *
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
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
132 extern void salsa20_encrypt(salsa20_ctx */*ctx*/,
133 const void */*src*/, void */*dest*/,
135 extern void salsa2012_encrypt(salsa20_ctx */*ctx*/,
136 const void */*src*/, void */*dest*/,
138 extern void salsa208_encrypt(salsa20_ctx */*ctx*/,
139 const void */*src*/, void */*dest*/,
142 /*----- The HSalsa20 pseudorandom function --------------------------------*/
144 /* --- @hsalsa20{,12,8}_prf@ --- *
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)
152 * Use: Apply the HSalsa20/r pseudorandom function to @src@, writing
153 * the result to @out@.
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*/);
163 /*----- The XSalsa20 stream cipher ----------------------------------------*/
165 /* --- @xsalsa20{,12,8}_init@ --- *
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
174 * Use: Initializes an XSalsa20/r context ready for use.
176 * There is a different function for each number of rounds,
177 * unlike for plain Salsa20.
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*/);
190 /* --- @xsalsa20{,12,8}_setnonce@ --- *
192 * Arguments: @xsalsa20R_ctx *ctx@ = pointer to context
193 * @const void *nonce@ = the nonce (@XSALSA20_NONCESZ@ bytes)
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.).
201 * There is a different function for each number of rounds,
202 * unlike for plain Salsa20.
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*/);
212 /* --- @xsalsa20{,12,8}_seek@, @xsalsa20{,12,8}_seeku64@ --- *
214 * Arguments: @xsalsa20R_ctx *ctx@ = pointer to context
215 * @unsigned long i@, @kludge64 i@ = new position to set
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@
224 * There is a different function for each number of rounds,
225 * unlike for plain Salsa20, because the context structures are
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*/);
236 /* --- @xsalsa20{,12,8}_tell@, @xsalsa20{,12,8}_tellu64@ --- *
238 * Arguments: @salsa20_ctx *ctx@ = pointer to context
240 * Returns: The current position in the output stream, in blocks,
243 * There is a different function for each number of rounds,
244 * unlike for plain Salsa20, because the context structures are
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*/);
255 /* --- @xsalsa20{,12,8}_encrypt@ --- *
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
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
272 extern void xsalsa20_encrypt(xsalsa20_ctx */*ctx*/,
273 const void */*src*/, void */*dest*/,
275 extern void xsalsa2012_encrypt(xsalsa2012_ctx */*ctx*/,
276 const void */*src*/, void */*dest*/,
278 extern void xsalsa208_encrypt(xsalsa208_ctx */*ctx*/,
279 const void */*src*/, void */*dest*/,
282 /*----- Generic cipher interface ------------------------------------------*/
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
291 const gccipher salsa20, salsa2012, salsa208;
292 const gccipher xsalsa20, xsalsa2012, xsalsa208;
294 /*----- Generic random number generator interface -------------------------*/
296 /* --- @salsa20{,12,8}_rand@, @xsalsa20{,12,8}_rand@ --- *
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@)
303 * Returns: Pointer to generic random number generator instance.
305 * Use: Creates a random number interface wrapper around
306 * the Salsa20/r or XSalsa20/r stream ciphers.
309 extern grand *salsa20_rand(const void */*k*/, size_t /*ksz*/,
311 extern grand *salsa2012_rand(const void */*k*/, size_t /*ksz*/,
313 extern grand *salsa208_rand(const void */*k*/, size_t /*ksz*/,
315 extern grand *xsalsa20_rand(const void */*k*/, size_t /*ksz*/,
317 extern grand *xsalsa2012_rand(const void */*k*/, size_t /*ksz*/,
319 extern grand *xsalsa208_rand(const void */*k*/, size_t /*ksz*/,
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@ */
329 /*----- That's all, folks -------------------------------------------------*/