2 * ChaCha20 256-bit cipher algorithm, RFC7539
4 * Copyright (C) 2015 Martin Willi
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
12 #include <crypto/algapi.h>
13 #include <linux/crypto.h>
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <crypto/chacha20.h>
18 static inline u32
rotl32(u32 v
, u8 n
)
20 return (v
<< n
) | (v
>> (sizeof(v
) * 8 - n
));
23 static inline u32
le32_to_cpuvp(const void *p
)
25 return le32_to_cpup(p
);
28 static void chacha20_block(u32
*state
, void *stream
)
30 u32 x
[16], *out
= stream
;
33 for (i
= 0; i
< ARRAY_SIZE(x
); i
++)
36 for (i
= 0; i
< 20; i
+= 2) {
37 x
[0] += x
[4]; x
[12] = rotl32(x
[12] ^ x
[0], 16);
38 x
[1] += x
[5]; x
[13] = rotl32(x
[13] ^ x
[1], 16);
39 x
[2] += x
[6]; x
[14] = rotl32(x
[14] ^ x
[2], 16);
40 x
[3] += x
[7]; x
[15] = rotl32(x
[15] ^ x
[3], 16);
42 x
[8] += x
[12]; x
[4] = rotl32(x
[4] ^ x
[8], 12);
43 x
[9] += x
[13]; x
[5] = rotl32(x
[5] ^ x
[9], 12);
44 x
[10] += x
[14]; x
[6] = rotl32(x
[6] ^ x
[10], 12);
45 x
[11] += x
[15]; x
[7] = rotl32(x
[7] ^ x
[11], 12);
47 x
[0] += x
[4]; x
[12] = rotl32(x
[12] ^ x
[0], 8);
48 x
[1] += x
[5]; x
[13] = rotl32(x
[13] ^ x
[1], 8);
49 x
[2] += x
[6]; x
[14] = rotl32(x
[14] ^ x
[2], 8);
50 x
[3] += x
[7]; x
[15] = rotl32(x
[15] ^ x
[3], 8);
52 x
[8] += x
[12]; x
[4] = rotl32(x
[4] ^ x
[8], 7);
53 x
[9] += x
[13]; x
[5] = rotl32(x
[5] ^ x
[9], 7);
54 x
[10] += x
[14]; x
[6] = rotl32(x
[6] ^ x
[10], 7);
55 x
[11] += x
[15]; x
[7] = rotl32(x
[7] ^ x
[11], 7);
57 x
[0] += x
[5]; x
[15] = rotl32(x
[15] ^ x
[0], 16);
58 x
[1] += x
[6]; x
[12] = rotl32(x
[12] ^ x
[1], 16);
59 x
[2] += x
[7]; x
[13] = rotl32(x
[13] ^ x
[2], 16);
60 x
[3] += x
[4]; x
[14] = rotl32(x
[14] ^ x
[3], 16);
62 x
[10] += x
[15]; x
[5] = rotl32(x
[5] ^ x
[10], 12);
63 x
[11] += x
[12]; x
[6] = rotl32(x
[6] ^ x
[11], 12);
64 x
[8] += x
[13]; x
[7] = rotl32(x
[7] ^ x
[8], 12);
65 x
[9] += x
[14]; x
[4] = rotl32(x
[4] ^ x
[9], 12);
67 x
[0] += x
[5]; x
[15] = rotl32(x
[15] ^ x
[0], 8);
68 x
[1] += x
[6]; x
[12] = rotl32(x
[12] ^ x
[1], 8);
69 x
[2] += x
[7]; x
[13] = rotl32(x
[13] ^ x
[2], 8);
70 x
[3] += x
[4]; x
[14] = rotl32(x
[14] ^ x
[3], 8);
72 x
[10] += x
[15]; x
[5] = rotl32(x
[5] ^ x
[10], 7);
73 x
[11] += x
[12]; x
[6] = rotl32(x
[6] ^ x
[11], 7);
74 x
[8] += x
[13]; x
[7] = rotl32(x
[7] ^ x
[8], 7);
75 x
[9] += x
[14]; x
[4] = rotl32(x
[4] ^ x
[9], 7);
78 for (i
= 0; i
< ARRAY_SIZE(x
); i
++)
79 out
[i
] = cpu_to_le32(x
[i
] + state
[i
]);
84 static void chacha20_docrypt(u32
*state
, u8
*dst
, const u8
*src
,
87 u8 stream
[CHACHA20_BLOCK_SIZE
];
90 memcpy(dst
, src
, bytes
);
92 while (bytes
>= CHACHA20_BLOCK_SIZE
) {
93 chacha20_block(state
, stream
);
94 crypto_xor(dst
, stream
, CHACHA20_BLOCK_SIZE
);
95 bytes
-= CHACHA20_BLOCK_SIZE
;
96 dst
+= CHACHA20_BLOCK_SIZE
;
99 chacha20_block(state
, stream
);
100 crypto_xor(dst
, stream
, bytes
);
104 void crypto_chacha20_init(u32
*state
, struct chacha20_ctx
*ctx
, u8
*iv
)
106 static const char constant
[16] = "expand 32-byte k";
108 state
[0] = le32_to_cpuvp(constant
+ 0);
109 state
[1] = le32_to_cpuvp(constant
+ 4);
110 state
[2] = le32_to_cpuvp(constant
+ 8);
111 state
[3] = le32_to_cpuvp(constant
+ 12);
112 state
[4] = ctx
->key
[0];
113 state
[5] = ctx
->key
[1];
114 state
[6] = ctx
->key
[2];
115 state
[7] = ctx
->key
[3];
116 state
[8] = ctx
->key
[4];
117 state
[9] = ctx
->key
[5];
118 state
[10] = ctx
->key
[6];
119 state
[11] = ctx
->key
[7];
120 state
[12] = le32_to_cpuvp(iv
+ 0);
121 state
[13] = le32_to_cpuvp(iv
+ 4);
122 state
[14] = le32_to_cpuvp(iv
+ 8);
123 state
[15] = le32_to_cpuvp(iv
+ 12);
125 EXPORT_SYMBOL_GPL(crypto_chacha20_init
);
127 int crypto_chacha20_setkey(struct crypto_tfm
*tfm
, const u8
*key
,
128 unsigned int keysize
)
130 struct chacha20_ctx
*ctx
= crypto_tfm_ctx(tfm
);
133 if (keysize
!= CHACHA20_KEY_SIZE
)
136 for (i
= 0; i
< ARRAY_SIZE(ctx
->key
); i
++)
137 ctx
->key
[i
] = le32_to_cpuvp(key
+ i
* sizeof(u32
));
141 EXPORT_SYMBOL_GPL(crypto_chacha20_setkey
);
143 int crypto_chacha20_crypt(struct blkcipher_desc
*desc
, struct scatterlist
*dst
,
144 struct scatterlist
*src
, unsigned int nbytes
)
146 struct blkcipher_walk walk
;
150 blkcipher_walk_init(&walk
, dst
, src
, nbytes
);
151 err
= blkcipher_walk_virt_block(desc
, &walk
, CHACHA20_BLOCK_SIZE
);
153 crypto_chacha20_init(state
, crypto_blkcipher_ctx(desc
->tfm
), walk
.iv
);
155 while (walk
.nbytes
>= CHACHA20_BLOCK_SIZE
) {
156 chacha20_docrypt(state
, walk
.dst
.virt
.addr
, walk
.src
.virt
.addr
,
157 rounddown(walk
.nbytes
, CHACHA20_BLOCK_SIZE
));
158 err
= blkcipher_walk_done(desc
, &walk
,
159 walk
.nbytes
% CHACHA20_BLOCK_SIZE
);
163 chacha20_docrypt(state
, walk
.dst
.virt
.addr
, walk
.src
.virt
.addr
,
165 err
= blkcipher_walk_done(desc
, &walk
, 0);
170 EXPORT_SYMBOL_GPL(crypto_chacha20_crypt
);
172 static struct crypto_alg alg
= {
173 .cra_name
= "chacha20",
174 .cra_driver_name
= "chacha20-generic",
176 .cra_flags
= CRYPTO_ALG_TYPE_BLKCIPHER
,
178 .cra_type
= &crypto_blkcipher_type
,
179 .cra_ctxsize
= sizeof(struct chacha20_ctx
),
180 .cra_alignmask
= sizeof(u32
) - 1,
181 .cra_module
= THIS_MODULE
,
184 .min_keysize
= CHACHA20_KEY_SIZE
,
185 .max_keysize
= CHACHA20_KEY_SIZE
,
186 .ivsize
= CHACHA20_IV_SIZE
,
188 .setkey
= crypto_chacha20_setkey
,
189 .encrypt
= crypto_chacha20_crypt
,
190 .decrypt
= crypto_chacha20_crypt
,
195 static int __init
chacha20_generic_mod_init(void)
197 return crypto_register_alg(&alg
);
200 static void __exit
chacha20_generic_mod_fini(void)
202 crypto_unregister_alg(&alg
);
205 module_init(chacha20_generic_mod_init
);
206 module_exit(chacha20_generic_mod_fini
);
208 MODULE_LICENSE("GPL");
209 MODULE_AUTHOR("Martin Willi <martin@strongswan.org>");
210 MODULE_DESCRIPTION("chacha20 cipher algorithm");
211 MODULE_ALIAS_CRYPTO("chacha20");
212 MODULE_ALIAS_CRYPTO("chacha20-generic");