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