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 <linux/module.h>
26 #define SALSA20_IV_SIZE 8
27 #define SALSA20_MIN_KEY_SIZE 16
28 #define SALSA20_MAX_KEY_SIZE 32
29 #define SALSA20_BLOCK_SIZE 64
32 u32 initial_state
[16];
35 static void salsa20_block(u32
*state
, __le32
*stream
)
40 memcpy(x
, state
, sizeof(x
));
42 for (i
= 0; i
< 20; i
+= 2) {
43 x
[ 4] ^= rol32((x
[ 0] + x
[12]), 7);
44 x
[ 8] ^= rol32((x
[ 4] + x
[ 0]), 9);
45 x
[12] ^= rol32((x
[ 8] + x
[ 4]), 13);
46 x
[ 0] ^= rol32((x
[12] + x
[ 8]), 18);
47 x
[ 9] ^= rol32((x
[ 5] + x
[ 1]), 7);
48 x
[13] ^= rol32((x
[ 9] + x
[ 5]), 9);
49 x
[ 1] ^= rol32((x
[13] + x
[ 9]), 13);
50 x
[ 5] ^= rol32((x
[ 1] + x
[13]), 18);
51 x
[14] ^= rol32((x
[10] + x
[ 6]), 7);
52 x
[ 2] ^= rol32((x
[14] + x
[10]), 9);
53 x
[ 6] ^= rol32((x
[ 2] + x
[14]), 13);
54 x
[10] ^= rol32((x
[ 6] + x
[ 2]), 18);
55 x
[ 3] ^= rol32((x
[15] + x
[11]), 7);
56 x
[ 7] ^= rol32((x
[ 3] + x
[15]), 9);
57 x
[11] ^= rol32((x
[ 7] + x
[ 3]), 13);
58 x
[15] ^= rol32((x
[11] + x
[ 7]), 18);
59 x
[ 1] ^= rol32((x
[ 0] + x
[ 3]), 7);
60 x
[ 2] ^= rol32((x
[ 1] + x
[ 0]), 9);
61 x
[ 3] ^= rol32((x
[ 2] + x
[ 1]), 13);
62 x
[ 0] ^= rol32((x
[ 3] + x
[ 2]), 18);
63 x
[ 6] ^= rol32((x
[ 5] + x
[ 4]), 7);
64 x
[ 7] ^= rol32((x
[ 6] + x
[ 5]), 9);
65 x
[ 4] ^= rol32((x
[ 7] + x
[ 6]), 13);
66 x
[ 5] ^= rol32((x
[ 4] + x
[ 7]), 18);
67 x
[11] ^= rol32((x
[10] + x
[ 9]), 7);
68 x
[ 8] ^= rol32((x
[11] + x
[10]), 9);
69 x
[ 9] ^= rol32((x
[ 8] + x
[11]), 13);
70 x
[10] ^= rol32((x
[ 9] + x
[ 8]), 18);
71 x
[12] ^= rol32((x
[15] + x
[14]), 7);
72 x
[13] ^= rol32((x
[12] + x
[15]), 9);
73 x
[14] ^= rol32((x
[13] + x
[12]), 13);
74 x
[15] ^= rol32((x
[14] + x
[13]), 18);
77 for (i
= 0; i
< 16; i
++)
78 stream
[i
] = cpu_to_le32(x
[i
] + state
[i
]);
84 static void salsa20_docrypt(u32
*state
, u8
*dst
, const u8
*src
,
87 __le32 stream
[SALSA20_BLOCK_SIZE
/ sizeof(__le32
)];
90 memcpy(dst
, src
, bytes
);
92 while (bytes
>= SALSA20_BLOCK_SIZE
) {
93 salsa20_block(state
, stream
);
94 crypto_xor(dst
, (const u8
*)stream
, SALSA20_BLOCK_SIZE
);
95 bytes
-= SALSA20_BLOCK_SIZE
;
96 dst
+= SALSA20_BLOCK_SIZE
;
99 salsa20_block(state
, stream
);
100 crypto_xor(dst
, (const u8
*)stream
, bytes
);
104 static void salsa20_init(u32
*state
, const struct salsa20_ctx
*ctx
,
107 memcpy(state
, ctx
->initial_state
, sizeof(ctx
->initial_state
));
108 state
[6] = get_unaligned_le32(iv
+ 0);
109 state
[7] = get_unaligned_le32(iv
+ 4);
112 static int salsa20_setkey(struct crypto_skcipher
*tfm
, const u8
*key
,
113 unsigned int keysize
)
115 static const char sigma
[16] = "expand 32-byte k";
116 static const char tau
[16] = "expand 16-byte k";
117 struct salsa20_ctx
*ctx
= crypto_skcipher_ctx(tfm
);
118 const char *constants
;
120 if (keysize
!= SALSA20_MIN_KEY_SIZE
&&
121 keysize
!= SALSA20_MAX_KEY_SIZE
)
124 ctx
->initial_state
[1] = get_unaligned_le32(key
+ 0);
125 ctx
->initial_state
[2] = get_unaligned_le32(key
+ 4);
126 ctx
->initial_state
[3] = get_unaligned_le32(key
+ 8);
127 ctx
->initial_state
[4] = get_unaligned_le32(key
+ 12);
128 if (keysize
== 32) { /* recommended */
131 } else { /* keysize == 16 */
134 ctx
->initial_state
[11] = get_unaligned_le32(key
+ 0);
135 ctx
->initial_state
[12] = get_unaligned_le32(key
+ 4);
136 ctx
->initial_state
[13] = get_unaligned_le32(key
+ 8);
137 ctx
->initial_state
[14] = get_unaligned_le32(key
+ 12);
138 ctx
->initial_state
[0] = get_unaligned_le32(constants
+ 0);
139 ctx
->initial_state
[5] = get_unaligned_le32(constants
+ 4);
140 ctx
->initial_state
[10] = get_unaligned_le32(constants
+ 8);
141 ctx
->initial_state
[15] = get_unaligned_le32(constants
+ 12);
143 /* space for the nonce; it will be overridden for each request */
144 ctx
->initial_state
[6] = 0;
145 ctx
->initial_state
[7] = 0;
147 /* initial block number */
148 ctx
->initial_state
[8] = 0;
149 ctx
->initial_state
[9] = 0;
154 static int salsa20_crypt(struct skcipher_request
*req
)
156 struct crypto_skcipher
*tfm
= crypto_skcipher_reqtfm(req
);
157 const struct salsa20_ctx
*ctx
= crypto_skcipher_ctx(tfm
);
158 struct skcipher_walk walk
;
162 err
= skcipher_walk_virt(&walk
, req
, false);
164 salsa20_init(state
, ctx
, walk
.iv
);
166 while (walk
.nbytes
> 0) {
167 unsigned int nbytes
= walk
.nbytes
;
169 if (nbytes
< walk
.total
)
170 nbytes
= round_down(nbytes
, walk
.stride
);
172 salsa20_docrypt(state
, walk
.dst
.virt
.addr
, walk
.src
.virt
.addr
,
174 err
= skcipher_walk_done(&walk
, walk
.nbytes
- nbytes
);
180 static struct skcipher_alg alg
= {
181 .base
.cra_name
= "salsa20",
182 .base
.cra_driver_name
= "salsa20-generic",
183 .base
.cra_priority
= 100,
184 .base
.cra_blocksize
= 1,
185 .base
.cra_ctxsize
= sizeof(struct salsa20_ctx
),
186 .base
.cra_module
= THIS_MODULE
,
188 .min_keysize
= SALSA20_MIN_KEY_SIZE
,
189 .max_keysize
= SALSA20_MAX_KEY_SIZE
,
190 .ivsize
= SALSA20_IV_SIZE
,
191 .chunksize
= SALSA20_BLOCK_SIZE
,
192 .setkey
= salsa20_setkey
,
193 .encrypt
= salsa20_crypt
,
194 .decrypt
= salsa20_crypt
,
197 static int __init
salsa20_generic_mod_init(void)
199 return crypto_register_skcipher(&alg
);
202 static void __exit
salsa20_generic_mod_fini(void)
204 crypto_unregister_skcipher(&alg
);
207 module_init(salsa20_generic_mod_init
);
208 module_exit(salsa20_generic_mod_fini
);
210 MODULE_LICENSE("GPL");
211 MODULE_DESCRIPTION ("Salsa20 stream cipher algorithm");
212 MODULE_ALIAS_CRYPTO("salsa20");
213 MODULE_ALIAS_CRYPTO("salsa20-generic");