Coverage Report

Created: 2022-12-08 06:09

/src/libgcrypt/cipher/salsa20.c
Line
Count
Source (jump to first uncovered line)
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
0
#define SALSA20_MIN_KEY_SIZE 16  /* Bytes.  */
64
0
#define SALSA20_MAX_KEY_SIZE 32  /* Bytes.  */
65
0
#define SALSA20_BLOCK_SIZE   64  /* Bytes.  */
66
0
#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
0
#define SALSA20_ROUNDS       20
72
0
#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
0
# 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
144
salsa20_keysetup(SALSA20_context_t *ctx, const byte *key, int keylen)
145
0
{
146
0
  _gcry_salsa20_amd64_keysetup(ctx->input, key, keylen * 8);
147
0
}
148
149
static void
150
salsa20_ivsetup(SALSA20_context_t *ctx, const byte *iv)
151
0
{
152
0
  _gcry_salsa20_amd64_ivsetup(ctx->input, iv);
153
0
}
154
155
static unsigned int
156
salsa20_core (u32 *dst, SALSA20_context_t *ctx, unsigned int rounds)
157
0
{
158
0
  memset(dst, 0, SALSA20_BLOCK_SIZE);
159
0
  return _gcry_salsa20_amd64_encrypt_blocks(ctx->input, dst, dst, 1, rounds)
160
0
         + ASM_EXTRA_STACK;
161
0
}
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
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
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
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
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
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
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
324
salsa20_do_setkey (SALSA20_context_t *ctx,
325
                   const byte *key, unsigned int keylen)
326
0
{
327
0
  static int initialized;
328
0
  static const char *selftest_failed;
329
330
0
  if (!initialized )
331
0
    {
332
0
      initialized = 1;
333
0
      selftest_failed = selftest ();
334
0
      if (selftest_failed)
335
0
        log_error ("SALSA20 selftest failed (%s)\n", selftest_failed );
336
0
    }
337
0
  if (selftest_failed)
338
0
    return GPG_ERR_SELFTEST_FAILED;
339
340
0
  if (keylen != SALSA20_MIN_KEY_SIZE
341
0
      && keylen != SALSA20_MAX_KEY_SIZE)
342
0
    return GPG_ERR_INV_KEYLEN;
343
344
  /* Default ops. */
345
0
  ctx->keysetup = salsa20_keysetup;
346
0
  ctx->ivsetup = salsa20_ivsetup;
347
0
  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
0
  ctx->keysetup (ctx, key, keylen);
361
362
  /* We default to a zero nonce.  */
363
0
  salsa20_setiv (ctx, NULL, 0);
364
365
0
  return 0;
366
0
}
367
368
369
static gcry_err_code_t
370
salsa20_setkey (void *context, const byte *key, unsigned int keylen,
371
                cipher_bulk_ops_t *bulk_ops)
372
0
{
373
0
  SALSA20_context_t *ctx = (SALSA20_context_t *)context;
374
0
  gcry_err_code_t rc = salsa20_do_setkey (ctx, key, keylen);
375
0
  (void)bulk_ops;
376
0
  _gcry_burn_stack (4 + sizeof (void *) + 4 * sizeof (void *));
377
0
  return rc;
378
0
}
379
380
381
static void
382
salsa20_setiv (void *context, const byte *iv, size_t ivlen)
383
0
{
384
0
  SALSA20_context_t *ctx = (SALSA20_context_t *)context;
385
0
  byte tmp[SALSA20_IV_SIZE];
386
387
0
  if (iv && ivlen != SALSA20_IV_SIZE)
388
0
    log_info ("WARNING: salsa20_setiv: bad ivlen=%u\n", (u32)ivlen);
389
390
0
  if (!iv || ivlen != SALSA20_IV_SIZE)
391
0
    memset (tmp, 0, sizeof(tmp));
392
0
  else
393
0
    memcpy (tmp, iv, SALSA20_IV_SIZE);
394
395
0
  ctx->ivsetup (ctx, tmp);
396
397
  /* Reset the unused pad bytes counter.  */
398
0
  ctx->unused = 0;
399
400
0
  wipememory (tmp, sizeof(tmp));
401
0
}
402
403
404

405
/* Note: This function requires LENGTH > 0.  */
406
static void
407
salsa20_do_encrypt_stream (SALSA20_context_t *ctx,
408
                           byte *outbuf, const byte *inbuf,
409
                           size_t length, unsigned rounds)
