18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * This file is part of the Chelsio T6 Crypto driver for Linux. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright (c) 2003-2016 Chelsio Communications, Inc. All rights reserved. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * This software is available to you under a choice of one of two 78c2ecf20Sopenharmony_ci * licenses. You may choose to be licensed under the terms of the GNU 88c2ecf20Sopenharmony_ci * General Public License (GPL) Version 2, available from the file 98c2ecf20Sopenharmony_ci * COPYING in the main directory of this source tree, or the 108c2ecf20Sopenharmony_ci * OpenIB.org BSD license below: 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or 138c2ecf20Sopenharmony_ci * without modification, are permitted provided that the following 148c2ecf20Sopenharmony_ci * conditions are met: 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * - Redistributions of source code must retain the above 178c2ecf20Sopenharmony_ci * copyright notice, this list of conditions and the following 188c2ecf20Sopenharmony_ci * disclaimer. 198c2ecf20Sopenharmony_ci * 208c2ecf20Sopenharmony_ci * - Redistributions in binary form must reproduce the above 218c2ecf20Sopenharmony_ci * copyright notice, this list of conditions and the following 228c2ecf20Sopenharmony_ci * disclaimer in the documentation and/or other materials 238c2ecf20Sopenharmony_ci * provided with the distribution. 248c2ecf20Sopenharmony_ci * 258c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 268c2ecf20Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 278c2ecf20Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 288c2ecf20Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 298c2ecf20Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 308c2ecf20Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 318c2ecf20Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 328c2ecf20Sopenharmony_ci * SOFTWARE. 338c2ecf20Sopenharmony_ci * 348c2ecf20Sopenharmony_ci * Written and Maintained by: 358c2ecf20Sopenharmony_ci * Manoj Malviya (manojmalviya@chelsio.com) 368c2ecf20Sopenharmony_ci * Atul Gupta (atul.gupta@chelsio.com) 378c2ecf20Sopenharmony_ci * Jitendra Lulla (jlulla@chelsio.com) 388c2ecf20Sopenharmony_ci * Yeshaswi M R Gowda (yeshaswi@chelsio.com) 398c2ecf20Sopenharmony_ci * Harsh Jain (harsh@chelsio.com) 408c2ecf20Sopenharmony_ci */ 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci#define pr_fmt(fmt) "chcr:" fmt 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci#include <linux/kernel.h> 458c2ecf20Sopenharmony_ci#include <linux/module.h> 468c2ecf20Sopenharmony_ci#include <linux/crypto.h> 478c2ecf20Sopenharmony_ci#include <linux/skbuff.h> 488c2ecf20Sopenharmony_ci#include <linux/rtnetlink.h> 498c2ecf20Sopenharmony_ci#include <linux/highmem.h> 508c2ecf20Sopenharmony_ci#include <linux/scatterlist.h> 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci#include <crypto/aes.h> 538c2ecf20Sopenharmony_ci#include <crypto/algapi.h> 548c2ecf20Sopenharmony_ci#include <crypto/hash.h> 558c2ecf20Sopenharmony_ci#include <crypto/gcm.h> 568c2ecf20Sopenharmony_ci#include <crypto/sha.h> 578c2ecf20Sopenharmony_ci#include <crypto/authenc.h> 588c2ecf20Sopenharmony_ci#include <crypto/ctr.h> 598c2ecf20Sopenharmony_ci#include <crypto/gf128mul.h> 608c2ecf20Sopenharmony_ci#include <crypto/internal/aead.h> 618c2ecf20Sopenharmony_ci#include <crypto/null.h> 628c2ecf20Sopenharmony_ci#include <crypto/internal/skcipher.h> 638c2ecf20Sopenharmony_ci#include <crypto/aead.h> 648c2ecf20Sopenharmony_ci#include <crypto/scatterwalk.h> 658c2ecf20Sopenharmony_ci#include <crypto/internal/hash.h> 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci#include "t4fw_api.h" 688c2ecf20Sopenharmony_ci#include "t4_msg.h" 698c2ecf20Sopenharmony_ci#include "chcr_core.h" 708c2ecf20Sopenharmony_ci#include "chcr_algo.h" 718c2ecf20Sopenharmony_ci#include "chcr_crypto.h" 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci#define IV AES_BLOCK_SIZE 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_cistatic unsigned int sgl_ent_len[] = { 768c2ecf20Sopenharmony_ci 0, 0, 16, 24, 40, 48, 64, 72, 88, 778c2ecf20Sopenharmony_ci 96, 112, 120, 136, 144, 160, 168, 184, 788c2ecf20Sopenharmony_ci 192, 208, 216, 232, 240, 256, 264, 280, 798c2ecf20Sopenharmony_ci 288, 304, 312, 328, 336, 352, 360, 376 808c2ecf20Sopenharmony_ci}; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_cistatic unsigned int dsgl_ent_len[] = { 838c2ecf20Sopenharmony_ci 0, 32, 32, 48, 48, 64, 64, 80, 80, 848c2ecf20Sopenharmony_ci 112, 112, 128, 128, 144, 144, 160, 160, 858c2ecf20Sopenharmony_ci 192, 192, 208, 208, 224, 224, 240, 240, 868c2ecf20Sopenharmony_ci 272, 272, 288, 288, 304, 304, 320, 320 878c2ecf20Sopenharmony_ci}; 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_cistatic u32 round_constant[11] = { 908c2ecf20Sopenharmony_ci 0x01000000, 0x02000000, 0x04000000, 0x08000000, 918c2ecf20Sopenharmony_ci 0x10000000, 0x20000000, 0x40000000, 0x80000000, 928c2ecf20Sopenharmony_ci 0x1B000000, 0x36000000, 0x6C000000 938c2ecf20Sopenharmony_ci}; 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_cistatic int chcr_handle_cipher_resp(struct skcipher_request *req, 968c2ecf20Sopenharmony_ci unsigned char *input, int err); 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_cistatic inline struct chcr_aead_ctx *AEAD_CTX(struct chcr_context *ctx) 998c2ecf20Sopenharmony_ci{ 1008c2ecf20Sopenharmony_ci return ctx->crypto_ctx->aeadctx; 1018c2ecf20Sopenharmony_ci} 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_cistatic inline struct ablk_ctx *ABLK_CTX(struct chcr_context *ctx) 1048c2ecf20Sopenharmony_ci{ 1058c2ecf20Sopenharmony_ci return ctx->crypto_ctx->ablkctx; 1068c2ecf20Sopenharmony_ci} 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_cistatic inline struct hmac_ctx *HMAC_CTX(struct chcr_context *ctx) 1098c2ecf20Sopenharmony_ci{ 1108c2ecf20Sopenharmony_ci return ctx->crypto_ctx->hmacctx; 1118c2ecf20Sopenharmony_ci} 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_cistatic inline struct chcr_gcm_ctx *GCM_CTX(struct chcr_aead_ctx *gctx) 1148c2ecf20Sopenharmony_ci{ 1158c2ecf20Sopenharmony_ci return gctx->ctx->gcm; 1168c2ecf20Sopenharmony_ci} 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_cistatic inline struct chcr_authenc_ctx *AUTHENC_CTX(struct chcr_aead_ctx *gctx) 1198c2ecf20Sopenharmony_ci{ 1208c2ecf20Sopenharmony_ci return gctx->ctx->authenc; 1218c2ecf20Sopenharmony_ci} 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_cistatic inline struct uld_ctx *ULD_CTX(struct chcr_context *ctx) 1248c2ecf20Sopenharmony_ci{ 1258c2ecf20Sopenharmony_ci return container_of(ctx->dev, struct uld_ctx, dev); 1268c2ecf20Sopenharmony_ci} 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_cistatic inline int is_ofld_imm(const struct sk_buff *skb) 1298c2ecf20Sopenharmony_ci{ 1308c2ecf20Sopenharmony_ci return (skb->len <= SGE_MAX_WR_LEN); 1318c2ecf20Sopenharmony_ci} 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_cistatic inline void chcr_init_hctx_per_wr(struct chcr_ahash_req_ctx *reqctx) 1348c2ecf20Sopenharmony_ci{ 1358c2ecf20Sopenharmony_ci memset(&reqctx->hctx_wr, 0, sizeof(struct chcr_hctx_per_wr)); 1368c2ecf20Sopenharmony_ci} 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_cistatic int sg_nents_xlen(struct scatterlist *sg, unsigned int reqlen, 1398c2ecf20Sopenharmony_ci unsigned int entlen, 1408c2ecf20Sopenharmony_ci unsigned int skip) 1418c2ecf20Sopenharmony_ci{ 1428c2ecf20Sopenharmony_ci int nents = 0; 1438c2ecf20Sopenharmony_ci unsigned int less; 1448c2ecf20Sopenharmony_ci unsigned int skip_len = 0; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci while (sg && skip) { 1478c2ecf20Sopenharmony_ci if (sg_dma_len(sg) <= skip) { 1488c2ecf20Sopenharmony_ci skip -= sg_dma_len(sg); 1498c2ecf20Sopenharmony_ci skip_len = 0; 1508c2ecf20Sopenharmony_ci sg = sg_next(sg); 1518c2ecf20Sopenharmony_ci } else { 1528c2ecf20Sopenharmony_ci skip_len = skip; 1538c2ecf20Sopenharmony_ci skip = 0; 1548c2ecf20Sopenharmony_ci } 1558c2ecf20Sopenharmony_ci } 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci while (sg && reqlen) { 1588c2ecf20Sopenharmony_ci less = min(reqlen, sg_dma_len(sg) - skip_len); 1598c2ecf20Sopenharmony_ci nents += DIV_ROUND_UP(less, entlen); 1608c2ecf20Sopenharmony_ci reqlen -= less; 1618c2ecf20Sopenharmony_ci skip_len = 0; 1628c2ecf20Sopenharmony_ci sg = sg_next(sg); 1638c2ecf20Sopenharmony_ci } 1648c2ecf20Sopenharmony_ci return nents; 1658c2ecf20Sopenharmony_ci} 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_cistatic inline int get_aead_subtype(struct crypto_aead *aead) 1688c2ecf20Sopenharmony_ci{ 1698c2ecf20Sopenharmony_ci struct aead_alg *alg = crypto_aead_alg(aead); 1708c2ecf20Sopenharmony_ci struct chcr_alg_template *chcr_crypto_alg = 1718c2ecf20Sopenharmony_ci container_of(alg, struct chcr_alg_template, alg.aead); 1728c2ecf20Sopenharmony_ci return chcr_crypto_alg->type & CRYPTO_ALG_SUB_TYPE_MASK; 1738c2ecf20Sopenharmony_ci} 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_civoid chcr_verify_tag(struct aead_request *req, u8 *input, int *err) 1768c2ecf20Sopenharmony_ci{ 1778c2ecf20Sopenharmony_ci u8 temp[SHA512_DIGEST_SIZE]; 1788c2ecf20Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 1798c2ecf20Sopenharmony_ci int authsize = crypto_aead_authsize(tfm); 1808c2ecf20Sopenharmony_ci struct cpl_fw6_pld *fw6_pld; 1818c2ecf20Sopenharmony_ci int cmp = 0; 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci fw6_pld = (struct cpl_fw6_pld *)input; 1848c2ecf20Sopenharmony_ci if ((get_aead_subtype(tfm) == CRYPTO_ALG_SUB_TYPE_AEAD_RFC4106) || 1858c2ecf20Sopenharmony_ci (get_aead_subtype(tfm) == CRYPTO_ALG_SUB_TYPE_AEAD_GCM)) { 1868c2ecf20Sopenharmony_ci cmp = crypto_memneq(&fw6_pld->data[2], (fw6_pld + 1), authsize); 1878c2ecf20Sopenharmony_ci } else { 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci sg_pcopy_to_buffer(req->src, sg_nents(req->src), temp, 1908c2ecf20Sopenharmony_ci authsize, req->assoclen + 1918c2ecf20Sopenharmony_ci req->cryptlen - authsize); 1928c2ecf20Sopenharmony_ci cmp = crypto_memneq(temp, (fw6_pld + 1), authsize); 1938c2ecf20Sopenharmony_ci } 1948c2ecf20Sopenharmony_ci if (cmp) 1958c2ecf20Sopenharmony_ci *err = -EBADMSG; 1968c2ecf20Sopenharmony_ci else 1978c2ecf20Sopenharmony_ci *err = 0; 1988c2ecf20Sopenharmony_ci} 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_cistatic int chcr_inc_wrcount(struct chcr_dev *dev) 2018c2ecf20Sopenharmony_ci{ 2028c2ecf20Sopenharmony_ci if (dev->state == CHCR_DETACH) 2038c2ecf20Sopenharmony_ci return 1; 2048c2ecf20Sopenharmony_ci atomic_inc(&dev->inflight); 2058c2ecf20Sopenharmony_ci return 0; 2068c2ecf20Sopenharmony_ci} 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_cistatic inline void chcr_dec_wrcount(struct chcr_dev *dev) 2098c2ecf20Sopenharmony_ci{ 2108c2ecf20Sopenharmony_ci atomic_dec(&dev->inflight); 2118c2ecf20Sopenharmony_ci} 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_cistatic inline int chcr_handle_aead_resp(struct aead_request *req, 2148c2ecf20Sopenharmony_ci unsigned char *input, 2158c2ecf20Sopenharmony_ci int err) 2168c2ecf20Sopenharmony_ci{ 2178c2ecf20Sopenharmony_ci struct chcr_aead_reqctx *reqctx = aead_request_ctx(req); 2188c2ecf20Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 2198c2ecf20Sopenharmony_ci struct chcr_dev *dev = a_ctx(tfm)->dev; 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci chcr_aead_common_exit(req); 2228c2ecf20Sopenharmony_ci if (reqctx->verify == VERIFY_SW) { 2238c2ecf20Sopenharmony_ci chcr_verify_tag(req, input, &err); 2248c2ecf20Sopenharmony_ci reqctx->verify = VERIFY_HW; 2258c2ecf20Sopenharmony_ci } 2268c2ecf20Sopenharmony_ci chcr_dec_wrcount(dev); 2278c2ecf20Sopenharmony_ci req->base.complete(&req->base, err); 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci return err; 2308c2ecf20Sopenharmony_ci} 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_cistatic void get_aes_decrypt_key(unsigned char *dec_key, 2338c2ecf20Sopenharmony_ci const unsigned char *key, 2348c2ecf20Sopenharmony_ci unsigned int keylength) 2358c2ecf20Sopenharmony_ci{ 2368c2ecf20Sopenharmony_ci u32 temp; 2378c2ecf20Sopenharmony_ci u32 w_ring[MAX_NK]; 2388c2ecf20Sopenharmony_ci int i, j, k; 2398c2ecf20Sopenharmony_ci u8 nr, nk; 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci switch (keylength) { 2428c2ecf20Sopenharmony_ci case AES_KEYLENGTH_128BIT: 2438c2ecf20Sopenharmony_ci nk = KEYLENGTH_4BYTES; 2448c2ecf20Sopenharmony_ci nr = NUMBER_OF_ROUNDS_10; 2458c2ecf20Sopenharmony_ci break; 2468c2ecf20Sopenharmony_ci case AES_KEYLENGTH_192BIT: 2478c2ecf20Sopenharmony_ci nk = KEYLENGTH_6BYTES; 2488c2ecf20Sopenharmony_ci nr = NUMBER_OF_ROUNDS_12; 2498c2ecf20Sopenharmony_ci break; 2508c2ecf20Sopenharmony_ci case AES_KEYLENGTH_256BIT: 2518c2ecf20Sopenharmony_ci nk = KEYLENGTH_8BYTES; 2528c2ecf20Sopenharmony_ci nr = NUMBER_OF_ROUNDS_14; 2538c2ecf20Sopenharmony_ci break; 2548c2ecf20Sopenharmony_ci default: 2558c2ecf20Sopenharmony_ci return; 2568c2ecf20Sopenharmony_ci } 2578c2ecf20Sopenharmony_ci for (i = 0; i < nk; i++) 2588c2ecf20Sopenharmony_ci w_ring[i] = get_unaligned_be32(&key[i * 4]); 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci i = 0; 2618c2ecf20Sopenharmony_ci temp = w_ring[nk - 1]; 2628c2ecf20Sopenharmony_ci while (i + nk < (nr + 1) * 4) { 2638c2ecf20Sopenharmony_ci if (!(i % nk)) { 2648c2ecf20Sopenharmony_ci /* RotWord(temp) */ 2658c2ecf20Sopenharmony_ci temp = (temp << 8) | (temp >> 24); 2668c2ecf20Sopenharmony_ci temp = aes_ks_subword(temp); 2678c2ecf20Sopenharmony_ci temp ^= round_constant[i / nk]; 2688c2ecf20Sopenharmony_ci } else if (nk == 8 && (i % 4 == 0)) { 2698c2ecf20Sopenharmony_ci temp = aes_ks_subword(temp); 2708c2ecf20Sopenharmony_ci } 2718c2ecf20Sopenharmony_ci w_ring[i % nk] ^= temp; 2728c2ecf20Sopenharmony_ci temp = w_ring[i % nk]; 2738c2ecf20Sopenharmony_ci i++; 2748c2ecf20Sopenharmony_ci } 2758c2ecf20Sopenharmony_ci i--; 2768c2ecf20Sopenharmony_ci for (k = 0, j = i % nk; k < nk; k++) { 2778c2ecf20Sopenharmony_ci put_unaligned_be32(w_ring[j], &dec_key[k * 4]); 2788c2ecf20Sopenharmony_ci j--; 2798c2ecf20Sopenharmony_ci if (j < 0) 2808c2ecf20Sopenharmony_ci j += nk; 2818c2ecf20Sopenharmony_ci } 2828c2ecf20Sopenharmony_ci} 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_cistatic struct crypto_shash *chcr_alloc_shash(unsigned int ds) 2858c2ecf20Sopenharmony_ci{ 2868c2ecf20Sopenharmony_ci struct crypto_shash *base_hash = ERR_PTR(-EINVAL); 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci switch (ds) { 2898c2ecf20Sopenharmony_ci case SHA1_DIGEST_SIZE: 2908c2ecf20Sopenharmony_ci base_hash = crypto_alloc_shash("sha1", 0, 0); 2918c2ecf20Sopenharmony_ci break; 2928c2ecf20Sopenharmony_ci case SHA224_DIGEST_SIZE: 2938c2ecf20Sopenharmony_ci base_hash = crypto_alloc_shash("sha224", 0, 0); 2948c2ecf20Sopenharmony_ci break; 2958c2ecf20Sopenharmony_ci case SHA256_DIGEST_SIZE: 2968c2ecf20Sopenharmony_ci base_hash = crypto_alloc_shash("sha256", 0, 0); 2978c2ecf20Sopenharmony_ci break; 2988c2ecf20Sopenharmony_ci case SHA384_DIGEST_SIZE: 2998c2ecf20Sopenharmony_ci base_hash = crypto_alloc_shash("sha384", 0, 0); 3008c2ecf20Sopenharmony_ci break; 3018c2ecf20Sopenharmony_ci case SHA512_DIGEST_SIZE: 3028c2ecf20Sopenharmony_ci base_hash = crypto_alloc_shash("sha512", 0, 0); 3038c2ecf20Sopenharmony_ci break; 3048c2ecf20Sopenharmony_ci } 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci return base_hash; 3078c2ecf20Sopenharmony_ci} 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_cistatic int chcr_compute_partial_hash(struct shash_desc *desc, 3108c2ecf20Sopenharmony_ci char *iopad, char *result_hash, 3118c2ecf20Sopenharmony_ci int digest_size) 3128c2ecf20Sopenharmony_ci{ 3138c2ecf20Sopenharmony_ci struct sha1_state sha1_st; 3148c2ecf20Sopenharmony_ci struct sha256_state sha256_st; 3158c2ecf20Sopenharmony_ci struct sha512_state sha512_st; 3168c2ecf20Sopenharmony_ci int error; 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci if (digest_size == SHA1_DIGEST_SIZE) { 3198c2ecf20Sopenharmony_ci error = crypto_shash_init(desc) ?: 3208c2ecf20Sopenharmony_ci crypto_shash_update(desc, iopad, SHA1_BLOCK_SIZE) ?: 3218c2ecf20Sopenharmony_ci crypto_shash_export(desc, (void *)&sha1_st); 3228c2ecf20Sopenharmony_ci memcpy(result_hash, sha1_st.state, SHA1_DIGEST_SIZE); 3238c2ecf20Sopenharmony_ci } else if (digest_size == SHA224_DIGEST_SIZE) { 3248c2ecf20Sopenharmony_ci error = crypto_shash_init(desc) ?: 3258c2ecf20Sopenharmony_ci crypto_shash_update(desc, iopad, SHA256_BLOCK_SIZE) ?: 3268c2ecf20Sopenharmony_ci crypto_shash_export(desc, (void *)&sha256_st); 3278c2ecf20Sopenharmony_ci memcpy(result_hash, sha256_st.state, SHA256_DIGEST_SIZE); 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci } else if (digest_size == SHA256_DIGEST_SIZE) { 3308c2ecf20Sopenharmony_ci error = crypto_shash_init(desc) ?: 3318c2ecf20Sopenharmony_ci crypto_shash_update(desc, iopad, SHA256_BLOCK_SIZE) ?: 3328c2ecf20Sopenharmony_ci crypto_shash_export(desc, (void *)&sha256_st); 3338c2ecf20Sopenharmony_ci memcpy(result_hash, sha256_st.state, SHA256_DIGEST_SIZE); 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci } else if (digest_size == SHA384_DIGEST_SIZE) { 3368c2ecf20Sopenharmony_ci error = crypto_shash_init(desc) ?: 3378c2ecf20Sopenharmony_ci crypto_shash_update(desc, iopad, SHA512_BLOCK_SIZE) ?: 3388c2ecf20Sopenharmony_ci crypto_shash_export(desc, (void *)&sha512_st); 3398c2ecf20Sopenharmony_ci memcpy(result_hash, sha512_st.state, SHA512_DIGEST_SIZE); 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci } else if (digest_size == SHA512_DIGEST_SIZE) { 3428c2ecf20Sopenharmony_ci error = crypto_shash_init(desc) ?: 3438c2ecf20Sopenharmony_ci crypto_shash_update(desc, iopad, SHA512_BLOCK_SIZE) ?: 3448c2ecf20Sopenharmony_ci crypto_shash_export(desc, (void *)&sha512_st); 3458c2ecf20Sopenharmony_ci memcpy(result_hash, sha512_st.state, SHA512_DIGEST_SIZE); 3468c2ecf20Sopenharmony_ci } else { 3478c2ecf20Sopenharmony_ci error = -EINVAL; 3488c2ecf20Sopenharmony_ci pr_err("Unknown digest size %d\n", digest_size); 3498c2ecf20Sopenharmony_ci } 3508c2ecf20Sopenharmony_ci return error; 3518c2ecf20Sopenharmony_ci} 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_cistatic void chcr_change_order(char *buf, int ds) 3548c2ecf20Sopenharmony_ci{ 3558c2ecf20Sopenharmony_ci int i; 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci if (ds == SHA512_DIGEST_SIZE) { 3588c2ecf20Sopenharmony_ci for (i = 0; i < (ds / sizeof(u64)); i++) 3598c2ecf20Sopenharmony_ci *((__be64 *)buf + i) = 3608c2ecf20Sopenharmony_ci cpu_to_be64(*((u64 *)buf + i)); 3618c2ecf20Sopenharmony_ci } else { 3628c2ecf20Sopenharmony_ci for (i = 0; i < (ds / sizeof(u32)); i++) 3638c2ecf20Sopenharmony_ci *((__be32 *)buf + i) = 3648c2ecf20Sopenharmony_ci cpu_to_be32(*((u32 *)buf + i)); 3658c2ecf20Sopenharmony_ci } 3668c2ecf20Sopenharmony_ci} 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_cistatic inline int is_hmac(struct crypto_tfm *tfm) 3698c2ecf20Sopenharmony_ci{ 3708c2ecf20Sopenharmony_ci struct crypto_alg *alg = tfm->__crt_alg; 3718c2ecf20Sopenharmony_ci struct chcr_alg_template *chcr_crypto_alg = 3728c2ecf20Sopenharmony_ci container_of(__crypto_ahash_alg(alg), struct chcr_alg_template, 3738c2ecf20Sopenharmony_ci alg.hash); 3748c2ecf20Sopenharmony_ci if (chcr_crypto_alg->type == CRYPTO_ALG_TYPE_HMAC) 3758c2ecf20Sopenharmony_ci return 1; 3768c2ecf20Sopenharmony_ci return 0; 3778c2ecf20Sopenharmony_ci} 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_cistatic inline void dsgl_walk_init(struct dsgl_walk *walk, 3808c2ecf20Sopenharmony_ci struct cpl_rx_phys_dsgl *dsgl) 3818c2ecf20Sopenharmony_ci{ 3828c2ecf20Sopenharmony_ci walk->dsgl = dsgl; 3838c2ecf20Sopenharmony_ci walk->nents = 0; 3848c2ecf20Sopenharmony_ci walk->to = (struct phys_sge_pairs *)(dsgl + 1); 3858c2ecf20Sopenharmony_ci} 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_cistatic inline void dsgl_walk_end(struct dsgl_walk *walk, unsigned short qid, 3888c2ecf20Sopenharmony_ci int pci_chan_id) 3898c2ecf20Sopenharmony_ci{ 3908c2ecf20Sopenharmony_ci struct cpl_rx_phys_dsgl *phys_cpl; 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci phys_cpl = walk->dsgl; 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci phys_cpl->op_to_tid = htonl(CPL_RX_PHYS_DSGL_OPCODE_V(CPL_RX_PHYS_DSGL) 3958c2ecf20Sopenharmony_ci | CPL_RX_PHYS_DSGL_ISRDMA_V(0)); 3968c2ecf20Sopenharmony_ci phys_cpl->pcirlxorder_to_noofsgentr = 3978c2ecf20Sopenharmony_ci htonl(CPL_RX_PHYS_DSGL_PCIRLXORDER_V(0) | 3988c2ecf20Sopenharmony_ci CPL_RX_PHYS_DSGL_PCINOSNOOP_V(0) | 3998c2ecf20Sopenharmony_ci CPL_RX_PHYS_DSGL_PCITPHNTENB_V(0) | 4008c2ecf20Sopenharmony_ci CPL_RX_PHYS_DSGL_PCITPHNT_V(0) | 4018c2ecf20Sopenharmony_ci CPL_RX_PHYS_DSGL_DCAID_V(0) | 4028c2ecf20Sopenharmony_ci CPL_RX_PHYS_DSGL_NOOFSGENTR_V(walk->nents)); 4038c2ecf20Sopenharmony_ci phys_cpl->rss_hdr_int.opcode = CPL_RX_PHYS_ADDR; 4048c2ecf20Sopenharmony_ci phys_cpl->rss_hdr_int.qid = htons(qid); 4058c2ecf20Sopenharmony_ci phys_cpl->rss_hdr_int.hash_val = 0; 4068c2ecf20Sopenharmony_ci phys_cpl->rss_hdr_int.channel = pci_chan_id; 4078c2ecf20Sopenharmony_ci} 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_cistatic inline void dsgl_walk_add_page(struct dsgl_walk *walk, 4108c2ecf20Sopenharmony_ci size_t size, 4118c2ecf20Sopenharmony_ci dma_addr_t addr) 4128c2ecf20Sopenharmony_ci{ 4138c2ecf20Sopenharmony_ci int j; 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci if (!size) 4168c2ecf20Sopenharmony_ci return; 4178c2ecf20Sopenharmony_ci j = walk->nents; 4188c2ecf20Sopenharmony_ci walk->to->len[j % 8] = htons(size); 4198c2ecf20Sopenharmony_ci walk->to->addr[j % 8] = cpu_to_be64(addr); 4208c2ecf20Sopenharmony_ci j++; 4218c2ecf20Sopenharmony_ci if ((j % 8) == 0) 4228c2ecf20Sopenharmony_ci walk->to++; 4238c2ecf20Sopenharmony_ci walk->nents = j; 4248c2ecf20Sopenharmony_ci} 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_cistatic void dsgl_walk_add_sg(struct dsgl_walk *walk, 4278c2ecf20Sopenharmony_ci struct scatterlist *sg, 4288c2ecf20Sopenharmony_ci unsigned int slen, 4298c2ecf20Sopenharmony_ci unsigned int skip) 4308c2ecf20Sopenharmony_ci{ 4318c2ecf20Sopenharmony_ci int skip_len = 0; 4328c2ecf20Sopenharmony_ci unsigned int left_size = slen, len = 0; 4338c2ecf20Sopenharmony_ci unsigned int j = walk->nents; 4348c2ecf20Sopenharmony_ci int offset, ent_len; 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci if (!slen) 4378c2ecf20Sopenharmony_ci return; 4388c2ecf20Sopenharmony_ci while (sg && skip) { 4398c2ecf20Sopenharmony_ci if (sg_dma_len(sg) <= skip) { 4408c2ecf20Sopenharmony_ci skip -= sg_dma_len(sg); 4418c2ecf20Sopenharmony_ci skip_len = 0; 4428c2ecf20Sopenharmony_ci sg = sg_next(sg); 4438c2ecf20Sopenharmony_ci } else { 4448c2ecf20Sopenharmony_ci skip_len = skip; 4458c2ecf20Sopenharmony_ci skip = 0; 4468c2ecf20Sopenharmony_ci } 4478c2ecf20Sopenharmony_ci } 4488c2ecf20Sopenharmony_ci 4498c2ecf20Sopenharmony_ci while (left_size && sg) { 4508c2ecf20Sopenharmony_ci len = min_t(u32, left_size, sg_dma_len(sg) - skip_len); 4518c2ecf20Sopenharmony_ci offset = 0; 4528c2ecf20Sopenharmony_ci while (len) { 4538c2ecf20Sopenharmony_ci ent_len = min_t(u32, len, CHCR_DST_SG_SIZE); 4548c2ecf20Sopenharmony_ci walk->to->len[j % 8] = htons(ent_len); 4558c2ecf20Sopenharmony_ci walk->to->addr[j % 8] = cpu_to_be64(sg_dma_address(sg) + 4568c2ecf20Sopenharmony_ci offset + skip_len); 4578c2ecf20Sopenharmony_ci offset += ent_len; 4588c2ecf20Sopenharmony_ci len -= ent_len; 4598c2ecf20Sopenharmony_ci j++; 4608c2ecf20Sopenharmony_ci if ((j % 8) == 0) 4618c2ecf20Sopenharmony_ci walk->to++; 4628c2ecf20Sopenharmony_ci } 4638c2ecf20Sopenharmony_ci walk->last_sg = sg; 4648c2ecf20Sopenharmony_ci walk->last_sg_len = min_t(u32, left_size, sg_dma_len(sg) - 4658c2ecf20Sopenharmony_ci skip_len) + skip_len; 4668c2ecf20Sopenharmony_ci left_size -= min_t(u32, left_size, sg_dma_len(sg) - skip_len); 4678c2ecf20Sopenharmony_ci skip_len = 0; 4688c2ecf20Sopenharmony_ci sg = sg_next(sg); 4698c2ecf20Sopenharmony_ci } 4708c2ecf20Sopenharmony_ci walk->nents = j; 4718c2ecf20Sopenharmony_ci} 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_cistatic inline void ulptx_walk_init(struct ulptx_walk *walk, 4748c2ecf20Sopenharmony_ci struct ulptx_sgl *ulp) 4758c2ecf20Sopenharmony_ci{ 4768c2ecf20Sopenharmony_ci walk->sgl = ulp; 4778c2ecf20Sopenharmony_ci walk->nents = 0; 4788c2ecf20Sopenharmony_ci walk->pair_idx = 0; 4798c2ecf20Sopenharmony_ci walk->pair = ulp->sge; 4808c2ecf20Sopenharmony_ci walk->last_sg = NULL; 4818c2ecf20Sopenharmony_ci walk->last_sg_len = 0; 4828c2ecf20Sopenharmony_ci} 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_cistatic inline void ulptx_walk_end(struct ulptx_walk *walk) 4858c2ecf20Sopenharmony_ci{ 4868c2ecf20Sopenharmony_ci walk->sgl->cmd_nsge = htonl(ULPTX_CMD_V(ULP_TX_SC_DSGL) | 4878c2ecf20Sopenharmony_ci ULPTX_NSGE_V(walk->nents)); 4888c2ecf20Sopenharmony_ci} 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_cistatic inline void ulptx_walk_add_page(struct ulptx_walk *walk, 4928c2ecf20Sopenharmony_ci size_t size, 4938c2ecf20Sopenharmony_ci dma_addr_t addr) 4948c2ecf20Sopenharmony_ci{ 4958c2ecf20Sopenharmony_ci if (!size) 4968c2ecf20Sopenharmony_ci return; 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ci if (walk->nents == 0) { 4998c2ecf20Sopenharmony_ci walk->sgl->len0 = cpu_to_be32(size); 5008c2ecf20Sopenharmony_ci walk->sgl->addr0 = cpu_to_be64(addr); 5018c2ecf20Sopenharmony_ci } else { 5028c2ecf20Sopenharmony_ci walk->pair->addr[walk->pair_idx] = cpu_to_be64(addr); 5038c2ecf20Sopenharmony_ci walk->pair->len[walk->pair_idx] = cpu_to_be32(size); 5048c2ecf20Sopenharmony_ci walk->pair_idx = !walk->pair_idx; 5058c2ecf20Sopenharmony_ci if (!walk->pair_idx) 5068c2ecf20Sopenharmony_ci walk->pair++; 5078c2ecf20Sopenharmony_ci } 5088c2ecf20Sopenharmony_ci walk->nents++; 5098c2ecf20Sopenharmony_ci} 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_cistatic void ulptx_walk_add_sg(struct ulptx_walk *walk, 5128c2ecf20Sopenharmony_ci struct scatterlist *sg, 5138c2ecf20Sopenharmony_ci unsigned int len, 5148c2ecf20Sopenharmony_ci unsigned int skip) 5158c2ecf20Sopenharmony_ci{ 5168c2ecf20Sopenharmony_ci int small; 5178c2ecf20Sopenharmony_ci int skip_len = 0; 5188c2ecf20Sopenharmony_ci unsigned int sgmin; 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_ci if (!len) 5218c2ecf20Sopenharmony_ci return; 5228c2ecf20Sopenharmony_ci while (sg && skip) { 5238c2ecf20Sopenharmony_ci if (sg_dma_len(sg) <= skip) { 5248c2ecf20Sopenharmony_ci skip -= sg_dma_len(sg); 5258c2ecf20Sopenharmony_ci skip_len = 0; 5268c2ecf20Sopenharmony_ci sg = sg_next(sg); 5278c2ecf20Sopenharmony_ci } else { 5288c2ecf20Sopenharmony_ci skip_len = skip; 5298c2ecf20Sopenharmony_ci skip = 0; 5308c2ecf20Sopenharmony_ci } 5318c2ecf20Sopenharmony_ci } 5328c2ecf20Sopenharmony_ci WARN(!sg, "SG should not be null here\n"); 5338c2ecf20Sopenharmony_ci if (sg && (walk->nents == 0)) { 5348c2ecf20Sopenharmony_ci small = min_t(unsigned int, sg_dma_len(sg) - skip_len, len); 5358c2ecf20Sopenharmony_ci sgmin = min_t(unsigned int, small, CHCR_SRC_SG_SIZE); 5368c2ecf20Sopenharmony_ci walk->sgl->len0 = cpu_to_be32(sgmin); 5378c2ecf20Sopenharmony_ci walk->sgl->addr0 = cpu_to_be64(sg_dma_address(sg) + skip_len); 5388c2ecf20Sopenharmony_ci walk->nents++; 5398c2ecf20Sopenharmony_ci len -= sgmin; 5408c2ecf20Sopenharmony_ci walk->last_sg = sg; 5418c2ecf20Sopenharmony_ci walk->last_sg_len = sgmin + skip_len; 5428c2ecf20Sopenharmony_ci skip_len += sgmin; 5438c2ecf20Sopenharmony_ci if (sg_dma_len(sg) == skip_len) { 5448c2ecf20Sopenharmony_ci sg = sg_next(sg); 5458c2ecf20Sopenharmony_ci skip_len = 0; 5468c2ecf20Sopenharmony_ci } 5478c2ecf20Sopenharmony_ci } 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_ci while (sg && len) { 5508c2ecf20Sopenharmony_ci small = min(sg_dma_len(sg) - skip_len, len); 5518c2ecf20Sopenharmony_ci sgmin = min_t(unsigned int, small, CHCR_SRC_SG_SIZE); 5528c2ecf20Sopenharmony_ci walk->pair->len[walk->pair_idx] = cpu_to_be32(sgmin); 5538c2ecf20Sopenharmony_ci walk->pair->addr[walk->pair_idx] = 5548c2ecf20Sopenharmony_ci cpu_to_be64(sg_dma_address(sg) + skip_len); 5558c2ecf20Sopenharmony_ci walk->pair_idx = !walk->pair_idx; 5568c2ecf20Sopenharmony_ci walk->nents++; 5578c2ecf20Sopenharmony_ci if (!walk->pair_idx) 5588c2ecf20Sopenharmony_ci walk->pair++; 5598c2ecf20Sopenharmony_ci len -= sgmin; 5608c2ecf20Sopenharmony_ci skip_len += sgmin; 5618c2ecf20Sopenharmony_ci walk->last_sg = sg; 5628c2ecf20Sopenharmony_ci walk->last_sg_len = skip_len; 5638c2ecf20Sopenharmony_ci if (sg_dma_len(sg) == skip_len) { 5648c2ecf20Sopenharmony_ci sg = sg_next(sg); 5658c2ecf20Sopenharmony_ci skip_len = 0; 5668c2ecf20Sopenharmony_ci } 5678c2ecf20Sopenharmony_ci } 5688c2ecf20Sopenharmony_ci} 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_cistatic inline int get_cryptoalg_subtype(struct crypto_skcipher *tfm) 5718c2ecf20Sopenharmony_ci{ 5728c2ecf20Sopenharmony_ci struct skcipher_alg *alg = crypto_skcipher_alg(tfm); 5738c2ecf20Sopenharmony_ci struct chcr_alg_template *chcr_crypto_alg = 5748c2ecf20Sopenharmony_ci container_of(alg, struct chcr_alg_template, alg.skcipher); 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci return chcr_crypto_alg->type & CRYPTO_ALG_SUB_TYPE_MASK; 5778c2ecf20Sopenharmony_ci} 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_cistatic int cxgb4_is_crypto_q_full(struct net_device *dev, unsigned int idx) 5808c2ecf20Sopenharmony_ci{ 5818c2ecf20Sopenharmony_ci struct adapter *adap = netdev2adap(dev); 5828c2ecf20Sopenharmony_ci struct sge_uld_txq_info *txq_info = 5838c2ecf20Sopenharmony_ci adap->sge.uld_txq_info[CXGB4_TX_CRYPTO]; 5848c2ecf20Sopenharmony_ci struct sge_uld_txq *txq; 5858c2ecf20Sopenharmony_ci int ret = 0; 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_ci local_bh_disable(); 5888c2ecf20Sopenharmony_ci txq = &txq_info->uldtxq[idx]; 5898c2ecf20Sopenharmony_ci spin_lock(&txq->sendq.lock); 5908c2ecf20Sopenharmony_ci if (txq->full) 5918c2ecf20Sopenharmony_ci ret = -1; 5928c2ecf20Sopenharmony_ci spin_unlock(&txq->sendq.lock); 5938c2ecf20Sopenharmony_ci local_bh_enable(); 5948c2ecf20Sopenharmony_ci return ret; 5958c2ecf20Sopenharmony_ci} 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_cistatic int generate_copy_rrkey(struct ablk_ctx *ablkctx, 5988c2ecf20Sopenharmony_ci struct _key_ctx *key_ctx) 5998c2ecf20Sopenharmony_ci{ 6008c2ecf20Sopenharmony_ci if (ablkctx->ciph_mode == CHCR_SCMD_CIPHER_MODE_AES_CBC) { 6018c2ecf20Sopenharmony_ci memcpy(key_ctx->key, ablkctx->rrkey, ablkctx->enckey_len); 6028c2ecf20Sopenharmony_ci } else { 6038c2ecf20Sopenharmony_ci memcpy(key_ctx->key, 6048c2ecf20Sopenharmony_ci ablkctx->key + (ablkctx->enckey_len >> 1), 6058c2ecf20Sopenharmony_ci ablkctx->enckey_len >> 1); 6068c2ecf20Sopenharmony_ci memcpy(key_ctx->key + (ablkctx->enckey_len >> 1), 6078c2ecf20Sopenharmony_ci ablkctx->rrkey, ablkctx->enckey_len >> 1); 6088c2ecf20Sopenharmony_ci } 6098c2ecf20Sopenharmony_ci return 0; 6108c2ecf20Sopenharmony_ci} 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_cistatic int chcr_hash_ent_in_wr(struct scatterlist *src, 6138c2ecf20Sopenharmony_ci unsigned int minsg, 6148c2ecf20Sopenharmony_ci unsigned int space, 6158c2ecf20Sopenharmony_ci unsigned int srcskip) 6168c2ecf20Sopenharmony_ci{ 6178c2ecf20Sopenharmony_ci int srclen = 0; 6188c2ecf20Sopenharmony_ci int srcsg = minsg; 6198c2ecf20Sopenharmony_ci int soffset = 0, sless; 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_ci if (sg_dma_len(src) == srcskip) { 6228c2ecf20Sopenharmony_ci src = sg_next(src); 6238c2ecf20Sopenharmony_ci srcskip = 0; 6248c2ecf20Sopenharmony_ci } 6258c2ecf20Sopenharmony_ci while (src && space > (sgl_ent_len[srcsg + 1])) { 6268c2ecf20Sopenharmony_ci sless = min_t(unsigned int, sg_dma_len(src) - soffset - srcskip, 6278c2ecf20Sopenharmony_ci CHCR_SRC_SG_SIZE); 6288c2ecf20Sopenharmony_ci srclen += sless; 6298c2ecf20Sopenharmony_ci soffset += sless; 6308c2ecf20Sopenharmony_ci srcsg++; 6318c2ecf20Sopenharmony_ci if (sg_dma_len(src) == (soffset + srcskip)) { 6328c2ecf20Sopenharmony_ci src = sg_next(src); 6338c2ecf20Sopenharmony_ci soffset = 0; 6348c2ecf20Sopenharmony_ci srcskip = 0; 6358c2ecf20Sopenharmony_ci } 6368c2ecf20Sopenharmony_ci } 6378c2ecf20Sopenharmony_ci return srclen; 6388c2ecf20Sopenharmony_ci} 6398c2ecf20Sopenharmony_ci 6408c2ecf20Sopenharmony_cistatic int chcr_sg_ent_in_wr(struct scatterlist *src, 6418c2ecf20Sopenharmony_ci struct scatterlist *dst, 6428c2ecf20Sopenharmony_ci unsigned int minsg, 6438c2ecf20Sopenharmony_ci unsigned int space, 6448c2ecf20Sopenharmony_ci unsigned int srcskip, 6458c2ecf20Sopenharmony_ci unsigned int dstskip) 6468c2ecf20Sopenharmony_ci{ 6478c2ecf20Sopenharmony_ci int srclen = 0, dstlen = 0; 6488c2ecf20Sopenharmony_ci int srcsg = minsg, dstsg = minsg; 6498c2ecf20Sopenharmony_ci int offset = 0, soffset = 0, less, sless = 0; 6508c2ecf20Sopenharmony_ci 6518c2ecf20Sopenharmony_ci if (sg_dma_len(src) == srcskip) { 6528c2ecf20Sopenharmony_ci src = sg_next(src); 6538c2ecf20Sopenharmony_ci srcskip = 0; 6548c2ecf20Sopenharmony_ci } 6558c2ecf20Sopenharmony_ci if (sg_dma_len(dst) == dstskip) { 6568c2ecf20Sopenharmony_ci dst = sg_next(dst); 6578c2ecf20Sopenharmony_ci dstskip = 0; 6588c2ecf20Sopenharmony_ci } 6598c2ecf20Sopenharmony_ci 6608c2ecf20Sopenharmony_ci while (src && dst && 6618c2ecf20Sopenharmony_ci space > (sgl_ent_len[srcsg + 1] + dsgl_ent_len[dstsg])) { 6628c2ecf20Sopenharmony_ci sless = min_t(unsigned int, sg_dma_len(src) - srcskip - soffset, 6638c2ecf20Sopenharmony_ci CHCR_SRC_SG_SIZE); 6648c2ecf20Sopenharmony_ci srclen += sless; 6658c2ecf20Sopenharmony_ci srcsg++; 6668c2ecf20Sopenharmony_ci offset = 0; 6678c2ecf20Sopenharmony_ci while (dst && ((dstsg + 1) <= MAX_DSGL_ENT) && 6688c2ecf20Sopenharmony_ci space > (sgl_ent_len[srcsg] + dsgl_ent_len[dstsg + 1])) { 6698c2ecf20Sopenharmony_ci if (srclen <= dstlen) 6708c2ecf20Sopenharmony_ci break; 6718c2ecf20Sopenharmony_ci less = min_t(unsigned int, sg_dma_len(dst) - offset - 6728c2ecf20Sopenharmony_ci dstskip, CHCR_DST_SG_SIZE); 6738c2ecf20Sopenharmony_ci dstlen += less; 6748c2ecf20Sopenharmony_ci offset += less; 6758c2ecf20Sopenharmony_ci if ((offset + dstskip) == sg_dma_len(dst)) { 6768c2ecf20Sopenharmony_ci dst = sg_next(dst); 6778c2ecf20Sopenharmony_ci offset = 0; 6788c2ecf20Sopenharmony_ci } 6798c2ecf20Sopenharmony_ci dstsg++; 6808c2ecf20Sopenharmony_ci dstskip = 0; 6818c2ecf20Sopenharmony_ci } 6828c2ecf20Sopenharmony_ci soffset += sless; 6838c2ecf20Sopenharmony_ci if ((soffset + srcskip) == sg_dma_len(src)) { 6848c2ecf20Sopenharmony_ci src = sg_next(src); 6858c2ecf20Sopenharmony_ci srcskip = 0; 6868c2ecf20Sopenharmony_ci soffset = 0; 6878c2ecf20Sopenharmony_ci } 6888c2ecf20Sopenharmony_ci 6898c2ecf20Sopenharmony_ci } 6908c2ecf20Sopenharmony_ci return min(srclen, dstlen); 6918c2ecf20Sopenharmony_ci} 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_cistatic int chcr_cipher_fallback(struct crypto_skcipher *cipher, 6948c2ecf20Sopenharmony_ci struct skcipher_request *req, 6958c2ecf20Sopenharmony_ci u8 *iv, 6968c2ecf20Sopenharmony_ci unsigned short op_type) 6978c2ecf20Sopenharmony_ci{ 6988c2ecf20Sopenharmony_ci struct chcr_skcipher_req_ctx *reqctx = skcipher_request_ctx(req); 6998c2ecf20Sopenharmony_ci int err; 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_ci skcipher_request_set_tfm(&reqctx->fallback_req, cipher); 7028c2ecf20Sopenharmony_ci skcipher_request_set_callback(&reqctx->fallback_req, req->base.flags, 7038c2ecf20Sopenharmony_ci req->base.complete, req->base.data); 7048c2ecf20Sopenharmony_ci skcipher_request_set_crypt(&reqctx->fallback_req, req->src, req->dst, 7058c2ecf20Sopenharmony_ci req->cryptlen, iv); 7068c2ecf20Sopenharmony_ci 7078c2ecf20Sopenharmony_ci err = op_type ? crypto_skcipher_decrypt(&reqctx->fallback_req) : 7088c2ecf20Sopenharmony_ci crypto_skcipher_encrypt(&reqctx->fallback_req); 7098c2ecf20Sopenharmony_ci 7108c2ecf20Sopenharmony_ci return err; 7118c2ecf20Sopenharmony_ci 7128c2ecf20Sopenharmony_ci} 7138c2ecf20Sopenharmony_ci 7148c2ecf20Sopenharmony_cistatic inline int get_qidxs(struct crypto_async_request *req, 7158c2ecf20Sopenharmony_ci unsigned int *txqidx, unsigned int *rxqidx) 7168c2ecf20Sopenharmony_ci{ 7178c2ecf20Sopenharmony_ci struct crypto_tfm *tfm = req->tfm; 7188c2ecf20Sopenharmony_ci int ret = 0; 7198c2ecf20Sopenharmony_ci 7208c2ecf20Sopenharmony_ci switch (tfm->__crt_alg->cra_flags & CRYPTO_ALG_TYPE_MASK) { 7218c2ecf20Sopenharmony_ci case CRYPTO_ALG_TYPE_AEAD: 7228c2ecf20Sopenharmony_ci { 7238c2ecf20Sopenharmony_ci struct aead_request *aead_req = 7248c2ecf20Sopenharmony_ci container_of(req, struct aead_request, base); 7258c2ecf20Sopenharmony_ci struct chcr_aead_reqctx *reqctx = aead_request_ctx(aead_req); 7268c2ecf20Sopenharmony_ci *txqidx = reqctx->txqidx; 7278c2ecf20Sopenharmony_ci *rxqidx = reqctx->rxqidx; 7288c2ecf20Sopenharmony_ci break; 7298c2ecf20Sopenharmony_ci } 7308c2ecf20Sopenharmony_ci case CRYPTO_ALG_TYPE_SKCIPHER: 7318c2ecf20Sopenharmony_ci { 7328c2ecf20Sopenharmony_ci struct skcipher_request *sk_req = 7338c2ecf20Sopenharmony_ci container_of(req, struct skcipher_request, base); 7348c2ecf20Sopenharmony_ci struct chcr_skcipher_req_ctx *reqctx = 7358c2ecf20Sopenharmony_ci skcipher_request_ctx(sk_req); 7368c2ecf20Sopenharmony_ci *txqidx = reqctx->txqidx; 7378c2ecf20Sopenharmony_ci *rxqidx = reqctx->rxqidx; 7388c2ecf20Sopenharmony_ci break; 7398c2ecf20Sopenharmony_ci } 7408c2ecf20Sopenharmony_ci case CRYPTO_ALG_TYPE_AHASH: 7418c2ecf20Sopenharmony_ci { 7428c2ecf20Sopenharmony_ci struct ahash_request *ahash_req = 7438c2ecf20Sopenharmony_ci container_of(req, struct ahash_request, base); 7448c2ecf20Sopenharmony_ci struct chcr_ahash_req_ctx *reqctx = 7458c2ecf20Sopenharmony_ci ahash_request_ctx(ahash_req); 7468c2ecf20Sopenharmony_ci *txqidx = reqctx->txqidx; 7478c2ecf20Sopenharmony_ci *rxqidx = reqctx->rxqidx; 7488c2ecf20Sopenharmony_ci break; 7498c2ecf20Sopenharmony_ci } 7508c2ecf20Sopenharmony_ci default: 7518c2ecf20Sopenharmony_ci ret = -EINVAL; 7528c2ecf20Sopenharmony_ci /* should never get here */ 7538c2ecf20Sopenharmony_ci BUG(); 7548c2ecf20Sopenharmony_ci break; 7558c2ecf20Sopenharmony_ci } 7568c2ecf20Sopenharmony_ci return ret; 7578c2ecf20Sopenharmony_ci} 7588c2ecf20Sopenharmony_ci 7598c2ecf20Sopenharmony_cistatic inline void create_wreq(struct chcr_context *ctx, 7608c2ecf20Sopenharmony_ci struct chcr_wr *chcr_req, 7618c2ecf20Sopenharmony_ci struct crypto_async_request *req, 7628c2ecf20Sopenharmony_ci unsigned int imm, 7638c2ecf20Sopenharmony_ci int hash_sz, 7648c2ecf20Sopenharmony_ci unsigned int len16, 7658c2ecf20Sopenharmony_ci unsigned int sc_len, 7668c2ecf20Sopenharmony_ci unsigned int lcb) 7678c2ecf20Sopenharmony_ci{ 7688c2ecf20Sopenharmony_ci struct uld_ctx *u_ctx = ULD_CTX(ctx); 7698c2ecf20Sopenharmony_ci unsigned int tx_channel_id, rx_channel_id; 7708c2ecf20Sopenharmony_ci unsigned int txqidx = 0, rxqidx = 0; 7718c2ecf20Sopenharmony_ci unsigned int qid, fid, portno; 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_ci get_qidxs(req, &txqidx, &rxqidx); 7748c2ecf20Sopenharmony_ci qid = u_ctx->lldi.rxq_ids[rxqidx]; 7758c2ecf20Sopenharmony_ci fid = u_ctx->lldi.rxq_ids[0]; 7768c2ecf20Sopenharmony_ci portno = rxqidx / ctx->rxq_perchan; 7778c2ecf20Sopenharmony_ci tx_channel_id = txqidx / ctx->txq_perchan; 7788c2ecf20Sopenharmony_ci rx_channel_id = cxgb4_port_e2cchan(u_ctx->lldi.ports[portno]); 7798c2ecf20Sopenharmony_ci 7808c2ecf20Sopenharmony_ci 7818c2ecf20Sopenharmony_ci chcr_req->wreq.op_to_cctx_size = FILL_WR_OP_CCTX_SIZE; 7828c2ecf20Sopenharmony_ci chcr_req->wreq.pld_size_hash_size = 7838c2ecf20Sopenharmony_ci htonl(FW_CRYPTO_LOOKASIDE_WR_HASH_SIZE_V(hash_sz)); 7848c2ecf20Sopenharmony_ci chcr_req->wreq.len16_pkd = 7858c2ecf20Sopenharmony_ci htonl(FW_CRYPTO_LOOKASIDE_WR_LEN16_V(DIV_ROUND_UP(len16, 16))); 7868c2ecf20Sopenharmony_ci chcr_req->wreq.cookie = cpu_to_be64((uintptr_t)req); 7878c2ecf20Sopenharmony_ci chcr_req->wreq.rx_chid_to_rx_q_id = FILL_WR_RX_Q_ID(rx_channel_id, qid, 7888c2ecf20Sopenharmony_ci !!lcb, txqidx); 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_ci chcr_req->ulptx.cmd_dest = FILL_ULPTX_CMD_DEST(tx_channel_id, fid); 7918c2ecf20Sopenharmony_ci chcr_req->ulptx.len = htonl((DIV_ROUND_UP(len16, 16) - 7928c2ecf20Sopenharmony_ci ((sizeof(chcr_req->wreq)) >> 4))); 7938c2ecf20Sopenharmony_ci chcr_req->sc_imm.cmd_more = FILL_CMD_MORE(!imm); 7948c2ecf20Sopenharmony_ci chcr_req->sc_imm.len = cpu_to_be32(sizeof(struct cpl_tx_sec_pdu) + 7958c2ecf20Sopenharmony_ci sizeof(chcr_req->key_ctx) + sc_len); 7968c2ecf20Sopenharmony_ci} 7978c2ecf20Sopenharmony_ci 7988c2ecf20Sopenharmony_ci/** 7998c2ecf20Sopenharmony_ci * create_cipher_wr - form the WR for cipher operations 8008c2ecf20Sopenharmony_ci * @req: cipher req. 8018c2ecf20Sopenharmony_ci * @ctx: crypto driver context of the request. 8028c2ecf20Sopenharmony_ci * @qid: ingress qid where response of this WR should be received. 8038c2ecf20Sopenharmony_ci * @op_type: encryption or decryption 8048c2ecf20Sopenharmony_ci */ 8058c2ecf20Sopenharmony_cistatic struct sk_buff *create_cipher_wr(struct cipher_wr_param *wrparam) 8068c2ecf20Sopenharmony_ci{ 8078c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(wrparam->req); 8088c2ecf20Sopenharmony_ci struct chcr_context *ctx = c_ctx(tfm); 8098c2ecf20Sopenharmony_ci struct uld_ctx *u_ctx = ULD_CTX(ctx); 8108c2ecf20Sopenharmony_ci struct ablk_ctx *ablkctx = ABLK_CTX(ctx); 8118c2ecf20Sopenharmony_ci struct sk_buff *skb = NULL; 8128c2ecf20Sopenharmony_ci struct chcr_wr *chcr_req; 8138c2ecf20Sopenharmony_ci struct cpl_rx_phys_dsgl *phys_cpl; 8148c2ecf20Sopenharmony_ci struct ulptx_sgl *ulptx; 8158c2ecf20Sopenharmony_ci struct chcr_skcipher_req_ctx *reqctx = 8168c2ecf20Sopenharmony_ci skcipher_request_ctx(wrparam->req); 8178c2ecf20Sopenharmony_ci unsigned int temp = 0, transhdr_len, dst_size; 8188c2ecf20Sopenharmony_ci int error; 8198c2ecf20Sopenharmony_ci int nents; 8208c2ecf20Sopenharmony_ci unsigned int kctx_len; 8218c2ecf20Sopenharmony_ci gfp_t flags = wrparam->req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? 8228c2ecf20Sopenharmony_ci GFP_KERNEL : GFP_ATOMIC; 8238c2ecf20Sopenharmony_ci struct adapter *adap = padap(ctx->dev); 8248c2ecf20Sopenharmony_ci unsigned int rx_channel_id = reqctx->rxqidx / ctx->rxq_perchan; 8258c2ecf20Sopenharmony_ci 8268c2ecf20Sopenharmony_ci rx_channel_id = cxgb4_port_e2cchan(u_ctx->lldi.ports[rx_channel_id]); 8278c2ecf20Sopenharmony_ci nents = sg_nents_xlen(reqctx->dstsg, wrparam->bytes, CHCR_DST_SG_SIZE, 8288c2ecf20Sopenharmony_ci reqctx->dst_ofst); 8298c2ecf20Sopenharmony_ci dst_size = get_space_for_phys_dsgl(nents); 8308c2ecf20Sopenharmony_ci kctx_len = roundup(ablkctx->enckey_len, 16); 8318c2ecf20Sopenharmony_ci transhdr_len = CIPHER_TRANSHDR_SIZE(kctx_len, dst_size); 8328c2ecf20Sopenharmony_ci nents = sg_nents_xlen(reqctx->srcsg, wrparam->bytes, 8338c2ecf20Sopenharmony_ci CHCR_SRC_SG_SIZE, reqctx->src_ofst); 8348c2ecf20Sopenharmony_ci temp = reqctx->imm ? roundup(wrparam->bytes, 16) : 8358c2ecf20Sopenharmony_ci (sgl_len(nents) * 8); 8368c2ecf20Sopenharmony_ci transhdr_len += temp; 8378c2ecf20Sopenharmony_ci transhdr_len = roundup(transhdr_len, 16); 8388c2ecf20Sopenharmony_ci skb = alloc_skb(SGE_MAX_WR_LEN, flags); 8398c2ecf20Sopenharmony_ci if (!skb) { 8408c2ecf20Sopenharmony_ci error = -ENOMEM; 8418c2ecf20Sopenharmony_ci goto err; 8428c2ecf20Sopenharmony_ci } 8438c2ecf20Sopenharmony_ci chcr_req = __skb_put_zero(skb, transhdr_len); 8448c2ecf20Sopenharmony_ci chcr_req->sec_cpl.op_ivinsrtofst = 8458c2ecf20Sopenharmony_ci FILL_SEC_CPL_OP_IVINSR(rx_channel_id, 2, 1); 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_ci chcr_req->sec_cpl.pldlen = htonl(IV + wrparam->bytes); 8488c2ecf20Sopenharmony_ci chcr_req->sec_cpl.aadstart_cipherstop_hi = 8498c2ecf20Sopenharmony_ci FILL_SEC_CPL_CIPHERSTOP_HI(0, 0, IV + 1, 0); 8508c2ecf20Sopenharmony_ci 8518c2ecf20Sopenharmony_ci chcr_req->sec_cpl.cipherstop_lo_authinsert = 8528c2ecf20Sopenharmony_ci FILL_SEC_CPL_AUTHINSERT(0, 0, 0, 0); 8538c2ecf20Sopenharmony_ci chcr_req->sec_cpl.seqno_numivs = FILL_SEC_CPL_SCMD0_SEQNO(reqctx->op, 0, 8548c2ecf20Sopenharmony_ci ablkctx->ciph_mode, 8558c2ecf20Sopenharmony_ci 0, 0, IV >> 1); 8568c2ecf20Sopenharmony_ci chcr_req->sec_cpl.ivgen_hdrlen = FILL_SEC_CPL_IVGEN_HDRLEN(0, 0, 0, 8578c2ecf20Sopenharmony_ci 0, 1, dst_size); 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_ci chcr_req->key_ctx.ctx_hdr = ablkctx->key_ctx_hdr; 8608c2ecf20Sopenharmony_ci if ((reqctx->op == CHCR_DECRYPT_OP) && 8618c2ecf20Sopenharmony_ci (!(get_cryptoalg_subtype(tfm) == 8628c2ecf20Sopenharmony_ci CRYPTO_ALG_SUB_TYPE_CTR)) && 8638c2ecf20Sopenharmony_ci (!(get_cryptoalg_subtype(tfm) == 8648c2ecf20Sopenharmony_ci CRYPTO_ALG_SUB_TYPE_CTR_RFC3686))) { 8658c2ecf20Sopenharmony_ci generate_copy_rrkey(ablkctx, &chcr_req->key_ctx); 8668c2ecf20Sopenharmony_ci } else { 8678c2ecf20Sopenharmony_ci if ((ablkctx->ciph_mode == CHCR_SCMD_CIPHER_MODE_AES_CBC) || 8688c2ecf20Sopenharmony_ci (ablkctx->ciph_mode == CHCR_SCMD_CIPHER_MODE_AES_CTR)) { 8698c2ecf20Sopenharmony_ci memcpy(chcr_req->key_ctx.key, ablkctx->key, 8708c2ecf20Sopenharmony_ci ablkctx->enckey_len); 8718c2ecf20Sopenharmony_ci } else { 8728c2ecf20Sopenharmony_ci memcpy(chcr_req->key_ctx.key, ablkctx->key + 8738c2ecf20Sopenharmony_ci (ablkctx->enckey_len >> 1), 8748c2ecf20Sopenharmony_ci ablkctx->enckey_len >> 1); 8758c2ecf20Sopenharmony_ci memcpy(chcr_req->key_ctx.key + 8768c2ecf20Sopenharmony_ci (ablkctx->enckey_len >> 1), 8778c2ecf20Sopenharmony_ci ablkctx->key, 8788c2ecf20Sopenharmony_ci ablkctx->enckey_len >> 1); 8798c2ecf20Sopenharmony_ci } 8808c2ecf20Sopenharmony_ci } 8818c2ecf20Sopenharmony_ci phys_cpl = (struct cpl_rx_phys_dsgl *)((u8 *)(chcr_req + 1) + kctx_len); 8828c2ecf20Sopenharmony_ci ulptx = (struct ulptx_sgl *)((u8 *)(phys_cpl + 1) + dst_size); 8838c2ecf20Sopenharmony_ci chcr_add_cipher_src_ent(wrparam->req, ulptx, wrparam); 8848c2ecf20Sopenharmony_ci chcr_add_cipher_dst_ent(wrparam->req, phys_cpl, wrparam, wrparam->qid); 8858c2ecf20Sopenharmony_ci 8868c2ecf20Sopenharmony_ci atomic_inc(&adap->chcr_stats.cipher_rqst); 8878c2ecf20Sopenharmony_ci temp = sizeof(struct cpl_rx_phys_dsgl) + dst_size + kctx_len + IV 8888c2ecf20Sopenharmony_ci + (reqctx->imm ? (wrparam->bytes) : 0); 8898c2ecf20Sopenharmony_ci create_wreq(c_ctx(tfm), chcr_req, &(wrparam->req->base), reqctx->imm, 0, 8908c2ecf20Sopenharmony_ci transhdr_len, temp, 8918c2ecf20Sopenharmony_ci ablkctx->ciph_mode == CHCR_SCMD_CIPHER_MODE_AES_CBC); 8928c2ecf20Sopenharmony_ci reqctx->skb = skb; 8938c2ecf20Sopenharmony_ci 8948c2ecf20Sopenharmony_ci if (reqctx->op && (ablkctx->ciph_mode == 8958c2ecf20Sopenharmony_ci CHCR_SCMD_CIPHER_MODE_AES_CBC)) 8968c2ecf20Sopenharmony_ci sg_pcopy_to_buffer(wrparam->req->src, 8978c2ecf20Sopenharmony_ci sg_nents(wrparam->req->src), wrparam->req->iv, 16, 8988c2ecf20Sopenharmony_ci reqctx->processed + wrparam->bytes - AES_BLOCK_SIZE); 8998c2ecf20Sopenharmony_ci 9008c2ecf20Sopenharmony_ci return skb; 9018c2ecf20Sopenharmony_cierr: 9028c2ecf20Sopenharmony_ci return ERR_PTR(error); 9038c2ecf20Sopenharmony_ci} 9048c2ecf20Sopenharmony_ci 9058c2ecf20Sopenharmony_cistatic inline int chcr_keyctx_ck_size(unsigned int keylen) 9068c2ecf20Sopenharmony_ci{ 9078c2ecf20Sopenharmony_ci int ck_size = 0; 9088c2ecf20Sopenharmony_ci 9098c2ecf20Sopenharmony_ci if (keylen == AES_KEYSIZE_128) 9108c2ecf20Sopenharmony_ci ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_128; 9118c2ecf20Sopenharmony_ci else if (keylen == AES_KEYSIZE_192) 9128c2ecf20Sopenharmony_ci ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_192; 9138c2ecf20Sopenharmony_ci else if (keylen == AES_KEYSIZE_256) 9148c2ecf20Sopenharmony_ci ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_256; 9158c2ecf20Sopenharmony_ci else 9168c2ecf20Sopenharmony_ci ck_size = 0; 9178c2ecf20Sopenharmony_ci 9188c2ecf20Sopenharmony_ci return ck_size; 9198c2ecf20Sopenharmony_ci} 9208c2ecf20Sopenharmony_cistatic int chcr_cipher_fallback_setkey(struct crypto_skcipher *cipher, 9218c2ecf20Sopenharmony_ci const u8 *key, 9228c2ecf20Sopenharmony_ci unsigned int keylen) 9238c2ecf20Sopenharmony_ci{ 9248c2ecf20Sopenharmony_ci struct ablk_ctx *ablkctx = ABLK_CTX(c_ctx(cipher)); 9258c2ecf20Sopenharmony_ci 9268c2ecf20Sopenharmony_ci crypto_skcipher_clear_flags(ablkctx->sw_cipher, 9278c2ecf20Sopenharmony_ci CRYPTO_TFM_REQ_MASK); 9288c2ecf20Sopenharmony_ci crypto_skcipher_set_flags(ablkctx->sw_cipher, 9298c2ecf20Sopenharmony_ci cipher->base.crt_flags & CRYPTO_TFM_REQ_MASK); 9308c2ecf20Sopenharmony_ci return crypto_skcipher_setkey(ablkctx->sw_cipher, key, keylen); 9318c2ecf20Sopenharmony_ci} 9328c2ecf20Sopenharmony_ci 9338c2ecf20Sopenharmony_cistatic int chcr_aes_cbc_setkey(struct crypto_skcipher *cipher, 9348c2ecf20Sopenharmony_ci const u8 *key, 9358c2ecf20Sopenharmony_ci unsigned int keylen) 9368c2ecf20Sopenharmony_ci{ 9378c2ecf20Sopenharmony_ci struct ablk_ctx *ablkctx = ABLK_CTX(c_ctx(cipher)); 9388c2ecf20Sopenharmony_ci unsigned int ck_size, context_size; 9398c2ecf20Sopenharmony_ci u16 alignment = 0; 9408c2ecf20Sopenharmony_ci int err; 9418c2ecf20Sopenharmony_ci 9428c2ecf20Sopenharmony_ci err = chcr_cipher_fallback_setkey(cipher, key, keylen); 9438c2ecf20Sopenharmony_ci if (err) 9448c2ecf20Sopenharmony_ci goto badkey_err; 9458c2ecf20Sopenharmony_ci 9468c2ecf20Sopenharmony_ci ck_size = chcr_keyctx_ck_size(keylen); 9478c2ecf20Sopenharmony_ci alignment = ck_size == CHCR_KEYCTX_CIPHER_KEY_SIZE_192 ? 8 : 0; 9488c2ecf20Sopenharmony_ci memcpy(ablkctx->key, key, keylen); 9498c2ecf20Sopenharmony_ci ablkctx->enckey_len = keylen; 9508c2ecf20Sopenharmony_ci get_aes_decrypt_key(ablkctx->rrkey, ablkctx->key, keylen << 3); 9518c2ecf20Sopenharmony_ci context_size = (KEY_CONTEXT_HDR_SALT_AND_PAD + 9528c2ecf20Sopenharmony_ci keylen + alignment) >> 4; 9538c2ecf20Sopenharmony_ci 9548c2ecf20Sopenharmony_ci ablkctx->key_ctx_hdr = FILL_KEY_CTX_HDR(ck_size, CHCR_KEYCTX_NO_KEY, 9558c2ecf20Sopenharmony_ci 0, 0, context_size); 9568c2ecf20Sopenharmony_ci ablkctx->ciph_mode = CHCR_SCMD_CIPHER_MODE_AES_CBC; 9578c2ecf20Sopenharmony_ci return 0; 9588c2ecf20Sopenharmony_cibadkey_err: 9598c2ecf20Sopenharmony_ci ablkctx->enckey_len = 0; 9608c2ecf20Sopenharmony_ci 9618c2ecf20Sopenharmony_ci return err; 9628c2ecf20Sopenharmony_ci} 9638c2ecf20Sopenharmony_ci 9648c2ecf20Sopenharmony_cistatic int chcr_aes_ctr_setkey(struct crypto_skcipher *cipher, 9658c2ecf20Sopenharmony_ci const u8 *key, 9668c2ecf20Sopenharmony_ci unsigned int keylen) 9678c2ecf20Sopenharmony_ci{ 9688c2ecf20Sopenharmony_ci struct ablk_ctx *ablkctx = ABLK_CTX(c_ctx(cipher)); 9698c2ecf20Sopenharmony_ci unsigned int ck_size, context_size; 9708c2ecf20Sopenharmony_ci u16 alignment = 0; 9718c2ecf20Sopenharmony_ci int err; 9728c2ecf20Sopenharmony_ci 9738c2ecf20Sopenharmony_ci err = chcr_cipher_fallback_setkey(cipher, key, keylen); 9748c2ecf20Sopenharmony_ci if (err) 9758c2ecf20Sopenharmony_ci goto badkey_err; 9768c2ecf20Sopenharmony_ci ck_size = chcr_keyctx_ck_size(keylen); 9778c2ecf20Sopenharmony_ci alignment = (ck_size == CHCR_KEYCTX_CIPHER_KEY_SIZE_192) ? 8 : 0; 9788c2ecf20Sopenharmony_ci memcpy(ablkctx->key, key, keylen); 9798c2ecf20Sopenharmony_ci ablkctx->enckey_len = keylen; 9808c2ecf20Sopenharmony_ci context_size = (KEY_CONTEXT_HDR_SALT_AND_PAD + 9818c2ecf20Sopenharmony_ci keylen + alignment) >> 4; 9828c2ecf20Sopenharmony_ci 9838c2ecf20Sopenharmony_ci ablkctx->key_ctx_hdr = FILL_KEY_CTX_HDR(ck_size, CHCR_KEYCTX_NO_KEY, 9848c2ecf20Sopenharmony_ci 0, 0, context_size); 9858c2ecf20Sopenharmony_ci ablkctx->ciph_mode = CHCR_SCMD_CIPHER_MODE_AES_CTR; 9868c2ecf20Sopenharmony_ci 9878c2ecf20Sopenharmony_ci return 0; 9888c2ecf20Sopenharmony_cibadkey_err: 9898c2ecf20Sopenharmony_ci ablkctx->enckey_len = 0; 9908c2ecf20Sopenharmony_ci 9918c2ecf20Sopenharmony_ci return err; 9928c2ecf20Sopenharmony_ci} 9938c2ecf20Sopenharmony_ci 9948c2ecf20Sopenharmony_cistatic int chcr_aes_rfc3686_setkey(struct crypto_skcipher *cipher, 9958c2ecf20Sopenharmony_ci const u8 *key, 9968c2ecf20Sopenharmony_ci unsigned int keylen) 9978c2ecf20Sopenharmony_ci{ 9988c2ecf20Sopenharmony_ci struct ablk_ctx *ablkctx = ABLK_CTX(c_ctx(cipher)); 9998c2ecf20Sopenharmony_ci unsigned int ck_size, context_size; 10008c2ecf20Sopenharmony_ci u16 alignment = 0; 10018c2ecf20Sopenharmony_ci int err; 10028c2ecf20Sopenharmony_ci 10038c2ecf20Sopenharmony_ci if (keylen < CTR_RFC3686_NONCE_SIZE) 10048c2ecf20Sopenharmony_ci return -EINVAL; 10058c2ecf20Sopenharmony_ci memcpy(ablkctx->nonce, key + (keylen - CTR_RFC3686_NONCE_SIZE), 10068c2ecf20Sopenharmony_ci CTR_RFC3686_NONCE_SIZE); 10078c2ecf20Sopenharmony_ci 10088c2ecf20Sopenharmony_ci keylen -= CTR_RFC3686_NONCE_SIZE; 10098c2ecf20Sopenharmony_ci err = chcr_cipher_fallback_setkey(cipher, key, keylen); 10108c2ecf20Sopenharmony_ci if (err) 10118c2ecf20Sopenharmony_ci goto badkey_err; 10128c2ecf20Sopenharmony_ci 10138c2ecf20Sopenharmony_ci ck_size = chcr_keyctx_ck_size(keylen); 10148c2ecf20Sopenharmony_ci alignment = (ck_size == CHCR_KEYCTX_CIPHER_KEY_SIZE_192) ? 8 : 0; 10158c2ecf20Sopenharmony_ci memcpy(ablkctx->key, key, keylen); 10168c2ecf20Sopenharmony_ci ablkctx->enckey_len = keylen; 10178c2ecf20Sopenharmony_ci context_size = (KEY_CONTEXT_HDR_SALT_AND_PAD + 10188c2ecf20Sopenharmony_ci keylen + alignment) >> 4; 10198c2ecf20Sopenharmony_ci 10208c2ecf20Sopenharmony_ci ablkctx->key_ctx_hdr = FILL_KEY_CTX_HDR(ck_size, CHCR_KEYCTX_NO_KEY, 10218c2ecf20Sopenharmony_ci 0, 0, context_size); 10228c2ecf20Sopenharmony_ci ablkctx->ciph_mode = CHCR_SCMD_CIPHER_MODE_AES_CTR; 10238c2ecf20Sopenharmony_ci 10248c2ecf20Sopenharmony_ci return 0; 10258c2ecf20Sopenharmony_cibadkey_err: 10268c2ecf20Sopenharmony_ci ablkctx->enckey_len = 0; 10278c2ecf20Sopenharmony_ci 10288c2ecf20Sopenharmony_ci return err; 10298c2ecf20Sopenharmony_ci} 10308c2ecf20Sopenharmony_cistatic void ctr_add_iv(u8 *dstiv, u8 *srciv, u32 add) 10318c2ecf20Sopenharmony_ci{ 10328c2ecf20Sopenharmony_ci unsigned int size = AES_BLOCK_SIZE; 10338c2ecf20Sopenharmony_ci __be32 *b = (__be32 *)(dstiv + size); 10348c2ecf20Sopenharmony_ci u32 c, prev; 10358c2ecf20Sopenharmony_ci 10368c2ecf20Sopenharmony_ci memcpy(dstiv, srciv, AES_BLOCK_SIZE); 10378c2ecf20Sopenharmony_ci for (; size >= 4; size -= 4) { 10388c2ecf20Sopenharmony_ci prev = be32_to_cpu(*--b); 10398c2ecf20Sopenharmony_ci c = prev + add; 10408c2ecf20Sopenharmony_ci *b = cpu_to_be32(c); 10418c2ecf20Sopenharmony_ci if (prev < c) 10428c2ecf20Sopenharmony_ci break; 10438c2ecf20Sopenharmony_ci add = 1; 10448c2ecf20Sopenharmony_ci } 10458c2ecf20Sopenharmony_ci 10468c2ecf20Sopenharmony_ci} 10478c2ecf20Sopenharmony_ci 10488c2ecf20Sopenharmony_cistatic unsigned int adjust_ctr_overflow(u8 *iv, u32 bytes) 10498c2ecf20Sopenharmony_ci{ 10508c2ecf20Sopenharmony_ci __be32 *b = (__be32 *)(iv + AES_BLOCK_SIZE); 10518c2ecf20Sopenharmony_ci u64 c; 10528c2ecf20Sopenharmony_ci u32 temp = be32_to_cpu(*--b); 10538c2ecf20Sopenharmony_ci 10548c2ecf20Sopenharmony_ci temp = ~temp; 10558c2ecf20Sopenharmony_ci c = (u64)temp + 1; // No of block can processed without overflow 10568c2ecf20Sopenharmony_ci if ((bytes / AES_BLOCK_SIZE) >= c) 10578c2ecf20Sopenharmony_ci bytes = c * AES_BLOCK_SIZE; 10588c2ecf20Sopenharmony_ci return bytes; 10598c2ecf20Sopenharmony_ci} 10608c2ecf20Sopenharmony_ci 10618c2ecf20Sopenharmony_cistatic int chcr_update_tweak(struct skcipher_request *req, u8 *iv, 10628c2ecf20Sopenharmony_ci u32 isfinal) 10638c2ecf20Sopenharmony_ci{ 10648c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 10658c2ecf20Sopenharmony_ci struct ablk_ctx *ablkctx = ABLK_CTX(c_ctx(tfm)); 10668c2ecf20Sopenharmony_ci struct chcr_skcipher_req_ctx *reqctx = skcipher_request_ctx(req); 10678c2ecf20Sopenharmony_ci struct crypto_aes_ctx aes; 10688c2ecf20Sopenharmony_ci int ret, i; 10698c2ecf20Sopenharmony_ci u8 *key; 10708c2ecf20Sopenharmony_ci unsigned int keylen; 10718c2ecf20Sopenharmony_ci int round = reqctx->last_req_len / AES_BLOCK_SIZE; 10728c2ecf20Sopenharmony_ci int round8 = round / 8; 10738c2ecf20Sopenharmony_ci 10748c2ecf20Sopenharmony_ci memcpy(iv, reqctx->iv, AES_BLOCK_SIZE); 10758c2ecf20Sopenharmony_ci 10768c2ecf20Sopenharmony_ci keylen = ablkctx->enckey_len / 2; 10778c2ecf20Sopenharmony_ci key = ablkctx->key + keylen; 10788c2ecf20Sopenharmony_ci /* For a 192 bit key remove the padded zeroes which was 10798c2ecf20Sopenharmony_ci * added in chcr_xts_setkey 10808c2ecf20Sopenharmony_ci */ 10818c2ecf20Sopenharmony_ci if (KEY_CONTEXT_CK_SIZE_G(ntohl(ablkctx->key_ctx_hdr)) 10828c2ecf20Sopenharmony_ci == CHCR_KEYCTX_CIPHER_KEY_SIZE_192) 10838c2ecf20Sopenharmony_ci ret = aes_expandkey(&aes, key, keylen - 8); 10848c2ecf20Sopenharmony_ci else 10858c2ecf20Sopenharmony_ci ret = aes_expandkey(&aes, key, keylen); 10868c2ecf20Sopenharmony_ci if (ret) 10878c2ecf20Sopenharmony_ci return ret; 10888c2ecf20Sopenharmony_ci aes_encrypt(&aes, iv, iv); 10898c2ecf20Sopenharmony_ci for (i = 0; i < round8; i++) 10908c2ecf20Sopenharmony_ci gf128mul_x8_ble((le128 *)iv, (le128 *)iv); 10918c2ecf20Sopenharmony_ci 10928c2ecf20Sopenharmony_ci for (i = 0; i < (round % 8); i++) 10938c2ecf20Sopenharmony_ci gf128mul_x_ble((le128 *)iv, (le128 *)iv); 10948c2ecf20Sopenharmony_ci 10958c2ecf20Sopenharmony_ci if (!isfinal) 10968c2ecf20Sopenharmony_ci aes_decrypt(&aes, iv, iv); 10978c2ecf20Sopenharmony_ci 10988c2ecf20Sopenharmony_ci memzero_explicit(&aes, sizeof(aes)); 10998c2ecf20Sopenharmony_ci return 0; 11008c2ecf20Sopenharmony_ci} 11018c2ecf20Sopenharmony_ci 11028c2ecf20Sopenharmony_cistatic int chcr_update_cipher_iv(struct skcipher_request *req, 11038c2ecf20Sopenharmony_ci struct cpl_fw6_pld *fw6_pld, u8 *iv) 11048c2ecf20Sopenharmony_ci{ 11058c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 11068c2ecf20Sopenharmony_ci struct chcr_skcipher_req_ctx *reqctx = skcipher_request_ctx(req); 11078c2ecf20Sopenharmony_ci int subtype = get_cryptoalg_subtype(tfm); 11088c2ecf20Sopenharmony_ci int ret = 0; 11098c2ecf20Sopenharmony_ci 11108c2ecf20Sopenharmony_ci if (subtype == CRYPTO_ALG_SUB_TYPE_CTR) 11118c2ecf20Sopenharmony_ci ctr_add_iv(iv, req->iv, (reqctx->processed / 11128c2ecf20Sopenharmony_ci AES_BLOCK_SIZE)); 11138c2ecf20Sopenharmony_ci else if (subtype == CRYPTO_ALG_SUB_TYPE_CTR_RFC3686) 11148c2ecf20Sopenharmony_ci *(__be32 *)(reqctx->iv + CTR_RFC3686_NONCE_SIZE + 11158c2ecf20Sopenharmony_ci CTR_RFC3686_IV_SIZE) = cpu_to_be32((reqctx->processed / 11168c2ecf20Sopenharmony_ci AES_BLOCK_SIZE) + 1); 11178c2ecf20Sopenharmony_ci else if (subtype == CRYPTO_ALG_SUB_TYPE_XTS) 11188c2ecf20Sopenharmony_ci ret = chcr_update_tweak(req, iv, 0); 11198c2ecf20Sopenharmony_ci else if (subtype == CRYPTO_ALG_SUB_TYPE_CBC) { 11208c2ecf20Sopenharmony_ci if (reqctx->op) 11218c2ecf20Sopenharmony_ci /*Updated before sending last WR*/ 11228c2ecf20Sopenharmony_ci memcpy(iv, req->iv, AES_BLOCK_SIZE); 11238c2ecf20Sopenharmony_ci else 11248c2ecf20Sopenharmony_ci memcpy(iv, &fw6_pld->data[2], AES_BLOCK_SIZE); 11258c2ecf20Sopenharmony_ci } 11268c2ecf20Sopenharmony_ci 11278c2ecf20Sopenharmony_ci return ret; 11288c2ecf20Sopenharmony_ci 11298c2ecf20Sopenharmony_ci} 11308c2ecf20Sopenharmony_ci 11318c2ecf20Sopenharmony_ci/* We need separate function for final iv because in rfc3686 Initial counter 11328c2ecf20Sopenharmony_ci * starts from 1 and buffer size of iv is 8 byte only which remains constant 11338c2ecf20Sopenharmony_ci * for subsequent update requests 11348c2ecf20Sopenharmony_ci */ 11358c2ecf20Sopenharmony_ci 11368c2ecf20Sopenharmony_cistatic int chcr_final_cipher_iv(struct skcipher_request *req, 11378c2ecf20Sopenharmony_ci struct cpl_fw6_pld *fw6_pld, u8 *iv) 11388c2ecf20Sopenharmony_ci{ 11398c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 11408c2ecf20Sopenharmony_ci struct chcr_skcipher_req_ctx *reqctx = skcipher_request_ctx(req); 11418c2ecf20Sopenharmony_ci int subtype = get_cryptoalg_subtype(tfm); 11428c2ecf20Sopenharmony_ci int ret = 0; 11438c2ecf20Sopenharmony_ci 11448c2ecf20Sopenharmony_ci if (subtype == CRYPTO_ALG_SUB_TYPE_CTR) 11458c2ecf20Sopenharmony_ci ctr_add_iv(iv, req->iv, DIV_ROUND_UP(reqctx->processed, 11468c2ecf20Sopenharmony_ci AES_BLOCK_SIZE)); 11478c2ecf20Sopenharmony_ci else if (subtype == CRYPTO_ALG_SUB_TYPE_XTS) { 11488c2ecf20Sopenharmony_ci if (!reqctx->partial_req) 11498c2ecf20Sopenharmony_ci memcpy(iv, reqctx->iv, AES_BLOCK_SIZE); 11508c2ecf20Sopenharmony_ci else 11518c2ecf20Sopenharmony_ci ret = chcr_update_tweak(req, iv, 1); 11528c2ecf20Sopenharmony_ci } 11538c2ecf20Sopenharmony_ci else if (subtype == CRYPTO_ALG_SUB_TYPE_CBC) { 11548c2ecf20Sopenharmony_ci /*Already updated for Decrypt*/ 11558c2ecf20Sopenharmony_ci if (!reqctx->op) 11568c2ecf20Sopenharmony_ci memcpy(iv, &fw6_pld->data[2], AES_BLOCK_SIZE); 11578c2ecf20Sopenharmony_ci 11588c2ecf20Sopenharmony_ci } 11598c2ecf20Sopenharmony_ci return ret; 11608c2ecf20Sopenharmony_ci 11618c2ecf20Sopenharmony_ci} 11628c2ecf20Sopenharmony_ci 11638c2ecf20Sopenharmony_cistatic int chcr_handle_cipher_resp(struct skcipher_request *req, 11648c2ecf20Sopenharmony_ci unsigned char *input, int err) 11658c2ecf20Sopenharmony_ci{ 11668c2ecf20Sopenharmony_ci struct chcr_skcipher_req_ctx *reqctx = skcipher_request_ctx(req); 11678c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 11688c2ecf20Sopenharmony_ci struct cpl_fw6_pld *fw6_pld = (struct cpl_fw6_pld *)input; 11698c2ecf20Sopenharmony_ci struct ablk_ctx *ablkctx = ABLK_CTX(c_ctx(tfm)); 11708c2ecf20Sopenharmony_ci struct uld_ctx *u_ctx = ULD_CTX(c_ctx(tfm)); 11718c2ecf20Sopenharmony_ci struct chcr_dev *dev = c_ctx(tfm)->dev; 11728c2ecf20Sopenharmony_ci struct chcr_context *ctx = c_ctx(tfm); 11738c2ecf20Sopenharmony_ci struct adapter *adap = padap(ctx->dev); 11748c2ecf20Sopenharmony_ci struct cipher_wr_param wrparam; 11758c2ecf20Sopenharmony_ci struct sk_buff *skb; 11768c2ecf20Sopenharmony_ci int bytes; 11778c2ecf20Sopenharmony_ci 11788c2ecf20Sopenharmony_ci if (err) 11798c2ecf20Sopenharmony_ci goto unmap; 11808c2ecf20Sopenharmony_ci if (req->cryptlen == reqctx->processed) { 11818c2ecf20Sopenharmony_ci chcr_cipher_dma_unmap(&ULD_CTX(c_ctx(tfm))->lldi.pdev->dev, 11828c2ecf20Sopenharmony_ci req); 11838c2ecf20Sopenharmony_ci err = chcr_final_cipher_iv(req, fw6_pld, req->iv); 11848c2ecf20Sopenharmony_ci goto complete; 11858c2ecf20Sopenharmony_ci } 11868c2ecf20Sopenharmony_ci 11878c2ecf20Sopenharmony_ci if (!reqctx->imm) { 11888c2ecf20Sopenharmony_ci bytes = chcr_sg_ent_in_wr(reqctx->srcsg, reqctx->dstsg, 0, 11898c2ecf20Sopenharmony_ci CIP_SPACE_LEFT(ablkctx->enckey_len), 11908c2ecf20Sopenharmony_ci reqctx->src_ofst, reqctx->dst_ofst); 11918c2ecf20Sopenharmony_ci if ((bytes + reqctx->processed) >= req->cryptlen) 11928c2ecf20Sopenharmony_ci bytes = req->cryptlen - reqctx->processed; 11938c2ecf20Sopenharmony_ci else 11948c2ecf20Sopenharmony_ci bytes = rounddown(bytes, 16); 11958c2ecf20Sopenharmony_ci } else { 11968c2ecf20Sopenharmony_ci /*CTR mode counter overfloa*/ 11978c2ecf20Sopenharmony_ci bytes = req->cryptlen - reqctx->processed; 11988c2ecf20Sopenharmony_ci } 11998c2ecf20Sopenharmony_ci err = chcr_update_cipher_iv(req, fw6_pld, reqctx->iv); 12008c2ecf20Sopenharmony_ci if (err) 12018c2ecf20Sopenharmony_ci goto unmap; 12028c2ecf20Sopenharmony_ci 12038c2ecf20Sopenharmony_ci if (unlikely(bytes == 0)) { 12048c2ecf20Sopenharmony_ci chcr_cipher_dma_unmap(&ULD_CTX(c_ctx(tfm))->lldi.pdev->dev, 12058c2ecf20Sopenharmony_ci req); 12068c2ecf20Sopenharmony_ci memcpy(req->iv, reqctx->init_iv, IV); 12078c2ecf20Sopenharmony_ci atomic_inc(&adap->chcr_stats.fallback); 12088c2ecf20Sopenharmony_ci err = chcr_cipher_fallback(ablkctx->sw_cipher, req, req->iv, 12098c2ecf20Sopenharmony_ci reqctx->op); 12108c2ecf20Sopenharmony_ci goto complete; 12118c2ecf20Sopenharmony_ci } 12128c2ecf20Sopenharmony_ci 12138c2ecf20Sopenharmony_ci if (get_cryptoalg_subtype(tfm) == 12148c2ecf20Sopenharmony_ci CRYPTO_ALG_SUB_TYPE_CTR) 12158c2ecf20Sopenharmony_ci bytes = adjust_ctr_overflow(reqctx->iv, bytes); 12168c2ecf20Sopenharmony_ci wrparam.qid = u_ctx->lldi.rxq_ids[reqctx->rxqidx]; 12178c2ecf20Sopenharmony_ci wrparam.req = req; 12188c2ecf20Sopenharmony_ci wrparam.bytes = bytes; 12198c2ecf20Sopenharmony_ci skb = create_cipher_wr(&wrparam); 12208c2ecf20Sopenharmony_ci if (IS_ERR(skb)) { 12218c2ecf20Sopenharmony_ci pr_err("%s : Failed to form WR. No memory\n", __func__); 12228c2ecf20Sopenharmony_ci err = PTR_ERR(skb); 12238c2ecf20Sopenharmony_ci goto unmap; 12248c2ecf20Sopenharmony_ci } 12258c2ecf20Sopenharmony_ci skb->dev = u_ctx->lldi.ports[0]; 12268c2ecf20Sopenharmony_ci set_wr_txq(skb, CPL_PRIORITY_DATA, reqctx->txqidx); 12278c2ecf20Sopenharmony_ci chcr_send_wr(skb); 12288c2ecf20Sopenharmony_ci reqctx->last_req_len = bytes; 12298c2ecf20Sopenharmony_ci reqctx->processed += bytes; 12308c2ecf20Sopenharmony_ci if (get_cryptoalg_subtype(tfm) == 12318c2ecf20Sopenharmony_ci CRYPTO_ALG_SUB_TYPE_CBC && req->base.flags == 12328c2ecf20Sopenharmony_ci CRYPTO_TFM_REQ_MAY_SLEEP ) { 12338c2ecf20Sopenharmony_ci complete(&ctx->cbc_aes_aio_done); 12348c2ecf20Sopenharmony_ci } 12358c2ecf20Sopenharmony_ci return 0; 12368c2ecf20Sopenharmony_ciunmap: 12378c2ecf20Sopenharmony_ci chcr_cipher_dma_unmap(&ULD_CTX(c_ctx(tfm))->lldi.pdev->dev, req); 12388c2ecf20Sopenharmony_cicomplete: 12398c2ecf20Sopenharmony_ci if (get_cryptoalg_subtype(tfm) == 12408c2ecf20Sopenharmony_ci CRYPTO_ALG_SUB_TYPE_CBC && req->base.flags == 12418c2ecf20Sopenharmony_ci CRYPTO_TFM_REQ_MAY_SLEEP ) { 12428c2ecf20Sopenharmony_ci complete(&ctx->cbc_aes_aio_done); 12438c2ecf20Sopenharmony_ci } 12448c2ecf20Sopenharmony_ci chcr_dec_wrcount(dev); 12458c2ecf20Sopenharmony_ci req->base.complete(&req->base, err); 12468c2ecf20Sopenharmony_ci return err; 12478c2ecf20Sopenharmony_ci} 12488c2ecf20Sopenharmony_ci 12498c2ecf20Sopenharmony_cistatic int process_cipher(struct skcipher_request *req, 12508c2ecf20Sopenharmony_ci unsigned short qid, 12518c2ecf20Sopenharmony_ci struct sk_buff **skb, 12528c2ecf20Sopenharmony_ci unsigned short op_type) 12538c2ecf20Sopenharmony_ci{ 12548c2ecf20Sopenharmony_ci struct chcr_skcipher_req_ctx *reqctx = skcipher_request_ctx(req); 12558c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 12568c2ecf20Sopenharmony_ci unsigned int ivsize = crypto_skcipher_ivsize(tfm); 12578c2ecf20Sopenharmony_ci struct ablk_ctx *ablkctx = ABLK_CTX(c_ctx(tfm)); 12588c2ecf20Sopenharmony_ci struct adapter *adap = padap(c_ctx(tfm)->dev); 12598c2ecf20Sopenharmony_ci struct cipher_wr_param wrparam; 12608c2ecf20Sopenharmony_ci int bytes, err = -EINVAL; 12618c2ecf20Sopenharmony_ci int subtype; 12628c2ecf20Sopenharmony_ci 12638c2ecf20Sopenharmony_ci reqctx->processed = 0; 12648c2ecf20Sopenharmony_ci reqctx->partial_req = 0; 12658c2ecf20Sopenharmony_ci if (!req->iv) 12668c2ecf20Sopenharmony_ci goto error; 12678c2ecf20Sopenharmony_ci subtype = get_cryptoalg_subtype(tfm); 12688c2ecf20Sopenharmony_ci if ((ablkctx->enckey_len == 0) || (ivsize > AES_BLOCK_SIZE) || 12698c2ecf20Sopenharmony_ci (req->cryptlen == 0) || 12708c2ecf20Sopenharmony_ci (req->cryptlen % crypto_skcipher_blocksize(tfm))) { 12718c2ecf20Sopenharmony_ci if (req->cryptlen == 0 && subtype != CRYPTO_ALG_SUB_TYPE_XTS) 12728c2ecf20Sopenharmony_ci goto fallback; 12738c2ecf20Sopenharmony_ci else if (req->cryptlen % crypto_skcipher_blocksize(tfm) && 12748c2ecf20Sopenharmony_ci subtype == CRYPTO_ALG_SUB_TYPE_XTS) 12758c2ecf20Sopenharmony_ci goto fallback; 12768c2ecf20Sopenharmony_ci pr_err("AES: Invalid value of Key Len %d nbytes %d IV Len %d\n", 12778c2ecf20Sopenharmony_ci ablkctx->enckey_len, req->cryptlen, ivsize); 12788c2ecf20Sopenharmony_ci goto error; 12798c2ecf20Sopenharmony_ci } 12808c2ecf20Sopenharmony_ci 12818c2ecf20Sopenharmony_ci err = chcr_cipher_dma_map(&ULD_CTX(c_ctx(tfm))->lldi.pdev->dev, req); 12828c2ecf20Sopenharmony_ci if (err) 12838c2ecf20Sopenharmony_ci goto error; 12848c2ecf20Sopenharmony_ci if (req->cryptlen < (SGE_MAX_WR_LEN - (sizeof(struct chcr_wr) + 12858c2ecf20Sopenharmony_ci AES_MIN_KEY_SIZE + 12868c2ecf20Sopenharmony_ci sizeof(struct cpl_rx_phys_dsgl) + 12878c2ecf20Sopenharmony_ci /*Min dsgl size*/ 12888c2ecf20Sopenharmony_ci 32))) { 12898c2ecf20Sopenharmony_ci /* Can be sent as Imm*/ 12908c2ecf20Sopenharmony_ci unsigned int dnents = 0, transhdr_len, phys_dsgl, kctx_len; 12918c2ecf20Sopenharmony_ci 12928c2ecf20Sopenharmony_ci dnents = sg_nents_xlen(req->dst, req->cryptlen, 12938c2ecf20Sopenharmony_ci CHCR_DST_SG_SIZE, 0); 12948c2ecf20Sopenharmony_ci phys_dsgl = get_space_for_phys_dsgl(dnents); 12958c2ecf20Sopenharmony_ci kctx_len = roundup(ablkctx->enckey_len, 16); 12968c2ecf20Sopenharmony_ci transhdr_len = CIPHER_TRANSHDR_SIZE(kctx_len, phys_dsgl); 12978c2ecf20Sopenharmony_ci reqctx->imm = (transhdr_len + IV + req->cryptlen) <= 12988c2ecf20Sopenharmony_ci SGE_MAX_WR_LEN; 12998c2ecf20Sopenharmony_ci bytes = IV + req->cryptlen; 13008c2ecf20Sopenharmony_ci 13018c2ecf20Sopenharmony_ci } else { 13028c2ecf20Sopenharmony_ci reqctx->imm = 0; 13038c2ecf20Sopenharmony_ci } 13048c2ecf20Sopenharmony_ci 13058c2ecf20Sopenharmony_ci if (!reqctx->imm) { 13068c2ecf20Sopenharmony_ci bytes = chcr_sg_ent_in_wr(req->src, req->dst, 0, 13078c2ecf20Sopenharmony_ci CIP_SPACE_LEFT(ablkctx->enckey_len), 13088c2ecf20Sopenharmony_ci 0, 0); 13098c2ecf20Sopenharmony_ci if ((bytes + reqctx->processed) >= req->cryptlen) 13108c2ecf20Sopenharmony_ci bytes = req->cryptlen - reqctx->processed; 13118c2ecf20Sopenharmony_ci else 13128c2ecf20Sopenharmony_ci bytes = rounddown(bytes, 16); 13138c2ecf20Sopenharmony_ci } else { 13148c2ecf20Sopenharmony_ci bytes = req->cryptlen; 13158c2ecf20Sopenharmony_ci } 13168c2ecf20Sopenharmony_ci if (subtype == CRYPTO_ALG_SUB_TYPE_CTR) { 13178c2ecf20Sopenharmony_ci bytes = adjust_ctr_overflow(req->iv, bytes); 13188c2ecf20Sopenharmony_ci } 13198c2ecf20Sopenharmony_ci if (subtype == CRYPTO_ALG_SUB_TYPE_CTR_RFC3686) { 13208c2ecf20Sopenharmony_ci memcpy(reqctx->iv, ablkctx->nonce, CTR_RFC3686_NONCE_SIZE); 13218c2ecf20Sopenharmony_ci memcpy(reqctx->iv + CTR_RFC3686_NONCE_SIZE, req->iv, 13228c2ecf20Sopenharmony_ci CTR_RFC3686_IV_SIZE); 13238c2ecf20Sopenharmony_ci 13248c2ecf20Sopenharmony_ci /* initialize counter portion of counter block */ 13258c2ecf20Sopenharmony_ci *(__be32 *)(reqctx->iv + CTR_RFC3686_NONCE_SIZE + 13268c2ecf20Sopenharmony_ci CTR_RFC3686_IV_SIZE) = cpu_to_be32(1); 13278c2ecf20Sopenharmony_ci memcpy(reqctx->init_iv, reqctx->iv, IV); 13288c2ecf20Sopenharmony_ci 13298c2ecf20Sopenharmony_ci } else { 13308c2ecf20Sopenharmony_ci 13318c2ecf20Sopenharmony_ci memcpy(reqctx->iv, req->iv, IV); 13328c2ecf20Sopenharmony_ci memcpy(reqctx->init_iv, req->iv, IV); 13338c2ecf20Sopenharmony_ci } 13348c2ecf20Sopenharmony_ci if (unlikely(bytes == 0)) { 13358c2ecf20Sopenharmony_ci chcr_cipher_dma_unmap(&ULD_CTX(c_ctx(tfm))->lldi.pdev->dev, 13368c2ecf20Sopenharmony_ci req); 13378c2ecf20Sopenharmony_cifallback: atomic_inc(&adap->chcr_stats.fallback); 13388c2ecf20Sopenharmony_ci err = chcr_cipher_fallback(ablkctx->sw_cipher, req, 13398c2ecf20Sopenharmony_ci subtype == 13408c2ecf20Sopenharmony_ci CRYPTO_ALG_SUB_TYPE_CTR_RFC3686 ? 13418c2ecf20Sopenharmony_ci reqctx->iv : req->iv, 13428c2ecf20Sopenharmony_ci op_type); 13438c2ecf20Sopenharmony_ci goto error; 13448c2ecf20Sopenharmony_ci } 13458c2ecf20Sopenharmony_ci reqctx->op = op_type; 13468c2ecf20Sopenharmony_ci reqctx->srcsg = req->src; 13478c2ecf20Sopenharmony_ci reqctx->dstsg = req->dst; 13488c2ecf20Sopenharmony_ci reqctx->src_ofst = 0; 13498c2ecf20Sopenharmony_ci reqctx->dst_ofst = 0; 13508c2ecf20Sopenharmony_ci wrparam.qid = qid; 13518c2ecf20Sopenharmony_ci wrparam.req = req; 13528c2ecf20Sopenharmony_ci wrparam.bytes = bytes; 13538c2ecf20Sopenharmony_ci *skb = create_cipher_wr(&wrparam); 13548c2ecf20Sopenharmony_ci if (IS_ERR(*skb)) { 13558c2ecf20Sopenharmony_ci err = PTR_ERR(*skb); 13568c2ecf20Sopenharmony_ci goto unmap; 13578c2ecf20Sopenharmony_ci } 13588c2ecf20Sopenharmony_ci reqctx->processed = bytes; 13598c2ecf20Sopenharmony_ci reqctx->last_req_len = bytes; 13608c2ecf20Sopenharmony_ci reqctx->partial_req = !!(req->cryptlen - reqctx->processed); 13618c2ecf20Sopenharmony_ci 13628c2ecf20Sopenharmony_ci return 0; 13638c2ecf20Sopenharmony_ciunmap: 13648c2ecf20Sopenharmony_ci chcr_cipher_dma_unmap(&ULD_CTX(c_ctx(tfm))->lldi.pdev->dev, req); 13658c2ecf20Sopenharmony_cierror: 13668c2ecf20Sopenharmony_ci return err; 13678c2ecf20Sopenharmony_ci} 13688c2ecf20Sopenharmony_ci 13698c2ecf20Sopenharmony_cistatic int chcr_aes_encrypt(struct skcipher_request *req) 13708c2ecf20Sopenharmony_ci{ 13718c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 13728c2ecf20Sopenharmony_ci struct chcr_skcipher_req_ctx *reqctx = skcipher_request_ctx(req); 13738c2ecf20Sopenharmony_ci struct chcr_dev *dev = c_ctx(tfm)->dev; 13748c2ecf20Sopenharmony_ci struct sk_buff *skb = NULL; 13758c2ecf20Sopenharmony_ci int err; 13768c2ecf20Sopenharmony_ci struct uld_ctx *u_ctx = ULD_CTX(c_ctx(tfm)); 13778c2ecf20Sopenharmony_ci struct chcr_context *ctx = c_ctx(tfm); 13788c2ecf20Sopenharmony_ci unsigned int cpu; 13798c2ecf20Sopenharmony_ci 13808c2ecf20Sopenharmony_ci cpu = get_cpu(); 13818c2ecf20Sopenharmony_ci reqctx->txqidx = cpu % ctx->ntxq; 13828c2ecf20Sopenharmony_ci reqctx->rxqidx = cpu % ctx->nrxq; 13838c2ecf20Sopenharmony_ci put_cpu(); 13848c2ecf20Sopenharmony_ci 13858c2ecf20Sopenharmony_ci err = chcr_inc_wrcount(dev); 13868c2ecf20Sopenharmony_ci if (err) 13878c2ecf20Sopenharmony_ci return -ENXIO; 13888c2ecf20Sopenharmony_ci if (unlikely(cxgb4_is_crypto_q_full(u_ctx->lldi.ports[0], 13898c2ecf20Sopenharmony_ci reqctx->txqidx) && 13908c2ecf20Sopenharmony_ci (!(req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)))) { 13918c2ecf20Sopenharmony_ci err = -ENOSPC; 13928c2ecf20Sopenharmony_ci goto error; 13938c2ecf20Sopenharmony_ci } 13948c2ecf20Sopenharmony_ci 13958c2ecf20Sopenharmony_ci err = process_cipher(req, u_ctx->lldi.rxq_ids[reqctx->rxqidx], 13968c2ecf20Sopenharmony_ci &skb, CHCR_ENCRYPT_OP); 13978c2ecf20Sopenharmony_ci if (err || !skb) 13988c2ecf20Sopenharmony_ci return err; 13998c2ecf20Sopenharmony_ci skb->dev = u_ctx->lldi.ports[0]; 14008c2ecf20Sopenharmony_ci set_wr_txq(skb, CPL_PRIORITY_DATA, reqctx->txqidx); 14018c2ecf20Sopenharmony_ci chcr_send_wr(skb); 14028c2ecf20Sopenharmony_ci if (get_cryptoalg_subtype(tfm) == 14038c2ecf20Sopenharmony_ci CRYPTO_ALG_SUB_TYPE_CBC && req->base.flags == 14048c2ecf20Sopenharmony_ci CRYPTO_TFM_REQ_MAY_SLEEP ) { 14058c2ecf20Sopenharmony_ci reqctx->partial_req = 1; 14068c2ecf20Sopenharmony_ci wait_for_completion(&ctx->cbc_aes_aio_done); 14078c2ecf20Sopenharmony_ci } 14088c2ecf20Sopenharmony_ci return -EINPROGRESS; 14098c2ecf20Sopenharmony_cierror: 14108c2ecf20Sopenharmony_ci chcr_dec_wrcount(dev); 14118c2ecf20Sopenharmony_ci return err; 14128c2ecf20Sopenharmony_ci} 14138c2ecf20Sopenharmony_ci 14148c2ecf20Sopenharmony_cistatic int chcr_aes_decrypt(struct skcipher_request *req) 14158c2ecf20Sopenharmony_ci{ 14168c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 14178c2ecf20Sopenharmony_ci struct chcr_skcipher_req_ctx *reqctx = skcipher_request_ctx(req); 14188c2ecf20Sopenharmony_ci struct uld_ctx *u_ctx = ULD_CTX(c_ctx(tfm)); 14198c2ecf20Sopenharmony_ci struct chcr_dev *dev = c_ctx(tfm)->dev; 14208c2ecf20Sopenharmony_ci struct sk_buff *skb = NULL; 14218c2ecf20Sopenharmony_ci int err; 14228c2ecf20Sopenharmony_ci struct chcr_context *ctx = c_ctx(tfm); 14238c2ecf20Sopenharmony_ci unsigned int cpu; 14248c2ecf20Sopenharmony_ci 14258c2ecf20Sopenharmony_ci cpu = get_cpu(); 14268c2ecf20Sopenharmony_ci reqctx->txqidx = cpu % ctx->ntxq; 14278c2ecf20Sopenharmony_ci reqctx->rxqidx = cpu % ctx->nrxq; 14288c2ecf20Sopenharmony_ci put_cpu(); 14298c2ecf20Sopenharmony_ci 14308c2ecf20Sopenharmony_ci err = chcr_inc_wrcount(dev); 14318c2ecf20Sopenharmony_ci if (err) 14328c2ecf20Sopenharmony_ci return -ENXIO; 14338c2ecf20Sopenharmony_ci 14348c2ecf20Sopenharmony_ci if (unlikely(cxgb4_is_crypto_q_full(u_ctx->lldi.ports[0], 14358c2ecf20Sopenharmony_ci reqctx->txqidx) && 14368c2ecf20Sopenharmony_ci (!(req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)))) 14378c2ecf20Sopenharmony_ci return -ENOSPC; 14388c2ecf20Sopenharmony_ci err = process_cipher(req, u_ctx->lldi.rxq_ids[reqctx->rxqidx], 14398c2ecf20Sopenharmony_ci &skb, CHCR_DECRYPT_OP); 14408c2ecf20Sopenharmony_ci if (err || !skb) 14418c2ecf20Sopenharmony_ci return err; 14428c2ecf20Sopenharmony_ci skb->dev = u_ctx->lldi.ports[0]; 14438c2ecf20Sopenharmony_ci set_wr_txq(skb, CPL_PRIORITY_DATA, reqctx->txqidx); 14448c2ecf20Sopenharmony_ci chcr_send_wr(skb); 14458c2ecf20Sopenharmony_ci return -EINPROGRESS; 14468c2ecf20Sopenharmony_ci} 14478c2ecf20Sopenharmony_cistatic int chcr_device_init(struct chcr_context *ctx) 14488c2ecf20Sopenharmony_ci{ 14498c2ecf20Sopenharmony_ci struct uld_ctx *u_ctx = NULL; 14508c2ecf20Sopenharmony_ci int txq_perchan, ntxq; 14518c2ecf20Sopenharmony_ci int err = 0, rxq_perchan; 14528c2ecf20Sopenharmony_ci 14538c2ecf20Sopenharmony_ci if (!ctx->dev) { 14548c2ecf20Sopenharmony_ci u_ctx = assign_chcr_device(); 14558c2ecf20Sopenharmony_ci if (!u_ctx) { 14568c2ecf20Sopenharmony_ci err = -ENXIO; 14578c2ecf20Sopenharmony_ci pr_err("chcr device assignment fails\n"); 14588c2ecf20Sopenharmony_ci goto out; 14598c2ecf20Sopenharmony_ci } 14608c2ecf20Sopenharmony_ci ctx->dev = &u_ctx->dev; 14618c2ecf20Sopenharmony_ci ntxq = u_ctx->lldi.ntxq; 14628c2ecf20Sopenharmony_ci rxq_perchan = u_ctx->lldi.nrxq / u_ctx->lldi.nchan; 14638c2ecf20Sopenharmony_ci txq_perchan = ntxq / u_ctx->lldi.nchan; 14648c2ecf20Sopenharmony_ci ctx->ntxq = ntxq; 14658c2ecf20Sopenharmony_ci ctx->nrxq = u_ctx->lldi.nrxq; 14668c2ecf20Sopenharmony_ci ctx->rxq_perchan = rxq_perchan; 14678c2ecf20Sopenharmony_ci ctx->txq_perchan = txq_perchan; 14688c2ecf20Sopenharmony_ci } 14698c2ecf20Sopenharmony_ciout: 14708c2ecf20Sopenharmony_ci return err; 14718c2ecf20Sopenharmony_ci} 14728c2ecf20Sopenharmony_ci 14738c2ecf20Sopenharmony_cistatic int chcr_init_tfm(struct crypto_skcipher *tfm) 14748c2ecf20Sopenharmony_ci{ 14758c2ecf20Sopenharmony_ci struct skcipher_alg *alg = crypto_skcipher_alg(tfm); 14768c2ecf20Sopenharmony_ci struct chcr_context *ctx = crypto_skcipher_ctx(tfm); 14778c2ecf20Sopenharmony_ci struct ablk_ctx *ablkctx = ABLK_CTX(ctx); 14788c2ecf20Sopenharmony_ci 14798c2ecf20Sopenharmony_ci ablkctx->sw_cipher = crypto_alloc_skcipher(alg->base.cra_name, 0, 14808c2ecf20Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK); 14818c2ecf20Sopenharmony_ci if (IS_ERR(ablkctx->sw_cipher)) { 14828c2ecf20Sopenharmony_ci pr_err("failed to allocate fallback for %s\n", alg->base.cra_name); 14838c2ecf20Sopenharmony_ci return PTR_ERR(ablkctx->sw_cipher); 14848c2ecf20Sopenharmony_ci } 14858c2ecf20Sopenharmony_ci init_completion(&ctx->cbc_aes_aio_done); 14868c2ecf20Sopenharmony_ci crypto_skcipher_set_reqsize(tfm, sizeof(struct chcr_skcipher_req_ctx) + 14878c2ecf20Sopenharmony_ci crypto_skcipher_reqsize(ablkctx->sw_cipher)); 14888c2ecf20Sopenharmony_ci 14898c2ecf20Sopenharmony_ci return chcr_device_init(ctx); 14908c2ecf20Sopenharmony_ci} 14918c2ecf20Sopenharmony_ci 14928c2ecf20Sopenharmony_cistatic int chcr_rfc3686_init(struct crypto_skcipher *tfm) 14938c2ecf20Sopenharmony_ci{ 14948c2ecf20Sopenharmony_ci struct skcipher_alg *alg = crypto_skcipher_alg(tfm); 14958c2ecf20Sopenharmony_ci struct chcr_context *ctx = crypto_skcipher_ctx(tfm); 14968c2ecf20Sopenharmony_ci struct ablk_ctx *ablkctx = ABLK_CTX(ctx); 14978c2ecf20Sopenharmony_ci 14988c2ecf20Sopenharmony_ci /*RFC3686 initialises IV counter value to 1, rfc3686(ctr(aes)) 14998c2ecf20Sopenharmony_ci * cannot be used as fallback in chcr_handle_cipher_response 15008c2ecf20Sopenharmony_ci */ 15018c2ecf20Sopenharmony_ci ablkctx->sw_cipher = crypto_alloc_skcipher("ctr(aes)", 0, 15028c2ecf20Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK); 15038c2ecf20Sopenharmony_ci if (IS_ERR(ablkctx->sw_cipher)) { 15048c2ecf20Sopenharmony_ci pr_err("failed to allocate fallback for %s\n", alg->base.cra_name); 15058c2ecf20Sopenharmony_ci return PTR_ERR(ablkctx->sw_cipher); 15068c2ecf20Sopenharmony_ci } 15078c2ecf20Sopenharmony_ci crypto_skcipher_set_reqsize(tfm, sizeof(struct chcr_skcipher_req_ctx) + 15088c2ecf20Sopenharmony_ci crypto_skcipher_reqsize(ablkctx->sw_cipher)); 15098c2ecf20Sopenharmony_ci return chcr_device_init(ctx); 15108c2ecf20Sopenharmony_ci} 15118c2ecf20Sopenharmony_ci 15128c2ecf20Sopenharmony_ci 15138c2ecf20Sopenharmony_cistatic void chcr_exit_tfm(struct crypto_skcipher *tfm) 15148c2ecf20Sopenharmony_ci{ 15158c2ecf20Sopenharmony_ci struct chcr_context *ctx = crypto_skcipher_ctx(tfm); 15168c2ecf20Sopenharmony_ci struct ablk_ctx *ablkctx = ABLK_CTX(ctx); 15178c2ecf20Sopenharmony_ci 15188c2ecf20Sopenharmony_ci crypto_free_skcipher(ablkctx->sw_cipher); 15198c2ecf20Sopenharmony_ci} 15208c2ecf20Sopenharmony_ci 15218c2ecf20Sopenharmony_cistatic int get_alg_config(struct algo_param *params, 15228c2ecf20Sopenharmony_ci unsigned int auth_size) 15238c2ecf20Sopenharmony_ci{ 15248c2ecf20Sopenharmony_ci switch (auth_size) { 15258c2ecf20Sopenharmony_ci case SHA1_DIGEST_SIZE: 15268c2ecf20Sopenharmony_ci params->mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_160; 15278c2ecf20Sopenharmony_ci params->auth_mode = CHCR_SCMD_AUTH_MODE_SHA1; 15288c2ecf20Sopenharmony_ci params->result_size = SHA1_DIGEST_SIZE; 15298c2ecf20Sopenharmony_ci break; 15308c2ecf20Sopenharmony_ci case SHA224_DIGEST_SIZE: 15318c2ecf20Sopenharmony_ci params->mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_256; 15328c2ecf20Sopenharmony_ci params->auth_mode = CHCR_SCMD_AUTH_MODE_SHA224; 15338c2ecf20Sopenharmony_ci params->result_size = SHA256_DIGEST_SIZE; 15348c2ecf20Sopenharmony_ci break; 15358c2ecf20Sopenharmony_ci case SHA256_DIGEST_SIZE: 15368c2ecf20Sopenharmony_ci params->mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_256; 15378c2ecf20Sopenharmony_ci params->auth_mode = CHCR_SCMD_AUTH_MODE_SHA256; 15388c2ecf20Sopenharmony_ci params->result_size = SHA256_DIGEST_SIZE; 15398c2ecf20Sopenharmony_ci break; 15408c2ecf20Sopenharmony_ci case SHA384_DIGEST_SIZE: 15418c2ecf20Sopenharmony_ci params->mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_512; 15428c2ecf20Sopenharmony_ci params->auth_mode = CHCR_SCMD_AUTH_MODE_SHA512_384; 15438c2ecf20Sopenharmony_ci params->result_size = SHA512_DIGEST_SIZE; 15448c2ecf20Sopenharmony_ci break; 15458c2ecf20Sopenharmony_ci case SHA512_DIGEST_SIZE: 15468c2ecf20Sopenharmony_ci params->mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_512; 15478c2ecf20Sopenharmony_ci params->auth_mode = CHCR_SCMD_AUTH_MODE_SHA512_512; 15488c2ecf20Sopenharmony_ci params->result_size = SHA512_DIGEST_SIZE; 15498c2ecf20Sopenharmony_ci break; 15508c2ecf20Sopenharmony_ci default: 15518c2ecf20Sopenharmony_ci pr_err("ERROR, unsupported digest size\n"); 15528c2ecf20Sopenharmony_ci return -EINVAL; 15538c2ecf20Sopenharmony_ci } 15548c2ecf20Sopenharmony_ci return 0; 15558c2ecf20Sopenharmony_ci} 15568c2ecf20Sopenharmony_ci 15578c2ecf20Sopenharmony_cistatic inline void chcr_free_shash(struct crypto_shash *base_hash) 15588c2ecf20Sopenharmony_ci{ 15598c2ecf20Sopenharmony_ci crypto_free_shash(base_hash); 15608c2ecf20Sopenharmony_ci} 15618c2ecf20Sopenharmony_ci 15628c2ecf20Sopenharmony_ci/** 15638c2ecf20Sopenharmony_ci * create_hash_wr - Create hash work request 15648c2ecf20Sopenharmony_ci * @req - Cipher req base 15658c2ecf20Sopenharmony_ci */ 15668c2ecf20Sopenharmony_cistatic struct sk_buff *create_hash_wr(struct ahash_request *req, 15678c2ecf20Sopenharmony_ci struct hash_wr_param *param) 15688c2ecf20Sopenharmony_ci{ 15698c2ecf20Sopenharmony_ci struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(req); 15708c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 15718c2ecf20Sopenharmony_ci struct chcr_context *ctx = h_ctx(tfm); 15728c2ecf20Sopenharmony_ci struct hmac_ctx *hmacctx = HMAC_CTX(ctx); 15738c2ecf20Sopenharmony_ci struct sk_buff *skb = NULL; 15748c2ecf20Sopenharmony_ci struct uld_ctx *u_ctx = ULD_CTX(ctx); 15758c2ecf20Sopenharmony_ci struct chcr_wr *chcr_req; 15768c2ecf20Sopenharmony_ci struct ulptx_sgl *ulptx; 15778c2ecf20Sopenharmony_ci unsigned int nents = 0, transhdr_len; 15788c2ecf20Sopenharmony_ci unsigned int temp = 0; 15798c2ecf20Sopenharmony_ci gfp_t flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL : 15808c2ecf20Sopenharmony_ci GFP_ATOMIC; 15818c2ecf20Sopenharmony_ci struct adapter *adap = padap(h_ctx(tfm)->dev); 15828c2ecf20Sopenharmony_ci int error = 0; 15838c2ecf20Sopenharmony_ci unsigned int rx_channel_id = req_ctx->rxqidx / ctx->rxq_perchan; 15848c2ecf20Sopenharmony_ci 15858c2ecf20Sopenharmony_ci rx_channel_id = cxgb4_port_e2cchan(u_ctx->lldi.ports[rx_channel_id]); 15868c2ecf20Sopenharmony_ci transhdr_len = HASH_TRANSHDR_SIZE(param->kctx_len); 15878c2ecf20Sopenharmony_ci req_ctx->hctx_wr.imm = (transhdr_len + param->bfr_len + 15888c2ecf20Sopenharmony_ci param->sg_len) <= SGE_MAX_WR_LEN; 15898c2ecf20Sopenharmony_ci nents = sg_nents_xlen(req_ctx->hctx_wr.srcsg, param->sg_len, 15908c2ecf20Sopenharmony_ci CHCR_SRC_SG_SIZE, req_ctx->hctx_wr.src_ofst); 15918c2ecf20Sopenharmony_ci nents += param->bfr_len ? 1 : 0; 15928c2ecf20Sopenharmony_ci transhdr_len += req_ctx->hctx_wr.imm ? roundup(param->bfr_len + 15938c2ecf20Sopenharmony_ci param->sg_len, 16) : (sgl_len(nents) * 8); 15948c2ecf20Sopenharmony_ci transhdr_len = roundup(transhdr_len, 16); 15958c2ecf20Sopenharmony_ci 15968c2ecf20Sopenharmony_ci skb = alloc_skb(transhdr_len, flags); 15978c2ecf20Sopenharmony_ci if (!skb) 15988c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 15998c2ecf20Sopenharmony_ci chcr_req = __skb_put_zero(skb, transhdr_len); 16008c2ecf20Sopenharmony_ci 16018c2ecf20Sopenharmony_ci chcr_req->sec_cpl.op_ivinsrtofst = 16028c2ecf20Sopenharmony_ci FILL_SEC_CPL_OP_IVINSR(rx_channel_id, 2, 0); 16038c2ecf20Sopenharmony_ci 16048c2ecf20Sopenharmony_ci chcr_req->sec_cpl.pldlen = htonl(param->bfr_len + param->sg_len); 16058c2ecf20Sopenharmony_ci 16068c2ecf20Sopenharmony_ci chcr_req->sec_cpl.aadstart_cipherstop_hi = 16078c2ecf20Sopenharmony_ci FILL_SEC_CPL_CIPHERSTOP_HI(0, 0, 0, 0); 16088c2ecf20Sopenharmony_ci chcr_req->sec_cpl.cipherstop_lo_authinsert = 16098c2ecf20Sopenharmony_ci FILL_SEC_CPL_AUTHINSERT(0, 1, 0, 0); 16108c2ecf20Sopenharmony_ci chcr_req->sec_cpl.seqno_numivs = 16118c2ecf20Sopenharmony_ci FILL_SEC_CPL_SCMD0_SEQNO(0, 0, 0, param->alg_prm.auth_mode, 16128c2ecf20Sopenharmony_ci param->opad_needed, 0); 16138c2ecf20Sopenharmony_ci 16148c2ecf20Sopenharmony_ci chcr_req->sec_cpl.ivgen_hdrlen = 16158c2ecf20Sopenharmony_ci FILL_SEC_CPL_IVGEN_HDRLEN(param->last, param->more, 0, 1, 0, 0); 16168c2ecf20Sopenharmony_ci 16178c2ecf20Sopenharmony_ci memcpy(chcr_req->key_ctx.key, req_ctx->partial_hash, 16188c2ecf20Sopenharmony_ci param->alg_prm.result_size); 16198c2ecf20Sopenharmony_ci 16208c2ecf20Sopenharmony_ci if (param->opad_needed) 16218c2ecf20Sopenharmony_ci memcpy(chcr_req->key_ctx.key + 16228c2ecf20Sopenharmony_ci ((param->alg_prm.result_size <= 32) ? 32 : 16238c2ecf20Sopenharmony_ci CHCR_HASH_MAX_DIGEST_SIZE), 16248c2ecf20Sopenharmony_ci hmacctx->opad, param->alg_prm.result_size); 16258c2ecf20Sopenharmony_ci 16268c2ecf20Sopenharmony_ci chcr_req->key_ctx.ctx_hdr = FILL_KEY_CTX_HDR(CHCR_KEYCTX_NO_KEY, 16278c2ecf20Sopenharmony_ci param->alg_prm.mk_size, 0, 16288c2ecf20Sopenharmony_ci param->opad_needed, 16298c2ecf20Sopenharmony_ci ((param->kctx_len + 16308c2ecf20Sopenharmony_ci sizeof(chcr_req->key_ctx)) >> 4)); 16318c2ecf20Sopenharmony_ci chcr_req->sec_cpl.scmd1 = cpu_to_be64((u64)param->scmd1); 16328c2ecf20Sopenharmony_ci ulptx = (struct ulptx_sgl *)((u8 *)(chcr_req + 1) + param->kctx_len + 16338c2ecf20Sopenharmony_ci DUMMY_BYTES); 16348c2ecf20Sopenharmony_ci if (param->bfr_len != 0) { 16358c2ecf20Sopenharmony_ci req_ctx->hctx_wr.dma_addr = 16368c2ecf20Sopenharmony_ci dma_map_single(&u_ctx->lldi.pdev->dev, req_ctx->reqbfr, 16378c2ecf20Sopenharmony_ci param->bfr_len, DMA_TO_DEVICE); 16388c2ecf20Sopenharmony_ci if (dma_mapping_error(&u_ctx->lldi.pdev->dev, 16398c2ecf20Sopenharmony_ci req_ctx->hctx_wr. dma_addr)) { 16408c2ecf20Sopenharmony_ci error = -ENOMEM; 16418c2ecf20Sopenharmony_ci goto err; 16428c2ecf20Sopenharmony_ci } 16438c2ecf20Sopenharmony_ci req_ctx->hctx_wr.dma_len = param->bfr_len; 16448c2ecf20Sopenharmony_ci } else { 16458c2ecf20Sopenharmony_ci req_ctx->hctx_wr.dma_addr = 0; 16468c2ecf20Sopenharmony_ci } 16478c2ecf20Sopenharmony_ci chcr_add_hash_src_ent(req, ulptx, param); 16488c2ecf20Sopenharmony_ci /* Request upto max wr size */ 16498c2ecf20Sopenharmony_ci temp = param->kctx_len + DUMMY_BYTES + (req_ctx->hctx_wr.imm ? 16508c2ecf20Sopenharmony_ci (param->sg_len + param->bfr_len) : 0); 16518c2ecf20Sopenharmony_ci atomic_inc(&adap->chcr_stats.digest_rqst); 16528c2ecf20Sopenharmony_ci create_wreq(h_ctx(tfm), chcr_req, &req->base, req_ctx->hctx_wr.imm, 16538c2ecf20Sopenharmony_ci param->hash_size, transhdr_len, 16548c2ecf20Sopenharmony_ci temp, 0); 16558c2ecf20Sopenharmony_ci req_ctx->hctx_wr.skb = skb; 16568c2ecf20Sopenharmony_ci return skb; 16578c2ecf20Sopenharmony_cierr: 16588c2ecf20Sopenharmony_ci kfree_skb(skb); 16598c2ecf20Sopenharmony_ci return ERR_PTR(error); 16608c2ecf20Sopenharmony_ci} 16618c2ecf20Sopenharmony_ci 16628c2ecf20Sopenharmony_cistatic int chcr_ahash_update(struct ahash_request *req) 16638c2ecf20Sopenharmony_ci{ 16648c2ecf20Sopenharmony_ci struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(req); 16658c2ecf20Sopenharmony_ci struct crypto_ahash *rtfm = crypto_ahash_reqtfm(req); 16668c2ecf20Sopenharmony_ci struct uld_ctx *u_ctx = ULD_CTX(h_ctx(rtfm)); 16678c2ecf20Sopenharmony_ci struct chcr_context *ctx = h_ctx(rtfm); 16688c2ecf20Sopenharmony_ci struct chcr_dev *dev = h_ctx(rtfm)->dev; 16698c2ecf20Sopenharmony_ci struct sk_buff *skb; 16708c2ecf20Sopenharmony_ci u8 remainder = 0, bs; 16718c2ecf20Sopenharmony_ci unsigned int nbytes = req->nbytes; 16728c2ecf20Sopenharmony_ci struct hash_wr_param params; 16738c2ecf20Sopenharmony_ci int error; 16748c2ecf20Sopenharmony_ci unsigned int cpu; 16758c2ecf20Sopenharmony_ci 16768c2ecf20Sopenharmony_ci cpu = get_cpu(); 16778c2ecf20Sopenharmony_ci req_ctx->txqidx = cpu % ctx->ntxq; 16788c2ecf20Sopenharmony_ci req_ctx->rxqidx = cpu % ctx->nrxq; 16798c2ecf20Sopenharmony_ci put_cpu(); 16808c2ecf20Sopenharmony_ci 16818c2ecf20Sopenharmony_ci bs = crypto_tfm_alg_blocksize(crypto_ahash_tfm(rtfm)); 16828c2ecf20Sopenharmony_ci 16838c2ecf20Sopenharmony_ci if (nbytes + req_ctx->reqlen >= bs) { 16848c2ecf20Sopenharmony_ci remainder = (nbytes + req_ctx->reqlen) % bs; 16858c2ecf20Sopenharmony_ci nbytes = nbytes + req_ctx->reqlen - remainder; 16868c2ecf20Sopenharmony_ci } else { 16878c2ecf20Sopenharmony_ci sg_pcopy_to_buffer(req->src, sg_nents(req->src), req_ctx->reqbfr 16888c2ecf20Sopenharmony_ci + req_ctx->reqlen, nbytes, 0); 16898c2ecf20Sopenharmony_ci req_ctx->reqlen += nbytes; 16908c2ecf20Sopenharmony_ci return 0; 16918c2ecf20Sopenharmony_ci } 16928c2ecf20Sopenharmony_ci error = chcr_inc_wrcount(dev); 16938c2ecf20Sopenharmony_ci if (error) 16948c2ecf20Sopenharmony_ci return -ENXIO; 16958c2ecf20Sopenharmony_ci /* Detach state for CHCR means lldi or padap is freed. Increasing 16968c2ecf20Sopenharmony_ci * inflight count for dev guarantees that lldi and padap is valid 16978c2ecf20Sopenharmony_ci */ 16988c2ecf20Sopenharmony_ci if (unlikely(cxgb4_is_crypto_q_full(u_ctx->lldi.ports[0], 16998c2ecf20Sopenharmony_ci req_ctx->txqidx) && 17008c2ecf20Sopenharmony_ci (!(req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)))) { 17018c2ecf20Sopenharmony_ci error = -ENOSPC; 17028c2ecf20Sopenharmony_ci goto err; 17038c2ecf20Sopenharmony_ci } 17048c2ecf20Sopenharmony_ci 17058c2ecf20Sopenharmony_ci chcr_init_hctx_per_wr(req_ctx); 17068c2ecf20Sopenharmony_ci error = chcr_hash_dma_map(&u_ctx->lldi.pdev->dev, req); 17078c2ecf20Sopenharmony_ci if (error) { 17088c2ecf20Sopenharmony_ci error = -ENOMEM; 17098c2ecf20Sopenharmony_ci goto err; 17108c2ecf20Sopenharmony_ci } 17118c2ecf20Sopenharmony_ci get_alg_config(¶ms.alg_prm, crypto_ahash_digestsize(rtfm)); 17128c2ecf20Sopenharmony_ci params.kctx_len = roundup(params.alg_prm.result_size, 16); 17138c2ecf20Sopenharmony_ci params.sg_len = chcr_hash_ent_in_wr(req->src, !!req_ctx->reqlen, 17148c2ecf20Sopenharmony_ci HASH_SPACE_LEFT(params.kctx_len), 0); 17158c2ecf20Sopenharmony_ci if (params.sg_len > req->nbytes) 17168c2ecf20Sopenharmony_ci params.sg_len = req->nbytes; 17178c2ecf20Sopenharmony_ci params.sg_len = rounddown(params.sg_len + req_ctx->reqlen, bs) - 17188c2ecf20Sopenharmony_ci req_ctx->reqlen; 17198c2ecf20Sopenharmony_ci params.opad_needed = 0; 17208c2ecf20Sopenharmony_ci params.more = 1; 17218c2ecf20Sopenharmony_ci params.last = 0; 17228c2ecf20Sopenharmony_ci params.bfr_len = req_ctx->reqlen; 17238c2ecf20Sopenharmony_ci params.scmd1 = 0; 17248c2ecf20Sopenharmony_ci req_ctx->hctx_wr.srcsg = req->src; 17258c2ecf20Sopenharmony_ci 17268c2ecf20Sopenharmony_ci params.hash_size = params.alg_prm.result_size; 17278c2ecf20Sopenharmony_ci req_ctx->data_len += params.sg_len + params.bfr_len; 17288c2ecf20Sopenharmony_ci skb = create_hash_wr(req, ¶ms); 17298c2ecf20Sopenharmony_ci if (IS_ERR(skb)) { 17308c2ecf20Sopenharmony_ci error = PTR_ERR(skb); 17318c2ecf20Sopenharmony_ci goto unmap; 17328c2ecf20Sopenharmony_ci } 17338c2ecf20Sopenharmony_ci 17348c2ecf20Sopenharmony_ci req_ctx->hctx_wr.processed += params.sg_len; 17358c2ecf20Sopenharmony_ci if (remainder) { 17368c2ecf20Sopenharmony_ci /* Swap buffers */ 17378c2ecf20Sopenharmony_ci swap(req_ctx->reqbfr, req_ctx->skbfr); 17388c2ecf20Sopenharmony_ci sg_pcopy_to_buffer(req->src, sg_nents(req->src), 17398c2ecf20Sopenharmony_ci req_ctx->reqbfr, remainder, req->nbytes - 17408c2ecf20Sopenharmony_ci remainder); 17418c2ecf20Sopenharmony_ci } 17428c2ecf20Sopenharmony_ci req_ctx->reqlen = remainder; 17438c2ecf20Sopenharmony_ci skb->dev = u_ctx->lldi.ports[0]; 17448c2ecf20Sopenharmony_ci set_wr_txq(skb, CPL_PRIORITY_DATA, req_ctx->txqidx); 17458c2ecf20Sopenharmony_ci chcr_send_wr(skb); 17468c2ecf20Sopenharmony_ci return -EINPROGRESS; 17478c2ecf20Sopenharmony_ciunmap: 17488c2ecf20Sopenharmony_ci chcr_hash_dma_unmap(&u_ctx->lldi.pdev->dev, req); 17498c2ecf20Sopenharmony_cierr: 17508c2ecf20Sopenharmony_ci chcr_dec_wrcount(dev); 17518c2ecf20Sopenharmony_ci return error; 17528c2ecf20Sopenharmony_ci} 17538c2ecf20Sopenharmony_ci 17548c2ecf20Sopenharmony_cistatic void create_last_hash_block(char *bfr_ptr, unsigned int bs, u64 scmd1) 17558c2ecf20Sopenharmony_ci{ 17568c2ecf20Sopenharmony_ci memset(bfr_ptr, 0, bs); 17578c2ecf20Sopenharmony_ci *bfr_ptr = 0x80; 17588c2ecf20Sopenharmony_ci if (bs == 64) 17598c2ecf20Sopenharmony_ci *(__be64 *)(bfr_ptr + 56) = cpu_to_be64(scmd1 << 3); 17608c2ecf20Sopenharmony_ci else 17618c2ecf20Sopenharmony_ci *(__be64 *)(bfr_ptr + 120) = cpu_to_be64(scmd1 << 3); 17628c2ecf20Sopenharmony_ci} 17638c2ecf20Sopenharmony_ci 17648c2ecf20Sopenharmony_cistatic int chcr_ahash_final(struct ahash_request *req) 17658c2ecf20Sopenharmony_ci{ 17668c2ecf20Sopenharmony_ci struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(req); 17678c2ecf20Sopenharmony_ci struct crypto_ahash *rtfm = crypto_ahash_reqtfm(req); 17688c2ecf20Sopenharmony_ci struct chcr_dev *dev = h_ctx(rtfm)->dev; 17698c2ecf20Sopenharmony_ci struct hash_wr_param params; 17708c2ecf20Sopenharmony_ci struct sk_buff *skb; 17718c2ecf20Sopenharmony_ci struct uld_ctx *u_ctx = ULD_CTX(h_ctx(rtfm)); 17728c2ecf20Sopenharmony_ci struct chcr_context *ctx = h_ctx(rtfm); 17738c2ecf20Sopenharmony_ci u8 bs = crypto_tfm_alg_blocksize(crypto_ahash_tfm(rtfm)); 17748c2ecf20Sopenharmony_ci int error; 17758c2ecf20Sopenharmony_ci unsigned int cpu; 17768c2ecf20Sopenharmony_ci 17778c2ecf20Sopenharmony_ci cpu = get_cpu(); 17788c2ecf20Sopenharmony_ci req_ctx->txqidx = cpu % ctx->ntxq; 17798c2ecf20Sopenharmony_ci req_ctx->rxqidx = cpu % ctx->nrxq; 17808c2ecf20Sopenharmony_ci put_cpu(); 17818c2ecf20Sopenharmony_ci 17828c2ecf20Sopenharmony_ci error = chcr_inc_wrcount(dev); 17838c2ecf20Sopenharmony_ci if (error) 17848c2ecf20Sopenharmony_ci return -ENXIO; 17858c2ecf20Sopenharmony_ci 17868c2ecf20Sopenharmony_ci chcr_init_hctx_per_wr(req_ctx); 17878c2ecf20Sopenharmony_ci if (is_hmac(crypto_ahash_tfm(rtfm))) 17888c2ecf20Sopenharmony_ci params.opad_needed = 1; 17898c2ecf20Sopenharmony_ci else 17908c2ecf20Sopenharmony_ci params.opad_needed = 0; 17918c2ecf20Sopenharmony_ci params.sg_len = 0; 17928c2ecf20Sopenharmony_ci req_ctx->hctx_wr.isfinal = 1; 17938c2ecf20Sopenharmony_ci get_alg_config(¶ms.alg_prm, crypto_ahash_digestsize(rtfm)); 17948c2ecf20Sopenharmony_ci params.kctx_len = roundup(params.alg_prm.result_size, 16); 17958c2ecf20Sopenharmony_ci if (is_hmac(crypto_ahash_tfm(rtfm))) { 17968c2ecf20Sopenharmony_ci params.opad_needed = 1; 17978c2ecf20Sopenharmony_ci params.kctx_len *= 2; 17988c2ecf20Sopenharmony_ci } else { 17998c2ecf20Sopenharmony_ci params.opad_needed = 0; 18008c2ecf20Sopenharmony_ci } 18018c2ecf20Sopenharmony_ci 18028c2ecf20Sopenharmony_ci req_ctx->hctx_wr.result = 1; 18038c2ecf20Sopenharmony_ci params.bfr_len = req_ctx->reqlen; 18048c2ecf20Sopenharmony_ci req_ctx->data_len += params.bfr_len + params.sg_len; 18058c2ecf20Sopenharmony_ci req_ctx->hctx_wr.srcsg = req->src; 18068c2ecf20Sopenharmony_ci if (req_ctx->reqlen == 0) { 18078c2ecf20Sopenharmony_ci create_last_hash_block(req_ctx->reqbfr, bs, req_ctx->data_len); 18088c2ecf20Sopenharmony_ci params.last = 0; 18098c2ecf20Sopenharmony_ci params.more = 1; 18108c2ecf20Sopenharmony_ci params.scmd1 = 0; 18118c2ecf20Sopenharmony_ci params.bfr_len = bs; 18128c2ecf20Sopenharmony_ci 18138c2ecf20Sopenharmony_ci } else { 18148c2ecf20Sopenharmony_ci params.scmd1 = req_ctx->data_len; 18158c2ecf20Sopenharmony_ci params.last = 1; 18168c2ecf20Sopenharmony_ci params.more = 0; 18178c2ecf20Sopenharmony_ci } 18188c2ecf20Sopenharmony_ci params.hash_size = crypto_ahash_digestsize(rtfm); 18198c2ecf20Sopenharmony_ci skb = create_hash_wr(req, ¶ms); 18208c2ecf20Sopenharmony_ci if (IS_ERR(skb)) { 18218c2ecf20Sopenharmony_ci error = PTR_ERR(skb); 18228c2ecf20Sopenharmony_ci goto err; 18238c2ecf20Sopenharmony_ci } 18248c2ecf20Sopenharmony_ci req_ctx->reqlen = 0; 18258c2ecf20Sopenharmony_ci skb->dev = u_ctx->lldi.ports[0]; 18268c2ecf20Sopenharmony_ci set_wr_txq(skb, CPL_PRIORITY_DATA, req_ctx->txqidx); 18278c2ecf20Sopenharmony_ci chcr_send_wr(skb); 18288c2ecf20Sopenharmony_ci return -EINPROGRESS; 18298c2ecf20Sopenharmony_cierr: 18308c2ecf20Sopenharmony_ci chcr_dec_wrcount(dev); 18318c2ecf20Sopenharmony_ci return error; 18328c2ecf20Sopenharmony_ci} 18338c2ecf20Sopenharmony_ci 18348c2ecf20Sopenharmony_cistatic int chcr_ahash_finup(struct ahash_request *req) 18358c2ecf20Sopenharmony_ci{ 18368c2ecf20Sopenharmony_ci struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(req); 18378c2ecf20Sopenharmony_ci struct crypto_ahash *rtfm = crypto_ahash_reqtfm(req); 18388c2ecf20Sopenharmony_ci struct chcr_dev *dev = h_ctx(rtfm)->dev; 18398c2ecf20Sopenharmony_ci struct uld_ctx *u_ctx = ULD_CTX(h_ctx(rtfm)); 18408c2ecf20Sopenharmony_ci struct chcr_context *ctx = h_ctx(rtfm); 18418c2ecf20Sopenharmony_ci struct sk_buff *skb; 18428c2ecf20Sopenharmony_ci struct hash_wr_param params; 18438c2ecf20Sopenharmony_ci u8 bs; 18448c2ecf20Sopenharmony_ci int error; 18458c2ecf20Sopenharmony_ci unsigned int cpu; 18468c2ecf20Sopenharmony_ci 18478c2ecf20Sopenharmony_ci cpu = get_cpu(); 18488c2ecf20Sopenharmony_ci req_ctx->txqidx = cpu % ctx->ntxq; 18498c2ecf20Sopenharmony_ci req_ctx->rxqidx = cpu % ctx->nrxq; 18508c2ecf20Sopenharmony_ci put_cpu(); 18518c2ecf20Sopenharmony_ci 18528c2ecf20Sopenharmony_ci bs = crypto_tfm_alg_blocksize(crypto_ahash_tfm(rtfm)); 18538c2ecf20Sopenharmony_ci error = chcr_inc_wrcount(dev); 18548c2ecf20Sopenharmony_ci if (error) 18558c2ecf20Sopenharmony_ci return -ENXIO; 18568c2ecf20Sopenharmony_ci 18578c2ecf20Sopenharmony_ci if (unlikely(cxgb4_is_crypto_q_full(u_ctx->lldi.ports[0], 18588c2ecf20Sopenharmony_ci req_ctx->txqidx) && 18598c2ecf20Sopenharmony_ci (!(req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)))) { 18608c2ecf20Sopenharmony_ci error = -ENOSPC; 18618c2ecf20Sopenharmony_ci goto err; 18628c2ecf20Sopenharmony_ci } 18638c2ecf20Sopenharmony_ci chcr_init_hctx_per_wr(req_ctx); 18648c2ecf20Sopenharmony_ci error = chcr_hash_dma_map(&u_ctx->lldi.pdev->dev, req); 18658c2ecf20Sopenharmony_ci if (error) { 18668c2ecf20Sopenharmony_ci error = -ENOMEM; 18678c2ecf20Sopenharmony_ci goto err; 18688c2ecf20Sopenharmony_ci } 18698c2ecf20Sopenharmony_ci 18708c2ecf20Sopenharmony_ci get_alg_config(¶ms.alg_prm, crypto_ahash_digestsize(rtfm)); 18718c2ecf20Sopenharmony_ci params.kctx_len = roundup(params.alg_prm.result_size, 16); 18728c2ecf20Sopenharmony_ci if (is_hmac(crypto_ahash_tfm(rtfm))) { 18738c2ecf20Sopenharmony_ci params.kctx_len *= 2; 18748c2ecf20Sopenharmony_ci params.opad_needed = 1; 18758c2ecf20Sopenharmony_ci } else { 18768c2ecf20Sopenharmony_ci params.opad_needed = 0; 18778c2ecf20Sopenharmony_ci } 18788c2ecf20Sopenharmony_ci 18798c2ecf20Sopenharmony_ci params.sg_len = chcr_hash_ent_in_wr(req->src, !!req_ctx->reqlen, 18808c2ecf20Sopenharmony_ci HASH_SPACE_LEFT(params.kctx_len), 0); 18818c2ecf20Sopenharmony_ci if (params.sg_len < req->nbytes) { 18828c2ecf20Sopenharmony_ci if (is_hmac(crypto_ahash_tfm(rtfm))) { 18838c2ecf20Sopenharmony_ci params.kctx_len /= 2; 18848c2ecf20Sopenharmony_ci params.opad_needed = 0; 18858c2ecf20Sopenharmony_ci } 18868c2ecf20Sopenharmony_ci params.last = 0; 18878c2ecf20Sopenharmony_ci params.more = 1; 18888c2ecf20Sopenharmony_ci params.sg_len = rounddown(params.sg_len + req_ctx->reqlen, bs) 18898c2ecf20Sopenharmony_ci - req_ctx->reqlen; 18908c2ecf20Sopenharmony_ci params.hash_size = params.alg_prm.result_size; 18918c2ecf20Sopenharmony_ci params.scmd1 = 0; 18928c2ecf20Sopenharmony_ci } else { 18938c2ecf20Sopenharmony_ci params.last = 1; 18948c2ecf20Sopenharmony_ci params.more = 0; 18958c2ecf20Sopenharmony_ci params.sg_len = req->nbytes; 18968c2ecf20Sopenharmony_ci params.hash_size = crypto_ahash_digestsize(rtfm); 18978c2ecf20Sopenharmony_ci params.scmd1 = req_ctx->data_len + req_ctx->reqlen + 18988c2ecf20Sopenharmony_ci params.sg_len; 18998c2ecf20Sopenharmony_ci } 19008c2ecf20Sopenharmony_ci params.bfr_len = req_ctx->reqlen; 19018c2ecf20Sopenharmony_ci req_ctx->data_len += params.bfr_len + params.sg_len; 19028c2ecf20Sopenharmony_ci req_ctx->hctx_wr.result = 1; 19038c2ecf20Sopenharmony_ci req_ctx->hctx_wr.srcsg = req->src; 19048c2ecf20Sopenharmony_ci if ((req_ctx->reqlen + req->nbytes) == 0) { 19058c2ecf20Sopenharmony_ci create_last_hash_block(req_ctx->reqbfr, bs, req_ctx->data_len); 19068c2ecf20Sopenharmony_ci params.last = 0; 19078c2ecf20Sopenharmony_ci params.more = 1; 19088c2ecf20Sopenharmony_ci params.scmd1 = 0; 19098c2ecf20Sopenharmony_ci params.bfr_len = bs; 19108c2ecf20Sopenharmony_ci } 19118c2ecf20Sopenharmony_ci skb = create_hash_wr(req, ¶ms); 19128c2ecf20Sopenharmony_ci if (IS_ERR(skb)) { 19138c2ecf20Sopenharmony_ci error = PTR_ERR(skb); 19148c2ecf20Sopenharmony_ci goto unmap; 19158c2ecf20Sopenharmony_ci } 19168c2ecf20Sopenharmony_ci req_ctx->reqlen = 0; 19178c2ecf20Sopenharmony_ci req_ctx->hctx_wr.processed += params.sg_len; 19188c2ecf20Sopenharmony_ci skb->dev = u_ctx->lldi.ports[0]; 19198c2ecf20Sopenharmony_ci set_wr_txq(skb, CPL_PRIORITY_DATA, req_ctx->txqidx); 19208c2ecf20Sopenharmony_ci chcr_send_wr(skb); 19218c2ecf20Sopenharmony_ci return -EINPROGRESS; 19228c2ecf20Sopenharmony_ciunmap: 19238c2ecf20Sopenharmony_ci chcr_hash_dma_unmap(&u_ctx->lldi.pdev->dev, req); 19248c2ecf20Sopenharmony_cierr: 19258c2ecf20Sopenharmony_ci chcr_dec_wrcount(dev); 19268c2ecf20Sopenharmony_ci return error; 19278c2ecf20Sopenharmony_ci} 19288c2ecf20Sopenharmony_ci 19298c2ecf20Sopenharmony_cistatic int chcr_ahash_digest(struct ahash_request *req) 19308c2ecf20Sopenharmony_ci{ 19318c2ecf20Sopenharmony_ci struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(req); 19328c2ecf20Sopenharmony_ci struct crypto_ahash *rtfm = crypto_ahash_reqtfm(req); 19338c2ecf20Sopenharmony_ci struct chcr_dev *dev = h_ctx(rtfm)->dev; 19348c2ecf20Sopenharmony_ci struct uld_ctx *u_ctx = ULD_CTX(h_ctx(rtfm)); 19358c2ecf20Sopenharmony_ci struct chcr_context *ctx = h_ctx(rtfm); 19368c2ecf20Sopenharmony_ci struct sk_buff *skb; 19378c2ecf20Sopenharmony_ci struct hash_wr_param params; 19388c2ecf20Sopenharmony_ci u8 bs; 19398c2ecf20Sopenharmony_ci int error; 19408c2ecf20Sopenharmony_ci unsigned int cpu; 19418c2ecf20Sopenharmony_ci 19428c2ecf20Sopenharmony_ci cpu = get_cpu(); 19438c2ecf20Sopenharmony_ci req_ctx->txqidx = cpu % ctx->ntxq; 19448c2ecf20Sopenharmony_ci req_ctx->rxqidx = cpu % ctx->nrxq; 19458c2ecf20Sopenharmony_ci put_cpu(); 19468c2ecf20Sopenharmony_ci 19478c2ecf20Sopenharmony_ci rtfm->init(req); 19488c2ecf20Sopenharmony_ci bs = crypto_tfm_alg_blocksize(crypto_ahash_tfm(rtfm)); 19498c2ecf20Sopenharmony_ci error = chcr_inc_wrcount(dev); 19508c2ecf20Sopenharmony_ci if (error) 19518c2ecf20Sopenharmony_ci return -ENXIO; 19528c2ecf20Sopenharmony_ci 19538c2ecf20Sopenharmony_ci if (unlikely(cxgb4_is_crypto_q_full(u_ctx->lldi.ports[0], 19548c2ecf20Sopenharmony_ci req_ctx->txqidx) && 19558c2ecf20Sopenharmony_ci (!(req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)))) { 19568c2ecf20Sopenharmony_ci error = -ENOSPC; 19578c2ecf20Sopenharmony_ci goto err; 19588c2ecf20Sopenharmony_ci } 19598c2ecf20Sopenharmony_ci 19608c2ecf20Sopenharmony_ci chcr_init_hctx_per_wr(req_ctx); 19618c2ecf20Sopenharmony_ci error = chcr_hash_dma_map(&u_ctx->lldi.pdev->dev, req); 19628c2ecf20Sopenharmony_ci if (error) { 19638c2ecf20Sopenharmony_ci error = -ENOMEM; 19648c2ecf20Sopenharmony_ci goto err; 19658c2ecf20Sopenharmony_ci } 19668c2ecf20Sopenharmony_ci 19678c2ecf20Sopenharmony_ci get_alg_config(¶ms.alg_prm, crypto_ahash_digestsize(rtfm)); 19688c2ecf20Sopenharmony_ci params.kctx_len = roundup(params.alg_prm.result_size, 16); 19698c2ecf20Sopenharmony_ci if (is_hmac(crypto_ahash_tfm(rtfm))) { 19708c2ecf20Sopenharmony_ci params.kctx_len *= 2; 19718c2ecf20Sopenharmony_ci params.opad_needed = 1; 19728c2ecf20Sopenharmony_ci } else { 19738c2ecf20Sopenharmony_ci params.opad_needed = 0; 19748c2ecf20Sopenharmony_ci } 19758c2ecf20Sopenharmony_ci params.sg_len = chcr_hash_ent_in_wr(req->src, !!req_ctx->reqlen, 19768c2ecf20Sopenharmony_ci HASH_SPACE_LEFT(params.kctx_len), 0); 19778c2ecf20Sopenharmony_ci if (params.sg_len < req->nbytes) { 19788c2ecf20Sopenharmony_ci if (is_hmac(crypto_ahash_tfm(rtfm))) { 19798c2ecf20Sopenharmony_ci params.kctx_len /= 2; 19808c2ecf20Sopenharmony_ci params.opad_needed = 0; 19818c2ecf20Sopenharmony_ci } 19828c2ecf20Sopenharmony_ci params.last = 0; 19838c2ecf20Sopenharmony_ci params.more = 1; 19848c2ecf20Sopenharmony_ci params.scmd1 = 0; 19858c2ecf20Sopenharmony_ci params.sg_len = rounddown(params.sg_len, bs); 19868c2ecf20Sopenharmony_ci params.hash_size = params.alg_prm.result_size; 19878c2ecf20Sopenharmony_ci } else { 19888c2ecf20Sopenharmony_ci params.sg_len = req->nbytes; 19898c2ecf20Sopenharmony_ci params.hash_size = crypto_ahash_digestsize(rtfm); 19908c2ecf20Sopenharmony_ci params.last = 1; 19918c2ecf20Sopenharmony_ci params.more = 0; 19928c2ecf20Sopenharmony_ci params.scmd1 = req->nbytes + req_ctx->data_len; 19938c2ecf20Sopenharmony_ci 19948c2ecf20Sopenharmony_ci } 19958c2ecf20Sopenharmony_ci params.bfr_len = 0; 19968c2ecf20Sopenharmony_ci req_ctx->hctx_wr.result = 1; 19978c2ecf20Sopenharmony_ci req_ctx->hctx_wr.srcsg = req->src; 19988c2ecf20Sopenharmony_ci req_ctx->data_len += params.bfr_len + params.sg_len; 19998c2ecf20Sopenharmony_ci 20008c2ecf20Sopenharmony_ci if (req->nbytes == 0) { 20018c2ecf20Sopenharmony_ci create_last_hash_block(req_ctx->reqbfr, bs, req_ctx->data_len); 20028c2ecf20Sopenharmony_ci params.more = 1; 20038c2ecf20Sopenharmony_ci params.bfr_len = bs; 20048c2ecf20Sopenharmony_ci } 20058c2ecf20Sopenharmony_ci 20068c2ecf20Sopenharmony_ci skb = create_hash_wr(req, ¶ms); 20078c2ecf20Sopenharmony_ci if (IS_ERR(skb)) { 20088c2ecf20Sopenharmony_ci error = PTR_ERR(skb); 20098c2ecf20Sopenharmony_ci goto unmap; 20108c2ecf20Sopenharmony_ci } 20118c2ecf20Sopenharmony_ci req_ctx->hctx_wr.processed += params.sg_len; 20128c2ecf20Sopenharmony_ci skb->dev = u_ctx->lldi.ports[0]; 20138c2ecf20Sopenharmony_ci set_wr_txq(skb, CPL_PRIORITY_DATA, req_ctx->txqidx); 20148c2ecf20Sopenharmony_ci chcr_send_wr(skb); 20158c2ecf20Sopenharmony_ci return -EINPROGRESS; 20168c2ecf20Sopenharmony_ciunmap: 20178c2ecf20Sopenharmony_ci chcr_hash_dma_unmap(&u_ctx->lldi.pdev->dev, req); 20188c2ecf20Sopenharmony_cierr: 20198c2ecf20Sopenharmony_ci chcr_dec_wrcount(dev); 20208c2ecf20Sopenharmony_ci return error; 20218c2ecf20Sopenharmony_ci} 20228c2ecf20Sopenharmony_ci 20238c2ecf20Sopenharmony_cistatic int chcr_ahash_continue(struct ahash_request *req) 20248c2ecf20Sopenharmony_ci{ 20258c2ecf20Sopenharmony_ci struct chcr_ahash_req_ctx *reqctx = ahash_request_ctx(req); 20268c2ecf20Sopenharmony_ci struct chcr_hctx_per_wr *hctx_wr = &reqctx->hctx_wr; 20278c2ecf20Sopenharmony_ci struct crypto_ahash *rtfm = crypto_ahash_reqtfm(req); 20288c2ecf20Sopenharmony_ci struct chcr_context *ctx = h_ctx(rtfm); 20298c2ecf20Sopenharmony_ci struct uld_ctx *u_ctx = ULD_CTX(ctx); 20308c2ecf20Sopenharmony_ci struct sk_buff *skb; 20318c2ecf20Sopenharmony_ci struct hash_wr_param params; 20328c2ecf20Sopenharmony_ci u8 bs; 20338c2ecf20Sopenharmony_ci int error; 20348c2ecf20Sopenharmony_ci unsigned int cpu; 20358c2ecf20Sopenharmony_ci 20368c2ecf20Sopenharmony_ci cpu = get_cpu(); 20378c2ecf20Sopenharmony_ci reqctx->txqidx = cpu % ctx->ntxq; 20388c2ecf20Sopenharmony_ci reqctx->rxqidx = cpu % ctx->nrxq; 20398c2ecf20Sopenharmony_ci put_cpu(); 20408c2ecf20Sopenharmony_ci 20418c2ecf20Sopenharmony_ci bs = crypto_tfm_alg_blocksize(crypto_ahash_tfm(rtfm)); 20428c2ecf20Sopenharmony_ci get_alg_config(¶ms.alg_prm, crypto_ahash_digestsize(rtfm)); 20438c2ecf20Sopenharmony_ci params.kctx_len = roundup(params.alg_prm.result_size, 16); 20448c2ecf20Sopenharmony_ci if (is_hmac(crypto_ahash_tfm(rtfm))) { 20458c2ecf20Sopenharmony_ci params.kctx_len *= 2; 20468c2ecf20Sopenharmony_ci params.opad_needed = 1; 20478c2ecf20Sopenharmony_ci } else { 20488c2ecf20Sopenharmony_ci params.opad_needed = 0; 20498c2ecf20Sopenharmony_ci } 20508c2ecf20Sopenharmony_ci params.sg_len = chcr_hash_ent_in_wr(hctx_wr->srcsg, 0, 20518c2ecf20Sopenharmony_ci HASH_SPACE_LEFT(params.kctx_len), 20528c2ecf20Sopenharmony_ci hctx_wr->src_ofst); 20538c2ecf20Sopenharmony_ci if ((params.sg_len + hctx_wr->processed) > req->nbytes) 20548c2ecf20Sopenharmony_ci params.sg_len = req->nbytes - hctx_wr->processed; 20558c2ecf20Sopenharmony_ci if (!hctx_wr->result || 20568c2ecf20Sopenharmony_ci ((params.sg_len + hctx_wr->processed) < req->nbytes)) { 20578c2ecf20Sopenharmony_ci if (is_hmac(crypto_ahash_tfm(rtfm))) { 20588c2ecf20Sopenharmony_ci params.kctx_len /= 2; 20598c2ecf20Sopenharmony_ci params.opad_needed = 0; 20608c2ecf20Sopenharmony_ci } 20618c2ecf20Sopenharmony_ci params.last = 0; 20628c2ecf20Sopenharmony_ci params.more = 1; 20638c2ecf20Sopenharmony_ci params.sg_len = rounddown(params.sg_len, bs); 20648c2ecf20Sopenharmony_ci params.hash_size = params.alg_prm.result_size; 20658c2ecf20Sopenharmony_ci params.scmd1 = 0; 20668c2ecf20Sopenharmony_ci } else { 20678c2ecf20Sopenharmony_ci params.last = 1; 20688c2ecf20Sopenharmony_ci params.more = 0; 20698c2ecf20Sopenharmony_ci params.hash_size = crypto_ahash_digestsize(rtfm); 20708c2ecf20Sopenharmony_ci params.scmd1 = reqctx->data_len + params.sg_len; 20718c2ecf20Sopenharmony_ci } 20728c2ecf20Sopenharmony_ci params.bfr_len = 0; 20738c2ecf20Sopenharmony_ci reqctx->data_len += params.sg_len; 20748c2ecf20Sopenharmony_ci skb = create_hash_wr(req, ¶ms); 20758c2ecf20Sopenharmony_ci if (IS_ERR(skb)) { 20768c2ecf20Sopenharmony_ci error = PTR_ERR(skb); 20778c2ecf20Sopenharmony_ci goto err; 20788c2ecf20Sopenharmony_ci } 20798c2ecf20Sopenharmony_ci hctx_wr->processed += params.sg_len; 20808c2ecf20Sopenharmony_ci skb->dev = u_ctx->lldi.ports[0]; 20818c2ecf20Sopenharmony_ci set_wr_txq(skb, CPL_PRIORITY_DATA, reqctx->txqidx); 20828c2ecf20Sopenharmony_ci chcr_send_wr(skb); 20838c2ecf20Sopenharmony_ci return 0; 20848c2ecf20Sopenharmony_cierr: 20858c2ecf20Sopenharmony_ci return error; 20868c2ecf20Sopenharmony_ci} 20878c2ecf20Sopenharmony_ci 20888c2ecf20Sopenharmony_cistatic inline void chcr_handle_ahash_resp(struct ahash_request *req, 20898c2ecf20Sopenharmony_ci unsigned char *input, 20908c2ecf20Sopenharmony_ci int err) 20918c2ecf20Sopenharmony_ci{ 20928c2ecf20Sopenharmony_ci struct chcr_ahash_req_ctx *reqctx = ahash_request_ctx(req); 20938c2ecf20Sopenharmony_ci struct chcr_hctx_per_wr *hctx_wr = &reqctx->hctx_wr; 20948c2ecf20Sopenharmony_ci int digestsize, updated_digestsize; 20958c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 20968c2ecf20Sopenharmony_ci struct uld_ctx *u_ctx = ULD_CTX(h_ctx(tfm)); 20978c2ecf20Sopenharmony_ci struct chcr_dev *dev = h_ctx(tfm)->dev; 20988c2ecf20Sopenharmony_ci 20998c2ecf20Sopenharmony_ci if (input == NULL) 21008c2ecf20Sopenharmony_ci goto out; 21018c2ecf20Sopenharmony_ci digestsize = crypto_ahash_digestsize(crypto_ahash_reqtfm(req)); 21028c2ecf20Sopenharmony_ci updated_digestsize = digestsize; 21038c2ecf20Sopenharmony_ci if (digestsize == SHA224_DIGEST_SIZE) 21048c2ecf20Sopenharmony_ci updated_digestsize = SHA256_DIGEST_SIZE; 21058c2ecf20Sopenharmony_ci else if (digestsize == SHA384_DIGEST_SIZE) 21068c2ecf20Sopenharmony_ci updated_digestsize = SHA512_DIGEST_SIZE; 21078c2ecf20Sopenharmony_ci 21088c2ecf20Sopenharmony_ci if (hctx_wr->dma_addr) { 21098c2ecf20Sopenharmony_ci dma_unmap_single(&u_ctx->lldi.pdev->dev, hctx_wr->dma_addr, 21108c2ecf20Sopenharmony_ci hctx_wr->dma_len, DMA_TO_DEVICE); 21118c2ecf20Sopenharmony_ci hctx_wr->dma_addr = 0; 21128c2ecf20Sopenharmony_ci } 21138c2ecf20Sopenharmony_ci if (hctx_wr->isfinal || ((hctx_wr->processed + reqctx->reqlen) == 21148c2ecf20Sopenharmony_ci req->nbytes)) { 21158c2ecf20Sopenharmony_ci if (hctx_wr->result == 1) { 21168c2ecf20Sopenharmony_ci hctx_wr->result = 0; 21178c2ecf20Sopenharmony_ci memcpy(req->result, input + sizeof(struct cpl_fw6_pld), 21188c2ecf20Sopenharmony_ci digestsize); 21198c2ecf20Sopenharmony_ci } else { 21208c2ecf20Sopenharmony_ci memcpy(reqctx->partial_hash, 21218c2ecf20Sopenharmony_ci input + sizeof(struct cpl_fw6_pld), 21228c2ecf20Sopenharmony_ci updated_digestsize); 21238c2ecf20Sopenharmony_ci 21248c2ecf20Sopenharmony_ci } 21258c2ecf20Sopenharmony_ci goto unmap; 21268c2ecf20Sopenharmony_ci } 21278c2ecf20Sopenharmony_ci memcpy(reqctx->partial_hash, input + sizeof(struct cpl_fw6_pld), 21288c2ecf20Sopenharmony_ci updated_digestsize); 21298c2ecf20Sopenharmony_ci 21308c2ecf20Sopenharmony_ci err = chcr_ahash_continue(req); 21318c2ecf20Sopenharmony_ci if (err) 21328c2ecf20Sopenharmony_ci goto unmap; 21338c2ecf20Sopenharmony_ci return; 21348c2ecf20Sopenharmony_ciunmap: 21358c2ecf20Sopenharmony_ci if (hctx_wr->is_sg_map) 21368c2ecf20Sopenharmony_ci chcr_hash_dma_unmap(&u_ctx->lldi.pdev->dev, req); 21378c2ecf20Sopenharmony_ci 21388c2ecf20Sopenharmony_ci 21398c2ecf20Sopenharmony_ciout: 21408c2ecf20Sopenharmony_ci chcr_dec_wrcount(dev); 21418c2ecf20Sopenharmony_ci req->base.complete(&req->base, err); 21428c2ecf20Sopenharmony_ci} 21438c2ecf20Sopenharmony_ci 21448c2ecf20Sopenharmony_ci/* 21458c2ecf20Sopenharmony_ci * chcr_handle_resp - Unmap the DMA buffers associated with the request 21468c2ecf20Sopenharmony_ci * @req: crypto request 21478c2ecf20Sopenharmony_ci */ 21488c2ecf20Sopenharmony_ciint chcr_handle_resp(struct crypto_async_request *req, unsigned char *input, 21498c2ecf20Sopenharmony_ci int err) 21508c2ecf20Sopenharmony_ci{ 21518c2ecf20Sopenharmony_ci struct crypto_tfm *tfm = req->tfm; 21528c2ecf20Sopenharmony_ci struct chcr_context *ctx = crypto_tfm_ctx(tfm); 21538c2ecf20Sopenharmony_ci struct adapter *adap = padap(ctx->dev); 21548c2ecf20Sopenharmony_ci 21558c2ecf20Sopenharmony_ci switch (tfm->__crt_alg->cra_flags & CRYPTO_ALG_TYPE_MASK) { 21568c2ecf20Sopenharmony_ci case CRYPTO_ALG_TYPE_AEAD: 21578c2ecf20Sopenharmony_ci err = chcr_handle_aead_resp(aead_request_cast(req), input, err); 21588c2ecf20Sopenharmony_ci break; 21598c2ecf20Sopenharmony_ci 21608c2ecf20Sopenharmony_ci case CRYPTO_ALG_TYPE_SKCIPHER: 21618c2ecf20Sopenharmony_ci chcr_handle_cipher_resp(skcipher_request_cast(req), 21628c2ecf20Sopenharmony_ci input, err); 21638c2ecf20Sopenharmony_ci break; 21648c2ecf20Sopenharmony_ci case CRYPTO_ALG_TYPE_AHASH: 21658c2ecf20Sopenharmony_ci chcr_handle_ahash_resp(ahash_request_cast(req), input, err); 21668c2ecf20Sopenharmony_ci } 21678c2ecf20Sopenharmony_ci atomic_inc(&adap->chcr_stats.complete); 21688c2ecf20Sopenharmony_ci return err; 21698c2ecf20Sopenharmony_ci} 21708c2ecf20Sopenharmony_cistatic int chcr_ahash_export(struct ahash_request *areq, void *out) 21718c2ecf20Sopenharmony_ci{ 21728c2ecf20Sopenharmony_ci struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 21738c2ecf20Sopenharmony_ci struct chcr_ahash_req_ctx *state = out; 21748c2ecf20Sopenharmony_ci 21758c2ecf20Sopenharmony_ci state->reqlen = req_ctx->reqlen; 21768c2ecf20Sopenharmony_ci state->data_len = req_ctx->data_len; 21778c2ecf20Sopenharmony_ci memcpy(state->bfr1, req_ctx->reqbfr, req_ctx->reqlen); 21788c2ecf20Sopenharmony_ci memcpy(state->partial_hash, req_ctx->partial_hash, 21798c2ecf20Sopenharmony_ci CHCR_HASH_MAX_DIGEST_SIZE); 21808c2ecf20Sopenharmony_ci chcr_init_hctx_per_wr(state); 21818c2ecf20Sopenharmony_ci return 0; 21828c2ecf20Sopenharmony_ci} 21838c2ecf20Sopenharmony_ci 21848c2ecf20Sopenharmony_cistatic int chcr_ahash_import(struct ahash_request *areq, const void *in) 21858c2ecf20Sopenharmony_ci{ 21868c2ecf20Sopenharmony_ci struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 21878c2ecf20Sopenharmony_ci struct chcr_ahash_req_ctx *state = (struct chcr_ahash_req_ctx *)in; 21888c2ecf20Sopenharmony_ci 21898c2ecf20Sopenharmony_ci req_ctx->reqlen = state->reqlen; 21908c2ecf20Sopenharmony_ci req_ctx->data_len = state->data_len; 21918c2ecf20Sopenharmony_ci req_ctx->reqbfr = req_ctx->bfr1; 21928c2ecf20Sopenharmony_ci req_ctx->skbfr = req_ctx->bfr2; 21938c2ecf20Sopenharmony_ci memcpy(req_ctx->bfr1, state->bfr1, CHCR_HASH_MAX_BLOCK_SIZE_128); 21948c2ecf20Sopenharmony_ci memcpy(req_ctx->partial_hash, state->partial_hash, 21958c2ecf20Sopenharmony_ci CHCR_HASH_MAX_DIGEST_SIZE); 21968c2ecf20Sopenharmony_ci chcr_init_hctx_per_wr(req_ctx); 21978c2ecf20Sopenharmony_ci return 0; 21988c2ecf20Sopenharmony_ci} 21998c2ecf20Sopenharmony_ci 22008c2ecf20Sopenharmony_cistatic int chcr_ahash_setkey(struct crypto_ahash *tfm, const u8 *key, 22018c2ecf20Sopenharmony_ci unsigned int keylen) 22028c2ecf20Sopenharmony_ci{ 22038c2ecf20Sopenharmony_ci struct hmac_ctx *hmacctx = HMAC_CTX(h_ctx(tfm)); 22048c2ecf20Sopenharmony_ci unsigned int digestsize = crypto_ahash_digestsize(tfm); 22058c2ecf20Sopenharmony_ci unsigned int bs = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); 22068c2ecf20Sopenharmony_ci unsigned int i, err = 0, updated_digestsize; 22078c2ecf20Sopenharmony_ci 22088c2ecf20Sopenharmony_ci SHASH_DESC_ON_STACK(shash, hmacctx->base_hash); 22098c2ecf20Sopenharmony_ci 22108c2ecf20Sopenharmony_ci /* use the key to calculate the ipad and opad. ipad will sent with the 22118c2ecf20Sopenharmony_ci * first request's data. opad will be sent with the final hash result 22128c2ecf20Sopenharmony_ci * ipad in hmacctx->ipad and opad in hmacctx->opad location 22138c2ecf20Sopenharmony_ci */ 22148c2ecf20Sopenharmony_ci shash->tfm = hmacctx->base_hash; 22158c2ecf20Sopenharmony_ci if (keylen > bs) { 22168c2ecf20Sopenharmony_ci err = crypto_shash_digest(shash, key, keylen, 22178c2ecf20Sopenharmony_ci hmacctx->ipad); 22188c2ecf20Sopenharmony_ci if (err) 22198c2ecf20Sopenharmony_ci goto out; 22208c2ecf20Sopenharmony_ci keylen = digestsize; 22218c2ecf20Sopenharmony_ci } else { 22228c2ecf20Sopenharmony_ci memcpy(hmacctx->ipad, key, keylen); 22238c2ecf20Sopenharmony_ci } 22248c2ecf20Sopenharmony_ci memset(hmacctx->ipad + keylen, 0, bs - keylen); 22258c2ecf20Sopenharmony_ci memcpy(hmacctx->opad, hmacctx->ipad, bs); 22268c2ecf20Sopenharmony_ci 22278c2ecf20Sopenharmony_ci for (i = 0; i < bs / sizeof(int); i++) { 22288c2ecf20Sopenharmony_ci *((unsigned int *)(&hmacctx->ipad) + i) ^= IPAD_DATA; 22298c2ecf20Sopenharmony_ci *((unsigned int *)(&hmacctx->opad) + i) ^= OPAD_DATA; 22308c2ecf20Sopenharmony_ci } 22318c2ecf20Sopenharmony_ci 22328c2ecf20Sopenharmony_ci updated_digestsize = digestsize; 22338c2ecf20Sopenharmony_ci if (digestsize == SHA224_DIGEST_SIZE) 22348c2ecf20Sopenharmony_ci updated_digestsize = SHA256_DIGEST_SIZE; 22358c2ecf20Sopenharmony_ci else if (digestsize == SHA384_DIGEST_SIZE) 22368c2ecf20Sopenharmony_ci updated_digestsize = SHA512_DIGEST_SIZE; 22378c2ecf20Sopenharmony_ci err = chcr_compute_partial_hash(shash, hmacctx->ipad, 22388c2ecf20Sopenharmony_ci hmacctx->ipad, digestsize); 22398c2ecf20Sopenharmony_ci if (err) 22408c2ecf20Sopenharmony_ci goto out; 22418c2ecf20Sopenharmony_ci chcr_change_order(hmacctx->ipad, updated_digestsize); 22428c2ecf20Sopenharmony_ci 22438c2ecf20Sopenharmony_ci err = chcr_compute_partial_hash(shash, hmacctx->opad, 22448c2ecf20Sopenharmony_ci hmacctx->opad, digestsize); 22458c2ecf20Sopenharmony_ci if (err) 22468c2ecf20Sopenharmony_ci goto out; 22478c2ecf20Sopenharmony_ci chcr_change_order(hmacctx->opad, updated_digestsize); 22488c2ecf20Sopenharmony_ciout: 22498c2ecf20Sopenharmony_ci return err; 22508c2ecf20Sopenharmony_ci} 22518c2ecf20Sopenharmony_ci 22528c2ecf20Sopenharmony_cistatic int chcr_aes_xts_setkey(struct crypto_skcipher *cipher, const u8 *key, 22538c2ecf20Sopenharmony_ci unsigned int key_len) 22548c2ecf20Sopenharmony_ci{ 22558c2ecf20Sopenharmony_ci struct ablk_ctx *ablkctx = ABLK_CTX(c_ctx(cipher)); 22568c2ecf20Sopenharmony_ci unsigned short context_size = 0; 22578c2ecf20Sopenharmony_ci int err; 22588c2ecf20Sopenharmony_ci 22598c2ecf20Sopenharmony_ci err = chcr_cipher_fallback_setkey(cipher, key, key_len); 22608c2ecf20Sopenharmony_ci if (err) 22618c2ecf20Sopenharmony_ci goto badkey_err; 22628c2ecf20Sopenharmony_ci 22638c2ecf20Sopenharmony_ci memcpy(ablkctx->key, key, key_len); 22648c2ecf20Sopenharmony_ci ablkctx->enckey_len = key_len; 22658c2ecf20Sopenharmony_ci get_aes_decrypt_key(ablkctx->rrkey, ablkctx->key, key_len << 2); 22668c2ecf20Sopenharmony_ci context_size = (KEY_CONTEXT_HDR_SALT_AND_PAD + key_len) >> 4; 22678c2ecf20Sopenharmony_ci /* Both keys for xts must be aligned to 16 byte boundary 22688c2ecf20Sopenharmony_ci * by padding with zeros. So for 24 byte keys padding 8 zeroes. 22698c2ecf20Sopenharmony_ci */ 22708c2ecf20Sopenharmony_ci if (key_len == 48) { 22718c2ecf20Sopenharmony_ci context_size = (KEY_CONTEXT_HDR_SALT_AND_PAD + key_len 22728c2ecf20Sopenharmony_ci + 16) >> 4; 22738c2ecf20Sopenharmony_ci memmove(ablkctx->key + 32, ablkctx->key + 24, 24); 22748c2ecf20Sopenharmony_ci memset(ablkctx->key + 24, 0, 8); 22758c2ecf20Sopenharmony_ci memset(ablkctx->key + 56, 0, 8); 22768c2ecf20Sopenharmony_ci ablkctx->enckey_len = 64; 22778c2ecf20Sopenharmony_ci ablkctx->key_ctx_hdr = 22788c2ecf20Sopenharmony_ci FILL_KEY_CTX_HDR(CHCR_KEYCTX_CIPHER_KEY_SIZE_192, 22798c2ecf20Sopenharmony_ci CHCR_KEYCTX_NO_KEY, 1, 22808c2ecf20Sopenharmony_ci 0, context_size); 22818c2ecf20Sopenharmony_ci } else { 22828c2ecf20Sopenharmony_ci ablkctx->key_ctx_hdr = 22838c2ecf20Sopenharmony_ci FILL_KEY_CTX_HDR((key_len == AES_KEYSIZE_256) ? 22848c2ecf20Sopenharmony_ci CHCR_KEYCTX_CIPHER_KEY_SIZE_128 : 22858c2ecf20Sopenharmony_ci CHCR_KEYCTX_CIPHER_KEY_SIZE_256, 22868c2ecf20Sopenharmony_ci CHCR_KEYCTX_NO_KEY, 1, 22878c2ecf20Sopenharmony_ci 0, context_size); 22888c2ecf20Sopenharmony_ci } 22898c2ecf20Sopenharmony_ci ablkctx->ciph_mode = CHCR_SCMD_CIPHER_MODE_AES_XTS; 22908c2ecf20Sopenharmony_ci return 0; 22918c2ecf20Sopenharmony_cibadkey_err: 22928c2ecf20Sopenharmony_ci ablkctx->enckey_len = 0; 22938c2ecf20Sopenharmony_ci 22948c2ecf20Sopenharmony_ci return err; 22958c2ecf20Sopenharmony_ci} 22968c2ecf20Sopenharmony_ci 22978c2ecf20Sopenharmony_cistatic int chcr_sha_init(struct ahash_request *areq) 22988c2ecf20Sopenharmony_ci{ 22998c2ecf20Sopenharmony_ci struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 23008c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 23018c2ecf20Sopenharmony_ci int digestsize = crypto_ahash_digestsize(tfm); 23028c2ecf20Sopenharmony_ci 23038c2ecf20Sopenharmony_ci req_ctx->data_len = 0; 23048c2ecf20Sopenharmony_ci req_ctx->reqlen = 0; 23058c2ecf20Sopenharmony_ci req_ctx->reqbfr = req_ctx->bfr1; 23068c2ecf20Sopenharmony_ci req_ctx->skbfr = req_ctx->bfr2; 23078c2ecf20Sopenharmony_ci copy_hash_init_values(req_ctx->partial_hash, digestsize); 23088c2ecf20Sopenharmony_ci 23098c2ecf20Sopenharmony_ci return 0; 23108c2ecf20Sopenharmony_ci} 23118c2ecf20Sopenharmony_ci 23128c2ecf20Sopenharmony_cistatic int chcr_sha_cra_init(struct crypto_tfm *tfm) 23138c2ecf20Sopenharmony_ci{ 23148c2ecf20Sopenharmony_ci crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), 23158c2ecf20Sopenharmony_ci sizeof(struct chcr_ahash_req_ctx)); 23168c2ecf20Sopenharmony_ci return chcr_device_init(crypto_tfm_ctx(tfm)); 23178c2ecf20Sopenharmony_ci} 23188c2ecf20Sopenharmony_ci 23198c2ecf20Sopenharmony_cistatic int chcr_hmac_init(struct ahash_request *areq) 23208c2ecf20Sopenharmony_ci{ 23218c2ecf20Sopenharmony_ci struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 23228c2ecf20Sopenharmony_ci struct crypto_ahash *rtfm = crypto_ahash_reqtfm(areq); 23238c2ecf20Sopenharmony_ci struct hmac_ctx *hmacctx = HMAC_CTX(h_ctx(rtfm)); 23248c2ecf20Sopenharmony_ci unsigned int digestsize = crypto_ahash_digestsize(rtfm); 23258c2ecf20Sopenharmony_ci unsigned int bs = crypto_tfm_alg_blocksize(crypto_ahash_tfm(rtfm)); 23268c2ecf20Sopenharmony_ci 23278c2ecf20Sopenharmony_ci chcr_sha_init(areq); 23288c2ecf20Sopenharmony_ci req_ctx->data_len = bs; 23298c2ecf20Sopenharmony_ci if (is_hmac(crypto_ahash_tfm(rtfm))) { 23308c2ecf20Sopenharmony_ci if (digestsize == SHA224_DIGEST_SIZE) 23318c2ecf20Sopenharmony_ci memcpy(req_ctx->partial_hash, hmacctx->ipad, 23328c2ecf20Sopenharmony_ci SHA256_DIGEST_SIZE); 23338c2ecf20Sopenharmony_ci else if (digestsize == SHA384_DIGEST_SIZE) 23348c2ecf20Sopenharmony_ci memcpy(req_ctx->partial_hash, hmacctx->ipad, 23358c2ecf20Sopenharmony_ci SHA512_DIGEST_SIZE); 23368c2ecf20Sopenharmony_ci else 23378c2ecf20Sopenharmony_ci memcpy(req_ctx->partial_hash, hmacctx->ipad, 23388c2ecf20Sopenharmony_ci digestsize); 23398c2ecf20Sopenharmony_ci } 23408c2ecf20Sopenharmony_ci return 0; 23418c2ecf20Sopenharmony_ci} 23428c2ecf20Sopenharmony_ci 23438c2ecf20Sopenharmony_cistatic int chcr_hmac_cra_init(struct crypto_tfm *tfm) 23448c2ecf20Sopenharmony_ci{ 23458c2ecf20Sopenharmony_ci struct chcr_context *ctx = crypto_tfm_ctx(tfm); 23468c2ecf20Sopenharmony_ci struct hmac_ctx *hmacctx = HMAC_CTX(ctx); 23478c2ecf20Sopenharmony_ci unsigned int digestsize = 23488c2ecf20Sopenharmony_ci crypto_ahash_digestsize(__crypto_ahash_cast(tfm)); 23498c2ecf20Sopenharmony_ci 23508c2ecf20Sopenharmony_ci crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), 23518c2ecf20Sopenharmony_ci sizeof(struct chcr_ahash_req_ctx)); 23528c2ecf20Sopenharmony_ci hmacctx->base_hash = chcr_alloc_shash(digestsize); 23538c2ecf20Sopenharmony_ci if (IS_ERR(hmacctx->base_hash)) 23548c2ecf20Sopenharmony_ci return PTR_ERR(hmacctx->base_hash); 23558c2ecf20Sopenharmony_ci return chcr_device_init(crypto_tfm_ctx(tfm)); 23568c2ecf20Sopenharmony_ci} 23578c2ecf20Sopenharmony_ci 23588c2ecf20Sopenharmony_cistatic void chcr_hmac_cra_exit(struct crypto_tfm *tfm) 23598c2ecf20Sopenharmony_ci{ 23608c2ecf20Sopenharmony_ci struct chcr_context *ctx = crypto_tfm_ctx(tfm); 23618c2ecf20Sopenharmony_ci struct hmac_ctx *hmacctx = HMAC_CTX(ctx); 23628c2ecf20Sopenharmony_ci 23638c2ecf20Sopenharmony_ci if (hmacctx->base_hash) { 23648c2ecf20Sopenharmony_ci chcr_free_shash(hmacctx->base_hash); 23658c2ecf20Sopenharmony_ci hmacctx->base_hash = NULL; 23668c2ecf20Sopenharmony_ci } 23678c2ecf20Sopenharmony_ci} 23688c2ecf20Sopenharmony_ci 23698c2ecf20Sopenharmony_ciinline void chcr_aead_common_exit(struct aead_request *req) 23708c2ecf20Sopenharmony_ci{ 23718c2ecf20Sopenharmony_ci struct chcr_aead_reqctx *reqctx = aead_request_ctx(req); 23728c2ecf20Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 23738c2ecf20Sopenharmony_ci struct uld_ctx *u_ctx = ULD_CTX(a_ctx(tfm)); 23748c2ecf20Sopenharmony_ci 23758c2ecf20Sopenharmony_ci chcr_aead_dma_unmap(&u_ctx->lldi.pdev->dev, req, reqctx->op); 23768c2ecf20Sopenharmony_ci} 23778c2ecf20Sopenharmony_ci 23788c2ecf20Sopenharmony_cistatic int chcr_aead_common_init(struct aead_request *req) 23798c2ecf20Sopenharmony_ci{ 23808c2ecf20Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 23818c2ecf20Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm)); 23828c2ecf20Sopenharmony_ci struct chcr_aead_reqctx *reqctx = aead_request_ctx(req); 23838c2ecf20Sopenharmony_ci unsigned int authsize = crypto_aead_authsize(tfm); 23848c2ecf20Sopenharmony_ci int error = -EINVAL; 23858c2ecf20Sopenharmony_ci 23868c2ecf20Sopenharmony_ci /* validate key size */ 23878c2ecf20Sopenharmony_ci if (aeadctx->enckey_len == 0) 23888c2ecf20Sopenharmony_ci goto err; 23898c2ecf20Sopenharmony_ci if (reqctx->op && req->cryptlen < authsize) 23908c2ecf20Sopenharmony_ci goto err; 23918c2ecf20Sopenharmony_ci if (reqctx->b0_len) 23928c2ecf20Sopenharmony_ci reqctx->scratch_pad = reqctx->iv + IV; 23938c2ecf20Sopenharmony_ci else 23948c2ecf20Sopenharmony_ci reqctx->scratch_pad = NULL; 23958c2ecf20Sopenharmony_ci 23968c2ecf20Sopenharmony_ci error = chcr_aead_dma_map(&ULD_CTX(a_ctx(tfm))->lldi.pdev->dev, req, 23978c2ecf20Sopenharmony_ci reqctx->op); 23988c2ecf20Sopenharmony_ci if (error) { 23998c2ecf20Sopenharmony_ci error = -ENOMEM; 24008c2ecf20Sopenharmony_ci goto err; 24018c2ecf20Sopenharmony_ci } 24028c2ecf20Sopenharmony_ci 24038c2ecf20Sopenharmony_ci return 0; 24048c2ecf20Sopenharmony_cierr: 24058c2ecf20Sopenharmony_ci return error; 24068c2ecf20Sopenharmony_ci} 24078c2ecf20Sopenharmony_ci 24088c2ecf20Sopenharmony_cistatic int chcr_aead_need_fallback(struct aead_request *req, int dst_nents, 24098c2ecf20Sopenharmony_ci int aadmax, int wrlen, 24108c2ecf20Sopenharmony_ci unsigned short op_type) 24118c2ecf20Sopenharmony_ci{ 24128c2ecf20Sopenharmony_ci unsigned int authsize = crypto_aead_authsize(crypto_aead_reqtfm(req)); 24138c2ecf20Sopenharmony_ci 24148c2ecf20Sopenharmony_ci if (((req->cryptlen - (op_type ? authsize : 0)) == 0) || 24158c2ecf20Sopenharmony_ci dst_nents > MAX_DSGL_ENT || 24168c2ecf20Sopenharmony_ci (req->assoclen > aadmax) || 24178c2ecf20Sopenharmony_ci (wrlen > SGE_MAX_WR_LEN)) 24188c2ecf20Sopenharmony_ci return 1; 24198c2ecf20Sopenharmony_ci return 0; 24208c2ecf20Sopenharmony_ci} 24218c2ecf20Sopenharmony_ci 24228c2ecf20Sopenharmony_cistatic int chcr_aead_fallback(struct aead_request *req, unsigned short op_type) 24238c2ecf20Sopenharmony_ci{ 24248c2ecf20Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 24258c2ecf20Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm)); 24268c2ecf20Sopenharmony_ci struct aead_request *subreq = aead_request_ctx(req); 24278c2ecf20Sopenharmony_ci 24288c2ecf20Sopenharmony_ci aead_request_set_tfm(subreq, aeadctx->sw_cipher); 24298c2ecf20Sopenharmony_ci aead_request_set_callback(subreq, req->base.flags, 24308c2ecf20Sopenharmony_ci req->base.complete, req->base.data); 24318c2ecf20Sopenharmony_ci aead_request_set_crypt(subreq, req->src, req->dst, req->cryptlen, 24328c2ecf20Sopenharmony_ci req->iv); 24338c2ecf20Sopenharmony_ci aead_request_set_ad(subreq, req->assoclen); 24348c2ecf20Sopenharmony_ci return op_type ? crypto_aead_decrypt(subreq) : 24358c2ecf20Sopenharmony_ci crypto_aead_encrypt(subreq); 24368c2ecf20Sopenharmony_ci} 24378c2ecf20Sopenharmony_ci 24388c2ecf20Sopenharmony_cistatic struct sk_buff *create_authenc_wr(struct aead_request *req, 24398c2ecf20Sopenharmony_ci unsigned short qid, 24408c2ecf20Sopenharmony_ci int size) 24418c2ecf20Sopenharmony_ci{ 24428c2ecf20Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 24438c2ecf20Sopenharmony_ci struct chcr_context *ctx = a_ctx(tfm); 24448c2ecf20Sopenharmony_ci struct uld_ctx *u_ctx = ULD_CTX(ctx); 24458c2ecf20Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(ctx); 24468c2ecf20Sopenharmony_ci struct chcr_authenc_ctx *actx = AUTHENC_CTX(aeadctx); 24478c2ecf20Sopenharmony_ci struct chcr_aead_reqctx *reqctx = aead_request_ctx(req); 24488c2ecf20Sopenharmony_ci struct sk_buff *skb = NULL; 24498c2ecf20Sopenharmony_ci struct chcr_wr *chcr_req; 24508c2ecf20Sopenharmony_ci struct cpl_rx_phys_dsgl *phys_cpl; 24518c2ecf20Sopenharmony_ci struct ulptx_sgl *ulptx; 24528c2ecf20Sopenharmony_ci unsigned int transhdr_len; 24538c2ecf20Sopenharmony_ci unsigned int dst_size = 0, temp, subtype = get_aead_subtype(tfm); 24548c2ecf20Sopenharmony_ci unsigned int kctx_len = 0, dnents, snents; 24558c2ecf20Sopenharmony_ci unsigned int authsize = crypto_aead_authsize(tfm); 24568c2ecf20Sopenharmony_ci int error = -EINVAL; 24578c2ecf20Sopenharmony_ci u8 *ivptr; 24588c2ecf20Sopenharmony_ci int null = 0; 24598c2ecf20Sopenharmony_ci gfp_t flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL : 24608c2ecf20Sopenharmony_ci GFP_ATOMIC; 24618c2ecf20Sopenharmony_ci struct adapter *adap = padap(ctx->dev); 24628c2ecf20Sopenharmony_ci unsigned int rx_channel_id = reqctx->rxqidx / ctx->rxq_perchan; 24638c2ecf20Sopenharmony_ci 24648c2ecf20Sopenharmony_ci rx_channel_id = cxgb4_port_e2cchan(u_ctx->lldi.ports[rx_channel_id]); 24658c2ecf20Sopenharmony_ci if (req->cryptlen == 0) 24668c2ecf20Sopenharmony_ci return NULL; 24678c2ecf20Sopenharmony_ci 24688c2ecf20Sopenharmony_ci reqctx->b0_len = 0; 24698c2ecf20Sopenharmony_ci error = chcr_aead_common_init(req); 24708c2ecf20Sopenharmony_ci if (error) 24718c2ecf20Sopenharmony_ci return ERR_PTR(error); 24728c2ecf20Sopenharmony_ci 24738c2ecf20Sopenharmony_ci if (subtype == CRYPTO_ALG_SUB_TYPE_CBC_NULL || 24748c2ecf20Sopenharmony_ci subtype == CRYPTO_ALG_SUB_TYPE_CTR_NULL) { 24758c2ecf20Sopenharmony_ci null = 1; 24768c2ecf20Sopenharmony_ci } 24778c2ecf20Sopenharmony_ci dnents = sg_nents_xlen(req->dst, req->assoclen + req->cryptlen + 24788c2ecf20Sopenharmony_ci (reqctx->op ? -authsize : authsize), CHCR_DST_SG_SIZE, 0); 24798c2ecf20Sopenharmony_ci dnents += MIN_AUTH_SG; // For IV 24808c2ecf20Sopenharmony_ci snents = sg_nents_xlen(req->src, req->assoclen + req->cryptlen, 24818c2ecf20Sopenharmony_ci CHCR_SRC_SG_SIZE, 0); 24828c2ecf20Sopenharmony_ci dst_size = get_space_for_phys_dsgl(dnents); 24838c2ecf20Sopenharmony_ci kctx_len = (KEY_CONTEXT_CTX_LEN_G(ntohl(aeadctx->key_ctx_hdr)) << 4) 24848c2ecf20Sopenharmony_ci - sizeof(chcr_req->key_ctx); 24858c2ecf20Sopenharmony_ci transhdr_len = CIPHER_TRANSHDR_SIZE(kctx_len, dst_size); 24868c2ecf20Sopenharmony_ci reqctx->imm = (transhdr_len + req->assoclen + req->cryptlen) < 24878c2ecf20Sopenharmony_ci SGE_MAX_WR_LEN; 24888c2ecf20Sopenharmony_ci temp = reqctx->imm ? roundup(req->assoclen + req->cryptlen, 16) 24898c2ecf20Sopenharmony_ci : (sgl_len(snents) * 8); 24908c2ecf20Sopenharmony_ci transhdr_len += temp; 24918c2ecf20Sopenharmony_ci transhdr_len = roundup(transhdr_len, 16); 24928c2ecf20Sopenharmony_ci 24938c2ecf20Sopenharmony_ci if (chcr_aead_need_fallback(req, dnents, T6_MAX_AAD_SIZE, 24948c2ecf20Sopenharmony_ci transhdr_len, reqctx->op)) { 24958c2ecf20Sopenharmony_ci atomic_inc(&adap->chcr_stats.fallback); 24968c2ecf20Sopenharmony_ci chcr_aead_common_exit(req); 24978c2ecf20Sopenharmony_ci return ERR_PTR(chcr_aead_fallback(req, reqctx->op)); 24988c2ecf20Sopenharmony_ci } 24998c2ecf20Sopenharmony_ci skb = alloc_skb(transhdr_len, flags); 25008c2ecf20Sopenharmony_ci if (!skb) { 25018c2ecf20Sopenharmony_ci error = -ENOMEM; 25028c2ecf20Sopenharmony_ci goto err; 25038c2ecf20Sopenharmony_ci } 25048c2ecf20Sopenharmony_ci 25058c2ecf20Sopenharmony_ci chcr_req = __skb_put_zero(skb, transhdr_len); 25068c2ecf20Sopenharmony_ci 25078c2ecf20Sopenharmony_ci temp = (reqctx->op == CHCR_ENCRYPT_OP) ? 0 : authsize; 25088c2ecf20Sopenharmony_ci 25098c2ecf20Sopenharmony_ci /* 25108c2ecf20Sopenharmony_ci * Input order is AAD,IV and Payload. where IV should be included as 25118c2ecf20Sopenharmony_ci * the part of authdata. All other fields should be filled according 25128c2ecf20Sopenharmony_ci * to the hardware spec 25138c2ecf20Sopenharmony_ci */ 25148c2ecf20Sopenharmony_ci chcr_req->sec_cpl.op_ivinsrtofst = 25158c2ecf20Sopenharmony_ci FILL_SEC_CPL_OP_IVINSR(rx_channel_id, 2, 1); 25168c2ecf20Sopenharmony_ci chcr_req->sec_cpl.pldlen = htonl(req->assoclen + IV + req->cryptlen); 25178c2ecf20Sopenharmony_ci chcr_req->sec_cpl.aadstart_cipherstop_hi = FILL_SEC_CPL_CIPHERSTOP_HI( 25188c2ecf20Sopenharmony_ci null ? 0 : 1 + IV, 25198c2ecf20Sopenharmony_ci null ? 0 : IV + req->assoclen, 25208c2ecf20Sopenharmony_ci req->assoclen + IV + 1, 25218c2ecf20Sopenharmony_ci (temp & 0x1F0) >> 4); 25228c2ecf20Sopenharmony_ci chcr_req->sec_cpl.cipherstop_lo_authinsert = FILL_SEC_CPL_AUTHINSERT( 25238c2ecf20Sopenharmony_ci temp & 0xF, 25248c2ecf20Sopenharmony_ci null ? 0 : req->assoclen + IV + 1, 25258c2ecf20Sopenharmony_ci temp, temp); 25268c2ecf20Sopenharmony_ci if (subtype == CRYPTO_ALG_SUB_TYPE_CTR_NULL || 25278c2ecf20Sopenharmony_ci subtype == CRYPTO_ALG_SUB_TYPE_CTR_SHA) 25288c2ecf20Sopenharmony_ci temp = CHCR_SCMD_CIPHER_MODE_AES_CTR; 25298c2ecf20Sopenharmony_ci else 25308c2ecf20Sopenharmony_ci temp = CHCR_SCMD_CIPHER_MODE_AES_CBC; 25318c2ecf20Sopenharmony_ci chcr_req->sec_cpl.seqno_numivs = FILL_SEC_CPL_SCMD0_SEQNO(reqctx->op, 25328c2ecf20Sopenharmony_ci (reqctx->op == CHCR_ENCRYPT_OP) ? 1 : 0, 25338c2ecf20Sopenharmony_ci temp, 25348c2ecf20Sopenharmony_ci actx->auth_mode, aeadctx->hmac_ctrl, 25358c2ecf20Sopenharmony_ci IV >> 1); 25368c2ecf20Sopenharmony_ci chcr_req->sec_cpl.ivgen_hdrlen = FILL_SEC_CPL_IVGEN_HDRLEN(0, 0, 1, 25378c2ecf20Sopenharmony_ci 0, 0, dst_size); 25388c2ecf20Sopenharmony_ci 25398c2ecf20Sopenharmony_ci chcr_req->key_ctx.ctx_hdr = aeadctx->key_ctx_hdr; 25408c2ecf20Sopenharmony_ci if (reqctx->op == CHCR_ENCRYPT_OP || 25418c2ecf20Sopenharmony_ci subtype == CRYPTO_ALG_SUB_TYPE_CTR_SHA || 25428c2ecf20Sopenharmony_ci subtype == CRYPTO_ALG_SUB_TYPE_CTR_NULL) 25438c2ecf20Sopenharmony_ci memcpy(chcr_req->key_ctx.key, aeadctx->key, 25448c2ecf20Sopenharmony_ci aeadctx->enckey_len); 25458c2ecf20Sopenharmony_ci else 25468c2ecf20Sopenharmony_ci memcpy(chcr_req->key_ctx.key, actx->dec_rrkey, 25478c2ecf20Sopenharmony_ci aeadctx->enckey_len); 25488c2ecf20Sopenharmony_ci 25498c2ecf20Sopenharmony_ci memcpy(chcr_req->key_ctx.key + roundup(aeadctx->enckey_len, 16), 25508c2ecf20Sopenharmony_ci actx->h_iopad, kctx_len - roundup(aeadctx->enckey_len, 16)); 25518c2ecf20Sopenharmony_ci phys_cpl = (struct cpl_rx_phys_dsgl *)((u8 *)(chcr_req + 1) + kctx_len); 25528c2ecf20Sopenharmony_ci ivptr = (u8 *)(phys_cpl + 1) + dst_size; 25538c2ecf20Sopenharmony_ci ulptx = (struct ulptx_sgl *)(ivptr + IV); 25548c2ecf20Sopenharmony_ci if (subtype == CRYPTO_ALG_SUB_TYPE_CTR_SHA || 25558c2ecf20Sopenharmony_ci subtype == CRYPTO_ALG_SUB_TYPE_CTR_NULL) { 25568c2ecf20Sopenharmony_ci memcpy(ivptr, aeadctx->nonce, CTR_RFC3686_NONCE_SIZE); 25578c2ecf20Sopenharmony_ci memcpy(ivptr + CTR_RFC3686_NONCE_SIZE, req->iv, 25588c2ecf20Sopenharmony_ci CTR_RFC3686_IV_SIZE); 25598c2ecf20Sopenharmony_ci *(__be32 *)(ivptr + CTR_RFC3686_NONCE_SIZE + 25608c2ecf20Sopenharmony_ci CTR_RFC3686_IV_SIZE) = cpu_to_be32(1); 25618c2ecf20Sopenharmony_ci } else { 25628c2ecf20Sopenharmony_ci memcpy(ivptr, req->iv, IV); 25638c2ecf20Sopenharmony_ci } 25648c2ecf20Sopenharmony_ci chcr_add_aead_dst_ent(req, phys_cpl, qid); 25658c2ecf20Sopenharmony_ci chcr_add_aead_src_ent(req, ulptx); 25668c2ecf20Sopenharmony_ci atomic_inc(&adap->chcr_stats.cipher_rqst); 25678c2ecf20Sopenharmony_ci temp = sizeof(struct cpl_rx_phys_dsgl) + dst_size + IV + 25688c2ecf20Sopenharmony_ci kctx_len + (reqctx->imm ? (req->assoclen + req->cryptlen) : 0); 25698c2ecf20Sopenharmony_ci create_wreq(a_ctx(tfm), chcr_req, &req->base, reqctx->imm, size, 25708c2ecf20Sopenharmony_ci transhdr_len, temp, 0); 25718c2ecf20Sopenharmony_ci reqctx->skb = skb; 25728c2ecf20Sopenharmony_ci 25738c2ecf20Sopenharmony_ci return skb; 25748c2ecf20Sopenharmony_cierr: 25758c2ecf20Sopenharmony_ci chcr_aead_common_exit(req); 25768c2ecf20Sopenharmony_ci 25778c2ecf20Sopenharmony_ci return ERR_PTR(error); 25788c2ecf20Sopenharmony_ci} 25798c2ecf20Sopenharmony_ci 25808c2ecf20Sopenharmony_ciint chcr_aead_dma_map(struct device *dev, 25818c2ecf20Sopenharmony_ci struct aead_request *req, 25828c2ecf20Sopenharmony_ci unsigned short op_type) 25838c2ecf20Sopenharmony_ci{ 25848c2ecf20Sopenharmony_ci int error; 25858c2ecf20Sopenharmony_ci struct chcr_aead_reqctx *reqctx = aead_request_ctx(req); 25868c2ecf20Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 25878c2ecf20Sopenharmony_ci unsigned int authsize = crypto_aead_authsize(tfm); 25888c2ecf20Sopenharmony_ci int src_len, dst_len; 25898c2ecf20Sopenharmony_ci 25908c2ecf20Sopenharmony_ci /* calculate and handle src and dst sg length separately 25918c2ecf20Sopenharmony_ci * for inplace and out-of place operations 25928c2ecf20Sopenharmony_ci */ 25938c2ecf20Sopenharmony_ci if (req->src == req->dst) { 25948c2ecf20Sopenharmony_ci src_len = req->assoclen + req->cryptlen + (op_type ? 25958c2ecf20Sopenharmony_ci 0 : authsize); 25968c2ecf20Sopenharmony_ci dst_len = src_len; 25978c2ecf20Sopenharmony_ci } else { 25988c2ecf20Sopenharmony_ci src_len = req->assoclen + req->cryptlen; 25998c2ecf20Sopenharmony_ci dst_len = req->assoclen + req->cryptlen + (op_type ? 26008c2ecf20Sopenharmony_ci -authsize : authsize); 26018c2ecf20Sopenharmony_ci } 26028c2ecf20Sopenharmony_ci 26038c2ecf20Sopenharmony_ci if (!req->cryptlen || !src_len || !dst_len) 26048c2ecf20Sopenharmony_ci return 0; 26058c2ecf20Sopenharmony_ci reqctx->iv_dma = dma_map_single(dev, reqctx->iv, (IV + reqctx->b0_len), 26068c2ecf20Sopenharmony_ci DMA_BIDIRECTIONAL); 26078c2ecf20Sopenharmony_ci if (dma_mapping_error(dev, reqctx->iv_dma)) 26088c2ecf20Sopenharmony_ci return -ENOMEM; 26098c2ecf20Sopenharmony_ci if (reqctx->b0_len) 26108c2ecf20Sopenharmony_ci reqctx->b0_dma = reqctx->iv_dma + IV; 26118c2ecf20Sopenharmony_ci else 26128c2ecf20Sopenharmony_ci reqctx->b0_dma = 0; 26138c2ecf20Sopenharmony_ci if (req->src == req->dst) { 26148c2ecf20Sopenharmony_ci error = dma_map_sg(dev, req->src, 26158c2ecf20Sopenharmony_ci sg_nents_for_len(req->src, src_len), 26168c2ecf20Sopenharmony_ci DMA_BIDIRECTIONAL); 26178c2ecf20Sopenharmony_ci if (!error) 26188c2ecf20Sopenharmony_ci goto err; 26198c2ecf20Sopenharmony_ci } else { 26208c2ecf20Sopenharmony_ci error = dma_map_sg(dev, req->src, 26218c2ecf20Sopenharmony_ci sg_nents_for_len(req->src, src_len), 26228c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 26238c2ecf20Sopenharmony_ci if (!error) 26248c2ecf20Sopenharmony_ci goto err; 26258c2ecf20Sopenharmony_ci error = dma_map_sg(dev, req->dst, 26268c2ecf20Sopenharmony_ci sg_nents_for_len(req->dst, dst_len), 26278c2ecf20Sopenharmony_ci DMA_FROM_DEVICE); 26288c2ecf20Sopenharmony_ci if (!error) { 26298c2ecf20Sopenharmony_ci dma_unmap_sg(dev, req->src, 26308c2ecf20Sopenharmony_ci sg_nents_for_len(req->src, src_len), 26318c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 26328c2ecf20Sopenharmony_ci goto err; 26338c2ecf20Sopenharmony_ci } 26348c2ecf20Sopenharmony_ci } 26358c2ecf20Sopenharmony_ci 26368c2ecf20Sopenharmony_ci return 0; 26378c2ecf20Sopenharmony_cierr: 26388c2ecf20Sopenharmony_ci dma_unmap_single(dev, reqctx->iv_dma, IV, DMA_BIDIRECTIONAL); 26398c2ecf20Sopenharmony_ci return -ENOMEM; 26408c2ecf20Sopenharmony_ci} 26418c2ecf20Sopenharmony_ci 26428c2ecf20Sopenharmony_civoid chcr_aead_dma_unmap(struct device *dev, 26438c2ecf20Sopenharmony_ci struct aead_request *req, 26448c2ecf20Sopenharmony_ci unsigned short op_type) 26458c2ecf20Sopenharmony_ci{ 26468c2ecf20Sopenharmony_ci struct chcr_aead_reqctx *reqctx = aead_request_ctx(req); 26478c2ecf20Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 26488c2ecf20Sopenharmony_ci unsigned int authsize = crypto_aead_authsize(tfm); 26498c2ecf20Sopenharmony_ci int src_len, dst_len; 26508c2ecf20Sopenharmony_ci 26518c2ecf20Sopenharmony_ci /* calculate and handle src and dst sg length separately 26528c2ecf20Sopenharmony_ci * for inplace and out-of place operations 26538c2ecf20Sopenharmony_ci */ 26548c2ecf20Sopenharmony_ci if (req->src == req->dst) { 26558c2ecf20Sopenharmony_ci src_len = req->assoclen + req->cryptlen + (op_type ? 26568c2ecf20Sopenharmony_ci 0 : authsize); 26578c2ecf20Sopenharmony_ci dst_len = src_len; 26588c2ecf20Sopenharmony_ci } else { 26598c2ecf20Sopenharmony_ci src_len = req->assoclen + req->cryptlen; 26608c2ecf20Sopenharmony_ci dst_len = req->assoclen + req->cryptlen + (op_type ? 26618c2ecf20Sopenharmony_ci -authsize : authsize); 26628c2ecf20Sopenharmony_ci } 26638c2ecf20Sopenharmony_ci 26648c2ecf20Sopenharmony_ci if (!req->cryptlen || !src_len || !dst_len) 26658c2ecf20Sopenharmony_ci return; 26668c2ecf20Sopenharmony_ci 26678c2ecf20Sopenharmony_ci dma_unmap_single(dev, reqctx->iv_dma, (IV + reqctx->b0_len), 26688c2ecf20Sopenharmony_ci DMA_BIDIRECTIONAL); 26698c2ecf20Sopenharmony_ci if (req->src == req->dst) { 26708c2ecf20Sopenharmony_ci dma_unmap_sg(dev, req->src, 26718c2ecf20Sopenharmony_ci sg_nents_for_len(req->src, src_len), 26728c2ecf20Sopenharmony_ci DMA_BIDIRECTIONAL); 26738c2ecf20Sopenharmony_ci } else { 26748c2ecf20Sopenharmony_ci dma_unmap_sg(dev, req->src, 26758c2ecf20Sopenharmony_ci sg_nents_for_len(req->src, src_len), 26768c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 26778c2ecf20Sopenharmony_ci dma_unmap_sg(dev, req->dst, 26788c2ecf20Sopenharmony_ci sg_nents_for_len(req->dst, dst_len), 26798c2ecf20Sopenharmony_ci DMA_FROM_DEVICE); 26808c2ecf20Sopenharmony_ci } 26818c2ecf20Sopenharmony_ci} 26828c2ecf20Sopenharmony_ci 26838c2ecf20Sopenharmony_civoid chcr_add_aead_src_ent(struct aead_request *req, 26848c2ecf20Sopenharmony_ci struct ulptx_sgl *ulptx) 26858c2ecf20Sopenharmony_ci{ 26868c2ecf20Sopenharmony_ci struct ulptx_walk ulp_walk; 26878c2ecf20Sopenharmony_ci struct chcr_aead_reqctx *reqctx = aead_request_ctx(req); 26888c2ecf20Sopenharmony_ci 26898c2ecf20Sopenharmony_ci if (reqctx->imm) { 26908c2ecf20Sopenharmony_ci u8 *buf = (u8 *)ulptx; 26918c2ecf20Sopenharmony_ci 26928c2ecf20Sopenharmony_ci if (reqctx->b0_len) { 26938c2ecf20Sopenharmony_ci memcpy(buf, reqctx->scratch_pad, reqctx->b0_len); 26948c2ecf20Sopenharmony_ci buf += reqctx->b0_len; 26958c2ecf20Sopenharmony_ci } 26968c2ecf20Sopenharmony_ci sg_pcopy_to_buffer(req->src, sg_nents(req->src), 26978c2ecf20Sopenharmony_ci buf, req->cryptlen + req->assoclen, 0); 26988c2ecf20Sopenharmony_ci } else { 26998c2ecf20Sopenharmony_ci ulptx_walk_init(&ulp_walk, ulptx); 27008c2ecf20Sopenharmony_ci if (reqctx->b0_len) 27018c2ecf20Sopenharmony_ci ulptx_walk_add_page(&ulp_walk, reqctx->b0_len, 27028c2ecf20Sopenharmony_ci reqctx->b0_dma); 27038c2ecf20Sopenharmony_ci ulptx_walk_add_sg(&ulp_walk, req->src, req->cryptlen + 27048c2ecf20Sopenharmony_ci req->assoclen, 0); 27058c2ecf20Sopenharmony_ci ulptx_walk_end(&ulp_walk); 27068c2ecf20Sopenharmony_ci } 27078c2ecf20Sopenharmony_ci} 27088c2ecf20Sopenharmony_ci 27098c2ecf20Sopenharmony_civoid chcr_add_aead_dst_ent(struct aead_request *req, 27108c2ecf20Sopenharmony_ci struct cpl_rx_phys_dsgl *phys_cpl, 27118c2ecf20Sopenharmony_ci unsigned short qid) 27128c2ecf20Sopenharmony_ci{ 27138c2ecf20Sopenharmony_ci struct chcr_aead_reqctx *reqctx = aead_request_ctx(req); 27148c2ecf20Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 27158c2ecf20Sopenharmony_ci struct dsgl_walk dsgl_walk; 27168c2ecf20Sopenharmony_ci unsigned int authsize = crypto_aead_authsize(tfm); 27178c2ecf20Sopenharmony_ci struct chcr_context *ctx = a_ctx(tfm); 27188c2ecf20Sopenharmony_ci struct uld_ctx *u_ctx = ULD_CTX(ctx); 27198c2ecf20Sopenharmony_ci u32 temp; 27208c2ecf20Sopenharmony_ci unsigned int rx_channel_id = reqctx->rxqidx / ctx->rxq_perchan; 27218c2ecf20Sopenharmony_ci 27228c2ecf20Sopenharmony_ci rx_channel_id = cxgb4_port_e2cchan(u_ctx->lldi.ports[rx_channel_id]); 27238c2ecf20Sopenharmony_ci dsgl_walk_init(&dsgl_walk, phys_cpl); 27248c2ecf20Sopenharmony_ci dsgl_walk_add_page(&dsgl_walk, IV + reqctx->b0_len, reqctx->iv_dma); 27258c2ecf20Sopenharmony_ci temp = req->assoclen + req->cryptlen + 27268c2ecf20Sopenharmony_ci (reqctx->op ? -authsize : authsize); 27278c2ecf20Sopenharmony_ci dsgl_walk_add_sg(&dsgl_walk, req->dst, temp, 0); 27288c2ecf20Sopenharmony_ci dsgl_walk_end(&dsgl_walk, qid, rx_channel_id); 27298c2ecf20Sopenharmony_ci} 27308c2ecf20Sopenharmony_ci 27318c2ecf20Sopenharmony_civoid chcr_add_cipher_src_ent(struct skcipher_request *req, 27328c2ecf20Sopenharmony_ci void *ulptx, 27338c2ecf20Sopenharmony_ci struct cipher_wr_param *wrparam) 27348c2ecf20Sopenharmony_ci{ 27358c2ecf20Sopenharmony_ci struct ulptx_walk ulp_walk; 27368c2ecf20Sopenharmony_ci struct chcr_skcipher_req_ctx *reqctx = skcipher_request_ctx(req); 27378c2ecf20Sopenharmony_ci u8 *buf = ulptx; 27388c2ecf20Sopenharmony_ci 27398c2ecf20Sopenharmony_ci memcpy(buf, reqctx->iv, IV); 27408c2ecf20Sopenharmony_ci buf += IV; 27418c2ecf20Sopenharmony_ci if (reqctx->imm) { 27428c2ecf20Sopenharmony_ci sg_pcopy_to_buffer(req->src, sg_nents(req->src), 27438c2ecf20Sopenharmony_ci buf, wrparam->bytes, reqctx->processed); 27448c2ecf20Sopenharmony_ci } else { 27458c2ecf20Sopenharmony_ci ulptx_walk_init(&ulp_walk, (struct ulptx_sgl *)buf); 27468c2ecf20Sopenharmony_ci ulptx_walk_add_sg(&ulp_walk, reqctx->srcsg, wrparam->bytes, 27478c2ecf20Sopenharmony_ci reqctx->src_ofst); 27488c2ecf20Sopenharmony_ci reqctx->srcsg = ulp_walk.last_sg; 27498c2ecf20Sopenharmony_ci reqctx->src_ofst = ulp_walk.last_sg_len; 27508c2ecf20Sopenharmony_ci ulptx_walk_end(&ulp_walk); 27518c2ecf20Sopenharmony_ci } 27528c2ecf20Sopenharmony_ci} 27538c2ecf20Sopenharmony_ci 27548c2ecf20Sopenharmony_civoid chcr_add_cipher_dst_ent(struct skcipher_request *req, 27558c2ecf20Sopenharmony_ci struct cpl_rx_phys_dsgl *phys_cpl, 27568c2ecf20Sopenharmony_ci struct cipher_wr_param *wrparam, 27578c2ecf20Sopenharmony_ci unsigned short qid) 27588c2ecf20Sopenharmony_ci{ 27598c2ecf20Sopenharmony_ci struct chcr_skcipher_req_ctx *reqctx = skcipher_request_ctx(req); 27608c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(wrparam->req); 27618c2ecf20Sopenharmony_ci struct chcr_context *ctx = c_ctx(tfm); 27628c2ecf20Sopenharmony_ci struct uld_ctx *u_ctx = ULD_CTX(ctx); 27638c2ecf20Sopenharmony_ci struct dsgl_walk dsgl_walk; 27648c2ecf20Sopenharmony_ci unsigned int rx_channel_id = reqctx->rxqidx / ctx->rxq_perchan; 27658c2ecf20Sopenharmony_ci 27668c2ecf20Sopenharmony_ci rx_channel_id = cxgb4_port_e2cchan(u_ctx->lldi.ports[rx_channel_id]); 27678c2ecf20Sopenharmony_ci dsgl_walk_init(&dsgl_walk, phys_cpl); 27688c2ecf20Sopenharmony_ci dsgl_walk_add_sg(&dsgl_walk, reqctx->dstsg, wrparam->bytes, 27698c2ecf20Sopenharmony_ci reqctx->dst_ofst); 27708c2ecf20Sopenharmony_ci reqctx->dstsg = dsgl_walk.last_sg; 27718c2ecf20Sopenharmony_ci reqctx->dst_ofst = dsgl_walk.last_sg_len; 27728c2ecf20Sopenharmony_ci dsgl_walk_end(&dsgl_walk, qid, rx_channel_id); 27738c2ecf20Sopenharmony_ci} 27748c2ecf20Sopenharmony_ci 27758c2ecf20Sopenharmony_civoid chcr_add_hash_src_ent(struct ahash_request *req, 27768c2ecf20Sopenharmony_ci struct ulptx_sgl *ulptx, 27778c2ecf20Sopenharmony_ci struct hash_wr_param *param) 27788c2ecf20Sopenharmony_ci{ 27798c2ecf20Sopenharmony_ci struct ulptx_walk ulp_walk; 27808c2ecf20Sopenharmony_ci struct chcr_ahash_req_ctx *reqctx = ahash_request_ctx(req); 27818c2ecf20Sopenharmony_ci 27828c2ecf20Sopenharmony_ci if (reqctx->hctx_wr.imm) { 27838c2ecf20Sopenharmony_ci u8 *buf = (u8 *)ulptx; 27848c2ecf20Sopenharmony_ci 27858c2ecf20Sopenharmony_ci if (param->bfr_len) { 27868c2ecf20Sopenharmony_ci memcpy(buf, reqctx->reqbfr, param->bfr_len); 27878c2ecf20Sopenharmony_ci buf += param->bfr_len; 27888c2ecf20Sopenharmony_ci } 27898c2ecf20Sopenharmony_ci 27908c2ecf20Sopenharmony_ci sg_pcopy_to_buffer(reqctx->hctx_wr.srcsg, 27918c2ecf20Sopenharmony_ci sg_nents(reqctx->hctx_wr.srcsg), buf, 27928c2ecf20Sopenharmony_ci param->sg_len, 0); 27938c2ecf20Sopenharmony_ci } else { 27948c2ecf20Sopenharmony_ci ulptx_walk_init(&ulp_walk, ulptx); 27958c2ecf20Sopenharmony_ci if (param->bfr_len) 27968c2ecf20Sopenharmony_ci ulptx_walk_add_page(&ulp_walk, param->bfr_len, 27978c2ecf20Sopenharmony_ci reqctx->hctx_wr.dma_addr); 27988c2ecf20Sopenharmony_ci ulptx_walk_add_sg(&ulp_walk, reqctx->hctx_wr.srcsg, 27998c2ecf20Sopenharmony_ci param->sg_len, reqctx->hctx_wr.src_ofst); 28008c2ecf20Sopenharmony_ci reqctx->hctx_wr.srcsg = ulp_walk.last_sg; 28018c2ecf20Sopenharmony_ci reqctx->hctx_wr.src_ofst = ulp_walk.last_sg_len; 28028c2ecf20Sopenharmony_ci ulptx_walk_end(&ulp_walk); 28038c2ecf20Sopenharmony_ci } 28048c2ecf20Sopenharmony_ci} 28058c2ecf20Sopenharmony_ci 28068c2ecf20Sopenharmony_ciint chcr_hash_dma_map(struct device *dev, 28078c2ecf20Sopenharmony_ci struct ahash_request *req) 28088c2ecf20Sopenharmony_ci{ 28098c2ecf20Sopenharmony_ci struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(req); 28108c2ecf20Sopenharmony_ci int error = 0; 28118c2ecf20Sopenharmony_ci 28128c2ecf20Sopenharmony_ci if (!req->nbytes) 28138c2ecf20Sopenharmony_ci return 0; 28148c2ecf20Sopenharmony_ci error = dma_map_sg(dev, req->src, sg_nents(req->src), 28158c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 28168c2ecf20Sopenharmony_ci if (!error) 28178c2ecf20Sopenharmony_ci return -ENOMEM; 28188c2ecf20Sopenharmony_ci req_ctx->hctx_wr.is_sg_map = 1; 28198c2ecf20Sopenharmony_ci return 0; 28208c2ecf20Sopenharmony_ci} 28218c2ecf20Sopenharmony_ci 28228c2ecf20Sopenharmony_civoid chcr_hash_dma_unmap(struct device *dev, 28238c2ecf20Sopenharmony_ci struct ahash_request *req) 28248c2ecf20Sopenharmony_ci{ 28258c2ecf20Sopenharmony_ci struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(req); 28268c2ecf20Sopenharmony_ci 28278c2ecf20Sopenharmony_ci if (!req->nbytes) 28288c2ecf20Sopenharmony_ci return; 28298c2ecf20Sopenharmony_ci 28308c2ecf20Sopenharmony_ci dma_unmap_sg(dev, req->src, sg_nents(req->src), 28318c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 28328c2ecf20Sopenharmony_ci req_ctx->hctx_wr.is_sg_map = 0; 28338c2ecf20Sopenharmony_ci 28348c2ecf20Sopenharmony_ci} 28358c2ecf20Sopenharmony_ci 28368c2ecf20Sopenharmony_ciint chcr_cipher_dma_map(struct device *dev, 28378c2ecf20Sopenharmony_ci struct skcipher_request *req) 28388c2ecf20Sopenharmony_ci{ 28398c2ecf20Sopenharmony_ci int error; 28408c2ecf20Sopenharmony_ci 28418c2ecf20Sopenharmony_ci if (req->src == req->dst) { 28428c2ecf20Sopenharmony_ci error = dma_map_sg(dev, req->src, sg_nents(req->src), 28438c2ecf20Sopenharmony_ci DMA_BIDIRECTIONAL); 28448c2ecf20Sopenharmony_ci if (!error) 28458c2ecf20Sopenharmony_ci goto err; 28468c2ecf20Sopenharmony_ci } else { 28478c2ecf20Sopenharmony_ci error = dma_map_sg(dev, req->src, sg_nents(req->src), 28488c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 28498c2ecf20Sopenharmony_ci if (!error) 28508c2ecf20Sopenharmony_ci goto err; 28518c2ecf20Sopenharmony_ci error = dma_map_sg(dev, req->dst, sg_nents(req->dst), 28528c2ecf20Sopenharmony_ci DMA_FROM_DEVICE); 28538c2ecf20Sopenharmony_ci if (!error) { 28548c2ecf20Sopenharmony_ci dma_unmap_sg(dev, req->src, sg_nents(req->src), 28558c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 28568c2ecf20Sopenharmony_ci goto err; 28578c2ecf20Sopenharmony_ci } 28588c2ecf20Sopenharmony_ci } 28598c2ecf20Sopenharmony_ci 28608c2ecf20Sopenharmony_ci return 0; 28618c2ecf20Sopenharmony_cierr: 28628c2ecf20Sopenharmony_ci return -ENOMEM; 28638c2ecf20Sopenharmony_ci} 28648c2ecf20Sopenharmony_ci 28658c2ecf20Sopenharmony_civoid chcr_cipher_dma_unmap(struct device *dev, 28668c2ecf20Sopenharmony_ci struct skcipher_request *req) 28678c2ecf20Sopenharmony_ci{ 28688c2ecf20Sopenharmony_ci if (req->src == req->dst) { 28698c2ecf20Sopenharmony_ci dma_unmap_sg(dev, req->src, sg_nents(req->src), 28708c2ecf20Sopenharmony_ci DMA_BIDIRECTIONAL); 28718c2ecf20Sopenharmony_ci } else { 28728c2ecf20Sopenharmony_ci dma_unmap_sg(dev, req->src, sg_nents(req->src), 28738c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 28748c2ecf20Sopenharmony_ci dma_unmap_sg(dev, req->dst, sg_nents(req->dst), 28758c2ecf20Sopenharmony_ci DMA_FROM_DEVICE); 28768c2ecf20Sopenharmony_ci } 28778c2ecf20Sopenharmony_ci} 28788c2ecf20Sopenharmony_ci 28798c2ecf20Sopenharmony_cistatic int set_msg_len(u8 *block, unsigned int msglen, int csize) 28808c2ecf20Sopenharmony_ci{ 28818c2ecf20Sopenharmony_ci __be32 data; 28828c2ecf20Sopenharmony_ci 28838c2ecf20Sopenharmony_ci memset(block, 0, csize); 28848c2ecf20Sopenharmony_ci block += csize; 28858c2ecf20Sopenharmony_ci 28868c2ecf20Sopenharmony_ci if (csize >= 4) 28878c2ecf20Sopenharmony_ci csize = 4; 28888c2ecf20Sopenharmony_ci else if (msglen > (unsigned int)(1 << (8 * csize))) 28898c2ecf20Sopenharmony_ci return -EOVERFLOW; 28908c2ecf20Sopenharmony_ci 28918c2ecf20Sopenharmony_ci data = cpu_to_be32(msglen); 28928c2ecf20Sopenharmony_ci memcpy(block - csize, (u8 *)&data + 4 - csize, csize); 28938c2ecf20Sopenharmony_ci 28948c2ecf20Sopenharmony_ci return 0; 28958c2ecf20Sopenharmony_ci} 28968c2ecf20Sopenharmony_ci 28978c2ecf20Sopenharmony_cistatic int generate_b0(struct aead_request *req, u8 *ivptr, 28988c2ecf20Sopenharmony_ci unsigned short op_type) 28998c2ecf20Sopenharmony_ci{ 29008c2ecf20Sopenharmony_ci unsigned int l, lp, m; 29018c2ecf20Sopenharmony_ci int rc; 29028c2ecf20Sopenharmony_ci struct crypto_aead *aead = crypto_aead_reqtfm(req); 29038c2ecf20Sopenharmony_ci struct chcr_aead_reqctx *reqctx = aead_request_ctx(req); 29048c2ecf20Sopenharmony_ci u8 *b0 = reqctx->scratch_pad; 29058c2ecf20Sopenharmony_ci 29068c2ecf20Sopenharmony_ci m = crypto_aead_authsize(aead); 29078c2ecf20Sopenharmony_ci 29088c2ecf20Sopenharmony_ci memcpy(b0, ivptr, 16); 29098c2ecf20Sopenharmony_ci 29108c2ecf20Sopenharmony_ci lp = b0[0]; 29118c2ecf20Sopenharmony_ci l = lp + 1; 29128c2ecf20Sopenharmony_ci 29138c2ecf20Sopenharmony_ci /* set m, bits 3-5 */ 29148c2ecf20Sopenharmony_ci *b0 |= (8 * ((m - 2) / 2)); 29158c2ecf20Sopenharmony_ci 29168c2ecf20Sopenharmony_ci /* set adata, bit 6, if associated data is used */ 29178c2ecf20Sopenharmony_ci if (req->assoclen) 29188c2ecf20Sopenharmony_ci *b0 |= 64; 29198c2ecf20Sopenharmony_ci rc = set_msg_len(b0 + 16 - l, 29208c2ecf20Sopenharmony_ci (op_type == CHCR_DECRYPT_OP) ? 29218c2ecf20Sopenharmony_ci req->cryptlen - m : req->cryptlen, l); 29228c2ecf20Sopenharmony_ci 29238c2ecf20Sopenharmony_ci return rc; 29248c2ecf20Sopenharmony_ci} 29258c2ecf20Sopenharmony_ci 29268c2ecf20Sopenharmony_cistatic inline int crypto_ccm_check_iv(const u8 *iv) 29278c2ecf20Sopenharmony_ci{ 29288c2ecf20Sopenharmony_ci /* 2 <= L <= 8, so 1 <= L' <= 7. */ 29298c2ecf20Sopenharmony_ci if (iv[0] < 1 || iv[0] > 7) 29308c2ecf20Sopenharmony_ci return -EINVAL; 29318c2ecf20Sopenharmony_ci 29328c2ecf20Sopenharmony_ci return 0; 29338c2ecf20Sopenharmony_ci} 29348c2ecf20Sopenharmony_ci 29358c2ecf20Sopenharmony_cistatic int ccm_format_packet(struct aead_request *req, 29368c2ecf20Sopenharmony_ci u8 *ivptr, 29378c2ecf20Sopenharmony_ci unsigned int sub_type, 29388c2ecf20Sopenharmony_ci unsigned short op_type, 29398c2ecf20Sopenharmony_ci unsigned int assoclen) 29408c2ecf20Sopenharmony_ci{ 29418c2ecf20Sopenharmony_ci struct chcr_aead_reqctx *reqctx = aead_request_ctx(req); 29428c2ecf20Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 29438c2ecf20Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm)); 29448c2ecf20Sopenharmony_ci int rc = 0; 29458c2ecf20Sopenharmony_ci 29468c2ecf20Sopenharmony_ci if (sub_type == CRYPTO_ALG_SUB_TYPE_AEAD_RFC4309) { 29478c2ecf20Sopenharmony_ci ivptr[0] = 3; 29488c2ecf20Sopenharmony_ci memcpy(ivptr + 1, &aeadctx->salt[0], 3); 29498c2ecf20Sopenharmony_ci memcpy(ivptr + 4, req->iv, 8); 29508c2ecf20Sopenharmony_ci memset(ivptr + 12, 0, 4); 29518c2ecf20Sopenharmony_ci } else { 29528c2ecf20Sopenharmony_ci memcpy(ivptr, req->iv, 16); 29538c2ecf20Sopenharmony_ci } 29548c2ecf20Sopenharmony_ci if (assoclen) 29558c2ecf20Sopenharmony_ci put_unaligned_be16(assoclen, &reqctx->scratch_pad[16]); 29568c2ecf20Sopenharmony_ci 29578c2ecf20Sopenharmony_ci rc = generate_b0(req, ivptr, op_type); 29588c2ecf20Sopenharmony_ci /* zero the ctr value */ 29598c2ecf20Sopenharmony_ci memset(ivptr + 15 - ivptr[0], 0, ivptr[0] + 1); 29608c2ecf20Sopenharmony_ci return rc; 29618c2ecf20Sopenharmony_ci} 29628c2ecf20Sopenharmony_ci 29638c2ecf20Sopenharmony_cistatic void fill_sec_cpl_for_aead(struct cpl_tx_sec_pdu *sec_cpl, 29648c2ecf20Sopenharmony_ci unsigned int dst_size, 29658c2ecf20Sopenharmony_ci struct aead_request *req, 29668c2ecf20Sopenharmony_ci unsigned short op_type) 29678c2ecf20Sopenharmony_ci{ 29688c2ecf20Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 29698c2ecf20Sopenharmony_ci struct chcr_context *ctx = a_ctx(tfm); 29708c2ecf20Sopenharmony_ci struct uld_ctx *u_ctx = ULD_CTX(ctx); 29718c2ecf20Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(ctx); 29728c2ecf20Sopenharmony_ci struct chcr_aead_reqctx *reqctx = aead_request_ctx(req); 29738c2ecf20Sopenharmony_ci unsigned int cipher_mode = CHCR_SCMD_CIPHER_MODE_AES_CCM; 29748c2ecf20Sopenharmony_ci unsigned int mac_mode = CHCR_SCMD_AUTH_MODE_CBCMAC; 29758c2ecf20Sopenharmony_ci unsigned int rx_channel_id = reqctx->rxqidx / ctx->rxq_perchan; 29768c2ecf20Sopenharmony_ci unsigned int ccm_xtra; 29778c2ecf20Sopenharmony_ci unsigned int tag_offset = 0, auth_offset = 0; 29788c2ecf20Sopenharmony_ci unsigned int assoclen; 29798c2ecf20Sopenharmony_ci 29808c2ecf20Sopenharmony_ci rx_channel_id = cxgb4_port_e2cchan(u_ctx->lldi.ports[rx_channel_id]); 29818c2ecf20Sopenharmony_ci 29828c2ecf20Sopenharmony_ci if (get_aead_subtype(tfm) == CRYPTO_ALG_SUB_TYPE_AEAD_RFC4309) 29838c2ecf20Sopenharmony_ci assoclen = req->assoclen - 8; 29848c2ecf20Sopenharmony_ci else 29858c2ecf20Sopenharmony_ci assoclen = req->assoclen; 29868c2ecf20Sopenharmony_ci ccm_xtra = CCM_B0_SIZE + 29878c2ecf20Sopenharmony_ci ((assoclen) ? CCM_AAD_FIELD_SIZE : 0); 29888c2ecf20Sopenharmony_ci 29898c2ecf20Sopenharmony_ci auth_offset = req->cryptlen ? 29908c2ecf20Sopenharmony_ci (req->assoclen + IV + 1 + ccm_xtra) : 0; 29918c2ecf20Sopenharmony_ci if (op_type == CHCR_DECRYPT_OP) { 29928c2ecf20Sopenharmony_ci if (crypto_aead_authsize(tfm) != req->cryptlen) 29938c2ecf20Sopenharmony_ci tag_offset = crypto_aead_authsize(tfm); 29948c2ecf20Sopenharmony_ci else 29958c2ecf20Sopenharmony_ci auth_offset = 0; 29968c2ecf20Sopenharmony_ci } 29978c2ecf20Sopenharmony_ci 29988c2ecf20Sopenharmony_ci sec_cpl->op_ivinsrtofst = FILL_SEC_CPL_OP_IVINSR(rx_channel_id, 2, 1); 29998c2ecf20Sopenharmony_ci sec_cpl->pldlen = 30008c2ecf20Sopenharmony_ci htonl(req->assoclen + IV + req->cryptlen + ccm_xtra); 30018c2ecf20Sopenharmony_ci /* For CCM there wil be b0 always. So AAD start will be 1 always */ 30028c2ecf20Sopenharmony_ci sec_cpl->aadstart_cipherstop_hi = FILL_SEC_CPL_CIPHERSTOP_HI( 30038c2ecf20Sopenharmony_ci 1 + IV, IV + assoclen + ccm_xtra, 30048c2ecf20Sopenharmony_ci req->assoclen + IV + 1 + ccm_xtra, 0); 30058c2ecf20Sopenharmony_ci 30068c2ecf20Sopenharmony_ci sec_cpl->cipherstop_lo_authinsert = FILL_SEC_CPL_AUTHINSERT(0, 30078c2ecf20Sopenharmony_ci auth_offset, tag_offset, 30088c2ecf20Sopenharmony_ci (op_type == CHCR_ENCRYPT_OP) ? 0 : 30098c2ecf20Sopenharmony_ci crypto_aead_authsize(tfm)); 30108c2ecf20Sopenharmony_ci sec_cpl->seqno_numivs = FILL_SEC_CPL_SCMD0_SEQNO(op_type, 30118c2ecf20Sopenharmony_ci (op_type == CHCR_ENCRYPT_OP) ? 0 : 1, 30128c2ecf20Sopenharmony_ci cipher_mode, mac_mode, 30138c2ecf20Sopenharmony_ci aeadctx->hmac_ctrl, IV >> 1); 30148c2ecf20Sopenharmony_ci 30158c2ecf20Sopenharmony_ci sec_cpl->ivgen_hdrlen = FILL_SEC_CPL_IVGEN_HDRLEN(0, 0, 1, 0, 30168c2ecf20Sopenharmony_ci 0, dst_size); 30178c2ecf20Sopenharmony_ci} 30188c2ecf20Sopenharmony_ci 30198c2ecf20Sopenharmony_cistatic int aead_ccm_validate_input(unsigned short op_type, 30208c2ecf20Sopenharmony_ci struct aead_request *req, 30218c2ecf20Sopenharmony_ci struct chcr_aead_ctx *aeadctx, 30228c2ecf20Sopenharmony_ci unsigned int sub_type) 30238c2ecf20Sopenharmony_ci{ 30248c2ecf20Sopenharmony_ci if (sub_type != CRYPTO_ALG_SUB_TYPE_AEAD_RFC4309) { 30258c2ecf20Sopenharmony_ci if (crypto_ccm_check_iv(req->iv)) { 30268c2ecf20Sopenharmony_ci pr_err("CCM: IV check fails\n"); 30278c2ecf20Sopenharmony_ci return -EINVAL; 30288c2ecf20Sopenharmony_ci } 30298c2ecf20Sopenharmony_ci } else { 30308c2ecf20Sopenharmony_ci if (req->assoclen != 16 && req->assoclen != 20) { 30318c2ecf20Sopenharmony_ci pr_err("RFC4309: Invalid AAD length %d\n", 30328c2ecf20Sopenharmony_ci req->assoclen); 30338c2ecf20Sopenharmony_ci return -EINVAL; 30348c2ecf20Sopenharmony_ci } 30358c2ecf20Sopenharmony_ci } 30368c2ecf20Sopenharmony_ci return 0; 30378c2ecf20Sopenharmony_ci} 30388c2ecf20Sopenharmony_ci 30398c2ecf20Sopenharmony_cistatic struct sk_buff *create_aead_ccm_wr(struct aead_request *req, 30408c2ecf20Sopenharmony_ci unsigned short qid, 30418c2ecf20Sopenharmony_ci int size) 30428c2ecf20Sopenharmony_ci{ 30438c2ecf20Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 30448c2ecf20Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm)); 30458c2ecf20Sopenharmony_ci struct chcr_aead_reqctx *reqctx = aead_request_ctx(req); 30468c2ecf20Sopenharmony_ci struct sk_buff *skb = NULL; 30478c2ecf20Sopenharmony_ci struct chcr_wr *chcr_req; 30488c2ecf20Sopenharmony_ci struct cpl_rx_phys_dsgl *phys_cpl; 30498c2ecf20Sopenharmony_ci struct ulptx_sgl *ulptx; 30508c2ecf20Sopenharmony_ci unsigned int transhdr_len; 30518c2ecf20Sopenharmony_ci unsigned int dst_size = 0, kctx_len, dnents, temp, snents; 30528c2ecf20Sopenharmony_ci unsigned int sub_type, assoclen = req->assoclen; 30538c2ecf20Sopenharmony_ci unsigned int authsize = crypto_aead_authsize(tfm); 30548c2ecf20Sopenharmony_ci int error = -EINVAL; 30558c2ecf20Sopenharmony_ci u8 *ivptr; 30568c2ecf20Sopenharmony_ci gfp_t flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL : 30578c2ecf20Sopenharmony_ci GFP_ATOMIC; 30588c2ecf20Sopenharmony_ci struct adapter *adap = padap(a_ctx(tfm)->dev); 30598c2ecf20Sopenharmony_ci 30608c2ecf20Sopenharmony_ci sub_type = get_aead_subtype(tfm); 30618c2ecf20Sopenharmony_ci if (sub_type == CRYPTO_ALG_SUB_TYPE_AEAD_RFC4309) 30628c2ecf20Sopenharmony_ci assoclen -= 8; 30638c2ecf20Sopenharmony_ci reqctx->b0_len = CCM_B0_SIZE + (assoclen ? CCM_AAD_FIELD_SIZE : 0); 30648c2ecf20Sopenharmony_ci error = chcr_aead_common_init(req); 30658c2ecf20Sopenharmony_ci if (error) 30668c2ecf20Sopenharmony_ci return ERR_PTR(error); 30678c2ecf20Sopenharmony_ci 30688c2ecf20Sopenharmony_ci error = aead_ccm_validate_input(reqctx->op, req, aeadctx, sub_type); 30698c2ecf20Sopenharmony_ci if (error) 30708c2ecf20Sopenharmony_ci goto err; 30718c2ecf20Sopenharmony_ci dnents = sg_nents_xlen(req->dst, req->assoclen + req->cryptlen 30728c2ecf20Sopenharmony_ci + (reqctx->op ? -authsize : authsize), 30738c2ecf20Sopenharmony_ci CHCR_DST_SG_SIZE, 0); 30748c2ecf20Sopenharmony_ci dnents += MIN_CCM_SG; // For IV and B0 30758c2ecf20Sopenharmony_ci dst_size = get_space_for_phys_dsgl(dnents); 30768c2ecf20Sopenharmony_ci snents = sg_nents_xlen(req->src, req->assoclen + req->cryptlen, 30778c2ecf20Sopenharmony_ci CHCR_SRC_SG_SIZE, 0); 30788c2ecf20Sopenharmony_ci snents += MIN_CCM_SG; //For B0 30798c2ecf20Sopenharmony_ci kctx_len = roundup(aeadctx->enckey_len, 16) * 2; 30808c2ecf20Sopenharmony_ci transhdr_len = CIPHER_TRANSHDR_SIZE(kctx_len, dst_size); 30818c2ecf20Sopenharmony_ci reqctx->imm = (transhdr_len + req->assoclen + req->cryptlen + 30828c2ecf20Sopenharmony_ci reqctx->b0_len) <= SGE_MAX_WR_LEN; 30838c2ecf20Sopenharmony_ci temp = reqctx->imm ? roundup(req->assoclen + req->cryptlen + 30848c2ecf20Sopenharmony_ci reqctx->b0_len, 16) : 30858c2ecf20Sopenharmony_ci (sgl_len(snents) * 8); 30868c2ecf20Sopenharmony_ci transhdr_len += temp; 30878c2ecf20Sopenharmony_ci transhdr_len = roundup(transhdr_len, 16); 30888c2ecf20Sopenharmony_ci 30898c2ecf20Sopenharmony_ci if (chcr_aead_need_fallback(req, dnents, T6_MAX_AAD_SIZE - 30908c2ecf20Sopenharmony_ci reqctx->b0_len, transhdr_len, reqctx->op)) { 30918c2ecf20Sopenharmony_ci atomic_inc(&adap->chcr_stats.fallback); 30928c2ecf20Sopenharmony_ci chcr_aead_common_exit(req); 30938c2ecf20Sopenharmony_ci return ERR_PTR(chcr_aead_fallback(req, reqctx->op)); 30948c2ecf20Sopenharmony_ci } 30958c2ecf20Sopenharmony_ci skb = alloc_skb(transhdr_len, flags); 30968c2ecf20Sopenharmony_ci 30978c2ecf20Sopenharmony_ci if (!skb) { 30988c2ecf20Sopenharmony_ci error = -ENOMEM; 30998c2ecf20Sopenharmony_ci goto err; 31008c2ecf20Sopenharmony_ci } 31018c2ecf20Sopenharmony_ci 31028c2ecf20Sopenharmony_ci chcr_req = __skb_put_zero(skb, transhdr_len); 31038c2ecf20Sopenharmony_ci 31048c2ecf20Sopenharmony_ci fill_sec_cpl_for_aead(&chcr_req->sec_cpl, dst_size, req, reqctx->op); 31058c2ecf20Sopenharmony_ci 31068c2ecf20Sopenharmony_ci chcr_req->key_ctx.ctx_hdr = aeadctx->key_ctx_hdr; 31078c2ecf20Sopenharmony_ci memcpy(chcr_req->key_ctx.key, aeadctx->key, aeadctx->enckey_len); 31088c2ecf20Sopenharmony_ci memcpy(chcr_req->key_ctx.key + roundup(aeadctx->enckey_len, 16), 31098c2ecf20Sopenharmony_ci aeadctx->key, aeadctx->enckey_len); 31108c2ecf20Sopenharmony_ci 31118c2ecf20Sopenharmony_ci phys_cpl = (struct cpl_rx_phys_dsgl *)((u8 *)(chcr_req + 1) + kctx_len); 31128c2ecf20Sopenharmony_ci ivptr = (u8 *)(phys_cpl + 1) + dst_size; 31138c2ecf20Sopenharmony_ci ulptx = (struct ulptx_sgl *)(ivptr + IV); 31148c2ecf20Sopenharmony_ci error = ccm_format_packet(req, ivptr, sub_type, reqctx->op, assoclen); 31158c2ecf20Sopenharmony_ci if (error) 31168c2ecf20Sopenharmony_ci goto dstmap_fail; 31178c2ecf20Sopenharmony_ci chcr_add_aead_dst_ent(req, phys_cpl, qid); 31188c2ecf20Sopenharmony_ci chcr_add_aead_src_ent(req, ulptx); 31198c2ecf20Sopenharmony_ci 31208c2ecf20Sopenharmony_ci atomic_inc(&adap->chcr_stats.aead_rqst); 31218c2ecf20Sopenharmony_ci temp = sizeof(struct cpl_rx_phys_dsgl) + dst_size + IV + 31228c2ecf20Sopenharmony_ci kctx_len + (reqctx->imm ? (req->assoclen + req->cryptlen + 31238c2ecf20Sopenharmony_ci reqctx->b0_len) : 0); 31248c2ecf20Sopenharmony_ci create_wreq(a_ctx(tfm), chcr_req, &req->base, reqctx->imm, 0, 31258c2ecf20Sopenharmony_ci transhdr_len, temp, 0); 31268c2ecf20Sopenharmony_ci reqctx->skb = skb; 31278c2ecf20Sopenharmony_ci 31288c2ecf20Sopenharmony_ci return skb; 31298c2ecf20Sopenharmony_cidstmap_fail: 31308c2ecf20Sopenharmony_ci kfree_skb(skb); 31318c2ecf20Sopenharmony_cierr: 31328c2ecf20Sopenharmony_ci chcr_aead_common_exit(req); 31338c2ecf20Sopenharmony_ci return ERR_PTR(error); 31348c2ecf20Sopenharmony_ci} 31358c2ecf20Sopenharmony_ci 31368c2ecf20Sopenharmony_cistatic struct sk_buff *create_gcm_wr(struct aead_request *req, 31378c2ecf20Sopenharmony_ci unsigned short qid, 31388c2ecf20Sopenharmony_ci int size) 31398c2ecf20Sopenharmony_ci{ 31408c2ecf20Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 31418c2ecf20Sopenharmony_ci struct chcr_context *ctx = a_ctx(tfm); 31428c2ecf20Sopenharmony_ci struct uld_ctx *u_ctx = ULD_CTX(ctx); 31438c2ecf20Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(ctx); 31448c2ecf20Sopenharmony_ci struct chcr_aead_reqctx *reqctx = aead_request_ctx(req); 31458c2ecf20Sopenharmony_ci struct sk_buff *skb = NULL; 31468c2ecf20Sopenharmony_ci struct chcr_wr *chcr_req; 31478c2ecf20Sopenharmony_ci struct cpl_rx_phys_dsgl *phys_cpl; 31488c2ecf20Sopenharmony_ci struct ulptx_sgl *ulptx; 31498c2ecf20Sopenharmony_ci unsigned int transhdr_len, dnents = 0, snents; 31508c2ecf20Sopenharmony_ci unsigned int dst_size = 0, temp = 0, kctx_len, assoclen = req->assoclen; 31518c2ecf20Sopenharmony_ci unsigned int authsize = crypto_aead_authsize(tfm); 31528c2ecf20Sopenharmony_ci int error = -EINVAL; 31538c2ecf20Sopenharmony_ci u8 *ivptr; 31548c2ecf20Sopenharmony_ci gfp_t flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL : 31558c2ecf20Sopenharmony_ci GFP_ATOMIC; 31568c2ecf20Sopenharmony_ci struct adapter *adap = padap(ctx->dev); 31578c2ecf20Sopenharmony_ci unsigned int rx_channel_id = reqctx->rxqidx / ctx->rxq_perchan; 31588c2ecf20Sopenharmony_ci 31598c2ecf20Sopenharmony_ci rx_channel_id = cxgb4_port_e2cchan(u_ctx->lldi.ports[rx_channel_id]); 31608c2ecf20Sopenharmony_ci if (get_aead_subtype(tfm) == CRYPTO_ALG_SUB_TYPE_AEAD_RFC4106) 31618c2ecf20Sopenharmony_ci assoclen = req->assoclen - 8; 31628c2ecf20Sopenharmony_ci 31638c2ecf20Sopenharmony_ci reqctx->b0_len = 0; 31648c2ecf20Sopenharmony_ci error = chcr_aead_common_init(req); 31658c2ecf20Sopenharmony_ci if (error) 31668c2ecf20Sopenharmony_ci return ERR_PTR(error); 31678c2ecf20Sopenharmony_ci dnents = sg_nents_xlen(req->dst, req->assoclen + req->cryptlen + 31688c2ecf20Sopenharmony_ci (reqctx->op ? -authsize : authsize), 31698c2ecf20Sopenharmony_ci CHCR_DST_SG_SIZE, 0); 31708c2ecf20Sopenharmony_ci snents = sg_nents_xlen(req->src, req->assoclen + req->cryptlen, 31718c2ecf20Sopenharmony_ci CHCR_SRC_SG_SIZE, 0); 31728c2ecf20Sopenharmony_ci dnents += MIN_GCM_SG; // For IV 31738c2ecf20Sopenharmony_ci dst_size = get_space_for_phys_dsgl(dnents); 31748c2ecf20Sopenharmony_ci kctx_len = roundup(aeadctx->enckey_len, 16) + AEAD_H_SIZE; 31758c2ecf20Sopenharmony_ci transhdr_len = CIPHER_TRANSHDR_SIZE(kctx_len, dst_size); 31768c2ecf20Sopenharmony_ci reqctx->imm = (transhdr_len + req->assoclen + req->cryptlen) <= 31778c2ecf20Sopenharmony_ci SGE_MAX_WR_LEN; 31788c2ecf20Sopenharmony_ci temp = reqctx->imm ? roundup(req->assoclen + req->cryptlen, 16) : 31798c2ecf20Sopenharmony_ci (sgl_len(snents) * 8); 31808c2ecf20Sopenharmony_ci transhdr_len += temp; 31818c2ecf20Sopenharmony_ci transhdr_len = roundup(transhdr_len, 16); 31828c2ecf20Sopenharmony_ci if (chcr_aead_need_fallback(req, dnents, T6_MAX_AAD_SIZE, 31838c2ecf20Sopenharmony_ci transhdr_len, reqctx->op)) { 31848c2ecf20Sopenharmony_ci 31858c2ecf20Sopenharmony_ci atomic_inc(&adap->chcr_stats.fallback); 31868c2ecf20Sopenharmony_ci chcr_aead_common_exit(req); 31878c2ecf20Sopenharmony_ci return ERR_PTR(chcr_aead_fallback(req, reqctx->op)); 31888c2ecf20Sopenharmony_ci } 31898c2ecf20Sopenharmony_ci skb = alloc_skb(transhdr_len, flags); 31908c2ecf20Sopenharmony_ci if (!skb) { 31918c2ecf20Sopenharmony_ci error = -ENOMEM; 31928c2ecf20Sopenharmony_ci goto err; 31938c2ecf20Sopenharmony_ci } 31948c2ecf20Sopenharmony_ci 31958c2ecf20Sopenharmony_ci chcr_req = __skb_put_zero(skb, transhdr_len); 31968c2ecf20Sopenharmony_ci 31978c2ecf20Sopenharmony_ci //Offset of tag from end 31988c2ecf20Sopenharmony_ci temp = (reqctx->op == CHCR_ENCRYPT_OP) ? 0 : authsize; 31998c2ecf20Sopenharmony_ci chcr_req->sec_cpl.op_ivinsrtofst = FILL_SEC_CPL_OP_IVINSR( 32008c2ecf20Sopenharmony_ci rx_channel_id, 2, 1); 32018c2ecf20Sopenharmony_ci chcr_req->sec_cpl.pldlen = 32028c2ecf20Sopenharmony_ci htonl(req->assoclen + IV + req->cryptlen); 32038c2ecf20Sopenharmony_ci chcr_req->sec_cpl.aadstart_cipherstop_hi = FILL_SEC_CPL_CIPHERSTOP_HI( 32048c2ecf20Sopenharmony_ci assoclen ? 1 + IV : 0, 32058c2ecf20Sopenharmony_ci assoclen ? IV + assoclen : 0, 32068c2ecf20Sopenharmony_ci req->assoclen + IV + 1, 0); 32078c2ecf20Sopenharmony_ci chcr_req->sec_cpl.cipherstop_lo_authinsert = 32088c2ecf20Sopenharmony_ci FILL_SEC_CPL_AUTHINSERT(0, req->assoclen + IV + 1, 32098c2ecf20Sopenharmony_ci temp, temp); 32108c2ecf20Sopenharmony_ci chcr_req->sec_cpl.seqno_numivs = 32118c2ecf20Sopenharmony_ci FILL_SEC_CPL_SCMD0_SEQNO(reqctx->op, (reqctx->op == 32128c2ecf20Sopenharmony_ci CHCR_ENCRYPT_OP) ? 1 : 0, 32138c2ecf20Sopenharmony_ci CHCR_SCMD_CIPHER_MODE_AES_GCM, 32148c2ecf20Sopenharmony_ci CHCR_SCMD_AUTH_MODE_GHASH, 32158c2ecf20Sopenharmony_ci aeadctx->hmac_ctrl, IV >> 1); 32168c2ecf20Sopenharmony_ci chcr_req->sec_cpl.ivgen_hdrlen = FILL_SEC_CPL_IVGEN_HDRLEN(0, 0, 1, 32178c2ecf20Sopenharmony_ci 0, 0, dst_size); 32188c2ecf20Sopenharmony_ci chcr_req->key_ctx.ctx_hdr = aeadctx->key_ctx_hdr; 32198c2ecf20Sopenharmony_ci memcpy(chcr_req->key_ctx.key, aeadctx->key, aeadctx->enckey_len); 32208c2ecf20Sopenharmony_ci memcpy(chcr_req->key_ctx.key + roundup(aeadctx->enckey_len, 16), 32218c2ecf20Sopenharmony_ci GCM_CTX(aeadctx)->ghash_h, AEAD_H_SIZE); 32228c2ecf20Sopenharmony_ci 32238c2ecf20Sopenharmony_ci phys_cpl = (struct cpl_rx_phys_dsgl *)((u8 *)(chcr_req + 1) + kctx_len); 32248c2ecf20Sopenharmony_ci ivptr = (u8 *)(phys_cpl + 1) + dst_size; 32258c2ecf20Sopenharmony_ci /* prepare a 16 byte iv */ 32268c2ecf20Sopenharmony_ci /* S A L T | IV | 0x00000001 */ 32278c2ecf20Sopenharmony_ci if (get_aead_subtype(tfm) == 32288c2ecf20Sopenharmony_ci CRYPTO_ALG_SUB_TYPE_AEAD_RFC4106) { 32298c2ecf20Sopenharmony_ci memcpy(ivptr, aeadctx->salt, 4); 32308c2ecf20Sopenharmony_ci memcpy(ivptr + 4, req->iv, GCM_RFC4106_IV_SIZE); 32318c2ecf20Sopenharmony_ci } else { 32328c2ecf20Sopenharmony_ci memcpy(ivptr, req->iv, GCM_AES_IV_SIZE); 32338c2ecf20Sopenharmony_ci } 32348c2ecf20Sopenharmony_ci put_unaligned_be32(0x01, &ivptr[12]); 32358c2ecf20Sopenharmony_ci ulptx = (struct ulptx_sgl *)(ivptr + 16); 32368c2ecf20Sopenharmony_ci 32378c2ecf20Sopenharmony_ci chcr_add_aead_dst_ent(req, phys_cpl, qid); 32388c2ecf20Sopenharmony_ci chcr_add_aead_src_ent(req, ulptx); 32398c2ecf20Sopenharmony_ci atomic_inc(&adap->chcr_stats.aead_rqst); 32408c2ecf20Sopenharmony_ci temp = sizeof(struct cpl_rx_phys_dsgl) + dst_size + IV + 32418c2ecf20Sopenharmony_ci kctx_len + (reqctx->imm ? (req->assoclen + req->cryptlen) : 0); 32428c2ecf20Sopenharmony_ci create_wreq(a_ctx(tfm), chcr_req, &req->base, reqctx->imm, size, 32438c2ecf20Sopenharmony_ci transhdr_len, temp, reqctx->verify); 32448c2ecf20Sopenharmony_ci reqctx->skb = skb; 32458c2ecf20Sopenharmony_ci return skb; 32468c2ecf20Sopenharmony_ci 32478c2ecf20Sopenharmony_cierr: 32488c2ecf20Sopenharmony_ci chcr_aead_common_exit(req); 32498c2ecf20Sopenharmony_ci return ERR_PTR(error); 32508c2ecf20Sopenharmony_ci} 32518c2ecf20Sopenharmony_ci 32528c2ecf20Sopenharmony_ci 32538c2ecf20Sopenharmony_ci 32548c2ecf20Sopenharmony_cistatic int chcr_aead_cra_init(struct crypto_aead *tfm) 32558c2ecf20Sopenharmony_ci{ 32568c2ecf20Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm)); 32578c2ecf20Sopenharmony_ci struct aead_alg *alg = crypto_aead_alg(tfm); 32588c2ecf20Sopenharmony_ci 32598c2ecf20Sopenharmony_ci aeadctx->sw_cipher = crypto_alloc_aead(alg->base.cra_name, 0, 32608c2ecf20Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK | 32618c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC); 32628c2ecf20Sopenharmony_ci if (IS_ERR(aeadctx->sw_cipher)) 32638c2ecf20Sopenharmony_ci return PTR_ERR(aeadctx->sw_cipher); 32648c2ecf20Sopenharmony_ci crypto_aead_set_reqsize(tfm, max(sizeof(struct chcr_aead_reqctx), 32658c2ecf20Sopenharmony_ci sizeof(struct aead_request) + 32668c2ecf20Sopenharmony_ci crypto_aead_reqsize(aeadctx->sw_cipher))); 32678c2ecf20Sopenharmony_ci return chcr_device_init(a_ctx(tfm)); 32688c2ecf20Sopenharmony_ci} 32698c2ecf20Sopenharmony_ci 32708c2ecf20Sopenharmony_cistatic void chcr_aead_cra_exit(struct crypto_aead *tfm) 32718c2ecf20Sopenharmony_ci{ 32728c2ecf20Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm)); 32738c2ecf20Sopenharmony_ci 32748c2ecf20Sopenharmony_ci crypto_free_aead(aeadctx->sw_cipher); 32758c2ecf20Sopenharmony_ci} 32768c2ecf20Sopenharmony_ci 32778c2ecf20Sopenharmony_cistatic int chcr_authenc_null_setauthsize(struct crypto_aead *tfm, 32788c2ecf20Sopenharmony_ci unsigned int authsize) 32798c2ecf20Sopenharmony_ci{ 32808c2ecf20Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm)); 32818c2ecf20Sopenharmony_ci 32828c2ecf20Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_NOP; 32838c2ecf20Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 32848c2ecf20Sopenharmony_ci return crypto_aead_setauthsize(aeadctx->sw_cipher, authsize); 32858c2ecf20Sopenharmony_ci} 32868c2ecf20Sopenharmony_cistatic int chcr_authenc_setauthsize(struct crypto_aead *tfm, 32878c2ecf20Sopenharmony_ci unsigned int authsize) 32888c2ecf20Sopenharmony_ci{ 32898c2ecf20Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm)); 32908c2ecf20Sopenharmony_ci u32 maxauth = crypto_aead_maxauthsize(tfm); 32918c2ecf20Sopenharmony_ci 32928c2ecf20Sopenharmony_ci /*SHA1 authsize in ipsec is 12 instead of 10 i.e maxauthsize / 2 is not 32938c2ecf20Sopenharmony_ci * true for sha1. authsize == 12 condition should be before 32948c2ecf20Sopenharmony_ci * authsize == (maxauth >> 1) 32958c2ecf20Sopenharmony_ci */ 32968c2ecf20Sopenharmony_ci if (authsize == ICV_4) { 32978c2ecf20Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_PL1; 32988c2ecf20Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 32998c2ecf20Sopenharmony_ci } else if (authsize == ICV_6) { 33008c2ecf20Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_PL2; 33018c2ecf20Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 33028c2ecf20Sopenharmony_ci } else if (authsize == ICV_10) { 33038c2ecf20Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_TRUNC_RFC4366; 33048c2ecf20Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 33058c2ecf20Sopenharmony_ci } else if (authsize == ICV_12) { 33068c2ecf20Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_IPSEC_96BIT; 33078c2ecf20Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 33088c2ecf20Sopenharmony_ci } else if (authsize == ICV_14) { 33098c2ecf20Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_PL3; 33108c2ecf20Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 33118c2ecf20Sopenharmony_ci } else if (authsize == (maxauth >> 1)) { 33128c2ecf20Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_DIV2; 33138c2ecf20Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 33148c2ecf20Sopenharmony_ci } else if (authsize == maxauth) { 33158c2ecf20Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_NO_TRUNC; 33168c2ecf20Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 33178c2ecf20Sopenharmony_ci } else { 33188c2ecf20Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_NO_TRUNC; 33198c2ecf20Sopenharmony_ci aeadctx->mayverify = VERIFY_SW; 33208c2ecf20Sopenharmony_ci } 33218c2ecf20Sopenharmony_ci return crypto_aead_setauthsize(aeadctx->sw_cipher, authsize); 33228c2ecf20Sopenharmony_ci} 33238c2ecf20Sopenharmony_ci 33248c2ecf20Sopenharmony_ci 33258c2ecf20Sopenharmony_cistatic int chcr_gcm_setauthsize(struct crypto_aead *tfm, unsigned int authsize) 33268c2ecf20Sopenharmony_ci{ 33278c2ecf20Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm)); 33288c2ecf20Sopenharmony_ci 33298c2ecf20Sopenharmony_ci switch (authsize) { 33308c2ecf20Sopenharmony_ci case ICV_4: 33318c2ecf20Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_PL1; 33328c2ecf20Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 33338c2ecf20Sopenharmony_ci break; 33348c2ecf20Sopenharmony_ci case ICV_8: 33358c2ecf20Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_DIV2; 33368c2ecf20Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 33378c2ecf20Sopenharmony_ci break; 33388c2ecf20Sopenharmony_ci case ICV_12: 33398c2ecf20Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_IPSEC_96BIT; 33408c2ecf20Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 33418c2ecf20Sopenharmony_ci break; 33428c2ecf20Sopenharmony_ci case ICV_14: 33438c2ecf20Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_PL3; 33448c2ecf20Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 33458c2ecf20Sopenharmony_ci break; 33468c2ecf20Sopenharmony_ci case ICV_16: 33478c2ecf20Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_NO_TRUNC; 33488c2ecf20Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 33498c2ecf20Sopenharmony_ci break; 33508c2ecf20Sopenharmony_ci case ICV_13: 33518c2ecf20Sopenharmony_ci case ICV_15: 33528c2ecf20Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_NO_TRUNC; 33538c2ecf20Sopenharmony_ci aeadctx->mayverify = VERIFY_SW; 33548c2ecf20Sopenharmony_ci break; 33558c2ecf20Sopenharmony_ci default: 33568c2ecf20Sopenharmony_ci return -EINVAL; 33578c2ecf20Sopenharmony_ci } 33588c2ecf20Sopenharmony_ci return crypto_aead_setauthsize(aeadctx->sw_cipher, authsize); 33598c2ecf20Sopenharmony_ci} 33608c2ecf20Sopenharmony_ci 33618c2ecf20Sopenharmony_cistatic int chcr_4106_4309_setauthsize(struct crypto_aead *tfm, 33628c2ecf20Sopenharmony_ci unsigned int authsize) 33638c2ecf20Sopenharmony_ci{ 33648c2ecf20Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm)); 33658c2ecf20Sopenharmony_ci 33668c2ecf20Sopenharmony_ci switch (authsize) { 33678c2ecf20Sopenharmony_ci case ICV_8: 33688c2ecf20Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_DIV2; 33698c2ecf20Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 33708c2ecf20Sopenharmony_ci break; 33718c2ecf20Sopenharmony_ci case ICV_12: 33728c2ecf20Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_IPSEC_96BIT; 33738c2ecf20Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 33748c2ecf20Sopenharmony_ci break; 33758c2ecf20Sopenharmony_ci case ICV_16: 33768c2ecf20Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_NO_TRUNC; 33778c2ecf20Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 33788c2ecf20Sopenharmony_ci break; 33798c2ecf20Sopenharmony_ci default: 33808c2ecf20Sopenharmony_ci return -EINVAL; 33818c2ecf20Sopenharmony_ci } 33828c2ecf20Sopenharmony_ci return crypto_aead_setauthsize(aeadctx->sw_cipher, authsize); 33838c2ecf20Sopenharmony_ci} 33848c2ecf20Sopenharmony_ci 33858c2ecf20Sopenharmony_cistatic int chcr_ccm_setauthsize(struct crypto_aead *tfm, 33868c2ecf20Sopenharmony_ci unsigned int authsize) 33878c2ecf20Sopenharmony_ci{ 33888c2ecf20Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm)); 33898c2ecf20Sopenharmony_ci 33908c2ecf20Sopenharmony_ci switch (authsize) { 33918c2ecf20Sopenharmony_ci case ICV_4: 33928c2ecf20Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_PL1; 33938c2ecf20Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 33948c2ecf20Sopenharmony_ci break; 33958c2ecf20Sopenharmony_ci case ICV_6: 33968c2ecf20Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_PL2; 33978c2ecf20Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 33988c2ecf20Sopenharmony_ci break; 33998c2ecf20Sopenharmony_ci case ICV_8: 34008c2ecf20Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_DIV2; 34018c2ecf20Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 34028c2ecf20Sopenharmony_ci break; 34038c2ecf20Sopenharmony_ci case ICV_10: 34048c2ecf20Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_TRUNC_RFC4366; 34058c2ecf20Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 34068c2ecf20Sopenharmony_ci break; 34078c2ecf20Sopenharmony_ci case ICV_12: 34088c2ecf20Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_IPSEC_96BIT; 34098c2ecf20Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 34108c2ecf20Sopenharmony_ci break; 34118c2ecf20Sopenharmony_ci case ICV_14: 34128c2ecf20Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_PL3; 34138c2ecf20Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 34148c2ecf20Sopenharmony_ci break; 34158c2ecf20Sopenharmony_ci case ICV_16: 34168c2ecf20Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_NO_TRUNC; 34178c2ecf20Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 34188c2ecf20Sopenharmony_ci break; 34198c2ecf20Sopenharmony_ci default: 34208c2ecf20Sopenharmony_ci return -EINVAL; 34218c2ecf20Sopenharmony_ci } 34228c2ecf20Sopenharmony_ci return crypto_aead_setauthsize(aeadctx->sw_cipher, authsize); 34238c2ecf20Sopenharmony_ci} 34248c2ecf20Sopenharmony_ci 34258c2ecf20Sopenharmony_cistatic int chcr_ccm_common_setkey(struct crypto_aead *aead, 34268c2ecf20Sopenharmony_ci const u8 *key, 34278c2ecf20Sopenharmony_ci unsigned int keylen) 34288c2ecf20Sopenharmony_ci{ 34298c2ecf20Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(aead)); 34308c2ecf20Sopenharmony_ci unsigned char ck_size, mk_size; 34318c2ecf20Sopenharmony_ci int key_ctx_size = 0; 34328c2ecf20Sopenharmony_ci 34338c2ecf20Sopenharmony_ci key_ctx_size = sizeof(struct _key_ctx) + roundup(keylen, 16) * 2; 34348c2ecf20Sopenharmony_ci if (keylen == AES_KEYSIZE_128) { 34358c2ecf20Sopenharmony_ci ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_128; 34368c2ecf20Sopenharmony_ci mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_128; 34378c2ecf20Sopenharmony_ci } else if (keylen == AES_KEYSIZE_192) { 34388c2ecf20Sopenharmony_ci ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_192; 34398c2ecf20Sopenharmony_ci mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_192; 34408c2ecf20Sopenharmony_ci } else if (keylen == AES_KEYSIZE_256) { 34418c2ecf20Sopenharmony_ci ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_256; 34428c2ecf20Sopenharmony_ci mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_256; 34438c2ecf20Sopenharmony_ci } else { 34448c2ecf20Sopenharmony_ci aeadctx->enckey_len = 0; 34458c2ecf20Sopenharmony_ci return -EINVAL; 34468c2ecf20Sopenharmony_ci } 34478c2ecf20Sopenharmony_ci aeadctx->key_ctx_hdr = FILL_KEY_CTX_HDR(ck_size, mk_size, 0, 0, 34488c2ecf20Sopenharmony_ci key_ctx_size >> 4); 34498c2ecf20Sopenharmony_ci memcpy(aeadctx->key, key, keylen); 34508c2ecf20Sopenharmony_ci aeadctx->enckey_len = keylen; 34518c2ecf20Sopenharmony_ci 34528c2ecf20Sopenharmony_ci return 0; 34538c2ecf20Sopenharmony_ci} 34548c2ecf20Sopenharmony_ci 34558c2ecf20Sopenharmony_cistatic int chcr_aead_ccm_setkey(struct crypto_aead *aead, 34568c2ecf20Sopenharmony_ci const u8 *key, 34578c2ecf20Sopenharmony_ci unsigned int keylen) 34588c2ecf20Sopenharmony_ci{ 34598c2ecf20Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(aead)); 34608c2ecf20Sopenharmony_ci int error; 34618c2ecf20Sopenharmony_ci 34628c2ecf20Sopenharmony_ci crypto_aead_clear_flags(aeadctx->sw_cipher, CRYPTO_TFM_REQ_MASK); 34638c2ecf20Sopenharmony_ci crypto_aead_set_flags(aeadctx->sw_cipher, crypto_aead_get_flags(aead) & 34648c2ecf20Sopenharmony_ci CRYPTO_TFM_REQ_MASK); 34658c2ecf20Sopenharmony_ci error = crypto_aead_setkey(aeadctx->sw_cipher, key, keylen); 34668c2ecf20Sopenharmony_ci if (error) 34678c2ecf20Sopenharmony_ci return error; 34688c2ecf20Sopenharmony_ci return chcr_ccm_common_setkey(aead, key, keylen); 34698c2ecf20Sopenharmony_ci} 34708c2ecf20Sopenharmony_ci 34718c2ecf20Sopenharmony_cistatic int chcr_aead_rfc4309_setkey(struct crypto_aead *aead, const u8 *key, 34728c2ecf20Sopenharmony_ci unsigned int keylen) 34738c2ecf20Sopenharmony_ci{ 34748c2ecf20Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(aead)); 34758c2ecf20Sopenharmony_ci int error; 34768c2ecf20Sopenharmony_ci 34778c2ecf20Sopenharmony_ci if (keylen < 3) { 34788c2ecf20Sopenharmony_ci aeadctx->enckey_len = 0; 34798c2ecf20Sopenharmony_ci return -EINVAL; 34808c2ecf20Sopenharmony_ci } 34818c2ecf20Sopenharmony_ci crypto_aead_clear_flags(aeadctx->sw_cipher, CRYPTO_TFM_REQ_MASK); 34828c2ecf20Sopenharmony_ci crypto_aead_set_flags(aeadctx->sw_cipher, crypto_aead_get_flags(aead) & 34838c2ecf20Sopenharmony_ci CRYPTO_TFM_REQ_MASK); 34848c2ecf20Sopenharmony_ci error = crypto_aead_setkey(aeadctx->sw_cipher, key, keylen); 34858c2ecf20Sopenharmony_ci if (error) 34868c2ecf20Sopenharmony_ci return error; 34878c2ecf20Sopenharmony_ci keylen -= 3; 34888c2ecf20Sopenharmony_ci memcpy(aeadctx->salt, key + keylen, 3); 34898c2ecf20Sopenharmony_ci return chcr_ccm_common_setkey(aead, key, keylen); 34908c2ecf20Sopenharmony_ci} 34918c2ecf20Sopenharmony_ci 34928c2ecf20Sopenharmony_cistatic int chcr_gcm_setkey(struct crypto_aead *aead, const u8 *key, 34938c2ecf20Sopenharmony_ci unsigned int keylen) 34948c2ecf20Sopenharmony_ci{ 34958c2ecf20Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(aead)); 34968c2ecf20Sopenharmony_ci struct chcr_gcm_ctx *gctx = GCM_CTX(aeadctx); 34978c2ecf20Sopenharmony_ci unsigned int ck_size; 34988c2ecf20Sopenharmony_ci int ret = 0, key_ctx_size = 0; 34998c2ecf20Sopenharmony_ci struct crypto_aes_ctx aes; 35008c2ecf20Sopenharmony_ci 35018c2ecf20Sopenharmony_ci aeadctx->enckey_len = 0; 35028c2ecf20Sopenharmony_ci crypto_aead_clear_flags(aeadctx->sw_cipher, CRYPTO_TFM_REQ_MASK); 35038c2ecf20Sopenharmony_ci crypto_aead_set_flags(aeadctx->sw_cipher, crypto_aead_get_flags(aead) 35048c2ecf20Sopenharmony_ci & CRYPTO_TFM_REQ_MASK); 35058c2ecf20Sopenharmony_ci ret = crypto_aead_setkey(aeadctx->sw_cipher, key, keylen); 35068c2ecf20Sopenharmony_ci if (ret) 35078c2ecf20Sopenharmony_ci goto out; 35088c2ecf20Sopenharmony_ci 35098c2ecf20Sopenharmony_ci if (get_aead_subtype(aead) == CRYPTO_ALG_SUB_TYPE_AEAD_RFC4106 && 35108c2ecf20Sopenharmony_ci keylen > 3) { 35118c2ecf20Sopenharmony_ci keylen -= 4; /* nonce/salt is present in the last 4 bytes */ 35128c2ecf20Sopenharmony_ci memcpy(aeadctx->salt, key + keylen, 4); 35138c2ecf20Sopenharmony_ci } 35148c2ecf20Sopenharmony_ci if (keylen == AES_KEYSIZE_128) { 35158c2ecf20Sopenharmony_ci ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_128; 35168c2ecf20Sopenharmony_ci } else if (keylen == AES_KEYSIZE_192) { 35178c2ecf20Sopenharmony_ci ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_192; 35188c2ecf20Sopenharmony_ci } else if (keylen == AES_KEYSIZE_256) { 35198c2ecf20Sopenharmony_ci ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_256; 35208c2ecf20Sopenharmony_ci } else { 35218c2ecf20Sopenharmony_ci pr_err("GCM: Invalid key length %d\n", keylen); 35228c2ecf20Sopenharmony_ci ret = -EINVAL; 35238c2ecf20Sopenharmony_ci goto out; 35248c2ecf20Sopenharmony_ci } 35258c2ecf20Sopenharmony_ci 35268c2ecf20Sopenharmony_ci memcpy(aeadctx->key, key, keylen); 35278c2ecf20Sopenharmony_ci aeadctx->enckey_len = keylen; 35288c2ecf20Sopenharmony_ci key_ctx_size = sizeof(struct _key_ctx) + roundup(keylen, 16) + 35298c2ecf20Sopenharmony_ci AEAD_H_SIZE; 35308c2ecf20Sopenharmony_ci aeadctx->key_ctx_hdr = FILL_KEY_CTX_HDR(ck_size, 35318c2ecf20Sopenharmony_ci CHCR_KEYCTX_MAC_KEY_SIZE_128, 35328c2ecf20Sopenharmony_ci 0, 0, 35338c2ecf20Sopenharmony_ci key_ctx_size >> 4); 35348c2ecf20Sopenharmony_ci /* Calculate the H = CIPH(K, 0 repeated 16 times). 35358c2ecf20Sopenharmony_ci * It will go in key context 35368c2ecf20Sopenharmony_ci */ 35378c2ecf20Sopenharmony_ci ret = aes_expandkey(&aes, key, keylen); 35388c2ecf20Sopenharmony_ci if (ret) { 35398c2ecf20Sopenharmony_ci aeadctx->enckey_len = 0; 35408c2ecf20Sopenharmony_ci goto out; 35418c2ecf20Sopenharmony_ci } 35428c2ecf20Sopenharmony_ci memset(gctx->ghash_h, 0, AEAD_H_SIZE); 35438c2ecf20Sopenharmony_ci aes_encrypt(&aes, gctx->ghash_h, gctx->ghash_h); 35448c2ecf20Sopenharmony_ci memzero_explicit(&aes, sizeof(aes)); 35458c2ecf20Sopenharmony_ci 35468c2ecf20Sopenharmony_ciout: 35478c2ecf20Sopenharmony_ci return ret; 35488c2ecf20Sopenharmony_ci} 35498c2ecf20Sopenharmony_ci 35508c2ecf20Sopenharmony_cistatic int chcr_authenc_setkey(struct crypto_aead *authenc, const u8 *key, 35518c2ecf20Sopenharmony_ci unsigned int keylen) 35528c2ecf20Sopenharmony_ci{ 35538c2ecf20Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(authenc)); 35548c2ecf20Sopenharmony_ci struct chcr_authenc_ctx *actx = AUTHENC_CTX(aeadctx); 35558c2ecf20Sopenharmony_ci /* it contains auth and cipher key both*/ 35568c2ecf20Sopenharmony_ci struct crypto_authenc_keys keys; 35578c2ecf20Sopenharmony_ci unsigned int bs, subtype; 35588c2ecf20Sopenharmony_ci unsigned int max_authsize = crypto_aead_alg(authenc)->maxauthsize; 35598c2ecf20Sopenharmony_ci int err = 0, i, key_ctx_len = 0; 35608c2ecf20Sopenharmony_ci unsigned char ck_size = 0; 35618c2ecf20Sopenharmony_ci unsigned char pad[CHCR_HASH_MAX_BLOCK_SIZE_128] = { 0 }; 35628c2ecf20Sopenharmony_ci struct crypto_shash *base_hash = ERR_PTR(-EINVAL); 35638c2ecf20Sopenharmony_ci struct algo_param param; 35648c2ecf20Sopenharmony_ci int align; 35658c2ecf20Sopenharmony_ci u8 *o_ptr = NULL; 35668c2ecf20Sopenharmony_ci 35678c2ecf20Sopenharmony_ci crypto_aead_clear_flags(aeadctx->sw_cipher, CRYPTO_TFM_REQ_MASK); 35688c2ecf20Sopenharmony_ci crypto_aead_set_flags(aeadctx->sw_cipher, crypto_aead_get_flags(authenc) 35698c2ecf20Sopenharmony_ci & CRYPTO_TFM_REQ_MASK); 35708c2ecf20Sopenharmony_ci err = crypto_aead_setkey(aeadctx->sw_cipher, key, keylen); 35718c2ecf20Sopenharmony_ci if (err) 35728c2ecf20Sopenharmony_ci goto out; 35738c2ecf20Sopenharmony_ci 35748c2ecf20Sopenharmony_ci if (crypto_authenc_extractkeys(&keys, key, keylen) != 0) 35758c2ecf20Sopenharmony_ci goto out; 35768c2ecf20Sopenharmony_ci 35778c2ecf20Sopenharmony_ci if (get_alg_config(¶m, max_authsize)) { 35788c2ecf20Sopenharmony_ci pr_err("Unsupported digest size\n"); 35798c2ecf20Sopenharmony_ci goto out; 35808c2ecf20Sopenharmony_ci } 35818c2ecf20Sopenharmony_ci subtype = get_aead_subtype(authenc); 35828c2ecf20Sopenharmony_ci if (subtype == CRYPTO_ALG_SUB_TYPE_CTR_SHA || 35838c2ecf20Sopenharmony_ci subtype == CRYPTO_ALG_SUB_TYPE_CTR_NULL) { 35848c2ecf20Sopenharmony_ci if (keys.enckeylen < CTR_RFC3686_NONCE_SIZE) 35858c2ecf20Sopenharmony_ci goto out; 35868c2ecf20Sopenharmony_ci memcpy(aeadctx->nonce, keys.enckey + (keys.enckeylen 35878c2ecf20Sopenharmony_ci - CTR_RFC3686_NONCE_SIZE), CTR_RFC3686_NONCE_SIZE); 35888c2ecf20Sopenharmony_ci keys.enckeylen -= CTR_RFC3686_NONCE_SIZE; 35898c2ecf20Sopenharmony_ci } 35908c2ecf20Sopenharmony_ci if (keys.enckeylen == AES_KEYSIZE_128) { 35918c2ecf20Sopenharmony_ci ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_128; 35928c2ecf20Sopenharmony_ci } else if (keys.enckeylen == AES_KEYSIZE_192) { 35938c2ecf20Sopenharmony_ci ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_192; 35948c2ecf20Sopenharmony_ci } else if (keys.enckeylen == AES_KEYSIZE_256) { 35958c2ecf20Sopenharmony_ci ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_256; 35968c2ecf20Sopenharmony_ci } else { 35978c2ecf20Sopenharmony_ci pr_err("Unsupported cipher key\n"); 35988c2ecf20Sopenharmony_ci goto out; 35998c2ecf20Sopenharmony_ci } 36008c2ecf20Sopenharmony_ci 36018c2ecf20Sopenharmony_ci /* Copy only encryption key. We use authkey to generate h(ipad) and 36028c2ecf20Sopenharmony_ci * h(opad) so authkey is not needed again. authkeylen size have the 36038c2ecf20Sopenharmony_ci * size of the hash digest size. 36048c2ecf20Sopenharmony_ci */ 36058c2ecf20Sopenharmony_ci memcpy(aeadctx->key, keys.enckey, keys.enckeylen); 36068c2ecf20Sopenharmony_ci aeadctx->enckey_len = keys.enckeylen; 36078c2ecf20Sopenharmony_ci if (subtype == CRYPTO_ALG_SUB_TYPE_CBC_SHA || 36088c2ecf20Sopenharmony_ci subtype == CRYPTO_ALG_SUB_TYPE_CBC_NULL) { 36098c2ecf20Sopenharmony_ci 36108c2ecf20Sopenharmony_ci get_aes_decrypt_key(actx->dec_rrkey, aeadctx->key, 36118c2ecf20Sopenharmony_ci aeadctx->enckey_len << 3); 36128c2ecf20Sopenharmony_ci } 36138c2ecf20Sopenharmony_ci base_hash = chcr_alloc_shash(max_authsize); 36148c2ecf20Sopenharmony_ci if (IS_ERR(base_hash)) { 36158c2ecf20Sopenharmony_ci pr_err("Base driver cannot be loaded\n"); 36168c2ecf20Sopenharmony_ci goto out; 36178c2ecf20Sopenharmony_ci } 36188c2ecf20Sopenharmony_ci { 36198c2ecf20Sopenharmony_ci SHASH_DESC_ON_STACK(shash, base_hash); 36208c2ecf20Sopenharmony_ci 36218c2ecf20Sopenharmony_ci shash->tfm = base_hash; 36228c2ecf20Sopenharmony_ci bs = crypto_shash_blocksize(base_hash); 36238c2ecf20Sopenharmony_ci align = KEYCTX_ALIGN_PAD(max_authsize); 36248c2ecf20Sopenharmony_ci o_ptr = actx->h_iopad + param.result_size + align; 36258c2ecf20Sopenharmony_ci 36268c2ecf20Sopenharmony_ci if (keys.authkeylen > bs) { 36278c2ecf20Sopenharmony_ci err = crypto_shash_digest(shash, keys.authkey, 36288c2ecf20Sopenharmony_ci keys.authkeylen, 36298c2ecf20Sopenharmony_ci o_ptr); 36308c2ecf20Sopenharmony_ci if (err) { 36318c2ecf20Sopenharmony_ci pr_err("Base driver cannot be loaded\n"); 36328c2ecf20Sopenharmony_ci goto out; 36338c2ecf20Sopenharmony_ci } 36348c2ecf20Sopenharmony_ci keys.authkeylen = max_authsize; 36358c2ecf20Sopenharmony_ci } else 36368c2ecf20Sopenharmony_ci memcpy(o_ptr, keys.authkey, keys.authkeylen); 36378c2ecf20Sopenharmony_ci 36388c2ecf20Sopenharmony_ci /* Compute the ipad-digest*/ 36398c2ecf20Sopenharmony_ci memset(pad + keys.authkeylen, 0, bs - keys.authkeylen); 36408c2ecf20Sopenharmony_ci memcpy(pad, o_ptr, keys.authkeylen); 36418c2ecf20Sopenharmony_ci for (i = 0; i < bs >> 2; i++) 36428c2ecf20Sopenharmony_ci *((unsigned int *)pad + i) ^= IPAD_DATA; 36438c2ecf20Sopenharmony_ci 36448c2ecf20Sopenharmony_ci if (chcr_compute_partial_hash(shash, pad, actx->h_iopad, 36458c2ecf20Sopenharmony_ci max_authsize)) 36468c2ecf20Sopenharmony_ci goto out; 36478c2ecf20Sopenharmony_ci /* Compute the opad-digest */ 36488c2ecf20Sopenharmony_ci memset(pad + keys.authkeylen, 0, bs - keys.authkeylen); 36498c2ecf20Sopenharmony_ci memcpy(pad, o_ptr, keys.authkeylen); 36508c2ecf20Sopenharmony_ci for (i = 0; i < bs >> 2; i++) 36518c2ecf20Sopenharmony_ci *((unsigned int *)pad + i) ^= OPAD_DATA; 36528c2ecf20Sopenharmony_ci 36538c2ecf20Sopenharmony_ci if (chcr_compute_partial_hash(shash, pad, o_ptr, max_authsize)) 36548c2ecf20Sopenharmony_ci goto out; 36558c2ecf20Sopenharmony_ci 36568c2ecf20Sopenharmony_ci /* convert the ipad and opad digest to network order */ 36578c2ecf20Sopenharmony_ci chcr_change_order(actx->h_iopad, param.result_size); 36588c2ecf20Sopenharmony_ci chcr_change_order(o_ptr, param.result_size); 36598c2ecf20Sopenharmony_ci key_ctx_len = sizeof(struct _key_ctx) + 36608c2ecf20Sopenharmony_ci roundup(keys.enckeylen, 16) + 36618c2ecf20Sopenharmony_ci (param.result_size + align) * 2; 36628c2ecf20Sopenharmony_ci aeadctx->key_ctx_hdr = FILL_KEY_CTX_HDR(ck_size, param.mk_size, 36638c2ecf20Sopenharmony_ci 0, 1, key_ctx_len >> 4); 36648c2ecf20Sopenharmony_ci actx->auth_mode = param.auth_mode; 36658c2ecf20Sopenharmony_ci chcr_free_shash(base_hash); 36668c2ecf20Sopenharmony_ci 36678c2ecf20Sopenharmony_ci memzero_explicit(&keys, sizeof(keys)); 36688c2ecf20Sopenharmony_ci return 0; 36698c2ecf20Sopenharmony_ci } 36708c2ecf20Sopenharmony_ciout: 36718c2ecf20Sopenharmony_ci aeadctx->enckey_len = 0; 36728c2ecf20Sopenharmony_ci memzero_explicit(&keys, sizeof(keys)); 36738c2ecf20Sopenharmony_ci if (!IS_ERR(base_hash)) 36748c2ecf20Sopenharmony_ci chcr_free_shash(base_hash); 36758c2ecf20Sopenharmony_ci return -EINVAL; 36768c2ecf20Sopenharmony_ci} 36778c2ecf20Sopenharmony_ci 36788c2ecf20Sopenharmony_cistatic int chcr_aead_digest_null_setkey(struct crypto_aead *authenc, 36798c2ecf20Sopenharmony_ci const u8 *key, unsigned int keylen) 36808c2ecf20Sopenharmony_ci{ 36818c2ecf20Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(authenc)); 36828c2ecf20Sopenharmony_ci struct chcr_authenc_ctx *actx = AUTHENC_CTX(aeadctx); 36838c2ecf20Sopenharmony_ci struct crypto_authenc_keys keys; 36848c2ecf20Sopenharmony_ci int err; 36858c2ecf20Sopenharmony_ci /* it contains auth and cipher key both*/ 36868c2ecf20Sopenharmony_ci unsigned int subtype; 36878c2ecf20Sopenharmony_ci int key_ctx_len = 0; 36888c2ecf20Sopenharmony_ci unsigned char ck_size = 0; 36898c2ecf20Sopenharmony_ci 36908c2ecf20Sopenharmony_ci crypto_aead_clear_flags(aeadctx->sw_cipher, CRYPTO_TFM_REQ_MASK); 36918c2ecf20Sopenharmony_ci crypto_aead_set_flags(aeadctx->sw_cipher, crypto_aead_get_flags(authenc) 36928c2ecf20Sopenharmony_ci & CRYPTO_TFM_REQ_MASK); 36938c2ecf20Sopenharmony_ci err = crypto_aead_setkey(aeadctx->sw_cipher, key, keylen); 36948c2ecf20Sopenharmony_ci if (err) 36958c2ecf20Sopenharmony_ci goto out; 36968c2ecf20Sopenharmony_ci 36978c2ecf20Sopenharmony_ci if (crypto_authenc_extractkeys(&keys, key, keylen) != 0) 36988c2ecf20Sopenharmony_ci goto out; 36998c2ecf20Sopenharmony_ci 37008c2ecf20Sopenharmony_ci subtype = get_aead_subtype(authenc); 37018c2ecf20Sopenharmony_ci if (subtype == CRYPTO_ALG_SUB_TYPE_CTR_SHA || 37028c2ecf20Sopenharmony_ci subtype == CRYPTO_ALG_SUB_TYPE_CTR_NULL) { 37038c2ecf20Sopenharmony_ci if (keys.enckeylen < CTR_RFC3686_NONCE_SIZE) 37048c2ecf20Sopenharmony_ci goto out; 37058c2ecf20Sopenharmony_ci memcpy(aeadctx->nonce, keys.enckey + (keys.enckeylen 37068c2ecf20Sopenharmony_ci - CTR_RFC3686_NONCE_SIZE), CTR_RFC3686_NONCE_SIZE); 37078c2ecf20Sopenharmony_ci keys.enckeylen -= CTR_RFC3686_NONCE_SIZE; 37088c2ecf20Sopenharmony_ci } 37098c2ecf20Sopenharmony_ci if (keys.enckeylen == AES_KEYSIZE_128) { 37108c2ecf20Sopenharmony_ci ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_128; 37118c2ecf20Sopenharmony_ci } else if (keys.enckeylen == AES_KEYSIZE_192) { 37128c2ecf20Sopenharmony_ci ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_192; 37138c2ecf20Sopenharmony_ci } else if (keys.enckeylen == AES_KEYSIZE_256) { 37148c2ecf20Sopenharmony_ci ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_256; 37158c2ecf20Sopenharmony_ci } else { 37168c2ecf20Sopenharmony_ci pr_err("Unsupported cipher key %d\n", keys.enckeylen); 37178c2ecf20Sopenharmony_ci goto out; 37188c2ecf20Sopenharmony_ci } 37198c2ecf20Sopenharmony_ci memcpy(aeadctx->key, keys.enckey, keys.enckeylen); 37208c2ecf20Sopenharmony_ci aeadctx->enckey_len = keys.enckeylen; 37218c2ecf20Sopenharmony_ci if (subtype == CRYPTO_ALG_SUB_TYPE_CBC_SHA || 37228c2ecf20Sopenharmony_ci subtype == CRYPTO_ALG_SUB_TYPE_CBC_NULL) { 37238c2ecf20Sopenharmony_ci get_aes_decrypt_key(actx->dec_rrkey, aeadctx->key, 37248c2ecf20Sopenharmony_ci aeadctx->enckey_len << 3); 37258c2ecf20Sopenharmony_ci } 37268c2ecf20Sopenharmony_ci key_ctx_len = sizeof(struct _key_ctx) + roundup(keys.enckeylen, 16); 37278c2ecf20Sopenharmony_ci 37288c2ecf20Sopenharmony_ci aeadctx->key_ctx_hdr = FILL_KEY_CTX_HDR(ck_size, CHCR_KEYCTX_NO_KEY, 0, 37298c2ecf20Sopenharmony_ci 0, key_ctx_len >> 4); 37308c2ecf20Sopenharmony_ci actx->auth_mode = CHCR_SCMD_AUTH_MODE_NOP; 37318c2ecf20Sopenharmony_ci memzero_explicit(&keys, sizeof(keys)); 37328c2ecf20Sopenharmony_ci return 0; 37338c2ecf20Sopenharmony_ciout: 37348c2ecf20Sopenharmony_ci aeadctx->enckey_len = 0; 37358c2ecf20Sopenharmony_ci memzero_explicit(&keys, sizeof(keys)); 37368c2ecf20Sopenharmony_ci return -EINVAL; 37378c2ecf20Sopenharmony_ci} 37388c2ecf20Sopenharmony_ci 37398c2ecf20Sopenharmony_cistatic int chcr_aead_op(struct aead_request *req, 37408c2ecf20Sopenharmony_ci int size, 37418c2ecf20Sopenharmony_ci create_wr_t create_wr_fn) 37428c2ecf20Sopenharmony_ci{ 37438c2ecf20Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 37448c2ecf20Sopenharmony_ci struct chcr_aead_reqctx *reqctx = aead_request_ctx(req); 37458c2ecf20Sopenharmony_ci struct chcr_context *ctx = a_ctx(tfm); 37468c2ecf20Sopenharmony_ci struct uld_ctx *u_ctx = ULD_CTX(ctx); 37478c2ecf20Sopenharmony_ci struct sk_buff *skb; 37488c2ecf20Sopenharmony_ci struct chcr_dev *cdev; 37498c2ecf20Sopenharmony_ci 37508c2ecf20Sopenharmony_ci cdev = a_ctx(tfm)->dev; 37518c2ecf20Sopenharmony_ci if (!cdev) { 37528c2ecf20Sopenharmony_ci pr_err("%s : No crypto device.\n", __func__); 37538c2ecf20Sopenharmony_ci return -ENXIO; 37548c2ecf20Sopenharmony_ci } 37558c2ecf20Sopenharmony_ci 37568c2ecf20Sopenharmony_ci if (chcr_inc_wrcount(cdev)) { 37578c2ecf20Sopenharmony_ci /* Detach state for CHCR means lldi or padap is freed. 37588c2ecf20Sopenharmony_ci * We cannot increment fallback here. 37598c2ecf20Sopenharmony_ci */ 37608c2ecf20Sopenharmony_ci return chcr_aead_fallback(req, reqctx->op); 37618c2ecf20Sopenharmony_ci } 37628c2ecf20Sopenharmony_ci 37638c2ecf20Sopenharmony_ci if (cxgb4_is_crypto_q_full(u_ctx->lldi.ports[0], 37648c2ecf20Sopenharmony_ci reqctx->txqidx) && 37658c2ecf20Sopenharmony_ci (!(req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG))) { 37668c2ecf20Sopenharmony_ci chcr_dec_wrcount(cdev); 37678c2ecf20Sopenharmony_ci return -ENOSPC; 37688c2ecf20Sopenharmony_ci } 37698c2ecf20Sopenharmony_ci 37708c2ecf20Sopenharmony_ci if (get_aead_subtype(tfm) == CRYPTO_ALG_SUB_TYPE_AEAD_RFC4106 && 37718c2ecf20Sopenharmony_ci crypto_ipsec_check_assoclen(req->assoclen) != 0) { 37728c2ecf20Sopenharmony_ci pr_err("RFC4106: Invalid value of assoclen %d\n", 37738c2ecf20Sopenharmony_ci req->assoclen); 37748c2ecf20Sopenharmony_ci return -EINVAL; 37758c2ecf20Sopenharmony_ci } 37768c2ecf20Sopenharmony_ci 37778c2ecf20Sopenharmony_ci /* Form a WR from req */ 37788c2ecf20Sopenharmony_ci skb = create_wr_fn(req, u_ctx->lldi.rxq_ids[reqctx->rxqidx], size); 37798c2ecf20Sopenharmony_ci 37808c2ecf20Sopenharmony_ci if (IS_ERR_OR_NULL(skb)) { 37818c2ecf20Sopenharmony_ci chcr_dec_wrcount(cdev); 37828c2ecf20Sopenharmony_ci return PTR_ERR_OR_ZERO(skb); 37838c2ecf20Sopenharmony_ci } 37848c2ecf20Sopenharmony_ci 37858c2ecf20Sopenharmony_ci skb->dev = u_ctx->lldi.ports[0]; 37868c2ecf20Sopenharmony_ci set_wr_txq(skb, CPL_PRIORITY_DATA, reqctx->txqidx); 37878c2ecf20Sopenharmony_ci chcr_send_wr(skb); 37888c2ecf20Sopenharmony_ci return -EINPROGRESS; 37898c2ecf20Sopenharmony_ci} 37908c2ecf20Sopenharmony_ci 37918c2ecf20Sopenharmony_cistatic int chcr_aead_encrypt(struct aead_request *req) 37928c2ecf20Sopenharmony_ci{ 37938c2ecf20Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 37948c2ecf20Sopenharmony_ci struct chcr_aead_reqctx *reqctx = aead_request_ctx(req); 37958c2ecf20Sopenharmony_ci struct chcr_context *ctx = a_ctx(tfm); 37968c2ecf20Sopenharmony_ci unsigned int cpu; 37978c2ecf20Sopenharmony_ci 37988c2ecf20Sopenharmony_ci cpu = get_cpu(); 37998c2ecf20Sopenharmony_ci reqctx->txqidx = cpu % ctx->ntxq; 38008c2ecf20Sopenharmony_ci reqctx->rxqidx = cpu % ctx->nrxq; 38018c2ecf20Sopenharmony_ci put_cpu(); 38028c2ecf20Sopenharmony_ci 38038c2ecf20Sopenharmony_ci reqctx->verify = VERIFY_HW; 38048c2ecf20Sopenharmony_ci reqctx->op = CHCR_ENCRYPT_OP; 38058c2ecf20Sopenharmony_ci 38068c2ecf20Sopenharmony_ci switch (get_aead_subtype(tfm)) { 38078c2ecf20Sopenharmony_ci case CRYPTO_ALG_SUB_TYPE_CTR_SHA: 38088c2ecf20Sopenharmony_ci case CRYPTO_ALG_SUB_TYPE_CBC_SHA: 38098c2ecf20Sopenharmony_ci case CRYPTO_ALG_SUB_TYPE_CBC_NULL: 38108c2ecf20Sopenharmony_ci case CRYPTO_ALG_SUB_TYPE_CTR_NULL: 38118c2ecf20Sopenharmony_ci return chcr_aead_op(req, 0, create_authenc_wr); 38128c2ecf20Sopenharmony_ci case CRYPTO_ALG_SUB_TYPE_AEAD_CCM: 38138c2ecf20Sopenharmony_ci case CRYPTO_ALG_SUB_TYPE_AEAD_RFC4309: 38148c2ecf20Sopenharmony_ci return chcr_aead_op(req, 0, create_aead_ccm_wr); 38158c2ecf20Sopenharmony_ci default: 38168c2ecf20Sopenharmony_ci return chcr_aead_op(req, 0, create_gcm_wr); 38178c2ecf20Sopenharmony_ci } 38188c2ecf20Sopenharmony_ci} 38198c2ecf20Sopenharmony_ci 38208c2ecf20Sopenharmony_cistatic int chcr_aead_decrypt(struct aead_request *req) 38218c2ecf20Sopenharmony_ci{ 38228c2ecf20Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 38238c2ecf20Sopenharmony_ci struct chcr_context *ctx = a_ctx(tfm); 38248c2ecf20Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(ctx); 38258c2ecf20Sopenharmony_ci struct chcr_aead_reqctx *reqctx = aead_request_ctx(req); 38268c2ecf20Sopenharmony_ci int size; 38278c2ecf20Sopenharmony_ci unsigned int cpu; 38288c2ecf20Sopenharmony_ci 38298c2ecf20Sopenharmony_ci cpu = get_cpu(); 38308c2ecf20Sopenharmony_ci reqctx->txqidx = cpu % ctx->ntxq; 38318c2ecf20Sopenharmony_ci reqctx->rxqidx = cpu % ctx->nrxq; 38328c2ecf20Sopenharmony_ci put_cpu(); 38338c2ecf20Sopenharmony_ci 38348c2ecf20Sopenharmony_ci if (aeadctx->mayverify == VERIFY_SW) { 38358c2ecf20Sopenharmony_ci size = crypto_aead_maxauthsize(tfm); 38368c2ecf20Sopenharmony_ci reqctx->verify = VERIFY_SW; 38378c2ecf20Sopenharmony_ci } else { 38388c2ecf20Sopenharmony_ci size = 0; 38398c2ecf20Sopenharmony_ci reqctx->verify = VERIFY_HW; 38408c2ecf20Sopenharmony_ci } 38418c2ecf20Sopenharmony_ci reqctx->op = CHCR_DECRYPT_OP; 38428c2ecf20Sopenharmony_ci switch (get_aead_subtype(tfm)) { 38438c2ecf20Sopenharmony_ci case CRYPTO_ALG_SUB_TYPE_CBC_SHA: 38448c2ecf20Sopenharmony_ci case CRYPTO_ALG_SUB_TYPE_CTR_SHA: 38458c2ecf20Sopenharmony_ci case CRYPTO_ALG_SUB_TYPE_CBC_NULL: 38468c2ecf20Sopenharmony_ci case CRYPTO_ALG_SUB_TYPE_CTR_NULL: 38478c2ecf20Sopenharmony_ci return chcr_aead_op(req, size, create_authenc_wr); 38488c2ecf20Sopenharmony_ci case CRYPTO_ALG_SUB_TYPE_AEAD_CCM: 38498c2ecf20Sopenharmony_ci case CRYPTO_ALG_SUB_TYPE_AEAD_RFC4309: 38508c2ecf20Sopenharmony_ci return chcr_aead_op(req, size, create_aead_ccm_wr); 38518c2ecf20Sopenharmony_ci default: 38528c2ecf20Sopenharmony_ci return chcr_aead_op(req, size, create_gcm_wr); 38538c2ecf20Sopenharmony_ci } 38548c2ecf20Sopenharmony_ci} 38558c2ecf20Sopenharmony_ci 38568c2ecf20Sopenharmony_cistatic struct chcr_alg_template driver_algs[] = { 38578c2ecf20Sopenharmony_ci /* AES-CBC */ 38588c2ecf20Sopenharmony_ci { 38598c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_SKCIPHER | CRYPTO_ALG_SUB_TYPE_CBC, 38608c2ecf20Sopenharmony_ci .is_registered = 0, 38618c2ecf20Sopenharmony_ci .alg.skcipher = { 38628c2ecf20Sopenharmony_ci .base.cra_name = "cbc(aes)", 38638c2ecf20Sopenharmony_ci .base.cra_driver_name = "cbc-aes-chcr", 38648c2ecf20Sopenharmony_ci .base.cra_blocksize = AES_BLOCK_SIZE, 38658c2ecf20Sopenharmony_ci 38668c2ecf20Sopenharmony_ci .init = chcr_init_tfm, 38678c2ecf20Sopenharmony_ci .exit = chcr_exit_tfm, 38688c2ecf20Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE, 38698c2ecf20Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE, 38708c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 38718c2ecf20Sopenharmony_ci .setkey = chcr_aes_cbc_setkey, 38728c2ecf20Sopenharmony_ci .encrypt = chcr_aes_encrypt, 38738c2ecf20Sopenharmony_ci .decrypt = chcr_aes_decrypt, 38748c2ecf20Sopenharmony_ci } 38758c2ecf20Sopenharmony_ci }, 38768c2ecf20Sopenharmony_ci { 38778c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_SKCIPHER | CRYPTO_ALG_SUB_TYPE_XTS, 38788c2ecf20Sopenharmony_ci .is_registered = 0, 38798c2ecf20Sopenharmony_ci .alg.skcipher = { 38808c2ecf20Sopenharmony_ci .base.cra_name = "xts(aes)", 38818c2ecf20Sopenharmony_ci .base.cra_driver_name = "xts-aes-chcr", 38828c2ecf20Sopenharmony_ci .base.cra_blocksize = AES_BLOCK_SIZE, 38838c2ecf20Sopenharmony_ci 38848c2ecf20Sopenharmony_ci .init = chcr_init_tfm, 38858c2ecf20Sopenharmony_ci .exit = chcr_exit_tfm, 38868c2ecf20Sopenharmony_ci .min_keysize = 2 * AES_MIN_KEY_SIZE, 38878c2ecf20Sopenharmony_ci .max_keysize = 2 * AES_MAX_KEY_SIZE, 38888c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 38898c2ecf20Sopenharmony_ci .setkey = chcr_aes_xts_setkey, 38908c2ecf20Sopenharmony_ci .encrypt = chcr_aes_encrypt, 38918c2ecf20Sopenharmony_ci .decrypt = chcr_aes_decrypt, 38928c2ecf20Sopenharmony_ci } 38938c2ecf20Sopenharmony_ci }, 38948c2ecf20Sopenharmony_ci { 38958c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_SKCIPHER | CRYPTO_ALG_SUB_TYPE_CTR, 38968c2ecf20Sopenharmony_ci .is_registered = 0, 38978c2ecf20Sopenharmony_ci .alg.skcipher = { 38988c2ecf20Sopenharmony_ci .base.cra_name = "ctr(aes)", 38998c2ecf20Sopenharmony_ci .base.cra_driver_name = "ctr-aes-chcr", 39008c2ecf20Sopenharmony_ci .base.cra_blocksize = 1, 39018c2ecf20Sopenharmony_ci 39028c2ecf20Sopenharmony_ci .init = chcr_init_tfm, 39038c2ecf20Sopenharmony_ci .exit = chcr_exit_tfm, 39048c2ecf20Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE, 39058c2ecf20Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE, 39068c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 39078c2ecf20Sopenharmony_ci .setkey = chcr_aes_ctr_setkey, 39088c2ecf20Sopenharmony_ci .encrypt = chcr_aes_encrypt, 39098c2ecf20Sopenharmony_ci .decrypt = chcr_aes_decrypt, 39108c2ecf20Sopenharmony_ci } 39118c2ecf20Sopenharmony_ci }, 39128c2ecf20Sopenharmony_ci { 39138c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_SKCIPHER | 39148c2ecf20Sopenharmony_ci CRYPTO_ALG_SUB_TYPE_CTR_RFC3686, 39158c2ecf20Sopenharmony_ci .is_registered = 0, 39168c2ecf20Sopenharmony_ci .alg.skcipher = { 39178c2ecf20Sopenharmony_ci .base.cra_name = "rfc3686(ctr(aes))", 39188c2ecf20Sopenharmony_ci .base.cra_driver_name = "rfc3686-ctr-aes-chcr", 39198c2ecf20Sopenharmony_ci .base.cra_blocksize = 1, 39208c2ecf20Sopenharmony_ci 39218c2ecf20Sopenharmony_ci .init = chcr_rfc3686_init, 39228c2ecf20Sopenharmony_ci .exit = chcr_exit_tfm, 39238c2ecf20Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE + CTR_RFC3686_NONCE_SIZE, 39248c2ecf20Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE + CTR_RFC3686_NONCE_SIZE, 39258c2ecf20Sopenharmony_ci .ivsize = CTR_RFC3686_IV_SIZE, 39268c2ecf20Sopenharmony_ci .setkey = chcr_aes_rfc3686_setkey, 39278c2ecf20Sopenharmony_ci .encrypt = chcr_aes_encrypt, 39288c2ecf20Sopenharmony_ci .decrypt = chcr_aes_decrypt, 39298c2ecf20Sopenharmony_ci } 39308c2ecf20Sopenharmony_ci }, 39318c2ecf20Sopenharmony_ci /* SHA */ 39328c2ecf20Sopenharmony_ci { 39338c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AHASH, 39348c2ecf20Sopenharmony_ci .is_registered = 0, 39358c2ecf20Sopenharmony_ci .alg.hash = { 39368c2ecf20Sopenharmony_ci .halg.digestsize = SHA1_DIGEST_SIZE, 39378c2ecf20Sopenharmony_ci .halg.base = { 39388c2ecf20Sopenharmony_ci .cra_name = "sha1", 39398c2ecf20Sopenharmony_ci .cra_driver_name = "sha1-chcr", 39408c2ecf20Sopenharmony_ci .cra_blocksize = SHA1_BLOCK_SIZE, 39418c2ecf20Sopenharmony_ci } 39428c2ecf20Sopenharmony_ci } 39438c2ecf20Sopenharmony_ci }, 39448c2ecf20Sopenharmony_ci { 39458c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AHASH, 39468c2ecf20Sopenharmony_ci .is_registered = 0, 39478c2ecf20Sopenharmony_ci .alg.hash = { 39488c2ecf20Sopenharmony_ci .halg.digestsize = SHA256_DIGEST_SIZE, 39498c2ecf20Sopenharmony_ci .halg.base = { 39508c2ecf20Sopenharmony_ci .cra_name = "sha256", 39518c2ecf20Sopenharmony_ci .cra_driver_name = "sha256-chcr", 39528c2ecf20Sopenharmony_ci .cra_blocksize = SHA256_BLOCK_SIZE, 39538c2ecf20Sopenharmony_ci } 39548c2ecf20Sopenharmony_ci } 39558c2ecf20Sopenharmony_ci }, 39568c2ecf20Sopenharmony_ci { 39578c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AHASH, 39588c2ecf20Sopenharmony_ci .is_registered = 0, 39598c2ecf20Sopenharmony_ci .alg.hash = { 39608c2ecf20Sopenharmony_ci .halg.digestsize = SHA224_DIGEST_SIZE, 39618c2ecf20Sopenharmony_ci .halg.base = { 39628c2ecf20Sopenharmony_ci .cra_name = "sha224", 39638c2ecf20Sopenharmony_ci .cra_driver_name = "sha224-chcr", 39648c2ecf20Sopenharmony_ci .cra_blocksize = SHA224_BLOCK_SIZE, 39658c2ecf20Sopenharmony_ci } 39668c2ecf20Sopenharmony_ci } 39678c2ecf20Sopenharmony_ci }, 39688c2ecf20Sopenharmony_ci { 39698c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AHASH, 39708c2ecf20Sopenharmony_ci .is_registered = 0, 39718c2ecf20Sopenharmony_ci .alg.hash = { 39728c2ecf20Sopenharmony_ci .halg.digestsize = SHA384_DIGEST_SIZE, 39738c2ecf20Sopenharmony_ci .halg.base = { 39748c2ecf20Sopenharmony_ci .cra_name = "sha384", 39758c2ecf20Sopenharmony_ci .cra_driver_name = "sha384-chcr", 39768c2ecf20Sopenharmony_ci .cra_blocksize = SHA384_BLOCK_SIZE, 39778c2ecf20Sopenharmony_ci } 39788c2ecf20Sopenharmony_ci } 39798c2ecf20Sopenharmony_ci }, 39808c2ecf20Sopenharmony_ci { 39818c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AHASH, 39828c2ecf20Sopenharmony_ci .is_registered = 0, 39838c2ecf20Sopenharmony_ci .alg.hash = { 39848c2ecf20Sopenharmony_ci .halg.digestsize = SHA512_DIGEST_SIZE, 39858c2ecf20Sopenharmony_ci .halg.base = { 39868c2ecf20Sopenharmony_ci .cra_name = "sha512", 39878c2ecf20Sopenharmony_ci .cra_driver_name = "sha512-chcr", 39888c2ecf20Sopenharmony_ci .cra_blocksize = SHA512_BLOCK_SIZE, 39898c2ecf20Sopenharmony_ci } 39908c2ecf20Sopenharmony_ci } 39918c2ecf20Sopenharmony_ci }, 39928c2ecf20Sopenharmony_ci /* HMAC */ 39938c2ecf20Sopenharmony_ci { 39948c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_HMAC, 39958c2ecf20Sopenharmony_ci .is_registered = 0, 39968c2ecf20Sopenharmony_ci .alg.hash = { 39978c2ecf20Sopenharmony_ci .halg.digestsize = SHA1_DIGEST_SIZE, 39988c2ecf20Sopenharmony_ci .halg.base = { 39998c2ecf20Sopenharmony_ci .cra_name = "hmac(sha1)", 40008c2ecf20Sopenharmony_ci .cra_driver_name = "hmac-sha1-chcr", 40018c2ecf20Sopenharmony_ci .cra_blocksize = SHA1_BLOCK_SIZE, 40028c2ecf20Sopenharmony_ci } 40038c2ecf20Sopenharmony_ci } 40048c2ecf20Sopenharmony_ci }, 40058c2ecf20Sopenharmony_ci { 40068c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_HMAC, 40078c2ecf20Sopenharmony_ci .is_registered = 0, 40088c2ecf20Sopenharmony_ci .alg.hash = { 40098c2ecf20Sopenharmony_ci .halg.digestsize = SHA224_DIGEST_SIZE, 40108c2ecf20Sopenharmony_ci .halg.base = { 40118c2ecf20Sopenharmony_ci .cra_name = "hmac(sha224)", 40128c2ecf20Sopenharmony_ci .cra_driver_name = "hmac-sha224-chcr", 40138c2ecf20Sopenharmony_ci .cra_blocksize = SHA224_BLOCK_SIZE, 40148c2ecf20Sopenharmony_ci } 40158c2ecf20Sopenharmony_ci } 40168c2ecf20Sopenharmony_ci }, 40178c2ecf20Sopenharmony_ci { 40188c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_HMAC, 40198c2ecf20Sopenharmony_ci .is_registered = 0, 40208c2ecf20Sopenharmony_ci .alg.hash = { 40218c2ecf20Sopenharmony_ci .halg.digestsize = SHA256_DIGEST_SIZE, 40228c2ecf20Sopenharmony_ci .halg.base = { 40238c2ecf20Sopenharmony_ci .cra_name = "hmac(sha256)", 40248c2ecf20Sopenharmony_ci .cra_driver_name = "hmac-sha256-chcr", 40258c2ecf20Sopenharmony_ci .cra_blocksize = SHA256_BLOCK_SIZE, 40268c2ecf20Sopenharmony_ci } 40278c2ecf20Sopenharmony_ci } 40288c2ecf20Sopenharmony_ci }, 40298c2ecf20Sopenharmony_ci { 40308c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_HMAC, 40318c2ecf20Sopenharmony_ci .is_registered = 0, 40328c2ecf20Sopenharmony_ci .alg.hash = { 40338c2ecf20Sopenharmony_ci .halg.digestsize = SHA384_DIGEST_SIZE, 40348c2ecf20Sopenharmony_ci .halg.base = { 40358c2ecf20Sopenharmony_ci .cra_name = "hmac(sha384)", 40368c2ecf20Sopenharmony_ci .cra_driver_name = "hmac-sha384-chcr", 40378c2ecf20Sopenharmony_ci .cra_blocksize = SHA384_BLOCK_SIZE, 40388c2ecf20Sopenharmony_ci } 40398c2ecf20Sopenharmony_ci } 40408c2ecf20Sopenharmony_ci }, 40418c2ecf20Sopenharmony_ci { 40428c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_HMAC, 40438c2ecf20Sopenharmony_ci .is_registered = 0, 40448c2ecf20Sopenharmony_ci .alg.hash = { 40458c2ecf20Sopenharmony_ci .halg.digestsize = SHA512_DIGEST_SIZE, 40468c2ecf20Sopenharmony_ci .halg.base = { 40478c2ecf20Sopenharmony_ci .cra_name = "hmac(sha512)", 40488c2ecf20Sopenharmony_ci .cra_driver_name = "hmac-sha512-chcr", 40498c2ecf20Sopenharmony_ci .cra_blocksize = SHA512_BLOCK_SIZE, 40508c2ecf20Sopenharmony_ci } 40518c2ecf20Sopenharmony_ci } 40528c2ecf20Sopenharmony_ci }, 40538c2ecf20Sopenharmony_ci /* Add AEAD Algorithms */ 40548c2ecf20Sopenharmony_ci { 40558c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_AEAD_GCM, 40568c2ecf20Sopenharmony_ci .is_registered = 0, 40578c2ecf20Sopenharmony_ci .alg.aead = { 40588c2ecf20Sopenharmony_ci .base = { 40598c2ecf20Sopenharmony_ci .cra_name = "gcm(aes)", 40608c2ecf20Sopenharmony_ci .cra_driver_name = "gcm-aes-chcr", 40618c2ecf20Sopenharmony_ci .cra_blocksize = 1, 40628c2ecf20Sopenharmony_ci .cra_priority = CHCR_AEAD_PRIORITY, 40638c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct chcr_context) + 40648c2ecf20Sopenharmony_ci sizeof(struct chcr_aead_ctx) + 40658c2ecf20Sopenharmony_ci sizeof(struct chcr_gcm_ctx), 40668c2ecf20Sopenharmony_ci }, 40678c2ecf20Sopenharmony_ci .ivsize = GCM_AES_IV_SIZE, 40688c2ecf20Sopenharmony_ci .maxauthsize = GHASH_DIGEST_SIZE, 40698c2ecf20Sopenharmony_ci .setkey = chcr_gcm_setkey, 40708c2ecf20Sopenharmony_ci .setauthsize = chcr_gcm_setauthsize, 40718c2ecf20Sopenharmony_ci } 40728c2ecf20Sopenharmony_ci }, 40738c2ecf20Sopenharmony_ci { 40748c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_AEAD_RFC4106, 40758c2ecf20Sopenharmony_ci .is_registered = 0, 40768c2ecf20Sopenharmony_ci .alg.aead = { 40778c2ecf20Sopenharmony_ci .base = { 40788c2ecf20Sopenharmony_ci .cra_name = "rfc4106(gcm(aes))", 40798c2ecf20Sopenharmony_ci .cra_driver_name = "rfc4106-gcm-aes-chcr", 40808c2ecf20Sopenharmony_ci .cra_blocksize = 1, 40818c2ecf20Sopenharmony_ci .cra_priority = CHCR_AEAD_PRIORITY + 1, 40828c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct chcr_context) + 40838c2ecf20Sopenharmony_ci sizeof(struct chcr_aead_ctx) + 40848c2ecf20Sopenharmony_ci sizeof(struct chcr_gcm_ctx), 40858c2ecf20Sopenharmony_ci 40868c2ecf20Sopenharmony_ci }, 40878c2ecf20Sopenharmony_ci .ivsize = GCM_RFC4106_IV_SIZE, 40888c2ecf20Sopenharmony_ci .maxauthsize = GHASH_DIGEST_SIZE, 40898c2ecf20Sopenharmony_ci .setkey = chcr_gcm_setkey, 40908c2ecf20Sopenharmony_ci .setauthsize = chcr_4106_4309_setauthsize, 40918c2ecf20Sopenharmony_ci } 40928c2ecf20Sopenharmony_ci }, 40938c2ecf20Sopenharmony_ci { 40948c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_AEAD_CCM, 40958c2ecf20Sopenharmony_ci .is_registered = 0, 40968c2ecf20Sopenharmony_ci .alg.aead = { 40978c2ecf20Sopenharmony_ci .base = { 40988c2ecf20Sopenharmony_ci .cra_name = "ccm(aes)", 40998c2ecf20Sopenharmony_ci .cra_driver_name = "ccm-aes-chcr", 41008c2ecf20Sopenharmony_ci .cra_blocksize = 1, 41018c2ecf20Sopenharmony_ci .cra_priority = CHCR_AEAD_PRIORITY, 41028c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct chcr_context) + 41038c2ecf20Sopenharmony_ci sizeof(struct chcr_aead_ctx), 41048c2ecf20Sopenharmony_ci 41058c2ecf20Sopenharmony_ci }, 41068c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 41078c2ecf20Sopenharmony_ci .maxauthsize = GHASH_DIGEST_SIZE, 41088c2ecf20Sopenharmony_ci .setkey = chcr_aead_ccm_setkey, 41098c2ecf20Sopenharmony_ci .setauthsize = chcr_ccm_setauthsize, 41108c2ecf20Sopenharmony_ci } 41118c2ecf20Sopenharmony_ci }, 41128c2ecf20Sopenharmony_ci { 41138c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_AEAD_RFC4309, 41148c2ecf20Sopenharmony_ci .is_registered = 0, 41158c2ecf20Sopenharmony_ci .alg.aead = { 41168c2ecf20Sopenharmony_ci .base = { 41178c2ecf20Sopenharmony_ci .cra_name = "rfc4309(ccm(aes))", 41188c2ecf20Sopenharmony_ci .cra_driver_name = "rfc4309-ccm-aes-chcr", 41198c2ecf20Sopenharmony_ci .cra_blocksize = 1, 41208c2ecf20Sopenharmony_ci .cra_priority = CHCR_AEAD_PRIORITY + 1, 41218c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct chcr_context) + 41228c2ecf20Sopenharmony_ci sizeof(struct chcr_aead_ctx), 41238c2ecf20Sopenharmony_ci 41248c2ecf20Sopenharmony_ci }, 41258c2ecf20Sopenharmony_ci .ivsize = 8, 41268c2ecf20Sopenharmony_ci .maxauthsize = GHASH_DIGEST_SIZE, 41278c2ecf20Sopenharmony_ci .setkey = chcr_aead_rfc4309_setkey, 41288c2ecf20Sopenharmony_ci .setauthsize = chcr_4106_4309_setauthsize, 41298c2ecf20Sopenharmony_ci } 41308c2ecf20Sopenharmony_ci }, 41318c2ecf20Sopenharmony_ci { 41328c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CBC_SHA, 41338c2ecf20Sopenharmony_ci .is_registered = 0, 41348c2ecf20Sopenharmony_ci .alg.aead = { 41358c2ecf20Sopenharmony_ci .base = { 41368c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(sha1),cbc(aes))", 41378c2ecf20Sopenharmony_ci .cra_driver_name = 41388c2ecf20Sopenharmony_ci "authenc-hmac-sha1-cbc-aes-chcr", 41398c2ecf20Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 41408c2ecf20Sopenharmony_ci .cra_priority = CHCR_AEAD_PRIORITY, 41418c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct chcr_context) + 41428c2ecf20Sopenharmony_ci sizeof(struct chcr_aead_ctx) + 41438c2ecf20Sopenharmony_ci sizeof(struct chcr_authenc_ctx), 41448c2ecf20Sopenharmony_ci 41458c2ecf20Sopenharmony_ci }, 41468c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 41478c2ecf20Sopenharmony_ci .maxauthsize = SHA1_DIGEST_SIZE, 41488c2ecf20Sopenharmony_ci .setkey = chcr_authenc_setkey, 41498c2ecf20Sopenharmony_ci .setauthsize = chcr_authenc_setauthsize, 41508c2ecf20Sopenharmony_ci } 41518c2ecf20Sopenharmony_ci }, 41528c2ecf20Sopenharmony_ci { 41538c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CBC_SHA, 41548c2ecf20Sopenharmony_ci .is_registered = 0, 41558c2ecf20Sopenharmony_ci .alg.aead = { 41568c2ecf20Sopenharmony_ci .base = { 41578c2ecf20Sopenharmony_ci 41588c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(sha256),cbc(aes))", 41598c2ecf20Sopenharmony_ci .cra_driver_name = 41608c2ecf20Sopenharmony_ci "authenc-hmac-sha256-cbc-aes-chcr", 41618c2ecf20Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 41628c2ecf20Sopenharmony_ci .cra_priority = CHCR_AEAD_PRIORITY, 41638c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct chcr_context) + 41648c2ecf20Sopenharmony_ci sizeof(struct chcr_aead_ctx) + 41658c2ecf20Sopenharmony_ci sizeof(struct chcr_authenc_ctx), 41668c2ecf20Sopenharmony_ci 41678c2ecf20Sopenharmony_ci }, 41688c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 41698c2ecf20Sopenharmony_ci .maxauthsize = SHA256_DIGEST_SIZE, 41708c2ecf20Sopenharmony_ci .setkey = chcr_authenc_setkey, 41718c2ecf20Sopenharmony_ci .setauthsize = chcr_authenc_setauthsize, 41728c2ecf20Sopenharmony_ci } 41738c2ecf20Sopenharmony_ci }, 41748c2ecf20Sopenharmony_ci { 41758c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CBC_SHA, 41768c2ecf20Sopenharmony_ci .is_registered = 0, 41778c2ecf20Sopenharmony_ci .alg.aead = { 41788c2ecf20Sopenharmony_ci .base = { 41798c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(sha224),cbc(aes))", 41808c2ecf20Sopenharmony_ci .cra_driver_name = 41818c2ecf20Sopenharmony_ci "authenc-hmac-sha224-cbc-aes-chcr", 41828c2ecf20Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 41838c2ecf20Sopenharmony_ci .cra_priority = CHCR_AEAD_PRIORITY, 41848c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct chcr_context) + 41858c2ecf20Sopenharmony_ci sizeof(struct chcr_aead_ctx) + 41868c2ecf20Sopenharmony_ci sizeof(struct chcr_authenc_ctx), 41878c2ecf20Sopenharmony_ci }, 41888c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 41898c2ecf20Sopenharmony_ci .maxauthsize = SHA224_DIGEST_SIZE, 41908c2ecf20Sopenharmony_ci .setkey = chcr_authenc_setkey, 41918c2ecf20Sopenharmony_ci .setauthsize = chcr_authenc_setauthsize, 41928c2ecf20Sopenharmony_ci } 41938c2ecf20Sopenharmony_ci }, 41948c2ecf20Sopenharmony_ci { 41958c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CBC_SHA, 41968c2ecf20Sopenharmony_ci .is_registered = 0, 41978c2ecf20Sopenharmony_ci .alg.aead = { 41988c2ecf20Sopenharmony_ci .base = { 41998c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(sha384),cbc(aes))", 42008c2ecf20Sopenharmony_ci .cra_driver_name = 42018c2ecf20Sopenharmony_ci "authenc-hmac-sha384-cbc-aes-chcr", 42028c2ecf20Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 42038c2ecf20Sopenharmony_ci .cra_priority = CHCR_AEAD_PRIORITY, 42048c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct chcr_context) + 42058c2ecf20Sopenharmony_ci sizeof(struct chcr_aead_ctx) + 42068c2ecf20Sopenharmony_ci sizeof(struct chcr_authenc_ctx), 42078c2ecf20Sopenharmony_ci 42088c2ecf20Sopenharmony_ci }, 42098c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 42108c2ecf20Sopenharmony_ci .maxauthsize = SHA384_DIGEST_SIZE, 42118c2ecf20Sopenharmony_ci .setkey = chcr_authenc_setkey, 42128c2ecf20Sopenharmony_ci .setauthsize = chcr_authenc_setauthsize, 42138c2ecf20Sopenharmony_ci } 42148c2ecf20Sopenharmony_ci }, 42158c2ecf20Sopenharmony_ci { 42168c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CBC_SHA, 42178c2ecf20Sopenharmony_ci .is_registered = 0, 42188c2ecf20Sopenharmony_ci .alg.aead = { 42198c2ecf20Sopenharmony_ci .base = { 42208c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(sha512),cbc(aes))", 42218c2ecf20Sopenharmony_ci .cra_driver_name = 42228c2ecf20Sopenharmony_ci "authenc-hmac-sha512-cbc-aes-chcr", 42238c2ecf20Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 42248c2ecf20Sopenharmony_ci .cra_priority = CHCR_AEAD_PRIORITY, 42258c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct chcr_context) + 42268c2ecf20Sopenharmony_ci sizeof(struct chcr_aead_ctx) + 42278c2ecf20Sopenharmony_ci sizeof(struct chcr_authenc_ctx), 42288c2ecf20Sopenharmony_ci 42298c2ecf20Sopenharmony_ci }, 42308c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 42318c2ecf20Sopenharmony_ci .maxauthsize = SHA512_DIGEST_SIZE, 42328c2ecf20Sopenharmony_ci .setkey = chcr_authenc_setkey, 42338c2ecf20Sopenharmony_ci .setauthsize = chcr_authenc_setauthsize, 42348c2ecf20Sopenharmony_ci } 42358c2ecf20Sopenharmony_ci }, 42368c2ecf20Sopenharmony_ci { 42378c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CBC_NULL, 42388c2ecf20Sopenharmony_ci .is_registered = 0, 42398c2ecf20Sopenharmony_ci .alg.aead = { 42408c2ecf20Sopenharmony_ci .base = { 42418c2ecf20Sopenharmony_ci .cra_name = "authenc(digest_null,cbc(aes))", 42428c2ecf20Sopenharmony_ci .cra_driver_name = 42438c2ecf20Sopenharmony_ci "authenc-digest_null-cbc-aes-chcr", 42448c2ecf20Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 42458c2ecf20Sopenharmony_ci .cra_priority = CHCR_AEAD_PRIORITY, 42468c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct chcr_context) + 42478c2ecf20Sopenharmony_ci sizeof(struct chcr_aead_ctx) + 42488c2ecf20Sopenharmony_ci sizeof(struct chcr_authenc_ctx), 42498c2ecf20Sopenharmony_ci 42508c2ecf20Sopenharmony_ci }, 42518c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 42528c2ecf20Sopenharmony_ci .maxauthsize = 0, 42538c2ecf20Sopenharmony_ci .setkey = chcr_aead_digest_null_setkey, 42548c2ecf20Sopenharmony_ci .setauthsize = chcr_authenc_null_setauthsize, 42558c2ecf20Sopenharmony_ci } 42568c2ecf20Sopenharmony_ci }, 42578c2ecf20Sopenharmony_ci { 42588c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CTR_SHA, 42598c2ecf20Sopenharmony_ci .is_registered = 0, 42608c2ecf20Sopenharmony_ci .alg.aead = { 42618c2ecf20Sopenharmony_ci .base = { 42628c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(sha1),rfc3686(ctr(aes)))", 42638c2ecf20Sopenharmony_ci .cra_driver_name = 42648c2ecf20Sopenharmony_ci "authenc-hmac-sha1-rfc3686-ctr-aes-chcr", 42658c2ecf20Sopenharmony_ci .cra_blocksize = 1, 42668c2ecf20Sopenharmony_ci .cra_priority = CHCR_AEAD_PRIORITY, 42678c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct chcr_context) + 42688c2ecf20Sopenharmony_ci sizeof(struct chcr_aead_ctx) + 42698c2ecf20Sopenharmony_ci sizeof(struct chcr_authenc_ctx), 42708c2ecf20Sopenharmony_ci 42718c2ecf20Sopenharmony_ci }, 42728c2ecf20Sopenharmony_ci .ivsize = CTR_RFC3686_IV_SIZE, 42738c2ecf20Sopenharmony_ci .maxauthsize = SHA1_DIGEST_SIZE, 42748c2ecf20Sopenharmony_ci .setkey = chcr_authenc_setkey, 42758c2ecf20Sopenharmony_ci .setauthsize = chcr_authenc_setauthsize, 42768c2ecf20Sopenharmony_ci } 42778c2ecf20Sopenharmony_ci }, 42788c2ecf20Sopenharmony_ci { 42798c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CTR_SHA, 42808c2ecf20Sopenharmony_ci .is_registered = 0, 42818c2ecf20Sopenharmony_ci .alg.aead = { 42828c2ecf20Sopenharmony_ci .base = { 42838c2ecf20Sopenharmony_ci 42848c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(sha256),rfc3686(ctr(aes)))", 42858c2ecf20Sopenharmony_ci .cra_driver_name = 42868c2ecf20Sopenharmony_ci "authenc-hmac-sha256-rfc3686-ctr-aes-chcr", 42878c2ecf20Sopenharmony_ci .cra_blocksize = 1, 42888c2ecf20Sopenharmony_ci .cra_priority = CHCR_AEAD_PRIORITY, 42898c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct chcr_context) + 42908c2ecf20Sopenharmony_ci sizeof(struct chcr_aead_ctx) + 42918c2ecf20Sopenharmony_ci sizeof(struct chcr_authenc_ctx), 42928c2ecf20Sopenharmony_ci 42938c2ecf20Sopenharmony_ci }, 42948c2ecf20Sopenharmony_ci .ivsize = CTR_RFC3686_IV_SIZE, 42958c2ecf20Sopenharmony_ci .maxauthsize = SHA256_DIGEST_SIZE, 42968c2ecf20Sopenharmony_ci .setkey = chcr_authenc_setkey, 42978c2ecf20Sopenharmony_ci .setauthsize = chcr_authenc_setauthsize, 42988c2ecf20Sopenharmony_ci } 42998c2ecf20Sopenharmony_ci }, 43008c2ecf20Sopenharmony_ci { 43018c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CTR_SHA, 43028c2ecf20Sopenharmony_ci .is_registered = 0, 43038c2ecf20Sopenharmony_ci .alg.aead = { 43048c2ecf20Sopenharmony_ci .base = { 43058c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(sha224),rfc3686(ctr(aes)))", 43068c2ecf20Sopenharmony_ci .cra_driver_name = 43078c2ecf20Sopenharmony_ci "authenc-hmac-sha224-rfc3686-ctr-aes-chcr", 43088c2ecf20Sopenharmony_ci .cra_blocksize = 1, 43098c2ecf20Sopenharmony_ci .cra_priority = CHCR_AEAD_PRIORITY, 43108c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct chcr_context) + 43118c2ecf20Sopenharmony_ci sizeof(struct chcr_aead_ctx) + 43128c2ecf20Sopenharmony_ci sizeof(struct chcr_authenc_ctx), 43138c2ecf20Sopenharmony_ci }, 43148c2ecf20Sopenharmony_ci .ivsize = CTR_RFC3686_IV_SIZE, 43158c2ecf20Sopenharmony_ci .maxauthsize = SHA224_DIGEST_SIZE, 43168c2ecf20Sopenharmony_ci .setkey = chcr_authenc_setkey, 43178c2ecf20Sopenharmony_ci .setauthsize = chcr_authenc_setauthsize, 43188c2ecf20Sopenharmony_ci } 43198c2ecf20Sopenharmony_ci }, 43208c2ecf20Sopenharmony_ci { 43218c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CTR_SHA, 43228c2ecf20Sopenharmony_ci .is_registered = 0, 43238c2ecf20Sopenharmony_ci .alg.aead = { 43248c2ecf20Sopenharmony_ci .base = { 43258c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(sha384),rfc3686(ctr(aes)))", 43268c2ecf20Sopenharmony_ci .cra_driver_name = 43278c2ecf20Sopenharmony_ci "authenc-hmac-sha384-rfc3686-ctr-aes-chcr", 43288c2ecf20Sopenharmony_ci .cra_blocksize = 1, 43298c2ecf20Sopenharmony_ci .cra_priority = CHCR_AEAD_PRIORITY, 43308c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct chcr_context) + 43318c2ecf20Sopenharmony_ci sizeof(struct chcr_aead_ctx) + 43328c2ecf20Sopenharmony_ci sizeof(struct chcr_authenc_ctx), 43338c2ecf20Sopenharmony_ci 43348c2ecf20Sopenharmony_ci }, 43358c2ecf20Sopenharmony_ci .ivsize = CTR_RFC3686_IV_SIZE, 43368c2ecf20Sopenharmony_ci .maxauthsize = SHA384_DIGEST_SIZE, 43378c2ecf20Sopenharmony_ci .setkey = chcr_authenc_setkey, 43388c2ecf20Sopenharmony_ci .setauthsize = chcr_authenc_setauthsize, 43398c2ecf20Sopenharmony_ci } 43408c2ecf20Sopenharmony_ci }, 43418c2ecf20Sopenharmony_ci { 43428c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CTR_SHA, 43438c2ecf20Sopenharmony_ci .is_registered = 0, 43448c2ecf20Sopenharmony_ci .alg.aead = { 43458c2ecf20Sopenharmony_ci .base = { 43468c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(sha512),rfc3686(ctr(aes)))", 43478c2ecf20Sopenharmony_ci .cra_driver_name = 43488c2ecf20Sopenharmony_ci "authenc-hmac-sha512-rfc3686-ctr-aes-chcr", 43498c2ecf20Sopenharmony_ci .cra_blocksize = 1, 43508c2ecf20Sopenharmony_ci .cra_priority = CHCR_AEAD_PRIORITY, 43518c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct chcr_context) + 43528c2ecf20Sopenharmony_ci sizeof(struct chcr_aead_ctx) + 43538c2ecf20Sopenharmony_ci sizeof(struct chcr_authenc_ctx), 43548c2ecf20Sopenharmony_ci 43558c2ecf20Sopenharmony_ci }, 43568c2ecf20Sopenharmony_ci .ivsize = CTR_RFC3686_IV_SIZE, 43578c2ecf20Sopenharmony_ci .maxauthsize = SHA512_DIGEST_SIZE, 43588c2ecf20Sopenharmony_ci .setkey = chcr_authenc_setkey, 43598c2ecf20Sopenharmony_ci .setauthsize = chcr_authenc_setauthsize, 43608c2ecf20Sopenharmony_ci } 43618c2ecf20Sopenharmony_ci }, 43628c2ecf20Sopenharmony_ci { 43638c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CTR_NULL, 43648c2ecf20Sopenharmony_ci .is_registered = 0, 43658c2ecf20Sopenharmony_ci .alg.aead = { 43668c2ecf20Sopenharmony_ci .base = { 43678c2ecf20Sopenharmony_ci .cra_name = "authenc(digest_null,rfc3686(ctr(aes)))", 43688c2ecf20Sopenharmony_ci .cra_driver_name = 43698c2ecf20Sopenharmony_ci "authenc-digest_null-rfc3686-ctr-aes-chcr", 43708c2ecf20Sopenharmony_ci .cra_blocksize = 1, 43718c2ecf20Sopenharmony_ci .cra_priority = CHCR_AEAD_PRIORITY, 43728c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct chcr_context) + 43738c2ecf20Sopenharmony_ci sizeof(struct chcr_aead_ctx) + 43748c2ecf20Sopenharmony_ci sizeof(struct chcr_authenc_ctx), 43758c2ecf20Sopenharmony_ci 43768c2ecf20Sopenharmony_ci }, 43778c2ecf20Sopenharmony_ci .ivsize = CTR_RFC3686_IV_SIZE, 43788c2ecf20Sopenharmony_ci .maxauthsize = 0, 43798c2ecf20Sopenharmony_ci .setkey = chcr_aead_digest_null_setkey, 43808c2ecf20Sopenharmony_ci .setauthsize = chcr_authenc_null_setauthsize, 43818c2ecf20Sopenharmony_ci } 43828c2ecf20Sopenharmony_ci }, 43838c2ecf20Sopenharmony_ci}; 43848c2ecf20Sopenharmony_ci 43858c2ecf20Sopenharmony_ci/* 43868c2ecf20Sopenharmony_ci * chcr_unregister_alg - Deregister crypto algorithms with 43878c2ecf20Sopenharmony_ci * kernel framework. 43888c2ecf20Sopenharmony_ci */ 43898c2ecf20Sopenharmony_cistatic int chcr_unregister_alg(void) 43908c2ecf20Sopenharmony_ci{ 43918c2ecf20Sopenharmony_ci int i; 43928c2ecf20Sopenharmony_ci 43938c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(driver_algs); i++) { 43948c2ecf20Sopenharmony_ci switch (driver_algs[i].type & CRYPTO_ALG_TYPE_MASK) { 43958c2ecf20Sopenharmony_ci case CRYPTO_ALG_TYPE_SKCIPHER: 43968c2ecf20Sopenharmony_ci if (driver_algs[i].is_registered && refcount_read( 43978c2ecf20Sopenharmony_ci &driver_algs[i].alg.skcipher.base.cra_refcnt) 43988c2ecf20Sopenharmony_ci == 1) { 43998c2ecf20Sopenharmony_ci crypto_unregister_skcipher( 44008c2ecf20Sopenharmony_ci &driver_algs[i].alg.skcipher); 44018c2ecf20Sopenharmony_ci driver_algs[i].is_registered = 0; 44028c2ecf20Sopenharmony_ci } 44038c2ecf20Sopenharmony_ci break; 44048c2ecf20Sopenharmony_ci case CRYPTO_ALG_TYPE_AEAD: 44058c2ecf20Sopenharmony_ci if (driver_algs[i].is_registered && refcount_read( 44068c2ecf20Sopenharmony_ci &driver_algs[i].alg.aead.base.cra_refcnt) == 1) { 44078c2ecf20Sopenharmony_ci crypto_unregister_aead( 44088c2ecf20Sopenharmony_ci &driver_algs[i].alg.aead); 44098c2ecf20Sopenharmony_ci driver_algs[i].is_registered = 0; 44108c2ecf20Sopenharmony_ci } 44118c2ecf20Sopenharmony_ci break; 44128c2ecf20Sopenharmony_ci case CRYPTO_ALG_TYPE_AHASH: 44138c2ecf20Sopenharmony_ci if (driver_algs[i].is_registered && refcount_read( 44148c2ecf20Sopenharmony_ci &driver_algs[i].alg.hash.halg.base.cra_refcnt) 44158c2ecf20Sopenharmony_ci == 1) { 44168c2ecf20Sopenharmony_ci crypto_unregister_ahash( 44178c2ecf20Sopenharmony_ci &driver_algs[i].alg.hash); 44188c2ecf20Sopenharmony_ci driver_algs[i].is_registered = 0; 44198c2ecf20Sopenharmony_ci } 44208c2ecf20Sopenharmony_ci break; 44218c2ecf20Sopenharmony_ci } 44228c2ecf20Sopenharmony_ci } 44238c2ecf20Sopenharmony_ci return 0; 44248c2ecf20Sopenharmony_ci} 44258c2ecf20Sopenharmony_ci 44268c2ecf20Sopenharmony_ci#define SZ_AHASH_CTX sizeof(struct chcr_context) 44278c2ecf20Sopenharmony_ci#define SZ_AHASH_H_CTX (sizeof(struct chcr_context) + sizeof(struct hmac_ctx)) 44288c2ecf20Sopenharmony_ci#define SZ_AHASH_REQ_CTX sizeof(struct chcr_ahash_req_ctx) 44298c2ecf20Sopenharmony_ci 44308c2ecf20Sopenharmony_ci/* 44318c2ecf20Sopenharmony_ci * chcr_register_alg - Register crypto algorithms with kernel framework. 44328c2ecf20Sopenharmony_ci */ 44338c2ecf20Sopenharmony_cistatic int chcr_register_alg(void) 44348c2ecf20Sopenharmony_ci{ 44358c2ecf20Sopenharmony_ci struct crypto_alg ai; 44368c2ecf20Sopenharmony_ci struct ahash_alg *a_hash; 44378c2ecf20Sopenharmony_ci int err = 0, i; 44388c2ecf20Sopenharmony_ci char *name = NULL; 44398c2ecf20Sopenharmony_ci 44408c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(driver_algs); i++) { 44418c2ecf20Sopenharmony_ci if (driver_algs[i].is_registered) 44428c2ecf20Sopenharmony_ci continue; 44438c2ecf20Sopenharmony_ci switch (driver_algs[i].type & CRYPTO_ALG_TYPE_MASK) { 44448c2ecf20Sopenharmony_ci case CRYPTO_ALG_TYPE_SKCIPHER: 44458c2ecf20Sopenharmony_ci driver_algs[i].alg.skcipher.base.cra_priority = 44468c2ecf20Sopenharmony_ci CHCR_CRA_PRIORITY; 44478c2ecf20Sopenharmony_ci driver_algs[i].alg.skcipher.base.cra_module = THIS_MODULE; 44488c2ecf20Sopenharmony_ci driver_algs[i].alg.skcipher.base.cra_flags = 44498c2ecf20Sopenharmony_ci CRYPTO_ALG_TYPE_SKCIPHER | CRYPTO_ALG_ASYNC | 44508c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 44518c2ecf20Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK; 44528c2ecf20Sopenharmony_ci driver_algs[i].alg.skcipher.base.cra_ctxsize = 44538c2ecf20Sopenharmony_ci sizeof(struct chcr_context) + 44548c2ecf20Sopenharmony_ci sizeof(struct ablk_ctx); 44558c2ecf20Sopenharmony_ci driver_algs[i].alg.skcipher.base.cra_alignmask = 0; 44568c2ecf20Sopenharmony_ci 44578c2ecf20Sopenharmony_ci err = crypto_register_skcipher(&driver_algs[i].alg.skcipher); 44588c2ecf20Sopenharmony_ci name = driver_algs[i].alg.skcipher.base.cra_driver_name; 44598c2ecf20Sopenharmony_ci break; 44608c2ecf20Sopenharmony_ci case CRYPTO_ALG_TYPE_AEAD: 44618c2ecf20Sopenharmony_ci driver_algs[i].alg.aead.base.cra_flags = 44628c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK | 44638c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY; 44648c2ecf20Sopenharmony_ci driver_algs[i].alg.aead.encrypt = chcr_aead_encrypt; 44658c2ecf20Sopenharmony_ci driver_algs[i].alg.aead.decrypt = chcr_aead_decrypt; 44668c2ecf20Sopenharmony_ci driver_algs[i].alg.aead.init = chcr_aead_cra_init; 44678c2ecf20Sopenharmony_ci driver_algs[i].alg.aead.exit = chcr_aead_cra_exit; 44688c2ecf20Sopenharmony_ci driver_algs[i].alg.aead.base.cra_module = THIS_MODULE; 44698c2ecf20Sopenharmony_ci err = crypto_register_aead(&driver_algs[i].alg.aead); 44708c2ecf20Sopenharmony_ci name = driver_algs[i].alg.aead.base.cra_driver_name; 44718c2ecf20Sopenharmony_ci break; 44728c2ecf20Sopenharmony_ci case CRYPTO_ALG_TYPE_AHASH: 44738c2ecf20Sopenharmony_ci a_hash = &driver_algs[i].alg.hash; 44748c2ecf20Sopenharmony_ci a_hash->update = chcr_ahash_update; 44758c2ecf20Sopenharmony_ci a_hash->final = chcr_ahash_final; 44768c2ecf20Sopenharmony_ci a_hash->finup = chcr_ahash_finup; 44778c2ecf20Sopenharmony_ci a_hash->digest = chcr_ahash_digest; 44788c2ecf20Sopenharmony_ci a_hash->export = chcr_ahash_export; 44798c2ecf20Sopenharmony_ci a_hash->import = chcr_ahash_import; 44808c2ecf20Sopenharmony_ci a_hash->halg.statesize = SZ_AHASH_REQ_CTX; 44818c2ecf20Sopenharmony_ci a_hash->halg.base.cra_priority = CHCR_CRA_PRIORITY; 44828c2ecf20Sopenharmony_ci a_hash->halg.base.cra_module = THIS_MODULE; 44838c2ecf20Sopenharmony_ci a_hash->halg.base.cra_flags = 44848c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY; 44858c2ecf20Sopenharmony_ci a_hash->halg.base.cra_alignmask = 0; 44868c2ecf20Sopenharmony_ci a_hash->halg.base.cra_exit = NULL; 44878c2ecf20Sopenharmony_ci 44888c2ecf20Sopenharmony_ci if (driver_algs[i].type == CRYPTO_ALG_TYPE_HMAC) { 44898c2ecf20Sopenharmony_ci a_hash->halg.base.cra_init = chcr_hmac_cra_init; 44908c2ecf20Sopenharmony_ci a_hash->halg.base.cra_exit = chcr_hmac_cra_exit; 44918c2ecf20Sopenharmony_ci a_hash->init = chcr_hmac_init; 44928c2ecf20Sopenharmony_ci a_hash->setkey = chcr_ahash_setkey; 44938c2ecf20Sopenharmony_ci a_hash->halg.base.cra_ctxsize = SZ_AHASH_H_CTX; 44948c2ecf20Sopenharmony_ci } else { 44958c2ecf20Sopenharmony_ci a_hash->init = chcr_sha_init; 44968c2ecf20Sopenharmony_ci a_hash->halg.base.cra_ctxsize = SZ_AHASH_CTX; 44978c2ecf20Sopenharmony_ci a_hash->halg.base.cra_init = chcr_sha_cra_init; 44988c2ecf20Sopenharmony_ci } 44998c2ecf20Sopenharmony_ci err = crypto_register_ahash(&driver_algs[i].alg.hash); 45008c2ecf20Sopenharmony_ci ai = driver_algs[i].alg.hash.halg.base; 45018c2ecf20Sopenharmony_ci name = ai.cra_driver_name; 45028c2ecf20Sopenharmony_ci break; 45038c2ecf20Sopenharmony_ci } 45048c2ecf20Sopenharmony_ci if (err) { 45058c2ecf20Sopenharmony_ci pr_err("%s : Algorithm registration failed\n", name); 45068c2ecf20Sopenharmony_ci goto register_err; 45078c2ecf20Sopenharmony_ci } else { 45088c2ecf20Sopenharmony_ci driver_algs[i].is_registered = 1; 45098c2ecf20Sopenharmony_ci } 45108c2ecf20Sopenharmony_ci } 45118c2ecf20Sopenharmony_ci return 0; 45128c2ecf20Sopenharmony_ci 45138c2ecf20Sopenharmony_ciregister_err: 45148c2ecf20Sopenharmony_ci chcr_unregister_alg(); 45158c2ecf20Sopenharmony_ci return err; 45168c2ecf20Sopenharmony_ci} 45178c2ecf20Sopenharmony_ci 45188c2ecf20Sopenharmony_ci/* 45198c2ecf20Sopenharmony_ci * start_crypto - Register the crypto algorithms. 45208c2ecf20Sopenharmony_ci * This should called once when the first device comesup. After this 45218c2ecf20Sopenharmony_ci * kernel will start calling driver APIs for crypto operations. 45228c2ecf20Sopenharmony_ci */ 45238c2ecf20Sopenharmony_ciint start_crypto(void) 45248c2ecf20Sopenharmony_ci{ 45258c2ecf20Sopenharmony_ci return chcr_register_alg(); 45268c2ecf20Sopenharmony_ci} 45278c2ecf20Sopenharmony_ci 45288c2ecf20Sopenharmony_ci/* 45298c2ecf20Sopenharmony_ci * stop_crypto - Deregister all the crypto algorithms with kernel. 45308c2ecf20Sopenharmony_ci * This should be called once when the last device goes down. After this 45318c2ecf20Sopenharmony_ci * kernel will not call the driver API for crypto operations. 45328c2ecf20Sopenharmony_ci */ 45338c2ecf20Sopenharmony_ciint stop_crypto(void) 45348c2ecf20Sopenharmony_ci{ 45358c2ecf20Sopenharmony_ci chcr_unregister_alg(); 45368c2ecf20Sopenharmony_ci return 0; 45378c2ecf20Sopenharmony_ci} 4538