859c7b905618730404e4a3b6d822b93e7f0d176c
[linux-2.6-microblaze.git] / crypto / aegis128-core.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * The AEGIS-128 Authenticated-Encryption Algorithm
4  *
5  * Copyright (c) 2017-2018 Ondrej Mosnacek <omosnacek@gmail.com>
6  * Copyright (C) 2017-2018 Red Hat, Inc. All rights reserved.
7  */
8
9 #include <crypto/algapi.h>
10 #include <crypto/internal/aead.h>
11 #include <crypto/internal/simd.h>
12 #include <crypto/internal/skcipher.h>
13 #include <crypto/scatterwalk.h>
14 #include <linux/err.h>
15 #include <linux/init.h>
16 #include <linux/jump_label.h>
17 #include <linux/kernel.h>
18 #include <linux/module.h>
19 #include <linux/scatterlist.h>
20
21 #include <asm/simd.h>
22
23 #include "aegis.h"
24
25 #define AEGIS128_NONCE_SIZE 16
26 #define AEGIS128_STATE_BLOCKS 5
27 #define AEGIS128_KEY_SIZE 16
28 #define AEGIS128_MIN_AUTH_SIZE 8
29 #define AEGIS128_MAX_AUTH_SIZE 16
30
31 struct aegis_state {
32         union aegis_block blocks[AEGIS128_STATE_BLOCKS];
33 };
34
35 struct aegis_ctx {
36         union aegis_block key;
37 };
38
39 static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_simd);
40
41 static const union aegis_block crypto_aegis_const[2] = {
42         { .words64 = {
43                 cpu_to_le64(U64_C(0x0d08050302010100)),
44                 cpu_to_le64(U64_C(0x6279e99059372215)),
45         } },
46         { .words64 = {
47                 cpu_to_le64(U64_C(0xf12fc26d55183ddb)),
48                 cpu_to_le64(U64_C(0xdd28b57342311120)),
49         } },
50 };
51
52 static bool aegis128_do_simd(void)
53 {
54 #ifdef CONFIG_CRYPTO_AEGIS128_SIMD
55         if (static_branch_likely(&have_simd))
56                 return crypto_simd_usable();
57 #endif
58         return false;
59 }
60
61 bool crypto_aegis128_have_simd(void);
62 void crypto_aegis128_update_simd(struct aegis_state *state, const void *msg);
63 void crypto_aegis128_init_simd(struct aegis_state *state,
64                                const union aegis_block *key,
65                                const u8 *iv);
66 void crypto_aegis128_encrypt_chunk_simd(struct aegis_state *state, u8 *dst,
67                                         const u8 *src, unsigned int size);
68 void crypto_aegis128_decrypt_chunk_simd(struct aegis_state *state, u8 *dst,
69                                         const u8 *src, unsigned int size);
70 int crypto_aegis128_final_simd(struct aegis_state *state,
71                                union aegis_block *tag_xor,
72                                unsigned int assoclen,
73                                unsigned int cryptlen,
74                                unsigned int authsize);
75
76 static void crypto_aegis128_update(struct aegis_state *state)
77 {
78         union aegis_block tmp;
79         unsigned int i;
80
81         tmp = state->blocks[AEGIS128_STATE_BLOCKS - 1];
82         for (i = AEGIS128_STATE_BLOCKS - 1; i > 0; i--)
83                 crypto_aegis_aesenc(&state->blocks[i], &state->blocks[i - 1],
84                                     &state->blocks[i]);
85         crypto_aegis_aesenc(&state->blocks[0], &tmp, &state->blocks[0]);
86 }
87
88 static void crypto_aegis128_update_a(struct aegis_state *state,
89                                      const union aegis_block *msg)
90 {
91         if (aegis128_do_simd()) {
92                 crypto_aegis128_update_simd(state, msg);
93                 return;
94         }
95
96         crypto_aegis128_update(state);
97         crypto_aegis_block_xor(&state->blocks[0], msg);
98 }
99
100 static void crypto_aegis128_update_u(struct aegis_state *state, const void *msg)
101 {
102         if (aegis128_do_simd()) {
103                 crypto_aegis128_update_simd(state, msg);
104                 return;
105         }
106
107         crypto_aegis128_update(state);
108         crypto_xor(state->blocks[0].bytes, msg, AEGIS_BLOCK_SIZE);
109 }
110
111 static void crypto_aegis128_init(struct aegis_state *state,
112                                  const union aegis_block *key,
113                                  const u8 *iv)
114 {
115         union aegis_block key_iv;
116         unsigned int i;
117
118         key_iv = *key;
119         crypto_xor(key_iv.bytes, iv, AEGIS_BLOCK_SIZE);
120
121         state->blocks[0] = key_iv;
122         state->blocks[1] = crypto_aegis_const[1];
123         state->blocks[2] = crypto_aegis_const[0];
124         state->blocks[3] = *key;
125         state->blocks[4] = *key;
126
127         crypto_aegis_block_xor(&state->blocks[3], &crypto_aegis_const[0]);
128         crypto_aegis_block_xor(&state->blocks[4], &crypto_aegis_const[1]);
129
130         for (i = 0; i < 5; i++) {
131                 crypto_aegis128_update_a(state, key);
132                 crypto_aegis128_update_a(state, &key_iv);
133         }
134 }
135
136 static void crypto_aegis128_ad(struct aegis_state *state,
137                                const u8 *src, unsigned int size)
138 {
139         if (AEGIS_ALIGNED(src)) {
140                 const union aegis_block *src_blk =
141                                 (const union aegis_block *)src;
142
143                 while (size >= AEGIS_BLOCK_SIZE) {
144                         crypto_aegis128_update_a(state, src_blk);
145
146                         size -= AEGIS_BLOCK_SIZE;
147                         src_blk++;
148                 }
149         } else {
150                 while (size >= AEGIS_BLOCK_SIZE) {
151                         crypto_aegis128_update_u(state, src);
152
153                         size -= AEGIS_BLOCK_SIZE;
154                         src += AEGIS_BLOCK_SIZE;
155                 }
156         }
157 }
158
159 static void crypto_aegis128_wipe_chunk(struct aegis_state *state, u8 *dst,
160                                        const u8 *src, unsigned int size)
161 {
162         memzero_explicit(dst, size);
163 }
164
165 static void crypto_aegis128_encrypt_chunk(struct aegis_state *state, u8 *dst,
166                                           const u8 *src, unsigned int size)
167 {
168         union aegis_block tmp;
169
170         if (AEGIS_ALIGNED(src) && AEGIS_ALIGNED(dst)) {
171                 while (size >= AEGIS_BLOCK_SIZE) {
172                         union aegis_block *dst_blk =
173                                         (union aegis_block *)dst;
174                         const union aegis_block *src_blk =
175                                         (const union aegis_block *)src;
176
177                         tmp = state->blocks[2];
178                         crypto_aegis_block_and(&tmp, &state->blocks[3]);
179                         crypto_aegis_block_xor(&tmp, &state->blocks[4]);
180                         crypto_aegis_block_xor(&tmp, &state->blocks[1]);
181                         crypto_aegis_block_xor(&tmp, src_blk);
182
183                         crypto_aegis128_update_a(state, src_blk);
184
185                         *dst_blk = tmp;
186
187                         size -= AEGIS_BLOCK_SIZE;
188                         src += AEGIS_BLOCK_SIZE;
189                         dst += AEGIS_BLOCK_SIZE;
190                 }
191         } else {
192                 while (size >= AEGIS_BLOCK_SIZE) {
193                         tmp = state->blocks[2];
194                         crypto_aegis_block_and(&tmp, &state->blocks[3]);
195                         crypto_aegis_block_xor(&tmp, &state->blocks[4]);
196                         crypto_aegis_block_xor(&tmp, &state->blocks[1]);
197                         crypto_xor(tmp.bytes, src, AEGIS_BLOCK_SIZE);
198
199                         crypto_aegis128_update_u(state, src);
200
201                         memcpy(dst, tmp.bytes, AEGIS_BLOCK_SIZE);
202
203                         size -= AEGIS_BLOCK_SIZE;
204                         src += AEGIS_BLOCK_SIZE;
205                         dst += AEGIS_BLOCK_SIZE;
206                 }
207         }
208
209         if (size > 0) {
210                 union aegis_block msg = {};
211                 memcpy(msg.bytes, src, size);
212
213                 tmp = state->blocks[2];
214                 crypto_aegis_block_and(&tmp, &state->blocks[3]);
215                 crypto_aegis_block_xor(&tmp, &state->blocks[4]);
216                 crypto_aegis_block_xor(&tmp, &state->blocks[1]);
217
218                 crypto_aegis128_update_a(state, &msg);
219
220                 crypto_aegis_block_xor(&msg, &tmp);
221
222                 memcpy(dst, msg.bytes, size);
223         }
224 }
225
226 static void crypto_aegis128_decrypt_chunk(struct aegis_state *state, u8 *dst,
227                                           const u8 *src, unsigned int size)
228 {
229         union aegis_block tmp;
230
231         if (AEGIS_ALIGNED(src) && AEGIS_ALIGNED(dst)) {
232                 while (size >= AEGIS_BLOCK_SIZE) {
233                         union aegis_block *dst_blk =
234                                         (union aegis_block *)dst;
235                         const union aegis_block *src_blk =
236                                         (const union aegis_block *)src;
237
238                         tmp = state->blocks[2];
239                         crypto_aegis_block_and(&tmp, &state->blocks[3]);
240                         crypto_aegis_block_xor(&tmp, &state->blocks[4]);
241                         crypto_aegis_block_xor(&tmp, &state->blocks[1]);
242                         crypto_aegis_block_xor(&tmp, src_blk);
243
244                         crypto_aegis128_update_a(state, &tmp);
245
246                         *dst_blk = tmp;
247
248                         size -= AEGIS_BLOCK_SIZE;
249                         src += AEGIS_BLOCK_SIZE;
250                         dst += AEGIS_BLOCK_SIZE;
251                 }
252         } else {
253                 while (size >= AEGIS_BLOCK_SIZE) {
254                         tmp = state->blocks[2];
255                         crypto_aegis_block_and(&tmp, &state->blocks[3]);
256                         crypto_aegis_block_xor(&tmp, &state->blocks[4]);
257                         crypto_aegis_block_xor(&tmp, &state->blocks[1]);
258                         crypto_xor(tmp.bytes, src, AEGIS_BLOCK_SIZE);
259
260                         crypto_aegis128_update_a(state, &tmp);
261
262                         memcpy(dst, tmp.bytes, AEGIS_BLOCK_SIZE);
263
264                         size -= AEGIS_BLOCK_SIZE;
265                         src += AEGIS_BLOCK_SIZE;
266                         dst += AEGIS_BLOCK_SIZE;
267                 }
268         }
269
270         if (size > 0) {
271                 union aegis_block msg = {};
272                 memcpy(msg.bytes, src, size);
273
274                 tmp = state->blocks[2];
275                 crypto_aegis_block_and(&tmp, &state->blocks[3]);
276                 crypto_aegis_block_xor(&tmp, &state->blocks[4]);
277                 crypto_aegis_block_xor(&tmp, &state->blocks[1]);
278                 crypto_aegis_block_xor(&msg, &tmp);
279
280                 memset(msg.bytes + size, 0, AEGIS_BLOCK_SIZE - size);
281
282                 crypto_aegis128_update_a(state, &msg);
283
284                 memcpy(dst, msg.bytes, size);
285         }
286 }
287
288 static void crypto_aegis128_process_ad(struct aegis_state *state,
289                                        struct scatterlist *sg_src,
290                                        unsigned int assoclen)
291 {
292         struct scatter_walk walk;
293         union aegis_block buf;
294         unsigned int pos = 0;
295
296         scatterwalk_start(&walk, sg_src);
297         while (assoclen != 0) {
298                 unsigned int size = scatterwalk_clamp(&walk, assoclen);
299                 unsigned int left = size;
300                 void *mapped = scatterwalk_map(&walk);
301                 const u8 *src = (const u8 *)mapped;
302
303                 if (pos + size >= AEGIS_BLOCK_SIZE) {
304                         if (pos > 0) {
305                                 unsigned int fill = AEGIS_BLOCK_SIZE - pos;
306                                 memcpy(buf.bytes + pos, src, fill);
307                                 crypto_aegis128_update_a(state, &buf);
308                                 pos = 0;
309                                 left -= fill;
310                                 src += fill;
311                         }
312
313                         crypto_aegis128_ad(state, src, left);
314                         src += left & ~(AEGIS_BLOCK_SIZE - 1);
315                         left &= AEGIS_BLOCK_SIZE - 1;
316                 }
317
318                 memcpy(buf.bytes + pos, src, left);
319
320                 pos += left;
321                 assoclen -= size;
322                 scatterwalk_unmap(mapped);
323                 scatterwalk_advance(&walk, size);
324                 scatterwalk_done(&walk, 0, assoclen);
325         }
326
327         if (pos > 0) {
328                 memset(buf.bytes + pos, 0, AEGIS_BLOCK_SIZE - pos);
329                 crypto_aegis128_update_a(state, &buf);
330         }
331 }
332
333 static __always_inline
334 int crypto_aegis128_process_crypt(struct aegis_state *state,
335                                   struct skcipher_walk *walk,
336                                   void (*crypt)(struct aegis_state *state,
337                                                 u8 *dst, const u8 *src,
338                                                 unsigned int size))
339 {
340         int err = 0;
341
342         while (walk->nbytes) {
343                 unsigned int nbytes = walk->nbytes;
344
345                 if (nbytes < walk->total)
346                         nbytes = round_down(nbytes, walk->stride);
347
348                 crypt(state, walk->dst.virt.addr, walk->src.virt.addr, nbytes);
349
350                 err = skcipher_walk_done(walk, walk->nbytes - nbytes);
351         }
352         return err;
353 }
354
355 static void crypto_aegis128_final(struct aegis_state *state,
356                                   union aegis_block *tag_xor,
357                                   u64 assoclen, u64 cryptlen)
358 {
359         u64 assocbits = assoclen * 8;
360         u64 cryptbits = cryptlen * 8;
361
362         union aegis_block tmp;
363         unsigned int i;
364
365         tmp.words64[0] = cpu_to_le64(assocbits);
366         tmp.words64[1] = cpu_to_le64(cryptbits);
367
368         crypto_aegis_block_xor(&tmp, &state->blocks[3]);
369
370         for (i = 0; i < 7; i++)
371                 crypto_aegis128_update_a(state, &tmp);
372
373         for (i = 0; i < AEGIS128_STATE_BLOCKS; i++)
374                 crypto_aegis_block_xor(tag_xor, &state->blocks[i]);
375 }
376
377 static int crypto_aegis128_setkey(struct crypto_aead *aead, const u8 *key,
378                                   unsigned int keylen)
379 {
380         struct aegis_ctx *ctx = crypto_aead_ctx(aead);
381
382         if (keylen != AEGIS128_KEY_SIZE)
383                 return -EINVAL;
384
385         memcpy(ctx->key.bytes, key, AEGIS128_KEY_SIZE);
386         return 0;
387 }
388
389 static int crypto_aegis128_setauthsize(struct crypto_aead *tfm,
390                                        unsigned int authsize)
391 {
392         if (authsize > AEGIS128_MAX_AUTH_SIZE)
393                 return -EINVAL;
394         if (authsize < AEGIS128_MIN_AUTH_SIZE)
395                 return -EINVAL;
396         return 0;
397 }
398
399 static int crypto_aegis128_encrypt(struct aead_request *req)
400 {
401         struct crypto_aead *tfm = crypto_aead_reqtfm(req);
402         union aegis_block tag = {};
403         unsigned int authsize = crypto_aead_authsize(tfm);
404         struct aegis_ctx *ctx = crypto_aead_ctx(tfm);
405         unsigned int cryptlen = req->cryptlen;
406         struct skcipher_walk walk;
407         struct aegis_state state;
408
409         skcipher_walk_aead_encrypt(&walk, req, false);
410         if (aegis128_do_simd()) {
411                 crypto_aegis128_init_simd(&state, &ctx->key, req->iv);
412                 crypto_aegis128_process_ad(&state, req->src, req->assoclen);
413                 crypto_aegis128_process_crypt(&state, &walk,
414                                               crypto_aegis128_encrypt_chunk_simd);
415                 crypto_aegis128_final_simd(&state, &tag, req->assoclen,
416                                            cryptlen, 0);
417         } else {
418                 crypto_aegis128_init(&state, &ctx->key, req->iv);
419                 crypto_aegis128_process_ad(&state, req->src, req->assoclen);
420                 crypto_aegis128_process_crypt(&state, &walk,
421                                               crypto_aegis128_encrypt_chunk);
422                 crypto_aegis128_final(&state, &tag, req->assoclen, cryptlen);
423         }
424
425         scatterwalk_map_and_copy(tag.bytes, req->dst, req->assoclen + cryptlen,
426                                  authsize, 1);
427         return 0;
428 }
429
430 static int crypto_aegis128_decrypt(struct aead_request *req)
431 {
432         static const u8 zeros[AEGIS128_MAX_AUTH_SIZE] = {};
433         struct crypto_aead *tfm = crypto_aead_reqtfm(req);
434         union aegis_block tag;
435         unsigned int authsize = crypto_aead_authsize(tfm);
436         unsigned int cryptlen = req->cryptlen - authsize;
437         struct aegis_ctx *ctx = crypto_aead_ctx(tfm);
438         struct skcipher_walk walk;
439         struct aegis_state state;
440
441         scatterwalk_map_and_copy(tag.bytes, req->src, req->assoclen + cryptlen,
442                                  authsize, 0);
443
444         skcipher_walk_aead_decrypt(&walk, req, false);
445         if (aegis128_do_simd()) {
446                 crypto_aegis128_init_simd(&state, &ctx->key, req->iv);
447                 crypto_aegis128_process_ad(&state, req->src, req->assoclen);
448                 crypto_aegis128_process_crypt(&state, &walk,
449                                               crypto_aegis128_decrypt_chunk_simd);
450                 if (unlikely(crypto_aegis128_final_simd(&state, &tag,
451                                                         req->assoclen,
452                                                         cryptlen, authsize))) {
453                         skcipher_walk_aead_decrypt(&walk, req, false);
454                         crypto_aegis128_process_crypt(NULL, req, &walk,
455                                                       crypto_aegis128_wipe_chunk);
456                         return -EBADMSG;
457                 }
458                 return 0;
459         } else {
460                 crypto_aegis128_init(&state, &ctx->key, req->iv);
461                 crypto_aegis128_process_ad(&state, req->src, req->assoclen);
462                 crypto_aegis128_process_crypt(&state, &walk,
463                                               crypto_aegis128_decrypt_chunk);
464                 crypto_aegis128_final(&state, &tag, req->assoclen, cryptlen);
465         }
466
467         if (unlikely(crypto_memneq(tag.bytes, zeros, authsize))) {
468                 /*
469                  * From Chapter 4. 'Security Analysis' of the AEGIS spec [0]
470                  *
471                  * "3. If verification fails, the decrypted plaintext and the
472                  *     wrong authentication tag should not be given as output."
473                  *
474                  * [0] https://competitions.cr.yp.to/round3/aegisv11.pdf
475                  */
476                 skcipher_walk_aead_decrypt(&walk, req, false);
477                 crypto_aegis128_process_crypt(NULL, &walk,
478                                               crypto_aegis128_wipe_chunk);
479                 memzero_explicit(&tag, sizeof(tag));
480                 return -EBADMSG;
481         }
482         return 0;
483 }
484
485 static struct aead_alg crypto_aegis128_alg = {
486         .setkey = crypto_aegis128_setkey,
487         .setauthsize = crypto_aegis128_setauthsize,
488         .encrypt = crypto_aegis128_encrypt,
489         .decrypt = crypto_aegis128_decrypt,
490
491         .ivsize = AEGIS128_NONCE_SIZE,
492         .maxauthsize = AEGIS128_MAX_AUTH_SIZE,
493         .chunksize = AEGIS_BLOCK_SIZE,
494
495         .base = {
496                 .cra_blocksize = 1,
497                 .cra_ctxsize = sizeof(struct aegis_ctx),
498                 .cra_alignmask = 0,
499
500                 .cra_priority = 100,
501
502                 .cra_name = "aegis128",
503                 .cra_driver_name = "aegis128-generic",
504
505                 .cra_module = THIS_MODULE,
506         }
507 };
508
509 static int __init crypto_aegis128_module_init(void)
510 {
511         if (IS_ENABLED(CONFIG_CRYPTO_AEGIS128_SIMD) &&
512             crypto_aegis128_have_simd())
513                 static_branch_enable(&have_simd);
514
515         return crypto_register_aead(&crypto_aegis128_alg);
516 }
517
518 static void __exit crypto_aegis128_module_exit(void)
519 {
520         crypto_unregister_aead(&crypto_aegis128_alg);
521 }
522
523 subsys_initcall(crypto_aegis128_module_init);
524 module_exit(crypto_aegis128_module_exit);
525
526 MODULE_LICENSE("GPL");
527 MODULE_AUTHOR("Ondrej Mosnacek <omosnacek@gmail.com>");
528 MODULE_DESCRIPTION("AEGIS-128 AEAD algorithm");
529 MODULE_ALIAS_CRYPTO("aegis128");
530 MODULE_ALIAS_CRYPTO("aegis128-generic");