lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20140711120939.DD0031A9740@localhost.localdomain>
Date:	Fri, 11 Jul 2014 14:09:39 +0200 (CEST)
From:	Christophe Leroy <christophe.leroy@....fr>
To:	Kim Phillips <kim.phillips@...escale.com>,
	Herbert Xu <herbert@...dor.apana.org.au>,
	"David S. Miller" <davem@...emloft.net>,
	Benjamin Herrenschmidt <benh@...nel.crashing.org>,
	Paul Mackerras <paulus@...ba.org>
CC:	linux-kernel@...r.kernel.org, linuxppc-dev@...ts.ozlabs.org,
	Joakim Tjernlund <joakim.tjernlund@...nsmode.se>,
	linux-crypto@...r.kernel.org
Subject: [RFC, prePATCH] crypto: talitos modified for powerpc 88x security engine

Here is a pre-patch for the support of the SEC ENGINE of MPC88x/MPC82xx
I have tried to make use of defines in order to keep a single driver for the two
TALITOS variants as suggested by Kim, but I'm not too happy about the quantity
of #ifdef
For the time being, it only supports basic crypto operations, not the combined
authentication/encryption ones.
Note that it has been tested on MPC885, but not on MPC82xx

I would be happy to receive comments and suggestions in order to improve this
first try.

Not-yet-signed-off-by: Christophe Leroy <christophe.leroy@....fr>

Index: b/drivers/crypto/talitos.c
===================================================================
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -53,10 +53,26 @@
 
 #include "talitos.h"
 
+#ifdef CONFIG_CRYPTO_DEV_TALITOS1
+static u8 padded_hash[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0,
+		0, 0, 0, 0, 0, 0, 0, 0,
+		0, 0, 0, 0, 0, 0, 0, 0,
+		0, 0, 0, 0, 0, 0, 0, 0,
+		0, 0, 0, 0, 0, 0, 0, 0,
+		0, 0, 0, 0, 0, 0, 0, 0,
+		0, 0, 0, 0, 0, 0, 0, 0,
+		0, 0, 0, 0, 0, 0, 0, 0,
+};
+#endif
+
 static void to_talitos_ptr(struct talitos_ptr *talitos_ptr, dma_addr_t dma_addr)
 {
 	talitos_ptr->ptr = cpu_to_be32(lower_32_bits(dma_addr));
+#ifdef CONFIG_CRYPTO_DEV_TALITOS1
+	talitos_ptr->res = 0;
+#else
 	talitos_ptr->eptr = upper_32_bits(dma_addr);
+#endif
 }
 
 /*
@@ -72,7 +88,11 @@
 
 	talitos_ptr->len = cpu_to_be16(len);
 	to_talitos_ptr(talitos_ptr, dma_addr);
+#ifdef CONFIG_CRYPTO_DEV_TALITOS1
+	talitos_ptr->res = 0;
+#else
 	talitos_ptr->j_extent = extent;
+#endif
 }
 
 /*
@@ -91,9 +111,17 @@
 	struct talitos_private *priv = dev_get_drvdata(dev);
 	unsigned int timeout = TALITOS_TIMEOUT;
 
+#ifdef CONFIG_CRYPTO_DEV_TALITOS1
+	setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, TALITOS_CCCR_LO_RESET);
+#else
 	setbits32(priv->chan[ch].reg + TALITOS_CCCR, TALITOS_CCCR_RESET);
+#endif
 
+#ifdef CONFIG_CRYPTO_DEV_TALITOS1
+	while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR_LO) & TALITOS_CCCR_LO_RESET)
+#else
 	while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) & TALITOS_CCCR_RESET)
+#endif
 	       && --timeout)
 		cpu_relax();
 
@@ -101,10 +129,11 @@
 		dev_err(dev, "failed to reset channel %d\n", ch);
 		return -EIO;
 	}
+dev_err(dev, "success to reset channel %d\n", ch);
 
 	/* set 36-bit addressing, done writeback enable and done IRQ enable */
 	setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, TALITOS_CCCR_LO_EAE |
-		  TALITOS_CCCR_LO_CDWE | TALITOS_CCCR_LO_CDIE);
+		  TALITOS_CCCR_LO_CDWE | TALITOS_CCCR_LO_CDIE /*| TALITOS_CCCR_LO_NT*/);
 
 	/* and ICCR writeback, if available */
 	if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
@@ -169,8 +198,15 @@
 	}
 
 	/* enable channel done and error interrupts */
+#ifdef CONFIG_CRYPTO_DEV_TALITOS1
+	clrbits32(priv->reg + TALITOS_IMR, TALITOS_IMR_INIT);
+	clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS_IMR_LO_INIT);
+	/* disable parity error check in DEU because of erroneous? test vectors */
+	setbits32(priv->reg + TALITOS_DEUICR, TALITOS_DEUICR_KPE);
+#else
 	setbits32(priv->reg + TALITOS_IMR, TALITOS_IMR_INIT);
 	setbits32(priv->reg + TALITOS_IMR_LO, TALITOS_IMR_LO_INIT);