410
0
{
411
0
  unsigned int nburn, burn = 0;
412
413
0
  if (ctx->unused)
414
0
    {
415
0
      unsigned char *p = (void*)ctx->pad;
416
0
      size_t n;
417
418
0
      gcry_assert (ctx->unused < SALSA20_BLOCK_SIZE);
419
420
0
      n = ctx->unused;
421
0
      if (n > length)
422
0
        n = length;
423
0
      buf_xor (outbuf, inbuf, p + SALSA20_BLOCK_SIZE - ctx->unused, n);
424
0
      length -= n;
425
0
      outbuf += n;
426
0
      inbuf  += n;
427
0
      ctx->unused -= n;
428
0
      if (!length)
429
0
        return;
430
0
      gcry_assert (!ctx->unused);
431
0
    }
432
433
0
#ifdef USE_AMD64
434
0
  if (length >= SALSA20_BLOCK_SIZE)
435
0
    {
436
0
      size_t nblocks = length / SALSA20_BLOCK_SIZE;
437
0
      burn = _gcry_salsa20_amd64_encrypt_blocks(ctx->input, inbuf, outbuf,
438
0
                                                nblocks, rounds);
439
0
      burn += ASM_EXTRA_STACK;
440
0
      length -= SALSA20_BLOCK_SIZE * nblocks;
441
0
      outbuf += SALSA20_BLOCK_SIZE * nblocks;
442
0
      inbuf  += SALSA20_BLOCK_SIZE * nblocks;
443
0
    }
444
0
#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
0
  while (length > 0)
459
0
    {
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
0
      nburn = ctx->core (ctx->pad, ctx, rounds);
464
0
      burn = nburn > burn ? nburn : burn;
465
466
0
      if (length <= SALSA20_BLOCK_SIZE)
467
0
  {
468
0
    buf_xor (outbuf, inbuf, ctx->pad, length);
469
0
          ctx->unused = SALSA20_BLOCK_SIZE - length;
470
0
    break;
471
0
  }
472
0
      buf_xor (outbuf, inbuf, ctx->pad, SALSA20_BLOCK_SIZE);
473
0
      length -= SALSA20_BLOCK_SIZE;
474
0
      outbuf += SALSA20_BLOCK_SIZE;
475
0
      inbuf  += SALSA20_BLOCK_SIZE;
476
0
    }
477
478
0
  _gcry_burn_stack (burn);
479
0
}
480
481
482
static void
483
salsa20_encrypt_stream (void *context,
484
                        byte *outbuf, const byte *inbuf, size_t length)
485
0
{
486
0
  SALSA20_context_t *ctx = (SALSA20_context_t *)context;
487
488
0
  if (length)
489
0
    salsa20_do_encrypt_stream (ctx, outbuf, inbuf, length, SALSA20_ROUNDS);
490
0
}
491
492
493
static void
494
salsa20r12_encrypt_stream (void *context,
495
                           byte *outbuf, const byte *inbuf, size_t length)
496
0
{
497
0
  SALSA20_context_t *ctx = (SALSA20_context_t *)context;
498
499
0
  if (length)
500
0
    salsa20_do_encrypt_stream (ctx, outbuf, inbuf, length, SALSA20R12_ROUNDS);
501
0
}
502
503
504
static const char*
505
selftest (void)
506
0
{
507
0
  byte ctxbuf[sizeof(SALSA20_context_t) + 15];
508
0
  SALSA20_context_t *ctx;
509
0
  byte scratch[8+1];
510
0
  byte buf[256+64+4];
511
0
  int i;
512
513
0
  static byte key_1[] =
514
0
    { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
515
0
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
516
0
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
517
0
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
518
0
  static const byte nonce_1[] =
519
0
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
520
0
  static const byte plaintext_1[] =
521
0
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
522
0
  static const byte ciphertext_1[] =
523
0
    { 0xE3, 0xBE, 0x8F, 0xDD, 0x8B, 0xEC, 0xA2, 0xE3};
524
525
  /* 16-byte alignment required for amd64 implementation. */
526
0
  ctx = (SALSA20_context_t *)((uintptr_t)(ctxbuf + 15) & ~(uintptr_t)15);
527
528
0
  salsa20_setkey (ctx, key_1, sizeof key_1, NULL);
529
0
  salsa20_setiv  (ctx, nonce_1, sizeof nonce_1);
530
0
  scratch[8] = 0;
531
0
  salsa20_encrypt_stream (ctx, scratch, plaintext_1, sizeof plaintext_1);
532
0
  if (memcmp (scratch, ciphertext_1, sizeof ciphertext_1))
533
0
    return "Salsa20 encryption test 1 failed.";
534
0
  if (scratch[8])
535
0
    return "Salsa20 wrote too much.";
536
0
  salsa20_setkey( ctx, key_1, sizeof(key_1), NULL);
537
0
  salsa20_setiv  (ctx, nonce_1, sizeof nonce_1);
538
0
  salsa20_encrypt_stream (ctx, scratch, scratch, sizeof plaintext_1);
539
0
  if (memcmp (scratch, plaintext_1, sizeof plaintext_1))
540
0
    return "Salsa20 decryption test 1 failed.";
541
542
0
  for (i = 0; i < sizeof buf; i++)
543
0
    buf[i] = i;
544
0
  salsa20_setkey (ctx, key_1, sizeof key_1, NULL);
545
0
  salsa20_setiv (ctx, nonce_1, sizeof nonce_1);
546
  /*encrypt*/
547
0
  salsa20_encrypt_stream (ctx, buf, buf, sizeof buf);
548
  /*decrypt*/
549
0
  salsa20_setkey (ctx, key_1, sizeof key_1, NULL);
550
0
  salsa20_setiv (ctx, nonce_1, sizeof nonce_1);
551
0
  salsa20_encrypt_stream (ctx, buf, buf, 1);
552
0
  salsa20_encrypt_stream (ctx, buf+1, buf+1, (sizeof buf)-1-1);
553
0
  salsa20_encrypt_stream (ctx, buf+(sizeof buf)-1, buf+(sizeof buf)-1, 1);
554
0
  for (i = 0; i < sizeof buf; i++)
555
0
    if (buf[i] != (byte)i)
556
0
      return "Salsa20 encryption test 2 failed.";
557
558
0
  return NULL;
559
0
}
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
  };