linux/arch/x86/crypto/des3_ede_glue.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Glue Code for assembler optimized version of 3DES
   4 *
   5 * Copyright © 2014 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
   6 *
   7 * CBC & ECB parts based on code (crypto/cbc.c,ecb.c) by:
   8 *   Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
   9 * CTR part based on code (crypto/ctr.c) by:
  10 *   (C) Copyright IBM Corp. 2007 - Joy Latten <latten@us.ibm.com>
  11 */
  12
  13#include <crypto/algapi.h>
  14#include <crypto/des.h>
  15#include <crypto/internal/skcipher.h>
  16#include <linux/crypto.h>
  17#include <linux/init.h>
  18#include <linux/module.h>
  19#include <linux/types.h>
  20
  21struct des3_ede_x86_ctx {
  22        struct des3_ede_ctx enc;
  23        struct des3_ede_ctx dec;
  24};
  25
  26/* regular block cipher functions */
  27asmlinkage void des3_ede_x86_64_crypt_blk(const u32 *expkey, u8 *dst,
  28                                          const u8 *src);
  29
  30/* 3-way parallel cipher functions */
  31asmlinkage void des3_ede_x86_64_crypt_blk_3way(const u32 *expkey, u8 *dst,
  32                                               const u8 *src);
  33
  34static inline void des3_ede_enc_blk(struct des3_ede_x86_ctx *ctx, u8 *dst,
  35                                    const u8 *src)
  36{
  37        u32 *enc_ctx = ctx->enc.expkey;
  38
  39        des3_ede_x86_64_crypt_blk(enc_ctx, dst, src);
  40}
  41
  42static inline void des3_ede_dec_blk(struct des3_ede_x86_ctx *ctx, u8 *dst,
  43                                    const u8 *src)
  44{
  45        u32 *dec_ctx = ctx->dec.expkey;
  46
  47        des3_ede_x86_64_crypt_blk(dec_ctx, dst, src);
  48}
  49
  50static inline void des3_ede_enc_blk_3way(struct des3_ede_x86_ctx *ctx, u8 *dst,
  51                                         const u8 *src)
  52{
  53        u32 *enc_ctx = ctx->enc.expkey;
  54
  55        des3_ede_x86_64_crypt_blk_3way(enc_ctx, dst, src);
  56}
  57
  58static inline void des3_ede_dec_blk_3way(struct des3_ede_x86_ctx *ctx, u8 *dst,
  59                                         const u8 *src)
  60{
  61        u32 *dec_ctx = ctx->dec.expkey;
  62
  63        des3_ede_x86_64_crypt_blk_3way(dec_ctx, dst, src);
  64}
  65
  66static void des3_ede_x86_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
  67{
  68        des3_ede_enc_blk(crypto_tfm_ctx(tfm), dst, src);
  69}
  70
  71static void des3_ede_x86_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
  72{
  73        des3_ede_dec_blk(crypto_tfm_ctx(tfm), dst, src);
  74}
  75
  76static int ecb_crypt(struct skcipher_request *req, const u32 *expkey)
  77{
  78        const unsigned int bsize = DES3_EDE_BLOCK_SIZE;
  79        struct skcipher_walk walk;
  80        unsigned int nbytes;
  81        int err;
  82
  83        err = skcipher_walk_virt(&walk, req, false);
  84
  85        while ((nbytes = walk.nbytes)) {
  86                u8 *wsrc = walk.src.virt.addr;
  87                u8 *wdst = walk.dst.virt.addr;
  88
  89                /* Process four block batch */
  90                if (nbytes >= bsize * 3) {
  91                        do {
  92                                des3_ede_x86_64_crypt_blk_3way(expkey, wdst,
  93                                                               wsrc);
  94
  95                                wsrc += bsize * 3;
  96                                wdst += bsize * 3;
  97                                nbytes -= bsize * 3;
  98                        } while (nbytes >= bsize * 3);
  99
 100                        if (nbytes < bsize)
 101                                goto done;
 102                }
 103
 104                /* Handle leftovers */
 105                do {
 106                        des3_ede_x86_64_crypt_blk(expkey, wdst, wsrc);
 107
 108                        wsrc += bsize;
 109                        wdst += bsize;
 110                        nbytes -= bsize;
 111                } while (nbytes >= bsize);
 112
 113done:
 114                err = skcipher_walk_done(&walk, nbytes);
 115        }
 116
 117        return err;
 118}
 119
 120static int ecb_encrypt(struct skcipher_request *req)
 121{
 122        struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
 123        struct des3_ede_x86_ctx *ctx = crypto_skcipher_ctx(tfm);
 124
 125        return ecb_crypt(req, ctx->enc.expkey);
 126}
 127
 128static int ecb_decrypt(struct skcipher_request *req)
 129{
 130        struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
 131        struct des3_ede_x86_ctx *ctx = crypto_skcipher_ctx(tfm);
 132
 133        return ecb_crypt(req, ctx->dec.expkey);
 134}
 135
 136static unsigned int __cbc_encrypt(struct des3_ede_x86_ctx *ctx,
 137                                  struct skcipher_walk *walk)
 138{
 139        unsigned int bsize = DES3_EDE_BLOCK_SIZE;
 140        unsigned int nbytes = walk->nbytes;
 141        u64 *src = (u64 *)walk->src.virt.addr;
 142        u64 *dst = (u64 *)walk->dst.virt.addr;
 143        u64 *iv = (u64 *)walk->iv;
 144
 145        do {
 146                *dst = *src ^ *iv;
 147                des3_ede_enc_blk(ctx, (u8 *)dst, (u8 *)dst);
 148                iv = dst;
 149
 150                src += 1;
 151                dst += 1;
 152                nbytes -= bsize;
 153        } while (nbytes >= bsize);
 154
 155        *(u64 *)walk->iv = *iv;
 156        return nbytes;
 157}
 158
 159static int cbc_encrypt(struct skcipher_request *req)
 160{
 161        struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
 162        struct des3_ede_x86_ctx *ctx = crypto_skcipher_ctx(tfm);
 163        struct skcipher_walk walk;
 164        unsigned int nbytes;
 165        int err;
 166
 167        err = skcipher_walk_virt(&walk, req, false);
 168
 169        while ((nbytes = walk.nbytes)) {
 170                nbytes = __cbc_encrypt(ctx, &walk);
 171                err = skcipher_walk_done(&walk, nbytes);
 172        }
 173
 174        return err;
 175}
 176
 177static unsigned int __cbc_decrypt(struct des3_ede_x86_ctx *ctx,
 178                                  struct skcipher_walk *walk)
 179{
 180        unsigned int bsize = DES3_EDE_BLOCK_SIZE;
 181        unsigned int nbytes = walk->nbytes;
 182        u64 *src = (u64 *)walk->src.virt.addr;
 183        u64 *dst = (u64 *)walk->dst.virt.addr;
 184        u64 ivs[3 - 1];
 185        u64 last_iv;
 186
 187        /* Start of the last block. */
 188        src += nbytes / bsize - 1;
 189        dst += nbytes / bsize - 1;
 190
 191        last_iv = *src;
 192
 193        /* Process four block batch */
 194        if (nbytes >= bsize * 3) {
 195                do {
 196                        nbytes -= bsize * 3 - bsize;
 197                        src -= 3 - 1;
 198                        dst -= 3 - 1;
 199
 200                        ivs[0] = src[0];
 201                        ivs[1] = src[1];
 202
 203                        des3_ede_dec_blk_3way(ctx, (u8 *)dst, (u8 *)src);
 204
 205                        dst[1] ^= ivs[0];
 206                        dst[2] ^= ivs[1];
 207
 208                        nbytes -= bsize;
 209                        if (nbytes < bsize)
 210                                goto done;
 211
 212                        *dst ^= *(src - 1);
 213                        src -= 1;
 214                        dst -= 1;
 215                } while (nbytes >= bsize * 3);
 216        }
 217
 218        /* Handle leftovers */
 219        for (;;) {
 220                des3_ede_dec_blk(ctx, (u8 *)dst, (u8 *)src);
 221
 222                nbytes -= bsize;
 223                if (nbytes < bsize)
 224                        break;
 225
 226                *dst ^= *(src - 1);
 227                src -= 1;
 228                dst -= 1;
 229        }
 230
 231done:
 232        *dst ^= *(u64 *)walk->iv;
 233        *(u64 *)walk->iv = last_iv;
 234
 235        return nbytes;
 236}
 237
 238static int cbc_decrypt(struct skcipher_request *req)
 239{
 240        struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
 241        struct des3_ede_x86_ctx *ctx = crypto_skcipher_ctx(tfm);
 242        struct skcipher_walk walk;
 243        unsigned int nbytes;
 244        int err;
 245
 246        err = skcipher_walk_virt(&walk, req, false);
 247
 248        while ((nbytes = walk.nbytes)) {
 249                nbytes = __cbc_decrypt(ctx, &walk);
 250                err = skcipher_walk_done(&walk, nbytes);
 251        }
 252
 253        return err;
 254}
 255
 256static void ctr_crypt_final(struct des3_ede_x86_ctx *ctx,
 257                            struct skcipher_walk *walk)
 258{
 259        u8 *ctrblk = walk->iv;
 260        u8 keystream[DES3_EDE_BLOCK_SIZE];
 261        u8 *src = walk->src.virt.addr;
 262        u8 *dst = walk->dst.virt.addr;
 263        unsigned int nbytes = walk->nbytes;
 264
 265        des3_ede_enc_blk(ctx, keystream, ctrblk);
 266        crypto_xor_cpy(dst, keystream, src, nbytes);
 267
 268        crypto_inc(ctrblk, DES3_EDE_BLOCK_SIZE);
 269}
 270
 271static unsigned int __ctr_crypt(struct des3_ede_x86_ctx *ctx,
 272                                struct skcipher_walk *walk)
 273{
 274        unsigned int bsize = DES3_EDE_BLOCK_SIZE;
 275        unsigned int nbytes = walk->nbytes;
 276        __be64 *src = (__be64 *)walk->src.virt.addr;
 277        __be64 *dst = (__be64 *)walk->dst.virt.addr;
 278        u64 ctrblk = be64_to_cpu(*(__be64 *)walk->iv);
 279        __be64 ctrblocks[3];
 280
 281        /* Process four block batch */
 282        if (nbytes >= bsize * 3) {
 283                do {
 284                        /* create ctrblks for parallel encrypt */
 285                        ctrblocks[0] = cpu_to_be64(ctrblk++);
 286                        ctrblocks[1] = cpu_to_be64(ctrblk++);
 287                        ctrblocks[2] = cpu_to_be64(ctrblk++);
 288
 289                        des3_ede_enc_blk_3way(ctx, (u8 *)ctrblocks,
 290                                              (u8 *)ctrblocks);
 291
 292                        dst[0] = src[0] ^ ctrblocks[0];
 293                        dst[1] = src[1] ^ ctrblocks[1];
 294                        dst[2] = src[2] ^ ctrblocks[2];
 295
 296                        src += 3;
 297                        dst += 3;
 298                } while ((nbytes -= bsize * 3) >= bsize * 3);
 299
 300                if (nbytes < bsize)
 301                        goto done;
 302        }
 303
 304        /* Handle leftovers */
 305        do {
 306                ctrblocks[0] = cpu_to_be64(ctrblk++);
 307
 308                des3_ede_enc_blk(ctx, (u8 *)ctrblocks, (u8 *)ctrblocks);
 309
 310                dst[0] = src[0] ^ ctrblocks[0];
 311
 312                src += 1;
 313                dst += 1;
 314        } while ((nbytes -= bsize) >= bsize);
 315
 316done:
 317        *(__be64 *)walk->iv = cpu_to_be64(ctrblk);
 318        return nbytes;
 319}
 320
 321static int ctr_crypt(struct skcipher_request *req)
 322{
 323        struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
 324        struct des3_ede_x86_ctx *ctx = crypto_skcipher_ctx(tfm);
 325        struct skcipher_walk walk;
 326        unsigned int nbytes;
 327        int err;
 328
 329        err = skcipher_walk_virt(&walk, req, false);
 330
 331        while ((nbytes = walk.nbytes) >= DES3_EDE_BLOCK_SIZE) {
 332                nbytes = __ctr_crypt(ctx, &walk);
 333                err = skcipher_walk_done(&walk, nbytes);
 334        }
 335
 336        if (nbytes) {
 337                ctr_crypt_final(ctx, &walk);
 338                err = skcipher_walk_done(&walk, 0);
 339        }
 340
 341        return err;
 342}
 343
 344static int des3_ede_x86_setkey(struct crypto_tfm *tfm, const u8 *key,
 345                               unsigned int keylen)
 346{
 347        struct des3_ede_x86_ctx *ctx = crypto_tfm_ctx(tfm);
 348        u32 i, j, tmp;
 349        int err;
 350
 351        err = des3_ede_expand_key(&ctx->enc, key, keylen);
 352        if (err == -ENOKEY) {
 353                if (crypto_tfm_get_flags(tfm) & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)
 354                        err = -EINVAL;
 355                else
 356                        err = 0;
 357        }
 358
 359        if (err) {
 360                memset(ctx, 0, sizeof(*ctx));
 361                return err;
 362        }
 363
 364        /* Fix encryption context for this implementation and form decryption
 365         * context. */
 366        j = DES3_EDE_EXPKEY_WORDS - 2;
 367        for (i = 0; i < DES3_EDE_EXPKEY_WORDS; i += 2, j -= 2) {
 368                tmp = ror32(ctx->enc.expkey[i + 1], 4);
 369                ctx->enc.expkey[i + 1] = tmp;
 370
 371                ctx->dec.expkey[j + 0] = ctx->enc.expkey[i + 0];
 372                ctx->dec.expkey[j + 1] = tmp;
 373        }
 374
 375        return 0;
 376}
 377
 378static int des3_ede_x86_setkey_skcipher(struct crypto_skcipher *tfm,
 379                                        const u8 *key,
 380                                        unsigned int keylen)
 381{
 382        return des3_ede_x86_setkey(&tfm->base, key, keylen);
 383}
 384
 385static struct crypto_alg des3_ede_cipher = {
 386        .cra_name               = "des3_ede",
 387        .cra_driver_name        = "des3_ede-asm",
 388        .cra_priority           = 200,
 389        .cra_flags              = CRYPTO_ALG_TYPE_CIPHER,
 390        .cra_blocksize          = DES3_EDE_BLOCK_SIZE,
 391        .cra_ctxsize            = sizeof(struct des3_ede_x86_ctx),
 392        .cra_alignmask          = 0,
 393        .cra_module             = THIS_MODULE,
 394        .cra_u = {
 395                .cipher = {
 396                        .cia_min_keysize        = DES3_EDE_KEY_SIZE,
 397                        .cia_max_keysize        = DES3_EDE_KEY_SIZE,
 398                        .cia_setkey             = des3_ede_x86_setkey,
 399                        .cia_encrypt            = des3_ede_x86_encrypt,
 400                        .cia_decrypt            = des3_ede_x86_decrypt,
 401                }
 402        }
 403};
 404
 405static struct skcipher_alg des3_ede_skciphers[] = {
 406        {
 407                .base.cra_name          = "ecb(des3_ede)",
 408                .base.cra_driver_name   = "ecb-des3_ede-asm",
 409                .base.cra_priority      = 300,
 410                .base.cra_blocksize     = DES3_EDE_BLOCK_SIZE,
 411                .base.cra_ctxsize       = sizeof(struct des3_ede_x86_ctx),
 412                .base.cra_module        = THIS_MODULE,
 413                .min_keysize            = DES3_EDE_KEY_SIZE,
 414                .max_keysize            = DES3_EDE_KEY_SIZE,
 415                .setkey                 = des3_ede_x86_setkey_skcipher,
 416                .encrypt                = ecb_encrypt,
 417                .decrypt                = ecb_decrypt,
 418        }, {
 419                .base.cra_name          = "cbc(des3_ede)",
 420                .base.cra_driver_name   = "cbc-des3_ede-asm",
 421                .base.cra_priority      = 300,
 422                .base.cra_blocksize     = DES3_EDE_BLOCK_SIZE,
 423                .base.cra_ctxsize       = sizeof(struct des3_ede_x86_ctx),
 424                .base.cra_module        = THIS_MODULE,
 425                .min_keysize            = DES3_EDE_KEY_SIZE,
 426                .max_keysize            = DES3_EDE_KEY_SIZE,
 427                .ivsize                 = DES3_EDE_BLOCK_SIZE,
 428                .setkey                 = des3_ede_x86_setkey_skcipher,
 429                .encrypt                = cbc_encrypt,
 430                .decrypt                = cbc_decrypt,
 431        }, {
 432                .base.cra_name          = "ctr(des3_ede)",
 433                .base.cra_driver_name   = "ctr-des3_ede-asm",
 434                .base.cra_priority      = 300,
 435                .base.cra_blocksize     = 1,
 436                .base.cra_ctxsize       = sizeof(struct des3_ede_x86_ctx),
 437                .base.cra_module        = THIS_MODULE,
 438                .min_keysize            = DES3_EDE_KEY_SIZE,
 439                .max_keysize            = DES3_EDE_KEY_SIZE,
 440                .ivsize                 = DES3_EDE_BLOCK_SIZE,
 441                .chunksize              = DES3_EDE_BLOCK_SIZE,
 442                .setkey                 = des3_ede_x86_setkey_skcipher,
 443                .encrypt                = ctr_crypt,
 444                .decrypt                = ctr_crypt,
 445        }
 446};
 447
 448static bool is_blacklisted_cpu(void)
 449{
 450        if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
 451                return false;
 452
 453        if (boot_cpu_data.x86 == 0x0f) {
 454                /*
 455                 * On Pentium 4, des3_ede-x86_64 is slower than generic C
 456                 * implementation because use of 64bit rotates (which are really
 457                 * slow on P4). Therefore blacklist P4s.
 458                 */
 459                return true;
 460        }
 461
 462        return false;
 463}
 464
 465static int force;
 466module_param(force, int, 0);
 467MODULE_PARM_DESC(force, "Force module load, ignore CPU blacklist");
 468
 469static int __init des3_ede_x86_init(void)
 470{
 471        int err;
 472
 473        if (!force && is_blacklisted_cpu()) {
 474                pr_info("des3_ede-x86_64: performance on this CPU would be suboptimal: disabling des3_ede-x86_64.\n");
 475                return -ENODEV;
 476        }
 477
 478        err = crypto_register_alg(&des3_ede_cipher);
 479        if (err)
 480                return err;
 481
 482        err = crypto_register_skciphers(des3_ede_skciphers,
 483                                        ARRAY_SIZE(des3_ede_skciphers));
 484        if (err)
 485                crypto_unregister_alg(&des3_ede_cipher);
 486
 487        return err;
 488}
 489
 490static void __exit des3_ede_x86_fini(void)
 491{
 492        crypto_unregister_alg(&des3_ede_cipher);
 493        crypto_unregister_skciphers(des3_ede_skciphers,
 494                                    ARRAY_SIZE(des3_ede_skciphers));
 495}
 496
 497module_init(des3_ede_x86_init);
 498module_exit(des3_ede_x86_fini);
 499
 500MODULE_LICENSE("GPL");
 501MODULE_DESCRIPTION("Triple DES EDE Cipher Algorithm, asm optimized");
 502MODULE_ALIAS_CRYPTO("des3_ede");
 503MODULE_ALIAS_CRYPTO("des3_ede-asm");
 504MODULE_AUTHOR("Jussi Kivilinna <jussi.kivilinna@iki.fi>");
 505