+#endif
 
 	/* disable integrity check error interrupts (use writeback instead) */
 	if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
@@ -228,6 +264,7 @@
 
 	/* GO! */
 	wmb();
+
 	out_be32(priv->chan[ch].reg + TALITOS_FF,
 		 upper_32_bits(request->dma_desc));
 	out_be32(priv->chan[ch].reg + TALITOS_FF_LO,
@@ -300,6 +337,7 @@
 /*
  * process completed requests for channels that have done status
  */
+#ifdef CONFIG_CRYPTO_DEV_TALITOS1
 #define DEF_TALITOS_DONE(name, ch_done_mask)				\
 static void talitos_done_##name(unsigned long data)			\
 {									\
@@ -307,6 +345,33 @@
 	struct talitos_private *priv = dev_get_drvdata(dev);		\
 	unsigned long flags;						\
 									\
+	if (ch_done_mask & 0x10000000)						\
+		flush_channel(dev, 0, 0, 0);				\
+	if (priv->num_channels == 1)					\
+		goto out;						\
+	if (ch_done_mask & 0x40000000)					\
+		flush_channel(dev, 1, 0, 0);				\
+	if (ch_done_mask & 0x00010000)					\
+		flush_channel(dev, 2, 0, 0);				\
+	if (ch_done_mask & 0x00040000)					\
+		flush_channel(dev, 3, 0, 0);				\
+									\
+out:									\
+	/* At this point, all completed channels have been processed */	\
+	/* Unmask done interrupts for channels completed later on. */	\
+	spin_lock_irqsave(&priv->reg_lock, flags);			\
+	clrbits32(priv->reg + TALITOS_IMR, ch_done_mask);		\
+	clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS_IMR_LO_INIT);	\
+	spin_unlock_irqrestore(&priv->reg_lock, flags);			\
+}
+#else
+#define DEF_TALITOS_DONE(name, ch_done_mask)				\
+static void talitos_done_##name(unsigned long data)			\
+{									\
+	struct device *dev = (struct device *)data;			\
+	struct talitos_private *priv = dev_get_drvdata(dev);		\
+	unsigned long flags;						\
+									\
 	if (ch_done_mask & 1)						\
 		flush_channel(dev, 0, 0, 0);				\
 	if (priv->num_channels == 1)					\
@@ -326,6 +391,7 @@
 	setbits32(priv->reg + TALITOS_IMR_LO, TALITOS_IMR_LO_INIT);	\
 	spin_unlock_irqrestore(&priv->reg_lock, flags);			\
 }
+#endif
 DEF_TALITOS_DONE(4ch, TALITOS_ISR_4CHDONE)
 DEF_TALITOS_DONE(ch0_2, TALITOS_ISR_CH_0_2_DONE)
 DEF_TALITOS_DONE(ch1_3, TALITOS_ISR_CH_1_3_DONE)
