2 * The AEGIS-128L Authenticated-Encryption Algorithm
4 * Copyright (c) 2017-2018 Ondrej Mosnacek <omosnacek@gmail.com>
5 * Copyright (C) 2017-2018 Red Hat, Inc. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
13 #include <crypto/algapi.h>
14 #include <crypto/internal/aead.h>
15 #include <crypto/internal/skcipher.h>
16 #include <crypto/scatterwalk.h>
17 #include <linux/err.h>
18 #include <linux/init.h>
19 #include <linux/kernel.h>
20 #include <linux/module.h>
21 #include <linux/scatterlist.h>
25 #define AEGIS128L_CHUNK_BLOCKS 2
26 #define AEGIS128L_CHUNK_SIZE (AEGIS128L_CHUNK_BLOCKS * AEGIS_BLOCK_SIZE)
27 #define AEGIS128L_NONCE_SIZE 16
28 #define AEGIS128L_STATE_BLOCKS 8
29 #define AEGIS128L_KEY_SIZE 16
30 #define AEGIS128L_MIN_AUTH_SIZE 8
31 #define AEGIS128L_MAX_AUTH_SIZE 16
34 union aegis_block blocks
[AEGIS128L_CHUNK_BLOCKS
];
35 u8 bytes
[AEGIS128L_CHUNK_SIZE
];
39 union aegis_block blocks
[AEGIS128L_STATE_BLOCKS
];
43 union aegis_block key
;
46 struct aegis128l_ops
{
47 int (*skcipher_walk_init
)(struct skcipher_walk
*walk
,
48 struct aead_request
*req
, bool atomic
);
50 void (*crypt_chunk
)(struct aegis_state
*state
, u8
*dst
,
51 const u8
*src
, unsigned int size
);
54 static void crypto_aegis128l_update(struct aegis_state
*state
)
56 union aegis_block tmp
;
59 tmp
= state
->blocks
[AEGIS128L_STATE_BLOCKS
- 1];
60 for (i
= AEGIS128L_STATE_BLOCKS
- 1; i
> 0; i
--)
61 crypto_aegis_aesenc(&state
->blocks
[i
], &state
->blocks
[i
- 1],
63 crypto_aegis_aesenc(&state
->blocks
[0], &tmp
, &state
->blocks
[0]);
66 static void crypto_aegis128l_update_a(struct aegis_state
*state
,
67 const union aegis_chunk
*msg
)
69 crypto_aegis128l_update(state
);
70 crypto_aegis_block_xor(&state
->blocks
[0], &msg
->blocks
[0]);
71 crypto_aegis_block_xor(&state
->blocks
[4], &msg
->blocks
[1]);
74 static void crypto_aegis128l_update_u(struct aegis_state
*state
,
77 crypto_aegis128l_update(state
);
78 crypto_xor(state
->blocks
[0].bytes
, msg
+ 0 * AEGIS_BLOCK_SIZE
,
80 crypto_xor(state
->blocks
[4].bytes
, msg
+ 1 * AEGIS_BLOCK_SIZE
,
84 static void crypto_aegis128l_init(struct aegis_state
*state
,
85 const union aegis_block
*key
,
88 union aegis_block key_iv
;
89 union aegis_chunk chunk
;
92 memcpy(chunk
.blocks
[0].bytes
, iv
, AEGIS_BLOCK_SIZE
);
93 chunk
.blocks
[1] = *key
;
96 crypto_aegis_block_xor(&key_iv
, &chunk
.blocks
[0]);
98 state
->blocks
[0] = key_iv
;
99 state
->blocks
[1] = crypto_aegis_const
[1];
100 state
->blocks
[2] = crypto_aegis_const
[0];
101 state
->blocks
[3] = crypto_aegis_const
[1];
102 state
->blocks
[4] = key_iv
;
103 state
->blocks
[5] = *key
;
104 state
->blocks
[6] = *key
;
105 state
->blocks
[7] = *key
;
107 crypto_aegis_block_xor(&state
->blocks
[5], &crypto_aegis_const
[0]);
108 crypto_aegis_block_xor(&state
->blocks
[6], &crypto_aegis_const
[1]);
109 crypto_aegis_block_xor(&state
->blocks
[7], &crypto_aegis_const
[0]);
111 for (i
= 0; i
< 10; i
++) {
112 crypto_aegis128l_update_a(state
, &chunk
);
116 static void crypto_aegis128l_ad(struct aegis_state
*state
,
117 const u8
*src
, unsigned int size
)
119 if (AEGIS_ALIGNED(src
)) {
120 const union aegis_chunk
*src_chunk
=
121 (const union aegis_chunk
*)src
;
123 while (size
>= AEGIS128L_CHUNK_SIZE
) {
124 crypto_aegis128l_update_a(state
, src_chunk
);
126 size
-= AEGIS128L_CHUNK_SIZE
;
130 while (size
>= AEGIS128L_CHUNK_SIZE
) {
131 crypto_aegis128l_update_u(state
, src
);
133 size
-= AEGIS128L_CHUNK_SIZE
;
134 src
+= AEGIS128L_CHUNK_SIZE
;
139 static void crypto_aegis128l_encrypt_chunk(struct aegis_state
*state
, u8
*dst
,
140 const u8
*src
, unsigned int size
)
142 union aegis_chunk tmp
;
143 union aegis_block
*tmp0
= &tmp
.blocks
[0];
144 union aegis_block
*tmp1
= &tmp
.blocks
[1];
146 if (AEGIS_ALIGNED(src
) && AEGIS_ALIGNED(dst
)) {
147 while (size
>= AEGIS128L_CHUNK_SIZE
) {
148 union aegis_chunk
*dst_blk
=
149 (union aegis_chunk
*)dst
;
150 const union aegis_chunk
*src_blk
=
151 (const union aegis_chunk
*)src
;
153 *tmp0
= state
->blocks
[2];
154 crypto_aegis_block_and(tmp0
, &state
->blocks
[3]);
155 crypto_aegis_block_xor(tmp0
, &state
->blocks
[6]);
156 crypto_aegis_block_xor(tmp0
, &state
->blocks
[1]);
157 crypto_aegis_block_xor(tmp0
, &src_blk
->blocks
[0]);
159 *tmp1
= state
->blocks
[6];
160 crypto_aegis_block_and(tmp1
, &state
->blocks
[7]);
161 crypto_aegis_block_xor(tmp1
, &state
->blocks
[5]);
162 crypto_aegis_block_xor(tmp1
, &state
->blocks
[2]);
163 crypto_aegis_block_xor(tmp1
, &src_blk
->blocks
[1]);
165 crypto_aegis128l_update_a(state
, src_blk
);
169 size
-= AEGIS128L_CHUNK_SIZE
;
170 src
+= AEGIS128L_CHUNK_SIZE
;
171 dst
+= AEGIS128L_CHUNK_SIZE
;
174 while (size
>= AEGIS128L_CHUNK_SIZE
) {
175 *tmp0
= state
->blocks
[2];
176 crypto_aegis_block_and(tmp0
, &state
->blocks
[3]);
177 crypto_aegis_block_xor(tmp0
, &state
->blocks
[6]);
178 crypto_aegis_block_xor(tmp0
, &state
->blocks
[1]);
179 crypto_xor(tmp0
->bytes
, src
+ 0 * AEGIS_BLOCK_SIZE
,
182 *tmp1
= state
->blocks
[6];
183 crypto_aegis_block_and(tmp1
, &state
->blocks
[7]);
184 crypto_aegis_block_xor(tmp1
, &state
->blocks
[5]);
185 crypto_aegis_block_xor(tmp1
, &state
->blocks
[2]);
186 crypto_xor(tmp1
->bytes
, src
+ 1 * AEGIS_BLOCK_SIZE
,
189 crypto_aegis128l_update_u(state
, src
);
191 memcpy(dst
, tmp
.bytes
, AEGIS128L_CHUNK_SIZE
);
193 size
-= AEGIS128L_CHUNK_SIZE
;
194 src
+= AEGIS128L_CHUNK_SIZE
;
195 dst
+= AEGIS128L_CHUNK_SIZE
;
200 union aegis_chunk msg
= {};
201 memcpy(msg
.bytes
, src
, size
);
203 *tmp0
= state
->blocks
[2];
204 crypto_aegis_block_and(tmp0
, &state
->blocks
[3]);
205 crypto_aegis_block_xor(tmp0
, &state
->blocks
[6]);
206 crypto_aegis_block_xor(tmp0
, &state
->blocks
[1]);
208 *tmp1
= state
->blocks
[6];
209 crypto_aegis_block_and(tmp1
, &state
->blocks
[7]);
210 crypto_aegis_block_xor(tmp1
, &state
->blocks
[5]);
211 crypto_aegis_block_xor(tmp1
, &state
->blocks
[2]);
213 crypto_aegis128l_update_a(state
, &msg
);
215 crypto_aegis_block_xor(&msg
.blocks
[0], tmp0
);
216 crypto_aegis_block_xor(&msg
.blocks
[1], tmp1
);
218 memcpy(dst
, msg
.bytes
, size
);
222 static void crypto_aegis128l_decrypt_chunk(struct aegis_state
*state
, u8
*dst
,
223 const u8
*src
, unsigned int size
)
225 union aegis_chunk tmp
;
226 union aegis_block
*tmp0
= &tmp
.blocks
[0];
227 union aegis_block
*tmp1
= &tmp
.blocks
[1];
229 if (AEGIS_ALIGNED(src
) && AEGIS_ALIGNED(dst
)) {
230 while (size
>= AEGIS128L_CHUNK_SIZE
) {
231 union aegis_chunk
*dst_blk
=
232 (union aegis_chunk
*)dst
;
233 const union aegis_chunk
*src_blk
=
234 (const union aegis_chunk
*)src
;
236 *tmp0
= state
->blocks
[2];
237 crypto_aegis_block_and(tmp0
, &state
->blocks
[3]);
238 crypto_aegis_block_xor(tmp0
, &state
->blocks
[6]);
239 crypto_aegis_block_xor(tmp0
, &state
->blocks
[1]);
240 crypto_aegis_block_xor(tmp0
, &src_blk
->blocks
[0]);
242 *tmp1
= state
->blocks
[6];
243 crypto_aegis_block_and(tmp1
, &state
->blocks
[7]);
244 crypto_aegis_block_xor(tmp1
, &state
->blocks
[5]);
245 crypto_aegis_block_xor(tmp1
, &state
->blocks
[2]);
246 crypto_aegis_block_xor(tmp1
, &src_blk
->blocks
[1]);
248 crypto_aegis128l_update_a(state
, &tmp
);
252 size
-= AEGIS128L_CHUNK_SIZE
;
253 src
+= AEGIS128L_CHUNK_SIZE
;
254 dst
+= AEGIS128L_CHUNK_SIZE
;
257 while (size
>= AEGIS128L_CHUNK_SIZE
) {
258 *tmp0
= state
->blocks
[2];
259 crypto_aegis_block_and(tmp0
, &state
->blocks
[3]);
260 crypto_aegis_block_xor(tmp0
, &state
->blocks
[6]);
261 crypto_aegis_block_xor(tmp0
, &state
->blocks
[1]);
262 crypto_xor(tmp0
->bytes
, src
+ 0 * AEGIS_BLOCK_SIZE
,
265 *tmp1
= state
->blocks
[6];
266 crypto_aegis_block_and(tmp1
, &state
->blocks
[7]);
267 crypto_aegis_block_xor(tmp1
, &state
->blocks
[5]);
268 crypto_aegis_block_xor(tmp1
, &state
->blocks
[2]);
269 crypto_xor(tmp1
->bytes
, src
+ 1 * AEGIS_BLOCK_SIZE
,
272 crypto_aegis128l_update_a(state
, &tmp
);
274 memcpy(dst
, tmp
.bytes
, AEGIS128L_CHUNK_SIZE
);
276 size
-= AEGIS128L_CHUNK_SIZE
;
277 src
+= AEGIS128L_CHUNK_SIZE
;
278 dst
+= AEGIS128L_CHUNK_SIZE
;
283 union aegis_chunk msg
= {};
284 memcpy(msg
.bytes
, src
, size
);
286 *tmp0
= state
->blocks
[2];
287 crypto_aegis_block_and(tmp0
, &state
->blocks
[3]);
288 crypto_aegis_block_xor(tmp0
, &state
->blocks
[6]);
289 crypto_aegis_block_xor(tmp0
, &state
->blocks
[1]);
290 crypto_aegis_block_xor(&msg
.blocks
[0], tmp0
);
292 *tmp1
= state
->blocks
[6];
293 crypto_aegis_block_and(tmp1
, &state
->blocks
[7]);
294 crypto_aegis_block_xor(tmp1
, &state
->blocks
[5]);
295 crypto_aegis_block_xor(tmp1
, &state
->blocks
[2]);
296 crypto_aegis_block_xor(&msg
.blocks
[1], tmp1
);
298 memset(msg
.bytes
+ size
, 0, AEGIS128L_CHUNK_SIZE
- size
);
300 crypto_aegis128l_update_a(state
, &msg
);
302 memcpy(dst
, msg
.bytes
, size
);
306 static void crypto_aegis128l_process_ad(struct aegis_state
*state
,
307 struct scatterlist
*sg_src
,
308 unsigned int assoclen
)
310 struct scatter_walk walk
;
311 union aegis_chunk buf
;
312 unsigned int pos
= 0;
314 scatterwalk_start(&walk
, sg_src
);
315 while (assoclen
!= 0) {
316 unsigned int size
= scatterwalk_clamp(&walk
, assoclen
);
317 unsigned int left
= size
;
318 void *mapped
= scatterwalk_map(&walk
);
319 const u8
*src
= (const u8
*)mapped
;
321 if (pos
+ size
>= AEGIS128L_CHUNK_SIZE
) {
323 unsigned int fill
= AEGIS128L_CHUNK_SIZE
- pos
;
324 memcpy(buf
.bytes
+ pos
, src
, fill
);
325 crypto_aegis128l_update_a(state
, &buf
);
331 crypto_aegis128l_ad(state
, src
, left
);
332 src
+= left
& ~(AEGIS128L_CHUNK_SIZE
- 1);
333 left
&= AEGIS128L_CHUNK_SIZE
- 1;
336 memcpy(buf
.bytes
+ pos
, src
, left
);
340 scatterwalk_unmap(mapped
);
341 scatterwalk_advance(&walk
, size
);
342 scatterwalk_done(&walk
, 0, assoclen
);
346 memset(buf
.bytes
+ pos
, 0, AEGIS128L_CHUNK_SIZE
- pos
);
347 crypto_aegis128l_update_a(state
, &buf
);
351 static void crypto_aegis128l_process_crypt(struct aegis_state
*state
,
352 struct aead_request
*req
,
353 const struct aegis128l_ops
*ops
)
355 struct skcipher_walk walk
;
357 ops
->skcipher_walk_init(&walk
, req
, false);
359 while (walk
.nbytes
) {
360 unsigned int nbytes
= walk
.nbytes
;
362 if (nbytes
< walk
.total
)
363 nbytes
= round_down(nbytes
, walk
.stride
);
365 ops
->crypt_chunk(state
, walk
.dst
.virt
.addr
, walk
.src
.virt
.addr
,
368 skcipher_walk_done(&walk
, walk
.nbytes
- nbytes
);
372 static void crypto_aegis128l_final(struct aegis_state
*state
,
373 union aegis_block
*tag_xor
,
374 u64 assoclen
, u64 cryptlen
)
376 u64 assocbits
= assoclen
* 8;
377 u64 cryptbits
= cryptlen
* 8;
379 union aegis_chunk tmp
;
382 tmp
.blocks
[0].words64
[0] = cpu_to_le64(assocbits
);
383 tmp
.blocks
[0].words64
[1] = cpu_to_le64(cryptbits
);
385 crypto_aegis_block_xor(&tmp
.blocks
[0], &state
->blocks
[2]);
387 tmp
.blocks
[1] = tmp
.blocks
[0];
388 for (i
= 0; i
< 7; i
++)
389 crypto_aegis128l_update_a(state
, &tmp
);
391 for (i
= 0; i
< 7; i
++)
392 crypto_aegis_block_xor(tag_xor
, &state
->blocks
[i
]);
395 static int crypto_aegis128l_setkey(struct crypto_aead
*aead
, const u8
*key
,
398 struct aegis_ctx
*ctx
= crypto_aead_ctx(aead
);
400 if (keylen
!= AEGIS128L_KEY_SIZE
) {
401 crypto_aead_set_flags(aead
, CRYPTO_TFM_RES_BAD_KEY_LEN
);
405 memcpy(ctx
->key
.bytes
, key
, AEGIS128L_KEY_SIZE
);
409 static int crypto_aegis128l_setauthsize(struct crypto_aead
*tfm
,
410 unsigned int authsize
)
412 if (authsize
> AEGIS128L_MAX_AUTH_SIZE
)
414 if (authsize
< AEGIS128L_MIN_AUTH_SIZE
)
419 static void crypto_aegis128l_crypt(struct aead_request
*req
,
420 union aegis_block
*tag_xor
,
421 unsigned int cryptlen
,
422 const struct aegis128l_ops
*ops
)
424 struct crypto_aead
*tfm
= crypto_aead_reqtfm(req
);
425 struct aegis_ctx
*ctx
= crypto_aead_ctx(tfm
);
426 struct aegis_state state
;
428 crypto_aegis128l_init(&state
, &ctx
->key
, req
->iv
);
429 crypto_aegis128l_process_ad(&state
, req
->src
, req
->assoclen
);
430 crypto_aegis128l_process_crypt(&state
, req
, ops
);
431 crypto_aegis128l_final(&state
, tag_xor
, req
->assoclen
, cryptlen
);
434 static int crypto_aegis128l_encrypt(struct aead_request
*req
)
436 static const struct aegis128l_ops ops
= {
437 .skcipher_walk_init
= skcipher_walk_aead_encrypt
,
438 .crypt_chunk
= crypto_aegis128l_encrypt_chunk
,
441 struct crypto_aead
*tfm
= crypto_aead_reqtfm(req
);
442 union aegis_block tag
= {};
443 unsigned int authsize
= crypto_aead_authsize(tfm
);
444 unsigned int cryptlen
= req
->cryptlen
;
446 crypto_aegis128l_crypt(req
, &tag
, cryptlen
, &ops
);
448 scatterwalk_map_and_copy(tag
.bytes
, req
->dst
, req
->assoclen
+ cryptlen
,
453 static int crypto_aegis128l_decrypt(struct aead_request
*req
)
455 static const struct aegis128l_ops ops
= {
456 .skcipher_walk_init
= skcipher_walk_aead_decrypt
,
457 .crypt_chunk
= crypto_aegis128l_decrypt_chunk
,
459 static const u8 zeros
[AEGIS128L_MAX_AUTH_SIZE
] = {};
461 struct crypto_aead
*tfm
= crypto_aead_reqtfm(req
);
462 union aegis_block tag
;
463 unsigned int authsize
= crypto_aead_authsize(tfm
);
464 unsigned int cryptlen
= req
->cryptlen
- authsize
;
466 scatterwalk_map_and_copy(tag
.bytes
, req
->src
, req
->assoclen
+ cryptlen
,
469 crypto_aegis128l_crypt(req
, &tag
, cryptlen
, &ops
);
471 return crypto_memneq(tag
.bytes
, zeros
, authsize
) ? -EBADMSG
: 0;
474 static int crypto_aegis128l_init_tfm(struct crypto_aead
*tfm
)
479 static void crypto_aegis128l_exit_tfm(struct crypto_aead
*tfm
)
483 static struct aead_alg crypto_aegis128l_alg
= {
484 .setkey
= crypto_aegis128l_setkey
,
485 .setauthsize
= crypto_aegis128l_setauthsize
,
486 .encrypt
= crypto_aegis128l_encrypt
,
487 .decrypt
= crypto_aegis128l_decrypt
,
488 .init
= crypto_aegis128l_init_tfm
,
489 .exit
= crypto_aegis128l_exit_tfm
,
491 .ivsize
= AEGIS128L_NONCE_SIZE
,
492 .maxauthsize
= AEGIS128L_MAX_AUTH_SIZE
,
493 .chunksize
= AEGIS128L_CHUNK_SIZE
,
497 .cra_ctxsize
= sizeof(struct aegis_ctx
),
502 .cra_name
= "aegis128l",
503 .cra_driver_name
= "aegis128l-generic",
505 .cra_module
= THIS_MODULE
,
509 static int __init
crypto_aegis128l_module_init(void)
511 return crypto_register_aead(&crypto_aegis128l_alg
);
514 static void __exit
crypto_aegis128l_module_exit(void)
516 crypto_unregister_aead(&crypto_aegis128l_alg
);
519 module_init(crypto_aegis128l_module_init
);
520 module_exit(crypto_aegis128l_module_exit
);
522 MODULE_LICENSE("GPL");
523 MODULE_AUTHOR("Ondrej Mosnacek <omosnacek@gmail.com>");
524 MODULE_DESCRIPTION("AEGIS-128L AEAD algorithm");
525 MODULE_ALIAS_CRYPTO("aegis128l");
526 MODULE_ALIAS_CRYPTO("aegis128l-generic");