11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
27efe4076SJohannes Goetzfried /*
37efe4076SJohannes Goetzfried * Glue Code for AVX assembler versions of Serpent Cipher
47efe4076SJohannes Goetzfried *
57efe4076SJohannes Goetzfried * Copyright (C) 2012 Johannes Goetzfried
67efe4076SJohannes Goetzfried * <Johannes.Goetzfried@informatik.stud.uni-erlangen.de>
77efe4076SJohannes Goetzfried *
8a05248edSJussi Kivilinna * Copyright © 2011-2013 Jussi Kivilinna <jussi.kivilinna@iki.fi>
97efe4076SJohannes Goetzfried */
107efe4076SJohannes Goetzfried
117efe4076SJohannes Goetzfried #include <linux/module.h>
127efe4076SJohannes Goetzfried #include <linux/types.h>
137efe4076SJohannes Goetzfried #include <linux/crypto.h>
147efe4076SJohannes Goetzfried #include <linux/err.h>
157efe4076SJohannes Goetzfried #include <crypto/algapi.h>
16e16bf974SEric Biggers #include <crypto/internal/simd.h>
177efe4076SJohannes Goetzfried #include <crypto/serpent.h>
187efe4076SJohannes Goetzfried
19*a04ea6f7SArd Biesheuvel #include "serpent-avx.h"
209ad58b46SArd Biesheuvel #include "ecb_cbc_helpers.h"
219ad58b46SArd Biesheuvel
2256d76c96SJussi Kivilinna /* 8-way parallel cipher functions */
239c1e8836SKees Cook asmlinkage void serpent_ecb_enc_8way_avx(const void *ctx, u8 *dst,
2456d76c96SJussi Kivilinna const u8 *src);
2556d76c96SJussi Kivilinna EXPORT_SYMBOL_GPL(serpent_ecb_enc_8way_avx);
2656d76c96SJussi Kivilinna
279c1e8836SKees Cook asmlinkage void serpent_ecb_dec_8way_avx(const void *ctx, u8 *dst,
2856d76c96SJussi Kivilinna const u8 *src);
2956d76c96SJussi Kivilinna EXPORT_SYMBOL_GPL(serpent_ecb_dec_8way_avx);
3056d76c96SJussi Kivilinna
319c1e8836SKees Cook asmlinkage void serpent_cbc_dec_8way_avx(const void *ctx, u8 *dst,
3256d76c96SJussi Kivilinna const u8 *src);
3356d76c96SJussi Kivilinna EXPORT_SYMBOL_GPL(serpent_cbc_dec_8way_avx);
3456d76c96SJussi Kivilinna
serpent_setkey_skcipher(struct crypto_skcipher * tfm,const u8 * key,unsigned int keylen)35e16bf974SEric Biggers static int serpent_setkey_skcipher(struct crypto_skcipher *tfm,
36e16bf974SEric Biggers const u8 *key, unsigned int keylen)
37e16bf974SEric Biggers {
38e16bf974SEric Biggers return __serpent_setkey(crypto_skcipher_ctx(tfm), key, keylen);
39e16bf974SEric Biggers }
40e16bf974SEric Biggers
ecb_encrypt(struct skcipher_request * req)41e16bf974SEric Biggers static int ecb_encrypt(struct skcipher_request *req)
427efe4076SJohannes Goetzfried {
439ad58b46SArd Biesheuvel ECB_WALK_START(req, SERPENT_BLOCK_SIZE, SERPENT_PARALLEL_BLOCKS);
449ad58b46SArd Biesheuvel ECB_BLOCK(SERPENT_PARALLEL_BLOCKS, serpent_ecb_enc_8way_avx);
459ad58b46SArd Biesheuvel ECB_BLOCK(1, __serpent_encrypt);
469ad58b46SArd Biesheuvel ECB_WALK_END();
477efe4076SJohannes Goetzfried }
487efe4076SJohannes Goetzfried
ecb_decrypt(struct skcipher_request * req)49e16bf974SEric Biggers static int ecb_decrypt(struct skcipher_request *req)
507efe4076SJohannes Goetzfried {
519ad58b46SArd Biesheuvel ECB_WALK_START(req, SERPENT_BLOCK_SIZE, SERPENT_PARALLEL_BLOCKS);
529ad58b46SArd Biesheuvel ECB_BLOCK(SERPENT_PARALLEL_BLOCKS, serpent_ecb_dec_8way_avx);
539ad58b46SArd Biesheuvel ECB_BLOCK(1, __serpent_decrypt);
549ad58b46SArd Biesheuvel ECB_WALK_END();
557efe4076SJohannes Goetzfried }
567efe4076SJohannes Goetzfried
cbc_encrypt(struct skcipher_request * req)57e16bf974SEric Biggers static int cbc_encrypt(struct skcipher_request *req)
587efe4076SJohannes Goetzfried {
599ad58b46SArd Biesheuvel CBC_WALK_START(req, SERPENT_BLOCK_SIZE, -1);
609ad58b46SArd Biesheuvel CBC_ENC_BLOCK(__serpent_encrypt);
619ad58b46SArd Biesheuvel CBC_WALK_END();
627efe4076SJohannes Goetzfried }
637efe4076SJohannes Goetzfried
cbc_decrypt(struct skcipher_request * req)64e16bf974SEric Biggers static int cbc_decrypt(struct skcipher_request *req)
657efe4076SJohannes Goetzfried {
669ad58b46SArd Biesheuvel CBC_WALK_START(req, SERPENT_BLOCK_SIZE, SERPENT_PARALLEL_BLOCKS);
679ad58b46SArd Biesheuvel CBC_DEC_BLOCK(SERPENT_PARALLEL_BLOCKS, serpent_cbc_dec_8way_avx);
689ad58b46SArd Biesheuvel CBC_DEC_BLOCK(1, __serpent_decrypt);
699ad58b46SArd Biesheuvel CBC_WALK_END();
707efe4076SJohannes Goetzfried }
717efe4076SJohannes Goetzfried
72e16bf974SEric Biggers static struct skcipher_alg serpent_algs[] = {
73e16bf974SEric Biggers {
74e16bf974SEric Biggers .base.cra_name = "__ecb(serpent)",
75e16bf974SEric Biggers .base.cra_driver_name = "__ecb-serpent-avx",
76e16bf974SEric Biggers .base.cra_priority = 500,
77e16bf974SEric Biggers .base.cra_flags = CRYPTO_ALG_INTERNAL,
78e16bf974SEric Biggers .base.cra_blocksize = SERPENT_BLOCK_SIZE,
79e16bf974SEric Biggers .base.cra_ctxsize = sizeof(struct serpent_ctx),
80e16bf974SEric Biggers .base.cra_module = THIS_MODULE,
817efe4076SJohannes Goetzfried .min_keysize = SERPENT_MIN_KEY_SIZE,
827efe4076SJohannes Goetzfried .max_keysize = SERPENT_MAX_KEY_SIZE,
83e16bf974SEric Biggers .setkey = serpent_setkey_skcipher,
847efe4076SJohannes Goetzfried .encrypt = ecb_encrypt,
857efe4076SJohannes Goetzfried .decrypt = ecb_decrypt,
867efe4076SJohannes Goetzfried }, {
87e16bf974SEric Biggers .base.cra_name = "__cbc(serpent)",
88e16bf974SEric Biggers .base.cra_driver_name = "__cbc-serpent-avx",
89e16bf974SEric Biggers .base.cra_priority = 500,
90e16bf974SEric Biggers .base.cra_flags = CRYPTO_ALG_INTERNAL,
91e16bf974SEric Biggers .base.cra_blocksize = SERPENT_BLOCK_SIZE,
92e16bf974SEric Biggers .base.cra_ctxsize = sizeof(struct serpent_ctx),
93e16bf974SEric Biggers .base.cra_module = THIS_MODULE,
947efe4076SJohannes Goetzfried .min_keysize = SERPENT_MIN_KEY_SIZE,
957efe4076SJohannes Goetzfried .max_keysize = SERPENT_MAX_KEY_SIZE,
967efe4076SJohannes Goetzfried .ivsize = SERPENT_BLOCK_SIZE,
97e16bf974SEric Biggers .setkey = serpent_setkey_skcipher,
98e16bf974SEric Biggers .encrypt = cbc_encrypt,
99e16bf974SEric Biggers .decrypt = cbc_decrypt,
1007efe4076SJohannes Goetzfried },
101e16bf974SEric Biggers };
102e16bf974SEric Biggers
103e16bf974SEric Biggers static struct simd_skcipher_alg *serpent_simd_algs[ARRAY_SIZE(serpent_algs)];
1047efe4076SJohannes Goetzfried
serpent_init(void)1057efe4076SJohannes Goetzfried static int __init serpent_init(void)
1067efe4076SJohannes Goetzfried {
107c1c23f7eSIngo Molnar const char *feature_name;
1087efe4076SJohannes Goetzfried
109d91cab78SDave Hansen if (!cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM,
110d91cab78SDave Hansen &feature_name)) {
111c1c23f7eSIngo Molnar pr_info("CPU feature '%s' is not supported.\n", feature_name);
1127efe4076SJohannes Goetzfried return -ENODEV;
1137efe4076SJohannes Goetzfried }
1147efe4076SJohannes Goetzfried
115e16bf974SEric Biggers return simd_register_skciphers_compat(serpent_algs,
116e16bf974SEric Biggers ARRAY_SIZE(serpent_algs),
117e16bf974SEric Biggers serpent_simd_algs);
1187efe4076SJohannes Goetzfried }
1197efe4076SJohannes Goetzfried
serpent_exit(void)1207efe4076SJohannes Goetzfried static void __exit serpent_exit(void)
1217efe4076SJohannes Goetzfried {
122e16bf974SEric Biggers simd_unregister_skciphers(serpent_algs, ARRAY_SIZE(serpent_algs),
123e16bf974SEric Biggers serpent_simd_algs);
1247efe4076SJohannes Goetzfried }
1257efe4076SJohannes Goetzfried
1267efe4076SJohannes Goetzfried module_init(serpent_init);
1277efe4076SJohannes Goetzfried module_exit(serpent_exit);
1287efe4076SJohannes Goetzfried
1297efe4076SJohannes Goetzfried MODULE_DESCRIPTION("Serpent Cipher Algorithm, AVX optimized");
1307efe4076SJohannes Goetzfried MODULE_LICENSE("GPL");
1315d26a105SKees Cook MODULE_ALIAS_CRYPTO("serpent");
132