1 /* salsa20.c  -  Bernstein's Salsa20 cipher
2  * Copyright (C) 2012 Simon Josefsson, Niels Möller
3  * Copyright (C) 2013 g10 Code GmbH
4  *
5  * This file is part of Libgcrypt.
6  *
7  * Libgcrypt is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU Lesser general Public License as
9  * published by the Free Software Foundation; either version 2.1 of
10  * the License, or (at your option) any later version.
11  *
12  * Libgcrypt is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
19  *
20  * For a description of the algorithm, see:
21  *   http://cr.yp.to/snuffle/spec.pdf
22  *   http://cr.yp.to/snuffle/design.pdf
23  */
24 
25 /* The code is based on the code in Nettle
26    (git commit id 9d2d8ddaee35b91a4e1a32ae77cba04bea3480e7)
27    which in turn is based on
28    salsa20-ref.c version 20051118
29    D. J. Bernstein
30    Public domain.
31 */
32 
33 
34 #include <config.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include "types.h"
39 #include "g10lib.h"
40 #include "cipher.h"
41 #include "bufhelp.h"
42 #include "cipher-internal.h"
43 
44 
45 /* USE_AMD64 indicates whether to compile with AMD64 code. */
46 #undef USE_AMD64
47 #if defined(__x86_64__) && (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
48     defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS))
49 # define USE_AMD64 1
50 #endif
51 
52 /* USE_ARM_NEON_ASM indicates whether to enable ARM NEON assembly code. */
53 #undef USE_ARM_NEON_ASM
54 #ifdef ENABLE_NEON_SUPPORT
55 # if defined(HAVE_ARM_ARCH_V6) && defined(__ARMEL__) \
56      && defined(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS) \
57      && defined(HAVE_GCC_INLINE_ASM_NEON)
58 #  define USE_ARM_NEON_ASM 1
59 # endif
60 #endif /*ENABLE_NEON_SUPPORT*/
61 
62 
63 #define SALSA20_MIN_KEY_SIZE 16  /* Bytes.  */
64 #define SALSA20_MAX_KEY_SIZE 32  /* Bytes.  */
65 #define SALSA20_BLOCK_SIZE   64  /* Bytes.  */
66 #define SALSA20_IV_SIZE       8  /* Bytes.  */
67 #define SALSA20_INPUT_LENGTH 16  /* Bytes.  */
68 
69 /* Number of rounds.  The standard uses 20 rounds.  In any case the
70    number of rounds must be even.  */
71 #define SALSA20_ROUNDS       20
72 #define SALSA20R12_ROUNDS    12
73 
74 
75 struct SALSA20_context_s;
76 
77 typedef unsigned int (*salsa20_core_t) (u32 *dst, struct SALSA20_context_s *ctx,
78                                         unsigned int rounds);
79 typedef void (* salsa20_keysetup_t)(struct SALSA20_context_s *ctx,
80                                     const byte *key, int keylen);
81 typedef void (* salsa20_ivsetup_t)(struct SALSA20_context_s *ctx,
82                                    const byte *iv);
83 
84 typedef struct SALSA20_context_s
85 {
86   /* Indices 1-4 and 11-14 holds the key (two identical copies for the
87      shorter key size), indices 0, 5, 10, 15 are constant, indices 6, 7
88      are the IV, and indices 8, 9 are the block counter:
89 
90      C K K K
91      K C I I
92      B B C K
93      K K K C
94   */
95   u32 input[SALSA20_INPUT_LENGTH];
96   u32 pad[SALSA20_INPUT_LENGTH];
97   unsigned int unused; /* bytes in the pad.  */
98 #ifdef USE_ARM_NEON_ASM
99   int use_neon;
100 #endif
101   salsa20_keysetup_t keysetup;
102   salsa20_ivsetup_t ivsetup;
103   salsa20_core_t core;
104 } SALSA20_context_t;
105 
106 
107 /* The masking of the right shift is needed to allow n == 0 (using
108    just 32 - n and 64 - n results in undefined behaviour). Most uses
109    of these macros use a constant and non-zero rotation count. */
110 #define ROTL32(n,x) (((x)<<(n)) | ((x)>>((-(n)&31))))
111 
112 
113 #define LE_SWAP32(v) le_bswap32(v)
114 
115 #define LE_READ_UINT32(p) buf_get_le32(p)
116 
117 
118 static void salsa20_setiv (void *context, const byte *iv, size_t ivlen);
119 static const char *selftest (void);
120 
121 
122 #ifdef USE_AMD64
123 
124 /* Assembly implementations use SystemV ABI, ABI conversion and additional
125  * stack to store XMM6-XMM15 needed on Win64. */
126 #ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
127 # define ASM_FUNC_ABI __attribute__((sysv_abi))
128 # define ASM_EXTRA_STACK (10 * 16)
129 #else
130 # define ASM_FUNC_ABI
131 # define ASM_EXTRA_STACK 0
132 #endif
133 
134 /* AMD64 assembly implementations of Salsa20. */
135 void _gcry_salsa20_amd64_keysetup(u32 *ctxinput, const void *key, int keybits)
136                                  ASM_FUNC_ABI;
137 void _gcry_salsa20_amd64_ivsetup(u32 *ctxinput, const void *iv)
138                                 ASM_FUNC_ABI;
139 unsigned int
140 _gcry_salsa20_amd64_encrypt_blocks(u32 *ctxinput, const void *src, void *dst,
141                                    size_t len, int rounds) ASM_FUNC_ABI;
142 
143 static void
salsa20_keysetup(SALSA20_context_t * ctx,const byte * key,int keylen)144 salsa20_keysetup(SALSA20_context_t *ctx, const byte *key, int keylen)
145 {
146   _gcry_salsa20_amd64_keysetup(ctx->input, key, keylen * 8);
147 }
148 
149 static void
salsa20_ivsetup(SALSA20_context_t * ctx,const byte * iv)150 salsa20_ivsetup(SALSA20_context_t *ctx, const byte *iv)
151 {
152   _gcry_salsa20_amd64_ivsetup(ctx->input, iv);
153 }
154 
155 static unsigned int
salsa20_core(u32 * dst,SALSA20_context_t * ctx,unsigned int rounds)156 salsa20_core (u32 *dst, SALSA20_context_t *ctx, unsigned int rounds)
157 {
158   memset(dst, 0, SALSA20_BLOCK_SIZE);
159   return _gcry_salsa20_amd64_encrypt_blocks(ctx->input, dst, dst, 1, rounds)
160          + ASM_EXTRA_STACK;
161 }
162 
163 #else /* USE_AMD64 */
164 
165 
166 
167 #if 0
168 # define SALSA20_CORE_DEBUG(i) do {		\
169     unsigned debug_j;				\
170     for (debug_j = 0; debug_j < 16; debug_j++)	\
171       {						\
172 	if (debug_j == 0)			\
173 	  fprintf(stderr, "%2d:", (i));		\
174 	else if (debug_j % 4 == 0)		\
175 	  fprintf(stderr, "\n   ");		\
176 	fprintf(stderr, " %8x", pad[debug_j]);	\
177       }						\
178     fprintf(stderr, "\n");			\
179   } while (0)
180 #else
181 # define SALSA20_CORE_DEBUG(i)
182 #endif
183 
184 #define QROUND(x0, x1, x2, x3)      \
185   do {                              \
186     x1 ^= ROTL32 ( 7, x0 + x3);	    \
187     x2 ^= ROTL32 ( 9, x1 + x0);	    \
188     x3 ^= ROTL32 (13, x2 + x1);	    \
189     x0 ^= ROTL32 (18, x3 + x2);	    \
190   } while(0)
191 
192 static unsigned int
salsa20_core(u32 * dst,SALSA20_context_t * ctx,unsigned rounds)193 salsa20_core (u32 *dst, SALSA20_context_t *ctx, unsigned rounds)
194 {
195   u32 pad[SALSA20_INPUT_LENGTH], *src = ctx->input;
196   unsigned int i;
197 
198   memcpy (pad, src, sizeof(pad));
199   for (i = 0; i < rounds; i += 2)
200     {
201       SALSA20_CORE_DEBUG (i);
202       QROUND (pad[0],  pad[4],  pad[8],  pad[12]);
203       QROUND (pad[5],  pad[9],  pad[13], pad[1] );
204       QROUND (pad[10], pad[14], pad[2],  pad[6] );
205       QROUND (pad[15], pad[3],  pad[7],  pad[11]);
206 
207       SALSA20_CORE_DEBUG (i+1);
208       QROUND (pad[0],  pad[1],  pad[2],  pad[3] );
209       QROUND (pad[5],  pad[6],  pad[7],  pad[4] );
210       QROUND (pad[10], pad[11], pad[8],  pad[9] );
211       QROUND (pad[15], pad[12], pad[13], pad[14]);
212     }
213   SALSA20_CORE_DEBUG (i);
214 
215   for (i = 0; i < SALSA20_INPUT_LENGTH; i++)
216     {
217       u32 t = pad[i] + src[i];
218       dst[i] = LE_SWAP32 (t);
219     }
220 
221   /* Update counter. */
222   if (!++src[8])
223     src[9]++;
224 
225   /* burn_stack */
226   return ( 3*sizeof (void*) \
227          + 2*sizeof (void*) \
228          + 64 \
229          + sizeof (unsigned int) \
230          + sizeof (u32) );
231 }
232 #undef QROUND
233 #undef SALSA20_CORE_DEBUG
234 
235 static void
salsa20_keysetup(SALSA20_context_t * ctx,const byte * key,int keylen)236 salsa20_keysetup(SALSA20_context_t *ctx, const byte *key, int keylen)
237 {
238   /* These constants are the little endian encoding of the string
239      "expand 32-byte k".  For the 128 bit variant, the "32" in that
240      string will be fixed up to "16".  */
241   ctx->input[0]  = 0x61707865; /* "apxe"  */
242   ctx->input[5]  = 0x3320646e; /* "3 dn"  */
243   ctx->input[10] = 0x79622d32; /* "yb-2"  */
244   ctx->input[15] = 0x6b206574; /* "k et"  */
245 
246   ctx->input[1] = LE_READ_UINT32(key + 0);
247   ctx->input[2] = LE_READ_UINT32(key + 4);
248   ctx->input[3] = LE_READ_UINT32(key + 8);
249   ctx->input[4] = LE_READ_UINT32(key + 12);
250   if (keylen == SALSA20_MAX_KEY_SIZE) /* 256 bits */
251     {
252       ctx->input[11] = LE_READ_UINT32(key + 16);
253       ctx->input[12] = LE_READ_UINT32(key + 20);
254       ctx->input[13] = LE_READ_UINT32(key + 24);
255       ctx->input[14] = LE_READ_UINT32(key + 28);
256     }
257   else  /* 128 bits */
258     {
259       ctx->input[11] = ctx->input[1];
260       ctx->input[12] = ctx->input[2];
261       ctx->input[13] = ctx->input[3];
262       ctx->input[14] = ctx->input[4];
263 
264       ctx->input[5]  -= 0x02000000; /* Change to "1 dn".  */
265       ctx->input[10] += 0x00000004; /* Change to "yb-6".  */
266     }
267 }
268 
salsa20_ivsetup(SALSA20_context_t * ctx,const byte * iv)269 static void salsa20_ivsetup(SALSA20_context_t *ctx, const byte *iv)
270 {
271   ctx->input[6] = LE_READ_UINT32(iv + 0);
272   ctx->input[7] = LE_READ_UINT32(iv + 4);
273   /* Reset the block counter.  */
274   ctx->input[8] = 0;
275   ctx->input[9] = 0;
276 }
277 
278 #endif /*!USE_AMD64*/
279 
280 #ifdef USE_ARM_NEON_ASM
281 
282 /* ARM NEON implementation of Salsa20. */
283 unsigned int
284 _gcry_arm_neon_salsa20_encrypt(void *c, const void *m, unsigned int nblks,
285                                void *k, unsigned int rounds);
286 
287 static unsigned int
salsa20_core_neon(u32 * dst,SALSA20_context_t * ctx,unsigned int rounds)288 salsa20_core_neon (u32 *dst, SALSA20_context_t *ctx, unsigned int rounds)
289 {
290   return _gcry_arm_neon_salsa20_encrypt(dst, NULL, 1, ctx->input, rounds);
291 }
292 
salsa20_ivsetup_neon(SALSA20_context_t * ctx,const byte * iv)293 static void salsa20_ivsetup_neon(SALSA20_context_t *ctx, const byte *iv)
294 {
295   memcpy(ctx->input + 8, iv, 8);
296   /* Reset the block counter.  */
297   memset(ctx->input + 10, 0, 8);
298 }
299 
300 static void
salsa20_keysetup_neon(SALSA20_context_t * ctx,const byte * key,int klen)301 salsa20_keysetup_neon(SALSA20_context_t *ctx, const byte *key, int klen)
302 {
303   static const unsigned char sigma32[16] = "expand 32-byte k";
304   static const unsigned char sigma16[16] = "expand 16-byte k";
305 
306   if (klen == 16)
307     {
308       memcpy (ctx->input, key, 16);
309       memcpy (ctx->input + 4, key, 16); /* Duplicate 128-bit key. */
310       memcpy (ctx->input + 12, sigma16, 16);
311     }
312   else
313     {
314       /* 32-byte key */
315       memcpy (ctx->input, key, 32);
316       memcpy (ctx->input + 12, sigma32, 16);
317     }
318 }
319 
320 #endif /*USE_ARM_NEON_ASM*/
321 
322 
323 static gcry_err_code_t
salsa20_do_setkey(SALSA20_context_t * ctx,const byte * key,unsigned int keylen)324 salsa20_do_setkey (SALSA20_context_t *ctx,
325                    const byte *key, unsigned int keylen)
326 {
327   static int initialized;
328   static const char *selftest_failed;
329 
330   if (!initialized )
331     {
332       initialized = 1;
333       selftest_failed = selftest ();
334       if (selftest_failed)
335         log_error ("SALSA20 selftest failed (%s)\n", selftest_failed );
336     }
337   if (selftest_failed)
338     return GPG_ERR_SELFTEST_FAILED;
339 
340   if (keylen != SALSA20_MIN_KEY_SIZE
341       && keylen != SALSA20_MAX_KEY_SIZE)
342     return GPG_ERR_INV_KEYLEN;
343 
344   /* Default ops. */
345   ctx->keysetup = salsa20_keysetup;
346   ctx->ivsetup = salsa20_ivsetup;
347   ctx->core = salsa20_core;
348 
349 #ifdef USE_ARM_NEON_ASM
350   ctx->use_neon = (_gcry_get_hw_features () & HWF_ARM_NEON) != 0;
351   if (ctx->use_neon)
352     {
353       /* Use ARM NEON ops instead. */
354       ctx->keysetup = salsa20_keysetup_neon;
355       ctx->ivsetup = salsa20_ivsetup_neon;
356       ctx->core = salsa20_core_neon;
357     }
358 #endif
359 
360   ctx->keysetup (ctx, key, keylen);
361 
362   /* We default to a zero nonce.  */
363   salsa20_setiv (ctx, NULL, 0);
364 
365   return 0;
366 }
367 
368 
369 static gcry_err_code_t
salsa20_setkey(void * context,const byte * key,unsigned int keylen,cipher_bulk_ops_t * bulk_ops)370 salsa20_setkey (void *context, const byte *key, unsigned int keylen,
371                 cipher_bulk_ops_t *bulk_ops)
372 {
373   SALSA20_context_t *ctx = (SALSA20_context_t *)context;
374   gcry_err_code_t rc = salsa20_do_setkey (ctx, key, keylen);
375   (void)bulk_ops;
376   _gcry_burn_stack (4 + sizeof (void *) + 4 * sizeof (void *));
377   return rc;
378 }
379 
380 
381 static void
salsa20_setiv(void * context,const byte * iv,size_t ivlen)382 salsa20_setiv (void *context, const byte *iv, size_t ivlen)
383 {
384   SALSA20_context_t *ctx = (SALSA20_context_t *)context;
385   byte tmp[SALSA20_IV_SIZE];
386 
387   if (iv && ivlen != SALSA20_IV_SIZE)
388     log_info ("WARNING: salsa20_setiv: bad ivlen=%u\n", (u32)ivlen);
389 
390   if (!iv || ivlen != SALSA20_IV_SIZE)
391     memset (tmp, 0, sizeof(tmp));
392   else
393     memcpy (tmp, iv, SALSA20_IV_SIZE);
394 
395   ctx->ivsetup (ctx, tmp);
396 
397   /* Reset the unused pad bytes counter.  */
398   ctx->unused = 0;
399 
400   wipememory (tmp, sizeof(tmp));
401 }
402 
403 
404 
405 /* Note: This function requires LENGTH > 0.  */
406 static void
salsa20_do_encrypt_stream(SALSA20_context_t * ctx,byte * outbuf,const byte * inbuf,size_t length,unsigned rounds)407 salsa20_do_encrypt_stream (SALSA20_context_t *ctx,
408                            byte *outbuf, const byte *inbuf,
409                            size_t length, unsigned rounds)
410 {
411   unsigned int nburn, burn = 0;
412 
413   if (ctx->unused)
414     {
415       unsigned char *p = (void*)ctx->pad;
416       size_t n;
417 
418       gcry_assert (ctx->unused < SALSA20_BLOCK_SIZE);
419 
420       n = ctx->unused;
421       if (n > length)
422         n = length;
423       buf_xor (outbuf, inbuf, p + SALSA20_BLOCK_SIZE - ctx->unused, n);
424       length -= n;
425       outbuf += n;
426       inbuf  += n;
427       ctx->unused -= n;
428       if (!length)
429         return;
430       gcry_assert (!ctx->unused);
431     }
432 
433 #ifdef USE_AMD64
434   if (length >= SALSA20_BLOCK_SIZE)
435     {
436       size_t nblocks = length / SALSA20_BLOCK_SIZE;
437       burn = _gcry_salsa20_amd64_encrypt_blocks(ctx->input, inbuf, outbuf,
438                                                 nblocks, rounds);
439       burn += ASM_EXTRA_STACK;
440       length -= SALSA20_BLOCK_SIZE * nblocks;
441       outbuf += SALSA20_BLOCK_SIZE * nblocks;
442       inbuf  += SALSA20_BLOCK_SIZE * nblocks;
443     }
444 #endif
445 
446 #ifdef USE_ARM_NEON_ASM
447   if (ctx->use_neon && length >= SALSA20_BLOCK_SIZE)
448     {
449       unsigned int nblocks = length / SALSA20_BLOCK_SIZE;
450       _gcry_arm_neon_salsa20_encrypt (outbuf, inbuf, nblocks, ctx->input,
451                                       rounds);
452       length -= SALSA20_BLOCK_SIZE * nblocks;
453       outbuf += SALSA20_BLOCK_SIZE * nblocks;
454       inbuf  += SALSA20_BLOCK_SIZE * nblocks;
455     }
456 #endif
457 
458   while (length > 0)
459     {
460       /* Create the next pad and bump the block counter.  Note that it
461          is the user's duty to change to another nonce not later than
462          after 2^70 processed bytes.  */
463       nburn = ctx->core (ctx->pad, ctx, rounds);
464       burn = nburn > burn ? nburn : burn;
465 
466       if (length <= SALSA20_BLOCK_SIZE)
467 	{
468 	  buf_xor (outbuf, inbuf, ctx->pad, length);
469           ctx->unused = SALSA20_BLOCK_SIZE - length;
470 	  break;
471 	}
472       buf_xor (outbuf, inbuf, ctx->pad, SALSA20_BLOCK_SIZE);
473       length -= SALSA20_BLOCK_SIZE;
474       outbuf += SALSA20_BLOCK_SIZE;
475       inbuf  += SALSA20_BLOCK_SIZE;
476     }
477 
478   _gcry_burn_stack (burn);
479 }
480 
481 
482 static void
salsa20_encrypt_stream(void * context,byte * outbuf,const byte * inbuf,size_t length)483 salsa20_encrypt_stream (void *context,
484                         byte *outbuf, const byte *inbuf, size_t length)
485 {
486   SALSA20_context_t *ctx = (SALSA20_context_t *)context;
487 
488   if (length)
489     salsa20_do_encrypt_stream (ctx, outbuf, inbuf, length, SALSA20_ROUNDS);
490 }
491 
492 
493 static void
salsa20r12_encrypt_stream(void * context,byte * outbuf,const byte * inbuf,size_t length)494 salsa20r12_encrypt_stream (void *context,
495                            byte *outbuf, const byte *inbuf, size_t length)
496 {
497   SALSA20_context_t *ctx = (SALSA20_context_t *)context;
498 
499   if (length)
500     salsa20_do_encrypt_stream (ctx, outbuf, inbuf, length, SALSA20R12_ROUNDS);
501 }
502 
503 
504 static const char*
selftest(void)505 selftest (void)
506 {
507   byte ctxbuf[sizeof(SALSA20_context_t) + 15];
508   SALSA20_context_t *ctx;
509   byte scratch[8+1];
510   byte buf[256+64+4];
511   int i;
512 
513   static byte key_1[] =
514     { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
515       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
516       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
517       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
518   static const byte nonce_1[] =
519     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
520   static const byte plaintext_1[] =
521     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
522   static const byte ciphertext_1[] =
523     { 0xE3, 0xBE, 0x8F, 0xDD, 0x8B, 0xEC, 0xA2, 0xE3};
524 
525   /* 16-byte alignment required for amd64 implementation. */
526   ctx = (SALSA20_context_t *)((uintptr_t)(ctxbuf + 15) & ~(uintptr_t)15);
527 
528   salsa20_setkey (ctx, key_1, sizeof key_1, NULL);
529   salsa20_setiv  (ctx, nonce_1, sizeof nonce_1);
530   scratch[8] = 0;
531   salsa20_encrypt_stream (ctx, scratch, plaintext_1, sizeof plaintext_1);
532   if (memcmp (scratch, ciphertext_1, sizeof ciphertext_1))
533     return "Salsa20 encryption test 1 failed.";
534   if (scratch[8])
535     return "Salsa20 wrote too much.";
536   salsa20_setkey( ctx, key_1, sizeof(key_1), NULL);
537   salsa20_setiv  (ctx, nonce_1, sizeof nonce_1);
538   salsa20_encrypt_stream (ctx, scratch, scratch, sizeof plaintext_1);
539   if (memcmp (scratch, plaintext_1, sizeof plaintext_1))
540     return "Salsa20 decryption test 1 failed.";
541 
542   for (i = 0; i < sizeof buf; i++)
543     buf[i] = i;
544   salsa20_setkey (ctx, key_1, sizeof key_1, NULL);
545   salsa20_setiv (ctx, nonce_1, sizeof nonce_1);
546   /*encrypt*/
547   salsa20_encrypt_stream (ctx, buf, buf, sizeof buf);
548   /*decrypt*/
549   salsa20_setkey (ctx, key_1, sizeof key_1, NULL);
550   salsa20_setiv (ctx, nonce_1, sizeof nonce_1);
551   salsa20_encrypt_stream (ctx, buf, buf, 1);
552   salsa20_encrypt_stream (ctx, buf+1, buf+1, (sizeof buf)-1-1);
553   salsa20_encrypt_stream (ctx, buf+(sizeof buf)-1, buf+(sizeof buf)-1, 1);
554   for (i = 0; i < sizeof buf; i++)
555     if (buf[i] != (byte)i)
556       return "Salsa20 encryption test 2 failed.";
557 
558   return NULL;
559 }
560 
561 
562 gcry_cipher_spec_t _gcry_cipher_spec_salsa20 =
563   {
564     GCRY_CIPHER_SALSA20,
565     {0, 0},     /* flags */
566     "SALSA20",  /* name */
567     NULL,       /* aliases */
568     NULL,       /* oids */
569     1,          /* blocksize in bytes. */
570     SALSA20_MAX_KEY_SIZE*8,  /* standard key length in bits. */
571     sizeof (SALSA20_context_t),
572     salsa20_setkey,
573     NULL,
574     NULL,
575     salsa20_encrypt_stream,
576     salsa20_encrypt_stream,
577     NULL,
578     NULL,
579     salsa20_setiv
580   };
581 
582 gcry_cipher_spec_t _gcry_cipher_spec_salsa20r12 =
583   {
584     GCRY_CIPHER_SALSA20R12,
585     {0, 0},     /* flags */
586     "SALSA20R12",  /* name */
587     NULL,       /* aliases */
588     NULL,       /* oids */
589     1,          /* blocksize in bytes. */
590     SALSA20_MAX_KEY_SIZE*8,  /* standard key length in bits. */
591     sizeof (SALSA20_context_t),
592     salsa20_setkey,
593     NULL,
594     NULL,
595     salsa20r12_encrypt_stream,
596     salsa20r12_encrypt_stream,
597     NULL,
598     NULL,
599     salsa20_setiv
600   };
601