1 /** 2 * SAFER-SK 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.safer_sk; 12 13 import botan.constants; 14 static if (BOTAN_HAS_SAFER): 15 16 import botan.block.block_cipher; 17 import botan.utils.rotate; 18 import botan.utils.parsing; 19 import botan.utils.rotate; 20 import std.conv : to; 21 import botan.utils.mem_ops; 22 23 ubyte opCast(T : ubyte)(int val) { 24 return cast(ubyte) val; 25 } 26 27 /** 28 * SAFER-SK 29 */ 30 final class SAFERSK : BlockCipherFixedParams!(8, 16), BlockCipher, SymmetricAlgorithm 31 { 32 public: 33 34 /* 35 * SAFER-SK Encryption 36 */ 37 override void encryptN(const(ubyte)* input, ubyte* output, size_t blocks) 38 { 39 foreach (size_t i; 0 .. blocks) 40 { 41 ubyte A = input[0], B = input[1], C = input[2], D = input[3], 42 E = input[4], F = input[5], G = input[6], H = input[7], 43 X, Y; 44 45 for (size_t j = 0; j != 16*m_rounds; j += 16) 46 { 47 A = EXP[A ^ m_EK[j ]]; B = LOG[B + m_EK[j+1]]; 48 C = LOG[C + m_EK[j+2]]; D = EXP[D ^ m_EK[j+3]]; 49 E = EXP[E ^ m_EK[j+4]]; F = LOG[F + m_EK[j+5]]; 50 G = LOG[G + m_EK[j+6]]; H = EXP[H ^ m_EK[j+7]]; 51 52 A += m_EK[j+ 8]; B ^= m_EK[j+ 9]; C ^= m_EK[j+10]; D += m_EK[j+11]; 53 E += m_EK[j+12]; F ^= m_EK[j+13]; G ^= m_EK[j+14]; H += m_EK[j+15]; 54 55 B += A; D += C; F += E; H += G; A += B; C += D; E += F; G += H; 56 C += A; G += E; D += B; H += F; A += C; E += G; B += D; F += H; 57 H += D; 58 Y = cast(ubyte)(D + H); 59 D = cast(ubyte)(B + F); 60 X = cast(ubyte)(B + D); 61 B = cast(ubyte)(A + E); 62 A += B; 63 F = cast(ubyte)(C + G); 64 E = cast(ubyte)(C + F); 65 C = X; G = Y; 66 } 67 68 output[0] = A ^ m_EK[16*m_rounds+0]; output[1] = cast(ubyte) (B + m_EK[16*m_rounds+1]); 69 output[2] = cast(ubyte) (C + m_EK[16*m_rounds+2]); output[3] = D ^ m_EK[16*m_rounds+3]; 70 output[4] = E ^ m_EK[16*m_rounds+4]; output[5] = cast(ubyte) (F + m_EK[16*m_rounds+5]); 71 output[6] = cast(ubyte) (G + m_EK[16*m_rounds+6]); output[7] = H ^ m_EK[16*m_rounds+7]; 72 73 input += BLOCK_SIZE; 74 output += BLOCK_SIZE; 75 } 76 } 77 78 /* 79 * SAFER-SK Decryption 80 */ 81 override void decryptN(const(ubyte)* input, ubyte* output, size_t blocks) 82 { 83 foreach (size_t i; 0 .. blocks) 84 { 85 ubyte A = input[0], B = input[1], C = input[2], D = input[3], 86 E = input[4], F = input[5], G = input[6], H = input[7]; 87 88 A ^= m_EK[16*m_rounds+0]; 89 B -= m_EK[16*m_rounds+1]; 90 C -= m_EK[16*m_rounds+2]; 91 D ^= m_EK[16*m_rounds+3]; 92 E ^= m_EK[16*m_rounds+4]; 93 F -= m_EK[16*m_rounds+5]; 94 G -= m_EK[16*m_rounds+6]; 95 H ^= m_EK[16*m_rounds+7]; 96 97 for (int j = cast(int) (16*(m_rounds-1)); j >= 0; j -= 16) 98 { 99 ubyte T = E; E = B; B = C; C = T; T = F; F = D; D = G; G = T; 100 A -= E; B -= F; C -= G; D -= H; E -= A; F -= B; G -= C; H -= D; 101 A -= C; E -= G; B -= D; F -= H; C -= A; G -= E; D -= B; H -= F; 102 A -= B; C -= D; E -= F; G -= H; B -= A; D -= C; F -= E; H -= G; 103 104 A = LOG[A - m_EK[j+8 ] + 256]; 105 B = EXP[B ^ m_EK[j+9 ]]; 106 C = EXP[C ^ m_EK[j+10]]; 107 D = LOG[D - m_EK[j+11] + 256]; 108 E = LOG[E - m_EK[j+12] + 256]; 109 F = EXP[F ^ m_EK[j+13]]; 110 G = EXP[G ^ m_EK[j+14]]; 111 H = LOG[H - m_EK[j+15] + 256]; 112 113 A ^= m_EK[j+0]; B -= m_EK[j+1]; C -= m_EK[j+2]; D ^= m_EK[j+3]; 114 E ^= m_EK[j+4]; F -= m_EK[j+5]; G -= m_EK[j+6]; H ^= m_EK[j+7]; 115 } 116 117 output[0] = A; output[1] = B; output[2] = C; output[3] = D; 118 output[4] = E; output[5] = F; output[6] = G; output[7] = H; 119 120 input += BLOCK_SIZE; 121 output += BLOCK_SIZE; 122 } 123 } 124 125 override void clear() 126 { 127 zap(m_EK); 128 } 129 130 /* 131 * Return the name of this type 132 */ 133 override @property string name() const 134 { 135 return "SAFER-SK(" ~ to!string(m_rounds) ~ ")"; 136 } 137 138 /* 139 * Return a clone of this object 140 */ 141 override BlockCipher clone() const 142 { 143 return new SAFERSK(m_rounds); 144 } 145 146 /** 147 * Params: 148 * r = the number of rounds to use - must be between 1 149 * and 13 150 */ 151 this(size_t r) 152 { 153 m_rounds = r; 154 if (m_rounds > 13 || m_rounds == 0) 155 throw new InvalidArgument(name ~ ": Invalid number of rounds"); 156 } 157 158 override @property size_t parallelism() const { return 1; } 159 override size_t blockSize() const { return super.blockSize(); } 160 override KeyLengthSpecification keySpec() const { return super.keySpec(); } 161 protected: 162 /* 163 * SAFER-SK Key Schedule 164 */ 165 override void keySchedule(const(ubyte)* key, size_t) 166 { 167 __gshared immutable ubyte[208] BIAS = [ 168 0x16, 0x73, 0x3B, 0x1E, 0x8E, 0x70, 0xBD, 0x86, 0x47, 0x7E, 0x24, 0x56, 169 0xF1, 0x77, 0x88, 0x46, 0xB1, 0xBA, 0xA3, 0xB7, 0x10, 0x0A, 0xC5, 0x37, 170 0xC9, 0x5A, 0x28, 0xAC, 0x64, 0xA5, 0xEC, 0xAB, 0xC6, 0x67, 0x95, 0x58, 171 0x0D, 0xF8, 0x9A, 0xF6, 0x66, 0xDC, 0x05, 0x3D, 0xD3, 0x8A, 0xC3, 0xD8, 172 0x6A, 0xE9, 0x36, 0x49, 0x43, 0xBF, 0xEB, 0xD4, 0x9B, 0x68, 0xA0, 0x65, 173 0x5D, 0x57, 0x92, 0x1F, 0x71, 0x5C, 0xBB, 0x22, 0xC1, 0xBE, 0x7B, 0xBC, 174 0x63, 0x94, 0x5F, 0x2A, 0x61, 0xB8, 0x34, 0x32, 0xFD, 0xFB, 0x17, 0x40, 175 0xE6, 0x51, 0x1D, 0x41, 0x8F, 0x29, 0xDD, 0x04, 0x80, 0xDE, 0xE7, 0x31, 176 0x7F, 0x01, 0xA2, 0xF7, 0x39, 0xDA, 0x6F, 0x23, 0xFE, 0x3A, 0xD0, 0x1C, 177 0xD1, 0x30, 0x3E, 0x12, 0xCD, 0x0F, 0xE0, 0xA8, 0xAF, 0x82, 0x59, 0x2C, 178 0x7D, 0xAD, 0xB2, 0xEF, 0xC2, 0x87, 0xCE, 0x75, 0x13, 0x02, 0x90, 0x4F, 179 0x2E, 0x72, 0x33, 0x85, 0x8D, 0xCF, 0xA9, 0x81, 0xE2, 0xC4, 0x27, 0x2F, 180 0x7A, 0x9F, 0x52, 0xE1, 0x15, 0x38, 0x2B, 0xFC, 0x42, 0xC7, 0x08, 0xE4, 181 0x09, 0x55, 0x5E, 0x8C, 0x76, 0x60, 0xFF, 0xDF, 0xD7, 0x98, 0xFA, 0x0B, 182 0x00, 0x1A, 0xF9, 0xA6, 0xB9, 0xE8, 0x9E, 0x62, 0xD9, 0x91, 0x50, 0xD2, 183 0xEE, 0x18, 0xB4, 0x07, 0xEA, 0x5B, 0xA4, 0xC8, 0x0E, 0xCB, 0x48, 0x69, 184 0x4E, 0x9C, 0x35, 0x79, 0x45, 0x4D, 0x54, 0xE5, 0x3C, 0x0C, 0x4A, 0x8B, 185 0x3F, 0xCC, 0xA7, 0xDB ]; 186 187 __gshared immutable ubyte[208] KEY_INDEX = [ 188 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0B, 0x0C, 0x0D, 0x0E, 189 0x0F, 0x10, 0x11, 0x09, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, 0x01, 190 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x09, 0x0A, 0x0B, 0x05, 0x06, 0x07, 0x08, 191 0x00, 0x01, 0x02, 0x03, 0x0F, 0x10, 0x11, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 192 0x07, 0x08, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x11, 0x09, 0x0A, 0x0B, 193 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 194 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x02, 0x03, 0x04, 0x05, 195 0x06, 0x07, 0x08, 0x00, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x09, 0x0A, 196 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, 0x01, 0x02, 0x0E, 0x0F, 0x10, 0x11, 197 0x09, 0x0A, 0x0B, 0x0C, 0x06, 0x07, 0x08, 0x00, 0x01, 0x02, 0x03, 0x04, 198 0x10, 0x11, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x08, 0x00, 0x01, 0x02, 199 0x03, 0x04, 0x05, 0x06, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 200 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0B, 0x0C, 0x0D, 0x0E, 201 0x0F, 0x10, 0x11, 0x09, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, 0x01, 202 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x09, 0x0A, 0x0B, 0x05, 0x06, 0x07, 0x08, 203 0x00, 0x01, 0x02, 0x03, 0x0F, 0x10, 0x11, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 204 0x07, 0x08, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x11, 0x09, 0x0A, 0x0B, 205 0x0C, 0x0D, 0x0E, 0x0F ]; 206 207 m_EK.resize(16 * m_rounds + 8); 208 209 SecureVector!ubyte KB = SecureVector!ubyte(18); 210 211 foreach (size_t i; 0 .. 8) 212 { 213 KB[i] = rotateLeft(key[i], 5); 214 KB[ 8] ^= KB[i]; 215 m_EK[i] = key[i+8]; 216 KB[i+9] = m_EK[i]; 217 KB[17] ^= KB[i+9]; 218 } 219 220 foreach (size_t i; 0 .. m_rounds) 221 { 222 foreach (size_t j; 0 .. 18) 223 KB[j] = rotateLeft(KB[j], 6); 224 foreach (size_t j; 0 .. 16) 225 m_EK[16*i+j+8] = cast(ubyte)(KB[KEY_INDEX[16*i+j]] + BIAS[16*i+j]); 226 } 227 } 228 229 size_t m_rounds; 230 SecureVector!ubyte m_EK; 231 } 232 233 private: 234 235 __gshared immutable ubyte[256] EXP = [ 236 0x01, 0x2D, 0xE2, 0x93, 0xBE, 0x45, 0x15, 0xAE, 0x78, 0x03, 0x87, 0xA4, 237 0xB8, 0x38, 0xCF, 0x3F, 0x08, 0x67, 0x09, 0x94, 0xEB, 0x26, 0xA8, 0x6B, 238 0xBD, 0x18, 0x34, 0x1B, 0xBB, 0xBF, 0x72, 0xF7, 0x40, 0x35, 0x48, 0x9C, 239 0x51, 0x2F, 0x3B, 0x55, 0xE3, 0xC0, 0x9F, 0xD8, 0xD3, 0xF3, 0x8D, 0xB1, 240 0xFF, 0xA7, 0x3E, 0xDC, 0x86, 0x77, 0xD7, 0xA6, 0x11, 0xFB, 0xF4, 0xBA, 241 0x92, 0x91, 0x64, 0x83, 0xF1, 0x33, 0xEF, 0xDA, 0x2C, 0xB5, 0xB2, 0x2B, 242 0x88, 0xD1, 0x99, 0xCB, 0x8C, 0x84, 0x1D, 0x14, 0x81, 0x97, 0x71, 0xCA, 243 0x5F, 0xA3, 0x8B, 0x57, 0x3C, 0x82, 0xC4, 0x52, 0x5C, 0x1C, 0xE8, 0xA0, 244 0x04, 0xB4, 0x85, 0x4A, 0xF6, 0x13, 0x54, 0xB6, 0xDF, 0x0C, 0x1A, 0x8E, 245 0xDE, 0xE0, 0x39, 0xFC, 0x20, 0x9B, 0x24, 0x4E, 0xA9, 0x98, 0x9E, 0xAB, 246 0xF2, 0x60, 0xD0, 0x6C, 0xEA, 0xFA, 0xC7, 0xD9, 0x00, 0xD4, 0x1F, 0x6E, 247 0x43, 0xBC, 0xEC, 0x53, 0x89, 0xFE, 0x7A, 0x5D, 0x49, 0xC9, 0x32, 0xC2, 248 0xF9, 0x9A, 0xF8, 0x6D, 0x16, 0xDB, 0x59, 0x96, 0x44, 0xE9, 0xCD, 0xE6, 249 0x46, 0x42, 0x8F, 0x0A, 0xC1, 0xCC, 0xB9, 0x65, 0xB0, 0xD2, 0xC6, 0xAC, 250 0x1E, 0x41, 0x62, 0x29, 0x2E, 0x0E, 0x74, 0x50, 0x02, 0x5A, 0xC3, 0x25, 251 0x7B, 0x8A, 0x2A, 0x5B, 0xF0, 0x06, 0x0D, 0x47, 0x6F, 0x70, 0x9D, 0x7E, 252 0x10, 0xCE, 0x12, 0x27, 0xD5, 0x4C, 0x4F, 0xD6, 0x79, 0x30, 0x68, 0x36, 253 0x75, 0x7D, 0xE4, 0xED, 0x80, 0x6A, 0x90, 0x37, 0xA2, 0x5E, 0x76, 0xAA, 254 0xC5, 0x7F, 0x3D, 0xAF, 0xA5, 0xE5, 0x19, 0x61, 0xFD, 0x4D, 0x7C, 0xB7, 255 0x0B, 0xEE, 0xAD, 0x4B, 0x22, 0xF5, 0xE7, 0x73, 0x23, 0x21, 0xC8, 0x05, 256 0xE1, 0x66, 0xDD, 0xB3, 0x58, 0x69, 0x63, 0x56, 0x0F, 0xA1, 0x31, 0x95, 257 0x17, 0x07, 0x3A, 0x28 ]; 258 259 __gshared immutable ubyte[512] LOG = [ 260 0x80, 0x00, 0xB0, 0x09, 0x60, 0xEF, 0xB9, 0xFD, 0x10, 0x12, 0x9F, 0xE4, 261 0x69, 0xBA, 0xAD, 0xF8, 0xC0, 0x38, 0xC2, 0x65, 0x4F, 0x06, 0x94, 0xFC, 262 0x19, 0xDE, 0x6A, 0x1B, 0x5D, 0x4E, 0xA8, 0x82, 0x70, 0xED, 0xE8, 0xEC, 263 0x72, 0xB3, 0x15, 0xC3, 0xFF, 0xAB, 0xB6, 0x47, 0x44, 0x01, 0xAC, 0x25, 264 0xC9, 0xFA, 0x8E, 0x41, 0x1A, 0x21, 0xCB, 0xD3, 0x0D, 0x6E, 0xFE, 0x26, 265 0x58, 0xDA, 0x32, 0x0F, 0x20, 0xA9, 0x9D, 0x84, 0x98, 0x05, 0x9C, 0xBB, 266 0x22, 0x8C, 0x63, 0xE7, 0xC5, 0xE1, 0x73, 0xC6, 0xAF, 0x24, 0x5B, 0x87, 267 0x66, 0x27, 0xF7, 0x57, 0xF4, 0x96, 0xB1, 0xB7, 0x5C, 0x8B, 0xD5, 0x54, 268 0x79, 0xDF, 0xAA, 0xF6, 0x3E, 0xA3, 0xF1, 0x11, 0xCA, 0xF5, 0xD1, 0x17, 269 0x7B, 0x93, 0x83, 0xBC, 0xBD, 0x52, 0x1E, 0xEB, 0xAE, 0xCC, 0xD6, 0x35, 270 0x08, 0xC8, 0x8A, 0xB4, 0xE2, 0xCD, 0xBF, 0xD9, 0xD0, 0x50, 0x59, 0x3F, 271 0x4D, 0x62, 0x34, 0x0A, 0x48, 0x88, 0xB5, 0x56, 0x4C, 0x2E, 0x6B, 0x9E, 272 0xD2, 0x3D, 0x3C, 0x03, 0x13, 0xFB, 0x97, 0x51, 0x75, 0x4A, 0x91, 0x71, 273 0x23, 0xBE, 0x76, 0x2A, 0x5F, 0xF9, 0xD4, 0x55, 0x0B, 0xDC, 0x37, 0x31, 274 0x16, 0x74, 0xD7, 0x77, 0xA7, 0xE6, 0x07, 0xDB, 0xA4, 0x2F, 0x46, 0xF3, 275 0x61, 0x45, 0x67, 0xE3, 0x0C, 0xA2, 0x3B, 0x1C, 0x85, 0x18, 0x04, 0x1D, 276 0x29, 0xA0, 0x8F, 0xB2, 0x5A, 0xD8, 0xA6, 0x7E, 0xEE, 0x8D, 0x53, 0x4B, 277 0xA1, 0x9A, 0xC1, 0x0E, 0x7A, 0x49, 0xA5, 0x2C, 0x81, 0xC4, 0xC7, 0x36, 278 0x2B, 0x7F, 0x43, 0x95, 0x33, 0xF2, 0x6C, 0x68, 0x6D, 0xF0, 0x02, 0x28, 279 0xCE, 0xDD, 0x9B, 0xEA, 0x5E, 0x99, 0x7C, 0x14, 0x86, 0xCF, 0xE5, 0x42, 280 0xB8, 0x40, 0x78, 0x2D, 0x3A, 0xE9, 0x64, 0x1F, 0x92, 0x90, 0x7D, 0x39, 281 0x6F, 0xE0, 0x89, 0x30, 0x80, 0x00, 0xB0, 0x09, 0x60, 0xEF, 0xB9, 0xFD, 282 0x10, 0x12, 0x9F, 0xE4, 0x69, 0xBA, 0xAD, 0xF8, 0xC0, 0x38, 0xC2, 0x65, 283 0x4F, 0x06, 0x94, 0xFC, 0x19, 0xDE, 0x6A, 0x1B, 0x5D, 0x4E, 0xA8, 0x82, 284 0x70, 0xED, 0xE8, 0xEC, 0x72, 0xB3, 0x15, 0xC3, 0xFF, 0xAB, 0xB6, 0x47, 285 0x44, 0x01, 0xAC, 0x25, 0xC9, 0xFA, 0x8E, 0x41, 0x1A, 0x21, 0xCB, 0xD3, 286 0x0D, 0x6E, 0xFE, 0x26, 0x58, 0xDA, 0x32, 0x0F, 0x20, 0xA9, 0x9D, 0x84, 287 0x98, 0x05, 0x9C, 0xBB, 0x22, 0x8C, 0x63, 0xE7, 0xC5, 0xE1, 0x73, 0xC6, 288 0xAF, 0x24, 0x5B, 0x87, 0x66, 0x27, 0xF7, 0x57, 0xF4, 0x96, 0xB1, 0xB7, 289 0x5C, 0x8B, 0xD5, 0x54, 0x79, 0xDF, 0xAA, 0xF6, 0x3E, 0xA3, 0xF1, 0x11, 290 0xCA, 0xF5, 0xD1, 0x17, 0x7B, 0x93, 0x83, 0xBC, 0xBD, 0x52, 0x1E, 0xEB, 291 0xAE, 0xCC, 0xD6, 0x35, 0x08, 0xC8, 0x8A, 0xB4, 0xE2, 0xCD, 0xBF, 0xD9, 292 0xD0, 0x50, 0x59, 0x3F, 0x4D, 0x62, 0x34, 0x0A, 0x48, 0x88, 0xB5, 0x56, 293 0x4C, 0x2E, 0x6B, 0x9E, 0xD2, 0x3D, 0x3C, 0x03, 0x13, 0xFB, 0x97, 0x51, 294 0x75, 0x4A, 0x91, 0x71, 0x23, 0xBE, 0x76, 0x2A, 0x5F, 0xF9, 0xD4, 0x55, 295 0x0B, 0xDC, 0x37, 0x31, 0x16, 0x74, 0xD7, 0x77, 0xA7, 0xE6, 0x07, 0xDB, 296 0xA4, 0x2F, 0x46, 0xF3, 0x61, 0x45, 0x67, 0xE3, 0x0C, 0xA2, 0x3B, 0x1C, 297 0x85, 0x18, 0x04, 0x1D, 0x29, 0xA0, 0x8F, 0xB2, 0x5A, 0xD8, 0xA6, 0x7E, 298 0xEE, 0x8D, 0x53, 0x4B, 0xA1, 0x9A, 0xC1, 0x0E, 0x7A, 0x49, 0xA5, 0x2C, 299 0x81, 0xC4, 0xC7, 0x36, 0x2B, 0x7F, 0x43, 0x95, 0x33, 0xF2, 0x6C, 0x68, 300 0x6D, 0xF0, 0x02, 0x28, 0xCE, 0xDD, 0x9B, 0xEA, 0x5E, 0x99, 0x7C, 0x14, 301 0x86, 0xCF, 0xE5, 0x42, 0xB8, 0x40, 0x78, 0x2D, 0x3A, 0xE9, 0x64, 0x1F, 302 0x92, 0x90, 0x7D, 0x39, 0x6F, 0xE0, 0x89, 0x30 ];