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 ];