Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.0 526 lines 15 kB view raw
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 33union aegis_chunk { 34 union aegis_block blocks[AEGIS128L_CHUNK_BLOCKS]; 35 u8 bytes[AEGIS128L_CHUNK_SIZE]; 36}; 37 38struct aegis_state { 39 union aegis_block blocks[AEGIS128L_STATE_BLOCKS]; 40}; 41 42struct aegis_ctx { 43 union aegis_block key; 44}; 45 46struct 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 54static 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 66static 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 74static 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 84static 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 116static 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 139static 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 222static 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 306static 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 351static 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 372static 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 395static 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 409static 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 419static 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 434static 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 453static 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 474static int crypto_aegis128l_init_tfm(struct crypto_aead *tfm) 475{ 476 return 0; 477} 478 479static void crypto_aegis128l_exit_tfm(struct crypto_aead *tfm) 480{ 481} 482 483static 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 509static int __init crypto_aegis128l_module_init(void) 510{ 511 return crypto_register_aead(&crypto_aegis128l_alg); 512} 513 514static void __exit crypto_aegis128l_module_exit(void) 515{ 516 crypto_unregister_aead(&crypto_aegis128l_alg); 517} 518 519module_init(crypto_aegis128l_module_init); 520module_exit(crypto_aegis128l_module_exit); 521 522MODULE_LICENSE("GPL"); 523MODULE_AUTHOR("Ondrej Mosnacek <omosnacek@gmail.com>"); 524MODULE_DESCRIPTION("AEGIS-128L AEAD algorithm"); 525MODULE_ALIAS_CRYPTO("aegis128l"); 526MODULE_ALIAS_CRYPTO("aegis128l-generic");