2 * Glue Code for AVX assembler versions of Serpent Cipher
4 * Copyright (C) 2012 Johannes Goetzfried
5 * <Johannes.Goetzfried@informatik.stud.uni-erlangen.de>
7 * Copyright © 2011-2013 Jussi Kivilinna <jussi.kivilinna@iki.fi>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
26 #include <linux/module.h>
27 #include <linux/types.h>
28 #include <linux/crypto.h>
29 #include <linux/err.h>
30 #include <crypto/algapi.h>
31 #include <crypto/internal/simd.h>
32 #include <crypto/serpent.h>
33 #include <crypto/xts.h>
34 #include <asm/crypto/glue_helper.h>
35 #include <asm/crypto/serpent-avx.h>
37 /* 8-way parallel cipher functions */
38 asmlinkage
void serpent_ecb_enc_8way_avx(struct serpent_ctx
*ctx
, u8
*dst
,
40 EXPORT_SYMBOL_GPL(serpent_ecb_enc_8way_avx
);
42 asmlinkage
void serpent_ecb_dec_8way_avx(struct serpent_ctx
*ctx
, u8
*dst
,
44 EXPORT_SYMBOL_GPL(serpent_ecb_dec_8way_avx
);
46 asmlinkage
void serpent_cbc_dec_8way_avx(struct serpent_ctx
*ctx
, u8
*dst
,
48 EXPORT_SYMBOL_GPL(serpent_cbc_dec_8way_avx
);
50 asmlinkage
void serpent_ctr_8way_avx(struct serpent_ctx
*ctx
, u8
*dst
,
51 const u8
*src
, le128
*iv
);
52 EXPORT_SYMBOL_GPL(serpent_ctr_8way_avx
);
54 asmlinkage
void serpent_xts_enc_8way_avx(struct serpent_ctx
*ctx
, u8
*dst
,
55 const u8
*src
, le128
*iv
);
56 EXPORT_SYMBOL_GPL(serpent_xts_enc_8way_avx
);
58 asmlinkage
void serpent_xts_dec_8way_avx(struct serpent_ctx
*ctx
, u8
*dst
,
59 const u8
*src
, le128
*iv
);
60 EXPORT_SYMBOL_GPL(serpent_xts_dec_8way_avx
);
62 void __serpent_crypt_ctr(void *ctx
, u128
*dst
, const u128
*src
, le128
*iv
)
66 le128_to_be128(&ctrblk
, iv
);
69 __serpent_encrypt(ctx
, (u8
*)&ctrblk
, (u8
*)&ctrblk
);
70 u128_xor(dst
, src
, (u128
*)&ctrblk
);
72 EXPORT_SYMBOL_GPL(__serpent_crypt_ctr
);
74 void serpent_xts_enc(void *ctx
, u128
*dst
, const u128
*src
, le128
*iv
)
76 glue_xts_crypt_128bit_one(ctx
, dst
, src
, iv
,
77 GLUE_FUNC_CAST(__serpent_encrypt
));
79 EXPORT_SYMBOL_GPL(serpent_xts_enc
);
81 void serpent_xts_dec(void *ctx
, u128
*dst
, const u128
*src
, le128
*iv
)
83 glue_xts_crypt_128bit_one(ctx
, dst
, src
, iv
,
84 GLUE_FUNC_CAST(__serpent_decrypt
));
86 EXPORT_SYMBOL_GPL(serpent_xts_dec
);
88 static int serpent_setkey_skcipher(struct crypto_skcipher
*tfm
,
89 const u8
*key
, unsigned int keylen
)
91 return __serpent_setkey(crypto_skcipher_ctx(tfm
), key
, keylen
);
94 int xts_serpent_setkey(struct crypto_skcipher
*tfm
, const u8
*key
,
97 struct serpent_xts_ctx
*ctx
= crypto_skcipher_ctx(tfm
);
100 err
= xts_verify_key(tfm
, key
, keylen
);
104 /* first half of xts-key is for crypt */
105 err
= __serpent_setkey(&ctx
->crypt_ctx
, key
, keylen
/ 2);
109 /* second half of xts-key is for tweak */
110 return __serpent_setkey(&ctx
->tweak_ctx
, key
+ keylen
/ 2, keylen
/ 2);
112 EXPORT_SYMBOL_GPL(xts_serpent_setkey
);
114 static const struct common_glue_ctx serpent_enc
= {
116 .fpu_blocks_limit
= SERPENT_PARALLEL_BLOCKS
,
119 .num_blocks
= SERPENT_PARALLEL_BLOCKS
,
120 .fn_u
= { .ecb
= GLUE_FUNC_CAST(serpent_ecb_enc_8way_avx
) }
123 .fn_u
= { .ecb
= GLUE_FUNC_CAST(__serpent_encrypt
) }
127 static const struct common_glue_ctx serpent_ctr
= {
129 .fpu_blocks_limit
= SERPENT_PARALLEL_BLOCKS
,
132 .num_blocks
= SERPENT_PARALLEL_BLOCKS
,
133 .fn_u
= { .ctr
= GLUE_CTR_FUNC_CAST(serpent_ctr_8way_avx
) }
136 .fn_u
= { .ctr
= GLUE_CTR_FUNC_CAST(__serpent_crypt_ctr
) }
140 static const struct common_glue_ctx serpent_enc_xts
= {
142 .fpu_blocks_limit
= SERPENT_PARALLEL_BLOCKS
,
145 .num_blocks
= SERPENT_PARALLEL_BLOCKS
,
146 .fn_u
= { .xts
= GLUE_XTS_FUNC_CAST(serpent_xts_enc_8way_avx
) }
149 .fn_u
= { .xts
= GLUE_XTS_FUNC_CAST(serpent_xts_enc
) }
153 static const struct common_glue_ctx serpent_dec
= {
155 .fpu_blocks_limit
= SERPENT_PARALLEL_BLOCKS
,
158 .num_blocks
= SERPENT_PARALLEL_BLOCKS
,
159 .fn_u
= { .ecb
= GLUE_FUNC_CAST(serpent_ecb_dec_8way_avx
) }
162 .fn_u
= { .ecb
= GLUE_FUNC_CAST(__serpent_decrypt
) }
166 static const struct common_glue_ctx serpent_dec_cbc
= {
168 .fpu_blocks_limit
= SERPENT_PARALLEL_BLOCKS
,
171 .num_blocks
= SERPENT_PARALLEL_BLOCKS
,
172 .fn_u
= { .cbc
= GLUE_CBC_FUNC_CAST(serpent_cbc_dec_8way_avx
) }
175 .fn_u
= { .cbc
= GLUE_CBC_FUNC_CAST(__serpent_decrypt
) }
179 static const struct common_glue_ctx serpent_dec_xts
= {
181 .fpu_blocks_limit
= SERPENT_PARALLEL_BLOCKS
,
184 .num_blocks
= SERPENT_PARALLEL_BLOCKS
,
185 .fn_u
= { .xts
= GLUE_XTS_FUNC_CAST(serpent_xts_dec_8way_avx
) }
188 .fn_u
= { .xts
= GLUE_XTS_FUNC_CAST(serpent_xts_dec
) }
192 static int ecb_encrypt(struct skcipher_request
*req
)
194 return glue_ecb_req_128bit(&serpent_enc
, req
);
197 static int ecb_decrypt(struct skcipher_request
*req
)
199 return glue_ecb_req_128bit(&serpent_dec
, req
);
202 static int cbc_encrypt(struct skcipher_request
*req
)
204 return glue_cbc_encrypt_req_128bit(GLUE_FUNC_CAST(__serpent_encrypt
),
208 static int cbc_decrypt(struct skcipher_request
*req
)
210 return glue_cbc_decrypt_req_128bit(&serpent_dec_cbc
, req
);
213 static int ctr_crypt(struct skcipher_request
*req
)
215 return glue_ctr_req_128bit(&serpent_ctr
, req
);
218 static int xts_encrypt(struct skcipher_request
*req
)
220 struct crypto_skcipher
*tfm
= crypto_skcipher_reqtfm(req
);
221 struct serpent_xts_ctx
*ctx
= crypto_skcipher_ctx(tfm
);
223 return glue_xts_req_128bit(&serpent_enc_xts
, req
,
224 XTS_TWEAK_CAST(__serpent_encrypt
),
225 &ctx
->tweak_ctx
, &ctx
->crypt_ctx
);
228 static int xts_decrypt(struct skcipher_request
*req
)
230 struct crypto_skcipher
*tfm
= crypto_skcipher_reqtfm(req
);
231 struct serpent_xts_ctx
*ctx
= crypto_skcipher_ctx(tfm
);
233 return glue_xts_req_128bit(&serpent_dec_xts
, req
,
234 XTS_TWEAK_CAST(__serpent_encrypt
),
235 &ctx
->tweak_ctx
, &ctx
->crypt_ctx
);
238 static struct skcipher_alg serpent_algs
[] = {
240 .base
.cra_name
= "__ecb(serpent)",
241 .base
.cra_driver_name
= "__ecb-serpent-avx",
242 .base
.cra_priority
= 500,
243 .base
.cra_flags
= CRYPTO_ALG_INTERNAL
,
244 .base
.cra_blocksize
= SERPENT_BLOCK_SIZE
,
245 .base
.cra_ctxsize
= sizeof(struct serpent_ctx
),
246 .base
.cra_module
= THIS_MODULE
,
247 .min_keysize
= SERPENT_MIN_KEY_SIZE
,
248 .max_keysize
= SERPENT_MAX_KEY_SIZE
,
249 .setkey
= serpent_setkey_skcipher
,
250 .encrypt
= ecb_encrypt
,
251 .decrypt
= ecb_decrypt
,
253 .base
.cra_name
= "__cbc(serpent)",
254 .base
.cra_driver_name
= "__cbc-serpent-avx",
255 .base
.cra_priority
= 500,
256 .base
.cra_flags
= CRYPTO_ALG_INTERNAL
,
257 .base
.cra_blocksize
= SERPENT_BLOCK_SIZE
,
258 .base
.cra_ctxsize
= sizeof(struct serpent_ctx
),
259 .base
.cra_module
= THIS_MODULE
,
260 .min_keysize
= SERPENT_MIN_KEY_SIZE
,
261 .max_keysize
= SERPENT_MAX_KEY_SIZE
,
262 .ivsize
= SERPENT_BLOCK_SIZE
,
263 .setkey
= serpent_setkey_skcipher
,
264 .encrypt
= cbc_encrypt
,
265 .decrypt
= cbc_decrypt
,
267 .base
.cra_name
= "__ctr(serpent)",
268 .base
.cra_driver_name
= "__ctr-serpent-avx",
269 .base
.cra_priority
= 500,
270 .base
.cra_flags
= CRYPTO_ALG_INTERNAL
,
271 .base
.cra_blocksize
= 1,
272 .base
.cra_ctxsize
= sizeof(struct serpent_ctx
),
273 .base
.cra_module
= THIS_MODULE
,
274 .min_keysize
= SERPENT_MIN_KEY_SIZE
,
275 .max_keysize
= SERPENT_MAX_KEY_SIZE
,
276 .ivsize
= SERPENT_BLOCK_SIZE
,
277 .chunksize
= SERPENT_BLOCK_SIZE
,
278 .setkey
= serpent_setkey_skcipher
,
279 .encrypt
= ctr_crypt
,
280 .decrypt
= ctr_crypt
,
282 .base
.cra_name
= "__xts(serpent)",
283 .base
.cra_driver_name
= "__xts-serpent-avx",
284 .base
.cra_priority
= 500,
285 .base
.cra_flags
= CRYPTO_ALG_INTERNAL
,
286 .base
.cra_blocksize
= SERPENT_BLOCK_SIZE
,
287 .base
.cra_ctxsize
= sizeof(struct serpent_xts_ctx
),
288 .base
.cra_module
= THIS_MODULE
,
289 .min_keysize
= 2 * SERPENT_MIN_KEY_SIZE
,
290 .max_keysize
= 2 * SERPENT_MAX_KEY_SIZE
,
291 .ivsize
= SERPENT_BLOCK_SIZE
,
292 .setkey
= xts_serpent_setkey
,
293 .encrypt
= xts_encrypt
,
294 .decrypt
= xts_decrypt
,
298 static struct simd_skcipher_alg
*serpent_simd_algs
[ARRAY_SIZE(serpent_algs
)];
300 static int __init
serpent_init(void)
302 const char *feature_name
;
304 if (!cpu_has_xfeatures(XFEATURE_MASK_SSE
| XFEATURE_MASK_YMM
,
306 pr_info("CPU feature '%s' is not supported.\n", feature_name
);
310 return simd_register_skciphers_compat(serpent_algs
,
311 ARRAY_SIZE(serpent_algs
),
315 static void __exit
serpent_exit(void)
317 simd_unregister_skciphers(serpent_algs
, ARRAY_SIZE(serpent_algs
),
321 module_init(serpent_init
);
322 module_exit(serpent_exit
);
324 MODULE_DESCRIPTION("Serpent Cipher Algorithm, AVX optimized");
325 MODULE_LICENSE("GPL");
326 MODULE_ALIAS_CRYPTO("serpent");