xref: /openbmc/linux/crypto/fcrypt.c (revision 14386d47)
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>
46*14386d47SHerbert Xu #include <crypto/algapi.h>
4790831639SDavid Howells #include <linux/bitops.h>
4890831639SDavid Howells #include <linux/init.h>
4990831639SDavid Howells #include <linux/module.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 */
665c083eb3SMilan Djurovic #define ror56_64(k, n) (k = (k >> n) | ((k & ((1 << n) - 1)) << (56 - n)))
6790831639SDavid Howells 
6890831639SDavid Howells /*
6990831639SDavid Howells  * Sboxes for Feistel network derived from
7090831639SDavid Howells  * /afs/transarc.com/public/afsps/afs.rel31b.export-src/rxkad/sboxes.h
7190831639SDavid Howells  */
7290831639SDavid Howells #undef Z
73dad3df20SHarvey Harrison #define Z(x) cpu_to_be32(x << 3)
743c50b368SAl Viro static const __be32 sbox0[256] = {
7590831639SDavid Howells 	Z(0xea), Z(0x7f), Z(0xb2), Z(0x64), Z(0x9d), Z(0xb0), Z(0xd9), Z(0x11),
7690831639SDavid Howells 	Z(0xcd), Z(0x86), Z(0x86), Z(0x91), Z(0x0a), Z(0xb2), Z(0x93), Z(0x06),
7790831639SDavid Howells 	Z(0x0e), Z(0x06), Z(0xd2), Z(0x65), Z(0x73), Z(0xc5), Z(0x28), Z(0x60),
7890831639SDavid Howells 	Z(0xf2), Z(0x20), Z(0xb5), Z(0x38), Z(0x7e), Z(0xda), Z(0x9f), Z(0xe3),
7990831639SDavid Howells 	Z(0xd2), Z(0xcf), Z(0xc4), Z(0x3c), Z(0x61), Z(0xff), Z(0x4a), Z(0x4a),
8090831639SDavid Howells 	Z(0x35), Z(0xac), Z(0xaa), Z(0x5f), Z(0x2b), Z(0xbb), Z(0xbc), Z(0x53),
8190831639SDavid Howells 	Z(0x4e), Z(0x9d), Z(0x78), Z(0xa3), Z(0xdc), Z(0x09), Z(0x32), Z(0x10),
8290831639SDavid Howells 	Z(0xc6), Z(0x6f), Z(0x66), Z(0xd6), Z(0xab), Z(0xa9), Z(0xaf), Z(0xfd),
8390831639SDavid Howells 	Z(0x3b), Z(0x95), Z(0xe8), Z(0x34), Z(0x9a), Z(0x81), Z(0x72), Z(0x80),
8490831639SDavid Howells 	Z(0x9c), Z(0xf3), Z(0xec), Z(0xda), Z(0x9f), Z(0x26), Z(0x76), Z(0x15),
8590831639SDavid Howells 	Z(0x3e), Z(0x55), Z(0x4d), Z(0xde), Z(0x84), Z(0xee), Z(0xad), Z(0xc7),
8690831639SDavid Howells 	Z(0xf1), Z(0x6b), Z(0x3d), Z(0xd3), Z(0x04), Z(0x49), Z(0xaa), Z(0x24),
8790831639SDavid Howells 	Z(0x0b), Z(0x8a), Z(0x83), Z(0xba), Z(0xfa), Z(0x85), Z(0xa0), Z(0xa8),
8890831639SDavid Howells 	Z(0xb1), Z(0xd4), Z(0x01), Z(0xd8), Z(0x70), Z(0x64), Z(0xf0), Z(0x51),
8990831639SDavid Howells 	Z(0xd2), Z(0xc3), Z(0xa7), Z(0x75), Z(0x8c), Z(0xa5), Z(0x64), Z(0xef),
9090831639SDavid Howells 	Z(0x10), Z(0x4e), Z(0xb7), Z(0xc6), Z(0x61), Z(0x03), Z(0xeb), Z(0x44),
9190831639SDavid Howells 	Z(0x3d), Z(0xe5), Z(0xb3), Z(0x5b), Z(0xae), Z(0xd5), Z(0xad), Z(0x1d),
9290831639SDavid Howells 	Z(0xfa), Z(0x5a), Z(0x1e), Z(0x33), Z(0xab), Z(0x93), Z(0xa2), Z(0xb7),
9390831639SDavid Howells 	Z(0xe7), Z(0xa8), Z(0x45), Z(0xa4), Z(0xcd), Z(0x29), Z(0x63), Z(0x44),
9490831639SDavid Howells 	Z(0xb6), Z(0x69), Z(0x7e), Z(0x2e), Z(0x62), Z(0x03), Z(0xc8), Z(0xe0),
9590831639SDavid Howells 	Z(0x17), Z(0xbb), Z(0xc7), Z(0xf3), Z(0x3f), Z(0x36), Z(0xba), Z(0x71),
9690831639SDavid Howells 	Z(0x8e), Z(0x97), Z(0x65), Z(0x60), Z(0x69), Z(0xb6), Z(0xf6), Z(0xe6),
9790831639SDavid Howells 	Z(0x6e), Z(0xe0), Z(0x81), Z(0x59), Z(0xe8), Z(0xaf), Z(0xdd), Z(0x95),
9890831639SDavid Howells 	Z(0x22), Z(0x99), Z(0xfd), Z(0x63), Z(0x19), Z(0x74), Z(0x61), Z(0xb1),
9990831639SDavid Howells 	Z(0xb6), Z(0x5b), Z(0xae), Z(0x54), Z(0xb3), Z(0x70), Z(0xff), Z(0xc6),
10090831639SDavid Howells 	Z(0x3b), Z(0x3e), Z(0xc1), Z(0xd7), Z(0xe1), Z(0x0e), Z(0x76), Z(0xe5),
10190831639SDavid Howells 	Z(0x36), Z(0x4f), Z(0x59), Z(0xc7), Z(0x08), Z(0x6e), Z(0x82), Z(0xa6),
10290831639SDavid Howells 	Z(0x93), Z(0xc4), Z(0xaa), Z(0x26), Z(0x49), Z(0xe0), Z(0x21), Z(0x64),
10390831639SDavid Howells 	Z(0x07), Z(0x9f), Z(0x64), Z(0x81), Z(0x9c), Z(0xbf), Z(0xf9), Z(0xd1),
10490831639SDavid Howells 	Z(0x43), Z(0xf8), Z(0xb6), Z(0xb9), Z(0xf1), Z(0x24), Z(0x75), Z(0x03),
10590831639SDavid Howells 	Z(0xe4), Z(0xb0), Z(0x99), Z(0x46), Z(0x3d), Z(0xf5), Z(0xd1), Z(0x39),
10690831639SDavid Howells 	Z(0x72), Z(0x12), Z(0xf6), Z(0xba), Z(0x0c), Z(0x0d), Z(0x42), Z(0x2e)
10790831639SDavid Howells };
10890831639SDavid Howells 
10990831639SDavid Howells #undef Z
11006e710bdSJan-Simon Möller #define Z(x) cpu_to_be32(((x & 0x1f) << 27) | (x >> 5))
1113c50b368SAl Viro static const __be32 sbox1[256] = {
11290831639SDavid Howells 	Z(0x77), Z(0x14), Z(0xa6), Z(0xfe), Z(0xb2), Z(0x5e), Z(0x8c), Z(0x3e),
11390831639SDavid Howells 	Z(0x67), Z(0x6c), Z(0xa1), Z(0x0d), Z(0xc2), Z(0xa2), Z(0xc1), Z(0x85),
11490831639SDavid Howells 	Z(0x6c), Z(0x7b), Z(0x67), Z(0xc6), Z(0x23), Z(0xe3), Z(0xf2), Z(0x89),
11590831639SDavid Howells 	Z(0x50), Z(0x9c), Z(0x03), Z(0xb7), Z(0x73), Z(0xe6), Z(0xe1), Z(0x39),
11690831639SDavid Howells 	Z(0x31), Z(0x2c), Z(0x27), Z(0x9f), Z(0xa5), Z(0x69), Z(0x44), Z(0xd6),
11790831639SDavid Howells 	Z(0x23), Z(0x83), Z(0x98), Z(0x7d), Z(0x3c), Z(0xb4), Z(0x2d), Z(0x99),
11890831639SDavid Howells 	Z(0x1c), Z(0x1f), Z(0x8c), Z(0x20), Z(0x03), Z(0x7c), Z(0x5f), Z(0xad),
11990831639SDavid Howells 	Z(0xf4), Z(0xfa), Z(0x95), Z(0xca), Z(0x76), Z(0x44), Z(0xcd), Z(0xb6),
12090831639SDavid Howells 	Z(0xb8), Z(0xa1), Z(0xa1), Z(0xbe), Z(0x9e), Z(0x54), Z(0x8f), Z(0x0b),
12190831639SDavid Howells 	Z(0x16), Z(0x74), Z(0x31), Z(0x8a), Z(0x23), Z(0x17), Z(0x04), Z(0xfa),
12290831639SDavid Howells 	Z(0x79), Z(0x84), Z(0xb1), Z(0xf5), Z(0x13), Z(0xab), Z(0xb5), Z(0x2e),
12390831639SDavid Howells 	Z(0xaa), Z(0x0c), Z(0x60), Z(0x6b), Z(0x5b), Z(0xc4), Z(0x4b), Z(0xbc),
12490831639SDavid Howells 	Z(0xe2), Z(0xaf), Z(0x45), Z(0x73), Z(0xfa), Z(0xc9), Z(0x49), Z(0xcd),
12590831639SDavid Howells 	Z(0x00), Z(0x92), Z(0x7d), Z(0x97), Z(0x7a), Z(0x18), Z(0x60), Z(0x3d),
12690831639SDavid Howells 	Z(0xcf), Z(0x5b), Z(0xde), Z(0xc6), Z(0xe2), Z(0xe6), Z(0xbb), Z(0x8b),
12790831639SDavid Howells 	Z(0x06), Z(0xda), Z(0x08), Z(0x15), Z(0x1b), Z(0x88), Z(0x6a), Z(0x17),
12890831639SDavid Howells 	Z(0x89), Z(0xd0), Z(0xa9), Z(0xc1), Z(0xc9), Z(0x70), Z(0x6b), Z(0xe5),
12990831639SDavid Howells 	Z(0x43), Z(0xf4), Z(0x68), Z(0xc8), Z(0xd3), Z(0x84), Z(0x28), Z(0x0a),
13090831639SDavid Howells 	Z(0x52), Z(0x66), Z(0xa3), Z(0xca), Z(0xf2), Z(0xe3), Z(0x7f), Z(0x7a),
13190831639SDavid Howells 	Z(0x31), Z(0xf7), Z(0x88), Z(0x94), Z(0x5e), Z(0x9c), Z(0x63), Z(0xd5),
13290831639SDavid Howells 	Z(0x24), Z(0x66), Z(0xfc), Z(0xb3), Z(0x57), Z(0x25), Z(0xbe), Z(0x89),
13390831639SDavid Howells 	Z(0x44), Z(0xc4), Z(0xe0), Z(0x8f), Z(0x23), Z(0x3c), Z(0x12), Z(0x52),
13490831639SDavid Howells 	Z(0xf5), Z(0x1e), Z(0xf4), Z(0xcb), Z(0x18), Z(0x33), Z(0x1f), Z(0xf8),
13590831639SDavid Howells 	Z(0x69), Z(0x10), Z(0x9d), Z(0xd3), Z(0xf7), Z(0x28), Z(0xf8), Z(0x30),
13690831639SDavid Howells 	Z(0x05), Z(0x5e), Z(0x32), Z(0xc0), Z(0xd5), Z(0x19), Z(0xbd), Z(0x45),
13790831639SDavid Howells 	Z(0x8b), Z(0x5b), Z(0xfd), Z(0xbc), Z(0xe2), Z(0x5c), Z(0xa9), Z(0x96),
13890831639SDavid Howells 	Z(0xef), Z(0x70), Z(0xcf), Z(0xc2), Z(0x2a), Z(0xb3), Z(0x61), Z(0xad),
13990831639SDavid Howells 	Z(0x80), Z(0x48), Z(0x81), Z(0xb7), Z(0x1d), Z(0x43), Z(0xd9), Z(0xd7),
14090831639SDavid Howells 	Z(0x45), Z(0xf0), Z(0xd8), Z(0x8a), Z(0x59), Z(0x7c), Z(0x57), Z(0xc1),
14190831639SDavid Howells 	Z(0x79), Z(0xc7), Z(0x34), Z(0xd6), Z(0x43), Z(0xdf), Z(0xe4), Z(0x78),
14290831639SDavid Howells 	Z(0x16), Z(0x06), Z(0xda), Z(0x92), Z(0x76), Z(0x51), Z(0xe1), Z(0xd4),
14390831639SDavid Howells 	Z(0x70), Z(0x03), Z(0xe0), Z(0x2f), Z(0x96), Z(0x91), Z(0x82), Z(0x80)
14490831639SDavid Howells };
14590831639SDavid Howells 
14690831639SDavid Howells #undef Z
147dad3df20SHarvey Harrison #define Z(x) cpu_to_be32(x << 11)
1483c50b368SAl Viro static const __be32 sbox2[256] = {
14990831639SDavid Howells 	Z(0xf0), Z(0x37), Z(0x24), Z(0x53), Z(0x2a), Z(0x03), Z(0x83), Z(0x86),
15090831639SDavid Howells 	Z(0xd1), Z(0xec), Z(0x50), Z(0xf0), Z(0x42), Z(0x78), Z(0x2f), Z(0x6d),
15190831639SDavid Howells 	Z(0xbf), Z(0x80), Z(0x87), Z(0x27), Z(0x95), Z(0xe2), Z(0xc5), Z(0x5d),
15290831639SDavid Howells 	Z(0xf9), Z(0x6f), Z(0xdb), Z(0xb4), Z(0x65), Z(0x6e), Z(0xe7), Z(0x24),
15390831639SDavid Howells 	Z(0xc8), Z(0x1a), Z(0xbb), Z(0x49), Z(0xb5), Z(0x0a), Z(0x7d), Z(0xb9),
15490831639SDavid Howells 	Z(0xe8), Z(0xdc), Z(0xb7), Z(0xd9), Z(0x45), Z(0x20), Z(0x1b), Z(0xce),
15590831639SDavid Howells 	Z(0x59), Z(0x9d), Z(0x6b), Z(0xbd), Z(0x0e), Z(0x8f), Z(0xa3), Z(0xa9),
15690831639SDavid Howells 	Z(0xbc), Z(0x74), Z(0xa6), Z(0xf6), Z(0x7f), Z(0x5f), Z(0xb1), Z(0x68),
15790831639SDavid Howells 	Z(0x84), Z(0xbc), Z(0xa9), Z(0xfd), Z(0x55), Z(0x50), Z(0xe9), Z(0xb6),
15890831639SDavid Howells 	Z(0x13), Z(0x5e), Z(0x07), Z(0xb8), Z(0x95), Z(0x02), Z(0xc0), Z(0xd0),
15990831639SDavid Howells 	Z(0x6a), Z(0x1a), Z(0x85), Z(0xbd), Z(0xb6), Z(0xfd), Z(0xfe), Z(0x17),
16090831639SDavid Howells 	Z(0x3f), Z(0x09), Z(0xa3), Z(0x8d), Z(0xfb), Z(0xed), Z(0xda), Z(0x1d),
16190831639SDavid Howells 	Z(0x6d), Z(0x1c), Z(0x6c), Z(0x01), Z(0x5a), Z(0xe5), Z(0x71), Z(0x3e),
16290831639SDavid Howells 	Z(0x8b), Z(0x6b), Z(0xbe), Z(0x29), Z(0xeb), Z(0x12), Z(0x19), Z(0x34),
16390831639SDavid Howells 	Z(0xcd), Z(0xb3), Z(0xbd), Z(0x35), Z(0xea), Z(0x4b), Z(0xd5), Z(0xae),
16490831639SDavid Howells 	Z(0x2a), Z(0x79), Z(0x5a), Z(0xa5), Z(0x32), Z(0x12), Z(0x7b), Z(0xdc),
16590831639SDavid Howells 	Z(0x2c), Z(0xd0), Z(0x22), Z(0x4b), Z(0xb1), Z(0x85), Z(0x59), Z(0x80),
16690831639SDavid Howells 	Z(0xc0), Z(0x30), Z(0x9f), Z(0x73), Z(0xd3), Z(0x14), Z(0x48), Z(0x40),
16790831639SDavid Howells 	Z(0x07), Z(0x2d), Z(0x8f), Z(0x80), Z(0x0f), Z(0xce), Z(0x0b), Z(0x5e),
16890831639SDavid Howells 	Z(0xb7), Z(0x5e), Z(0xac), Z(0x24), Z(0x94), Z(0x4a), Z(0x18), Z(0x15),
16990831639SDavid Howells 	Z(0x05), Z(0xe8), Z(0x02), Z(0x77), Z(0xa9), Z(0xc7), Z(0x40), Z(0x45),
17090831639SDavid Howells 	Z(0x89), Z(0xd1), Z(0xea), Z(0xde), Z(0x0c), Z(0x79), Z(0x2a), Z(0x99),
17190831639SDavid Howells 	Z(0x6c), Z(0x3e), Z(0x95), Z(0xdd), Z(0x8c), Z(0x7d), Z(0xad), Z(0x6f),
17290831639SDavid Howells 	Z(0xdc), Z(0xff), Z(0xfd), Z(0x62), Z(0x47), Z(0xb3), Z(0x21), Z(0x8a),
17390831639SDavid Howells 	Z(0xec), Z(0x8e), Z(0x19), Z(0x18), Z(0xb4), Z(0x6e), Z(0x3d), Z(0xfd),
17490831639SDavid Howells 	Z(0x74), Z(0x54), Z(0x1e), Z(0x04), Z(0x85), Z(0xd8), Z(0xbc), Z(0x1f),
17590831639SDavid Howells 	Z(0x56), Z(0xe7), Z(0x3a), Z(0x56), Z(0x67), Z(0xd6), Z(0xc8), Z(0xa5),
17690831639SDavid Howells 	Z(0xf3), Z(0x8e), Z(0xde), Z(0xae), Z(0x37), Z(0x49), Z(0xb7), Z(0xfa),
17790831639SDavid Howells 	Z(0xc8), Z(0xf4), Z(0x1f), Z(0xe0), Z(0x2a), Z(0x9b), Z(0x15), Z(0xd1),
17890831639SDavid Howells 	Z(0x34), Z(0x0e), Z(0xb5), Z(0xe0), Z(0x44), Z(0x78), Z(0x84), Z(0x59),
17990831639SDavid Howells 	Z(0x56), Z(0x68), Z(0x77), Z(0xa5), Z(0x14), Z(0x06), Z(0xf5), Z(0x2f),
18090831639SDavid Howells 	Z(0x8c), Z(0x8a), Z(0x73), Z(0x80), Z(0x76), Z(0xb4), Z(0x10), Z(0x86)
18190831639SDavid Howells };
18290831639SDavid Howells 
18390831639SDavid Howells #undef Z
184dad3df20SHarvey Harrison #define Z(x) cpu_to_be32(x << 19)
1853c50b368SAl Viro static const __be32 sbox3[256] = {
18690831639SDavid Howells 	Z(0xa9), Z(0x2a), Z(0x48), Z(0x51), Z(0x84), Z(0x7e), Z(0x49), Z(0xe2),
18790831639SDavid Howells 	Z(0xb5), Z(0xb7), Z(0x42), Z(0x33), Z(0x7d), Z(0x5d), Z(0xa6), Z(0x12),
18890831639SDavid Howells 	Z(0x44), Z(0x48), Z(0x6d), Z(0x28), Z(0xaa), Z(0x20), Z(0x6d), Z(0x57),
18990831639SDavid Howells 	Z(0xd6), Z(0x6b), Z(0x5d), Z(0x72), Z(0xf0), Z(0x92), Z(0x5a), Z(0x1b),
19090831639SDavid Howells 	Z(0x53), Z(0x80), Z(0x24), Z(0x70), Z(0x9a), Z(0xcc), Z(0xa7), Z(0x66),
19190831639SDavid Howells 	Z(0xa1), Z(0x01), Z(0xa5), Z(0x41), Z(0x97), Z(0x41), Z(0x31), Z(0x82),
19290831639SDavid Howells 	Z(0xf1), Z(0x14), Z(0xcf), Z(0x53), Z(0x0d), Z(0xa0), Z(0x10), Z(0xcc),
19390831639SDavid Howells 	Z(0x2a), Z(0x7d), Z(0xd2), Z(0xbf), Z(0x4b), Z(0x1a), Z(0xdb), Z(0x16),
19490831639SDavid Howells 	Z(0x47), Z(0xf6), Z(0x51), Z(0x36), Z(0xed), Z(0xf3), Z(0xb9), Z(0x1a),
19590831639SDavid Howells 	Z(0xa7), Z(0xdf), Z(0x29), Z(0x43), Z(0x01), Z(0x54), Z(0x70), Z(0xa4),
19690831639SDavid Howells 	Z(0xbf), Z(0xd4), Z(0x0b), Z(0x53), Z(0x44), Z(0x60), Z(0x9e), Z(0x23),
19790831639SDavid Howells 	Z(0xa1), Z(0x18), Z(0x68), Z(0x4f), Z(0xf0), Z(0x2f), Z(0x82), Z(0xc2),
19890831639SDavid Howells 	Z(0x2a), Z(0x41), Z(0xb2), Z(0x42), Z(0x0c), Z(0xed), Z(0x0c), Z(0x1d),
19990831639SDavid Howells 	Z(0x13), Z(0x3a), Z(0x3c), Z(0x6e), Z(0x35), Z(0xdc), Z(0x60), Z(0x65),
20090831639SDavid Howells 	Z(0x85), Z(0xe9), Z(0x64), Z(0x02), Z(0x9a), Z(0x3f), Z(0x9f), Z(0x87),
20190831639SDavid Howells 	Z(0x96), Z(0xdf), Z(0xbe), Z(0xf2), Z(0xcb), Z(0xe5), Z(0x6c), Z(0xd4),
20290831639SDavid Howells 	Z(0x5a), Z(0x83), Z(0xbf), Z(0x92), Z(0x1b), Z(0x94), Z(0x00), Z(0x42),
20390831639SDavid Howells 	Z(0xcf), Z(0x4b), Z(0x00), Z(0x75), Z(0xba), Z(0x8f), Z(0x76), Z(0x5f),
20490831639SDavid Howells 	Z(0x5d), Z(0x3a), Z(0x4d), Z(0x09), Z(0x12), Z(0x08), Z(0x38), Z(0x95),
20590831639SDavid Howells 	Z(0x17), Z(0xe4), Z(0x01), Z(0x1d), Z(0x4c), Z(0xa9), Z(0xcc), Z(0x85),
20690831639SDavid Howells 	Z(0x82), Z(0x4c), Z(0x9d), Z(0x2f), Z(0x3b), Z(0x66), Z(0xa1), Z(0x34),
20790831639SDavid Howells 	Z(0x10), Z(0xcd), Z(0x59), Z(0x89), Z(0xa5), Z(0x31), Z(0xcf), Z(0x05),
20890831639SDavid Howells 	Z(0xc8), Z(0x84), Z(0xfa), Z(0xc7), Z(0xba), Z(0x4e), Z(0x8b), Z(0x1a),
20990831639SDavid Howells 	Z(0x19), Z(0xf1), Z(0xa1), Z(0x3b), Z(0x18), Z(0x12), Z(0x17), Z(0xb0),
21090831639SDavid Howells 	Z(0x98), Z(0x8d), Z(0x0b), Z(0x23), Z(0xc3), Z(0x3a), Z(0x2d), Z(0x20),
21190831639SDavid Howells 	Z(0xdf), Z(0x13), Z(0xa0), Z(0xa8), Z(0x4c), Z(0x0d), Z(0x6c), Z(0x2f),
21290831639SDavid Howells 	Z(0x47), Z(0x13), Z(0x13), Z(0x52), Z(0x1f), Z(0x2d), Z(0xf5), Z(0x79),
21390831639SDavid Howells 	Z(0x3d), Z(0xa2), Z(0x54), Z(0xbd), Z(0x69), Z(0xc8), Z(0x6b), Z(0xf3),
21490831639SDavid Howells 	Z(0x05), Z(0x28), Z(0xf1), Z(0x16), Z(0x46), Z(0x40), Z(0xb0), Z(0x11),
21590831639SDavid Howells 	Z(0xd3), Z(0xb7), Z(0x95), Z(0x49), Z(0xcf), Z(0xc3), Z(0x1d), Z(0x8f),
21690831639SDavid Howells 	Z(0xd8), Z(0xe1), Z(0x73), Z(0xdb), Z(0xad), Z(0xc8), Z(0xc9), Z(0xa9),
21790831639SDavid Howells 	Z(0xa1), Z(0xc2), Z(0xc5), Z(0xe3), Z(0xba), Z(0xfc), Z(0x0e), Z(0x25)
21890831639SDavid Howells };
21990831639SDavid Howells 
22090831639SDavid Howells /*
22190831639SDavid Howells  * This is a 16 round Feistel network with permutation F_ENCRYPT
22290831639SDavid Howells  */
22390831639SDavid Howells #define F_ENCRYPT(R, L, sched)						\
22490831639SDavid Howells do {									\
2253c50b368SAl Viro 	union lc4 { __be32 l; u8 c[4]; } u;				\
22690831639SDavid Howells 	u.l = sched ^ R;						\
22790831639SDavid Howells 	L ^= sbox0[u.c[0]] ^ sbox1[u.c[1]] ^ sbox2[u.c[2]] ^ sbox3[u.c[3]]; \
22890831639SDavid Howells } while (0)
22990831639SDavid Howells 
23090831639SDavid Howells /*
23190831639SDavid Howells  * encryptor
23290831639SDavid Howells  */
fcrypt_encrypt(struct crypto_tfm * tfm,u8 * dst,const u8 * src)23390831639SDavid Howells static void fcrypt_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
23490831639SDavid Howells {
23590831639SDavid Howells 	const struct fcrypt_ctx *ctx = crypto_tfm_ctx(tfm);
23690831639SDavid Howells 	struct {
2373c50b368SAl Viro 		__be32 l, r;
23890831639SDavid Howells 	} X;
23990831639SDavid Howells 
24090831639SDavid Howells 	memcpy(&X, src, sizeof(X));
24190831639SDavid Howells 
24290831639SDavid Howells 	F_ENCRYPT(X.r, X.l, ctx->sched[0x0]);
24390831639SDavid Howells 	F_ENCRYPT(X.l, X.r, ctx->sched[0x1]);
24490831639SDavid Howells 	F_ENCRYPT(X.r, X.l, ctx->sched[0x2]);
24590831639SDavid Howells 	F_ENCRYPT(X.l, X.r, ctx->sched[0x3]);
24690831639SDavid Howells 	F_ENCRYPT(X.r, X.l, ctx->sched[0x4]);
24790831639SDavid Howells 	F_ENCRYPT(X.l, X.r, ctx->sched[0x5]);
24890831639SDavid Howells 	F_ENCRYPT(X.r, X.l, ctx->sched[0x6]);
24990831639SDavid Howells 	F_ENCRYPT(X.l, X.r, ctx->sched[0x7]);
25090831639SDavid Howells 	F_ENCRYPT(X.r, X.l, ctx->sched[0x8]);
25190831639SDavid Howells 	F_ENCRYPT(X.l, X.r, ctx->sched[0x9]);
25290831639SDavid Howells 	F_ENCRYPT(X.r, X.l, ctx->sched[0xa]);
25390831639SDavid Howells 	F_ENCRYPT(X.l, X.r, ctx->sched[0xb]);
25490831639SDavid Howells 	F_ENCRYPT(X.r, X.l, ctx->sched[0xc]);
25590831639SDavid Howells 	F_ENCRYPT(X.l, X.r, ctx->sched[0xd]);
25690831639SDavid Howells 	F_ENCRYPT(X.r, X.l, ctx->sched[0xe]);
25790831639SDavid Howells 	F_ENCRYPT(X.l, X.r, ctx->sched[0xf]);
25890831639SDavid Howells 
25990831639SDavid Howells 	memcpy(dst, &X, sizeof(X));
26090831639SDavid Howells }
26190831639SDavid Howells 
26290831639SDavid Howells /*
26390831639SDavid Howells  * decryptor
26490831639SDavid Howells  */
fcrypt_decrypt(struct crypto_tfm * tfm,u8 * dst,const u8 * src)26590831639SDavid Howells static void fcrypt_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
26690831639SDavid Howells {
26790831639SDavid Howells 	const struct fcrypt_ctx *ctx = crypto_tfm_ctx(tfm);
26890831639SDavid Howells 	struct {
2693c50b368SAl Viro 		__be32 l, r;
27090831639SDavid Howells 	} X;
27190831639SDavid Howells 
27290831639SDavid Howells 	memcpy(&X, src, sizeof(X));
27390831639SDavid Howells 
27490831639SDavid Howells 	F_ENCRYPT(X.l, X.r, ctx->sched[0xf]);
27590831639SDavid Howells 	F_ENCRYPT(X.r, X.l, ctx->sched[0xe]);
27690831639SDavid Howells 	F_ENCRYPT(X.l, X.r, ctx->sched[0xd]);
27790831639SDavid Howells 	F_ENCRYPT(X.r, X.l, ctx->sched[0xc]);
27890831639SDavid Howells 	F_ENCRYPT(X.l, X.r, ctx->sched[0xb]);
27990831639SDavid Howells 	F_ENCRYPT(X.r, X.l, ctx->sched[0xa]);
28090831639SDavid Howells 	F_ENCRYPT(X.l, X.r, ctx->sched[0x9]);
28190831639SDavid Howells 	F_ENCRYPT(X.r, X.l, ctx->sched[0x8]);
28290831639SDavid Howells 	F_ENCRYPT(X.l, X.r, ctx->sched[0x7]);
28390831639SDavid Howells 	F_ENCRYPT(X.r, X.l, ctx->sched[0x6]);
28490831639SDavid Howells 	F_ENCRYPT(X.l, X.r, ctx->sched[0x5]);
28590831639SDavid Howells 	F_ENCRYPT(X.r, X.l, ctx->sched[0x4]);
28690831639SDavid Howells 	F_ENCRYPT(X.l, X.r, ctx->sched[0x3]);
28790831639SDavid Howells 	F_ENCRYPT(X.r, X.l, ctx->sched[0x2]);
28890831639SDavid Howells 	F_ENCRYPT(X.l, X.r, ctx->sched[0x1]);
28990831639SDavid Howells 	F_ENCRYPT(X.r, X.l, ctx->sched[0x0]);
29090831639SDavid Howells 
29190831639SDavid Howells 	memcpy(dst, &X, sizeof(X));
29290831639SDavid Howells }
29390831639SDavid Howells 
29490831639SDavid Howells /*
29590831639SDavid Howells  * Generate a key schedule from key, the least significant bit in each key byte
29690831639SDavid Howells  * is parity and shall be ignored. This leaves 56 significant bits in the key
29790831639SDavid Howells  * to scatter over the 16 key schedules. For each schedule extract the low
29890831639SDavid Howells  * order 32 bits and use as schedule, then rotate right by 11 bits.
29990831639SDavid Howells  */
fcrypt_setkey(struct crypto_tfm * tfm,const u8 * key,unsigned int keylen)30090831639SDavid Howells static int fcrypt_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
30190831639SDavid Howells {
30290831639SDavid Howells 	struct fcrypt_ctx *ctx = crypto_tfm_ctx(tfm);
30390831639SDavid Howells 
30490831639SDavid Howells #if BITS_PER_LONG == 64  /* the 64-bit version can also be used for 32-bit
30590831639SDavid Howells 			  * kernels - it seems to be faster but the code is
30690831639SDavid Howells 			  * larger */
30790831639SDavid Howells 
30890831639SDavid Howells 	u64 k;	/* k holds all 56 non-parity bits */
30990831639SDavid Howells 
31090831639SDavid Howells 	/* discard the parity bits */
31190831639SDavid Howells 	k = (*key++) >> 1;
31290831639SDavid Howells 	k <<= 7;
31390831639SDavid Howells 	k |= (*key++) >> 1;
31490831639SDavid Howells 	k <<= 7;
31590831639SDavid Howells 	k |= (*key++) >> 1;
31690831639SDavid Howells 	k <<= 7;
31790831639SDavid Howells 	k |= (*key++) >> 1;
31890831639SDavid Howells 	k <<= 7;
31990831639SDavid Howells 	k |= (*key++) >> 1;
32090831639SDavid Howells 	k <<= 7;
32190831639SDavid Howells 	k |= (*key++) >> 1;
32290831639SDavid Howells 	k <<= 7;
32390831639SDavid Howells 	k |= (*key++) >> 1;
32490831639SDavid Howells 	k <<= 7;
32590831639SDavid Howells 	k |= (*key) >> 1;
32690831639SDavid Howells 
32790831639SDavid Howells 	/* Use lower 32 bits for schedule, rotate by 11 each round (16 times) */
3283c50b368SAl Viro 	ctx->sched[0x0] = cpu_to_be32(k); ror56_64(k, 11);
3293c50b368SAl Viro 	ctx->sched[0x1] = cpu_to_be32(k); ror56_64(k, 11);
3303c50b368SAl Viro 	ctx->sched[0x2] = cpu_to_be32(k); ror56_64(k, 11);
3313c50b368SAl Viro 	ctx->sched[0x3] = cpu_to_be32(k); ror56_64(k, 11);
3323c50b368SAl Viro 	ctx->sched[0x4] = cpu_to_be32(k); ror56_64(k, 11);
3333c50b368SAl Viro 	ctx->sched[0x5] = cpu_to_be32(k); ror56_64(k, 11);
3343c50b368SAl Viro 	ctx->sched[0x6] = cpu_to_be32(k); ror56_64(k, 11);
3353c50b368SAl Viro 	ctx->sched[0x7] = cpu_to_be32(k); ror56_64(k, 11);
3363c50b368SAl Viro 	ctx->sched[0x8] = cpu_to_be32(k); ror56_64(k, 11);
3373c50b368SAl Viro 	ctx->sched[0x9] = cpu_to_be32(k); ror56_64(k, 11);
3383c50b368SAl Viro 	ctx->sched[0xa] = cpu_to_be32(k); ror56_64(k, 11);
3393c50b368SAl Viro 	ctx->sched[0xb] = cpu_to_be32(k); ror56_64(k, 11);
3403c50b368SAl Viro 	ctx->sched[0xc] = cpu_to_be32(k); ror56_64(k, 11);
3413c50b368SAl Viro 	ctx->sched[0xd] = cpu_to_be32(k); ror56_64(k, 11);
3423c50b368SAl Viro 	ctx->sched[0xe] = cpu_to_be32(k); ror56_64(k, 11);
3433c50b368SAl Viro 	ctx->sched[0xf] = cpu_to_be32(k);
34490831639SDavid Howells 
34590831639SDavid Howells 	return 0;
34690831639SDavid Howells #else
34790831639SDavid Howells 	u32 hi, lo;		/* hi is upper 24 bits and lo lower 32, total 56 */
34890831639SDavid Howells 
34990831639SDavid Howells 	/* discard the parity bits */
35090831639SDavid Howells 	lo = (*key++) >> 1;
35190831639SDavid Howells 	lo <<= 7;
35290831639SDavid Howells 	lo |= (*key++) >> 1;
35390831639SDavid Howells 	lo <<= 7;
35490831639SDavid Howells 	lo |= (*key++) >> 1;
35590831639SDavid Howells 	lo <<= 7;
35690831639SDavid Howells 	lo |= (*key++) >> 1;
35790831639SDavid Howells 	hi = lo >> 4;
35890831639SDavid Howells 	lo &= 0xf;
35990831639SDavid Howells 	lo <<= 7;
36090831639SDavid Howells 	lo |= (*key++) >> 1;
36190831639SDavid Howells 	lo <<= 7;
36290831639SDavid Howells 	lo |= (*key++) >> 1;
36390831639SDavid Howells 	lo <<= 7;
36490831639SDavid Howells 	lo |= (*key++) >> 1;
36590831639SDavid Howells 	lo <<= 7;
36690831639SDavid Howells 	lo |= (*key) >> 1;
36790831639SDavid Howells 
36890831639SDavid Howells 	/* Use lower 32 bits for schedule, rotate by 11 each round (16 times) */
3693c50b368SAl Viro 	ctx->sched[0x0] = cpu_to_be32(lo); ror56(hi, lo, 11);
3703c50b368SAl Viro 	ctx->sched[0x1] = cpu_to_be32(lo); ror56(hi, lo, 11);
3713c50b368SAl Viro 	ctx->sched[0x2] = cpu_to_be32(lo); ror56(hi, lo, 11);
3723c50b368SAl Viro 	ctx->sched[0x3] = cpu_to_be32(lo); ror56(hi, lo, 11);
3733c50b368SAl Viro 	ctx->sched[0x4] = cpu_to_be32(lo); ror56(hi, lo, 11);
3743c50b368SAl Viro 	ctx->sched[0x5] = cpu_to_be32(lo); ror56(hi, lo, 11);
3753c50b368SAl Viro 	ctx->sched[0x6] = cpu_to_be32(lo); ror56(hi, lo, 11);
3763c50b368SAl Viro 	ctx->sched[0x7] = cpu_to_be32(lo); ror56(hi, lo, 11);
3773c50b368SAl Viro 	ctx->sched[0x8] = cpu_to_be32(lo); ror56(hi, lo, 11);
3783c50b368SAl Viro 	ctx->sched[0x9] = cpu_to_be32(lo); ror56(hi, lo, 11);
3793c50b368SAl Viro 	ctx->sched[0xa] = cpu_to_be32(lo); ror56(hi, lo, 11);
3803c50b368SAl Viro 	ctx->sched[0xb] = cpu_to_be32(lo); ror56(hi, lo, 11);
3813c50b368SAl Viro 	ctx->sched[0xc] = cpu_to_be32(lo); ror56(hi, lo, 11);
3823c50b368SAl Viro 	ctx->sched[0xd] = cpu_to_be32(lo); ror56(hi, lo, 11);
3833c50b368SAl Viro 	ctx->sched[0xe] = cpu_to_be32(lo); ror56(hi, lo, 11);
3843c50b368SAl Viro 	ctx->sched[0xf] = cpu_to_be32(lo);
38590831639SDavid Howells 	return 0;
38690831639SDavid Howells #endif
38790831639SDavid Howells }
38890831639SDavid Howells 
38990831639SDavid Howells static struct crypto_alg fcrypt_alg = {
39090831639SDavid Howells 	.cra_name		=	"fcrypt",
391d6ebf528SEric Biggers 	.cra_driver_name	=	"fcrypt-generic",
39290831639SDavid Howells 	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
39390831639SDavid Howells 	.cra_blocksize		=	8,
39490831639SDavid Howells 	.cra_ctxsize		=	sizeof(struct fcrypt_ctx),
39590831639SDavid Howells 	.cra_module		=	THIS_MODULE,
39690831639SDavid Howells 	.cra_u			=	{ .cipher = {
39790831639SDavid Howells 	.cia_min_keysize	=	8,
39890831639SDavid Howells 	.cia_max_keysize	=	8,
39990831639SDavid Howells 	.cia_setkey		=	fcrypt_setkey,
40090831639SDavid Howells 	.cia_encrypt		=	fcrypt_encrypt,
40190831639SDavid Howells 	.cia_decrypt		=	fcrypt_decrypt } }
40290831639SDavid Howells };
40390831639SDavid Howells 
fcrypt_mod_init(void)4043af5b90bSKamalesh Babulal static int __init fcrypt_mod_init(void)
40590831639SDavid Howells {
40690831639SDavid Howells 	return crypto_register_alg(&fcrypt_alg);
40790831639SDavid Howells }
40890831639SDavid Howells 
fcrypt_mod_fini(void)4093af5b90bSKamalesh Babulal static void __exit fcrypt_mod_fini(void)
41090831639SDavid Howells {
41190831639SDavid Howells 	crypto_unregister_alg(&fcrypt_alg);
41290831639SDavid Howells }
41390831639SDavid Howells 
414c4741b23SEric Biggers subsys_initcall(fcrypt_mod_init);
4153af5b90bSKamalesh Babulal module_exit(fcrypt_mod_fini);
41690831639SDavid Howells 
41790831639SDavid Howells MODULE_LICENSE("Dual BSD/GPL");
41890831639SDavid Howells MODULE_DESCRIPTION("FCrypt Cipher Algorithm");
41990831639SDavid Howells MODULE_AUTHOR("David Howells <dhowells@redhat.com>");
4205d26a105SKees Cook MODULE_ALIAS_CRYPTO("fcrypt");
421