linux/arch/s390/crypto/aes_s390.c
<<
>>
Prefs
   1/*
   2 * Cryptographic API.
   3 *
   4 * s390 implementation of the AES Cipher Algorithm.
   5 *
   6 * s390 Version:
   7 *   Copyright IBM Corp. 2005,2007
   8 *   Author(s): Jan Glauber (jang@de.ibm.com)
   9 *              Sebastian Siewior (sebastian@breakpoint.cc> SW-Fallback
  10 *
  11 * Derived from "crypto/aes_generic.c"
  12 *
  13 * This program is free software; you can redistribute it and/or modify it
  14 * under the terms of the GNU General Public License as published by the Free
  15 * Software Foundation; either version 2 of the License, or (at your option)
  16 * any later version.
  17 *
  18 */
  19
  20#include <crypto/aes.h>
  21#include <crypto/algapi.h>
  22#include <linux/err.h>
  23#include <linux/module.h>
  24#include <linux/init.h>
  25#include "crypt_s390.h"
  26
  27#define AES_KEYLEN_128          1
  28#define AES_KEYLEN_192          2
  29#define AES_KEYLEN_256          4
  30
  31static char keylen_flag = 0;
  32
  33struct s390_aes_ctx {
  34        u8 iv[AES_BLOCK_SIZE];
  35        u8 key[AES_MAX_KEY_SIZE];
  36        long enc;
  37        long dec;
  38        int key_len;
  39        union {
  40                struct crypto_blkcipher *blk;
  41                struct crypto_cipher *cip;
  42        } fallback;
  43};
  44
  45/*
  46 * Check if the key_len is supported by the HW.
  47 * Returns 0 if it is, a positive number if it is not and software fallback is
  48 * required or a negative number in case the key size is not valid
  49 */
  50static int need_fallback(unsigned int key_len)
  51{
  52        switch (key_len) {
  53        case 16:
  54                if (!(keylen_flag & AES_KEYLEN_128))
  55                        return 1;
  56                break;
  57        case 24:
  58                if (!(keylen_flag & AES_KEYLEN_192))
  59                        return 1;
  60                break;
  61        case 32:
  62                if (!(keylen_flag & AES_KEYLEN_256))
  63                        return 1;
  64                break;
  65        default:
  66                return -1;
  67                break;
  68        }
  69        return 0;
  70}
  71
  72static int setkey_fallback_cip(struct crypto_tfm *tfm, const u8 *in_key,
  73                unsigned int key_len)
  74{
  75        struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
  76        int ret;
  77
  78        sctx->fallback.blk->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
  79        sctx->fallback.blk->base.crt_flags |= (tfm->crt_flags &
  80                        CRYPTO_TFM_REQ_MASK);
  81
  82        ret = crypto_cipher_setkey(sctx->fallback.cip, in_key, key_len);
  83        if (ret) {
  84                tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK;
  85                tfm->crt_flags |= (sctx->fallback.blk->base.crt_flags &
  86                                CRYPTO_TFM_RES_MASK);
  87        }
  88        return ret;
  89}
  90
  91static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
  92                       unsigned int key_len)
  93{
  94        struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
  95        u32 *flags = &tfm->crt_flags;
  96        int ret;
  97
  98        ret = need_fallback(key_len);
  99        if (ret < 0) {
 100                *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
 101                return -EINVAL;
 102        }
 103
 104        sctx->key_len = key_len;
 105        if (!ret) {
 106                memcpy(sctx->key, in_key, key_len);
 107                return 0;
 108        }
 109
 110        return setkey_fallback_cip(tfm, in_key, key_len);
 111}
 112
 113static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
 114{
 115        const struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
 116
 117        if (unlikely(need_fallback(sctx->key_len))) {
 118                crypto_cipher_encrypt_one(sctx->fallback.cip, out, in);
 119                return;
 120        }
 121
 122        switch (sctx->key_len) {
 123        case 16:
 124                crypt_s390_km(KM_AES_128_ENCRYPT, &sctx->key, out, in,
 125                              AES_BLOCK_SIZE);
 126                break;
 127        case 24:
 128                crypt_s390_km(KM_AES_192_ENCRYPT, &sctx->key, out, in,
 129                              AES_BLOCK_SIZE);
 130                break;
 131        case 32:
 132                crypt_s390_km(KM_AES_256_ENCRYPT, &sctx->key, out, in,
 133                              AES_BLOCK_SIZE);
 134                break;
 135        }
 136}
 137
 138static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
 139{
 140        const struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
 141
 142        if (unlikely(need_fallback(sctx->key_len))) {
 143                crypto_cipher_decrypt_one(sctx->fallback.cip, out, in);
 144                return;
 145        }
 146
 147        switch (sctx->key_len) {
 148        case 16:
 149                crypt_s390_km(KM_AES_128_DECRYPT, &sctx->key, out, in,
 150                              AES_BLOCK_SIZE);
 151                break;
 152        case 24:
 153                crypt_s390_km(KM_AES_192_DECRYPT, &sctx->key, out, in,
 154                              AES_BLOCK_SIZE);
 155                break;
 156        case 32:
 157                crypt_s390_km(KM_AES_256_DECRYPT, &sctx->key, out, in,
 158                              AES_BLOCK_SIZE);
 159                break;
 160        }
 161}
 162
 163static int fallback_init_cip(struct crypto_tfm *tfm)
 164{
 165        const char *name = tfm->__crt_alg->cra_name;
 166        struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
 167
 168        sctx->fallback.cip = crypto_alloc_cipher(name, 0,
 169                        CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK);
 170
 171        if (IS_ERR(sctx->fallback.cip)) {
 172                printk(KERN_ERR "Error allocating fallback algo %s\n", name);
 173                return PTR_ERR(sctx->fallback.blk);
 174        }
 175
 176        return 0;
 177}
 178
 179static void fallback_exit_cip(struct crypto_tfm *tfm)
 180{
 181        struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
 182
 183        crypto_free_cipher(sctx->fallback.cip);
 184        sctx->fallback.cip = NULL;
 185}
 186
 187static struct crypto_alg aes_alg = {
 188        .cra_name               =       "aes",
 189        .cra_driver_name        =       "aes-s390",
 190        .cra_priority           =       CRYPT_S390_PRIORITY,
 191        .cra_flags              =       CRYPTO_ALG_TYPE_CIPHER |
 192                                        CRYPTO_ALG_NEED_FALLBACK,
 193        .cra_blocksize          =       AES_BLOCK_SIZE,
 194        .cra_ctxsize            =       sizeof(struct s390_aes_ctx),
 195        .cra_module             =       THIS_MODULE,
 196        .cra_list               =       LIST_HEAD_INIT(aes_alg.cra_list),
 197        .cra_init               =       fallback_init_cip,
 198        .cra_exit               =       fallback_exit_cip,
 199        .cra_u                  =       {
 200                .cipher = {
 201                        .cia_min_keysize        =       AES_MIN_KEY_SIZE,
 202                        .cia_max_keysize        =       AES_MAX_KEY_SIZE,
 203                        .cia_setkey             =       aes_set_key,
 204                        .cia_encrypt            =       aes_encrypt,
 205                        .cia_decrypt            =       aes_decrypt,
 206                }
 207        }
 208};
 209
 210static int setkey_fallback_blk(struct crypto_tfm *tfm, const u8 *key,
 211                unsigned int len)
 212{
 213        struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
 214        unsigned int ret;
 215
 216        sctx->fallback.blk->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
 217        sctx->fallback.blk->base.crt_flags |= (tfm->crt_flags &
 218                        CRYPTO_TFM_REQ_MASK);
 219
 220        ret = crypto_blkcipher_setkey(sctx->fallback.blk, key, len);
 221        if (ret) {
 222                tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK;
 223                tfm->crt_flags |= (sctx->fallback.blk->base.crt_flags &
 224                                CRYPTO_TFM_RES_MASK);
 225        }
 226        return ret;
 227}
 228
 229static int fallback_blk_dec(struct blkcipher_desc *desc,
 230                struct scatterlist *dst, struct scatterlist *src,
 231                unsigned int nbytes)
 232{
 233        unsigned int ret;
 234        struct crypto_blkcipher *tfm;
 235        struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
 236
 237        tfm = desc->tfm;
 238        desc->tfm = sctx->fallback.blk;
 239
 240        ret = crypto_blkcipher_decrypt_iv(desc, dst, src, nbytes);
 241
 242        desc->tfm = tfm;
 243        return ret;
 244}
 245
 246static int fallback_blk_enc(struct blkcipher_desc *desc,
 247                struct scatterlist *dst, struct scatterlist *src,
 248                unsigned int nbytes)
 249{
 250        unsigned int ret;
 251        struct crypto_blkcipher *tfm;
 252        struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
 253
 254        tfm = desc->tfm;
 255        desc->tfm = sctx->fallback.blk;
 256
 257        ret = crypto_blkcipher_encrypt_iv(desc, dst, src, nbytes);
 258
 259        desc->tfm = tfm;
 260        return ret;
 261}
 262
 263static int ecb_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
 264                           unsigned int key_len)
 265{
 266        struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
 267        int ret;
 268
 269        ret = need_fallback(key_len);
 270        if (ret > 0) {
 271                sctx->key_len = key_len;
 272                return setkey_fallback_blk(tfm, in_key, key_len);
 273        }
 274
 275        switch (key_len) {
 276        case 16:
 277                sctx->enc = KM_AES_128_ENCRYPT;
 278                sctx->dec = KM_AES_128_DECRYPT;
 279                break;
 280        case 24:
 281                sctx->enc = KM_AES_192_ENCRYPT;
 282                sctx->dec = KM_AES_192_DECRYPT;
 283                break;
 284        case 32:
 285                sctx->enc = KM_AES_256_ENCRYPT;
 286                sctx->dec = KM_AES_256_DECRYPT;
 287                break;
 288        }
 289
 290        return aes_set_key(tfm, in_key, key_len);
 291}
 292
 293static int ecb_aes_crypt(struct blkcipher_desc *desc, long func, void *param,
 294                         struct blkcipher_walk *walk)
 295{
 296        int ret = blkcipher_walk_virt(desc, walk);
 297        unsigned int nbytes;
 298
 299        while ((nbytes = walk->nbytes)) {
 300                /* only use complete blocks */
 301                unsigned int n = nbytes & ~(AES_BLOCK_SIZE - 1);
 302                u8 *out = walk->dst.virt.addr;
 303                u8 *in = walk->src.virt.addr;
 304
 305                ret = crypt_s390_km(func, param, out, in, n);
 306                BUG_ON((ret < 0) || (ret != n));
 307
 308                nbytes &= AES_BLOCK_SIZE - 1;
 309                ret = blkcipher_walk_done(desc, walk, nbytes);
 310        }
 311
 312        return ret;
 313}
 314
 315static int ecb_aes_encrypt(struct blkcipher_desc *desc,
 316                           struct scatterlist *dst, struct scatterlist *src,
 317                           unsigned int nbytes)
 318{
 319        struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
 320        struct blkcipher_walk walk;
 321
 322        if (unlikely(need_fallback(sctx->key_len)))
 323                return fallback_blk_enc(desc, dst, src, nbytes);
 324
 325        blkcipher_walk_init(&walk, dst, src, nbytes);
 326        return ecb_aes_crypt(desc, sctx->enc, sctx->key, &walk);
 327}
 328
 329static int ecb_aes_decrypt(struct blkcipher_desc *desc,
 330                           struct scatterlist *dst, struct scatterlist *src,
 331                           unsigned int nbytes)
 332{
 333        struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
 334        struct blkcipher_walk walk;
 335
 336        if (unlikely(need_fallback(sctx->key_len)))
 337                return fallback_blk_dec(desc, dst, src, nbytes);
 338
 339        blkcipher_walk_init(&walk, dst, src, nbytes);
 340        return ecb_aes_crypt(desc, sctx->dec, sctx->key, &walk);
 341}
 342
 343static int fallback_init_blk(struct crypto_tfm *tfm)
 344{
 345        const char *name = tfm->__crt_alg->cra_name;
 346        struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
 347
 348        sctx->fallback.blk = crypto_alloc_blkcipher(name, 0,
 349                        CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK);
 350
 351        if (IS_ERR(sctx->fallback.blk)) {
 352                printk(KERN_ERR "Error allocating fallback algo %s\n", name);
 353                return PTR_ERR(sctx->fallback.blk);
 354        }
 355
 356        return 0;
 357}
 358
 359static void fallback_exit_blk(struct crypto_tfm *tfm)
 360{
 361        struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
 362
 363        crypto_free_blkcipher(sctx->fallback.blk);
 364        sctx->fallback.blk = NULL;
 365}
 366
 367static struct crypto_alg ecb_aes_alg = {
 368        .cra_name               =       "ecb(aes)",
 369        .cra_driver_name        =       "ecb-aes-s390",
 370        .cra_priority           =       CRYPT_S390_COMPOSITE_PRIORITY,
 371        .cra_flags              =       CRYPTO_ALG_TYPE_BLKCIPHER |
 372                                        CRYPTO_ALG_NEED_FALLBACK,
 373        .cra_blocksize          =       AES_BLOCK_SIZE,
 374        .cra_ctxsize            =       sizeof(struct s390_aes_ctx),
 375        .cra_type               =       &crypto_blkcipher_type,
 376        .cra_module             =       THIS_MODULE,
 377        .cra_list               =       LIST_HEAD_INIT(ecb_aes_alg.cra_list),
 378        .cra_init               =       fallback_init_blk,
 379        .cra_exit               =       fallback_exit_blk,
 380        .cra_u                  =       {
 381                .blkcipher = {
 382                        .min_keysize            =       AES_MIN_KEY_SIZE,
 383                        .max_keysize            =       AES_MAX_KEY_SIZE,
 384                        .setkey                 =       ecb_aes_set_key,
 385                        .encrypt                =       ecb_aes_encrypt,
 386                        .decrypt                =       ecb_aes_decrypt,
 387                }
 388        }
 389};
 390
 391static int cbc_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
 392                           unsigned int key_len)
 393{
 394        struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
 395        int ret;
 396
 397        ret = need_fallback(key_len);
 398        if (ret > 0) {
 399                sctx->key_len = key_len;
 400                return setkey_fallback_blk(tfm, in_key, key_len);
 401        }
 402
 403        switch (key_len) {
 404        case 16:
 405                sctx->enc = KMC_AES_128_ENCRYPT;
 406                sctx->dec = KMC_AES_128_DECRYPT;
 407                break;
 408        case 24:
 409                sctx->enc = KMC_AES_192_ENCRYPT;
 410                sctx->dec = KMC_AES_192_DECRYPT;
 411                break;
 412        case 32:
 413                sctx->enc = KMC_AES_256_ENCRYPT;
 414                sctx->dec = KMC_AES_256_DECRYPT;
 415                break;
 416        }
 417
 418        return aes_set_key(tfm, in_key, key_len);
 419}
 420
 421static int cbc_aes_crypt(struct blkcipher_desc *desc, long func, void *param,
 422                         struct blkcipher_walk *walk)
 423{
 424        int ret = blkcipher_walk_virt(desc, walk);
 425        unsigned int nbytes = walk->nbytes;
 426
 427        if (!nbytes)
 428                goto out;
 429
 430        memcpy(param, walk->iv, AES_BLOCK_SIZE);
 431        do {
 432                /* only use complete blocks */
 433                unsigned int n = nbytes & ~(AES_BLOCK_SIZE - 1);
 434                u8 *out = walk->dst.virt.addr;
 435                u8 *in = walk->src.virt.addr;
 436
 437                ret = crypt_s390_kmc(func, param, out, in, n);
 438                BUG_ON((ret < 0) || (ret != n));
 439
 440                nbytes &= AES_BLOCK_SIZE - 1;
 441                ret = blkcipher_walk_done(desc, walk, nbytes);
 442        } while ((nbytes = walk->nbytes));
 443        memcpy(walk->iv, param, AES_BLOCK_SIZE);
 444
 445out:
 446        return ret;
 447}
 448
 449static int cbc_aes_encrypt(struct blkcipher_desc *desc,
 450                           struct scatterlist *dst, struct scatterlist *src,
 451                           unsigned int nbytes)
 452{
 453        struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
 454        struct blkcipher_walk walk;
 455
 456        if (unlikely(need_fallback(sctx->key_len)))
 457                return fallback_blk_enc(desc, dst, src, nbytes);
 458
 459        blkcipher_walk_init(&walk, dst, src, nbytes);
 460        return cbc_aes_crypt(desc, sctx->enc, sctx->iv, &walk);
 461}
 462
 463static int cbc_aes_decrypt(struct blkcipher_desc *desc,
 464                           struct scatterlist *dst, struct scatterlist *src,
 465                           unsigned int nbytes)
 466{
 467        struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
 468        struct blkcipher_walk walk;
 469
 470        if (unlikely(need_fallback(sctx->key_len)))
 471                return fallback_blk_dec(desc, dst, src, nbytes);
 472
 473        blkcipher_walk_init(&walk, dst, src, nbytes);
 474        return cbc_aes_crypt(desc, sctx->dec, sctx->iv, &walk);
 475}
 476
 477static struct crypto_alg cbc_aes_alg = {
 478        .cra_name               =       "cbc(aes)",
 479        .cra_driver_name        =       "cbc-aes-s390",
 480        .cra_priority           =       CRYPT_S390_COMPOSITE_PRIORITY,
 481        .cra_flags              =       CRYPTO_ALG_TYPE_BLKCIPHER |
 482                                        CRYPTO_ALG_NEED_FALLBACK,
 483        .cra_blocksize          =       AES_BLOCK_SIZE,
 484        .cra_ctxsize            =       sizeof(struct s390_aes_ctx),
 485        .cra_type               =       &crypto_blkcipher_type,
 486        .cra_module             =       THIS_MODULE,
 487        .cra_list               =       LIST_HEAD_INIT(cbc_aes_alg.cra_list),
 488        .cra_init               =       fallback_init_blk,
 489        .cra_exit               =       fallback_exit_blk,
 490        .cra_u                  =       {
 491                .blkcipher = {
 492                        .min_keysize            =       AES_MIN_KEY_SIZE,
 493                        .max_keysize            =       AES_MAX_KEY_SIZE,
 494                        .ivsize                 =       AES_BLOCK_SIZE,
 495                        .setkey                 =       cbc_aes_set_key,
 496                        .encrypt                =       cbc_aes_encrypt,
 497                        .decrypt                =       cbc_aes_decrypt,
 498                }
 499        }
 500};
 501
 502static int __init aes_s390_init(void)
 503{
 504        int ret;
 505
 506        if (crypt_s390_func_available(KM_AES_128_ENCRYPT))
 507                keylen_flag |= AES_KEYLEN_128;
 508        if (crypt_s390_func_available(KM_AES_192_ENCRYPT))
 509                keylen_flag |= AES_KEYLEN_192;
 510        if (crypt_s390_func_available(KM_AES_256_ENCRYPT))
 511                keylen_flag |= AES_KEYLEN_256;
 512
 513        if (!keylen_flag)
 514                return -EOPNOTSUPP;
 515
 516        /* z9 109 and z9 BC/EC only support 128 bit key length */
 517        if (keylen_flag == AES_KEYLEN_128)
 518                printk(KERN_INFO
 519                       "aes_s390: hardware acceleration only available for "
 520                       "128 bit keys\n");
 521
 522        ret = crypto_register_alg(&aes_alg);
 523        if (ret)
 524                goto aes_err;
 525
 526        ret = crypto_register_alg(&ecb_aes_alg);
 527        if (ret)
 528                goto ecb_aes_err;
 529
 530        ret = crypto_register_alg(&cbc_aes_alg);
 531        if (ret)
 532                goto cbc_aes_err;
 533
 534out:
 535        return ret;
 536
 537cbc_aes_err:
 538        crypto_unregister_alg(&ecb_aes_alg);
 539ecb_aes_err:
 540        crypto_unregister_alg(&aes_alg);
 541aes_err:
 542        goto out;
 543}
 544
 545static void __exit aes_s390_fini(void)
 546{
 547        crypto_unregister_alg(&cbc_aes_alg);
 548        crypto_unregister_alg(&ecb_aes_alg);
 549        crypto_unregister_alg(&aes_alg);
 550}
 551
 552module_init(aes_s390_init);
 553module_exit(aes_s390_fini);
 554
 555MODULE_ALIAS("aes");
 556
 557MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm");
 558MODULE_LICENSE("GPL");
 559