1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 * Glue Code for the AVX512/GFNI assembler implementation of the ARIA Cipher
5 * Copyright (c) 2022 Taehee Yoo <ap420073@gmail.com>
8 #include <crypto/algapi.h>
9 #include <crypto/internal/simd.h>
10 #include <crypto/aria.h>
11 #include <linux/crypto.h>
12 #include <linux/err.h>
13 #include <linux/module.h>
14 #include <linux/types.h>
16 #include "ecb_cbc_helpers.h"
19 asmlinkage
void aria_gfni_avx512_encrypt_64way(const void *ctx
, u8
*dst
,
21 asmlinkage
void aria_gfni_avx512_decrypt_64way(const void *ctx
, u8
*dst
,
23 asmlinkage
void aria_gfni_avx512_ctr_crypt_64way(const void *ctx
, u8
*dst
,
25 u8
*keystream
, u8
*iv
);
27 static struct aria_avx_ops aria_ops
;
29 struct aria_avx512_request_ctx
{
30 u8 keystream
[ARIA_GFNI_AVX512_PARALLEL_BLOCK_SIZE
];
33 static int ecb_do_encrypt(struct skcipher_request
*req
, const u32
*rkey
)
35 ECB_WALK_START(req
, ARIA_BLOCK_SIZE
, ARIA_AESNI_PARALLEL_BLOCKS
);
36 ECB_BLOCK(ARIA_GFNI_AVX512_PARALLEL_BLOCKS
, aria_ops
.aria_encrypt_64way
);
37 ECB_BLOCK(ARIA_AESNI_AVX2_PARALLEL_BLOCKS
, aria_ops
.aria_encrypt_32way
);
38 ECB_BLOCK(ARIA_AESNI_PARALLEL_BLOCKS
, aria_ops
.aria_encrypt_16way
);
39 ECB_BLOCK(1, aria_encrypt
);
43 static int ecb_do_decrypt(struct skcipher_request
*req
, const u32
*rkey
)
45 ECB_WALK_START(req
, ARIA_BLOCK_SIZE
, ARIA_AESNI_PARALLEL_BLOCKS
);
46 ECB_BLOCK(ARIA_GFNI_AVX512_PARALLEL_BLOCKS
, aria_ops
.aria_decrypt_64way
);
47 ECB_BLOCK(ARIA_AESNI_AVX2_PARALLEL_BLOCKS
, aria_ops
.aria_decrypt_32way
);
48 ECB_BLOCK(ARIA_AESNI_PARALLEL_BLOCKS
, aria_ops
.aria_decrypt_16way
);
49 ECB_BLOCK(1, aria_decrypt
);
53 static int aria_avx512_ecb_encrypt(struct skcipher_request
*req
)
55 struct crypto_skcipher
*tfm
= crypto_skcipher_reqtfm(req
);
56 struct aria_ctx
*ctx
= crypto_skcipher_ctx(tfm
);
58 return ecb_do_encrypt(req
, ctx
->enc_key
[0]);
61 static int aria_avx512_ecb_decrypt(struct skcipher_request
*req
)
63 struct crypto_skcipher
*tfm
= crypto_skcipher_reqtfm(req
);
64 struct aria_ctx
*ctx
= crypto_skcipher_ctx(tfm
);
66 return ecb_do_decrypt(req
, ctx
->dec_key
[0]);
69 static int aria_avx512_set_key(struct crypto_skcipher
*tfm
, const u8
*key
,
72 return aria_set_key(&tfm
->base
, key
, keylen
);
75 static int aria_avx512_ctr_encrypt(struct skcipher_request
*req
)
77 struct aria_avx512_request_ctx
*req_ctx
= skcipher_request_ctx(req
);
78 struct crypto_skcipher
*tfm
= crypto_skcipher_reqtfm(req
);
79 struct aria_ctx
*ctx
= crypto_skcipher_ctx(tfm
);
80 struct skcipher_walk walk
;
84 err
= skcipher_walk_virt(&walk
, req
, false);
86 while ((nbytes
= walk
.nbytes
) > 0) {
87 const u8
*src
= walk
.src
.virt
.addr
;
88 u8
*dst
= walk
.dst
.virt
.addr
;
90 while (nbytes
>= ARIA_GFNI_AVX512_PARALLEL_BLOCK_SIZE
) {
92 aria_ops
.aria_ctr_crypt_64way(ctx
, dst
, src
,
93 &req_ctx
->keystream
[0],
96 dst
+= ARIA_GFNI_AVX512_PARALLEL_BLOCK_SIZE
;
97 src
+= ARIA_GFNI_AVX512_PARALLEL_BLOCK_SIZE
;
98 nbytes
-= ARIA_GFNI_AVX512_PARALLEL_BLOCK_SIZE
;
101 while (nbytes
>= ARIA_AESNI_AVX2_PARALLEL_BLOCK_SIZE
) {
103 aria_ops
.aria_ctr_crypt_32way(ctx
, dst
, src
,
104 &req_ctx
->keystream
[0],
107 dst
+= ARIA_AESNI_AVX2_PARALLEL_BLOCK_SIZE
;
108 src
+= ARIA_AESNI_AVX2_PARALLEL_BLOCK_SIZE
;
109 nbytes
-= ARIA_AESNI_AVX2_PARALLEL_BLOCK_SIZE
;
112 while (nbytes
>= ARIA_AESNI_PARALLEL_BLOCK_SIZE
) {
114 aria_ops
.aria_ctr_crypt_16way(ctx
, dst
, src
,
115 &req_ctx
->keystream
[0],
118 dst
+= ARIA_AESNI_PARALLEL_BLOCK_SIZE
;
119 src
+= ARIA_AESNI_PARALLEL_BLOCK_SIZE
;
120 nbytes
-= ARIA_AESNI_PARALLEL_BLOCK_SIZE
;
123 while (nbytes
>= ARIA_BLOCK_SIZE
) {
124 memcpy(&req_ctx
->keystream
[0], walk
.iv
,
126 crypto_inc(walk
.iv
, ARIA_BLOCK_SIZE
);
128 aria_encrypt(ctx
, &req_ctx
->keystream
[0],
129 &req_ctx
->keystream
[0]);
131 crypto_xor_cpy(dst
, src
, &req_ctx
->keystream
[0],
133 dst
+= ARIA_BLOCK_SIZE
;
134 src
+= ARIA_BLOCK_SIZE
;
135 nbytes
-= ARIA_BLOCK_SIZE
;
138 if (walk
.nbytes
== walk
.total
&& nbytes
> 0) {
139 memcpy(&req_ctx
->keystream
[0], walk
.iv
,
141 crypto_inc(walk
.iv
, ARIA_BLOCK_SIZE
);
143 aria_encrypt(ctx
, &req_ctx
->keystream
[0],
144 &req_ctx
->keystream
[0]);
146 crypto_xor_cpy(dst
, src
, &req_ctx
->keystream
[0],
152 err
= skcipher_walk_done(&walk
, nbytes
);
158 static int aria_avx512_init_tfm(struct crypto_skcipher
*tfm
)
160 crypto_skcipher_set_reqsize(tfm
,
161 sizeof(struct aria_avx512_request_ctx
));
166 static struct skcipher_alg aria_algs
[] = {
168 .base
.cra_name
= "__ecb(aria)",
169 .base
.cra_driver_name
= "__ecb-aria-avx512",
170 .base
.cra_priority
= 600,
171 .base
.cra_flags
= CRYPTO_ALG_INTERNAL
,
172 .base
.cra_blocksize
= ARIA_BLOCK_SIZE
,
173 .base
.cra_ctxsize
= sizeof(struct aria_ctx
),
174 .base
.cra_module
= THIS_MODULE
,
175 .min_keysize
= ARIA_MIN_KEY_SIZE
,
176 .max_keysize
= ARIA_MAX_KEY_SIZE
,
177 .setkey
= aria_avx512_set_key
,
178 .encrypt
= aria_avx512_ecb_encrypt
,
179 .decrypt
= aria_avx512_ecb_decrypt
,
181 .base
.cra_name
= "__ctr(aria)",
182 .base
.cra_driver_name
= "__ctr-aria-avx512",
183 .base
.cra_priority
= 600,
184 .base
.cra_flags
= CRYPTO_ALG_INTERNAL
|
185 CRYPTO_ALG_SKCIPHER_REQSIZE_LARGE
,
186 .base
.cra_blocksize
= 1,
187 .base
.cra_ctxsize
= sizeof(struct aria_ctx
),
188 .base
.cra_module
= THIS_MODULE
,
189 .min_keysize
= ARIA_MIN_KEY_SIZE
,
190 .max_keysize
= ARIA_MAX_KEY_SIZE
,
191 .ivsize
= ARIA_BLOCK_SIZE
,
192 .chunksize
= ARIA_BLOCK_SIZE
,
193 .setkey
= aria_avx512_set_key
,
194 .encrypt
= aria_avx512_ctr_encrypt
,
195 .decrypt
= aria_avx512_ctr_encrypt
,
196 .init
= aria_avx512_init_tfm
,
200 static struct simd_skcipher_alg
*aria_simd_algs
[ARRAY_SIZE(aria_algs
)];
202 static int __init
aria_avx512_init(void)
204 const char *feature_name
;
206 if (!boot_cpu_has(X86_FEATURE_AVX
) ||
207 !boot_cpu_has(X86_FEATURE_AVX2
) ||
208 !boot_cpu_has(X86_FEATURE_AVX512F
) ||
209 !boot_cpu_has(X86_FEATURE_AVX512VL
) ||
210 !boot_cpu_has(X86_FEATURE_GFNI
) ||
211 !boot_cpu_has(X86_FEATURE_OSXSAVE
)) {
212 pr_info("AVX512/GFNI instructions are not detected.\n");
216 if (!cpu_has_xfeatures(XFEATURE_MASK_SSE
| XFEATURE_MASK_YMM
|
217 XFEATURE_MASK_AVX512
, &feature_name
)) {
218 pr_info("CPU feature '%s' is not supported.\n", feature_name
);
222 aria_ops
.aria_encrypt_16way
= aria_aesni_avx_gfni_encrypt_16way
;
223 aria_ops
.aria_decrypt_16way
= aria_aesni_avx_gfni_decrypt_16way
;
224 aria_ops
.aria_ctr_crypt_16way
= aria_aesni_avx_gfni_ctr_crypt_16way
;
225 aria_ops
.aria_encrypt_32way
= aria_aesni_avx2_gfni_encrypt_32way
;
226 aria_ops
.aria_decrypt_32way
= aria_aesni_avx2_gfni_decrypt_32way
;
227 aria_ops
.aria_ctr_crypt_32way
= aria_aesni_avx2_gfni_ctr_crypt_32way
;
228 aria_ops
.aria_encrypt_64way
= aria_gfni_avx512_encrypt_64way
;
229 aria_ops
.aria_decrypt_64way
= aria_gfni_avx512_decrypt_64way
;
230 aria_ops
.aria_ctr_crypt_64way
= aria_gfni_avx512_ctr_crypt_64way
;
232 return simd_register_skciphers_compat(aria_algs
,
233 ARRAY_SIZE(aria_algs
),
237 static void __exit
aria_avx512_exit(void)
239 simd_unregister_skciphers(aria_algs
, ARRAY_SIZE(aria_algs
),
243 module_init(aria_avx512_init
);
244 module_exit(aria_avx512_exit
);
246 MODULE_LICENSE("GPL");
247 MODULE_AUTHOR("Taehee Yoo <ap420073@gmail.com>");
248 MODULE_DESCRIPTION("ARIA Cipher Algorithm, AVX512/GFNI optimized");
249 MODULE_ALIAS_CRYPTO("aria");
250 MODULE_ALIAS_CRYPTO("aria-gfni-avx512");