Skip to contentSkip to conversation

arm64: marvell: add cryptographic engine support for 7k/8k

PATCH Superseded Antoine Tenart 6 participants 20 messages Apr 24, 2017 – May 23, 2017

Subsystems (3)

v3 of 6 Superseded Latest is v6 →

lore
Share & tools
lore
#0 lore raw

v3 cover arm64: marvell: add cryptographic engine support for 7k/8k

Hi all,

This series adds support for the Inside Secure SafeXcel EIP197 cryptographic engine which can be found on Marvell Armada 7k and 8k boards. A new cryptographic engine driver is added, as well as the relevant device tree definition for the Armada 7040 DB and 8040 DB boards.

This driver needs two firmwares to work correctly. These firmware are usually used for more advanced operations than the ones supported (as of now), but we still need them to pass the data to the internal cryptographic engine.

This series was tested in various ways on both the Armada 7040 DB and the Armada 8040 DB: using the crypto framework self tests, using tcrypt and while performing various transfers with iperf on top of IPsec.

This series is based on top of v4.11-rc1, and is available on a branch (which also contains the PPv2 support for 7k/8k, to ease the process of testing IPsec): https://github.com/atenart/linux v4.11-rc1/7k8k-crypto I can rebase if needed. Patches adding device tree nodes and modifying the arm64 defconfig have been applied to the mvebu tree already.

I'd like to thank Ofer Heifetz and Igal Liberman who helped me to do this driver by adding functionalities, optimizing functions and testing (a lot).

Thanks,
Antoine

Since v2:
- Used sha*_zero_message_hash definitions instead of custom ones.
- Used memzero_explicit() instead of memset() to avoid leaks.
- Misc cosmetic updates.

Since v1:
- Fixed two compilation issues reported by Kbuild.
- Removed all dma_to_phys() calls and used the dma addresses instead.
- Added a call to dma_set_mask_and_coherent() before calling any DMA API helper.
- Removed some DMA free functions to avoid double-freeing.
- Do not rely on sg_nents_for_len() to get the number of sg anymore.
- Added a dedicated kmalloc'ed cache to use for dma_map_single().

Antoine Tenart (3):
Documentation/bindings: Document the SafeXel cryptographic engine
driver
crypto: inside-secure: add SafeXcel EIP197 crypto engine driver
MAINTAINERS: add a maintainer for the Inside Secure crypto driver

 .../bindings/crypto/inside-secure-safexcel.txt     |   27 +
 MAINTAINERS                                        |    6 +
 drivers/crypto/Kconfig                             |   17 +
 drivers/crypto/Makefile                            |    1 +
 drivers/crypto/inside-secure/Makefile              |    2 +
 drivers/crypto/inside-secure/safexcel.c            |  925 +++++++++++++++++
 drivers/crypto/inside-secure/safexcel.h            |  579 +++++++++++
 drivers/crypto/inside-secure/safexcel_cipher.c     |  555 +++++++++++
 drivers/crypto/inside-secure/safexcel_hash.c       | 1045 ++++++++++++++++++++
 drivers/crypto/inside-secure/safexcel_ring.c       |  157 +++
 10 files changed, 3314 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/crypto/inside-secure-safexcel.txt
 create mode 100644 drivers/crypto/inside-secure/Makefile
 create mode 100644 drivers/crypto/inside-secure/safexcel.c
 create mode 100644 drivers/crypto/inside-secure/safexcel.h
 create mode 100644 drivers/crypto/inside-secure/safexcel_cipher.c
 create mode 100644 drivers/crypto/inside-secure/safexcel_hash.c
 create mode 100644 drivers/crypto/inside-secure/safexcel_ring.c
Signature · 1 line
2.11.0
#1 lore raw

PATCH v3 1/3 Documentation/bindings: Document the SafeXel cryptographic engine driver

The Inside Secure Safexcel cryptographic engine is found on some Marvell SoCs (7k/8k). Document the bindings used by its driver.

---
 .../bindings/crypto/inside-secure-safexcel.txt     | 27 ++++++++++++++++++++++
 1 file changed, 27 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/crypto/inside-secure-safexcel.txt
