30
30
31
31
asmlinkage void chacha20_block_xor_neon (u32 * state , u8 * dst , const u8 * src );
32
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 );
33
34
34
35
static void chacha20_doneon (u32 * state , u8 * dst , const u8 * src ,
35
36
unsigned int bytes )
@@ -65,20 +66,16 @@ static void chacha20_doneon(u32 *state, u8 *dst, const u8 *src,
65
66
kernel_neon_end ();
66
67
}
67
68
68
- static int chacha20_neon (struct skcipher_request * req )
69
+ static int chacha20_neon_stream_xor (struct skcipher_request * req ,
70
+ struct chacha_ctx * ctx , u8 * iv )
69
71
{
70
- struct crypto_skcipher * tfm = crypto_skcipher_reqtfm (req );
71
- struct chacha_ctx * ctx = crypto_skcipher_ctx (tfm );
72
72
struct skcipher_walk walk ;
73
73
u32 state [16 ];
74
74
int err ;
75
75
76
- if (!may_use_simd () || req -> cryptlen <= CHACHA_BLOCK_SIZE )
77
- return crypto_chacha_crypt (req );
78
-
79
76
err = skcipher_walk_virt (& walk , req , false);
80
77
81
- crypto_chacha_init (state , ctx , walk . iv );
78
+ crypto_chacha_init (state , ctx , iv );
82
79
83
80
while (walk .nbytes > 0 ) {
84
81
unsigned int nbytes = walk .nbytes ;
@@ -94,35 +91,86 @@ static int chacha20_neon(struct skcipher_request *req)
94
91
return err ;
95
92
}
96
93
97
- static struct skcipher_alg alg = {
98
- .base .cra_name = "chacha20" ,
99
- .base .cra_driver_name = "chacha20-neon" ,
100
- .base .cra_priority = 300 ,
101
- .base .cra_blocksize = 1 ,
102
- .base .cra_ctxsize = sizeof (struct chacha_ctx ),
103
- .base .cra_module = THIS_MODULE ,
104
-
105
- .min_keysize = CHACHA_KEY_SIZE ,
106
- .max_keysize = CHACHA_KEY_SIZE ,
107
- .ivsize = CHACHA_IV_SIZE ,
108
- .chunksize = CHACHA_BLOCK_SIZE ,
109
- .walksize = 4 * CHACHA_BLOCK_SIZE ,
110
- .setkey = crypto_chacha20_setkey ,
111
- .encrypt = chacha20_neon ,
112
- .decrypt = chacha20_neon ,
94
+ static int chacha20_neon (struct skcipher_request * req )
95
+ {
96
+ struct crypto_skcipher * tfm = crypto_skcipher_reqtfm (req );
97
+ struct chacha_ctx * ctx = crypto_skcipher_ctx (tfm );
98
+
99
+ if (req -> cryptlen <= CHACHA_BLOCK_SIZE || !may_use_simd ())
100
+ return crypto_chacha_crypt (req );
101
+
102
+ return chacha20_neon_stream_xor (req , ctx , req -> iv );
103
+ }
104
+
105
+ static int xchacha20_neon (struct skcipher_request * req )
106
+ {
107
+ struct crypto_skcipher * tfm = crypto_skcipher_reqtfm (req );
108
+ struct chacha_ctx * ctx = crypto_skcipher_ctx (tfm );
109
+ struct chacha_ctx subctx ;
110
+ u32 state [16 ];
111
+ u8 real_iv [16 ];
112
+
113
+ if (req -> cryptlen <= CHACHA_BLOCK_SIZE || !may_use_simd ())
114
+ return crypto_xchacha_crypt (req );
115
+
116
+ crypto_chacha_init (state , ctx , req -> iv );
117
+
118
+ kernel_neon_begin ();
119
+ hchacha20_block_neon (state , subctx .key );
120
+ kernel_neon_end ();
121
+
122
+ memcpy (& real_iv [0 ], req -> iv + 24 , 8 );
123
+ memcpy (& real_iv [8 ], req -> iv + 16 , 8 );
124
+ return chacha20_neon_stream_xor (req , & subctx , real_iv );
125
+ }
126
+
127
+ static struct skcipher_alg algs [] = {
128
+ {
129
+ .base .cra_name = "chacha20" ,
130
+ .base .cra_driver_name = "chacha20-neon" ,
131
+ .base .cra_priority = 300 ,
132
+ .base .cra_blocksize = 1 ,
133
+ .base .cra_ctxsize = sizeof (struct chacha_ctx ),
134
+ .base .cra_module = THIS_MODULE ,
135
+
136
+ .min_keysize = CHACHA_KEY_SIZE ,
137
+ .max_keysize = CHACHA_KEY_SIZE ,
138
+ .ivsize = CHACHA_IV_SIZE ,
139
+ .chunksize = CHACHA_BLOCK_SIZE ,
140
+ .walksize = 4 * CHACHA_BLOCK_SIZE ,
141
+ .setkey = crypto_chacha20_setkey ,
142
+ .encrypt = chacha20_neon ,
143
+ .decrypt = chacha20_neon ,
144
+ }, {
145
+ .base .cra_name = "xchacha20" ,
146
+ .base .cra_driver_name = "xchacha20-neon" ,
147
+ .base .cra_priority = 300 ,
148
+ .base .cra_blocksize = 1 ,
149
+ .base .cra_ctxsize = sizeof (struct chacha_ctx ),
150
+ .base .cra_module = THIS_MODULE ,
151
+
152
+ .min_keysize = CHACHA_KEY_SIZE ,
153
+ .max_keysize = CHACHA_KEY_SIZE ,
154
+ .ivsize = XCHACHA_IV_SIZE ,
155
+ .chunksize = CHACHA_BLOCK_SIZE ,
156
+ .walksize = 4 * CHACHA_BLOCK_SIZE ,
157
+ .setkey = crypto_chacha20_setkey ,
158
+ .encrypt = xchacha20_neon ,
159
+ .decrypt = xchacha20_neon ,
160
+ }
113
161
};
114
162
115
163
static int __init chacha20_simd_mod_init (void )
116
164
{
117
165
if (!(elf_hwcap & HWCAP_ASIMD ))
118
166
return - ENODEV ;
119
167
120
- return crypto_register_skcipher ( & alg );
168
+ return crypto_register_skciphers ( algs , ARRAY_SIZE ( algs ) );
121
169
}
122
170
123
171
static void __exit chacha20_simd_mod_fini (void )
124
172
{
125
- crypto_unregister_skcipher ( & alg );
173
+ crypto_unregister_skciphers ( algs , ARRAY_SIZE ( algs ) );
126
174
}
127
175
128
176
module_init (chacha20_simd_mod_init );
@@ -131,3 +179,6 @@ module_exit(chacha20_simd_mod_fini);
131
179
MODULE_AUTHOR (
"Ard Biesheuvel <[email protected] >" );
132
180
MODULE_LICENSE ("GPL v2" );
133
181
MODULE_ALIAS_CRYPTO ("chacha20" );
182
+ MODULE_ALIAS_CRYPTO ("chacha20-neon" );
183
+ MODULE_ALIAS_CRYPTO ("xchacha20" );
184
+ MODULE_ALIAS_CRYPTO ("xchacha20-neon" );
0 commit comments