Path: blob/master/arch/x86/crypto/aria_aesni_avx2_glue.c
26442 views
/* SPDX-License-Identifier: GPL-2.0-or-later */1/*2* Glue Code for the AVX2/AES-NI/GFNI assembler implementation of the ARIA Cipher3*4* Copyright (c) 2022 Taehee Yoo <[email protected]>5*/67#include <crypto/algapi.h>8#include <crypto/aria.h>9#include <linux/crypto.h>10#include <linux/err.h>11#include <linux/export.h>12#include <linux/module.h>13#include <linux/types.h>1415#include "ecb_cbc_helpers.h"16#include "aria-avx.h"1718asmlinkage void aria_aesni_avx2_encrypt_32way(const void *ctx, u8 *dst,19const u8 *src);20EXPORT_SYMBOL_GPL(aria_aesni_avx2_encrypt_32way);21asmlinkage void aria_aesni_avx2_decrypt_32way(const void *ctx, u8 *dst,22const u8 *src);23EXPORT_SYMBOL_GPL(aria_aesni_avx2_decrypt_32way);24asmlinkage void aria_aesni_avx2_ctr_crypt_32way(const void *ctx, u8 *dst,25const u8 *src,26u8 *keystream, u8 *iv);27EXPORT_SYMBOL_GPL(aria_aesni_avx2_ctr_crypt_32way);28#ifdef CONFIG_AS_GFNI29asmlinkage void aria_aesni_avx2_gfni_encrypt_32way(const void *ctx, u8 *dst,30const u8 *src);31EXPORT_SYMBOL_GPL(aria_aesni_avx2_gfni_encrypt_32way);32asmlinkage void aria_aesni_avx2_gfni_decrypt_32way(const void *ctx, u8 *dst,33const u8 *src);34EXPORT_SYMBOL_GPL(aria_aesni_avx2_gfni_decrypt_32way);35asmlinkage void aria_aesni_avx2_gfni_ctr_crypt_32way(const void *ctx, u8 *dst,36const u8 *src,37u8 *keystream, u8 *iv);38EXPORT_SYMBOL_GPL(aria_aesni_avx2_gfni_ctr_crypt_32way);39#endif /* CONFIG_AS_GFNI */4041static struct aria_avx_ops aria_ops;4243struct aria_avx2_request_ctx {44u8 keystream[ARIA_AESNI_AVX2_PARALLEL_BLOCK_SIZE];45};4647static int ecb_do_encrypt(struct skcipher_request *req, const u32 *rkey)48{49ECB_WALK_START(req, ARIA_BLOCK_SIZE, ARIA_AESNI_PARALLEL_BLOCKS);50ECB_BLOCK(ARIA_AESNI_AVX2_PARALLEL_BLOCKS, aria_ops.aria_encrypt_32way);51ECB_BLOCK(ARIA_AESNI_PARALLEL_BLOCKS, aria_ops.aria_encrypt_16way);52ECB_BLOCK(1, aria_encrypt);53ECB_WALK_END();54}5556static int ecb_do_decrypt(struct skcipher_request *req, const u32 *rkey)57{58ECB_WALK_START(req, ARIA_BLOCK_SIZE, ARIA_AESNI_PARALLEL_BLOCKS);59ECB_BLOCK(ARIA_AESNI_AVX2_PARALLEL_BLOCKS, aria_ops.aria_decrypt_32way);60ECB_BLOCK(ARIA_AESNI_PARALLEL_BLOCKS, aria_ops.aria_decrypt_16way);61ECB_BLOCK(1, aria_decrypt);62ECB_WALK_END();63}6465static int aria_avx2_ecb_encrypt(struct skcipher_request *req)66{67struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);68struct aria_ctx *ctx = crypto_skcipher_ctx(tfm);6970return ecb_do_encrypt(req, ctx->enc_key[0]);71}7273static int aria_avx2_ecb_decrypt(struct skcipher_request *req)74{75struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);76struct aria_ctx *ctx = crypto_skcipher_ctx(tfm);7778return ecb_do_decrypt(req, ctx->dec_key[0]);79}8081static int aria_avx2_set_key(struct crypto_skcipher *tfm, const u8 *key,82unsigned int keylen)83{84return aria_set_key(&tfm->base, key, keylen);85}8687static int aria_avx2_ctr_encrypt(struct skcipher_request *req)88{89struct aria_avx2_request_ctx *req_ctx = skcipher_request_ctx(req);90struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);91struct aria_ctx *ctx = crypto_skcipher_ctx(tfm);92struct skcipher_walk walk;93unsigned int nbytes;94int err;9596err = skcipher_walk_virt(&walk, req, false);9798while ((nbytes = walk.nbytes) > 0) {99const u8 *src = walk.src.virt.addr;100u8 *dst = walk.dst.virt.addr;101102while (nbytes >= ARIA_AESNI_AVX2_PARALLEL_BLOCK_SIZE) {103kernel_fpu_begin();104aria_ops.aria_ctr_crypt_32way(ctx, dst, src,105&req_ctx->keystream[0],106walk.iv);107kernel_fpu_end();108dst += ARIA_AESNI_AVX2_PARALLEL_BLOCK_SIZE;109src += ARIA_AESNI_AVX2_PARALLEL_BLOCK_SIZE;110nbytes -= ARIA_AESNI_AVX2_PARALLEL_BLOCK_SIZE;111}112113while (nbytes >= ARIA_AESNI_PARALLEL_BLOCK_SIZE) {114kernel_fpu_begin();115aria_ops.aria_ctr_crypt_16way(ctx, dst, src,116&req_ctx->keystream[0],117walk.iv);118kernel_fpu_end();119dst += ARIA_AESNI_PARALLEL_BLOCK_SIZE;120src += ARIA_AESNI_PARALLEL_BLOCK_SIZE;121nbytes -= ARIA_AESNI_PARALLEL_BLOCK_SIZE;122}123124while (nbytes >= ARIA_BLOCK_SIZE) {125memcpy(&req_ctx->keystream[0], walk.iv, ARIA_BLOCK_SIZE);126crypto_inc(walk.iv, ARIA_BLOCK_SIZE);127128aria_encrypt(ctx, &req_ctx->keystream[0],129&req_ctx->keystream[0]);130131crypto_xor_cpy(dst, src, &req_ctx->keystream[0],132ARIA_BLOCK_SIZE);133dst += ARIA_BLOCK_SIZE;134src += ARIA_BLOCK_SIZE;135nbytes -= ARIA_BLOCK_SIZE;136}137138if (walk.nbytes == walk.total && nbytes > 0) {139memcpy(&req_ctx->keystream[0], walk.iv,140ARIA_BLOCK_SIZE);141crypto_inc(walk.iv, ARIA_BLOCK_SIZE);142143aria_encrypt(ctx, &req_ctx->keystream[0],144&req_ctx->keystream[0]);145146crypto_xor_cpy(dst, src, &req_ctx->keystream[0],147nbytes);148dst += nbytes;149src += nbytes;150nbytes = 0;151}152err = skcipher_walk_done(&walk, nbytes);153}154155return err;156}157158static int aria_avx2_init_tfm(struct crypto_skcipher *tfm)159{160crypto_skcipher_set_reqsize(tfm, sizeof(struct aria_avx2_request_ctx));161162return 0;163}164165static struct skcipher_alg aria_algs[] = {166{167.base.cra_name = "ecb(aria)",168.base.cra_driver_name = "ecb-aria-avx2",169.base.cra_priority = 500,170.base.cra_blocksize = ARIA_BLOCK_SIZE,171.base.cra_ctxsize = sizeof(struct aria_ctx),172.base.cra_module = THIS_MODULE,173.min_keysize = ARIA_MIN_KEY_SIZE,174.max_keysize = ARIA_MAX_KEY_SIZE,175.setkey = aria_avx2_set_key,176.encrypt = aria_avx2_ecb_encrypt,177.decrypt = aria_avx2_ecb_decrypt,178}, {179.base.cra_name = "ctr(aria)",180.base.cra_driver_name = "ctr-aria-avx2",181.base.cra_priority = 500,182.base.cra_flags = CRYPTO_ALG_SKCIPHER_REQSIZE_LARGE,183.base.cra_blocksize = 1,184.base.cra_ctxsize = sizeof(struct aria_ctx),185.base.cra_module = THIS_MODULE,186.min_keysize = ARIA_MIN_KEY_SIZE,187.max_keysize = ARIA_MAX_KEY_SIZE,188.ivsize = ARIA_BLOCK_SIZE,189.chunksize = ARIA_BLOCK_SIZE,190.setkey = aria_avx2_set_key,191.encrypt = aria_avx2_ctr_encrypt,192.decrypt = aria_avx2_ctr_encrypt,193.init = aria_avx2_init_tfm,194}195};196197static int __init aria_avx2_init(void)198{199const char *feature_name;200201if (!boot_cpu_has(X86_FEATURE_AVX) ||202!boot_cpu_has(X86_FEATURE_AVX2) ||203!boot_cpu_has(X86_FEATURE_AES) ||204!boot_cpu_has(X86_FEATURE_OSXSAVE)) {205pr_info("AVX2 or AES-NI instructions are not detected.\n");206return -ENODEV;207}208209if (!cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM,210&feature_name)) {211pr_info("CPU feature '%s' is not supported.\n", feature_name);212return -ENODEV;213}214215if (boot_cpu_has(X86_FEATURE_GFNI) && IS_ENABLED(CONFIG_AS_GFNI)) {216aria_ops.aria_encrypt_16way = aria_aesni_avx_gfni_encrypt_16way;217aria_ops.aria_decrypt_16way = aria_aesni_avx_gfni_decrypt_16way;218aria_ops.aria_ctr_crypt_16way = aria_aesni_avx_gfni_ctr_crypt_16way;219aria_ops.aria_encrypt_32way = aria_aesni_avx2_gfni_encrypt_32way;220aria_ops.aria_decrypt_32way = aria_aesni_avx2_gfni_decrypt_32way;221aria_ops.aria_ctr_crypt_32way = aria_aesni_avx2_gfni_ctr_crypt_32way;222} else {223aria_ops.aria_encrypt_16way = aria_aesni_avx_encrypt_16way;224aria_ops.aria_decrypt_16way = aria_aesni_avx_decrypt_16way;225aria_ops.aria_ctr_crypt_16way = aria_aesni_avx_ctr_crypt_16way;226aria_ops.aria_encrypt_32way = aria_aesni_avx2_encrypt_32way;227aria_ops.aria_decrypt_32way = aria_aesni_avx2_decrypt_32way;228aria_ops.aria_ctr_crypt_32way = aria_aesni_avx2_ctr_crypt_32way;229}230231return crypto_register_skciphers(aria_algs, ARRAY_SIZE(aria_algs));232}233234static void __exit aria_avx2_exit(void)235{236crypto_unregister_skciphers(aria_algs, ARRAY_SIZE(aria_algs));237}238239module_init(aria_avx2_init);240module_exit(aria_avx2_exit);241242MODULE_LICENSE("GPL");243MODULE_AUTHOR("Taehee Yoo <[email protected]>");244MODULE_DESCRIPTION("ARIA Cipher Algorithm, AVX2/AES-NI/GFNI optimized");245MODULE_ALIAS_CRYPTO("aria");246MODULE_ALIAS_CRYPTO("aria-aesni-avx2");247248249