18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci#include <linux/kernel.h> 38c2ecf20Sopenharmony_ci#include <linux/printk.h> 48c2ecf20Sopenharmony_ci#include <linux/crypto.h> 58c2ecf20Sopenharmony_ci#include <linux/rtnetlink.h> 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include <crypto/aead.h> 88c2ecf20Sopenharmony_ci#include <crypto/authenc.h> 98c2ecf20Sopenharmony_ci#include <crypto/des.h> 108c2ecf20Sopenharmony_ci#include <crypto/sha.h> 118c2ecf20Sopenharmony_ci#include <crypto/internal/aead.h> 128c2ecf20Sopenharmony_ci#include <crypto/scatterwalk.h> 138c2ecf20Sopenharmony_ci#include <crypto/gcm.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include "nitrox_dev.h" 168c2ecf20Sopenharmony_ci#include "nitrox_common.h" 178c2ecf20Sopenharmony_ci#include "nitrox_req.h" 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#define GCM_AES_SALT_SIZE 4 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ciunion gph_p3 { 228c2ecf20Sopenharmony_ci struct { 238c2ecf20Sopenharmony_ci#ifdef __BIG_ENDIAN_BITFIELD 248c2ecf20Sopenharmony_ci u16 iv_offset : 8; 258c2ecf20Sopenharmony_ci u16 auth_offset : 8; 268c2ecf20Sopenharmony_ci#else 278c2ecf20Sopenharmony_ci u16 auth_offset : 8; 288c2ecf20Sopenharmony_ci u16 iv_offset : 8; 298c2ecf20Sopenharmony_ci#endif 308c2ecf20Sopenharmony_ci }; 318c2ecf20Sopenharmony_ci u16 param; 328c2ecf20Sopenharmony_ci}; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_cistatic int nitrox_aes_gcm_setkey(struct crypto_aead *aead, const u8 *key, 358c2ecf20Sopenharmony_ci unsigned int keylen) 368c2ecf20Sopenharmony_ci{ 378c2ecf20Sopenharmony_ci int aes_keylen; 388c2ecf20Sopenharmony_ci struct nitrox_crypto_ctx *nctx = crypto_aead_ctx(aead); 398c2ecf20Sopenharmony_ci struct flexi_crypto_context *fctx; 408c2ecf20Sopenharmony_ci union fc_ctx_flags flags; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci aes_keylen = flexi_aes_keylen(keylen); 438c2ecf20Sopenharmony_ci if (aes_keylen < 0) 448c2ecf20Sopenharmony_ci return -EINVAL; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci /* fill crypto context */ 478c2ecf20Sopenharmony_ci fctx = nctx->u.fctx; 488c2ecf20Sopenharmony_ci flags.f = be64_to_cpu(fctx->flags.f); 498c2ecf20Sopenharmony_ci flags.w0.aes_keylen = aes_keylen; 508c2ecf20Sopenharmony_ci fctx->flags.f = cpu_to_be64(flags.f); 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci /* copy enc key to context */ 538c2ecf20Sopenharmony_ci memset(&fctx->crypto, 0, sizeof(fctx->crypto)); 548c2ecf20Sopenharmony_ci memcpy(fctx->crypto.u.key, key, keylen); 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci return 0; 578c2ecf20Sopenharmony_ci} 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_cistatic int nitrox_aead_setauthsize(struct crypto_aead *aead, 608c2ecf20Sopenharmony_ci unsigned int authsize) 618c2ecf20Sopenharmony_ci{ 628c2ecf20Sopenharmony_ci struct nitrox_crypto_ctx *nctx = crypto_aead_ctx(aead); 638c2ecf20Sopenharmony_ci struct flexi_crypto_context *fctx = nctx->u.fctx; 648c2ecf20Sopenharmony_ci union fc_ctx_flags flags; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci flags.f = be64_to_cpu(fctx->flags.f); 678c2ecf20Sopenharmony_ci flags.w0.mac_len = authsize; 688c2ecf20Sopenharmony_ci fctx->flags.f = cpu_to_be64(flags.f); 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci aead->authsize = authsize; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci return 0; 738c2ecf20Sopenharmony_ci} 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_cistatic int nitrox_aes_gcm_setauthsize(struct crypto_aead *aead, 768c2ecf20Sopenharmony_ci unsigned int authsize) 778c2ecf20Sopenharmony_ci{ 788c2ecf20Sopenharmony_ci switch (authsize) { 798c2ecf20Sopenharmony_ci case 4: 808c2ecf20Sopenharmony_ci case 8: 818c2ecf20Sopenharmony_ci case 12: 828c2ecf20Sopenharmony_ci case 13: 838c2ecf20Sopenharmony_ci case 14: 848c2ecf20Sopenharmony_ci case 15: 858c2ecf20Sopenharmony_ci case 16: 868c2ecf20Sopenharmony_ci break; 878c2ecf20Sopenharmony_ci default: 888c2ecf20Sopenharmony_ci return -EINVAL; 898c2ecf20Sopenharmony_ci } 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci return nitrox_aead_setauthsize(aead, authsize); 928c2ecf20Sopenharmony_ci} 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_cistatic int alloc_src_sglist(struct nitrox_kcrypt_request *nkreq, 958c2ecf20Sopenharmony_ci struct scatterlist *src, char *iv, int ivsize, 968c2ecf20Sopenharmony_ci int buflen) 978c2ecf20Sopenharmony_ci{ 988c2ecf20Sopenharmony_ci int nents = sg_nents_for_len(src, buflen); 998c2ecf20Sopenharmony_ci int ret; 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci if (nents < 0) 1028c2ecf20Sopenharmony_ci return nents; 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci /* IV entry */ 1058c2ecf20Sopenharmony_ci nents += 1; 1068c2ecf20Sopenharmony_ci /* Allocate buffer to hold IV and input scatterlist array */ 1078c2ecf20Sopenharmony_ci ret = alloc_src_req_buf(nkreq, nents, ivsize); 1088c2ecf20Sopenharmony_ci if (ret) 1098c2ecf20Sopenharmony_ci return ret; 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci nitrox_creq_copy_iv(nkreq->src, iv, ivsize); 1128c2ecf20Sopenharmony_ci nitrox_creq_set_src_sg(nkreq, nents, ivsize, src, buflen); 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci return 0; 1158c2ecf20Sopenharmony_ci} 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_cistatic int alloc_dst_sglist(struct nitrox_kcrypt_request *nkreq, 1188c2ecf20Sopenharmony_ci struct scatterlist *dst, int ivsize, int buflen) 1198c2ecf20Sopenharmony_ci{ 1208c2ecf20Sopenharmony_ci int nents = sg_nents_for_len(dst, buflen); 1218c2ecf20Sopenharmony_ci int ret; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci if (nents < 0) 1248c2ecf20Sopenharmony_ci return nents; 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci /* IV, ORH, COMPLETION entries */ 1278c2ecf20Sopenharmony_ci nents += 3; 1288c2ecf20Sopenharmony_ci /* Allocate buffer to hold ORH, COMPLETION and output scatterlist 1298c2ecf20Sopenharmony_ci * array 1308c2ecf20Sopenharmony_ci */ 1318c2ecf20Sopenharmony_ci ret = alloc_dst_req_buf(nkreq, nents); 1328c2ecf20Sopenharmony_ci if (ret) 1338c2ecf20Sopenharmony_ci return ret; 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci nitrox_creq_set_orh(nkreq); 1368c2ecf20Sopenharmony_ci nitrox_creq_set_comp(nkreq); 1378c2ecf20Sopenharmony_ci nitrox_creq_set_dst_sg(nkreq, nents, ivsize, dst, buflen); 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci return 0; 1408c2ecf20Sopenharmony_ci} 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_cistatic void free_src_sglist(struct nitrox_kcrypt_request *nkreq) 1438c2ecf20Sopenharmony_ci{ 1448c2ecf20Sopenharmony_ci kfree(nkreq->src); 1458c2ecf20Sopenharmony_ci} 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_cistatic void free_dst_sglist(struct nitrox_kcrypt_request *nkreq) 1488c2ecf20Sopenharmony_ci{ 1498c2ecf20Sopenharmony_ci kfree(nkreq->dst); 1508c2ecf20Sopenharmony_ci} 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_cistatic int nitrox_set_creq(struct nitrox_aead_rctx *rctx) 1538c2ecf20Sopenharmony_ci{ 1548c2ecf20Sopenharmony_ci struct se_crypto_request *creq = &rctx->nkreq.creq; 1558c2ecf20Sopenharmony_ci union gph_p3 param3; 1568c2ecf20Sopenharmony_ci int ret; 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci creq->flags = rctx->flags; 1598c2ecf20Sopenharmony_ci creq->gfp = (rctx->flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? GFP_KERNEL : 1608c2ecf20Sopenharmony_ci GFP_ATOMIC; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci creq->ctrl.value = 0; 1638c2ecf20Sopenharmony_ci creq->opcode = FLEXI_CRYPTO_ENCRYPT_HMAC; 1648c2ecf20Sopenharmony_ci creq->ctrl.s.arg = rctx->ctrl_arg; 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci creq->gph.param0 = cpu_to_be16(rctx->cryptlen); 1678c2ecf20Sopenharmony_ci creq->gph.param1 = cpu_to_be16(rctx->cryptlen + rctx->assoclen); 1688c2ecf20Sopenharmony_ci creq->gph.param2 = cpu_to_be16(rctx->ivsize + rctx->assoclen); 1698c2ecf20Sopenharmony_ci param3.iv_offset = 0; 1708c2ecf20Sopenharmony_ci param3.auth_offset = rctx->ivsize; 1718c2ecf20Sopenharmony_ci creq->gph.param3 = cpu_to_be16(param3.param); 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci creq->ctx_handle = rctx->ctx_handle; 1748c2ecf20Sopenharmony_ci creq->ctrl.s.ctxl = sizeof(struct flexi_crypto_context); 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci ret = alloc_src_sglist(&rctx->nkreq, rctx->src, rctx->iv, rctx->ivsize, 1778c2ecf20Sopenharmony_ci rctx->srclen); 1788c2ecf20Sopenharmony_ci if (ret) 1798c2ecf20Sopenharmony_ci return ret; 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci ret = alloc_dst_sglist(&rctx->nkreq, rctx->dst, rctx->ivsize, 1828c2ecf20Sopenharmony_ci rctx->dstlen); 1838c2ecf20Sopenharmony_ci if (ret) { 1848c2ecf20Sopenharmony_ci free_src_sglist(&rctx->nkreq); 1858c2ecf20Sopenharmony_ci return ret; 1868c2ecf20Sopenharmony_ci } 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci return 0; 1898c2ecf20Sopenharmony_ci} 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_cistatic void nitrox_aead_callback(void *arg, int err) 1928c2ecf20Sopenharmony_ci{ 1938c2ecf20Sopenharmony_ci struct aead_request *areq = arg; 1948c2ecf20Sopenharmony_ci struct nitrox_aead_rctx *rctx = aead_request_ctx(areq); 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci free_src_sglist(&rctx->nkreq); 1978c2ecf20Sopenharmony_ci free_dst_sglist(&rctx->nkreq); 1988c2ecf20Sopenharmony_ci if (err) { 1998c2ecf20Sopenharmony_ci pr_err_ratelimited("request failed status 0x%0x\n", err); 2008c2ecf20Sopenharmony_ci err = -EINVAL; 2018c2ecf20Sopenharmony_ci } 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci areq->base.complete(&areq->base, err); 2048c2ecf20Sopenharmony_ci} 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_cistatic inline bool nitrox_aes_gcm_assoclen_supported(unsigned int assoclen) 2078c2ecf20Sopenharmony_ci{ 2088c2ecf20Sopenharmony_ci if (assoclen <= 512) 2098c2ecf20Sopenharmony_ci return true; 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci return false; 2128c2ecf20Sopenharmony_ci} 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_cistatic int nitrox_aes_gcm_enc(struct aead_request *areq) 2158c2ecf20Sopenharmony_ci{ 2168c2ecf20Sopenharmony_ci struct crypto_aead *aead = crypto_aead_reqtfm(areq); 2178c2ecf20Sopenharmony_ci struct nitrox_crypto_ctx *nctx = crypto_aead_ctx(aead); 2188c2ecf20Sopenharmony_ci struct nitrox_aead_rctx *rctx = aead_request_ctx(areq); 2198c2ecf20Sopenharmony_ci struct se_crypto_request *creq = &rctx->nkreq.creq; 2208c2ecf20Sopenharmony_ci struct flexi_crypto_context *fctx = nctx->u.fctx; 2218c2ecf20Sopenharmony_ci int ret; 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci if (!nitrox_aes_gcm_assoclen_supported(areq->assoclen)) 2248c2ecf20Sopenharmony_ci return -EINVAL; 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci memcpy(fctx->crypto.iv, areq->iv, GCM_AES_SALT_SIZE); 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci rctx->cryptlen = areq->cryptlen; 2298c2ecf20Sopenharmony_ci rctx->assoclen = areq->assoclen; 2308c2ecf20Sopenharmony_ci rctx->srclen = areq->assoclen + areq->cryptlen; 2318c2ecf20Sopenharmony_ci rctx->dstlen = rctx->srclen + aead->authsize; 2328c2ecf20Sopenharmony_ci rctx->iv = &areq->iv[GCM_AES_SALT_SIZE]; 2338c2ecf20Sopenharmony_ci rctx->ivsize = GCM_AES_IV_SIZE - GCM_AES_SALT_SIZE; 2348c2ecf20Sopenharmony_ci rctx->flags = areq->base.flags; 2358c2ecf20Sopenharmony_ci rctx->ctx_handle = nctx->u.ctx_handle; 2368c2ecf20Sopenharmony_ci rctx->src = areq->src; 2378c2ecf20Sopenharmony_ci rctx->dst = areq->dst; 2388c2ecf20Sopenharmony_ci rctx->ctrl_arg = ENCRYPT; 2398c2ecf20Sopenharmony_ci ret = nitrox_set_creq(rctx); 2408c2ecf20Sopenharmony_ci if (ret) 2418c2ecf20Sopenharmony_ci return ret; 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci /* send the crypto request */ 2448c2ecf20Sopenharmony_ci return nitrox_process_se_request(nctx->ndev, creq, nitrox_aead_callback, 2458c2ecf20Sopenharmony_ci areq); 2468c2ecf20Sopenharmony_ci} 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_cistatic int nitrox_aes_gcm_dec(struct aead_request *areq) 2498c2ecf20Sopenharmony_ci{ 2508c2ecf20Sopenharmony_ci struct crypto_aead *aead = crypto_aead_reqtfm(areq); 2518c2ecf20Sopenharmony_ci struct nitrox_crypto_ctx *nctx = crypto_aead_ctx(aead); 2528c2ecf20Sopenharmony_ci struct nitrox_aead_rctx *rctx = aead_request_ctx(areq); 2538c2ecf20Sopenharmony_ci struct se_crypto_request *creq = &rctx->nkreq.creq; 2548c2ecf20Sopenharmony_ci struct flexi_crypto_context *fctx = nctx->u.fctx; 2558c2ecf20Sopenharmony_ci int ret; 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci if (!nitrox_aes_gcm_assoclen_supported(areq->assoclen)) 2588c2ecf20Sopenharmony_ci return -EINVAL; 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci memcpy(fctx->crypto.iv, areq->iv, GCM_AES_SALT_SIZE); 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci rctx->cryptlen = areq->cryptlen - aead->authsize; 2638c2ecf20Sopenharmony_ci rctx->assoclen = areq->assoclen; 2648c2ecf20Sopenharmony_ci rctx->srclen = areq->cryptlen + areq->assoclen; 2658c2ecf20Sopenharmony_ci rctx->dstlen = rctx->srclen - aead->authsize; 2668c2ecf20Sopenharmony_ci rctx->iv = &areq->iv[GCM_AES_SALT_SIZE]; 2678c2ecf20Sopenharmony_ci rctx->ivsize = GCM_AES_IV_SIZE - GCM_AES_SALT_SIZE; 2688c2ecf20Sopenharmony_ci rctx->flags = areq->base.flags; 2698c2ecf20Sopenharmony_ci rctx->ctx_handle = nctx->u.ctx_handle; 2708c2ecf20Sopenharmony_ci rctx->src = areq->src; 2718c2ecf20Sopenharmony_ci rctx->dst = areq->dst; 2728c2ecf20Sopenharmony_ci rctx->ctrl_arg = DECRYPT; 2738c2ecf20Sopenharmony_ci ret = nitrox_set_creq(rctx); 2748c2ecf20Sopenharmony_ci if (ret) 2758c2ecf20Sopenharmony_ci return ret; 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci /* send the crypto request */ 2788c2ecf20Sopenharmony_ci return nitrox_process_se_request(nctx->ndev, creq, nitrox_aead_callback, 2798c2ecf20Sopenharmony_ci areq); 2808c2ecf20Sopenharmony_ci} 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_cistatic int nitrox_aead_init(struct crypto_aead *aead) 2838c2ecf20Sopenharmony_ci{ 2848c2ecf20Sopenharmony_ci struct nitrox_crypto_ctx *nctx = crypto_aead_ctx(aead); 2858c2ecf20Sopenharmony_ci struct crypto_ctx_hdr *chdr; 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci /* get the first device */ 2888c2ecf20Sopenharmony_ci nctx->ndev = nitrox_get_first_device(); 2898c2ecf20Sopenharmony_ci if (!nctx->ndev) 2908c2ecf20Sopenharmony_ci return -ENODEV; 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci /* allocate nitrox crypto context */ 2938c2ecf20Sopenharmony_ci chdr = crypto_alloc_context(nctx->ndev); 2948c2ecf20Sopenharmony_ci if (!chdr) { 2958c2ecf20Sopenharmony_ci nitrox_put_device(nctx->ndev); 2968c2ecf20Sopenharmony_ci return -ENOMEM; 2978c2ecf20Sopenharmony_ci } 2988c2ecf20Sopenharmony_ci nctx->chdr = chdr; 2998c2ecf20Sopenharmony_ci nctx->u.ctx_handle = (uintptr_t)((u8 *)chdr->vaddr + 3008c2ecf20Sopenharmony_ci sizeof(struct ctx_hdr)); 3018c2ecf20Sopenharmony_ci nctx->u.fctx->flags.f = 0; 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci return 0; 3048c2ecf20Sopenharmony_ci} 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_cistatic int nitrox_gcm_common_init(struct crypto_aead *aead) 3078c2ecf20Sopenharmony_ci{ 3088c2ecf20Sopenharmony_ci int ret; 3098c2ecf20Sopenharmony_ci struct nitrox_crypto_ctx *nctx = crypto_aead_ctx(aead); 3108c2ecf20Sopenharmony_ci union fc_ctx_flags *flags; 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci ret = nitrox_aead_init(aead); 3138c2ecf20Sopenharmony_ci if (ret) 3148c2ecf20Sopenharmony_ci return ret; 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci flags = &nctx->u.fctx->flags; 3178c2ecf20Sopenharmony_ci flags->w0.cipher_type = CIPHER_AES_GCM; 3188c2ecf20Sopenharmony_ci flags->w0.hash_type = AUTH_NULL; 3198c2ecf20Sopenharmony_ci flags->w0.iv_source = IV_FROM_DPTR; 3208c2ecf20Sopenharmony_ci /* ask microcode to calculate ipad/opad */ 3218c2ecf20Sopenharmony_ci flags->w0.auth_input_type = 1; 3228c2ecf20Sopenharmony_ci flags->f = be64_to_cpu(flags->f); 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci return 0; 3258c2ecf20Sopenharmony_ci} 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_cistatic int nitrox_aes_gcm_init(struct crypto_aead *aead) 3288c2ecf20Sopenharmony_ci{ 3298c2ecf20Sopenharmony_ci int ret; 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci ret = nitrox_gcm_common_init(aead); 3328c2ecf20Sopenharmony_ci if (ret) 3338c2ecf20Sopenharmony_ci return ret; 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci crypto_aead_set_reqsize(aead, 3368c2ecf20Sopenharmony_ci sizeof(struct aead_request) + 3378c2ecf20Sopenharmony_ci sizeof(struct nitrox_aead_rctx)); 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci return 0; 3408c2ecf20Sopenharmony_ci} 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_cistatic void nitrox_aead_exit(struct crypto_aead *aead) 3438c2ecf20Sopenharmony_ci{ 3448c2ecf20Sopenharmony_ci struct nitrox_crypto_ctx *nctx = crypto_aead_ctx(aead); 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci /* free the nitrox crypto context */ 3478c2ecf20Sopenharmony_ci if (nctx->u.ctx_handle) { 3488c2ecf20Sopenharmony_ci struct flexi_crypto_context *fctx = nctx->u.fctx; 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci memzero_explicit(&fctx->crypto, sizeof(struct crypto_keys)); 3518c2ecf20Sopenharmony_ci memzero_explicit(&fctx->auth, sizeof(struct auth_keys)); 3528c2ecf20Sopenharmony_ci crypto_free_context((void *)nctx->chdr); 3538c2ecf20Sopenharmony_ci } 3548c2ecf20Sopenharmony_ci nitrox_put_device(nctx->ndev); 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci nctx->u.ctx_handle = 0; 3578c2ecf20Sopenharmony_ci nctx->ndev = NULL; 3588c2ecf20Sopenharmony_ci} 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_cistatic int nitrox_rfc4106_setkey(struct crypto_aead *aead, const u8 *key, 3618c2ecf20Sopenharmony_ci unsigned int keylen) 3628c2ecf20Sopenharmony_ci{ 3638c2ecf20Sopenharmony_ci struct nitrox_crypto_ctx *nctx = crypto_aead_ctx(aead); 3648c2ecf20Sopenharmony_ci struct flexi_crypto_context *fctx = nctx->u.fctx; 3658c2ecf20Sopenharmony_ci int ret; 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ci if (keylen < GCM_AES_SALT_SIZE) 3688c2ecf20Sopenharmony_ci return -EINVAL; 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci keylen -= GCM_AES_SALT_SIZE; 3718c2ecf20Sopenharmony_ci ret = nitrox_aes_gcm_setkey(aead, key, keylen); 3728c2ecf20Sopenharmony_ci if (ret) 3738c2ecf20Sopenharmony_ci return ret; 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ci memcpy(fctx->crypto.iv, key + keylen, GCM_AES_SALT_SIZE); 3768c2ecf20Sopenharmony_ci return 0; 3778c2ecf20Sopenharmony_ci} 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_cistatic int nitrox_rfc4106_setauthsize(struct crypto_aead *aead, 3808c2ecf20Sopenharmony_ci unsigned int authsize) 3818c2ecf20Sopenharmony_ci{ 3828c2ecf20Sopenharmony_ci switch (authsize) { 3838c2ecf20Sopenharmony_ci case 8: 3848c2ecf20Sopenharmony_ci case 12: 3858c2ecf20Sopenharmony_ci case 16: 3868c2ecf20Sopenharmony_ci break; 3878c2ecf20Sopenharmony_ci default: 3888c2ecf20Sopenharmony_ci return -EINVAL; 3898c2ecf20Sopenharmony_ci } 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci return nitrox_aead_setauthsize(aead, authsize); 3928c2ecf20Sopenharmony_ci} 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_cistatic int nitrox_rfc4106_set_aead_rctx_sglist(struct aead_request *areq) 3958c2ecf20Sopenharmony_ci{ 3968c2ecf20Sopenharmony_ci struct nitrox_rfc4106_rctx *rctx = aead_request_ctx(areq); 3978c2ecf20Sopenharmony_ci struct nitrox_aead_rctx *aead_rctx = &rctx->base; 3988c2ecf20Sopenharmony_ci unsigned int assoclen = areq->assoclen - GCM_RFC4106_IV_SIZE; 3998c2ecf20Sopenharmony_ci struct scatterlist *sg; 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci if (areq->assoclen != 16 && areq->assoclen != 20) 4028c2ecf20Sopenharmony_ci return -EINVAL; 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci scatterwalk_map_and_copy(rctx->assoc, areq->src, 0, assoclen, 0); 4058c2ecf20Sopenharmony_ci sg_init_table(rctx->src, 3); 4068c2ecf20Sopenharmony_ci sg_set_buf(rctx->src, rctx->assoc, assoclen); 4078c2ecf20Sopenharmony_ci sg = scatterwalk_ffwd(rctx->src + 1, areq->src, areq->assoclen); 4088c2ecf20Sopenharmony_ci if (sg != rctx->src + 1) 4098c2ecf20Sopenharmony_ci sg_chain(rctx->src, 2, sg); 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci if (areq->src != areq->dst) { 4128c2ecf20Sopenharmony_ci sg_init_table(rctx->dst, 3); 4138c2ecf20Sopenharmony_ci sg_set_buf(rctx->dst, rctx->assoc, assoclen); 4148c2ecf20Sopenharmony_ci sg = scatterwalk_ffwd(rctx->dst + 1, areq->dst, areq->assoclen); 4158c2ecf20Sopenharmony_ci if (sg != rctx->dst + 1) 4168c2ecf20Sopenharmony_ci sg_chain(rctx->dst, 2, sg); 4178c2ecf20Sopenharmony_ci } 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci aead_rctx->src = rctx->src; 4208c2ecf20Sopenharmony_ci aead_rctx->dst = (areq->src == areq->dst) ? rctx->src : rctx->dst; 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci return 0; 4238c2ecf20Sopenharmony_ci} 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_cistatic void nitrox_rfc4106_callback(void *arg, int err) 4268c2ecf20Sopenharmony_ci{ 4278c2ecf20Sopenharmony_ci struct aead_request *areq = arg; 4288c2ecf20Sopenharmony_ci struct nitrox_rfc4106_rctx *rctx = aead_request_ctx(areq); 4298c2ecf20Sopenharmony_ci struct nitrox_kcrypt_request *nkreq = &rctx->base.nkreq; 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci free_src_sglist(nkreq); 4328c2ecf20Sopenharmony_ci free_dst_sglist(nkreq); 4338c2ecf20Sopenharmony_ci if (err) { 4348c2ecf20Sopenharmony_ci pr_err_ratelimited("request failed status 0x%0x\n", err); 4358c2ecf20Sopenharmony_ci err = -EINVAL; 4368c2ecf20Sopenharmony_ci } 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci areq->base.complete(&areq->base, err); 4398c2ecf20Sopenharmony_ci} 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_cistatic int nitrox_rfc4106_enc(struct aead_request *areq) 4428c2ecf20Sopenharmony_ci{ 4438c2ecf20Sopenharmony_ci struct crypto_aead *aead = crypto_aead_reqtfm(areq); 4448c2ecf20Sopenharmony_ci struct nitrox_crypto_ctx *nctx = crypto_aead_ctx(aead); 4458c2ecf20Sopenharmony_ci struct nitrox_rfc4106_rctx *rctx = aead_request_ctx(areq); 4468c2ecf20Sopenharmony_ci struct nitrox_aead_rctx *aead_rctx = &rctx->base; 4478c2ecf20Sopenharmony_ci struct se_crypto_request *creq = &aead_rctx->nkreq.creq; 4488c2ecf20Sopenharmony_ci int ret; 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_ci aead_rctx->cryptlen = areq->cryptlen; 4518c2ecf20Sopenharmony_ci aead_rctx->assoclen = areq->assoclen - GCM_RFC4106_IV_SIZE; 4528c2ecf20Sopenharmony_ci aead_rctx->srclen = aead_rctx->assoclen + aead_rctx->cryptlen; 4538c2ecf20Sopenharmony_ci aead_rctx->dstlen = aead_rctx->srclen + aead->authsize; 4548c2ecf20Sopenharmony_ci aead_rctx->iv = areq->iv; 4558c2ecf20Sopenharmony_ci aead_rctx->ivsize = GCM_RFC4106_IV_SIZE; 4568c2ecf20Sopenharmony_ci aead_rctx->flags = areq->base.flags; 4578c2ecf20Sopenharmony_ci aead_rctx->ctx_handle = nctx->u.ctx_handle; 4588c2ecf20Sopenharmony_ci aead_rctx->ctrl_arg = ENCRYPT; 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci ret = nitrox_rfc4106_set_aead_rctx_sglist(areq); 4618c2ecf20Sopenharmony_ci if (ret) 4628c2ecf20Sopenharmony_ci return ret; 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_ci ret = nitrox_set_creq(aead_rctx); 4658c2ecf20Sopenharmony_ci if (ret) 4668c2ecf20Sopenharmony_ci return ret; 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci /* send the crypto request */ 4698c2ecf20Sopenharmony_ci return nitrox_process_se_request(nctx->ndev, creq, 4708c2ecf20Sopenharmony_ci nitrox_rfc4106_callback, areq); 4718c2ecf20Sopenharmony_ci} 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_cistatic int nitrox_rfc4106_dec(struct aead_request *areq) 4748c2ecf20Sopenharmony_ci{ 4758c2ecf20Sopenharmony_ci struct crypto_aead *aead = crypto_aead_reqtfm(areq); 4768c2ecf20Sopenharmony_ci struct nitrox_crypto_ctx *nctx = crypto_aead_ctx(aead); 4778c2ecf20Sopenharmony_ci struct nitrox_rfc4106_rctx *rctx = aead_request_ctx(areq); 4788c2ecf20Sopenharmony_ci struct nitrox_aead_rctx *aead_rctx = &rctx->base; 4798c2ecf20Sopenharmony_ci struct se_crypto_request *creq = &aead_rctx->nkreq.creq; 4808c2ecf20Sopenharmony_ci int ret; 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci aead_rctx->cryptlen = areq->cryptlen - aead->authsize; 4838c2ecf20Sopenharmony_ci aead_rctx->assoclen = areq->assoclen - GCM_RFC4106_IV_SIZE; 4848c2ecf20Sopenharmony_ci aead_rctx->srclen = 4858c2ecf20Sopenharmony_ci areq->cryptlen - GCM_RFC4106_IV_SIZE + areq->assoclen; 4868c2ecf20Sopenharmony_ci aead_rctx->dstlen = aead_rctx->srclen - aead->authsize; 4878c2ecf20Sopenharmony_ci aead_rctx->iv = areq->iv; 4888c2ecf20Sopenharmony_ci aead_rctx->ivsize = GCM_RFC4106_IV_SIZE; 4898c2ecf20Sopenharmony_ci aead_rctx->flags = areq->base.flags; 4908c2ecf20Sopenharmony_ci aead_rctx->ctx_handle = nctx->u.ctx_handle; 4918c2ecf20Sopenharmony_ci aead_rctx->ctrl_arg = DECRYPT; 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_ci ret = nitrox_rfc4106_set_aead_rctx_sglist(areq); 4948c2ecf20Sopenharmony_ci if (ret) 4958c2ecf20Sopenharmony_ci return ret; 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_ci ret = nitrox_set_creq(aead_rctx); 4988c2ecf20Sopenharmony_ci if (ret) 4998c2ecf20Sopenharmony_ci return ret; 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci /* send the crypto request */ 5028c2ecf20Sopenharmony_ci return nitrox_process_se_request(nctx->ndev, creq, 5038c2ecf20Sopenharmony_ci nitrox_rfc4106_callback, areq); 5048c2ecf20Sopenharmony_ci} 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_cistatic int nitrox_rfc4106_init(struct crypto_aead *aead) 5078c2ecf20Sopenharmony_ci{ 5088c2ecf20Sopenharmony_ci int ret; 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_ci ret = nitrox_gcm_common_init(aead); 5118c2ecf20Sopenharmony_ci if (ret) 5128c2ecf20Sopenharmony_ci return ret; 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ci crypto_aead_set_reqsize(aead, sizeof(struct aead_request) + 5158c2ecf20Sopenharmony_ci sizeof(struct nitrox_rfc4106_rctx)); 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_ci return 0; 5188c2ecf20Sopenharmony_ci} 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_cistatic struct aead_alg nitrox_aeads[] = { { 5218c2ecf20Sopenharmony_ci .base = { 5228c2ecf20Sopenharmony_ci .cra_name = "gcm(aes)", 5238c2ecf20Sopenharmony_ci .cra_driver_name = "n5_aes_gcm", 5248c2ecf20Sopenharmony_ci .cra_priority = PRIO, 5258c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY, 5268c2ecf20Sopenharmony_ci .cra_blocksize = 1, 5278c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct nitrox_crypto_ctx), 5288c2ecf20Sopenharmony_ci .cra_alignmask = 0, 5298c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 5308c2ecf20Sopenharmony_ci }, 5318c2ecf20Sopenharmony_ci .setkey = nitrox_aes_gcm_setkey, 5328c2ecf20Sopenharmony_ci .setauthsize = nitrox_aes_gcm_setauthsize, 5338c2ecf20Sopenharmony_ci .encrypt = nitrox_aes_gcm_enc, 5348c2ecf20Sopenharmony_ci .decrypt = nitrox_aes_gcm_dec, 5358c2ecf20Sopenharmony_ci .init = nitrox_aes_gcm_init, 5368c2ecf20Sopenharmony_ci .exit = nitrox_aead_exit, 5378c2ecf20Sopenharmony_ci .ivsize = GCM_AES_IV_SIZE, 5388c2ecf20Sopenharmony_ci .maxauthsize = AES_BLOCK_SIZE, 5398c2ecf20Sopenharmony_ci}, { 5408c2ecf20Sopenharmony_ci .base = { 5418c2ecf20Sopenharmony_ci .cra_name = "rfc4106(gcm(aes))", 5428c2ecf20Sopenharmony_ci .cra_driver_name = "n5_rfc4106", 5438c2ecf20Sopenharmony_ci .cra_priority = PRIO, 5448c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY, 5458c2ecf20Sopenharmony_ci .cra_blocksize = 1, 5468c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct nitrox_crypto_ctx), 5478c2ecf20Sopenharmony_ci .cra_alignmask = 0, 5488c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 5498c2ecf20Sopenharmony_ci }, 5508c2ecf20Sopenharmony_ci .setkey = nitrox_rfc4106_setkey, 5518c2ecf20Sopenharmony_ci .setauthsize = nitrox_rfc4106_setauthsize, 5528c2ecf20Sopenharmony_ci .encrypt = nitrox_rfc4106_enc, 5538c2ecf20Sopenharmony_ci .decrypt = nitrox_rfc4106_dec, 5548c2ecf20Sopenharmony_ci .init = nitrox_rfc4106_init, 5558c2ecf20Sopenharmony_ci .exit = nitrox_aead_exit, 5568c2ecf20Sopenharmony_ci .ivsize = GCM_RFC4106_IV_SIZE, 5578c2ecf20Sopenharmony_ci .maxauthsize = AES_BLOCK_SIZE, 5588c2ecf20Sopenharmony_ci} }; 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_ciint nitrox_register_aeads(void) 5618c2ecf20Sopenharmony_ci{ 5628c2ecf20Sopenharmony_ci return crypto_register_aeads(nitrox_aeads, ARRAY_SIZE(nitrox_aeads)); 5638c2ecf20Sopenharmony_ci} 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_civoid nitrox_unregister_aeads(void) 5668c2ecf20Sopenharmony_ci{ 5678c2ecf20Sopenharmony_ci crypto_unregister_aeads(nitrox_aeads, ARRAY_SIZE(nitrox_aeads)); 5688c2ecf20Sopenharmony_ci} 569