This update includes the following changes:

API:
 
 - Fix memcpy_sglist to handle partially overlapping SG lists.
 - Use memcpy_sglist to replace null skcipher.
 - Rename CRYPTO_TESTS to CRYPTO_BENCHMARK.
 - Flip CRYPTO_MANAGER_DISABLE_TEST into CRYPTO_SELFTESTS.
 - Hide CRYPTO_MANAGER.
 - Add delayed freeing of driver crypto_alg structures.
 
 Compression:
 
 - Allocate large buffers on first use instead of initialisation in scomp.
 - Drop destination linearisation buffer in scomp.
 - Move scomp stream allocation into acomp.
 - Add acomp scatter-gather walker.
 - Remove request chaining.
 - Add optional async request allocation.
 
 Hashing:
 
 - Remove request chaining.
 - Add optional async request allocation.
 - Move partial block handling into API.
 - Add ahash support to hmac.
 - Fix shash documentation to disallow usage in hard IRQs.
 
 Algorithms:
 
 - Remove unnecessary SIMD fallback code on x86 and arm/arm64.
 - Drop avx10_256 xts(aes)/ctr(aes) on x86.
 - Improve avx-512 optimisations for xts(aes).
 - Move chacha arch implementations into lib/crypto.
 - Move poly1305 into lib/crypto and drop unused Crypto API algorithm.
 - Disable powerpc/poly1305 as it has no SIMD fallback.
 - Move sha256 arch implementations into lib/crypto.
 - Convert deflate to acomp.
 - Set block size correctly in cbcmac.
 
 Drivers:
 
 - Do not use sg_dma_len before mapping in sun8i-ss.
 - Fix warm-reboot failure by making shutdown do more work in qat.
 - Add locking in zynqmp-sha.
 - Remove cavium/zip.
 - Add support for PCI device 0x17D8 to ccp.
 - Add qat_6xxx support in qat.
 - Add support for RK3576 in rockchip-rng.
 - Add support for i.MX8QM in caam.
 
 Others:
 
 - Fix irq_fpu_usable/kernel_fpu_begin inconsistency during CPU bring-up.
 - Add new SEV/SNP platform shutdown API in ccp.
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEn51F/lCuNhUwmDeSxycdCkmxi6cFAmgz47AACgkQxycdCkmx
 i6fvKRAAr4Xa903L0r1Q1P1alQqoFFCqimUWeH72m68LiWynHWi0lUo0z/+tKweg
 mnPStz7/Ha9HRHJjdNCMPnlJqXQDkuH3bIOuBJCwduDuhHo9VGOd46XGzmGMv3gb
 HKuZhI0lk7pznK3CSyD/2nHmbDCHD+7feTZSBMoN9mm875+aSoM6fdxgak8uPFcq
 KbB1L+hObTn2kAPSqRrNOR8/xG2N7hdH8eax7Li+LAtqYNVT5HvWVECsB/CKRPfB
 sgAv3UTzcIFapSSHUHaONppSeoqPAIAeV7SdQhJvlT+EUUR/h/B6+D9OUQQqbphQ
 LBalgTnqMKl0ymDEQFQ6QyYCat9ZfNmDft2WcXEsxc8PxImkgJI1W3B8O51sOjbG
 78D8JqVQ96dleo4FsBhM2wfG0b41JM6zU4raC4vS7a3qsUS+Q1MpehvcS1iORicy
 SpGdE8e7DLlxKhzWyW1xJnbrtMZDC7Sa2hUnxrvP0/xOvRhChKscRVtWcf0a5q7X
 8JmuvwVSOJuSbQ3MeFbQvpo5lR9+0WsNjM6e9miiH6Y7vZUKmWcq2yDp377qVzeh
 7NK6+OwGIQZZExrmtPw2BXwssT9Eg+ks6Y7g2Ne7yzvrjVNfEPY7Cws/5w7p8mRS
 qhrcpbJNFlWgD7YYkmGZFTQ8DCN25ipP8lklO/hbcfchqLE/o1o=
 =O8L5
 -----END PGP SIGNATURE-----

Merge tag 'v6.16-p1' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6

Pull crypto updates from Herbert Xu:
 "API:
   - Fix memcpy_sglist to handle partially overlapping SG lists
   - Use memcpy_sglist to replace null skcipher
   - Rename CRYPTO_TESTS to CRYPTO_BENCHMARK
   - Flip CRYPTO_MANAGER_DISABLE_TEST into CRYPTO_SELFTESTS
   - Hide CRYPTO_MANAGER
   - Add delayed freeing of driver crypto_alg structures

  Compression:
   - Allocate large buffers on first use instead of initialisation in scomp
   - Drop destination linearisation buffer in scomp
   - Move scomp stream allocation into acomp
   - Add acomp scatter-gather walker
   - Remove request chaining
   - Add optional async request allocation

  Hashing:
   - Remove request chaining
   - Add optional async request allocation
   - Move partial block handling into API
   - Add ahash support to hmac
   - Fix shash documentation to disallow usage in hard IRQs

  Algorithms:
   - Remove unnecessary SIMD fallback code on x86 and arm/arm64
   - Drop avx10_256 xts(aes)/ctr(aes) on x86
   - Improve avx-512 optimisations for xts(aes)
   - Move chacha arch implementations into lib/crypto
   - Move poly1305 into lib/crypto and drop unused Crypto API algorithm
   - Disable powerpc/poly1305 as it has no SIMD fallback
   - Move sha256 arch implementations into lib/crypto
   - Convert deflate to acomp
   - Set block size correctly in cbcmac

  Drivers:
   - Do not use sg_dma_len before mapping in sun8i-ss
   - Fix warm-reboot failure by making shutdown do more work in qat
   - Add locking in zynqmp-sha
   - Remove cavium/zip
   - Add support for PCI device 0x17D8 to ccp
   - Add qat_6xxx support in qat
   - Add support for RK3576 in rockchip-rng
   - Add support for i.MX8QM in caam

  Others:
   - Fix irq_fpu_usable/kernel_fpu_begin inconsistency during CPU bring-up
   - Add new SEV/SNP platform shutdown API in ccp"

* tag 'v6.16-p1' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6: (382 commits)
  x86/fpu: Fix irq_fpu_usable() to return false during CPU onlining
  crypto: qat - add missing header inclusion
  crypto: api - Redo lookup on EEXIST
  Revert "crypto: testmgr - Add hash export format testing"
  crypto: marvell/cesa - Do not chain submitted requests
  crypto: powerpc/poly1305 - add depends on BROKEN for now
  Revert "crypto: powerpc/poly1305 - Add SIMD fallback"
  crypto: ccp - Add missing tee info reg for teev2
  crypto: ccp - Add missing bootloader info reg for pspv5
  crypto: sun8i-ce - move fallback ahash_request to the end of the struct
  crypto: octeontx2 - Use dynamic allocated memory region for lmtst
  crypto: octeontx2 - Initialize cptlfs device info once
  crypto: xts - Only add ecb if it is not already there
  crypto: lrw - Only add ecb if it is not already there
  crypto: testmgr - Add hash export format testing
  crypto: testmgr - Use ahash for generic tfm
  crypto: hmac - Add ahash support
  crypto: testmgr - Ignore EEXIST on shash allocation
  crypto: algapi - Add driver template support to crypto_inst_setname
  crypto: shash - Set reqsize in shash_alg
  ...
pull/1250/head
Linus Torvalds 2025-05-26 13:47:28 -07:00
commit 14418ddcc2
583 changed files with 13829 additions and 19664 deletions

View File

@ -4,7 +4,7 @@ KernelVersion: 6.7
Contact: qat-linux@intel.com Contact: qat-linux@intel.com
Description: (RO) Reports the number of correctable errors detected by the device. Description: (RO) Reports the number of correctable errors detected by the device.
This attribute is only available for qat_4xxx devices. This attribute is only available for qat_4xxx and qat_6xxx devices.
What: /sys/bus/pci/devices/<BDF>/qat_ras/errors_nonfatal What: /sys/bus/pci/devices/<BDF>/qat_ras/errors_nonfatal
Date: January 2024 Date: January 2024
@ -12,7 +12,7 @@ KernelVersion: 6.7
Contact: qat-linux@intel.com Contact: qat-linux@intel.com
Description: (RO) Reports the number of non fatal errors detected by the device. Description: (RO) Reports the number of non fatal errors detected by the device.
This attribute is only available for qat_4xxx devices. This attribute is only available for qat_4xxx and qat_6xxx devices.
What: /sys/bus/pci/devices/<BDF>/qat_ras/errors_fatal What: /sys/bus/pci/devices/<BDF>/qat_ras/errors_fatal
Date: January 2024 Date: January 2024
@ -20,7 +20,7 @@ KernelVersion: 6.7
Contact: qat-linux@intel.com Contact: qat-linux@intel.com
Description: (RO) Reports the number of fatal errors detected by the device. Description: (RO) Reports the number of fatal errors detected by the device.
This attribute is only available for qat_4xxx devices. This attribute is only available for qat_4xxx and qat_6xxx devices.
What: /sys/bus/pci/devices/<BDF>/qat_ras/reset_error_counters What: /sys/bus/pci/devices/<BDF>/qat_ras/reset_error_counters
Date: January 2024 Date: January 2024
@ -38,4 +38,4 @@ Description: (WO) Write to resets all error counters of a device.
# cat /sys/bus/pci/devices/<BDF>/qat_ras/errors_fatal # cat /sys/bus/pci/devices/<BDF>/qat_ras/errors_fatal
0 0
This attribute is only available for qat_4xxx devices. This attribute is only available for qat_4xxx and qat_6xxx devices.

View File

@ -0,0 +1,38 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/amd,ccp-seattle-v1a.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: AMD Cryptographic Coprocessor (ccp)
maintainers:
- Tom Lendacky <thomas.lendacky@amd.com>
properties:
compatible:
const: amd,ccp-seattle-v1a
reg:
maxItems: 1
interrupts:
maxItems: 1
dma-coherent: true
required:
- compatible
- reg
- interrupts
additionalProperties: false
examples:
- |
crypto@e0100000 {
compatible = "amd,ccp-seattle-v1a";
reg = <0xe0100000 0x10000>;
interrupts = <0 3 4>;
dma-coherent;
};

View File

@ -1,17 +0,0 @@
* AMD Cryptographic Coprocessor driver (ccp)
Required properties:
- compatible: Should be "amd,ccp-seattle-v1a"
- reg: Address and length of the register set for the device
- interrupts: Should contain the CCP interrupt
Optional properties:
- dma-coherent: Present if dma operations are coherent
Example:
ccp@e0100000 {
compatible = "amd,ccp-seattle-v1a";
reg = <0 0xe0100000 0 0x10000>;
interrupt-parent = <&gic>;
interrupts = <0 3 4>;
};

View File

@ -1,16 +0,0 @@
Axis crypto engine with PDMA interface.
Required properties:
- compatible : Should be one of the following strings:
"axis,artpec6-crypto" for the version in the Axis ARTPEC-6 SoC
"axis,artpec7-crypto" for the version in the Axis ARTPEC-7 SoC.
- reg: Base address and size for the PDMA register area.
- interrupts: Interrupt handle for the PDMA interrupt line.
Example:
crypto@f4264000 {
compatible = "axis,artpec6-crypto";
reg = <0xf4264000 0x1000>;
interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
};

View File

@ -0,0 +1,39 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/crypto/axis,artpec6-crypto.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Axis ARTPEC6 crypto engine with PDMA interface
maintainers:
- Lars Persson <lars.persson@axis.com>
properties:
compatible:
enum:
- axis,artpec6-crypto
- axis,artpec7-crypto
reg:
maxItems: 1
interrupts:
maxItems: 1
required:
- compatible
- reg
- interrupts
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
crypto@f4264000 {
compatible = "axis,artpec6-crypto";
reg = <0xf4264000 0x1000>;
interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
};

View File

@ -1,22 +0,0 @@
The Broadcom Secure Processing Unit (SPU) hardware supports symmetric
cryptographic offload for Broadcom SoCs. A SoC may have multiple SPU hardware
blocks.
Required properties:
- compatible: Should be one of the following:
brcm,spum-crypto - for devices with SPU-M hardware
brcm,spu2-crypto - for devices with SPU2 hardware
brcm,spu2-v2-crypto - for devices with enhanced SPU2 hardware features like SHA3
and Rabin Fingerprint support
brcm,spum-nsp-crypto - for the Northstar Plus variant of the SPU-M hardware
- reg: Should contain SPU registers location and length.
- mboxes: The mailbox channel to be used to communicate with the SPU.
Mailbox channels correspond to DMA rings on the device.
Example:
crypto@612d0000 {
compatible = "brcm,spum-crypto";
reg = <0 0x612d0000 0 0x900>;
mboxes = <&pdc0 0>;
};

View File

@ -0,0 +1,44 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/brcm,spum-crypto.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Broadcom SPU Crypto Offload
maintainers:
- Rob Rice <rob.rice@broadcom.com>
description:
The Broadcom Secure Processing Unit (SPU) hardware supports symmetric
cryptographic offload for Broadcom SoCs. A SoC may have multiple SPU hardware
blocks.
properties:
compatible:
enum:
- brcm,spum-crypto
- brcm,spu2-crypto
- brcm,spu2-v2-crypto # enhanced SPU2 hardware features like SHA3 and Rabin Fingerprint support
- brcm,spum-nsp-crypto # Northstar Plus variant of the SPU-M hardware
reg:
maxItems: 1
mboxes:
maxItems: 1
required:
- compatible
- reg
- mboxes
additionalProperties: false
examples:
- |
crypto@612d0000 {
compatible = "brcm,spum-crypto";
reg = <0x612d0000 0x900>;
mboxes = <&pdc0 0>;
};

View File

@ -38,7 +38,9 @@ properties:
compatible: compatible:
oneOf: oneOf:
- items: - items:
- const: fsl,sec-v5.4 - enum:
- fsl,sec-v5.4
- fsl,sec-v6.0
- const: fsl,sec-v5.0 - const: fsl,sec-v5.0
- const: fsl,sec-v4.0 - const: fsl,sec-v4.0
- items: - items:
@ -93,6 +95,12 @@ patternProperties:
properties: properties:
compatible: compatible:
oneOf: oneOf:
- items:
- const: fsl,sec-v6.0-job-ring
- const: fsl,sec-v5.2-job-ring
- const: fsl,sec-v5.0-job-ring
- const: fsl,sec-v4.4-job-ring
- const: fsl,sec-v4.0-job-ring
- items: - items:
- const: fsl,sec-v5.4-job-ring - const: fsl,sec-v5.4-job-ring
- const: fsl,sec-v5.0-job-ring - const: fsl,sec-v5.0-job-ring

View File

@ -1,157 +0,0 @@
SEC 6 is as Freescale's Cryptographic Accelerator and Assurance Module (CAAM).
Currently Freescale powerpc chip C29X is embedded with SEC 6.
SEC 6 device tree binding include:
-SEC 6 Node
-Job Ring Node
-Full Example
=====================================================================
SEC 6 Node
Description
Node defines the base address of the SEC 6 block.
This block specifies the address range of all global
configuration registers for the SEC 6 block.
For example, In C293, we could see three SEC 6 node.
PROPERTIES
- compatible
Usage: required
Value type: <string>
Definition: Must include "fsl,sec-v6.0".
- fsl,sec-era
Usage: optional
Value type: <u32>
Definition: A standard property. Define the 'ERA' of the SEC
device.
- #address-cells
Usage: required
Value type: <u32>
Definition: A standard property. Defines the number of cells
for representing physical addresses in child nodes.
- #size-cells
Usage: required
Value type: <u32>
Definition: A standard property. Defines the number of cells
for representing the size of physical addresses in
child nodes.
- reg
Usage: required
Value type: <prop-encoded-array>
Definition: A standard property. Specifies the physical
address and length of the SEC 6 configuration registers.
- ranges
Usage: required
Value type: <prop-encoded-array>
Definition: A standard property. Specifies the physical address
range of the SEC 6.0 register space (-SNVS not included). A
triplet that includes the child address, parent address, &
length.
Note: All other standard properties (see the Devicetree Specification)
are allowed but are optional.
EXAMPLE
crypto@a0000 {
compatible = "fsl,sec-v6.0";
fsl,sec-era = <6>;
#address-cells = <1>;
#size-cells = <1>;
reg = <0xa0000 0x20000>;
ranges = <0 0xa0000 0x20000>;
};
=====================================================================
Job Ring (JR) Node
Child of the crypto node defines data processing interface to SEC 6
across the peripheral bus for purposes of processing
cryptographic descriptors. The specified address
range can be made visible to one (or more) cores.
The interrupt defined for this node is controlled within
the address range of this node.
- compatible
Usage: required
Value type: <string>
Definition: Must include "fsl,sec-v6.0-job-ring".
- reg
Usage: required
Value type: <prop-encoded-array>
Definition: Specifies a two JR parameters: an offset from
the parent physical address and the length the JR registers.
- interrupts
Usage: required
Value type: <prop_encoded-array>
Definition: Specifies the interrupts generated by this
device. The value of the interrupts property
consists of one interrupt specifier. The format
of the specifier is defined by the binding document
describing the node's interrupt parent.
EXAMPLE
jr@1000 {
compatible = "fsl,sec-v6.0-job-ring";
reg = <0x1000 0x1000>;
interrupts = <49 2 0 0>;
};
===================================================================
Full Example
Since some chips may contain more than one SEC, the dtsi contains
only the node contents, not the node itself. A chip using the SEC
should include the dtsi inside each SEC node. Example:
In qoriq-sec6.0.dtsi:
compatible = "fsl,sec-v6.0";
fsl,sec-era = <6>;
#address-cells = <1>;
#size-cells = <1>;
jr@1000 {
compatible = "fsl,sec-v6.0-job-ring",
"fsl,sec-v5.2-job-ring",
"fsl,sec-v5.0-job-ring",
"fsl,sec-v4.4-job-ring",
"fsl,sec-v4.0-job-ring";
reg = <0x1000 0x1000>;
};
jr@2000 {
compatible = "fsl,sec-v6.0-job-ring",
"fsl,sec-v5.2-job-ring",
"fsl,sec-v5.0-job-ring",
"fsl,sec-v4.4-job-ring",
"fsl,sec-v4.0-job-ring";
reg = <0x2000 0x1000>;
};
In the C293 device tree, we add the include of public property:
crypto@a0000 {
/include/ "qoriq-sec6.0.dtsi"
}
crypto@a0000 {
reg = <0xa0000 0x20000>;
ranges = <0 0xa0000 0x20000>;
jr@1000 {
interrupts = <49 2 0 0>;
};
jr@2000 {
interrupts = <50 2 0 0>;
};
};

View File

@ -0,0 +1,134 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/crypto/hisilicon,hip06-sec.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Hisilicon hip06/hip07 Security Accelerator
maintainers:
- Jonathan Cameron <Jonathan.Cameron@huawei.com>
properties:
compatible:
enum:
- hisilicon,hip06-sec
- hisilicon,hip07-sec
reg:
items:
- description: Registers for backend processing engines
- description: Registers for common functionality
- description: Registers for queue 0
- description: Registers for queue 1
- description: Registers for queue 2
- description: Registers for queue 3
- description: Registers for queue 4
- description: Registers for queue 5
- description: Registers for queue 6
- description: Registers for queue 7
- description: Registers for queue 8
- description: Registers for queue 9
- description: Registers for queue 10
- description: Registers for queue 11
- description: Registers for queue 12
- description: Registers for queue 13
- description: Registers for queue 14
- description: Registers for queue 15
interrupts:
items:
- description: SEC unit error queue interrupt
- description: Completion interrupt for queue 0
- description: Error interrupt for queue 0
- description: Completion interrupt for queue 1
- description: Error interrupt for queue 1
- description: Completion interrupt for queue 2
- description: Error interrupt for queue 2
- description: Completion interrupt for queue 3
- description: Error interrupt for queue 3
- description: Completion interrupt for queue 4
- description: Error interrupt for queue 4
- description: Completion interrupt for queue 5
- description: Error interrupt for queue 5
- description: Completion interrupt for queue 6
- description: Error interrupt for queue 6
- description: Completion interrupt for queue 7
- description: Error interrupt for queue 7
- description: Completion interrupt for queue 8
- description: Error interrupt for queue 8
- description: Completion interrupt for queue 9
- description: Error interrupt for queue 9
- description: Completion interrupt for queue 10
- description: Error interrupt for queue 10
- description: Completion interrupt for queue 11
- description: Error interrupt for queue 11
- description: Completion interrupt for queue 12
- description: Error interrupt for queue 12
- description: Completion interrupt for queue 13
- description: Error interrupt for queue 13
- description: Completion interrupt for queue 14
- description: Error interrupt for queue 14
- description: Completion interrupt for queue 15
- description: Error interrupt for queue 15
dma-coherent: true
iommus:
maxItems: 1
required:
- compatible
- reg
- interrupts
- dma-coherent
additionalProperties: false
examples:
- |
bus {
#address-cells = <2>;
#size-cells = <2>;
crypto@400d2000000 {
compatible = "hisilicon,hip07-sec";
reg = <0x400 0xd0000000 0x0 0x10000
0x400 0xd2000000 0x0 0x10000
0x400 0xd2010000 0x0 0x10000
0x400 0xd2020000 0x0 0x10000
0x400 0xd2030000 0x0 0x10000
0x400 0xd2040000 0x0 0x10000
0x400 0xd2050000 0x0 0x10000
0x400 0xd2060000 0x0 0x10000
0x400 0xd2070000 0x0 0x10000
0x400 0xd2080000 0x0 0x10000
0x400 0xd2090000 0x0 0x10000
0x400 0xd20a0000 0x0 0x10000
0x400 0xd20b0000 0x0 0x10000
0x400 0xd20c0000 0x0 0x10000
0x400 0xd20d0000 0x0 0x10000
0x400 0xd20e0000 0x0 0x10000
0x400 0xd20f0000 0x0 0x10000
0x400 0xd2100000 0x0 0x10000>;
interrupts = <576 4>,
<577 1>, <578 4>,
<579 1>, <580 4>,
<581 1>, <582 4>,
<583 1>, <584 4>,
<585 1>, <586 4>,
<587 1>, <588 4>,
<589 1>, <590 4>,
<591 1>, <592 4>,
<593 1>, <594 4>,
<595 1>, <596 4>,
<597 1>, <598 4>,
<599 1>, <600 4>,
<601 1>, <602 4>,
<603 1>, <604 4>,
<605 1>, <606 4>,
<607 1>, <608 4>;
dma-coherent;
iommus = <&p1_smmu_alg_a 0x600>;
};
};

View File

@ -1,67 +0,0 @@
* Hisilicon hip07 Security Accelerator (SEC)
Required properties:
- compatible: Must contain one of
- "hisilicon,hip06-sec"
- "hisilicon,hip07-sec"
- reg: Memory addresses and lengths of the memory regions through which
this device is controlled.
Region 0 has registers to control the backend processing engines.
Region 1 has registers for functionality common to all queues.
Regions 2-18 have registers for the 16 individual queues which are isolated
both in hardware and within the driver.
- interrupts: Interrupt specifiers.
Refer to interrupt-controller/interrupts.txt for generic interrupt client node
bindings.
Interrupt 0 is for the SEC unit error queue.
Interrupt 2N + 1 is the completion interrupt for queue N.
Interrupt 2N + 2 is the error interrupt for queue N.
- dma-coherent: The driver assumes coherent dma is possible.
Optional properties:
- iommus: The SEC units are behind smmu-v3 iommus.
Refer to iommu/arm,smmu-v3.txt for more information.
Example:
p1_sec_a: crypto@400d2000000 {
compatible = "hisilicon,hip07-sec";
reg = <0x400 0xd0000000 0x0 0x10000
0x400 0xd2000000 0x0 0x10000
0x400 0xd2010000 0x0 0x10000
0x400 0xd2020000 0x0 0x10000
0x400 0xd2030000 0x0 0x10000
0x400 0xd2040000 0x0 0x10000
0x400 0xd2050000 0x0 0x10000
0x400 0xd2060000 0x0 0x10000
0x400 0xd2070000 0x0 0x10000
0x400 0xd2080000 0x0 0x10000
0x400 0xd2090000 0x0 0x10000
0x400 0xd20a0000 0x0 0x10000
0x400 0xd20b0000 0x0 0x10000
0x400 0xd20c0000 0x0 0x10000
0x400 0xd20d0000 0x0 0x10000
0x400 0xd20e0000 0x0 0x10000
0x400 0xd20f0000 0x0 0x10000
0x400 0xd2100000 0x0 0x10000>;
interrupt-parent = <&p1_mbigen_sec_a>;
iommus = <&p1_smmu_alg_a 0x600>;
dma-coherent;
interrupts = <576 4>,
<577 1>, <578 4>,
<579 1>, <580 4>,
<581 1>, <582 4>,
<583 1>, <584 4>,
<585 1>, <586 4>,
<587 1>, <588 4>,
<589 1>, <590 4>,
<591 1>, <592 4>,
<593 1>, <594 4>,
<595 1>, <596 4>,
<597 1>, <598 4>,
<599 1>, <600 4>,
<601 1>, <602 4>,
<603 1>, <604 4>,
<605 1>, <606 4>,
<607 1>, <608 4>;
};

View File

@ -0,0 +1,69 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/img,hash-accelerator.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Imagination Technologies hardware hash accelerator
maintainers:
- James Hartley <james.hartley@imgtec.com>
description:
The hash accelerator provides hardware hashing acceleration for
SHA1, SHA224, SHA256 and MD5 hashes.
properties:
compatible:
const: img,hash-accelerator
reg:
items:
- description: Register base address and size
- description: DMA port specifier
interrupts:
maxItems: 1
dmas:
maxItems: 1
dma-names:
items:
- const: tx
clocks:
items:
- description: System clock for hash block registers
- description: Hash clock for data path
clock-names:
items:
- const: sys
- const: hash
additionalProperties: false
required:
- compatible
- reg
- interrupts
- dmas
- dma-names
- clocks
- clock-names
examples:
- |
#include <dt-bindings/interrupt-controller/mips-gic.h>
#include <dt-bindings/clock/pistachio-clk.h>
hash@18149600 {
compatible = "img,hash-accelerator";
reg = <0x18149600 0x100>, <0x18101100 0x4>;
interrupts = <GIC_SHARED 59 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&dma 8 0xffffffff 0>;
dma-names = "tx";
clocks = <&cr_periph SYS_CLK_HASH>, <&clk_periph PERIPH_CLK_ROM>;
clock-names = "sys", "hash";
};

View File

@ -1,27 +0,0 @@
Imagination Technologies hardware hash accelerator
The hash accelerator provides hardware hashing acceleration for
SHA1, SHA224, SHA256 and MD5 hashes
Required properties:
- compatible : "img,hash-accelerator"
- reg : Offset and length of the register set for the module, and the DMA port
- interrupts : The designated IRQ line for the hashing module.
- dmas : DMA specifier as per Documentation/devicetree/bindings/dma/dma.txt
- dma-names : Should be "tx"
- clocks : Clock specifiers
- clock-names : "sys" Used to clock the hash block registers
"hash" Used to clock data through the accelerator
Example:
hash: hash@18149600 {
compatible = "img,hash-accelerator";
reg = <0x18149600 0x100>, <0x18101100 0x4>;
interrupts = <GIC_SHARED 59 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&dma 8 0xffffffff 0>;
dma-names = "tx";
clocks = <&cr_periph SYS_CLK_HASH>, <&clk_periph PERIPH_CLK_ROM>;
clock-names = "sys", "hash";
};

View File

@ -0,0 +1,133 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/crypto/marvell,orion-crypto.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Marvell Cryptographic Engines And Security Accelerator
maintainers:
- Andrew Lunn <andrew@lunn.ch>
- Boris Brezillon <bbrezillon@kernel.org>
description: |
Marvell Cryptographic Engines And Security Accelerator
properties:
compatible:
enum:
- marvell,armada-370-crypto
- marvell,armada-xp-crypto
- marvell,armada-375-crypto
- marvell,armada-38x-crypto
- marvell,dove-crypto
- marvell,kirkwood-crypto
- marvell,orion-crypto
reg:
minItems: 1
items:
- description: Registers region
- description: SRAM region
deprecated: true
reg-names:
minItems: 1
items:
- const: regs
- const: sram
deprecated: true
interrupts:
description: One interrupt for each CESA engine
minItems: 1
maxItems: 2
clocks:
description: One or two clocks for each CESA engine
minItems: 1
maxItems: 4
clock-names:
minItems: 1
items:
- const: cesa0
- const: cesa1
- const: cesaz0
- const: cesaz1
marvell,crypto-srams:
description: Phandle(s) to crypto SRAM.
$ref: /schemas/types.yaml#/definitions/phandle-array
minItems: 1
maxItems: 2
items:
maxItems: 1
marvell,crypto-sram-size:
description: SRAM size reserved for crypto operations.
$ref: /schemas/types.yaml#/definitions/uint32
default: 0x800
required:
- compatible
- reg
- reg-names
- interrupts
- marvell,crypto-srams
allOf:
- if:
not:
properties:
compatible:
enum:
- marvell,kirkwood-crypto
- marvell,orion-crypto
then:
required:
- clocks
- if:
properties:
compatible:
contains:
enum:
- marvell,armada-370-crypto
- marvell,armada-375-crypto
- marvell,armada-38x-crypto
- marvell,armada-xp-crypto
then:
required:
- clock-names
- if:
properties:
compatible:
contains:
enum:
- marvell,armada-375-crypto
- marvell,armada-38x-crypto
then:
properties:
clocks:
minItems: 4
clock-names:
minItems: 4
else:
properties:
clocks:
maxItems: 2
clock-names:
maxItems: 2
additionalProperties: false
examples:
- |
crypto@30000 {
compatible = "marvell,orion-crypto";
reg = <0x30000 0x10000>;
reg-names = "regs";
interrupts = <22>;
marvell,crypto-srams = <&crypto_sram>;
marvell,crypto-sram-size = <0x600>;
};

View File

@ -1,44 +0,0 @@
Marvell Cryptographic Engines And Security Accelerator
Required properties:
- compatible: should be one of the following string
"marvell,orion-crypto"
"marvell,kirkwood-crypto"
"marvell,dove-crypto"
"marvell,armada-370-crypto"
"marvell,armada-xp-crypto"
"marvell,armada-375-crypto"
"marvell,armada-38x-crypto"
- reg: base physical address of the engine and length of memory mapped
region. Can also contain an entry for the SRAM attached to the CESA,
but this representation is deprecated and marvell,crypto-srams should
be used instead
- reg-names: "regs". Can contain an "sram" entry, but this representation
is deprecated and marvell,crypto-srams should be used instead
- interrupts: interrupt number
- clocks: reference to the crypto engines clocks. This property is not
required for orion and kirkwood platforms
- clock-names: "cesaX" and "cesazX", X should be replaced by the crypto engine
id.
This property is not required for the orion and kirkwoord
platforms.
"cesazX" clocks are not required on armada-370 platforms
- marvell,crypto-srams: phandle to crypto SRAM definitions
Optional properties:
- marvell,crypto-sram-size: SRAM size reserved for crypto operations, if not
specified the whole SRAM is used (2KB)
Examples:
crypto@90000 {
compatible = "marvell,armada-xp-crypto";
reg = <0x90000 0x10000>;
reg-names = "regs";
interrupts = <48>, <49>;
clocks = <&gateclk 23>, <&gateclk 23>;
clock-names = "cesa0", "cesa1";
marvell,crypto-srams = <&crypto_sram0>, <&crypto_sram1>;
marvell,crypto-sram-size = <0x600>;
};

View File

@ -1,25 +0,0 @@
MediaTek cryptographic accelerators
Required properties:
- compatible: Should be "mediatek,eip97-crypto"
- reg: Address and length of the register set for the device
- interrupts: Should contain the five crypto engines interrupts in numeric
order. These are global system and four descriptor rings.
- clocks: the clock used by the core
- clock-names: Must contain "cryp".
- power-domains: Must contain a reference to the PM domain.
Example:
crypto: crypto@1b240000 {
compatible = "mediatek,eip97-crypto";
reg = <0 0x1b240000 0 0x20000>;
interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_LOW>,
<GIC_SPI 83 IRQ_TYPE_LEVEL_LOW>,
<GIC_SPI 84 IRQ_TYPE_LEVEL_LOW>,
<GIC_SPI 91 IRQ_TYPE_LEVEL_LOW>,
<GIC_SPI 97 IRQ_TYPE_LEVEL_LOW>;
clocks = <&ethsys CLK_ETHSYS_CRYPTO>;
clock-names = "cryp";
power-domains = <&scpsys MT2701_POWER_DOMAIN_ETH>;
};

View File

@ -1,32 +0,0 @@
Marvell Cryptographic Engines And Security Accelerator
Required properties:
- compatible: should be one of the following string
"marvell,orion-crypto"
"marvell,kirkwood-crypto"
"marvell,dove-crypto"
- reg: base physical address of the engine and length of memory mapped
region. Can also contain an entry for the SRAM attached to the CESA,
but this representation is deprecated and marvell,crypto-srams should
be used instead
- reg-names: "regs". Can contain an "sram" entry, but this representation
is deprecated and marvell,crypto-srams should be used instead
- interrupts: interrupt number
- clocks: reference to the crypto engines clocks. This property is only
required for Dove platforms
- marvell,crypto-srams: phandle to crypto SRAM definitions
Optional properties:
- marvell,crypto-sram-size: SRAM size reserved for crypto operations, if not
specified the whole SRAM is used (2KB)
Examples:
crypto@30000 {
compatible = "marvell,orion-crypto";
reg = <0x30000 0x10000>;
reg-names = "regs";
interrupts = <22>;
marvell,crypto-srams = <&crypto_sram>;
marvell,crypto-sram-size = <0x600>;
};

View File

@ -45,6 +45,7 @@ properties:
- items: - items:
- enum: - enum:
- qcom,qcs615-qce
- qcom,qcs8300-qce - qcom,qcs8300-qce
- qcom,sa8775p-qce - qcom,sa8775p-qce
- qcom,sc7280-qce - qcom,sc7280-qce

View File

@ -4,9 +4,9 @@
$id: http://devicetree.org/schemas/rng/rockchip,rk3588-rng.yaml# $id: http://devicetree.org/schemas/rng/rockchip,rk3588-rng.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Rockchip RK3588 TRNG title: Rockchip RK3576/RK3588 TRNG
description: True Random Number Generator on Rockchip RK3588 SoC description: True Random Number Generator on Rockchip RK3576/RK3588 SoCs
maintainers: maintainers:
- Nicolas Frattaroli <nicolas.frattaroli@collabora.com> - Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
@ -14,6 +14,7 @@ maintainers:
properties: properties:
compatible: compatible:
enum: enum:
- rockchip,rk3576-rng
- rockchip,rk3588-rng - rockchip,rk3588-rng
reg: reg:

View File

