18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Cryptographic API. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Support for OMAP AES GCM HW acceleration. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright (c) 2016 Texas Instruments Incorporated 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/errno.h> 118c2ecf20Sopenharmony_ci#include <linux/scatterlist.h> 128c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h> 138c2ecf20Sopenharmony_ci#include <linux/dmaengine.h> 148c2ecf20Sopenharmony_ci#include <linux/omap-dma.h> 158c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 168c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h> 178c2ecf20Sopenharmony_ci#include <crypto/aes.h> 188c2ecf20Sopenharmony_ci#include <crypto/gcm.h> 198c2ecf20Sopenharmony_ci#include <crypto/scatterwalk.h> 208c2ecf20Sopenharmony_ci#include <crypto/skcipher.h> 218c2ecf20Sopenharmony_ci#include <crypto/internal/aead.h> 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#include "omap-crypto.h" 248c2ecf20Sopenharmony_ci#include "omap-aes.h" 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_cistatic int omap_aes_gcm_handle_queue(struct omap_aes_dev *dd, 278c2ecf20Sopenharmony_ci struct aead_request *req); 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_cistatic void omap_aes_gcm_finish_req(struct omap_aes_dev *dd, int ret) 308c2ecf20Sopenharmony_ci{ 318c2ecf20Sopenharmony_ci struct aead_request *req = dd->aead_req; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci dd->in_sg = NULL; 348c2ecf20Sopenharmony_ci dd->out_sg = NULL; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci crypto_finalize_aead_request(dd->engine, req, ret); 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci pm_runtime_mark_last_busy(dd->dev); 398c2ecf20Sopenharmony_ci pm_runtime_put_autosuspend(dd->dev); 408c2ecf20Sopenharmony_ci} 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_cistatic void omap_aes_gcm_done_task(struct omap_aes_dev *dd) 438c2ecf20Sopenharmony_ci{ 448c2ecf20Sopenharmony_ci u8 *tag; 458c2ecf20Sopenharmony_ci int alen, clen, i, ret = 0, nsg; 468c2ecf20Sopenharmony_ci struct omap_aes_reqctx *rctx; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci alen = ALIGN(dd->assoc_len, AES_BLOCK_SIZE); 498c2ecf20Sopenharmony_ci clen = ALIGN(dd->total, AES_BLOCK_SIZE); 508c2ecf20Sopenharmony_ci rctx = aead_request_ctx(dd->aead_req); 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci nsg = !!(dd->assoc_len && dd->total); 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci dma_sync_sg_for_device(dd->dev, dd->out_sg, dd->out_sg_len, 558c2ecf20Sopenharmony_ci DMA_FROM_DEVICE); 568c2ecf20Sopenharmony_ci dma_unmap_sg(dd->dev, dd->in_sg, dd->in_sg_len, DMA_TO_DEVICE); 578c2ecf20Sopenharmony_ci dma_unmap_sg(dd->dev, dd->out_sg, dd->out_sg_len, DMA_FROM_DEVICE); 588c2ecf20Sopenharmony_ci omap_aes_crypt_dma_stop(dd); 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci omap_crypto_cleanup(dd->out_sg, dd->orig_out, 618c2ecf20Sopenharmony_ci dd->aead_req->assoclen, dd->total, 628c2ecf20Sopenharmony_ci FLAGS_OUT_DATA_ST_SHIFT, dd->flags); 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci if (dd->flags & FLAGS_ENCRYPT) 658c2ecf20Sopenharmony_ci scatterwalk_map_and_copy(rctx->auth_tag, 668c2ecf20Sopenharmony_ci dd->aead_req->dst, 678c2ecf20Sopenharmony_ci dd->total + dd->aead_req->assoclen, 688c2ecf20Sopenharmony_ci dd->authsize, 1); 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci omap_crypto_cleanup(&dd->in_sgl[0], NULL, 0, alen, 718c2ecf20Sopenharmony_ci FLAGS_ASSOC_DATA_ST_SHIFT, dd->flags); 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci omap_crypto_cleanup(&dd->in_sgl[nsg], NULL, 0, clen, 748c2ecf20Sopenharmony_ci FLAGS_IN_DATA_ST_SHIFT, dd->flags); 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci if (!(dd->flags & FLAGS_ENCRYPT)) { 778c2ecf20Sopenharmony_ci tag = (u8 *)rctx->auth_tag; 788c2ecf20Sopenharmony_ci for (i = 0; i < dd->authsize; i++) { 798c2ecf20Sopenharmony_ci if (tag[i]) { 808c2ecf20Sopenharmony_ci ret = -EBADMSG; 818c2ecf20Sopenharmony_ci } 828c2ecf20Sopenharmony_ci } 838c2ecf20Sopenharmony_ci } 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci omap_aes_gcm_finish_req(dd, ret); 868c2ecf20Sopenharmony_ci} 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_cistatic int omap_aes_gcm_copy_buffers(struct omap_aes_dev *dd, 898c2ecf20Sopenharmony_ci struct aead_request *req) 908c2ecf20Sopenharmony_ci{ 918c2ecf20Sopenharmony_ci int alen, clen, cryptlen, assoclen, ret; 928c2ecf20Sopenharmony_ci struct crypto_aead *aead = crypto_aead_reqtfm(req); 938c2ecf20Sopenharmony_ci unsigned int authlen = crypto_aead_authsize(aead); 948c2ecf20Sopenharmony_ci struct scatterlist *tmp, sg_arr[2]; 958c2ecf20Sopenharmony_ci int nsg; 968c2ecf20Sopenharmony_ci u16 flags; 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci assoclen = req->assoclen; 998c2ecf20Sopenharmony_ci cryptlen = req->cryptlen; 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci if (dd->flags & FLAGS_RFC4106_GCM) 1028c2ecf20Sopenharmony_ci assoclen -= 8; 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci if (!(dd->flags & FLAGS_ENCRYPT)) 1058c2ecf20Sopenharmony_ci cryptlen -= authlen; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci alen = ALIGN(assoclen, AES_BLOCK_SIZE); 1088c2ecf20Sopenharmony_ci clen = ALIGN(cryptlen, AES_BLOCK_SIZE); 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci nsg = !!(assoclen && cryptlen); 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci omap_aes_clear_copy_flags(dd); 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci sg_init_table(dd->in_sgl, nsg + 1); 1158c2ecf20Sopenharmony_ci if (assoclen) { 1168c2ecf20Sopenharmony_ci tmp = req->src; 1178c2ecf20Sopenharmony_ci ret = omap_crypto_align_sg(&tmp, assoclen, 1188c2ecf20Sopenharmony_ci AES_BLOCK_SIZE, dd->in_sgl, 1198c2ecf20Sopenharmony_ci OMAP_CRYPTO_COPY_DATA | 1208c2ecf20Sopenharmony_ci OMAP_CRYPTO_ZERO_BUF | 1218c2ecf20Sopenharmony_ci OMAP_CRYPTO_FORCE_SINGLE_ENTRY, 1228c2ecf20Sopenharmony_ci FLAGS_ASSOC_DATA_ST_SHIFT, 1238c2ecf20Sopenharmony_ci &dd->flags); 1248c2ecf20Sopenharmony_ci if (ret) 1258c2ecf20Sopenharmony_ci return ret; 1268c2ecf20Sopenharmony_ci } 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci if (cryptlen) { 1298c2ecf20Sopenharmony_ci tmp = scatterwalk_ffwd(sg_arr, req->src, req->assoclen); 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci if (nsg) 1328c2ecf20Sopenharmony_ci sg_unmark_end(dd->in_sgl); 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci ret = omap_crypto_align_sg(&tmp, cryptlen, 1358c2ecf20Sopenharmony_ci AES_BLOCK_SIZE, &dd->in_sgl[nsg], 1368c2ecf20Sopenharmony_ci OMAP_CRYPTO_COPY_DATA | 1378c2ecf20Sopenharmony_ci OMAP_CRYPTO_ZERO_BUF | 1388c2ecf20Sopenharmony_ci OMAP_CRYPTO_FORCE_SINGLE_ENTRY, 1398c2ecf20Sopenharmony_ci FLAGS_IN_DATA_ST_SHIFT, 1408c2ecf20Sopenharmony_ci &dd->flags); 1418c2ecf20Sopenharmony_ci if (ret) 1428c2ecf20Sopenharmony_ci return ret; 1438c2ecf20Sopenharmony_ci } 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci dd->in_sg = dd->in_sgl; 1468c2ecf20Sopenharmony_ci dd->total = cryptlen; 1478c2ecf20Sopenharmony_ci dd->assoc_len = assoclen; 1488c2ecf20Sopenharmony_ci dd->authsize = authlen; 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci dd->out_sg = req->dst; 1518c2ecf20Sopenharmony_ci dd->orig_out = req->dst; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci dd->out_sg = scatterwalk_ffwd(sg_arr, req->dst, req->assoclen); 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci flags = 0; 1568c2ecf20Sopenharmony_ci if (req->src == req->dst || dd->out_sg == sg_arr) 1578c2ecf20Sopenharmony_ci flags |= OMAP_CRYPTO_FORCE_COPY; 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci if (cryptlen) { 1608c2ecf20Sopenharmony_ci ret = omap_crypto_align_sg(&dd->out_sg, cryptlen, 1618c2ecf20Sopenharmony_ci AES_BLOCK_SIZE, &dd->out_sgl, 1628c2ecf20Sopenharmony_ci flags, 1638c2ecf20Sopenharmony_ci FLAGS_OUT_DATA_ST_SHIFT, &dd->flags); 1648c2ecf20Sopenharmony_ci if (ret) 1658c2ecf20Sopenharmony_ci return ret; 1668c2ecf20Sopenharmony_ci } 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci dd->in_sg_len = sg_nents_for_len(dd->in_sg, alen + clen); 1698c2ecf20Sopenharmony_ci dd->out_sg_len = sg_nents_for_len(dd->out_sg, clen); 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci return 0; 1728c2ecf20Sopenharmony_ci} 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_cistatic int do_encrypt_iv(struct aead_request *req, u32 *tag, u32 *iv) 1758c2ecf20Sopenharmony_ci{ 1768c2ecf20Sopenharmony_ci struct omap_aes_gcm_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci aes_encrypt(&ctx->actx, (u8 *)tag, (u8 *)iv); 1798c2ecf20Sopenharmony_ci return 0; 1808c2ecf20Sopenharmony_ci} 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_civoid omap_aes_gcm_dma_out_callback(void *data) 1838c2ecf20Sopenharmony_ci{ 1848c2ecf20Sopenharmony_ci struct omap_aes_dev *dd = data; 1858c2ecf20Sopenharmony_ci struct omap_aes_reqctx *rctx; 1868c2ecf20Sopenharmony_ci int i, val; 1878c2ecf20Sopenharmony_ci u32 *auth_tag, tag[4]; 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci if (!(dd->flags & FLAGS_ENCRYPT)) 1908c2ecf20Sopenharmony_ci scatterwalk_map_and_copy(tag, dd->aead_req->src, 1918c2ecf20Sopenharmony_ci dd->total + dd->aead_req->assoclen, 1928c2ecf20Sopenharmony_ci dd->authsize, 0); 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci rctx = aead_request_ctx(dd->aead_req); 1958c2ecf20Sopenharmony_ci auth_tag = (u32 *)rctx->auth_tag; 1968c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) { 1978c2ecf20Sopenharmony_ci val = omap_aes_read(dd, AES_REG_TAG_N(dd, i)); 1988c2ecf20Sopenharmony_ci auth_tag[i] = val ^ auth_tag[i]; 1998c2ecf20Sopenharmony_ci if (!(dd->flags & FLAGS_ENCRYPT)) 2008c2ecf20Sopenharmony_ci auth_tag[i] = auth_tag[i] ^ tag[i]; 2018c2ecf20Sopenharmony_ci } 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci omap_aes_gcm_done_task(dd); 2048c2ecf20Sopenharmony_ci} 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_cistatic int omap_aes_gcm_handle_queue(struct omap_aes_dev *dd, 2078c2ecf20Sopenharmony_ci struct aead_request *req) 2088c2ecf20Sopenharmony_ci{ 2098c2ecf20Sopenharmony_ci if (req) 2108c2ecf20Sopenharmony_ci return crypto_transfer_aead_request_to_engine(dd->engine, req); 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci return 0; 2138c2ecf20Sopenharmony_ci} 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_cistatic int omap_aes_gcm_prepare_req(struct crypto_engine *engine, void *areq) 2168c2ecf20Sopenharmony_ci{ 2178c2ecf20Sopenharmony_ci struct aead_request *req = container_of(areq, struct aead_request, 2188c2ecf20Sopenharmony_ci base); 2198c2ecf20Sopenharmony_ci struct omap_aes_reqctx *rctx = aead_request_ctx(req); 2208c2ecf20Sopenharmony_ci struct omap_aes_dev *dd = rctx->dd; 2218c2ecf20Sopenharmony_ci struct omap_aes_gcm_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); 2228c2ecf20Sopenharmony_ci int err; 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci dd->aead_req = req; 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci rctx->mode &= FLAGS_MODE_MASK; 2278c2ecf20Sopenharmony_ci dd->flags = (dd->flags & ~FLAGS_MODE_MASK) | rctx->mode; 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci err = omap_aes_gcm_copy_buffers(dd, req); 2308c2ecf20Sopenharmony_ci if (err) 2318c2ecf20Sopenharmony_ci return err; 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci dd->ctx = &ctx->octx; 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci return omap_aes_write_ctrl(dd); 2368c2ecf20Sopenharmony_ci} 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_cistatic int omap_aes_gcm_crypt(struct aead_request *req, unsigned long mode) 2398c2ecf20Sopenharmony_ci{ 2408c2ecf20Sopenharmony_ci struct omap_aes_reqctx *rctx = aead_request_ctx(req); 2418c2ecf20Sopenharmony_ci struct crypto_aead *aead = crypto_aead_reqtfm(req); 2428c2ecf20Sopenharmony_ci unsigned int authlen = crypto_aead_authsize(aead); 2438c2ecf20Sopenharmony_ci struct omap_aes_dev *dd; 2448c2ecf20Sopenharmony_ci __be32 counter = cpu_to_be32(1); 2458c2ecf20Sopenharmony_ci int err, assoclen; 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci memset(rctx->auth_tag, 0, sizeof(rctx->auth_tag)); 2488c2ecf20Sopenharmony_ci memcpy(rctx->iv + GCM_AES_IV_SIZE, &counter, 4); 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci err = do_encrypt_iv(req, (u32 *)rctx->auth_tag, (u32 *)rctx->iv); 2518c2ecf20Sopenharmony_ci if (err) 2528c2ecf20Sopenharmony_ci return err; 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci if (mode & FLAGS_RFC4106_GCM) 2558c2ecf20Sopenharmony_ci assoclen = req->assoclen - 8; 2568c2ecf20Sopenharmony_ci else 2578c2ecf20Sopenharmony_ci assoclen = req->assoclen; 2588c2ecf20Sopenharmony_ci if (assoclen + req->cryptlen == 0) { 2598c2ecf20Sopenharmony_ci scatterwalk_map_and_copy(rctx->auth_tag, req->dst, 0, authlen, 2608c2ecf20Sopenharmony_ci 1); 2618c2ecf20Sopenharmony_ci return 0; 2628c2ecf20Sopenharmony_ci } 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci dd = omap_aes_find_dev(rctx); 2658c2ecf20Sopenharmony_ci if (!dd) 2668c2ecf20Sopenharmony_ci return -ENODEV; 2678c2ecf20Sopenharmony_ci rctx->mode = mode; 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci return omap_aes_gcm_handle_queue(dd, req); 2708c2ecf20Sopenharmony_ci} 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ciint omap_aes_gcm_encrypt(struct aead_request *req) 2738c2ecf20Sopenharmony_ci{ 2748c2ecf20Sopenharmony_ci struct omap_aes_reqctx *rctx = aead_request_ctx(req); 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci memcpy(rctx->iv, req->iv, GCM_AES_IV_SIZE); 2778c2ecf20Sopenharmony_ci return omap_aes_gcm_crypt(req, FLAGS_ENCRYPT | FLAGS_GCM); 2788c2ecf20Sopenharmony_ci} 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ciint omap_aes_gcm_decrypt(struct aead_request *req) 2818c2ecf20Sopenharmony_ci{ 2828c2ecf20Sopenharmony_ci struct omap_aes_reqctx *rctx = aead_request_ctx(req); 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci memcpy(rctx->iv, req->iv, GCM_AES_IV_SIZE); 2858c2ecf20Sopenharmony_ci return omap_aes_gcm_crypt(req, FLAGS_GCM); 2868c2ecf20Sopenharmony_ci} 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ciint omap_aes_4106gcm_encrypt(struct aead_request *req) 2898c2ecf20Sopenharmony_ci{ 2908c2ecf20Sopenharmony_ci struct omap_aes_gcm_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); 2918c2ecf20Sopenharmony_ci struct omap_aes_reqctx *rctx = aead_request_ctx(req); 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci memcpy(rctx->iv, ctx->octx.nonce, 4); 2948c2ecf20Sopenharmony_ci memcpy(rctx->iv + 4, req->iv, 8); 2958c2ecf20Sopenharmony_ci return crypto_ipsec_check_assoclen(req->assoclen) ?: 2968c2ecf20Sopenharmony_ci omap_aes_gcm_crypt(req, FLAGS_ENCRYPT | FLAGS_GCM | 2978c2ecf20Sopenharmony_ci FLAGS_RFC4106_GCM); 2988c2ecf20Sopenharmony_ci} 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ciint omap_aes_4106gcm_decrypt(struct aead_request *req) 3018c2ecf20Sopenharmony_ci{ 3028c2ecf20Sopenharmony_ci struct omap_aes_gcm_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); 3038c2ecf20Sopenharmony_ci struct omap_aes_reqctx *rctx = aead_request_ctx(req); 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci memcpy(rctx->iv, ctx->octx.nonce, 4); 3068c2ecf20Sopenharmony_ci memcpy(rctx->iv + 4, req->iv, 8); 3078c2ecf20Sopenharmony_ci return crypto_ipsec_check_assoclen(req->assoclen) ?: 3088c2ecf20Sopenharmony_ci omap_aes_gcm_crypt(req, FLAGS_GCM | FLAGS_RFC4106_GCM); 3098c2ecf20Sopenharmony_ci} 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ciint omap_aes_gcm_setkey(struct crypto_aead *tfm, const u8 *key, 3128c2ecf20Sopenharmony_ci unsigned int keylen) 3138c2ecf20Sopenharmony_ci{ 3148c2ecf20Sopenharmony_ci struct omap_aes_gcm_ctx *ctx = crypto_aead_ctx(tfm); 3158c2ecf20Sopenharmony_ci int ret; 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci ret = aes_expandkey(&ctx->actx, key, keylen); 3188c2ecf20Sopenharmony_ci if (ret) 3198c2ecf20Sopenharmony_ci return ret; 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci memcpy(ctx->octx.key, key, keylen); 3228c2ecf20Sopenharmony_ci ctx->octx.keylen = keylen; 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci return 0; 3258c2ecf20Sopenharmony_ci} 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ciint omap_aes_4106gcm_setkey(struct crypto_aead *tfm, const u8 *key, 3288c2ecf20Sopenharmony_ci unsigned int keylen) 3298c2ecf20Sopenharmony_ci{ 3308c2ecf20Sopenharmony_ci struct omap_aes_gcm_ctx *ctx = crypto_aead_ctx(tfm); 3318c2ecf20Sopenharmony_ci int ret; 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci if (keylen < 4) 3348c2ecf20Sopenharmony_ci return -EINVAL; 3358c2ecf20Sopenharmony_ci keylen -= 4; 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci ret = aes_expandkey(&ctx->actx, key, keylen); 3388c2ecf20Sopenharmony_ci if (ret) 3398c2ecf20Sopenharmony_ci return ret; 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci memcpy(ctx->octx.key, key, keylen); 3428c2ecf20Sopenharmony_ci memcpy(ctx->octx.nonce, key + keylen, 4); 3438c2ecf20Sopenharmony_ci ctx->octx.keylen = keylen; 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci return 0; 3468c2ecf20Sopenharmony_ci} 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ciint omap_aes_gcm_setauthsize(struct crypto_aead *tfm, unsigned int authsize) 3498c2ecf20Sopenharmony_ci{ 3508c2ecf20Sopenharmony_ci return crypto_gcm_check_authsize(authsize); 3518c2ecf20Sopenharmony_ci} 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ciint omap_aes_4106gcm_setauthsize(struct crypto_aead *parent, 3548c2ecf20Sopenharmony_ci unsigned int authsize) 3558c2ecf20Sopenharmony_ci{ 3568c2ecf20Sopenharmony_ci return crypto_rfc4106_check_authsize(authsize); 3578c2ecf20Sopenharmony_ci} 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_cistatic int omap_aes_gcm_crypt_req(struct crypto_engine *engine, void *areq) 3608c2ecf20Sopenharmony_ci{ 3618c2ecf20Sopenharmony_ci struct aead_request *req = container_of(areq, struct aead_request, 3628c2ecf20Sopenharmony_ci base); 3638c2ecf20Sopenharmony_ci struct omap_aes_reqctx *rctx = aead_request_ctx(req); 3648c2ecf20Sopenharmony_ci struct omap_aes_dev *dd = rctx->dd; 3658c2ecf20Sopenharmony_ci int ret = 0; 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ci if (!dd) 3688c2ecf20Sopenharmony_ci return -ENODEV; 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci if (dd->in_sg_len) 3718c2ecf20Sopenharmony_ci ret = omap_aes_crypt_dma_start(dd); 3728c2ecf20Sopenharmony_ci else 3738c2ecf20Sopenharmony_ci omap_aes_gcm_dma_out_callback(dd); 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ci return ret; 3768c2ecf20Sopenharmony_ci} 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ciint omap_aes_gcm_cra_init(struct crypto_aead *tfm) 3798c2ecf20Sopenharmony_ci{ 3808c2ecf20Sopenharmony_ci struct omap_aes_ctx *ctx = crypto_aead_ctx(tfm); 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci ctx->enginectx.op.prepare_request = omap_aes_gcm_prepare_req; 3838c2ecf20Sopenharmony_ci ctx->enginectx.op.unprepare_request = NULL; 3848c2ecf20Sopenharmony_ci ctx->enginectx.op.do_one_request = omap_aes_gcm_crypt_req; 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci crypto_aead_set_reqsize(tfm, sizeof(struct omap_aes_reqctx)); 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ci return 0; 3898c2ecf20Sopenharmony_ci} 390