linux/drivers/crypto/cavium/nitrox/nitrox_algs.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2#include <linux/crypto.h>
   3#include <linux/kernel.h>
   4#include <linux/module.h>
   5#include <linux/printk.h>
   6
   7#include <crypto/aes.h>
   8#include <crypto/skcipher.h>
   9#include <crypto/ctr.h>
  10#include <crypto/des.h>
  11#include <crypto/xts.h>
  12
  13#include "nitrox_dev.h"
  14#include "nitrox_common.h"
  15#include "nitrox_req.h"
  16
  17#define PRIO 4001
  18
  19struct nitrox_cipher {
  20        const char *name;
  21        enum flexi_cipher value;
  22};
  23
  24/**
  25 * supported cipher list
  26 */
  27static const struct nitrox_cipher flexi_cipher_table[] = {
  28        { "null",               CIPHER_NULL },
  29        { "cbc(des3_ede)",      CIPHER_3DES_CBC },
  30        { "ecb(des3_ede)",      CIPHER_3DES_ECB },
  31        { "cbc(aes)",           CIPHER_AES_CBC },
  32        { "ecb(aes)",           CIPHER_AES_ECB },
  33        { "cfb(aes)",           CIPHER_AES_CFB },
  34        { "rfc3686(ctr(aes))",  CIPHER_AES_CTR },
  35        { "xts(aes)",           CIPHER_AES_XTS },
  36        { "cts(cbc(aes))",      CIPHER_AES_CBC_CTS },
  37        { NULL,                 CIPHER_INVALID }
  38};
  39
  40static enum flexi_cipher flexi_cipher_type(const char *name)
  41{
  42        const struct nitrox_cipher *cipher = flexi_cipher_table;
  43
  44        while (cipher->name) {
  45                if (!strcmp(cipher->name, name))
  46                        break;
  47                cipher++;
  48        }
  49        return cipher->value;
  50}
  51
  52static int flexi_aes_keylen(int keylen)
  53{
  54        int aes_keylen;
  55
  56        switch (keylen) {
  57        case AES_KEYSIZE_128:
  58                aes_keylen = 1;
  59                break;
  60        case AES_KEYSIZE_192:
  61                aes_keylen = 2;
  62                break;
  63        case AES_KEYSIZE_256:
  64                aes_keylen = 3;
  65                break;
  66        default:
  67                aes_keylen = -EINVAL;
  68                break;
  69        }
  70        return aes_keylen;
  71}
  72
  73static int nitrox_skcipher_init(struct crypto_skcipher *tfm)
  74{
  75        struct nitrox_crypto_ctx *nctx = crypto_skcipher_ctx(tfm);
  76        void *fctx;
  77
  78        /* get the first device */
  79        nctx->ndev = nitrox_get_first_device();
  80        if (!nctx->ndev)
  81                return -ENODEV;
  82
  83        /* allocate nitrox crypto context */
  84        fctx = crypto_alloc_context(nctx->ndev);
  85        if (!fctx) {
  86                nitrox_put_device(nctx->ndev);
  87                return -ENOMEM;
  88        }
  89        nctx->u.ctx_handle = (uintptr_t)fctx;
  90        crypto_skcipher_set_reqsize(tfm, crypto_skcipher_reqsize(tfm) +
  91                                    sizeof(struct nitrox_kcrypt_request));
  92        return 0;
  93}
  94
  95static void nitrox_skcipher_exit(struct crypto_skcipher *tfm)
  96{
  97        struct nitrox_crypto_ctx *nctx = crypto_skcipher_ctx(tfm);
  98
  99        /* free the nitrox crypto context */
 100        if (nctx->u.ctx_handle) {
 101                struct flexi_crypto_context *fctx = nctx->u.fctx;
 102
 103                memset(&fctx->crypto, 0, sizeof(struct crypto_keys));
 104                memset(&fctx->auth, 0, sizeof(struct auth_keys));
 105                crypto_free_context((void *)fctx);
 106        }
 107        nitrox_put_device(nctx->ndev);
 108
 109        nctx->u.ctx_handle = 0;
 110        nctx->ndev = NULL;
 111}
 112
 113static inline int nitrox_skcipher_setkey(struct crypto_skcipher *cipher,
 114                                         int aes_keylen, const u8 *key,
 115                                         unsigned int keylen)
 116{
 117        struct crypto_tfm *tfm = crypto_skcipher_tfm(cipher);
 118        struct nitrox_crypto_ctx *nctx = crypto_tfm_ctx(tfm);
 119        struct flexi_crypto_context *fctx;
 120        enum flexi_cipher cipher_type;
 121        const char *name;
 122
 123        name = crypto_tfm_alg_name(tfm);
 124        cipher_type = flexi_cipher_type(name);
 125        if (unlikely(cipher_type == CIPHER_INVALID)) {
 126                pr_err("unsupported cipher: %s\n", name);
 127                return -EINVAL;
 128        }
 129
 130        /* fill crypto context */
 131        fctx = nctx->u.fctx;
 132        fctx->flags = 0;
 133        fctx->w0.cipher_type = cipher_type;
 134        fctx->w0.aes_keylen = aes_keylen;
 135        fctx->w0.iv_source = IV_FROM_DPTR;
 136        fctx->flags = cpu_to_be64(*(u64 *)&fctx->w0);
 137        /* copy the key to context */
 138        memcpy(fctx->crypto.u.key, key, keylen);
 139
 140        return 0;
 141}
 142
 143static int nitrox_aes_setkey(struct crypto_skcipher *cipher, const u8 *key,
 144                             unsigned int keylen)
 145{
 146        int aes_keylen;
 147
 148        aes_keylen = flexi_aes_keylen(keylen);
 149        if (aes_keylen < 0) {
 150                crypto_skcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN);
 151                return -EINVAL;
 152        }
 153        return nitrox_skcipher_setkey(cipher, aes_keylen, key, keylen);
 154}
 155
 156static void nitrox_skcipher_callback(struct skcipher_request *skreq,
 157                                     int err)
 158{
 159        if (err) {
 160                pr_err_ratelimited("request failed status 0x%0x\n", err);
 161                err = -EINVAL;
 162        }
 163        skcipher_request_complete(skreq, err);
 164}
 165
 166static int nitrox_skcipher_crypt(struct skcipher_request *skreq, bool enc)
 167{
 168        struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(skreq);
 169        struct nitrox_crypto_ctx *nctx = crypto_skcipher_ctx(cipher);
 170        struct nitrox_kcrypt_request *nkreq = skcipher_request_ctx(skreq);
 171        int ivsize = crypto_skcipher_ivsize(cipher);
 172        struct se_crypto_request *creq;
 173
 174        creq = &nkreq->creq;
 175        creq->flags = skreq->base.flags;
 176        creq->gfp = (skreq->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
 177                     GFP_KERNEL : GFP_ATOMIC;
 178
 179        /* fill the request */
 180        creq->ctrl.value = 0;
 181        creq->opcode = FLEXI_CRYPTO_ENCRYPT_HMAC;
 182        creq->ctrl.s.arg = (enc ? ENCRYPT : DECRYPT);
 183        /* param0: length of the data to be encrypted */
 184        creq->gph.param0 = cpu_to_be16(skreq->cryptlen);
 185        creq->gph.param1 = 0;
 186        /* param2: encryption data offset */
 187        creq->gph.param2 = cpu_to_be16(ivsize);
 188        creq->gph.param3 = 0;
 189
 190        creq->ctx_handle = nctx->u.ctx_handle;
 191        creq->ctrl.s.ctxl = sizeof(struct flexi_crypto_context);
 192
 193        /* copy the iv */
 194        memcpy(creq->iv, skreq->iv, ivsize);
 195        creq->ivsize = ivsize;
 196        creq->src = skreq->src;
 197        creq->dst = skreq->dst;
 198
 199        nkreq->nctx = nctx;
 200        nkreq->skreq = skreq;
 201
 202        /* send the crypto request */
 203        return nitrox_process_se_request(nctx->ndev, creq,
 204                                         nitrox_skcipher_callback, skreq);
 205}
 206
 207static int nitrox_aes_encrypt(struct skcipher_request *skreq)
 208{
 209        return nitrox_skcipher_crypt(skreq, true);
 210}
 211
 212static int nitrox_aes_decrypt(struct skcipher_request *skreq)
 213{
 214        return nitrox_skcipher_crypt(skreq, false);
 215}
 216
 217static int nitrox_3des_setkey(struct crypto_skcipher *cipher,
 218                              const u8 *key, unsigned int keylen)
 219{
 220        if (keylen != DES3_EDE_KEY_SIZE) {
 221                crypto_skcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN);
 222                return -EINVAL;
 223        }
 224
 225        return nitrox_skcipher_setkey(cipher, 0, key, keylen);
 226}
 227
 228static int nitrox_3des_encrypt(struct skcipher_request *skreq)
 229{
 230        return nitrox_skcipher_crypt(skreq, true);
 231}
 232
 233static int nitrox_3des_decrypt(struct skcipher_request *skreq)
 234{
 235        return nitrox_skcipher_crypt(skreq, false);
 236}
 237
 238static int nitrox_aes_xts_setkey(struct crypto_skcipher *cipher,
 239                                 const u8 *key, unsigned int keylen)
 240{
 241        struct crypto_tfm *tfm = crypto_skcipher_tfm(cipher);
 242        struct nitrox_crypto_ctx *nctx = crypto_tfm_ctx(tfm);
 243        struct flexi_crypto_context *fctx;
 244        int aes_keylen, ret;
 245
 246        ret = xts_check_key(tfm, key, keylen);
 247        if (ret)
 248                return ret;
 249
 250        keylen /= 2;
 251
 252        aes_keylen = flexi_aes_keylen(keylen);
 253        if (aes_keylen < 0) {
 254                crypto_skcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN);
 255                return -EINVAL;
 256        }
 257
 258        fctx = nctx->u.fctx;
 259        /* copy KEY2 */
 260        memcpy(fctx->auth.u.key2, (key + keylen), keylen);
 261
 262        return nitrox_skcipher_setkey(cipher, aes_keylen, key, keylen);
 263}
 264
 265static int nitrox_aes_ctr_rfc3686_setkey(struct crypto_skcipher *cipher,
 266                                         const u8 *key, unsigned int keylen)
 267{
 268        struct crypto_tfm *tfm = crypto_skcipher_tfm(cipher);
 269        struct nitrox_crypto_ctx *nctx = crypto_tfm_ctx(tfm);
 270        struct flexi_crypto_context *fctx;
 271        int aes_keylen;
 272
 273        if (keylen < CTR_RFC3686_NONCE_SIZE)
 274                return -EINVAL;
 275
 276        fctx = nctx->u.fctx;
 277
 278        memcpy(fctx->crypto.iv, key + (keylen - CTR_RFC3686_NONCE_SIZE),
 279               CTR_RFC3686_NONCE_SIZE);
 280
 281        keylen -= CTR_RFC3686_NONCE_SIZE;
 282
 283        aes_keylen = flexi_aes_keylen(keylen);
 284        if (aes_keylen < 0) {
 285                crypto_skcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN);
 286                return -EINVAL;
 287        }
 288        return nitrox_skcipher_setkey(cipher, aes_keylen, key, keylen);
 289}
 290
 291static struct skcipher_alg nitrox_skciphers[] = { {
 292        .base = {
 293                .cra_name = "cbc(aes)",
 294                .cra_driver_name = "n5_cbc(aes)",
 295                .cra_priority = PRIO,
 296                .cra_flags = CRYPTO_ALG_ASYNC,
 297                .cra_blocksize = AES_BLOCK_SIZE,
 298                .cra_ctxsize = sizeof(struct nitrox_crypto_ctx),
 299                .cra_alignmask = 0,
 300                .cra_module = THIS_MODULE,
 301        },
 302        .min_keysize = AES_MIN_KEY_SIZE,
 303        .max_keysize = AES_MAX_KEY_SIZE,
 304        .ivsize = AES_BLOCK_SIZE,
 305        .setkey = nitrox_aes_setkey,
 306        .encrypt = nitrox_aes_encrypt,
 307        .decrypt = nitrox_aes_decrypt,
 308        .init = nitrox_skcipher_init,
 309        .exit = nitrox_skcipher_exit,
 310}, {
 311        .base = {
 312                .cra_name = "ecb(aes)",
 313                .cra_driver_name = "n5_ecb(aes)",
 314                .cra_priority = PRIO,
 315                .cra_flags = CRYPTO_ALG_ASYNC,
 316                .cra_blocksize = AES_BLOCK_SIZE,
 317                .cra_ctxsize = sizeof(struct nitrox_crypto_ctx),
 318                .cra_alignmask = 0,
 319                .cra_module = THIS_MODULE,
 320        },
 321        .min_keysize = AES_MIN_KEY_SIZE,
 322        .max_keysize = AES_MAX_KEY_SIZE,
 323        .ivsize = AES_BLOCK_SIZE,
 324        .setkey = nitrox_aes_setkey,
 325        .encrypt = nitrox_aes_encrypt,
 326        .decrypt = nitrox_aes_decrypt,
 327        .init = nitrox_skcipher_init,
 328        .exit = nitrox_skcipher_exit,
 329}, {
 330        .base = {
 331                .cra_name = "cfb(aes)",
 332                .cra_driver_name = "n5_cfb(aes)",
 333                .cra_priority = PRIO,
 334                .cra_flags = CRYPTO_ALG_ASYNC,
 335                .cra_blocksize = AES_BLOCK_SIZE,
 336                .cra_ctxsize = sizeof(struct nitrox_crypto_ctx),
 337                .cra_alignmask = 0,
 338                .cra_module = THIS_MODULE,
 339        },
 340        .min_keysize = AES_MIN_KEY_SIZE,
 341        .max_keysize = AES_MAX_KEY_SIZE,
 342        .ivsize = AES_BLOCK_SIZE,
 343        .setkey = nitrox_aes_setkey,
 344        .encrypt = nitrox_aes_encrypt,
 345        .decrypt = nitrox_aes_decrypt,
 346        .init = nitrox_skcipher_init,
 347        .exit = nitrox_skcipher_exit,
 348}, {
 349        .base = {
 350                .cra_name = "xts(aes)",
 351                .cra_driver_name = "n5_xts(aes)",
 352                .cra_priority = PRIO,
 353                .cra_flags = CRYPTO_ALG_ASYNC,
 354                .cra_blocksize = AES_BLOCK_SIZE,
 355                .cra_ctxsize = sizeof(struct nitrox_crypto_ctx),
 356                .cra_alignmask = 0,
 357                .cra_module = THIS_MODULE,
 358        },
 359        .min_keysize = 2 * AES_MIN_KEY_SIZE,
 360        .max_keysize = 2 * AES_MAX_KEY_SIZE,
 361        .ivsize = AES_BLOCK_SIZE,
 362        .setkey = nitrox_aes_xts_setkey,
 363        .encrypt = nitrox_aes_encrypt,
 364        .decrypt = nitrox_aes_decrypt,
 365        .init = nitrox_skcipher_init,
 366        .exit = nitrox_skcipher_exit,
 367}, {
 368        .base = {
 369                .cra_name = "rfc3686(ctr(aes))",
 370                .cra_driver_name = "n5_rfc3686(ctr(aes))",
 371                .cra_priority = PRIO,
 372                .cra_flags = CRYPTO_ALG_ASYNC,
 373                .cra_blocksize = 1,
 374                .cra_ctxsize = sizeof(struct nitrox_crypto_ctx),
 375                .cra_alignmask = 0,
 376                .cra_module = THIS_MODULE,
 377        },
 378        .min_keysize = AES_MIN_KEY_SIZE + CTR_RFC3686_NONCE_SIZE,
 379        .max_keysize = AES_MAX_KEY_SIZE + CTR_RFC3686_NONCE_SIZE,
 380        .ivsize = CTR_RFC3686_IV_SIZE,
 381        .init = nitrox_skcipher_init,
 382        .exit = nitrox_skcipher_exit,
 383        .setkey = nitrox_aes_ctr_rfc3686_setkey,
 384        .encrypt = nitrox_aes_encrypt,
 385        .decrypt = nitrox_aes_decrypt,
 386}, {
 387        .base = {
 388                .cra_name = "cts(cbc(aes))",
 389                .cra_driver_name = "n5_cts(cbc(aes))",
 390                .cra_priority = PRIO,
 391                .cra_flags = CRYPTO_ALG_ASYNC,
 392                .cra_blocksize = AES_BLOCK_SIZE,
 393                .cra_ctxsize = sizeof(struct nitrox_crypto_ctx),
 394                .cra_alignmask = 0,
 395                .cra_type = &crypto_ablkcipher_type,
 396                .cra_module = THIS_MODULE,
 397        },
 398        .min_keysize = AES_MIN_KEY_SIZE,
 399        .max_keysize = AES_MAX_KEY_SIZE,
 400        .ivsize = AES_BLOCK_SIZE,
 401        .setkey = nitrox_aes_setkey,
 402        .encrypt = nitrox_aes_encrypt,
 403        .decrypt = nitrox_aes_decrypt,
 404        .init = nitrox_skcipher_init,
 405        .exit = nitrox_skcipher_exit,
 406}, {
 407        .base = {
 408                .cra_name = "cbc(des3_ede)",
 409                .cra_driver_name = "n5_cbc(des3_ede)",
 410                .cra_priority = PRIO,
 411                .cra_flags = CRYPTO_ALG_ASYNC,
 412                .cra_blocksize = DES3_EDE_BLOCK_SIZE,
 413                .cra_ctxsize = sizeof(struct nitrox_crypto_ctx),
 414                .cra_alignmask = 0,
 415                .cra_module = THIS_MODULE,
 416        },
 417        .min_keysize = DES3_EDE_KEY_SIZE,
 418        .max_keysize = DES3_EDE_KEY_SIZE,
 419        .ivsize = DES3_EDE_BLOCK_SIZE,
 420        .setkey = nitrox_3des_setkey,
 421        .encrypt = nitrox_3des_encrypt,
 422        .decrypt = nitrox_3des_decrypt,
 423        .init = nitrox_skcipher_init,
 424        .exit = nitrox_skcipher_exit,
 425}, {
 426        .base = {
 427                .cra_name = "ecb(des3_ede)",
 428                .cra_driver_name = "n5_ecb(des3_ede)",
 429                .cra_priority = PRIO,
 430                .cra_flags = CRYPTO_ALG_ASYNC,
 431                .cra_blocksize = DES3_EDE_BLOCK_SIZE,
 432                .cra_ctxsize = sizeof(struct nitrox_crypto_ctx),
 433                .cra_alignmask = 0,
 434                .cra_module = THIS_MODULE,
 435        },
 436        .min_keysize = DES3_EDE_KEY_SIZE,
 437        .max_keysize = DES3_EDE_KEY_SIZE,
 438        .ivsize = DES3_EDE_BLOCK_SIZE,
 439        .setkey = nitrox_3des_setkey,
 440        .encrypt = nitrox_3des_encrypt,
 441        .decrypt = nitrox_3des_decrypt,
 442        .init = nitrox_skcipher_init,
 443        .exit = nitrox_skcipher_exit,
 444}
 445
 446};
 447
 448int nitrox_crypto_register(void)
 449{
 450        return crypto_register_skciphers(nitrox_skciphers,
 451                                         ARRAY_SIZE(nitrox_skciphers));
 452}
 453
 454void nitrox_crypto_unregister(void)
 455{
 456        crypto_unregister_skciphers(nitrox_skciphers,
 457                                    ARRAY_SIZE(nitrox_skciphers));
 458}
 459