2 * Glue Code for x86_64/AVX2 assembler optimized version of Serpent
4 * Copyright © 2012-2013 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
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.
13 #include <linux/module.h>
14 #include <linux/types.h>
15 #include <linux/crypto.h>
16 #include <linux/err.h>
17 #include <crypto/algapi.h>
18 #include <crypto/internal/simd.h>
19 #include <crypto/serpent.h>
20 #include <crypto/xts.h>
21 #include <asm/crypto/glue_helper.h>
22 #include <asm/crypto/serpent-avx.h>
24 #define SERPENT_AVX2_PARALLEL_BLOCKS 16
26 /* 16-way AVX2 parallel cipher functions */
27 asmlinkage
void serpent_ecb_enc_16way(struct serpent_ctx
*ctx
, u8
*dst
,
29 asmlinkage
void serpent_ecb_dec_16way(struct serpent_ctx
*ctx
, u8
*dst
,
31 asmlinkage
void serpent_cbc_dec_16way(void *ctx
, u128
*dst
, const u128
*src
);
33 asmlinkage
void serpent_ctr_16way(void *ctx
, u128
*dst
, const u128
*src
,
35 asmlinkage
void serpent_xts_enc_16way(struct serpent_ctx
*ctx
, u8
*dst
,
36 const u8
*src
, le128
*iv
);
37 asmlinkage
void serpent_xts_dec_16way(struct serpent_ctx
*ctx
, u8
*dst
,
38 const u8
*src
, le128
*iv
);
40 static int serpent_setkey_skcipher(struct crypto_skcipher
*tfm
,
41 const u8
*key
, unsigned int keylen
)
43 return __serpent_setkey(crypto_skcipher_ctx(tfm
), key
, keylen
);
46 static const struct common_glue_ctx serpent_enc
= {
48 .fpu_blocks_limit
= 8,
52 .fn_u
= { .ecb
= GLUE_FUNC_CAST(serpent_ecb_enc_16way
) }
55 .fn_u
= { .ecb
= GLUE_FUNC_CAST(serpent_ecb_enc_8way_avx
) }
58 .fn_u
= { .ecb
= GLUE_FUNC_CAST(__serpent_encrypt
) }
62 static const struct common_glue_ctx serpent_ctr
= {
64 .fpu_blocks_limit
= 8,
68 .fn_u
= { .ctr
= GLUE_CTR_FUNC_CAST(serpent_ctr_16way
) }
71 .fn_u
= { .ctr
= GLUE_CTR_FUNC_CAST(serpent_ctr_8way_avx
) }
74 .fn_u
= { .ctr
= GLUE_CTR_FUNC_CAST(__serpent_crypt_ctr
) }
78 static const struct common_glue_ctx serpent_enc_xts
= {
80 .fpu_blocks_limit
= 8,
84 .fn_u
= { .xts
= GLUE_XTS_FUNC_CAST(serpent_xts_enc_16way
) }
87 .fn_u
= { .xts
= GLUE_XTS_FUNC_CAST(serpent_xts_enc_8way_avx
) }
90 .fn_u
= { .xts
= GLUE_XTS_FUNC_CAST(serpent_xts_enc
) }
94 static const struct common_glue_ctx serpent_dec
= {
96 .fpu_blocks_limit
= 8,
100 .fn_u
= { .ecb
= GLUE_FUNC_CAST(serpent_ecb_dec_16way
) }
103 .fn_u
= { .ecb
= GLUE_FUNC_CAST(serpent_ecb_dec_8way_avx
) }
106 .fn_u
= { .ecb
= GLUE_FUNC_CAST(__serpent_decrypt
) }
110 static const struct common_glue_ctx serpent_dec_cbc
= {
112 .fpu_blocks_limit
= 8,
116 .fn_u
= { .cbc
= GLUE_CBC_FUNC_CAST(serpent_cbc_dec_16way
) }
119 .fn_u
= { .cbc
= GLUE_CBC_FUNC_CAST(serpent_cbc_dec_8way_avx
) }
122 .fn_u
= { .cbc
= GLUE_CBC_FUNC_CAST(__serpent_decrypt
) }
126 static const struct common_glue_ctx serpent_dec_xts
= {
128 .fpu_blocks_limit
= 8,
132 .fn_u
= { .xts
= GLUE_XTS_FUNC_CAST(serpent_xts_dec_16way
) }
135 .fn_u
= { .xts
= GLUE_XTS_FUNC_CAST(serpent_xts_dec_8way_avx
) }
138 .fn_u
= { .xts
= GLUE_XTS_FUNC_CAST(serpent_xts_dec
) }
142 static int ecb_encrypt(struct skcipher_request
*req
)
144 return glue_ecb_req_128bit(&serpent_enc
, req
);
147 static int ecb_decrypt(struct skcipher_request
*req
)
149 return glue_ecb_req_128bit(&serpent_dec
, req
);
152 static int cbc_encrypt(struct skcipher_request
*req
)
154 return glue_cbc_encrypt_req_128bit(GLUE_FUNC_CAST(__serpent_encrypt
),
158 static int cbc_decrypt(struct skcipher_request
*req
)
160 return glue_cbc_decrypt_req_128bit(&serpent_dec_cbc
, req
);
163 static int ctr_crypt(struct skcipher_request
*req
)
165 return glue_ctr_req_128bit(&serpent_ctr
, req
);
168 static int xts_encrypt(struct skcipher_request
*req
)
170 struct crypto_skcipher
*tfm
= crypto_skcipher_reqtfm(req
);
171 struct serpent_xts_ctx
*ctx
= crypto_skcipher_ctx(tfm
);
173 return glue_xts_req_128bit(&serpent_enc_xts
, req
,
174 XTS_TWEAK_CAST(__serpent_encrypt
),
175 &ctx
->tweak_ctx
, &ctx
->crypt_ctx
);
178 static int xts_decrypt(struct skcipher_request
*req
)
180 struct crypto_skcipher
*tfm
= crypto_skcipher_reqtfm(req
);
181 struct serpent_xts_ctx
*ctx
= crypto_skcipher_ctx(tfm
);
183 return glue_xts_req_128bit(&serpent_dec_xts
, req
,
184 XTS_TWEAK_CAST(__serpent_encrypt
),
185 &ctx
->tweak_ctx
, &ctx
->crypt_ctx
);
188 static struct skcipher_alg serpent_algs
[] = {
190 .base
.cra_name
= "__ecb(serpent)",
191 .base
.cra_driver_name
= "__ecb-serpent-avx2",
192 .base
.cra_priority
= 600,
193 .base
.cra_flags
= CRYPTO_ALG_INTERNAL
,
194 .base
.cra_blocksize
= SERPENT_BLOCK_SIZE
,
195 .base
.cra_ctxsize
= sizeof(struct serpent_ctx
),
196 .base
.cra_module
= THIS_MODULE
,
197 .min_keysize
= SERPENT_MIN_KEY_SIZE
,
198 .max_keysize
= SERPENT_MAX_KEY_SIZE
,
199 .setkey
= serpent_setkey_skcipher
,
200 .encrypt
= ecb_encrypt
,
201 .decrypt
= ecb_decrypt
,
203 .base
.cra_name
= "__cbc(serpent)",
204 .base
.cra_driver_name
= "__cbc-serpent-avx2",
205 .base
.cra_priority
= 600,
206 .base
.cra_flags
= CRYPTO_ALG_INTERNAL
,
207 .base
.cra_blocksize
= SERPENT_BLOCK_SIZE
,
208 .base
.cra_ctxsize
= sizeof(struct serpent_ctx
),
209 .base
.cra_module
= THIS_MODULE
,
210 .min_keysize
= SERPENT_MIN_KEY_SIZE
,
211 .max_keysize
= SERPENT_MAX_KEY_SIZE
,
212 .ivsize
= SERPENT_BLOCK_SIZE
,
213 .setkey
= serpent_setkey_skcipher
,
214 .encrypt
= cbc_encrypt
,
215 .decrypt
= cbc_decrypt
,
217 .base
.cra_name
= "__ctr(serpent)",
218 .base
.cra_driver_name
= "__ctr-serpent-avx2",
219 .base
.cra_priority
= 600,
220 .base
.cra_flags
= CRYPTO_ALG_INTERNAL
,
221 .base
.cra_blocksize
= 1,
222 .base
.cra_ctxsize
= sizeof(struct serpent_ctx
),
223 .base
.cra_module
= THIS_MODULE
,
224 .min_keysize
= SERPENT_MIN_KEY_SIZE
,
225 .max_keysize
= SERPENT_MAX_KEY_SIZE
,
226 .ivsize
= SERPENT_BLOCK_SIZE
,
227 .chunksize
= SERPENT_BLOCK_SIZE
,
228 .setkey
= serpent_setkey_skcipher
,
229 .encrypt
= ctr_crypt
,
230 .decrypt
= ctr_crypt
,
232 .base
.cra_name
= "__xts(serpent)",
233 .base
.cra_driver_name
= "__xts-serpent-avx2",
234 .base
.cra_priority
= 600,
235 .base
.cra_flags
= CRYPTO_ALG_INTERNAL
,
236 .base
.cra_blocksize
= SERPENT_BLOCK_SIZE
,
237 .base
.cra_ctxsize
= sizeof(struct serpent_xts_ctx
),
238 .base
.cra_module
= THIS_MODULE
,
239 .min_keysize
= 2 * SERPENT_MIN_KEY_SIZE
,
240 .max_keysize
= 2 * SERPENT_MAX_KEY_SIZE
,
241 .ivsize
= SERPENT_BLOCK_SIZE
,
242 .setkey
= xts_serpent_setkey
,
243 .encrypt
= xts_encrypt
,
244 .decrypt
= xts_decrypt
,
248 static struct simd_skcipher_alg
*serpent_simd_algs
[ARRAY_SIZE(serpent_algs
)];
250 static int __init
init(void)
252 const char *feature_name
;
254 if (!boot_cpu_has(X86_FEATURE_AVX2
) || !boot_cpu_has(X86_FEATURE_OSXSAVE
)) {
255 pr_info("AVX2 instructions are not detected.\n");
258 if (!cpu_has_xfeatures(XFEATURE_MASK_SSE
| XFEATURE_MASK_YMM
,
260 pr_info("CPU feature '%s' is not supported.\n", feature_name
);
264 return simd_register_skciphers_compat(serpent_algs
,
265 ARRAY_SIZE(serpent_algs
),
269 static void __exit
fini(void)
271 simd_unregister_skciphers(serpent_algs
, ARRAY_SIZE(serpent_algs
),
278 MODULE_LICENSE("GPL");
279 MODULE_DESCRIPTION("Serpent Cipher Algorithm, AVX2 optimized");
280 MODULE_ALIAS_CRYPTO("serpent");
281 MODULE_ALIAS_CRYPTO("serpent-asm");