Path: blob/master/arch/x86/crypto/aria_gfni_avx512_glue.c
26439 views
/* SPDX-License-Identifier: GPL-2.0-or-later */1/*2* Glue Code for the AVX512/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/module.h>12#include <linux/types.h>1314#include "ecb_cbc_helpers.h"15#include "aria-avx.h"1617asmlinkage void aria_gfni_avx512_encrypt_64way(const void *ctx, u8 *dst,18const u8 *src);19asmlinkage void aria_gfni_avx512_decrypt_64way(const void *ctx, u8 *dst,20const u8 *src);21asmlinkage void aria_gfni_avx512_ctr_crypt_64way(const void *ctx, u8 *dst,22const u8 *src,23u8 *keystream, u8 *iv);2425static struct aria_avx_ops aria_ops;2627struct aria_avx512_request_ctx {28u8 keystream[ARIA_GFNI_AVX512_PARALLEL_BLOCK_SIZE];29};3031static int ecb_do_encrypt(struct skcipher_request *req, const u32 *rkey)32{33ECB_WALK_START(req, ARIA_BLOCK_SIZE, ARIA_AESNI_PARALLEL_BLOCKS);34ECB_BLOCK(ARIA_GFNI_AVX512_PARALLEL_BLOCKS, aria_ops.aria_encrypt_64way);35ECB_BLOCK(ARIA_AESNI_AVX2_PARALLEL_BLOCKS, aria_ops.aria_encrypt_32way);36ECB_BLOCK(ARIA_AESNI_PARALLEL_BLOCKS, aria_ops.aria_encrypt_16way);37ECB_BLOCK(1, aria_encrypt);38ECB_WALK_END();39}4041static int ecb_do_decrypt(struct skcipher_request *req, const u32 *rkey)42{43ECB_WALK_START(req, ARIA_BLOCK_SIZE, ARIA_AESNI_PARALLEL_BLOCKS);44ECB_BLOCK(ARIA_GFNI_AVX512_PARALLEL_BLOCKS, aria_ops.aria_decrypt_64way);45ECB_BLOCK(ARIA_AESNI_AVX2_PARALLEL_BLOCKS, aria_ops.aria_decrypt_32way);46ECB_BLOCK(ARIA_AESNI_PARALLEL_BLOCKS, aria_ops.aria_decrypt_16way);47ECB_BLOCK(1, aria_decrypt);48ECB_WALK_END();49}5051static int aria_avx512_ecb_encrypt(struct skcipher_request *req)52{53struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);54struct aria_ctx *ctx = crypto_skcipher_ctx(tfm);5556return ecb_do_encrypt(req, ctx->enc_key[0]);57}5859static int aria_avx512_ecb_decrypt(struct skcipher_request *req)60{61struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);62struct aria_ctx *ctx = crypto_skcipher_ctx(tfm);6364return ecb_do_decrypt(req, ctx->dec_key[0]);65}6667static int aria_avx512_set_key(struct crypto_skcipher *tfm, const u8 *key,68unsigned int keylen)69{70return aria_set_key(&tfm->base, key, keylen);71}7273static int aria_avx512_ctr_encrypt(struct skcipher_request *req)74{75struct aria_avx512_request_ctx *req_ctx = skcipher_request_ctx(req);76struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);77struct aria_ctx *ctx = crypto_skcipher_ctx(tfm);78struct skcipher_walk walk;79unsigned int nbytes;80int err;8182err = skcipher_walk_virt(&walk, req, false);8384while ((nbytes = walk.nbytes) > 0) {85const u8 *src = walk.src.virt.addr;86u8 *dst = walk.dst.virt.addr;8788while (nbytes >= ARIA_GFNI_AVX512_PARALLEL_BLOCK_SIZE) {89kernel_fpu_begin();90aria_ops.aria_ctr_crypt_64way(ctx, dst, src,91&req_ctx->keystream[0],92walk.iv);93kernel_fpu_end();94dst += ARIA_GFNI_AVX512_PARALLEL_BLOCK_SIZE;95src += ARIA_GFNI_AVX512_PARALLEL_BLOCK_SIZE;96nbytes -= ARIA_GFNI_AVX512_PARALLEL_BLOCK_SIZE;97}9899while (nbytes >= ARIA_AESNI_AVX2_PARALLEL_BLOCK_SIZE) {100kernel_fpu_begin();101aria_ops.aria_ctr_crypt_32way(ctx, dst, src,102&req_ctx->keystream[0],103walk.iv);104kernel_fpu_end();105dst += ARIA_AESNI_AVX2_PARALLEL_BLOCK_SIZE;106src += ARIA_AESNI_AVX2_PARALLEL_BLOCK_SIZE;107nbytes -= ARIA_AESNI_AVX2_PARALLEL_BLOCK_SIZE;108}109110while (nbytes >= ARIA_AESNI_PARALLEL_BLOCK_SIZE) {111kernel_fpu_begin();112aria_ops.aria_ctr_crypt_16way(ctx, dst, src,113&req_ctx->keystream[0],114walk.iv);115kernel_fpu_end();116dst += ARIA_AESNI_PARALLEL_BLOCK_SIZE;117src += ARIA_AESNI_PARALLEL_BLOCK_SIZE;118nbytes -= ARIA_AESNI_PARALLEL_BLOCK_SIZE;119}120121while (nbytes >= ARIA_BLOCK_SIZE) {122memcpy(&req_ctx->keystream[0], walk.iv,123ARIA_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_avx512_init_tfm(struct crypto_skcipher *tfm)157{158crypto_skcipher_set_reqsize(tfm,159sizeof(struct aria_avx512_request_ctx));160161return 0;162}163164static struct skcipher_alg aria_algs[] = {165{166.base.cra_name = "ecb(aria)",167.base.cra_driver_name = "ecb-aria-avx512",168.base.cra_priority = 600,169.base.cra_blocksize = ARIA_BLOCK_SIZE,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.setkey = aria_avx512_set_key,175.encrypt = aria_avx512_ecb_encrypt,176.decrypt = aria_avx512_ecb_decrypt,177}, {178.base.cra_name = "ctr(aria)",179.base.cra_driver_name = "ctr-aria-avx512",180.base.cra_priority = 600,181.base.cra_flags = CRYPTO_ALG_SKCIPHER_REQSIZE_LARGE,182.base.cra_blocksize = 1,183.base.cra_ctxsize = sizeof(struct aria_ctx),184.base.cra_module = THIS_MODULE,185.min_keysize = ARIA_MIN_KEY_SIZE,186.max_keysize = ARIA_MAX_KEY_SIZE,187.ivsize = ARIA_BLOCK_SIZE,188.chunksize = ARIA_BLOCK_SIZE,189.setkey = aria_avx512_set_key,190.encrypt = aria_avx512_ctr_encrypt,191.decrypt = aria_avx512_ctr_encrypt,192.init = aria_avx512_init_tfm,193}194};195196static int __init aria_avx512_init(void)197{198const char *feature_name;199200if (!boot_cpu_has(X86_FEATURE_AVX) ||201!boot_cpu_has(X86_FEATURE_AVX2) ||202!boot_cpu_has(X86_FEATURE_AVX512F) ||203!boot_cpu_has(X86_FEATURE_AVX512VL) ||204!boot_cpu_has(X86_FEATURE_GFNI) ||205!boot_cpu_has(X86_FEATURE_OSXSAVE)) {206pr_info("AVX512/GFNI instructions are not detected.\n");207return -ENODEV;208}209210if (!cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM |211XFEATURE_MASK_AVX512, &feature_name)) {212pr_info("CPU feature '%s' is not supported.\n", feature_name);213return -ENODEV;214}215216aria_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;222aria_ops.aria_encrypt_64way = aria_gfni_avx512_encrypt_64way;223aria_ops.aria_decrypt_64way = aria_gfni_avx512_decrypt_64way;224aria_ops.aria_ctr_crypt_64way = aria_gfni_avx512_ctr_crypt_64way;225226return crypto_register_skciphers(aria_algs, ARRAY_SIZE(aria_algs));227}228229static void __exit aria_avx512_exit(void)230{231crypto_unregister_skciphers(aria_algs, ARRAY_SIZE(aria_algs));232}233234module_init(aria_avx512_init);235module_exit(aria_avx512_exit);236237MODULE_LICENSE("GPL");238MODULE_AUTHOR("Taehee Yoo <[email protected]>");239MODULE_DESCRIPTION("ARIA Cipher Algorithm, AVX512/GFNI optimized");240MODULE_ALIAS_CRYPTO("aria");241MODULE_ALIAS_CRYPTO("aria-gfni-avx512");242243244