Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
[sfrench/cifs-2.6.git] / crypto / morus640.c
1 /*
2  * The MORUS-640 Authenticated-Encryption Algorithm
3  *
4  * Copyright (c) 2016-2018 Ondrej Mosnacek <omosnacek@gmail.com>
5  * Copyright (C) 2017-2018 Red Hat, Inc. All rights reserved.
6  *
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)
10  * any later version.
11  */
12
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>
24
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)
29
30 struct morus640_block {
31         u32 words[MORUS_BLOCK_WORDS];
32 };
33
34 union morus640_block_in {
35         __le32 words[MORUS_BLOCK_WORDS];
36         u8 bytes[MORUS640_BLOCK_SIZE];
37 };
38
39 struct morus640_state {
40         struct morus640_block s[MORUS_STATE_BLOCKS];
41 };
42
43 struct morus640_ctx {
44         struct morus640_block key;
45 };
46
47 struct morus640_ops {
48         int (*skcipher_walk_init)(struct skcipher_walk *walk,
49                                   struct aead_request *req, bool atomic);
50
51         void (*crypt_chunk)(struct morus640_state *state,
52                             u8 *dst, const u8 *src, unsigned int size);
53 };
54
55 static const struct morus640_block crypto_morus640_const[2] = {
56         { .words = {
57                 U32_C(0x02010100),
58                 U32_C(0x0d080503),
59                 U32_C(0x59372215),
60                 U32_C(0x6279e990),
61         } },
62         { .words = {
63                 U32_C(0x55183ddb),
64                 U32_C(0xf12fc26d),
65                 U32_C(0x42311120),
66                 U32_C(0xdd28b573),
67         } },
68 };
69
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)
77 {
78         unsigned int i;
79         struct morus640_block tmp;
80
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);
86         }
87
88         tmp = *b3;
89         for (i = 0; i < MORUS_BLOCK_WORDS; i++)
90                 b3->words[(i + w) % MORUS_BLOCK_WORDS] = tmp.words[i];
91 }
92
93 static void crypto_morus640_update(struct morus640_state *state,
94                                    const struct morus640_block *m)
95 {
96         static const struct morus640_block z = {};
97
98         struct morus640_block *s = state->s;
99
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);
105 }
106
107 static void crypto_morus640_load_a(struct morus640_block *dst, const u8 *src)
108 {
109         unsigned int i;
110         for (i = 0; i < MORUS_BLOCK_WORDS; i++) {
111                 dst->words[i] = le32_to_cpu(*(const __le32 *)src);
112                 src += MORUS640_WORD_SIZE;
113         }
114 }
115
116 static void crypto_morus640_load_u(struct morus640_block *dst, const u8 *src)
117 {
118         unsigned int i;
119         for (i = 0; i < MORUS_BLOCK_WORDS; i++) {
120                 dst->words[i] = get_unaligned_le32(src);
121                 src += MORUS640_WORD_SIZE;
122         }
123 }
124
125 static void crypto_morus640_load(struct morus640_block *dst, const u8 *src)
126 {
127         if (MORUS640_ALIGNED(src))
128                 crypto_morus640_load_a(dst, src);
129         else
130                 crypto_morus640_load_u(dst, src);
131 }
132
133 static void crypto_morus640_store_a(u8 *dst, const struct morus640_block *src)
134 {
135         unsigned int i;
136         for (i = 0; i < MORUS_BLOCK_WORDS; i++) {
137                 *(__le32 *)dst = cpu_to_le32(src->words[i]);
138                 dst += MORUS640_WORD_SIZE;
139         }
140 }
141
142 static void crypto_morus640_store_u(u8 *dst, const struct morus640_block *src)
143 {
144         unsigned int i;
145         for (i = 0; i < MORUS_BLOCK_WORDS; i++) {
146                 put_unaligned_le32(src->words[i], dst);
147                 dst += MORUS640_WORD_SIZE;
148         }
149 }
150
151 static void crypto_morus640_store(u8 *dst, const struct morus640_block *src)
152 {
153         if (MORUS640_ALIGNED(dst))
154                 crypto_morus640_store_a(dst, src);
155         else
156                 crypto_morus640_store_u(dst, src);
157 }
158
159 static void crypto_morus640_ad(struct morus640_state *state, const u8 *src,
160                                unsigned int size)
161 {
162         struct morus640_block m;
163
164         if (MORUS640_ALIGNED(src)) {
165                 while (size >= MORUS640_BLOCK_SIZE) {
166                         crypto_morus640_load_a(&m, src);
167                         crypto_morus640_update(state, &m);
168
169                         size -= MORUS640_BLOCK_SIZE;
170                         src += MORUS640_BLOCK_SIZE;
171                 }
172         } else {
173                 while (size >= MORUS640_BLOCK_SIZE) {
174                         crypto_morus640_load_u(&m, src);
175                         crypto_morus640_update(state, &m);
176
177                         size -= MORUS640_BLOCK_SIZE;
178                         src += MORUS640_BLOCK_SIZE;
179                 }
180         }
181 }
182
183 static void crypto_morus640_core(const struct morus640_state *state,
184                                  struct morus640_block *blk)
185 {
186         unsigned int i;
187
188         for (i = 0; i < MORUS_BLOCK_WORDS; i++)
189                 blk->words[(i + 3) % MORUS_BLOCK_WORDS] ^= state->s[1].words[i];
190
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];
194         }
195 }
196
197 static void crypto_morus640_encrypt_chunk(struct morus640_state *state, u8 *dst,
198                                           const u8 *src, unsigned int size)
199 {
200         struct morus640_block c, m;
201
202         if (MORUS640_ALIGNED(src) && MORUS640_ALIGNED(dst)) {
203                 while (size >= MORUS640_BLOCK_SIZE) {
204                         crypto_morus640_load_a(&m, src);
205                         c = m;
206                         crypto_morus640_core(state, &c);
207                         crypto_morus640_store_a(dst, &c);
208                         crypto_morus640_update(state, &m);
209
210                         src += MORUS640_BLOCK_SIZE;
211                         dst += MORUS640_BLOCK_SIZE;
212                         size -= MORUS640_BLOCK_SIZE;
213                 }
214         } else {
215                 while (size >= MORUS640_BLOCK_SIZE) {
216                         crypto_morus640_load_u(&m, src);
217                         c = m;
218                         crypto_morus640_core(state, &c);
219                         crypto_morus640_store_u(dst, &c);
220                         crypto_morus640_update(state, &m);
221
222                         src += MORUS640_BLOCK_SIZE;
223                         dst += MORUS640_BLOCK_SIZE;
224                         size -= MORUS640_BLOCK_SIZE;
225                 }
226         }
227
228         if (size > 0) {
229                 union morus640_block_in tail;
230
231                 memcpy(tail.bytes, src, size);
232                 memset(tail.bytes + size, 0, MORUS640_BLOCK_SIZE - size);
233
234                 crypto_morus640_load_a(&m, tail.bytes);
235                 c = m;
236                 crypto_morus640_core(state, &c);
237                 crypto_morus640_store_a(tail.bytes, &c);
238                 crypto_morus640_update(state, &m);
239
240                 memcpy(dst, tail.bytes, size);
241         }
242 }
243
244 static void crypto_morus640_decrypt_chunk(struct morus640_state *state, u8 *dst,
245                                           const u8 *src, unsigned int size)
246 {
247         struct morus640_block m;
248
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);
255
256                         src += MORUS640_BLOCK_SIZE;
257                         dst += MORUS640_BLOCK_SIZE;
258                         size -= MORUS640_BLOCK_SIZE;
259                 }
260         } else {
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);
266
267                         src += MORUS640_BLOCK_SIZE;
268                         dst += MORUS640_BLOCK_SIZE;
269                         size -= MORUS640_BLOCK_SIZE;
270                 }
271         }
272
273         if (size > 0) {
274                 union morus640_block_in tail;
275
276                 memcpy(tail.bytes, src, size);
277                 memset(tail.bytes + size, 0, MORUS640_BLOCK_SIZE - size);
278
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);
285
286                 memcpy(dst, tail.bytes, size);
287         }
288 }
289
290 static void crypto_morus640_init(struct morus640_state *state,
291                                  const struct morus640_block *key,
292                                  const u8 *iv)
293 {
294         static const struct morus640_block z = {};
295
296         unsigned int i;
297
298         crypto_morus640_load(&state->s[0], iv);
299         state->s[1] = *key;
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];
304
305         for (i = 0; i < 16; i++)
306                 crypto_morus640_update(state, &z);
307
308         for (i = 0; i < MORUS_BLOCK_WORDS; i++)
309                 state->s[1].words[i] ^= key->words[i];
310 }
311
312 static void crypto_morus640_process_ad(struct morus640_state *state,
313                                        struct scatterlist *sg_src,
314                                        unsigned int assoclen)
315 {
316         struct scatter_walk walk;
317         struct morus640_block m;
318         union morus640_block_in buf;
319         unsigned int pos = 0;
320
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;
327
328                 if (pos + size >= MORUS640_BLOCK_SIZE) {
329                         if (pos > 0) {
330                                 unsigned int fill = MORUS640_BLOCK_SIZE - pos;
331                                 memcpy(buf.bytes + pos, src, fill);
332
333                                 crypto_morus640_load_a(&m, buf.bytes);
334                                 crypto_morus640_update(state, &m);
335
336                                 pos = 0;
337                                 left -= fill;
338                                 src += fill;
339                         }
340
341                         crypto_morus640_ad(state, src, left);
342                         src += left & ~(MORUS640_BLOCK_SIZE - 1);
343                         left &= MORUS640_BLOCK_SIZE - 1;
344                 }
345
346                 memcpy(buf.bytes + pos, src, left);
347
348                 pos += left;
349                 assoclen -= size;
350                 scatterwalk_unmap(mapped);
351                 scatterwalk_advance(&walk, size);
352                 scatterwalk_done(&walk, 0, assoclen);
353         }
354
355         if (pos > 0) {
356                 memset(buf.bytes + pos, 0, MORUS640_BLOCK_SIZE - pos);
357
358                 crypto_morus640_load_a(&m, buf.bytes);
359                 crypto_morus640_update(state, &m);
360         }
361 }
362
363 static void crypto_morus640_process_crypt(struct morus640_state *state,
364                                           struct aead_request *req,
365                                           const struct morus640_ops *ops)
366 {
367         struct skcipher_walk walk;
368         u8 *dst;
369         const u8 *src;
370
371         ops->skcipher_walk_init(&walk, req, false);
372
373         while (walk.nbytes) {
374                 src = walk.src.virt.addr;
375                 dst = walk.dst.virt.addr;
376
377                 ops->crypt_chunk(state, dst, src, walk.nbytes);
378
379                 skcipher_walk_done(&walk, 0);
380         }
381 }
382
383 static void crypto_morus640_final(struct morus640_state *state,
384                                   struct morus640_block *tag_xor,
385                                   u64 assoclen, u64 cryptlen)
386 {
387         u64 assocbits = assoclen * 8;
388         u64 cryptbits = cryptlen * 8;
389
390         u32 assocbits_lo = (u32)assocbits;
391         u32 assocbits_hi = (u32)(assocbits >> 32);
392         u32 cryptbits_lo = (u32)cryptbits;
393         u32 cryptbits_hi = (u32)(cryptbits >> 32);
394
395         struct morus640_block tmp;
396         unsigned int i;
397
398         tmp.words[0] = cpu_to_le32(assocbits_lo);
399         tmp.words[1] = cpu_to_le32(assocbits_hi);
400         tmp.words[2] = cpu_to_le32(cryptbits_lo);
401         tmp.words[3] = cpu_to_le32(cryptbits_hi);
402
403         for (i = 0; i < MORUS_BLOCK_WORDS; i++)
404                 state->s[4].words[i] ^= state->s[0].words[i];
405
406         for (i = 0; i < 10; i++)
407                 crypto_morus640_update(state, &tmp);
408
409         crypto_morus640_core(state, tag_xor);
410 }
411
412 static int crypto_morus640_setkey(struct crypto_aead *aead, const u8 *key,
413                                   unsigned int keylen)
414 {
415         struct morus640_ctx *ctx = crypto_aead_ctx(aead);
416
417         if (keylen != MORUS640_BLOCK_SIZE) {
418                 crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN);
419                 return -EINVAL;
420         }
421
422         crypto_morus640_load(&ctx->key, key);
423         return 0;
424 }
425
426 static int crypto_morus640_setauthsize(struct crypto_aead *tfm,
427                                        unsigned int authsize)
428 {
429         return (authsize <= MORUS_MAX_AUTH_SIZE) ? 0 : -EINVAL;
430 }
431
432 static void crypto_morus640_crypt(struct aead_request *req,
433                                   struct morus640_block *tag_xor,
434                                   unsigned int cryptlen,
435                                   const struct morus640_ops *ops)
436 {
437         struct crypto_aead *tfm = crypto_aead_reqtfm(req);
438         struct morus640_ctx *ctx = crypto_aead_ctx(tfm);
439         struct morus640_state state;
440
441         crypto_morus640_init(&state, &ctx->key, req->iv);
442         crypto_morus640_process_ad(&state, req->src, req->assoclen);
443         crypto_morus640_process_crypt(&state, req, ops);
444         crypto_morus640_final(&state, tag_xor, req->assoclen, cryptlen);
445 }
446
447 static int crypto_morus640_encrypt(struct aead_request *req)
448 {
449         static const struct morus640_ops ops = {
450                 .skcipher_walk_init = skcipher_walk_aead_encrypt,
451                 .crypt_chunk = crypto_morus640_encrypt_chunk,
452         };
453
454         struct crypto_aead *tfm = crypto_aead_reqtfm(req);
455         struct morus640_block tag = {};
456         union morus640_block_in tag_out;
457         unsigned int authsize = crypto_aead_authsize(tfm);
458         unsigned int cryptlen = req->cryptlen;
459
460         crypto_morus640_crypt(req, &tag, cryptlen, &ops);
461         crypto_morus640_store(tag_out.bytes, &tag);
462
463         scatterwalk_map_and_copy(tag_out.bytes, req->dst,
464                                  req->assoclen + cryptlen, authsize, 1);
465         return 0;
466 }
467
468 static int crypto_morus640_decrypt(struct aead_request *req)
469 {
470         static const struct morus640_ops ops = {
471                 .skcipher_walk_init = skcipher_walk_aead_decrypt,
472                 .crypt_chunk = crypto_morus640_decrypt_chunk,
473         };
474         static const u8 zeros[MORUS640_BLOCK_SIZE] = {};
475
476         struct crypto_aead *tfm = crypto_aead_reqtfm(req);
477         union morus640_block_in tag_in;
478         struct morus640_block tag;
479         unsigned int authsize = crypto_aead_authsize(tfm);
480         unsigned int cryptlen = req->cryptlen - authsize;
481
482         scatterwalk_map_and_copy(tag_in.bytes, req->src,
483                                  req->assoclen + cryptlen, authsize, 0);
484
485         crypto_morus640_load(&tag, tag_in.bytes);
486         crypto_morus640_crypt(req, &tag, cryptlen, &ops);
487         crypto_morus640_store(tag_in.bytes, &tag);
488
489         return crypto_memneq(tag_in.bytes, zeros, authsize) ? -EBADMSG : 0;
490 }
491
492 static int crypto_morus640_init_tfm(struct crypto_aead *tfm)
493 {
494         return 0;
495 }
496
497 static void crypto_morus640_exit_tfm(struct crypto_aead *tfm)
498 {
499 }
500
501 static struct aead_alg crypto_morus640_alg = {
502         .setkey = crypto_morus640_setkey,
503         .setauthsize = crypto_morus640_setauthsize,
504         .encrypt = crypto_morus640_encrypt,
505         .decrypt = crypto_morus640_decrypt,
506         .init = crypto_morus640_init_tfm,
507         .exit = crypto_morus640_exit_tfm,
508
509         .ivsize = MORUS_NONCE_SIZE,
510         .maxauthsize = MORUS_MAX_AUTH_SIZE,
511         .chunksize = MORUS640_BLOCK_SIZE,
512
513         .base = {
514                 .cra_flags = CRYPTO_ALG_TYPE_AEAD,
515                 .cra_blocksize = 1,
516                 .cra_ctxsize = sizeof(struct morus640_ctx),
517                 .cra_alignmask = 0,
518
519                 .cra_priority = 100,
520
521                 .cra_name = "morus640",
522                 .cra_driver_name = "morus640-generic",
523
524                 .cra_module = THIS_MODULE,
525         }
526 };
527
528 static int __init crypto_morus640_module_init(void)
529 {
530         return crypto_register_aead(&crypto_morus640_alg);
531 }
532
533 static void __exit crypto_morus640_module_exit(void)
534 {
535         crypto_unregister_aead(&crypto_morus640_alg);
536 }
537
538 module_init(crypto_morus640_module_init);
539 module_exit(crypto_morus640_module_exit);
540
541 MODULE_LICENSE("GPL");
542 MODULE_AUTHOR("Ondrej Mosnacek <omosnacek@gmail.com>");
543 MODULE_DESCRIPTION("MORUS-640 AEAD algorithm");
544 MODULE_ALIAS_CRYPTO("morus640");
545 MODULE_ALIAS_CRYPTO("morus640-generic");