162306a36Sopenharmony_ci/* FCrypt encryption algorithm
262306a36Sopenharmony_ci *
362306a36Sopenharmony_ci * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
462306a36Sopenharmony_ci * Written by David Howells (dhowells@redhat.com)
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * This program is free software; you can redistribute it and/or
762306a36Sopenharmony_ci * modify it under the terms of the GNU General Public License
862306a36Sopenharmony_ci * as published by the Free Software Foundation; either version
962306a36Sopenharmony_ci * 2 of the License, or (at your option) any later version.
1062306a36Sopenharmony_ci *
1162306a36Sopenharmony_ci * Based on code:
1262306a36Sopenharmony_ci *
1362306a36Sopenharmony_ci * Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan
1462306a36Sopenharmony_ci * (Royal Institute of Technology, Stockholm, Sweden).
1562306a36Sopenharmony_ci * All rights reserved.
1662306a36Sopenharmony_ci *
1762306a36Sopenharmony_ci * Redistribution and use in source and binary forms, with or without
1862306a36Sopenharmony_ci * modification, are permitted provided that the following conditions
1962306a36Sopenharmony_ci * are met:
2062306a36Sopenharmony_ci *
2162306a36Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright
2262306a36Sopenharmony_ci *    notice, this list of conditions and the following disclaimer.
2362306a36Sopenharmony_ci *
2462306a36Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright
2562306a36Sopenharmony_ci *    notice, this list of conditions and the following disclaimer in the
2662306a36Sopenharmony_ci *    documentation and/or other materials provided with the distribution.
2762306a36Sopenharmony_ci *
2862306a36Sopenharmony_ci * 3. Neither the name of the Institute nor the names of its contributors
2962306a36Sopenharmony_ci *    may be used to endorse or promote products derived from this software
3062306a36Sopenharmony_ci *    without specific prior written permission.
3162306a36Sopenharmony_ci *
3262306a36Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
3362306a36Sopenharmony_ci * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3462306a36Sopenharmony_ci * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3562306a36Sopenharmony_ci * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
3662306a36Sopenharmony_ci * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3762306a36Sopenharmony_ci * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3862306a36Sopenharmony_ci * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3962306a36Sopenharmony_ci * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4062306a36Sopenharmony_ci * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4162306a36Sopenharmony_ci * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4262306a36Sopenharmony_ci * SUCH DAMAGE.
4362306a36Sopenharmony_ci */
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci#include <asm/byteorder.h>
4662306a36Sopenharmony_ci#include <crypto/algapi.h>
4762306a36Sopenharmony_ci#include <linux/bitops.h>
4862306a36Sopenharmony_ci#include <linux/init.h>
4962306a36Sopenharmony_ci#include <linux/module.h>
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci#define ROUNDS 16
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_cistruct fcrypt_ctx {
5462306a36Sopenharmony_ci	__be32 sched[ROUNDS];
5562306a36Sopenharmony_ci};
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci/* Rotate right two 32 bit numbers as a 56 bit number */
5862306a36Sopenharmony_ci#define ror56(hi, lo, n)					\
5962306a36Sopenharmony_cido {								\
6062306a36Sopenharmony_ci	u32 t = lo & ((1 << n) - 1);				\
6162306a36Sopenharmony_ci	lo = (lo >> n) | ((hi & ((1 << n) - 1)) << (32 - n));	\
6262306a36Sopenharmony_ci	hi = (hi >> n) | (t << (24-n));				\
6362306a36Sopenharmony_ci} while (0)
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci/* Rotate right one 64 bit number as a 56 bit number */
6662306a36Sopenharmony_ci#define ror56_64(k, n) (k = (k >> n) | ((k & ((1 << n) - 1)) << (56 - n)))
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci/*
6962306a36Sopenharmony_ci * Sboxes for Feistel network derived from
7062306a36Sopenharmony_ci * /afs/transarc.com/public/afsps/afs.rel31b.export-src/rxkad/sboxes.h
7162306a36Sopenharmony_ci */
7262306a36Sopenharmony_ci#undef Z
7362306a36Sopenharmony_ci#define Z(x) cpu_to_be32(x << 3)
7462306a36Sopenharmony_cistatic const __be32 sbox0[256] = {
7562306a36Sopenharmony_ci	Z(0xea), Z(0x7f), Z(0xb2), Z(0x64), Z(0x9d), Z(0xb0), Z(0xd9), Z(0x11),
7662306a36Sopenharmony_ci	Z(0xcd), Z(0x86), Z(0x86), Z(0x91), Z(0x0a), Z(0xb2), Z(0x93), Z(0x06),
7762306a36Sopenharmony_ci	Z(0x0e), Z(0x06), Z(0xd2), Z(0x65), Z(0x73), Z(0xc5), Z(0x28), Z(0x60),
7862306a36Sopenharmony_ci	Z(0xf2), Z(0x20), Z(0xb5), Z(0x38), Z(0x7e), Z(0xda), Z(0x9f), Z(0xe3),
7962306a36Sopenharmony_ci	Z(0xd2), Z(0xcf), Z(0xc4), Z(0x3c), Z(0x61), Z(0xff), Z(0x4a), Z(0x4a),
8062306a36Sopenharmony_ci	Z(0x35), Z(0xac), Z(0xaa), Z(0x5f), Z(0x2b), Z(0xbb), Z(0xbc), Z(0x53),
8162306a36Sopenharmony_ci	Z(0x4e), Z(0x9d), Z(0x78), Z(0xa3), Z(0xdc), Z(0x09), Z(0x32), Z(0x10),
8262306a36Sopenharmony_ci	Z(0xc6), Z(0x6f), Z(0x66), Z(0xd6), Z(0xab), Z(0xa9), Z(0xaf), Z(0xfd),
8362306a36Sopenharmony_ci	Z(0x3b), Z(0x95), Z(0xe8), Z(0x34), Z(0x9a), Z(0x81), Z(0x72), Z(0x80),
8462306a36Sopenharmony_ci	Z(0x9c), Z(0xf3), Z(0xec), Z(0xda), Z(0x9f), Z(0x26), Z(0x76), Z(0x15),
8562306a36Sopenharmony_ci	Z(0x3e), Z(0x55), Z(0x4d), Z(0xde), Z(0x84), Z(0xee), Z(0xad), Z(0xc7),
8662306a36Sopenharmony_ci	Z(0xf1), Z(0x6b), Z(0x3d), Z(0xd3), Z(0x04), Z(0x49), Z(0xaa), Z(0x24),
8762306a36Sopenharmony_ci	Z(0x0b), Z(0x8a), Z(0x83), Z(0xba), Z(0xfa), Z(0x85), Z(0xa0), Z(0xa8),
8862306a36Sopenharmony_ci	Z(0xb1), Z(0xd4), Z(0x01), Z(0xd8), Z(0x70), Z(0x64), Z(0xf0), Z(0x51),
8962306a36Sopenharmony_ci	Z(0xd2), Z(0xc3), Z(0xa7), Z(0x75), Z(0x8c), Z(0xa5), Z(0x64), Z(0xef),
9062306a36Sopenharmony_ci	Z(0x10), Z(0x4e), Z(0xb7), Z(0xc6), Z(0x61), Z(0x03), Z(0xeb), Z(0x44),
9162306a36Sopenharmony_ci	Z(0x3d), Z(0xe5), Z(0xb3), Z(0x5b), Z(0xae), Z(0xd5), Z(0xad), Z(0x1d),
9262306a36Sopenharmony_ci	Z(0xfa), Z(0x5a), Z(0x1e), Z(0x33), Z(0xab), Z(0x93), Z(0xa2), Z(0xb7),
9362306a36Sopenharmony_ci	Z(0xe7), Z(0xa8), Z(0x45), Z(0xa4), Z(0xcd), Z(0x29), Z(0x63), Z(0x44),
9462306a36Sopenharmony_ci	Z(0xb6), Z(0x69), Z(0x7e), Z(0x2e), Z(0x62), Z(0x03), Z(0xc8), Z(0xe0),
9562306a36Sopenharmony_ci	Z(0x17), Z(0xbb), Z(0xc7), Z(0xf3), Z(0x3f), Z(0x36), Z(0xba), Z(0x71),
9662306a36Sopenharmony_ci	Z(0x8e), Z(0x97), Z(0x65), Z(0x60), Z(0x69), Z(0xb6), Z(0xf6), Z(0xe6),
9762306a36Sopenharmony_ci	Z(0x6e), Z(0xe0), Z(0x81), Z(0x59), Z(0xe8), Z(0xaf), Z(0xdd), Z(0x95),
9862306a36Sopenharmony_ci	Z(0x22), Z(0x99), Z(0xfd), Z(0x63), Z(0x19), Z(0x74), Z(0x61), Z(0xb1),
9962306a36Sopenharmony_ci	Z(0xb6), Z(0x5b), Z(0xae), Z(0x54), Z(0xb3), Z(0x70), Z(0xff), Z(0xc6),
10062306a36Sopenharmony_ci	Z(0x3b), Z(0x3e), Z(0xc1), Z(0xd7), Z(0xe1), Z(0x0e), Z(0x76), Z(0xe5),
10162306a36Sopenharmony_ci	Z(0x36), Z(0x4f), Z(0x59), Z(0xc7), Z(0x08), Z(0x6e), Z(0x82), Z(0xa6),
10262306a36Sopenharmony_ci	Z(0x93), Z(0xc4), Z(0xaa), Z(0x26), Z(0x49), Z(0xe0), Z(0x21), Z(0x64),
10362306a36Sopenharmony_ci	Z(0x07), Z(0x9f), Z(0x64), Z(0x81), Z(0x9c), Z(0xbf), Z(0xf9), Z(0xd1),
10462306a36Sopenharmony_ci	Z(0x43), Z(0xf8), Z(0xb6), Z(0xb9), Z(0xf1), Z(0x24), Z(0x75), Z(0x03),
10562306a36Sopenharmony_ci	Z(0xe4), Z(0xb0), Z(0x99), Z(0x46), Z(0x3d), Z(0xf5), Z(0xd1), Z(0x39),
10662306a36Sopenharmony_ci	Z(0x72), Z(0x12), Z(0xf6), Z(0xba), Z(0x0c), Z(0x0d), Z(0x42), Z(0x2e)
10762306a36Sopenharmony_ci};
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci#undef Z
11062306a36Sopenharmony_ci#define Z(x) cpu_to_be32(((x & 0x1f) << 27) | (x >> 5))
11162306a36Sopenharmony_cistatic const __be32 sbox1[256] = {
11262306a36Sopenharmony_ci	Z(0x77), Z(0x14), Z(0xa6), Z(0xfe), Z(0xb2), Z(0x5e), Z(0x8c), Z(0x3e),
11362306a36Sopenharmony_ci	Z(0x67), Z(0x6c), Z(0xa1), Z(0x0d), Z(0xc2), Z(0xa2), Z(0xc1), Z(0x85),
11462306a36Sopenharmony_ci	Z(0x6c), Z(0x7b), Z(0x67), Z(0xc6), Z(0x23), Z(0xe3), Z(0xf2), Z(0x89),
11562306a36Sopenharmony_ci	Z(0x50), Z(0x9c), Z(0x03), Z(0xb7), Z(0x73), Z(0xe6), Z(0xe1), Z(0x39),
11662306a36Sopenharmony_ci	Z(0x31), Z(0x2c), Z(0x27), Z(0x9f), Z(0xa5), Z(0x69), Z(0x44), Z(0xd6),
11762306a36Sopenharmony_ci	Z(0x23), Z(0x83), Z(0x98), Z(0x7d), Z(0x3c), Z(0xb4), Z(0x2d), Z(0x99),
11862306a36Sopenharmony_ci	Z(0x1c), Z(0x1f), Z(0x8c), Z(0x20), Z(0x03), Z(0x7c), Z(0x5f), Z(0xad),
11962306a36Sopenharmony_ci	Z(0xf4), Z(0xfa), Z(0x95), Z(0xca), Z(0x76), Z(0x44), Z(0xcd), Z(0xb6),
12062306a36Sopenharmony_ci	Z(0xb8), Z(0xa1), Z(0xa1), Z(0xbe), Z(0x9e), Z(0x54), Z(0x8f), Z(0x0b),
12162306a36Sopenharmony_ci	Z(0x16), Z(0x74), Z(0x31), Z(0x8a), Z(0x23), Z(0x17), Z(0x04), Z(0xfa),
12262306a36Sopenharmony_ci	Z(0x79), Z(0x84), Z(0xb1), Z(0xf5), Z(0x13), Z(0xab), Z(0xb5), Z(0x2e),
12362306a36Sopenharmony_ci	Z(0xaa), Z(0x0c), Z(0x60), Z(0x6b), Z(0x5b), Z(0xc4), Z(0x4b), Z(0xbc),
12462306a36Sopenharmony_ci	Z(0xe2), Z(0xaf), Z(0x45), Z(0x73), Z(0xfa), Z(0xc9), Z(0x49), Z(0xcd),
12562306a36Sopenharmony_ci	Z(0x00), Z(0x92), Z(0x7d), Z(0x97), Z(0x7a), Z(0x18), Z(0x60), Z(0x3d),
12662306a36Sopenharmony_ci	Z(0xcf), Z(0x5b), Z(0xde), Z(0xc6), Z(0xe2), Z(0xe6), Z(0xbb), Z(0x8b),
12762306a36Sopenharmony_ci	Z(0x06), Z(0xda), Z(0x08), Z(0x15), Z(0x1b), Z(0x88), Z(0x6a), Z(0x17),
12862306a36Sopenharmony_ci	Z(0x89), Z(0xd0), Z(0xa9), Z(0xc1), Z(0xc9), Z(0x70), Z(0x6b), Z(0xe5),
12962306a36Sopenharmony_ci	Z(0x43), Z(0xf4), Z(0x68), Z(0xc8), Z(0xd3), Z(0x84), Z(0x28), Z(0x0a),
13062306a36Sopenharmony_ci	Z(0x52), Z(0x66), Z(0xa3), Z(0xca), Z(0xf2), Z(0xe3), Z(0x7f), Z(0x7a),
13162306a36Sopenharmony_ci	Z(0x31), Z(0xf7), Z(0x88), Z(0x94), Z(0x5e), Z(0x9c), Z(0x63), Z(0xd5),
13262306a36Sopenharmony_ci	Z(0x24), Z(0x66), Z(0xfc), Z(0xb3), Z(0x57), Z(0x25), Z(0xbe), Z(0x89),
13362306a36Sopenharmony_ci	Z(0x44), Z(0xc4), Z(0xe0), Z(0x8f), Z(0x23), Z(0x3c), Z(0x12), Z(0x52),
13462306a36Sopenharmony_ci	Z(0xf5), Z(0x1e), Z(0xf4), Z(0xcb), Z(0x18), Z(0x33), Z(0x1f), Z(0xf8),
13562306a36Sopenharmony_ci	Z(0x69), Z(0x10), Z(0x9d), Z(0xd3), Z(0xf7), Z(0x28), Z(0xf8), Z(0x30),
13662306a36Sopenharmony_ci	Z(0x05), Z(0x5e), Z(0x32), Z(0xc0), Z(0xd5), Z(0x19), Z(0xbd), Z(0x45),
13762306a36Sopenharmony_ci	Z(0x8b), Z(0x5b), Z(0xfd), Z(0xbc), Z(0xe2), Z(0x5c), Z(0xa9), Z(0x96),
13862306a36Sopenharmony_ci	Z(0xef), Z(0x70), Z(0xcf), Z(0xc2), Z(0x2a), Z(0xb3), Z(0x61), Z(0xad),
13962306a36Sopenharmony_ci	Z(0x80), Z(0x48), Z(0x81), Z(0xb7), Z(0x1d), Z(0x43), Z(0xd9), Z(0xd7),
14062306a36Sopenharmony_ci	Z(0x45), Z(0xf0), Z(0xd8), Z(0x8a), Z(0x59), Z(0x7c), Z(0x57), Z(0xc1),
14162306a36Sopenharmony_ci	Z(0x79), Z(0xc7), Z(0x34), Z(0xd6), Z(0x43), Z(0xdf), Z(0xe4), Z(0x78),
14262306a36Sopenharmony_ci	Z(0x16), Z(0x06), Z(0xda), Z(0x92), Z(0x76), Z(0x51), Z(0xe1), Z(0xd4),
14362306a36Sopenharmony_ci	Z(0x70), Z(0x03), Z(0xe0), Z(0x2f), Z(0x96), Z(0x91), Z(0x82), Z(0x80)
14462306a36Sopenharmony_ci};
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci#undef Z
14762306a36Sopenharmony_ci#define Z(x) cpu_to_be32(x << 11)
14862306a36Sopenharmony_cistatic const __be32 sbox2[256] = {
14962306a36Sopenharmony_ci	Z(0xf0), Z(0x37), Z(0x24), Z(0x53), Z(0x2a), Z(0x03), Z(0x83), Z(0x86),
15062306a36Sopenharmony_ci	Z(0xd1), Z(0xec), Z(0x50), Z(0xf0), Z(0x42), Z(0x78), Z(0x2f), Z(0x6d),
15162306a36Sopenharmony_ci	Z(0xbf), Z(0x80), Z(0x87), Z(0x27), Z(0x95), Z(0xe2), Z(0xc5), Z(0x5d),
15262306a36Sopenharmony_ci	Z(0xf9), Z(0x6f), Z(0xdb), Z(0xb4), Z(0x65), Z(0x6e), Z(0xe7), Z(0x24),
15362306a36Sopenharmony_ci	Z(0xc8), Z(0x1a), Z(0xbb), Z(0x49), Z(0xb5), Z(0x0a), Z(0x7d), Z(0xb9),
15462306a36Sopenharmony_ci	Z(0xe8), Z(0xdc), Z(0xb7), Z(0xd9), Z(0x45), Z(0x20), Z(0x1b), Z(0xce),
15562306a36Sopenharmony_ci	Z(0x59), Z(0x9d), Z(0x6b), Z(0xbd), Z(0x0e), Z(0x8f), Z(0xa3), Z(0xa9),
15662306a36Sopenharmony_ci	Z(0xbc), Z(0x74), Z(0xa6), Z(0xf6), Z(0x7f), Z(0x5f), Z(0xb1), Z(0x68),
15762306a36Sopenharmony_ci	Z(0x84), Z(0xbc), Z(0xa9), Z(0xfd), Z(0x55), Z(0x50), Z(0xe9), Z(0xb6),
15862306a36Sopenharmony_ci	Z(0x13), Z(0x5e), Z(0x07), Z(0xb8), Z(0x95), Z(0x02), Z(0xc0), Z(0xd0),
15962306a36Sopenharmony_ci	Z(0x6a), Z(0x1a), Z(0x85), Z(0xbd), Z(0xb6), Z(0xfd), Z(0xfe), Z(0x17),
16062306a36Sopenharmony_ci	Z(0x3f), Z(0x09), Z(0xa3), Z(0x8d), Z(0xfb), Z(0xed), Z(0xda), Z(0x1d),
16162306a36Sopenharmony_ci	Z(0x6d), Z(0x1c), Z(0x6c), Z(0x01), Z(0x5a), Z(0xe5), Z(0x71), Z(0x3e),
16262306a36Sopenharmony_ci	Z(0x8b), Z(0x6b), Z(0xbe), Z(0x29), Z(0xeb), Z(0x12), Z(0x19), Z(0x34),
16362306a36Sopenharmony_ci	Z(0xcd), Z(0xb3), Z(0xbd), Z(0x35), Z(0xea), Z(0x4b), Z(0xd5), Z(0xae),
16462306a36Sopenharmony_ci	Z(0x2a), Z(0x79), Z(0x5a), Z(0xa5), Z(0x32), Z(0x12), Z(0x7b), Z(0xdc),
16562306a36Sopenharmony_ci	Z(0x2c), Z(0xd0), Z(0x22), Z(0x4b), Z(0xb1), Z(0x85), Z(0x59), Z(0x80),
16662306a36Sopenharmony_ci	Z(0xc0), Z(0x30), Z(0x9f), Z(0x73), Z(0xd3), Z(0x14), Z(0x48), Z(0x40),
16762306a36Sopenharmony_ci	Z(0x07), Z(0x2d), Z(0x8f), Z(0x80), Z(0x0f), Z(0xce), Z(0x0b), Z(0x5e),
16862306a36Sopenharmony_ci	Z(0xb7), Z(0x5e), Z(0xac), Z(0x24), Z(0x94), Z(0x4a), Z(0x18), Z(0x15),
16962306a36Sopenharmony_ci	Z(0x05), Z(0xe8), Z(0x02), Z(0x77), Z(0xa9), Z(0xc7), Z(0x40), Z(0x45),
17062306a36Sopenharmony_ci	Z(0x89), Z(0xd1), Z(0xea), Z(0xde), Z(0x0c), Z(0x79), Z(0x2a), Z(0x99),
17162306a36Sopenharmony_ci	Z(0x6c), Z(0x3e), Z(0x95), Z(0xdd), Z(0x8c), Z(0x7d), Z(0xad), Z(0x6f),
17262306a36Sopenharmony_ci	Z(0xdc), Z(0xff), Z(0xfd), Z(0x62), Z(0x47), Z(0xb3), Z(0x21), Z(0x8a),
17362306a36Sopenharmony_ci	Z(0xec), Z(0x8e), Z(0x19), Z(0x18), Z(0xb4), Z(0x6e), Z(0x3d), Z(0xfd),
17462306a36Sopenharmony_ci	Z(0x74), Z(0x54), Z(0x1e), Z(0x04), Z(0x85), Z(0xd8), Z(0xbc), Z(0x1f),
17562306a36Sopenharmony_ci	Z(0x56), Z(0xe7), Z(0x3a), Z(0x56), Z(0x67), Z(0xd6), Z(0xc8), Z(0xa5),
17662306a36Sopenharmony_ci	Z(0xf3), Z(0x8e), Z(0xde), Z(0xae), Z(0x37), Z(0x49), Z(0xb7), Z(0xfa),
17762306a36Sopenharmony_ci	Z(0xc8), Z(0xf4), Z(0x1f), Z(0xe0), Z(0x2a), Z(0x9b), Z(0x15), Z(0xd1),
17862306a36Sopenharmony_ci	Z(0x34), Z(0x0e), Z(0xb5), Z(0xe0), Z(0x44), Z(0x78), Z(0x84), Z(0x59),
17962306a36Sopenharmony_ci	Z(0x56), Z(0x68), Z(0x77), Z(0xa5), Z(0x14), Z(0x06), Z(0xf5), Z(0x2f),
18062306a36Sopenharmony_ci	Z(0x8c), Z(0x8a), Z(0x73), Z(0x80), Z(0x76), Z(0xb4), Z(0x10), Z(0x86)
18162306a36Sopenharmony_ci};
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci#undef Z
18462306a36Sopenharmony_ci#define Z(x) cpu_to_be32(x << 19)
18562306a36Sopenharmony_cistatic const __be32 sbox3[256] = {
18662306a36Sopenharmony_ci	Z(0xa9), Z(0x2a), Z(0x48), Z(0x51), Z(0x84), Z(0x7e), Z(0x49), Z(0xe2),
18762306a36Sopenharmony_ci	Z(0xb5), Z(0xb7), Z(0x42), Z(0x33), Z(0x7d), Z(0x5d), Z(0xa6), Z(0x12),
18862306a36Sopenharmony_ci	Z(0x44), Z(0x48), Z(0x6d), Z(0x28), Z(0xaa), Z(0x20), Z(0x6d), Z(0x57),
18962306a36Sopenharmony_ci	Z(0xd6), Z(0x6b), Z(0x5d), Z(0x72), Z(0xf0), Z(0x92), Z(0x5a), Z(0x1b),
19062306a36Sopenharmony_ci	Z(0x53), Z(0x80), Z(0x24), Z(0x70), Z(0x9a), Z(0xcc), Z(0xa7), Z(0x66),
19162306a36Sopenharmony_ci	Z(0xa1), Z(0x01), Z(0xa5), Z(0x41), Z(0x97), Z(0x41), Z(0x31), Z(0x82),
19262306a36Sopenharmony_ci	Z(0xf1), Z(0x14), Z(0xcf), Z(0x53), Z(0x0d), Z(0xa0), Z(0x10), Z(0xcc),
19362306a36Sopenharmony_ci	Z(0x2a), Z(0x7d), Z(0xd2), Z(0xbf), Z(0x4b), Z(0x1a), Z(0xdb), Z(0x16),
19462306a36Sopenharmony_ci	Z(0x47), Z(0xf6), Z(0x51), Z(0x36), Z(0xed), Z(0xf3), Z(0xb9), Z(0x1a),
19562306a36Sopenharmony_ci	Z(0xa7), Z(0xdf), Z(0x29), Z(0x43), Z(0x01), Z(0x54), Z(0x70), Z(0xa4),
19662306a36Sopenharmony_ci	Z(0xbf), Z(0xd4), Z(0x0b), Z(0x53), Z(0x44), Z(0x60), Z(0x9e), Z(0x23),
19762306a36Sopenharmony_ci	Z(0xa1), Z(0x18), Z(0x68), Z(0x4f), Z(0xf0), Z(0x2f), Z(0x82), Z(0xc2),
19862306a36Sopenharmony_ci	Z(0x2a), Z(0x41), Z(0xb2), Z(0x42), Z(0x0c), Z(0xed), Z(0x0c), Z(0x1d),
19962306a36Sopenharmony_ci	Z(0x13), Z(0x3a), Z(0x3c), Z(0x6e), Z(0x35), Z(0xdc), Z(0x60), Z(0x65),
20062306a36Sopenharmony_ci	Z(0x85), Z(0xe9), Z(0x64), Z(0x02), Z(0x9a), Z(0x3f), Z(0x9f), Z(0x87),
20162306a36Sopenharmony_ci	Z(0x96), Z(0xdf), Z(0xbe), Z(0xf2), Z(0xcb), Z(0xe5), Z(0x6c), Z(0xd4),
20262306a36Sopenharmony_ci	Z(0x5a), Z(0x83), Z(0xbf), Z(0x92), Z(0x1b), Z(0x94), Z(0x00), Z(0x42),
20362306a36Sopenharmony_ci	Z(0xcf), Z(0x4b), Z(0x00), Z(0x75), Z(0xba), Z(0x8f), Z(0x76), Z(0x5f),
20462306a36Sopenharmony_ci	Z(0x5d), Z(0x3a), Z(0x4d), Z(0x09), Z(0x12), Z(0x08), Z(0x38), Z(0x95),
20562306a36Sopenharmony_ci	Z(0x17), Z(0xe4), Z(0x01), Z(0x1d), Z(0x4c), Z(0xa9), Z(0xcc), Z(0x85),
20662306a36Sopenharmony_ci	Z(0x82), Z(0x4c), Z(0x9d), Z(0x2f), Z(0x3b), Z(0x66), Z(0xa1), Z(0x34),
20762306a36Sopenharmony_ci	Z(0x10), Z(0xcd), Z(0x59), Z(0x89), Z(0xa5), Z(0x31), Z(0xcf), Z(0x05),
20862306a36Sopenharmony_ci	Z(0xc8), Z(0x84), Z(0xfa), Z(0xc7), Z(0xba), Z(0x4e), Z(0x8b), Z(0x1a),
20962306a36Sopenharmony_ci	Z(0x19), Z(0xf1), Z(0xa1), Z(0x3b), Z(0x18), Z(0x12), Z(0x17), Z(0xb0),
21062306a36Sopenharmony_ci	Z(0x98), Z(0x8d), Z(0x0b), Z(0x23), Z(0xc3), Z(0x3a), Z(0x2d), Z(0x20),
21162306a36Sopenharmony_ci	Z(0xdf), Z(0x13), Z(0xa0), Z(0xa8), Z(0x4c), Z(0x0d), Z(0x6c), Z(0x2f),
21262306a36Sopenharmony_ci	Z(0x47), Z(0x13), Z(0x13), Z(0x52), Z(0x1f), Z(0x2d), Z(0xf5), Z(0x79),
21362306a36Sopenharmony_ci	Z(0x3d), Z(0xa2), Z(0x54), Z(0xbd), Z(0x69), Z(0xc8), Z(0x6b), Z(0xf3),
21462306a36Sopenharmony_ci	Z(0x05), Z(0x28), Z(0xf1), Z(0x16), Z(0x46), Z(0x40), Z(0xb0), Z(0x11),
21562306a36Sopenharmony_ci	Z(0xd3), Z(0xb7), Z(0x95), Z(0x49), Z(0xcf), Z(0xc3), Z(0x1d), Z(0x8f),
21662306a36Sopenharmony_ci	Z(0xd8), Z(0xe1), Z(0x73), Z(0xdb), Z(0xad), Z(0xc8), Z(0xc9), Z(0xa9),
21762306a36Sopenharmony_ci	Z(0xa1), Z(0xc2), Z(0xc5), Z(0xe3), Z(0xba), Z(0xfc), Z(0x0e), Z(0x25)
21862306a36Sopenharmony_ci};
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci/*
22162306a36Sopenharmony_ci * This is a 16 round Feistel network with permutation F_ENCRYPT
22262306a36Sopenharmony_ci */
22362306a36Sopenharmony_ci#define F_ENCRYPT(R, L, sched)						\
22462306a36Sopenharmony_cido {									\
22562306a36Sopenharmony_ci	union lc4 { __be32 l; u8 c[4]; } u;				\
22662306a36Sopenharmony_ci	u.l = sched ^ R;						\
22762306a36Sopenharmony_ci	L ^= sbox0[u.c[0]] ^ sbox1[u.c[1]] ^ sbox2[u.c[2]] ^ sbox3[u.c[3]]; \
22862306a36Sopenharmony_ci} while (0)
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci/*
23162306a36Sopenharmony_ci * encryptor
23262306a36Sopenharmony_ci */
23362306a36Sopenharmony_cistatic void fcrypt_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
23462306a36Sopenharmony_ci{
23562306a36Sopenharmony_ci	const struct fcrypt_ctx *ctx = crypto_tfm_ctx(tfm);
23662306a36Sopenharmony_ci	struct {
23762306a36Sopenharmony_ci		__be32 l, r;
23862306a36Sopenharmony_ci	} X;
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci	memcpy(&X, src, sizeof(X));
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_ci	F_ENCRYPT(X.r, X.l, ctx->sched[0x0]);
24362306a36Sopenharmony_ci	F_ENCRYPT(X.l, X.r, ctx->sched[0x1]);
24462306a36Sopenharmony_ci	F_ENCRYPT(X.r, X.l, ctx->sched[0x2]);
24562306a36Sopenharmony_ci	F_ENCRYPT(X.l, X.r, ctx->sched[0x3]);
24662306a36Sopenharmony_ci	F_ENCRYPT(X.r, X.l, ctx->sched[0x4]);
24762306a36Sopenharmony_ci	F_ENCRYPT(X.l, X.r, ctx->sched[0x5]);
24862306a36Sopenharmony_ci	F_ENCRYPT(X.r, X.l, ctx->sched[0x6]);
24962306a36Sopenharmony_ci	F_ENCRYPT(X.l, X.r, ctx->sched[0x7]);
25062306a36Sopenharmony_ci	F_ENCRYPT(X.r, X.l, ctx->sched[0x8]);
25162306a36Sopenharmony_ci	F_ENCRYPT(X.l, X.r, ctx->sched[0x9]);
25262306a36Sopenharmony_ci	F_ENCRYPT(X.r, X.l, ctx->sched[0xa]);
25362306a36Sopenharmony_ci	F_ENCRYPT(X.l, X.r, ctx->sched[0xb]);
25462306a36Sopenharmony_ci	F_ENCRYPT(X.r, X.l, ctx->sched[0xc]);
25562306a36Sopenharmony_ci	F_ENCRYPT(X.l, X.r, ctx->sched[0xd]);
25662306a36Sopenharmony_ci	F_ENCRYPT(X.r, X.l, ctx->sched[0xe]);
25762306a36Sopenharmony_ci	F_ENCRYPT(X.l, X.r, ctx->sched[0xf]);
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci	memcpy(dst, &X, sizeof(X));
26062306a36Sopenharmony_ci}
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci/*
26362306a36Sopenharmony_ci * decryptor
26462306a36Sopenharmony_ci */
26562306a36Sopenharmony_cistatic void fcrypt_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
26662306a36Sopenharmony_ci{
26762306a36Sopenharmony_ci	const struct fcrypt_ctx *ctx = crypto_tfm_ctx(tfm);
26862306a36Sopenharmony_ci	struct {
26962306a36Sopenharmony_ci		__be32 l, r;
27062306a36Sopenharmony_ci	} X;
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci	memcpy(&X, src, sizeof(X));
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci	F_ENCRYPT(X.l, X.r, ctx->sched[0xf]);
27562306a36Sopenharmony_ci	F_ENCRYPT(X.r, X.l, ctx->sched[0xe]);
27662306a36Sopenharmony_ci	F_ENCRYPT(X.l, X.r, ctx->sched[0xd]);
27762306a36Sopenharmony_ci	F_ENCRYPT(X.r, X.l, ctx->sched[0xc]);
27862306a36Sopenharmony_ci	F_ENCRYPT(X.l, X.r, ctx->sched[0xb]);
27962306a36Sopenharmony_ci	F_ENCRYPT(X.r, X.l, ctx->sched[0xa]);
28062306a36Sopenharmony_ci	F_ENCRYPT(X.l, X.r, ctx->sched[0x9]);
28162306a36Sopenharmony_ci	F_ENCRYPT(X.r, X.l, ctx->sched[0x8]);
28262306a36Sopenharmony_ci	F_ENCRYPT(X.l, X.r, ctx->sched[0x7]);
28362306a36Sopenharmony_ci	F_ENCRYPT(X.r, X.l, ctx->sched[0x6]);
28462306a36Sopenharmony_ci	F_ENCRYPT(X.l, X.r, ctx->sched[0x5]);
28562306a36Sopenharmony_ci	F_ENCRYPT(X.r, X.l, ctx->sched[0x4]);
28662306a36Sopenharmony_ci	F_ENCRYPT(X.l, X.r, ctx->sched[0x3]);
28762306a36Sopenharmony_ci	F_ENCRYPT(X.r, X.l, ctx->sched[0x2]);
28862306a36Sopenharmony_ci	F_ENCRYPT(X.l, X.r, ctx->sched[0x1]);
28962306a36Sopenharmony_ci	F_ENCRYPT(X.r, X.l, ctx->sched[0x0]);
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci	memcpy(dst, &X, sizeof(X));
29262306a36Sopenharmony_ci}
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci/*
29562306a36Sopenharmony_ci * Generate a key schedule from key, the least significant bit in each key byte
29662306a36Sopenharmony_ci * is parity and shall be ignored. This leaves 56 significant bits in the key
29762306a36Sopenharmony_ci * to scatter over the 16 key schedules. For each schedule extract the low
29862306a36Sopenharmony_ci * order 32 bits and use as schedule, then rotate right by 11 bits.
29962306a36Sopenharmony_ci */
30062306a36Sopenharmony_cistatic int fcrypt_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
30162306a36Sopenharmony_ci{
30262306a36Sopenharmony_ci	struct fcrypt_ctx *ctx = crypto_tfm_ctx(tfm);
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci#if BITS_PER_LONG == 64  /* the 64-bit version can also be used for 32-bit
30562306a36Sopenharmony_ci			  * kernels - it seems to be faster but the code is
30662306a36Sopenharmony_ci			  * larger */
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci	u64 k;	/* k holds all 56 non-parity bits */
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ci	/* discard the parity bits */
31162306a36Sopenharmony_ci	k = (*key++) >> 1;
31262306a36Sopenharmony_ci	k <<= 7;
31362306a36Sopenharmony_ci	k |= (*key++) >> 1;
31462306a36Sopenharmony_ci	k <<= 7;
31562306a36Sopenharmony_ci	k |= (*key++) >> 1;
31662306a36Sopenharmony_ci	k <<= 7;
31762306a36Sopenharmony_ci	k |= (*key++) >> 1;
31862306a36Sopenharmony_ci	k <<= 7;
31962306a36Sopenharmony_ci	k |= (*key++) >> 1;
32062306a36Sopenharmony_ci	k <<= 7;
32162306a36Sopenharmony_ci	k |= (*key++) >> 1;
32262306a36Sopenharmony_ci	k <<= 7;
32362306a36Sopenharmony_ci	k |= (*key++) >> 1;
32462306a36Sopenharmony_ci	k <<= 7;
32562306a36Sopenharmony_ci	k |= (*key) >> 1;
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci	/* Use lower 32 bits for schedule, rotate by 11 each round (16 times) */
32862306a36Sopenharmony_ci	ctx->sched[0x0] = cpu_to_be32(k); ror56_64(k, 11);
32962306a36Sopenharmony_ci	ctx->sched[0x1] = cpu_to_be32(k); ror56_64(k, 11);
33062306a36Sopenharmony_ci	ctx->sched[0x2] = cpu_to_be32(k); ror56_64(k, 11);
33162306a36Sopenharmony_ci	ctx->sched[0x3] = cpu_to_be32(k); ror56_64(k, 11);
33262306a36Sopenharmony_ci	ctx->sched[0x4] = cpu_to_be32(k); ror56_64(k, 11);
33362306a36Sopenharmony_ci	ctx->sched[0x5] = cpu_to_be32(k); ror56_64(k, 11);
33462306a36Sopenharmony_ci	ctx->sched[0x6] = cpu_to_be32(k); ror56_64(k, 11);
33562306a36Sopenharmony_ci	ctx->sched[0x7] = cpu_to_be32(k); ror56_64(k, 11);
33662306a36Sopenharmony_ci	ctx->sched[0x8] = cpu_to_be32(k); ror56_64(k, 11);
33762306a36Sopenharmony_ci	ctx->sched[0x9] = cpu_to_be32(k); ror56_64(k, 11);
33862306a36Sopenharmony_ci	ctx->sched[0xa] = cpu_to_be32(k); ror56_64(k, 11);
33962306a36Sopenharmony_ci	ctx->sched[0xb] = cpu_to_be32(k); ror56_64(k, 11);
34062306a36Sopenharmony_ci	ctx->sched[0xc] = cpu_to_be32(k); ror56_64(k, 11);
34162306a36Sopenharmony_ci	ctx->sched[0xd] = cpu_to_be32(k); ror56_64(k, 11);
34262306a36Sopenharmony_ci	ctx->sched[0xe] = cpu_to_be32(k); ror56_64(k, 11);
34362306a36Sopenharmony_ci	ctx->sched[0xf] = cpu_to_be32(k);
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci	return 0;
34662306a36Sopenharmony_ci#else
34762306a36Sopenharmony_ci	u32 hi, lo;		/* hi is upper 24 bits and lo lower 32, total 56 */
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci	/* discard the parity bits */
35062306a36Sopenharmony_ci	lo = (*key++) >> 1;
35162306a36Sopenharmony_ci	lo <<= 7;
35262306a36Sopenharmony_ci	lo |= (*key++) >> 1;
35362306a36Sopenharmony_ci	lo <<= 7;
35462306a36Sopenharmony_ci	lo |= (*key++) >> 1;
35562306a36Sopenharmony_ci	lo <<= 7;
35662306a36Sopenharmony_ci	lo |= (*key++) >> 1;
35762306a36Sopenharmony_ci	hi = lo >> 4;
35862306a36Sopenharmony_ci	lo &= 0xf;
35962306a36Sopenharmony_ci	lo <<= 7;
36062306a36Sopenharmony_ci	lo |= (*key++) >> 1;
36162306a36Sopenharmony_ci	lo <<= 7;
36262306a36Sopenharmony_ci	lo |= (*key++) >> 1;
36362306a36Sopenharmony_ci	lo <<= 7;
36462306a36Sopenharmony_ci	lo |= (*key++) >> 1;
36562306a36Sopenharmony_ci	lo <<= 7;
36662306a36Sopenharmony_ci	lo |= (*key) >> 1;
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_ci	/* Use lower 32 bits for schedule, rotate by 11 each round (16 times) */
36962306a36Sopenharmony_ci	ctx->sched[0x0] = cpu_to_be32(lo); ror56(hi, lo, 11);
37062306a36Sopenharmony_ci	ctx->sched[0x1] = cpu_to_be32(lo); ror56(hi, lo, 11);
37162306a36Sopenharmony_ci	ctx->sched[0x2] = cpu_to_be32(lo); ror56(hi, lo, 11);
37262306a36Sopenharmony_ci	ctx->sched[0x3] = cpu_to_be32(lo); ror56(hi, lo, 11);
37362306a36Sopenharmony_ci	ctx->sched[0x4] = cpu_to_be32(lo); ror56(hi, lo, 11);
37462306a36Sopenharmony_ci	ctx->sched[0x5] = cpu_to_be32(lo); ror56(hi, lo, 11);
37562306a36Sopenharmony_ci	ctx->sched[0x6] = cpu_to_be32(lo); ror56(hi, lo, 11);
37662306a36Sopenharmony_ci	ctx->sched[0x7] = cpu_to_be32(lo); ror56(hi, lo, 11);
37762306a36Sopenharmony_ci	ctx->sched[0x8] = cpu_to_be32(lo); ror56(hi, lo, 11);
37862306a36Sopenharmony_ci	ctx->sched[0x9] = cpu_to_be32(lo); ror56(hi, lo, 11);
37962306a36Sopenharmony_ci	ctx->sched[0xa] = cpu_to_be32(lo); ror56(hi, lo, 11);
38062306a36Sopenharmony_ci	ctx->sched[0xb] = cpu_to_be32(lo); ror56(hi, lo, 11);
38162306a36Sopenharmony_ci	ctx->sched[0xc] = cpu_to_be32(lo); ror56(hi, lo, 11);
38262306a36Sopenharmony_ci	ctx->sched[0xd] = cpu_to_be32(lo); ror56(hi, lo, 11);
38362306a36Sopenharmony_ci	ctx->sched[0xe] = cpu_to_be32(lo); ror56(hi, lo, 11);
38462306a36Sopenharmony_ci	ctx->sched[0xf] = cpu_to_be32(lo);
38562306a36Sopenharmony_ci	return 0;
38662306a36Sopenharmony_ci#endif
38762306a36Sopenharmony_ci}
38862306a36Sopenharmony_ci
38962306a36Sopenharmony_cistatic struct crypto_alg fcrypt_alg = {
39062306a36Sopenharmony_ci	.cra_name		=	"fcrypt",
39162306a36Sopenharmony_ci	.cra_driver_name	=	"fcrypt-generic",
39262306a36Sopenharmony_ci	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
39362306a36Sopenharmony_ci	.cra_blocksize		=	8,
39462306a36Sopenharmony_ci	.cra_ctxsize		=	sizeof(struct fcrypt_ctx),
39562306a36Sopenharmony_ci	.cra_module		=	THIS_MODULE,
39662306a36Sopenharmony_ci	.cra_u			=	{ .cipher = {
39762306a36Sopenharmony_ci	.cia_min_keysize	=	8,
39862306a36Sopenharmony_ci	.cia_max_keysize	=	8,
39962306a36Sopenharmony_ci	.cia_setkey		=	fcrypt_setkey,
40062306a36Sopenharmony_ci	.cia_encrypt		=	fcrypt_encrypt,
40162306a36Sopenharmony_ci	.cia_decrypt		=	fcrypt_decrypt } }
40262306a36Sopenharmony_ci};
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_cistatic int __init fcrypt_mod_init(void)
40562306a36Sopenharmony_ci{
40662306a36Sopenharmony_ci	return crypto_register_alg(&fcrypt_alg);
40762306a36Sopenharmony_ci}
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_cistatic void __exit fcrypt_mod_fini(void)
41062306a36Sopenharmony_ci{
41162306a36Sopenharmony_ci	crypto_unregister_alg(&fcrypt_alg);
41262306a36Sopenharmony_ci}
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_cisubsys_initcall(fcrypt_mod_init);
41562306a36Sopenharmony_cimodule_exit(fcrypt_mod_fini);
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL");
41862306a36Sopenharmony_ciMODULE_DESCRIPTION("FCrypt Cipher Algorithm");
41962306a36Sopenharmony_ciMODULE_AUTHOR("David Howells <dhowells@redhat.com>");
42062306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("fcrypt");
421