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

crypto: morus - Add generic MORUS AEAD implementations

This patch adds the generic implementation of the MORUS family of AEAD
algorithms (MORUS-640 and MORUS-1280). The original authors of MORUS
are Hongjun Wu and Tao Huang.

At the time of writing, MORUS is one of the finalists in CAESAR, an
open competition intended to select a portfolio of alternatives to
the problematic AES-GCM:

https://competitions.cr.yp.to/caesar-submissions.html
https://competitions.cr.yp.to/round3/morusv2.pdf

Signed-off-by: Ondrej Mosnacek <omosnacek@gmail.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Ondrej Mosnacek and committed by
Herbert Xu
396be41f 1d373d4e

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