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 & ~R3) + (R2 & R3) + m_K[4*j];
42                 R0 = rotateLeft(R0, 1);
43                 
44                 R1 += (R2 & ~R0) + (R3 & R0) + m_K[4*j + 1];
45                 R1 = rotateLeft(R1, 2);
46                 
47                 R2 += (R3 & ~R1) + (R0 & R1) + m_K[4*j + 2];
48                 R2 = rotateLeft(R2, 3);
49                 
50                 R3 += (R0 & ~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 & ~R2) + (R1 & R2) + m_K[63 - (4*j + 0)];
85                 
86                 R2 = rotateRight(R2, 3);
87                 R2 -= (R3 & ~R1) + (R0 & R1) + m_K[63 - (4*j + 1)];
88                 
89                 R1 = rotateRight(R1, 2);
90                 R1 -= (R2 & ~R0) + (R3 & R0) + m_K[63 - (4*j + 2)];
91                 
92                 R0 = rotateRight(R0, 1);
93                 R0 -= (R1 & ~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 }