ecc: Fix ec_mulm_25519.
[libgcrypt.git] / cipher / chacha20.c
1 /* chacha20.c  -  Bernstein's ChaCha20 cipher
2  * Copyright (C) 2014 Jussi Kivilinna <jussi.kivilinna@iki.fi>
3  *
4  * This file is part of Libgcrypt.
5  *
6  * Libgcrypt is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser general Public License as
8  * published by the Free Software Foundation; either version 2.1 of
9  * the License, or (at your option) any later version.
10  *
11  * Libgcrypt is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
18  *
19  * For a description of the algorithm, see:
20  *   http://cr.yp.to/chacha.html
21  */
22
23 /* The code is based on salsa20.c and public-domain ChaCha implementations:
24  *  chacha-ref.c version 20080118
25  *  D. J. Bernstein
26  *  Public domain.
27  * and
28  *  Andrew Moon
29  *  https://github.com/floodyberry/chacha-opt
30  */
31
32
33 #include <config.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include "types.h"
38 #include "g10lib.h"
39 #include "cipher.h"
40 #include "bufhelp.h"
41
42
43 #define CHACHA20_MIN_KEY_SIZE 16        /* Bytes.  */
44 #define CHACHA20_MAX_KEY_SIZE 32        /* Bytes.  */
45 #define CHACHA20_BLOCK_SIZE   64        /* Bytes.  */
46 #define CHACHA20_MIN_IV_SIZE   8        /* Bytes.  */
47 #define CHACHA20_MAX_IV_SIZE  12        /* Bytes.  */
48 #define CHACHA20_CTR_SIZE     16        /* Bytes.  */
49 #define CHACHA20_INPUT_LENGTH (CHACHA20_BLOCK_SIZE / 4)
50
51 /* USE_SSE2 indicates whether to compile with Intel SSE2 code. */
52 #undef USE_SSE2
53 #if defined(__x86_64__) && (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
54     defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS))
55 # define USE_SSE2 1
56 #endif
57
58 /* USE_SSSE3 indicates whether to compile with Intel SSSE3 code. */
59 #undef USE_SSSE3
60 #if defined(__x86_64__) && (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
61     defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && \
62     defined(HAVE_GCC_INLINE_ASM_SSSE3)
63 # define USE_SSSE3 1
64 #endif
65
66 /* USE_AVX2 indicates whether to compile with Intel AVX2 code. */
67 #undef USE_AVX2
68 #if defined(__x86_64__) && (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
69     defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && \
70     defined(ENABLE_AVX2_SUPPORT)
71 # define USE_AVX2 1
72 #endif
73
74 /* USE_NEON indicates whether to enable ARM NEON assembly code. */
75 #undef USE_NEON
76 #ifdef ENABLE_NEON_SUPPORT
77 # if defined(HAVE_ARM_ARCH_V6) && defined(__ARMEL__) \
78      && defined(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS) \
79      && defined(HAVE_GCC_INLINE_ASM_NEON)
80 #  define USE_NEON 1
81 # endif
82 #endif /*ENABLE_NEON_SUPPORT*/
83
84
85 struct CHACHA20_context_s;
86
87
88 /* Assembly implementations use SystemV ABI, ABI conversion and additional
89  * stack to store XMM6-XMM15 needed on Win64. */
90 #undef ASM_FUNC_ABI
91 #undef ASM_EXTRA_STACK
92 #if (defined(USE_SSE2) || defined(USE_SSSE3) || defined(USE_AVX2)) && \
93     defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)
94 # define ASM_FUNC_ABI __attribute__((sysv_abi))
95 # define ASM_EXTRA_STACK (10 * 16)
96 #else
97 # define ASM_FUNC_ABI
98 # define ASM_EXTRA_STACK 0
99 #endif
100
101
102 typedef unsigned int (* chacha20_blocks_t)(u32 *state, const byte *src,
103                                            byte *dst,
104                                            size_t bytes) ASM_FUNC_ABI;
105
106 typedef struct CHACHA20_context_s
107 {
108   u32 input[CHACHA20_INPUT_LENGTH];
109   u32 pad[CHACHA20_INPUT_LENGTH];
110   chacha20_blocks_t blocks;
111   unsigned int unused; /* bytes in the pad.  */
112 } CHACHA20_context_t;
113
114
115 #ifdef USE_SSE2
116
117 unsigned int _gcry_chacha20_amd64_sse2_blocks(u32 *state, const byte *in,
118                                               byte *out,
119                                               size_t bytes) ASM_FUNC_ABI;
120
121 #endif /* USE_SSE2 */
122
123 #ifdef USE_SSSE3
124
125 unsigned int _gcry_chacha20_amd64_ssse3_blocks(u32 *state, const byte *in,
126                                                byte *out,
127                                                size_t bytes) ASM_FUNC_ABI;
128
129 #endif /* USE_SSSE3 */
130
131 #ifdef USE_AVX2
132
133 unsigned int _gcry_chacha20_amd64_avx2_blocks(u32 *state, const byte *in,
134                                               byte *out,
135                                               size_t bytes) ASM_FUNC_ABI;
136
137 #endif /* USE_AVX2 */
138
139 #ifdef USE_NEON
140
141 unsigned int _gcry_chacha20_armv7_neon_blocks(u32 *state, const byte *in,
142                                               byte *out,
143                                               size_t bytes) ASM_FUNC_ABI;
144
145 #endif /* USE_NEON */
146
147
148 static void chacha20_setiv (void *context, const byte * iv, size_t ivlen);
149 static const char *selftest (void);
150 \f
151
152
153 #define QROUND(a,b,c,d)         \
154   do {                          \
155     a += b; d = rol(d ^ a, 16); \
156     c += d; b = rol(b ^ c, 12); \
157     a += b; d = rol(d ^ a, 8);  \
158     c += d; b = rol(b ^ c, 7);  \
159   } while (0)
160
161 #define QOUT(ai, bi, ci, di) \
162   DO_OUT(ai); DO_OUT(bi); DO_OUT(ci); DO_OUT(di)
163
164
165 #ifndef USE_SSE2
166 ASM_FUNC_ABI static unsigned int
167 chacha20_blocks (u32 *state, const byte *src, byte *dst, size_t bytes)
168 {
169   u32 pad[CHACHA20_INPUT_LENGTH];
170   u32 inp[CHACHA20_INPUT_LENGTH];
171   unsigned int i;
172
173   /* Note: 'bytes' must be multiple of 64 and not zero. */
174
175   inp[0] = state[0];
176   inp[1] = state[1];
177   inp[2] = state[2];
178   inp[3] = state[3];
179   inp[4] = state[4];
180   inp[5] = state[5];
181   inp[6] = state[6];
182   inp[7] = state[7];
183   inp[8] = state[8];
184   inp[9] = state[9];
185   inp[10] = state[10];
186   inp[11] = state[11];
187   inp[12] = state[12];
188   inp[13] = state[13];
189   inp[14] = state[14];
190   inp[15] = state[15];
191
192   do
193     {
194       /* First round. */
195       pad[0] = inp[0];
196       pad[4] = inp[4];
197       pad[8] = inp[8];
198       pad[12] = inp[12];
199       QROUND (pad[0], pad[4], pad[8], pad[12]);
200       pad[1] = inp[1];
201       pad[5] = inp[5];
202       pad[9] = inp[9];
203       pad[13] = inp[13];
204       QROUND (pad[1], pad[5], pad[9], pad[13]);
205       pad[2] = inp[2];
206       pad[6] = inp[6];
207       pad[10] = inp[10];
208       pad[14] = inp[14];
209       QROUND (pad[2], pad[6], pad[10], pad[14]);
210       pad[3] = inp[3];
211       pad[7] = inp[7];
212       pad[11] = inp[11];
213       pad[15] = inp[15];
214       QROUND (pad[3], pad[7], pad[11], pad[15]);
215
216       QROUND (pad[0], pad[5], pad[10], pad[15]);
217       QROUND (pad[1], pad[6], pad[11], pad[12]);
218       QROUND (pad[2], pad[7], pad[8], pad[13]);
219       QROUND (pad[3], pad[4], pad[9], pad[14]);
220
221       for (i = 2; i < 20 - 2; i += 2)
222       {
223         QROUND (pad[0], pad[4], pad[8], pad[12]);
224         QROUND (pad[1], pad[5], pad[9], pad[13]);
225         QROUND (pad[2], pad[6], pad[10], pad[14]);
226         QROUND (pad[3], pad[7], pad[11], pad[15]);
227
228         QROUND (pad[0], pad[5], pad[10], pad[15]);
229         QROUND (pad[1], pad[6], pad[11], pad[12]);
230         QROUND (pad[2], pad[7], pad[8], pad[13]);
231         QROUND (pad[3], pad[4], pad[9], pad[14]);
232       }
233
234       QROUND (pad[0], pad[4], pad[8], pad[12]);
235       QROUND (pad[1], pad[5], pad[9], pad[13]);
236       QROUND (pad[2], pad[6], pad[10], pad[14]);
237       QROUND (pad[3], pad[7], pad[11], pad[15]);
238
239       if (src)
240         {
241 #define DO_OUT(idx) buf_put_le32(dst + (idx) * 4, \
242                                  (pad[idx] + inp[idx]) ^ \
243                                   buf_get_le32(src + (idx) * 4))
244           /* Last round. */
245           QROUND (pad[0], pad[5], pad[10], pad[15]);
246           QOUT(0, 5, 10, 15);
247           QROUND (pad[1], pad[6], pad[11], pad[12]);
248           QOUT(1, 6, 11, 12);
249           QROUND (pad[2], pad[7], pad[8], pad[13]);
250           QOUT(2, 7, 8, 13);
251           QROUND (pad[3], pad[4], pad[9], pad[14]);
252           QOUT(3, 4, 9, 14);
253 #undef DO_OUT
254         }
255       else
256         {
257 #define DO_OUT(idx) buf_put_le32(dst + (idx) * 4, pad[idx] + inp[idx])
258           /* Last round. */
259           QROUND (pad[0], pad[5], pad[10], pad[15]);
260           QOUT(0, 5, 10, 15);
261           QROUND (pad[1], pad[6], pad[11], pad[12]);
262           QOUT(1, 6, 11, 12);
263           QROUND (pad[2], pad[7], pad[8], pad[13]);
264           QOUT(2, 7, 8, 13);
265           QROUND (pad[3], pad[4], pad[9], pad[14]);
266           QOUT(3, 4, 9, 14);
267 #undef DO_OUT
268         }
269
270       /* Update counter. */
271       inp[13] += (!++inp[12]);
272
273       bytes -= CHACHA20_BLOCK_SIZE;
274       dst += CHACHA20_BLOCK_SIZE;
275       src += (src) ? CHACHA20_BLOCK_SIZE : 0;
276     }
277   while (bytes >= CHACHA20_BLOCK_SIZE);
278
279   state[12] = inp[12];
280   state[13] = inp[13];
281
282   /* burn_stack */
283   return (2 * CHACHA20_INPUT_LENGTH * sizeof(u32) + 6 * sizeof(void *));
284 }
285 #endif /*!USE_SSE2*/
286
287 #undef QROUND
288 #undef QOUT
289
290
291 static unsigned int
292 chacha20_core(u32 *dst, struct CHACHA20_context_s *ctx)
293 {
294   return ctx->blocks(ctx->input, NULL, (byte *)dst, CHACHA20_BLOCK_SIZE)
295          + ASM_EXTRA_STACK;
296 }
297
298
299 static void
300 chacha20_keysetup (CHACHA20_context_t * ctx, const byte * key,
301                    unsigned int keylen)
302 {
303   /* These constants are the little endian encoding of the string
304      "expand 32-byte k".  For the 128 bit variant, the "32" in that
305      string will be fixed up to "16".  */
306   ctx->input[0] = 0x61707865;        /* "apxe"  */
307   ctx->input[1] = 0x3320646e;        /* "3 dn"  */
308   ctx->input[2] = 0x79622d32;        /* "yb-2"  */
309   ctx->input[3] = 0x6b206574;        /* "k et"  */
310
311   ctx->input[4] = buf_get_le32 (key + 0);
312   ctx->input[5] = buf_get_le32 (key + 4);
313   ctx->input[6] = buf_get_le32 (key + 8);
314   ctx->input[7] = buf_get_le32 (key + 12);
315
316   if (keylen == CHACHA20_MAX_KEY_SIZE) /* 256 bits */
317     {
318       ctx->input[8] = buf_get_le32 (key + 16);
319       ctx->input[9] = buf_get_le32 (key + 20);
320       ctx->input[10] = buf_get_le32 (key + 24);
321       ctx->input[11] = buf_get_le32 (key + 28);
322     }
323   else /* 128 bits */
324     {
325       ctx->input[8] = ctx->input[4];
326       ctx->input[9] = ctx->input[5];
327       ctx->input[10] = ctx->input[6];
328       ctx->input[11] = ctx->input[7];
329
330       ctx->input[1] -= 0x02000000;        /* Change to "1 dn".  */
331       ctx->input[2] += 0x00000004;        /* Change to "yb-6".  */
332     }
333 }
334
335
336 static void
337 chacha20_ivsetup (CHACHA20_context_t * ctx, const byte * iv, size_t ivlen)
338 {
339   if (ivlen == CHACHA20_CTR_SIZE)
340     {
341       ctx->input[12] = buf_get_le32 (iv + 0);
342       ctx->input[13] = buf_get_le32 (iv + 4);
343       ctx->input[14] = buf_get_le32 (iv + 8);
344       ctx->input[15] = buf_get_le32 (iv + 12);
345     }
346   else if (ivlen == CHACHA20_MAX_IV_SIZE)
347     {
348       ctx->input[12] = 0;
349       ctx->input[13] = buf_get_le32 (iv + 0);
350       ctx->input[14] = buf_get_le32 (iv + 4);
351       ctx->input[15] = buf_get_le32 (iv + 8);
352     }
353   else if (ivlen == CHACHA20_MIN_IV_SIZE)
354     {
355       ctx->input[12] = 0;
356       ctx->input[13] = 0;
357       ctx->input[14] = buf_get_le32 (iv + 0);
358       ctx->input[15] = buf_get_le32 (iv + 4);
359     }
360   else
361     {
362       ctx->input[12] = 0;
363       ctx->input[13] = 0;
364       ctx->input[14] = 0;
365       ctx->input[15] = 0;
366     }
367 }
368
369
370 static gcry_err_code_t
371 chacha20_do_setkey (CHACHA20_context_t * ctx,
372                     const byte * key, unsigned int keylen)
373 {
374   static int initialized;
375   static const char *selftest_failed;
376   unsigned int features = _gcry_get_hw_features ();
377
378   if (!initialized)
379     {
380       initialized = 1;
381       selftest_failed = selftest ();
382       if (selftest_failed)
383         log_error ("CHACHA20 selftest failed (%s)\n", selftest_failed);
384     }
385   if (selftest_failed)
386     return GPG_ERR_SELFTEST_FAILED;
387
388   if (keylen != CHACHA20_MAX_KEY_SIZE && keylen != CHACHA20_MIN_KEY_SIZE)
389     return GPG_ERR_INV_KEYLEN;
390
391 #ifdef USE_SSE2
392   ctx->blocks = _gcry_chacha20_amd64_sse2_blocks;
393 #else
394   ctx->blocks = chacha20_blocks;
395 #endif
396
397 #ifdef USE_SSSE3
398   if (features & HWF_INTEL_SSSE3)
399     ctx->blocks = _gcry_chacha20_amd64_ssse3_blocks;
400 #endif
401 #ifdef USE_AVX2
402   if (features & HWF_INTEL_AVX2)
403     ctx->blocks = _gcry_chacha20_amd64_avx2_blocks;
404 #endif
405 #ifdef USE_NEON
406   if (features & HWF_ARM_NEON)
407     ctx->blocks = _gcry_chacha20_armv7_neon_blocks;
408 #endif
409
410   (void)features;
411
412   chacha20_keysetup (ctx, key, keylen);
413
414   /* We default to a zero nonce.  */
415   chacha20_setiv (ctx, NULL, 0);
416
417   return 0;
418 }
419
420
421 static gcry_err_code_t
422 chacha20_setkey (void *context, const byte * key, unsigned int keylen)
423 {
424   CHACHA20_context_t *ctx = (CHACHA20_context_t *) context;
425   gcry_err_code_t rc = chacha20_do_setkey (ctx, key, keylen);
426   _gcry_burn_stack (4 + sizeof (void *) + 4 * sizeof (void *));
427   return rc;
428 }
429
430
431 static void
432 chacha20_setiv (void *context, const byte * iv, size_t ivlen)
433 {
434   CHACHA20_context_t *ctx = (CHACHA20_context_t *) context;
435
436   /* draft-nir-cfrg-chacha20-poly1305-02 defines 96-bit and 64-bit nonce. */
437   if (iv && ivlen != CHACHA20_MAX_IV_SIZE && ivlen != CHACHA20_MIN_IV_SIZE
438       && ivlen != CHACHA20_CTR_SIZE)
439     log_info ("WARNING: chacha20_setiv: bad ivlen=%u\n", (u32) ivlen);
440
441   if (iv && (ivlen == CHACHA20_MAX_IV_SIZE || ivlen == CHACHA20_MIN_IV_SIZE
442              || ivlen == CHACHA20_CTR_SIZE))
443     chacha20_ivsetup (ctx, iv, ivlen);
444   else
445     chacha20_ivsetup (ctx, NULL, 0);
446
447   /* Reset the unused pad bytes counter.  */
448   ctx->unused = 0;
449 }
450 \f
451
452
453 /* Note: This function requires LENGTH > 0.  */
454 static void
455 chacha20_do_encrypt_stream (CHACHA20_context_t * ctx,
456                             byte * outbuf, const byte * inbuf, size_t length)
457 {
458   unsigned int nburn, burn = 0;
459
460   if (ctx->unused)
461     {
462       unsigned char *p = (void *) ctx->pad;
463       size_t n;
464
465       gcry_assert (ctx->unused < CHACHA20_BLOCK_SIZE);
466
467       n = ctx->unused;
468       if (n > length)
469         n = length;
470       buf_xor (outbuf, inbuf, p + CHACHA20_BLOCK_SIZE - ctx->unused, n);
471       length -= n;
472       outbuf += n;
473       inbuf += n;
474       ctx->unused -= n;
475       if (!length)
476         return;
477       gcry_assert (!ctx->unused);
478     }
479
480   if (length >= CHACHA20_BLOCK_SIZE)
481     {
482       size_t nblocks = length / CHACHA20_BLOCK_SIZE;
483       size_t bytes = nblocks * CHACHA20_BLOCK_SIZE;
484       burn = ctx->blocks(ctx->input, inbuf, outbuf, bytes);
485       length -= bytes;
486       outbuf += bytes;
487       inbuf  += bytes;
488     }
489
490   if (length > 0)
491     {
492       nburn = chacha20_core (ctx->pad, ctx);
493       burn = nburn > burn ? nburn : burn;
494
495       buf_xor (outbuf, inbuf, ctx->pad, length);
496       ctx->unused = CHACHA20_BLOCK_SIZE - length;
497     }
498
499   _gcry_burn_stack (burn);
500 }
501
502
503 static void
504 chacha20_encrypt_stream (void *context, byte * outbuf, const byte * inbuf,
505                          size_t length)
506 {
507   CHACHA20_context_t *ctx = (CHACHA20_context_t *) context;
508
509   if (length)
510     chacha20_do_encrypt_stream (ctx, outbuf, inbuf, length);
511 }
512
513
514 static const char *
515 selftest (void)
516 {
517   byte ctxbuf[sizeof(CHACHA20_context_t) + 15];
518   CHACHA20_context_t *ctx;
519   byte scratch[127 + 1];
520   byte buf[512 + 64 + 4];
521   int i;
522
523   /* From draft-strombergson-chacha-test-vectors */
524   static byte key_1[] = {
525     0xc4, 0x6e, 0xc1, 0xb1, 0x8c, 0xe8, 0xa8, 0x78,
526     0x72, 0x5a, 0x37, 0xe7, 0x80, 0xdf, 0xb7, 0x35,
527     0x1f, 0x68, 0xed, 0x2e, 0x19, 0x4c, 0x79, 0xfb,
528     0xc6, 0xae, 0xbe, 0xe1, 0xa6, 0x67, 0x97, 0x5d
529   };
530   static const byte nonce_1[] =
531     { 0x1a, 0xda, 0x31, 0xd5, 0xcf, 0x68, 0x82, 0x21 };
532   static const byte plaintext_1[127] = {
533     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
534     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
535     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
536     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
537     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
538     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
539     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
540     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
541     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
542     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
543     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
544     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
545     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
546     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
547     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
548     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
549   };
550   static const byte ciphertext_1[127] = {
551     0xf6, 0x3a, 0x89, 0xb7, 0x5c, 0x22, 0x71, 0xf9,
552     0x36, 0x88, 0x16, 0x54, 0x2b, 0xa5, 0x2f, 0x06,
553     0xed, 0x49, 0x24, 0x17, 0x92, 0x30, 0x2b, 0x00,
554     0xb5, 0xe8, 0xf8, 0x0a, 0xe9, 0xa4, 0x73, 0xaf,
555     0xc2, 0x5b, 0x21, 0x8f, 0x51, 0x9a, 0xf0, 0xfd,
556     0xd4, 0x06, 0x36, 0x2e, 0x8d, 0x69, 0xde, 0x7f,
557     0x54, 0xc6, 0x04, 0xa6, 0xe0, 0x0f, 0x35, 0x3f,
558     0x11, 0x0f, 0x77, 0x1b, 0xdc, 0xa8, 0xab, 0x92,
559     0xe5, 0xfb, 0xc3, 0x4e, 0x60, 0xa1, 0xd9, 0xa9,
560     0xdb, 0x17, 0x34, 0x5b, 0x0a, 0x40, 0x27, 0x36,
561     0x85, 0x3b, 0xf9, 0x10, 0xb0, 0x60, 0xbd, 0xf1,
562     0xf8, 0x97, 0xb6, 0x29, 0x0f, 0x01, 0xd1, 0x38,
563     0xae, 0x2c, 0x4c, 0x90, 0x22, 0x5b, 0xa9, 0xea,
564     0x14, 0xd5, 0x18, 0xf5, 0x59, 0x29, 0xde, 0xa0,
565     0x98, 0xca, 0x7a, 0x6c, 0xcf, 0xe6, 0x12, 0x27,
566     0x05, 0x3c, 0x84, 0xe4, 0x9a, 0x4a, 0x33
567   };
568
569   /* 16-byte alignment required for amd64 implementation. */
570   ctx = (CHACHA20_context_t *)((uintptr_t)(ctxbuf + 15) & ~(uintptr_t)15);
571
572   chacha20_setkey (ctx, key_1, sizeof key_1);
573   chacha20_setiv (ctx, nonce_1, sizeof nonce_1);
574   scratch[sizeof (scratch) - 1] = 0;
575   chacha20_encrypt_stream (ctx, scratch, plaintext_1, sizeof plaintext_1);
576   if (memcmp (scratch, ciphertext_1, sizeof ciphertext_1))
577     return "ChaCha20 encryption test 1 failed.";
578   if (scratch[sizeof (scratch) - 1])
579     return "ChaCha20 wrote too much.";
580   chacha20_setkey (ctx, key_1, sizeof (key_1));
581   chacha20_setiv (ctx, nonce_1, sizeof nonce_1);
582   chacha20_encrypt_stream (ctx, scratch, scratch, sizeof plaintext_1);
583   if (memcmp (scratch, plaintext_1, sizeof plaintext_1))
584     return "ChaCha20 decryption test 1 failed.";
585
586   for (i = 0; i < sizeof buf; i++)
587     buf[i] = i;
588   chacha20_setkey (ctx, key_1, sizeof key_1);
589   chacha20_setiv (ctx, nonce_1, sizeof nonce_1);
590   /*encrypt */
591   chacha20_encrypt_stream (ctx, buf, buf, sizeof buf);
592   /*decrypt */
593   chacha20_setkey (ctx, key_1, sizeof key_1);
594   chacha20_setiv (ctx, nonce_1, sizeof nonce_1);
595   chacha20_encrypt_stream (ctx, buf, buf, 1);
596   chacha20_encrypt_stream (ctx, buf + 1, buf + 1, (sizeof buf) - 1 - 1);
597   chacha20_encrypt_stream (ctx, buf + (sizeof buf) - 1,
598                            buf + (sizeof buf) - 1, 1);
599   for (i = 0; i < sizeof buf; i++)
600     if (buf[i] != (byte) i)
601       return "ChaCha20 encryption test 2 failed.";
602
603   chacha20_setkey (ctx, key_1, sizeof key_1);
604   chacha20_setiv (ctx, nonce_1, sizeof nonce_1);
605   /* encrypt */
606   for (i = 0; i < sizeof buf; i++)
607     chacha20_encrypt_stream (ctx, &buf[i], &buf[i], 1);
608   /* decrypt */
609   chacha20_setkey (ctx, key_1, sizeof key_1);
610   chacha20_setiv (ctx, nonce_1, sizeof nonce_1);
611   chacha20_encrypt_stream (ctx, buf, buf, sizeof buf);
612   for (i = 0; i < sizeof buf; i++)
613     if (buf[i] != (byte) i)
614       return "ChaCha20 encryption test 3 failed.";
615
616   return NULL;
617 }
618
619
620 gcry_cipher_spec_t _gcry_cipher_spec_chacha20 = {
621   GCRY_CIPHER_CHACHA20,
622   {0, 0},                       /* flags */
623   "CHACHA20",                   /* name */
624   NULL,                         /* aliases */
625   NULL,                         /* oids */
626   1,                            /* blocksize in bytes. */
627   CHACHA20_MAX_KEY_SIZE * 8,    /* standard key length in bits. */
628   sizeof (CHACHA20_context_t),
629   chacha20_setkey,
630   NULL,
631   NULL,
632   chacha20_encrypt_stream,
633   chacha20_encrypt_stream,
634   NULL,
635   NULL,
636   chacha20_setiv
637 };