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