11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 29c4a7965SKim Phillips /* 39c4a7965SKim Phillips * talitos - Freescale Integrated Security Engine (SEC) device driver 49c4a7965SKim Phillips * 55228f0f7SKim Phillips * Copyright (c) 2008-2011 Freescale Semiconductor, Inc. 69c4a7965SKim Phillips * 79c4a7965SKim Phillips * Scatterlist Crypto API glue code copied from files with the following: 89c4a7965SKim Phillips * Copyright (c) 2006-2007 Herbert Xu <herbert@gondor.apana.org.au> 99c4a7965SKim Phillips * 109c4a7965SKim Phillips * Crypto algorithm registration code copied from hifn driver: 119c4a7965SKim Phillips * 2007+ Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru> 129c4a7965SKim Phillips * All rights reserved. 139c4a7965SKim Phillips */ 149c4a7965SKim Phillips 159c4a7965SKim Phillips #include <linux/kernel.h> 169c4a7965SKim Phillips #include <linux/module.h> 179c4a7965SKim Phillips #include <linux/mod_devicetable.h> 189c4a7965SKim Phillips #include <linux/device.h> 199c4a7965SKim Phillips #include <linux/interrupt.h> 209c4a7965SKim Phillips #include <linux/crypto.h> 219c4a7965SKim Phillips #include <linux/hw_random.h> 225af50730SRob Herring #include <linux/of_address.h> 235af50730SRob Herring #include <linux/of_irq.h> 249c4a7965SKim Phillips #include <linux/of_platform.h> 259c4a7965SKim Phillips #include <linux/dma-mapping.h> 269c4a7965SKim Phillips #include <linux/io.h> 279c4a7965SKim Phillips #include <linux/spinlock.h> 289c4a7965SKim Phillips #include <linux/rtnetlink.h> 295a0e3ad6STejun Heo #include <linux/slab.h> 309c4a7965SKim Phillips 319c4a7965SKim Phillips #include <crypto/algapi.h> 329c4a7965SKim Phillips #include <crypto/aes.h> 339d574ae8SArd Biesheuvel #include <crypto/internal/des.h> 34a24d22b2SEric Biggers #include <crypto/sha1.h> 35a24d22b2SEric Biggers #include <crypto/sha2.h> 36497f2e6bSLee Nipper #include <crypto/md5.h> 37e98014abSHerbert Xu #include <crypto/internal/aead.h> 389c4a7965SKim Phillips #include <crypto/authenc.h> 39373960d7SArd Biesheuvel #include <crypto/internal/skcipher.h> 40acbf7c62SLee Nipper #include <crypto/hash.h> 41acbf7c62SLee Nipper #include <crypto/internal/hash.h> 424de9d0b5SLee Nipper #include <crypto/scatterwalk.h> 439c4a7965SKim Phillips 449c4a7965SKim Phillips #include "talitos.h" 459c4a7965SKim Phillips 46922f9dc8SLEROY Christophe static void to_talitos_ptr(struct talitos_ptr *ptr, dma_addr_t dma_addr, 47da9de146SLEROY Christophe unsigned int len, bool is_sec1) 4881eb024cSKim Phillips { 49edc6bd69SLEROY Christophe ptr->ptr = cpu_to_be32(lower_32_bits(dma_addr)); 50da9de146SLEROY Christophe if (is_sec1) { 51da9de146SLEROY Christophe ptr->len1 = cpu_to_be16(len); 52da9de146SLEROY Christophe } else { 53da9de146SLEROY Christophe ptr->len = cpu_to_be16(len); 54edc6bd69SLEROY Christophe ptr->eptr = upper_32_bits(dma_addr); 5581eb024cSKim Phillips } 56da9de146SLEROY Christophe } 5781eb024cSKim Phillips 58340ff60aSHoria Geant? static void copy_talitos_ptr(struct talitos_ptr *dst_ptr, 59340ff60aSHoria Geant? struct talitos_ptr *src_ptr, bool is_sec1) 60340ff60aSHoria Geant? { 61340ff60aSHoria Geant? dst_ptr->ptr = src_ptr->ptr; 62922f9dc8SLEROY Christophe if (is_sec1) { 63da9de146SLEROY Christophe dst_ptr->len1 = src_ptr->len1; 64922f9dc8SLEROY Christophe } else { 65da9de146SLEROY Christophe dst_ptr->len = src_ptr->len; 66da9de146SLEROY Christophe dst_ptr->eptr = src_ptr->eptr; 67538caf83SLEROY Christophe } 68922f9dc8SLEROY Christophe } 69538caf83SLEROY Christophe 70922f9dc8SLEROY Christophe static unsigned short from_talitos_ptr_len(struct talitos_ptr *ptr, 71922f9dc8SLEROY Christophe bool is_sec1) 72538caf83SLEROY Christophe { 73922f9dc8SLEROY Christophe if (is_sec1) 74922f9dc8SLEROY Christophe return be16_to_cpu(ptr->len1); 75922f9dc8SLEROY Christophe else 76538caf83SLEROY Christophe return be16_to_cpu(ptr->len); 77538caf83SLEROY Christophe } 78538caf83SLEROY Christophe 79b096b544SLEROY Christophe static void to_talitos_ptr_ext_set(struct talitos_ptr *ptr, u8 val, 80b096b544SLEROY Christophe bool is_sec1) 81185eb79fSLEROY Christophe { 82922f9dc8SLEROY Christophe if (!is_sec1) 83b096b544SLEROY Christophe ptr->j_extent = val; 84b096b544SLEROY Christophe } 85b096b544SLEROY Christophe 86b096b544SLEROY Christophe static void to_talitos_ptr_ext_or(struct talitos_ptr *ptr, u8 val, bool is_sec1) 87b096b544SLEROY Christophe { 88b096b544SLEROY Christophe if (!is_sec1) 89b096b544SLEROY Christophe ptr->j_extent |= val; 90185eb79fSLEROY Christophe } 91185eb79fSLEROY Christophe 929c4a7965SKim Phillips /* 939c4a7965SKim Phillips * map virtual single (contiguous) pointer to h/w descriptor pointer 949c4a7965SKim Phillips */ 956a4967c3SLEROY Christophe static void __map_single_talitos_ptr(struct device *dev, 966a4967c3SLEROY Christophe struct talitos_ptr *ptr, 976a4967c3SLEROY Christophe unsigned int len, void *data, 986a4967c3SLEROY Christophe enum dma_data_direction dir, 996a4967c3SLEROY Christophe unsigned long attrs) 1006a4967c3SLEROY Christophe { 1016a4967c3SLEROY Christophe dma_addr_t dma_addr = dma_map_single_attrs(dev, data, len, dir, attrs); 1026a4967c3SLEROY Christophe struct talitos_private *priv = dev_get_drvdata(dev); 1036a4967c3SLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 1046a4967c3SLEROY Christophe 1056a4967c3SLEROY Christophe to_talitos_ptr(ptr, dma_addr, len, is_sec1); 1066a4967c3SLEROY Christophe } 1076a4967c3SLEROY Christophe 1089c4a7965SKim Phillips static void map_single_talitos_ptr(struct device *dev, 109edc6bd69SLEROY Christophe struct talitos_ptr *ptr, 11042e8b0d7SHoria Geant? unsigned int len, void *data, 1119c4a7965SKim Phillips enum dma_data_direction dir) 1129c4a7965SKim Phillips { 1136a4967c3SLEROY Christophe __map_single_talitos_ptr(dev, ptr, len, data, dir, 0); 1146a4967c3SLEROY Christophe } 11581eb024cSKim Phillips 1166a4967c3SLEROY Christophe static void map_single_talitos_ptr_nosync(struct device *dev, 1176a4967c3SLEROY Christophe struct talitos_ptr *ptr, 1186a4967c3SLEROY Christophe unsigned int len, void *data, 1196a4967c3SLEROY Christophe enum dma_data_direction dir) 1206a4967c3SLEROY Christophe { 1216a4967c3SLEROY Christophe __map_single_talitos_ptr(dev, ptr, len, data, dir, 1226a4967c3SLEROY Christophe DMA_ATTR_SKIP_CPU_SYNC); 1239c4a7965SKim Phillips } 1249c4a7965SKim Phillips 1259c4a7965SKim Phillips /* 1269c4a7965SKim Phillips * unmap bus single (contiguous) h/w descriptor pointer 1279c4a7965SKim Phillips */ 1289c4a7965SKim Phillips static void unmap_single_talitos_ptr(struct device *dev, 129edc6bd69SLEROY Christophe struct talitos_ptr *ptr, 1309c4a7965SKim Phillips enum dma_data_direction dir) 1319c4a7965SKim Phillips { 132922f9dc8SLEROY Christophe struct talitos_private *priv = dev_get_drvdata(dev); 133922f9dc8SLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 134922f9dc8SLEROY Christophe 135edc6bd69SLEROY Christophe dma_unmap_single(dev, be32_to_cpu(ptr->ptr), 136922f9dc8SLEROY Christophe from_talitos_ptr_len(ptr, is_sec1), dir); 1379c4a7965SKim Phillips } 1389c4a7965SKim Phillips 1399c4a7965SKim Phillips static int reset_channel(struct device *dev, int ch) 1409c4a7965SKim Phillips { 1419c4a7965SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); 1429c4a7965SKim Phillips unsigned int timeout = TALITOS_TIMEOUT; 143dd3c0987SLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 1449c4a7965SKim Phillips 145dd3c0987SLEROY Christophe if (is_sec1) { 146dd3c0987SLEROY Christophe setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, 147dd3c0987SLEROY Christophe TALITOS1_CCCR_LO_RESET); 1489c4a7965SKim Phillips 149dd3c0987SLEROY Christophe while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR_LO) & 150dd3c0987SLEROY Christophe TALITOS1_CCCR_LO_RESET) && --timeout) 1519c4a7965SKim Phillips cpu_relax(); 152dd3c0987SLEROY Christophe } else { 153dd3c0987SLEROY Christophe setbits32(priv->chan[ch].reg + TALITOS_CCCR, 154dd3c0987SLEROY Christophe TALITOS2_CCCR_RESET); 155dd3c0987SLEROY Christophe 156dd3c0987SLEROY Christophe while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) & 157dd3c0987SLEROY Christophe TALITOS2_CCCR_RESET) && --timeout) 158dd3c0987SLEROY Christophe cpu_relax(); 159dd3c0987SLEROY Christophe } 1609c4a7965SKim Phillips 1619c4a7965SKim Phillips if (timeout == 0) { 1629c4a7965SKim Phillips dev_err(dev, "failed to reset channel %d\n", ch); 1639c4a7965SKim Phillips return -EIO; 1649c4a7965SKim Phillips } 1659c4a7965SKim Phillips 16681eb024cSKim Phillips /* set 36-bit addressing, done writeback enable and done IRQ enable */ 167ad42d5fcSKim Phillips setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, TALITOS_CCCR_LO_EAE | 16881eb024cSKim Phillips TALITOS_CCCR_LO_CDWE | TALITOS_CCCR_LO_CDIE); 16937b5e889SLEROY Christophe /* enable chaining descriptors */ 17037b5e889SLEROY Christophe if (is_sec1) 17137b5e889SLEROY Christophe setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, 17237b5e889SLEROY Christophe TALITOS_CCCR_LO_NE); 1739c4a7965SKim Phillips 174fe5720e2SKim Phillips /* and ICCR writeback, if available */ 175fe5720e2SKim Phillips if (priv->features & TALITOS_FTR_HW_AUTH_CHECK) 176ad42d5fcSKim Phillips setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, 177fe5720e2SKim Phillips TALITOS_CCCR_LO_IWSE); 178fe5720e2SKim Phillips 1799c4a7965SKim Phillips return 0; 1809c4a7965SKim Phillips } 1819c4a7965SKim Phillips 1829c4a7965SKim Phillips static int reset_device(struct device *dev) 1839c4a7965SKim Phillips { 1849c4a7965SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); 1859c4a7965SKim Phillips unsigned int timeout = TALITOS_TIMEOUT; 186dd3c0987SLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 187dd3c0987SLEROY Christophe u32 mcr = is_sec1 ? TALITOS1_MCR_SWR : TALITOS2_MCR_SWR; 1889c4a7965SKim Phillips 189c3e337f8SKim Phillips setbits32(priv->reg + TALITOS_MCR, mcr); 1909c4a7965SKim Phillips 191dd3c0987SLEROY Christophe while ((in_be32(priv->reg + TALITOS_MCR) & mcr) 1929c4a7965SKim Phillips && --timeout) 1939c4a7965SKim Phillips cpu_relax(); 1949c4a7965SKim Phillips 1952cdba3cfSKim Phillips if (priv->irq[1]) { 196c3e337f8SKim Phillips mcr = TALITOS_MCR_RCA1 | TALITOS_MCR_RCA3; 197c3e337f8SKim Phillips setbits32(priv->reg + TALITOS_MCR, mcr); 198c3e337f8SKim Phillips } 199c3e337f8SKim Phillips 2009c4a7965SKim Phillips if (timeout == 0) { 2019c4a7965SKim Phillips dev_err(dev, "failed to reset device\n"); 2029c4a7965SKim Phillips return -EIO; 2039c4a7965SKim Phillips } 2049c4a7965SKim Phillips 2059c4a7965SKim Phillips return 0; 2069c4a7965SKim Phillips } 2079c4a7965SKim Phillips 2089c4a7965SKim Phillips /* 2099c4a7965SKim Phillips * Reset and initialize the device 2109c4a7965SKim Phillips */ 2119c4a7965SKim Phillips static int init_device(struct device *dev) 2129c4a7965SKim Phillips { 2139c4a7965SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); 2149c4a7965SKim Phillips int ch, err; 215dd3c0987SLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 2169c4a7965SKim Phillips 2179c4a7965SKim Phillips /* 2189c4a7965SKim Phillips * Master reset 2199c4a7965SKim Phillips * errata documentation: warning: certain SEC interrupts 2209c4a7965SKim Phillips * are not fully cleared by writing the MCR:SWR bit, 2219c4a7965SKim Phillips * set bit twice to completely reset 2229c4a7965SKim Phillips */ 2239c4a7965SKim Phillips err = reset_device(dev); 2249c4a7965SKim Phillips if (err) 2259c4a7965SKim Phillips return err; 2269c4a7965SKim Phillips 2279c4a7965SKim Phillips err = reset_device(dev); 2289c4a7965SKim Phillips if (err) 2299c4a7965SKim Phillips return err; 2309c4a7965SKim Phillips 2319c4a7965SKim Phillips /* reset channels */ 2329c4a7965SKim Phillips for (ch = 0; ch < priv->num_channels; ch++) { 2339c4a7965SKim Phillips err = reset_channel(dev, ch); 2349c4a7965SKim Phillips if (err) 2359c4a7965SKim Phillips return err; 2369c4a7965SKim Phillips } 2379c4a7965SKim Phillips 2389c4a7965SKim Phillips /* enable channel done and error interrupts */ 239dd3c0987SLEROY Christophe if (is_sec1) { 240dd3c0987SLEROY Christophe clrbits32(priv->reg + TALITOS_IMR, TALITOS1_IMR_INIT); 241dd3c0987SLEROY Christophe clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT); 242dd3c0987SLEROY Christophe /* disable parity error check in DEU (erroneous? test vect.) */ 243dd3c0987SLEROY Christophe setbits32(priv->reg_deu + TALITOS_EUICR, TALITOS1_DEUICR_KPE); 244dd3c0987SLEROY Christophe } else { 245dd3c0987SLEROY Christophe setbits32(priv->reg + TALITOS_IMR, TALITOS2_IMR_INIT); 246dd3c0987SLEROY Christophe setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT); 247dd3c0987SLEROY Christophe } 2489c4a7965SKim Phillips 249fe5720e2SKim Phillips /* disable integrity check error interrupts (use writeback instead) */ 250fe5720e2SKim Phillips if (priv->features & TALITOS_FTR_HW_AUTH_CHECK) 2515fa7fa14SLEROY Christophe setbits32(priv->reg_mdeu + TALITOS_EUICR_LO, 252fe5720e2SKim Phillips TALITOS_MDEUICR_LO_ICE); 253fe5720e2SKim Phillips 2549c4a7965SKim Phillips return 0; 2559c4a7965SKim Phillips } 2569c4a7965SKim Phillips 2579c4a7965SKim Phillips /** 2589c4a7965SKim Phillips * talitos_submit - submits a descriptor to the device for processing 2599c4a7965SKim Phillips * @dev: the SEC device to be used 2605228f0f7SKim Phillips * @ch: the SEC device channel to be used 2619c4a7965SKim Phillips * @desc: the descriptor to be processed by the device 2629c4a7965SKim Phillips * @callback: whom to call when processing is complete 2639c4a7965SKim Phillips * @context: a handle for use by caller (optional) 2649c4a7965SKim Phillips * 2659c4a7965SKim Phillips * desc must contain valid dma-mapped (bus physical) address pointers. 2669c4a7965SKim Phillips * callback must check err and feedback in descriptor header 2679c4a7965SKim Phillips * for device processing status. 2689c4a7965SKim Phillips */ 269fbb8d46eSChristophe Leroy static int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc, 2709c4a7965SKim Phillips void (*callback)(struct device *dev, 2719c4a7965SKim Phillips struct talitos_desc *desc, 2729c4a7965SKim Phillips void *context, int error), 2739c4a7965SKim Phillips void *context) 2749c4a7965SKim Phillips { 2759c4a7965SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); 2769c4a7965SKim Phillips struct talitos_request *request; 2775228f0f7SKim Phillips unsigned long flags; 2789c4a7965SKim Phillips int head; 2797d607c6aSLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 2809c4a7965SKim Phillips 2814b992628SKim Phillips spin_lock_irqsave(&priv->chan[ch].head_lock, flags); 2829c4a7965SKim Phillips 2834b992628SKim Phillips if (!atomic_inc_not_zero(&priv->chan[ch].submit_count)) { 284ec6644d6SKim Phillips /* h/w fifo is full */ 2854b992628SKim Phillips spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags); 2869c4a7965SKim Phillips return -EAGAIN; 2879c4a7965SKim Phillips } 2889c4a7965SKim Phillips 2894b992628SKim Phillips head = priv->chan[ch].head; 2904b992628SKim Phillips request = &priv->chan[ch].fifo[head]; 291ec6644d6SKim Phillips 2929c4a7965SKim Phillips /* map descriptor and save caller data */ 2937d607c6aSLEROY Christophe if (is_sec1) { 2947d607c6aSLEROY Christophe desc->hdr1 = desc->hdr; 2957d607c6aSLEROY Christophe request->dma_desc = dma_map_single(dev, &desc->hdr1, 2967d607c6aSLEROY Christophe TALITOS_DESC_SIZE, 2979c4a7965SKim Phillips DMA_BIDIRECTIONAL); 2987d607c6aSLEROY Christophe } else { 2997d607c6aSLEROY Christophe request->dma_desc = dma_map_single(dev, desc, 3007d607c6aSLEROY Christophe TALITOS_DESC_SIZE, 3017d607c6aSLEROY Christophe DMA_BIDIRECTIONAL); 3027d607c6aSLEROY Christophe } 3039c4a7965SKim Phillips request->callback = callback; 3049c4a7965SKim Phillips request->context = context; 3059c4a7965SKim Phillips 3069c4a7965SKim Phillips /* increment fifo head */ 3074b992628SKim Phillips priv->chan[ch].head = (priv->chan[ch].head + 1) & (priv->fifo_len - 1); 3089c4a7965SKim Phillips 3099c4a7965SKim Phillips smp_wmb(); 3109c4a7965SKim Phillips request->desc = desc; 3119c4a7965SKim Phillips 3129c4a7965SKim Phillips /* GO! */ 3139c4a7965SKim Phillips wmb(); 314ad42d5fcSKim Phillips out_be32(priv->chan[ch].reg + TALITOS_FF, 315ad42d5fcSKim Phillips upper_32_bits(request->dma_desc)); 316ad42d5fcSKim Phillips out_be32(priv->chan[ch].reg + TALITOS_FF_LO, 317a752447aSKim Phillips lower_32_bits(request->dma_desc)); 3189c4a7965SKim Phillips 3194b992628SKim Phillips spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags); 3209c4a7965SKim Phillips 3219c4a7965SKim Phillips return -EINPROGRESS; 3229c4a7965SKim Phillips } 3239c4a7965SKim Phillips 32458cdbc6dSChristophe Leroy static __be32 get_request_hdr(struct talitos_request *request, bool is_sec1) 32558cdbc6dSChristophe Leroy { 32658cdbc6dSChristophe Leroy struct talitos_edesc *edesc; 32758cdbc6dSChristophe Leroy 32858cdbc6dSChristophe Leroy if (!is_sec1) 32958cdbc6dSChristophe Leroy return request->desc->hdr; 33058cdbc6dSChristophe Leroy 33158cdbc6dSChristophe Leroy if (!request->desc->next_desc) 33258cdbc6dSChristophe Leroy return request->desc->hdr1; 33358cdbc6dSChristophe Leroy 33458cdbc6dSChristophe Leroy edesc = container_of(request->desc, struct talitos_edesc, desc); 33558cdbc6dSChristophe Leroy 33658cdbc6dSChristophe Leroy return ((struct talitos_desc *)(edesc->buf + edesc->dma_len))->hdr1; 33758cdbc6dSChristophe Leroy } 3389c4a7965SKim Phillips 3399c4a7965SKim Phillips /* 3409c4a7965SKim Phillips * process what was done, notify callback of error if not 3419c4a7965SKim Phillips */ 3429c4a7965SKim Phillips static void flush_channel(struct device *dev, int ch, int error, int reset_ch) 3439c4a7965SKim Phillips { 3449c4a7965SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); 3459c4a7965SKim Phillips struct talitos_request *request, saved_req; 3469c4a7965SKim Phillips unsigned long flags; 3479c4a7965SKim Phillips int tail, status; 3487d607c6aSLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 3499c4a7965SKim Phillips 3504b992628SKim Phillips spin_lock_irqsave(&priv->chan[ch].tail_lock, flags); 3519c4a7965SKim Phillips 3524b992628SKim Phillips tail = priv->chan[ch].tail; 3534b992628SKim Phillips while (priv->chan[ch].fifo[tail].desc) { 3547d607c6aSLEROY Christophe __be32 hdr; 3557d607c6aSLEROY Christophe 3564b992628SKim Phillips request = &priv->chan[ch].fifo[tail]; 3579c4a7965SKim Phillips 3589c4a7965SKim Phillips /* descriptors with their done bits set don't get the error */ 3599c4a7965SKim Phillips rmb(); 36058cdbc6dSChristophe Leroy hdr = get_request_hdr(request, is_sec1); 3617d607c6aSLEROY Christophe 3627d607c6aSLEROY Christophe if ((hdr & DESC_HDR_DONE) == DESC_HDR_DONE) 3639c4a7965SKim Phillips status = 0; 364ca38a814SLee Nipper else 3659c4a7965SKim Phillips if (!error) 3669c4a7965SKim Phillips break; 3679c4a7965SKim Phillips else 3689c4a7965SKim Phillips status = error; 3699c4a7965SKim Phillips 3709c4a7965SKim Phillips dma_unmap_single(dev, request->dma_desc, 3717d607c6aSLEROY Christophe TALITOS_DESC_SIZE, 372e938e465SKim Phillips DMA_BIDIRECTIONAL); 3739c4a7965SKim Phillips 3749c4a7965SKim Phillips /* copy entries so we can call callback outside lock */ 3759c4a7965SKim Phillips saved_req.desc = request->desc; 3769c4a7965SKim Phillips saved_req.callback = request->callback; 3779c4a7965SKim Phillips saved_req.context = request->context; 3789c4a7965SKim Phillips 3799c4a7965SKim Phillips /* release request entry in fifo */ 3809c4a7965SKim Phillips smp_wmb(); 3819c4a7965SKim Phillips request->desc = NULL; 3829c4a7965SKim Phillips 3839c4a7965SKim Phillips /* increment fifo tail */ 3844b992628SKim Phillips priv->chan[ch].tail = (tail + 1) & (priv->fifo_len - 1); 3859c4a7965SKim Phillips 3864b992628SKim Phillips spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags); 387ec6644d6SKim Phillips 3884b992628SKim Phillips atomic_dec(&priv->chan[ch].submit_count); 389ec6644d6SKim Phillips 3909c4a7965SKim Phillips saved_req.callback(dev, saved_req.desc, saved_req.context, 3919c4a7965SKim Phillips status); 3929c4a7965SKim Phillips /* channel may resume processing in single desc error case */ 3939c4a7965SKim Phillips if (error && !reset_ch && status == error) 3949c4a7965SKim Phillips return; 3954b992628SKim Phillips spin_lock_irqsave(&priv->chan[ch].tail_lock, flags); 3964b992628SKim Phillips tail = priv->chan[ch].tail; 3979c4a7965SKim Phillips } 3989c4a7965SKim Phillips 3994b992628SKim Phillips spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags); 4009c4a7965SKim Phillips } 4019c4a7965SKim Phillips 4029c4a7965SKim Phillips /* 4039c4a7965SKim Phillips * process completed requests for channels that have done status 4049c4a7965SKim Phillips */ 405dd3c0987SLEROY Christophe #define DEF_TALITOS1_DONE(name, ch_done_mask) \ 406dd3c0987SLEROY Christophe static void talitos1_done_##name(unsigned long data) \ 407dd3c0987SLEROY Christophe { \ 408dd3c0987SLEROY Christophe struct device *dev = (struct device *)data; \ 409dd3c0987SLEROY Christophe struct talitos_private *priv = dev_get_drvdata(dev); \ 410dd3c0987SLEROY Christophe unsigned long flags; \ 411dd3c0987SLEROY Christophe \ 412dd3c0987SLEROY Christophe if (ch_done_mask & 0x10000000) \ 413dd3c0987SLEROY Christophe flush_channel(dev, 0, 0, 0); \ 414dd3c0987SLEROY Christophe if (ch_done_mask & 0x40000000) \ 415dd3c0987SLEROY Christophe flush_channel(dev, 1, 0, 0); \ 416dd3c0987SLEROY Christophe if (ch_done_mask & 0x00010000) \ 417dd3c0987SLEROY Christophe flush_channel(dev, 2, 0, 0); \ 418dd3c0987SLEROY Christophe if (ch_done_mask & 0x00040000) \ 419dd3c0987SLEROY Christophe flush_channel(dev, 3, 0, 0); \ 420dd3c0987SLEROY Christophe \ 421dd3c0987SLEROY Christophe /* At this point, all completed channels have been processed */ \ 422dd3c0987SLEROY Christophe /* Unmask done interrupts for channels completed later on. */ \ 423dd3c0987SLEROY Christophe spin_lock_irqsave(&priv->reg_lock, flags); \ 424dd3c0987SLEROY Christophe clrbits32(priv->reg + TALITOS_IMR, ch_done_mask); \ 425dd3c0987SLEROY Christophe clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT); \ 426dd3c0987SLEROY Christophe spin_unlock_irqrestore(&priv->reg_lock, flags); \ 427dd3c0987SLEROY Christophe } 428dd3c0987SLEROY Christophe 429dd3c0987SLEROY Christophe DEF_TALITOS1_DONE(4ch, TALITOS1_ISR_4CHDONE) 4309c02e285SLEROY Christophe DEF_TALITOS1_DONE(ch0, TALITOS1_ISR_CH_0_DONE) 431dd3c0987SLEROY Christophe 432dd3c0987SLEROY Christophe #define DEF_TALITOS2_DONE(name, ch_done_mask) \ 433dd3c0987SLEROY Christophe static void talitos2_done_##name(unsigned long data) \ 434c3e337f8SKim Phillips { \ 435c3e337f8SKim Phillips struct device *dev = (struct device *)data; \ 436c3e337f8SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); \ 437511d63cbSHoria Geanta unsigned long flags; \ 438c3e337f8SKim Phillips \ 439c3e337f8SKim Phillips if (ch_done_mask & 1) \ 440c3e337f8SKim Phillips flush_channel(dev, 0, 0, 0); \ 441c3e337f8SKim Phillips if (ch_done_mask & (1 << 2)) \ 442c3e337f8SKim Phillips flush_channel(dev, 1, 0, 0); \ 443c3e337f8SKim Phillips if (ch_done_mask & (1 << 4)) \ 444c3e337f8SKim Phillips flush_channel(dev, 2, 0, 0); \ 445c3e337f8SKim Phillips if (ch_done_mask & (1 << 6)) \ 446c3e337f8SKim Phillips flush_channel(dev, 3, 0, 0); \ 447c3e337f8SKim Phillips \ 448c3e337f8SKim Phillips /* At this point, all completed channels have been processed */ \ 449c3e337f8SKim Phillips /* Unmask done interrupts for channels completed later on. */ \ 450511d63cbSHoria Geanta spin_lock_irqsave(&priv->reg_lock, flags); \ 451c3e337f8SKim Phillips setbits32(priv->reg + TALITOS_IMR, ch_done_mask); \ 452dd3c0987SLEROY Christophe setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT); \ 453511d63cbSHoria Geanta spin_unlock_irqrestore(&priv->reg_lock, flags); \ 4549c4a7965SKim Phillips } 455dd3c0987SLEROY Christophe 456dd3c0987SLEROY Christophe DEF_TALITOS2_DONE(4ch, TALITOS2_ISR_4CHDONE) 4579c02e285SLEROY Christophe DEF_TALITOS2_DONE(ch0, TALITOS2_ISR_CH_0_DONE) 458dd3c0987SLEROY Christophe DEF_TALITOS2_DONE(ch0_2, TALITOS2_ISR_CH_0_2_DONE) 459dd3c0987SLEROY Christophe DEF_TALITOS2_DONE(ch1_3, TALITOS2_ISR_CH_1_3_DONE) 4609c4a7965SKim Phillips 4619c4a7965SKim Phillips /* 4629c4a7965SKim Phillips * locate current (offending) descriptor 4639c4a7965SKim Phillips */ 46402376161SChristophe Leroy static __be32 current_desc_hdr(struct device *dev, int ch) 4659c4a7965SKim Phillips { 4669c4a7965SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); 467b62ffd8cSHoria Geanta int tail, iter; 4689c4a7965SKim Phillips dma_addr_t cur_desc; 4699c4a7965SKim Phillips 470b62ffd8cSHoria Geanta cur_desc = ((u64)in_be32(priv->chan[ch].reg + TALITOS_CDPR)) << 32; 471b62ffd8cSHoria Geanta cur_desc |= in_be32(priv->chan[ch].reg + TALITOS_CDPR_LO); 4729c4a7965SKim Phillips 473b62ffd8cSHoria Geanta if (!cur_desc) { 474b62ffd8cSHoria Geanta dev_err(dev, "CDPR is NULL, giving up search for offending descriptor\n"); 475b62ffd8cSHoria Geanta return 0; 476b62ffd8cSHoria Geanta } 477b62ffd8cSHoria Geanta 478b62ffd8cSHoria Geanta tail = priv->chan[ch].tail; 479b62ffd8cSHoria Geanta 480b62ffd8cSHoria Geanta iter = tail; 48137b5e889SLEROY Christophe while (priv->chan[ch].fifo[iter].dma_desc != cur_desc && 482195404dbSChristophe Leroy priv->chan[ch].fifo[iter].desc->next_desc != cpu_to_be32(cur_desc)) { 483b62ffd8cSHoria Geanta iter = (iter + 1) & (priv->fifo_len - 1); 484b62ffd8cSHoria Geanta if (iter == tail) { 4859c4a7965SKim Phillips dev_err(dev, "couldn't locate current descriptor\n"); 4863e721aebSKim Phillips return 0; 4879c4a7965SKim Phillips } 4889c4a7965SKim Phillips } 4899c4a7965SKim Phillips 490195404dbSChristophe Leroy if (priv->chan[ch].fifo[iter].desc->next_desc == cpu_to_be32(cur_desc)) { 49158cdbc6dSChristophe Leroy struct talitos_edesc *edesc; 49258cdbc6dSChristophe Leroy 49358cdbc6dSChristophe Leroy edesc = container_of(priv->chan[ch].fifo[iter].desc, 49458cdbc6dSChristophe Leroy struct talitos_edesc, desc); 49558cdbc6dSChristophe Leroy return ((struct talitos_desc *) 49658cdbc6dSChristophe Leroy (edesc->buf + edesc->dma_len))->hdr; 49758cdbc6dSChristophe Leroy } 49837b5e889SLEROY Christophe 499b62ffd8cSHoria Geanta return priv->chan[ch].fifo[iter].desc->hdr; 5009c4a7965SKim Phillips } 5019c4a7965SKim Phillips 5029c4a7965SKim Phillips /* 5039c4a7965SKim Phillips * user diagnostics; report root cause of error based on execution unit status 5049c4a7965SKim Phillips */ 50502376161SChristophe Leroy static void report_eu_error(struct device *dev, int ch, __be32 desc_hdr) 5069c4a7965SKim Phillips { 5079c4a7965SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); 5089c4a7965SKim Phillips int i; 5099c4a7965SKim Phillips 5103e721aebSKim Phillips if (!desc_hdr) 51102376161SChristophe Leroy desc_hdr = cpu_to_be32(in_be32(priv->chan[ch].reg + TALITOS_DESCBUF)); 5123e721aebSKim Phillips 5133e721aebSKim Phillips switch (desc_hdr & DESC_HDR_SEL0_MASK) { 5149c4a7965SKim Phillips case DESC_HDR_SEL0_AFEU: 5159c4a7965SKim Phillips dev_err(dev, "AFEUISR 0x%08x_%08x\n", 5165fa7fa14SLEROY Christophe in_be32(priv->reg_afeu + TALITOS_EUISR), 5175fa7fa14SLEROY Christophe in_be32(priv->reg_afeu + TALITOS_EUISR_LO)); 5189c4a7965SKim Phillips break; 5199c4a7965SKim Phillips case DESC_HDR_SEL0_DEU: 5209c4a7965SKim Phillips dev_err(dev, "DEUISR 0x%08x_%08x\n", 5215fa7fa14SLEROY Christophe in_be32(priv->reg_deu + TALITOS_EUISR), 5225fa7fa14SLEROY Christophe in_be32(priv->reg_deu + TALITOS_EUISR_LO)); 5239c4a7965SKim Phillips break; 5249c4a7965SKim Phillips case DESC_HDR_SEL0_MDEUA: 5259c4a7965SKim Phillips case DESC_HDR_SEL0_MDEUB: 5269c4a7965SKim Phillips dev_err(dev, "MDEUISR 0x%08x_%08x\n", 5275fa7fa14SLEROY Christophe in_be32(priv->reg_mdeu + TALITOS_EUISR), 5285fa7fa14SLEROY Christophe in_be32(priv->reg_mdeu + TALITOS_EUISR_LO)); 5299c4a7965SKim Phillips break; 5309c4a7965SKim Phillips case DESC_HDR_SEL0_RNG: 5319c4a7965SKim Phillips dev_err(dev, "RNGUISR 0x%08x_%08x\n", 5325fa7fa14SLEROY Christophe in_be32(priv->reg_rngu + TALITOS_ISR), 5335fa7fa14SLEROY Christophe in_be32(priv->reg_rngu + TALITOS_ISR_LO)); 5349c4a7965SKim Phillips break; 5359c4a7965SKim Phillips case DESC_HDR_SEL0_PKEU: 5369c4a7965SKim Phillips dev_err(dev, "PKEUISR 0x%08x_%08x\n", 5375fa7fa14SLEROY Christophe in_be32(priv->reg_pkeu + TALITOS_EUISR), 5385fa7fa14SLEROY Christophe in_be32(priv->reg_pkeu + TALITOS_EUISR_LO)); 5399c4a7965SKim Phillips break; 5409c4a7965SKim Phillips case DESC_HDR_SEL0_AESU: 5419c4a7965SKim Phillips dev_err(dev, "AESUISR 0x%08x_%08x\n", 5425fa7fa14SLEROY Christophe in_be32(priv->reg_aesu + TALITOS_EUISR), 5435fa7fa14SLEROY Christophe in_be32(priv->reg_aesu + TALITOS_EUISR_LO)); 5449c4a7965SKim Phillips break; 5459c4a7965SKim Phillips case DESC_HDR_SEL0_CRCU: 5469c4a7965SKim Phillips dev_err(dev, "CRCUISR 0x%08x_%08x\n", 5475fa7fa14SLEROY Christophe in_be32(priv->reg_crcu + TALITOS_EUISR), 5485fa7fa14SLEROY Christophe in_be32(priv->reg_crcu + TALITOS_EUISR_LO)); 5499c4a7965SKim Phillips break; 5509c4a7965SKim Phillips case DESC_HDR_SEL0_KEU: 5519c4a7965SKim Phillips dev_err(dev, "KEUISR 0x%08x_%08x\n", 5525fa7fa14SLEROY Christophe in_be32(priv->reg_pkeu + TALITOS_EUISR), 5535fa7fa14SLEROY Christophe in_be32(priv->reg_pkeu + TALITOS_EUISR_LO)); 5549c4a7965SKim Phillips break; 5559c4a7965SKim Phillips } 5569c4a7965SKim Phillips 5573e721aebSKim Phillips switch (desc_hdr & DESC_HDR_SEL1_MASK) { 5589c4a7965SKim Phillips case DESC_HDR_SEL1_MDEUA: 5599c4a7965SKim Phillips case DESC_HDR_SEL1_MDEUB: 5609c4a7965SKim Phillips dev_err(dev, "MDEUISR 0x%08x_%08x\n", 5615fa7fa14SLEROY Christophe in_be32(priv->reg_mdeu + TALITOS_EUISR), 5625fa7fa14SLEROY Christophe in_be32(priv->reg_mdeu + TALITOS_EUISR_LO)); 5639c4a7965SKim Phillips break; 5649c4a7965SKim Phillips case DESC_HDR_SEL1_CRCU: 5659c4a7965SKim Phillips dev_err(dev, "CRCUISR 0x%08x_%08x\n", 5665fa7fa14SLEROY Christophe in_be32(priv->reg_crcu + TALITOS_EUISR), 5675fa7fa14SLEROY Christophe in_be32(priv->reg_crcu + TALITOS_EUISR_LO)); 5689c4a7965SKim Phillips break; 5699c4a7965SKim Phillips } 5709c4a7965SKim Phillips 5719c4a7965SKim Phillips for (i = 0; i < 8; i++) 5729c4a7965SKim Phillips dev_err(dev, "DESCBUF 0x%08x_%08x\n", 573ad42d5fcSKim Phillips in_be32(priv->chan[ch].reg + TALITOS_DESCBUF + 8*i), 574ad42d5fcSKim Phillips in_be32(priv->chan[ch].reg + TALITOS_DESCBUF_LO + 8*i)); 5759c4a7965SKim Phillips } 5769c4a7965SKim Phillips 5779c4a7965SKim Phillips /* 5789c4a7965SKim Phillips * recover from error interrupts 5799c4a7965SKim Phillips */ 5805e718a09SKim Phillips static void talitos_error(struct device *dev, u32 isr, u32 isr_lo) 5819c4a7965SKim Phillips { 5829c4a7965SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); 5839c4a7965SKim Phillips unsigned int timeout = TALITOS_TIMEOUT; 584dd3c0987SLEROY Christophe int ch, error, reset_dev = 0; 58542e8b0d7SHoria Geant? u32 v_lo; 586dd3c0987SLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 587dd3c0987SLEROY Christophe int reset_ch = is_sec1 ? 1 : 0; /* only SEC2 supports continuation */ 5889c4a7965SKim Phillips 5899c4a7965SKim Phillips for (ch = 0; ch < priv->num_channels; ch++) { 5909c4a7965SKim Phillips /* skip channels without errors */ 591dd3c0987SLEROY Christophe if (is_sec1) { 592dd3c0987SLEROY Christophe /* bits 29, 31, 17, 19 */ 593dd3c0987SLEROY Christophe if (!(isr & (1 << (29 + (ch & 1) * 2 - (ch & 2) * 6)))) 594dd3c0987SLEROY Christophe continue; 595dd3c0987SLEROY Christophe } else { 5969c4a7965SKim Phillips if (!(isr & (1 << (ch * 2 + 1)))) 5979c4a7965SKim Phillips continue; 598dd3c0987SLEROY Christophe } 5999c4a7965SKim Phillips 6009c4a7965SKim Phillips error = -EINVAL; 6019c4a7965SKim Phillips 602ad42d5fcSKim Phillips v_lo = in_be32(priv->chan[ch].reg + TALITOS_CCPSR_LO); 6039c4a7965SKim Phillips 6049c4a7965SKim Phillips if (v_lo & TALITOS_CCPSR_LO_DOF) { 6059c4a7965SKim Phillips dev_err(dev, "double fetch fifo overflow error\n"); 6069c4a7965SKim Phillips error = -EAGAIN; 6079c4a7965SKim Phillips reset_ch = 1; 6089c4a7965SKim Phillips } 6099c4a7965SKim Phillips if (v_lo & TALITOS_CCPSR_LO_SOF) { 6109c4a7965SKim Phillips /* h/w dropped descriptor */ 6119c4a7965SKim Phillips dev_err(dev, "single fetch fifo overflow error\n"); 6129c4a7965SKim Phillips error = -EAGAIN; 6139c4a7965SKim Phillips } 6149c4a7965SKim Phillips if (v_lo & TALITOS_CCPSR_LO_MDTE) 6159c4a7965SKim Phillips dev_err(dev, "master data transfer error\n"); 6169c4a7965SKim Phillips if (v_lo & TALITOS_CCPSR_LO_SGDLZ) 6174d9b3a5bSColin Ian King dev_err(dev, is_sec1 ? "pointer not complete error\n" 618dd3c0987SLEROY Christophe : "s/g data length zero error\n"); 6199c4a7965SKim Phillips if (v_lo & TALITOS_CCPSR_LO_FPZ) 620dd3c0987SLEROY Christophe dev_err(dev, is_sec1 ? "parity error\n" 621dd3c0987SLEROY Christophe : "fetch pointer zero error\n"); 6229c4a7965SKim Phillips if (v_lo & TALITOS_CCPSR_LO_IDH) 6239c4a7965SKim Phillips dev_err(dev, "illegal descriptor header error\n"); 6249c4a7965SKim Phillips if (v_lo & TALITOS_CCPSR_LO_IEU) 625dd3c0987SLEROY Christophe dev_err(dev, is_sec1 ? "static assignment error\n" 626dd3c0987SLEROY Christophe : "invalid exec unit error\n"); 6279c4a7965SKim Phillips if (v_lo & TALITOS_CCPSR_LO_EU) 6283e721aebSKim Phillips report_eu_error(dev, ch, current_desc_hdr(dev, ch)); 629dd3c0987SLEROY Christophe if (!is_sec1) { 6309c4a7965SKim Phillips if (v_lo & TALITOS_CCPSR_LO_GB) 6319c4a7965SKim Phillips dev_err(dev, "gather boundary error\n"); 6329c4a7965SKim Phillips if (v_lo & TALITOS_CCPSR_LO_GRL) 6339c4a7965SKim Phillips dev_err(dev, "gather return/length error\n"); 6349c4a7965SKim Phillips if (v_lo & TALITOS_CCPSR_LO_SB) 6359c4a7965SKim Phillips dev_err(dev, "scatter boundary error\n"); 6369c4a7965SKim Phillips if (v_lo & TALITOS_CCPSR_LO_SRL) 6379c4a7965SKim Phillips dev_err(dev, "scatter return/length error\n"); 638dd3c0987SLEROY Christophe } 6399c4a7965SKim Phillips 6409c4a7965SKim Phillips flush_channel(dev, ch, error, reset_ch); 6419c4a7965SKim Phillips 6429c4a7965SKim Phillips if (reset_ch) { 6439c4a7965SKim Phillips reset_channel(dev, ch); 6449c4a7965SKim Phillips } else { 645ad42d5fcSKim Phillips setbits32(priv->chan[ch].reg + TALITOS_CCCR, 646dd3c0987SLEROY Christophe TALITOS2_CCCR_CONT); 647ad42d5fcSKim Phillips setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, 0); 648ad42d5fcSKim Phillips while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) & 649dd3c0987SLEROY Christophe TALITOS2_CCCR_CONT) && --timeout) 6509c4a7965SKim Phillips cpu_relax(); 6519c4a7965SKim Phillips if (timeout == 0) { 6529c4a7965SKim Phillips dev_err(dev, "failed to restart channel %d\n", 6539c4a7965SKim Phillips ch); 6549c4a7965SKim Phillips reset_dev = 1; 6559c4a7965SKim Phillips } 6569c4a7965SKim Phillips } 6579c4a7965SKim Phillips } 658dd3c0987SLEROY Christophe if (reset_dev || (is_sec1 && isr & ~TALITOS1_ISR_4CHERR) || 659dd3c0987SLEROY Christophe (!is_sec1 && isr & ~TALITOS2_ISR_4CHERR) || isr_lo) { 660dd3c0987SLEROY Christophe if (is_sec1 && (isr_lo & TALITOS1_ISR_TEA_ERR)) 661dd3c0987SLEROY Christophe dev_err(dev, "TEA error: ISR 0x%08x_%08x\n", 662dd3c0987SLEROY Christophe isr, isr_lo); 663dd3c0987SLEROY Christophe else 664dd3c0987SLEROY Christophe dev_err(dev, "done overflow, internal time out, or " 665dd3c0987SLEROY Christophe "rngu error: ISR 0x%08x_%08x\n", isr, isr_lo); 6669c4a7965SKim Phillips 6679c4a7965SKim Phillips /* purge request queues */ 6689c4a7965SKim Phillips for (ch = 0; ch < priv->num_channels; ch++) 6699c4a7965SKim Phillips flush_channel(dev, ch, -EIO, 1); 6709c4a7965SKim Phillips 6719c4a7965SKim Phillips /* reset and reinitialize the device */ 6729c4a7965SKim Phillips init_device(dev); 6739c4a7965SKim Phillips } 6749c4a7965SKim Phillips } 6759c4a7965SKim Phillips 676dd3c0987SLEROY Christophe #define DEF_TALITOS1_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet) \ 677dd3c0987SLEROY Christophe static irqreturn_t talitos1_interrupt_##name(int irq, void *data) \ 678dd3c0987SLEROY Christophe { \ 679dd3c0987SLEROY Christophe struct device *dev = data; \ 680dd3c0987SLEROY Christophe struct talitos_private *priv = dev_get_drvdata(dev); \ 681dd3c0987SLEROY Christophe u32 isr, isr_lo; \ 682dd3c0987SLEROY Christophe unsigned long flags; \ 683dd3c0987SLEROY Christophe \ 684dd3c0987SLEROY Christophe spin_lock_irqsave(&priv->reg_lock, flags); \ 685dd3c0987SLEROY Christophe isr = in_be32(priv->reg + TALITOS_ISR); \ 686dd3c0987SLEROY Christophe isr_lo = in_be32(priv->reg + TALITOS_ISR_LO); \ 687dd3c0987SLEROY Christophe /* Acknowledge interrupt */ \ 688dd3c0987SLEROY Christophe out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \ 689dd3c0987SLEROY Christophe out_be32(priv->reg + TALITOS_ICR_LO, isr_lo); \ 690dd3c0987SLEROY Christophe \ 691dd3c0987SLEROY Christophe if (unlikely(isr & ch_err_mask || isr_lo & TALITOS1_IMR_LO_INIT)) { \ 692dd3c0987SLEROY Christophe spin_unlock_irqrestore(&priv->reg_lock, flags); \ 693dd3c0987SLEROY Christophe talitos_error(dev, isr & ch_err_mask, isr_lo); \ 694dd3c0987SLEROY Christophe } \ 695dd3c0987SLEROY Christophe else { \ 696dd3c0987SLEROY Christophe if (likely(isr & ch_done_mask)) { \ 697dd3c0987SLEROY Christophe /* mask further done interrupts. */ \ 698dd3c0987SLEROY Christophe setbits32(priv->reg + TALITOS_IMR, ch_done_mask); \ 699dd3c0987SLEROY Christophe /* done_task will unmask done interrupts at exit */ \ 700dd3c0987SLEROY Christophe tasklet_schedule(&priv->done_task[tlet]); \ 701dd3c0987SLEROY Christophe } \ 702dd3c0987SLEROY Christophe spin_unlock_irqrestore(&priv->reg_lock, flags); \ 703dd3c0987SLEROY Christophe } \ 704dd3c0987SLEROY Christophe \ 705dd3c0987SLEROY Christophe return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED : \ 706dd3c0987SLEROY Christophe IRQ_NONE; \ 707dd3c0987SLEROY Christophe } 708dd3c0987SLEROY Christophe 709dd3c0987SLEROY Christophe DEF_TALITOS1_INTERRUPT(4ch, TALITOS1_ISR_4CHDONE, TALITOS1_ISR_4CHERR, 0) 710dd3c0987SLEROY Christophe 711dd3c0987SLEROY Christophe #define DEF_TALITOS2_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet) \ 712dd3c0987SLEROY Christophe static irqreturn_t talitos2_interrupt_##name(int irq, void *data) \ 713c3e337f8SKim Phillips { \ 714c3e337f8SKim Phillips struct device *dev = data; \ 715c3e337f8SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); \ 716c3e337f8SKim Phillips u32 isr, isr_lo; \ 717511d63cbSHoria Geanta unsigned long flags; \ 718c3e337f8SKim Phillips \ 719511d63cbSHoria Geanta spin_lock_irqsave(&priv->reg_lock, flags); \ 720c3e337f8SKim Phillips isr = in_be32(priv->reg + TALITOS_ISR); \ 721c3e337f8SKim Phillips isr_lo = in_be32(priv->reg + TALITOS_ISR_LO); \ 722c3e337f8SKim Phillips /* Acknowledge interrupt */ \ 723c3e337f8SKim Phillips out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \ 724c3e337f8SKim Phillips out_be32(priv->reg + TALITOS_ICR_LO, isr_lo); \ 725c3e337f8SKim Phillips \ 726511d63cbSHoria Geanta if (unlikely(isr & ch_err_mask || isr_lo)) { \ 727511d63cbSHoria Geanta spin_unlock_irqrestore(&priv->reg_lock, flags); \ 728511d63cbSHoria Geanta talitos_error(dev, isr & ch_err_mask, isr_lo); \ 729511d63cbSHoria Geanta } \ 730511d63cbSHoria Geanta else { \ 731c3e337f8SKim Phillips if (likely(isr & ch_done_mask)) { \ 732c3e337f8SKim Phillips /* mask further done interrupts. */ \ 733c3e337f8SKim Phillips clrbits32(priv->reg + TALITOS_IMR, ch_done_mask); \ 734c3e337f8SKim Phillips /* done_task will unmask done interrupts at exit */ \ 735c3e337f8SKim Phillips tasklet_schedule(&priv->done_task[tlet]); \ 736c3e337f8SKim Phillips } \ 737511d63cbSHoria Geanta spin_unlock_irqrestore(&priv->reg_lock, flags); \ 738511d63cbSHoria Geanta } \ 739c3e337f8SKim Phillips \ 740c3e337f8SKim Phillips return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED : \ 741c3e337f8SKim Phillips IRQ_NONE; \ 7421c2e8811SLee Nipper } 743dd3c0987SLEROY Christophe 744dd3c0987SLEROY Christophe DEF_TALITOS2_INTERRUPT(4ch, TALITOS2_ISR_4CHDONE, TALITOS2_ISR_4CHERR, 0) 745dd3c0987SLEROY Christophe DEF_TALITOS2_INTERRUPT(ch0_2, TALITOS2_ISR_CH_0_2_DONE, TALITOS2_ISR_CH_0_2_ERR, 746dd3c0987SLEROY Christophe 0) 747dd3c0987SLEROY Christophe DEF_TALITOS2_INTERRUPT(ch1_3, TALITOS2_ISR_CH_1_3_DONE, TALITOS2_ISR_CH_1_3_ERR, 748dd3c0987SLEROY Christophe 1) 7499c4a7965SKim Phillips 7509c4a7965SKim Phillips /* 7519c4a7965SKim Phillips * hwrng 7529c4a7965SKim Phillips */ 7539c4a7965SKim Phillips static int talitos_rng_data_present(struct hwrng *rng, int wait) 7549c4a7965SKim Phillips { 7559c4a7965SKim Phillips struct device *dev = (struct device *)rng->priv; 7569c4a7965SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); 7579c4a7965SKim Phillips u32 ofl; 7589c4a7965SKim Phillips int i; 7599c4a7965SKim Phillips 7609c4a7965SKim Phillips for (i = 0; i < 20; i++) { 7615fa7fa14SLEROY Christophe ofl = in_be32(priv->reg_rngu + TALITOS_EUSR_LO) & 7629c4a7965SKim Phillips TALITOS_RNGUSR_LO_OFL; 7639c4a7965SKim Phillips if (ofl || !wait) 7649c4a7965SKim Phillips break; 7659c4a7965SKim Phillips udelay(10); 7669c4a7965SKim Phillips } 7679c4a7965SKim Phillips 7689c4a7965SKim Phillips return !!ofl; 7699c4a7965SKim Phillips } 7709c4a7965SKim Phillips 7719c4a7965SKim Phillips static int talitos_rng_data_read(struct hwrng *rng, u32 *data) 7729c4a7965SKim Phillips { 7739c4a7965SKim Phillips struct device *dev = (struct device *)rng->priv; 7749c4a7965SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); 7759c4a7965SKim Phillips 7769c4a7965SKim Phillips /* rng fifo requires 64-bit accesses */ 7775fa7fa14SLEROY Christophe *data = in_be32(priv->reg_rngu + TALITOS_EU_FIFO); 7785fa7fa14SLEROY Christophe *data = in_be32(priv->reg_rngu + TALITOS_EU_FIFO_LO); 7799c4a7965SKim Phillips 7809c4a7965SKim Phillips return sizeof(u32); 7819c4a7965SKim Phillips } 7829c4a7965SKim Phillips 7839c4a7965SKim Phillips static int talitos_rng_init(struct hwrng *rng) 7849c4a7965SKim Phillips { 7859c4a7965SKim Phillips struct device *dev = (struct device *)rng->priv; 7869c4a7965SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); 7879c4a7965SKim Phillips unsigned int timeout = TALITOS_TIMEOUT; 7889c4a7965SKim Phillips 7895fa7fa14SLEROY Christophe setbits32(priv->reg_rngu + TALITOS_EURCR_LO, TALITOS_RNGURCR_LO_SR); 7905fa7fa14SLEROY Christophe while (!(in_be32(priv->reg_rngu + TALITOS_EUSR_LO) 7915fa7fa14SLEROY Christophe & TALITOS_RNGUSR_LO_RD) 7929c4a7965SKim Phillips && --timeout) 7939c4a7965SKim Phillips cpu_relax(); 7949c4a7965SKim Phillips if (timeout == 0) { 7959c4a7965SKim Phillips dev_err(dev, "failed to reset rng hw\n"); 7969c4a7965SKim Phillips return -ENODEV; 7979c4a7965SKim Phillips } 7989c4a7965SKim Phillips 7999c4a7965SKim Phillips /* start generating */ 8005fa7fa14SLEROY Christophe setbits32(priv->reg_rngu + TALITOS_EUDSR_LO, 0); 8019c4a7965SKim Phillips 8029c4a7965SKim Phillips return 0; 8039c4a7965SKim Phillips } 8049c4a7965SKim Phillips 8059c4a7965SKim Phillips static int talitos_register_rng(struct device *dev) 8069c4a7965SKim Phillips { 8079c4a7965SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); 80835a3bb3dSAaron Sierra int err; 8099c4a7965SKim Phillips 81077450fd7SJulia Lawall priv->rng.name = dev_driver_string(dev); 81177450fd7SJulia Lawall priv->rng.init = talitos_rng_init; 81277450fd7SJulia Lawall priv->rng.data_present = talitos_rng_data_present; 81377450fd7SJulia Lawall priv->rng.data_read = talitos_rng_data_read; 8149c4a7965SKim Phillips priv->rng.priv = (unsigned long)dev; 8159c4a7965SKim Phillips 81635a3bb3dSAaron Sierra err = hwrng_register(&priv->rng); 81735a3bb3dSAaron Sierra if (!err) 81835a3bb3dSAaron Sierra priv->rng_registered = true; 81935a3bb3dSAaron Sierra 82035a3bb3dSAaron Sierra return err; 8219c4a7965SKim Phillips } 8229c4a7965SKim Phillips 8239c4a7965SKim Phillips static void talitos_unregister_rng(struct device *dev) 8249c4a7965SKim Phillips { 8259c4a7965SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); 8269c4a7965SKim Phillips 82735a3bb3dSAaron Sierra if (!priv->rng_registered) 82835a3bb3dSAaron Sierra return; 82935a3bb3dSAaron Sierra 8309c4a7965SKim Phillips hwrng_unregister(&priv->rng); 83135a3bb3dSAaron Sierra priv->rng_registered = false; 8329c4a7965SKim Phillips } 8339c4a7965SKim Phillips 8349c4a7965SKim Phillips /* 8359c4a7965SKim Phillips * crypto alg 8369c4a7965SKim Phillips */ 8379c4a7965SKim Phillips #define TALITOS_CRA_PRIORITY 3000 8387405c8d7SLEROY Christophe /* 8397405c8d7SLEROY Christophe * Defines a priority for doing AEAD with descriptors type 8407405c8d7SLEROY Christophe * HMAC_SNOOP_NO_AFEA (HSNA) instead of type IPSEC_ESP 8417405c8d7SLEROY Christophe */ 8427405c8d7SLEROY Christophe #define TALITOS_CRA_PRIORITY_AEAD_HSNA (TALITOS_CRA_PRIORITY - 1) 843192125edSChristophe Leroy #ifdef CONFIG_CRYPTO_DEV_TALITOS2 84403d2c511SMartin Hicks #define TALITOS_MAX_KEY_SIZE (AES_MAX_KEY_SIZE + SHA512_BLOCK_SIZE) 845b8fbdc2bSChristophe Leroy #else 846b8fbdc2bSChristophe Leroy #define TALITOS_MAX_KEY_SIZE (AES_MAX_KEY_SIZE + SHA256_BLOCK_SIZE) 847b8fbdc2bSChristophe Leroy #endif 8483952f17eSLee Nipper #define TALITOS_MAX_IV_LENGTH 16 /* max of AES_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE */ 84970bcaca7SLee Nipper 8509c4a7965SKim Phillips struct talitos_ctx { 8519c4a7965SKim Phillips struct device *dev; 8525228f0f7SKim Phillips int ch; 8539c4a7965SKim Phillips __be32 desc_hdr_template; 8549c4a7965SKim Phillips u8 key[TALITOS_MAX_KEY_SIZE]; 85570bcaca7SLee Nipper u8 iv[TALITOS_MAX_IV_LENGTH]; 8562e13ce08SLEROY Christophe dma_addr_t dma_key; 8579c4a7965SKim Phillips unsigned int keylen; 8589c4a7965SKim Phillips unsigned int enckeylen; 8599c4a7965SKim Phillips unsigned int authkeylen; 8609c4a7965SKim Phillips }; 8619c4a7965SKim Phillips 862497f2e6bSLee Nipper #define HASH_MAX_BLOCK_SIZE SHA512_BLOCK_SIZE 863497f2e6bSLee Nipper #define TALITOS_MDEU_MAX_CONTEXT_SIZE TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512 864497f2e6bSLee Nipper 865497f2e6bSLee Nipper struct talitos_ahash_req_ctx { 86660f208d7SKim Phillips u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)]; 867497f2e6bSLee Nipper unsigned int hw_context_size; 8683c0dd190SLEROY Christophe u8 buf[2][HASH_MAX_BLOCK_SIZE]; 8693c0dd190SLEROY Christophe int buf_idx; 87060f208d7SKim Phillips unsigned int swinit; 871497f2e6bSLee Nipper unsigned int first; 872497f2e6bSLee Nipper unsigned int last; 873497f2e6bSLee Nipper unsigned int to_hash_later; 87442e8b0d7SHoria Geant? unsigned int nbuf; 875497f2e6bSLee Nipper struct scatterlist bufsl[2]; 876497f2e6bSLee Nipper struct scatterlist *psrc; 877497f2e6bSLee Nipper }; 878497f2e6bSLee Nipper 8793639ca84SHoria Geant? struct talitos_export_state { 8803639ca84SHoria Geant? u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)]; 8813639ca84SHoria Geant? u8 buf[HASH_MAX_BLOCK_SIZE]; 8823639ca84SHoria Geant? unsigned int swinit; 8833639ca84SHoria Geant? unsigned int first; 8843639ca84SHoria Geant? unsigned int last; 8853639ca84SHoria Geant? unsigned int to_hash_later; 8863639ca84SHoria Geant? unsigned int nbuf; 8873639ca84SHoria Geant? }; 8883639ca84SHoria Geant? 88956af8cd4SLee Nipper static int aead_setkey(struct crypto_aead *authenc, 8909c4a7965SKim Phillips const u8 *key, unsigned int keylen) 8919c4a7965SKim Phillips { 8929c4a7965SKim Phillips struct talitos_ctx *ctx = crypto_aead_ctx(authenc); 8932e13ce08SLEROY Christophe struct device *dev = ctx->dev; 894c306a98dSMathias Krause struct crypto_authenc_keys keys; 8959c4a7965SKim Phillips 896c306a98dSMathias Krause if (crypto_authenc_extractkeys(&keys, key, keylen) != 0) 8979c4a7965SKim Phillips goto badkey; 8989c4a7965SKim Phillips 899c306a98dSMathias Krause if (keys.authkeylen + keys.enckeylen > TALITOS_MAX_KEY_SIZE) 9009c4a7965SKim Phillips goto badkey; 9019c4a7965SKim Phillips 9022e13ce08SLEROY Christophe if (ctx->keylen) 9032e13ce08SLEROY Christophe dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE); 9042e13ce08SLEROY Christophe 905c306a98dSMathias Krause memcpy(ctx->key, keys.authkey, keys.authkeylen); 906c306a98dSMathias Krause memcpy(&ctx->key[keys.authkeylen], keys.enckey, keys.enckeylen); 9079c4a7965SKim Phillips 908c306a98dSMathias Krause ctx->keylen = keys.authkeylen + keys.enckeylen; 909c306a98dSMathias Krause ctx->enckeylen = keys.enckeylen; 910c306a98dSMathias Krause ctx->authkeylen = keys.authkeylen; 9112e13ce08SLEROY Christophe ctx->dma_key = dma_map_single(dev, ctx->key, ctx->keylen, 9122e13ce08SLEROY Christophe DMA_TO_DEVICE); 9139c4a7965SKim Phillips 9148f0691fcSTudor-Dan Ambarus memzero_explicit(&keys, sizeof(keys)); 9159c4a7965SKim Phillips return 0; 9169c4a7965SKim Phillips 9179c4a7965SKim Phillips badkey: 9188f0691fcSTudor-Dan Ambarus memzero_explicit(&keys, sizeof(keys)); 9199c4a7965SKim Phillips return -EINVAL; 9209c4a7965SKim Phillips } 9219c4a7965SKim Phillips 922ef7c5c85SHerbert Xu static int aead_des3_setkey(struct crypto_aead *authenc, 923ef7c5c85SHerbert Xu const u8 *key, unsigned int keylen) 924ef7c5c85SHerbert Xu { 925ef7c5c85SHerbert Xu struct talitos_ctx *ctx = crypto_aead_ctx(authenc); 926ef7c5c85SHerbert Xu struct device *dev = ctx->dev; 927ef7c5c85SHerbert Xu struct crypto_authenc_keys keys; 928ef7c5c85SHerbert Xu int err; 929ef7c5c85SHerbert Xu 930ef7c5c85SHerbert Xu err = crypto_authenc_extractkeys(&keys, key, keylen); 931ef7c5c85SHerbert Xu if (unlikely(err)) 932674f368aSEric Biggers goto out; 933ef7c5c85SHerbert Xu 934ef7c5c85SHerbert Xu err = -EINVAL; 935ef7c5c85SHerbert Xu if (keys.authkeylen + keys.enckeylen > TALITOS_MAX_KEY_SIZE) 936674f368aSEric Biggers goto out; 937ef7c5c85SHerbert Xu 9389d574ae8SArd Biesheuvel err = verify_aead_des3_key(authenc, keys.enckey, keys.enckeylen); 9399d574ae8SArd Biesheuvel if (err) 940ef7c5c85SHerbert Xu goto out; 941ef7c5c85SHerbert Xu 942ef7c5c85SHerbert Xu if (ctx->keylen) 943ef7c5c85SHerbert Xu dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE); 944ef7c5c85SHerbert Xu 945ef7c5c85SHerbert Xu memcpy(ctx->key, keys.authkey, keys.authkeylen); 946ef7c5c85SHerbert Xu memcpy(&ctx->key[keys.authkeylen], keys.enckey, keys.enckeylen); 947ef7c5c85SHerbert Xu 948ef7c5c85SHerbert Xu ctx->keylen = keys.authkeylen + keys.enckeylen; 949ef7c5c85SHerbert Xu ctx->enckeylen = keys.enckeylen; 950ef7c5c85SHerbert Xu ctx->authkeylen = keys.authkeylen; 951ef7c5c85SHerbert Xu ctx->dma_key = dma_map_single(dev, ctx->key, ctx->keylen, 952ef7c5c85SHerbert Xu DMA_TO_DEVICE); 953ef7c5c85SHerbert Xu 954ef7c5c85SHerbert Xu out: 955ef7c5c85SHerbert Xu memzero_explicit(&keys, sizeof(keys)); 956ef7c5c85SHerbert Xu return err; 957ef7c5c85SHerbert Xu } 958ef7c5c85SHerbert Xu 9594de9d0b5SLee Nipper static void talitos_sg_unmap(struct device *dev, 9604de9d0b5SLee Nipper struct talitos_edesc *edesc, 9614de9d0b5SLee Nipper struct scatterlist *src, 9626a1e8d14SLEROY Christophe struct scatterlist *dst, 9636a1e8d14SLEROY Christophe unsigned int len, unsigned int offset) 964246a87cdSLEROY Christophe { 965246a87cdSLEROY Christophe struct talitos_private *priv = dev_get_drvdata(dev); 966246a87cdSLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 9676a1e8d14SLEROY Christophe unsigned int src_nents = edesc->src_nents ? : 1; 9686a1e8d14SLEROY Christophe unsigned int dst_nents = edesc->dst_nents ? : 1; 969246a87cdSLEROY Christophe 9706a1e8d14SLEROY Christophe if (is_sec1 && dst && dst_nents > 1) { 9716a1e8d14SLEROY Christophe dma_sync_single_for_device(dev, edesc->dma_link_tbl + offset, 972246a87cdSLEROY Christophe len, DMA_FROM_DEVICE); 9736a1e8d14SLEROY Christophe sg_pcopy_from_buffer(dst, dst_nents, edesc->buf + offset, len, 9746a1e8d14SLEROY Christophe offset); 975246a87cdSLEROY Christophe } 9766a1e8d14SLEROY Christophe if (src != dst) { 9776a1e8d14SLEROY Christophe if (src_nents == 1 || !is_sec1) 9786a1e8d14SLEROY Christophe dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE); 9796a1e8d14SLEROY Christophe 9806a1e8d14SLEROY Christophe if (dst && (dst_nents == 1 || !is_sec1)) 9816a1e8d14SLEROY Christophe dma_unmap_sg(dev, dst, dst_nents, DMA_FROM_DEVICE); 9826a1e8d14SLEROY Christophe } else if (src_nents == 1 || !is_sec1) { 9836a1e8d14SLEROY Christophe dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL); 984246a87cdSLEROY Christophe } 985246a87cdSLEROY Christophe } 986246a87cdSLEROY Christophe 9879c4a7965SKim Phillips static void ipsec_esp_unmap(struct device *dev, 98856af8cd4SLee Nipper struct talitos_edesc *edesc, 9897ede4c36SChristophe Leroy struct aead_request *areq, bool encrypt) 9909c4a7965SKim Phillips { 991549bd8bcSLEROY Christophe struct crypto_aead *aead = crypto_aead_reqtfm(areq); 992549bd8bcSLEROY Christophe struct talitos_ctx *ctx = crypto_aead_ctx(aead); 993549bd8bcSLEROY Christophe unsigned int ivsize = crypto_aead_ivsize(aead); 9947ede4c36SChristophe Leroy unsigned int authsize = crypto_aead_authsize(aead); 9957ede4c36SChristophe Leroy unsigned int cryptlen = areq->cryptlen - (encrypt ? 0 : authsize); 9969a655608SLEROY Christophe bool is_ipsec_esp = edesc->desc.hdr & DESC_HDR_TYPE_IPSEC_ESP; 9979a655608SLEROY Christophe struct talitos_ptr *civ_ptr = &edesc->desc.ptr[is_ipsec_esp ? 2 : 3]; 998549bd8bcSLEROY Christophe 9999a655608SLEROY Christophe if (is_ipsec_esp) 1000549bd8bcSLEROY Christophe unmap_single_talitos_ptr(dev, &edesc->desc.ptr[6], 1001549bd8bcSLEROY Christophe DMA_FROM_DEVICE); 10029a655608SLEROY Christophe unmap_single_talitos_ptr(dev, civ_ptr, DMA_TO_DEVICE); 10039c4a7965SKim Phillips 1004e345177dSChristophe Leroy talitos_sg_unmap(dev, edesc, areq->src, areq->dst, 1005e345177dSChristophe Leroy cryptlen + authsize, areq->assoclen); 10069c4a7965SKim Phillips 10079c4a7965SKim Phillips if (edesc->dma_len) 10089c4a7965SKim Phillips dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len, 10099c4a7965SKim Phillips DMA_BIDIRECTIONAL); 1010549bd8bcSLEROY Christophe 10119a655608SLEROY Christophe if (!is_ipsec_esp) { 1012549bd8bcSLEROY Christophe unsigned int dst_nents = edesc->dst_nents ? : 1; 1013549bd8bcSLEROY Christophe 1014549bd8bcSLEROY Christophe sg_pcopy_to_buffer(areq->dst, dst_nents, ctx->iv, ivsize, 10157ede4c36SChristophe Leroy areq->assoclen + cryptlen - ivsize); 1016549bd8bcSLEROY Christophe } 10179c4a7965SKim Phillips } 10189c4a7965SKim Phillips 10199c4a7965SKim Phillips /* 10209c4a7965SKim Phillips * ipsec_esp descriptor callbacks 10219c4a7965SKim Phillips */ 10229c4a7965SKim Phillips static void ipsec_esp_encrypt_done(struct device *dev, 10239c4a7965SKim Phillips struct talitos_desc *desc, void *context, 10249c4a7965SKim Phillips int err) 10259c4a7965SKim Phillips { 10269c4a7965SKim Phillips struct aead_request *areq = context; 10279c4a7965SKim Phillips struct crypto_aead *authenc = crypto_aead_reqtfm(areq); 10282e13ce08SLEROY Christophe unsigned int ivsize = crypto_aead_ivsize(authenc); 102919bbbc63SKim Phillips struct talitos_edesc *edesc; 10309c4a7965SKim Phillips 103119bbbc63SKim Phillips edesc = container_of(desc, struct talitos_edesc, desc); 103219bbbc63SKim Phillips 10337ede4c36SChristophe Leroy ipsec_esp_unmap(dev, edesc, areq, true); 10349c4a7965SKim Phillips 10352e13ce08SLEROY Christophe dma_unmap_single(dev, edesc->iv_dma, ivsize, DMA_TO_DEVICE); 10362e13ce08SLEROY Christophe 10379c4a7965SKim Phillips kfree(edesc); 10389c4a7965SKim Phillips 10399c4a7965SKim Phillips aead_request_complete(areq, err); 10409c4a7965SKim Phillips } 10419c4a7965SKim Phillips 1042fe5720e2SKim Phillips static void ipsec_esp_decrypt_swauth_done(struct device *dev, 1043e938e465SKim Phillips struct talitos_desc *desc, 1044e938e465SKim Phillips void *context, int err) 10459c4a7965SKim Phillips { 10469c4a7965SKim Phillips struct aead_request *req = context; 10479c4a7965SKim Phillips struct crypto_aead *authenc = crypto_aead_reqtfm(req); 1048aeb4c132SHerbert Xu unsigned int authsize = crypto_aead_authsize(authenc); 104919bbbc63SKim Phillips struct talitos_edesc *edesc; 1050aeb4c132SHerbert Xu char *oicv, *icv; 10519c4a7965SKim Phillips 105219bbbc63SKim Phillips edesc = container_of(desc, struct talitos_edesc, desc); 105319bbbc63SKim Phillips 10547ede4c36SChristophe Leroy ipsec_esp_unmap(dev, edesc, req, false); 10559c4a7965SKim Phillips 10569c4a7965SKim Phillips if (!err) { 10579c4a7965SKim Phillips /* auth check */ 1058e345177dSChristophe Leroy oicv = edesc->buf + edesc->dma_len; 1059e345177dSChristophe Leroy icv = oicv - authsize; 1060aeb4c132SHerbert Xu 106179960943SDavid Gstir err = crypto_memneq(oicv, icv, authsize) ? -EBADMSG : 0; 10629c4a7965SKim Phillips } 10639c4a7965SKim Phillips 10649c4a7965SKim Phillips kfree(edesc); 10659c4a7965SKim Phillips 10669c4a7965SKim Phillips aead_request_complete(req, err); 10679c4a7965SKim Phillips } 10689c4a7965SKim Phillips 1069fe5720e2SKim Phillips static void ipsec_esp_decrypt_hwauth_done(struct device *dev, 1070e938e465SKim Phillips struct talitos_desc *desc, 1071e938e465SKim Phillips void *context, int err) 1072fe5720e2SKim Phillips { 1073fe5720e2SKim Phillips struct aead_request *req = context; 107419bbbc63SKim Phillips struct talitos_edesc *edesc; 107519bbbc63SKim Phillips 107619bbbc63SKim Phillips edesc = container_of(desc, struct talitos_edesc, desc); 1077fe5720e2SKim Phillips 10787ede4c36SChristophe Leroy ipsec_esp_unmap(dev, edesc, req, false); 1079fe5720e2SKim Phillips 1080fe5720e2SKim Phillips /* check ICV auth status */ 1081e938e465SKim Phillips if (!err && ((desc->hdr_lo & DESC_HDR_LO_ICCR1_MASK) != 1082e938e465SKim Phillips DESC_HDR_LO_ICCR1_PASS)) 1083fe5720e2SKim Phillips err = -EBADMSG; 1084fe5720e2SKim Phillips 1085fe5720e2SKim Phillips kfree(edesc); 1086fe5720e2SKim Phillips 1087fe5720e2SKim Phillips aead_request_complete(req, err); 1088fe5720e2SKim Phillips } 1089fe5720e2SKim Phillips 10909c4a7965SKim Phillips /* 10919c4a7965SKim Phillips * convert scatterlist to SEC h/w link table format 10929c4a7965SKim Phillips * stop at cryptlen bytes 10939c4a7965SKim Phillips */ 1094aeb4c132SHerbert Xu static int sg_to_link_tbl_offset(struct scatterlist *sg, int sg_count, 1095e345177dSChristophe Leroy unsigned int offset, int datalen, int elen, 1096416b8467SChristophe Leroy struct talitos_ptr *link_tbl_ptr, int align) 10979c4a7965SKim Phillips { 1098e345177dSChristophe Leroy int n_sg = elen ? sg_count + 1 : sg_count; 1099aeb4c132SHerbert Xu int count = 0; 1100e345177dSChristophe Leroy int cryptlen = datalen + elen; 1101416b8467SChristophe Leroy int padding = ALIGN(cryptlen, align) - cryptlen; 110270bcaca7SLee Nipper 1103aeb4c132SHerbert Xu while (cryptlen && sg && n_sg--) { 1104aeb4c132SHerbert Xu unsigned int len = sg_dma_len(sg); 1105aeb4c132SHerbert Xu 1106aeb4c132SHerbert Xu if (offset >= len) { 1107aeb4c132SHerbert Xu offset -= len; 1108aeb4c132SHerbert Xu goto next; 1109aeb4c132SHerbert Xu } 1110aeb4c132SHerbert Xu 1111aeb4c132SHerbert Xu len -= offset; 1112aeb4c132SHerbert Xu 1113aeb4c132SHerbert Xu if (len > cryptlen) 1114aeb4c132SHerbert Xu len = cryptlen; 1115aeb4c132SHerbert Xu 1116e345177dSChristophe Leroy if (datalen > 0 && len > datalen) { 1117e345177dSChristophe Leroy to_talitos_ptr(link_tbl_ptr + count, 1118e345177dSChristophe Leroy sg_dma_address(sg) + offset, datalen, 0); 1119e345177dSChristophe Leroy to_talitos_ptr_ext_set(link_tbl_ptr + count, 0, 0); 1120e345177dSChristophe Leroy count++; 1121e345177dSChristophe Leroy len -= datalen; 1122e345177dSChristophe Leroy offset += datalen; 1123e345177dSChristophe Leroy } 1124aeb4c132SHerbert Xu to_talitos_ptr(link_tbl_ptr + count, 1125416b8467SChristophe Leroy sg_dma_address(sg) + offset, sg_next(sg) ? len : len + padding, 0); 1126b096b544SLEROY Christophe to_talitos_ptr_ext_set(link_tbl_ptr + count, 0, 0); 1127aeb4c132SHerbert Xu count++; 1128aeb4c132SHerbert Xu cryptlen -= len; 1129e345177dSChristophe Leroy datalen -= len; 1130aeb4c132SHerbert Xu offset = 0; 1131aeb4c132SHerbert Xu 1132aeb4c132SHerbert Xu next: 11335be4d4c9SCristian Stoica sg = sg_next(sg); 11349c4a7965SKim Phillips } 11359c4a7965SKim Phillips 11369c4a7965SKim Phillips /* tag end of link table */ 1137aeb4c132SHerbert Xu if (count > 0) 1138b096b544SLEROY Christophe to_talitos_ptr_ext_set(link_tbl_ptr + count - 1, 1139e345177dSChristophe Leroy DESC_PTR_LNKTBL_RET, 0); 114070bcaca7SLee Nipper 1141aeb4c132SHerbert Xu return count; 1142aeb4c132SHerbert Xu } 1143aeb4c132SHerbert Xu 11442b122730SLEROY Christophe static int talitos_sg_map_ext(struct device *dev, struct scatterlist *src, 1145246a87cdSLEROY Christophe unsigned int len, struct talitos_edesc *edesc, 11462b122730SLEROY Christophe struct talitos_ptr *ptr, int sg_count, 1147e345177dSChristophe Leroy unsigned int offset, int tbl_off, int elen, 1148416b8467SChristophe Leroy bool force, int align) 1149246a87cdSLEROY Christophe { 1150246a87cdSLEROY Christophe struct talitos_private *priv = dev_get_drvdata(dev); 1151246a87cdSLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 1152416b8467SChristophe Leroy int aligned_len = ALIGN(len, align); 1153246a87cdSLEROY Christophe 115487a81dceSLEROY Christophe if (!src) { 115587a81dceSLEROY Christophe to_talitos_ptr(ptr, 0, 0, is_sec1); 115687a81dceSLEROY Christophe return 1; 115787a81dceSLEROY Christophe } 11582b122730SLEROY Christophe to_talitos_ptr_ext_set(ptr, elen, is_sec1); 1159e345177dSChristophe Leroy if (sg_count == 1 && !force) { 1160416b8467SChristophe Leroy to_talitos_ptr(ptr, sg_dma_address(src) + offset, aligned_len, is_sec1); 1161246a87cdSLEROY Christophe return sg_count; 1162246a87cdSLEROY Christophe } 1163246a87cdSLEROY Christophe if (is_sec1) { 1164416b8467SChristophe Leroy to_talitos_ptr(ptr, edesc->dma_link_tbl + offset, aligned_len, is_sec1); 11656a1e8d14SLEROY Christophe return sg_count; 1166246a87cdSLEROY Christophe } 1167e345177dSChristophe Leroy sg_count = sg_to_link_tbl_offset(src, sg_count, offset, len, elen, 1168416b8467SChristophe Leroy &edesc->link_tbl[tbl_off], align); 1169e345177dSChristophe Leroy if (sg_count == 1 && !force) { 11706a1e8d14SLEROY Christophe /* Only one segment now, so no link tbl needed*/ 11716a1e8d14SLEROY Christophe copy_talitos_ptr(ptr, &edesc->link_tbl[tbl_off], is_sec1); 11726a1e8d14SLEROY Christophe return sg_count; 11736a1e8d14SLEROY Christophe } 1174246a87cdSLEROY Christophe to_talitos_ptr(ptr, edesc->dma_link_tbl + 1175416b8467SChristophe Leroy tbl_off * sizeof(struct talitos_ptr), aligned_len, is_sec1); 11766a1e8d14SLEROY Christophe to_talitos_ptr_ext_or(ptr, DESC_PTR_LNKTBL_JUMP, is_sec1); 11776a1e8d14SLEROY Christophe 11786a1e8d14SLEROY Christophe return sg_count; 1179246a87cdSLEROY Christophe } 1180246a87cdSLEROY Christophe 11812b122730SLEROY Christophe static int talitos_sg_map(struct device *dev, struct scatterlist *src, 11822b122730SLEROY Christophe unsigned int len, struct talitos_edesc *edesc, 11832b122730SLEROY Christophe struct talitos_ptr *ptr, int sg_count, 11842b122730SLEROY Christophe unsigned int offset, int tbl_off) 11852b122730SLEROY Christophe { 11862b122730SLEROY Christophe return talitos_sg_map_ext(dev, src, len, edesc, ptr, sg_count, offset, 1187416b8467SChristophe Leroy tbl_off, 0, false, 1); 11882b122730SLEROY Christophe } 11892b122730SLEROY Christophe 11909c4a7965SKim Phillips /* 11919c4a7965SKim Phillips * fill in and submit ipsec_esp descriptor 11929c4a7965SKim Phillips */ 119356af8cd4SLee Nipper static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq, 11947ede4c36SChristophe Leroy bool encrypt, 1195aeb4c132SHerbert Xu void (*callback)(struct device *dev, 11969c4a7965SKim Phillips struct talitos_desc *desc, 11979c4a7965SKim Phillips void *context, int error)) 11989c4a7965SKim Phillips { 11999c4a7965SKim Phillips struct crypto_aead *aead = crypto_aead_reqtfm(areq); 1200aeb4c132SHerbert Xu unsigned int authsize = crypto_aead_authsize(aead); 12019c4a7965SKim Phillips struct talitos_ctx *ctx = crypto_aead_ctx(aead); 12029c4a7965SKim Phillips struct device *dev = ctx->dev; 12039c4a7965SKim Phillips struct talitos_desc *desc = &edesc->desc; 12047ede4c36SChristophe Leroy unsigned int cryptlen = areq->cryptlen - (encrypt ? 0 : authsize); 1205e41256f1SKim Phillips unsigned int ivsize = crypto_aead_ivsize(aead); 1206aeb4c132SHerbert Xu int tbl_off = 0; 1207fa86a267SKim Phillips int sg_count, ret; 12082b122730SLEROY Christophe int elen = 0; 1209549bd8bcSLEROY Christophe bool sync_needed = false; 1210549bd8bcSLEROY Christophe struct talitos_private *priv = dev_get_drvdata(dev); 1211549bd8bcSLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 12129a655608SLEROY Christophe bool is_ipsec_esp = desc->hdr & DESC_HDR_TYPE_IPSEC_ESP; 12139a655608SLEROY Christophe struct talitos_ptr *civ_ptr = &desc->ptr[is_ipsec_esp ? 2 : 3]; 12149a655608SLEROY Christophe struct talitos_ptr *ckey_ptr = &desc->ptr[is_ipsec_esp ? 3 : 2]; 1215e345177dSChristophe Leroy dma_addr_t dma_icv = edesc->dma_link_tbl + edesc->dma_len - authsize; 12169c4a7965SKim Phillips 12179c4a7965SKim Phillips /* hmac key */ 12182e13ce08SLEROY Christophe to_talitos_ptr(&desc->ptr[0], ctx->dma_key, ctx->authkeylen, is_sec1); 121979fd31d3SHoria Geanta 1220549bd8bcSLEROY Christophe sg_count = edesc->src_nents ?: 1; 1221549bd8bcSLEROY Christophe if (is_sec1 && sg_count > 1) 1222549bd8bcSLEROY Christophe sg_copy_to_buffer(areq->src, sg_count, edesc->buf, 1223549bd8bcSLEROY Christophe areq->assoclen + cryptlen); 1224549bd8bcSLEROY Christophe else 1225549bd8bcSLEROY Christophe sg_count = dma_map_sg(dev, areq->src, sg_count, 1226549bd8bcSLEROY Christophe (areq->src == areq->dst) ? 1227549bd8bcSLEROY Christophe DMA_BIDIRECTIONAL : DMA_TO_DEVICE); 1228549bd8bcSLEROY Christophe 12299c4a7965SKim Phillips /* hmac data */ 1230549bd8bcSLEROY Christophe ret = talitos_sg_map(dev, areq->src, areq->assoclen, edesc, 1231549bd8bcSLEROY Christophe &desc->ptr[1], sg_count, 0, tbl_off); 123279fd31d3SHoria Geanta 1233549bd8bcSLEROY Christophe if (ret > 1) { 1234340ff60aSHoria Geant? tbl_off += ret; 1235549bd8bcSLEROY Christophe sync_needed = true; 123679fd31d3SHoria Geanta } 123779fd31d3SHoria Geanta 12389c4a7965SKim Phillips /* cipher iv */ 12399a655608SLEROY Christophe to_talitos_ptr(civ_ptr, edesc->iv_dma, ivsize, is_sec1); 12409c4a7965SKim Phillips 12419c4a7965SKim Phillips /* cipher key */ 12422e13ce08SLEROY Christophe to_talitos_ptr(ckey_ptr, ctx->dma_key + ctx->authkeylen, 12432e13ce08SLEROY Christophe ctx->enckeylen, is_sec1); 12449c4a7965SKim Phillips 12459c4a7965SKim Phillips /* 12469c4a7965SKim Phillips * cipher in 12479c4a7965SKim Phillips * map and adjust cipher len to aead request cryptlen. 12489c4a7965SKim Phillips * extent is bytes of HMAC postpended to ciphertext, 12499c4a7965SKim Phillips * typically 12 for ipsec 12509c4a7965SKim Phillips */ 12512b122730SLEROY Christophe if (is_ipsec_esp && (desc->hdr & DESC_HDR_MODE1_MDEU_CICV)) 12522b122730SLEROY Christophe elen = authsize; 1253549bd8bcSLEROY Christophe 12542b122730SLEROY Christophe ret = talitos_sg_map_ext(dev, areq->src, cryptlen, edesc, &desc->ptr[4], 1255e345177dSChristophe Leroy sg_count, areq->assoclen, tbl_off, elen, 1256416b8467SChristophe Leroy false, 1); 1257549bd8bcSLEROY Christophe 1258ec8c7d14SLEROY Christophe if (ret > 1) { 1259ec8c7d14SLEROY Christophe tbl_off += ret; 1260549bd8bcSLEROY Christophe sync_needed = true; 1261340ff60aSHoria Geant? } 12629c4a7965SKim Phillips 12639c4a7965SKim Phillips /* cipher out */ 1264549bd8bcSLEROY Christophe if (areq->src != areq->dst) { 1265549bd8bcSLEROY Christophe sg_count = edesc->dst_nents ? : 1; 1266549bd8bcSLEROY Christophe if (!is_sec1 || sg_count == 1) 1267549bd8bcSLEROY Christophe dma_map_sg(dev, areq->dst, sg_count, DMA_FROM_DEVICE); 1268549bd8bcSLEROY Christophe } 12699c4a7965SKim Phillips 1270e345177dSChristophe Leroy if (is_ipsec_esp && encrypt) 1271e345177dSChristophe Leroy elen = authsize; 1272e345177dSChristophe Leroy else 1273e345177dSChristophe Leroy elen = 0; 1274e345177dSChristophe Leroy ret = talitos_sg_map_ext(dev, areq->dst, cryptlen, edesc, &desc->ptr[5], 1275e345177dSChristophe Leroy sg_count, areq->assoclen, tbl_off, elen, 1276416b8467SChristophe Leroy is_ipsec_esp && !encrypt, 1); 1277e04a61beSLEROY Christophe tbl_off += ret; 1278549bd8bcSLEROY Christophe 1279e345177dSChristophe Leroy if (!encrypt && is_ipsec_esp) { 128079fd31d3SHoria Geanta struct talitos_ptr *tbl_ptr = &edesc->link_tbl[tbl_off]; 1281fe5720e2SKim Phillips 1282f3c85bc1SLee Nipper /* Add an entry to the link table for ICV data */ 1283e04a61beSLEROY Christophe to_talitos_ptr_ext_set(tbl_ptr - 1, 0, is_sec1); 1284e345177dSChristophe Leroy to_talitos_ptr_ext_set(tbl_ptr, DESC_PTR_LNKTBL_RET, is_sec1); 12859c4a7965SKim Phillips 12869c4a7965SKim Phillips /* icv data follows link tables */ 1287e345177dSChristophe Leroy to_talitos_ptr(tbl_ptr, dma_icv, authsize, is_sec1); 1288e345177dSChristophe Leroy to_talitos_ptr_ext_or(&desc->ptr[5], authsize, is_sec1); 1289e04a61beSLEROY Christophe sync_needed = true; 1290e345177dSChristophe Leroy } else if (!encrypt) { 1291e345177dSChristophe Leroy to_talitos_ptr(&desc->ptr[6], dma_icv, authsize, is_sec1); 1292e345177dSChristophe Leroy sync_needed = true; 1293e345177dSChristophe Leroy } else if (!is_ipsec_esp) { 1294e345177dSChristophe Leroy talitos_sg_map(dev, areq->dst, authsize, edesc, &desc->ptr[6], 1295e345177dSChristophe Leroy sg_count, areq->assoclen + cryptlen, tbl_off); 1296340ff60aSHoria Geant? } 12979c4a7965SKim Phillips 12989c4a7965SKim Phillips /* iv out */ 12999a655608SLEROY Christophe if (is_ipsec_esp) 1300a2b35aa8SLEROY Christophe map_single_talitos_ptr(dev, &desc->ptr[6], ivsize, ctx->iv, 13019c4a7965SKim Phillips DMA_FROM_DEVICE); 13029c4a7965SKim Phillips 1303549bd8bcSLEROY Christophe if (sync_needed) 1304549bd8bcSLEROY Christophe dma_sync_single_for_device(dev, edesc->dma_link_tbl, 1305549bd8bcSLEROY Christophe edesc->dma_len, 1306549bd8bcSLEROY Christophe DMA_BIDIRECTIONAL); 1307549bd8bcSLEROY Christophe 13085228f0f7SKim Phillips ret = talitos_submit(dev, ctx->ch, desc, callback, areq); 1309fa86a267SKim Phillips if (ret != -EINPROGRESS) { 13107ede4c36SChristophe Leroy ipsec_esp_unmap(dev, edesc, areq, encrypt); 1311fa86a267SKim Phillips kfree(edesc); 1312fa86a267SKim Phillips } 1313fa86a267SKim Phillips return ret; 13149c4a7965SKim Phillips } 13159c4a7965SKim Phillips 13169c4a7965SKim Phillips /* 131756af8cd4SLee Nipper * allocate and map the extended descriptor 13189c4a7965SKim Phillips */ 13194de9d0b5SLee Nipper static struct talitos_edesc *talitos_edesc_alloc(struct device *dev, 13204de9d0b5SLee Nipper struct scatterlist *src, 13214de9d0b5SLee Nipper struct scatterlist *dst, 132279fd31d3SHoria Geanta u8 *iv, 132379fd31d3SHoria Geanta unsigned int assoclen, 13244de9d0b5SLee Nipper unsigned int cryptlen, 13254de9d0b5SLee Nipper unsigned int authsize, 132679fd31d3SHoria Geanta unsigned int ivsize, 13274de9d0b5SLee Nipper int icv_stashing, 132862293a37SHoria Geanta u32 cryptoflags, 132962293a37SHoria Geanta bool encrypt) 13309c4a7965SKim Phillips { 133156af8cd4SLee Nipper struct talitos_edesc *edesc; 13326a1e8d14SLEROY Christophe int src_nents, dst_nents, alloc_len, dma_len, src_len, dst_len; 133379fd31d3SHoria Geanta dma_addr_t iv_dma = 0; 13344de9d0b5SLee Nipper gfp_t flags = cryptoflags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL : 1335586725f8SKim Phillips GFP_ATOMIC; 13366f65f6acSLEROY Christophe struct talitos_private *priv = dev_get_drvdata(dev); 13376f65f6acSLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 13386f65f6acSLEROY Christophe int max_len = is_sec1 ? TALITOS1_MAX_DATA_LEN : TALITOS2_MAX_DATA_LEN; 13399c4a7965SKim Phillips 13406f65f6acSLEROY Christophe if (cryptlen + authsize > max_len) { 13414de9d0b5SLee Nipper dev_err(dev, "length exceeds h/w max limit\n"); 13429c4a7965SKim Phillips return ERR_PTR(-EINVAL); 13439c4a7965SKim Phillips } 13449c4a7965SKim Phillips 134562293a37SHoria Geanta if (!dst || dst == src) { 13466a1e8d14SLEROY Christophe src_len = assoclen + cryptlen + authsize; 13476a1e8d14SLEROY Christophe src_nents = sg_nents_for_len(src, src_len); 13488e409fe1SLABBE Corentin if (src_nents < 0) { 13498e409fe1SLABBE Corentin dev_err(dev, "Invalid number of src SG.\n"); 1350c56c2e17SChristophe Leroy return ERR_PTR(-EINVAL); 13518e409fe1SLABBE Corentin } 13529c4a7965SKim Phillips src_nents = (src_nents == 1) ? 0 : src_nents; 135362293a37SHoria Geanta dst_nents = dst ? src_nents : 0; 13546a1e8d14SLEROY Christophe dst_len = 0; 135562293a37SHoria Geanta } else { /* dst && dst != src*/ 13566a1e8d14SLEROY Christophe src_len = assoclen + cryptlen + (encrypt ? 0 : authsize); 13576a1e8d14SLEROY Christophe src_nents = sg_nents_for_len(src, src_len); 13588e409fe1SLABBE Corentin if (src_nents < 0) { 13598e409fe1SLABBE Corentin dev_err(dev, "Invalid number of src SG.\n"); 1360c56c2e17SChristophe Leroy return ERR_PTR(-EINVAL); 13618e409fe1SLABBE Corentin } 136262293a37SHoria Geanta src_nents = (src_nents == 1) ? 0 : src_nents; 13636a1e8d14SLEROY Christophe dst_len = assoclen + cryptlen + (encrypt ? authsize : 0); 13646a1e8d14SLEROY Christophe dst_nents = sg_nents_for_len(dst, dst_len); 13658e409fe1SLABBE Corentin if (dst_nents < 0) { 13668e409fe1SLABBE Corentin dev_err(dev, "Invalid number of dst SG.\n"); 1367c56c2e17SChristophe Leroy return ERR_PTR(-EINVAL); 13688e409fe1SLABBE Corentin } 1369695ad589SLee Nipper dst_nents = (dst_nents == 1) ? 0 : dst_nents; 13709c4a7965SKim Phillips } 13719c4a7965SKim Phillips 13729c4a7965SKim Phillips /* 13739c4a7965SKim Phillips * allocate space for base edesc plus the link tables, 1374aeb4c132SHerbert Xu * allowing for two separate entries for AD and generated ICV (+ 2), 1375aeb4c132SHerbert Xu * and space for two sets of ICVs (stashed and generated) 13769c4a7965SKim Phillips */ 137756af8cd4SLee Nipper alloc_len = sizeof(struct talitos_edesc); 1378e345177dSChristophe Leroy if (src_nents || dst_nents || !encrypt) { 13796f65f6acSLEROY Christophe if (is_sec1) 13806a1e8d14SLEROY Christophe dma_len = (src_nents ? src_len : 0) + 1381e345177dSChristophe Leroy (dst_nents ? dst_len : 0) + authsize; 13826f65f6acSLEROY Christophe else 1383aeb4c132SHerbert Xu dma_len = (src_nents + dst_nents + 2) * 1384e345177dSChristophe Leroy sizeof(struct talitos_ptr) + authsize; 13859c4a7965SKim Phillips alloc_len += dma_len; 13869c4a7965SKim Phillips } else { 13879c4a7965SKim Phillips dma_len = 0; 13889c4a7965SKim Phillips } 1389e345177dSChristophe Leroy alloc_len += icv_stashing ? authsize : 0; 13909c4a7965SKim Phillips 139137b5e889SLEROY Christophe /* if its a ahash, add space for a second desc next to the first one */ 139237b5e889SLEROY Christophe if (is_sec1 && !dst) 139337b5e889SLEROY Christophe alloc_len += sizeof(struct talitos_desc); 13941bea445bSChristophe Leroy alloc_len += ivsize; 139537b5e889SLEROY Christophe 13968e613cecSHerbert Xu edesc = kmalloc(ALIGN(alloc_len, dma_get_cache_alignment()), flags); 1397c56c2e17SChristophe Leroy if (!edesc) 1398c56c2e17SChristophe Leroy return ERR_PTR(-ENOMEM); 13991bea445bSChristophe Leroy if (ivsize) { 14001bea445bSChristophe Leroy iv = memcpy(((u8 *)edesc) + alloc_len - ivsize, iv, ivsize); 1401c56c2e17SChristophe Leroy iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE); 14021bea445bSChristophe Leroy } 1403e4a647c4SLEROY Christophe memset(&edesc->desc, 0, sizeof(edesc->desc)); 14049c4a7965SKim Phillips 14059c4a7965SKim Phillips edesc->src_nents = src_nents; 14069c4a7965SKim Phillips edesc->dst_nents = dst_nents; 140779fd31d3SHoria Geanta edesc->iv_dma = iv_dma; 14089c4a7965SKim Phillips edesc->dma_len = dma_len; 140958cdbc6dSChristophe Leroy if (dma_len) 141058cdbc6dSChristophe Leroy edesc->dma_link_tbl = dma_map_single(dev, &edesc->link_tbl[0], 1411497f2e6bSLee Nipper edesc->dma_len, 1412497f2e6bSLee Nipper DMA_BIDIRECTIONAL); 141358cdbc6dSChristophe Leroy 14149c4a7965SKim Phillips return edesc; 14159c4a7965SKim Phillips } 14169c4a7965SKim Phillips 141779fd31d3SHoria Geanta static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv, 141862293a37SHoria Geanta int icv_stashing, bool encrypt) 14194de9d0b5SLee Nipper { 14204de9d0b5SLee Nipper struct crypto_aead *authenc = crypto_aead_reqtfm(areq); 1421aeb4c132SHerbert Xu unsigned int authsize = crypto_aead_authsize(authenc); 14224de9d0b5SLee Nipper struct talitos_ctx *ctx = crypto_aead_ctx(authenc); 142379fd31d3SHoria Geanta unsigned int ivsize = crypto_aead_ivsize(authenc); 14247ede4c36SChristophe Leroy unsigned int cryptlen = areq->cryptlen - (encrypt ? 0 : authsize); 14254de9d0b5SLee Nipper 1426aeb4c132SHerbert Xu return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst, 14277ede4c36SChristophe Leroy iv, areq->assoclen, cryptlen, 1428aeb4c132SHerbert Xu authsize, ivsize, icv_stashing, 142962293a37SHoria Geanta areq->base.flags, encrypt); 14304de9d0b5SLee Nipper } 14314de9d0b5SLee Nipper 143256af8cd4SLee Nipper static int aead_encrypt(struct aead_request *req) 14339c4a7965SKim Phillips { 14349c4a7965SKim Phillips struct crypto_aead *authenc = crypto_aead_reqtfm(req); 14359c4a7965SKim Phillips struct talitos_ctx *ctx = crypto_aead_ctx(authenc); 143656af8cd4SLee Nipper struct talitos_edesc *edesc; 14379c4a7965SKim Phillips 14389c4a7965SKim Phillips /* allocate extended descriptor */ 143962293a37SHoria Geanta edesc = aead_edesc_alloc(req, req->iv, 0, true); 14409c4a7965SKim Phillips if (IS_ERR(edesc)) 14419c4a7965SKim Phillips return PTR_ERR(edesc); 14429c4a7965SKim Phillips 14439c4a7965SKim Phillips /* set encrypt */ 144470bcaca7SLee Nipper edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT; 14459c4a7965SKim Phillips 14467ede4c36SChristophe Leroy return ipsec_esp(edesc, req, true, ipsec_esp_encrypt_done); 14479c4a7965SKim Phillips } 14489c4a7965SKim Phillips 144956af8cd4SLee Nipper static int aead_decrypt(struct aead_request *req) 14509c4a7965SKim Phillips { 14519c4a7965SKim Phillips struct crypto_aead *authenc = crypto_aead_reqtfm(req); 1452aeb4c132SHerbert Xu unsigned int authsize = crypto_aead_authsize(authenc); 14539c4a7965SKim Phillips struct talitos_ctx *ctx = crypto_aead_ctx(authenc); 1454fe5720e2SKim Phillips struct talitos_private *priv = dev_get_drvdata(ctx->dev); 145556af8cd4SLee Nipper struct talitos_edesc *edesc; 14569c4a7965SKim Phillips void *icvdata; 14579c4a7965SKim Phillips 14589c4a7965SKim Phillips /* allocate extended descriptor */ 145962293a37SHoria Geanta edesc = aead_edesc_alloc(req, req->iv, 1, false); 14609c4a7965SKim Phillips if (IS_ERR(edesc)) 14619c4a7965SKim Phillips return PTR_ERR(edesc); 14629c4a7965SKim Phillips 14634bbfb839SChristophe Leroy if ((edesc->desc.hdr & DESC_HDR_TYPE_IPSEC_ESP) && 14644bbfb839SChristophe Leroy (priv->features & TALITOS_FTR_HW_AUTH_CHECK) && 1465e938e465SKim Phillips ((!edesc->src_nents && !edesc->dst_nents) || 1466e938e465SKim Phillips priv->features & TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT)) { 1467fe5720e2SKim Phillips 1468fe5720e2SKim Phillips /* decrypt and check the ICV */ 1469e938e465SKim Phillips edesc->desc.hdr = ctx->desc_hdr_template | 1470e938e465SKim Phillips DESC_HDR_DIR_INBOUND | 1471fe5720e2SKim Phillips DESC_HDR_MODE1_MDEU_CICV; 1472fe5720e2SKim Phillips 1473fe5720e2SKim Phillips /* reset integrity check result bits */ 1474fe5720e2SKim Phillips 14757ede4c36SChristophe Leroy return ipsec_esp(edesc, req, false, 14767ede4c36SChristophe Leroy ipsec_esp_decrypt_hwauth_done); 1477e938e465SKim Phillips } 1478fe5720e2SKim Phillips 1479fe5720e2SKim Phillips /* Have to check the ICV with software */ 1480fe5720e2SKim Phillips edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND; 1481fe5720e2SKim Phillips 14829c4a7965SKim Phillips /* stash incoming ICV for later cmp with ICV generated by the h/w */ 1483e345177dSChristophe Leroy icvdata = edesc->buf + edesc->dma_len; 14849c4a7965SKim Phillips 1485eae55a58SChristophe Leroy sg_pcopy_to_buffer(req->src, edesc->src_nents ? : 1, icvdata, authsize, 1486eae55a58SChristophe Leroy req->assoclen + req->cryptlen - authsize); 14879c4a7965SKim Phillips 14887ede4c36SChristophe Leroy return ipsec_esp(edesc, req, false, ipsec_esp_decrypt_swauth_done); 14899c4a7965SKim Phillips } 14909c4a7965SKim Phillips 1491373960d7SArd Biesheuvel static int skcipher_setkey(struct crypto_skcipher *cipher, 14924de9d0b5SLee Nipper const u8 *key, unsigned int keylen) 14934de9d0b5SLee Nipper { 1494373960d7SArd Biesheuvel struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher); 14952e13ce08SLEROY Christophe struct device *dev = ctx->dev; 1496f384cdc4SLEROY Christophe 14972e13ce08SLEROY Christophe if (ctx->keylen) 14982e13ce08SLEROY Christophe dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE); 14992e13ce08SLEROY Christophe 15004de9d0b5SLee Nipper memcpy(&ctx->key, key, keylen); 15014de9d0b5SLee Nipper ctx->keylen = keylen; 15024de9d0b5SLee Nipper 15032e13ce08SLEROY Christophe ctx->dma_key = dma_map_single(dev, ctx->key, keylen, DMA_TO_DEVICE); 15042e13ce08SLEROY Christophe 15054de9d0b5SLee Nipper return 0; 15064de9d0b5SLee Nipper } 15074de9d0b5SLee Nipper 1508373960d7SArd Biesheuvel static int skcipher_des_setkey(struct crypto_skcipher *cipher, 1509ef7c5c85SHerbert Xu const u8 *key, unsigned int keylen) 1510ef7c5c85SHerbert Xu { 1511373960d7SArd Biesheuvel return verify_skcipher_des_key(cipher, key) ?: 1512373960d7SArd Biesheuvel skcipher_setkey(cipher, key, keylen); 1513ef7c5c85SHerbert Xu } 1514ef7c5c85SHerbert Xu 1515373960d7SArd Biesheuvel static int skcipher_des3_setkey(struct crypto_skcipher *cipher, 1516ef7c5c85SHerbert Xu const u8 *key, unsigned int keylen) 1517ef7c5c85SHerbert Xu { 1518373960d7SArd Biesheuvel return verify_skcipher_des3_key(cipher, key) ?: 1519373960d7SArd Biesheuvel skcipher_setkey(cipher, key, keylen); 1520ef7c5c85SHerbert Xu } 1521ef7c5c85SHerbert Xu 1522373960d7SArd Biesheuvel static int skcipher_aes_setkey(struct crypto_skcipher *cipher, 15231ba34e71SChristophe Leroy const u8 *key, unsigned int keylen) 15241ba34e71SChristophe Leroy { 15251ba34e71SChristophe Leroy if (keylen == AES_KEYSIZE_128 || keylen == AES_KEYSIZE_192 || 15261ba34e71SChristophe Leroy keylen == AES_KEYSIZE_256) 1527373960d7SArd Biesheuvel return skcipher_setkey(cipher, key, keylen); 15281ba34e71SChristophe Leroy 15291ba34e71SChristophe Leroy return -EINVAL; 15301ba34e71SChristophe Leroy } 15311ba34e71SChristophe Leroy 15324de9d0b5SLee Nipper static void common_nonsnoop_unmap(struct device *dev, 15334de9d0b5SLee Nipper struct talitos_edesc *edesc, 1534373960d7SArd Biesheuvel struct skcipher_request *areq) 15354de9d0b5SLee Nipper { 15364de9d0b5SLee Nipper unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE); 1537032d197eSLEROY Christophe 1538373960d7SArd Biesheuvel talitos_sg_unmap(dev, edesc, areq->src, areq->dst, areq->cryptlen, 0); 15394de9d0b5SLee Nipper unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1], DMA_TO_DEVICE); 15404de9d0b5SLee Nipper 15414de9d0b5SLee Nipper if (edesc->dma_len) 15424de9d0b5SLee Nipper dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len, 15434de9d0b5SLee Nipper DMA_BIDIRECTIONAL); 15444de9d0b5SLee Nipper } 15454de9d0b5SLee Nipper 1546373960d7SArd Biesheuvel static void skcipher_done(struct device *dev, 15474de9d0b5SLee Nipper struct talitos_desc *desc, void *context, 15484de9d0b5SLee Nipper int err) 15494de9d0b5SLee Nipper { 1550373960d7SArd Biesheuvel struct skcipher_request *areq = context; 1551373960d7SArd Biesheuvel struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(areq); 1552373960d7SArd Biesheuvel struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher); 1553373960d7SArd Biesheuvel unsigned int ivsize = crypto_skcipher_ivsize(cipher); 155419bbbc63SKim Phillips struct talitos_edesc *edesc; 155519bbbc63SKim Phillips 155619bbbc63SKim Phillips edesc = container_of(desc, struct talitos_edesc, desc); 15574de9d0b5SLee Nipper 15584de9d0b5SLee Nipper common_nonsnoop_unmap(dev, edesc, areq); 1559373960d7SArd Biesheuvel memcpy(areq->iv, ctx->iv, ivsize); 15604de9d0b5SLee Nipper 15614de9d0b5SLee Nipper kfree(edesc); 15624de9d0b5SLee Nipper 1563*234650bdSHerbert Xu skcipher_request_complete(areq, err); 15644de9d0b5SLee Nipper } 15654de9d0b5SLee Nipper 15664de9d0b5SLee Nipper static int common_nonsnoop(struct talitos_edesc *edesc, 1567373960d7SArd Biesheuvel struct skcipher_request *areq, 15684de9d0b5SLee Nipper void (*callback) (struct device *dev, 15694de9d0b5SLee Nipper struct talitos_desc *desc, 15704de9d0b5SLee Nipper void *context, int error)) 15714de9d0b5SLee Nipper { 1572373960d7SArd Biesheuvel struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(areq); 1573373960d7SArd Biesheuvel struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher); 15744de9d0b5SLee Nipper struct device *dev = ctx->dev; 15754de9d0b5SLee Nipper struct talitos_desc *desc = &edesc->desc; 1576373960d7SArd Biesheuvel unsigned int cryptlen = areq->cryptlen; 1577373960d7SArd Biesheuvel unsigned int ivsize = crypto_skcipher_ivsize(cipher); 15784de9d0b5SLee Nipper int sg_count, ret; 15796a1e8d14SLEROY Christophe bool sync_needed = false; 1580922f9dc8SLEROY Christophe struct talitos_private *priv = dev_get_drvdata(dev); 1581922f9dc8SLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 1582416b8467SChristophe Leroy bool is_ctr = (desc->hdr & DESC_HDR_SEL0_MASK) == DESC_HDR_SEL0_AESU && 1583416b8467SChristophe Leroy (desc->hdr & DESC_HDR_MODE0_AESU_MASK) == DESC_HDR_MODE0_AESU_CTR; 15844de9d0b5SLee Nipper 15854de9d0b5SLee Nipper /* first DWORD empty */ 15864de9d0b5SLee Nipper 15874de9d0b5SLee Nipper /* cipher iv */ 1588da9de146SLEROY Christophe to_talitos_ptr(&desc->ptr[1], edesc->iv_dma, ivsize, is_sec1); 15894de9d0b5SLee Nipper 15904de9d0b5SLee Nipper /* cipher key */ 15912e13ce08SLEROY Christophe to_talitos_ptr(&desc->ptr[2], ctx->dma_key, ctx->keylen, is_sec1); 15924de9d0b5SLee Nipper 15936a1e8d14SLEROY Christophe sg_count = edesc->src_nents ?: 1; 15946a1e8d14SLEROY Christophe if (is_sec1 && sg_count > 1) 15956a1e8d14SLEROY Christophe sg_copy_to_buffer(areq->src, sg_count, edesc->buf, 15966a1e8d14SLEROY Christophe cryptlen); 15976a1e8d14SLEROY Christophe else 15986a1e8d14SLEROY Christophe sg_count = dma_map_sg(dev, areq->src, sg_count, 15996a1e8d14SLEROY Christophe (areq->src == areq->dst) ? 16006a1e8d14SLEROY Christophe DMA_BIDIRECTIONAL : DMA_TO_DEVICE); 16014de9d0b5SLee Nipper /* 16024de9d0b5SLee Nipper * cipher in 16034de9d0b5SLee Nipper */ 1604416b8467SChristophe Leroy sg_count = talitos_sg_map_ext(dev, areq->src, cryptlen, edesc, &desc->ptr[3], 1605416b8467SChristophe Leroy sg_count, 0, 0, 0, false, is_ctr ? 16 : 1); 16066a1e8d14SLEROY Christophe if (sg_count > 1) 16076a1e8d14SLEROY Christophe sync_needed = true; 16084de9d0b5SLee Nipper 16094de9d0b5SLee Nipper /* cipher out */ 16106a1e8d14SLEROY Christophe if (areq->src != areq->dst) { 16116a1e8d14SLEROY Christophe sg_count = edesc->dst_nents ? : 1; 16126a1e8d14SLEROY Christophe if (!is_sec1 || sg_count == 1) 16136a1e8d14SLEROY Christophe dma_map_sg(dev, areq->dst, sg_count, DMA_FROM_DEVICE); 16146a1e8d14SLEROY Christophe } 16156a1e8d14SLEROY Christophe 16166a1e8d14SLEROY Christophe ret = talitos_sg_map(dev, areq->dst, cryptlen, edesc, &desc->ptr[4], 16176a1e8d14SLEROY Christophe sg_count, 0, (edesc->src_nents + 1)); 16186a1e8d14SLEROY Christophe if (ret > 1) 16196a1e8d14SLEROY Christophe sync_needed = true; 16204de9d0b5SLee Nipper 16214de9d0b5SLee Nipper /* iv out */ 1622a2b35aa8SLEROY Christophe map_single_talitos_ptr(dev, &desc->ptr[5], ivsize, ctx->iv, 16234de9d0b5SLee Nipper DMA_FROM_DEVICE); 16244de9d0b5SLee Nipper 16254de9d0b5SLee Nipper /* last DWORD empty */ 16264de9d0b5SLee Nipper 16276a1e8d14SLEROY Christophe if (sync_needed) 16286a1e8d14SLEROY Christophe dma_sync_single_for_device(dev, edesc->dma_link_tbl, 16296a1e8d14SLEROY Christophe edesc->dma_len, DMA_BIDIRECTIONAL); 16306a1e8d14SLEROY Christophe 16315228f0f7SKim Phillips ret = talitos_submit(dev, ctx->ch, desc, callback, areq); 16324de9d0b5SLee Nipper if (ret != -EINPROGRESS) { 16334de9d0b5SLee Nipper common_nonsnoop_unmap(dev, edesc, areq); 16344de9d0b5SLee Nipper kfree(edesc); 16354de9d0b5SLee Nipper } 16364de9d0b5SLee Nipper return ret; 16374de9d0b5SLee Nipper } 16384de9d0b5SLee Nipper 1639373960d7SArd Biesheuvel static struct talitos_edesc *skcipher_edesc_alloc(struct skcipher_request * 164062293a37SHoria Geanta areq, bool encrypt) 16414de9d0b5SLee Nipper { 1642373960d7SArd Biesheuvel struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(areq); 1643373960d7SArd Biesheuvel struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher); 1644373960d7SArd Biesheuvel unsigned int ivsize = crypto_skcipher_ivsize(cipher); 16454de9d0b5SLee Nipper 1646aeb4c132SHerbert Xu return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst, 1647373960d7SArd Biesheuvel areq->iv, 0, areq->cryptlen, 0, ivsize, 0, 164862293a37SHoria Geanta areq->base.flags, encrypt); 16494de9d0b5SLee Nipper } 16504de9d0b5SLee Nipper 1651373960d7SArd Biesheuvel static int skcipher_encrypt(struct skcipher_request *areq) 16524de9d0b5SLee Nipper { 1653373960d7SArd Biesheuvel struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(areq); 1654373960d7SArd Biesheuvel struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher); 16554de9d0b5SLee Nipper struct talitos_edesc *edesc; 1656ee483d32SChristophe Leroy unsigned int blocksize = 1657373960d7SArd Biesheuvel crypto_tfm_alg_blocksize(crypto_skcipher_tfm(cipher)); 1658ee483d32SChristophe Leroy 1659373960d7SArd Biesheuvel if (!areq->cryptlen) 1660ee483d32SChristophe Leroy return 0; 1661ee483d32SChristophe Leroy 1662373960d7SArd Biesheuvel if (areq->cryptlen % blocksize) 1663ee483d32SChristophe Leroy return -EINVAL; 16644de9d0b5SLee Nipper 16654de9d0b5SLee Nipper /* allocate extended descriptor */ 1666373960d7SArd Biesheuvel edesc = skcipher_edesc_alloc(areq, true); 16674de9d0b5SLee Nipper if (IS_ERR(edesc)) 16684de9d0b5SLee Nipper return PTR_ERR(edesc); 16694de9d0b5SLee Nipper 16704de9d0b5SLee Nipper /* set encrypt */ 16714de9d0b5SLee Nipper edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT; 16724de9d0b5SLee Nipper 1673373960d7SArd Biesheuvel return common_nonsnoop(edesc, areq, skcipher_done); 16744de9d0b5SLee Nipper } 16754de9d0b5SLee Nipper 1676373960d7SArd Biesheuvel static int skcipher_decrypt(struct skcipher_request *areq) 16774de9d0b5SLee Nipper { 1678373960d7SArd Biesheuvel struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(areq); 1679373960d7SArd Biesheuvel struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher); 16804de9d0b5SLee Nipper struct talitos_edesc *edesc; 1681ee483d32SChristophe Leroy unsigned int blocksize = 1682373960d7SArd Biesheuvel crypto_tfm_alg_blocksize(crypto_skcipher_tfm(cipher)); 1683ee483d32SChristophe Leroy 1684373960d7SArd Biesheuvel if (!areq->cryptlen) 1685ee483d32SChristophe Leroy return 0; 1686ee483d32SChristophe Leroy 1687373960d7SArd Biesheuvel if (areq->cryptlen % blocksize) 1688ee483d32SChristophe Leroy return -EINVAL; 16894de9d0b5SLee Nipper 16904de9d0b5SLee Nipper /* allocate extended descriptor */ 1691373960d7SArd Biesheuvel edesc = skcipher_edesc_alloc(areq, false); 16924de9d0b5SLee Nipper if (IS_ERR(edesc)) 16934de9d0b5SLee Nipper return PTR_ERR(edesc); 16944de9d0b5SLee Nipper 16954de9d0b5SLee Nipper edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND; 16964de9d0b5SLee Nipper 1697373960d7SArd Biesheuvel return common_nonsnoop(edesc, areq, skcipher_done); 16984de9d0b5SLee Nipper } 16994de9d0b5SLee Nipper 1700497f2e6bSLee Nipper static void common_nonsnoop_hash_unmap(struct device *dev, 1701497f2e6bSLee Nipper struct talitos_edesc *edesc, 1702497f2e6bSLee Nipper struct ahash_request *areq) 1703497f2e6bSLee Nipper { 1704497f2e6bSLee Nipper struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 17057a6eda5bSChristophe Leroy struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 1706ad4cd51fSLEROY Christophe struct talitos_private *priv = dev_get_drvdata(dev); 1707ad4cd51fSLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 1708ad4cd51fSLEROY Christophe struct talitos_desc *desc = &edesc->desc; 170958cdbc6dSChristophe Leroy struct talitos_desc *desc2 = (struct talitos_desc *) 171058cdbc6dSChristophe Leroy (edesc->buf + edesc->dma_len); 1711ad4cd51fSLEROY Christophe 17126ae7a8b1Sjianchunfu unmap_single_talitos_ptr(dev, &desc->ptr[5], DMA_FROM_DEVICE); 1713ad4cd51fSLEROY Christophe if (desc->next_desc && 1714ad4cd51fSLEROY Christophe desc->ptr[5].ptr != desc2->ptr[5].ptr) 1715ad4cd51fSLEROY Christophe unmap_single_talitos_ptr(dev, &desc2->ptr[5], DMA_FROM_DEVICE); 17167a6eda5bSChristophe Leroy if (req_ctx->last) 17177a6eda5bSChristophe Leroy memcpy(areq->result, req_ctx->hw_context, 17187a6eda5bSChristophe Leroy crypto_ahash_digestsize(tfm)); 1719497f2e6bSLee Nipper 172058cdbc6dSChristophe Leroy if (req_ctx->psrc) 17216a1e8d14SLEROY Christophe talitos_sg_unmap(dev, edesc, req_ctx->psrc, NULL, 0, 0); 1722032d197eSLEROY Christophe 1723ad4cd51fSLEROY Christophe /* When using hashctx-in, must unmap it. */ 17246ae7a8b1Sjianchunfu if (from_talitos_ptr_len(&desc->ptr[1], is_sec1)) 17256ae7a8b1Sjianchunfu unmap_single_talitos_ptr(dev, &desc->ptr[1], 1726ad4cd51fSLEROY Christophe DMA_TO_DEVICE); 1727ad4cd51fSLEROY Christophe else if (desc->next_desc) 1728ad4cd51fSLEROY Christophe unmap_single_talitos_ptr(dev, &desc2->ptr[1], 1729ad4cd51fSLEROY Christophe DMA_TO_DEVICE); 1730ad4cd51fSLEROY Christophe 1731ad4cd51fSLEROY Christophe if (is_sec1 && req_ctx->nbuf) 1732ad4cd51fSLEROY Christophe unmap_single_talitos_ptr(dev, &desc->ptr[3], 1733ad4cd51fSLEROY Christophe DMA_TO_DEVICE); 1734ad4cd51fSLEROY Christophe 1735497f2e6bSLee Nipper if (edesc->dma_len) 1736497f2e6bSLee Nipper dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len, 1737497f2e6bSLee Nipper DMA_BIDIRECTIONAL); 1738497f2e6bSLee Nipper 17396ae7a8b1Sjianchunfu if (desc->next_desc) 17406ae7a8b1Sjianchunfu dma_unmap_single(dev, be32_to_cpu(desc->next_desc), 174137b5e889SLEROY Christophe TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL); 1742497f2e6bSLee Nipper } 1743497f2e6bSLee Nipper 1744497f2e6bSLee Nipper static void ahash_done(struct device *dev, 1745497f2e6bSLee Nipper struct talitos_desc *desc, void *context, 1746497f2e6bSLee Nipper int err) 1747497f2e6bSLee Nipper { 1748497f2e6bSLee Nipper struct ahash_request *areq = context; 1749497f2e6bSLee Nipper struct talitos_edesc *edesc = 1750497f2e6bSLee Nipper container_of(desc, struct talitos_edesc, desc); 1751497f2e6bSLee Nipper struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 1752497f2e6bSLee Nipper 1753497f2e6bSLee Nipper if (!req_ctx->last && req_ctx->to_hash_later) { 1754497f2e6bSLee Nipper /* Position any partial block for next update/final/finup */ 17553c0dd190SLEROY Christophe req_ctx->buf_idx = (req_ctx->buf_idx + 1) & 1; 17565e833bc4SLee Nipper req_ctx->nbuf = req_ctx->to_hash_later; 1757497f2e6bSLee Nipper } 1758497f2e6bSLee Nipper common_nonsnoop_hash_unmap(dev, edesc, areq); 1759497f2e6bSLee Nipper 1760497f2e6bSLee Nipper kfree(edesc); 1761497f2e6bSLee Nipper 1762*234650bdSHerbert Xu ahash_request_complete(areq, err); 1763497f2e6bSLee Nipper } 1764497f2e6bSLee Nipper 17652d02905eSLEROY Christophe /* 17662d02905eSLEROY Christophe * SEC1 doesn't like hashing of 0 sized message, so we do the padding 17672d02905eSLEROY Christophe * ourself and submit a padded block 17682d02905eSLEROY Christophe */ 17695b2cf268SLEROY Christophe static void talitos_handle_buggy_hash(struct talitos_ctx *ctx, 17702d02905eSLEROY Christophe struct talitos_edesc *edesc, 17712d02905eSLEROY Christophe struct talitos_ptr *ptr) 17722d02905eSLEROY Christophe { 17732d02905eSLEROY Christophe static u8 padded_hash[64] = { 17742d02905eSLEROY Christophe 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17752d02905eSLEROY Christophe 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17762d02905eSLEROY Christophe 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17772d02905eSLEROY Christophe 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17782d02905eSLEROY Christophe }; 17792d02905eSLEROY Christophe 17802d02905eSLEROY Christophe pr_err_once("Bug in SEC1, padding ourself\n"); 17812d02905eSLEROY Christophe edesc->desc.hdr &= ~DESC_HDR_MODE0_MDEU_PAD; 17822d02905eSLEROY Christophe map_single_talitos_ptr(ctx->dev, ptr, sizeof(padded_hash), 17832d02905eSLEROY Christophe (char *)padded_hash, DMA_TO_DEVICE); 17842d02905eSLEROY Christophe } 17852d02905eSLEROY Christophe 1786497f2e6bSLee Nipper static int common_nonsnoop_hash(struct talitos_edesc *edesc, 1787497f2e6bSLee Nipper struct ahash_request *areq, unsigned int length, 1788497f2e6bSLee Nipper void (*callback) (struct device *dev, 1789497f2e6bSLee Nipper struct talitos_desc *desc, 1790497f2e6bSLee Nipper void *context, int error)) 1791497f2e6bSLee Nipper { 1792497f2e6bSLee Nipper struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 1793497f2e6bSLee Nipper struct talitos_ctx *ctx = crypto_ahash_ctx(tfm); 1794497f2e6bSLee Nipper struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 1795497f2e6bSLee Nipper struct device *dev = ctx->dev; 1796497f2e6bSLee Nipper struct talitos_desc *desc = &edesc->desc; 1797032d197eSLEROY Christophe int ret; 17986a1e8d14SLEROY Christophe bool sync_needed = false; 1799922f9dc8SLEROY Christophe struct talitos_private *priv = dev_get_drvdata(dev); 1800922f9dc8SLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 18016a1e8d14SLEROY Christophe int sg_count; 1802497f2e6bSLee Nipper 1803497f2e6bSLee Nipper /* first DWORD empty */ 1804497f2e6bSLee Nipper 180560f208d7SKim Phillips /* hash context in */ 180660f208d7SKim Phillips if (!req_ctx->first || req_ctx->swinit) { 18076a4967c3SLEROY Christophe map_single_talitos_ptr_nosync(dev, &desc->ptr[1], 1808ad4cd51fSLEROY Christophe req_ctx->hw_context_size, 18096a4967c3SLEROY Christophe req_ctx->hw_context, 1810ad4cd51fSLEROY Christophe DMA_TO_DEVICE); 181160f208d7SKim Phillips req_ctx->swinit = 0; 1812afd62fa2SLEROY Christophe } 1813497f2e6bSLee Nipper /* Indicate next op is not the first. */ 1814497f2e6bSLee Nipper req_ctx->first = 0; 1815497f2e6bSLee Nipper 1816497f2e6bSLee Nipper /* HMAC key */ 1817497f2e6bSLee Nipper if (ctx->keylen) 18182e13ce08SLEROY Christophe to_talitos_ptr(&desc->ptr[2], ctx->dma_key, ctx->keylen, 18192e13ce08SLEROY Christophe is_sec1); 1820497f2e6bSLee Nipper 182137b5e889SLEROY Christophe if (is_sec1 && req_ctx->nbuf) 182237b5e889SLEROY Christophe length -= req_ctx->nbuf; 182337b5e889SLEROY Christophe 18246a1e8d14SLEROY Christophe sg_count = edesc->src_nents ?: 1; 18256a1e8d14SLEROY Christophe if (is_sec1 && sg_count > 1) 182658cdbc6dSChristophe Leroy sg_copy_to_buffer(req_ctx->psrc, sg_count, edesc->buf, length); 182737b5e889SLEROY Christophe else if (length) 18286a1e8d14SLEROY Christophe sg_count = dma_map_sg(dev, req_ctx->psrc, sg_count, 18296a1e8d14SLEROY Christophe DMA_TO_DEVICE); 1830497f2e6bSLee Nipper /* 1831497f2e6bSLee Nipper * data in 1832497f2e6bSLee Nipper */ 183337b5e889SLEROY Christophe if (is_sec1 && req_ctx->nbuf) { 1834ad4cd51fSLEROY Christophe map_single_talitos_ptr(dev, &desc->ptr[3], req_ctx->nbuf, 1835ad4cd51fSLEROY Christophe req_ctx->buf[req_ctx->buf_idx], 1836ad4cd51fSLEROY Christophe DMA_TO_DEVICE); 183737b5e889SLEROY Christophe } else { 18386a1e8d14SLEROY Christophe sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc, 183958cdbc6dSChristophe Leroy &desc->ptr[3], sg_count, 0, 0); 18406a1e8d14SLEROY Christophe if (sg_count > 1) 18416a1e8d14SLEROY Christophe sync_needed = true; 184237b5e889SLEROY Christophe } 1843497f2e6bSLee Nipper 1844497f2e6bSLee Nipper /* fifth DWORD empty */ 1845497f2e6bSLee Nipper 1846497f2e6bSLee Nipper /* hash/HMAC out -or- hash context out */ 1847497f2e6bSLee Nipper if (req_ctx->last) 1848497f2e6bSLee Nipper map_single_talitos_ptr(dev, &desc->ptr[5], 1849497f2e6bSLee Nipper crypto_ahash_digestsize(tfm), 18507a6eda5bSChristophe Leroy req_ctx->hw_context, DMA_FROM_DEVICE); 1851497f2e6bSLee Nipper else 18526a4967c3SLEROY Christophe map_single_talitos_ptr_nosync(dev, &desc->ptr[5], 1853ad4cd51fSLEROY Christophe req_ctx->hw_context_size, 18546a4967c3SLEROY Christophe req_ctx->hw_context, 18556a4967c3SLEROY Christophe DMA_FROM_DEVICE); 1856497f2e6bSLee Nipper 1857497f2e6bSLee Nipper /* last DWORD empty */ 1858497f2e6bSLee Nipper 18592d02905eSLEROY Christophe if (is_sec1 && from_talitos_ptr_len(&desc->ptr[3], true) == 0) 18602d02905eSLEROY Christophe talitos_handle_buggy_hash(ctx, edesc, &desc->ptr[3]); 18612d02905eSLEROY Christophe 186237b5e889SLEROY Christophe if (is_sec1 && req_ctx->nbuf && length) { 186358cdbc6dSChristophe Leroy struct talitos_desc *desc2 = (struct talitos_desc *) 186458cdbc6dSChristophe Leroy (edesc->buf + edesc->dma_len); 186537b5e889SLEROY Christophe dma_addr_t next_desc; 186637b5e889SLEROY Christophe 186737b5e889SLEROY Christophe memset(desc2, 0, sizeof(*desc2)); 186837b5e889SLEROY Christophe desc2->hdr = desc->hdr; 186937b5e889SLEROY Christophe desc2->hdr &= ~DESC_HDR_MODE0_MDEU_INIT; 187037b5e889SLEROY Christophe desc2->hdr1 = desc2->hdr; 187137b5e889SLEROY Christophe desc->hdr &= ~DESC_HDR_MODE0_MDEU_PAD; 187237b5e889SLEROY Christophe desc->hdr |= DESC_HDR_MODE0_MDEU_CONT; 187337b5e889SLEROY Christophe desc->hdr &= ~DESC_HDR_DONE_NOTIFY; 187437b5e889SLEROY Christophe 1875ad4cd51fSLEROY Christophe if (desc->ptr[1].ptr) 1876ad4cd51fSLEROY Christophe copy_talitos_ptr(&desc2->ptr[1], &desc->ptr[1], 1877ad4cd51fSLEROY Christophe is_sec1); 1878ad4cd51fSLEROY Christophe else 18796a4967c3SLEROY Christophe map_single_talitos_ptr_nosync(dev, &desc2->ptr[1], 1880ad4cd51fSLEROY Christophe req_ctx->hw_context_size, 1881ad4cd51fSLEROY Christophe req_ctx->hw_context, 1882ad4cd51fSLEROY Christophe DMA_TO_DEVICE); 188337b5e889SLEROY Christophe copy_talitos_ptr(&desc2->ptr[2], &desc->ptr[2], is_sec1); 188437b5e889SLEROY Christophe sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc, 188558cdbc6dSChristophe Leroy &desc2->ptr[3], sg_count, 0, 0); 188637b5e889SLEROY Christophe if (sg_count > 1) 188737b5e889SLEROY Christophe sync_needed = true; 188837b5e889SLEROY Christophe copy_talitos_ptr(&desc2->ptr[5], &desc->ptr[5], is_sec1); 188937b5e889SLEROY Christophe if (req_ctx->last) 18906a4967c3SLEROY Christophe map_single_talitos_ptr_nosync(dev, &desc->ptr[5], 1891ad4cd51fSLEROY Christophe req_ctx->hw_context_size, 1892ad4cd51fSLEROY Christophe req_ctx->hw_context, 1893ad4cd51fSLEROY Christophe DMA_FROM_DEVICE); 189437b5e889SLEROY Christophe 189537b5e889SLEROY Christophe next_desc = dma_map_single(dev, &desc2->hdr1, TALITOS_DESC_SIZE, 189637b5e889SLEROY Christophe DMA_BIDIRECTIONAL); 189737b5e889SLEROY Christophe desc->next_desc = cpu_to_be32(next_desc); 189837b5e889SLEROY Christophe } 189937b5e889SLEROY Christophe 19006a1e8d14SLEROY Christophe if (sync_needed) 19016a1e8d14SLEROY Christophe dma_sync_single_for_device(dev, edesc->dma_link_tbl, 19026a1e8d14SLEROY Christophe edesc->dma_len, DMA_BIDIRECTIONAL); 19036a1e8d14SLEROY Christophe 19045228f0f7SKim Phillips ret = talitos_submit(dev, ctx->ch, desc, callback, areq); 1905497f2e6bSLee Nipper if (ret != -EINPROGRESS) { 1906497f2e6bSLee Nipper common_nonsnoop_hash_unmap(dev, edesc, areq); 1907497f2e6bSLee Nipper kfree(edesc); 1908497f2e6bSLee Nipper } 1909497f2e6bSLee Nipper return ret; 1910497f2e6bSLee Nipper } 1911497f2e6bSLee Nipper 1912497f2e6bSLee Nipper static struct talitos_edesc *ahash_edesc_alloc(struct ahash_request *areq, 1913497f2e6bSLee Nipper unsigned int nbytes) 1914497f2e6bSLee Nipper { 1915497f2e6bSLee Nipper struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 1916497f2e6bSLee Nipper struct talitos_ctx *ctx = crypto_ahash_ctx(tfm); 1917497f2e6bSLee Nipper struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 191837b5e889SLEROY Christophe struct talitos_private *priv = dev_get_drvdata(ctx->dev); 191937b5e889SLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 192037b5e889SLEROY Christophe 192137b5e889SLEROY Christophe if (is_sec1) 192237b5e889SLEROY Christophe nbytes -= req_ctx->nbuf; 1923497f2e6bSLee Nipper 1924aeb4c132SHerbert Xu return talitos_edesc_alloc(ctx->dev, req_ctx->psrc, NULL, NULL, 0, 192562293a37SHoria Geanta nbytes, 0, 0, 0, areq->base.flags, false); 1926497f2e6bSLee Nipper } 1927497f2e6bSLee Nipper 1928497f2e6bSLee Nipper static int ahash_init(struct ahash_request *areq) 1929497f2e6bSLee Nipper { 1930497f2e6bSLee Nipper struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 19316a4967c3SLEROY Christophe struct talitos_ctx *ctx = crypto_ahash_ctx(tfm); 19326a4967c3SLEROY Christophe struct device *dev = ctx->dev; 1933497f2e6bSLee Nipper struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 193449f9783bSLEROY Christophe unsigned int size; 19356a4967c3SLEROY Christophe dma_addr_t dma; 1936497f2e6bSLee Nipper 1937497f2e6bSLee Nipper /* Initialize the context */ 19383c0dd190SLEROY Christophe req_ctx->buf_idx = 0; 19395e833bc4SLee Nipper req_ctx->nbuf = 0; 194060f208d7SKim Phillips req_ctx->first = 1; /* first indicates h/w must init its context */ 194160f208d7SKim Phillips req_ctx->swinit = 0; /* assume h/w init of context */ 194249f9783bSLEROY Christophe size = (crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE) 1943497f2e6bSLee Nipper ? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256 1944497f2e6bSLee Nipper : TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512; 194549f9783bSLEROY Christophe req_ctx->hw_context_size = size; 1946497f2e6bSLee Nipper 19476a4967c3SLEROY Christophe dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size, 19486a4967c3SLEROY Christophe DMA_TO_DEVICE); 19496a4967c3SLEROY Christophe dma_unmap_single(dev, dma, req_ctx->hw_context_size, DMA_TO_DEVICE); 19506a4967c3SLEROY Christophe 1951497f2e6bSLee Nipper return 0; 1952497f2e6bSLee Nipper } 1953497f2e6bSLee Nipper 195460f208d7SKim Phillips /* 195560f208d7SKim Phillips * on h/w without explicit sha224 support, we initialize h/w context 195660f208d7SKim Phillips * manually with sha224 constants, and tell it to run sha256. 195760f208d7SKim Phillips */ 195860f208d7SKim Phillips static int ahash_init_sha224_swinit(struct ahash_request *areq) 195960f208d7SKim Phillips { 196060f208d7SKim Phillips struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 196160f208d7SKim Phillips 1962a752447aSKim Phillips req_ctx->hw_context[0] = SHA224_H0; 1963a752447aSKim Phillips req_ctx->hw_context[1] = SHA224_H1; 1964a752447aSKim Phillips req_ctx->hw_context[2] = SHA224_H2; 1965a752447aSKim Phillips req_ctx->hw_context[3] = SHA224_H3; 1966a752447aSKim Phillips req_ctx->hw_context[4] = SHA224_H4; 1967a752447aSKim Phillips req_ctx->hw_context[5] = SHA224_H5; 1968a752447aSKim Phillips req_ctx->hw_context[6] = SHA224_H6; 1969a752447aSKim Phillips req_ctx->hw_context[7] = SHA224_H7; 197060f208d7SKim Phillips 197160f208d7SKim Phillips /* init 64-bit count */ 197260f208d7SKim Phillips req_ctx->hw_context[8] = 0; 197360f208d7SKim Phillips req_ctx->hw_context[9] = 0; 197460f208d7SKim Phillips 19756a4967c3SLEROY Christophe ahash_init(areq); 19766a4967c3SLEROY Christophe req_ctx->swinit = 1;/* prevent h/w initting context with sha256 values*/ 19776a4967c3SLEROY Christophe 197860f208d7SKim Phillips return 0; 197960f208d7SKim Phillips } 198060f208d7SKim Phillips 1981497f2e6bSLee Nipper static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes) 1982497f2e6bSLee Nipper { 1983497f2e6bSLee Nipper struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 1984497f2e6bSLee Nipper struct talitos_ctx *ctx = crypto_ahash_ctx(tfm); 1985497f2e6bSLee Nipper struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 1986497f2e6bSLee Nipper struct talitos_edesc *edesc; 1987497f2e6bSLee Nipper unsigned int blocksize = 1988497f2e6bSLee Nipper crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); 1989497f2e6bSLee Nipper unsigned int nbytes_to_hash; 1990497f2e6bSLee Nipper unsigned int to_hash_later; 19915e833bc4SLee Nipper unsigned int nsg; 19928e409fe1SLABBE Corentin int nents; 199337b5e889SLEROY Christophe struct device *dev = ctx->dev; 199437b5e889SLEROY Christophe struct talitos_private *priv = dev_get_drvdata(dev); 199537b5e889SLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 19963c0dd190SLEROY Christophe u8 *ctx_buf = req_ctx->buf[req_ctx->buf_idx]; 1997497f2e6bSLee Nipper 19985e833bc4SLee Nipper if (!req_ctx->last && (nbytes + req_ctx->nbuf <= blocksize)) { 19995e833bc4SLee Nipper /* Buffer up to one whole block */ 20008e409fe1SLABBE Corentin nents = sg_nents_for_len(areq->src, nbytes); 20018e409fe1SLABBE Corentin if (nents < 0) { 2002854e25a6Sjianchunfu dev_err(dev, "Invalid number of src SG.\n"); 20038e409fe1SLABBE Corentin return nents; 20048e409fe1SLABBE Corentin } 20058e409fe1SLABBE Corentin sg_copy_to_buffer(areq->src, nents, 20063c0dd190SLEROY Christophe ctx_buf + req_ctx->nbuf, nbytes); 20075e833bc4SLee Nipper req_ctx->nbuf += nbytes; 2008497f2e6bSLee Nipper return 0; 2009497f2e6bSLee Nipper } 2010497f2e6bSLee Nipper 20115e833bc4SLee Nipper /* At least (blocksize + 1) bytes are available to hash */ 20125e833bc4SLee Nipper nbytes_to_hash = nbytes + req_ctx->nbuf; 20135e833bc4SLee Nipper to_hash_later = nbytes_to_hash & (blocksize - 1); 20145e833bc4SLee Nipper 20155e833bc4SLee Nipper if (req_ctx->last) 20165e833bc4SLee Nipper to_hash_later = 0; 20175e833bc4SLee Nipper else if (to_hash_later) 20185e833bc4SLee Nipper /* There is a partial block. Hash the full block(s) now */ 20195e833bc4SLee Nipper nbytes_to_hash -= to_hash_later; 20205e833bc4SLee Nipper else { 20215e833bc4SLee Nipper /* Keep one block buffered */ 20225e833bc4SLee Nipper nbytes_to_hash -= blocksize; 20235e833bc4SLee Nipper to_hash_later = blocksize; 2024497f2e6bSLee Nipper } 20255e833bc4SLee Nipper 20265e833bc4SLee Nipper /* Chain in any previously buffered data */ 202737b5e889SLEROY Christophe if (!is_sec1 && req_ctx->nbuf) { 20285e833bc4SLee Nipper nsg = (req_ctx->nbuf < nbytes_to_hash) ? 2 : 1; 20295e833bc4SLee Nipper sg_init_table(req_ctx->bufsl, nsg); 20303c0dd190SLEROY Christophe sg_set_buf(req_ctx->bufsl, ctx_buf, req_ctx->nbuf); 20315e833bc4SLee Nipper if (nsg > 1) 2032c56f6d12SDan Williams sg_chain(req_ctx->bufsl, 2, areq->src); 20335e833bc4SLee Nipper req_ctx->psrc = req_ctx->bufsl; 203437b5e889SLEROY Christophe } else if (is_sec1 && req_ctx->nbuf && req_ctx->nbuf < blocksize) { 203558cdbc6dSChristophe Leroy int offset; 203658cdbc6dSChristophe Leroy 203737b5e889SLEROY Christophe if (nbytes_to_hash > blocksize) 203837b5e889SLEROY Christophe offset = blocksize - req_ctx->nbuf; 203937b5e889SLEROY Christophe else 204037b5e889SLEROY Christophe offset = nbytes_to_hash - req_ctx->nbuf; 204137b5e889SLEROY Christophe nents = sg_nents_for_len(areq->src, offset); 204237b5e889SLEROY Christophe if (nents < 0) { 2043854e25a6Sjianchunfu dev_err(dev, "Invalid number of src SG.\n"); 204437b5e889SLEROY Christophe return nents; 204537b5e889SLEROY Christophe } 204637b5e889SLEROY Christophe sg_copy_to_buffer(areq->src, nents, 20473c0dd190SLEROY Christophe ctx_buf + req_ctx->nbuf, offset); 204837b5e889SLEROY Christophe req_ctx->nbuf += offset; 204958cdbc6dSChristophe Leroy req_ctx->psrc = scatterwalk_ffwd(req_ctx->bufsl, areq->src, 205058cdbc6dSChristophe Leroy offset); 20515e833bc4SLee Nipper } else 20525e833bc4SLee Nipper req_ctx->psrc = areq->src; 20535e833bc4SLee Nipper 2054497f2e6bSLee Nipper if (to_hash_later) { 20558e409fe1SLABBE Corentin nents = sg_nents_for_len(areq->src, nbytes); 20568e409fe1SLABBE Corentin if (nents < 0) { 2057854e25a6Sjianchunfu dev_err(dev, "Invalid number of src SG.\n"); 20588e409fe1SLABBE Corentin return nents; 20598e409fe1SLABBE Corentin } 2060d0525723SAkinobu Mita sg_pcopy_to_buffer(areq->src, nents, 20613c0dd190SLEROY Christophe req_ctx->buf[(req_ctx->buf_idx + 1) & 1], 2062497f2e6bSLee Nipper to_hash_later, 2063497f2e6bSLee Nipper nbytes - to_hash_later); 2064497f2e6bSLee Nipper } 2065497f2e6bSLee Nipper req_ctx->to_hash_later = to_hash_later; 2066497f2e6bSLee Nipper 20675e833bc4SLee Nipper /* Allocate extended descriptor */ 2068497f2e6bSLee Nipper edesc = ahash_edesc_alloc(areq, nbytes_to_hash); 2069497f2e6bSLee Nipper if (IS_ERR(edesc)) 2070497f2e6bSLee Nipper return PTR_ERR(edesc); 2071497f2e6bSLee Nipper 2072497f2e6bSLee Nipper edesc->desc.hdr = ctx->desc_hdr_template; 2073497f2e6bSLee Nipper 2074497f2e6bSLee Nipper /* On last one, request SEC to pad; otherwise continue */ 2075497f2e6bSLee Nipper if (req_ctx->last) 2076497f2e6bSLee Nipper edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_PAD; 2077497f2e6bSLee Nipper else 2078497f2e6bSLee Nipper edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_CONT; 2079497f2e6bSLee Nipper 208060f208d7SKim Phillips /* request SEC to INIT hash. */ 208160f208d7SKim Phillips if (req_ctx->first && !req_ctx->swinit) 2082497f2e6bSLee Nipper edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_INIT; 2083497f2e6bSLee Nipper 2084497f2e6bSLee Nipper /* When the tfm context has a keylen, it's an HMAC. 2085497f2e6bSLee Nipper * A first or last (ie. not middle) descriptor must request HMAC. 2086497f2e6bSLee Nipper */ 2087497f2e6bSLee Nipper if (ctx->keylen && (req_ctx->first || req_ctx->last)) 2088497f2e6bSLee Nipper edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_HMAC; 2089497f2e6bSLee Nipper 209058cdbc6dSChristophe Leroy return common_nonsnoop_hash(edesc, areq, nbytes_to_hash, ahash_done); 2091497f2e6bSLee Nipper } 2092497f2e6bSLee Nipper 2093497f2e6bSLee Nipper static int ahash_update(struct ahash_request *areq) 2094497f2e6bSLee Nipper { 2095497f2e6bSLee Nipper struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 2096497f2e6bSLee Nipper 2097497f2e6bSLee Nipper req_ctx->last = 0; 2098497f2e6bSLee Nipper 2099497f2e6bSLee Nipper return ahash_process_req(areq, areq->nbytes); 2100497f2e6bSLee Nipper } 2101497f2e6bSLee Nipper 2102497f2e6bSLee Nipper static int ahash_final(struct ahash_request *areq) 2103497f2e6bSLee Nipper { 2104497f2e6bSLee Nipper struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 2105497f2e6bSLee Nipper 2106497f2e6bSLee Nipper req_ctx->last = 1; 2107497f2e6bSLee Nipper 2108497f2e6bSLee Nipper return ahash_process_req(areq, 0); 2109497f2e6bSLee Nipper } 2110497f2e6bSLee Nipper 2111497f2e6bSLee Nipper static int ahash_finup(struct ahash_request *areq) 2112497f2e6bSLee Nipper { 2113497f2e6bSLee Nipper struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 2114497f2e6bSLee Nipper 2115497f2e6bSLee Nipper req_ctx->last = 1; 2116497f2e6bSLee Nipper 2117497f2e6bSLee Nipper return ahash_process_req(areq, areq->nbytes); 2118497f2e6bSLee Nipper } 2119497f2e6bSLee Nipper 2120497f2e6bSLee Nipper static int ahash_digest(struct ahash_request *areq) 2121497f2e6bSLee Nipper { 2122497f2e6bSLee Nipper struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 212360f208d7SKim Phillips struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq); 2124497f2e6bSLee Nipper 212560f208d7SKim Phillips ahash->init(areq); 2126497f2e6bSLee Nipper req_ctx->last = 1; 2127497f2e6bSLee Nipper 2128497f2e6bSLee Nipper return ahash_process_req(areq, areq->nbytes); 2129497f2e6bSLee Nipper } 2130497f2e6bSLee Nipper 21313639ca84SHoria Geant? static int ahash_export(struct ahash_request *areq, void *out) 21323639ca84SHoria Geant? { 21333639ca84SHoria Geant? struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 21343639ca84SHoria Geant? struct talitos_export_state *export = out; 21356a4967c3SLEROY Christophe struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 21366a4967c3SLEROY Christophe struct talitos_ctx *ctx = crypto_ahash_ctx(tfm); 21376a4967c3SLEROY Christophe struct device *dev = ctx->dev; 21386a4967c3SLEROY Christophe dma_addr_t dma; 21396a4967c3SLEROY Christophe 21406a4967c3SLEROY Christophe dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size, 21416a4967c3SLEROY Christophe DMA_FROM_DEVICE); 21426a4967c3SLEROY Christophe dma_unmap_single(dev, dma, req_ctx->hw_context_size, DMA_FROM_DEVICE); 21433639ca84SHoria Geant? 21443639ca84SHoria Geant? memcpy(export->hw_context, req_ctx->hw_context, 21453639ca84SHoria Geant? req_ctx->hw_context_size); 21463c0dd190SLEROY Christophe memcpy(export->buf, req_ctx->buf[req_ctx->buf_idx], req_ctx->nbuf); 21473639ca84SHoria Geant? export->swinit = req_ctx->swinit; 21483639ca84SHoria Geant? export->first = req_ctx->first; 21493639ca84SHoria Geant? export->last = req_ctx->last; 21503639ca84SHoria Geant? export->to_hash_later = req_ctx->to_hash_later; 21513639ca84SHoria Geant? export->nbuf = req_ctx->nbuf; 21523639ca84SHoria Geant? 21533639ca84SHoria Geant? return 0; 21543639ca84SHoria Geant? } 21553639ca84SHoria Geant? 21563639ca84SHoria Geant? static int ahash_import(struct ahash_request *areq, const void *in) 21573639ca84SHoria Geant? { 21583639ca84SHoria Geant? struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); 21593639ca84SHoria Geant? struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 21606a4967c3SLEROY Christophe struct talitos_ctx *ctx = crypto_ahash_ctx(tfm); 21616a4967c3SLEROY Christophe struct device *dev = ctx->dev; 21623639ca84SHoria Geant? const struct talitos_export_state *export = in; 216349f9783bSLEROY Christophe unsigned int size; 21646a4967c3SLEROY Christophe dma_addr_t dma; 21653639ca84SHoria Geant? 21663639ca84SHoria Geant? memset(req_ctx, 0, sizeof(*req_ctx)); 216749f9783bSLEROY Christophe size = (crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE) 21683639ca84SHoria Geant? ? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256 21693639ca84SHoria Geant? : TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512; 217049f9783bSLEROY Christophe req_ctx->hw_context_size = size; 217149f9783bSLEROY Christophe memcpy(req_ctx->hw_context, export->hw_context, size); 21723c0dd190SLEROY Christophe memcpy(req_ctx->buf[0], export->buf, export->nbuf); 21733639ca84SHoria Geant? req_ctx->swinit = export->swinit; 21743639ca84SHoria Geant? req_ctx->first = export->first; 21753639ca84SHoria Geant? req_ctx->last = export->last; 21763639ca84SHoria Geant? req_ctx->to_hash_later = export->to_hash_later; 21773639ca84SHoria Geant? req_ctx->nbuf = export->nbuf; 21783639ca84SHoria Geant? 21796a4967c3SLEROY Christophe dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size, 21806a4967c3SLEROY Christophe DMA_TO_DEVICE); 21816a4967c3SLEROY Christophe dma_unmap_single(dev, dma, req_ctx->hw_context_size, DMA_TO_DEVICE); 21826a4967c3SLEROY Christophe 21833639ca84SHoria Geant? return 0; 21843639ca84SHoria Geant? } 21853639ca84SHoria Geant? 218679b3a418SLee Nipper static int keyhash(struct crypto_ahash *tfm, const u8 *key, unsigned int keylen, 218779b3a418SLee Nipper u8 *hash) 218879b3a418SLee Nipper { 218979b3a418SLee Nipper struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); 219079b3a418SLee Nipper 219179b3a418SLee Nipper struct scatterlist sg[1]; 219279b3a418SLee Nipper struct ahash_request *req; 2193f1c90ac3SGilad Ben-Yossef struct crypto_wait wait; 219479b3a418SLee Nipper int ret; 219579b3a418SLee Nipper 2196f1c90ac3SGilad Ben-Yossef crypto_init_wait(&wait); 219779b3a418SLee Nipper 219879b3a418SLee Nipper req = ahash_request_alloc(tfm, GFP_KERNEL); 219979b3a418SLee Nipper if (!req) 220079b3a418SLee Nipper return -ENOMEM; 220179b3a418SLee Nipper 220279b3a418SLee Nipper /* Keep tfm keylen == 0 during hash of the long key */ 220379b3a418SLee Nipper ctx->keylen = 0; 220479b3a418SLee Nipper ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, 2205f1c90ac3SGilad Ben-Yossef crypto_req_done, &wait); 220679b3a418SLee Nipper 220779b3a418SLee Nipper sg_init_one(&sg[0], key, keylen); 220879b3a418SLee Nipper 220979b3a418SLee Nipper ahash_request_set_crypt(req, sg, hash, keylen); 2210f1c90ac3SGilad Ben-Yossef ret = crypto_wait_req(crypto_ahash_digest(req), &wait); 2211f1c90ac3SGilad Ben-Yossef 221279b3a418SLee Nipper ahash_request_free(req); 221379b3a418SLee Nipper 221479b3a418SLee Nipper return ret; 221579b3a418SLee Nipper } 221679b3a418SLee Nipper 221779b3a418SLee Nipper static int ahash_setkey(struct crypto_ahash *tfm, const u8 *key, 221879b3a418SLee Nipper unsigned int keylen) 221979b3a418SLee Nipper { 222079b3a418SLee Nipper struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); 22212e13ce08SLEROY Christophe struct device *dev = ctx->dev; 222279b3a418SLee Nipper unsigned int blocksize = 222379b3a418SLee Nipper crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); 222479b3a418SLee Nipper unsigned int digestsize = crypto_ahash_digestsize(tfm); 222579b3a418SLee Nipper unsigned int keysize = keylen; 222679b3a418SLee Nipper u8 hash[SHA512_DIGEST_SIZE]; 222779b3a418SLee Nipper int ret; 222879b3a418SLee Nipper 222979b3a418SLee Nipper if (keylen <= blocksize) 223079b3a418SLee Nipper memcpy(ctx->key, key, keysize); 223179b3a418SLee Nipper else { 223279b3a418SLee Nipper /* Must get the hash of the long key */ 223379b3a418SLee Nipper ret = keyhash(tfm, key, keylen, hash); 223479b3a418SLee Nipper 2235674f368aSEric Biggers if (ret) 223679b3a418SLee Nipper return -EINVAL; 223779b3a418SLee Nipper 223879b3a418SLee Nipper keysize = digestsize; 223979b3a418SLee Nipper memcpy(ctx->key, hash, digestsize); 224079b3a418SLee Nipper } 224179b3a418SLee Nipper 22422e13ce08SLEROY Christophe if (ctx->keylen) 22432e13ce08SLEROY Christophe dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE); 22442e13ce08SLEROY Christophe 224579b3a418SLee Nipper ctx->keylen = keysize; 22462e13ce08SLEROY Christophe ctx->dma_key = dma_map_single(dev, ctx->key, keysize, DMA_TO_DEVICE); 224779b3a418SLee Nipper 224879b3a418SLee Nipper return 0; 224979b3a418SLee Nipper } 225079b3a418SLee Nipper 225179b3a418SLee Nipper 22529c4a7965SKim Phillips struct talitos_alg_template { 2253d5e4aaefSLee Nipper u32 type; 2254b0057763SLEROY Christophe u32 priority; 2255d5e4aaefSLee Nipper union { 2256373960d7SArd Biesheuvel struct skcipher_alg skcipher; 2257acbf7c62SLee Nipper struct ahash_alg hash; 2258aeb4c132SHerbert Xu struct aead_alg aead; 2259d5e4aaefSLee Nipper } alg; 22609c4a7965SKim Phillips __be32 desc_hdr_template; 22619c4a7965SKim Phillips }; 22629c4a7965SKim Phillips 22639c4a7965SKim Phillips static struct talitos_alg_template driver_algs[] = { 2264991155baSHoria Geanta /* AEAD algorithms. These use a single-pass ipsec_esp descriptor */ 2265d5e4aaefSLee Nipper { .type = CRYPTO_ALG_TYPE_AEAD, 2266aeb4c132SHerbert Xu .alg.aead = { 2267aeb4c132SHerbert Xu .base = { 226856af8cd4SLee Nipper .cra_name = "authenc(hmac(sha1),cbc(aes))", 2269aeb4c132SHerbert Xu .cra_driver_name = "authenc-hmac-sha1-" 2270aeb4c132SHerbert Xu "cbc-aes-talitos", 227156af8cd4SLee Nipper .cra_blocksize = AES_BLOCK_SIZE, 2272b8aa7dc5SMikulas Patocka .cra_flags = CRYPTO_ALG_ASYNC | 2273b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY, 2274aeb4c132SHerbert Xu }, 22753952f17eSLee Nipper .ivsize = AES_BLOCK_SIZE, 22763952f17eSLee Nipper .maxauthsize = SHA1_DIGEST_SIZE, 22779c4a7965SKim Phillips }, 22789c4a7965SKim Phillips .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 22799c4a7965SKim Phillips DESC_HDR_SEL0_AESU | 22809c4a7965SKim Phillips DESC_HDR_MODE0_AESU_CBC | 22819c4a7965SKim Phillips DESC_HDR_SEL1_MDEUA | 22829c4a7965SKim Phillips DESC_HDR_MODE1_MDEU_INIT | 22839c4a7965SKim Phillips DESC_HDR_MODE1_MDEU_PAD | 22849c4a7965SKim Phillips DESC_HDR_MODE1_MDEU_SHA1_HMAC, 228570bcaca7SLee Nipper }, 2286d5e4aaefSLee Nipper { .type = CRYPTO_ALG_TYPE_AEAD, 22877405c8d7SLEROY Christophe .priority = TALITOS_CRA_PRIORITY_AEAD_HSNA, 22887405c8d7SLEROY Christophe .alg.aead = { 22897405c8d7SLEROY Christophe .base = { 22907405c8d7SLEROY Christophe .cra_name = "authenc(hmac(sha1),cbc(aes))", 22917405c8d7SLEROY Christophe .cra_driver_name = "authenc-hmac-sha1-" 2292a1a42f84SChristophe Leroy "cbc-aes-talitos-hsna", 22937405c8d7SLEROY Christophe .cra_blocksize = AES_BLOCK_SIZE, 2294b8aa7dc5SMikulas Patocka .cra_flags = CRYPTO_ALG_ASYNC | 2295b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY, 22967405c8d7SLEROY Christophe }, 22977405c8d7SLEROY Christophe .ivsize = AES_BLOCK_SIZE, 22987405c8d7SLEROY Christophe .maxauthsize = SHA1_DIGEST_SIZE, 22997405c8d7SLEROY Christophe }, 23007405c8d7SLEROY Christophe .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | 23017405c8d7SLEROY Christophe DESC_HDR_SEL0_AESU | 23027405c8d7SLEROY Christophe DESC_HDR_MODE0_AESU_CBC | 23037405c8d7SLEROY Christophe DESC_HDR_SEL1_MDEUA | 23047405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_INIT | 23057405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_PAD | 23067405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_SHA1_HMAC, 23077405c8d7SLEROY Christophe }, 23087405c8d7SLEROY Christophe { .type = CRYPTO_ALG_TYPE_AEAD, 2309aeb4c132SHerbert Xu .alg.aead = { 2310aeb4c132SHerbert Xu .base = { 2311aeb4c132SHerbert Xu .cra_name = "authenc(hmac(sha1)," 2312aeb4c132SHerbert Xu "cbc(des3_ede))", 2313aeb4c132SHerbert Xu .cra_driver_name = "authenc-hmac-sha1-" 2314aeb4c132SHerbert Xu "cbc-3des-talitos", 231556af8cd4SLee Nipper .cra_blocksize = DES3_EDE_BLOCK_SIZE, 2316b8aa7dc5SMikulas Patocka .cra_flags = CRYPTO_ALG_ASYNC | 2317b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY, 2318aeb4c132SHerbert Xu }, 23193952f17eSLee Nipper .ivsize = DES3_EDE_BLOCK_SIZE, 23203952f17eSLee Nipper .maxauthsize = SHA1_DIGEST_SIZE, 2321ef7c5c85SHerbert Xu .setkey = aead_des3_setkey, 232270bcaca7SLee Nipper }, 232370bcaca7SLee Nipper .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 232470bcaca7SLee Nipper DESC_HDR_SEL0_DEU | 232570bcaca7SLee Nipper DESC_HDR_MODE0_DEU_CBC | 232670bcaca7SLee Nipper DESC_HDR_MODE0_DEU_3DES | 232770bcaca7SLee Nipper DESC_HDR_SEL1_MDEUA | 232870bcaca7SLee Nipper DESC_HDR_MODE1_MDEU_INIT | 232970bcaca7SLee Nipper DESC_HDR_MODE1_MDEU_PAD | 233070bcaca7SLee Nipper DESC_HDR_MODE1_MDEU_SHA1_HMAC, 23313952f17eSLee Nipper }, 2332d5e4aaefSLee Nipper { .type = CRYPTO_ALG_TYPE_AEAD, 23337405c8d7SLEROY Christophe .priority = TALITOS_CRA_PRIORITY_AEAD_HSNA, 23347405c8d7SLEROY Christophe .alg.aead = { 23357405c8d7SLEROY Christophe .base = { 23367405c8d7SLEROY Christophe .cra_name = "authenc(hmac(sha1)," 23377405c8d7SLEROY Christophe "cbc(des3_ede))", 23387405c8d7SLEROY Christophe .cra_driver_name = "authenc-hmac-sha1-" 2339a1a42f84SChristophe Leroy "cbc-3des-talitos-hsna", 23407405c8d7SLEROY Christophe .cra_blocksize = DES3_EDE_BLOCK_SIZE, 2341b8aa7dc5SMikulas Patocka .cra_flags = CRYPTO_ALG_ASYNC | 2342b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY, 23437405c8d7SLEROY Christophe }, 23447405c8d7SLEROY Christophe .ivsize = DES3_EDE_BLOCK_SIZE, 23457405c8d7SLEROY Christophe .maxauthsize = SHA1_DIGEST_SIZE, 2346ef7c5c85SHerbert Xu .setkey = aead_des3_setkey, 23477405c8d7SLEROY Christophe }, 23487405c8d7SLEROY Christophe .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | 23497405c8d7SLEROY Christophe DESC_HDR_SEL0_DEU | 23507405c8d7SLEROY Christophe DESC_HDR_MODE0_DEU_CBC | 23517405c8d7SLEROY Christophe DESC_HDR_MODE0_DEU_3DES | 23527405c8d7SLEROY Christophe DESC_HDR_SEL1_MDEUA | 23537405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_INIT | 23547405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_PAD | 23557405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_SHA1_HMAC, 23567405c8d7SLEROY Christophe }, 23577405c8d7SLEROY Christophe { .type = CRYPTO_ALG_TYPE_AEAD, 2358aeb4c132SHerbert Xu .alg.aead = { 2359aeb4c132SHerbert Xu .base = { 2360357fb605SHoria Geanta .cra_name = "authenc(hmac(sha224),cbc(aes))", 2361aeb4c132SHerbert Xu .cra_driver_name = "authenc-hmac-sha224-" 2362aeb4c132SHerbert Xu "cbc-aes-talitos", 2363357fb605SHoria Geanta .cra_blocksize = AES_BLOCK_SIZE, 2364b8aa7dc5SMikulas Patocka .cra_flags = CRYPTO_ALG_ASYNC | 2365b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY, 2366aeb4c132SHerbert Xu }, 2367357fb605SHoria Geanta .ivsize = AES_BLOCK_SIZE, 2368357fb605SHoria Geanta .maxauthsize = SHA224_DIGEST_SIZE, 2369357fb605SHoria Geanta }, 2370357fb605SHoria Geanta .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 2371357fb605SHoria Geanta DESC_HDR_SEL0_AESU | 2372357fb605SHoria Geanta DESC_HDR_MODE0_AESU_CBC | 2373357fb605SHoria Geanta DESC_HDR_SEL1_MDEUA | 2374357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_INIT | 2375357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_PAD | 2376357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_SHA224_HMAC, 2377357fb605SHoria Geanta }, 2378357fb605SHoria Geanta { .type = CRYPTO_ALG_TYPE_AEAD, 23797405c8d7SLEROY Christophe .priority = TALITOS_CRA_PRIORITY_AEAD_HSNA, 23807405c8d7SLEROY Christophe .alg.aead = { 23817405c8d7SLEROY Christophe .base = { 23827405c8d7SLEROY Christophe .cra_name = "authenc(hmac(sha224),cbc(aes))", 23837405c8d7SLEROY Christophe .cra_driver_name = "authenc-hmac-sha224-" 2384a1a42f84SChristophe Leroy "cbc-aes-talitos-hsna", 23857405c8d7SLEROY Christophe .cra_blocksize = AES_BLOCK_SIZE, 2386b8aa7dc5SMikulas Patocka .cra_flags = CRYPTO_ALG_ASYNC | 2387b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY, 23887405c8d7SLEROY Christophe }, 23897405c8d7SLEROY Christophe .ivsize = AES_BLOCK_SIZE, 23907405c8d7SLEROY Christophe .maxauthsize = SHA224_DIGEST_SIZE, 23917405c8d7SLEROY Christophe }, 23927405c8d7SLEROY Christophe .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | 23937405c8d7SLEROY Christophe DESC_HDR_SEL0_AESU | 23947405c8d7SLEROY Christophe DESC_HDR_MODE0_AESU_CBC | 23957405c8d7SLEROY Christophe DESC_HDR_SEL1_MDEUA | 23967405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_INIT | 23977405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_PAD | 23987405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_SHA224_HMAC, 23997405c8d7SLEROY Christophe }, 24007405c8d7SLEROY Christophe { .type = CRYPTO_ALG_TYPE_AEAD, 2401aeb4c132SHerbert Xu .alg.aead = { 2402aeb4c132SHerbert Xu .base = { 2403aeb4c132SHerbert Xu .cra_name = "authenc(hmac(sha224)," 2404aeb4c132SHerbert Xu "cbc(des3_ede))", 2405aeb4c132SHerbert Xu .cra_driver_name = "authenc-hmac-sha224-" 2406aeb4c132SHerbert Xu "cbc-3des-talitos", 2407357fb605SHoria Geanta .cra_blocksize = DES3_EDE_BLOCK_SIZE, 2408b8aa7dc5SMikulas Patocka .cra_flags = CRYPTO_ALG_ASYNC | 2409b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY, 2410aeb4c132SHerbert Xu }, 2411357fb605SHoria Geanta .ivsize = DES3_EDE_BLOCK_SIZE, 2412357fb605SHoria Geanta .maxauthsize = SHA224_DIGEST_SIZE, 2413ef7c5c85SHerbert Xu .setkey = aead_des3_setkey, 2414357fb605SHoria Geanta }, 2415357fb605SHoria Geanta .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 2416357fb605SHoria Geanta DESC_HDR_SEL0_DEU | 2417357fb605SHoria Geanta DESC_HDR_MODE0_DEU_CBC | 2418357fb605SHoria Geanta DESC_HDR_MODE0_DEU_3DES | 2419357fb605SHoria Geanta DESC_HDR_SEL1_MDEUA | 2420357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_INIT | 2421357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_PAD | 2422357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_SHA224_HMAC, 2423357fb605SHoria Geanta }, 2424357fb605SHoria Geanta { .type = CRYPTO_ALG_TYPE_AEAD, 24257405c8d7SLEROY Christophe .priority = TALITOS_CRA_PRIORITY_AEAD_HSNA, 24267405c8d7SLEROY Christophe .alg.aead = { 24277405c8d7SLEROY Christophe .base = { 24287405c8d7SLEROY Christophe .cra_name = "authenc(hmac(sha224)," 24297405c8d7SLEROY Christophe "cbc(des3_ede))", 24307405c8d7SLEROY Christophe .cra_driver_name = "authenc-hmac-sha224-" 2431a1a42f84SChristophe Leroy "cbc-3des-talitos-hsna", 24327405c8d7SLEROY Christophe .cra_blocksize = DES3_EDE_BLOCK_SIZE, 2433b8aa7dc5SMikulas Patocka .cra_flags = CRYPTO_ALG_ASYNC | 2434b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY, 24357405c8d7SLEROY Christophe }, 24367405c8d7SLEROY Christophe .ivsize = DES3_EDE_BLOCK_SIZE, 24377405c8d7SLEROY Christophe .maxauthsize = SHA224_DIGEST_SIZE, 2438ef7c5c85SHerbert Xu .setkey = aead_des3_setkey, 24397405c8d7SLEROY Christophe }, 24407405c8d7SLEROY Christophe .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | 24417405c8d7SLEROY Christophe DESC_HDR_SEL0_DEU | 24427405c8d7SLEROY Christophe DESC_HDR_MODE0_DEU_CBC | 24437405c8d7SLEROY Christophe DESC_HDR_MODE0_DEU_3DES | 24447405c8d7SLEROY Christophe DESC_HDR_SEL1_MDEUA | 24457405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_INIT | 24467405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_PAD | 24477405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_SHA224_HMAC, 24487405c8d7SLEROY Christophe }, 24497405c8d7SLEROY Christophe { .type = CRYPTO_ALG_TYPE_AEAD, 2450aeb4c132SHerbert Xu .alg.aead = { 2451aeb4c132SHerbert Xu .base = { 245256af8cd4SLee Nipper .cra_name = "authenc(hmac(sha256),cbc(aes))", 2453aeb4c132SHerbert Xu .cra_driver_name = "authenc-hmac-sha256-" 2454aeb4c132SHerbert Xu "cbc-aes-talitos", 245556af8cd4SLee Nipper .cra_blocksize = AES_BLOCK_SIZE, 2456b8aa7dc5SMikulas Patocka .cra_flags = CRYPTO_ALG_ASYNC | 2457b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY, 2458aeb4c132SHerbert Xu }, 24593952f17eSLee Nipper .ivsize = AES_BLOCK_SIZE, 24603952f17eSLee Nipper .maxauthsize = SHA256_DIGEST_SIZE, 24613952f17eSLee Nipper }, 24623952f17eSLee Nipper .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 24633952f17eSLee Nipper DESC_HDR_SEL0_AESU | 24643952f17eSLee Nipper DESC_HDR_MODE0_AESU_CBC | 24653952f17eSLee Nipper DESC_HDR_SEL1_MDEUA | 24663952f17eSLee Nipper DESC_HDR_MODE1_MDEU_INIT | 24673952f17eSLee Nipper DESC_HDR_MODE1_MDEU_PAD | 24683952f17eSLee Nipper DESC_HDR_MODE1_MDEU_SHA256_HMAC, 24693952f17eSLee Nipper }, 2470d5e4aaefSLee Nipper { .type = CRYPTO_ALG_TYPE_AEAD, 24717405c8d7SLEROY Christophe .priority = TALITOS_CRA_PRIORITY_AEAD_HSNA, 24727405c8d7SLEROY Christophe .alg.aead = { 24737405c8d7SLEROY Christophe .base = { 24747405c8d7SLEROY Christophe .cra_name = "authenc(hmac(sha256),cbc(aes))", 24757405c8d7SLEROY Christophe .cra_driver_name = "authenc-hmac-sha256-" 2476a1a42f84SChristophe Leroy "cbc-aes-talitos-hsna", 24777405c8d7SLEROY Christophe .cra_blocksize = AES_BLOCK_SIZE, 2478b8aa7dc5SMikulas Patocka .cra_flags = CRYPTO_ALG_ASYNC | 2479b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY, 24807405c8d7SLEROY Christophe }, 24817405c8d7SLEROY Christophe .ivsize = AES_BLOCK_SIZE, 24827405c8d7SLEROY Christophe .maxauthsize = SHA256_DIGEST_SIZE, 24837405c8d7SLEROY Christophe }, 24847405c8d7SLEROY Christophe .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | 24857405c8d7SLEROY Christophe DESC_HDR_SEL0_AESU | 24867405c8d7SLEROY Christophe DESC_HDR_MODE0_AESU_CBC | 24877405c8d7SLEROY Christophe DESC_HDR_SEL1_MDEUA | 24887405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_INIT | 24897405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_PAD | 24907405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_SHA256_HMAC, 24917405c8d7SLEROY Christophe }, 24927405c8d7SLEROY Christophe { .type = CRYPTO_ALG_TYPE_AEAD, 2493aeb4c132SHerbert Xu .alg.aead = { 2494aeb4c132SHerbert Xu .base = { 2495aeb4c132SHerbert Xu .cra_name = "authenc(hmac(sha256)," 2496aeb4c132SHerbert Xu "cbc(des3_ede))", 2497aeb4c132SHerbert Xu .cra_driver_name = "authenc-hmac-sha256-" 2498aeb4c132SHerbert Xu "cbc-3des-talitos", 249956af8cd4SLee Nipper .cra_blocksize = DES3_EDE_BLOCK_SIZE, 2500b8aa7dc5SMikulas Patocka .cra_flags = CRYPTO_ALG_ASYNC | 2501b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY, 2502aeb4c132SHerbert Xu }, 25033952f17eSLee Nipper .ivsize = DES3_EDE_BLOCK_SIZE, 25043952f17eSLee Nipper .maxauthsize = SHA256_DIGEST_SIZE, 2505ef7c5c85SHerbert Xu .setkey = aead_des3_setkey, 25063952f17eSLee Nipper }, 25073952f17eSLee Nipper .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 25083952f17eSLee Nipper DESC_HDR_SEL0_DEU | 25093952f17eSLee Nipper DESC_HDR_MODE0_DEU_CBC | 25103952f17eSLee Nipper DESC_HDR_MODE0_DEU_3DES | 25113952f17eSLee Nipper DESC_HDR_SEL1_MDEUA | 25123952f17eSLee Nipper DESC_HDR_MODE1_MDEU_INIT | 25133952f17eSLee Nipper DESC_HDR_MODE1_MDEU_PAD | 25143952f17eSLee Nipper DESC_HDR_MODE1_MDEU_SHA256_HMAC, 25153952f17eSLee Nipper }, 2516d5e4aaefSLee Nipper { .type = CRYPTO_ALG_TYPE_AEAD, 25177405c8d7SLEROY Christophe .priority = TALITOS_CRA_PRIORITY_AEAD_HSNA, 25187405c8d7SLEROY Christophe .alg.aead = { 25197405c8d7SLEROY Christophe .base = { 25207405c8d7SLEROY Christophe .cra_name = "authenc(hmac(sha256)," 25217405c8d7SLEROY Christophe "cbc(des3_ede))", 25227405c8d7SLEROY Christophe .cra_driver_name = "authenc-hmac-sha256-" 2523a1a42f84SChristophe Leroy "cbc-3des-talitos-hsna", 25247405c8d7SLEROY Christophe .cra_blocksize = DES3_EDE_BLOCK_SIZE, 2525b8aa7dc5SMikulas Patocka .cra_flags = CRYPTO_ALG_ASYNC | 2526b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY, 25277405c8d7SLEROY Christophe }, 25287405c8d7SLEROY Christophe .ivsize = DES3_EDE_BLOCK_SIZE, 25297405c8d7SLEROY Christophe .maxauthsize = SHA256_DIGEST_SIZE, 2530ef7c5c85SHerbert Xu .setkey = aead_des3_setkey, 25317405c8d7SLEROY Christophe }, 25327405c8d7SLEROY Christophe .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | 25337405c8d7SLEROY Christophe DESC_HDR_SEL0_DEU | 25347405c8d7SLEROY Christophe DESC_HDR_MODE0_DEU_CBC | 25357405c8d7SLEROY Christophe DESC_HDR_MODE0_DEU_3DES | 25367405c8d7SLEROY Christophe DESC_HDR_SEL1_MDEUA | 25377405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_INIT | 25387405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_PAD | 25397405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_SHA256_HMAC, 25407405c8d7SLEROY Christophe }, 25417405c8d7SLEROY Christophe { .type = CRYPTO_ALG_TYPE_AEAD, 2542aeb4c132SHerbert Xu .alg.aead = { 2543aeb4c132SHerbert Xu .base = { 2544357fb605SHoria Geanta .cra_name = "authenc(hmac(sha384),cbc(aes))", 2545aeb4c132SHerbert Xu .cra_driver_name = "authenc-hmac-sha384-" 2546aeb4c132SHerbert Xu "cbc-aes-talitos", 2547357fb605SHoria Geanta .cra_blocksize = AES_BLOCK_SIZE, 2548b8aa7dc5SMikulas Patocka .cra_flags = CRYPTO_ALG_ASYNC | 2549b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY, 2550aeb4c132SHerbert Xu }, 2551357fb605SHoria Geanta .ivsize = AES_BLOCK_SIZE, 2552357fb605SHoria Geanta .maxauthsize = SHA384_DIGEST_SIZE, 2553357fb605SHoria Geanta }, 2554357fb605SHoria Geanta .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 2555357fb605SHoria Geanta DESC_HDR_SEL0_AESU | 2556357fb605SHoria Geanta DESC_HDR_MODE0_AESU_CBC | 2557357fb605SHoria Geanta DESC_HDR_SEL1_MDEUB | 2558357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_INIT | 2559357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_PAD | 2560357fb605SHoria Geanta DESC_HDR_MODE1_MDEUB_SHA384_HMAC, 2561357fb605SHoria Geanta }, 2562357fb605SHoria Geanta { .type = CRYPTO_ALG_TYPE_AEAD, 2563aeb4c132SHerbert Xu .alg.aead = { 2564aeb4c132SHerbert Xu .base = { 2565aeb4c132SHerbert Xu .cra_name = "authenc(hmac(sha384)," 2566aeb4c132SHerbert Xu "cbc(des3_ede))", 2567aeb4c132SHerbert Xu .cra_driver_name = "authenc-hmac-sha384-" 2568aeb4c132SHerbert Xu "cbc-3des-talitos", 2569357fb605SHoria Geanta .cra_blocksize = DES3_EDE_BLOCK_SIZE, 2570b8aa7dc5SMikulas Patocka .cra_flags = CRYPTO_ALG_ASYNC | 2571b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY, 2572aeb4c132SHerbert Xu }, 2573357fb605SHoria Geanta .ivsize = DES3_EDE_BLOCK_SIZE, 2574357fb605SHoria Geanta .maxauthsize = SHA384_DIGEST_SIZE, 2575ef7c5c85SHerbert Xu .setkey = aead_des3_setkey, 2576357fb605SHoria Geanta }, 2577357fb605SHoria Geanta .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 2578357fb605SHoria Geanta DESC_HDR_SEL0_DEU | 2579357fb605SHoria Geanta DESC_HDR_MODE0_DEU_CBC | 2580357fb605SHoria Geanta DESC_HDR_MODE0_DEU_3DES | 2581357fb605SHoria Geanta DESC_HDR_SEL1_MDEUB | 2582357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_INIT | 2583357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_PAD | 2584357fb605SHoria Geanta DESC_HDR_MODE1_MDEUB_SHA384_HMAC, 2585357fb605SHoria Geanta }, 2586357fb605SHoria Geanta { .type = CRYPTO_ALG_TYPE_AEAD, 2587aeb4c132SHerbert Xu .alg.aead = { 2588aeb4c132SHerbert Xu .base = { 2589357fb605SHoria Geanta .cra_name = "authenc(hmac(sha512),cbc(aes))", 2590aeb4c132SHerbert Xu .cra_driver_name = "authenc-hmac-sha512-" 2591aeb4c132SHerbert Xu "cbc-aes-talitos", 2592357fb605SHoria Geanta .cra_blocksize = AES_BLOCK_SIZE, 2593b8aa7dc5SMikulas Patocka .cra_flags = CRYPTO_ALG_ASYNC | 2594b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY, 2595aeb4c132SHerbert Xu }, 2596357fb605SHoria Geanta .ivsize = AES_BLOCK_SIZE, 2597357fb605SHoria Geanta .maxauthsize = SHA512_DIGEST_SIZE, 2598357fb605SHoria Geanta }, 2599357fb605SHoria Geanta .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 2600357fb605SHoria Geanta DESC_HDR_SEL0_AESU | 2601357fb605SHoria Geanta DESC_HDR_MODE0_AESU_CBC | 2602357fb605SHoria Geanta DESC_HDR_SEL1_MDEUB | 2603357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_INIT | 2604357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_PAD | 2605357fb605SHoria Geanta DESC_HDR_MODE1_MDEUB_SHA512_HMAC, 2606357fb605SHoria Geanta }, 2607357fb605SHoria Geanta { .type = CRYPTO_ALG_TYPE_AEAD, 2608aeb4c132SHerbert Xu .alg.aead = { 2609aeb4c132SHerbert Xu .base = { 2610aeb4c132SHerbert Xu .cra_name = "authenc(hmac(sha512)," 2611aeb4c132SHerbert Xu "cbc(des3_ede))", 2612aeb4c132SHerbert Xu .cra_driver_name = "authenc-hmac-sha512-" 2613aeb4c132SHerbert Xu "cbc-3des-talitos", 2614357fb605SHoria Geanta .cra_blocksize = DES3_EDE_BLOCK_SIZE, 2615b8aa7dc5SMikulas Patocka .cra_flags = CRYPTO_ALG_ASYNC | 2616b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY, 2617aeb4c132SHerbert Xu }, 2618357fb605SHoria Geanta .ivsize = DES3_EDE_BLOCK_SIZE, 2619357fb605SHoria Geanta .maxauthsize = SHA512_DIGEST_SIZE, 2620ef7c5c85SHerbert Xu .setkey = aead_des3_setkey, 2621357fb605SHoria Geanta }, 2622357fb605SHoria Geanta .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 2623357fb605SHoria Geanta DESC_HDR_SEL0_DEU | 2624357fb605SHoria Geanta DESC_HDR_MODE0_DEU_CBC | 2625357fb605SHoria Geanta DESC_HDR_MODE0_DEU_3DES | 2626357fb605SHoria Geanta DESC_HDR_SEL1_MDEUB | 2627357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_INIT | 2628357fb605SHoria Geanta DESC_HDR_MODE1_MDEU_PAD | 2629357fb605SHoria Geanta DESC_HDR_MODE1_MDEUB_SHA512_HMAC, 2630357fb605SHoria Geanta }, 2631357fb605SHoria Geanta { .type = CRYPTO_ALG_TYPE_AEAD, 2632aeb4c132SHerbert Xu .alg.aead = { 2633aeb4c132SHerbert Xu .base = { 263456af8cd4SLee Nipper .cra_name = "authenc(hmac(md5),cbc(aes))", 2635aeb4c132SHerbert Xu .cra_driver_name = "authenc-hmac-md5-" 2636aeb4c132SHerbert Xu "cbc-aes-talitos", 263756af8cd4SLee Nipper .cra_blocksize = AES_BLOCK_SIZE, 2638b8aa7dc5SMikulas Patocka .cra_flags = CRYPTO_ALG_ASYNC | 2639b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY, 2640aeb4c132SHerbert Xu }, 26413952f17eSLee Nipper .ivsize = AES_BLOCK_SIZE, 26423952f17eSLee Nipper .maxauthsize = MD5_DIGEST_SIZE, 26433952f17eSLee Nipper }, 26443952f17eSLee Nipper .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 26453952f17eSLee Nipper DESC_HDR_SEL0_AESU | 26463952f17eSLee Nipper DESC_HDR_MODE0_AESU_CBC | 26473952f17eSLee Nipper DESC_HDR_SEL1_MDEUA | 26483952f17eSLee Nipper DESC_HDR_MODE1_MDEU_INIT | 26493952f17eSLee Nipper DESC_HDR_MODE1_MDEU_PAD | 26503952f17eSLee Nipper DESC_HDR_MODE1_MDEU_MD5_HMAC, 26513952f17eSLee Nipper }, 2652d5e4aaefSLee Nipper { .type = CRYPTO_ALG_TYPE_AEAD, 26537405c8d7SLEROY Christophe .priority = TALITOS_CRA_PRIORITY_AEAD_HSNA, 26547405c8d7SLEROY Christophe .alg.aead = { 26557405c8d7SLEROY Christophe .base = { 26567405c8d7SLEROY Christophe .cra_name = "authenc(hmac(md5),cbc(aes))", 26577405c8d7SLEROY Christophe .cra_driver_name = "authenc-hmac-md5-" 2658a1a42f84SChristophe Leroy "cbc-aes-talitos-hsna", 26597405c8d7SLEROY Christophe .cra_blocksize = AES_BLOCK_SIZE, 2660b8aa7dc5SMikulas Patocka .cra_flags = CRYPTO_ALG_ASYNC | 2661b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY, 26627405c8d7SLEROY Christophe }, 26637405c8d7SLEROY Christophe .ivsize = AES_BLOCK_SIZE, 26647405c8d7SLEROY Christophe .maxauthsize = MD5_DIGEST_SIZE, 26657405c8d7SLEROY Christophe }, 26667405c8d7SLEROY Christophe .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | 26677405c8d7SLEROY Christophe DESC_HDR_SEL0_AESU | 26687405c8d7SLEROY Christophe DESC_HDR_MODE0_AESU_CBC | 26697405c8d7SLEROY Christophe DESC_HDR_SEL1_MDEUA | 26707405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_INIT | 26717405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_PAD | 26727405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_MD5_HMAC, 26737405c8d7SLEROY Christophe }, 26747405c8d7SLEROY Christophe { .type = CRYPTO_ALG_TYPE_AEAD, 2675aeb4c132SHerbert Xu .alg.aead = { 2676aeb4c132SHerbert Xu .base = { 267756af8cd4SLee Nipper .cra_name = "authenc(hmac(md5),cbc(des3_ede))", 2678aeb4c132SHerbert Xu .cra_driver_name = "authenc-hmac-md5-" 2679aeb4c132SHerbert Xu "cbc-3des-talitos", 268056af8cd4SLee Nipper .cra_blocksize = DES3_EDE_BLOCK_SIZE, 2681b8aa7dc5SMikulas Patocka .cra_flags = CRYPTO_ALG_ASYNC | 2682b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY, 2683aeb4c132SHerbert Xu }, 26843952f17eSLee Nipper .ivsize = DES3_EDE_BLOCK_SIZE, 26853952f17eSLee Nipper .maxauthsize = MD5_DIGEST_SIZE, 2686ef7c5c85SHerbert Xu .setkey = aead_des3_setkey, 26873952f17eSLee Nipper }, 26883952f17eSLee Nipper .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP | 26893952f17eSLee Nipper DESC_HDR_SEL0_DEU | 26903952f17eSLee Nipper DESC_HDR_MODE0_DEU_CBC | 26913952f17eSLee Nipper DESC_HDR_MODE0_DEU_3DES | 26923952f17eSLee Nipper DESC_HDR_SEL1_MDEUA | 26933952f17eSLee Nipper DESC_HDR_MODE1_MDEU_INIT | 26943952f17eSLee Nipper DESC_HDR_MODE1_MDEU_PAD | 26953952f17eSLee Nipper DESC_HDR_MODE1_MDEU_MD5_HMAC, 26964de9d0b5SLee Nipper }, 26977405c8d7SLEROY Christophe { .type = CRYPTO_ALG_TYPE_AEAD, 26987405c8d7SLEROY Christophe .priority = TALITOS_CRA_PRIORITY_AEAD_HSNA, 26997405c8d7SLEROY Christophe .alg.aead = { 27007405c8d7SLEROY Christophe .base = { 27017405c8d7SLEROY Christophe .cra_name = "authenc(hmac(md5),cbc(des3_ede))", 27027405c8d7SLEROY Christophe .cra_driver_name = "authenc-hmac-md5-" 2703a1a42f84SChristophe Leroy "cbc-3des-talitos-hsna", 27047405c8d7SLEROY Christophe .cra_blocksize = DES3_EDE_BLOCK_SIZE, 2705b8aa7dc5SMikulas Patocka .cra_flags = CRYPTO_ALG_ASYNC | 2706b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY, 27077405c8d7SLEROY Christophe }, 27087405c8d7SLEROY Christophe .ivsize = DES3_EDE_BLOCK_SIZE, 27097405c8d7SLEROY Christophe .maxauthsize = MD5_DIGEST_SIZE, 2710ef7c5c85SHerbert Xu .setkey = aead_des3_setkey, 27117405c8d7SLEROY Christophe }, 27127405c8d7SLEROY Christophe .desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU | 27137405c8d7SLEROY Christophe DESC_HDR_SEL0_DEU | 27147405c8d7SLEROY Christophe DESC_HDR_MODE0_DEU_CBC | 27157405c8d7SLEROY Christophe DESC_HDR_MODE0_DEU_3DES | 27167405c8d7SLEROY Christophe DESC_HDR_SEL1_MDEUA | 27177405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_INIT | 27187405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_PAD | 27197405c8d7SLEROY Christophe DESC_HDR_MODE1_MDEU_MD5_HMAC, 27207405c8d7SLEROY Christophe }, 2721373960d7SArd Biesheuvel /* SKCIPHER algorithms. */ 2722373960d7SArd Biesheuvel { .type = CRYPTO_ALG_TYPE_SKCIPHER, 2723373960d7SArd Biesheuvel .alg.skcipher = { 2724373960d7SArd Biesheuvel .base.cra_name = "ecb(aes)", 2725373960d7SArd Biesheuvel .base.cra_driver_name = "ecb-aes-talitos", 2726373960d7SArd Biesheuvel .base.cra_blocksize = AES_BLOCK_SIZE, 2727b8aa7dc5SMikulas Patocka .base.cra_flags = CRYPTO_ALG_ASYNC | 2728b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY, 27295e75ae1bSLEROY Christophe .min_keysize = AES_MIN_KEY_SIZE, 27305e75ae1bSLEROY Christophe .max_keysize = AES_MAX_KEY_SIZE, 2731373960d7SArd Biesheuvel .setkey = skcipher_aes_setkey, 27325e75ae1bSLEROY Christophe }, 27335e75ae1bSLEROY Christophe .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 27345e75ae1bSLEROY Christophe DESC_HDR_SEL0_AESU, 27355e75ae1bSLEROY Christophe }, 2736373960d7SArd Biesheuvel { .type = CRYPTO_ALG_TYPE_SKCIPHER, 2737373960d7SArd Biesheuvel .alg.skcipher = { 2738373960d7SArd Biesheuvel .base.cra_name = "cbc(aes)", 2739373960d7SArd Biesheuvel .base.cra_driver_name = "cbc-aes-talitos", 2740373960d7SArd Biesheuvel .base.cra_blocksize = AES_BLOCK_SIZE, 2741b8aa7dc5SMikulas Patocka .base.cra_flags = CRYPTO_ALG_ASYNC | 2742b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY, 27434de9d0b5SLee Nipper .min_keysize = AES_MIN_KEY_SIZE, 27444de9d0b5SLee Nipper .max_keysize = AES_MAX_KEY_SIZE, 27454de9d0b5SLee Nipper .ivsize = AES_BLOCK_SIZE, 2746373960d7SArd Biesheuvel .setkey = skcipher_aes_setkey, 27474de9d0b5SLee Nipper }, 27484de9d0b5SLee Nipper .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 27494de9d0b5SLee Nipper DESC_HDR_SEL0_AESU | 27504de9d0b5SLee Nipper DESC_HDR_MODE0_AESU_CBC, 27514de9d0b5SLee Nipper }, 2752373960d7SArd Biesheuvel { .type = CRYPTO_ALG_TYPE_SKCIPHER, 2753373960d7SArd Biesheuvel .alg.skcipher = { 2754373960d7SArd Biesheuvel .base.cra_name = "ctr(aes)", 2755373960d7SArd Biesheuvel .base.cra_driver_name = "ctr-aes-talitos", 2756373960d7SArd Biesheuvel .base.cra_blocksize = 1, 2757b8aa7dc5SMikulas Patocka .base.cra_flags = CRYPTO_ALG_ASYNC | 2758b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY, 27595e75ae1bSLEROY Christophe .min_keysize = AES_MIN_KEY_SIZE, 27605e75ae1bSLEROY Christophe .max_keysize = AES_MAX_KEY_SIZE, 27615e75ae1bSLEROY Christophe .ivsize = AES_BLOCK_SIZE, 2762373960d7SArd Biesheuvel .setkey = skcipher_aes_setkey, 27635e75ae1bSLEROY Christophe }, 276470d355ccSLEROY Christophe .desc_hdr_template = DESC_HDR_TYPE_AESU_CTR_NONSNOOP | 27655e75ae1bSLEROY Christophe DESC_HDR_SEL0_AESU | 27665e75ae1bSLEROY Christophe DESC_HDR_MODE0_AESU_CTR, 27675e75ae1bSLEROY Christophe }, 2768373960d7SArd Biesheuvel { .type = CRYPTO_ALG_TYPE_SKCIPHER, 2769373960d7SArd Biesheuvel .alg.skcipher = { 277043a942d2SChristophe Leroy .base.cra_name = "ctr(aes)", 277143a942d2SChristophe Leroy .base.cra_driver_name = "ctr-aes-talitos", 277243a942d2SChristophe Leroy .base.cra_blocksize = 1, 277343a942d2SChristophe Leroy .base.cra_flags = CRYPTO_ALG_ASYNC | 277443a942d2SChristophe Leroy CRYPTO_ALG_ALLOCATES_MEMORY, 277543a942d2SChristophe Leroy .min_keysize = AES_MIN_KEY_SIZE, 277643a942d2SChristophe Leroy .max_keysize = AES_MAX_KEY_SIZE, 277743a942d2SChristophe Leroy .ivsize = AES_BLOCK_SIZE, 277843a942d2SChristophe Leroy .setkey = skcipher_aes_setkey, 277943a942d2SChristophe Leroy }, 278043a942d2SChristophe Leroy .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 278143a942d2SChristophe Leroy DESC_HDR_SEL0_AESU | 278243a942d2SChristophe Leroy DESC_HDR_MODE0_AESU_CTR, 278343a942d2SChristophe Leroy }, 278443a942d2SChristophe Leroy { .type = CRYPTO_ALG_TYPE_SKCIPHER, 278543a942d2SChristophe Leroy .alg.skcipher = { 2786373960d7SArd Biesheuvel .base.cra_name = "ecb(des)", 2787373960d7SArd Biesheuvel .base.cra_driver_name = "ecb-des-talitos", 2788373960d7SArd Biesheuvel .base.cra_blocksize = DES_BLOCK_SIZE, 2789b8aa7dc5SMikulas Patocka .base.cra_flags = CRYPTO_ALG_ASYNC | 2790b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY, 27915e75ae1bSLEROY Christophe .min_keysize = DES_KEY_SIZE, 27925e75ae1bSLEROY Christophe .max_keysize = DES_KEY_SIZE, 2793373960d7SArd Biesheuvel .setkey = skcipher_des_setkey, 27945e75ae1bSLEROY Christophe }, 27955e75ae1bSLEROY Christophe .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 27965e75ae1bSLEROY Christophe DESC_HDR_SEL0_DEU, 27975e75ae1bSLEROY Christophe }, 2798373960d7SArd Biesheuvel { .type = CRYPTO_ALG_TYPE_SKCIPHER, 2799373960d7SArd Biesheuvel .alg.skcipher = { 2800373960d7SArd Biesheuvel .base.cra_name = "cbc(des)", 2801373960d7SArd Biesheuvel .base.cra_driver_name = "cbc-des-talitos", 2802373960d7SArd Biesheuvel .base.cra_blocksize = DES_BLOCK_SIZE, 2803b8aa7dc5SMikulas Patocka .base.cra_flags = CRYPTO_ALG_ASYNC | 2804b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY, 28055e75ae1bSLEROY Christophe .min_keysize = DES_KEY_SIZE, 28065e75ae1bSLEROY Christophe .max_keysize = DES_KEY_SIZE, 28075e75ae1bSLEROY Christophe .ivsize = DES_BLOCK_SIZE, 2808373960d7SArd Biesheuvel .setkey = skcipher_des_setkey, 28095e75ae1bSLEROY Christophe }, 28105e75ae1bSLEROY Christophe .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 28115e75ae1bSLEROY Christophe DESC_HDR_SEL0_DEU | 28125e75ae1bSLEROY Christophe DESC_HDR_MODE0_DEU_CBC, 28135e75ae1bSLEROY Christophe }, 2814373960d7SArd Biesheuvel { .type = CRYPTO_ALG_TYPE_SKCIPHER, 2815373960d7SArd Biesheuvel .alg.skcipher = { 2816373960d7SArd Biesheuvel .base.cra_name = "ecb(des3_ede)", 2817373960d7SArd Biesheuvel .base.cra_driver_name = "ecb-3des-talitos", 2818373960d7SArd Biesheuvel .base.cra_blocksize = DES3_EDE_BLOCK_SIZE, 2819b8aa7dc5SMikulas Patocka .base.cra_flags = CRYPTO_ALG_ASYNC | 2820b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY, 28215e75ae1bSLEROY Christophe .min_keysize = DES3_EDE_KEY_SIZE, 28225e75ae1bSLEROY Christophe .max_keysize = DES3_EDE_KEY_SIZE, 2823373960d7SArd Biesheuvel .setkey = skcipher_des3_setkey, 28245e75ae1bSLEROY Christophe }, 28255e75ae1bSLEROY Christophe .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 28265e75ae1bSLEROY Christophe DESC_HDR_SEL0_DEU | 28275e75ae1bSLEROY Christophe DESC_HDR_MODE0_DEU_3DES, 28285e75ae1bSLEROY Christophe }, 2829373960d7SArd Biesheuvel { .type = CRYPTO_ALG_TYPE_SKCIPHER, 2830373960d7SArd Biesheuvel .alg.skcipher = { 2831373960d7SArd Biesheuvel .base.cra_name = "cbc(des3_ede)", 2832373960d7SArd Biesheuvel .base.cra_driver_name = "cbc-3des-talitos", 2833373960d7SArd Biesheuvel .base.cra_blocksize = DES3_EDE_BLOCK_SIZE, 2834b8aa7dc5SMikulas Patocka .base.cra_flags = CRYPTO_ALG_ASYNC | 2835b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY, 28364de9d0b5SLee Nipper .min_keysize = DES3_EDE_KEY_SIZE, 28374de9d0b5SLee Nipper .max_keysize = DES3_EDE_KEY_SIZE, 28384de9d0b5SLee Nipper .ivsize = DES3_EDE_BLOCK_SIZE, 2839373960d7SArd Biesheuvel .setkey = skcipher_des3_setkey, 28404de9d0b5SLee Nipper }, 28414de9d0b5SLee Nipper .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 28424de9d0b5SLee Nipper DESC_HDR_SEL0_DEU | 28434de9d0b5SLee Nipper DESC_HDR_MODE0_DEU_CBC | 28444de9d0b5SLee Nipper DESC_HDR_MODE0_DEU_3DES, 2845497f2e6bSLee Nipper }, 2846497f2e6bSLee Nipper /* AHASH algorithms. */ 2847497f2e6bSLee Nipper { .type = CRYPTO_ALG_TYPE_AHASH, 2848497f2e6bSLee Nipper .alg.hash = { 2849497f2e6bSLee Nipper .halg.digestsize = MD5_DIGEST_SIZE, 28503639ca84SHoria Geant? .halg.statesize = sizeof(struct talitos_export_state), 2851497f2e6bSLee Nipper .halg.base = { 2852497f2e6bSLee Nipper .cra_name = "md5", 2853497f2e6bSLee Nipper .cra_driver_name = "md5-talitos", 2854b3988618SMartin Hicks .cra_blocksize = MD5_HMAC_BLOCK_SIZE, 2855b8aa7dc5SMikulas Patocka .cra_flags = CRYPTO_ALG_ASYNC | 2856b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY, 28579c4a7965SKim Phillips } 2858497f2e6bSLee Nipper }, 2859497f2e6bSLee Nipper .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 2860497f2e6bSLee Nipper DESC_HDR_SEL0_MDEUA | 2861497f2e6bSLee Nipper DESC_HDR_MODE0_MDEU_MD5, 2862497f2e6bSLee Nipper }, 2863497f2e6bSLee Nipper { .type = CRYPTO_ALG_TYPE_AHASH, 2864497f2e6bSLee Nipper .alg.hash = { 2865497f2e6bSLee Nipper .halg.digestsize = SHA1_DIGEST_SIZE, 28663639ca84SHoria Geant? .halg.statesize = sizeof(struct talitos_export_state), 2867497f2e6bSLee Nipper .halg.base = { 2868497f2e6bSLee Nipper .cra_name = "sha1", 2869497f2e6bSLee Nipper .cra_driver_name = "sha1-talitos", 2870497f2e6bSLee Nipper .cra_blocksize = SHA1_BLOCK_SIZE, 2871b8aa7dc5SMikulas Patocka .cra_flags = CRYPTO_ALG_ASYNC | 2872b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY, 2873497f2e6bSLee Nipper } 2874497f2e6bSLee Nipper }, 2875497f2e6bSLee Nipper .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 2876497f2e6bSLee Nipper DESC_HDR_SEL0_MDEUA | 2877497f2e6bSLee Nipper DESC_HDR_MODE0_MDEU_SHA1, 2878497f2e6bSLee Nipper }, 2879497f2e6bSLee Nipper { .type = CRYPTO_ALG_TYPE_AHASH, 2880497f2e6bSLee Nipper .alg.hash = { 288160f208d7SKim Phillips .halg.digestsize = SHA224_DIGEST_SIZE, 28823639ca84SHoria Geant? .halg.statesize = sizeof(struct talitos_export_state), 288360f208d7SKim Phillips .halg.base = { 288460f208d7SKim Phillips .cra_name = "sha224", 288560f208d7SKim Phillips .cra_driver_name = "sha224-talitos", 288660f208d7SKim Phillips .cra_blocksize = SHA224_BLOCK_SIZE, 2887b8aa7dc5SMikulas Patocka .cra_flags = CRYPTO_ALG_ASYNC | 2888b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY, 288960f208d7SKim Phillips } 289060f208d7SKim Phillips }, 289160f208d7SKim Phillips .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 289260f208d7SKim Phillips DESC_HDR_SEL0_MDEUA | 289360f208d7SKim Phillips DESC_HDR_MODE0_MDEU_SHA224, 289460f208d7SKim Phillips }, 289560f208d7SKim Phillips { .type = CRYPTO_ALG_TYPE_AHASH, 289660f208d7SKim Phillips .alg.hash = { 2897497f2e6bSLee Nipper .halg.digestsize = SHA256_DIGEST_SIZE, 28983639ca84SHoria Geant? .halg.statesize = sizeof(struct talitos_export_state), 2899497f2e6bSLee Nipper .halg.base = { 2900497f2e6bSLee Nipper .cra_name = "sha256", 2901497f2e6bSLee Nipper .cra_driver_name = "sha256-talitos", 2902497f2e6bSLee Nipper .cra_blocksize = SHA256_BLOCK_SIZE, 2903b8aa7dc5SMikulas Patocka .cra_flags = CRYPTO_ALG_ASYNC | 2904b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY, 2905497f2e6bSLee Nipper } 2906497f2e6bSLee Nipper }, 2907497f2e6bSLee Nipper .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 2908497f2e6bSLee Nipper DESC_HDR_SEL0_MDEUA | 2909497f2e6bSLee Nipper DESC_HDR_MODE0_MDEU_SHA256, 2910497f2e6bSLee Nipper }, 2911497f2e6bSLee Nipper { .type = CRYPTO_ALG_TYPE_AHASH, 2912497f2e6bSLee Nipper .alg.hash = { 2913497f2e6bSLee Nipper .halg.digestsize = SHA384_DIGEST_SIZE, 29143639ca84SHoria Geant? .halg.statesize = sizeof(struct talitos_export_state), 2915497f2e6bSLee Nipper .halg.base = { 2916497f2e6bSLee Nipper .cra_name = "sha384", 2917497f2e6bSLee Nipper .cra_driver_name = "sha384-talitos", 2918497f2e6bSLee Nipper .cra_blocksize = SHA384_BLOCK_SIZE, 2919b8aa7dc5SMikulas Patocka .cra_flags = CRYPTO_ALG_ASYNC | 2920b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY, 2921497f2e6bSLee Nipper } 2922497f2e6bSLee Nipper }, 2923497f2e6bSLee Nipper .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 2924497f2e6bSLee Nipper DESC_HDR_SEL0_MDEUB | 2925497f2e6bSLee Nipper DESC_HDR_MODE0_MDEUB_SHA384, 2926497f2e6bSLee Nipper }, 2927497f2e6bSLee Nipper { .type = CRYPTO_ALG_TYPE_AHASH, 2928497f2e6bSLee Nipper .alg.hash = { 2929497f2e6bSLee Nipper .halg.digestsize = SHA512_DIGEST_SIZE, 29303639ca84SHoria Geant? .halg.statesize = sizeof(struct talitos_export_state), 2931497f2e6bSLee Nipper .halg.base = { 2932497f2e6bSLee Nipper .cra_name = "sha512", 2933497f2e6bSLee Nipper .cra_driver_name = "sha512-talitos", 2934497f2e6bSLee Nipper .cra_blocksize = SHA512_BLOCK_SIZE, 2935b8aa7dc5SMikulas Patocka .cra_flags = CRYPTO_ALG_ASYNC | 2936b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY, 2937497f2e6bSLee Nipper } 2938497f2e6bSLee Nipper }, 2939497f2e6bSLee Nipper .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 2940497f2e6bSLee Nipper DESC_HDR_SEL0_MDEUB | 2941497f2e6bSLee Nipper DESC_HDR_MODE0_MDEUB_SHA512, 2942497f2e6bSLee Nipper }, 294379b3a418SLee Nipper { .type = CRYPTO_ALG_TYPE_AHASH, 294479b3a418SLee Nipper .alg.hash = { 294579b3a418SLee Nipper .halg.digestsize = MD5_DIGEST_SIZE, 29463639ca84SHoria Geant? .halg.statesize = sizeof(struct talitos_export_state), 294779b3a418SLee Nipper .halg.base = { 294879b3a418SLee Nipper .cra_name = "hmac(md5)", 294979b3a418SLee Nipper .cra_driver_name = "hmac-md5-talitos", 2950b3988618SMartin Hicks .cra_blocksize = MD5_HMAC_BLOCK_SIZE, 2951b8aa7dc5SMikulas Patocka .cra_flags = CRYPTO_ALG_ASYNC | 2952b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY, 295379b3a418SLee Nipper } 295479b3a418SLee Nipper }, 295579b3a418SLee Nipper .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 295679b3a418SLee Nipper DESC_HDR_SEL0_MDEUA | 295779b3a418SLee Nipper DESC_HDR_MODE0_MDEU_MD5, 295879b3a418SLee Nipper }, 295979b3a418SLee Nipper { .type = CRYPTO_ALG_TYPE_AHASH, 296079b3a418SLee Nipper .alg.hash = { 296179b3a418SLee Nipper .halg.digestsize = SHA1_DIGEST_SIZE, 29623639ca84SHoria Geant? .halg.statesize = sizeof(struct talitos_export_state), 296379b3a418SLee Nipper .halg.base = { 296479b3a418SLee Nipper .cra_name = "hmac(sha1)", 296579b3a418SLee Nipper .cra_driver_name = "hmac-sha1-talitos", 296679b3a418SLee Nipper .cra_blocksize = SHA1_BLOCK_SIZE, 2967b8aa7dc5SMikulas Patocka .cra_flags = CRYPTO_ALG_ASYNC | 2968b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY, 296979b3a418SLee Nipper } 297079b3a418SLee Nipper }, 297179b3a418SLee Nipper .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 297279b3a418SLee Nipper DESC_HDR_SEL0_MDEUA | 297379b3a418SLee Nipper DESC_HDR_MODE0_MDEU_SHA1, 297479b3a418SLee Nipper }, 297579b3a418SLee Nipper { .type = CRYPTO_ALG_TYPE_AHASH, 297679b3a418SLee Nipper .alg.hash = { 297779b3a418SLee Nipper .halg.digestsize = SHA224_DIGEST_SIZE, 29783639ca84SHoria Geant? .halg.statesize = sizeof(struct talitos_export_state), 297979b3a418SLee Nipper .halg.base = { 298079b3a418SLee Nipper .cra_name = "hmac(sha224)", 298179b3a418SLee Nipper .cra_driver_name = "hmac-sha224-talitos", 298279b3a418SLee Nipper .cra_blocksize = SHA224_BLOCK_SIZE, 2983b8aa7dc5SMikulas Patocka .cra_flags = CRYPTO_ALG_ASYNC | 2984b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY, 298579b3a418SLee Nipper } 298679b3a418SLee Nipper }, 298779b3a418SLee Nipper .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 298879b3a418SLee Nipper DESC_HDR_SEL0_MDEUA | 298979b3a418SLee Nipper DESC_HDR_MODE0_MDEU_SHA224, 299079b3a418SLee Nipper }, 299179b3a418SLee Nipper { .type = CRYPTO_ALG_TYPE_AHASH, 299279b3a418SLee Nipper .alg.hash = { 299379b3a418SLee Nipper .halg.digestsize = SHA256_DIGEST_SIZE, 29943639ca84SHoria Geant? .halg.statesize = sizeof(struct talitos_export_state), 299579b3a418SLee Nipper .halg.base = { 299679b3a418SLee Nipper .cra_name = "hmac(sha256)", 299779b3a418SLee Nipper .cra_driver_name = "hmac-sha256-talitos", 299879b3a418SLee Nipper .cra_blocksize = SHA256_BLOCK_SIZE, 2999b8aa7dc5SMikulas Patocka .cra_flags = CRYPTO_ALG_ASYNC | 3000b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY, 300179b3a418SLee Nipper } 300279b3a418SLee Nipper }, 300379b3a418SLee Nipper .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 300479b3a418SLee Nipper DESC_HDR_SEL0_MDEUA | 300579b3a418SLee Nipper DESC_HDR_MODE0_MDEU_SHA256, 300679b3a418SLee Nipper }, 300779b3a418SLee Nipper { .type = CRYPTO_ALG_TYPE_AHASH, 300879b3a418SLee Nipper .alg.hash = { 300979b3a418SLee Nipper .halg.digestsize = SHA384_DIGEST_SIZE, 30103639ca84SHoria Geant? .halg.statesize = sizeof(struct talitos_export_state), 301179b3a418SLee Nipper .halg.base = { 301279b3a418SLee Nipper .cra_name = "hmac(sha384)", 301379b3a418SLee Nipper .cra_driver_name = "hmac-sha384-talitos", 301479b3a418SLee Nipper .cra_blocksize = SHA384_BLOCK_SIZE, 3015b8aa7dc5SMikulas Patocka .cra_flags = CRYPTO_ALG_ASYNC | 3016b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY, 301779b3a418SLee Nipper } 301879b3a418SLee Nipper }, 301979b3a418SLee Nipper .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 302079b3a418SLee Nipper DESC_HDR_SEL0_MDEUB | 302179b3a418SLee Nipper DESC_HDR_MODE0_MDEUB_SHA384, 302279b3a418SLee Nipper }, 302379b3a418SLee Nipper { .type = CRYPTO_ALG_TYPE_AHASH, 302479b3a418SLee Nipper .alg.hash = { 302579b3a418SLee Nipper .halg.digestsize = SHA512_DIGEST_SIZE, 30263639ca84SHoria Geant? .halg.statesize = sizeof(struct talitos_export_state), 302779b3a418SLee Nipper .halg.base = { 302879b3a418SLee Nipper .cra_name = "hmac(sha512)", 302979b3a418SLee Nipper .cra_driver_name = "hmac-sha512-talitos", 303079b3a418SLee Nipper .cra_blocksize = SHA512_BLOCK_SIZE, 3031b8aa7dc5SMikulas Patocka .cra_flags = CRYPTO_ALG_ASYNC | 3032b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY, 303379b3a418SLee Nipper } 303479b3a418SLee Nipper }, 303579b3a418SLee Nipper .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 303679b3a418SLee Nipper DESC_HDR_SEL0_MDEUB | 303779b3a418SLee Nipper DESC_HDR_MODE0_MDEUB_SHA512, 303879b3a418SLee Nipper } 30399c4a7965SKim Phillips }; 30409c4a7965SKim Phillips 30419c4a7965SKim Phillips struct talitos_crypto_alg { 30429c4a7965SKim Phillips struct list_head entry; 30439c4a7965SKim Phillips struct device *dev; 3044acbf7c62SLee Nipper struct talitos_alg_template algt; 30459c4a7965SKim Phillips }; 30469c4a7965SKim Phillips 304789d124cbSJonas Eymann static int talitos_init_common(struct talitos_ctx *ctx, 304889d124cbSJonas Eymann struct talitos_crypto_alg *talitos_alg) 30499c4a7965SKim Phillips { 30505228f0f7SKim Phillips struct talitos_private *priv; 30519c4a7965SKim Phillips 30529c4a7965SKim Phillips /* update context with ptr to dev */ 30539c4a7965SKim Phillips ctx->dev = talitos_alg->dev; 305419bbbc63SKim Phillips 30555228f0f7SKim Phillips /* assign SEC channel to tfm in round-robin fashion */ 30565228f0f7SKim Phillips priv = dev_get_drvdata(ctx->dev); 30575228f0f7SKim Phillips ctx->ch = atomic_inc_return(&priv->last_chan) & 30585228f0f7SKim Phillips (priv->num_channels - 1); 30595228f0f7SKim Phillips 30609c4a7965SKim Phillips /* copy descriptor header template value */ 3061acbf7c62SLee Nipper ctx->desc_hdr_template = talitos_alg->algt.desc_hdr_template; 30629c4a7965SKim Phillips 3063602dba5aSKim Phillips /* select done notification */ 3064602dba5aSKim Phillips ctx->desc_hdr_template |= DESC_HDR_DONE_NOTIFY; 3065602dba5aSKim Phillips 3066497f2e6bSLee Nipper return 0; 3067497f2e6bSLee Nipper } 3068497f2e6bSLee Nipper 3069aeb4c132SHerbert Xu static int talitos_cra_init_aead(struct crypto_aead *tfm) 3070497f2e6bSLee Nipper { 307189d124cbSJonas Eymann struct aead_alg *alg = crypto_aead_alg(tfm); 307289d124cbSJonas Eymann struct talitos_crypto_alg *talitos_alg; 307389d124cbSJonas Eymann struct talitos_ctx *ctx = crypto_aead_ctx(tfm); 307489d124cbSJonas Eymann 307589d124cbSJonas Eymann talitos_alg = container_of(alg, struct talitos_crypto_alg, 307689d124cbSJonas Eymann algt.alg.aead); 307789d124cbSJonas Eymann 307889d124cbSJonas Eymann return talitos_init_common(ctx, talitos_alg); 30799c4a7965SKim Phillips } 30809c4a7965SKim Phillips 3081373960d7SArd Biesheuvel static int talitos_cra_init_skcipher(struct crypto_skcipher *tfm) 3082373960d7SArd Biesheuvel { 3083373960d7SArd Biesheuvel struct skcipher_alg *alg = crypto_skcipher_alg(tfm); 3084373960d7SArd Biesheuvel struct talitos_crypto_alg *talitos_alg; 3085373960d7SArd Biesheuvel struct talitos_ctx *ctx = crypto_skcipher_ctx(tfm); 3086373960d7SArd Biesheuvel 3087373960d7SArd Biesheuvel talitos_alg = container_of(alg, struct talitos_crypto_alg, 3088373960d7SArd Biesheuvel algt.alg.skcipher); 3089373960d7SArd Biesheuvel 3090373960d7SArd Biesheuvel return talitos_init_common(ctx, talitos_alg); 3091373960d7SArd Biesheuvel } 3092373960d7SArd Biesheuvel 3093497f2e6bSLee Nipper static int talitos_cra_init_ahash(struct crypto_tfm *tfm) 3094497f2e6bSLee Nipper { 3095373960d7SArd Biesheuvel struct crypto_alg *alg = tfm->__crt_alg; 3096373960d7SArd Biesheuvel struct talitos_crypto_alg *talitos_alg; 3097497f2e6bSLee Nipper struct talitos_ctx *ctx = crypto_tfm_ctx(tfm); 3098497f2e6bSLee Nipper 3099373960d7SArd Biesheuvel talitos_alg = container_of(__crypto_ahash_alg(alg), 3100373960d7SArd Biesheuvel struct talitos_crypto_alg, 3101373960d7SArd Biesheuvel algt.alg.hash); 3102497f2e6bSLee Nipper 3103497f2e6bSLee Nipper ctx->keylen = 0; 3104497f2e6bSLee Nipper crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), 3105497f2e6bSLee Nipper sizeof(struct talitos_ahash_req_ctx)); 3106497f2e6bSLee Nipper 3107373960d7SArd Biesheuvel return talitos_init_common(ctx, talitos_alg); 3108497f2e6bSLee Nipper } 3109497f2e6bSLee Nipper 31102e13ce08SLEROY Christophe static void talitos_cra_exit(struct crypto_tfm *tfm) 31112e13ce08SLEROY Christophe { 31122e13ce08SLEROY Christophe struct talitos_ctx *ctx = crypto_tfm_ctx(tfm); 31132e13ce08SLEROY Christophe struct device *dev = ctx->dev; 31142e13ce08SLEROY Christophe 31152e13ce08SLEROY Christophe if (ctx->keylen) 31162e13ce08SLEROY Christophe dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE); 31172e13ce08SLEROY Christophe } 31182e13ce08SLEROY Christophe 31199c4a7965SKim Phillips /* 31209c4a7965SKim Phillips * given the alg's descriptor header template, determine whether descriptor 31219c4a7965SKim Phillips * type and primary/secondary execution units required match the hw 31229c4a7965SKim Phillips * capabilities description provided in the device tree node. 31239c4a7965SKim Phillips */ 31249c4a7965SKim Phillips static int hw_supports(struct device *dev, __be32 desc_hdr_template) 31259c4a7965SKim Phillips { 31269c4a7965SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); 31279c4a7965SKim Phillips int ret; 31289c4a7965SKim Phillips 31299c4a7965SKim Phillips ret = (1 << DESC_TYPE(desc_hdr_template) & priv->desc_types) && 31309c4a7965SKim Phillips (1 << PRIMARY_EU(desc_hdr_template) & priv->exec_units); 31319c4a7965SKim Phillips 31329c4a7965SKim Phillips if (SECONDARY_EU(desc_hdr_template)) 31339c4a7965SKim Phillips ret = ret && (1 << SECONDARY_EU(desc_hdr_template) 31349c4a7965SKim Phillips & priv->exec_units); 31359c4a7965SKim Phillips 31369c4a7965SKim Phillips return ret; 31379c4a7965SKim Phillips } 31389c4a7965SKim Phillips 31392dc11581SGrant Likely static int talitos_remove(struct platform_device *ofdev) 31409c4a7965SKim Phillips { 31419c4a7965SKim Phillips struct device *dev = &ofdev->dev; 31429c4a7965SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); 31439c4a7965SKim Phillips struct talitos_crypto_alg *t_alg, *n; 31449c4a7965SKim Phillips int i; 31459c4a7965SKim Phillips 31469c4a7965SKim Phillips list_for_each_entry_safe(t_alg, n, &priv->alg_list, entry) { 3147acbf7c62SLee Nipper switch (t_alg->algt.type) { 3148373960d7SArd Biesheuvel case CRYPTO_ALG_TYPE_SKCIPHER: 3149373960d7SArd Biesheuvel crypto_unregister_skcipher(&t_alg->algt.alg.skcipher); 3150acbf7c62SLee Nipper break; 3151aeb4c132SHerbert Xu case CRYPTO_ALG_TYPE_AEAD: 3152aeb4c132SHerbert Xu crypto_unregister_aead(&t_alg->algt.alg.aead); 31535fc194eaSGustavo A. R. Silva break; 3154acbf7c62SLee Nipper case CRYPTO_ALG_TYPE_AHASH: 3155acbf7c62SLee Nipper crypto_unregister_ahash(&t_alg->algt.alg.hash); 3156acbf7c62SLee Nipper break; 3157acbf7c62SLee Nipper } 31589c4a7965SKim Phillips list_del(&t_alg->entry); 31599c4a7965SKim Phillips } 31609c4a7965SKim Phillips 31619c4a7965SKim Phillips if (hw_supports(dev, DESC_HDR_SEL0_RNG)) 31629c4a7965SKim Phillips talitos_unregister_rng(dev); 31639c4a7965SKim Phillips 3164c3e337f8SKim Phillips for (i = 0; i < 2; i++) 31652cdba3cfSKim Phillips if (priv->irq[i]) { 3166c3e337f8SKim Phillips free_irq(priv->irq[i], dev); 3167c3e337f8SKim Phillips irq_dispose_mapping(priv->irq[i]); 31689c4a7965SKim Phillips } 31699c4a7965SKim Phillips 3170c3e337f8SKim Phillips tasklet_kill(&priv->done_task[0]); 31712cdba3cfSKim Phillips if (priv->irq[1]) 3172c3e337f8SKim Phillips tasklet_kill(&priv->done_task[1]); 31739c4a7965SKim Phillips 31749c4a7965SKim Phillips return 0; 31759c4a7965SKim Phillips } 31769c4a7965SKim Phillips 31779c4a7965SKim Phillips static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev, 31789c4a7965SKim Phillips struct talitos_alg_template 31799c4a7965SKim Phillips *template) 31809c4a7965SKim Phillips { 318160f208d7SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); 31829c4a7965SKim Phillips struct talitos_crypto_alg *t_alg; 31839c4a7965SKim Phillips struct crypto_alg *alg; 31849c4a7965SKim Phillips 318524b92ff2SLEROY Christophe t_alg = devm_kzalloc(dev, sizeof(struct talitos_crypto_alg), 318624b92ff2SLEROY Christophe GFP_KERNEL); 31879c4a7965SKim Phillips if (!t_alg) 31889c4a7965SKim Phillips return ERR_PTR(-ENOMEM); 31899c4a7965SKim Phillips 3190acbf7c62SLee Nipper t_alg->algt = *template; 3191acbf7c62SLee Nipper 3192acbf7c62SLee Nipper switch (t_alg->algt.type) { 3193373960d7SArd Biesheuvel case CRYPTO_ALG_TYPE_SKCIPHER: 3194373960d7SArd Biesheuvel alg = &t_alg->algt.alg.skcipher.base; 31952e13ce08SLEROY Christophe alg->cra_exit = talitos_cra_exit; 3196373960d7SArd Biesheuvel t_alg->algt.alg.skcipher.init = talitos_cra_init_skcipher; 3197373960d7SArd Biesheuvel t_alg->algt.alg.skcipher.setkey = 3198373960d7SArd Biesheuvel t_alg->algt.alg.skcipher.setkey ?: skcipher_setkey; 3199373960d7SArd Biesheuvel t_alg->algt.alg.skcipher.encrypt = skcipher_encrypt; 3200373960d7SArd Biesheuvel t_alg->algt.alg.skcipher.decrypt = skcipher_decrypt; 320143a942d2SChristophe Leroy if (!strcmp(alg->cra_name, "ctr(aes)") && !has_ftr_sec1(priv) && 320243a942d2SChristophe Leroy DESC_TYPE(t_alg->algt.desc_hdr_template) != 320343a942d2SChristophe Leroy DESC_TYPE(DESC_HDR_TYPE_AESU_CTR_NONSNOOP)) { 320443a942d2SChristophe Leroy devm_kfree(dev, t_alg); 320543a942d2SChristophe Leroy return ERR_PTR(-ENOTSUPP); 320643a942d2SChristophe Leroy } 3207497f2e6bSLee Nipper break; 3208acbf7c62SLee Nipper case CRYPTO_ALG_TYPE_AEAD: 3209aeb4c132SHerbert Xu alg = &t_alg->algt.alg.aead.base; 32102e13ce08SLEROY Christophe alg->cra_exit = talitos_cra_exit; 3211aeb4c132SHerbert Xu t_alg->algt.alg.aead.init = talitos_cra_init_aead; 3212ef7c5c85SHerbert Xu t_alg->algt.alg.aead.setkey = t_alg->algt.alg.aead.setkey ?: 3213ef7c5c85SHerbert Xu aead_setkey; 3214aeb4c132SHerbert Xu t_alg->algt.alg.aead.encrypt = aead_encrypt; 3215aeb4c132SHerbert Xu t_alg->algt.alg.aead.decrypt = aead_decrypt; 32166cda075aSLEROY Christophe if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) && 32176cda075aSLEROY Christophe !strncmp(alg->cra_name, "authenc(hmac(sha224)", 20)) { 321824b92ff2SLEROY Christophe devm_kfree(dev, t_alg); 32196cda075aSLEROY Christophe return ERR_PTR(-ENOTSUPP); 32206cda075aSLEROY Christophe } 3221acbf7c62SLee Nipper break; 3222acbf7c62SLee Nipper case CRYPTO_ALG_TYPE_AHASH: 3223acbf7c62SLee Nipper alg = &t_alg->algt.alg.hash.halg.base; 3224497f2e6bSLee Nipper alg->cra_init = talitos_cra_init_ahash; 3225ad4cd51fSLEROY Christophe alg->cra_exit = talitos_cra_exit; 3226b286e003SKim Phillips t_alg->algt.alg.hash.init = ahash_init; 3227b286e003SKim Phillips t_alg->algt.alg.hash.update = ahash_update; 3228b286e003SKim Phillips t_alg->algt.alg.hash.final = ahash_final; 3229b286e003SKim Phillips t_alg->algt.alg.hash.finup = ahash_finup; 3230b286e003SKim Phillips t_alg->algt.alg.hash.digest = ahash_digest; 323156136631SLEROY Christophe if (!strncmp(alg->cra_name, "hmac", 4)) 3232b286e003SKim Phillips t_alg->algt.alg.hash.setkey = ahash_setkey; 32333639ca84SHoria Geant? t_alg->algt.alg.hash.import = ahash_import; 32343639ca84SHoria Geant? t_alg->algt.alg.hash.export = ahash_export; 3235b286e003SKim Phillips 323679b3a418SLee Nipper if (!(priv->features & TALITOS_FTR_HMAC_OK) && 32370b2730d8SKim Phillips !strncmp(alg->cra_name, "hmac", 4)) { 323824b92ff2SLEROY Christophe devm_kfree(dev, t_alg); 323979b3a418SLee Nipper return ERR_PTR(-ENOTSUPP); 32400b2730d8SKim Phillips } 324160f208d7SKim Phillips if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) && 324279b3a418SLee Nipper (!strcmp(alg->cra_name, "sha224") || 324379b3a418SLee Nipper !strcmp(alg->cra_name, "hmac(sha224)"))) { 324460f208d7SKim Phillips t_alg->algt.alg.hash.init = ahash_init_sha224_swinit; 324560f208d7SKim Phillips t_alg->algt.desc_hdr_template = 324660f208d7SKim Phillips DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | 324760f208d7SKim Phillips DESC_HDR_SEL0_MDEUA | 324860f208d7SKim Phillips DESC_HDR_MODE0_MDEU_SHA256; 324960f208d7SKim Phillips } 3250497f2e6bSLee Nipper break; 32511d11911aSKim Phillips default: 32521d11911aSKim Phillips dev_err(dev, "unknown algorithm type %d\n", t_alg->algt.type); 325324b92ff2SLEROY Christophe devm_kfree(dev, t_alg); 32541d11911aSKim Phillips return ERR_PTR(-EINVAL); 3255acbf7c62SLee Nipper } 32569c4a7965SKim Phillips 32579c4a7965SKim Phillips alg->cra_module = THIS_MODULE; 3258b0057763SLEROY Christophe if (t_alg->algt.priority) 3259b0057763SLEROY Christophe alg->cra_priority = t_alg->algt.priority; 3260b0057763SLEROY Christophe else 32619c4a7965SKim Phillips alg->cra_priority = TALITOS_CRA_PRIORITY; 3262c9cca703SChristophe Leroy if (has_ftr_sec1(priv)) 3263c9cca703SChristophe Leroy alg->cra_alignmask = 3; 3264c9cca703SChristophe Leroy else 32659c4a7965SKim Phillips alg->cra_alignmask = 0; 32669c4a7965SKim Phillips alg->cra_ctxsize = sizeof(struct talitos_ctx); 3267d912bb76SNikos Mavrogiannopoulos alg->cra_flags |= CRYPTO_ALG_KERN_DRIVER_ONLY; 32689c4a7965SKim Phillips 32699c4a7965SKim Phillips t_alg->dev = dev; 32709c4a7965SKim Phillips 32719c4a7965SKim Phillips return t_alg; 32729c4a7965SKim Phillips } 32739c4a7965SKim Phillips 3274c3e337f8SKim Phillips static int talitos_probe_irq(struct platform_device *ofdev) 3275c3e337f8SKim Phillips { 3276c3e337f8SKim Phillips struct device *dev = &ofdev->dev; 3277c3e337f8SKim Phillips struct device_node *np = ofdev->dev.of_node; 3278c3e337f8SKim Phillips struct talitos_private *priv = dev_get_drvdata(dev); 3279c3e337f8SKim Phillips int err; 3280dd3c0987SLEROY Christophe bool is_sec1 = has_ftr_sec1(priv); 3281c3e337f8SKim Phillips 3282c3e337f8SKim Phillips priv->irq[0] = irq_of_parse_and_map(np, 0); 32832cdba3cfSKim Phillips if (!priv->irq[0]) { 3284c3e337f8SKim Phillips dev_err(dev, "failed to map irq\n"); 3285c3e337f8SKim Phillips return -EINVAL; 3286c3e337f8SKim Phillips } 3287dd3c0987SLEROY Christophe if (is_sec1) { 3288dd3c0987SLEROY Christophe err = request_irq(priv->irq[0], talitos1_interrupt_4ch, 0, 3289dd3c0987SLEROY Christophe dev_driver_string(dev), dev); 3290dd3c0987SLEROY Christophe goto primary_out; 3291dd3c0987SLEROY Christophe } 3292c3e337f8SKim Phillips 3293c3e337f8SKim Phillips priv->irq[1] = irq_of_parse_and_map(np, 1); 3294c3e337f8SKim Phillips 3295c3e337f8SKim Phillips /* get the primary irq line */ 32962cdba3cfSKim Phillips if (!priv->irq[1]) { 3297dd3c0987SLEROY Christophe err = request_irq(priv->irq[0], talitos2_interrupt_4ch, 0, 3298c3e337f8SKim Phillips dev_driver_string(dev), dev); 3299c3e337f8SKim Phillips goto primary_out; 3300c3e337f8SKim Phillips } 3301c3e337f8SKim Phillips 3302dd3c0987SLEROY Christophe err = request_irq(priv->irq[0], talitos2_interrupt_ch0_2, 0, 3303c3e337f8SKim Phillips dev_driver_string(dev), dev); 3304c3e337f8SKim Phillips if (err) 3305c3e337f8SKim Phillips goto primary_out; 3306c3e337f8SKim Phillips 3307c3e337f8SKim Phillips /* get the secondary irq line */ 3308dd3c0987SLEROY Christophe err = request_irq(priv->irq[1], talitos2_interrupt_ch1_3, 0, 3309c3e337f8SKim Phillips dev_driver_string(dev), dev); 3310c3e337f8SKim Phillips if (err) { 3311c3e337f8SKim Phillips dev_err(dev, "failed to request secondary irq\n"); 3312c3e337f8SKim Phillips irq_dispose_mapping(priv->irq[1]); 33132cdba3cfSKim Phillips priv->irq[1] = 0; 3314c3e337f8SKim Phillips } 3315c3e337f8SKim Phillips 3316c3e337f8SKim Phillips return err; 3317c3e337f8SKim Phillips 3318c3e337f8SKim Phillips primary_out: 3319c3e337f8SKim Phillips if (err) { 3320c3e337f8SKim Phillips dev_err(dev, "failed to request primary irq\n"); 3321c3e337f8SKim Phillips irq_dispose_mapping(priv->irq[0]); 33222cdba3cfSKim Phillips priv->irq[0] = 0; 3323c3e337f8SKim Phillips } 3324c3e337f8SKim Phillips 3325c3e337f8SKim Phillips return err; 3326c3e337f8SKim Phillips } 3327c3e337f8SKim Phillips 33281c48a5c9SGrant Likely static int talitos_probe(struct platform_device *ofdev) 33299c4a7965SKim Phillips { 33309c4a7965SKim Phillips struct device *dev = &ofdev->dev; 333161c7a080SGrant Likely struct device_node *np = ofdev->dev.of_node; 33329c4a7965SKim Phillips struct talitos_private *priv; 33339c4a7965SKim Phillips int i, err; 33345fa7fa14SLEROY Christophe int stride; 3335fd5ea7f0SLEROY Christophe struct resource *res; 33369c4a7965SKim Phillips 333724b92ff2SLEROY Christophe priv = devm_kzalloc(dev, sizeof(struct talitos_private), GFP_KERNEL); 33389c4a7965SKim Phillips if (!priv) 33399c4a7965SKim Phillips return -ENOMEM; 33409c4a7965SKim Phillips 3341f3de9cb1SKevin Hao INIT_LIST_HEAD(&priv->alg_list); 3342f3de9cb1SKevin Hao 33439c4a7965SKim Phillips dev_set_drvdata(dev, priv); 33449c4a7965SKim Phillips 33459c4a7965SKim Phillips priv->ofdev = ofdev; 33469c4a7965SKim Phillips 3347511d63cbSHoria Geanta spin_lock_init(&priv->reg_lock); 3348511d63cbSHoria Geanta 3349fd5ea7f0SLEROY Christophe res = platform_get_resource(ofdev, IORESOURCE_MEM, 0); 3350fd5ea7f0SLEROY Christophe if (!res) 3351fd5ea7f0SLEROY Christophe return -ENXIO; 3352fd5ea7f0SLEROY Christophe priv->reg = devm_ioremap(dev, res->start, resource_size(res)); 33539c4a7965SKim Phillips if (!priv->reg) { 33549c4a7965SKim Phillips dev_err(dev, "failed to of_iomap\n"); 33559c4a7965SKim Phillips err = -ENOMEM; 33569c4a7965SKim Phillips goto err_out; 33579c4a7965SKim Phillips } 33589c4a7965SKim Phillips 33599c4a7965SKim Phillips /* get SEC version capabilities from device tree */ 3360fa14c6cfSLEROY Christophe of_property_read_u32(np, "fsl,num-channels", &priv->num_channels); 3361fa14c6cfSLEROY Christophe of_property_read_u32(np, "fsl,channel-fifo-len", &priv->chfifo_len); 3362fa14c6cfSLEROY Christophe of_property_read_u32(np, "fsl,exec-units-mask", &priv->exec_units); 3363fa14c6cfSLEROY Christophe of_property_read_u32(np, "fsl,descriptor-types-mask", 3364fa14c6cfSLEROY Christophe &priv->desc_types); 33659c4a7965SKim Phillips 33669c4a7965SKim Phillips if (!is_power_of_2(priv->num_channels) || !priv->chfifo_len || 33679c4a7965SKim Phillips !priv->exec_units || !priv->desc_types) { 33689c4a7965SKim Phillips dev_err(dev, "invalid property data in device tree node\n"); 33699c4a7965SKim Phillips err = -EINVAL; 33709c4a7965SKim Phillips goto err_out; 33719c4a7965SKim Phillips } 33729c4a7965SKim Phillips 3373f3c85bc1SLee Nipper if (of_device_is_compatible(np, "fsl,sec3.0")) 3374f3c85bc1SLee Nipper priv->features |= TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT; 3375f3c85bc1SLee Nipper 3376fe5720e2SKim Phillips if (of_device_is_compatible(np, "fsl,sec2.1")) 337760f208d7SKim Phillips priv->features |= TALITOS_FTR_HW_AUTH_CHECK | 337879b3a418SLee Nipper TALITOS_FTR_SHA224_HWINIT | 337979b3a418SLee Nipper TALITOS_FTR_HMAC_OK; 3380fe5720e2SKim Phillips 338121590888SLEROY Christophe if (of_device_is_compatible(np, "fsl,sec1.0")) 338221590888SLEROY Christophe priv->features |= TALITOS_FTR_SEC1; 338321590888SLEROY Christophe 33845fa7fa14SLEROY Christophe if (of_device_is_compatible(np, "fsl,sec1.2")) { 33855fa7fa14SLEROY Christophe priv->reg_deu = priv->reg + TALITOS12_DEU; 33865fa7fa14SLEROY Christophe priv->reg_aesu = priv->reg + TALITOS12_AESU; 33875fa7fa14SLEROY Christophe priv->reg_mdeu = priv->reg + TALITOS12_MDEU; 33885fa7fa14SLEROY Christophe stride = TALITOS1_CH_STRIDE; 33895fa7fa14SLEROY Christophe } else if (of_device_is_compatible(np, "fsl,sec1.0")) { 33905fa7fa14SLEROY Christophe priv->reg_deu = priv->reg + TALITOS10_DEU; 33915fa7fa14SLEROY Christophe priv->reg_aesu = priv->reg + TALITOS10_AESU; 33925fa7fa14SLEROY Christophe priv->reg_mdeu = priv->reg + TALITOS10_MDEU; 33935fa7fa14SLEROY Christophe priv->reg_afeu = priv->reg + TALITOS10_AFEU; 33945fa7fa14SLEROY Christophe priv->reg_rngu = priv->reg + TALITOS10_RNGU; 33955fa7fa14SLEROY Christophe priv->reg_pkeu = priv->reg + TALITOS10_PKEU; 33965fa7fa14SLEROY Christophe stride = TALITOS1_CH_STRIDE; 33975fa7fa14SLEROY Christophe } else { 33985fa7fa14SLEROY Christophe priv->reg_deu = priv->reg + TALITOS2_DEU; 33995fa7fa14SLEROY Christophe priv->reg_aesu = priv->reg + TALITOS2_AESU; 34005fa7fa14SLEROY Christophe priv->reg_mdeu = priv->reg + TALITOS2_MDEU; 34015fa7fa14SLEROY Christophe priv->reg_afeu = priv->reg + TALITOS2_AFEU; 34025fa7fa14SLEROY Christophe priv->reg_rngu = priv->reg + TALITOS2_RNGU; 34035fa7fa14SLEROY Christophe priv->reg_pkeu = priv->reg + TALITOS2_PKEU; 34045fa7fa14SLEROY Christophe priv->reg_keu = priv->reg + TALITOS2_KEU; 34055fa7fa14SLEROY Christophe priv->reg_crcu = priv->reg + TALITOS2_CRCU; 34065fa7fa14SLEROY Christophe stride = TALITOS2_CH_STRIDE; 34075fa7fa14SLEROY Christophe } 34085fa7fa14SLEROY Christophe 3409dd3c0987SLEROY Christophe err = talitos_probe_irq(ofdev); 3410dd3c0987SLEROY Christophe if (err) 3411dd3c0987SLEROY Christophe goto err_out; 3412dd3c0987SLEROY Christophe 3413c8c74647SChristophe Leroy if (has_ftr_sec1(priv)) { 34149c02e285SLEROY Christophe if (priv->num_channels == 1) 34159c02e285SLEROY Christophe tasklet_init(&priv->done_task[0], talitos1_done_ch0, 34169c02e285SLEROY Christophe (unsigned long)dev); 34179c02e285SLEROY Christophe else 3418dd3c0987SLEROY Christophe tasklet_init(&priv->done_task[0], talitos1_done_4ch, 3419dd3c0987SLEROY Christophe (unsigned long)dev); 3420dd3c0987SLEROY Christophe } else { 34219c02e285SLEROY Christophe if (priv->irq[1]) { 3422dd3c0987SLEROY Christophe tasklet_init(&priv->done_task[0], talitos2_done_ch0_2, 3423dd3c0987SLEROY Christophe (unsigned long)dev); 3424dd3c0987SLEROY Christophe tasklet_init(&priv->done_task[1], talitos2_done_ch1_3, 3425dd3c0987SLEROY Christophe (unsigned long)dev); 34269c02e285SLEROY Christophe } else if (priv->num_channels == 1) { 34279c02e285SLEROY Christophe tasklet_init(&priv->done_task[0], talitos2_done_ch0, 34289c02e285SLEROY Christophe (unsigned long)dev); 34299c02e285SLEROY Christophe } else { 34309c02e285SLEROY Christophe tasklet_init(&priv->done_task[0], talitos2_done_4ch, 34319c02e285SLEROY Christophe (unsigned long)dev); 3432dd3c0987SLEROY Christophe } 3433dd3c0987SLEROY Christophe } 3434dd3c0987SLEROY Christophe 3435a86854d0SKees Cook priv->chan = devm_kcalloc(dev, 3436a86854d0SKees Cook priv->num_channels, 3437a86854d0SKees Cook sizeof(struct talitos_channel), 3438a86854d0SKees Cook GFP_KERNEL); 34394b992628SKim Phillips if (!priv->chan) { 34404b992628SKim Phillips dev_err(dev, "failed to allocate channel management space\n"); 34419c4a7965SKim Phillips err = -ENOMEM; 34429c4a7965SKim Phillips goto err_out; 34439c4a7965SKim Phillips } 34449c4a7965SKim Phillips 3445f641ddddSMartin Hicks priv->fifo_len = roundup_pow_of_two(priv->chfifo_len); 3446f641ddddSMartin Hicks 3447c3e337f8SKim Phillips for (i = 0; i < priv->num_channels; i++) { 34485fa7fa14SLEROY Christophe priv->chan[i].reg = priv->reg + stride * (i + 1); 34492cdba3cfSKim Phillips if (!priv->irq[1] || !(i & 1)) 3450c3e337f8SKim Phillips priv->chan[i].reg += TALITOS_CH_BASE_OFFSET; 3451ad42d5fcSKim Phillips 34524b992628SKim Phillips spin_lock_init(&priv->chan[i].head_lock); 34534b992628SKim Phillips spin_lock_init(&priv->chan[i].tail_lock); 34549c4a7965SKim Phillips 3455a86854d0SKees Cook priv->chan[i].fifo = devm_kcalloc(dev, 3456a86854d0SKees Cook priv->fifo_len, 3457a86854d0SKees Cook sizeof(struct talitos_request), 3458a86854d0SKees Cook GFP_KERNEL); 34594b992628SKim Phillips if (!priv->chan[i].fifo) { 34609c4a7965SKim Phillips dev_err(dev, "failed to allocate request fifo %d\n", i); 34619c4a7965SKim Phillips err = -ENOMEM; 34629c4a7965SKim Phillips goto err_out; 34639c4a7965SKim Phillips } 34649c4a7965SKim Phillips 34654b992628SKim Phillips atomic_set(&priv->chan[i].submit_count, 34664b992628SKim Phillips -(priv->chfifo_len - 1)); 3467f641ddddSMartin Hicks } 34689c4a7965SKim Phillips 346981eb024cSKim Phillips dma_set_mask(dev, DMA_BIT_MASK(36)); 347081eb024cSKim Phillips 34719c4a7965SKim Phillips /* reset and initialize the h/w */ 34729c4a7965SKim Phillips err = init_device(dev); 34739c4a7965SKim Phillips if (err) { 34749c4a7965SKim Phillips dev_err(dev, "failed to initialize device\n"); 34759c4a7965SKim Phillips goto err_out; 34769c4a7965SKim Phillips } 34779c4a7965SKim Phillips 34789c4a7965SKim Phillips /* register the RNG, if available */ 34799c4a7965SKim Phillips if (hw_supports(dev, DESC_HDR_SEL0_RNG)) { 34809c4a7965SKim Phillips err = talitos_register_rng(dev); 34819c4a7965SKim Phillips if (err) { 34829c4a7965SKim Phillips dev_err(dev, "failed to register hwrng: %d\n", err); 34839c4a7965SKim Phillips goto err_out; 34849c4a7965SKim Phillips } else 34859c4a7965SKim Phillips dev_info(dev, "hwrng\n"); 34869c4a7965SKim Phillips } 34879c4a7965SKim Phillips 34889c4a7965SKim Phillips /* register crypto algorithms the device supports */ 34899c4a7965SKim Phillips for (i = 0; i < ARRAY_SIZE(driver_algs); i++) { 34909c4a7965SKim Phillips if (hw_supports(dev, driver_algs[i].desc_hdr_template)) { 34919c4a7965SKim Phillips struct talitos_crypto_alg *t_alg; 3492aeb4c132SHerbert Xu struct crypto_alg *alg = NULL; 34939c4a7965SKim Phillips 34949c4a7965SKim Phillips t_alg = talitos_alg_alloc(dev, &driver_algs[i]); 34959c4a7965SKim Phillips if (IS_ERR(t_alg)) { 34969c4a7965SKim Phillips err = PTR_ERR(t_alg); 34970b2730d8SKim Phillips if (err == -ENOTSUPP) 349879b3a418SLee Nipper continue; 34999c4a7965SKim Phillips goto err_out; 35009c4a7965SKim Phillips } 35019c4a7965SKim Phillips 3502acbf7c62SLee Nipper switch (t_alg->algt.type) { 3503373960d7SArd Biesheuvel case CRYPTO_ALG_TYPE_SKCIPHER: 3504373960d7SArd Biesheuvel err = crypto_register_skcipher( 3505373960d7SArd Biesheuvel &t_alg->algt.alg.skcipher); 3506373960d7SArd Biesheuvel alg = &t_alg->algt.alg.skcipher.base; 3507acbf7c62SLee Nipper break; 3508aeb4c132SHerbert Xu 3509aeb4c132SHerbert Xu case CRYPTO_ALG_TYPE_AEAD: 3510aeb4c132SHerbert Xu err = crypto_register_aead( 3511aeb4c132SHerbert Xu &t_alg->algt.alg.aead); 3512aeb4c132SHerbert Xu alg = &t_alg->algt.alg.aead.base; 3513aeb4c132SHerbert Xu break; 3514aeb4c132SHerbert Xu 3515acbf7c62SLee Nipper case CRYPTO_ALG_TYPE_AHASH: 3516acbf7c62SLee Nipper err = crypto_register_ahash( 3517acbf7c62SLee Nipper &t_alg->algt.alg.hash); 3518aeb4c132SHerbert Xu alg = &t_alg->algt.alg.hash.halg.base; 3519acbf7c62SLee Nipper break; 3520acbf7c62SLee Nipper } 35219c4a7965SKim Phillips if (err) { 35229c4a7965SKim Phillips dev_err(dev, "%s alg registration failed\n", 3523aeb4c132SHerbert Xu alg->cra_driver_name); 352424b92ff2SLEROY Christophe devm_kfree(dev, t_alg); 3525991155baSHoria Geanta } else 35269c4a7965SKim Phillips list_add_tail(&t_alg->entry, &priv->alg_list); 35279c4a7965SKim Phillips } 35289c4a7965SKim Phillips } 35295b859b6eSKim Phillips if (!list_empty(&priv->alg_list)) 35305b859b6eSKim Phillips dev_info(dev, "%s algorithms registered in /proc/crypto\n", 35315b859b6eSKim Phillips (char *)of_get_property(np, "compatible", NULL)); 35329c4a7965SKim Phillips 35339c4a7965SKim Phillips return 0; 35349c4a7965SKim Phillips 35359c4a7965SKim Phillips err_out: 35369c4a7965SKim Phillips talitos_remove(ofdev); 35379c4a7965SKim Phillips 35389c4a7965SKim Phillips return err; 35399c4a7965SKim Phillips } 35409c4a7965SKim Phillips 35416c3f975aSMárton Németh static const struct of_device_id talitos_match[] = { 35420635b7dbSLEROY Christophe #ifdef CONFIG_CRYPTO_DEV_TALITOS1 35430635b7dbSLEROY Christophe { 35440635b7dbSLEROY Christophe .compatible = "fsl,sec1.0", 35450635b7dbSLEROY Christophe }, 35460635b7dbSLEROY Christophe #endif 35470635b7dbSLEROY Christophe #ifdef CONFIG_CRYPTO_DEV_TALITOS2 35489c4a7965SKim Phillips { 35499c4a7965SKim Phillips .compatible = "fsl,sec2.0", 35509c4a7965SKim Phillips }, 35510635b7dbSLEROY Christophe #endif 35529c4a7965SKim Phillips {}, 35539c4a7965SKim Phillips }; 35549c4a7965SKim Phillips MODULE_DEVICE_TABLE(of, talitos_match); 35559c4a7965SKim Phillips 35561c48a5c9SGrant Likely static struct platform_driver talitos_driver = { 35574018294bSGrant Likely .driver = { 35589c4a7965SKim Phillips .name = "talitos", 35594018294bSGrant Likely .of_match_table = talitos_match, 35604018294bSGrant Likely }, 35619c4a7965SKim Phillips .probe = talitos_probe, 3562596f1034SAl Viro .remove = talitos_remove, 35639c4a7965SKim Phillips }; 35649c4a7965SKim Phillips 3565741e8c2dSAxel Lin module_platform_driver(talitos_driver); 35669c4a7965SKim Phillips 35679c4a7965SKim Phillips MODULE_LICENSE("GPL"); 35689c4a7965SKim Phillips MODULE_AUTHOR("Kim Phillips <kim.phillips@freescale.com>"); 35699c4a7965SKim Phillips MODULE_DESCRIPTION("Freescale integrated security engine (SEC) driver"); 3570