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