xref: /openbmc/linux/crypto/fcrypt.c (revision dad3df20)
190831639SDavid Howells /* FCrypt encryption algorithm
290831639SDavid Howells  *
390831639SDavid Howells  * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
490831639SDavid Howells  * Written by David Howells (dhowells@redhat.com)
590831639SDavid Howells  *
690831639SDavid Howells  * This program is free software; you can redistribute it and/or
790831639SDavid Howells  * modify it under the terms of the GNU General Public License
890831639SDavid Howells  * as published by the Free Software Foundation; either version
990831639SDavid Howells  * 2 of the License, or (at your option) any later version.
1090831639SDavid Howells  *
1190831639SDavid Howells  * Based on code:
1290831639SDavid Howells  *
13991d1740SJohn Anthony Kazos Jr  * Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan
1490831639SDavid Howells  * (Royal Institute of Technology, Stockholm, Sweden).
1590831639SDavid Howells  * All rights reserved.
1690831639SDavid Howells  *
1790831639SDavid Howells  * Redistribution and use in source and binary forms, with or without
1890831639SDavid Howells  * modification, are permitted provided that the following conditions
1990831639SDavid Howells  * are met:
2090831639SDavid Howells  *
2190831639SDavid Howells  * 1. Redistributions of source code must retain the above copyright
2290831639SDavid Howells  *    notice, this list of conditions and the following disclaimer.
2390831639SDavid Howells  *
2490831639SDavid Howells  * 2. Redistributions in binary form must reproduce the above copyright
2590831639SDavid Howells  *    notice, this list of conditions and the following disclaimer in the
2690831639SDavid Howells  *    documentation and/or other materials provided with the distribution.
2790831639SDavid Howells  *
2890831639SDavid Howells  * 3. Neither the name of the Institute nor the names of its contributors
2990831639SDavid Howells  *    may be used to endorse or promote products derived from this software
3090831639SDavid Howells  *    without specific prior written permission.
3190831639SDavid Howells  *
3290831639SDavid Howells  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
3390831639SDavid Howells  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3490831639SDavid Howells  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3590831639SDavid Howells  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
3690831639SDavid Howells  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3790831639SDavid Howells  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3890831639SDavid Howells  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3990831639SDavid Howells  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4090831639SDavid Howells  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4190831639SDavid Howells  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4290831639SDavid Howells  * SUCH DAMAGE.
4390831639SDavid Howells  */
4490831639SDavid Howells 
4590831639SDavid Howells #include <asm/byteorder.h>
4690831639SDavid Howells #include <linux/bitops.h>
4790831639SDavid Howells #include <linux/init.h>
4890831639SDavid Howells #include <linux/module.h>
4990831639SDavid Howells #include <linux/crypto.h>
5090831639SDavid Howells 
5190831639SDavid Howells #define ROUNDS 16
5290831639SDavid Howells 
5390831639SDavid Howells struct fcrypt_ctx {
543c50b368SAl Viro 	__be32 sched[ROUNDS];
5590831639SDavid Howells };
5690831639SDavid Howells 
5790831639SDavid Howells /* Rotate right two 32 bit numbers as a 56 bit number */
5890831639SDavid Howells #define ror56(hi, lo, n)					\
5990831639SDavid Howells do {								\
6090831639SDavid Howells 	u32 t = lo & ((1 << n) - 1);				\
6190831639SDavid Howells 	lo = (lo >> n) | ((hi & ((1 << n) - 1)) << (32 - n));	\
6290831639SDavid Howells 	hi = (hi >> n) | (t << (24-n));				\
6390831639SDavid Howells } while(0)
6490831639SDavid Howells 
6590831639SDavid Howells /* Rotate right one 64 bit number as a 56 bit number */
6690831639SDavid Howells #define ror56_64(k, n)						\
6790831639SDavid Howells do {								\
6890831639SDavid Howells 	k = (k >> n) | ((k & ((1 << n) - 1)) << (56 - n));	\
6990831639SDavid Howells } while(0)
7090831639SDavid Howells 
7190831639SDavid Howells /*
7290831639SDavid Howells  * Sboxes for Feistel network derived from
7390831639SDavid Howells  * /afs/transarc.com/public/afsps/afs.rel31b.export-src/rxkad/sboxes.h
7490831639SDavid Howells  */
7590831639SDavid Howells #undef Z
76dad3df20SHarvey Harrison #define Z(x) cpu_to_be32(x << 3)
773c50b368SAl Viro static const __be32 sbox0[256] = {
7890831639SDavid Howells 	Z(0xea), Z(0x7f), Z(0xb2), Z(0x64), Z(0x9d), Z(0xb0), Z(0xd9), Z(0x11),
7990831639SDavid Howells 	Z(0xcd), Z(0x86), Z(0x86), Z(0x91), Z(0x0a), Z(0xb2), Z(0x93), Z(0x06),
8090831639SDavid Howells 	Z(0x0e), Z(0x06), Z(0xd2), Z(0x65), Z(0x73), Z(0xc5), Z(0x28), Z(0x60),
8190831639SDavid Howells 	Z(0xf2), Z(0x20), Z(0xb5), Z(0x38), Z(0x7e), Z(0xda), Z(0x9f), Z(0xe3),
8290831639SDavid Howells 	Z(0xd2), Z(0xcf), Z(0xc4), Z(0x3c), Z(0x61), Z(0xff), Z(0x4a), Z(0x4a),
8390831639SDavid Howells 	Z(0x35), Z(0xac), Z(0xaa), Z(0x5f), Z(0x2b), Z(0xbb), Z(0xbc), Z(0x53),
8490831639SDavid Howells 	Z(0x4e), Z(0x9d), Z(0x78), Z(0xa3), Z(0xdc), Z(0x09), Z(0x32), Z(0x10),
8590831639SDavid Howells 	Z(0xc6), Z(0x6f), Z(0x66), Z(0xd6), Z(0xab), Z(0xa9), Z(0xaf), Z(0xfd),
8690831639SDavid Howells 	Z(0x3b), Z(0x95), Z(0xe8), Z(0x34), Z(0x9a), Z(0x81), Z(0x72), Z(0x80),
8790831639SDavid Howells 	Z(0x9c), Z(0xf3), Z(0xec), Z(0xda), Z(0x9f), Z(0x26), Z(0x76), Z(0x15),
8890831639SDavid Howells 	Z(0x3e), Z(0x55), Z(0x4d), Z(0xde), Z(0x84), Z(0xee), Z(0xad), Z(0xc7),
8990831639SDavid Howells 	Z(0xf1), Z(0x6b), Z(0x3d), Z(0xd3), Z(0x04), Z(0x49), Z(0xaa), Z(0x24),
9090831639SDavid Howells 	Z(0x0b), Z(0x8a), Z(0x83), Z(0xba), Z(0xfa), Z(0x85), Z(0xa0), Z(0xa8),
9190831639SDavid Howells 	Z(0xb1), Z(0xd4), Z(0x01), Z(0xd8), Z(0x70), Z(0x64), Z(0xf0), Z(0x51),
9290831639SDavid Howells 	Z(0xd2), Z(0xc3), Z(0xa7), Z(0x75), Z(0x8c), Z(0xa5), Z(0x64), Z(0xef),
9390831639SDavid Howells 	Z(0x10), Z(0x4e), Z(0xb7), Z(0xc6), Z(0x61), Z(0x03), Z(0xeb), Z(0x44),
9490831639SDavid Howells 	Z(0x3d), Z(0xe5), Z(0xb3), Z(0x5b), Z(0xae), Z(0xd5), Z(0xad), Z(0x1d),
9590831639SDavid Howells 	Z(0xfa), Z(0x5a), Z(0x1e), Z(0x33), Z(0xab), Z(0x93), Z(0xa2), Z(0xb7),
9690831639SDavid Howells 	Z(0xe7), Z(0xa8), Z(0x45), Z(0xa4), Z(0xcd), Z(0x29), Z(0x63), Z(0x44),
9790831639SDavid Howells 	Z(0xb6), Z(0x69), Z(0x7e), Z(0x2e), Z(0x62), Z(0x03), Z(0xc8), Z(0xe0),
9890831639SDavid Howells 	Z(0x17), Z(0xbb), Z(0xc7), Z(0xf3), Z(0x3f), Z(0x36), Z(0xba), Z(0x71),
9990831639SDavid Howells 	Z(0x8e), Z(0x97), Z(0x65), Z(0x60), Z(0x69), Z(0xb6), Z(0xf6), Z(0xe6),
10090831639SDavid Howells 	Z(0x6e), Z(0xe0), Z(0x81), Z(0x59), Z(0xe8), Z(0xaf), Z(0xdd), Z(0x95),
10190831639SDavid Howells 	Z(0x22), Z(0x99), Z(0xfd), Z(0x63), Z(0x19), Z(0x74), Z(0x61), Z(0xb1),
10290831639SDavid Howells 	Z(0xb6), Z(0x5b), Z(0xae), Z(0x54), Z(0xb3), Z(0x70), Z(0xff), Z(0xc6),
10390831639SDavid Howells 	Z(0x3b), Z(0x3e), Z(0xc1), Z(0xd7), Z(0xe1), Z(0x0e), Z(0x76), Z(0xe5),
10490831639SDavid Howells 	Z(0x36), Z(0x4f), Z(0x59), Z(0xc7), Z(0x08), Z(0x6e), Z(0x82), Z(0xa6),
10590831639SDavid Howells 	Z(0x93), Z(0xc4), Z(0xaa), Z(0x26), Z(0x49), Z(0xe0), Z(0x21), Z(0x64),
10690831639SDavid Howells 	Z(0x07), Z(0x9f), Z(0x64), Z(0x81), Z(0x9c), Z(0xbf), Z(0xf9), Z(0xd1),
10790831639SDavid Howells 	Z(0x43), Z(0xf8), Z(0xb6), Z(0xb9), Z(0xf1), Z(0x24), Z(0x75), Z(0x03),
10890831639SDavid Howells 	Z(0xe4), Z(0xb0), Z(0x99), Z(0x46), Z(0x3d), Z(0xf5), Z(0xd1), Z(0x39),
10990831639SDavid Howells 	Z(0x72), Z(0x12), Z(0xf6), Z(0xba), Z(0x0c), Z(0x0d), Z(0x42), Z(0x2e)
11090831639SDavid Howells };
11190831639SDavid Howells 
11290831639SDavid Howells #undef Z
113dad3df20SHarvey Harrison #define Z(x) cpu_to_be32((x << 27) | (x >> 5))
1143c50b368SAl Viro static const __be32 sbox1[256] = {
11590831639SDavid Howells 	Z(0x77), Z(0x14), Z(0xa6), Z(0xfe), Z(0xb2), Z(0x5e), Z(0x8c), Z(0x3e),
11690831639SDavid Howells 	Z(0x67), Z(0x6c), Z(0xa1), Z(0x0d), Z(0xc2), Z(0xa2), Z(0xc1), Z(0x85),
11790831639SDavid Howells 	Z(0x6c), Z(0x7b), Z(0x67), Z(0xc6), Z(0x23), Z(0xe3), Z(0xf2), Z(0x89),
11890831639SDavid Howells 	Z(0x50), Z(0x9c), Z(0x03), Z(0xb7), Z(0x73), Z(0xe6), Z(0xe1), Z(0x39),
11990831639SDavid Howells 	Z(0x31), Z(0x2c), Z(0x27), Z(0x9f), Z(0xa5), Z(0x69), Z(0x44), Z(0xd6),
12090831639SDavid Howells 	Z(0x23), Z(0x83), Z(0x98), Z(0x7d), Z(0x3c), Z(0xb4), Z(0x2d), Z(0x99),
12190831639SDavid Howells 	Z(0x1c), Z(0x1f), Z(0x8c), Z(0x20), Z(0x03), Z(0x7c), Z(0x5f), Z(0xad),
12290831639SDavid Howells 	Z(0xf4), Z(0xfa), Z(0x95), Z(0xca), Z(0x76), Z(0x44), Z(0xcd), Z(0xb6),
12390831639SDavid Howells 	Z(0xb8), Z(0xa1), Z(0xa1), Z(0xbe), Z(0x9e), Z(0x54), Z(0x8f), Z(0x0b),
12490831639SDavid Howells 	Z(0x16), Z(0x74), Z(0x31), Z(0x8a), Z(0x23), Z(0x17), Z(0x04), Z(0xfa),
12590831639SDavid Howells 	Z(0x79), Z(0x84), Z(0xb1), Z(0xf5), Z(0x13), Z(0xab), Z(0xb5), Z(0x2e),
12690831639SDavid Howells 	Z(0xaa), Z(0x0c), Z(0x60), Z(0x6b), Z(0x5b), Z(0xc4), Z(0x4b), Z(0xbc),
12790831639SDavid Howells 	Z(0xe2), Z(0xaf), Z(0x45), Z(0x73), Z(0xfa), Z(0xc9), Z(0x49), Z(0xcd),
12890831639SDavid Howells 	Z(0x00), Z(0x92), Z(0x7d), Z(0x97), Z(0x7a), Z(0x18), Z(0x60), Z(0x3d),
12990831639SDavid Howells 	Z(0xcf), Z(0x5b), Z(0xde), Z(0xc6), Z(0xe2), Z(0xe6), Z(0xbb), Z(0x8b),
13090831639SDavid Howells 	Z(0x06), Z(0xda), Z(0x08), Z(0x15), Z(0x1b), Z(0x88), Z(0x6a), Z(0x17),
13190831639SDavid Howells 	Z(0x89), Z(0xd0), Z(0xa9), Z(0xc1), Z(0xc9), Z(0x70), Z(0x6b), Z(0xe5),
13290831639SDavid Howells 	Z(0x43), Z(0xf4), Z(0x68), Z(0xc8), Z(0xd3), Z(0x84), Z(0x28), Z(0x0a),
13390831639SDavid Howells 	Z(0x52), Z(0x66), Z(0xa3), Z(0xca), Z(0xf2), Z(0xe3), Z(0x7f), Z(0x7a),
13490831639SDavid Howells 	Z(0x31), Z(0xf7), Z(0x88), Z(0x94), Z(0x5e), Z(0x9c), Z(0x63), Z(0xd5),
13590831639SDavid Howells 	Z(0x24), Z(0x66), Z(0xfc), Z(0xb3), Z(0x57), Z(0x25), Z(0xbe), Z(0x89),
13690831639SDavid Howells 	Z(0x44), Z(0xc4), Z(0xe0), Z(0x8f), Z(0x23), Z(0x3c), Z(0x12), Z(0x52),
13790831639SDavid Howells 	Z(0xf5), Z(0x1e), Z(0xf4), Z(0xcb), Z(0x18), Z(0x33), Z(0x1f), Z(0xf8),
13890831639SDavid Howells 	Z(0x69), Z(0x10), Z(0x9d), Z(0xd3), Z(0xf7), Z(0x28), Z(0xf8), Z(0x30),
13990831639SDavid Howells 	Z(0x05), Z(0x5e), Z(0x32), Z(0xc0), Z(0xd5), Z(0x19), Z(0xbd), Z(0x45),
14090831639SDavid Howells 	Z(0x8b), Z(0x5b), Z(0xfd), Z(0xbc), Z(0xe2), Z(0x5c), Z(0xa9), Z(0x96),
14190831639SDavid Howells 	Z(0xef), Z(0x70), Z(0xcf), Z(0xc2), Z(0x2a), Z(0xb3), Z(0x61), Z(0xad),
14290831639SDavid Howells 	Z(0x80), Z(0x48), Z(0x81), Z(0xb7), Z(0x1d), Z(0x43), Z(0xd9), Z(0xd7),
14390831639SDavid Howells 	Z(0x45), Z(0xf0), Z(0xd8), Z(0x8a), Z(0x59), Z(0x7c), Z(0x57), Z(0xc1),
14490831639SDavid Howells 	Z(0x79), Z(0xc7), Z(0x34), Z(0xd6), Z(0x43), Z(0xdf), Z(0xe4), Z(0x78),
14590831639SDavid Howells 	Z(0x16), Z(0x06), Z(0xda), Z(0x92), Z(0x76), Z(0x51), Z(0xe1), Z(0xd4),
14690831639SDavid Howells 	Z(0x70), Z(0x03), Z(0xe0), Z(0x2f), Z(0x96), Z(0x91), Z(0x82), Z(0x80)
14790831639SDavid Howells };
14890831639SDavid Howells 
14990831639SDavid Howells #undef Z
150dad3df20SHarvey Harrison #define Z(x) cpu_to_be32(x << 11)
1513c50b368SAl Viro static const __be32 sbox2[256] = {
15290831639SDavid Howells 	Z(0xf0), Z(0x37), Z(0x24), Z(0x53), Z(0x2a), Z(0x03), Z(0x83), Z(0x86),
15390831639SDavid Howells 	Z(0xd1), Z(0xec), Z(0x50), Z(0xf0), Z(0x42), Z(0x78), Z(0x2f), Z(0x6d),
15490831639SDavid Howells 	Z(0xbf), Z(0x80), Z(0x87), Z(0x27), Z(0x95), Z(0xe2), Z(0xc5), Z(0x5d),
15590831639SDavid Howells 	Z(0xf9), Z(0x6f), Z(0xdb), Z(0xb4), Z(0x65), Z(0x6e), Z(0xe7), Z(0x24),
15690831639SDavid Howells 	Z(0xc8), Z(0x1a), Z(0xbb), Z(0x49), Z(0xb5), Z(0x0a), Z(0x7d), Z(0xb9),
15790831639SDavid Howells 	Z(0xe8), Z(0xdc), Z(0xb7), Z(0xd9), Z(0x45), Z(0x20), Z(0x1b), Z(0xce),
15890831639SDavid Howells 	Z(0x59), Z(0x9d), Z(0x6b), Z(0xbd), Z(0x0e), Z(0x8f), Z(0xa3), Z(0xa9),
15990831639SDavid Howells 	Z(0xbc), Z(0x74), Z(0xa6), Z(0xf6), Z(0x7f), Z(0x5f), Z(0xb1), Z(0x68),
16090831639SDavid Howells 	Z(0x84), Z(0xbc), Z(0xa9), Z(0xfd), Z(0x55), Z(0x50), Z(0xe9), Z(0xb6),
16190831639SDavid Howells 	Z(0x13), Z(0x5e), Z(0x07), Z(0xb8), Z(0x95), Z(0x02), Z(0xc0), Z(0xd0),
16290831639SDavid Howells 	Z(0x6a), Z(0x1a), Z(0x85), Z(0xbd), Z(0xb6), Z(0xfd), Z(0xfe), Z(0x17),
16390831639SDavid Howells 	Z(0x3f), Z(0x09), Z(0xa3), Z(0x8d), Z(0xfb), Z(0xed), Z(0xda), Z(0x1d),
16490831639SDavid Howells 	Z(0x6d), Z(0x1c), Z(0x6c), Z(0x01), Z(0x5a), Z(0xe5), Z(0x71), Z(0x3e),
16590831639SDavid Howells 	Z(0x8b), Z(0x6b), Z(0xbe), Z(0x29), Z(0xeb), Z(0x12), Z(0x19), Z(0x34),
16690831639SDavid Howells 	Z(0xcd), Z(0xb3), Z(0xbd), Z(0x35), Z(0xea), Z(0x4b), Z(0xd5), Z(0xae),
16790831639SDavid Howells 	Z(0x2a), Z(0x79), Z(0x5a), Z(0xa5), Z(0x32), Z(0x12), Z(0x7b), Z(0xdc),
16890831639SDavid Howells 	Z(0x2c), Z(0xd0), Z(0x22), Z(0x4b), Z(0xb1), Z(0x85), Z(0x59), Z(0x80),
16990831639SDavid Howells 	Z(0xc0), Z(0x30), Z(0x9f), Z(0x73), Z(0xd3), Z(0x14), Z(0x48), Z(0x40),
17090831639SDavid Howells 	Z(0x07), Z(0x2d), Z(0x8f), Z(0x80), Z(0x0f), Z(0xce), Z(0x0b), Z(0x5e),
17190831639SDavid Howells 	Z(0xb7), Z(0x5e), Z(0xac), Z(0x24), Z(0x94), Z(0x4a), Z(0x18), Z(0x15),
17290831639SDavid Howells 	Z(0x05), Z(0xe8), Z(0x02), Z(0x77), Z(0xa9), Z(0xc7), Z(0x40), Z(0x45),
17390831639SDavid Howells 	Z(0x89), Z(0xd1), Z(0xea), Z(0xde), Z(0x0c), Z(0x79), Z(0x2a), Z(0x99),
17490831639SDavid Howells 	Z(0x6c), Z(0x3e), Z(0x95), Z(0xdd), Z(0x8c), Z(0x7d), Z(0xad), Z(0x6f),
17590831639SDavid Howells 	Z(0xdc), Z(0xff), Z(0xfd), Z(0x62), Z(0x47), Z(0xb3), Z(0x21), Z(0x8a),
17690831639SDavid Howells 	Z(0xec), Z(0x8e), Z(0x19), Z(0x18), Z(0xb4), Z(0x6e), Z(0x3d), Z(0xfd),
17790831639SDavid Howells 	Z(0x74), Z(0x54), Z(0x1e), Z(0x04), Z(0x85), Z(0xd8), Z(0xbc), Z(0x1f),
17890831639SDavid Howells 	Z(0x56), Z(0xe7), Z(0x3a), Z(0x56), Z(0x67), Z(0xd6), Z(0xc8), Z(0xa5),
17990831639SDavid Howells 	Z(0xf3), Z(0x8e), Z(0xde), Z(0xae), Z(0x37), Z(0x49), Z(0xb7), Z(0xfa),
18090831639SDavid Howells 	Z(0xc8), Z(0xf4), Z(0x1f), Z(0xe0), Z(0x2a), Z(0x9b), Z(0x15), Z(0xd1),
18190831639SDavid Howells 	Z(0x34), Z(0x0e), Z(0xb5), Z(0xe0), Z(0x44), Z(0x78), Z(0x84), Z(0x59),
18290831639SDavid Howells 	Z(0x56), Z(0x68), Z(0x77), Z(0xa5), Z(0x14), Z(0x06), Z(0xf5), Z(0x2f),
18390831639SDavid Howells 	Z(0x8c), Z(0x8a), Z(0x73), Z(0x80), Z(0x76), Z(0xb4), Z(0x10), Z(0x86)
18490831639SDavid Howells };
18590831639SDavid Howells 
18690831639SDavid Howells #undef Z
187dad3df20SHarvey Harrison #define Z(x) cpu_to_be32(x << 19)
1883c50b368SAl Viro static const __be32 sbox3[256] = {
18990831639SDavid Howells 	Z(0xa9), Z(0x2a), Z(0x48), Z(0x51), Z(0x84), Z(0x7e), Z(0x49), Z(0xe2),
19090831639SDavid Howells 	Z(0xb5), Z(0xb7), Z(0x42), Z(0x33), Z(0x7d), Z(0x5d), Z(0xa6), Z(0x12),
19190831639SDavid Howells 	Z(0x44), Z(0x48), Z(0x6d), Z(0x28), Z(0xaa), Z(0x20), Z(0x6d), Z(0x57),
19290831639SDavid Howells 	Z(0xd6), Z(0x6b), Z(0x5d), Z(0x72), Z(0xf0), Z(0x92), Z(0x5a), Z(0x1b),
19390831639SDavid Howells 	Z(0x53), Z(0x80), Z(0x24), Z(0x70), Z(0x9a), Z(0xcc), Z(0xa7), Z(0x66),
19490831639SDavid Howells 	Z(0xa1), Z(0x01), Z(0xa5), Z(0x41), Z(0x97), Z(0x41), Z(0x31), Z(0x82),
19590831639SDavid Howells 	Z(0xf1), Z(0x14), Z(0xcf), Z(0x53), Z(0x0d), Z(0xa0), Z(0x10), Z(0xcc),
19690831639SDavid Howells 	Z(0x2a), Z(0x7d), Z(0xd2), Z(0xbf), Z(0x4b), Z(0x1a), Z(0xdb), Z(0x16),
19790831639SDavid Howells 	Z(0x47), Z(0xf6), Z(0x51), Z(0x36), Z(0xed), Z(0xf3), Z(0xb9), Z(0x1a),
19890831639SDavid Howells 	Z(0xa7), Z(0xdf), Z(0x29), Z(0x43), Z(0x01), Z(0x54), Z(0x70), Z(0xa4),
19990831639SDavid Howells 	Z(0xbf), Z(0xd4), Z(0x0b), Z(0x53), Z(0x44), Z(0x60), Z(0x9e), Z(0x23),
20090831639SDavid Howells 	Z(0xa1), Z(0x18), Z(0x68), Z(0x4f), Z(0xf0), Z(0x2f), Z(0x82), Z(0xc2),
20190831639SDavid Howells 	Z(0x2a), Z(0x41), Z(0xb2), Z(0x42), Z(0x0c), Z(0xed), Z(0x0c), Z(0x1d),
20290831639SDavid Howells 	Z(0x13), Z(0x3a), Z(0x3c), Z(0x6e), Z(0x35), Z(0xdc), Z(0x60), Z(0x65),
20390831639SDavid Howells 	Z(0x85), Z(0xe9), Z(0x64), Z(0x02), Z(0x9a), Z(0x3f), Z(0x9f), Z(0x87),
20490831639SDavid Howells 	Z(0x96), Z(0xdf), Z(0xbe), Z(0xf2), Z(0xcb), Z(0xe5), Z(0x6c), Z(0xd4),
20590831639SDavid Howells 	Z(0x5a), Z(0x83), Z(0xbf), Z(0x92), Z(0x1b), Z(0x94), Z(0x00), Z(0x42),
20690831639SDavid Howells 	Z(0xcf), Z(0x4b), Z(0x00), Z(0x75), Z(0xba), Z(0x8f), Z(0x76), Z(0x5f),
20790831639SDavid Howells 	Z(0x5d), Z(0x3a), Z(0x4d), Z(0x09), Z(0x12), Z(0x08), Z(0x38), Z(0x95),
20890831639SDavid Howells 	Z(0x17), Z(0xe4), Z(0x01), Z(0x1d), Z(0x4c), Z(0xa9), Z(0xcc), Z(0x85),
20990831639SDavid Howells 	Z(0x82), Z(0x4c), Z(0x9d), Z(0x2f), Z(0x3b), Z(0x66), Z(0xa1), Z(0x34),
21090831639SDavid Howells 	Z(0x10), Z(0xcd), Z(0x59), Z(0x89), Z(0xa5), Z(0x31), Z(0xcf), Z(0x05),
21190831639SDavid Howells 	Z(0xc8), Z(0x84), Z(0xfa), Z(0xc7), Z(0xba), Z(0x4e), Z(0x8b), Z(0x1a),
21290831639SDavid Howells 	Z(0x19), Z(0xf1), Z(0xa1), Z(0x3b), Z(0x18), Z(0x12), Z(0x17), Z(0xb0),
21390831639SDavid Howells 	Z(0x98), Z(0x8d), Z(0x0b), Z(0x23), Z(0xc3), Z(0x3a), Z(0x2d), Z(0x20),
21490831639SDavid Howells 	Z(0xdf), Z(0x13), Z(0xa0), Z(0xa8), Z(0x4c), Z(0x0d), Z(0x6c), Z(0x2f),
21590831639SDavid Howells 	Z(0x47), Z(0x13), Z(0x13), Z(0x52), Z(0x1f), Z(0x2d), Z(0xf5), Z(0x79),
21690831639SDavid Howells 	Z(0x3d), Z(0xa2), Z(0x54), Z(0xbd), Z(0x69), Z(0xc8), Z(0x6b), Z(0xf3),
21790831639SDavid Howells 	Z(0x05), Z(0x28), Z(0xf1), Z(0x16), Z(0x46), Z(0x40), Z(0xb0), Z(0x11),
21890831639SDavid Howells 	Z(0xd3), Z(0xb7), Z(0x95), Z(0x49), Z(0xcf), Z(0xc3), Z(0x1d), Z(0x8f),
21990831639SDavid Howells 	Z(0xd8), Z(0xe1), Z(0x73), Z(0xdb), Z(0xad), Z(0xc8), Z(0xc9), Z(0xa9),
22090831639SDavid Howells 	Z(0xa1), Z(0xc2), Z(0xc5), Z(0xe3), Z(0xba), Z(0xfc), Z(0x0e), Z(0x25)
22190831639SDavid Howells };
22290831639SDavid Howells 
22390831639SDavid Howells /*
22490831639SDavid Howells  * This is a 16 round Feistel network with permutation F_ENCRYPT
22590831639SDavid Howells  */
22690831639SDavid Howells #define F_ENCRYPT(R, L, sched)						\
22790831639SDavid Howells do {									\
2283c50b368SAl Viro 	union lc4 { __be32 l; u8 c[4]; } u;				\
22990831639SDavid Howells 	u.l = sched ^ R;						\
23090831639SDavid Howells 	L ^= sbox0[u.c[0]] ^ sbox1[u.c[1]] ^ sbox2[u.c[2]] ^ sbox3[u.c[3]]; \
23190831639SDavid Howells } while(0)
23290831639SDavid Howells 
23390831639SDavid Howells /*
23490831639SDavid Howells  * encryptor
23590831639SDavid Howells  */
23690831639SDavid Howells static void fcrypt_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
23790831639SDavid Howells {
23890831639SDavid Howells 	const struct fcrypt_ctx *ctx = crypto_tfm_ctx(tfm);
23990831639SDavid Howells 	struct {
2403c50b368SAl Viro 		__be32 l, r;
24190831639SDavid Howells 	} X;
24290831639SDavid Howells 
24390831639SDavid Howells 	memcpy(&X, src, sizeof(X));
24490831639SDavid Howells 
24590831639SDavid Howells 	F_ENCRYPT(X.r, X.l, ctx->sched[0x0]);
24690831639SDavid Howells 	F_ENCRYPT(X.l, X.r, ctx->sched[0x1]);
24790831639SDavid Howells 	F_ENCRYPT(X.r, X.l, ctx->sched[0x2]);
24890831639SDavid Howells 	F_ENCRYPT(X.l, X.r, ctx->sched[0x3]);
24990831639SDavid Howells 	F_ENCRYPT(X.r, X.l, ctx->sched[0x4]);
25090831639SDavid Howells 	F_ENCRYPT(X.l, X.r, ctx->sched[0x5]);
25190831639SDavid Howells 	F_ENCRYPT(X.r, X.l, ctx->sched[0x6]);
25290831639SDavid Howells 	F_ENCRYPT(X.l, X.r, ctx->sched[0x7]);
25390831639SDavid Howells 	F_ENCRYPT(X.r, X.l, ctx->sched[0x8]);
25490831639SDavid Howells 	F_ENCRYPT(X.l, X.r, ctx->sched[0x9]);
25590831639SDavid Howells 	F_ENCRYPT(X.r, X.l, ctx->sched[0xa]);
25690831639SDavid Howells 	F_ENCRYPT(X.l, X.r, ctx->sched[0xb]);
25790831639SDavid Howells 	F_ENCRYPT(X.r, X.l, ctx->sched[0xc]);
25890831639SDavid Howells 	F_ENCRYPT(X.l, X.r, ctx->sched[0xd]);
25990831639SDavid Howells 	F_ENCRYPT(X.r, X.l, ctx->sched[0xe]);
26090831639SDavid Howells 	F_ENCRYPT(X.l, X.r, ctx->sched[0xf]);
26190831639SDavid Howells 
26290831639SDavid Howells 	memcpy(dst, &X, sizeof(X));
26390831639SDavid Howells }
26490831639SDavid Howells 
26590831639SDavid Howells /*
26690831639SDavid Howells  * decryptor
26790831639SDavid Howells  */
26890831639SDavid Howells static void fcrypt_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
26990831639SDavid Howells {
27090831639SDavid Howells 	const struct fcrypt_ctx *ctx = crypto_tfm_ctx(tfm);
27190831639SDavid Howells 	struct {
2723c50b368SAl Viro 		__be32 l, r;
27390831639SDavid Howells 	} X;
27490831639SDavid Howells 
27590831639SDavid Howells 	memcpy(&X, src, sizeof(X));
27690831639SDavid Howells 
27790831639SDavid Howells 	F_ENCRYPT(X.l, X.r, ctx->sched[0xf]);
27890831639SDavid Howells 	F_ENCRYPT(X.r, X.l, ctx->sched[0xe]);
27990831639SDavid Howells 	F_ENCRYPT(X.l, X.r, ctx->sched[0xd]);
28090831639SDavid Howells 	F_ENCRYPT(X.r, X.l, ctx->sched[0xc]);
28190831639SDavid Howells 	F_ENCRYPT(X.l, X.r, ctx->sched[0xb]);
28290831639SDavid Howells 	F_ENCRYPT(X.r, X.l, ctx->sched[0xa]);
28390831639SDavid Howells 	F_ENCRYPT(X.l, X.r, ctx->sched[0x9]);
28490831639SDavid Howells 	F_ENCRYPT(X.r, X.l, ctx->sched[0x8]);
28590831639SDavid Howells 	F_ENCRYPT(X.l, X.r, ctx->sched[0x7]);
28690831639SDavid Howells 	F_ENCRYPT(X.r, X.l, ctx->sched[0x6]);
28790831639SDavid Howells 	F_ENCRYPT(X.l, X.r, ctx->sched[0x5]);
28890831639SDavid Howells 	F_ENCRYPT(X.r, X.l, ctx->sched[0x4]);
28990831639SDavid Howells 	F_ENCRYPT(X.l, X.r, ctx->sched[0x3]);
29090831639SDavid Howells 	F_ENCRYPT(X.r, X.l, ctx->sched[0x2]);
29190831639SDavid Howells 	F_ENCRYPT(X.l, X.r, ctx->sched[0x1]);
29290831639SDavid Howells 	F_ENCRYPT(X.r, X.l, ctx->sched[0x0]);
29390831639SDavid Howells 
29490831639SDavid Howells 	memcpy(dst, &X, sizeof(X));
29590831639SDavid Howells }
29690831639SDavid Howells 
29790831639SDavid Howells /*
29890831639SDavid Howells  * Generate a key schedule from key, the least significant bit in each key byte
29990831639SDavid Howells  * is parity and shall be ignored. This leaves 56 significant bits in the key
30090831639SDavid Howells  * to scatter over the 16 key schedules. For each schedule extract the low
30190831639SDavid Howells  * order 32 bits and use as schedule, then rotate right by 11 bits.
30290831639SDavid Howells  */
30390831639SDavid Howells static int fcrypt_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
30490831639SDavid Howells {
30590831639SDavid Howells 	struct fcrypt_ctx *ctx = crypto_tfm_ctx(tfm);
30690831639SDavid Howells 
30790831639SDavid Howells #if BITS_PER_LONG == 64  /* the 64-bit version can also be used for 32-bit
30890831639SDavid Howells 			  * kernels - it seems to be faster but the code is
30990831639SDavid Howells 			  * larger */
31090831639SDavid Howells 
31190831639SDavid Howells 	u64 k;	/* k holds all 56 non-parity bits */
31290831639SDavid Howells 
31390831639SDavid Howells 	/* discard the parity bits */
31490831639SDavid Howells 	k = (*key++) >> 1;
31590831639SDavid Howells 	k <<= 7;
31690831639SDavid Howells 	k |= (*key++) >> 1;
31790831639SDavid Howells 	k <<= 7;
31890831639SDavid Howells 	k |= (*key++) >> 1;
31990831639SDavid Howells 	k <<= 7;
32090831639SDavid Howells 	k |= (*key++) >> 1;
32190831639SDavid Howells 	k <<= 7;
32290831639SDavid Howells 	k |= (*key++) >> 1;
32390831639SDavid Howells 	k <<= 7;
32490831639SDavid Howells 	k |= (*key++) >> 1;
32590831639SDavid Howells 	k <<= 7;
32690831639SDavid Howells 	k |= (*key++) >> 1;
32790831639SDavid Howells 	k <<= 7;
32890831639SDavid Howells 	k |= (*key) >> 1;
32990831639SDavid Howells 
33090831639SDavid Howells 	/* Use lower 32 bits for schedule, rotate by 11 each round (16 times) */
3313c50b368SAl Viro 	ctx->sched[0x0] = cpu_to_be32(k); ror56_64(k, 11);
3323c50b368SAl Viro 	ctx->sched[0x1] = cpu_to_be32(k); ror56_64(k, 11);
3333c50b368SAl Viro 	ctx->sched[0x2] = cpu_to_be32(k); ror56_64(k, 11);
3343c50b368SAl Viro 	ctx->sched[0x3] = cpu_to_be32(k); ror56_64(k, 11);
3353c50b368SAl Viro 	ctx->sched[0x4] = cpu_to_be32(k); ror56_64(k, 11);
3363c50b368SAl Viro 	ctx->sched[0x5] = cpu_to_be32(k); ror56_64(k, 11);
3373c50b368SAl Viro 	ctx->sched[0x6] = cpu_to_be32(k); ror56_64(k, 11);
3383c50b368SAl Viro 	ctx->sched[0x7] = cpu_to_be32(k); ror56_64(k, 11);
3393c50b368SAl Viro 	ctx->sched[0x8] = cpu_to_be32(k); ror56_64(k, 11);
3403c50b368SAl Viro 	ctx->sched[0x9] = cpu_to_be32(k); ror56_64(k, 11);
3413c50b368SAl Viro 	ctx->sched[0xa] = cpu_to_be32(k); ror56_64(k, 11);
3423c50b368SAl Viro 	ctx->sched[0xb] = cpu_to_be32(k); ror56_64(k, 11);
3433c50b368SAl Viro 	ctx->sched[0xc] = cpu_to_be32(k); ror56_64(k, 11);
3443c50b368SAl Viro 	ctx->sched[0xd] = cpu_to_be32(k); ror56_64(k, 11);
3453c50b368SAl Viro 	ctx->sched[0xe] = cpu_to_be32(k); ror56_64(k, 11);
3463c50b368SAl Viro 	ctx->sched[0xf] = cpu_to_be32(k);
34790831639SDavid Howells 
34890831639SDavid Howells 	return 0;
34990831639SDavid Howells #else
35090831639SDavid Howells 	u32 hi, lo;		/* hi is upper 24 bits and lo lower 32, total 56 */
35190831639SDavid Howells 
35290831639SDavid Howells 	/* discard the parity bits */
35390831639SDavid Howells 	lo = (*key++) >> 1;
35490831639SDavid Howells 	lo <<= 7;
35590831639SDavid Howells 	lo |= (*key++) >> 1;
35690831639SDavid Howells 	lo <<= 7;
35790831639SDavid Howells 	lo |= (*key++) >> 1;
35890831639SDavid Howells 	lo <<= 7;
35990831639SDavid Howells 	lo |= (*key++) >> 1;
36090831639SDavid Howells 	hi = lo >> 4;
36190831639SDavid Howells 	lo &= 0xf;
36290831639SDavid Howells 	lo <<= 7;
36390831639SDavid Howells 	lo |= (*key++) >> 1;
36490831639SDavid Howells 	lo <<= 7;
36590831639SDavid Howells 	lo |= (*key++) >> 1;
36690831639SDavid Howells 	lo <<= 7;
36790831639SDavid Howells 	lo |= (*key++) >> 1;
36890831639SDavid Howells 	lo <<= 7;
36990831639SDavid Howells 	lo |= (*key) >> 1;
37090831639SDavid Howells 
37190831639SDavid Howells 	/* Use lower 32 bits for schedule, rotate by 11 each round (16 times) */
3723c50b368SAl Viro 	ctx->sched[0x0] = cpu_to_be32(lo); ror56(hi, lo, 11);
3733c50b368SAl Viro 	ctx->sched[0x1] = cpu_to_be32(lo); ror56(hi, lo, 11);
3743c50b368SAl Viro 	ctx->sched[0x2] = cpu_to_be32(lo); ror56(hi, lo, 11);
3753c50b368SAl Viro 	ctx->sched[0x3] = cpu_to_be32(lo); ror56(hi, lo, 11);
3763c50b368SAl Viro 	ctx->sched[0x4] = cpu_to_be32(lo); ror56(hi, lo, 11);
3773c50b368SAl Viro 	ctx->sched[0x5] = cpu_to_be32(lo); ror56(hi, lo, 11);
3783c50b368SAl Viro 	ctx->sched[0x6] = cpu_to_be32(lo); ror56(hi, lo, 11);
3793c50b368SAl Viro 	ctx->sched[0x7] = cpu_to_be32(lo); ror56(hi, lo, 11);
3803c50b368SAl Viro 	ctx->sched[0x8] = cpu_to_be32(lo); ror56(hi, lo, 11);
3813c50b368SAl Viro 	ctx->sched[0x9] = cpu_to_be32(lo); ror56(hi, lo, 11);
3823c50b368SAl Viro 	ctx->sched[0xa] = cpu_to_be32(lo); ror56(hi, lo, 11);
3833c50b368SAl Viro 	ctx->sched[0xb] = cpu_to_be32(lo); ror56(hi, lo, 11);
3843c50b368SAl Viro 	ctx->sched[0xc] = cpu_to_be32(lo); ror56(hi, lo, 11);
3853c50b368SAl Viro 	ctx->sched[0xd] = cpu_to_be32(lo); ror56(hi, lo, 11);
3863c50b368SAl Viro 	ctx->sched[0xe] = cpu_to_be32(lo); ror56(hi, lo, 11);
3873c50b368SAl Viro 	ctx->sched[0xf] = cpu_to_be32(lo);
38890831639SDavid Howells 	return 0;
38990831639SDavid Howells #endif
39090831639SDavid Howells }
39190831639SDavid Howells 
39290831639SDavid Howells static struct crypto_alg fcrypt_alg = {
39390831639SDavid Howells 	.cra_name		=	"fcrypt",
39490831639SDavid Howells 	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
39590831639SDavid Howells 	.cra_blocksize		=	8,
39690831639SDavid Howells 	.cra_ctxsize		=	sizeof(struct fcrypt_ctx),
39790831639SDavid Howells 	.cra_module		=	THIS_MODULE,
39890831639SDavid Howells 	.cra_alignmask		=	3,
39990831639SDavid Howells 	.cra_list		=	LIST_HEAD_INIT(fcrypt_alg.cra_list),
40090831639SDavid Howells 	.cra_u			=	{ .cipher = {
40190831639SDavid Howells 	.cia_min_keysize	=	8,
40290831639SDavid Howells 	.cia_max_keysize	=	8,
40390831639SDavid Howells 	.cia_setkey		=	fcrypt_setkey,
40490831639SDavid Howells 	.cia_encrypt		=	fcrypt_encrypt,
40590831639SDavid Howells 	.cia_decrypt		=	fcrypt_decrypt } }
40690831639SDavid Howells };
40790831639SDavid Howells 
4083af5b90bSKamalesh Babulal static int __init fcrypt_mod_init(void)
40990831639SDavid Howells {
41090831639SDavid Howells 	return crypto_register_alg(&fcrypt_alg);
41190831639SDavid Howells }
41290831639SDavid Howells 
4133af5b90bSKamalesh Babulal static void __exit fcrypt_mod_fini(void)
41490831639SDavid Howells {
41590831639SDavid Howells 	crypto_unregister_alg(&fcrypt_alg);
41690831639SDavid Howells }
41790831639SDavid Howells 
4183af5b90bSKamalesh Babulal module_init(fcrypt_mod_init);
4193af5b90bSKamalesh Babulal module_exit(fcrypt_mod_fini);
42090831639SDavid Howells 
42190831639SDavid Howells MODULE_LICENSE("Dual BSD/GPL");
42290831639SDavid Howells MODULE_DESCRIPTION("FCrypt Cipher Algorithm");
42390831639SDavid Howells MODULE_AUTHOR("David Howells <dhowells@redhat.com>");
424