Path: blob/master/drivers/crypto/rockchip/rk3288_crypto_skcipher.c
26289 views
// SPDX-License-Identifier: GPL-2.0-only1/*2* Crypto acceleration support for Rockchip RK32883*4* Copyright (c) 2015, Fuzhou Rockchip Electronics Co., Ltd5*6* Author: Zain Wang <[email protected]>7*8* Some ideas are from marvell-cesa.c and s5p-sss.c driver.9*/1011#include <crypto/engine.h>12#include <crypto/internal/skcipher.h>13#include <crypto/scatterwalk.h>14#include <linux/device.h>15#include <linux/err.h>16#include <linux/kernel.h>17#include <linux/string.h>18#include "rk3288_crypto.h"1920#define RK_CRYPTO_DEC BIT(0)2122static int rk_cipher_need_fallback(struct skcipher_request *req)23{24struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);25struct skcipher_alg *alg = crypto_skcipher_alg(tfm);26struct rk_crypto_tmp *algt = container_of(alg, struct rk_crypto_tmp, alg.skcipher.base);27struct scatterlist *sgs, *sgd;28unsigned int stodo, dtodo, len;29unsigned int bs = crypto_skcipher_blocksize(tfm);3031if (!req->cryptlen)32return true;3334len = req->cryptlen;35sgs = req->src;36sgd = req->dst;37while (sgs && sgd) {38if (!IS_ALIGNED(sgs->offset, sizeof(u32))) {39algt->stat_fb_align++;40return true;41}42if (!IS_ALIGNED(sgd->offset, sizeof(u32))) {43algt->stat_fb_align++;44return true;45}46stodo = min(len, sgs->length);47if (stodo % bs) {48algt->stat_fb_len++;49return true;50}51dtodo = min(len, sgd->length);52if (dtodo % bs) {53algt->stat_fb_len++;54return true;55}56if (stodo != dtodo) {57algt->stat_fb_sgdiff++;58return true;59}60len -= stodo;61sgs = sg_next(sgs);62sgd = sg_next(sgd);63}64return false;65}6667static int rk_cipher_fallback(struct skcipher_request *areq)68{69struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq);70struct rk_cipher_ctx *op = crypto_skcipher_ctx(tfm);71struct rk_cipher_rctx *rctx = skcipher_request_ctx(areq);72struct skcipher_alg *alg = crypto_skcipher_alg(tfm);73struct rk_crypto_tmp *algt = container_of(alg, struct rk_crypto_tmp, alg.skcipher.base);74int err;7576algt->stat_fb++;7778skcipher_request_set_tfm(&rctx->fallback_req, op->fallback_tfm);79skcipher_request_set_callback(&rctx->fallback_req, areq->base.flags,80areq->base.complete, areq->base.data);81skcipher_request_set_crypt(&rctx->fallback_req, areq->src, areq->dst,82areq->cryptlen, areq->iv);83if (rctx->mode & RK_CRYPTO_DEC)84err = crypto_skcipher_decrypt(&rctx->fallback_req);85else86err = crypto_skcipher_encrypt(&rctx->fallback_req);87return err;88}8990static int rk_cipher_handle_req(struct skcipher_request *req)91{92struct rk_cipher_rctx *rctx = skcipher_request_ctx(req);93struct rk_crypto_info *rkc;94struct crypto_engine *engine;9596if (rk_cipher_need_fallback(req))97return rk_cipher_fallback(req);9899rkc = get_rk_crypto();100101engine = rkc->engine;102rctx->dev = rkc;103104return crypto_transfer_skcipher_request_to_engine(engine, req);105}106107static int rk_aes_setkey(struct crypto_skcipher *cipher,108const u8 *key, unsigned int keylen)109{110struct crypto_tfm *tfm = crypto_skcipher_tfm(cipher);111struct rk_cipher_ctx *ctx = crypto_tfm_ctx(tfm);112113if (keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_192 &&114keylen != AES_KEYSIZE_256)115return -EINVAL;116ctx->keylen = keylen;117memcpy(ctx->key, key, keylen);118119return crypto_skcipher_setkey(ctx->fallback_tfm, key, keylen);120}121122static int rk_des_setkey(struct crypto_skcipher *cipher,123const u8 *key, unsigned int keylen)124{125struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(cipher);126int err;127128err = verify_skcipher_des_key(cipher, key);129if (err)130return err;131132ctx->keylen = keylen;133memcpy(ctx->key, key, keylen);134135return crypto_skcipher_setkey(ctx->fallback_tfm, key, keylen);136}137138static int rk_tdes_setkey(struct crypto_skcipher *cipher,139const u8 *key, unsigned int keylen)140{141struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(cipher);142int err;143144err = verify_skcipher_des3_key(cipher, key);145if (err)146return err;147148ctx->keylen = keylen;149memcpy(ctx->key, key, keylen);150151return crypto_skcipher_setkey(ctx->fallback_tfm, key, keylen);152}153154static int rk_aes_ecb_encrypt(struct skcipher_request *req)155{156struct rk_cipher_rctx *rctx = skcipher_request_ctx(req);157158rctx->mode = RK_CRYPTO_AES_ECB_MODE;159return rk_cipher_handle_req(req);160}161162static int rk_aes_ecb_decrypt(struct skcipher_request *req)163{164struct rk_cipher_rctx *rctx = skcipher_request_ctx(req);165166rctx->mode = RK_CRYPTO_AES_ECB_MODE | RK_CRYPTO_DEC;167return rk_cipher_handle_req(req);168}169170static int rk_aes_cbc_encrypt(struct skcipher_request *req)171{172struct rk_cipher_rctx *rctx = skcipher_request_ctx(req);173174rctx->mode = RK_CRYPTO_AES_CBC_MODE;175return rk_cipher_handle_req(req);176}177178static int rk_aes_cbc_decrypt(struct skcipher_request *req)179{180struct rk_cipher_rctx *rctx = skcipher_request_ctx(req);181182rctx->mode = RK_CRYPTO_AES_CBC_MODE | RK_CRYPTO_DEC;183return rk_cipher_handle_req(req);184}185186static int rk_des_ecb_encrypt(struct skcipher_request *req)187{188struct rk_cipher_rctx *rctx = skcipher_request_ctx(req);189190rctx->mode = 0;191return rk_cipher_handle_req(req);192}193194static int rk_des_ecb_decrypt(struct skcipher_request *req)195{196struct rk_cipher_rctx *rctx = skcipher_request_ctx(req);197198rctx->mode = RK_CRYPTO_DEC;199return rk_cipher_handle_req(req);200}201202static int rk_des_cbc_encrypt(struct skcipher_request *req)203{204struct rk_cipher_rctx *rctx = skcipher_request_ctx(req);205206rctx->mode = RK_CRYPTO_TDES_CHAINMODE_CBC;207return rk_cipher_handle_req(req);208}209210static int rk_des_cbc_decrypt(struct skcipher_request *req)211{212struct rk_cipher_rctx *rctx = skcipher_request_ctx(req);213214rctx->mode = RK_CRYPTO_TDES_CHAINMODE_CBC | RK_CRYPTO_DEC;215return rk_cipher_handle_req(req);216}217218static int rk_des3_ede_ecb_encrypt(struct skcipher_request *req)219{220struct rk_cipher_rctx *rctx = skcipher_request_ctx(req);221222rctx->mode = RK_CRYPTO_TDES_SELECT;223return rk_cipher_handle_req(req);224}225226static int rk_des3_ede_ecb_decrypt(struct skcipher_request *req)227{228struct rk_cipher_rctx *rctx = skcipher_request_ctx(req);229230rctx->mode = RK_CRYPTO_TDES_SELECT | RK_CRYPTO_DEC;231return rk_cipher_handle_req(req);232}233234static int rk_des3_ede_cbc_encrypt(struct skcipher_request *req)235{236struct rk_cipher_rctx *rctx = skcipher_request_ctx(req);237238rctx->mode = RK_CRYPTO_TDES_SELECT | RK_CRYPTO_TDES_CHAINMODE_CBC;239return rk_cipher_handle_req(req);240}241242static int rk_des3_ede_cbc_decrypt(struct skcipher_request *req)243{244struct rk_cipher_rctx *rctx = skcipher_request_ctx(req);245246rctx->mode = RK_CRYPTO_TDES_SELECT | RK_CRYPTO_TDES_CHAINMODE_CBC |247RK_CRYPTO_DEC;248return rk_cipher_handle_req(req);249}250251static void rk_cipher_hw_init(struct rk_crypto_info *dev, struct skcipher_request *req)252{253struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(req);254struct crypto_tfm *tfm = crypto_skcipher_tfm(cipher);255struct rk_cipher_rctx *rctx = skcipher_request_ctx(req);256struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(cipher);257u32 block, conf_reg = 0;258259block = crypto_tfm_alg_blocksize(tfm);260261if (block == DES_BLOCK_SIZE) {262rctx->mode |= RK_CRYPTO_TDES_FIFO_MODE |263RK_CRYPTO_TDES_BYTESWAP_KEY |264RK_CRYPTO_TDES_BYTESWAP_IV;265CRYPTO_WRITE(dev, RK_CRYPTO_TDES_CTRL, rctx->mode);266memcpy_toio(dev->reg + RK_CRYPTO_TDES_KEY1_0, ctx->key, ctx->keylen);267conf_reg = RK_CRYPTO_DESSEL;268} else {269rctx->mode |= RK_CRYPTO_AES_FIFO_MODE |270RK_CRYPTO_AES_KEY_CHANGE |271RK_CRYPTO_AES_BYTESWAP_KEY |272RK_CRYPTO_AES_BYTESWAP_IV;273if (ctx->keylen == AES_KEYSIZE_192)274rctx->mode |= RK_CRYPTO_AES_192BIT_key;275else if (ctx->keylen == AES_KEYSIZE_256)276rctx->mode |= RK_CRYPTO_AES_256BIT_key;277CRYPTO_WRITE(dev, RK_CRYPTO_AES_CTRL, rctx->mode);278memcpy_toio(dev->reg + RK_CRYPTO_AES_KEY_0, ctx->key, ctx->keylen);279}280conf_reg |= RK_CRYPTO_BYTESWAP_BTFIFO |281RK_CRYPTO_BYTESWAP_BRFIFO;282CRYPTO_WRITE(dev, RK_CRYPTO_CONF, conf_reg);283CRYPTO_WRITE(dev, RK_CRYPTO_INTENA,284RK_CRYPTO_BCDMA_ERR_ENA | RK_CRYPTO_BCDMA_DONE_ENA);285}286287static void crypto_dma_start(struct rk_crypto_info *dev,288struct scatterlist *sgs,289struct scatterlist *sgd, unsigned int todo)290{291CRYPTO_WRITE(dev, RK_CRYPTO_BRDMAS, sg_dma_address(sgs));292CRYPTO_WRITE(dev, RK_CRYPTO_BRDMAL, todo);293CRYPTO_WRITE(dev, RK_CRYPTO_BTDMAS, sg_dma_address(sgd));294CRYPTO_WRITE(dev, RK_CRYPTO_CTRL, RK_CRYPTO_BLOCK_START |295_SBF(RK_CRYPTO_BLOCK_START, 16));296}297298static int rk_cipher_run(struct crypto_engine *engine, void *async_req)299{300struct skcipher_request *areq = container_of(async_req, struct skcipher_request, base);301struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq);302struct rk_cipher_rctx *rctx = skcipher_request_ctx(areq);303struct scatterlist *sgs, *sgd;304int err = 0;305int ivsize = crypto_skcipher_ivsize(tfm);306int offset;307u8 iv[AES_BLOCK_SIZE];308u8 biv[AES_BLOCK_SIZE];309u8 *ivtouse = areq->iv;310unsigned int len = areq->cryptlen;311unsigned int todo;312struct skcipher_alg *alg = crypto_skcipher_alg(tfm);313struct rk_crypto_tmp *algt = container_of(alg, struct rk_crypto_tmp, alg.skcipher.base);314struct rk_crypto_info *rkc = rctx->dev;315316err = pm_runtime_resume_and_get(rkc->dev);317if (err)318return err;319320algt->stat_req++;321rkc->nreq++;322323ivsize = crypto_skcipher_ivsize(tfm);324if (areq->iv && crypto_skcipher_ivsize(tfm) > 0) {325if (rctx->mode & RK_CRYPTO_DEC) {326offset = areq->cryptlen - ivsize;327scatterwalk_map_and_copy(rctx->backup_iv, areq->src,328offset, ivsize, 0);329}330}331332sgs = areq->src;333sgd = areq->dst;334335while (sgs && sgd && len) {336if (!sgs->length) {337sgs = sg_next(sgs);338sgd = sg_next(sgd);339continue;340}341if (rctx->mode & RK_CRYPTO_DEC) {342/* we backup last block of source to be used as IV at next step */343offset = sgs->length - ivsize;344scatterwalk_map_and_copy(biv, sgs, offset, ivsize, 0);345}346if (sgs == sgd) {347err = dma_map_sg(rkc->dev, sgs, 1, DMA_BIDIRECTIONAL);348if (err <= 0) {349err = -EINVAL;350goto theend_iv;351}352} else {353err = dma_map_sg(rkc->dev, sgs, 1, DMA_TO_DEVICE);354if (err <= 0) {355err = -EINVAL;356goto theend_iv;357}358err = dma_map_sg(rkc->dev, sgd, 1, DMA_FROM_DEVICE);359if (err <= 0) {360err = -EINVAL;361goto theend_sgs;362}363}364err = 0;365rk_cipher_hw_init(rkc, areq);366if (ivsize) {367if (ivsize == DES_BLOCK_SIZE)368memcpy_toio(rkc->reg + RK_CRYPTO_TDES_IV_0, ivtouse, ivsize);369else370memcpy_toio(rkc->reg + RK_CRYPTO_AES_IV_0, ivtouse, ivsize);371}372reinit_completion(&rkc->complete);373rkc->status = 0;374375todo = min(sg_dma_len(sgs), len);376len -= todo;377crypto_dma_start(rkc, sgs, sgd, todo / 4);378wait_for_completion_interruptible_timeout(&rkc->complete,379msecs_to_jiffies(2000));380if (!rkc->status) {381dev_err(rkc->dev, "DMA timeout\n");382err = -EFAULT;383goto theend;384}385if (sgs == sgd) {386dma_unmap_sg(rkc->dev, sgs, 1, DMA_BIDIRECTIONAL);387} else {388dma_unmap_sg(rkc->dev, sgs, 1, DMA_TO_DEVICE);389dma_unmap_sg(rkc->dev, sgd, 1, DMA_FROM_DEVICE);390}391if (rctx->mode & RK_CRYPTO_DEC) {392memcpy(iv, biv, ivsize);393ivtouse = iv;394} else {395offset = sgd->length - ivsize;396scatterwalk_map_and_copy(iv, sgd, offset, ivsize, 0);397ivtouse = iv;398}399sgs = sg_next(sgs);400sgd = sg_next(sgd);401}402403if (areq->iv && ivsize > 0) {404offset = areq->cryptlen - ivsize;405if (rctx->mode & RK_CRYPTO_DEC) {406memcpy(areq->iv, rctx->backup_iv, ivsize);407memzero_explicit(rctx->backup_iv, ivsize);408} else {409scatterwalk_map_and_copy(areq->iv, areq->dst, offset,410ivsize, 0);411}412}413414theend:415pm_runtime_put_autosuspend(rkc->dev);416417local_bh_disable();418crypto_finalize_skcipher_request(engine, areq, err);419local_bh_enable();420return 0;421422theend_sgs:423if (sgs == sgd) {424dma_unmap_sg(rkc->dev, sgs, 1, DMA_BIDIRECTIONAL);425} else {426dma_unmap_sg(rkc->dev, sgs, 1, DMA_TO_DEVICE);427dma_unmap_sg(rkc->dev, sgd, 1, DMA_FROM_DEVICE);428}429theend_iv:430return err;431}432433static int rk_cipher_tfm_init(struct crypto_skcipher *tfm)434{435struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm);436const char *name = crypto_tfm_alg_name(&tfm->base);437struct skcipher_alg *alg = crypto_skcipher_alg(tfm);438struct rk_crypto_tmp *algt = container_of(alg, struct rk_crypto_tmp, alg.skcipher.base);439440ctx->fallback_tfm = crypto_alloc_skcipher(name, 0, CRYPTO_ALG_NEED_FALLBACK);441if (IS_ERR(ctx->fallback_tfm)) {442dev_err(algt->dev->dev, "ERROR: Cannot allocate fallback for %s %ld\n",443name, PTR_ERR(ctx->fallback_tfm));444return PTR_ERR(ctx->fallback_tfm);445}446447crypto_skcipher_set_reqsize(tfm, sizeof(struct rk_cipher_rctx) +448crypto_skcipher_reqsize(ctx->fallback_tfm));449450return 0;451}452453static void rk_cipher_tfm_exit(struct crypto_skcipher *tfm)454{455struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm);456457memzero_explicit(ctx->key, ctx->keylen);458crypto_free_skcipher(ctx->fallback_tfm);459}460461struct rk_crypto_tmp rk_ecb_aes_alg = {462.type = CRYPTO_ALG_TYPE_SKCIPHER,463.alg.skcipher.base = {464.base.cra_name = "ecb(aes)",465.base.cra_driver_name = "ecb-aes-rk",466.base.cra_priority = 300,467.base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK,468.base.cra_blocksize = AES_BLOCK_SIZE,469.base.cra_ctxsize = sizeof(struct rk_cipher_ctx),470.base.cra_alignmask = 0x0f,471.base.cra_module = THIS_MODULE,472473.init = rk_cipher_tfm_init,474.exit = rk_cipher_tfm_exit,475.min_keysize = AES_MIN_KEY_SIZE,476.max_keysize = AES_MAX_KEY_SIZE,477.setkey = rk_aes_setkey,478.encrypt = rk_aes_ecb_encrypt,479.decrypt = rk_aes_ecb_decrypt,480},481.alg.skcipher.op = {482.do_one_request = rk_cipher_run,483},484};485486struct rk_crypto_tmp rk_cbc_aes_alg = {487.type = CRYPTO_ALG_TYPE_SKCIPHER,488.alg.skcipher.base = {489.base.cra_name = "cbc(aes)",490.base.cra_driver_name = "cbc-aes-rk",491.base.cra_priority = 300,492.base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK,493.base.cra_blocksize = AES_BLOCK_SIZE,494.base.cra_ctxsize = sizeof(struct rk_cipher_ctx),495.base.cra_alignmask = 0x0f,496.base.cra_module = THIS_MODULE,497498.init = rk_cipher_tfm_init,499.exit = rk_cipher_tfm_exit,500.min_keysize = AES_MIN_KEY_SIZE,501.max_keysize = AES_MAX_KEY_SIZE,502.ivsize = AES_BLOCK_SIZE,503.setkey = rk_aes_setkey,504.encrypt = rk_aes_cbc_encrypt,505.decrypt = rk_aes_cbc_decrypt,506},507.alg.skcipher.op = {508.do_one_request = rk_cipher_run,509},510};511512struct rk_crypto_tmp rk_ecb_des_alg = {513.type = CRYPTO_ALG_TYPE_SKCIPHER,514.alg.skcipher.base = {515.base.cra_name = "ecb(des)",516.base.cra_driver_name = "ecb-des-rk",517.base.cra_priority = 300,518.base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK,519.base.cra_blocksize = DES_BLOCK_SIZE,520.base.cra_ctxsize = sizeof(struct rk_cipher_ctx),521.base.cra_alignmask = 0x07,522.base.cra_module = THIS_MODULE,523524.init = rk_cipher_tfm_init,525.exit = rk_cipher_tfm_exit,526.min_keysize = DES_KEY_SIZE,527.max_keysize = DES_KEY_SIZE,528.setkey = rk_des_setkey,529.encrypt = rk_des_ecb_encrypt,530.decrypt = rk_des_ecb_decrypt,531},532.alg.skcipher.op = {533.do_one_request = rk_cipher_run,534},535};536537struct rk_crypto_tmp rk_cbc_des_alg = {538.type = CRYPTO_ALG_TYPE_SKCIPHER,539.alg.skcipher.base = {540.base.cra_name = "cbc(des)",541.base.cra_driver_name = "cbc-des-rk",542.base.cra_priority = 300,543.base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK,544.base.cra_blocksize = DES_BLOCK_SIZE,545.base.cra_ctxsize = sizeof(struct rk_cipher_ctx),546.base.cra_alignmask = 0x07,547.base.cra_module = THIS_MODULE,548549.init = rk_cipher_tfm_init,550.exit = rk_cipher_tfm_exit,551.min_keysize = DES_KEY_SIZE,552.max_keysize = DES_KEY_SIZE,553.ivsize = DES_BLOCK_SIZE,554.setkey = rk_des_setkey,555.encrypt = rk_des_cbc_encrypt,556.decrypt = rk_des_cbc_decrypt,557},558.alg.skcipher.op = {559.do_one_request = rk_cipher_run,560},561};562563struct rk_crypto_tmp rk_ecb_des3_ede_alg = {564.type = CRYPTO_ALG_TYPE_SKCIPHER,565.alg.skcipher.base = {566.base.cra_name = "ecb(des3_ede)",567.base.cra_driver_name = "ecb-des3-ede-rk",568.base.cra_priority = 300,569.base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK,570.base.cra_blocksize = DES_BLOCK_SIZE,571.base.cra_ctxsize = sizeof(struct rk_cipher_ctx),572.base.cra_alignmask = 0x07,573.base.cra_module = THIS_MODULE,574575.init = rk_cipher_tfm_init,576.exit = rk_cipher_tfm_exit,577.min_keysize = DES3_EDE_KEY_SIZE,578.max_keysize = DES3_EDE_KEY_SIZE,579.setkey = rk_tdes_setkey,580.encrypt = rk_des3_ede_ecb_encrypt,581.decrypt = rk_des3_ede_ecb_decrypt,582},583.alg.skcipher.op = {584.do_one_request = rk_cipher_run,585},586};587588struct rk_crypto_tmp rk_cbc_des3_ede_alg = {589.type = CRYPTO_ALG_TYPE_SKCIPHER,590.alg.skcipher.base = {591.base.cra_name = "cbc(des3_ede)",592.base.cra_driver_name = "cbc-des3-ede-rk",593.base.cra_priority = 300,594.base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK,595.base.cra_blocksize = DES_BLOCK_SIZE,596.base.cra_ctxsize = sizeof(struct rk_cipher_ctx),597.base.cra_alignmask = 0x07,598.base.cra_module = THIS_MODULE,599600.init = rk_cipher_tfm_init,601.exit = rk_cipher_tfm_exit,602.min_keysize = DES3_EDE_KEY_SIZE,603.max_keysize = DES3_EDE_KEY_SIZE,604.ivsize = DES_BLOCK_SIZE,605.setkey = rk_tdes_setkey,606.encrypt = rk_des3_ede_cbc_encrypt,607.decrypt = rk_des3_ede_cbc_decrypt,608},609.alg.skcipher.op = {610.do_one_request = rk_cipher_run,611},612};613614615