/* FCrypt encryption algorithm
*
* Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
* Based on code:
*
* Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <asm /byteorder.h>
#include <crypto/algapi.h>
#include <linux/bitops.h>
#include <linux/init.h>
#include <linux/module.h>
#define ROUNDS 16
struct fcrypt_ctx {
__be32 sched[ROUNDS];
};
/* Rotate right two 32 bit numbers as a 56 bit number */
#define ror56(hi, lo, n) \
do { \
u32 t = lo & ((1 << n) - 1 ); \
lo = (lo >> n) | ((hi & ((1 << n) - 1 )) << (32 - n)); \
hi = (hi >> n) | (t << (24 -n)); \
} while (0 )
/* Rotate right one 64 bit number as a 56 bit number */
#define ror56_64(k, n) (k = (k >> n) | ((k & ((1 << n) - 1 )) << (56 - n)))
/*
* Sboxes for Feistel network derived from
* /afs/transarc.com/public/afsps/afs.rel31b.export-src/rxkad/sboxes.h
*/
#undef Z
#define Z(x) cpu_to_be32(x << 3 )
static const __be32 sbox0[256 ] = {
Z(0 xea), Z(0 x7f), Z(0 xb2), Z(0 x64), Z(0 x9d), Z(0 xb0), Z(0 xd9), Z(0 x11),
Z(0 xcd), Z(0 x86), Z(0 x86), Z(0 x91), Z(0 x0a), Z(0 xb2), Z(0 x93), Z(0 x06),
Z(0 x0e), Z(0 x06), Z(0 xd2), Z(0 x65), Z(0 x73), Z(0 xc5), Z(0 x28), Z(0 x60),
Z(0 xf2), Z(0 x20), Z(0 xb5), Z(0 x38), Z(0 x7e), Z(0 xda), Z(0 x9f), Z(0 xe3),
Z(0 xd2), Z(0 xcf), Z(0 xc4), Z(0 x3c), Z(0 x61), Z(0 xff), Z(0 x4a), Z(0 x4a),
Z(0 x35), Z(0 xac), Z(0 xaa), Z(0 x5f), Z(0 x2b), Z(0 xbb), Z(0 xbc), Z(0 x53),
Z(0 x4e), Z(0 x9d), Z(0 x78), Z(0 xa3), Z(0 xdc), Z(0 x09), Z(0 x32), Z(0 x10),
Z(0 xc6), Z(0 x6f), Z(0 x66), Z(0 xd6), Z(0 xab), Z(0 xa9), Z(0 xaf), Z(0 xfd),
Z(0 x3b), Z(0 x95), Z(0 xe8), Z(0 x34), Z(0 x9a), Z(0 x81), Z(0 x72), Z(0 x80),
Z(0 x9c), Z(0 xf3), Z(0 xec), Z(0 xda), Z(0 x9f), Z(0 x26), Z(0 x76), Z(0 x15),
Z(0 x3e), Z(0 x55), Z(0 x4d), Z(0 xde), Z(0 x84), Z(0 xee), Z(0 xad), Z(0 xc7),
Z(0 xf1), Z(0 x6b), Z(0 x3d), Z(0 xd3), Z(0 x04), Z(0 x49), Z(0 xaa), Z(0 x24),
Z(0 x0b), Z(0 x8a), Z(0 x83), Z(0 xba), Z(0 xfa), Z(0 x85), Z(0 xa0), Z(0 xa8),
Z(0 xb1), Z(0 xd4), Z(0 x01), Z(0 xd8), Z(0 x70), Z(0 x64), Z(0 xf0), Z(0 x51),
Z(0 xd2), Z(0 xc3), Z(0 xa7), Z(0 x75), Z(0 x8c), Z(0 xa5), Z(0 x64), Z(0 xef),
Z(0 x10), Z(0 x4e), Z(0 xb7), Z(0 xc6), Z(0 x61), Z(0 x03), Z(0 xeb), Z(0 x44),
Z(0 x3d), Z(0 xe5), Z(0 xb3), Z(0 x5b), Z(0 xae), Z(0 xd5), Z(0 xad), Z(0 x1d),
Z(0 xfa), Z(0 x5a), Z(0 x1e), Z(0 x33), Z(0 xab), Z(0 x93), Z(0 xa2), Z(0 xb7),
Z(0 xe7), Z(0 xa8), Z(0 x45), Z(0 xa4), Z(0 xcd), Z(0 x29), Z(0 x63), Z(0 x44),
Z(0 xb6), Z(0 x69), Z(0 x7e), Z(0 x2e), Z(0 x62), Z(0 x03), Z(0 xc8), Z(0 xe0),
Z(0 x17), Z(0 xbb), Z(0 xc7), Z(0 xf3), Z(0 x3f), Z(0 x36), Z(0 xba), Z(0 x71),
Z(0 x8e), Z(0 x97), Z(0 x65), Z(0 x60), Z(0 x69), Z(0 xb6), Z(0 xf6), Z(0 xe6),
Z(0 x6e), Z(0 xe0), Z(0 x81), Z(0 x59), Z(0 xe8), Z(0 xaf), Z(0 xdd), Z(0 x95),
Z(0 x22), Z(0 x99), Z(0 xfd), Z(0 x63), Z(0 x19), Z(0 x74), Z(0 x61), Z(0 xb1),
Z(0 xb6), Z(0 x5b), Z(0 xae), Z(0 x54), Z(0 xb3), Z(0 x70), Z(0 xff), Z(0 xc6),
Z(0 x3b), Z(0 x3e), Z(0 xc1), Z(0 xd7), Z(0 xe1), Z(0 x0e), Z(0 x76), Z(0 xe5),
Z(0 x36), Z(0 x4f), Z(0 x59), Z(0 xc7), Z(0 x08), Z(0 x6e), Z(0 x82), Z(0 xa6),
Z(0 x93), Z(0 xc4), Z(0 xaa), Z(0 x26), Z(0 x49), Z(0 xe0), Z(0 x21), Z(0 x64),
Z(0 x07), Z(0 x9f), Z(0 x64), Z(0 x81), Z(0 x9c), Z(0 xbf), Z(0 xf9), Z(0 xd1),
Z(0 x43), Z(0 xf8), Z(0 xb6), Z(0 xb9), Z(0 xf1), Z(0 x24), Z(0 x75), Z(0 x03),
Z(0 xe4), Z(0 xb0), Z(0 x99), Z(0 x46), Z(0 x3d), Z(0 xf5), Z(0 xd1), Z(0 x39),
Z(0 x72), Z(0 x12), Z(0 xf6), Z(0 xba), Z(0 x0c), Z(0 x0d), Z(0 x42), Z(0 x2e)
};
#undef Z
#define Z(x) cpu_to_be32(((x & 0 x1f) << 27 ) | (x >> 5 ))
static const __be32 sbox1[256 ] = {
Z(0 x77), Z(0 x14), Z(0 xa6), Z(0 xfe), Z(0 xb2), Z(0 x5e), Z(0 x8c), Z(0 x3e),
Z(0 x67), Z(0 x6c), Z(0 xa1), Z(0 x0d), Z(0 xc2), Z(0 xa2), Z(0 xc1), Z(0 x85),
Z(0 x6c), Z(0 x7b), Z(0 x67), Z(0 xc6), Z(0 x23), Z(0 xe3), Z(0 xf2), Z(0 x89),
Z(0 x50), Z(0 x9c), Z(0 x03), Z(0 xb7), Z(0 x73), Z(0 xe6), Z(0 xe1), Z(0 x39),
Z(0 x31), Z(0 x2c), Z(0 x27), Z(0 x9f), Z(0 xa5), Z(0 x69), Z(0 x44), Z(0 xd6),
Z(0 x23), Z(0 x83), Z(0 x98), Z(0 x7d), Z(0 x3c), Z(0 xb4), Z(0 x2d), Z(0 x99),
Z(0 x1c), Z(0 x1f), Z(0 x8c), Z(0 x20), Z(0 x03), Z(0 x7c), Z(0 x5f), Z(0 xad),
Z(0 xf4), Z(0 xfa), Z(0 x95), Z(0 xca), Z(0 x76), Z(0 x44), Z(0 xcd), Z(0 xb6),
Z(0 xb8), Z(0 xa1), Z(0 xa1), Z(0 xbe), Z(0 x9e), Z(0 x54), Z(0 x8f), Z(0 x0b),
Z(0 x16), Z(0 x74), Z(0 x31), Z(0 x8a), Z(0 x23), Z(0 x17), Z(0 x04), Z(0 xfa),
Z(0 x79), Z(0 x84), Z(0 xb1), Z(0 xf5), Z(0 x13), Z(0 xab), Z(0 xb5), Z(0 x2e),
Z(0 xaa), Z(0 x0c), Z(0 x60), Z(0 x6b), Z(0 x5b), Z(0 xc4), Z(0 x4b), Z(0 xbc),
Z(0 xe2), Z(0 xaf), Z(0 x45), Z(0 x73), Z(0 xfa), Z(0 xc9), Z(0 x49), Z(0 xcd),
Z(0 x00), Z(0 x92), Z(0 x7d), Z(0 x97), Z(0 x7a), Z(0 x18), Z(0 x60), Z(0 x3d),
Z(0 xcf), Z(0 x5b), Z(0 xde), Z(0 xc6), Z(0 xe2), Z(0 xe6), Z(0 xbb), Z(0 x8b),
Z(0 x06), Z(0 xda), Z(0 x08), Z(0 x15), Z(0 x1b), Z(0 x88), Z(0 x6a), Z(0 x17),
Z(0 x89), Z(0 xd0), Z(0 xa9), Z(0 xc1), Z(0 xc9), Z(0 x70), Z(0 x6b), Z(0 xe5),
Z(0 x43), Z(0 xf4), Z(0 x68), Z(0 xc8), Z(0 xd3), Z(0 x84), Z(0 x28), Z(0 x0a),
Z(0 x52), Z(0 x66), Z(0 xa3), Z(0 xca), Z(0 xf2), Z(0 xe3), Z(0 x7f), Z(0 x7a),
Z(0 x31), Z(0 xf7), Z(0 x88), Z(0 x94), Z(0 x5e), Z(0 x9c), Z(0 x63), Z(0 xd5),
Z(0 x24), Z(0 x66), Z(0 xfc), Z(0 xb3), Z(0 x57), Z(0 x25), Z(0 xbe), Z(0 x89),
Z(0 x44), Z(0 xc4), Z(0 xe0), Z(0 x8f), Z(0 x23), Z(0 x3c), Z(0 x12), Z(0 x52),
Z(0 xf5), Z(0 x1e), Z(0 xf4), Z(0 xcb), Z(0 x18), Z(0 x33), Z(0 x1f), Z(0 xf8),
Z(0 x69), Z(0 x10), Z(0 x9d), Z(0 xd3), Z(0 xf7), Z(0 x28), Z(0 xf8), Z(0 x30),
Z(0 x05), Z(0 x5e), Z(0 x32), Z(0 xc0), Z(0 xd5), Z(0 x19), Z(0 xbd), Z(0 x45),
Z(0 x8b), Z(0 x5b), Z(0 xfd), Z(0 xbc), Z(0 xe2), Z(0 x5c), Z(0 xa9), Z(0 x96),
Z(0 xef), Z(0 x70), Z(0 xcf), Z(0 xc2), Z(0 x2a), Z(0 xb3), Z(0 x61), Z(0 xad),
Z(0 x80), Z(0 x48), Z(0 x81), Z(0 xb7), Z(0 x1d), Z(0 x43), Z(0 xd9), Z(0 xd7),
Z(0 x45), Z(0 xf0), Z(0 xd8), Z(0 x8a), Z(0 x59), Z(0 x7c), Z(0 x57), Z(0 xc1),
Z(0 x79), Z(0 xc7), Z(0 x34), Z(0 xd6), Z(0 x43), Z(0 xdf), Z(0 xe4), Z(0 x78),
Z(0 x16), Z(0 x06), Z(0 xda), Z(0 x92), Z(0 x76), Z(0 x51), Z(0 xe1), Z(0 xd4),
Z(0 x70), Z(0 x03), Z(0 xe0), Z(0 x2f), Z(0 x96), Z(0 x91), Z(0 x82), Z(0 x80)
};
#undef Z
#define Z(x) cpu_to_be32(x << 11 )
static const __be32 sbox2[256 ] = {
Z(0 xf0), Z(0 x37), Z(0 x24), Z(0 x53), Z(0 x2a), Z(0 x03), Z(0 x83), Z(0 x86),
Z(0 xd1), Z(0 xec), Z(0 x50), Z(0 xf0), Z(0 x42), Z(0 x78), Z(0 x2f), Z(0 x6d),
Z(0 xbf), Z(0 x80), Z(0 x87), Z(0 x27), Z(0 x95), Z(0 xe2), Z(0 xc5), Z(0 x5d),
Z(0 xf9), Z(0 x6f), Z(0 xdb), Z(0 xb4), Z(0 x65), Z(0 x6e), Z(0 xe7), Z(0 x24),
Z(0 xc8), Z(0 x1a), Z(0 xbb), Z(0 x49), Z(0 xb5), Z(0 x0a), Z(0 x7d), Z(0 xb9),
Z(0 xe8), Z(0 xdc), Z(0 xb7), Z(0 xd9), Z(0 x45), Z(0 x20), Z(0 x1b), Z(0 xce),
Z(0 x59), Z(0 x9d), Z(0 x6b), Z(0 xbd), Z(0 x0e), Z(0 x8f), Z(0 xa3), Z(0 xa9),
Z(0 xbc), Z(0 x74), Z(0 xa6), Z(0 xf6), Z(0 x7f), Z(0 x5f), Z(0 xb1), Z(0 x68),
Z(0 x84), Z(0 xbc), Z(0 xa9), Z(0 xfd), Z(0 x55), Z(0 x50), Z(0 xe9), Z(0 xb6),
Z(0 x13), Z(0 x5e), Z(0 x07), Z(0 xb8), Z(0 x95), Z(0 x02), Z(0 xc0), Z(0 xd0),
Z(0 x6a), Z(0 x1a), Z(0 x85), Z(0 xbd), Z(0 xb6), Z(0 xfd), Z(0 xfe), Z(0 x17),
Z(0 x3f), Z(0 x09), Z(0 xa3), Z(0 x8d), Z(0 xfb), Z(0 xed), Z(0 xda), Z(0 x1d),
Z(0 x6d), Z(0 x1c), Z(0 x6c), Z(0 x01), Z(0 x5a), Z(0 xe5), Z(0 x71), Z(0 x3e),
Z(0 x8b), Z(0 x6b), Z(0 xbe), Z(0 x29), Z(0 xeb), Z(0 x12), Z(0 x19), Z(0 x34),
Z(0 xcd), Z(0 xb3), Z(0 xbd), Z(0 x35), Z(0 xea), Z(0 x4b), Z(0 xd5), Z(0 xae),
Z(0 x2a), Z(0 x79), Z(0 x5a), Z(0 xa5), Z(0 x32), Z(0 x12), Z(0 x7b), Z(0 xdc),
Z(0 x2c), Z(0 xd0), Z(0 x22), Z(0 x4b), Z(0 xb1), Z(0 x85), Z(0 x59), Z(0 x80),
Z(0 xc0), Z(0 x30), Z(0 x9f), Z(0 x73), Z(0 xd3), Z(0 x14), Z(0 x48), Z(0 x40),
Z(0 x07), Z(0 x2d), Z(0 x8f), Z(0 x80), Z(0 x0f), Z(0 xce), Z(0 x0b), Z(0 x5e),
Z(0 xb7), Z(0 x5e), Z(0 xac), Z(0 x24), Z(0 x94), Z(0 x4a), Z(0 x18), Z(0 x15),
Z(0 x05), Z(0 xe8), Z(0 x02), Z(0 x77), Z(0 xa9), Z(0 xc7), Z(0 x40), Z(0 x45),
Z(0 x89), Z(0 xd1), Z(0 xea), Z(0 xde), Z(0 x0c), Z(0 x79), Z(0 x2a), Z(0 x99),
Z(0 x6c), Z(0 x3e), Z(0 x95), Z(0 xdd), Z(0 x8c), Z(0 x7d), Z(0 xad), Z(0 x6f),
Z(0 xdc), Z(0 xff), Z(0 xfd), Z(0 x62), Z(0 x47), Z(0 xb3), Z(0 x21), Z(0 x8a),
Z(0 xec), Z(0 x8e), Z(0 x19), Z(0 x18), Z(0 xb4), Z(0 x6e), Z(0 x3d), Z(0 xfd),
Z(0 x74), Z(0 x54), Z(0 x1e), Z(0 x04), Z(0 x85), Z(0 xd8), Z(0 xbc), Z(0 x1f),
Z(0 x56), Z(0 xe7), Z(0 x3a), Z(0 x56), Z(0 x67), Z(0 xd6), Z(0 xc8), Z(0 xa5),
Z(0 xf3), Z(0 x8e), Z(0 xde), Z(0 xae), Z(0 x37), Z(0 x49), Z(0 xb7), Z(0 xfa),
Z(0 xc8), Z(0 xf4), Z(0 x1f), Z(0 xe0), Z(0 x2a), Z(0 x9b), Z(0 x15), Z(0 xd1),
Z(0 x34), Z(0 x0e), Z(0 xb5), Z(0 xe0), Z(0 x44), Z(0 x78), Z(0 x84), Z(0 x59),
Z(0 x56), Z(0 x68), Z(0 x77), Z(0 xa5), Z(0 x14), Z(0 x06), Z(0 xf5), Z(0 x2f),
Z(0 x8c), Z(0 x8a), Z(0 x73), Z(0 x80), Z(0 x76), Z(0 xb4), Z(0 x10), Z(0 x86)
};
#undef Z
#define Z(x) cpu_to_be32(x << 19 )
static const __be32 sbox3[256 ] = {
Z(0 xa9), Z(0 x2a), Z(0 x48), Z(0 x51), Z(0 x84), Z(0 x7e), Z(0 x49), Z(0 xe2),
Z(0 xb5), Z(0 xb7), Z(0 x42), Z(0 x33), Z(0 x7d), Z(0 x5d), Z(0 xa6), Z(0 x12),
Z(0 x44), Z(0 x48), Z(0 x6d), Z(0 x28), Z(0 xaa), Z(0 x20), Z(0 x6d), Z(0 x57),
Z(0 xd6), Z(0 x6b), Z(0 x5d), Z(0 x72), Z(0 xf0), Z(0 x92), Z(0 x5a), Z(0 x1b),
Z(0 x53), Z(0 x80), Z(0 x24), Z(0 x70), Z(0 x9a), Z(0 xcc), Z(0 xa7), Z(0 x66),
Z(0 xa1), Z(0 x01), Z(0 xa5), Z(0 x41), Z(0 x97), Z(0 x41), Z(0 x31), Z(0 x82),
Z(0 xf1), Z(0 x14), Z(0 xcf), Z(0 x53), Z(0 x0d), Z(0 xa0), Z(0 x10), Z(0 xcc),
Z(0 x2a), Z(0 x7d), Z(0 xd2), Z(0 xbf), Z(0 x4b), Z(0 x1a), Z(0 xdb), Z(0 x16),
Z(0 x47), Z(0 xf6), Z(0 x51), Z(0 x36), Z(0 xed), Z(0 xf3), Z(0 xb9), Z(0 x1a),
Z(0 xa7), Z(0 xdf), Z(0 x29), Z(0 x43), Z(0 x01), Z(0 x54), Z(0 x70), Z(0 xa4),
Z(0 xbf), Z(0 xd4), Z(0 x0b), Z(0 x53), Z(0 x44), Z(0 x60), Z(0 x9e), Z(0 x23),
Z(0 xa1), Z(0 x18), Z(0 x68), Z(0 x4f), Z(0 xf0), Z(0 x2f), Z(0 x82), Z(0 xc2),
Z(0 x2a), Z(0 x41), Z(0 xb2), Z(0 x42), Z(0 x0c), Z(0 xed), Z(0 x0c), Z(0 x1d),
Z(0 x13), Z(0 x3a), Z(0 x3c), Z(0 x6e), Z(0 x35), Z(0 xdc), Z(0 x60), Z(0 x65),
Z(0 x85), Z(0 xe9), Z(0 x64), Z(0 x02), Z(0 x9a), Z(0 x3f), Z(0 x9f), Z(0 x87),
Z(0 x96), Z(0 xdf), Z(0 xbe), Z(0 xf2), Z(0 xcb), Z(0 xe5), Z(0 x6c), Z(0 xd4),
Z(0 x5a), Z(0 x83), Z(0 xbf), Z(0 x92), Z(0 x1b), Z(0 x94), Z(0 x00), Z(0 x42),
Z(0 xcf), Z(0 x4b), Z(0 x00), Z(0 x75), Z(0 xba), Z(0 x8f), Z(0 x76), Z(0 x5f),
Z(0 x5d), Z(0 x3a), Z(0 x4d), Z(0 x09), Z(0 x12), Z(0 x08), Z(0 x38), Z(0 x95),
Z(0 x17), Z(0 xe4), Z(0 x01), Z(0 x1d), Z(0 x4c), Z(0 xa9), Z(0 xcc), Z(0 x85),
Z(0 x82), Z(0 x4c), Z(0 x9d), Z(0 x2f), Z(0 x3b), Z(0 x66), Z(0 xa1), Z(0 x34),
Z(0 x10), Z(0 xcd), Z(0 x59), Z(0 x89), Z(0 xa5), Z(0 x31), Z(0 xcf), Z(0 x05),
Z(0 xc8), Z(0 x84), Z(0 xfa), Z(0 xc7), Z(0 xba), Z(0 x4e), Z(0 x8b), Z(0 x1a),
Z(0 x19), Z(0 xf1), Z(0 xa1), Z(0 x3b), Z(0 x18), Z(0 x12), Z(0 x17), Z(0 xb0),
Z(0 x98), Z(0 x8d), Z(0 x0b), Z(0 x23), Z(0 xc3), Z(0 x3a), Z(0 x2d), Z(0 x20),
Z(0 xdf), Z(0 x13), Z(0 xa0), Z(0 xa8), Z(0 x4c), Z(0 x0d), Z(0 x6c), Z(0 x2f),
Z(0 x47), Z(0 x13), Z(0 x13), Z(0 x52), Z(0 x1f), Z(0 x2d), Z(0 xf5), Z(0 x79),
Z(0 x3d), Z(0 xa2), Z(0 x54), Z(0 xbd), Z(0 x69), Z(0 xc8), Z(0 x6b), Z(0 xf3),
Z(0 x05), Z(0 x28), Z(0 xf1), Z(0 x16), Z(0 x46), Z(0 x40), Z(0 xb0), Z(0 x11),
Z(0 xd3), Z(0 xb7), Z(0 x95), Z(0 x49), Z(0 xcf), Z(0 xc3), Z(0 x1d), Z(0 x8f),
Z(0 xd8), Z(0 xe1), Z(0 x73), Z(0 xdb), Z(0 xad), Z(0 xc8), Z(0 xc9), Z(0 xa9),
Z(0 xa1), Z(0 xc2), Z(0 xc5), Z(0 xe3), Z(0 xba), Z(0 xfc), Z(0 x0e), Z(0 x25)
};
/*
* This is a 16 round Feistel network with permutation F_ENCRYPT
*/
#define F_ENCRYPT(R, L, sched) \
do { \
union lc4 { __be32 l; u8 c[4 ]; } u; \
u.l = sched ^ R; \
L ^= sbox0[u.c[0 ]] ^ sbox1[u.c[1 ]] ^ sbox2[u.c[2 ]] ^ sbox3[u.c[3 ]]; \
} while (0 )
/*
* encryptor
*/
static void fcrypt_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
{
const struct fcrypt_ctx *ctx = crypto_tfm_ctx(tfm);
struct {
__be32 l, r;
} X;
memcpy(&X, src, sizeof (X));
F_ENCRYPT(X.r, X.l, ctx->sched[0 x0]);
F_ENCRYPT(X.l, X.r, ctx->sched[0 x1]);
F_ENCRYPT(X.r, X.l, ctx->sched[0 x2]);
F_ENCRYPT(X.l, X.r, ctx->sched[0 x3]);
F_ENCRYPT(X.r, X.l, ctx->sched[0 x4]);
F_ENCRYPT(X.l, X.r, ctx->sched[0 x5]);
F_ENCRYPT(X.r, X.l, ctx->sched[0 x6]);
F_ENCRYPT(X.l, X.r, ctx->sched[0 x7]);
F_ENCRYPT(X.r, X.l, ctx->sched[0 x8]);
F_ENCRYPT(X.l, X.r, ctx->sched[0 x9]);
F_ENCRYPT(X.r, X.l, ctx->sched[0 xa]);
F_ENCRYPT(X.l, X.r, ctx->sched[0 xb]);
F_ENCRYPT(X.r, X.l, ctx->sched[0 xc]);
F_ENCRYPT(X.l, X.r, ctx->sched[0 xd]);
F_ENCRYPT(X.r, X.l, ctx->sched[0 xe]);
F_ENCRYPT(X.l, X.r, ctx->sched[0 xf]);
memcpy(dst, &X, sizeof (X));
}
/*
* decryptor
*/
static void fcrypt_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
{
const struct fcrypt_ctx *ctx = crypto_tfm_ctx(tfm);
struct {
__be32 l, r;
} X;
memcpy(&X, src, sizeof (X));
F_ENCRYPT(X.l, X.r, ctx->sched[0 xf]);
F_ENCRYPT(X.r, X.l, ctx->sched[0 xe]);
F_ENCRYPT(X.l, X.r, ctx->sched[0 xd]);
F_ENCRYPT(X.r, X.l, ctx->sched[0 xc]);
F_ENCRYPT(X.l, X.r, ctx->sched[0 xb]);
F_ENCRYPT(X.r, X.l, ctx->sched[0 xa]);
F_ENCRYPT(X.l, X.r, ctx->sched[0 x9]);
F_ENCRYPT(X.r, X.l, ctx->sched[0 x8]);
F_ENCRYPT(X.l, X.r, ctx->sched[0 x7]);
F_ENCRYPT(X.r, X.l, ctx->sched[0 x6]);
F_ENCRYPT(X.l, X.r, ctx->sched[0 x5]);
F_ENCRYPT(X.r, X.l, ctx->sched[0 x4]);
F_ENCRYPT(X.l, X.r, ctx->sched[0 x3]);
F_ENCRYPT(X.r, X.l, ctx->sched[0 x2]);
F_ENCRYPT(X.l, X.r, ctx->sched[0 x1]);
F_ENCRYPT(X.r, X.l, ctx->sched[0 x0]);
memcpy(dst, &X, sizeof (X));
}
/*
* Generate a key schedule from key, the least significant bit in each key byte
* is parity and shall be ignored. This leaves 56 significant bits in the key
* to scatter over the 16 key schedules. For each schedule extract the low
* order 32 bits and use as schedule, then rotate right by 11 bits.
*/
static int fcrypt_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
{
struct fcrypt_ctx *ctx = crypto_tfm_ctx(tfm);
#if BITS_PER_LONG == 64 /* the 64-bit version can also be used for 32-bit
* kernels - it seems to be faster but the code is
* larger */
u64 k; /* k holds all 56 non-parity bits */
/* discard the parity bits */
k = (*key++) >> 1 ;
k <<= 7 ;
k |= (*key++) >> 1 ;
k <<= 7 ;
k |= (*key++) >> 1 ;
k <<= 7 ;
k |= (*key++) >> 1 ;
k <<= 7 ;
k |= (*key++) >> 1 ;
k <<= 7 ;
k |= (*key++) >> 1 ;
k <<= 7 ;
k |= (*key++) >> 1 ;
k <<= 7 ;
k |= (*key) >> 1 ;
/* Use lower 32 bits for schedule, rotate by 11 each round (16 times) */
ctx->sched[0 x0] = cpu_to_be32(k); ror56_64(k, 11 );
ctx->sched[0 x1] = cpu_to_be32(k); ror56_64(k, 11 );
ctx->sched[0 x2] = cpu_to_be32(k); ror56_64(k, 11 );
ctx->sched[0 x3] = cpu_to_be32(k); ror56_64(k, 11 );
ctx->sched[0 x4] = cpu_to_be32(k); ror56_64(k, 11 );
ctx->sched[0 x5] = cpu_to_be32(k); ror56_64(k, 11 );
ctx->sched[0 x6] = cpu_to_be32(k); ror56_64(k, 11 );
ctx->sched[0 x7] = cpu_to_be32(k); ror56_64(k, 11 );
ctx->sched[0 x8] = cpu_to_be32(k); ror56_64(k, 11 );
ctx->sched[0 x9] = cpu_to_be32(k); ror56_64(k, 11 );
ctx->sched[0 xa] = cpu_to_be32(k); ror56_64(k, 11 );
ctx->sched[0 xb] = cpu_to_be32(k); ror56_64(k, 11 );
ctx->sched[0 xc] = cpu_to_be32(k); ror56_64(k, 11 );
ctx->sched[0 xd] = cpu_to_be32(k); ror56_64(k, 11 );
ctx->sched[0 xe] = cpu_to_be32(k); ror56_64(k, 11 );
ctx->sched[0 xf] = cpu_to_be32(k);
return 0 ;
#else
u32 hi, lo; /* hi is upper 24 bits and lo lower 32, total 56 */
/* discard the parity bits */
lo = (*key++) >> 1 ;
lo <<= 7 ;
lo |= (*key++) >> 1 ;
lo <<= 7 ;
lo |= (*key++) >> 1 ;
lo <<= 7 ;
lo |= (*key++) >> 1 ;
hi = lo >> 4 ;
lo &= 0 xf;
lo <<= 7 ;
lo |= (*key++) >> 1 ;
lo <<= 7 ;
lo |= (*key++) >> 1 ;
lo <<= 7 ;
lo |= (*key++) >> 1 ;
lo <<= 7 ;
lo |= (*key) >> 1 ;
/* Use lower 32 bits for schedule, rotate by 11 each round (16 times) */
ctx->sched[0 x0] = cpu_to_be32(lo); ror56(hi, lo, 11 );
ctx->sched[0 x1] = cpu_to_be32(lo); ror56(hi, lo, 11 );
ctx->sched[0 x2] = cpu_to_be32(lo); ror56(hi, lo, 11 );
ctx->sched[0 x3] = cpu_to_be32(lo); ror56(hi, lo, 11 );
ctx->sched[0 x4] = cpu_to_be32(lo); ror56(hi, lo, 11 );
ctx->sched[0 x5] = cpu_to_be32(lo); ror56(hi, lo, 11 );
ctx->sched[0 x6] = cpu_to_be32(lo); ror56(hi, lo, 11 );
ctx->sched[0 x7] = cpu_to_be32(lo); ror56(hi, lo, 11 );
ctx->sched[0 x8] = cpu_to_be32(lo); ror56(hi, lo, 11 );
ctx->sched[0 x9] = cpu_to_be32(lo); ror56(hi, lo, 11 );
ctx->sched[0 xa] = cpu_to_be32(lo); ror56(hi, lo, 11 );
ctx->sched[0 xb] = cpu_to_be32(lo); ror56(hi, lo, 11 );
ctx->sched[0 xc] = cpu_to_be32(lo); ror56(hi, lo, 11 );
ctx->sched[0 xd] = cpu_to_be32(lo); ror56(hi, lo, 11 );
ctx->sched[0 xe] = cpu_to_be32(lo); ror56(hi, lo, 11 );
ctx->sched[0 xf] = cpu_to_be32(lo);
return 0 ;
#endif
}
static struct crypto_alg fcrypt_alg = {
.cra_name = "fcrypt" ,
.cra_driver_name = "fcrypt-generic" ,
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
.cra_blocksize = 8 ,
.cra_ctxsize = sizeof (struct fcrypt_ctx),
.cra_module = THIS_MODULE,
.cra_u = { .cipher = {
.cia_min_keysize = 8 ,
.cia_max_keysize = 8 ,
.cia_setkey = fcrypt_setkey,
.cia_encrypt = fcrypt_encrypt,
.cia_decrypt = fcrypt_decrypt } }
};
static int __init fcrypt_mod_init(void )
{
return crypto_register_alg(&fcrypt_alg);
}
static void __exit fcrypt_mod_fini(void )
{
crypto_unregister_alg(&fcrypt_alg);
}
module_init(fcrypt_mod_init);
module_exit(fcrypt_mod_fini);
MODULE_LICENSE("Dual BSD/GPL" );
MODULE_DESCRIPTION("FCrypt Cipher Algorithm" );
MODULE_AUTHOR("David Howells <dhowells@redhat.com>" );
MODULE_ALIAS_CRYPTO("fcrypt" );
Messung V0.5 in Prozent C=97 H=82 G=89