2 * The AEGIS-256 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 AEGIS256_NONCE_SIZE 32
26 #define AEGIS256_STATE_BLOCKS 6
27 #define AEGIS256_KEY_SIZE 32
28 #define AEGIS256_MIN_AUTH_SIZE 8
29 #define AEGIS256_MAX_AUTH_SIZE 16
32 union aegis_block blocks
[AEGIS256_STATE_BLOCKS
];
36 union aegis_block key
[AEGIS256_KEY_SIZE
/ AEGIS_BLOCK_SIZE
];
40 int (*skcipher_walk_init
)(struct skcipher_walk
*walk
,
41 struct aead_request
*req
, bool atomic
);
43 void (*crypt_chunk
)(struct aegis_state
*state
, u8
*dst
,
44 const u8
*src
, unsigned int size
);
47 static void crypto_aegis256_update(struct aegis_state
*state
)
49 union aegis_block tmp
;
52 tmp
= state
->blocks
[AEGIS256_STATE_BLOCKS
- 1];
53 for (i
= AEGIS256_STATE_BLOCKS
- 1; i
> 0; i
--)
54 crypto_aegis_aesenc(&state
->blocks
[i
], &state
->blocks
[i
- 1],
56 crypto_aegis_aesenc(&state
->blocks
[0], &tmp
, &state
->blocks
[0]);
59 static void crypto_aegis256_update_a(struct aegis_state
*state
,
60 const union aegis_block
*msg
)
62 crypto_aegis256_update(state
);
63 crypto_aegis_block_xor(&state
->blocks
[0], msg
);
66 static void crypto_aegis256_update_u(struct aegis_state
*state
, const void *msg
)
68 crypto_aegis256_update(state
);
69 crypto_xor(state
->blocks
[0].bytes
, msg
, AEGIS_BLOCK_SIZE
);
72 static void crypto_aegis256_init(struct aegis_state
*state
,
73 const union aegis_block
*key
,
76 union aegis_block key_iv
[2];
81 crypto_xor(key_iv
[0].bytes
, iv
+ 0 * AEGIS_BLOCK_SIZE
,
83 crypto_xor(key_iv
[1].bytes
, iv
+ 1 * AEGIS_BLOCK_SIZE
,
86 state
->blocks
[0] = key_iv
[0];
87 state
->blocks
[1] = key_iv
[1];
88 state
->blocks
[2] = crypto_aegis_const
[1];
89 state
->blocks
[3] = crypto_aegis_const
[0];
90 state
->blocks
[4] = key
[0];
91 state
->blocks
[5] = key
[1];
93 crypto_aegis_block_xor(&state
->blocks
[4], &crypto_aegis_const
[0]);
94 crypto_aegis_block_xor(&state
->blocks
[5], &crypto_aegis_const
[1]);
96 for (i
= 0; i
< 4; i
++) {
97 crypto_aegis256_update_a(state
, &key
[0]);
98 crypto_aegis256_update_a(state
, &key
[1]);
99 crypto_aegis256_update_a(state
, &key_iv
[0]);
100 crypto_aegis256_update_a(state
, &key_iv
[1]);
104 static void crypto_aegis256_ad(struct aegis_state
*state
,
105 const u8
*src
, unsigned int size
)
107 if (AEGIS_ALIGNED(src
)) {
108 const union aegis_block
*src_blk
=
109 (const union aegis_block
*)src
;
111 while (size
>= AEGIS_BLOCK_SIZE
) {
112 crypto_aegis256_update_a(state
, src_blk
);
114 size
-= AEGIS_BLOCK_SIZE
;
118 while (size
>= AEGIS_BLOCK_SIZE
) {
119 crypto_aegis256_update_u(state
, src
);
121 size
-= AEGIS_BLOCK_SIZE
;
122 src
+= AEGIS_BLOCK_SIZE
;
127 static void crypto_aegis256_encrypt_chunk(struct aegis_state
*state
, u8
*dst
,
128 const u8
*src
, unsigned int size
)
130 union aegis_block tmp
;
132 if (AEGIS_ALIGNED(src
) && AEGIS_ALIGNED(dst
)) {
133 while (size
>= AEGIS_BLOCK_SIZE
) {
134 union aegis_block
*dst_blk
=
135 (union aegis_block
*)dst
;
136 const union aegis_block
*src_blk
=
137 (const union aegis_block
*)src
;
139 tmp
= state
->blocks
[2];
140 crypto_aegis_block_and(&tmp
, &state
->blocks
[3]);
141 crypto_aegis_block_xor(&tmp
, &state
->blocks
[5]);
142 crypto_aegis_block_xor(&tmp
, &state
->blocks
[4]);
143 crypto_aegis_block_xor(&tmp
, &state
->blocks
[1]);
144 crypto_aegis_block_xor(&tmp
, src_blk
);
146 crypto_aegis256_update_a(state
, src_blk
);
150 size
-= AEGIS_BLOCK_SIZE
;
151 src
+= AEGIS_BLOCK_SIZE
;
152 dst
+= AEGIS_BLOCK_SIZE
;
155 while (size
>= AEGIS_BLOCK_SIZE
) {
156 tmp
= state
->blocks
[2];
157 crypto_aegis_block_and(&tmp
, &state
->blocks
[3]);
158 crypto_aegis_block_xor(&tmp
, &state
->blocks
[5]);
159 crypto_aegis_block_xor(&tmp
, &state
->blocks
[4]);
160 crypto_aegis_block_xor(&tmp
, &state
->blocks
[1]);
161 crypto_xor(tmp
.bytes
, src
, AEGIS_BLOCK_SIZE
);
163 crypto_aegis256_update_u(state
, src
);
165 memcpy(dst
, tmp
.bytes
, AEGIS_BLOCK_SIZE
);
167 size
-= AEGIS_BLOCK_SIZE
;
168 src
+= AEGIS_BLOCK_SIZE
;
169 dst
+= AEGIS_BLOCK_SIZE
;
174 union aegis_block msg
= {};
175 memcpy(msg
.bytes
, src
, size
);
177 tmp
= state
->blocks
[2];
178 crypto_aegis_block_and(&tmp
, &state
->blocks
[3]);
179 crypto_aegis_block_xor(&tmp
, &state
->blocks
[5]);
180 crypto_aegis_block_xor(&tmp
, &state
->blocks
[4]);
181 crypto_aegis_block_xor(&tmp
, &state
->blocks
[1]);
183 crypto_aegis256_update_a(state
, &msg
);
185 crypto_aegis_block_xor(&msg
, &tmp
);
187 memcpy(dst
, msg
.bytes
, size
);
191 static void crypto_aegis256_decrypt_chunk(struct aegis_state
*state
, u8
*dst
,
192 const u8
*src
, unsigned int size
)
194 union aegis_block tmp
;
196 if (AEGIS_ALIGNED(src
) && AEGIS_ALIGNED(dst
)) {
197 while (size
>= AEGIS_BLOCK_SIZE
) {
198 union aegis_block
*dst_blk
=
199 (union aegis_block
*)dst
;
200 const union aegis_block
*src_blk
=
201 (const union aegis_block
*)src
;
203 tmp
= state
->blocks
[2];
204 crypto_aegis_block_and(&tmp
, &state
->blocks
[3]);
205 crypto_aegis_block_xor(&tmp
, &state
->blocks
[5]);
206 crypto_aegis_block_xor(&tmp
, &state
->blocks
[4]);
207 crypto_aegis_block_xor(&tmp
, &state
->blocks
[1]);
208 crypto_aegis_block_xor(&tmp
, src_blk
);
210 crypto_aegis256_update_a(state
, &tmp
);
214 size
-= AEGIS_BLOCK_SIZE
;
215 src
+= AEGIS_BLOCK_SIZE
;
216 dst
+= AEGIS_BLOCK_SIZE
;
219 while (size
>= AEGIS_BLOCK_SIZE
) {
220 tmp
= state
->blocks
[2];
221 crypto_aegis_block_and(&tmp
, &state
->blocks
[3]);
222 crypto_aegis_block_xor(&tmp
, &state
->blocks
[5]);
223 crypto_aegis_block_xor(&tmp
, &state
->blocks
[4]);
224 crypto_aegis_block_xor(&tmp
, &state
->blocks
[1]);
225 crypto_xor(tmp
.bytes
, src
, AEGIS_BLOCK_SIZE
);
227 crypto_aegis256_update_a(state
, &tmp
);
229 memcpy(dst
, tmp
.bytes
, AEGIS_BLOCK_SIZE
);
231 size
-= AEGIS_BLOCK_SIZE
;
232 src
+= AEGIS_BLOCK_SIZE
;
233 dst
+= AEGIS_BLOCK_SIZE
;
238 union aegis_block msg
= {};
239 memcpy(msg
.bytes
, src
, size
);
241 tmp
= state
->blocks
[2];
242 crypto_aegis_block_and(&tmp
, &state
->blocks
[3]);
243 crypto_aegis_block_xor(&tmp
, &state
->blocks
[5]);
244 crypto_aegis_block_xor(&tmp
, &state
->blocks
[4]);
245 crypto_aegis_block_xor(&tmp
, &state
->blocks
[1]);
246 crypto_aegis_block_xor(&msg
, &tmp
);
248 memset(msg
.bytes
+ size
, 0, AEGIS_BLOCK_SIZE
- size
);
250 crypto_aegis256_update_a(state
, &msg
);
252 memcpy(dst
, msg
.bytes
, size
);
256 static void crypto_aegis256_process_ad(struct aegis_state
*state
,
257 struct scatterlist
*sg_src
,
258 unsigned int assoclen
)
260 struct scatter_walk walk
;
261 union aegis_block buf
;
262 unsigned int pos
= 0;
264 scatterwalk_start(&walk
, sg_src
);
265 while (assoclen
!= 0) {
266 unsigned int size
= scatterwalk_clamp(&walk
, assoclen
);
267 unsigned int left
= size
;
268 void *mapped
= scatterwalk_map(&walk
);
269 const u8
*src
= (const u8
*)mapped
;
271 if (pos
+ size
>= AEGIS_BLOCK_SIZE
) {
273 unsigned int fill
= AEGIS_BLOCK_SIZE
- pos
;
274 memcpy(buf
.bytes
+ pos
, src
, fill
);
275 crypto_aegis256_update_a(state
, &buf
);
281 crypto_aegis256_ad(state
, src
, left
);
282 src
+= left
& ~(AEGIS_BLOCK_SIZE
- 1);
283 left
&= AEGIS_BLOCK_SIZE
- 1;
286 memcpy(buf
.bytes
+ pos
, src
, left
);
290 scatterwalk_unmap(mapped
);
291 scatterwalk_advance(&walk
, size
);
292 scatterwalk_done(&walk
, 0, assoclen
);
296 memset(buf
.bytes
+ pos
, 0, AEGIS_BLOCK_SIZE
- pos
);
297 crypto_aegis256_update_a(state
, &buf
);
301 static void crypto_aegis256_process_crypt(struct aegis_state
*state
,
302 struct aead_request
*req
,
303 const struct aegis256_ops
*ops
)
305 struct skcipher_walk walk
;
307 ops
->skcipher_walk_init(&walk
, req
, false);
309 while (walk
.nbytes
) {
310 unsigned int nbytes
= walk
.nbytes
;
312 if (nbytes
< walk
.total
)
313 nbytes
= round_down(nbytes
, walk
.stride
);
315 ops
->crypt_chunk(state
, walk
.dst
.virt
.addr
, walk
.src
.virt
.addr
,
318 skcipher_walk_done(&walk
, walk
.nbytes
- nbytes
);
322 static void crypto_aegis256_final(struct aegis_state
*state
,
323 union aegis_block
*tag_xor
,
324 u64 assoclen
, u64 cryptlen
)
326 u64 assocbits
= assoclen
* 8;
327 u64 cryptbits
= cryptlen
* 8;
329 union aegis_block tmp
;
332 tmp
.words64
[0] = cpu_to_le64(assocbits
);
333 tmp
.words64
[1] = cpu_to_le64(cryptbits
);
335 crypto_aegis_block_xor(&tmp
, &state
->blocks
[3]);
337 for (i
= 0; i
< 7; i
++)
338 crypto_aegis256_update_a(state
, &tmp
);
340 for (i
= 0; i
< AEGIS256_STATE_BLOCKS
; i
++)
341 crypto_aegis_block_xor(tag_xor
, &state
->blocks
[i
]);
344 static int crypto_aegis256_setkey(struct crypto_aead
*aead
, const u8
*key
,
347 struct aegis_ctx
*ctx
= crypto_aead_ctx(aead
);
349 if (keylen
!= AEGIS256_KEY_SIZE
) {
350 crypto_aead_set_flags(aead
, CRYPTO_TFM_RES_BAD_KEY_LEN
);
354 memcpy(ctx
->key
[0].bytes
, key
, AEGIS_BLOCK_SIZE
);
355 memcpy(ctx
->key
[1].bytes
, key
+ AEGIS_BLOCK_SIZE
,
360 static int crypto_aegis256_setauthsize(struct crypto_aead
*tfm
,
361 unsigned int authsize
)
363 if (authsize
> AEGIS256_MAX_AUTH_SIZE
)
365 if (authsize
< AEGIS256_MIN_AUTH_SIZE
)
370 static void crypto_aegis256_crypt(struct aead_request
*req
,
371 union aegis_block
*tag_xor
,
372 unsigned int cryptlen
,
373 const struct aegis256_ops
*ops
)
375 struct crypto_aead
*tfm
= crypto_aead_reqtfm(req
);
376 struct aegis_ctx
*ctx
= crypto_aead_ctx(tfm
);
377 struct aegis_state state
;
379 crypto_aegis256_init(&state
, ctx
->key
, req
->iv
);
380 crypto_aegis256_process_ad(&state
, req
->src
, req
->assoclen
);
381 crypto_aegis256_process_crypt(&state
, req
, ops
);
382 crypto_aegis256_final(&state
, tag_xor
, req
->assoclen
, cryptlen
);
385 static int crypto_aegis256_encrypt(struct aead_request
*req
)
387 static const struct aegis256_ops ops
= {
388 .skcipher_walk_init
= skcipher_walk_aead_encrypt
,
389 .crypt_chunk
= crypto_aegis256_encrypt_chunk
,
392 struct crypto_aead
*tfm
= crypto_aead_reqtfm(req
);
393 union aegis_block tag
= {};
394 unsigned int authsize
= crypto_aead_authsize(tfm
);
395 unsigned int cryptlen
= req
->cryptlen
;
397 crypto_aegis256_crypt(req
, &tag
, cryptlen
, &ops
);
399 scatterwalk_map_and_copy(tag
.bytes
, req
->dst
, req
->assoclen
+ cryptlen
,
404 static int crypto_aegis256_decrypt(struct aead_request
*req
)
406 static const struct aegis256_ops ops
= {
407 .skcipher_walk_init
= skcipher_walk_aead_decrypt
,
408 .crypt_chunk
= crypto_aegis256_decrypt_chunk
,
410 static const u8 zeros
[AEGIS256_MAX_AUTH_SIZE
] = {};
412 struct crypto_aead
*tfm
= crypto_aead_reqtfm(req
);
413 union aegis_block tag
;
414 unsigned int authsize
= crypto_aead_authsize(tfm
);
415 unsigned int cryptlen
= req
->cryptlen
- authsize
;
417 scatterwalk_map_and_copy(tag
.bytes
, req
->src
, req
->assoclen
+ cryptlen
,
420 crypto_aegis256_crypt(req
, &tag
, cryptlen
, &ops
);
422 return crypto_memneq(tag
.bytes
, zeros
, authsize
) ? -EBADMSG
: 0;
425 static int crypto_aegis256_init_tfm(struct crypto_aead
*tfm
)
430 static void crypto_aegis256_exit_tfm(struct crypto_aead
*tfm
)
434 static struct aead_alg crypto_aegis256_alg
= {
435 .setkey
= crypto_aegis256_setkey
,
436 .setauthsize
= crypto_aegis256_setauthsize
,
437 .encrypt
= crypto_aegis256_encrypt
,
438 .decrypt
= crypto_aegis256_decrypt
,
439 .init
= crypto_aegis256_init_tfm
,
440 .exit
= crypto_aegis256_exit_tfm
,
442 .ivsize
= AEGIS256_NONCE_SIZE
,
443 .maxauthsize
= AEGIS256_MAX_AUTH_SIZE
,
444 .chunksize
= AEGIS_BLOCK_SIZE
,
448 .cra_ctxsize
= sizeof(struct aegis_ctx
),
453 .cra_name
= "aegis256",
454 .cra_driver_name
= "aegis256-generic",
456 .cra_module
= THIS_MODULE
,
460 static int __init
crypto_aegis256_module_init(void)
462 return crypto_register_aead(&crypto_aegis256_alg
);
465 static void __exit
crypto_aegis256_module_exit(void)
467 crypto_unregister_aead(&crypto_aegis256_alg
);
470 module_init(crypto_aegis256_module_init
);
471 module_exit(crypto_aegis256_module_exit
);
473 MODULE_LICENSE("GPL");
474 MODULE_AUTHOR("Ondrej Mosnacek <omosnacek@gmail.com>");
475 MODULE_DESCRIPTION("AEGIS-256 AEAD algorithm");
476 MODULE_ALIAS_CRYPTO("aegis256");
477 MODULE_ALIAS_CRYPTO("aegis256-generic");