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>
17 #define CHACHA20_NONCE_SIZE 16
18 #define CHACHA20_KEY_SIZE 32
19 #define CHACHA20_BLOCK_SIZE 64
25 static inline u32
rotl32(u32 v
, u8 n
)
27 return (v
<< n
) | (v
>> (sizeof(v
) * 8 - n
));
30 static inline u32
le32_to_cpuvp(const void *p
)
32 return le32_to_cpup(p
);
35 static void chacha20_block(u32
*state
, void *stream
)
37 u32 x
[16], *out
= stream
;
40 for (i
= 0; i
< ARRAY_SIZE(x
); i
++)
43 for (i
= 0; i
< 20; i
+= 2) {
44 x
[0] += x
[4]; x
[12] = rotl32(x
[12] ^ x
[0], 16);
45 x
[1] += x
[5]; x
[13] = rotl32(x
[13] ^ x
[1], 16);
46 x
[2] += x
[6]; x
[14] = rotl32(x
[14] ^ x
[2], 16);
47 x
[3] += x
[7]; x
[15] = rotl32(x
[15] ^ x
[3], 16);
49 x
[8] += x
[12]; x
[4] = rotl32(x
[4] ^ x
[8], 12);
50 x
[9] += x
[13]; x
[5] = rotl32(x
[5] ^ x
[9], 12);
51 x
[10] += x
[14]; x
[6] = rotl32(x
[6] ^ x
[10], 12);
52 x
[11] += x
[15]; x
[7] = rotl32(x
[7] ^ x
[11], 12);
54 x
[0] += x
[4]; x
[12] = rotl32(x
[12] ^ x
[0], 8);
55 x
[1] += x
[5]; x
[13] = rotl32(x
[13] ^ x
[1], 8);
56 x
[2] += x
[6]; x
[14] = rotl32(x
[14] ^ x
[2], 8);
57 x
[3] += x
[7]; x
[15] = rotl32(x
[15] ^ x
[3], 8);
59 x
[8] += x
[12]; x
[4] = rotl32(x
[4] ^ x
[8], 7);
60 x
[9] += x
[13]; x
[5] = rotl32(x
[5] ^ x
[9], 7);
61 x
[10] += x
[14]; x
[6] = rotl32(x
[6] ^ x
[10], 7);
62 x
[11] += x
[15]; x
[7] = rotl32(x
[7] ^ x
[11], 7);
64 x
[0] += x
[5]; x
[15] = rotl32(x
[15] ^ x
[0], 16);
65 x
[1] += x
[6]; x
[12] = rotl32(x
[12] ^ x
[1], 16);
66 x
[2] += x
[7]; x
[13] = rotl32(x
[13] ^ x
[2], 16);
67 x
[3] += x
[4]; x
[14] = rotl32(x
[14] ^ x
[3], 16);
69 x
[10] += x
[15]; x
[5] = rotl32(x
[5] ^ x
[10], 12);
70 x
[11] += x
[12]; x
[6] = rotl32(x
[6] ^ x
[11], 12);
71 x
[8] += x
[13]; x
[7] = rotl32(x
[7] ^ x
[8], 12);
72 x
[9] += x
[14]; x
[4] = rotl32(x
[4] ^ x
[9], 12);
74 x
[0] += x
[5]; x
[15] = rotl32(x
[15] ^ x
[0], 8);
75 x
[1] += x
[6]; x
[12] = rotl32(x
[12] ^ x
[1], 8);
76 x
[2] += x
[7]; x
[13] = rotl32(x
[13] ^ x
[2], 8);
77 x
[3] += x
[4]; x
[14] = rotl32(x
[14] ^ x
[3], 8);
79 x
[10] += x
[15]; x
[5] = rotl32(x
[5] ^ x
[10], 7);
80 x
[11] += x
[12]; x
[6] = rotl32(x
[6] ^ x
[11], 7);
81 x
[8] += x
[13]; x
[7] = rotl32(x
[7] ^ x
[8], 7);
82 x
[9] += x
[14]; x
[4] = rotl32(x
[4] ^ x
[9], 7);
85 for (i
= 0; i
< ARRAY_SIZE(x
); i
++)
86 out
[i
] = cpu_to_le32(x
[i
] + state
[i
]);
91 static void chacha20_docrypt(u32
*state
, u8
*dst
, const u8
*src
,
94 u8 stream
[CHACHA20_BLOCK_SIZE
];
97 memcpy(dst
, src
, bytes
);
99 while (bytes
>= CHACHA20_BLOCK_SIZE
) {
100 chacha20_block(state
, stream
);
101 crypto_xor(dst
, stream
, CHACHA20_BLOCK_SIZE
);
102 bytes
-= CHACHA20_BLOCK_SIZE
;
103 dst
+= CHACHA20_BLOCK_SIZE
;
106 chacha20_block(state
, stream
);
107 crypto_xor(dst
, stream
, bytes
);
111 static void chacha20_init(u32
*state
, struct chacha20_ctx
*ctx
, u8
*iv
)
113 static const char constant
[16] = "expand 32-byte k";
115 state
[0] = le32_to_cpuvp(constant
+ 0);
116 state
[1] = le32_to_cpuvp(constant
+ 4);
117 state
[2] = le32_to_cpuvp(constant
+ 8);
118 state
[3] = le32_to_cpuvp(constant
+ 12);
119 state
[4] = ctx
->key
[0];
120 state
[5] = ctx
->key
[1];
121 state
[6] = ctx
->key
[2];
122 state
[7] = ctx
->key
[3];
123 state
[8] = ctx
->key
[4];
124 state
[9] = ctx
->key
[5];
125 state
[10] = ctx
->key
[6];
126 state
[11] = ctx
->key
[7];
127 state
[12] = le32_to_cpuvp(iv
+ 0);
128 state
[13] = le32_to_cpuvp(iv
+ 4);
129 state
[14] = le32_to_cpuvp(iv
+ 8);
130 state
[15] = le32_to_cpuvp(iv
+ 12);
133 static int chacha20_setkey(struct crypto_tfm
*tfm
, const u8
*key
,
134 unsigned int keysize
)
136 struct chacha20_ctx
*ctx
= crypto_tfm_ctx(tfm
);
139 if (keysize
!= CHACHA20_KEY_SIZE
)
142 for (i
= 0; i
< ARRAY_SIZE(ctx
->key
); i
++)
143 ctx
->key
[i
] = le32_to_cpuvp(key
+ i
* sizeof(u32
));
148 static int chacha20_crypt(struct blkcipher_desc
*desc
, struct scatterlist
*dst
,
149 struct scatterlist
*src
, unsigned int nbytes
)
151 struct blkcipher_walk walk
;
155 blkcipher_walk_init(&walk
, dst
, src
, nbytes
);
156 err
= blkcipher_walk_virt_block(desc
, &walk
, CHACHA20_BLOCK_SIZE
);
158 chacha20_init(state
, crypto_blkcipher_ctx(desc
->tfm
), walk
.iv
);
160 while (walk
.nbytes
>= CHACHA20_BLOCK_SIZE
) {
161 chacha20_docrypt(state
, walk
.dst
.virt
.addr
, walk
.src
.virt
.addr
,
162 rounddown(walk
.nbytes
, CHACHA20_BLOCK_SIZE
));
163 err
= blkcipher_walk_done(desc
, &walk
,
164 walk
.nbytes
% CHACHA20_BLOCK_SIZE
);
168 chacha20_docrypt(state
, walk
.dst
.virt
.addr
, walk
.src
.virt
.addr
,
170 err
= blkcipher_walk_done(desc
, &walk
, 0);
176 static struct crypto_alg alg
= {
177 .cra_name
= "chacha20",
178 .cra_driver_name
= "chacha20-generic",
180 .cra_flags
= CRYPTO_ALG_TYPE_BLKCIPHER
,
182 .cra_type
= &crypto_blkcipher_type
,
183 .cra_ctxsize
= sizeof(struct chacha20_ctx
),
184 .cra_alignmask
= sizeof(u32
) - 1,
185 .cra_module
= THIS_MODULE
,
188 .min_keysize
= CHACHA20_KEY_SIZE
,
189 .max_keysize
= CHACHA20_KEY_SIZE
,
190 .ivsize
= CHACHA20_NONCE_SIZE
,
192 .setkey
= chacha20_setkey
,
193 .encrypt
= chacha20_crypt
,
194 .decrypt
= chacha20_crypt
,
199 static int __init
chacha20_generic_mod_init(void)
201 return crypto_register_alg(&alg
);
204 static void __exit
chacha20_generic_mod_fini(void)
206 crypto_unregister_alg(&alg
);
209 module_init(chacha20_generic_mod_init
);
210 module_exit(chacha20_generic_mod_fini
);
212 MODULE_LICENSE("GPL");
213 MODULE_AUTHOR("Martin Willi <martin@strongswan.org>");
214 MODULE_DESCRIPTION("chacha20 cipher algorithm");
215 MODULE_ALIAS_CRYPTO("chacha20");
216 MODULE_ALIAS_CRYPTO("chacha20-generic");