Path: blob/master/arch/x86/crypto/aria_aesni_avx_glue.c
54184 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);28asmlinkage void aria_aesni_avx_gfni_encrypt_16way(const void *ctx, u8 *dst,29const u8 *src);30EXPORT_SYMBOL_GPL(aria_aesni_avx_gfni_encrypt_16way);31asmlinkage void aria_aesni_avx_gfni_decrypt_16way(const void *ctx, u8 *dst,32const u8 *src);33EXPORT_SYMBOL_GPL(aria_aesni_avx_gfni_decrypt_16way);34asmlinkage void aria_aesni_avx_gfni_ctr_crypt_16way(const void *ctx, u8 *dst,35const u8 *src,36u8 *keystream, u8 *iv);37EXPORT_SYMBOL_GPL(aria_aesni_avx_gfni_ctr_crypt_16way);3839static struct aria_avx_ops aria_ops;4041struct aria_avx_request_ctx {42u8 keystream[ARIA_AESNI_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_PARALLEL_BLOCKS, aria_ops.aria_encrypt_16way);49ECB_BLOCK(1, aria_encrypt);50ECB_WALK_END();51}5253static int ecb_do_decrypt(struct skcipher_request *req, const u32 *rkey)54{55ECB_WALK_START(req, ARIA_BLOCK_SIZE, ARIA_AESNI_PARALLEL_BLOCKS);56ECB_BLOCK(ARIA_AESNI_PARALLEL_BLOCKS, aria_ops.aria_decrypt_16way);57ECB_BLOCK(1, aria_decrypt);58ECB_WALK_END();59}6061static int aria_avx_ecb_encrypt(struct skcipher_request *req)62{63struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);64struct aria_ctx *ctx = crypto_skcipher_ctx(tfm);6566return ecb_do_encrypt(req, ctx->enc_key[0]);67}6869static int aria_avx_ecb_decrypt(struct skcipher_request *req)70{71struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);72struct aria_ctx *ctx = crypto_skcipher_ctx(tfm);7374return ecb_do_decrypt(req, ctx->dec_key[0]);75}7677static int aria_avx_set_key(struct crypto_skcipher *tfm, const u8 *key,78unsigned int keylen)79{80return aria_set_key(&tfm->base, key, keylen);81}8283static int aria_avx_ctr_encrypt(struct skcipher_request *req)84{85struct aria_avx_request_ctx *req_ctx = skcipher_request_ctx(req);86struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);87struct aria_ctx *ctx = crypto_skcipher_ctx(tfm);88struct skcipher_walk walk;89unsigned int nbytes;90int err;9192err = skcipher_walk_virt(&walk, req, false);9394while ((nbytes = walk.nbytes) > 0) {95const u8 *src = walk.src.virt.addr;96u8 *dst = walk.dst.virt.addr;9798while (nbytes >= ARIA_AESNI_PARALLEL_BLOCK_SIZE) {99kernel_fpu_begin();100aria_ops.aria_ctr_crypt_16way(ctx, dst, src,101&req_ctx->keystream[0],102walk.iv);103kernel_fpu_end();104dst += ARIA_AESNI_PARALLEL_BLOCK_SIZE;105src += ARIA_AESNI_PARALLEL_BLOCK_SIZE;106nbytes -= ARIA_AESNI_PARALLEL_BLOCK_SIZE;107}108109while (nbytes >= ARIA_BLOCK_SIZE) {110memcpy(&req_ctx->keystream[0], walk.iv, ARIA_BLOCK_SIZE);111crypto_inc(walk.iv, ARIA_BLOCK_SIZE);112113aria_encrypt(ctx, &req_ctx->keystream[0],114&req_ctx->keystream[0]);115116crypto_xor_cpy(dst, src, &req_ctx->keystream[0],117ARIA_BLOCK_SIZE);118dst += ARIA_BLOCK_SIZE;119src += ARIA_BLOCK_SIZE;120nbytes -= ARIA_BLOCK_SIZE;121}122123if (walk.nbytes == walk.total && nbytes > 0) {124memcpy(&req_ctx->keystream[0], walk.iv,125ARIA_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],132nbytes);133dst += nbytes;134src += nbytes;135nbytes = 0;136}137err = skcipher_walk_done(&walk, nbytes);138}139140return err;141}142143static int aria_avx_init_tfm(struct crypto_skcipher *tfm)144{145crypto_skcipher_set_reqsize(tfm, sizeof(struct aria_avx_request_ctx));146147return 0;148}149150static struct skcipher_alg aria_algs[] = {151{152.base.cra_name = "ecb(aria)",153.base.cra_driver_name = "ecb-aria-avx",154.base.cra_priority = 400,155.base.cra_blocksize = ARIA_BLOCK_SIZE,156.base.cra_ctxsize = sizeof(struct aria_ctx),157.base.cra_module = THIS_MODULE,158.min_keysize = ARIA_MIN_KEY_SIZE,159.max_keysize = ARIA_MAX_KEY_SIZE,160.setkey = aria_avx_set_key,161.encrypt = aria_avx_ecb_encrypt,162.decrypt = aria_avx_ecb_decrypt,163}, {164.base.cra_name = "ctr(aria)",165.base.cra_driver_name = "ctr-aria-avx",166.base.cra_priority = 400,167.base.cra_blocksize = 1,168.base.cra_ctxsize = sizeof(struct aria_ctx),169.base.cra_module = THIS_MODULE,170.min_keysize = ARIA_MIN_KEY_SIZE,171.max_keysize = ARIA_MAX_KEY_SIZE,172.ivsize = ARIA_BLOCK_SIZE,173.chunksize = ARIA_BLOCK_SIZE,174.walksize = 16 * ARIA_BLOCK_SIZE,175.setkey = aria_avx_set_key,176.encrypt = aria_avx_ctr_encrypt,177.decrypt = aria_avx_ctr_encrypt,178.init = aria_avx_init_tfm,179}180};181182static int __init aria_avx_init(void)183{184const char *feature_name;185186if (!boot_cpu_has(X86_FEATURE_AVX) ||187!boot_cpu_has(X86_FEATURE_AES) ||188!boot_cpu_has(X86_FEATURE_OSXSAVE)) {189pr_info("AVX or AES-NI instructions are not detected.\n");190return -ENODEV;191}192193if (!cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM,194&feature_name)) {195pr_info("CPU feature '%s' is not supported.\n", feature_name);196return -ENODEV;197}198199if (boot_cpu_has(X86_FEATURE_GFNI)) {200aria_ops.aria_encrypt_16way = aria_aesni_avx_gfni_encrypt_16way;201aria_ops.aria_decrypt_16way = aria_aesni_avx_gfni_decrypt_16way;202aria_ops.aria_ctr_crypt_16way = aria_aesni_avx_gfni_ctr_crypt_16way;203} else {204aria_ops.aria_encrypt_16way = aria_aesni_avx_encrypt_16way;205aria_ops.aria_decrypt_16way = aria_aesni_avx_decrypt_16way;206aria_ops.aria_ctr_crypt_16way = aria_aesni_avx_ctr_crypt_16way;207}208209return crypto_register_skciphers(aria_algs, ARRAY_SIZE(aria_algs));210}211212static void __exit aria_avx_exit(void)213{214crypto_unregister_skciphers(aria_algs, ARRAY_SIZE(aria_algs));215}216217module_init(aria_avx_init);218module_exit(aria_avx_exit);219220MODULE_LICENSE("GPL");221MODULE_AUTHOR("Taehee Yoo <[email protected]>");222MODULE_DESCRIPTION("ARIA Cipher Algorithm, AVX/AES-NI/GFNI optimized");223MODULE_ALIAS_CRYPTO("aria");224MODULE_ALIAS_CRYPTO("aria-aesni-avx");225226227