@@ -433,13 +499,24 @@
 static void talitos_error(struct device *dev, u32 isr, u32 isr_lo)
 {
 	struct talitos_private *priv = dev_get_drvdata(dev);
+#ifndef CONFIG_CRYPTO_DEV_TALITOS1
 	unsigned int timeout = TALITOS_TIMEOUT;
+#endif
 	int ch, error, reset_dev = 0, reset_ch = 0;
 	u32 v, v_lo;
 
+#ifdef CONFIG_CRYPTO_DEV_TALITOS1
+	reset_ch = 1;
+#endif
 	for (ch = 0; ch < priv->num_channels; ch++) {
 		/* skip channels without errors */
+
+#ifdef CONFIG_CRYPTO_DEV_TALITOS1
+		/* 29 , 31, 17, 19 */
+		if (!(isr & (1 << (29 + (ch & 1) * 2 - (ch & 2) * 6))))
+#else
 		if (!(isr & (1 << (ch * 2 + 1))))
+#endif
 			continue;
 
 		error = -EINVAL;
@@ -447,6 +524,14 @@
 		v = in_be32(priv->chan[ch].reg + TALITOS_CCPSR);
 		v_lo = in_be32(priv->chan[ch].reg + TALITOS_CCPSR_LO);
 
+#ifdef CONFIG_CRYPTO_DEV_TALITOS1
+		if (v_lo & TALITOS_CCPSR_LO_TEA)
+			dev_err(dev, "master data transfer error\n");
+		if (v_lo & TALITOS_CCPSR_LO_PNC)
+			dev_err(dev, "pointeur not complete error\n");
+		if (v_lo & TALITOS_CCPSR_LO_PAR)
+			dev_err(dev, "parity error\n");
+#else
 		if (v_lo & TALITOS_CCPSR_LO_DOF) {
 			dev_err(dev, "double fetch fifo overflow error\n");
 			error = -EAGAIN;
@@ -463,12 +548,19 @@
 			dev_err(dev, "s/g data length zero error\n");
 		if (v_lo & TALITOS_CCPSR_LO_FPZ)
 			dev_err(dev, "fetch pointer zero error\n");
+#endif
 		if (v_lo & TALITOS_CCPSR_LO_IDH)
 			dev_err(dev, "illegal descriptor header error\n");
+#ifdef CONFIG_CRYPTO_DEV_TALITOS1
+		if (v_lo & TALITOS_CCPSR_LO_SA)
+			dev_err(dev, "static assignment error\n");
+#else
 		if (v_lo & TALITOS_CCPSR_LO_IEU)
 			dev_err(dev, "invalid execution unit error\n");
+#endif
 		if (v_lo & TALITOS_CCPSR_LO_EU)
 			report_eu_error(dev, ch, current_desc_hdr(dev, ch));
+#ifndef CONFIG_CRYPTO_DEV_TALITOS1
 		if (v_lo & TALITOS_CCPSR_LO_GB)
 			dev_err(dev, "gather boundary error\n");
 		if (v_lo & TALITOS_CCPSR_LO_GRL)
@@ -477,9 +569,13 @@
 			dev_err(dev, "scatter boundary error\n");
 		if (v_lo & TALITOS_CCPSR_LO_SRL)
 			dev_err(dev, "scatter return/length error\n");
+#endif
 
 		flush_channel(dev, ch, error, reset_ch);
 
+#ifdef CONFIG_CRYPTO_DEV_TALITOS1
+		reset_channel(dev, ch);
+#else
 		if (reset_ch) {
 			reset_channel(dev, ch);
 		} else {
@@ -495,10 +591,17 @@
 				reset_dev = 1;
 			}
 		}
+#endif
 	}
 	if (reset_dev || isr & ~TALITOS_ISR_4CHERR || isr_lo) {
-		dev_err(dev, "done overflow, internal time out, or rngu error: "
+#ifdef CONFIG_CRYPTO_DEV_TALITOS1
+		if (isr_lo & TALITOS_ISR_TEA_ERR)
+			dev_err(dev, "TEA error: "
 		        "ISR 0x%08x_%08x\n", isr, isr_lo);
+		else
+#endif
+			dev_err(dev, "done overflow, internal time out, or rngu error: "
+				"ISR 0x%08x_%08x\n", isr, isr_lo);
 
 		/* purge request queues */
 		for (ch = 0; ch < priv->num_channels; ch++)
@@ -509,6 +612,7 @@
 	}
 }
 
+#ifdef CONFIG_CRYPTO_DEV_TALITOS1
 #define DEF_TALITOS_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet)	       \
 static irqreturn_t talitos_interrupt_##name(int irq, void *data)	       \
 {									       \
@@ -523,7 +627,39 @@
 	/* Acknowledge interrupt */					       \
 	out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
 	out_be32(priv->reg + TALITOS_ICR_LO, isr_lo);			       \
+	if (unlikely(isr & ch_err_mask || isr_lo & TALITOS_IMR_LO_INIT)) {     \
+		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
+		talitos_error(dev, isr & ch_err_mask, isr_lo);		       \
+	}								       \
+	else {								       \
+		if (likely(isr & ch_done_mask)) {			       \
+			/* mask further done interrupts. */		       \
+			setbits32(priv->reg + TALITOS_IMR, ch_done_mask);      \
+			/* done_task will unmask done interrupts at exit */    \
+			tasklet_schedule(&priv->done_task[tlet]);	       \
+		}							       \
+		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
+	}								       \
 									       \
+	return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED :  \
+								IRQ_NONE;      \
+}
+#else
+#define DEF_TALITOS_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet)	       \
+static irqreturn_t talitos_interrupt_##name(int irq, void *data)	       \
+{									       \
+	struct device *dev = data;					       \
+	struct talitos_private *priv = dev_get_drvdata(dev);		       \
+	u32 isr, isr_lo;						       \
+	unsigned long flags;						       \
+									       \
+	spin_lock_irqsave(&priv->reg_lock, flags);			       \
+	isr = in_be32(priv->reg + TALITOS_ISR);				       \
+	isr_lo = in_be32(priv->reg + TALITOS_ISR_LO);			       \
+	/* Acknowledge interrupt */					       \
+	out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
+	out_be32(priv->reg + TALITOS_ICR_LO, isr_lo);			       \
+									       \
 	if (unlikely(isr & ch_err_mask || isr_lo)) {			       \
 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
 		talitos_error(dev, isr & ch_err_mask, isr_lo);		       \
@@ -541,6 +677,7 @@
 	return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED :  \
 								IRQ_NONE;      \
 }
+#endif
 DEF_TALITOS_INTERRUPT(4ch, TALITOS_ISR_4CHDONE, TALITOS_ISR_4CHERR, 0)
 DEF_TALITOS_INTERRUPT(ch0_2, TALITOS_ISR_CH_0_2_DONE, TALITOS_ISR_CH_0_2_ERR, 0)
 DEF_TALITOS_INTERRUPT(ch1_3, TALITOS_ISR_CH_1_3_DONE, TALITOS_ISR_CH_1_3_ERR, 1)
@@ -638,6 +775,10 @@
 	unsigned int enckeylen;
 	unsigned int authkeylen;
 	unsigned int authsize;
+#ifdef CONFIG_CRYPTO_DEV_TALITOS1
+	u8 *ptr_in;
+	u8 *ptr_out;
+#endif
 };
 
 #define HASH_MAX_BLOCK_SIZE		SHA512_BLOCK_SIZE
@@ -646,7 +787,7 @@
 struct talitos_ahash_req_ctx {
 	u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)];
 	unsigned int hw_context_size;
