162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <crypto/internal/hash.h> 762306a36Sopenharmony_ci#include <linux/err.h> 862306a36Sopenharmony_ci#include <linux/interrupt.h> 962306a36Sopenharmony_ci#include <linux/types.h> 1062306a36Sopenharmony_ci#include <crypto/scatterwalk.h> 1162306a36Sopenharmony_ci#include <crypto/sha1.h> 1262306a36Sopenharmony_ci#include <crypto/sha2.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include "cipher.h" 1562306a36Sopenharmony_ci#include "common.h" 1662306a36Sopenharmony_ci#include "core.h" 1762306a36Sopenharmony_ci#include "regs-v5.h" 1862306a36Sopenharmony_ci#include "sha.h" 1962306a36Sopenharmony_ci#include "aead.h" 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_cistatic inline u32 qce_read(struct qce_device *qce, u32 offset) 2262306a36Sopenharmony_ci{ 2362306a36Sopenharmony_ci return readl(qce->base + offset); 2462306a36Sopenharmony_ci} 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_cistatic inline void qce_write(struct qce_device *qce, u32 offset, u32 val) 2762306a36Sopenharmony_ci{ 2862306a36Sopenharmony_ci writel(val, qce->base + offset); 2962306a36Sopenharmony_ci} 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_cistatic inline void qce_write_array(struct qce_device *qce, u32 offset, 3262306a36Sopenharmony_ci const u32 *val, unsigned int len) 3362306a36Sopenharmony_ci{ 3462306a36Sopenharmony_ci int i; 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci for (i = 0; i < len; i++) 3762306a36Sopenharmony_ci qce_write(qce, offset + i * sizeof(u32), val[i]); 3862306a36Sopenharmony_ci} 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_cistatic inline void 4162306a36Sopenharmony_ciqce_clear_array(struct qce_device *qce, u32 offset, unsigned int len) 4262306a36Sopenharmony_ci{ 4362306a36Sopenharmony_ci int i; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci for (i = 0; i < len; i++) 4662306a36Sopenharmony_ci qce_write(qce, offset + i * sizeof(u32), 0); 4762306a36Sopenharmony_ci} 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_cistatic u32 qce_config_reg(struct qce_device *qce, int little) 5062306a36Sopenharmony_ci{ 5162306a36Sopenharmony_ci u32 beats = (qce->burst_size >> 3) - 1; 5262306a36Sopenharmony_ci u32 pipe_pair = qce->pipe_pair_id; 5362306a36Sopenharmony_ci u32 config; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci config = (beats << REQ_SIZE_SHIFT) & REQ_SIZE_MASK; 5662306a36Sopenharmony_ci config |= BIT(MASK_DOUT_INTR_SHIFT) | BIT(MASK_DIN_INTR_SHIFT) | 5762306a36Sopenharmony_ci BIT(MASK_OP_DONE_INTR_SHIFT) | BIT(MASK_ERR_INTR_SHIFT); 5862306a36Sopenharmony_ci config |= (pipe_pair << PIPE_SET_SELECT_SHIFT) & PIPE_SET_SELECT_MASK; 5962306a36Sopenharmony_ci config &= ~HIGH_SPD_EN_N_SHIFT; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci if (little) 6262306a36Sopenharmony_ci config |= BIT(LITTLE_ENDIAN_MODE_SHIFT); 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci return config; 6562306a36Sopenharmony_ci} 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_civoid qce_cpu_to_be32p_array(__be32 *dst, const u8 *src, unsigned int len) 6862306a36Sopenharmony_ci{ 6962306a36Sopenharmony_ci __be32 *d = dst; 7062306a36Sopenharmony_ci const u8 *s = src; 7162306a36Sopenharmony_ci unsigned int n; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci n = len / sizeof(u32); 7462306a36Sopenharmony_ci for (; n > 0; n--) { 7562306a36Sopenharmony_ci *d = cpu_to_be32p((const __u32 *) s); 7662306a36Sopenharmony_ci s += sizeof(__u32); 7762306a36Sopenharmony_ci d++; 7862306a36Sopenharmony_ci } 7962306a36Sopenharmony_ci} 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_cistatic void qce_setup_config(struct qce_device *qce) 8262306a36Sopenharmony_ci{ 8362306a36Sopenharmony_ci u32 config; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci /* get big endianness */ 8662306a36Sopenharmony_ci config = qce_config_reg(qce, 0); 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci /* clear status */ 8962306a36Sopenharmony_ci qce_write(qce, REG_STATUS, 0); 9062306a36Sopenharmony_ci qce_write(qce, REG_CONFIG, config); 9162306a36Sopenharmony_ci} 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_cistatic inline void qce_crypto_go(struct qce_device *qce, bool result_dump) 9462306a36Sopenharmony_ci{ 9562306a36Sopenharmony_ci if (result_dump) 9662306a36Sopenharmony_ci qce_write(qce, REG_GOPROC, BIT(GO_SHIFT) | BIT(RESULTS_DUMP_SHIFT)); 9762306a36Sopenharmony_ci else 9862306a36Sopenharmony_ci qce_write(qce, REG_GOPROC, BIT(GO_SHIFT)); 9962306a36Sopenharmony_ci} 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci#if defined(CONFIG_CRYPTO_DEV_QCE_SHA) || defined(CONFIG_CRYPTO_DEV_QCE_AEAD) 10262306a36Sopenharmony_cistatic u32 qce_auth_cfg(unsigned long flags, u32 key_size, u32 auth_size) 10362306a36Sopenharmony_ci{ 10462306a36Sopenharmony_ci u32 cfg = 0; 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci if (IS_CCM(flags) || IS_CMAC(flags)) 10762306a36Sopenharmony_ci cfg |= AUTH_ALG_AES << AUTH_ALG_SHIFT; 10862306a36Sopenharmony_ci else 10962306a36Sopenharmony_ci cfg |= AUTH_ALG_SHA << AUTH_ALG_SHIFT; 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci if (IS_CCM(flags) || IS_CMAC(flags)) { 11262306a36Sopenharmony_ci if (key_size == AES_KEYSIZE_128) 11362306a36Sopenharmony_ci cfg |= AUTH_KEY_SZ_AES128 << AUTH_KEY_SIZE_SHIFT; 11462306a36Sopenharmony_ci else if (key_size == AES_KEYSIZE_256) 11562306a36Sopenharmony_ci cfg |= AUTH_KEY_SZ_AES256 << AUTH_KEY_SIZE_SHIFT; 11662306a36Sopenharmony_ci } 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci if (IS_SHA1(flags) || IS_SHA1_HMAC(flags)) 11962306a36Sopenharmony_ci cfg |= AUTH_SIZE_SHA1 << AUTH_SIZE_SHIFT; 12062306a36Sopenharmony_ci else if (IS_SHA256(flags) || IS_SHA256_HMAC(flags)) 12162306a36Sopenharmony_ci cfg |= AUTH_SIZE_SHA256 << AUTH_SIZE_SHIFT; 12262306a36Sopenharmony_ci else if (IS_CMAC(flags)) 12362306a36Sopenharmony_ci cfg |= AUTH_SIZE_ENUM_16_BYTES << AUTH_SIZE_SHIFT; 12462306a36Sopenharmony_ci else if (IS_CCM(flags)) 12562306a36Sopenharmony_ci cfg |= (auth_size - 1) << AUTH_SIZE_SHIFT; 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci if (IS_SHA1(flags) || IS_SHA256(flags)) 12862306a36Sopenharmony_ci cfg |= AUTH_MODE_HASH << AUTH_MODE_SHIFT; 12962306a36Sopenharmony_ci else if (IS_SHA1_HMAC(flags) || IS_SHA256_HMAC(flags)) 13062306a36Sopenharmony_ci cfg |= AUTH_MODE_HMAC << AUTH_MODE_SHIFT; 13162306a36Sopenharmony_ci else if (IS_CCM(flags)) 13262306a36Sopenharmony_ci cfg |= AUTH_MODE_CCM << AUTH_MODE_SHIFT; 13362306a36Sopenharmony_ci else if (IS_CMAC(flags)) 13462306a36Sopenharmony_ci cfg |= AUTH_MODE_CMAC << AUTH_MODE_SHIFT; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci if (IS_SHA(flags) || IS_SHA_HMAC(flags)) 13762306a36Sopenharmony_ci cfg |= AUTH_POS_BEFORE << AUTH_POS_SHIFT; 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci if (IS_CCM(flags)) 14062306a36Sopenharmony_ci cfg |= QCE_MAX_NONCE_WORDS << AUTH_NONCE_NUM_WORDS_SHIFT; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci return cfg; 14362306a36Sopenharmony_ci} 14462306a36Sopenharmony_ci#endif 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci#ifdef CONFIG_CRYPTO_DEV_QCE_SHA 14762306a36Sopenharmony_cistatic int qce_setup_regs_ahash(struct crypto_async_request *async_req) 14862306a36Sopenharmony_ci{ 14962306a36Sopenharmony_ci struct ahash_request *req = ahash_request_cast(async_req); 15062306a36Sopenharmony_ci struct crypto_ahash *ahash = __crypto_ahash_cast(async_req->tfm); 15162306a36Sopenharmony_ci struct qce_sha_reqctx *rctx = ahash_request_ctx_dma(req); 15262306a36Sopenharmony_ci struct qce_alg_template *tmpl = to_ahash_tmpl(async_req->tfm); 15362306a36Sopenharmony_ci struct qce_device *qce = tmpl->qce; 15462306a36Sopenharmony_ci unsigned int digestsize = crypto_ahash_digestsize(ahash); 15562306a36Sopenharmony_ci unsigned int blocksize = crypto_tfm_alg_blocksize(async_req->tfm); 15662306a36Sopenharmony_ci __be32 auth[SHA256_DIGEST_SIZE / sizeof(__be32)] = {0}; 15762306a36Sopenharmony_ci __be32 mackey[QCE_SHA_HMAC_KEY_SIZE / sizeof(__be32)] = {0}; 15862306a36Sopenharmony_ci u32 auth_cfg = 0, config; 15962306a36Sopenharmony_ci unsigned int iv_words; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci /* if not the last, the size has to be on the block boundary */ 16262306a36Sopenharmony_ci if (!rctx->last_blk && req->nbytes % blocksize) 16362306a36Sopenharmony_ci return -EINVAL; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci qce_setup_config(qce); 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci if (IS_CMAC(rctx->flags)) { 16862306a36Sopenharmony_ci qce_write(qce, REG_AUTH_SEG_CFG, 0); 16962306a36Sopenharmony_ci qce_write(qce, REG_ENCR_SEG_CFG, 0); 17062306a36Sopenharmony_ci qce_write(qce, REG_ENCR_SEG_SIZE, 0); 17162306a36Sopenharmony_ci qce_clear_array(qce, REG_AUTH_IV0, 16); 17262306a36Sopenharmony_ci qce_clear_array(qce, REG_AUTH_KEY0, 16); 17362306a36Sopenharmony_ci qce_clear_array(qce, REG_AUTH_BYTECNT0, 4); 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci auth_cfg = qce_auth_cfg(rctx->flags, rctx->authklen, digestsize); 17662306a36Sopenharmony_ci } 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci if (IS_SHA_HMAC(rctx->flags) || IS_CMAC(rctx->flags)) { 17962306a36Sopenharmony_ci u32 authkey_words = rctx->authklen / sizeof(u32); 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci qce_cpu_to_be32p_array(mackey, rctx->authkey, rctx->authklen); 18262306a36Sopenharmony_ci qce_write_array(qce, REG_AUTH_KEY0, (u32 *)mackey, 18362306a36Sopenharmony_ci authkey_words); 18462306a36Sopenharmony_ci } 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci if (IS_CMAC(rctx->flags)) 18762306a36Sopenharmony_ci goto go_proc; 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci if (rctx->first_blk) 19062306a36Sopenharmony_ci memcpy(auth, rctx->digest, digestsize); 19162306a36Sopenharmony_ci else 19262306a36Sopenharmony_ci qce_cpu_to_be32p_array(auth, rctx->digest, digestsize); 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci iv_words = (IS_SHA1(rctx->flags) || IS_SHA1_HMAC(rctx->flags)) ? 5 : 8; 19562306a36Sopenharmony_ci qce_write_array(qce, REG_AUTH_IV0, (u32 *)auth, iv_words); 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci if (rctx->first_blk) 19862306a36Sopenharmony_ci qce_clear_array(qce, REG_AUTH_BYTECNT0, 4); 19962306a36Sopenharmony_ci else 20062306a36Sopenharmony_ci qce_write_array(qce, REG_AUTH_BYTECNT0, 20162306a36Sopenharmony_ci (u32 *)rctx->byte_count, 2); 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci auth_cfg = qce_auth_cfg(rctx->flags, 0, digestsize); 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci if (rctx->last_blk) 20662306a36Sopenharmony_ci auth_cfg |= BIT(AUTH_LAST_SHIFT); 20762306a36Sopenharmony_ci else 20862306a36Sopenharmony_ci auth_cfg &= ~BIT(AUTH_LAST_SHIFT); 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci if (rctx->first_blk) 21162306a36Sopenharmony_ci auth_cfg |= BIT(AUTH_FIRST_SHIFT); 21262306a36Sopenharmony_ci else 21362306a36Sopenharmony_ci auth_cfg &= ~BIT(AUTH_FIRST_SHIFT); 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_cigo_proc: 21662306a36Sopenharmony_ci qce_write(qce, REG_AUTH_SEG_CFG, auth_cfg); 21762306a36Sopenharmony_ci qce_write(qce, REG_AUTH_SEG_SIZE, req->nbytes); 21862306a36Sopenharmony_ci qce_write(qce, REG_AUTH_SEG_START, 0); 21962306a36Sopenharmony_ci qce_write(qce, REG_ENCR_SEG_CFG, 0); 22062306a36Sopenharmony_ci qce_write(qce, REG_SEG_SIZE, req->nbytes); 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci /* get little endianness */ 22362306a36Sopenharmony_ci config = qce_config_reg(qce, 1); 22462306a36Sopenharmony_ci qce_write(qce, REG_CONFIG, config); 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci qce_crypto_go(qce, true); 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci return 0; 22962306a36Sopenharmony_ci} 23062306a36Sopenharmony_ci#endif 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci#if defined(CONFIG_CRYPTO_DEV_QCE_SKCIPHER) || defined(CONFIG_CRYPTO_DEV_QCE_AEAD) 23362306a36Sopenharmony_cistatic u32 qce_encr_cfg(unsigned long flags, u32 aes_key_size) 23462306a36Sopenharmony_ci{ 23562306a36Sopenharmony_ci u32 cfg = 0; 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci if (IS_AES(flags)) { 23862306a36Sopenharmony_ci if (aes_key_size == AES_KEYSIZE_128) 23962306a36Sopenharmony_ci cfg |= ENCR_KEY_SZ_AES128 << ENCR_KEY_SZ_SHIFT; 24062306a36Sopenharmony_ci else if (aes_key_size == AES_KEYSIZE_256) 24162306a36Sopenharmony_ci cfg |= ENCR_KEY_SZ_AES256 << ENCR_KEY_SZ_SHIFT; 24262306a36Sopenharmony_ci } 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci if (IS_AES(flags)) 24562306a36Sopenharmony_ci cfg |= ENCR_ALG_AES << ENCR_ALG_SHIFT; 24662306a36Sopenharmony_ci else if (IS_DES(flags) || IS_3DES(flags)) 24762306a36Sopenharmony_ci cfg |= ENCR_ALG_DES << ENCR_ALG_SHIFT; 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci if (IS_DES(flags)) 25062306a36Sopenharmony_ci cfg |= ENCR_KEY_SZ_DES << ENCR_KEY_SZ_SHIFT; 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci if (IS_3DES(flags)) 25362306a36Sopenharmony_ci cfg |= ENCR_KEY_SZ_3DES << ENCR_KEY_SZ_SHIFT; 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci switch (flags & QCE_MODE_MASK) { 25662306a36Sopenharmony_ci case QCE_MODE_ECB: 25762306a36Sopenharmony_ci cfg |= ENCR_MODE_ECB << ENCR_MODE_SHIFT; 25862306a36Sopenharmony_ci break; 25962306a36Sopenharmony_ci case QCE_MODE_CBC: 26062306a36Sopenharmony_ci cfg |= ENCR_MODE_CBC << ENCR_MODE_SHIFT; 26162306a36Sopenharmony_ci break; 26262306a36Sopenharmony_ci case QCE_MODE_CTR: 26362306a36Sopenharmony_ci cfg |= ENCR_MODE_CTR << ENCR_MODE_SHIFT; 26462306a36Sopenharmony_ci break; 26562306a36Sopenharmony_ci case QCE_MODE_XTS: 26662306a36Sopenharmony_ci cfg |= ENCR_MODE_XTS << ENCR_MODE_SHIFT; 26762306a36Sopenharmony_ci break; 26862306a36Sopenharmony_ci case QCE_MODE_CCM: 26962306a36Sopenharmony_ci cfg |= ENCR_MODE_CCM << ENCR_MODE_SHIFT; 27062306a36Sopenharmony_ci cfg |= LAST_CCM_XFR << LAST_CCM_SHIFT; 27162306a36Sopenharmony_ci break; 27262306a36Sopenharmony_ci default: 27362306a36Sopenharmony_ci return ~0; 27462306a36Sopenharmony_ci } 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci return cfg; 27762306a36Sopenharmony_ci} 27862306a36Sopenharmony_ci#endif 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci#ifdef CONFIG_CRYPTO_DEV_QCE_SKCIPHER 28162306a36Sopenharmony_cistatic void qce_xts_swapiv(__be32 *dst, const u8 *src, unsigned int ivsize) 28262306a36Sopenharmony_ci{ 28362306a36Sopenharmony_ci u8 swap[QCE_AES_IV_LENGTH]; 28462306a36Sopenharmony_ci u32 i, j; 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci if (ivsize > QCE_AES_IV_LENGTH) 28762306a36Sopenharmony_ci return; 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci memset(swap, 0, QCE_AES_IV_LENGTH); 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci for (i = (QCE_AES_IV_LENGTH - ivsize), j = ivsize - 1; 29262306a36Sopenharmony_ci i < QCE_AES_IV_LENGTH; i++, j--) 29362306a36Sopenharmony_ci swap[i] = src[j]; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci qce_cpu_to_be32p_array(dst, swap, QCE_AES_IV_LENGTH); 29662306a36Sopenharmony_ci} 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_cistatic void qce_xtskey(struct qce_device *qce, const u8 *enckey, 29962306a36Sopenharmony_ci unsigned int enckeylen, unsigned int cryptlen) 30062306a36Sopenharmony_ci{ 30162306a36Sopenharmony_ci u32 xtskey[QCE_MAX_CIPHER_KEY_SIZE / sizeof(u32)] = {0}; 30262306a36Sopenharmony_ci unsigned int xtsklen = enckeylen / (2 * sizeof(u32)); 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci qce_cpu_to_be32p_array((__be32 *)xtskey, enckey + enckeylen / 2, 30562306a36Sopenharmony_ci enckeylen / 2); 30662306a36Sopenharmony_ci qce_write_array(qce, REG_ENCR_XTS_KEY0, xtskey, xtsklen); 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci /* Set data unit size to cryptlen. Anything else causes 30962306a36Sopenharmony_ci * crypto engine to return back incorrect results. 31062306a36Sopenharmony_ci */ 31162306a36Sopenharmony_ci qce_write(qce, REG_ENCR_XTS_DU_SIZE, cryptlen); 31262306a36Sopenharmony_ci} 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_cistatic int qce_setup_regs_skcipher(struct crypto_async_request *async_req) 31562306a36Sopenharmony_ci{ 31662306a36Sopenharmony_ci struct skcipher_request *req = skcipher_request_cast(async_req); 31762306a36Sopenharmony_ci struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); 31862306a36Sopenharmony_ci struct qce_cipher_ctx *ctx = crypto_tfm_ctx(async_req->tfm); 31962306a36Sopenharmony_ci struct qce_alg_template *tmpl = to_cipher_tmpl(crypto_skcipher_reqtfm(req)); 32062306a36Sopenharmony_ci struct qce_device *qce = tmpl->qce; 32162306a36Sopenharmony_ci __be32 enckey[QCE_MAX_CIPHER_KEY_SIZE / sizeof(__be32)] = {0}; 32262306a36Sopenharmony_ci __be32 enciv[QCE_MAX_IV_SIZE / sizeof(__be32)] = {0}; 32362306a36Sopenharmony_ci unsigned int enckey_words, enciv_words; 32462306a36Sopenharmony_ci unsigned int keylen; 32562306a36Sopenharmony_ci u32 encr_cfg = 0, auth_cfg = 0, config; 32662306a36Sopenharmony_ci unsigned int ivsize = rctx->ivsize; 32762306a36Sopenharmony_ci unsigned long flags = rctx->flags; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci qce_setup_config(qce); 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci if (IS_XTS(flags)) 33262306a36Sopenharmony_ci keylen = ctx->enc_keylen / 2; 33362306a36Sopenharmony_ci else 33462306a36Sopenharmony_ci keylen = ctx->enc_keylen; 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci qce_cpu_to_be32p_array(enckey, ctx->enc_key, keylen); 33762306a36Sopenharmony_ci enckey_words = keylen / sizeof(u32); 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci qce_write(qce, REG_AUTH_SEG_CFG, auth_cfg); 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci encr_cfg = qce_encr_cfg(flags, keylen); 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci if (IS_DES(flags)) { 34462306a36Sopenharmony_ci enciv_words = 2; 34562306a36Sopenharmony_ci enckey_words = 2; 34662306a36Sopenharmony_ci } else if (IS_3DES(flags)) { 34762306a36Sopenharmony_ci enciv_words = 2; 34862306a36Sopenharmony_ci enckey_words = 6; 34962306a36Sopenharmony_ci } else if (IS_AES(flags)) { 35062306a36Sopenharmony_ci if (IS_XTS(flags)) 35162306a36Sopenharmony_ci qce_xtskey(qce, ctx->enc_key, ctx->enc_keylen, 35262306a36Sopenharmony_ci rctx->cryptlen); 35362306a36Sopenharmony_ci enciv_words = 4; 35462306a36Sopenharmony_ci } else { 35562306a36Sopenharmony_ci return -EINVAL; 35662306a36Sopenharmony_ci } 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci qce_write_array(qce, REG_ENCR_KEY0, (u32 *)enckey, enckey_words); 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci if (!IS_ECB(flags)) { 36162306a36Sopenharmony_ci if (IS_XTS(flags)) 36262306a36Sopenharmony_ci qce_xts_swapiv(enciv, rctx->iv, ivsize); 36362306a36Sopenharmony_ci else 36462306a36Sopenharmony_ci qce_cpu_to_be32p_array(enciv, rctx->iv, ivsize); 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci qce_write_array(qce, REG_CNTR0_IV0, (u32 *)enciv, enciv_words); 36762306a36Sopenharmony_ci } 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci if (IS_ENCRYPT(flags)) 37062306a36Sopenharmony_ci encr_cfg |= BIT(ENCODE_SHIFT); 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci qce_write(qce, REG_ENCR_SEG_CFG, encr_cfg); 37362306a36Sopenharmony_ci qce_write(qce, REG_ENCR_SEG_SIZE, rctx->cryptlen); 37462306a36Sopenharmony_ci qce_write(qce, REG_ENCR_SEG_START, 0); 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci if (IS_CTR(flags)) { 37762306a36Sopenharmony_ci qce_write(qce, REG_CNTR_MASK, ~0); 37862306a36Sopenharmony_ci qce_write(qce, REG_CNTR_MASK0, ~0); 37962306a36Sopenharmony_ci qce_write(qce, REG_CNTR_MASK1, ~0); 38062306a36Sopenharmony_ci qce_write(qce, REG_CNTR_MASK2, ~0); 38162306a36Sopenharmony_ci } 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci qce_write(qce, REG_SEG_SIZE, rctx->cryptlen); 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci /* get little endianness */ 38662306a36Sopenharmony_ci config = qce_config_reg(qce, 1); 38762306a36Sopenharmony_ci qce_write(qce, REG_CONFIG, config); 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci qce_crypto_go(qce, true); 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci return 0; 39262306a36Sopenharmony_ci} 39362306a36Sopenharmony_ci#endif 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci#ifdef CONFIG_CRYPTO_DEV_QCE_AEAD 39662306a36Sopenharmony_cistatic const u32 std_iv_sha1[SHA256_DIGEST_SIZE / sizeof(u32)] = { 39762306a36Sopenharmony_ci SHA1_H0, SHA1_H1, SHA1_H2, SHA1_H3, SHA1_H4, 0, 0, 0 39862306a36Sopenharmony_ci}; 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_cistatic const u32 std_iv_sha256[SHA256_DIGEST_SIZE / sizeof(u32)] = { 40162306a36Sopenharmony_ci SHA256_H0, SHA256_H1, SHA256_H2, SHA256_H3, 40262306a36Sopenharmony_ci SHA256_H4, SHA256_H5, SHA256_H6, SHA256_H7 40362306a36Sopenharmony_ci}; 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_cistatic unsigned int qce_be32_to_cpu_array(u32 *dst, const u8 *src, unsigned int len) 40662306a36Sopenharmony_ci{ 40762306a36Sopenharmony_ci u32 *d = dst; 40862306a36Sopenharmony_ci const u8 *s = src; 40962306a36Sopenharmony_ci unsigned int n; 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci n = len / sizeof(u32); 41262306a36Sopenharmony_ci for (; n > 0; n--) { 41362306a36Sopenharmony_ci *d = be32_to_cpup((const __be32 *)s); 41462306a36Sopenharmony_ci s += sizeof(u32); 41562306a36Sopenharmony_ci d++; 41662306a36Sopenharmony_ci } 41762306a36Sopenharmony_ci return DIV_ROUND_UP(len, sizeof(u32)); 41862306a36Sopenharmony_ci} 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_cistatic int qce_setup_regs_aead(struct crypto_async_request *async_req) 42162306a36Sopenharmony_ci{ 42262306a36Sopenharmony_ci struct aead_request *req = aead_request_cast(async_req); 42362306a36Sopenharmony_ci struct qce_aead_reqctx *rctx = aead_request_ctx_dma(req); 42462306a36Sopenharmony_ci struct qce_aead_ctx *ctx = crypto_tfm_ctx(async_req->tfm); 42562306a36Sopenharmony_ci struct qce_alg_template *tmpl = to_aead_tmpl(crypto_aead_reqtfm(req)); 42662306a36Sopenharmony_ci struct qce_device *qce = tmpl->qce; 42762306a36Sopenharmony_ci u32 enckey[QCE_MAX_CIPHER_KEY_SIZE / sizeof(u32)] = {0}; 42862306a36Sopenharmony_ci u32 enciv[QCE_MAX_IV_SIZE / sizeof(u32)] = {0}; 42962306a36Sopenharmony_ci u32 authkey[QCE_SHA_HMAC_KEY_SIZE / sizeof(u32)] = {0}; 43062306a36Sopenharmony_ci u32 authiv[SHA256_DIGEST_SIZE / sizeof(u32)] = {0}; 43162306a36Sopenharmony_ci u32 authnonce[QCE_MAX_NONCE / sizeof(u32)] = {0}; 43262306a36Sopenharmony_ci unsigned int enc_keylen = ctx->enc_keylen; 43362306a36Sopenharmony_ci unsigned int auth_keylen = ctx->auth_keylen; 43462306a36Sopenharmony_ci unsigned int enc_ivsize = rctx->ivsize; 43562306a36Sopenharmony_ci unsigned int auth_ivsize = 0; 43662306a36Sopenharmony_ci unsigned int enckey_words, enciv_words; 43762306a36Sopenharmony_ci unsigned int authkey_words, authiv_words, authnonce_words; 43862306a36Sopenharmony_ci unsigned long flags = rctx->flags; 43962306a36Sopenharmony_ci u32 encr_cfg, auth_cfg, config, totallen; 44062306a36Sopenharmony_ci u32 iv_last_word; 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci qce_setup_config(qce); 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci /* Write encryption key */ 44562306a36Sopenharmony_ci enckey_words = qce_be32_to_cpu_array(enckey, ctx->enc_key, enc_keylen); 44662306a36Sopenharmony_ci qce_write_array(qce, REG_ENCR_KEY0, enckey, enckey_words); 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci /* Write encryption iv */ 44962306a36Sopenharmony_ci enciv_words = qce_be32_to_cpu_array(enciv, rctx->iv, enc_ivsize); 45062306a36Sopenharmony_ci qce_write_array(qce, REG_CNTR0_IV0, enciv, enciv_words); 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci if (IS_CCM(rctx->flags)) { 45362306a36Sopenharmony_ci iv_last_word = enciv[enciv_words - 1]; 45462306a36Sopenharmony_ci qce_write(qce, REG_CNTR3_IV3, iv_last_word + 1); 45562306a36Sopenharmony_ci qce_write_array(qce, REG_ENCR_CCM_INT_CNTR0, (u32 *)enciv, enciv_words); 45662306a36Sopenharmony_ci qce_write(qce, REG_CNTR_MASK, ~0); 45762306a36Sopenharmony_ci qce_write(qce, REG_CNTR_MASK0, ~0); 45862306a36Sopenharmony_ci qce_write(qce, REG_CNTR_MASK1, ~0); 45962306a36Sopenharmony_ci qce_write(qce, REG_CNTR_MASK2, ~0); 46062306a36Sopenharmony_ci } 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci /* Clear authentication IV and KEY registers of previous values */ 46362306a36Sopenharmony_ci qce_clear_array(qce, REG_AUTH_IV0, 16); 46462306a36Sopenharmony_ci qce_clear_array(qce, REG_AUTH_KEY0, 16); 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci /* Clear byte count */ 46762306a36Sopenharmony_ci qce_clear_array(qce, REG_AUTH_BYTECNT0, 4); 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci /* Write authentication key */ 47062306a36Sopenharmony_ci authkey_words = qce_be32_to_cpu_array(authkey, ctx->auth_key, auth_keylen); 47162306a36Sopenharmony_ci qce_write_array(qce, REG_AUTH_KEY0, (u32 *)authkey, authkey_words); 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci /* Write initial authentication IV only for HMAC algorithms */ 47462306a36Sopenharmony_ci if (IS_SHA_HMAC(rctx->flags)) { 47562306a36Sopenharmony_ci /* Write default authentication iv */ 47662306a36Sopenharmony_ci if (IS_SHA1_HMAC(rctx->flags)) { 47762306a36Sopenharmony_ci auth_ivsize = SHA1_DIGEST_SIZE; 47862306a36Sopenharmony_ci memcpy(authiv, std_iv_sha1, auth_ivsize); 47962306a36Sopenharmony_ci } else if (IS_SHA256_HMAC(rctx->flags)) { 48062306a36Sopenharmony_ci auth_ivsize = SHA256_DIGEST_SIZE; 48162306a36Sopenharmony_ci memcpy(authiv, std_iv_sha256, auth_ivsize); 48262306a36Sopenharmony_ci } 48362306a36Sopenharmony_ci authiv_words = auth_ivsize / sizeof(u32); 48462306a36Sopenharmony_ci qce_write_array(qce, REG_AUTH_IV0, (u32 *)authiv, authiv_words); 48562306a36Sopenharmony_ci } else if (IS_CCM(rctx->flags)) { 48662306a36Sopenharmony_ci /* Write nonce for CCM algorithms */ 48762306a36Sopenharmony_ci authnonce_words = qce_be32_to_cpu_array(authnonce, rctx->ccm_nonce, QCE_MAX_NONCE); 48862306a36Sopenharmony_ci qce_write_array(qce, REG_AUTH_INFO_NONCE0, authnonce, authnonce_words); 48962306a36Sopenharmony_ci } 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci /* Set up ENCR_SEG_CFG */ 49262306a36Sopenharmony_ci encr_cfg = qce_encr_cfg(flags, enc_keylen); 49362306a36Sopenharmony_ci if (IS_ENCRYPT(flags)) 49462306a36Sopenharmony_ci encr_cfg |= BIT(ENCODE_SHIFT); 49562306a36Sopenharmony_ci qce_write(qce, REG_ENCR_SEG_CFG, encr_cfg); 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci /* Set up AUTH_SEG_CFG */ 49862306a36Sopenharmony_ci auth_cfg = qce_auth_cfg(rctx->flags, auth_keylen, ctx->authsize); 49962306a36Sopenharmony_ci auth_cfg |= BIT(AUTH_LAST_SHIFT); 50062306a36Sopenharmony_ci auth_cfg |= BIT(AUTH_FIRST_SHIFT); 50162306a36Sopenharmony_ci if (IS_ENCRYPT(flags)) { 50262306a36Sopenharmony_ci if (IS_CCM(rctx->flags)) 50362306a36Sopenharmony_ci auth_cfg |= AUTH_POS_BEFORE << AUTH_POS_SHIFT; 50462306a36Sopenharmony_ci else 50562306a36Sopenharmony_ci auth_cfg |= AUTH_POS_AFTER << AUTH_POS_SHIFT; 50662306a36Sopenharmony_ci } else { 50762306a36Sopenharmony_ci if (IS_CCM(rctx->flags)) 50862306a36Sopenharmony_ci auth_cfg |= AUTH_POS_AFTER << AUTH_POS_SHIFT; 50962306a36Sopenharmony_ci else 51062306a36Sopenharmony_ci auth_cfg |= AUTH_POS_BEFORE << AUTH_POS_SHIFT; 51162306a36Sopenharmony_ci } 51262306a36Sopenharmony_ci qce_write(qce, REG_AUTH_SEG_CFG, auth_cfg); 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci totallen = rctx->cryptlen + rctx->assoclen; 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci /* Set the encryption size and start offset */ 51762306a36Sopenharmony_ci if (IS_CCM(rctx->flags) && IS_DECRYPT(rctx->flags)) 51862306a36Sopenharmony_ci qce_write(qce, REG_ENCR_SEG_SIZE, rctx->cryptlen + ctx->authsize); 51962306a36Sopenharmony_ci else 52062306a36Sopenharmony_ci qce_write(qce, REG_ENCR_SEG_SIZE, rctx->cryptlen); 52162306a36Sopenharmony_ci qce_write(qce, REG_ENCR_SEG_START, rctx->assoclen & 0xffff); 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_ci /* Set the authentication size and start offset */ 52462306a36Sopenharmony_ci qce_write(qce, REG_AUTH_SEG_SIZE, totallen); 52562306a36Sopenharmony_ci qce_write(qce, REG_AUTH_SEG_START, 0); 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci /* Write total length */ 52862306a36Sopenharmony_ci if (IS_CCM(rctx->flags) && IS_DECRYPT(rctx->flags)) 52962306a36Sopenharmony_ci qce_write(qce, REG_SEG_SIZE, totallen + ctx->authsize); 53062306a36Sopenharmony_ci else 53162306a36Sopenharmony_ci qce_write(qce, REG_SEG_SIZE, totallen); 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci /* get little endianness */ 53462306a36Sopenharmony_ci config = qce_config_reg(qce, 1); 53562306a36Sopenharmony_ci qce_write(qce, REG_CONFIG, config); 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci /* Start the process */ 53862306a36Sopenharmony_ci qce_crypto_go(qce, !IS_CCM(flags)); 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci return 0; 54162306a36Sopenharmony_ci} 54262306a36Sopenharmony_ci#endif 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ciint qce_start(struct crypto_async_request *async_req, u32 type) 54562306a36Sopenharmony_ci{ 54662306a36Sopenharmony_ci switch (type) { 54762306a36Sopenharmony_ci#ifdef CONFIG_CRYPTO_DEV_QCE_SKCIPHER 54862306a36Sopenharmony_ci case CRYPTO_ALG_TYPE_SKCIPHER: 54962306a36Sopenharmony_ci return qce_setup_regs_skcipher(async_req); 55062306a36Sopenharmony_ci#endif 55162306a36Sopenharmony_ci#ifdef CONFIG_CRYPTO_DEV_QCE_SHA 55262306a36Sopenharmony_ci case CRYPTO_ALG_TYPE_AHASH: 55362306a36Sopenharmony_ci return qce_setup_regs_ahash(async_req); 55462306a36Sopenharmony_ci#endif 55562306a36Sopenharmony_ci#ifdef CONFIG_CRYPTO_DEV_QCE_AEAD 55662306a36Sopenharmony_ci case CRYPTO_ALG_TYPE_AEAD: 55762306a36Sopenharmony_ci return qce_setup_regs_aead(async_req); 55862306a36Sopenharmony_ci#endif 55962306a36Sopenharmony_ci default: 56062306a36Sopenharmony_ci return -EINVAL; 56162306a36Sopenharmony_ci } 56262306a36Sopenharmony_ci} 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_ci#define STATUS_ERRORS \ 56562306a36Sopenharmony_ci (BIT(SW_ERR_SHIFT) | BIT(AXI_ERR_SHIFT) | BIT(HSD_ERR_SHIFT)) 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_ciint qce_check_status(struct qce_device *qce, u32 *status) 56862306a36Sopenharmony_ci{ 56962306a36Sopenharmony_ci int ret = 0; 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_ci *status = qce_read(qce, REG_STATUS); 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci /* 57462306a36Sopenharmony_ci * Don't use result dump status. The operation may not be complete. 57562306a36Sopenharmony_ci * Instead, use the status we just read from device. In case, we need to 57662306a36Sopenharmony_ci * use result_status from result dump the result_status needs to be byte 57762306a36Sopenharmony_ci * swapped, since we set the device to little endian. 57862306a36Sopenharmony_ci */ 57962306a36Sopenharmony_ci if (*status & STATUS_ERRORS || !(*status & BIT(OPERATION_DONE_SHIFT))) 58062306a36Sopenharmony_ci ret = -ENXIO; 58162306a36Sopenharmony_ci else if (*status & BIT(MAC_FAILED_SHIFT)) 58262306a36Sopenharmony_ci ret = -EBADMSG; 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci return ret; 58562306a36Sopenharmony_ci} 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_civoid qce_get_version(struct qce_device *qce, u32 *major, u32 *minor, u32 *step) 58862306a36Sopenharmony_ci{ 58962306a36Sopenharmony_ci u32 val; 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci val = qce_read(qce, REG_VERSION); 59262306a36Sopenharmony_ci *major = (val & CORE_MAJOR_REV_MASK) >> CORE_MAJOR_REV_SHIFT; 59362306a36Sopenharmony_ci *minor = (val & CORE_MINOR_REV_MASK) >> CORE_MINOR_REV_SHIFT; 59462306a36Sopenharmony_ci *step = (val & CORE_STEP_REV_MASK) >> CORE_STEP_REV_SHIFT; 59562306a36Sopenharmony_ci} 596