1 /** 2 * RC2 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.rc2; 12 13 import botan.constants; 14 static if (BOTAN_HAS_RC2): 15 16 import botan.block.block_cipher; 17 import botan.utils.loadstor; 18 import botan.utils.rotate; 19 import botan.utils.mem_ops; 20 21 /** 22 * RC2 23 */ 24 final class RC2 : BlockCipherFixedParams!(8, 1, 32), BlockCipher, SymmetricAlgorithm 25 { 26 public: 27 /* 28 * RC2 Encryption 29 */ 30 override void encryptN(const(ubyte)* input, ubyte* output, size_t blocks) 31 { 32 foreach (size_t i; 0 .. blocks) 33 { 34 ushort R0 = loadLittleEndian!ushort(input, 0); 35 ushort R1 = loadLittleEndian!ushort(input, 1); 36 ushort R2 = loadLittleEndian!ushort(input, 2); 37 ushort R3 = loadLittleEndian!ushort(input, 3); 38 39 foreach (size_t j; 0 .. 16) 40 { 41 R0 += (R1 & ~cast(int)R3) + (R2 & R3) + m_K[4*j]; 42 R0 = rotateLeft(R0, 1); 43 44 R1 += (R2 & ~cast(int)R0) + (R3 & R0) + m_K[4*j + 1]; 45 R1 = rotateLeft(R1, 2); 46 47 R2 += (R3 & ~cast(int)R1) + (R0 & R1) + m_K[4*j + 2]; 48 R2 = rotateLeft(R2, 3); 49 50 R3 += (R0 & ~cast(int)R2) + (R1 & R2) + m_K[4*j + 3]; 51 R3 = rotateLeft(R3, 5); 52 53 if (j == 4 || j == 10) 54 { 55 R0 += m_K[R3 % 64]; 56 R1 += m_K[R0 % 64]; 57 R2 += m_K[R1 % 64]; 58 R3 += m_K[R2 % 64]; 59 } 60 } 61 62 storeLittleEndian(output, R0, R1, R2, R3); 63 64 input += BLOCK_SIZE; 65 output += BLOCK_SIZE; 66 } 67 } 68 69 /* 70 * RC2 Decryption 71 */ 72 override void decryptN(const(ubyte)* input, ubyte* output, size_t blocks) 73 { 74 foreach (size_t i; 0 .. blocks) 75 { 76 ushort R0 = loadLittleEndian!ushort(input, 0); 77 ushort R1 = loadLittleEndian!ushort(input, 1); 78 ushort R2 = loadLittleEndian!ushort(input, 2); 79 ushort R3 = loadLittleEndian!ushort(input, 3); 80 81 foreach (size_t j; 0 .. 16) 82 { 83 R3 = rotateRight(R3, 5); 84 R3 -= (R0 & ~cast(int)R2) + (R1 & R2) + m_K[63 - (4*j + 0)]; 85 86 R2 = rotateRight(R2, 3); 87 R2 -= (R3 & ~cast(int)R1) + (R0 & R1) + m_K[63 - (4*j + 1)]; 88 89 R1 = rotateRight(R1, 2); 90 R1 -= (R2 & ~cast(int)R0) + (R3 & R0) + m_K[63 - (4*j + 2)]; 91 92 R0 = rotateRight(R0, 1); 93 R0 -= (R1 & ~cast(int)R3) + (R2 & R3) + m_K[63 - (4*j + 3)]; 94 95 if (j == 4 || j == 10) 96 { 97 R3 -= m_K[R2 % 64]; 98 R2 -= m_K[R1 % 64]; 99 R1 -= m_K[R0 % 64]; 100 R0 -= m_K[R3 % 64]; 101 } 102 } 103 104 storeLittleEndian(output, R0, R1, R2, R3); 105 106 input += BLOCK_SIZE; 107 output += BLOCK_SIZE; 108 } 109 } 110 /** 111 * Return the code of the effective key bits 112 * Params: 113 * bits = key length 114 * Returns: EKB code 115 */ 116 version(none) 117 static ubyte EKBCode(size_t ekb) 118 { 119 __gshared immutable ubyte[256] EKB = [ 120 0xBD, 0x56, 0xEA, 0xF2, 0xA2, 0xF1, 0xAC, 0x2A, 0xB0, 0x93, 0xD1, 0x9C, 121 0x1B, 0x33, 0xFD, 0xD0, 0x30, 0x04, 0xB6, 0xDC, 0x7D, 0xDF, 0x32, 0x4B, 122 0xF7, 0xCB, 0x45, 0x9B, 0x31, 0xBB, 0x21, 0x5A, 0x41, 0x9F, 0xE1, 0xD9, 123 0x4A, 0x4D, 0x9E, 0xDA, 0xA0, 0x68, 0x2C, 0xC3, 0x27, 0x5F, 0x80, 0x36, 124 0x3E, 0xEE, 0xFB, 0x95, 0x1A, 0xFE, 0xCE, 0xA8, 0x34, 0xA9, 0x13, 0xF0, 125 0xA6, 0x3F, 0xD8, 0x0C, 0x78, 0x24, 0xAF, 0x23, 0x52, 0xC1, 0x67, 0x17, 126 0xF5, 0x66, 0x90, 0xE7, 0xE8, 0x07, 0xB8, 0x60, 0x48, 0xE6, 0x1E, 0x53, 127 0xF3, 0x92, 0xA4, 0x72, 0x8C, 0x08, 0x15, 0x6E, 0x86, 0x00, 0x84, 0xFA, 128 0xF4, 0x7F, 0x8A, 0x42, 0x19, 0xF6, 0xDB, 0xCD, 0x14, 0x8D, 0x50, 0x12, 129 0xBA, 0x3C, 0x06, 0x4E, 0xEC, 0xB3, 0x35, 0x11, 0xA1, 0x88, 0x8E, 0x2B, 130 0x94, 0x99, 0xB7, 0x71, 0x74, 0xD3, 0xE4, 0xBF, 0x3A, 0xDE, 0x96, 0x0E, 131 0xBC, 0x0A, 0xED, 0x77, 0xFC, 0x37, 0x6B, 0x03, 0x79, 0x89, 0x62, 0xC6, 132 0xD7, 0xC0, 0xD2, 0x7C, 0x6A, 0x8B, 0x22, 0xA3, 0x5B, 0x05, 0x5D, 0x02, 133 0x75, 0xD5, 0x61, 0xE3, 0x18, 0x8F, 0x55, 0x51, 0xAD, 0x1F, 0x0B, 0x5E, 134 0x85, 0xE5, 0xC2, 0x57, 0x63, 0xCA, 0x3D, 0x6C, 0xB4, 0xC5, 0xCC, 0x70, 135 0xB2, 0x91, 0x59, 0x0D, 0x47, 0x20, 0xC8, 0x4F, 0x58, 0xE0, 0x01, 0xE2, 136 0x16, 0x38, 0xC4, 0x6F, 0x3B, 0x0F, 0x65, 0x46, 0xBE, 0x7E, 0x2D, 0x7B, 137 0x82, 0xF9, 0x40, 0xB5, 0x1D, 0x73, 0xF8, 0xEB, 0x26, 0xC7, 0x87, 0x97, 138 0x25, 0x54, 0xB1, 0x28, 0xAA, 0x98, 0x9D, 0xA5, 0x64, 0x6D, 0x7A, 0xD4, 139 0x10, 0x81, 0x44, 0xEF, 0x49, 0xD6, 0xAE, 0x2E, 0xDD, 0x76, 0x5C, 0x2F, 140 0xA7, 0x1C, 0xC9, 0x09, 0x69, 0x9A, 0x83, 0xCF, 0x29, 0x39, 0xB9, 0xE9, 141 0x4C, 0xFF, 0x43, 0xAB ]; 142 143 if (ekb < 256) 144 return EKB[ekb]; 145 else 146 throw new EncodingError("EKB_code: EKB is too large"); 147 } 148 149 override void clear() 150 { 151 zap(m_K); 152 } 153 154 override @property string name() const { return "RC2"; } 155 override @property size_t parallelism() const { return 1; } 156 override BlockCipher clone() const { return new RC2; } 157 override size_t blockSize() const { return super.blockSize(); } 158 override KeyLengthSpecification keySpec() const { return super.keySpec(); } 159 protected: 160 /* 161 * RC2 Key Schedule 162 */ 163 override void keySchedule(const(ubyte)* key, size_t length) 164 { 165 __gshared immutable ubyte[256] TABLE = [ 166 0xD9, 0x78, 0xF9, 0xC4, 0x19, 0xDD, 0xB5, 0xED, 0x28, 0xE9, 0xFD, 0x79, 167 0x4A, 0xA0, 0xD8, 0x9D, 0xC6, 0x7E, 0x37, 0x83, 0x2B, 0x76, 0x53, 0x8E, 168 0x62, 0x4C, 0x64, 0x88, 0x44, 0x8B, 0xFB, 0xA2, 0x17, 0x9A, 0x59, 0xF5, 169 0x87, 0xB3, 0x4F, 0x13, 0x61, 0x45, 0x6D, 0x8D, 0x09, 0x81, 0x7D, 0x32, 170 0xBD, 0x8F, 0x40, 0xEB, 0x86, 0xB7, 0x7B, 0x0B, 0xF0, 0x95, 0x21, 0x22, 171 0x5C, 0x6B, 0x4E, 0x82, 0x54, 0xD6, 0x65, 0x93, 0xCE, 0x60, 0xB2, 0x1C, 172 0x73, 0x56, 0xC0, 0x14, 0xA7, 0x8C, 0xF1, 0xDC, 0x12, 0x75, 0xCA, 0x1F, 173 0x3B, 0xBE, 0xE4, 0xD1, 0x42, 0x3D, 0xD4, 0x30, 0xA3, 0x3C, 0xB6, 0x26, 174 0x6F, 0xBF, 0x0E, 0xDA, 0x46, 0x69, 0x07, 0x57, 0x27, 0xF2, 0x1D, 0x9B, 175 0xBC, 0x94, 0x43, 0x03, 0xF8, 0x11, 0xC7, 0xF6, 0x90, 0xEF, 0x3E, 0xE7, 176 0x06, 0xC3, 0xD5, 0x2F, 0xC8, 0x66, 0x1E, 0xD7, 0x08, 0xE8, 0xEA, 0xDE, 177 0x80, 0x52, 0xEE, 0xF7, 0x84, 0xAA, 0x72, 0xAC, 0x35, 0x4D, 0x6A, 0x2A, 178 0x96, 0x1A, 0xD2, 0x71, 0x5A, 0x15, 0x49, 0x74, 0x4B, 0x9F, 0xD0, 0x5E, 179 0x04, 0x18, 0xA4, 0xEC, 0xC2, 0xE0, 0x41, 0x6E, 0x0F, 0x51, 0xCB, 0xCC, 180 0x24, 0x91, 0xAF, 0x50, 0xA1, 0xF4, 0x70, 0x39, 0x99, 0x7C, 0x3A, 0x85, 181 0x23, 0xB8, 0xB4, 0x7A, 0xFC, 0x02, 0x36, 0x5B, 0x25, 0x55, 0x97, 0x31, 182 0x2D, 0x5D, 0xFA, 0x98, 0xE3, 0x8A, 0x92, 0xAE, 0x05, 0xDF, 0x29, 0x10, 183 0x67, 0x6C, 0xBA, 0xC9, 0xD3, 0x00, 0xE6, 0xCF, 0xE1, 0x9E, 0xA8, 0x2C, 184 0x63, 0x16, 0x01, 0x3F, 0x58, 0xE2, 0x89, 0xA9, 0x0D, 0x38, 0x34, 0x1B, 185 0xAB, 0x33, 0xFF, 0xB0, 0xBB, 0x48, 0x0C, 0x5F, 0xB9, 0xB1, 0xCD, 0x2E, 186 0xC5, 0xF3, 0xDB, 0x47, 0xE5, 0xA5, 0x9C, 0x77, 0x0A, 0xA6, 0x20, 0x68, 187 0xFE, 0x7F, 0xC1, 0xAD ]; 188 189 SecureVector!ubyte L = SecureVector!ubyte(128); 190 copyMem(L.ptr, key, length); 191 192 foreach (size_t i; length .. 128) 193 L[i] = TABLE[(L[i-1] + L[i-length]) % 256]; 194 195 L[128-length] = TABLE[L[128-length]]; 196 for (int i = cast(int) (127 - length); i >= 0; --i) { 197 L[i] = TABLE[L[i+1] ^ L[i+length]]; 198 } 199 200 m_K.resize(64); 201 loadLittleEndian!ushort(m_K.ptr, L.ptr, 64); 202 } 203 204 SecureVector!ushort m_K; 205 }