-	u8 buf[HASH_MAX_BLOCK_SIZE];
+	u8 buf[4096];
 	u8 bufnext[HASH_MAX_BLOCK_SIZE];
 	unsigned int swinit;
 	unsigned int first;
@@ -657,6 +798,7 @@
 	struct scatterlist *psrc;
 };
 
+#ifndef CONFIG_CRYPTO_DEV_TALITOS1
 static int aead_setauthsize(struct crypto_aead *authenc,
 			    unsigned int authsize)
 {
@@ -711,6 +853,7 @@
 	crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN);
 	return -EINVAL;
 }
+#endif
 
 /*
  * talitos_edesc - s/w-extended descriptor
@@ -796,6 +939,7 @@
 			dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL);
 }
 
+#ifndef CONFIG_CRYPTO_DEV_TALITOS1
 static void ipsec_esp_unmap(struct device *dev,
 			    struct talitos_edesc *edesc,
 			    struct aead_request *areq)
@@ -1091,6 +1235,7 @@
 	}
 	return ret;
 }
+#endif
 
 /*
  * derive number of elements in scatterlist
@@ -1213,6 +1358,7 @@
 	return edesc;
 }
 
+#ifndef CONFIG_CRYPTO_DEV_TALITOS1
 static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv,
 					      int icv_stashing)
 {
@@ -1315,6 +1461,7 @@
 
 	return ipsec_esp(edesc, areq, req->seq, ipsec_esp_encrypt_done);
 }
+#endif
 
 static int ablkcipher_setkey(struct crypto_ablkcipher *cipher,
 			     const u8 *key, unsigned int keylen)
@@ -1331,7 +1478,21 @@
 				  struct talitos_edesc *edesc,
 				  struct ablkcipher_request *areq)
 {
+	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
+	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
+
 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE);
+	if (ctx->ptr_out) {
+		unsigned int cryptlen = areq->nbytes;
+
+		sg_copy_from_buffer(areq->dst, edesc->dst_nents ? : 1, ctx->ptr_out, cryptlen);
+		unmap_single_talitos_ptr(dev, &edesc->desc.ptr[4], DMA_FROM_DEVICE);
+		kfree(ctx->ptr_out);
+	}
+	if (ctx->ptr_in) {
+		unmap_single_talitos_ptr(dev, &edesc->desc.ptr[3], DMA_TO_DEVICE);
+		kfree(ctx->ptr_in);
+	}
 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[2], DMA_TO_DEVICE);
 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1], DMA_TO_DEVICE);
 
@@ -1375,13 +1536,16 @@
 	/* first DWORD empty */
 	desc->ptr[0].len = 0;
 	to_talitos_ptr(&desc->ptr[0], 0);
+#ifndef CONFIG_CRYPTO_DEV_TALITOS1
 	desc->ptr[0].j_extent = 0;
+#endif
 
 	/* cipher iv */
 	to_talitos_ptr(&desc->ptr[1], edesc->iv_dma);
 	desc->ptr[1].len = cpu_to_be16(ivsize);
+#ifndef CONFIG_CRYPTO_DEV_TALITOS1
 	desc->ptr[1].j_extent = 0;
-
+#endif
 	/* cipher key */
 	map_single_talitos_ptr(dev, &desc->ptr[2], ctx->keylen,
 			       (char *)&ctx->key, 0, DMA_TO_DEVICE);
@@ -1390,7 +1554,9 @@
 	 * cipher in
 	 */
 	desc->ptr[3].len = cpu_to_be16(cryptlen);
+#ifndef CONFIG_CRYPTO_DEV_TALITOS1
 	desc->ptr[3].j_extent = 0;
