2 * The MORUS-640 Authenticated-Encryption Algorithm
4 * Copyright (c) 2016-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 <asm/unaligned.h>
14 #include <crypto/algapi.h>
15 #include <crypto/internal/aead.h>
16 #include <crypto/internal/skcipher.h>
17 #include <crypto/morus_common.h>
18 #include <crypto/scatterwalk.h>
19 #include <linux/err.h>
20 #include <linux/init.h>
21 #include <linux/kernel.h>
22 #include <linux/module.h>
23 #include <linux/scatterlist.h>
25 #define MORUS640_WORD_SIZE 4
26 #define MORUS640_BLOCK_SIZE (MORUS_BLOCK_WORDS * MORUS640_WORD_SIZE)
27 #define MORUS640_BLOCK_ALIGN (__alignof__(__le32))
28 #define MORUS640_ALIGNED(p) IS_ALIGNED((uintptr_t)p, MORUS640_BLOCK_ALIGN)
30 struct morus640_block
{
31 u32 words
[MORUS_BLOCK_WORDS
];
34 union morus640_block_in
{
35 __le32 words
[MORUS_BLOCK_WORDS
];
36 u8 bytes
[MORUS640_BLOCK_SIZE
];
39 struct morus640_state
{
40 struct morus640_block s
[MORUS_STATE_BLOCKS
];
44 struct morus640_block key
;
48 int (*skcipher_walk_init
)(struct skcipher_walk
*walk
,
49 struct aead_request
*req
, bool atomic
);
51 void (*crypt_chunk
)(struct morus640_state
*state
,
52 u8
*dst
, const u8
*src
, unsigned int size
);
55 static const struct morus640_block crypto_morus640_const
[2] = {
70 static void crypto_morus640_round(struct morus640_block
*b0
,
71 struct morus640_block
*b1
,
72 struct morus640_block
*b2
,
73 struct morus640_block
*b3
,
74 struct morus640_block
*b4
,
75 const struct morus640_block
*m
,
76 unsigned int b
, unsigned int w
)
79 struct morus640_block tmp
;
81 for (i
= 0; i
< MORUS_BLOCK_WORDS
; i
++) {
82 b0
->words
[i
] ^= b1
->words
[i
] & b2
->words
[i
];
83 b0
->words
[i
] ^= b3
->words
[i
];
84 b0
->words
[i
] ^= m
->words
[i
];
85 b0
->words
[i
] = rol32(b0
->words
[i
], b
);
89 for (i
= 0; i
< MORUS_BLOCK_WORDS
; i
++)
90 b3
->words
[(i
+ w
) % MORUS_BLOCK_WORDS
] = tmp
.words
[i
];
93 static void crypto_morus640_update(struct morus640_state
*state
,
94 const struct morus640_block
*m
)
96 static const struct morus640_block z
= {};
98 struct morus640_block
*s
= state
->s
;
100 crypto_morus640_round(&s
[0], &s
[1], &s
[2], &s
[3], &s
[4], &z
, 5, 1);
101 crypto_morus640_round(&s
[1], &s
[2], &s
[3], &s
[4], &s
[0], m
, 31, 2);
102 crypto_morus640_round(&s
[2], &s
[3], &s
[4], &s
[0], &s
[1], m
, 7, 3);
103 crypto_morus640_round(&s
[3], &s
[4], &s
[0], &s
[1], &s
[2], m
, 22, 2);
104 crypto_morus640_round(&s
[4], &s
[0], &s
[1], &s
[2], &s
[3], m
, 13, 1);
107 static void crypto_morus640_load_a(struct morus640_block
*dst
, const u8
*src
)
110 for (i
= 0; i
< MORUS_BLOCK_WORDS
; i
++) {
111 dst
->words
[i
] = le32_to_cpu(*(const __le32
*)src
);
112 src
+= MORUS640_WORD_SIZE
;
116 static void crypto_morus640_load_u(struct morus640_block
*dst
, const u8
*src
)
119 for (i
= 0; i
< MORUS_BLOCK_WORDS
; i
++) {
120 dst
->words
[i
] = get_unaligned_le32(src
);
121 src
+= MORUS640_WORD_SIZE
;
125 static void crypto_morus640_load(struct morus640_block
*dst
, const u8
*src
)
127 if (MORUS640_ALIGNED(src
))
128 crypto_morus640_load_a(dst
, src
);
130 crypto_morus640_load_u(dst
, src
);
133 static void crypto_morus640_store_a(u8
*dst
, const struct morus640_block
*src
)
136 for (i
= 0; i
< MORUS_BLOCK_WORDS
; i
++) {
137 *(__le32
*)dst
= cpu_to_le32(src
->words
[i
]);
138 dst
+= MORUS640_WORD_SIZE
;
142 static void crypto_morus640_store_u(u8
*dst
, const struct morus640_block
*src
)
145 for (i
= 0; i
< MORUS_BLOCK_WORDS
; i
++) {
146 put_unaligned_le32(src
->words
[i
], dst
);
147 dst
+= MORUS640_WORD_SIZE
;
151 static void crypto_morus640_store(u8
*dst
, const struct morus640_block
*src
)
153 if (MORUS640_ALIGNED(dst
))
154 crypto_morus640_store_a(dst
, src
);
156 crypto_morus640_store_u(dst
, src
);
159 static void crypto_morus640_ad(struct morus640_state
*state
, const u8
*src
,
162 struct morus640_block m
;
164 if (MORUS640_ALIGNED(src
)) {
165 while (size
>= MORUS640_BLOCK_SIZE
) {
166 crypto_morus640_load_a(&m
, src
);
167 crypto_morus640_update(state
, &m
);
169 size
-= MORUS640_BLOCK_SIZE
;
170 src
+= MORUS640_BLOCK_SIZE
;
173 while (size
>= MORUS640_BLOCK_SIZE
) {
174 crypto_morus640_load_u(&m
, src
);
175 crypto_morus640_update(state
, &m
);
177 size
-= MORUS640_BLOCK_SIZE
;
178 src
+= MORUS640_BLOCK_SIZE
;
183 static void crypto_morus640_core(const struct morus640_state
*state
,
184 struct morus640_block
*blk
)
188 for (i
= 0; i
< MORUS_BLOCK_WORDS
; i
++)
189 blk
->words
[(i
+ 3) % MORUS_BLOCK_WORDS
] ^= state
->s
[1].words
[i
];
191 for (i
= 0; i
< MORUS_BLOCK_WORDS
; i
++) {
192 blk
->words
[i
] ^= state
->s
[0].words
[i
];
193 blk
->words
[i
] ^= state
->s
[2].words
[i
] & state
->s
[3].words
[i
];
197 static void crypto_morus640_encrypt_chunk(struct morus640_state
*state
, u8
*dst
,
198 const u8
*src
, unsigned int size
)
200 struct morus640_block c
, m
;
202 if (MORUS640_ALIGNED(src
) && MORUS640_ALIGNED(dst
)) {
203 while (size
>= MORUS640_BLOCK_SIZE
) {
204 crypto_morus640_load_a(&m
, src
);
206 crypto_morus640_core(state
, &c
);
207 crypto_morus640_store_a(dst
, &c
);
208 crypto_morus640_update(state
, &m
);
210 src
+= MORUS640_BLOCK_SIZE
;
211 dst
+= MORUS640_BLOCK_SIZE
;
212 size
-= MORUS640_BLOCK_SIZE
;
215 while (size
>= MORUS640_BLOCK_SIZE
) {
216 crypto_morus640_load_u(&m
, src
);
218 crypto_morus640_core(state
, &c
);
219 crypto_morus640_store_u(dst
, &c
);
220 crypto_morus640_update(state
, &m
);
222 src
+= MORUS640_BLOCK_SIZE
;
223 dst
+= MORUS640_BLOCK_SIZE
;
224 size
-= MORUS640_BLOCK_SIZE
;
229 union morus640_block_in tail
;
231 memcpy(tail
.bytes
, src
, size
);
232 memset(tail
.bytes
+ size
, 0, MORUS640_BLOCK_SIZE
- size
);
234 crypto_morus640_load_a(&m
, tail
.bytes
);
236 crypto_morus640_core(state
, &c
);
237 crypto_morus640_store_a(tail
.bytes
, &c
);
238 crypto_morus640_update(state
, &m
);
240 memcpy(dst
, tail
.bytes
, size
);
244 static void crypto_morus640_decrypt_chunk(struct morus640_state
*state
, u8
*dst
,
245 const u8
*src
, unsigned int size
)
247 struct morus640_block m
;
249 if (MORUS640_ALIGNED(src
) && MORUS640_ALIGNED(dst
)) {
250 while (size
>= MORUS640_BLOCK_SIZE
) {
251 crypto_morus640_load_a(&m
, src
);
252 crypto_morus640_core(state
, &m
);
253 crypto_morus640_store_a(dst
, &m
);
254 crypto_morus640_update(state
, &m
);
256 src
+= MORUS640_BLOCK_SIZE
;
257 dst
+= MORUS640_BLOCK_SIZE
;
258 size
-= MORUS640_BLOCK_SIZE
;
261 while (size
>= MORUS640_BLOCK_SIZE
) {
262 crypto_morus640_load_u(&m
, src
);
263 crypto_morus640_core(state
, &m
);
264 crypto_morus640_store_u(dst
, &m
);
265 crypto_morus640_update(state
, &m
);
267 src
+= MORUS640_BLOCK_SIZE
;
268 dst
+= MORUS640_BLOCK_SIZE
;
269 size
-= MORUS640_BLOCK_SIZE
;
274 union morus640_block_in tail
;
276 memcpy(tail
.bytes
, src
, size
);
277 memset(tail
.bytes
+ size
, 0, MORUS640_BLOCK_SIZE
- size
);
279 crypto_morus640_load_a(&m
, tail
.bytes
);
280 crypto_morus640_core(state
, &m
);
281 crypto_morus640_store_a(tail
.bytes
, &m
);
282 memset(tail
.bytes
+ size
, 0, MORUS640_BLOCK_SIZE
- size
);
283 crypto_morus640_load_a(&m
, tail
.bytes
);
284 crypto_morus640_update(state
, &m
);
286 memcpy(dst
, tail
.bytes
, size
);
290 static void crypto_morus640_init(struct morus640_state
*state
,
291 const struct morus640_block
*key
,
294 static const struct morus640_block z
= {};
298 crypto_morus640_load(&state
->s
[0], iv
);
300 for (i
= 0; i
< MORUS_BLOCK_WORDS
; i
++)
301 state
->s
[2].words
[i
] = U32_C(0xFFFFFFFF);
302 state
->s
[3] = crypto_morus640_const
[0];
303 state
->s
[4] = crypto_morus640_const
[1];
305 for (i
= 0; i
< 16; i
++)
306 crypto_morus640_update(state
, &z
);
308 for (i
= 0; i
< MORUS_BLOCK_WORDS
; i
++)
309 state
->s
[1].words
[i
] ^= key
->words
[i
];
312 static void crypto_morus640_process_ad(struct morus640_state
*state
,
313 struct scatterlist
*sg_src
,
314 unsigned int assoclen
)
316 struct scatter_walk walk
;
317 struct morus640_block m
;
318 union morus640_block_in buf
;
319 unsigned int pos
= 0;
321 scatterwalk_start(&walk
, sg_src
);
322 while (assoclen
!= 0) {
323 unsigned int size
= scatterwalk_clamp(&walk
, assoclen
);
324 unsigned int left
= size
;
325 void *mapped
= scatterwalk_map(&walk
);
326 const u8
*src
= (const u8
*)mapped
;
328 if (pos
+ size
>= MORUS640_BLOCK_SIZE
) {
330 unsigned int fill
= MORUS640_BLOCK_SIZE
- pos
;
331 memcpy(buf
.bytes
+ pos
, src
, fill
);
333 crypto_morus640_load_a(&m
, buf
.bytes
);
334 crypto_morus640_update(state
, &m
);
341 crypto_morus640_ad(state
, src
, left
);
342 src
+= left
& ~(MORUS640_BLOCK_SIZE
- 1);
343 left
&= MORUS640_BLOCK_SIZE
- 1;
346 memcpy(buf
.bytes
+ pos
, src
, left
);
350 scatterwalk_unmap(mapped
);
351 scatterwalk_advance(&walk
, size
);
352 scatterwalk_done(&walk
, 0, assoclen
);
356 memset(buf
.bytes
+ pos
, 0, MORUS640_BLOCK_SIZE
- pos
);
358 crypto_morus640_load_a(&m
, buf
.bytes
);
359 crypto_morus640_update(state
, &m
);
363 static void crypto_morus640_process_crypt(struct morus640_state
*state
,
364 struct aead_request
*req
,
365 const struct morus640_ops
*ops
)
367 struct skcipher_walk walk
;
369 ops
->skcipher_walk_init(&walk
, req
, false);
371 while (walk
.nbytes
) {
372 unsigned int nbytes
= walk
.nbytes
;
374 if (nbytes
< walk
.total
)
375 nbytes
= round_down(nbytes
, walk
.stride
);
377 ops
->crypt_chunk(state
, walk
.dst
.virt
.addr
, walk
.src
.virt
.addr
,
380 skcipher_walk_done(&walk
, walk
.nbytes
- nbytes
);
384 static void crypto_morus640_final(struct morus640_state
*state
,
385 struct morus640_block
*tag_xor
,
386 u64 assoclen
, u64 cryptlen
)
388 struct morus640_block tmp
;
391 tmp
.words
[0] = lower_32_bits(assoclen
* 8);
392 tmp
.words
[1] = upper_32_bits(assoclen
* 8);
393 tmp
.words
[2] = lower_32_bits(cryptlen
* 8);
394 tmp
.words
[3] = upper_32_bits(cryptlen
* 8);
396 for (i
= 0; i
< MORUS_BLOCK_WORDS
; i
++)
397 state
->s
[4].words
[i
] ^= state
->s
[0].words
[i
];
399 for (i
= 0; i
< 10; i
++)
400 crypto_morus640_update(state
, &tmp
);
402 crypto_morus640_core(state
, tag_xor
);
405 static int crypto_morus640_setkey(struct crypto_aead
*aead
, const u8
*key
,
408 struct morus640_ctx
*ctx
= crypto_aead_ctx(aead
);
410 if (keylen
!= MORUS640_BLOCK_SIZE
) {
411 crypto_aead_set_flags(aead
, CRYPTO_TFM_RES_BAD_KEY_LEN
);
415 crypto_morus640_load(&ctx
->key
, key
);
419 static int crypto_morus640_setauthsize(struct crypto_aead
*tfm
,
420 unsigned int authsize
)
422 return (authsize
<= MORUS_MAX_AUTH_SIZE
) ? 0 : -EINVAL
;
425 static void crypto_morus640_crypt(struct aead_request
*req
,
426 struct morus640_block
*tag_xor
,
427 unsigned int cryptlen
,
428 const struct morus640_ops
*ops
)
430 struct crypto_aead
*tfm
= crypto_aead_reqtfm(req
);
431 struct morus640_ctx
*ctx
= crypto_aead_ctx(tfm
);
432 struct morus640_state state
;
434 crypto_morus640_init(&state
, &ctx
->key
, req
->iv
);
435 crypto_morus640_process_ad(&state
, req
->src
, req
->assoclen
);
436 crypto_morus640_process_crypt(&state
, req
, ops
);
437 crypto_morus640_final(&state
, tag_xor
, req
->assoclen
, cryptlen
);
440 static int crypto_morus640_encrypt(struct aead_request
*req
)
442 static const struct morus640_ops ops
= {
443 .skcipher_walk_init
= skcipher_walk_aead_encrypt
,
444 .crypt_chunk
= crypto_morus640_encrypt_chunk
,
447 struct crypto_aead
*tfm
= crypto_aead_reqtfm(req
);
448 struct morus640_block tag
= {};
449 union morus640_block_in tag_out
;
450 unsigned int authsize
= crypto_aead_authsize(tfm
);
451 unsigned int cryptlen
= req
->cryptlen
;
453 crypto_morus640_crypt(req
, &tag
, cryptlen
, &ops
);
454 crypto_morus640_store(tag_out
.bytes
, &tag
);
456 scatterwalk_map_and_copy(tag_out
.bytes
, req
->dst
,
457 req
->assoclen
+ cryptlen
, authsize
, 1);
461 static int crypto_morus640_decrypt(struct aead_request
*req
)
463 static const struct morus640_ops ops
= {
464 .skcipher_walk_init
= skcipher_walk_aead_decrypt
,
465 .crypt_chunk
= crypto_morus640_decrypt_chunk
,
467 static const u8 zeros
[MORUS640_BLOCK_SIZE
] = {};
469 struct crypto_aead
*tfm
= crypto_aead_reqtfm(req
);
470 union morus640_block_in tag_in
;
471 struct morus640_block tag
;
472 unsigned int authsize
= crypto_aead_authsize(tfm
);
473 unsigned int cryptlen
= req
->cryptlen
- authsize
;
475 scatterwalk_map_and_copy(tag_in
.bytes
, req
->src
,
476 req
->assoclen
+ cryptlen
, authsize
, 0);
478 crypto_morus640_load(&tag
, tag_in
.bytes
);
479 crypto_morus640_crypt(req
, &tag
, cryptlen
, &ops
);
480 crypto_morus640_store(tag_in
.bytes
, &tag
);
482 return crypto_memneq(tag_in
.bytes
, zeros
, authsize
) ? -EBADMSG
: 0;
485 static int crypto_morus640_init_tfm(struct crypto_aead
*tfm
)
490 static void crypto_morus640_exit_tfm(struct crypto_aead
*tfm
)
494 static struct aead_alg crypto_morus640_alg
= {
495 .setkey
= crypto_morus640_setkey
,
496 .setauthsize
= crypto_morus640_setauthsize
,
497 .encrypt
= crypto_morus640_encrypt
,
498 .decrypt
= crypto_morus640_decrypt
,
499 .init
= crypto_morus640_init_tfm
,
500 .exit
= crypto_morus640_exit_tfm
,
502 .ivsize
= MORUS_NONCE_SIZE
,
503 .maxauthsize
= MORUS_MAX_AUTH_SIZE
,
504 .chunksize
= MORUS640_BLOCK_SIZE
,
508 .cra_ctxsize
= sizeof(struct morus640_ctx
),
513 .cra_name
= "morus640",
514 .cra_driver_name
= "morus640-generic",
516 .cra_module
= THIS_MODULE
,
520 static int __init
crypto_morus640_module_init(void)
522 return crypto_register_aead(&crypto_morus640_alg
);
525 static void __exit
crypto_morus640_module_exit(void)
527 crypto_unregister_aead(&crypto_morus640_alg
);
530 module_init(crypto_morus640_module_init
);
531 module_exit(crypto_morus640_module_exit
);
533 MODULE_LICENSE("GPL");
534 MODULE_AUTHOR("Ondrej Mosnacek <omosnacek@gmail.com>");
535 MODULE_DESCRIPTION("MORUS-640 AEAD algorithm");
536 MODULE_ALIAS_CRYPTO("morus640");
537 MODULE_ALIAS_CRYPTO("morus640-generic");