2 * Salsa20: Salsa20 stream cipher algorithm
4 * Copyright (c) 2007 Tan Swee Heng <thesweeheng@gmail.com>
7 * - salsa20.c: Public domain C code by Daniel J. Bernstein <djb@cr.yp.to>
9 * Salsa20 is a stream cipher candidate in eSTREAM, the ECRYPT Stream
10 * Cipher Project. It is designed by Daniel J. Bernstein <djb@cr.yp.to>.
11 * More information about eSTREAM and Salsa20 can be found here:
12 * http://www.ecrypt.eu.org/stream/
13 * http://cr.yp.to/snuffle.html
15 * This program is free software; you can redistribute it and/or modify it
16 * under the terms of the GNU General Public License as published by the Free
17 * Software Foundation; either version 2 of the License, or (at your option)
22 #include <asm/unaligned.h>
23 #include <crypto/internal/skcipher.h>
24 #include <crypto/salsa20.h>
25 #include <linux/module.h>
27 static void salsa20_block(u32
*state
, __le32
*stream
)
32 memcpy(x
, state
, sizeof(x
));
34 for (i
= 0; i
< 20; i
+= 2) {
35 x
[ 4] ^= rol32((x
[ 0] + x
[12]), 7);
36 x
[ 8] ^= rol32((x
[ 4] + x
[ 0]), 9);
37 x
[12] ^= rol32((x
[ 8] + x
[ 4]), 13);
38 x
[ 0] ^= rol32((x
[12] + x
[ 8]), 18);
39 x
[ 9] ^= rol32((x
[ 5] + x
[ 1]), 7);
40 x
[13] ^= rol32((x
[ 9] + x
[ 5]), 9);
41 x
[ 1] ^= rol32((x
[13] + x
[ 9]), 13);
42 x
[ 5] ^= rol32((x
[ 1] + x
[13]), 18);
43 x
[14] ^= rol32((x
[10] + x
[ 6]), 7);
44 x
[ 2] ^= rol32((x
[14] + x
[10]), 9);
45 x
[ 6] ^= rol32((x
[ 2] + x
[14]), 13);
46 x
[10] ^= rol32((x
[ 6] + x
[ 2]), 18);
47 x
[ 3] ^= rol32((x
[15] + x
[11]), 7);
48 x
[ 7] ^= rol32((x
[ 3] + x
[15]), 9);
49 x
[11] ^= rol32((x
[ 7] + x
[ 3]), 13);
50 x
[15] ^= rol32((x
[11] + x
[ 7]), 18);
51 x
[ 1] ^= rol32((x
[ 0] + x
[ 3]), 7);
52 x
[ 2] ^= rol32((x
[ 1] + x
[ 0]), 9);
53 x
[ 3] ^= rol32((x
[ 2] + x
[ 1]), 13);
54 x
[ 0] ^= rol32((x
[ 3] + x
[ 2]), 18);
55 x
[ 6] ^= rol32((x
[ 5] + x
[ 4]), 7);
56 x
[ 7] ^= rol32((x
[ 6] + x
[ 5]), 9);
57 x
[ 4] ^= rol32((x
[ 7] + x
[ 6]), 13);
58 x
[ 5] ^= rol32((x
[ 4] + x
[ 7]), 18);
59 x
[11] ^= rol32((x
[10] + x
[ 9]), 7);
60 x
[ 8] ^= rol32((x
[11] + x
[10]), 9);
61 x
[ 9] ^= rol32((x
[ 8] + x
[11]), 13);
62 x
[10] ^= rol32((x
[ 9] + x
[ 8]), 18);
63 x
[12] ^= rol32((x
[15] + x
[14]), 7);
64 x
[13] ^= rol32((x
[12] + x
[15]), 9);
65 x
[14] ^= rol32((x
[13] + x
[12]), 13);
66 x
[15] ^= rol32((x
[14] + x
[13]), 18);
69 for (i
= 0; i
< 16; i
++)
70 stream
[i
] = cpu_to_le32(x
[i
] + state
[i
]);
76 static void salsa20_docrypt(u32
*state
, u8
*dst
, const u8
*src
,
79 __le32 stream
[SALSA20_BLOCK_SIZE
/ sizeof(__le32
)];
82 memcpy(dst
, src
, bytes
);
84 while (bytes
>= SALSA20_BLOCK_SIZE
) {
85 salsa20_block(state
, stream
);
86 crypto_xor(dst
, (const u8
*)stream
, SALSA20_BLOCK_SIZE
);
87 bytes
-= SALSA20_BLOCK_SIZE
;
88 dst
+= SALSA20_BLOCK_SIZE
;
91 salsa20_block(state
, stream
);
92 crypto_xor(dst
, (const u8
*)stream
, bytes
);
96 void crypto_salsa20_init(u32
*state
, const struct salsa20_ctx
*ctx
,
99 memcpy(state
, ctx
->initial_state
, sizeof(ctx
->initial_state
));
100 state
[6] = get_unaligned_le32(iv
+ 0);
101 state
[7] = get_unaligned_le32(iv
+ 4);
103 EXPORT_SYMBOL_GPL(crypto_salsa20_init
);
105 int crypto_salsa20_setkey(struct crypto_skcipher
*tfm
, const u8
*key
,
106 unsigned int keysize
)
108 static const char sigma
[16] = "expand 32-byte k";
109 static const char tau
[16] = "expand 16-byte k";
110 struct salsa20_ctx
*ctx
= crypto_skcipher_ctx(tfm
);
111 const char *constants
;
113 if (keysize
!= SALSA20_MIN_KEY_SIZE
&&
114 keysize
!= SALSA20_MAX_KEY_SIZE
)
117 ctx
->initial_state
[1] = get_unaligned_le32(key
+ 0);
118 ctx
->initial_state
[2] = get_unaligned_le32(key
+ 4);
119 ctx
->initial_state
[3] = get_unaligned_le32(key
+ 8);
120 ctx
->initial_state
[4] = get_unaligned_le32(key
+ 12);
121 if (keysize
== 32) { /* recommended */
124 } else { /* keysize == 16 */
127 ctx
->initial_state
[11] = get_unaligned_le32(key
+ 0);
128 ctx
->initial_state
[12] = get_unaligned_le32(key
+ 4);
129 ctx
->initial_state
[13] = get_unaligned_le32(key
+ 8);
130 ctx
->initial_state
[14] = get_unaligned_le32(key
+ 12);
131 ctx
->initial_state
[0] = get_unaligned_le32(constants
+ 0);
132 ctx
->initial_state
[5] = get_unaligned_le32(constants
+ 4);
133 ctx
->initial_state
[10] = get_unaligned_le32(constants
+ 8);
134 ctx
->initial_state
[15] = get_unaligned_le32(constants
+ 12);
136 /* space for the nonce; it will be overridden for each request */
137 ctx
->initial_state
[6] = 0;
138 ctx
->initial_state
[7] = 0;
140 /* initial block number */
141 ctx
->initial_state
[8] = 0;
142 ctx
->initial_state
[9] = 0;
146 EXPORT_SYMBOL_GPL(crypto_salsa20_setkey
);
148 static int salsa20_crypt(struct skcipher_request
*req
)
150 struct crypto_skcipher
*tfm
= crypto_skcipher_reqtfm(req
);
151 const struct salsa20_ctx
*ctx
= crypto_skcipher_ctx(tfm
);
152 struct skcipher_walk walk
;
156 err
= skcipher_walk_virt(&walk
, req
, true);
158 crypto_salsa20_init(state
, ctx
, walk
.iv
);
160 while (walk
.nbytes
> 0) {
161 unsigned int nbytes
= walk
.nbytes
;
163 if (nbytes
< walk
.total
)
164 nbytes
= round_down(nbytes
, walk
.stride
);
166 salsa20_docrypt(state
, walk
.dst
.virt
.addr
, walk
.src
.virt
.addr
,
168 err
= skcipher_walk_done(&walk
, walk
.nbytes
- nbytes
);
174 static struct skcipher_alg alg
= {
175 .base
.cra_name
= "salsa20",
176 .base
.cra_driver_name
= "salsa20-generic",
177 .base
.cra_priority
= 100,
178 .base
.cra_blocksize
= 1,
179 .base
.cra_ctxsize
= sizeof(struct salsa20_ctx
),
180 .base
.cra_module
= THIS_MODULE
,
182 .min_keysize
= SALSA20_MIN_KEY_SIZE
,
183 .max_keysize
= SALSA20_MAX_KEY_SIZE
,
184 .ivsize
= SALSA20_IV_SIZE
,
185 .chunksize
= SALSA20_BLOCK_SIZE
,
186 .setkey
= crypto_salsa20_setkey
,
187 .encrypt
= salsa20_crypt
,
188 .decrypt
= salsa20_crypt
,
191 static int __init
salsa20_generic_mod_init(void)
193 return crypto_register_skcipher(&alg
);
196 static void __exit
salsa20_generic_mod_fini(void)
198 crypto_unregister_skcipher(&alg
);
201 module_init(salsa20_generic_mod_init
);
202 module_exit(salsa20_generic_mod_fini
);
204 MODULE_LICENSE("GPL");
205 MODULE_DESCRIPTION ("Salsa20 stream cipher algorithm");
206 MODULE_ALIAS_CRYPTO("salsa20");
207 MODULE_ALIAS_CRYPTO("salsa20-generic");