2 * The AEGIS-128 Authenticated-Encryption Algorithm
3 * Glue for AES-NI + SSE2 implementation
5 * Copyright (c) 2017-2018 Ondrej Mosnacek <omosnacek@gmail.com>
6 * Copyright (C) 2017-2018 Red Hat, Inc. All rights reserved.
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the Free
10 * Software Foundation; either version 2 of the License, or (at your option)
14 #include <crypto/cryptd.h>
15 #include <crypto/internal/aead.h>
16 #include <crypto/internal/skcipher.h>
17 #include <crypto/scatterwalk.h>
18 #include <linux/module.h>
19 #include <asm/fpu/api.h>
20 #include <asm/cpu_device_id.h>
22 #define AEGIS128_BLOCK_ALIGN 16
23 #define AEGIS128_BLOCK_SIZE 16
24 #define AEGIS128_NONCE_SIZE 16
25 #define AEGIS128_STATE_BLOCKS 5
26 #define AEGIS128_KEY_SIZE 16
27 #define AEGIS128_MIN_AUTH_SIZE 8
28 #define AEGIS128_MAX_AUTH_SIZE 16
30 asmlinkage
void crypto_aegis128_aesni_init(void *state
, void *key
, void *iv
);
32 asmlinkage
void crypto_aegis128_aesni_ad(
33 void *state
, unsigned int length
, const void *data
);
35 asmlinkage
void crypto_aegis128_aesni_enc(
36 void *state
, unsigned int length
, const void *src
, void *dst
);
38 asmlinkage
void crypto_aegis128_aesni_dec(
39 void *state
, unsigned int length
, const void *src
, void *dst
);
41 asmlinkage
void crypto_aegis128_aesni_enc_tail(
42 void *state
, unsigned int length
, const void *src
, void *dst
);
44 asmlinkage
void crypto_aegis128_aesni_dec_tail(
45 void *state
, unsigned int length
, const void *src
, void *dst
);
47 asmlinkage
void crypto_aegis128_aesni_final(
48 void *state
, void *tag_xor
, unsigned int cryptlen
,
49 unsigned int assoclen
);
52 u8 bytes
[AEGIS128_BLOCK_SIZE
] __aligned(AEGIS128_BLOCK_ALIGN
);
56 struct aegis_block blocks
[AEGIS128_STATE_BLOCKS
];
60 struct aegis_block key
;
63 struct aegis_crypt_ops
{
64 int (*skcipher_walk_init
)(struct skcipher_walk
*walk
,
65 struct aead_request
*req
, bool atomic
);
67 void (*crypt_blocks
)(void *state
, unsigned int length
, const void *src
,
69 void (*crypt_tail
)(void *state
, unsigned int length
, const void *src
,
73 static void crypto_aegis128_aesni_process_ad(
74 struct aegis_state
*state
, struct scatterlist
*sg_src
,
75 unsigned int assoclen
)
77 struct scatter_walk walk
;
78 struct aegis_block buf
;
81 scatterwalk_start(&walk
, sg_src
);
82 while (assoclen
!= 0) {
83 unsigned int size
= scatterwalk_clamp(&walk
, assoclen
);
84 unsigned int left
= size
;
85 void *mapped
= scatterwalk_map(&walk
);
86 const u8
*src
= (const u8
*)mapped
;
88 if (pos
+ size
>= AEGIS128_BLOCK_SIZE
) {
90 unsigned int fill
= AEGIS128_BLOCK_SIZE
- pos
;
91 memcpy(buf
.bytes
+ pos
, src
, fill
);
92 crypto_aegis128_aesni_ad(state
,
100 crypto_aegis128_aesni_ad(state
, left
, src
);
102 src
+= left
& ~(AEGIS128_BLOCK_SIZE
- 1);
103 left
&= AEGIS128_BLOCK_SIZE
- 1;
106 memcpy(buf
.bytes
+ pos
, src
, left
);
110 scatterwalk_unmap(mapped
);
111 scatterwalk_advance(&walk
, size
);
112 scatterwalk_done(&walk
, 0, assoclen
);
116 memset(buf
.bytes
+ pos
, 0, AEGIS128_BLOCK_SIZE
- pos
);
117 crypto_aegis128_aesni_ad(state
, AEGIS128_BLOCK_SIZE
, buf
.bytes
);
121 static void crypto_aegis128_aesni_process_crypt(
122 struct aegis_state
*state
, struct aead_request
*req
,
123 const struct aegis_crypt_ops
*ops
)
125 struct skcipher_walk walk
;
127 unsigned int chunksize
, base
;
129 ops
->skcipher_walk_init(&walk
, req
, false);
131 while (walk
.nbytes
) {
132 src
= walk
.src
.virt
.addr
;
133 dst
= walk
.dst
.virt
.addr
;
134 chunksize
= walk
.nbytes
;
136 ops
->crypt_blocks(state
, chunksize
, src
, dst
);
138 base
= chunksize
& ~(AEGIS128_BLOCK_SIZE
- 1);
141 chunksize
&= AEGIS128_BLOCK_SIZE
- 1;
144 ops
->crypt_tail(state
, chunksize
, src
, dst
);
146 skcipher_walk_done(&walk
, 0);
150 static struct aegis_ctx
*crypto_aegis128_aesni_ctx(struct crypto_aead
*aead
)
152 u8
*ctx
= crypto_aead_ctx(aead
);
153 ctx
= PTR_ALIGN(ctx
, __alignof__(struct aegis_ctx
));
157 static int crypto_aegis128_aesni_setkey(struct crypto_aead
*aead
, const u8
*key
,
160 struct aegis_ctx
*ctx
= crypto_aegis128_aesni_ctx(aead
);
162 if (keylen
!= AEGIS128_KEY_SIZE
) {
163 crypto_aead_set_flags(aead
, CRYPTO_TFM_RES_BAD_KEY_LEN
);
167 memcpy(ctx
->key
.bytes
, key
, AEGIS128_KEY_SIZE
);
172 static int crypto_aegis128_aesni_setauthsize(struct crypto_aead
*tfm
,
173 unsigned int authsize
)
175 if (authsize
> AEGIS128_MAX_AUTH_SIZE
)
177 if (authsize
< AEGIS128_MIN_AUTH_SIZE
)
182 static void crypto_aegis128_aesni_crypt(struct aead_request
*req
,
183 struct aegis_block
*tag_xor
,
184 unsigned int cryptlen
,
185 const struct aegis_crypt_ops
*ops
)
187 struct crypto_aead
*tfm
= crypto_aead_reqtfm(req
);
188 struct aegis_ctx
*ctx
= crypto_aegis128_aesni_ctx(tfm
);
189 struct aegis_state state
;
193 crypto_aegis128_aesni_init(&state
, ctx
->key
.bytes
, req
->iv
);
194 crypto_aegis128_aesni_process_ad(&state
, req
->src
, req
->assoclen
);
195 crypto_aegis128_aesni_process_crypt(&state
, req
, ops
);
196 crypto_aegis128_aesni_final(&state
, tag_xor
, req
->assoclen
, cryptlen
);
201 static int crypto_aegis128_aesni_encrypt(struct aead_request
*req
)
203 static const struct aegis_crypt_ops OPS
= {
204 .skcipher_walk_init
= skcipher_walk_aead_encrypt
,
205 .crypt_blocks
= crypto_aegis128_aesni_enc
,
206 .crypt_tail
= crypto_aegis128_aesni_enc_tail
,
209 struct crypto_aead
*tfm
= crypto_aead_reqtfm(req
);
210 struct aegis_block tag
= {};
211 unsigned int authsize
= crypto_aead_authsize(tfm
);
212 unsigned int cryptlen
= req
->cryptlen
;
214 crypto_aegis128_aesni_crypt(req
, &tag
, cryptlen
, &OPS
);
216 scatterwalk_map_and_copy(tag
.bytes
, req
->dst
,
217 req
->assoclen
+ cryptlen
, authsize
, 1);
221 static int crypto_aegis128_aesni_decrypt(struct aead_request
*req
)
223 static const struct aegis_block zeros
= {};
225 static const struct aegis_crypt_ops OPS
= {
226 .skcipher_walk_init
= skcipher_walk_aead_decrypt
,
227 .crypt_blocks
= crypto_aegis128_aesni_dec
,
228 .crypt_tail
= crypto_aegis128_aesni_dec_tail
,
231 struct crypto_aead
*tfm
= crypto_aead_reqtfm(req
);
232 struct aegis_block tag
;
233 unsigned int authsize
= crypto_aead_authsize(tfm
);
234 unsigned int cryptlen
= req
->cryptlen
- authsize
;
236 scatterwalk_map_and_copy(tag
.bytes
, req
->src
,
237 req
->assoclen
+ cryptlen
, authsize
, 0);
239 crypto_aegis128_aesni_crypt(req
, &tag
, cryptlen
, &OPS
);
241 return crypto_memneq(tag
.bytes
, zeros
.bytes
, authsize
) ? -EBADMSG
: 0;
244 static int crypto_aegis128_aesni_init_tfm(struct crypto_aead
*aead
)
249 static void crypto_aegis128_aesni_exit_tfm(struct crypto_aead
*aead
)
253 static int cryptd_aegis128_aesni_setkey(struct crypto_aead
*aead
,
254 const u8
*key
, unsigned int keylen
)
256 struct cryptd_aead
**ctx
= crypto_aead_ctx(aead
);
257 struct cryptd_aead
*cryptd_tfm
= *ctx
;
259 return crypto_aead_setkey(&cryptd_tfm
->base
, key
, keylen
);
262 static int cryptd_aegis128_aesni_setauthsize(struct crypto_aead
*aead
,
263 unsigned int authsize
)
265 struct cryptd_aead
**ctx
= crypto_aead_ctx(aead
);
266 struct cryptd_aead
*cryptd_tfm
= *ctx
;
268 return crypto_aead_setauthsize(&cryptd_tfm
->base
, authsize
);
271 static int cryptd_aegis128_aesni_encrypt(struct aead_request
*req
)
273 struct crypto_aead
*aead
= crypto_aead_reqtfm(req
);
274 struct cryptd_aead
**ctx
= crypto_aead_ctx(aead
);
275 struct cryptd_aead
*cryptd_tfm
= *ctx
;
277 aead
= &cryptd_tfm
->base
;
278 if (irq_fpu_usable() && (!in_atomic() ||
279 !cryptd_aead_queued(cryptd_tfm
)))
280 aead
= cryptd_aead_child(cryptd_tfm
);
282 aead_request_set_tfm(req
, aead
);
284 return crypto_aead_encrypt(req
);
287 static int cryptd_aegis128_aesni_decrypt(struct aead_request
*req
)
289 struct crypto_aead
*aead
= crypto_aead_reqtfm(req
);
290 struct cryptd_aead
**ctx
= crypto_aead_ctx(aead
);
291 struct cryptd_aead
*cryptd_tfm
= *ctx
;
293 aead
= &cryptd_tfm
->base
;
294 if (irq_fpu_usable() && (!in_atomic() ||
295 !cryptd_aead_queued(cryptd_tfm
)))
296 aead
= cryptd_aead_child(cryptd_tfm
);
298 aead_request_set_tfm(req
, aead
);
300 return crypto_aead_decrypt(req
);
303 static int cryptd_aegis128_aesni_init_tfm(struct crypto_aead
*aead
)
305 struct cryptd_aead
*cryptd_tfm
;
306 struct cryptd_aead
**ctx
= crypto_aead_ctx(aead
);
308 cryptd_tfm
= cryptd_alloc_aead("__aegis128-aesni", CRYPTO_ALG_INTERNAL
,
309 CRYPTO_ALG_INTERNAL
);
310 if (IS_ERR(cryptd_tfm
))
311 return PTR_ERR(cryptd_tfm
);
314 crypto_aead_set_reqsize(aead
, crypto_aead_reqsize(&cryptd_tfm
->base
));
318 static void cryptd_aegis128_aesni_exit_tfm(struct crypto_aead
*aead
)
320 struct cryptd_aead
**ctx
= crypto_aead_ctx(aead
);
322 cryptd_free_aead(*ctx
);
325 static struct aead_alg crypto_aegis128_aesni_alg
[] = {
327 .setkey
= crypto_aegis128_aesni_setkey
,
328 .setauthsize
= crypto_aegis128_aesni_setauthsize
,
329 .encrypt
= crypto_aegis128_aesni_encrypt
,
330 .decrypt
= crypto_aegis128_aesni_decrypt
,
331 .init
= crypto_aegis128_aesni_init_tfm
,
332 .exit
= crypto_aegis128_aesni_exit_tfm
,
334 .ivsize
= AEGIS128_NONCE_SIZE
,
335 .maxauthsize
= AEGIS128_MAX_AUTH_SIZE
,
336 .chunksize
= AEGIS128_BLOCK_SIZE
,
339 .cra_flags
= CRYPTO_ALG_INTERNAL
,
341 .cra_ctxsize
= sizeof(struct aegis_ctx
) +
342 __alignof__(struct aegis_ctx
),
345 .cra_name
= "__aegis128",
346 .cra_driver_name
= "__aegis128-aesni",
348 .cra_module
= THIS_MODULE
,
351 .setkey
= cryptd_aegis128_aesni_setkey
,
352 .setauthsize
= cryptd_aegis128_aesni_setauthsize
,
353 .encrypt
= cryptd_aegis128_aesni_encrypt
,
354 .decrypt
= cryptd_aegis128_aesni_decrypt
,
355 .init
= cryptd_aegis128_aesni_init_tfm
,
356 .exit
= cryptd_aegis128_aesni_exit_tfm
,
358 .ivsize
= AEGIS128_NONCE_SIZE
,
359 .maxauthsize
= AEGIS128_MAX_AUTH_SIZE
,
360 .chunksize
= AEGIS128_BLOCK_SIZE
,
363 .cra_flags
= CRYPTO_ALG_ASYNC
,
365 .cra_ctxsize
= sizeof(struct cryptd_aead
*),
370 .cra_name
= "aegis128",
371 .cra_driver_name
= "aegis128-aesni",
373 .cra_module
= THIS_MODULE
,
378 static int __init
crypto_aegis128_aesni_module_init(void)
380 if (!boot_cpu_has(X86_FEATURE_XMM2
) ||
381 !boot_cpu_has(X86_FEATURE_AES
) ||
382 !boot_cpu_has(X86_FEATURE_OSXSAVE
) ||
383 !cpu_has_xfeatures(XFEATURE_MASK_SSE
, NULL
))
386 return crypto_register_aeads(crypto_aegis128_aesni_alg
,
387 ARRAY_SIZE(crypto_aegis128_aesni_alg
));
390 static void __exit
crypto_aegis128_aesni_module_exit(void)
392 crypto_unregister_aeads(crypto_aegis128_aesni_alg
,
393 ARRAY_SIZE(crypto_aegis128_aesni_alg
));
396 module_init(crypto_aegis128_aesni_module_init
);
397 module_exit(crypto_aegis128_aesni_module_exit
);
399 MODULE_LICENSE("GPL");
400 MODULE_AUTHOR("Ondrej Mosnacek <omosnacek@gmail.com>");
401 MODULE_DESCRIPTION("AEGIS-128 AEAD algorithm -- AESNI+SSE2 implementation");
402 MODULE_ALIAS_CRYPTO("aegis128");
403 MODULE_ALIAS_CRYPTO("aegis128-aesni");