18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * talitos - Freescale Integrated Security Engine (SEC) device driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2008-2011 Freescale Semiconductor, Inc. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Scatterlist Crypto API glue code copied from files with the following: 88c2ecf20Sopenharmony_ci * Copyright (c) 2006-2007 Herbert Xu <herbert@gondor.apana.org.au> 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Crypto algorithm registration code copied from hifn driver: 118c2ecf20Sopenharmony_ci * 2007+ Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru> 128c2ecf20Sopenharmony_ci * All rights reserved. 138c2ecf20Sopenharmony_ci */ 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include <linux/kernel.h> 168c2ecf20Sopenharmony_ci#include <linux/module.h> 178c2ecf20Sopenharmony_ci#include <linux/mod_devicetable.h> 188c2ecf20Sopenharmony_ci#include <linux/device.h> 198c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 208c2ecf20Sopenharmony_ci#include <linux/crypto.h> 218c2ecf20Sopenharmony_ci#include <linux/hw_random.h> 228c2ecf20Sopenharmony_ci#include <linux/of_address.h> 238c2ecf20Sopenharmony_ci#include <linux/of_irq.h> 248c2ecf20Sopenharmony_ci#include <linux/of_platform.h> 258c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h> 268c2ecf20Sopenharmony_ci#include <linux/io.h> 278c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 288c2ecf20Sopenharmony_ci#include <linux/rtnetlink.h> 298c2ecf20Sopenharmony_ci#include <linux/slab.h> 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci#include <crypto/algapi.h> 328c2ecf20Sopenharmony_ci#include <crypto/aes.h> 338c2ecf20Sopenharmony_ci#include <crypto/internal/des.h> 348c2ecf20Sopenharmony_ci#include <crypto/sha.h> 358c2ecf20Sopenharmony_ci#include <crypto/md5.h> 368c2ecf20Sopenharmony_ci#include <crypto/internal/aead.h> 378c2ecf20Sopenharmony_ci#include <crypto/authenc.h> 388c2ecf20Sopenharmony_ci#include <crypto/internal/skcipher.h> 398c2ecf20Sopenharmony_ci#include <crypto/hash.h> 408c2ecf20Sopenharmony_ci#include <crypto/internal/hash.h> 418c2ecf20Sopenharmony_ci#include <crypto/scatterwalk.h> 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci#include "talitos.h" 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cistatic void to_talitos_ptr(struct talitos_ptr *ptr, dma_addr_t dma_addr, 468c2ecf20Sopenharmony_ci unsigned int len, bool is_sec1) 478c2ecf20Sopenharmony_ci{ 488c2ecf20Sopenharmony_ci ptr->ptr = cpu_to_be32(lower_32_bits(dma_addr)); 498c2ecf20Sopenharmony_ci if (is_sec1) { 508c2ecf20Sopenharmony_ci ptr->len1 = cpu_to_be16(len); 518c2ecf20Sopenharmony_ci } else { 528c2ecf20Sopenharmony_ci ptr->len = cpu_to_be16(len); 538c2ecf20Sopenharmony_ci ptr->eptr = upper_32_bits(dma_addr); 548c2ecf20Sopenharmony_ci } 558c2ecf20Sopenharmony_ci} 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_cistatic void copy_talitos_ptr(struct talitos_ptr *dst_ptr, 588c2ecf20Sopenharmony_ci struct talitos_ptr *src_ptr, bool is_sec1) 598c2ecf20Sopenharmony_ci{ 608c2ecf20Sopenharmony_ci dst_ptr->ptr = src_ptr->ptr; 618c2ecf20Sopenharmony_ci if (is_sec1) { 628c2ecf20Sopenharmony_ci dst_ptr->len1 = src_ptr->len1; 638c2ecf20Sopenharmony_ci } else { 648c2ecf20Sopenharmony_ci dst_ptr->len = src_ptr->len; 658c2ecf20Sopenharmony_ci dst_ptr->eptr = src_ptr->eptr; 668c2ecf20Sopenharmony_ci } 678c2ecf20Sopenharmony_ci} 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_cistatic unsigned short from_talitos_ptr_len(struct talitos_ptr *ptr, 708c2ecf20Sopenharmony_ci bool is_sec1) 718c2ecf20Sopenharmony_ci{ 728c2ecf20Sopenharmony_ci if (is_sec1) 738c2ecf20Sopenharmony_ci return be16_to_cpu(ptr->len1); 748c2ecf20Sopenharmony_ci else 758c2ecf20Sopenharmony_ci return be16_to_cpu(ptr->len); 768c2ecf20Sopenharmony_ci} 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_cistatic void to_talitos_ptr_ext_set(struct talitos_ptr *ptr, u8 val, 798c2ecf20Sopenharmony_ci bool is_sec1) 808c2ecf20Sopenharmony_ci{ 818c2ecf20Sopenharmony_ci if (!is_sec1) 828c2ecf20Sopenharmony_ci ptr->j_extent = val; 838c2ecf20Sopenharmony_ci} 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_cistatic void to_talitos_ptr_ext_or(struct talitos_ptr *ptr, u8 val, bool is_sec1) 868c2ecf20Sopenharmony_ci{ 878c2ecf20Sopenharmony_ci if (!is_sec1) 888c2ecf20Sopenharmony_ci ptr->j_extent |= val; 898c2ecf20Sopenharmony_ci} 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci/* 928c2ecf20Sopenharmony_ci * map virtual single (contiguous) pointer to h/w descriptor pointer 938c2ecf20Sopenharmony_ci */ 948c2ecf20Sopenharmony_cistatic void __map_single_talitos_ptr(struct device *dev, 958c2ecf20Sopenharmony_ci struct talitos_ptr *ptr, 968c2ecf20Sopenharmony_ci unsigned int len, void *data, 978c2ecf20Sopenharmony_ci enum dma_data_direction dir, 988c2ecf20Sopenharmony_ci unsigned long attrs) 998c2ecf20Sopenharmony_ci{ 1008c2ecf20Sopenharmony_ci dma_addr_t dma_addr = dma_map_single_attrs(dev, data, len, dir, attrs); 1018c2ecf20Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 1028c2ecf20Sopenharmony_ci bool is_sec1 = has_ftr_sec1(priv); 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci to_talitos_ptr(ptr, dma_addr, len, is_sec1); 1058c2ecf20Sopenharmony_ci} 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_cistatic void map_single_talitos_ptr(struct device *dev, 1088c2ecf20Sopenharmony_ci struct talitos_ptr *ptr, 1098c2ecf20Sopenharmony_ci unsigned int len, void *data, 1108c2ecf20Sopenharmony_ci enum dma_data_direction dir) 1118c2ecf20Sopenharmony_ci{ 1128c2ecf20Sopenharmony_ci __map_single_talitos_ptr(dev, ptr, len, data, dir, 0); 1138c2ecf20Sopenharmony_ci} 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_cistatic void map_single_talitos_ptr_nosync(struct device *dev, 1168c2ecf20Sopenharmony_ci struct talitos_ptr *ptr, 1178c2ecf20Sopenharmony_ci unsigned int len, void *data, 1188c2ecf20Sopenharmony_ci enum dma_data_direction dir) 1198c2ecf20Sopenharmony_ci{ 1208c2ecf20Sopenharmony_ci __map_single_talitos_ptr(dev, ptr, len, data, dir, 1218c2ecf20Sopenharmony_ci DMA_ATTR_SKIP_CPU_SYNC); 1228c2ecf20Sopenharmony_ci} 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci/* 1258c2ecf20Sopenharmony_ci * unmap bus single (contiguous) h/w descriptor pointer 1268c2ecf20Sopenharmony_ci */ 1278c2ecf20Sopenharmony_cistatic void unmap_single_talitos_ptr(struct device *dev, 1288c2ecf20Sopenharmony_ci struct talitos_ptr *ptr, 1298c2ecf20Sopenharmony_ci enum dma_data_direction dir) 1308c2ecf20Sopenharmony_ci{ 1318c2ecf20Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 1328c2ecf20Sopenharmony_ci bool is_sec1 = has_ftr_sec1(priv); 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci dma_unmap_single(dev, be32_to_cpu(ptr->ptr), 1358c2ecf20Sopenharmony_ci from_talitos_ptr_len(ptr, is_sec1), dir); 1368c2ecf20Sopenharmony_ci} 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_cistatic int reset_channel(struct device *dev, int ch) 1398c2ecf20Sopenharmony_ci{ 1408c2ecf20Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 1418c2ecf20Sopenharmony_ci unsigned int timeout = TALITOS_TIMEOUT; 1428c2ecf20Sopenharmony_ci bool is_sec1 = has_ftr_sec1(priv); 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci if (is_sec1) { 1458c2ecf20Sopenharmony_ci setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, 1468c2ecf20Sopenharmony_ci TALITOS1_CCCR_LO_RESET); 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR_LO) & 1498c2ecf20Sopenharmony_ci TALITOS1_CCCR_LO_RESET) && --timeout) 1508c2ecf20Sopenharmony_ci cpu_relax(); 1518c2ecf20Sopenharmony_ci } else { 1528c2ecf20Sopenharmony_ci setbits32(priv->chan[ch].reg + TALITOS_CCCR, 1538c2ecf20Sopenharmony_ci TALITOS2_CCCR_RESET); 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) & 1568c2ecf20Sopenharmony_ci TALITOS2_CCCR_RESET) && --timeout) 1578c2ecf20Sopenharmony_ci cpu_relax(); 1588c2ecf20Sopenharmony_ci } 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci if (timeout == 0) { 1618c2ecf20Sopenharmony_ci dev_err(dev, "failed to reset channel %d\n", ch); 1628c2ecf20Sopenharmony_ci return -EIO; 1638c2ecf20Sopenharmony_ci } 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci /* set 36-bit addressing, done writeback enable and done IRQ enable */ 1668c2ecf20Sopenharmony_ci setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, TALITOS_CCCR_LO_EAE | 1678c2ecf20Sopenharmony_ci TALITOS_CCCR_LO_CDWE | TALITOS_CCCR_LO_CDIE); 1688c2ecf20Sopenharmony_ci /* enable chaining descriptors */ 1698c2ecf20Sopenharmony_ci if (is_sec1) 1708c2ecf20Sopenharmony_ci setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, 1718c2ecf20Sopenharmony_ci TALITOS_CCCR_LO_NE); 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci /* and ICCR writeback, if available */ 1748c2ecf20Sopenharmony_ci if (priv->features & TALITOS_FTR_HW_AUTH_CHECK) 1758c2ecf20Sopenharmony_ci setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, 1768c2ecf20Sopenharmony_ci TALITOS_CCCR_LO_IWSE); 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci return 0; 1798c2ecf20Sopenharmony_ci} 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_cistatic int reset_device(struct device *dev) 1828c2ecf20Sopenharmony_ci{ 1838c2ecf20Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 1848c2ecf20Sopenharmony_ci unsigned int timeout = TALITOS_TIMEOUT; 1858c2ecf20Sopenharmony_ci bool is_sec1 = has_ftr_sec1(priv); 1868c2ecf20Sopenharmony_ci u32 mcr = is_sec1 ? TALITOS1_MCR_SWR : TALITOS2_MCR_SWR; 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci setbits32(priv->reg + TALITOS_MCR, mcr); 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci while ((in_be32(priv->reg + TALITOS_MCR) & mcr) 1918c2ecf20Sopenharmony_ci && --timeout) 1928c2ecf20Sopenharmony_ci cpu_relax(); 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci if (priv->irq[1]) { 1958c2ecf20Sopenharmony_ci mcr = TALITOS_MCR_RCA1 | TALITOS_MCR_RCA3; 1968c2ecf20Sopenharmony_ci setbits32(priv->reg + TALITOS_MCR, mcr); 1978c2ecf20Sopenharmony_ci } 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci if (timeout == 0) { 2008c2ecf20Sopenharmony_ci dev_err(dev, "failed to reset device\n"); 2018c2ecf20Sopenharmony_ci return -EIO; 2028c2ecf20Sopenharmony_ci } 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci return 0; 2058c2ecf20Sopenharmony_ci} 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci/* 2088c2ecf20Sopenharmony_ci * Reset and initialize the device 2098c2ecf20Sopenharmony_ci */ 2108c2ecf20Sopenharmony_cistatic int init_device(struct device *dev) 2118c2ecf20Sopenharmony_ci{ 2128c2ecf20Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 2138c2ecf20Sopenharmony_ci int ch, err; 2148c2ecf20Sopenharmony_ci bool is_sec1 = has_ftr_sec1(priv); 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci /* 2178c2ecf20Sopenharmony_ci * Master reset 2188c2ecf20Sopenharmony_ci * errata documentation: warning: certain SEC interrupts 2198c2ecf20Sopenharmony_ci * are not fully cleared by writing the MCR:SWR bit, 2208c2ecf20Sopenharmony_ci * set bit twice to completely reset 2218c2ecf20Sopenharmony_ci */ 2228c2ecf20Sopenharmony_ci err = reset_device(dev); 2238c2ecf20Sopenharmony_ci if (err) 2248c2ecf20Sopenharmony_ci return err; 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci err = reset_device(dev); 2278c2ecf20Sopenharmony_ci if (err) 2288c2ecf20Sopenharmony_ci return err; 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci /* reset channels */ 2318c2ecf20Sopenharmony_ci for (ch = 0; ch < priv->num_channels; ch++) { 2328c2ecf20Sopenharmony_ci err = reset_channel(dev, ch); 2338c2ecf20Sopenharmony_ci if (err) 2348c2ecf20Sopenharmony_ci return err; 2358c2ecf20Sopenharmony_ci } 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci /* enable channel done and error interrupts */ 2388c2ecf20Sopenharmony_ci if (is_sec1) { 2398c2ecf20Sopenharmony_ci clrbits32(priv->reg + TALITOS_IMR, TALITOS1_IMR_INIT); 2408c2ecf20Sopenharmony_ci clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT); 2418c2ecf20Sopenharmony_ci /* disable parity error check in DEU (erroneous? test vect.) */ 2428c2ecf20Sopenharmony_ci setbits32(priv->reg_deu + TALITOS_EUICR, TALITOS1_DEUICR_KPE); 2438c2ecf20Sopenharmony_ci } else { 2448c2ecf20Sopenharmony_ci setbits32(priv->reg + TALITOS_IMR, TALITOS2_IMR_INIT); 2458c2ecf20Sopenharmony_ci setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT); 2468c2ecf20Sopenharmony_ci } 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci /* disable integrity check error interrupts (use writeback instead) */ 2498c2ecf20Sopenharmony_ci if (priv->features & TALITOS_FTR_HW_AUTH_CHECK) 2508c2ecf20Sopenharmony_ci setbits32(priv->reg_mdeu + TALITOS_EUICR_LO, 2518c2ecf20Sopenharmony_ci TALITOS_MDEUICR_LO_ICE); 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci return 0; 2548c2ecf20Sopenharmony_ci} 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci/** 2578c2ecf20Sopenharmony_ci * talitos_submit - submits a descriptor to the device for processing 2588c2ecf20Sopenharmony_ci * @dev: the SEC device to be used 2598c2ecf20Sopenharmony_ci * @ch: the SEC device channel to be used 2608c2ecf20Sopenharmony_ci * @desc: the descriptor to be processed by the device 2618c2ecf20Sopenharmony_ci * @callback: whom to call when processing is complete 2628c2ecf20Sopenharmony_ci * @context: a handle for use by caller (optional) 2638c2ecf20Sopenharmony_ci * 2648c2ecf20Sopenharmony_ci * desc must contain valid dma-mapped (bus physical) address pointers. 2658c2ecf20Sopenharmony_ci * callback must check err and feedback in descriptor header 2668c2ecf20Sopenharmony_ci * for device processing status. 2678c2ecf20Sopenharmony_ci */ 2688c2ecf20Sopenharmony_cistatic int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc, 2698c2ecf20Sopenharmony_ci void (*callback)(struct device *dev, 2708c2ecf20Sopenharmony_ci struct talitos_desc *desc, 2718c2ecf20Sopenharmony_ci void *context, int error), 2728c2ecf20Sopenharmony_ci void *context) 2738c2ecf20Sopenharmony_ci{ 2748c2ecf20Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 2758c2ecf20Sopenharmony_ci struct talitos_request *request; 2768c2ecf20Sopenharmony_ci unsigned long flags; 2778c2ecf20Sopenharmony_ci int head; 2788c2ecf20Sopenharmony_ci bool is_sec1 = has_ftr_sec1(priv); 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci spin_lock_irqsave(&priv->chan[ch].head_lock, flags); 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci if (!atomic_inc_not_zero(&priv->chan[ch].submit_count)) { 2838c2ecf20Sopenharmony_ci /* h/w fifo is full */ 2848c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags); 2858c2ecf20Sopenharmony_ci return -EAGAIN; 2868c2ecf20Sopenharmony_ci } 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci head = priv->chan[ch].head; 2898c2ecf20Sopenharmony_ci request = &priv->chan[ch].fifo[head]; 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci /* map descriptor and save caller data */ 2928c2ecf20Sopenharmony_ci if (is_sec1) { 2938c2ecf20Sopenharmony_ci desc->hdr1 = desc->hdr; 2948c2ecf20Sopenharmony_ci request->dma_desc = dma_map_single(dev, &desc->hdr1, 2958c2ecf20Sopenharmony_ci TALITOS_DESC_SIZE, 2968c2ecf20Sopenharmony_ci DMA_BIDIRECTIONAL); 2978c2ecf20Sopenharmony_ci } else { 2988c2ecf20Sopenharmony_ci request->dma_desc = dma_map_single(dev, desc, 2998c2ecf20Sopenharmony_ci TALITOS_DESC_SIZE, 3008c2ecf20Sopenharmony_ci DMA_BIDIRECTIONAL); 3018c2ecf20Sopenharmony_ci } 3028c2ecf20Sopenharmony_ci request->callback = callback; 3038c2ecf20Sopenharmony_ci request->context = context; 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci /* increment fifo head */ 3068c2ecf20Sopenharmony_ci priv->chan[ch].head = (priv->chan[ch].head + 1) & (priv->fifo_len - 1); 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci smp_wmb(); 3098c2ecf20Sopenharmony_ci request->desc = desc; 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci /* GO! */ 3128c2ecf20Sopenharmony_ci wmb(); 3138c2ecf20Sopenharmony_ci out_be32(priv->chan[ch].reg + TALITOS_FF, 3148c2ecf20Sopenharmony_ci upper_32_bits(request->dma_desc)); 3158c2ecf20Sopenharmony_ci out_be32(priv->chan[ch].reg + TALITOS_FF_LO, 3168c2ecf20Sopenharmony_ci lower_32_bits(request->dma_desc)); 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags); 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci return -EINPROGRESS; 3218c2ecf20Sopenharmony_ci} 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_cistatic __be32 get_request_hdr(struct talitos_request *request, bool is_sec1) 3248c2ecf20Sopenharmony_ci{ 3258c2ecf20Sopenharmony_ci struct talitos_edesc *edesc; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci if (!is_sec1) 3288c2ecf20Sopenharmony_ci return request->desc->hdr; 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci if (!request->desc->next_desc) 3318c2ecf20Sopenharmony_ci return request->desc->hdr1; 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci edesc = container_of(request->desc, struct talitos_edesc, desc); 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci return ((struct talitos_desc *)(edesc->buf + edesc->dma_len))->hdr1; 3368c2ecf20Sopenharmony_ci} 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci/* 3398c2ecf20Sopenharmony_ci * process what was done, notify callback of error if not 3408c2ecf20Sopenharmony_ci */ 3418c2ecf20Sopenharmony_cistatic void flush_channel(struct device *dev, int ch, int error, int reset_ch) 3428c2ecf20Sopenharmony_ci{ 3438c2ecf20Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 3448c2ecf20Sopenharmony_ci struct talitos_request *request, saved_req; 3458c2ecf20Sopenharmony_ci unsigned long flags; 3468c2ecf20Sopenharmony_ci int tail, status; 3478c2ecf20Sopenharmony_ci bool is_sec1 = has_ftr_sec1(priv); 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci spin_lock_irqsave(&priv->chan[ch].tail_lock, flags); 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci tail = priv->chan[ch].tail; 3528c2ecf20Sopenharmony_ci while (priv->chan[ch].fifo[tail].desc) { 3538c2ecf20Sopenharmony_ci __be32 hdr; 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci request = &priv->chan[ch].fifo[tail]; 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci /* descriptors with their done bits set don't get the error */ 3588c2ecf20Sopenharmony_ci rmb(); 3598c2ecf20Sopenharmony_ci hdr = get_request_hdr(request, is_sec1); 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci if ((hdr & DESC_HDR_DONE) == DESC_HDR_DONE) 3628c2ecf20Sopenharmony_ci status = 0; 3638c2ecf20Sopenharmony_ci else 3648c2ecf20Sopenharmony_ci if (!error) 3658c2ecf20Sopenharmony_ci break; 3668c2ecf20Sopenharmony_ci else 3678c2ecf20Sopenharmony_ci status = error; 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci dma_unmap_single(dev, request->dma_desc, 3708c2ecf20Sopenharmony_ci TALITOS_DESC_SIZE, 3718c2ecf20Sopenharmony_ci DMA_BIDIRECTIONAL); 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci /* copy entries so we can call callback outside lock */ 3748c2ecf20Sopenharmony_ci saved_req.desc = request->desc; 3758c2ecf20Sopenharmony_ci saved_req.callback = request->callback; 3768c2ecf20Sopenharmony_ci saved_req.context = request->context; 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci /* release request entry in fifo */ 3798c2ecf20Sopenharmony_ci smp_wmb(); 3808c2ecf20Sopenharmony_ci request->desc = NULL; 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci /* increment fifo tail */ 3838c2ecf20Sopenharmony_ci priv->chan[ch].tail = (tail + 1) & (priv->fifo_len - 1); 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags); 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci atomic_dec(&priv->chan[ch].submit_count); 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci saved_req.callback(dev, saved_req.desc, saved_req.context, 3908c2ecf20Sopenharmony_ci status); 3918c2ecf20Sopenharmony_ci /* channel may resume processing in single desc error case */ 3928c2ecf20Sopenharmony_ci if (error && !reset_ch && status == error) 3938c2ecf20Sopenharmony_ci return; 3948c2ecf20Sopenharmony_ci spin_lock_irqsave(&priv->chan[ch].tail_lock, flags); 3958c2ecf20Sopenharmony_ci tail = priv->chan[ch].tail; 3968c2ecf20Sopenharmony_ci } 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags); 3998c2ecf20Sopenharmony_ci} 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci/* 4028c2ecf20Sopenharmony_ci * process completed requests for channels that have done status 4038c2ecf20Sopenharmony_ci */ 4048c2ecf20Sopenharmony_ci#define DEF_TALITOS1_DONE(name, ch_done_mask) \ 4058c2ecf20Sopenharmony_cistatic void talitos1_done_##name(unsigned long data) \ 4068c2ecf20Sopenharmony_ci{ \ 4078c2ecf20Sopenharmony_ci struct device *dev = (struct device *)data; \ 4088c2ecf20Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); \ 4098c2ecf20Sopenharmony_ci unsigned long flags; \ 4108c2ecf20Sopenharmony_ci \ 4118c2ecf20Sopenharmony_ci if (ch_done_mask & 0x10000000) \ 4128c2ecf20Sopenharmony_ci flush_channel(dev, 0, 0, 0); \ 4138c2ecf20Sopenharmony_ci if (ch_done_mask & 0x40000000) \ 4148c2ecf20Sopenharmony_ci flush_channel(dev, 1, 0, 0); \ 4158c2ecf20Sopenharmony_ci if (ch_done_mask & 0x00010000) \ 4168c2ecf20Sopenharmony_ci flush_channel(dev, 2, 0, 0); \ 4178c2ecf20Sopenharmony_ci if (ch_done_mask & 0x00040000) \ 4188c2ecf20Sopenharmony_ci flush_channel(dev, 3, 0, 0); \ 4198c2ecf20Sopenharmony_ci \ 4208c2ecf20Sopenharmony_ci /* At this point, all completed channels have been processed */ \ 4218c2ecf20Sopenharmony_ci /* Unmask done interrupts for channels completed later on. */ \ 4228c2ecf20Sopenharmony_ci spin_lock_irqsave(&priv->reg_lock, flags); \ 4238c2ecf20Sopenharmony_ci clrbits32(priv->reg + TALITOS_IMR, ch_done_mask); \ 4248c2ecf20Sopenharmony_ci clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT); \ 4258c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&priv->reg_lock, flags); \ 4268c2ecf20Sopenharmony_ci} 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ciDEF_TALITOS1_DONE(4ch, TALITOS1_ISR_4CHDONE) 4298c2ecf20Sopenharmony_ciDEF_TALITOS1_DONE(ch0, TALITOS1_ISR_CH_0_DONE) 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci#define DEF_TALITOS2_DONE(name, ch_done_mask) \ 4328c2ecf20Sopenharmony_cistatic void talitos2_done_##name(unsigned long data) \ 4338c2ecf20Sopenharmony_ci{ \ 4348c2ecf20Sopenharmony_ci struct device *dev = (struct device *)data; \ 4358c2ecf20Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); \ 4368c2ecf20Sopenharmony_ci unsigned long flags; \ 4378c2ecf20Sopenharmony_ci \ 4388c2ecf20Sopenharmony_ci if (ch_done_mask & 1) \ 4398c2ecf20Sopenharmony_ci flush_channel(dev, 0, 0, 0); \ 4408c2ecf20Sopenharmony_ci if (ch_done_mask & (1 << 2)) \ 4418c2ecf20Sopenharmony_ci flush_channel(dev, 1, 0, 0); \ 4428c2ecf20Sopenharmony_ci if (ch_done_mask & (1 << 4)) \ 4438c2ecf20Sopenharmony_ci flush_channel(dev, 2, 0, 0); \ 4448c2ecf20Sopenharmony_ci if (ch_done_mask & (1 << 6)) \ 4458c2ecf20Sopenharmony_ci flush_channel(dev, 3, 0, 0); \ 4468c2ecf20Sopenharmony_ci \ 4478c2ecf20Sopenharmony_ci /* At this point, all completed channels have been processed */ \ 4488c2ecf20Sopenharmony_ci /* Unmask done interrupts for channels completed later on. */ \ 4498c2ecf20Sopenharmony_ci spin_lock_irqsave(&priv->reg_lock, flags); \ 4508c2ecf20Sopenharmony_ci setbits32(priv->reg + TALITOS_IMR, ch_done_mask); \ 4518c2ecf20Sopenharmony_ci setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT); \ 4528c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&priv->reg_lock, flags); \ 4538c2ecf20Sopenharmony_ci} 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_ciDEF_TALITOS2_DONE(4ch, TALITOS2_ISR_4CHDONE) 4568c2ecf20Sopenharmony_ciDEF_TALITOS2_DONE(ch0, TALITOS2_ISR_CH_0_DONE) 4578c2ecf20Sopenharmony_ciDEF_TALITOS2_DONE(ch0_2, TALITOS2_ISR_CH_0_2_DONE) 4588c2ecf20Sopenharmony_ciDEF_TALITOS2_DONE(ch1_3, TALITOS2_ISR_CH_1_3_DONE) 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci/* 4618c2ecf20Sopenharmony_ci * locate current (offending) descriptor 4628c2ecf20Sopenharmony_ci */ 4638c2ecf20Sopenharmony_cistatic __be32 current_desc_hdr(struct device *dev, int ch) 4648c2ecf20Sopenharmony_ci{ 4658c2ecf20Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 4668c2ecf20Sopenharmony_ci int tail, iter; 4678c2ecf20Sopenharmony_ci dma_addr_t cur_desc; 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci cur_desc = ((u64)in_be32(priv->chan[ch].reg + TALITOS_CDPR)) << 32; 4708c2ecf20Sopenharmony_ci cur_desc |= in_be32(priv->chan[ch].reg + TALITOS_CDPR_LO); 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci if (!cur_desc) { 4738c2ecf20Sopenharmony_ci dev_err(dev, "CDPR is NULL, giving up search for offending descriptor\n"); 4748c2ecf20Sopenharmony_ci return 0; 4758c2ecf20Sopenharmony_ci } 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ci tail = priv->chan[ch].tail; 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci iter = tail; 4808c2ecf20Sopenharmony_ci while (priv->chan[ch].fifo[iter].dma_desc != cur_desc && 4818c2ecf20Sopenharmony_ci priv->chan[ch].fifo[iter].desc->next_desc != cpu_to_be32(cur_desc)) { 4828c2ecf20Sopenharmony_ci iter = (iter + 1) & (priv->fifo_len - 1); 4838c2ecf20Sopenharmony_ci if (iter == tail) { 4848c2ecf20Sopenharmony_ci dev_err(dev, "couldn't locate current descriptor\n"); 4858c2ecf20Sopenharmony_ci return 0; 4868c2ecf20Sopenharmony_ci } 4878c2ecf20Sopenharmony_ci } 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci if (priv->chan[ch].fifo[iter].desc->next_desc == cpu_to_be32(cur_desc)) { 4908c2ecf20Sopenharmony_ci struct talitos_edesc *edesc; 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_ci edesc = container_of(priv->chan[ch].fifo[iter].desc, 4938c2ecf20Sopenharmony_ci struct talitos_edesc, desc); 4948c2ecf20Sopenharmony_ci return ((struct talitos_desc *) 4958c2ecf20Sopenharmony_ci (edesc->buf + edesc->dma_len))->hdr; 4968c2ecf20Sopenharmony_ci } 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ci return priv->chan[ch].fifo[iter].desc->hdr; 4998c2ecf20Sopenharmony_ci} 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci/* 5028c2ecf20Sopenharmony_ci * user diagnostics; report root cause of error based on execution unit status 5038c2ecf20Sopenharmony_ci */ 5048c2ecf20Sopenharmony_cistatic void report_eu_error(struct device *dev, int ch, __be32 desc_hdr) 5058c2ecf20Sopenharmony_ci{ 5068c2ecf20Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 5078c2ecf20Sopenharmony_ci int i; 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci if (!desc_hdr) 5108c2ecf20Sopenharmony_ci desc_hdr = cpu_to_be32(in_be32(priv->chan[ch].reg + TALITOS_DESCBUF)); 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_ci switch (desc_hdr & DESC_HDR_SEL0_MASK) { 5138c2ecf20Sopenharmony_ci case DESC_HDR_SEL0_AFEU: 5148c2ecf20Sopenharmony_ci dev_err(dev, "AFEUISR 0x%08x_%08x\n", 5158c2ecf20Sopenharmony_ci in_be32(priv->reg_afeu + TALITOS_EUISR), 5168c2ecf20Sopenharmony_ci in_be32(priv->reg_afeu + TALITOS_EUISR_LO)); 5178c2ecf20Sopenharmony_ci break; 5188c2ecf20Sopenharmony_ci case DESC_HDR_SEL0_DEU: 5198c2ecf20Sopenharmony_ci dev_err(dev, "DEUISR 0x%08x_%08x\n", 5208c2ecf20Sopenharmony_ci in_be32(priv->reg_deu + TALITOS_EUISR), 5218c2ecf20Sopenharmony_ci in_be32(priv->reg_deu + TALITOS_EUISR_LO)); 5228c2ecf20Sopenharmony_ci break; 5238c2ecf20Sopenharmony_ci case DESC_HDR_SEL0_MDEUA: 5248c2ecf20Sopenharmony_ci case DESC_HDR_SEL0_MDEUB: 5258c2ecf20Sopenharmony_ci dev_err(dev, "MDEUISR 0x%08x_%08x\n", 5268c2ecf20Sopenharmony_ci in_be32(priv->reg_mdeu + TALITOS_EUISR), 5278c2ecf20Sopenharmony_ci in_be32(priv->reg_mdeu + TALITOS_EUISR_LO)); 5288c2ecf20Sopenharmony_ci break; 5298c2ecf20Sopenharmony_ci case DESC_HDR_SEL0_RNG: 5308c2ecf20Sopenharmony_ci dev_err(dev, "RNGUISR 0x%08x_%08x\n", 5318c2ecf20Sopenharmony_ci in_be32(priv->reg_rngu + TALITOS_ISR), 5328c2ecf20Sopenharmony_ci in_be32(priv->reg_rngu + TALITOS_ISR_LO)); 5338c2ecf20Sopenharmony_ci break; 5348c2ecf20Sopenharmony_ci case DESC_HDR_SEL0_PKEU: 5358c2ecf20Sopenharmony_ci dev_err(dev, "PKEUISR 0x%08x_%08x\n", 5368c2ecf20Sopenharmony_ci in_be32(priv->reg_pkeu + TALITOS_EUISR), 5378c2ecf20Sopenharmony_ci in_be32(priv->reg_pkeu + TALITOS_EUISR_LO)); 5388c2ecf20Sopenharmony_ci break; 5398c2ecf20Sopenharmony_ci case DESC_HDR_SEL0_AESU: 5408c2ecf20Sopenharmony_ci dev_err(dev, "AESUISR 0x%08x_%08x\n", 5418c2ecf20Sopenharmony_ci in_be32(priv->reg_aesu + TALITOS_EUISR), 5428c2ecf20Sopenharmony_ci in_be32(priv->reg_aesu + TALITOS_EUISR_LO)); 5438c2ecf20Sopenharmony_ci break; 5448c2ecf20Sopenharmony_ci case DESC_HDR_SEL0_CRCU: 5458c2ecf20Sopenharmony_ci dev_err(dev, "CRCUISR 0x%08x_%08x\n", 5468c2ecf20Sopenharmony_ci in_be32(priv->reg_crcu + TALITOS_EUISR), 5478c2ecf20Sopenharmony_ci in_be32(priv->reg_crcu + TALITOS_EUISR_LO)); 5488c2ecf20Sopenharmony_ci break; 5498c2ecf20Sopenharmony_ci case DESC_HDR_SEL0_KEU: 5508c2ecf20Sopenharmony_ci dev_err(dev, "KEUISR 0x%08x_%08x\n", 5518c2ecf20Sopenharmony_ci in_be32(priv->reg_pkeu + TALITOS_EUISR), 5528c2ecf20Sopenharmony_ci in_be32(priv->reg_pkeu + TALITOS_EUISR_LO)); 5538c2ecf20Sopenharmony_ci break; 5548c2ecf20Sopenharmony_ci } 5558c2ecf20Sopenharmony_ci 5568c2ecf20Sopenharmony_ci switch (desc_hdr & DESC_HDR_SEL1_MASK) { 5578c2ecf20Sopenharmony_ci case DESC_HDR_SEL1_MDEUA: 5588c2ecf20Sopenharmony_ci case DESC_HDR_SEL1_MDEUB: 5598c2ecf20Sopenharmony_ci dev_err(dev, "MDEUISR 0x%08x_%08x\n", 5608c2ecf20Sopenharmony_ci in_be32(priv->reg_mdeu + TALITOS_EUISR), 5618c2ecf20Sopenharmony_ci in_be32(priv->reg_mdeu + TALITOS_EUISR_LO)); 5628c2ecf20Sopenharmony_ci break; 5638c2ecf20Sopenharmony_ci case DESC_HDR_SEL1_CRCU: 5648c2ecf20Sopenharmony_ci dev_err(dev, "CRCUISR 0x%08x_%08x\n", 5658c2ecf20Sopenharmony_ci in_be32(priv->reg_crcu + TALITOS_EUISR), 5668c2ecf20Sopenharmony_ci in_be32(priv->reg_crcu + TALITOS_EUISR_LO)); 5678c2ecf20Sopenharmony_ci break; 5688c2ecf20Sopenharmony_ci } 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) 5718c2ecf20Sopenharmony_ci dev_err(dev, "DESCBUF 0x%08x_%08x\n", 5728c2ecf20Sopenharmony_ci in_be32(priv->chan[ch].reg + TALITOS_DESCBUF + 8*i), 5738c2ecf20Sopenharmony_ci in_be32(priv->chan[ch].reg + TALITOS_DESCBUF_LO + 8*i)); 5748c2ecf20Sopenharmony_ci} 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci/* 5778c2ecf20Sopenharmony_ci * recover from error interrupts 5788c2ecf20Sopenharmony_ci */ 5798c2ecf20Sopenharmony_cistatic void talitos_error(struct device *dev, u32 isr, u32 isr_lo) 5808c2ecf20Sopenharmony_ci{ 5818c2ecf20Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 5828c2ecf20Sopenharmony_ci unsigned int timeout = TALITOS_TIMEOUT; 5838c2ecf20Sopenharmony_ci int ch, error, reset_dev = 0; 5848c2ecf20Sopenharmony_ci u32 v_lo; 5858c2ecf20Sopenharmony_ci bool is_sec1 = has_ftr_sec1(priv); 5868c2ecf20Sopenharmony_ci int reset_ch = is_sec1 ? 1 : 0; /* only SEC2 supports continuation */ 5878c2ecf20Sopenharmony_ci 5888c2ecf20Sopenharmony_ci for (ch = 0; ch < priv->num_channels; ch++) { 5898c2ecf20Sopenharmony_ci /* skip channels without errors */ 5908c2ecf20Sopenharmony_ci if (is_sec1) { 5918c2ecf20Sopenharmony_ci /* bits 29, 31, 17, 19 */ 5928c2ecf20Sopenharmony_ci if (!(isr & (1 << (29 + (ch & 1) * 2 - (ch & 2) * 6)))) 5938c2ecf20Sopenharmony_ci continue; 5948c2ecf20Sopenharmony_ci } else { 5958c2ecf20Sopenharmony_ci if (!(isr & (1 << (ch * 2 + 1)))) 5968c2ecf20Sopenharmony_ci continue; 5978c2ecf20Sopenharmony_ci } 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci error = -EINVAL; 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci v_lo = in_be32(priv->chan[ch].reg + TALITOS_CCPSR_LO); 6028c2ecf20Sopenharmony_ci 6038c2ecf20Sopenharmony_ci if (v_lo & TALITOS_CCPSR_LO_DOF) { 6048c2ecf20Sopenharmony_ci dev_err(dev, "double fetch fifo overflow error\n"); 6058c2ecf20Sopenharmony_ci error = -EAGAIN; 6068c2ecf20Sopenharmony_ci reset_ch = 1; 6078c2ecf20Sopenharmony_ci } 6088c2ecf20Sopenharmony_ci if (v_lo & TALITOS_CCPSR_LO_SOF) { 6098c2ecf20Sopenharmony_ci /* h/w dropped descriptor */ 6108c2ecf20Sopenharmony_ci dev_err(dev, "single fetch fifo overflow error\n"); 6118c2ecf20Sopenharmony_ci error = -EAGAIN; 6128c2ecf20Sopenharmony_ci } 6138c2ecf20Sopenharmony_ci if (v_lo & TALITOS_CCPSR_LO_MDTE) 6148c2ecf20Sopenharmony_ci dev_err(dev, "master data transfer error\n"); 6158c2ecf20Sopenharmony_ci if (v_lo & TALITOS_CCPSR_LO_SGDLZ) 6168c2ecf20Sopenharmony_ci dev_err(dev, is_sec1 ? "pointer not complete error\n" 6178c2ecf20Sopenharmony_ci : "s/g data length zero error\n"); 6188c2ecf20Sopenharmony_ci if (v_lo & TALITOS_CCPSR_LO_FPZ) 6198c2ecf20Sopenharmony_ci dev_err(dev, is_sec1 ? "parity error\n" 6208c2ecf20Sopenharmony_ci : "fetch pointer zero error\n"); 6218c2ecf20Sopenharmony_ci if (v_lo & TALITOS_CCPSR_LO_IDH) 6228c2ecf20Sopenharmony_ci dev_err(dev, "illegal descriptor header error\n"); 6238c2ecf20Sopenharmony_ci if (v_lo & TALITOS_CCPSR_LO_IEU) 6248c2ecf20Sopenharmony_ci dev_err(dev, is_sec1 ? "static assignment error\n" 6258c2ecf20Sopenharmony_ci : "invalid exec unit error\n"); 6268c2ecf20Sopenharmony_ci if (v_lo & TALITOS_CCPSR_LO_EU) 6278c2ecf20Sopenharmony_ci report_eu_error(dev, ch, current_desc_hdr(dev, ch)); 6288c2ecf20Sopenharmony_ci if (!is_sec1) { 6298c2ecf20Sopenharmony_ci if (v_lo & TALITOS_CCPSR_LO_GB) 6308c2ecf20Sopenharmony_ci dev_err(dev, "gather boundary error\n"); 6318c2ecf20Sopenharmony_ci if (v_lo & TALITOS_CCPSR_LO_GRL) 6328c2ecf20Sopenharmony_ci dev_err(dev, "gather return/length error\n"); 6338c2ecf20Sopenharmony_ci if (v_lo & TALITOS_CCPSR_LO_SB) 6348c2ecf20Sopenharmony_ci dev_err(dev, "scatter boundary error\n"); 6358c2ecf20Sopenharmony_ci if (v_lo & TALITOS_CCPSR_LO_SRL) 6368c2ecf20Sopenharmony_ci dev_err(dev, "scatter return/length error\n"); 6378c2ecf20Sopenharmony_ci } 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ci flush_channel(dev, ch, error, reset_ch); 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_ci if (reset_ch) { 6428c2ecf20Sopenharmony_ci reset_channel(dev, ch); 6438c2ecf20Sopenharmony_ci } else { 6448c2ecf20Sopenharmony_ci setbits32(priv->chan[ch].reg + TALITOS_CCCR, 6458c2ecf20Sopenharmony_ci TALITOS2_CCCR_CONT); 6468c2ecf20Sopenharmony_ci setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, 0); 6478c2ecf20Sopenharmony_ci while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) & 6488c2ecf20Sopenharmony_ci TALITOS2_CCCR_CONT) && --timeout) 6498c2ecf20Sopenharmony_ci cpu_relax(); 6508c2ecf20Sopenharmony_ci if (timeout == 0) { 6518c2ecf20Sopenharmony_ci dev_err(dev, "failed to restart channel %d\n", 6528c2ecf20Sopenharmony_ci ch); 6538c2ecf20Sopenharmony_ci reset_dev = 1; 6548c2ecf20Sopenharmony_ci } 6558c2ecf20Sopenharmony_ci } 6568c2ecf20Sopenharmony_ci } 6578c2ecf20Sopenharmony_ci if (reset_dev || (is_sec1 && isr & ~TALITOS1_ISR_4CHERR) || 6588c2ecf20Sopenharmony_ci (!is_sec1 && isr & ~TALITOS2_ISR_4CHERR) || isr_lo) { 6598c2ecf20Sopenharmony_ci if (is_sec1 && (isr_lo & TALITOS1_ISR_TEA_ERR)) 6608c2ecf20Sopenharmony_ci dev_err(dev, "TEA error: ISR 0x%08x_%08x\n", 6618c2ecf20Sopenharmony_ci isr, isr_lo); 6628c2ecf20Sopenharmony_ci else 6638c2ecf20Sopenharmony_ci dev_err(dev, "done overflow, internal time out, or " 6648c2ecf20Sopenharmony_ci "rngu error: ISR 0x%08x_%08x\n", isr, isr_lo); 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci /* purge request queues */ 6678c2ecf20Sopenharmony_ci for (ch = 0; ch < priv->num_channels; ch++) 6688c2ecf20Sopenharmony_ci flush_channel(dev, ch, -EIO, 1); 6698c2ecf20Sopenharmony_ci 6708c2ecf20Sopenharmony_ci /* reset and reinitialize the device */ 6718c2ecf20Sopenharmony_ci init_device(dev); 6728c2ecf20Sopenharmony_ci } 6738c2ecf20Sopenharmony_ci} 6748c2ecf20Sopenharmony_ci 6758c2ecf20Sopenharmony_ci#define DEF_TALITOS1_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet) \ 6768c2ecf20Sopenharmony_cistatic irqreturn_t talitos1_interrupt_##name(int irq, void *data) \ 6778c2ecf20Sopenharmony_ci{ \ 6788c2ecf20Sopenharmony_ci struct device *dev = data; \ 6798c2ecf20Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); \ 6808c2ecf20Sopenharmony_ci u32 isr, isr_lo; \ 6818c2ecf20Sopenharmony_ci unsigned long flags; \ 6828c2ecf20Sopenharmony_ci \ 6838c2ecf20Sopenharmony_ci spin_lock_irqsave(&priv->reg_lock, flags); \ 6848c2ecf20Sopenharmony_ci isr = in_be32(priv->reg + TALITOS_ISR); \ 6858c2ecf20Sopenharmony_ci isr_lo = in_be32(priv->reg + TALITOS_ISR_LO); \ 6868c2ecf20Sopenharmony_ci /* Acknowledge interrupt */ \ 6878c2ecf20Sopenharmony_ci out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \ 6888c2ecf20Sopenharmony_ci out_be32(priv->reg + TALITOS_ICR_LO, isr_lo); \ 6898c2ecf20Sopenharmony_ci \ 6908c2ecf20Sopenharmony_ci if (unlikely(isr & ch_err_mask || isr_lo & TALITOS1_IMR_LO_INIT)) { \ 6918c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&priv->reg_lock, flags); \ 6928c2ecf20Sopenharmony_ci talitos_error(dev, isr & ch_err_mask, isr_lo); \ 6938c2ecf20Sopenharmony_ci } \ 6948c2ecf20Sopenharmony_ci else { \ 6958c2ecf20Sopenharmony_ci if (likely(isr & ch_done_mask)) { \ 6968c2ecf20Sopenharmony_ci /* mask further done interrupts. */ \ 6978c2ecf20Sopenharmony_ci setbits32(priv->reg + TALITOS_IMR, ch_done_mask); \ 6988c2ecf20Sopenharmony_ci /* done_task will unmask done interrupts at exit */ \ 6998c2ecf20Sopenharmony_ci tasklet_schedule(&priv->done_task[tlet]); \ 7008c2ecf20Sopenharmony_ci } \ 7018c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&priv->reg_lock, flags); \ 7028c2ecf20Sopenharmony_ci } \ 7038c2ecf20Sopenharmony_ci \ 7048c2ecf20Sopenharmony_ci return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED : \ 7058c2ecf20Sopenharmony_ci IRQ_NONE; \ 7068c2ecf20Sopenharmony_ci} 7078c2ecf20Sopenharmony_ci 7088c2ecf20Sopenharmony_ciDEF_TALITOS1_INTERRUPT(4ch, TALITOS1_ISR_4CHDONE, TALITOS1_ISR_4CHERR, 0) 7098c2ecf20Sopenharmony_ci 7108c2ecf20Sopenharmony_ci#define DEF_TALITOS2_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet) \ 7118c2ecf20Sopenharmony_cistatic irqreturn_t talitos2_interrupt_##name(int irq, void *data) \ 7128c2ecf20Sopenharmony_ci{ \ 7138c2ecf20Sopenharmony_ci struct device *dev = data; \ 7148c2ecf20Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); \ 7158c2ecf20Sopenharmony_ci u32 isr, isr_lo; \ 7168c2ecf20Sopenharmony_ci unsigned long flags; \ 7178c2ecf20Sopenharmony_ci \ 7188c2ecf20Sopenharmony_ci spin_lock_irqsave(&priv->reg_lock, flags); \ 7198c2ecf20Sopenharmony_ci isr = in_be32(priv->reg + TALITOS_ISR); \ 7208c2ecf20Sopenharmony_ci isr_lo = in_be32(priv->reg + TALITOS_ISR_LO); \ 7218c2ecf20Sopenharmony_ci /* Acknowledge interrupt */ \ 7228c2ecf20Sopenharmony_ci out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \ 7238c2ecf20Sopenharmony_ci out_be32(priv->reg + TALITOS_ICR_LO, isr_lo); \ 7248c2ecf20Sopenharmony_ci \ 7258c2ecf20Sopenharmony_ci if (unlikely(isr & ch_err_mask || isr_lo)) { \ 7268c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&priv->reg_lock, flags); \ 7278c2ecf20Sopenharmony_ci talitos_error(dev, isr & ch_err_mask, isr_lo); \ 7288c2ecf20Sopenharmony_ci } \ 7298c2ecf20Sopenharmony_ci else { \ 7308c2ecf20Sopenharmony_ci if (likely(isr & ch_done_mask)) { \ 7318c2ecf20Sopenharmony_ci /* mask further done interrupts. */ \ 7328c2ecf20Sopenharmony_ci clrbits32(priv->reg + TALITOS_IMR, ch_done_mask); \ 7338c2ecf20Sopenharmony_ci /* done_task will unmask done interrupts at exit */ \ 7348c2ecf20Sopenharmony_ci tasklet_schedule(&priv->done_task[tlet]); \ 7358c2ecf20Sopenharmony_ci } \ 7368c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&priv->reg_lock, flags); \ 7378c2ecf20Sopenharmony_ci } \ 7388c2ecf20Sopenharmony_ci \ 7398c2ecf20Sopenharmony_ci return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED : \ 7408c2ecf20Sopenharmony_ci IRQ_NONE; \ 7418c2ecf20Sopenharmony_ci} 7428c2ecf20Sopenharmony_ci 7438c2ecf20Sopenharmony_ciDEF_TALITOS2_INTERRUPT(4ch, TALITOS2_ISR_4CHDONE, TALITOS2_ISR_4CHERR, 0) 7448c2ecf20Sopenharmony_ciDEF_TALITOS2_INTERRUPT(ch0_2, TALITOS2_ISR_CH_0_2_DONE, TALITOS2_ISR_CH_0_2_ERR, 7458c2ecf20Sopenharmony_ci 0) 7468c2ecf20Sopenharmony_ciDEF_TALITOS2_INTERRUPT(ch1_3, TALITOS2_ISR_CH_1_3_DONE, TALITOS2_ISR_CH_1_3_ERR, 7478c2ecf20Sopenharmony_ci 1) 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_ci/* 7508c2ecf20Sopenharmony_ci * hwrng 7518c2ecf20Sopenharmony_ci */ 7528c2ecf20Sopenharmony_cistatic int talitos_rng_data_present(struct hwrng *rng, int wait) 7538c2ecf20Sopenharmony_ci{ 7548c2ecf20Sopenharmony_ci struct device *dev = (struct device *)rng->priv; 7558c2ecf20Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 7568c2ecf20Sopenharmony_ci u32 ofl; 7578c2ecf20Sopenharmony_ci int i; 7588c2ecf20Sopenharmony_ci 7598c2ecf20Sopenharmony_ci for (i = 0; i < 20; i++) { 7608c2ecf20Sopenharmony_ci ofl = in_be32(priv->reg_rngu + TALITOS_EUSR_LO) & 7618c2ecf20Sopenharmony_ci TALITOS_RNGUSR_LO_OFL; 7628c2ecf20Sopenharmony_ci if (ofl || !wait) 7638c2ecf20Sopenharmony_ci break; 7648c2ecf20Sopenharmony_ci udelay(10); 7658c2ecf20Sopenharmony_ci } 7668c2ecf20Sopenharmony_ci 7678c2ecf20Sopenharmony_ci return !!ofl; 7688c2ecf20Sopenharmony_ci} 7698c2ecf20Sopenharmony_ci 7708c2ecf20Sopenharmony_cistatic int talitos_rng_data_read(struct hwrng *rng, u32 *data) 7718c2ecf20Sopenharmony_ci{ 7728c2ecf20Sopenharmony_ci struct device *dev = (struct device *)rng->priv; 7738c2ecf20Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 7748c2ecf20Sopenharmony_ci 7758c2ecf20Sopenharmony_ci /* rng fifo requires 64-bit accesses */ 7768c2ecf20Sopenharmony_ci *data = in_be32(priv->reg_rngu + TALITOS_EU_FIFO); 7778c2ecf20Sopenharmony_ci *data = in_be32(priv->reg_rngu + TALITOS_EU_FIFO_LO); 7788c2ecf20Sopenharmony_ci 7798c2ecf20Sopenharmony_ci return sizeof(u32); 7808c2ecf20Sopenharmony_ci} 7818c2ecf20Sopenharmony_ci 7828c2ecf20Sopenharmony_cistatic int talitos_rng_init(struct hwrng *rng) 7838c2ecf20Sopenharmony_ci{ 7848c2ecf20Sopenharmony_ci struct device *dev = (struct device *)rng->priv; 7858c2ecf20Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 7868c2ecf20Sopenharmony_ci unsigned int timeout = TALITOS_TIMEOUT; 7878c2ecf20Sopenharmony_ci 7888c2ecf20Sopenharmony_ci setbits32(priv->reg_rngu + TALITOS_EURCR_LO, TALITOS_RNGURCR_LO_SR); 7898c2ecf20Sopenharmony_ci while (!(in_be32(priv->reg_rngu + TALITOS_EUSR_LO) 7908c2ecf20Sopenharmony_ci & TALITOS_RNGUSR_LO_RD) 7918c2ecf20Sopenharmony_ci && --timeout) 7928c2ecf20Sopenharmony_ci cpu_relax(); 7938c2ecf20Sopenharmony_ci if (timeout == 0) { 7948c2ecf20Sopenharmony_ci dev_err(dev, "failed to reset rng hw\n"); 7958c2ecf20Sopenharmony_ci return -ENODEV; 7968c2ecf20Sopenharmony_ci } 7978c2ecf20Sopenharmony_ci 7988c2ecf20Sopenharmony_ci /* start generating */ 7998c2ecf20Sopenharmony_ci setbits32(priv->reg_rngu + TALITOS_EUDSR_LO, 0); 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_ci return 0; 8028c2ecf20Sopenharmony_ci} 8038c2ecf20Sopenharmony_ci 8048c2ecf20Sopenharmony_cistatic int talitos_register_rng(struct device *dev) 8058c2ecf20Sopenharmony_ci{ 8068c2ecf20Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 8078c2ecf20Sopenharmony_ci int err; 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_ci priv->rng.name = dev_driver_string(dev); 8108c2ecf20Sopenharmony_ci priv->rng.init = talitos_rng_init; 8118c2ecf20Sopenharmony_ci priv->rng.data_present = talitos_rng_data_present; 8128c2ecf20Sopenharmony_ci priv->rng.data_read = talitos_rng_data_read; 8138c2ecf20Sopenharmony_ci priv->rng.priv = (unsigned long)dev; 8148c2ecf20Sopenharmony_ci 8158c2ecf20Sopenharmony_ci err = hwrng_register(&priv->rng); 8168c2ecf20Sopenharmony_ci if (!err) 8178c2ecf20Sopenharmony_ci priv->rng_registered = true; 8188c2ecf20Sopenharmony_ci 8198c2ecf20Sopenharmony_ci return err; 8208c2ecf20Sopenharmony_ci} 8218c2ecf20Sopenharmony_ci 8228c2ecf20Sopenharmony_cistatic void talitos_unregister_rng(struct device *dev) 8238c2ecf20Sopenharmony_ci{ 8248c2ecf20Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 8258c2ecf20Sopenharmony_ci 8268c2ecf20Sopenharmony_ci if (!priv->rng_registered) 8278c2ecf20Sopenharmony_ci return; 8288c2ecf20Sopenharmony_ci 8298c2ecf20Sopenharmony_ci hwrng_unregister(&priv->rng); 8308c2ecf20Sopenharmony_ci priv->rng_registered = false; 8318c2ecf20Sopenharmony_ci} 8328c2ecf20Sopenharmony_ci 8338c2ecf20Sopenharmony_ci/* 8348c2ecf20Sopenharmony_ci * crypto alg 8358c2ecf20Sopenharmony_ci */ 8368c2ecf20Sopenharmony_ci#define TALITOS_CRA_PRIORITY 3000 8378c2ecf20Sopenharmony_ci/* 8388c2ecf20Sopenharmony_ci * Defines a priority for doing AEAD with descriptors type 8398c2ecf20Sopenharmony_ci * HMAC_SNOOP_NO_AFEA (HSNA) instead of type IPSEC_ESP 8408c2ecf20Sopenharmony_ci */ 8418c2ecf20Sopenharmony_ci#define TALITOS_CRA_PRIORITY_AEAD_HSNA (TALITOS_CRA_PRIORITY - 1) 8428c2ecf20Sopenharmony_ci#ifdef CONFIG_CRYPTO_DEV_TALITOS2 8438c2ecf20Sopenharmony_ci#define TALITOS_MAX_KEY_SIZE (AES_MAX_KEY_SIZE + SHA512_BLOCK_SIZE) 8448c2ecf20Sopenharmony_ci#else 8458c2ecf20Sopenharmony_ci#define TALITOS_MAX_KEY_SIZE (AES_MAX_KEY_SIZE + SHA256_BLOCK_SIZE) 8468c2ecf20Sopenharmony_ci#endif 8478c2ecf20Sopenharmony_ci#define TALITOS_MAX_IV_LENGTH 16 /* max of AES_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE */ 8488c2ecf20Sopenharmony_ci 8498c2ecf20Sopenharmony_cistruct talitos_ctx { 8508c2ecf20Sopenharmony_ci struct device *dev; 8518c2ecf20Sopenharmony_ci int ch; 8528c2ecf20Sopenharmony_ci __be32 desc_hdr_template; 8538c2ecf20Sopenharmony_ci u8 key[TALITOS_MAX_KEY_SIZE]; 8548c2ecf20Sopenharmony_ci u8 iv[TALITOS_MAX_IV_LENGTH]; 8558c2ecf20Sopenharmony_ci dma_addr_t dma_key; 8568c2ecf20Sopenharmony_ci unsigned int keylen; 8578c2ecf20Sopenharmony_ci unsigned int enckeylen; 8588c2ecf20Sopenharmony_ci unsigned int authkeylen; 8598c2ecf20Sopenharmony_ci}; 8608c2ecf20Sopenharmony_ci 8618c2ecf20Sopenharmony_ci#define HASH_MAX_BLOCK_SIZE SHA512_BLOCK_SIZE 8628c2ecf20Sopenharmony_ci#define TALITOS_MDEU_MAX_CONTEXT_SIZE TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512 8638c2ecf20Sopenharmony_ci 8648c2ecf20Sopenharmony_cistruct talitos_ahash_req_ctx { 8658c2ecf20Sopenharmony_ci u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)]; 8668c2ecf20Sopenharmony_ci unsigned int hw_context_size; 8678c2ecf20Sopenharmony_ci u8 buf[2][HASH_MAX_BLOCK_SIZE]; 8688c2ecf20Sopenharmony_ci int buf_idx; 8698c2ecf20Sopenharmony_ci unsigned int swinit; 8708c2ecf20Sopenharmony_ci unsigned int first; 8718c2ecf20Sopenharmony_ci unsigned int last; 8728c2ecf20Sopenharmony_ci unsigned int to_hash_later; 8738c2ecf20Sopenharmony_ci unsigned int nbuf; 8748c2ecf20Sopenharmony_ci struct scatterlist bufsl[2]; 8758c2ecf20Sopenharmony_ci struct scatterlist *psrc; 8768c2ecf20Sopenharmony_ci}; 8778c2ecf20Sopenharmony_ci 8788c2ecf20Sopenharmony_cistruct talitos_export_state { 8798c2ecf20Sopenharmony_ci u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)]; 8808c2ecf20Sopenharmony_ci u8 buf[HASH_MAX_BLOCK_SIZE]; 8818c2ecf20Sopenharmony_ci unsigned int swinit; 8828c2ecf20Sopenharmony_ci unsigned int first; 8838c2ecf20Sopenharmony_ci unsigned int last; 8848c2ecf20Sopenharmony_ci unsigned int to_hash_later; 8858c2ecf20Sopenharmony_ci unsigned int nbuf; 8868c2ecf20Sopenharmony_ci}; 8878c2ecf20Sopenharmony_ci 8888c2ecf20Sopenharmony_cistatic int aead_setkey(struct crypto_aead *authenc, 8898c2ecf20Sopenharmony_ci const u8 *key, unsigned int keylen) 8908c2ecf20Sopenharmony_ci{ 8918c2ecf20Sopenharmony_ci struct talitos_ctx *ctx = crypto_aead_ctx(authenc); 8928c2ecf20Sopenharmony_ci struct device *dev = ctx->dev; 8938c2ecf20Sopenharmony_ci struct crypto_authenc_keys keys; 8948c2ecf20Sopenharmony_ci 8958c2ecf20Sopenharmony_ci if (crypto_authenc_extractkeys(&keys, key, keylen) != 0) 8968c2ecf20Sopenharmony_ci goto badkey; 8978c2ecf20Sopenharmony_ci 8988c2ecf20Sopenharmony_ci if (keys.authkeylen + keys.enckeylen > TALITOS_MAX_KEY_SIZE) 8998c2ecf20Sopenharmony_ci goto badkey; 9008c2ecf20Sopenharmony_ci 9018c2ecf20Sopenharmony_ci if (ctx->keylen) 9028c2ecf20Sopenharmony_ci dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE); 9038c2ecf20Sopenharmony_ci 9048c2ecf20Sopenharmony_ci memcpy(ctx->key, keys.authkey, keys.authkeylen); 9058c2ecf20Sopenharmony_ci memcpy(&ctx->key[keys.authkeylen], keys.enckey, keys.enckeylen); 9068c2ecf20Sopenharmony_ci 9078c2ecf20Sopenharmony_ci ctx->keylen = keys.authkeylen + keys.enckeylen; 9088c2ecf20Sopenharmony_ci ctx->enckeylen = keys.enckeylen; 9098c2ecf20Sopenharmony_ci ctx->authkeylen = keys.authkeylen; 9108c2ecf20Sopenharmony_ci ctx->dma_key = dma_map_single(dev, ctx->key, ctx->keylen, 9118c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 9128c2ecf20Sopenharmony_ci 9138c2ecf20Sopenharmony_ci memzero_explicit(&keys, sizeof(keys)); 9148c2ecf20Sopenharmony_ci return 0; 9158c2ecf20Sopenharmony_ci 9168c2ecf20Sopenharmony_cibadkey: 9178c2ecf20Sopenharmony_ci memzero_explicit(&keys, sizeof(keys)); 9188c2ecf20Sopenharmony_ci return -EINVAL; 9198c2ecf20Sopenharmony_ci} 9208c2ecf20Sopenharmony_ci 9218c2ecf20Sopenharmony_cistatic int aead_des3_setkey(struct crypto_aead *authenc, 9228c2ecf20Sopenharmony_ci const u8 *key, unsigned int keylen) 9238c2ecf20Sopenharmony_ci{ 9248c2ecf20Sopenharmony_ci struct talitos_ctx *ctx = crypto_aead_ctx(authenc); 9258c2ecf20Sopenharmony_ci struct device *dev = ctx->dev; 9268c2ecf20Sopenharmony_ci struct crypto_authenc_keys keys; 9278c2ecf20Sopenharmony_ci int err; 9288c2ecf20Sopenharmony_ci 9298c2ecf20Sopenharmony_ci err = crypto_authenc_extractkeys(&keys, key, keylen); 9308c2ecf20Sopenharmony_ci if (unlikely(err)) 9318c2ecf20Sopenharmony_ci goto out; 9328c2ecf20Sopenharmony_ci 9338c2ecf20Sopenharmony_ci err = -EINVAL; 9348c2ecf20Sopenharmony_ci if (keys.authkeylen + keys.enckeylen > TALITOS_MAX_KEY_SIZE) 9358c2ecf20Sopenharmony_ci goto out; 9368c2ecf20Sopenharmony_ci 9378c2ecf20Sopenharmony_ci err = verify_aead_des3_key(authenc, keys.enckey, keys.enckeylen); 9388c2ecf20Sopenharmony_ci if (err) 9398c2ecf20Sopenharmony_ci goto out; 9408c2ecf20Sopenharmony_ci 9418c2ecf20Sopenharmony_ci if (ctx->keylen) 9428c2ecf20Sopenharmony_ci dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE); 9438c2ecf20Sopenharmony_ci 9448c2ecf20Sopenharmony_ci memcpy(ctx->key, keys.authkey, keys.authkeylen); 9458c2ecf20Sopenharmony_ci memcpy(&ctx->key[keys.authkeylen], keys.enckey, keys.enckeylen); 9468c2ecf20Sopenharmony_ci 9478c2ecf20Sopenharmony_ci ctx->keylen = keys.authkeylen + keys.enckeylen; 9488c2ecf20Sopenharmony_ci ctx->enckeylen = keys.enckeylen; 9498c2ecf20Sopenharmony_ci ctx->authkeylen = keys.authkeylen; 9508c2ecf20Sopenharmony_ci ctx->dma_key = dma_map_single(dev, ctx->key, ctx->keylen, 9518c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 9528c2ecf20Sopenharmony_ci 9538c2ecf20Sopenharmony_ciout: 9548c2ecf20Sopenharmony_ci memzero_explicit(&keys, sizeof(keys)); 9558c2ecf20Sopenharmony_ci return err; 9568c2ecf20Sopenharmony_ci} 9578c2ecf20Sopenharmony_ci 9588c2ecf20Sopenharmony_cistatic void talitos_sg_unmap(struct device *dev, 9598c2ecf20Sopenharmony_ci struct talitos_edesc *edesc, 9608c2ecf20Sopenharmony_ci struct scatterlist *src, 9618c2ecf20Sopenharmony_ci struct scatterlist *dst, 9628c2ecf20Sopenharmony_ci unsigned int len, unsigned int offset) 9638c2ecf20Sopenharmony_ci{ 9648c2ecf20Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 9658c2ecf20Sopenharmony_ci bool is_sec1 = has_ftr_sec1(priv); 9668c2ecf20Sopenharmony_ci unsigned int src_nents = edesc->src_nents ? : 1; 9678c2ecf20Sopenharmony_ci unsigned int dst_nents = edesc->dst_nents ? : 1; 9688c2ecf20Sopenharmony_ci 9698c2ecf20Sopenharmony_ci if (is_sec1 && dst && dst_nents > 1) { 9708c2ecf20Sopenharmony_ci dma_sync_single_for_device(dev, edesc->dma_link_tbl + offset, 9718c2ecf20Sopenharmony_ci len, DMA_FROM_DEVICE); 9728c2ecf20Sopenharmony_ci sg_pcopy_from_buffer(dst, dst_nents, edesc->buf + offset, len, 9738c2ecf20Sopenharmony_ci offset); 9748c2ecf20Sopenharmony_ci } 9758c2ecf20Sopenharmony_ci if (src != dst) { 9768c2ecf20Sopenharmony_ci if (src_nents == 1 || !is_sec1) 9778c2ecf20Sopenharmony_ci dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE); 9788c2ecf20Sopenharmony_ci 9798c2ecf20Sopenharmony_ci if (dst && (dst_nents == 1 || !is_sec1)) 9808c2ecf20Sopenharmony_ci dma_unmap_sg(dev, dst, dst_nents, DMA_FROM_DEVICE); 9818c2ecf20Sopenharmony_ci } else if (src_nents == 1 || !is_sec1) { 9828c2ecf20Sopenharmony_ci dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL); 9838c2ecf20Sopenharmony_ci } 9848c2ecf20Sopenharmony_ci} 9858c2ecf20Sopenharmony_ci 9868c2ecf20Sopenharmony_cistatic void ipsec_esp_unmap(struct device *dev, 9878c2ecf20Sopenharmony_ci struct talitos_edesc *edesc, 9888c2ecf20Sopenharmony_ci struct aead_request *areq, bool encrypt) 9898c2ecf20Sopenharmony_ci{ 9908c2ecf20Sopenharmony_ci struct crypto_aead *aead = crypto_aead_reqtfm(areq); 9918c2ecf20Sopenharmony_ci struct talitos_ctx *ctx = crypto_aead_ctx(aead); 9928c2ecf20Sopenharmony_ci unsigned int ivsize = crypto_aead_ivsize(aead); 9938c2ecf20Sopenharmony_ci unsigned int authsize = crypto_aead_authsize(aead); 9948c2ecf20Sopenharmony_ci unsigned int cryptlen = areq->cryptlen - (encrypt ? 0 : authsize); 9958c2ecf20Sopenharmony_ci bool is_ipsec_esp = edesc->desc.hdr & DESC_HDR_TYPE_IPSEC_ESP; 9968c2ecf20Sopenharmony_ci struct talitos_ptr *civ_ptr = &edesc->desc.ptr[is_ipsec_esp ? 2 : 3]; 9978c2ecf20Sopenharmony_ci 9988c2ecf20Sopenharmony_ci if (is_ipsec_esp) 9998c2ecf20Sopenharmony_ci unmap_single_talitos_ptr(dev, &edesc->desc.ptr[6], 10008c2ecf20Sopenharmony_ci DMA_FROM_DEVICE); 10018c2ecf20Sopenharmony_ci unmap_single_talitos_ptr(dev, civ_ptr, DMA_TO_DEVICE); 10028c2ecf20Sopenharmony_ci 10038c2ecf20Sopenharmony_ci talitos_sg_unmap(dev, edesc, areq->src, areq->dst, 10048c2ecf20Sopenharmony_ci cryptlen + authsize, areq->assoclen); 10058c2ecf20Sopenharmony_ci 10068c2ecf20Sopenharmony_ci if (edesc->dma_len) 10078c2ecf20Sopenharmony_ci dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len, 10088c2ecf20Sopenharmony_ci DMA_BIDIRECTIONAL); 10098c2ecf20Sopenharmony_ci 10108c2ecf20Sopenharmony_ci if (!is_ipsec_esp) { 10118c2ecf20Sopenharmony_ci unsigned int dst_nents = edesc->dst_nents ? : 1; 10128c2ecf20Sopenharmony_ci 10138c2ecf20Sopenharmony_ci sg_pcopy_to_buffer(areq->dst, dst_nents, ctx->iv, ivsize, 10148c2ecf20Sopenharmony_ci areq->assoclen + cryptlen - ivsize); 10158c2ecf20Sopenharmony_ci } 10168c2ecf20Sopenharmony_ci} 10178c2ecf20Sopenharmony_ci 10188c2ecf20Sopenharmony_ci/* 10198c2ecf20Sopenharmony_ci * ipsec_esp descriptor callbacks 10208c2ecf20Sopenharmony_ci */ 10218c2ecf20Sopenharmony_cistatic void ipsec_esp_encrypt_done(struct device *dev, 10228c2ecf20Sopenharmony_ci struct talitos_desc *desc, void *context, 10238c2ecf20Sopenharmony_ci int err) 10248c2ecf20Sopenharmony_ci{ 10258c2ecf20Sopenharmony_ci struct aead_request *areq = context; 10268c2ecf20Sopenharmony_ci struct crypto_aead *authenc = crypto_aead_reqtfm(areq); 10278c2ecf20Sopenharmony_ci unsigned int ivsize = crypto_aead_ivsize(authenc); 10288c2ecf20Sopenharmony_ci struct talitos_edesc *edesc; 10298c2ecf20Sopenharmony_ci 10308c2ecf20Sopenharmony_ci edesc = container_of(desc, struct talitos_edesc, desc); 10318c2ecf20Sopenharmony_ci 10328c2ecf20Sopenharmony_ci ipsec_esp_unmap(dev, edesc, areq, true); 10338c2ecf20Sopenharmony_ci 10348c2ecf20Sopenharmony_ci dma_unmap_single(dev, edesc->iv_dma, ivsize, DMA_TO_DEVICE); 10358c2ecf20Sopenharmony_ci 10368c2ecf20Sopenharmony_ci kfree(edesc); 10378c2ecf20Sopenharmony_ci 10388c2ecf20Sopenharmony_ci aead_request_complete(areq, err); 10398c2ecf20Sopenharmony_ci} 10408c2ecf20Sopenharmony_ci 10418c2ecf20Sopenharmony_cistatic void ipsec_esp_decrypt_swauth_done(struct device *dev, 10428c2ecf20Sopenharmony_ci struct talitos_desc *desc, 10438c2ecf20Sopenharmony_ci void *context, int err) 10448c2ecf20Sopenharmony_ci{ 10458c2ecf20Sopenharmony_ci struct aead_request *req = context; 10468c2ecf20Sopenharmony_ci struct crypto_aead *authenc = crypto_aead_reqtfm(req); 10478c2ecf20Sopenharmony_ci unsigned int authsize = crypto_aead_authsize(authenc); 10488c2ecf20Sopenharmony_ci struct talitos_edesc *edesc; 10498c2ecf20Sopenharmony_ci char *oicv, *icv; 10508c2ecf20Sopenharmony_ci 10518c2ecf20Sopenharmony_ci edesc = container_of(desc, struct talitos_edesc, desc); 10528c2ecf20Sopenharmony_ci 10538c2ecf20Sopenharmony_ci ipsec_esp_unmap(dev, edesc, req, false); 10548c2ecf20Sopenharmony_ci 10558c2ecf20Sopenharmony_ci if (!err) { 10568c2ecf20Sopenharmony_ci /* auth check */ 10578c2ecf20Sopenharmony_ci oicv = edesc->buf + edesc->dma_len; 10588c2ecf20Sopenharmony_ci icv = oicv - authsize; 10598c2ecf20Sopenharmony_ci 10608c2ecf20Sopenharmony_ci err = crypto_memneq(oicv, icv, authsize) ? -EBADMSG : 0; 10618c2ecf20Sopenharmony_ci } 10628c2ecf20Sopenharmony_ci 10638c2ecf20Sopenharmony_ci kfree(edesc); 10648c2ecf20Sopenharmony_ci 10658c2ecf20Sopenharmony_ci aead_request_complete(req, err); 10668c2ecf20Sopenharmony_ci} 10678c2ecf20Sopenharmony_ci 10688c2ecf20Sopenharmony_cistatic void ipsec_esp_decrypt_hwauth_done(struct device *dev, 10698c2ecf20Sopenharmony_ci struct talitos_desc *desc, 10708c2ecf20Sopenharmony_ci void *context, int err) 10718c2ecf20Sopenharmony_ci{ 10728c2ecf20Sopenharmony_ci struct aead_request *req = context; 10738c2ecf20Sopenharmony_ci struct talitos_edesc *edesc; 10748c2ecf20Sopenharmony_ci 10758c2ecf20Sopenharmony_ci edesc = container_of(desc, struct talitos_edesc, desc); 10768c2ecf20Sopenharmony_ci 10778c2ecf20Sopenharmony_ci ipsec_esp_unmap(dev, edesc, req, false); 10788c2ecf20Sopenharmony_ci 10798c2ecf20Sopenharmony_ci /* check ICV auth status */ 10808c2ecf20Sopenharmony_ci if (!err && ((desc->hdr_lo & DESC_HDR_LO_ICCR1_MASK) != 10818c2ecf20Sopenharmony_ci DESC_HDR_LO_ICCR1_PASS)) 10828c2ecf20Sopenharmony_ci err = -EBADMSG; 10838c2ecf20Sopenharmony_ci 10848c2ecf20Sopenharmony_ci kfree(edesc); 10858c2ecf20Sopenharmony_ci 10868c2ecf20Sopenharmony_ci aead_request_complete(req, err); 10878c2ecf20Sopenharmony_ci} 10888c2ecf20Sopenharmony_ci 10898c2ecf20Sopenharmony_ci/* 10908c2ecf20Sopenharmony_ci * convert scatterlist to SEC h/w link table format 10918c2ecf20Sopenharmony_ci * stop at cryptlen bytes 10928c2ecf20Sopenharmony_ci */ 10938c2ecf20Sopenharmony_cistatic int sg_to_link_tbl_offset(struct scatterlist *sg, int sg_count, 10948c2ecf20Sopenharmony_ci unsigned int offset, int datalen, int elen, 10958c2ecf20Sopenharmony_ci struct talitos_ptr *link_tbl_ptr, int align) 10968c2ecf20Sopenharmony_ci{ 10978c2ecf20Sopenharmony_ci int n_sg = elen ? sg_count + 1 : sg_count; 10988c2ecf20Sopenharmony_ci int count = 0; 10998c2ecf20Sopenharmony_ci int cryptlen = datalen + elen; 11008c2ecf20Sopenharmony_ci int padding = ALIGN(cryptlen, align) - cryptlen; 11018c2ecf20Sopenharmony_ci 11028c2ecf20Sopenharmony_ci while (cryptlen && sg && n_sg--) { 11038c2ecf20Sopenharmony_ci unsigned int len = sg_dma_len(sg); 11048c2ecf20Sopenharmony_ci 11058c2ecf20Sopenharmony_ci if (offset >= len) { 11068c2ecf20Sopenharmony_ci offset -= len; 11078c2ecf20Sopenharmony_ci goto next; 11088c2ecf20Sopenharmony_ci } 11098c2ecf20Sopenharmony_ci 11108c2ecf20Sopenharmony_ci len -= offset; 11118c2ecf20Sopenharmony_ci 11128c2ecf20Sopenharmony_ci if (len > cryptlen) 11138c2ecf20Sopenharmony_ci len = cryptlen; 11148c2ecf20Sopenharmony_ci 11158c2ecf20Sopenharmony_ci if (datalen > 0 && len > datalen) { 11168c2ecf20Sopenharmony_ci to_talitos_ptr(link_tbl_ptr + count, 11178c2ecf20Sopenharmony_ci sg_dma_address(sg) + offset, datalen, 0); 11188c2ecf20Sopenharmony_ci to_talitos_ptr_ext_set(link_tbl_ptr + count, 0, 0); 11198c2ecf20Sopenharmony_ci count++; 11208c2ecf20Sopenharmony_ci len -= datalen; 11218c2ecf20Sopenharmony_ci offset += datalen; 11228c2ecf20Sopenharmony_ci } 11238c2ecf20Sopenharmony_ci to_talitos_ptr(link_tbl_ptr + count, 11248c2ecf20Sopenharmony_ci sg_dma_address(sg) + offset, sg_next(sg) ? len : len + padding, 0); 11258c2ecf20Sopenharmony_ci to_talitos_ptr_ext_set(link_tbl_ptr + count, 0, 0); 11268c2ecf20Sopenharmony_ci count++; 11278c2ecf20Sopenharmony_ci cryptlen -= len; 11288c2ecf20Sopenharmony_ci datalen -= len; 11298c2ecf20Sopenharmony_ci offset = 0; 11308c2ecf20Sopenharmony_ci 11318c2ecf20Sopenharmony_cinext: 11328c2ecf20Sopenharmony_ci sg = sg_next(sg); 11338c2ecf20Sopenharmony_ci } 11348c2ecf20Sopenharmony_ci 11358c2ecf20Sopenharmony_ci /* tag end of link table */ 11368c2ecf20Sopenharmony_ci if (count > 0) 11378c2ecf20Sopenharmony_ci to_talitos_ptr_ext_set(link_tbl_ptr + count - 1, 11388c2ecf20Sopenharmony_ci DESC_PTR_LNKTBL_RET, 0); 11398c2ecf20Sopenharmony_ci 11408c2ecf20Sopenharmony_ci return count; 11418c2ecf20Sopenharmony_ci} 11428c2ecf20Sopenharmony_ci 11438c2ecf20Sopenharmony_cistatic int talitos_sg_map_ext(struct device *dev, struct scatterlist *src, 11448c2ecf20Sopenharmony_ci unsigned int len, struct talitos_edesc *edesc, 11458c2ecf20Sopenharmony_ci struct talitos_ptr *ptr, int sg_count, 11468c2ecf20Sopenharmony_ci unsigned int offset, int tbl_off, int elen, 11478c2ecf20Sopenharmony_ci bool force, int align) 11488c2ecf20Sopenharmony_ci{ 11498c2ecf20Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 11508c2ecf20Sopenharmony_ci bool is_sec1 = has_ftr_sec1(priv); 11518c2ecf20Sopenharmony_ci int aligned_len = ALIGN(len, align); 11528c2ecf20Sopenharmony_ci 11538c2ecf20Sopenharmony_ci if (!src) { 11548c2ecf20Sopenharmony_ci to_talitos_ptr(ptr, 0, 0, is_sec1); 11558c2ecf20Sopenharmony_ci return 1; 11568c2ecf20Sopenharmony_ci } 11578c2ecf20Sopenharmony_ci to_talitos_ptr_ext_set(ptr, elen, is_sec1); 11588c2ecf20Sopenharmony_ci if (sg_count == 1 && !force) { 11598c2ecf20Sopenharmony_ci to_talitos_ptr(ptr, sg_dma_address(src) + offset, aligned_len, is_sec1); 11608c2ecf20Sopenharmony_ci return sg_count; 11618c2ecf20Sopenharmony_ci } 11628c2ecf20Sopenharmony_ci if (is_sec1) { 11638c2ecf20Sopenharmony_ci to_talitos_ptr(ptr, edesc->dma_link_tbl + offset, aligned_len, is_sec1); 11648c2ecf20Sopenharmony_ci return sg_count; 11658c2ecf20Sopenharmony_ci } 11668c2ecf20Sopenharmony_ci sg_count = sg_to_link_tbl_offset(src, sg_count, offset, len, elen, 11678c2ecf20Sopenharmony_ci &edesc->link_tbl[tbl_off], align); 11688c2ecf20Sopenharmony_ci if (sg_count == 1 && !force) { 11698c2ecf20Sopenharmony_ci /* Only one segment now, so no link tbl needed*/ 11708c2ecf20Sopenharmony_ci copy_talitos_ptr(ptr, &edesc->link_tbl[tbl_off], is_sec1); 11718c2ecf20Sopenharmony_ci return sg_count; 11728c2ecf20Sopenharmony_ci } 11738c2ecf20Sopenharmony_ci to_talitos_ptr(ptr, edesc->dma_link_tbl + 11748c2ecf20Sopenharmony_ci tbl_off * sizeof(struct talitos_ptr), aligned_len, is_sec1); 11758c2ecf20Sopenharmony_ci to_talitos_ptr_ext_or(ptr, DESC_PTR_LNKTBL_JUMP, is_sec1); 11768c2ecf20Sopenharmony_ci 11778c2ecf20Sopenharmony_ci return sg_count; 11788c2ecf20Sopenharmony_ci} 11798c2ecf20Sopenharmony_ci 11808c2ecf20Sopenharmony_cistatic int talitos_sg_map(struct device *dev, struct scatterlist *src, 11818c2ecf20Sopenharmony_ci unsigned int len, struct talitos_edesc *edesc, 11828c2ecf20Sopenharmony_ci struct talitos_ptr *ptr, int sg_count, 11838c2ecf20Sopenharmony_ci unsigned int offset, int tbl_off) 11848c2ecf20Sopenharmony_ci{ 11858c2ecf20Sopenharmony_ci return talitos_sg_map_ext(dev, src, len, edesc, ptr, sg_count, offset, 11868c2ecf20Sopenharmony_ci tbl_off, 0, false, 1); 11878c2ecf20Sopenharmony_ci} 11888c2ecf20Sopenharmony_ci 11898c2ecf20Sopenharmony_ci/* 11908c2ecf20Sopenharmony_ci * fill in and submit ipsec_esp descriptor 11918c2ecf20Sopenharmony_ci */ 11928c2ecf20Sopenharmony_cistatic int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq, 11938c2ecf20Sopenharmony_ci bool encrypt, 11948c2ecf20Sopenharmony_ci void (*callback)(struct device *dev, 11958c2ecf20Sopenharmony_ci struct talitos_desc *desc, 11968c2ecf20Sopenharmony_ci void *context, int error)) 11978c2ecf20Sopenharmony_ci{ 11988c2ecf20Sopenharmony_ci struct crypto_aead *aead = crypto_aead_reqtfm(areq); 11998c2ecf20Sopenharmony_ci unsigned int authsize = crypto_aead_authsize(aead); 12008c2ecf20Sopenharmony_ci struct talitos_ctx *ctx = crypto_aead_ctx(aead); 12018c2ecf20Sopenharmony_ci struct device *dev = ctx->dev; 12028c2ecf20Sopenharmony_ci struct talitos_desc *desc = &edesc->desc; 12038c2ecf20Sopenharmony_ci unsigned int cryptlen = areq->cryptlen - (encrypt ? 0 : authsize); 12048c2ecf20Sopenharmony_ci unsigned int ivsize = crypto_aead_ivsize(aead); 12058c2ecf20Sopenharmony_ci int tbl_off = 0; 12068c2ecf20Sopenharmony_ci int sg_count, ret; 12078c2ecf20Sopenharmony_ci int elen = 0; 12088c2ecf20Sopenharmony_ci bool sync_needed = false; 12098c2ecf20Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 12108c2ecf20Sopenharmony_ci bool is_sec1 = has_ftr_sec1(priv); 12118c2ecf20Sopenharmony_ci bool is_ipsec_esp = desc->hdr & DESC_HDR_TYPE_IPSEC_ESP; 12128c2ecf20Sopenharmony_ci struct talitos_ptr *civ_ptr = &desc->ptr[is_ipsec_esp ? 2 : 3]; 12138c2ecf20Sopenharmony_ci struct talitos_ptr *ckey_ptr = &desc->ptr[is_ipsec_esp ? 3 : 2]; 12148c2ecf20Sopenharmony_ci dma_addr_t dma_icv = edesc->dma_link_tbl + edesc->dma_len - authsize; 12158c2ecf20Sopenharmony_ci 12168c2ecf20Sopenharmony_ci /* hmac key */ 12178c2ecf20Sopenharmony_ci to_talitos_ptr(&desc->ptr[0], ctx->dma_key, ctx->authkeylen, is_sec1); 12188c2ecf20Sopenharmony_ci 12198c2ecf20Sopenharmony_ci sg_count = edesc->src_nents ?: 1; 12208c2ecf20Sopenharmony_ci if (is_sec1 && sg_count > 1) 12218c2ecf20Sopenharmony_ci sg_copy_to_buffer(areq->src, sg_count, edesc->buf, 12228c2ecf20Sopenharmony_ci areq->assoclen + cryptlen); 12238c2ecf20Sopenharmony_ci else 12248c2ecf20Sopenharmony_ci sg_count = dma_map_sg(dev, areq->src, sg_count, 12258c2ecf20Sopenharmony_ci (areq->src == areq->dst) ? 12268c2ecf20Sopenharmony_ci DMA_BIDIRECTIONAL : DMA_TO_DEVICE); 12278c2ecf20Sopenharmony_ci 12288c2ecf20Sopenharmony_ci /* hmac data */ 12298c2ecf20Sopenharmony_ci ret = talitos_sg_map(dev, areq->src, areq->assoclen, edesc, 12308c2ecf20Sopenharmony_ci &desc->ptr[1], sg_count, 0, tbl_off); 12318c2ecf20Sopenharmony_ci 12328c2ecf20Sopenharmony_ci if (ret > 1) { 12338c2ecf20Sopenharmony_ci tbl_off += ret; 12348c2ecf20Sopenharmony_ci sync_needed = true; 12358c2ecf20Sopenharmony_ci } 12368c2ecf20Sopenharmony_ci 12378c2ecf20Sopenharmony_ci /* cipher iv */ 12388c2ecf20Sopenharmony_ci to_talitos_ptr(civ_ptr, edesc->iv_dma, ivsize, is_sec1); 12398c2ecf20Sopenharmony_ci 12408c2ecf20Sopenharmony_ci /* cipher key */ 12418c2ecf20Sopenharmony_ci to_talitos_ptr(ckey_ptr, ctx->dma_key + ctx->authkeylen, 12428c2ecf20Sopenharmony_ci ctx->enckeylen, is_sec1); 12438c2ecf20Sopenharmony_ci 12448c2ecf20Sopenharmony_ci /* 12458c2ecf20Sopenharmony_ci * cipher in 12468c2ecf20Sopenharmony_ci * map and adjust cipher len to aead request cryptlen. 12478c2ecf20Sopenharmony_ci * extent is bytes of HMAC postpended to ciphertext, 12488c2ecf20Sopenharmony_ci * typically 12 for ipsec 12498c2ecf20Sopenharmony_ci */ 12508c2ecf20Sopenharmony_ci if (is_ipsec_esp && (desc->hdr & DESC_HDR_MODE1_MDEU_CICV)) 12518c2ecf20Sopenharmony_ci elen = authsize; 12528c2ecf20Sopenharmony_ci 12538c2ecf20Sopenharmony_ci ret = talitos_sg_map_ext(dev, areq->src, cryptlen, edesc, &desc->ptr[4], 12548c2ecf20Sopenharmony_ci sg_count, areq->assoclen, tbl_off, elen, 12558c2ecf20Sopenharmony_ci false, 1); 12568c2ecf20Sopenharmony_ci 12578c2ecf20Sopenharmony_ci if (ret > 1) { 12588c2ecf20Sopenharmony_ci tbl_off += ret; 12598c2ecf20Sopenharmony_ci sync_needed = true; 12608c2ecf20Sopenharmony_ci } 12618c2ecf20Sopenharmony_ci 12628c2ecf20Sopenharmony_ci /* cipher out */ 12638c2ecf20Sopenharmony_ci if (areq->src != areq->dst) { 12648c2ecf20Sopenharmony_ci sg_count = edesc->dst_nents ? : 1; 12658c2ecf20Sopenharmony_ci if (!is_sec1 || sg_count == 1) 12668c2ecf20Sopenharmony_ci dma_map_sg(dev, areq->dst, sg_count, DMA_FROM_DEVICE); 12678c2ecf20Sopenharmony_ci } 12688c2ecf20Sopenharmony_ci 12698c2ecf20Sopenharmony_ci if (is_ipsec_esp && encrypt) 12708c2ecf20Sopenharmony_ci elen = authsize; 12718c2ecf20Sopenharmony_ci else 12728c2ecf20Sopenharmony_ci elen = 0; 12738c2ecf20Sopenharmony_ci ret = talitos_sg_map_ext(dev, areq->dst, cryptlen, edesc, &desc->ptr[5], 12748c2ecf20Sopenharmony_ci sg_count, areq->assoclen, tbl_off, elen, 12758c2ecf20Sopenharmony_ci is_ipsec_esp && !encrypt, 1); 12768c2ecf20Sopenharmony_ci tbl_off += ret; 12778c2ecf20Sopenharmony_ci 12788c2ecf20Sopenharmony_ci if (!encrypt && is_ipsec_esp) { 12798c2ecf20Sopenharmony_ci struct talitos_ptr *tbl_ptr = &edesc->link_tbl[tbl_off]; 12808c2ecf20Sopenharmony_ci 12818c2ecf20Sopenharmony_ci /* Add an entry to the link table for ICV data */ 12828c2ecf20Sopenharmony_ci to_talitos_ptr_ext_set(tbl_ptr - 1, 0, is_sec1); 12838c2ecf20Sopenharmony_ci to_talitos_ptr_ext_set(tbl_ptr, DESC_PTR_LNKTBL_RET, is_sec1); 12848c2ecf20Sopenharmony_ci 12858c2ecf20Sopenharmony_ci /* icv data follows link tables */ 12868c2ecf20Sopenharmony_ci to_talitos_ptr(tbl_ptr, dma_icv, authsize, is_sec1); 12878c2ecf20Sopenharmony_ci to_talitos_ptr_ext_or(&desc->ptr[5], authsize, is_sec1); 12888c2ecf20Sopenharmony_ci sync_needed = true; 12898c2ecf20Sopenharmony_ci } else if (!encrypt) { 12908c2ecf20Sopenharmony_ci to_talitos_ptr(&desc->ptr[6], dma_icv, authsize, is_sec1); 12918c2ecf20Sopenharmony_ci sync_needed = true; 12928c2ecf20Sopenharmony_ci } else if (!is_ipsec_esp) { 12938c2ecf20Sopenharmony_ci talitos_sg_map(dev, areq->dst, authsize, edesc, &desc->ptr[6], 12948c2ecf20Sopenharmony_ci sg_count, areq->assoclen + cryptlen, tbl_off); 12958c2ecf20Sopenharmony_ci } 12968c2ecf20Sopenharmony_ci 12978c2ecf20Sopenharmony_ci /* iv out */ 12988c2ecf20Sopenharmony_ci if (is_ipsec_esp) 12998c2ecf20Sopenharmony_ci map_single_talitos_ptr(dev, &desc->ptr[6], ivsize, ctx->iv, 13008c2ecf20Sopenharmony_ci DMA_FROM_DEVICE); 13018c2ecf20Sopenharmony_ci 13028c2ecf20Sopenharmony_ci if (sync_needed) 13038c2ecf20Sopenharmony_ci dma_sync_single_for_device(dev, edesc->dma_link_tbl, 13048c2ecf20Sopenharmony_ci edesc->dma_len, 13058c2ecf20Sopenharmony_ci DMA_BIDIRECTIONAL); 13068c2ecf20Sopenharmony_ci 13078c2ecf20Sopenharmony_ci ret = talitos_submit(dev, ctx->ch, desc, callback, areq); 13088c2ecf20Sopenharmony_ci if (ret != -EINPROGRESS) { 13098c2ecf20Sopenharmony_ci ipsec_esp_unmap(dev, edesc, areq, encrypt); 13108c2ecf20Sopenharmony_ci kfree(edesc); 13118c2ecf20Sopenharmony_ci } 13128c2ecf20Sopenharmony_ci return ret; 13138c2ecf20Sopenharmony_ci} 13148c2ecf20Sopenharmony_ci 13158c2ecf20Sopenharmony_ci/* 13168c2ecf20Sopenharmony_ci * allocate and map the extended descriptor 13178c2ecf20Sopenharmony_ci */ 13188c2ecf20Sopenharmony_cistatic struct talitos_edesc *talitos_edesc_alloc(struct device *dev, 13198c2ecf20Sopenharmony_ci struct scatterlist *src, 13208c2ecf20Sopenharmony_ci struct scatterlist *dst, 13218c2ecf20Sopenharmony_ci u8 *iv, 13228c2ecf20Sopenharmony_ci unsigned int assoclen, 13238c2ecf20Sopenharmony_ci unsigned int cryptlen, 13248c2ecf20Sopenharmony_ci unsigned int authsize, 13258c2ecf20Sopenharmony_ci unsigned int ivsize, 13268c2ecf20Sopenharmony_ci int icv_stashing, 13278c2ecf20Sopenharmony_ci u32 cryptoflags, 13288c2ecf20Sopenharmony_ci bool encrypt) 13298c2ecf20Sopenharmony_ci{ 13308c2ecf20Sopenharmony_ci struct talitos_edesc *edesc; 13318c2ecf20Sopenharmony_ci int src_nents, dst_nents, alloc_len, dma_len, src_len, dst_len; 13328c2ecf20Sopenharmony_ci dma_addr_t iv_dma = 0; 13338c2ecf20Sopenharmony_ci gfp_t flags = cryptoflags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL : 13348c2ecf20Sopenharmony_ci GFP_ATOMIC; 13358c2ecf20Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 13368c2ecf20Sopenharmony_ci bool is_sec1 = has_ftr_sec1(priv); 13378c2ecf20Sopenharmony_ci int max_len = is_sec1 ? TALITOS1_MAX_DATA_LEN : TALITOS2_MAX_DATA_LEN; 13388c2ecf20Sopenharmony_ci 13398c2ecf20Sopenharmony_ci if (cryptlen + authsize > max_len) { 13408c2ecf20Sopenharmony_ci dev_err(dev, "length exceeds h/w max limit\n"); 13418c2ecf20Sopenharmony_ci return ERR_PTR(-EINVAL); 13428c2ecf20Sopenharmony_ci } 13438c2ecf20Sopenharmony_ci 13448c2ecf20Sopenharmony_ci if (!dst || dst == src) { 13458c2ecf20Sopenharmony_ci src_len = assoclen + cryptlen + authsize; 13468c2ecf20Sopenharmony_ci src_nents = sg_nents_for_len(src, src_len); 13478c2ecf20Sopenharmony_ci if (src_nents < 0) { 13488c2ecf20Sopenharmony_ci dev_err(dev, "Invalid number of src SG.\n"); 13498c2ecf20Sopenharmony_ci return ERR_PTR(-EINVAL); 13508c2ecf20Sopenharmony_ci } 13518c2ecf20Sopenharmony_ci src_nents = (src_nents == 1) ? 0 : src_nents; 13528c2ecf20Sopenharmony_ci dst_nents = dst ? src_nents : 0; 13538c2ecf20Sopenharmony_ci dst_len = 0; 13548c2ecf20Sopenharmony_ci } else { /* dst && dst != src*/ 13558c2ecf20Sopenharmony_ci src_len = assoclen + cryptlen + (encrypt ? 0 : authsize); 13568c2ecf20Sopenharmony_ci src_nents = sg_nents_for_len(src, src_len); 13578c2ecf20Sopenharmony_ci if (src_nents < 0) { 13588c2ecf20Sopenharmony_ci dev_err(dev, "Invalid number of src SG.\n"); 13598c2ecf20Sopenharmony_ci return ERR_PTR(-EINVAL); 13608c2ecf20Sopenharmony_ci } 13618c2ecf20Sopenharmony_ci src_nents = (src_nents == 1) ? 0 : src_nents; 13628c2ecf20Sopenharmony_ci dst_len = assoclen + cryptlen + (encrypt ? authsize : 0); 13638c2ecf20Sopenharmony_ci dst_nents = sg_nents_for_len(dst, dst_len); 13648c2ecf20Sopenharmony_ci if (dst_nents < 0) { 13658c2ecf20Sopenharmony_ci dev_err(dev, "Invalid number of dst SG.\n"); 13668c2ecf20Sopenharmony_ci return ERR_PTR(-EINVAL); 13678c2ecf20Sopenharmony_ci } 13688c2ecf20Sopenharmony_ci dst_nents = (dst_nents == 1) ? 0 : dst_nents; 13698c2ecf20Sopenharmony_ci } 13708c2ecf20Sopenharmony_ci 13718c2ecf20Sopenharmony_ci /* 13728c2ecf20Sopenharmony_ci * allocate space for base edesc plus the link tables, 13738c2ecf20Sopenharmony_ci * allowing for two separate entries for AD and generated ICV (+ 2), 13748c2ecf20Sopenharmony_ci * and space for two sets of ICVs (stashed and generated) 13758c2ecf20Sopenharmony_ci */ 13768c2ecf20Sopenharmony_ci alloc_len = sizeof(struct talitos_edesc); 13778c2ecf20Sopenharmony_ci if (src_nents || dst_nents || !encrypt) { 13788c2ecf20Sopenharmony_ci if (is_sec1) 13798c2ecf20Sopenharmony_ci dma_len = (src_nents ? src_len : 0) + 13808c2ecf20Sopenharmony_ci (dst_nents ? dst_len : 0) + authsize; 13818c2ecf20Sopenharmony_ci else 13828c2ecf20Sopenharmony_ci dma_len = (src_nents + dst_nents + 2) * 13838c2ecf20Sopenharmony_ci sizeof(struct talitos_ptr) + authsize; 13848c2ecf20Sopenharmony_ci alloc_len += dma_len; 13858c2ecf20Sopenharmony_ci } else { 13868c2ecf20Sopenharmony_ci dma_len = 0; 13878c2ecf20Sopenharmony_ci } 13888c2ecf20Sopenharmony_ci alloc_len += icv_stashing ? authsize : 0; 13898c2ecf20Sopenharmony_ci 13908c2ecf20Sopenharmony_ci /* if its a ahash, add space for a second desc next to the first one */ 13918c2ecf20Sopenharmony_ci if (is_sec1 && !dst) 13928c2ecf20Sopenharmony_ci alloc_len += sizeof(struct talitos_desc); 13938c2ecf20Sopenharmony_ci alloc_len += ivsize; 13948c2ecf20Sopenharmony_ci 13958c2ecf20Sopenharmony_ci edesc = kmalloc(alloc_len, GFP_DMA | flags); 13968c2ecf20Sopenharmony_ci if (!edesc) 13978c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 13988c2ecf20Sopenharmony_ci if (ivsize) { 13998c2ecf20Sopenharmony_ci iv = memcpy(((u8 *)edesc) + alloc_len - ivsize, iv, ivsize); 14008c2ecf20Sopenharmony_ci iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE); 14018c2ecf20Sopenharmony_ci } 14028c2ecf20Sopenharmony_ci memset(&edesc->desc, 0, sizeof(edesc->desc)); 14038c2ecf20Sopenharmony_ci 14048c2ecf20Sopenharmony_ci edesc->src_nents = src_nents; 14058c2ecf20Sopenharmony_ci edesc->dst_nents = dst_nents; 14068c2ecf20Sopenharmony_ci edesc->iv_dma = iv_dma; 14078c2ecf20Sopenharmony_ci edesc->dma_len = dma_len; 14088c2ecf20Sopenharmony_ci if (dma_len) 14098c2ecf20Sopenharmony_ci edesc->dma_link_tbl = dma_map_single(dev, &edesc->link_tbl[0], 14108c2ecf20Sopenharmony_ci edesc->dma_len, 14118c2ecf20Sopenharmony_ci DMA_BIDIRECTIONAL); 14128c2ecf20Sopenharmony_ci 14138c2ecf20Sopenharmony_ci return edesc; 14148c2ecf20Sopenharmony_ci} 14158c2ecf20Sopenharmony_ci 14168c2ecf20Sopenharmony_cistatic struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv, 14178c2ecf20Sopenharmony_ci int icv_stashing, bool encrypt) 14188c2ecf20Sopenharmony_ci{ 14198c2ecf20Sopenharmony_ci struct crypto_aead *authenc = crypto_aead_reqtfm(areq); 14208c2ecf20Sopenharmony_ci unsigned int authsize = crypto_aead_authsize(authenc); 14218c2ecf20Sopenharmony_ci struct talitos_ctx *ctx = crypto_aead_ctx(authenc); 14228c2ecf20Sopenharmony_ci unsigned int ivsize = crypto_aead_ivsize(authenc); 14238c2ecf20Sopenharmony_ci unsigned int cryptlen = areq->cryptlen - (encrypt ? 0 : authsize); 14248c2ecf20Sopenharmony_ci 14258c2ecf20Sopenharmony_ci return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst, 14268c2ecf20Sopenharmony_ci iv, areq->assoclen, cryptlen, 14278c2ecf20Sopenharmony_ci authsize, ivsize, icv_stashing, 14288c2ecf20Sopenharmony_ci areq->base.flags, encrypt); 14298c2ecf20Sopenharmony_ci} 14308c2ecf20Sopenharmony_ci 14318c2ecf20Sopenharmony_cistatic int aead_encrypt(struct aead_request *req) 14328c2ecf20Sopenharmony_ci{ 14338c2ecf20Sopenharmony_ci struct crypto_aead *authenc = crypto_aead_reqtfm(req); 14348c2ecf20Sopenharmony_ci struct talitos_ctx *ctx = crypto_aead_ctx(authenc); 14358c2ecf20Sopenharmony_ci struct talitos_edesc *edesc; 14368c2ecf20Sopenharmony_ci 14378c2ecf20Sopenharmony_ci /* allocate extended descriptor */ 14388c2ecf20Sopenharmony_ci edesc = aead_edesc_alloc(req, req->iv, 0, true); 14398c2ecf20Sopenharmony_ci if (IS_ERR(edesc)) 14408c2ecf20Sopenharmony_ci return PTR_ERR(edesc); 14418c2ecf20Sopenharmony_ci 14428c2ecf20Sopenharmony_ci /* set encrypt */ 14438c2ecf20Sopenharmony_ci edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT; 14448c2ecf20Sopenharmony_ci 14458c2ecf20Sopenharmony_ci return ipsec_esp(edesc, req, true, ipsec_esp_encrypt_done); 14468c2ecf20Sopenharmony_ci} 14478c2ecf20Sopenharmony_ci 14488c2ecf20Sopenharmony_cistatic int aead_decrypt(struct aead_request *req) 14498c2ecf20Sopenharmony_ci{ 14508c2ecf20Sopenharmony_ci struct crypto_aead *authenc = crypto_aead_reqtfm(req); 14518c2ecf20Sopenharmony_ci unsigned int authsize = crypto_aead_authsize(authenc); 14528c2ecf20Sopenharmony_ci struct talitos_ctx *ctx = crypto_aead_ctx(authenc); 14538c2ecf20Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(ctx->dev); 14548c2ecf20Sopenharmony_ci struct talitos_edesc *edesc; 14558c2ecf20Sopenharmony_ci void *icvdata; 14568c2ecf20Sopenharmony_ci 14578c2ecf20Sopenharmony_ci /* allocate extended descriptor */ 14588c2ecf20Sopenharmony_ci edesc = aead_edesc_alloc(req, req->iv, 1, false); 14598c2ecf20Sopenharmony_ci if (IS_ERR(edesc)) 14608c2ecf20Sopenharmony_ci return PTR_ERR(edesc); 14618c2ecf20Sopenharmony_ci 14628c2ecf20Sopenharmony_ci if ((edesc->desc.hdr & DESC_HDR_TYPE_IPSEC_ESP) && 14638c2ecf20Sopenharmony_ci (priv->features & TALITOS_FTR_HW_AUTH_CHECK) && 14648c2ecf20Sopenharmony_ci ((!edesc->src_nents && !edesc->dst_nents) || 14658c2ecf20Sopenharmony_ci priv->features & TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT)) { 14668c2ecf20Sopenharmony_ci 14678c2ecf20Sopenharmony_ci /* decrypt and check the ICV */ 14688c2ecf20Sopenharmony_ci edesc->desc.hdr = ctx->desc_hdr_template | 14698c2ecf20Sopenharmony_ci DESC_HDR_DIR_INBOUND | 14708c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_CICV; 14718c2ecf20Sopenharmony_ci 14728c2ecf20Sopenharmony_ci /* reset integrity check result bits */ 14738c2ecf20Sopenharmony_ci 14748c2ecf20Sopenharmony_ci return ipsec_esp(edesc, req, false, 14758c2ecf20Sopenharmony_ci ipsec_esp_decrypt_hwauth_done); 14768c2ecf20Sopenharmony_ci } 14778c2ecf20Sopenharmony_ci 14788c2ecf20Sopenharmony_ci /* Have to check the ICV with software */ 14798c2ecf20Sopenharmony_ci edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND; 14808c2ecf20Sopenharmony_ci 14818c2ecf20Sopenharmony_ci /* stash incoming ICV for later cmp with ICV generated by the h/w */ 14828c2ecf20Sopenharmony_ci icvdata = edesc->buf + edesc->dma_len; 14838c2ecf20Sopenharmony_ci 14848c2ecf20Sopenharmony_ci sg_pcopy_to_buffer(req->src, edesc->src_nents ? : 1, icvdata, authsize, 14858c2ecf20Sopenharmony_ci req->assoclen + req->cryptlen - authsize); 14868c2ecf20Sopenharmony_ci 14878c2ecf20Sopenharmony_ci return ipsec_esp(edesc, req, false, ipsec_esp_decrypt_swauth_done); 14888c2ecf20Sopenharmony_ci} 14898c2ecf20Sopenharmony_ci 14908c2ecf20Sopenharmony_cistatic int skcipher_setkey(struct crypto_skcipher *cipher, 14918c2ecf20Sopenharmony_ci const u8 *key, unsigned int keylen) 14928c2ecf20Sopenharmony_ci{ 14938c2ecf20Sopenharmony_ci struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher); 14948c2ecf20Sopenharmony_ci struct device *dev = ctx->dev; 14958c2ecf20Sopenharmony_ci 14968c2ecf20Sopenharmony_ci if (ctx->keylen) 14978c2ecf20Sopenharmony_ci dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE); 14988c2ecf20Sopenharmony_ci 14998c2ecf20Sopenharmony_ci memcpy(&ctx->key, key, keylen); 15008c2ecf20Sopenharmony_ci ctx->keylen = keylen; 15018c2ecf20Sopenharmony_ci 15028c2ecf20Sopenharmony_ci ctx->dma_key = dma_map_single(dev, ctx->key, keylen, DMA_TO_DEVICE); 15038c2ecf20Sopenharmony_ci 15048c2ecf20Sopenharmony_ci return 0; 15058c2ecf20Sopenharmony_ci} 15068c2ecf20Sopenharmony_ci 15078c2ecf20Sopenharmony_cistatic int skcipher_des_setkey(struct crypto_skcipher *cipher, 15088c2ecf20Sopenharmony_ci const u8 *key, unsigned int keylen) 15098c2ecf20Sopenharmony_ci{ 15108c2ecf20Sopenharmony_ci return verify_skcipher_des_key(cipher, key) ?: 15118c2ecf20Sopenharmony_ci skcipher_setkey(cipher, key, keylen); 15128c2ecf20Sopenharmony_ci} 15138c2ecf20Sopenharmony_ci 15148c2ecf20Sopenharmony_cistatic int skcipher_des3_setkey(struct crypto_skcipher *cipher, 15158c2ecf20Sopenharmony_ci const u8 *key, unsigned int keylen) 15168c2ecf20Sopenharmony_ci{ 15178c2ecf20Sopenharmony_ci return verify_skcipher_des3_key(cipher, key) ?: 15188c2ecf20Sopenharmony_ci skcipher_setkey(cipher, key, keylen); 15198c2ecf20Sopenharmony_ci} 15208c2ecf20Sopenharmony_ci 15218c2ecf20Sopenharmony_cistatic int skcipher_aes_setkey(struct crypto_skcipher *cipher, 15228c2ecf20Sopenharmony_ci const u8 *key, unsigned int keylen) 15238c2ecf20Sopenharmony_ci{ 15248c2ecf20Sopenharmony_ci if (keylen == AES_KEYSIZE_128 || keylen == AES_KEYSIZE_192 || 15258c2ecf20Sopenharmony_ci keylen == AES_KEYSIZE_256) 15268c2ecf20Sopenharmony_ci return skcipher_setkey(cipher, key, keylen); 15278c2ecf20Sopenharmony_ci 15288c2ecf20Sopenharmony_ci return -EINVAL; 15298c2ecf20Sopenharmony_ci} 15308c2ecf20Sopenharmony_ci 15318c2ecf20Sopenharmony_cistatic void common_nonsnoop_unmap(struct device *dev, 15328c2ecf20Sopenharmony_ci struct talitos_edesc *edesc, 15338c2ecf20Sopenharmony_ci struct skcipher_request *areq) 15348c2ecf20Sopenharmony_ci{ 15358c2ecf20Sopenharmony_ci unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE); 15368c2ecf20Sopenharmony_ci 15378c2ecf20Sopenharmony_ci talitos_sg_unmap(dev, edesc, areq->src, areq->dst, areq->cryptlen, 0); 15388c2ecf20Sopenharmony_ci unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1], DMA_TO_DEVICE); 15398c2ecf20Sopenharmony_ci 15408c2ecf20Sopenharmony_ci if (edesc->dma_len) 15418c2ecf20Sopenharmony_ci dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len, 15428c2ecf20Sopenharmony_ci DMA_BIDIRECTIONAL); 15438c2ecf20Sopenharmony_ci} 15448c2ecf20Sopenharmony_ci 15458c2ecf20Sopenharmony_cistatic void skcipher_done(struct device *dev, 15468c2ecf20Sopenharmony_ci struct talitos_desc *desc, void *context, 15478c2ecf20Sopenharmony_ci int err) 15488c2ecf20Sopenharmony_ci{ 15498c2ecf20Sopenharmony_ci struct skcipher_request *areq = context; 15508c2ecf20Sopenharmony_ci struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(areq); 15518c2ecf20Sopenharmony_ci struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher); 15528c2ecf20Sopenharmony_ci unsigned int ivsize = crypto_skcipher_ivsize(cipher); 15538c2ecf20Sopenharmony_ci struct talitos_edesc *edesc; 15548c2ecf20Sopenharmony_ci 15558c2ecf20Sopenharmony_ci edesc = container_of(desc, struct talitos_edesc, desc); 15568c2ecf20Sopenharmony_ci 15578c2ecf20Sopenharmony_ci common_nonsnoop_unmap(dev, edesc, areq); 15588c2ecf20Sopenharmony_ci memcpy(areq->iv, ctx->iv, ivsize); 15598c2ecf20Sopenharmony_ci 15608c2ecf20Sopenharmony_ci kfree(edesc); 15618c2ecf20Sopenharmony_ci 15628c2ecf20Sopenharmony_ci areq->base.complete(&areq->base, err); 15638c2ecf20Sopenharmony_ci} 15648c2ecf20Sopenharmony_ci 15658c2ecf20Sopenharmony_cistatic int common_nonsnoop(struct talitos_edesc *edesc, 15668c2ecf20Sopenharmony_ci struct skcipher_request *areq, 15678c2ecf20Sopenharmony_ci void (*callback) (struct device *dev, 15688c2ecf20Sopenharmony_ci struct talitos_desc *desc, 15698c2ecf20Sopenharmony_ci void *context, int error)) 15708c2ecf20Sopenharmony_ci{ 15718c2ecf20Sopenharmony_ci struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(areq); 15728c2ecf20Sopenharmony_ci struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher); 15738c2ecf20Sopenharmony_ci struct device *dev = ctx->dev; 15748c2ecf20Sopenharmony_ci struct talitos_desc *desc = &edesc->desc; 15758c2ecf20Sopenharmony_ci unsigned int cryptlen = areq->cryptlen; 15768c2ecf20Sopenharmony_ci unsigned int ivsize = crypto_skcipher_ivsize(cipher); 15778c2ecf20Sopenharmony_ci int sg_count, ret; 15788c2ecf20Sopenharmony_ci bool sync_needed = false; 15798c2ecf20Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 15808c2ecf20Sopenharmony_ci bool is_sec1 = has_ftr_sec1(priv); 15818c2ecf20Sopenharmony_ci bool is_ctr = (desc->hdr & DESC_HDR_SEL0_MASK) == DESC_HDR_SEL0_AESU && 15828c2ecf20Sopenharmony_ci (desc->hdr & DESC_HDR_MODE0_AESU_MASK) == DESC_HDR_MODE0_AESU_CTR; 15838c2ecf20Sopenharmony_ci 15848c2ecf20Sopenharmony_ci /* first DWORD empty */ 15858c2ecf20Sopenharmony_ci 15868c2ecf20Sopenharmony_ci /* cipher iv */ 15878c2ecf20Sopenharmony_ci to_talitos_ptr(&desc->ptr[1], edesc->iv_dma, ivsize, is_sec1); 15888c2ecf20Sopenharmony_ci 15898c2ecf20Sopenharmony_ci /* cipher key */ 15908c2ecf20Sopenharmony_ci to_talitos_ptr(&desc->ptr[2], ctx->dma_key, ctx->keylen, is_sec1); 15918c2ecf20Sopenharmony_ci 15928c2ecf20Sopenharmony_ci sg_count = edesc->src_nents ?: 1; 15938c2ecf20Sopenharmony_ci if (is_sec1 && sg_count > 1) 15948c2ecf20Sopenharmony_ci sg_copy_to_buffer(areq->src, sg_count, edesc->buf, 15958c2ecf20Sopenharmony_ci cryptlen); 15968c2ecf20Sopenharmony_ci else 15978c2ecf20Sopenharmony_ci sg_count = dma_map_sg(dev, areq->src, sg_count, 15988c2ecf20Sopenharmony_ci (areq->src == areq->dst) ? 15998c2ecf20Sopenharmony_ci DMA_BIDIRECTIONAL : DMA_TO_DEVICE); 16008c2ecf20Sopenharmony_ci /* 16018c2ecf20Sopenharmony_ci * cipher in 16028c2ecf20Sopenharmony_ci */ 16038c2ecf20Sopenharmony_ci sg_count = talitos_sg_map_ext(dev, areq->src, cryptlen, edesc, &desc->ptr[3], 16048c2ecf20Sopenharmony_ci sg_count, 0, 0, 0, false, is_ctr ? 16 : 1); 16058c2ecf20Sopenharmony_ci if (sg_count > 1) 16068c2ecf20Sopenharmony_ci sync_needed = true; 16078c2ecf20Sopenharmony_ci 16088c2ecf20Sopenharmony_ci /* cipher out */ 16098c2ecf20Sopenharmony_ci if (areq->src != areq->dst) { 16108c2ecf20Sopenharmony_ci sg_count = edesc->dst_nents ? : 1; 16118c2ecf20Sopenharmony_ci if (!is_sec1 || sg_count == 1) 16128c2ecf20Sopenharmony_ci dma_map_sg(dev, areq->dst, sg_count, DMA_FROM_DEVICE); 16138c2ecf20Sopenharmony_ci } 16148c2ecf20Sopenharmony_ci 16158c2ecf20Sopenharmony_ci ret = talitos_sg_map(dev, areq->dst, cryptlen, edesc, &desc->ptr[4], 16168c2ecf20Sopenharmony_ci sg_count, 0, (edesc->src_nents + 1)); 16178c2ecf20Sopenharmony_ci if (ret > 1) 16188c2ecf20Sopenharmony_ci sync_needed = true; 16198c2ecf20Sopenharmony_ci 16208c2ecf20Sopenharmony_ci /* iv out */ 16218c2ecf20Sopenharmony_ci map_single_talitos_ptr(dev, &desc->ptr[5], ivsize, ctx->iv, 16228c2ecf20Sopenharmony_ci DMA_FROM_DEVICE); 16238c2ecf20Sopenharmony_ci 16248c2ecf20Sopenharmony_ci /* last DWORD empty */ 16258c2ecf20Sopenharmony_ci 16268c2ecf20Sopenharmony_ci if (sync_needed) 16278c2ecf20Sopenharmony_ci dma_sync_single_for_device(dev, edesc->dma_link_tbl, 16288c2ecf20Sopenharmony_ci edesc->dma_len, DMA_BIDIRECTIONAL); 16298c2ecf20Sopenharmony_ci 16308c2ecf20Sopenharmony_ci ret = talitos_submit(dev, ctx->ch, desc, callback, areq); 16318c2ecf20Sopenharmony_ci if (ret != -EINPROGRESS) { 16328c2ecf20Sopenharmony_ci common_nonsnoop_unmap(dev, edesc, areq); 16338c2ecf20Sopenharmony_ci kfree(edesc); 16348c2ecf20Sopenharmony_ci } 16358c2ecf20Sopenharmony_ci return ret; 16368c2ecf20Sopenharmony_ci} 16378c2ecf20Sopenharmony_ci 16388c2ecf20Sopenharmony_cistatic struct talitos_edesc *skcipher_edesc_alloc(struct skcipher_request * 16398c2ecf20Sopenharmony_ci areq, bool encrypt) 16408c2ecf20Sopenharmony_ci{ 16418c2ecf20Sopenharmony_ci struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(areq); 16428c2ecf20Sopenharmony_ci struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher); 16438c2ecf20Sopenharmony_ci unsigned int ivsize = crypto_skcipher_ivsize(cipher); 16448c2ecf20Sopenharmony_ci 16458c2ecf20Sopenharmony_ci return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst, 16468c2ecf20Sopenharmony_ci areq->iv, 0, areq->cryptlen, 0, ivsize, 0, 16478c2ecf20Sopenharmony_ci areq->base.flags, encrypt); 16488c2ecf20Sopenharmony_ci} 16498c2ecf20Sopenharmony_ci 16508c2ecf20Sopenharmony_cistatic int skcipher_encrypt(struct skcipher_request *areq) 16518c2ecf20Sopenharmony_ci{ 16528c2ecf20Sopenharmony_ci struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(areq); 16538c2ecf20Sopenharmony_ci struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher); 16548c2ecf20Sopenharmony_ci struct talitos_edesc *edesc; 16558c2ecf20Sopenharmony_ci unsigned int blocksize = 16568c2ecf20Sopenharmony_ci crypto_tfm_alg_blocksize(crypto_skcipher_tfm(cipher)); 16578c2ecf20Sopenharmony_ci 16588c2ecf20Sopenharmony_ci if (!areq->cryptlen) 16598c2ecf20Sopenharmony_ci return 0; 16608c2ecf20Sopenharmony_ci 16618c2ecf20Sopenharmony_ci if (areq->cryptlen % blocksize) 16628c2ecf20Sopenharmony_ci return -EINVAL; 16638c2ecf20Sopenharmony_ci 16648c2ecf20Sopenharmony_ci /* allocate extended descriptor */ 16658c2ecf20Sopenharmony_ci edesc = skcipher_edesc_alloc(areq, true); 16668c2ecf20Sopenharmony_ci if (IS_ERR(edesc)) 16678c2ecf20Sopenharmony_ci return PTR_ERR(edesc); 16688c2ecf20Sopenharmony_ci 16698c2ecf20Sopenharmony_ci /* set encrypt */ 16708c2ecf20Sopenharmony_ci edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT; 16718c2ecf20Sopenharmony_ci 16728c2ecf20Sopenharmony_ci return common_nonsnoop(edesc, areq, skcipher_done); 16738c2ecf20Sopenharmony_ci} 16748c2ecf20Sopenharmony_ci 16758c2ecf20Sopenharmony_cistatic int skcipher_decrypt(struct skcipher_request *areq) 16768c2ecf20Sopenharmony_ci{ 16778c2ecf20Sopenharmony_ci struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(areq); 16788c2ecf20Sopenharmony_ci struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher); 16798c2ecf20Sopenharmony_ci struct talitos_edesc *edesc; 16808c2ecf20Sopenharmony_ci unsigned int blocksize = 16818c2ecf20Sopenharmony_ci crypto_tfm_alg_blocksize(crypto_skcipher_tfm(cipher)); 16828c2ecf20Sopenharmony_ci 16838c2ecf20Sopenharmony_ci if (!areq->cryptlen) 16848c2ecf20Sopenharmony_ci return 0; 16858c2ecf20Sopenharmony_ci 16868c2ecf20Sopenharmony_ci if (areq->cryptlen % blocksize) 16878c2ecf20Sopenharmony_ci return -EINVAL; 16888c2ecf20Sopenharmony_ci 16898c2ecf20Sopenharmony_ci /* allocate extended descriptor */ 16908c2ecf20Sopenharmony_ci edesc = skcipher_edesc_alloc(areq, false); 16918c2ecf20Sopenharmony_ci if (IS_ERR(edesc)) 16928c2ecf20Sopenharmony_ci return PTR_ERR(edesc); 16938c2ecf20Sopenharmony_ci 16948c2ecf20Sopenharmony_ci edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND; 16958c2ecf20Sopenharmony_ci 16968c2ecf20Sopenharmony_ci return common_nonsnoop(edesc, areq, skcipher_done); 16978c2ecf20Sopenharmony_ci} 16988c2ecf20Sopenharmony_ci 16998c2ecf20Sopenharmony_cistatic void common_nonsnoop_hash_unmap(struct device *dev, 17008c2ecf20Sopenharmony_ci struct talitos_edesc *edesc, 17018c2ecf20Sopenharmony_ci struct ahash_request *areq) 17028c2ecf20Sopenharmony_ci{ 17038c2ecf20Sopenharmony_ci struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 17048c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 17058c2ecf20Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 17068c2ecf20Sopenharmony_ci bool is_sec1 = has_ftr_sec1(priv); 17078c2ecf20Sopenharmony_ci struct talitos_desc *desc = &edesc->desc; 17088c2ecf20Sopenharmony_ci struct talitos_desc *desc2 = (struct talitos_desc *) 17098c2ecf20Sopenharmony_ci (edesc->buf + edesc->dma_len); 17108c2ecf20Sopenharmony_ci 17118c2ecf20Sopenharmony_ci unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE); 17128c2ecf20Sopenharmony_ci if (desc->next_desc && 17138c2ecf20Sopenharmony_ci desc->ptr[5].ptr != desc2->ptr[5].ptr) 17148c2ecf20Sopenharmony_ci unmap_single_talitos_ptr(dev, &desc2->ptr[5], DMA_FROM_DEVICE); 17158c2ecf20Sopenharmony_ci if (req_ctx->last) 17168c2ecf20Sopenharmony_ci memcpy(areq->result, req_ctx->hw_context, 17178c2ecf20Sopenharmony_ci crypto_ahash_digestsize(tfm)); 17188c2ecf20Sopenharmony_ci 17198c2ecf20Sopenharmony_ci if (req_ctx->psrc) 17208c2ecf20Sopenharmony_ci talitos_sg_unmap(dev, edesc, req_ctx->psrc, NULL, 0, 0); 17218c2ecf20Sopenharmony_ci 17228c2ecf20Sopenharmony_ci /* When using hashctx-in, must unmap it. */ 17238c2ecf20Sopenharmony_ci if (from_talitos_ptr_len(&edesc->desc.ptr[1], is_sec1)) 17248c2ecf20Sopenharmony_ci unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1], 17258c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 17268c2ecf20Sopenharmony_ci else if (desc->next_desc) 17278c2ecf20Sopenharmony_ci unmap_single_talitos_ptr(dev, &desc2->ptr[1], 17288c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 17298c2ecf20Sopenharmony_ci 17308c2ecf20Sopenharmony_ci if (is_sec1 && req_ctx->nbuf) 17318c2ecf20Sopenharmony_ci unmap_single_talitos_ptr(dev, &desc->ptr[3], 17328c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 17338c2ecf20Sopenharmony_ci 17348c2ecf20Sopenharmony_ci if (edesc->dma_len) 17358c2ecf20Sopenharmony_ci dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len, 17368c2ecf20Sopenharmony_ci DMA_BIDIRECTIONAL); 17378c2ecf20Sopenharmony_ci 17388c2ecf20Sopenharmony_ci if (edesc->desc.next_desc) 17398c2ecf20Sopenharmony_ci dma_unmap_single(dev, be32_to_cpu(edesc->desc.next_desc), 17408c2ecf20Sopenharmony_ci TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL); 17418c2ecf20Sopenharmony_ci} 17428c2ecf20Sopenharmony_ci 17438c2ecf20Sopenharmony_cistatic void ahash_done(struct device *dev, 17448c2ecf20Sopenharmony_ci struct talitos_desc *desc, void *context, 17458c2ecf20Sopenharmony_ci int err) 17468c2ecf20Sopenharmony_ci{ 17478c2ecf20Sopenharmony_ci struct ahash_request *areq = context; 17488c2ecf20Sopenharmony_ci struct talitos_edesc *edesc = 17498c2ecf20Sopenharmony_ci container_of(desc, struct talitos_edesc, desc); 17508c2ecf20Sopenharmony_ci struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 17518c2ecf20Sopenharmony_ci 17528c2ecf20Sopenharmony_ci if (!req_ctx->last && req_ctx->to_hash_later) { 17538c2ecf20Sopenharmony_ci /* Position any partial block for next update/final/finup */ 17548c2ecf20Sopenharmony_ci req_ctx->buf_idx = (req_ctx->buf_idx + 1) & 1; 17558c2ecf20Sopenharmony_ci req_ctx->nbuf = req_ctx->to_hash_later; 17568c2ecf20Sopenharmony_ci } 17578c2ecf20Sopenharmony_ci common_nonsnoop_hash_unmap(dev, edesc, areq); 17588c2ecf20Sopenharmony_ci 17598c2ecf20Sopenharmony_ci kfree(edesc); 17608c2ecf20Sopenharmony_ci 17618c2ecf20Sopenharmony_ci areq->base.complete(&areq->base, err); 17628c2ecf20Sopenharmony_ci} 17638c2ecf20Sopenharmony_ci 17648c2ecf20Sopenharmony_ci/* 17658c2ecf20Sopenharmony_ci * SEC1 doesn't like hashing of 0 sized message, so we do the padding 17668c2ecf20Sopenharmony_ci * ourself and submit a padded block 17678c2ecf20Sopenharmony_ci */ 17688c2ecf20Sopenharmony_cistatic void talitos_handle_buggy_hash(struct talitos_ctx *ctx, 17698c2ecf20Sopenharmony_ci struct talitos_edesc *edesc, 17708c2ecf20Sopenharmony_ci struct talitos_ptr *ptr) 17718c2ecf20Sopenharmony_ci{ 17728c2ecf20Sopenharmony_ci static u8 padded_hash[64] = { 17738c2ecf20Sopenharmony_ci 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17748c2ecf20Sopenharmony_ci 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17758c2ecf20Sopenharmony_ci 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17768c2ecf20Sopenharmony_ci 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17778c2ecf20Sopenharmony_ci }; 17788c2ecf20Sopenharmony_ci 17798c2ecf20Sopenharmony_ci pr_err_once("Bug in SEC1, padding ourself\n"); 17808c2ecf20Sopenharmony_ci edesc->desc.hdr &= ~DESC_HDR_MODE0_MDEU_PAD; 17818c2ecf20Sopenharmony_ci map_single_talitos_ptr(ctx->dev, ptr, sizeof(padded_hash), 17828c2ecf20Sopenharmony_ci (char *)padded_hash, DMA_TO_DEVICE); 17838c2ecf20Sopenharmony_ci} 17848c2ecf20Sopenharmony_ci 17858c2ecf20Sopenharmony_cistatic int common_nonsnoop_hash(struct talitos_edesc *edesc, 17868c2ecf20Sopenharmony_ci struct ahash_request *areq, unsigned int length, 17878c2ecf20Sopenharmony_ci void (*callback) (struct device *dev, 17888c2ecf20Sopenharmony_ci struct talitos_desc *desc, 17898c2ecf20Sopenharmony_ci void *context, int error)) 17908c2ecf20Sopenharmony_ci{ 17918c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 17928c2ecf20Sopenharmony_ci struct talitos_ctx *ctx = crypto_ahash_ctx(tfm); 17938c2ecf20Sopenharmony_ci struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 17948c2ecf20Sopenharmony_ci struct device *dev = ctx->dev; 17958c2ecf20Sopenharmony_ci struct talitos_desc *desc = &edesc->desc; 17968c2ecf20Sopenharmony_ci int ret; 17978c2ecf20Sopenharmony_ci bool sync_needed = false; 17988c2ecf20Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 17998c2ecf20Sopenharmony_ci bool is_sec1 = has_ftr_sec1(priv); 18008c2ecf20Sopenharmony_ci int sg_count; 18018c2ecf20Sopenharmony_ci 18028c2ecf20Sopenharmony_ci /* first DWORD empty */ 18038c2ecf20Sopenharmony_ci 18048c2ecf20Sopenharmony_ci /* hash context in */ 18058c2ecf20Sopenharmony_ci if (!req_ctx->first || req_ctx->swinit) { 18068c2ecf20Sopenharmony_ci map_single_talitos_ptr_nosync(dev, &desc->ptr[1], 18078c2ecf20Sopenharmony_ci req_ctx->hw_context_size, 18088c2ecf20Sopenharmony_ci req_ctx->hw_context, 18098c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 18108c2ecf20Sopenharmony_ci req_ctx->swinit = 0; 18118c2ecf20Sopenharmony_ci } 18128c2ecf20Sopenharmony_ci /* Indicate next op is not the first. */ 18138c2ecf20Sopenharmony_ci req_ctx->first = 0; 18148c2ecf20Sopenharmony_ci 18158c2ecf20Sopenharmony_ci /* HMAC key */ 18168c2ecf20Sopenharmony_ci if (ctx->keylen) 18178c2ecf20Sopenharmony_ci to_talitos_ptr(&desc->ptr[2], ctx->dma_key, ctx->keylen, 18188c2ecf20Sopenharmony_ci is_sec1); 18198c2ecf20Sopenharmony_ci 18208c2ecf20Sopenharmony_ci if (is_sec1 && req_ctx->nbuf) 18218c2ecf20Sopenharmony_ci length -= req_ctx->nbuf; 18228c2ecf20Sopenharmony_ci 18238c2ecf20Sopenharmony_ci sg_count = edesc->src_nents ?: 1; 18248c2ecf20Sopenharmony_ci if (is_sec1 && sg_count > 1) 18258c2ecf20Sopenharmony_ci sg_copy_to_buffer(req_ctx->psrc, sg_count, edesc->buf, length); 18268c2ecf20Sopenharmony_ci else if (length) 18278c2ecf20Sopenharmony_ci sg_count = dma_map_sg(dev, req_ctx->psrc, sg_count, 18288c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 18298c2ecf20Sopenharmony_ci /* 18308c2ecf20Sopenharmony_ci * data in 18318c2ecf20Sopenharmony_ci */ 18328c2ecf20Sopenharmony_ci if (is_sec1 && req_ctx->nbuf) { 18338c2ecf20Sopenharmony_ci map_single_talitos_ptr(dev, &desc->ptr[3], req_ctx->nbuf, 18348c2ecf20Sopenharmony_ci req_ctx->buf[req_ctx->buf_idx], 18358c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 18368c2ecf20Sopenharmony_ci } else { 18378c2ecf20Sopenharmony_ci sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc, 18388c2ecf20Sopenharmony_ci &desc->ptr[3], sg_count, 0, 0); 18398c2ecf20Sopenharmony_ci if (sg_count > 1) 18408c2ecf20Sopenharmony_ci sync_needed = true; 18418c2ecf20Sopenharmony_ci } 18428c2ecf20Sopenharmony_ci 18438c2ecf20Sopenharmony_ci /* fifth DWORD empty */ 18448c2ecf20Sopenharmony_ci 18458c2ecf20Sopenharmony_ci /* hash/HMAC out -or- hash context out */ 18468c2ecf20Sopenharmony_ci if (req_ctx->last) 18478c2ecf20Sopenharmony_ci map_single_talitos_ptr(dev, &desc->ptr[5], 18488c2ecf20Sopenharmony_ci crypto_ahash_digestsize(tfm), 18498c2ecf20Sopenharmony_ci req_ctx->hw_context, DMA_FROM_DEVICE); 18508c2ecf20Sopenharmony_ci else 18518c2ecf20Sopenharmony_ci map_single_talitos_ptr_nosync(dev, &desc->ptr[5], 18528c2ecf20Sopenharmony_ci req_ctx->hw_context_size, 18538c2ecf20Sopenharmony_ci req_ctx->hw_context, 18548c2ecf20Sopenharmony_ci DMA_FROM_DEVICE); 18558c2ecf20Sopenharmony_ci 18568c2ecf20Sopenharmony_ci /* last DWORD empty */ 18578c2ecf20Sopenharmony_ci 18588c2ecf20Sopenharmony_ci if (is_sec1 && from_talitos_ptr_len(&desc->ptr[3], true) == 0) 18598c2ecf20Sopenharmony_ci talitos_handle_buggy_hash(ctx, edesc, &desc->ptr[3]); 18608c2ecf20Sopenharmony_ci 18618c2ecf20Sopenharmony_ci if (is_sec1 && req_ctx->nbuf && length) { 18628c2ecf20Sopenharmony_ci struct talitos_desc *desc2 = (struct talitos_desc *) 18638c2ecf20Sopenharmony_ci (edesc->buf + edesc->dma_len); 18648c2ecf20Sopenharmony_ci dma_addr_t next_desc; 18658c2ecf20Sopenharmony_ci 18668c2ecf20Sopenharmony_ci memset(desc2, 0, sizeof(*desc2)); 18678c2ecf20Sopenharmony_ci desc2->hdr = desc->hdr; 18688c2ecf20Sopenharmony_ci desc2->hdr &= ~DESC_HDR_MODE0_MDEU_INIT; 18698c2ecf20Sopenharmony_ci desc2->hdr1 = desc2->hdr; 18708c2ecf20Sopenharmony_ci desc->hdr &= ~DESC_HDR_MODE0_MDEU_PAD; 18718c2ecf20Sopenharmony_ci desc->hdr |= DESC_HDR_MODE0_MDEU_CONT; 18728c2ecf20Sopenharmony_ci desc->hdr &= ~DESC_HDR_DONE_NOTIFY; 18738c2ecf20Sopenharmony_ci 18748c2ecf20Sopenharmony_ci if (desc->ptr[1].ptr) 18758c2ecf20Sopenharmony_ci copy_talitos_ptr(&desc2->ptr[1], &desc->ptr[1], 18768c2ecf20Sopenharmony_ci is_sec1); 18778c2ecf20Sopenharmony_ci else 18788c2ecf20Sopenharmony_ci map_single_talitos_ptr_nosync(dev, &desc2->ptr[1], 18798c2ecf20Sopenharmony_ci req_ctx->hw_context_size, 18808c2ecf20Sopenharmony_ci req_ctx->hw_context, 18818c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 18828c2ecf20Sopenharmony_ci copy_talitos_ptr(&desc2->ptr[2], &desc->ptr[2], is_sec1); 18838c2ecf20Sopenharmony_ci sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc, 18848c2ecf20Sopenharmony_ci &desc2->ptr[3], sg_count, 0, 0); 18858c2ecf20Sopenharmony_ci if (sg_count > 1) 18868c2ecf20Sopenharmony_ci sync_needed = true; 18878c2ecf20Sopenharmony_ci copy_talitos_ptr(&desc2->ptr[5], &desc->ptr[5], is_sec1); 18888c2ecf20Sopenharmony_ci if (req_ctx->last) 18898c2ecf20Sopenharmony_ci map_single_talitos_ptr_nosync(dev, &desc->ptr[5], 18908c2ecf20Sopenharmony_ci req_ctx->hw_context_size, 18918c2ecf20Sopenharmony_ci req_ctx->hw_context, 18928c2ecf20Sopenharmony_ci DMA_FROM_DEVICE); 18938c2ecf20Sopenharmony_ci 18948c2ecf20Sopenharmony_ci next_desc = dma_map_single(dev, &desc2->hdr1, TALITOS_DESC_SIZE, 18958c2ecf20Sopenharmony_ci DMA_BIDIRECTIONAL); 18968c2ecf20Sopenharmony_ci desc->next_desc = cpu_to_be32(next_desc); 18978c2ecf20Sopenharmony_ci } 18988c2ecf20Sopenharmony_ci 18998c2ecf20Sopenharmony_ci if (sync_needed) 19008c2ecf20Sopenharmony_ci dma_sync_single_for_device(dev, edesc->dma_link_tbl, 19018c2ecf20Sopenharmony_ci edesc->dma_len, DMA_BIDIRECTIONAL); 19028c2ecf20Sopenharmony_ci 19038c2ecf20Sopenharmony_ci ret = talitos_submit(dev, ctx->ch, desc, callback, areq); 19048c2ecf20Sopenharmony_ci if (ret != -EINPROGRESS) { 19058c2ecf20Sopenharmony_ci common_nonsnoop_hash_unmap(dev, edesc, areq); 19068c2ecf20Sopenharmony_ci kfree(edesc); 19078c2ecf20Sopenharmony_ci } 19088c2ecf20Sopenharmony_ci return ret; 19098c2ecf20Sopenharmony_ci} 19108c2ecf20Sopenharmony_ci 19118c2ecf20Sopenharmony_cistatic struct talitos_edesc *ahash_edesc_alloc(struct ahash_request *areq, 19128c2ecf20Sopenharmony_ci unsigned int nbytes) 19138c2ecf20Sopenharmony_ci{ 19148c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 19158c2ecf20Sopenharmony_ci struct talitos_ctx *ctx = crypto_ahash_ctx(tfm); 19168c2ecf20Sopenharmony_ci struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 19178c2ecf20Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(ctx->dev); 19188c2ecf20Sopenharmony_ci bool is_sec1 = has_ftr_sec1(priv); 19198c2ecf20Sopenharmony_ci 19208c2ecf20Sopenharmony_ci if (is_sec1) 19218c2ecf20Sopenharmony_ci nbytes -= req_ctx->nbuf; 19228c2ecf20Sopenharmony_ci 19238c2ecf20Sopenharmony_ci return talitos_edesc_alloc(ctx->dev, req_ctx->psrc, NULL, NULL, 0, 19248c2ecf20Sopenharmony_ci nbytes, 0, 0, 0, areq->base.flags, false); 19258c2ecf20Sopenharmony_ci} 19268c2ecf20Sopenharmony_ci 19278c2ecf20Sopenharmony_cistatic int ahash_init(struct ahash_request *areq) 19288c2ecf20Sopenharmony_ci{ 19298c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 19308c2ecf20Sopenharmony_ci struct talitos_ctx *ctx = crypto_ahash_ctx(tfm); 19318c2ecf20Sopenharmony_ci struct device *dev = ctx->dev; 19328c2ecf20Sopenharmony_ci struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 19338c2ecf20Sopenharmony_ci unsigned int size; 19348c2ecf20Sopenharmony_ci dma_addr_t dma; 19358c2ecf20Sopenharmony_ci 19368c2ecf20Sopenharmony_ci /* Initialize the context */ 19378c2ecf20Sopenharmony_ci req_ctx->buf_idx = 0; 19388c2ecf20Sopenharmony_ci req_ctx->nbuf = 0; 19398c2ecf20Sopenharmony_ci req_ctx->first = 1; /* first indicates h/w must init its context */ 19408c2ecf20Sopenharmony_ci req_ctx->swinit = 0; /* assume h/w init of context */ 19418c2ecf20Sopenharmony_ci size = (crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE) 19428c2ecf20Sopenharmony_ci ? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256 19438c2ecf20Sopenharmony_ci : TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512; 19448c2ecf20Sopenharmony_ci req_ctx->hw_context_size = size; 19458c2ecf20Sopenharmony_ci 19468c2ecf20Sopenharmony_ci dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size, 19478c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 19488c2ecf20Sopenharmony_ci dma_unmap_single(dev, dma, req_ctx->hw_context_size, DMA_TO_DEVICE); 19498c2ecf20Sopenharmony_ci 19508c2ecf20Sopenharmony_ci return 0; 19518c2ecf20Sopenharmony_ci} 19528c2ecf20Sopenharmony_ci 19538c2ecf20Sopenharmony_ci/* 19548c2ecf20Sopenharmony_ci * on h/w without explicit sha224 support, we initialize h/w context 19558c2ecf20Sopenharmony_ci * manually with sha224 constants, and tell it to run sha256. 19568c2ecf20Sopenharmony_ci */ 19578c2ecf20Sopenharmony_cistatic int ahash_init_sha224_swinit(struct ahash_request *areq) 19588c2ecf20Sopenharmony_ci{ 19598c2ecf20Sopenharmony_ci struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 19608c2ecf20Sopenharmony_ci 19618c2ecf20Sopenharmony_ci req_ctx->hw_context[0] = SHA224_H0; 19628c2ecf20Sopenharmony_ci req_ctx->hw_context[1] = SHA224_H1; 19638c2ecf20Sopenharmony_ci req_ctx->hw_context[2] = SHA224_H2; 19648c2ecf20Sopenharmony_ci req_ctx->hw_context[3] = SHA224_H3; 19658c2ecf20Sopenharmony_ci req_ctx->hw_context[4] = SHA224_H4; 19668c2ecf20Sopenharmony_ci req_ctx->hw_context[5] = SHA224_H5; 19678c2ecf20Sopenharmony_ci req_ctx->hw_context[6] = SHA224_H6; 19688c2ecf20Sopenharmony_ci req_ctx->hw_context[7] = SHA224_H7; 19698c2ecf20Sopenharmony_ci 19708c2ecf20Sopenharmony_ci /* init 64-bit count */ 19718c2ecf20Sopenharmony_ci req_ctx->hw_context[8] = 0; 19728c2ecf20Sopenharmony_ci req_ctx->hw_context[9] = 0; 19738c2ecf20Sopenharmony_ci 19748c2ecf20Sopenharmony_ci ahash_init(areq); 19758c2ecf20Sopenharmony_ci req_ctx->swinit = 1;/* prevent h/w initting context with sha256 values*/ 19768c2ecf20Sopenharmony_ci 19778c2ecf20Sopenharmony_ci return 0; 19788c2ecf20Sopenharmony_ci} 19798c2ecf20Sopenharmony_ci 19808c2ecf20Sopenharmony_cistatic int ahash_process_req(struct ahash_request *areq, unsigned int nbytes) 19818c2ecf20Sopenharmony_ci{ 19828c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 19838c2ecf20Sopenharmony_ci struct talitos_ctx *ctx = crypto_ahash_ctx(tfm); 19848c2ecf20Sopenharmony_ci struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 19858c2ecf20Sopenharmony_ci struct talitos_edesc *edesc; 19868c2ecf20Sopenharmony_ci unsigned int blocksize = 19878c2ecf20Sopenharmony_ci crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); 19888c2ecf20Sopenharmony_ci unsigned int nbytes_to_hash; 19898c2ecf20Sopenharmony_ci unsigned int to_hash_later; 19908c2ecf20Sopenharmony_ci unsigned int nsg; 19918c2ecf20Sopenharmony_ci int nents; 19928c2ecf20Sopenharmony_ci struct device *dev = ctx->dev; 19938c2ecf20Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 19948c2ecf20Sopenharmony_ci bool is_sec1 = has_ftr_sec1(priv); 19958c2ecf20Sopenharmony_ci u8 *ctx_buf = req_ctx->buf[req_ctx->buf_idx]; 19968c2ecf20Sopenharmony_ci 19978c2ecf20Sopenharmony_ci if (!req_ctx->last && (nbytes + req_ctx->nbuf <= blocksize)) { 19988c2ecf20Sopenharmony_ci /* Buffer up to one whole block */ 19998c2ecf20Sopenharmony_ci nents = sg_nents_for_len(areq->src, nbytes); 20008c2ecf20Sopenharmony_ci if (nents < 0) { 20018c2ecf20Sopenharmony_ci dev_err(ctx->dev, "Invalid number of src SG.\n"); 20028c2ecf20Sopenharmony_ci return nents; 20038c2ecf20Sopenharmony_ci } 20048c2ecf20Sopenharmony_ci sg_copy_to_buffer(areq->src, nents, 20058c2ecf20Sopenharmony_ci ctx_buf + req_ctx->nbuf, nbytes); 20068c2ecf20Sopenharmony_ci req_ctx->nbuf += nbytes; 20078c2ecf20Sopenharmony_ci return 0; 20088c2ecf20Sopenharmony_ci } 20098c2ecf20Sopenharmony_ci 20108c2ecf20Sopenharmony_ci /* At least (blocksize + 1) bytes are available to hash */ 20118c2ecf20Sopenharmony_ci nbytes_to_hash = nbytes + req_ctx->nbuf; 20128c2ecf20Sopenharmony_ci to_hash_later = nbytes_to_hash & (blocksize - 1); 20138c2ecf20Sopenharmony_ci 20148c2ecf20Sopenharmony_ci if (req_ctx->last) 20158c2ecf20Sopenharmony_ci to_hash_later = 0; 20168c2ecf20Sopenharmony_ci else if (to_hash_later) 20178c2ecf20Sopenharmony_ci /* There is a partial block. Hash the full block(s) now */ 20188c2ecf20Sopenharmony_ci nbytes_to_hash -= to_hash_later; 20198c2ecf20Sopenharmony_ci else { 20208c2ecf20Sopenharmony_ci /* Keep one block buffered */ 20218c2ecf20Sopenharmony_ci nbytes_to_hash -= blocksize; 20228c2ecf20Sopenharmony_ci to_hash_later = blocksize; 20238c2ecf20Sopenharmony_ci } 20248c2ecf20Sopenharmony_ci 20258c2ecf20Sopenharmony_ci /* Chain in any previously buffered data */ 20268c2ecf20Sopenharmony_ci if (!is_sec1 && req_ctx->nbuf) { 20278c2ecf20Sopenharmony_ci nsg = (req_ctx->nbuf < nbytes_to_hash) ? 2 : 1; 20288c2ecf20Sopenharmony_ci sg_init_table(req_ctx->bufsl, nsg); 20298c2ecf20Sopenharmony_ci sg_set_buf(req_ctx->bufsl, ctx_buf, req_ctx->nbuf); 20308c2ecf20Sopenharmony_ci if (nsg > 1) 20318c2ecf20Sopenharmony_ci sg_chain(req_ctx->bufsl, 2, areq->src); 20328c2ecf20Sopenharmony_ci req_ctx->psrc = req_ctx->bufsl; 20338c2ecf20Sopenharmony_ci } else if (is_sec1 && req_ctx->nbuf && req_ctx->nbuf < blocksize) { 20348c2ecf20Sopenharmony_ci int offset; 20358c2ecf20Sopenharmony_ci 20368c2ecf20Sopenharmony_ci if (nbytes_to_hash > blocksize) 20378c2ecf20Sopenharmony_ci offset = blocksize - req_ctx->nbuf; 20388c2ecf20Sopenharmony_ci else 20398c2ecf20Sopenharmony_ci offset = nbytes_to_hash - req_ctx->nbuf; 20408c2ecf20Sopenharmony_ci nents = sg_nents_for_len(areq->src, offset); 20418c2ecf20Sopenharmony_ci if (nents < 0) { 20428c2ecf20Sopenharmony_ci dev_err(ctx->dev, "Invalid number of src SG.\n"); 20438c2ecf20Sopenharmony_ci return nents; 20448c2ecf20Sopenharmony_ci } 20458c2ecf20Sopenharmony_ci sg_copy_to_buffer(areq->src, nents, 20468c2ecf20Sopenharmony_ci ctx_buf + req_ctx->nbuf, offset); 20478c2ecf20Sopenharmony_ci req_ctx->nbuf += offset; 20488c2ecf20Sopenharmony_ci req_ctx->psrc = scatterwalk_ffwd(req_ctx->bufsl, areq->src, 20498c2ecf20Sopenharmony_ci offset); 20508c2ecf20Sopenharmony_ci } else 20518c2ecf20Sopenharmony_ci req_ctx->psrc = areq->src; 20528c2ecf20Sopenharmony_ci 20538c2ecf20Sopenharmony_ci if (to_hash_later) { 20548c2ecf20Sopenharmony_ci nents = sg_nents_for_len(areq->src, nbytes); 20558c2ecf20Sopenharmony_ci if (nents < 0) { 20568c2ecf20Sopenharmony_ci dev_err(ctx->dev, "Invalid number of src SG.\n"); 20578c2ecf20Sopenharmony_ci return nents; 20588c2ecf20Sopenharmony_ci } 20598c2ecf20Sopenharmony_ci sg_pcopy_to_buffer(areq->src, nents, 20608c2ecf20Sopenharmony_ci req_ctx->buf[(req_ctx->buf_idx + 1) & 1], 20618c2ecf20Sopenharmony_ci to_hash_later, 20628c2ecf20Sopenharmony_ci nbytes - to_hash_later); 20638c2ecf20Sopenharmony_ci } 20648c2ecf20Sopenharmony_ci req_ctx->to_hash_later = to_hash_later; 20658c2ecf20Sopenharmony_ci 20668c2ecf20Sopenharmony_ci /* Allocate extended descriptor */ 20678c2ecf20Sopenharmony_ci edesc = ahash_edesc_alloc(areq, nbytes_to_hash); 20688c2ecf20Sopenharmony_ci if (IS_ERR(edesc)) 20698c2ecf20Sopenharmony_ci return PTR_ERR(edesc); 20708c2ecf20Sopenharmony_ci 20718c2ecf20Sopenharmony_ci edesc->desc.hdr = ctx->desc_hdr_template; 20728c2ecf20Sopenharmony_ci 20738c2ecf20Sopenharmony_ci /* On last one, request SEC to pad; otherwise continue */ 20748c2ecf20Sopenharmony_ci if (req_ctx->last) 20758c2ecf20Sopenharmony_ci edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_PAD; 20768c2ecf20Sopenharmony_ci else 20778c2ecf20Sopenharmony_ci edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_CONT; 20788c2ecf20Sopenharmony_ci 20798c2ecf20Sopenharmony_ci /* request SEC to INIT hash. */ 20808c2ecf20Sopenharmony_ci if (req_ctx->first && !req_ctx->swinit) 20818c2ecf20Sopenharmony_ci edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_INIT; 20828c2ecf20Sopenharmony_ci 20838c2ecf20Sopenharmony_ci /* When the tfm context has a keylen, it's an HMAC. 20848c2ecf20Sopenharmony_ci * A first or last (ie. not middle) descriptor must request HMAC. 20858c2ecf20Sopenharmony_ci */ 20868c2ecf20Sopenharmony_ci if (ctx->keylen && (req_ctx->first || req_ctx->last)) 20878c2ecf20Sopenharmony_ci edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_HMAC; 20888c2ecf20Sopenharmony_ci 20898c2ecf20Sopenharmony_ci return common_nonsnoop_hash(edesc, areq, nbytes_to_hash, ahash_done); 20908c2ecf20Sopenharmony_ci} 20918c2ecf20Sopenharmony_ci 20928c2ecf20Sopenharmony_cistatic int ahash_update(struct ahash_request *areq) 20938c2ecf20Sopenharmony_ci{ 20948c2ecf20Sopenharmony_ci struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 20958c2ecf20Sopenharmony_ci 20968c2ecf20Sopenharmony_ci req_ctx->last = 0; 20978c2ecf20Sopenharmony_ci 20988c2ecf20Sopenharmony_ci return ahash_process_req(areq, areq->nbytes); 20998c2ecf20Sopenharmony_ci} 21008c2ecf20Sopenharmony_ci 21018c2ecf20Sopenharmony_cistatic int ahash_final(struct ahash_request *areq) 21028c2ecf20Sopenharmony_ci{ 21038c2ecf20Sopenharmony_ci struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 21048c2ecf20Sopenharmony_ci 21058c2ecf20Sopenharmony_ci req_ctx->last = 1; 21068c2ecf20Sopenharmony_ci 21078c2ecf20Sopenharmony_ci return ahash_process_req(areq, 0); 21088c2ecf20Sopenharmony_ci} 21098c2ecf20Sopenharmony_ci 21108c2ecf20Sopenharmony_cistatic int ahash_finup(struct ahash_request *areq) 21118c2ecf20Sopenharmony_ci{ 21128c2ecf20Sopenharmony_ci struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 21138c2ecf20Sopenharmony_ci 21148c2ecf20Sopenharmony_ci req_ctx->last = 1; 21158c2ecf20Sopenharmony_ci 21168c2ecf20Sopenharmony_ci return ahash_process_req(areq, areq->nbytes); 21178c2ecf20Sopenharmony_ci} 21188c2ecf20Sopenharmony_ci 21198c2ecf20Sopenharmony_cistatic int ahash_digest(struct ahash_request *areq) 21208c2ecf20Sopenharmony_ci{ 21218c2ecf20Sopenharmony_ci struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 21228c2ecf20Sopenharmony_ci struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq); 21238c2ecf20Sopenharmony_ci 21248c2ecf20Sopenharmony_ci ahash->init(areq); 21258c2ecf20Sopenharmony_ci req_ctx->last = 1; 21268c2ecf20Sopenharmony_ci 21278c2ecf20Sopenharmony_ci return ahash_process_req(areq, areq->nbytes); 21288c2ecf20Sopenharmony_ci} 21298c2ecf20Sopenharmony_ci 21308c2ecf20Sopenharmony_cistatic int ahash_export(struct ahash_request *areq, void *out) 21318c2ecf20Sopenharmony_ci{ 21328c2ecf20Sopenharmony_ci struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 21338c2ecf20Sopenharmony_ci struct talitos_export_state *export = out; 21348c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 21358c2ecf20Sopenharmony_ci struct talitos_ctx *ctx = crypto_ahash_ctx(tfm); 21368c2ecf20Sopenharmony_ci struct device *dev = ctx->dev; 21378c2ecf20Sopenharmony_ci dma_addr_t dma; 21388c2ecf20Sopenharmony_ci 21398c2ecf20Sopenharmony_ci dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size, 21408c2ecf20Sopenharmony_ci DMA_FROM_DEVICE); 21418c2ecf20Sopenharmony_ci dma_unmap_single(dev, dma, req_ctx->hw_context_size, DMA_FROM_DEVICE); 21428c2ecf20Sopenharmony_ci 21438c2ecf20Sopenharmony_ci memcpy(export->hw_context, req_ctx->hw_context, 21448c2ecf20Sopenharmony_ci req_ctx->hw_context_size); 21458c2ecf20Sopenharmony_ci memcpy(export->buf, req_ctx->buf[req_ctx->buf_idx], req_ctx->nbuf); 21468c2ecf20Sopenharmony_ci export->swinit = req_ctx->swinit; 21478c2ecf20Sopenharmony_ci export->first = req_ctx->first; 21488c2ecf20Sopenharmony_ci export->last = req_ctx->last; 21498c2ecf20Sopenharmony_ci export->to_hash_later = req_ctx->to_hash_later; 21508c2ecf20Sopenharmony_ci export->nbuf = req_ctx->nbuf; 21518c2ecf20Sopenharmony_ci 21528c2ecf20Sopenharmony_ci return 0; 21538c2ecf20Sopenharmony_ci} 21548c2ecf20Sopenharmony_ci 21558c2ecf20Sopenharmony_cistatic int ahash_import(struct ahash_request *areq, const void *in) 21568c2ecf20Sopenharmony_ci{ 21578c2ecf20Sopenharmony_ci struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 21588c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 21598c2ecf20Sopenharmony_ci struct talitos_ctx *ctx = crypto_ahash_ctx(tfm); 21608c2ecf20Sopenharmony_ci struct device *dev = ctx->dev; 21618c2ecf20Sopenharmony_ci const struct talitos_export_state *export = in; 21628c2ecf20Sopenharmony_ci unsigned int size; 21638c2ecf20Sopenharmony_ci dma_addr_t dma; 21648c2ecf20Sopenharmony_ci 21658c2ecf20Sopenharmony_ci memset(req_ctx, 0, sizeof(*req_ctx)); 21668c2ecf20Sopenharmony_ci size = (crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE) 21678c2ecf20Sopenharmony_ci ? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256 21688c2ecf20Sopenharmony_ci : TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512; 21698c2ecf20Sopenharmony_ci req_ctx->hw_context_size = size; 21708c2ecf20Sopenharmony_ci memcpy(req_ctx->hw_context, export->hw_context, size); 21718c2ecf20Sopenharmony_ci memcpy(req_ctx->buf[0], export->buf, export->nbuf); 21728c2ecf20Sopenharmony_ci req_ctx->swinit = export->swinit; 21738c2ecf20Sopenharmony_ci req_ctx->first = export->first; 21748c2ecf20Sopenharmony_ci req_ctx->last = export->last; 21758c2ecf20Sopenharmony_ci req_ctx->to_hash_later = export->to_hash_later; 21768c2ecf20Sopenharmony_ci req_ctx->nbuf = export->nbuf; 21778c2ecf20Sopenharmony_ci 21788c2ecf20Sopenharmony_ci dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size, 21798c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 21808c2ecf20Sopenharmony_ci dma_unmap_single(dev, dma, req_ctx->hw_context_size, DMA_TO_DEVICE); 21818c2ecf20Sopenharmony_ci 21828c2ecf20Sopenharmony_ci return 0; 21838c2ecf20Sopenharmony_ci} 21848c2ecf20Sopenharmony_ci 21858c2ecf20Sopenharmony_cistatic int keyhash(struct crypto_ahash *tfm, const u8 *key, unsigned int keylen, 21868c2ecf20Sopenharmony_ci u8 *hash) 21878c2ecf20Sopenharmony_ci{ 21888c2ecf20Sopenharmony_ci struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); 21898c2ecf20Sopenharmony_ci 21908c2ecf20Sopenharmony_ci struct scatterlist sg[1]; 21918c2ecf20Sopenharmony_ci struct ahash_request *req; 21928c2ecf20Sopenharmony_ci struct crypto_wait wait; 21938c2ecf20Sopenharmony_ci int ret; 21948c2ecf20Sopenharmony_ci 21958c2ecf20Sopenharmony_ci crypto_init_wait(&wait); 21968c2ecf20Sopenharmony_ci 21978c2ecf20Sopenharmony_ci req = ahash_request_alloc(tfm, GFP_KERNEL); 21988c2ecf20Sopenharmony_ci if (!req) 21998c2ecf20Sopenharmony_ci return -ENOMEM; 22008c2ecf20Sopenharmony_ci 22018c2ecf20Sopenharmony_ci /* Keep tfm keylen == 0 during hash of the long key */ 22028c2ecf20Sopenharmony_ci ctx->keylen = 0; 22038c2ecf20Sopenharmony_ci ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, 22048c2ecf20Sopenharmony_ci crypto_req_done, &wait); 22058c2ecf20Sopenharmony_ci 22068c2ecf20Sopenharmony_ci sg_init_one(&sg[0], key, keylen); 22078c2ecf20Sopenharmony_ci 22088c2ecf20Sopenharmony_ci ahash_request_set_crypt(req, sg, hash, keylen); 22098c2ecf20Sopenharmony_ci ret = crypto_wait_req(crypto_ahash_digest(req), &wait); 22108c2ecf20Sopenharmony_ci 22118c2ecf20Sopenharmony_ci ahash_request_free(req); 22128c2ecf20Sopenharmony_ci 22138c2ecf20Sopenharmony_ci return ret; 22148c2ecf20Sopenharmony_ci} 22158c2ecf20Sopenharmony_ci 22168c2ecf20Sopenharmony_cistatic int ahash_setkey(struct crypto_ahash *tfm, const u8 *key, 22178c2ecf20Sopenharmony_ci unsigned int keylen) 22188c2ecf20Sopenharmony_ci{ 22198c2ecf20Sopenharmony_ci struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); 22208c2ecf20Sopenharmony_ci struct device *dev = ctx->dev; 22218c2ecf20Sopenharmony_ci unsigned int blocksize = 22228c2ecf20Sopenharmony_ci crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); 22238c2ecf20Sopenharmony_ci unsigned int digestsize = crypto_ahash_digestsize(tfm); 22248c2ecf20Sopenharmony_ci unsigned int keysize = keylen; 22258c2ecf20Sopenharmony_ci u8 hash[SHA512_DIGEST_SIZE]; 22268c2ecf20Sopenharmony_ci int ret; 22278c2ecf20Sopenharmony_ci 22288c2ecf20Sopenharmony_ci if (keylen <= blocksize) 22298c2ecf20Sopenharmony_ci memcpy(ctx->key, key, keysize); 22308c2ecf20Sopenharmony_ci else { 22318c2ecf20Sopenharmony_ci /* Must get the hash of the long key */ 22328c2ecf20Sopenharmony_ci ret = keyhash(tfm, key, keylen, hash); 22338c2ecf20Sopenharmony_ci 22348c2ecf20Sopenharmony_ci if (ret) 22358c2ecf20Sopenharmony_ci return -EINVAL; 22368c2ecf20Sopenharmony_ci 22378c2ecf20Sopenharmony_ci keysize = digestsize; 22388c2ecf20Sopenharmony_ci memcpy(ctx->key, hash, digestsize); 22398c2ecf20Sopenharmony_ci } 22408c2ecf20Sopenharmony_ci 22418c2ecf20Sopenharmony_ci if (ctx->keylen) 22428c2ecf20Sopenharmony_ci dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE); 22438c2ecf20Sopenharmony_ci 22448c2ecf20Sopenharmony_ci ctx->keylen = keysize; 22458c2ecf20Sopenharmony_ci ctx->dma_key = dma_map_single(dev, ctx->key, keysize, DMA_TO_DEVICE); 22468c2ecf20Sopenharmony_ci 22478c2ecf20Sopenharmony_ci return 0; 22488c2ecf20Sopenharmony_ci} 22498c2ecf20Sopenharmony_ci 22508c2ecf20Sopenharmony_ci 22518c2ecf20Sopenharmony_cistruct talitos_alg_template { 22528c2ecf20Sopenharmony_ci u32 type; 22538c2ecf20Sopenharmony_ci u32 priority; 22548c2ecf20Sopenharmony_ci union { 22558c2ecf20Sopenharmony_ci struct skcipher_alg skcipher; 22568c2ecf20Sopenharmony_ci struct ahash_alg hash; 22578c2ecf20Sopenharmony_ci struct aead_alg aead; 22588c2ecf20Sopenharmony_ci } alg; 22598c2ecf20Sopenharmony_ci __be32 desc_hdr_template; 22608c2ecf20Sopenharmony_ci}; 22618c2ecf20Sopenharmony_ci 22628c2ecf20Sopenharmony_cistatic struct talitos_alg_template driver_algs[] = { 22638c2ecf20Sopenharmony_ci /* AEAD algorithms. These use a single-pass ipsec_esp descriptor */ 22648c2ecf20Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AEAD, 22658c2ecf20Sopenharmony_ci .alg.aead = { 22668c2ecf20Sopenharmony_ci .base = { 22678c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(sha1),cbc(aes))", 22688c2ecf20Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha1-" 22698c2ecf20Sopenharmony_ci "cbc-aes-talitos", 22708c2ecf20Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 22718c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 22728c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 22738c2ecf20Sopenharmony_ci }, 22748c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 22758c2ecf20Sopenharmony_ci .maxauthsize = SHA1_DIGEST_SIZE, 22768c2ecf20Sopenharmony_ci }, 22778c2ecf20Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 22788c2ecf20Sopenharmony_ci DESC_HDR_SEL0_AESU | 22798c2ecf20Sopenharmony_ci DESC_HDR_MODE0_AESU_CBC | 22808c2ecf20Sopenharmony_ci DESC_HDR_SEL1_MDEUA | 22818c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_INIT | 22828c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_PAD | 22838c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_SHA1_HMAC, 22848c2ecf20Sopenharmony_ci }, 22858c2ecf20Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AEAD, 22868c2ecf20Sopenharmony_ci .priority = TALITOS_CRA_PRIORITY_AEAD_HSNA, 22878c2ecf20Sopenharmony_ci .alg.aead = { 22888c2ecf20Sopenharmony_ci .base = { 22898c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(sha1),cbc(aes))", 22908c2ecf20Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha1-" 22918c2ecf20Sopenharmony_ci "cbc-aes-talitos-hsna", 22928c2ecf20Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 22938c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 22948c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 22958c2ecf20Sopenharmony_ci }, 22968c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 22978c2ecf20Sopenharmony_ci .maxauthsize = SHA1_DIGEST_SIZE, 22988c2ecf20Sopenharmony_ci }, 22998c2ecf20Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | 23008c2ecf20Sopenharmony_ci DESC_HDR_SEL0_AESU | 23018c2ecf20Sopenharmony_ci DESC_HDR_MODE0_AESU_CBC | 23028c2ecf20Sopenharmony_ci DESC_HDR_SEL1_MDEUA | 23038c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_INIT | 23048c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_PAD | 23058c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_SHA1_HMAC, 23068c2ecf20Sopenharmony_ci }, 23078c2ecf20Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AEAD, 23088c2ecf20Sopenharmony_ci .alg.aead = { 23098c2ecf20Sopenharmony_ci .base = { 23108c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(sha1)," 23118c2ecf20Sopenharmony_ci "cbc(des3_ede))", 23128c2ecf20Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha1-" 23138c2ecf20Sopenharmony_ci "cbc-3des-talitos", 23148c2ecf20Sopenharmony_ci .cra_blocksize = DES3_EDE_BLOCK_SIZE, 23158c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 23168c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 23178c2ecf20Sopenharmony_ci }, 23188c2ecf20Sopenharmony_ci .ivsize = DES3_EDE_BLOCK_SIZE, 23198c2ecf20Sopenharmony_ci .maxauthsize = SHA1_DIGEST_SIZE, 23208c2ecf20Sopenharmony_ci .setkey = aead_des3_setkey, 23218c2ecf20Sopenharmony_ci }, 23228c2ecf20Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 23238c2ecf20Sopenharmony_ci DESC_HDR_SEL0_DEU | 23248c2ecf20Sopenharmony_ci DESC_HDR_MODE0_DEU_CBC | 23258c2ecf20Sopenharmony_ci DESC_HDR_MODE0_DEU_3DES | 23268c2ecf20Sopenharmony_ci DESC_HDR_SEL1_MDEUA | 23278c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_INIT | 23288c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_PAD | 23298c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_SHA1_HMAC, 23308c2ecf20Sopenharmony_ci }, 23318c2ecf20Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AEAD, 23328c2ecf20Sopenharmony_ci .priority = TALITOS_CRA_PRIORITY_AEAD_HSNA, 23338c2ecf20Sopenharmony_ci .alg.aead = { 23348c2ecf20Sopenharmony_ci .base = { 23358c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(sha1)," 23368c2ecf20Sopenharmony_ci "cbc(des3_ede))", 23378c2ecf20Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha1-" 23388c2ecf20Sopenharmony_ci "cbc-3des-talitos-hsna", 23398c2ecf20Sopenharmony_ci .cra_blocksize = DES3_EDE_BLOCK_SIZE, 23408c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 23418c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 23428c2ecf20Sopenharmony_ci }, 23438c2ecf20Sopenharmony_ci .ivsize = DES3_EDE_BLOCK_SIZE, 23448c2ecf20Sopenharmony_ci .maxauthsize = SHA1_DIGEST_SIZE, 23458c2ecf20Sopenharmony_ci .setkey = aead_des3_setkey, 23468c2ecf20Sopenharmony_ci }, 23478c2ecf20Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | 23488c2ecf20Sopenharmony_ci DESC_HDR_SEL0_DEU | 23498c2ecf20Sopenharmony_ci DESC_HDR_MODE0_DEU_CBC | 23508c2ecf20Sopenharmony_ci DESC_HDR_MODE0_DEU_3DES | 23518c2ecf20Sopenharmony_ci DESC_HDR_SEL1_MDEUA | 23528c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_INIT | 23538c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_PAD | 23548c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_SHA1_HMAC, 23558c2ecf20Sopenharmony_ci }, 23568c2ecf20Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AEAD, 23578c2ecf20Sopenharmony_ci .alg.aead = { 23588c2ecf20Sopenharmony_ci .base = { 23598c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(sha224),cbc(aes))", 23608c2ecf20Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha224-" 23618c2ecf20Sopenharmony_ci "cbc-aes-talitos", 23628c2ecf20Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 23638c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 23648c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 23658c2ecf20Sopenharmony_ci }, 23668c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 23678c2ecf20Sopenharmony_ci .maxauthsize = SHA224_DIGEST_SIZE, 23688c2ecf20Sopenharmony_ci }, 23698c2ecf20Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 23708c2ecf20Sopenharmony_ci DESC_HDR_SEL0_AESU | 23718c2ecf20Sopenharmony_ci DESC_HDR_MODE0_AESU_CBC | 23728c2ecf20Sopenharmony_ci DESC_HDR_SEL1_MDEUA | 23738c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_INIT | 23748c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_PAD | 23758c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_SHA224_HMAC, 23768c2ecf20Sopenharmony_ci }, 23778c2ecf20Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AEAD, 23788c2ecf20Sopenharmony_ci .priority = TALITOS_CRA_PRIORITY_AEAD_HSNA, 23798c2ecf20Sopenharmony_ci .alg.aead = { 23808c2ecf20Sopenharmony_ci .base = { 23818c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(sha224),cbc(aes))", 23828c2ecf20Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha224-" 23838c2ecf20Sopenharmony_ci "cbc-aes-talitos-hsna", 23848c2ecf20Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 23858c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 23868c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 23878c2ecf20Sopenharmony_ci }, 23888c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 23898c2ecf20Sopenharmony_ci .maxauthsize = SHA224_DIGEST_SIZE, 23908c2ecf20Sopenharmony_ci }, 23918c2ecf20Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | 23928c2ecf20Sopenharmony_ci DESC_HDR_SEL0_AESU | 23938c2ecf20Sopenharmony_ci DESC_HDR_MODE0_AESU_CBC | 23948c2ecf20Sopenharmony_ci DESC_HDR_SEL1_MDEUA | 23958c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_INIT | 23968c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_PAD | 23978c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_SHA224_HMAC, 23988c2ecf20Sopenharmony_ci }, 23998c2ecf20Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AEAD, 24008c2ecf20Sopenharmony_ci .alg.aead = { 24018c2ecf20Sopenharmony_ci .base = { 24028c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(sha224)," 24038c2ecf20Sopenharmony_ci "cbc(des3_ede))", 24048c2ecf20Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha224-" 24058c2ecf20Sopenharmony_ci "cbc-3des-talitos", 24068c2ecf20Sopenharmony_ci .cra_blocksize = DES3_EDE_BLOCK_SIZE, 24078c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 24088c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 24098c2ecf20Sopenharmony_ci }, 24108c2ecf20Sopenharmony_ci .ivsize = DES3_EDE_BLOCK_SIZE, 24118c2ecf20Sopenharmony_ci .maxauthsize = SHA224_DIGEST_SIZE, 24128c2ecf20Sopenharmony_ci .setkey = aead_des3_setkey, 24138c2ecf20Sopenharmony_ci }, 24148c2ecf20Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 24158c2ecf20Sopenharmony_ci DESC_HDR_SEL0_DEU | 24168c2ecf20Sopenharmony_ci DESC_HDR_MODE0_DEU_CBC | 24178c2ecf20Sopenharmony_ci DESC_HDR_MODE0_DEU_3DES | 24188c2ecf20Sopenharmony_ci DESC_HDR_SEL1_MDEUA | 24198c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_INIT | 24208c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_PAD | 24218c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_SHA224_HMAC, 24228c2ecf20Sopenharmony_ci }, 24238c2ecf20Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AEAD, 24248c2ecf20Sopenharmony_ci .priority = TALITOS_CRA_PRIORITY_AEAD_HSNA, 24258c2ecf20Sopenharmony_ci .alg.aead = { 24268c2ecf20Sopenharmony_ci .base = { 24278c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(sha224)," 24288c2ecf20Sopenharmony_ci "cbc(des3_ede))", 24298c2ecf20Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha224-" 24308c2ecf20Sopenharmony_ci "cbc-3des-talitos-hsna", 24318c2ecf20Sopenharmony_ci .cra_blocksize = DES3_EDE_BLOCK_SIZE, 24328c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 24338c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 24348c2ecf20Sopenharmony_ci }, 24358c2ecf20Sopenharmony_ci .ivsize = DES3_EDE_BLOCK_SIZE, 24368c2ecf20Sopenharmony_ci .maxauthsize = SHA224_DIGEST_SIZE, 24378c2ecf20Sopenharmony_ci .setkey = aead_des3_setkey, 24388c2ecf20Sopenharmony_ci }, 24398c2ecf20Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | 24408c2ecf20Sopenharmony_ci DESC_HDR_SEL0_DEU | 24418c2ecf20Sopenharmony_ci DESC_HDR_MODE0_DEU_CBC | 24428c2ecf20Sopenharmony_ci DESC_HDR_MODE0_DEU_3DES | 24438c2ecf20Sopenharmony_ci DESC_HDR_SEL1_MDEUA | 24448c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_INIT | 24458c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_PAD | 24468c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_SHA224_HMAC, 24478c2ecf20Sopenharmony_ci }, 24488c2ecf20Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AEAD, 24498c2ecf20Sopenharmony_ci .alg.aead = { 24508c2ecf20Sopenharmony_ci .base = { 24518c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(sha256),cbc(aes))", 24528c2ecf20Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha256-" 24538c2ecf20Sopenharmony_ci "cbc-aes-talitos", 24548c2ecf20Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 24558c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 24568c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 24578c2ecf20Sopenharmony_ci }, 24588c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 24598c2ecf20Sopenharmony_ci .maxauthsize = SHA256_DIGEST_SIZE, 24608c2ecf20Sopenharmony_ci }, 24618c2ecf20Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 24628c2ecf20Sopenharmony_ci DESC_HDR_SEL0_AESU | 24638c2ecf20Sopenharmony_ci DESC_HDR_MODE0_AESU_CBC | 24648c2ecf20Sopenharmony_ci DESC_HDR_SEL1_MDEUA | 24658c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_INIT | 24668c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_PAD | 24678c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_SHA256_HMAC, 24688c2ecf20Sopenharmony_ci }, 24698c2ecf20Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AEAD, 24708c2ecf20Sopenharmony_ci .priority = TALITOS_CRA_PRIORITY_AEAD_HSNA, 24718c2ecf20Sopenharmony_ci .alg.aead = { 24728c2ecf20Sopenharmony_ci .base = { 24738c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(sha256),cbc(aes))", 24748c2ecf20Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha256-" 24758c2ecf20Sopenharmony_ci "cbc-aes-talitos-hsna", 24768c2ecf20Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 24778c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 24788c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 24798c2ecf20Sopenharmony_ci }, 24808c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 24818c2ecf20Sopenharmony_ci .maxauthsize = SHA256_DIGEST_SIZE, 24828c2ecf20Sopenharmony_ci }, 24838c2ecf20Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | 24848c2ecf20Sopenharmony_ci DESC_HDR_SEL0_AESU | 24858c2ecf20Sopenharmony_ci DESC_HDR_MODE0_AESU_CBC | 24868c2ecf20Sopenharmony_ci DESC_HDR_SEL1_MDEUA | 24878c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_INIT | 24888c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_PAD | 24898c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_SHA256_HMAC, 24908c2ecf20Sopenharmony_ci }, 24918c2ecf20Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AEAD, 24928c2ecf20Sopenharmony_ci .alg.aead = { 24938c2ecf20Sopenharmony_ci .base = { 24948c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(sha256)," 24958c2ecf20Sopenharmony_ci "cbc(des3_ede))", 24968c2ecf20Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha256-" 24978c2ecf20Sopenharmony_ci "cbc-3des-talitos", 24988c2ecf20Sopenharmony_ci .cra_blocksize = DES3_EDE_BLOCK_SIZE, 24998c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 25008c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 25018c2ecf20Sopenharmony_ci }, 25028c2ecf20Sopenharmony_ci .ivsize = DES3_EDE_BLOCK_SIZE, 25038c2ecf20Sopenharmony_ci .maxauthsize = SHA256_DIGEST_SIZE, 25048c2ecf20Sopenharmony_ci .setkey = aead_des3_setkey, 25058c2ecf20Sopenharmony_ci }, 25068c2ecf20Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 25078c2ecf20Sopenharmony_ci DESC_HDR_SEL0_DEU | 25088c2ecf20Sopenharmony_ci DESC_HDR_MODE0_DEU_CBC | 25098c2ecf20Sopenharmony_ci DESC_HDR_MODE0_DEU_3DES | 25108c2ecf20Sopenharmony_ci DESC_HDR_SEL1_MDEUA | 25118c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_INIT | 25128c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_PAD | 25138c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_SHA256_HMAC, 25148c2ecf20Sopenharmony_ci }, 25158c2ecf20Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AEAD, 25168c2ecf20Sopenharmony_ci .priority = TALITOS_CRA_PRIORITY_AEAD_HSNA, 25178c2ecf20Sopenharmony_ci .alg.aead = { 25188c2ecf20Sopenharmony_ci .base = { 25198c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(sha256)," 25208c2ecf20Sopenharmony_ci "cbc(des3_ede))", 25218c2ecf20Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha256-" 25228c2ecf20Sopenharmony_ci "cbc-3des-talitos-hsna", 25238c2ecf20Sopenharmony_ci .cra_blocksize = DES3_EDE_BLOCK_SIZE, 25248c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 25258c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 25268c2ecf20Sopenharmony_ci }, 25278c2ecf20Sopenharmony_ci .ivsize = DES3_EDE_BLOCK_SIZE, 25288c2ecf20Sopenharmony_ci .maxauthsize = SHA256_DIGEST_SIZE, 25298c2ecf20Sopenharmony_ci .setkey = aead_des3_setkey, 25308c2ecf20Sopenharmony_ci }, 25318c2ecf20Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | 25328c2ecf20Sopenharmony_ci DESC_HDR_SEL0_DEU | 25338c2ecf20Sopenharmony_ci DESC_HDR_MODE0_DEU_CBC | 25348c2ecf20Sopenharmony_ci DESC_HDR_MODE0_DEU_3DES | 25358c2ecf20Sopenharmony_ci DESC_HDR_SEL1_MDEUA | 25368c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_INIT | 25378c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_PAD | 25388c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_SHA256_HMAC, 25398c2ecf20Sopenharmony_ci }, 25408c2ecf20Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AEAD, 25418c2ecf20Sopenharmony_ci .alg.aead = { 25428c2ecf20Sopenharmony_ci .base = { 25438c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(sha384),cbc(aes))", 25448c2ecf20Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha384-" 25458c2ecf20Sopenharmony_ci "cbc-aes-talitos", 25468c2ecf20Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 25478c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 25488c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 25498c2ecf20Sopenharmony_ci }, 25508c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 25518c2ecf20Sopenharmony_ci .maxauthsize = SHA384_DIGEST_SIZE, 25528c2ecf20Sopenharmony_ci }, 25538c2ecf20Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 25548c2ecf20Sopenharmony_ci DESC_HDR_SEL0_AESU | 25558c2ecf20Sopenharmony_ci DESC_HDR_MODE0_AESU_CBC | 25568c2ecf20Sopenharmony_ci DESC_HDR_SEL1_MDEUB | 25578c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_INIT | 25588c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_PAD | 25598c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEUB_SHA384_HMAC, 25608c2ecf20Sopenharmony_ci }, 25618c2ecf20Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AEAD, 25628c2ecf20Sopenharmony_ci .alg.aead = { 25638c2ecf20Sopenharmony_ci .base = { 25648c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(sha384)," 25658c2ecf20Sopenharmony_ci "cbc(des3_ede))", 25668c2ecf20Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha384-" 25678c2ecf20Sopenharmony_ci "cbc-3des-talitos", 25688c2ecf20Sopenharmony_ci .cra_blocksize = DES3_EDE_BLOCK_SIZE, 25698c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 25708c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 25718c2ecf20Sopenharmony_ci }, 25728c2ecf20Sopenharmony_ci .ivsize = DES3_EDE_BLOCK_SIZE, 25738c2ecf20Sopenharmony_ci .maxauthsize = SHA384_DIGEST_SIZE, 25748c2ecf20Sopenharmony_ci .setkey = aead_des3_setkey, 25758c2ecf20Sopenharmony_ci }, 25768c2ecf20Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 25778c2ecf20Sopenharmony_ci DESC_HDR_SEL0_DEU | 25788c2ecf20Sopenharmony_ci DESC_HDR_MODE0_DEU_CBC | 25798c2ecf20Sopenharmony_ci DESC_HDR_MODE0_DEU_3DES | 25808c2ecf20Sopenharmony_ci DESC_HDR_SEL1_MDEUB | 25818c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_INIT | 25828c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_PAD | 25838c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEUB_SHA384_HMAC, 25848c2ecf20Sopenharmony_ci }, 25858c2ecf20Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AEAD, 25868c2ecf20Sopenharmony_ci .alg.aead = { 25878c2ecf20Sopenharmony_ci .base = { 25888c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(sha512),cbc(aes))", 25898c2ecf20Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha512-" 25908c2ecf20Sopenharmony_ci "cbc-aes-talitos", 25918c2ecf20Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 25928c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 25938c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 25948c2ecf20Sopenharmony_ci }, 25958c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 25968c2ecf20Sopenharmony_ci .maxauthsize = SHA512_DIGEST_SIZE, 25978c2ecf20Sopenharmony_ci }, 25988c2ecf20Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 25998c2ecf20Sopenharmony_ci DESC_HDR_SEL0_AESU | 26008c2ecf20Sopenharmony_ci DESC_HDR_MODE0_AESU_CBC | 26018c2ecf20Sopenharmony_ci DESC_HDR_SEL1_MDEUB | 26028c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_INIT | 26038c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_PAD | 26048c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEUB_SHA512_HMAC, 26058c2ecf20Sopenharmony_ci }, 26068c2ecf20Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AEAD, 26078c2ecf20Sopenharmony_ci .alg.aead = { 26088c2ecf20Sopenharmony_ci .base = { 26098c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(sha512)," 26108c2ecf20Sopenharmony_ci "cbc(des3_ede))", 26118c2ecf20Sopenharmony_ci .cra_driver_name = "authenc-hmac-sha512-" 26128c2ecf20Sopenharmony_ci "cbc-3des-talitos", 26138c2ecf20Sopenharmony_ci .cra_blocksize = DES3_EDE_BLOCK_SIZE, 26148c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 26158c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 26168c2ecf20Sopenharmony_ci }, 26178c2ecf20Sopenharmony_ci .ivsize = DES3_EDE_BLOCK_SIZE, 26188c2ecf20Sopenharmony_ci .maxauthsize = SHA512_DIGEST_SIZE, 26198c2ecf20Sopenharmony_ci .setkey = aead_des3_setkey, 26208c2ecf20Sopenharmony_ci }, 26218c2ecf20Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 26228c2ecf20Sopenharmony_ci DESC_HDR_SEL0_DEU | 26238c2ecf20Sopenharmony_ci DESC_HDR_MODE0_DEU_CBC | 26248c2ecf20Sopenharmony_ci DESC_HDR_MODE0_DEU_3DES | 26258c2ecf20Sopenharmony_ci DESC_HDR_SEL1_MDEUB | 26268c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_INIT | 26278c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_PAD | 26288c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEUB_SHA512_HMAC, 26298c2ecf20Sopenharmony_ci }, 26308c2ecf20Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AEAD, 26318c2ecf20Sopenharmony_ci .alg.aead = { 26328c2ecf20Sopenharmony_ci .base = { 26338c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(md5),cbc(aes))", 26348c2ecf20Sopenharmony_ci .cra_driver_name = "authenc-hmac-md5-" 26358c2ecf20Sopenharmony_ci "cbc-aes-talitos", 26368c2ecf20Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 26378c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 26388c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 26398c2ecf20Sopenharmony_ci }, 26408c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 26418c2ecf20Sopenharmony_ci .maxauthsize = MD5_DIGEST_SIZE, 26428c2ecf20Sopenharmony_ci }, 26438c2ecf20Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 26448c2ecf20Sopenharmony_ci DESC_HDR_SEL0_AESU | 26458c2ecf20Sopenharmony_ci DESC_HDR_MODE0_AESU_CBC | 26468c2ecf20Sopenharmony_ci DESC_HDR_SEL1_MDEUA | 26478c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_INIT | 26488c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_PAD | 26498c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_MD5_HMAC, 26508c2ecf20Sopenharmony_ci }, 26518c2ecf20Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AEAD, 26528c2ecf20Sopenharmony_ci .priority = TALITOS_CRA_PRIORITY_AEAD_HSNA, 26538c2ecf20Sopenharmony_ci .alg.aead = { 26548c2ecf20Sopenharmony_ci .base = { 26558c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(md5),cbc(aes))", 26568c2ecf20Sopenharmony_ci .cra_driver_name = "authenc-hmac-md5-" 26578c2ecf20Sopenharmony_ci "cbc-aes-talitos-hsna", 26588c2ecf20Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 26598c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 26608c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 26618c2ecf20Sopenharmony_ci }, 26628c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 26638c2ecf20Sopenharmony_ci .maxauthsize = MD5_DIGEST_SIZE, 26648c2ecf20Sopenharmony_ci }, 26658c2ecf20Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | 26668c2ecf20Sopenharmony_ci DESC_HDR_SEL0_AESU | 26678c2ecf20Sopenharmony_ci DESC_HDR_MODE0_AESU_CBC | 26688c2ecf20Sopenharmony_ci DESC_HDR_SEL1_MDEUA | 26698c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_INIT | 26708c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_PAD | 26718c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_MD5_HMAC, 26728c2ecf20Sopenharmony_ci }, 26738c2ecf20Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AEAD, 26748c2ecf20Sopenharmony_ci .alg.aead = { 26758c2ecf20Sopenharmony_ci .base = { 26768c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(md5),cbc(des3_ede))", 26778c2ecf20Sopenharmony_ci .cra_driver_name = "authenc-hmac-md5-" 26788c2ecf20Sopenharmony_ci "cbc-3des-talitos", 26798c2ecf20Sopenharmony_ci .cra_blocksize = DES3_EDE_BLOCK_SIZE, 26808c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 26818c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 26828c2ecf20Sopenharmony_ci }, 26838c2ecf20Sopenharmony_ci .ivsize = DES3_EDE_BLOCK_SIZE, 26848c2ecf20Sopenharmony_ci .maxauthsize = MD5_DIGEST_SIZE, 26858c2ecf20Sopenharmony_ci .setkey = aead_des3_setkey, 26868c2ecf20Sopenharmony_ci }, 26878c2ecf20Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 26888c2ecf20Sopenharmony_ci DESC_HDR_SEL0_DEU | 26898c2ecf20Sopenharmony_ci DESC_HDR_MODE0_DEU_CBC | 26908c2ecf20Sopenharmony_ci DESC_HDR_MODE0_DEU_3DES | 26918c2ecf20Sopenharmony_ci DESC_HDR_SEL1_MDEUA | 26928c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_INIT | 26938c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_PAD | 26948c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_MD5_HMAC, 26958c2ecf20Sopenharmony_ci }, 26968c2ecf20Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AEAD, 26978c2ecf20Sopenharmony_ci .priority = TALITOS_CRA_PRIORITY_AEAD_HSNA, 26988c2ecf20Sopenharmony_ci .alg.aead = { 26998c2ecf20Sopenharmony_ci .base = { 27008c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(md5),cbc(des3_ede))", 27018c2ecf20Sopenharmony_ci .cra_driver_name = "authenc-hmac-md5-" 27028c2ecf20Sopenharmony_ci "cbc-3des-talitos-hsna", 27038c2ecf20Sopenharmony_ci .cra_blocksize = DES3_EDE_BLOCK_SIZE, 27048c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 27058c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 27068c2ecf20Sopenharmony_ci }, 27078c2ecf20Sopenharmony_ci .ivsize = DES3_EDE_BLOCK_SIZE, 27088c2ecf20Sopenharmony_ci .maxauthsize = MD5_DIGEST_SIZE, 27098c2ecf20Sopenharmony_ci .setkey = aead_des3_setkey, 27108c2ecf20Sopenharmony_ci }, 27118c2ecf20Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | 27128c2ecf20Sopenharmony_ci DESC_HDR_SEL0_DEU | 27138c2ecf20Sopenharmony_ci DESC_HDR_MODE0_DEU_CBC | 27148c2ecf20Sopenharmony_ci DESC_HDR_MODE0_DEU_3DES | 27158c2ecf20Sopenharmony_ci DESC_HDR_SEL1_MDEUA | 27168c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_INIT | 27178c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_PAD | 27188c2ecf20Sopenharmony_ci DESC_HDR_MODE1_MDEU_MD5_HMAC, 27198c2ecf20Sopenharmony_ci }, 27208c2ecf20Sopenharmony_ci /* SKCIPHER algorithms. */ 27218c2ecf20Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_SKCIPHER, 27228c2ecf20Sopenharmony_ci .alg.skcipher = { 27238c2ecf20Sopenharmony_ci .base.cra_name = "ecb(aes)", 27248c2ecf20Sopenharmony_ci .base.cra_driver_name = "ecb-aes-talitos", 27258c2ecf20Sopenharmony_ci .base.cra_blocksize = AES_BLOCK_SIZE, 27268c2ecf20Sopenharmony_ci .base.cra_flags = CRYPTO_ALG_ASYNC | 27278c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 27288c2ecf20Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE, 27298c2ecf20Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE, 27308c2ecf20Sopenharmony_ci .setkey = skcipher_aes_setkey, 27318c2ecf20Sopenharmony_ci }, 27328c2ecf20Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 27338c2ecf20Sopenharmony_ci DESC_HDR_SEL0_AESU, 27348c2ecf20Sopenharmony_ci }, 27358c2ecf20Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_SKCIPHER, 27368c2ecf20Sopenharmony_ci .alg.skcipher = { 27378c2ecf20Sopenharmony_ci .base.cra_name = "cbc(aes)", 27388c2ecf20Sopenharmony_ci .base.cra_driver_name = "cbc-aes-talitos", 27398c2ecf20Sopenharmony_ci .base.cra_blocksize = AES_BLOCK_SIZE, 27408c2ecf20Sopenharmony_ci .base.cra_flags = CRYPTO_ALG_ASYNC | 27418c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 27428c2ecf20Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE, 27438c2ecf20Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE, 27448c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 27458c2ecf20Sopenharmony_ci .setkey = skcipher_aes_setkey, 27468c2ecf20Sopenharmony_ci }, 27478c2ecf20Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 27488c2ecf20Sopenharmony_ci DESC_HDR_SEL0_AESU | 27498c2ecf20Sopenharmony_ci DESC_HDR_MODE0_AESU_CBC, 27508c2ecf20Sopenharmony_ci }, 27518c2ecf20Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_SKCIPHER, 27528c2ecf20Sopenharmony_ci .alg.skcipher = { 27538c2ecf20Sopenharmony_ci .base.cra_name = "ctr(aes)", 27548c2ecf20Sopenharmony_ci .base.cra_driver_name = "ctr-aes-talitos", 27558c2ecf20Sopenharmony_ci .base.cra_blocksize = 1, 27568c2ecf20Sopenharmony_ci .base.cra_flags = CRYPTO_ALG_ASYNC | 27578c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 27588c2ecf20Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE, 27598c2ecf20Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE, 27608c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 27618c2ecf20Sopenharmony_ci .setkey = skcipher_aes_setkey, 27628c2ecf20Sopenharmony_ci }, 27638c2ecf20Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_AESU_CTR_NONSNOOP | 27648c2ecf20Sopenharmony_ci DESC_HDR_SEL0_AESU | 27658c2ecf20Sopenharmony_ci DESC_HDR_MODE0_AESU_CTR, 27668c2ecf20Sopenharmony_ci }, 27678c2ecf20Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_SKCIPHER, 27688c2ecf20Sopenharmony_ci .alg.skcipher = { 27698c2ecf20Sopenharmony_ci .base.cra_name = "ctr(aes)", 27708c2ecf20Sopenharmony_ci .base.cra_driver_name = "ctr-aes-talitos", 27718c2ecf20Sopenharmony_ci .base.cra_blocksize = 1, 27728c2ecf20Sopenharmony_ci .base.cra_flags = CRYPTO_ALG_ASYNC | 27738c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 27748c2ecf20Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE, 27758c2ecf20Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE, 27768c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 27778c2ecf20Sopenharmony_ci .setkey = skcipher_aes_setkey, 27788c2ecf20Sopenharmony_ci }, 27798c2ecf20Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 27808c2ecf20Sopenharmony_ci DESC_HDR_SEL0_AESU | 27818c2ecf20Sopenharmony_ci DESC_HDR_MODE0_AESU_CTR, 27828c2ecf20Sopenharmony_ci }, 27838c2ecf20Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_SKCIPHER, 27848c2ecf20Sopenharmony_ci .alg.skcipher = { 27858c2ecf20Sopenharmony_ci .base.cra_name = "ecb(des)", 27868c2ecf20Sopenharmony_ci .base.cra_driver_name = "ecb-des-talitos", 27878c2ecf20Sopenharmony_ci .base.cra_blocksize = DES_BLOCK_SIZE, 27888c2ecf20Sopenharmony_ci .base.cra_flags = CRYPTO_ALG_ASYNC | 27898c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 27908c2ecf20Sopenharmony_ci .min_keysize = DES_KEY_SIZE, 27918c2ecf20Sopenharmony_ci .max_keysize = DES_KEY_SIZE, 27928c2ecf20Sopenharmony_ci .setkey = skcipher_des_setkey, 27938c2ecf20Sopenharmony_ci }, 27948c2ecf20Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 27958c2ecf20Sopenharmony_ci DESC_HDR_SEL0_DEU, 27968c2ecf20Sopenharmony_ci }, 27978c2ecf20Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_SKCIPHER, 27988c2ecf20Sopenharmony_ci .alg.skcipher = { 27998c2ecf20Sopenharmony_ci .base.cra_name = "cbc(des)", 28008c2ecf20Sopenharmony_ci .base.cra_driver_name = "cbc-des-talitos", 28018c2ecf20Sopenharmony_ci .base.cra_blocksize = DES_BLOCK_SIZE, 28028c2ecf20Sopenharmony_ci .base.cra_flags = CRYPTO_ALG_ASYNC | 28038c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 28048c2ecf20Sopenharmony_ci .min_keysize = DES_KEY_SIZE, 28058c2ecf20Sopenharmony_ci .max_keysize = DES_KEY_SIZE, 28068c2ecf20Sopenharmony_ci .ivsize = DES_BLOCK_SIZE, 28078c2ecf20Sopenharmony_ci .setkey = skcipher_des_setkey, 28088c2ecf20Sopenharmony_ci }, 28098c2ecf20Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 28108c2ecf20Sopenharmony_ci DESC_HDR_SEL0_DEU | 28118c2ecf20Sopenharmony_ci DESC_HDR_MODE0_DEU_CBC, 28128c2ecf20Sopenharmony_ci }, 28138c2ecf20Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_SKCIPHER, 28148c2ecf20Sopenharmony_ci .alg.skcipher = { 28158c2ecf20Sopenharmony_ci .base.cra_name = "ecb(des3_ede)", 28168c2ecf20Sopenharmony_ci .base.cra_driver_name = "ecb-3des-talitos", 28178c2ecf20Sopenharmony_ci .base.cra_blocksize = DES3_EDE_BLOCK_SIZE, 28188c2ecf20Sopenharmony_ci .base.cra_flags = CRYPTO_ALG_ASYNC | 28198c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 28208c2ecf20Sopenharmony_ci .min_keysize = DES3_EDE_KEY_SIZE, 28218c2ecf20Sopenharmony_ci .max_keysize = DES3_EDE_KEY_SIZE, 28228c2ecf20Sopenharmony_ci .setkey = skcipher_des3_setkey, 28238c2ecf20Sopenharmony_ci }, 28248c2ecf20Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 28258c2ecf20Sopenharmony_ci DESC_HDR_SEL0_DEU | 28268c2ecf20Sopenharmony_ci DESC_HDR_MODE0_DEU_3DES, 28278c2ecf20Sopenharmony_ci }, 28288c2ecf20Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_SKCIPHER, 28298c2ecf20Sopenharmony_ci .alg.skcipher = { 28308c2ecf20Sopenharmony_ci .base.cra_name = "cbc(des3_ede)", 28318c2ecf20Sopenharmony_ci .base.cra_driver_name = "cbc-3des-talitos", 28328c2ecf20Sopenharmony_ci .base.cra_blocksize = DES3_EDE_BLOCK_SIZE, 28338c2ecf20Sopenharmony_ci .base.cra_flags = CRYPTO_ALG_ASYNC | 28348c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 28358c2ecf20Sopenharmony_ci .min_keysize = DES3_EDE_KEY_SIZE, 28368c2ecf20Sopenharmony_ci .max_keysize = DES3_EDE_KEY_SIZE, 28378c2ecf20Sopenharmony_ci .ivsize = DES3_EDE_BLOCK_SIZE, 28388c2ecf20Sopenharmony_ci .setkey = skcipher_des3_setkey, 28398c2ecf20Sopenharmony_ci }, 28408c2ecf20Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 28418c2ecf20Sopenharmony_ci DESC_HDR_SEL0_DEU | 28428c2ecf20Sopenharmony_ci DESC_HDR_MODE0_DEU_CBC | 28438c2ecf20Sopenharmony_ci DESC_HDR_MODE0_DEU_3DES, 28448c2ecf20Sopenharmony_ci }, 28458c2ecf20Sopenharmony_ci /* AHASH algorithms. */ 28468c2ecf20Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AHASH, 28478c2ecf20Sopenharmony_ci .alg.hash = { 28488c2ecf20Sopenharmony_ci .halg.digestsize = MD5_DIGEST_SIZE, 28498c2ecf20Sopenharmony_ci .halg.statesize = sizeof(struct talitos_export_state), 28508c2ecf20Sopenharmony_ci .halg.base = { 28518c2ecf20Sopenharmony_ci .cra_name = "md5", 28528c2ecf20Sopenharmony_ci .cra_driver_name = "md5-talitos", 28538c2ecf20Sopenharmony_ci .cra_blocksize = MD5_HMAC_BLOCK_SIZE, 28548c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 28558c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 28568c2ecf20Sopenharmony_ci } 28578c2ecf20Sopenharmony_ci }, 28588c2ecf20Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 28598c2ecf20Sopenharmony_ci DESC_HDR_SEL0_MDEUA | 28608c2ecf20Sopenharmony_ci DESC_HDR_MODE0_MDEU_MD5, 28618c2ecf20Sopenharmony_ci }, 28628c2ecf20Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AHASH, 28638c2ecf20Sopenharmony_ci .alg.hash = { 28648c2ecf20Sopenharmony_ci .halg.digestsize = SHA1_DIGEST_SIZE, 28658c2ecf20Sopenharmony_ci .halg.statesize = sizeof(struct talitos_export_state), 28668c2ecf20Sopenharmony_ci .halg.base = { 28678c2ecf20Sopenharmony_ci .cra_name = "sha1", 28688c2ecf20Sopenharmony_ci .cra_driver_name = "sha1-talitos", 28698c2ecf20Sopenharmony_ci .cra_blocksize = SHA1_BLOCK_SIZE, 28708c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 28718c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 28728c2ecf20Sopenharmony_ci } 28738c2ecf20Sopenharmony_ci }, 28748c2ecf20Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 28758c2ecf20Sopenharmony_ci DESC_HDR_SEL0_MDEUA | 28768c2ecf20Sopenharmony_ci DESC_HDR_MODE0_MDEU_SHA1, 28778c2ecf20Sopenharmony_ci }, 28788c2ecf20Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AHASH, 28798c2ecf20Sopenharmony_ci .alg.hash = { 28808c2ecf20Sopenharmony_ci .halg.digestsize = SHA224_DIGEST_SIZE, 28818c2ecf20Sopenharmony_ci .halg.statesize = sizeof(struct talitos_export_state), 28828c2ecf20Sopenharmony_ci .halg.base = { 28838c2ecf20Sopenharmony_ci .cra_name = "sha224", 28848c2ecf20Sopenharmony_ci .cra_driver_name = "sha224-talitos", 28858c2ecf20Sopenharmony_ci .cra_blocksize = SHA224_BLOCK_SIZE, 28868c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 28878c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 28888c2ecf20Sopenharmony_ci } 28898c2ecf20Sopenharmony_ci }, 28908c2ecf20Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 28918c2ecf20Sopenharmony_ci DESC_HDR_SEL0_MDEUA | 28928c2ecf20Sopenharmony_ci DESC_HDR_MODE0_MDEU_SHA224, 28938c2ecf20Sopenharmony_ci }, 28948c2ecf20Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AHASH, 28958c2ecf20Sopenharmony_ci .alg.hash = { 28968c2ecf20Sopenharmony_ci .halg.digestsize = SHA256_DIGEST_SIZE, 28978c2ecf20Sopenharmony_ci .halg.statesize = sizeof(struct talitos_export_state), 28988c2ecf20Sopenharmony_ci .halg.base = { 28998c2ecf20Sopenharmony_ci .cra_name = "sha256", 29008c2ecf20Sopenharmony_ci .cra_driver_name = "sha256-talitos", 29018c2ecf20Sopenharmony_ci .cra_blocksize = SHA256_BLOCK_SIZE, 29028c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 29038c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 29048c2ecf20Sopenharmony_ci } 29058c2ecf20Sopenharmony_ci }, 29068c2ecf20Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 29078c2ecf20Sopenharmony_ci DESC_HDR_SEL0_MDEUA | 29088c2ecf20Sopenharmony_ci DESC_HDR_MODE0_MDEU_SHA256, 29098c2ecf20Sopenharmony_ci }, 29108c2ecf20Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AHASH, 29118c2ecf20Sopenharmony_ci .alg.hash = { 29128c2ecf20Sopenharmony_ci .halg.digestsize = SHA384_DIGEST_SIZE, 29138c2ecf20Sopenharmony_ci .halg.statesize = sizeof(struct talitos_export_state), 29148c2ecf20Sopenharmony_ci .halg.base = { 29158c2ecf20Sopenharmony_ci .cra_name = "sha384", 29168c2ecf20Sopenharmony_ci .cra_driver_name = "sha384-talitos", 29178c2ecf20Sopenharmony_ci .cra_blocksize = SHA384_BLOCK_SIZE, 29188c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 29198c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 29208c2ecf20Sopenharmony_ci } 29218c2ecf20Sopenharmony_ci }, 29228c2ecf20Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 29238c2ecf20Sopenharmony_ci DESC_HDR_SEL0_MDEUB | 29248c2ecf20Sopenharmony_ci DESC_HDR_MODE0_MDEUB_SHA384, 29258c2ecf20Sopenharmony_ci }, 29268c2ecf20Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AHASH, 29278c2ecf20Sopenharmony_ci .alg.hash = { 29288c2ecf20Sopenharmony_ci .halg.digestsize = SHA512_DIGEST_SIZE, 29298c2ecf20Sopenharmony_ci .halg.statesize = sizeof(struct talitos_export_state), 29308c2ecf20Sopenharmony_ci .halg.base = { 29318c2ecf20Sopenharmony_ci .cra_name = "sha512", 29328c2ecf20Sopenharmony_ci .cra_driver_name = "sha512-talitos", 29338c2ecf20Sopenharmony_ci .cra_blocksize = SHA512_BLOCK_SIZE, 29348c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 29358c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 29368c2ecf20Sopenharmony_ci } 29378c2ecf20Sopenharmony_ci }, 29388c2ecf20Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 29398c2ecf20Sopenharmony_ci DESC_HDR_SEL0_MDEUB | 29408c2ecf20Sopenharmony_ci DESC_HDR_MODE0_MDEUB_SHA512, 29418c2ecf20Sopenharmony_ci }, 29428c2ecf20Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AHASH, 29438c2ecf20Sopenharmony_ci .alg.hash = { 29448c2ecf20Sopenharmony_ci .halg.digestsize = MD5_DIGEST_SIZE, 29458c2ecf20Sopenharmony_ci .halg.statesize = sizeof(struct talitos_export_state), 29468c2ecf20Sopenharmony_ci .halg.base = { 29478c2ecf20Sopenharmony_ci .cra_name = "hmac(md5)", 29488c2ecf20Sopenharmony_ci .cra_driver_name = "hmac-md5-talitos", 29498c2ecf20Sopenharmony_ci .cra_blocksize = MD5_HMAC_BLOCK_SIZE, 29508c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 29518c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 29528c2ecf20Sopenharmony_ci } 29538c2ecf20Sopenharmony_ci }, 29548c2ecf20Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 29558c2ecf20Sopenharmony_ci DESC_HDR_SEL0_MDEUA | 29568c2ecf20Sopenharmony_ci DESC_HDR_MODE0_MDEU_MD5, 29578c2ecf20Sopenharmony_ci }, 29588c2ecf20Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AHASH, 29598c2ecf20Sopenharmony_ci .alg.hash = { 29608c2ecf20Sopenharmony_ci .halg.digestsize = SHA1_DIGEST_SIZE, 29618c2ecf20Sopenharmony_ci .halg.statesize = sizeof(struct talitos_export_state), 29628c2ecf20Sopenharmony_ci .halg.base = { 29638c2ecf20Sopenharmony_ci .cra_name = "hmac(sha1)", 29648c2ecf20Sopenharmony_ci .cra_driver_name = "hmac-sha1-talitos", 29658c2ecf20Sopenharmony_ci .cra_blocksize = SHA1_BLOCK_SIZE, 29668c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 29678c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 29688c2ecf20Sopenharmony_ci } 29698c2ecf20Sopenharmony_ci }, 29708c2ecf20Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 29718c2ecf20Sopenharmony_ci DESC_HDR_SEL0_MDEUA | 29728c2ecf20Sopenharmony_ci DESC_HDR_MODE0_MDEU_SHA1, 29738c2ecf20Sopenharmony_ci }, 29748c2ecf20Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AHASH, 29758c2ecf20Sopenharmony_ci .alg.hash = { 29768c2ecf20Sopenharmony_ci .halg.digestsize = SHA224_DIGEST_SIZE, 29778c2ecf20Sopenharmony_ci .halg.statesize = sizeof(struct talitos_export_state), 29788c2ecf20Sopenharmony_ci .halg.base = { 29798c2ecf20Sopenharmony_ci .cra_name = "hmac(sha224)", 29808c2ecf20Sopenharmony_ci .cra_driver_name = "hmac-sha224-talitos", 29818c2ecf20Sopenharmony_ci .cra_blocksize = SHA224_BLOCK_SIZE, 29828c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 29838c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 29848c2ecf20Sopenharmony_ci } 29858c2ecf20Sopenharmony_ci }, 29868c2ecf20Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 29878c2ecf20Sopenharmony_ci DESC_HDR_SEL0_MDEUA | 29888c2ecf20Sopenharmony_ci DESC_HDR_MODE0_MDEU_SHA224, 29898c2ecf20Sopenharmony_ci }, 29908c2ecf20Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AHASH, 29918c2ecf20Sopenharmony_ci .alg.hash = { 29928c2ecf20Sopenharmony_ci .halg.digestsize = SHA256_DIGEST_SIZE, 29938c2ecf20Sopenharmony_ci .halg.statesize = sizeof(struct talitos_export_state), 29948c2ecf20Sopenharmony_ci .halg.base = { 29958c2ecf20Sopenharmony_ci .cra_name = "hmac(sha256)", 29968c2ecf20Sopenharmony_ci .cra_driver_name = "hmac-sha256-talitos", 29978c2ecf20Sopenharmony_ci .cra_blocksize = SHA256_BLOCK_SIZE, 29988c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 29998c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 30008c2ecf20Sopenharmony_ci } 30018c2ecf20Sopenharmony_ci }, 30028c2ecf20Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 30038c2ecf20Sopenharmony_ci DESC_HDR_SEL0_MDEUA | 30048c2ecf20Sopenharmony_ci DESC_HDR_MODE0_MDEU_SHA256, 30058c2ecf20Sopenharmony_ci }, 30068c2ecf20Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AHASH, 30078c2ecf20Sopenharmony_ci .alg.hash = { 30088c2ecf20Sopenharmony_ci .halg.digestsize = SHA384_DIGEST_SIZE, 30098c2ecf20Sopenharmony_ci .halg.statesize = sizeof(struct talitos_export_state), 30108c2ecf20Sopenharmony_ci .halg.base = { 30118c2ecf20Sopenharmony_ci .cra_name = "hmac(sha384)", 30128c2ecf20Sopenharmony_ci .cra_driver_name = "hmac-sha384-talitos", 30138c2ecf20Sopenharmony_ci .cra_blocksize = SHA384_BLOCK_SIZE, 30148c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 30158c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 30168c2ecf20Sopenharmony_ci } 30178c2ecf20Sopenharmony_ci }, 30188c2ecf20Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 30198c2ecf20Sopenharmony_ci DESC_HDR_SEL0_MDEUB | 30208c2ecf20Sopenharmony_ci DESC_HDR_MODE0_MDEUB_SHA384, 30218c2ecf20Sopenharmony_ci }, 30228c2ecf20Sopenharmony_ci { .type = CRYPTO_ALG_TYPE_AHASH, 30238c2ecf20Sopenharmony_ci .alg.hash = { 30248c2ecf20Sopenharmony_ci .halg.digestsize = SHA512_DIGEST_SIZE, 30258c2ecf20Sopenharmony_ci .halg.statesize = sizeof(struct talitos_export_state), 30268c2ecf20Sopenharmony_ci .halg.base = { 30278c2ecf20Sopenharmony_ci .cra_name = "hmac(sha512)", 30288c2ecf20Sopenharmony_ci .cra_driver_name = "hmac-sha512-talitos", 30298c2ecf20Sopenharmony_ci .cra_blocksize = SHA512_BLOCK_SIZE, 30308c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 30318c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 30328c2ecf20Sopenharmony_ci } 30338c2ecf20Sopenharmony_ci }, 30348c2ecf20Sopenharmony_ci .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 30358c2ecf20Sopenharmony_ci DESC_HDR_SEL0_MDEUB | 30368c2ecf20Sopenharmony_ci DESC_HDR_MODE0_MDEUB_SHA512, 30378c2ecf20Sopenharmony_ci } 30388c2ecf20Sopenharmony_ci}; 30398c2ecf20Sopenharmony_ci 30408c2ecf20Sopenharmony_cistruct talitos_crypto_alg { 30418c2ecf20Sopenharmony_ci struct list_head entry; 30428c2ecf20Sopenharmony_ci struct device *dev; 30438c2ecf20Sopenharmony_ci struct talitos_alg_template algt; 30448c2ecf20Sopenharmony_ci}; 30458c2ecf20Sopenharmony_ci 30468c2ecf20Sopenharmony_cistatic int talitos_init_common(struct talitos_ctx *ctx, 30478c2ecf20Sopenharmony_ci struct talitos_crypto_alg *talitos_alg) 30488c2ecf20Sopenharmony_ci{ 30498c2ecf20Sopenharmony_ci struct talitos_private *priv; 30508c2ecf20Sopenharmony_ci 30518c2ecf20Sopenharmony_ci /* update context with ptr to dev */ 30528c2ecf20Sopenharmony_ci ctx->dev = talitos_alg->dev; 30538c2ecf20Sopenharmony_ci 30548c2ecf20Sopenharmony_ci /* assign SEC channel to tfm in round-robin fashion */ 30558c2ecf20Sopenharmony_ci priv = dev_get_drvdata(ctx->dev); 30568c2ecf20Sopenharmony_ci ctx->ch = atomic_inc_return(&priv->last_chan) & 30578c2ecf20Sopenharmony_ci (priv->num_channels - 1); 30588c2ecf20Sopenharmony_ci 30598c2ecf20Sopenharmony_ci /* copy descriptor header template value */ 30608c2ecf20Sopenharmony_ci ctx->desc_hdr_template = talitos_alg->algt.desc_hdr_template; 30618c2ecf20Sopenharmony_ci 30628c2ecf20Sopenharmony_ci /* select done notification */ 30638c2ecf20Sopenharmony_ci ctx->desc_hdr_template |= DESC_HDR_DONE_NOTIFY; 30648c2ecf20Sopenharmony_ci 30658c2ecf20Sopenharmony_ci return 0; 30668c2ecf20Sopenharmony_ci} 30678c2ecf20Sopenharmony_ci 30688c2ecf20Sopenharmony_cistatic int talitos_cra_init_aead(struct crypto_aead *tfm) 30698c2ecf20Sopenharmony_ci{ 30708c2ecf20Sopenharmony_ci struct aead_alg *alg = crypto_aead_alg(tfm); 30718c2ecf20Sopenharmony_ci struct talitos_crypto_alg *talitos_alg; 30728c2ecf20Sopenharmony_ci struct talitos_ctx *ctx = crypto_aead_ctx(tfm); 30738c2ecf20Sopenharmony_ci 30748c2ecf20Sopenharmony_ci talitos_alg = container_of(alg, struct talitos_crypto_alg, 30758c2ecf20Sopenharmony_ci algt.alg.aead); 30768c2ecf20Sopenharmony_ci 30778c2ecf20Sopenharmony_ci return talitos_init_common(ctx, talitos_alg); 30788c2ecf20Sopenharmony_ci} 30798c2ecf20Sopenharmony_ci 30808c2ecf20Sopenharmony_cistatic int talitos_cra_init_skcipher(struct crypto_skcipher *tfm) 30818c2ecf20Sopenharmony_ci{ 30828c2ecf20Sopenharmony_ci struct skcipher_alg *alg = crypto_skcipher_alg(tfm); 30838c2ecf20Sopenharmony_ci struct talitos_crypto_alg *talitos_alg; 30848c2ecf20Sopenharmony_ci struct talitos_ctx *ctx = crypto_skcipher_ctx(tfm); 30858c2ecf20Sopenharmony_ci 30868c2ecf20Sopenharmony_ci talitos_alg = container_of(alg, struct talitos_crypto_alg, 30878c2ecf20Sopenharmony_ci algt.alg.skcipher); 30888c2ecf20Sopenharmony_ci 30898c2ecf20Sopenharmony_ci return talitos_init_common(ctx, talitos_alg); 30908c2ecf20Sopenharmony_ci} 30918c2ecf20Sopenharmony_ci 30928c2ecf20Sopenharmony_cistatic int talitos_cra_init_ahash(struct crypto_tfm *tfm) 30938c2ecf20Sopenharmony_ci{ 30948c2ecf20Sopenharmony_ci struct crypto_alg *alg = tfm->__crt_alg; 30958c2ecf20Sopenharmony_ci struct talitos_crypto_alg *talitos_alg; 30968c2ecf20Sopenharmony_ci struct talitos_ctx *ctx = crypto_tfm_ctx(tfm); 30978c2ecf20Sopenharmony_ci 30988c2ecf20Sopenharmony_ci talitos_alg = container_of(__crypto_ahash_alg(alg), 30998c2ecf20Sopenharmony_ci struct talitos_crypto_alg, 31008c2ecf20Sopenharmony_ci algt.alg.hash); 31018c2ecf20Sopenharmony_ci 31028c2ecf20Sopenharmony_ci ctx->keylen = 0; 31038c2ecf20Sopenharmony_ci crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), 31048c2ecf20Sopenharmony_ci sizeof(struct talitos_ahash_req_ctx)); 31058c2ecf20Sopenharmony_ci 31068c2ecf20Sopenharmony_ci return talitos_init_common(ctx, talitos_alg); 31078c2ecf20Sopenharmony_ci} 31088c2ecf20Sopenharmony_ci 31098c2ecf20Sopenharmony_cistatic void talitos_cra_exit(struct crypto_tfm *tfm) 31108c2ecf20Sopenharmony_ci{ 31118c2ecf20Sopenharmony_ci struct talitos_ctx *ctx = crypto_tfm_ctx(tfm); 31128c2ecf20Sopenharmony_ci struct device *dev = ctx->dev; 31138c2ecf20Sopenharmony_ci 31148c2ecf20Sopenharmony_ci if (ctx->keylen) 31158c2ecf20Sopenharmony_ci dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE); 31168c2ecf20Sopenharmony_ci} 31178c2ecf20Sopenharmony_ci 31188c2ecf20Sopenharmony_ci/* 31198c2ecf20Sopenharmony_ci * given the alg's descriptor header template, determine whether descriptor 31208c2ecf20Sopenharmony_ci * type and primary/secondary execution units required match the hw 31218c2ecf20Sopenharmony_ci * capabilities description provided in the device tree node. 31228c2ecf20Sopenharmony_ci */ 31238c2ecf20Sopenharmony_cistatic int hw_supports(struct device *dev, __be32 desc_hdr_template) 31248c2ecf20Sopenharmony_ci{ 31258c2ecf20Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 31268c2ecf20Sopenharmony_ci int ret; 31278c2ecf20Sopenharmony_ci 31288c2ecf20Sopenharmony_ci ret = (1 << DESC_TYPE(desc_hdr_template) & priv->desc_types) && 31298c2ecf20Sopenharmony_ci (1 << PRIMARY_EU(desc_hdr_template) & priv->exec_units); 31308c2ecf20Sopenharmony_ci 31318c2ecf20Sopenharmony_ci if (SECONDARY_EU(desc_hdr_template)) 31328c2ecf20Sopenharmony_ci ret = ret && (1 << SECONDARY_EU(desc_hdr_template) 31338c2ecf20Sopenharmony_ci & priv->exec_units); 31348c2ecf20Sopenharmony_ci 31358c2ecf20Sopenharmony_ci return ret; 31368c2ecf20Sopenharmony_ci} 31378c2ecf20Sopenharmony_ci 31388c2ecf20Sopenharmony_cistatic int talitos_remove(struct platform_device *ofdev) 31398c2ecf20Sopenharmony_ci{ 31408c2ecf20Sopenharmony_ci struct device *dev = &ofdev->dev; 31418c2ecf20Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 31428c2ecf20Sopenharmony_ci struct talitos_crypto_alg *t_alg, *n; 31438c2ecf20Sopenharmony_ci int i; 31448c2ecf20Sopenharmony_ci 31458c2ecf20Sopenharmony_ci list_for_each_entry_safe(t_alg, n, &priv->alg_list, entry) { 31468c2ecf20Sopenharmony_ci switch (t_alg->algt.type) { 31478c2ecf20Sopenharmony_ci case CRYPTO_ALG_TYPE_SKCIPHER: 31488c2ecf20Sopenharmony_ci crypto_unregister_skcipher(&t_alg->algt.alg.skcipher); 31498c2ecf20Sopenharmony_ci break; 31508c2ecf20Sopenharmony_ci case CRYPTO_ALG_TYPE_AEAD: 31518c2ecf20Sopenharmony_ci crypto_unregister_aead(&t_alg->algt.alg.aead); 31528c2ecf20Sopenharmony_ci break; 31538c2ecf20Sopenharmony_ci case CRYPTO_ALG_TYPE_AHASH: 31548c2ecf20Sopenharmony_ci crypto_unregister_ahash(&t_alg->algt.alg.hash); 31558c2ecf20Sopenharmony_ci break; 31568c2ecf20Sopenharmony_ci } 31578c2ecf20Sopenharmony_ci list_del(&t_alg->entry); 31588c2ecf20Sopenharmony_ci } 31598c2ecf20Sopenharmony_ci 31608c2ecf20Sopenharmony_ci if (hw_supports(dev, DESC_HDR_SEL0_RNG)) 31618c2ecf20Sopenharmony_ci talitos_unregister_rng(dev); 31628c2ecf20Sopenharmony_ci 31638c2ecf20Sopenharmony_ci for (i = 0; i < 2; i++) 31648c2ecf20Sopenharmony_ci if (priv->irq[i]) { 31658c2ecf20Sopenharmony_ci free_irq(priv->irq[i], dev); 31668c2ecf20Sopenharmony_ci irq_dispose_mapping(priv->irq[i]); 31678c2ecf20Sopenharmony_ci } 31688c2ecf20Sopenharmony_ci 31698c2ecf20Sopenharmony_ci tasklet_kill(&priv->done_task[0]); 31708c2ecf20Sopenharmony_ci if (priv->irq[1]) 31718c2ecf20Sopenharmony_ci tasklet_kill(&priv->done_task[1]); 31728c2ecf20Sopenharmony_ci 31738c2ecf20Sopenharmony_ci return 0; 31748c2ecf20Sopenharmony_ci} 31758c2ecf20Sopenharmony_ci 31768c2ecf20Sopenharmony_cistatic struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev, 31778c2ecf20Sopenharmony_ci struct talitos_alg_template 31788c2ecf20Sopenharmony_ci *template) 31798c2ecf20Sopenharmony_ci{ 31808c2ecf20Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 31818c2ecf20Sopenharmony_ci struct talitos_crypto_alg *t_alg; 31828c2ecf20Sopenharmony_ci struct crypto_alg *alg; 31838c2ecf20Sopenharmony_ci 31848c2ecf20Sopenharmony_ci t_alg = devm_kzalloc(dev, sizeof(struct talitos_crypto_alg), 31858c2ecf20Sopenharmony_ci GFP_KERNEL); 31868c2ecf20Sopenharmony_ci if (!t_alg) 31878c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 31888c2ecf20Sopenharmony_ci 31898c2ecf20Sopenharmony_ci t_alg->algt = *template; 31908c2ecf20Sopenharmony_ci 31918c2ecf20Sopenharmony_ci switch (t_alg->algt.type) { 31928c2ecf20Sopenharmony_ci case CRYPTO_ALG_TYPE_SKCIPHER: 31938c2ecf20Sopenharmony_ci alg = &t_alg->algt.alg.skcipher.base; 31948c2ecf20Sopenharmony_ci alg->cra_exit = talitos_cra_exit; 31958c2ecf20Sopenharmony_ci t_alg->algt.alg.skcipher.init = talitos_cra_init_skcipher; 31968c2ecf20Sopenharmony_ci t_alg->algt.alg.skcipher.setkey = 31978c2ecf20Sopenharmony_ci t_alg->algt.alg.skcipher.setkey ?: skcipher_setkey; 31988c2ecf20Sopenharmony_ci t_alg->algt.alg.skcipher.encrypt = skcipher_encrypt; 31998c2ecf20Sopenharmony_ci t_alg->algt.alg.skcipher.decrypt = skcipher_decrypt; 32008c2ecf20Sopenharmony_ci if (!strcmp(alg->cra_name, "ctr(aes)") && !has_ftr_sec1(priv) && 32018c2ecf20Sopenharmony_ci DESC_TYPE(t_alg->algt.desc_hdr_template) != 32028c2ecf20Sopenharmony_ci DESC_TYPE(DESC_HDR_TYPE_AESU_CTR_NONSNOOP)) { 32038c2ecf20Sopenharmony_ci devm_kfree(dev, t_alg); 32048c2ecf20Sopenharmony_ci return ERR_PTR(-ENOTSUPP); 32058c2ecf20Sopenharmony_ci } 32068c2ecf20Sopenharmony_ci break; 32078c2ecf20Sopenharmony_ci case CRYPTO_ALG_TYPE_AEAD: 32088c2ecf20Sopenharmony_ci alg = &t_alg->algt.alg.aead.base; 32098c2ecf20Sopenharmony_ci alg->cra_exit = talitos_cra_exit; 32108c2ecf20Sopenharmony_ci t_alg->algt.alg.aead.init = talitos_cra_init_aead; 32118c2ecf20Sopenharmony_ci t_alg->algt.alg.aead.setkey = t_alg->algt.alg.aead.setkey ?: 32128c2ecf20Sopenharmony_ci aead_setkey; 32138c2ecf20Sopenharmony_ci t_alg->algt.alg.aead.encrypt = aead_encrypt; 32148c2ecf20Sopenharmony_ci t_alg->algt.alg.aead.decrypt = aead_decrypt; 32158c2ecf20Sopenharmony_ci if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) && 32168c2ecf20Sopenharmony_ci !strncmp(alg->cra_name, "authenc(hmac(sha224)", 20)) { 32178c2ecf20Sopenharmony_ci devm_kfree(dev, t_alg); 32188c2ecf20Sopenharmony_ci return ERR_PTR(-ENOTSUPP); 32198c2ecf20Sopenharmony_ci } 32208c2ecf20Sopenharmony_ci break; 32218c2ecf20Sopenharmony_ci case CRYPTO_ALG_TYPE_AHASH: 32228c2ecf20Sopenharmony_ci alg = &t_alg->algt.alg.hash.halg.base; 32238c2ecf20Sopenharmony_ci alg->cra_init = talitos_cra_init_ahash; 32248c2ecf20Sopenharmony_ci alg->cra_exit = talitos_cra_exit; 32258c2ecf20Sopenharmony_ci t_alg->algt.alg.hash.init = ahash_init; 32268c2ecf20Sopenharmony_ci t_alg->algt.alg.hash.update = ahash_update; 32278c2ecf20Sopenharmony_ci t_alg->algt.alg.hash.final = ahash_final; 32288c2ecf20Sopenharmony_ci t_alg->algt.alg.hash.finup = ahash_finup; 32298c2ecf20Sopenharmony_ci t_alg->algt.alg.hash.digest = ahash_digest; 32308c2ecf20Sopenharmony_ci if (!strncmp(alg->cra_name, "hmac", 4)) 32318c2ecf20Sopenharmony_ci t_alg->algt.alg.hash.setkey = ahash_setkey; 32328c2ecf20Sopenharmony_ci t_alg->algt.alg.hash.import = ahash_import; 32338c2ecf20Sopenharmony_ci t_alg->algt.alg.hash.export = ahash_export; 32348c2ecf20Sopenharmony_ci 32358c2ecf20Sopenharmony_ci if (!(priv->features & TALITOS_FTR_HMAC_OK) && 32368c2ecf20Sopenharmony_ci !strncmp(alg->cra_name, "hmac", 4)) { 32378c2ecf20Sopenharmony_ci devm_kfree(dev, t_alg); 32388c2ecf20Sopenharmony_ci return ERR_PTR(-ENOTSUPP); 32398c2ecf20Sopenharmony_ci } 32408c2ecf20Sopenharmony_ci if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) && 32418c2ecf20Sopenharmony_ci (!strcmp(alg->cra_name, "sha224") || 32428c2ecf20Sopenharmony_ci !strcmp(alg->cra_name, "hmac(sha224)"))) { 32438c2ecf20Sopenharmony_ci t_alg->algt.alg.hash.init = ahash_init_sha224_swinit; 32448c2ecf20Sopenharmony_ci t_alg->algt.desc_hdr_template = 32458c2ecf20Sopenharmony_ci DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 32468c2ecf20Sopenharmony_ci DESC_HDR_SEL0_MDEUA | 32478c2ecf20Sopenharmony_ci DESC_HDR_MODE0_MDEU_SHA256; 32488c2ecf20Sopenharmony_ci } 32498c2ecf20Sopenharmony_ci break; 32508c2ecf20Sopenharmony_ci default: 32518c2ecf20Sopenharmony_ci dev_err(dev, "unknown algorithm type %d\n", t_alg->algt.type); 32528c2ecf20Sopenharmony_ci devm_kfree(dev, t_alg); 32538c2ecf20Sopenharmony_ci return ERR_PTR(-EINVAL); 32548c2ecf20Sopenharmony_ci } 32558c2ecf20Sopenharmony_ci 32568c2ecf20Sopenharmony_ci alg->cra_module = THIS_MODULE; 32578c2ecf20Sopenharmony_ci if (t_alg->algt.priority) 32588c2ecf20Sopenharmony_ci alg->cra_priority = t_alg->algt.priority; 32598c2ecf20Sopenharmony_ci else 32608c2ecf20Sopenharmony_ci alg->cra_priority = TALITOS_CRA_PRIORITY; 32618c2ecf20Sopenharmony_ci if (has_ftr_sec1(priv)) 32628c2ecf20Sopenharmony_ci alg->cra_alignmask = 3; 32638c2ecf20Sopenharmony_ci else 32648c2ecf20Sopenharmony_ci alg->cra_alignmask = 0; 32658c2ecf20Sopenharmony_ci alg->cra_ctxsize = sizeof(struct talitos_ctx); 32668c2ecf20Sopenharmony_ci alg->cra_flags |= CRYPTO_ALG_KERN_DRIVER_ONLY; 32678c2ecf20Sopenharmony_ci 32688c2ecf20Sopenharmony_ci t_alg->dev = dev; 32698c2ecf20Sopenharmony_ci 32708c2ecf20Sopenharmony_ci return t_alg; 32718c2ecf20Sopenharmony_ci} 32728c2ecf20Sopenharmony_ci 32738c2ecf20Sopenharmony_cistatic int talitos_probe_irq(struct platform_device *ofdev) 32748c2ecf20Sopenharmony_ci{ 32758c2ecf20Sopenharmony_ci struct device *dev = &ofdev->dev; 32768c2ecf20Sopenharmony_ci struct device_node *np = ofdev->dev.of_node; 32778c2ecf20Sopenharmony_ci struct talitos_private *priv = dev_get_drvdata(dev); 32788c2ecf20Sopenharmony_ci int err; 32798c2ecf20Sopenharmony_ci bool is_sec1 = has_ftr_sec1(priv); 32808c2ecf20Sopenharmony_ci 32818c2ecf20Sopenharmony_ci priv->irq[0] = irq_of_parse_and_map(np, 0); 32828c2ecf20Sopenharmony_ci if (!priv->irq[0]) { 32838c2ecf20Sopenharmony_ci dev_err(dev, "failed to map irq\n"); 32848c2ecf20Sopenharmony_ci return -EINVAL; 32858c2ecf20Sopenharmony_ci } 32868c2ecf20Sopenharmony_ci if (is_sec1) { 32878c2ecf20Sopenharmony_ci err = request_irq(priv->irq[0], talitos1_interrupt_4ch, 0, 32888c2ecf20Sopenharmony_ci dev_driver_string(dev), dev); 32898c2ecf20Sopenharmony_ci goto primary_out; 32908c2ecf20Sopenharmony_ci } 32918c2ecf20Sopenharmony_ci 32928c2ecf20Sopenharmony_ci priv->irq[1] = irq_of_parse_and_map(np, 1); 32938c2ecf20Sopenharmony_ci 32948c2ecf20Sopenharmony_ci /* get the primary irq line */ 32958c2ecf20Sopenharmony_ci if (!priv->irq[1]) { 32968c2ecf20Sopenharmony_ci err = request_irq(priv->irq[0], talitos2_interrupt_4ch, 0, 32978c2ecf20Sopenharmony_ci dev_driver_string(dev), dev); 32988c2ecf20Sopenharmony_ci goto primary_out; 32998c2ecf20Sopenharmony_ci } 33008c2ecf20Sopenharmony_ci 33018c2ecf20Sopenharmony_ci err = request_irq(priv->irq[0], talitos2_interrupt_ch0_2, 0, 33028c2ecf20Sopenharmony_ci dev_driver_string(dev), dev); 33038c2ecf20Sopenharmony_ci if (err) 33048c2ecf20Sopenharmony_ci goto primary_out; 33058c2ecf20Sopenharmony_ci 33068c2ecf20Sopenharmony_ci /* get the secondary irq line */ 33078c2ecf20Sopenharmony_ci err = request_irq(priv->irq[1], talitos2_interrupt_ch1_3, 0, 33088c2ecf20Sopenharmony_ci dev_driver_string(dev), dev); 33098c2ecf20Sopenharmony_ci if (err) { 33108c2ecf20Sopenharmony_ci dev_err(dev, "failed to request secondary irq\n"); 33118c2ecf20Sopenharmony_ci irq_dispose_mapping(priv->irq[1]); 33128c2ecf20Sopenharmony_ci priv->irq[1] = 0; 33138c2ecf20Sopenharmony_ci } 33148c2ecf20Sopenharmony_ci 33158c2ecf20Sopenharmony_ci return err; 33168c2ecf20Sopenharmony_ci 33178c2ecf20Sopenharmony_ciprimary_out: 33188c2ecf20Sopenharmony_ci if (err) { 33198c2ecf20Sopenharmony_ci dev_err(dev, "failed to request primary irq\n"); 33208c2ecf20Sopenharmony_ci irq_dispose_mapping(priv->irq[0]); 33218c2ecf20Sopenharmony_ci priv->irq[0] = 0; 33228c2ecf20Sopenharmony_ci } 33238c2ecf20Sopenharmony_ci 33248c2ecf20Sopenharmony_ci return err; 33258c2ecf20Sopenharmony_ci} 33268c2ecf20Sopenharmony_ci 33278c2ecf20Sopenharmony_cistatic int talitos_probe(struct platform_device *ofdev) 33288c2ecf20Sopenharmony_ci{ 33298c2ecf20Sopenharmony_ci struct device *dev = &ofdev->dev; 33308c2ecf20Sopenharmony_ci struct device_node *np = ofdev->dev.of_node; 33318c2ecf20Sopenharmony_ci struct talitos_private *priv; 33328c2ecf20Sopenharmony_ci int i, err; 33338c2ecf20Sopenharmony_ci int stride; 33348c2ecf20Sopenharmony_ci struct resource *res; 33358c2ecf20Sopenharmony_ci 33368c2ecf20Sopenharmony_ci priv = devm_kzalloc(dev, sizeof(struct talitos_private), GFP_KERNEL); 33378c2ecf20Sopenharmony_ci if (!priv) 33388c2ecf20Sopenharmony_ci return -ENOMEM; 33398c2ecf20Sopenharmony_ci 33408c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&priv->alg_list); 33418c2ecf20Sopenharmony_ci 33428c2ecf20Sopenharmony_ci dev_set_drvdata(dev, priv); 33438c2ecf20Sopenharmony_ci 33448c2ecf20Sopenharmony_ci priv->ofdev = ofdev; 33458c2ecf20Sopenharmony_ci 33468c2ecf20Sopenharmony_ci spin_lock_init(&priv->reg_lock); 33478c2ecf20Sopenharmony_ci 33488c2ecf20Sopenharmony_ci res = platform_get_resource(ofdev, IORESOURCE_MEM, 0); 33498c2ecf20Sopenharmony_ci if (!res) 33508c2ecf20Sopenharmony_ci return -ENXIO; 33518c2ecf20Sopenharmony_ci priv->reg = devm_ioremap(dev, res->start, resource_size(res)); 33528c2ecf20Sopenharmony_ci if (!priv->reg) { 33538c2ecf20Sopenharmony_ci dev_err(dev, "failed to of_iomap\n"); 33548c2ecf20Sopenharmony_ci err = -ENOMEM; 33558c2ecf20Sopenharmony_ci goto err_out; 33568c2ecf20Sopenharmony_ci } 33578c2ecf20Sopenharmony_ci 33588c2ecf20Sopenharmony_ci /* get SEC version capabilities from device tree */ 33598c2ecf20Sopenharmony_ci of_property_read_u32(np, "fsl,num-channels", &priv->num_channels); 33608c2ecf20Sopenharmony_ci of_property_read_u32(np, "fsl,channel-fifo-len", &priv->chfifo_len); 33618c2ecf20Sopenharmony_ci of_property_read_u32(np, "fsl,exec-units-mask", &priv->exec_units); 33628c2ecf20Sopenharmony_ci of_property_read_u32(np, "fsl,descriptor-types-mask", 33638c2ecf20Sopenharmony_ci &priv->desc_types); 33648c2ecf20Sopenharmony_ci 33658c2ecf20Sopenharmony_ci if (!is_power_of_2(priv->num_channels) || !priv->chfifo_len || 33668c2ecf20Sopenharmony_ci !priv->exec_units || !priv->desc_types) { 33678c2ecf20Sopenharmony_ci dev_err(dev, "invalid property data in device tree node\n"); 33688c2ecf20Sopenharmony_ci err = -EINVAL; 33698c2ecf20Sopenharmony_ci goto err_out; 33708c2ecf20Sopenharmony_ci } 33718c2ecf20Sopenharmony_ci 33728c2ecf20Sopenharmony_ci if (of_device_is_compatible(np, "fsl,sec3.0")) 33738c2ecf20Sopenharmony_ci priv->features |= TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT; 33748c2ecf20Sopenharmony_ci 33758c2ecf20Sopenharmony_ci if (of_device_is_compatible(np, "fsl,sec2.1")) 33768c2ecf20Sopenharmony_ci priv->features |= TALITOS_FTR_HW_AUTH_CHECK | 33778c2ecf20Sopenharmony_ci TALITOS_FTR_SHA224_HWINIT | 33788c2ecf20Sopenharmony_ci TALITOS_FTR_HMAC_OK; 33798c2ecf20Sopenharmony_ci 33808c2ecf20Sopenharmony_ci if (of_device_is_compatible(np, "fsl,sec1.0")) 33818c2ecf20Sopenharmony_ci priv->features |= TALITOS_FTR_SEC1; 33828c2ecf20Sopenharmony_ci 33838c2ecf20Sopenharmony_ci if (of_device_is_compatible(np, "fsl,sec1.2")) { 33848c2ecf20Sopenharmony_ci priv->reg_deu = priv->reg + TALITOS12_DEU; 33858c2ecf20Sopenharmony_ci priv->reg_aesu = priv->reg + TALITOS12_AESU; 33868c2ecf20Sopenharmony_ci priv->reg_mdeu = priv->reg + TALITOS12_MDEU; 33878c2ecf20Sopenharmony_ci stride = TALITOS1_CH_STRIDE; 33888c2ecf20Sopenharmony_ci } else if (of_device_is_compatible(np, "fsl,sec1.0")) { 33898c2ecf20Sopenharmony_ci priv->reg_deu = priv->reg + TALITOS10_DEU; 33908c2ecf20Sopenharmony_ci priv->reg_aesu = priv->reg + TALITOS10_AESU; 33918c2ecf20Sopenharmony_ci priv->reg_mdeu = priv->reg + TALITOS10_MDEU; 33928c2ecf20Sopenharmony_ci priv->reg_afeu = priv->reg + TALITOS10_AFEU; 33938c2ecf20Sopenharmony_ci priv->reg_rngu = priv->reg + TALITOS10_RNGU; 33948c2ecf20Sopenharmony_ci priv->reg_pkeu = priv->reg + TALITOS10_PKEU; 33958c2ecf20Sopenharmony_ci stride = TALITOS1_CH_STRIDE; 33968c2ecf20Sopenharmony_ci } else { 33978c2ecf20Sopenharmony_ci priv->reg_deu = priv->reg + TALITOS2_DEU; 33988c2ecf20Sopenharmony_ci priv->reg_aesu = priv->reg + TALITOS2_AESU; 33998c2ecf20Sopenharmony_ci priv->reg_mdeu = priv->reg + TALITOS2_MDEU; 34008c2ecf20Sopenharmony_ci priv->reg_afeu = priv->reg + TALITOS2_AFEU; 34018c2ecf20Sopenharmony_ci priv->reg_rngu = priv->reg + TALITOS2_RNGU; 34028c2ecf20Sopenharmony_ci priv->reg_pkeu = priv->reg + TALITOS2_PKEU; 34038c2ecf20Sopenharmony_ci priv->reg_keu = priv->reg + TALITOS2_KEU; 34048c2ecf20Sopenharmony_ci priv->reg_crcu = priv->reg + TALITOS2_CRCU; 34058c2ecf20Sopenharmony_ci stride = TALITOS2_CH_STRIDE; 34068c2ecf20Sopenharmony_ci } 34078c2ecf20Sopenharmony_ci 34088c2ecf20Sopenharmony_ci err = talitos_probe_irq(ofdev); 34098c2ecf20Sopenharmony_ci if (err) 34108c2ecf20Sopenharmony_ci goto err_out; 34118c2ecf20Sopenharmony_ci 34128c2ecf20Sopenharmony_ci if (has_ftr_sec1(priv)) { 34138c2ecf20Sopenharmony_ci if (priv->num_channels == 1) 34148c2ecf20Sopenharmony_ci tasklet_init(&priv->done_task[0], talitos1_done_ch0, 34158c2ecf20Sopenharmony_ci (unsigned long)dev); 34168c2ecf20Sopenharmony_ci else 34178c2ecf20Sopenharmony_ci tasklet_init(&priv->done_task[0], talitos1_done_4ch, 34188c2ecf20Sopenharmony_ci (unsigned long)dev); 34198c2ecf20Sopenharmony_ci } else { 34208c2ecf20Sopenharmony_ci if (priv->irq[1]) { 34218c2ecf20Sopenharmony_ci tasklet_init(&priv->done_task[0], talitos2_done_ch0_2, 34228c2ecf20Sopenharmony_ci (unsigned long)dev); 34238c2ecf20Sopenharmony_ci tasklet_init(&priv->done_task[1], talitos2_done_ch1_3, 34248c2ecf20Sopenharmony_ci (unsigned long)dev); 34258c2ecf20Sopenharmony_ci } else if (priv->num_channels == 1) { 34268c2ecf20Sopenharmony_ci tasklet_init(&priv->done_task[0], talitos2_done_ch0, 34278c2ecf20Sopenharmony_ci (unsigned long)dev); 34288c2ecf20Sopenharmony_ci } else { 34298c2ecf20Sopenharmony_ci tasklet_init(&priv->done_task[0], talitos2_done_4ch, 34308c2ecf20Sopenharmony_ci (unsigned long)dev); 34318c2ecf20Sopenharmony_ci } 34328c2ecf20Sopenharmony_ci } 34338c2ecf20Sopenharmony_ci 34348c2ecf20Sopenharmony_ci priv->chan = devm_kcalloc(dev, 34358c2ecf20Sopenharmony_ci priv->num_channels, 34368c2ecf20Sopenharmony_ci sizeof(struct talitos_channel), 34378c2ecf20Sopenharmony_ci GFP_KERNEL); 34388c2ecf20Sopenharmony_ci if (!priv->chan) { 34398c2ecf20Sopenharmony_ci dev_err(dev, "failed to allocate channel management space\n"); 34408c2ecf20Sopenharmony_ci err = -ENOMEM; 34418c2ecf20Sopenharmony_ci goto err_out; 34428c2ecf20Sopenharmony_ci } 34438c2ecf20Sopenharmony_ci 34448c2ecf20Sopenharmony_ci priv->fifo_len = roundup_pow_of_two(priv->chfifo_len); 34458c2ecf20Sopenharmony_ci 34468c2ecf20Sopenharmony_ci for (i = 0; i < priv->num_channels; i++) { 34478c2ecf20Sopenharmony_ci priv->chan[i].reg = priv->reg + stride * (i + 1); 34488c2ecf20Sopenharmony_ci if (!priv->irq[1] || !(i & 1)) 34498c2ecf20Sopenharmony_ci priv->chan[i].reg += TALITOS_CH_BASE_OFFSET; 34508c2ecf20Sopenharmony_ci 34518c2ecf20Sopenharmony_ci spin_lock_init(&priv->chan[i].head_lock); 34528c2ecf20Sopenharmony_ci spin_lock_init(&priv->chan[i].tail_lock); 34538c2ecf20Sopenharmony_ci 34548c2ecf20Sopenharmony_ci priv->chan[i].fifo = devm_kcalloc(dev, 34558c2ecf20Sopenharmony_ci priv->fifo_len, 34568c2ecf20Sopenharmony_ci sizeof(struct talitos_request), 34578c2ecf20Sopenharmony_ci GFP_KERNEL); 34588c2ecf20Sopenharmony_ci if (!priv->chan[i].fifo) { 34598c2ecf20Sopenharmony_ci dev_err(dev, "failed to allocate request fifo %d\n", i); 34608c2ecf20Sopenharmony_ci err = -ENOMEM; 34618c2ecf20Sopenharmony_ci goto err_out; 34628c2ecf20Sopenharmony_ci } 34638c2ecf20Sopenharmony_ci 34648c2ecf20Sopenharmony_ci atomic_set(&priv->chan[i].submit_count, 34658c2ecf20Sopenharmony_ci -(priv->chfifo_len - 1)); 34668c2ecf20Sopenharmony_ci } 34678c2ecf20Sopenharmony_ci 34688c2ecf20Sopenharmony_ci dma_set_mask(dev, DMA_BIT_MASK(36)); 34698c2ecf20Sopenharmony_ci 34708c2ecf20Sopenharmony_ci /* reset and initialize the h/w */ 34718c2ecf20Sopenharmony_ci err = init_device(dev); 34728c2ecf20Sopenharmony_ci if (err) { 34738c2ecf20Sopenharmony_ci dev_err(dev, "failed to initialize device\n"); 34748c2ecf20Sopenharmony_ci goto err_out; 34758c2ecf20Sopenharmony_ci } 34768c2ecf20Sopenharmony_ci 34778c2ecf20Sopenharmony_ci /* register the RNG, if available */ 34788c2ecf20Sopenharmony_ci if (hw_supports(dev, DESC_HDR_SEL0_RNG)) { 34798c2ecf20Sopenharmony_ci err = talitos_register_rng(dev); 34808c2ecf20Sopenharmony_ci if (err) { 34818c2ecf20Sopenharmony_ci dev_err(dev, "failed to register hwrng: %d\n", err); 34828c2ecf20Sopenharmony_ci goto err_out; 34838c2ecf20Sopenharmony_ci } else 34848c2ecf20Sopenharmony_ci dev_info(dev, "hwrng\n"); 34858c2ecf20Sopenharmony_ci } 34868c2ecf20Sopenharmony_ci 34878c2ecf20Sopenharmony_ci /* register crypto algorithms the device supports */ 34888c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(driver_algs); i++) { 34898c2ecf20Sopenharmony_ci if (hw_supports(dev, driver_algs[i].desc_hdr_template)) { 34908c2ecf20Sopenharmony_ci struct talitos_crypto_alg *t_alg; 34918c2ecf20Sopenharmony_ci struct crypto_alg *alg = NULL; 34928c2ecf20Sopenharmony_ci 34938c2ecf20Sopenharmony_ci t_alg = talitos_alg_alloc(dev, &driver_algs[i]); 34948c2ecf20Sopenharmony_ci if (IS_ERR(t_alg)) { 34958c2ecf20Sopenharmony_ci err = PTR_ERR(t_alg); 34968c2ecf20Sopenharmony_ci if (err == -ENOTSUPP) 34978c2ecf20Sopenharmony_ci continue; 34988c2ecf20Sopenharmony_ci goto err_out; 34998c2ecf20Sopenharmony_ci } 35008c2ecf20Sopenharmony_ci 35018c2ecf20Sopenharmony_ci switch (t_alg->algt.type) { 35028c2ecf20Sopenharmony_ci case CRYPTO_ALG_TYPE_SKCIPHER: 35038c2ecf20Sopenharmony_ci err = crypto_register_skcipher( 35048c2ecf20Sopenharmony_ci &t_alg->algt.alg.skcipher); 35058c2ecf20Sopenharmony_ci alg = &t_alg->algt.alg.skcipher.base; 35068c2ecf20Sopenharmony_ci break; 35078c2ecf20Sopenharmony_ci 35088c2ecf20Sopenharmony_ci case CRYPTO_ALG_TYPE_AEAD: 35098c2ecf20Sopenharmony_ci err = crypto_register_aead( 35108c2ecf20Sopenharmony_ci &t_alg->algt.alg.aead); 35118c2ecf20Sopenharmony_ci alg = &t_alg->algt.alg.aead.base; 35128c2ecf20Sopenharmony_ci break; 35138c2ecf20Sopenharmony_ci 35148c2ecf20Sopenharmony_ci case CRYPTO_ALG_TYPE_AHASH: 35158c2ecf20Sopenharmony_ci err = crypto_register_ahash( 35168c2ecf20Sopenharmony_ci &t_alg->algt.alg.hash); 35178c2ecf20Sopenharmony_ci alg = &t_alg->algt.alg.hash.halg.base; 35188c2ecf20Sopenharmony_ci break; 35198c2ecf20Sopenharmony_ci } 35208c2ecf20Sopenharmony_ci if (err) { 35218c2ecf20Sopenharmony_ci dev_err(dev, "%s alg registration failed\n", 35228c2ecf20Sopenharmony_ci alg->cra_driver_name); 35238c2ecf20Sopenharmony_ci devm_kfree(dev, t_alg); 35248c2ecf20Sopenharmony_ci } else 35258c2ecf20Sopenharmony_ci list_add_tail(&t_alg->entry, &priv->alg_list); 35268c2ecf20Sopenharmony_ci } 35278c2ecf20Sopenharmony_ci } 35288c2ecf20Sopenharmony_ci if (!list_empty(&priv->alg_list)) 35298c2ecf20Sopenharmony_ci dev_info(dev, "%s algorithms registered in /proc/crypto\n", 35308c2ecf20Sopenharmony_ci (char *)of_get_property(np, "compatible", NULL)); 35318c2ecf20Sopenharmony_ci 35328c2ecf20Sopenharmony_ci return 0; 35338c2ecf20Sopenharmony_ci 35348c2ecf20Sopenharmony_cierr_out: 35358c2ecf20Sopenharmony_ci talitos_remove(ofdev); 35368c2ecf20Sopenharmony_ci 35378c2ecf20Sopenharmony_ci return err; 35388c2ecf20Sopenharmony_ci} 35398c2ecf20Sopenharmony_ci 35408c2ecf20Sopenharmony_cistatic const struct of_device_id talitos_match[] = { 35418c2ecf20Sopenharmony_ci#ifdef CONFIG_CRYPTO_DEV_TALITOS1 35428c2ecf20Sopenharmony_ci { 35438c2ecf20Sopenharmony_ci .compatible = "fsl,sec1.0", 35448c2ecf20Sopenharmony_ci }, 35458c2ecf20Sopenharmony_ci#endif 35468c2ecf20Sopenharmony_ci#ifdef CONFIG_CRYPTO_DEV_TALITOS2 35478c2ecf20Sopenharmony_ci { 35488c2ecf20Sopenharmony_ci .compatible = "fsl,sec2.0", 35498c2ecf20Sopenharmony_ci }, 35508c2ecf20Sopenharmony_ci#endif 35518c2ecf20Sopenharmony_ci {}, 35528c2ecf20Sopenharmony_ci}; 35538c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, talitos_match); 35548c2ecf20Sopenharmony_ci 35558c2ecf20Sopenharmony_cistatic struct platform_driver talitos_driver = { 35568c2ecf20Sopenharmony_ci .driver = { 35578c2ecf20Sopenharmony_ci .name = "talitos", 35588c2ecf20Sopenharmony_ci .of_match_table = talitos_match, 35598c2ecf20Sopenharmony_ci }, 35608c2ecf20Sopenharmony_ci .probe = talitos_probe, 35618c2ecf20Sopenharmony_ci .remove = talitos_remove, 35628c2ecf20Sopenharmony_ci}; 35638c2ecf20Sopenharmony_ci 35648c2ecf20Sopenharmony_cimodule_platform_driver(talitos_driver); 35658c2ecf20Sopenharmony_ci 35668c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 35678c2ecf20Sopenharmony_ciMODULE_AUTHOR("Kim Phillips <kim.phillips@freescale.com>"); 35688c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Freescale integrated security engine (SEC) driver"); 3569