1 /*
2  * The AEGIS-128L Authenticated-Encryption Algorithm
3  *
4  * Copyright (c) 2017-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 <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>
22 
23 #include "aegis.h"
24 
25 #define AEGIS128L_CHUNK_BLOCKS 2
26 #define AEGIS128L_CHUNK_SIZE (AEGIS128L_CHUNK_BLOCKS * AEGIS_BLOCK_SIZE)
27 #define AEGIS128L_NONCE_SIZE 16
28 #define AEGIS128L_STATE_BLOCKS 8
29 #define AEGIS128L_KEY_SIZE 16
30 #define AEGIS128L_MIN_AUTH_SIZE 8
31 #define AEGIS128L_MAX_AUTH_SIZE 16
32 
33 union aegis_chunk {
34 	union aegis_block blocks[AEGIS128L_CHUNK_BLOCKS];
35 	u8 bytes[AEGIS128L_CHUNK_SIZE];
36 };
37 
38 struct aegis_state {
39 	union aegis_block blocks[AEGIS128L_STATE_BLOCKS];
40 };
41 
42 struct aegis_ctx {
43 	union aegis_block key;
44 };
45 
46 struct aegis128l_ops {
47 	int (*skcipher_walk_init)(struct skcipher_walk *walk,
48 				  struct aead_request *req, bool atomic);
49 
50 	void (*crypt_chunk)(struct aegis_state *state, u8 *dst,
51 			    const u8 *src, unsigned int size);
52 };
53 
crypto_aegis128l_update(struct aegis_state * state)54 static void crypto_aegis128l_update(struct aegis_state *state)
55 {
56 	union aegis_block tmp;
57 	unsigned int i;
58 
59 	tmp = state->blocks[AEGIS128L_STATE_BLOCKS - 1];
60 	for (i = AEGIS128L_STATE_BLOCKS - 1; i > 0; i--)
61 		crypto_aegis_aesenc(&state->blocks[i], &state->blocks[i - 1],
62 				    &state->blocks[i]);
63 	crypto_aegis_aesenc(&state->blocks[0], &tmp, &state->blocks[0]);
64 }
65 
crypto_aegis128l_update_a(struct aegis_state * state,const union aegis_chunk * msg)66 static void crypto_aegis128l_update_a(struct aegis_state *state,
67 				      const union aegis_chunk *msg)
68 {
69 	crypto_aegis128l_update(state);
70 	crypto_aegis_block_xor(&state->blocks[0], &msg->blocks[0]);
71 	crypto_aegis_block_xor(&state->blocks[4], &msg->blocks[1]);
72 }
73 
crypto_aegis128l_update_u(struct aegis_state * state,const void * msg)74 static void crypto_aegis128l_update_u(struct aegis_state *state,
75 				      const void *msg)
76 {
77 	crypto_aegis128l_update(state);
78 	crypto_xor(state->blocks[0].bytes, msg + 0 * AEGIS_BLOCK_SIZE,
79 			AEGIS_BLOCK_SIZE);
80 	crypto_xor(state->blocks[4].bytes, msg + 1 * AEGIS_BLOCK_SIZE,
81 			AEGIS_BLOCK_SIZE);
82 }
83 
crypto_aegis128l_init(struct aegis_state * state,const union aegis_block * key,const u8 * iv)84 static void crypto_aegis128l_init(struct aegis_state *state,
85 				  const union aegis_block *key,
86 				  const u8 *iv)
87 {
88 	union aegis_block key_iv;
89 	union aegis_chunk chunk;
90 	unsigned int i;
91 
92 	memcpy(chunk.blocks[0].bytes, iv, AEGIS_BLOCK_SIZE);
93 	chunk.blocks[1] = *key;
94 
95 	key_iv = *key;
96 	crypto_aegis_block_xor(&key_iv, &chunk.blocks[0]);
97 
98 	state->blocks[0] = key_iv;
99 	state->blocks[1] = crypto_aegis_const[1];
100 	state->blocks[2] = crypto_aegis_const[0];
101 	state->blocks[3] = crypto_aegis_const[1];
102 	state->blocks[4] = key_iv;
103 	state->blocks[5] = *key;
104 	state->blocks[6] = *key;
105 	state->blocks[7] = *key;
106 
107 	crypto_aegis_block_xor(&state->blocks[5], &crypto_aegis_const[0]);
108 	crypto_aegis_block_xor(&state->blocks[6], &crypto_aegis_const[1]);
109 	crypto_aegis_block_xor(&state->blocks[7], &crypto_aegis_const[0]);
110 
111 	for (i = 0; i < 10; i++) {
112 		crypto_aegis128l_update_a(state, &chunk);
113 	}
114 }
115 
crypto_aegis128l_ad(struct aegis_state * state,const u8 * src,unsigned int size)116 static void crypto_aegis128l_ad(struct aegis_state *state,
117 				const u8 *src, unsigned int size)
118 {
119 	if (AEGIS_ALIGNED(src)) {
120 		const union aegis_chunk *src_chunk =
121 				(const union aegis_chunk *)src;
122 
123 		while (size >= AEGIS128L_CHUNK_SIZE) {
124 			crypto_aegis128l_update_a(state, src_chunk);
125 
126 			size -= AEGIS128L_CHUNK_SIZE;
127 			src_chunk += 1;
128 		}
129 	} else {
130 		while (size >= AEGIS128L_CHUNK_SIZE) {
131 			crypto_aegis128l_update_u(state, src);
132 
133 			size -= AEGIS128L_CHUNK_SIZE;
134 			src += AEGIS128L_CHUNK_SIZE;
135 		}
136 	}
137 }
138 
crypto_aegis128l_encrypt_chunk(struct aegis_state * state,u8 * dst,const u8 * src,unsigned int size)139 static void crypto_aegis128l_encrypt_chunk(struct aegis_state *state, u8 *dst,
140 					   const u8 *src, unsigned int size)
141 {
142 	union aegis_chunk tmp;
143 	union aegis_block *tmp0 = &tmp.blocks[0];
144 	union aegis_block *tmp1 = &tmp.blocks[1];
145 
146 	if (AEGIS_ALIGNED(src) && AEGIS_ALIGNED(dst)) {
147 		while (size >= AEGIS128L_CHUNK_SIZE) {
148 			union aegis_chunk *dst_blk =
149 					(union aegis_chunk *)dst;
150 			const union aegis_chunk *src_blk =
151 					(const union aegis_chunk *)src;
152 
153 			*tmp0 = state->blocks[2];
154 			crypto_aegis_block_and(tmp0, &state->blocks[3]);
155 			crypto_aegis_block_xor(tmp0, &state->blocks[6]);
156 			crypto_aegis_block_xor(tmp0, &state->blocks[1]);
157 			crypto_aegis_block_xor(tmp0, &src_blk->blocks[0]);
158 
159 			*tmp1 = state->blocks[6];
160 			crypto_aegis_block_and(tmp1, &state->blocks[7]);
161 			crypto_aegis_block_xor(tmp1, &state->blocks[5]);
162 			crypto_aegis_block_xor(tmp1, &state->blocks[2]);
163 			crypto_aegis_block_xor(tmp1, &src_blk->blocks[1]);
164 
165 			crypto_aegis128l_update_a(state, src_blk);
166 
167 			*dst_blk = tmp;
168 
169 			size -= AEGIS128L_CHUNK_SIZE;
170 			src += AEGIS128L_CHUNK_SIZE;
171 			dst += AEGIS128L_CHUNK_SIZE;
172 		}
173 	} else {
174 		while (size >= AEGIS128L_CHUNK_SIZE) {
175 			*tmp0 = state->blocks[2];
176 			crypto_aegis_block_and(tmp0, &state->blocks[3]);
177 			crypto_aegis_block_xor(tmp0, &state->blocks[6]);
178 			crypto_aegis_block_xor(tmp0, &state->blocks[1]);
179 			crypto_xor(tmp0->bytes, src + 0 * AEGIS_BLOCK_SIZE,
180 				   AEGIS_BLOCK_SIZE);
181 
182 			*tmp1 = state->blocks[6];
183 			crypto_aegis_block_and(tmp1, &state->blocks[7]);
184 			crypto_aegis_block_xor(tmp1, &state->blocks[5]);
185 			crypto_aegis_block_xor(tmp1, &state->blocks[2]);
186 			crypto_xor(tmp1->bytes, src + 1 * AEGIS_BLOCK_SIZE,
187 				   AEGIS_BLOCK_SIZE);
188 
189 			crypto_aegis128l_update_u(state, src);
190 
191 			memcpy(dst, tmp.bytes, AEGIS128L_CHUNK_SIZE);
192 
193 			size -= AEGIS128L_CHUNK_SIZE;
194 			src += AEGIS128L_CHUNK_SIZE;
195 			dst += AEGIS128L_CHUNK_SIZE;
196 		}
197 	}
198 
199 	if (size > 0) {
200 		union aegis_chunk msg = {};
201 		memcpy(msg.bytes, src, size);
202 
203 		*tmp0 = state->blocks[2];
204 		crypto_aegis_block_and(tmp0, &state->blocks[3]);
205 		crypto_aegis_block_xor(tmp0, &state->blocks[6]);
206 		crypto_aegis_block_xor(tmp0, &state->blocks[1]);
207 
208 		*tmp1 = state->blocks[6];
209 		crypto_aegis_block_and(tmp1, &state->blocks[7]);
210 		crypto_aegis_block_xor(tmp1, &state->blocks[5]);
211 		crypto_aegis_block_xor(tmp1, &state->blocks[2]);
212 
213 		crypto_aegis128l_update_a(state, &msg);
214 
215 		crypto_aegis_block_xor(&msg.blocks[0], tmp0);
216 		crypto_aegis_block_xor(&msg.blocks[1], tmp1);
217 
218 		memcpy(dst, msg.bytes, size);
219 	}
220 }
221 
crypto_aegis128l_decrypt_chunk(struct aegis_state * state,u8 * dst,const u8 * src,unsigned int size)222 static void crypto_aegis128l_decrypt_chunk(struct aegis_state *state, u8 *dst,
223 					   const u8 *src, unsigned int size)
224 {
225 	union aegis_chunk tmp;
226 	union aegis_block *tmp0 = &tmp.blocks[0];
227 	union aegis_block *tmp1 = &tmp.blocks[1];
228 
229 	if (AEGIS_ALIGNED(src) && AEGIS_ALIGNED(dst)) {
230 		while (size >= AEGIS128L_CHUNK_SIZE) {
231 			union aegis_chunk *dst_blk =
232 					(union aegis_chunk *)dst;
233 			const union aegis_chunk *src_blk =
234 					(const union aegis_chunk *)src;
235 
236 			*tmp0 = state->blocks[2];
237 			crypto_aegis_block_and(tmp0, &state->blocks[3]);
238 			crypto_aegis_block_xor(tmp0, &state->blocks[6]);
239 			crypto_aegis_block_xor(tmp0, &state->blocks[1]);
240 			crypto_aegis_block_xor(tmp0, &src_blk->blocks[0]);
241 
242 			*tmp1 = state->blocks[6];
243 			crypto_aegis_block_and(tmp1, &state->blocks[7]);
244 			crypto_aegis_block_xor(tmp1, &state->blocks[5]);
245 			crypto_aegis_block_xor(tmp1, &state->blocks[2]);
246 			crypto_aegis_block_xor(tmp1, &src_blk->blocks[1]);
247 
248 			crypto_aegis128l_update_a(state, &tmp);
249 
250 			*dst_blk = tmp;
251 
252 			size -= AEGIS128L_CHUNK_SIZE;
253 			src += AEGIS128L_CHUNK_SIZE;
254 			dst += AEGIS128L_CHUNK_SIZE;
255 		}
256 	} else {
257 		while (size >= AEGIS128L_CHUNK_SIZE) {
258 			*tmp0 = state->blocks[2];
259 			crypto_aegis_block_and(tmp0, &state->blocks[3]);
260 			crypto_aegis_block_xor(tmp0, &state->blocks[6]);
261 			crypto_aegis_block_xor(tmp0, &state->blocks[1]);
262 			crypto_xor(tmp0->bytes, src + 0 * AEGIS_BLOCK_SIZE,
263 				   AEGIS_BLOCK_SIZE);
264 
265 			*tmp1 = state->blocks[6];
266 			crypto_aegis_block_and(tmp1, &state->blocks[7]);
267 			crypto_aegis_block_xor(tmp1, &state->blocks[5]);
268 			crypto_aegis_block_xor(tmp1, &state->blocks[2]);
269 			crypto_xor(tmp1->bytes, src + 1 * AEGIS_BLOCK_SIZE,
270 				   AEGIS_BLOCK_SIZE);
271 
272 			crypto_aegis128l_update_a(state, &tmp);
273 
274 			memcpy(dst, tmp.bytes, AEGIS128L_CHUNK_SIZE);
275 
276 			size -= AEGIS128L_CHUNK_SIZE;
277 			src += AEGIS128L_CHUNK_SIZE;
278 			dst += AEGIS128L_CHUNK_SIZE;
279 		}
280 	}
281 
282 	if (size > 0) {
283 		union aegis_chunk msg = {};
284 		memcpy(msg.bytes, src, size);
285 
286 		*tmp0 = state->blocks[2];
287 		crypto_aegis_block_and(tmp0, &state->blocks[3]);
288 		crypto_aegis_block_xor(tmp0, &state->blocks[6]);
289 		crypto_aegis_block_xor(tmp0, &state->blocks[1]);
290 		crypto_aegis_block_xor(&msg.blocks[0], tmp0);
291 
292 		*tmp1 = state->blocks[6];
293 		crypto_aegis_block_and(tmp1, &state->blocks[7]);
294 		crypto_aegis_block_xor(tmp1, &state->blocks[5]);
295 		crypto_aegis_block_xor(tmp1, &state->blocks[2]);
296 		crypto_aegis_block_xor(&msg.blocks[1], tmp1);
297 
298 		memset(msg.bytes + size, 0, AEGIS128L_CHUNK_SIZE - size);
299 
300 		crypto_aegis128l_update_a(state, &msg);
301 
302 		memcpy(dst, msg.bytes, size);
303 	}
304 }
305 
crypto_aegis128l_process_ad(struct aegis_state * state,struct scatterlist * sg_src,unsigned int assoclen)306 static void crypto_aegis128l_process_ad(struct aegis_state *state,
307 					struct scatterlist *sg_src,
308 					unsigned int assoclen)
309 {
310 	struct scatter_walk walk;
311 	union aegis_chunk buf;
312 	unsigned int pos = 0;
313 
314 	scatterwalk_start(&walk, sg_src);
315 	while (assoclen != 0) {
316 		unsigned int size = scatterwalk_clamp(&walk, assoclen);
317 		unsigned int left = size;
318 		void *mapped = scatterwalk_map(&walk);
319 		const u8 *src = (const u8 *)mapped;
320 
321 		if (pos + size >= AEGIS128L_CHUNK_SIZE) {
322 			if (pos > 0) {
323 				unsigned int fill = AEGIS128L_CHUNK_SIZE - pos;
324 				memcpy(buf.bytes + pos, src, fill);
325 				crypto_aegis128l_update_a(state, &buf);
326 				pos = 0;
327 				left -= fill;
328 				src += fill;
329 			}
330 
331 			crypto_aegis128l_ad(state, src, left);
332 			src += left & ~(AEGIS128L_CHUNK_SIZE - 1);
333 			left &= AEGIS128L_CHUNK_SIZE - 1;
334 		}
335 
336 		memcpy(buf.bytes + pos, src, left);
337 
338 		pos += left;
339 		assoclen -= size;
340 		scatterwalk_unmap(mapped);
341 		scatterwalk_advance(&walk, size);
342 		scatterwalk_done(&walk, 0, assoclen);
343 	}
344 
345 	if (pos > 0) {
346 		memset(buf.bytes + pos, 0, AEGIS128L_CHUNK_SIZE - pos);
347 		crypto_aegis128l_update_a(state, &buf);
348 	}
349 }
350 
crypto_aegis128l_process_crypt(struct aegis_state * state,struct aead_request * req,const struct aegis128l_ops * ops)351 static void crypto_aegis128l_process_crypt(struct aegis_state *state,
352 					   struct aead_request *req,
353 					   const struct aegis128l_ops *ops)
354 {
355 	struct skcipher_walk walk;
356 	u8 *src, *dst;
357 	unsigned int chunksize;
358 
359 	ops->skcipher_walk_init(&walk, req, false);
360 
361 	while (walk.nbytes) {
362 		src = walk.src.virt.addr;
363 		dst = walk.dst.virt.addr;
364 		chunksize = walk.nbytes;
365 
366 		ops->crypt_chunk(state, dst, src, chunksize);
367 
368 		skcipher_walk_done(&walk, 0);
369 	}
370 }
371 
crypto_aegis128l_final(struct aegis_state * state,union aegis_block * tag_xor,u64 assoclen,u64 cryptlen)372 static void crypto_aegis128l_final(struct aegis_state *state,
373 				   union aegis_block *tag_xor,
374 				   u64 assoclen, u64 cryptlen)
375 {
376 	u64 assocbits = assoclen * 8;
377 	u64 cryptbits = cryptlen * 8;
378 
379 	union aegis_chunk tmp;
380 	unsigned int i;
381 
382 	tmp.blocks[0].words64[0] = cpu_to_le64(assocbits);
383 	tmp.blocks[0].words64[1] = cpu_to_le64(cryptbits);
384 
385 	crypto_aegis_block_xor(&tmp.blocks[0], &state->blocks[2]);
386 
387 	tmp.blocks[1] = tmp.blocks[0];
388 	for (i = 0; i < 7; i++)
389 		crypto_aegis128l_update_a(state, &tmp);
390 
391 	for (i = 0; i < 7; i++)
392 		crypto_aegis_block_xor(tag_xor, &state->blocks[i]);
393 }
394 
crypto_aegis128l_setkey(struct crypto_aead * aead,const u8 * key,unsigned int keylen)395 static int crypto_aegis128l_setkey(struct crypto_aead *aead, const u8 *key,
396 				   unsigned int keylen)
397 {
398 	struct aegis_ctx *ctx = crypto_aead_ctx(aead);
399 
400 	if (keylen != AEGIS128L_KEY_SIZE) {
401 		crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN);
402 		return -EINVAL;
403 	}
404 
405 	memcpy(ctx->key.bytes, key, AEGIS128L_KEY_SIZE);
406 	return 0;
407 }
408 
crypto_aegis128l_setauthsize(struct crypto_aead * tfm,unsigned int authsize)409 static int crypto_aegis128l_setauthsize(struct crypto_aead *tfm,
410 					unsigned int authsize)
411 {
412 	if (authsize > AEGIS128L_MAX_AUTH_SIZE)
413 		return -EINVAL;
414 	if (authsize < AEGIS128L_MIN_AUTH_SIZE)
415 		return -EINVAL;
416 	return 0;
417 }
418 
crypto_aegis128l_crypt(struct aead_request * req,union aegis_block * tag_xor,unsigned int cryptlen,const struct aegis128l_ops * ops)419 static void crypto_aegis128l_crypt(struct aead_request *req,
420 				   union aegis_block *tag_xor,
421 				   unsigned int cryptlen,
422 				   const struct aegis128l_ops *ops)
423 {
424 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
425 	struct aegis_ctx *ctx = crypto_aead_ctx(tfm);
426 	struct aegis_state state;
427 
428 	crypto_aegis128l_init(&state, &ctx->key, req->iv);
429 	crypto_aegis128l_process_ad(&state, req->src, req->assoclen);
430 	crypto_aegis128l_process_crypt(&state, req, ops);
431 	crypto_aegis128l_final(&state, tag_xor, req->assoclen, cryptlen);
432 }
433 
crypto_aegis128l_encrypt(struct aead_request * req)434 static int crypto_aegis128l_encrypt(struct aead_request *req)
435 {
436 	static const struct aegis128l_ops ops = {
437 		.skcipher_walk_init = skcipher_walk_aead_encrypt,
438 		.crypt_chunk = crypto_aegis128l_encrypt_chunk,
439 	};
440 
441 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
442 	union aegis_block tag = {};
443 	unsigned int authsize = crypto_aead_authsize(tfm);
444 	unsigned int cryptlen = req->cryptlen;
445 
446 	crypto_aegis128l_crypt(req, &tag, cryptlen, &ops);
447 
448 	scatterwalk_map_and_copy(tag.bytes, req->dst, req->assoclen + cryptlen,
449 				 authsize, 1);
450 	return 0;
451 }
452 
crypto_aegis128l_decrypt(struct aead_request * req)453 static int crypto_aegis128l_decrypt(struct aead_request *req)
454 {
455 	static const struct aegis128l_ops ops = {
456 		.skcipher_walk_init = skcipher_walk_aead_decrypt,
457 		.crypt_chunk = crypto_aegis128l_decrypt_chunk,
458 	};
459 	static const u8 zeros[AEGIS128L_MAX_AUTH_SIZE] = {};
460 
461 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
462 	union aegis_block tag;
463 	unsigned int authsize = crypto_aead_authsize(tfm);
464 	unsigned int cryptlen = req->cryptlen - authsize;
465 
466 	scatterwalk_map_and_copy(tag.bytes, req->src, req->assoclen + cryptlen,
467 				 authsize, 0);
468 
469 	crypto_aegis128l_crypt(req, &tag, cryptlen, &ops);
470 
471 	return crypto_memneq(tag.bytes, zeros, authsize) ? -EBADMSG : 0;
472 }
473 
crypto_aegis128l_init_tfm(struct crypto_aead * tfm)474 static int crypto_aegis128l_init_tfm(struct crypto_aead *tfm)
475 {
476 	return 0;
477 }
478 
crypto_aegis128l_exit_tfm(struct crypto_aead * tfm)479 static void crypto_aegis128l_exit_tfm(struct crypto_aead *tfm)
480 {
481 }
482 
483 static struct aead_alg crypto_aegis128l_alg = {
484 	.setkey = crypto_aegis128l_setkey,
485 	.setauthsize = crypto_aegis128l_setauthsize,
486 	.encrypt = crypto_aegis128l_encrypt,
487 	.decrypt = crypto_aegis128l_decrypt,
488 	.init = crypto_aegis128l_init_tfm,
489 	.exit = crypto_aegis128l_exit_tfm,
490 
491 	.ivsize = AEGIS128L_NONCE_SIZE,
492 	.maxauthsize = AEGIS128L_MAX_AUTH_SIZE,
493 	.chunksize = AEGIS128L_CHUNK_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 = "aegis128l",
503 		.cra_driver_name = "aegis128l-generic",
504 
505 		.cra_module = THIS_MODULE,
506 	}
507 };
508 
crypto_aegis128l_module_init(void)509 static int __init crypto_aegis128l_module_init(void)
510 {
511 	return crypto_register_aead(&crypto_aegis128l_alg);
512 }
513 
crypto_aegis128l_module_exit(void)514 static void __exit crypto_aegis128l_module_exit(void)
515 {
516 	crypto_unregister_aead(&crypto_aegis128l_alg);
517 }
518 
519 module_init(crypto_aegis128l_module_init);
520 module_exit(crypto_aegis128l_module_exit);
521 
522 MODULE_LICENSE("GPL");
523 MODULE_AUTHOR("Ondrej Mosnacek <omosnacek@gmail.com>");
524 MODULE_DESCRIPTION("AEGIS-128L AEAD algorithm");
525 MODULE_ALIAS_CRYPTO("aegis128l");
526 MODULE_ALIAS_CRYPTO("aegis128l-generic");
527