1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * The MORUS-640 Authenticated-Encryption Algorithm
5 * Copyright (c) 2016-2018 Ondrej Mosnacek <omosnacek@gmail.com>
6 * Copyright (C) 2017-2018 Red Hat, Inc. All rights reserved.
9 #include <asm/unaligned.h>
10 #include <crypto/algapi.h>
11 #include <crypto/internal/aead.h>
12 #include <crypto/internal/skcipher.h>
13 #include <crypto/morus_common.h>
14 #include <crypto/scatterwalk.h>
15 #include <linux/err.h>
16 #include <linux/init.h>
17 #include <linux/kernel.h>
18 #include <linux/module.h>
19 #include <linux/scatterlist.h>
21 #define MORUS640_WORD_SIZE 4
22 #define MORUS640_BLOCK_SIZE (MORUS_BLOCK_WORDS * MORUS640_WORD_SIZE)
23 #define MORUS640_BLOCK_ALIGN (__alignof__(__le32))
24 #define MORUS640_ALIGNED(p) IS_ALIGNED((uintptr_t)p, MORUS640_BLOCK_ALIGN)
26 struct morus640_block
{
27 u32 words
[MORUS_BLOCK_WORDS
];
30 union morus640_block_in
{
31 __le32 words
[MORUS_BLOCK_WORDS
];
32 u8 bytes
[MORUS640_BLOCK_SIZE
];
35 struct morus640_state
{
36 struct morus640_block s
[MORUS_STATE_BLOCKS
];
40 struct morus640_block key
;
44 int (*skcipher_walk_init
)(struct skcipher_walk
*walk
,
45 struct aead_request
*req
, bool atomic
);
47 void (*crypt_chunk
)(struct morus640_state
*state
,
48 u8
*dst
, const u8
*src
, unsigned int size
);
51 static const struct morus640_block crypto_morus640_const
[2] = {
66 static void crypto_morus640_round(struct morus640_block
*b0
,
67 struct morus640_block
*b1
,
68 struct morus640_block
*b2
,
69 struct morus640_block
*b3
,
70 struct morus640_block
*b4
,
71 const struct morus640_block
*m
,
72 unsigned int b
, unsigned int w
)
75 struct morus640_block tmp
;
77 for (i
= 0; i
< MORUS_BLOCK_WORDS
; i
++) {
78 b0
->words
[i
] ^= b1
->words
[i
] & b2
->words
[i
];
79 b0
->words
[i
] ^= b3
->words
[i
];
80 b0
->words
[i
] ^= m
->words
[i
];
81 b0
->words
[i
] = rol32(b0
->words
[i
], b
);
85 for (i
= 0; i
< MORUS_BLOCK_WORDS
; i
++)
86 b3
->words
[(i
+ w
) % MORUS_BLOCK_WORDS
] = tmp
.words
[i
];
89 static void crypto_morus640_update(struct morus640_state
*state
,
90 const struct morus640_block
*m
)
92 static const struct morus640_block z
= {};
94 struct morus640_block
*s
= state
->s
;
96 crypto_morus640_round(&s
[0], &s
[1], &s
[2], &s
[3], &s
[4], &z
, 5, 1);
97 crypto_morus640_round(&s
[1], &s
[2], &s
[3], &s
[4], &s
[0], m
, 31, 2);
98 crypto_morus640_round(&s
[2], &s
[3], &s
[4], &s
[0], &s
[1], m
, 7, 3);
99 crypto_morus640_round(&s
[3], &s
[4], &s
[0], &s
[1], &s
[2], m
, 22, 2);
100 crypto_morus640_round(&s
[4], &s
[0], &s
[1], &s
[2], &s
[3], m
, 13, 1);
103 static void crypto_morus640_load_a(struct morus640_block
*dst
, const u8
*src
)
106 for (i
= 0; i
< MORUS_BLOCK_WORDS
; i
++) {
107 dst
->words
[i
] = le32_to_cpu(*(const __le32
*)src
);
108 src
+= MORUS640_WORD_SIZE
;
112 static void crypto_morus640_load_u(struct morus640_block
*dst
, const u8
*src
)
115 for (i
= 0; i
< MORUS_BLOCK_WORDS
; i
++) {
116 dst
->words
[i
] = get_unaligned_le32(src
);
117 src
+= MORUS640_WORD_SIZE
;
121 static void crypto_morus640_load(struct morus640_block
*dst
, const u8
*src
)
123 if (MORUS640_ALIGNED(src
))
124 crypto_morus640_load_a(dst
, src
);
126 crypto_morus640_load_u(dst
, src
);
129 static void crypto_morus640_store_a(u8
*dst
, const struct morus640_block
*src
)
132 for (i
= 0; i
< MORUS_BLOCK_WORDS
; i
++) {
133 *(__le32
*)dst
= cpu_to_le32(src
->words
[i
]);
134 dst
+= MORUS640_WORD_SIZE
;
138 static void crypto_morus640_store_u(u8
*dst
, const struct morus640_block
*src
)
141 for (i
= 0; i
< MORUS_BLOCK_WORDS
; i
++) {
142 put_unaligned_le32(src
->words
[i
], dst
);
143 dst
+= MORUS640_WORD_SIZE
;
147 static void crypto_morus640_store(u8
*dst
, const struct morus640_block
*src
)
149 if (MORUS640_ALIGNED(dst
))
150 crypto_morus640_store_a(dst
, src
);
152 crypto_morus640_store_u(dst
, src
);
155 static void crypto_morus640_ad(struct morus640_state
*state
, const u8
*src
,
158 struct morus640_block m
;
160 if (MORUS640_ALIGNED(src
)) {
161 while (size
>= MORUS640_BLOCK_SIZE
) {
162 crypto_morus640_load_a(&m
, src
);
163 crypto_morus640_update(state
, &m
);
165 size
-= MORUS640_BLOCK_SIZE
;
166 src
+= MORUS640_BLOCK_SIZE
;
169 while (size
>= MORUS640_BLOCK_SIZE
) {
170 crypto_morus640_load_u(&m
, src
);
171 crypto_morus640_update(state
, &m
);
173 size
-= MORUS640_BLOCK_SIZE
;
174 src
+= MORUS640_BLOCK_SIZE
;
179 static void crypto_morus640_core(const struct morus640_state
*state
,
180 struct morus640_block
*blk
)
184 for (i
= 0; i
< MORUS_BLOCK_WORDS
; i
++)
185 blk
->words
[(i
+ 3) % MORUS_BLOCK_WORDS
] ^= state
->s
[1].words
[i
];
187 for (i
= 0; i
< MORUS_BLOCK_WORDS
; i
++) {
188 blk
->words
[i
] ^= state
->s
[0].words
[i
];
189 blk
->words
[i
] ^= state
->s
[2].words
[i
] & state
->s
[3].words
[i
];
193 static void crypto_morus640_encrypt_chunk(struct morus640_state
*state
, u8
*dst
,
194 const u8
*src
, unsigned int size
)
196 struct morus640_block c
, m
;
198 if (MORUS640_ALIGNED(src
) && MORUS640_ALIGNED(dst
)) {
199 while (size
>= MORUS640_BLOCK_SIZE
) {
200 crypto_morus640_load_a(&m
, src
);
202 crypto_morus640_core(state
, &c
);
203 crypto_morus640_store_a(dst
, &c
);
204 crypto_morus640_update(state
, &m
);
206 src
+= MORUS640_BLOCK_SIZE
;
207 dst
+= MORUS640_BLOCK_SIZE
;
208 size
-= MORUS640_BLOCK_SIZE
;
211 while (size
>= MORUS640_BLOCK_SIZE
) {
212 crypto_morus640_load_u(&m
, src
);
214 crypto_morus640_core(state
, &c
);
215 crypto_morus640_store_u(dst
, &c
);
216 crypto_morus640_update(state
, &m
);
218 src
+= MORUS640_BLOCK_SIZE
;
219 dst
+= MORUS640_BLOCK_SIZE
;
220 size
-= MORUS640_BLOCK_SIZE
;
225 union morus640_block_in tail
;
227 memcpy(tail
.bytes
, src
, size
);
228 memset(tail
.bytes
+ size
, 0, MORUS640_BLOCK_SIZE
- size
);
230 crypto_morus640_load_a(&m
, tail
.bytes
);
232 crypto_morus640_core(state
, &c
);
233 crypto_morus640_store_a(tail
.bytes
, &c
);
234 crypto_morus640_update(state
, &m
);
236 memcpy(dst
, tail
.bytes
, size
);
240 static void crypto_morus640_decrypt_chunk(struct morus640_state
*state
, u8
*dst
,
241 const u8
*src
, unsigned int size
)
243 struct morus640_block m
;
245 if (MORUS640_ALIGNED(src
) && MORUS640_ALIGNED(dst
)) {
246 while (size
>= MORUS640_BLOCK_SIZE
) {
247 crypto_morus640_load_a(&m
, src
);
248 crypto_morus640_core(state
, &m
);
249 crypto_morus640_store_a(dst
, &m
);
250 crypto_morus640_update(state
, &m
);
252 src
+= MORUS640_BLOCK_SIZE
;
253 dst
+= MORUS640_BLOCK_SIZE
;
254 size
-= MORUS640_BLOCK_SIZE
;
257 while (size
>= MORUS640_BLOCK_SIZE
) {
258 crypto_morus640_load_u(&m
, src
);
259 crypto_morus640_core(state
, &m
);
260 crypto_morus640_store_u(dst
, &m
);
261 crypto_morus640_update(state
, &m
);
263 src
+= MORUS640_BLOCK_SIZE
;
264 dst
+= MORUS640_BLOCK_SIZE
;
265 size
-= MORUS640_BLOCK_SIZE
;
270 union morus640_block_in tail
;
272 memcpy(tail
.bytes
, src
, size
);
273 memset(tail
.bytes
+ size
, 0, MORUS640_BLOCK_SIZE
- size
);
275 crypto_morus640_load_a(&m
, tail
.bytes
);
276 crypto_morus640_core(state
, &m
);
277 crypto_morus640_store_a(tail
.bytes
, &m
);
278 memset(tail
.bytes
+ size
, 0, MORUS640_BLOCK_SIZE
- size
);
279 crypto_morus640_load_a(&m
, tail
.bytes
);
280 crypto_morus640_update(state
, &m
);
282 memcpy(dst
, tail
.bytes
, size
);
286 static void crypto_morus640_init(struct morus640_state
*state
,
287 const struct morus640_block
*key
,
290 static const struct morus640_block z
= {};
294 crypto_morus640_load(&state
->s
[0], iv
);
296 for (i
= 0; i
< MORUS_BLOCK_WORDS
; i
++)
297 state
->s
[2].words
[i
] = U32_C(0xFFFFFFFF);
298 state
->s
[3] = crypto_morus640_const
[0];
299 state
->s
[4] = crypto_morus640_const
[1];
301 for (i
= 0; i
< 16; i
++)
302 crypto_morus640_update(state
, &z
);
304 for (i
= 0; i
< MORUS_BLOCK_WORDS
; i
++)
305 state
->s
[1].words
[i
] ^= key
->words
[i
];
308 static void crypto_morus640_process_ad(struct morus640_state
*state
,
309 struct scatterlist
*sg_src
,
310 unsigned int assoclen
)
312 struct scatter_walk walk
;
313 struct morus640_block m
;
314 union morus640_block_in buf
;
315 unsigned int pos
= 0;
317 scatterwalk_start(&walk
, sg_src
);
318 while (assoclen
!= 0) {
319 unsigned int size
= scatterwalk_clamp(&walk
, assoclen
);
320 unsigned int left
= size
;
321 void *mapped
= scatterwalk_map(&walk
);
322 const u8
*src
= (const u8
*)mapped
;
324 if (pos
+ size
>= MORUS640_BLOCK_SIZE
) {
326 unsigned int fill
= MORUS640_BLOCK_SIZE
- pos
;
327 memcpy(buf
.bytes
+ pos
, src
, fill
);
329 crypto_morus640_load_a(&m
, buf
.bytes
);
330 crypto_morus640_update(state
, &m
);
337 crypto_morus640_ad(state
, src
, left
);
338 src
+= left
& ~(MORUS640_BLOCK_SIZE
- 1);
339 left
&= MORUS640_BLOCK_SIZE
- 1;
342 memcpy(buf
.bytes
+ pos
, src
, left
);
346 scatterwalk_unmap(mapped
);
347 scatterwalk_advance(&walk
, size
);
348 scatterwalk_done(&walk
, 0, assoclen
);
352 memset(buf
.bytes
+ pos
, 0, MORUS640_BLOCK_SIZE
- pos
);
354 crypto_morus640_load_a(&m
, buf
.bytes
);
355 crypto_morus640_update(state
, &m
);
359 static void crypto_morus640_process_crypt(struct morus640_state
*state
,
360 struct aead_request
*req
,
361 const struct morus640_ops
*ops
)
363 struct skcipher_walk walk
;
365 ops
->skcipher_walk_init(&walk
, req
, false);
367 while (walk
.nbytes
) {
368 unsigned int nbytes
= walk
.nbytes
;
370 if (nbytes
< walk
.total
)
371 nbytes
= round_down(nbytes
, walk
.stride
);
373 ops
->crypt_chunk(state
, walk
.dst
.virt
.addr
, walk
.src
.virt
.addr
,
376 skcipher_walk_done(&walk
, walk
.nbytes
- nbytes
);
380 static void crypto_morus640_final(struct morus640_state
*state
,
381 struct morus640_block
*tag_xor
,
382 u64 assoclen
, u64 cryptlen
)
384 struct morus640_block tmp
;
387 tmp
.words
[0] = lower_32_bits(assoclen
* 8);
388 tmp
.words
[1] = upper_32_bits(assoclen
* 8);
389 tmp
.words
[2] = lower_32_bits(cryptlen
* 8);
390 tmp
.words
[3] = upper_32_bits(cryptlen
* 8);
392 for (i
= 0; i
< MORUS_BLOCK_WORDS
; i
++)
393 state
->s
[4].words
[i
] ^= state
->s
[0].words
[i
];
395 for (i
= 0; i
< 10; i
++)
396 crypto_morus640_update(state
, &tmp
);
398 crypto_morus640_core(state
, tag_xor
);
401 static int crypto_morus640_setkey(struct crypto_aead
*aead
, const u8
*key
,
404 struct morus640_ctx
*ctx
= crypto_aead_ctx(aead
);
406 if (keylen
!= MORUS640_BLOCK_SIZE
) {
407 crypto_aead_set_flags(aead
, CRYPTO_TFM_RES_BAD_KEY_LEN
);
411 crypto_morus640_load(&ctx
->key
, key
);
415 static int crypto_morus640_setauthsize(struct crypto_aead
*tfm
,
416 unsigned int authsize
)
418 return (authsize
<= MORUS_MAX_AUTH_SIZE
) ? 0 : -EINVAL
;
421 static void crypto_morus640_crypt(struct aead_request
*req
,
422 struct morus640_block
*tag_xor
,
423 unsigned int cryptlen
,
424 const struct morus640_ops
*ops
)
426 struct crypto_aead
*tfm
= crypto_aead_reqtfm(req
);
427 struct morus640_ctx
*ctx
= crypto_aead_ctx(tfm
);
428 struct morus640_state state
;
430 crypto_morus640_init(&state
, &ctx
->key
, req
->iv
);
431 crypto_morus640_process_ad(&state
, req
->src
, req
->assoclen
);
432 crypto_morus640_process_crypt(&state
, req
, ops
);
433 crypto_morus640_final(&state
, tag_xor
, req
->assoclen
, cryptlen
);
436 static int crypto_morus640_encrypt(struct aead_request
*req
)
438 static const struct morus640_ops ops
= {
439 .skcipher_walk_init
= skcipher_walk_aead_encrypt
,
440 .crypt_chunk
= crypto_morus640_encrypt_chunk
,
443 struct crypto_aead
*tfm
= crypto_aead_reqtfm(req
);
444 struct morus640_block tag
= {};
445 union morus640_block_in tag_out
;
446 unsigned int authsize
= crypto_aead_authsize(tfm
);
447 unsigned int cryptlen
= req
->cryptlen
;
449 crypto_morus640_crypt(req
, &tag
, cryptlen
, &ops
);
450 crypto_morus640_store(tag_out
.bytes
, &tag
);
452 scatterwalk_map_and_copy(tag_out
.bytes
, req
->dst
,
453 req
->assoclen
+ cryptlen
, authsize
, 1);
457 static int crypto_morus640_decrypt(struct aead_request
*req
)
459 static const struct morus640_ops ops
= {
460 .skcipher_walk_init
= skcipher_walk_aead_decrypt
,
461 .crypt_chunk
= crypto_morus640_decrypt_chunk
,
463 static const u8 zeros
[MORUS640_BLOCK_SIZE
] = {};
465 struct crypto_aead
*tfm
= crypto_aead_reqtfm(req
);
466 union morus640_block_in tag_in
;
467 struct morus640_block tag
;
468 unsigned int authsize
= crypto_aead_authsize(tfm
);
469 unsigned int cryptlen
= req
->cryptlen
- authsize
;
471 scatterwalk_map_and_copy(tag_in
.bytes
, req
->src
,
472 req
->assoclen
+ cryptlen
, authsize
, 0);
474 crypto_morus640_load(&tag
, tag_in
.bytes
);
475 crypto_morus640_crypt(req
, &tag
, cryptlen
, &ops
);
476 crypto_morus640_store(tag_in
.bytes
, &tag
);
478 return crypto_memneq(tag_in
.bytes
, zeros
, authsize
) ? -EBADMSG
: 0;
481 static int crypto_morus640_init_tfm(struct crypto_aead
*tfm
)
486 static void crypto_morus640_exit_tfm(struct crypto_aead
*tfm
)
490 static struct aead_alg crypto_morus640_alg
= {
491 .setkey
= crypto_morus640_setkey
,
492 .setauthsize
= crypto_morus640_setauthsize
,
493 .encrypt
= crypto_morus640_encrypt
,
494 .decrypt
= crypto_morus640_decrypt
,
495 .init
= crypto_morus640_init_tfm
,
496 .exit
= crypto_morus640_exit_tfm
,
498 .ivsize
= MORUS_NONCE_SIZE
,
499 .maxauthsize
= MORUS_MAX_AUTH_SIZE
,
500 .chunksize
= MORUS640_BLOCK_SIZE
,
504 .cra_ctxsize
= sizeof(struct morus640_ctx
),
509 .cra_name
= "morus640",
510 .cra_driver_name
= "morus640-generic",
512 .cra_module
= THIS_MODULE
,
516 static int __init
crypto_morus640_module_init(void)
518 return crypto_register_aead(&crypto_morus640_alg
);
521 static void __exit
crypto_morus640_module_exit(void)
523 crypto_unregister_aead(&crypto_morus640_alg
);
526 subsys_initcall(crypto_morus640_module_init
);
527 module_exit(crypto_morus640_module_exit
);
529 MODULE_LICENSE("GPL");
530 MODULE_AUTHOR("Ondrej Mosnacek <omosnacek@gmail.com>");
531 MODULE_DESCRIPTION("MORUS-640 AEAD algorithm");
532 MODULE_ALIAS_CRYPTO("morus640");
533 MODULE_ALIAS_CRYPTO("morus640-generic");