1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Salsa20: Salsa20 stream cipher algorithm
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Copyright (c) 2007 Tan Swee Heng <thesweeheng@gmail.com>
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Derived from:
7*4882a593Smuzhiyun * - salsa20.c: Public domain C code by Daniel J. Bernstein <djb@cr.yp.to>
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun * Salsa20 is a stream cipher candidate in eSTREAM, the ECRYPT Stream
10*4882a593Smuzhiyun * Cipher Project. It is designed by Daniel J. Bernstein <djb@cr.yp.to>.
11*4882a593Smuzhiyun * More information about eSTREAM and Salsa20 can be found here:
12*4882a593Smuzhiyun * https://www.ecrypt.eu.org/stream/
13*4882a593Smuzhiyun * https://cr.yp.to/snuffle.html
14*4882a593Smuzhiyun *
15*4882a593Smuzhiyun * This program is free software; you can redistribute it and/or modify it
16*4882a593Smuzhiyun * under the terms of the GNU General Public License as published by the Free
17*4882a593Smuzhiyun * Software Foundation; either version 2 of the License, or (at your option)
18*4882a593Smuzhiyun * any later version.
19*4882a593Smuzhiyun *
20*4882a593Smuzhiyun */
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun #include <asm/unaligned.h>
23*4882a593Smuzhiyun #include <crypto/internal/skcipher.h>
24*4882a593Smuzhiyun #include <linux/module.h>
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun #define SALSA20_IV_SIZE 8
27*4882a593Smuzhiyun #define SALSA20_MIN_KEY_SIZE 16
28*4882a593Smuzhiyun #define SALSA20_MAX_KEY_SIZE 32
29*4882a593Smuzhiyun #define SALSA20_BLOCK_SIZE 64
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun struct salsa20_ctx {
32*4882a593Smuzhiyun u32 initial_state[16];
33*4882a593Smuzhiyun };
34*4882a593Smuzhiyun
salsa20_block(u32 * state,__le32 * stream)35*4882a593Smuzhiyun static void salsa20_block(u32 *state, __le32 *stream)
36*4882a593Smuzhiyun {
37*4882a593Smuzhiyun u32 x[16];
38*4882a593Smuzhiyun int i;
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun memcpy(x, state, sizeof(x));
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun for (i = 0; i < 20; i += 2) {
43*4882a593Smuzhiyun x[ 4] ^= rol32((x[ 0] + x[12]), 7);
44*4882a593Smuzhiyun x[ 8] ^= rol32((x[ 4] + x[ 0]), 9);
45*4882a593Smuzhiyun x[12] ^= rol32((x[ 8] + x[ 4]), 13);
46*4882a593Smuzhiyun x[ 0] ^= rol32((x[12] + x[ 8]), 18);
47*4882a593Smuzhiyun x[ 9] ^= rol32((x[ 5] + x[ 1]), 7);
48*4882a593Smuzhiyun x[13] ^= rol32((x[ 9] + x[ 5]), 9);
49*4882a593Smuzhiyun x[ 1] ^= rol32((x[13] + x[ 9]), 13);
50*4882a593Smuzhiyun x[ 5] ^= rol32((x[ 1] + x[13]), 18);
51*4882a593Smuzhiyun x[14] ^= rol32((x[10] + x[ 6]), 7);
52*4882a593Smuzhiyun x[ 2] ^= rol32((x[14] + x[10]), 9);
53*4882a593Smuzhiyun x[ 6] ^= rol32((x[ 2] + x[14]), 13);
54*4882a593Smuzhiyun x[10] ^= rol32((x[ 6] + x[ 2]), 18);
55*4882a593Smuzhiyun x[ 3] ^= rol32((x[15] + x[11]), 7);
56*4882a593Smuzhiyun x[ 7] ^= rol32((x[ 3] + x[15]), 9);
57*4882a593Smuzhiyun x[11] ^= rol32((x[ 7] + x[ 3]), 13);
58*4882a593Smuzhiyun x[15] ^= rol32((x[11] + x[ 7]), 18);
59*4882a593Smuzhiyun x[ 1] ^= rol32((x[ 0] + x[ 3]), 7);
60*4882a593Smuzhiyun x[ 2] ^= rol32((x[ 1] + x[ 0]), 9);
61*4882a593Smuzhiyun x[ 3] ^= rol32((x[ 2] + x[ 1]), 13);
62*4882a593Smuzhiyun x[ 0] ^= rol32((x[ 3] + x[ 2]), 18);
63*4882a593Smuzhiyun x[ 6] ^= rol32((x[ 5] + x[ 4]), 7);
64*4882a593Smuzhiyun x[ 7] ^= rol32((x[ 6] + x[ 5]), 9);
65*4882a593Smuzhiyun x[ 4] ^= rol32((x[ 7] + x[ 6]), 13);
66*4882a593Smuzhiyun x[ 5] ^= rol32((x[ 4] + x[ 7]), 18);
67*4882a593Smuzhiyun x[11] ^= rol32((x[10] + x[ 9]), 7);
68*4882a593Smuzhiyun x[ 8] ^= rol32((x[11] + x[10]), 9);
69*4882a593Smuzhiyun x[ 9] ^= rol32((x[ 8] + x[11]), 13);
70*4882a593Smuzhiyun x[10] ^= rol32((x[ 9] + x[ 8]), 18);
71*4882a593Smuzhiyun x[12] ^= rol32((x[15] + x[14]), 7);
72*4882a593Smuzhiyun x[13] ^= rol32((x[12] + x[15]), 9);
73*4882a593Smuzhiyun x[14] ^= rol32((x[13] + x[12]), 13);
74*4882a593Smuzhiyun x[15] ^= rol32((x[14] + x[13]), 18);
75*4882a593Smuzhiyun }
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun for (i = 0; i < 16; i++)
78*4882a593Smuzhiyun stream[i] = cpu_to_le32(x[i] + state[i]);
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun if (++state[8] == 0)
81*4882a593Smuzhiyun state[9]++;
82*4882a593Smuzhiyun }
83*4882a593Smuzhiyun
salsa20_docrypt(u32 * state,u8 * dst,const u8 * src,unsigned int bytes)84*4882a593Smuzhiyun static void salsa20_docrypt(u32 *state, u8 *dst, const u8 *src,
85*4882a593Smuzhiyun unsigned int bytes)
86*4882a593Smuzhiyun {
87*4882a593Smuzhiyun __le32 stream[SALSA20_BLOCK_SIZE / sizeof(__le32)];
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun while (bytes >= SALSA20_BLOCK_SIZE) {
90*4882a593Smuzhiyun salsa20_block(state, stream);
91*4882a593Smuzhiyun crypto_xor_cpy(dst, src, (const u8 *)stream,
92*4882a593Smuzhiyun SALSA20_BLOCK_SIZE);
93*4882a593Smuzhiyun bytes -= SALSA20_BLOCK_SIZE;
94*4882a593Smuzhiyun dst += SALSA20_BLOCK_SIZE;
95*4882a593Smuzhiyun src += SALSA20_BLOCK_SIZE;
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun if (bytes) {
98*4882a593Smuzhiyun salsa20_block(state, stream);
99*4882a593Smuzhiyun crypto_xor_cpy(dst, src, (const u8 *)stream, bytes);
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun }
102*4882a593Smuzhiyun
salsa20_init(u32 * state,const struct salsa20_ctx * ctx,const u8 * iv)103*4882a593Smuzhiyun static void salsa20_init(u32 *state, const struct salsa20_ctx *ctx,
104*4882a593Smuzhiyun const u8 *iv)
105*4882a593Smuzhiyun {
106*4882a593Smuzhiyun memcpy(state, ctx->initial_state, sizeof(ctx->initial_state));
107*4882a593Smuzhiyun state[6] = get_unaligned_le32(iv + 0);
108*4882a593Smuzhiyun state[7] = get_unaligned_le32(iv + 4);
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun
salsa20_setkey(struct crypto_skcipher * tfm,const u8 * key,unsigned int keysize)111*4882a593Smuzhiyun static int salsa20_setkey(struct crypto_skcipher *tfm, const u8 *key,
112*4882a593Smuzhiyun unsigned int keysize)
113*4882a593Smuzhiyun {
114*4882a593Smuzhiyun static const char sigma[16] = "expand 32-byte k";
115*4882a593Smuzhiyun static const char tau[16] = "expand 16-byte k";
116*4882a593Smuzhiyun struct salsa20_ctx *ctx = crypto_skcipher_ctx(tfm);
117*4882a593Smuzhiyun const char *constants;
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun if (keysize != SALSA20_MIN_KEY_SIZE &&
120*4882a593Smuzhiyun keysize != SALSA20_MAX_KEY_SIZE)
121*4882a593Smuzhiyun return -EINVAL;
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun ctx->initial_state[1] = get_unaligned_le32(key + 0);
124*4882a593Smuzhiyun ctx->initial_state[2] = get_unaligned_le32(key + 4);
125*4882a593Smuzhiyun ctx->initial_state[3] = get_unaligned_le32(key + 8);
126*4882a593Smuzhiyun ctx->initial_state[4] = get_unaligned_le32(key + 12);
127*4882a593Smuzhiyun if (keysize == 32) { /* recommended */
128*4882a593Smuzhiyun key += 16;
129*4882a593Smuzhiyun constants = sigma;
130*4882a593Smuzhiyun } else { /* keysize == 16 */
131*4882a593Smuzhiyun constants = tau;
132*4882a593Smuzhiyun }
133*4882a593Smuzhiyun ctx->initial_state[11] = get_unaligned_le32(key + 0);
134*4882a593Smuzhiyun ctx->initial_state[12] = get_unaligned_le32(key + 4);
135*4882a593Smuzhiyun ctx->initial_state[13] = get_unaligned_le32(key + 8);
136*4882a593Smuzhiyun ctx->initial_state[14] = get_unaligned_le32(key + 12);
137*4882a593Smuzhiyun ctx->initial_state[0] = get_unaligned_le32(constants + 0);
138*4882a593Smuzhiyun ctx->initial_state[5] = get_unaligned_le32(constants + 4);
139*4882a593Smuzhiyun ctx->initial_state[10] = get_unaligned_le32(constants + 8);
140*4882a593Smuzhiyun ctx->initial_state[15] = get_unaligned_le32(constants + 12);
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun /* space for the nonce; it will be overridden for each request */
143*4882a593Smuzhiyun ctx->initial_state[6] = 0;
144*4882a593Smuzhiyun ctx->initial_state[7] = 0;
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun /* initial block number */
147*4882a593Smuzhiyun ctx->initial_state[8] = 0;
148*4882a593Smuzhiyun ctx->initial_state[9] = 0;
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun return 0;
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun
salsa20_crypt(struct skcipher_request * req)153*4882a593Smuzhiyun static int salsa20_crypt(struct skcipher_request *req)
154*4882a593Smuzhiyun {
155*4882a593Smuzhiyun struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
156*4882a593Smuzhiyun const struct salsa20_ctx *ctx = crypto_skcipher_ctx(tfm);
157*4882a593Smuzhiyun struct skcipher_walk walk;
158*4882a593Smuzhiyun u32 state[16];
159*4882a593Smuzhiyun int err;
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun err = skcipher_walk_virt(&walk, req, false);
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun salsa20_init(state, ctx, req->iv);
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun while (walk.nbytes > 0) {
166*4882a593Smuzhiyun unsigned int nbytes = walk.nbytes;
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun if (nbytes < walk.total)
169*4882a593Smuzhiyun nbytes = round_down(nbytes, walk.stride);
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun salsa20_docrypt(state, walk.dst.virt.addr, walk.src.virt.addr,
172*4882a593Smuzhiyun nbytes);
173*4882a593Smuzhiyun err = skcipher_walk_done(&walk, walk.nbytes - nbytes);
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun return err;
177*4882a593Smuzhiyun }
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun static struct skcipher_alg alg = {
180*4882a593Smuzhiyun .base.cra_name = "salsa20",
181*4882a593Smuzhiyun .base.cra_driver_name = "salsa20-generic",
182*4882a593Smuzhiyun .base.cra_priority = 100,
183*4882a593Smuzhiyun .base.cra_blocksize = 1,
184*4882a593Smuzhiyun .base.cra_ctxsize = sizeof(struct salsa20_ctx),
185*4882a593Smuzhiyun .base.cra_module = THIS_MODULE,
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun .min_keysize = SALSA20_MIN_KEY_SIZE,
188*4882a593Smuzhiyun .max_keysize = SALSA20_MAX_KEY_SIZE,
189*4882a593Smuzhiyun .ivsize = SALSA20_IV_SIZE,
190*4882a593Smuzhiyun .chunksize = SALSA20_BLOCK_SIZE,
191*4882a593Smuzhiyun .setkey = salsa20_setkey,
192*4882a593Smuzhiyun .encrypt = salsa20_crypt,
193*4882a593Smuzhiyun .decrypt = salsa20_crypt,
194*4882a593Smuzhiyun };
195*4882a593Smuzhiyun
salsa20_generic_mod_init(void)196*4882a593Smuzhiyun static int __init salsa20_generic_mod_init(void)
197*4882a593Smuzhiyun {
198*4882a593Smuzhiyun return crypto_register_skcipher(&alg);
199*4882a593Smuzhiyun }
200*4882a593Smuzhiyun
salsa20_generic_mod_fini(void)201*4882a593Smuzhiyun static void __exit salsa20_generic_mod_fini(void)
202*4882a593Smuzhiyun {
203*4882a593Smuzhiyun crypto_unregister_skcipher(&alg);
204*4882a593Smuzhiyun }
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun subsys_initcall(salsa20_generic_mod_init);
207*4882a593Smuzhiyun module_exit(salsa20_generic_mod_fini);
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun MODULE_LICENSE("GPL");
210*4882a593Smuzhiyun MODULE_DESCRIPTION ("Salsa20 stream cipher algorithm");
211*4882a593Smuzhiyun MODULE_ALIAS_CRYPTO("salsa20");
212*4882a593Smuzhiyun MODULE_ALIAS_CRYPTO("salsa20-generic");
213