diff options
author | Ard Biesheuvel <ard.biesheuvel@linaro.org> | 2018-01-19 07:04:39 -0500 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2018-01-25 09:10:35 -0500 |
commit | 140aa50d68ea01e7caea6900f6f51882d4dd65c5 (patch) | |
tree | bd885fab91d34f380acd75321c9f465913f55cd3 | |
parent | 15d5910e92614e642e7485bb9e89d46e4d1d65d9 (diff) |
crypto: arm64/sm3 - new v8.2 Crypto Extensions implementation
Implement the Chinese SM3 secure hash algorithm using the new
special instructions that have been introduced as an optional
extension in ARMv8.2.
Tested-by: Steve Capper <steve.capper@arm.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r-- | arch/arm64/crypto/Kconfig | 6 | ||||
-rw-r--r-- | arch/arm64/crypto/Makefile | 3 | ||||
-rw-r--r-- | arch/arm64/crypto/sm3-ce-core.S | 141 | ||||
-rw-r--r-- | arch/arm64/crypto/sm3-ce-glue.c | 92 |
4 files changed, 242 insertions, 0 deletions
diff --git a/arch/arm64/crypto/Kconfig b/arch/arm64/crypto/Kconfig index 3321b2c9a2b5..285c36c7b408 100644 --- a/arch/arm64/crypto/Kconfig +++ b/arch/arm64/crypto/Kconfig | |||
@@ -41,6 +41,12 @@ config CRYPTO_SHA3_ARM64 | |||
41 | select CRYPTO_HASH | 41 | select CRYPTO_HASH |
42 | select CRYPTO_SHA3 | 42 | select CRYPTO_SHA3 |
43 | 43 | ||
44 | config CRYPTO_SM3_ARM64_CE | ||
45 | tristate "SM3 digest algorithm (ARMv8.2 Crypto Extensions)" | ||
46 | depends on KERNEL_MODE_NEON | ||
47 | select CRYPTO_HASH | ||
48 | select CRYPTO_SM3 | ||
49 | |||
44 | config CRYPTO_GHASH_ARM64_CE | 50 | config CRYPTO_GHASH_ARM64_CE |
45 | tristate "GHASH/AES-GCM using ARMv8 Crypto Extensions" | 51 | tristate "GHASH/AES-GCM using ARMv8 Crypto Extensions" |
46 | depends on KERNEL_MODE_NEON | 52 | depends on KERNEL_MODE_NEON |
diff --git a/arch/arm64/crypto/Makefile b/arch/arm64/crypto/Makefile index 4ca2d146e213..cee9b8d9830b 100644 --- a/arch/arm64/crypto/Makefile +++ b/arch/arm64/crypto/Makefile | |||
@@ -20,6 +20,9 @@ sha512-ce-y := sha512-ce-glue.o sha512-ce-core.o | |||
20 | obj-$(CONFIG_CRYPTO_SHA3_ARM64) += sha3-ce.o | 20 | obj-$(CONFIG_CRYPTO_SHA3_ARM64) += sha3-ce.o |
21 | sha3-ce-y := sha3-ce-glue.o sha3-ce-core.o | 21 | sha3-ce-y := sha3-ce-glue.o sha3-ce-core.o |
22 | 22 | ||
23 | obj-$(CONFIG_CRYPTO_SM3_ARM64_CE) += sm3-ce.o | ||
24 | sm3-ce-y := sm3-ce-glue.o sm3-ce-core.o | ||
25 | |||
23 | obj-$(CONFIG_CRYPTO_GHASH_ARM64_CE) += ghash-ce.o | 26 | obj-$(CONFIG_CRYPTO_GHASH_ARM64_CE) += ghash-ce.o |
24 | ghash-ce-y := ghash-ce-glue.o ghash-ce-core.o | 27 | ghash-ce-y := ghash-ce-glue.o ghash-ce-core.o |
25 | 28 | ||
diff --git a/arch/arm64/crypto/sm3-ce-core.S b/arch/arm64/crypto/sm3-ce-core.S new file mode 100644 index 000000000000..27169fe07a68 --- /dev/null +++ b/arch/arm64/crypto/sm3-ce-core.S | |||
@@ -0,0 +1,141 @@ | |||
1 | /* | ||
2 | * sm3-ce-core.S - SM3 secure hash using ARMv8.2 Crypto Extensions | ||
3 | * | ||
4 | * Copyright (C) 2018 Linaro Ltd <ard.biesheuvel@linaro.org> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/linkage.h> | ||
12 | #include <asm/assembler.h> | ||
13 | |||
14 | .irp b, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 | ||
15 | .set .Lv\b\().4s, \b | ||
16 | .endr | ||
17 | |||
18 | .macro sm3partw1, rd, rn, rm | ||
19 | .inst 0xce60c000 | .L\rd | (.L\rn << 5) | (.L\rm << 16) | ||
20 | .endm | ||
21 | |||
22 | .macro sm3partw2, rd, rn, rm | ||
23 | .inst 0xce60c400 | .L\rd | (.L\rn << 5) | (.L\rm << 16) | ||
24 | .endm | ||
25 | |||
26 | .macro sm3ss1, rd, rn, rm, ra | ||
27 | .inst 0xce400000 | .L\rd | (.L\rn << 5) | (.L\ra << 10) | (.L\rm << 16) | ||
28 | .endm | ||
29 | |||
30 | .macro sm3tt1a, rd, rn, rm, imm2 | ||
31 | .inst 0xce408000 | .L\rd | (.L\rn << 5) | ((\imm2) << 12) | (.L\rm << 16) | ||
32 | .endm | ||
33 | |||
34 | .macro sm3tt1b, rd, rn, rm, imm2 | ||
35 | .inst 0xce408400 | .L\rd | (.L\rn << 5) | ((\imm2) << 12) | (.L\rm << 16) | ||
36 | .endm | ||
37 | |||
38 | .macro sm3tt2a, rd, rn, rm, imm2 | ||
39 | .inst 0xce408800 | .L\rd | (.L\rn << 5) | ((\imm2) << 12) | (.L\rm << 16) | ||
40 | .endm | ||
41 | |||
42 | .macro sm3tt2b, rd, rn, rm, imm2 | ||
43 | .inst 0xce408c00 | .L\rd | (.L\rn << 5) | ((\imm2) << 12) | (.L\rm << 16) | ||
44 | .endm | ||
45 | |||
46 | .macro round, ab, s0, t0, t1, i | ||
47 | sm3ss1 v5.4s, v8.4s, \t0\().4s, v9.4s | ||
48 | shl \t1\().4s, \t0\().4s, #1 | ||
49 | sri \t1\().4s, \t0\().4s, #31 | ||
50 | sm3tt1\ab v8.4s, v5.4s, v10.4s, \i | ||
51 | sm3tt2\ab v9.4s, v5.4s, \s0\().4s, \i | ||
52 | .endm | ||
53 | |||
54 | .macro qround, ab, s0, s1, s2, s3, s4 | ||
55 | .ifnb \s4 | ||
56 | ext \s4\().16b, \s1\().16b, \s2\().16b, #12 | ||
57 | ext v6.16b, \s0\().16b, \s1\().16b, #12 | ||
58 | ext v7.16b, \s2\().16b, \s3\().16b, #8 | ||
59 | sm3partw1 \s4\().4s, \s0\().4s, \s3\().4s | ||
60 | .endif | ||
61 | |||
62 | eor v10.16b, \s0\().16b, \s1\().16b | ||
63 | |||
64 | round \ab, \s0, v11, v12, 0 | ||
65 | round \ab, \s0, v12, v11, 1 | ||
66 | round \ab, \s0, v11, v12, 2 | ||
67 | round \ab, \s0, v12, v11, 3 | ||
68 | |||
69 | .ifnb \s4 | ||
70 | sm3partw2 \s4\().4s, v7.4s, v6.4s | ||
71 | .endif | ||
72 | .endm | ||
73 | |||
74 | /* | ||
75 | * void sm3_ce_transform(struct sm3_state *sst, u8 const *src, | ||
76 | * int blocks) | ||
77 | */ | ||
78 | .text | ||
79 | ENTRY(sm3_ce_transform) | ||
80 | /* load state */ | ||
81 | ld1 {v8.4s-v9.4s}, [x0] | ||
82 | rev64 v8.4s, v8.4s | ||
83 | rev64 v9.4s, v9.4s | ||
84 | ext v8.16b, v8.16b, v8.16b, #8 | ||
85 | ext v9.16b, v9.16b, v9.16b, #8 | ||
86 | |||
87 | adr_l x8, .Lt | ||
88 | ldp s13, s14, [x8] | ||
89 | |||
90 | /* load input */ | ||
91 | 0: ld1 {v0.16b-v3.16b}, [x1], #64 | ||
92 | sub w2, w2, #1 | ||
93 | |||
94 | mov v15.16b, v8.16b | ||
95 | mov v16.16b, v9.16b | ||
96 | |||
97 | CPU_LE( rev32 v0.16b, v0.16b ) | ||
98 | CPU_LE( rev32 v1.16b, v1.16b ) | ||
99 | CPU_LE( rev32 v2.16b, v2.16b ) | ||
100 | CPU_LE( rev32 v3.16b, v3.16b ) | ||
101 | |||
102 | ext v11.16b, v13.16b, v13.16b, #4 | ||
103 | |||
104 | qround a, v0, v1, v2, v3, v4 | ||
105 | qround a, v1, v2, v3, v4, v0 | ||
106 | qround a, v2, v3, v4, v0, v1 | ||
107 | qround a, v3, v4, v0, v1, v2 | ||
108 | |||
109 | ext v11.16b, v14.16b, v14.16b, #4 | ||
110 | |||
111 | qround b, v4, v0, v1, v2, v3 | ||
112 | qround b, v0, v1, v2, v3, v4 | ||
113 | qround b, v1, v2, v3, v4, v0 | ||
114 | qround b, v2, v3, v4, v0, v1 | ||
115 | qround b, v3, v4, v0, v1, v2 | ||
116 | qround b, v4, v0, v1, v2, v3 | ||
117 | qround b, v0, v1, v2, v3, v4 | ||
118 | qround b, v1, v2, v3, v4, v0 | ||
119 | qround b, v2, v3, v4, v0, v1 | ||
120 | qround b, v3, v4 | ||
121 | qround b, v4, v0 | ||
122 | qround b, v0, v1 | ||
123 | |||
124 | eor v8.16b, v8.16b, v15.16b | ||
125 | eor v9.16b, v9.16b, v16.16b | ||
126 | |||
127 | /* handled all input blocks? */ | ||
128 | cbnz w2, 0b | ||
129 | |||
130 | /* save state */ | ||
131 | rev64 v8.4s, v8.4s | ||
132 | rev64 v9.4s, v9.4s | ||
133 | ext v8.16b, v8.16b, v8.16b, #8 | ||
134 | ext v9.16b, v9.16b, v9.16b, #8 | ||
135 | st1 {v8.4s-v9.4s}, [x0] | ||
136 | ret | ||
137 | ENDPROC(sm3_ce_transform) | ||
138 | |||
139 | .section ".rodata", "a" | ||
140 | .align 3 | ||
141 | .Lt: .word 0x79cc4519, 0x9d8a7a87 | ||
diff --git a/arch/arm64/crypto/sm3-ce-glue.c b/arch/arm64/crypto/sm3-ce-glue.c new file mode 100644 index 000000000000..3b4948f7e26f --- /dev/null +++ b/arch/arm64/crypto/sm3-ce-glue.c | |||
@@ -0,0 +1,92 @@ | |||
1 | /* | ||
2 | * sm3-ce-glue.c - SM3 secure hash using ARMv8.2 Crypto Extensions | ||
3 | * | ||
4 | * Copyright (C) 2018 Linaro Ltd <ard.biesheuvel@linaro.org> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <asm/neon.h> | ||
12 | #include <asm/simd.h> | ||
13 | #include <asm/unaligned.h> | ||
14 | #include <crypto/internal/hash.h> | ||
15 | #include <crypto/sm3.h> | ||
16 | #include <crypto/sm3_base.h> | ||
17 | #include <linux/cpufeature.h> | ||
18 | #include <linux/crypto.h> | ||
19 | #include <linux/module.h> | ||
20 | |||
21 | MODULE_DESCRIPTION("SM3 secure hash using ARMv8 Crypto Extensions"); | ||
22 | MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>"); | ||
23 | MODULE_LICENSE("GPL v2"); | ||
24 | |||
25 | asmlinkage void sm3_ce_transform(struct sm3_state *sst, u8 const *src, | ||
26 | int blocks); | ||
27 | |||
28 | static int sm3_ce_update(struct shash_desc *desc, const u8 *data, | ||
29 | unsigned int len) | ||
30 | { | ||
31 | if (!may_use_simd()) | ||
32 | return crypto_sm3_update(desc, data, len); | ||
33 | |||
34 | kernel_neon_begin(); | ||
35 | sm3_base_do_update(desc, data, len, sm3_ce_transform); | ||
36 | kernel_neon_end(); | ||
37 | |||
38 | return 0; | ||
39 | } | ||
40 | |||
41 | static int sm3_ce_final(struct shash_desc *desc, u8 *out) | ||
42 | { | ||
43 | if (!may_use_simd()) | ||
44 | return crypto_sm3_finup(desc, NULL, 0, out); | ||
45 | |||
46 | kernel_neon_begin(); | ||
47 | sm3_base_do_finalize(desc, sm3_ce_transform); | ||
48 | kernel_neon_end(); | ||
49 | |||
50 | return sm3_base_finish(desc, out); | ||
51 | } | ||
52 | |||
53 | static int sm3_ce_finup(struct shash_desc *desc, const u8 *data, | ||
54 | unsigned int len, u8 *out) | ||
55 | { | ||
56 | if (!may_use_simd()) | ||
57 | return crypto_sm3_finup(desc, data, len, out); | ||
58 | |||
59 | kernel_neon_begin(); | ||
60 | sm3_base_do_update(desc, data, len, sm3_ce_transform); | ||
61 | kernel_neon_end(); | ||
62 | |||
63 | return sm3_ce_final(desc, out); | ||
64 | } | ||
65 | |||
66 | static struct shash_alg sm3_alg = { | ||
67 | .digestsize = SM3_DIGEST_SIZE, | ||
68 | .init = sm3_base_init, | ||
69 | .update = sm3_ce_update, | ||
70 | .final = sm3_ce_final, | ||
71 | .finup = sm3_ce_finup, | ||
72 | .descsize = sizeof(struct sm3_state), | ||
73 | .base.cra_name = "sm3", | ||
74 | .base.cra_driver_name = "sm3-ce", | ||
75 | .base.cra_flags = CRYPTO_ALG_TYPE_SHASH, | ||
76 | .base.cra_blocksize = SM3_BLOCK_SIZE, | ||
77 | .base.cra_module = THIS_MODULE, | ||
78 | .base.cra_priority = 200, | ||
79 | }; | ||
80 | |||
81 | static int __init sm3_ce_mod_init(void) | ||
82 | { | ||
83 | return crypto_register_shash(&sm3_alg); | ||
84 | } | ||
85 | |||
86 | static void __exit sm3_ce_mod_fini(void) | ||
87 | { | ||
88 | crypto_unregister_shash(&sm3_alg); | ||
89 | } | ||
90 | |||
91 | module_cpu_feature_match(SM3, sm3_ce_mod_init); | ||
92 | module_exit(sm3_ce_mod_fini); | ||