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_CHACHA_H
29 #define CATACOMB_CHACHA_H
35 /*----- Header files ------------------------------------------------------*/
37 #include <mLib/bits.h>
39 #ifndef CATACOMB_GCIPHER_H
43 #ifndef CATACOMB_GRAND_H
47 /*----- Constants ---------------------------------------------------------*/
49 #define CHACHA_NONCESZ 8u
50 #define CHACHA_KEYSZ 32u
51 #define CHACHA_OUTSZ 64u
53 #define HCHACHA_INSZ 16u
54 #define HCHACHA_OUTSZ 32u
56 #define XCHACHA_NONCESZ 24u
57 #define XCHACHA_KEYSZ CHACHA_KEYSZ
58 #define XCHACHA_OUTSZ CHACHA_OUTSZ
60 /*----- Data structures ---------------------------------------------------*/
62 typedef uint32 chacha_matrix[16];
64 typedef struct chacha_ctx {
66 octet buf[CHACHA_OUTSZ];
70 #define XCHACHA_DEFCTX(name) \
71 typedef struct name { chacha_ctx s; chacha_matrix k; } name
72 XCHACHA_DEFCTX(xchacha20_ctx);
73 XCHACHA_DEFCTX(xchacha12_ctx);
74 XCHACHA_DEFCTX(xchacha8_ctx);
76 /*----- The ChaCha stream cipher ------------------------------------------*/
78 /* --- @chacha_init@ --- *
80 * Arguments: @chacha_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 ChaCha context ready for use.
90 extern void chacha_init(chacha_ctx */*ctx*/,
91 const void */*key*/, size_t /*ksz*/,
92 const void */*nonce*/);
94 /* --- @chacha_setnonce@ --- *
96 * Arguments: @chacha_ctx *ctx@ = pointer to context
97 * @const void *nonce@ = the nonce (@CHACHA_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 * @chacha_seek@ etc.).
106 extern void chacha_setnonce(chacha_ctx */*ctx*/, const void */*nonce*/);
108 /* --- @chacha_seek@, @chacha_seeku64@ --- *
110 * Arguments: @chacha_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 ChaCha output
116 * blocks, which are @CHACHA_OUTSZ@ bytes each. Byte
117 * granularity can be achieved by calling @chacha_encrypt@
121 extern void chacha_seek(chacha_ctx */*ctx*/, unsigned long /*i*/);
122 extern void chacha_seeku64(chacha_ctx */*ctx*/, kludge64 /*i*/);
124 /* --- @chacha_tell@, @chacha_tellu64@ --- *
126 * Arguments: @chacha_ctx *ctx@ = pointer to context
128 * Returns: The current position in the output stream, in blocks,
132 extern unsigned long chacha_tell(chacha_ctx */*ctx*/);
133 extern kludge64 chacha_tellu64(chacha_ctx */*ctx*/);
135 /* --- @chacha{20,12,8}_encrypt@ --- *
137 * Arguments: @chacha_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 * ChaCha 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 chacha20_encrypt(chacha_ctx */*ctx*/,
153 const void */*src*/, void */*dest*/,
155 extern void chacha12_encrypt(chacha_ctx */*ctx*/,
156 const void */*src*/, void */*dest*/,
158 extern void chacha8_encrypt(chacha_ctx */*ctx*/,
159 const void */*src*/, void */*dest*/,
162 /*----- The HChaCha pseudorandom function ---------------------------------*/
164 /* --- @hchacha{20,12,8}_prf@ --- *
166 * Arguments: @chacha_ctx *ctx@ = pointer to context
167 * @const void *src@ = the input (@HCHACHA_INSZ@ bytes)
168 * @void *dest@ = the output (@HCHACHA_OUTSZ@ bytes)
172 * Use: Apply the HChaCha/r pseudorandom function to @src@, writing
173 * the result to @out@.
176 extern void hchacha20_prf(chacha_ctx */*ctx*/,
177 const void */*src*/, void */*dest*/);
178 extern void hchacha12_prf(chacha_ctx */*ctx*/,
179 const void */*src*/, void */*dest*/);
180 extern void hchacha8_prf(chacha_ctx */*ctx*/,
181 const void */*src*/, void */*dest*/);
183 /*----- The XChaCha stream cipher ----------------------------------------*/
185 /* --- @xchacha{20,12,8}_init@ --- *
187 * Arguments: @xchachaR_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 XChaCha/r context ready for use.
196 * There is a different function for each number of rounds,
197 * unlike for plain ChaCha.
200 extern void xchacha20_init(xchacha20_ctx */*ctx*/,
201 const void */*key*/, size_t /*ksz*/,
202 const void */*nonce*/);
203 extern void xchacha12_init(xchacha12_ctx */*ctx*/,
204 const void */*key*/, size_t /*ksz*/,
205 const void */*nonce*/);
206 extern void xchacha8_init(xchacha8_ctx */*ctx*/,
207 const void */*key*/, size_t /*ksz*/,
208 const void */*nonce*/);
210 /* --- @xchacha{20,12,8}_setnonce@ --- *
212 * Arguments: @xchachaR_ctx *ctx@ = pointer to context
213 * @const void *nonce@ = the nonce (@XCHACHA_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 * @chacha_seek@ etc.).
221 * There is a different function for each number of rounds,
222 * unlike for plain ChaCha.
225 extern void xchacha20_setnonce(xchacha20_ctx */*ctx*/,
226 const void */*nonce*/);
227 extern void xchacha12_setnonce(xchacha12_ctx */*ctx*/,
228 const void */*nonce*/);
229 extern void xchacha8_setnonce(xchacha8_ctx */*ctx*/,
230 const void */*nonce*/);
232 /* --- @xchacha{20,12,8}_seek@, @xchacha{20,12,8}_seeku64@ --- *
234 * Arguments: @xchachaR_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 ChaCha output
240 * blocks, which are @XCHACHA_OUTSZ@ bytes each. Byte
241 * granularity can be achieved by calling @xchachaR_encrypt@
244 * There is a different function for each number of rounds,
245 * unlike for plain ChaCha, because the context structures are
249 extern void xchacha20_seek(xchacha20_ctx */*ctx*/, unsigned long /*i*/);
250 extern void xchacha12_seek(xchacha12_ctx */*ctx*/, unsigned long /*i*/);
251 extern void xchacha8_seek(xchacha8_ctx */*ctx*/, unsigned long /*i*/);
252 extern void xchacha20_seeku64(xchacha20_ctx */*ctx*/, kludge64 /*i*/);
253 extern void xchacha12_seeku64(xchacha12_ctx */*ctx*/, kludge64 /*i*/);
254 extern void xchacha8_seeku64(xchacha8_ctx */*ctx*/, kludge64 /*i*/);
256 /* --- @xchacha{20,12,8}_tell@, @xchacha{20,12,8}_tellu64@ --- *
258 * Arguments: @chacha_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 ChaCha, because the context structures are
268 extern unsigned long xchacha20_tell(xchacha20_ctx */*ctx*/);
269 extern unsigned long xchacha12_tell(xchacha12_ctx */*ctx*/);
270 extern unsigned long xchacha8_tell(xchacha8_ctx */*ctx*/);
271 extern kludge64 xchacha20_tellu64(xchacha20_ctx */*ctx*/);
272 extern kludge64 xchacha12_tellu64(xchacha12_ctx */*ctx*/);
273 extern kludge64 xchacha8_tellu64(xchacha8_ctx */*ctx*/);
275 /* --- @xchacha{20,12,8}_encrypt@ --- *
277 * Arguments: @xchachaR_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 * XChaCha 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 xchacha20_encrypt(xchacha20_ctx */*ctx*/,
293 const void */*src*/, void */*dest*/,
295 extern void xchacha12_encrypt(xchacha12_ctx */*ctx*/,
296 const void */*src*/, void */*dest*/,
298 extern void xchacha8_encrypt(xchacha8_ctx */*ctx*/,
299 const void */*src*/, void */*dest*/,
302 /*----- Generic cipher interface ------------------------------------------*/
304 extern const octet chacha_keysz[];
305 #define chacha20_keysz chacha_keysz
306 #define chacha12_keysz chacha_keysz
307 #define chacha8_keysz chacha_keysz
308 #define xchacha_keysz chacha_keysz
309 #define xchacha20_keysz chacha_keysz
310 #define xchacha12_keysz chacha_keysz
311 #define xchacha8_keysz chacha_keysz
313 const gccipher chacha20, chacha12, chacha8;
314 const gccipher xchacha20, xchacha12, xchacha8;
316 /*----- Generic random number generator interface -------------------------*/
318 /* --- @chacha{,12,8}_rand@, @xchacha{,12,8}_rand@ --- *
320 * Arguments: @const void *k@ = pointer to key material
321 * @size_t ksz@ = size of key material
322 * @const void *n@ = pointer to nonce or null
323 * (@CHACHA_NONCESZ@ or @XCHACHA_NONCESZ@)
325 * Returns: Pointer to generic random number generator instance.
327 * Use: Creates a random number interface wrapper around
328 * the ChaCha or XChaCha stream ciphers.
331 extern grand *chacha20_rand(const void */*k*/, size_t /*ksz*/,
333 extern grand *chacha12_rand(const void */*k*/, size_t /*ksz*/,
335 extern grand *chacha8_rand(const void */*k*/, size_t /*ksz*/,
337 extern grand *xchacha20_rand(const void */*k*/, size_t /*ksz*/,
339 extern grand *xchacha12_rand(const void */*k*/, size_t /*ksz*/,
341 extern grand *xchacha8_rand(const void */*k*/, size_t /*ksz*/,
345 CHACHA_SEEK = GRAND_SPECIFIC('S'), /* @unsigned long pos@ */
346 CHACHA_SEEKU64, /* @kludge64 pos@ */
347 CHACHA_TELL, /* @unsigned long *pos@ */
348 CHACHA_TELLU64 /* @kludge64 *pos@ */
351 /*----- That's all, folks -------------------------------------------------*/