162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Xilinx ZynqMP AES Driver. 462306a36Sopenharmony_ci * Copyright (c) 2020 Xilinx Inc. 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <crypto/aes.h> 862306a36Sopenharmony_ci#include <crypto/engine.h> 962306a36Sopenharmony_ci#include <crypto/gcm.h> 1062306a36Sopenharmony_ci#include <crypto/internal/aead.h> 1162306a36Sopenharmony_ci#include <crypto/scatterwalk.h> 1262306a36Sopenharmony_ci#include <linux/dma-mapping.h> 1362306a36Sopenharmony_ci#include <linux/err.h> 1462306a36Sopenharmony_ci#include <linux/firmware/xlnx-zynqmp.h> 1562306a36Sopenharmony_ci#include <linux/kernel.h> 1662306a36Sopenharmony_ci#include <linux/module.h> 1762306a36Sopenharmony_ci#include <linux/mod_devicetable.h> 1862306a36Sopenharmony_ci#include <linux/platform_device.h> 1962306a36Sopenharmony_ci#include <linux/string.h> 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#define ZYNQMP_DMA_BIT_MASK 32U 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#define ZYNQMP_AES_KEY_SIZE AES_KEYSIZE_256 2462306a36Sopenharmony_ci#define ZYNQMP_AES_AUTH_SIZE 16U 2562306a36Sopenharmony_ci#define ZYNQMP_KEY_SRC_SEL_KEY_LEN 1U 2662306a36Sopenharmony_ci#define ZYNQMP_AES_BLK_SIZE 1U 2762306a36Sopenharmony_ci#define ZYNQMP_AES_MIN_INPUT_BLK_SIZE 4U 2862306a36Sopenharmony_ci#define ZYNQMP_AES_WORD_LEN 4U 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#define ZYNQMP_AES_GCM_TAG_MISMATCH_ERR 0x01 3162306a36Sopenharmony_ci#define ZYNQMP_AES_WRONG_KEY_SRC_ERR 0x13 3262306a36Sopenharmony_ci#define ZYNQMP_AES_PUF_NOT_PROGRAMMED 0xE300 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cienum zynqmp_aead_op { 3562306a36Sopenharmony_ci ZYNQMP_AES_DECRYPT = 0, 3662306a36Sopenharmony_ci ZYNQMP_AES_ENCRYPT 3762306a36Sopenharmony_ci}; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cienum zynqmp_aead_keysrc { 4062306a36Sopenharmony_ci ZYNQMP_AES_KUP_KEY = 0, 4162306a36Sopenharmony_ci ZYNQMP_AES_DEV_KEY, 4262306a36Sopenharmony_ci ZYNQMP_AES_PUF_KEY 4362306a36Sopenharmony_ci}; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_cistruct zynqmp_aead_drv_ctx { 4662306a36Sopenharmony_ci union { 4762306a36Sopenharmony_ci struct aead_engine_alg aead; 4862306a36Sopenharmony_ci } alg; 4962306a36Sopenharmony_ci struct device *dev; 5062306a36Sopenharmony_ci struct crypto_engine *engine; 5162306a36Sopenharmony_ci}; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_cistruct zynqmp_aead_hw_req { 5462306a36Sopenharmony_ci u64 src; 5562306a36Sopenharmony_ci u64 iv; 5662306a36Sopenharmony_ci u64 key; 5762306a36Sopenharmony_ci u64 dst; 5862306a36Sopenharmony_ci u64 size; 5962306a36Sopenharmony_ci u64 op; 6062306a36Sopenharmony_ci u64 keysrc; 6162306a36Sopenharmony_ci}; 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_cistruct zynqmp_aead_tfm_ctx { 6462306a36Sopenharmony_ci struct device *dev; 6562306a36Sopenharmony_ci u8 key[ZYNQMP_AES_KEY_SIZE]; 6662306a36Sopenharmony_ci u8 *iv; 6762306a36Sopenharmony_ci u32 keylen; 6862306a36Sopenharmony_ci u32 authsize; 6962306a36Sopenharmony_ci enum zynqmp_aead_keysrc keysrc; 7062306a36Sopenharmony_ci struct crypto_aead *fbk_cipher; 7162306a36Sopenharmony_ci}; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_cistruct zynqmp_aead_req_ctx { 7462306a36Sopenharmony_ci enum zynqmp_aead_op op; 7562306a36Sopenharmony_ci}; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_cistatic int zynqmp_aes_aead_cipher(struct aead_request *req) 7862306a36Sopenharmony_ci{ 7962306a36Sopenharmony_ci struct crypto_aead *aead = crypto_aead_reqtfm(req); 8062306a36Sopenharmony_ci struct zynqmp_aead_tfm_ctx *tfm_ctx = crypto_aead_ctx(aead); 8162306a36Sopenharmony_ci struct zynqmp_aead_req_ctx *rq_ctx = aead_request_ctx(req); 8262306a36Sopenharmony_ci struct device *dev = tfm_ctx->dev; 8362306a36Sopenharmony_ci struct zynqmp_aead_hw_req *hwreq; 8462306a36Sopenharmony_ci dma_addr_t dma_addr_data, dma_addr_hw_req; 8562306a36Sopenharmony_ci unsigned int data_size; 8662306a36Sopenharmony_ci unsigned int status; 8762306a36Sopenharmony_ci int ret; 8862306a36Sopenharmony_ci size_t dma_size; 8962306a36Sopenharmony_ci char *kbuf; 9062306a36Sopenharmony_ci int err; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci if (tfm_ctx->keysrc == ZYNQMP_AES_KUP_KEY) 9362306a36Sopenharmony_ci dma_size = req->cryptlen + ZYNQMP_AES_KEY_SIZE 9462306a36Sopenharmony_ci + GCM_AES_IV_SIZE; 9562306a36Sopenharmony_ci else 9662306a36Sopenharmony_ci dma_size = req->cryptlen + GCM_AES_IV_SIZE; 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci kbuf = dma_alloc_coherent(dev, dma_size, &dma_addr_data, GFP_KERNEL); 9962306a36Sopenharmony_ci if (!kbuf) 10062306a36Sopenharmony_ci return -ENOMEM; 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci hwreq = dma_alloc_coherent(dev, sizeof(struct zynqmp_aead_hw_req), 10362306a36Sopenharmony_ci &dma_addr_hw_req, GFP_KERNEL); 10462306a36Sopenharmony_ci if (!hwreq) { 10562306a36Sopenharmony_ci dma_free_coherent(dev, dma_size, kbuf, dma_addr_data); 10662306a36Sopenharmony_ci return -ENOMEM; 10762306a36Sopenharmony_ci } 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci data_size = req->cryptlen; 11062306a36Sopenharmony_ci scatterwalk_map_and_copy(kbuf, req->src, 0, req->cryptlen, 0); 11162306a36Sopenharmony_ci memcpy(kbuf + data_size, req->iv, GCM_AES_IV_SIZE); 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci hwreq->src = dma_addr_data; 11462306a36Sopenharmony_ci hwreq->dst = dma_addr_data; 11562306a36Sopenharmony_ci hwreq->iv = hwreq->src + data_size; 11662306a36Sopenharmony_ci hwreq->keysrc = tfm_ctx->keysrc; 11762306a36Sopenharmony_ci hwreq->op = rq_ctx->op; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci if (hwreq->op == ZYNQMP_AES_ENCRYPT) 12062306a36Sopenharmony_ci hwreq->size = data_size; 12162306a36Sopenharmony_ci else 12262306a36Sopenharmony_ci hwreq->size = data_size - ZYNQMP_AES_AUTH_SIZE; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci if (hwreq->keysrc == ZYNQMP_AES_KUP_KEY) { 12562306a36Sopenharmony_ci memcpy(kbuf + data_size + GCM_AES_IV_SIZE, 12662306a36Sopenharmony_ci tfm_ctx->key, ZYNQMP_AES_KEY_SIZE); 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci hwreq->key = hwreq->src + data_size + GCM_AES_IV_SIZE; 12962306a36Sopenharmony_ci } else { 13062306a36Sopenharmony_ci hwreq->key = 0; 13162306a36Sopenharmony_ci } 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci ret = zynqmp_pm_aes_engine(dma_addr_hw_req, &status); 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci if (ret) { 13662306a36Sopenharmony_ci dev_err(dev, "ERROR: AES PM API failed\n"); 13762306a36Sopenharmony_ci err = ret; 13862306a36Sopenharmony_ci } else if (status) { 13962306a36Sopenharmony_ci switch (status) { 14062306a36Sopenharmony_ci case ZYNQMP_AES_GCM_TAG_MISMATCH_ERR: 14162306a36Sopenharmony_ci dev_err(dev, "ERROR: Gcm Tag mismatch\n"); 14262306a36Sopenharmony_ci break; 14362306a36Sopenharmony_ci case ZYNQMP_AES_WRONG_KEY_SRC_ERR: 14462306a36Sopenharmony_ci dev_err(dev, "ERROR: Wrong KeySrc, enable secure mode\n"); 14562306a36Sopenharmony_ci break; 14662306a36Sopenharmony_ci case ZYNQMP_AES_PUF_NOT_PROGRAMMED: 14762306a36Sopenharmony_ci dev_err(dev, "ERROR: PUF is not registered\n"); 14862306a36Sopenharmony_ci break; 14962306a36Sopenharmony_ci default: 15062306a36Sopenharmony_ci dev_err(dev, "ERROR: Unknown error\n"); 15162306a36Sopenharmony_ci break; 15262306a36Sopenharmony_ci } 15362306a36Sopenharmony_ci err = -status; 15462306a36Sopenharmony_ci } else { 15562306a36Sopenharmony_ci if (hwreq->op == ZYNQMP_AES_ENCRYPT) 15662306a36Sopenharmony_ci data_size = data_size + ZYNQMP_AES_AUTH_SIZE; 15762306a36Sopenharmony_ci else 15862306a36Sopenharmony_ci data_size = data_size - ZYNQMP_AES_AUTH_SIZE; 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci sg_copy_from_buffer(req->dst, sg_nents(req->dst), 16162306a36Sopenharmony_ci kbuf, data_size); 16262306a36Sopenharmony_ci err = 0; 16362306a36Sopenharmony_ci } 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci if (kbuf) { 16662306a36Sopenharmony_ci memzero_explicit(kbuf, dma_size); 16762306a36Sopenharmony_ci dma_free_coherent(dev, dma_size, kbuf, dma_addr_data); 16862306a36Sopenharmony_ci } 16962306a36Sopenharmony_ci if (hwreq) { 17062306a36Sopenharmony_ci memzero_explicit(hwreq, sizeof(struct zynqmp_aead_hw_req)); 17162306a36Sopenharmony_ci dma_free_coherent(dev, sizeof(struct zynqmp_aead_hw_req), 17262306a36Sopenharmony_ci hwreq, dma_addr_hw_req); 17362306a36Sopenharmony_ci } 17462306a36Sopenharmony_ci return err; 17562306a36Sopenharmony_ci} 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_cistatic int zynqmp_fallback_check(struct zynqmp_aead_tfm_ctx *tfm_ctx, 17862306a36Sopenharmony_ci struct aead_request *req) 17962306a36Sopenharmony_ci{ 18062306a36Sopenharmony_ci int need_fallback = 0; 18162306a36Sopenharmony_ci struct zynqmp_aead_req_ctx *rq_ctx = aead_request_ctx(req); 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci if (tfm_ctx->authsize != ZYNQMP_AES_AUTH_SIZE) 18462306a36Sopenharmony_ci need_fallback = 1; 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci if (tfm_ctx->keysrc == ZYNQMP_AES_KUP_KEY && 18762306a36Sopenharmony_ci tfm_ctx->keylen != ZYNQMP_AES_KEY_SIZE) { 18862306a36Sopenharmony_ci need_fallback = 1; 18962306a36Sopenharmony_ci } 19062306a36Sopenharmony_ci if (req->assoclen != 0 || 19162306a36Sopenharmony_ci req->cryptlen < ZYNQMP_AES_MIN_INPUT_BLK_SIZE) { 19262306a36Sopenharmony_ci need_fallback = 1; 19362306a36Sopenharmony_ci } 19462306a36Sopenharmony_ci if ((req->cryptlen % ZYNQMP_AES_WORD_LEN) != 0) 19562306a36Sopenharmony_ci need_fallback = 1; 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci if (rq_ctx->op == ZYNQMP_AES_DECRYPT && 19862306a36Sopenharmony_ci req->cryptlen <= ZYNQMP_AES_AUTH_SIZE) { 19962306a36Sopenharmony_ci need_fallback = 1; 20062306a36Sopenharmony_ci } 20162306a36Sopenharmony_ci return need_fallback; 20262306a36Sopenharmony_ci} 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_cistatic int zynqmp_handle_aes_req(struct crypto_engine *engine, 20562306a36Sopenharmony_ci void *req) 20662306a36Sopenharmony_ci{ 20762306a36Sopenharmony_ci struct aead_request *areq = 20862306a36Sopenharmony_ci container_of(req, struct aead_request, base); 20962306a36Sopenharmony_ci struct crypto_aead *aead = crypto_aead_reqtfm(req); 21062306a36Sopenharmony_ci struct zynqmp_aead_tfm_ctx *tfm_ctx = crypto_aead_ctx(aead); 21162306a36Sopenharmony_ci struct zynqmp_aead_req_ctx *rq_ctx = aead_request_ctx(areq); 21262306a36Sopenharmony_ci struct aead_request *subreq = aead_request_ctx(req); 21362306a36Sopenharmony_ci int need_fallback; 21462306a36Sopenharmony_ci int err; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci need_fallback = zynqmp_fallback_check(tfm_ctx, areq); 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci if (need_fallback) { 21962306a36Sopenharmony_ci aead_request_set_tfm(subreq, tfm_ctx->fbk_cipher); 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci aead_request_set_callback(subreq, areq->base.flags, 22262306a36Sopenharmony_ci NULL, NULL); 22362306a36Sopenharmony_ci aead_request_set_crypt(subreq, areq->src, areq->dst, 22462306a36Sopenharmony_ci areq->cryptlen, areq->iv); 22562306a36Sopenharmony_ci aead_request_set_ad(subreq, areq->assoclen); 22662306a36Sopenharmony_ci if (rq_ctx->op == ZYNQMP_AES_ENCRYPT) 22762306a36Sopenharmony_ci err = crypto_aead_encrypt(subreq); 22862306a36Sopenharmony_ci else 22962306a36Sopenharmony_ci err = crypto_aead_decrypt(subreq); 23062306a36Sopenharmony_ci } else { 23162306a36Sopenharmony_ci err = zynqmp_aes_aead_cipher(areq); 23262306a36Sopenharmony_ci } 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci local_bh_disable(); 23562306a36Sopenharmony_ci crypto_finalize_aead_request(engine, areq, err); 23662306a36Sopenharmony_ci local_bh_enable(); 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci return 0; 23962306a36Sopenharmony_ci} 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_cistatic int zynqmp_aes_aead_setkey(struct crypto_aead *aead, const u8 *key, 24262306a36Sopenharmony_ci unsigned int keylen) 24362306a36Sopenharmony_ci{ 24462306a36Sopenharmony_ci struct crypto_tfm *tfm = crypto_aead_tfm(aead); 24562306a36Sopenharmony_ci struct zynqmp_aead_tfm_ctx *tfm_ctx = 24662306a36Sopenharmony_ci (struct zynqmp_aead_tfm_ctx *)crypto_tfm_ctx(tfm); 24762306a36Sopenharmony_ci unsigned char keysrc; 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci if (keylen == ZYNQMP_KEY_SRC_SEL_KEY_LEN) { 25062306a36Sopenharmony_ci keysrc = *key; 25162306a36Sopenharmony_ci if (keysrc == ZYNQMP_AES_KUP_KEY || 25262306a36Sopenharmony_ci keysrc == ZYNQMP_AES_DEV_KEY || 25362306a36Sopenharmony_ci keysrc == ZYNQMP_AES_PUF_KEY) { 25462306a36Sopenharmony_ci tfm_ctx->keysrc = (enum zynqmp_aead_keysrc)keysrc; 25562306a36Sopenharmony_ci } else { 25662306a36Sopenharmony_ci tfm_ctx->keylen = keylen; 25762306a36Sopenharmony_ci } 25862306a36Sopenharmony_ci } else { 25962306a36Sopenharmony_ci tfm_ctx->keylen = keylen; 26062306a36Sopenharmony_ci if (keylen == ZYNQMP_AES_KEY_SIZE) { 26162306a36Sopenharmony_ci tfm_ctx->keysrc = ZYNQMP_AES_KUP_KEY; 26262306a36Sopenharmony_ci memcpy(tfm_ctx->key, key, keylen); 26362306a36Sopenharmony_ci } 26462306a36Sopenharmony_ci } 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci tfm_ctx->fbk_cipher->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK; 26762306a36Sopenharmony_ci tfm_ctx->fbk_cipher->base.crt_flags |= (aead->base.crt_flags & 26862306a36Sopenharmony_ci CRYPTO_TFM_REQ_MASK); 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci return crypto_aead_setkey(tfm_ctx->fbk_cipher, key, keylen); 27162306a36Sopenharmony_ci} 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_cistatic int zynqmp_aes_aead_setauthsize(struct crypto_aead *aead, 27462306a36Sopenharmony_ci unsigned int authsize) 27562306a36Sopenharmony_ci{ 27662306a36Sopenharmony_ci struct crypto_tfm *tfm = crypto_aead_tfm(aead); 27762306a36Sopenharmony_ci struct zynqmp_aead_tfm_ctx *tfm_ctx = 27862306a36Sopenharmony_ci (struct zynqmp_aead_tfm_ctx *)crypto_tfm_ctx(tfm); 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci tfm_ctx->authsize = authsize; 28162306a36Sopenharmony_ci return crypto_aead_setauthsize(tfm_ctx->fbk_cipher, authsize); 28262306a36Sopenharmony_ci} 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_cistatic int zynqmp_aes_aead_encrypt(struct aead_request *req) 28562306a36Sopenharmony_ci{ 28662306a36Sopenharmony_ci struct zynqmp_aead_drv_ctx *drv_ctx; 28762306a36Sopenharmony_ci struct crypto_aead *aead = crypto_aead_reqtfm(req); 28862306a36Sopenharmony_ci struct aead_alg *alg = crypto_aead_alg(aead); 28962306a36Sopenharmony_ci struct zynqmp_aead_req_ctx *rq_ctx = aead_request_ctx(req); 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci rq_ctx->op = ZYNQMP_AES_ENCRYPT; 29262306a36Sopenharmony_ci drv_ctx = container_of(alg, struct zynqmp_aead_drv_ctx, alg.aead.base); 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci return crypto_transfer_aead_request_to_engine(drv_ctx->engine, req); 29562306a36Sopenharmony_ci} 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_cistatic int zynqmp_aes_aead_decrypt(struct aead_request *req) 29862306a36Sopenharmony_ci{ 29962306a36Sopenharmony_ci struct zynqmp_aead_drv_ctx *drv_ctx; 30062306a36Sopenharmony_ci struct crypto_aead *aead = crypto_aead_reqtfm(req); 30162306a36Sopenharmony_ci struct aead_alg *alg = crypto_aead_alg(aead); 30262306a36Sopenharmony_ci struct zynqmp_aead_req_ctx *rq_ctx = aead_request_ctx(req); 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci rq_ctx->op = ZYNQMP_AES_DECRYPT; 30562306a36Sopenharmony_ci drv_ctx = container_of(alg, struct zynqmp_aead_drv_ctx, alg.aead.base); 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci return crypto_transfer_aead_request_to_engine(drv_ctx->engine, req); 30862306a36Sopenharmony_ci} 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_cistatic int zynqmp_aes_aead_init(struct crypto_aead *aead) 31162306a36Sopenharmony_ci{ 31262306a36Sopenharmony_ci struct crypto_tfm *tfm = crypto_aead_tfm(aead); 31362306a36Sopenharmony_ci struct zynqmp_aead_tfm_ctx *tfm_ctx = 31462306a36Sopenharmony_ci (struct zynqmp_aead_tfm_ctx *)crypto_tfm_ctx(tfm); 31562306a36Sopenharmony_ci struct zynqmp_aead_drv_ctx *drv_ctx; 31662306a36Sopenharmony_ci struct aead_alg *alg = crypto_aead_alg(aead); 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci drv_ctx = container_of(alg, struct zynqmp_aead_drv_ctx, alg.aead.base); 31962306a36Sopenharmony_ci tfm_ctx->dev = drv_ctx->dev; 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci tfm_ctx->fbk_cipher = crypto_alloc_aead(drv_ctx->alg.aead.base.base.cra_name, 32262306a36Sopenharmony_ci 0, 32362306a36Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK); 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci if (IS_ERR(tfm_ctx->fbk_cipher)) { 32662306a36Sopenharmony_ci pr_err("%s() Error: failed to allocate fallback for %s\n", 32762306a36Sopenharmony_ci __func__, drv_ctx->alg.aead.base.base.cra_name); 32862306a36Sopenharmony_ci return PTR_ERR(tfm_ctx->fbk_cipher); 32962306a36Sopenharmony_ci } 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci crypto_aead_set_reqsize(aead, 33262306a36Sopenharmony_ci max(sizeof(struct zynqmp_aead_req_ctx), 33362306a36Sopenharmony_ci sizeof(struct aead_request) + 33462306a36Sopenharmony_ci crypto_aead_reqsize(tfm_ctx->fbk_cipher))); 33562306a36Sopenharmony_ci return 0; 33662306a36Sopenharmony_ci} 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_cistatic void zynqmp_aes_aead_exit(struct crypto_aead *aead) 33962306a36Sopenharmony_ci{ 34062306a36Sopenharmony_ci struct crypto_tfm *tfm = crypto_aead_tfm(aead); 34162306a36Sopenharmony_ci struct zynqmp_aead_tfm_ctx *tfm_ctx = 34262306a36Sopenharmony_ci (struct zynqmp_aead_tfm_ctx *)crypto_tfm_ctx(tfm); 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci if (tfm_ctx->fbk_cipher) { 34562306a36Sopenharmony_ci crypto_free_aead(tfm_ctx->fbk_cipher); 34662306a36Sopenharmony_ci tfm_ctx->fbk_cipher = NULL; 34762306a36Sopenharmony_ci } 34862306a36Sopenharmony_ci memzero_explicit(tfm_ctx, sizeof(struct zynqmp_aead_tfm_ctx)); 34962306a36Sopenharmony_ci} 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_cistatic struct zynqmp_aead_drv_ctx aes_drv_ctx = { 35262306a36Sopenharmony_ci .alg.aead.base = { 35362306a36Sopenharmony_ci .setkey = zynqmp_aes_aead_setkey, 35462306a36Sopenharmony_ci .setauthsize = zynqmp_aes_aead_setauthsize, 35562306a36Sopenharmony_ci .encrypt = zynqmp_aes_aead_encrypt, 35662306a36Sopenharmony_ci .decrypt = zynqmp_aes_aead_decrypt, 35762306a36Sopenharmony_ci .init = zynqmp_aes_aead_init, 35862306a36Sopenharmony_ci .exit = zynqmp_aes_aead_exit, 35962306a36Sopenharmony_ci .ivsize = GCM_AES_IV_SIZE, 36062306a36Sopenharmony_ci .maxauthsize = ZYNQMP_AES_AUTH_SIZE, 36162306a36Sopenharmony_ci .base = { 36262306a36Sopenharmony_ci .cra_name = "gcm(aes)", 36362306a36Sopenharmony_ci .cra_driver_name = "xilinx-zynqmp-aes-gcm", 36462306a36Sopenharmony_ci .cra_priority = 200, 36562306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_TYPE_AEAD | 36662306a36Sopenharmony_ci CRYPTO_ALG_ASYNC | 36762306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 36862306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY | 36962306a36Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 37062306a36Sopenharmony_ci .cra_blocksize = ZYNQMP_AES_BLK_SIZE, 37162306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct zynqmp_aead_tfm_ctx), 37262306a36Sopenharmony_ci .cra_module = THIS_MODULE, 37362306a36Sopenharmony_ci } 37462306a36Sopenharmony_ci }, 37562306a36Sopenharmony_ci .alg.aead.op = { 37662306a36Sopenharmony_ci .do_one_request = zynqmp_handle_aes_req, 37762306a36Sopenharmony_ci }, 37862306a36Sopenharmony_ci}; 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_cistatic int zynqmp_aes_aead_probe(struct platform_device *pdev) 38162306a36Sopenharmony_ci{ 38262306a36Sopenharmony_ci struct device *dev = &pdev->dev; 38362306a36Sopenharmony_ci int err; 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci /* ZynqMP AES driver supports only one instance */ 38662306a36Sopenharmony_ci if (!aes_drv_ctx.dev) 38762306a36Sopenharmony_ci aes_drv_ctx.dev = dev; 38862306a36Sopenharmony_ci else 38962306a36Sopenharmony_ci return -ENODEV; 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(ZYNQMP_DMA_BIT_MASK)); 39262306a36Sopenharmony_ci if (err < 0) { 39362306a36Sopenharmony_ci dev_err(dev, "No usable DMA configuration\n"); 39462306a36Sopenharmony_ci return err; 39562306a36Sopenharmony_ci } 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci aes_drv_ctx.engine = crypto_engine_alloc_init(dev, 1); 39862306a36Sopenharmony_ci if (!aes_drv_ctx.engine) { 39962306a36Sopenharmony_ci dev_err(dev, "Cannot alloc AES engine\n"); 40062306a36Sopenharmony_ci err = -ENOMEM; 40162306a36Sopenharmony_ci goto err_engine; 40262306a36Sopenharmony_ci } 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci err = crypto_engine_start(aes_drv_ctx.engine); 40562306a36Sopenharmony_ci if (err) { 40662306a36Sopenharmony_ci dev_err(dev, "Cannot start AES engine\n"); 40762306a36Sopenharmony_ci goto err_engine; 40862306a36Sopenharmony_ci } 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci err = crypto_engine_register_aead(&aes_drv_ctx.alg.aead); 41162306a36Sopenharmony_ci if (err < 0) { 41262306a36Sopenharmony_ci dev_err(dev, "Failed to register AEAD alg.\n"); 41362306a36Sopenharmony_ci goto err_aead; 41462306a36Sopenharmony_ci } 41562306a36Sopenharmony_ci return 0; 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_cierr_aead: 41862306a36Sopenharmony_ci crypto_engine_unregister_aead(&aes_drv_ctx.alg.aead); 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_cierr_engine: 42162306a36Sopenharmony_ci if (aes_drv_ctx.engine) 42262306a36Sopenharmony_ci crypto_engine_exit(aes_drv_ctx.engine); 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci return err; 42562306a36Sopenharmony_ci} 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_cistatic int zynqmp_aes_aead_remove(struct platform_device *pdev) 42862306a36Sopenharmony_ci{ 42962306a36Sopenharmony_ci crypto_engine_exit(aes_drv_ctx.engine); 43062306a36Sopenharmony_ci crypto_engine_unregister_aead(&aes_drv_ctx.alg.aead); 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci return 0; 43362306a36Sopenharmony_ci} 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_cistatic const struct of_device_id zynqmp_aes_dt_ids[] = { 43662306a36Sopenharmony_ci { .compatible = "xlnx,zynqmp-aes" }, 43762306a36Sopenharmony_ci { /* sentinel */ } 43862306a36Sopenharmony_ci}; 43962306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, zynqmp_aes_dt_ids); 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_cistatic struct platform_driver zynqmp_aes_driver = { 44262306a36Sopenharmony_ci .probe = zynqmp_aes_aead_probe, 44362306a36Sopenharmony_ci .remove = zynqmp_aes_aead_remove, 44462306a36Sopenharmony_ci .driver = { 44562306a36Sopenharmony_ci .name = "zynqmp-aes", 44662306a36Sopenharmony_ci .of_match_table = zynqmp_aes_dt_ids, 44762306a36Sopenharmony_ci }, 44862306a36Sopenharmony_ci}; 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_cimodule_platform_driver(zynqmp_aes_driver); 45162306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 452