immortalwrt/target/linux/ramips/files/drivers/crypto/mtk-eip93/eip93-cipher.c
2022-03-08 13:08:59 +08:00

430 lines
12 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2019 - 2021
*
* Richard van Schagen <vschagen@icloud.com>
*/
#if IS_ENABLED(CONFIG_CRYPTO_DEV_EIP93_AES)
#include <crypto/aes.h>
#include <crypto/ctr.h>
#endif
#if IS_ENABLED(CONFIG_CRYPTO_DEV_EIP93_DES)
#include <crypto/internal/des.h>
#endif
#include <linux/dma-mapping.h>
#include "eip93-cipher.h"
#include "eip93-common.h"
#include "eip93-regs.h"
void mtk_skcipher_handle_result(struct crypto_async_request *async, int err)
{
struct mtk_crypto_ctx *ctx = crypto_tfm_ctx(async->tfm);
struct mtk_device *mtk = ctx->mtk;
struct skcipher_request *req = skcipher_request_cast(async);
struct mtk_cipher_reqctx *rctx = skcipher_request_ctx(req);
mtk_unmap_dma(mtk, rctx, req->src, req->dst);
mtk_handle_result(mtk, rctx, req->iv);
skcipher_request_complete(req, err);
}
static int mtk_skcipher_send_req(struct crypto_async_request *async)
{
struct skcipher_request *req = skcipher_request_cast(async);
struct mtk_cipher_reqctx *rctx = skcipher_request_ctx(req);
int err;
err = check_valid_request(rctx);
if (err) {
skcipher_request_complete(req, err);
return err;
}
return mtk_send_req(async, req->iv, rctx);
}
/* Crypto skcipher API functions */
static int mtk_skcipher_cra_init(struct crypto_tfm *tfm)
{
struct mtk_crypto_ctx *ctx = crypto_tfm_ctx(tfm);
struct mtk_alg_template *tmpl = container_of(tfm->__crt_alg,
struct mtk_alg_template, alg.skcipher.base);
crypto_skcipher_set_reqsize(__crypto_skcipher_cast(tfm),
sizeof(struct mtk_cipher_reqctx));
memset(ctx, 0, sizeof(*ctx));
ctx->mtk = tmpl->mtk;
ctx->sa_in = kzalloc(sizeof(struct saRecord_s), GFP_KERNEL);
if (!ctx->sa_in)
return -ENOMEM;
ctx->sa_base_in = dma_map_single(ctx->mtk->dev, ctx->sa_in,
sizeof(struct saRecord_s), DMA_TO_DEVICE);
ctx->sa_out = kzalloc(sizeof(struct saRecord_s), GFP_KERNEL);
if (!ctx->sa_out)
return -ENOMEM;
ctx->sa_base_out = dma_map_single(ctx->mtk->dev, ctx->sa_out,
sizeof(struct saRecord_s), DMA_TO_DEVICE);
return 0;
}
static void mtk_skcipher_cra_exit(struct crypto_tfm *tfm)
{
struct mtk_crypto_ctx *ctx = crypto_tfm_ctx(tfm);
dma_unmap_single(ctx->mtk->dev, ctx->sa_base_in,
sizeof(struct saRecord_s), DMA_TO_DEVICE);
dma_unmap_single(ctx->mtk->dev, ctx->sa_base_out,
sizeof(struct saRecord_s), DMA_TO_DEVICE);
kfree(ctx->sa_in);
kfree(ctx->sa_out);
}
static int mtk_skcipher_setkey(struct crypto_skcipher *ctfm, const u8 *key,
unsigned int len)
{
struct crypto_tfm *tfm = crypto_skcipher_tfm(ctfm);
struct mtk_crypto_ctx *ctx = crypto_tfm_ctx(tfm);
struct mtk_alg_template *tmpl = container_of(tfm->__crt_alg,
struct mtk_alg_template, alg.skcipher.base);
struct saRecord_s *saRecord = ctx->sa_out;
u32 flags = tmpl->flags;
u32 nonce = 0;
unsigned int keylen = len;
int sa_size = sizeof(struct saRecord_s);
int err = -EINVAL;
if (!key || !keylen)
return err;
#if IS_ENABLED(CONFIG_CRYPTO_DEV_EIP93_AES)
if (IS_RFC3686(flags)) {
if (len < CTR_RFC3686_NONCE_SIZE)
return err;
keylen = len - CTR_RFC3686_NONCE_SIZE;
memcpy(&nonce, key + keylen, CTR_RFC3686_NONCE_SIZE);
}
#endif
#if IS_ENABLED(CONFIG_CRYPTO_DEV_EIP93_DES)
if (flags & MTK_ALG_DES) {
ctx->blksize = DES_BLOCK_SIZE;
err = verify_skcipher_des_key(ctfm, key);
}
if (flags & MTK_ALG_3DES) {
ctx->blksize = DES3_EDE_BLOCK_SIZE;
err = verify_skcipher_des3_key(ctfm, key);
}
#endif
#if IS_ENABLED(CONFIG_CRYPTO_DEV_EIP93_AES)
if (flags & MTK_ALG_AES) {
struct crypto_aes_ctx aes;
ctx->blksize = AES_BLOCK_SIZE;
err = aes_expandkey(&aes, key, keylen);
}
#endif
if (err)
return err;
dma_unmap_single(ctx->mtk->dev, ctx->sa_base_in, sa_size,
DMA_TO_DEVICE);
dma_unmap_single(ctx->mtk->dev, ctx->sa_base_out, sa_size,
DMA_TO_DEVICE);
mtk_set_saRecord(saRecord, keylen, flags);
memcpy(saRecord->saKey, key, keylen);
ctx->saNonce = nonce;
saRecord->saNonce = nonce;
saRecord->saCmd0.bits.direction = 0;
memcpy(ctx->sa_in, saRecord, sa_size);
ctx->sa_in->saCmd0.bits.direction = 1;
ctx->sa_base_out = dma_map_single(ctx->mtk->dev, ctx->sa_out, sa_size,
DMA_TO_DEVICE);
ctx->sa_base_in = dma_map_single(ctx->mtk->dev, ctx->sa_in, sa_size,
DMA_TO_DEVICE);
return err;
}
static int mtk_skcipher_crypt(struct skcipher_request *req)
{
struct mtk_cipher_reqctx *rctx = skcipher_request_ctx(req);
struct crypto_async_request *async = &req->base;
struct mtk_crypto_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req);
if (!req->cryptlen)
return 0;
rctx->assoclen = 0;
rctx->textsize = req->cryptlen;
rctx->authsize = 0;
rctx->sg_src = req->src;
rctx->sg_dst = req->dst;
rctx->ivsize = crypto_skcipher_ivsize(skcipher);
rctx->blksize = ctx->blksize;
rctx->flags |= MTK_DESC_SKCIPHER;
if (!IS_ECB(rctx->flags))
rctx->flags |= MTK_DESC_DMA_IV;
return mtk_skcipher_send_req(async);
}
static int mtk_skcipher_encrypt(struct skcipher_request *req)
{
struct mtk_crypto_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
struct mtk_cipher_reqctx *rctx = skcipher_request_ctx(req);
struct mtk_alg_template *tmpl = container_of(req->base.tfm->__crt_alg,
struct mtk_alg_template, alg.skcipher.base);
rctx->flags = tmpl->flags;
rctx->flags |= MTK_ENCRYPT;
rctx->saRecord_base = ctx->sa_base_out;
return mtk_skcipher_crypt(req);
}
static int mtk_skcipher_decrypt(struct skcipher_request *req)
{
struct mtk_crypto_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
struct mtk_cipher_reqctx *rctx = skcipher_request_ctx(req);
struct mtk_alg_template *tmpl = container_of(req->base.tfm->__crt_alg,
struct mtk_alg_template, alg.skcipher.base);
rctx->flags = tmpl->flags;
rctx->flags |= MTK_DECRYPT;
rctx->saRecord_base = ctx->sa_base_in;
return mtk_skcipher_crypt(req);
}
/* Available algorithms in this module */
#if IS_ENABLED(CONFIG_CRYPTO_DEV_EIP93_AES)
struct mtk_alg_template mtk_alg_ecb_aes = {
.type = MTK_ALG_TYPE_SKCIPHER,
.flags = MTK_MODE_ECB | MTK_ALG_AES,
.alg.skcipher = {
.setkey = mtk_skcipher_setkey,
.encrypt = mtk_skcipher_encrypt,
.decrypt = mtk_skcipher_decrypt,
.min_keysize = AES_MIN_KEY_SIZE,
.max_keysize = AES_MAX_KEY_SIZE,
.ivsize = 0,
.base = {
.cra_name = "ecb(aes)",
.cra_driver_name = "ecb(aes-eip93)",
.cra_priority = MTK_CRA_PRIORITY,
.cra_flags = CRYPTO_ALG_ASYNC |
CRYPTO_ALG_NEED_FALLBACK |
CRYPTO_ALG_KERN_DRIVER_ONLY,
.cra_blocksize = AES_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct mtk_crypto_ctx),
.cra_alignmask = 0xf,
.cra_init = mtk_skcipher_cra_init,
.cra_exit = mtk_skcipher_cra_exit,
.cra_module = THIS_MODULE,
},
},
};
struct mtk_alg_template mtk_alg_cbc_aes = {
.type = MTK_ALG_TYPE_SKCIPHER,
.flags = MTK_MODE_CBC | MTK_ALG_AES,
.alg.skcipher = {
.setkey = mtk_skcipher_setkey,
.encrypt = mtk_skcipher_encrypt,
.decrypt = mtk_skcipher_decrypt,
.min_keysize = AES_MIN_KEY_SIZE,
.max_keysize = AES_MAX_KEY_SIZE,
.ivsize = AES_BLOCK_SIZE,
.base = {
.cra_name = "cbc(aes)",
.cra_driver_name = "cbc(aes-eip93)",
.cra_priority = MTK_CRA_PRIORITY,
.cra_flags = CRYPTO_ALG_ASYNC |
CRYPTO_ALG_NEED_FALLBACK |
CRYPTO_ALG_KERN_DRIVER_ONLY,
.cra_blocksize = AES_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct mtk_crypto_ctx),
.cra_alignmask = 0xf,
.cra_init = mtk_skcipher_cra_init,
.cra_exit = mtk_skcipher_cra_exit,
.cra_module = THIS_MODULE,
},
},
};
struct mtk_alg_template mtk_alg_ctr_aes = {
.type = MTK_ALG_TYPE_SKCIPHER,
.flags = MTK_MODE_CTR | MTK_ALG_AES,
.alg.skcipher = {
.setkey = mtk_skcipher_setkey,
.encrypt = mtk_skcipher_encrypt,
.decrypt = mtk_skcipher_decrypt,
.min_keysize = AES_MIN_KEY_SIZE,
.max_keysize = AES_MAX_KEY_SIZE,
.ivsize = AES_BLOCK_SIZE,
.base = {
.cra_name = "ctr(aes)",
.cra_driver_name = "ctr(aes-eip93)",
.cra_priority = MTK_CRA_PRIORITY,
.cra_flags = CRYPTO_ALG_ASYNC |
CRYPTO_ALG_NEED_FALLBACK |
CRYPTO_ALG_KERN_DRIVER_ONLY,
.cra_blocksize = 1,
.cra_ctxsize = sizeof(struct mtk_crypto_ctx),
.cra_alignmask = 0xf,
.cra_init = mtk_skcipher_cra_init,
.cra_exit = mtk_skcipher_cra_exit,
.cra_module = THIS_MODULE,
},
},
};
struct mtk_alg_template mtk_alg_rfc3686_aes = {
.type = MTK_ALG_TYPE_SKCIPHER,
.flags = MTK_MODE_CTR | MTK_MODE_RFC3686 | MTK_ALG_AES,
.alg.skcipher = {
.setkey = mtk_skcipher_setkey,
.encrypt = mtk_skcipher_encrypt,
.decrypt = mtk_skcipher_decrypt,
.min_keysize = AES_MIN_KEY_SIZE + CTR_RFC3686_NONCE_SIZE,
.max_keysize = AES_MAX_KEY_SIZE + CTR_RFC3686_NONCE_SIZE,
.ivsize = CTR_RFC3686_IV_SIZE,
.base = {
.cra_name = "rfc3686(ctr(aes))",
.cra_driver_name = "rfc3686(ctr(aes-eip93))",
.cra_priority = MTK_CRA_PRIORITY,
.cra_flags = CRYPTO_ALG_ASYNC |
CRYPTO_ALG_NEED_FALLBACK |
CRYPTO_ALG_KERN_DRIVER_ONLY,
.cra_blocksize = 1,
.cra_ctxsize = sizeof(struct mtk_crypto_ctx),
.cra_alignmask = 0xf,
.cra_init = mtk_skcipher_cra_init,
.cra_exit = mtk_skcipher_cra_exit,
.cra_module = THIS_MODULE,
},
},
};
#endif
#if IS_ENABLED(CONFIG_CRYPTO_DEV_EIP93_DES)
struct mtk_alg_template mtk_alg_ecb_des = {
.type = MTK_ALG_TYPE_SKCIPHER,
.flags = MTK_MODE_ECB | MTK_ALG_DES,
.alg.skcipher = {
.setkey = mtk_skcipher_setkey,
.encrypt = mtk_skcipher_encrypt,
.decrypt = mtk_skcipher_decrypt,
.min_keysize = DES_KEY_SIZE,
.max_keysize = DES_KEY_SIZE,
.ivsize = 0,
.base = {
.cra_name = "ecb(des)",
.cra_driver_name = "ebc(des-eip93)",
.cra_priority = MTK_CRA_PRIORITY,
.cra_flags = CRYPTO_ALG_ASYNC |
CRYPTO_ALG_KERN_DRIVER_ONLY,
.cra_blocksize = DES_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct mtk_crypto_ctx),
.cra_alignmask = 0,
.cra_init = mtk_skcipher_cra_init,
.cra_exit = mtk_skcipher_cra_exit,
.cra_module = THIS_MODULE,
},
},
};
struct mtk_alg_template mtk_alg_cbc_des = {
.type = MTK_ALG_TYPE_SKCIPHER,
.flags = MTK_MODE_CBC | MTK_ALG_DES,
.alg.skcipher = {
.setkey = mtk_skcipher_setkey,
.encrypt = mtk_skcipher_encrypt,
.decrypt = mtk_skcipher_decrypt,
.min_keysize = DES_KEY_SIZE,
.max_keysize = DES_KEY_SIZE,
.ivsize = DES_BLOCK_SIZE,
.base = {
.cra_name = "cbc(des)",
.cra_driver_name = "cbc(des-eip93)",
.cra_priority = MTK_CRA_PRIORITY,
.cra_flags = CRYPTO_ALG_ASYNC |
CRYPTO_ALG_KERN_DRIVER_ONLY,
.cra_blocksize = DES_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct mtk_crypto_ctx),
.cra_alignmask = 0,
.cra_init = mtk_skcipher_cra_init,
.cra_exit = mtk_skcipher_cra_exit,
.cra_module = THIS_MODULE,
},
},
};
struct mtk_alg_template mtk_alg_ecb_des3_ede = {
.type = MTK_ALG_TYPE_SKCIPHER,
.flags = MTK_MODE_ECB | MTK_ALG_3DES,
.alg.skcipher = {
.setkey = mtk_skcipher_setkey,
.encrypt = mtk_skcipher_encrypt,
.decrypt = mtk_skcipher_decrypt,
.min_keysize = DES3_EDE_KEY_SIZE,
.max_keysize = DES3_EDE_KEY_SIZE,
.ivsize = 0,
.base = {
.cra_name = "ecb(des3_ede)",
.cra_driver_name = "ecb(des3_ede-eip93)",
.cra_priority = MTK_CRA_PRIORITY,
.cra_flags = CRYPTO_ALG_ASYNC |
CRYPTO_ALG_KERN_DRIVER_ONLY,
.cra_blocksize = DES3_EDE_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct mtk_crypto_ctx),
.cra_alignmask = 0,
.cra_init = mtk_skcipher_cra_init,
.cra_exit = mtk_skcipher_cra_exit,
.cra_module = THIS_MODULE,
},
},
};
struct mtk_alg_template mtk_alg_cbc_des3_ede = {
.type = MTK_ALG_TYPE_SKCIPHER,
.flags = MTK_MODE_CBC | MTK_ALG_3DES,
.alg.skcipher = {
.setkey = mtk_skcipher_setkey,
.encrypt = mtk_skcipher_encrypt,
.decrypt = mtk_skcipher_decrypt,
.min_keysize = DES3_EDE_KEY_SIZE,
.max_keysize = DES3_EDE_KEY_SIZE,
.ivsize = DES3_EDE_BLOCK_SIZE,
.base = {
.cra_name = "cbc(des3_ede)",
.cra_driver_name = "cbc(des3_ede-eip93)",
.cra_priority = MTK_CRA_PRIORITY,
.cra_flags = CRYPTO_ALG_ASYNC |
CRYPTO_ALG_KERN_DRIVER_ONLY,
.cra_blocksize = DES3_EDE_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct mtk_crypto_ctx),
.cra_alignmask = 0,
.cra_init = mtk_skcipher_cra_init,
.cra_exit = mtk_skcipher_cra_exit,
.cra_module = THIS_MODULE,
},
},
};
#endif