@ -6299,6 +6299,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6.git
F: Documentation/crypto/ F: Documentation/crypto/
F: Documentation/devicetree/bindings/crypto/ F: Documentation/devicetree/bindings/crypto/
F: arch/*/crypto/ F: arch/*/crypto/
F: arch/*/lib/crypto/
F: crypto/ F: crypto/
F: drivers/crypto/ F: drivers/crypto/
F: include/crypto/ F: include/crypto/
@ -14307,9 +14308,8 @@ F: drivers/gpu/drm/armada/
F: include/uapi/drm/armada_drm.h F: include/uapi/drm/armada_drm.h
MARVELL CRYPTO DRIVER MARVELL CRYPTO DRIVER
M: Boris Brezillon <bbrezillon@kernel.org>
M: Arnaud Ebalard <arno@natisbad.org>
M: Srujana Challa <schalla@marvell.com> M: Srujana Challa <schalla@marvell.com>
M: Bharat Bhushan <bbhushan2@marvell.com>
L: linux-crypto@vger.kernel.org L: linux-crypto@vger.kernel.org
S: Maintained S: Maintained
F: drivers/crypto/marvell/ F: drivers/crypto/marvell/

View File

@ -349,7 +349,7 @@ CONFIG_NLS_ASCII=y
CONFIG_NLS_ISO8859_1=y CONFIG_NLS_ISO8859_1=y
CONFIG_NLS_UTF8=y CONFIG_NLS_UTF8=y
CONFIG_CRYPTO_USER=m CONFIG_CRYPTO_USER=m
CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_BENCHMARK=m
CONFIG_CRYPTO_DH=m CONFIG_CRYPTO_DH=m
CONFIG_CRYPTO_LRW=m CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_XTS=m CONFIG_CRYPTO_XTS=m
@ -364,7 +364,6 @@ CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m CONFIG_CRYPTO_USER_API_RNG=m
CONFIG_CRYPTO_USER_API_AEAD=m CONFIG_CRYPTO_USER_API_AEAD=m
CONFIG_CRYPTO_SHA1_ARM_NEON=m CONFIG_CRYPTO_SHA1_ARM_NEON=m
CONFIG_CRYPTO_SHA256_ARM=m
CONFIG_CRYPTO_SHA512_ARM=m CONFIG_CRYPTO_SHA512_ARM=m
CONFIG_CRYPTO_AES_ARM_BS=m CONFIG_CRYPTO_AES_ARM_BS=m
CONFIG_CRYPTO_CHACHA20_NEON=m CONFIG_CRYPTO_CHACHA20_NEON=m

View File

@ -93,15 +93,13 @@ CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y CONFIG_NLS_ISO8859_1=y
CONFIG_NLS_UTF8=y CONFIG_NLS_UTF8=y
CONFIG_KEYS=y CONFIG_KEYS=y
CONFIG_CRYPTO_MANAGER=y CONFIG_CRYPTO_SELFTESTS=y
# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
# CONFIG_CRYPTO_ECHAINIV is not set # CONFIG_CRYPTO_ECHAINIV is not set
CONFIG_CRYPTO_AES=y CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_SEQIV=m CONFIG_CRYPTO_SEQIV=m
CONFIG_CRYPTO_GHASH_ARM_CE=m CONFIG_CRYPTO_GHASH_ARM_CE=m
CONFIG_CRYPTO_SHA1_ARM_NEON=m CONFIG_CRYPTO_SHA1_ARM_NEON=m
CONFIG_CRYPTO_SHA1_ARM_CE=m CONFIG_CRYPTO_SHA1_ARM_CE=m
CONFIG_CRYPTO_SHA2_ARM_CE=m
CONFIG_CRYPTO_SHA512_ARM=m CONFIG_CRYPTO_SHA512_ARM=m
CONFIG_CRYPTO_AES_ARM=m CONFIG_CRYPTO_AES_ARM=m
CONFIG_CRYPTO_AES_ARM_BS=m CONFIG_CRYPTO_AES_ARM_BS=m

View File

@ -1301,7 +1301,6 @@ CONFIG_CRYPTO_USER_API_AEAD=m
CONFIG_CRYPTO_GHASH_ARM_CE=m CONFIG_CRYPTO_GHASH_ARM_CE=m
CONFIG_CRYPTO_SHA1_ARM_NEON=m CONFIG_CRYPTO_SHA1_ARM_NEON=m
CONFIG_CRYPTO_SHA1_ARM_CE=m CONFIG_CRYPTO_SHA1_ARM_CE=m
CONFIG_CRYPTO_SHA2_ARM_CE=m
CONFIG_CRYPTO_SHA512_ARM=m CONFIG_CRYPTO_SHA512_ARM=m
CONFIG_CRYPTO_AES_ARM=m CONFIG_CRYPTO_AES_ARM=m
CONFIG_CRYPTO_AES_ARM_BS=m CONFIG_CRYPTO_AES_ARM_BS=m

View File

@ -697,7 +697,6 @@ CONFIG_SECURITY=y
CONFIG_CRYPTO_MICHAEL_MIC=y CONFIG_CRYPTO_MICHAEL_MIC=y
CONFIG_CRYPTO_GHASH_ARM_CE=m CONFIG_CRYPTO_GHASH_ARM_CE=m
CONFIG_CRYPTO_SHA1_ARM_NEON=m CONFIG_CRYPTO_SHA1_ARM_NEON=m
CONFIG_CRYPTO_SHA256_ARM=m
CONFIG_CRYPTO_SHA512_ARM=m CONFIG_CRYPTO_SHA512_ARM=m
CONFIG_CRYPTO_AES_ARM=m CONFIG_CRYPTO_AES_ARM=m
CONFIG_CRYPTO_AES_ARM_BS=m CONFIG_CRYPTO_AES_ARM_BS=m

View File

@ -636,10 +636,9 @@ CONFIG_NLS_ISO8859_15=m
CONFIG_NLS_UTF8=m CONFIG_NLS_UTF8=m
CONFIG_TIMER_STATS=y CONFIG_TIMER_STATS=y
CONFIG_SECURITY=y CONFIG_SECURITY=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_CRYPTD=m CONFIG_CRYPTO_CRYPTD=m
CONFIG_CRYPTO_AUTHENC=m CONFIG_CRYPTO_AUTHENC=m
CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_BENCHMARK=m
CONFIG_CRYPTO_BLOWFISH=m CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAST5=m CONFIG_CRYPTO_CAST5=m
CONFIG_CRYPTO_CAST6=m CONFIG_CRYPTO_CAST6=m
@ -660,7 +659,6 @@ CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_DEFLATE=y
CONFIG_CRYPTO_LZO=y CONFIG_CRYPTO_LZO=y
CONFIG_CRYPTO_SHA1_ARM=m CONFIG_CRYPTO_SHA1_ARM=m
CONFIG_CRYPTO_SHA256_ARM=m
CONFIG_CRYPTO_SHA512_ARM=m CONFIG_CRYPTO_SHA512_ARM=m
CONFIG_CRYPTO_AES_ARM=m CONFIG_CRYPTO_AES_ARM=m
CONFIG_FONTS=y CONFIG_FONTS=y

View File

@ -215,7 +215,7 @@ CONFIG_NLS_ISO8859_1=y
CONFIG_NLS_UTF8=y CONFIG_NLS_UTF8=y
CONFIG_DEBUG_KERNEL=y CONFIG_DEBUG_KERNEL=y
CONFIG_CRYPTO_NULL=m CONFIG_CRYPTO_NULL=m
CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_BENCHMARK=m
CONFIG_CRYPTO_ECB=m CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_SHA256=m CONFIG_CRYPTO_SHA256=m
CONFIG_CRYPTO_AES=m CONFIG_CRYPTO_AES=m

View File

@ -46,30 +46,6 @@ config CRYPTO_NHPOLY1305_NEON
Architecture: arm using: Architecture: arm using:
- NEON (Advanced SIMD) extensions - NEON (Advanced SIMD) extensions
config CRYPTO_POLY1305_ARM
tristate
select CRYPTO_HASH
select CRYPTO_ARCH_HAVE_LIB_POLY1305
default CRYPTO_LIB_POLY1305_INTERNAL
help
Poly1305 authenticator algorithm (RFC7539)
Architecture: arm optionally using
- NEON (Advanced SIMD) extensions
config CRYPTO_BLAKE2S_ARM
bool "Hash functions: BLAKE2s"
select CRYPTO_ARCH_HAVE_LIB_BLAKE2S
help
BLAKE2s cryptographic hash function (RFC 7693)
Architecture: arm
This is faster than the generic implementations of BLAKE2s and
BLAKE2b, but slower than the NEON implementation of BLAKE2b.
There is no NEON implementation of BLAKE2s, since NEON doesn't
really help with it.
config CRYPTO_BLAKE2B_NEON config CRYPTO_BLAKE2B_NEON
tristate "Hash functions: BLAKE2b (NEON)" tristate "Hash functions: BLAKE2b (NEON)"
depends on KERNEL_MODE_NEON depends on KERNEL_MODE_NEON
@ -117,27 +93,6 @@ config CRYPTO_SHA1_ARM_CE
Architecture: arm using ARMv8 Crypto Extensions Architecture: arm using ARMv8 Crypto Extensions
config CRYPTO_SHA2_ARM_CE
tristate "Hash functions: SHA-224 and SHA-256 (ARMv8 Crypto Extensions)"
depends on KERNEL_MODE_NEON
select CRYPTO_SHA256_ARM
select CRYPTO_HASH
help
SHA-224 and SHA-256 secure hash algorithms (FIPS 180)
Architecture: arm using
- ARMv8 Crypto Extensions
config CRYPTO_SHA256_ARM
tristate "Hash functions: SHA-224 and SHA-256 (NEON)"
select CRYPTO_HASH
depends on !CPU_V7M
help
SHA-224 and SHA-256 secure hash algorithms (FIPS 180)
Architecture: arm using
- NEON (Advanced SIMD) extensions
config CRYPTO_SHA512_ARM config CRYPTO_SHA512_ARM
tristate "Hash functions: SHA-384 and SHA-512 (NEON)" tristate "Hash functions: SHA-384 and SHA-512 (NEON)"
select CRYPTO_HASH select CRYPTO_HASH
@ -172,7 +127,6 @@ config CRYPTO_AES_ARM_BS
select CRYPTO_AES_ARM select CRYPTO_AES_ARM
select CRYPTO_SKCIPHER select CRYPTO_SKCIPHER
select CRYPTO_LIB_AES select CRYPTO_LIB_AES
select CRYPTO_SIMD
help help
Length-preserving ciphers: AES cipher algorithms (FIPS-197) Length-preserving ciphers: AES cipher algorithms (FIPS-197)
with block cipher modes: with block cipher modes:
@ -200,7 +154,6 @@ config CRYPTO_AES_ARM_CE
depends on KERNEL_MODE_NEON depends on KERNEL_MODE_NEON
select CRYPTO_SKCIPHER select CRYPTO_SKCIPHER
select CRYPTO_LIB_AES select CRYPTO_LIB_AES
select CRYPTO_SIMD
help help
Length-preserving ciphers: AES cipher algorithms (FIPS-197) Length-preserving ciphers: AES cipher algorithms (FIPS-197)
with block cipher modes: with block cipher modes:
@ -214,17 +167,5 @@ config CRYPTO_AES_ARM_CE
Architecture: arm using: Architecture: arm using:
- ARMv8 Crypto Extensions - ARMv8 Crypto Extensions
config CRYPTO_CHACHA20_NEON
tristate
select CRYPTO_SKCIPHER
select CRYPTO_ARCH_HAVE_LIB_CHACHA
default CRYPTO_LIB_CHACHA_INTERNAL
help
Length-preserving ciphers: ChaCha20, XChaCha20, and XChaCha12
stream cipher algorithms
Architecture: arm using:
- NEON (Advanced SIMD) extensions
endmenu endmenu

View File

@ -7,37 +7,25 @@ obj-$(CONFIG_CRYPTO_AES_ARM) += aes-arm.o
obj-$(CONFIG_CRYPTO_AES_ARM_BS) += aes-arm-bs.o obj-$(CONFIG_CRYPTO_AES_ARM_BS) += aes-arm-bs.o
obj-$(CONFIG_CRYPTO_SHA1_ARM) += sha1-arm.o obj-$(CONFIG_CRYPTO_SHA1_ARM) += sha1-arm.o
obj-$(CONFIG_CRYPTO_SHA1_ARM_NEON) += sha1-arm-neon.o obj-$(CONFIG_CRYPTO_SHA1_ARM_NEON) += sha1-arm-neon.o
obj-$(CONFIG_CRYPTO_SHA256_ARM) += sha256-arm.o
obj-$(CONFIG_CRYPTO_SHA512_ARM) += sha512-arm.o obj-$(CONFIG_CRYPTO_SHA512_ARM) += sha512-arm.o
obj-$(CONFIG_CRYPTO_BLAKE2S_ARM) += libblake2s-arm.o
obj-$(CONFIG_CRYPTO_BLAKE2B_NEON) += blake2b-neon.o obj-$(CONFIG_CRYPTO_BLAKE2B_NEON) += blake2b-neon.o
obj-$(CONFIG_CRYPTO_CHACHA20_NEON) += chacha-neon.o
obj-$(CONFIG_CRYPTO_POLY1305_ARM) += poly1305-arm.o
obj-$(CONFIG_CRYPTO_NHPOLY1305_NEON) += nhpoly1305-neon.o obj-$(CONFIG_CRYPTO_NHPOLY1305_NEON) += nhpoly1305-neon.o
obj-$(CONFIG_CRYPTO_CURVE25519_NEON) += curve25519-neon.o obj-$(CONFIG_CRYPTO_CURVE25519_NEON) += curve25519-neon.o
obj-$(CONFIG_CRYPTO_AES_ARM_CE) += aes-arm-ce.o obj-$(CONFIG_CRYPTO_AES_ARM_CE) += aes-arm-ce.o
obj-$(CONFIG_CRYPTO_SHA1_ARM_CE) += sha1-arm-ce.o obj-$(CONFIG_CRYPTO_SHA1_ARM_CE) += sha1-arm-ce.o
obj-$(CONFIG_CRYPTO_SHA2_ARM_CE) += sha2-arm-ce.o
obj-$(CONFIG_CRYPTO_GHASH_ARM_CE) += ghash-arm-ce.o obj-$(CONFIG_CRYPTO_GHASH_ARM_CE) += ghash-arm-ce.o
aes-arm-y := aes-cipher-core.o aes-cipher-glue.o aes-arm-y := aes-cipher-core.o aes-cipher-glue.o
aes-arm-bs-y := aes-neonbs-core.o aes-neonbs-glue.o aes-arm-bs-y := aes-neonbs-core.o aes-neonbs-glue.o
sha1-arm-y := sha1-armv4-large.o sha1_glue.o sha1-arm-y := sha1-armv4-large.o sha1_glue.o
sha1-arm-neon-y := sha1-armv7-neon.o sha1_neon_glue.o sha1-arm-neon-y := sha1-armv7-neon.o sha1_neon_glue.o
sha256-arm-neon-$(CONFIG_KERNEL_MODE_NEON) := sha256_neon_glue.o
sha256-arm-y := sha256-core.o sha256_glue.o $(sha256-arm-neon-y)
sha512-arm-neon-$(CONFIG_KERNEL_MODE_NEON) := sha512-neon-glue.o sha512-arm-neon-$(CONFIG_KERNEL_MODE_NEON) := sha512-neon-glue.o
sha512-arm-y := sha512-core.o sha512-glue.o $(sha512-arm-neon-y) sha512-arm-y := sha512-core.o sha512-glue.o $(sha512-arm-neon-y)
libblake2s-arm-y:= blake2s-core.o blake2s-glue.o
blake2b-neon-y := blake2b-neon-core.o blake2b-neon-glue.o blake2b-neon-y := blake2b-neon-core.o blake2b-neon-glue.o
sha1-arm-ce-y := sha1-ce-core.o sha1-ce-glue.o sha1-arm-ce-y := sha1-ce-core.o sha1-ce-glue.o
sha2-arm-ce-y := sha2-ce-core.o sha2-ce-glue.o
aes-arm-ce-y := aes-ce-core.o aes-ce-glue.o aes-arm-ce-y := aes-ce-core.o aes-ce-glue.o
ghash-arm-ce-y := ghash-ce-core.o ghash-ce-glue.o ghash-arm-ce-y := ghash-ce-core.o ghash-ce-glue.o
chacha-neon-y := chacha-scalar-core.o chacha-glue.o
chacha-neon-$(CONFIG_KERNEL_MODE_NEON) += chacha-neon-core.o
poly1305-arm-y := poly1305-core.o poly1305-glue.o
nhpoly1305-neon-y := nh-neon-core.o nhpoly1305-neon-glue.o nhpoly1305-neon-y := nh-neon-core.o nhpoly1305-neon-glue.o
curve25519-neon-y := curve25519-core.o curve25519-glue.o curve25519-neon-y := curve25519-core.o curve25519-glue.o
@ -47,14 +35,8 @@ quiet_cmd_perl = PERL $@
$(obj)/%-core.S: $(src)/%-armv4.pl $(obj)/%-core.S: $(src)/%-armv4.pl
$(call cmd,perl) $(call cmd,perl)
clean-files += poly1305-core.S sha256-core.S sha512-core.S clean-files += sha512-core.S
aflags-thumb2-$(CONFIG_THUMB2_KERNEL) := -U__thumb2__ -D__thumb2__=1 aflags-thumb2-$(CONFIG_THUMB2_KERNEL) := -U__thumb2__ -D__thumb2__=1
AFLAGS_sha256-core.o += $(aflags-thumb2-y)
AFLAGS_sha512-core.o += $(aflags-thumb2-y) AFLAGS_sha512-core.o += $(aflags-thumb2-y)
# massage the perlasm code a bit so we only get the NEON routine if we need it
poly1305-aflags-$(CONFIG_CPU_V7) := -U__LINUX_ARM_ARCH__ -D__LINUX_ARM_ARCH__=5
poly1305-aflags-$(CONFIG_KERNEL_MODE_NEON) := -U__LINUX_ARM_ARCH__ -D__LINUX_ARM_ARCH__=7
AFLAGS_poly1305-core.o += $(poly1305-aflags-y) $(aflags-thumb2-y)

View File

@ -10,8 +10,6 @@
#include <asm/simd.h> #include <asm/simd.h>
#include <linux/unaligned.h> #include <linux/unaligned.h>
#include <crypto/aes.h> #include <crypto/aes.h>
#include <crypto/ctr.h>
#include <crypto/internal/simd.h>
#include <crypto/internal/skcipher.h> #include <crypto/internal/skcipher.h>
#include <crypto/scatterwalk.h> #include <crypto/scatterwalk.h>
#include <linux/cpufeature.h> #include <linux/cpufeature.h>
@ -418,29 +416,6 @@ static int ctr_encrypt(struct skcipher_request *req)
return err; return err;
} }
static void ctr_encrypt_one(struct crypto_skcipher *tfm, const u8 *src, u8 *dst)
{
struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
unsigned long flags;
/*
* Temporarily disable interrupts to avoid races where
* cachelines are evicted when the CPU is interrupted
* to do something else.
*/
local_irq_save(flags);
aes_encrypt(ctx, dst, src);
local_irq_restore(flags);
}
static int ctr_encrypt_sync(struct skcipher_request *req)
{
if (!crypto_simd_usable())
return crypto_ctr_encrypt_walk(req, ctr_encrypt_one);
return ctr_encrypt(req);
}
static int xts_encrypt(struct skcipher_request *req) static int xts_encrypt(struct skcipher_request *req)
{ {
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
@ -586,10 +561,9 @@ static int xts_decrypt(struct skcipher_request *req)
} }
static struct skcipher_alg aes_algs[] = { { static struct skcipher_alg aes_algs[] = { {
.base.cra_name = "__ecb(aes)", .base.cra_name = "ecb(aes)",
.base.cra_driver_name = "__ecb-aes-ce", .base.cra_driver_name = "ecb-aes-ce",
.base.cra_priority = 300, .base.cra_priority = 300,
.base.cra_flags = CRYPTO_ALG_INTERNAL,
.base.cra_blocksize = AES_BLOCK_SIZE, .base.cra_blocksize = AES_BLOCK_SIZE,
.base.cra_ctxsize = sizeof(struct crypto_aes_ctx), .base.cra_ctxsize = sizeof(struct crypto_aes_ctx),
.base.cra_module = THIS_MODULE, .base.cra_module = THIS_MODULE,
@ -600,10 +574,9 @@ static struct skcipher_alg aes_algs[] = { {
.encrypt = ecb_encrypt, .encrypt = ecb_encrypt,
.decrypt = ecb_decrypt, .decrypt = ecb_decrypt,
}, { }, {
.base.cra_name = "__cbc(aes)", .base.cra_name = "cbc(aes)",
.base.cra_driver_name = "__cbc-aes-ce", .base.cra_driver_name = "cbc-aes-ce",
.base.cra_priority = 300, .base.cra_priority = 300,
.base.cra_flags = CRYPTO_ALG_INTERNAL,
.base.cra_blocksize = AES_BLOCK_SIZE, .base.cra_blocksize = AES_BLOCK_SIZE,
.base.cra_ctxsize = sizeof(struct crypto_aes_ctx), .base.cra_ctxsize = sizeof(struct crypto_aes_ctx),
.base.cra_module = THIS_MODULE, .base.cra_module = THIS_MODULE,
@ -615,10 +588,9 @@ static struct skcipher_alg aes_algs[] = { {
.encrypt = cbc_encrypt, .encrypt = cbc_encrypt,
.decrypt = cbc_decrypt, .decrypt = cbc_decrypt,
}, { }, {
.base.cra_name = "__cts(cbc(aes))", .base.cra_name = "cts(cbc(aes))",
.base.cra_driver_name = "__cts-cbc-aes-ce", .base.cra_driver_name = "cts-cbc-aes-ce",
.base.cra_priority = 300, .base.cra_priority = 300,
.base.cra_flags = CRYPTO_ALG_INTERNAL,
.base.cra_blocksize = AES_BLOCK_SIZE, .base.cra_blocksize = AES_BLOCK_SIZE,
.base.cra_ctxsize = sizeof(struct crypto_aes_ctx), .base.cra_ctxsize = sizeof(struct crypto_aes_ctx),
.base.cra_module = THIS_MODULE, .base.cra_module = THIS_MODULE,
@ -631,10 +603,9 @@ static struct skcipher_alg aes_algs[] = { {
.encrypt = cts_cbc_encrypt, .encrypt = cts_cbc_encrypt,
.decrypt = cts_cbc_decrypt, .decrypt = cts_cbc_decrypt,
}, { }, {
.base.cra_name = "__ctr(aes)", .base.cra_name = "ctr(aes)",
.base.cra_driver_name = "__ctr-aes-ce", .base.cra_driver_name = "ctr-aes-ce",
.base.cra_priority = 300, .base.cra_priority = 300,
.base.cra_flags = CRYPTO_ALG_INTERNAL,
.base.cra_blocksize = 1, .base.cra_blocksize = 1,
.base.cra_ctxsize = sizeof(struct crypto_aes_ctx), .base.cra_ctxsize = sizeof(struct crypto_aes_ctx),
.base.cra_module = THIS_MODULE, .base.cra_module = THIS_MODULE,
@ -647,25 +618,9 @@ static struct skcipher_alg aes_algs[] = { {
.encrypt = ctr_encrypt, .encrypt = ctr_encrypt,
.decrypt = ctr_encrypt, .decrypt = ctr_encrypt,
}, { }, {
.base.cra_name = "ctr(aes)", .base.cra_name = "xts(aes)",
.base.cra_driver_name = "ctr-aes-ce-sync", .base.cra_driver_name = "xts-aes-ce",
.base.cra_priority = 300 - 1,
.base.cra_blocksize = 1,
.base.cra_ctxsize = sizeof(struct crypto_aes_ctx),
.base.cra_module = THIS_MODULE,
.min_keysize = AES_MIN_KEY_SIZE,
.max_keysize = AES_MAX_KEY_SIZE,
.ivsize = AES_BLOCK_SIZE,
.chunksize = AES_BLOCK_SIZE,
.setkey = ce_aes_setkey,
.encrypt = ctr_encrypt_sync,
.decrypt = ctr_encrypt_sync,
}, {
.base.cra_name = "__xts(aes)",
.base.cra_driver_name = "__xts-aes-ce",
.base.cra_priority = 300, .base.cra_priority = 300,
.base.cra_flags = CRYPTO_ALG_INTERNAL,
.base.cra_blocksize = AES_BLOCK_SIZE, .base.cra_blocksize = AES_BLOCK_SIZE,
.base.cra_ctxsize = sizeof(struct crypto_aes_xts_ctx), .base.cra_ctxsize = sizeof(struct crypto_aes_xts_ctx),
.base.cra_module = THIS_MODULE, .base.cra_module = THIS_MODULE,
@ -679,51 +634,14 @@ static struct skcipher_alg aes_algs[] = { {
.decrypt = xts_decrypt, .decrypt = xts_decrypt,
} }; } };
static struct simd_skcipher_alg *aes_simd_algs[ARRAY_SIZE(aes_algs)];
static void aes_exit(void) static void aes_exit(void)
{ {
int i;
for (i = 0; i < ARRAY_SIZE(aes_simd_algs) && aes_simd_algs[i]; i++)
simd_skcipher_free(aes_simd_algs[i]);
crypto_unregister_skciphers(aes_algs, ARRAY_SIZE(aes_algs)); crypto_unregister_skciphers(aes_algs, ARRAY_SIZE(aes_algs));
} }
static int __init aes_init(void) static int __init aes_init(void)
{ {
struct simd_skcipher_alg *simd; return crypto_register_skciphers(aes_algs, ARRAY_SIZE(aes_algs));
const char *basename;
const char *algname;
const char *drvname;
int err;
int i;
err = crypto_register_skciphers(aes_algs, ARRAY_SIZE(aes_algs));
if (err)
return err;
for (i = 0; i < ARRAY_SIZE(aes_algs); i++) {
if (!(aes_algs[i].base.cra_flags & CRYPTO_ALG_INTERNAL))
continue;
algname = aes_algs[i].base.cra_name + 2;
drvname = aes_algs[i].base.cra_driver_name + 2;
basename = aes_algs[i].base.cra_driver_name;
simd = simd_skcipher_create_compat(aes_algs + i, algname, drvname, basename);
err = PTR_ERR(simd);
if (IS_ERR(simd))
goto unregister_simds;
aes_simd_algs[i] = simd;
}
return 0;
unregister_simds:
aes_exit();
return err;
} }
module_cpu_feature_match(AES, aes_init); module_cpu_feature_match(AES, aes_init);

View File

@ -8,8 +8,6 @@
#include <asm/neon.h> #include <asm/neon.h>
#include <asm/simd.h> #include <asm/simd.h>
#include <crypto/aes.h> #include <crypto/aes.h>
#include <crypto/ctr.h>
#include <crypto/internal/simd.h>
#include <crypto/internal/skcipher.h> #include <crypto/internal/skcipher.h>
#include <crypto/scatterwalk.h> #include <crypto/scatterwalk.h>
#include <crypto/xts.h> #include <crypto/xts.h>
@ -59,11 +57,6 @@ struct aesbs_xts_ctx {
struct crypto_aes_ctx tweak_key; struct crypto_aes_ctx tweak_key;
}; };
struct aesbs_ctr_ctx {
struct aesbs_ctx key; /* must be first member */
struct crypto_aes_ctx fallback;
};
static int aesbs_setkey(struct crypto_skcipher *tfm, const u8 *in_key, static int aesbs_setkey(struct crypto_skcipher *tfm, const u8 *in_key,
unsigned int key_len) unsigned int key_len)
{ {
@ -200,25 +193,6 @@ static int cbc_decrypt(struct skcipher_request *req)
return err; return err;
} }
static int aesbs_ctr_setkey_sync(struct crypto_skcipher *tfm, const u8 *in_key,
unsigned int key_len)
{
struct aesbs_ctr_ctx *ctx = crypto_skcipher_ctx(tfm);
int err;
err = aes_expandkey(&ctx->fallback, in_key, key_len);
if (err)
return err;
ctx->key.rounds = 6 + key_len / 4;
kernel_neon_begin();
aesbs_convert_key(ctx->key.rk, ctx->fallback.key_enc, ctx->key.rounds);
kernel_neon_end();
return 0;
}
static int ctr_encrypt(struct skcipher_request *req) static int ctr_encrypt(struct skcipher_request *req)
{ {
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
@ -254,21 +228,6 @@ static int ctr_encrypt(struct skcipher_request *req)
return err; return err;
} }
static void ctr_encrypt_one(struct crypto_skcipher *tfm, const u8 *src, u8 *dst)
{
struct aesbs_ctr_ctx *ctx = crypto_skcipher_ctx(tfm);
__aes_arm_encrypt(ctx->fallback.key_enc, ctx->key.rounds, src, dst);
}
static int ctr_encrypt_sync(struct skcipher_request *req)
{
if (!crypto_simd_usable())
return crypto_ctr_encrypt_walk(req, ctr_encrypt_one);
return ctr_encrypt(req);
}
static int aesbs_xts_setkey(struct crypto_skcipher *tfm, const u8 *in_key, static int aesbs_xts_setkey(struct crypto_skcipher *tfm, const u8 *in_key,
unsigned int key_len) unsigned int key_len)
{ {
@ -374,13 +333,12 @@ static int xts_decrypt(struct skcipher_request *req)
} }
static struct skcipher_alg aes_algs[] = { { static struct skcipher_alg aes_algs[] = { {
.base.cra_name = "__ecb(aes)", .base.cra_name = "ecb(aes)",
.base.cra_driver_name = "__ecb-aes-neonbs", .base.cra_driver_name = "ecb-aes-neonbs",
.base.cra_priority = 250, .base.cra_priority = 250,
.base.cra_blocksize = AES_BLOCK_SIZE, .base.cra_blocksize = AES_BLOCK_SIZE,
.base.cra_ctxsize = sizeof(struct aesbs_ctx), .base.cra_ctxsize = sizeof(struct aesbs_ctx),
.base.cra_module = THIS_MODULE, .base.cra_module = THIS_MODULE,
.base.cra_flags = CRYPTO_ALG_INTERNAL,
.min_keysize = AES_MIN_KEY_SIZE, .min_keysize = AES_MIN_KEY_SIZE,
.max_keysize = AES_MAX_KEY_SIZE, .max_keysize = AES_MAX_KEY_SIZE,
@ -389,13 +347,12 @@ static struct skcipher_alg aes_algs[] = { {
.encrypt = ecb_encrypt, .encrypt = ecb_encrypt,
.decrypt = ecb_decrypt, .decrypt = ecb_decrypt,
}, { }, {
.base.cra_name = "__cbc(aes)", .base.cra_name = "cbc(aes)",
.base.cra_driver_name = "__cbc-aes-neonbs", .base.cra_driver_name = "cbc-aes-neonbs",
.base.cra_priority = 250, .base.cra_priority = 250,
.base.cra_blocksize = AES_BLOCK_SIZE, .base.cra_blocksize = AES_BLOCK_SIZE,
.base.cra_ctxsize = sizeof(struct aesbs_cbc_ctx), .base.cra_ctxsize = sizeof(struct aesbs_cbc_ctx),
.base.cra_module = THIS_MODULE, .base.cra_module = THIS_MODULE,
.base.cra_flags = CRYPTO_ALG_INTERNAL,
.min_keysize = AES_MIN_KEY_SIZE, .min_keysize = AES_MIN_KEY_SIZE,
.max_keysize = AES_MAX_KEY_SIZE, .max_keysize = AES_MAX_KEY_SIZE,
@ -405,13 +362,12 @@ static struct skcipher_alg aes_algs[] = { {
.encrypt = cbc_encrypt, .encrypt = cbc_encrypt,
.decrypt = cbc_decrypt, .decrypt = cbc_decrypt,
}, { }, {
.base.cra_name = "__ctr(aes)", .base.cra_name = "ctr(aes)",
.base.cra_driver_name = "__ctr-aes-neonbs", .base.cra_driver_name = "ctr-aes-neonbs",
.base.cra_priority = 250, .base.cra_priority = 250,
.base.cra_blocksize = 1, .base.cra_blocksize = 1,
.base.cra_ctxsize = sizeof(struct aesbs_ctx), .base.cra_ctxsize = sizeof(struct aesbs_ctx),
.base.cra_module = THIS_MODULE, .base.cra_module = THIS_MODULE,
.base.cra_flags = CRYPTO_ALG_INTERNAL,
.min_keysize = AES_MIN_KEY_SIZE, .min_keysize = AES_MIN_KEY_SIZE,
.max_keysize = AES_MAX_KEY_SIZE, .max_keysize = AES_MAX_KEY_SIZE,
@ -422,29 +378,12 @@ static struct skcipher_alg aes_algs[] = { {
.encrypt = ctr_encrypt, .encrypt = ctr_encrypt,
.decrypt = ctr_encrypt, .decrypt = ctr_encrypt,
}, { }, {
.base.cra_name = "ctr(aes)", .base.cra_name = "xts(aes)",
.base.cra_driver_name = "ctr-aes-neonbs-sync", .base.cra_driver_name = "xts-aes-neonbs",
.base.cra_priority = 250 - 1,
.base.cra_blocksize = 1,
.base.cra_ctxsize = sizeof(struct aesbs_ctr_ctx),
.base.cra_module = THIS_MODULE,
.min_keysize = AES_MIN_KEY_SIZE,
.max_keysize = AES_MAX_KEY_SIZE,
.chunksize = AES_BLOCK_SIZE,
.walksize = 8 * AES_BLOCK_SIZE,
.ivsize = AES_BLOCK_SIZE,
.setkey = aesbs_ctr_setkey_sync,
.encrypt = ctr_encrypt_sync,
.decrypt = ctr_encrypt_sync,
}, {
.base.cra_name = "__xts(aes)",
.base.cra_driver_name = "__xts-aes-neonbs",
.base.cra_priority = 250, .base.cra_priority = 250,
.base.cra_blocksize = AES_BLOCK_SIZE, .base.cra_blocksize = AES_BLOCK_SIZE,
.base.cra_ctxsize = sizeof(struct aesbs_xts_ctx), .base.cra_ctxsize = sizeof(struct aesbs_xts_ctx),
.base.cra_module = THIS_MODULE, .base.cra_module = THIS_MODULE,
.base.cra_flags = CRYPTO_ALG_INTERNAL,
.min_keysize = 2 * AES_MIN_KEY_SIZE, .min_keysize = 2 * AES_MIN_KEY_SIZE,
.max_keysize = 2 * AES_MAX_KEY_SIZE, .max_keysize = 2 * AES_MAX_KEY_SIZE,
@ -455,55 +394,18 @@ static struct skcipher_alg aes_algs[] = { {
.decrypt = xts_decrypt, .decrypt = xts_decrypt,
} }; } };
static struct simd_skcipher_alg *aes_simd_algs[ARRAY_SIZE(aes_algs)];
static void aes_exit(void) static void aes_exit(void)
{ {
int i;
for (i = 0; i < ARRAY_SIZE(aes_simd_algs); i++)
if (aes_simd_algs[i])
simd_skcipher_free(aes_simd_algs[i]);
crypto_unregister_skciphers(aes_algs, ARRAY_SIZE(aes_algs)); crypto_unregister_skciphers(aes_algs, ARRAY_SIZE(aes_algs));
} }
static int __init aes_init(void) static int __init aes_init(void)
{ {
struct simd_skcipher_alg *simd;
const char *basename;
const char *algname;
const char *drvname;
int err;
int i;
if (!(elf_hwcap & HWCAP_NEON)) if (!(elf_hwcap & HWCAP_NEON))
return -ENODEV; return -ENODEV;
err = crypto_register_skciphers(aes_algs, ARRAY_SIZE(aes_algs)); return crypto_register_skciphers(aes_algs, ARRAY_SIZE(aes_algs));
if (err)
return err;
for (i = 0; i < ARRAY_SIZE(aes_algs); i++) {
if (!(aes_algs[i].base.cra_flags & CRYPTO_ALG_INTERNAL))
continue;
algname = aes_algs[i].base.cra_name + 2;
drvname = aes_algs[i].base.cra_driver_name + 2;
basename = aes_algs[i].base.cra_driver_name;
simd = simd_skcipher_create_compat(aes_algs + i, algname, drvname, basename);
err = PTR_ERR(simd);
if (IS_ERR(simd))
goto unregister_simds;
aes_simd_algs[i] = simd;
}
return 0;
unregister_simds:
aes_exit();
return err;
} }
late_initcall(aes_init); module_init(aes_init);
module_exit(aes_exit); module_exit(aes_exit);

View File

@ -7,7 +7,6 @@
#include <crypto/internal/blake2b.h> #include <crypto/internal/blake2b.h>
#include <crypto/internal/hash.h> #include <crypto/internal/hash.h>
#include <crypto/internal/simd.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/sizes.h> #include <linux/sizes.h>
@ -21,11 +20,6 @@ asmlinkage void blake2b_compress_neon(struct blake2b_state *state,
static void blake2b_compress_arch(struct blake2b_state *state, static void blake2b_compress_arch(struct blake2b_state *state,
const u8 *block, size_t nblocks, u32 inc) const u8 *block, size_t nblocks, u32 inc)
{ {
if (!crypto_simd_usable()) {
blake2b_compress_generic(state, block, nblocks, inc);
return;
}
do { do {
const size_t blocks = min_t(size_t, nblocks, const size_t blocks = min_t(size_t, nblocks,
SZ_4K / BLAKE2B_BLOCK_SIZE); SZ_4K / BLAKE2B_BLOCK_SIZE);
@ -42,12 +36,14 @@ static void blake2b_compress_arch(struct blake2b_state *state,
static int crypto_blake2b_update_neon(struct shash_desc *desc, static int crypto_blake2b_update_neon(struct shash_desc *desc,
const u8 *in, unsigned int inlen) const u8 *in, unsigned int inlen)
{ {
return crypto_blake2b_update(desc, in, inlen, blake2b_compress_arch); return crypto_blake2b_update_bo(desc, in, inlen, blake2b_compress_arch);
} }
static int crypto_blake2b_final_neon(struct shash_desc *desc, u8 *out) static int crypto_blake2b_finup_neon(struct shash_desc *desc, const u8 *in,
unsigned int inlen, u8 *out)
{ {
return crypto_blake2b_final(desc, out, blake2b_compress_arch); return crypto_blake2b_finup(desc, in, inlen, out,
blake2b_compress_arch);
} }
#define BLAKE2B_ALG(name, driver_name, digest_size) \ #define BLAKE2B_ALG(name, driver_name, digest_size) \
@ -55,7 +51,9 @@ static int crypto_blake2b_final_neon(struct shash_desc *desc, u8 *out)
.base.cra_name = name, \ .base.cra_name = name, \
.base.cra_driver_name = driver_name, \ .base.cra_driver_name = driver_name, \
.base.cra_priority = 200, \ .base.cra_priority = 200, \
.base.cra_flags = CRYPTO_ALG_OPTIONAL_KEY, \ .base.cra_flags = CRYPTO_ALG_OPTIONAL_KEY | \
CRYPTO_AHASH_ALG_BLOCK_ONLY | \
CRYPTO_AHASH_ALG_FINAL_NONZERO, \
.base.cra_blocksize = BLAKE2B_BLOCK_SIZE, \ .base.cra_blocksize = BLAKE2B_BLOCK_SIZE, \
.base.cra_ctxsize = sizeof(struct blake2b_tfm_ctx), \ .base.cra_ctxsize = sizeof(struct blake2b_tfm_ctx), \
.base.cra_module = THIS_MODULE, \ .base.cra_module = THIS_MODULE, \
@ -63,8 +61,9 @@ static int crypto_blake2b_final_neon(struct shash_desc *desc, u8 *out)
.setkey = crypto_blake2b_setkey, \ .setkey = crypto_blake2b_setkey, \
.init = crypto_blake2b_init, \ .init = crypto_blake2b_init, \
.update = crypto_blake2b_update_neon, \ .update = crypto_blake2b_update_neon, \
.final = crypto_blake2b_final_neon, \ .finup = crypto_blake2b_finup_neon, \
.descsize = sizeof(struct blake2b_state), \ .descsize = sizeof(struct blake2b_state), \
.statesize = BLAKE2B_STATE_SIZE, \
} }
static struct shash_alg blake2b_neon_algs[] = { static struct shash_alg blake2b_neon_algs[] = {

View File

@ -1,352 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* ARM NEON accelerated ChaCha and XChaCha stream ciphers,
* including ChaCha20 (RFC7539)
*
* Copyright (C) 2016-2019 Linaro, Ltd. <ard.biesheuvel@linaro.org>
* Copyright (C) 2015 Martin Willi
*/
#include <crypto/algapi.h>
#include <crypto/internal/chacha.h>
#include <crypto/internal/simd.h>
#include <crypto/internal/skcipher.h>
#include <linux/jump_label.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <asm/cputype.h>
#include <asm/hwcap.h>
#include <asm/neon.h>
#include <asm/simd.h>
asmlinkage void chacha_block_xor_neon(const u32 *state, u8 *dst, const u8 *src,
int nrounds);
asmlinkage void chacha_4block_xor_neon(const u32 *state, u8 *dst, const u8 *src,
int nrounds, unsigned int nbytes);
asmlinkage void hchacha_block_arm(const u32 *state, u32 *out, int nrounds);
asmlinkage void hchacha_block_neon(const u32 *state, u32 *out, int nrounds);
asmlinkage void chacha_doarm(u8 *dst, const u8 *src, unsigned int bytes,
const u32 *state, int nrounds);
static __ro_after_init DEFINE_STATIC_KEY_FALSE(use_neon);
static inline bool neon_usable(void)
{
return static_branch_likely(&use_neon) && crypto_simd_usable();
}
static void chacha_doneon(u32 *state, u8 *dst, const u8 *src,
unsigned int bytes, int nrounds)
{
u8 buf[CHACHA_BLOCK_SIZE];
while (bytes > CHACHA_BLOCK_SIZE) {
unsigned int l = min(bytes, CHACHA_BLOCK_SIZE * 4U);
chacha_4block_xor_neon(state, dst, src, nrounds, l);
bytes -= l;
src += l;
dst += l;
state[12] += DIV_ROUND_UP(l, CHACHA_BLOCK_SIZE);
}
if (bytes) {
const u8 *s = src;
u8 *d = dst;
if (bytes != CHACHA_BLOCK_SIZE)
s = d = memcpy(buf, src, bytes);
chacha_block_xor_neon(state, d, s, nrounds);
if (d != dst)
memcpy(dst, buf, bytes);
state[12]++;
}
}
void hchacha_block_arch(const u32 *state, u32 *stream, int nrounds)
{
if (!IS_ENABLED(CONFIG_KERNEL_MODE_NEON) || !neon_usable()) {
hchacha_block_arm(state, stream, nrounds);
} else {
kernel_neon_begin();
hchacha_block_neon(state, stream, nrounds);
kernel_neon_end();
}
}
EXPORT_SYMBOL(hchacha_block_arch);
void chacha_crypt_arch(u32 *state, u8 *dst, const u8 *src, unsigned int bytes,
int nrounds)
{
if (!IS_ENABLED(CONFIG_KERNEL_MODE_NEON) || !neon_usable() ||
bytes <= CHACHA_BLOCK_SIZE) {
chacha_doarm(dst, src, bytes, state, nrounds);
state[12] += DIV_ROUND_UP(bytes, CHACHA_BLOCK_SIZE);
return;
}
do {
unsigned int todo = min_t(unsigned int, bytes, SZ_4K);
kernel_neon_begin();
chacha_doneon(state, dst, src, todo, nrounds);
kernel_neon_end();
bytes -= todo;
src += todo;
dst += todo;
} while (bytes);
}
EXPORT_SYMBOL(chacha_crypt_arch);
static int chacha_stream_xor(struct skcipher_request *req,
const struct chacha_ctx *ctx, const u8 *iv,
bool neon)
{
struct skcipher_walk walk;
u32 state[16];
int err;
err = skcipher_walk_virt(&walk, req, false);
chacha_init(state, ctx->key, iv);
while (walk.nbytes > 0) {
unsigned int nbytes = walk.nbytes;
if (nbytes < walk.total)
nbytes = round_down(nbytes, walk.stride);
if (!IS_ENABLED(CONFIG_KERNEL_MODE_NEON) || !neon) {
chacha_doarm(walk.dst.virt.addr, walk.src.virt.addr,
nbytes, state, ctx->nrounds);
state[12] += DIV_ROUND_UP(nbytes, CHACHA_BLOCK_SIZE);
} else {
kernel_neon_begin();
chacha_doneon(state, walk.dst.virt.addr,
walk.src.virt.addr, nbytes, ctx->nrounds);
kernel_neon_end();
}
err = skcipher_walk_done(&walk, walk.nbytes - nbytes);
}
return err;
}
static int do_chacha(struct skcipher_request *req, bool neon)
{
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
struct chacha_ctx *ctx = crypto_skcipher_ctx(tfm);
return chacha_stream_xor(req, ctx, req->iv, neon);
}
static int chacha_arm(struct skcipher_request *req)
{
return do_chacha(req, false);
}
static int chacha_neon(struct skcipher_request *req)
{
return do_chacha(req, neon_usable());
}
static int do_xchacha(struct skcipher_request *req, bool neon)
{
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
struct chacha_ctx *ctx = crypto_skcipher_ctx(tfm);
struct chacha_ctx subctx;
u32 state[16];
u8 real_iv[16];
chacha_init(state, ctx->key, req->iv);
if (!IS_ENABLED(CONFIG_KERNEL_MODE_NEON) || !neon) {
hchacha_block_arm(state, subctx.key, ctx->nrounds);
} else {
kernel_neon_begin();
hchacha_block_neon(state, subctx.key, ctx->nrounds);
kernel_neon_end();
}
subctx.nrounds = ctx->nrounds;
memcpy(&real_iv[0], req->iv + 24, 8);
memcpy(&real_iv[8], req->iv + 16, 8);
return chacha_stream_xor(req, &subctx, real_iv, neon);
}
static int xchacha_arm(struct skcipher_request *req)
{
return do_xchacha(req, false);
}
static int xchacha_neon(struct skcipher_request *req)
{
return do_xchacha(req, neon_usable());
}
static struct skcipher_alg arm_algs[] = {
{
.base.cra_name = "chacha20",
.base.cra_driver_name = "chacha20-arm",
.base.cra_priority = 200,
.base.cra_blocksize = 1,
.base.cra_ctxsize = sizeof(struct chacha_ctx),
.base.cra_module = THIS_MODULE,
.min_keysize = CHACHA_KEY_SIZE,
.max_keysize = CHACHA_KEY_SIZE,
.ivsize = CHACHA_IV_SIZE,
.chunksize = CHACHA_BLOCK_SIZE,
.setkey = chacha20_setkey,
.encrypt = chacha_arm,
.decrypt = chacha_arm,
}, {
.base.cra_name = "xchacha20",
.base.cra_driver_name = "xchacha20-arm",
.base.cra_priority = 200,
.base.cra_blocksize = 1,
.base.cra_ctxsize = sizeof(struct chacha_ctx),
.base.cra_module = THIS_MODULE,
.min_keysize = CHACHA_KEY_SIZE,
.max_keysize = CHACHA_KEY_SIZE,
.ivsize = XCHACHA_IV_SIZE,
.chunksize = CHACHA_BLOCK_SIZE,
.setkey = chacha20_setkey,
.encrypt = xchacha_arm,
.decrypt = xchacha_arm,
}, {
.base.cra_name = "xchacha12",
.base.cra_driver_name = "xchacha12-arm",
.base.cra_priority = 200,
.base.cra_blocksize = 1,
.base.cra_ctxsize = sizeof(struct chacha_ctx),
.base.cra_module = THIS_MODULE,
.min_keysize = CHACHA_KEY_SIZE,
.max_keysize = CHACHA_KEY_SIZE,
.ivsize = XCHACHA_IV_SIZE,
.chunksize = CHACHA_BLOCK_SIZE,
.setkey = chacha12_setkey,
.encrypt = xchacha_arm,
.decrypt = xchacha_arm,
},
};
static struct skcipher_alg neon_algs[] = {
{
.base.cra_name = "chacha20",
.base.cra_driver_name = "chacha20-neon",
.base.cra_priority = 300,
.base.cra_blocksize = 1,
.base.cra_ctxsize = sizeof(struct chacha_ctx),
.base.cra_module = THIS_MODULE,
.min_keysize = CHACHA_KEY_SIZE,
.max_keysize = CHACHA_KEY_SIZE,
.ivsize = CHACHA_IV_SIZE,
.chunksize = CHACHA_BLOCK_SIZE,
.walksize = 4 * CHACHA_BLOCK_SIZE,
.setkey = chacha20_setkey,
.encrypt = chacha_neon,
.decrypt = chacha_neon,
}, {
.base.cra_name = "xchacha20",
.base.cra_driver_name = "xchacha20-neon",
.base.cra_priority = 300,
.base.cra_blocksize = 1,
.base.cra_ctxsize = sizeof(struct chacha_ctx),
.base.cra_module = THIS_MODULE,
.min_keysize = CHACHA_KEY_SIZE,
.max_keysize = CHACHA_KEY_SIZE,
.ivsize = XCHACHA_IV_SIZE,
.chunksize = CHACHA_BLOCK_SIZE,
.walksize = 4 * CHACHA_BLOCK_SIZE,
.setkey = chacha20_setkey,
.encrypt = xchacha_neon,
.decrypt = xchacha_neon,
}, {
.base.cra_name = "xchacha12",
.base.cra_driver_name = "xchacha12-neon",
.base.cra_priority = 300,
.base.cra_blocksize = 1,
.base.cra_ctxsize = sizeof(struct chacha_ctx),
.base.cra_module = THIS_MODULE,
.min_keysize = CHACHA_KEY_SIZE,
.max_keysize = CHACHA_KEY_SIZE,
.ivsize = XCHACHA_IV_SIZE,
.chunksize = CHACHA_BLOCK_SIZE,
.walksize = 4 * CHACHA_BLOCK_SIZE,
.setkey = chacha12_setkey,
.encrypt = xchacha_neon,
.decrypt = xchacha_neon,
}
};
static int __init chacha_simd_mod_init(void)
{
int err = 0;
if (IS_REACHABLE(CONFIG_CRYPTO_SKCIPHER)) {
err = crypto_register_skciphers(arm_algs, ARRAY_SIZE(arm_algs));
if (err)
return err;
}
if (IS_ENABLED(CONFIG_KERNEL_MODE_NEON) && (elf_hwcap & HWCAP_NEON)) {
int i;
switch (read_cpuid_part()) {
case ARM_CPU_PART_CORTEX_A7:
case ARM_CPU_PART_CORTEX_A5:
/*
* The Cortex-A7 and Cortex-A5 do not perform well with
* the NEON implementation but do incredibly with the
* scalar one and use less power.
*/
for (i = 0; i < ARRAY_SIZE(neon_algs); i++)
neon_algs[i].base.cra_priority = 0;
break;
default:
static_branch_enable(&use_neon);
}
if (IS_REACHABLE(CONFIG_CRYPTO_SKCIPHER)) {
err = crypto_register_skciphers(neon_algs, ARRAY_SIZE(neon_algs));
if (err)
crypto_unregister_skciphers(arm_algs, ARRAY_SIZE(arm_algs));
}
}
return err;
}
static void __exit chacha_simd_mod_fini(void)
{
if (IS_REACHABLE(CONFIG_CRYPTO_SKCIPHER)) {
crypto_unregister_skciphers(arm_algs, ARRAY_SIZE(arm_algs));
if (IS_ENABLED(CONFIG_KERNEL_MODE_NEON) && (elf_hwcap & HWCAP_NEON))
crypto_unregister_skciphers(neon_algs, ARRAY_SIZE(neon_algs));
}
}
module_init(chacha_simd_mod_init);
module_exit(chacha_simd_mod_fini);
MODULE_DESCRIPTION("ChaCha and XChaCha stream ciphers (scalar and NEON accelerated)");
MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS_CRYPTO("chacha20");
MODULE_ALIAS_CRYPTO("chacha20-arm");
MODULE_ALIAS_CRYPTO("xchacha20");
MODULE_ALIAS_CRYPTO("xchacha20-arm");
MODULE_ALIAS_CRYPTO("xchacha12");
MODULE_ALIAS_CRYPTO("xchacha12-arm");
#ifdef CONFIG_KERNEL_MODE_NEON
MODULE_ALIAS_CRYPTO("chacha20-neon");
MODULE_ALIAS_CRYPTO("xchacha20-neon");
MODULE_ALIAS_CRYPTO("xchacha12-neon");
#endif

View File

@ -8,22 +8,22 @@
#include <asm/hwcap.h> #include <asm/hwcap.h>
#include <asm/neon.h> #include <asm/neon.h>
#include <asm/simd.h>
#include <linux/unaligned.h>
#include <crypto/aes.h> #include <crypto/aes.h>
#include <crypto/gcm.h>
#include <crypto/b128ops.h> #include <crypto/b128ops.h>
#include <crypto/cryptd.h> #include <crypto/gcm.h>
#include <crypto/gf128mul.h>
#include <crypto/ghash.h>
#include <crypto/internal/aead.h> #include <crypto/internal/aead.h>
#include <crypto/internal/hash.h> #include <crypto/internal/hash.h>
#include <crypto/internal/simd.h>
#include <crypto/internal/skcipher.h> #include <crypto/internal/skcipher.h>
#include <crypto/gf128mul.h>
#include <crypto/scatterwalk.h> #include <crypto/scatterwalk.h>
#include <linux/cpufeature.h> #include <linux/cpufeature.h>
#include <linux/crypto.h> #include <linux/errno.h>
#include <linux/jump_label.h> #include <linux/jump_label.h>
#include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/string.h>
#include <linux/unaligned.h>
MODULE_DESCRIPTION("GHASH hash function using ARMv8 Crypto Extensions"); MODULE_DESCRIPTION("GHASH hash function using ARMv8 Crypto Extensions");
MODULE_AUTHOR("Ard Biesheuvel <ardb@kernel.org>"); MODULE_AUTHOR("Ard Biesheuvel <ardb@kernel.org>");
@ -32,9 +32,6 @@ MODULE_ALIAS_CRYPTO("ghash");
MODULE_ALIAS_CRYPTO("gcm(aes)"); MODULE_ALIAS_CRYPTO("gcm(aes)");
MODULE_ALIAS_CRYPTO("rfc4106(gcm(aes))"); MODULE_ALIAS_CRYPTO("rfc4106(gcm(aes))");
#define GHASH_BLOCK_SIZE 16
#define GHASH_DIGEST_SIZE 16
#define RFC4106_NONCE_SIZE 4 #define RFC4106_NONCE_SIZE 4
struct ghash_key { struct ghash_key {
@ -49,10 +46,8 @@ struct gcm_key {
u8 nonce[]; // for RFC4106 nonce u8 nonce[]; // for RFC4106 nonce
}; };
struct ghash_desc_ctx { struct arm_ghash_desc_ctx {
u64 digest[GHASH_DIGEST_SIZE/sizeof(u64)]; u64 digest[GHASH_DIGEST_SIZE/sizeof(u64)];
u8 buf[GHASH_BLOCK_SIZE];
u32 count;
}; };
asmlinkage void pmull_ghash_update_p64(int blocks, u64 dg[], const char *src, asmlinkage void pmull_ghash_update_p64(int blocks, u64 dg[], const char *src,
@ -65,9 +60,9 @@ static __ro_after_init DEFINE_STATIC_KEY_FALSE(use_p64);
static int ghash_init(struct shash_desc *desc) static int ghash_init(struct shash_desc *desc)
{ {
struct ghash_desc_ctx *ctx = shash_desc_ctx(desc); struct arm_ghash_desc_ctx *ctx = shash_desc_ctx(desc);
*ctx = (struct ghash_desc_ctx){}; *ctx = (struct arm_ghash_desc_ctx){};
return 0; return 0;
} }
@ -85,54 +80,51 @@ static void ghash_do_update(int blocks, u64 dg[], const char *src,
static int ghash_update(struct shash_desc *desc, const u8 *src, static int ghash_update(struct shash_desc *desc, const u8 *src,
unsigned int len) unsigned int len)
{ {
struct ghash_desc_ctx *ctx = shash_desc_ctx(desc); struct ghash_key *key = crypto_shash_ctx(desc->tfm);
unsigned int partial = ctx->count % GHASH_BLOCK_SIZE; struct arm_ghash_desc_ctx *ctx = shash_desc_ctx(desc);
int blocks;
ctx->count += len; blocks = len / GHASH_BLOCK_SIZE;
ghash_do_update(blocks, ctx->digest, src, key, NULL);
return len - blocks * GHASH_BLOCK_SIZE;
}
if ((partial + len) >= GHASH_BLOCK_SIZE) { static int ghash_export(struct shash_desc *desc, void *out)
struct ghash_key *key = crypto_shash_ctx(desc->tfm); {
int blocks; struct arm_ghash_desc_ctx *ctx = shash_desc_ctx(desc);
u8 *dst = out;
if (partial) { put_unaligned_be64(ctx->digest[1], dst);
int p = GHASH_BLOCK_SIZE - partial; put_unaligned_be64(ctx->digest[0], dst + 8);
memcpy(ctx->buf + partial, src, p);
src += p;
len -= p;
}
blocks = len / GHASH_BLOCK_SIZE;
len %= GHASH_BLOCK_SIZE;
ghash_do_update(blocks, ctx->digest, src, key,
partial ? ctx->buf : NULL);
src += blocks * GHASH_BLOCK_SIZE;
partial = 0;
}
if (len)
memcpy(ctx->buf + partial, src, len);
return 0; return 0;
} }
static int ghash_final(struct shash_desc *desc, u8 *dst) static int ghash_import(struct shash_desc *desc, const void *in)
{ {
struct ghash_desc_ctx *ctx = shash_desc_ctx(desc); struct arm_ghash_desc_ctx *ctx = shash_desc_ctx(desc);
unsigned int partial = ctx->count % GHASH_BLOCK_SIZE; const u8 *src = in;
if (partial) { ctx->digest[1] = get_unaligned_be64(src);
struct ghash_key *key = crypto_shash_ctx(desc->tfm); ctx->digest[0] = get_unaligned_be64(src + 8);
memset(ctx->buf + partial, 0, GHASH_BLOCK_SIZE - partial);
ghash_do_update(1, ctx->digest, ctx->buf, key, NULL);
}
put_unaligned_be64(ctx->digest[1], dst);
put_unaligned_be64(ctx->digest[0], dst + 8);
*ctx = (struct ghash_desc_ctx){};
return 0; return 0;
} }
static int ghash_finup(struct shash_desc *desc, const u8 *src,
unsigned int len, u8 *dst)
{
struct ghash_key *key = crypto_shash_ctx(desc->tfm);
struct arm_ghash_desc_ctx *ctx = shash_desc_ctx(desc);
if (len) {
u8 buf[GHASH_BLOCK_SIZE] = {};
memcpy(buf, src, len);
ghash_do_update(1, ctx->digest, buf, key, NULL);
memzero_explicit(buf, sizeof(buf));
}
return ghash_export(desc, dst);
}
static void ghash_reflect(u64 h[], const be128 *k) static void ghash_reflect(u64 h[], const be128 *k)
{ {
u64 carry = be64_to_cpu(k->a) >> 63; u64 carry = be64_to_cpu(k->a) >> 63;
@ -175,13 +167,17 @@ static struct shash_alg ghash_alg = {
.digestsize = GHASH_DIGEST_SIZE, .digestsize = GHASH_DIGEST_SIZE,
.init = ghash_init, .init = ghash_init,
.update = ghash_update, .update = ghash_update,
.final = ghash_final, .finup = ghash_finup,
.setkey = ghash_setkey, .setkey = ghash_setkey,
.descsize = sizeof(struct ghash_desc_ctx), .export = ghash_export,
.import = ghash_import,
.descsize = sizeof(struct arm_ghash_desc_ctx),
.statesize = sizeof(struct ghash_desc_ctx),
.base.cra_name = "ghash", .base.cra_name = "ghash",
.base.cra_driver_name = "ghash-ce", .base.cra_driver_name = "ghash-ce",
.base.cra_priority = 300, .base.cra_priority = 300,
.base.cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY,
.base.cra_blocksize = GHASH_BLOCK_SIZE, .base.cra_blocksize = GHASH_BLOCK_SIZE,
.base.cra_ctxsize = sizeof(struct ghash_key) + sizeof(u64[2]), .base.cra_ctxsize = sizeof(struct ghash_key) + sizeof(u64[2]),
.base.cra_module = THIS_MODULE, .base.cra_module = THIS_MODULE,
@ -317,9 +313,6 @@ static int gcm_encrypt(struct aead_request *req, const u8 *iv, u32 assoclen)
u8 *tag, *dst; u8 *tag, *dst;
int tail, err; int tail, err;
if (WARN_ON_ONCE(!may_use_simd()))
return -EBUSY;
err = skcipher_walk_aead_encrypt(&walk, req, false); err = skcipher_walk_aead_encrypt(&walk, req, false);
kernel_neon_begin(); kernel_neon_begin();
@ -409,9 +402,6 @@ static int gcm_decrypt(struct aead_request *req, const u8 *iv, u32 assoclen)
u8 *tag, *dst; u8 *tag, *dst;
int tail, err, ret; int tail, err, ret;
if (WARN_ON_ONCE(!may_use_simd()))
return -EBUSY;
scatterwalk_map_and_copy(otag, req->src, scatterwalk_map_and_copy(otag, req->src,
req->assoclen + req->cryptlen - authsize, req->assoclen + req->cryptlen - authsize,
authsize, 0); authsize, 0);

View File

@ -1,274 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* OpenSSL/Cryptogams accelerated Poly1305 transform for ARM
*
* Copyright (C) 2019 Linaro Ltd. <ard.biesheuvel@linaro.org>
*/
#include <asm/hwcap.h>
#include <asm/neon.h>
#include <asm/simd.h>
#include <linux/unaligned.h>
#include <crypto/algapi.h>
#include <crypto/internal/hash.h>
#include <crypto/internal/poly1305.h>
#include <crypto/internal/simd.h>
#include <linux/cpufeature.h>
#include <linux/crypto.h>
#include <linux/jump_label.h>
#include <linux/module.h>
void poly1305_init_arm(void *state, const u8 *key);
void poly1305_blocks_arm(void *state, const u8 *src, u32 len, u32 hibit);
void poly1305_blocks_neon(void *state, const u8 *src, u32 len, u32 hibit);
void poly1305_emit_arm(void *state, u8 *digest, const u32 *nonce);
void __weak poly1305_blocks_neon(void *state, const u8 *src, u32 len, u32 hibit)
{
}
static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_neon);
void poly1305_init_arch(struct poly1305_desc_ctx *dctx, const u8 key[POLY1305_KEY_SIZE])
{
poly1305_init_arm(&dctx->h, key);
dctx->s[0] = get_unaligned_le32(key + 16);
dctx->s[1] = get_unaligned_le32(key + 20);
dctx->s[2] = get_unaligned_le32(key + 24);
dctx->s[3] = get_unaligned_le32(key + 28);
dctx->buflen = 0;
}
EXPORT_SYMBOL(poly1305_init_arch);
static int arm_poly1305_init(struct shash_desc *desc)
{
struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc);
dctx->buflen = 0;
dctx->rset = 0;
dctx->sset = false;
return 0;
}
static void arm_poly1305_blocks(struct poly1305_desc_ctx *dctx, const u8 *src,
u32 len, u32 hibit, bool do_neon)
{
if (unlikely(!dctx->sset)) {
if (!dctx->rset) {
poly1305_init_arm(&dctx->h, src);
src += POLY1305_BLOCK_SIZE;
len -= POLY1305_BLOCK_SIZE;
dctx->rset = 1;
}
if (len >= POLY1305_BLOCK_SIZE) {
dctx->s[0] = get_unaligned_le32(src + 0);
dctx->s[1] = get_unaligned_le32(src + 4);
dctx->s[2] = get_unaligned_le32(src + 8);
dctx->s[3] = get_unaligned_le32(src + 12);
src += POLY1305_BLOCK_SIZE;
len -= POLY1305_BLOCK_SIZE;
dctx->sset = true;
}
if (len < POLY1305_BLOCK_SIZE)
return;
}
len &= ~(POLY1305_BLOCK_SIZE - 1);
if (static_branch_likely(&have_neon) && likely(do_neon))
poly1305_blocks_neon(&dctx->h, src, len, hibit);
else
poly1305_blocks_arm(&dctx->h, src, len, hibit);
}
static void arm_poly1305_do_update(struct poly1305_desc_ctx *dctx,
const u8 *src, u32 len, bool do_neon)
{
if (unlikely(dctx->buflen)) {
u32 bytes = min(len, POLY1305_BLOCK_SIZE - dctx->buflen);
memcpy(dctx->buf + dctx->buflen, src, bytes);
src += bytes;
len -= bytes;
dctx->buflen += bytes;
if (dctx->buflen == POLY1305_BLOCK_SIZE) {
arm_poly1305_blocks(dctx, dctx->buf,
POLY1305_BLOCK_SIZE, 1, false);
dctx->buflen = 0;
}
}
if (likely(len >= POLY1305_BLOCK_SIZE)) {
arm_poly1305_blocks(dctx, src, len, 1, do_neon);
src += round_down(len, POLY1305_BLOCK_SIZE);
len %= POLY1305_BLOCK_SIZE;
}
if (unlikely(len)) {
dctx->buflen = len;
memcpy(dctx->buf, src, len);
}
}
static int arm_poly1305_update(struct shash_desc *desc,
const u8 *src, unsigned int srclen)
{
struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc);
arm_poly1305_do_update(dctx, src, srclen, false);
return 0;
}
static int __maybe_unused arm_poly1305_update_neon(struct shash_desc *desc,
const u8 *src,
unsigned int srclen)
{
struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc);
bool do_neon = crypto_simd_usable() && srclen > 128;
if (static_branch_likely(&have_neon) && do_neon)
kernel_neon_begin();
arm_poly1305_do_update(dctx, src, srclen, do_neon);
if (static_branch_likely(&have_neon) && do_neon)
kernel_neon_end();
return 0;
}
void poly1305_update_arch(struct poly1305_desc_ctx *dctx, const u8 *src,
unsigned int nbytes)
{
bool do_neon = IS_ENABLED(CONFIG_KERNEL_MODE_NEON) &&
crypto_simd_usable();
if (unlikely(dctx->buflen)) {
u32 bytes = min(nbytes, POLY1305_BLOCK_SIZE - dctx->buflen);
memcpy(dctx->buf + dctx->buflen, src, bytes);
src += bytes;
nbytes -= bytes;
dctx->buflen += bytes;
if (dctx->buflen == POLY1305_BLOCK_SIZE) {
poly1305_blocks_arm(&dctx->h, dctx->buf,
POLY1305_BLOCK_SIZE, 1);
dctx->buflen = 0;
}
}
if (likely(nbytes >= POLY1305_BLOCK_SIZE)) {
unsigned int len = round_down(nbytes, POLY1305_BLOCK_SIZE);
if (static_branch_likely(&have_neon) && do_neon) {
do {
unsigned int todo = min_t(unsigned int, len, SZ_4K);
kernel_neon_begin();
poly1305_blocks_neon(&dctx->h, src, todo, 1);
kernel_neon_end();
len -= todo;
src += todo;
} while (len);
} else {
poly1305_blocks_arm(&dctx->h, src, len, 1);
src += len;
}
nbytes %= POLY1305_BLOCK_SIZE;
}
if (unlikely(nbytes)) {
dctx->buflen = nbytes;
memcpy(dctx->buf, src, nbytes);
}
}
EXPORT_SYMBOL(poly1305_update_arch);
void poly1305_final_arch(struct poly1305_desc_ctx *dctx, u8 *dst)
{
if (unlikely(dctx->buflen)) {
dctx->buf[dctx->buflen++] = 1;
memset(dctx->buf + dctx->buflen, 0,
POLY1305_BLOCK_SIZE - dctx->buflen);
poly1305_blocks_arm(&dctx->h, dctx->buf, POLY1305_BLOCK_SIZE, 0);
}
poly1305_emit_arm(&dctx->h, dst, dctx->s);
*dctx = (struct poly1305_desc_ctx){};
}
EXPORT_SYMBOL(poly1305_final_arch);
static int arm_poly1305_final(struct shash_desc *desc, u8 *dst)
{
struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc);
if (unlikely(!dctx->sset))
return -ENOKEY;
poly1305_final_arch(dctx, dst);
return 0;
}
static struct shash_alg arm_poly1305_algs[] = {{
.init = arm_poly1305_init,
.update = arm_poly1305_update,
.final = arm_poly1305_final,
.digestsize = POLY1305_DIGEST_SIZE,
.descsize = sizeof(struct poly1305_desc_ctx),
.base.cra_name = "poly1305",
.base.cra_driver_name = "poly1305-arm",
.base.cra_priority = 150,
.base.cra_blocksize = POLY1305_BLOCK_SIZE,
.base.cra_module = THIS_MODULE,
#ifdef CONFIG_KERNEL_MODE_NEON
}, {
.init = arm_poly1305_init,
.update = arm_poly1305_update_neon,
.final = arm_poly1305_final,
.digestsize = POLY1305_DIGEST_SIZE,
.descsize = sizeof(struct poly1305_desc_ctx),
.base.cra_name = "poly1305",
.base.cra_driver_name = "poly1305-neon",
.base.cra_priority = 200,
.base.cra_blocksize = POLY1305_BLOCK_SIZE,
.base.cra_module = THIS_MODULE,
#endif
}};
static int __init arm_poly1305_mod_init(void)
{
if (IS_ENABLED(CONFIG_KERNEL_MODE_NEON) &&
(elf_hwcap & HWCAP_NEON))
static_branch_enable(&have_neon);
else if (IS_REACHABLE(CONFIG_CRYPTO_HASH))
/* register only the first entry */
return crypto_register_shash(&arm_poly1305_algs[0]);
return IS_REACHABLE(CONFIG_CRYPTO_HASH) ?
crypto_register_shashes(arm_poly1305_algs,
ARRAY_SIZE(arm_poly1305_algs)) : 0;
}
static void __exit arm_poly1305_mod_exit(void)
{
if (!IS_REACHABLE(CONFIG_CRYPTO_HASH))
return;
if (!static_branch_likely(&have_neon)) {
crypto_unregister_shash(&arm_poly1305_algs[0]);
return;
}
crypto_unregister_shashes(arm_poly1305_algs,
ARRAY_SIZE(arm_poly1305_algs));
}
module_init(arm_poly1305_mod_init);
module_exit(arm_poly1305_mod_exit);
MODULE_DESCRIPTION("Accelerated Poly1305 transform for ARM");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS_CRYPTO("poly1305");
MODULE_ALIAS_CRYPTO("poly1305-arm");
MODULE_ALIAS_CRYPTO("poly1305-neon");

View File

@ -5,20 +5,14 @@
* Copyright (C) 2015 Linaro Ltd <ard.biesheuvel@linaro.org> * Copyright (C) 2015 Linaro Ltd <ard.biesheuvel@linaro.org>
*/ */
#include <asm/neon.h>
#include <crypto/internal/hash.h> #include <crypto/internal/hash.h>
#include <crypto/internal/simd.h>
#include <crypto/sha1.h> #include <crypto/sha1.h>
#include <crypto/sha1_base.h> #include <crypto/sha1_base.h>
#include <linux/cpufeature.h> #include <linux/cpufeature.h>
#include <linux/crypto.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <asm/hwcap.h>
#include <asm/neon.h>
#include <asm/simd.h>
#include "sha1.h"
MODULE_DESCRIPTION("SHA1 secure hash using ARMv8 Crypto Extensions"); MODULE_DESCRIPTION("SHA1 secure hash using ARMv8 Crypto Extensions");
MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>"); MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
@ -29,50 +23,36 @@ asmlinkage void sha1_ce_transform(struct sha1_state *sst, u8 const *src,
static int sha1_ce_update(struct shash_desc *desc, const u8 *data, static int sha1_ce_update(struct shash_desc *desc, const u8 *data,
unsigned int len) unsigned int len)
{ {
struct sha1_state *sctx = shash_desc_ctx(desc); int remain;
if (!crypto_simd_usable() ||
(sctx->count % SHA1_BLOCK_SIZE) + len < SHA1_BLOCK_SIZE)
return sha1_update_arm(desc, data, len);
kernel_neon_begin(); kernel_neon_begin();
sha1_base_do_update(desc, data, len, sha1_ce_transform); remain = sha1_base_do_update_blocks(desc, data, len, sha1_ce_transform);
kernel_neon_end(); kernel_neon_end();
return 0; return remain;
} }
static int sha1_ce_finup(struct shash_desc *desc, const u8 *data, static int sha1_ce_finup(struct shash_desc *desc, const u8 *data,
unsigned int len, u8 *out) unsigned int len, u8 *out)
{ {
if (!crypto_simd_usable())
return sha1_finup_arm(desc, data, len, out);
kernel_neon_begin(); kernel_neon_begin();
if (len) sha1_base_do_finup(desc, data, len, sha1_ce_transform);
sha1_base_do_update(desc, data, len, sha1_ce_transform);
sha1_base_do_finalize(desc, sha1_ce_transform);
kernel_neon_end(); kernel_neon_end();
return sha1_base_finish(desc, out); return sha1_base_finish(desc, out);
} }
static int sha1_ce_final(struct shash_desc *desc, u8 *out)
{
return sha1_ce_finup(desc, NULL, 0, out);
}
static struct shash_alg alg = { static struct shash_alg alg = {
.init = sha1_base_init, .init = sha1_base_init,
.update = sha1_ce_update, .update = sha1_ce_update,
.final = sha1_ce_final,
.finup = sha1_ce_finup, .finup = sha1_ce_finup,
.descsize = sizeof(struct sha1_state), .descsize = SHA1_STATE_SIZE,
.digestsize = SHA1_DIGEST_SIZE, .digestsize = SHA1_DIGEST_SIZE,
.base = { .base = {
.cra_name = "sha1", .cra_name = "sha1",
.cra_driver_name = "sha1-ce", .cra_driver_name = "sha1-ce",
.cra_priority = 200, .cra_priority = 200,
.cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY,
.cra_blocksize = SHA1_BLOCK_SIZE, .cra_blocksize = SHA1_BLOCK_SIZE,
.cra_module = THIS_MODULE, .cra_module = THIS_MODULE,
} }

View File

@ -1,14 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef ASM_ARM_CRYPTO_SHA1_H
#define ASM_ARM_CRYPTO_SHA1_H
#include <linux/crypto.h>
#include <crypto/sha1.h>
extern int sha1_update_arm(struct shash_desc *desc, const u8 *data,
unsigned int len);
extern int sha1_finup_arm(struct shash_desc *desc, const u8 *data,
unsigned int len, u8 *out);
#endif

View File

@ -12,53 +12,42 @@
*/ */
#include <crypto/internal/hash.h> #include <crypto/internal/hash.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
#include <crypto/sha1.h> #include <crypto/sha1.h>
#include <crypto/sha1_base.h> #include <crypto/sha1_base.h>
#include <asm/byteorder.h> #include <linux/kernel.h>
#include <linux/module.h>
#include "sha1.h"
asmlinkage void sha1_block_data_order(struct sha1_state *digest, asmlinkage void sha1_block_data_order(struct sha1_state *digest,
const u8 *data, int rounds); const u8 *data, int rounds);
int sha1_update_arm(struct shash_desc *desc, const u8 *data, static int sha1_update_arm(struct shash_desc *desc, const u8 *data,
unsigned int len) unsigned int len)
{ {
/* make sure signature matches sha1_block_fn() */ /* make sure signature matches sha1_block_fn() */
BUILD_BUG_ON(offsetof(struct sha1_state, state) != 0); BUILD_BUG_ON(offsetof(struct sha1_state, state) != 0);
return sha1_base_do_update(desc, data, len, sha1_block_data_order); return sha1_base_do_update_blocks(desc, data, len,
sha1_block_data_order);
} }
EXPORT_SYMBOL_GPL(sha1_update_arm);
static int sha1_final(struct shash_desc *desc, u8 *out) static int sha1_finup_arm(struct shash_desc *desc, const u8 *data,
unsigned int len, u8 *out)
{ {
sha1_base_do_finalize(desc, sha1_block_data_order); sha1_base_do_finup(desc, data, len, sha1_block_data_order);
return sha1_base_finish(desc, out); return sha1_base_finish(desc, out);
} }
int sha1_finup_arm(struct shash_desc *desc, const u8 *data,
unsigned int len, u8 *out)
{
sha1_base_do_update(desc, data, len, sha1_block_data_order);
return sha1_final(desc, out);
}
EXPORT_SYMBOL_GPL(sha1_finup_arm);
static struct shash_alg alg = { static struct shash_alg alg = {
.digestsize = SHA1_DIGEST_SIZE, .digestsize = SHA1_DIGEST_SIZE,
.init = sha1_base_init, .init = sha1_base_init,
.update = sha1_update_arm, .update = sha1_update_arm,
.final = sha1_final,
.finup = sha1_finup_arm, .finup = sha1_finup_arm,
.descsize = sizeof(struct sha1_state), .descsize = SHA1_STATE_SIZE,
.base = { .base = {
.cra_name = "sha1", .cra_name = "sha1",
.cra_driver_name= "sha1-asm", .cra_driver_name= "sha1-asm",
.cra_priority = 150, .cra_priority = 150,
.cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY,
.cra_blocksize = SHA1_BLOCK_SIZE, .cra_blocksize = SHA1_BLOCK_SIZE,
.cra_module = THIS_MODULE, .cra_module = THIS_MODULE,
} }

View File

@ -13,18 +13,12 @@
* Copyright (c) Chandramouli Narayanan <mouli@linux.intel.com> * Copyright (c) Chandramouli Narayanan <mouli@linux.intel.com>
*/ */
#include <asm/neon.h>
#include <crypto/internal/hash.h> #include <crypto/internal/hash.h>
#include <crypto/internal/simd.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/types.h>
#include <crypto/sha1.h> #include <crypto/sha1.h>
#include <crypto/sha1_base.h> #include <crypto/sha1_base.h>
#include <asm/neon.h> #include <linux/kernel.h>
#include <asm/simd.h> #include <linux/module.h>
#include "sha1.h"
asmlinkage void sha1_transform_neon(struct sha1_state *state_h, asmlinkage void sha1_transform_neon(struct sha1_state *state_h,
const u8 *data, int rounds); const u8 *data, int rounds);
@ -32,50 +26,37 @@ asmlinkage void sha1_transform_neon(struct sha1_state *state_h,
static int sha1_neon_update(struct shash_desc *desc, const u8 *data, static int sha1_neon_update(struct shash_desc *desc, const u8 *data,
unsigned int len) unsigned int len)
{ {
struct sha1_state *sctx = shash_desc_ctx(desc); int remain;
if (!crypto_simd_usable() ||
(sctx->count % SHA1_BLOCK_SIZE) + len < SHA1_BLOCK_SIZE)
return sha1_update_arm(desc, data, len);
kernel_neon_begin(); kernel_neon_begin();
sha1_base_do_update(desc, data, len, sha1_transform_neon); remain = sha1_base_do_update_blocks(desc, data, len,
sha1_transform_neon);
kernel_neon_end(); kernel_neon_end();
return 0; return remain;
} }
static int sha1_neon_finup(struct shash_desc *desc, const u8 *data, static int sha1_neon_finup(struct shash_desc *desc, const u8 *data,
unsigned int len, u8 *out) unsigned int len, u8 *out)
{ {
if (!crypto_simd_usable())
return sha1_finup_arm(desc, data, len, out);
kernel_neon_begin(); kernel_neon_begin();
if (len) sha1_base_do_finup(desc, data, len, sha1_transform_neon);
sha1_base_do_update(desc, data, len, sha1_transform_neon);
sha1_base_do_finalize(desc, sha1_transform_neon);
kernel_neon_end(); kernel_neon_end();
return sha1_base_finish(desc, out); return sha1_base_finish(desc, out);
} }
static int sha1_neon_final(struct shash_desc *desc, u8 *out)
{
return sha1_neon_finup(desc, NULL, 0, out);
}
static struct shash_alg alg = { static struct shash_alg alg = {
.digestsize = SHA1_DIGEST_SIZE, .digestsize = SHA1_DIGEST_SIZE,
.init = sha1_base_init, .init = sha1_base_init,
.update = sha1_neon_update, .update = sha1_neon_update,
.final = sha1_neon_final,
.finup = sha1_neon_finup, .finup = sha1_neon_finup,
.descsize = sizeof(struct sha1_state), .descsize = SHA1_STATE_SIZE,
.base = { .base = {
.cra_name = "sha1", .cra_name = "sha1",
.cra_driver_name = "sha1-neon", .cra_driver_name = "sha1-neon",
.cra_priority = 250, .cra_priority = 250,
.cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY,
.cra_blocksize = SHA1_BLOCK_SIZE, .cra_blocksize = SHA1_BLOCK_SIZE,
.cra_module = THIS_MODULE, .cra_module = THIS_MODULE,
} }

View File

@ -1,109 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* sha2-ce-glue.c - SHA-224/SHA-256 using ARMv8 Crypto Extensions
*
* Copyright (C) 2015 Linaro Ltd <ard.biesheuvel@linaro.org>
*/
#include <crypto/internal/hash.h>
#include <crypto/internal/simd.h>
#include <crypto/sha2.h>
#include <crypto/sha256_base.h>
#include <linux/cpufeature.h>
#include <linux/crypto.h>
#include <linux/module.h>
#include <asm/hwcap.h>
#include <asm/simd.h>
#include <asm/neon.h>
#include <linux/unaligned.h>
#include "sha256_glue.h"
MODULE_DESCRIPTION("SHA-224/SHA-256 secure hash using ARMv8 Crypto Extensions");
MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
MODULE_LICENSE("GPL v2");
asmlinkage void sha2_ce_transform(struct sha256_state *sst, u8 const *src,
int blocks);
static int sha2_ce_update(struct shash_desc *desc, const u8 *data,
unsigned int len)
{
struct sha256_state *sctx = shash_desc_ctx(desc);
if (!crypto_simd_usable() ||
(sctx->count % SHA256_BLOCK_SIZE) + len < SHA256_BLOCK_SIZE)
return crypto_sha256_arm_update(desc, data, len);
kernel_neon_begin();
sha256_base_do_update(desc, data, len,
(sha256_block_fn *)sha2_ce_transform);
kernel_neon_end();
return 0;
}
static int sha2_ce_finup(struct shash_desc *desc, const u8 *data,
unsigned int len, u8 *out)
{
if (!crypto_simd_usable())
return crypto_sha256_arm_finup(desc, data, len, out);
kernel_neon_begin();
if (len)
sha256_base_do_update(desc, data, len,
(sha256_block_fn *)sha2_ce_transform);
sha256_base_do_finalize(desc, (sha256_block_fn *)sha2_ce_transform);
kernel_neon_end();
return sha256_base_finish(desc, out);
}
static int sha2_ce_final(struct shash_desc *desc, u8 *out)
{
return sha2_ce_finup(desc, NULL, 0, out);
}
static struct shash_alg algs[] = { {
.init = sha224_base_init,
.update = sha2_ce_update,
.final = sha2_ce_final,
.finup = sha2_ce_finup,
.descsize = sizeof(struct sha256_state),
.digestsize = SHA224_DIGEST_SIZE,
.base = {
.cra_name = "sha224",
.cra_driver_name = "sha224-ce",
.cra_priority = 300,
.cra_blocksize = SHA256_BLOCK_SIZE,
.cra_module = THIS_MODULE,
}
}, {
.init = sha256_base_init,
.update = sha2_ce_update,
.final = sha2_ce_final,
.finup = sha2_ce_finup,
.descsize = sizeof(struct sha256_state),
.digestsize = SHA256_DIGEST_SIZE,
.base = {
.cra_name = "sha256",
.cra_driver_name = "sha256-ce",
.cra_priority = 300,
.cra_blocksize = SHA256_BLOCK_SIZE,
.cra_module = THIS_MODULE,
}
} };
static int __init sha2_ce_mod_init(void)
{
return crypto_register_shashes(algs, ARRAY_SIZE(algs));
}
static void __exit sha2_ce_mod_fini(void)
{
crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
}
module_cpu_feature_match(SHA2, sha2_ce_mod_init);
module_exit(sha2_ce_mod_fini);

View File

@ -1,117 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Glue code for the SHA256 Secure Hash Algorithm assembly implementation
* using optimized ARM assembler and NEON instructions.
*
* Copyright © 2015 Google Inc.
*
* This file is based on sha256_ssse3_glue.c:
* Copyright (C) 2013 Intel Corporation
* Author: Tim Chen <tim.c.chen@linux.intel.com>
*/
#include <crypto/internal/hash.h>
#include <linux/crypto.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/types.h>
#include <linux/string.h>
#include <crypto/sha2.h>
#include <crypto/sha256_base.h>
#include <asm/simd.h>
#include <asm/neon.h>
#include "sha256_glue.h"
asmlinkage void sha256_block_data_order(struct sha256_state *state,
const u8 *data, int num_blks);
int crypto_sha256_arm_update(struct shash_desc *desc, const u8 *data,
unsigned int len)
{
/* make sure casting to sha256_block_fn() is safe */
BUILD_BUG_ON(offsetof(struct sha256_state, state) != 0);
return sha256_base_do_update(desc, data, len, sha256_block_data_order);
}
EXPORT_SYMBOL(crypto_sha256_arm_update);
static int crypto_sha256_arm_final(struct shash_desc *desc, u8 *out)
{
sha256_base_do_finalize(desc, sha256_block_data_order);
return sha256_base_finish(desc, out);
}
int crypto_sha256_arm_finup(struct shash_desc *desc, const u8 *data,
unsigned int len, u8 *out)
{
sha256_base_do_update(desc, data, len, sha256_block_data_order);
return crypto_sha256_arm_final(desc, out);
}
EXPORT_SYMBOL(crypto_sha256_arm_finup);
static struct shash_alg algs[] = { {
.digestsize = SHA256_DIGEST_SIZE,
.init = sha256_base_init,
.update = crypto_sha256_arm_update,
.final = crypto_sha256_arm_final,
.finup = crypto_sha256_arm_finup,
.descsize = sizeof(struct sha256_state),
.base = {
.cra_name = "sha256",
.cra_driver_name = "sha256-asm",
.cra_priority = 150,
.cra_blocksize = SHA256_BLOCK_SIZE,
.cra_module = THIS_MODULE,
}
}, {
.digestsize = SHA224_DIGEST_SIZE,
.init = sha224_base_init,
.update = crypto_sha256_arm_update,
.final = crypto_sha256_arm_final,
.finup = crypto_sha256_arm_finup,
.descsize = sizeof(struct sha256_state),
.base = {
.cra_name = "sha224",
.cra_driver_name = "sha224-asm",
.cra_priority = 150,
.cra_blocksize = SHA224_BLOCK_SIZE,
.cra_module = THIS_MODULE,
}
} };
static int __init sha256_mod_init(void)
{
int res = crypto_register_shashes(algs, ARRAY_SIZE(algs));
if (res < 0)
return res;
if (IS_ENABLED(CONFIG_KERNEL_MODE_NEON) && cpu_has_neon()) {
res = crypto_register_shashes(sha256_neon_algs,
ARRAY_SIZE(sha256_neon_algs));
if (res < 0)
crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
}
return res;
}
static void __exit sha256_mod_fini(void)
{
crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
if (IS_ENABLED(CONFIG_KERNEL_MODE_NEON) && cpu_has_neon())
crypto_unregister_shashes(sha256_neon_algs,
ARRAY_SIZE(sha256_neon_algs));
}
module_init(sha256_mod_init);
module_exit(sha256_mod_fini);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SHA256 Secure Hash Algorithm (ARM), including NEON");
MODULE_ALIAS_CRYPTO("sha256");

View File

@ -1,15 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _CRYPTO_SHA256_GLUE_H
#define _CRYPTO_SHA256_GLUE_H
#include <linux/crypto.h>
extern struct shash_alg sha256_neon_algs[2];
int crypto_sha256_arm_update(struct shash_desc *desc, const u8 *data,
unsigned int len);
int crypto_sha256_arm_finup(struct shash_desc *desc, const u8 *data,
unsigned int len, u8 *hash);
#endif /* _CRYPTO_SHA256_GLUE_H */

View File

@ -1,92 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Glue code for the SHA256 Secure Hash Algorithm assembly implementation
* using NEON instructions.
*
* Copyright © 2015 Google Inc.
*
* This file is based on sha512_neon_glue.c:
* Copyright © 2014 Jussi Kivilinna <jussi.kivilinna@iki.fi>
*/
#include <crypto/internal/hash.h>
#include <crypto/internal/simd.h>
#include <linux/types.h>
#include <linux/string.h>
#include <crypto/sha2.h>
#include <crypto/sha256_base.h>
#include <asm/byteorder.h>
#include <asm/simd.h>
#include <asm/neon.h>
#include "sha256_glue.h"
asmlinkage void sha256_block_data_order_neon(struct sha256_state *digest,
const u8 *data, int num_blks);
static int crypto_sha256_neon_update(struct shash_desc *desc, const u8 *data,
unsigned int len)
{
struct sha256_state *sctx = shash_desc_ctx(desc);
if (!crypto_simd_usable() ||
(sctx->count % SHA256_BLOCK_SIZE) + len < SHA256_BLOCK_SIZE)
return crypto_sha256_arm_update(desc, data, len);
kernel_neon_begin();
sha256_base_do_update(desc, data, len, sha256_block_data_order_neon);
kernel_neon_end();
return 0;
}
static int crypto_sha256_neon_finup(struct shash_desc *desc, const u8 *data,
unsigned int len, u8 *out)
{
if (!crypto_simd_usable())
return crypto_sha256_arm_finup(desc, data, len, out);
kernel_neon_begin();
if (len)
sha256_base_do_update(desc, data, len,
sha256_block_data_order_neon);
sha256_base_do_finalize(desc, sha256_block_data_order_neon);
kernel_neon_end();
return sha256_base_finish(desc, out);
}
static int crypto_sha256_neon_final(struct shash_desc *desc, u8 *out)
{
return crypto_sha256_neon_finup(desc, NULL, 0, out);
}
struct shash_alg sha256_neon_algs[] = { {
.digestsize = SHA256_DIGEST_SIZE,
.init = sha256_base_init,
.update = crypto_sha256_neon_update,
.final = crypto_sha256_neon_final,
.finup = crypto_sha256_neon_finup,
.descsize = sizeof(struct sha256_state),
.base = {
.cra_name = "sha256",
.cra_driver_name = "sha256-neon",
.cra_priority = 250,
.cra_blocksize = SHA256_BLOCK_SIZE,
.cra_module = THIS_MODULE,
}
}, {
.digestsize = SHA224_DIGEST_SIZE,
.init = sha224_base_init,
.update = crypto_sha256_neon_update,
.final = crypto_sha256_neon_final,
.finup = crypto_sha256_neon_finup,
.descsize = sizeof(struct sha256_state),
.base = {
.cra_name = "sha224",
.cra_driver_name = "sha224-neon",
.cra_priority = 250,
.cra_blocksize = SHA224_BLOCK_SIZE,
.cra_module = THIS_MODULE,
}
} };

View File

@ -5,15 +5,14 @@
* Copyright (C) 2015 Linaro Ltd <ard.biesheuvel@linaro.org> * Copyright (C) 2015 Linaro Ltd <ard.biesheuvel@linaro.org>
*/ */
#include <asm/hwcap.h>
#include <asm/neon.h>
#include <crypto/internal/hash.h> #include <crypto/internal/hash.h>
#include <crypto/sha2.h> #include <crypto/sha2.h>
#include <crypto/sha512_base.h> #include <crypto/sha512_base.h>
#include <linux/crypto.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <asm/hwcap.h>
#include <asm/neon.h>
#include "sha512.h" #include "sha512.h"
MODULE_DESCRIPTION("Accelerated SHA-384/SHA-512 secure hash for ARM"); MODULE_DESCRIPTION("Accelerated SHA-384/SHA-512 secure hash for ARM");
@ -28,50 +27,47 @@ MODULE_ALIAS_CRYPTO("sha512-arm");
asmlinkage void sha512_block_data_order(struct sha512_state *state, asmlinkage void sha512_block_data_order(struct sha512_state *state,
u8 const *src, int blocks); u8 const *src, int blocks);
int sha512_arm_update(struct shash_desc *desc, const u8 *data, static int sha512_arm_update(struct shash_desc *desc, const u8 *data,
unsigned int len) unsigned int len)
{ {
return sha512_base_do_update(desc, data, len, sha512_block_data_order); return sha512_base_do_update_blocks(desc, data, len,
sha512_block_data_order);
} }
static int sha512_arm_final(struct shash_desc *desc, u8 *out) static int sha512_arm_finup(struct shash_desc *desc, const u8 *data,
unsigned int len, u8 *out)
{ {
sha512_base_do_finalize(desc, sha512_block_data_order); sha512_base_do_finup(desc, data, len, sha512_block_data_order);
return sha512_base_finish(desc, out); return sha512_base_finish(desc, out);
} }
int sha512_arm_finup(struct shash_desc *desc, const u8 *data,
unsigned int len, u8 *out)
{
sha512_base_do_update(desc, data, len, sha512_block_data_order);
return sha512_arm_final(desc, out);
}
static struct shash_alg sha512_arm_algs[] = { { static struct shash_alg sha512_arm_algs[] = { {
.init = sha384_base_init, .init = sha384_base_init,
.update = sha512_arm_update, .update = sha512_arm_update,
.final = sha512_arm_final,
.finup = sha512_arm_finup, .finup = sha512_arm_finup,
.descsize = sizeof(struct sha512_state), .descsize = SHA512_STATE_SIZE,
.digestsize = SHA384_DIGEST_SIZE, .digestsize = SHA384_DIGEST_SIZE,
.base = { .base = {
.cra_name = "sha384", .cra_name = "sha384",
.cra_driver_name = "sha384-arm", .cra_driver_name = "sha384-arm",
.cra_priority = 250, .cra_priority = 250,
.cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY |
CRYPTO_AHASH_ALG_FINUP_MAX,
.cra_blocksize = SHA512_BLOCK_SIZE, .cra_blocksize = SHA512_BLOCK_SIZE,
.cra_module = THIS_MODULE, .cra_module = THIS_MODULE,
} }
}, { }, {
.init = sha512_base_init, .init = sha512_base_init,
.update = sha512_arm_update, .update = sha512_arm_update,
.final = sha512_arm_final,
.finup = sha512_arm_finup, .finup = sha512_arm_finup,
.descsize = sizeof(struct sha512_state), .descsize = SHA512_STATE_SIZE,
.digestsize = SHA512_DIGEST_SIZE, .digestsize = SHA512_DIGEST_SIZE,
.base = { .base = {
.cra_name = "sha512", .cra_name = "sha512",
.cra_driver_name = "sha512-arm", .cra_driver_name = "sha512-arm",
.cra_priority = 250, .cra_priority = 250,
.cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY |
CRYPTO_AHASH_ALG_FINUP_MAX,
.cra_blocksize = SHA512_BLOCK_SIZE, .cra_blocksize = SHA512_BLOCK_SIZE,
.cra_module = THIS_MODULE, .cra_module = THIS_MODULE,
} }

View File

@ -5,16 +5,13 @@
* Copyright (C) 2015 Linaro Ltd <ard.biesheuvel@linaro.org> * Copyright (C) 2015 Linaro Ltd <ard.biesheuvel@linaro.org>
*/ */
#include <asm/neon.h>
#include <crypto/internal/hash.h> #include <crypto/internal/hash.h>
#include <crypto/internal/simd.h>
#include <crypto/sha2.h> #include <crypto/sha2.h>
#include <crypto/sha512_base.h> #include <crypto/sha512_base.h>
#include <linux/crypto.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <asm/simd.h>
#include <asm/neon.h>
#include "sha512.h" #include "sha512.h"
MODULE_ALIAS_CRYPTO("sha384-neon"); MODULE_ALIAS_CRYPTO("sha384-neon");
@ -26,51 +23,36 @@ asmlinkage void sha512_block_data_order_neon(struct sha512_state *state,
static int sha512_neon_update(struct shash_desc *desc, const u8 *data, static int sha512_neon_update(struct shash_desc *desc, const u8 *data,
unsigned int len) unsigned int len)
{ {
struct sha512_state *sctx = shash_desc_ctx(desc); int remain;
if (!crypto_simd_usable() ||
(sctx->count[0] % SHA512_BLOCK_SIZE) + len < SHA512_BLOCK_SIZE)
return sha512_arm_update(desc, data, len);
kernel_neon_begin(); kernel_neon_begin();
sha512_base_do_update(desc, data, len, sha512_block_data_order_neon); remain = sha512_base_do_update_blocks(desc, data, len,
sha512_block_data_order_neon);
kernel_neon_end(); kernel_neon_end();
return remain;
return 0;
} }
static int sha512_neon_finup(struct shash_desc *desc, const u8 *data, static int sha512_neon_finup(struct shash_desc *desc, const u8 *data,
unsigned int len, u8 *out) unsigned int len, u8 *out)
{ {
if (!crypto_simd_usable())
return sha512_arm_finup(desc, data, len, out);
kernel_neon_begin(); kernel_neon_begin();
if (len) sha512_base_do_finup(desc, data, len, sha512_block_data_order_neon);
sha512_base_do_update(desc, data, len,
sha512_block_data_order_neon);
sha512_base_do_finalize(desc, sha512_block_data_order_neon);
kernel_neon_end(); kernel_neon_end();
return sha512_base_finish(desc, out); return sha512_base_finish(desc, out);
} }
static int sha512_neon_final(struct shash_desc *desc, u8 *out)
{
return sha512_neon_finup(desc, NULL, 0, out);
}
struct shash_alg sha512_neon_algs[] = { { struct shash_alg sha512_neon_algs[] = { {
.init = sha384_base_init, .init = sha384_base_init,
.update = sha512_neon_update, .update = sha512_neon_update,
.final = sha512_neon_final,
.finup = sha512_neon_finup, .finup = sha512_neon_finup,
.descsize = sizeof(struct sha512_state), .descsize = SHA512_STATE_SIZE,
.digestsize = SHA384_DIGEST_SIZE, .digestsize = SHA384_DIGEST_SIZE,
.base = { .base = {
.cra_name = "sha384", .cra_name = "sha384",
.cra_driver_name = "sha384-neon", .cra_driver_name = "sha384-neon",
.cra_priority = 300, .cra_priority = 300,
.cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY |
CRYPTO_AHASH_ALG_FINUP_MAX,
.cra_blocksize = SHA384_BLOCK_SIZE, .cra_blocksize = SHA384_BLOCK_SIZE,
.cra_module = THIS_MODULE, .cra_module = THIS_MODULE,
@ -78,14 +60,15 @@ struct shash_alg sha512_neon_algs[] = { {
}, { }, {
.init = sha512_base_init, .init = sha512_base_init,
.update = sha512_neon_update, .update = sha512_neon_update,
.final = sha512_neon_final,
.finup = sha512_neon_finup, .finup = sha512_neon_finup,
.descsize = sizeof(struct sha512_state), .descsize = SHA512_STATE_SIZE,
.digestsize = SHA512_DIGEST_SIZE, .digestsize = SHA512_DIGEST_SIZE,
.base = { .base = {
.cra_name = "sha512", .cra_name = "sha512",
.cra_driver_name = "sha512-neon", .cra_driver_name = "sha512-neon",
.cra_priority = 300, .cra_priority = 300,
.cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY |
CRYPTO_AHASH_ALG_FINUP_MAX,
.cra_blocksize = SHA512_BLOCK_SIZE, .cra_blocksize = SHA512_BLOCK_SIZE,
.cra_module = THIS_MODULE, .cra_module = THIS_MODULE,
} }

View File

@ -1,9 +1,3 @@
/* SPDX-License-Identifier: GPL-2.0 */ /* SPDX-License-Identifier: GPL-2.0 */
int sha512_arm_update(struct shash_desc *desc, const u8 *data,
unsigned int len);
int sha512_arm_finup(struct shash_desc *desc, const u8 *data,
unsigned int len, u8 *out);
extern struct shash_alg sha512_neon_algs[2]; extern struct shash_alg sha512_neon_algs[2];

View File

@ -1,8 +1,14 @@
/* SPDX-License-Identifier: GPL-2.0 */ /* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_SIMD_H
#define _ASM_SIMD_H
#include <linux/hardirq.h> #include <linux/compiler_attributes.h>
#include <linux/preempt.h>
#include <linux/types.h>
static __must_check inline bool may_use_simd(void) static __must_check inline bool may_use_simd(void)
{ {
return IS_ENABLED(CONFIG_KERNEL_MODE_NEON) && !in_hardirq(); return IS_ENABLED(CONFIG_KERNEL_MODE_NEON) && !in_hardirq();
} }
#endif /* _ASM_SIMD_H */

View File

@ -5,6 +5,8 @@
# Copyright (C) 1995-2000 Russell King # Copyright (C) 1995-2000 Russell King
# #
obj-y += crypto/
lib-y := changebit.o csumipv6.o csumpartial.o \ lib-y := changebit.o csumipv6.o csumpartial.o \
csumpartialcopy.o csumpartialcopyuser.o clearbit.o \ csumpartialcopy.o csumpartialcopyuser.o clearbit.o \
delay.o delay-loop.o findbit.o memchr.o memcpy.o \ delay.o delay-loop.o findbit.o memchr.o memcpy.o \

3
arch/arm/lib/crypto/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
# SPDX-License-Identifier: GPL-2.0-only
poly1305-core.S
sha256-core.S

View File

@ -0,0 +1,31 @@
# SPDX-License-Identifier: GPL-2.0-only
config CRYPTO_BLAKE2S_ARM
bool "Hash functions: BLAKE2s"
select CRYPTO_ARCH_HAVE_LIB_BLAKE2S
help
BLAKE2s cryptographic hash function (RFC 7693)
Architecture: arm
This is faster than the generic implementations of BLAKE2s and
BLAKE2b, but slower than the NEON implementation of BLAKE2b.
There is no NEON implementation of BLAKE2s, since NEON doesn't
really help with it.
config CRYPTO_CHACHA20_NEON
tristate
default CRYPTO_LIB_CHACHA
select CRYPTO_ARCH_HAVE_LIB_CHACHA
config CRYPTO_POLY1305_ARM
tristate
default CRYPTO_LIB_POLY1305
select CRYPTO_ARCH_HAVE_LIB_POLY1305
config CRYPTO_SHA256_ARM
tristate
depends on !CPU_V7M
default CRYPTO_LIB_SHA256
select CRYPTO_ARCH_HAVE_LIB_SHA256
select CRYPTO_ARCH_HAVE_LIB_SHA256_SIMD

View File

@ -0,0 +1,32 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_CRYPTO_BLAKE2S_ARM) += libblake2s-arm.o
libblake2s-arm-y := blake2s-core.o blake2s-glue.o
obj-$(CONFIG_CRYPTO_CHACHA20_NEON) += chacha-neon.o
chacha-neon-y := chacha-scalar-core.o chacha-glue.o
chacha-neon-$(CONFIG_KERNEL_MODE_NEON) += chacha-neon-core.o
obj-$(CONFIG_CRYPTO_POLY1305_ARM) += poly1305-arm.o
poly1305-arm-y := poly1305-core.o poly1305-glue.o
obj-$(CONFIG_CRYPTO_SHA256_ARM) += sha256-arm.o
sha256-arm-y := sha256.o sha256-core.o
sha256-arm-$(CONFIG_KERNEL_MODE_NEON) += sha256-ce.o
quiet_cmd_perl = PERL $@
cmd_perl = $(PERL) $(<) > $(@)
$(obj)/%-core.S: $(src)/%-armv4.pl
$(call cmd,perl)
clean-files += poly1305-core.S sha256-core.S
aflags-thumb2-$(CONFIG_THUMB2_KERNEL) := -U__thumb2__ -D__thumb2__=1
# massage the perlasm code a bit so we only get the NEON routine if we need it
poly1305-aflags-$(CONFIG_CPU_V7) := -U__LINUX_ARM_ARCH__ -D__LINUX_ARM_ARCH__=5
poly1305-aflags-$(CONFIG_KERNEL_MODE_NEON) := -U__LINUX_ARM_ARCH__ -D__LINUX_ARM_ARCH__=7
AFLAGS_poly1305-core.o += $(poly1305-aflags-y) $(aflags-thumb2-y)
AFLAGS_sha256-core.o += $(aflags-thumb2-y)

View File

@ -0,0 +1,138 @@
// SPDX-License-Identifier: GPL-2.0
/*
* ChaCha and HChaCha functions (ARM optimized)
*
* Copyright (C) 2016-2019 Linaro, Ltd. <ard.biesheuvel@linaro.org>
* Copyright (C) 2015 Martin Willi
*/
#include <crypto/chacha.h>
#include <crypto/internal/simd.h>
#include <linux/jump_label.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <asm/cputype.h>
#include <asm/hwcap.h>
#include <asm/neon.h>
#include <asm/simd.h>
asmlinkage void chacha_block_xor_neon(const struct chacha_state *state,
u8 *dst, const u8 *src, int nrounds);
asmlinkage void chacha_4block_xor_neon(const struct chacha_state *state,
u8 *dst, const u8 *src,
int nrounds, unsigned int nbytes);
asmlinkage void hchacha_block_arm(const struct chacha_state *state,
u32 out[HCHACHA_OUT_WORDS], int nrounds);
asmlinkage void hchacha_block_neon(const struct chacha_state *state,
u32 out[HCHACHA_OUT_WORDS], int nrounds);
asmlinkage void chacha_doarm(u8 *dst, const u8 *src, unsigned int bytes,
const struct chacha_state *state, int nrounds);
static __ro_after_init DEFINE_STATIC_KEY_FALSE(use_neon);
static inline bool neon_usable(void)
{
return static_branch_likely(&use_neon) && crypto_simd_usable();
}
static void chacha_doneon(struct chacha_state *state, u8 *dst, const u8 *src,
unsigned int bytes, int nrounds)
{
u8 buf[CHACHA_BLOCK_SIZE];
while (bytes > CHACHA_BLOCK_SIZE) {
unsigned int l = min(bytes, CHACHA_BLOCK_SIZE * 4U);
chacha_4block_xor_neon(state, dst, src, nrounds, l);
bytes -= l;
src += l;
dst += l;
state->x[12] += DIV_ROUND_UP(l, CHACHA_BLOCK_SIZE);
}
if (bytes) {
const u8 *s = src;
u8 *d = dst;
if (bytes != CHACHA_BLOCK_SIZE)
s = d = memcpy(buf, src, bytes);
chacha_block_xor_neon(state, d, s, nrounds);
if (d != dst)
memcpy(dst, buf, bytes);
state->x[12]++;
}
}
void hchacha_block_arch(const struct chacha_state *state,
u32 out[HCHACHA_OUT_WORDS], int nrounds)
{
if (!IS_ENABLED(CONFIG_KERNEL_MODE_NEON) || !neon_usable()) {
hchacha_block_arm(state, out, nrounds);
} else {
kernel_neon_begin();
hchacha_block_neon(state, out, nrounds);
kernel_neon_end();
}
}
EXPORT_SYMBOL(hchacha_block_arch);
void chacha_crypt_arch(struct chacha_state *state, u8 *dst, const u8 *src,
unsigned int bytes, int nrounds)
{
if (!IS_ENABLED(CONFIG_KERNEL_MODE_NEON) || !neon_usable() ||
bytes <= CHACHA_BLOCK_SIZE) {
chacha_doarm(dst, src, bytes, state, nrounds);
state->x[12] += DIV_ROUND_UP(bytes, CHACHA_BLOCK_SIZE);
return;
}
do {
unsigned int todo = min_t(unsigned int, bytes, SZ_4K);
kernel_neon_begin();
chacha_doneon(state, dst, src, todo, nrounds);
kernel_neon_end();
bytes -= todo;
src += todo;
dst += todo;
} while (bytes);
}
EXPORT_SYMBOL(chacha_crypt_arch);
bool chacha_is_arch_optimized(void)
{
/* We always can use at least the ARM scalar implementation. */
return true;
}
EXPORT_SYMBOL(chacha_is_arch_optimized);
static int __init chacha_arm_mod_init(void)
{
if (IS_ENABLED(CONFIG_KERNEL_MODE_NEON) && (elf_hwcap & HWCAP_NEON)) {
switch (read_cpuid_part()) {
case ARM_CPU_PART_CORTEX_A7:
case ARM_CPU_PART_CORTEX_A5:
/*
* The Cortex-A7 and Cortex-A5 do not perform well with
* the NEON implementation but do incredibly with the
* scalar one and use less power.
*/
break;
default:
static_branch_enable(&use_neon);
}
}
return 0;
}
subsys_initcall(chacha_arm_mod_init);
static void __exit chacha_arm_mod_exit(void)
{
}
module_exit(chacha_arm_mod_exit);
MODULE_DESCRIPTION("ChaCha and HChaCha functions (ARM optimized)");
MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
MODULE_LICENSE("GPL v2");

View File

@ -1,5 +1,5 @@
/* /*
* ChaCha/XChaCha NEON helper functions * ChaCha/HChaCha NEON helper functions
* *
* Copyright (C) 2016 Linaro, Ltd. <ard.biesheuvel@linaro.org> * Copyright (C) 2016 Linaro, Ltd. <ard.biesheuvel@linaro.org>
* *

View File

@ -367,7 +367,7 @@
/* /*
* void chacha_doarm(u8 *dst, const u8 *src, unsigned int bytes, * void chacha_doarm(u8 *dst, const u8 *src, unsigned int bytes,
* const u32 *state, int nrounds); * const struct chacha_state *state, int nrounds);
*/ */
ENTRY(chacha_doarm) ENTRY(chacha_doarm)
cmp r2, #0 // len == 0? cmp r2, #0 // len == 0?
@ -407,7 +407,8 @@ ENTRY(chacha_doarm)
ENDPROC(chacha_doarm) ENDPROC(chacha_doarm)
/* /*
* void hchacha_block_arm(const u32 state[16], u32 out[8], int nrounds); * void hchacha_block_arm(const struct chacha_state *state,
* u32 out[HCHACHA_OUT_WORDS], int nrounds);
*/ */
ENTRY(hchacha_block_arm) ENTRY(hchacha_block_arm)
push {r1,r4-r11,lr} push {r1,r4-r11,lr}

View File

@ -43,9 +43,9 @@ $code.=<<___;
#else #else
# define __ARM_ARCH__ __LINUX_ARM_ARCH__ # define __ARM_ARCH__ __LINUX_ARM_ARCH__
# define __ARM_MAX_ARCH__ __LINUX_ARM_ARCH__ # define __ARM_MAX_ARCH__ __LINUX_ARM_ARCH__
# define poly1305_init poly1305_init_arm # define poly1305_init poly1305_block_init_arch
# define poly1305_blocks poly1305_blocks_arm # define poly1305_blocks poly1305_blocks_arm
# define poly1305_emit poly1305_emit_arm # define poly1305_emit poly1305_emit_arch
.globl poly1305_blocks_neon .globl poly1305_blocks_neon
#endif #endif

View File

@ -0,0 +1,80 @@
// SPDX-License-Identifier: GPL-2.0
/*
* OpenSSL/Cryptogams accelerated Poly1305 transform for ARM
*
* Copyright (C) 2019 Linaro Ltd. <ard.biesheuvel@linaro.org>
*/
#include <asm/hwcap.h>
#include <asm/neon.h>
#include <crypto/internal/poly1305.h>
#include <linux/cpufeature.h>
#include <linux/jump_label.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/unaligned.h>
asmlinkage void poly1305_block_init_arch(
struct poly1305_block_state *state,
const u8 raw_key[POLY1305_BLOCK_SIZE]);
EXPORT_SYMBOL_GPL(poly1305_block_init_arch);
asmlinkage void poly1305_blocks_arm(struct poly1305_block_state *state,
const u8 *src, u32 len, u32 hibit);
asmlinkage void poly1305_blocks_neon(struct poly1305_block_state *state,
const u8 *src, u32 len, u32 hibit);
asmlinkage void poly1305_emit_arch(const struct poly1305_state *state,
u8 digest[POLY1305_DIGEST_SIZE],
const u32 nonce[4]);
EXPORT_SYMBOL_GPL(poly1305_emit_arch);
void __weak poly1305_blocks_neon(struct poly1305_block_state *state,
const u8 *src, u32 len, u32 hibit)
{
}
static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_neon);
void poly1305_blocks_arch(struct poly1305_block_state *state, const u8 *src,
unsigned int len, u32 padbit)
{
len = round_down(len, POLY1305_BLOCK_SIZE);
if (IS_ENABLED(CONFIG_KERNEL_MODE_NEON) &&
static_branch_likely(&have_neon)) {
do {
unsigned int todo = min_t(unsigned int, len, SZ_4K);
kernel_neon_begin();
poly1305_blocks_neon(state, src, todo, padbit);
kernel_neon_end();
len -= todo;
src += todo;
} while (len);
} else
poly1305_blocks_arm(state, src, len, padbit);
}
EXPORT_SYMBOL_GPL(poly1305_blocks_arch);
bool poly1305_is_arch_optimized(void)
{
/* We always can use at least the ARM scalar implementation. */
return true;
}
EXPORT_SYMBOL(poly1305_is_arch_optimized);
static int __init arm_poly1305_mod_init(void)
{
if (IS_ENABLED(CONFIG_KERNEL_MODE_NEON) &&
(elf_hwcap & HWCAP_NEON))
static_branch_enable(&have_neon);
return 0;
}
subsys_initcall(arm_poly1305_mod_init);
static void __exit arm_poly1305_mod_exit(void)
{
}
module_exit(arm_poly1305_mod_exit);
MODULE_DESCRIPTION("Accelerated Poly1305 transform for ARM");
MODULE_LICENSE("GPL v2");

View File

@ -204,18 +204,18 @@ K256:
.word 0 @ terminator .word 0 @ terminator
#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) #if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__)
.LOPENSSL_armcap: .LOPENSSL_armcap:
.word OPENSSL_armcap_P-sha256_block_data_order .word OPENSSL_armcap_P-sha256_blocks_arch
#endif #endif
.align 5 .align 5
.global sha256_block_data_order .global sha256_blocks_arch
.type sha256_block_data_order,%function .type sha256_blocks_arch,%function
sha256_block_data_order: sha256_blocks_arch:
.Lsha256_block_data_order: .Lsha256_blocks_arch:
#if __ARM_ARCH__<7 #if __ARM_ARCH__<7
sub r3,pc,#8 @ sha256_block_data_order sub r3,pc,#8 @ sha256_blocks_arch
#else #else
adr r3,.Lsha256_block_data_order adr r3,.Lsha256_blocks_arch
#endif #endif
#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) #if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__)
ldr r12,.LOPENSSL_armcap ldr r12,.LOPENSSL_armcap
@ -282,7 +282,7 @@ $code.=<<___;
moveq pc,lr @ be binary compatible with V4, yet moveq pc,lr @ be binary compatible with V4, yet
bx lr @ interoperable with Thumb ISA:-) bx lr @ interoperable with Thumb ISA:-)
#endif #endif
.size sha256_block_data_order,.-sha256_block_data_order .size sha256_blocks_arch,.-sha256_blocks_arch
___ ___
###################################################################### ######################################################################
# NEON stuff # NEON stuff
@ -470,8 +470,8 @@ sha256_block_data_order_neon:
stmdb sp!,{r4-r12,lr} stmdb sp!,{r4-r12,lr}
sub $H,sp,#16*4+16 sub $H,sp,#16*4+16
adr $Ktbl,.Lsha256_block_data_order adr $Ktbl,.Lsha256_blocks_arch
sub $Ktbl,$Ktbl,#.Lsha256_block_data_order-K256 sub $Ktbl,$Ktbl,#.Lsha256_blocks_arch-K256
bic $H,$H,#15 @ align for 128-bit stores bic $H,$H,#15 @ align for 128-bit stores
mov $t2,sp mov $t2,sp
mov sp,$H @ alloca mov sp,$H @ alloca

View File

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
/* /*
* sha2-ce-core.S - SHA-224/256 secure hash using ARMv8 Crypto Extensions * sha256-ce.S - SHA-224/256 secure hash using ARMv8 Crypto Extensions
* *
* Copyright (C) 2015 Linaro Ltd. * Copyright (C) 2015 Linaro Ltd.
* Author: Ard Biesheuvel <ard.biesheuvel@linaro.org> * Author: Ard Biesheuvel <ard.biesheuvel@linaro.org>
@ -67,10 +67,10 @@
.word 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 .word 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
/* /*
* void sha2_ce_transform(struct sha256_state *sst, u8 const *src, * void sha256_ce_transform(u32 state[SHA256_STATE_WORDS],
int blocks); * const u8 *data, size_t nblocks);
*/ */
ENTRY(sha2_ce_transform) ENTRY(sha256_ce_transform)
/* load state */ /* load state */
vld1.32 {dga-dgb}, [r0] vld1.32 {dga-dgb}, [r0]
@ -120,4 +120,4 @@ ENTRY(sha2_ce_transform)
/* store new state */ /* store new state */
vst1.32 {dga-dgb}, [r0] vst1.32 {dga-dgb}, [r0]
bx lr bx lr
ENDPROC(sha2_ce_transform) ENDPROC(sha256_ce_transform)

View File

@ -0,0 +1,64 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* SHA-256 optimized for ARM
*
* Copyright 2025 Google LLC
*/
#include <asm/neon.h>
#include <crypto/internal/sha2.h>
#include <linux/kernel.h>
#include <linux/module.h>
asmlinkage void sha256_blocks_arch(u32 state[SHA256_STATE_WORDS],
const u8 *data, size_t nblocks);
EXPORT_SYMBOL_GPL(sha256_blocks_arch);
asmlinkage void sha256_block_data_order_neon(u32 state[SHA256_STATE_WORDS],
const u8 *data, size_t nblocks);
asmlinkage void sha256_ce_transform(u32 state[SHA256_STATE_WORDS],
const u8 *data, size_t nblocks);
static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_neon);
static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_ce);
void sha256_blocks_simd(u32 state[SHA256_STATE_WORDS],
const u8 *data, size_t nblocks)
{
if (IS_ENABLED(CONFIG_KERNEL_MODE_NEON) &&
static_branch_likely(&have_neon)) {
kernel_neon_begin();
if (static_branch_likely(&have_ce))
sha256_ce_transform(state, data, nblocks);
else
sha256_block_data_order_neon(state, data, nblocks);
kernel_neon_end();
} else {
sha256_blocks_arch(state, data, nblocks);
}
}
EXPORT_SYMBOL_GPL(sha256_blocks_simd);
bool sha256_is_arch_optimized(void)
{
/* We always can use at least the ARM scalar implementation. */
return true;
}
EXPORT_SYMBOL_GPL(sha256_is_arch_optimized);
static int __init sha256_arm_mod_init(void)
{
if (IS_ENABLED(CONFIG_KERNEL_MODE_NEON) && (elf_hwcap & HWCAP_NEON)) {
static_branch_enable(&have_neon);
if (elf_hwcap2 & HWCAP2_SHA2)
static_branch_enable(&have_ce);
}
return 0;
}
subsys_initcall(sha256_arm_mod_init);
static void __exit sha256_arm_mod_exit(void)
{
}
module_exit(sha256_arm_mod_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SHA-256 optimized for ARM");

View File

@ -1730,14 +1730,13 @@ CONFIG_NLS_ISO8859_1=y
CONFIG_SECURITY=y CONFIG_SECURITY=y
CONFIG_CRYPTO_USER=y CONFIG_CRYPTO_USER=y
CONFIG_CRYPTO_CHACHA20=m CONFIG_CRYPTO_CHACHA20=m
CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_BENCHMARK=m
CONFIG_CRYPTO_ECHAINIV=y CONFIG_CRYPTO_ECHAINIV=y
CONFIG_CRYPTO_MICHAEL_MIC=m CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_ANSI_CPRNG=y CONFIG_CRYPTO_ANSI_CPRNG=y
CONFIG_CRYPTO_USER_API_RNG=m CONFIG_CRYPTO_USER_API_RNG=m
CONFIG_CRYPTO_GHASH_ARM64_CE=y CONFIG_CRYPTO_GHASH_ARM64_CE=y
CONFIG_CRYPTO_SHA1_ARM64_CE=y CONFIG_CRYPTO_SHA1_ARM64_CE=y
CONFIG_CRYPTO_SHA2_ARM64_CE=y
CONFIG_CRYPTO_SHA512_ARM64_CE=m CONFIG_CRYPTO_SHA512_ARM64_CE=m
CONFIG_CRYPTO_SHA3_ARM64=m CONFIG_CRYPTO_SHA3_ARM64=m
CONFIG_CRYPTO_SM3_ARM64_CE=m CONFIG_CRYPTO_SM3_ARM64_CE=m

View File

@ -25,18 +25,6 @@ config CRYPTO_NHPOLY1305_NEON
Architecture: arm64 using: Architecture: arm64 using:
- NEON (Advanced SIMD) extensions - NEON (Advanced SIMD) extensions
config CRYPTO_POLY1305_NEON
tristate
depends on KERNEL_MODE_NEON
select CRYPTO_HASH
select CRYPTO_ARCH_HAVE_LIB_POLY1305
default CRYPTO_LIB_POLY1305_INTERNAL
help
Poly1305 authenticator algorithm (RFC7539)
Architecture: arm64 using:
- NEON (Advanced SIMD) extensions
config CRYPTO_SHA1_ARM64_CE config CRYPTO_SHA1_ARM64_CE
tristate "Hash functions: SHA-1 (ARMv8 Crypto Extensions)" tristate "Hash functions: SHA-1 (ARMv8 Crypto Extensions)"
depends on KERNEL_MODE_NEON depends on KERNEL_MODE_NEON
@ -48,25 +36,6 @@ config CRYPTO_SHA1_ARM64_CE
Architecture: arm64 using: Architecture: arm64 using:
- ARMv8 Crypto Extensions - ARMv8 Crypto Extensions
config CRYPTO_SHA256_ARM64
tristate "Hash functions: SHA-224 and SHA-256"
select CRYPTO_HASH
help
SHA-224 and SHA-256 secure hash algorithms (FIPS 180)
Architecture: arm64
config CRYPTO_SHA2_ARM64_CE
tristate "Hash functions: SHA-224 and SHA-256 (ARMv8 Crypto Extensions)"
depends on KERNEL_MODE_NEON
select CRYPTO_HASH
select CRYPTO_SHA256_ARM64
help
SHA-224 and SHA-256 secure hash algorithms (FIPS 180)
Architecture: arm64 using:
- ARMv8 Crypto Extensions
config CRYPTO_SHA512_ARM64 config CRYPTO_SHA512_ARM64
tristate "Hash functions: SHA-384 and SHA-512" tristate "Hash functions: SHA-384 and SHA-512"
select CRYPTO_HASH select CRYPTO_HASH
@ -101,7 +70,7 @@ config CRYPTO_SM3_NEON
tristate "Hash functions: SM3 (NEON)" tristate "Hash functions: SM3 (NEON)"
depends on KERNEL_MODE_NEON depends on KERNEL_MODE_NEON
select CRYPTO_HASH select CRYPTO_HASH
select CRYPTO_SM3 select CRYPTO_LIB_SM3
help help
SM3 (ShangMi 3) secure hash function (OSCCA GM/T 0004-2012) SM3 (ShangMi 3) secure hash function (OSCCA GM/T 0004-2012)
@ -112,7 +81,7 @@ config CRYPTO_SM3_ARM64_CE
tristate "Hash functions: SM3 (ARMv8.2 Crypto Extensions)" tristate "Hash functions: SM3 (ARMv8.2 Crypto Extensions)"
depends on KERNEL_MODE_NEON depends on KERNEL_MODE_NEON
select CRYPTO_HASH select CRYPTO_HASH
select CRYPTO_SM3 select CRYPTO_LIB_SM3
help help
SM3 (ShangMi 3) secure hash function (OSCCA GM/T 0004-2012) SM3 (ShangMi 3) secure hash function (OSCCA GM/T 0004-2012)
@ -143,7 +112,7 @@ config CRYPTO_AES_ARM64
config CRYPTO_AES_ARM64_CE config CRYPTO_AES_ARM64_CE
tristate "Ciphers: AES (ARMv8 Crypto Extensions)" tristate "Ciphers: AES (ARMv8 Crypto Extensions)"
depends on ARM64 && KERNEL_MODE_NEON depends on KERNEL_MODE_NEON
select CRYPTO_ALGAPI select CRYPTO_ALGAPI
select CRYPTO_LIB_AES select CRYPTO_LIB_AES
help help
@ -186,20 +155,6 @@ config CRYPTO_AES_ARM64_NEON_BLK
Architecture: arm64 using: Architecture: arm64 using:
- NEON (Advanced SIMD) extensions - NEON (Advanced SIMD) extensions
config CRYPTO_CHACHA20_NEON
tristate
depends on KERNEL_MODE_NEON
select CRYPTO_SKCIPHER
select CRYPTO_LIB_CHACHA_GENERIC
select CRYPTO_ARCH_HAVE_LIB_CHACHA
default CRYPTO_LIB_CHACHA_INTERNAL
help
Length-preserving ciphers: ChaCha20, XChaCha20, and XChaCha12
stream cipher algorithms
Architecture: arm64 using:
- NEON (Advanced SIMD) extensions
config CRYPTO_AES_ARM64_BS config CRYPTO_AES_ARM64_BS
tristate "Ciphers: AES, modes: ECB/CBC/CTR/XCTR/XTS modes (bit-sliced NEON)" tristate "Ciphers: AES, modes: ECB/CBC/CTR/XCTR/XTS modes (bit-sliced NEON)"
depends on KERNEL_MODE_NEON depends on KERNEL_MODE_NEON
@ -267,7 +222,7 @@ config CRYPTO_SM4_ARM64_NEON_BLK
config CRYPTO_AES_ARM64_CE_CCM config CRYPTO_AES_ARM64_CE_CCM
tristate "AEAD cipher: AES in CCM mode (ARMv8 Crypto Extensions)" tristate "AEAD cipher: AES in CCM mode (ARMv8 Crypto Extensions)"
depends on ARM64 && KERNEL_MODE_NEON depends on KERNEL_MODE_NEON
select CRYPTO_ALGAPI select CRYPTO_ALGAPI
select CRYPTO_AES_ARM64_CE select CRYPTO_AES_ARM64_CE
select CRYPTO_AES_ARM64_CE_BLK select CRYPTO_AES_ARM64_CE_BLK

View File

@ -8,9 +8,6 @@
obj-$(CONFIG_CRYPTO_SHA1_ARM64_CE) += sha1-ce.o obj-$(CONFIG_CRYPTO_SHA1_ARM64_CE) += sha1-ce.o
sha1-ce-y := sha1-ce-glue.o sha1-ce-core.o sha1-ce-y := sha1-ce-glue.o sha1-ce-core.o
obj-$(CONFIG_CRYPTO_SHA2_ARM64_CE) += sha2-ce.o
sha2-ce-y := sha2-ce-glue.o sha2-ce-core.o
obj-$(CONFIG_CRYPTO_SHA512_ARM64_CE) += sha512-ce.o obj-$(CONFIG_CRYPTO_SHA512_ARM64_CE) += sha512-ce.o
sha512-ce-y := sha512-ce-glue.o sha512-ce-core.o sha512-ce-y := sha512-ce-glue.o sha512-ce-core.o
@ -56,19 +53,9 @@ aes-ce-blk-y := aes-glue-ce.o aes-ce.o
obj-$(CONFIG_CRYPTO_AES_ARM64_NEON_BLK) += aes-neon-blk.o obj-$(CONFIG_CRYPTO_AES_ARM64_NEON_BLK) += aes-neon-blk.o
aes-neon-blk-y := aes-glue-neon.o aes-neon.o aes-neon-blk-y := aes-glue-neon.o aes-neon.o
obj-$(CONFIG_CRYPTO_SHA256_ARM64) += sha256-arm64.o
sha256-arm64-y := sha256-glue.o sha256-core.o
obj-$(CONFIG_CRYPTO_SHA512_ARM64) += sha512-arm64.o obj-$(CONFIG_CRYPTO_SHA512_ARM64) += sha512-arm64.o
sha512-arm64-y := sha512-glue.o sha512-core.o sha512-arm64-y := sha512-glue.o sha512-core.o
obj-$(CONFIG_CRYPTO_CHACHA20_NEON) += chacha-neon.o
chacha-neon-y := chacha-neon-core.o chacha-neon-glue.o
obj-$(CONFIG_CRYPTO_POLY1305_NEON) += poly1305-neon.o
poly1305-neon-y := poly1305-core.o poly1305-glue.o
AFLAGS_poly1305-core.o += -Dpoly1305_init=poly1305_init_arm64
obj-$(CONFIG_CRYPTO_NHPOLY1305_NEON) += nhpoly1305-neon.o obj-$(CONFIG_CRYPTO_NHPOLY1305_NEON) += nhpoly1305-neon.o
nhpoly1305-neon-y := nh-neon-core.o nhpoly1305-neon-glue.o nhpoly1305-neon-y := nh-neon-core.o nhpoly1305-neon-glue.o
@ -81,10 +68,7 @@ aes-neon-bs-y := aes-neonbs-core.o aes-neonbs-glue.o
quiet_cmd_perlasm = PERLASM $@ quiet_cmd_perlasm = PERLASM $@
cmd_perlasm = $(PERL) $(<) void $(@) cmd_perlasm = $(PERL) $(<) void $(@)
$(obj)/%-core.S: $(src)/%-armv8.pl $(obj)/sha512-core.S: $(src)/../lib/crypto/sha2-armv8.pl
$(call cmd,perlasm) $(call cmd,perlasm)
$(obj)/sha256-core.S: $(src)/sha512-armv8.pl clean-files += sha512-core.S
$(call cmd,perlasm)
clean-files += poly1305-core.S sha256-core.S sha512-core.S

View File

@ -5,19 +5,20 @@
* Copyright (C) 2013 - 2017 Linaro Ltd <ard.biesheuvel@linaro.org> * Copyright (C) 2013 - 2017 Linaro Ltd <ard.biesheuvel@linaro.org>
*/ */
#include <asm/neon.h>
#include <asm/hwcap.h> #include <asm/hwcap.h>
#include <asm/simd.h> #include <asm/neon.h>
#include <crypto/aes.h> #include <crypto/aes.h>
#include <crypto/ctr.h> #include <crypto/ctr.h>
#include <crypto/sha2.h>
#include <crypto/internal/hash.h> #include <crypto/internal/hash.h>
#include <crypto/internal/simd.h>
#include <crypto/internal/skcipher.h> #include <crypto/internal/skcipher.h>
#include <crypto/scatterwalk.h> #include <crypto/scatterwalk.h>
#include <linux/module.h> #include <crypto/sha2.h>
#include <linux/cpufeature.h> #include <crypto/utils.h>
#include <crypto/xts.h> #include <crypto/xts.h>
#include <linux/cpufeature.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/string.h>
#include "aes-ce-setkey.h" #include "aes-ce-setkey.h"
@ -130,7 +131,6 @@ struct mac_tfm_ctx {
}; };
struct mac_desc_ctx { struct mac_desc_ctx {
unsigned int len;
u8 dg[AES_BLOCK_SIZE]; u8 dg[AES_BLOCK_SIZE];
}; };
@ -869,109 +869,64 @@ static int mac_init(struct shash_desc *desc)
struct mac_desc_ctx *ctx = shash_desc_ctx(desc); struct mac_desc_ctx *ctx = shash_desc_ctx(desc);
memset(ctx->dg, 0, AES_BLOCK_SIZE); memset(ctx->dg, 0, AES_BLOCK_SIZE);
ctx->len = 0;
return 0; return 0;
} }
static void mac_do_update(struct crypto_aes_ctx *ctx, u8 const in[], int blocks, static void mac_do_update(struct crypto_aes_ctx *ctx, u8 const in[], int blocks,
u8 dg[], int enc_before, int enc_after) u8 dg[], int enc_before)
{ {
int rounds = 6 + ctx->key_length / 4; int rounds = 6 + ctx->key_length / 4;
int rem;
if (crypto_simd_usable()) { do {
int rem; kernel_neon_begin();
rem = aes_mac_update(in, ctx->key_enc, rounds, blocks,
do { dg, enc_before, !enc_before);
kernel_neon_begin(); kernel_neon_end();
rem = aes_mac_update(in, ctx->key_enc, rounds, blocks, in += (blocks - rem) * AES_BLOCK_SIZE;
dg, enc_before, enc_after); blocks = rem;
kernel_neon_end(); } while (blocks);
in += (blocks - rem) * AES_BLOCK_SIZE;
blocks = rem;
enc_before = 0;
} while (blocks);
} else {
if (enc_before)
aes_encrypt(ctx, dg, dg);
while (blocks--) {
crypto_xor(dg, in, AES_BLOCK_SIZE);
in += AES_BLOCK_SIZE;
if (blocks || enc_after)
aes_encrypt(ctx, dg, dg);
}
}
} }
static int mac_update(struct shash_desc *desc, const u8 *p, unsigned int len) static int mac_update(struct shash_desc *desc, const u8 *p, unsigned int len)
{ {
struct mac_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm); struct mac_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm);
struct mac_desc_ctx *ctx = shash_desc_ctx(desc); struct mac_desc_ctx *ctx = shash_desc_ctx(desc);
int blocks = len / AES_BLOCK_SIZE;
while (len > 0) { len %= AES_BLOCK_SIZE;
unsigned int l; mac_do_update(&tctx->key, p, blocks, ctx->dg, 0);
return len;
if ((ctx->len % AES_BLOCK_SIZE) == 0 &&
(ctx->len + len) > AES_BLOCK_SIZE) {
int blocks = len / AES_BLOCK_SIZE;
len %= AES_BLOCK_SIZE;
mac_do_update(&tctx->key, p, blocks, ctx->dg,
(ctx->len != 0), (len != 0));
p += blocks * AES_BLOCK_SIZE;
if (!len) {
ctx->len = AES_BLOCK_SIZE;
break;
}
ctx->len = 0;
}
l = min(len, AES_BLOCK_SIZE - ctx->len);
if (l <= AES_BLOCK_SIZE) {
crypto_xor(ctx->dg + ctx->len, p, l);
ctx->len += l;
len -= l;
p += l;
}
}
return 0;
} }
static int cbcmac_final(struct shash_desc *desc, u8 *out) static int cbcmac_finup(struct shash_desc *desc, const u8 *src,
unsigned int len, u8 *out)
{ {
struct mac_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm); struct mac_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm);
struct mac_desc_ctx *ctx = shash_desc_ctx(desc); struct mac_desc_ctx *ctx = shash_desc_ctx(desc);
mac_do_update(&tctx->key, NULL, 0, ctx->dg, (ctx->len != 0), 0); if (len) {
crypto_xor(ctx->dg, src, len);
mac_do_update(&tctx->key, NULL, 0, ctx->dg, 1);
}
memcpy(out, ctx->dg, AES_BLOCK_SIZE); memcpy(out, ctx->dg, AES_BLOCK_SIZE);
return 0; return 0;
} }
static int cmac_final(struct shash_desc *desc, u8 *out) static int cmac_finup(struct shash_desc *desc, const u8 *src, unsigned int len,
u8 *out)
{ {
struct mac_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm); struct mac_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm);
struct mac_desc_ctx *ctx = shash_desc_ctx(desc); struct mac_desc_ctx *ctx = shash_desc_ctx(desc);
u8 *consts = tctx->consts; u8 *consts = tctx->consts;
if (ctx->len != AES_BLOCK_SIZE) { crypto_xor(ctx->dg, src, len);
ctx->dg[ctx->len] ^= 0x80; if (len != AES_BLOCK_SIZE) {
ctx->dg[len] ^= 0x80;
consts += AES_BLOCK_SIZE; consts += AES_BLOCK_SIZE;
} }
mac_do_update(&tctx->key, consts, 1, ctx->dg, 0);
mac_do_update(&tctx->key, consts, 1, ctx->dg, 0, 1);
memcpy(out, ctx->dg, AES_BLOCK_SIZE); memcpy(out, ctx->dg, AES_BLOCK_SIZE);
return 0; return 0;
} }
@ -979,6 +934,8 @@ static struct shash_alg mac_algs[] = { {
.base.cra_name = "cmac(aes)", .base.cra_name = "cmac(aes)",
.base.cra_driver_name = "cmac-aes-" MODE, .base.cra_driver_name = "cmac-aes-" MODE,
.base.cra_priority = PRIO, .base.cra_priority = PRIO,
.base.cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY |
CRYPTO_AHASH_ALG_FINAL_NONZERO,
.base.cra_blocksize = AES_BLOCK_SIZE, .base.cra_blocksize = AES_BLOCK_SIZE,
.base.cra_ctxsize = sizeof(struct mac_tfm_ctx) + .base.cra_ctxsize = sizeof(struct mac_tfm_ctx) +
2 * AES_BLOCK_SIZE, 2 * AES_BLOCK_SIZE,
@ -987,13 +944,15 @@ static struct shash_alg mac_algs[] = { {
.digestsize = AES_BLOCK_SIZE, .digestsize = AES_BLOCK_SIZE,
.init = mac_init, .init = mac_init,
.update = mac_update, .update = mac_update,
.final = cmac_final, .finup = cmac_finup,
.setkey = cmac_setkey, .setkey = cmac_setkey,
.descsize = sizeof(struct mac_desc_ctx), .descsize = sizeof(struct mac_desc_ctx),
}, { }, {
.base.cra_name = "xcbc(aes)", .base.cra_name = "xcbc(aes)",
.base.cra_driver_name = "xcbc-aes-" MODE, .base.cra_driver_name = "xcbc-aes-" MODE,
.base.cra_priority = PRIO, .base.cra_priority = PRIO,
.base.cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY |
CRYPTO_AHASH_ALG_FINAL_NONZERO,
.base.cra_blocksize = AES_BLOCK_SIZE, .base.cra_blocksize = AES_BLOCK_SIZE,
.base.cra_ctxsize = sizeof(struct mac_tfm_ctx) + .base.cra_ctxsize = sizeof(struct mac_tfm_ctx) +
2 * AES_BLOCK_SIZE, 2 * AES_BLOCK_SIZE,
@ -1002,21 +961,22 @@ static struct shash_alg mac_algs[] = { {
.digestsize = AES_BLOCK_SIZE, .digestsize = AES_BLOCK_SIZE,
.init = mac_init, .init = mac_init,
.update = mac_update, .update = mac_update,
.final = cmac_final, .finup = cmac_finup,
.setkey = xcbc_setkey, .setkey = xcbc_setkey,
.descsize = sizeof(struct mac_desc_ctx), .descsize = sizeof(struct mac_desc_ctx),
}, { }, {
.base.cra_name = "cbcmac(aes)", .base.cra_name = "cbcmac(aes)",
.base.cra_driver_name = "cbcmac-aes-" MODE, .base.cra_driver_name = "cbcmac-aes-" MODE,
.base.cra_priority = PRIO, .base.cra_priority = PRIO,
.base.cra_blocksize = 1, .base.cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY,
.base.cra_blocksize = AES_BLOCK_SIZE,
.base.cra_ctxsize = sizeof(struct mac_tfm_ctx), .base.cra_ctxsize = sizeof(struct mac_tfm_ctx),
.base.cra_module = THIS_MODULE, .base.cra_module = THIS_MODULE,
.digestsize = AES_BLOCK_SIZE, .digestsize = AES_BLOCK_SIZE,
.init = mac_init, .init = mac_init,
.update = mac_update, .update = mac_update,
.final = cbcmac_final, .finup = cbcmac_finup,
.setkey = cbcmac_setkey, .setkey = cbcmac_setkey,
.descsize = sizeof(struct mac_desc_ctx), .descsize = sizeof(struct mac_desc_ctx),
} }; } };

View File

@ -1,237 +0,0 @@
/*
* ARM NEON and scalar accelerated ChaCha and XChaCha stream ciphers,
* including ChaCha20 (RFC7539)
*
* Copyright (C) 2016 - 2017 Linaro, Ltd. <ard.biesheuvel@linaro.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Based on:
* ChaCha20 256-bit cipher algorithm, RFC7539, SIMD glue code
*
* Copyright (C) 2015 Martin Willi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <crypto/algapi.h>
#include <crypto/internal/chacha.h>
#include <crypto/internal/simd.h>
#include <crypto/internal/skcipher.h>
#include <linux/jump_label.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <asm/hwcap.h>
#include <asm/neon.h>
#include <asm/simd.h>
asmlinkage void chacha_block_xor_neon(u32 *state, u8 *dst, const u8 *src,
int nrounds);
asmlinkage void chacha_4block_xor_neon(u32 *state, u8 *dst, const u8 *src,
int nrounds, int bytes);
asmlinkage void hchacha_block_neon(const u32 *state, u32 *out, int nrounds);
static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_neon);
static void chacha_doneon(u32 *state, u8 *dst, const u8 *src,
int bytes, int nrounds)
{
while (bytes > 0) {
int l = min(bytes, CHACHA_BLOCK_SIZE * 5);
if (l <= CHACHA_BLOCK_SIZE) {
u8 buf[CHACHA_BLOCK_SIZE];
memcpy(buf, src, l);
chacha_block_xor_neon(state, buf, buf, nrounds);
memcpy(dst, buf, l);
state[12] += 1;
break;
}
chacha_4block_xor_neon(state, dst, src, nrounds, l);
bytes -= l;
src += l;
dst += l;
state[12] += DIV_ROUND_UP(l, CHACHA_BLOCK_SIZE);
}
}
void hchacha_block_arch(const u32 *state, u32 *stream, int nrounds)
{
if (!static_branch_likely(&have_neon) || !crypto_simd_usable()) {
hchacha_block_generic(state, stream, nrounds);
} else {
kernel_neon_begin();
hchacha_block_neon(state, stream, nrounds);
kernel_neon_end();
}
}
EXPORT_SYMBOL(hchacha_block_arch);
void chacha_crypt_arch(u32 *state, u8 *dst, const u8 *src, unsigned int bytes,
int nrounds)
{
if (!static_branch_likely(&have_neon) || bytes <= CHACHA_BLOCK_SIZE ||
!crypto_simd_usable())
return chacha_crypt_generic(state, dst, src, bytes, nrounds);
do {
unsigned int todo = min_t(unsigned int, bytes, SZ_4K);
kernel_neon_begin();
chacha_doneon(state, dst, src, todo, nrounds);
kernel_neon_end();
bytes -= todo;
src += todo;
dst += todo;
} while (bytes);
}
EXPORT_SYMBOL(chacha_crypt_arch);
static int chacha_neon_stream_xor(struct skcipher_request *req,
const struct chacha_ctx *ctx, const u8 *iv)
{
struct skcipher_walk walk;
u32 state[16];
int err;
err = skcipher_walk_virt(&walk, req, false);
chacha_init(state, ctx->key, iv);
while (walk.nbytes > 0) {
unsigned int nbytes = walk.nbytes;
if (nbytes < walk.total)
nbytes = rounddown(nbytes, walk.stride);
if (!static_branch_likely(&have_neon) ||
!crypto_simd_usable()) {
chacha_crypt_generic(state, walk.dst.virt.addr,
walk.src.virt.addr, nbytes,
ctx->nrounds);
} else {
kernel_neon_begin();
chacha_doneon(state, walk.dst.virt.addr,
walk.src.virt.addr, nbytes, ctx->nrounds);
kernel_neon_end();
}
err = skcipher_walk_done(&walk, walk.nbytes - nbytes);
}
return err;
}
static int chacha_neon(struct skcipher_request *req)
{
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
struct chacha_ctx *ctx = crypto_skcipher_ctx(tfm);
return chacha_neon_stream_xor(req, ctx, req->iv);
}
static int xchacha_neon(struct skcipher_request *req)
{
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
struct chacha_ctx *ctx = crypto_skcipher_ctx(tfm);
struct chacha_ctx subctx;
u32 state[16];
u8 real_iv[16];
chacha_init(state, ctx->key, req->iv);
hchacha_block_arch(state, subctx.key, ctx->nrounds);
subctx.nrounds = ctx->nrounds;
memcpy(&real_iv[0], req->iv + 24, 8);
memcpy(&real_iv[8], req->iv + 16, 8);
return chacha_neon_stream_xor(req, &subctx, real_iv);
}
static struct skcipher_alg algs[] = {
{
.base.cra_name = "chacha20",
.base.cra_driver_name = "chacha20-neon",
.base.cra_priority = 300,
.base.cra_blocksize = 1,
.base.cra_ctxsize = sizeof(struct chacha_ctx),
.base.cra_module = THIS_MODULE,
.min_keysize = CHACHA_KEY_SIZE,
.max_keysize = CHACHA_KEY_SIZE,
.ivsize = CHACHA_IV_SIZE,
.chunksize = CHACHA_BLOCK_SIZE,
.walksize = 5 * CHACHA_BLOCK_SIZE,
.setkey = chacha20_setkey,
.encrypt = chacha_neon,
.decrypt = chacha_neon,
}, {
.base.cra_name = "xchacha20",
.base.cra_driver_name = "xchacha20-neon",
.base.cra_priority = 300,
.base.cra_blocksize = 1,
.base.cra_ctxsize = sizeof(struct chacha_ctx),
.base.cra_module = THIS_MODULE,
.min_keysize = CHACHA_KEY_SIZE,
.max_keysize = CHACHA_KEY_SIZE,
.ivsize = XCHACHA_IV_SIZE,
.chunksize = CHACHA_BLOCK_SIZE,
.walksize = 5 * CHACHA_BLOCK_SIZE,
.setkey = chacha20_setkey,
.encrypt = xchacha_neon,
.decrypt = xchacha_neon,
}, {
.base.cra_name = "xchacha12",
.base.cra_driver_name = "xchacha12-neon",
.base.cra_priority = 300,
.base.cra_blocksize = 1,
.base.cra_ctxsize = sizeof(struct chacha_ctx),
.base.cra_module = THIS_MODULE,
.min_keysize = CHACHA_KEY_SIZE,
.max_keysize = CHACHA_KEY_SIZE,
.ivsize = XCHACHA_IV_SIZE,
.chunksize = CHACHA_BLOCK_SIZE,
.walksize = 5 * CHACHA_BLOCK_SIZE,
.setkey = chacha12_setkey,
.encrypt = xchacha_neon,
.decrypt = xchacha_neon,
}
};
static int __init chacha_simd_mod_init(void)
{
if (!cpu_have_named_feature(ASIMD))
return 0;
static_branch_enable(&have_neon);
return IS_REACHABLE(CONFIG_CRYPTO_SKCIPHER) ?
crypto_register_skciphers(algs, ARRAY_SIZE(algs)) : 0;
}
static void __exit chacha_simd_mod_fini(void)
{
if (IS_REACHABLE(CONFIG_CRYPTO_SKCIPHER) && cpu_have_named_feature(ASIMD))
crypto_unregister_skciphers(algs, ARRAY_SIZE(algs));
}
module_init(chacha_simd_mod_init);
module_exit(chacha_simd_mod_fini);
MODULE_DESCRIPTION("ChaCha and XChaCha stream ciphers (NEON accelerated)");
MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS_CRYPTO("chacha20");
MODULE_ALIAS_CRYPTO("chacha20-neon");
MODULE_ALIAS_CRYPTO("xchacha20");
MODULE_ALIAS_CRYPTO("xchacha20-neon");
MODULE_ALIAS_CRYPTO("xchacha12");
MODULE_ALIAS_CRYPTO("xchacha12-neon");

View File

@ -6,30 +6,27 @@
*/ */
#include <asm/neon.h> #include <asm/neon.h>
#include <asm/simd.h>
#include <linux/unaligned.h>
#include <crypto/aes.h> #include <crypto/aes.h>
#include <crypto/gcm.h>
#include <crypto/algapi.h>
#include <crypto/b128ops.h> #include <crypto/b128ops.h>
#include <crypto/gcm.h>
#include <crypto/ghash.h>
#include <crypto/gf128mul.h> #include <crypto/gf128mul.h>
#include <crypto/internal/aead.h> #include <crypto/internal/aead.h>
#include <crypto/internal/hash.h> #include <crypto/internal/hash.h>
#include <crypto/internal/simd.h>
#include <crypto/internal/skcipher.h> #include <crypto/internal/skcipher.h>
#include <crypto/scatterwalk.h> #include <crypto/scatterwalk.h>
#include <linux/cpufeature.h> #include <linux/cpufeature.h>
#include <linux/crypto.h> #include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/string.h>
#include <linux/unaligned.h>
MODULE_DESCRIPTION("GHASH and AES-GCM using ARMv8 Crypto Extensions"); MODULE_DESCRIPTION("GHASH and AES-GCM using ARMv8 Crypto Extensions");
MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>"); MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_ALIAS_CRYPTO("ghash"); MODULE_ALIAS_CRYPTO("ghash");
#define GHASH_BLOCK_SIZE 16
#define GHASH_DIGEST_SIZE 16
#define RFC4106_NONCE_SIZE 4 #define RFC4106_NONCE_SIZE 4
struct ghash_key { struct ghash_key {
@ -37,10 +34,8 @@ struct ghash_key {
u64 h[][2]; u64 h[][2];
}; };
struct ghash_desc_ctx { struct arm_ghash_desc_ctx {
u64 digest[GHASH_DIGEST_SIZE/sizeof(u64)]; u64 digest[GHASH_DIGEST_SIZE/sizeof(u64)];
u8 buf[GHASH_BLOCK_SIZE];
u32 count;
}; };
struct gcm_aes_ctx { struct gcm_aes_ctx {
@ -65,36 +60,12 @@ asmlinkage int pmull_gcm_decrypt(int bytes, u8 dst[], const u8 src[],
static int ghash_init(struct shash_desc *desc) static int ghash_init(struct shash_desc *desc)
{ {
struct ghash_desc_ctx *ctx = shash_desc_ctx(desc); struct arm_ghash_desc_ctx *ctx = shash_desc_ctx(desc);
*ctx = (struct ghash_desc_ctx){}; *ctx = (struct arm_ghash_desc_ctx){};
return 0; return 0;
} }
static void ghash_do_update(int blocks, u64 dg[], const char *src,
struct ghash_key *key, const char *head)
{
be128 dst = { cpu_to_be64(dg[1]), cpu_to_be64(dg[0]) };
do {
const u8 *in = src;
if (head) {
in = head;
blocks++;
head = NULL;
} else {
src += GHASH_BLOCK_SIZE;
}
crypto_xor((u8 *)&dst, in, GHASH_BLOCK_SIZE);
gf128mul_lle(&dst, &key->k);
} while (--blocks);
dg[0] = be64_to_cpu(dst.b);
dg[1] = be64_to_cpu(dst.a);
}
static __always_inline static __always_inline
void ghash_do_simd_update(int blocks, u64 dg[], const char *src, void ghash_do_simd_update(int blocks, u64 dg[], const char *src,
struct ghash_key *key, const char *head, struct ghash_key *key, const char *head,
@ -103,13 +74,9 @@ void ghash_do_simd_update(int blocks, u64 dg[], const char *src,
u64 const h[][2], u64 const h[][2],
const char *head)) const char *head))
{ {
if (likely(crypto_simd_usable())) { kernel_neon_begin();
kernel_neon_begin(); simd_update(blocks, dg, src, key->h, head);
simd_update(blocks, dg, src, key->h, head); kernel_neon_end();
kernel_neon_end();
} else {
ghash_do_update(blocks, dg, src, key, head);
}
} }
/* avoid hogging the CPU for too long */ /* avoid hogging the CPU for too long */
@ -118,63 +85,61 @@ void ghash_do_simd_update(int blocks, u64 dg[], const char *src,
static int ghash_update(struct shash_desc *desc, const u8 *src, static int ghash_update(struct shash_desc *desc, const u8 *src,
unsigned int len) unsigned int len)
{ {
struct ghash_desc_ctx *ctx = shash_desc_ctx(desc); struct arm_ghash_desc_ctx *ctx = shash_desc_ctx(desc);
unsigned int partial = ctx->count % GHASH_BLOCK_SIZE; struct ghash_key *key = crypto_shash_ctx(desc->tfm);
int blocks;
ctx->count += len; blocks = len / GHASH_BLOCK_SIZE;
len -= blocks * GHASH_BLOCK_SIZE;
if ((partial + len) >= GHASH_BLOCK_SIZE) { do {
struct ghash_key *key = crypto_shash_ctx(desc->tfm); int chunk = min(blocks, MAX_BLOCKS);
int blocks;
if (partial) { ghash_do_simd_update(chunk, ctx->digest, src, key, NULL,
int p = GHASH_BLOCK_SIZE - partial; pmull_ghash_update_p8);
blocks -= chunk;
src += chunk * GHASH_BLOCK_SIZE;
} while (unlikely(blocks > 0));
return len;
}
memcpy(ctx->buf + partial, src, p); static int ghash_export(struct shash_desc *desc, void *out)
src += p; {
len -= p; struct arm_ghash_desc_ctx *ctx = shash_desc_ctx(desc);
} u8 *dst = out;
blocks = len / GHASH_BLOCK_SIZE; put_unaligned_be64(ctx->digest[1], dst);
len %= GHASH_BLOCK_SIZE; put_unaligned_be64(ctx->digest[0], dst + 8);
do {
int chunk = min(blocks, MAX_BLOCKS);
ghash_do_simd_update(chunk, ctx->digest, src, key,
partial ? ctx->buf : NULL,
pmull_ghash_update_p8);
blocks -= chunk;
src += chunk * GHASH_BLOCK_SIZE;
partial = 0;
} while (unlikely(blocks > 0));
}
if (len)
memcpy(ctx->buf + partial, src, len);
return 0; return 0;
} }
static int ghash_final(struct shash_desc *desc, u8 *dst) static int ghash_import(struct shash_desc *desc, const void *in)
{ {
struct ghash_desc_ctx *ctx = shash_desc_ctx(desc); struct arm_ghash_desc_ctx *ctx = shash_desc_ctx(desc);
unsigned int partial = ctx->count % GHASH_BLOCK_SIZE; const u8 *src = in;
if (partial) { ctx->digest[1] = get_unaligned_be64(src);
struct ghash_key *key = crypto_shash_ctx(desc->tfm); ctx->digest[0] = get_unaligned_be64(src + 8);
memset(ctx->buf + partial, 0, GHASH_BLOCK_SIZE - partial);
ghash_do_simd_update(1, ctx->digest, ctx->buf, key, NULL,
pmull_ghash_update_p8);
}
put_unaligned_be64(ctx->digest[1], dst);
put_unaligned_be64(ctx->digest[0], dst + 8);
memzero_explicit(ctx, sizeof(*ctx));
return 0; return 0;
} }
static int ghash_finup(struct shash_desc *desc, const u8 *src,
unsigned int len, u8 *dst)
{
struct arm_ghash_desc_ctx *ctx = shash_desc_ctx(desc);
struct ghash_key *key = crypto_shash_ctx(desc->tfm);
if (len) {
u8 buf[GHASH_BLOCK_SIZE] = {};
memcpy(buf, src, len);
ghash_do_simd_update(1, ctx->digest, src, key, NULL,
pmull_ghash_update_p8);
memzero_explicit(buf, sizeof(buf));
}
return ghash_export(desc, dst);
}
static void ghash_reflect(u64 h[], const be128 *k) static void ghash_reflect(u64 h[], const be128 *k)
{ {
u64 carry = be64_to_cpu(k->a) & BIT(63) ? 1 : 0; u64 carry = be64_to_cpu(k->a) & BIT(63) ? 1 : 0;
@ -205,6 +170,7 @@ static struct shash_alg ghash_alg = {
.base.cra_name = "ghash", .base.cra_name = "ghash",
.base.cra_driver_name = "ghash-neon", .base.cra_driver_name = "ghash-neon",
.base.cra_priority = 150, .base.cra_priority = 150,
.base.cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY,
.base.cra_blocksize = GHASH_BLOCK_SIZE, .base.cra_blocksize = GHASH_BLOCK_SIZE,
.base.cra_ctxsize = sizeof(struct ghash_key) + sizeof(u64[2]), .base.cra_ctxsize = sizeof(struct ghash_key) + sizeof(u64[2]),
.base.cra_module = THIS_MODULE, .base.cra_module = THIS_MODULE,
@ -212,9 +178,12 @@ static struct shash_alg ghash_alg = {
.digestsize = GHASH_DIGEST_SIZE, .digestsize = GHASH_DIGEST_SIZE,
.init = ghash_init, .init = ghash_init,
.update = ghash_update, .update = ghash_update,
.final = ghash_final, .finup = ghash_finup,
.setkey = ghash_setkey, .setkey = ghash_setkey,
.descsize = sizeof(struct ghash_desc_ctx), .export = ghash_export,
.import = ghash_import,
.descsize = sizeof(struct arm_ghash_desc_ctx),
.statesize = sizeof(struct ghash_desc_ctx),
}; };
static int num_rounds(struct crypto_aes_ctx *ctx) static int num_rounds(struct crypto_aes_ctx *ctx)

View File

@ -1,232 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* OpenSSL/Cryptogams accelerated Poly1305 transform for arm64
*
* Copyright (C) 2019 Linaro Ltd. <ard.biesheuvel@linaro.org>
*/
#include <asm/hwcap.h>
#include <asm/neon.h>
#include <asm/simd.h>
#include <linux/unaligned.h>
#include <crypto/algapi.h>
#include <crypto/internal/hash.h>
#include <crypto/internal/poly1305.h>
#include <crypto/internal/simd.h>
#include <linux/cpufeature.h>
#include <linux/crypto.h>
#include <linux/jump_label.h>
#include <linux/module.h>
asmlinkage void poly1305_init_arm64(void *state, const u8 *key);
asmlinkage void poly1305_blocks(void *state, const u8 *src, u32 len, u32 hibit);
asmlinkage void poly1305_blocks_neon(void *state, const u8 *src, u32 len, u32 hibit);
asmlinkage void poly1305_emit(void *state, u8 *digest, const u32 *nonce);
static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_neon);
void poly1305_init_arch(struct poly1305_desc_ctx *dctx, const u8 key[POLY1305_KEY_SIZE])
{
poly1305_init_arm64(&dctx->h, key);
dctx->s[0] = get_unaligned_le32(key + 16);
dctx->s[1] = get_unaligned_le32(key + 20);
dctx->s[2] = get_unaligned_le32(key + 24);
dctx->s[3] = get_unaligned_le32(key + 28);
dctx->buflen = 0;
}
EXPORT_SYMBOL(poly1305_init_arch);
static int neon_poly1305_init(struct shash_desc *desc)
{
struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc);
dctx->buflen = 0;
dctx->rset = 0;
dctx->sset = false;
return 0;
}
static void neon_poly1305_blocks(struct poly1305_desc_ctx *dctx, const u8 *src,
u32 len, u32 hibit, bool do_neon)
{
if (unlikely(!dctx->sset)) {
if (!dctx->rset) {
poly1305_init_arm64(&dctx->h, src);
src += POLY1305_BLOCK_SIZE;
len -= POLY1305_BLOCK_SIZE;
dctx->rset = 1;
}
if (len >= POLY1305_BLOCK_SIZE) {
dctx->s[0] = get_unaligned_le32(src + 0);
dctx->s[1] = get_unaligned_le32(src + 4);
dctx->s[2] = get_unaligned_le32(src + 8);
dctx->s[3] = get_unaligned_le32(src + 12);
src += POLY1305_BLOCK_SIZE;
len -= POLY1305_BLOCK_SIZE;
dctx->sset = true;
}
if (len < POLY1305_BLOCK_SIZE)
return;
}
len &= ~(POLY1305_BLOCK_SIZE - 1);
if (static_branch_likely(&have_neon) && likely(do_neon))
poly1305_blocks_neon(&dctx->h, src, len, hibit);
else
poly1305_blocks(&dctx->h, src, len, hibit);
}
static void neon_poly1305_do_update(struct poly1305_desc_ctx *dctx,
const u8 *src, u32 len, bool do_neon)
{
if (unlikely(dctx->buflen)) {
u32 bytes = min(len, POLY1305_BLOCK_SIZE - dctx->buflen);
memcpy(dctx->buf + dctx->buflen, src, bytes);
src += bytes;
len -= bytes;
dctx->buflen += bytes;
if (dctx->buflen == POLY1305_BLOCK_SIZE) {
neon_poly1305_blocks(dctx, dctx->buf,
POLY1305_BLOCK_SIZE, 1, false);
dctx->buflen = 0;
}
}
if (likely(len >= POLY1305_BLOCK_SIZE)) {
neon_poly1305_blocks(dctx, src, len, 1, do_neon);
src += round_down(len, POLY1305_BLOCK_SIZE);
len %= POLY1305_BLOCK_SIZE;
}
if (unlikely(len)) {
dctx->buflen = len;
memcpy(dctx->buf, src, len);
}
}
static int neon_poly1305_update(struct shash_desc *desc,
const u8 *src, unsigned int srclen)
{
bool do_neon = crypto_simd_usable() && srclen > 128;
struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc);
if (static_branch_likely(&have_neon) && do_neon)
kernel_neon_begin();
neon_poly1305_do_update(dctx, src, srclen, do_neon);
if (static_branch_likely(&have_neon) && do_neon)
kernel_neon_end();
return 0;
}
void poly1305_update_arch(struct poly1305_desc_ctx *dctx, const u8 *src,
unsigned int nbytes)
{
if (unlikely(dctx->buflen)) {
u32 bytes = min(nbytes, POLY1305_BLOCK_SIZE - dctx->buflen);
memcpy(dctx->buf + dctx->buflen, src, bytes);
src += bytes;
nbytes -= bytes;
dctx->buflen += bytes;
if (dctx->buflen == POLY1305_BLOCK_SIZE) {
poly1305_blocks(&dctx->h, dctx->buf, POLY1305_BLOCK_SIZE, 1);
dctx->buflen = 0;
}
}
if (likely(nbytes >= POLY1305_BLOCK_SIZE)) {
unsigned int len = round_down(nbytes, POLY1305_BLOCK_SIZE);
if (static_branch_likely(&have_neon) && crypto_simd_usable()) {
do {
unsigned int todo = min_t(unsigned int, len, SZ_4K);
kernel_neon_begin();
poly1305_blocks_neon(&dctx->h, src, todo, 1);
kernel_neon_end();
len -= todo;
src += todo;
} while (len);
} else {
poly1305_blocks(&dctx->h, src, len, 1);
src += len;
}
nbytes %= POLY1305_BLOCK_SIZE;
}
if (unlikely(nbytes)) {
dctx->buflen = nbytes;
memcpy(dctx->buf, src, nbytes);
}
}
EXPORT_SYMBOL(poly1305_update_arch);
void poly1305_final_arch(struct poly1305_desc_ctx *dctx, u8 *dst)
{
if (unlikely(dctx->buflen)) {
dctx->buf[dctx->buflen++] = 1;
memset(dctx->buf + dctx->buflen, 0,
POLY1305_BLOCK_SIZE - dctx->buflen);
poly1305_blocks(&dctx->h, dctx->buf, POLY1305_BLOCK_SIZE, 0);
}
poly1305_emit(&dctx->h, dst, dctx->s);
memzero_explicit(dctx, sizeof(*dctx));
}
EXPORT_SYMBOL(poly1305_final_arch);
static int neon_poly1305_final(struct shash_desc *desc, u8 *dst)
{
struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc);
if (unlikely(!dctx->sset))
return -ENOKEY;
poly1305_final_arch(dctx, dst);
return 0;
}
static struct shash_alg neon_poly1305_alg = {
.init = neon_poly1305_init,
.update = neon_poly1305_update,
.final = neon_poly1305_final,
.digestsize = POLY1305_DIGEST_SIZE,
.descsize = sizeof(struct poly1305_desc_ctx),
.base.cra_name = "poly1305",
.base.cra_driver_name = "poly1305-neon",
.base.cra_priority = 200,
.base.cra_blocksize = POLY1305_BLOCK_SIZE,
.base.cra_module = THIS_MODULE,
};
static int __init neon_poly1305_mod_init(void)
{
if (!cpu_have_named_feature(ASIMD))
return 0;
static_branch_enable(&have_neon);
return IS_REACHABLE(CONFIG_CRYPTO_HASH) ?
crypto_register_shash(&neon_poly1305_alg) : 0;
}
static void __exit neon_poly1305_mod_exit(void)
{
if (IS_REACHABLE(CONFIG_CRYPTO_HASH) && cpu_have_named_feature(ASIMD))
crypto_unregister_shash(&neon_poly1305_alg);
}
module_init(neon_poly1305_mod_init);
module_exit(neon_poly1305_mod_exit);
MODULE_DESCRIPTION("Poly1305 transform using NEON instructions");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS_CRYPTO("poly1305");
MODULE_ALIAS_CRYPTO("poly1305-neon");

View File

@ -15,17 +15,15 @@
* ARMv8 Crypto Extensions instructions to implement the finite field operations. * ARMv8 Crypto Extensions instructions to implement the finite field operations.
*/ */
#include <crypto/algapi.h> #include <asm/neon.h>
#include <crypto/internal/hash.h> #include <crypto/internal/hash.h>
#include <crypto/internal/simd.h>
#include <crypto/polyval.h> #include <crypto/polyval.h>
#include <linux/crypto.h> #include <crypto/utils.h>
#include <linux/init.h> #include <linux/cpufeature.h>
#include <linux/errno.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/cpufeature.h> #include <linux/string.h>
#include <asm/neon.h>
#include <asm/simd.h>
#define NUM_KEY_POWERS 8 #define NUM_KEY_POWERS 8
@ -38,7 +36,6 @@ struct polyval_tfm_ctx {
struct polyval_desc_ctx { struct polyval_desc_ctx {
u8 buffer[POLYVAL_BLOCK_SIZE]; u8 buffer[POLYVAL_BLOCK_SIZE];
u32 bytes;
}; };
asmlinkage void pmull_polyval_update(const struct polyval_tfm_ctx *keys, asmlinkage void pmull_polyval_update(const struct polyval_tfm_ctx *keys,
@ -48,25 +45,16 @@ asmlinkage void pmull_polyval_mul(u8 *op1, const u8 *op2);
static void internal_polyval_update(const struct polyval_tfm_ctx *keys, static void internal_polyval_update(const struct polyval_tfm_ctx *keys,
const u8 *in, size_t nblocks, u8 *accumulator) const u8 *in, size_t nblocks, u8 *accumulator)
{ {
if (likely(crypto_simd_usable())) { kernel_neon_begin();
kernel_neon_begin(); pmull_polyval_update(keys, in, nblocks, accumulator);
pmull_polyval_update(keys, in, nblocks, accumulator); kernel_neon_end();
kernel_neon_end();
} else {
polyval_update_non4k(keys->key_powers[NUM_KEY_POWERS-1], in,
nblocks, accumulator);
}
} }
static void internal_polyval_mul(u8 *op1, const u8 *op2) static void internal_polyval_mul(u8 *op1, const u8 *op2)
{ {
if (likely(crypto_simd_usable())) { kernel_neon_begin();
kernel_neon_begin(); pmull_polyval_mul(op1, op2);
pmull_polyval_mul(op1, op2); kernel_neon_end();
kernel_neon_end();
} else {
polyval_mul_non4k(op1, op2);
}
} }
static int polyval_arm64_setkey(struct crypto_shash *tfm, static int polyval_arm64_setkey(struct crypto_shash *tfm,
@ -103,49 +91,27 @@ static int polyval_arm64_update(struct shash_desc *desc,
{ {
struct polyval_desc_ctx *dctx = shash_desc_ctx(desc); struct polyval_desc_ctx *dctx = shash_desc_ctx(desc);
const struct polyval_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm); const struct polyval_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm);
u8 *pos;
unsigned int nblocks; unsigned int nblocks;
unsigned int n;
if (dctx->bytes) { do {
n = min(srclen, dctx->bytes);
pos = dctx->buffer + POLYVAL_BLOCK_SIZE - dctx->bytes;
dctx->bytes -= n;
srclen -= n;
while (n--)
*pos++ ^= *src++;
if (!dctx->bytes)
internal_polyval_mul(dctx->buffer,
tctx->key_powers[NUM_KEY_POWERS-1]);
}
while (srclen >= POLYVAL_BLOCK_SIZE) {
/* allow rescheduling every 4K bytes */ /* allow rescheduling every 4K bytes */
nblocks = min(srclen, 4096U) / POLYVAL_BLOCK_SIZE; nblocks = min(srclen, 4096U) / POLYVAL_BLOCK_SIZE;
internal_polyval_update(tctx, src, nblocks, dctx->buffer); internal_polyval_update(tctx, src, nblocks, dctx->buffer);
srclen -= nblocks * POLYVAL_BLOCK_SIZE; srclen -= nblocks * POLYVAL_BLOCK_SIZE;
src += nblocks * POLYVAL_BLOCK_SIZE; src += nblocks * POLYVAL_BLOCK_SIZE;
} } while (srclen >= POLYVAL_BLOCK_SIZE);
if (srclen) { return srclen;
dctx->bytes = POLYVAL_BLOCK_SIZE - srclen;
pos = dctx->buffer;
while (srclen--)
*pos++ ^= *src++;
}
return 0;
} }
static int polyval_arm64_final(struct shash_desc *desc, u8 *dst) static int polyval_arm64_finup(struct shash_desc *desc, const u8 *src,
unsigned int len, u8 *dst)
{ {
struct polyval_desc_ctx *dctx = shash_desc_ctx(desc); struct polyval_desc_ctx *dctx = shash_desc_ctx(desc);
const struct polyval_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm); const struct polyval_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm);
if (dctx->bytes) { if (len) {
crypto_xor(dctx->buffer, src, len);
internal_polyval_mul(dctx->buffer, internal_polyval_mul(dctx->buffer,
tctx->key_powers[NUM_KEY_POWERS-1]); tctx->key_powers[NUM_KEY_POWERS-1]);
} }
@ -159,13 +125,14 @@ static struct shash_alg polyval_alg = {
.digestsize = POLYVAL_DIGEST_SIZE, .digestsize = POLYVAL_DIGEST_SIZE,
.init = polyval_arm64_init, .init = polyval_arm64_init,
.update = polyval_arm64_update, .update = polyval_arm64_update,
.final = polyval_arm64_final, .finup = polyval_arm64_finup,
.setkey = polyval_arm64_setkey, .setkey = polyval_arm64_setkey,
.descsize = sizeof(struct polyval_desc_ctx), .descsize = sizeof(struct polyval_desc_ctx),
.base = { .base = {
.cra_name = "polyval", .cra_name = "polyval",
.cra_driver_name = "polyval-ce", .cra_driver_name = "polyval-ce",
.cra_priority = 200, .cra_priority = 200,
.cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY,
.cra_blocksize = POLYVAL_BLOCK_SIZE, .cra_blocksize = POLYVAL_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct polyval_tfm_ctx), .cra_ctxsize = sizeof(struct polyval_tfm_ctx),
.cra_module = THIS_MODULE, .cra_module = THIS_MODULE,

View File

@ -7,14 +7,14 @@
#include <asm/neon.h> #include <asm/neon.h>
#include <asm/simd.h> #include <asm/simd.h>
#include <linux/unaligned.h>
#include <crypto/internal/hash.h> #include <crypto/internal/hash.h>
#include <crypto/internal/simd.h> #include <crypto/internal/simd.h>
#include <crypto/sha1.h> #include <crypto/sha1.h>
#include <crypto/sha1_base.h> #include <crypto/sha1_base.h>
#include <linux/cpufeature.h> #include <linux/cpufeature.h>
#include <linux/crypto.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/string.h>
MODULE_DESCRIPTION("SHA1 secure hash using ARMv8 Crypto Extensions"); MODULE_DESCRIPTION("SHA1 secure hash using ARMv8 Crypto Extensions");
MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>"); MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
@ -56,79 +56,49 @@ static int sha1_ce_update(struct shash_desc *desc, const u8 *data,
{ {
struct sha1_ce_state *sctx = shash_desc_ctx(desc); struct sha1_ce_state *sctx = shash_desc_ctx(desc);
if (!crypto_simd_usable())
return crypto_sha1_update(desc, data, len);
sctx->finalize = 0; sctx->finalize = 0;
sha1_base_do_update(desc, data, len, sha1_ce_transform); return sha1_base_do_update_blocks(desc, data, len, sha1_ce_transform);
return 0;
} }
static int sha1_ce_finup(struct shash_desc *desc, const u8 *data, static int sha1_ce_finup(struct shash_desc *desc, const u8 *data,
unsigned int len, u8 *out) unsigned int len, u8 *out)
{ {
struct sha1_ce_state *sctx = shash_desc_ctx(desc); struct sha1_ce_state *sctx = shash_desc_ctx(desc);
bool finalize = !sctx->sst.count && !(len % SHA1_BLOCK_SIZE) && len; bool finalized = false;
if (!crypto_simd_usable())
return crypto_sha1_finup(desc, data, len, out);
/* /*
* Allow the asm code to perform the finalization if there is no * Allow the asm code to perform the finalization if there is no
* partial data and the input is a round multiple of the block size. * partial data and the input is a round multiple of the block size.
*/ */
sctx->finalize = finalize; if (len >= SHA1_BLOCK_SIZE) {
unsigned int remain = len - round_down(len, SHA1_BLOCK_SIZE);
sha1_base_do_update(desc, data, len, sha1_ce_transform); finalized = !remain;
if (!finalize) sctx->finalize = finalized;
sha1_base_do_finalize(desc, sha1_ce_transform); sha1_base_do_update_blocks(desc, data, len, sha1_ce_transform);
data += len - remain;
len = remain;
}
if (!finalized) {
sctx->finalize = 0;
sha1_base_do_finup(desc, data, len, sha1_ce_transform);
}
return sha1_base_finish(desc, out); return sha1_base_finish(desc, out);
} }
static int sha1_ce_final(struct shash_desc *desc, u8 *out)
{
struct sha1_ce_state *sctx = shash_desc_ctx(desc);
if (!crypto_simd_usable())
return crypto_sha1_finup(desc, NULL, 0, out);
sctx->finalize = 0;
sha1_base_do_finalize(desc, sha1_ce_transform);
return sha1_base_finish(desc, out);
}
static int sha1_ce_export(struct shash_desc *desc, void *out)
{
struct sha1_ce_state *sctx = shash_desc_ctx(desc);
memcpy(out, &sctx->sst, sizeof(struct sha1_state));
return 0;
}
static int sha1_ce_import(struct shash_desc *desc, const void *in)
{
struct sha1_ce_state *sctx = shash_desc_ctx(desc);
memcpy(&sctx->sst, in, sizeof(struct sha1_state));
sctx->finalize = 0;
return 0;
}
static struct shash_alg alg = { static struct shash_alg alg = {
.init = sha1_base_init, .init = sha1_base_init,
.update = sha1_ce_update, .update = sha1_ce_update,
.final = sha1_ce_final,
.finup = sha1_ce_finup, .finup = sha1_ce_finup,
.import = sha1_ce_import,
.export = sha1_ce_export,
.descsize = sizeof(struct sha1_ce_state), .descsize = sizeof(struct sha1_ce_state),
.statesize = sizeof(struct sha1_state), .statesize = SHA1_STATE_SIZE,
.digestsize = SHA1_DIGEST_SIZE, .digestsize = SHA1_DIGEST_SIZE,
.base = { .base = {
.cra_name = "sha1", .cra_name = "sha1",
.cra_driver_name = "sha1-ce", .cra_driver_name = "sha1-ce",
.cra_priority = 200, .cra_priority = 200,
.cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY |
CRYPTO_AHASH_ALG_FINUP_MAX,
.cra_blocksize = SHA1_BLOCK_SIZE, .cra_blocksize = SHA1_BLOCK_SIZE,
.cra_module = THIS_MODULE, .cra_module = THIS_MODULE,
} }

View File

@ -1,192 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* sha2-ce-glue.c - SHA-224/SHA-256 using ARMv8 Crypto Extensions
*
* Copyright (C) 2014 - 2017 Linaro Ltd <ard.biesheuvel@linaro.org>
*/
#include <asm/neon.h>
#include <asm/simd.h>
#include <linux/unaligned.h>
#include <crypto/internal/hash.h>
#include <crypto/internal/simd.h>
#include <crypto/sha2.h>
#include <crypto/sha256_base.h>
#include <linux/cpufeature.h>
#include <linux/crypto.h>
#include <linux/module.h>
MODULE_DESCRIPTION("SHA-224/SHA-256 secure hash using ARMv8 Crypto Extensions");
MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS_CRYPTO("sha224");
MODULE_ALIAS_CRYPTO("sha256");
struct sha256_ce_state {
struct sha256_state sst;
u32 finalize;
};
extern const u32 sha256_ce_offsetof_count;
extern const u32 sha256_ce_offsetof_finalize;
asmlinkage int __sha256_ce_transform(struct sha256_ce_state *sst, u8 const *src,
int blocks);
static void sha256_ce_transform(struct sha256_state *sst, u8 const *src,
int blocks)
{
while (blocks) {
int rem;
kernel_neon_begin();
rem = __sha256_ce_transform(container_of(sst,
struct sha256_ce_state,
sst), src, blocks);
kernel_neon_end();
src += (blocks - rem) * SHA256_BLOCK_SIZE;
blocks = rem;
}
}
const u32 sha256_ce_offsetof_count = offsetof(struct sha256_ce_state,
sst.count);
const u32 sha256_ce_offsetof_finalize = offsetof(struct sha256_ce_state,
finalize);
asmlinkage void sha256_block_data_order(u32 *digest, u8 const *src, int blocks);
static void sha256_arm64_transform(struct sha256_state *sst, u8 const *src,
int blocks)
{
sha256_block_data_order(sst->state, src, blocks);
}
static int sha256_ce_update(struct shash_desc *desc, const u8 *data,
unsigned int len)
{
struct sha256_ce_state *sctx = shash_desc_ctx(desc);
if (!crypto_simd_usable())
return sha256_base_do_update(desc, data, len,
sha256_arm64_transform);
sctx->finalize = 0;
sha256_base_do_update(desc, data, len, sha256_ce_transform);
return 0;
}
static int sha256_ce_finup(struct shash_desc *desc, const u8 *data,
unsigned int len, u8 *out)
{
struct sha256_ce_state *sctx = shash_desc_ctx(desc);
bool finalize = !sctx->sst.count && !(len % SHA256_BLOCK_SIZE) && len;
if (!crypto_simd_usable()) {
if (len)
sha256_base_do_update(desc, data, len,
sha256_arm64_transform);
sha256_base_do_finalize(desc, sha256_arm64_transform);
return sha256_base_finish(desc, out);
}
/*
* Allow the asm code to perform the finalization if there is no
* partial data and the input is a round multiple of the block size.
*/
sctx->finalize = finalize;
sha256_base_do_update(desc, data, len, sha256_ce_transform);
if (!finalize)
sha256_base_do_finalize(desc, sha256_ce_transform);
return sha256_base_finish(desc, out);
}
static int sha256_ce_final(struct shash_desc *desc, u8 *out)
{
struct sha256_ce_state *sctx = shash_desc_ctx(desc);
if (!crypto_simd_usable()) {
sha256_base_do_finalize(desc, sha256_arm64_transform);
return sha256_base_finish(desc, out);
}
sctx->finalize = 0;
sha256_base_do_finalize(desc, sha256_ce_transform);
return sha256_base_finish(desc, out);
}
static int sha256_ce_digest(struct shash_desc *desc, const u8 *data,
unsigned int len, u8 *out)
{
sha256_base_init(desc);
return sha256_ce_finup(desc, data, len, out);
}
static int sha256_ce_export(struct shash_desc *desc, void *out)
{
struct sha256_ce_state *sctx = shash_desc_ctx(desc);
memcpy(out, &sctx->sst, sizeof(struct sha256_state));
return 0;
}
static int sha256_ce_import(struct shash_desc *desc, const void *in)
{
struct sha256_ce_state *sctx = shash_desc_ctx(desc);
memcpy(&sctx->sst, in, sizeof(struct sha256_state));
sctx->finalize = 0;
return 0;
}
static struct shash_alg algs[] = { {
.init = sha224_base_init,
.update = sha256_ce_update,
.final = sha256_ce_final,
.finup = sha256_ce_finup,
.export = sha256_ce_export,
.import = sha256_ce_import,
.descsize = sizeof(struct sha256_ce_state),
.statesize = sizeof(struct sha256_state),
.digestsize = SHA224_DIGEST_SIZE,
.base = {
.cra_name = "sha224",
.cra_driver_name = "sha224-ce",
.cra_priority = 200,
.cra_blocksize = SHA256_BLOCK_SIZE,
.cra_module = THIS_MODULE,
}
}, {
.init = sha256_base_init,
.update = sha256_ce_update,
.final = sha256_ce_final,
.finup = sha256_ce_finup,
.digest = sha256_ce_digest,
.export = sha256_ce_export,
.import = sha256_ce_import,
.descsize = sizeof(struct sha256_ce_state),
.statesize = sizeof(struct sha256_state),
.digestsize = SHA256_DIGEST_SIZE,
.base = {
.cra_name = "sha256",
.cra_driver_name = "sha256-ce",
.cra_priority = 200,
.cra_blocksize = SHA256_BLOCK_SIZE,
.cra_module = THIS_MODULE,
}
} };
static int __init sha2_ce_mod_init(void)
{
return crypto_register_shashes(algs, ARRAY_SIZE(algs));
}
static void __exit sha2_ce_mod_fini(void)
{
crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
}
module_cpu_feature_match(SHA2, sha2_ce_mod_init);
module_exit(sha2_ce_mod_fini);

View File

@ -1,194 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Linux/arm64 port of the OpenSSL SHA256 implementation for AArch64
*
* Copyright (c) 2016 Linaro Ltd. <ard.biesheuvel@linaro.org>
*/
#include <asm/hwcap.h>
#include <asm/neon.h>
#include <asm/simd.h>
#include <crypto/internal/hash.h>
#include <crypto/internal/simd.h>
#include <crypto/sha2.h>
#include <crypto/sha256_base.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/types.h>
MODULE_DESCRIPTION("SHA-224/SHA-256 secure hash for arm64");
MODULE_AUTHOR("Andy Polyakov <appro@openssl.org>");
MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS_CRYPTO("sha224");
MODULE_ALIAS_CRYPTO("sha256");
asmlinkage void sha256_block_data_order(u32 *digest, const void *data,
unsigned int num_blks);
EXPORT_SYMBOL(sha256_block_data_order);
static void sha256_arm64_transform(struct sha256_state *sst, u8 const *src,
int blocks)
{
sha256_block_data_order(sst->state, src, blocks);
}
asmlinkage void sha256_block_neon(u32 *digest, const void *data,
unsigned int num_blks);
static void sha256_neon_transform(struct sha256_state *sst, u8 const *src,
int blocks)
{
sha256_block_neon(sst->state, src, blocks);
}
static int crypto_sha256_arm64_update(struct shash_desc *desc, const u8 *data,
unsigned int len)
{
return sha256_base_do_update(desc, data, len, sha256_arm64_transform);
}
static int crypto_sha256_arm64_finup(struct shash_desc *desc, const u8 *data,
unsigned int len, u8 *out)
{
if (len)
sha256_base_do_update(desc, data, len, sha256_arm64_transform);
sha256_base_do_finalize(desc, sha256_arm64_transform);
return sha256_base_finish(desc, out);
}
static int crypto_sha256_arm64_final(struct shash_desc *desc, u8 *out)
{
return crypto_sha256_arm64_finup(desc, NULL, 0, out);
}
static struct shash_alg algs[] = { {
.digestsize = SHA256_DIGEST_SIZE,
.init = sha256_base_init,
.update = crypto_sha256_arm64_update,
.final = crypto_sha256_arm64_final,
.finup = crypto_sha256_arm64_finup,
.descsize = sizeof(struct sha256_state),
.base.cra_name = "sha256",
.base.cra_driver_name = "sha256-arm64",
.base.cra_priority = 125,
.base.cra_blocksize = SHA256_BLOCK_SIZE,
.base.cra_module = THIS_MODULE,
}, {
.digestsize = SHA224_DIGEST_SIZE,
.init = sha224_base_init,
.update = crypto_sha256_arm64_update,
.final = crypto_sha256_arm64_final,
.finup = crypto_sha256_arm64_finup,
.descsize = sizeof(struct sha256_state),
.base.cra_name = "sha224",
.base.cra_driver_name = "sha224-arm64",
.base.cra_priority = 125,
.base.cra_blocksize = SHA224_BLOCK_SIZE,
.base.cra_module = THIS_MODULE,
} };
static int sha256_update_neon(struct shash_desc *desc, const u8 *data,
unsigned int len)
{
struct sha256_state *sctx = shash_desc_ctx(desc);
if (!crypto_simd_usable())
return sha256_base_do_update(desc, data, len,
sha256_arm64_transform);
while (len > 0) {
unsigned int chunk = len;
/*
* Don't hog the CPU for the entire time it takes to process all
* input when running on a preemptible kernel, but process the
* data block by block instead.
*/
if (IS_ENABLED(CONFIG_PREEMPTION) &&
chunk + sctx->count % SHA256_BLOCK_SIZE > SHA256_BLOCK_SIZE)
chunk = SHA256_BLOCK_SIZE -
sctx->count % SHA256_BLOCK_SIZE;
kernel_neon_begin();
sha256_base_do_update(desc, data, chunk, sha256_neon_transform);
kernel_neon_end();
data += chunk;
len -= chunk;
}
return 0;
}
static int sha256_finup_neon(struct shash_desc *desc, const u8 *data,
unsigned int len, u8 *out)
{
if (!crypto_simd_usable()) {
if (len)
sha256_base_do_update(desc, data, len,
sha256_arm64_transform);
sha256_base_do_finalize(desc, sha256_arm64_transform);
} else {
if (len)
sha256_update_neon(desc, data, len);
kernel_neon_begin();
sha256_base_do_finalize(desc, sha256_neon_transform);
kernel_neon_end();
}
return sha256_base_finish(desc, out);
}
static int sha256_final_neon(struct shash_desc *desc, u8 *out)
{
return sha256_finup_neon(desc, NULL, 0, out);
}
static struct shash_alg neon_algs[] = { {
.digestsize = SHA256_DIGEST_SIZE,
.init = sha256_base_init,
.update = sha256_update_neon,
.final = sha256_final_neon,
.finup = sha256_finup_neon,
.descsize = sizeof(struct sha256_state),
.base.cra_name = "sha256",
.base.cra_driver_name = "sha256-arm64-neon",
.base.cra_priority = 150,
.base.cra_blocksize = SHA256_BLOCK_SIZE,
.base.cra_module = THIS_MODULE,
}, {
.digestsize = SHA224_DIGEST_SIZE,
.init = sha224_base_init,
.update = sha256_update_neon,
.final = sha256_final_neon,
.finup = sha256_finup_neon,
.descsize = sizeof(struct sha256_state),
.base.cra_name = "sha224",
.base.cra_driver_name = "sha224-arm64-neon",
.base.cra_priority = 150,
.base.cra_blocksize = SHA224_BLOCK_SIZE,
.base.cra_module = THIS_MODULE,
} };
static int __init sha256_mod_init(void)
{
int ret = crypto_register_shashes(algs, ARRAY_SIZE(algs));
if (ret)
return ret;
if (cpu_have_named_feature(ASIMD)) {
ret = crypto_register_shashes(neon_algs, ARRAY_SIZE(neon_algs));
if (ret)
crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
}
return ret;
}
static void __exit sha256_mod_fini(void)
{
if (cpu_have_named_feature(ASIMD))
crypto_unregister_shashes(neon_algs, ARRAY_SIZE(neon_algs));
crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
}
module_init(sha256_mod_init);
module_exit(sha256_mod_fini);

View File

@ -12,13 +12,13 @@
#include <asm/hwcap.h> #include <asm/hwcap.h>
#include <asm/neon.h> #include <asm/neon.h>
#include <asm/simd.h> #include <asm/simd.h>
#include <linux/unaligned.h>
#include <crypto/internal/hash.h> #include <crypto/internal/hash.h>
#include <crypto/internal/simd.h>
#include <crypto/sha3.h> #include <crypto/sha3.h>
#include <linux/cpufeature.h> #include <linux/cpufeature.h>
#include <linux/crypto.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/string.h>
#include <linux/unaligned.h>
MODULE_DESCRIPTION("SHA3 secure hash using ARMv8 Crypto Extensions"); MODULE_DESCRIPTION("SHA3 secure hash using ARMv8 Crypto Extensions");
MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>"); MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
@ -35,74 +35,55 @@ static int sha3_update(struct shash_desc *desc, const u8 *data,
unsigned int len) unsigned int len)
{ {
struct sha3_state *sctx = shash_desc_ctx(desc); struct sha3_state *sctx = shash_desc_ctx(desc);
unsigned int digest_size = crypto_shash_digestsize(desc->tfm); struct crypto_shash *tfm = desc->tfm;
unsigned int bs, ds;
int blocks;
if (!crypto_simd_usable()) ds = crypto_shash_digestsize(tfm);
return crypto_sha3_update(desc, data, len); bs = crypto_shash_blocksize(tfm);
blocks = len / bs;
len -= blocks * bs;
do {
int rem;
if ((sctx->partial + len) >= sctx->rsiz) { kernel_neon_begin();
int blocks; rem = sha3_ce_transform(sctx->st, data, blocks, ds);
kernel_neon_end();
if (sctx->partial) { data += (blocks - rem) * bs;
int p = sctx->rsiz - sctx->partial; blocks = rem;
} while (blocks);
memcpy(sctx->buf + sctx->partial, data, p); return len;
kernel_neon_begin();
sha3_ce_transform(sctx->st, sctx->buf, 1, digest_size);
kernel_neon_end();
data += p;
len -= p;
sctx->partial = 0;
}
blocks = len / sctx->rsiz;
len %= sctx->rsiz;
while (blocks) {
int rem;
kernel_neon_begin();
rem = sha3_ce_transform(sctx->st, data, blocks,
digest_size);
kernel_neon_end();
data += (blocks - rem) * sctx->rsiz;
blocks = rem;
}
}
if (len) {
memcpy(sctx->buf + sctx->partial, data, len);
sctx->partial += len;
}
return 0;
} }
static int sha3_final(struct shash_desc *desc, u8 *out) static int sha3_finup(struct shash_desc *desc, const u8 *src, unsigned int len,
u8 *out)
{ {
struct sha3_state *sctx = shash_desc_ctx(desc); struct sha3_state *sctx = shash_desc_ctx(desc);
unsigned int digest_size = crypto_shash_digestsize(desc->tfm); struct crypto_shash *tfm = desc->tfm;
__le64 *digest = (__le64 *)out; __le64 *digest = (__le64 *)out;
u8 block[SHA3_224_BLOCK_SIZE];
unsigned int bs, ds;
int i; int i;
if (!crypto_simd_usable()) ds = crypto_shash_digestsize(tfm);
return crypto_sha3_final(desc, out); bs = crypto_shash_blocksize(tfm);
memcpy(block, src, len);
sctx->buf[sctx->partial++] = 0x06; block[len++] = 0x06;
memset(sctx->buf + sctx->partial, 0, sctx->rsiz - sctx->partial); memset(block + len, 0, bs - len);
sctx->buf[sctx->rsiz - 1] |= 0x80; block[bs - 1] |= 0x80;
kernel_neon_begin(); kernel_neon_begin();
sha3_ce_transform(sctx->st, sctx->buf, 1, digest_size); sha3_ce_transform(sctx->st, block, 1, ds);
kernel_neon_end(); kernel_neon_end();
memzero_explicit(block , sizeof(block));
for (i = 0; i < digest_size / 8; i++) for (i = 0; i < ds / 8; i++)
put_unaligned_le64(sctx->st[i], digest++); put_unaligned_le64(sctx->st[i], digest++);
if (digest_size & 4) if (ds & 4)
put_unaligned_le32(sctx->st[i], (__le32 *)digest); put_unaligned_le32(sctx->st[i], (__le32 *)digest);
memzero_explicit(sctx, sizeof(*sctx));
return 0; return 0;
} }
@ -110,10 +91,11 @@ static struct shash_alg algs[] = { {
.digestsize = SHA3_224_DIGEST_SIZE, .digestsize = SHA3_224_DIGEST_SIZE,
.init = crypto_sha3_init, .init = crypto_sha3_init,
.update = sha3_update, .update = sha3_update,
.final = sha3_final, .finup = sha3_finup,
.descsize = sizeof(struct sha3_state), .descsize = SHA3_STATE_SIZE,
.base.cra_name = "sha3-224", .base.cra_name = "sha3-224",
.base.cra_driver_name = "sha3-224-ce", .base.cra_driver_name = "sha3-224-ce",
.base.cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY,
.base.cra_blocksize = SHA3_224_BLOCK_SIZE, .base.cra_blocksize = SHA3_224_BLOCK_SIZE,
.base.cra_module = THIS_MODULE, .base.cra_module = THIS_MODULE,
.base.cra_priority = 200, .base.cra_priority = 200,
@ -121,10 +103,11 @@ static struct shash_alg algs[] = { {
.digestsize = SHA3_256_DIGEST_SIZE, .digestsize = SHA3_256_DIGEST_SIZE,
.init = crypto_sha3_init, .init = crypto_sha3_init,
.update = sha3_update, .update = sha3_update,
.final = sha3_final, .finup = sha3_finup,
.descsize = sizeof(struct sha3_state), .descsize = SHA3_STATE_SIZE,
.base.cra_name = "sha3-256", .base.cra_name = "sha3-256",
.base.cra_driver_name = "sha3-256-ce", .base.cra_driver_name = "sha3-256-ce",
.base.cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY,
.base.cra_blocksize = SHA3_256_BLOCK_SIZE, .base.cra_blocksize = SHA3_256_BLOCK_SIZE,
.base.cra_module = THIS_MODULE, .base.cra_module = THIS_MODULE,
.base.cra_priority = 200, .base.cra_priority = 200,
@ -132,10 +115,11 @@ static struct shash_alg algs[] = { {
.digestsize = SHA3_384_DIGEST_SIZE, .digestsize = SHA3_384_DIGEST_SIZE,
.init = crypto_sha3_init, .init = crypto_sha3_init,
.update = sha3_update, .update = sha3_update,
.final = sha3_final, .finup = sha3_finup,
.descsize = sizeof(struct sha3_state), .descsize = SHA3_STATE_SIZE,
.base.cra_name = "sha3-384", .base.cra_name = "sha3-384",
.base.cra_driver_name = "sha3-384-ce", .base.cra_driver_name = "sha3-384-ce",
.base.cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY,
.base.cra_blocksize = SHA3_384_BLOCK_SIZE, .base.cra_blocksize = SHA3_384_BLOCK_SIZE,
.base.cra_module = THIS_MODULE, .base.cra_module = THIS_MODULE,
.base.cra_priority = 200, .base.cra_priority = 200,
@ -143,10 +127,11 @@ static struct shash_alg algs[] = { {
.digestsize = SHA3_512_DIGEST_SIZE, .digestsize = SHA3_512_DIGEST_SIZE,
.init = crypto_sha3_init, .init = crypto_sha3_init,
.update = sha3_update, .update = sha3_update,
.final = sha3_final, .finup = sha3_finup,
.descsize = sizeof(struct sha3_state), .descsize = SHA3_STATE_SIZE,
.base.cra_name = "sha3-512", .base.cra_name = "sha3-512",
.base.cra_driver_name = "sha3-512-ce", .base.cra_driver_name = "sha3-512-ce",
.base.cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY,
.base.cra_blocksize = SHA3_512_BLOCK_SIZE, .base.cra_blocksize = SHA3_512_BLOCK_SIZE,
.base.cra_module = THIS_MODULE, .base.cra_module = THIS_MODULE,
.base.cra_priority = 200, .base.cra_priority = 200,

View File

@ -10,14 +10,11 @@
*/ */
#include <asm/neon.h> #include <asm/neon.h>
#include <asm/simd.h>
#include <linux/unaligned.h>
#include <crypto/internal/hash.h> #include <crypto/internal/hash.h>
#include <crypto/internal/simd.h>
#include <crypto/sha2.h> #include <crypto/sha2.h>
#include <crypto/sha512_base.h> #include <crypto/sha512_base.h>
#include <linux/cpufeature.h> #include <linux/cpufeature.h>
#include <linux/crypto.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
MODULE_DESCRIPTION("SHA-384/SHA-512 secure hash using ARMv8 Crypto Extensions"); MODULE_DESCRIPTION("SHA-384/SHA-512 secure hash using ARMv8 Crypto Extensions");
@ -29,12 +26,10 @@ MODULE_ALIAS_CRYPTO("sha512");
asmlinkage int __sha512_ce_transform(struct sha512_state *sst, u8 const *src, asmlinkage int __sha512_ce_transform(struct sha512_state *sst, u8 const *src,
int blocks); int blocks);
asmlinkage void sha512_block_data_order(u64 *digest, u8 const *src, int blocks);
static void sha512_ce_transform(struct sha512_state *sst, u8 const *src, static void sha512_ce_transform(struct sha512_state *sst, u8 const *src,
int blocks) int blocks)
{ {
while (blocks) { do {
int rem; int rem;
kernel_neon_begin(); kernel_neon_begin();
@ -42,67 +37,47 @@ static void sha512_ce_transform(struct sha512_state *sst, u8 const *src,
kernel_neon_end(); kernel_neon_end();
src += (blocks - rem) * SHA512_BLOCK_SIZE; src += (blocks - rem) * SHA512_BLOCK_SIZE;
blocks = rem; blocks = rem;
} } while (blocks);
}
static void sha512_arm64_transform(struct sha512_state *sst, u8 const *src,
int blocks)
{
sha512_block_data_order(sst->state, src, blocks);
} }
static int sha512_ce_update(struct shash_desc *desc, const u8 *data, static int sha512_ce_update(struct shash_desc *desc, const u8 *data,
unsigned int len) unsigned int len)
{ {
sha512_block_fn *fn = crypto_simd_usable() ? sha512_ce_transform return sha512_base_do_update_blocks(desc, data, len,
: sha512_arm64_transform; sha512_ce_transform);
sha512_base_do_update(desc, data, len, fn);
return 0;
} }
static int sha512_ce_finup(struct shash_desc *desc, const u8 *data, static int sha512_ce_finup(struct shash_desc *desc, const u8 *data,
unsigned int len, u8 *out) unsigned int len, u8 *out)
{ {
sha512_block_fn *fn = crypto_simd_usable() ? sha512_ce_transform sha512_base_do_finup(desc, data, len, sha512_ce_transform);
: sha512_arm64_transform;
sha512_base_do_update(desc, data, len, fn);
sha512_base_do_finalize(desc, fn);
return sha512_base_finish(desc, out);
}
static int sha512_ce_final(struct shash_desc *desc, u8 *out)
{
sha512_block_fn *fn = crypto_simd_usable() ? sha512_ce_transform
: sha512_arm64_transform;
sha512_base_do_finalize(desc, fn);
return sha512_base_finish(desc, out); return sha512_base_finish(desc, out);
} }
static struct shash_alg algs[] = { { static struct shash_alg algs[] = { {
.init = sha384_base_init, .init = sha384_base_init,
.update = sha512_ce_update, .update = sha512_ce_update,
.final = sha512_ce_final,
.finup = sha512_ce_finup, .finup = sha512_ce_finup,
.descsize = sizeof(struct sha512_state), .descsize = SHA512_STATE_SIZE,
.digestsize = SHA384_DIGEST_SIZE, .digestsize = SHA384_DIGEST_SIZE,
.base.cra_name = "sha384", .base.cra_name = "sha384",
.base.cra_driver_name = "sha384-ce", .base.cra_driver_name = "sha384-ce",
.base.cra_priority = 200, .base.cra_priority = 200,
.base.cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY |
CRYPTO_AHASH_ALG_FINUP_MAX,
.base.cra_blocksize = SHA512_BLOCK_SIZE, .base.cra_blocksize = SHA512_BLOCK_SIZE,
.base.cra_module = THIS_MODULE, .base.cra_module = THIS_MODULE,
}, { }, {
.init = sha512_base_init, .init = sha512_base_init,
.update = sha512_ce_update, .update = sha512_ce_update,
.final = sha512_ce_final,
.finup = sha512_ce_finup, .finup = sha512_ce_finup,
.descsize = sizeof(struct sha512_state), .descsize = SHA512_STATE_SIZE,
.digestsize = SHA512_DIGEST_SIZE, .digestsize = SHA512_DIGEST_SIZE,
.base.cra_name = "sha512", .base.cra_name = "sha512",
.base.cra_driver_name = "sha512-ce", .base.cra_driver_name = "sha512-ce",
.base.cra_priority = 200, .base.cra_priority = 200,
.base.cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY |
CRYPTO_AHASH_ALG_FINUP_MAX,
.base.cra_blocksize = SHA512_BLOCK_SIZE, .base.cra_blocksize = SHA512_BLOCK_SIZE,
.base.cra_module = THIS_MODULE, .base.cra_module = THIS_MODULE,
} }; } };

View File

@ -6,11 +6,10 @@
*/ */
#include <crypto/internal/hash.h> #include <crypto/internal/hash.h>
#include <linux/types.h>
#include <linux/string.h>
#include <crypto/sha2.h> #include <crypto/sha2.h>
#include <crypto/sha512_base.h> #include <crypto/sha512_base.h>
#include <asm/neon.h> #include <linux/kernel.h>
#include <linux/module.h>
MODULE_DESCRIPTION("SHA-384/SHA-512 secure hash for arm64"); MODULE_DESCRIPTION("SHA-384/SHA-512 secure hash for arm64");
MODULE_AUTHOR("Andy Polyakov <appro@openssl.org>"); MODULE_AUTHOR("Andy Polyakov <appro@openssl.org>");
@ -19,59 +18,53 @@ MODULE_LICENSE("GPL v2");
MODULE_ALIAS_CRYPTO("sha384"); MODULE_ALIAS_CRYPTO("sha384");
MODULE_ALIAS_CRYPTO("sha512"); MODULE_ALIAS_CRYPTO("sha512");
asmlinkage void sha512_block_data_order(u64 *digest, const void *data, asmlinkage void sha512_blocks_arch(u64 *digest, const void *data,
unsigned int num_blks); unsigned int num_blks);
EXPORT_SYMBOL(sha512_block_data_order);
static void sha512_arm64_transform(struct sha512_state *sst, u8 const *src, static void sha512_arm64_transform(struct sha512_state *sst, u8 const *src,
int blocks) int blocks)
{ {
sha512_block_data_order(sst->state, src, blocks); sha512_blocks_arch(sst->state, src, blocks);
} }
static int sha512_update(struct shash_desc *desc, const u8 *data, static int sha512_update(struct shash_desc *desc, const u8 *data,
unsigned int len) unsigned int len)
{ {
return sha512_base_do_update(desc, data, len, sha512_arm64_transform); return sha512_base_do_update_blocks(desc, data, len,
sha512_arm64_transform);
} }
static int sha512_finup(struct shash_desc *desc, const u8 *data, static int sha512_finup(struct shash_desc *desc, const u8 *data,
unsigned int len, u8 *out) unsigned int len, u8 *out)
{ {
if (len) sha512_base_do_finup(desc, data, len, sha512_arm64_transform);
sha512_base_do_update(desc, data, len, sha512_arm64_transform);
sha512_base_do_finalize(desc, sha512_arm64_transform);
return sha512_base_finish(desc, out); return sha512_base_finish(desc, out);
} }
static int sha512_final(struct shash_desc *desc, u8 *out)
{
return sha512_finup(desc, NULL, 0, out);
}
static struct shash_alg algs[] = { { static struct shash_alg algs[] = { {
.digestsize = SHA512_DIGEST_SIZE, .digestsize = SHA512_DIGEST_SIZE,
.init = sha512_base_init, .init = sha512_base_init,
.update = sha512_update, .update = sha512_update,
.final = sha512_final,
.finup = sha512_finup, .finup = sha512_finup,
.descsize = sizeof(struct sha512_state), .descsize = SHA512_STATE_SIZE,
.base.cra_name = "sha512", .base.cra_name = "sha512",
.base.cra_driver_name = "sha512-arm64", .base.cra_driver_name = "sha512-arm64",
.base.cra_priority = 150, .base.cra_priority = 150,
.base.cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY |
CRYPTO_AHASH_ALG_FINUP_MAX,
.base.cra_blocksize = SHA512_BLOCK_SIZE, .base.cra_blocksize = SHA512_BLOCK_SIZE,
.base.cra_module = THIS_MODULE, .base.cra_module = THIS_MODULE,
}, { }, {
.digestsize = SHA384_DIGEST_SIZE, .digestsize = SHA384_DIGEST_SIZE,
.init = sha384_base_init, .init = sha384_base_init,
.update = sha512_update, .update = sha512_update,
.final = sha512_final,
.finup = sha512_finup, .finup = sha512_finup,
.descsize = sizeof(struct sha512_state), .descsize = SHA512_STATE_SIZE,
.base.cra_name = "sha384", .base.cra_name = "sha384",
.base.cra_driver_name = "sha384-arm64", .base.cra_driver_name = "sha384-arm64",
.base.cra_priority = 150, .base.cra_priority = 150,
.base.cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY |
CRYPTO_AHASH_ALG_FINUP_MAX,
.base.cra_blocksize = SHA384_BLOCK_SIZE, .base.cra_blocksize = SHA384_BLOCK_SIZE,
.base.cra_module = THIS_MODULE, .base.cra_module = THIS_MODULE,
} }; } };

View File

@ -6,14 +6,11 @@
*/ */
#include <asm/neon.h> #include <asm/neon.h>
#include <asm/simd.h>
#include <linux/unaligned.h>
#include <crypto/internal/hash.h> #include <crypto/internal/hash.h>
#include <crypto/internal/simd.h>
#include <crypto/sm3.h> #include <crypto/sm3.h>
#include <crypto/sm3_base.h> #include <crypto/sm3_base.h>
#include <linux/cpufeature.h> #include <linux/cpufeature.h>
#include <linux/crypto.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
MODULE_DESCRIPTION("SM3 secure hash using ARMv8 Crypto Extensions"); MODULE_DESCRIPTION("SM3 secure hash using ARMv8 Crypto Extensions");
@ -26,50 +23,20 @@ asmlinkage void sm3_ce_transform(struct sm3_state *sst, u8 const *src,
static int sm3_ce_update(struct shash_desc *desc, const u8 *data, static int sm3_ce_update(struct shash_desc *desc, const u8 *data,
unsigned int len) unsigned int len)
{ {
if (!crypto_simd_usable()) { int remain;
sm3_update(shash_desc_ctx(desc), data, len);
return 0;
}
kernel_neon_begin(); kernel_neon_begin();
sm3_base_do_update(desc, data, len, sm3_ce_transform); remain = sm3_base_do_update_blocks(desc, data, len, sm3_ce_transform);
kernel_neon_end(); kernel_neon_end();
return remain;
return 0;
}
static int sm3_ce_final(struct shash_desc *desc, u8 *out)
{
if (!crypto_simd_usable()) {
sm3_final(shash_desc_ctx(desc), out);
return 0;
}
kernel_neon_begin();
sm3_base_do_finalize(desc, sm3_ce_transform);
kernel_neon_end();
return sm3_base_finish(desc, out);
} }
static int sm3_ce_finup(struct shash_desc *desc, const u8 *data, static int sm3_ce_finup(struct shash_desc *desc, const u8 *data,
unsigned int len, u8 *out) unsigned int len, u8 *out)
{ {
if (!crypto_simd_usable()) {
struct sm3_state *sctx = shash_desc_ctx(desc);
if (len)
sm3_update(sctx, data, len);
sm3_final(sctx, out);
return 0;
}
kernel_neon_begin(); kernel_neon_begin();
if (len) sm3_base_do_finup(desc, data, len, sm3_ce_transform);
sm3_base_do_update(desc, data, len, sm3_ce_transform);
sm3_base_do_finalize(desc, sm3_ce_transform);
kernel_neon_end(); kernel_neon_end();
return sm3_base_finish(desc, out); return sm3_base_finish(desc, out);
} }
@ -77,11 +44,12 @@ static struct shash_alg sm3_alg = {
.digestsize = SM3_DIGEST_SIZE, .digestsize = SM3_DIGEST_SIZE,
.init = sm3_base_init, .init = sm3_base_init,
.update = sm3_ce_update, .update = sm3_ce_update,
.final = sm3_ce_final,
.finup = sm3_ce_finup, .finup = sm3_ce_finup,
.descsize = sizeof(struct sm3_state), .descsize = SM3_STATE_SIZE,
.base.cra_name = "sm3", .base.cra_name = "sm3",
.base.cra_driver_name = "sm3-ce", .base.cra_driver_name = "sm3-ce",
.base.cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY |
CRYPTO_AHASH_ALG_FINUP_MAX,
.base.cra_blocksize = SM3_BLOCK_SIZE, .base.cra_blocksize = SM3_BLOCK_SIZE,
.base.cra_module = THIS_MODULE, .base.cra_module = THIS_MODULE,
.base.cra_priority = 400, .base.cra_priority = 400,

View File

@ -6,14 +6,11 @@
*/ */
#include <asm/neon.h> #include <asm/neon.h>
#include <asm/simd.h>
#include <linux/unaligned.h>
#include <crypto/internal/hash.h> #include <crypto/internal/hash.h>
#include <crypto/internal/simd.h>
#include <crypto/sm3.h> #include <crypto/sm3.h>
#include <crypto/sm3_base.h> #include <crypto/sm3_base.h>
#include <linux/cpufeature.h> #include <linux/cpufeature.h>
#include <linux/crypto.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
@ -23,50 +20,20 @@ asmlinkage void sm3_neon_transform(struct sm3_state *sst, u8 const *src,
static int sm3_neon_update(struct shash_desc *desc, const u8 *data, static int sm3_neon_update(struct shash_desc *desc, const u8 *data,
unsigned int len) unsigned int len)
{ {
if (!crypto_simd_usable()) { int remain;
sm3_update(shash_desc_ctx(desc), data, len);
return 0;
}
kernel_neon_begin(); kernel_neon_begin();
sm3_base_do_update(desc, data, len, sm3_neon_transform); remain = sm3_base_do_update_blocks(desc, data, len, sm3_neon_transform);
kernel_neon_end(); kernel_neon_end();
return remain;
return 0;
}
static int sm3_neon_final(struct shash_desc *desc, u8 *out)
{
if (!crypto_simd_usable()) {
sm3_final(shash_desc_ctx(desc), out);
return 0;
}
kernel_neon_begin();
sm3_base_do_finalize(desc, sm3_neon_transform);
kernel_neon_end();
return sm3_base_finish(desc, out);
} }
static int sm3_neon_finup(struct shash_desc *desc, const u8 *data, static int sm3_neon_finup(struct shash_desc *desc, const u8 *data,
unsigned int len, u8 *out) unsigned int len, u8 *out)
{ {
if (!crypto_simd_usable()) {
struct sm3_state *sctx = shash_desc_ctx(desc);
if (len)
sm3_update(sctx, data, len);
sm3_final(sctx, out);
return 0;
}
kernel_neon_begin(); kernel_neon_begin();
if (len) sm3_base_do_finup(desc, data, len, sm3_neon_transform);
sm3_base_do_update(desc, data, len, sm3_neon_transform);
sm3_base_do_finalize(desc, sm3_neon_transform);
kernel_neon_end(); kernel_neon_end();
return sm3_base_finish(desc, out); return sm3_base_finish(desc, out);
} }
@ -74,11 +41,12 @@ static struct shash_alg sm3_alg = {
.digestsize = SM3_DIGEST_SIZE, .digestsize = SM3_DIGEST_SIZE,
.init = sm3_base_init, .init = sm3_base_init,
.update = sm3_neon_update, .update = sm3_neon_update,
.final = sm3_neon_final,
.finup = sm3_neon_finup, .finup = sm3_neon_finup,
.descsize = sizeof(struct sm3_state), .descsize = SM3_STATE_SIZE,
.base.cra_name = "sm3", .base.cra_name = "sm3",
.base.cra_driver_name = "sm3-neon", .base.cra_driver_name = "sm3-neon",
.base.cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY |
CRYPTO_AHASH_ALG_FINUP_MAX,
.base.cra_blocksize = SM3_BLOCK_SIZE, .base.cra_blocksize = SM3_BLOCK_SIZE,
.base.cra_module = THIS_MODULE, .base.cra_module = THIS_MODULE,
.base.cra_priority = 200, .base.cra_priority = 200,

View File

@ -8,19 +8,18 @@
* Copyright (C) 2022 Tianjia Zhang <tianjia.zhang@linux.alibaba.com> * Copyright (C) 2022 Tianjia Zhang <tianjia.zhang@linux.alibaba.com>
*/ */
#include <linux/module.h>
#include <linux/crypto.h>
#include <linux/kernel.h>
#include <linux/cpufeature.h>
#include <asm/neon.h> #include <asm/neon.h>
#include <asm/simd.h>
#include <crypto/b128ops.h> #include <crypto/b128ops.h>
#include <crypto/internal/simd.h>
#include <crypto/internal/skcipher.h>
#include <crypto/internal/hash.h> #include <crypto/internal/hash.h>
#include <crypto/internal/skcipher.h>
#include <crypto/scatterwalk.h> #include <crypto/scatterwalk.h>
#include <crypto/xts.h>
#include <crypto/sm4.h> #include <crypto/sm4.h>
#include <crypto/utils.h>
#include <crypto/xts.h>
#include <linux/cpufeature.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/string.h>
#define BYTES2BLKS(nbytes) ((nbytes) >> 4) #define BYTES2BLKS(nbytes) ((nbytes) >> 4)
@ -64,7 +63,6 @@ struct sm4_mac_tfm_ctx {
}; };
struct sm4_mac_desc_ctx { struct sm4_mac_desc_ctx {
unsigned int len;
u8 digest[SM4_BLOCK_SIZE]; u8 digest[SM4_BLOCK_SIZE];
}; };
@ -591,8 +589,6 @@ static int sm4_mac_init(struct shash_desc *desc)
struct sm4_mac_desc_ctx *ctx = shash_desc_ctx(desc); struct sm4_mac_desc_ctx *ctx = shash_desc_ctx(desc);
memset(ctx->digest, 0, SM4_BLOCK_SIZE); memset(ctx->digest, 0, SM4_BLOCK_SIZE);
ctx->len = 0;
return 0; return 0;
} }
@ -601,87 +597,50 @@ static int sm4_mac_update(struct shash_desc *desc, const u8 *p,
{ {
struct sm4_mac_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm); struct sm4_mac_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm);
struct sm4_mac_desc_ctx *ctx = shash_desc_ctx(desc); struct sm4_mac_desc_ctx *ctx = shash_desc_ctx(desc);
unsigned int l, nblocks; unsigned int nblocks = len / SM4_BLOCK_SIZE;
if (len == 0) len %= SM4_BLOCK_SIZE;
return 0; kernel_neon_begin();
sm4_ce_mac_update(tctx->key.rkey_enc, ctx->digest, p,
if (ctx->len || ctx->len + len < SM4_BLOCK_SIZE) { nblocks, false, true);
l = min(len, SM4_BLOCK_SIZE - ctx->len); kernel_neon_end();
return len;
crypto_xor(ctx->digest + ctx->len, p, l);
ctx->len += l;
len -= l;
p += l;
}
if (len && (ctx->len % SM4_BLOCK_SIZE) == 0) {
kernel_neon_begin();
if (len < SM4_BLOCK_SIZE && ctx->len == SM4_BLOCK_SIZE) {
sm4_ce_crypt_block(tctx->key.rkey_enc,
ctx->digest, ctx->digest);
ctx->len = 0;
} else {
nblocks = len / SM4_BLOCK_SIZE;
len %= SM4_BLOCK_SIZE;
sm4_ce_mac_update(tctx->key.rkey_enc, ctx->digest, p,
nblocks, (ctx->len == SM4_BLOCK_SIZE),
(len != 0));
p += nblocks * SM4_BLOCK_SIZE;
if (len == 0)
ctx->len = SM4_BLOCK_SIZE;
}
kernel_neon_end();
if (len) {
crypto_xor(ctx->digest, p, len);
ctx->len = len;
}
}
return 0;
} }
static int sm4_cmac_final(struct shash_desc *desc, u8 *out) static int sm4_cmac_finup(struct shash_desc *desc, const u8 *src,
unsigned int len, u8 *out)
{ {
struct sm4_mac_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm); struct sm4_mac_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm);
struct sm4_mac_desc_ctx *ctx = shash_desc_ctx(desc); struct sm4_mac_desc_ctx *ctx = shash_desc_ctx(desc);
const u8 *consts = tctx->consts; const u8 *consts = tctx->consts;
if (ctx->len != SM4_BLOCK_SIZE) { crypto_xor(ctx->digest, src, len);
ctx->digest[ctx->len] ^= 0x80; if (len != SM4_BLOCK_SIZE) {
ctx->digest[len] ^= 0x80;
consts += SM4_BLOCK_SIZE; consts += SM4_BLOCK_SIZE;
} }
kernel_neon_begin(); kernel_neon_begin();
sm4_ce_mac_update(tctx->key.rkey_enc, ctx->digest, consts, 1, sm4_ce_mac_update(tctx->key.rkey_enc, ctx->digest, consts, 1,
false, true); false, true);
kernel_neon_end(); kernel_neon_end();
memcpy(out, ctx->digest, SM4_BLOCK_SIZE); memcpy(out, ctx->digest, SM4_BLOCK_SIZE);
return 0; return 0;
} }
static int sm4_cbcmac_final(struct shash_desc *desc, u8 *out) static int sm4_cbcmac_finup(struct shash_desc *desc, const u8 *src,
unsigned int len, u8 *out)
{ {
struct sm4_mac_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm); struct sm4_mac_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm);
struct sm4_mac_desc_ctx *ctx = shash_desc_ctx(desc); struct sm4_mac_desc_ctx *ctx = shash_desc_ctx(desc);
if (ctx->len) { if (len) {
crypto_xor(ctx->digest, src, len);
kernel_neon_begin(); kernel_neon_begin();
sm4_ce_crypt_block(tctx->key.rkey_enc, ctx->digest, sm4_ce_crypt_block(tctx->key.rkey_enc, ctx->digest,
ctx->digest); ctx->digest);
kernel_neon_end(); kernel_neon_end();
} }
memcpy(out, ctx->digest, SM4_BLOCK_SIZE); memcpy(out, ctx->digest, SM4_BLOCK_SIZE);
return 0; return 0;
} }
@ -691,6 +650,8 @@ static struct shash_alg sm4_mac_algs[] = {
.cra_name = "cmac(sm4)", .cra_name = "cmac(sm4)",
.cra_driver_name = "cmac-sm4-ce", .cra_driver_name = "cmac-sm4-ce",
.cra_priority = 400, .cra_priority = 400,
.cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY |
CRYPTO_AHASH_ALG_FINAL_NONZERO,
.cra_blocksize = SM4_BLOCK_SIZE, .cra_blocksize = SM4_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct sm4_mac_tfm_ctx) .cra_ctxsize = sizeof(struct sm4_mac_tfm_ctx)
+ SM4_BLOCK_SIZE * 2, + SM4_BLOCK_SIZE * 2,
@ -699,7 +660,7 @@ static struct shash_alg sm4_mac_algs[] = {
.digestsize = SM4_BLOCK_SIZE, .digestsize = SM4_BLOCK_SIZE,
.init = sm4_mac_init, .init = sm4_mac_init,
.update = sm4_mac_update, .update = sm4_mac_update,
.final = sm4_cmac_final, .finup = sm4_cmac_finup,
.setkey = sm4_cmac_setkey, .setkey = sm4_cmac_setkey,
.descsize = sizeof(struct sm4_mac_desc_ctx), .descsize = sizeof(struct sm4_mac_desc_ctx),
}, { }, {
@ -707,6 +668,8 @@ static struct shash_alg sm4_mac_algs[] = {
.cra_name = "xcbc(sm4)", .cra_name = "xcbc(sm4)",
.cra_driver_name = "xcbc-sm4-ce", .cra_driver_name = "xcbc-sm4-ce",
.cra_priority = 400, .cra_priority = 400,
.cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY |
CRYPTO_AHASH_ALG_FINAL_NONZERO,
.cra_blocksize = SM4_BLOCK_SIZE, .cra_blocksize = SM4_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct sm4_mac_tfm_ctx) .cra_ctxsize = sizeof(struct sm4_mac_tfm_ctx)
+ SM4_BLOCK_SIZE * 2, + SM4_BLOCK_SIZE * 2,
@ -715,7 +678,7 @@ static struct shash_alg sm4_mac_algs[] = {
.digestsize = SM4_BLOCK_SIZE, .digestsize = SM4_BLOCK_SIZE,
.init = sm4_mac_init, .init = sm4_mac_init,
.update = sm4_mac_update, .update = sm4_mac_update,
.final = sm4_cmac_final, .finup = sm4_cmac_finup,
.setkey = sm4_xcbc_setkey, .setkey = sm4_xcbc_setkey,
.descsize = sizeof(struct sm4_mac_desc_ctx), .descsize = sizeof(struct sm4_mac_desc_ctx),
}, { }, {
@ -723,14 +686,15 @@ static struct shash_alg sm4_mac_algs[] = {
.cra_name = "cbcmac(sm4)", .cra_name = "cbcmac(sm4)",
.cra_driver_name = "cbcmac-sm4-ce", .cra_driver_name = "cbcmac-sm4-ce",
.cra_priority = 400, .cra_priority = 400,
.cra_blocksize = 1, .cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY,
.cra_blocksize = SM4_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct sm4_mac_tfm_ctx), .cra_ctxsize = sizeof(struct sm4_mac_tfm_ctx),
.cra_module = THIS_MODULE, .cra_module = THIS_MODULE,
}, },
.digestsize = SM4_BLOCK_SIZE, .digestsize = SM4_BLOCK_SIZE,
.init = sm4_mac_init, .init = sm4_mac_init,
.update = sm4_mac_update, .update = sm4_mac_update,
.final = sm4_cbcmac_final, .finup = sm4_cbcmac_finup,
.setkey = sm4_cbcmac_setkey, .setkey = sm4_cbcmac_setkey,
.descsize = sizeof(struct sm4_mac_desc_ctx), .descsize = sizeof(struct sm4_mac_desc_ctx),
} }

View File

@ -1,4 +1,7 @@
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
obj-y += crypto/
lib-y := clear_user.o delay.o copy_from_user.o \ lib-y := clear_user.o delay.o copy_from_user.o \
copy_to_user.o copy_page.o \ copy_to_user.o copy_page.o \
clear_page.o csum.o insn.o memchr.o memcpy.o \ clear_page.o csum.o insn.o memchr.o memcpy.o \

3
arch/arm64/lib/crypto/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
# SPDX-License-Identifier: GPL-2.0-only
poly1305-core.S
sha256-core.S

View File

@ -0,0 +1,20 @@
# SPDX-License-Identifier: GPL-2.0-only
config CRYPTO_CHACHA20_NEON
tristate
depends on KERNEL_MODE_NEON
default CRYPTO_LIB_CHACHA
select CRYPTO_LIB_CHACHA_GENERIC
select CRYPTO_ARCH_HAVE_LIB_CHACHA
config CRYPTO_POLY1305_NEON
tristate
depends on KERNEL_MODE_NEON
default CRYPTO_LIB_POLY1305
select CRYPTO_ARCH_HAVE_LIB_POLY1305
config CRYPTO_SHA256_ARM64
tristate
default CRYPTO_LIB_SHA256
select CRYPTO_ARCH_HAVE_LIB_SHA256
select CRYPTO_ARCH_HAVE_LIB_SHA256_SIMD

View File

@ -0,0 +1,24 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_CRYPTO_CHACHA20_NEON) += chacha-neon.o
chacha-neon-y := chacha-neon-core.o chacha-neon-glue.o
obj-$(CONFIG_CRYPTO_POLY1305_NEON) += poly1305-neon.o
poly1305-neon-y := poly1305-core.o poly1305-glue.o
AFLAGS_poly1305-core.o += -Dpoly1305_init=poly1305_block_init_arch
AFLAGS_poly1305-core.o += -Dpoly1305_emit=poly1305_emit_arch
obj-$(CONFIG_CRYPTO_SHA256_ARM64) += sha256-arm64.o
sha256-arm64-y := sha256.o sha256-core.o
sha256-arm64-$(CONFIG_KERNEL_MODE_NEON) += sha256-ce.o
quiet_cmd_perlasm = PERLASM $@
cmd_perlasm = $(PERL) $(<) void $(@)
$(obj)/%-core.S: $(src)/%-armv8.pl
$(call cmd,perlasm)
$(obj)/sha256-core.S: $(src)/sha2-armv8.pl
$(call cmd,perlasm)
clean-files += poly1305-core.S sha256-core.S

View File

@ -1,5 +1,5 @@
/* /*
* ChaCha/XChaCha NEON helper functions * ChaCha/HChaCha NEON helper functions
* *
* Copyright (C) 2016-2018 Linaro, Ltd. <ard.biesheuvel@linaro.org> * Copyright (C) 2016-2018 Linaro, Ltd. <ard.biesheuvel@linaro.org>
* *

View File

@ -0,0 +1,119 @@
/*
* ChaCha and HChaCha functions (ARM64 optimized)
*
* Copyright (C) 2016 - 2017 Linaro, Ltd. <ard.biesheuvel@linaro.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Based on:
* ChaCha20 256-bit cipher algorithm, RFC7539, SIMD glue code
*
* Copyright (C) 2015 Martin Willi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <crypto/chacha.h>
#include <crypto/internal/simd.h>
#include <linux/jump_label.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <asm/hwcap.h>
#include <asm/neon.h>
#include <asm/simd.h>
asmlinkage void chacha_block_xor_neon(const struct chacha_state *state,
u8 *dst, const u8 *src, int nrounds);
asmlinkage void chacha_4block_xor_neon(const struct chacha_state *state,
u8 *dst, const u8 *src,
int nrounds, int bytes);
asmlinkage void hchacha_block_neon(const struct chacha_state *state,
u32 out[HCHACHA_OUT_WORDS], int nrounds);
static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_neon);
static void chacha_doneon(struct chacha_state *state, u8 *dst, const u8 *src,
int bytes, int nrounds)
{
while (bytes > 0) {
int l = min(bytes, CHACHA_BLOCK_SIZE * 5);
if (l <= CHACHA_BLOCK_SIZE) {
u8 buf[CHACHA_BLOCK_SIZE];
memcpy(buf, src, l);
chacha_block_xor_neon(state, buf, buf, nrounds);
memcpy(dst, buf, l);
state->x[12] += 1;
break;
}
chacha_4block_xor_neon(state, dst, src, nrounds, l);
bytes -= l;
src += l;
dst += l;
state->x[12] += DIV_ROUND_UP(l, CHACHA_BLOCK_SIZE);
}
}
void hchacha_block_arch(const struct chacha_state *state,
u32 out[HCHACHA_OUT_WORDS], int nrounds)
{
if (!static_branch_likely(&have_neon) || !crypto_simd_usable()) {
hchacha_block_generic(state, out, nrounds);
} else {
kernel_neon_begin();
hchacha_block_neon(state, out, nrounds);
kernel_neon_end();
}
}
EXPORT_SYMBOL(hchacha_block_arch);
void chacha_crypt_arch(struct chacha_state *state, u8 *dst, const u8 *src,
unsigned int bytes, int nrounds)
{
if (!static_branch_likely(&have_neon) || bytes <= CHACHA_BLOCK_SIZE ||
!crypto_simd_usable())
return chacha_crypt_generic(state, dst, src, bytes, nrounds);
do {
unsigned int todo = min_t(unsigned int, bytes, SZ_4K);
kernel_neon_begin();
chacha_doneon(state, dst, src, todo, nrounds);
kernel_neon_end();
bytes -= todo;
src += todo;
dst += todo;
} while (bytes);
}
EXPORT_SYMBOL(chacha_crypt_arch);
bool chacha_is_arch_optimized(void)
{
return static_key_enabled(&have_neon);
}
EXPORT_SYMBOL(chacha_is_arch_optimized);
static int __init chacha_simd_mod_init(void)
{
if (cpu_have_named_feature(ASIMD))
static_branch_enable(&have_neon);
return 0;
}
subsys_initcall(chacha_simd_mod_init);
static void __exit chacha_simd_mod_exit(void)
{
}
module_exit(chacha_simd_mod_exit);
MODULE_DESCRIPTION("ChaCha and HChaCha functions (ARM64 optimized)");
MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
MODULE_LICENSE("GPL v2");

View File

@ -0,0 +1,73 @@
// SPDX-License-Identifier: GPL-2.0
/*
* OpenSSL/Cryptogams accelerated Poly1305 transform for arm64
*
* Copyright (C) 2019 Linaro Ltd. <ard.biesheuvel@linaro.org>
*/
#include <asm/hwcap.h>
#include <asm/neon.h>
#include <crypto/internal/poly1305.h>
#include <linux/cpufeature.h>
#include <linux/jump_label.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/unaligned.h>
asmlinkage void poly1305_block_init_arch(
struct poly1305_block_state *state,
const u8 raw_key[POLY1305_BLOCK_SIZE]);
EXPORT_SYMBOL_GPL(poly1305_block_init_arch);
asmlinkage void poly1305_blocks(struct poly1305_block_state *state,
const u8 *src, u32 len, u32 hibit);
asmlinkage void poly1305_blocks_neon(struct poly1305_block_state *state,
const u8 *src, u32 len, u32 hibit);
asmlinkage void poly1305_emit_arch(const struct poly1305_state *state,
u8 digest[POLY1305_DIGEST_SIZE],
const u32 nonce[4]);
EXPORT_SYMBOL_GPL(poly1305_emit_arch);
static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_neon);
void poly1305_blocks_arch(struct poly1305_block_state *state, const u8 *src,
unsigned int len, u32 padbit)
{
len = round_down(len, POLY1305_BLOCK_SIZE);
if (static_branch_likely(&have_neon)) {
do {
unsigned int todo = min_t(unsigned int, len, SZ_4K);
kernel_neon_begin();
poly1305_blocks_neon(state, src, todo, 1);
kernel_neon_end();
len -= todo;
src += todo;
} while (len);
} else
poly1305_blocks(state, src, len, 1);
}
EXPORT_SYMBOL_GPL(poly1305_blocks_arch);
bool poly1305_is_arch_optimized(void)
{
/* We always can use at least the ARM64 scalar implementation. */
return true;
}
EXPORT_SYMBOL(poly1305_is_arch_optimized);
static int __init neon_poly1305_mod_init(void)
{
if (cpu_have_named_feature(ASIMD))
static_branch_enable(&have_neon);
return 0;
}
subsys_initcall(neon_poly1305_mod_init);
static void __exit neon_poly1305_mod_exit(void)
{
}
module_exit(neon_poly1305_mod_exit);
MODULE_DESCRIPTION("Poly1305 authenticator (ARM64 optimized)");
MODULE_LICENSE("GPL v2");

View File

@ -95,7 +95,7 @@ if ($output =~ /512/) {
$reg_t="w"; $reg_t="w";
} }
$func="sha${BITS}_block_data_order"; $func="sha${BITS}_blocks_arch";
($ctx,$inp,$num,$Ktbl)=map("x$_",(0..2,30)); ($ctx,$inp,$num,$Ktbl)=map("x$_",(0..2,30));

View File

@ -71,8 +71,8 @@
.word 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 .word 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
/* /*
* int __sha256_ce_transform(struct sha256_ce_state *sst, u8 const *src, * size_t __sha256_ce_transform(u32 state[SHA256_STATE_WORDS],
* int blocks) * const u8 *data, size_t nblocks);
*/ */
.text .text
SYM_FUNC_START(__sha256_ce_transform) SYM_FUNC_START(__sha256_ce_transform)
@ -86,20 +86,16 @@ SYM_FUNC_START(__sha256_ce_transform)
/* load state */ /* load state */
ld1 {dgav.4s, dgbv.4s}, [x0] ld1 {dgav.4s, dgbv.4s}, [x0]
/* load sha256_ce_state::finalize */
ldr_l w4, sha256_ce_offsetof_finalize, x4
ldr w4, [x0, x4]
/* load input */ /* load input */
0: ld1 {v16.4s-v19.4s}, [x1], #64 0: ld1 {v16.4s-v19.4s}, [x1], #64
sub w2, w2, #1 sub x2, x2, #1
CPU_LE( rev32 v16.16b, v16.16b ) CPU_LE( rev32 v16.16b, v16.16b )
CPU_LE( rev32 v17.16b, v17.16b ) CPU_LE( rev32 v17.16b, v17.16b )
CPU_LE( rev32 v18.16b, v18.16b ) CPU_LE( rev32 v18.16b, v18.16b )
CPU_LE( rev32 v19.16b, v19.16b ) CPU_LE( rev32 v19.16b, v19.16b )
1: add t0.4s, v16.4s, v0.4s add t0.4s, v16.4s, v0.4s
mov dg0v.16b, dgav.16b mov dg0v.16b, dgav.16b
mov dg1v.16b, dgbv.16b mov dg1v.16b, dgbv.16b
@ -127,31 +123,14 @@ CPU_LE( rev32 v19.16b, v19.16b )
add dgav.4s, dgav.4s, dg0v.4s add dgav.4s, dgav.4s, dg0v.4s
add dgbv.4s, dgbv.4s, dg1v.4s add dgbv.4s, dgbv.4s, dg1v.4s
/* handled all input blocks? */ /* return early if voluntary preemption is needed */
cbz w2, 2f cond_yield 1f, x5, x6
cond_yield 3f, x5, x6
b 0b
/* /* handled all input blocks? */
* Final block: add padding and total bit count. cbnz x2, 0b
* Skip if the input size was not a round multiple of the block size,
* the padding is handled by the C code in that case.
*/
2: cbz x4, 3f
ldr_l w4, sha256_ce_offsetof_count, x4
ldr x4, [x0, x4]
movi v17.2d, #0
mov x8, #0x80000000
movi v18.2d, #0
ror x7, x4, #29 // ror(lsl(x4, 3), 32)
fmov d16, x8
mov x4, #0
mov v19.d[0], xzr
mov v19.d[1], x7
b 1b
/* store new state */ /* store new state */
3: st1 {dgav.4s, dgbv.4s}, [x0] 1: st1 {dgav.4s, dgbv.4s}, [x0]
mov w0, w2 mov x0, x2
ret ret
SYM_FUNC_END(__sha256_ce_transform) SYM_FUNC_END(__sha256_ce_transform)

View File

@ -0,0 +1,75 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* SHA-256 optimized for ARM64
*
* Copyright 2025 Google LLC
*/
#include <asm/neon.h>
#include <crypto/internal/sha2.h>
#include <linux/kernel.h>
#include <linux/module.h>
asmlinkage void sha256_blocks_arch(u32 state[SHA256_STATE_WORDS],
const u8 *data, size_t nblocks);
EXPORT_SYMBOL_GPL(sha256_blocks_arch);
asmlinkage void sha256_block_neon(u32 state[SHA256_STATE_WORDS],
const u8 *data, size_t nblocks);
asmlinkage size_t __sha256_ce_transform(u32 state[SHA256_STATE_WORDS],
const u8 *data, size_t nblocks);
static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_neon);
static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_ce);
void sha256_blocks_simd(u32 state[SHA256_STATE_WORDS],
const u8 *data, size_t nblocks)
{
if (IS_ENABLED(CONFIG_KERNEL_MODE_NEON) &&
static_branch_likely(&have_neon)) {
if (static_branch_likely(&have_ce)) {
do {
size_t rem;
kernel_neon_begin();
rem = __sha256_ce_transform(state,
data, nblocks);
kernel_neon_end();
data += (nblocks - rem) * SHA256_BLOCK_SIZE;
nblocks = rem;
} while (nblocks);
} else {
kernel_neon_begin();
sha256_block_neon(state, data, nblocks);
kernel_neon_end();
}
} else {
sha256_blocks_arch(state, data, nblocks);
}
}
EXPORT_SYMBOL_GPL(sha256_blocks_simd);
bool sha256_is_arch_optimized(void)
{
/* We always can use at least the ARM64 scalar implementation. */
return true;
}
EXPORT_SYMBOL_GPL(sha256_is_arch_optimized);
static int __init sha256_arm64_mod_init(void)
{
if (IS_ENABLED(CONFIG_KERNEL_MODE_NEON) &&
cpu_have_named_feature(ASIMD)) {
static_branch_enable(&have_neon);
if (cpu_have_named_feature(SHA2))
static_branch_enable(&have_ce);
}
return 0;
}
subsys_initcall(sha256_arm64_mod_init);
static void __exit sha256_arm64_mod_exit(void)
{
}
module_exit(sha256_arm64_mod_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SHA-256 optimized for ARM64");

View File

@ -1026,7 +1026,7 @@ CONFIG_SECURITY_APPARMOR=y
CONFIG_SECURITY_YAMA=y CONFIG_SECURITY_YAMA=y
CONFIG_DEFAULT_SECURITY_DAC=y CONFIG_DEFAULT_SECURITY_DAC=y
CONFIG_CRYPTO_USER=m CONFIG_CRYPTO_USER=m
# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set CONFIG_CRYPTO_SELFTESTS=y
CONFIG_CRYPTO_PCRYPT=m CONFIG_CRYPTO_PCRYPT=m
CONFIG_CRYPTO_CRYPTD=m CONFIG_CRYPTO_CRYPTD=m
CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_ANUBIS=m

View File

@ -551,7 +551,7 @@ CONFIG_ENCRYPTED_KEYS=m
CONFIG_HARDENED_USERCOPY=y CONFIG_HARDENED_USERCOPY=y
CONFIG_CRYPTO_USER=m CONFIG_CRYPTO_USER=m
CONFIG_CRYPTO_CRYPTD=m CONFIG_CRYPTO_CRYPTD=m
CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_BENCHMARK=m
CONFIG_CRYPTO_RSA=m CONFIG_CRYPTO_RSA=m
CONFIG_CRYPTO_DH=m CONFIG_CRYPTO_DH=m
CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_ECDH=m

View File

@ -508,7 +508,7 @@ CONFIG_ENCRYPTED_KEYS=m
CONFIG_HARDENED_USERCOPY=y CONFIG_HARDENED_USERCOPY=y
CONFIG_CRYPTO_USER=m CONFIG_CRYPTO_USER=m
CONFIG_CRYPTO_CRYPTD=m CONFIG_CRYPTO_CRYPTD=m
CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_BENCHMARK=m
CONFIG_CRYPTO_RSA=m CONFIG_CRYPTO_RSA=m
CONFIG_CRYPTO_DH=m CONFIG_CRYPTO_DH=m
CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_ECDH=m

View File

@ -528,7 +528,7 @@ CONFIG_ENCRYPTED_KEYS=m
CONFIG_HARDENED_USERCOPY=y CONFIG_HARDENED_USERCOPY=y
CONFIG_CRYPTO_USER=m CONFIG_CRYPTO_USER=m
CONFIG_CRYPTO_CRYPTD=m CONFIG_CRYPTO_CRYPTD=m
CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_BENCHMARK=m
CONFIG_CRYPTO_RSA=m CONFIG_CRYPTO_RSA=m
CONFIG_CRYPTO_DH=m CONFIG_CRYPTO_DH=m
CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_ECDH=m

View File

@ -500,7 +500,7 @@ CONFIG_ENCRYPTED_KEYS=m
CONFIG_HARDENED_USERCOPY=y CONFIG_HARDENED_USERCOPY=y
CONFIG_CRYPTO_USER=m CONFIG_CRYPTO_USER=m
CONFIG_CRYPTO_CRYPTD=m CONFIG_CRYPTO_CRYPTD=m
CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_BENCHMARK=m
CONFIG_CRYPTO_RSA=m CONFIG_CRYPTO_RSA=m
CONFIG_CRYPTO_DH=m CONFIG_CRYPTO_DH=m
CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_ECDH=m

View File

@ -510,7 +510,7 @@ CONFIG_ENCRYPTED_KEYS=m
CONFIG_HARDENED_USERCOPY=y CONFIG_HARDENED_USERCOPY=y
CONFIG_CRYPTO_USER=m CONFIG_CRYPTO_USER=m
CONFIG_CRYPTO_CRYPTD=m CONFIG_CRYPTO_CRYPTD=m
CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_BENCHMARK=m
CONFIG_CRYPTO_RSA=m CONFIG_CRYPTO_RSA=m
CONFIG_CRYPTO_DH=m CONFIG_CRYPTO_DH=m
CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_ECDH=m

View File

@ -527,7 +527,7 @@ CONFIG_ENCRYPTED_KEYS=m
CONFIG_HARDENED_USERCOPY=y CONFIG_HARDENED_USERCOPY=y
CONFIG_CRYPTO_USER=m CONFIG_CRYPTO_USER=m
CONFIG_CRYPTO_CRYPTD=m CONFIG_CRYPTO_CRYPTD=m
CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_BENCHMARK=m
CONFIG_CRYPTO_RSA=m CONFIG_CRYPTO_RSA=m
CONFIG_CRYPTO_DH=m CONFIG_CRYPTO_DH=m
CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_ECDH=m

View File

@ -614,7 +614,7 @@ CONFIG_ENCRYPTED_KEYS=m
CONFIG_HARDENED_USERCOPY=y CONFIG_HARDENED_USERCOPY=y
CONFIG_CRYPTO_USER=m CONFIG_CRYPTO_USER=m
CONFIG_CRYPTO_CRYPTD=m CONFIG_CRYPTO_CRYPTD=m
CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_BENCHMARK=m
CONFIG_CRYPTO_RSA=m CONFIG_CRYPTO_RSA=m
CONFIG_CRYPTO_DH=m CONFIG_CRYPTO_DH=m
CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_ECDH=m

View File

@ -500,7 +500,7 @@ CONFIG_ENCRYPTED_KEYS=m
CONFIG_HARDENED_USERCOPY=y CONFIG_HARDENED_USERCOPY=y
CONFIG_CRYPTO_USER=m CONFIG_CRYPTO_USER=m
CONFIG_CRYPTO_CRYPTD=m CONFIG_CRYPTO_CRYPTD=m
CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_BENCHMARK=m
CONFIG_CRYPTO_RSA=m CONFIG_CRYPTO_RSA=m
CONFIG_CRYPTO_DH=m CONFIG_CRYPTO_DH=m
CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_ECDH=m

View File

@ -501,7 +501,7 @@ CONFIG_ENCRYPTED_KEYS=m
CONFIG_HARDENED_USERCOPY=y CONFIG_HARDENED_USERCOPY=y
CONFIG_CRYPTO_USER=m CONFIG_CRYPTO_USER=m
CONFIG_CRYPTO_CRYPTD=m CONFIG_CRYPTO_CRYPTD=m
CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_BENCHMARK=m
CONFIG_CRYPTO_RSA=m CONFIG_CRYPTO_RSA=m
CONFIG_CRYPTO_DH=m CONFIG_CRYPTO_DH=m
CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_ECDH=m

View File

@ -517,7 +517,7 @@ CONFIG_ENCRYPTED_KEYS=m
CONFIG_HARDENED_USERCOPY=y CONFIG_HARDENED_USERCOPY=y
CONFIG_CRYPTO_USER=m CONFIG_CRYPTO_USER=m
CONFIG_CRYPTO_CRYPTD=m CONFIG_CRYPTO_CRYPTD=m
CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_BENCHMARK=m
CONFIG_CRYPTO_RSA=m CONFIG_CRYPTO_RSA=m
CONFIG_CRYPTO_DH=m CONFIG_CRYPTO_DH=m
CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_ECDH=m

View File

@ -498,7 +498,7 @@ CONFIG_ENCRYPTED_KEYS=m
CONFIG_HARDENED_USERCOPY=y CONFIG_HARDENED_USERCOPY=y
CONFIG_CRYPTO_USER=m CONFIG_CRYPTO_USER=m
CONFIG_CRYPTO_CRYPTD=m CONFIG_CRYPTO_CRYPTD=m
CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_BENCHMARK=m
CONFIG_CRYPTO_RSA=m CONFIG_CRYPTO_RSA=m
CONFIG_CRYPTO_DH=m CONFIG_CRYPTO_DH=m
CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_ECDH=m

Some files were not shown because too many files have changed in this diff Show More