1 /** 2 * MARS 3 * 4 * Copyright: 5 * (C) 1999-2007 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.mars; 12 13 import botan.constants; 14 static if (BOTAN_HAS_MARS): 15 16 import std.range : iota; 17 import botan.block.block_cipher; 18 import botan.utils.loadstor; 19 import botan.utils.rotate; 20 import botan.utils.get_byte; 21 import botan.utils.mem_ops; 22 23 /** 24 * MARS, IBM's candidate for AES 25 */ 26 final class MARS : BlockCipherFixedParams!(16, 16, 32, 4), BlockCipher, SymmetricAlgorithm 27 { 28 public: 29 /* 30 * MARS Encryption 31 */ 32 override void encryptN(const(ubyte)* input, ubyte* output, size_t blocks) 33 { 34 foreach (size_t i; 0 .. blocks) 35 { 36 uint A = loadLittleEndian!uint(input, 0) + m_EK[0]; 37 uint B = loadLittleEndian!uint(input, 1) + m_EK[1]; 38 uint C = loadLittleEndian!uint(input, 2) + m_EK[2]; 39 uint D = loadLittleEndian!uint(input, 3) + m_EK[3]; 40 41 forward_mix(A, B, C, D); 42 43 encrypt_round(A, B, C, D, m_EK[ 4], m_EK[ 5]); 44 encrypt_round(B, C, D, A, m_EK[ 6], m_EK[ 7]); 45 encrypt_round(C, D, A, B, m_EK[ 8], m_EK[ 9]); 46 encrypt_round(D, A, B, C, m_EK[10], m_EK[11]); 47 encrypt_round(A, B, C, D, m_EK[12], m_EK[13]); 48 encrypt_round(B, C, D, A, m_EK[14], m_EK[15]); 49 encrypt_round(C, D, A, B, m_EK[16], m_EK[17]); 50 encrypt_round(D, A, B, C, m_EK[18], m_EK[19]); 51 52 encrypt_round(A, D, C, B, m_EK[20], m_EK[21]); 53 encrypt_round(B, A, D, C, m_EK[22], m_EK[23]); 54 encrypt_round(C, B, A, D, m_EK[24], m_EK[25]); 55 encrypt_round(D, C, B, A, m_EK[26], m_EK[27]); 56 encrypt_round(A, D, C, B, m_EK[28], m_EK[29]); 57 encrypt_round(B, A, D, C, m_EK[30], m_EK[31]); 58 encrypt_round(C, B, A, D, m_EK[32], m_EK[33]); 59 encrypt_round(D, C, B, A, m_EK[34], m_EK[35]); 60 61 reverse_mix(A, B, C, D); 62 63 A -= m_EK[36]; B -= m_EK[37]; C -= m_EK[38]; D -= m_EK[39]; 64 65 storeLittleEndian(output, A, B, C, D); 66 67 input += BLOCK_SIZE; 68 output += BLOCK_SIZE; 69 } 70 } 71 72 /* 73 * MARS Decryption 74 */ 75 override void decryptN(const(ubyte)* input, ubyte* output, size_t blocks) 76 { 77 foreach (size_t i; 0 .. blocks) 78 { 79 uint A = loadLittleEndian!uint(input, 3) + m_EK[39]; 80 uint B = loadLittleEndian!uint(input, 2) + m_EK[38]; 81 uint C = loadLittleEndian!uint(input, 1) + m_EK[37]; 82 uint D = loadLittleEndian!uint(input, 0) + m_EK[36]; 83 84 forward_mix(A, B, C, D); 85 86 decrypt_round(A, B, C, D, m_EK[35], m_EK[34]); 87 decrypt_round(B, C, D, A, m_EK[33], m_EK[32]); 88 decrypt_round(C, D, A, B, m_EK[31], m_EK[30]); 89 decrypt_round(D, A, B, C, m_EK[29], m_EK[28]); 90 decrypt_round(A, B, C, D, m_EK[27], m_EK[26]); 91 decrypt_round(B, C, D, A, m_EK[25], m_EK[24]); 92 decrypt_round(C, D, A, B, m_EK[23], m_EK[22]); 93 decrypt_round(D, A, B, C, m_EK[21], m_EK[20]); 94 95 decrypt_round(A, D, C, B, m_EK[19], m_EK[18]); 96 decrypt_round(B, A, D, C, m_EK[17], m_EK[16]); 97 decrypt_round(C, B, A, D, m_EK[15], m_EK[14]); 98 decrypt_round(D, C, B, A, m_EK[13], m_EK[12]); 99 decrypt_round(A, D, C, B, m_EK[11], m_EK[10]); 100 decrypt_round(B, A, D, C, m_EK[ 9], m_EK[ 8]); 101 decrypt_round(C, B, A, D, m_EK[ 7], m_EK[ 6]); 102 decrypt_round(D, C, B, A, m_EK[ 5], m_EK[ 4]); 103 104 reverse_mix(A, B, C, D); 105 106 A -= m_EK[3]; B -= m_EK[2]; C -= m_EK[1]; D -= m_EK[0]; 107 108 storeLittleEndian(output, D, C, B, A); 109 110 input += BLOCK_SIZE; 111 output += BLOCK_SIZE; 112 } 113 } 114 115 override void clear() 116 { 117 zap(m_EK); 118 } 119 120 @property string name() const { return "MARS"; } 121 override @property size_t parallelism() const { return 1; } 122 override BlockCipher clone() const { return new MARS; } 123 override size_t blockSize() const { return super.blockSize(); } 124 override KeyLengthSpecification keySpec() const { return super.keySpec(); } 125 126 protected: 127 /* 128 * MARS Key Schedule 129 */ 130 override void keySchedule(const(ubyte)* key, size_t length) 131 { 132 SecureVector!uint T = SecureVector!uint(15); 133 foreach (size_t i; 0 .. (length / 4)) 134 T[i] = loadLittleEndian!uint(key, i); 135 136 T[length / 4] = cast(uint)(length) / 4; 137 138 m_EK.resize(40); 139 140 for (uint i = 0; i != 4; ++i) 141 { 142 T[ 0] ^= rotateLeft(T[ 8] ^ T[13], 3) ^ (i ); 143 T[ 1] ^= rotateLeft(T[ 9] ^ T[14], 3) ^ (i + 4); 144 T[ 2] ^= rotateLeft(T[10] ^ T[ 0], 3) ^ (i + 8); 145 T[ 3] ^= rotateLeft(T[11] ^ T[ 1], 3) ^ (i + 12); 146 T[ 4] ^= rotateLeft(T[12] ^ T[ 2], 3) ^ (i + 16); 147 T[ 5] ^= rotateLeft(T[13] ^ T[ 3], 3) ^ (i + 20); 148 T[ 6] ^= rotateLeft(T[14] ^ T[ 4], 3) ^ (i + 24); 149 T[ 7] ^= rotateLeft(T[ 0] ^ T[ 5], 3) ^ (i + 28); 150 T[ 8] ^= rotateLeft(T[ 1] ^ T[ 6], 3) ^ (i + 32); 151 T[ 9] ^= rotateLeft(T[ 2] ^ T[ 7], 3) ^ (i + 36); 152 T[10] ^= rotateLeft(T[ 3] ^ T[ 8], 3) ^ (i + 40); 153 T[11] ^= rotateLeft(T[ 4] ^ T[ 9], 3) ^ (i + 44); 154 T[12] ^= rotateLeft(T[ 5] ^ T[10], 3) ^ (i + 48); 155 T[13] ^= rotateLeft(T[ 6] ^ T[11], 3) ^ (i + 52); 156 T[14] ^= rotateLeft(T[ 7] ^ T[12], 3) ^ (i + 56); 157 158 foreach (size_t j; 0 .. 4) 159 { 160 T[ 0] = rotateLeft(T[ 0] + SBOX[T[14] % 512], 9); 161 T[ 1] = rotateLeft(T[ 1] + SBOX[T[ 0] % 512], 9); 162 T[ 2] = rotateLeft(T[ 2] + SBOX[T[ 1] % 512], 9); 163 T[ 3] = rotateLeft(T[ 3] + SBOX[T[ 2] % 512], 9); 164 T[ 4] = rotateLeft(T[ 4] + SBOX[T[ 3] % 512], 9); 165 T[ 5] = rotateLeft(T[ 5] + SBOX[T[ 4] % 512], 9); 166 T[ 6] = rotateLeft(T[ 6] + SBOX[T[ 5] % 512], 9); 167 T[ 7] = rotateLeft(T[ 7] + SBOX[T[ 6] % 512], 9); 168 T[ 8] = rotateLeft(T[ 8] + SBOX[T[ 7] % 512], 9); 169 T[ 9] = rotateLeft(T[ 9] + SBOX[T[ 8] % 512], 9); 170 T[10] = rotateLeft(T[10] + SBOX[T[ 9] % 512], 9); 171 T[11] = rotateLeft(T[11] + SBOX[T[10] % 512], 9); 172 T[12] = rotateLeft(T[12] + SBOX[T[11] % 512], 9); 173 T[13] = rotateLeft(T[13] + SBOX[T[12] % 512], 9); 174 T[14] = rotateLeft(T[14] + SBOX[T[13] % 512], 9); 175 } 176 177 m_EK[10*i + 0] = T[ 0]; 178 m_EK[10*i + 1] = T[ 4]; 179 m_EK[10*i + 2] = T[ 8]; 180 m_EK[10*i + 3] = T[12]; 181 m_EK[10*i + 4] = T[ 1]; 182 m_EK[10*i + 5] = T[ 5]; 183 m_EK[10*i + 6] = T[ 9]; 184 m_EK[10*i + 7] = T[13]; 185 m_EK[10*i + 8] = T[ 2]; 186 m_EK[10*i + 9] = T[ 6]; 187 } 188 189 foreach (size_t i; iota(5, 37, 2)) 190 { 191 const uint key3 = m_EK[i] & 3; 192 m_EK[i] |= 3; 193 m_EK[i] ^= rotateLeft(SBOX[265 + key3], m_EK[i-1] % 32) & gen_mask(m_EK[i]); 194 } 195 } 196 197 SecureVector!uint m_EK; 198 } 199 200 201 private: 202 203 /** 204 * The MARS sbox 205 */ 206 __gshared immutable uint[512] SBOX = [ 207 0x09D0C479, 0x28C8FFE0, 0x84AA6C39, 0x9DAD7287, 0x7DFF9BE3, 0xD4268361, 208 0xC96DA1D4, 0x7974CC93, 0x85D0582E, 0x2A4B5705, 0x1CA16A62, 0xC3BD279D, 209 0x0F1F25E5, 0x5160372F, 0xC695C1FB, 0x4D7FF1E4, 0xAE5F6BF4, 0x0D72EE46, 210 0xFF23DE8A, 0xB1CF8E83, 0xF14902E2, 0x3E981E42, 0x8BF53EB6, 0x7F4BF8AC, 211 0x83631F83, 0x25970205, 0x76AFE784, 0x3A7931D4, 0x4F846450, 0x5C64C3F6, 212 0x210A5F18, 0xC6986A26, 0x28F4E826, 0x3A60A81C, 0xD340A664, 0x7EA820C4, 213 0x526687C5, 0x7EDDD12B, 0x32A11D1D, 0x9C9EF086, 0x80F6E831, 0xAB6F04AD, 214 0x56FB9B53, 0x8B2E095C, 0xB68556AE, 0xD2250B0D, 0x294A7721, 0xE21FB253, 215 0xAE136749, 0xE82AAE86, 0x93365104, 0x99404A66, 0x78A784DC, 0xB69BA84B, 216 0x04046793, 0x23DB5C1E, 0x46CAE1D6, 0x2FE28134, 0x5A223942, 0x1863CD5B, 217 0xC190C6E3, 0x07DFB846, 0x6EB88816, 0x2D0DCC4A, 0xA4CCAE59, 0x3798670D, 218 0xCBFA9493, 0x4F481D45, 0xEAFC8CA8, 0xDB1129D6, 0xB0449E20, 0x0F5407FB, 219 0x6167D9A8, 0xD1F45763, 0x4DAA96C3, 0x3BEC5958, 0xABABA014, 0xB6CCD201, 220 0x38D6279F, 0x02682215, 0x8F376CD5, 0x092C237E, 0xBFC56593, 0x32889D2C, 221 0x854B3E95, 0x05BB9B43, 0x7DCD5DCD, 0xA02E926C, 0xFAE527E5, 0x36A1C330, 222 0x3412E1AE, 0xF257F462, 0x3C4F1D71, 0x30A2E809, 0x68E5F551, 0x9C61BA44, 223 0x5DED0AB8, 0x75CE09C8, 0x9654F93E, 0x698C0CCA, 0x243CB3E4, 0x2B062B97, 224 0x0F3B8D9E, 0x00E050DF, 0xFC5D6166, 0xE35F9288, 0xC079550D, 0x0591AEE8, 225 0x8E531E74, 0x75FE3578, 0x2F6D829A, 0xF60B21AE, 0x95E8EB8D, 0x6699486B, 226 0x901D7D9B, 0xFD6D6E31, 0x1090ACEF, 0xE0670DD8, 0xDAB2E692, 0xCD6D4365, 227 0xE5393514, 0x3AF345F0, 0x6241FC4D, 0x460DA3A3, 0x7BCF3729, 0x8BF1D1E0, 228 0x14AAC070, 0x1587ED55, 0x3AFD7D3E, 0xD2F29E01, 0x29A9D1F6, 0xEFB10C53, 229 0xCF3B870F, 0xB414935C, 0x664465ED, 0x024ACAC7, 0x59A744C1, 0x1D2936A7, 230 0xDC580AA6, 0xCF574CA8, 0x040A7A10, 0x6CD81807, 0x8A98BE4C, 0xACCEA063, 231 0xC33E92B5, 0xD1E0E03D, 0xB322517E, 0x2092BD13, 0x386B2C4A, 0x52E8DD58, 232 0x58656DFB, 0x50820371, 0x41811896, 0xE337EF7E, 0xD39FB119, 0xC97F0DF6, 233 0x68FEA01B, 0xA150A6E5, 0x55258962, 0xEB6FF41B, 0xD7C9CD7A, 0xA619CD9E, 234 0xBCF09576, 0x2672C073, 0xF003FB3C, 0x4AB7A50B, 0x1484126A, 0x487BA9B1, 235 0xA64FC9C6, 0xF6957D49, 0x38B06A75, 0xDD805FCD, 0x63D094CF, 0xF51C999E, 236 0x1AA4D343, 0xB8495294, 0xCE9F8E99, 0xBFFCD770, 0xC7C275CC, 0x378453A7, 237 0x7B21BE33, 0x397F41BD, 0x4E94D131, 0x92CC1F98, 0x5915EA51, 0x99F861B7, 238 0xC9980A88, 0x1D74FD5F, 0xB0A495F8, 0x614DEED0, 0xB5778EEA, 0x5941792D, 239 0xFA90C1F8, 0x33F824B4, 0xC4965372, 0x3FF6D550, 0x4CA5FEC0, 0x8630E964, 240 0x5B3FBBD6, 0x7DA26A48, 0xB203231A, 0x04297514, 0x2D639306, 0x2EB13149, 241 0x16A45272, 0x532459A0, 0x8E5F4872, 0xF966C7D9, 0x07128DC0, 0x0D44DB62, 242 0xAFC8D52D, 0x06316131, 0xD838E7CE, 0x1BC41D00, 0x3A2E8C0F, 0xEA83837E, 243 0xB984737D, 0x13BA4891, 0xC4F8B949, 0xA6D6ACB3, 0xA215CDCE, 0x8359838B, 244 0x6BD1AA31, 0xF579DD52, 0x21B93F93, 0xF5176781, 0x187DFDDE, 0xE94AEB76, 245 0x2B38FD54, 0x431DE1DA, 0xAB394825, 0x9AD3048F, 0xDFEA32AA, 0x659473E3, 246 0x623F7863, 0xF3346C59, 0xAB3AB685, 0x3346A90B, 0x6B56443E, 0xC6DE01F8, 247 0x8D421FC0, 0x9B0ED10C, 0x88F1A1E9, 0x54C1F029, 0x7DEAD57B, 0x8D7BA426, 248 0x4CF5178A, 0x551A7CCA, 0x1A9A5F08, 0xFCD651B9, 0x25605182, 0xE11FC6C3, 249 0xB6FD9676, 0x337B3027, 0xB7C8EB14, 0x9E5FD030, 0x6B57E354, 0xAD913CF7, 250 0x7E16688D, 0x58872A69, 0x2C2FC7DF, 0xE389CCC6, 0x30738DF1, 0x0824A734, 251 0xE1797A8B, 0xA4A8D57B, 0x5B5D193B, 0xC8A8309B, 0x73F9A978, 0x73398D32, 252 0x0F59573E, 0xE9DF2B03, 0xE8A5B6C8, 0x848D0704, 0x98DF93C2, 0x720A1DC3, 253 0x684F259A, 0x943BA848, 0xA6370152, 0x863B5EA3, 0xD17B978B, 0x6D9B58EF, 254 0x0A700DD4, 0xA73D36BF, 0x8E6A0829, 0x8695BC14, 0xE35B3447, 0x933AC568, 255 0x8894B022, 0x2F511C27, 0xDDFBCC3C, 0x006662B6, 0x117C83FE, 0x4E12B414, 256 0xC2BCA766, 0x3A2FEC10, 0xF4562420, 0x55792E2A, 0x46F5D857, 0xCEDA25CE, 257 0xC3601D3B, 0x6C00AB46, 0xEFAC9C28, 0xB3C35047, 0x611DFEE3, 0x257C3207, 258 0xFDD58482, 0x3B14D84F, 0x23BECB64, 0xA075F3A3, 0x088F8EAD, 0x07ADF158, 259 0x7796943C, 0xFACABF3D, 0xC09730CD, 0xF7679969, 0xDA44E9ED, 0x2C854C12, 260 0x35935FA3, 0x2F057D9F, 0x690624F8, 0x1CB0BAFD, 0x7B0DBDC6, 0x810F23BB, 261 0xFA929A1A, 0x6D969A17, 0x6742979B, 0x74AC7D05, 0x010E65C4, 0x86A3D963, 262 0xF907B5A0, 0xD0042BD3, 0x158D7D03, 0x287A8255, 0xBBA8366F, 0x096EDC33, 263 0x21916A7B, 0x77B56B86, 0x951622F9, 0xA6C5E650, 0x8CEA17D1, 0xCD8C62BC, 264 0xA3D63433, 0x358A68FD, 0x0F9B9D3C, 0xD6AA295B, 0xFE33384A, 0xC000738E, 265 0xCD67EB2F, 0xE2EB6DC2, 0x97338B02, 0x06C9F246, 0x419CF1AD, 0x2B83C045, 266 0x3723F18A, 0xCB5B3089, 0x160BEAD7, 0x5D494656, 0x35F8A74B, 0x1E4E6C9E, 267 0x000399BD, 0x67466880, 0xB4174831, 0xACF423B2, 0xCA815AB3, 0x5A6395E7, 268 0x302A67C5, 0x8BDB446B, 0x108F8FA4, 0x10223EDA, 0x92B8B48B, 0x7F38D0EE, 269 0xAB2701D4, 0x0262D415, 0xAF224A30, 0xB3D88ABA, 0xF8B2C3AF, 0xDAF7EF70, 270 0xCC97D3B7, 0xE9614B6C, 0x2BAEBFF4, 0x70F687CF, 0x386C9156, 0xCE092EE5, 271 0x01E87DA6, 0x6CE91E6A, 0xBB7BCC84, 0xC7922C20, 0x9D3B71FD, 0x060E41C6, 272 0xD7590F15, 0x4E03BB47, 0x183C198E, 0x63EEB240, 0x2DDBF49A, 0x6D5CBA54, 273 0x923750AF, 0xF9E14236, 0x7838162B, 0x59726C72, 0x81B66760, 0xBB2926C1, 274 0x48A0CE0D, 0xA6C0496D, 0xAD43507B, 0x718D496A, 0x9DF057AF, 0x44B1BDE6, 275 0x054356DC, 0xDE7CED35, 0xD51A138B, 0x62088CC9, 0x35830311, 0xC96EFCA2, 276 0x686F86EC, 0x8E77CB68, 0x63E1D6B8, 0xC80F9778, 0x79C491FD, 0x1B4C67F2, 277 0x72698D7D, 0x5E368C31, 0xF7D95E2E, 0xA1D3493F, 0xDCD9433E, 0x896F1552, 278 0x4BC4CA7A, 0xA6D1BAF4, 0xA5A96DCC, 0x0BEF8B46, 0xA169FDA7, 0x74DF40B7, 279 0x4E208804, 0x9A756607, 0x038E87C8, 0x20211E44, 0x8B7AD4BF, 0xC6403F35, 280 0x1848E36D, 0x80BDB038, 0x1E62891C, 0x643D2107, 0xBF04D6F8, 0x21092C8C, 281 0xF644F389, 0x0778404E, 0x7B78ADB8, 0xA2C52D53, 0x42157ABE, 0xA2253E2E, 282 0x7BF3F4AE, 0x80F594F9, 0x953194E7, 0x77EB92ED, 0xB3816930, 0xDA8D9336, 283 0xBF447469, 0xF26D9483, 0xEE6FAED5, 0x71371235, 0xDE425F73, 0xB4E59F43, 284 0x7DBE2D4E, 0x2D37B185, 0x49DC9A63, 0x98C39D98, 0x1301C9A2, 0x389B1BBF, 285 0x0C18588D, 0xA421C1BA, 0x7AA3865C, 0x71E08558, 0x3C5CFCAA, 0x7D239CA4, 286 0x0297D9DD, 0xD7DC2830, 0x4B37802B, 0x7428AB54, 0xAEEE0347, 0x4B3FBB85, 287 0x692F2F08, 0x134E578E, 0x36D9E0BF, 0xAE8B5FCF, 0xEDB93ECF, 0x2B27248E, 288 0x170EB1EF, 0x7DC57FD6, 0x1E760F16, 0xB1136601, 0x864E1B9B, 0xD7EA7319, 289 0x3AB871BD, 0xCFA4D76F, 0xE31BD782, 0x0DBEB469, 0xABB96061, 0x5370F85D, 290 0xFFB07E37, 0xDA30D0FB, 0xEBC977B6, 0x0B98B40F, 0x3A4D0FE6, 0xDF4FC26B, 291 0x159CF22A, 0xC298D6E2, 0x2B78EF6A, 0x61A94AC0, 0xAB561187, 0x14EEA0F0, 292 0xDF0D4164, 0x19AF70EE ]; 293 294 /* 295 * MARS Encryption Round 296 */ 297 void encrypt_round(ref uint A, ref uint B, ref uint C, ref uint D, 298 uint EK1, uint EK2) pure 299 { 300 const uint X = A + EK1; 301 A = rotateLeft(A, 13); 302 uint Y = A * EK2; 303 uint Z = SBOX[X % 512]; 304 305 Y = rotateLeft(Y, 5); 306 Z ^= Y; 307 C += rotateLeft(X, Y % 32); 308 Y = rotateLeft(Y, 5); 309 Z ^= Y; 310 D ^= Y; 311 B += rotateLeft(Z, Y % 32); 312 } 313 314 /* 315 * MARS Decryption Round 316 */ 317 void decrypt_round(ref uint A, ref uint B, ref uint C, ref uint D, 318 uint EK1, uint EK2) pure 319 { 320 uint Y = A * EK1; 321 A = rotateRight(A, 13); 322 const uint X = A + EK2; 323 uint Z = SBOX[X % 512]; 324 325 Y = rotateLeft(Y, 5); 326 Z ^= Y; 327 C -= rotateLeft(X, Y % 32); 328 Y = rotateLeft(Y, 5); 329 Z ^= Y; 330 D ^= Y; 331 B -= rotateLeft(Z, Y % 32); 332 } 333 334 /* 335 * MARS Forward Mixing Operation 336 */ 337 void forward_mix(ref uint A, ref uint B, ref uint C, ref uint D) pure 338 { 339 foreach (size_t j; 0 .. 2) 340 { 341 B ^= SBOX[get_byte(3, A)]; B += SBOX[get_byte(2, A) + 256]; 342 C += SBOX[get_byte(1, A)]; D ^= SBOX[get_byte(0, A) + 256]; 343 A = rotateRight(A, 24) + D; 344 345 C ^= SBOX[get_byte(3, B)]; C += SBOX[get_byte(2, B) + 256]; 346 D += SBOX[get_byte(1, B)]; A ^= SBOX[get_byte(0, B) + 256]; 347 B = rotateRight(B, 24) + C; 348 349 D ^= SBOX[get_byte(3, C)]; D += SBOX[get_byte(2, C) + 256]; 350 A += SBOX[get_byte(1, C)]; B ^= SBOX[get_byte(0, C) + 256]; 351 C = rotateRight(C, 24); 352 353 A ^= SBOX[get_byte(3, D)]; A += SBOX[get_byte(2, D) + 256]; 354 B += SBOX[get_byte(1, D)]; C ^= SBOX[get_byte(0, D) + 256]; 355 D = rotateRight(D, 24); 356 } 357 } 358 359 /* 360 * MARS Reverse Mixing Operation 361 */ 362 void reverse_mix(ref uint A, ref uint B, ref uint C, ref uint D) pure 363 { 364 foreach (size_t j; 0 .. 2) 365 { 366 B ^= SBOX[get_byte(3, A) + 256]; C -= SBOX[get_byte(0, A)]; 367 D -= SBOX[get_byte(1, A) + 256]; D ^= SBOX[get_byte(2, A)]; 368 A = rotateLeft(A, 24); 369 370 C ^= SBOX[get_byte(3, B) + 256]; D -= SBOX[get_byte(0, B)]; 371 A -= SBOX[get_byte(1, B) + 256]; A ^= SBOX[get_byte(2, B)]; 372 C -= (B = rotateLeft(B, 24)); 373 374 D ^= SBOX[get_byte(3, C) + 256]; A -= SBOX[get_byte(0, C)]; 375 B -= SBOX[get_byte(1, C) + 256]; B ^= SBOX[get_byte(2, C)]; 376 C = rotateLeft(C, 24); 377 D -= A; 378 379 A ^= SBOX[get_byte(3, D) + 256]; B -= SBOX[get_byte(0, D)]; 380 C -= SBOX[get_byte(1, D) + 256]; C ^= SBOX[get_byte(2, D)]; 381 D = rotateLeft(D, 24); 382 } 383 } 384 385 /* 386 * Generate a mask for runs of bits 387 */ 388 uint gen_mask(uint input) pure 389 { 390 uint mask = 0; 391 392 for (uint j = 2; j != 31; ++j) 393 { 394 const uint region = (input >> (j-1)) & 0x07; 395 396 if (region == 0x00 || region == 0x07) 397 { 398 const uint low = (j < 9) ? 0 : (j - 9); 399 const uint high = (j < 23) ? j : 23; 400 401 for (uint k = low; k != high; ++k) 402 { 403 const uint value = (input >> k) & 0x3FF; 404 405 if (value == 0 || value == 0x3FF) 406 { 407 mask |= 1 << j; 408 break; 409 } 410 } 411 } 412 } 413 414 return mask; 415 }