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#include <crypto/xts.h>
  19#include <asm/crypto/glue_helper.h>
  20#include <asm/crypto/twofish.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);
  29asmlinkage void twofish_ctr_8way(const void *ctx, u8 *dst, const u8 *src,
  30                                 le128 *iv);
  31
  32asmlinkage void twofish_xts_enc_8way(const void *ctx, u8 *dst, const u8 *src,
  33                                     le128 *iv);
  34asmlinkage void twofish_xts_dec_8way(const void *ctx, u8 *dst, const u8 *src,
  35                                     le128 *iv);
  36
  37static int twofish_setkey_skcipher(struct crypto_skcipher *tfm,
  38                                   const u8 *key, unsigned int keylen)
  39{
  40        return twofish_setkey(&tfm->base, key, keylen);
  41}
  42
  43static inline void twofish_enc_blk_3way(const void *ctx, u8 *dst, const u8 *src)
  44{
  45        __twofish_enc_blk_3way(ctx, dst, src, false);
  46}
  47
  48static void twofish_xts_enc(const void *ctx, u8 *dst, const u8 *src, le128 *iv)
  49{
  50        glue_xts_crypt_128bit_one(ctx, dst, src, iv, twofish_enc_blk);
  51}
  52
  53static void twofish_xts_dec(const void *ctx, u8 *dst, const u8 *src, le128 *iv)
  54{
  55        glue_xts_crypt_128bit_one(ctx, dst, src, iv, twofish_dec_blk);
  56}
  57
  58struct twofish_xts_ctx {
  59        struct twofish_ctx tweak_ctx;
  60        struct twofish_ctx crypt_ctx;
  61};
  62
  63static int xts_twofish_setkey(struct crypto_skcipher *tfm, const u8 *key,
  64                              unsigned int keylen)
  65{
  66        struct twofish_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
  67        int err;
  68
  69        err = xts_verify_key(tfm, key, keylen);
  70        if (err)
  71                return err;
  72
  73        /* first half of xts-key is for crypt */
  74        err = __twofish_setkey(&ctx->crypt_ctx, key, keylen / 2);
  75        if (err)
  76                return err;
  77
  78        /* second half of xts-key is for tweak */
  79        return __twofish_setkey(&ctx->tweak_ctx, key + keylen / 2, keylen / 2);
  80}
  81
  82static const struct common_glue_ctx twofish_enc = {
  83        .num_funcs = 3,
  84        .fpu_blocks_limit = TWOFISH_PARALLEL_BLOCKS,
  85
  86        .funcs = { {
  87                .num_blocks = TWOFISH_PARALLEL_BLOCKS,
  88                .fn_u = { .ecb = twofish_ecb_enc_8way }
  89        }, {
  90                .num_blocks = 3,
  91                .fn_u = { .ecb = twofish_enc_blk_3way }
  92        }, {
  93                .num_blocks = 1,
  94                .fn_u = { .ecb = twofish_enc_blk }
  95        } }
  96};
  97
  98static const struct common_glue_ctx twofish_ctr = {
  99        .num_funcs = 3,
 100        .fpu_blocks_limit = TWOFISH_PARALLEL_BLOCKS,
 101
 102        .funcs = { {
 103                .num_blocks = TWOFISH_PARALLEL_BLOCKS,
 104                .fn_u = { .ctr = twofish_ctr_8way }
 105        }, {
 106                .num_blocks = 3,
 107                .fn_u = { .ctr = twofish_enc_blk_ctr_3way }
 108        }, {
 109                .num_blocks = 1,
 110                .fn_u = { .ctr = twofish_enc_blk_ctr }
 111        } }
 112};
 113
 114static const struct common_glue_ctx twofish_enc_xts = {
 115        .num_funcs = 2,
 116        .fpu_blocks_limit = TWOFISH_PARALLEL_BLOCKS,
 117
 118        .funcs = { {
 119                .num_blocks = TWOFISH_PARALLEL_BLOCKS,
 120                .fn_u = { .xts = twofish_xts_enc_8way }
 121        }, {
 122                .num_blocks = 1,
 123                .fn_u = { .xts = twofish_xts_enc }
 124        } }
 125};
 126
 127static const struct common_glue_ctx twofish_dec = {
 128        .num_funcs = 3,
 129        .fpu_blocks_limit = TWOFISH_PARALLEL_BLOCKS,
 130
 131        .funcs = { {
 132                .num_blocks = TWOFISH_PARALLEL_BLOCKS,
 133                .fn_u = { .ecb = twofish_ecb_dec_8way }
 134        }, {
 135                .num_blocks = 3,
 136                .fn_u = { .ecb = twofish_dec_blk_3way }
 137        }, {
 138                .num_blocks = 1,
 139                .fn_u = { .ecb = twofish_dec_blk }
 140        } }
 141};
 142
 143static const struct common_glue_ctx twofish_dec_cbc = {
 144        .num_funcs = 3,
 145        .fpu_blocks_limit = TWOFISH_PARALLEL_BLOCKS,
 146
 147        .funcs = { {
 148                .num_blocks = TWOFISH_PARALLEL_BLOCKS,
 149                .fn_u = { .cbc = twofish_cbc_dec_8way }
 150        }, {
 151                .num_blocks = 3,
 152                .fn_u = { .cbc = twofish_dec_blk_cbc_3way }
 153        }, {
 154                .num_blocks = 1,
 155                .fn_u = { .cbc = twofish_dec_blk }
 156        } }
 157};
 158
 159static const struct common_glue_ctx twofish_dec_xts = {
 160        .num_funcs = 2,
 161        .fpu_blocks_limit = TWOFISH_PARALLEL_BLOCKS,
 162
 163        .funcs = { {
 164                .num_blocks = TWOFISH_PARALLEL_BLOCKS,
 165                .fn_u = { .xts = twofish_xts_dec_8way }
 166        }, {
 167                .num_blocks = 1,
 168                .fn_u = { .xts = twofish_xts_dec }
 169        } }
 170};
 171
 172static int ecb_encrypt(struct skcipher_request *req)
 173{
 174        return glue_ecb_req_128bit(&twofish_enc, req);
 175}
 176
 177static int ecb_decrypt(struct skcipher_request *req)
 178{
 179        return glue_ecb_req_128bit(&twofish_dec, req);
 180}
 181
 182static int cbc_encrypt(struct skcipher_request *req)
 183{
 184        return glue_cbc_encrypt_req_128bit(twofish_enc_blk, req);
 185}
 186
 187static int cbc_decrypt(struct skcipher_request *req)
 188{
 189        return glue_cbc_decrypt_req_128bit(&twofish_dec_cbc, req);
 190}
 191
 192static int ctr_crypt(struct skcipher_request *req)
 193{
 194        return glue_ctr_req_128bit(&twofish_ctr, req);
 195}
 196
 197static int xts_encrypt(struct skcipher_request *req)
 198{
 199        struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
 200        struct twofish_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
 201
 202        return glue_xts_req_128bit(&twofish_enc_xts, req, twofish_enc_blk,
 203                                   &ctx->tweak_ctx, &ctx->crypt_ctx, false);
 204}
 205
 206static int xts_decrypt(struct skcipher_request *req)
 207{
 208        struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
 209        struct twofish_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
 210
 211        return glue_xts_req_128bit(&twofish_dec_xts, req, twofish_enc_blk,
 212                                   &ctx->tweak_ctx, &ctx->crypt_ctx, true);
 213}
 214
 215static struct skcipher_alg twofish_algs[] = {
 216        {
 217                .base.cra_name          = "__ecb(twofish)",
 218                .base.cra_driver_name   = "__ecb-twofish-avx",
 219                .base.cra_priority      = 400,
 220                .base.cra_flags         = CRYPTO_ALG_INTERNAL,
 221                .base.cra_blocksize     = TF_BLOCK_SIZE,
 222                .base.cra_ctxsize       = sizeof(struct twofish_ctx),
 223                .base.cra_module        = THIS_MODULE,
 224                .min_keysize            = TF_MIN_KEY_SIZE,
 225                .max_keysize            = TF_MAX_KEY_SIZE,
 226                .setkey                 = twofish_setkey_skcipher,
 227                .encrypt                = ecb_encrypt,
 228                .decrypt                = ecb_decrypt,
 229        }, {
 230                .base.cra_name          = "__cbc(twofish)",
 231                .base.cra_driver_name   = "__cbc-twofish-avx",
 232                .base.cra_priority      = 400,
 233                .base.cra_flags         = CRYPTO_ALG_INTERNAL,
 234                .base.cra_blocksize     = TF_BLOCK_SIZE,
 235                .base.cra_ctxsize       = sizeof(struct twofish_ctx),
 236                .base.cra_module        = THIS_MODULE,
 237                .min_keysize            = TF_MIN_KEY_SIZE,
 238                .max_keysize            = TF_MAX_KEY_SIZE,
 239                .ivsize                 = TF_BLOCK_SIZE,
 240                .setkey                 = twofish_setkey_skcipher,
 241                .encrypt                = cbc_encrypt,
 242                .decrypt                = cbc_decrypt,
 243        }, {
 244                .base.cra_name          = "__ctr(twofish)",
 245                .base.cra_driver_name   = "__ctr-twofish-avx",
 246                .base.cra_priority      = 400,
 247                .base.cra_flags         = CRYPTO_ALG_INTERNAL,
 248                .base.cra_blocksize     = 1,
 249                .base.cra_ctxsize       = sizeof(struct twofish_ctx),
 250                .base.cra_module        = THIS_MODULE,
 251                .min_keysize            = TF_MIN_KEY_SIZE,
 252                .max_keysize            = TF_MAX_KEY_SIZE,
 253                .ivsize                 = TF_BLOCK_SIZE,
 254                .chunksize              = TF_BLOCK_SIZE,
 255                .setkey                 = twofish_setkey_skcipher,
 256                .encrypt                = ctr_crypt,
 257                .decrypt                = ctr_crypt,
 258        }, {
 259                .base.cra_name          = "__xts(twofish)",
 260                .base.cra_driver_name   = "__xts-twofish-avx",
 261                .base.cra_priority      = 400,
 262                .base.cra_flags         = CRYPTO_ALG_INTERNAL,
 263                .base.cra_blocksize     = TF_BLOCK_SIZE,
 264                .base.cra_ctxsize       = sizeof(struct twofish_xts_ctx),
 265                .base.cra_module        = THIS_MODULE,
 266                .min_keysize            = 2 * TF_MIN_KEY_SIZE,
 267                .max_keysize            = 2 * TF_MAX_KEY_SIZE,
 268                .ivsize                 = TF_BLOCK_SIZE,
 269                .setkey                 = xts_twofish_setkey,
 270                .encrypt                = xts_encrypt,
 271                .decrypt                = xts_decrypt,
 272        },
 273};
 274
 275static struct simd_skcipher_alg *twofish_simd_algs[ARRAY_SIZE(twofish_algs)];
 276
 277static int __init twofish_init(void)
 278{
 279        const char *feature_name;
 280
 281        if (!cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM, &feature_name)) {
 282                pr_info("CPU feature '%s' is not supported.\n", feature_name);
 283                return -ENODEV;
 284        }
 285
 286        return simd_register_skciphers_compat(twofish_algs,
 287                                              ARRAY_SIZE(twofish_algs),
 288                                              twofish_simd_algs);
 289}
 290
 291static void __exit twofish_exit(void)
 292{
 293        simd_unregister_skciphers(twofish_algs, ARRAY_SIZE(twofish_algs),
 294                                  twofish_simd_algs);
 295}
 296
 297module_init(twofish_init);
 298module_exit(twofish_exit);
 299
 300MODULE_DESCRIPTION("Twofish Cipher Algorithm, AVX optimized");
 301MODULE_LICENSE("GPL");
 302MODULE_ALIAS_CRYPTO("twofish");
 303