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