diff options
Diffstat (limited to 'target/linux/mediatek/patches-5.4/0500-v5.6-crypto-backport-inside-secure.patch')
-rw-r--r-- | target/linux/mediatek/patches-5.4/0500-v5.6-crypto-backport-inside-secure.patch | 5464 |
1 files changed, 0 insertions, 5464 deletions
diff --git a/target/linux/mediatek/patches-5.4/0500-v5.6-crypto-backport-inside-secure.patch b/target/linux/mediatek/patches-5.4/0500-v5.6-crypto-backport-inside-secure.patch deleted file mode 100644 index 2fae90ef9e..0000000000 --- a/target/linux/mediatek/patches-5.4/0500-v5.6-crypto-backport-inside-secure.patch +++ /dev/null @@ -1,5464 +0,0 @@ ---- a/drivers/crypto/inside-secure/safexcel.c -+++ b/drivers/crypto/inside-secure/safexcel.c -@@ -75,9 +75,9 @@ static void eip197_trc_cache_banksel(str - } - - static u32 eip197_trc_cache_probe(struct safexcel_crypto_priv *priv, -- int maxbanks, u32 probemask) -+ int maxbanks, u32 probemask, u32 stride) - { -- u32 val, addrhi, addrlo, addrmid; -+ u32 val, addrhi, addrlo, addrmid, addralias, delta, marker; - int actbank; - - /* -@@ -87,32 +87,37 @@ static u32 eip197_trc_cache_probe(struct - addrhi = 1 << (16 + maxbanks); - addrlo = 0; - actbank = min(maxbanks - 1, 0); -- while ((addrhi - addrlo) > 32) { -+ while ((addrhi - addrlo) > stride) { - /* write marker to lowest address in top half */ - addrmid = (addrhi + addrlo) >> 1; -+ marker = (addrmid ^ 0xabadbabe) & probemask; /* Unique */ - eip197_trc_cache_banksel(priv, addrmid, &actbank); -- writel((addrmid | (addrlo << 16)) & probemask, -+ writel(marker, - priv->base + EIP197_CLASSIFICATION_RAMS + - (addrmid & 0xffff)); - -- /* write marker to lowest address in bottom half */ -- eip197_trc_cache_banksel(priv, addrlo, &actbank); -- writel((addrlo | (addrhi << 16)) & probemask, -- priv->base + EIP197_CLASSIFICATION_RAMS + -- (addrlo & 0xffff)); -+ /* write invalid markers to possible aliases */ -+ delta = 1 << __fls(addrmid); -+ while (delta >= stride) { -+ addralias = addrmid - delta; -+ eip197_trc_cache_banksel(priv, addralias, &actbank); -+ writel(~marker, -+ priv->base + EIP197_CLASSIFICATION_RAMS + -+ (addralias & 0xffff)); -+ delta >>= 1; -+ } - - /* read back marker from top half */ - eip197_trc_cache_banksel(priv, addrmid, &actbank); - val = readl(priv->base + EIP197_CLASSIFICATION_RAMS + - (addrmid & 0xffff)); - -- if (val == ((addrmid | (addrlo << 16)) & probemask)) { -+ if ((val & probemask) == marker) - /* read back correct, continue with top half */ - addrlo = addrmid; -- } else { -+ else - /* not read back correct, continue with bottom half */ - addrhi = addrmid; -- } - } - return addrhi; - } -@@ -150,7 +155,7 @@ static void eip197_trc_cache_clear(struc - htable_offset + i * sizeof(u32)); - } - --static void eip197_trc_cache_init(struct safexcel_crypto_priv *priv) -+static int eip197_trc_cache_init(struct safexcel_crypto_priv *priv) - { - u32 val, dsize, asize; - int cs_rc_max, cs_ht_wc, cs_trc_rec_wc, cs_trc_lg_rec_wc; -@@ -183,7 +188,7 @@ static void eip197_trc_cache_init(struct - writel(val, priv->base + EIP197_TRC_PARAMS); - - /* Probed data RAM size in bytes */ -- dsize = eip197_trc_cache_probe(priv, maxbanks, 0xffffffff); -+ dsize = eip197_trc_cache_probe(priv, maxbanks, 0xffffffff, 32); - - /* - * Now probe the administration RAM size pretty much the same way -@@ -196,11 +201,18 @@ static void eip197_trc_cache_init(struct - writel(val, priv->base + EIP197_TRC_PARAMS); - - /* Probed admin RAM size in admin words */ -- asize = eip197_trc_cache_probe(priv, 0, 0xbfffffff) >> 4; -+ asize = eip197_trc_cache_probe(priv, 0, 0x3fffffff, 16) >> 4; - - /* Clear any ECC errors detected while probing! */ - writel(0, priv->base + EIP197_TRC_ECCCTRL); - -+ /* Sanity check probing results */ -+ if (dsize < EIP197_MIN_DSIZE || asize < EIP197_MIN_ASIZE) { -+ dev_err(priv->dev, "Record cache probing failed (%d,%d).", -+ dsize, asize); -+ return -ENODEV; -+ } -+ - /* - * Determine optimal configuration from RAM sizes - * Note that we assume that the physical RAM configuration is sane -@@ -251,6 +263,7 @@ static void eip197_trc_cache_init(struct - - dev_info(priv->dev, "TRC init: %dd,%da (%dr,%dh)\n", - dsize, asize, cs_rc_max, cs_ht_wc + cs_ht_wc); -+ return 0; - } - - static void eip197_init_firmware(struct safexcel_crypto_priv *priv) -@@ -298,13 +311,14 @@ static void eip197_init_firmware(struct - static int eip197_write_firmware(struct safexcel_crypto_priv *priv, - const struct firmware *fw) - { -- const u32 *data = (const u32 *)fw->data; -+ const __be32 *data = (const __be32 *)fw->data; - int i; - - /* Write the firmware */ - for (i = 0; i < fw->size / sizeof(u32); i++) - writel(be32_to_cpu(data[i]), -- priv->base + EIP197_CLASSIFICATION_RAMS + i * sizeof(u32)); -+ priv->base + EIP197_CLASSIFICATION_RAMS + -+ i * sizeof(__be32)); - - /* Exclude final 2 NOPs from size */ - return i - EIP197_FW_TERMINAL_NOPS; -@@ -471,6 +485,14 @@ static int safexcel_hw_setup_cdesc_rings - cd_fetch_cnt = ((1 << priv->hwconfig.hwcfsize) / - cd_size_rnd) - 1; - } -+ /* -+ * Since we're using command desc's way larger than formally specified, -+ * we need to check whether we can fit even 1 for low-end EIP196's! -+ */ -+ if (!cd_fetch_cnt) { -+ dev_err(priv->dev, "Unable to fit even 1 command desc!\n"); -+ return -ENODEV; -+ } - - for (i = 0; i < priv->config.rings; i++) { - /* ring base address */ -@@ -479,12 +501,12 @@ static int safexcel_hw_setup_cdesc_rings - writel(upper_32_bits(priv->ring[i].cdr.base_dma), - EIP197_HIA_CDR(priv, i) + EIP197_HIA_xDR_RING_BASE_ADDR_HI); - -- writel(EIP197_xDR_DESC_MODE_64BIT | (priv->config.cd_offset << 16) | -- priv->config.cd_size, -+ writel(EIP197_xDR_DESC_MODE_64BIT | EIP197_CDR_DESC_MODE_ADCP | -+ (priv->config.cd_offset << 14) | priv->config.cd_size, - EIP197_HIA_CDR(priv, i) + EIP197_HIA_xDR_DESC_SIZE); - writel(((cd_fetch_cnt * - (cd_size_rnd << priv->hwconfig.hwdataw)) << 16) | -- (cd_fetch_cnt * priv->config.cd_offset), -+ (cd_fetch_cnt * (priv->config.cd_offset / sizeof(u32))), - EIP197_HIA_CDR(priv, i) + EIP197_HIA_xDR_CFG); - - /* Configure DMA tx control */ -@@ -527,13 +549,13 @@ static int safexcel_hw_setup_rdesc_rings - writel(upper_32_bits(priv->ring[i].rdr.base_dma), - EIP197_HIA_RDR(priv, i) + EIP197_HIA_xDR_RING_BASE_ADDR_HI); - -- writel(EIP197_xDR_DESC_MODE_64BIT | (priv->config.rd_offset << 16) | -+ writel(EIP197_xDR_DESC_MODE_64BIT | (priv->config.rd_offset << 14) | - priv->config.rd_size, - EIP197_HIA_RDR(priv, i) + EIP197_HIA_xDR_DESC_SIZE); - - writel(((rd_fetch_cnt * - (rd_size_rnd << priv->hwconfig.hwdataw)) << 16) | -- (rd_fetch_cnt * priv->config.rd_offset), -+ (rd_fetch_cnt * (priv->config.rd_offset / sizeof(u32))), - EIP197_HIA_RDR(priv, i) + EIP197_HIA_xDR_CFG); - - /* Configure DMA tx control */ -@@ -559,7 +581,7 @@ static int safexcel_hw_setup_rdesc_rings - static int safexcel_hw_init(struct safexcel_crypto_priv *priv) - { - u32 val; -- int i, ret, pe; -+ int i, ret, pe, opbuflo, opbufhi; - - dev_dbg(priv->dev, "HW init: using %d pipe(s) and %d ring(s)\n", - priv->config.pes, priv->config.rings); -@@ -595,8 +617,8 @@ static int safexcel_hw_init(struct safex - writel(EIP197_DxE_THR_CTRL_RESET_PE, - EIP197_HIA_DFE_THR(priv) + EIP197_HIA_DFE_THR_CTRL(pe)); - -- if (priv->flags & SAFEXCEL_HW_EIP197) -- /* Reset HIA input interface arbiter (EIP197 only) */ -+ if (priv->flags & EIP197_PE_ARB) -+ /* Reset HIA input interface arbiter (if present) */ - writel(EIP197_HIA_RA_PE_CTRL_RESET, - EIP197_HIA_AIC(priv) + EIP197_HIA_RA_PE_CTRL(pe)); - -@@ -639,9 +661,16 @@ static int safexcel_hw_init(struct safex - ; - - /* DMA transfer size to use */ -+ if (priv->hwconfig.hwnumpes > 4) { -+ opbuflo = 9; -+ opbufhi = 10; -+ } else { -+ opbuflo = 7; -+ opbufhi = 8; -+ } - val = EIP197_HIA_DSE_CFG_DIS_DEBUG; -- val |= EIP197_HIA_DxE_CFG_MIN_DATA_SIZE(7) | -- EIP197_HIA_DxE_CFG_MAX_DATA_SIZE(8); -+ val |= EIP197_HIA_DxE_CFG_MIN_DATA_SIZE(opbuflo) | -+ EIP197_HIA_DxE_CFG_MAX_DATA_SIZE(opbufhi); - val |= EIP197_HIA_DxE_CFG_DATA_CACHE_CTRL(WR_CACHE_3BITS); - val |= EIP197_HIA_DSE_CFG_ALWAYS_BUFFERABLE; - /* FIXME: instability issues can occur for EIP97 but disabling -@@ -655,8 +684,8 @@ static int safexcel_hw_init(struct safex - writel(0, EIP197_HIA_DSE_THR(priv) + EIP197_HIA_DSE_THR_CTRL(pe)); - - /* Configure the procesing engine thresholds */ -- writel(EIP197_PE_OUT_DBUF_THRES_MIN(7) | -- EIP197_PE_OUT_DBUF_THRES_MAX(8), -+ writel(EIP197_PE_OUT_DBUF_THRES_MIN(opbuflo) | -+ EIP197_PE_OUT_DBUF_THRES_MAX(opbufhi), - EIP197_PE(priv) + EIP197_PE_OUT_DBUF_THRES(pe)); - - /* Processing Engine configuration */ -@@ -696,7 +725,7 @@ static int safexcel_hw_init(struct safex - writel(0, - EIP197_HIA_CDR(priv, i) + EIP197_HIA_xDR_PROC_PNTR); - -- writel((EIP197_DEFAULT_RING_SIZE * priv->config.cd_offset) << 2, -+ writel((EIP197_DEFAULT_RING_SIZE * priv->config.cd_offset), - EIP197_HIA_CDR(priv, i) + EIP197_HIA_xDR_RING_SIZE); - } - -@@ -719,7 +748,7 @@ static int safexcel_hw_init(struct safex - EIP197_HIA_RDR(priv, i) + EIP197_HIA_xDR_PROC_PNTR); - - /* Ring size */ -- writel((EIP197_DEFAULT_RING_SIZE * priv->config.rd_offset) << 2, -+ writel((EIP197_DEFAULT_RING_SIZE * priv->config.rd_offset), - EIP197_HIA_RDR(priv, i) + EIP197_HIA_xDR_RING_SIZE); - } - -@@ -736,19 +765,28 @@ static int safexcel_hw_init(struct safex - /* Clear any HIA interrupt */ - writel(GENMASK(30, 20), EIP197_HIA_AIC_G(priv) + EIP197_HIA_AIC_G_ACK); - -- if (priv->flags & SAFEXCEL_HW_EIP197) { -- eip197_trc_cache_init(priv); -- priv->flags |= EIP197_TRC_CACHE; -+ if (priv->flags & EIP197_SIMPLE_TRC) { -+ writel(EIP197_STRC_CONFIG_INIT | -+ EIP197_STRC_CONFIG_LARGE_REC(EIP197_CS_TRC_REC_WC) | -+ EIP197_STRC_CONFIG_SMALL_REC(EIP197_CS_TRC_REC_WC), -+ priv->base + EIP197_STRC_CONFIG); -+ writel(EIP197_PE_EIP96_TOKEN_CTRL2_CTX_DONE, -+ EIP197_PE(priv) + EIP197_PE_EIP96_TOKEN_CTRL2(0)); -+ } else if (priv->flags & SAFEXCEL_HW_EIP197) { -+ ret = eip197_trc_cache_init(priv); -+ if (ret) -+ return ret; -+ } - -+ if (priv->flags & EIP197_ICE) { - ret = eip197_load_firmwares(priv); - if (ret) - return ret; - } - -- safexcel_hw_setup_cdesc_rings(priv); -- safexcel_hw_setup_rdesc_rings(priv); -- -- return 0; -+ return safexcel_hw_setup_cdesc_rings(priv) ?: -+ safexcel_hw_setup_rdesc_rings(priv) ?: -+ 0; - } - - /* Called with ring's lock taken */ -@@ -836,20 +874,24 @@ finalize: - spin_unlock_bh(&priv->ring[ring].lock); - - /* let the RDR know we have pending descriptors */ -- writel((rdesc * priv->config.rd_offset) << 2, -+ writel((rdesc * priv->config.rd_offset), - EIP197_HIA_RDR(priv, ring) + EIP197_HIA_xDR_PREP_COUNT); - - /* let the CDR know we have pending descriptors */ -- writel((cdesc * priv->config.cd_offset) << 2, -+ writel((cdesc * priv->config.cd_offset), - EIP197_HIA_CDR(priv, ring) + EIP197_HIA_xDR_PREP_COUNT); - } - - inline int safexcel_rdesc_check_errors(struct safexcel_crypto_priv *priv, -- struct safexcel_result_desc *rdesc) -+ void *rdp) - { -- if (likely((!rdesc->descriptor_overflow) && -- (!rdesc->buffer_overflow) && -- (!rdesc->result_data.error_code))) -+ struct safexcel_result_desc *rdesc = rdp; -+ struct result_data_desc *result_data = rdp + priv->config.res_offset; -+ -+ if (likely((!rdesc->last_seg) || /* Rest only valid if last seg! */ -+ ((!rdesc->descriptor_overflow) && -+ (!rdesc->buffer_overflow) && -+ (!result_data->error_code)))) - return 0; - - if (rdesc->descriptor_overflow) -@@ -858,13 +900,14 @@ inline int safexcel_rdesc_check_errors(s - if (rdesc->buffer_overflow) - dev_err(priv->dev, "Buffer overflow detected"); - -- if (rdesc->result_data.error_code & 0x4066) { -+ if (result_data->error_code & 0x4066) { - /* Fatal error (bits 1,2,5,6 & 14) */ - dev_err(priv->dev, - "result descriptor error (%x)", -- rdesc->result_data.error_code); -+ result_data->error_code); -+ - return -EIO; -- } else if (rdesc->result_data.error_code & -+ } else if (result_data->error_code & - (BIT(7) | BIT(4) | BIT(3) | BIT(0))) { - /* - * Give priority over authentication fails: -@@ -872,7 +915,7 @@ inline int safexcel_rdesc_check_errors(s - * something wrong with the input! - */ - return -EINVAL; -- } else if (rdesc->result_data.error_code & BIT(9)) { -+ } else if (result_data->error_code & BIT(9)) { - /* Authentication failed */ - return -EBADMSG; - } -@@ -931,16 +974,18 @@ int safexcel_invalidate_cache(struct cry - { - struct safexcel_command_desc *cdesc; - struct safexcel_result_desc *rdesc; -+ struct safexcel_token *dmmy; - int ret = 0; - - /* Prepare command descriptor */ -- cdesc = safexcel_add_cdesc(priv, ring, true, true, 0, 0, 0, ctxr_dma); -+ cdesc = safexcel_add_cdesc(priv, ring, true, true, 0, 0, 0, ctxr_dma, -+ &dmmy); - if (IS_ERR(cdesc)) - return PTR_ERR(cdesc); - - cdesc->control_data.type = EIP197_TYPE_EXTENDED; - cdesc->control_data.options = 0; -- cdesc->control_data.refresh = 0; -+ cdesc->control_data.context_lo &= ~EIP197_CONTEXT_SIZE_MASK; - cdesc->control_data.control0 = CONTEXT_CONTROL_INV_TR; - - /* Prepare result descriptor */ -@@ -1003,7 +1048,7 @@ handle_results: - acknowledge: - if (i) - writel(EIP197_xDR_PROC_xD_PKT(i) | -- EIP197_xDR_PROC_xD_COUNT(tot_descs * priv->config.rd_offset), -+ (tot_descs * priv->config.rd_offset), - EIP197_HIA_RDR(priv, ring) + EIP197_HIA_xDR_PROC_COUNT); - - /* If the number of requests overflowed the counter, try to proceed more -@@ -1171,6 +1216,44 @@ static struct safexcel_alg_template *saf - &safexcel_alg_xts_aes, - &safexcel_alg_gcm, - &safexcel_alg_ccm, -+ &safexcel_alg_crc32, -+ &safexcel_alg_cbcmac, -+ &safexcel_alg_xcbcmac, -+ &safexcel_alg_cmac, -+ &safexcel_alg_chacha20, -+ &safexcel_alg_chachapoly, -+ &safexcel_alg_chachapoly_esp, -+ &safexcel_alg_sm3, -+ &safexcel_alg_hmac_sm3, -+ &safexcel_alg_ecb_sm4, -+ &safexcel_alg_cbc_sm4, -+ &safexcel_alg_ofb_sm4, -+ &safexcel_alg_cfb_sm4, -+ &safexcel_alg_ctr_sm4, -+ &safexcel_alg_authenc_hmac_sha1_cbc_sm4, -+ &safexcel_alg_authenc_hmac_sm3_cbc_sm4, -+ &safexcel_alg_authenc_hmac_sha1_ctr_sm4, -+ &safexcel_alg_authenc_hmac_sm3_ctr_sm4, -+ &safexcel_alg_sha3_224, -+ &safexcel_alg_sha3_256, -+ &safexcel_alg_sha3_384, -+ &safexcel_alg_sha3_512, -+ &safexcel_alg_hmac_sha3_224, -+ &safexcel_alg_hmac_sha3_256, -+ &safexcel_alg_hmac_sha3_384, -+ &safexcel_alg_hmac_sha3_512, -+ &safexcel_alg_authenc_hmac_sha1_cbc_des, -+ &safexcel_alg_authenc_hmac_sha256_cbc_des3_ede, -+ &safexcel_alg_authenc_hmac_sha224_cbc_des3_ede, -+ &safexcel_alg_authenc_hmac_sha512_cbc_des3_ede, -+ &safexcel_alg_authenc_hmac_sha384_cbc_des3_ede, -+ &safexcel_alg_authenc_hmac_sha256_cbc_des, -+ &safexcel_alg_authenc_hmac_sha224_cbc_des, -+ &safexcel_alg_authenc_hmac_sha512_cbc_des, -+ &safexcel_alg_authenc_hmac_sha384_cbc_des, -+ &safexcel_alg_rfc4106_gcm, -+ &safexcel_alg_rfc4543_gcm, -+ &safexcel_alg_rfc4309_ccm, - }; - - static int safexcel_register_algorithms(struct safexcel_crypto_priv *priv) -@@ -1240,30 +1323,30 @@ static void safexcel_unregister_algorith - - static void safexcel_configure(struct safexcel_crypto_priv *priv) - { -- u32 val, mask = 0; -- -- val = readl(EIP197_HIA_AIC_G(priv) + EIP197_HIA_OPTIONS); -- -- /* Read number of PEs from the engine */ -- if (priv->flags & SAFEXCEL_HW_EIP197) -- /* Wider field width for all EIP197 type engines */ -- mask = EIP197_N_PES_MASK; -- else -- /* Narrow field width for EIP97 type engine */ -- mask = EIP97_N_PES_MASK; -- -- priv->config.pes = (val >> EIP197_N_PES_OFFSET) & mask; -+ u32 mask = BIT(priv->hwconfig.hwdataw) - 1; - -- priv->config.rings = min_t(u32, val & GENMASK(3, 0), max_rings); -+ priv->config.pes = priv->hwconfig.hwnumpes; -+ priv->config.rings = min_t(u32, priv->hwconfig.hwnumrings, max_rings); -+ /* Cannot currently support more rings than we have ring AICs! */ -+ priv->config.rings = min_t(u32, priv->config.rings, -+ priv->hwconfig.hwnumraic); - -- val = (val & GENMASK(27, 25)) >> 25; -- mask = BIT(val) - 1; -- -- priv->config.cd_size = (sizeof(struct safexcel_command_desc) / sizeof(u32)); -+ priv->config.cd_size = EIP197_CD64_FETCH_SIZE; - priv->config.cd_offset = (priv->config.cd_size + mask) & ~mask; -+ priv->config.cdsh_offset = (EIP197_MAX_TOKENS + mask) & ~mask; - -- priv->config.rd_size = (sizeof(struct safexcel_result_desc) / sizeof(u32)); -+ /* res token is behind the descr, but ofs must be rounded to buswdth */ -+ priv->config.res_offset = (EIP197_RD64_FETCH_SIZE + mask) & ~mask; -+ /* now the size of the descr is this 1st part plus the result struct */ -+ priv->config.rd_size = priv->config.res_offset + -+ EIP197_RD64_RESULT_SIZE; - priv->config.rd_offset = (priv->config.rd_size + mask) & ~mask; -+ -+ /* convert dwords to bytes */ -+ priv->config.cd_offset *= sizeof(u32); -+ priv->config.cdsh_offset *= sizeof(u32); -+ priv->config.rd_offset *= sizeof(u32); -+ priv->config.res_offset *= sizeof(u32); - } - - static void safexcel_init_register_offsets(struct safexcel_crypto_priv *priv) -@@ -1309,7 +1392,7 @@ static int safexcel_probe_generic(void * - int is_pci_dev) - { - struct device *dev = priv->dev; -- u32 peid, version, mask, val, hiaopt; -+ u32 peid, version, mask, val, hiaopt, hwopt, peopt; - int i, ret, hwctg; - - priv->context_pool = dmam_pool_create("safexcel-context", dev, -@@ -1371,13 +1454,16 @@ static int safexcel_probe_generic(void * - */ - version = readl(EIP197_GLOBAL(priv) + EIP197_VERSION); - if (((priv->flags & SAFEXCEL_HW_EIP197) && -- (EIP197_REG_LO16(version) != EIP197_VERSION_LE)) || -+ (EIP197_REG_LO16(version) != EIP197_VERSION_LE) && -+ (EIP197_REG_LO16(version) != EIP196_VERSION_LE)) || - ((!(priv->flags & SAFEXCEL_HW_EIP197) && - (EIP197_REG_LO16(version) != EIP97_VERSION_LE)))) { - /* - * We did not find the device that matched our initial probing - * (or our initial probing failed) Report appropriate error. - */ -+ dev_err(priv->dev, "Probing for EIP97/EIP19x failed - no such device (read %08x)\n", -+ version); - return -ENODEV; - } - -@@ -1385,6 +1471,14 @@ static int safexcel_probe_generic(void * - hwctg = version >> 28; - peid = version & 255; - -+ /* Detect EIP206 processing pipe */ -+ version = readl(EIP197_PE(priv) + + EIP197_PE_VERSION(0)); -+ if (EIP197_REG_LO16(version) != EIP206_VERSION_LE) { -+ dev_err(priv->dev, "EIP%d: EIP206 not detected\n", peid); -+ return -ENODEV; -+ } -+ priv->hwconfig.ppver = EIP197_VERSION_MASK(version); -+ - /* Detect EIP96 packet engine and version */ - version = readl(EIP197_PE(priv) + EIP197_PE_EIP96_VERSION(0)); - if (EIP197_REG_LO16(version) != EIP96_VERSION_LE) { -@@ -1393,10 +1487,13 @@ static int safexcel_probe_generic(void * - } - priv->hwconfig.pever = EIP197_VERSION_MASK(version); - -+ hwopt = readl(EIP197_GLOBAL(priv) + EIP197_OPTIONS); - hiaopt = readl(EIP197_HIA_AIC(priv) + EIP197_HIA_OPTIONS); - - if (priv->flags & SAFEXCEL_HW_EIP197) { - /* EIP197 */ -+ peopt = readl(EIP197_PE(priv) + EIP197_PE_OPTIONS(0)); -+ - priv->hwconfig.hwdataw = (hiaopt >> EIP197_HWDATAW_OFFSET) & - EIP197_HWDATAW_MASK; - priv->hwconfig.hwcfsize = ((hiaopt >> EIP197_CFSIZE_OFFSET) & -@@ -1405,6 +1502,19 @@ static int safexcel_probe_generic(void * - priv->hwconfig.hwrfsize = ((hiaopt >> EIP197_RFSIZE_OFFSET) & - EIP197_RFSIZE_MASK) + - EIP197_RFSIZE_ADJUST; -+ priv->hwconfig.hwnumpes = (hiaopt >> EIP197_N_PES_OFFSET) & -+ EIP197_N_PES_MASK; -+ priv->hwconfig.hwnumrings = (hiaopt >> EIP197_N_RINGS_OFFSET) & -+ EIP197_N_RINGS_MASK; -+ if (hiaopt & EIP197_HIA_OPT_HAS_PE_ARB) -+ priv->flags |= EIP197_PE_ARB; -+ if (EIP206_OPT_ICE_TYPE(peopt) == 1) -+ priv->flags |= EIP197_ICE; -+ /* If not a full TRC, then assume simple TRC */ -+ if (!(hwopt & EIP197_OPT_HAS_TRC)) -+ priv->flags |= EIP197_SIMPLE_TRC; -+ /* EIP197 always has SOME form of TRC */ -+ priv->flags |= EIP197_TRC_CACHE; - } else { - /* EIP97 */ - priv->hwconfig.hwdataw = (hiaopt >> EIP197_HWDATAW_OFFSET) & -@@ -1413,6 +1523,23 @@ static int safexcel_probe_generic(void * - EIP97_CFSIZE_MASK; - priv->hwconfig.hwrfsize = (hiaopt >> EIP97_RFSIZE_OFFSET) & - EIP97_RFSIZE_MASK; -+ priv->hwconfig.hwnumpes = 1; /* by definition */ -+ priv->hwconfig.hwnumrings = (hiaopt >> EIP197_N_RINGS_OFFSET) & -+ EIP197_N_RINGS_MASK; -+ } -+ -+ /* Scan for ring AIC's */ -+ for (i = 0; i < EIP197_MAX_RING_AIC; i++) { -+ version = readl(EIP197_HIA_AIC_R(priv) + -+ EIP197_HIA_AIC_R_VERSION(i)); -+ if (EIP197_REG_LO16(version) != EIP201_VERSION_LE) -+ break; -+ } -+ priv->hwconfig.hwnumraic = i; -+ /* Low-end EIP196 may not have any ring AIC's ... */ -+ if (!priv->hwconfig.hwnumraic) { -+ dev_err(priv->dev, "No ring interrupt controller present!\n"); -+ return -ENODEV; - } - - /* Get supported algorithms from EIP96 transform engine */ -@@ -1420,10 +1547,12 @@ static int safexcel_probe_generic(void * - EIP197_PE_EIP96_OPTIONS(0)); - - /* Print single info line describing what we just detected */ -- dev_info(priv->dev, "EIP%d:%x(%d)-HIA:%x(%d,%d,%d),PE:%x,alg:%08x\n", -- peid, priv->hwconfig.hwver, hwctg, priv->hwconfig.hiaver, -- priv->hwconfig.hwdataw, priv->hwconfig.hwcfsize, -- priv->hwconfig.hwrfsize, priv->hwconfig.pever, -+ dev_info(priv->dev, "EIP%d:%x(%d,%d,%d,%d)-HIA:%x(%d,%d,%d),PE:%x/%x,alg:%08x\n", -+ peid, priv->hwconfig.hwver, hwctg, priv->hwconfig.hwnumpes, -+ priv->hwconfig.hwnumrings, priv->hwconfig.hwnumraic, -+ priv->hwconfig.hiaver, priv->hwconfig.hwdataw, -+ priv->hwconfig.hwcfsize, priv->hwconfig.hwrfsize, -+ priv->hwconfig.ppver, priv->hwconfig.pever, - priv->hwconfig.algo_flags); - - safexcel_configure(priv); -@@ -1547,7 +1676,6 @@ static void safexcel_hw_reset_rings(stru - } - } - --#if IS_ENABLED(CONFIG_OF) - /* for Device Tree platform driver */ - - static int safexcel_probe(struct platform_device *pdev) -@@ -1625,6 +1753,7 @@ static int safexcel_remove(struct platfo - safexcel_unregister_algorithms(priv); - safexcel_hw_reset_rings(priv); - -+ clk_disable_unprepare(priv->reg_clk); - clk_disable_unprepare(priv->clk); - - for (i = 0; i < priv->config.rings; i++) -@@ -1666,9 +1795,7 @@ static struct platform_driver crypto_sa - .of_match_table = safexcel_of_match_table, - }, - }; --#endif - --#if IS_ENABLED(CONFIG_PCI) - /* PCIE devices - i.e. Inside Secure development boards */ - - static int safexcel_pci_probe(struct pci_dev *pdev, -@@ -1759,7 +1886,7 @@ static int safexcel_pci_probe(struct pci - return rc; - } - --void safexcel_pci_remove(struct pci_dev *pdev) -+static void safexcel_pci_remove(struct pci_dev *pdev) - { - struct safexcel_crypto_priv *priv = pci_get_drvdata(pdev); - int i; -@@ -1789,54 +1916,32 @@ static struct pci_driver safexcel_pci_dr - .probe = safexcel_pci_probe, - .remove = safexcel_pci_remove, - }; --#endif -- --/* Unfortunately, we have to resort to global variables here */ --#if IS_ENABLED(CONFIG_PCI) --int pcireg_rc = -EINVAL; /* Default safe value */ --#endif --#if IS_ENABLED(CONFIG_OF) --int ofreg_rc = -EINVAL; /* Default safe value */ --#endif - - static int __init safexcel_init(void) - { --#if IS_ENABLED(CONFIG_PCI) -+ int ret; -+ - /* Register PCI driver */ -- pcireg_rc = pci_register_driver(&safexcel_pci_driver); --#endif -+ ret = pci_register_driver(&safexcel_pci_driver); - --#if IS_ENABLED(CONFIG_OF) - /* Register platform driver */ -- ofreg_rc = platform_driver_register(&crypto_safexcel); -- #if IS_ENABLED(CONFIG_PCI) -- /* Return success if either PCI or OF registered OK */ -- return pcireg_rc ? ofreg_rc : 0; -- #else -- return ofreg_rc; -- #endif --#else -- #if IS_ENABLED(CONFIG_PCI) -- return pcireg_rc; -- #else -- return -EINVAL; -- #endif --#endif -+ if (IS_ENABLED(CONFIG_OF) && !ret) { -+ ret = platform_driver_register(&crypto_safexcel); -+ if (ret) -+ pci_unregister_driver(&safexcel_pci_driver); -+ } -+ -+ return ret; - } - - static void __exit safexcel_exit(void) - { --#if IS_ENABLED(CONFIG_OF) - /* Unregister platform driver */ -- if (!ofreg_rc) -+ if (IS_ENABLED(CONFIG_OF)) - platform_driver_unregister(&crypto_safexcel); --#endif - --#if IS_ENABLED(CONFIG_PCI) - /* Unregister PCI driver if successfully registered before */ -- if (!pcireg_rc) -- pci_unregister_driver(&safexcel_pci_driver); --#endif -+ pci_unregister_driver(&safexcel_pci_driver); - } - - module_init(safexcel_init); ---- a/drivers/crypto/inside-secure/safexcel_cipher.c -+++ b/drivers/crypto/inside-secure/safexcel_cipher.c -@@ -5,18 +5,22 @@ - * Antoine Tenart <antoine.tenart@free-electrons.com> - */ - -+#include <asm/unaligned.h> - #include <linux/device.h> - #include <linux/dma-mapping.h> - #include <linux/dmapool.h> -- - #include <crypto/aead.h> - #include <crypto/aes.h> - #include <crypto/authenc.h> -+#include <crypto/chacha.h> - #include <crypto/ctr.h> - #include <crypto/internal/des.h> - #include <crypto/gcm.h> - #include <crypto/ghash.h> -+#include <crypto/poly1305.h> - #include <crypto/sha.h> -+#include <crypto/sm3.h> -+#include <crypto/sm4.h> - #include <crypto/xts.h> - #include <crypto/skcipher.h> - #include <crypto/internal/aead.h> -@@ -33,6 +37,8 @@ enum safexcel_cipher_alg { - SAFEXCEL_DES, - SAFEXCEL_3DES, - SAFEXCEL_AES, -+ SAFEXCEL_CHACHA20, -+ SAFEXCEL_SM4, - }; - - struct safexcel_cipher_ctx { -@@ -41,8 +47,12 @@ struct safexcel_cipher_ctx { - - u32 mode; - enum safexcel_cipher_alg alg; -- bool aead; -- int xcm; /* 0=authenc, 1=GCM, 2 reserved for CCM */ -+ u8 aead; /* !=0=AEAD, 2=IPSec ESP AEAD, 3=IPsec ESP GMAC */ -+ u8 xcm; /* 0=authenc, 1=GCM, 2 reserved for CCM */ -+ u8 aadskip; -+ u8 blocksz; -+ u32 ivmask; -+ u32 ctrinit; - - __le32 key[16]; - u32 nonce; -@@ -51,10 +61,11 @@ struct safexcel_cipher_ctx { - /* All the below is AEAD specific */ - u32 hash_alg; - u32 state_sz; -- u32 ipad[SHA512_DIGEST_SIZE / sizeof(u32)]; -- u32 opad[SHA512_DIGEST_SIZE / sizeof(u32)]; -+ __be32 ipad[SHA512_DIGEST_SIZE / sizeof(u32)]; -+ __be32 opad[SHA512_DIGEST_SIZE / sizeof(u32)]; - - struct crypto_cipher *hkaes; -+ struct crypto_aead *fback; - }; - - struct safexcel_cipher_req { -@@ -65,206 +76,298 @@ struct safexcel_cipher_req { - int nr_src, nr_dst; - }; - --static void safexcel_cipher_token(struct safexcel_cipher_ctx *ctx, u8 *iv, -- struct safexcel_command_desc *cdesc) -+static int safexcel_skcipher_iv(struct safexcel_cipher_ctx *ctx, u8 *iv, -+ struct safexcel_command_desc *cdesc) - { -- u32 block_sz = 0; -- - if (ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD) { - cdesc->control_data.options |= EIP197_OPTION_4_TOKEN_IV_CMD; -- - /* 32 bit nonce */ - cdesc->control_data.token[0] = ctx->nonce; - /* 64 bit IV part */ - memcpy(&cdesc->control_data.token[1], iv, 8); -- /* 32 bit counter, start at 1 (big endian!) */ -- cdesc->control_data.token[3] = cpu_to_be32(1); -- -- return; -- } else if (ctx->xcm == EIP197_XCM_MODE_GCM) { -- cdesc->control_data.options |= EIP197_OPTION_4_TOKEN_IV_CMD; -- -- /* 96 bit IV part */ -- memcpy(&cdesc->control_data.token[0], iv, 12); -- /* 32 bit counter, start at 1 (big endian!) */ -- cdesc->control_data.token[3] = cpu_to_be32(1); -- -- return; -- } else if (ctx->xcm == EIP197_XCM_MODE_CCM) { -+ /* 32 bit counter, start at 0 or 1 (big endian!) */ -+ cdesc->control_data.token[3] = -+ (__force u32)cpu_to_be32(ctx->ctrinit); -+ return 4; -+ } -+ if (ctx->alg == SAFEXCEL_CHACHA20) { - cdesc->control_data.options |= EIP197_OPTION_4_TOKEN_IV_CMD; -- -- /* Variable length IV part */ -- memcpy(&cdesc->control_data.token[0], iv, 15 - iv[0]); -- /* Start variable length counter at 0 */ -- memset((u8 *)&cdesc->control_data.token[0] + 15 - iv[0], -- 0, iv[0] + 1); -- -- return; -+ /* 96 bit nonce part */ -+ memcpy(&cdesc->control_data.token[0], &iv[4], 12); -+ /* 32 bit counter */ -+ cdesc->control_data.token[3] = *(u32 *)iv; -+ return 4; - } - -- if (ctx->mode != CONTEXT_CONTROL_CRYPTO_MODE_ECB) { -- switch (ctx->alg) { -- case SAFEXCEL_DES: -- block_sz = DES_BLOCK_SIZE; -- cdesc->control_data.options |= EIP197_OPTION_2_TOKEN_IV_CMD; -- break; -- case SAFEXCEL_3DES: -- block_sz = DES3_EDE_BLOCK_SIZE; -- cdesc->control_data.options |= EIP197_OPTION_2_TOKEN_IV_CMD; -- break; -- case SAFEXCEL_AES: -- block_sz = AES_BLOCK_SIZE; -- cdesc->control_data.options |= EIP197_OPTION_4_TOKEN_IV_CMD; -- break; -- } -- memcpy(cdesc->control_data.token, iv, block_sz); -- } -+ cdesc->control_data.options |= ctx->ivmask; -+ memcpy(cdesc->control_data.token, iv, ctx->blocksz); -+ return ctx->blocksz / sizeof(u32); - } - - static void safexcel_skcipher_token(struct safexcel_cipher_ctx *ctx, u8 *iv, - struct safexcel_command_desc *cdesc, -+ struct safexcel_token *atoken, - u32 length) - { - struct safexcel_token *token; -+ int ivlen; - -- safexcel_cipher_token(ctx, iv, cdesc); -- -- /* skip over worst case IV of 4 dwords, no need to be exact */ -- token = (struct safexcel_token *)(cdesc->control_data.token + 4); -+ ivlen = safexcel_skcipher_iv(ctx, iv, cdesc); -+ if (ivlen == 4) { -+ /* No space in cdesc, instruction moves to atoken */ -+ cdesc->additional_cdata_size = 1; -+ token = atoken; -+ } else { -+ /* Everything fits in cdesc */ -+ token = (struct safexcel_token *)(cdesc->control_data.token + 2); -+ /* Need to pad with NOP */ -+ eip197_noop_token(&token[1]); -+ } -+ -+ token->opcode = EIP197_TOKEN_OPCODE_DIRECTION; -+ token->packet_length = length; -+ token->stat = EIP197_TOKEN_STAT_LAST_PACKET | -+ EIP197_TOKEN_STAT_LAST_HASH; -+ token->instructions = EIP197_TOKEN_INS_LAST | -+ EIP197_TOKEN_INS_TYPE_CRYPTO | -+ EIP197_TOKEN_INS_TYPE_OUTPUT; -+} - -- token[0].opcode = EIP197_TOKEN_OPCODE_DIRECTION; -- token[0].packet_length = length; -- token[0].stat = EIP197_TOKEN_STAT_LAST_PACKET | -- EIP197_TOKEN_STAT_LAST_HASH; -- token[0].instructions = EIP197_TOKEN_INS_LAST | -- EIP197_TOKEN_INS_TYPE_CRYPTO | -- EIP197_TOKEN_INS_TYPE_OUTPUT; -+static void safexcel_aead_iv(struct safexcel_cipher_ctx *ctx, u8 *iv, -+ struct safexcel_command_desc *cdesc) -+{ -+ if (ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD || -+ ctx->aead & EIP197_AEAD_TYPE_IPSEC_ESP) { /* _ESP and _ESP_GMAC */ -+ /* 32 bit nonce */ -+ cdesc->control_data.token[0] = ctx->nonce; -+ /* 64 bit IV part */ -+ memcpy(&cdesc->control_data.token[1], iv, 8); -+ /* 32 bit counter, start at 0 or 1 (big endian!) */ -+ cdesc->control_data.token[3] = -+ (__force u32)cpu_to_be32(ctx->ctrinit); -+ return; -+ } -+ if (ctx->xcm == EIP197_XCM_MODE_GCM || ctx->alg == SAFEXCEL_CHACHA20) { -+ /* 96 bit IV part */ -+ memcpy(&cdesc->control_data.token[0], iv, 12); -+ /* 32 bit counter, start at 0 or 1 (big endian!) */ -+ cdesc->control_data.token[3] = -+ (__force u32)cpu_to_be32(ctx->ctrinit); -+ return; -+ } -+ /* CBC */ -+ memcpy(cdesc->control_data.token, iv, ctx->blocksz); - } - - static void safexcel_aead_token(struct safexcel_cipher_ctx *ctx, u8 *iv, - struct safexcel_command_desc *cdesc, -+ struct safexcel_token *atoken, - enum safexcel_cipher_direction direction, - u32 cryptlen, u32 assoclen, u32 digestsize) - { -- struct safexcel_token *token; -+ struct safexcel_token *aadref; -+ int atoksize = 2; /* Start with minimum size */ -+ int assocadj = assoclen - ctx->aadskip, aadalign; - -- safexcel_cipher_token(ctx, iv, cdesc); -+ /* Always 4 dwords of embedded IV for AEAD modes */ -+ cdesc->control_data.options |= EIP197_OPTION_4_TOKEN_IV_CMD; - -- if (direction == SAFEXCEL_ENCRYPT) { -- /* align end of instruction sequence to end of token */ -- token = (struct safexcel_token *)(cdesc->control_data.token + -- EIP197_MAX_TOKENS - 13); -- -- token[12].opcode = EIP197_TOKEN_OPCODE_INSERT; -- token[12].packet_length = digestsize; -- token[12].stat = EIP197_TOKEN_STAT_LAST_HASH | -- EIP197_TOKEN_STAT_LAST_PACKET; -- token[12].instructions = EIP197_TOKEN_INS_TYPE_OUTPUT | -- EIP197_TOKEN_INS_INSERT_HASH_DIGEST; -- } else { -+ if (direction == SAFEXCEL_DECRYPT) - cryptlen -= digestsize; - -- /* align end of instruction sequence to end of token */ -- token = (struct safexcel_token *)(cdesc->control_data.token + -- EIP197_MAX_TOKENS - 14); -- -- token[12].opcode = EIP197_TOKEN_OPCODE_RETRIEVE; -- token[12].packet_length = digestsize; -- token[12].stat = EIP197_TOKEN_STAT_LAST_HASH | -- EIP197_TOKEN_STAT_LAST_PACKET; -- token[12].instructions = EIP197_TOKEN_INS_INSERT_HASH_DIGEST; -- -- token[13].opcode = EIP197_TOKEN_OPCODE_VERIFY; -- token[13].packet_length = digestsize | -- EIP197_TOKEN_HASH_RESULT_VERIFY; -- token[13].stat = EIP197_TOKEN_STAT_LAST_HASH | -- EIP197_TOKEN_STAT_LAST_PACKET; -- token[13].instructions = EIP197_TOKEN_INS_TYPE_OUTPUT; -- } -- -- token[6].opcode = EIP197_TOKEN_OPCODE_DIRECTION; -- token[6].packet_length = assoclen; -- -- if (likely(cryptlen)) { -- token[6].instructions = EIP197_TOKEN_INS_TYPE_HASH; -- -- token[10].opcode = EIP197_TOKEN_OPCODE_DIRECTION; -- token[10].packet_length = cryptlen; -- token[10].stat = EIP197_TOKEN_STAT_LAST_HASH; -- token[10].instructions = EIP197_TOKEN_INS_LAST | -- EIP197_TOKEN_INS_TYPE_CRYPTO | -- EIP197_TOKEN_INS_TYPE_HASH | -- EIP197_TOKEN_INS_TYPE_OUTPUT; -- } else if (ctx->xcm != EIP197_XCM_MODE_CCM) { -- token[6].stat = EIP197_TOKEN_STAT_LAST_HASH; -- token[6].instructions = EIP197_TOKEN_INS_LAST | -- EIP197_TOKEN_INS_TYPE_HASH; -- } -- -- if (!ctx->xcm) -- return; -- -- token[8].opcode = EIP197_TOKEN_OPCODE_INSERT_REMRES; -- token[8].packet_length = 0; -- token[8].instructions = AES_BLOCK_SIZE; -- -- token[9].opcode = EIP197_TOKEN_OPCODE_INSERT; -- token[9].packet_length = AES_BLOCK_SIZE; -- token[9].instructions = EIP197_TOKEN_INS_TYPE_OUTPUT | -- EIP197_TOKEN_INS_TYPE_CRYPTO; -- -- if (ctx->xcm == EIP197_XCM_MODE_GCM) { -- token[6].instructions = EIP197_TOKEN_INS_LAST | -- EIP197_TOKEN_INS_TYPE_HASH; -- } else { -- u8 *cbcmaciv = (u8 *)&token[1]; -- u32 *aadlen = (u32 *)&token[5]; -- -+ if (unlikely(ctx->xcm == EIP197_XCM_MODE_CCM)) { - /* Construct IV block B0 for the CBC-MAC */ -- token[0].opcode = EIP197_TOKEN_OPCODE_INSERT; -- token[0].packet_length = AES_BLOCK_SIZE + -- ((assoclen > 0) << 1); -- token[0].instructions = EIP197_TOKEN_INS_ORIGIN_TOKEN | -- EIP197_TOKEN_INS_TYPE_HASH; -- /* Variable length IV part */ -- memcpy(cbcmaciv, iv, 15 - iv[0]); -- /* fixup flags byte */ -- cbcmaciv[0] |= ((assoclen > 0) << 6) | ((digestsize - 2) << 2); -- /* Clear upper bytes of variable message length to 0 */ -- memset(cbcmaciv + 15 - iv[0], 0, iv[0] - 1); -- /* insert lower 2 bytes of message length */ -- cbcmaciv[14] = cryptlen >> 8; -- cbcmaciv[15] = cryptlen & 255; -- -- if (assoclen) { -- *aadlen = cpu_to_le32(cpu_to_be16(assoclen)); -- assoclen += 2; -+ u8 *final_iv = (u8 *)cdesc->control_data.token; -+ u8 *cbcmaciv = (u8 *)&atoken[1]; -+ __le32 *aadlen = (__le32 *)&atoken[5]; -+ -+ if (ctx->aead == EIP197_AEAD_TYPE_IPSEC_ESP) { -+ /* Length + nonce */ -+ cdesc->control_data.token[0] = ctx->nonce; -+ /* Fixup flags byte */ -+ *(__le32 *)cbcmaciv = -+ cpu_to_le32(ctx->nonce | -+ ((assocadj > 0) << 6) | -+ ((digestsize - 2) << 2)); -+ /* 64 bit IV part */ -+ memcpy(&cdesc->control_data.token[1], iv, 8); -+ memcpy(cbcmaciv + 4, iv, 8); -+ /* Start counter at 0 */ -+ cdesc->control_data.token[3] = 0; -+ /* Message length */ -+ *(__be32 *)(cbcmaciv + 12) = cpu_to_be32(cryptlen); -+ } else { -+ /* Variable length IV part */ -+ memcpy(final_iv, iv, 15 - iv[0]); -+ memcpy(cbcmaciv, iv, 15 - iv[0]); -+ /* Start variable length counter at 0 */ -+ memset(final_iv + 15 - iv[0], 0, iv[0] + 1); -+ memset(cbcmaciv + 15 - iv[0], 0, iv[0] - 1); -+ /* fixup flags byte */ -+ cbcmaciv[0] |= ((assocadj > 0) << 6) | -+ ((digestsize - 2) << 2); -+ /* insert lower 2 bytes of message length */ -+ cbcmaciv[14] = cryptlen >> 8; -+ cbcmaciv[15] = cryptlen & 255; -+ } -+ -+ atoken->opcode = EIP197_TOKEN_OPCODE_INSERT; -+ atoken->packet_length = AES_BLOCK_SIZE + -+ ((assocadj > 0) << 1); -+ atoken->stat = 0; -+ atoken->instructions = EIP197_TOKEN_INS_ORIGIN_TOKEN | -+ EIP197_TOKEN_INS_TYPE_HASH; -+ -+ if (likely(assocadj)) { -+ *aadlen = cpu_to_le32((assocadj >> 8) | -+ (assocadj & 255) << 8); -+ atoken += 6; -+ atoksize += 7; -+ } else { -+ atoken += 5; -+ atoksize += 6; - } - -- token[6].instructions = EIP197_TOKEN_INS_TYPE_HASH; -- -- /* Align AAD data towards hash engine */ -- token[7].opcode = EIP197_TOKEN_OPCODE_INSERT; -- assoclen &= 15; -- token[7].packet_length = assoclen ? 16 - assoclen : 0; -- -+ /* Process AAD data */ -+ aadref = atoken; -+ atoken->opcode = EIP197_TOKEN_OPCODE_DIRECTION; -+ atoken->packet_length = assocadj; -+ atoken->stat = 0; -+ atoken->instructions = EIP197_TOKEN_INS_TYPE_HASH; -+ atoken++; -+ -+ /* For CCM only, align AAD data towards hash engine */ -+ atoken->opcode = EIP197_TOKEN_OPCODE_INSERT; -+ aadalign = (assocadj + 2) & 15; -+ atoken->packet_length = assocadj && aadalign ? -+ 16 - aadalign : -+ 0; - if (likely(cryptlen)) { -- token[7].instructions = EIP197_TOKEN_INS_TYPE_HASH; -- -- /* Align crypto data towards hash engine */ -- token[10].stat = 0; -+ atoken->stat = 0; -+ atoken->instructions = EIP197_TOKEN_INS_TYPE_HASH; -+ } else { -+ atoken->stat = EIP197_TOKEN_STAT_LAST_HASH; -+ atoken->instructions = EIP197_TOKEN_INS_LAST | -+ EIP197_TOKEN_INS_TYPE_HASH; -+ } -+ } else { -+ safexcel_aead_iv(ctx, iv, cdesc); - -- token[11].opcode = EIP197_TOKEN_OPCODE_INSERT; -- cryptlen &= 15; -- token[11].packet_length = cryptlen ? 16 - cryptlen : 0; -- token[11].stat = EIP197_TOKEN_STAT_LAST_HASH; -- token[11].instructions = EIP197_TOKEN_INS_TYPE_HASH; -+ /* Process AAD data */ -+ aadref = atoken; -+ atoken->opcode = EIP197_TOKEN_OPCODE_DIRECTION; -+ atoken->packet_length = assocadj; -+ atoken->stat = EIP197_TOKEN_STAT_LAST_HASH; -+ atoken->instructions = EIP197_TOKEN_INS_LAST | -+ EIP197_TOKEN_INS_TYPE_HASH; -+ } -+ atoken++; -+ -+ if (ctx->aead == EIP197_AEAD_TYPE_IPSEC_ESP) { -+ /* For ESP mode (and not GMAC), skip over the IV */ -+ atoken->opcode = EIP197_TOKEN_OPCODE_DIRECTION; -+ atoken->packet_length = EIP197_AEAD_IPSEC_IV_SIZE; -+ atoken->stat = 0; -+ atoken->instructions = 0; -+ atoken++; -+ atoksize++; -+ } else if (unlikely(ctx->alg == SAFEXCEL_CHACHA20 && -+ direction == SAFEXCEL_DECRYPT)) { -+ /* Poly-chacha decryption needs a dummy NOP here ... */ -+ atoken->opcode = EIP197_TOKEN_OPCODE_INSERT; -+ atoken->packet_length = 16; /* According to Op Manual */ -+ atoken->stat = 0; -+ atoken->instructions = 0; -+ atoken++; -+ atoksize++; -+ } -+ -+ if (ctx->xcm) { -+ /* For GCM and CCM, obtain enc(Y0) */ -+ atoken->opcode = EIP197_TOKEN_OPCODE_INSERT_REMRES; -+ atoken->packet_length = 0; -+ atoken->stat = 0; -+ atoken->instructions = AES_BLOCK_SIZE; -+ atoken++; -+ -+ atoken->opcode = EIP197_TOKEN_OPCODE_INSERT; -+ atoken->packet_length = AES_BLOCK_SIZE; -+ atoken->stat = 0; -+ atoken->instructions = EIP197_TOKEN_INS_TYPE_OUTPUT | -+ EIP197_TOKEN_INS_TYPE_CRYPTO; -+ atoken++; -+ atoksize += 2; -+ } -+ -+ if (likely(cryptlen || ctx->alg == SAFEXCEL_CHACHA20)) { -+ /* Fixup stat field for AAD direction instruction */ -+ aadref->stat = 0; -+ -+ /* Process crypto data */ -+ atoken->opcode = EIP197_TOKEN_OPCODE_DIRECTION; -+ atoken->packet_length = cryptlen; -+ -+ if (unlikely(ctx->aead == EIP197_AEAD_TYPE_IPSEC_ESP_GMAC)) { -+ /* Fixup instruction field for AAD dir instruction */ -+ aadref->instructions = EIP197_TOKEN_INS_TYPE_HASH; -+ -+ /* Do not send to crypt engine in case of GMAC */ -+ atoken->instructions = EIP197_TOKEN_INS_LAST | -+ EIP197_TOKEN_INS_TYPE_HASH | -+ EIP197_TOKEN_INS_TYPE_OUTPUT; -+ } else { -+ atoken->instructions = EIP197_TOKEN_INS_LAST | -+ EIP197_TOKEN_INS_TYPE_CRYPTO | -+ EIP197_TOKEN_INS_TYPE_HASH | -+ EIP197_TOKEN_INS_TYPE_OUTPUT; -+ } -+ -+ cryptlen &= 15; -+ if (unlikely(ctx->xcm == EIP197_XCM_MODE_CCM && cryptlen)) { -+ atoken->stat = 0; -+ /* For CCM only, pad crypto data to the hash engine */ -+ atoken++; -+ atoksize++; -+ atoken->opcode = EIP197_TOKEN_OPCODE_INSERT; -+ atoken->packet_length = 16 - cryptlen; -+ atoken->stat = EIP197_TOKEN_STAT_LAST_HASH; -+ atoken->instructions = EIP197_TOKEN_INS_TYPE_HASH; - } else { -- token[7].stat = EIP197_TOKEN_STAT_LAST_HASH; -- token[7].instructions = EIP197_TOKEN_INS_LAST | -- EIP197_TOKEN_INS_TYPE_HASH; -+ atoken->stat = EIP197_TOKEN_STAT_LAST_HASH; - } -+ atoken++; -+ atoksize++; - } -+ -+ if (direction == SAFEXCEL_ENCRYPT) { -+ /* Append ICV */ -+ atoken->opcode = EIP197_TOKEN_OPCODE_INSERT; -+ atoken->packet_length = digestsize; -+ atoken->stat = EIP197_TOKEN_STAT_LAST_HASH | -+ EIP197_TOKEN_STAT_LAST_PACKET; -+ atoken->instructions = EIP197_TOKEN_INS_TYPE_OUTPUT | -+ EIP197_TOKEN_INS_INSERT_HASH_DIGEST; -+ } else { -+ /* Extract ICV */ -+ atoken->opcode = EIP197_TOKEN_OPCODE_RETRIEVE; -+ atoken->packet_length = digestsize; -+ atoken->stat = EIP197_TOKEN_STAT_LAST_HASH | -+ EIP197_TOKEN_STAT_LAST_PACKET; -+ atoken->instructions = EIP197_TOKEN_INS_INSERT_HASH_DIGEST; -+ atoken++; -+ atoksize++; -+ -+ /* Verify ICV */ -+ atoken->opcode = EIP197_TOKEN_OPCODE_VERIFY; -+ atoken->packet_length = digestsize | -+ EIP197_TOKEN_HASH_RESULT_VERIFY; -+ atoken->stat = EIP197_TOKEN_STAT_LAST_HASH | -+ EIP197_TOKEN_STAT_LAST_PACKET; -+ atoken->instructions = EIP197_TOKEN_INS_TYPE_OUTPUT; -+ } -+ -+ /* Fixup length of the token in the command descriptor */ -+ cdesc->additional_cdata_size = atoksize; - } - - static int safexcel_skcipher_aes_setkey(struct crypto_skcipher *ctfm, -@@ -277,14 +380,12 @@ static int safexcel_skcipher_aes_setkey( - int ret, i; - - ret = aes_expandkey(&aes, key, len); -- if (ret) { -- crypto_skcipher_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN); -+ if (ret) - return ret; -- } - - if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) { - for (i = 0; i < len / sizeof(u32); i++) { -- if (ctx->key[i] != cpu_to_le32(aes.key_enc[i])) { -+ if (le32_to_cpu(ctx->key[i]) != aes.key_enc[i]) { - ctx->base.needs_inv = true; - break; - } -@@ -309,43 +410,57 @@ static int safexcel_aead_setkey(struct c - struct safexcel_crypto_priv *priv = ctx->priv; - struct crypto_authenc_keys keys; - struct crypto_aes_ctx aes; -- int err = -EINVAL; -+ int err = -EINVAL, i; - -- if (crypto_authenc_extractkeys(&keys, key, len) != 0) -+ if (unlikely(crypto_authenc_extractkeys(&keys, key, len))) - goto badkey; - - if (ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD) { -- /* Minimum keysize is minimum AES key size + nonce size */ -- if (keys.enckeylen < (AES_MIN_KEY_SIZE + -- CTR_RFC3686_NONCE_SIZE)) -+ /* Must have at least space for the nonce here */ -+ if (unlikely(keys.enckeylen < CTR_RFC3686_NONCE_SIZE)) - goto badkey; - /* last 4 bytes of key are the nonce! */ - ctx->nonce = *(u32 *)(keys.enckey + keys.enckeylen - - CTR_RFC3686_NONCE_SIZE); - /* exclude the nonce here */ -- keys.enckeylen -= CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD; -+ keys.enckeylen -= CTR_RFC3686_NONCE_SIZE; - } - - /* Encryption key */ - switch (ctx->alg) { -+ case SAFEXCEL_DES: -+ err = verify_aead_des_key(ctfm, keys.enckey, keys.enckeylen); -+ if (unlikely(err)) -+ goto badkey; -+ break; - case SAFEXCEL_3DES: - err = verify_aead_des3_key(ctfm, keys.enckey, keys.enckeylen); - if (unlikely(err)) -- goto badkey_expflags; -+ goto badkey; - break; - case SAFEXCEL_AES: - err = aes_expandkey(&aes, keys.enckey, keys.enckeylen); - if (unlikely(err)) - goto badkey; - break; -+ case SAFEXCEL_SM4: -+ if (unlikely(keys.enckeylen != SM4_KEY_SIZE)) -+ goto badkey; -+ break; - default: - dev_err(priv->dev, "aead: unsupported cipher algorithm\n"); - goto badkey; - } - -- if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma && -- memcmp(ctx->key, keys.enckey, keys.enckeylen)) -- ctx->base.needs_inv = true; -+ if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) { -+ for (i = 0; i < keys.enckeylen / sizeof(u32); i++) { -+ if (le32_to_cpu(ctx->key[i]) != -+ ((u32 *)keys.enckey)[i]) { -+ ctx->base.needs_inv = true; -+ break; -+ } -+ } -+ } - - /* Auth key */ - switch (ctx->hash_alg) { -@@ -374,21 +489,24 @@ static int safexcel_aead_setkey(struct c - keys.authkeylen, &istate, &ostate)) - goto badkey; - break; -+ case CONTEXT_CONTROL_CRYPTO_ALG_SM3: -+ if (safexcel_hmac_setkey("safexcel-sm3", keys.authkey, -+ keys.authkeylen, &istate, &ostate)) -+ goto badkey; -+ break; - default: - dev_err(priv->dev, "aead: unsupported hash algorithm\n"); - goto badkey; - } - -- crypto_aead_set_flags(ctfm, crypto_aead_get_flags(ctfm) & -- CRYPTO_TFM_RES_MASK); -- - if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma && - (memcmp(ctx->ipad, istate.state, ctx->state_sz) || - memcmp(ctx->opad, ostate.state, ctx->state_sz))) - ctx->base.needs_inv = true; - - /* Now copy the keys into the context */ -- memcpy(ctx->key, keys.enckey, keys.enckeylen); -+ for (i = 0; i < keys.enckeylen / sizeof(u32); i++) -+ ctx->key[i] = cpu_to_le32(((u32 *)keys.enckey)[i]); - ctx->key_len = keys.enckeylen; - - memcpy(ctx->ipad, &istate.state, ctx->state_sz); -@@ -398,8 +516,6 @@ static int safexcel_aead_setkey(struct c - return 0; - - badkey: -- crypto_aead_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN); --badkey_expflags: - memzero_explicit(&keys, sizeof(keys)); - return err; - } -@@ -423,6 +539,17 @@ static int safexcel_context_control(stru - CONTEXT_CONTROL_DIGEST_XCM | - ctx->hash_alg | - CONTEXT_CONTROL_SIZE(ctrl_size); -+ } else if (ctx->alg == SAFEXCEL_CHACHA20) { -+ /* Chacha20-Poly1305 */ -+ cdesc->control_data.control0 = -+ CONTEXT_CONTROL_KEY_EN | -+ CONTEXT_CONTROL_CRYPTO_ALG_CHACHA20 | -+ (sreq->direction == SAFEXCEL_ENCRYPT ? -+ CONTEXT_CONTROL_TYPE_ENCRYPT_HASH_OUT : -+ CONTEXT_CONTROL_TYPE_HASH_DECRYPT_IN) | -+ ctx->hash_alg | -+ CONTEXT_CONTROL_SIZE(ctrl_size); -+ return 0; - } else { - ctrl_size += ctx->state_sz / sizeof(u32) * 2; - cdesc->control_data.control0 = -@@ -431,17 +558,21 @@ static int safexcel_context_control(stru - ctx->hash_alg | - CONTEXT_CONTROL_SIZE(ctrl_size); - } -- if (sreq->direction == SAFEXCEL_ENCRYPT) -- cdesc->control_data.control0 |= -- (ctx->xcm == EIP197_XCM_MODE_CCM) ? -- CONTEXT_CONTROL_TYPE_HASH_ENCRYPT_OUT : -- CONTEXT_CONTROL_TYPE_ENCRYPT_HASH_OUT; - -+ if (sreq->direction == SAFEXCEL_ENCRYPT && -+ (ctx->xcm == EIP197_XCM_MODE_CCM || -+ ctx->aead == EIP197_AEAD_TYPE_IPSEC_ESP_GMAC)) -+ cdesc->control_data.control0 |= -+ CONTEXT_CONTROL_TYPE_HASH_ENCRYPT_OUT; -+ else if (sreq->direction == SAFEXCEL_ENCRYPT) -+ cdesc->control_data.control0 |= -+ CONTEXT_CONTROL_TYPE_ENCRYPT_HASH_OUT; -+ else if (ctx->xcm == EIP197_XCM_MODE_CCM) -+ cdesc->control_data.control0 |= -+ CONTEXT_CONTROL_TYPE_DECRYPT_HASH_IN; - else - cdesc->control_data.control0 |= -- (ctx->xcm == EIP197_XCM_MODE_CCM) ? -- CONTEXT_CONTROL_TYPE_DECRYPT_HASH_IN : -- CONTEXT_CONTROL_TYPE_HASH_DECRYPT_IN; -+ CONTEXT_CONTROL_TYPE_HASH_DECRYPT_IN; - } else { - if (sreq->direction == SAFEXCEL_ENCRYPT) - cdesc->control_data.control0 = -@@ -480,6 +611,12 @@ static int safexcel_context_control(stru - ctx->key_len >> ctx->xts); - return -EINVAL; - } -+ } else if (ctx->alg == SAFEXCEL_CHACHA20) { -+ cdesc->control_data.control0 |= -+ CONTEXT_CONTROL_CRYPTO_ALG_CHACHA20; -+ } else if (ctx->alg == SAFEXCEL_SM4) { -+ cdesc->control_data.control0 |= -+ CONTEXT_CONTROL_CRYPTO_ALG_SM4; - } - - return 0; -@@ -563,6 +700,7 @@ static int safexcel_send_req(struct cryp - unsigned int totlen; - unsigned int totlen_src = cryptlen + assoclen; - unsigned int totlen_dst = totlen_src; -+ struct safexcel_token *atoken; - int n_cdesc = 0, n_rdesc = 0; - int queued, i, ret = 0; - bool first = true; -@@ -637,56 +775,60 @@ static int safexcel_send_req(struct cryp - - memcpy(ctx->base.ctxr->data, ctx->key, ctx->key_len); - -- /* The EIP cannot deal with zero length input packets! */ -- if (totlen == 0) -- totlen = 1; -+ if (!totlen) { -+ /* -+ * The EIP97 cannot deal with zero length input packets! -+ * So stuff a dummy command descriptor indicating a 1 byte -+ * (dummy) input packet, using the context record as source. -+ */ -+ first_cdesc = safexcel_add_cdesc(priv, ring, -+ 1, 1, ctx->base.ctxr_dma, -+ 1, 1, ctx->base.ctxr_dma, -+ &atoken); -+ if (IS_ERR(first_cdesc)) { -+ /* No space left in the command descriptor ring */ -+ ret = PTR_ERR(first_cdesc); -+ goto cdesc_rollback; -+ } -+ n_cdesc = 1; -+ goto skip_cdesc; -+ } - - /* command descriptors */ - for_each_sg(src, sg, sreq->nr_src, i) { - int len = sg_dma_len(sg); - - /* Do not overflow the request */ -- if (queued - len < 0) -+ if (queued < len) - len = queued; - - cdesc = safexcel_add_cdesc(priv, ring, !n_cdesc, - !(queued - len), - sg_dma_address(sg), len, totlen, -- ctx->base.ctxr_dma); -+ ctx->base.ctxr_dma, &atoken); - if (IS_ERR(cdesc)) { - /* No space left in the command descriptor ring */ - ret = PTR_ERR(cdesc); - goto cdesc_rollback; - } -- n_cdesc++; - -- if (n_cdesc == 1) { -+ if (!n_cdesc) - first_cdesc = cdesc; -- } - -+ n_cdesc++; - queued -= len; - if (!queued) - break; - } -- -- if (unlikely(!n_cdesc)) { -- /* -- * Special case: zero length input buffer. -- * The engine always needs the 1st command descriptor, however! -- */ -- first_cdesc = safexcel_add_cdesc(priv, ring, 1, 1, 0, 0, totlen, -- ctx->base.ctxr_dma); -- n_cdesc = 1; -- } -- -+skip_cdesc: - /* Add context control words and token to first command descriptor */ - safexcel_context_control(ctx, base, sreq, first_cdesc); - if (ctx->aead) -- safexcel_aead_token(ctx, iv, first_cdesc, -+ safexcel_aead_token(ctx, iv, first_cdesc, atoken, - sreq->direction, cryptlen, - assoclen, digestsize); - else -- safexcel_skcipher_token(ctx, iv, first_cdesc, -+ safexcel_skcipher_token(ctx, iv, first_cdesc, atoken, - cryptlen); - - /* result descriptors */ -@@ -1073,6 +1215,8 @@ static int safexcel_skcipher_cra_init(st - - ctx->base.send = safexcel_skcipher_send; - ctx->base.handle_result = safexcel_skcipher_handle_result; -+ ctx->ivmask = EIP197_OPTION_4_TOKEN_IV_CMD; -+ ctx->ctrinit = 1; - return 0; - } - -@@ -1137,6 +1281,8 @@ static int safexcel_skcipher_aes_ecb_cra - safexcel_skcipher_cra_init(tfm); - ctx->alg = SAFEXCEL_AES; - ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_ECB; -+ ctx->blocksz = 0; -+ ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD; - return 0; - } - -@@ -1171,6 +1317,7 @@ static int safexcel_skcipher_aes_cbc_cra - - safexcel_skcipher_cra_init(tfm); - ctx->alg = SAFEXCEL_AES; -+ ctx->blocksz = AES_BLOCK_SIZE; - ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CBC; - return 0; - } -@@ -1207,6 +1354,7 @@ static int safexcel_skcipher_aes_cfb_cra - - safexcel_skcipher_cra_init(tfm); - ctx->alg = SAFEXCEL_AES; -+ ctx->blocksz = AES_BLOCK_SIZE; - ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CFB; - return 0; - } -@@ -1243,6 +1391,7 @@ static int safexcel_skcipher_aes_ofb_cra - - safexcel_skcipher_cra_init(tfm); - ctx->alg = SAFEXCEL_AES; -+ ctx->blocksz = AES_BLOCK_SIZE; - ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_OFB; - return 0; - } -@@ -1288,14 +1437,12 @@ static int safexcel_skcipher_aesctr_setk - /* exclude the nonce here */ - keylen = len - CTR_RFC3686_NONCE_SIZE; - ret = aes_expandkey(&aes, key, keylen); -- if (ret) { -- crypto_skcipher_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN); -+ if (ret) - return ret; -- } - - if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) { - for (i = 0; i < keylen / sizeof(u32); i++) { -- if (ctx->key[i] != cpu_to_le32(aes.key_enc[i])) { -+ if (le32_to_cpu(ctx->key[i]) != aes.key_enc[i]) { - ctx->base.needs_inv = true; - break; - } -@@ -1317,6 +1464,7 @@ static int safexcel_skcipher_aes_ctr_cra - - safexcel_skcipher_cra_init(tfm); - ctx->alg = SAFEXCEL_AES; -+ ctx->blocksz = AES_BLOCK_SIZE; - ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD; - return 0; - } -@@ -1352,6 +1500,7 @@ static int safexcel_des_setkey(struct cr - unsigned int len) - { - struct safexcel_cipher_ctx *ctx = crypto_skcipher_ctx(ctfm); -+ struct safexcel_crypto_priv *priv = ctx->priv; - int ret; - - ret = verify_skcipher_des_key(ctfm, key); -@@ -1359,7 +1508,7 @@ static int safexcel_des_setkey(struct cr - return ret; - - /* if context exits and key changed, need to invalidate it */ -- if (ctx->base.ctxr_dma) -+ if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) - if (memcmp(ctx->key, key, len)) - ctx->base.needs_inv = true; - -@@ -1375,6 +1524,8 @@ static int safexcel_skcipher_des_cbc_cra - - safexcel_skcipher_cra_init(tfm); - ctx->alg = SAFEXCEL_DES; -+ ctx->blocksz = DES_BLOCK_SIZE; -+ ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD; - ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CBC; - return 0; - } -@@ -1412,6 +1563,8 @@ static int safexcel_skcipher_des_ecb_cra - safexcel_skcipher_cra_init(tfm); - ctx->alg = SAFEXCEL_DES; - ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_ECB; -+ ctx->blocksz = 0; -+ ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD; - return 0; - } - -@@ -1444,6 +1597,7 @@ static int safexcel_des3_ede_setkey(stru - const u8 *key, unsigned int len) - { - struct safexcel_cipher_ctx *ctx = crypto_skcipher_ctx(ctfm); -+ struct safexcel_crypto_priv *priv = ctx->priv; - int err; - - err = verify_skcipher_des3_key(ctfm, key); -@@ -1451,13 +1605,11 @@ static int safexcel_des3_ede_setkey(stru - return err; - - /* if context exits and key changed, need to invalidate it */ -- if (ctx->base.ctxr_dma) { -+ if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) - if (memcmp(ctx->key, key, len)) - ctx->base.needs_inv = true; -- } - - memcpy(ctx->key, key, len); -- - ctx->key_len = len; - - return 0; -@@ -1469,6 +1621,8 @@ static int safexcel_skcipher_des3_cbc_cr - - safexcel_skcipher_cra_init(tfm); - ctx->alg = SAFEXCEL_3DES; -+ ctx->blocksz = DES3_EDE_BLOCK_SIZE; -+ ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD; - ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CBC; - return 0; - } -@@ -1506,6 +1660,8 @@ static int safexcel_skcipher_des3_ecb_cr - safexcel_skcipher_cra_init(tfm); - ctx->alg = SAFEXCEL_3DES; - ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_ECB; -+ ctx->blocksz = 0; -+ ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD; - return 0; - } - -@@ -1561,6 +1717,9 @@ static int safexcel_aead_cra_init(struct - ctx->priv = tmpl->priv; - - ctx->alg = SAFEXCEL_AES; /* default */ -+ ctx->blocksz = AES_BLOCK_SIZE; -+ ctx->ivmask = EIP197_OPTION_4_TOKEN_IV_CMD; -+ ctx->ctrinit = 1; - ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CBC; /* default */ - ctx->aead = true; - ctx->base.send = safexcel_aead_send; -@@ -1749,6 +1908,8 @@ static int safexcel_aead_sha1_des3_cra_i - - safexcel_aead_sha1_cra_init(tfm); - ctx->alg = SAFEXCEL_3DES; /* override default */ -+ ctx->blocksz = DES3_EDE_BLOCK_SIZE; -+ ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD; - return 0; - } - -@@ -1777,6 +1938,330 @@ struct safexcel_alg_template safexcel_al - }, - }; - -+static int safexcel_aead_sha256_des3_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_aead_sha256_cra_init(tfm); -+ ctx->alg = SAFEXCEL_3DES; /* override default */ -+ ctx->blocksz = DES3_EDE_BLOCK_SIZE; -+ ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD; -+ return 0; -+} -+ -+struct safexcel_alg_template safexcel_alg_authenc_hmac_sha256_cbc_des3_ede = { -+ .type = SAFEXCEL_ALG_TYPE_AEAD, -+ .algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_256, -+ .alg.aead = { -+ .setkey = safexcel_aead_setkey, -+ .encrypt = safexcel_aead_encrypt, -+ .decrypt = safexcel_aead_decrypt, -+ .ivsize = DES3_EDE_BLOCK_SIZE, -+ .maxauthsize = SHA256_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(sha256),cbc(des3_ede))", -+ .cra_driver_name = "safexcel-authenc-hmac-sha256-cbc-des3_ede", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = DES3_EDE_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_aead_sha256_des3_cra_init, -+ .cra_exit = safexcel_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+static int safexcel_aead_sha224_des3_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_aead_sha224_cra_init(tfm); -+ ctx->alg = SAFEXCEL_3DES; /* override default */ -+ ctx->blocksz = DES3_EDE_BLOCK_SIZE; -+ ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD; -+ return 0; -+} -+ -+struct safexcel_alg_template safexcel_alg_authenc_hmac_sha224_cbc_des3_ede = { -+ .type = SAFEXCEL_ALG_TYPE_AEAD, -+ .algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_256, -+ .alg.aead = { -+ .setkey = safexcel_aead_setkey, -+ .encrypt = safexcel_aead_encrypt, -+ .decrypt = safexcel_aead_decrypt, -+ .ivsize = DES3_EDE_BLOCK_SIZE, -+ .maxauthsize = SHA224_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(sha224),cbc(des3_ede))", -+ .cra_driver_name = "safexcel-authenc-hmac-sha224-cbc-des3_ede", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = DES3_EDE_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_aead_sha224_des3_cra_init, -+ .cra_exit = safexcel_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+static int safexcel_aead_sha512_des3_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_aead_sha512_cra_init(tfm); -+ ctx->alg = SAFEXCEL_3DES; /* override default */ -+ ctx->blocksz = DES3_EDE_BLOCK_SIZE; -+ ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD; -+ return 0; -+} -+ -+struct safexcel_alg_template safexcel_alg_authenc_hmac_sha512_cbc_des3_ede = { -+ .type = SAFEXCEL_ALG_TYPE_AEAD, -+ .algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_512, -+ .alg.aead = { -+ .setkey = safexcel_aead_setkey, -+ .encrypt = safexcel_aead_encrypt, -+ .decrypt = safexcel_aead_decrypt, -+ .ivsize = DES3_EDE_BLOCK_SIZE, -+ .maxauthsize = SHA512_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(sha512),cbc(des3_ede))", -+ .cra_driver_name = "safexcel-authenc-hmac-sha512-cbc-des3_ede", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = DES3_EDE_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_aead_sha512_des3_cra_init, -+ .cra_exit = safexcel_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+static int safexcel_aead_sha384_des3_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_aead_sha384_cra_init(tfm); -+ ctx->alg = SAFEXCEL_3DES; /* override default */ -+ ctx->blocksz = DES3_EDE_BLOCK_SIZE; -+ ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD; -+ return 0; -+} -+ -+struct safexcel_alg_template safexcel_alg_authenc_hmac_sha384_cbc_des3_ede = { -+ .type = SAFEXCEL_ALG_TYPE_AEAD, -+ .algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_512, -+ .alg.aead = { -+ .setkey = safexcel_aead_setkey, -+ .encrypt = safexcel_aead_encrypt, -+ .decrypt = safexcel_aead_decrypt, -+ .ivsize = DES3_EDE_BLOCK_SIZE, -+ .maxauthsize = SHA384_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(sha384),cbc(des3_ede))", -+ .cra_driver_name = "safexcel-authenc-hmac-sha384-cbc-des3_ede", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = DES3_EDE_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_aead_sha384_des3_cra_init, -+ .cra_exit = safexcel_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+static int safexcel_aead_sha1_des_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_aead_sha1_cra_init(tfm); -+ ctx->alg = SAFEXCEL_DES; /* override default */ -+ ctx->blocksz = DES_BLOCK_SIZE; -+ ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD; -+ return 0; -+} -+ -+struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_cbc_des = { -+ .type = SAFEXCEL_ALG_TYPE_AEAD, -+ .algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA1, -+ .alg.aead = { -+ .setkey = safexcel_aead_setkey, -+ .encrypt = safexcel_aead_encrypt, -+ .decrypt = safexcel_aead_decrypt, -+ .ivsize = DES_BLOCK_SIZE, -+ .maxauthsize = SHA1_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(sha1),cbc(des))", -+ .cra_driver_name = "safexcel-authenc-hmac-sha1-cbc-des", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = DES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_aead_sha1_des_cra_init, -+ .cra_exit = safexcel_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+static int safexcel_aead_sha256_des_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_aead_sha256_cra_init(tfm); -+ ctx->alg = SAFEXCEL_DES; /* override default */ -+ ctx->blocksz = DES_BLOCK_SIZE; -+ ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD; -+ return 0; -+} -+ -+struct safexcel_alg_template safexcel_alg_authenc_hmac_sha256_cbc_des = { -+ .type = SAFEXCEL_ALG_TYPE_AEAD, -+ .algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_256, -+ .alg.aead = { -+ .setkey = safexcel_aead_setkey, -+ .encrypt = safexcel_aead_encrypt, -+ .decrypt = safexcel_aead_decrypt, -+ .ivsize = DES_BLOCK_SIZE, -+ .maxauthsize = SHA256_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(sha256),cbc(des))", -+ .cra_driver_name = "safexcel-authenc-hmac-sha256-cbc-des", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = DES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_aead_sha256_des_cra_init, -+ .cra_exit = safexcel_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+static int safexcel_aead_sha224_des_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_aead_sha224_cra_init(tfm); -+ ctx->alg = SAFEXCEL_DES; /* override default */ -+ ctx->blocksz = DES_BLOCK_SIZE; -+ ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD; -+ return 0; -+} -+ -+struct safexcel_alg_template safexcel_alg_authenc_hmac_sha224_cbc_des = { -+ .type = SAFEXCEL_ALG_TYPE_AEAD, -+ .algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_256, -+ .alg.aead = { -+ .setkey = safexcel_aead_setkey, -+ .encrypt = safexcel_aead_encrypt, -+ .decrypt = safexcel_aead_decrypt, -+ .ivsize = DES_BLOCK_SIZE, -+ .maxauthsize = SHA224_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(sha224),cbc(des))", -+ .cra_driver_name = "safexcel-authenc-hmac-sha224-cbc-des", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = DES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_aead_sha224_des_cra_init, -+ .cra_exit = safexcel_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+static int safexcel_aead_sha512_des_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_aead_sha512_cra_init(tfm); -+ ctx->alg = SAFEXCEL_DES; /* override default */ -+ ctx->blocksz = DES_BLOCK_SIZE; -+ ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD; -+ return 0; -+} -+ -+struct safexcel_alg_template safexcel_alg_authenc_hmac_sha512_cbc_des = { -+ .type = SAFEXCEL_ALG_TYPE_AEAD, -+ .algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_512, -+ .alg.aead = { -+ .setkey = safexcel_aead_setkey, -+ .encrypt = safexcel_aead_encrypt, -+ .decrypt = safexcel_aead_decrypt, -+ .ivsize = DES_BLOCK_SIZE, -+ .maxauthsize = SHA512_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(sha512),cbc(des))", -+ .cra_driver_name = "safexcel-authenc-hmac-sha512-cbc-des", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = DES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_aead_sha512_des_cra_init, -+ .cra_exit = safexcel_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+static int safexcel_aead_sha384_des_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_aead_sha384_cra_init(tfm); -+ ctx->alg = SAFEXCEL_DES; /* override default */ -+ ctx->blocksz = DES_BLOCK_SIZE; -+ ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD; -+ return 0; -+} -+ -+struct safexcel_alg_template safexcel_alg_authenc_hmac_sha384_cbc_des = { -+ .type = SAFEXCEL_ALG_TYPE_AEAD, -+ .algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_512, -+ .alg.aead = { -+ .setkey = safexcel_aead_setkey, -+ .encrypt = safexcel_aead_encrypt, -+ .decrypt = safexcel_aead_decrypt, -+ .ivsize = DES_BLOCK_SIZE, -+ .maxauthsize = SHA384_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(sha384),cbc(des))", -+ .cra_driver_name = "safexcel-authenc-hmac-sha384-cbc-des", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = DES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_aead_sha384_des_cra_init, -+ .cra_exit = safexcel_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ - static int safexcel_aead_sha1_ctr_cra_init(struct crypto_tfm *tfm) - { - struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -@@ -1965,14 +2450,12 @@ static int safexcel_skcipher_aesxts_setk - /* Only half of the key data is cipher key */ - keylen = (len >> 1); - ret = aes_expandkey(&aes, key, keylen); -- if (ret) { -- crypto_skcipher_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN); -+ if (ret) - return ret; -- } - - if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) { - for (i = 0; i < keylen / sizeof(u32); i++) { -- if (ctx->key[i] != cpu_to_le32(aes.key_enc[i])) { -+ if (le32_to_cpu(ctx->key[i]) != aes.key_enc[i]) { - ctx->base.needs_inv = true; - break; - } -@@ -1984,15 +2467,13 @@ static int safexcel_skcipher_aesxts_setk - - /* The other half is the tweak key */ - ret = aes_expandkey(&aes, (u8 *)(key + keylen), keylen); -- if (ret) { -- crypto_skcipher_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN); -+ if (ret) - return ret; -- } - - if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) { - for (i = 0; i < keylen / sizeof(u32); i++) { -- if (ctx->key[i + keylen / sizeof(u32)] != -- cpu_to_le32(aes.key_enc[i])) { -+ if (le32_to_cpu(ctx->key[i + keylen / sizeof(u32)]) != -+ aes.key_enc[i]) { - ctx->base.needs_inv = true; - break; - } -@@ -2015,6 +2496,7 @@ static int safexcel_skcipher_aes_xts_cra - - safexcel_skcipher_cra_init(tfm); - ctx->alg = SAFEXCEL_AES; -+ ctx->blocksz = AES_BLOCK_SIZE; - ctx->xts = 1; - ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_XTS; - return 0; -@@ -2075,14 +2557,13 @@ static int safexcel_aead_gcm_setkey(stru - - ret = aes_expandkey(&aes, key, len); - if (ret) { -- crypto_aead_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN); - memzero_explicit(&aes, sizeof(aes)); - return ret; - } - - if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) { - for (i = 0; i < len / sizeof(u32); i++) { -- if (ctx->key[i] != cpu_to_le32(aes.key_enc[i])) { -+ if (le32_to_cpu(ctx->key[i]) != aes.key_enc[i]) { - ctx->base.needs_inv = true; - break; - } -@@ -2099,8 +2580,6 @@ static int safexcel_aead_gcm_setkey(stru - crypto_cipher_set_flags(ctx->hkaes, crypto_aead_get_flags(ctfm) & - CRYPTO_TFM_REQ_MASK); - ret = crypto_cipher_setkey(ctx->hkaes, key, len); -- crypto_aead_set_flags(ctfm, crypto_cipher_get_flags(ctx->hkaes) & -- CRYPTO_TFM_RES_MASK); - if (ret) - return ret; - -@@ -2109,7 +2588,7 @@ static int safexcel_aead_gcm_setkey(stru - - if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) { - for (i = 0; i < AES_BLOCK_SIZE / sizeof(u32); i++) { -- if (ctx->ipad[i] != cpu_to_be32(hashkey[i])) { -+ if (be32_to_cpu(ctx->ipad[i]) != hashkey[i]) { - ctx->base.needs_inv = true; - break; - } -@@ -2135,10 +2614,7 @@ static int safexcel_aead_gcm_cra_init(st - ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_XCM; /* override default */ - - ctx->hkaes = crypto_alloc_cipher("aes", 0, 0); -- if (IS_ERR(ctx->hkaes)) -- return PTR_ERR(ctx->hkaes); -- -- return 0; -+ return PTR_ERR_OR_ZERO(ctx->hkaes); - } - - static void safexcel_aead_gcm_cra_exit(struct crypto_tfm *tfm) -@@ -2192,14 +2668,13 @@ static int safexcel_aead_ccm_setkey(stru - - ret = aes_expandkey(&aes, key, len); - if (ret) { -- crypto_aead_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN); - memzero_explicit(&aes, sizeof(aes)); - return ret; - } - - if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) { - for (i = 0; i < len / sizeof(u32); i++) { -- if (ctx->key[i] != cpu_to_le32(aes.key_enc[i])) { -+ if (le32_to_cpu(ctx->key[i]) != aes.key_enc[i]) { - ctx->base.needs_inv = true; - break; - } -@@ -2235,6 +2710,7 @@ static int safexcel_aead_ccm_cra_init(st - ctx->state_sz = 3 * AES_BLOCK_SIZE; - ctx->xcm = EIP197_XCM_MODE_CCM; - ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_XCM; /* override default */ -+ ctx->ctrinit = 0; - return 0; - } - -@@ -2301,5 +2777,949 @@ struct safexcel_alg_template safexcel_al - .cra_exit = safexcel_aead_cra_exit, - .cra_module = THIS_MODULE, - }, -+ }, -+}; -+ -+static void safexcel_chacha20_setkey(struct safexcel_cipher_ctx *ctx, -+ const u8 *key) -+{ -+ struct safexcel_crypto_priv *priv = ctx->priv; -+ -+ if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) -+ if (memcmp(ctx->key, key, CHACHA_KEY_SIZE)) -+ ctx->base.needs_inv = true; -+ -+ memcpy(ctx->key, key, CHACHA_KEY_SIZE); -+ ctx->key_len = CHACHA_KEY_SIZE; -+} -+ -+static int safexcel_skcipher_chacha20_setkey(struct crypto_skcipher *ctfm, -+ const u8 *key, unsigned int len) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_skcipher_ctx(ctfm); -+ -+ if (len != CHACHA_KEY_SIZE) -+ return -EINVAL; -+ -+ safexcel_chacha20_setkey(ctx, key); -+ -+ return 0; -+} -+ -+static int safexcel_skcipher_chacha20_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_skcipher_cra_init(tfm); -+ ctx->alg = SAFEXCEL_CHACHA20; -+ ctx->ctrinit = 0; -+ ctx->mode = CONTEXT_CONTROL_CHACHA20_MODE_256_32; -+ return 0; -+} -+ -+struct safexcel_alg_template safexcel_alg_chacha20 = { -+ .type = SAFEXCEL_ALG_TYPE_SKCIPHER, -+ .algo_mask = SAFEXCEL_ALG_CHACHA20, -+ .alg.skcipher = { -+ .setkey = safexcel_skcipher_chacha20_setkey, -+ .encrypt = safexcel_encrypt, -+ .decrypt = safexcel_decrypt, -+ .min_keysize = CHACHA_KEY_SIZE, -+ .max_keysize = CHACHA_KEY_SIZE, -+ .ivsize = CHACHA_IV_SIZE, -+ .base = { -+ .cra_name = "chacha20", -+ .cra_driver_name = "safexcel-chacha20", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = 1, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_skcipher_chacha20_cra_init, -+ .cra_exit = safexcel_skcipher_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+static int safexcel_aead_chachapoly_setkey(struct crypto_aead *ctfm, -+ const u8 *key, unsigned int len) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_aead_ctx(ctfm); -+ -+ if (ctx->aead == EIP197_AEAD_TYPE_IPSEC_ESP && -+ len > EIP197_AEAD_IPSEC_NONCE_SIZE) { -+ /* ESP variant has nonce appended to key */ -+ len -= EIP197_AEAD_IPSEC_NONCE_SIZE; -+ ctx->nonce = *(u32 *)(key + len); -+ } -+ if (len != CHACHA_KEY_SIZE) -+ return -EINVAL; -+ -+ safexcel_chacha20_setkey(ctx, key); -+ -+ return 0; -+} -+ -+static int safexcel_aead_chachapoly_setauthsize(struct crypto_aead *tfm, -+ unsigned int authsize) -+{ -+ if (authsize != POLY1305_DIGEST_SIZE) -+ return -EINVAL; -+ return 0; -+} -+ -+static int safexcel_aead_chachapoly_crypt(struct aead_request *req, -+ enum safexcel_cipher_direction dir) -+{ -+ struct safexcel_cipher_req *creq = aead_request_ctx(req); -+ struct crypto_aead *aead = crypto_aead_reqtfm(req); -+ struct crypto_tfm *tfm = crypto_aead_tfm(aead); -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ struct aead_request *subreq = aead_request_ctx(req); -+ u32 key[CHACHA_KEY_SIZE / sizeof(u32) + 1]; -+ int ret = 0; -+ -+ /* -+ * Instead of wasting time detecting umpteen silly corner cases, -+ * just dump all "small" requests to the fallback implementation. -+ * HW would not be faster on such small requests anyway. -+ */ -+ if (likely((ctx->aead != EIP197_AEAD_TYPE_IPSEC_ESP || -+ req->assoclen >= EIP197_AEAD_IPSEC_IV_SIZE) && -+ req->cryptlen > POLY1305_DIGEST_SIZE)) { -+ return safexcel_queue_req(&req->base, creq, dir); -+ } -+ -+ /* HW cannot do full (AAD+payload) zero length, use fallback */ -+ memcpy(key, ctx->key, CHACHA_KEY_SIZE); -+ if (ctx->aead == EIP197_AEAD_TYPE_IPSEC_ESP) { -+ /* ESP variant has nonce appended to the key */ -+ key[CHACHA_KEY_SIZE / sizeof(u32)] = ctx->nonce; -+ ret = crypto_aead_setkey(ctx->fback, (u8 *)key, -+ CHACHA_KEY_SIZE + -+ EIP197_AEAD_IPSEC_NONCE_SIZE); -+ } else { -+ ret = crypto_aead_setkey(ctx->fback, (u8 *)key, -+ CHACHA_KEY_SIZE); -+ } -+ if (ret) { -+ crypto_aead_clear_flags(aead, CRYPTO_TFM_REQ_MASK); -+ crypto_aead_set_flags(aead, crypto_aead_get_flags(ctx->fback) & -+ CRYPTO_TFM_REQ_MASK); -+ return ret; -+ } -+ -+ aead_request_set_tfm(subreq, ctx->fback); -+ aead_request_set_callback(subreq, req->base.flags, req->base.complete, -+ req->base.data); -+ aead_request_set_crypt(subreq, req->src, req->dst, req->cryptlen, -+ req->iv); -+ aead_request_set_ad(subreq, req->assoclen); -+ -+ return (dir == SAFEXCEL_ENCRYPT) ? -+ crypto_aead_encrypt(subreq) : -+ crypto_aead_decrypt(subreq); -+} -+ -+static int safexcel_aead_chachapoly_encrypt(struct aead_request *req) -+{ -+ return safexcel_aead_chachapoly_crypt(req, SAFEXCEL_ENCRYPT); -+} -+ -+static int safexcel_aead_chachapoly_decrypt(struct aead_request *req) -+{ -+ return safexcel_aead_chachapoly_crypt(req, SAFEXCEL_DECRYPT); -+} -+ -+static int safexcel_aead_fallback_cra_init(struct crypto_tfm *tfm) -+{ -+ struct crypto_aead *aead = __crypto_aead_cast(tfm); -+ struct aead_alg *alg = crypto_aead_alg(aead); -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_aead_cra_init(tfm); -+ -+ /* Allocate fallback implementation */ -+ ctx->fback = crypto_alloc_aead(alg->base.cra_name, 0, -+ CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_NEED_FALLBACK); -+ if (IS_ERR(ctx->fback)) -+ return PTR_ERR(ctx->fback); -+ -+ crypto_aead_set_reqsize(aead, max(sizeof(struct safexcel_cipher_req), -+ sizeof(struct aead_request) + -+ crypto_aead_reqsize(ctx->fback))); -+ -+ return 0; -+} -+ -+static int safexcel_aead_chachapoly_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_aead_fallback_cra_init(tfm); -+ ctx->alg = SAFEXCEL_CHACHA20; -+ ctx->mode = CONTEXT_CONTROL_CHACHA20_MODE_256_32 | -+ CONTEXT_CONTROL_CHACHA20_MODE_CALC_OTK; -+ ctx->ctrinit = 0; -+ ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_POLY1305; -+ ctx->state_sz = 0; /* Precomputed by HW */ -+ return 0; -+} -+ -+static void safexcel_aead_fallback_cra_exit(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ crypto_free_aead(ctx->fback); -+ safexcel_aead_cra_exit(tfm); -+} -+ -+struct safexcel_alg_template safexcel_alg_chachapoly = { -+ .type = SAFEXCEL_ALG_TYPE_AEAD, -+ .algo_mask = SAFEXCEL_ALG_CHACHA20 | SAFEXCEL_ALG_POLY1305, -+ .alg.aead = { -+ .setkey = safexcel_aead_chachapoly_setkey, -+ .setauthsize = safexcel_aead_chachapoly_setauthsize, -+ .encrypt = safexcel_aead_chachapoly_encrypt, -+ .decrypt = safexcel_aead_chachapoly_decrypt, -+ .ivsize = CHACHAPOLY_IV_SIZE, -+ .maxauthsize = POLY1305_DIGEST_SIZE, -+ .base = { -+ .cra_name = "rfc7539(chacha20,poly1305)", -+ .cra_driver_name = "safexcel-chacha20-poly1305", -+ /* +1 to put it above HW chacha + SW poly */ -+ .cra_priority = SAFEXCEL_CRA_PRIORITY + 1, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY | -+ CRYPTO_ALG_NEED_FALLBACK, -+ .cra_blocksize = 1, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_aead_chachapoly_cra_init, -+ .cra_exit = safexcel_aead_fallback_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+static int safexcel_aead_chachapolyesp_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ int ret; -+ -+ ret = safexcel_aead_chachapoly_cra_init(tfm); -+ ctx->aead = EIP197_AEAD_TYPE_IPSEC_ESP; -+ ctx->aadskip = EIP197_AEAD_IPSEC_IV_SIZE; -+ return ret; -+} -+ -+struct safexcel_alg_template safexcel_alg_chachapoly_esp = { -+ .type = SAFEXCEL_ALG_TYPE_AEAD, -+ .algo_mask = SAFEXCEL_ALG_CHACHA20 | SAFEXCEL_ALG_POLY1305, -+ .alg.aead = { -+ .setkey = safexcel_aead_chachapoly_setkey, -+ .setauthsize = safexcel_aead_chachapoly_setauthsize, -+ .encrypt = safexcel_aead_chachapoly_encrypt, -+ .decrypt = safexcel_aead_chachapoly_decrypt, -+ .ivsize = CHACHAPOLY_IV_SIZE - EIP197_AEAD_IPSEC_NONCE_SIZE, -+ .maxauthsize = POLY1305_DIGEST_SIZE, -+ .base = { -+ .cra_name = "rfc7539esp(chacha20,poly1305)", -+ .cra_driver_name = "safexcel-chacha20-poly1305-esp", -+ /* +1 to put it above HW chacha + SW poly */ -+ .cra_priority = SAFEXCEL_CRA_PRIORITY + 1, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY | -+ CRYPTO_ALG_NEED_FALLBACK, -+ .cra_blocksize = 1, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_aead_chachapolyesp_cra_init, -+ .cra_exit = safexcel_aead_fallback_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+static int safexcel_skcipher_sm4_setkey(struct crypto_skcipher *ctfm, -+ const u8 *key, unsigned int len) -+{ -+ struct crypto_tfm *tfm = crypto_skcipher_tfm(ctfm); -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ struct safexcel_crypto_priv *priv = ctx->priv; -+ -+ if (len != SM4_KEY_SIZE) -+ return -EINVAL; -+ -+ if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) -+ if (memcmp(ctx->key, key, SM4_KEY_SIZE)) -+ ctx->base.needs_inv = true; -+ -+ memcpy(ctx->key, key, SM4_KEY_SIZE); -+ ctx->key_len = SM4_KEY_SIZE; -+ -+ return 0; -+} -+ -+static int safexcel_sm4_blk_encrypt(struct skcipher_request *req) -+{ -+ /* Workaround for HW bug: EIP96 4.3 does not report blocksize error */ -+ if (req->cryptlen & (SM4_BLOCK_SIZE - 1)) -+ return -EINVAL; -+ else -+ return safexcel_queue_req(&req->base, skcipher_request_ctx(req), -+ SAFEXCEL_ENCRYPT); -+} -+ -+static int safexcel_sm4_blk_decrypt(struct skcipher_request *req) -+{ -+ /* Workaround for HW bug: EIP96 4.3 does not report blocksize error */ -+ if (req->cryptlen & (SM4_BLOCK_SIZE - 1)) -+ return -EINVAL; -+ else -+ return safexcel_queue_req(&req->base, skcipher_request_ctx(req), -+ SAFEXCEL_DECRYPT); -+} -+ -+static int safexcel_skcipher_sm4_ecb_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_skcipher_cra_init(tfm); -+ ctx->alg = SAFEXCEL_SM4; -+ ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_ECB; -+ ctx->blocksz = 0; -+ ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD; -+ return 0; -+} -+ -+struct safexcel_alg_template safexcel_alg_ecb_sm4 = { -+ .type = SAFEXCEL_ALG_TYPE_SKCIPHER, -+ .algo_mask = SAFEXCEL_ALG_SM4, -+ .alg.skcipher = { -+ .setkey = safexcel_skcipher_sm4_setkey, -+ .encrypt = safexcel_sm4_blk_encrypt, -+ .decrypt = safexcel_sm4_blk_decrypt, -+ .min_keysize = SM4_KEY_SIZE, -+ .max_keysize = SM4_KEY_SIZE, -+ .base = { -+ .cra_name = "ecb(sm4)", -+ .cra_driver_name = "safexcel-ecb-sm4", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = SM4_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_skcipher_sm4_ecb_cra_init, -+ .cra_exit = safexcel_skcipher_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+static int safexcel_skcipher_sm4_cbc_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_skcipher_cra_init(tfm); -+ ctx->alg = SAFEXCEL_SM4; -+ ctx->blocksz = SM4_BLOCK_SIZE; -+ ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CBC; -+ return 0; -+} -+ -+struct safexcel_alg_template safexcel_alg_cbc_sm4 = { -+ .type = SAFEXCEL_ALG_TYPE_SKCIPHER, -+ .algo_mask = SAFEXCEL_ALG_SM4, -+ .alg.skcipher = { -+ .setkey = safexcel_skcipher_sm4_setkey, -+ .encrypt = safexcel_sm4_blk_encrypt, -+ .decrypt = safexcel_sm4_blk_decrypt, -+ .min_keysize = SM4_KEY_SIZE, -+ .max_keysize = SM4_KEY_SIZE, -+ .ivsize = SM4_BLOCK_SIZE, -+ .base = { -+ .cra_name = "cbc(sm4)", -+ .cra_driver_name = "safexcel-cbc-sm4", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = SM4_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_skcipher_sm4_cbc_cra_init, -+ .cra_exit = safexcel_skcipher_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+static int safexcel_skcipher_sm4_ofb_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_skcipher_cra_init(tfm); -+ ctx->alg = SAFEXCEL_SM4; -+ ctx->blocksz = SM4_BLOCK_SIZE; -+ ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_OFB; -+ return 0; -+} -+ -+struct safexcel_alg_template safexcel_alg_ofb_sm4 = { -+ .type = SAFEXCEL_ALG_TYPE_SKCIPHER, -+ .algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_AES_XFB, -+ .alg.skcipher = { -+ .setkey = safexcel_skcipher_sm4_setkey, -+ .encrypt = safexcel_encrypt, -+ .decrypt = safexcel_decrypt, -+ .min_keysize = SM4_KEY_SIZE, -+ .max_keysize = SM4_KEY_SIZE, -+ .ivsize = SM4_BLOCK_SIZE, -+ .base = { -+ .cra_name = "ofb(sm4)", -+ .cra_driver_name = "safexcel-ofb-sm4", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = 1, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_skcipher_sm4_ofb_cra_init, -+ .cra_exit = safexcel_skcipher_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+static int safexcel_skcipher_sm4_cfb_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_skcipher_cra_init(tfm); -+ ctx->alg = SAFEXCEL_SM4; -+ ctx->blocksz = SM4_BLOCK_SIZE; -+ ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CFB; -+ return 0; -+} -+ -+struct safexcel_alg_template safexcel_alg_cfb_sm4 = { -+ .type = SAFEXCEL_ALG_TYPE_SKCIPHER, -+ .algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_AES_XFB, -+ .alg.skcipher = { -+ .setkey = safexcel_skcipher_sm4_setkey, -+ .encrypt = safexcel_encrypt, -+ .decrypt = safexcel_decrypt, -+ .min_keysize = SM4_KEY_SIZE, -+ .max_keysize = SM4_KEY_SIZE, -+ .ivsize = SM4_BLOCK_SIZE, -+ .base = { -+ .cra_name = "cfb(sm4)", -+ .cra_driver_name = "safexcel-cfb-sm4", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = 1, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_skcipher_sm4_cfb_cra_init, -+ .cra_exit = safexcel_skcipher_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+static int safexcel_skcipher_sm4ctr_setkey(struct crypto_skcipher *ctfm, -+ const u8 *key, unsigned int len) -+{ -+ struct crypto_tfm *tfm = crypto_skcipher_tfm(ctfm); -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ /* last 4 bytes of key are the nonce! */ -+ ctx->nonce = *(u32 *)(key + len - CTR_RFC3686_NONCE_SIZE); -+ /* exclude the nonce here */ -+ len -= CTR_RFC3686_NONCE_SIZE; -+ -+ return safexcel_skcipher_sm4_setkey(ctfm, key, len); -+} -+ -+static int safexcel_skcipher_sm4_ctr_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_skcipher_cra_init(tfm); -+ ctx->alg = SAFEXCEL_SM4; -+ ctx->blocksz = SM4_BLOCK_SIZE; -+ ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD; -+ return 0; -+} -+ -+struct safexcel_alg_template safexcel_alg_ctr_sm4 = { -+ .type = SAFEXCEL_ALG_TYPE_SKCIPHER, -+ .algo_mask = SAFEXCEL_ALG_SM4, -+ .alg.skcipher = { -+ .setkey = safexcel_skcipher_sm4ctr_setkey, -+ .encrypt = safexcel_encrypt, -+ .decrypt = safexcel_decrypt, -+ /* Add nonce size */ -+ .min_keysize = SM4_KEY_SIZE + CTR_RFC3686_NONCE_SIZE, -+ .max_keysize = SM4_KEY_SIZE + CTR_RFC3686_NONCE_SIZE, -+ .ivsize = CTR_RFC3686_IV_SIZE, -+ .base = { -+ .cra_name = "rfc3686(ctr(sm4))", -+ .cra_driver_name = "safexcel-ctr-sm4", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = 1, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_skcipher_sm4_ctr_cra_init, -+ .cra_exit = safexcel_skcipher_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+static int safexcel_aead_sm4_blk_encrypt(struct aead_request *req) -+{ -+ /* Workaround for HW bug: EIP96 4.3 does not report blocksize error */ -+ if (req->cryptlen & (SM4_BLOCK_SIZE - 1)) -+ return -EINVAL; -+ -+ return safexcel_queue_req(&req->base, aead_request_ctx(req), -+ SAFEXCEL_ENCRYPT); -+} -+ -+static int safexcel_aead_sm4_blk_decrypt(struct aead_request *req) -+{ -+ struct crypto_aead *tfm = crypto_aead_reqtfm(req); -+ -+ /* Workaround for HW bug: EIP96 4.3 does not report blocksize error */ -+ if ((req->cryptlen - crypto_aead_authsize(tfm)) & (SM4_BLOCK_SIZE - 1)) -+ return -EINVAL; -+ -+ return safexcel_queue_req(&req->base, aead_request_ctx(req), -+ SAFEXCEL_DECRYPT); -+} -+ -+static int safexcel_aead_sm4cbc_sha1_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_aead_cra_init(tfm); -+ ctx->alg = SAFEXCEL_SM4; -+ ctx->blocksz = SM4_BLOCK_SIZE; -+ ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1; -+ ctx->state_sz = SHA1_DIGEST_SIZE; -+ return 0; -+} -+ -+struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_cbc_sm4 = { -+ .type = SAFEXCEL_ALG_TYPE_AEAD, -+ .algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_SHA1, -+ .alg.aead = { -+ .setkey = safexcel_aead_setkey, -+ .encrypt = safexcel_aead_sm4_blk_encrypt, -+ .decrypt = safexcel_aead_sm4_blk_decrypt, -+ .ivsize = SM4_BLOCK_SIZE, -+ .maxauthsize = SHA1_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(sha1),cbc(sm4))", -+ .cra_driver_name = "safexcel-authenc-hmac-sha1-cbc-sm4", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = SM4_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_aead_sm4cbc_sha1_cra_init, -+ .cra_exit = safexcel_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+static int safexcel_aead_fallback_setkey(struct crypto_aead *ctfm, -+ const u8 *key, unsigned int len) -+{ -+ struct crypto_tfm *tfm = crypto_aead_tfm(ctfm); -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ /* Keep fallback cipher synchronized */ -+ return crypto_aead_setkey(ctx->fback, (u8 *)key, len) ?: -+ safexcel_aead_setkey(ctfm, key, len); -+} -+ -+static int safexcel_aead_fallback_setauthsize(struct crypto_aead *ctfm, -+ unsigned int authsize) -+{ -+ struct crypto_tfm *tfm = crypto_aead_tfm(ctfm); -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ /* Keep fallback cipher synchronized */ -+ return crypto_aead_setauthsize(ctx->fback, authsize); -+} -+ -+static int safexcel_aead_fallback_crypt(struct aead_request *req, -+ enum safexcel_cipher_direction dir) -+{ -+ struct crypto_aead *aead = crypto_aead_reqtfm(req); -+ struct crypto_tfm *tfm = crypto_aead_tfm(aead); -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ struct aead_request *subreq = aead_request_ctx(req); -+ -+ aead_request_set_tfm(subreq, ctx->fback); -+ aead_request_set_callback(subreq, req->base.flags, req->base.complete, -+ req->base.data); -+ aead_request_set_crypt(subreq, req->src, req->dst, req->cryptlen, -+ req->iv); -+ aead_request_set_ad(subreq, req->assoclen); -+ -+ return (dir == SAFEXCEL_ENCRYPT) ? -+ crypto_aead_encrypt(subreq) : -+ crypto_aead_decrypt(subreq); -+} -+ -+static int safexcel_aead_sm4cbc_sm3_encrypt(struct aead_request *req) -+{ -+ struct safexcel_cipher_req *creq = aead_request_ctx(req); -+ -+ /* Workaround for HW bug: EIP96 4.3 does not report blocksize error */ -+ if (req->cryptlen & (SM4_BLOCK_SIZE - 1)) -+ return -EINVAL; -+ else if (req->cryptlen || req->assoclen) /* If input length > 0 only */ -+ return safexcel_queue_req(&req->base, creq, SAFEXCEL_ENCRYPT); -+ -+ /* HW cannot do full (AAD+payload) zero length, use fallback */ -+ return safexcel_aead_fallback_crypt(req, SAFEXCEL_ENCRYPT); -+} -+ -+static int safexcel_aead_sm4cbc_sm3_decrypt(struct aead_request *req) -+{ -+ struct safexcel_cipher_req *creq = aead_request_ctx(req); -+ struct crypto_aead *tfm = crypto_aead_reqtfm(req); -+ -+ /* Workaround for HW bug: EIP96 4.3 does not report blocksize error */ -+ if ((req->cryptlen - crypto_aead_authsize(tfm)) & (SM4_BLOCK_SIZE - 1)) -+ return -EINVAL; -+ else if (req->cryptlen > crypto_aead_authsize(tfm) || req->assoclen) -+ /* If input length > 0 only */ -+ return safexcel_queue_req(&req->base, creq, SAFEXCEL_DECRYPT); -+ -+ /* HW cannot do full (AAD+payload) zero length, use fallback */ -+ return safexcel_aead_fallback_crypt(req, SAFEXCEL_DECRYPT); -+} -+ -+static int safexcel_aead_sm4cbc_sm3_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_aead_fallback_cra_init(tfm); -+ ctx->alg = SAFEXCEL_SM4; -+ ctx->blocksz = SM4_BLOCK_SIZE; -+ ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_SM3; -+ ctx->state_sz = SM3_DIGEST_SIZE; -+ return 0; -+} -+ -+struct safexcel_alg_template safexcel_alg_authenc_hmac_sm3_cbc_sm4 = { -+ .type = SAFEXCEL_ALG_TYPE_AEAD, -+ .algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_SM3, -+ .alg.aead = { -+ .setkey = safexcel_aead_fallback_setkey, -+ .setauthsize = safexcel_aead_fallback_setauthsize, -+ .encrypt = safexcel_aead_sm4cbc_sm3_encrypt, -+ .decrypt = safexcel_aead_sm4cbc_sm3_decrypt, -+ .ivsize = SM4_BLOCK_SIZE, -+ .maxauthsize = SM3_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(sm3),cbc(sm4))", -+ .cra_driver_name = "safexcel-authenc-hmac-sm3-cbc-sm4", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY | -+ CRYPTO_ALG_NEED_FALLBACK, -+ .cra_blocksize = SM4_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_aead_sm4cbc_sm3_cra_init, -+ .cra_exit = safexcel_aead_fallback_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+static int safexcel_aead_sm4ctr_sha1_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_aead_sm4cbc_sha1_cra_init(tfm); -+ ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD; -+ return 0; -+} -+ -+struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_ctr_sm4 = { -+ .type = SAFEXCEL_ALG_TYPE_AEAD, -+ .algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_SHA1, -+ .alg.aead = { -+ .setkey = safexcel_aead_setkey, -+ .encrypt = safexcel_aead_encrypt, -+ .decrypt = safexcel_aead_decrypt, -+ .ivsize = CTR_RFC3686_IV_SIZE, -+ .maxauthsize = SHA1_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(sha1),rfc3686(ctr(sm4)))", -+ .cra_driver_name = "safexcel-authenc-hmac-sha1-ctr-sm4", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = 1, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_aead_sm4ctr_sha1_cra_init, -+ .cra_exit = safexcel_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+static int safexcel_aead_sm4ctr_sm3_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_aead_sm4cbc_sm3_cra_init(tfm); -+ ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD; -+ return 0; -+} -+ -+struct safexcel_alg_template safexcel_alg_authenc_hmac_sm3_ctr_sm4 = { -+ .type = SAFEXCEL_ALG_TYPE_AEAD, -+ .algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_SM3, -+ .alg.aead = { -+ .setkey = safexcel_aead_setkey, -+ .encrypt = safexcel_aead_encrypt, -+ .decrypt = safexcel_aead_decrypt, -+ .ivsize = CTR_RFC3686_IV_SIZE, -+ .maxauthsize = SM3_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(sm3),rfc3686(ctr(sm4)))", -+ .cra_driver_name = "safexcel-authenc-hmac-sm3-ctr-sm4", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = 1, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_aead_sm4ctr_sm3_cra_init, -+ .cra_exit = safexcel_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+static int safexcel_rfc4106_gcm_setkey(struct crypto_aead *ctfm, const u8 *key, -+ unsigned int len) -+{ -+ struct crypto_tfm *tfm = crypto_aead_tfm(ctfm); -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ /* last 4 bytes of key are the nonce! */ -+ ctx->nonce = *(u32 *)(key + len - CTR_RFC3686_NONCE_SIZE); -+ -+ len -= CTR_RFC3686_NONCE_SIZE; -+ return safexcel_aead_gcm_setkey(ctfm, key, len); -+} -+ -+static int safexcel_rfc4106_gcm_setauthsize(struct crypto_aead *tfm, -+ unsigned int authsize) -+{ -+ return crypto_rfc4106_check_authsize(authsize); -+} -+ -+static int safexcel_rfc4106_encrypt(struct aead_request *req) -+{ -+ return crypto_ipsec_check_assoclen(req->assoclen) ?: -+ safexcel_aead_encrypt(req); -+} -+ -+static int safexcel_rfc4106_decrypt(struct aead_request *req) -+{ -+ return crypto_ipsec_check_assoclen(req->assoclen) ?: -+ safexcel_aead_decrypt(req); -+} -+ -+static int safexcel_rfc4106_gcm_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ int ret; -+ -+ ret = safexcel_aead_gcm_cra_init(tfm); -+ ctx->aead = EIP197_AEAD_TYPE_IPSEC_ESP; -+ ctx->aadskip = EIP197_AEAD_IPSEC_IV_SIZE; -+ return ret; -+} -+ -+struct safexcel_alg_template safexcel_alg_rfc4106_gcm = { -+ .type = SAFEXCEL_ALG_TYPE_AEAD, -+ .algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_GHASH, -+ .alg.aead = { -+ .setkey = safexcel_rfc4106_gcm_setkey, -+ .setauthsize = safexcel_rfc4106_gcm_setauthsize, -+ .encrypt = safexcel_rfc4106_encrypt, -+ .decrypt = safexcel_rfc4106_decrypt, -+ .ivsize = GCM_RFC4106_IV_SIZE, -+ .maxauthsize = GHASH_DIGEST_SIZE, -+ .base = { -+ .cra_name = "rfc4106(gcm(aes))", -+ .cra_driver_name = "safexcel-rfc4106-gcm-aes", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = 1, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_rfc4106_gcm_cra_init, -+ .cra_exit = safexcel_aead_gcm_cra_exit, -+ }, -+ }, -+}; -+ -+static int safexcel_rfc4543_gcm_setauthsize(struct crypto_aead *tfm, -+ unsigned int authsize) -+{ -+ if (authsize != GHASH_DIGEST_SIZE) -+ return -EINVAL; -+ -+ return 0; -+} -+ -+static int safexcel_rfc4543_gcm_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ int ret; -+ -+ ret = safexcel_aead_gcm_cra_init(tfm); -+ ctx->aead = EIP197_AEAD_TYPE_IPSEC_ESP_GMAC; -+ return ret; -+} -+ -+struct safexcel_alg_template safexcel_alg_rfc4543_gcm = { -+ .type = SAFEXCEL_ALG_TYPE_AEAD, -+ .algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_GHASH, -+ .alg.aead = { -+ .setkey = safexcel_rfc4106_gcm_setkey, -+ .setauthsize = safexcel_rfc4543_gcm_setauthsize, -+ .encrypt = safexcel_rfc4106_encrypt, -+ .decrypt = safexcel_rfc4106_decrypt, -+ .ivsize = GCM_RFC4543_IV_SIZE, -+ .maxauthsize = GHASH_DIGEST_SIZE, -+ .base = { -+ .cra_name = "rfc4543(gcm(aes))", -+ .cra_driver_name = "safexcel-rfc4543-gcm-aes", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = 1, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_rfc4543_gcm_cra_init, -+ .cra_exit = safexcel_aead_gcm_cra_exit, -+ }, -+ }, -+}; -+ -+static int safexcel_rfc4309_ccm_setkey(struct crypto_aead *ctfm, const u8 *key, -+ unsigned int len) -+{ -+ struct crypto_tfm *tfm = crypto_aead_tfm(ctfm); -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ /* First byte of the nonce = L = always 3 for RFC4309 (4 byte ctr) */ -+ *(u8 *)&ctx->nonce = EIP197_AEAD_IPSEC_COUNTER_SIZE - 1; -+ /* last 3 bytes of key are the nonce! */ -+ memcpy((u8 *)&ctx->nonce + 1, key + len - -+ EIP197_AEAD_IPSEC_CCM_NONCE_SIZE, -+ EIP197_AEAD_IPSEC_CCM_NONCE_SIZE); -+ -+ len -= EIP197_AEAD_IPSEC_CCM_NONCE_SIZE; -+ return safexcel_aead_ccm_setkey(ctfm, key, len); -+} -+ -+static int safexcel_rfc4309_ccm_setauthsize(struct crypto_aead *tfm, -+ unsigned int authsize) -+{ -+ /* Borrowed from crypto/ccm.c */ -+ switch (authsize) { -+ case 8: -+ case 12: -+ case 16: -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static int safexcel_rfc4309_ccm_encrypt(struct aead_request *req) -+{ -+ struct safexcel_cipher_req *creq = aead_request_ctx(req); -+ -+ /* Borrowed from crypto/ccm.c */ -+ if (req->assoclen != 16 && req->assoclen != 20) -+ return -EINVAL; -+ -+ return safexcel_queue_req(&req->base, creq, SAFEXCEL_ENCRYPT); -+} -+ -+static int safexcel_rfc4309_ccm_decrypt(struct aead_request *req) -+{ -+ struct safexcel_cipher_req *creq = aead_request_ctx(req); -+ -+ /* Borrowed from crypto/ccm.c */ -+ if (req->assoclen != 16 && req->assoclen != 20) -+ return -EINVAL; -+ -+ return safexcel_queue_req(&req->base, creq, SAFEXCEL_DECRYPT); -+} -+ -+static int safexcel_rfc4309_ccm_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ int ret; -+ -+ ret = safexcel_aead_ccm_cra_init(tfm); -+ ctx->aead = EIP197_AEAD_TYPE_IPSEC_ESP; -+ ctx->aadskip = EIP197_AEAD_IPSEC_IV_SIZE; -+ return ret; -+} -+ -+struct safexcel_alg_template safexcel_alg_rfc4309_ccm = { -+ .type = SAFEXCEL_ALG_TYPE_AEAD, -+ .algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_CBC_MAC_ALL, -+ .alg.aead = { -+ .setkey = safexcel_rfc4309_ccm_setkey, -+ .setauthsize = safexcel_rfc4309_ccm_setauthsize, -+ .encrypt = safexcel_rfc4309_ccm_encrypt, -+ .decrypt = safexcel_rfc4309_ccm_decrypt, -+ .ivsize = EIP197_AEAD_IPSEC_IV_SIZE, -+ .maxauthsize = AES_BLOCK_SIZE, -+ .base = { -+ .cra_name = "rfc4309(ccm(aes))", -+ .cra_driver_name = "safexcel-rfc4309-ccm-aes", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = 1, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_rfc4309_ccm_cra_init, -+ .cra_exit = safexcel_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, - }, - }; ---- a/drivers/crypto/inside-secure/safexcel.h -+++ b/drivers/crypto/inside-secure/safexcel.h -@@ -17,8 +17,11 @@ - #define EIP197_HIA_VERSION_BE 0xca35 - #define EIP197_HIA_VERSION_LE 0x35ca - #define EIP97_VERSION_LE 0x9e61 -+#define EIP196_VERSION_LE 0x3bc4 - #define EIP197_VERSION_LE 0x3ac5 - #define EIP96_VERSION_LE 0x9f60 -+#define EIP201_VERSION_LE 0x36c9 -+#define EIP206_VERSION_LE 0x31ce - #define EIP197_REG_LO16(reg) (reg & 0xffff) - #define EIP197_REG_HI16(reg) ((reg >> 16) & 0xffff) - #define EIP197_VERSION_MASK(reg) ((reg >> 16) & 0xfff) -@@ -26,12 +29,23 @@ - ((reg >> 4) & 0xf0) | \ - ((reg >> 12) & 0xf)) - -+/* EIP197 HIA OPTIONS ENCODING */ -+#define EIP197_HIA_OPT_HAS_PE_ARB BIT(29) -+ -+/* EIP206 OPTIONS ENCODING */ -+#define EIP206_OPT_ICE_TYPE(n) ((n>>8)&3) -+ -+/* EIP197 OPTIONS ENCODING */ -+#define EIP197_OPT_HAS_TRC BIT(31) -+ - /* Static configuration */ - #define EIP197_DEFAULT_RING_SIZE 400 --#define EIP197_MAX_TOKENS 18 -+#define EIP197_EMB_TOKENS 4 /* Pad CD to 16 dwords */ -+#define EIP197_MAX_TOKENS 16 - #define EIP197_MAX_RINGS 4 - #define EIP197_FETCH_DEPTH 2 - #define EIP197_MAX_BATCH_SZ 64 -+#define EIP197_MAX_RING_AIC 14 - - #define EIP197_GFP_FLAGS(base) ((base).flags & CRYPTO_TFM_REQ_MAY_SLEEP ? \ - GFP_KERNEL : GFP_ATOMIC) -@@ -138,6 +152,7 @@ - #define EIP197_HIA_AIC_R_ENABLED_STAT(r) (0xe010 - EIP197_HIA_AIC_R_OFF(r)) - #define EIP197_HIA_AIC_R_ACK(r) (0xe010 - EIP197_HIA_AIC_R_OFF(r)) - #define EIP197_HIA_AIC_R_ENABLE_CLR(r) (0xe014 - EIP197_HIA_AIC_R_OFF(r)) -+#define EIP197_HIA_AIC_R_VERSION(r) (0xe01c - EIP197_HIA_AIC_R_OFF(r)) - #define EIP197_HIA_AIC_G_ENABLE_CTRL 0xf808 - #define EIP197_HIA_AIC_G_ENABLED_STAT 0xf810 - #define EIP197_HIA_AIC_G_ACK 0xf810 -@@ -157,12 +172,16 @@ - #define EIP197_PE_EIP96_FUNCTION_EN(n) (0x1004 + (0x2000 * (n))) - #define EIP197_PE_EIP96_CONTEXT_CTRL(n) (0x1008 + (0x2000 * (n))) - #define EIP197_PE_EIP96_CONTEXT_STAT(n) (0x100c + (0x2000 * (n))) -+#define EIP197_PE_EIP96_TOKEN_CTRL2(n) (0x102c + (0x2000 * (n))) - #define EIP197_PE_EIP96_FUNCTION2_EN(n) (0x1030 + (0x2000 * (n))) - #define EIP197_PE_EIP96_OPTIONS(n) (0x13f8 + (0x2000 * (n))) - #define EIP197_PE_EIP96_VERSION(n) (0x13fc + (0x2000 * (n))) - #define EIP197_PE_OUT_DBUF_THRES(n) (0x1c00 + (0x2000 * (n))) - #define EIP197_PE_OUT_TBUF_THRES(n) (0x1d00 + (0x2000 * (n))) -+#define EIP197_PE_OPTIONS(n) (0x1ff8 + (0x2000 * (n))) -+#define EIP197_PE_VERSION(n) (0x1ffc + (0x2000 * (n))) - #define EIP197_MST_CTRL 0xfff4 -+#define EIP197_OPTIONS 0xfff8 - #define EIP197_VERSION 0xfffc - - /* EIP197-specific registers, no indirection */ -@@ -178,6 +197,7 @@ - #define EIP197_TRC_ECCADMINSTAT 0xf0838 - #define EIP197_TRC_ECCDATASTAT 0xf083c - #define EIP197_TRC_ECCDATA 0xf0840 -+#define EIP197_STRC_CONFIG 0xf43f0 - #define EIP197_FLUE_CACHEBASE_LO(n) (0xf6000 + (32 * (n))) - #define EIP197_FLUE_CACHEBASE_HI(n) (0xf6004 + (32 * (n))) - #define EIP197_FLUE_CONFIG(n) (0xf6010 + (32 * (n))) -@@ -188,6 +208,7 @@ - - /* EIP197_HIA_xDR_DESC_SIZE */ - #define EIP197_xDR_DESC_MODE_64BIT BIT(31) -+#define EIP197_CDR_DESC_MODE_ADCP BIT(30) - - /* EIP197_HIA_xDR_DMA_CFG */ - #define EIP197_HIA_xDR_WR_RES_BUF BIT(22) -@@ -213,7 +234,6 @@ - /* EIP197_HIA_xDR_PROC_COUNT */ - #define EIP197_xDR_PROC_xD_PKT_OFFSET 24 - #define EIP197_xDR_PROC_xD_PKT_MASK GENMASK(6, 0) --#define EIP197_xDR_PROC_xD_COUNT(n) ((n) << 2) - #define EIP197_xDR_PROC_xD_PKT(n) ((n) << 24) - #define EIP197_xDR_PROC_CLR_COUNT BIT(31) - -@@ -228,6 +248,8 @@ - #define EIP197_HIA_RA_PE_CTRL_EN BIT(30) - - /* EIP197_HIA_OPTIONS */ -+#define EIP197_N_RINGS_OFFSET 0 -+#define EIP197_N_RINGS_MASK GENMASK(3, 0) - #define EIP197_N_PES_OFFSET 4 - #define EIP197_N_PES_MASK GENMASK(4, 0) - #define EIP97_N_PES_MASK GENMASK(2, 0) -@@ -237,13 +259,13 @@ - #define EIP197_CFSIZE_OFFSET 9 - #define EIP197_CFSIZE_ADJUST 4 - #define EIP97_CFSIZE_OFFSET 8 --#define EIP197_CFSIZE_MASK GENMASK(3, 0) --#define EIP97_CFSIZE_MASK GENMASK(4, 0) -+#define EIP197_CFSIZE_MASK GENMASK(2, 0) -+#define EIP97_CFSIZE_MASK GENMASK(3, 0) - #define EIP197_RFSIZE_OFFSET 12 - #define EIP197_RFSIZE_ADJUST 4 - #define EIP97_RFSIZE_OFFSET 12 --#define EIP197_RFSIZE_MASK GENMASK(3, 0) --#define EIP97_RFSIZE_MASK GENMASK(4, 0) -+#define EIP197_RFSIZE_MASK GENMASK(2, 0) -+#define EIP97_RFSIZE_MASK GENMASK(3, 0) - - /* EIP197_HIA_AIC_R_ENABLE_CTRL */ - #define EIP197_CDR_IRQ(n) BIT((n) * 2) -@@ -257,9 +279,9 @@ - #define EIP197_HIA_DxE_CFG_MIN_CTRL_SIZE(n) ((n) << 16) - #define EIP197_HIA_DxE_CFG_CTRL_CACHE_CTRL(n) (((n) & 0x7) << 20) - #define EIP197_HIA_DxE_CFG_MAX_CTRL_SIZE(n) ((n) << 24) --#define EIP197_HIA_DFE_CFG_DIS_DEBUG (BIT(31) | BIT(29)) -+#define EIP197_HIA_DFE_CFG_DIS_DEBUG GENMASK(31, 29) - #define EIP197_HIA_DSE_CFG_EN_SINGLE_WR BIT(29) --#define EIP197_HIA_DSE_CFG_DIS_DEBUG BIT(31) -+#define EIP197_HIA_DSE_CFG_DIS_DEBUG GENMASK(31, 30) - - /* EIP197_HIA_DFE/DSE_THR_CTRL */ - #define EIP197_DxE_THR_CTRL_EN BIT(30) -@@ -327,13 +349,21 @@ - #define EIP197_ADDRESS_MODE BIT(8) - #define EIP197_CONTROL_MODE BIT(9) - -+/* EIP197_PE_EIP96_TOKEN_CTRL2 */ -+#define EIP197_PE_EIP96_TOKEN_CTRL2_CTX_DONE BIT(3) -+ -+/* EIP197_STRC_CONFIG */ -+#define EIP197_STRC_CONFIG_INIT BIT(31) -+#define EIP197_STRC_CONFIG_LARGE_REC(s) (s<<8) -+#define EIP197_STRC_CONFIG_SMALL_REC(s) (s<<0) -+ - /* EIP197_FLUE_CONFIG */ - #define EIP197_FLUE_CONFIG_MAGIC 0xc7000004 - - /* Context Control */ - struct safexcel_context_record { -- u32 control0; -- u32 control1; -+ __le32 control0; -+ __le32 control1; - - __le32 data[40]; - } __packed; -@@ -358,10 +388,14 @@ struct safexcel_context_record { - #define CONTEXT_CONTROL_CRYPTO_ALG_AES128 (0x5 << 17) - #define CONTEXT_CONTROL_CRYPTO_ALG_AES192 (0x6 << 17) - #define CONTEXT_CONTROL_CRYPTO_ALG_AES256 (0x7 << 17) -+#define CONTEXT_CONTROL_CRYPTO_ALG_CHACHA20 (0x8 << 17) -+#define CONTEXT_CONTROL_CRYPTO_ALG_SM4 (0xd << 17) -+#define CONTEXT_CONTROL_DIGEST_INITIAL (0x0 << 21) - #define CONTEXT_CONTROL_DIGEST_PRECOMPUTED (0x1 << 21) - #define CONTEXT_CONTROL_DIGEST_XCM (0x2 << 21) - #define CONTEXT_CONTROL_DIGEST_HMAC (0x3 << 21) - #define CONTEXT_CONTROL_CRYPTO_ALG_MD5 (0x0 << 23) -+#define CONTEXT_CONTROL_CRYPTO_ALG_CRC32 (0x0 << 23) - #define CONTEXT_CONTROL_CRYPTO_ALG_SHA1 (0x2 << 23) - #define CONTEXT_CONTROL_CRYPTO_ALG_SHA224 (0x4 << 23) - #define CONTEXT_CONTROL_CRYPTO_ALG_SHA256 (0x3 << 23) -@@ -371,17 +405,25 @@ struct safexcel_context_record { - #define CONTEXT_CONTROL_CRYPTO_ALG_XCBC128 (0x1 << 23) - #define CONTEXT_CONTROL_CRYPTO_ALG_XCBC192 (0x2 << 23) - #define CONTEXT_CONTROL_CRYPTO_ALG_XCBC256 (0x3 << 23) -+#define CONTEXT_CONTROL_CRYPTO_ALG_SM3 (0x7 << 23) -+#define CONTEXT_CONTROL_CRYPTO_ALG_SHA3_256 (0xb << 23) -+#define CONTEXT_CONTROL_CRYPTO_ALG_SHA3_224 (0xc << 23) -+#define CONTEXT_CONTROL_CRYPTO_ALG_SHA3_512 (0xd << 23) -+#define CONTEXT_CONTROL_CRYPTO_ALG_SHA3_384 (0xe << 23) -+#define CONTEXT_CONTROL_CRYPTO_ALG_POLY1305 (0xf << 23) - #define CONTEXT_CONTROL_INV_FR (0x5 << 24) - #define CONTEXT_CONTROL_INV_TR (0x6 << 24) - - /* control1 */ - #define CONTEXT_CONTROL_CRYPTO_MODE_ECB (0 << 0) - #define CONTEXT_CONTROL_CRYPTO_MODE_CBC (1 << 0) -+#define CONTEXT_CONTROL_CHACHA20_MODE_256_32 (2 << 0) - #define CONTEXT_CONTROL_CRYPTO_MODE_OFB (4 << 0) - #define CONTEXT_CONTROL_CRYPTO_MODE_CFB (5 << 0) - #define CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD (6 << 0) - #define CONTEXT_CONTROL_CRYPTO_MODE_XTS (7 << 0) - #define CONTEXT_CONTROL_CRYPTO_MODE_XCM ((6 << 0) | BIT(17)) -+#define CONTEXT_CONTROL_CHACHA20_MODE_CALC_OTK (12 << 0) - #define CONTEXT_CONTROL_IV0 BIT(5) - #define CONTEXT_CONTROL_IV1 BIT(6) - #define CONTEXT_CONTROL_IV2 BIT(7) -@@ -394,6 +436,13 @@ struct safexcel_context_record { - #define EIP197_XCM_MODE_GCM 1 - #define EIP197_XCM_MODE_CCM 2 - -+#define EIP197_AEAD_TYPE_IPSEC_ESP 2 -+#define EIP197_AEAD_TYPE_IPSEC_ESP_GMAC 3 -+#define EIP197_AEAD_IPSEC_IV_SIZE 8 -+#define EIP197_AEAD_IPSEC_NONCE_SIZE 4 -+#define EIP197_AEAD_IPSEC_COUNTER_SIZE 4 -+#define EIP197_AEAD_IPSEC_CCM_NONCE_SIZE 3 -+ - /* The hash counter given to the engine in the context has a granularity of - * 64 bits. - */ -@@ -423,6 +472,8 @@ struct safexcel_context_record { - #define EIP197_TRC_PARAMS2_RC_SZ_SMALL(n) ((n) << 18) - - /* Cache helpers */ -+#define EIP197_MIN_DSIZE 1024 -+#define EIP197_MIN_ASIZE 8 - #define EIP197_CS_TRC_REC_WC 64 - #define EIP197_CS_RC_SIZE (4 * sizeof(u32)) - #define EIP197_CS_RC_NEXT(x) (x) -@@ -447,7 +498,7 @@ struct result_data_desc { - u16 application_id; - u16 rsvd1; - -- u32 rsvd2; -+ u32 rsvd2[5]; - } __packed; - - -@@ -465,16 +516,15 @@ struct safexcel_result_desc { - - u32 data_lo; - u32 data_hi; -- -- struct result_data_desc result_data; - } __packed; - - /* - * The EIP(1)97 only needs to fetch the descriptor part of - * the result descriptor, not the result token part! - */ --#define EIP197_RD64_FETCH_SIZE ((sizeof(struct safexcel_result_desc) -\ -- sizeof(struct result_data_desc)) /\ -+#define EIP197_RD64_FETCH_SIZE (sizeof(struct safexcel_result_desc) /\ -+ sizeof(u32)) -+#define EIP197_RD64_RESULT_SIZE (sizeof(struct result_data_desc) /\ - sizeof(u32)) - - struct safexcel_token { -@@ -505,6 +555,8 @@ static inline void eip197_noop_token(str - { - token->opcode = EIP197_TOKEN_OPCODE_NOOP; - token->packet_length = BIT(2); -+ token->stat = 0; -+ token->instructions = 0; - } - - /* Instructions */ -@@ -526,14 +578,13 @@ struct safexcel_control_data_desc { - u16 application_id; - u16 rsvd; - -- u8 refresh:2; -- u32 context_lo:30; -+ u32 context_lo; - u32 context_hi; - - u32 control0; - u32 control1; - -- u32 token[EIP197_MAX_TOKENS]; -+ u32 token[EIP197_EMB_TOKENS]; - } __packed; - - #define EIP197_OPTION_MAGIC_VALUE BIT(0) -@@ -543,7 +594,10 @@ struct safexcel_control_data_desc { - #define EIP197_OPTION_2_TOKEN_IV_CMD GENMASK(11, 10) - #define EIP197_OPTION_4_TOKEN_IV_CMD GENMASK(11, 9) - -+#define EIP197_TYPE_BCLA 0x0 - #define EIP197_TYPE_EXTENDED 0x3 -+#define EIP197_CONTEXT_SMALL 0x2 -+#define EIP197_CONTEXT_SIZE_MASK 0x3 - - /* Basic Command Descriptor format */ - struct safexcel_command_desc { -@@ -551,16 +605,22 @@ struct safexcel_command_desc { - u8 rsvd0:5; - u8 last_seg:1; - u8 first_seg:1; -- u16 additional_cdata_size:8; -+ u8 additional_cdata_size:8; - - u32 rsvd1; - - u32 data_lo; - u32 data_hi; - -+ u32 atok_lo; -+ u32 atok_hi; -+ - struct safexcel_control_data_desc control_data; - } __packed; - -+#define EIP197_CD64_FETCH_SIZE (sizeof(struct safexcel_command_desc) /\ -+ sizeof(u32)) -+ - /* - * Internal structures & functions - */ -@@ -578,15 +638,20 @@ enum eip197_fw { - - struct safexcel_desc_ring { - void *base; -+ void *shbase; - void *base_end; -+ void *shbase_end; - dma_addr_t base_dma; -+ dma_addr_t shbase_dma; - - /* write and read pointers */ - void *write; -+ void *shwrite; - void *read; - - /* descriptor element offset */ -- unsigned offset; -+ unsigned int offset; -+ unsigned int shoffset; - }; - - enum safexcel_alg_type { -@@ -601,9 +666,11 @@ struct safexcel_config { - - u32 cd_size; - u32 cd_offset; -+ u32 cdsh_offset; - - u32 rd_size; - u32 rd_offset; -+ u32 res_offset; - }; - - struct safexcel_work_data { -@@ -654,6 +721,12 @@ enum safexcel_eip_version { - /* Priority we use for advertising our algorithms */ - #define SAFEXCEL_CRA_PRIORITY 300 - -+/* SM3 digest result for zero length message */ -+#define EIP197_SM3_ZEROM_HASH "\x1A\xB2\x1D\x83\x55\xCF\xA1\x7F" \ -+ "\x8E\x61\x19\x48\x31\xE8\x1A\x8F" \ -+ "\x22\xBE\xC8\xC7\x28\xFE\xFB\x74" \ -+ "\x7E\xD0\x35\xEB\x50\x82\xAA\x2B" -+ - /* EIP algorithm presence flags */ - enum safexcel_eip_algorithms { - SAFEXCEL_ALG_BC0 = BIT(5), -@@ -697,16 +770,23 @@ struct safexcel_register_offsets { - enum safexcel_flags { - EIP197_TRC_CACHE = BIT(0), - SAFEXCEL_HW_EIP197 = BIT(1), -+ EIP197_PE_ARB = BIT(2), -+ EIP197_ICE = BIT(3), -+ EIP197_SIMPLE_TRC = BIT(4), - }; - - struct safexcel_hwconfig { - enum safexcel_eip_algorithms algo_flags; - int hwver; - int hiaver; -+ int ppver; - int pever; - int hwdataw; - int hwcfsize; - int hwrfsize; -+ int hwnumpes; -+ int hwnumrings; -+ int hwnumraic; - }; - - struct safexcel_crypto_priv { -@@ -778,7 +858,7 @@ struct safexcel_inv_result { - - void safexcel_dequeue(struct safexcel_crypto_priv *priv, int ring); - int safexcel_rdesc_check_errors(struct safexcel_crypto_priv *priv, -- struct safexcel_result_desc *rdesc); -+ void *rdp); - void safexcel_complete(struct safexcel_crypto_priv *priv, int ring); - int safexcel_invalidate_cache(struct crypto_async_request *async, - struct safexcel_crypto_priv *priv, -@@ -797,7 +877,8 @@ struct safexcel_command_desc *safexcel_a - bool first, bool last, - dma_addr_t data, u32 len, - u32 full_data_len, -- dma_addr_t context); -+ dma_addr_t context, -+ struct safexcel_token **atoken); - struct safexcel_result_desc *safexcel_add_rdesc(struct safexcel_crypto_priv *priv, - int ring_id, - bool first, bool last, -@@ -853,5 +934,43 @@ extern struct safexcel_alg_template safe - extern struct safexcel_alg_template safexcel_alg_xts_aes; - extern struct safexcel_alg_template safexcel_alg_gcm; - extern struct safexcel_alg_template safexcel_alg_ccm; -+extern struct safexcel_alg_template safexcel_alg_crc32; -+extern struct safexcel_alg_template safexcel_alg_cbcmac; -+extern struct safexcel_alg_template safexcel_alg_xcbcmac; -+extern struct safexcel_alg_template safexcel_alg_cmac; -+extern struct safexcel_alg_template safexcel_alg_chacha20; -+extern struct safexcel_alg_template safexcel_alg_chachapoly; -+extern struct safexcel_alg_template safexcel_alg_chachapoly_esp; -+extern struct safexcel_alg_template safexcel_alg_sm3; -+extern struct safexcel_alg_template safexcel_alg_hmac_sm3; -+extern struct safexcel_alg_template safexcel_alg_ecb_sm4; -+extern struct safexcel_alg_template safexcel_alg_cbc_sm4; -+extern struct safexcel_alg_template safexcel_alg_ofb_sm4; -+extern struct safexcel_alg_template safexcel_alg_cfb_sm4; -+extern struct safexcel_alg_template safexcel_alg_ctr_sm4; -+extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_cbc_sm4; -+extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sm3_cbc_sm4; -+extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_ctr_sm4; -+extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sm3_ctr_sm4; -+extern struct safexcel_alg_template safexcel_alg_sha3_224; -+extern struct safexcel_alg_template safexcel_alg_sha3_256; -+extern struct safexcel_alg_template safexcel_alg_sha3_384; -+extern struct safexcel_alg_template safexcel_alg_sha3_512; -+extern struct safexcel_alg_template safexcel_alg_hmac_sha3_224; -+extern struct safexcel_alg_template safexcel_alg_hmac_sha3_256; -+extern struct safexcel_alg_template safexcel_alg_hmac_sha3_384; -+extern struct safexcel_alg_template safexcel_alg_hmac_sha3_512; -+extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_cbc_des; -+extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sha256_cbc_des3_ede; -+extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sha224_cbc_des3_ede; -+extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sha512_cbc_des3_ede; -+extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sha384_cbc_des3_ede; -+extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sha256_cbc_des; -+extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sha224_cbc_des; -+extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sha512_cbc_des; -+extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sha384_cbc_des; -+extern struct safexcel_alg_template safexcel_alg_rfc4106_gcm; -+extern struct safexcel_alg_template safexcel_alg_rfc4543_gcm; -+extern struct safexcel_alg_template safexcel_alg_rfc4309_ccm; - - #endif ---- a/drivers/crypto/inside-secure/safexcel_hash.c -+++ b/drivers/crypto/inside-secure/safexcel_hash.c -@@ -5,9 +5,13 @@ - * Antoine Tenart <antoine.tenart@free-electrons.com> - */ - -+#include <crypto/aes.h> - #include <crypto/hmac.h> - #include <crypto/md5.h> - #include <crypto/sha.h> -+#include <crypto/sha3.h> -+#include <crypto/skcipher.h> -+#include <crypto/sm3.h> - #include <linux/device.h> - #include <linux/dma-mapping.h> - #include <linux/dmapool.h> -@@ -19,9 +23,19 @@ struct safexcel_ahash_ctx { - struct safexcel_crypto_priv *priv; - - u32 alg; -- -- u32 ipad[SHA512_DIGEST_SIZE / sizeof(u32)]; -- u32 opad[SHA512_DIGEST_SIZE / sizeof(u32)]; -+ u8 key_sz; -+ bool cbcmac; -+ bool do_fallback; -+ bool fb_init_done; -+ bool fb_do_setkey; -+ -+ __le32 ipad[SHA3_512_BLOCK_SIZE / sizeof(__le32)]; -+ __le32 opad[SHA3_512_BLOCK_SIZE / sizeof(__le32)]; -+ -+ struct crypto_cipher *kaes; -+ struct crypto_ahash *fback; -+ struct crypto_shash *shpre; -+ struct shash_desc *shdesc; - }; - - struct safexcel_ahash_req { -@@ -31,6 +45,8 @@ struct safexcel_ahash_req { - bool needs_inv; - bool hmac_zlen; - bool len_is_le; -+ bool not_first; -+ bool xcbcmac; - - int nents; - dma_addr_t result_dma; -@@ -39,7 +55,9 @@ struct safexcel_ahash_req { - - u8 state_sz; /* expected state size, only set once */ - u8 block_sz; /* block size, only set once */ -- u32 state[SHA512_DIGEST_SIZE / sizeof(u32)] __aligned(sizeof(u32)); -+ u8 digest_sz; /* output digest size, only set once */ -+ __le32 state[SHA3_512_BLOCK_SIZE / -+ sizeof(__le32)] __aligned(sizeof(__le32)); - - u64 len; - u64 processed; -@@ -57,22 +75,36 @@ static inline u64 safexcel_queued_len(st - } - - static void safexcel_hash_token(struct safexcel_command_desc *cdesc, -- u32 input_length, u32 result_length) -+ u32 input_length, u32 result_length, -+ bool cbcmac) - { - struct safexcel_token *token = - (struct safexcel_token *)cdesc->control_data.token; - - token[0].opcode = EIP197_TOKEN_OPCODE_DIRECTION; - token[0].packet_length = input_length; -- token[0].stat = EIP197_TOKEN_STAT_LAST_HASH; - token[0].instructions = EIP197_TOKEN_INS_TYPE_HASH; - -- token[1].opcode = EIP197_TOKEN_OPCODE_INSERT; -- token[1].packet_length = result_length; -- token[1].stat = EIP197_TOKEN_STAT_LAST_HASH | -+ input_length &= 15; -+ if (unlikely(cbcmac && input_length)) { -+ token[0].stat = 0; -+ token[1].opcode = EIP197_TOKEN_OPCODE_INSERT; -+ token[1].packet_length = 16 - input_length; -+ token[1].stat = EIP197_TOKEN_STAT_LAST_HASH; -+ token[1].instructions = EIP197_TOKEN_INS_TYPE_HASH; -+ } else { -+ token[0].stat = EIP197_TOKEN_STAT_LAST_HASH; -+ eip197_noop_token(&token[1]); -+ } -+ -+ token[2].opcode = EIP197_TOKEN_OPCODE_INSERT; -+ token[2].stat = EIP197_TOKEN_STAT_LAST_HASH | - EIP197_TOKEN_STAT_LAST_PACKET; -- token[1].instructions = EIP197_TOKEN_INS_TYPE_OUTPUT | -+ token[2].packet_length = result_length; -+ token[2].instructions = EIP197_TOKEN_INS_TYPE_OUTPUT | - EIP197_TOKEN_INS_INSERT_HASH_DIGEST; -+ -+ eip197_noop_token(&token[3]); - } - - static void safexcel_context_control(struct safexcel_ahash_ctx *ctx, -@@ -82,29 +114,49 @@ static void safexcel_context_control(str - struct safexcel_crypto_priv *priv = ctx->priv; - u64 count = 0; - -- cdesc->control_data.control0 |= ctx->alg; -+ cdesc->control_data.control0 = ctx->alg; -+ cdesc->control_data.control1 = 0; - - /* - * Copy the input digest if needed, and setup the context - * fields. Do this now as we need it to setup the first command - * descriptor. - */ -- if (!req->processed) { -- /* First - and possibly only - block of basic hash only */ -- if (req->finish) { -+ if (unlikely(req->digest == CONTEXT_CONTROL_DIGEST_XCM)) { -+ if (req->xcbcmac) -+ memcpy(ctx->base.ctxr->data, ctx->ipad, ctx->key_sz); -+ else -+ memcpy(ctx->base.ctxr->data, req->state, req->state_sz); -+ -+ if (!req->finish && req->xcbcmac) -+ cdesc->control_data.control0 |= -+ CONTEXT_CONTROL_DIGEST_XCM | -+ CONTEXT_CONTROL_TYPE_HASH_OUT | -+ CONTEXT_CONTROL_NO_FINISH_HASH | -+ CONTEXT_CONTROL_SIZE(req->state_sz / -+ sizeof(u32)); -+ else - cdesc->control_data.control0 |= -+ CONTEXT_CONTROL_DIGEST_XCM | -+ CONTEXT_CONTROL_TYPE_HASH_OUT | -+ CONTEXT_CONTROL_SIZE(req->state_sz / -+ sizeof(u32)); -+ return; -+ } else if (!req->processed) { -+ /* First - and possibly only - block of basic hash only */ -+ if (req->finish) -+ cdesc->control_data.control0 |= req->digest | - CONTEXT_CONTROL_TYPE_HASH_OUT | - CONTEXT_CONTROL_RESTART_HASH | - /* ensure its not 0! */ - CONTEXT_CONTROL_SIZE(1); -- } else { -- cdesc->control_data.control0 |= -+ else -+ cdesc->control_data.control0 |= req->digest | - CONTEXT_CONTROL_TYPE_HASH_OUT | - CONTEXT_CONTROL_RESTART_HASH | - CONTEXT_CONTROL_NO_FINISH_HASH | - /* ensure its not 0! */ - CONTEXT_CONTROL_SIZE(1); -- } - return; - } - -@@ -204,7 +256,7 @@ static int safexcel_handle_req_result(st - } - - if (sreq->result_dma) { -- dma_unmap_single(priv->dev, sreq->result_dma, sreq->state_sz, -+ dma_unmap_single(priv->dev, sreq->result_dma, sreq->digest_sz, - DMA_FROM_DEVICE); - sreq->result_dma = 0; - } -@@ -223,14 +275,15 @@ static int safexcel_handle_req_result(st - memcpy(sreq->cache, sreq->state, - crypto_ahash_digestsize(ahash)); - -- memcpy(sreq->state, ctx->opad, sreq->state_sz); -+ memcpy(sreq->state, ctx->opad, sreq->digest_sz); - - sreq->len = sreq->block_sz + - crypto_ahash_digestsize(ahash); - sreq->processed = sreq->block_sz; - sreq->hmac = 0; - -- ctx->base.needs_inv = true; -+ if (priv->flags & EIP197_TRC_CACHE) -+ ctx->base.needs_inv = true; - areq->nbytes = 0; - safexcel_ahash_enqueue(areq); - -@@ -238,8 +291,14 @@ static int safexcel_handle_req_result(st - return 1; - } - -- memcpy(areq->result, sreq->state, -- crypto_ahash_digestsize(ahash)); -+ if (unlikely(sreq->digest == CONTEXT_CONTROL_DIGEST_XCM && -+ ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_CRC32)) { -+ /* Undo final XOR with 0xffffffff ...*/ -+ *(__le32 *)areq->result = ~sreq->state[0]; -+ } else { -+ memcpy(areq->result, sreq->state, -+ crypto_ahash_digestsize(ahash)); -+ } - } - - cache_len = safexcel_queued_len(sreq); -@@ -261,10 +320,11 @@ static int safexcel_ahash_send_req(struc - struct safexcel_command_desc *cdesc, *first_cdesc = NULL; - struct safexcel_result_desc *rdesc; - struct scatterlist *sg; -- int i, extra = 0, n_cdesc = 0, ret = 0; -- u64 queued, len, cache_len; -+ struct safexcel_token *dmmy; -+ int i, extra = 0, n_cdesc = 0, ret = 0, cache_len, skip = 0; -+ u64 queued, len; - -- queued = len = safexcel_queued_len(req); -+ queued = safexcel_queued_len(req); - if (queued <= HASH_CACHE_SIZE) - cache_len = queued; - else -@@ -287,15 +347,52 @@ static int safexcel_ahash_send_req(struc - areq->nbytes - extra); - - queued -= extra; -- len -= extra; - - if (!queued) { - *commands = 0; - *results = 0; - return 0; - } -+ -+ extra = 0; -+ } -+ -+ if (unlikely(req->xcbcmac && req->processed > AES_BLOCK_SIZE)) { -+ if (unlikely(cache_len < AES_BLOCK_SIZE)) { -+ /* -+ * Cache contains less than 1 full block, complete. -+ */ -+ extra = AES_BLOCK_SIZE - cache_len; -+ if (queued > cache_len) { -+ /* More data follows: borrow bytes */ -+ u64 tmp = queued - cache_len; -+ -+ skip = min_t(u64, tmp, extra); -+ sg_pcopy_to_buffer(areq->src, -+ sg_nents(areq->src), -+ req->cache + cache_len, -+ skip, 0); -+ } -+ extra -= skip; -+ memset(req->cache + cache_len + skip, 0, extra); -+ if (!ctx->cbcmac && extra) { -+ // 10- padding for XCBCMAC & CMAC -+ req->cache[cache_len + skip] = 0x80; -+ // HW will use K2 iso K3 - compensate! -+ for (i = 0; i < AES_BLOCK_SIZE / sizeof(u32); i++) -+ ((__be32 *)req->cache)[i] ^= -+ cpu_to_be32(le32_to_cpu( -+ ctx->ipad[i] ^ ctx->ipad[i + 4])); -+ } -+ cache_len = AES_BLOCK_SIZE; -+ queued = queued + extra; -+ } -+ -+ /* XCBC continue: XOR previous result into 1st word */ -+ crypto_xor(req->cache, (const u8 *)req->state, AES_BLOCK_SIZE); - } - -+ len = queued; - /* Add a command descriptor for the cached data, if any */ - if (cache_len) { - req->cache_dma = dma_map_single(priv->dev, req->cache, -@@ -306,8 +403,9 @@ static int safexcel_ahash_send_req(struc - req->cache_sz = cache_len; - first_cdesc = safexcel_add_cdesc(priv, ring, 1, - (cache_len == len), -- req->cache_dma, cache_len, len, -- ctx->base.ctxr_dma); -+ req->cache_dma, cache_len, -+ len, ctx->base.ctxr_dma, -+ &dmmy); - if (IS_ERR(first_cdesc)) { - ret = PTR_ERR(first_cdesc); - goto unmap_cache; -@@ -319,10 +417,6 @@ static int safexcel_ahash_send_req(struc - goto send_command; - } - -- /* Skip descriptor generation for zero-length requests */ -- if (!areq->nbytes) -- goto send_command; -- - /* Now handle the current ahash request buffer(s) */ - req->nents = dma_map_sg(priv->dev, areq->src, - sg_nents_for_len(areq->src, -@@ -336,26 +430,34 @@ static int safexcel_ahash_send_req(struc - for_each_sg(areq->src, sg, req->nents, i) { - int sglen = sg_dma_len(sg); - -+ if (unlikely(sglen <= skip)) { -+ skip -= sglen; -+ continue; -+ } -+ - /* Do not overflow the request */ -- if (queued < sglen) -+ if ((queued + skip) <= sglen) - sglen = queued; -+ else -+ sglen -= skip; - - cdesc = safexcel_add_cdesc(priv, ring, !n_cdesc, - !(queued - sglen), -- sg_dma_address(sg), -- sglen, len, ctx->base.ctxr_dma); -+ sg_dma_address(sg) + skip, sglen, -+ len, ctx->base.ctxr_dma, &dmmy); - if (IS_ERR(cdesc)) { - ret = PTR_ERR(cdesc); - goto unmap_sg; - } -- n_cdesc++; - -- if (n_cdesc == 1) -+ if (!n_cdesc) - first_cdesc = cdesc; -+ n_cdesc++; - - queued -= sglen; - if (!queued) - break; -+ skip = 0; - } - - send_command: -@@ -363,9 +465,9 @@ send_command: - safexcel_context_control(ctx, req, first_cdesc); - - /* Add the token */ -- safexcel_hash_token(first_cdesc, len, req->state_sz); -+ safexcel_hash_token(first_cdesc, len, req->digest_sz, ctx->cbcmac); - -- req->result_dma = dma_map_single(priv->dev, req->state, req->state_sz, -+ req->result_dma = dma_map_single(priv->dev, req->state, req->digest_sz, - DMA_FROM_DEVICE); - if (dma_mapping_error(priv->dev, req->result_dma)) { - ret = -EINVAL; -@@ -374,7 +476,7 @@ send_command: - - /* Add a result descriptor */ - rdesc = safexcel_add_rdesc(priv, ring, 1, 1, req->result_dma, -- req->state_sz); -+ req->digest_sz); - if (IS_ERR(rdesc)) { - ret = PTR_ERR(rdesc); - goto unmap_result; -@@ -382,17 +484,20 @@ send_command: - - safexcel_rdr_req_set(priv, ring, rdesc, &areq->base); - -- req->processed += len; -+ req->processed += len - extra; - - *commands = n_cdesc; - *results = 1; - return 0; - - unmap_result: -- dma_unmap_single(priv->dev, req->result_dma, req->state_sz, -+ dma_unmap_single(priv->dev, req->result_dma, req->digest_sz, - DMA_FROM_DEVICE); - unmap_sg: -- dma_unmap_sg(priv->dev, areq->src, req->nents, DMA_TO_DEVICE); -+ if (req->nents) { -+ dma_unmap_sg(priv->dev, areq->src, req->nents, DMA_TO_DEVICE); -+ req->nents = 0; -+ } - cdesc_rollback: - for (i = 0; i < n_cdesc; i++) - safexcel_ring_rollback_wptr(priv, &priv->ring[ring].cdr); -@@ -590,16 +695,12 @@ static int safexcel_ahash_enqueue(struct - - if (ctx->base.ctxr) { - if (priv->flags & EIP197_TRC_CACHE && !ctx->base.needs_inv && -- req->processed && -- (/* invalidate for basic hash continuation finish */ -- (req->finish && -- (req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED)) || -+ /* invalidate for *any* non-XCBC continuation */ -+ ((req->not_first && !req->xcbcmac) || - /* invalidate if (i)digest changed */ - memcmp(ctx->base.ctxr->data, req->state, req->state_sz) || -- /* invalidate for HMAC continuation finish */ -- (req->finish && (req->processed != req->block_sz)) || - /* invalidate for HMAC finish with odigest changed */ -- (req->finish && -+ (req->finish && req->hmac && - memcmp(ctx->base.ctxr->data + (req->state_sz>>2), - ctx->opad, req->state_sz)))) - /* -@@ -622,6 +723,7 @@ static int safexcel_ahash_enqueue(struct - if (!ctx->base.ctxr) - return -ENOMEM; - } -+ req->not_first = true; - - ring = ctx->base.ring; - -@@ -691,8 +793,34 @@ static int safexcel_ahash_final(struct a - else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA512) - memcpy(areq->result, sha512_zero_message_hash, - SHA512_DIGEST_SIZE); -+ else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SM3) { -+ memcpy(areq->result, -+ EIP197_SM3_ZEROM_HASH, SM3_DIGEST_SIZE); -+ } - - return 0; -+ } else if (unlikely(req->digest == CONTEXT_CONTROL_DIGEST_XCM && -+ ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_MD5 && -+ req->len == sizeof(u32) && !areq->nbytes)) { -+ /* Zero length CRC32 */ -+ memcpy(areq->result, ctx->ipad, sizeof(u32)); -+ return 0; -+ } else if (unlikely(ctx->cbcmac && req->len == AES_BLOCK_SIZE && -+ !areq->nbytes)) { -+ /* Zero length CBC MAC */ -+ memset(areq->result, 0, AES_BLOCK_SIZE); -+ return 0; -+ } else if (unlikely(req->xcbcmac && req->len == AES_BLOCK_SIZE && -+ !areq->nbytes)) { -+ /* Zero length (X)CBC/CMAC */ -+ int i; -+ -+ for (i = 0; i < AES_BLOCK_SIZE / sizeof(u32); i++) -+ ((__be32 *)areq->result)[i] = -+ cpu_to_be32(le32_to_cpu(ctx->ipad[i + 4]));//K3 -+ areq->result[0] ^= 0x80; // 10- padding -+ crypto_cipher_encrypt_one(ctx->kaes, areq->result, areq->result); -+ return 0; - } else if (unlikely(req->hmac && - (req->len == req->block_sz) && - !areq->nbytes)) { -@@ -792,6 +920,7 @@ static int safexcel_ahash_cra_init(struc - ctx->priv = tmpl->priv; - ctx->base.send = safexcel_ahash_send; - ctx->base.handle_result = safexcel_handle_result; -+ ctx->fb_do_setkey = false; - - crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), - sizeof(struct safexcel_ahash_req)); -@@ -808,6 +937,7 @@ static int safexcel_sha1_init(struct aha - ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1; - req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; - req->state_sz = SHA1_DIGEST_SIZE; -+ req->digest_sz = SHA1_DIGEST_SIZE; - req->block_sz = SHA1_BLOCK_SIZE; - - return 0; -@@ -889,6 +1019,7 @@ static int safexcel_hmac_sha1_init(struc - ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1; - req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; - req->state_sz = SHA1_DIGEST_SIZE; -+ req->digest_sz = SHA1_DIGEST_SIZE; - req->block_sz = SHA1_BLOCK_SIZE; - req->hmac = true; - -@@ -1125,6 +1256,7 @@ static int safexcel_sha256_init(struct a - ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256; - req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; - req->state_sz = SHA256_DIGEST_SIZE; -+ req->digest_sz = SHA256_DIGEST_SIZE; - req->block_sz = SHA256_BLOCK_SIZE; - - return 0; -@@ -1180,6 +1312,7 @@ static int safexcel_sha224_init(struct a - ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224; - req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; - req->state_sz = SHA256_DIGEST_SIZE; -+ req->digest_sz = SHA256_DIGEST_SIZE; - req->block_sz = SHA256_BLOCK_SIZE; - - return 0; -@@ -1248,6 +1381,7 @@ static int safexcel_hmac_sha224_init(str - ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224; - req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; - req->state_sz = SHA256_DIGEST_SIZE; -+ req->digest_sz = SHA256_DIGEST_SIZE; - req->block_sz = SHA256_BLOCK_SIZE; - req->hmac = true; - -@@ -1318,6 +1452,7 @@ static int safexcel_hmac_sha256_init(str - ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256; - req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; - req->state_sz = SHA256_DIGEST_SIZE; -+ req->digest_sz = SHA256_DIGEST_SIZE; - req->block_sz = SHA256_BLOCK_SIZE; - req->hmac = true; - -@@ -1375,6 +1510,7 @@ static int safexcel_sha512_init(struct a - ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA512; - req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; - req->state_sz = SHA512_DIGEST_SIZE; -+ req->digest_sz = SHA512_DIGEST_SIZE; - req->block_sz = SHA512_BLOCK_SIZE; - - return 0; -@@ -1430,6 +1566,7 @@ static int safexcel_sha384_init(struct a - ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA384; - req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; - req->state_sz = SHA512_DIGEST_SIZE; -+ req->digest_sz = SHA512_DIGEST_SIZE; - req->block_sz = SHA512_BLOCK_SIZE; - - return 0; -@@ -1498,6 +1635,7 @@ static int safexcel_hmac_sha512_init(str - ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA512; - req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; - req->state_sz = SHA512_DIGEST_SIZE; -+ req->digest_sz = SHA512_DIGEST_SIZE; - req->block_sz = SHA512_BLOCK_SIZE; - req->hmac = true; - -@@ -1568,6 +1706,7 @@ static int safexcel_hmac_sha384_init(str - ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA384; - req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; - req->state_sz = SHA512_DIGEST_SIZE; -+ req->digest_sz = SHA512_DIGEST_SIZE; - req->block_sz = SHA512_BLOCK_SIZE; - req->hmac = true; - -@@ -1625,6 +1764,7 @@ static int safexcel_md5_init(struct ahas - ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_MD5; - req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; - req->state_sz = MD5_DIGEST_SIZE; -+ req->digest_sz = MD5_DIGEST_SIZE; - req->block_sz = MD5_HMAC_BLOCK_SIZE; - - return 0; -@@ -1686,6 +1826,7 @@ static int safexcel_hmac_md5_init(struct - ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_MD5; - req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; - req->state_sz = MD5_DIGEST_SIZE; -+ req->digest_sz = MD5_DIGEST_SIZE; - req->block_sz = MD5_HMAC_BLOCK_SIZE; - req->len_is_le = true; /* MD5 is little endian! ... */ - req->hmac = true; -@@ -1738,5 +1879,1235 @@ struct safexcel_alg_template safexcel_al - .cra_module = THIS_MODULE, - }, - }, -+ }, -+}; -+ -+static int safexcel_crc32_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); -+ int ret = safexcel_ahash_cra_init(tfm); -+ -+ /* Default 'key' is all zeroes */ -+ memset(ctx->ipad, 0, sizeof(u32)); -+ return ret; -+} -+ -+static int safexcel_crc32_init(struct ahash_request *areq) -+{ -+ struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); -+ struct safexcel_ahash_req *req = ahash_request_ctx(areq); -+ -+ memset(req, 0, sizeof(*req)); -+ -+ /* Start from loaded key */ -+ req->state[0] = (__force __le32)le32_to_cpu(~ctx->ipad[0]); -+ /* Set processed to non-zero to enable invalidation detection */ -+ req->len = sizeof(u32); -+ req->processed = sizeof(u32); -+ -+ ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_CRC32; -+ req->digest = CONTEXT_CONTROL_DIGEST_XCM; -+ req->state_sz = sizeof(u32); -+ req->digest_sz = sizeof(u32); -+ req->block_sz = sizeof(u32); -+ -+ return 0; -+} -+ -+static int safexcel_crc32_setkey(struct crypto_ahash *tfm, const u8 *key, -+ unsigned int keylen) -+{ -+ struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); -+ -+ if (keylen != sizeof(u32)) -+ return -EINVAL; -+ -+ memcpy(ctx->ipad, key, sizeof(u32)); -+ return 0; -+} -+ -+static int safexcel_crc32_digest(struct ahash_request *areq) -+{ -+ return safexcel_crc32_init(areq) ?: safexcel_ahash_finup(areq); -+} -+ -+struct safexcel_alg_template safexcel_alg_crc32 = { -+ .type = SAFEXCEL_ALG_TYPE_AHASH, -+ .algo_mask = 0, -+ .alg.ahash = { -+ .init = safexcel_crc32_init, -+ .update = safexcel_ahash_update, -+ .final = safexcel_ahash_final, -+ .finup = safexcel_ahash_finup, -+ .digest = safexcel_crc32_digest, -+ .setkey = safexcel_crc32_setkey, -+ .export = safexcel_ahash_export, -+ .import = safexcel_ahash_import, -+ .halg = { -+ .digestsize = sizeof(u32), -+ .statesize = sizeof(struct safexcel_ahash_export_state), -+ .base = { -+ .cra_name = "crc32", -+ .cra_driver_name = "safexcel-crc32", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_OPTIONAL_KEY | -+ CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = 1, -+ .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), -+ .cra_init = safexcel_crc32_cra_init, -+ .cra_exit = safexcel_ahash_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+ }, -+}; -+ -+static int safexcel_cbcmac_init(struct ahash_request *areq) -+{ -+ struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); -+ struct safexcel_ahash_req *req = ahash_request_ctx(areq); -+ -+ memset(req, 0, sizeof(*req)); -+ -+ /* Start from loaded keys */ -+ memcpy(req->state, ctx->ipad, ctx->key_sz); -+ /* Set processed to non-zero to enable invalidation detection */ -+ req->len = AES_BLOCK_SIZE; -+ req->processed = AES_BLOCK_SIZE; -+ -+ req->digest = CONTEXT_CONTROL_DIGEST_XCM; -+ req->state_sz = ctx->key_sz; -+ req->digest_sz = AES_BLOCK_SIZE; -+ req->block_sz = AES_BLOCK_SIZE; -+ req->xcbcmac = true; -+ -+ return 0; -+} -+ -+static int safexcel_cbcmac_setkey(struct crypto_ahash *tfm, const u8 *key, -+ unsigned int len) -+{ -+ struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); -+ struct crypto_aes_ctx aes; -+ int ret, i; -+ -+ ret = aes_expandkey(&aes, key, len); -+ if (ret) -+ return ret; -+ -+ memset(ctx->ipad, 0, 2 * AES_BLOCK_SIZE); -+ for (i = 0; i < len / sizeof(u32); i++) -+ ctx->ipad[i + 8] = (__force __le32)cpu_to_be32(aes.key_enc[i]); -+ -+ if (len == AES_KEYSIZE_192) { -+ ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC192; -+ ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE; -+ } else if (len == AES_KEYSIZE_256) { -+ ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC256; -+ ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE; -+ } else { -+ ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128; -+ ctx->key_sz = AES_MIN_KEY_SIZE + 2 * AES_BLOCK_SIZE; -+ } -+ ctx->cbcmac = true; -+ -+ memzero_explicit(&aes, sizeof(aes)); -+ return 0; -+} -+ -+static int safexcel_cbcmac_digest(struct ahash_request *areq) -+{ -+ return safexcel_cbcmac_init(areq) ?: safexcel_ahash_finup(areq); -+} -+ -+struct safexcel_alg_template safexcel_alg_cbcmac = { -+ .type = SAFEXCEL_ALG_TYPE_AHASH, -+ .algo_mask = 0, -+ .alg.ahash = { -+ .init = safexcel_cbcmac_init, -+ .update = safexcel_ahash_update, -+ .final = safexcel_ahash_final, -+ .finup = safexcel_ahash_finup, -+ .digest = safexcel_cbcmac_digest, -+ .setkey = safexcel_cbcmac_setkey, -+ .export = safexcel_ahash_export, -+ .import = safexcel_ahash_import, -+ .halg = { -+ .digestsize = AES_BLOCK_SIZE, -+ .statesize = sizeof(struct safexcel_ahash_export_state), -+ .base = { -+ .cra_name = "cbcmac(aes)", -+ .cra_driver_name = "safexcel-cbcmac-aes", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = 1, -+ .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), -+ .cra_init = safexcel_ahash_cra_init, -+ .cra_exit = safexcel_ahash_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+ }, -+}; -+ -+static int safexcel_xcbcmac_setkey(struct crypto_ahash *tfm, const u8 *key, -+ unsigned int len) -+{ -+ struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); -+ struct crypto_aes_ctx aes; -+ u32 key_tmp[3 * AES_BLOCK_SIZE / sizeof(u32)]; -+ int ret, i; -+ -+ ret = aes_expandkey(&aes, key, len); -+ if (ret) -+ return ret; -+ -+ /* precompute the XCBC key material */ -+ crypto_cipher_clear_flags(ctx->kaes, CRYPTO_TFM_REQ_MASK); -+ crypto_cipher_set_flags(ctx->kaes, crypto_ahash_get_flags(tfm) & -+ CRYPTO_TFM_REQ_MASK); -+ ret = crypto_cipher_setkey(ctx->kaes, key, len); -+ if (ret) -+ return ret; -+ -+ crypto_cipher_encrypt_one(ctx->kaes, (u8 *)key_tmp + 2 * AES_BLOCK_SIZE, -+ "\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1"); -+ crypto_cipher_encrypt_one(ctx->kaes, (u8 *)key_tmp, -+ "\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2"); -+ crypto_cipher_encrypt_one(ctx->kaes, (u8 *)key_tmp + AES_BLOCK_SIZE, -+ "\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3"); -+ for (i = 0; i < 3 * AES_BLOCK_SIZE / sizeof(u32); i++) -+ ctx->ipad[i] = -+ cpu_to_le32((__force u32)cpu_to_be32(key_tmp[i])); -+ -+ crypto_cipher_clear_flags(ctx->kaes, CRYPTO_TFM_REQ_MASK); -+ crypto_cipher_set_flags(ctx->kaes, crypto_ahash_get_flags(tfm) & -+ CRYPTO_TFM_REQ_MASK); -+ ret = crypto_cipher_setkey(ctx->kaes, -+ (u8 *)key_tmp + 2 * AES_BLOCK_SIZE, -+ AES_MIN_KEY_SIZE); -+ if (ret) -+ return ret; -+ -+ ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128; -+ ctx->key_sz = AES_MIN_KEY_SIZE + 2 * AES_BLOCK_SIZE; -+ ctx->cbcmac = false; -+ -+ memzero_explicit(&aes, sizeof(aes)); -+ return 0; -+} -+ -+static int safexcel_xcbcmac_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_ahash_cra_init(tfm); -+ ctx->kaes = crypto_alloc_cipher("aes", 0, 0); -+ return PTR_ERR_OR_ZERO(ctx->kaes); -+} -+ -+static void safexcel_xcbcmac_cra_exit(struct crypto_tfm *tfm) -+{ -+ struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ crypto_free_cipher(ctx->kaes); -+ safexcel_ahash_cra_exit(tfm); -+} -+ -+struct safexcel_alg_template safexcel_alg_xcbcmac = { -+ .type = SAFEXCEL_ALG_TYPE_AHASH, -+ .algo_mask = 0, -+ .alg.ahash = { -+ .init = safexcel_cbcmac_init, -+ .update = safexcel_ahash_update, -+ .final = safexcel_ahash_final, -+ .finup = safexcel_ahash_finup, -+ .digest = safexcel_cbcmac_digest, -+ .setkey = safexcel_xcbcmac_setkey, -+ .export = safexcel_ahash_export, -+ .import = safexcel_ahash_import, -+ .halg = { -+ .digestsize = AES_BLOCK_SIZE, -+ .statesize = sizeof(struct safexcel_ahash_export_state), -+ .base = { -+ .cra_name = "xcbc(aes)", -+ .cra_driver_name = "safexcel-xcbc-aes", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = AES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), -+ .cra_init = safexcel_xcbcmac_cra_init, -+ .cra_exit = safexcel_xcbcmac_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+ }, -+}; -+ -+static int safexcel_cmac_setkey(struct crypto_ahash *tfm, const u8 *key, -+ unsigned int len) -+{ -+ struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); -+ struct crypto_aes_ctx aes; -+ __be64 consts[4]; -+ u64 _const[2]; -+ u8 msb_mask, gfmask; -+ int ret, i; -+ -+ ret = aes_expandkey(&aes, key, len); -+ if (ret) -+ return ret; -+ -+ for (i = 0; i < len / sizeof(u32); i++) -+ ctx->ipad[i + 8] = -+ cpu_to_le32((__force u32)cpu_to_be32(aes.key_enc[i])); -+ -+ /* precompute the CMAC key material */ -+ crypto_cipher_clear_flags(ctx->kaes, CRYPTO_TFM_REQ_MASK); -+ crypto_cipher_set_flags(ctx->kaes, crypto_ahash_get_flags(tfm) & -+ CRYPTO_TFM_REQ_MASK); -+ ret = crypto_cipher_setkey(ctx->kaes, key, len); -+ if (ret) -+ return ret; -+ -+ /* code below borrowed from crypto/cmac.c */ -+ /* encrypt the zero block */ -+ memset(consts, 0, AES_BLOCK_SIZE); -+ crypto_cipher_encrypt_one(ctx->kaes, (u8 *)consts, (u8 *)consts); -+ -+ gfmask = 0x87; -+ _const[0] = be64_to_cpu(consts[1]); -+ _const[1] = be64_to_cpu(consts[0]); -+ -+ /* gf(2^128) multiply zero-ciphertext with u and u^2 */ -+ for (i = 0; i < 4; i += 2) { -+ msb_mask = ((s64)_const[1] >> 63) & gfmask; -+ _const[1] = (_const[1] << 1) | (_const[0] >> 63); -+ _const[0] = (_const[0] << 1) ^ msb_mask; -+ -+ consts[i + 0] = cpu_to_be64(_const[1]); -+ consts[i + 1] = cpu_to_be64(_const[0]); -+ } -+ /* end of code borrowed from crypto/cmac.c */ -+ -+ for (i = 0; i < 2 * AES_BLOCK_SIZE / sizeof(u32); i++) -+ ctx->ipad[i] = (__force __le32)cpu_to_be32(((u32 *)consts)[i]); -+ -+ if (len == AES_KEYSIZE_192) { -+ ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC192; -+ ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE; -+ } else if (len == AES_KEYSIZE_256) { -+ ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC256; -+ ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE; -+ } else { -+ ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128; -+ ctx->key_sz = AES_MIN_KEY_SIZE + 2 * AES_BLOCK_SIZE; -+ } -+ ctx->cbcmac = false; -+ -+ memzero_explicit(&aes, sizeof(aes)); -+ return 0; -+} -+ -+struct safexcel_alg_template safexcel_alg_cmac = { -+ .type = SAFEXCEL_ALG_TYPE_AHASH, -+ .algo_mask = 0, -+ .alg.ahash = { -+ .init = safexcel_cbcmac_init, -+ .update = safexcel_ahash_update, -+ .final = safexcel_ahash_final, -+ .finup = safexcel_ahash_finup, -+ .digest = safexcel_cbcmac_digest, -+ .setkey = safexcel_cmac_setkey, -+ .export = safexcel_ahash_export, -+ .import = safexcel_ahash_import, -+ .halg = { -+ .digestsize = AES_BLOCK_SIZE, -+ .statesize = sizeof(struct safexcel_ahash_export_state), -+ .base = { -+ .cra_name = "cmac(aes)", -+ .cra_driver_name = "safexcel-cmac-aes", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = AES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), -+ .cra_init = safexcel_xcbcmac_cra_init, -+ .cra_exit = safexcel_xcbcmac_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+ }, -+}; -+ -+static int safexcel_sm3_init(struct ahash_request *areq) -+{ -+ struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); -+ struct safexcel_ahash_req *req = ahash_request_ctx(areq); -+ -+ memset(req, 0, sizeof(*req)); -+ -+ ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SM3; -+ req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; -+ req->state_sz = SM3_DIGEST_SIZE; -+ req->digest_sz = SM3_DIGEST_SIZE; -+ req->block_sz = SM3_BLOCK_SIZE; -+ -+ return 0; -+} -+ -+static int safexcel_sm3_digest(struct ahash_request *areq) -+{ -+ int ret = safexcel_sm3_init(areq); -+ -+ if (ret) -+ return ret; -+ -+ return safexcel_ahash_finup(areq); -+} -+ -+struct safexcel_alg_template safexcel_alg_sm3 = { -+ .type = SAFEXCEL_ALG_TYPE_AHASH, -+ .algo_mask = SAFEXCEL_ALG_SM3, -+ .alg.ahash = { -+ .init = safexcel_sm3_init, -+ .update = safexcel_ahash_update, -+ .final = safexcel_ahash_final, -+ .finup = safexcel_ahash_finup, -+ .digest = safexcel_sm3_digest, -+ .export = safexcel_ahash_export, -+ .import = safexcel_ahash_import, -+ .halg = { -+ .digestsize = SM3_DIGEST_SIZE, -+ .statesize = sizeof(struct safexcel_ahash_export_state), -+ .base = { -+ .cra_name = "sm3", -+ .cra_driver_name = "safexcel-sm3", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = SM3_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), -+ .cra_init = safexcel_ahash_cra_init, -+ .cra_exit = safexcel_ahash_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+ }, -+}; -+ -+static int safexcel_hmac_sm3_setkey(struct crypto_ahash *tfm, const u8 *key, -+ unsigned int keylen) -+{ -+ return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sm3", -+ SM3_DIGEST_SIZE); -+} -+ -+static int safexcel_hmac_sm3_init(struct ahash_request *areq) -+{ -+ struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); -+ struct safexcel_ahash_req *req = ahash_request_ctx(areq); -+ -+ memset(req, 0, sizeof(*req)); -+ -+ /* Start from ipad precompute */ -+ memcpy(req->state, ctx->ipad, SM3_DIGEST_SIZE); -+ /* Already processed the key^ipad part now! */ -+ req->len = SM3_BLOCK_SIZE; -+ req->processed = SM3_BLOCK_SIZE; -+ -+ ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SM3; -+ req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; -+ req->state_sz = SM3_DIGEST_SIZE; -+ req->digest_sz = SM3_DIGEST_SIZE; -+ req->block_sz = SM3_BLOCK_SIZE; -+ req->hmac = true; -+ -+ return 0; -+} -+ -+static int safexcel_hmac_sm3_digest(struct ahash_request *areq) -+{ -+ int ret = safexcel_hmac_sm3_init(areq); -+ -+ if (ret) -+ return ret; -+ -+ return safexcel_ahash_finup(areq); -+} -+ -+struct safexcel_alg_template safexcel_alg_hmac_sm3 = { -+ .type = SAFEXCEL_ALG_TYPE_AHASH, -+ .algo_mask = SAFEXCEL_ALG_SM3, -+ .alg.ahash = { -+ .init = safexcel_hmac_sm3_init, -+ .update = safexcel_ahash_update, -+ .final = safexcel_ahash_final, -+ .finup = safexcel_ahash_finup, -+ .digest = safexcel_hmac_sm3_digest, -+ .setkey = safexcel_hmac_sm3_setkey, -+ .export = safexcel_ahash_export, -+ .import = safexcel_ahash_import, -+ .halg = { -+ .digestsize = SM3_DIGEST_SIZE, -+ .statesize = sizeof(struct safexcel_ahash_export_state), -+ .base = { -+ .cra_name = "hmac(sm3)", -+ .cra_driver_name = "safexcel-hmac-sm3", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = SM3_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), -+ .cra_init = safexcel_ahash_cra_init, -+ .cra_exit = safexcel_ahash_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+ }, -+}; -+ -+static int safexcel_sha3_224_init(struct ahash_request *areq) -+{ -+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); -+ struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); -+ struct safexcel_ahash_req *req = ahash_request_ctx(areq); -+ -+ memset(req, 0, sizeof(*req)); -+ -+ ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_224; -+ req->digest = CONTEXT_CONTROL_DIGEST_INITIAL; -+ req->state_sz = SHA3_224_DIGEST_SIZE; -+ req->digest_sz = SHA3_224_DIGEST_SIZE; -+ req->block_sz = SHA3_224_BLOCK_SIZE; -+ ctx->do_fallback = false; -+ ctx->fb_init_done = false; -+ return 0; -+} -+ -+static int safexcel_sha3_fbcheck(struct ahash_request *req) -+{ -+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); -+ struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); -+ struct ahash_request *subreq = ahash_request_ctx(req); -+ int ret = 0; -+ -+ if (ctx->do_fallback) { -+ ahash_request_set_tfm(subreq, ctx->fback); -+ ahash_request_set_callback(subreq, req->base.flags, -+ req->base.complete, req->base.data); -+ ahash_request_set_crypt(subreq, req->src, req->result, -+ req->nbytes); -+ if (!ctx->fb_init_done) { -+ if (ctx->fb_do_setkey) { -+ /* Set fallback cipher HMAC key */ -+ u8 key[SHA3_224_BLOCK_SIZE]; -+ -+ memcpy(key, ctx->ipad, -+ crypto_ahash_blocksize(ctx->fback) / 2); -+ memcpy(key + -+ crypto_ahash_blocksize(ctx->fback) / 2, -+ ctx->opad, -+ crypto_ahash_blocksize(ctx->fback) / 2); -+ ret = crypto_ahash_setkey(ctx->fback, key, -+ crypto_ahash_blocksize(ctx->fback)); -+ memzero_explicit(key, -+ crypto_ahash_blocksize(ctx->fback)); -+ ctx->fb_do_setkey = false; -+ } -+ ret = ret ?: crypto_ahash_init(subreq); -+ ctx->fb_init_done = true; -+ } -+ } -+ return ret; -+} -+ -+static int safexcel_sha3_update(struct ahash_request *req) -+{ -+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); -+ struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); -+ struct ahash_request *subreq = ahash_request_ctx(req); -+ -+ ctx->do_fallback = true; -+ return safexcel_sha3_fbcheck(req) ?: crypto_ahash_update(subreq); -+} -+ -+static int safexcel_sha3_final(struct ahash_request *req) -+{ -+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); -+ struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); -+ struct ahash_request *subreq = ahash_request_ctx(req); -+ -+ ctx->do_fallback = true; -+ return safexcel_sha3_fbcheck(req) ?: crypto_ahash_final(subreq); -+} -+ -+static int safexcel_sha3_finup(struct ahash_request *req) -+{ -+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); -+ struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); -+ struct ahash_request *subreq = ahash_request_ctx(req); -+ -+ ctx->do_fallback |= !req->nbytes; -+ if (ctx->do_fallback) -+ /* Update or ex/import happened or len 0, cannot use the HW */ -+ return safexcel_sha3_fbcheck(req) ?: -+ crypto_ahash_finup(subreq); -+ else -+ return safexcel_ahash_finup(req); -+} -+ -+static int safexcel_sha3_digest_fallback(struct ahash_request *req) -+{ -+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); -+ struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); -+ struct ahash_request *subreq = ahash_request_ctx(req); -+ -+ ctx->do_fallback = true; -+ ctx->fb_init_done = false; -+ return safexcel_sha3_fbcheck(req) ?: crypto_ahash_finup(subreq); -+} -+ -+static int safexcel_sha3_224_digest(struct ahash_request *req) -+{ -+ if (req->nbytes) -+ return safexcel_sha3_224_init(req) ?: safexcel_ahash_finup(req); -+ -+ /* HW cannot do zero length hash, use fallback instead */ -+ return safexcel_sha3_digest_fallback(req); -+} -+ -+static int safexcel_sha3_export(struct ahash_request *req, void *out) -+{ -+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); -+ struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); -+ struct ahash_request *subreq = ahash_request_ctx(req); -+ -+ ctx->do_fallback = true; -+ return safexcel_sha3_fbcheck(req) ?: crypto_ahash_export(subreq, out); -+} -+ -+static int safexcel_sha3_import(struct ahash_request *req, const void *in) -+{ -+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); -+ struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); -+ struct ahash_request *subreq = ahash_request_ctx(req); -+ -+ ctx->do_fallback = true; -+ return safexcel_sha3_fbcheck(req) ?: crypto_ahash_import(subreq, in); -+ // return safexcel_ahash_import(req, in); -+} -+ -+static int safexcel_sha3_cra_init(struct crypto_tfm *tfm) -+{ -+ struct crypto_ahash *ahash = __crypto_ahash_cast(tfm); -+ struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_ahash_cra_init(tfm); -+ -+ /* Allocate fallback implementation */ -+ ctx->fback = crypto_alloc_ahash(crypto_tfm_alg_name(tfm), 0, -+ CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_NEED_FALLBACK); -+ if (IS_ERR(ctx->fback)) -+ return PTR_ERR(ctx->fback); -+ -+ /* Update statesize from fallback algorithm! */ -+ crypto_hash_alg_common(ahash)->statesize = -+ crypto_ahash_statesize(ctx->fback); -+ crypto_ahash_set_reqsize(ahash, max(sizeof(struct safexcel_ahash_req), -+ sizeof(struct ahash_request) + -+ crypto_ahash_reqsize(ctx->fback))); -+ return 0; -+} -+ -+static void safexcel_sha3_cra_exit(struct crypto_tfm *tfm) -+{ -+ struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ crypto_free_ahash(ctx->fback); -+ safexcel_ahash_cra_exit(tfm); -+} -+ -+struct safexcel_alg_template safexcel_alg_sha3_224 = { -+ .type = SAFEXCEL_ALG_TYPE_AHASH, -+ .algo_mask = SAFEXCEL_ALG_SHA3, -+ .alg.ahash = { -+ .init = safexcel_sha3_224_init, -+ .update = safexcel_sha3_update, -+ .final = safexcel_sha3_final, -+ .finup = safexcel_sha3_finup, -+ .digest = safexcel_sha3_224_digest, -+ .export = safexcel_sha3_export, -+ .import = safexcel_sha3_import, -+ .halg = { -+ .digestsize = SHA3_224_DIGEST_SIZE, -+ .statesize = sizeof(struct safexcel_ahash_export_state), -+ .base = { -+ .cra_name = "sha3-224", -+ .cra_driver_name = "safexcel-sha3-224", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY | -+ CRYPTO_ALG_NEED_FALLBACK, -+ .cra_blocksize = SHA3_224_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), -+ .cra_init = safexcel_sha3_cra_init, -+ .cra_exit = safexcel_sha3_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+ }, -+}; -+ -+static int safexcel_sha3_256_init(struct ahash_request *areq) -+{ -+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); -+ struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); -+ struct safexcel_ahash_req *req = ahash_request_ctx(areq); -+ -+ memset(req, 0, sizeof(*req)); -+ -+ ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_256; -+ req->digest = CONTEXT_CONTROL_DIGEST_INITIAL; -+ req->state_sz = SHA3_256_DIGEST_SIZE; -+ req->digest_sz = SHA3_256_DIGEST_SIZE; -+ req->block_sz = SHA3_256_BLOCK_SIZE; -+ ctx->do_fallback = false; -+ ctx->fb_init_done = false; -+ return 0; -+} -+ -+static int safexcel_sha3_256_digest(struct ahash_request *req) -+{ -+ if (req->nbytes) -+ return safexcel_sha3_256_init(req) ?: safexcel_ahash_finup(req); -+ -+ /* HW cannot do zero length hash, use fallback instead */ -+ return safexcel_sha3_digest_fallback(req); -+} -+ -+struct safexcel_alg_template safexcel_alg_sha3_256 = { -+ .type = SAFEXCEL_ALG_TYPE_AHASH, -+ .algo_mask = SAFEXCEL_ALG_SHA3, -+ .alg.ahash = { -+ .init = safexcel_sha3_256_init, -+ .update = safexcel_sha3_update, -+ .final = safexcel_sha3_final, -+ .finup = safexcel_sha3_finup, -+ .digest = safexcel_sha3_256_digest, -+ .export = safexcel_sha3_export, -+ .import = safexcel_sha3_import, -+ .halg = { -+ .digestsize = SHA3_256_DIGEST_SIZE, -+ .statesize = sizeof(struct safexcel_ahash_export_state), -+ .base = { -+ .cra_name = "sha3-256", -+ .cra_driver_name = "safexcel-sha3-256", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY | -+ CRYPTO_ALG_NEED_FALLBACK, -+ .cra_blocksize = SHA3_256_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), -+ .cra_init = safexcel_sha3_cra_init, -+ .cra_exit = safexcel_sha3_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+ }, -+}; -+ -+static int safexcel_sha3_384_init(struct ahash_request *areq) -+{ -+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); -+ struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); -+ struct safexcel_ahash_req *req = ahash_request_ctx(areq); -+ -+ memset(req, 0, sizeof(*req)); -+ -+ ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_384; -+ req->digest = CONTEXT_CONTROL_DIGEST_INITIAL; -+ req->state_sz = SHA3_384_DIGEST_SIZE; -+ req->digest_sz = SHA3_384_DIGEST_SIZE; -+ req->block_sz = SHA3_384_BLOCK_SIZE; -+ ctx->do_fallback = false; -+ ctx->fb_init_done = false; -+ return 0; -+} -+ -+static int safexcel_sha3_384_digest(struct ahash_request *req) -+{ -+ if (req->nbytes) -+ return safexcel_sha3_384_init(req) ?: safexcel_ahash_finup(req); -+ -+ /* HW cannot do zero length hash, use fallback instead */ -+ return safexcel_sha3_digest_fallback(req); -+} -+ -+struct safexcel_alg_template safexcel_alg_sha3_384 = { -+ .type = SAFEXCEL_ALG_TYPE_AHASH, -+ .algo_mask = SAFEXCEL_ALG_SHA3, -+ .alg.ahash = { -+ .init = safexcel_sha3_384_init, -+ .update = safexcel_sha3_update, -+ .final = safexcel_sha3_final, -+ .finup = safexcel_sha3_finup, -+ .digest = safexcel_sha3_384_digest, -+ .export = safexcel_sha3_export, -+ .import = safexcel_sha3_import, -+ .halg = { -+ .digestsize = SHA3_384_DIGEST_SIZE, -+ .statesize = sizeof(struct safexcel_ahash_export_state), -+ .base = { -+ .cra_name = "sha3-384", -+ .cra_driver_name = "safexcel-sha3-384", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY | -+ CRYPTO_ALG_NEED_FALLBACK, -+ .cra_blocksize = SHA3_384_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), -+ .cra_init = safexcel_sha3_cra_init, -+ .cra_exit = safexcel_sha3_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+ }, -+}; -+ -+static int safexcel_sha3_512_init(struct ahash_request *areq) -+{ -+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); -+ struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); -+ struct safexcel_ahash_req *req = ahash_request_ctx(areq); -+ -+ memset(req, 0, sizeof(*req)); -+ -+ ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_512; -+ req->digest = CONTEXT_CONTROL_DIGEST_INITIAL; -+ req->state_sz = SHA3_512_DIGEST_SIZE; -+ req->digest_sz = SHA3_512_DIGEST_SIZE; -+ req->block_sz = SHA3_512_BLOCK_SIZE; -+ ctx->do_fallback = false; -+ ctx->fb_init_done = false; -+ return 0; -+} -+ -+static int safexcel_sha3_512_digest(struct ahash_request *req) -+{ -+ if (req->nbytes) -+ return safexcel_sha3_512_init(req) ?: safexcel_ahash_finup(req); -+ -+ /* HW cannot do zero length hash, use fallback instead */ -+ return safexcel_sha3_digest_fallback(req); -+} -+ -+struct safexcel_alg_template safexcel_alg_sha3_512 = { -+ .type = SAFEXCEL_ALG_TYPE_AHASH, -+ .algo_mask = SAFEXCEL_ALG_SHA3, -+ .alg.ahash = { -+ .init = safexcel_sha3_512_init, -+ .update = safexcel_sha3_update, -+ .final = safexcel_sha3_final, -+ .finup = safexcel_sha3_finup, -+ .digest = safexcel_sha3_512_digest, -+ .export = safexcel_sha3_export, -+ .import = safexcel_sha3_import, -+ .halg = { -+ .digestsize = SHA3_512_DIGEST_SIZE, -+ .statesize = sizeof(struct safexcel_ahash_export_state), -+ .base = { -+ .cra_name = "sha3-512", -+ .cra_driver_name = "safexcel-sha3-512", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY | -+ CRYPTO_ALG_NEED_FALLBACK, -+ .cra_blocksize = SHA3_512_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), -+ .cra_init = safexcel_sha3_cra_init, -+ .cra_exit = safexcel_sha3_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+ }, -+}; -+ -+static int safexcel_hmac_sha3_cra_init(struct crypto_tfm *tfm, const char *alg) -+{ -+ struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); -+ int ret; -+ -+ ret = safexcel_sha3_cra_init(tfm); -+ if (ret) -+ return ret; -+ -+ /* Allocate precalc basic digest implementation */ -+ ctx->shpre = crypto_alloc_shash(alg, 0, CRYPTO_ALG_NEED_FALLBACK); -+ if (IS_ERR(ctx->shpre)) -+ return PTR_ERR(ctx->shpre); -+ -+ ctx->shdesc = kmalloc(sizeof(*ctx->shdesc) + -+ crypto_shash_descsize(ctx->shpre), GFP_KERNEL); -+ if (!ctx->shdesc) { -+ crypto_free_shash(ctx->shpre); -+ return -ENOMEM; -+ } -+ ctx->shdesc->tfm = ctx->shpre; -+ return 0; -+} -+ -+static void safexcel_hmac_sha3_cra_exit(struct crypto_tfm *tfm) -+{ -+ struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ crypto_free_ahash(ctx->fback); -+ crypto_free_shash(ctx->shpre); -+ kfree(ctx->shdesc); -+ safexcel_ahash_cra_exit(tfm); -+} -+ -+static int safexcel_hmac_sha3_setkey(struct crypto_ahash *tfm, const u8 *key, -+ unsigned int keylen) -+{ -+ struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); -+ int ret = 0; -+ -+ if (keylen > crypto_ahash_blocksize(tfm)) { -+ /* -+ * If the key is larger than the blocksize, then hash it -+ * first using our fallback cipher -+ */ -+ ret = crypto_shash_digest(ctx->shdesc, key, keylen, -+ (u8 *)ctx->ipad); -+ keylen = crypto_shash_digestsize(ctx->shpre); -+ -+ /* -+ * If the digest is larger than half the blocksize, we need to -+ * move the rest to opad due to the way our HMAC infra works. -+ */ -+ if (keylen > crypto_ahash_blocksize(tfm) / 2) -+ /* Buffers overlap, need to use memmove iso memcpy! */ -+ memmove(ctx->opad, -+ (u8 *)ctx->ipad + -+ crypto_ahash_blocksize(tfm) / 2, -+ keylen - crypto_ahash_blocksize(tfm) / 2); -+ } else { -+ /* -+ * Copy the key to our ipad & opad buffers -+ * Note that ipad and opad each contain one half of the key, -+ * to match the existing HMAC driver infrastructure. -+ */ -+ if (keylen <= crypto_ahash_blocksize(tfm) / 2) { -+ memcpy(ctx->ipad, key, keylen); -+ } else { -+ memcpy(ctx->ipad, key, -+ crypto_ahash_blocksize(tfm) / 2); -+ memcpy(ctx->opad, -+ key + crypto_ahash_blocksize(tfm) / 2, -+ keylen - crypto_ahash_blocksize(tfm) / 2); -+ } -+ } -+ -+ /* Pad key with zeroes */ -+ if (keylen <= crypto_ahash_blocksize(tfm) / 2) { -+ memset((u8 *)ctx->ipad + keylen, 0, -+ crypto_ahash_blocksize(tfm) / 2 - keylen); -+ memset(ctx->opad, 0, crypto_ahash_blocksize(tfm) / 2); -+ } else { -+ memset((u8 *)ctx->opad + keylen - -+ crypto_ahash_blocksize(tfm) / 2, 0, -+ crypto_ahash_blocksize(tfm) - keylen); -+ } -+ -+ /* If doing fallback, still need to set the new key! */ -+ ctx->fb_do_setkey = true; -+ return ret; -+} -+ -+static int safexcel_hmac_sha3_224_init(struct ahash_request *areq) -+{ -+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); -+ struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); -+ struct safexcel_ahash_req *req = ahash_request_ctx(areq); -+ -+ memset(req, 0, sizeof(*req)); -+ -+ /* Copy (half of) the key */ -+ memcpy(req->state, ctx->ipad, SHA3_224_BLOCK_SIZE / 2); -+ /* Start of HMAC should have len == processed == blocksize */ -+ req->len = SHA3_224_BLOCK_SIZE; -+ req->processed = SHA3_224_BLOCK_SIZE; -+ ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_224; -+ req->digest = CONTEXT_CONTROL_DIGEST_HMAC; -+ req->state_sz = SHA3_224_BLOCK_SIZE / 2; -+ req->digest_sz = SHA3_224_DIGEST_SIZE; -+ req->block_sz = SHA3_224_BLOCK_SIZE; -+ req->hmac = true; -+ ctx->do_fallback = false; -+ ctx->fb_init_done = false; -+ return 0; -+} -+ -+static int safexcel_hmac_sha3_224_digest(struct ahash_request *req) -+{ -+ if (req->nbytes) -+ return safexcel_hmac_sha3_224_init(req) ?: -+ safexcel_ahash_finup(req); -+ -+ /* HW cannot do zero length HMAC, use fallback instead */ -+ return safexcel_sha3_digest_fallback(req); -+} -+ -+static int safexcel_hmac_sha3_224_cra_init(struct crypto_tfm *tfm) -+{ -+ return safexcel_hmac_sha3_cra_init(tfm, "sha3-224"); -+} -+ -+struct safexcel_alg_template safexcel_alg_hmac_sha3_224 = { -+ .type = SAFEXCEL_ALG_TYPE_AHASH, -+ .algo_mask = SAFEXCEL_ALG_SHA3, -+ .alg.ahash = { -+ .init = safexcel_hmac_sha3_224_init, -+ .update = safexcel_sha3_update, -+ .final = safexcel_sha3_final, -+ .finup = safexcel_sha3_finup, -+ .digest = safexcel_hmac_sha3_224_digest, -+ .setkey = safexcel_hmac_sha3_setkey, -+ .export = safexcel_sha3_export, -+ .import = safexcel_sha3_import, -+ .halg = { -+ .digestsize = SHA3_224_DIGEST_SIZE, -+ .statesize = sizeof(struct safexcel_ahash_export_state), -+ .base = { -+ .cra_name = "hmac(sha3-224)", -+ .cra_driver_name = "safexcel-hmac-sha3-224", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY | -+ CRYPTO_ALG_NEED_FALLBACK, -+ .cra_blocksize = SHA3_224_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), -+ .cra_init = safexcel_hmac_sha3_224_cra_init, -+ .cra_exit = safexcel_hmac_sha3_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+ }, -+}; -+ -+static int safexcel_hmac_sha3_256_init(struct ahash_request *areq) -+{ -+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); -+ struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); -+ struct safexcel_ahash_req *req = ahash_request_ctx(areq); -+ -+ memset(req, 0, sizeof(*req)); -+ -+ /* Copy (half of) the key */ -+ memcpy(req->state, ctx->ipad, SHA3_256_BLOCK_SIZE / 2); -+ /* Start of HMAC should have len == processed == blocksize */ -+ req->len = SHA3_256_BLOCK_SIZE; -+ req->processed = SHA3_256_BLOCK_SIZE; -+ ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_256; -+ req->digest = CONTEXT_CONTROL_DIGEST_HMAC; -+ req->state_sz = SHA3_256_BLOCK_SIZE / 2; -+ req->digest_sz = SHA3_256_DIGEST_SIZE; -+ req->block_sz = SHA3_256_BLOCK_SIZE; -+ req->hmac = true; -+ ctx->do_fallback = false; -+ ctx->fb_init_done = false; -+ return 0; -+} -+ -+static int safexcel_hmac_sha3_256_digest(struct ahash_request *req) -+{ -+ if (req->nbytes) -+ return safexcel_hmac_sha3_256_init(req) ?: -+ safexcel_ahash_finup(req); -+ -+ /* HW cannot do zero length HMAC, use fallback instead */ -+ return safexcel_sha3_digest_fallback(req); -+} -+ -+static int safexcel_hmac_sha3_256_cra_init(struct crypto_tfm *tfm) -+{ -+ return safexcel_hmac_sha3_cra_init(tfm, "sha3-256"); -+} -+ -+struct safexcel_alg_template safexcel_alg_hmac_sha3_256 = { -+ .type = SAFEXCEL_ALG_TYPE_AHASH, -+ .algo_mask = SAFEXCEL_ALG_SHA3, -+ .alg.ahash = { -+ .init = safexcel_hmac_sha3_256_init, -+ .update = safexcel_sha3_update, -+ .final = safexcel_sha3_final, -+ .finup = safexcel_sha3_finup, -+ .digest = safexcel_hmac_sha3_256_digest, -+ .setkey = safexcel_hmac_sha3_setkey, -+ .export = safexcel_sha3_export, -+ .import = safexcel_sha3_import, -+ .halg = { -+ .digestsize = SHA3_256_DIGEST_SIZE, -+ .statesize = sizeof(struct safexcel_ahash_export_state), -+ .base = { -+ .cra_name = "hmac(sha3-256)", -+ .cra_driver_name = "safexcel-hmac-sha3-256", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY | -+ CRYPTO_ALG_NEED_FALLBACK, -+ .cra_blocksize = SHA3_256_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), -+ .cra_init = safexcel_hmac_sha3_256_cra_init, -+ .cra_exit = safexcel_hmac_sha3_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+ }, -+}; -+ -+static int safexcel_hmac_sha3_384_init(struct ahash_request *areq) -+{ -+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); -+ struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); -+ struct safexcel_ahash_req *req = ahash_request_ctx(areq); -+ -+ memset(req, 0, sizeof(*req)); -+ -+ /* Copy (half of) the key */ -+ memcpy(req->state, ctx->ipad, SHA3_384_BLOCK_SIZE / 2); -+ /* Start of HMAC should have len == processed == blocksize */ -+ req->len = SHA3_384_BLOCK_SIZE; -+ req->processed = SHA3_384_BLOCK_SIZE; -+ ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_384; -+ req->digest = CONTEXT_CONTROL_DIGEST_HMAC; -+ req->state_sz = SHA3_384_BLOCK_SIZE / 2; -+ req->digest_sz = SHA3_384_DIGEST_SIZE; -+ req->block_sz = SHA3_384_BLOCK_SIZE; -+ req->hmac = true; -+ ctx->do_fallback = false; -+ ctx->fb_init_done = false; -+ return 0; -+} -+ -+static int safexcel_hmac_sha3_384_digest(struct ahash_request *req) -+{ -+ if (req->nbytes) -+ return safexcel_hmac_sha3_384_init(req) ?: -+ safexcel_ahash_finup(req); -+ -+ /* HW cannot do zero length HMAC, use fallback instead */ -+ return safexcel_sha3_digest_fallback(req); -+} -+ -+static int safexcel_hmac_sha3_384_cra_init(struct crypto_tfm *tfm) -+{ -+ return safexcel_hmac_sha3_cra_init(tfm, "sha3-384"); -+} -+ -+struct safexcel_alg_template safexcel_alg_hmac_sha3_384 = { -+ .type = SAFEXCEL_ALG_TYPE_AHASH, -+ .algo_mask = SAFEXCEL_ALG_SHA3, -+ .alg.ahash = { -+ .init = safexcel_hmac_sha3_384_init, -+ .update = safexcel_sha3_update, -+ .final = safexcel_sha3_final, -+ .finup = safexcel_sha3_finup, -+ .digest = safexcel_hmac_sha3_384_digest, -+ .setkey = safexcel_hmac_sha3_setkey, -+ .export = safexcel_sha3_export, -+ .import = safexcel_sha3_import, -+ .halg = { -+ .digestsize = SHA3_384_DIGEST_SIZE, -+ .statesize = sizeof(struct safexcel_ahash_export_state), -+ .base = { -+ .cra_name = "hmac(sha3-384)", -+ .cra_driver_name = "safexcel-hmac-sha3-384", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY | -+ CRYPTO_ALG_NEED_FALLBACK, -+ .cra_blocksize = SHA3_384_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), -+ .cra_init = safexcel_hmac_sha3_384_cra_init, -+ .cra_exit = safexcel_hmac_sha3_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+ }, -+}; -+ -+static int safexcel_hmac_sha3_512_init(struct ahash_request *areq) -+{ -+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); -+ struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); -+ struct safexcel_ahash_req *req = ahash_request_ctx(areq); -+ -+ memset(req, 0, sizeof(*req)); -+ -+ /* Copy (half of) the key */ -+ memcpy(req->state, ctx->ipad, SHA3_512_BLOCK_SIZE / 2); -+ /* Start of HMAC should have len == processed == blocksize */ -+ req->len = SHA3_512_BLOCK_SIZE; -+ req->processed = SHA3_512_BLOCK_SIZE; -+ ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_512; -+ req->digest = CONTEXT_CONTROL_DIGEST_HMAC; -+ req->state_sz = SHA3_512_BLOCK_SIZE / 2; -+ req->digest_sz = SHA3_512_DIGEST_SIZE; -+ req->block_sz = SHA3_512_BLOCK_SIZE; -+ req->hmac = true; -+ ctx->do_fallback = false; -+ ctx->fb_init_done = false; -+ return 0; -+} -+ -+static int safexcel_hmac_sha3_512_digest(struct ahash_request *req) -+{ -+ if (req->nbytes) -+ return safexcel_hmac_sha3_512_init(req) ?: -+ safexcel_ahash_finup(req); -+ -+ /* HW cannot do zero length HMAC, use fallback instead */ -+ return safexcel_sha3_digest_fallback(req); -+} -+ -+static int safexcel_hmac_sha3_512_cra_init(struct crypto_tfm *tfm) -+{ -+ return safexcel_hmac_sha3_cra_init(tfm, "sha3-512"); -+} -+struct safexcel_alg_template safexcel_alg_hmac_sha3_512 = { -+ .type = SAFEXCEL_ALG_TYPE_AHASH, -+ .algo_mask = SAFEXCEL_ALG_SHA3, -+ .alg.ahash = { -+ .init = safexcel_hmac_sha3_512_init, -+ .update = safexcel_sha3_update, -+ .final = safexcel_sha3_final, -+ .finup = safexcel_sha3_finup, -+ .digest = safexcel_hmac_sha3_512_digest, -+ .setkey = safexcel_hmac_sha3_setkey, -+ .export = safexcel_sha3_export, -+ .import = safexcel_sha3_import, -+ .halg = { -+ .digestsize = SHA3_512_DIGEST_SIZE, -+ .statesize = sizeof(struct safexcel_ahash_export_state), -+ .base = { -+ .cra_name = "hmac(sha3-512)", -+ .cra_driver_name = "safexcel-hmac-sha3-512", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY | -+ CRYPTO_ALG_NEED_FALLBACK, -+ .cra_blocksize = SHA3_512_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), -+ .cra_init = safexcel_hmac_sha3_512_cra_init, -+ .cra_exit = safexcel_hmac_sha3_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, - }, - }; ---- a/drivers/crypto/inside-secure/safexcel_ring.c -+++ b/drivers/crypto/inside-secure/safexcel_ring.c -@@ -14,7 +14,12 @@ int safexcel_init_ring_descriptors(struc - struct safexcel_desc_ring *cdr, - struct safexcel_desc_ring *rdr) - { -- cdr->offset = sizeof(u32) * priv->config.cd_offset; -+ int i; -+ struct safexcel_command_desc *cdesc; -+ dma_addr_t atok; -+ -+ /* Actual command descriptor ring */ -+ cdr->offset = priv->config.cd_offset; - cdr->base = dmam_alloc_coherent(priv->dev, - cdr->offset * EIP197_DEFAULT_RING_SIZE, - &cdr->base_dma, GFP_KERNEL); -@@ -24,7 +29,34 @@ int safexcel_init_ring_descriptors(struc - cdr->base_end = cdr->base + cdr->offset * (EIP197_DEFAULT_RING_SIZE - 1); - cdr->read = cdr->base; - -- rdr->offset = sizeof(u32) * priv->config.rd_offset; -+ /* Command descriptor shadow ring for storing additional token data */ -+ cdr->shoffset = priv->config.cdsh_offset; -+ cdr->shbase = dmam_alloc_coherent(priv->dev, -+ cdr->shoffset * -+ EIP197_DEFAULT_RING_SIZE, -+ &cdr->shbase_dma, GFP_KERNEL); -+ if (!cdr->shbase) -+ return -ENOMEM; -+ cdr->shwrite = cdr->shbase; -+ cdr->shbase_end = cdr->shbase + cdr->shoffset * -+ (EIP197_DEFAULT_RING_SIZE - 1); -+ -+ /* -+ * Populate command descriptors with physical pointers to shadow descs. -+ * Note that we only need to do this once if we don't overwrite them. -+ */ -+ cdesc = cdr->base; -+ atok = cdr->shbase_dma; -+ for (i = 0; i < EIP197_DEFAULT_RING_SIZE; i++) { -+ cdesc->atok_lo = lower_32_bits(atok); -+ cdesc->atok_hi = upper_32_bits(atok); -+ cdesc = (void *)cdesc + cdr->offset; -+ atok += cdr->shoffset; -+ } -+ -+ rdr->offset = priv->config.rd_offset; -+ /* Use shoffset for result token offset here */ -+ rdr->shoffset = priv->config.res_offset; - rdr->base = dmam_alloc_coherent(priv->dev, - rdr->offset * EIP197_DEFAULT_RING_SIZE, - &rdr->base_dma, GFP_KERNEL); -@@ -42,11 +74,40 @@ inline int safexcel_select_ring(struct s - return (atomic_inc_return(&priv->ring_used) % priv->config.rings); - } - --static void *safexcel_ring_next_wptr(struct safexcel_crypto_priv *priv, -- struct safexcel_desc_ring *ring) -+static void *safexcel_ring_next_cwptr(struct safexcel_crypto_priv *priv, -+ struct safexcel_desc_ring *ring, -+ bool first, -+ struct safexcel_token **atoken) - { - void *ptr = ring->write; - -+ if (first) -+ *atoken = ring->shwrite; -+ -+ if ((ring->write == ring->read - ring->offset) || -+ (ring->read == ring->base && ring->write == ring->base_end)) -+ return ERR_PTR(-ENOMEM); -+ -+ if (ring->write == ring->base_end) { -+ ring->write = ring->base; -+ ring->shwrite = ring->shbase; -+ } else { -+ ring->write += ring->offset; -+ ring->shwrite += ring->shoffset; -+ } -+ -+ return ptr; -+} -+ -+static void *safexcel_ring_next_rwptr(struct safexcel_crypto_priv *priv, -+ struct safexcel_desc_ring *ring, -+ struct result_data_desc **rtoken) -+{ -+ void *ptr = ring->write; -+ -+ /* Result token at relative offset shoffset */ -+ *rtoken = ring->write + ring->shoffset; -+ - if ((ring->write == ring->read - ring->offset) || - (ring->read == ring->base && ring->write == ring->base_end)) - return ERR_PTR(-ENOMEM); -@@ -106,10 +167,13 @@ void safexcel_ring_rollback_wptr(struct - if (ring->write == ring->read) - return; - -- if (ring->write == ring->base) -+ if (ring->write == ring->base) { - ring->write = ring->base_end; -- else -+ ring->shwrite = ring->shbase_end; -+ } else { - ring->write -= ring->offset; -+ ring->shwrite -= ring->shoffset; -+ } - } - - struct safexcel_command_desc *safexcel_add_cdesc(struct safexcel_crypto_priv *priv, -@@ -117,26 +181,26 @@ struct safexcel_command_desc *safexcel_a - bool first, bool last, - dma_addr_t data, u32 data_len, - u32 full_data_len, -- dma_addr_t context) { -+ dma_addr_t context, -+ struct safexcel_token **atoken) -+{ - struct safexcel_command_desc *cdesc; -- int i; - -- cdesc = safexcel_ring_next_wptr(priv, &priv->ring[ring_id].cdr); -+ cdesc = safexcel_ring_next_cwptr(priv, &priv->ring[ring_id].cdr, -+ first, atoken); - if (IS_ERR(cdesc)) - return cdesc; - -- memset(cdesc, 0, sizeof(struct safexcel_command_desc)); -- -- cdesc->first_seg = first; -- cdesc->last_seg = last; - cdesc->particle_size = data_len; -+ cdesc->rsvd0 = 0; -+ cdesc->last_seg = last; -+ cdesc->first_seg = first; -+ cdesc->additional_cdata_size = 0; -+ cdesc->rsvd1 = 0; - cdesc->data_lo = lower_32_bits(data); - cdesc->data_hi = upper_32_bits(data); - -- if (first && context) { -- struct safexcel_token *token = -- (struct safexcel_token *)cdesc->control_data.token; -- -+ if (first) { - /* - * Note that the length here MUST be >0 or else the EIP(1)97 - * may hang. Newer EIP197 firmware actually incorporates this -@@ -146,20 +210,12 @@ struct safexcel_command_desc *safexcel_a - cdesc->control_data.packet_length = full_data_len ?: 1; - cdesc->control_data.options = EIP197_OPTION_MAGIC_VALUE | - EIP197_OPTION_64BIT_CTX | -- EIP197_OPTION_CTX_CTRL_IN_CMD; -- cdesc->control_data.context_lo = -- (lower_32_bits(context) & GENMASK(31, 2)) >> 2; -+ EIP197_OPTION_CTX_CTRL_IN_CMD | -+ EIP197_OPTION_RC_AUTO; -+ cdesc->control_data.type = EIP197_TYPE_BCLA; -+ cdesc->control_data.context_lo = lower_32_bits(context) | -+ EIP197_CONTEXT_SMALL; - cdesc->control_data.context_hi = upper_32_bits(context); -- -- if (priv->version == EIP197B_MRVL || -- priv->version == EIP197D_MRVL) -- cdesc->control_data.options |= EIP197_OPTION_RC_AUTO; -- -- /* TODO: large xform HMAC with SHA-384/512 uses refresh = 3 */ -- cdesc->control_data.refresh = 2; -- -- for (i = 0; i < EIP197_MAX_TOKENS; i++) -- eip197_noop_token(&token[i]); - } - - return cdesc; -@@ -171,18 +227,27 @@ struct safexcel_result_desc *safexcel_ad - dma_addr_t data, u32 len) - { - struct safexcel_result_desc *rdesc; -+ struct result_data_desc *rtoken; - -- rdesc = safexcel_ring_next_wptr(priv, &priv->ring[ring_id].rdr); -+ rdesc = safexcel_ring_next_rwptr(priv, &priv->ring[ring_id].rdr, -+ &rtoken); - if (IS_ERR(rdesc)) - return rdesc; - -- memset(rdesc, 0, sizeof(struct safexcel_result_desc)); -- -- rdesc->first_seg = first; -- rdesc->last_seg = last; - rdesc->particle_size = len; -+ rdesc->rsvd0 = 0; -+ rdesc->descriptor_overflow = 0; -+ rdesc->buffer_overflow = 0; -+ rdesc->last_seg = last; -+ rdesc->first_seg = first; -+ rdesc->result_size = EIP197_RD64_RESULT_SIZE; -+ rdesc->rsvd1 = 0; - rdesc->data_lo = lower_32_bits(data); - rdesc->data_hi = upper_32_bits(data); - -+ /* Clear length & error code in result token */ -+ rtoken->packet_length = 0; -+ rtoken->error_code = 0; -+ - return rdesc; - } |