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