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