linux/arch/x86/crypto/twofish_avx_glue.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Glue Code for AVX assembler version of Twofish Cipher
   4 *
   5 * Copyright (C) 2012 Johannes Goetzfried
   6 *     <Johannes.Goetzfried@informatik.stud.uni-erlangen.de>
   7 *
   8 * Copyright © 2013 Jussi Kivilinna <jussi.kivilinna@iki.fi>
   9 */
  10
  11#include <linux/module.h>
  12#include <linux/types.h>
  13#include <linux/crypto.h>
  14#include <linux/err.h>
  15#include <crypto/algapi.h>
  16#include <crypto/internal/simd.h>
  17#include <crypto/twofish.h>
  18
  19#include "twofish.h"
  20#include "ecb_cbc_helpers.h"
  21
  22#define TWOFISH_PARALLEL_BLOCKS 8
  23
  24/* 8-way parallel cipher functions */
  25asmlinkage void twofish_ecb_enc_8way(const void *ctx, u8 *dst, const u8 *src);
  26asmlinkage void twofish_ecb_dec_8way(const void *ctx, u8 *dst, const u8 *src);
  27
  28asmlinkage void twofish_cbc_dec_8way(const void *ctx, u8 *dst, const u8 *src);
  29
  30static int twofish_setkey_skcipher(struct crypto_skcipher *tfm,
  31                                   const u8 *key, unsigned int keylen)
  32{
  33        return twofish_setkey(&tfm->base, key, keylen);
  34}
  35
  36static inline void twofish_enc_blk_3way(const void *ctx, u8 *dst, const u8 *src)
  37{
  38        __twofish_enc_blk_3way(ctx, dst, src, false);
  39}
  40
  41static int ecb_encrypt(struct skcipher_request *req)
  42{
  43        ECB_WALK_START(req, TF_BLOCK_SIZE, TWOFISH_PARALLEL_BLOCKS);
  44        ECB_BLOCK(TWOFISH_PARALLEL_BLOCKS, twofish_ecb_enc_8way);
  45        ECB_BLOCK(3, twofish_enc_blk_3way);
  46        ECB_BLOCK(1, twofish_enc_blk);
  47        ECB_WALK_END();
  48}
  49
  50static int ecb_decrypt(struct skcipher_request *req)
  51{
  52        ECB_WALK_START(req, TF_BLOCK_SIZE, TWOFISH_PARALLEL_BLOCKS);
  53        ECB_BLOCK(TWOFISH_PARALLEL_BLOCKS, twofish_ecb_dec_8way);
  54        ECB_BLOCK(3, twofish_dec_blk_3way);
  55        ECB_BLOCK(1, twofish_dec_blk);
  56        ECB_WALK_END();
  57}
  58
  59static int cbc_encrypt(struct skcipher_request *req)
  60{
  61        CBC_WALK_START(req, TF_BLOCK_SIZE, -1);
  62        CBC_ENC_BLOCK(twofish_enc_blk);
  63        CBC_WALK_END();
  64}
  65
  66static int cbc_decrypt(struct skcipher_request *req)
  67{
  68        CBC_WALK_START(req, TF_BLOCK_SIZE, TWOFISH_PARALLEL_BLOCKS);
  69        CBC_DEC_BLOCK(TWOFISH_PARALLEL_BLOCKS, twofish_cbc_dec_8way);
  70        CBC_DEC_BLOCK(3, twofish_dec_blk_cbc_3way);
  71        CBC_DEC_BLOCK(1, twofish_dec_blk);
  72        CBC_WALK_END();
  73}
  74
  75static struct skcipher_alg twofish_algs[] = {
  76        {
  77                .base.cra_name          = "__ecb(twofish)",
  78                .base.cra_driver_name   = "__ecb-twofish-avx",
  79                .base.cra_priority      = 400,
  80                .base.cra_flags         = CRYPTO_ALG_INTERNAL,
  81                .base.cra_blocksize     = TF_BLOCK_SIZE,
  82                .base.cra_ctxsize       = sizeof(struct twofish_ctx),
  83                .base.cra_module        = THIS_MODULE,
  84                .min_keysize            = TF_MIN_KEY_SIZE,
  85                .max_keysize            = TF_MAX_KEY_SIZE,
  86                .setkey                 = twofish_setkey_skcipher,
  87                .encrypt                = ecb_encrypt,
  88                .decrypt                = ecb_decrypt,
  89        }, {
  90                .base.cra_name          = "__cbc(twofish)",
  91                .base.cra_driver_name   = "__cbc-twofish-avx",
  92                .base.cra_priority      = 400,
  93                .base.cra_flags         = CRYPTO_ALG_INTERNAL,
  94                .base.cra_blocksize     = TF_BLOCK_SIZE,
  95                .base.cra_ctxsize       = sizeof(struct twofish_ctx),
  96                .base.cra_module        = THIS_MODULE,
  97                .min_keysize            = TF_MIN_KEY_SIZE,
  98                .max_keysize            = TF_MAX_KEY_SIZE,
  99                .ivsize                 = TF_BLOCK_SIZE,
 100                .setkey                 = twofish_setkey_skcipher,
 101                .encrypt                = cbc_encrypt,
 102                .decrypt                = cbc_decrypt,
 103        },
 104};
 105
 106static struct simd_skcipher_alg *twofish_simd_algs[ARRAY_SIZE(twofish_algs)];
 107
 108static int __init twofish_init(void)
 109{
 110        const char *feature_name;
 111
 112        if (!cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM, &feature_name)) {
 113                pr_info("CPU feature '%s' is not supported.\n", feature_name);
 114                return -ENODEV;
 115        }
 116
 117        return simd_register_skciphers_compat(twofish_algs,
 118                                              ARRAY_SIZE(twofish_algs),
 119                                              twofish_simd_algs);
 120}
 121
 122static void __exit twofish_exit(void)
 123{
 124        simd_unregister_skciphers(twofish_algs, ARRAY_SIZE(twofish_algs),
 125                                  twofish_simd_algs);
 126}
 127
 128module_init(twofish_init);
 129module_exit(twofish_exit);
 130
 131MODULE_DESCRIPTION("Twofish Cipher Algorithm, AVX optimized");
 132MODULE_LICENSE("GPL");
 133MODULE_ALIAS_CRYPTO("twofish");
 134