mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
Merge tag 'v6.13-p1' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
Pull crypto updates from Herbert Xu:
"API:
- Add sig driver API
- Remove signing/verification from akcipher API
- Move crypto_simd_disabled_for_test to lib/crypto
- Add WARN_ON for return values from driver that indicates memory
corruption
Algorithms:
- Provide crc32-arch and crc32c-arch through Crypto API
- Optimise crc32c code size on x86
- Optimise crct10dif on arm/arm64
- Optimise p10-aes-gcm on powerpc
- Optimise aegis128 on x86
- Output full sample from test interface in jitter RNG
- Retry without padata when it fails in pcrypt
Drivers:
- Add support for Airoha EN7581 TRNG
- Add support for STM32MP25x platforms in stm32
- Enable iproc-r200 RNG driver on BCMBCA
- Add Broadcom BCM74110 RNG driver"
* tag 'v6.13-p1' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6: (112 commits)
crypto: marvell/cesa - fix uninit value for struct mv_cesa_op_ctx
crypto: cavium - Fix an error handling path in cpt_ucode_load_fw()
crypto: aesni - Move back to module_init
crypto: lib/mpi - Export mpi_set_bit
crypto: aes-gcm-p10 - Use the correct bit to test for P10
hwrng: amd - remove reference to removed PPC_MAPLE config
crypto: arm/crct10dif - Implement plain NEON variant
crypto: arm/crct10dif - Macroify PMULL asm code
crypto: arm/crct10dif - Use existing mov_l macro instead of __adrl
crypto: arm64/crct10dif - Remove remaining 64x64 PMULL fallback code
crypto: arm64/crct10dif - Use faster 16x64 bit polynomial multiply
crypto: arm64/crct10dif - Remove obsolete chunking logic
crypto: bcm - add error check in the ahash_hmac_init function
crypto: caam - add error check to caam_rsa_set_priv_key_form
hwrng: bcm74110 - Add Broadcom BCM74110 RNG driver
dt-bindings: rng: add binding for BCM74110 RNG
padata: Clean up in padata_do_multithreaded()
crypto: inside-secure - Fix the return value of safexcel_xcbcmac_cra_init()
crypto: qat - Fix missing destroy_workqueue in adf_init_aer()
crypto: rsassa-pkcs1 - Reinstate support for legacy protocols
...
This commit is contained in:
@@ -184,3 +184,10 @@ Date: Apr 2020
|
||||
Contact: linux-crypto@vger.kernel.org
|
||||
Description: Dump the total number of time out requests.
|
||||
Available for both PF and VF, and take no other effect on HPRE.
|
||||
|
||||
What: /sys/kernel/debug/hisi_hpre/<bdf>/cap_regs
|
||||
Date: Oct 2024
|
||||
Contact: linux-crypto@vger.kernel.org
|
||||
Description: Dump the values of the qm and hpre capability bit registers and
|
||||
support the query of device specifications to facilitate fault locating.
|
||||
Available for both PF and VF, and take no other effect on HPRE.
|
||||
|
||||
@@ -157,3 +157,10 @@ Contact: linux-crypto@vger.kernel.org
|
||||
Description: Dump the total number of completed but marked error requests
|
||||
to be received.
|
||||
Available for both PF and VF, and take no other effect on SEC.
|
||||
|
||||
What: /sys/kernel/debug/hisi_sec2/<bdf>/cap_regs
|
||||
Date: Oct 2024
|
||||
Contact: linux-crypto@vger.kernel.org
|
||||
Description: Dump the values of the qm and sec capability bit registers and
|
||||
support the query of device specifications to facilitate fault locating.
|
||||
Available for both PF and VF, and take no other effect on SEC.
|
||||
|
||||
@@ -158,3 +158,10 @@ Contact: linux-crypto@vger.kernel.org
|
||||
Description: Dump the total number of BD type error requests
|
||||
to be received.
|
||||
Available for both PF and VF, and take no other effect on ZIP.
|
||||
|
||||
What: /sys/kernel/debug/hisi_zip/<bdf>/cap_regs
|
||||
Date: Oct 2024
|
||||
Contact: linux-crypto@vger.kernel.org
|
||||
Description: Dump the values of the qm and zip capability bit registers and
|
||||
support the query of device specifications to facilitate fault locating.
|
||||
Available for both PF and VF, and take no other effect on ZIP.
|
||||
|
||||
@@ -8,10 +8,10 @@ Asymmetric Cipher API
|
||||
---------------------
|
||||
|
||||
.. kernel-doc:: include/crypto/akcipher.h
|
||||
:doc: Generic Public Key API
|
||||
:doc: Generic Public Key Cipher API
|
||||
|
||||
.. kernel-doc:: include/crypto/akcipher.h
|
||||
:functions: crypto_alloc_akcipher crypto_free_akcipher crypto_akcipher_set_pub_key crypto_akcipher_set_priv_key crypto_akcipher_maxsize crypto_akcipher_encrypt crypto_akcipher_decrypt crypto_akcipher_sign crypto_akcipher_verify
|
||||
:functions: crypto_alloc_akcipher crypto_free_akcipher crypto_akcipher_set_pub_key crypto_akcipher_set_priv_key crypto_akcipher_maxsize crypto_akcipher_encrypt crypto_akcipher_decrypt
|
||||
|
||||
Asymmetric Cipher Request Handle
|
||||
--------------------------------
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
Asymmetric Signature Algorithm Definitions
|
||||
------------------------------------------
|
||||
|
||||
.. kernel-doc:: include/crypto/sig.h
|
||||
:functions: sig_alg
|
||||
|
||||
Asymmetric Signature API
|
||||
------------------------
|
||||
|
||||
.. kernel-doc:: include/crypto/sig.h
|
||||
:doc: Generic Public Key Signature API
|
||||
|
||||
.. kernel-doc:: include/crypto/sig.h
|
||||
:functions: crypto_alloc_sig crypto_free_sig crypto_sig_set_pubkey crypto_sig_set_privkey crypto_sig_keysize crypto_sig_maxsize crypto_sig_digestsize crypto_sig_sign crypto_sig_verify
|
||||
|
||||
@@ -10,4 +10,5 @@ Programming Interface
|
||||
api-digest
|
||||
api-rng
|
||||
api-akcipher
|
||||
api-sig
|
||||
api-kpp
|
||||
|
||||
@@ -214,6 +214,8 @@ the aforementioned cipher types:
|
||||
|
||||
- CRYPTO_ALG_TYPE_AKCIPHER Asymmetric cipher
|
||||
|
||||
- CRYPTO_ALG_TYPE_SIG Asymmetric signature
|
||||
|
||||
- CRYPTO_ALG_TYPE_PCOMPRESS Enhanced version of
|
||||
CRYPTO_ALG_TYPE_COMPRESS allowing for segmented compression /
|
||||
decompression instead of performing the operation on one segment
|
||||
|
||||
@@ -44,6 +44,7 @@ properties:
|
||||
|
||||
- items:
|
||||
- enum:
|
||||
- qcom,sa8775p-qce
|
||||
- qcom,sc7280-qce
|
||||
- qcom,sm6350-qce
|
||||
- qcom,sm8250-qce
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/rng/airoha,en7581-trng.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Airoha EN7851 True Random Number Generator
|
||||
|
||||
maintainers:
|
||||
- Christian Marangi <ansuelsmth@gmail.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: airoha,en7581-trng
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
|
||||
rng@1faa1000 {
|
||||
compatible = "airoha,en7581-trng";
|
||||
reg = <0x1faa1000 0x1000>;
|
||||
interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
@@ -0,0 +1,35 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/rng/brcm,bcm74110-rng.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: BCM74110 Random number generator
|
||||
|
||||
description:
|
||||
Random number generator used on the BCM74110.
|
||||
|
||||
maintainers:
|
||||
- Markus Mayer <mmayer@broadcom.com>
|
||||
- Florian Fainelli <florian.fainelli@broadcom.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- brcm,bcm74110-rng
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
rng@83ba000 {
|
||||
compatible = "brcm,bcm74110-rng";
|
||||
reg = <0x83ba000 0x14>;
|
||||
};
|
||||
@@ -14,8 +14,8 @@ properties:
|
||||
oneOf:
|
||||
- const: fsl,imx21-rnga
|
||||
- const: fsl,imx25-rngb
|
||||
- const: fsl,imx31-rnga
|
||||
- items:
|
||||
- const: fsl,imx31-rnga
|
||||
- const: fsl,imx21-rnga
|
||||
- items:
|
||||
- enum:
|
||||
|
||||
+11
-6
@@ -1,20 +1,25 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/rng/omap_rng.yaml#
|
||||
$id: http://devicetree.org/schemas/rng/inside-secure,safexcel-eip76.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: OMAP SoC and Inside-Secure HWRNG Module
|
||||
title: Inside-Secure HWRNG Module
|
||||
|
||||
maintainers:
|
||||
- Jayesh Choudhary <j-choudhary@ti.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- ti,omap2-rng
|
||||
- ti,omap4-rng
|
||||
- inside-secure,safexcel-eip76
|
||||
oneOf:
|
||||
- enum:
|
||||
- ti,omap2-rng
|
||||
- ti,omap4-rng
|
||||
- inside-secure,safexcel-eip76
|
||||
- items:
|
||||
- enum:
|
||||
- marvell,armada-8k-rng
|
||||
- const: inside-secure,safexcel-eip76
|
||||
|
||||
ti,hwmods:
|
||||
const: rng
|
||||
@@ -18,12 +18,19 @@ properties:
|
||||
enum:
|
||||
- st,stm32-rng
|
||||
- st,stm32mp13-rng
|
||||
- st,stm32mp25-rng
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: core
|
||||
- const: bus
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
@@ -57,6 +64,25 @@ allOf:
|
||||
properties:
|
||||
st,rng-lock-conf: false
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- st,stm32-rng
|
||||
- st,stm32mp13-rng
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 1
|
||||
clock-names: false
|
||||
else:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 2
|
||||
required:
|
||||
- clock-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
|
||||
+1
-1
@@ -11447,7 +11447,7 @@ Q: https://patchwork.kernel.org/project/linux-dmaengine/list/
|
||||
F: drivers/dma/ioat*
|
||||
|
||||
INTEL IAA CRYPTO DRIVER
|
||||
M: Tom Zanussi <tom.zanussi@linux.intel.com>
|
||||
M: Kristen Accardi <kristen.c.accardi@intel.com>
|
||||
L: linux-crypto@vger.kernel.org
|
||||
S: Supported
|
||||
F: Documentation/driver-api/crypto/iaa/iaa-crypto.rst
|
||||
|
||||
@@ -112,55 +112,120 @@
|
||||
FOLD_CONST_L .req q10l
|
||||
FOLD_CONST_H .req q10h
|
||||
|
||||
/*
|
||||
* Pairwise long polynomial multiplication of two 16-bit values
|
||||
*
|
||||
* { w0, w1 }, { y0, y1 }
|
||||
*
|
||||
* by two 64-bit values
|
||||
*
|
||||
* { x0, x1, x2, x3, x4, x5, x6, x7 }, { z0, z1, z2, z3, z4, z5, z6, z7 }
|
||||
*
|
||||
* where each vector element is a byte, ordered from least to most
|
||||
* significant. The resulting 80-bit vectors are XOR'ed together.
|
||||
*
|
||||
* This can be implemented using 8x8 long polynomial multiplication, by
|
||||
* reorganizing the input so that each pairwise 8x8 multiplication
|
||||
* produces one of the terms from the decomposition below, and
|
||||
* combining the results of each rank and shifting them into place.
|
||||
*
|
||||
* Rank
|
||||
* 0 w0*x0 ^ | y0*z0 ^
|
||||
* 1 (w0*x1 ^ w1*x0) << 8 ^ | (y0*z1 ^ y1*z0) << 8 ^
|
||||
* 2 (w0*x2 ^ w1*x1) << 16 ^ | (y0*z2 ^ y1*z1) << 16 ^
|
||||
* 3 (w0*x3 ^ w1*x2) << 24 ^ | (y0*z3 ^ y1*z2) << 24 ^
|
||||
* 4 (w0*x4 ^ w1*x3) << 32 ^ | (y0*z4 ^ y1*z3) << 32 ^
|
||||
* 5 (w0*x5 ^ w1*x4) << 40 ^ | (y0*z5 ^ y1*z4) << 40 ^
|
||||
* 6 (w0*x6 ^ w1*x5) << 48 ^ | (y0*z6 ^ y1*z5) << 48 ^
|
||||
* 7 (w0*x7 ^ w1*x6) << 56 ^ | (y0*z7 ^ y1*z6) << 56 ^
|
||||
* 8 w1*x7 << 64 | y1*z7 << 64
|
||||
*
|
||||
* The inputs can be reorganized into
|
||||
*
|
||||
* { w0, w0, w0, w0, y0, y0, y0, y0 }, { w1, w1, w1, w1, y1, y1, y1, y1 }
|
||||
* { x0, x2, x4, x6, z0, z2, z4, z6 }, { x1, x3, x5, x7, z1, z3, z5, z7 }
|
||||
*
|
||||
* and after performing 8x8->16 bit long polynomial multiplication of
|
||||
* each of the halves of the first vector with those of the second one,
|
||||
* we obtain the following four vectors of 16-bit elements:
|
||||
*
|
||||
* a := { w0*x0, w0*x2, w0*x4, w0*x6 }, { y0*z0, y0*z2, y0*z4, y0*z6 }
|
||||
* b := { w0*x1, w0*x3, w0*x5, w0*x7 }, { y0*z1, y0*z3, y0*z5, y0*z7 }
|
||||
* c := { w1*x0, w1*x2, w1*x4, w1*x6 }, { y1*z0, y1*z2, y1*z4, y1*z6 }
|
||||
* d := { w1*x1, w1*x3, w1*x5, w1*x7 }, { y1*z1, y1*z3, y1*z5, y1*z7 }
|
||||
*
|
||||
* Results b and c can be XORed together, as the vector elements have
|
||||
* matching ranks. Then, the final XOR can be pulled forward, and
|
||||
* applied between the halves of each of the remaining three vectors,
|
||||
* which are then shifted into place, and XORed together to produce the
|
||||
* final 80-bit result.
|
||||
*/
|
||||
.macro pmull16x64_p8, v16, v64
|
||||
vext.8 q11, \v64, \v64, #1
|
||||
vld1.64 {q12}, [r4, :128]
|
||||
vuzp.8 q11, \v64
|
||||
vtbl.8 d24, {\v16\()_L-\v16\()_H}, d24
|
||||
vtbl.8 d25, {\v16\()_L-\v16\()_H}, d25
|
||||
bl __pmull16x64_p8
|
||||
veor \v64, q12, q14
|
||||
.endm
|
||||
|
||||
__pmull16x64_p8:
|
||||
vmull.p8 q13, d23, d24
|
||||
vmull.p8 q14, d23, d25
|
||||
vmull.p8 q15, d22, d24
|
||||
vmull.p8 q12, d22, d25
|
||||
|
||||
veor q14, q14, q15
|
||||
veor d24, d24, d25
|
||||
veor d26, d26, d27
|
||||
veor d28, d28, d29
|
||||
vmov.i32 d25, #0
|
||||
vmov.i32 d29, #0
|
||||
vext.8 q12, q12, q12, #14
|
||||
vext.8 q14, q14, q14, #15
|
||||
veor d24, d24, d26
|
||||
bx lr
|
||||
ENDPROC(__pmull16x64_p8)
|
||||
|
||||
.macro pmull16x64_p64, v16, v64
|
||||
vmull.p64 q11, \v64\()l, \v16\()_L
|
||||
vmull.p64 \v64, \v64\()h, \v16\()_H
|
||||
veor \v64, \v64, q11
|
||||
.endm
|
||||
|
||||
// Fold reg1, reg2 into the next 32 data bytes, storing the result back
|
||||
// into reg1, reg2.
|
||||
.macro fold_32_bytes, reg1, reg2
|
||||
vld1.64 {q11-q12}, [buf]!
|
||||
.macro fold_32_bytes, reg1, reg2, p
|
||||
vld1.64 {q8-q9}, [buf]!
|
||||
|
||||
vmull.p64 q8, \reg1\()h, FOLD_CONST_H
|
||||
vmull.p64 \reg1, \reg1\()l, FOLD_CONST_L
|
||||
vmull.p64 q9, \reg2\()h, FOLD_CONST_H
|
||||
vmull.p64 \reg2, \reg2\()l, FOLD_CONST_L
|
||||
pmull16x64_\p FOLD_CONST, \reg1
|
||||
pmull16x64_\p FOLD_CONST, \reg2
|
||||
|
||||
CPU_LE( vrev64.8 q11, q11 )
|
||||
CPU_LE( vrev64.8 q12, q12 )
|
||||
vswp q11l, q11h
|
||||
vswp q12l, q12h
|
||||
CPU_LE( vrev64.8 q8, q8 )
|
||||
CPU_LE( vrev64.8 q9, q9 )
|
||||
vswp q8l, q8h
|
||||
vswp q9l, q9h
|
||||
|
||||
veor.8 \reg1, \reg1, q8
|
||||
veor.8 \reg2, \reg2, q9
|
||||
veor.8 \reg1, \reg1, q11
|
||||
veor.8 \reg2, \reg2, q12
|
||||
.endm
|
||||
|
||||
// Fold src_reg into dst_reg, optionally loading the next fold constants
|
||||
.macro fold_16_bytes, src_reg, dst_reg, load_next_consts
|
||||
vmull.p64 q8, \src_reg\()l, FOLD_CONST_L
|
||||
vmull.p64 \src_reg, \src_reg\()h, FOLD_CONST_H
|
||||
.macro fold_16_bytes, src_reg, dst_reg, p, load_next_consts
|
||||
pmull16x64_\p FOLD_CONST, \src_reg
|
||||
.ifnb \load_next_consts
|
||||
vld1.64 {FOLD_CONSTS}, [fold_consts_ptr, :128]!
|
||||
.endif
|
||||
veor.8 \dst_reg, \dst_reg, q8
|
||||
veor.8 \dst_reg, \dst_reg, \src_reg
|
||||
.endm
|
||||
|
||||
.macro __adrl, out, sym
|
||||
movw \out, #:lower16:\sym
|
||||
movt \out, #:upper16:\sym
|
||||
.endm
|
||||
|
||||
//
|
||||
// u16 crc_t10dif_pmull(u16 init_crc, const u8 *buf, size_t len);
|
||||
//
|
||||
// Assumes len >= 16.
|
||||
//
|
||||
ENTRY(crc_t10dif_pmull)
|
||||
|
||||
.macro crct10dif, p
|
||||
// For sizes less than 256 bytes, we can't fold 128 bytes at a time.
|
||||
cmp len, #256
|
||||
blt .Lless_than_256_bytes
|
||||
blt .Lless_than_256_bytes\@
|
||||
|
||||
__adrl fold_consts_ptr, .Lfold_across_128_bytes_consts
|
||||
mov_l fold_consts_ptr, .Lfold_across_128_bytes_consts
|
||||
|
||||
// Load the first 128 data bytes. Byte swapping is necessary to make
|
||||
// the bit order match the polynomial coefficient order.
|
||||
@@ -199,27 +264,27 @@ CPU_LE( vrev64.8 q7, q7 )
|
||||
|
||||
// While >= 128 data bytes remain (not counting q0-q7), fold the 128
|
||||
// bytes q0-q7 into them, storing the result back into q0-q7.
|
||||
.Lfold_128_bytes_loop:
|
||||
fold_32_bytes q0, q1
|
||||
fold_32_bytes q2, q3
|
||||
fold_32_bytes q4, q5
|
||||
fold_32_bytes q6, q7
|
||||
.Lfold_128_bytes_loop\@:
|
||||
fold_32_bytes q0, q1, \p
|
||||
fold_32_bytes q2, q3, \p
|
||||
fold_32_bytes q4, q5, \p
|
||||
fold_32_bytes q6, q7, \p
|
||||
subs len, len, #128
|
||||
bge .Lfold_128_bytes_loop
|
||||
bge .Lfold_128_bytes_loop\@
|
||||
|
||||
// Now fold the 112 bytes in q0-q6 into the 16 bytes in q7.
|
||||
|
||||
// Fold across 64 bytes.
|
||||
vld1.64 {FOLD_CONSTS}, [fold_consts_ptr, :128]!
|
||||
fold_16_bytes q0, q4
|
||||
fold_16_bytes q1, q5
|
||||
fold_16_bytes q2, q6
|
||||
fold_16_bytes q3, q7, 1
|
||||
fold_16_bytes q0, q4, \p
|
||||
fold_16_bytes q1, q5, \p
|
||||
fold_16_bytes q2, q6, \p
|
||||
fold_16_bytes q3, q7, \p, 1
|
||||
// Fold across 32 bytes.
|
||||
fold_16_bytes q4, q6
|
||||
fold_16_bytes q5, q7, 1
|
||||
fold_16_bytes q4, q6, \p
|
||||
fold_16_bytes q5, q7, \p, 1
|
||||
// Fold across 16 bytes.
|
||||
fold_16_bytes q6, q7
|
||||
fold_16_bytes q6, q7, \p
|
||||
|
||||
// Add 128 to get the correct number of data bytes remaining in 0...127
|
||||
// (not counting q7), following the previous extra subtraction by 128.
|
||||
@@ -229,25 +294,23 @@ CPU_LE( vrev64.8 q7, q7 )
|
||||
|
||||
// While >= 16 data bytes remain (not counting q7), fold the 16 bytes q7
|
||||
// into them, storing the result back into q7.
|
||||
blt .Lfold_16_bytes_loop_done
|
||||
.Lfold_16_bytes_loop:
|
||||
vmull.p64 q8, q7l, FOLD_CONST_L
|
||||
vmull.p64 q7, q7h, FOLD_CONST_H
|
||||
veor.8 q7, q7, q8
|
||||
blt .Lfold_16_bytes_loop_done\@
|
||||
.Lfold_16_bytes_loop\@:
|
||||
pmull16x64_\p FOLD_CONST, q7
|
||||
vld1.64 {q0}, [buf]!
|
||||
CPU_LE( vrev64.8 q0, q0 )
|
||||
vswp q0l, q0h
|
||||
veor.8 q7, q7, q0
|
||||
subs len, len, #16
|
||||
bge .Lfold_16_bytes_loop
|
||||
bge .Lfold_16_bytes_loop\@
|
||||
|
||||
.Lfold_16_bytes_loop_done:
|
||||
.Lfold_16_bytes_loop_done\@:
|
||||
// Add 16 to get the correct number of data bytes remaining in 0...15
|
||||
// (not counting q7), following the previous extra subtraction by 16.
|
||||
adds len, len, #16
|
||||
beq .Lreduce_final_16_bytes
|
||||
beq .Lreduce_final_16_bytes\@
|
||||
|
||||
.Lhandle_partial_segment:
|
||||
.Lhandle_partial_segment\@:
|
||||
// Reduce the last '16 + len' bytes where 1 <= len <= 15 and the first
|
||||
// 16 bytes are in q7 and the rest are the remaining data in 'buf'. To
|
||||
// do this without needing a fold constant for each possible 'len',
|
||||
@@ -262,9 +325,9 @@ CPU_LE( vrev64.8 q0, q0 )
|
||||
vswp q0l, q0h
|
||||
|
||||
// q1 = high order part of second chunk: q7 left-shifted by 'len' bytes.
|
||||
__adrl r3, .Lbyteshift_table + 16
|
||||
sub r3, r3, len
|
||||
vld1.8 {q2}, [r3]
|
||||
mov_l r1, .Lbyteshift_table + 16
|
||||
sub r1, r1, len
|
||||
vld1.8 {q2}, [r1]
|
||||
vtbl.8 q1l, {q7l-q7h}, q2l
|
||||
vtbl.8 q1h, {q7l-q7h}, q2h
|
||||
|
||||
@@ -282,12 +345,46 @@ CPU_LE( vrev64.8 q0, q0 )
|
||||
vbsl.8 q2, q1, q0
|
||||
|
||||
// Fold the first chunk into the second chunk, storing the result in q7.
|
||||
vmull.p64 q0, q3l, FOLD_CONST_L
|
||||
vmull.p64 q7, q3h, FOLD_CONST_H
|
||||
veor.8 q7, q7, q0
|
||||
veor.8 q7, q7, q2
|
||||
pmull16x64_\p FOLD_CONST, q3
|
||||
veor.8 q7, q3, q2
|
||||
b .Lreduce_final_16_bytes\@
|
||||
|
||||
.Lless_than_256_bytes\@:
|
||||
// Checksumming a buffer of length 16...255 bytes
|
||||
|
||||
mov_l fold_consts_ptr, .Lfold_across_16_bytes_consts
|
||||
|
||||
// Load the first 16 data bytes.
|
||||
vld1.64 {q7}, [buf]!
|
||||
CPU_LE( vrev64.8 q7, q7 )
|
||||
vswp q7l, q7h
|
||||
|
||||
// XOR the first 16 data *bits* with the initial CRC value.
|
||||
vmov.i8 q0h, #0
|
||||
vmov.u16 q0h[3], init_crc
|
||||
veor.8 q7h, q7h, q0h
|
||||
|
||||
// Load the fold-across-16-bytes constants.
|
||||
vld1.64 {FOLD_CONSTS}, [fold_consts_ptr, :128]!
|
||||
|
||||
cmp len, #16
|
||||
beq .Lreduce_final_16_bytes\@ // len == 16
|
||||
subs len, len, #32
|
||||
addlt len, len, #16
|
||||
blt .Lhandle_partial_segment\@ // 17 <= len <= 31
|
||||
b .Lfold_16_bytes_loop\@ // 32 <= len <= 255
|
||||
|
||||
.Lreduce_final_16_bytes\@:
|
||||
.endm
|
||||
|
||||
//
|
||||
// u16 crc_t10dif_pmull(u16 init_crc, const u8 *buf, size_t len);
|
||||
//
|
||||
// Assumes len >= 16.
|
||||
//
|
||||
ENTRY(crc_t10dif_pmull64)
|
||||
crct10dif p64
|
||||
|
||||
.Lreduce_final_16_bytes:
|
||||
// Reduce the 128-bit value M(x), stored in q7, to the final 16-bit CRC.
|
||||
|
||||
// Load 'x^48 * (x^48 mod G(x))' and 'x^48 * (x^80 mod G(x))'.
|
||||
@@ -320,32 +417,19 @@ CPU_LE( vrev64.8 q0, q0 )
|
||||
|
||||
vmov.u16 r0, q0l[0]
|
||||
bx lr
|
||||
ENDPROC(crc_t10dif_pmull64)
|
||||
|
||||
.Lless_than_256_bytes:
|
||||
// Checksumming a buffer of length 16...255 bytes
|
||||
ENTRY(crc_t10dif_pmull8)
|
||||
push {r4, lr}
|
||||
mov_l r4, .L16x64perm
|
||||
|
||||
__adrl fold_consts_ptr, .Lfold_across_16_bytes_consts
|
||||
crct10dif p8
|
||||
|
||||
// Load the first 16 data bytes.
|
||||
vld1.64 {q7}, [buf]!
|
||||
CPU_LE( vrev64.8 q7, q7 )
|
||||
vswp q7l, q7h
|
||||
|
||||
// XOR the first 16 data *bits* with the initial CRC value.
|
||||
vmov.i8 q0h, #0
|
||||
vmov.u16 q0h[3], init_crc
|
||||
veor.8 q7h, q7h, q0h
|
||||
|
||||
// Load the fold-across-16-bytes constants.
|
||||
vld1.64 {FOLD_CONSTS}, [fold_consts_ptr, :128]!
|
||||
|
||||
cmp len, #16
|
||||
beq .Lreduce_final_16_bytes // len == 16
|
||||
subs len, len, #32
|
||||
addlt len, len, #16
|
||||
blt .Lhandle_partial_segment // 17 <= len <= 31
|
||||
b .Lfold_16_bytes_loop // 32 <= len <= 255
|
||||
ENDPROC(crc_t10dif_pmull)
|
||||
vst1.64 {q7}, [r3, :128]
|
||||
pop {r4, pc}
|
||||
ENDPROC(crc_t10dif_pmull8)
|
||||
|
||||
.section ".rodata", "a"
|
||||
.align 4
|
||||
@@ -379,3 +463,6 @@ ENDPROC(crc_t10dif_pmull)
|
||||
.byte 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f
|
||||
.byte 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7
|
||||
.byte 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe , 0x0
|
||||
|
||||
.L16x64perm:
|
||||
.quad 0x808080800000000, 0x909090901010101
|
||||
|
||||
@@ -19,7 +19,9 @@
|
||||
|
||||
#define CRC_T10DIF_PMULL_CHUNK_SIZE 16U
|
||||
|
||||
asmlinkage u16 crc_t10dif_pmull(u16 init_crc, const u8 *buf, size_t len);
|
||||
asmlinkage u16 crc_t10dif_pmull64(u16 init_crc, const u8 *buf, size_t len);
|
||||
asmlinkage void crc_t10dif_pmull8(u16 init_crc, const u8 *buf, size_t len,
|
||||
u8 out[16]);
|
||||
|
||||
static int crct10dif_init(struct shash_desc *desc)
|
||||
{
|
||||
@@ -29,14 +31,14 @@ static int crct10dif_init(struct shash_desc *desc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int crct10dif_update(struct shash_desc *desc, const u8 *data,
|
||||
unsigned int length)
|
||||
static int crct10dif_update_ce(struct shash_desc *desc, const u8 *data,
|
||||
unsigned int length)
|
||||
{
|
||||
u16 *crc = shash_desc_ctx(desc);
|
||||
|
||||
if (length >= CRC_T10DIF_PMULL_CHUNK_SIZE && crypto_simd_usable()) {
|
||||
kernel_neon_begin();
|
||||
*crc = crc_t10dif_pmull(*crc, data, length);
|
||||
*crc = crc_t10dif_pmull64(*crc, data, length);
|
||||
kernel_neon_end();
|
||||
} else {
|
||||
*crc = crc_t10dif_generic(*crc, data, length);
|
||||
@@ -45,6 +47,27 @@ static int crct10dif_update(struct shash_desc *desc, const u8 *data,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int crct10dif_update_neon(struct shash_desc *desc, const u8 *data,
|
||||
unsigned int length)
|
||||
{
|
||||
u16 *crcp = shash_desc_ctx(desc);
|
||||
u8 buf[16] __aligned(16);
|
||||
u16 crc = *crcp;
|
||||
|
||||
if (length > CRC_T10DIF_PMULL_CHUNK_SIZE && crypto_simd_usable()) {
|
||||
kernel_neon_begin();
|
||||
crc_t10dif_pmull8(crc, data, length, buf);
|
||||
kernel_neon_end();
|
||||
|
||||
crc = 0;
|
||||
data = buf;
|
||||
length = sizeof(buf);
|
||||
}
|
||||
|
||||
*crcp = crc_t10dif_generic(crc, data, length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int crct10dif_final(struct shash_desc *desc, u8 *out)
|
||||
{
|
||||
u16 *crc = shash_desc_ctx(desc);
|
||||
@@ -53,10 +76,22 @@ static int crct10dif_final(struct shash_desc *desc, u8 *out)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct shash_alg crc_t10dif_alg = {
|
||||
static struct shash_alg algs[] = {{
|
||||
.digestsize = CRC_T10DIF_DIGEST_SIZE,
|
||||
.init = crct10dif_init,
|
||||
.update = crct10dif_update,
|
||||
.update = crct10dif_update_neon,
|
||||
.final = crct10dif_final,
|
||||
.descsize = CRC_T10DIF_DIGEST_SIZE,
|
||||
|
||||
.base.cra_name = "crct10dif",
|
||||
.base.cra_driver_name = "crct10dif-arm-neon",
|
||||
.base.cra_priority = 150,
|
||||
.base.cra_blocksize = CRC_T10DIF_BLOCK_SIZE,
|
||||
.base.cra_module = THIS_MODULE,
|
||||
}, {
|
||||
.digestsize = CRC_T10DIF_DIGEST_SIZE,
|
||||
.init = crct10dif_init,
|
||||
.update = crct10dif_update_ce,
|
||||
.final = crct10dif_final,
|
||||
.descsize = CRC_T10DIF_DIGEST_SIZE,
|
||||
|
||||
@@ -65,19 +100,19 @@ static struct shash_alg crc_t10dif_alg = {
|
||||
.base.cra_priority = 200,
|
||||
.base.cra_blocksize = CRC_T10DIF_BLOCK_SIZE,
|
||||
.base.cra_module = THIS_MODULE,
|
||||
};
|
||||
}};
|
||||
|
||||
static int __init crc_t10dif_mod_init(void)
|
||||
{
|
||||
if (!(elf_hwcap2 & HWCAP2_PMULL))
|
||||
if (!(elf_hwcap & HWCAP_NEON))
|
||||
return -ENODEV;
|
||||
|
||||
return crypto_register_shash(&crc_t10dif_alg);
|
||||
return crypto_register_shashes(algs, 1 + !!(elf_hwcap2 & HWCAP2_PMULL));
|
||||
}
|
||||
|
||||
static void __exit crc_t10dif_mod_exit(void)
|
||||
{
|
||||
crypto_unregister_shash(&crc_t10dif_alg);
|
||||
crypto_unregister_shashes(algs, 1 + !!(elf_hwcap2 & HWCAP2_PMULL));
|
||||
}
|
||||
|
||||
module_init(crc_t10dif_mod_init);
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
//
|
||||
// Accelerated CRC-T10DIF using arm64 NEON and Crypto Extensions instructions
|
||||
//
|
||||
// Copyright (C) 2016 Linaro Ltd <ard.biesheuvel@linaro.org>
|
||||
// Copyright (C) 2019 Google LLC <ebiggers@google.com>
|
||||
// Copyright (C) 2016 Linaro Ltd
|
||||
// Copyright (C) 2019-2024 Google LLC
|
||||
//
|
||||
// Authors: Ard Biesheuvel <ardb@google.com>
|
||||
// Eric Biggers <ebiggers@google.com>
|
||||
//
|
||||
// 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
|
||||
@@ -71,161 +74,117 @@
|
||||
init_crc .req w0
|
||||
buf .req x1
|
||||
len .req x2
|
||||
fold_consts_ptr .req x3
|
||||
fold_consts_ptr .req x5
|
||||
|
||||
fold_consts .req v10
|
||||
|
||||
ad .req v14
|
||||
|
||||
k00_16 .req v15
|
||||
k32_48 .req v16
|
||||
|
||||
t3 .req v17
|
||||
t4 .req v18
|
||||
t5 .req v19
|
||||
t6 .req v20
|
||||
t7 .req v21
|
||||
t8 .req v22
|
||||
t9 .req v23
|
||||
|
||||
perm1 .req v24
|
||||
perm2 .req v25
|
||||
perm3 .req v26
|
||||
perm4 .req v27
|
||||
perm .req v27
|
||||
|
||||
bd1 .req v28
|
||||
bd2 .req v29
|
||||
bd3 .req v30
|
||||
bd4 .req v31
|
||||
|
||||
.macro __pmull_init_p64
|
||||
.macro pmull16x64_p64, a16, b64, c64
|
||||
pmull2 \c64\().1q, \a16\().2d, \b64\().2d
|
||||
pmull \b64\().1q, \a16\().1d, \b64\().1d
|
||||
.endm
|
||||
|
||||
.macro __pmull_pre_p64, bd
|
||||
/*
|
||||
* Pairwise long polynomial multiplication of two 16-bit values
|
||||
*
|
||||
* { w0, w1 }, { y0, y1 }
|
||||
*
|
||||
* by two 64-bit values
|
||||
*
|
||||
* { x0, x1, x2, x3, x4, x5, x6, x7 }, { z0, z1, z2, z3, z4, z5, z6, z7 }
|
||||
*
|
||||
* where each vector element is a byte, ordered from least to most
|
||||
* significant.
|
||||
*
|
||||
* This can be implemented using 8x8 long polynomial multiplication, by
|
||||
* reorganizing the input so that each pairwise 8x8 multiplication
|
||||
* produces one of the terms from the decomposition below, and
|
||||
* combining the results of each rank and shifting them into place.
|
||||
*
|
||||
* Rank
|
||||
* 0 w0*x0 ^ | y0*z0 ^
|
||||
* 1 (w0*x1 ^ w1*x0) << 8 ^ | (y0*z1 ^ y1*z0) << 8 ^
|
||||
* 2 (w0*x2 ^ w1*x1) << 16 ^ | (y0*z2 ^ y1*z1) << 16 ^
|
||||
* 3 (w0*x3 ^ w1*x2) << 24 ^ | (y0*z3 ^ y1*z2) << 24 ^
|
||||
* 4 (w0*x4 ^ w1*x3) << 32 ^ | (y0*z4 ^ y1*z3) << 32 ^
|
||||
* 5 (w0*x5 ^ w1*x4) << 40 ^ | (y0*z5 ^ y1*z4) << 40 ^
|
||||
* 6 (w0*x6 ^ w1*x5) << 48 ^ | (y0*z6 ^ y1*z5) << 48 ^
|
||||
* 7 (w0*x7 ^ w1*x6) << 56 ^ | (y0*z7 ^ y1*z6) << 56 ^
|
||||
* 8 w1*x7 << 64 | y1*z7 << 64
|
||||
*
|
||||
* The inputs can be reorganized into
|
||||
*
|
||||
* { w0, w0, w0, w0, y0, y0, y0, y0 }, { w1, w1, w1, w1, y1, y1, y1, y1 }
|
||||
* { x0, x2, x4, x6, z0, z2, z4, z6 }, { x1, x3, x5, x7, z1, z3, z5, z7 }
|
||||
*
|
||||
* and after performing 8x8->16 bit long polynomial multiplication of
|
||||
* each of the halves of the first vector with those of the second one,
|
||||
* we obtain the following four vectors of 16-bit elements:
|
||||
*
|
||||
* a := { w0*x0, w0*x2, w0*x4, w0*x6 }, { y0*z0, y0*z2, y0*z4, y0*z6 }
|
||||
* b := { w0*x1, w0*x3, w0*x5, w0*x7 }, { y0*z1, y0*z3, y0*z5, y0*z7 }
|
||||
* c := { w1*x0, w1*x2, w1*x4, w1*x6 }, { y1*z0, y1*z2, y1*z4, y1*z6 }
|
||||
* d := { w1*x1, w1*x3, w1*x5, w1*x7 }, { y1*z1, y1*z3, y1*z5, y1*z7 }
|
||||
*
|
||||
* Results b and c can be XORed together, as the vector elements have
|
||||
* matching ranks. Then, the final XOR (*) can be pulled forward, and
|
||||
* applied between the halves of each of the remaining three vectors,
|
||||
* which are then shifted into place, and combined to produce two
|
||||
* 80-bit results.
|
||||
*
|
||||
* (*) NOTE: the 16x64 bit polynomial multiply below is not equivalent
|
||||
* to the 64x64 bit one above, but XOR'ing the outputs together will
|
||||
* produce the expected result, and this is sufficient in the context of
|
||||
* this algorithm.
|
||||
*/
|
||||
.macro pmull16x64_p8, a16, b64, c64
|
||||
ext t7.16b, \b64\().16b, \b64\().16b, #1
|
||||
tbl t5.16b, {\a16\().16b}, perm.16b
|
||||
uzp1 t7.16b, \b64\().16b, t7.16b
|
||||
bl __pmull_p8_16x64
|
||||
ext \b64\().16b, t4.16b, t4.16b, #15
|
||||
eor \c64\().16b, t8.16b, t5.16b
|
||||
.endm
|
||||
|
||||
.macro __pmull_init_p8
|
||||
// k00_16 := 0x0000000000000000_000000000000ffff
|
||||
// k32_48 := 0x00000000ffffffff_0000ffffffffffff
|
||||
movi k32_48.2d, #0xffffffff
|
||||
mov k32_48.h[2], k32_48.h[0]
|
||||
ushr k00_16.2d, k32_48.2d, #32
|
||||
SYM_FUNC_START_LOCAL(__pmull_p8_16x64)
|
||||
ext t6.16b, t5.16b, t5.16b, #8
|
||||
|
||||
// prepare the permutation vectors
|
||||
mov_q x5, 0x080f0e0d0c0b0a09
|
||||
movi perm4.8b, #8
|
||||
dup perm1.2d, x5
|
||||
eor perm1.16b, perm1.16b, perm4.16b
|
||||
ushr perm2.2d, perm1.2d, #8
|
||||
ushr perm3.2d, perm1.2d, #16
|
||||
ushr perm4.2d, perm1.2d, #24
|
||||
sli perm2.2d, perm1.2d, #56
|
||||
sli perm3.2d, perm1.2d, #48
|
||||
sli perm4.2d, perm1.2d, #40
|
||||
.endm
|
||||
pmull t3.8h, t7.8b, t5.8b
|
||||
pmull t4.8h, t7.8b, t6.8b
|
||||
pmull2 t5.8h, t7.16b, t5.16b
|
||||
pmull2 t6.8h, t7.16b, t6.16b
|
||||
|
||||
.macro __pmull_pre_p8, bd
|
||||
tbl bd1.16b, {\bd\().16b}, perm1.16b
|
||||
tbl bd2.16b, {\bd\().16b}, perm2.16b
|
||||
tbl bd3.16b, {\bd\().16b}, perm3.16b
|
||||
tbl bd4.16b, {\bd\().16b}, perm4.16b
|
||||
.endm
|
||||
|
||||
SYM_FUNC_START_LOCAL(__pmull_p8_core)
|
||||
.L__pmull_p8_core:
|
||||
ext t4.8b, ad.8b, ad.8b, #1 // A1
|
||||
ext t5.8b, ad.8b, ad.8b, #2 // A2
|
||||
ext t6.8b, ad.8b, ad.8b, #3 // A3
|
||||
|
||||
pmull t4.8h, t4.8b, fold_consts.8b // F = A1*B
|
||||
pmull t8.8h, ad.8b, bd1.8b // E = A*B1
|
||||
pmull t5.8h, t5.8b, fold_consts.8b // H = A2*B
|
||||
pmull t7.8h, ad.8b, bd2.8b // G = A*B2
|
||||
pmull t6.8h, t6.8b, fold_consts.8b // J = A3*B
|
||||
pmull t9.8h, ad.8b, bd3.8b // I = A*B3
|
||||
pmull t3.8h, ad.8b, bd4.8b // K = A*B4
|
||||
b 0f
|
||||
|
||||
.L__pmull_p8_core2:
|
||||
tbl t4.16b, {ad.16b}, perm1.16b // A1
|
||||
tbl t5.16b, {ad.16b}, perm2.16b // A2
|
||||
tbl t6.16b, {ad.16b}, perm3.16b // A3
|
||||
|
||||
pmull2 t4.8h, t4.16b, fold_consts.16b // F = A1*B
|
||||
pmull2 t8.8h, ad.16b, bd1.16b // E = A*B1
|
||||
pmull2 t5.8h, t5.16b, fold_consts.16b // H = A2*B
|
||||
pmull2 t7.8h, ad.16b, bd2.16b // G = A*B2
|
||||
pmull2 t6.8h, t6.16b, fold_consts.16b // J = A3*B
|
||||
pmull2 t9.8h, ad.16b, bd3.16b // I = A*B3
|
||||
pmull2 t3.8h, ad.16b, bd4.16b // K = A*B4
|
||||
|
||||
0: eor t4.16b, t4.16b, t8.16b // L = E + F
|
||||
eor t5.16b, t5.16b, t7.16b // M = G + H
|
||||
eor t6.16b, t6.16b, t9.16b // N = I + J
|
||||
|
||||
uzp1 t8.2d, t4.2d, t5.2d
|
||||
uzp2 t4.2d, t4.2d, t5.2d
|
||||
uzp1 t7.2d, t6.2d, t3.2d
|
||||
uzp2 t6.2d, t6.2d, t3.2d
|
||||
|
||||
// t4 = (L) (P0 + P1) << 8
|
||||
// t5 = (M) (P2 + P3) << 16
|
||||
eor t8.16b, t8.16b, t4.16b
|
||||
and t4.16b, t4.16b, k32_48.16b
|
||||
|
||||
// t6 = (N) (P4 + P5) << 24
|
||||
// t7 = (K) (P6 + P7) << 32
|
||||
eor t7.16b, t7.16b, t6.16b
|
||||
and t6.16b, t6.16b, k00_16.16b
|
||||
|
||||
eor t8.16b, t8.16b, t4.16b
|
||||
eor t7.16b, t7.16b, t6.16b
|
||||
|
||||
zip2 t5.2d, t8.2d, t4.2d
|
||||
zip1 t4.2d, t8.2d, t4.2d
|
||||
zip2 t3.2d, t7.2d, t6.2d
|
||||
zip1 t6.2d, t7.2d, t6.2d
|
||||
|
||||
ext t4.16b, t4.16b, t4.16b, #15
|
||||
ext t8.16b, t3.16b, t3.16b, #8
|
||||
eor t4.16b, t4.16b, t6.16b
|
||||
ext t7.16b, t5.16b, t5.16b, #8
|
||||
ext t6.16b, t4.16b, t4.16b, #8
|
||||
eor t8.8b, t8.8b, t3.8b
|
||||
eor t5.8b, t5.8b, t7.8b
|
||||
eor t4.8b, t4.8b, t6.8b
|
||||
ext t5.16b, t5.16b, t5.16b, #14
|
||||
ext t6.16b, t6.16b, t6.16b, #13
|
||||
ext t3.16b, t3.16b, t3.16b, #12
|
||||
|
||||
eor t4.16b, t4.16b, t5.16b
|
||||
eor t6.16b, t6.16b, t3.16b
|
||||
ret
|
||||
SYM_FUNC_END(__pmull_p8_core)
|
||||
SYM_FUNC_END(__pmull_p8_16x64)
|
||||
|
||||
.macro __pmull_p8, rq, ad, bd, i
|
||||
.ifnc \bd, fold_consts
|
||||
.err
|
||||
.endif
|
||||
mov ad.16b, \ad\().16b
|
||||
.ifb \i
|
||||
pmull \rq\().8h, \ad\().8b, \bd\().8b // D = A*B
|
||||
.else
|
||||
pmull2 \rq\().8h, \ad\().16b, \bd\().16b // D = A*B
|
||||
.endif
|
||||
|
||||
bl .L__pmull_p8_core\i
|
||||
|
||||
eor \rq\().16b, \rq\().16b, t4.16b
|
||||
eor \rq\().16b, \rq\().16b, t6.16b
|
||||
.endm
|
||||
|
||||
// Fold reg1, reg2 into the next 32 data bytes, storing the result back
|
||||
// into reg1, reg2.
|
||||
.macro fold_32_bytes, p, reg1, reg2
|
||||
ldp q11, q12, [buf], #0x20
|
||||
|
||||
__pmull_\p v8, \reg1, fold_consts, 2
|
||||
__pmull_\p \reg1, \reg1, fold_consts
|
||||
pmull16x64_\p fold_consts, \reg1, v8
|
||||
|
||||
CPU_LE( rev64 v11.16b, v11.16b )
|
||||
CPU_LE( rev64 v12.16b, v12.16b )
|
||||
|
||||
__pmull_\p v9, \reg2, fold_consts, 2
|
||||
__pmull_\p \reg2, \reg2, fold_consts
|
||||
pmull16x64_\p fold_consts, \reg2, v9
|
||||
|
||||
CPU_LE( ext v11.16b, v11.16b, v11.16b, #8 )
|
||||
CPU_LE( ext v12.16b, v12.16b, v12.16b, #8 )
|
||||
@@ -238,26 +197,15 @@ CPU_LE( ext v12.16b, v12.16b, v12.16b, #8 )
|
||||
|
||||
// Fold src_reg into dst_reg, optionally loading the next fold constants
|
||||
.macro fold_16_bytes, p, src_reg, dst_reg, load_next_consts
|
||||
__pmull_\p v8, \src_reg, fold_consts
|
||||
__pmull_\p \src_reg, \src_reg, fold_consts, 2
|
||||
pmull16x64_\p fold_consts, \src_reg, v8
|
||||
.ifnb \load_next_consts
|
||||
ld1 {fold_consts.2d}, [fold_consts_ptr], #16
|
||||
__pmull_pre_\p fold_consts
|
||||
.endif
|
||||
eor \dst_reg\().16b, \dst_reg\().16b, v8.16b
|
||||
eor \dst_reg\().16b, \dst_reg\().16b, \src_reg\().16b
|
||||
.endm
|
||||
|
||||
.macro __pmull_p64, rd, rn, rm, n
|
||||
.ifb \n
|
||||
pmull \rd\().1q, \rn\().1d, \rm\().1d
|
||||
.else
|
||||
pmull2 \rd\().1q, \rn\().2d, \rm\().2d
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro crc_t10dif_pmull, p
|
||||
__pmull_init_\p
|
||||
|
||||
// For sizes less than 256 bytes, we can't fold 128 bytes at a time.
|
||||
cmp len, #256
|
||||
@@ -296,7 +244,6 @@ CPU_LE( ext v7.16b, v7.16b, v7.16b, #8 )
|
||||
|
||||
// Load the constants for folding across 128 bytes.
|
||||
ld1 {fold_consts.2d}, [fold_consts_ptr]
|
||||
__pmull_pre_\p fold_consts
|
||||
|
||||
// Subtract 128 for the 128 data bytes just consumed. Subtract another
|
||||
// 128 to simplify the termination condition of the following loop.
|
||||
@@ -318,7 +265,6 @@ CPU_LE( ext v7.16b, v7.16b, v7.16b, #8 )
|
||||
// Fold across 64 bytes.
|
||||
add fold_consts_ptr, fold_consts_ptr, #16
|
||||
ld1 {fold_consts.2d}, [fold_consts_ptr], #16
|
||||
__pmull_pre_\p fold_consts
|
||||
fold_16_bytes \p, v0, v4
|
||||
fold_16_bytes \p, v1, v5
|
||||
fold_16_bytes \p, v2, v6
|
||||
@@ -339,8 +285,7 @@ CPU_LE( ext v7.16b, v7.16b, v7.16b, #8 )
|
||||
// into them, storing the result back into v7.
|
||||
b.lt .Lfold_16_bytes_loop_done_\@
|
||||
.Lfold_16_bytes_loop_\@:
|
||||
__pmull_\p v8, v7, fold_consts
|
||||
__pmull_\p v7, v7, fold_consts, 2
|
||||
pmull16x64_\p fold_consts, v7, v8
|
||||
eor v7.16b, v7.16b, v8.16b
|
||||
ldr q0, [buf], #16
|
||||
CPU_LE( rev64 v0.16b, v0.16b )
|
||||
@@ -387,51 +332,10 @@ CPU_LE( ext v0.16b, v0.16b, v0.16b, #8 )
|
||||
bsl v2.16b, v1.16b, v0.16b
|
||||
|
||||
// Fold the first chunk into the second chunk, storing the result in v7.
|
||||
__pmull_\p v0, v3, fold_consts
|
||||
__pmull_\p v7, v3, fold_consts, 2
|
||||
eor v7.16b, v7.16b, v0.16b
|
||||
pmull16x64_\p fold_consts, v3, v0
|
||||
eor v7.16b, v3.16b, v0.16b
|
||||
eor v7.16b, v7.16b, v2.16b
|
||||
|
||||
.Lreduce_final_16_bytes_\@:
|
||||
// Reduce the 128-bit value M(x), stored in v7, to the final 16-bit CRC.
|
||||
|
||||
movi v2.16b, #0 // init zero register
|
||||
|
||||
// Load 'x^48 * (x^48 mod G(x))' and 'x^48 * (x^80 mod G(x))'.
|
||||
ld1 {fold_consts.2d}, [fold_consts_ptr], #16
|
||||
__pmull_pre_\p fold_consts
|
||||
|
||||
// Fold the high 64 bits into the low 64 bits, while also multiplying by
|
||||
// x^64. This produces a 128-bit value congruent to x^64 * M(x) and
|
||||
// whose low 48 bits are 0.
|
||||
ext v0.16b, v2.16b, v7.16b, #8
|
||||
__pmull_\p v7, v7, fold_consts, 2 // high bits * x^48 * (x^80 mod G(x))
|
||||
eor v0.16b, v0.16b, v7.16b // + low bits * x^64
|
||||
|
||||
// Fold the high 32 bits into the low 96 bits. This produces a 96-bit
|
||||
// value congruent to x^64 * M(x) and whose low 48 bits are 0.
|
||||
ext v1.16b, v0.16b, v2.16b, #12 // extract high 32 bits
|
||||
mov v0.s[3], v2.s[0] // zero high 32 bits
|
||||
__pmull_\p v1, v1, fold_consts // high 32 bits * x^48 * (x^48 mod G(x))
|
||||
eor v0.16b, v0.16b, v1.16b // + low bits
|
||||
|
||||
// Load G(x) and floor(x^48 / G(x)).
|
||||
ld1 {fold_consts.2d}, [fold_consts_ptr]
|
||||
__pmull_pre_\p fold_consts
|
||||
|
||||
// Use Barrett reduction to compute the final CRC value.
|
||||
__pmull_\p v1, v0, fold_consts, 2 // high 32 bits * floor(x^48 / G(x))
|
||||
ushr v1.2d, v1.2d, #32 // /= x^32
|
||||
__pmull_\p v1, v1, fold_consts // *= G(x)
|
||||
ushr v0.2d, v0.2d, #48
|
||||
eor v0.16b, v0.16b, v1.16b // + low 16 nonzero bits
|
||||
// Final CRC value (x^16 * M(x)) mod G(x) is in low 16 bits of v0.
|
||||
|
||||
umov w0, v0.h[0]
|
||||
.ifc \p, p8
|
||||
frame_pop
|
||||
.endif
|
||||
ret
|
||||
b .Lreduce_final_16_bytes_\@
|
||||
|
||||
.Lless_than_256_bytes_\@:
|
||||
// Checksumming a buffer of length 16...255 bytes
|
||||
@@ -450,7 +354,6 @@ CPU_LE( ext v7.16b, v7.16b, v7.16b, #8 )
|
||||
|
||||
// Load the fold-across-16-bytes constants.
|
||||
ld1 {fold_consts.2d}, [fold_consts_ptr], #16
|
||||
__pmull_pre_\p fold_consts
|
||||
|
||||
cmp len, #16
|
||||
b.eq .Lreduce_final_16_bytes_\@ // len == 16
|
||||
@@ -458,6 +361,8 @@ CPU_LE( ext v7.16b, v7.16b, v7.16b, #8 )
|
||||
b.ge .Lfold_16_bytes_loop_\@ // 32 <= len <= 255
|
||||
add len, len, #16
|
||||
b .Lhandle_partial_segment_\@ // 17 <= len <= 31
|
||||
|
||||
.Lreduce_final_16_bytes_\@:
|
||||
.endm
|
||||
|
||||
//
|
||||
@@ -467,7 +372,22 @@ CPU_LE( ext v7.16b, v7.16b, v7.16b, #8 )
|
||||
//
|
||||
SYM_FUNC_START(crc_t10dif_pmull_p8)
|
||||
frame_push 1
|
||||
|
||||
// Compose { 0,0,0,0, 8,8,8,8, 1,1,1,1, 9,9,9,9 }
|
||||
movi perm.4h, #8, lsl #8
|
||||
orr perm.2s, #1, lsl #16
|
||||
orr perm.2s, #1, lsl #24
|
||||
zip1 perm.16b, perm.16b, perm.16b
|
||||
zip1 perm.16b, perm.16b, perm.16b
|
||||
|
||||
crc_t10dif_pmull p8
|
||||
|
||||
CPU_LE( rev64 v7.16b, v7.16b )
|
||||
CPU_LE( ext v7.16b, v7.16b, v7.16b, #8 )
|
||||
str q7, [x3]
|
||||
|
||||
frame_pop
|
||||
ret
|
||||
SYM_FUNC_END(crc_t10dif_pmull_p8)
|
||||
|
||||
.align 5
|
||||
@@ -478,6 +398,41 @@ SYM_FUNC_END(crc_t10dif_pmull_p8)
|
||||
//
|
||||
SYM_FUNC_START(crc_t10dif_pmull_p64)
|
||||
crc_t10dif_pmull p64
|
||||
|
||||
// Reduce the 128-bit value M(x), stored in v7, to the final 16-bit CRC.
|
||||
|
||||
movi v2.16b, #0 // init zero register
|
||||
|
||||
// Load 'x^48 * (x^48 mod G(x))' and 'x^48 * (x^80 mod G(x))'.
|
||||
ld1 {fold_consts.2d}, [fold_consts_ptr], #16
|
||||
|
||||
// Fold the high 64 bits into the low 64 bits, while also multiplying by
|
||||
// x^64. This produces a 128-bit value congruent to x^64 * M(x) and
|
||||
// whose low 48 bits are 0.
|
||||
ext v0.16b, v2.16b, v7.16b, #8
|
||||
pmull2 v7.1q, v7.2d, fold_consts.2d // high bits * x^48 * (x^80 mod G(x))
|
||||
eor v0.16b, v0.16b, v7.16b // + low bits * x^64
|
||||
|
||||
// Fold the high 32 bits into the low 96 bits. This produces a 96-bit
|
||||
// value congruent to x^64 * M(x) and whose low 48 bits are 0.
|
||||
ext v1.16b, v0.16b, v2.16b, #12 // extract high 32 bits
|
||||
mov v0.s[3], v2.s[0] // zero high 32 bits
|
||||
pmull v1.1q, v1.1d, fold_consts.1d // high 32 bits * x^48 * (x^48 mod G(x))
|
||||
eor v0.16b, v0.16b, v1.16b // + low bits
|
||||
|
||||
// Load G(x) and floor(x^48 / G(x)).
|
||||
ld1 {fold_consts.2d}, [fold_consts_ptr]
|
||||
|
||||
// Use Barrett reduction to compute the final CRC value.
|
||||
pmull2 v1.1q, v0.2d, fold_consts.2d // high 32 bits * floor(x^48 / G(x))
|
||||
ushr v1.2d, v1.2d, #32 // /= x^32
|
||||
pmull v1.1q, v1.1d, fold_consts.1d // *= G(x)
|
||||
ushr v0.2d, v0.2d, #48
|
||||
eor v0.16b, v0.16b, v1.16b // + low 16 nonzero bits
|
||||
// Final CRC value (x^16 * M(x)) mod G(x) is in low 16 bits of v0.
|
||||
|
||||
umov w0, v0.h[0]
|
||||
ret
|
||||
SYM_FUNC_END(crc_t10dif_pmull_p64)
|
||||
|
||||
.section ".rodata", "a"
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
|
||||
#define CRC_T10DIF_PMULL_CHUNK_SIZE 16U
|
||||
|
||||
asmlinkage u16 crc_t10dif_pmull_p8(u16 init_crc, const u8 *buf, size_t len);
|
||||
asmlinkage void crc_t10dif_pmull_p8(u16 init_crc, const u8 *buf, size_t len,
|
||||
u8 out[16]);
|
||||
asmlinkage u16 crc_t10dif_pmull_p64(u16 init_crc, const u8 *buf, size_t len);
|
||||
|
||||
static int crct10dif_init(struct shash_desc *desc)
|
||||
@@ -34,25 +35,21 @@ static int crct10dif_init(struct shash_desc *desc)
|
||||
static int crct10dif_update_pmull_p8(struct shash_desc *desc, const u8 *data,
|
||||
unsigned int length)
|
||||
{
|
||||
u16 *crc = shash_desc_ctx(desc);
|
||||
u16 *crcp = shash_desc_ctx(desc);
|
||||
u16 crc = *crcp;
|
||||
u8 buf[16];
|
||||
|
||||
if (length >= CRC_T10DIF_PMULL_CHUNK_SIZE && crypto_simd_usable()) {
|
||||
do {
|
||||
unsigned int chunk = length;
|
||||
if (length > CRC_T10DIF_PMULL_CHUNK_SIZE && crypto_simd_usable()) {
|
||||
kernel_neon_begin();
|
||||
crc_t10dif_pmull_p8(crc, data, length, buf);
|
||||
kernel_neon_end();
|
||||
|
||||
if (chunk > SZ_4K + CRC_T10DIF_PMULL_CHUNK_SIZE)
|
||||
chunk = SZ_4K;
|
||||
|
||||
kernel_neon_begin();
|
||||
*crc = crc_t10dif_pmull_p8(*crc, data, chunk);
|
||||
kernel_neon_end();
|
||||
data += chunk;
|
||||
length -= chunk;
|
||||
} while (length);
|
||||
} else {
|
||||
*crc = crc_t10dif_generic(*crc, data, length);
|
||||
crc = 0;
|
||||
data = buf;
|
||||
length = sizeof(buf);
|
||||
}
|
||||
|
||||
*crcp = crc_t10dif_generic(crc, data, length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -62,18 +59,9 @@ static int crct10dif_update_pmull_p64(struct shash_desc *desc, const u8 *data,
|
||||
u16 *crc = shash_desc_ctx(desc);
|
||||
|
||||
if (length >= CRC_T10DIF_PMULL_CHUNK_SIZE && crypto_simd_usable()) {
|
||||
do {
|
||||
unsigned int chunk = length;
|
||||
|
||||
if (chunk > SZ_4K + CRC_T10DIF_PMULL_CHUNK_SIZE)
|
||||
chunk = SZ_4K;
|
||||
|
||||
kernel_neon_begin();
|
||||
*crc = crc_t10dif_pmull_p64(*crc, data, chunk);
|
||||
kernel_neon_end();
|
||||
data += chunk;
|
||||
length -= chunk;
|
||||
} while (length);
|
||||
kernel_neon_begin();
|
||||
*crc = crc_t10dif_pmull_p64(*crc, data, length);
|
||||
kernel_neon_end();
|
||||
} else {
|
||||
*crc = crc_t10dif_generic(*crc, data, length);
|
||||
}
|
||||
|
||||
@@ -107,12 +107,12 @@ config CRYPTO_AES_PPC_SPE
|
||||
|
||||
config CRYPTO_AES_GCM_P10
|
||||
tristate "Stitched AES/GCM acceleration support on P10 or later CPU (PPC)"
|
||||
depends on BROKEN
|
||||
depends on PPC64 && CPU_LITTLE_ENDIAN && VSX
|
||||
select CRYPTO_LIB_AES
|
||||
select CRYPTO_ALGAPI
|
||||
select CRYPTO_AEAD
|
||||
select CRYPTO_SKCIPHER
|
||||
select CRYPTO_SIMD
|
||||
help
|
||||
AEAD cipher: AES cipher algorithms (FIPS-197)
|
||||
GCM (Galois/Counter Mode) authenticated encryption mode (NIST SP800-38D)
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <linux/unaligned.h>
|
||||
#include <asm/simd.h>
|
||||
#include <asm/switch_to.h>
|
||||
#include <crypto/gcm.h>
|
||||
#include <crypto/aes.h>
|
||||
#include <crypto/algapi.h>
|
||||
#include <crypto/b128ops.h>
|
||||
@@ -24,6 +25,7 @@
|
||||
|
||||
#define PPC_ALIGN 16
|
||||
#define GCM_IV_SIZE 12
|
||||
#define RFC4106_NONCE_SIZE 4
|
||||
|
||||
MODULE_DESCRIPTION("PPC64le AES-GCM with Stitched implementation");
|
||||
MODULE_AUTHOR("Danny Tsen <dtsen@linux.ibm.com");
|
||||
@@ -31,7 +33,7 @@ MODULE_LICENSE("GPL v2");
|
||||
MODULE_ALIAS_CRYPTO("aes");
|
||||
|
||||
asmlinkage int aes_p10_set_encrypt_key(const u8 *userKey, const int bits,
|
||||
void *key);
|
||||
void *key);
|
||||
asmlinkage void aes_p10_encrypt(const u8 *in, u8 *out, const void *key);
|
||||
asmlinkage void aes_p10_gcm_encrypt(u8 *in, u8 *out, size_t len,
|
||||
void *rkey, u8 *iv, void *Xi);
|
||||
@@ -39,7 +41,8 @@ asmlinkage void aes_p10_gcm_decrypt(u8 *in, u8 *out, size_t len,
|
||||
void *rkey, u8 *iv, void *Xi);
|
||||
asmlinkage void gcm_init_htable(unsigned char htable[], unsigned char Xi[]);
|
||||
asmlinkage void gcm_ghash_p10(unsigned char *Xi, unsigned char *Htable,
|
||||
unsigned char *aad, unsigned int alen);
|
||||
unsigned char *aad, unsigned int alen);
|
||||
asmlinkage void gcm_update(u8 *iv, void *Xi);
|
||||
|
||||
struct aes_key {
|
||||
u8 key[AES_MAX_KEYLENGTH];
|
||||
@@ -52,6 +55,7 @@ struct gcm_ctx {
|
||||
u8 aad_hash[16];
|
||||
u64 aadLen;
|
||||
u64 Plen; /* offset 56 - used in aes_p10_gcm_{en/de}crypt */
|
||||
u8 pblock[16];
|
||||
};
|
||||
struct Hash_ctx {
|
||||
u8 H[16]; /* subkey */
|
||||
@@ -60,17 +64,20 @@ struct Hash_ctx {
|
||||
|
||||
struct p10_aes_gcm_ctx {
|
||||
struct aes_key enc_key;
|
||||
u8 nonce[RFC4106_NONCE_SIZE];
|
||||
};
|
||||
|
||||
static void vsx_begin(void)
|
||||
{
|
||||
preempt_disable();
|
||||
pagefault_disable();
|
||||
enable_kernel_vsx();
|
||||
}
|
||||
|
||||
static void vsx_end(void)
|
||||
{
|
||||
disable_kernel_vsx();
|
||||
pagefault_enable();
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
@@ -185,7 +192,7 @@ static int set_authsize(struct crypto_aead *tfm, unsigned int authsize)
|
||||
}
|
||||
|
||||
static int p10_aes_gcm_setkey(struct crypto_aead *aead, const u8 *key,
|
||||
unsigned int keylen)
|
||||
unsigned int keylen)
|
||||
{
|
||||
struct crypto_tfm *tfm = crypto_aead_tfm(aead);
|
||||
struct p10_aes_gcm_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
@@ -198,7 +205,8 @@ static int p10_aes_gcm_setkey(struct crypto_aead *aead, const u8 *key,
|
||||
return ret ? -EINVAL : 0;
|
||||
}
|
||||
|
||||
static int p10_aes_gcm_crypt(struct aead_request *req, int enc)
|
||||
static int p10_aes_gcm_crypt(struct aead_request *req, u8 *riv,
|
||||
int assoclen, int enc)
|
||||
{
|
||||
struct crypto_tfm *tfm = req->base.tfm;
|
||||
struct p10_aes_gcm_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
@@ -210,7 +218,6 @@ static int p10_aes_gcm_crypt(struct aead_request *req, int enc)
|
||||
struct skcipher_walk walk;
|
||||
u8 *assocmem = NULL;
|
||||
u8 *assoc;
|
||||
unsigned int assoclen = req->assoclen;
|
||||
unsigned int cryptlen = req->cryptlen;
|
||||
unsigned char ivbuf[AES_BLOCK_SIZE+PPC_ALIGN];
|
||||
unsigned char *iv = PTR_ALIGN((void *)ivbuf, PPC_ALIGN);
|
||||
@@ -218,11 +225,12 @@ static int p10_aes_gcm_crypt(struct aead_request *req, int enc)
|
||||
unsigned long auth_tag_len = crypto_aead_authsize(__crypto_aead_cast(tfm));
|
||||
u8 otag[16];
|
||||
int total_processed = 0;
|
||||
int nbytes;
|
||||
|
||||
memset(databuf, 0, sizeof(databuf));
|
||||
memset(hashbuf, 0, sizeof(hashbuf));
|
||||
memset(ivbuf, 0, sizeof(ivbuf));
|
||||
memcpy(iv, req->iv, GCM_IV_SIZE);
|
||||
memcpy(iv, riv, GCM_IV_SIZE);
|
||||
|
||||
/* Linearize assoc, if not already linear */
|
||||
if (req->src->length >= assoclen && req->src->length) {
|
||||
@@ -257,19 +265,25 @@ static int p10_aes_gcm_crypt(struct aead_request *req, int enc)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
while (walk.nbytes > 0 && ret == 0) {
|
||||
while ((nbytes = walk.nbytes) > 0 && ret == 0) {
|
||||
u8 *src = walk.src.virt.addr;
|
||||
u8 *dst = walk.dst.virt.addr;
|
||||
u8 buf[AES_BLOCK_SIZE];
|
||||
|
||||
if (unlikely(nbytes > 0 && nbytes < AES_BLOCK_SIZE))
|
||||
src = dst = memcpy(buf, src, nbytes);
|
||||
|
||||
vsx_begin();
|
||||
if (enc)
|
||||
aes_p10_gcm_encrypt(walk.src.virt.addr,
|
||||
walk.dst.virt.addr,
|
||||
walk.nbytes,
|
||||
aes_p10_gcm_encrypt(src, dst, nbytes,
|
||||
&ctx->enc_key, gctx->iv, hash->Htable);
|
||||
else
|
||||
aes_p10_gcm_decrypt(walk.src.virt.addr,
|
||||
walk.dst.virt.addr,
|
||||
walk.nbytes,
|
||||
aes_p10_gcm_decrypt(src, dst, nbytes,
|
||||
&ctx->enc_key, gctx->iv, hash->Htable);
|
||||
|
||||
if (unlikely(nbytes > 0 && nbytes < AES_BLOCK_SIZE))
|
||||
memcpy(walk.dst.virt.addr, buf, nbytes);
|
||||
|
||||
vsx_end();
|
||||
|
||||
total_processed += walk.nbytes;
|
||||
@@ -281,6 +295,7 @@ static int p10_aes_gcm_crypt(struct aead_request *req, int enc)
|
||||
|
||||
/* Finalize hash */
|
||||
vsx_begin();
|
||||
gcm_update(gctx->iv, hash->Htable);
|
||||
finish_tag(gctx, hash, total_processed);
|
||||
vsx_end();
|
||||
|
||||
@@ -302,17 +317,63 @@ static int p10_aes_gcm_crypt(struct aead_request *req, int enc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rfc4106_setkey(struct crypto_aead *tfm, const u8 *inkey,
|
||||
unsigned int keylen)
|
||||
{
|
||||
struct p10_aes_gcm_ctx *ctx = crypto_aead_ctx(tfm);
|
||||
int err;
|
||||
|
||||
keylen -= RFC4106_NONCE_SIZE;
|
||||
err = p10_aes_gcm_setkey(tfm, inkey, keylen);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
memcpy(ctx->nonce, inkey + keylen, RFC4106_NONCE_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rfc4106_setauthsize(struct crypto_aead *tfm, unsigned int authsize)
|
||||
{
|
||||
return crypto_rfc4106_check_authsize(authsize);
|
||||
}
|
||||
|
||||
static int rfc4106_encrypt(struct aead_request *req)
|
||||
{
|
||||
struct crypto_aead *aead = crypto_aead_reqtfm(req);
|
||||
struct p10_aes_gcm_ctx *ctx = crypto_aead_ctx(aead);
|
||||
u8 iv[AES_BLOCK_SIZE];
|
||||
|
||||
memcpy(iv, ctx->nonce, RFC4106_NONCE_SIZE);
|
||||
memcpy(iv + RFC4106_NONCE_SIZE, req->iv, GCM_RFC4106_IV_SIZE);
|
||||
|
||||
return crypto_ipsec_check_assoclen(req->assoclen) ?:
|
||||
p10_aes_gcm_crypt(req, iv, req->assoclen - GCM_RFC4106_IV_SIZE, 1);
|
||||
}
|
||||
|
||||
static int rfc4106_decrypt(struct aead_request *req)
|
||||
{
|
||||
struct crypto_aead *aead = crypto_aead_reqtfm(req);
|
||||
struct p10_aes_gcm_ctx *ctx = crypto_aead_ctx(aead);
|
||||
u8 iv[AES_BLOCK_SIZE];
|
||||
|
||||
memcpy(iv, ctx->nonce, RFC4106_NONCE_SIZE);
|
||||
memcpy(iv + RFC4106_NONCE_SIZE, req->iv, GCM_RFC4106_IV_SIZE);
|
||||
|
||||
return crypto_ipsec_check_assoclen(req->assoclen) ?:
|
||||
p10_aes_gcm_crypt(req, iv, req->assoclen - GCM_RFC4106_IV_SIZE, 0);
|
||||
}
|
||||
|
||||
static int p10_aes_gcm_encrypt(struct aead_request *req)
|
||||
{
|
||||
return p10_aes_gcm_crypt(req, 1);
|
||||
return p10_aes_gcm_crypt(req, req->iv, req->assoclen, 1);
|
||||
}
|
||||
|
||||
static int p10_aes_gcm_decrypt(struct aead_request *req)
|
||||
{
|
||||
return p10_aes_gcm_crypt(req, 0);
|
||||
return p10_aes_gcm_crypt(req, req->iv, req->assoclen, 0);
|
||||
}
|
||||
|
||||
static struct aead_alg gcm_aes_alg = {
|
||||
static struct aead_alg gcm_aes_algs[] = {{
|
||||
.ivsize = GCM_IV_SIZE,
|
||||
.maxauthsize = 16,
|
||||
|
||||
@@ -321,23 +382,57 @@ static struct aead_alg gcm_aes_alg = {
|
||||
.encrypt = p10_aes_gcm_encrypt,
|
||||
.decrypt = p10_aes_gcm_decrypt,
|
||||
|
||||
.base.cra_name = "gcm(aes)",
|
||||
.base.cra_driver_name = "aes_gcm_p10",
|
||||
.base.cra_name = "__gcm(aes)",
|
||||
.base.cra_driver_name = "__aes_gcm_p10",
|
||||
.base.cra_priority = 2100,
|
||||
.base.cra_blocksize = 1,
|
||||
.base.cra_ctxsize = sizeof(struct p10_aes_gcm_ctx),
|
||||
.base.cra_ctxsize = sizeof(struct p10_aes_gcm_ctx)+
|
||||
4 * sizeof(u64[2]),
|
||||
.base.cra_module = THIS_MODULE,
|
||||
};
|
||||
.base.cra_flags = CRYPTO_ALG_INTERNAL,
|
||||
}, {
|
||||
.ivsize = GCM_RFC4106_IV_SIZE,
|
||||
.maxauthsize = 16,
|
||||
.setkey = rfc4106_setkey,
|
||||
.setauthsize = rfc4106_setauthsize,
|
||||
.encrypt = rfc4106_encrypt,
|
||||
.decrypt = rfc4106_decrypt,
|
||||
|
||||
.base.cra_name = "__rfc4106(gcm(aes))",
|
||||
.base.cra_driver_name = "__rfc4106_aes_gcm_p10",
|
||||
.base.cra_priority = 2100,
|
||||
.base.cra_blocksize = 1,
|
||||
.base.cra_ctxsize = sizeof(struct p10_aes_gcm_ctx) +
|
||||
4 * sizeof(u64[2]),
|
||||
.base.cra_module = THIS_MODULE,
|
||||
.base.cra_flags = CRYPTO_ALG_INTERNAL,
|
||||
}};
|
||||
|
||||
static struct simd_aead_alg *p10_simd_aeads[ARRAY_SIZE(gcm_aes_algs)];
|
||||
|
||||
static int __init p10_init(void)
|
||||
{
|
||||
return crypto_register_aead(&gcm_aes_alg);
|
||||
int ret;
|
||||
|
||||
if (!cpu_has_feature(CPU_FTR_ARCH_31))
|
||||
return 0;
|
||||
|
||||
ret = simd_register_aeads_compat(gcm_aes_algs,
|
||||
ARRAY_SIZE(gcm_aes_algs),
|
||||
p10_simd_aeads);
|
||||
if (ret) {
|
||||
simd_unregister_aeads(gcm_aes_algs, ARRAY_SIZE(gcm_aes_algs),
|
||||
p10_simd_aeads);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit p10_exit(void)
|
||||
{
|
||||
crypto_unregister_aead(&gcm_aes_alg);
|
||||
simd_unregister_aeads(gcm_aes_algs, ARRAY_SIZE(gcm_aes_algs),
|
||||
p10_simd_aeads);
|
||||
}
|
||||
|
||||
module_cpu_feature_match(PPC_MODULE_FEATURE_P10, p10_init);
|
||||
module_init(p10_init);
|
||||
module_exit(p10_exit);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user