1
1
/*
2
- * ChaCha20 256-bit cipher algorithm, RFC7539, arm64 NEON functions
2
+ * ARM NEON accelerated ChaCha and XChaCha stream ciphers,
3
+ * including ChaCha20 (RFC7539)
3
4
*
4
5
* Copyright (C) 2016 - 2017 Linaro, Ltd. <ard.biesheuvel@linaro.org>
5
6
*
28
29
#include <asm/neon.h>
29
30
#include <asm/simd.h>
30
31
31
- asmlinkage void chacha20_block_xor_neon (u32 * state , u8 * dst , const u8 * src );
32
- asmlinkage void chacha20_4block_xor_neon (u32 * state , u8 * dst , const u8 * src );
33
- asmlinkage void hchacha20_block_neon (const u32 * state , u32 * out );
32
+ asmlinkage void chacha_block_xor_neon (u32 * state , u8 * dst , const u8 * src ,
33
+ int nrounds );
34
+ asmlinkage void chacha_4block_xor_neon (u32 * state , u8 * dst , const u8 * src ,
35
+ int nrounds );
36
+ asmlinkage void hchacha_block_neon (const u32 * state , u32 * out , int nrounds );
34
37
35
- static void chacha20_doneon (u32 * state , u8 * dst , const u8 * src ,
36
- unsigned int bytes )
38
+ static void chacha_doneon (u32 * state , u8 * dst , const u8 * src ,
39
+ unsigned int bytes , int nrounds )
37
40
{
38
41
u8 buf [CHACHA_BLOCK_SIZE ];
39
42
40
43
while (bytes >= CHACHA_BLOCK_SIZE * 4 ) {
41
44
kernel_neon_begin ();
42
- chacha20_4block_xor_neon (state , dst , src );
45
+ chacha_4block_xor_neon (state , dst , src , nrounds );
43
46
kernel_neon_end ();
44
47
bytes -= CHACHA_BLOCK_SIZE * 4 ;
45
48
src += CHACHA_BLOCK_SIZE * 4 ;
@@ -52,22 +55,22 @@ static void chacha20_doneon(u32 *state, u8 *dst, const u8 *src,
52
55
53
56
kernel_neon_begin ();
54
57
while (bytes >= CHACHA_BLOCK_SIZE ) {
55
- chacha20_block_xor_neon (state , dst , src );
58
+ chacha_block_xor_neon (state , dst , src , nrounds );
56
59
bytes -= CHACHA_BLOCK_SIZE ;
57
60
src += CHACHA_BLOCK_SIZE ;
58
61
dst += CHACHA_BLOCK_SIZE ;
59
62
state [12 ]++ ;
60
63
}
61
64
if (bytes ) {
62
65
memcpy (buf , src , bytes );
63
- chacha20_block_xor_neon (state , buf , buf );
66
+ chacha_block_xor_neon (state , buf , buf , nrounds );
64
67
memcpy (dst , buf , bytes );
65
68
}
66
69
kernel_neon_end ();
67
70
}
68
71
69
- static int chacha20_neon_stream_xor (struct skcipher_request * req ,
70
- struct chacha_ctx * ctx , u8 * iv )
72
+ static int chacha_neon_stream_xor (struct skcipher_request * req ,
73
+ struct chacha_ctx * ctx , u8 * iv )
71
74
{
72
75
struct skcipher_walk walk ;
73
76
u32 state [16 ];
@@ -83,26 +86,26 @@ static int chacha20_neon_stream_xor(struct skcipher_request *req,
83
86
if (nbytes < walk .total )
84
87
nbytes = round_down (nbytes , walk .stride );
85
88
86
- chacha20_doneon (state , walk .dst .virt .addr , walk .src .virt .addr ,
87
- nbytes );
89
+ chacha_doneon (state , walk .dst .virt .addr , walk .src .virt .addr ,
90
+ nbytes , ctx -> nrounds );
88
91
err = skcipher_walk_done (& walk , walk .nbytes - nbytes );
89
92
}
90
93
91
94
return err ;
92
95
}
93
96
94
- static int chacha20_neon (struct skcipher_request * req )
97
+ static int chacha_neon (struct skcipher_request * req )
95
98
{
96
99
struct crypto_skcipher * tfm = crypto_skcipher_reqtfm (req );
97
100
struct chacha_ctx * ctx = crypto_skcipher_ctx (tfm );
98
101
99
102
if (req -> cryptlen <= CHACHA_BLOCK_SIZE || !may_use_simd ())
100
103
return crypto_chacha_crypt (req );
101
104
102
- return chacha20_neon_stream_xor (req , ctx , req -> iv );
105
+ return chacha_neon_stream_xor (req , ctx , req -> iv );
103
106
}
104
107
105
- static int xchacha20_neon (struct skcipher_request * req )
108
+ static int xchacha_neon (struct skcipher_request * req )
106
109
{
107
110
struct crypto_skcipher * tfm = crypto_skcipher_reqtfm (req );
108
111
struct chacha_ctx * ctx = crypto_skcipher_ctx (tfm );
@@ -116,12 +119,13 @@ static int xchacha20_neon(struct skcipher_request *req)
116
119
crypto_chacha_init (state , ctx , req -> iv );
117
120
118
121
kernel_neon_begin ();
119
- hchacha20_block_neon (state , subctx .key );
122
+ hchacha_block_neon (state , subctx .key , ctx -> nrounds );
120
123
kernel_neon_end ();
124
+ subctx .nrounds = ctx -> nrounds ;
121
125
122
126
memcpy (& real_iv [0 ], req -> iv + 24 , 8 );
123
127
memcpy (& real_iv [8 ], req -> iv + 16 , 8 );
124
- return chacha20_neon_stream_xor (req , & subctx , real_iv );
128
+ return chacha_neon_stream_xor (req , & subctx , real_iv );
125
129
}
126
130
127
131
static struct skcipher_alg algs [] = {
@@ -139,8 +143,8 @@ static struct skcipher_alg algs[] = {
139
143
.chunksize = CHACHA_BLOCK_SIZE ,
140
144
.walksize = 4 * CHACHA_BLOCK_SIZE ,
141
145
.setkey = crypto_chacha20_setkey ,
142
- .encrypt = chacha20_neon ,
143
- .decrypt = chacha20_neon ,
146
+ .encrypt = chacha_neon ,
147
+ .decrypt = chacha_neon ,
144
148
}, {
145
149
.base .cra_name = "xchacha20" ,
146
150
.base .cra_driver_name = "xchacha20-neon" ,
@@ -155,27 +159,28 @@ static struct skcipher_alg algs[] = {
155
159
.chunksize = CHACHA_BLOCK_SIZE ,
156
160
.walksize = 4 * CHACHA_BLOCK_SIZE ,
157
161
.setkey = crypto_chacha20_setkey ,
158
- .encrypt = xchacha20_neon ,
159
- .decrypt = xchacha20_neon ,
162
+ .encrypt = xchacha_neon ,
163
+ .decrypt = xchacha_neon ,
160
164
}
161
165
};
162
166
163
- static int __init chacha20_simd_mod_init (void )
167
+ static int __init chacha_simd_mod_init (void )
164
168
{
165
169
if (!(elf_hwcap & HWCAP_ASIMD ))
166
170
return - ENODEV ;
167
171
168
172
return crypto_register_skciphers (algs , ARRAY_SIZE (algs ));
169
173
}
170
174
171
- static void __exit chacha20_simd_mod_fini (void )
175
+ static void __exit chacha_simd_mod_fini (void )
172
176
{
173
177
crypto_unregister_skciphers (algs , ARRAY_SIZE (algs ));
174
178
}
175
179
176
- module_init (chacha20_simd_mod_init );
177
- module_exit (chacha20_simd_mod_fini );
180
+ module_init (chacha_simd_mod_init );
181
+ module_exit (chacha_simd_mod_fini );
178
182
183
+ MODULE_DESCRIPTION ("ChaCha and XChaCha stream ciphers (NEON accelerated)" );
179
184
MODULE_AUTHOR ("Ard Biesheuvel <ard.biesheuvel@linaro.org>" );
180
185
MODULE_LICENSE ("GPL v2" );
181
186
MODULE_ALIAS_CRYPTO ("chacha20" );
0 commit comments