1c9613335SNagadheeraj Rottela // SPDX-License-Identifier: GPL-2.0 2c9613335SNagadheeraj Rottela #include <linux/kernel.h> 3c9613335SNagadheeraj Rottela #include <linux/printk.h> 4c9613335SNagadheeraj Rottela #include <linux/crypto.h> 5c9613335SNagadheeraj Rottela #include <linux/rtnetlink.h> 6c9613335SNagadheeraj Rottela 7c9613335SNagadheeraj Rottela #include <crypto/aead.h> 8c9613335SNagadheeraj Rottela #include <crypto/authenc.h> 9c9613335SNagadheeraj Rottela #include <crypto/des.h> 10c9613335SNagadheeraj Rottela #include <crypto/internal/aead.h> 11c9613335SNagadheeraj Rottela #include <crypto/scatterwalk.h> 12c9613335SNagadheeraj Rottela #include <crypto/gcm.h> 13c9613335SNagadheeraj Rottela 14c9613335SNagadheeraj Rottela #include "nitrox_dev.h" 15c9613335SNagadheeraj Rottela #include "nitrox_common.h" 16c9613335SNagadheeraj Rottela #include "nitrox_req.h" 17c9613335SNagadheeraj Rottela 18c9613335SNagadheeraj Rottela #define GCM_AES_SALT_SIZE 4 19c9613335SNagadheeraj Rottela 20c9613335SNagadheeraj Rottela union gph_p3 { 21c9613335SNagadheeraj Rottela struct { 22c9613335SNagadheeraj Rottela #ifdef __BIG_ENDIAN_BITFIELD 23c9613335SNagadheeraj Rottela u16 iv_offset : 8; 24c9613335SNagadheeraj Rottela u16 auth_offset : 8; 25c9613335SNagadheeraj Rottela #else 26c9613335SNagadheeraj Rottela u16 auth_offset : 8; 27c9613335SNagadheeraj Rottela u16 iv_offset : 8; 28c9613335SNagadheeraj Rottela #endif 29c9613335SNagadheeraj Rottela }; 30c9613335SNagadheeraj Rottela u16 param; 31c9613335SNagadheeraj Rottela }; 32c9613335SNagadheeraj Rottela 33c9613335SNagadheeraj Rottela static int nitrox_aes_gcm_setkey(struct crypto_aead *aead, const u8 *key, 34c9613335SNagadheeraj Rottela unsigned int keylen) 35c9613335SNagadheeraj Rottela { 36c9613335SNagadheeraj Rottela int aes_keylen; 37c9613335SNagadheeraj Rottela struct nitrox_crypto_ctx *nctx = crypto_aead_ctx(aead); 38c9613335SNagadheeraj Rottela struct flexi_crypto_context *fctx; 39c9613335SNagadheeraj Rottela union fc_ctx_flags flags; 40c9613335SNagadheeraj Rottela 41c9613335SNagadheeraj Rottela aes_keylen = flexi_aes_keylen(keylen); 42674f368aSEric Biggers if (aes_keylen < 0) 43c9613335SNagadheeraj Rottela return -EINVAL; 44c9613335SNagadheeraj Rottela 45c9613335SNagadheeraj Rottela /* fill crypto context */ 46c9613335SNagadheeraj Rottela fctx = nctx->u.fctx; 47cd078cb6SHerbert Xu flags.fu = be64_to_cpu(fctx->flags.f); 48c9613335SNagadheeraj Rottela flags.w0.aes_keylen = aes_keylen; 49cd078cb6SHerbert Xu fctx->flags.f = cpu_to_be64(flags.fu); 50c9613335SNagadheeraj Rottela 51c9613335SNagadheeraj Rottela /* copy enc key to context */ 52c9613335SNagadheeraj Rottela memset(&fctx->crypto, 0, sizeof(fctx->crypto)); 53c9613335SNagadheeraj Rottela memcpy(fctx->crypto.u.key, key, keylen); 54c9613335SNagadheeraj Rottela 55c9613335SNagadheeraj Rottela return 0; 56c9613335SNagadheeraj Rottela } 57c9613335SNagadheeraj Rottela 58c9613335SNagadheeraj Rottela static int nitrox_aead_setauthsize(struct crypto_aead *aead, 59c9613335SNagadheeraj Rottela unsigned int authsize) 60c9613335SNagadheeraj Rottela { 61c9613335SNagadheeraj Rottela struct nitrox_crypto_ctx *nctx = crypto_aead_ctx(aead); 62c9613335SNagadheeraj Rottela struct flexi_crypto_context *fctx = nctx->u.fctx; 63c9613335SNagadheeraj Rottela union fc_ctx_flags flags; 64c9613335SNagadheeraj Rottela 65cd078cb6SHerbert Xu flags.fu = be64_to_cpu(fctx->flags.f); 66c9613335SNagadheeraj Rottela flags.w0.mac_len = authsize; 67cd078cb6SHerbert Xu fctx->flags.f = cpu_to_be64(flags.fu); 68c9613335SNagadheeraj Rottela 69c9613335SNagadheeraj Rottela aead->authsize = authsize; 70c9613335SNagadheeraj Rottela 71c9613335SNagadheeraj Rottela return 0; 72c9613335SNagadheeraj Rottela } 73c9613335SNagadheeraj Rottela 743fed9baaSNagadheeraj Rottela static int nitrox_aes_gcm_setauthsize(struct crypto_aead *aead, 753fed9baaSNagadheeraj Rottela unsigned int authsize) 763fed9baaSNagadheeraj Rottela { 773fed9baaSNagadheeraj Rottela switch (authsize) { 783fed9baaSNagadheeraj Rottela case 4: 793fed9baaSNagadheeraj Rottela case 8: 803fed9baaSNagadheeraj Rottela case 12: 813fed9baaSNagadheeraj Rottela case 13: 823fed9baaSNagadheeraj Rottela case 14: 833fed9baaSNagadheeraj Rottela case 15: 843fed9baaSNagadheeraj Rottela case 16: 853fed9baaSNagadheeraj Rottela break; 863fed9baaSNagadheeraj Rottela default: 873fed9baaSNagadheeraj Rottela return -EINVAL; 883fed9baaSNagadheeraj Rottela } 893fed9baaSNagadheeraj Rottela 903fed9baaSNagadheeraj Rottela return nitrox_aead_setauthsize(aead, authsize); 913fed9baaSNagadheeraj Rottela } 923fed9baaSNagadheeraj Rottela 938a3719a5SNagadheeraj Rottela static int alloc_src_sglist(struct nitrox_kcrypt_request *nkreq, 948a3719a5SNagadheeraj Rottela struct scatterlist *src, char *iv, int ivsize, 95c9613335SNagadheeraj Rottela int buflen) 96c9613335SNagadheeraj Rottela { 978a3719a5SNagadheeraj Rottela int nents = sg_nents_for_len(src, buflen); 98c9613335SNagadheeraj Rottela int ret; 99c9613335SNagadheeraj Rottela 100c9613335SNagadheeraj Rottela if (nents < 0) 101c9613335SNagadheeraj Rottela return nents; 102c9613335SNagadheeraj Rottela 1038a3719a5SNagadheeraj Rottela /* IV entry */ 1048a3719a5SNagadheeraj Rottela nents += 1; 105c9613335SNagadheeraj Rottela /* Allocate buffer to hold IV and input scatterlist array */ 106c9613335SNagadheeraj Rottela ret = alloc_src_req_buf(nkreq, nents, ivsize); 107c9613335SNagadheeraj Rottela if (ret) 108c9613335SNagadheeraj Rottela return ret; 109c9613335SNagadheeraj Rottela 110c9613335SNagadheeraj Rottela nitrox_creq_copy_iv(nkreq->src, iv, ivsize); 1118a3719a5SNagadheeraj Rottela nitrox_creq_set_src_sg(nkreq, nents, ivsize, src, buflen); 112c9613335SNagadheeraj Rottela 113c9613335SNagadheeraj Rottela return 0; 114c9613335SNagadheeraj Rottela } 115c9613335SNagadheeraj Rottela 1168a3719a5SNagadheeraj Rottela static int alloc_dst_sglist(struct nitrox_kcrypt_request *nkreq, 1178a3719a5SNagadheeraj Rottela struct scatterlist *dst, int ivsize, int buflen) 118c9613335SNagadheeraj Rottela { 1198a3719a5SNagadheeraj Rottela int nents = sg_nents_for_len(dst, buflen); 120c9613335SNagadheeraj Rottela int ret; 121c9613335SNagadheeraj Rottela 122c9613335SNagadheeraj Rottela if (nents < 0) 123c9613335SNagadheeraj Rottela return nents; 124c9613335SNagadheeraj Rottela 1258a3719a5SNagadheeraj Rottela /* IV, ORH, COMPLETION entries */ 1268a3719a5SNagadheeraj Rottela nents += 3; 127c9613335SNagadheeraj Rottela /* Allocate buffer to hold ORH, COMPLETION and output scatterlist 128c9613335SNagadheeraj Rottela * array 129c9613335SNagadheeraj Rottela */ 130c9613335SNagadheeraj Rottela ret = alloc_dst_req_buf(nkreq, nents); 131c9613335SNagadheeraj Rottela if (ret) 132c9613335SNagadheeraj Rottela return ret; 133c9613335SNagadheeraj Rottela 134c9613335SNagadheeraj Rottela nitrox_creq_set_orh(nkreq); 135c9613335SNagadheeraj Rottela nitrox_creq_set_comp(nkreq); 1368a3719a5SNagadheeraj Rottela nitrox_creq_set_dst_sg(nkreq, nents, ivsize, dst, buflen); 137c9613335SNagadheeraj Rottela 138c9613335SNagadheeraj Rottela return 0; 139c9613335SNagadheeraj Rottela } 140c9613335SNagadheeraj Rottela 1418a3719a5SNagadheeraj Rottela static void free_src_sglist(struct nitrox_kcrypt_request *nkreq) 142c9613335SNagadheeraj Rottela { 143c9613335SNagadheeraj Rottela kfree(nkreq->src); 144c9613335SNagadheeraj Rottela } 145c9613335SNagadheeraj Rottela 1468a3719a5SNagadheeraj Rottela static void free_dst_sglist(struct nitrox_kcrypt_request *nkreq) 147c9613335SNagadheeraj Rottela { 148c9613335SNagadheeraj Rottela kfree(nkreq->dst); 149c9613335SNagadheeraj Rottela } 150c9613335SNagadheeraj Rottela 1518a3719a5SNagadheeraj Rottela static int nitrox_set_creq(struct nitrox_aead_rctx *rctx) 152c9613335SNagadheeraj Rottela { 1538a3719a5SNagadheeraj Rottela struct se_crypto_request *creq = &rctx->nkreq.creq; 154c9613335SNagadheeraj Rottela union gph_p3 param3; 155c9613335SNagadheeraj Rottela int ret; 156c9613335SNagadheeraj Rottela 1578a3719a5SNagadheeraj Rottela creq->flags = rctx->flags; 1588a3719a5SNagadheeraj Rottela creq->gfp = (rctx->flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? GFP_KERNEL : 1598a3719a5SNagadheeraj Rottela GFP_ATOMIC; 160c9613335SNagadheeraj Rottela 161c9613335SNagadheeraj Rottela creq->ctrl.value = 0; 162c9613335SNagadheeraj Rottela creq->opcode = FLEXI_CRYPTO_ENCRYPT_HMAC; 1638a3719a5SNagadheeraj Rottela creq->ctrl.s.arg = rctx->ctrl_arg; 164c9613335SNagadheeraj Rottela 1658a3719a5SNagadheeraj Rottela creq->gph.param0 = cpu_to_be16(rctx->cryptlen); 1668a3719a5SNagadheeraj Rottela creq->gph.param1 = cpu_to_be16(rctx->cryptlen + rctx->assoclen); 1678a3719a5SNagadheeraj Rottela creq->gph.param2 = cpu_to_be16(rctx->ivsize + rctx->assoclen); 168c9613335SNagadheeraj Rottela param3.iv_offset = 0; 1698a3719a5SNagadheeraj Rottela param3.auth_offset = rctx->ivsize; 170c9613335SNagadheeraj Rottela creq->gph.param3 = cpu_to_be16(param3.param); 171c9613335SNagadheeraj Rottela 1728a3719a5SNagadheeraj Rottela creq->ctx_handle = rctx->ctx_handle; 173c9613335SNagadheeraj Rottela creq->ctrl.s.ctxl = sizeof(struct flexi_crypto_context); 174c9613335SNagadheeraj Rottela 1758a3719a5SNagadheeraj Rottela ret = alloc_src_sglist(&rctx->nkreq, rctx->src, rctx->iv, rctx->ivsize, 1768a3719a5SNagadheeraj Rottela rctx->srclen); 177c9613335SNagadheeraj Rottela if (ret) 178c9613335SNagadheeraj Rottela return ret; 179c9613335SNagadheeraj Rottela 1808a3719a5SNagadheeraj Rottela ret = alloc_dst_sglist(&rctx->nkreq, rctx->dst, rctx->ivsize, 1818a3719a5SNagadheeraj Rottela rctx->dstlen); 182c9613335SNagadheeraj Rottela if (ret) { 1838a3719a5SNagadheeraj Rottela free_src_sglist(&rctx->nkreq); 184c9613335SNagadheeraj Rottela return ret; 185c9613335SNagadheeraj Rottela } 186c9613335SNagadheeraj Rottela 187c9613335SNagadheeraj Rottela return 0; 188c9613335SNagadheeraj Rottela } 189c9613335SNagadheeraj Rottela 190c9613335SNagadheeraj Rottela static void nitrox_aead_callback(void *arg, int err) 191c9613335SNagadheeraj Rottela { 192c9613335SNagadheeraj Rottela struct aead_request *areq = arg; 1938a3719a5SNagadheeraj Rottela struct nitrox_aead_rctx *rctx = aead_request_ctx(areq); 194c9613335SNagadheeraj Rottela 1958a3719a5SNagadheeraj Rottela free_src_sglist(&rctx->nkreq); 1968a3719a5SNagadheeraj Rottela free_dst_sglist(&rctx->nkreq); 197c9613335SNagadheeraj Rottela if (err) { 198c9613335SNagadheeraj Rottela pr_err_ratelimited("request failed status 0x%0x\n", err); 199c9613335SNagadheeraj Rottela err = -EINVAL; 200c9613335SNagadheeraj Rottela } 201c9613335SNagadheeraj Rottela 202c9613335SNagadheeraj Rottela areq->base.complete(&areq->base, err); 203c9613335SNagadheeraj Rottela } 204c9613335SNagadheeraj Rottela 2053fed9baaSNagadheeraj Rottela static inline bool nitrox_aes_gcm_assoclen_supported(unsigned int assoclen) 2063fed9baaSNagadheeraj Rottela { 2073fed9baaSNagadheeraj Rottela if (assoclen <= 512) 2083fed9baaSNagadheeraj Rottela return true; 2093fed9baaSNagadheeraj Rottela 2103fed9baaSNagadheeraj Rottela return false; 2113fed9baaSNagadheeraj Rottela } 2123fed9baaSNagadheeraj Rottela 213c9613335SNagadheeraj Rottela static int nitrox_aes_gcm_enc(struct aead_request *areq) 214c9613335SNagadheeraj Rottela { 215c9613335SNagadheeraj Rottela struct crypto_aead *aead = crypto_aead_reqtfm(areq); 216c9613335SNagadheeraj Rottela struct nitrox_crypto_ctx *nctx = crypto_aead_ctx(aead); 2178a3719a5SNagadheeraj Rottela struct nitrox_aead_rctx *rctx = aead_request_ctx(areq); 2188a3719a5SNagadheeraj Rottela struct se_crypto_request *creq = &rctx->nkreq.creq; 219c9613335SNagadheeraj Rottela struct flexi_crypto_context *fctx = nctx->u.fctx; 220c9613335SNagadheeraj Rottela int ret; 221c9613335SNagadheeraj Rottela 2223fed9baaSNagadheeraj Rottela if (!nitrox_aes_gcm_assoclen_supported(areq->assoclen)) 2233fed9baaSNagadheeraj Rottela return -EINVAL; 2243fed9baaSNagadheeraj Rottela 225c9613335SNagadheeraj Rottela memcpy(fctx->crypto.iv, areq->iv, GCM_AES_SALT_SIZE); 226c9613335SNagadheeraj Rottela 2278a3719a5SNagadheeraj Rottela rctx->cryptlen = areq->cryptlen; 2288a3719a5SNagadheeraj Rottela rctx->assoclen = areq->assoclen; 2298a3719a5SNagadheeraj Rottela rctx->srclen = areq->assoclen + areq->cryptlen; 2308a3719a5SNagadheeraj Rottela rctx->dstlen = rctx->srclen + aead->authsize; 2318a3719a5SNagadheeraj Rottela rctx->iv = &areq->iv[GCM_AES_SALT_SIZE]; 2328a3719a5SNagadheeraj Rottela rctx->ivsize = GCM_AES_IV_SIZE - GCM_AES_SALT_SIZE; 2338a3719a5SNagadheeraj Rottela rctx->flags = areq->base.flags; 2348a3719a5SNagadheeraj Rottela rctx->ctx_handle = nctx->u.ctx_handle; 2358a3719a5SNagadheeraj Rottela rctx->src = areq->src; 2368a3719a5SNagadheeraj Rottela rctx->dst = areq->dst; 2378a3719a5SNagadheeraj Rottela rctx->ctrl_arg = ENCRYPT; 2388a3719a5SNagadheeraj Rottela ret = nitrox_set_creq(rctx); 239c9613335SNagadheeraj Rottela if (ret) 240c9613335SNagadheeraj Rottela return ret; 241c9613335SNagadheeraj Rottela 242c9613335SNagadheeraj Rottela /* send the crypto request */ 243c9613335SNagadheeraj Rottela return nitrox_process_se_request(nctx->ndev, creq, nitrox_aead_callback, 244c9613335SNagadheeraj Rottela areq); 245c9613335SNagadheeraj Rottela } 246c9613335SNagadheeraj Rottela 247c9613335SNagadheeraj Rottela static int nitrox_aes_gcm_dec(struct aead_request *areq) 248c9613335SNagadheeraj Rottela { 249c9613335SNagadheeraj Rottela struct crypto_aead *aead = crypto_aead_reqtfm(areq); 250c9613335SNagadheeraj Rottela struct nitrox_crypto_ctx *nctx = crypto_aead_ctx(aead); 2518a3719a5SNagadheeraj Rottela struct nitrox_aead_rctx *rctx = aead_request_ctx(areq); 2528a3719a5SNagadheeraj Rottela struct se_crypto_request *creq = &rctx->nkreq.creq; 253c9613335SNagadheeraj Rottela struct flexi_crypto_context *fctx = nctx->u.fctx; 254c9613335SNagadheeraj Rottela int ret; 255c9613335SNagadheeraj Rottela 2563fed9baaSNagadheeraj Rottela if (!nitrox_aes_gcm_assoclen_supported(areq->assoclen)) 2573fed9baaSNagadheeraj Rottela return -EINVAL; 2583fed9baaSNagadheeraj Rottela 259c9613335SNagadheeraj Rottela memcpy(fctx->crypto.iv, areq->iv, GCM_AES_SALT_SIZE); 260c9613335SNagadheeraj Rottela 2618a3719a5SNagadheeraj Rottela rctx->cryptlen = areq->cryptlen - aead->authsize; 2628a3719a5SNagadheeraj Rottela rctx->assoclen = areq->assoclen; 2638a3719a5SNagadheeraj Rottela rctx->srclen = areq->cryptlen + areq->assoclen; 2648a3719a5SNagadheeraj Rottela rctx->dstlen = rctx->srclen - aead->authsize; 2658a3719a5SNagadheeraj Rottela rctx->iv = &areq->iv[GCM_AES_SALT_SIZE]; 2668a3719a5SNagadheeraj Rottela rctx->ivsize = GCM_AES_IV_SIZE - GCM_AES_SALT_SIZE; 2678a3719a5SNagadheeraj Rottela rctx->flags = areq->base.flags; 2688a3719a5SNagadheeraj Rottela rctx->ctx_handle = nctx->u.ctx_handle; 2698a3719a5SNagadheeraj Rottela rctx->src = areq->src; 2708a3719a5SNagadheeraj Rottela rctx->dst = areq->dst; 2718a3719a5SNagadheeraj Rottela rctx->ctrl_arg = DECRYPT; 2728a3719a5SNagadheeraj Rottela ret = nitrox_set_creq(rctx); 273c9613335SNagadheeraj Rottela if (ret) 274c9613335SNagadheeraj Rottela return ret; 275c9613335SNagadheeraj Rottela 276c9613335SNagadheeraj Rottela /* send the crypto request */ 277c9613335SNagadheeraj Rottela return nitrox_process_se_request(nctx->ndev, creq, nitrox_aead_callback, 278c9613335SNagadheeraj Rottela areq); 279c9613335SNagadheeraj Rottela } 280c9613335SNagadheeraj Rottela 281c9613335SNagadheeraj Rottela static int nitrox_aead_init(struct crypto_aead *aead) 282c9613335SNagadheeraj Rottela { 283c9613335SNagadheeraj Rottela struct nitrox_crypto_ctx *nctx = crypto_aead_ctx(aead); 284c9613335SNagadheeraj Rottela struct crypto_ctx_hdr *chdr; 285c9613335SNagadheeraj Rottela 286c9613335SNagadheeraj Rottela /* get the first device */ 287c9613335SNagadheeraj Rottela nctx->ndev = nitrox_get_first_device(); 288c9613335SNagadheeraj Rottela if (!nctx->ndev) 289c9613335SNagadheeraj Rottela return -ENODEV; 290c9613335SNagadheeraj Rottela 291c9613335SNagadheeraj Rottela /* allocate nitrox crypto context */ 292c9613335SNagadheeraj Rottela chdr = crypto_alloc_context(nctx->ndev); 293c9613335SNagadheeraj Rottela if (!chdr) { 294c9613335SNagadheeraj Rottela nitrox_put_device(nctx->ndev); 295c9613335SNagadheeraj Rottela return -ENOMEM; 296c9613335SNagadheeraj Rottela } 297c9613335SNagadheeraj Rottela nctx->chdr = chdr; 298c9613335SNagadheeraj Rottela nctx->u.ctx_handle = (uintptr_t)((u8 *)chdr->vaddr + 299c9613335SNagadheeraj Rottela sizeof(struct ctx_hdr)); 300c9613335SNagadheeraj Rottela nctx->u.fctx->flags.f = 0; 301c9613335SNagadheeraj Rottela 302c9613335SNagadheeraj Rottela return 0; 303c9613335SNagadheeraj Rottela } 304c9613335SNagadheeraj Rottela 3058a3719a5SNagadheeraj Rottela static int nitrox_gcm_common_init(struct crypto_aead *aead) 306c9613335SNagadheeraj Rottela { 307c9613335SNagadheeraj Rottela int ret; 308c9613335SNagadheeraj Rottela struct nitrox_crypto_ctx *nctx = crypto_aead_ctx(aead); 309c9613335SNagadheeraj Rottela union fc_ctx_flags *flags; 310c9613335SNagadheeraj Rottela 311c9613335SNagadheeraj Rottela ret = nitrox_aead_init(aead); 312c9613335SNagadheeraj Rottela if (ret) 313c9613335SNagadheeraj Rottela return ret; 314c9613335SNagadheeraj Rottela 315c9613335SNagadheeraj Rottela flags = &nctx->u.fctx->flags; 316c9613335SNagadheeraj Rottela flags->w0.cipher_type = CIPHER_AES_GCM; 317c9613335SNagadheeraj Rottela flags->w0.hash_type = AUTH_NULL; 318c9613335SNagadheeraj Rottela flags->w0.iv_source = IV_FROM_DPTR; 319c9613335SNagadheeraj Rottela /* ask microcode to calculate ipad/opad */ 320c9613335SNagadheeraj Rottela flags->w0.auth_input_type = 1; 321cd078cb6SHerbert Xu flags->f = cpu_to_be64(flags->fu); 322c9613335SNagadheeraj Rottela 3238a3719a5SNagadheeraj Rottela return 0; 3248a3719a5SNagadheeraj Rottela } 3258a3719a5SNagadheeraj Rottela 3268a3719a5SNagadheeraj Rottela static int nitrox_aes_gcm_init(struct crypto_aead *aead) 3278a3719a5SNagadheeraj Rottela { 3288a3719a5SNagadheeraj Rottela int ret; 3298a3719a5SNagadheeraj Rottela 3308a3719a5SNagadheeraj Rottela ret = nitrox_gcm_common_init(aead); 3318a3719a5SNagadheeraj Rottela if (ret) 3328a3719a5SNagadheeraj Rottela return ret; 3338a3719a5SNagadheeraj Rottela 3348a3719a5SNagadheeraj Rottela crypto_aead_set_reqsize(aead, 3358a3719a5SNagadheeraj Rottela sizeof(struct aead_request) + 3368a3719a5SNagadheeraj Rottela sizeof(struct nitrox_aead_rctx)); 337c9613335SNagadheeraj Rottela 338c9613335SNagadheeraj Rottela return 0; 339c9613335SNagadheeraj Rottela } 340c9613335SNagadheeraj Rottela 341c9613335SNagadheeraj Rottela static void nitrox_aead_exit(struct crypto_aead *aead) 342c9613335SNagadheeraj Rottela { 343c9613335SNagadheeraj Rottela struct nitrox_crypto_ctx *nctx = crypto_aead_ctx(aead); 344c9613335SNagadheeraj Rottela 345c9613335SNagadheeraj Rottela /* free the nitrox crypto context */ 346c9613335SNagadheeraj Rottela if (nctx->u.ctx_handle) { 347c9613335SNagadheeraj Rottela struct flexi_crypto_context *fctx = nctx->u.fctx; 348c9613335SNagadheeraj Rottela 349c9613335SNagadheeraj Rottela memzero_explicit(&fctx->crypto, sizeof(struct crypto_keys)); 350c9613335SNagadheeraj Rottela memzero_explicit(&fctx->auth, sizeof(struct auth_keys)); 351c9613335SNagadheeraj Rottela crypto_free_context((void *)nctx->chdr); 352c9613335SNagadheeraj Rottela } 353c9613335SNagadheeraj Rottela nitrox_put_device(nctx->ndev); 354c9613335SNagadheeraj Rottela 355c9613335SNagadheeraj Rottela nctx->u.ctx_handle = 0; 356c9613335SNagadheeraj Rottela nctx->ndev = NULL; 357c9613335SNagadheeraj Rottela } 358c9613335SNagadheeraj Rottela 3598a3719a5SNagadheeraj Rottela static int nitrox_rfc4106_setkey(struct crypto_aead *aead, const u8 *key, 3608a3719a5SNagadheeraj Rottela unsigned int keylen) 3618a3719a5SNagadheeraj Rottela { 3628a3719a5SNagadheeraj Rottela struct nitrox_crypto_ctx *nctx = crypto_aead_ctx(aead); 3638a3719a5SNagadheeraj Rottela struct flexi_crypto_context *fctx = nctx->u.fctx; 3648a3719a5SNagadheeraj Rottela int ret; 3658a3719a5SNagadheeraj Rottela 3668a3719a5SNagadheeraj Rottela if (keylen < GCM_AES_SALT_SIZE) 3678a3719a5SNagadheeraj Rottela return -EINVAL; 3688a3719a5SNagadheeraj Rottela 3698a3719a5SNagadheeraj Rottela keylen -= GCM_AES_SALT_SIZE; 3708a3719a5SNagadheeraj Rottela ret = nitrox_aes_gcm_setkey(aead, key, keylen); 3718a3719a5SNagadheeraj Rottela if (ret) 3728a3719a5SNagadheeraj Rottela return ret; 3738a3719a5SNagadheeraj Rottela 3748a3719a5SNagadheeraj Rottela memcpy(fctx->crypto.iv, key + keylen, GCM_AES_SALT_SIZE); 3758a3719a5SNagadheeraj Rottela return 0; 3768a3719a5SNagadheeraj Rottela } 3778a3719a5SNagadheeraj Rottela 3788a3719a5SNagadheeraj Rottela static int nitrox_rfc4106_setauthsize(struct crypto_aead *aead, 3798a3719a5SNagadheeraj Rottela unsigned int authsize) 3808a3719a5SNagadheeraj Rottela { 3818a3719a5SNagadheeraj Rottela switch (authsize) { 3828a3719a5SNagadheeraj Rottela case 8: 3838a3719a5SNagadheeraj Rottela case 12: 3848a3719a5SNagadheeraj Rottela case 16: 3858a3719a5SNagadheeraj Rottela break; 3868a3719a5SNagadheeraj Rottela default: 3878a3719a5SNagadheeraj Rottela return -EINVAL; 3888a3719a5SNagadheeraj Rottela } 3898a3719a5SNagadheeraj Rottela 3908a3719a5SNagadheeraj Rottela return nitrox_aead_setauthsize(aead, authsize); 3918a3719a5SNagadheeraj Rottela } 3928a3719a5SNagadheeraj Rottela 3938a3719a5SNagadheeraj Rottela static int nitrox_rfc4106_set_aead_rctx_sglist(struct aead_request *areq) 3948a3719a5SNagadheeraj Rottela { 395*1c64a7e1SHerbert Xu struct nitrox_rfc4106_rctx *rctx = aead_request_ctx_dma(areq); 3968a3719a5SNagadheeraj Rottela struct nitrox_aead_rctx *aead_rctx = &rctx->base; 3978a3719a5SNagadheeraj Rottela unsigned int assoclen = areq->assoclen - GCM_RFC4106_IV_SIZE; 3988a3719a5SNagadheeraj Rottela struct scatterlist *sg; 3998a3719a5SNagadheeraj Rottela 4008a3719a5SNagadheeraj Rottela if (areq->assoclen != 16 && areq->assoclen != 20) 4018a3719a5SNagadheeraj Rottela return -EINVAL; 4028a3719a5SNagadheeraj Rottela 4038a3719a5SNagadheeraj Rottela scatterwalk_map_and_copy(rctx->assoc, areq->src, 0, assoclen, 0); 4048a3719a5SNagadheeraj Rottela sg_init_table(rctx->src, 3); 4058a3719a5SNagadheeraj Rottela sg_set_buf(rctx->src, rctx->assoc, assoclen); 4068a3719a5SNagadheeraj Rottela sg = scatterwalk_ffwd(rctx->src + 1, areq->src, areq->assoclen); 4078a3719a5SNagadheeraj Rottela if (sg != rctx->src + 1) 4088a3719a5SNagadheeraj Rottela sg_chain(rctx->src, 2, sg); 4098a3719a5SNagadheeraj Rottela 4108a3719a5SNagadheeraj Rottela if (areq->src != areq->dst) { 4118a3719a5SNagadheeraj Rottela sg_init_table(rctx->dst, 3); 4128a3719a5SNagadheeraj Rottela sg_set_buf(rctx->dst, rctx->assoc, assoclen); 4138a3719a5SNagadheeraj Rottela sg = scatterwalk_ffwd(rctx->dst + 1, areq->dst, areq->assoclen); 4148a3719a5SNagadheeraj Rottela if (sg != rctx->dst + 1) 4158a3719a5SNagadheeraj Rottela sg_chain(rctx->dst, 2, sg); 4168a3719a5SNagadheeraj Rottela } 4178a3719a5SNagadheeraj Rottela 4188a3719a5SNagadheeraj Rottela aead_rctx->src = rctx->src; 4198a3719a5SNagadheeraj Rottela aead_rctx->dst = (areq->src == areq->dst) ? rctx->src : rctx->dst; 4208a3719a5SNagadheeraj Rottela 4218a3719a5SNagadheeraj Rottela return 0; 4228a3719a5SNagadheeraj Rottela } 4238a3719a5SNagadheeraj Rottela 4248a3719a5SNagadheeraj Rottela static void nitrox_rfc4106_callback(void *arg, int err) 4258a3719a5SNagadheeraj Rottela { 4268a3719a5SNagadheeraj Rottela struct aead_request *areq = arg; 427*1c64a7e1SHerbert Xu struct nitrox_rfc4106_rctx *rctx = aead_request_ctx_dma(areq); 4288a3719a5SNagadheeraj Rottela struct nitrox_kcrypt_request *nkreq = &rctx->base.nkreq; 4298a3719a5SNagadheeraj Rottela 4308a3719a5SNagadheeraj Rottela free_src_sglist(nkreq); 4318a3719a5SNagadheeraj Rottela free_dst_sglist(nkreq); 4328a3719a5SNagadheeraj Rottela if (err) { 4338a3719a5SNagadheeraj Rottela pr_err_ratelimited("request failed status 0x%0x\n", err); 4348a3719a5SNagadheeraj Rottela err = -EINVAL; 4358a3719a5SNagadheeraj Rottela } 4368a3719a5SNagadheeraj Rottela 4378a3719a5SNagadheeraj Rottela areq->base.complete(&areq->base, err); 4388a3719a5SNagadheeraj Rottela } 4398a3719a5SNagadheeraj Rottela 4408a3719a5SNagadheeraj Rottela static int nitrox_rfc4106_enc(struct aead_request *areq) 4418a3719a5SNagadheeraj Rottela { 4428a3719a5SNagadheeraj Rottela struct crypto_aead *aead = crypto_aead_reqtfm(areq); 4438a3719a5SNagadheeraj Rottela struct nitrox_crypto_ctx *nctx = crypto_aead_ctx(aead); 444*1c64a7e1SHerbert Xu struct nitrox_rfc4106_rctx *rctx = aead_request_ctx_dma(areq); 4458a3719a5SNagadheeraj Rottela struct nitrox_aead_rctx *aead_rctx = &rctx->base; 4468a3719a5SNagadheeraj Rottela struct se_crypto_request *creq = &aead_rctx->nkreq.creq; 4478a3719a5SNagadheeraj Rottela int ret; 4488a3719a5SNagadheeraj Rottela 4498a3719a5SNagadheeraj Rottela aead_rctx->cryptlen = areq->cryptlen; 4508a3719a5SNagadheeraj Rottela aead_rctx->assoclen = areq->assoclen - GCM_RFC4106_IV_SIZE; 4518a3719a5SNagadheeraj Rottela aead_rctx->srclen = aead_rctx->assoclen + aead_rctx->cryptlen; 4528a3719a5SNagadheeraj Rottela aead_rctx->dstlen = aead_rctx->srclen + aead->authsize; 4538a3719a5SNagadheeraj Rottela aead_rctx->iv = areq->iv; 4548a3719a5SNagadheeraj Rottela aead_rctx->ivsize = GCM_RFC4106_IV_SIZE; 4558a3719a5SNagadheeraj Rottela aead_rctx->flags = areq->base.flags; 4568a3719a5SNagadheeraj Rottela aead_rctx->ctx_handle = nctx->u.ctx_handle; 4578a3719a5SNagadheeraj Rottela aead_rctx->ctrl_arg = ENCRYPT; 4588a3719a5SNagadheeraj Rottela 4598a3719a5SNagadheeraj Rottela ret = nitrox_rfc4106_set_aead_rctx_sglist(areq); 4608a3719a5SNagadheeraj Rottela if (ret) 4618a3719a5SNagadheeraj Rottela return ret; 4628a3719a5SNagadheeraj Rottela 4638a3719a5SNagadheeraj Rottela ret = nitrox_set_creq(aead_rctx); 4648a3719a5SNagadheeraj Rottela if (ret) 4658a3719a5SNagadheeraj Rottela return ret; 4668a3719a5SNagadheeraj Rottela 4678a3719a5SNagadheeraj Rottela /* send the crypto request */ 4688a3719a5SNagadheeraj Rottela return nitrox_process_se_request(nctx->ndev, creq, 4698a3719a5SNagadheeraj Rottela nitrox_rfc4106_callback, areq); 4708a3719a5SNagadheeraj Rottela } 4718a3719a5SNagadheeraj Rottela 4728a3719a5SNagadheeraj Rottela static int nitrox_rfc4106_dec(struct aead_request *areq) 4738a3719a5SNagadheeraj Rottela { 4748a3719a5SNagadheeraj Rottela struct crypto_aead *aead = crypto_aead_reqtfm(areq); 475*1c64a7e1SHerbert Xu struct nitrox_crypto_ctx *nctx = crypto_aead_ctx_dma(aead); 4768a3719a5SNagadheeraj Rottela struct nitrox_rfc4106_rctx *rctx = aead_request_ctx(areq); 4778a3719a5SNagadheeraj Rottela struct nitrox_aead_rctx *aead_rctx = &rctx->base; 4788a3719a5SNagadheeraj Rottela struct se_crypto_request *creq = &aead_rctx->nkreq.creq; 4798a3719a5SNagadheeraj Rottela int ret; 4808a3719a5SNagadheeraj Rottela 4818a3719a5SNagadheeraj Rottela aead_rctx->cryptlen = areq->cryptlen - aead->authsize; 4828a3719a5SNagadheeraj Rottela aead_rctx->assoclen = areq->assoclen - GCM_RFC4106_IV_SIZE; 4838a3719a5SNagadheeraj Rottela aead_rctx->srclen = 4848a3719a5SNagadheeraj Rottela areq->cryptlen - GCM_RFC4106_IV_SIZE + areq->assoclen; 4858a3719a5SNagadheeraj Rottela aead_rctx->dstlen = aead_rctx->srclen - aead->authsize; 4868a3719a5SNagadheeraj Rottela aead_rctx->iv = areq->iv; 4878a3719a5SNagadheeraj Rottela aead_rctx->ivsize = GCM_RFC4106_IV_SIZE; 4888a3719a5SNagadheeraj Rottela aead_rctx->flags = areq->base.flags; 4898a3719a5SNagadheeraj Rottela aead_rctx->ctx_handle = nctx->u.ctx_handle; 4908a3719a5SNagadheeraj Rottela aead_rctx->ctrl_arg = DECRYPT; 4918a3719a5SNagadheeraj Rottela 4928a3719a5SNagadheeraj Rottela ret = nitrox_rfc4106_set_aead_rctx_sglist(areq); 4938a3719a5SNagadheeraj Rottela if (ret) 4948a3719a5SNagadheeraj Rottela return ret; 4958a3719a5SNagadheeraj Rottela 4968a3719a5SNagadheeraj Rottela ret = nitrox_set_creq(aead_rctx); 4978a3719a5SNagadheeraj Rottela if (ret) 4988a3719a5SNagadheeraj Rottela return ret; 4998a3719a5SNagadheeraj Rottela 5008a3719a5SNagadheeraj Rottela /* send the crypto request */ 5018a3719a5SNagadheeraj Rottela return nitrox_process_se_request(nctx->ndev, creq, 5028a3719a5SNagadheeraj Rottela nitrox_rfc4106_callback, areq); 5038a3719a5SNagadheeraj Rottela } 5048a3719a5SNagadheeraj Rottela 5058a3719a5SNagadheeraj Rottela static int nitrox_rfc4106_init(struct crypto_aead *aead) 5068a3719a5SNagadheeraj Rottela { 5078a3719a5SNagadheeraj Rottela int ret; 5088a3719a5SNagadheeraj Rottela 5098a3719a5SNagadheeraj Rottela ret = nitrox_gcm_common_init(aead); 5108a3719a5SNagadheeraj Rottela if (ret) 5118a3719a5SNagadheeraj Rottela return ret; 5128a3719a5SNagadheeraj Rottela 513*1c64a7e1SHerbert Xu crypto_aead_set_reqsize_dma(aead, sizeof(struct aead_request) + 5148a3719a5SNagadheeraj Rottela sizeof(struct nitrox_rfc4106_rctx)); 5158a3719a5SNagadheeraj Rottela 5168a3719a5SNagadheeraj Rottela return 0; 5178a3719a5SNagadheeraj Rottela } 5188a3719a5SNagadheeraj Rottela 519c9613335SNagadheeraj Rottela static struct aead_alg nitrox_aeads[] = { { 520c9613335SNagadheeraj Rottela .base = { 521c9613335SNagadheeraj Rottela .cra_name = "gcm(aes)", 522c9613335SNagadheeraj Rottela .cra_driver_name = "n5_aes_gcm", 523c9613335SNagadheeraj Rottela .cra_priority = PRIO, 524b8aa7dc5SMikulas Patocka .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY, 5253fed9baaSNagadheeraj Rottela .cra_blocksize = 1, 526c9613335SNagadheeraj Rottela .cra_ctxsize = sizeof(struct nitrox_crypto_ctx), 527c9613335SNagadheeraj Rottela .cra_alignmask = 0, 528c9613335SNagadheeraj Rottela .cra_module = THIS_MODULE, 529c9613335SNagadheeraj Rottela }, 530c9613335SNagadheeraj Rottela .setkey = nitrox_aes_gcm_setkey, 5313fed9baaSNagadheeraj Rottela .setauthsize = nitrox_aes_gcm_setauthsize, 532c9613335SNagadheeraj Rottela .encrypt = nitrox_aes_gcm_enc, 533c9613335SNagadheeraj Rottela .decrypt = nitrox_aes_gcm_dec, 534c9613335SNagadheeraj Rottela .init = nitrox_aes_gcm_init, 535c9613335SNagadheeraj Rottela .exit = nitrox_aead_exit, 536c9613335SNagadheeraj Rottela .ivsize = GCM_AES_IV_SIZE, 537c9613335SNagadheeraj Rottela .maxauthsize = AES_BLOCK_SIZE, 5388a3719a5SNagadheeraj Rottela }, { 5398a3719a5SNagadheeraj Rottela .base = { 5408a3719a5SNagadheeraj Rottela .cra_name = "rfc4106(gcm(aes))", 5418a3719a5SNagadheeraj Rottela .cra_driver_name = "n5_rfc4106", 5428a3719a5SNagadheeraj Rottela .cra_priority = PRIO, 543b8aa7dc5SMikulas Patocka .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY, 5443fed9baaSNagadheeraj Rottela .cra_blocksize = 1, 5458a3719a5SNagadheeraj Rottela .cra_ctxsize = sizeof(struct nitrox_crypto_ctx), 5468a3719a5SNagadheeraj Rottela .cra_alignmask = 0, 5478a3719a5SNagadheeraj Rottela .cra_module = THIS_MODULE, 5488a3719a5SNagadheeraj Rottela }, 5498a3719a5SNagadheeraj Rottela .setkey = nitrox_rfc4106_setkey, 5508a3719a5SNagadheeraj Rottela .setauthsize = nitrox_rfc4106_setauthsize, 5518a3719a5SNagadheeraj Rottela .encrypt = nitrox_rfc4106_enc, 5528a3719a5SNagadheeraj Rottela .decrypt = nitrox_rfc4106_dec, 5538a3719a5SNagadheeraj Rottela .init = nitrox_rfc4106_init, 5548a3719a5SNagadheeraj Rottela .exit = nitrox_aead_exit, 5558a3719a5SNagadheeraj Rottela .ivsize = GCM_RFC4106_IV_SIZE, 5568a3719a5SNagadheeraj Rottela .maxauthsize = AES_BLOCK_SIZE, 557c9613335SNagadheeraj Rottela } }; 558c9613335SNagadheeraj Rottela 559c9613335SNagadheeraj Rottela int nitrox_register_aeads(void) 560c9613335SNagadheeraj Rottela { 561c9613335SNagadheeraj Rottela return crypto_register_aeads(nitrox_aeads, ARRAY_SIZE(nitrox_aeads)); 562c9613335SNagadheeraj Rottela } 563c9613335SNagadheeraj Rottela 564c9613335SNagadheeraj Rottela void nitrox_unregister_aeads(void) 565c9613335SNagadheeraj Rottela { 566c9613335SNagadheeraj Rottela crypto_unregister_aeads(nitrox_aeads, ARRAY_SIZE(nitrox_aeads)); 567c9613335SNagadheeraj Rottela } 568