1 /** 2 * Serpent 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.serpent; 12 13 import botan.constants; 14 static if (BOTAN_HAS_SERPENT): 15 16 import botan.block.block_cipher; 17 import botan.utils.loadstor; 18 import botan.utils.rotate; 19 import botan.utils.types; 20 import botan.utils.mem_ops; 21 22 /** 23 * Serpent, an AES finalist 24 */ 25 class Serpent : BlockCipherFixedParams!(16, 16, 32, 8), BlockCipher, SymmetricAlgorithm 26 { 27 public: 28 /* 29 * Serpent Encryption 30 */ 31 override void encryptN(const(ubyte)* input, ubyte* output, size_t blocks) 32 { 33 foreach (size_t i; 0 .. blocks) 34 { 35 uint B0 = loadLittleEndian!uint(input, 0); 36 uint B1 = loadLittleEndian!uint(input, 1); 37 uint B2 = loadLittleEndian!uint(input, 2); 38 uint B3 = loadLittleEndian!uint(input, 3); 39 40 mixin(key_xor!( 0)); mixin(SBoxE1!("B0", "B1", "B2", "B3")); transform(B0,B1,B2,B3); 41 mixin(key_xor!( 1)); mixin(SBoxE2!("B0", "B1", "B2", "B3")); transform(B0,B1,B2,B3); 42 mixin(key_xor!( 2)); mixin(SBoxE3!("B0", "B1", "B2", "B3")); transform(B0,B1,B2,B3); 43 mixin(key_xor!( 3)); mixin(SBoxE4!("B0", "B1", "B2", "B3")); transform(B0,B1,B2,B3); 44 mixin(key_xor!( 4)); mixin(SBoxE5!("B0", "B1", "B2", "B3")); transform(B0,B1,B2,B3); 45 mixin(key_xor!( 5)); mixin(SBoxE6!("B0", "B1", "B2", "B3")); transform(B0,B1,B2,B3); 46 mixin(key_xor!( 6)); mixin(SBoxE7!("B0", "B1", "B2", "B3")); transform(B0,B1,B2,B3); 47 mixin(key_xor!( 7)); mixin(SBoxE8!("B0", "B1", "B2", "B3")); transform(B0,B1,B2,B3); 48 mixin(key_xor!( 8)); mixin(SBoxE1!("B0", "B1", "B2", "B3")); transform(B0,B1,B2,B3); 49 mixin(key_xor!( 9)); mixin(SBoxE2!("B0", "B1", "B2", "B3")); transform(B0,B1,B2,B3); 50 mixin(key_xor!(10)); mixin(SBoxE3!("B0", "B1", "B2", "B3")); transform(B0,B1,B2,B3); 51 mixin(key_xor!(11)); mixin(SBoxE4!("B0", "B1", "B2", "B3")); transform(B0,B1,B2,B3); 52 mixin(key_xor!(12)); mixin(SBoxE5!("B0", "B1", "B2", "B3")); transform(B0,B1,B2,B3); 53 mixin(key_xor!(13)); mixin(SBoxE6!("B0", "B1", "B2", "B3")); transform(B0,B1,B2,B3); 54 mixin(key_xor!(14)); mixin(SBoxE7!("B0", "B1", "B2", "B3")); transform(B0,B1,B2,B3); 55 mixin(key_xor!(15)); mixin(SBoxE8!("B0", "B1", "B2", "B3")); transform(B0,B1,B2,B3); 56 mixin(key_xor!(16)); mixin(SBoxE1!("B0", "B1", "B2", "B3")); transform(B0,B1,B2,B3); 57 mixin(key_xor!(17)); mixin(SBoxE2!("B0", "B1", "B2", "B3")); transform(B0,B1,B2,B3); 58 mixin(key_xor!(18)); mixin(SBoxE3!("B0", "B1", "B2", "B3")); transform(B0,B1,B2,B3); 59 mixin(key_xor!(19)); mixin(SBoxE4!("B0", "B1", "B2", "B3")); transform(B0,B1,B2,B3); 60 mixin(key_xor!(20)); mixin(SBoxE5!("B0", "B1", "B2", "B3")); transform(B0,B1,B2,B3); 61 mixin(key_xor!(21)); mixin(SBoxE6!("B0", "B1", "B2", "B3")); transform(B0,B1,B2,B3); 62 mixin(key_xor!(22)); mixin(SBoxE7!("B0", "B1", "B2", "B3")); transform(B0,B1,B2,B3); 63 mixin(key_xor!(23)); mixin(SBoxE8!("B0", "B1", "B2", "B3")); transform(B0,B1,B2,B3); 64 mixin(key_xor!(24)); mixin(SBoxE1!("B0", "B1", "B2", "B3")); transform(B0,B1,B2,B3); 65 mixin(key_xor!(25)); mixin(SBoxE2!("B0", "B1", "B2", "B3")); transform(B0,B1,B2,B3); 66 mixin(key_xor!(26)); mixin(SBoxE3!("B0", "B1", "B2", "B3")); transform(B0,B1,B2,B3); 67 mixin(key_xor!(27)); mixin(SBoxE4!("B0", "B1", "B2", "B3")); transform(B0,B1,B2,B3); 68 mixin(key_xor!(28)); mixin(SBoxE5!("B0", "B1", "B2", "B3")); transform(B0,B1,B2,B3); 69 mixin(key_xor!(29)); mixin(SBoxE6!("B0", "B1", "B2", "B3")); transform(B0,B1,B2,B3); 70 mixin(key_xor!(30)); mixin(SBoxE7!("B0", "B1", "B2", "B3")); transform(B0,B1,B2,B3); 71 mixin(key_xor!(31)); mixin(SBoxE8!("B0", "B1", "B2", "B3")); mixin(key_xor!(32)); 72 73 storeLittleEndian(output, B0, B1, B2, B3); 74 75 input += BLOCK_SIZE; 76 output += BLOCK_SIZE; 77 } 78 } 79 80 /* 81 * Serpent Decryption 82 */ 83 override void decryptN(const(ubyte)* input, ubyte* output, size_t blocks) 84 { 85 foreach (size_t i; 0 .. blocks) 86 { 87 uint B0 = loadLittleEndian!uint(input, 0); 88 uint B1 = loadLittleEndian!uint(input, 1); 89 uint B2 = loadLittleEndian!uint(input, 2); 90 uint B3 = loadLittleEndian!uint(input, 3); 91 92 mixin(key_xor!(32)); mixin(SBoxD8); mixin(key_xor!(31)); 93 i_transform(B0,B1,B2,B3); mixin(SBoxD7); mixin(key_xor!(30)); 94 i_transform(B0,B1,B2,B3); mixin(SBoxD6); mixin(key_xor!(29)); 95 i_transform(B0,B1,B2,B3); mixin(SBoxD5); mixin(key_xor!(28)); 96 i_transform(B0,B1,B2,B3); mixin(SBoxD4); mixin(key_xor!(27)); 97 i_transform(B0,B1,B2,B3); mixin(SBoxD3); mixin(key_xor!(26)); 98 i_transform(B0,B1,B2,B3); mixin(SBoxD2); mixin(key_xor!(25)); 99 i_transform(B0,B1,B2,B3); mixin(SBoxD1); mixin(key_xor!(24)); 100 i_transform(B0,B1,B2,B3); mixin(SBoxD8); mixin(key_xor!(23)); 101 i_transform(B0,B1,B2,B3); mixin(SBoxD7); mixin(key_xor!(22)); 102 i_transform(B0,B1,B2,B3); mixin(SBoxD6); mixin(key_xor!(21)); 103 i_transform(B0,B1,B2,B3); mixin(SBoxD5); mixin(key_xor!(20)); 104 i_transform(B0,B1,B2,B3); mixin(SBoxD4); mixin(key_xor!(19)); 105 i_transform(B0,B1,B2,B3); mixin(SBoxD3); mixin(key_xor!(18)); 106 i_transform(B0,B1,B2,B3); mixin(SBoxD2); mixin(key_xor!(17)); 107 i_transform(B0,B1,B2,B3); mixin(SBoxD1); mixin(key_xor!(16)); 108 i_transform(B0,B1,B2,B3); mixin(SBoxD8); mixin(key_xor!(15)); 109 i_transform(B0,B1,B2,B3); mixin(SBoxD7); mixin(key_xor!(14)); 110 i_transform(B0,B1,B2,B3); mixin(SBoxD6); mixin(key_xor!(13)); 111 i_transform(B0,B1,B2,B3); mixin(SBoxD5); mixin(key_xor!(12)); 112 i_transform(B0,B1,B2,B3); mixin(SBoxD4); mixin(key_xor!(11)); 113 i_transform(B0,B1,B2,B3); mixin(SBoxD3); mixin(key_xor!(10)); 114 i_transform(B0,B1,B2,B3); mixin(SBoxD2); mixin(key_xor!( 9)); 115 i_transform(B0,B1,B2,B3); mixin(SBoxD1); mixin(key_xor!( 8)); 116 i_transform(B0,B1,B2,B3); mixin(SBoxD8); mixin(key_xor!( 7)); 117 i_transform(B0,B1,B2,B3); mixin(SBoxD7); mixin(key_xor!( 6)); 118 i_transform(B0,B1,B2,B3); mixin(SBoxD6); mixin(key_xor!( 5)); 119 i_transform(B0,B1,B2,B3); mixin(SBoxD5); mixin(key_xor!( 4)); 120 i_transform(B0,B1,B2,B3); mixin(SBoxD4); mixin(key_xor!( 3)); 121 i_transform(B0,B1,B2,B3); mixin(SBoxD3); mixin(key_xor!( 2)); 122 i_transform(B0,B1,B2,B3); mixin(SBoxD2); mixin(key_xor!( 1)); 123 i_transform(B0,B1,B2,B3); mixin(SBoxD1); mixin(key_xor!( 0)); 124 125 storeLittleEndian(output, B0, B1, B2, B3); 126 127 input += BLOCK_SIZE; 128 output += BLOCK_SIZE; 129 } 130 } 131 132 override void clear() 133 { 134 zap(m_round_key); 135 } 136 137 override @property string name() const { return "Serpent"; } 138 override @property size_t parallelism() const { return 1; } 139 override BlockCipher clone() const { return new Serpent; } 140 override size_t blockSize() const { return super.blockSize(); } 141 override KeyLengthSpecification keySpec() const { return super.keySpec(); } 142 protected: 143 /** 144 * For use by subclasses using SIMD, asm, etc 145 * Returns: const reference to the key schedule 146 */ 147 ref const(SecureVector!uint) getRoundKeys() const 148 { return m_round_key; } 149 150 /** 151 * For use by subclasses that implement the key schedule 152 * Params: 153 * ks = is the new key schedule value to set 154 */ 155 void setRoundKeys(in uint[132] ks) 156 { 157 m_round_key[] = ks.ptr[0 .. 132]; 158 } 159 160 /* 161 * Serpent Key Schedule 162 */ 163 override void keySchedule(const(ubyte)* key, size_t length) 164 { 165 const uint PHI = 0x9E3779B9; 166 167 SecureVector!uint W = SecureVector!uint(140); 168 foreach (size_t i; 0 .. (length / 4)) 169 W[i] = loadLittleEndian!uint(key, i); 170 171 W[length / 4] |= uint(1) << ((length%4)*8); 172 173 foreach (size_t i; 8 .. 140) 174 { 175 uint wi = cast(uint) (W[i-8] ^ W[i-5] ^ W[i-3] ^ W[i-1] ^ PHI ^ (cast(uint) i - 8)); 176 W[i] = rotateLeft(wi, 11); 177 } 178 179 mixin(SBoxE4!("W[ 8]", "W[ 9]", "W[ 10]", "W[ 11]")); mixin(SBoxE3!("W[ 12]", "W[ 13]", "W[ 14]", "W[ 15]")); 180 mixin(SBoxE2!("W[ 16]", "W[ 17]", "W[ 18]", "W[ 19]")); mixin(SBoxE1!("W[ 20]", "W[ 21]", "W[ 22]", "W[ 23]")); 181 mixin(SBoxE8!("W[ 24]", "W[ 25]", "W[ 26]", "W[ 27]")); mixin(SBoxE7!("W[ 28]", "W[ 29]", "W[ 30]", "W[ 31]")); 182 mixin(SBoxE6!("W[ 32]", "W[ 33]", "W[ 34]", "W[ 35]")); mixin(SBoxE5!("W[ 36]", "W[ 37]", "W[ 38]", "W[ 39]")); 183 mixin(SBoxE4!("W[ 40]", "W[ 41]", "W[ 42]", "W[ 43]")); mixin(SBoxE3!("W[ 44]", "W[ 45]", "W[ 46]", "W[ 47]")); 184 mixin(SBoxE2!("W[ 48]", "W[ 49]", "W[ 50]", "W[ 51]")); mixin(SBoxE1!("W[ 52]", "W[ 53]", "W[ 54]", "W[ 55]")); 185 mixin(SBoxE8!("W[ 56]", "W[ 57]", "W[ 58]", "W[ 59]")); mixin(SBoxE7!("W[ 60]", "W[ 61]", "W[ 62]", "W[ 63]")); 186 mixin(SBoxE6!("W[ 64]", "W[ 65]", "W[ 66]", "W[ 67]")); mixin(SBoxE5!("W[ 68]", "W[ 69]", "W[ 70]", "W[ 71]")); 187 mixin(SBoxE4!("W[ 72]", "W[ 73]", "W[ 74]", "W[ 75]")); mixin(SBoxE3!("W[ 76]", "W[ 77]", "W[ 78]", "W[ 79]")); 188 mixin(SBoxE2!("W[ 80]", "W[ 81]", "W[ 82]", "W[ 83]")); mixin(SBoxE1!("W[ 84]", "W[ 85]", "W[ 86]", "W[ 87]")); 189 mixin(SBoxE8!("W[ 88]", "W[ 89]", "W[ 90]", "W[ 91]")); mixin(SBoxE7!("W[ 92]", "W[ 93]", "W[ 94]", "W[ 95]")); 190 mixin(SBoxE6!("W[ 96]", "W[ 97]", "W[ 98]", "W[ 99]")); mixin(SBoxE5!("W[100]", "W[101]", "W[102]", "W[103]")); 191 mixin(SBoxE4!("W[104]", "W[105]", "W[106]", "W[107]")); mixin(SBoxE3!("W[108]", "W[109]", "W[110]", "W[111]")); 192 mixin(SBoxE2!("W[112]", "W[113]", "W[114]", "W[115]")); mixin(SBoxE1!("W[116]", "W[117]", "W[118]", "W[119]")); 193 mixin(SBoxE8!("W[120]", "W[121]", "W[122]", "W[123]")); mixin(SBoxE7!("W[124]", "W[125]", "W[126]", "W[127]")); 194 mixin(SBoxE6!("W[128]", "W[129]", "W[130]", "W[131]")); mixin(SBoxE5!("W[132]", "W[133]", "W[134]", "W[135]")); 195 mixin(SBoxE4!("W[136]", "W[137]", "W[138]", "W[139]")); 196 197 m_round_key[] = W.ptr[8 .. 140]; 198 } 199 200 SecureVector!uint m_round_key; 201 } 202 203 204 package: 205 206 enum string SBoxE1(string B0, string B1, string B2, string B3) = 207 `{` ~ B3 ~ ` ^= ` ~ B0 ~ `; 208 auto B4 = ` ~ B1 ~ `; 209 ` ~ B1 ~ ` &= ` ~ B3 ~ `; 210 B4 ^= ` ~ B2 ~ `; 211 ` ~ B1 ~ ` ^= ` ~ B0 ~ `; 212 ` ~ B0 ~ ` |= ` ~ B3 ~ `; 213 ` ~ B0 ~ ` ^= B4; 214 B4 ^= ` ~ B3 ~ `; 215 ` ~ B3 ~ ` ^= ` ~ B2 ~ `; 216 ` ~ B2 ~ ` |= ` ~ B1 ~ `; 217 ` ~ B2 ~ ` ^= B4; 218 B4 = ~B4; 219 B4 |= ` ~ B1 ~ `; 220 ` ~ B1 ~ ` ^= ` ~ B3 ~ `; 221 ` ~ B1 ~ ` ^= B4; 222 ` ~ B3 ~ ` |= ` ~ B0 ~ `; 223 ` ~ B1 ~ ` ^= ` ~ B3 ~ `; 224 B4 ^= ` ~ B3 ~ `; 225 ` ~ B3 ~ ` = ` ~ B0 ~ `; 226 ` ~ B0 ~ ` = ` ~ B1 ~ `; 227 ` ~ B1 ~ ` = B4; }`; 228 229 enum string SBoxE2(string B0, string B1, string B2, string B3) = 230 `{` ~ B0 ~ ` = ~` ~ B0 ~ `; 231 ` ~ B2 ~ ` = ~` ~ B2 ~ `; 232 auto B4 = ` ~ B0 ~ `; 233 ` ~ B0 ~ ` &= ` ~ B1 ~ `; 234 ` ~ B2 ~ ` ^= ` ~ B0 ~ `; 235 ` ~ B0 ~ ` |= ` ~ B3 ~ `; 236 ` ~ B3 ~ ` ^= ` ~ B2 ~ `; 237 ` ~ B1 ~ ` ^= ` ~ B0 ~ `; 238 ` ~ B0 ~ ` ^= B4; 239 B4 |= ` ~ B1 ~ `; 240 ` ~ B1 ~ ` ^= ` ~ B3 ~ `; 241 ` ~ B2 ~ ` |= ` ~ B0 ~ `; 242 ` ~ B2 ~ ` &= B4; 243 ` ~ B0 ~ ` ^= ` ~ B1 ~ `; 244 ` ~ B1 ~ ` &= ` ~ B2 ~ `; 245 ` ~ B1 ~ ` ^= ` ~ B0 ~ `; 246 ` ~ B0 ~ ` &= ` ~ B2 ~ `; 247 B4 ^= ` ~ B0 ~ `; 248 ` ~ B0 ~ ` = ` ~ B2 ~ `; 249 ` ~ B2 ~ ` = ` ~ B3 ~ `; 250 ` ~ B3 ~ ` = ` ~ B1 ~ `; 251 ` ~ B1 ~ ` = B4;}`; 252 253 enum string SBoxE3(string B0, string B1, string B2, string B3) = 254 `{auto B4 = ` ~ B0 ~ `; 255 ` ~ B0 ~ ` &= ` ~ B2 ~ `; 256 ` ~ B0 ~ ` ^= ` ~ B3 ~ `; 257 ` ~ B2 ~ ` ^= ` ~ B1 ~ `; 258 ` ~ B2 ~ ` ^= ` ~ B0 ~ `; 259 ` ~ B3 ~ ` |= B4; 260 ` ~ B3 ~ ` ^= ` ~ B1 ~ `; 261 B4 ^= ` ~ B2 ~ `; 262 ` ~ B1 ~ ` = ` ~ B3 ~ `; 263 ` ~ B3 ~ ` |= B4; 264 ` ~ B3 ~ ` ^= ` ~ B0 ~ `; 265 ` ~ B0 ~ ` &= ` ~ B1 ~ `; 266 B4 ^= ` ~ B0 ~ `; 267 ` ~ B1 ~ ` ^= ` ~ B3 ~ `; 268 ` ~ B1 ~ ` ^= B4; 269 ` ~ B0 ~ ` = ` ~ B2 ~ `; 270 ` ~ B2 ~ ` = ` ~ B1 ~ `; 271 ` ~ B1 ~ ` = ` ~ B3 ~ `; 272 ` ~ B3 ~ ` = ~B4;}`; 273 274 enum string SBoxE4(string B0, string B1, string B2, string B3) = 275 `{auto B4 = ` ~ B0 ~ `; 276 ` ~ B0 ~ ` |= ` ~ B3 ~ `; 277 ` ~ B3 ~ ` ^= ` ~ B1 ~ `; 278 ` ~ B1 ~ ` &= B4; 279 B4 ^= ` ~ B2 ~ `; 280 ` ~ B2 ~ ` ^= ` ~ B3 ~ `; 281 ` ~ B3 ~ ` &= ` ~ B0 ~ `; 282 B4 |= ` ~ B1 ~ `; 283 ` ~ B3 ~ ` ^= B4; 284 ` ~ B0 ~ ` ^= ` ~ B1 ~ `; 285 B4 &= ` ~ B0 ~ `; 286 ` ~ B1 ~ ` ^= ` ~ B3 ~ `; 287 B4 ^= ` ~ B2 ~ `; 288 ` ~ B1 ~ ` |= ` ~ B0 ~ `; 289 ` ~ B1 ~ ` ^= ` ~ B2 ~ `; 290 ` ~ B0 ~ ` ^= ` ~ B3 ~ `; 291 ` ~ B2 ~ ` = ` ~ B1 ~ `; 292 ` ~ B1 ~ ` |= ` ~ B3 ~ `; 293 ` ~ B0 ~ ` ^= ` ~ B1 ~ `; 294 ` ~ B1 ~ ` = ` ~ B2 ~ `; 295 ` ~ B2 ~ ` = ` ~ B3 ~ `; 296 ` ~ B3 ~ ` = B4;}`; 297 298 enum string SBoxE5(string B0, string B1, string B2, string B3) = 299 `{` ~ B1 ~ ` ^= ` ~ B3 ~ `; 300 ` ~ B3 ~ ` = ~` ~ B3 ~ `; 301 ` ~ B2 ~ ` ^= ` ~ B3 ~ `; 302 ` ~ B3 ~ ` ^= ` ~ B0 ~ `; 303 auto B4 = ` ~ B1 ~ `; 304 ` ~ B1 ~ ` &= ` ~ B3 ~ `; 305 ` ~ B1 ~ ` ^= ` ~ B2 ~ `; 306 B4 ^= ` ~ B3 ~ `; 307 ` ~ B0 ~ ` ^= B4; 308 ` ~ B2 ~ ` &= B4; 309 ` ~ B2 ~ ` ^= ` ~ B0 ~ `; 310 ` ~ B0 ~ ` &= ` ~ B1 ~ `; 311 ` ~ B3 ~ ` ^= ` ~ B0 ~ `; 312 B4 |= ` ~ B1 ~ `; 313 B4 ^= ` ~ B0 ~ `; 314 ` ~ B0 ~ ` |= ` ~ B3 ~ `; 315 ` ~ B0 ~ ` ^= ` ~ B2 ~ `; 316 ` ~ B2 ~ ` &= ` ~ B3 ~ `; 317 ` ~ B0 ~ ` = ~` ~ B0 ~ `; 318 B4 ^= ` ~ B2 ~ `; 319 ` ~ B2 ~ ` = ` ~ B0 ~ `; 320 ` ~ B0 ~ ` = ` ~ B1 ~ `; 321 ` ~ B1 ~ ` = B4;}`; 322 323 enum string SBoxE6(string B0, string B1, string B2, string B3) = 324 `{` ~ B0 ~ ` ^= ` ~ B1 ~ `; 325 ` ~ B1 ~ ` ^= ` ~ B3 ~ `; 326 ` ~ B3 ~ ` = ~` ~ B3 ~ `; 327 auto B4 = ` ~ B1 ~ `; 328 ` ~ B1 ~ ` &= ` ~ B0 ~ `; 329 ` ~ B2 ~ ` ^= ` ~ B3 ~ `; 330 ` ~ B1 ~ ` ^= ` ~ B2 ~ `; 331 ` ~ B2 ~ ` |= B4; 332 B4 ^= ` ~ B3 ~ `; 333 ` ~ B3 ~ ` &= ` ~ B1 ~ `; 334 ` ~ B3 ~ ` ^= ` ~ B0 ~ `; 335 B4 ^= ` ~ B1 ~ `; 336 B4 ^= ` ~ B2 ~ `; 337 ` ~ B2 ~ ` ^= ` ~ B0 ~ `; 338 ` ~ B0 ~ ` &= ` ~ B3 ~ `; 339 ` ~ B2 ~ ` = ~` ~ B2 ~ `; 340 ` ~ B0 ~ ` ^= B4; 341 B4 |= ` ~ B3 ~ `; 342 B4 ^= ` ~ B2 ~ `; 343 ` ~ B2 ~ ` = ` ~ B0 ~ `; 344 ` ~ B0 ~ ` = ` ~ B1 ~ `; 345 ` ~ B1 ~ ` = ` ~ B3 ~ `; 346 ` ~ B3 ~ ` = B4;}`; 347 348 enum string SBoxE7(string B0, string B1, string B2, string B3) = 349 `{` ~ B2 ~ ` = ~` ~ B2 ~ `; 350 auto B4 = ` ~ B3 ~ `; 351 ` ~ B3 ~ ` &= ` ~ B0 ~ `; 352 ` ~ B0 ~ ` ^= B4; 353 ` ~ B3 ~ ` ^= ` ~ B2 ~ `; 354 ` ~ B2 ~ ` |= B4; 355 ` ~ B1 ~ ` ^= ` ~ B3 ~ `; 356 ` ~ B2 ~ ` ^= ` ~ B0 ~ `; 357 ` ~ B0 ~ ` |= ` ~ B1 ~ `; 358 ` ~ B2 ~ ` ^= ` ~ B1 ~ `; 359 B4 ^= ` ~ B0 ~ `; 360 ` ~ B0 ~ ` |= ` ~ B3 ~ `; 361 ` ~ B0 ~ ` ^= ` ~ B2 ~ `; 362 B4 ^= ` ~ B3 ~ `; 363 B4 ^= ` ~ B0 ~ `; 364 ` ~ B3 ~ ` = ~` ~ B3 ~ `; 365 ` ~ B2 ~ ` &= B4; 366 ` ~ B3 ~ ` ^= ` ~ B2 ~ `; 367 ` ~ B2 ~ ` = B4;}`; 368 369 enum string SBoxE8(string B0, string B1, string B2, string B3) = 370 `{auto B4 = ` ~ B1 ~ `; 371 ` ~ B1 ~ ` |= ` ~ B2 ~ `; 372 ` ~ B1 ~ ` ^= ` ~ B3 ~ `; 373 B4 ^= ` ~ B2 ~ `; 374 ` ~ B2 ~ ` ^= ` ~ B1 ~ `; 375 ` ~ B3 ~ ` |= B4; 376 ` ~ B3 ~ ` &= ` ~ B0 ~ `; 377 B4 ^= ` ~ B2 ~ `; 378 ` ~ B3 ~ ` ^= ` ~ B1 ~ `; 379 ` ~ B1 ~ ` |= B4; 380 ` ~ B1 ~ ` ^= ` ~ B0 ~ `; 381 ` ~ B0 ~ ` |= B4; 382 ` ~ B0 ~ ` ^= ` ~ B2 ~ `; 383 ` ~ B1 ~ ` ^= B4; 384 ` ~ B2 ~ ` ^= ` ~ B1 ~ `; 385 ` ~ B1 ~ ` &= ` ~ B0 ~ `; 386 ` ~ B1 ~ ` ^= B4; 387 ` ~ B2 ~ ` = ~` ~ B2 ~ `; 388 ` ~ B2 ~ ` |= ` ~ B0 ~ `; 389 B4 ^= ` ~ B2 ~ `; 390 ` ~ B2 ~ ` = ` ~ B1 ~ `; 391 ` ~ B1 ~ ` = ` ~ B3 ~ `; 392 ` ~ B3 ~ ` = ` ~ B0 ~ `; 393 ` ~ B0 ~ ` = B4;}`; 394 395 enum string SBoxD1 = 396 `{B2 = ~B2; 397 auto B4 = B1; 398 B1 |= B0; 399 B4 = ~B4; 400 B1 ^= B2; 401 B2 |= B4; 402 B1 ^= B3; 403 B0 ^= B4; 404 B2 ^= B0; 405 B0 &= B3; 406 B4 ^= B0; 407 B0 |= B1; 408 B0 ^= B2; 409 B3 ^= B4; 410 B2 ^= B1; 411 B3 ^= B0; 412 B3 ^= B1; 413 B2 &= B3; 414 B4 ^= B2; 415 B2 = B1; 416 B1 = B4;}`; 417 418 enum string SBoxD2 = 419 `{auto B4 = B1; 420 B1 ^= B3; 421 B3 &= B1; 422 B4 ^= B2; 423 B3 ^= B0; 424 B0 |= B1; 425 B2 ^= B3; 426 B0 ^= B4; 427 B0 |= B2; 428 B1 ^= B3; 429 B0 ^= B1; 430 B1 |= B3; 431 B1 ^= B0; 432 B4 = ~B4; 433 B4 ^= B1; 434 B1 |= B0; 435 B1 ^= B0; 436 B1 |= B4; 437 B3 ^= B1; 438 B1 = B0; 439 B0 = B4; 440 B4 = B2; 441 B2 = B3; 442 B3 = B4;}`; 443 444 enum string SBoxD3 = 445 `{B2 ^= B3; 446 B3 ^= B0; 447 auto B4 = B3; 448 B3 &= B2; 449 B3 ^= B1; 450 B1 |= B2; 451 B1 ^= B4; 452 B4 &= B3; 453 B2 ^= B3; 454 B4 &= B0; 455 B4 ^= B2; 456 B2 &= B1; 457 B2 |= B0; 458 B3 = ~B3; 459 B2 ^= B3; 460 B0 ^= B3; 461 B0 &= B1; 462 B3 ^= B4; 463 B3 ^= B0; 464 B0 = B1; 465 B1 = B4;}`; 466 467 enum string SBoxD4 = 468 `{auto B4 = B2; 469 B2 ^= B1; 470 B0 ^= B2; 471 B4 &= B2; 472 B4 ^= B0; 473 B0 &= B1; 474 B1 ^= B3; 475 B3 |= B4; 476 B2 ^= B3; 477 B0 ^= B3; 478 B1 ^= B4; 479 B3 &= B2; 480 B3 ^= B1; 481 B1 ^= B0; 482 B1 |= B2; 483 B0 ^= B3; 484 B1 ^= B4; 485 B0 ^= B1; 486 B4 = B0; 487 B0 = B2; 488 B2 = B3; 489 B3 = B4;}`; 490 491 enum string SBoxD5 = 492 `{auto B4 = B2; 493 B2 &= B3; 494 B2 ^= B1; 495 B1 |= B3; 496 B1 &= B0; 497 B4 ^= B2; 498 B4 ^= B1; 499 B1 &= B2; 500 B0 = ~B0; 501 B3 ^= B4; 502 B1 ^= B3; 503 B3 &= B0; 504 B3 ^= B2; 505 B0 ^= B1; 506 B2 &= B0; 507 B3 ^= B0; 508 B2 ^= B4; 509 B2 |= B3; 510 B3 ^= B0; 511 B2 ^= B1; 512 B1 = B3; 513 B3 = B4;}`; 514 515 enum string SBoxD6 = 516 `{B1 = ~B1; 517 auto B4 = B3; 518 B2 ^= B1; 519 B3 |= B0; 520 B3 ^= B2; 521 B2 |= B1; 522 B2 &= B0; 523 B4 ^= B3; 524 B2 ^= B4; 525 B4 |= B0; 526 B4 ^= B1; 527 B1 &= B2; 528 B1 ^= B3; 529 B4 ^= B2; 530 B3 &= B4; 531 B4 ^= B1; 532 B3 ^= B4; 533 B4 = ~B4; 534 B3 ^= B0; 535 B0 = B1; 536 B1 = B4; 537 B4 = B3; 538 B3 = B2; 539 B2 = B4;}`; 540 541 enum string SBoxD7 = 542 `{B0 ^= B2; 543 auto B4 = B2; 544 B2 &= B0; 545 B4 ^= B3; 546 B2 = ~B2; 547 B3 ^= B1; 548 B2 ^= B3; 549 B4 |= B0; 550 B0 ^= B2; 551 B3 ^= B4; 552 B4 ^= B1; 553 B1 &= B3; 554 B1 ^= B0; 555 B0 ^= B3; 556 B0 |= B2; 557 B3 ^= B1; 558 B4 ^= B0; 559 B0 = B1; 560 B1 = B2; 561 B2 = B4;}`; 562 563 enum string SBoxD8 = 564 `{auto B4 = B2; 565 B2 ^= B0; 566 B0 &= B3; 567 B4 |= B3; 568 B2 = ~B2; 569 B3 ^= B1; 570 B1 |= B0; 571 B0 ^= B2; 572 B2 &= B4; 573 B3 &= B4; 574 B1 ^= B2; 575 B2 ^= B0; 576 B0 |= B2; 577 B4 ^= B1; 578 B0 ^= B3; 579 B3 ^= B4; 580 B4 |= B0; 581 B3 ^= B2; 582 B4 ^= B2; 583 B2 = B1; 584 B1 = B0; 585 B0 = B3; 586 B3 = B4;}`; 587 588 private: 589 590 /* 591 * Serpent's Linear Transformation 592 */ 593 void transform(ref uint B0, ref uint B1, ref uint B2, ref uint B3) 594 { 595 B0 = rotateLeft(B0, 13); B2 = rotateLeft(B2, 3); 596 B1 ^= B0 ^ B2;B3 ^= B2 ^ (B0 << 3); 597 B1 = rotateLeft(B1, 1); B3 = rotateLeft(B3, 7); 598 B0 ^= B1 ^ B3;B2 ^= B3 ^ (B1 << 7); 599 B0 = rotateLeft(B0, 5); B2 = rotateLeft(B2, 22); 600 } 601 602 /* 603 * Serpent's Inverse Linear Transformation 604 */ 605 void i_transform(ref uint B0, ref uint B1, ref uint B2, ref uint B3) 606 { 607 B2 = rotateRight(B2, 22); B0 = rotateRight(B0, 5); 608 B2 ^= B3 ^ (B1 << 7); B0 ^= B1 ^ B3; 609 B3 = rotateRight(B3, 7); B1 = rotateRight(B1, 1); 610 B3 ^= B2 ^ (B0 << 3); B1 ^= B0 ^ B2; 611 B2 = rotateRight(B2, 3); B0 = rotateRight(B0, 13); 612 } 613 /* 614 * XOR a key block with a data block 615 */ 616 enum string key_xor(ubyte round) = 617 `B0 ^= m_round_key[4*` ~ round.stringof ~ ` ]; 618 B1 ^= m_round_key[4*` ~ round.stringof ~ `+1]; 619 B2 ^= m_round_key[4*` ~ round.stringof ~ `+2]; 620 B3 ^= m_round_key[4*` ~ round.stringof ~ `+3];`;