00001
00002
00003
#include "pch.h"
00004
#include "safer.h"
00005
#include "misc.h"
00006
00007 NAMESPACE_BEGIN(CryptoPP)
00008
00009 const byte
SAFER::Base::exp_tab[256] =
00010 {1, 45, 226, 147, 190, 69, 21, 174, 120, 3, 135, 164, 184, 56, 207, 63,
00011 8, 103, 9, 148, 235, 38, 168, 107, 189, 24, 52, 27, 187, 191, 114, 247,
00012 64, 53, 72, 156, 81, 47, 59, 85, 227, 192, 159, 216, 211, 243, 141, 177,
00013 255, 167, 62, 220, 134, 119, 215, 166, 17, 251, 244, 186, 146, 145, 100, 131,
00014 241, 51, 239, 218, 44, 181, 178, 43, 136, 209, 153, 203, 140, 132, 29, 20,
00015 129, 151, 113, 202, 95, 163, 139, 87, 60, 130, 196, 82, 92, 28, 232, 160,
00016 4, 180, 133, 74, 246, 19, 84, 182, 223, 12, 26, 142, 222, 224, 57, 252,
00017 32, 155, 36, 78, 169, 152, 158, 171, 242, 96, 208, 108, 234, 250, 199, 217,
00018 0, 212, 31, 110, 67, 188, 236, 83, 137, 254, 122, 93, 73, 201, 50, 194,
00019 249, 154, 248, 109, 22, 219, 89, 150, 68, 233, 205, 230, 70, 66, 143, 10,
00020 193, 204, 185, 101, 176, 210, 198, 172, 30, 65, 98, 41, 46, 14, 116, 80,
00021 2, 90, 195, 37, 123, 138, 42, 91, 240, 6, 13, 71, 111, 112, 157, 126,
00022 16, 206, 18, 39, 213, 76, 79, 214, 121, 48, 104, 54, 117, 125, 228, 237,
00023 128, 106, 144, 55, 162, 94, 118, 170, 197, 127, 61, 175, 165, 229, 25, 97,
00024 253, 77, 124, 183, 11, 238, 173, 75, 34, 245, 231, 115, 35, 33, 200, 5,
00025 225, 102, 221, 179, 88, 105, 99, 86, 15, 161, 49, 149, 23, 7, 58, 40};
00026
00027
const byte SAFER::Base::log_tab[256] =
00028 {128, 0, 176, 9, 96, 239, 185, 253, 16, 18, 159, 228, 105, 186, 173, 248,
00029 192, 56, 194, 101, 79, 6, 148, 252, 25, 222, 106, 27, 93, 78, 168, 130,
00030 112, 237, 232, 236, 114, 179, 21, 195, 255, 171, 182, 71, 68, 1, 172, 37,
00031 201, 250, 142, 65, 26, 33, 203, 211, 13, 110, 254, 38, 88, 218, 50, 15,
00032 32, 169, 157, 132, 152, 5, 156, 187, 34, 140, 99, 231, 197, 225, 115, 198,
00033 175, 36, 91, 135, 102, 39, 247, 87, 244, 150, 177, 183, 92, 139, 213, 84,
00034 121, 223, 170, 246, 62, 163, 241, 17, 202, 245, 209, 23, 123, 147, 131, 188,
00035 189, 82, 30, 235, 174, 204, 214, 53, 8, 200, 138, 180, 226, 205, 191, 217,
00036 208, 80, 89, 63, 77, 98, 52, 10, 72, 136, 181, 86, 76, 46, 107, 158,
00037 210, 61, 60, 3, 19, 251, 151, 81, 117, 74, 145, 113, 35, 190, 118, 42,
00038 95, 249, 212, 85, 11, 220, 55, 49, 22, 116, 215, 119, 167, 230, 7, 219,
00039 164, 47, 70, 243, 97, 69, 103, 227, 12, 162, 59, 28, 133, 24, 4, 29,
00040 41, 160, 143, 178, 90, 216, 166, 126, 238, 141, 83, 75, 161, 154, 193, 14,
00041 122, 73, 165, 44, 129, 196, 199, 54, 43, 127, 67, 149, 51, 242, 108, 104,
00042 109, 240, 2, 40, 206, 221, 155, 234, 94, 153, 124, 20, 134, 207, 229, 66,
00043 184, 64, 120, 45, 58, 233, 100, 31, 146, 144, 125, 57, 111, 224, 137, 48};
00044
00045
#define EXP(x) exp_tab[(x)]
00046
#define LOG(x) log_tab[(x)]
00047
#define PHT(x, y) { y += x; x += y; }
00048
#define IPHT(x, y) { x -= y; y -= x; }
00049
00050
static const unsigned int BLOCKSIZE = 8;
00051
static const unsigned int MAX_ROUNDS = 13;
00052
00053
void SAFER::Base::UncheckedSetKey(CipherDir dir,
const byte *userkey_1,
unsigned int length,
unsigned nof_rounds)
00054 {
00055
const byte *userkey_2 = length == 8 ? userkey_1 : userkey_1 + 8;
00056 keySchedule.New(1 + BLOCKSIZE * (1 + 2 * nof_rounds));
00057
00058
unsigned int i, j;
00059 byte *key = keySchedule;
00060
SecByteBlock ka(BLOCKSIZE + 1), kb(BLOCKSIZE + 1);
00061
00062
if (MAX_ROUNDS < nof_rounds)
00063 nof_rounds = MAX_ROUNDS;
00064 *key++ = (
unsigned char)nof_rounds;
00065 ka[BLOCKSIZE] = 0;
00066 kb[BLOCKSIZE] = 0;
00067
for (j = 0; j < BLOCKSIZE; j++)
00068 {
00069 ka[BLOCKSIZE] ^= ka[j] = rotlFixed(userkey_1[j], 5U);
00070 kb[BLOCKSIZE] ^= kb[j] = *key++ = userkey_2[j];
00071 }
00072
for (i = 1; i <= nof_rounds; i++)
00073 {
00074
for (j = 0; j < BLOCKSIZE + 1; j++)
00075 {
00076 ka[j] = rotlFixed(ka[j], 6U);
00077 kb[j] = rotlFixed(kb[j], 6U);
00078 }
00079
for (j = 0; j < BLOCKSIZE; j++)
00080
if (strengthened)
00081 *key++ = (ka[(j + 2 * i - 1) % (BLOCKSIZE + 1)]
00082 + exp_tab[exp_tab[18 * i + j + 1]]) & 0xFF;
00083
else
00084 *key++ = (ka[j] + exp_tab[exp_tab[18 * i + j + 1]]) & 0xFF;
00085
for (j = 0; j < BLOCKSIZE; j++)
00086
if (strengthened)
00087 *key++ = (kb[(j + 2 * i) % (BLOCKSIZE + 1)]
00088 + exp_tab[exp_tab[18 * i + j + 10]]) & 0xFF;
00089
else
00090 *key++ = (kb[j] + exp_tab[exp_tab[18 * i + j + 10]]) & 0xFF;
00091 }
00092 }
00093
00094
typedef BlockGetAndPut<byte, BigEndian> Block;
00095
00096
void SAFER::Enc::ProcessAndXorBlock(
const byte *inBlock,
const byte *xorBlock, byte *outBlock)
const
00097
{
00098 byte a, b, c, d, e, f, g, h, t;
00099
const byte *key = keySchedule+1;
00100
unsigned int round = keySchedule[0];
00101
00102 Block::Get(inBlock)(a)(b)(c)(d)(e)(f)(g)(h);
00103
while(round--)
00104 {
00105 a ^= key[0]; b += key[1]; c += key[2]; d ^= key[3];
00106 e ^= key[4]; f += key[5]; g += key[6]; h ^= key[7];
00107 a = EXP(a) + key[ 8]; b = LOG(b) ^ key[ 9];
00108 c = LOG(c) ^ key[10]; d = EXP(d) + key[11];
00109 e = EXP(e) + key[12]; f = LOG(f) ^ key[13];
00110 g = LOG(g) ^ key[14]; h = EXP(h) + key[15];
00111 key += 16;
00112 PHT(a, b); PHT(c, d); PHT(e, f); PHT(g, h);
00113 PHT(a, c); PHT(e, g); PHT(b, d); PHT(f, h);
00114 PHT(a, e); PHT(b, f); PHT(c, g); PHT(d, h);
00115 t = b; b = e; e = c; c = t; t = d; d = f; f = g; g = t;
00116 }
00117 a ^= key[0]; b += key[1]; c += key[2]; d ^= key[3];
00118 e ^= key[4]; f += key[5]; g += key[6]; h ^= key[7];
00119 Block::Put(xorBlock, outBlock)(a)(b)(c)(d)(e)(f)(g)(h);
00120 }
00121
00122
void SAFER::Dec::ProcessAndXorBlock(
const byte *inBlock,
const byte *xorBlock, byte *outBlock)
const
00123
{
00124 byte a, b, c, d, e, f, g, h, t;
00125
unsigned int round = keySchedule[0];
00126
const byte *key = keySchedule + BLOCKSIZE * (1 + 2 * round) - 7;
00127
00128 Block::Get(inBlock)(a)(b)(c)(d)(e)(f)(g)(h);
00129 h ^= key[7]; g -= key[6]; f -= key[5]; e ^= key[4];
00130 d ^= key[3]; c -= key[2]; b -= key[1]; a ^= key[0];
00131
while (round--)
00132 {
00133 key -= 16;
00134 t = e; e = b; b = c; c = t; t = f; f = d; d = g; g = t;
00135 IPHT(a, e); IPHT(b, f); IPHT(c, g); IPHT(d, h);
00136 IPHT(a, c); IPHT(e, g); IPHT(b, d); IPHT(f, h);
00137 IPHT(a, b); IPHT(c, d); IPHT(e, f); IPHT(g, h);
00138 h -= key[15]; g ^= key[14]; f ^= key[13]; e -= key[12];
00139 d -= key[11]; c ^= key[10]; b ^= key[9]; a -= key[8];
00140 h = LOG(h) ^ key[7]; g = EXP(g) - key[6];
00141 f = EXP(f) - key[5]; e = LOG(e) ^ key[4];
00142 d = LOG(d) ^ key[3]; c = EXP(c) - key[2];
00143 b = EXP(b) - key[1]; a = LOG(a) ^ key[0];
00144 }
00145 Block::Put(xorBlock, outBlock)(a)(b)(c)(d)(e)(f)(g)(h);
00146 }
00147
00148 NAMESPACE_END