+#endif
 
 	sg_count = talitos_map_sg(dev, areq->src, edesc->src_nents ? : 1,
 				  (areq->src == areq->dst) ? DMA_BIDIRECTIONAL
@@ -1398,8 +1564,17 @@
 				  edesc->src_chained);
 
 	if (sg_count == 1) {
+#ifdef CONFIG_CRYPTO_DEV_TALITOS1
+		ctx->ptr_in = NULL;
+#endif
 		to_talitos_ptr(&desc->ptr[3], sg_dma_address(areq->src));
 	} else {
+#ifdef CONFIG_CRYPTO_DEV_TALITOS1
+		ctx->ptr_in = kzalloc(cryptlen, GFP_DMA);
+		sg_copy_to_buffer(areq->src, sg_count, ctx->ptr_in, cryptlen);
+		map_single_talitos_ptr(dev, &desc->ptr[3], cryptlen,
+			       (char *)ctx->ptr_in, 0, DMA_TO_DEVICE);
+#else
 		sg_count = sg_to_link_tbl(areq->src, sg_count, cryptlen,
 					  &edesc->link_tbl[0]);
 		if (sg_count > 1) {
@@ -1412,12 +1587,17 @@
 			/* Only one segment now, so no link tbl needed */
 			to_talitos_ptr(&desc->ptr[3],
 				       sg_dma_address(areq->src));
+#endif
+#ifndef CONFIG_CRYPTO_DEV_TALITOS1
 		}
+#endif
 	}
 
 	/* cipher out */
 	desc->ptr[4].len = cpu_to_be16(cryptlen);
+#ifndef CONFIG_CRYPTO_DEV_TALITOS1
 	desc->ptr[4].j_extent = 0;
+#endif
 
 	if (areq->src != areq->dst)
 		sg_count = talitos_map_sg(dev, areq->dst,
@@ -1425,8 +1605,16 @@
 					  DMA_FROM_DEVICE, edesc->dst_chained);
 
 	if (sg_count == 1) {
+#ifdef CONFIG_CRYPTO_DEV_TALITOS1
+		ctx->ptr_out = NULL;
+#endif
 		to_talitos_ptr(&desc->ptr[4], sg_dma_address(areq->dst));
 	} else {
+#ifdef CONFIG_CRYPTO_DEV_TALITOS1
+		ctx->ptr_out = kzalloc(cryptlen, GFP_DMA);
+		map_single_talitos_ptr(dev, &desc->ptr[4], cryptlen,
+			       (char *)ctx->ptr_out, 0, DMA_FROM_DEVICE);
+#else
 		struct talitos_ptr *link_tbl_ptr =
 			&edesc->link_tbl[edesc->src_nents + 1];
 
@@ -1438,6 +1626,7 @@
 					  link_tbl_ptr);
 		dma_sync_single_for_device(ctx->dev, edesc->dma_link_tbl,
 					   edesc->dma_len, DMA_BIDIRECTIONAL);
+#endif
 	}
 
 	/* iv out */
@@ -1447,7 +1636,12 @@
 	/* last DWORD empty */
 	desc->ptr[6].len = 0;
 	to_talitos_ptr(&desc->ptr[6], 0);
+#ifndef CONFIG_CRYPTO_DEV_TALITOS1
 	desc->ptr[6].j_extent = 0;
+#endif
+#ifdef CONFIG_CRYPTO_DEV_TALITOS1
+	desc->next_desc = 0;
+#endif
 
 	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
 	if (ret != -EINPROGRESS) {
@@ -1578,9 +1772,10 @@
 	}
 
 	/* HMAC key */
-	if (ctx->keylen)
+	if (ctx->keylen) {
 		map_single_talitos_ptr(dev, &desc->ptr[2], ctx->keylen,
 				       (char *)&ctx->key, 0, DMA_TO_DEVICE);
+	}
 	else
 		desc->ptr[2] = zero_entry;
 
@@ -1588,7 +1783,9 @@
 	 * data in
 	 */
 	desc->ptr[3].len = cpu_to_be16(length);
+#ifndef CONFIG_CRYPTO_DEV_TALITOS1
 	desc->ptr[3].j_extent = 0;