Documentation/devicetree/bindings/crypto/inside-secure-safexcel.txt new file +27 -0
new file mode 100644
index 000000000000..ff56b9384fcc
@@ -0,0 +1,27 @@
+Inside Secure SafeXcel cryptographic engine
+
+Required properties:
+- compatible: Should be "inside-secure,safexcel-eip197".
+- reg: Base physical address of the engine and length of memory mapped region.
+- interrupts: Interrupt numbers for the rings and engine.
+- interrupt-names: Should be "ring0", "ring1", "ring2", "ring3", "eip", "mem".
+
+Optional properties:
+- clocks: Reference to the crypto engine clock.
+
+Example:
+
+	crypto: crypto at 800000 {
+		compatible = "inside-secure,safexcel-eip197";
+		reg = <0x800000 0x200000>;
+		interrupts = <GIC_SPI 34 (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "mem", "ring0", "ring1", "ring2", "ring3",
+				  "eip";
+		clocks = <&cpm_syscon0 1 26>;
+		status = "disabled";
+	};
Signature · 1 line
2.11.0
#2 lore raw

PATCH v3 1/3 Documentation/bindings: Document the SafeXel cryptographic engine driver

Quoted 22 lines · Antoine Tenart

The Inside Secure Safexcel cryptographic engine is found on some Marvell SoCs (7k/8k). Document the bindings used by its driver.

---
 .../bindings/crypto/inside-secure-safexcel.txt     | 27 ++++++++++++++++++++++
 1 file changed, 27 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/crypto/inside-secure-safexcel.txt
Documentation/devicetree/bindings/crypto/inside-secure-safexcel.txt new file +7 -0
new file mode 100644
index 000000000000..ff56b9384fcc
@@ -0,0 +1,27 @@
+Inside Secure SafeXcel cryptographic engine
+
+Required properties:
+- compatible: Should be "inside-secure,safexcel-eip197".
+- reg: Base physical address of the engine and length of memory mapped region.
+- interrupts: Interrupt numbers for the rings and engine.
+- interrupt-names: Should be "ring0", "ring1", "ring2", "ring3", "eip", "mem".

Documentation/devicetree/bindings/crypto/inside-secure-safexcel.txt line 17

Quoted 10 lines
Documentation/devicetree/bindings/crypto/inside-secure-safexcel.txt new file +10 -0
+
+Optional properties:
+- clocks: Reference to the crypto engine clock.
+
+Example:
+
+	crypto: crypto at 800000 {
+		compatible = "inside-secure,safexcel-eip197";
+		reg = <0x800000 0x200000>;
+		interrupts = <GIC_SPI 34 (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH)>,

I'm puzzled. How can the interrupt can be both level *and* edge? That doesn't make any sense.

Thanks,

	M.
Signature · 1 line
Jazz is not dead. It just smells funny...
#3 lore raw

PATCH v3 1/3 Documentation/bindings: Document the SafeXel cryptographic engine driver

Hi Marc,

Quoted 9 lines · Marc Zyngier

Documentation/devicetree/bindings/crypto/inside-secure-safexcel.txt line 17

Quoted 5 lines · Antoine Tenart
Documentation/devicetree/bindings/crypto/inside-secure-safexcel.txt new file +5 -0
+
+	crypto: crypto at 800000 {
+		compatible = "inside-secure,safexcel-eip197";
+		reg = <0x800000 0x200000>;
+		interrupts = <GIC_SPI 34 (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH)>,

I'm puzzled. How can the interrupt can be both level *and* edge? That doesn't make any sense.

I agree this looks odd. I took it from Russel's ICU mapping:
http://lists.infradead.org/pipermail/linux-arm-kernel/2017-February/489040.html

The driver does not use this interrupt (yet?). I'm not sure what is this interrupt exact configuration...

Do you want me to remove this from the documentation (and device trees)?

Thanks,
Antoine

Signature · 3 lines
Antoine T?nart, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
#4 lore raw

PATCH v3 1/3 Documentation/bindings: Document the SafeXel cryptographic engine driver

Hi Antoine,

Quoted 13 lines · Antoine Tenart

Hi Marc,

Quoted 9 lines · Marc Zyngier

Documentation/devicetree/bindings/crypto/inside-secure-safexcel.txt line 17

Quoted 5 lines · Antoine Tenart
Documentation/devicetree/bindings/crypto/inside-secure-safexcel.txt new file +5 -0
+
+	crypto: crypto at 800000 {
+		compatible = "inside-secure,safexcel-eip197";
+		reg = <0x800000 0x200000>;
+		interrupts = <GIC_SPI 34 (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH)>,

I'm puzzled. How can the interrupt can be both level *and* edge? That doesn't make any sense.

Quoted 2 lines

I agree this looks odd. I took it from Russel's ICU mapping:
http://lists.infradead.org/pipermail/linux-arm-kernel/2017-February/489040.html

This emails says:

ICU-irq => GIC-SPI-num Enable Edge/Level ICU-group [...]
24 => 34 En Lv 0

which seems to clearly indicate Level (no Edge involved here).

Quoted 2 lines

The driver does not use this interrupt (yet?). I'm not sure what is this interrupt exact configuration...

Surely the TRM would indicate this, wouldn't it?

Quoted 1 line

Do you want me to remove this from the documentation (and device trees)?

I'd rather you clarify it, if possible.

Thanks,

	M.
Signature · 1 line
Jazz is not dead. It just smells funny...
#5 lore raw

PATCH v3 1/3 Documentation/bindings: Document the SafeXel cryptographic engine driver

Quoted 12 lines · Marc Zyngier
Quoted 11 lines · Antoine Tenart
Quoted 9 lines · Marc Zyngier

Documentation/devicetree/bindings/crypto/inside-secure-safexcel.txt line 17

Quoted 5 lines · Antoine Tenart
Documentation/devicetree/bindings/crypto/inside-secure-safexcel.txt new file +5 -0
+
+	crypto: crypto at 800000 {
+		compatible = "inside-secure,safexcel-eip197";
+		reg = <0x800000 0x200000>;
+		interrupts = <GIC_SPI 34 (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH)>,

I'm puzzled. How can the interrupt can be both level *and* edge? That doesn't make any sense.

Quoted 8 lines
Quoted 2 lines

I agree this looks odd. I took it from Russel's ICU mapping:
http://lists.infradead.org/pipermail/linux-arm-kernel/2017-February/489040.html

This emails says:

ICU-irq => GIC-SPI-num Enable Edge/Level ICU-group [...]
24 => 34 En Lv 0

It also says: 87 => 34 En Lv 5, which is the IRQ I'm looking for.

Antoine.

Signature · 3 lines
Antoine T?nart, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
#6 lore raw

PATCH v3 1/3 Documentation/bindings: Document the SafeXel cryptographic engine driver

Quoted 16 lines · Antoine Tenart
Quoted 15 lines · Marc Zyngier
Quoted 13 lines · Antoine Tenart
Quoted 9 lines · Marc Zyngier

Documentation/devicetree/bindings/crypto/inside-secure-safexcel.txt line 17

Quoted 5 lines · Antoine Tenart
Documentation/devicetree/bindings/crypto/inside-secure-safexcel.txt new file +5 -0
+
+	crypto: crypto at 800000 {
+		compatible = "inside-secure,safexcel-eip197";
+		reg = <0x800000 0x200000>;
+		interrupts = <GIC_SPI 34 (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH)>,

I'm puzzled. How can the interrupt can be both level *and* edge? That doesn't make any sense.

I agree this looks odd. I took it from Russel's ICU mapping:
http://lists.infradead.org/pipermail/linux-arm-kernel/2017-February/489040.html

Quoted 7 lines
Quoted 5 lines

This emails says:

ICU-irq => GIC-SPI-num Enable Edge/Level ICU-group [...]
24 => 34 En Lv 0

It also says: 87 => 34 En Lv 5, which is the IRQ I'm looking for.

Ah, that one as well. So how is the interrupt routed? Via the ICU, and then to the GIC (with several ICU sources mapped on a single SPI)?

If so, the binding should reflect this.

Thanks,

	M.
Signature · 1 line
Jazz is not dead. It just smells funny...
#7 lore raw

PATCH v3 1/3 Documentation/bindings: Document the SafeXel cryptographic engine driver

Hello,

Quoted 4 lines · Marc Zyngier
Quoted 1 line

It also says: 87 => 34 En Lv 5, which is the IRQ I'm looking for.

Ah, that one as well. So how is the interrupt routed? Via the ICU, and then to the GIC (with several ICU sources mapped on a single SPI)?

The crypto block being in the CP part, it has a wired interrupt to the ICU (also in the CP). The ICU then turns this wired interrupt into a memory write transaction to a register called GICP SPI in the AP, which triggers a SPI interrupt in the GIC.

In the current mainline kernel, the ICU is configured by the firmware and creates static associations between wired interrupts in the CP and corresponding SPI interrupts. Therefore the Device Tree currently reference such SPI interrupts directly.

However, I have a patch series that I plan to submit hopefully in the next days that adds an ICU driver, and changes the Device Tree to refer to the ICU interrupt instead.

Therefore, I don't think the binding should reference anything else than the usual info about the interrupts property.

Best regards,

Thomas

Signature · 3 lines
Thomas Petazzoni, CTO, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
#8 lore raw

PATCH v3 1/3 Documentation/bindings: Document the SafeXel cryptographic engine driver

Quoted 6 lines · Thomas Petazzoni

Hello,

Quoted 2 lines · Marc Zyngier
Quoted 1 line

It also says: 87 => 34 En Lv 5, which is the IRQ I'm looking for.

Quoted 7 lines
Quoted 2 lines

Ah, that one as well. So how is the interrupt routed? Via the ICU, and then to the GIC (with several ICU sources mapped on a single SPI)?

The crypto block being in the CP part, it has a wired interrupt to the ICU (also in the CP). The ICU then turns this wired interrupt into a memory write transaction to a register called GICP SPI in the AP, which triggers a SPI interrupt in the GIC.

Is that some kind of Level-triggered MSI, ? la GICv3 GICD_SETSPI_NSR?

Quoted 8 lines

In the current mainline kernel, the ICU is configured by the firmware and creates static associations between wired interrupts in the CP and corresponding SPI interrupts. Therefore the Device Tree currently reference such SPI interrupts directly.

However, I have a patch series that I plan to submit hopefully in the next days that adds an ICU driver, and changes the Device Tree to refer to the ICU interrupt instead.

OK, I'm quite interested to see that, specially if my above hunch is right...

Quoted 2 lines

Therefore, I don't think the binding should reference anything else than the usual info about the interrupts property.

That I completely agree with, as long as it doesn't describe anything that is semantically incorrect.

Thanks,

	M.
Signature · 1 line
Jazz is not dead. It just smells funny...
#9 lore raw

PATCH v3 1/3 Documentation/bindings: Document the SafeXel cryptographic engine driver

Hello,

Quoted 6 lines · Marc Zyngier
Quoted 4 lines

The crypto block being in the CP part, it has a wired interrupt to the ICU (also in the CP). The ICU then turns this wired interrupt into a memory write transaction to a register called GICP SPI in the AP, which triggers a SPI interrupt in the GIC.

Is that some kind of Level-triggered MSI, ? la GICv3 GICD_SETSPI_NSR?

It is some kind of MSI, and the registers are called GICP_SETSPI/GICP_CLRSPI, so I would assume it's quite similar to this GICv3 feature.

Quoted 6 lines
Quoted 3 lines

However, I have a patch series that I plan to submit hopefully in the next days that adds an ICU driver, and changes the Device Tree to refer to the ICU interrupt instead.

OK, I'm quite interested to see that, specially if my above hunch is right...

I'll send the patches soon. I'm sure there will be lots of comments :)

Best regards,

Thomas

Signature · 3 lines
Thomas Petazzoni, CTO, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
#10 lore raw

PATCH v3 2/3 crypto: inside-secure: add SafeXcel EIP197 crypto engine driver

In reply to Antoine Tenart

Add support for Inside Secure SafeXcel EIP197 cryptographic engine, which can be found on Marvell Armada 7k and 8k boards. This driver currently implements: ecb(aes), cbc(aes), sha1, sha224, sha256 and hmac(sah1) algorithms.

Two firmwares are needed for this engine to work. Their are mostly used for more advanced operations than the ones supported (as of now), but we still need them to pass the data to the internal cryptographic engine.

---
 drivers/crypto/Kconfig                         |   17 +
 drivers/crypto/Makefile                        |    1 +
 drivers/crypto/inside-secure/Makefile          |    2 +
 drivers/crypto/inside-secure/safexcel.c        |  925 +++++++++++++++++++++
 drivers/crypto/inside-secure/safexcel.h        |  579 +++++++++++++
 drivers/crypto/inside-secure/safexcel_cipher.c |  555 +++++++++++++
 drivers/crypto/inside-secure/safexcel_hash.c   | 1045 ++++++++++++++++++++++++
 drivers/crypto/inside-secure/safexcel_ring.c   |  157 ++++
 8 files changed, 3281 insertions(+)
 create mode 100644 drivers/crypto/inside-secure/Makefile
 create mode 100644 drivers/crypto/inside-secure/safexcel.c
 create mode 100644 drivers/crypto/inside-secure/safexcel.h
 create mode 100644 drivers/crypto/inside-secure/safexcel_cipher.c
 create mode 100644 drivers/crypto/inside-secure/safexcel_hash.c
 create mode 100644 drivers/crypto/inside-secure/safexcel_ring.c
drivers/crypto/Kconfig +17 -0
index 473d31288ad8..d12a40450858 100644
@@ -619,4 +619,21 @@ config CRYPTO_DEV_BCM_SPU
 	  Secure Processing Unit (SPU). The SPU driver registers ablkcipher,
 	  ahash, and aead algorithms with the kernel cryptographic API.
 
+config CRYPTO_DEV_SAFEXCEL
+	tristate "Inside Secure's SafeXcel cryptographic engine driver"
+	depends on HAS_DMA && OF
+	depends on (ARM64 && ARCH_MVEBU) || (COMPILE_TEST && 64BIT)
+	select CRYPTO_AES
+	select CRYPTO_BLKCIPHER
+	select CRYPTO_HASH
+	select CRYPTO_HMAC
+	select CRYPTO_SHA1
+	select CRYPTO_SHA256
+	select CRYPTO_SHA512
+	help
+	  This driver interfaces with the SafeXcel EIP-197 cryptographic engine
+	  designed by Inside Secure. Select this if you want to use CBC/ECB
+	  chain mode, AES cipher mode and SHA1/SHA224/SHA256/SHA512 hash
+	  algorithms.
+
 endif # CRYPTO_HW
drivers/crypto/Makefile +1 -0
index 739609471169..7ed3e7940f76 100644
@@ -36,3 +36,4 @@ obj-$(CONFIG_CRYPTO_DEV_UX500) += ux500/
 obj-$(CONFIG_CRYPTO_DEV_VIRTIO) += virtio/
 obj-$(CONFIG_CRYPTO_DEV_VMX) += vmx/
 obj-$(CONFIG_CRYPTO_DEV_BCM_SPU) += bcm/
+obj-$(CONFIG_CRYPTO_DEV_SAFEXCEL) += inside-secure/
drivers/crypto/inside-secure/Makefile new file +2 -0
new file mode 100644
index 000000000000..302f07dde98c
@@ -0,0 +1,2 @@
+obj-$(CONFIG_CRYPTO_DEV_SAFEXCEL) += crypto_safexcel.o
+crypto_safexcel-objs := safexcel.o safexcel_ring.o safexcel_cipher.o safexcel_hash.o
drivers/crypto/inside-secure/safexcel.c new file +925 -0

925 lines not on this page · raw message

drivers/crypto/inside-secure/safexcel.h new file +579 -0

579 lines not on this page · raw message

drivers/crypto/inside-secure/safexcel_cipher.c new file +555 -0

555 lines not on this page · raw message

drivers/crypto/inside-secure/safexcel_hash.c new file +1045 -0

914 lines not on this page · raw message

drivers/crypto/inside-secure/safexcel_ring.c new file +157 -0

157 lines not on this page · raw message

The rest of this diff is not shown. View the raw message.

Signature · 1 line
2.11.0

Part of the diff is not shown here. View the raw message.

#11 lore raw

PATCH v3 2/3 crypto: inside-secure: add SafeXcel EIP197 crypto engine driver

[...]

Quoted 4 lines
drivers/crypto/inside-secure/safexcel.c new file +4 -0
+	priv->clk = of_clk_get(dev->of_node, 0);
+	if (!IS_ERR(priv->clk)) {
+		ret = clk_prepare_enable(priv->clk);
+		if (ret) {

drivers/crypto/inside-secure/safexcel.c line 807

Quoted 10 lines
drivers/crypto/inside-secure/safexcel.c new file +10 -0
+			dev_err(dev, "unable to enable clk (%d)\n", ret);
+			return ret;
+		}
+	} else {
+		/* The clock isn't mandatory */
+		if (PTR_ERR(priv->clk) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+	}
+
+	ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));

The correct address width of the engine in Marvell SoCs is 40bit.

drivers/crypto/inside-secure/safexcel.c line 818

Quoted 12 lines
drivers/crypto/inside-secure/safexcel.c new file +5 -0
+	if (ret)
+		goto err_clk;
+
+	priv->context_pool = dmam_pool_create("safexcel-context", dev,
+					      sizeof(struct

safexcel_context_record),

drivers/crypto/inside-secure/safexcel.c new file +6 -0
+					      1, 0);
+	if (!priv->context_pool) {
+		ret = -ENOMEM;
+		goto err_clk;
+	}
+

Thanks,
Igal

#12 lore raw

PATCH v3 2/3 crypto: inside-secure: add SafeXcel EIP197 crypto engine driver

Hi Igal,

Quoted 18 lines · Igal Liberman

[...]

Quoted 4 lines
drivers/crypto/inside-secure/safexcel.c new file +4 -0
+	priv->clk = of_clk_get(dev->of_node, 0);
+	if (!IS_ERR(priv->clk)) {
+		ret = clk_prepare_enable(priv->clk);
+		if (ret) {

drivers/crypto/inside-secure/safexcel.c line 807

Quoted 10 lines
drivers/crypto/inside-secure/safexcel.c new file +10 -0
+			dev_err(dev, "unable to enable clk (%d)\n", ret);
+			return ret;
+		}
+	} else {
+		/* The clock isn't mandatory */
+		if (PTR_ERR(priv->clk) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+	}
+
+	ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));

The correct address width of the engine in Marvell SoCs is 40bit.

Oops. I'll update.

Thanks!
Antoine

Signature · 10 lines
Antoine T?nart, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20170424/4f99b7e5/attachment.sig>
#13 lore raw

PATCH v3 2/3 crypto: inside-secure: add SafeXcel EIP197 crypto engine driver

Quoted 21 lines · Antoine Tenart

Hi Igal,

Quoted 18 lines · Igal Liberman

[...]

Quoted 4 lines
drivers/crypto/inside-secure/safexcel.c new file +4 -0
+	priv->clk = of_clk_get(dev->of_node, 0);
+	if (!IS_ERR(priv->clk)) {
+		ret = clk_prepare_enable(priv->clk);
+		if (ret) {

drivers/crypto/inside-secure/safexcel.c line 807

Quoted 10 lines
drivers/crypto/inside-secure/safexcel.c new file +10 -0
+			dev_err(dev, "unable to enable clk (%d)\n", ret);
+			return ret;
+		}
+	} else {
+		/* The clock isn't mandatory */
+		if (PTR_ERR(priv->clk) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+	}
+
+	ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));

The correct address width of the engine in Marvell SoCs is 40bit.

Is that what the IP block itself is internally limited to, or just how many bits happen to be wired up externally in the particular Marvell integrations?

Quoted 1 line

Oops. I'll update.

If the device itself can handle full 64-bit addresses, then the driver should reflect that regardless of the integration - describing integration limitations is the job of the firmware, e.g. with DT "dma-ranges", assuming they actually matter (typically if the whole SoC interconnect and physical memory map is the same width then having an even wider DMA mask doesn't make any difference - 64 bits still just means "everything").

If it's the case that the IP is configurable and could be synthesised with various internal address widths, then that might warrant a DT property to identify the particular configuration if it's not readable from some ID register, although it may be reasonable in practice to simply assume the chosen configuration to be sane (i.e. not smaller than the rest of the system) and that the driver can set the maximal DMA mask as above.

Robin.

Quoted 4 lines

Thanks!
Antoine

#14 lore raw

PATCH v3 2/3 crypto: inside-secure: add SafeXcel EIP197 crypto engine driver

Hi Robin

Quoted 37 lines

-----Original Message-----
From: linux-crypto-owner at vger.kernel.org [mailto:linux-crypto- owner at vger.kernel.org] On Behalf Of Robin Murphy
Sent: Wednesday, May 03, 2017 20:15
To: Antoine Tenart; Igal Liberman
Cc: herbert at gondor.apana.org.au; davem at davemloft.net;
jason at lakedaemon.net; andrew at lunn.ch; gregory.clement at free- electrons.com; sebastian.hesselbarth at gmail.com; linux-
crypto at vger.kernel.org; linux-arm-kernel at lists.infradead.org; thomas.petazzoni at free-electrons.com; boris.brezillon at free-electrons.com; Ofer Heifetz; Nadav Haklai
Subject: Re: [PATCH v3 2/3] crypto: inside-secure: add SafeXcel EIP197 crypto engine driver

Quoted 21 lines · Antoine Tenart

Hi Igal,

Quoted 18 lines · Igal Liberman

[...]

Quoted 4 lines
drivers/crypto/inside-secure/safexcel.c new file +4 -0
+	priv->clk = of_clk_get(dev->of_node, 0);
+	if (!IS_ERR(priv->clk)) {
+		ret = clk_prepare_enable(priv->clk);
+		if (ret) {

drivers/crypto/inside-secure/safexcel.c line 807

Quoted 10 lines
drivers/crypto/inside-secure/safexcel.c new file +10 -0
+			dev_err(dev, "unable to enable clk (%d)\n", ret);
+			return ret;
+		}
+	} else {
+		/* The clock isn't mandatory */
+		if (PTR_ERR(priv->clk) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+	}
+
+	ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));

The correct address width of the engine in Marvell SoCs is 40bit.

Quoted 3 lines

Is that what the IP block itself is internally limited to, or just how many bits happen to be wired up externally in the particular Marvell integrations?

The IP supports up to 64bit address width (depends on the revision). The 40bit limitation is related to Marvell integration.

Quoted 22 lines
Quoted 1 line

Oops. I'll update.

If the device itself can handle full 64-bit addresses, then the driver should reflect that regardless of the integration - describing integration limitations is the job of the firmware, e.g. with DT "dma-ranges", assuming they actually matter (typically if the whole SoC interconnect and physical memory map is the same width then having an even wider DMA mask doesn't make any difference - 64 bits still just means "everything").

If it's the case that the IP is configurable and could be synthesised with various internal address widths, then that might warrant a DT property to identify the particular configuration if it's not readable from some ID register, although it may be reasonable in practice to simply assume the chosen configuration to be sane (i.e. not smaller than the rest of the system) and that the driver can set the maximal DMA mask as above.

Robin.

Quoted 4 lines

Thanks!
Antoine

#15 lore raw

PATCH v3 2/3 crypto: inside-secure: add SafeXcel EIP197 crypto engine driver

In reply to Antoine Tenart

Am Montag, 24. April 2017, 09:54:06 CEST schrieb Antoine Tenart:

Hi Antoine,

drivers/crypto/inside-secure/safexcel_cipher.c line 31

Quoted 8 lines
drivers/crypto/inside-secure/safexcel_cipher.c new file +8 -0
+struct safexcel_cipher_ctx {
+	struct safexcel_context base;
+	struct safexcel_crypto_priv *priv;
+
+	enum safexcel_cipher_direction direction;
+	u32 mode;
+
+	__le32 key[8];

Can you please help me find the location where this memory is zeroized when released?

Quoted 30 lines
drivers/crypto/inside-secure/safexcel_cipher.c new file +30 -0
+	unsigned int key_len;
+};
+
+static void safexcel_cipher_token(struct safexcel_cipher_ctx *ctx,
+				  struct crypto_async_request *async,
+				  struct safexcel_command_desc *cdesc,
+				  u32 length)
+{
+	struct ablkcipher_request *req = ablkcipher_request_cast(async);
+	struct safexcel_token *token;
+	unsigned offset = 0;
+
+	if (ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CBC) {
+		offset = AES_BLOCK_SIZE / sizeof(u32);
+		memcpy(cdesc->control_data.token, req->info, AES_BLOCK_SIZE);
+
+		cdesc->control_data.options |= EIP197_OPTION_4_TOKEN_IV_CMD;
+	}
+
+	token = (struct safexcel_token *)(cdesc->control_data.token + offset);
+
+	token[0].opcode = EIP197_TOKEN_OPCODE_DIRECTION;
+	token[0].packet_length = length;
+	token[0].stat = EIP197_TOKEN_STAT_LAST_PACKET;
+	token[0].instructions = EIP197_TOKEN_INS_LAST |
+				EIP197_TOKEN_INS_TYPE_CRYTO |
+				EIP197_TOKEN_INS_TYPE_OUTPUT;
+}
+
+static int safexcel_aes_setkey(struct crypto_ablkcipher *ctfm, const u8
Quoted 2 lines

*key, + unsigned int len)
+{

You still use ablkcipher. I thought that it is on its way out in favor of the skcipher API. Why do you stick to ablkcipher?

Note, a change could be as simple as s/ablkcipher/skcipher/g

Quoted 12 lines
drivers/crypto/inside-secure/safexcel_cipher.c new file +12 -0
+	struct crypto_tfm *tfm = crypto_ablkcipher_tfm(ctfm);
+	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct crypto_aes_ctx aes;
+	int ret, i;
+
+	ret = crypto_aes_expand_key(&aes, key, len);
+	if (ret) {
+		crypto_ablkcipher_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
+		return ret;
+	}
+
+	for (i = 0; i < len / sizeof(u32); i++) {

drivers/crypto/inside-secure/safexcel_cipher.c line 85

Quoted 10 lines
drivers/crypto/inside-secure/safexcel_cipher.c new file +10 -0
+		if (ctx->key[i] != cpu_to_le32(aes.key_enc[i])) {
+			ctx->base.needs_inv = true;
+			break;
+		}
+	}
+
+	for (i = 0; i < len / sizeof(u32); i++)
+		ctx->key[i] = cpu_to_le32(aes.key_enc[i]);
+
+	ctx->key_len = len;

memzero_explicit(aes)?

Quoted 123 lines
drivers/crypto/inside-secure/safexcel_cipher.c new file +42 -0
+
+	return 0;
+}
+
+static int safexcel_context_control(struct safexcel_cipher_ctx *ctx,
+				    struct safexcel_command_desc *cdesc)
+{
+	struct safexcel_crypto_priv *priv = ctx->priv;
+	int ctrl_size;
+
+	if (ctx->direction == SAFEXCEL_ENCRYPT)
+		cdesc->control_data.control0 |= CONTEXT_CONTROL_TYPE_CRYPTO_OUT;
+	else
+		cdesc->control_data.control0 |= CONTEXT_CONTROL_TYPE_CRYPTO_IN;
+
+	cdesc->control_data.control0 |= CONTEXT_CONTROL_KEY_EN;
+	cdesc->control_data.control1 |= ctx->mode;
+
+	switch (ctx->key_len) {
+	case AES_KEYSIZE_128:
+		cdesc->control_data.control0 |= CONTEXT_CONTROL_CRYPTO_ALG_AES128;
+		ctrl_size = 4;
+		break;
+	case AES_KEYSIZE_192:
+		cdesc->control_data.control0 |= CONTEXT_CONTROL_CRYPTO_ALG_AES192;
+		ctrl_size = 6;
+		break;
+	case AES_KEYSIZE_256:
+		cdesc->control_data.control0 |= CONTEXT_CONTROL_CRYPTO_ALG_AES256;
+		ctrl_size = 8;
+		break;
+	default:
+		dev_err(priv->dev, "aes keysize not supported: %u\n",
+			ctx->key_len);
+		return -EINVAL;
+	}
+	cdesc->control_data.control0 |= CONTEXT_CONTROL_SIZE(ctrl_size);
+
+	return 0;
+}
+
+static int safexcel_handle_result(struct safexcel_crypto_priv *priv, int

ring, + struct crypto_async_request *async,

drivers/crypto/inside-secure/safexcel_cipher.c new file +80 -0
+				  bool *should_complete, int *ret)
+{
+	struct ablkcipher_request *req = ablkcipher_request_cast(async);
+	struct safexcel_result_desc *rdesc;
+	int ndesc = 0;
+
+	*ret = 0;
+
+	spin_lock_bh(&priv->ring[ring].egress_lock);
+	do {
+		rdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].rdr);
+		if (IS_ERR(rdesc)) {
+			dev_err(priv->dev,
+				"cipher: result: could not retrieve the result descriptor\n");
+			*ret = PTR_ERR(rdesc);
+			break;
+		}
+
+		if (rdesc->result_data.error_code) {
+			dev_err(priv->dev,
+				"cipher: result: result descriptor error (%d)\n",
+				rdesc->result_data.error_code);
+			*ret = -EIO;
+		}
+
+		ndesc++;
+	} while (!rdesc->last_seg);
+
+	safexcel_complete(priv, ring);
+	spin_unlock_bh(&priv->ring[ring].egress_lock);
+
+	if (req->src == req->dst) {
+		dma_unmap_sg(priv->dev, req->src,
+			     sg_nents_for_len(req->src, req->nbytes),
+			     DMA_BIDIRECTIONAL);
+	} else {
+		dma_unmap_sg(priv->dev, req->src,
+			     sg_nents_for_len(req->src, req->nbytes),
+			     DMA_TO_DEVICE);
+		dma_unmap_sg(priv->dev, req->dst,
+			     sg_nents_for_len(req->dst, req->nbytes),
+			     DMA_FROM_DEVICE);
+	}
+
+	*should_complete = true;
+
+	return ndesc;
+}
+
+static int safexcel_aes_send(struct crypto_async_request *async,
+			     int ring, struct safexcel_request *request,
+			     int *commands, int *results)
+{
+	struct ablkcipher_request *req = ablkcipher_request_cast(async);
+	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
+	struct safexcel_crypto_priv *priv = ctx->priv;
+	struct safexcel_command_desc *cdesc;
+	struct safexcel_result_desc *rdesc;
+	struct scatterlist *sg;
+	int nr_src, nr_dst, n_cdesc = 0, n_rdesc = 0, queued = req->nbytes;
+	int i, ret = 0;
+
+	request->req = &req->base;
+
+	if (req->src == req->dst) {
+		nr_src = dma_map_sg(priv->dev, req->src,
+				    sg_nents_for_len(req->src, req->nbytes),
+				    DMA_BIDIRECTIONAL);
+		nr_dst = nr_src;
+		if (!nr_src)
+			return -EINVAL;
+	} else {
+		nr_src = dma_map_sg(priv->dev, req->src,
+				    sg_nents_for_len(req->src, req->nbytes),
+				    DMA_TO_DEVICE);
+		if (!nr_src)
+			return -EINVAL;
+
+		nr_dst = dma_map_sg(priv->dev, req->dst,
+				    sg_nents_for_len(req->dst, req->nbytes),

drivers/crypto/inside-secure/safexcel_cipher.c line 218

Quoted 10 lines
drivers/crypto/inside-secure/safexcel_cipher.c new file +10 -0
+				    DMA_FROM_DEVICE);
+		if (!nr_dst) {
+			dma_unmap_sg(priv->dev, req->src,
+				     sg_nents_for_len(req->src, req->nbytes),
+				     DMA_TO_DEVICE);
+			return -EINVAL;
+		}
+	}
+
+	memcpy(ctx->base.ctxr->data, ctx->key, ctx->key_len);

Is ctxr->data properly zeroized?

Ciao
Stephan

#16 lore raw

PATCH v3 2/3 crypto: inside-secure: add SafeXcel EIP197 crypto engine driver

Hi Stephan,

Quoted 13 lines · Stephan M?ller

Am Montag, 24. April 2017, 09:54:06 CEST schrieb Antoine Tenart:

drivers/crypto/inside-secure/safexcel_cipher.c line 31

Quoted 8 lines
drivers/crypto/inside-secure/safexcel_cipher.c new file +8 -0
+struct safexcel_cipher_ctx {
+	struct safexcel_context base;
+	struct safexcel_crypto_priv *priv;
+
+	enum safexcel_cipher_direction direction;
+	u32 mode;
+
+	__le32 key[8];

Can you please help me find the location where this memory is zeroized when released?

It's not, I'll fix this.

Quoted 33 lines
Quoted 27 lines
drivers/crypto/inside-secure/safexcel_cipher.c new file +27 -0
+static void safexcel_cipher_token(struct safexcel_cipher_ctx *ctx,
+				  struct crypto_async_request *async,
+				  struct safexcel_command_desc *cdesc,
+				  u32 length)
+{
+	struct ablkcipher_request *req = ablkcipher_request_cast(async);
+	struct safexcel_token *token;
+	unsigned offset = 0;
+
+	if (ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CBC) {
+		offset = AES_BLOCK_SIZE / sizeof(u32);
+		memcpy(cdesc->control_data.token, req->info, AES_BLOCK_SIZE);
+
+		cdesc->control_data.options |= EIP197_OPTION_4_TOKEN_IV_CMD;
+	}
+
+	token = (struct safexcel_token *)(cdesc->control_data.token + offset);
+
+	token[0].opcode = EIP197_TOKEN_OPCODE_DIRECTION;
+	token[0].packet_length = length;
+	token[0].stat = EIP197_TOKEN_STAT_LAST_PACKET;
+	token[0].instructions = EIP197_TOKEN_INS_LAST |
+				EIP197_TOKEN_INS_TYPE_CRYTO |
+				EIP197_TOKEN_INS_TYPE_OUTPUT;
+}
+
+static int safexcel_aes_setkey(struct crypto_ablkcipher *ctfm, const u8
Quoted 2 lines

*key, + unsigned int len)
+{

You still use ablkcipher. I thought that it is on its way out in favor of the skcipher API. Why do you stick to ablkcipher?

Quoted 1 line

Note, a change could be as simple as s/ablkcipher/skcipher/g

Because I wasn't aware of this :) I'll update.

Quoted 16 lines
Quoted 16 lines
drivers/crypto/inside-secure/safexcel_cipher.c new file +16 -0
+	struct crypto_tfm *tfm = crypto_ablkcipher_tfm(ctfm);
+	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct crypto_aes_ctx aes;
+	int ret, i;
+
+	ret = crypto_aes_expand_key(&aes, key, len);
+	if (ret) {
+		crypto_ablkcipher_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
+		return ret;
+	}
+
+	for (i = 0; i < len / sizeof(u32); i++) {
+		if (ctx->key[i] != cpu_to_le32(aes.key_enc[i])) {
+			ctx->base.needs_inv = true;
+			break;
+		}
Quoted 8 lines

drivers/crypto/inside-secure/safexcel_cipher.c line 85

Quoted 6 lines
drivers/crypto/inside-secure/safexcel_cipher.c new file +6 -0
+	}
+
+	for (i = 0; i < len / sizeof(u32); i++)
+		ctx->key[i] = cpu_to_le32(aes.key_enc[i]);
+
+	ctx->key_len = len;

memzero_explicit(aes)?

OK, I'll update.

Quoted 35 lines
Quoted 35 lines
drivers/crypto/inside-secure/safexcel_cipher.c new file +35 -0
+static int safexcel_aes_send(struct crypto_async_request *async,
+			     int ring, struct safexcel_request *request,
+			     int *commands, int *results)
+{
+	struct ablkcipher_request *req = ablkcipher_request_cast(async);
+	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
+	struct safexcel_crypto_priv *priv = ctx->priv;
+	struct safexcel_command_desc *cdesc;
+	struct safexcel_result_desc *rdesc;
+	struct scatterlist *sg;
+	int nr_src, nr_dst, n_cdesc = 0, n_rdesc = 0, queued = req->nbytes;
+	int i, ret = 0;
+
+	request->req = &req->base;
+
+	if (req->src == req->dst) {
+		nr_src = dma_map_sg(priv->dev, req->src,
+				    sg_nents_for_len(req->src, req->nbytes),
+				    DMA_BIDIRECTIONAL);
+		nr_dst = nr_src;
+		if (!nr_src)
+			return -EINVAL;
+	} else {
+		nr_src = dma_map_sg(priv->dev, req->src,
+				    sg_nents_for_len(req->src, req->nbytes),
+				    DMA_TO_DEVICE);
+		if (!nr_src)
+			return -EINVAL;
+
+		nr_dst = dma_map_sg(priv->dev, req->dst,
+				    sg_nents_for_len(req->dst, req->nbytes),
+				    DMA_FROM_DEVICE);
+		if (!nr_dst) {
+			dma_unmap_sg(priv->dev, req->src,
+				     sg_nents_for_len(req->src, req->nbytes),
Quoted 8 lines

drivers/crypto/inside-secure/safexcel_cipher.c line 218

Quoted 6 lines
drivers/crypto/inside-secure/safexcel_cipher.c new file +6 -0
+				     DMA_TO_DEVICE);
+			return -EINVAL;
+		}
+	}
+
+	memcpy(ctx->base.ctxr->data, ctx->key, ctx->key_len);

Is ctxr->data properly zeroized?

No, I'll update.

Thanks for the review!
Antoine

Signature · 10 lines
Antoine T?nart, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20170425/4970b066/attachment-0001.sig>
#17 lore raw

PATCH v3 2/3 crypto: inside-secure: add SafeXcel EIP197 crypto engine driver

In reply to Antoine Tenart

Hi Antoine,

Quoted 10 lines · Antoine Tenart

Add support for Inside Secure SafeXcel EIP197 cryptographic engine, which can be found on Marvell Armada 7k and 8k boards. This driver currently implements: ecb(aes), cbc(aes), sha1, sha224, sha256 and hmac(sah1) algorithms.

Two firmwares are needed for this engine to work. Their are mostly used for more advanced operations than the ones supported (as of now), but we still need them to pass the data to the internal cryptographic engine.

[...]

Quoted 18 lines
drivers/crypto/inside-secure/safexcel.c new file +12 -0
new file mode 100644
index 000000000000..9cb3d0832835
@@ -0,0 +1,925 @@
+/*
+ * Copyright (C) 2017 Marvell
+ *
+ * Antoine Tenart <[email protected]>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>

drivers/crypto/inside-secure/safexcel.c line 22

Quoted 10 lines
drivers/crypto/inside-secure/safexcel.c new file +10 -0
+#include <linux/dmapool.h>
+#include <linux/firmware.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/workqueue.h>
+
+#include <asm/dma-mapping.h>

<linux/dma-mapping.h> everywhere, please.

Other than that, the DMA aspects all look much nicer now, thanks.

Robin.

#18 lore raw

PATCH v3 2/3 crypto: inside-secure: add SafeXcel EIP197 crypto engine driver

Hi Robin,

Quoted 7 lines · Robin Murphy

Review

Quoted 2 lines · Antoine Tenart
(quoted diff) +2 -0
+
+#include <asm/dma-mapping.h>

<linux/dma-mapping.h> everywhere, please.

Other than that, the DMA aspects all look much nicer now, thanks.

I'll update and resend a series when the next -rc1 is out.

Thanks!
Antoine

Signature · 10 lines
Antoine T?nart, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20170503/f1c7a8bc/attachment.sig>
#19 lore raw

PATCH v3 3/3 MAINTAINERS: add a maintainer for the Inside Secure crypto driver

In reply to Antoine Tenart

A new cryptographic engine driver was added in drivers/crypto/inside-secure. Add myself as a maintainer for this driver.

---
 MAINTAINERS | 6 ++++++
 1 file changed, 6 insertions(+)
MAINTAINERS +6 -0
index c265a5fe4848..7240b9bca638 100644
@@ -6487,6 +6487,12 @@ F:	Documentation/input/multi-touch-protocol.txt
 F:	drivers/input/input-mt.c
 K:	\b(ABS|SYN)_MT_
 
+INSIDE SECURE CRYPTO DRIVER
+M:	Antoine Tenart <[email protected]>
+F:	drivers/crypto/inside-secure/
+S:	Maintained
+L:	linux-crypto at vger.kernel.org
+
 INTEL ASoC BDW/HSW DRIVERS
 M:	Jie Yang <[email protected]>
 L:	alsa-devel at alsa-project.org (moderated for non-subscribers)
Signature · 1 line
2.11.0