1 /** 2 * MISTY1 3 * 4 * Copyright: 5 * (C) 1999-2008 Jack Lloyd 6 * (C) 2014-2015 Etienne Cimon 7 * 8 * License: 9 * Botan is released under the Simplified BSD License (see LICENSE.md) 10 */ 11 module botan.block.misty1; 12 13 import botan.constants; 14 static if (BOTAN_HAS_MISTY1): 15 16 import botan.block.block_cipher; 17 import botan.utils.loadstor; 18 import botan.utils.parsing; 19 import std.conv : to; 20 import botan.utils.mem_ops; 21 22 /** 23 * MISTY1 24 */ 25 final class MISTY1 : BlockCipherFixedParams!(8, 16), BlockCipher, SymmetricAlgorithm 26 { 27 public: 28 /* 29 * MISTY1 Encryption 30 */ 31 override void encryptN(const(ubyte)* input, ubyte* output, size_t blocks) 32 { 33 foreach (size_t i; 0 .. blocks) 34 { 35 ushort B0 = loadBigEndian!ushort(input, 0); 36 ushort B1 = loadBigEndian!ushort(input, 1); 37 ushort B2 = loadBigEndian!ushort(input, 2); 38 ushort B3 = loadBigEndian!ushort(input, 3); 39 40 for (size_t j = 0; j != 12; j += 3) 41 { 42 const ushort* RK = &m_EK[8 * j]; 43 44 B1 ^= B0 & RK[0]; 45 B0 ^= B1 | RK[1]; 46 B3 ^= B2 & RK[2]; 47 B2 ^= B3 | RK[3]; 48 49 ushort T0, T1; 50 51 T0 = FI(B0 ^ RK[ 4], RK[ 5], RK[ 6]) ^ B1; 52 T1 = FI(B1 ^ RK[ 7], RK[ 8], RK[ 9]) ^ T0; 53 T0 = FI(T0 ^ RK[10], RK[11], RK[12]) ^ T1; 54 55 B2 ^= T1 ^ RK[13]; 56 B3 ^= T0; 57 58 T0 = FI(B2 ^ RK[14], RK[15], RK[16]) ^ B3; 59 T1 = FI(B3 ^ RK[17], RK[18], RK[19]) ^ T0; 60 T0 = FI(T0 ^ RK[20], RK[21], RK[22]) ^ T1; 61 62 B0 ^= T1 ^ RK[23]; 63 B1 ^= T0; 64 } 65 66 B1 ^= B0 & m_EK[96]; 67 B0 ^= B1 | m_EK[97]; 68 B3 ^= B2 & m_EK[98]; 69 B2 ^= B3 | m_EK[99]; 70 71 storeBigEndian(output, B2, B3, B0, B1); 72 73 input += BLOCK_SIZE; 74 output += BLOCK_SIZE; 75 } 76 } 77 78 /* 79 * MISTY1 Decryption 80 */ 81 override void decryptN(const(ubyte)* input, ubyte* output, size_t blocks) 82 { 83 foreach (size_t i; 0 .. blocks) 84 { 85 ushort B0 = loadBigEndian!ushort(input, 2); 86 ushort B1 = loadBigEndian!ushort(input, 3); 87 ushort B2 = loadBigEndian!ushort(input, 0); 88 ushort B3 = loadBigEndian!ushort(input, 1); 89 90 for (size_t j = 0; j != 12; j += 3) 91 { 92 const ushort* RK = &m_DK[8 * j]; 93 94 B2 ^= B3 | RK[0]; 95 B3 ^= B2 & RK[1]; 96 B0 ^= B1 | RK[2]; 97 B1 ^= B0 & RK[3]; 98 99 ushort T0, T1; 100 101 T0 = FI(B2 ^ RK[ 4], RK[ 5], RK[ 6]) ^ B3; 102 T1 = FI(B3 ^ RK[ 7], RK[ 8], RK[ 9]) ^ T0; 103 T0 = FI(T0 ^ RK[10], RK[11], RK[12]) ^ T1; 104 105 B0 ^= T1 ^ RK[13]; 106 B1 ^= T0; 107 108 T0 = FI(B0 ^ RK[14], RK[15], RK[16]) ^ B1; 109 T1 = FI(B1 ^ RK[17], RK[18], RK[19]) ^ T0; 110 T0 = FI(T0 ^ RK[20], RK[21], RK[22]) ^ T1; 111 112 B2 ^= T1 ^ RK[23]; 113 B3 ^= T0; 114 } 115 116 B2 ^= B3 | m_DK[96]; 117 B3 ^= B2 & m_DK[97]; 118 B0 ^= B1 | m_DK[98]; 119 B1 ^= B0 & m_DK[99]; 120 121 storeBigEndian(output, B0, B1, B2, B3); 122 123 input += BLOCK_SIZE; 124 output += BLOCK_SIZE; 125 } 126 } 127 128 override void clear() 129 { 130 zap(m_EK); 131 zap(m_DK); 132 } 133 134 @property string name() const { return "MISTY1"; } 135 override @property size_t parallelism() const { return 1; } 136 override BlockCipher clone() const { return new MISTY1; } 137 override size_t blockSize() const { return super.blockSize(); } 138 override KeyLengthSpecification keySpec() const { return super.keySpec(); } 139 140 /** 141 * Params: 142 * rounds = the number of rounds. Must be 8 with the current 143 * implementation 144 */ 145 this(size_t rounds = 8) 146 { 147 if (rounds != 8) 148 throw new InvalidArgument("MISTY1: Invalid number of rounds: " ~ to!string(rounds)); 149 } 150 151 protected: 152 /* 153 * MISTY1 Key Schedule 154 */ 155 override void keySchedule(const(ubyte)* key, size_t length) 156 { 157 SecureVector!ushort KS = SecureVector!ushort(32); 158 foreach (size_t i; 0 .. (length / 2)) 159 KS[i] = loadBigEndian!ushort(key, i); 160 161 foreach (size_t i; 0 .. 8) 162 { 163 KS[i+ 8] = FI(KS[i], KS[(i+1) % 8] >> 9, KS[(i+1) % 8] & 0x1FF); 164 KS[i+16] = KS[i+8] >> 9; 165 KS[i+24] = KS[i+8] & 0x1FF; 166 } 167 168 /* 169 * Precomputed indexes for the orderings of the subkeys (MISTY1 reuses 170 * values) 171 */ 172 __gshared immutable ubyte[100] EK_ORDER = [ 173 0x00, 0x0E, 0x0A, 0x04, 0x00, 0x15, 0x1D, 0x02, 0x11, 0x19, 0x07, 0x13, 174 0x1B, 0x04, 0x01, 0x16, 0x1E, 0x03, 0x12, 0x1A, 0x00, 0x14, 0x1C, 0x05, 175 0x01, 0x0F, 0x0B, 0x05, 0x02, 0x17, 0x1F, 0x04, 0x13, 0x1B, 0x01, 0x15, 176 0x1D, 0x06, 0x03, 0x10, 0x18, 0x05, 0x14, 0x1C, 0x02, 0x16, 0x1E, 0x07, 177 0x02, 0x08, 0x0C, 0x06, 0x04, 0x11, 0x19, 0x06, 0x15, 0x1D, 0x03, 0x17, 178 0x1F, 0x00, 0x05, 0x12, 0x1A, 0x07, 0x16, 0x1E, 0x04, 0x10, 0x18, 0x01, 179 0x03, 0x09, 0x0D, 0x07, 0x06, 0x13, 0x1B, 0x00, 0x17, 0x1F, 0x05, 0x11, 180 0x19, 0x02, 0x07, 0x14, 0x1C, 0x01, 0x10, 0x18, 0x06, 0x12, 0x1A, 0x03, 181 0x04, 0x0A, 0x0E, 0x00 ]; 182 183 __gshared immutable ubyte[100] DK_ORDER = [ 184 0x00, 0x0E, 0x0A, 0x04, 0x07, 0x14, 0x1C, 0x01, 0x10, 0x18, 0x06, 0x12, 185 0x1A, 0x03, 0x06, 0x13, 0x1B, 0x00, 0x17, 0x1F, 0x05, 0x11, 0x19, 0x02, 186 0x07, 0x0D, 0x09, 0x03, 0x05, 0x12, 0x1A, 0x07, 0x16, 0x1E, 0x04, 0x10, 187 0x18, 0x01, 0x04, 0x11, 0x19, 0x06, 0x15, 0x1D, 0x03, 0x17, 0x1F, 0x00, 188 0x06, 0x0C, 0x08, 0x02, 0x03, 0x10, 0x18, 0x05, 0x14, 0x1C, 0x02, 0x16, 189 0x1E, 0x07, 0x02, 0x17, 0x1F, 0x04, 0x13, 0x1B, 0x01, 0x15, 0x1D, 0x06, 190 0x05, 0x0B, 0x0F, 0x01, 0x01, 0x16, 0x1E, 0x03, 0x12, 0x1A, 0x00, 0x14, 191 0x1C, 0x05, 0x00, 0x15, 0x1D, 0x02, 0x11, 0x19, 0x07, 0x13, 0x1B, 0x04, 192 0x04, 0x0A, 0x0E, 0x00 ]; 193 194 m_EK.resize(100); 195 m_DK.resize(100); 196 197 foreach (size_t i; 0 .. 100) 198 { 199 m_EK[i] = KS[EK_ORDER[i]]; 200 m_DK[i] = KS[DK_ORDER[i]]; 201 } 202 } 203 204 205 206 SecureVector!ushort m_EK, m_DK; 207 } 208 209 private: 210 211 __gshared immutable ubyte[128] MISTY1_SBOX_S7 = [ 212 0x1B, 0x32, 0x33, 0x5A, 0x3B, 0x10, 0x17, 0x54, 0x5B, 0x1A, 0x72, 0x73, 213 0x6B, 0x2C, 0x66, 0x49, 0x1F, 0x24, 0x13, 0x6C, 0x37, 0x2E, 0x3F, 0x4A, 214 0x5D, 0x0F, 0x40, 0x56, 0x25, 0x51, 0x1C, 0x04, 0x0B, 0x46, 0x20, 0x0D, 215 0x7B, 0x35, 0x44, 0x42, 0x2B, 0x1E, 0x41, 0x14, 0x4B, 0x79, 0x15, 0x6F, 216 0x0E, 0x55, 0x09, 0x36, 0x74, 0x0C, 0x67, 0x53, 0x28, 0x0A, 0x7E, 0x38, 217 0x02, 0x07, 0x60, 0x29, 0x19, 0x12, 0x65, 0x2F, 0x30, 0x39, 0x08, 0x68, 218 0x5F, 0x78, 0x2A, 0x4C, 0x64, 0x45, 0x75, 0x3D, 0x59, 0x48, 0x03, 0x57, 219 0x7C, 0x4F, 0x62, 0x3C, 0x1D, 0x21, 0x5E, 0x27, 0x6A, 0x70, 0x4D, 0x3A, 220 0x01, 0x6D, 0x6E, 0x63, 0x18, 0x77, 0x23, 0x05, 0x26, 0x76, 0x00, 0x31, 221 0x2D, 0x7A, 0x7F, 0x61, 0x50, 0x22, 0x11, 0x06, 0x47, 0x16, 0x52, 0x4E, 222 0x71, 0x3E, 0x69, 0x43, 0x34, 0x5C, 0x58, 0x7D ]; 223 224 __gshared immutable ushort[512] MISTY1_SBOX_S9 = [ 225 0x01C3, 0x00CB, 0x0153, 0x019F, 0x01E3, 0x00E9, 0x00FB, 0x0035, 0x0181, 226 0x00B9, 0x0117, 0x01EB, 0x0133, 0x0009, 0x002D, 0x00D3, 0x00C7, 0x014A, 227 0x0037, 0x007E, 0x00EB, 0x0164, 0x0193, 0x01D8, 0x00A3, 0x011E, 0x0055, 228 0x002C, 0x001D, 0x01A2, 0x0163, 0x0118, 0x014B, 0x0152, 0x01D2, 0x000F, 229 0x002B, 0x0030, 0x013A, 0x00E5, 0x0111, 0x0138, 0x018E, 0x0063, 0x00E3, 230 0x00C8, 0x01F4, 0x001B, 0x0001, 0x009D, 0x00F8, 0x01A0, 0x016D, 0x01F3, 231 0x001C, 0x0146, 0x007D, 0x00D1, 0x0082, 0x01EA, 0x0183, 0x012D, 0x00F4, 232 0x019E, 0x01D3, 0x00DD, 0x01E2, 0x0128, 0x01E0, 0x00EC, 0x0059, 0x0091, 233 0x0011, 0x012F, 0x0026, 0x00DC, 0x00B0, 0x018C, 0x010F, 0x01F7, 0x00E7, 234 0x016C, 0x00B6, 0x00F9, 0x00D8, 0x0151, 0x0101, 0x014C, 0x0103, 0x00B8, 235 0x0154, 0x012B, 0x01AE, 0x0017, 0x0071, 0x000C, 0x0047, 0x0058, 0x007F, 236 0x01A4, 0x0134, 0x0129, 0x0084, 0x015D, 0x019D, 0x01B2, 0x01A3, 0x0048, 237 0x007C, 0x0051, 0x01CA, 0x0023, 0x013D, 0x01A7, 0x0165, 0x003B, 0x0042, 238 0x00DA, 0x0192, 0x00CE, 0x00C1, 0x006B, 0x009F, 0x01F1, 0x012C, 0x0184, 239 0x00FA, 0x0196, 0x01E1, 0x0169, 0x017D, 0x0031, 0x0180, 0x010A, 0x0094, 240 0x01DA, 0x0186, 0x013E, 0x011C, 0x0060, 0x0175, 0x01CF, 0x0067, 0x0119, 241 0x0065, 0x0068, 0x0099, 0x0150, 0x0008, 0x0007, 0x017C, 0x00B7, 0x0024, 242 0x0019, 0x00DE, 0x0127, 0x00DB, 0x00E4, 0x01A9, 0x0052, 0x0109, 0x0090, 243 0x019C, 0x01C1, 0x0028, 0x01B3, 0x0135, 0x016A, 0x0176, 0x00DF, 0x01E5, 244 0x0188, 0x00C5, 0x016E, 0x01DE, 0x01B1, 0x00C3, 0x01DF, 0x0036, 0x00EE, 245 0x01EE, 0x00F0, 0x0093, 0x0049, 0x009A, 0x01B6, 0x0069, 0x0081, 0x0125, 246 0x000B, 0x005E, 0x00B4, 0x0149, 0x01C7, 0x0174, 0x003E, 0x013B, 0x01B7, 247 0x008E, 0x01C6, 0x00AE, 0x0010, 0x0095, 0x01EF, 0x004E, 0x00F2, 0x01FD, 248 0x0085, 0x00FD, 0x00F6, 0x00A0, 0x016F, 0x0083, 0x008A, 0x0156, 0x009B, 249 0x013C, 0x0107, 0x0167, 0x0098, 0x01D0, 0x01E9, 0x0003, 0x01FE, 0x00BD, 250 0x0122, 0x0089, 0x00D2, 0x018F, 0x0012, 0x0033, 0x006A, 0x0142, 0x00ED, 251 0x0170, 0x011B, 0x00E2, 0x014F, 0x0158, 0x0131, 0x0147, 0x005D, 0x0113, 252 0x01CD, 0x0079, 0x0161, 0x01A5, 0x0179, 0x009E, 0x01B4, 0x00CC, 0x0022, 253 0x0132, 0x001A, 0x00E8, 0x0004, 0x0187, 0x01ED, 0x0197, 0x0039, 0x01BF, 254 0x01D7, 0x0027, 0x018B, 0x00C6, 0x009C, 0x00D0, 0x014E, 0x006C, 0x0034, 255 0x01F2, 0x006E, 0x00CA, 0x0025, 0x00BA, 0x0191, 0x00FE, 0x0013, 0x0106, 256 0x002F, 0x01AD, 0x0172, 0x01DB, 0x00C0, 0x010B, 0x01D6, 0x00F5, 0x01EC, 257 0x010D, 0x0076, 0x0114, 0x01AB, 0x0075, 0x010C, 0x01E4, 0x0159, 0x0054, 258 0x011F, 0x004B, 0x00C4, 0x01BE, 0x00F7, 0x0029, 0x00A4, 0x000E, 0x01F0, 259 0x0077, 0x004D, 0x017A, 0x0086, 0x008B, 0x00B3, 0x0171, 0x00BF, 0x010E, 260 0x0104, 0x0097, 0x015B, 0x0160, 0x0168, 0x00D7, 0x00BB, 0x0066, 0x01CE, 261 0x00FC, 0x0092, 0x01C5, 0x006F, 0x0016, 0x004A, 0x00A1, 0x0139, 0x00AF, 262 0x00F1, 0x0190, 0x000A, 0x01AA, 0x0143, 0x017B, 0x0056, 0x018D, 0x0166, 263 0x00D4, 0x01FB, 0x014D, 0x0194, 0x019A, 0x0087, 0x01F8, 0x0123, 0x00A7, 264 0x01B8, 0x0141, 0x003C, 0x01F9, 0x0140, 0x002A, 0x0155, 0x011A, 0x01A1, 265 0x0198, 0x00D5, 0x0126, 0x01AF, 0x0061, 0x012E, 0x0157, 0x01DC, 0x0072, 266 0x018A, 0x00AA, 0x0096, 0x0115, 0x00EF, 0x0045, 0x007B, 0x008D, 0x0145, 267 0x0053, 0x005F, 0x0178, 0x00B2, 0x002E, 0x0020, 0x01D5, 0x003F, 0x01C9, 268 0x01E7, 0x01AC, 0x0044, 0x0038, 0x0014, 0x00B1, 0x016B, 0x00AB, 0x00B5, 269 0x005A, 0x0182, 0x01C8, 0x01D4, 0x0018, 0x0177, 0x0064, 0x00CF, 0x006D, 270 0x0100, 0x0199, 0x0130, 0x015A, 0x0005, 0x0120, 0x01BB, 0x01BD, 0x00E0, 271 0x004F, 0x00D6, 0x013F, 0x01C4, 0x012A, 0x0015, 0x0006, 0x00FF, 0x019B, 272 0x00A6, 0x0043, 0x0088, 0x0050, 0x015F, 0x01E8, 0x0121, 0x0073, 0x017E, 273 0x00BC, 0x00C2, 0x00C9, 0x0173, 0x0189, 0x01F5, 0x0074, 0x01CC, 0x01E6, 274 0x01A8, 0x0195, 0x001F, 0x0041, 0x000D, 0x01BA, 0x0032, 0x003D, 0x01D1, 275 0x0080, 0x00A8, 0x0057, 0x01B9, 0x0162, 0x0148, 0x00D9, 0x0105, 0x0062, 276 0x007A, 0x0021, 0x01FF, 0x0112, 0x0108, 0x01C0, 0x00A9, 0x011D, 0x01B0, 277 0x01A6, 0x00CD, 0x00F3, 0x005C, 0x0102, 0x005B, 0x01D9, 0x0144, 0x01F6, 278 0x00AD, 0x00A5, 0x003A, 0x01CB, 0x0136, 0x017F, 0x0046, 0x00E1, 0x001E, 279 0x01DD, 0x00E6, 0x0137, 0x01FA, 0x0185, 0x008C, 0x008F, 0x0040, 0x01B5, 280 0x00BE, 0x0078, 0x0000, 0x00AC, 0x0110, 0x015E, 0x0124, 0x0002, 0x01BC, 281 0x00A2, 0x00EA, 0x0070, 0x01FC, 0x0116, 0x015C, 0x004C, 0x01C2 ]; 282 283 /* 284 * MISTY1 FI Function 285 */ 286 ushort FI(in ushort input, in ushort key7, in ushort key9) pure 287 { 288 ushort D9 = input >> 7, D7 = input & 0x7F; 289 D9 = MISTY1_SBOX_S9[D9] ^ D7; 290 D7 = (MISTY1_SBOX_S7[D7] ^ key7 ^ D9) & 0x7F; 291 D9 = MISTY1_SBOX_S9[D9 ^ key9] ^ D7; 292 return cast(ushort)((D7 << 9) | D9); 293 }