Path: blob/master/arch/x86/crypto/aria_aesni_avx2_glue.c
54321 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);28asmlinkage void aria_aesni_avx2_gfni_encrypt_32way(const void *ctx, u8 *dst,29const u8 *src);30EXPORT_SYMBOL_GPL(aria_aesni_avx2_gfni_encrypt_32way);31asmlinkage void aria_aesni_avx2_gfni_decrypt_32way(const void *ctx, u8 *dst,32const u8 *src);33EXPORT_SYMBOL_GPL(aria_aesni_avx2_gfni_decrypt_32way);34asmlinkage void aria_aesni_avx2_gfni_ctr_crypt_32way(const void *ctx, u8 *dst,35const u8 *src,36u8 *keystream, u8 *iv);37EXPORT_SYMBOL_GPL(aria_aesni_avx2_gfni_ctr_crypt_32way);3839static struct aria_avx_ops aria_ops;4041struct aria_avx2_request_ctx {42u8 keystream[ARIA_AESNI_AVX2_PARALLEL_BLOCK_SIZE];43};4445static int ecb_do_encrypt(struct skcipher_request *req, const u32 *rkey)46{47ECB_WALK_START(req, ARIA_BLOCK_SIZE, ARIA_AESNI_PARALLEL_BLOCKS);48ECB_BLOCK(ARIA_AESNI_AVX2_PARALLEL_BLOCKS, aria_ops.aria_encrypt_32way);49ECB_BLOCK(ARIA_AESNI_PARALLEL_BLOCKS, aria_ops.aria_encrypt_16way);50ECB_BLOCK(1, aria_encrypt);51ECB_WALK_END();52}5354static int ecb_do_decrypt(struct skcipher_request *req, const u32 *rkey)55{56ECB_WALK_START(req, ARIA_BLOCK_SIZE, ARIA_AESNI_PARALLEL_BLOCKS);57ECB_BLOCK(ARIA_AESNI_AVX2_PARALLEL_BLOCKS, aria_ops.aria_decrypt_32way);58ECB_BLOCK(ARIA_AESNI_PARALLEL_BLOCKS, aria_ops.aria_decrypt_16way);59ECB_BLOCK(1, aria_decrypt);60ECB_WALK_END();61}6263static int aria_avx2_ecb_encrypt(struct skcipher_request *req)64{65struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);66struct aria_ctx *ctx = crypto_skcipher_ctx(tfm);6768return ecb_do_encrypt(req, ctx->enc_key[0]);69}7071static int aria_avx2_ecb_decrypt(struct skcipher_request *req)72{73struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);74struct aria_ctx *ctx = crypto_skcipher_ctx(tfm);7576return ecb_do_decrypt(req, ctx->dec_key[0]);77}7879static int aria_avx2_set_key(struct crypto_skcipher *tfm, const u8 *key,80unsigned int keylen)81{82return aria_set_key(&tfm->base, key, keylen);83}8485static int aria_avx2_ctr_encrypt(struct skcipher_request *req)86{87struct aria_avx2_request_ctx *req_ctx = skcipher_request_ctx(req);88struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);89struct aria_ctx *ctx = crypto_skcipher_ctx(tfm);90struct skcipher_walk walk;91unsigned int nbytes;92int err;9394err = skcipher_walk_virt(&walk, req, false);9596while ((nbytes = walk.nbytes) > 0) {97const u8 *src = walk.src.virt.addr;98u8 *dst = walk.dst.virt.addr;99100while (nbytes >= ARIA_AESNI_AVX2_PARALLEL_BLOCK_SIZE) {101kernel_fpu_begin();102aria_ops.aria_ctr_crypt_32way(ctx, dst, src,103&req_ctx->keystream[0],104walk.iv);105kernel_fpu_end();106dst += ARIA_AESNI_AVX2_PARALLEL_BLOCK_SIZE;107src += ARIA_AESNI_AVX2_PARALLEL_BLOCK_SIZE;108nbytes -= ARIA_AESNI_AVX2_PARALLEL_BLOCK_SIZE;109}110111while (nbytes >= ARIA_AESNI_PARALLEL_BLOCK_SIZE) {112kernel_fpu_begin();113aria_ops.aria_ctr_crypt_16way(ctx, dst, src,114&req_ctx->keystream[0],115walk.iv);116kernel_fpu_end();117dst += ARIA_AESNI_PARALLEL_BLOCK_SIZE;118src += ARIA_AESNI_PARALLEL_BLOCK_SIZE;119nbytes -= ARIA_AESNI_PARALLEL_BLOCK_SIZE;120}121122while (nbytes >= ARIA_BLOCK_SIZE) {123memcpy(&req_ctx->keystream[0], walk.iv, ARIA_BLOCK_SIZE);124crypto_inc(walk.iv, ARIA_BLOCK_SIZE);125126aria_encrypt(ctx, &req_ctx->keystream[0],127&req_ctx->keystream[0]);128129crypto_xor_cpy(dst, src, &req_ctx->keystream[0],130ARIA_BLOCK_SIZE);131dst += ARIA_BLOCK_SIZE;132src += ARIA_BLOCK_SIZE;133nbytes -= ARIA_BLOCK_SIZE;134}135136if (walk.nbytes == walk.total && nbytes > 0) {137memcpy(&req_ctx->keystream[0], walk.iv,138ARIA_BLOCK_SIZE);139crypto_inc(walk.iv, ARIA_BLOCK_SIZE);140141aria_encrypt(ctx, &req_ctx->keystream[0],142&req_ctx->keystream[0]);143144crypto_xor_cpy(dst, src, &req_ctx->keystream[0],145nbytes);146dst += nbytes;147src += nbytes;148nbytes = 0;149}150err = skcipher_walk_done(&walk, nbytes);151}152153return err;154}155156static int aria_avx2_init_tfm(struct crypto_skcipher *tfm)157{158crypto_skcipher_set_reqsize(tfm, sizeof(struct aria_avx2_request_ctx));159160return 0;161}162163static struct skcipher_alg aria_algs[] = {164{165.base.cra_name = "ecb(aria)",166.base.cra_driver_name = "ecb-aria-avx2",167.base.cra_priority = 500,168.base.cra_blocksize = ARIA_BLOCK_SIZE,169.base.cra_ctxsize = sizeof(struct aria_ctx),170.base.cra_module = THIS_MODULE,171.min_keysize = ARIA_MIN_KEY_SIZE,172.max_keysize = ARIA_MAX_KEY_SIZE,173.setkey = aria_avx2_set_key,174.encrypt = aria_avx2_ecb_encrypt,175.decrypt = aria_avx2_ecb_decrypt,176}, {177.base.cra_name = "ctr(aria)",178.base.cra_driver_name = "ctr-aria-avx2",179.base.cra_priority = 500,180.base.cra_flags = CRYPTO_ALG_SKCIPHER_REQSIZE_LARGE,181.base.cra_blocksize = 1,182.base.cra_ctxsize = sizeof(struct aria_ctx),183.base.cra_module = THIS_MODULE,184.min_keysize = ARIA_MIN_KEY_SIZE,185.max_keysize = ARIA_MAX_KEY_SIZE,186.ivsize = ARIA_BLOCK_SIZE,187.chunksize = ARIA_BLOCK_SIZE,188.setkey = aria_avx2_set_key,189.encrypt = aria_avx2_ctr_encrypt,190.decrypt = aria_avx2_ctr_encrypt,191.init = aria_avx2_init_tfm,192}193};194195static int __init aria_avx2_init(void)196{197const char *feature_name;198199if (!boot_cpu_has(X86_FEATURE_AVX) ||200!boot_cpu_has(X86_FEATURE_AVX2) ||201!boot_cpu_has(X86_FEATURE_AES) ||202!boot_cpu_has(X86_FEATURE_OSXSAVE)) {203pr_info("AVX2 or AES-NI instructions are not detected.\n");204return -ENODEV;205}206207if (!cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM,208&feature_name)) {209pr_info("CPU feature '%s' is not supported.\n", feature_name);210return -ENODEV;211}212213if (boot_cpu_has(X86_FEATURE_GFNI)) {214aria_ops.aria_encrypt_16way = aria_aesni_avx_gfni_encrypt_16way;215aria_ops.aria_decrypt_16way = aria_aesni_avx_gfni_decrypt_16way;216aria_ops.aria_ctr_crypt_16way = aria_aesni_avx_gfni_ctr_crypt_16way;217aria_ops.aria_encrypt_32way = aria_aesni_avx2_gfni_encrypt_32way;218aria_ops.aria_decrypt_32way = aria_aesni_avx2_gfni_decrypt_32way;219aria_ops.aria_ctr_crypt_32way = aria_aesni_avx2_gfni_ctr_crypt_32way;220} else {221aria_ops.aria_encrypt_16way = aria_aesni_avx_encrypt_16way;222aria_ops.aria_decrypt_16way = aria_aesni_avx_decrypt_16way;223aria_ops.aria_ctr_crypt_16way = aria_aesni_avx_ctr_crypt_16way;224aria_ops.aria_encrypt_32way = aria_aesni_avx2_encrypt_32way;225aria_ops.aria_decrypt_32way = aria_aesni_avx2_decrypt_32way;226aria_ops.aria_ctr_crypt_32way = aria_aesni_avx2_ctr_crypt_32way;227}228229return crypto_register_skciphers(aria_algs, ARRAY_SIZE(aria_algs));230}231232static void __exit aria_avx2_exit(void)233{234crypto_unregister_skciphers(aria_algs, ARRAY_SIZE(aria_algs));235}236237module_init(aria_avx2_init);238module_exit(aria_avx2_exit);239240MODULE_LICENSE("GPL");241MODULE_AUTHOR("Taehee Yoo <[email protected]>");242MODULE_DESCRIPTION("ARIA Cipher Algorithm, AVX2/AES-NI/GFNI optimized");243MODULE_ALIAS_CRYPTO("aria");244MODULE_ALIAS_CRYPTO("aria-aesni-avx2");245246247