162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * This file is part of the Chelsio T6 Crypto driver for Linux. 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (c) 2003-2016 Chelsio Communications, Inc. All rights reserved. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * This software is available to you under a choice of one of two 762306a36Sopenharmony_ci * licenses. You may choose to be licensed under the terms of the GNU 862306a36Sopenharmony_ci * General Public License (GPL) Version 2, available from the file 962306a36Sopenharmony_ci * COPYING in the main directory of this source tree, or the 1062306a36Sopenharmony_ci * OpenIB.org BSD license below: 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * Redistribution and use in source and binary forms, with or 1362306a36Sopenharmony_ci * without modification, are permitted provided that the following 1462306a36Sopenharmony_ci * conditions are met: 1562306a36Sopenharmony_ci * 1662306a36Sopenharmony_ci * - Redistributions of source code must retain the above 1762306a36Sopenharmony_ci * copyright notice, this list of conditions and the following 1862306a36Sopenharmony_ci * disclaimer. 1962306a36Sopenharmony_ci * 2062306a36Sopenharmony_ci * - Redistributions in binary form must reproduce the above 2162306a36Sopenharmony_ci * copyright notice, this list of conditions and the following 2262306a36Sopenharmony_ci * disclaimer in the documentation and/or other materials 2362306a36Sopenharmony_ci * provided with the distribution. 2462306a36Sopenharmony_ci * 2562306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 2662306a36Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 2762306a36Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 2862306a36Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 2962306a36Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 3062306a36Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 3162306a36Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 3262306a36Sopenharmony_ci * SOFTWARE. 3362306a36Sopenharmony_ci * 3462306a36Sopenharmony_ci * Written and Maintained by: 3562306a36Sopenharmony_ci * Manoj Malviya (manojmalviya@chelsio.com) 3662306a36Sopenharmony_ci * Atul Gupta (atul.gupta@chelsio.com) 3762306a36Sopenharmony_ci * Jitendra Lulla (jlulla@chelsio.com) 3862306a36Sopenharmony_ci * Yeshaswi M R Gowda (yeshaswi@chelsio.com) 3962306a36Sopenharmony_ci * Harsh Jain (harsh@chelsio.com) 4062306a36Sopenharmony_ci */ 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci#define pr_fmt(fmt) "chcr:" fmt 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci#include <linux/kernel.h> 4562306a36Sopenharmony_ci#include <linux/module.h> 4662306a36Sopenharmony_ci#include <linux/crypto.h> 4762306a36Sopenharmony_ci#include <linux/skbuff.h> 4862306a36Sopenharmony_ci#include <linux/rtnetlink.h> 4962306a36Sopenharmony_ci#include <linux/highmem.h> 5062306a36Sopenharmony_ci#include <linux/scatterlist.h> 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci#include <crypto/aes.h> 5362306a36Sopenharmony_ci#include <crypto/algapi.h> 5462306a36Sopenharmony_ci#include <crypto/hash.h> 5562306a36Sopenharmony_ci#include <crypto/gcm.h> 5662306a36Sopenharmony_ci#include <crypto/sha1.h> 5762306a36Sopenharmony_ci#include <crypto/sha2.h> 5862306a36Sopenharmony_ci#include <crypto/authenc.h> 5962306a36Sopenharmony_ci#include <crypto/ctr.h> 6062306a36Sopenharmony_ci#include <crypto/gf128mul.h> 6162306a36Sopenharmony_ci#include <crypto/internal/aead.h> 6262306a36Sopenharmony_ci#include <crypto/null.h> 6362306a36Sopenharmony_ci#include <crypto/internal/skcipher.h> 6462306a36Sopenharmony_ci#include <crypto/aead.h> 6562306a36Sopenharmony_ci#include <crypto/scatterwalk.h> 6662306a36Sopenharmony_ci#include <crypto/internal/hash.h> 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci#include "t4fw_api.h" 6962306a36Sopenharmony_ci#include "t4_msg.h" 7062306a36Sopenharmony_ci#include "chcr_core.h" 7162306a36Sopenharmony_ci#include "chcr_algo.h" 7262306a36Sopenharmony_ci#include "chcr_crypto.h" 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci#define IV AES_BLOCK_SIZE 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_cistatic unsigned int sgl_ent_len[] = { 7762306a36Sopenharmony_ci 0, 0, 16, 24, 40, 48, 64, 72, 88, 7862306a36Sopenharmony_ci 96, 112, 120, 136, 144, 160, 168, 184, 7962306a36Sopenharmony_ci 192, 208, 216, 232, 240, 256, 264, 280, 8062306a36Sopenharmony_ci 288, 304, 312, 328, 336, 352, 360, 376 8162306a36Sopenharmony_ci}; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_cistatic unsigned int dsgl_ent_len[] = { 8462306a36Sopenharmony_ci 0, 32, 32, 48, 48, 64, 64, 80, 80, 8562306a36Sopenharmony_ci 112, 112, 128, 128, 144, 144, 160, 160, 8662306a36Sopenharmony_ci 192, 192, 208, 208, 224, 224, 240, 240, 8762306a36Sopenharmony_ci 272, 272, 288, 288, 304, 304, 320, 320 8862306a36Sopenharmony_ci}; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_cistatic u32 round_constant[11] = { 9162306a36Sopenharmony_ci 0x01000000, 0x02000000, 0x04000000, 0x08000000, 9262306a36Sopenharmony_ci 0x10000000, 0x20000000, 0x40000000, 0x80000000, 9362306a36Sopenharmony_ci 0x1B000000, 0x36000000, 0x6C000000 9462306a36Sopenharmony_ci}; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_cistatic int chcr_handle_cipher_resp(struct skcipher_request *req, 9762306a36Sopenharmony_ci unsigned char *input, int err); 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_cistatic inline struct chcr_aead_ctx *AEAD_CTX(struct chcr_context *ctx) 10062306a36Sopenharmony_ci{ 10162306a36Sopenharmony_ci return &ctx->crypto_ctx->aeadctx; 10262306a36Sopenharmony_ci} 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_cistatic inline struct ablk_ctx *ABLK_CTX(struct chcr_context *ctx) 10562306a36Sopenharmony_ci{ 10662306a36Sopenharmony_ci return &ctx->crypto_ctx->ablkctx; 10762306a36Sopenharmony_ci} 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_cistatic inline struct hmac_ctx *HMAC_CTX(struct chcr_context *ctx) 11062306a36Sopenharmony_ci{ 11162306a36Sopenharmony_ci return &ctx->crypto_ctx->hmacctx; 11262306a36Sopenharmony_ci} 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_cistatic inline struct chcr_gcm_ctx *GCM_CTX(struct chcr_aead_ctx *gctx) 11562306a36Sopenharmony_ci{ 11662306a36Sopenharmony_ci return gctx->ctx->gcm; 11762306a36Sopenharmony_ci} 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_cistatic inline struct chcr_authenc_ctx *AUTHENC_CTX(struct chcr_aead_ctx *gctx) 12062306a36Sopenharmony_ci{ 12162306a36Sopenharmony_ci return gctx->ctx->authenc; 12262306a36Sopenharmony_ci} 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_cistatic inline struct uld_ctx *ULD_CTX(struct chcr_context *ctx) 12562306a36Sopenharmony_ci{ 12662306a36Sopenharmony_ci return container_of(ctx->dev, struct uld_ctx, dev); 12762306a36Sopenharmony_ci} 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_cistatic inline void chcr_init_hctx_per_wr(struct chcr_ahash_req_ctx *reqctx) 13062306a36Sopenharmony_ci{ 13162306a36Sopenharmony_ci memset(&reqctx->hctx_wr, 0, sizeof(struct chcr_hctx_per_wr)); 13262306a36Sopenharmony_ci} 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_cistatic int sg_nents_xlen(struct scatterlist *sg, unsigned int reqlen, 13562306a36Sopenharmony_ci unsigned int entlen, 13662306a36Sopenharmony_ci unsigned int skip) 13762306a36Sopenharmony_ci{ 13862306a36Sopenharmony_ci int nents = 0; 13962306a36Sopenharmony_ci unsigned int less; 14062306a36Sopenharmony_ci unsigned int skip_len = 0; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci while (sg && skip) { 14362306a36Sopenharmony_ci if (sg_dma_len(sg) <= skip) { 14462306a36Sopenharmony_ci skip -= sg_dma_len(sg); 14562306a36Sopenharmony_ci skip_len = 0; 14662306a36Sopenharmony_ci sg = sg_next(sg); 14762306a36Sopenharmony_ci } else { 14862306a36Sopenharmony_ci skip_len = skip; 14962306a36Sopenharmony_ci skip = 0; 15062306a36Sopenharmony_ci } 15162306a36Sopenharmony_ci } 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci while (sg && reqlen) { 15462306a36Sopenharmony_ci less = min(reqlen, sg_dma_len(sg) - skip_len); 15562306a36Sopenharmony_ci nents += DIV_ROUND_UP(less, entlen); 15662306a36Sopenharmony_ci reqlen -= less; 15762306a36Sopenharmony_ci skip_len = 0; 15862306a36Sopenharmony_ci sg = sg_next(sg); 15962306a36Sopenharmony_ci } 16062306a36Sopenharmony_ci return nents; 16162306a36Sopenharmony_ci} 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_cistatic inline int get_aead_subtype(struct crypto_aead *aead) 16462306a36Sopenharmony_ci{ 16562306a36Sopenharmony_ci struct aead_alg *alg = crypto_aead_alg(aead); 16662306a36Sopenharmony_ci struct chcr_alg_template *chcr_crypto_alg = 16762306a36Sopenharmony_ci container_of(alg, struct chcr_alg_template, alg.aead); 16862306a36Sopenharmony_ci return chcr_crypto_alg->type & CRYPTO_ALG_SUB_TYPE_MASK; 16962306a36Sopenharmony_ci} 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_civoid chcr_verify_tag(struct aead_request *req, u8 *input, int *err) 17262306a36Sopenharmony_ci{ 17362306a36Sopenharmony_ci u8 temp[SHA512_DIGEST_SIZE]; 17462306a36Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 17562306a36Sopenharmony_ci int authsize = crypto_aead_authsize(tfm); 17662306a36Sopenharmony_ci struct cpl_fw6_pld *fw6_pld; 17762306a36Sopenharmony_ci int cmp = 0; 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci fw6_pld = (struct cpl_fw6_pld *)input; 18062306a36Sopenharmony_ci if ((get_aead_subtype(tfm) == CRYPTO_ALG_SUB_TYPE_AEAD_RFC4106) || 18162306a36Sopenharmony_ci (get_aead_subtype(tfm) == CRYPTO_ALG_SUB_TYPE_AEAD_GCM)) { 18262306a36Sopenharmony_ci cmp = crypto_memneq(&fw6_pld->data[2], (fw6_pld + 1), authsize); 18362306a36Sopenharmony_ci } else { 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci sg_pcopy_to_buffer(req->src, sg_nents(req->src), temp, 18662306a36Sopenharmony_ci authsize, req->assoclen + 18762306a36Sopenharmony_ci req->cryptlen - authsize); 18862306a36Sopenharmony_ci cmp = crypto_memneq(temp, (fw6_pld + 1), authsize); 18962306a36Sopenharmony_ci } 19062306a36Sopenharmony_ci if (cmp) 19162306a36Sopenharmony_ci *err = -EBADMSG; 19262306a36Sopenharmony_ci else 19362306a36Sopenharmony_ci *err = 0; 19462306a36Sopenharmony_ci} 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_cistatic int chcr_inc_wrcount(struct chcr_dev *dev) 19762306a36Sopenharmony_ci{ 19862306a36Sopenharmony_ci if (dev->state == CHCR_DETACH) 19962306a36Sopenharmony_ci return 1; 20062306a36Sopenharmony_ci atomic_inc(&dev->inflight); 20162306a36Sopenharmony_ci return 0; 20262306a36Sopenharmony_ci} 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_cistatic inline void chcr_dec_wrcount(struct chcr_dev *dev) 20562306a36Sopenharmony_ci{ 20662306a36Sopenharmony_ci atomic_dec(&dev->inflight); 20762306a36Sopenharmony_ci} 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_cistatic inline int chcr_handle_aead_resp(struct aead_request *req, 21062306a36Sopenharmony_ci unsigned char *input, 21162306a36Sopenharmony_ci int err) 21262306a36Sopenharmony_ci{ 21362306a36Sopenharmony_ci struct chcr_aead_reqctx *reqctx = aead_request_ctx_dma(req); 21462306a36Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 21562306a36Sopenharmony_ci struct chcr_dev *dev = a_ctx(tfm)->dev; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci chcr_aead_common_exit(req); 21862306a36Sopenharmony_ci if (reqctx->verify == VERIFY_SW) { 21962306a36Sopenharmony_ci chcr_verify_tag(req, input, &err); 22062306a36Sopenharmony_ci reqctx->verify = VERIFY_HW; 22162306a36Sopenharmony_ci } 22262306a36Sopenharmony_ci chcr_dec_wrcount(dev); 22362306a36Sopenharmony_ci aead_request_complete(req, err); 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci return err; 22662306a36Sopenharmony_ci} 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_cistatic void get_aes_decrypt_key(unsigned char *dec_key, 22962306a36Sopenharmony_ci const unsigned char *key, 23062306a36Sopenharmony_ci unsigned int keylength) 23162306a36Sopenharmony_ci{ 23262306a36Sopenharmony_ci u32 temp; 23362306a36Sopenharmony_ci u32 w_ring[MAX_NK]; 23462306a36Sopenharmony_ci int i, j, k; 23562306a36Sopenharmony_ci u8 nr, nk; 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci switch (keylength) { 23862306a36Sopenharmony_ci case AES_KEYLENGTH_128BIT: 23962306a36Sopenharmony_ci nk = KEYLENGTH_4BYTES; 24062306a36Sopenharmony_ci nr = NUMBER_OF_ROUNDS_10; 24162306a36Sopenharmony_ci break; 24262306a36Sopenharmony_ci case AES_KEYLENGTH_192BIT: 24362306a36Sopenharmony_ci nk = KEYLENGTH_6BYTES; 24462306a36Sopenharmony_ci nr = NUMBER_OF_ROUNDS_12; 24562306a36Sopenharmony_ci break; 24662306a36Sopenharmony_ci case AES_KEYLENGTH_256BIT: 24762306a36Sopenharmony_ci nk = KEYLENGTH_8BYTES; 24862306a36Sopenharmony_ci nr = NUMBER_OF_ROUNDS_14; 24962306a36Sopenharmony_ci break; 25062306a36Sopenharmony_ci default: 25162306a36Sopenharmony_ci return; 25262306a36Sopenharmony_ci } 25362306a36Sopenharmony_ci for (i = 0; i < nk; i++) 25462306a36Sopenharmony_ci w_ring[i] = get_unaligned_be32(&key[i * 4]); 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci i = 0; 25762306a36Sopenharmony_ci temp = w_ring[nk - 1]; 25862306a36Sopenharmony_ci while (i + nk < (nr + 1) * 4) { 25962306a36Sopenharmony_ci if (!(i % nk)) { 26062306a36Sopenharmony_ci /* RotWord(temp) */ 26162306a36Sopenharmony_ci temp = (temp << 8) | (temp >> 24); 26262306a36Sopenharmony_ci temp = aes_ks_subword(temp); 26362306a36Sopenharmony_ci temp ^= round_constant[i / nk]; 26462306a36Sopenharmony_ci } else if (nk == 8 && (i % 4 == 0)) { 26562306a36Sopenharmony_ci temp = aes_ks_subword(temp); 26662306a36Sopenharmony_ci } 26762306a36Sopenharmony_ci w_ring[i % nk] ^= temp; 26862306a36Sopenharmony_ci temp = w_ring[i % nk]; 26962306a36Sopenharmony_ci i++; 27062306a36Sopenharmony_ci } 27162306a36Sopenharmony_ci i--; 27262306a36Sopenharmony_ci for (k = 0, j = i % nk; k < nk; k++) { 27362306a36Sopenharmony_ci put_unaligned_be32(w_ring[j], &dec_key[k * 4]); 27462306a36Sopenharmony_ci j--; 27562306a36Sopenharmony_ci if (j < 0) 27662306a36Sopenharmony_ci j += nk; 27762306a36Sopenharmony_ci } 27862306a36Sopenharmony_ci} 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_cistatic struct crypto_shash *chcr_alloc_shash(unsigned int ds) 28162306a36Sopenharmony_ci{ 28262306a36Sopenharmony_ci struct crypto_shash *base_hash = ERR_PTR(-EINVAL); 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci switch (ds) { 28562306a36Sopenharmony_ci case SHA1_DIGEST_SIZE: 28662306a36Sopenharmony_ci base_hash = crypto_alloc_shash("sha1", 0, 0); 28762306a36Sopenharmony_ci break; 28862306a36Sopenharmony_ci case SHA224_DIGEST_SIZE: 28962306a36Sopenharmony_ci base_hash = crypto_alloc_shash("sha224", 0, 0); 29062306a36Sopenharmony_ci break; 29162306a36Sopenharmony_ci case SHA256_DIGEST_SIZE: 29262306a36Sopenharmony_ci base_hash = crypto_alloc_shash("sha256", 0, 0); 29362306a36Sopenharmony_ci break; 29462306a36Sopenharmony_ci case SHA384_DIGEST_SIZE: 29562306a36Sopenharmony_ci base_hash = crypto_alloc_shash("sha384", 0, 0); 29662306a36Sopenharmony_ci break; 29762306a36Sopenharmony_ci case SHA512_DIGEST_SIZE: 29862306a36Sopenharmony_ci base_hash = crypto_alloc_shash("sha512", 0, 0); 29962306a36Sopenharmony_ci break; 30062306a36Sopenharmony_ci } 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci return base_hash; 30362306a36Sopenharmony_ci} 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_cistatic int chcr_compute_partial_hash(struct shash_desc *desc, 30662306a36Sopenharmony_ci char *iopad, char *result_hash, 30762306a36Sopenharmony_ci int digest_size) 30862306a36Sopenharmony_ci{ 30962306a36Sopenharmony_ci struct sha1_state sha1_st; 31062306a36Sopenharmony_ci struct sha256_state sha256_st; 31162306a36Sopenharmony_ci struct sha512_state sha512_st; 31262306a36Sopenharmony_ci int error; 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci if (digest_size == SHA1_DIGEST_SIZE) { 31562306a36Sopenharmony_ci error = crypto_shash_init(desc) ?: 31662306a36Sopenharmony_ci crypto_shash_update(desc, iopad, SHA1_BLOCK_SIZE) ?: 31762306a36Sopenharmony_ci crypto_shash_export(desc, (void *)&sha1_st); 31862306a36Sopenharmony_ci memcpy(result_hash, sha1_st.state, SHA1_DIGEST_SIZE); 31962306a36Sopenharmony_ci } else if (digest_size == SHA224_DIGEST_SIZE) { 32062306a36Sopenharmony_ci error = crypto_shash_init(desc) ?: 32162306a36Sopenharmony_ci crypto_shash_update(desc, iopad, SHA256_BLOCK_SIZE) ?: 32262306a36Sopenharmony_ci crypto_shash_export(desc, (void *)&sha256_st); 32362306a36Sopenharmony_ci memcpy(result_hash, sha256_st.state, SHA256_DIGEST_SIZE); 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci } else if (digest_size == SHA256_DIGEST_SIZE) { 32662306a36Sopenharmony_ci error = crypto_shash_init(desc) ?: 32762306a36Sopenharmony_ci crypto_shash_update(desc, iopad, SHA256_BLOCK_SIZE) ?: 32862306a36Sopenharmony_ci crypto_shash_export(desc, (void *)&sha256_st); 32962306a36Sopenharmony_ci memcpy(result_hash, sha256_st.state, SHA256_DIGEST_SIZE); 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci } else if (digest_size == SHA384_DIGEST_SIZE) { 33262306a36Sopenharmony_ci error = crypto_shash_init(desc) ?: 33362306a36Sopenharmony_ci crypto_shash_update(desc, iopad, SHA512_BLOCK_SIZE) ?: 33462306a36Sopenharmony_ci crypto_shash_export(desc, (void *)&sha512_st); 33562306a36Sopenharmony_ci memcpy(result_hash, sha512_st.state, SHA512_DIGEST_SIZE); 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci } else if (digest_size == SHA512_DIGEST_SIZE) { 33862306a36Sopenharmony_ci error = crypto_shash_init(desc) ?: 33962306a36Sopenharmony_ci crypto_shash_update(desc, iopad, SHA512_BLOCK_SIZE) ?: 34062306a36Sopenharmony_ci crypto_shash_export(desc, (void *)&sha512_st); 34162306a36Sopenharmony_ci memcpy(result_hash, sha512_st.state, SHA512_DIGEST_SIZE); 34262306a36Sopenharmony_ci } else { 34362306a36Sopenharmony_ci error = -EINVAL; 34462306a36Sopenharmony_ci pr_err("Unknown digest size %d\n", digest_size); 34562306a36Sopenharmony_ci } 34662306a36Sopenharmony_ci return error; 34762306a36Sopenharmony_ci} 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_cistatic void chcr_change_order(char *buf, int ds) 35062306a36Sopenharmony_ci{ 35162306a36Sopenharmony_ci int i; 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci if (ds == SHA512_DIGEST_SIZE) { 35462306a36Sopenharmony_ci for (i = 0; i < (ds / sizeof(u64)); i++) 35562306a36Sopenharmony_ci *((__be64 *)buf + i) = 35662306a36Sopenharmony_ci cpu_to_be64(*((u64 *)buf + i)); 35762306a36Sopenharmony_ci } else { 35862306a36Sopenharmony_ci for (i = 0; i < (ds / sizeof(u32)); i++) 35962306a36Sopenharmony_ci *((__be32 *)buf + i) = 36062306a36Sopenharmony_ci cpu_to_be32(*((u32 *)buf + i)); 36162306a36Sopenharmony_ci } 36262306a36Sopenharmony_ci} 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_cistatic inline int is_hmac(struct crypto_tfm *tfm) 36562306a36Sopenharmony_ci{ 36662306a36Sopenharmony_ci struct crypto_alg *alg = tfm->__crt_alg; 36762306a36Sopenharmony_ci struct chcr_alg_template *chcr_crypto_alg = 36862306a36Sopenharmony_ci container_of(__crypto_ahash_alg(alg), struct chcr_alg_template, 36962306a36Sopenharmony_ci alg.hash); 37062306a36Sopenharmony_ci if (chcr_crypto_alg->type == CRYPTO_ALG_TYPE_HMAC) 37162306a36Sopenharmony_ci return 1; 37262306a36Sopenharmony_ci return 0; 37362306a36Sopenharmony_ci} 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_cistatic inline void dsgl_walk_init(struct dsgl_walk *walk, 37662306a36Sopenharmony_ci struct cpl_rx_phys_dsgl *dsgl) 37762306a36Sopenharmony_ci{ 37862306a36Sopenharmony_ci walk->dsgl = dsgl; 37962306a36Sopenharmony_ci walk->nents = 0; 38062306a36Sopenharmony_ci walk->to = (struct phys_sge_pairs *)(dsgl + 1); 38162306a36Sopenharmony_ci} 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_cistatic inline void dsgl_walk_end(struct dsgl_walk *walk, unsigned short qid, 38462306a36Sopenharmony_ci int pci_chan_id) 38562306a36Sopenharmony_ci{ 38662306a36Sopenharmony_ci struct cpl_rx_phys_dsgl *phys_cpl; 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci phys_cpl = walk->dsgl; 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci phys_cpl->op_to_tid = htonl(CPL_RX_PHYS_DSGL_OPCODE_V(CPL_RX_PHYS_DSGL) 39162306a36Sopenharmony_ci | CPL_RX_PHYS_DSGL_ISRDMA_V(0)); 39262306a36Sopenharmony_ci phys_cpl->pcirlxorder_to_noofsgentr = 39362306a36Sopenharmony_ci htonl(CPL_RX_PHYS_DSGL_PCIRLXORDER_V(0) | 39462306a36Sopenharmony_ci CPL_RX_PHYS_DSGL_PCINOSNOOP_V(0) | 39562306a36Sopenharmony_ci CPL_RX_PHYS_DSGL_PCITPHNTENB_V(0) | 39662306a36Sopenharmony_ci CPL_RX_PHYS_DSGL_PCITPHNT_V(0) | 39762306a36Sopenharmony_ci CPL_RX_PHYS_DSGL_DCAID_V(0) | 39862306a36Sopenharmony_ci CPL_RX_PHYS_DSGL_NOOFSGENTR_V(walk->nents)); 39962306a36Sopenharmony_ci phys_cpl->rss_hdr_int.opcode = CPL_RX_PHYS_ADDR; 40062306a36Sopenharmony_ci phys_cpl->rss_hdr_int.qid = htons(qid); 40162306a36Sopenharmony_ci phys_cpl->rss_hdr_int.hash_val = 0; 40262306a36Sopenharmony_ci phys_cpl->rss_hdr_int.channel = pci_chan_id; 40362306a36Sopenharmony_ci} 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_cistatic inline void dsgl_walk_add_page(struct dsgl_walk *walk, 40662306a36Sopenharmony_ci size_t size, 40762306a36Sopenharmony_ci dma_addr_t addr) 40862306a36Sopenharmony_ci{ 40962306a36Sopenharmony_ci int j; 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci if (!size) 41262306a36Sopenharmony_ci return; 41362306a36Sopenharmony_ci j = walk->nents; 41462306a36Sopenharmony_ci walk->to->len[j % 8] = htons(size); 41562306a36Sopenharmony_ci walk->to->addr[j % 8] = cpu_to_be64(addr); 41662306a36Sopenharmony_ci j++; 41762306a36Sopenharmony_ci if ((j % 8) == 0) 41862306a36Sopenharmony_ci walk->to++; 41962306a36Sopenharmony_ci walk->nents = j; 42062306a36Sopenharmony_ci} 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_cistatic void dsgl_walk_add_sg(struct dsgl_walk *walk, 42362306a36Sopenharmony_ci struct scatterlist *sg, 42462306a36Sopenharmony_ci unsigned int slen, 42562306a36Sopenharmony_ci unsigned int skip) 42662306a36Sopenharmony_ci{ 42762306a36Sopenharmony_ci int skip_len = 0; 42862306a36Sopenharmony_ci unsigned int left_size = slen, len = 0; 42962306a36Sopenharmony_ci unsigned int j = walk->nents; 43062306a36Sopenharmony_ci int offset, ent_len; 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci if (!slen) 43362306a36Sopenharmony_ci return; 43462306a36Sopenharmony_ci while (sg && skip) { 43562306a36Sopenharmony_ci if (sg_dma_len(sg) <= skip) { 43662306a36Sopenharmony_ci skip -= sg_dma_len(sg); 43762306a36Sopenharmony_ci skip_len = 0; 43862306a36Sopenharmony_ci sg = sg_next(sg); 43962306a36Sopenharmony_ci } else { 44062306a36Sopenharmony_ci skip_len = skip; 44162306a36Sopenharmony_ci skip = 0; 44262306a36Sopenharmony_ci } 44362306a36Sopenharmony_ci } 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci while (left_size && sg) { 44662306a36Sopenharmony_ci len = min_t(u32, left_size, sg_dma_len(sg) - skip_len); 44762306a36Sopenharmony_ci offset = 0; 44862306a36Sopenharmony_ci while (len) { 44962306a36Sopenharmony_ci ent_len = min_t(u32, len, CHCR_DST_SG_SIZE); 45062306a36Sopenharmony_ci walk->to->len[j % 8] = htons(ent_len); 45162306a36Sopenharmony_ci walk->to->addr[j % 8] = cpu_to_be64(sg_dma_address(sg) + 45262306a36Sopenharmony_ci offset + skip_len); 45362306a36Sopenharmony_ci offset += ent_len; 45462306a36Sopenharmony_ci len -= ent_len; 45562306a36Sopenharmony_ci j++; 45662306a36Sopenharmony_ci if ((j % 8) == 0) 45762306a36Sopenharmony_ci walk->to++; 45862306a36Sopenharmony_ci } 45962306a36Sopenharmony_ci walk->last_sg = sg; 46062306a36Sopenharmony_ci walk->last_sg_len = min_t(u32, left_size, sg_dma_len(sg) - 46162306a36Sopenharmony_ci skip_len) + skip_len; 46262306a36Sopenharmony_ci left_size -= min_t(u32, left_size, sg_dma_len(sg) - skip_len); 46362306a36Sopenharmony_ci skip_len = 0; 46462306a36Sopenharmony_ci sg = sg_next(sg); 46562306a36Sopenharmony_ci } 46662306a36Sopenharmony_ci walk->nents = j; 46762306a36Sopenharmony_ci} 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_cistatic inline void ulptx_walk_init(struct ulptx_walk *walk, 47062306a36Sopenharmony_ci struct ulptx_sgl *ulp) 47162306a36Sopenharmony_ci{ 47262306a36Sopenharmony_ci walk->sgl = ulp; 47362306a36Sopenharmony_ci walk->nents = 0; 47462306a36Sopenharmony_ci walk->pair_idx = 0; 47562306a36Sopenharmony_ci walk->pair = ulp->sge; 47662306a36Sopenharmony_ci walk->last_sg = NULL; 47762306a36Sopenharmony_ci walk->last_sg_len = 0; 47862306a36Sopenharmony_ci} 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_cistatic inline void ulptx_walk_end(struct ulptx_walk *walk) 48162306a36Sopenharmony_ci{ 48262306a36Sopenharmony_ci walk->sgl->cmd_nsge = htonl(ULPTX_CMD_V(ULP_TX_SC_DSGL) | 48362306a36Sopenharmony_ci ULPTX_NSGE_V(walk->nents)); 48462306a36Sopenharmony_ci} 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_cistatic inline void ulptx_walk_add_page(struct ulptx_walk *walk, 48862306a36Sopenharmony_ci size_t size, 48962306a36Sopenharmony_ci dma_addr_t addr) 49062306a36Sopenharmony_ci{ 49162306a36Sopenharmony_ci if (!size) 49262306a36Sopenharmony_ci return; 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci if (walk->nents == 0) { 49562306a36Sopenharmony_ci walk->sgl->len0 = cpu_to_be32(size); 49662306a36Sopenharmony_ci walk->sgl->addr0 = cpu_to_be64(addr); 49762306a36Sopenharmony_ci } else { 49862306a36Sopenharmony_ci walk->pair->addr[walk->pair_idx] = cpu_to_be64(addr); 49962306a36Sopenharmony_ci walk->pair->len[walk->pair_idx] = cpu_to_be32(size); 50062306a36Sopenharmony_ci walk->pair_idx = !walk->pair_idx; 50162306a36Sopenharmony_ci if (!walk->pair_idx) 50262306a36Sopenharmony_ci walk->pair++; 50362306a36Sopenharmony_ci } 50462306a36Sopenharmony_ci walk->nents++; 50562306a36Sopenharmony_ci} 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_cistatic void ulptx_walk_add_sg(struct ulptx_walk *walk, 50862306a36Sopenharmony_ci struct scatterlist *sg, 50962306a36Sopenharmony_ci unsigned int len, 51062306a36Sopenharmony_ci unsigned int skip) 51162306a36Sopenharmony_ci{ 51262306a36Sopenharmony_ci int small; 51362306a36Sopenharmony_ci int skip_len = 0; 51462306a36Sopenharmony_ci unsigned int sgmin; 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci if (!len) 51762306a36Sopenharmony_ci return; 51862306a36Sopenharmony_ci while (sg && skip) { 51962306a36Sopenharmony_ci if (sg_dma_len(sg) <= skip) { 52062306a36Sopenharmony_ci skip -= sg_dma_len(sg); 52162306a36Sopenharmony_ci skip_len = 0; 52262306a36Sopenharmony_ci sg = sg_next(sg); 52362306a36Sopenharmony_ci } else { 52462306a36Sopenharmony_ci skip_len = skip; 52562306a36Sopenharmony_ci skip = 0; 52662306a36Sopenharmony_ci } 52762306a36Sopenharmony_ci } 52862306a36Sopenharmony_ci WARN(!sg, "SG should not be null here\n"); 52962306a36Sopenharmony_ci if (sg && (walk->nents == 0)) { 53062306a36Sopenharmony_ci small = min_t(unsigned int, sg_dma_len(sg) - skip_len, len); 53162306a36Sopenharmony_ci sgmin = min_t(unsigned int, small, CHCR_SRC_SG_SIZE); 53262306a36Sopenharmony_ci walk->sgl->len0 = cpu_to_be32(sgmin); 53362306a36Sopenharmony_ci walk->sgl->addr0 = cpu_to_be64(sg_dma_address(sg) + skip_len); 53462306a36Sopenharmony_ci walk->nents++; 53562306a36Sopenharmony_ci len -= sgmin; 53662306a36Sopenharmony_ci walk->last_sg = sg; 53762306a36Sopenharmony_ci walk->last_sg_len = sgmin + skip_len; 53862306a36Sopenharmony_ci skip_len += sgmin; 53962306a36Sopenharmony_ci if (sg_dma_len(sg) == skip_len) { 54062306a36Sopenharmony_ci sg = sg_next(sg); 54162306a36Sopenharmony_ci skip_len = 0; 54262306a36Sopenharmony_ci } 54362306a36Sopenharmony_ci } 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci while (sg && len) { 54662306a36Sopenharmony_ci small = min(sg_dma_len(sg) - skip_len, len); 54762306a36Sopenharmony_ci sgmin = min_t(unsigned int, small, CHCR_SRC_SG_SIZE); 54862306a36Sopenharmony_ci walk->pair->len[walk->pair_idx] = cpu_to_be32(sgmin); 54962306a36Sopenharmony_ci walk->pair->addr[walk->pair_idx] = 55062306a36Sopenharmony_ci cpu_to_be64(sg_dma_address(sg) + skip_len); 55162306a36Sopenharmony_ci walk->pair_idx = !walk->pair_idx; 55262306a36Sopenharmony_ci walk->nents++; 55362306a36Sopenharmony_ci if (!walk->pair_idx) 55462306a36Sopenharmony_ci walk->pair++; 55562306a36Sopenharmony_ci len -= sgmin; 55662306a36Sopenharmony_ci skip_len += sgmin; 55762306a36Sopenharmony_ci walk->last_sg = sg; 55862306a36Sopenharmony_ci walk->last_sg_len = skip_len; 55962306a36Sopenharmony_ci if (sg_dma_len(sg) == skip_len) { 56062306a36Sopenharmony_ci sg = sg_next(sg); 56162306a36Sopenharmony_ci skip_len = 0; 56262306a36Sopenharmony_ci } 56362306a36Sopenharmony_ci } 56462306a36Sopenharmony_ci} 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_cistatic inline int get_cryptoalg_subtype(struct crypto_skcipher *tfm) 56762306a36Sopenharmony_ci{ 56862306a36Sopenharmony_ci struct skcipher_alg *alg = crypto_skcipher_alg(tfm); 56962306a36Sopenharmony_ci struct chcr_alg_template *chcr_crypto_alg = 57062306a36Sopenharmony_ci container_of(alg, struct chcr_alg_template, alg.skcipher); 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci return chcr_crypto_alg->type & CRYPTO_ALG_SUB_TYPE_MASK; 57362306a36Sopenharmony_ci} 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_cistatic int cxgb4_is_crypto_q_full(struct net_device *dev, unsigned int idx) 57662306a36Sopenharmony_ci{ 57762306a36Sopenharmony_ci struct adapter *adap = netdev2adap(dev); 57862306a36Sopenharmony_ci struct sge_uld_txq_info *txq_info = 57962306a36Sopenharmony_ci adap->sge.uld_txq_info[CXGB4_TX_CRYPTO]; 58062306a36Sopenharmony_ci struct sge_uld_txq *txq; 58162306a36Sopenharmony_ci int ret = 0; 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_ci local_bh_disable(); 58462306a36Sopenharmony_ci txq = &txq_info->uldtxq[idx]; 58562306a36Sopenharmony_ci spin_lock(&txq->sendq.lock); 58662306a36Sopenharmony_ci if (txq->full) 58762306a36Sopenharmony_ci ret = -1; 58862306a36Sopenharmony_ci spin_unlock(&txq->sendq.lock); 58962306a36Sopenharmony_ci local_bh_enable(); 59062306a36Sopenharmony_ci return ret; 59162306a36Sopenharmony_ci} 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_cistatic int generate_copy_rrkey(struct ablk_ctx *ablkctx, 59462306a36Sopenharmony_ci struct _key_ctx *key_ctx) 59562306a36Sopenharmony_ci{ 59662306a36Sopenharmony_ci if (ablkctx->ciph_mode == CHCR_SCMD_CIPHER_MODE_AES_CBC) { 59762306a36Sopenharmony_ci memcpy(key_ctx->key, ablkctx->rrkey, ablkctx->enckey_len); 59862306a36Sopenharmony_ci } else { 59962306a36Sopenharmony_ci memcpy(key_ctx->key, 60062306a36Sopenharmony_ci ablkctx->key + (ablkctx->enckey_len >> 1), 60162306a36Sopenharmony_ci ablkctx->enckey_len >> 1); 60262306a36Sopenharmony_ci memcpy(key_ctx->key + (ablkctx->enckey_len >> 1), 60362306a36Sopenharmony_ci ablkctx->rrkey, ablkctx->enckey_len >> 1); 60462306a36Sopenharmony_ci } 60562306a36Sopenharmony_ci return 0; 60662306a36Sopenharmony_ci} 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_cistatic int chcr_hash_ent_in_wr(struct scatterlist *src, 60962306a36Sopenharmony_ci unsigned int minsg, 61062306a36Sopenharmony_ci unsigned int space, 61162306a36Sopenharmony_ci unsigned int srcskip) 61262306a36Sopenharmony_ci{ 61362306a36Sopenharmony_ci int srclen = 0; 61462306a36Sopenharmony_ci int srcsg = minsg; 61562306a36Sopenharmony_ci int soffset = 0, sless; 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci if (sg_dma_len(src) == srcskip) { 61862306a36Sopenharmony_ci src = sg_next(src); 61962306a36Sopenharmony_ci srcskip = 0; 62062306a36Sopenharmony_ci } 62162306a36Sopenharmony_ci while (src && space > (sgl_ent_len[srcsg + 1])) { 62262306a36Sopenharmony_ci sless = min_t(unsigned int, sg_dma_len(src) - soffset - srcskip, 62362306a36Sopenharmony_ci CHCR_SRC_SG_SIZE); 62462306a36Sopenharmony_ci srclen += sless; 62562306a36Sopenharmony_ci soffset += sless; 62662306a36Sopenharmony_ci srcsg++; 62762306a36Sopenharmony_ci if (sg_dma_len(src) == (soffset + srcskip)) { 62862306a36Sopenharmony_ci src = sg_next(src); 62962306a36Sopenharmony_ci soffset = 0; 63062306a36Sopenharmony_ci srcskip = 0; 63162306a36Sopenharmony_ci } 63262306a36Sopenharmony_ci } 63362306a36Sopenharmony_ci return srclen; 63462306a36Sopenharmony_ci} 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_cistatic int chcr_sg_ent_in_wr(struct scatterlist *src, 63762306a36Sopenharmony_ci struct scatterlist *dst, 63862306a36Sopenharmony_ci unsigned int minsg, 63962306a36Sopenharmony_ci unsigned int space, 64062306a36Sopenharmony_ci unsigned int srcskip, 64162306a36Sopenharmony_ci unsigned int dstskip) 64262306a36Sopenharmony_ci{ 64362306a36Sopenharmony_ci int srclen = 0, dstlen = 0; 64462306a36Sopenharmony_ci int srcsg = minsg, dstsg = minsg; 64562306a36Sopenharmony_ci int offset = 0, soffset = 0, less, sless = 0; 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci if (sg_dma_len(src) == srcskip) { 64862306a36Sopenharmony_ci src = sg_next(src); 64962306a36Sopenharmony_ci srcskip = 0; 65062306a36Sopenharmony_ci } 65162306a36Sopenharmony_ci if (sg_dma_len(dst) == dstskip) { 65262306a36Sopenharmony_ci dst = sg_next(dst); 65362306a36Sopenharmony_ci dstskip = 0; 65462306a36Sopenharmony_ci } 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci while (src && dst && 65762306a36Sopenharmony_ci space > (sgl_ent_len[srcsg + 1] + dsgl_ent_len[dstsg])) { 65862306a36Sopenharmony_ci sless = min_t(unsigned int, sg_dma_len(src) - srcskip - soffset, 65962306a36Sopenharmony_ci CHCR_SRC_SG_SIZE); 66062306a36Sopenharmony_ci srclen += sless; 66162306a36Sopenharmony_ci srcsg++; 66262306a36Sopenharmony_ci offset = 0; 66362306a36Sopenharmony_ci while (dst && ((dstsg + 1) <= MAX_DSGL_ENT) && 66462306a36Sopenharmony_ci space > (sgl_ent_len[srcsg] + dsgl_ent_len[dstsg + 1])) { 66562306a36Sopenharmony_ci if (srclen <= dstlen) 66662306a36Sopenharmony_ci break; 66762306a36Sopenharmony_ci less = min_t(unsigned int, sg_dma_len(dst) - offset - 66862306a36Sopenharmony_ci dstskip, CHCR_DST_SG_SIZE); 66962306a36Sopenharmony_ci dstlen += less; 67062306a36Sopenharmony_ci offset += less; 67162306a36Sopenharmony_ci if ((offset + dstskip) == sg_dma_len(dst)) { 67262306a36Sopenharmony_ci dst = sg_next(dst); 67362306a36Sopenharmony_ci offset = 0; 67462306a36Sopenharmony_ci } 67562306a36Sopenharmony_ci dstsg++; 67662306a36Sopenharmony_ci dstskip = 0; 67762306a36Sopenharmony_ci } 67862306a36Sopenharmony_ci soffset += sless; 67962306a36Sopenharmony_ci if ((soffset + srcskip) == sg_dma_len(src)) { 68062306a36Sopenharmony_ci src = sg_next(src); 68162306a36Sopenharmony_ci srcskip = 0; 68262306a36Sopenharmony_ci soffset = 0; 68362306a36Sopenharmony_ci } 68462306a36Sopenharmony_ci 68562306a36Sopenharmony_ci } 68662306a36Sopenharmony_ci return min(srclen, dstlen); 68762306a36Sopenharmony_ci} 68862306a36Sopenharmony_ci 68962306a36Sopenharmony_cistatic int chcr_cipher_fallback(struct crypto_skcipher *cipher, 69062306a36Sopenharmony_ci struct skcipher_request *req, 69162306a36Sopenharmony_ci u8 *iv, 69262306a36Sopenharmony_ci unsigned short op_type) 69362306a36Sopenharmony_ci{ 69462306a36Sopenharmony_ci struct chcr_skcipher_req_ctx *reqctx = skcipher_request_ctx(req); 69562306a36Sopenharmony_ci int err; 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ci skcipher_request_set_tfm(&reqctx->fallback_req, cipher); 69862306a36Sopenharmony_ci skcipher_request_set_callback(&reqctx->fallback_req, req->base.flags, 69962306a36Sopenharmony_ci req->base.complete, req->base.data); 70062306a36Sopenharmony_ci skcipher_request_set_crypt(&reqctx->fallback_req, req->src, req->dst, 70162306a36Sopenharmony_ci req->cryptlen, iv); 70262306a36Sopenharmony_ci 70362306a36Sopenharmony_ci err = op_type ? crypto_skcipher_decrypt(&reqctx->fallback_req) : 70462306a36Sopenharmony_ci crypto_skcipher_encrypt(&reqctx->fallback_req); 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_ci return err; 70762306a36Sopenharmony_ci 70862306a36Sopenharmony_ci} 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_cistatic inline int get_qidxs(struct crypto_async_request *req, 71162306a36Sopenharmony_ci unsigned int *txqidx, unsigned int *rxqidx) 71262306a36Sopenharmony_ci{ 71362306a36Sopenharmony_ci struct crypto_tfm *tfm = req->tfm; 71462306a36Sopenharmony_ci int ret = 0; 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_ci switch (tfm->__crt_alg->cra_flags & CRYPTO_ALG_TYPE_MASK) { 71762306a36Sopenharmony_ci case CRYPTO_ALG_TYPE_AEAD: 71862306a36Sopenharmony_ci { 71962306a36Sopenharmony_ci struct aead_request *aead_req = 72062306a36Sopenharmony_ci container_of(req, struct aead_request, base); 72162306a36Sopenharmony_ci struct chcr_aead_reqctx *reqctx = aead_request_ctx_dma(aead_req); 72262306a36Sopenharmony_ci *txqidx = reqctx->txqidx; 72362306a36Sopenharmony_ci *rxqidx = reqctx->rxqidx; 72462306a36Sopenharmony_ci break; 72562306a36Sopenharmony_ci } 72662306a36Sopenharmony_ci case CRYPTO_ALG_TYPE_SKCIPHER: 72762306a36Sopenharmony_ci { 72862306a36Sopenharmony_ci struct skcipher_request *sk_req = 72962306a36Sopenharmony_ci container_of(req, struct skcipher_request, base); 73062306a36Sopenharmony_ci struct chcr_skcipher_req_ctx *reqctx = 73162306a36Sopenharmony_ci skcipher_request_ctx(sk_req); 73262306a36Sopenharmony_ci *txqidx = reqctx->txqidx; 73362306a36Sopenharmony_ci *rxqidx = reqctx->rxqidx; 73462306a36Sopenharmony_ci break; 73562306a36Sopenharmony_ci } 73662306a36Sopenharmony_ci case CRYPTO_ALG_TYPE_AHASH: 73762306a36Sopenharmony_ci { 73862306a36Sopenharmony_ci struct ahash_request *ahash_req = 73962306a36Sopenharmony_ci container_of(req, struct ahash_request, base); 74062306a36Sopenharmony_ci struct chcr_ahash_req_ctx *reqctx = 74162306a36Sopenharmony_ci ahash_request_ctx(ahash_req); 74262306a36Sopenharmony_ci *txqidx = reqctx->txqidx; 74362306a36Sopenharmony_ci *rxqidx = reqctx->rxqidx; 74462306a36Sopenharmony_ci break; 74562306a36Sopenharmony_ci } 74662306a36Sopenharmony_ci default: 74762306a36Sopenharmony_ci ret = -EINVAL; 74862306a36Sopenharmony_ci /* should never get here */ 74962306a36Sopenharmony_ci BUG(); 75062306a36Sopenharmony_ci break; 75162306a36Sopenharmony_ci } 75262306a36Sopenharmony_ci return ret; 75362306a36Sopenharmony_ci} 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_cistatic inline void create_wreq(struct chcr_context *ctx, 75662306a36Sopenharmony_ci struct chcr_wr *chcr_req, 75762306a36Sopenharmony_ci struct crypto_async_request *req, 75862306a36Sopenharmony_ci unsigned int imm, 75962306a36Sopenharmony_ci int hash_sz, 76062306a36Sopenharmony_ci unsigned int len16, 76162306a36Sopenharmony_ci unsigned int sc_len, 76262306a36Sopenharmony_ci unsigned int lcb) 76362306a36Sopenharmony_ci{ 76462306a36Sopenharmony_ci struct uld_ctx *u_ctx = ULD_CTX(ctx); 76562306a36Sopenharmony_ci unsigned int tx_channel_id, rx_channel_id; 76662306a36Sopenharmony_ci unsigned int txqidx = 0, rxqidx = 0; 76762306a36Sopenharmony_ci unsigned int qid, fid, portno; 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_ci get_qidxs(req, &txqidx, &rxqidx); 77062306a36Sopenharmony_ci qid = u_ctx->lldi.rxq_ids[rxqidx]; 77162306a36Sopenharmony_ci fid = u_ctx->lldi.rxq_ids[0]; 77262306a36Sopenharmony_ci portno = rxqidx / ctx->rxq_perchan; 77362306a36Sopenharmony_ci tx_channel_id = txqidx / ctx->txq_perchan; 77462306a36Sopenharmony_ci rx_channel_id = cxgb4_port_e2cchan(u_ctx->lldi.ports[portno]); 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_ci chcr_req->wreq.op_to_cctx_size = FILL_WR_OP_CCTX_SIZE; 77862306a36Sopenharmony_ci chcr_req->wreq.pld_size_hash_size = 77962306a36Sopenharmony_ci htonl(FW_CRYPTO_LOOKASIDE_WR_HASH_SIZE_V(hash_sz)); 78062306a36Sopenharmony_ci chcr_req->wreq.len16_pkd = 78162306a36Sopenharmony_ci htonl(FW_CRYPTO_LOOKASIDE_WR_LEN16_V(DIV_ROUND_UP(len16, 16))); 78262306a36Sopenharmony_ci chcr_req->wreq.cookie = cpu_to_be64((uintptr_t)req); 78362306a36Sopenharmony_ci chcr_req->wreq.rx_chid_to_rx_q_id = FILL_WR_RX_Q_ID(rx_channel_id, qid, 78462306a36Sopenharmony_ci !!lcb, txqidx); 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_ci chcr_req->ulptx.cmd_dest = FILL_ULPTX_CMD_DEST(tx_channel_id, fid); 78762306a36Sopenharmony_ci chcr_req->ulptx.len = htonl((DIV_ROUND_UP(len16, 16) - 78862306a36Sopenharmony_ci ((sizeof(chcr_req->wreq)) >> 4))); 78962306a36Sopenharmony_ci chcr_req->sc_imm.cmd_more = FILL_CMD_MORE(!imm); 79062306a36Sopenharmony_ci chcr_req->sc_imm.len = cpu_to_be32(sizeof(struct cpl_tx_sec_pdu) + 79162306a36Sopenharmony_ci sizeof(chcr_req->key_ctx) + sc_len); 79262306a36Sopenharmony_ci} 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ci/** 79562306a36Sopenharmony_ci * create_cipher_wr - form the WR for cipher operations 79662306a36Sopenharmony_ci * @wrparam: Container for create_cipher_wr()'s parameters 79762306a36Sopenharmony_ci */ 79862306a36Sopenharmony_cistatic struct sk_buff *create_cipher_wr(struct cipher_wr_param *wrparam) 79962306a36Sopenharmony_ci{ 80062306a36Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(wrparam->req); 80162306a36Sopenharmony_ci struct chcr_context *ctx = c_ctx(tfm); 80262306a36Sopenharmony_ci struct uld_ctx *u_ctx = ULD_CTX(ctx); 80362306a36Sopenharmony_ci struct ablk_ctx *ablkctx = ABLK_CTX(ctx); 80462306a36Sopenharmony_ci struct sk_buff *skb = NULL; 80562306a36Sopenharmony_ci struct chcr_wr *chcr_req; 80662306a36Sopenharmony_ci struct cpl_rx_phys_dsgl *phys_cpl; 80762306a36Sopenharmony_ci struct ulptx_sgl *ulptx; 80862306a36Sopenharmony_ci struct chcr_skcipher_req_ctx *reqctx = 80962306a36Sopenharmony_ci skcipher_request_ctx(wrparam->req); 81062306a36Sopenharmony_ci unsigned int temp = 0, transhdr_len, dst_size; 81162306a36Sopenharmony_ci int error; 81262306a36Sopenharmony_ci int nents; 81362306a36Sopenharmony_ci unsigned int kctx_len; 81462306a36Sopenharmony_ci gfp_t flags = wrparam->req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? 81562306a36Sopenharmony_ci GFP_KERNEL : GFP_ATOMIC; 81662306a36Sopenharmony_ci struct adapter *adap = padap(ctx->dev); 81762306a36Sopenharmony_ci unsigned int rx_channel_id = reqctx->rxqidx / ctx->rxq_perchan; 81862306a36Sopenharmony_ci 81962306a36Sopenharmony_ci rx_channel_id = cxgb4_port_e2cchan(u_ctx->lldi.ports[rx_channel_id]); 82062306a36Sopenharmony_ci nents = sg_nents_xlen(reqctx->dstsg, wrparam->bytes, CHCR_DST_SG_SIZE, 82162306a36Sopenharmony_ci reqctx->dst_ofst); 82262306a36Sopenharmony_ci dst_size = get_space_for_phys_dsgl(nents); 82362306a36Sopenharmony_ci kctx_len = roundup(ablkctx->enckey_len, 16); 82462306a36Sopenharmony_ci transhdr_len = CIPHER_TRANSHDR_SIZE(kctx_len, dst_size); 82562306a36Sopenharmony_ci nents = sg_nents_xlen(reqctx->srcsg, wrparam->bytes, 82662306a36Sopenharmony_ci CHCR_SRC_SG_SIZE, reqctx->src_ofst); 82762306a36Sopenharmony_ci temp = reqctx->imm ? roundup(wrparam->bytes, 16) : 82862306a36Sopenharmony_ci (sgl_len(nents) * 8); 82962306a36Sopenharmony_ci transhdr_len += temp; 83062306a36Sopenharmony_ci transhdr_len = roundup(transhdr_len, 16); 83162306a36Sopenharmony_ci skb = alloc_skb(SGE_MAX_WR_LEN, flags); 83262306a36Sopenharmony_ci if (!skb) { 83362306a36Sopenharmony_ci error = -ENOMEM; 83462306a36Sopenharmony_ci goto err; 83562306a36Sopenharmony_ci } 83662306a36Sopenharmony_ci chcr_req = __skb_put_zero(skb, transhdr_len); 83762306a36Sopenharmony_ci chcr_req->sec_cpl.op_ivinsrtofst = 83862306a36Sopenharmony_ci FILL_SEC_CPL_OP_IVINSR(rx_channel_id, 2, 1); 83962306a36Sopenharmony_ci 84062306a36Sopenharmony_ci chcr_req->sec_cpl.pldlen = htonl(IV + wrparam->bytes); 84162306a36Sopenharmony_ci chcr_req->sec_cpl.aadstart_cipherstop_hi = 84262306a36Sopenharmony_ci FILL_SEC_CPL_CIPHERSTOP_HI(0, 0, IV + 1, 0); 84362306a36Sopenharmony_ci 84462306a36Sopenharmony_ci chcr_req->sec_cpl.cipherstop_lo_authinsert = 84562306a36Sopenharmony_ci FILL_SEC_CPL_AUTHINSERT(0, 0, 0, 0); 84662306a36Sopenharmony_ci chcr_req->sec_cpl.seqno_numivs = FILL_SEC_CPL_SCMD0_SEQNO(reqctx->op, 0, 84762306a36Sopenharmony_ci ablkctx->ciph_mode, 84862306a36Sopenharmony_ci 0, 0, IV >> 1); 84962306a36Sopenharmony_ci chcr_req->sec_cpl.ivgen_hdrlen = FILL_SEC_CPL_IVGEN_HDRLEN(0, 0, 0, 85062306a36Sopenharmony_ci 0, 1, dst_size); 85162306a36Sopenharmony_ci 85262306a36Sopenharmony_ci chcr_req->key_ctx.ctx_hdr = ablkctx->key_ctx_hdr; 85362306a36Sopenharmony_ci if ((reqctx->op == CHCR_DECRYPT_OP) && 85462306a36Sopenharmony_ci (!(get_cryptoalg_subtype(tfm) == 85562306a36Sopenharmony_ci CRYPTO_ALG_SUB_TYPE_CTR)) && 85662306a36Sopenharmony_ci (!(get_cryptoalg_subtype(tfm) == 85762306a36Sopenharmony_ci CRYPTO_ALG_SUB_TYPE_CTR_RFC3686))) { 85862306a36Sopenharmony_ci generate_copy_rrkey(ablkctx, &chcr_req->key_ctx); 85962306a36Sopenharmony_ci } else { 86062306a36Sopenharmony_ci if ((ablkctx->ciph_mode == CHCR_SCMD_CIPHER_MODE_AES_CBC) || 86162306a36Sopenharmony_ci (ablkctx->ciph_mode == CHCR_SCMD_CIPHER_MODE_AES_CTR)) { 86262306a36Sopenharmony_ci memcpy(chcr_req->key_ctx.key, ablkctx->key, 86362306a36Sopenharmony_ci ablkctx->enckey_len); 86462306a36Sopenharmony_ci } else { 86562306a36Sopenharmony_ci memcpy(chcr_req->key_ctx.key, ablkctx->key + 86662306a36Sopenharmony_ci (ablkctx->enckey_len >> 1), 86762306a36Sopenharmony_ci ablkctx->enckey_len >> 1); 86862306a36Sopenharmony_ci memcpy(chcr_req->key_ctx.key + 86962306a36Sopenharmony_ci (ablkctx->enckey_len >> 1), 87062306a36Sopenharmony_ci ablkctx->key, 87162306a36Sopenharmony_ci ablkctx->enckey_len >> 1); 87262306a36Sopenharmony_ci } 87362306a36Sopenharmony_ci } 87462306a36Sopenharmony_ci phys_cpl = (struct cpl_rx_phys_dsgl *)((u8 *)(chcr_req + 1) + kctx_len); 87562306a36Sopenharmony_ci ulptx = (struct ulptx_sgl *)((u8 *)(phys_cpl + 1) + dst_size); 87662306a36Sopenharmony_ci chcr_add_cipher_src_ent(wrparam->req, ulptx, wrparam); 87762306a36Sopenharmony_ci chcr_add_cipher_dst_ent(wrparam->req, phys_cpl, wrparam, wrparam->qid); 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_ci atomic_inc(&adap->chcr_stats.cipher_rqst); 88062306a36Sopenharmony_ci temp = sizeof(struct cpl_rx_phys_dsgl) + dst_size + kctx_len + IV 88162306a36Sopenharmony_ci + (reqctx->imm ? (wrparam->bytes) : 0); 88262306a36Sopenharmony_ci create_wreq(c_ctx(tfm), chcr_req, &(wrparam->req->base), reqctx->imm, 0, 88362306a36Sopenharmony_ci transhdr_len, temp, 88462306a36Sopenharmony_ci ablkctx->ciph_mode == CHCR_SCMD_CIPHER_MODE_AES_CBC); 88562306a36Sopenharmony_ci reqctx->skb = skb; 88662306a36Sopenharmony_ci 88762306a36Sopenharmony_ci if (reqctx->op && (ablkctx->ciph_mode == 88862306a36Sopenharmony_ci CHCR_SCMD_CIPHER_MODE_AES_CBC)) 88962306a36Sopenharmony_ci sg_pcopy_to_buffer(wrparam->req->src, 89062306a36Sopenharmony_ci sg_nents(wrparam->req->src), wrparam->req->iv, 16, 89162306a36Sopenharmony_ci reqctx->processed + wrparam->bytes - AES_BLOCK_SIZE); 89262306a36Sopenharmony_ci 89362306a36Sopenharmony_ci return skb; 89462306a36Sopenharmony_cierr: 89562306a36Sopenharmony_ci return ERR_PTR(error); 89662306a36Sopenharmony_ci} 89762306a36Sopenharmony_ci 89862306a36Sopenharmony_cistatic inline int chcr_keyctx_ck_size(unsigned int keylen) 89962306a36Sopenharmony_ci{ 90062306a36Sopenharmony_ci int ck_size = 0; 90162306a36Sopenharmony_ci 90262306a36Sopenharmony_ci if (keylen == AES_KEYSIZE_128) 90362306a36Sopenharmony_ci ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_128; 90462306a36Sopenharmony_ci else if (keylen == AES_KEYSIZE_192) 90562306a36Sopenharmony_ci ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_192; 90662306a36Sopenharmony_ci else if (keylen == AES_KEYSIZE_256) 90762306a36Sopenharmony_ci ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_256; 90862306a36Sopenharmony_ci else 90962306a36Sopenharmony_ci ck_size = 0; 91062306a36Sopenharmony_ci 91162306a36Sopenharmony_ci return ck_size; 91262306a36Sopenharmony_ci} 91362306a36Sopenharmony_cistatic int chcr_cipher_fallback_setkey(struct crypto_skcipher *cipher, 91462306a36Sopenharmony_ci const u8 *key, 91562306a36Sopenharmony_ci unsigned int keylen) 91662306a36Sopenharmony_ci{ 91762306a36Sopenharmony_ci struct ablk_ctx *ablkctx = ABLK_CTX(c_ctx(cipher)); 91862306a36Sopenharmony_ci 91962306a36Sopenharmony_ci crypto_skcipher_clear_flags(ablkctx->sw_cipher, 92062306a36Sopenharmony_ci CRYPTO_TFM_REQ_MASK); 92162306a36Sopenharmony_ci crypto_skcipher_set_flags(ablkctx->sw_cipher, 92262306a36Sopenharmony_ci cipher->base.crt_flags & CRYPTO_TFM_REQ_MASK); 92362306a36Sopenharmony_ci return crypto_skcipher_setkey(ablkctx->sw_cipher, key, keylen); 92462306a36Sopenharmony_ci} 92562306a36Sopenharmony_ci 92662306a36Sopenharmony_cistatic int chcr_aes_cbc_setkey(struct crypto_skcipher *cipher, 92762306a36Sopenharmony_ci const u8 *key, 92862306a36Sopenharmony_ci unsigned int keylen) 92962306a36Sopenharmony_ci{ 93062306a36Sopenharmony_ci struct ablk_ctx *ablkctx = ABLK_CTX(c_ctx(cipher)); 93162306a36Sopenharmony_ci unsigned int ck_size, context_size; 93262306a36Sopenharmony_ci u16 alignment = 0; 93362306a36Sopenharmony_ci int err; 93462306a36Sopenharmony_ci 93562306a36Sopenharmony_ci err = chcr_cipher_fallback_setkey(cipher, key, keylen); 93662306a36Sopenharmony_ci if (err) 93762306a36Sopenharmony_ci goto badkey_err; 93862306a36Sopenharmony_ci 93962306a36Sopenharmony_ci ck_size = chcr_keyctx_ck_size(keylen); 94062306a36Sopenharmony_ci alignment = ck_size == CHCR_KEYCTX_CIPHER_KEY_SIZE_192 ? 8 : 0; 94162306a36Sopenharmony_ci memcpy(ablkctx->key, key, keylen); 94262306a36Sopenharmony_ci ablkctx->enckey_len = keylen; 94362306a36Sopenharmony_ci get_aes_decrypt_key(ablkctx->rrkey, ablkctx->key, keylen << 3); 94462306a36Sopenharmony_ci context_size = (KEY_CONTEXT_HDR_SALT_AND_PAD + 94562306a36Sopenharmony_ci keylen + alignment) >> 4; 94662306a36Sopenharmony_ci 94762306a36Sopenharmony_ci ablkctx->key_ctx_hdr = FILL_KEY_CTX_HDR(ck_size, CHCR_KEYCTX_NO_KEY, 94862306a36Sopenharmony_ci 0, 0, context_size); 94962306a36Sopenharmony_ci ablkctx->ciph_mode = CHCR_SCMD_CIPHER_MODE_AES_CBC; 95062306a36Sopenharmony_ci return 0; 95162306a36Sopenharmony_cibadkey_err: 95262306a36Sopenharmony_ci ablkctx->enckey_len = 0; 95362306a36Sopenharmony_ci 95462306a36Sopenharmony_ci return err; 95562306a36Sopenharmony_ci} 95662306a36Sopenharmony_ci 95762306a36Sopenharmony_cistatic int chcr_aes_ctr_setkey(struct crypto_skcipher *cipher, 95862306a36Sopenharmony_ci const u8 *key, 95962306a36Sopenharmony_ci unsigned int keylen) 96062306a36Sopenharmony_ci{ 96162306a36Sopenharmony_ci struct ablk_ctx *ablkctx = ABLK_CTX(c_ctx(cipher)); 96262306a36Sopenharmony_ci unsigned int ck_size, context_size; 96362306a36Sopenharmony_ci u16 alignment = 0; 96462306a36Sopenharmony_ci int err; 96562306a36Sopenharmony_ci 96662306a36Sopenharmony_ci err = chcr_cipher_fallback_setkey(cipher, key, keylen); 96762306a36Sopenharmony_ci if (err) 96862306a36Sopenharmony_ci goto badkey_err; 96962306a36Sopenharmony_ci ck_size = chcr_keyctx_ck_size(keylen); 97062306a36Sopenharmony_ci alignment = (ck_size == CHCR_KEYCTX_CIPHER_KEY_SIZE_192) ? 8 : 0; 97162306a36Sopenharmony_ci memcpy(ablkctx->key, key, keylen); 97262306a36Sopenharmony_ci ablkctx->enckey_len = keylen; 97362306a36Sopenharmony_ci context_size = (KEY_CONTEXT_HDR_SALT_AND_PAD + 97462306a36Sopenharmony_ci keylen + alignment) >> 4; 97562306a36Sopenharmony_ci 97662306a36Sopenharmony_ci ablkctx->key_ctx_hdr = FILL_KEY_CTX_HDR(ck_size, CHCR_KEYCTX_NO_KEY, 97762306a36Sopenharmony_ci 0, 0, context_size); 97862306a36Sopenharmony_ci ablkctx->ciph_mode = CHCR_SCMD_CIPHER_MODE_AES_CTR; 97962306a36Sopenharmony_ci 98062306a36Sopenharmony_ci return 0; 98162306a36Sopenharmony_cibadkey_err: 98262306a36Sopenharmony_ci ablkctx->enckey_len = 0; 98362306a36Sopenharmony_ci 98462306a36Sopenharmony_ci return err; 98562306a36Sopenharmony_ci} 98662306a36Sopenharmony_ci 98762306a36Sopenharmony_cistatic int chcr_aes_rfc3686_setkey(struct crypto_skcipher *cipher, 98862306a36Sopenharmony_ci const u8 *key, 98962306a36Sopenharmony_ci unsigned int keylen) 99062306a36Sopenharmony_ci{ 99162306a36Sopenharmony_ci struct ablk_ctx *ablkctx = ABLK_CTX(c_ctx(cipher)); 99262306a36Sopenharmony_ci unsigned int ck_size, context_size; 99362306a36Sopenharmony_ci u16 alignment = 0; 99462306a36Sopenharmony_ci int err; 99562306a36Sopenharmony_ci 99662306a36Sopenharmony_ci if (keylen < CTR_RFC3686_NONCE_SIZE) 99762306a36Sopenharmony_ci return -EINVAL; 99862306a36Sopenharmony_ci memcpy(ablkctx->nonce, key + (keylen - CTR_RFC3686_NONCE_SIZE), 99962306a36Sopenharmony_ci CTR_RFC3686_NONCE_SIZE); 100062306a36Sopenharmony_ci 100162306a36Sopenharmony_ci keylen -= CTR_RFC3686_NONCE_SIZE; 100262306a36Sopenharmony_ci err = chcr_cipher_fallback_setkey(cipher, key, keylen); 100362306a36Sopenharmony_ci if (err) 100462306a36Sopenharmony_ci goto badkey_err; 100562306a36Sopenharmony_ci 100662306a36Sopenharmony_ci ck_size = chcr_keyctx_ck_size(keylen); 100762306a36Sopenharmony_ci alignment = (ck_size == CHCR_KEYCTX_CIPHER_KEY_SIZE_192) ? 8 : 0; 100862306a36Sopenharmony_ci memcpy(ablkctx->key, key, keylen); 100962306a36Sopenharmony_ci ablkctx->enckey_len = keylen; 101062306a36Sopenharmony_ci context_size = (KEY_CONTEXT_HDR_SALT_AND_PAD + 101162306a36Sopenharmony_ci keylen + alignment) >> 4; 101262306a36Sopenharmony_ci 101362306a36Sopenharmony_ci ablkctx->key_ctx_hdr = FILL_KEY_CTX_HDR(ck_size, CHCR_KEYCTX_NO_KEY, 101462306a36Sopenharmony_ci 0, 0, context_size); 101562306a36Sopenharmony_ci ablkctx->ciph_mode = CHCR_SCMD_CIPHER_MODE_AES_CTR; 101662306a36Sopenharmony_ci 101762306a36Sopenharmony_ci return 0; 101862306a36Sopenharmony_cibadkey_err: 101962306a36Sopenharmony_ci ablkctx->enckey_len = 0; 102062306a36Sopenharmony_ci 102162306a36Sopenharmony_ci return err; 102262306a36Sopenharmony_ci} 102362306a36Sopenharmony_cistatic void ctr_add_iv(u8 *dstiv, u8 *srciv, u32 add) 102462306a36Sopenharmony_ci{ 102562306a36Sopenharmony_ci unsigned int size = AES_BLOCK_SIZE; 102662306a36Sopenharmony_ci __be32 *b = (__be32 *)(dstiv + size); 102762306a36Sopenharmony_ci u32 c, prev; 102862306a36Sopenharmony_ci 102962306a36Sopenharmony_ci memcpy(dstiv, srciv, AES_BLOCK_SIZE); 103062306a36Sopenharmony_ci for (; size >= 4; size -= 4) { 103162306a36Sopenharmony_ci prev = be32_to_cpu(*--b); 103262306a36Sopenharmony_ci c = prev + add; 103362306a36Sopenharmony_ci *b = cpu_to_be32(c); 103462306a36Sopenharmony_ci if (prev < c) 103562306a36Sopenharmony_ci break; 103662306a36Sopenharmony_ci add = 1; 103762306a36Sopenharmony_ci } 103862306a36Sopenharmony_ci 103962306a36Sopenharmony_ci} 104062306a36Sopenharmony_ci 104162306a36Sopenharmony_cistatic unsigned int adjust_ctr_overflow(u8 *iv, u32 bytes) 104262306a36Sopenharmony_ci{ 104362306a36Sopenharmony_ci __be32 *b = (__be32 *)(iv + AES_BLOCK_SIZE); 104462306a36Sopenharmony_ci u64 c; 104562306a36Sopenharmony_ci u32 temp = be32_to_cpu(*--b); 104662306a36Sopenharmony_ci 104762306a36Sopenharmony_ci temp = ~temp; 104862306a36Sopenharmony_ci c = (u64)temp + 1; // No of block can processed without overflow 104962306a36Sopenharmony_ci if ((bytes / AES_BLOCK_SIZE) >= c) 105062306a36Sopenharmony_ci bytes = c * AES_BLOCK_SIZE; 105162306a36Sopenharmony_ci return bytes; 105262306a36Sopenharmony_ci} 105362306a36Sopenharmony_ci 105462306a36Sopenharmony_cistatic int chcr_update_tweak(struct skcipher_request *req, u8 *iv, 105562306a36Sopenharmony_ci u32 isfinal) 105662306a36Sopenharmony_ci{ 105762306a36Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 105862306a36Sopenharmony_ci struct ablk_ctx *ablkctx = ABLK_CTX(c_ctx(tfm)); 105962306a36Sopenharmony_ci struct chcr_skcipher_req_ctx *reqctx = skcipher_request_ctx(req); 106062306a36Sopenharmony_ci struct crypto_aes_ctx aes; 106162306a36Sopenharmony_ci int ret, i; 106262306a36Sopenharmony_ci u8 *key; 106362306a36Sopenharmony_ci unsigned int keylen; 106462306a36Sopenharmony_ci int round = reqctx->last_req_len / AES_BLOCK_SIZE; 106562306a36Sopenharmony_ci int round8 = round / 8; 106662306a36Sopenharmony_ci 106762306a36Sopenharmony_ci memcpy(iv, reqctx->iv, AES_BLOCK_SIZE); 106862306a36Sopenharmony_ci 106962306a36Sopenharmony_ci keylen = ablkctx->enckey_len / 2; 107062306a36Sopenharmony_ci key = ablkctx->key + keylen; 107162306a36Sopenharmony_ci /* For a 192 bit key remove the padded zeroes which was 107262306a36Sopenharmony_ci * added in chcr_xts_setkey 107362306a36Sopenharmony_ci */ 107462306a36Sopenharmony_ci if (KEY_CONTEXT_CK_SIZE_G(ntohl(ablkctx->key_ctx_hdr)) 107562306a36Sopenharmony_ci == CHCR_KEYCTX_CIPHER_KEY_SIZE_192) 107662306a36Sopenharmony_ci ret = aes_expandkey(&aes, key, keylen - 8); 107762306a36Sopenharmony_ci else 107862306a36Sopenharmony_ci ret = aes_expandkey(&aes, key, keylen); 107962306a36Sopenharmony_ci if (ret) 108062306a36Sopenharmony_ci return ret; 108162306a36Sopenharmony_ci aes_encrypt(&aes, iv, iv); 108262306a36Sopenharmony_ci for (i = 0; i < round8; i++) 108362306a36Sopenharmony_ci gf128mul_x8_ble((le128 *)iv, (le128 *)iv); 108462306a36Sopenharmony_ci 108562306a36Sopenharmony_ci for (i = 0; i < (round % 8); i++) 108662306a36Sopenharmony_ci gf128mul_x_ble((le128 *)iv, (le128 *)iv); 108762306a36Sopenharmony_ci 108862306a36Sopenharmony_ci if (!isfinal) 108962306a36Sopenharmony_ci aes_decrypt(&aes, iv, iv); 109062306a36Sopenharmony_ci 109162306a36Sopenharmony_ci memzero_explicit(&aes, sizeof(aes)); 109262306a36Sopenharmony_ci return 0; 109362306a36Sopenharmony_ci} 109462306a36Sopenharmony_ci 109562306a36Sopenharmony_cistatic int chcr_update_cipher_iv(struct skcipher_request *req, 109662306a36Sopenharmony_ci struct cpl_fw6_pld *fw6_pld, u8 *iv) 109762306a36Sopenharmony_ci{ 109862306a36Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 109962306a36Sopenharmony_ci struct chcr_skcipher_req_ctx *reqctx = skcipher_request_ctx(req); 110062306a36Sopenharmony_ci int subtype = get_cryptoalg_subtype(tfm); 110162306a36Sopenharmony_ci int ret = 0; 110262306a36Sopenharmony_ci 110362306a36Sopenharmony_ci if (subtype == CRYPTO_ALG_SUB_TYPE_CTR) 110462306a36Sopenharmony_ci ctr_add_iv(iv, req->iv, (reqctx->processed / 110562306a36Sopenharmony_ci AES_BLOCK_SIZE)); 110662306a36Sopenharmony_ci else if (subtype == CRYPTO_ALG_SUB_TYPE_CTR_RFC3686) 110762306a36Sopenharmony_ci *(__be32 *)(reqctx->iv + CTR_RFC3686_NONCE_SIZE + 110862306a36Sopenharmony_ci CTR_RFC3686_IV_SIZE) = cpu_to_be32((reqctx->processed / 110962306a36Sopenharmony_ci AES_BLOCK_SIZE) + 1); 111062306a36Sopenharmony_ci else if (subtype == CRYPTO_ALG_SUB_TYPE_XTS) 111162306a36Sopenharmony_ci ret = chcr_update_tweak(req, iv, 0); 111262306a36Sopenharmony_ci else if (subtype == CRYPTO_ALG_SUB_TYPE_CBC) { 111362306a36Sopenharmony_ci if (reqctx->op) 111462306a36Sopenharmony_ci /*Updated before sending last WR*/ 111562306a36Sopenharmony_ci memcpy(iv, req->iv, AES_BLOCK_SIZE); 111662306a36Sopenharmony_ci else 111762306a36Sopenharmony_ci memcpy(iv, &fw6_pld->data[2], AES_BLOCK_SIZE); 111862306a36Sopenharmony_ci } 111962306a36Sopenharmony_ci 112062306a36Sopenharmony_ci return ret; 112162306a36Sopenharmony_ci 112262306a36Sopenharmony_ci} 112362306a36Sopenharmony_ci 112462306a36Sopenharmony_ci/* We need separate function for final iv because in rfc3686 Initial counter 112562306a36Sopenharmony_ci * starts from 1 and buffer size of iv is 8 byte only which remains constant 112662306a36Sopenharmony_ci * for subsequent update requests 112762306a36Sopenharmony_ci */ 112862306a36Sopenharmony_ci 112962306a36Sopenharmony_cistatic int chcr_final_cipher_iv(struct skcipher_request *req, 113062306a36Sopenharmony_ci struct cpl_fw6_pld *fw6_pld, u8 *iv) 113162306a36Sopenharmony_ci{ 113262306a36Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 113362306a36Sopenharmony_ci struct chcr_skcipher_req_ctx *reqctx = skcipher_request_ctx(req); 113462306a36Sopenharmony_ci int subtype = get_cryptoalg_subtype(tfm); 113562306a36Sopenharmony_ci int ret = 0; 113662306a36Sopenharmony_ci 113762306a36Sopenharmony_ci if (subtype == CRYPTO_ALG_SUB_TYPE_CTR) 113862306a36Sopenharmony_ci ctr_add_iv(iv, req->iv, DIV_ROUND_UP(reqctx->processed, 113962306a36Sopenharmony_ci AES_BLOCK_SIZE)); 114062306a36Sopenharmony_ci else if (subtype == CRYPTO_ALG_SUB_TYPE_XTS) { 114162306a36Sopenharmony_ci if (!reqctx->partial_req) 114262306a36Sopenharmony_ci memcpy(iv, reqctx->iv, AES_BLOCK_SIZE); 114362306a36Sopenharmony_ci else 114462306a36Sopenharmony_ci ret = chcr_update_tweak(req, iv, 1); 114562306a36Sopenharmony_ci } 114662306a36Sopenharmony_ci else if (subtype == CRYPTO_ALG_SUB_TYPE_CBC) { 114762306a36Sopenharmony_ci /*Already updated for Decrypt*/ 114862306a36Sopenharmony_ci if (!reqctx->op) 114962306a36Sopenharmony_ci memcpy(iv, &fw6_pld->data[2], AES_BLOCK_SIZE); 115062306a36Sopenharmony_ci 115162306a36Sopenharmony_ci } 115262306a36Sopenharmony_ci return ret; 115362306a36Sopenharmony_ci 115462306a36Sopenharmony_ci} 115562306a36Sopenharmony_ci 115662306a36Sopenharmony_cistatic int chcr_handle_cipher_resp(struct skcipher_request *req, 115762306a36Sopenharmony_ci unsigned char *input, int err) 115862306a36Sopenharmony_ci{ 115962306a36Sopenharmony_ci struct chcr_skcipher_req_ctx *reqctx = skcipher_request_ctx(req); 116062306a36Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 116162306a36Sopenharmony_ci struct cpl_fw6_pld *fw6_pld = (struct cpl_fw6_pld *)input; 116262306a36Sopenharmony_ci struct ablk_ctx *ablkctx = ABLK_CTX(c_ctx(tfm)); 116362306a36Sopenharmony_ci struct uld_ctx *u_ctx = ULD_CTX(c_ctx(tfm)); 116462306a36Sopenharmony_ci struct chcr_dev *dev = c_ctx(tfm)->dev; 116562306a36Sopenharmony_ci struct chcr_context *ctx = c_ctx(tfm); 116662306a36Sopenharmony_ci struct adapter *adap = padap(ctx->dev); 116762306a36Sopenharmony_ci struct cipher_wr_param wrparam; 116862306a36Sopenharmony_ci struct sk_buff *skb; 116962306a36Sopenharmony_ci int bytes; 117062306a36Sopenharmony_ci 117162306a36Sopenharmony_ci if (err) 117262306a36Sopenharmony_ci goto unmap; 117362306a36Sopenharmony_ci if (req->cryptlen == reqctx->processed) { 117462306a36Sopenharmony_ci chcr_cipher_dma_unmap(&ULD_CTX(c_ctx(tfm))->lldi.pdev->dev, 117562306a36Sopenharmony_ci req); 117662306a36Sopenharmony_ci err = chcr_final_cipher_iv(req, fw6_pld, req->iv); 117762306a36Sopenharmony_ci goto complete; 117862306a36Sopenharmony_ci } 117962306a36Sopenharmony_ci 118062306a36Sopenharmony_ci if (!reqctx->imm) { 118162306a36Sopenharmony_ci bytes = chcr_sg_ent_in_wr(reqctx->srcsg, reqctx->dstsg, 0, 118262306a36Sopenharmony_ci CIP_SPACE_LEFT(ablkctx->enckey_len), 118362306a36Sopenharmony_ci reqctx->src_ofst, reqctx->dst_ofst); 118462306a36Sopenharmony_ci if ((bytes + reqctx->processed) >= req->cryptlen) 118562306a36Sopenharmony_ci bytes = req->cryptlen - reqctx->processed; 118662306a36Sopenharmony_ci else 118762306a36Sopenharmony_ci bytes = rounddown(bytes, 16); 118862306a36Sopenharmony_ci } else { 118962306a36Sopenharmony_ci /*CTR mode counter overfloa*/ 119062306a36Sopenharmony_ci bytes = req->cryptlen - reqctx->processed; 119162306a36Sopenharmony_ci } 119262306a36Sopenharmony_ci err = chcr_update_cipher_iv(req, fw6_pld, reqctx->iv); 119362306a36Sopenharmony_ci if (err) 119462306a36Sopenharmony_ci goto unmap; 119562306a36Sopenharmony_ci 119662306a36Sopenharmony_ci if (unlikely(bytes == 0)) { 119762306a36Sopenharmony_ci chcr_cipher_dma_unmap(&ULD_CTX(c_ctx(tfm))->lldi.pdev->dev, 119862306a36Sopenharmony_ci req); 119962306a36Sopenharmony_ci memcpy(req->iv, reqctx->init_iv, IV); 120062306a36Sopenharmony_ci atomic_inc(&adap->chcr_stats.fallback); 120162306a36Sopenharmony_ci err = chcr_cipher_fallback(ablkctx->sw_cipher, req, req->iv, 120262306a36Sopenharmony_ci reqctx->op); 120362306a36Sopenharmony_ci goto complete; 120462306a36Sopenharmony_ci } 120562306a36Sopenharmony_ci 120662306a36Sopenharmony_ci if (get_cryptoalg_subtype(tfm) == 120762306a36Sopenharmony_ci CRYPTO_ALG_SUB_TYPE_CTR) 120862306a36Sopenharmony_ci bytes = adjust_ctr_overflow(reqctx->iv, bytes); 120962306a36Sopenharmony_ci wrparam.qid = u_ctx->lldi.rxq_ids[reqctx->rxqidx]; 121062306a36Sopenharmony_ci wrparam.req = req; 121162306a36Sopenharmony_ci wrparam.bytes = bytes; 121262306a36Sopenharmony_ci skb = create_cipher_wr(&wrparam); 121362306a36Sopenharmony_ci if (IS_ERR(skb)) { 121462306a36Sopenharmony_ci pr_err("%s : Failed to form WR. No memory\n", __func__); 121562306a36Sopenharmony_ci err = PTR_ERR(skb); 121662306a36Sopenharmony_ci goto unmap; 121762306a36Sopenharmony_ci } 121862306a36Sopenharmony_ci skb->dev = u_ctx->lldi.ports[0]; 121962306a36Sopenharmony_ci set_wr_txq(skb, CPL_PRIORITY_DATA, reqctx->txqidx); 122062306a36Sopenharmony_ci chcr_send_wr(skb); 122162306a36Sopenharmony_ci reqctx->last_req_len = bytes; 122262306a36Sopenharmony_ci reqctx->processed += bytes; 122362306a36Sopenharmony_ci if (get_cryptoalg_subtype(tfm) == 122462306a36Sopenharmony_ci CRYPTO_ALG_SUB_TYPE_CBC && req->base.flags == 122562306a36Sopenharmony_ci CRYPTO_TFM_REQ_MAY_SLEEP ) { 122662306a36Sopenharmony_ci complete(&ctx->cbc_aes_aio_done); 122762306a36Sopenharmony_ci } 122862306a36Sopenharmony_ci return 0; 122962306a36Sopenharmony_ciunmap: 123062306a36Sopenharmony_ci chcr_cipher_dma_unmap(&ULD_CTX(c_ctx(tfm))->lldi.pdev->dev, req); 123162306a36Sopenharmony_cicomplete: 123262306a36Sopenharmony_ci if (get_cryptoalg_subtype(tfm) == 123362306a36Sopenharmony_ci CRYPTO_ALG_SUB_TYPE_CBC && req->base.flags == 123462306a36Sopenharmony_ci CRYPTO_TFM_REQ_MAY_SLEEP ) { 123562306a36Sopenharmony_ci complete(&ctx->cbc_aes_aio_done); 123662306a36Sopenharmony_ci } 123762306a36Sopenharmony_ci chcr_dec_wrcount(dev); 123862306a36Sopenharmony_ci skcipher_request_complete(req, err); 123962306a36Sopenharmony_ci return err; 124062306a36Sopenharmony_ci} 124162306a36Sopenharmony_ci 124262306a36Sopenharmony_cistatic int process_cipher(struct skcipher_request *req, 124362306a36Sopenharmony_ci unsigned short qid, 124462306a36Sopenharmony_ci struct sk_buff **skb, 124562306a36Sopenharmony_ci unsigned short op_type) 124662306a36Sopenharmony_ci{ 124762306a36Sopenharmony_ci struct chcr_skcipher_req_ctx *reqctx = skcipher_request_ctx(req); 124862306a36Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 124962306a36Sopenharmony_ci unsigned int ivsize = crypto_skcipher_ivsize(tfm); 125062306a36Sopenharmony_ci struct ablk_ctx *ablkctx = ABLK_CTX(c_ctx(tfm)); 125162306a36Sopenharmony_ci struct adapter *adap = padap(c_ctx(tfm)->dev); 125262306a36Sopenharmony_ci struct cipher_wr_param wrparam; 125362306a36Sopenharmony_ci int bytes, err = -EINVAL; 125462306a36Sopenharmony_ci int subtype; 125562306a36Sopenharmony_ci 125662306a36Sopenharmony_ci reqctx->processed = 0; 125762306a36Sopenharmony_ci reqctx->partial_req = 0; 125862306a36Sopenharmony_ci if (!req->iv) 125962306a36Sopenharmony_ci goto error; 126062306a36Sopenharmony_ci subtype = get_cryptoalg_subtype(tfm); 126162306a36Sopenharmony_ci if ((ablkctx->enckey_len == 0) || (ivsize > AES_BLOCK_SIZE) || 126262306a36Sopenharmony_ci (req->cryptlen == 0) || 126362306a36Sopenharmony_ci (req->cryptlen % crypto_skcipher_blocksize(tfm))) { 126462306a36Sopenharmony_ci if (req->cryptlen == 0 && subtype != CRYPTO_ALG_SUB_TYPE_XTS) 126562306a36Sopenharmony_ci goto fallback; 126662306a36Sopenharmony_ci else if (req->cryptlen % crypto_skcipher_blocksize(tfm) && 126762306a36Sopenharmony_ci subtype == CRYPTO_ALG_SUB_TYPE_XTS) 126862306a36Sopenharmony_ci goto fallback; 126962306a36Sopenharmony_ci pr_err("AES: Invalid value of Key Len %d nbytes %d IV Len %d\n", 127062306a36Sopenharmony_ci ablkctx->enckey_len, req->cryptlen, ivsize); 127162306a36Sopenharmony_ci goto error; 127262306a36Sopenharmony_ci } 127362306a36Sopenharmony_ci 127462306a36Sopenharmony_ci err = chcr_cipher_dma_map(&ULD_CTX(c_ctx(tfm))->lldi.pdev->dev, req); 127562306a36Sopenharmony_ci if (err) 127662306a36Sopenharmony_ci goto error; 127762306a36Sopenharmony_ci if (req->cryptlen < (SGE_MAX_WR_LEN - (sizeof(struct chcr_wr) + 127862306a36Sopenharmony_ci AES_MIN_KEY_SIZE + 127962306a36Sopenharmony_ci sizeof(struct cpl_rx_phys_dsgl) + 128062306a36Sopenharmony_ci /*Min dsgl size*/ 128162306a36Sopenharmony_ci 32))) { 128262306a36Sopenharmony_ci /* Can be sent as Imm*/ 128362306a36Sopenharmony_ci unsigned int dnents = 0, transhdr_len, phys_dsgl, kctx_len; 128462306a36Sopenharmony_ci 128562306a36Sopenharmony_ci dnents = sg_nents_xlen(req->dst, req->cryptlen, 128662306a36Sopenharmony_ci CHCR_DST_SG_SIZE, 0); 128762306a36Sopenharmony_ci phys_dsgl = get_space_for_phys_dsgl(dnents); 128862306a36Sopenharmony_ci kctx_len = roundup(ablkctx->enckey_len, 16); 128962306a36Sopenharmony_ci transhdr_len = CIPHER_TRANSHDR_SIZE(kctx_len, phys_dsgl); 129062306a36Sopenharmony_ci reqctx->imm = (transhdr_len + IV + req->cryptlen) <= 129162306a36Sopenharmony_ci SGE_MAX_WR_LEN; 129262306a36Sopenharmony_ci bytes = IV + req->cryptlen; 129362306a36Sopenharmony_ci 129462306a36Sopenharmony_ci } else { 129562306a36Sopenharmony_ci reqctx->imm = 0; 129662306a36Sopenharmony_ci } 129762306a36Sopenharmony_ci 129862306a36Sopenharmony_ci if (!reqctx->imm) { 129962306a36Sopenharmony_ci bytes = chcr_sg_ent_in_wr(req->src, req->dst, 0, 130062306a36Sopenharmony_ci CIP_SPACE_LEFT(ablkctx->enckey_len), 130162306a36Sopenharmony_ci 0, 0); 130262306a36Sopenharmony_ci if ((bytes + reqctx->processed) >= req->cryptlen) 130362306a36Sopenharmony_ci bytes = req->cryptlen - reqctx->processed; 130462306a36Sopenharmony_ci else 130562306a36Sopenharmony_ci bytes = rounddown(bytes, 16); 130662306a36Sopenharmony_ci } else { 130762306a36Sopenharmony_ci bytes = req->cryptlen; 130862306a36Sopenharmony_ci } 130962306a36Sopenharmony_ci if (subtype == CRYPTO_ALG_SUB_TYPE_CTR) { 131062306a36Sopenharmony_ci bytes = adjust_ctr_overflow(req->iv, bytes); 131162306a36Sopenharmony_ci } 131262306a36Sopenharmony_ci if (subtype == CRYPTO_ALG_SUB_TYPE_CTR_RFC3686) { 131362306a36Sopenharmony_ci memcpy(reqctx->iv, ablkctx->nonce, CTR_RFC3686_NONCE_SIZE); 131462306a36Sopenharmony_ci memcpy(reqctx->iv + CTR_RFC3686_NONCE_SIZE, req->iv, 131562306a36Sopenharmony_ci CTR_RFC3686_IV_SIZE); 131662306a36Sopenharmony_ci 131762306a36Sopenharmony_ci /* initialize counter portion of counter block */ 131862306a36Sopenharmony_ci *(__be32 *)(reqctx->iv + CTR_RFC3686_NONCE_SIZE + 131962306a36Sopenharmony_ci CTR_RFC3686_IV_SIZE) = cpu_to_be32(1); 132062306a36Sopenharmony_ci memcpy(reqctx->init_iv, reqctx->iv, IV); 132162306a36Sopenharmony_ci 132262306a36Sopenharmony_ci } else { 132362306a36Sopenharmony_ci 132462306a36Sopenharmony_ci memcpy(reqctx->iv, req->iv, IV); 132562306a36Sopenharmony_ci memcpy(reqctx->init_iv, req->iv, IV); 132662306a36Sopenharmony_ci } 132762306a36Sopenharmony_ci if (unlikely(bytes == 0)) { 132862306a36Sopenharmony_ci chcr_cipher_dma_unmap(&ULD_CTX(c_ctx(tfm))->lldi.pdev->dev, 132962306a36Sopenharmony_ci req); 133062306a36Sopenharmony_cifallback: atomic_inc(&adap->chcr_stats.fallback); 133162306a36Sopenharmony_ci err = chcr_cipher_fallback(ablkctx->sw_cipher, req, 133262306a36Sopenharmony_ci subtype == 133362306a36Sopenharmony_ci CRYPTO_ALG_SUB_TYPE_CTR_RFC3686 ? 133462306a36Sopenharmony_ci reqctx->iv : req->iv, 133562306a36Sopenharmony_ci op_type); 133662306a36Sopenharmony_ci goto error; 133762306a36Sopenharmony_ci } 133862306a36Sopenharmony_ci reqctx->op = op_type; 133962306a36Sopenharmony_ci reqctx->srcsg = req->src; 134062306a36Sopenharmony_ci reqctx->dstsg = req->dst; 134162306a36Sopenharmony_ci reqctx->src_ofst = 0; 134262306a36Sopenharmony_ci reqctx->dst_ofst = 0; 134362306a36Sopenharmony_ci wrparam.qid = qid; 134462306a36Sopenharmony_ci wrparam.req = req; 134562306a36Sopenharmony_ci wrparam.bytes = bytes; 134662306a36Sopenharmony_ci *skb = create_cipher_wr(&wrparam); 134762306a36Sopenharmony_ci if (IS_ERR(*skb)) { 134862306a36Sopenharmony_ci err = PTR_ERR(*skb); 134962306a36Sopenharmony_ci goto unmap; 135062306a36Sopenharmony_ci } 135162306a36Sopenharmony_ci reqctx->processed = bytes; 135262306a36Sopenharmony_ci reqctx->last_req_len = bytes; 135362306a36Sopenharmony_ci reqctx->partial_req = !!(req->cryptlen - reqctx->processed); 135462306a36Sopenharmony_ci 135562306a36Sopenharmony_ci return 0; 135662306a36Sopenharmony_ciunmap: 135762306a36Sopenharmony_ci chcr_cipher_dma_unmap(&ULD_CTX(c_ctx(tfm))->lldi.pdev->dev, req); 135862306a36Sopenharmony_cierror: 135962306a36Sopenharmony_ci return err; 136062306a36Sopenharmony_ci} 136162306a36Sopenharmony_ci 136262306a36Sopenharmony_cistatic int chcr_aes_encrypt(struct skcipher_request *req) 136362306a36Sopenharmony_ci{ 136462306a36Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 136562306a36Sopenharmony_ci struct chcr_skcipher_req_ctx *reqctx = skcipher_request_ctx(req); 136662306a36Sopenharmony_ci struct chcr_dev *dev = c_ctx(tfm)->dev; 136762306a36Sopenharmony_ci struct sk_buff *skb = NULL; 136862306a36Sopenharmony_ci int err; 136962306a36Sopenharmony_ci struct uld_ctx *u_ctx = ULD_CTX(c_ctx(tfm)); 137062306a36Sopenharmony_ci struct chcr_context *ctx = c_ctx(tfm); 137162306a36Sopenharmony_ci unsigned int cpu; 137262306a36Sopenharmony_ci 137362306a36Sopenharmony_ci cpu = get_cpu(); 137462306a36Sopenharmony_ci reqctx->txqidx = cpu % ctx->ntxq; 137562306a36Sopenharmony_ci reqctx->rxqidx = cpu % ctx->nrxq; 137662306a36Sopenharmony_ci put_cpu(); 137762306a36Sopenharmony_ci 137862306a36Sopenharmony_ci err = chcr_inc_wrcount(dev); 137962306a36Sopenharmony_ci if (err) 138062306a36Sopenharmony_ci return -ENXIO; 138162306a36Sopenharmony_ci if (unlikely(cxgb4_is_crypto_q_full(u_ctx->lldi.ports[0], 138262306a36Sopenharmony_ci reqctx->txqidx) && 138362306a36Sopenharmony_ci (!(req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)))) { 138462306a36Sopenharmony_ci err = -ENOSPC; 138562306a36Sopenharmony_ci goto error; 138662306a36Sopenharmony_ci } 138762306a36Sopenharmony_ci 138862306a36Sopenharmony_ci err = process_cipher(req, u_ctx->lldi.rxq_ids[reqctx->rxqidx], 138962306a36Sopenharmony_ci &skb, CHCR_ENCRYPT_OP); 139062306a36Sopenharmony_ci if (err || !skb) 139162306a36Sopenharmony_ci return err; 139262306a36Sopenharmony_ci skb->dev = u_ctx->lldi.ports[0]; 139362306a36Sopenharmony_ci set_wr_txq(skb, CPL_PRIORITY_DATA, reqctx->txqidx); 139462306a36Sopenharmony_ci chcr_send_wr(skb); 139562306a36Sopenharmony_ci if (get_cryptoalg_subtype(tfm) == 139662306a36Sopenharmony_ci CRYPTO_ALG_SUB_TYPE_CBC && req->base.flags == 139762306a36Sopenharmony_ci CRYPTO_TFM_REQ_MAY_SLEEP ) { 139862306a36Sopenharmony_ci reqctx->partial_req = 1; 139962306a36Sopenharmony_ci wait_for_completion(&ctx->cbc_aes_aio_done); 140062306a36Sopenharmony_ci } 140162306a36Sopenharmony_ci return -EINPROGRESS; 140262306a36Sopenharmony_cierror: 140362306a36Sopenharmony_ci chcr_dec_wrcount(dev); 140462306a36Sopenharmony_ci return err; 140562306a36Sopenharmony_ci} 140662306a36Sopenharmony_ci 140762306a36Sopenharmony_cistatic int chcr_aes_decrypt(struct skcipher_request *req) 140862306a36Sopenharmony_ci{ 140962306a36Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 141062306a36Sopenharmony_ci struct chcr_skcipher_req_ctx *reqctx = skcipher_request_ctx(req); 141162306a36Sopenharmony_ci struct uld_ctx *u_ctx = ULD_CTX(c_ctx(tfm)); 141262306a36Sopenharmony_ci struct chcr_dev *dev = c_ctx(tfm)->dev; 141362306a36Sopenharmony_ci struct sk_buff *skb = NULL; 141462306a36Sopenharmony_ci int err; 141562306a36Sopenharmony_ci struct chcr_context *ctx = c_ctx(tfm); 141662306a36Sopenharmony_ci unsigned int cpu; 141762306a36Sopenharmony_ci 141862306a36Sopenharmony_ci cpu = get_cpu(); 141962306a36Sopenharmony_ci reqctx->txqidx = cpu % ctx->ntxq; 142062306a36Sopenharmony_ci reqctx->rxqidx = cpu % ctx->nrxq; 142162306a36Sopenharmony_ci put_cpu(); 142262306a36Sopenharmony_ci 142362306a36Sopenharmony_ci err = chcr_inc_wrcount(dev); 142462306a36Sopenharmony_ci if (err) 142562306a36Sopenharmony_ci return -ENXIO; 142662306a36Sopenharmony_ci 142762306a36Sopenharmony_ci if (unlikely(cxgb4_is_crypto_q_full(u_ctx->lldi.ports[0], 142862306a36Sopenharmony_ci reqctx->txqidx) && 142962306a36Sopenharmony_ci (!(req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)))) 143062306a36Sopenharmony_ci return -ENOSPC; 143162306a36Sopenharmony_ci err = process_cipher(req, u_ctx->lldi.rxq_ids[reqctx->rxqidx], 143262306a36Sopenharmony_ci &skb, CHCR_DECRYPT_OP); 143362306a36Sopenharmony_ci if (err || !skb) 143462306a36Sopenharmony_ci return err; 143562306a36Sopenharmony_ci skb->dev = u_ctx->lldi.ports[0]; 143662306a36Sopenharmony_ci set_wr_txq(skb, CPL_PRIORITY_DATA, reqctx->txqidx); 143762306a36Sopenharmony_ci chcr_send_wr(skb); 143862306a36Sopenharmony_ci return -EINPROGRESS; 143962306a36Sopenharmony_ci} 144062306a36Sopenharmony_cistatic int chcr_device_init(struct chcr_context *ctx) 144162306a36Sopenharmony_ci{ 144262306a36Sopenharmony_ci struct uld_ctx *u_ctx = NULL; 144362306a36Sopenharmony_ci int txq_perchan, ntxq; 144462306a36Sopenharmony_ci int err = 0, rxq_perchan; 144562306a36Sopenharmony_ci 144662306a36Sopenharmony_ci if (!ctx->dev) { 144762306a36Sopenharmony_ci u_ctx = assign_chcr_device(); 144862306a36Sopenharmony_ci if (!u_ctx) { 144962306a36Sopenharmony_ci err = -ENXIO; 145062306a36Sopenharmony_ci pr_err("chcr device assignment fails\n"); 145162306a36Sopenharmony_ci goto out; 145262306a36Sopenharmony_ci } 145362306a36Sopenharmony_ci ctx->dev = &u_ctx->dev; 145462306a36Sopenharmony_ci ntxq = u_ctx->lldi.ntxq; 145562306a36Sopenharmony_ci rxq_perchan = u_ctx->lldi.nrxq / u_ctx->lldi.nchan; 145662306a36Sopenharmony_ci txq_perchan = ntxq / u_ctx->lldi.nchan; 145762306a36Sopenharmony_ci ctx->ntxq = ntxq; 145862306a36Sopenharmony_ci ctx->nrxq = u_ctx->lldi.nrxq; 145962306a36Sopenharmony_ci ctx->rxq_perchan = rxq_perchan; 146062306a36Sopenharmony_ci ctx->txq_perchan = txq_perchan; 146162306a36Sopenharmony_ci } 146262306a36Sopenharmony_ciout: 146362306a36Sopenharmony_ci return err; 146462306a36Sopenharmony_ci} 146562306a36Sopenharmony_ci 146662306a36Sopenharmony_cistatic int chcr_init_tfm(struct crypto_skcipher *tfm) 146762306a36Sopenharmony_ci{ 146862306a36Sopenharmony_ci struct skcipher_alg *alg = crypto_skcipher_alg(tfm); 146962306a36Sopenharmony_ci struct chcr_context *ctx = crypto_skcipher_ctx(tfm); 147062306a36Sopenharmony_ci struct ablk_ctx *ablkctx = ABLK_CTX(ctx); 147162306a36Sopenharmony_ci 147262306a36Sopenharmony_ci ablkctx->sw_cipher = crypto_alloc_skcipher(alg->base.cra_name, 0, 147362306a36Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK); 147462306a36Sopenharmony_ci if (IS_ERR(ablkctx->sw_cipher)) { 147562306a36Sopenharmony_ci pr_err("failed to allocate fallback for %s\n", alg->base.cra_name); 147662306a36Sopenharmony_ci return PTR_ERR(ablkctx->sw_cipher); 147762306a36Sopenharmony_ci } 147862306a36Sopenharmony_ci init_completion(&ctx->cbc_aes_aio_done); 147962306a36Sopenharmony_ci crypto_skcipher_set_reqsize(tfm, sizeof(struct chcr_skcipher_req_ctx) + 148062306a36Sopenharmony_ci crypto_skcipher_reqsize(ablkctx->sw_cipher)); 148162306a36Sopenharmony_ci 148262306a36Sopenharmony_ci return chcr_device_init(ctx); 148362306a36Sopenharmony_ci} 148462306a36Sopenharmony_ci 148562306a36Sopenharmony_cistatic int chcr_rfc3686_init(struct crypto_skcipher *tfm) 148662306a36Sopenharmony_ci{ 148762306a36Sopenharmony_ci struct skcipher_alg *alg = crypto_skcipher_alg(tfm); 148862306a36Sopenharmony_ci struct chcr_context *ctx = crypto_skcipher_ctx(tfm); 148962306a36Sopenharmony_ci struct ablk_ctx *ablkctx = ABLK_CTX(ctx); 149062306a36Sopenharmony_ci 149162306a36Sopenharmony_ci /*RFC3686 initialises IV counter value to 1, rfc3686(ctr(aes)) 149262306a36Sopenharmony_ci * cannot be used as fallback in chcr_handle_cipher_response 149362306a36Sopenharmony_ci */ 149462306a36Sopenharmony_ci ablkctx->sw_cipher = crypto_alloc_skcipher("ctr(aes)", 0, 149562306a36Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK); 149662306a36Sopenharmony_ci if (IS_ERR(ablkctx->sw_cipher)) { 149762306a36Sopenharmony_ci pr_err("failed to allocate fallback for %s\n", alg->base.cra_name); 149862306a36Sopenharmony_ci return PTR_ERR(ablkctx->sw_cipher); 149962306a36Sopenharmony_ci } 150062306a36Sopenharmony_ci crypto_skcipher_set_reqsize(tfm, sizeof(struct chcr_skcipher_req_ctx) + 150162306a36Sopenharmony_ci crypto_skcipher_reqsize(ablkctx->sw_cipher)); 150262306a36Sopenharmony_ci return chcr_device_init(ctx); 150362306a36Sopenharmony_ci} 150462306a36Sopenharmony_ci 150562306a36Sopenharmony_ci 150662306a36Sopenharmony_cistatic void chcr_exit_tfm(struct crypto_skcipher *tfm) 150762306a36Sopenharmony_ci{ 150862306a36Sopenharmony_ci struct chcr_context *ctx = crypto_skcipher_ctx(tfm); 150962306a36Sopenharmony_ci struct ablk_ctx *ablkctx = ABLK_CTX(ctx); 151062306a36Sopenharmony_ci 151162306a36Sopenharmony_ci crypto_free_skcipher(ablkctx->sw_cipher); 151262306a36Sopenharmony_ci} 151362306a36Sopenharmony_ci 151462306a36Sopenharmony_cistatic int get_alg_config(struct algo_param *params, 151562306a36Sopenharmony_ci unsigned int auth_size) 151662306a36Sopenharmony_ci{ 151762306a36Sopenharmony_ci switch (auth_size) { 151862306a36Sopenharmony_ci case SHA1_DIGEST_SIZE: 151962306a36Sopenharmony_ci params->mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_160; 152062306a36Sopenharmony_ci params->auth_mode = CHCR_SCMD_AUTH_MODE_SHA1; 152162306a36Sopenharmony_ci params->result_size = SHA1_DIGEST_SIZE; 152262306a36Sopenharmony_ci break; 152362306a36Sopenharmony_ci case SHA224_DIGEST_SIZE: 152462306a36Sopenharmony_ci params->mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_256; 152562306a36Sopenharmony_ci params->auth_mode = CHCR_SCMD_AUTH_MODE_SHA224; 152662306a36Sopenharmony_ci params->result_size = SHA256_DIGEST_SIZE; 152762306a36Sopenharmony_ci break; 152862306a36Sopenharmony_ci case SHA256_DIGEST_SIZE: 152962306a36Sopenharmony_ci params->mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_256; 153062306a36Sopenharmony_ci params->auth_mode = CHCR_SCMD_AUTH_MODE_SHA256; 153162306a36Sopenharmony_ci params->result_size = SHA256_DIGEST_SIZE; 153262306a36Sopenharmony_ci break; 153362306a36Sopenharmony_ci case SHA384_DIGEST_SIZE: 153462306a36Sopenharmony_ci params->mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_512; 153562306a36Sopenharmony_ci params->auth_mode = CHCR_SCMD_AUTH_MODE_SHA512_384; 153662306a36Sopenharmony_ci params->result_size = SHA512_DIGEST_SIZE; 153762306a36Sopenharmony_ci break; 153862306a36Sopenharmony_ci case SHA512_DIGEST_SIZE: 153962306a36Sopenharmony_ci params->mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_512; 154062306a36Sopenharmony_ci params->auth_mode = CHCR_SCMD_AUTH_MODE_SHA512_512; 154162306a36Sopenharmony_ci params->result_size = SHA512_DIGEST_SIZE; 154262306a36Sopenharmony_ci break; 154362306a36Sopenharmony_ci default: 154462306a36Sopenharmony_ci pr_err("ERROR, unsupported digest size\n"); 154562306a36Sopenharmony_ci return -EINVAL; 154662306a36Sopenharmony_ci } 154762306a36Sopenharmony_ci return 0; 154862306a36Sopenharmony_ci} 154962306a36Sopenharmony_ci 155062306a36Sopenharmony_cistatic inline void chcr_free_shash(struct crypto_shash *base_hash) 155162306a36Sopenharmony_ci{ 155262306a36Sopenharmony_ci crypto_free_shash(base_hash); 155362306a36Sopenharmony_ci} 155462306a36Sopenharmony_ci 155562306a36Sopenharmony_ci/** 155662306a36Sopenharmony_ci * create_hash_wr - Create hash work request 155762306a36Sopenharmony_ci * @req: Cipher req base 155862306a36Sopenharmony_ci * @param: Container for create_hash_wr()'s parameters 155962306a36Sopenharmony_ci */ 156062306a36Sopenharmony_cistatic struct sk_buff *create_hash_wr(struct ahash_request *req, 156162306a36Sopenharmony_ci struct hash_wr_param *param) 156262306a36Sopenharmony_ci{ 156362306a36Sopenharmony_ci struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(req); 156462306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 156562306a36Sopenharmony_ci struct chcr_context *ctx = h_ctx(tfm); 156662306a36Sopenharmony_ci struct hmac_ctx *hmacctx = HMAC_CTX(ctx); 156762306a36Sopenharmony_ci struct sk_buff *skb = NULL; 156862306a36Sopenharmony_ci struct uld_ctx *u_ctx = ULD_CTX(ctx); 156962306a36Sopenharmony_ci struct chcr_wr *chcr_req; 157062306a36Sopenharmony_ci struct ulptx_sgl *ulptx; 157162306a36Sopenharmony_ci unsigned int nents = 0, transhdr_len; 157262306a36Sopenharmony_ci unsigned int temp = 0; 157362306a36Sopenharmony_ci gfp_t flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL : 157462306a36Sopenharmony_ci GFP_ATOMIC; 157562306a36Sopenharmony_ci struct adapter *adap = padap(h_ctx(tfm)->dev); 157662306a36Sopenharmony_ci int error = 0; 157762306a36Sopenharmony_ci unsigned int rx_channel_id = req_ctx->rxqidx / ctx->rxq_perchan; 157862306a36Sopenharmony_ci 157962306a36Sopenharmony_ci rx_channel_id = cxgb4_port_e2cchan(u_ctx->lldi.ports[rx_channel_id]); 158062306a36Sopenharmony_ci transhdr_len = HASH_TRANSHDR_SIZE(param->kctx_len); 158162306a36Sopenharmony_ci req_ctx->hctx_wr.imm = (transhdr_len + param->bfr_len + 158262306a36Sopenharmony_ci param->sg_len) <= SGE_MAX_WR_LEN; 158362306a36Sopenharmony_ci nents = sg_nents_xlen(req_ctx->hctx_wr.srcsg, param->sg_len, 158462306a36Sopenharmony_ci CHCR_SRC_SG_SIZE, req_ctx->hctx_wr.src_ofst); 158562306a36Sopenharmony_ci nents += param->bfr_len ? 1 : 0; 158662306a36Sopenharmony_ci transhdr_len += req_ctx->hctx_wr.imm ? roundup(param->bfr_len + 158762306a36Sopenharmony_ci param->sg_len, 16) : (sgl_len(nents) * 8); 158862306a36Sopenharmony_ci transhdr_len = roundup(transhdr_len, 16); 158962306a36Sopenharmony_ci 159062306a36Sopenharmony_ci skb = alloc_skb(transhdr_len, flags); 159162306a36Sopenharmony_ci if (!skb) 159262306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 159362306a36Sopenharmony_ci chcr_req = __skb_put_zero(skb, transhdr_len); 159462306a36Sopenharmony_ci 159562306a36Sopenharmony_ci chcr_req->sec_cpl.op_ivinsrtofst = 159662306a36Sopenharmony_ci FILL_SEC_CPL_OP_IVINSR(rx_channel_id, 2, 0); 159762306a36Sopenharmony_ci 159862306a36Sopenharmony_ci chcr_req->sec_cpl.pldlen = htonl(param->bfr_len + param->sg_len); 159962306a36Sopenharmony_ci 160062306a36Sopenharmony_ci chcr_req->sec_cpl.aadstart_cipherstop_hi = 160162306a36Sopenharmony_ci FILL_SEC_CPL_CIPHERSTOP_HI(0, 0, 0, 0); 160262306a36Sopenharmony_ci chcr_req->sec_cpl.cipherstop_lo_authinsert = 160362306a36Sopenharmony_ci FILL_SEC_CPL_AUTHINSERT(0, 1, 0, 0); 160462306a36Sopenharmony_ci chcr_req->sec_cpl.seqno_numivs = 160562306a36Sopenharmony_ci FILL_SEC_CPL_SCMD0_SEQNO(0, 0, 0, param->alg_prm.auth_mode, 160662306a36Sopenharmony_ci param->opad_needed, 0); 160762306a36Sopenharmony_ci 160862306a36Sopenharmony_ci chcr_req->sec_cpl.ivgen_hdrlen = 160962306a36Sopenharmony_ci FILL_SEC_CPL_IVGEN_HDRLEN(param->last, param->more, 0, 1, 0, 0); 161062306a36Sopenharmony_ci 161162306a36Sopenharmony_ci memcpy(chcr_req->key_ctx.key, req_ctx->partial_hash, 161262306a36Sopenharmony_ci param->alg_prm.result_size); 161362306a36Sopenharmony_ci 161462306a36Sopenharmony_ci if (param->opad_needed) 161562306a36Sopenharmony_ci memcpy(chcr_req->key_ctx.key + 161662306a36Sopenharmony_ci ((param->alg_prm.result_size <= 32) ? 32 : 161762306a36Sopenharmony_ci CHCR_HASH_MAX_DIGEST_SIZE), 161862306a36Sopenharmony_ci hmacctx->opad, param->alg_prm.result_size); 161962306a36Sopenharmony_ci 162062306a36Sopenharmony_ci chcr_req->key_ctx.ctx_hdr = FILL_KEY_CTX_HDR(CHCR_KEYCTX_NO_KEY, 162162306a36Sopenharmony_ci param->alg_prm.mk_size, 0, 162262306a36Sopenharmony_ci param->opad_needed, 162362306a36Sopenharmony_ci ((param->kctx_len + 162462306a36Sopenharmony_ci sizeof(chcr_req->key_ctx)) >> 4)); 162562306a36Sopenharmony_ci chcr_req->sec_cpl.scmd1 = cpu_to_be64((u64)param->scmd1); 162662306a36Sopenharmony_ci ulptx = (struct ulptx_sgl *)((u8 *)(chcr_req + 1) + param->kctx_len + 162762306a36Sopenharmony_ci DUMMY_BYTES); 162862306a36Sopenharmony_ci if (param->bfr_len != 0) { 162962306a36Sopenharmony_ci req_ctx->hctx_wr.dma_addr = 163062306a36Sopenharmony_ci dma_map_single(&u_ctx->lldi.pdev->dev, req_ctx->reqbfr, 163162306a36Sopenharmony_ci param->bfr_len, DMA_TO_DEVICE); 163262306a36Sopenharmony_ci if (dma_mapping_error(&u_ctx->lldi.pdev->dev, 163362306a36Sopenharmony_ci req_ctx->hctx_wr. dma_addr)) { 163462306a36Sopenharmony_ci error = -ENOMEM; 163562306a36Sopenharmony_ci goto err; 163662306a36Sopenharmony_ci } 163762306a36Sopenharmony_ci req_ctx->hctx_wr.dma_len = param->bfr_len; 163862306a36Sopenharmony_ci } else { 163962306a36Sopenharmony_ci req_ctx->hctx_wr.dma_addr = 0; 164062306a36Sopenharmony_ci } 164162306a36Sopenharmony_ci chcr_add_hash_src_ent(req, ulptx, param); 164262306a36Sopenharmony_ci /* Request upto max wr size */ 164362306a36Sopenharmony_ci temp = param->kctx_len + DUMMY_BYTES + (req_ctx->hctx_wr.imm ? 164462306a36Sopenharmony_ci (param->sg_len + param->bfr_len) : 0); 164562306a36Sopenharmony_ci atomic_inc(&adap->chcr_stats.digest_rqst); 164662306a36Sopenharmony_ci create_wreq(h_ctx(tfm), chcr_req, &req->base, req_ctx->hctx_wr.imm, 164762306a36Sopenharmony_ci param->hash_size, transhdr_len, 164862306a36Sopenharmony_ci temp, 0); 164962306a36Sopenharmony_ci req_ctx->hctx_wr.skb = skb; 165062306a36Sopenharmony_ci return skb; 165162306a36Sopenharmony_cierr: 165262306a36Sopenharmony_ci kfree_skb(skb); 165362306a36Sopenharmony_ci return ERR_PTR(error); 165462306a36Sopenharmony_ci} 165562306a36Sopenharmony_ci 165662306a36Sopenharmony_cistatic int chcr_ahash_update(struct ahash_request *req) 165762306a36Sopenharmony_ci{ 165862306a36Sopenharmony_ci struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(req); 165962306a36Sopenharmony_ci struct crypto_ahash *rtfm = crypto_ahash_reqtfm(req); 166062306a36Sopenharmony_ci struct uld_ctx *u_ctx = ULD_CTX(h_ctx(rtfm)); 166162306a36Sopenharmony_ci struct chcr_context *ctx = h_ctx(rtfm); 166262306a36Sopenharmony_ci struct chcr_dev *dev = h_ctx(rtfm)->dev; 166362306a36Sopenharmony_ci struct sk_buff *skb; 166462306a36Sopenharmony_ci u8 remainder = 0, bs; 166562306a36Sopenharmony_ci unsigned int nbytes = req->nbytes; 166662306a36Sopenharmony_ci struct hash_wr_param params; 166762306a36Sopenharmony_ci int error; 166862306a36Sopenharmony_ci unsigned int cpu; 166962306a36Sopenharmony_ci 167062306a36Sopenharmony_ci cpu = get_cpu(); 167162306a36Sopenharmony_ci req_ctx->txqidx = cpu % ctx->ntxq; 167262306a36Sopenharmony_ci req_ctx->rxqidx = cpu % ctx->nrxq; 167362306a36Sopenharmony_ci put_cpu(); 167462306a36Sopenharmony_ci 167562306a36Sopenharmony_ci bs = crypto_tfm_alg_blocksize(crypto_ahash_tfm(rtfm)); 167662306a36Sopenharmony_ci 167762306a36Sopenharmony_ci if (nbytes + req_ctx->reqlen >= bs) { 167862306a36Sopenharmony_ci remainder = (nbytes + req_ctx->reqlen) % bs; 167962306a36Sopenharmony_ci nbytes = nbytes + req_ctx->reqlen - remainder; 168062306a36Sopenharmony_ci } else { 168162306a36Sopenharmony_ci sg_pcopy_to_buffer(req->src, sg_nents(req->src), req_ctx->reqbfr 168262306a36Sopenharmony_ci + req_ctx->reqlen, nbytes, 0); 168362306a36Sopenharmony_ci req_ctx->reqlen += nbytes; 168462306a36Sopenharmony_ci return 0; 168562306a36Sopenharmony_ci } 168662306a36Sopenharmony_ci error = chcr_inc_wrcount(dev); 168762306a36Sopenharmony_ci if (error) 168862306a36Sopenharmony_ci return -ENXIO; 168962306a36Sopenharmony_ci /* Detach state for CHCR means lldi or padap is freed. Increasing 169062306a36Sopenharmony_ci * inflight count for dev guarantees that lldi and padap is valid 169162306a36Sopenharmony_ci */ 169262306a36Sopenharmony_ci if (unlikely(cxgb4_is_crypto_q_full(u_ctx->lldi.ports[0], 169362306a36Sopenharmony_ci req_ctx->txqidx) && 169462306a36Sopenharmony_ci (!(req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)))) { 169562306a36Sopenharmony_ci error = -ENOSPC; 169662306a36Sopenharmony_ci goto err; 169762306a36Sopenharmony_ci } 169862306a36Sopenharmony_ci 169962306a36Sopenharmony_ci chcr_init_hctx_per_wr(req_ctx); 170062306a36Sopenharmony_ci error = chcr_hash_dma_map(&u_ctx->lldi.pdev->dev, req); 170162306a36Sopenharmony_ci if (error) { 170262306a36Sopenharmony_ci error = -ENOMEM; 170362306a36Sopenharmony_ci goto err; 170462306a36Sopenharmony_ci } 170562306a36Sopenharmony_ci get_alg_config(¶ms.alg_prm, crypto_ahash_digestsize(rtfm)); 170662306a36Sopenharmony_ci params.kctx_len = roundup(params.alg_prm.result_size, 16); 170762306a36Sopenharmony_ci params.sg_len = chcr_hash_ent_in_wr(req->src, !!req_ctx->reqlen, 170862306a36Sopenharmony_ci HASH_SPACE_LEFT(params.kctx_len), 0); 170962306a36Sopenharmony_ci if (params.sg_len > req->nbytes) 171062306a36Sopenharmony_ci params.sg_len = req->nbytes; 171162306a36Sopenharmony_ci params.sg_len = rounddown(params.sg_len + req_ctx->reqlen, bs) - 171262306a36Sopenharmony_ci req_ctx->reqlen; 171362306a36Sopenharmony_ci params.opad_needed = 0; 171462306a36Sopenharmony_ci params.more = 1; 171562306a36Sopenharmony_ci params.last = 0; 171662306a36Sopenharmony_ci params.bfr_len = req_ctx->reqlen; 171762306a36Sopenharmony_ci params.scmd1 = 0; 171862306a36Sopenharmony_ci req_ctx->hctx_wr.srcsg = req->src; 171962306a36Sopenharmony_ci 172062306a36Sopenharmony_ci params.hash_size = params.alg_prm.result_size; 172162306a36Sopenharmony_ci req_ctx->data_len += params.sg_len + params.bfr_len; 172262306a36Sopenharmony_ci skb = create_hash_wr(req, ¶ms); 172362306a36Sopenharmony_ci if (IS_ERR(skb)) { 172462306a36Sopenharmony_ci error = PTR_ERR(skb); 172562306a36Sopenharmony_ci goto unmap; 172662306a36Sopenharmony_ci } 172762306a36Sopenharmony_ci 172862306a36Sopenharmony_ci req_ctx->hctx_wr.processed += params.sg_len; 172962306a36Sopenharmony_ci if (remainder) { 173062306a36Sopenharmony_ci /* Swap buffers */ 173162306a36Sopenharmony_ci swap(req_ctx->reqbfr, req_ctx->skbfr); 173262306a36Sopenharmony_ci sg_pcopy_to_buffer(req->src, sg_nents(req->src), 173362306a36Sopenharmony_ci req_ctx->reqbfr, remainder, req->nbytes - 173462306a36Sopenharmony_ci remainder); 173562306a36Sopenharmony_ci } 173662306a36Sopenharmony_ci req_ctx->reqlen = remainder; 173762306a36Sopenharmony_ci skb->dev = u_ctx->lldi.ports[0]; 173862306a36Sopenharmony_ci set_wr_txq(skb, CPL_PRIORITY_DATA, req_ctx->txqidx); 173962306a36Sopenharmony_ci chcr_send_wr(skb); 174062306a36Sopenharmony_ci return -EINPROGRESS; 174162306a36Sopenharmony_ciunmap: 174262306a36Sopenharmony_ci chcr_hash_dma_unmap(&u_ctx->lldi.pdev->dev, req); 174362306a36Sopenharmony_cierr: 174462306a36Sopenharmony_ci chcr_dec_wrcount(dev); 174562306a36Sopenharmony_ci return error; 174662306a36Sopenharmony_ci} 174762306a36Sopenharmony_ci 174862306a36Sopenharmony_cistatic void create_last_hash_block(char *bfr_ptr, unsigned int bs, u64 scmd1) 174962306a36Sopenharmony_ci{ 175062306a36Sopenharmony_ci memset(bfr_ptr, 0, bs); 175162306a36Sopenharmony_ci *bfr_ptr = 0x80; 175262306a36Sopenharmony_ci if (bs == 64) 175362306a36Sopenharmony_ci *(__be64 *)(bfr_ptr + 56) = cpu_to_be64(scmd1 << 3); 175462306a36Sopenharmony_ci else 175562306a36Sopenharmony_ci *(__be64 *)(bfr_ptr + 120) = cpu_to_be64(scmd1 << 3); 175662306a36Sopenharmony_ci} 175762306a36Sopenharmony_ci 175862306a36Sopenharmony_cistatic int chcr_ahash_final(struct ahash_request *req) 175962306a36Sopenharmony_ci{ 176062306a36Sopenharmony_ci struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(req); 176162306a36Sopenharmony_ci struct crypto_ahash *rtfm = crypto_ahash_reqtfm(req); 176262306a36Sopenharmony_ci struct chcr_dev *dev = h_ctx(rtfm)->dev; 176362306a36Sopenharmony_ci struct hash_wr_param params; 176462306a36Sopenharmony_ci struct sk_buff *skb; 176562306a36Sopenharmony_ci struct uld_ctx *u_ctx = ULD_CTX(h_ctx(rtfm)); 176662306a36Sopenharmony_ci struct chcr_context *ctx = h_ctx(rtfm); 176762306a36Sopenharmony_ci u8 bs = crypto_tfm_alg_blocksize(crypto_ahash_tfm(rtfm)); 176862306a36Sopenharmony_ci int error; 176962306a36Sopenharmony_ci unsigned int cpu; 177062306a36Sopenharmony_ci 177162306a36Sopenharmony_ci cpu = get_cpu(); 177262306a36Sopenharmony_ci req_ctx->txqidx = cpu % ctx->ntxq; 177362306a36Sopenharmony_ci req_ctx->rxqidx = cpu % ctx->nrxq; 177462306a36Sopenharmony_ci put_cpu(); 177562306a36Sopenharmony_ci 177662306a36Sopenharmony_ci error = chcr_inc_wrcount(dev); 177762306a36Sopenharmony_ci if (error) 177862306a36Sopenharmony_ci return -ENXIO; 177962306a36Sopenharmony_ci 178062306a36Sopenharmony_ci chcr_init_hctx_per_wr(req_ctx); 178162306a36Sopenharmony_ci if (is_hmac(crypto_ahash_tfm(rtfm))) 178262306a36Sopenharmony_ci params.opad_needed = 1; 178362306a36Sopenharmony_ci else 178462306a36Sopenharmony_ci params.opad_needed = 0; 178562306a36Sopenharmony_ci params.sg_len = 0; 178662306a36Sopenharmony_ci req_ctx->hctx_wr.isfinal = 1; 178762306a36Sopenharmony_ci get_alg_config(¶ms.alg_prm, crypto_ahash_digestsize(rtfm)); 178862306a36Sopenharmony_ci params.kctx_len = roundup(params.alg_prm.result_size, 16); 178962306a36Sopenharmony_ci if (is_hmac(crypto_ahash_tfm(rtfm))) { 179062306a36Sopenharmony_ci params.opad_needed = 1; 179162306a36Sopenharmony_ci params.kctx_len *= 2; 179262306a36Sopenharmony_ci } else { 179362306a36Sopenharmony_ci params.opad_needed = 0; 179462306a36Sopenharmony_ci } 179562306a36Sopenharmony_ci 179662306a36Sopenharmony_ci req_ctx->hctx_wr.result = 1; 179762306a36Sopenharmony_ci params.bfr_len = req_ctx->reqlen; 179862306a36Sopenharmony_ci req_ctx->data_len += params.bfr_len + params.sg_len; 179962306a36Sopenharmony_ci req_ctx->hctx_wr.srcsg = req->src; 180062306a36Sopenharmony_ci if (req_ctx->reqlen == 0) { 180162306a36Sopenharmony_ci create_last_hash_block(req_ctx->reqbfr, bs, req_ctx->data_len); 180262306a36Sopenharmony_ci params.last = 0; 180362306a36Sopenharmony_ci params.more = 1; 180462306a36Sopenharmony_ci params.scmd1 = 0; 180562306a36Sopenharmony_ci params.bfr_len = bs; 180662306a36Sopenharmony_ci 180762306a36Sopenharmony_ci } else { 180862306a36Sopenharmony_ci params.scmd1 = req_ctx->data_len; 180962306a36Sopenharmony_ci params.last = 1; 181062306a36Sopenharmony_ci params.more = 0; 181162306a36Sopenharmony_ci } 181262306a36Sopenharmony_ci params.hash_size = crypto_ahash_digestsize(rtfm); 181362306a36Sopenharmony_ci skb = create_hash_wr(req, ¶ms); 181462306a36Sopenharmony_ci if (IS_ERR(skb)) { 181562306a36Sopenharmony_ci error = PTR_ERR(skb); 181662306a36Sopenharmony_ci goto err; 181762306a36Sopenharmony_ci } 181862306a36Sopenharmony_ci req_ctx->reqlen = 0; 181962306a36Sopenharmony_ci skb->dev = u_ctx->lldi.ports[0]; 182062306a36Sopenharmony_ci set_wr_txq(skb, CPL_PRIORITY_DATA, req_ctx->txqidx); 182162306a36Sopenharmony_ci chcr_send_wr(skb); 182262306a36Sopenharmony_ci return -EINPROGRESS; 182362306a36Sopenharmony_cierr: 182462306a36Sopenharmony_ci chcr_dec_wrcount(dev); 182562306a36Sopenharmony_ci return error; 182662306a36Sopenharmony_ci} 182762306a36Sopenharmony_ci 182862306a36Sopenharmony_cistatic int chcr_ahash_finup(struct ahash_request *req) 182962306a36Sopenharmony_ci{ 183062306a36Sopenharmony_ci struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(req); 183162306a36Sopenharmony_ci struct crypto_ahash *rtfm = crypto_ahash_reqtfm(req); 183262306a36Sopenharmony_ci struct chcr_dev *dev = h_ctx(rtfm)->dev; 183362306a36Sopenharmony_ci struct uld_ctx *u_ctx = ULD_CTX(h_ctx(rtfm)); 183462306a36Sopenharmony_ci struct chcr_context *ctx = h_ctx(rtfm); 183562306a36Sopenharmony_ci struct sk_buff *skb; 183662306a36Sopenharmony_ci struct hash_wr_param params; 183762306a36Sopenharmony_ci u8 bs; 183862306a36Sopenharmony_ci int error; 183962306a36Sopenharmony_ci unsigned int cpu; 184062306a36Sopenharmony_ci 184162306a36Sopenharmony_ci cpu = get_cpu(); 184262306a36Sopenharmony_ci req_ctx->txqidx = cpu % ctx->ntxq; 184362306a36Sopenharmony_ci req_ctx->rxqidx = cpu % ctx->nrxq; 184462306a36Sopenharmony_ci put_cpu(); 184562306a36Sopenharmony_ci 184662306a36Sopenharmony_ci bs = crypto_tfm_alg_blocksize(crypto_ahash_tfm(rtfm)); 184762306a36Sopenharmony_ci error = chcr_inc_wrcount(dev); 184862306a36Sopenharmony_ci if (error) 184962306a36Sopenharmony_ci return -ENXIO; 185062306a36Sopenharmony_ci 185162306a36Sopenharmony_ci if (unlikely(cxgb4_is_crypto_q_full(u_ctx->lldi.ports[0], 185262306a36Sopenharmony_ci req_ctx->txqidx) && 185362306a36Sopenharmony_ci (!(req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)))) { 185462306a36Sopenharmony_ci error = -ENOSPC; 185562306a36Sopenharmony_ci goto err; 185662306a36Sopenharmony_ci } 185762306a36Sopenharmony_ci chcr_init_hctx_per_wr(req_ctx); 185862306a36Sopenharmony_ci error = chcr_hash_dma_map(&u_ctx->lldi.pdev->dev, req); 185962306a36Sopenharmony_ci if (error) { 186062306a36Sopenharmony_ci error = -ENOMEM; 186162306a36Sopenharmony_ci goto err; 186262306a36Sopenharmony_ci } 186362306a36Sopenharmony_ci 186462306a36Sopenharmony_ci get_alg_config(¶ms.alg_prm, crypto_ahash_digestsize(rtfm)); 186562306a36Sopenharmony_ci params.kctx_len = roundup(params.alg_prm.result_size, 16); 186662306a36Sopenharmony_ci if (is_hmac(crypto_ahash_tfm(rtfm))) { 186762306a36Sopenharmony_ci params.kctx_len *= 2; 186862306a36Sopenharmony_ci params.opad_needed = 1; 186962306a36Sopenharmony_ci } else { 187062306a36Sopenharmony_ci params.opad_needed = 0; 187162306a36Sopenharmony_ci } 187262306a36Sopenharmony_ci 187362306a36Sopenharmony_ci params.sg_len = chcr_hash_ent_in_wr(req->src, !!req_ctx->reqlen, 187462306a36Sopenharmony_ci HASH_SPACE_LEFT(params.kctx_len), 0); 187562306a36Sopenharmony_ci if (params.sg_len < req->nbytes) { 187662306a36Sopenharmony_ci if (is_hmac(crypto_ahash_tfm(rtfm))) { 187762306a36Sopenharmony_ci params.kctx_len /= 2; 187862306a36Sopenharmony_ci params.opad_needed = 0; 187962306a36Sopenharmony_ci } 188062306a36Sopenharmony_ci params.last = 0; 188162306a36Sopenharmony_ci params.more = 1; 188262306a36Sopenharmony_ci params.sg_len = rounddown(params.sg_len + req_ctx->reqlen, bs) 188362306a36Sopenharmony_ci - req_ctx->reqlen; 188462306a36Sopenharmony_ci params.hash_size = params.alg_prm.result_size; 188562306a36Sopenharmony_ci params.scmd1 = 0; 188662306a36Sopenharmony_ci } else { 188762306a36Sopenharmony_ci params.last = 1; 188862306a36Sopenharmony_ci params.more = 0; 188962306a36Sopenharmony_ci params.sg_len = req->nbytes; 189062306a36Sopenharmony_ci params.hash_size = crypto_ahash_digestsize(rtfm); 189162306a36Sopenharmony_ci params.scmd1 = req_ctx->data_len + req_ctx->reqlen + 189262306a36Sopenharmony_ci params.sg_len; 189362306a36Sopenharmony_ci } 189462306a36Sopenharmony_ci params.bfr_len = req_ctx->reqlen; 189562306a36Sopenharmony_ci req_ctx->data_len += params.bfr_len + params.sg_len; 189662306a36Sopenharmony_ci req_ctx->hctx_wr.result = 1; 189762306a36Sopenharmony_ci req_ctx->hctx_wr.srcsg = req->src; 189862306a36Sopenharmony_ci if ((req_ctx->reqlen + req->nbytes) == 0) { 189962306a36Sopenharmony_ci create_last_hash_block(req_ctx->reqbfr, bs, req_ctx->data_len); 190062306a36Sopenharmony_ci params.last = 0; 190162306a36Sopenharmony_ci params.more = 1; 190262306a36Sopenharmony_ci params.scmd1 = 0; 190362306a36Sopenharmony_ci params.bfr_len = bs; 190462306a36Sopenharmony_ci } 190562306a36Sopenharmony_ci skb = create_hash_wr(req, ¶ms); 190662306a36Sopenharmony_ci if (IS_ERR(skb)) { 190762306a36Sopenharmony_ci error = PTR_ERR(skb); 190862306a36Sopenharmony_ci goto unmap; 190962306a36Sopenharmony_ci } 191062306a36Sopenharmony_ci req_ctx->reqlen = 0; 191162306a36Sopenharmony_ci req_ctx->hctx_wr.processed += params.sg_len; 191262306a36Sopenharmony_ci skb->dev = u_ctx->lldi.ports[0]; 191362306a36Sopenharmony_ci set_wr_txq(skb, CPL_PRIORITY_DATA, req_ctx->txqidx); 191462306a36Sopenharmony_ci chcr_send_wr(skb); 191562306a36Sopenharmony_ci return -EINPROGRESS; 191662306a36Sopenharmony_ciunmap: 191762306a36Sopenharmony_ci chcr_hash_dma_unmap(&u_ctx->lldi.pdev->dev, req); 191862306a36Sopenharmony_cierr: 191962306a36Sopenharmony_ci chcr_dec_wrcount(dev); 192062306a36Sopenharmony_ci return error; 192162306a36Sopenharmony_ci} 192262306a36Sopenharmony_ci 192362306a36Sopenharmony_cistatic int chcr_ahash_digest(struct ahash_request *req) 192462306a36Sopenharmony_ci{ 192562306a36Sopenharmony_ci struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(req); 192662306a36Sopenharmony_ci struct crypto_ahash *rtfm = crypto_ahash_reqtfm(req); 192762306a36Sopenharmony_ci struct chcr_dev *dev = h_ctx(rtfm)->dev; 192862306a36Sopenharmony_ci struct uld_ctx *u_ctx = ULD_CTX(h_ctx(rtfm)); 192962306a36Sopenharmony_ci struct chcr_context *ctx = h_ctx(rtfm); 193062306a36Sopenharmony_ci struct sk_buff *skb; 193162306a36Sopenharmony_ci struct hash_wr_param params; 193262306a36Sopenharmony_ci u8 bs; 193362306a36Sopenharmony_ci int error; 193462306a36Sopenharmony_ci unsigned int cpu; 193562306a36Sopenharmony_ci 193662306a36Sopenharmony_ci cpu = get_cpu(); 193762306a36Sopenharmony_ci req_ctx->txqidx = cpu % ctx->ntxq; 193862306a36Sopenharmony_ci req_ctx->rxqidx = cpu % ctx->nrxq; 193962306a36Sopenharmony_ci put_cpu(); 194062306a36Sopenharmony_ci 194162306a36Sopenharmony_ci rtfm->init(req); 194262306a36Sopenharmony_ci bs = crypto_tfm_alg_blocksize(crypto_ahash_tfm(rtfm)); 194362306a36Sopenharmony_ci error = chcr_inc_wrcount(dev); 194462306a36Sopenharmony_ci if (error) 194562306a36Sopenharmony_ci return -ENXIO; 194662306a36Sopenharmony_ci 194762306a36Sopenharmony_ci if (unlikely(cxgb4_is_crypto_q_full(u_ctx->lldi.ports[0], 194862306a36Sopenharmony_ci req_ctx->txqidx) && 194962306a36Sopenharmony_ci (!(req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)))) { 195062306a36Sopenharmony_ci error = -ENOSPC; 195162306a36Sopenharmony_ci goto err; 195262306a36Sopenharmony_ci } 195362306a36Sopenharmony_ci 195462306a36Sopenharmony_ci chcr_init_hctx_per_wr(req_ctx); 195562306a36Sopenharmony_ci error = chcr_hash_dma_map(&u_ctx->lldi.pdev->dev, req); 195662306a36Sopenharmony_ci if (error) { 195762306a36Sopenharmony_ci error = -ENOMEM; 195862306a36Sopenharmony_ci goto err; 195962306a36Sopenharmony_ci } 196062306a36Sopenharmony_ci 196162306a36Sopenharmony_ci get_alg_config(¶ms.alg_prm, crypto_ahash_digestsize(rtfm)); 196262306a36Sopenharmony_ci params.kctx_len = roundup(params.alg_prm.result_size, 16); 196362306a36Sopenharmony_ci if (is_hmac(crypto_ahash_tfm(rtfm))) { 196462306a36Sopenharmony_ci params.kctx_len *= 2; 196562306a36Sopenharmony_ci params.opad_needed = 1; 196662306a36Sopenharmony_ci } else { 196762306a36Sopenharmony_ci params.opad_needed = 0; 196862306a36Sopenharmony_ci } 196962306a36Sopenharmony_ci params.sg_len = chcr_hash_ent_in_wr(req->src, !!req_ctx->reqlen, 197062306a36Sopenharmony_ci HASH_SPACE_LEFT(params.kctx_len), 0); 197162306a36Sopenharmony_ci if (params.sg_len < req->nbytes) { 197262306a36Sopenharmony_ci if (is_hmac(crypto_ahash_tfm(rtfm))) { 197362306a36Sopenharmony_ci params.kctx_len /= 2; 197462306a36Sopenharmony_ci params.opad_needed = 0; 197562306a36Sopenharmony_ci } 197662306a36Sopenharmony_ci params.last = 0; 197762306a36Sopenharmony_ci params.more = 1; 197862306a36Sopenharmony_ci params.scmd1 = 0; 197962306a36Sopenharmony_ci params.sg_len = rounddown(params.sg_len, bs); 198062306a36Sopenharmony_ci params.hash_size = params.alg_prm.result_size; 198162306a36Sopenharmony_ci } else { 198262306a36Sopenharmony_ci params.sg_len = req->nbytes; 198362306a36Sopenharmony_ci params.hash_size = crypto_ahash_digestsize(rtfm); 198462306a36Sopenharmony_ci params.last = 1; 198562306a36Sopenharmony_ci params.more = 0; 198662306a36Sopenharmony_ci params.scmd1 = req->nbytes + req_ctx->data_len; 198762306a36Sopenharmony_ci 198862306a36Sopenharmony_ci } 198962306a36Sopenharmony_ci params.bfr_len = 0; 199062306a36Sopenharmony_ci req_ctx->hctx_wr.result = 1; 199162306a36Sopenharmony_ci req_ctx->hctx_wr.srcsg = req->src; 199262306a36Sopenharmony_ci req_ctx->data_len += params.bfr_len + params.sg_len; 199362306a36Sopenharmony_ci 199462306a36Sopenharmony_ci if (req->nbytes == 0) { 199562306a36Sopenharmony_ci create_last_hash_block(req_ctx->reqbfr, bs, req_ctx->data_len); 199662306a36Sopenharmony_ci params.more = 1; 199762306a36Sopenharmony_ci params.bfr_len = bs; 199862306a36Sopenharmony_ci } 199962306a36Sopenharmony_ci 200062306a36Sopenharmony_ci skb = create_hash_wr(req, ¶ms); 200162306a36Sopenharmony_ci if (IS_ERR(skb)) { 200262306a36Sopenharmony_ci error = PTR_ERR(skb); 200362306a36Sopenharmony_ci goto unmap; 200462306a36Sopenharmony_ci } 200562306a36Sopenharmony_ci req_ctx->hctx_wr.processed += params.sg_len; 200662306a36Sopenharmony_ci skb->dev = u_ctx->lldi.ports[0]; 200762306a36Sopenharmony_ci set_wr_txq(skb, CPL_PRIORITY_DATA, req_ctx->txqidx); 200862306a36Sopenharmony_ci chcr_send_wr(skb); 200962306a36Sopenharmony_ci return -EINPROGRESS; 201062306a36Sopenharmony_ciunmap: 201162306a36Sopenharmony_ci chcr_hash_dma_unmap(&u_ctx->lldi.pdev->dev, req); 201262306a36Sopenharmony_cierr: 201362306a36Sopenharmony_ci chcr_dec_wrcount(dev); 201462306a36Sopenharmony_ci return error; 201562306a36Sopenharmony_ci} 201662306a36Sopenharmony_ci 201762306a36Sopenharmony_cistatic int chcr_ahash_continue(struct ahash_request *req) 201862306a36Sopenharmony_ci{ 201962306a36Sopenharmony_ci struct chcr_ahash_req_ctx *reqctx = ahash_request_ctx(req); 202062306a36Sopenharmony_ci struct chcr_hctx_per_wr *hctx_wr = &reqctx->hctx_wr; 202162306a36Sopenharmony_ci struct crypto_ahash *rtfm = crypto_ahash_reqtfm(req); 202262306a36Sopenharmony_ci struct chcr_context *ctx = h_ctx(rtfm); 202362306a36Sopenharmony_ci struct uld_ctx *u_ctx = ULD_CTX(ctx); 202462306a36Sopenharmony_ci struct sk_buff *skb; 202562306a36Sopenharmony_ci struct hash_wr_param params; 202662306a36Sopenharmony_ci u8 bs; 202762306a36Sopenharmony_ci int error; 202862306a36Sopenharmony_ci unsigned int cpu; 202962306a36Sopenharmony_ci 203062306a36Sopenharmony_ci cpu = get_cpu(); 203162306a36Sopenharmony_ci reqctx->txqidx = cpu % ctx->ntxq; 203262306a36Sopenharmony_ci reqctx->rxqidx = cpu % ctx->nrxq; 203362306a36Sopenharmony_ci put_cpu(); 203462306a36Sopenharmony_ci 203562306a36Sopenharmony_ci bs = crypto_tfm_alg_blocksize(crypto_ahash_tfm(rtfm)); 203662306a36Sopenharmony_ci get_alg_config(¶ms.alg_prm, crypto_ahash_digestsize(rtfm)); 203762306a36Sopenharmony_ci params.kctx_len = roundup(params.alg_prm.result_size, 16); 203862306a36Sopenharmony_ci if (is_hmac(crypto_ahash_tfm(rtfm))) { 203962306a36Sopenharmony_ci params.kctx_len *= 2; 204062306a36Sopenharmony_ci params.opad_needed = 1; 204162306a36Sopenharmony_ci } else { 204262306a36Sopenharmony_ci params.opad_needed = 0; 204362306a36Sopenharmony_ci } 204462306a36Sopenharmony_ci params.sg_len = chcr_hash_ent_in_wr(hctx_wr->srcsg, 0, 204562306a36Sopenharmony_ci HASH_SPACE_LEFT(params.kctx_len), 204662306a36Sopenharmony_ci hctx_wr->src_ofst); 204762306a36Sopenharmony_ci if ((params.sg_len + hctx_wr->processed) > req->nbytes) 204862306a36Sopenharmony_ci params.sg_len = req->nbytes - hctx_wr->processed; 204962306a36Sopenharmony_ci if (!hctx_wr->result || 205062306a36Sopenharmony_ci ((params.sg_len + hctx_wr->processed) < req->nbytes)) { 205162306a36Sopenharmony_ci if (is_hmac(crypto_ahash_tfm(rtfm))) { 205262306a36Sopenharmony_ci params.kctx_len /= 2; 205362306a36Sopenharmony_ci params.opad_needed = 0; 205462306a36Sopenharmony_ci } 205562306a36Sopenharmony_ci params.last = 0; 205662306a36Sopenharmony_ci params.more = 1; 205762306a36Sopenharmony_ci params.sg_len = rounddown(params.sg_len, bs); 205862306a36Sopenharmony_ci params.hash_size = params.alg_prm.result_size; 205962306a36Sopenharmony_ci params.scmd1 = 0; 206062306a36Sopenharmony_ci } else { 206162306a36Sopenharmony_ci params.last = 1; 206262306a36Sopenharmony_ci params.more = 0; 206362306a36Sopenharmony_ci params.hash_size = crypto_ahash_digestsize(rtfm); 206462306a36Sopenharmony_ci params.scmd1 = reqctx->data_len + params.sg_len; 206562306a36Sopenharmony_ci } 206662306a36Sopenharmony_ci params.bfr_len = 0; 206762306a36Sopenharmony_ci reqctx->data_len += params.sg_len; 206862306a36Sopenharmony_ci skb = create_hash_wr(req, ¶ms); 206962306a36Sopenharmony_ci if (IS_ERR(skb)) { 207062306a36Sopenharmony_ci error = PTR_ERR(skb); 207162306a36Sopenharmony_ci goto err; 207262306a36Sopenharmony_ci } 207362306a36Sopenharmony_ci hctx_wr->processed += params.sg_len; 207462306a36Sopenharmony_ci skb->dev = u_ctx->lldi.ports[0]; 207562306a36Sopenharmony_ci set_wr_txq(skb, CPL_PRIORITY_DATA, reqctx->txqidx); 207662306a36Sopenharmony_ci chcr_send_wr(skb); 207762306a36Sopenharmony_ci return 0; 207862306a36Sopenharmony_cierr: 207962306a36Sopenharmony_ci return error; 208062306a36Sopenharmony_ci} 208162306a36Sopenharmony_ci 208262306a36Sopenharmony_cistatic inline void chcr_handle_ahash_resp(struct ahash_request *req, 208362306a36Sopenharmony_ci unsigned char *input, 208462306a36Sopenharmony_ci int err) 208562306a36Sopenharmony_ci{ 208662306a36Sopenharmony_ci struct chcr_ahash_req_ctx *reqctx = ahash_request_ctx(req); 208762306a36Sopenharmony_ci struct chcr_hctx_per_wr *hctx_wr = &reqctx->hctx_wr; 208862306a36Sopenharmony_ci int digestsize, updated_digestsize; 208962306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 209062306a36Sopenharmony_ci struct uld_ctx *u_ctx = ULD_CTX(h_ctx(tfm)); 209162306a36Sopenharmony_ci struct chcr_dev *dev = h_ctx(tfm)->dev; 209262306a36Sopenharmony_ci 209362306a36Sopenharmony_ci if (input == NULL) 209462306a36Sopenharmony_ci goto out; 209562306a36Sopenharmony_ci digestsize = crypto_ahash_digestsize(crypto_ahash_reqtfm(req)); 209662306a36Sopenharmony_ci updated_digestsize = digestsize; 209762306a36Sopenharmony_ci if (digestsize == SHA224_DIGEST_SIZE) 209862306a36Sopenharmony_ci updated_digestsize = SHA256_DIGEST_SIZE; 209962306a36Sopenharmony_ci else if (digestsize == SHA384_DIGEST_SIZE) 210062306a36Sopenharmony_ci updated_digestsize = SHA512_DIGEST_SIZE; 210162306a36Sopenharmony_ci 210262306a36Sopenharmony_ci if (hctx_wr->dma_addr) { 210362306a36Sopenharmony_ci dma_unmap_single(&u_ctx->lldi.pdev->dev, hctx_wr->dma_addr, 210462306a36Sopenharmony_ci hctx_wr->dma_len, DMA_TO_DEVICE); 210562306a36Sopenharmony_ci hctx_wr->dma_addr = 0; 210662306a36Sopenharmony_ci } 210762306a36Sopenharmony_ci if (hctx_wr->isfinal || ((hctx_wr->processed + reqctx->reqlen) == 210862306a36Sopenharmony_ci req->nbytes)) { 210962306a36Sopenharmony_ci if (hctx_wr->result == 1) { 211062306a36Sopenharmony_ci hctx_wr->result = 0; 211162306a36Sopenharmony_ci memcpy(req->result, input + sizeof(struct cpl_fw6_pld), 211262306a36Sopenharmony_ci digestsize); 211362306a36Sopenharmony_ci } else { 211462306a36Sopenharmony_ci memcpy(reqctx->partial_hash, 211562306a36Sopenharmony_ci input + sizeof(struct cpl_fw6_pld), 211662306a36Sopenharmony_ci updated_digestsize); 211762306a36Sopenharmony_ci 211862306a36Sopenharmony_ci } 211962306a36Sopenharmony_ci goto unmap; 212062306a36Sopenharmony_ci } 212162306a36Sopenharmony_ci memcpy(reqctx->partial_hash, input + sizeof(struct cpl_fw6_pld), 212262306a36Sopenharmony_ci updated_digestsize); 212362306a36Sopenharmony_ci 212462306a36Sopenharmony_ci err = chcr_ahash_continue(req); 212562306a36Sopenharmony_ci if (err) 212662306a36Sopenharmony_ci goto unmap; 212762306a36Sopenharmony_ci return; 212862306a36Sopenharmony_ciunmap: 212962306a36Sopenharmony_ci if (hctx_wr->is_sg_map) 213062306a36Sopenharmony_ci chcr_hash_dma_unmap(&u_ctx->lldi.pdev->dev, req); 213162306a36Sopenharmony_ci 213262306a36Sopenharmony_ci 213362306a36Sopenharmony_ciout: 213462306a36Sopenharmony_ci chcr_dec_wrcount(dev); 213562306a36Sopenharmony_ci ahash_request_complete(req, err); 213662306a36Sopenharmony_ci} 213762306a36Sopenharmony_ci 213862306a36Sopenharmony_ci/* 213962306a36Sopenharmony_ci * chcr_handle_resp - Unmap the DMA buffers associated with the request 214062306a36Sopenharmony_ci * @req: crypto request 214162306a36Sopenharmony_ci */ 214262306a36Sopenharmony_ciint chcr_handle_resp(struct crypto_async_request *req, unsigned char *input, 214362306a36Sopenharmony_ci int err) 214462306a36Sopenharmony_ci{ 214562306a36Sopenharmony_ci struct crypto_tfm *tfm = req->tfm; 214662306a36Sopenharmony_ci struct chcr_context *ctx = crypto_tfm_ctx(tfm); 214762306a36Sopenharmony_ci struct adapter *adap = padap(ctx->dev); 214862306a36Sopenharmony_ci 214962306a36Sopenharmony_ci switch (tfm->__crt_alg->cra_flags & CRYPTO_ALG_TYPE_MASK) { 215062306a36Sopenharmony_ci case CRYPTO_ALG_TYPE_AEAD: 215162306a36Sopenharmony_ci err = chcr_handle_aead_resp(aead_request_cast(req), input, err); 215262306a36Sopenharmony_ci break; 215362306a36Sopenharmony_ci 215462306a36Sopenharmony_ci case CRYPTO_ALG_TYPE_SKCIPHER: 215562306a36Sopenharmony_ci chcr_handle_cipher_resp(skcipher_request_cast(req), 215662306a36Sopenharmony_ci input, err); 215762306a36Sopenharmony_ci break; 215862306a36Sopenharmony_ci case CRYPTO_ALG_TYPE_AHASH: 215962306a36Sopenharmony_ci chcr_handle_ahash_resp(ahash_request_cast(req), input, err); 216062306a36Sopenharmony_ci } 216162306a36Sopenharmony_ci atomic_inc(&adap->chcr_stats.complete); 216262306a36Sopenharmony_ci return err; 216362306a36Sopenharmony_ci} 216462306a36Sopenharmony_cistatic int chcr_ahash_export(struct ahash_request *areq, void *out) 216562306a36Sopenharmony_ci{ 216662306a36Sopenharmony_ci struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 216762306a36Sopenharmony_ci struct chcr_ahash_req_ctx *state = out; 216862306a36Sopenharmony_ci 216962306a36Sopenharmony_ci state->reqlen = req_ctx->reqlen; 217062306a36Sopenharmony_ci state->data_len = req_ctx->data_len; 217162306a36Sopenharmony_ci memcpy(state->bfr1, req_ctx->reqbfr, req_ctx->reqlen); 217262306a36Sopenharmony_ci memcpy(state->partial_hash, req_ctx->partial_hash, 217362306a36Sopenharmony_ci CHCR_HASH_MAX_DIGEST_SIZE); 217462306a36Sopenharmony_ci chcr_init_hctx_per_wr(state); 217562306a36Sopenharmony_ci return 0; 217662306a36Sopenharmony_ci} 217762306a36Sopenharmony_ci 217862306a36Sopenharmony_cistatic int chcr_ahash_import(struct ahash_request *areq, const void *in) 217962306a36Sopenharmony_ci{ 218062306a36Sopenharmony_ci struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 218162306a36Sopenharmony_ci struct chcr_ahash_req_ctx *state = (struct chcr_ahash_req_ctx *)in; 218262306a36Sopenharmony_ci 218362306a36Sopenharmony_ci req_ctx->reqlen = state->reqlen; 218462306a36Sopenharmony_ci req_ctx->data_len = state->data_len; 218562306a36Sopenharmony_ci req_ctx->reqbfr = req_ctx->bfr1; 218662306a36Sopenharmony_ci req_ctx->skbfr = req_ctx->bfr2; 218762306a36Sopenharmony_ci memcpy(req_ctx->bfr1, state->bfr1, CHCR_HASH_MAX_BLOCK_SIZE_128); 218862306a36Sopenharmony_ci memcpy(req_ctx->partial_hash, state->partial_hash, 218962306a36Sopenharmony_ci CHCR_HASH_MAX_DIGEST_SIZE); 219062306a36Sopenharmony_ci chcr_init_hctx_per_wr(req_ctx); 219162306a36Sopenharmony_ci return 0; 219262306a36Sopenharmony_ci} 219362306a36Sopenharmony_ci 219462306a36Sopenharmony_cistatic int chcr_ahash_setkey(struct crypto_ahash *tfm, const u8 *key, 219562306a36Sopenharmony_ci unsigned int keylen) 219662306a36Sopenharmony_ci{ 219762306a36Sopenharmony_ci struct hmac_ctx *hmacctx = HMAC_CTX(h_ctx(tfm)); 219862306a36Sopenharmony_ci unsigned int digestsize = crypto_ahash_digestsize(tfm); 219962306a36Sopenharmony_ci unsigned int bs = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); 220062306a36Sopenharmony_ci unsigned int i, err = 0, updated_digestsize; 220162306a36Sopenharmony_ci 220262306a36Sopenharmony_ci SHASH_DESC_ON_STACK(shash, hmacctx->base_hash); 220362306a36Sopenharmony_ci 220462306a36Sopenharmony_ci /* use the key to calculate the ipad and opad. ipad will sent with the 220562306a36Sopenharmony_ci * first request's data. opad will be sent with the final hash result 220662306a36Sopenharmony_ci * ipad in hmacctx->ipad and opad in hmacctx->opad location 220762306a36Sopenharmony_ci */ 220862306a36Sopenharmony_ci shash->tfm = hmacctx->base_hash; 220962306a36Sopenharmony_ci if (keylen > bs) { 221062306a36Sopenharmony_ci err = crypto_shash_digest(shash, key, keylen, 221162306a36Sopenharmony_ci hmacctx->ipad); 221262306a36Sopenharmony_ci if (err) 221362306a36Sopenharmony_ci goto out; 221462306a36Sopenharmony_ci keylen = digestsize; 221562306a36Sopenharmony_ci } else { 221662306a36Sopenharmony_ci memcpy(hmacctx->ipad, key, keylen); 221762306a36Sopenharmony_ci } 221862306a36Sopenharmony_ci memset(hmacctx->ipad + keylen, 0, bs - keylen); 221962306a36Sopenharmony_ci unsafe_memcpy(hmacctx->opad, hmacctx->ipad, bs, 222062306a36Sopenharmony_ci "fortified memcpy causes -Wrestrict warning"); 222162306a36Sopenharmony_ci 222262306a36Sopenharmony_ci for (i = 0; i < bs / sizeof(int); i++) { 222362306a36Sopenharmony_ci *((unsigned int *)(&hmacctx->ipad) + i) ^= IPAD_DATA; 222462306a36Sopenharmony_ci *((unsigned int *)(&hmacctx->opad) + i) ^= OPAD_DATA; 222562306a36Sopenharmony_ci } 222662306a36Sopenharmony_ci 222762306a36Sopenharmony_ci updated_digestsize = digestsize; 222862306a36Sopenharmony_ci if (digestsize == SHA224_DIGEST_SIZE) 222962306a36Sopenharmony_ci updated_digestsize = SHA256_DIGEST_SIZE; 223062306a36Sopenharmony_ci else if (digestsize == SHA384_DIGEST_SIZE) 223162306a36Sopenharmony_ci updated_digestsize = SHA512_DIGEST_SIZE; 223262306a36Sopenharmony_ci err = chcr_compute_partial_hash(shash, hmacctx->ipad, 223362306a36Sopenharmony_ci hmacctx->ipad, digestsize); 223462306a36Sopenharmony_ci if (err) 223562306a36Sopenharmony_ci goto out; 223662306a36Sopenharmony_ci chcr_change_order(hmacctx->ipad, updated_digestsize); 223762306a36Sopenharmony_ci 223862306a36Sopenharmony_ci err = chcr_compute_partial_hash(shash, hmacctx->opad, 223962306a36Sopenharmony_ci hmacctx->opad, digestsize); 224062306a36Sopenharmony_ci if (err) 224162306a36Sopenharmony_ci goto out; 224262306a36Sopenharmony_ci chcr_change_order(hmacctx->opad, updated_digestsize); 224362306a36Sopenharmony_ciout: 224462306a36Sopenharmony_ci return err; 224562306a36Sopenharmony_ci} 224662306a36Sopenharmony_ci 224762306a36Sopenharmony_cistatic int chcr_aes_xts_setkey(struct crypto_skcipher *cipher, const u8 *key, 224862306a36Sopenharmony_ci unsigned int key_len) 224962306a36Sopenharmony_ci{ 225062306a36Sopenharmony_ci struct ablk_ctx *ablkctx = ABLK_CTX(c_ctx(cipher)); 225162306a36Sopenharmony_ci unsigned short context_size = 0; 225262306a36Sopenharmony_ci int err; 225362306a36Sopenharmony_ci 225462306a36Sopenharmony_ci err = chcr_cipher_fallback_setkey(cipher, key, key_len); 225562306a36Sopenharmony_ci if (err) 225662306a36Sopenharmony_ci goto badkey_err; 225762306a36Sopenharmony_ci 225862306a36Sopenharmony_ci memcpy(ablkctx->key, key, key_len); 225962306a36Sopenharmony_ci ablkctx->enckey_len = key_len; 226062306a36Sopenharmony_ci get_aes_decrypt_key(ablkctx->rrkey, ablkctx->key, key_len << 2); 226162306a36Sopenharmony_ci context_size = (KEY_CONTEXT_HDR_SALT_AND_PAD + key_len) >> 4; 226262306a36Sopenharmony_ci /* Both keys for xts must be aligned to 16 byte boundary 226362306a36Sopenharmony_ci * by padding with zeros. So for 24 byte keys padding 8 zeroes. 226462306a36Sopenharmony_ci */ 226562306a36Sopenharmony_ci if (key_len == 48) { 226662306a36Sopenharmony_ci context_size = (KEY_CONTEXT_HDR_SALT_AND_PAD + key_len 226762306a36Sopenharmony_ci + 16) >> 4; 226862306a36Sopenharmony_ci memmove(ablkctx->key + 32, ablkctx->key + 24, 24); 226962306a36Sopenharmony_ci memset(ablkctx->key + 24, 0, 8); 227062306a36Sopenharmony_ci memset(ablkctx->key + 56, 0, 8); 227162306a36Sopenharmony_ci ablkctx->enckey_len = 64; 227262306a36Sopenharmony_ci ablkctx->key_ctx_hdr = 227362306a36Sopenharmony_ci FILL_KEY_CTX_HDR(CHCR_KEYCTX_CIPHER_KEY_SIZE_192, 227462306a36Sopenharmony_ci CHCR_KEYCTX_NO_KEY, 1, 227562306a36Sopenharmony_ci 0, context_size); 227662306a36Sopenharmony_ci } else { 227762306a36Sopenharmony_ci ablkctx->key_ctx_hdr = 227862306a36Sopenharmony_ci FILL_KEY_CTX_HDR((key_len == AES_KEYSIZE_256) ? 227962306a36Sopenharmony_ci CHCR_KEYCTX_CIPHER_KEY_SIZE_128 : 228062306a36Sopenharmony_ci CHCR_KEYCTX_CIPHER_KEY_SIZE_256, 228162306a36Sopenharmony_ci CHCR_KEYCTX_NO_KEY, 1, 228262306a36Sopenharmony_ci 0, context_size); 228362306a36Sopenharmony_ci } 228462306a36Sopenharmony_ci ablkctx->ciph_mode = CHCR_SCMD_CIPHER_MODE_AES_XTS; 228562306a36Sopenharmony_ci return 0; 228662306a36Sopenharmony_cibadkey_err: 228762306a36Sopenharmony_ci ablkctx->enckey_len = 0; 228862306a36Sopenharmony_ci 228962306a36Sopenharmony_ci return err; 229062306a36Sopenharmony_ci} 229162306a36Sopenharmony_ci 229262306a36Sopenharmony_cistatic int chcr_sha_init(struct ahash_request *areq) 229362306a36Sopenharmony_ci{ 229462306a36Sopenharmony_ci struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 229562306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 229662306a36Sopenharmony_ci int digestsize = crypto_ahash_digestsize(tfm); 229762306a36Sopenharmony_ci 229862306a36Sopenharmony_ci req_ctx->data_len = 0; 229962306a36Sopenharmony_ci req_ctx->reqlen = 0; 230062306a36Sopenharmony_ci req_ctx->reqbfr = req_ctx->bfr1; 230162306a36Sopenharmony_ci req_ctx->skbfr = req_ctx->bfr2; 230262306a36Sopenharmony_ci copy_hash_init_values(req_ctx->partial_hash, digestsize); 230362306a36Sopenharmony_ci 230462306a36Sopenharmony_ci return 0; 230562306a36Sopenharmony_ci} 230662306a36Sopenharmony_ci 230762306a36Sopenharmony_cistatic int chcr_sha_cra_init(struct crypto_tfm *tfm) 230862306a36Sopenharmony_ci{ 230962306a36Sopenharmony_ci crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), 231062306a36Sopenharmony_ci sizeof(struct chcr_ahash_req_ctx)); 231162306a36Sopenharmony_ci return chcr_device_init(crypto_tfm_ctx(tfm)); 231262306a36Sopenharmony_ci} 231362306a36Sopenharmony_ci 231462306a36Sopenharmony_cistatic int chcr_hmac_init(struct ahash_request *areq) 231562306a36Sopenharmony_ci{ 231662306a36Sopenharmony_ci struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 231762306a36Sopenharmony_ci struct crypto_ahash *rtfm = crypto_ahash_reqtfm(areq); 231862306a36Sopenharmony_ci struct hmac_ctx *hmacctx = HMAC_CTX(h_ctx(rtfm)); 231962306a36Sopenharmony_ci unsigned int digestsize = crypto_ahash_digestsize(rtfm); 232062306a36Sopenharmony_ci unsigned int bs = crypto_tfm_alg_blocksize(crypto_ahash_tfm(rtfm)); 232162306a36Sopenharmony_ci 232262306a36Sopenharmony_ci chcr_sha_init(areq); 232362306a36Sopenharmony_ci req_ctx->data_len = bs; 232462306a36Sopenharmony_ci if (is_hmac(crypto_ahash_tfm(rtfm))) { 232562306a36Sopenharmony_ci if (digestsize == SHA224_DIGEST_SIZE) 232662306a36Sopenharmony_ci memcpy(req_ctx->partial_hash, hmacctx->ipad, 232762306a36Sopenharmony_ci SHA256_DIGEST_SIZE); 232862306a36Sopenharmony_ci else if (digestsize == SHA384_DIGEST_SIZE) 232962306a36Sopenharmony_ci memcpy(req_ctx->partial_hash, hmacctx->ipad, 233062306a36Sopenharmony_ci SHA512_DIGEST_SIZE); 233162306a36Sopenharmony_ci else 233262306a36Sopenharmony_ci memcpy(req_ctx->partial_hash, hmacctx->ipad, 233362306a36Sopenharmony_ci digestsize); 233462306a36Sopenharmony_ci } 233562306a36Sopenharmony_ci return 0; 233662306a36Sopenharmony_ci} 233762306a36Sopenharmony_ci 233862306a36Sopenharmony_cistatic int chcr_hmac_cra_init(struct crypto_tfm *tfm) 233962306a36Sopenharmony_ci{ 234062306a36Sopenharmony_ci struct chcr_context *ctx = crypto_tfm_ctx(tfm); 234162306a36Sopenharmony_ci struct hmac_ctx *hmacctx = HMAC_CTX(ctx); 234262306a36Sopenharmony_ci unsigned int digestsize = 234362306a36Sopenharmony_ci crypto_ahash_digestsize(__crypto_ahash_cast(tfm)); 234462306a36Sopenharmony_ci 234562306a36Sopenharmony_ci crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), 234662306a36Sopenharmony_ci sizeof(struct chcr_ahash_req_ctx)); 234762306a36Sopenharmony_ci hmacctx->base_hash = chcr_alloc_shash(digestsize); 234862306a36Sopenharmony_ci if (IS_ERR(hmacctx->base_hash)) 234962306a36Sopenharmony_ci return PTR_ERR(hmacctx->base_hash); 235062306a36Sopenharmony_ci return chcr_device_init(crypto_tfm_ctx(tfm)); 235162306a36Sopenharmony_ci} 235262306a36Sopenharmony_ci 235362306a36Sopenharmony_cistatic void chcr_hmac_cra_exit(struct crypto_tfm *tfm) 235462306a36Sopenharmony_ci{ 235562306a36Sopenharmony_ci struct chcr_context *ctx = crypto_tfm_ctx(tfm); 235662306a36Sopenharmony_ci struct hmac_ctx *hmacctx = HMAC_CTX(ctx); 235762306a36Sopenharmony_ci 235862306a36Sopenharmony_ci if (hmacctx->base_hash) { 235962306a36Sopenharmony_ci chcr_free_shash(hmacctx->base_hash); 236062306a36Sopenharmony_ci hmacctx->base_hash = NULL; 236162306a36Sopenharmony_ci } 236262306a36Sopenharmony_ci} 236362306a36Sopenharmony_ci 236462306a36Sopenharmony_ciinline void chcr_aead_common_exit(struct aead_request *req) 236562306a36Sopenharmony_ci{ 236662306a36Sopenharmony_ci struct chcr_aead_reqctx *reqctx = aead_request_ctx_dma(req); 236762306a36Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 236862306a36Sopenharmony_ci struct uld_ctx *u_ctx = ULD_CTX(a_ctx(tfm)); 236962306a36Sopenharmony_ci 237062306a36Sopenharmony_ci chcr_aead_dma_unmap(&u_ctx->lldi.pdev->dev, req, reqctx->op); 237162306a36Sopenharmony_ci} 237262306a36Sopenharmony_ci 237362306a36Sopenharmony_cistatic int chcr_aead_common_init(struct aead_request *req) 237462306a36Sopenharmony_ci{ 237562306a36Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 237662306a36Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm)); 237762306a36Sopenharmony_ci struct chcr_aead_reqctx *reqctx = aead_request_ctx_dma(req); 237862306a36Sopenharmony_ci unsigned int authsize = crypto_aead_authsize(tfm); 237962306a36Sopenharmony_ci int error = -EINVAL; 238062306a36Sopenharmony_ci 238162306a36Sopenharmony_ci /* validate key size */ 238262306a36Sopenharmony_ci if (aeadctx->enckey_len == 0) 238362306a36Sopenharmony_ci goto err; 238462306a36Sopenharmony_ci if (reqctx->op && req->cryptlen < authsize) 238562306a36Sopenharmony_ci goto err; 238662306a36Sopenharmony_ci if (reqctx->b0_len) 238762306a36Sopenharmony_ci reqctx->scratch_pad = reqctx->iv + IV; 238862306a36Sopenharmony_ci else 238962306a36Sopenharmony_ci reqctx->scratch_pad = NULL; 239062306a36Sopenharmony_ci 239162306a36Sopenharmony_ci error = chcr_aead_dma_map(&ULD_CTX(a_ctx(tfm))->lldi.pdev->dev, req, 239262306a36Sopenharmony_ci reqctx->op); 239362306a36Sopenharmony_ci if (error) { 239462306a36Sopenharmony_ci error = -ENOMEM; 239562306a36Sopenharmony_ci goto err; 239662306a36Sopenharmony_ci } 239762306a36Sopenharmony_ci 239862306a36Sopenharmony_ci return 0; 239962306a36Sopenharmony_cierr: 240062306a36Sopenharmony_ci return error; 240162306a36Sopenharmony_ci} 240262306a36Sopenharmony_ci 240362306a36Sopenharmony_cistatic int chcr_aead_need_fallback(struct aead_request *req, int dst_nents, 240462306a36Sopenharmony_ci int aadmax, int wrlen, 240562306a36Sopenharmony_ci unsigned short op_type) 240662306a36Sopenharmony_ci{ 240762306a36Sopenharmony_ci unsigned int authsize = crypto_aead_authsize(crypto_aead_reqtfm(req)); 240862306a36Sopenharmony_ci 240962306a36Sopenharmony_ci if (((req->cryptlen - (op_type ? authsize : 0)) == 0) || 241062306a36Sopenharmony_ci dst_nents > MAX_DSGL_ENT || 241162306a36Sopenharmony_ci (req->assoclen > aadmax) || 241262306a36Sopenharmony_ci (wrlen > SGE_MAX_WR_LEN)) 241362306a36Sopenharmony_ci return 1; 241462306a36Sopenharmony_ci return 0; 241562306a36Sopenharmony_ci} 241662306a36Sopenharmony_ci 241762306a36Sopenharmony_cistatic int chcr_aead_fallback(struct aead_request *req, unsigned short op_type) 241862306a36Sopenharmony_ci{ 241962306a36Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 242062306a36Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm)); 242162306a36Sopenharmony_ci struct aead_request *subreq = aead_request_ctx_dma(req); 242262306a36Sopenharmony_ci 242362306a36Sopenharmony_ci aead_request_set_tfm(subreq, aeadctx->sw_cipher); 242462306a36Sopenharmony_ci aead_request_set_callback(subreq, req->base.flags, 242562306a36Sopenharmony_ci req->base.complete, req->base.data); 242662306a36Sopenharmony_ci aead_request_set_crypt(subreq, req->src, req->dst, req->cryptlen, 242762306a36Sopenharmony_ci req->iv); 242862306a36Sopenharmony_ci aead_request_set_ad(subreq, req->assoclen); 242962306a36Sopenharmony_ci return op_type ? crypto_aead_decrypt(subreq) : 243062306a36Sopenharmony_ci crypto_aead_encrypt(subreq); 243162306a36Sopenharmony_ci} 243262306a36Sopenharmony_ci 243362306a36Sopenharmony_cistatic struct sk_buff *create_authenc_wr(struct aead_request *req, 243462306a36Sopenharmony_ci unsigned short qid, 243562306a36Sopenharmony_ci int size) 243662306a36Sopenharmony_ci{ 243762306a36Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 243862306a36Sopenharmony_ci struct chcr_context *ctx = a_ctx(tfm); 243962306a36Sopenharmony_ci struct uld_ctx *u_ctx = ULD_CTX(ctx); 244062306a36Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(ctx); 244162306a36Sopenharmony_ci struct chcr_authenc_ctx *actx = AUTHENC_CTX(aeadctx); 244262306a36Sopenharmony_ci struct chcr_aead_reqctx *reqctx = aead_request_ctx_dma(req); 244362306a36Sopenharmony_ci struct sk_buff *skb = NULL; 244462306a36Sopenharmony_ci struct chcr_wr *chcr_req; 244562306a36Sopenharmony_ci struct cpl_rx_phys_dsgl *phys_cpl; 244662306a36Sopenharmony_ci struct ulptx_sgl *ulptx; 244762306a36Sopenharmony_ci unsigned int transhdr_len; 244862306a36Sopenharmony_ci unsigned int dst_size = 0, temp, subtype = get_aead_subtype(tfm); 244962306a36Sopenharmony_ci unsigned int kctx_len = 0, dnents, snents; 245062306a36Sopenharmony_ci unsigned int authsize = crypto_aead_authsize(tfm); 245162306a36Sopenharmony_ci int error = -EINVAL; 245262306a36Sopenharmony_ci u8 *ivptr; 245362306a36Sopenharmony_ci int null = 0; 245462306a36Sopenharmony_ci gfp_t flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL : 245562306a36Sopenharmony_ci GFP_ATOMIC; 245662306a36Sopenharmony_ci struct adapter *adap = padap(ctx->dev); 245762306a36Sopenharmony_ci unsigned int rx_channel_id = reqctx->rxqidx / ctx->rxq_perchan; 245862306a36Sopenharmony_ci 245962306a36Sopenharmony_ci rx_channel_id = cxgb4_port_e2cchan(u_ctx->lldi.ports[rx_channel_id]); 246062306a36Sopenharmony_ci if (req->cryptlen == 0) 246162306a36Sopenharmony_ci return NULL; 246262306a36Sopenharmony_ci 246362306a36Sopenharmony_ci reqctx->b0_len = 0; 246462306a36Sopenharmony_ci error = chcr_aead_common_init(req); 246562306a36Sopenharmony_ci if (error) 246662306a36Sopenharmony_ci return ERR_PTR(error); 246762306a36Sopenharmony_ci 246862306a36Sopenharmony_ci if (subtype == CRYPTO_ALG_SUB_TYPE_CBC_NULL || 246962306a36Sopenharmony_ci subtype == CRYPTO_ALG_SUB_TYPE_CTR_NULL) { 247062306a36Sopenharmony_ci null = 1; 247162306a36Sopenharmony_ci } 247262306a36Sopenharmony_ci dnents = sg_nents_xlen(req->dst, req->assoclen + req->cryptlen + 247362306a36Sopenharmony_ci (reqctx->op ? -authsize : authsize), CHCR_DST_SG_SIZE, 0); 247462306a36Sopenharmony_ci dnents += MIN_AUTH_SG; // For IV 247562306a36Sopenharmony_ci snents = sg_nents_xlen(req->src, req->assoclen + req->cryptlen, 247662306a36Sopenharmony_ci CHCR_SRC_SG_SIZE, 0); 247762306a36Sopenharmony_ci dst_size = get_space_for_phys_dsgl(dnents); 247862306a36Sopenharmony_ci kctx_len = (KEY_CONTEXT_CTX_LEN_G(ntohl(aeadctx->key_ctx_hdr)) << 4) 247962306a36Sopenharmony_ci - sizeof(chcr_req->key_ctx); 248062306a36Sopenharmony_ci transhdr_len = CIPHER_TRANSHDR_SIZE(kctx_len, dst_size); 248162306a36Sopenharmony_ci reqctx->imm = (transhdr_len + req->assoclen + req->cryptlen) < 248262306a36Sopenharmony_ci SGE_MAX_WR_LEN; 248362306a36Sopenharmony_ci temp = reqctx->imm ? roundup(req->assoclen + req->cryptlen, 16) 248462306a36Sopenharmony_ci : (sgl_len(snents) * 8); 248562306a36Sopenharmony_ci transhdr_len += temp; 248662306a36Sopenharmony_ci transhdr_len = roundup(transhdr_len, 16); 248762306a36Sopenharmony_ci 248862306a36Sopenharmony_ci if (chcr_aead_need_fallback(req, dnents, T6_MAX_AAD_SIZE, 248962306a36Sopenharmony_ci transhdr_len, reqctx->op)) { 249062306a36Sopenharmony_ci atomic_inc(&adap->chcr_stats.fallback); 249162306a36Sopenharmony_ci chcr_aead_common_exit(req); 249262306a36Sopenharmony_ci return ERR_PTR(chcr_aead_fallback(req, reqctx->op)); 249362306a36Sopenharmony_ci } 249462306a36Sopenharmony_ci skb = alloc_skb(transhdr_len, flags); 249562306a36Sopenharmony_ci if (!skb) { 249662306a36Sopenharmony_ci error = -ENOMEM; 249762306a36Sopenharmony_ci goto err; 249862306a36Sopenharmony_ci } 249962306a36Sopenharmony_ci 250062306a36Sopenharmony_ci chcr_req = __skb_put_zero(skb, transhdr_len); 250162306a36Sopenharmony_ci 250262306a36Sopenharmony_ci temp = (reqctx->op == CHCR_ENCRYPT_OP) ? 0 : authsize; 250362306a36Sopenharmony_ci 250462306a36Sopenharmony_ci /* 250562306a36Sopenharmony_ci * Input order is AAD,IV and Payload. where IV should be included as 250662306a36Sopenharmony_ci * the part of authdata. All other fields should be filled according 250762306a36Sopenharmony_ci * to the hardware spec 250862306a36Sopenharmony_ci */ 250962306a36Sopenharmony_ci chcr_req->sec_cpl.op_ivinsrtofst = 251062306a36Sopenharmony_ci FILL_SEC_CPL_OP_IVINSR(rx_channel_id, 2, 1); 251162306a36Sopenharmony_ci chcr_req->sec_cpl.pldlen = htonl(req->assoclen + IV + req->cryptlen); 251262306a36Sopenharmony_ci chcr_req->sec_cpl.aadstart_cipherstop_hi = FILL_SEC_CPL_CIPHERSTOP_HI( 251362306a36Sopenharmony_ci null ? 0 : 1 + IV, 251462306a36Sopenharmony_ci null ? 0 : IV + req->assoclen, 251562306a36Sopenharmony_ci req->assoclen + IV + 1, 251662306a36Sopenharmony_ci (temp & 0x1F0) >> 4); 251762306a36Sopenharmony_ci chcr_req->sec_cpl.cipherstop_lo_authinsert = FILL_SEC_CPL_AUTHINSERT( 251862306a36Sopenharmony_ci temp & 0xF, 251962306a36Sopenharmony_ci null ? 0 : req->assoclen + IV + 1, 252062306a36Sopenharmony_ci temp, temp); 252162306a36Sopenharmony_ci if (subtype == CRYPTO_ALG_SUB_TYPE_CTR_NULL || 252262306a36Sopenharmony_ci subtype == CRYPTO_ALG_SUB_TYPE_CTR_SHA) 252362306a36Sopenharmony_ci temp = CHCR_SCMD_CIPHER_MODE_AES_CTR; 252462306a36Sopenharmony_ci else 252562306a36Sopenharmony_ci temp = CHCR_SCMD_CIPHER_MODE_AES_CBC; 252662306a36Sopenharmony_ci chcr_req->sec_cpl.seqno_numivs = FILL_SEC_CPL_SCMD0_SEQNO(reqctx->op, 252762306a36Sopenharmony_ci (reqctx->op == CHCR_ENCRYPT_OP) ? 1 : 0, 252862306a36Sopenharmony_ci temp, 252962306a36Sopenharmony_ci actx->auth_mode, aeadctx->hmac_ctrl, 253062306a36Sopenharmony_ci IV >> 1); 253162306a36Sopenharmony_ci chcr_req->sec_cpl.ivgen_hdrlen = FILL_SEC_CPL_IVGEN_HDRLEN(0, 0, 1, 253262306a36Sopenharmony_ci 0, 0, dst_size); 253362306a36Sopenharmony_ci 253462306a36Sopenharmony_ci chcr_req->key_ctx.ctx_hdr = aeadctx->key_ctx_hdr; 253562306a36Sopenharmony_ci if (reqctx->op == CHCR_ENCRYPT_OP || 253662306a36Sopenharmony_ci subtype == CRYPTO_ALG_SUB_TYPE_CTR_SHA || 253762306a36Sopenharmony_ci subtype == CRYPTO_ALG_SUB_TYPE_CTR_NULL) 253862306a36Sopenharmony_ci memcpy(chcr_req->key_ctx.key, aeadctx->key, 253962306a36Sopenharmony_ci aeadctx->enckey_len); 254062306a36Sopenharmony_ci else 254162306a36Sopenharmony_ci memcpy(chcr_req->key_ctx.key, actx->dec_rrkey, 254262306a36Sopenharmony_ci aeadctx->enckey_len); 254362306a36Sopenharmony_ci 254462306a36Sopenharmony_ci memcpy(chcr_req->key_ctx.key + roundup(aeadctx->enckey_len, 16), 254562306a36Sopenharmony_ci actx->h_iopad, kctx_len - roundup(aeadctx->enckey_len, 16)); 254662306a36Sopenharmony_ci phys_cpl = (struct cpl_rx_phys_dsgl *)((u8 *)(chcr_req + 1) + kctx_len); 254762306a36Sopenharmony_ci ivptr = (u8 *)(phys_cpl + 1) + dst_size; 254862306a36Sopenharmony_ci ulptx = (struct ulptx_sgl *)(ivptr + IV); 254962306a36Sopenharmony_ci if (subtype == CRYPTO_ALG_SUB_TYPE_CTR_SHA || 255062306a36Sopenharmony_ci subtype == CRYPTO_ALG_SUB_TYPE_CTR_NULL) { 255162306a36Sopenharmony_ci memcpy(ivptr, aeadctx->nonce, CTR_RFC3686_NONCE_SIZE); 255262306a36Sopenharmony_ci memcpy(ivptr + CTR_RFC3686_NONCE_SIZE, req->iv, 255362306a36Sopenharmony_ci CTR_RFC3686_IV_SIZE); 255462306a36Sopenharmony_ci *(__be32 *)(ivptr + CTR_RFC3686_NONCE_SIZE + 255562306a36Sopenharmony_ci CTR_RFC3686_IV_SIZE) = cpu_to_be32(1); 255662306a36Sopenharmony_ci } else { 255762306a36Sopenharmony_ci memcpy(ivptr, req->iv, IV); 255862306a36Sopenharmony_ci } 255962306a36Sopenharmony_ci chcr_add_aead_dst_ent(req, phys_cpl, qid); 256062306a36Sopenharmony_ci chcr_add_aead_src_ent(req, ulptx); 256162306a36Sopenharmony_ci atomic_inc(&adap->chcr_stats.cipher_rqst); 256262306a36Sopenharmony_ci temp = sizeof(struct cpl_rx_phys_dsgl) + dst_size + IV + 256362306a36Sopenharmony_ci kctx_len + (reqctx->imm ? (req->assoclen + req->cryptlen) : 0); 256462306a36Sopenharmony_ci create_wreq(a_ctx(tfm), chcr_req, &req->base, reqctx->imm, size, 256562306a36Sopenharmony_ci transhdr_len, temp, 0); 256662306a36Sopenharmony_ci reqctx->skb = skb; 256762306a36Sopenharmony_ci 256862306a36Sopenharmony_ci return skb; 256962306a36Sopenharmony_cierr: 257062306a36Sopenharmony_ci chcr_aead_common_exit(req); 257162306a36Sopenharmony_ci 257262306a36Sopenharmony_ci return ERR_PTR(error); 257362306a36Sopenharmony_ci} 257462306a36Sopenharmony_ci 257562306a36Sopenharmony_ciint chcr_aead_dma_map(struct device *dev, 257662306a36Sopenharmony_ci struct aead_request *req, 257762306a36Sopenharmony_ci unsigned short op_type) 257862306a36Sopenharmony_ci{ 257962306a36Sopenharmony_ci int error; 258062306a36Sopenharmony_ci struct chcr_aead_reqctx *reqctx = aead_request_ctx_dma(req); 258162306a36Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 258262306a36Sopenharmony_ci unsigned int authsize = crypto_aead_authsize(tfm); 258362306a36Sopenharmony_ci int src_len, dst_len; 258462306a36Sopenharmony_ci 258562306a36Sopenharmony_ci /* calculate and handle src and dst sg length separately 258662306a36Sopenharmony_ci * for inplace and out-of place operations 258762306a36Sopenharmony_ci */ 258862306a36Sopenharmony_ci if (req->src == req->dst) { 258962306a36Sopenharmony_ci src_len = req->assoclen + req->cryptlen + (op_type ? 259062306a36Sopenharmony_ci 0 : authsize); 259162306a36Sopenharmony_ci dst_len = src_len; 259262306a36Sopenharmony_ci } else { 259362306a36Sopenharmony_ci src_len = req->assoclen + req->cryptlen; 259462306a36Sopenharmony_ci dst_len = req->assoclen + req->cryptlen + (op_type ? 259562306a36Sopenharmony_ci -authsize : authsize); 259662306a36Sopenharmony_ci } 259762306a36Sopenharmony_ci 259862306a36Sopenharmony_ci if (!req->cryptlen || !src_len || !dst_len) 259962306a36Sopenharmony_ci return 0; 260062306a36Sopenharmony_ci reqctx->iv_dma = dma_map_single(dev, reqctx->iv, (IV + reqctx->b0_len), 260162306a36Sopenharmony_ci DMA_BIDIRECTIONAL); 260262306a36Sopenharmony_ci if (dma_mapping_error(dev, reqctx->iv_dma)) 260362306a36Sopenharmony_ci return -ENOMEM; 260462306a36Sopenharmony_ci if (reqctx->b0_len) 260562306a36Sopenharmony_ci reqctx->b0_dma = reqctx->iv_dma + IV; 260662306a36Sopenharmony_ci else 260762306a36Sopenharmony_ci reqctx->b0_dma = 0; 260862306a36Sopenharmony_ci if (req->src == req->dst) { 260962306a36Sopenharmony_ci error = dma_map_sg(dev, req->src, 261062306a36Sopenharmony_ci sg_nents_for_len(req->src, src_len), 261162306a36Sopenharmony_ci DMA_BIDIRECTIONAL); 261262306a36Sopenharmony_ci if (!error) 261362306a36Sopenharmony_ci goto err; 261462306a36Sopenharmony_ci } else { 261562306a36Sopenharmony_ci error = dma_map_sg(dev, req->src, 261662306a36Sopenharmony_ci sg_nents_for_len(req->src, src_len), 261762306a36Sopenharmony_ci DMA_TO_DEVICE); 261862306a36Sopenharmony_ci if (!error) 261962306a36Sopenharmony_ci goto err; 262062306a36Sopenharmony_ci error = dma_map_sg(dev, req->dst, 262162306a36Sopenharmony_ci sg_nents_for_len(req->dst, dst_len), 262262306a36Sopenharmony_ci DMA_FROM_DEVICE); 262362306a36Sopenharmony_ci if (!error) { 262462306a36Sopenharmony_ci dma_unmap_sg(dev, req->src, 262562306a36Sopenharmony_ci sg_nents_for_len(req->src, src_len), 262662306a36Sopenharmony_ci DMA_TO_DEVICE); 262762306a36Sopenharmony_ci goto err; 262862306a36Sopenharmony_ci } 262962306a36Sopenharmony_ci } 263062306a36Sopenharmony_ci 263162306a36Sopenharmony_ci return 0; 263262306a36Sopenharmony_cierr: 263362306a36Sopenharmony_ci dma_unmap_single(dev, reqctx->iv_dma, IV, DMA_BIDIRECTIONAL); 263462306a36Sopenharmony_ci return -ENOMEM; 263562306a36Sopenharmony_ci} 263662306a36Sopenharmony_ci 263762306a36Sopenharmony_civoid chcr_aead_dma_unmap(struct device *dev, 263862306a36Sopenharmony_ci struct aead_request *req, 263962306a36Sopenharmony_ci unsigned short op_type) 264062306a36Sopenharmony_ci{ 264162306a36Sopenharmony_ci struct chcr_aead_reqctx *reqctx = aead_request_ctx_dma(req); 264262306a36Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 264362306a36Sopenharmony_ci unsigned int authsize = crypto_aead_authsize(tfm); 264462306a36Sopenharmony_ci int src_len, dst_len; 264562306a36Sopenharmony_ci 264662306a36Sopenharmony_ci /* calculate and handle src and dst sg length separately 264762306a36Sopenharmony_ci * for inplace and out-of place operations 264862306a36Sopenharmony_ci */ 264962306a36Sopenharmony_ci if (req->src == req->dst) { 265062306a36Sopenharmony_ci src_len = req->assoclen + req->cryptlen + (op_type ? 265162306a36Sopenharmony_ci 0 : authsize); 265262306a36Sopenharmony_ci dst_len = src_len; 265362306a36Sopenharmony_ci } else { 265462306a36Sopenharmony_ci src_len = req->assoclen + req->cryptlen; 265562306a36Sopenharmony_ci dst_len = req->assoclen + req->cryptlen + (op_type ? 265662306a36Sopenharmony_ci -authsize : authsize); 265762306a36Sopenharmony_ci } 265862306a36Sopenharmony_ci 265962306a36Sopenharmony_ci if (!req->cryptlen || !src_len || !dst_len) 266062306a36Sopenharmony_ci return; 266162306a36Sopenharmony_ci 266262306a36Sopenharmony_ci dma_unmap_single(dev, reqctx->iv_dma, (IV + reqctx->b0_len), 266362306a36Sopenharmony_ci DMA_BIDIRECTIONAL); 266462306a36Sopenharmony_ci if (req->src == req->dst) { 266562306a36Sopenharmony_ci dma_unmap_sg(dev, req->src, 266662306a36Sopenharmony_ci sg_nents_for_len(req->src, src_len), 266762306a36Sopenharmony_ci DMA_BIDIRECTIONAL); 266862306a36Sopenharmony_ci } else { 266962306a36Sopenharmony_ci dma_unmap_sg(dev, req->src, 267062306a36Sopenharmony_ci sg_nents_for_len(req->src, src_len), 267162306a36Sopenharmony_ci DMA_TO_DEVICE); 267262306a36Sopenharmony_ci dma_unmap_sg(dev, req->dst, 267362306a36Sopenharmony_ci sg_nents_for_len(req->dst, dst_len), 267462306a36Sopenharmony_ci DMA_FROM_DEVICE); 267562306a36Sopenharmony_ci } 267662306a36Sopenharmony_ci} 267762306a36Sopenharmony_ci 267862306a36Sopenharmony_civoid chcr_add_aead_src_ent(struct aead_request *req, 267962306a36Sopenharmony_ci struct ulptx_sgl *ulptx) 268062306a36Sopenharmony_ci{ 268162306a36Sopenharmony_ci struct ulptx_walk ulp_walk; 268262306a36Sopenharmony_ci struct chcr_aead_reqctx *reqctx = aead_request_ctx_dma(req); 268362306a36Sopenharmony_ci 268462306a36Sopenharmony_ci if (reqctx->imm) { 268562306a36Sopenharmony_ci u8 *buf = (u8 *)ulptx; 268662306a36Sopenharmony_ci 268762306a36Sopenharmony_ci if (reqctx->b0_len) { 268862306a36Sopenharmony_ci memcpy(buf, reqctx->scratch_pad, reqctx->b0_len); 268962306a36Sopenharmony_ci buf += reqctx->b0_len; 269062306a36Sopenharmony_ci } 269162306a36Sopenharmony_ci sg_pcopy_to_buffer(req->src, sg_nents(req->src), 269262306a36Sopenharmony_ci buf, req->cryptlen + req->assoclen, 0); 269362306a36Sopenharmony_ci } else { 269462306a36Sopenharmony_ci ulptx_walk_init(&ulp_walk, ulptx); 269562306a36Sopenharmony_ci if (reqctx->b0_len) 269662306a36Sopenharmony_ci ulptx_walk_add_page(&ulp_walk, reqctx->b0_len, 269762306a36Sopenharmony_ci reqctx->b0_dma); 269862306a36Sopenharmony_ci ulptx_walk_add_sg(&ulp_walk, req->src, req->cryptlen + 269962306a36Sopenharmony_ci req->assoclen, 0); 270062306a36Sopenharmony_ci ulptx_walk_end(&ulp_walk); 270162306a36Sopenharmony_ci } 270262306a36Sopenharmony_ci} 270362306a36Sopenharmony_ci 270462306a36Sopenharmony_civoid chcr_add_aead_dst_ent(struct aead_request *req, 270562306a36Sopenharmony_ci struct cpl_rx_phys_dsgl *phys_cpl, 270662306a36Sopenharmony_ci unsigned short qid) 270762306a36Sopenharmony_ci{ 270862306a36Sopenharmony_ci struct chcr_aead_reqctx *reqctx = aead_request_ctx_dma(req); 270962306a36Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 271062306a36Sopenharmony_ci struct dsgl_walk dsgl_walk; 271162306a36Sopenharmony_ci unsigned int authsize = crypto_aead_authsize(tfm); 271262306a36Sopenharmony_ci struct chcr_context *ctx = a_ctx(tfm); 271362306a36Sopenharmony_ci struct uld_ctx *u_ctx = ULD_CTX(ctx); 271462306a36Sopenharmony_ci u32 temp; 271562306a36Sopenharmony_ci unsigned int rx_channel_id = reqctx->rxqidx / ctx->rxq_perchan; 271662306a36Sopenharmony_ci 271762306a36Sopenharmony_ci rx_channel_id = cxgb4_port_e2cchan(u_ctx->lldi.ports[rx_channel_id]); 271862306a36Sopenharmony_ci dsgl_walk_init(&dsgl_walk, phys_cpl); 271962306a36Sopenharmony_ci dsgl_walk_add_page(&dsgl_walk, IV + reqctx->b0_len, reqctx->iv_dma); 272062306a36Sopenharmony_ci temp = req->assoclen + req->cryptlen + 272162306a36Sopenharmony_ci (reqctx->op ? -authsize : authsize); 272262306a36Sopenharmony_ci dsgl_walk_add_sg(&dsgl_walk, req->dst, temp, 0); 272362306a36Sopenharmony_ci dsgl_walk_end(&dsgl_walk, qid, rx_channel_id); 272462306a36Sopenharmony_ci} 272562306a36Sopenharmony_ci 272662306a36Sopenharmony_civoid chcr_add_cipher_src_ent(struct skcipher_request *req, 272762306a36Sopenharmony_ci void *ulptx, 272862306a36Sopenharmony_ci struct cipher_wr_param *wrparam) 272962306a36Sopenharmony_ci{ 273062306a36Sopenharmony_ci struct ulptx_walk ulp_walk; 273162306a36Sopenharmony_ci struct chcr_skcipher_req_ctx *reqctx = skcipher_request_ctx(req); 273262306a36Sopenharmony_ci u8 *buf = ulptx; 273362306a36Sopenharmony_ci 273462306a36Sopenharmony_ci memcpy(buf, reqctx->iv, IV); 273562306a36Sopenharmony_ci buf += IV; 273662306a36Sopenharmony_ci if (reqctx->imm) { 273762306a36Sopenharmony_ci sg_pcopy_to_buffer(req->src, sg_nents(req->src), 273862306a36Sopenharmony_ci buf, wrparam->bytes, reqctx->processed); 273962306a36Sopenharmony_ci } else { 274062306a36Sopenharmony_ci ulptx_walk_init(&ulp_walk, (struct ulptx_sgl *)buf); 274162306a36Sopenharmony_ci ulptx_walk_add_sg(&ulp_walk, reqctx->srcsg, wrparam->bytes, 274262306a36Sopenharmony_ci reqctx->src_ofst); 274362306a36Sopenharmony_ci reqctx->srcsg = ulp_walk.last_sg; 274462306a36Sopenharmony_ci reqctx->src_ofst = ulp_walk.last_sg_len; 274562306a36Sopenharmony_ci ulptx_walk_end(&ulp_walk); 274662306a36Sopenharmony_ci } 274762306a36Sopenharmony_ci} 274862306a36Sopenharmony_ci 274962306a36Sopenharmony_civoid chcr_add_cipher_dst_ent(struct skcipher_request *req, 275062306a36Sopenharmony_ci struct cpl_rx_phys_dsgl *phys_cpl, 275162306a36Sopenharmony_ci struct cipher_wr_param *wrparam, 275262306a36Sopenharmony_ci unsigned short qid) 275362306a36Sopenharmony_ci{ 275462306a36Sopenharmony_ci struct chcr_skcipher_req_ctx *reqctx = skcipher_request_ctx(req); 275562306a36Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(wrparam->req); 275662306a36Sopenharmony_ci struct chcr_context *ctx = c_ctx(tfm); 275762306a36Sopenharmony_ci struct uld_ctx *u_ctx = ULD_CTX(ctx); 275862306a36Sopenharmony_ci struct dsgl_walk dsgl_walk; 275962306a36Sopenharmony_ci unsigned int rx_channel_id = reqctx->rxqidx / ctx->rxq_perchan; 276062306a36Sopenharmony_ci 276162306a36Sopenharmony_ci rx_channel_id = cxgb4_port_e2cchan(u_ctx->lldi.ports[rx_channel_id]); 276262306a36Sopenharmony_ci dsgl_walk_init(&dsgl_walk, phys_cpl); 276362306a36Sopenharmony_ci dsgl_walk_add_sg(&dsgl_walk, reqctx->dstsg, wrparam->bytes, 276462306a36Sopenharmony_ci reqctx->dst_ofst); 276562306a36Sopenharmony_ci reqctx->dstsg = dsgl_walk.last_sg; 276662306a36Sopenharmony_ci reqctx->dst_ofst = dsgl_walk.last_sg_len; 276762306a36Sopenharmony_ci dsgl_walk_end(&dsgl_walk, qid, rx_channel_id); 276862306a36Sopenharmony_ci} 276962306a36Sopenharmony_ci 277062306a36Sopenharmony_civoid chcr_add_hash_src_ent(struct ahash_request *req, 277162306a36Sopenharmony_ci struct ulptx_sgl *ulptx, 277262306a36Sopenharmony_ci struct hash_wr_param *param) 277362306a36Sopenharmony_ci{ 277462306a36Sopenharmony_ci struct ulptx_walk ulp_walk; 277562306a36Sopenharmony_ci struct chcr_ahash_req_ctx *reqctx = ahash_request_ctx(req); 277662306a36Sopenharmony_ci 277762306a36Sopenharmony_ci if (reqctx->hctx_wr.imm) { 277862306a36Sopenharmony_ci u8 *buf = (u8 *)ulptx; 277962306a36Sopenharmony_ci 278062306a36Sopenharmony_ci if (param->bfr_len) { 278162306a36Sopenharmony_ci memcpy(buf, reqctx->reqbfr, param->bfr_len); 278262306a36Sopenharmony_ci buf += param->bfr_len; 278362306a36Sopenharmony_ci } 278462306a36Sopenharmony_ci 278562306a36Sopenharmony_ci sg_pcopy_to_buffer(reqctx->hctx_wr.srcsg, 278662306a36Sopenharmony_ci sg_nents(reqctx->hctx_wr.srcsg), buf, 278762306a36Sopenharmony_ci param->sg_len, 0); 278862306a36Sopenharmony_ci } else { 278962306a36Sopenharmony_ci ulptx_walk_init(&ulp_walk, ulptx); 279062306a36Sopenharmony_ci if (param->bfr_len) 279162306a36Sopenharmony_ci ulptx_walk_add_page(&ulp_walk, param->bfr_len, 279262306a36Sopenharmony_ci reqctx->hctx_wr.dma_addr); 279362306a36Sopenharmony_ci ulptx_walk_add_sg(&ulp_walk, reqctx->hctx_wr.srcsg, 279462306a36Sopenharmony_ci param->sg_len, reqctx->hctx_wr.src_ofst); 279562306a36Sopenharmony_ci reqctx->hctx_wr.srcsg = ulp_walk.last_sg; 279662306a36Sopenharmony_ci reqctx->hctx_wr.src_ofst = ulp_walk.last_sg_len; 279762306a36Sopenharmony_ci ulptx_walk_end(&ulp_walk); 279862306a36Sopenharmony_ci } 279962306a36Sopenharmony_ci} 280062306a36Sopenharmony_ci 280162306a36Sopenharmony_ciint chcr_hash_dma_map(struct device *dev, 280262306a36Sopenharmony_ci struct ahash_request *req) 280362306a36Sopenharmony_ci{ 280462306a36Sopenharmony_ci struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(req); 280562306a36Sopenharmony_ci int error = 0; 280662306a36Sopenharmony_ci 280762306a36Sopenharmony_ci if (!req->nbytes) 280862306a36Sopenharmony_ci return 0; 280962306a36Sopenharmony_ci error = dma_map_sg(dev, req->src, sg_nents(req->src), 281062306a36Sopenharmony_ci DMA_TO_DEVICE); 281162306a36Sopenharmony_ci if (!error) 281262306a36Sopenharmony_ci return -ENOMEM; 281362306a36Sopenharmony_ci req_ctx->hctx_wr.is_sg_map = 1; 281462306a36Sopenharmony_ci return 0; 281562306a36Sopenharmony_ci} 281662306a36Sopenharmony_ci 281762306a36Sopenharmony_civoid chcr_hash_dma_unmap(struct device *dev, 281862306a36Sopenharmony_ci struct ahash_request *req) 281962306a36Sopenharmony_ci{ 282062306a36Sopenharmony_ci struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(req); 282162306a36Sopenharmony_ci 282262306a36Sopenharmony_ci if (!req->nbytes) 282362306a36Sopenharmony_ci return; 282462306a36Sopenharmony_ci 282562306a36Sopenharmony_ci dma_unmap_sg(dev, req->src, sg_nents(req->src), 282662306a36Sopenharmony_ci DMA_TO_DEVICE); 282762306a36Sopenharmony_ci req_ctx->hctx_wr.is_sg_map = 0; 282862306a36Sopenharmony_ci 282962306a36Sopenharmony_ci} 283062306a36Sopenharmony_ci 283162306a36Sopenharmony_ciint chcr_cipher_dma_map(struct device *dev, 283262306a36Sopenharmony_ci struct skcipher_request *req) 283362306a36Sopenharmony_ci{ 283462306a36Sopenharmony_ci int error; 283562306a36Sopenharmony_ci 283662306a36Sopenharmony_ci if (req->src == req->dst) { 283762306a36Sopenharmony_ci error = dma_map_sg(dev, req->src, sg_nents(req->src), 283862306a36Sopenharmony_ci DMA_BIDIRECTIONAL); 283962306a36Sopenharmony_ci if (!error) 284062306a36Sopenharmony_ci goto err; 284162306a36Sopenharmony_ci } else { 284262306a36Sopenharmony_ci error = dma_map_sg(dev, req->src, sg_nents(req->src), 284362306a36Sopenharmony_ci DMA_TO_DEVICE); 284462306a36Sopenharmony_ci if (!error) 284562306a36Sopenharmony_ci goto err; 284662306a36Sopenharmony_ci error = dma_map_sg(dev, req->dst, sg_nents(req->dst), 284762306a36Sopenharmony_ci DMA_FROM_DEVICE); 284862306a36Sopenharmony_ci if (!error) { 284962306a36Sopenharmony_ci dma_unmap_sg(dev, req->src, sg_nents(req->src), 285062306a36Sopenharmony_ci DMA_TO_DEVICE); 285162306a36Sopenharmony_ci goto err; 285262306a36Sopenharmony_ci } 285362306a36Sopenharmony_ci } 285462306a36Sopenharmony_ci 285562306a36Sopenharmony_ci return 0; 285662306a36Sopenharmony_cierr: 285762306a36Sopenharmony_ci return -ENOMEM; 285862306a36Sopenharmony_ci} 285962306a36Sopenharmony_ci 286062306a36Sopenharmony_civoid chcr_cipher_dma_unmap(struct device *dev, 286162306a36Sopenharmony_ci struct skcipher_request *req) 286262306a36Sopenharmony_ci{ 286362306a36Sopenharmony_ci if (req->src == req->dst) { 286462306a36Sopenharmony_ci dma_unmap_sg(dev, req->src, sg_nents(req->src), 286562306a36Sopenharmony_ci DMA_BIDIRECTIONAL); 286662306a36Sopenharmony_ci } else { 286762306a36Sopenharmony_ci dma_unmap_sg(dev, req->src, sg_nents(req->src), 286862306a36Sopenharmony_ci DMA_TO_DEVICE); 286962306a36Sopenharmony_ci dma_unmap_sg(dev, req->dst, sg_nents(req->dst), 287062306a36Sopenharmony_ci DMA_FROM_DEVICE); 287162306a36Sopenharmony_ci } 287262306a36Sopenharmony_ci} 287362306a36Sopenharmony_ci 287462306a36Sopenharmony_cistatic int set_msg_len(u8 *block, unsigned int msglen, int csize) 287562306a36Sopenharmony_ci{ 287662306a36Sopenharmony_ci __be32 data; 287762306a36Sopenharmony_ci 287862306a36Sopenharmony_ci memset(block, 0, csize); 287962306a36Sopenharmony_ci block += csize; 288062306a36Sopenharmony_ci 288162306a36Sopenharmony_ci if (csize >= 4) 288262306a36Sopenharmony_ci csize = 4; 288362306a36Sopenharmony_ci else if (msglen > (unsigned int)(1 << (8 * csize))) 288462306a36Sopenharmony_ci return -EOVERFLOW; 288562306a36Sopenharmony_ci 288662306a36Sopenharmony_ci data = cpu_to_be32(msglen); 288762306a36Sopenharmony_ci memcpy(block - csize, (u8 *)&data + 4 - csize, csize); 288862306a36Sopenharmony_ci 288962306a36Sopenharmony_ci return 0; 289062306a36Sopenharmony_ci} 289162306a36Sopenharmony_ci 289262306a36Sopenharmony_cistatic int generate_b0(struct aead_request *req, u8 *ivptr, 289362306a36Sopenharmony_ci unsigned short op_type) 289462306a36Sopenharmony_ci{ 289562306a36Sopenharmony_ci unsigned int l, lp, m; 289662306a36Sopenharmony_ci int rc; 289762306a36Sopenharmony_ci struct crypto_aead *aead = crypto_aead_reqtfm(req); 289862306a36Sopenharmony_ci struct chcr_aead_reqctx *reqctx = aead_request_ctx_dma(req); 289962306a36Sopenharmony_ci u8 *b0 = reqctx->scratch_pad; 290062306a36Sopenharmony_ci 290162306a36Sopenharmony_ci m = crypto_aead_authsize(aead); 290262306a36Sopenharmony_ci 290362306a36Sopenharmony_ci memcpy(b0, ivptr, 16); 290462306a36Sopenharmony_ci 290562306a36Sopenharmony_ci lp = b0[0]; 290662306a36Sopenharmony_ci l = lp + 1; 290762306a36Sopenharmony_ci 290862306a36Sopenharmony_ci /* set m, bits 3-5 */ 290962306a36Sopenharmony_ci *b0 |= (8 * ((m - 2) / 2)); 291062306a36Sopenharmony_ci 291162306a36Sopenharmony_ci /* set adata, bit 6, if associated data is used */ 291262306a36Sopenharmony_ci if (req->assoclen) 291362306a36Sopenharmony_ci *b0 |= 64; 291462306a36Sopenharmony_ci rc = set_msg_len(b0 + 16 - l, 291562306a36Sopenharmony_ci (op_type == CHCR_DECRYPT_OP) ? 291662306a36Sopenharmony_ci req->cryptlen - m : req->cryptlen, l); 291762306a36Sopenharmony_ci 291862306a36Sopenharmony_ci return rc; 291962306a36Sopenharmony_ci} 292062306a36Sopenharmony_ci 292162306a36Sopenharmony_cistatic inline int crypto_ccm_check_iv(const u8 *iv) 292262306a36Sopenharmony_ci{ 292362306a36Sopenharmony_ci /* 2 <= L <= 8, so 1 <= L' <= 7. */ 292462306a36Sopenharmony_ci if (iv[0] < 1 || iv[0] > 7) 292562306a36Sopenharmony_ci return -EINVAL; 292662306a36Sopenharmony_ci 292762306a36Sopenharmony_ci return 0; 292862306a36Sopenharmony_ci} 292962306a36Sopenharmony_ci 293062306a36Sopenharmony_cistatic int ccm_format_packet(struct aead_request *req, 293162306a36Sopenharmony_ci u8 *ivptr, 293262306a36Sopenharmony_ci unsigned int sub_type, 293362306a36Sopenharmony_ci unsigned short op_type, 293462306a36Sopenharmony_ci unsigned int assoclen) 293562306a36Sopenharmony_ci{ 293662306a36Sopenharmony_ci struct chcr_aead_reqctx *reqctx = aead_request_ctx_dma(req); 293762306a36Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 293862306a36Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm)); 293962306a36Sopenharmony_ci int rc = 0; 294062306a36Sopenharmony_ci 294162306a36Sopenharmony_ci if (sub_type == CRYPTO_ALG_SUB_TYPE_AEAD_RFC4309) { 294262306a36Sopenharmony_ci ivptr[0] = 3; 294362306a36Sopenharmony_ci memcpy(ivptr + 1, &aeadctx->salt[0], 3); 294462306a36Sopenharmony_ci memcpy(ivptr + 4, req->iv, 8); 294562306a36Sopenharmony_ci memset(ivptr + 12, 0, 4); 294662306a36Sopenharmony_ci } else { 294762306a36Sopenharmony_ci memcpy(ivptr, req->iv, 16); 294862306a36Sopenharmony_ci } 294962306a36Sopenharmony_ci if (assoclen) 295062306a36Sopenharmony_ci put_unaligned_be16(assoclen, &reqctx->scratch_pad[16]); 295162306a36Sopenharmony_ci 295262306a36Sopenharmony_ci rc = generate_b0(req, ivptr, op_type); 295362306a36Sopenharmony_ci /* zero the ctr value */ 295462306a36Sopenharmony_ci memset(ivptr + 15 - ivptr[0], 0, ivptr[0] + 1); 295562306a36Sopenharmony_ci return rc; 295662306a36Sopenharmony_ci} 295762306a36Sopenharmony_ci 295862306a36Sopenharmony_cistatic void fill_sec_cpl_for_aead(struct cpl_tx_sec_pdu *sec_cpl, 295962306a36Sopenharmony_ci unsigned int dst_size, 296062306a36Sopenharmony_ci struct aead_request *req, 296162306a36Sopenharmony_ci unsigned short op_type) 296262306a36Sopenharmony_ci{ 296362306a36Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 296462306a36Sopenharmony_ci struct chcr_context *ctx = a_ctx(tfm); 296562306a36Sopenharmony_ci struct uld_ctx *u_ctx = ULD_CTX(ctx); 296662306a36Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(ctx); 296762306a36Sopenharmony_ci struct chcr_aead_reqctx *reqctx = aead_request_ctx_dma(req); 296862306a36Sopenharmony_ci unsigned int cipher_mode = CHCR_SCMD_CIPHER_MODE_AES_CCM; 296962306a36Sopenharmony_ci unsigned int mac_mode = CHCR_SCMD_AUTH_MODE_CBCMAC; 297062306a36Sopenharmony_ci unsigned int rx_channel_id = reqctx->rxqidx / ctx->rxq_perchan; 297162306a36Sopenharmony_ci unsigned int ccm_xtra; 297262306a36Sopenharmony_ci unsigned int tag_offset = 0, auth_offset = 0; 297362306a36Sopenharmony_ci unsigned int assoclen; 297462306a36Sopenharmony_ci 297562306a36Sopenharmony_ci rx_channel_id = cxgb4_port_e2cchan(u_ctx->lldi.ports[rx_channel_id]); 297662306a36Sopenharmony_ci 297762306a36Sopenharmony_ci if (get_aead_subtype(tfm) == CRYPTO_ALG_SUB_TYPE_AEAD_RFC4309) 297862306a36Sopenharmony_ci assoclen = req->assoclen - 8; 297962306a36Sopenharmony_ci else 298062306a36Sopenharmony_ci assoclen = req->assoclen; 298162306a36Sopenharmony_ci ccm_xtra = CCM_B0_SIZE + 298262306a36Sopenharmony_ci ((assoclen) ? CCM_AAD_FIELD_SIZE : 0); 298362306a36Sopenharmony_ci 298462306a36Sopenharmony_ci auth_offset = req->cryptlen ? 298562306a36Sopenharmony_ci (req->assoclen + IV + 1 + ccm_xtra) : 0; 298662306a36Sopenharmony_ci if (op_type == CHCR_DECRYPT_OP) { 298762306a36Sopenharmony_ci if (crypto_aead_authsize(tfm) != req->cryptlen) 298862306a36Sopenharmony_ci tag_offset = crypto_aead_authsize(tfm); 298962306a36Sopenharmony_ci else 299062306a36Sopenharmony_ci auth_offset = 0; 299162306a36Sopenharmony_ci } 299262306a36Sopenharmony_ci 299362306a36Sopenharmony_ci sec_cpl->op_ivinsrtofst = FILL_SEC_CPL_OP_IVINSR(rx_channel_id, 2, 1); 299462306a36Sopenharmony_ci sec_cpl->pldlen = 299562306a36Sopenharmony_ci htonl(req->assoclen + IV + req->cryptlen + ccm_xtra); 299662306a36Sopenharmony_ci /* For CCM there wil be b0 always. So AAD start will be 1 always */ 299762306a36Sopenharmony_ci sec_cpl->aadstart_cipherstop_hi = FILL_SEC_CPL_CIPHERSTOP_HI( 299862306a36Sopenharmony_ci 1 + IV, IV + assoclen + ccm_xtra, 299962306a36Sopenharmony_ci req->assoclen + IV + 1 + ccm_xtra, 0); 300062306a36Sopenharmony_ci 300162306a36Sopenharmony_ci sec_cpl->cipherstop_lo_authinsert = FILL_SEC_CPL_AUTHINSERT(0, 300262306a36Sopenharmony_ci auth_offset, tag_offset, 300362306a36Sopenharmony_ci (op_type == CHCR_ENCRYPT_OP) ? 0 : 300462306a36Sopenharmony_ci crypto_aead_authsize(tfm)); 300562306a36Sopenharmony_ci sec_cpl->seqno_numivs = FILL_SEC_CPL_SCMD0_SEQNO(op_type, 300662306a36Sopenharmony_ci (op_type == CHCR_ENCRYPT_OP) ? 0 : 1, 300762306a36Sopenharmony_ci cipher_mode, mac_mode, 300862306a36Sopenharmony_ci aeadctx->hmac_ctrl, IV >> 1); 300962306a36Sopenharmony_ci 301062306a36Sopenharmony_ci sec_cpl->ivgen_hdrlen = FILL_SEC_CPL_IVGEN_HDRLEN(0, 0, 1, 0, 301162306a36Sopenharmony_ci 0, dst_size); 301262306a36Sopenharmony_ci} 301362306a36Sopenharmony_ci 301462306a36Sopenharmony_cistatic int aead_ccm_validate_input(unsigned short op_type, 301562306a36Sopenharmony_ci struct aead_request *req, 301662306a36Sopenharmony_ci struct chcr_aead_ctx *aeadctx, 301762306a36Sopenharmony_ci unsigned int sub_type) 301862306a36Sopenharmony_ci{ 301962306a36Sopenharmony_ci if (sub_type != CRYPTO_ALG_SUB_TYPE_AEAD_RFC4309) { 302062306a36Sopenharmony_ci if (crypto_ccm_check_iv(req->iv)) { 302162306a36Sopenharmony_ci pr_err("CCM: IV check fails\n"); 302262306a36Sopenharmony_ci return -EINVAL; 302362306a36Sopenharmony_ci } 302462306a36Sopenharmony_ci } else { 302562306a36Sopenharmony_ci if (req->assoclen != 16 && req->assoclen != 20) { 302662306a36Sopenharmony_ci pr_err("RFC4309: Invalid AAD length %d\n", 302762306a36Sopenharmony_ci req->assoclen); 302862306a36Sopenharmony_ci return -EINVAL; 302962306a36Sopenharmony_ci } 303062306a36Sopenharmony_ci } 303162306a36Sopenharmony_ci return 0; 303262306a36Sopenharmony_ci} 303362306a36Sopenharmony_ci 303462306a36Sopenharmony_cistatic struct sk_buff *create_aead_ccm_wr(struct aead_request *req, 303562306a36Sopenharmony_ci unsigned short qid, 303662306a36Sopenharmony_ci int size) 303762306a36Sopenharmony_ci{ 303862306a36Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 303962306a36Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm)); 304062306a36Sopenharmony_ci struct chcr_aead_reqctx *reqctx = aead_request_ctx_dma(req); 304162306a36Sopenharmony_ci struct sk_buff *skb = NULL; 304262306a36Sopenharmony_ci struct chcr_wr *chcr_req; 304362306a36Sopenharmony_ci struct cpl_rx_phys_dsgl *phys_cpl; 304462306a36Sopenharmony_ci struct ulptx_sgl *ulptx; 304562306a36Sopenharmony_ci unsigned int transhdr_len; 304662306a36Sopenharmony_ci unsigned int dst_size = 0, kctx_len, dnents, temp, snents; 304762306a36Sopenharmony_ci unsigned int sub_type, assoclen = req->assoclen; 304862306a36Sopenharmony_ci unsigned int authsize = crypto_aead_authsize(tfm); 304962306a36Sopenharmony_ci int error = -EINVAL; 305062306a36Sopenharmony_ci u8 *ivptr; 305162306a36Sopenharmony_ci gfp_t flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL : 305262306a36Sopenharmony_ci GFP_ATOMIC; 305362306a36Sopenharmony_ci struct adapter *adap = padap(a_ctx(tfm)->dev); 305462306a36Sopenharmony_ci 305562306a36Sopenharmony_ci sub_type = get_aead_subtype(tfm); 305662306a36Sopenharmony_ci if (sub_type == CRYPTO_ALG_SUB_TYPE_AEAD_RFC4309) 305762306a36Sopenharmony_ci assoclen -= 8; 305862306a36Sopenharmony_ci reqctx->b0_len = CCM_B0_SIZE + (assoclen ? CCM_AAD_FIELD_SIZE : 0); 305962306a36Sopenharmony_ci error = chcr_aead_common_init(req); 306062306a36Sopenharmony_ci if (error) 306162306a36Sopenharmony_ci return ERR_PTR(error); 306262306a36Sopenharmony_ci 306362306a36Sopenharmony_ci error = aead_ccm_validate_input(reqctx->op, req, aeadctx, sub_type); 306462306a36Sopenharmony_ci if (error) 306562306a36Sopenharmony_ci goto err; 306662306a36Sopenharmony_ci dnents = sg_nents_xlen(req->dst, req->assoclen + req->cryptlen 306762306a36Sopenharmony_ci + (reqctx->op ? -authsize : authsize), 306862306a36Sopenharmony_ci CHCR_DST_SG_SIZE, 0); 306962306a36Sopenharmony_ci dnents += MIN_CCM_SG; // For IV and B0 307062306a36Sopenharmony_ci dst_size = get_space_for_phys_dsgl(dnents); 307162306a36Sopenharmony_ci snents = sg_nents_xlen(req->src, req->assoclen + req->cryptlen, 307262306a36Sopenharmony_ci CHCR_SRC_SG_SIZE, 0); 307362306a36Sopenharmony_ci snents += MIN_CCM_SG; //For B0 307462306a36Sopenharmony_ci kctx_len = roundup(aeadctx->enckey_len, 16) * 2; 307562306a36Sopenharmony_ci transhdr_len = CIPHER_TRANSHDR_SIZE(kctx_len, dst_size); 307662306a36Sopenharmony_ci reqctx->imm = (transhdr_len + req->assoclen + req->cryptlen + 307762306a36Sopenharmony_ci reqctx->b0_len) <= SGE_MAX_WR_LEN; 307862306a36Sopenharmony_ci temp = reqctx->imm ? roundup(req->assoclen + req->cryptlen + 307962306a36Sopenharmony_ci reqctx->b0_len, 16) : 308062306a36Sopenharmony_ci (sgl_len(snents) * 8); 308162306a36Sopenharmony_ci transhdr_len += temp; 308262306a36Sopenharmony_ci transhdr_len = roundup(transhdr_len, 16); 308362306a36Sopenharmony_ci 308462306a36Sopenharmony_ci if (chcr_aead_need_fallback(req, dnents, T6_MAX_AAD_SIZE - 308562306a36Sopenharmony_ci reqctx->b0_len, transhdr_len, reqctx->op)) { 308662306a36Sopenharmony_ci atomic_inc(&adap->chcr_stats.fallback); 308762306a36Sopenharmony_ci chcr_aead_common_exit(req); 308862306a36Sopenharmony_ci return ERR_PTR(chcr_aead_fallback(req, reqctx->op)); 308962306a36Sopenharmony_ci } 309062306a36Sopenharmony_ci skb = alloc_skb(transhdr_len, flags); 309162306a36Sopenharmony_ci 309262306a36Sopenharmony_ci if (!skb) { 309362306a36Sopenharmony_ci error = -ENOMEM; 309462306a36Sopenharmony_ci goto err; 309562306a36Sopenharmony_ci } 309662306a36Sopenharmony_ci 309762306a36Sopenharmony_ci chcr_req = __skb_put_zero(skb, transhdr_len); 309862306a36Sopenharmony_ci 309962306a36Sopenharmony_ci fill_sec_cpl_for_aead(&chcr_req->sec_cpl, dst_size, req, reqctx->op); 310062306a36Sopenharmony_ci 310162306a36Sopenharmony_ci chcr_req->key_ctx.ctx_hdr = aeadctx->key_ctx_hdr; 310262306a36Sopenharmony_ci memcpy(chcr_req->key_ctx.key, aeadctx->key, aeadctx->enckey_len); 310362306a36Sopenharmony_ci memcpy(chcr_req->key_ctx.key + roundup(aeadctx->enckey_len, 16), 310462306a36Sopenharmony_ci aeadctx->key, aeadctx->enckey_len); 310562306a36Sopenharmony_ci 310662306a36Sopenharmony_ci phys_cpl = (struct cpl_rx_phys_dsgl *)((u8 *)(chcr_req + 1) + kctx_len); 310762306a36Sopenharmony_ci ivptr = (u8 *)(phys_cpl + 1) + dst_size; 310862306a36Sopenharmony_ci ulptx = (struct ulptx_sgl *)(ivptr + IV); 310962306a36Sopenharmony_ci error = ccm_format_packet(req, ivptr, sub_type, reqctx->op, assoclen); 311062306a36Sopenharmony_ci if (error) 311162306a36Sopenharmony_ci goto dstmap_fail; 311262306a36Sopenharmony_ci chcr_add_aead_dst_ent(req, phys_cpl, qid); 311362306a36Sopenharmony_ci chcr_add_aead_src_ent(req, ulptx); 311462306a36Sopenharmony_ci 311562306a36Sopenharmony_ci atomic_inc(&adap->chcr_stats.aead_rqst); 311662306a36Sopenharmony_ci temp = sizeof(struct cpl_rx_phys_dsgl) + dst_size + IV + 311762306a36Sopenharmony_ci kctx_len + (reqctx->imm ? (req->assoclen + req->cryptlen + 311862306a36Sopenharmony_ci reqctx->b0_len) : 0); 311962306a36Sopenharmony_ci create_wreq(a_ctx(tfm), chcr_req, &req->base, reqctx->imm, 0, 312062306a36Sopenharmony_ci transhdr_len, temp, 0); 312162306a36Sopenharmony_ci reqctx->skb = skb; 312262306a36Sopenharmony_ci 312362306a36Sopenharmony_ci return skb; 312462306a36Sopenharmony_cidstmap_fail: 312562306a36Sopenharmony_ci kfree_skb(skb); 312662306a36Sopenharmony_cierr: 312762306a36Sopenharmony_ci chcr_aead_common_exit(req); 312862306a36Sopenharmony_ci return ERR_PTR(error); 312962306a36Sopenharmony_ci} 313062306a36Sopenharmony_ci 313162306a36Sopenharmony_cistatic struct sk_buff *create_gcm_wr(struct aead_request *req, 313262306a36Sopenharmony_ci unsigned short qid, 313362306a36Sopenharmony_ci int size) 313462306a36Sopenharmony_ci{ 313562306a36Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 313662306a36Sopenharmony_ci struct chcr_context *ctx = a_ctx(tfm); 313762306a36Sopenharmony_ci struct uld_ctx *u_ctx = ULD_CTX(ctx); 313862306a36Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(ctx); 313962306a36Sopenharmony_ci struct chcr_aead_reqctx *reqctx = aead_request_ctx_dma(req); 314062306a36Sopenharmony_ci struct sk_buff *skb = NULL; 314162306a36Sopenharmony_ci struct chcr_wr *chcr_req; 314262306a36Sopenharmony_ci struct cpl_rx_phys_dsgl *phys_cpl; 314362306a36Sopenharmony_ci struct ulptx_sgl *ulptx; 314462306a36Sopenharmony_ci unsigned int transhdr_len, dnents = 0, snents; 314562306a36Sopenharmony_ci unsigned int dst_size = 0, temp = 0, kctx_len, assoclen = req->assoclen; 314662306a36Sopenharmony_ci unsigned int authsize = crypto_aead_authsize(tfm); 314762306a36Sopenharmony_ci int error = -EINVAL; 314862306a36Sopenharmony_ci u8 *ivptr; 314962306a36Sopenharmony_ci gfp_t flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL : 315062306a36Sopenharmony_ci GFP_ATOMIC; 315162306a36Sopenharmony_ci struct adapter *adap = padap(ctx->dev); 315262306a36Sopenharmony_ci unsigned int rx_channel_id = reqctx->rxqidx / ctx->rxq_perchan; 315362306a36Sopenharmony_ci 315462306a36Sopenharmony_ci rx_channel_id = cxgb4_port_e2cchan(u_ctx->lldi.ports[rx_channel_id]); 315562306a36Sopenharmony_ci if (get_aead_subtype(tfm) == CRYPTO_ALG_SUB_TYPE_AEAD_RFC4106) 315662306a36Sopenharmony_ci assoclen = req->assoclen - 8; 315762306a36Sopenharmony_ci 315862306a36Sopenharmony_ci reqctx->b0_len = 0; 315962306a36Sopenharmony_ci error = chcr_aead_common_init(req); 316062306a36Sopenharmony_ci if (error) 316162306a36Sopenharmony_ci return ERR_PTR(error); 316262306a36Sopenharmony_ci dnents = sg_nents_xlen(req->dst, req->assoclen + req->cryptlen + 316362306a36Sopenharmony_ci (reqctx->op ? -authsize : authsize), 316462306a36Sopenharmony_ci CHCR_DST_SG_SIZE, 0); 316562306a36Sopenharmony_ci snents = sg_nents_xlen(req->src, req->assoclen + req->cryptlen, 316662306a36Sopenharmony_ci CHCR_SRC_SG_SIZE, 0); 316762306a36Sopenharmony_ci dnents += MIN_GCM_SG; // For IV 316862306a36Sopenharmony_ci dst_size = get_space_for_phys_dsgl(dnents); 316962306a36Sopenharmony_ci kctx_len = roundup(aeadctx->enckey_len, 16) + AEAD_H_SIZE; 317062306a36Sopenharmony_ci transhdr_len = CIPHER_TRANSHDR_SIZE(kctx_len, dst_size); 317162306a36Sopenharmony_ci reqctx->imm = (transhdr_len + req->assoclen + req->cryptlen) <= 317262306a36Sopenharmony_ci SGE_MAX_WR_LEN; 317362306a36Sopenharmony_ci temp = reqctx->imm ? roundup(req->assoclen + req->cryptlen, 16) : 317462306a36Sopenharmony_ci (sgl_len(snents) * 8); 317562306a36Sopenharmony_ci transhdr_len += temp; 317662306a36Sopenharmony_ci transhdr_len = roundup(transhdr_len, 16); 317762306a36Sopenharmony_ci if (chcr_aead_need_fallback(req, dnents, T6_MAX_AAD_SIZE, 317862306a36Sopenharmony_ci transhdr_len, reqctx->op)) { 317962306a36Sopenharmony_ci 318062306a36Sopenharmony_ci atomic_inc(&adap->chcr_stats.fallback); 318162306a36Sopenharmony_ci chcr_aead_common_exit(req); 318262306a36Sopenharmony_ci return ERR_PTR(chcr_aead_fallback(req, reqctx->op)); 318362306a36Sopenharmony_ci } 318462306a36Sopenharmony_ci skb = alloc_skb(transhdr_len, flags); 318562306a36Sopenharmony_ci if (!skb) { 318662306a36Sopenharmony_ci error = -ENOMEM; 318762306a36Sopenharmony_ci goto err; 318862306a36Sopenharmony_ci } 318962306a36Sopenharmony_ci 319062306a36Sopenharmony_ci chcr_req = __skb_put_zero(skb, transhdr_len); 319162306a36Sopenharmony_ci 319262306a36Sopenharmony_ci //Offset of tag from end 319362306a36Sopenharmony_ci temp = (reqctx->op == CHCR_ENCRYPT_OP) ? 0 : authsize; 319462306a36Sopenharmony_ci chcr_req->sec_cpl.op_ivinsrtofst = FILL_SEC_CPL_OP_IVINSR( 319562306a36Sopenharmony_ci rx_channel_id, 2, 1); 319662306a36Sopenharmony_ci chcr_req->sec_cpl.pldlen = 319762306a36Sopenharmony_ci htonl(req->assoclen + IV + req->cryptlen); 319862306a36Sopenharmony_ci chcr_req->sec_cpl.aadstart_cipherstop_hi = FILL_SEC_CPL_CIPHERSTOP_HI( 319962306a36Sopenharmony_ci assoclen ? 1 + IV : 0, 320062306a36Sopenharmony_ci assoclen ? IV + assoclen : 0, 320162306a36Sopenharmony_ci req->assoclen + IV + 1, 0); 320262306a36Sopenharmony_ci chcr_req->sec_cpl.cipherstop_lo_authinsert = 320362306a36Sopenharmony_ci FILL_SEC_CPL_AUTHINSERT(0, req->assoclen + IV + 1, 320462306a36Sopenharmony_ci temp, temp); 320562306a36Sopenharmony_ci chcr_req->sec_cpl.seqno_numivs = 320662306a36Sopenharmony_ci FILL_SEC_CPL_SCMD0_SEQNO(reqctx->op, (reqctx->op == 320762306a36Sopenharmony_ci CHCR_ENCRYPT_OP) ? 1 : 0, 320862306a36Sopenharmony_ci CHCR_SCMD_CIPHER_MODE_AES_GCM, 320962306a36Sopenharmony_ci CHCR_SCMD_AUTH_MODE_GHASH, 321062306a36Sopenharmony_ci aeadctx->hmac_ctrl, IV >> 1); 321162306a36Sopenharmony_ci chcr_req->sec_cpl.ivgen_hdrlen = FILL_SEC_CPL_IVGEN_HDRLEN(0, 0, 1, 321262306a36Sopenharmony_ci 0, 0, dst_size); 321362306a36Sopenharmony_ci chcr_req->key_ctx.ctx_hdr = aeadctx->key_ctx_hdr; 321462306a36Sopenharmony_ci memcpy(chcr_req->key_ctx.key, aeadctx->key, aeadctx->enckey_len); 321562306a36Sopenharmony_ci memcpy(chcr_req->key_ctx.key + roundup(aeadctx->enckey_len, 16), 321662306a36Sopenharmony_ci GCM_CTX(aeadctx)->ghash_h, AEAD_H_SIZE); 321762306a36Sopenharmony_ci 321862306a36Sopenharmony_ci phys_cpl = (struct cpl_rx_phys_dsgl *)((u8 *)(chcr_req + 1) + kctx_len); 321962306a36Sopenharmony_ci ivptr = (u8 *)(phys_cpl + 1) + dst_size; 322062306a36Sopenharmony_ci /* prepare a 16 byte iv */ 322162306a36Sopenharmony_ci /* S A L T | IV | 0x00000001 */ 322262306a36Sopenharmony_ci if (get_aead_subtype(tfm) == 322362306a36Sopenharmony_ci CRYPTO_ALG_SUB_TYPE_AEAD_RFC4106) { 322462306a36Sopenharmony_ci memcpy(ivptr, aeadctx->salt, 4); 322562306a36Sopenharmony_ci memcpy(ivptr + 4, req->iv, GCM_RFC4106_IV_SIZE); 322662306a36Sopenharmony_ci } else { 322762306a36Sopenharmony_ci memcpy(ivptr, req->iv, GCM_AES_IV_SIZE); 322862306a36Sopenharmony_ci } 322962306a36Sopenharmony_ci put_unaligned_be32(0x01, &ivptr[12]); 323062306a36Sopenharmony_ci ulptx = (struct ulptx_sgl *)(ivptr + 16); 323162306a36Sopenharmony_ci 323262306a36Sopenharmony_ci chcr_add_aead_dst_ent(req, phys_cpl, qid); 323362306a36Sopenharmony_ci chcr_add_aead_src_ent(req, ulptx); 323462306a36Sopenharmony_ci atomic_inc(&adap->chcr_stats.aead_rqst); 323562306a36Sopenharmony_ci temp = sizeof(struct cpl_rx_phys_dsgl) + dst_size + IV + 323662306a36Sopenharmony_ci kctx_len + (reqctx->imm ? (req->assoclen + req->cryptlen) : 0); 323762306a36Sopenharmony_ci create_wreq(a_ctx(tfm), chcr_req, &req->base, reqctx->imm, size, 323862306a36Sopenharmony_ci transhdr_len, temp, reqctx->verify); 323962306a36Sopenharmony_ci reqctx->skb = skb; 324062306a36Sopenharmony_ci return skb; 324162306a36Sopenharmony_ci 324262306a36Sopenharmony_cierr: 324362306a36Sopenharmony_ci chcr_aead_common_exit(req); 324462306a36Sopenharmony_ci return ERR_PTR(error); 324562306a36Sopenharmony_ci} 324662306a36Sopenharmony_ci 324762306a36Sopenharmony_ci 324862306a36Sopenharmony_ci 324962306a36Sopenharmony_cistatic int chcr_aead_cra_init(struct crypto_aead *tfm) 325062306a36Sopenharmony_ci{ 325162306a36Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm)); 325262306a36Sopenharmony_ci struct aead_alg *alg = crypto_aead_alg(tfm); 325362306a36Sopenharmony_ci 325462306a36Sopenharmony_ci aeadctx->sw_cipher = crypto_alloc_aead(alg->base.cra_name, 0, 325562306a36Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK | 325662306a36Sopenharmony_ci CRYPTO_ALG_ASYNC); 325762306a36Sopenharmony_ci if (IS_ERR(aeadctx->sw_cipher)) 325862306a36Sopenharmony_ci return PTR_ERR(aeadctx->sw_cipher); 325962306a36Sopenharmony_ci crypto_aead_set_reqsize_dma( 326062306a36Sopenharmony_ci tfm, max(sizeof(struct chcr_aead_reqctx), 326162306a36Sopenharmony_ci sizeof(struct aead_request) + 326262306a36Sopenharmony_ci crypto_aead_reqsize(aeadctx->sw_cipher))); 326362306a36Sopenharmony_ci return chcr_device_init(a_ctx(tfm)); 326462306a36Sopenharmony_ci} 326562306a36Sopenharmony_ci 326662306a36Sopenharmony_cistatic void chcr_aead_cra_exit(struct crypto_aead *tfm) 326762306a36Sopenharmony_ci{ 326862306a36Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm)); 326962306a36Sopenharmony_ci 327062306a36Sopenharmony_ci crypto_free_aead(aeadctx->sw_cipher); 327162306a36Sopenharmony_ci} 327262306a36Sopenharmony_ci 327362306a36Sopenharmony_cistatic int chcr_authenc_null_setauthsize(struct crypto_aead *tfm, 327462306a36Sopenharmony_ci unsigned int authsize) 327562306a36Sopenharmony_ci{ 327662306a36Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm)); 327762306a36Sopenharmony_ci 327862306a36Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_NOP; 327962306a36Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 328062306a36Sopenharmony_ci return crypto_aead_setauthsize(aeadctx->sw_cipher, authsize); 328162306a36Sopenharmony_ci} 328262306a36Sopenharmony_cistatic int chcr_authenc_setauthsize(struct crypto_aead *tfm, 328362306a36Sopenharmony_ci unsigned int authsize) 328462306a36Sopenharmony_ci{ 328562306a36Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm)); 328662306a36Sopenharmony_ci u32 maxauth = crypto_aead_maxauthsize(tfm); 328762306a36Sopenharmony_ci 328862306a36Sopenharmony_ci /*SHA1 authsize in ipsec is 12 instead of 10 i.e maxauthsize / 2 is not 328962306a36Sopenharmony_ci * true for sha1. authsize == 12 condition should be before 329062306a36Sopenharmony_ci * authsize == (maxauth >> 1) 329162306a36Sopenharmony_ci */ 329262306a36Sopenharmony_ci if (authsize == ICV_4) { 329362306a36Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_PL1; 329462306a36Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 329562306a36Sopenharmony_ci } else if (authsize == ICV_6) { 329662306a36Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_PL2; 329762306a36Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 329862306a36Sopenharmony_ci } else if (authsize == ICV_10) { 329962306a36Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_TRUNC_RFC4366; 330062306a36Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 330162306a36Sopenharmony_ci } else if (authsize == ICV_12) { 330262306a36Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_IPSEC_96BIT; 330362306a36Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 330462306a36Sopenharmony_ci } else if (authsize == ICV_14) { 330562306a36Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_PL3; 330662306a36Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 330762306a36Sopenharmony_ci } else if (authsize == (maxauth >> 1)) { 330862306a36Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_DIV2; 330962306a36Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 331062306a36Sopenharmony_ci } else if (authsize == maxauth) { 331162306a36Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_NO_TRUNC; 331262306a36Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 331362306a36Sopenharmony_ci } else { 331462306a36Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_NO_TRUNC; 331562306a36Sopenharmony_ci aeadctx->mayverify = VERIFY_SW; 331662306a36Sopenharmony_ci } 331762306a36Sopenharmony_ci return crypto_aead_setauthsize(aeadctx->sw_cipher, authsize); 331862306a36Sopenharmony_ci} 331962306a36Sopenharmony_ci 332062306a36Sopenharmony_ci 332162306a36Sopenharmony_cistatic int chcr_gcm_setauthsize(struct crypto_aead *tfm, unsigned int authsize) 332262306a36Sopenharmony_ci{ 332362306a36Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm)); 332462306a36Sopenharmony_ci 332562306a36Sopenharmony_ci switch (authsize) { 332662306a36Sopenharmony_ci case ICV_4: 332762306a36Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_PL1; 332862306a36Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 332962306a36Sopenharmony_ci break; 333062306a36Sopenharmony_ci case ICV_8: 333162306a36Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_DIV2; 333262306a36Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 333362306a36Sopenharmony_ci break; 333462306a36Sopenharmony_ci case ICV_12: 333562306a36Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_IPSEC_96BIT; 333662306a36Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 333762306a36Sopenharmony_ci break; 333862306a36Sopenharmony_ci case ICV_14: 333962306a36Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_PL3; 334062306a36Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 334162306a36Sopenharmony_ci break; 334262306a36Sopenharmony_ci case ICV_16: 334362306a36Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_NO_TRUNC; 334462306a36Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 334562306a36Sopenharmony_ci break; 334662306a36Sopenharmony_ci case ICV_13: 334762306a36Sopenharmony_ci case ICV_15: 334862306a36Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_NO_TRUNC; 334962306a36Sopenharmony_ci aeadctx->mayverify = VERIFY_SW; 335062306a36Sopenharmony_ci break; 335162306a36Sopenharmony_ci default: 335262306a36Sopenharmony_ci return -EINVAL; 335362306a36Sopenharmony_ci } 335462306a36Sopenharmony_ci return crypto_aead_setauthsize(aeadctx->sw_cipher, authsize); 335562306a36Sopenharmony_ci} 335662306a36Sopenharmony_ci 335762306a36Sopenharmony_cistatic int chcr_4106_4309_setauthsize(struct crypto_aead *tfm, 335862306a36Sopenharmony_ci unsigned int authsize) 335962306a36Sopenharmony_ci{ 336062306a36Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm)); 336162306a36Sopenharmony_ci 336262306a36Sopenharmony_ci switch (authsize) { 336362306a36Sopenharmony_ci case ICV_8: 336462306a36Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_DIV2; 336562306a36Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 336662306a36Sopenharmony_ci break; 336762306a36Sopenharmony_ci case ICV_12: 336862306a36Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_IPSEC_96BIT; 336962306a36Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 337062306a36Sopenharmony_ci break; 337162306a36Sopenharmony_ci case ICV_16: 337262306a36Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_NO_TRUNC; 337362306a36Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 337462306a36Sopenharmony_ci break; 337562306a36Sopenharmony_ci default: 337662306a36Sopenharmony_ci return -EINVAL; 337762306a36Sopenharmony_ci } 337862306a36Sopenharmony_ci return crypto_aead_setauthsize(aeadctx->sw_cipher, authsize); 337962306a36Sopenharmony_ci} 338062306a36Sopenharmony_ci 338162306a36Sopenharmony_cistatic int chcr_ccm_setauthsize(struct crypto_aead *tfm, 338262306a36Sopenharmony_ci unsigned int authsize) 338362306a36Sopenharmony_ci{ 338462306a36Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(tfm)); 338562306a36Sopenharmony_ci 338662306a36Sopenharmony_ci switch (authsize) { 338762306a36Sopenharmony_ci case ICV_4: 338862306a36Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_PL1; 338962306a36Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 339062306a36Sopenharmony_ci break; 339162306a36Sopenharmony_ci case ICV_6: 339262306a36Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_PL2; 339362306a36Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 339462306a36Sopenharmony_ci break; 339562306a36Sopenharmony_ci case ICV_8: 339662306a36Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_DIV2; 339762306a36Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 339862306a36Sopenharmony_ci break; 339962306a36Sopenharmony_ci case ICV_10: 340062306a36Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_TRUNC_RFC4366; 340162306a36Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 340262306a36Sopenharmony_ci break; 340362306a36Sopenharmony_ci case ICV_12: 340462306a36Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_IPSEC_96BIT; 340562306a36Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 340662306a36Sopenharmony_ci break; 340762306a36Sopenharmony_ci case ICV_14: 340862306a36Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_PL3; 340962306a36Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 341062306a36Sopenharmony_ci break; 341162306a36Sopenharmony_ci case ICV_16: 341262306a36Sopenharmony_ci aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_NO_TRUNC; 341362306a36Sopenharmony_ci aeadctx->mayverify = VERIFY_HW; 341462306a36Sopenharmony_ci break; 341562306a36Sopenharmony_ci default: 341662306a36Sopenharmony_ci return -EINVAL; 341762306a36Sopenharmony_ci } 341862306a36Sopenharmony_ci return crypto_aead_setauthsize(aeadctx->sw_cipher, authsize); 341962306a36Sopenharmony_ci} 342062306a36Sopenharmony_ci 342162306a36Sopenharmony_cistatic int chcr_ccm_common_setkey(struct crypto_aead *aead, 342262306a36Sopenharmony_ci const u8 *key, 342362306a36Sopenharmony_ci unsigned int keylen) 342462306a36Sopenharmony_ci{ 342562306a36Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(aead)); 342662306a36Sopenharmony_ci unsigned char ck_size, mk_size; 342762306a36Sopenharmony_ci int key_ctx_size = 0; 342862306a36Sopenharmony_ci 342962306a36Sopenharmony_ci key_ctx_size = sizeof(struct _key_ctx) + roundup(keylen, 16) * 2; 343062306a36Sopenharmony_ci if (keylen == AES_KEYSIZE_128) { 343162306a36Sopenharmony_ci ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_128; 343262306a36Sopenharmony_ci mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_128; 343362306a36Sopenharmony_ci } else if (keylen == AES_KEYSIZE_192) { 343462306a36Sopenharmony_ci ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_192; 343562306a36Sopenharmony_ci mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_192; 343662306a36Sopenharmony_ci } else if (keylen == AES_KEYSIZE_256) { 343762306a36Sopenharmony_ci ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_256; 343862306a36Sopenharmony_ci mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_256; 343962306a36Sopenharmony_ci } else { 344062306a36Sopenharmony_ci aeadctx->enckey_len = 0; 344162306a36Sopenharmony_ci return -EINVAL; 344262306a36Sopenharmony_ci } 344362306a36Sopenharmony_ci aeadctx->key_ctx_hdr = FILL_KEY_CTX_HDR(ck_size, mk_size, 0, 0, 344462306a36Sopenharmony_ci key_ctx_size >> 4); 344562306a36Sopenharmony_ci memcpy(aeadctx->key, key, keylen); 344662306a36Sopenharmony_ci aeadctx->enckey_len = keylen; 344762306a36Sopenharmony_ci 344862306a36Sopenharmony_ci return 0; 344962306a36Sopenharmony_ci} 345062306a36Sopenharmony_ci 345162306a36Sopenharmony_cistatic int chcr_aead_ccm_setkey(struct crypto_aead *aead, 345262306a36Sopenharmony_ci const u8 *key, 345362306a36Sopenharmony_ci unsigned int keylen) 345462306a36Sopenharmony_ci{ 345562306a36Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(aead)); 345662306a36Sopenharmony_ci int error; 345762306a36Sopenharmony_ci 345862306a36Sopenharmony_ci crypto_aead_clear_flags(aeadctx->sw_cipher, CRYPTO_TFM_REQ_MASK); 345962306a36Sopenharmony_ci crypto_aead_set_flags(aeadctx->sw_cipher, crypto_aead_get_flags(aead) & 346062306a36Sopenharmony_ci CRYPTO_TFM_REQ_MASK); 346162306a36Sopenharmony_ci error = crypto_aead_setkey(aeadctx->sw_cipher, key, keylen); 346262306a36Sopenharmony_ci if (error) 346362306a36Sopenharmony_ci return error; 346462306a36Sopenharmony_ci return chcr_ccm_common_setkey(aead, key, keylen); 346562306a36Sopenharmony_ci} 346662306a36Sopenharmony_ci 346762306a36Sopenharmony_cistatic int chcr_aead_rfc4309_setkey(struct crypto_aead *aead, const u8 *key, 346862306a36Sopenharmony_ci unsigned int keylen) 346962306a36Sopenharmony_ci{ 347062306a36Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(aead)); 347162306a36Sopenharmony_ci int error; 347262306a36Sopenharmony_ci 347362306a36Sopenharmony_ci if (keylen < 3) { 347462306a36Sopenharmony_ci aeadctx->enckey_len = 0; 347562306a36Sopenharmony_ci return -EINVAL; 347662306a36Sopenharmony_ci } 347762306a36Sopenharmony_ci crypto_aead_clear_flags(aeadctx->sw_cipher, CRYPTO_TFM_REQ_MASK); 347862306a36Sopenharmony_ci crypto_aead_set_flags(aeadctx->sw_cipher, crypto_aead_get_flags(aead) & 347962306a36Sopenharmony_ci CRYPTO_TFM_REQ_MASK); 348062306a36Sopenharmony_ci error = crypto_aead_setkey(aeadctx->sw_cipher, key, keylen); 348162306a36Sopenharmony_ci if (error) 348262306a36Sopenharmony_ci return error; 348362306a36Sopenharmony_ci keylen -= 3; 348462306a36Sopenharmony_ci memcpy(aeadctx->salt, key + keylen, 3); 348562306a36Sopenharmony_ci return chcr_ccm_common_setkey(aead, key, keylen); 348662306a36Sopenharmony_ci} 348762306a36Sopenharmony_ci 348862306a36Sopenharmony_cistatic int chcr_gcm_setkey(struct crypto_aead *aead, const u8 *key, 348962306a36Sopenharmony_ci unsigned int keylen) 349062306a36Sopenharmony_ci{ 349162306a36Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(aead)); 349262306a36Sopenharmony_ci struct chcr_gcm_ctx *gctx = GCM_CTX(aeadctx); 349362306a36Sopenharmony_ci unsigned int ck_size; 349462306a36Sopenharmony_ci int ret = 0, key_ctx_size = 0; 349562306a36Sopenharmony_ci struct crypto_aes_ctx aes; 349662306a36Sopenharmony_ci 349762306a36Sopenharmony_ci aeadctx->enckey_len = 0; 349862306a36Sopenharmony_ci crypto_aead_clear_flags(aeadctx->sw_cipher, CRYPTO_TFM_REQ_MASK); 349962306a36Sopenharmony_ci crypto_aead_set_flags(aeadctx->sw_cipher, crypto_aead_get_flags(aead) 350062306a36Sopenharmony_ci & CRYPTO_TFM_REQ_MASK); 350162306a36Sopenharmony_ci ret = crypto_aead_setkey(aeadctx->sw_cipher, key, keylen); 350262306a36Sopenharmony_ci if (ret) 350362306a36Sopenharmony_ci goto out; 350462306a36Sopenharmony_ci 350562306a36Sopenharmony_ci if (get_aead_subtype(aead) == CRYPTO_ALG_SUB_TYPE_AEAD_RFC4106 && 350662306a36Sopenharmony_ci keylen > 3) { 350762306a36Sopenharmony_ci keylen -= 4; /* nonce/salt is present in the last 4 bytes */ 350862306a36Sopenharmony_ci memcpy(aeadctx->salt, key + keylen, 4); 350962306a36Sopenharmony_ci } 351062306a36Sopenharmony_ci if (keylen == AES_KEYSIZE_128) { 351162306a36Sopenharmony_ci ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_128; 351262306a36Sopenharmony_ci } else if (keylen == AES_KEYSIZE_192) { 351362306a36Sopenharmony_ci ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_192; 351462306a36Sopenharmony_ci } else if (keylen == AES_KEYSIZE_256) { 351562306a36Sopenharmony_ci ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_256; 351662306a36Sopenharmony_ci } else { 351762306a36Sopenharmony_ci pr_err("GCM: Invalid key length %d\n", keylen); 351862306a36Sopenharmony_ci ret = -EINVAL; 351962306a36Sopenharmony_ci goto out; 352062306a36Sopenharmony_ci } 352162306a36Sopenharmony_ci 352262306a36Sopenharmony_ci memcpy(aeadctx->key, key, keylen); 352362306a36Sopenharmony_ci aeadctx->enckey_len = keylen; 352462306a36Sopenharmony_ci key_ctx_size = sizeof(struct _key_ctx) + roundup(keylen, 16) + 352562306a36Sopenharmony_ci AEAD_H_SIZE; 352662306a36Sopenharmony_ci aeadctx->key_ctx_hdr = FILL_KEY_CTX_HDR(ck_size, 352762306a36Sopenharmony_ci CHCR_KEYCTX_MAC_KEY_SIZE_128, 352862306a36Sopenharmony_ci 0, 0, 352962306a36Sopenharmony_ci key_ctx_size >> 4); 353062306a36Sopenharmony_ci /* Calculate the H = CIPH(K, 0 repeated 16 times). 353162306a36Sopenharmony_ci * It will go in key context 353262306a36Sopenharmony_ci */ 353362306a36Sopenharmony_ci ret = aes_expandkey(&aes, key, keylen); 353462306a36Sopenharmony_ci if (ret) { 353562306a36Sopenharmony_ci aeadctx->enckey_len = 0; 353662306a36Sopenharmony_ci goto out; 353762306a36Sopenharmony_ci } 353862306a36Sopenharmony_ci memset(gctx->ghash_h, 0, AEAD_H_SIZE); 353962306a36Sopenharmony_ci aes_encrypt(&aes, gctx->ghash_h, gctx->ghash_h); 354062306a36Sopenharmony_ci memzero_explicit(&aes, sizeof(aes)); 354162306a36Sopenharmony_ci 354262306a36Sopenharmony_ciout: 354362306a36Sopenharmony_ci return ret; 354462306a36Sopenharmony_ci} 354562306a36Sopenharmony_ci 354662306a36Sopenharmony_cistatic int chcr_authenc_setkey(struct crypto_aead *authenc, const u8 *key, 354762306a36Sopenharmony_ci unsigned int keylen) 354862306a36Sopenharmony_ci{ 354962306a36Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(authenc)); 355062306a36Sopenharmony_ci struct chcr_authenc_ctx *actx = AUTHENC_CTX(aeadctx); 355162306a36Sopenharmony_ci /* it contains auth and cipher key both*/ 355262306a36Sopenharmony_ci struct crypto_authenc_keys keys; 355362306a36Sopenharmony_ci unsigned int bs, subtype; 355462306a36Sopenharmony_ci unsigned int max_authsize = crypto_aead_alg(authenc)->maxauthsize; 355562306a36Sopenharmony_ci int err = 0, i, key_ctx_len = 0; 355662306a36Sopenharmony_ci unsigned char ck_size = 0; 355762306a36Sopenharmony_ci unsigned char pad[CHCR_HASH_MAX_BLOCK_SIZE_128] = { 0 }; 355862306a36Sopenharmony_ci struct crypto_shash *base_hash = ERR_PTR(-EINVAL); 355962306a36Sopenharmony_ci struct algo_param param; 356062306a36Sopenharmony_ci int align; 356162306a36Sopenharmony_ci u8 *o_ptr = NULL; 356262306a36Sopenharmony_ci 356362306a36Sopenharmony_ci crypto_aead_clear_flags(aeadctx->sw_cipher, CRYPTO_TFM_REQ_MASK); 356462306a36Sopenharmony_ci crypto_aead_set_flags(aeadctx->sw_cipher, crypto_aead_get_flags(authenc) 356562306a36Sopenharmony_ci & CRYPTO_TFM_REQ_MASK); 356662306a36Sopenharmony_ci err = crypto_aead_setkey(aeadctx->sw_cipher, key, keylen); 356762306a36Sopenharmony_ci if (err) 356862306a36Sopenharmony_ci goto out; 356962306a36Sopenharmony_ci 357062306a36Sopenharmony_ci if (crypto_authenc_extractkeys(&keys, key, keylen) != 0) 357162306a36Sopenharmony_ci goto out; 357262306a36Sopenharmony_ci 357362306a36Sopenharmony_ci if (get_alg_config(¶m, max_authsize)) { 357462306a36Sopenharmony_ci pr_err("Unsupported digest size\n"); 357562306a36Sopenharmony_ci goto out; 357662306a36Sopenharmony_ci } 357762306a36Sopenharmony_ci subtype = get_aead_subtype(authenc); 357862306a36Sopenharmony_ci if (subtype == CRYPTO_ALG_SUB_TYPE_CTR_SHA || 357962306a36Sopenharmony_ci subtype == CRYPTO_ALG_SUB_TYPE_CTR_NULL) { 358062306a36Sopenharmony_ci if (keys.enckeylen < CTR_RFC3686_NONCE_SIZE) 358162306a36Sopenharmony_ci goto out; 358262306a36Sopenharmony_ci memcpy(aeadctx->nonce, keys.enckey + (keys.enckeylen 358362306a36Sopenharmony_ci - CTR_RFC3686_NONCE_SIZE), CTR_RFC3686_NONCE_SIZE); 358462306a36Sopenharmony_ci keys.enckeylen -= CTR_RFC3686_NONCE_SIZE; 358562306a36Sopenharmony_ci } 358662306a36Sopenharmony_ci if (keys.enckeylen == AES_KEYSIZE_128) { 358762306a36Sopenharmony_ci ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_128; 358862306a36Sopenharmony_ci } else if (keys.enckeylen == AES_KEYSIZE_192) { 358962306a36Sopenharmony_ci ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_192; 359062306a36Sopenharmony_ci } else if (keys.enckeylen == AES_KEYSIZE_256) { 359162306a36Sopenharmony_ci ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_256; 359262306a36Sopenharmony_ci } else { 359362306a36Sopenharmony_ci pr_err("Unsupported cipher key\n"); 359462306a36Sopenharmony_ci goto out; 359562306a36Sopenharmony_ci } 359662306a36Sopenharmony_ci 359762306a36Sopenharmony_ci /* Copy only encryption key. We use authkey to generate h(ipad) and 359862306a36Sopenharmony_ci * h(opad) so authkey is not needed again. authkeylen size have the 359962306a36Sopenharmony_ci * size of the hash digest size. 360062306a36Sopenharmony_ci */ 360162306a36Sopenharmony_ci memcpy(aeadctx->key, keys.enckey, keys.enckeylen); 360262306a36Sopenharmony_ci aeadctx->enckey_len = keys.enckeylen; 360362306a36Sopenharmony_ci if (subtype == CRYPTO_ALG_SUB_TYPE_CBC_SHA || 360462306a36Sopenharmony_ci subtype == CRYPTO_ALG_SUB_TYPE_CBC_NULL) { 360562306a36Sopenharmony_ci 360662306a36Sopenharmony_ci get_aes_decrypt_key(actx->dec_rrkey, aeadctx->key, 360762306a36Sopenharmony_ci aeadctx->enckey_len << 3); 360862306a36Sopenharmony_ci } 360962306a36Sopenharmony_ci base_hash = chcr_alloc_shash(max_authsize); 361062306a36Sopenharmony_ci if (IS_ERR(base_hash)) { 361162306a36Sopenharmony_ci pr_err("Base driver cannot be loaded\n"); 361262306a36Sopenharmony_ci goto out; 361362306a36Sopenharmony_ci } 361462306a36Sopenharmony_ci { 361562306a36Sopenharmony_ci SHASH_DESC_ON_STACK(shash, base_hash); 361662306a36Sopenharmony_ci 361762306a36Sopenharmony_ci shash->tfm = base_hash; 361862306a36Sopenharmony_ci bs = crypto_shash_blocksize(base_hash); 361962306a36Sopenharmony_ci align = KEYCTX_ALIGN_PAD(max_authsize); 362062306a36Sopenharmony_ci o_ptr = actx->h_iopad + param.result_size + align; 362162306a36Sopenharmony_ci 362262306a36Sopenharmony_ci if (keys.authkeylen > bs) { 362362306a36Sopenharmony_ci err = crypto_shash_digest(shash, keys.authkey, 362462306a36Sopenharmony_ci keys.authkeylen, 362562306a36Sopenharmony_ci o_ptr); 362662306a36Sopenharmony_ci if (err) { 362762306a36Sopenharmony_ci pr_err("Base driver cannot be loaded\n"); 362862306a36Sopenharmony_ci goto out; 362962306a36Sopenharmony_ci } 363062306a36Sopenharmony_ci keys.authkeylen = max_authsize; 363162306a36Sopenharmony_ci } else 363262306a36Sopenharmony_ci memcpy(o_ptr, keys.authkey, keys.authkeylen); 363362306a36Sopenharmony_ci 363462306a36Sopenharmony_ci /* Compute the ipad-digest*/ 363562306a36Sopenharmony_ci memset(pad + keys.authkeylen, 0, bs - keys.authkeylen); 363662306a36Sopenharmony_ci memcpy(pad, o_ptr, keys.authkeylen); 363762306a36Sopenharmony_ci for (i = 0; i < bs >> 2; i++) 363862306a36Sopenharmony_ci *((unsigned int *)pad + i) ^= IPAD_DATA; 363962306a36Sopenharmony_ci 364062306a36Sopenharmony_ci if (chcr_compute_partial_hash(shash, pad, actx->h_iopad, 364162306a36Sopenharmony_ci max_authsize)) 364262306a36Sopenharmony_ci goto out; 364362306a36Sopenharmony_ci /* Compute the opad-digest */ 364462306a36Sopenharmony_ci memset(pad + keys.authkeylen, 0, bs - keys.authkeylen); 364562306a36Sopenharmony_ci memcpy(pad, o_ptr, keys.authkeylen); 364662306a36Sopenharmony_ci for (i = 0; i < bs >> 2; i++) 364762306a36Sopenharmony_ci *((unsigned int *)pad + i) ^= OPAD_DATA; 364862306a36Sopenharmony_ci 364962306a36Sopenharmony_ci if (chcr_compute_partial_hash(shash, pad, o_ptr, max_authsize)) 365062306a36Sopenharmony_ci goto out; 365162306a36Sopenharmony_ci 365262306a36Sopenharmony_ci /* convert the ipad and opad digest to network order */ 365362306a36Sopenharmony_ci chcr_change_order(actx->h_iopad, param.result_size); 365462306a36Sopenharmony_ci chcr_change_order(o_ptr, param.result_size); 365562306a36Sopenharmony_ci key_ctx_len = sizeof(struct _key_ctx) + 365662306a36Sopenharmony_ci roundup(keys.enckeylen, 16) + 365762306a36Sopenharmony_ci (param.result_size + align) * 2; 365862306a36Sopenharmony_ci aeadctx->key_ctx_hdr = FILL_KEY_CTX_HDR(ck_size, param.mk_size, 365962306a36Sopenharmony_ci 0, 1, key_ctx_len >> 4); 366062306a36Sopenharmony_ci actx->auth_mode = param.auth_mode; 366162306a36Sopenharmony_ci chcr_free_shash(base_hash); 366262306a36Sopenharmony_ci 366362306a36Sopenharmony_ci memzero_explicit(&keys, sizeof(keys)); 366462306a36Sopenharmony_ci return 0; 366562306a36Sopenharmony_ci } 366662306a36Sopenharmony_ciout: 366762306a36Sopenharmony_ci aeadctx->enckey_len = 0; 366862306a36Sopenharmony_ci memzero_explicit(&keys, sizeof(keys)); 366962306a36Sopenharmony_ci if (!IS_ERR(base_hash)) 367062306a36Sopenharmony_ci chcr_free_shash(base_hash); 367162306a36Sopenharmony_ci return -EINVAL; 367262306a36Sopenharmony_ci} 367362306a36Sopenharmony_ci 367462306a36Sopenharmony_cistatic int chcr_aead_digest_null_setkey(struct crypto_aead *authenc, 367562306a36Sopenharmony_ci const u8 *key, unsigned int keylen) 367662306a36Sopenharmony_ci{ 367762306a36Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(a_ctx(authenc)); 367862306a36Sopenharmony_ci struct chcr_authenc_ctx *actx = AUTHENC_CTX(aeadctx); 367962306a36Sopenharmony_ci struct crypto_authenc_keys keys; 368062306a36Sopenharmony_ci int err; 368162306a36Sopenharmony_ci /* it contains auth and cipher key both*/ 368262306a36Sopenharmony_ci unsigned int subtype; 368362306a36Sopenharmony_ci int key_ctx_len = 0; 368462306a36Sopenharmony_ci unsigned char ck_size = 0; 368562306a36Sopenharmony_ci 368662306a36Sopenharmony_ci crypto_aead_clear_flags(aeadctx->sw_cipher, CRYPTO_TFM_REQ_MASK); 368762306a36Sopenharmony_ci crypto_aead_set_flags(aeadctx->sw_cipher, crypto_aead_get_flags(authenc) 368862306a36Sopenharmony_ci & CRYPTO_TFM_REQ_MASK); 368962306a36Sopenharmony_ci err = crypto_aead_setkey(aeadctx->sw_cipher, key, keylen); 369062306a36Sopenharmony_ci if (err) 369162306a36Sopenharmony_ci goto out; 369262306a36Sopenharmony_ci 369362306a36Sopenharmony_ci if (crypto_authenc_extractkeys(&keys, key, keylen) != 0) 369462306a36Sopenharmony_ci goto out; 369562306a36Sopenharmony_ci 369662306a36Sopenharmony_ci subtype = get_aead_subtype(authenc); 369762306a36Sopenharmony_ci if (subtype == CRYPTO_ALG_SUB_TYPE_CTR_SHA || 369862306a36Sopenharmony_ci subtype == CRYPTO_ALG_SUB_TYPE_CTR_NULL) { 369962306a36Sopenharmony_ci if (keys.enckeylen < CTR_RFC3686_NONCE_SIZE) 370062306a36Sopenharmony_ci goto out; 370162306a36Sopenharmony_ci memcpy(aeadctx->nonce, keys.enckey + (keys.enckeylen 370262306a36Sopenharmony_ci - CTR_RFC3686_NONCE_SIZE), CTR_RFC3686_NONCE_SIZE); 370362306a36Sopenharmony_ci keys.enckeylen -= CTR_RFC3686_NONCE_SIZE; 370462306a36Sopenharmony_ci } 370562306a36Sopenharmony_ci if (keys.enckeylen == AES_KEYSIZE_128) { 370662306a36Sopenharmony_ci ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_128; 370762306a36Sopenharmony_ci } else if (keys.enckeylen == AES_KEYSIZE_192) { 370862306a36Sopenharmony_ci ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_192; 370962306a36Sopenharmony_ci } else if (keys.enckeylen == AES_KEYSIZE_256) { 371062306a36Sopenharmony_ci ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_256; 371162306a36Sopenharmony_ci } else { 371262306a36Sopenharmony_ci pr_err("Unsupported cipher key %d\n", keys.enckeylen); 371362306a36Sopenharmony_ci goto out; 371462306a36Sopenharmony_ci } 371562306a36Sopenharmony_ci memcpy(aeadctx->key, keys.enckey, keys.enckeylen); 371662306a36Sopenharmony_ci aeadctx->enckey_len = keys.enckeylen; 371762306a36Sopenharmony_ci if (subtype == CRYPTO_ALG_SUB_TYPE_CBC_SHA || 371862306a36Sopenharmony_ci subtype == CRYPTO_ALG_SUB_TYPE_CBC_NULL) { 371962306a36Sopenharmony_ci get_aes_decrypt_key(actx->dec_rrkey, aeadctx->key, 372062306a36Sopenharmony_ci aeadctx->enckey_len << 3); 372162306a36Sopenharmony_ci } 372262306a36Sopenharmony_ci key_ctx_len = sizeof(struct _key_ctx) + roundup(keys.enckeylen, 16); 372362306a36Sopenharmony_ci 372462306a36Sopenharmony_ci aeadctx->key_ctx_hdr = FILL_KEY_CTX_HDR(ck_size, CHCR_KEYCTX_NO_KEY, 0, 372562306a36Sopenharmony_ci 0, key_ctx_len >> 4); 372662306a36Sopenharmony_ci actx->auth_mode = CHCR_SCMD_AUTH_MODE_NOP; 372762306a36Sopenharmony_ci memzero_explicit(&keys, sizeof(keys)); 372862306a36Sopenharmony_ci return 0; 372962306a36Sopenharmony_ciout: 373062306a36Sopenharmony_ci aeadctx->enckey_len = 0; 373162306a36Sopenharmony_ci memzero_explicit(&keys, sizeof(keys)); 373262306a36Sopenharmony_ci return -EINVAL; 373362306a36Sopenharmony_ci} 373462306a36Sopenharmony_ci 373562306a36Sopenharmony_cistatic int chcr_aead_op(struct aead_request *req, 373662306a36Sopenharmony_ci int size, 373762306a36Sopenharmony_ci create_wr_t create_wr_fn) 373862306a36Sopenharmony_ci{ 373962306a36Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 374062306a36Sopenharmony_ci struct chcr_aead_reqctx *reqctx = aead_request_ctx_dma(req); 374162306a36Sopenharmony_ci struct chcr_context *ctx = a_ctx(tfm); 374262306a36Sopenharmony_ci struct uld_ctx *u_ctx = ULD_CTX(ctx); 374362306a36Sopenharmony_ci struct sk_buff *skb; 374462306a36Sopenharmony_ci struct chcr_dev *cdev; 374562306a36Sopenharmony_ci 374662306a36Sopenharmony_ci cdev = a_ctx(tfm)->dev; 374762306a36Sopenharmony_ci if (!cdev) { 374862306a36Sopenharmony_ci pr_err("%s : No crypto device.\n", __func__); 374962306a36Sopenharmony_ci return -ENXIO; 375062306a36Sopenharmony_ci } 375162306a36Sopenharmony_ci 375262306a36Sopenharmony_ci if (chcr_inc_wrcount(cdev)) { 375362306a36Sopenharmony_ci /* Detach state for CHCR means lldi or padap is freed. 375462306a36Sopenharmony_ci * We cannot increment fallback here. 375562306a36Sopenharmony_ci */ 375662306a36Sopenharmony_ci return chcr_aead_fallback(req, reqctx->op); 375762306a36Sopenharmony_ci } 375862306a36Sopenharmony_ci 375962306a36Sopenharmony_ci if (cxgb4_is_crypto_q_full(u_ctx->lldi.ports[0], 376062306a36Sopenharmony_ci reqctx->txqidx) && 376162306a36Sopenharmony_ci (!(req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG))) { 376262306a36Sopenharmony_ci chcr_dec_wrcount(cdev); 376362306a36Sopenharmony_ci return -ENOSPC; 376462306a36Sopenharmony_ci } 376562306a36Sopenharmony_ci 376662306a36Sopenharmony_ci if (get_aead_subtype(tfm) == CRYPTO_ALG_SUB_TYPE_AEAD_RFC4106 && 376762306a36Sopenharmony_ci crypto_ipsec_check_assoclen(req->assoclen) != 0) { 376862306a36Sopenharmony_ci pr_err("RFC4106: Invalid value of assoclen %d\n", 376962306a36Sopenharmony_ci req->assoclen); 377062306a36Sopenharmony_ci return -EINVAL; 377162306a36Sopenharmony_ci } 377262306a36Sopenharmony_ci 377362306a36Sopenharmony_ci /* Form a WR from req */ 377462306a36Sopenharmony_ci skb = create_wr_fn(req, u_ctx->lldi.rxq_ids[reqctx->rxqidx], size); 377562306a36Sopenharmony_ci 377662306a36Sopenharmony_ci if (IS_ERR_OR_NULL(skb)) { 377762306a36Sopenharmony_ci chcr_dec_wrcount(cdev); 377862306a36Sopenharmony_ci return PTR_ERR_OR_ZERO(skb); 377962306a36Sopenharmony_ci } 378062306a36Sopenharmony_ci 378162306a36Sopenharmony_ci skb->dev = u_ctx->lldi.ports[0]; 378262306a36Sopenharmony_ci set_wr_txq(skb, CPL_PRIORITY_DATA, reqctx->txqidx); 378362306a36Sopenharmony_ci chcr_send_wr(skb); 378462306a36Sopenharmony_ci return -EINPROGRESS; 378562306a36Sopenharmony_ci} 378662306a36Sopenharmony_ci 378762306a36Sopenharmony_cistatic int chcr_aead_encrypt(struct aead_request *req) 378862306a36Sopenharmony_ci{ 378962306a36Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 379062306a36Sopenharmony_ci struct chcr_aead_reqctx *reqctx = aead_request_ctx_dma(req); 379162306a36Sopenharmony_ci struct chcr_context *ctx = a_ctx(tfm); 379262306a36Sopenharmony_ci unsigned int cpu; 379362306a36Sopenharmony_ci 379462306a36Sopenharmony_ci cpu = get_cpu(); 379562306a36Sopenharmony_ci reqctx->txqidx = cpu % ctx->ntxq; 379662306a36Sopenharmony_ci reqctx->rxqidx = cpu % ctx->nrxq; 379762306a36Sopenharmony_ci put_cpu(); 379862306a36Sopenharmony_ci 379962306a36Sopenharmony_ci reqctx->verify = VERIFY_HW; 380062306a36Sopenharmony_ci reqctx->op = CHCR_ENCRYPT_OP; 380162306a36Sopenharmony_ci 380262306a36Sopenharmony_ci switch (get_aead_subtype(tfm)) { 380362306a36Sopenharmony_ci case CRYPTO_ALG_SUB_TYPE_CTR_SHA: 380462306a36Sopenharmony_ci case CRYPTO_ALG_SUB_TYPE_CBC_SHA: 380562306a36Sopenharmony_ci case CRYPTO_ALG_SUB_TYPE_CBC_NULL: 380662306a36Sopenharmony_ci case CRYPTO_ALG_SUB_TYPE_CTR_NULL: 380762306a36Sopenharmony_ci return chcr_aead_op(req, 0, create_authenc_wr); 380862306a36Sopenharmony_ci case CRYPTO_ALG_SUB_TYPE_AEAD_CCM: 380962306a36Sopenharmony_ci case CRYPTO_ALG_SUB_TYPE_AEAD_RFC4309: 381062306a36Sopenharmony_ci return chcr_aead_op(req, 0, create_aead_ccm_wr); 381162306a36Sopenharmony_ci default: 381262306a36Sopenharmony_ci return chcr_aead_op(req, 0, create_gcm_wr); 381362306a36Sopenharmony_ci } 381462306a36Sopenharmony_ci} 381562306a36Sopenharmony_ci 381662306a36Sopenharmony_cistatic int chcr_aead_decrypt(struct aead_request *req) 381762306a36Sopenharmony_ci{ 381862306a36Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 381962306a36Sopenharmony_ci struct chcr_context *ctx = a_ctx(tfm); 382062306a36Sopenharmony_ci struct chcr_aead_ctx *aeadctx = AEAD_CTX(ctx); 382162306a36Sopenharmony_ci struct chcr_aead_reqctx *reqctx = aead_request_ctx_dma(req); 382262306a36Sopenharmony_ci int size; 382362306a36Sopenharmony_ci unsigned int cpu; 382462306a36Sopenharmony_ci 382562306a36Sopenharmony_ci cpu = get_cpu(); 382662306a36Sopenharmony_ci reqctx->txqidx = cpu % ctx->ntxq; 382762306a36Sopenharmony_ci reqctx->rxqidx = cpu % ctx->nrxq; 382862306a36Sopenharmony_ci put_cpu(); 382962306a36Sopenharmony_ci 383062306a36Sopenharmony_ci if (aeadctx->mayverify == VERIFY_SW) { 383162306a36Sopenharmony_ci size = crypto_aead_maxauthsize(tfm); 383262306a36Sopenharmony_ci reqctx->verify = VERIFY_SW; 383362306a36Sopenharmony_ci } else { 383462306a36Sopenharmony_ci size = 0; 383562306a36Sopenharmony_ci reqctx->verify = VERIFY_HW; 383662306a36Sopenharmony_ci } 383762306a36Sopenharmony_ci reqctx->op = CHCR_DECRYPT_OP; 383862306a36Sopenharmony_ci switch (get_aead_subtype(tfm)) { 383962306a36Sopenharmony_ci case CRYPTO_ALG_SUB_TYPE_CBC_SHA: 384062306a36Sopenharmony_ci case CRYPTO_ALG_SUB_TYPE_CTR_SHA: 384162306a36Sopenharmony_ci case CRYPTO_ALG_SUB_TYPE_CBC_NULL: 384262306a36Sopenharmony_ci case CRYPTO_ALG_SUB_TYPE_CTR_NULL: 384362306a36Sopenharmony_ci return chcr_aead_op(req, size, create_authenc_wr); 384462306a36Sopenharmony_ci case CRYPTO_ALG_SUB_TYPE_AEAD_CCM: 384562306a36Sopenharmony_ci case CRYPTO_ALG_SUB_TYPE_AEAD_RFC4309: 384662306a36Sopenharmony_ci return chcr_aead_op(req, size, create_aead_ccm_wr); 384762306a36Sopenharmony_ci default: 384862306a36Sopenharmony_ci return chcr_aead_op(req, size, create_gcm_wr); 384962306a36Sopenharmony_ci } 385062306a36Sopenharmony_ci} 385162306a36Sopenharmony_ci 385262306a36Sopenharmony_cistatic struct chcr_alg_template driver_algs[] = { 385362306a36Sopenharmony_ci /* AES-CBC */ 385462306a36Sopenharmony_ci { 385562306a36Sopenharmony_ci .type = CRYPTO_ALG_TYPE_SKCIPHER | CRYPTO_ALG_SUB_TYPE_CBC, 385662306a36Sopenharmony_ci .is_registered = 0, 385762306a36Sopenharmony_ci .alg.skcipher = { 385862306a36Sopenharmony_ci .base.cra_name = "cbc(aes)", 385962306a36Sopenharmony_ci .base.cra_driver_name = "cbc-aes-chcr", 386062306a36Sopenharmony_ci .base.cra_blocksize = AES_BLOCK_SIZE, 386162306a36Sopenharmony_ci 386262306a36Sopenharmony_ci .init = chcr_init_tfm, 386362306a36Sopenharmony_ci .exit = chcr_exit_tfm, 386462306a36Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE, 386562306a36Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE, 386662306a36Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 386762306a36Sopenharmony_ci .setkey = chcr_aes_cbc_setkey, 386862306a36Sopenharmony_ci .encrypt = chcr_aes_encrypt, 386962306a36Sopenharmony_ci .decrypt = chcr_aes_decrypt, 387062306a36Sopenharmony_ci } 387162306a36Sopenharmony_ci }, 387262306a36Sopenharmony_ci { 387362306a36Sopenharmony_ci .type = CRYPTO_ALG_TYPE_SKCIPHER | CRYPTO_ALG_SUB_TYPE_XTS, 387462306a36Sopenharmony_ci .is_registered = 0, 387562306a36Sopenharmony_ci .alg.skcipher = { 387662306a36Sopenharmony_ci .base.cra_name = "xts(aes)", 387762306a36Sopenharmony_ci .base.cra_driver_name = "xts-aes-chcr", 387862306a36Sopenharmony_ci .base.cra_blocksize = AES_BLOCK_SIZE, 387962306a36Sopenharmony_ci 388062306a36Sopenharmony_ci .init = chcr_init_tfm, 388162306a36Sopenharmony_ci .exit = chcr_exit_tfm, 388262306a36Sopenharmony_ci .min_keysize = 2 * AES_MIN_KEY_SIZE, 388362306a36Sopenharmony_ci .max_keysize = 2 * AES_MAX_KEY_SIZE, 388462306a36Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 388562306a36Sopenharmony_ci .setkey = chcr_aes_xts_setkey, 388662306a36Sopenharmony_ci .encrypt = chcr_aes_encrypt, 388762306a36Sopenharmony_ci .decrypt = chcr_aes_decrypt, 388862306a36Sopenharmony_ci } 388962306a36Sopenharmony_ci }, 389062306a36Sopenharmony_ci { 389162306a36Sopenharmony_ci .type = CRYPTO_ALG_TYPE_SKCIPHER | CRYPTO_ALG_SUB_TYPE_CTR, 389262306a36Sopenharmony_ci .is_registered = 0, 389362306a36Sopenharmony_ci .alg.skcipher = { 389462306a36Sopenharmony_ci .base.cra_name = "ctr(aes)", 389562306a36Sopenharmony_ci .base.cra_driver_name = "ctr-aes-chcr", 389662306a36Sopenharmony_ci .base.cra_blocksize = 1, 389762306a36Sopenharmony_ci 389862306a36Sopenharmony_ci .init = chcr_init_tfm, 389962306a36Sopenharmony_ci .exit = chcr_exit_tfm, 390062306a36Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE, 390162306a36Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE, 390262306a36Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 390362306a36Sopenharmony_ci .setkey = chcr_aes_ctr_setkey, 390462306a36Sopenharmony_ci .encrypt = chcr_aes_encrypt, 390562306a36Sopenharmony_ci .decrypt = chcr_aes_decrypt, 390662306a36Sopenharmony_ci } 390762306a36Sopenharmony_ci }, 390862306a36Sopenharmony_ci { 390962306a36Sopenharmony_ci .type = CRYPTO_ALG_TYPE_SKCIPHER | 391062306a36Sopenharmony_ci CRYPTO_ALG_SUB_TYPE_CTR_RFC3686, 391162306a36Sopenharmony_ci .is_registered = 0, 391262306a36Sopenharmony_ci .alg.skcipher = { 391362306a36Sopenharmony_ci .base.cra_name = "rfc3686(ctr(aes))", 391462306a36Sopenharmony_ci .base.cra_driver_name = "rfc3686-ctr-aes-chcr", 391562306a36Sopenharmony_ci .base.cra_blocksize = 1, 391662306a36Sopenharmony_ci 391762306a36Sopenharmony_ci .init = chcr_rfc3686_init, 391862306a36Sopenharmony_ci .exit = chcr_exit_tfm, 391962306a36Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE + CTR_RFC3686_NONCE_SIZE, 392062306a36Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE + CTR_RFC3686_NONCE_SIZE, 392162306a36Sopenharmony_ci .ivsize = CTR_RFC3686_IV_SIZE, 392262306a36Sopenharmony_ci .setkey = chcr_aes_rfc3686_setkey, 392362306a36Sopenharmony_ci .encrypt = chcr_aes_encrypt, 392462306a36Sopenharmony_ci .decrypt = chcr_aes_decrypt, 392562306a36Sopenharmony_ci } 392662306a36Sopenharmony_ci }, 392762306a36Sopenharmony_ci /* SHA */ 392862306a36Sopenharmony_ci { 392962306a36Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AHASH, 393062306a36Sopenharmony_ci .is_registered = 0, 393162306a36Sopenharmony_ci .alg.hash = { 393262306a36Sopenharmony_ci .halg.digestsize = SHA1_DIGEST_SIZE, 393362306a36Sopenharmony_ci .halg.base = { 393462306a36Sopenharmony_ci .cra_name = "sha1", 393562306a36Sopenharmony_ci .cra_driver_name = "sha1-chcr", 393662306a36Sopenharmony_ci .cra_blocksize = SHA1_BLOCK_SIZE, 393762306a36Sopenharmony_ci } 393862306a36Sopenharmony_ci } 393962306a36Sopenharmony_ci }, 394062306a36Sopenharmony_ci { 394162306a36Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AHASH, 394262306a36Sopenharmony_ci .is_registered = 0, 394362306a36Sopenharmony_ci .alg.hash = { 394462306a36Sopenharmony_ci .halg.digestsize = SHA256_DIGEST_SIZE, 394562306a36Sopenharmony_ci .halg.base = { 394662306a36Sopenharmony_ci .cra_name = "sha256", 394762306a36Sopenharmony_ci .cra_driver_name = "sha256-chcr", 394862306a36Sopenharmony_ci .cra_blocksize = SHA256_BLOCK_SIZE, 394962306a36Sopenharmony_ci } 395062306a36Sopenharmony_ci } 395162306a36Sopenharmony_ci }, 395262306a36Sopenharmony_ci { 395362306a36Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AHASH, 395462306a36Sopenharmony_ci .is_registered = 0, 395562306a36Sopenharmony_ci .alg.hash = { 395662306a36Sopenharmony_ci .halg.digestsize = SHA224_DIGEST_SIZE, 395762306a36Sopenharmony_ci .halg.base = { 395862306a36Sopenharmony_ci .cra_name = "sha224", 395962306a36Sopenharmony_ci .cra_driver_name = "sha224-chcr", 396062306a36Sopenharmony_ci .cra_blocksize = SHA224_BLOCK_SIZE, 396162306a36Sopenharmony_ci } 396262306a36Sopenharmony_ci } 396362306a36Sopenharmony_ci }, 396462306a36Sopenharmony_ci { 396562306a36Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AHASH, 396662306a36Sopenharmony_ci .is_registered = 0, 396762306a36Sopenharmony_ci .alg.hash = { 396862306a36Sopenharmony_ci .halg.digestsize = SHA384_DIGEST_SIZE, 396962306a36Sopenharmony_ci .halg.base = { 397062306a36Sopenharmony_ci .cra_name = "sha384", 397162306a36Sopenharmony_ci .cra_driver_name = "sha384-chcr", 397262306a36Sopenharmony_ci .cra_blocksize = SHA384_BLOCK_SIZE, 397362306a36Sopenharmony_ci } 397462306a36Sopenharmony_ci } 397562306a36Sopenharmony_ci }, 397662306a36Sopenharmony_ci { 397762306a36Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AHASH, 397862306a36Sopenharmony_ci .is_registered = 0, 397962306a36Sopenharmony_ci .alg.hash = { 398062306a36Sopenharmony_ci .halg.digestsize = SHA512_DIGEST_SIZE, 398162306a36Sopenharmony_ci .halg.base = { 398262306a36Sopenharmony_ci .cra_name = "sha512", 398362306a36Sopenharmony_ci .cra_driver_name = "sha512-chcr", 398462306a36Sopenharmony_ci .cra_blocksize = SHA512_BLOCK_SIZE, 398562306a36Sopenharmony_ci } 398662306a36Sopenharmony_ci } 398762306a36Sopenharmony_ci }, 398862306a36Sopenharmony_ci /* HMAC */ 398962306a36Sopenharmony_ci { 399062306a36Sopenharmony_ci .type = CRYPTO_ALG_TYPE_HMAC, 399162306a36Sopenharmony_ci .is_registered = 0, 399262306a36Sopenharmony_ci .alg.hash = { 399362306a36Sopenharmony_ci .halg.digestsize = SHA1_DIGEST_SIZE, 399462306a36Sopenharmony_ci .halg.base = { 399562306a36Sopenharmony_ci .cra_name = "hmac(sha1)", 399662306a36Sopenharmony_ci .cra_driver_name = "hmac-sha1-chcr", 399762306a36Sopenharmony_ci .cra_blocksize = SHA1_BLOCK_SIZE, 399862306a36Sopenharmony_ci } 399962306a36Sopenharmony_ci } 400062306a36Sopenharmony_ci }, 400162306a36Sopenharmony_ci { 400262306a36Sopenharmony_ci .type = CRYPTO_ALG_TYPE_HMAC, 400362306a36Sopenharmony_ci .is_registered = 0, 400462306a36Sopenharmony_ci .alg.hash = { 400562306a36Sopenharmony_ci .halg.digestsize = SHA224_DIGEST_SIZE, 400662306a36Sopenharmony_ci .halg.base = { 400762306a36Sopenharmony_ci .cra_name = "hmac(sha224)", 400862306a36Sopenharmony_ci .cra_driver_name = "hmac-sha224-chcr", 400962306a36Sopenharmony_ci .cra_blocksize = SHA224_BLOCK_SIZE, 401062306a36Sopenharmony_ci } 401162306a36Sopenharmony_ci } 401262306a36Sopenharmony_ci }, 401362306a36Sopenharmony_ci { 401462306a36Sopenharmony_ci .type = CRYPTO_ALG_TYPE_HMAC, 401562306a36Sopenharmony_ci .is_registered = 0, 401662306a36Sopenharmony_ci .alg.hash = { 401762306a36Sopenharmony_ci .halg.digestsize = SHA256_DIGEST_SIZE, 401862306a36Sopenharmony_ci .halg.base = { 401962306a36Sopenharmony_ci .cra_name = "hmac(sha256)", 402062306a36Sopenharmony_ci .cra_driver_name = "hmac-sha256-chcr", 402162306a36Sopenharmony_ci .cra_blocksize = SHA256_BLOCK_SIZE, 402262306a36Sopenharmony_ci } 402362306a36Sopenharmony_ci } 402462306a36Sopenharmony_ci }, 402562306a36Sopenharmony_ci { 402662306a36Sopenharmony_ci .type = CRYPTO_ALG_TYPE_HMAC, 402762306a36Sopenharmony_ci .is_registered = 0, 402862306a36Sopenharmony_ci .alg.hash = { 402962306a36Sopenharmony_ci .halg.digestsize = SHA384_DIGEST_SIZE, 403062306a36Sopenharmony_ci .halg.base = { 403162306a36Sopenharmony_ci .cra_name = "hmac(sha384)", 403262306a36Sopenharmony_ci .cra_driver_name = "hmac-sha384-chcr", 403362306a36Sopenharmony_ci .cra_blocksize = SHA384_BLOCK_SIZE, 403462306a36Sopenharmony_ci } 403562306a36Sopenharmony_ci } 403662306a36Sopenharmony_ci }, 403762306a36Sopenharmony_ci { 403862306a36Sopenharmony_ci .type = CRYPTO_ALG_TYPE_HMAC, 403962306a36Sopenharmony_ci .is_registered = 0, 404062306a36Sopenharmony_ci .alg.hash = { 404162306a36Sopenharmony_ci .halg.digestsize = SHA512_DIGEST_SIZE, 404262306a36Sopenharmony_ci .halg.base = { 404362306a36Sopenharmony_ci .cra_name = "hmac(sha512)", 404462306a36Sopenharmony_ci .cra_driver_name = "hmac-sha512-chcr", 404562306a36Sopenharmony_ci .cra_blocksize = SHA512_BLOCK_SIZE, 404662306a36Sopenharmony_ci } 404762306a36Sopenharmony_ci } 404862306a36Sopenharmony_ci }, 404962306a36Sopenharmony_ci /* Add AEAD Algorithms */ 405062306a36Sopenharmony_ci { 405162306a36Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_AEAD_GCM, 405262306a36Sopenharmony_ci .is_registered = 0, 405362306a36Sopenharmony_ci .alg.aead = { 405462306a36Sopenharmony_ci .base = { 405562306a36Sopenharmony_ci .cra_name = "gcm(aes)", 405662306a36Sopenharmony_ci .cra_driver_name = "gcm-aes-chcr", 405762306a36Sopenharmony_ci .cra_blocksize = 1, 405862306a36Sopenharmony_ci .cra_priority = CHCR_AEAD_PRIORITY, 405962306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct chcr_context) + 406062306a36Sopenharmony_ci sizeof(struct chcr_aead_ctx) + 406162306a36Sopenharmony_ci sizeof(struct chcr_gcm_ctx), 406262306a36Sopenharmony_ci }, 406362306a36Sopenharmony_ci .ivsize = GCM_AES_IV_SIZE, 406462306a36Sopenharmony_ci .maxauthsize = GHASH_DIGEST_SIZE, 406562306a36Sopenharmony_ci .setkey = chcr_gcm_setkey, 406662306a36Sopenharmony_ci .setauthsize = chcr_gcm_setauthsize, 406762306a36Sopenharmony_ci } 406862306a36Sopenharmony_ci }, 406962306a36Sopenharmony_ci { 407062306a36Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_AEAD_RFC4106, 407162306a36Sopenharmony_ci .is_registered = 0, 407262306a36Sopenharmony_ci .alg.aead = { 407362306a36Sopenharmony_ci .base = { 407462306a36Sopenharmony_ci .cra_name = "rfc4106(gcm(aes))", 407562306a36Sopenharmony_ci .cra_driver_name = "rfc4106-gcm-aes-chcr", 407662306a36Sopenharmony_ci .cra_blocksize = 1, 407762306a36Sopenharmony_ci .cra_priority = CHCR_AEAD_PRIORITY + 1, 407862306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct chcr_context) + 407962306a36Sopenharmony_ci sizeof(struct chcr_aead_ctx) + 408062306a36Sopenharmony_ci sizeof(struct chcr_gcm_ctx), 408162306a36Sopenharmony_ci 408262306a36Sopenharmony_ci }, 408362306a36Sopenharmony_ci .ivsize = GCM_RFC4106_IV_SIZE, 408462306a36Sopenharmony_ci .maxauthsize = GHASH_DIGEST_SIZE, 408562306a36Sopenharmony_ci .setkey = chcr_gcm_setkey, 408662306a36Sopenharmony_ci .setauthsize = chcr_4106_4309_setauthsize, 408762306a36Sopenharmony_ci } 408862306a36Sopenharmony_ci }, 408962306a36Sopenharmony_ci { 409062306a36Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_AEAD_CCM, 409162306a36Sopenharmony_ci .is_registered = 0, 409262306a36Sopenharmony_ci .alg.aead = { 409362306a36Sopenharmony_ci .base = { 409462306a36Sopenharmony_ci .cra_name = "ccm(aes)", 409562306a36Sopenharmony_ci .cra_driver_name = "ccm-aes-chcr", 409662306a36Sopenharmony_ci .cra_blocksize = 1, 409762306a36Sopenharmony_ci .cra_priority = CHCR_AEAD_PRIORITY, 409862306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct chcr_context) + 409962306a36Sopenharmony_ci sizeof(struct chcr_aead_ctx), 410062306a36Sopenharmony_ci 410162306a36Sopenharmony_ci }, 410262306a36Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 410362306a36Sopenharmony_ci .maxauthsize = GHASH_DIGEST_SIZE, 410462306a36Sopenharmony_ci .setkey = chcr_aead_ccm_setkey, 410562306a36Sopenharmony_ci .setauthsize = chcr_ccm_setauthsize, 410662306a36Sopenharmony_ci } 410762306a36Sopenharmony_ci }, 410862306a36Sopenharmony_ci { 410962306a36Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_AEAD_RFC4309, 411062306a36Sopenharmony_ci .is_registered = 0, 411162306a36Sopenharmony_ci .alg.aead = { 411262306a36Sopenharmony_ci .base = { 411362306a36Sopenharmony_ci .cra_name = "rfc4309(ccm(aes))", 411462306a36Sopenharmony_ci .cra_driver_name = "rfc4309-ccm-aes-chcr", 411562306a36Sopenharmony_ci .cra_blocksize = 1, 411662306a36Sopenharmony_ci .cra_priority = CHCR_AEAD_PRIORITY + 1, 411762306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct chcr_context) + 411862306a36Sopenharmony_ci sizeof(struct chcr_aead_ctx), 411962306a36Sopenharmony_ci 412062306a36Sopenharmony_ci }, 412162306a36Sopenharmony_ci .ivsize = 8, 412262306a36Sopenharmony_ci .maxauthsize = GHASH_DIGEST_SIZE, 412362306a36Sopenharmony_ci .setkey = chcr_aead_rfc4309_setkey, 412462306a36Sopenharmony_ci .setauthsize = chcr_4106_4309_setauthsize, 412562306a36Sopenharmony_ci } 412662306a36Sopenharmony_ci }, 412762306a36Sopenharmony_ci { 412862306a36Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CBC_SHA, 412962306a36Sopenharmony_ci .is_registered = 0, 413062306a36Sopenharmony_ci .alg.aead = { 413162306a36Sopenharmony_ci .base = { 413262306a36Sopenharmony_ci .cra_name = "authenc(hmac(sha1),cbc(aes))", 413362306a36Sopenharmony_ci .cra_driver_name = 413462306a36Sopenharmony_ci "authenc-hmac-sha1-cbc-aes-chcr", 413562306a36Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 413662306a36Sopenharmony_ci .cra_priority = CHCR_AEAD_PRIORITY, 413762306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct chcr_context) + 413862306a36Sopenharmony_ci sizeof(struct chcr_aead_ctx) + 413962306a36Sopenharmony_ci sizeof(struct chcr_authenc_ctx), 414062306a36Sopenharmony_ci 414162306a36Sopenharmony_ci }, 414262306a36Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 414362306a36Sopenharmony_ci .maxauthsize = SHA1_DIGEST_SIZE, 414462306a36Sopenharmony_ci .setkey = chcr_authenc_setkey, 414562306a36Sopenharmony_ci .setauthsize = chcr_authenc_setauthsize, 414662306a36Sopenharmony_ci } 414762306a36Sopenharmony_ci }, 414862306a36Sopenharmony_ci { 414962306a36Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CBC_SHA, 415062306a36Sopenharmony_ci .is_registered = 0, 415162306a36Sopenharmony_ci .alg.aead = { 415262306a36Sopenharmony_ci .base = { 415362306a36Sopenharmony_ci 415462306a36Sopenharmony_ci .cra_name = "authenc(hmac(sha256),cbc(aes))", 415562306a36Sopenharmony_ci .cra_driver_name = 415662306a36Sopenharmony_ci "authenc-hmac-sha256-cbc-aes-chcr", 415762306a36Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 415862306a36Sopenharmony_ci .cra_priority = CHCR_AEAD_PRIORITY, 415962306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct chcr_context) + 416062306a36Sopenharmony_ci sizeof(struct chcr_aead_ctx) + 416162306a36Sopenharmony_ci sizeof(struct chcr_authenc_ctx), 416262306a36Sopenharmony_ci 416362306a36Sopenharmony_ci }, 416462306a36Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 416562306a36Sopenharmony_ci .maxauthsize = SHA256_DIGEST_SIZE, 416662306a36Sopenharmony_ci .setkey = chcr_authenc_setkey, 416762306a36Sopenharmony_ci .setauthsize = chcr_authenc_setauthsize, 416862306a36Sopenharmony_ci } 416962306a36Sopenharmony_ci }, 417062306a36Sopenharmony_ci { 417162306a36Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CBC_SHA, 417262306a36Sopenharmony_ci .is_registered = 0, 417362306a36Sopenharmony_ci .alg.aead = { 417462306a36Sopenharmony_ci .base = { 417562306a36Sopenharmony_ci .cra_name = "authenc(hmac(sha224),cbc(aes))", 417662306a36Sopenharmony_ci .cra_driver_name = 417762306a36Sopenharmony_ci "authenc-hmac-sha224-cbc-aes-chcr", 417862306a36Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 417962306a36Sopenharmony_ci .cra_priority = CHCR_AEAD_PRIORITY, 418062306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct chcr_context) + 418162306a36Sopenharmony_ci sizeof(struct chcr_aead_ctx) + 418262306a36Sopenharmony_ci sizeof(struct chcr_authenc_ctx), 418362306a36Sopenharmony_ci }, 418462306a36Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 418562306a36Sopenharmony_ci .maxauthsize = SHA224_DIGEST_SIZE, 418662306a36Sopenharmony_ci .setkey = chcr_authenc_setkey, 418762306a36Sopenharmony_ci .setauthsize = chcr_authenc_setauthsize, 418862306a36Sopenharmony_ci } 418962306a36Sopenharmony_ci }, 419062306a36Sopenharmony_ci { 419162306a36Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CBC_SHA, 419262306a36Sopenharmony_ci .is_registered = 0, 419362306a36Sopenharmony_ci .alg.aead = { 419462306a36Sopenharmony_ci .base = { 419562306a36Sopenharmony_ci .cra_name = "authenc(hmac(sha384),cbc(aes))", 419662306a36Sopenharmony_ci .cra_driver_name = 419762306a36Sopenharmony_ci "authenc-hmac-sha384-cbc-aes-chcr", 419862306a36Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 419962306a36Sopenharmony_ci .cra_priority = CHCR_AEAD_PRIORITY, 420062306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct chcr_context) + 420162306a36Sopenharmony_ci sizeof(struct chcr_aead_ctx) + 420262306a36Sopenharmony_ci sizeof(struct chcr_authenc_ctx), 420362306a36Sopenharmony_ci 420462306a36Sopenharmony_ci }, 420562306a36Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 420662306a36Sopenharmony_ci .maxauthsize = SHA384_DIGEST_SIZE, 420762306a36Sopenharmony_ci .setkey = chcr_authenc_setkey, 420862306a36Sopenharmony_ci .setauthsize = chcr_authenc_setauthsize, 420962306a36Sopenharmony_ci } 421062306a36Sopenharmony_ci }, 421162306a36Sopenharmony_ci { 421262306a36Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CBC_SHA, 421362306a36Sopenharmony_ci .is_registered = 0, 421462306a36Sopenharmony_ci .alg.aead = { 421562306a36Sopenharmony_ci .base = { 421662306a36Sopenharmony_ci .cra_name = "authenc(hmac(sha512),cbc(aes))", 421762306a36Sopenharmony_ci .cra_driver_name = 421862306a36Sopenharmony_ci "authenc-hmac-sha512-cbc-aes-chcr", 421962306a36Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 422062306a36Sopenharmony_ci .cra_priority = CHCR_AEAD_PRIORITY, 422162306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct chcr_context) + 422262306a36Sopenharmony_ci sizeof(struct chcr_aead_ctx) + 422362306a36Sopenharmony_ci sizeof(struct chcr_authenc_ctx), 422462306a36Sopenharmony_ci 422562306a36Sopenharmony_ci }, 422662306a36Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 422762306a36Sopenharmony_ci .maxauthsize = SHA512_DIGEST_SIZE, 422862306a36Sopenharmony_ci .setkey = chcr_authenc_setkey, 422962306a36Sopenharmony_ci .setauthsize = chcr_authenc_setauthsize, 423062306a36Sopenharmony_ci } 423162306a36Sopenharmony_ci }, 423262306a36Sopenharmony_ci { 423362306a36Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CBC_NULL, 423462306a36Sopenharmony_ci .is_registered = 0, 423562306a36Sopenharmony_ci .alg.aead = { 423662306a36Sopenharmony_ci .base = { 423762306a36Sopenharmony_ci .cra_name = "authenc(digest_null,cbc(aes))", 423862306a36Sopenharmony_ci .cra_driver_name = 423962306a36Sopenharmony_ci "authenc-digest_null-cbc-aes-chcr", 424062306a36Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 424162306a36Sopenharmony_ci .cra_priority = CHCR_AEAD_PRIORITY, 424262306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct chcr_context) + 424362306a36Sopenharmony_ci sizeof(struct chcr_aead_ctx) + 424462306a36Sopenharmony_ci sizeof(struct chcr_authenc_ctx), 424562306a36Sopenharmony_ci 424662306a36Sopenharmony_ci }, 424762306a36Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 424862306a36Sopenharmony_ci .maxauthsize = 0, 424962306a36Sopenharmony_ci .setkey = chcr_aead_digest_null_setkey, 425062306a36Sopenharmony_ci .setauthsize = chcr_authenc_null_setauthsize, 425162306a36Sopenharmony_ci } 425262306a36Sopenharmony_ci }, 425362306a36Sopenharmony_ci { 425462306a36Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CTR_SHA, 425562306a36Sopenharmony_ci .is_registered = 0, 425662306a36Sopenharmony_ci .alg.aead = { 425762306a36Sopenharmony_ci .base = { 425862306a36Sopenharmony_ci .cra_name = "authenc(hmac(sha1),rfc3686(ctr(aes)))", 425962306a36Sopenharmony_ci .cra_driver_name = 426062306a36Sopenharmony_ci "authenc-hmac-sha1-rfc3686-ctr-aes-chcr", 426162306a36Sopenharmony_ci .cra_blocksize = 1, 426262306a36Sopenharmony_ci .cra_priority = CHCR_AEAD_PRIORITY, 426362306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct chcr_context) + 426462306a36Sopenharmony_ci sizeof(struct chcr_aead_ctx) + 426562306a36Sopenharmony_ci sizeof(struct chcr_authenc_ctx), 426662306a36Sopenharmony_ci 426762306a36Sopenharmony_ci }, 426862306a36Sopenharmony_ci .ivsize = CTR_RFC3686_IV_SIZE, 426962306a36Sopenharmony_ci .maxauthsize = SHA1_DIGEST_SIZE, 427062306a36Sopenharmony_ci .setkey = chcr_authenc_setkey, 427162306a36Sopenharmony_ci .setauthsize = chcr_authenc_setauthsize, 427262306a36Sopenharmony_ci } 427362306a36Sopenharmony_ci }, 427462306a36Sopenharmony_ci { 427562306a36Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CTR_SHA, 427662306a36Sopenharmony_ci .is_registered = 0, 427762306a36Sopenharmony_ci .alg.aead = { 427862306a36Sopenharmony_ci .base = { 427962306a36Sopenharmony_ci 428062306a36Sopenharmony_ci .cra_name = "authenc(hmac(sha256),rfc3686(ctr(aes)))", 428162306a36Sopenharmony_ci .cra_driver_name = 428262306a36Sopenharmony_ci "authenc-hmac-sha256-rfc3686-ctr-aes-chcr", 428362306a36Sopenharmony_ci .cra_blocksize = 1, 428462306a36Sopenharmony_ci .cra_priority = CHCR_AEAD_PRIORITY, 428562306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct chcr_context) + 428662306a36Sopenharmony_ci sizeof(struct chcr_aead_ctx) + 428762306a36Sopenharmony_ci sizeof(struct chcr_authenc_ctx), 428862306a36Sopenharmony_ci 428962306a36Sopenharmony_ci }, 429062306a36Sopenharmony_ci .ivsize = CTR_RFC3686_IV_SIZE, 429162306a36Sopenharmony_ci .maxauthsize = SHA256_DIGEST_SIZE, 429262306a36Sopenharmony_ci .setkey = chcr_authenc_setkey, 429362306a36Sopenharmony_ci .setauthsize = chcr_authenc_setauthsize, 429462306a36Sopenharmony_ci } 429562306a36Sopenharmony_ci }, 429662306a36Sopenharmony_ci { 429762306a36Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CTR_SHA, 429862306a36Sopenharmony_ci .is_registered = 0, 429962306a36Sopenharmony_ci .alg.aead = { 430062306a36Sopenharmony_ci .base = { 430162306a36Sopenharmony_ci .cra_name = "authenc(hmac(sha224),rfc3686(ctr(aes)))", 430262306a36Sopenharmony_ci .cra_driver_name = 430362306a36Sopenharmony_ci "authenc-hmac-sha224-rfc3686-ctr-aes-chcr", 430462306a36Sopenharmony_ci .cra_blocksize = 1, 430562306a36Sopenharmony_ci .cra_priority = CHCR_AEAD_PRIORITY, 430662306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct chcr_context) + 430762306a36Sopenharmony_ci sizeof(struct chcr_aead_ctx) + 430862306a36Sopenharmony_ci sizeof(struct chcr_authenc_ctx), 430962306a36Sopenharmony_ci }, 431062306a36Sopenharmony_ci .ivsize = CTR_RFC3686_IV_SIZE, 431162306a36Sopenharmony_ci .maxauthsize = SHA224_DIGEST_SIZE, 431262306a36Sopenharmony_ci .setkey = chcr_authenc_setkey, 431362306a36Sopenharmony_ci .setauthsize = chcr_authenc_setauthsize, 431462306a36Sopenharmony_ci } 431562306a36Sopenharmony_ci }, 431662306a36Sopenharmony_ci { 431762306a36Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CTR_SHA, 431862306a36Sopenharmony_ci .is_registered = 0, 431962306a36Sopenharmony_ci .alg.aead = { 432062306a36Sopenharmony_ci .base = { 432162306a36Sopenharmony_ci .cra_name = "authenc(hmac(sha384),rfc3686(ctr(aes)))", 432262306a36Sopenharmony_ci .cra_driver_name = 432362306a36Sopenharmony_ci "authenc-hmac-sha384-rfc3686-ctr-aes-chcr", 432462306a36Sopenharmony_ci .cra_blocksize = 1, 432562306a36Sopenharmony_ci .cra_priority = CHCR_AEAD_PRIORITY, 432662306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct chcr_context) + 432762306a36Sopenharmony_ci sizeof(struct chcr_aead_ctx) + 432862306a36Sopenharmony_ci sizeof(struct chcr_authenc_ctx), 432962306a36Sopenharmony_ci 433062306a36Sopenharmony_ci }, 433162306a36Sopenharmony_ci .ivsize = CTR_RFC3686_IV_SIZE, 433262306a36Sopenharmony_ci .maxauthsize = SHA384_DIGEST_SIZE, 433362306a36Sopenharmony_ci .setkey = chcr_authenc_setkey, 433462306a36Sopenharmony_ci .setauthsize = chcr_authenc_setauthsize, 433562306a36Sopenharmony_ci } 433662306a36Sopenharmony_ci }, 433762306a36Sopenharmony_ci { 433862306a36Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CTR_SHA, 433962306a36Sopenharmony_ci .is_registered = 0, 434062306a36Sopenharmony_ci .alg.aead = { 434162306a36Sopenharmony_ci .base = { 434262306a36Sopenharmony_ci .cra_name = "authenc(hmac(sha512),rfc3686(ctr(aes)))", 434362306a36Sopenharmony_ci .cra_driver_name = 434462306a36Sopenharmony_ci "authenc-hmac-sha512-rfc3686-ctr-aes-chcr", 434562306a36Sopenharmony_ci .cra_blocksize = 1, 434662306a36Sopenharmony_ci .cra_priority = CHCR_AEAD_PRIORITY, 434762306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct chcr_context) + 434862306a36Sopenharmony_ci sizeof(struct chcr_aead_ctx) + 434962306a36Sopenharmony_ci sizeof(struct chcr_authenc_ctx), 435062306a36Sopenharmony_ci 435162306a36Sopenharmony_ci }, 435262306a36Sopenharmony_ci .ivsize = CTR_RFC3686_IV_SIZE, 435362306a36Sopenharmony_ci .maxauthsize = SHA512_DIGEST_SIZE, 435462306a36Sopenharmony_ci .setkey = chcr_authenc_setkey, 435562306a36Sopenharmony_ci .setauthsize = chcr_authenc_setauthsize, 435662306a36Sopenharmony_ci } 435762306a36Sopenharmony_ci }, 435862306a36Sopenharmony_ci { 435962306a36Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_CTR_NULL, 436062306a36Sopenharmony_ci .is_registered = 0, 436162306a36Sopenharmony_ci .alg.aead = { 436262306a36Sopenharmony_ci .base = { 436362306a36Sopenharmony_ci .cra_name = "authenc(digest_null,rfc3686(ctr(aes)))", 436462306a36Sopenharmony_ci .cra_driver_name = 436562306a36Sopenharmony_ci "authenc-digest_null-rfc3686-ctr-aes-chcr", 436662306a36Sopenharmony_ci .cra_blocksize = 1, 436762306a36Sopenharmony_ci .cra_priority = CHCR_AEAD_PRIORITY, 436862306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct chcr_context) + 436962306a36Sopenharmony_ci sizeof(struct chcr_aead_ctx) + 437062306a36Sopenharmony_ci sizeof(struct chcr_authenc_ctx), 437162306a36Sopenharmony_ci 437262306a36Sopenharmony_ci }, 437362306a36Sopenharmony_ci .ivsize = CTR_RFC3686_IV_SIZE, 437462306a36Sopenharmony_ci .maxauthsize = 0, 437562306a36Sopenharmony_ci .setkey = chcr_aead_digest_null_setkey, 437662306a36Sopenharmony_ci .setauthsize = chcr_authenc_null_setauthsize, 437762306a36Sopenharmony_ci } 437862306a36Sopenharmony_ci }, 437962306a36Sopenharmony_ci}; 438062306a36Sopenharmony_ci 438162306a36Sopenharmony_ci/* 438262306a36Sopenharmony_ci * chcr_unregister_alg - Deregister crypto algorithms with 438362306a36Sopenharmony_ci * kernel framework. 438462306a36Sopenharmony_ci */ 438562306a36Sopenharmony_cistatic int chcr_unregister_alg(void) 438662306a36Sopenharmony_ci{ 438762306a36Sopenharmony_ci int i; 438862306a36Sopenharmony_ci 438962306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(driver_algs); i++) { 439062306a36Sopenharmony_ci switch (driver_algs[i].type & CRYPTO_ALG_TYPE_MASK) { 439162306a36Sopenharmony_ci case CRYPTO_ALG_TYPE_SKCIPHER: 439262306a36Sopenharmony_ci if (driver_algs[i].is_registered && refcount_read( 439362306a36Sopenharmony_ci &driver_algs[i].alg.skcipher.base.cra_refcnt) 439462306a36Sopenharmony_ci == 1) { 439562306a36Sopenharmony_ci crypto_unregister_skcipher( 439662306a36Sopenharmony_ci &driver_algs[i].alg.skcipher); 439762306a36Sopenharmony_ci driver_algs[i].is_registered = 0; 439862306a36Sopenharmony_ci } 439962306a36Sopenharmony_ci break; 440062306a36Sopenharmony_ci case CRYPTO_ALG_TYPE_AEAD: 440162306a36Sopenharmony_ci if (driver_algs[i].is_registered && refcount_read( 440262306a36Sopenharmony_ci &driver_algs[i].alg.aead.base.cra_refcnt) == 1) { 440362306a36Sopenharmony_ci crypto_unregister_aead( 440462306a36Sopenharmony_ci &driver_algs[i].alg.aead); 440562306a36Sopenharmony_ci driver_algs[i].is_registered = 0; 440662306a36Sopenharmony_ci } 440762306a36Sopenharmony_ci break; 440862306a36Sopenharmony_ci case CRYPTO_ALG_TYPE_AHASH: 440962306a36Sopenharmony_ci if (driver_algs[i].is_registered && refcount_read( 441062306a36Sopenharmony_ci &driver_algs[i].alg.hash.halg.base.cra_refcnt) 441162306a36Sopenharmony_ci == 1) { 441262306a36Sopenharmony_ci crypto_unregister_ahash( 441362306a36Sopenharmony_ci &driver_algs[i].alg.hash); 441462306a36Sopenharmony_ci driver_algs[i].is_registered = 0; 441562306a36Sopenharmony_ci } 441662306a36Sopenharmony_ci break; 441762306a36Sopenharmony_ci } 441862306a36Sopenharmony_ci } 441962306a36Sopenharmony_ci return 0; 442062306a36Sopenharmony_ci} 442162306a36Sopenharmony_ci 442262306a36Sopenharmony_ci#define SZ_AHASH_CTX sizeof(struct chcr_context) 442362306a36Sopenharmony_ci#define SZ_AHASH_H_CTX (sizeof(struct chcr_context) + sizeof(struct hmac_ctx)) 442462306a36Sopenharmony_ci#define SZ_AHASH_REQ_CTX sizeof(struct chcr_ahash_req_ctx) 442562306a36Sopenharmony_ci 442662306a36Sopenharmony_ci/* 442762306a36Sopenharmony_ci * chcr_register_alg - Register crypto algorithms with kernel framework. 442862306a36Sopenharmony_ci */ 442962306a36Sopenharmony_cistatic int chcr_register_alg(void) 443062306a36Sopenharmony_ci{ 443162306a36Sopenharmony_ci struct crypto_alg ai; 443262306a36Sopenharmony_ci struct ahash_alg *a_hash; 443362306a36Sopenharmony_ci int err = 0, i; 443462306a36Sopenharmony_ci char *name = NULL; 443562306a36Sopenharmony_ci 443662306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(driver_algs); i++) { 443762306a36Sopenharmony_ci if (driver_algs[i].is_registered) 443862306a36Sopenharmony_ci continue; 443962306a36Sopenharmony_ci switch (driver_algs[i].type & CRYPTO_ALG_TYPE_MASK) { 444062306a36Sopenharmony_ci case CRYPTO_ALG_TYPE_SKCIPHER: 444162306a36Sopenharmony_ci driver_algs[i].alg.skcipher.base.cra_priority = 444262306a36Sopenharmony_ci CHCR_CRA_PRIORITY; 444362306a36Sopenharmony_ci driver_algs[i].alg.skcipher.base.cra_module = THIS_MODULE; 444462306a36Sopenharmony_ci driver_algs[i].alg.skcipher.base.cra_flags = 444562306a36Sopenharmony_ci CRYPTO_ALG_TYPE_SKCIPHER | CRYPTO_ALG_ASYNC | 444662306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 444762306a36Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK; 444862306a36Sopenharmony_ci driver_algs[i].alg.skcipher.base.cra_ctxsize = 444962306a36Sopenharmony_ci sizeof(struct chcr_context) + 445062306a36Sopenharmony_ci sizeof(struct ablk_ctx); 445162306a36Sopenharmony_ci driver_algs[i].alg.skcipher.base.cra_alignmask = 0; 445262306a36Sopenharmony_ci 445362306a36Sopenharmony_ci err = crypto_register_skcipher(&driver_algs[i].alg.skcipher); 445462306a36Sopenharmony_ci name = driver_algs[i].alg.skcipher.base.cra_driver_name; 445562306a36Sopenharmony_ci break; 445662306a36Sopenharmony_ci case CRYPTO_ALG_TYPE_AEAD: 445762306a36Sopenharmony_ci driver_algs[i].alg.aead.base.cra_flags = 445862306a36Sopenharmony_ci CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK | 445962306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY; 446062306a36Sopenharmony_ci driver_algs[i].alg.aead.encrypt = chcr_aead_encrypt; 446162306a36Sopenharmony_ci driver_algs[i].alg.aead.decrypt = chcr_aead_decrypt; 446262306a36Sopenharmony_ci driver_algs[i].alg.aead.init = chcr_aead_cra_init; 446362306a36Sopenharmony_ci driver_algs[i].alg.aead.exit = chcr_aead_cra_exit; 446462306a36Sopenharmony_ci driver_algs[i].alg.aead.base.cra_module = THIS_MODULE; 446562306a36Sopenharmony_ci err = crypto_register_aead(&driver_algs[i].alg.aead); 446662306a36Sopenharmony_ci name = driver_algs[i].alg.aead.base.cra_driver_name; 446762306a36Sopenharmony_ci break; 446862306a36Sopenharmony_ci case CRYPTO_ALG_TYPE_AHASH: 446962306a36Sopenharmony_ci a_hash = &driver_algs[i].alg.hash; 447062306a36Sopenharmony_ci a_hash->update = chcr_ahash_update; 447162306a36Sopenharmony_ci a_hash->final = chcr_ahash_final; 447262306a36Sopenharmony_ci a_hash->finup = chcr_ahash_finup; 447362306a36Sopenharmony_ci a_hash->digest = chcr_ahash_digest; 447462306a36Sopenharmony_ci a_hash->export = chcr_ahash_export; 447562306a36Sopenharmony_ci a_hash->import = chcr_ahash_import; 447662306a36Sopenharmony_ci a_hash->halg.statesize = SZ_AHASH_REQ_CTX; 447762306a36Sopenharmony_ci a_hash->halg.base.cra_priority = CHCR_CRA_PRIORITY; 447862306a36Sopenharmony_ci a_hash->halg.base.cra_module = THIS_MODULE; 447962306a36Sopenharmony_ci a_hash->halg.base.cra_flags = 448062306a36Sopenharmony_ci CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY; 448162306a36Sopenharmony_ci a_hash->halg.base.cra_alignmask = 0; 448262306a36Sopenharmony_ci a_hash->halg.base.cra_exit = NULL; 448362306a36Sopenharmony_ci 448462306a36Sopenharmony_ci if (driver_algs[i].type == CRYPTO_ALG_TYPE_HMAC) { 448562306a36Sopenharmony_ci a_hash->halg.base.cra_init = chcr_hmac_cra_init; 448662306a36Sopenharmony_ci a_hash->halg.base.cra_exit = chcr_hmac_cra_exit; 448762306a36Sopenharmony_ci a_hash->init = chcr_hmac_init; 448862306a36Sopenharmony_ci a_hash->setkey = chcr_ahash_setkey; 448962306a36Sopenharmony_ci a_hash->halg.base.cra_ctxsize = SZ_AHASH_H_CTX; 449062306a36Sopenharmony_ci } else { 449162306a36Sopenharmony_ci a_hash->init = chcr_sha_init; 449262306a36Sopenharmony_ci a_hash->halg.base.cra_ctxsize = SZ_AHASH_CTX; 449362306a36Sopenharmony_ci a_hash->halg.base.cra_init = chcr_sha_cra_init; 449462306a36Sopenharmony_ci } 449562306a36Sopenharmony_ci err = crypto_register_ahash(&driver_algs[i].alg.hash); 449662306a36Sopenharmony_ci ai = driver_algs[i].alg.hash.halg.base; 449762306a36Sopenharmony_ci name = ai.cra_driver_name; 449862306a36Sopenharmony_ci break; 449962306a36Sopenharmony_ci } 450062306a36Sopenharmony_ci if (err) { 450162306a36Sopenharmony_ci pr_err("%s : Algorithm registration failed\n", name); 450262306a36Sopenharmony_ci goto register_err; 450362306a36Sopenharmony_ci } else { 450462306a36Sopenharmony_ci driver_algs[i].is_registered = 1; 450562306a36Sopenharmony_ci } 450662306a36Sopenharmony_ci } 450762306a36Sopenharmony_ci return 0; 450862306a36Sopenharmony_ci 450962306a36Sopenharmony_ciregister_err: 451062306a36Sopenharmony_ci chcr_unregister_alg(); 451162306a36Sopenharmony_ci return err; 451262306a36Sopenharmony_ci} 451362306a36Sopenharmony_ci 451462306a36Sopenharmony_ci/* 451562306a36Sopenharmony_ci * start_crypto - Register the crypto algorithms. 451662306a36Sopenharmony_ci * This should called once when the first device comesup. After this 451762306a36Sopenharmony_ci * kernel will start calling driver APIs for crypto operations. 451862306a36Sopenharmony_ci */ 451962306a36Sopenharmony_ciint start_crypto(void) 452062306a36Sopenharmony_ci{ 452162306a36Sopenharmony_ci return chcr_register_alg(); 452262306a36Sopenharmony_ci} 452362306a36Sopenharmony_ci 452462306a36Sopenharmony_ci/* 452562306a36Sopenharmony_ci * stop_crypto - Deregister all the crypto algorithms with kernel. 452662306a36Sopenharmony_ci * This should be called once when the last device goes down. After this 452762306a36Sopenharmony_ci * kernel will not call the driver API for crypto operations. 452862306a36Sopenharmony_ci */ 452962306a36Sopenharmony_ciint stop_crypto(void) 453062306a36Sopenharmony_ci{ 453162306a36Sopenharmony_ci chcr_unregister_alg(); 453262306a36Sopenharmony_ci return 0; 453362306a36Sopenharmony_ci} 4534