Path: blob/master/arch/x86/crypto/aria_aesni_avx_glue.c
26424 views
/* SPDX-License-Identifier: GPL-2.0-or-later */1/*2* Glue Code for the AVX/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_avx_encrypt_16way(const void *ctx, u8 *dst,19const u8 *src);20EXPORT_SYMBOL_GPL(aria_aesni_avx_encrypt_16way);21asmlinkage void aria_aesni_avx_decrypt_16way(const void *ctx, u8 *dst,22const u8 *src);23EXPORT_SYMBOL_GPL(aria_aesni_avx_decrypt_16way);24asmlinkage void aria_aesni_avx_ctr_crypt_16way(const void *ctx, u8 *dst,25const u8 *src,26u8 *keystream, u8 *iv);27EXPORT_SYMBOL_GPL(aria_aesni_avx_ctr_crypt_16way);28#ifdef CONFIG_AS_GFNI29asmlinkage void aria_aesni_avx_gfni_encrypt_16way(const void *ctx, u8 *dst,30const u8 *src);31EXPORT_SYMBOL_GPL(aria_aesni_avx_gfni_encrypt_16way);32asmlinkage void aria_aesni_avx_gfni_decrypt_16way(const void *ctx, u8 *dst,33const u8 *src);34EXPORT_SYMBOL_GPL(aria_aesni_avx_gfni_decrypt_16way);35asmlinkage void aria_aesni_avx_gfni_ctr_crypt_16way(const void *ctx, u8 *dst,36const u8 *src,37u8 *keystream, u8 *iv);38EXPORT_SYMBOL_GPL(aria_aesni_avx_gfni_ctr_crypt_16way);39#endif /* CONFIG_AS_GFNI */4041static struct aria_avx_ops aria_ops;4243struct aria_avx_request_ctx {44u8 keystream[ARIA_AESNI_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_PARALLEL_BLOCKS, aria_ops.aria_encrypt_16way);51ECB_BLOCK(1, aria_encrypt);52ECB_WALK_END();53}5455static int ecb_do_decrypt(struct skcipher_request *req, const u32 *rkey)56{57ECB_WALK_START(req, ARIA_BLOCK_SIZE, ARIA_AESNI_PARALLEL_BLOCKS);58ECB_BLOCK(ARIA_AESNI_PARALLEL_BLOCKS, aria_ops.aria_decrypt_16way);59ECB_BLOCK(1, aria_decrypt);60ECB_WALK_END();61}6263static int aria_avx_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_avx_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_avx_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_avx_ctr_encrypt(struct skcipher_request *req)86{87struct aria_avx_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_PARALLEL_BLOCK_SIZE) {101kernel_fpu_begin();102aria_ops.aria_ctr_crypt_16way(ctx, dst, src,103&req_ctx->keystream[0],104walk.iv);105kernel_fpu_end();106dst += ARIA_AESNI_PARALLEL_BLOCK_SIZE;107src += ARIA_AESNI_PARALLEL_BLOCK_SIZE;108nbytes -= ARIA_AESNI_PARALLEL_BLOCK_SIZE;109}110111while (nbytes >= ARIA_BLOCK_SIZE) {112memcpy(&req_ctx->keystream[0], walk.iv, ARIA_BLOCK_SIZE);113crypto_inc(walk.iv, ARIA_BLOCK_SIZE);114115aria_encrypt(ctx, &req_ctx->keystream[0],116&req_ctx->keystream[0]);117118crypto_xor_cpy(dst, src, &req_ctx->keystream[0],119ARIA_BLOCK_SIZE);120dst += ARIA_BLOCK_SIZE;121src += ARIA_BLOCK_SIZE;122nbytes -= ARIA_BLOCK_SIZE;123}124125if (walk.nbytes == walk.total && nbytes > 0) {126memcpy(&req_ctx->keystream[0], walk.iv,127ARIA_BLOCK_SIZE);128crypto_inc(walk.iv, ARIA_BLOCK_SIZE);129130aria_encrypt(ctx, &req_ctx->keystream[0],131&req_ctx->keystream[0]);132133crypto_xor_cpy(dst, src, &req_ctx->keystream[0],134nbytes);135dst += nbytes;136src += nbytes;137nbytes = 0;138}139err = skcipher_walk_done(&walk, nbytes);140}141142return err;143}144145static int aria_avx_init_tfm(struct crypto_skcipher *tfm)146{147crypto_skcipher_set_reqsize(tfm, sizeof(struct aria_avx_request_ctx));148149return 0;150}151152static struct skcipher_alg aria_algs[] = {153{154.base.cra_name = "ecb(aria)",155.base.cra_driver_name = "ecb-aria-avx",156.base.cra_priority = 400,157.base.cra_blocksize = ARIA_BLOCK_SIZE,158.base.cra_ctxsize = sizeof(struct aria_ctx),159.base.cra_module = THIS_MODULE,160.min_keysize = ARIA_MIN_KEY_SIZE,161.max_keysize = ARIA_MAX_KEY_SIZE,162.setkey = aria_avx_set_key,163.encrypt = aria_avx_ecb_encrypt,164.decrypt = aria_avx_ecb_decrypt,165}, {166.base.cra_name = "ctr(aria)",167.base.cra_driver_name = "ctr-aria-avx",168.base.cra_priority = 400,169.base.cra_blocksize = 1,170.base.cra_ctxsize = sizeof(struct aria_ctx),171.base.cra_module = THIS_MODULE,172.min_keysize = ARIA_MIN_KEY_SIZE,173.max_keysize = ARIA_MAX_KEY_SIZE,174.ivsize = ARIA_BLOCK_SIZE,175.chunksize = ARIA_BLOCK_SIZE,176.walksize = 16 * ARIA_BLOCK_SIZE,177.setkey = aria_avx_set_key,178.encrypt = aria_avx_ctr_encrypt,179.decrypt = aria_avx_ctr_encrypt,180.init = aria_avx_init_tfm,181}182};183184static int __init aria_avx_init(void)185{186const char *feature_name;187188if (!boot_cpu_has(X86_FEATURE_AVX) ||189!boot_cpu_has(X86_FEATURE_AES) ||190!boot_cpu_has(X86_FEATURE_OSXSAVE)) {191pr_info("AVX or AES-NI instructions are not detected.\n");192return -ENODEV;193}194195if (!cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM,196&feature_name)) {197pr_info("CPU feature '%s' is not supported.\n", feature_name);198return -ENODEV;199}200201if (boot_cpu_has(X86_FEATURE_GFNI) && IS_ENABLED(CONFIG_AS_GFNI)) {202aria_ops.aria_encrypt_16way = aria_aesni_avx_gfni_encrypt_16way;203aria_ops.aria_decrypt_16way = aria_aesni_avx_gfni_decrypt_16way;204aria_ops.aria_ctr_crypt_16way = aria_aesni_avx_gfni_ctr_crypt_16way;205} else {206aria_ops.aria_encrypt_16way = aria_aesni_avx_encrypt_16way;207aria_ops.aria_decrypt_16way = aria_aesni_avx_decrypt_16way;208aria_ops.aria_ctr_crypt_16way = aria_aesni_avx_ctr_crypt_16way;209}210211return crypto_register_skciphers(aria_algs, ARRAY_SIZE(aria_algs));212}213214static void __exit aria_avx_exit(void)215{216crypto_unregister_skciphers(aria_algs, ARRAY_SIZE(aria_algs));217}218219module_init(aria_avx_init);220module_exit(aria_avx_exit);221222MODULE_LICENSE("GPL");223MODULE_AUTHOR("Taehee Yoo <[email protected]>");224MODULE_DESCRIPTION("ARIA Cipher Algorithm, AVX/AES-NI/GFNI optimized");225MODULE_ALIAS_CRYPTO("aria");226MODULE_ALIAS_CRYPTO("aria-aesni-avx");227228229