+#endif
 
 	sg_count = talitos_map_sg(dev, req_ctx->psrc,
 				  edesc->src_nents ? : 1,
@@ -1597,6 +1794,7 @@
 	if (sg_count == 1) {
 		to_talitos_ptr(&desc->ptr[3], sg_dma_address(req_ctx->psrc));
 	} else {
+#ifndef CONFIG_CRYPTO_DEV_TALITOS1
 		sg_count = sg_to_link_tbl(req_ctx->psrc, sg_count, length,
 					  &edesc->link_tbl[0]);
 		if (sg_count > 1) {
@@ -1611,6 +1809,7 @@
 			to_talitos_ptr(&desc->ptr[3],
 				       sg_dma_address(req_ctx->psrc));
 		}
+#endif
 	}
 
 	/* fifth DWORD empty */
@@ -1628,7 +1827,22 @@
 
 	/* last DWORD empty */
 	desc->ptr[6] = zero_entry;
+#ifdef CONFIG_CRYPTO_DEV_TALITOS1
+	desc->next_desc = 0;
+#endif
 
+#ifdef CONFIG_CRYPTO_DEV_TALITOS1
+	/*
+	 * SEC1 doesn't like hashing of 0 sized message, so we do the padding
+	 * ourself and submit a padded block
+	 */
+	if (desc->ptr[3].len == 0) {
+		pr_err_once("Bug in SEC1, padding ourself\n");
+		edesc->desc.hdr &= ~DESC_HDR_MODE0_MDEU_PAD;
+		map_single_talitos_ptr(dev, &desc->ptr[3], sizeof(padded_hash),
+				       (char *)padded_hash, 0, DMA_TO_DEVICE);
+	}
+#endif
 	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
 	if (ret != -EINPROGRESS) {
 		common_nonsnoop_hash_unmap(dev, edesc, areq);
@@ -1702,7 +1916,10 @@
 			crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
 	unsigned int nbytes_to_hash;
 	unsigned int to_hash_later;
+#ifndef CONFIG_CRYPTO_DEV_TALITOS1
 	unsigned int nsg;
+#endif
+	int nents;
 	bool chained;
 
 	if (!req_ctx->last && (nbytes + req_ctx->nbuf <= blocksize)) {
@@ -1730,6 +1947,16 @@
 	}
 
 	/* Chain in any previously buffered data */
+#ifdef CONFIG_CRYPTO_DEV_TALITOS1
+	if ((nents = sg_count(areq->src, nbytes, &chained)) > 1 || req_ctx->nbuf) {
+		sg_copy_to_buffer(areq->src, nents,
+			req_ctx->buf + req_ctx->nbuf,
+			nbytes_to_hash - req_ctx->nbuf);
+		sg_init_one(req_ctx->bufsl, req_ctx->buf, nbytes_to_hash);
+		req_ctx->psrc = req_ctx->bufsl;
+	} else
+		req_ctx->psrc = areq->src;
+#else
 	if (req_ctx->nbuf) {
 		nsg = (req_ctx->nbuf < nbytes_to_hash) ? 2 : 1;
 		sg_init_table(req_ctx->bufsl, nsg);
@@ -1739,9 +1966,9 @@
 		req_ctx->psrc = req_ctx->bufsl;
 	} else
 		req_ctx->psrc = areq->src;
-
+#endif
 	if (to_hash_later) {
-		int nents = sg_count(areq->src, nbytes, &chained);
+		nents = sg_count(areq->src, nbytes, &chained);
 		sg_pcopy_to_buffer(areq->src, nents,
 				      req_ctx->bufnext,
 				      to_hash_later,
@@ -2407,6 +2634,7 @@
 	return 0;
 }
 
+#ifndef CONFIG_CRYPTO_DEV_TALITOS1
 static int talitos_cra_init_aead(struct crypto_tfm *tfm)
 {
 	struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
@@ -2418,6 +2646,7 @@
 
 	return 0;
 }
+#endif
 
 static int talitos_cra_init_ahash(struct crypto_tfm *tfm)
 {
@@ -2524,6 +2753,7 @@
 		alg->cra_ablkcipher.decrypt = ablkcipher_decrypt;
 		alg->cra_ablkcipher.geniv = "eseqiv";
 		break;
+#ifndef CONFIG_CRYPTO_DEV_TALITOS1
 	case CRYPTO_ALG_TYPE_AEAD:
 		alg = &t_alg->algt.alg.crypto;
 		alg->cra_init = talitos_cra_init_aead;
@@ -2535,6 +2765,7 @@
 		alg->cra_aead.givencrypt = aead_givencrypt;
 		alg->cra_aead.geniv = "<built-in>";
 		break;
+#endif
 	case CRYPTO_ALG_TYPE_AHASH:
 		alg = &t_alg->algt.alg.hash.halg.base;
 		alg->cra_init = talitos_cra_init_ahash;
@@ -2698,6 +2929,9 @@
 				  TALITOS_FTR_SHA224_HWINIT |
 				  TALITOS_FTR_HMAC_OK;
 
+	if (of_device_is_compatible(np, "fsl,sec1.2"))
+		priv->features |= TALITOS_FTR_HMAC_OK;
+
 	priv->chan = kzalloc(sizeof(struct talitos_channel) *
 			     priv->num_channels, GFP_KERNEL);
 	if (!priv->chan) {
@@ -2801,9 +3035,15 @@
 }
 
 static const struct of_device_id talitos_match[] = {
+#ifdef CONFIG_CRYPTO_DEV_TALITOS1
 	{
+		.compatible = "fsl,sec1.0",
+	},
+#else
+	{
 		.compatible = "fsl,sec2.0",
 	},
+#endif
 	{},
 };
 MODULE_DEVICE_TABLE(of, talitos_match);
Index: b/drivers/crypto/talitos.h
===================================================================
--- a/drivers/crypto/talitos.h
+++ b/drivers/crypto/talitos.h
@@ -28,8 +28,16 @@
  *
  */
 
+#if defined(CONFIG_PPC_8xx) || defined(CONFIG_PPC_82xx)
+#define CONFIG_CRYPTO_DEV_TALITOS1
+#endif
+
 #define TALITOS_TIMEOUT 100000
+#ifdef CONFIG_CRYPTO_DEV_TALITOS1
+#define TALITOS_MAX_DATA_LEN 32768
+#else
 #define TALITOS_MAX_DATA_LEN 65535
+#endif
 
 #define DESC_TYPE(desc_hdr) ((be32_to_cpu(desc_hdr) >> 3) & 0x1f)
 #define PRIMARY_EU(desc_hdr) ((be32_to_cpu(desc_hdr) >> 28) & 0xf)
@@ -37,24 +45,39 @@
 
 /* descriptor pointer entry */
 struct talitos_ptr {
+#ifdef CONFIG_CRYPTO_DEV_TALITOS1
+	__be16 res;	/* reserved */
 	__be16 len;     /* length */
+	__be32 ptr;     /* address */
+#else
+	__be16 len;     /* length */
 	u8 j_extent;    /* jump to sg link table and/or extent */
 	u8 eptr;        /* extended address */
 	__be32 ptr;     /* address */
+#endif
 };
 
 static const struct talitos_ptr zero_entry = {
 	.len = 0,
+#ifdef CONFIG_CRYPTO_DEV_TALITOS1
+	.res = 0,
+#else
 	.j_extent = 0,
 	.eptr = 0,
+#endif
 	.ptr = 0
 };
 
 /* descriptor */
 struct talitos_desc {
 	__be32 hdr;                     /* header high bits */
+#ifndef CONFIG_CRYPTO_DEV_TALITOS1
 	__be32 hdr_lo;                  /* header low bits */
+#endif
 	struct talitos_ptr ptr[7];      /* ptr/len pair array */
+#ifdef CONFIG_CRYPTO_DEV_TALITOS1
+	__be32 next_desc;
+#endif
 };
 
 /**
@@ -155,42 +178,84 @@
 #define   TALITOS_MCR_RCA1		(1 << 14) /* remap channel 1 */
 #define   TALITOS_MCR_RCA2		(1 << 13) /* remap channel 2 */
 #define   TALITOS_MCR_RCA3		(1 << 12) /* remap channel 3 */
+#ifdef CONFIG_CRYPTO_DEV_TALITOS1
+#define   TALITOS_MCR_SWR		0x01000000     /* s/w reset */
+#else
 #define   TALITOS_MCR_SWR		0x1     /* s/w reset */
+#endif
 #define TALITOS_MCR_LO			0x1034
 #define TALITOS_IMR			0x1008  /* interrupt mask register */
+#ifdef CONFIG_CRYPTO_DEV_TALITOS1
+#define   TALITOS_IMR_INIT		0xf00f0000 /* enable channel IRQs */
+#define   TALITOS_IMR_DONE		0x50050000 /* done IRQs */
+#else
 #define   TALITOS_IMR_INIT		0x100ff /* enable channel IRQs */
 #define   TALITOS_IMR_DONE		0x00055 /* done IRQs */
+#endif
 #define TALITOS_IMR_LO			0x100C
+#ifdef CONFIG_CRYPTO_DEV_TALITOS1
+#define   TALITOS_IMR_LO_INIT		0x2000000 /* allow RNGU error IRQs */
+#else
 #define   TALITOS_IMR_LO_INIT		0x20000 /* allow RNGU error IRQs */
+#endif
 #define TALITOS_ISR			0x1010  /* interrupt status register */
+#ifdef CONFIG_CRYPTO_DEV_TALITOS1
+#define   TALITOS_ISR_4CHERR		0xa00a0000    /* 4 channel errors mask */
+#define   TALITOS_ISR_4CHDONE		0x50050000    /* 4 channel done mask */
+#define   TALITOS_ISR_CH_0_2_ERR	0x20020000    /* channels 0, 2 errors mask */
+#define   TALITOS_ISR_CH_0_2_DONE	0x10010000    /* channels 0, 2 done mask */
+#define   TALITOS_ISR_CH_1_3_ERR	0x80080000    /* channels 1, 3 errors mask */
+#define   TALITOS_ISR_CH_1_3_DONE	0x40040000    /* channels 1, 3 done mask */
+#define   TALITOS_ISR_TEA_ERR		0x00000040
+#else
 #define   TALITOS_ISR_4CHERR		0xaa    /* 4 channel errors mask */
 #define   TALITOS_ISR_4CHDONE		0x55    /* 4 channel done mask */
 #define   TALITOS_ISR_CH_0_2_ERR	0x22    /* channels 0, 2 errors mask */
 #define   TALITOS_ISR_CH_0_2_DONE	0x11    /* channels 0, 2 done mask */
 #define   TALITOS_ISR_CH_1_3_ERR	0x88    /* channels 1, 3 errors mask */
 #define   TALITOS_ISR_CH_1_3_DONE	0x44    /* channels 1, 3 done mask */
+#endif
 #define TALITOS_ISR_LO			0x1014
 #define TALITOS_ICR			0x1018  /* interrupt clear register */
 #define TALITOS_ICR_LO			0x101C
 
 /* channel register address stride */
+#ifdef CONFIG_CRYPTO_DEV_TALITOS1
 #define TALITOS_CH_BASE_OFFSET		0x1000	/* default channel map base */
+#define TALITOS_CH_STRIDE		0x1000
+#else
+#define TALITOS_CH_BASE_OFFSET		0x1000	/* default channel map base */
 #define TALITOS_CH_STRIDE		0x100
+#endif
 
 /* channel configuration register  */
 #define TALITOS_CCCR			0x8
+#ifdef CONFIG_CRYPTO_DEV_TALITOS1
+#else
 #define   TALITOS_CCCR_CONT		0x2    /* channel continue */
 #define   TALITOS_CCCR_RESET		0x1    /* channel reset */
+#endif
 #define TALITOS_CCCR_LO			0xc
 #define   TALITOS_CCCR_LO_IWSE		0x80   /* chan. ICCR writeback enab. */
 #define   TALITOS_CCCR_LO_EAE		0x20   /* extended address enable */
 #define   TALITOS_CCCR_LO_CDWE		0x10   /* chan. done writeback enab. */
 #define   TALITOS_CCCR_LO_NT		0x4    /* notification type */
 #define   TALITOS_CCCR_LO_CDIE		0x2    /* channel done IRQ enable */
+#ifdef CONFIG_CRYPTO_DEV_TALITOS1
+#define   TALITOS_CCCR_LO_RESET		0x1    /* channel reset */
+#endif
 
 /* CCPSR: channel pointer status register */
 #define TALITOS_CCPSR			0x10
 #define TALITOS_CCPSR_LO		0x14
+#ifdef CONFIG_CRYPTO_DEV_TALITOS1
+#define   TALITOS_CCPSR_LO_TEA		0x2000 /* master data transfer error */
+#define   TALITOS_CCPSR_LO_PNC		0x1000 /* pointeur not complete error */
+#define   TALITOS_CCPSR_LO_PAR		0x0800 /* parity error */
+#define   TALITOS_CCPSR_LO_IDH		0x0400 /* illegal desc hdr error */
+#define   TALITOS_CCPSR_LO_SA		0x0200 /* static assignment error */
+#define   TALITOS_CCPSR_LO_EU		0x0100 /* EU error detected */
+#else
 #define   TALITOS_CCPSR_LO_DOF		0x8000 /* double FF write oflow error */
 #define   TALITOS_CCPSR_LO_SOF		0x4000 /* single FF write oflow error */
 #define   TALITOS_CCPSR_LO_MDTE		0x2000 /* master data transfer error */
@@ -203,6 +268,7 @@
 #define   TALITOS_CCPSR_LO_GRL		0x0040 /* gather return/length error */
 #define   TALITOS_CCPSR_LO_SB		0x0020 /* scatter boundary error */
 #define   TALITOS_CCPSR_LO_SRL		0x0010 /* scatter return/length error */
+#endif
 
 /* channel fetch fifo register */
 #define TALITOS_FF			0x48
@@ -225,8 +291,16 @@
 #define TALITOS_SCATTER_LO		0xe4
 
 /* execution unit interrupt status registers */
+#ifdef CONFIG_CRYPTO_DEV_TALITOS1
+#define TALITOS_DEUISR			0x5030 /* DES unit */
+#define TALITOS_DEUISR_LO		0x5034
+#define TALITOS_DEUICR			0x5038 /* interrupt control */
+#define   TALITOS_DEUICR_KPE		0x00200000 /* Key Parity Error */
+#else
 #define TALITOS_DEUISR			0x2030 /* DES unit */
 #define TALITOS_DEUISR_LO		0x2034
+#endif
+
 #define TALITOS_AESUISR			0x4030 /* AES unit */
 #define TALITOS_AESUISR_LO		0x4034
 #define TALITOS_MDEUISR			0x6030 /* message digest unit */
@@ -234,6 +308,7 @@
 #define TALITOS_MDEUICR			0x6038 /* interrupt control */
 #define TALITOS_MDEUICR_LO		0x603c
 #define   TALITOS_MDEUICR_LO_ICE	0x4000 /* integrity check IRQ enable */
+
 #define TALITOS_AFEUISR			0x8030 /* arc4 unit */
 #define TALITOS_AFEUISR_LO		0x8034
 #define TALITOS_RNGUISR			0xa030 /* random number unit */
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