1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package io.github.tonywasher.joceanus.gordianknot.impl.ext.engines;
18
19 import org.bouncycastle.crypto.BlockCipher;
20 import org.bouncycastle.crypto.CipherParameters;
21 import org.bouncycastle.crypto.DataLengthException;
22 import org.bouncycastle.crypto.OutputLengthException;
23 import org.bouncycastle.crypto.params.KeyParameter;
24
25
26
27
28 @SuppressWarnings("checkstyle:MagicNumber")
29 public class GordianMARSEngine
30 implements BlockCipher {
31
32
33
34 private static final int BLOCKSIZE = 128;
35
36
37
38
39 private static final int BLOCKSIZEB = (BLOCKSIZE / 8);
40
41
42
43
44 private static final int INTLENGTH = BLOCKSIZEB / Integer.BYTES;
45
46
47
48
49 private Boolean forEncryption;
50
51
52
53
54 private final int[] input = new int[INTLENGTH];
55
56
57
58
59 private final int[] output = new int[INTLENGTH];
60
61
62
63
64 private static final int[] S_BOX = {
65 0x09d0c479, 0x28c8ffe0, 0x84aa6c39, 0x9dad7287,
66 0x7dff9be3, 0xd4268361, 0xc96da1d4, 0x7974cc93,
67 0x85d0582e, 0x2a4b5705, 0x1ca16a62, 0xc3bd279d,
68 0x0f1f25e5, 0x5160372f, 0xc695c1fb, 0x4d7ff1e4,
69 0xae5f6bf4, 0x0d72ee46, 0xff23de8a, 0xb1cf8e83,
70 0xf14902e2, 0x3e981e42, 0x8bf53eb6, 0x7f4bf8ac,
71 0x83631f83, 0x25970205, 0x76afe784, 0x3a7931d4,
72 0x4f846450, 0x5c64c3f6, 0x210a5f18, 0xc6986a26,
73 0x28f4e826, 0x3a60a81c, 0xd340a664, 0x7ea820c4,
74 0x526687c5, 0x7eddd12b, 0x32a11d1d, 0x9c9ef086,
75 0x80f6e831, 0xab6f04ad, 0x56fb9b53, 0x8b2e095c,
76 0xb68556ae, 0xd2250b0d, 0x294a7721, 0xe21fb253,
77 0xae136749, 0xe82aae86, 0x93365104, 0x99404a66,
78 0x78a784dc, 0xb69ba84b, 0x04046793, 0x23db5c1e,
79 0x46cae1d6, 0x2fe28134, 0x5a223942, 0x1863cd5b,
80 0xc190c6e3, 0x07dfb846, 0x6eb88816, 0x2d0dcc4a,
81 0xa4ccae59, 0x3798670d, 0xcbfa9493, 0x4f481d45,
82 0xeafc8ca8, 0xdb1129d6, 0xb0449e20, 0x0f5407fb,
83 0x6167d9a8, 0xd1f45763, 0x4daa96c3, 0x3bec5958,
84 0xababa014, 0xb6ccd201, 0x38d6279f, 0x02682215,
85 0x8f376cd5, 0x092c237e, 0xbfc56593, 0x32889d2c,
86 0x854b3e95, 0x05bb9b43, 0x7dcd5dcd, 0xa02e926c,
87 0xfae527e5, 0x36a1c330, 0x3412e1ae, 0xf257f462,
88 0x3c4f1d71, 0x30a2e809, 0x68e5f551, 0x9c61ba44,
89 0x5ded0ab8, 0x75ce09c8, 0x9654f93e, 0x698c0cca,
90 0x243cb3e4, 0x2b062b97, 0x0f3b8d9e, 0x00e050df,
91 0xfc5d6166, 0xe35f9288, 0xc079550d, 0x0591aee8,
92 0x8e531e74, 0x75fe3578, 0x2f6d829a, 0xf60b21ae,
93 0x95e8eb8d, 0x6699486b, 0x901d7d9b, 0xfd6d6e31,
94 0x1090acef, 0xe0670dd8, 0xdab2e692, 0xcd6d4365,
95 0xe5393514, 0x3af345f0, 0x6241fc4d, 0x460da3a3,
96 0x7bcf3729, 0x8bf1d1e0, 0x14aac070, 0x1587ed55,
97 0x3afd7d3e, 0xd2f29e01, 0x29a9d1f6, 0xefb10c53,
98 0xcf3b870f, 0xb414935c, 0x664465ed, 0x024acac7,
99 0x59a744c1, 0x1d2936a7, 0xdc580aa6, 0xcf574ca8,
100 0x040a7a10, 0x6cd81807, 0x8a98be4c, 0xaccea063,
101 0xc33e92b5, 0xd1e0e03d, 0xb322517e, 0x2092bd13,
102 0x386b2c4a, 0x52e8dd58, 0x58656dfb, 0x50820371,
103 0x41811896, 0xe337ef7e, 0xd39fb119, 0xc97f0df6,
104 0x68fea01b, 0xa150a6e5, 0x55258962, 0xeb6ff41b,
105 0xd7c9cd7a, 0xa619cd9e, 0xbcf09576, 0x2672c073,
106 0xf003fb3c, 0x4ab7a50b, 0x1484126a, 0x487ba9b1,
107 0xa64fc9c6, 0xf6957d49, 0x38b06a75, 0xdd805fcd,
108 0x63d094cf, 0xf51c999e, 0x1aa4d343, 0xb8495294,
109 0xce9f8e99, 0xbffcd770, 0xc7c275cc, 0x378453a7,
110 0x7b21be33, 0x397f41bd, 0x4e94d131, 0x92cc1f98,
111 0x5915ea51, 0x99f861b7, 0xc9980a88, 0x1d74fd5f,
112 0xb0a495f8, 0x614deed0, 0xb5778eea, 0x5941792d,
113 0xfa90c1f8, 0x33f824b4, 0xc4965372, 0x3ff6d550,
114 0x4ca5fec0, 0x8630e964, 0x5b3fbbd6, 0x7da26a48,
115 0xb203231a, 0x04297514, 0x2d639306, 0x2eb13149,
116 0x16a45272, 0x532459a0, 0x8e5f4872, 0xf966c7d9,
117 0x07128dc0, 0x0d44db62, 0xafc8d52d, 0x06316131,
118 0xd838e7ce, 0x1bc41d00, 0x3a2e8c0f, 0xea83837e,
119 0xb984737d, 0x13ba4891, 0xc4f8b949, 0xa6d6acb3,
120 0xa215cdce, 0x8359838b, 0x6bd1aa31, 0xf579dd52,
121 0x21b93f93, 0xf5176781, 0x187dfdde, 0xe94aeb76,
122 0x2b38fd54, 0x431de1da, 0xab394825, 0x9ad3048f,
123 0xdfea32aa, 0x659473e3, 0x623f7863, 0xf3346c59,
124 0xab3ab685, 0x3346a90b, 0x6b56443e, 0xc6de01f8,
125 0x8d421fc0, 0x9b0ed10c, 0x88f1a1e9, 0x54c1f029,
126 0x7dead57b, 0x8d7ba426, 0x4cf5178a, 0x551a7cca,
127 0x1a9a5f08, 0xfcd651b9, 0x25605182, 0xe11fc6c3,
128 0xb6fd9676, 0x337b3027, 0xb7c8eb14, 0x9e5fd030,
129 0x6b57e354, 0xad913cf7, 0x7e16688d, 0x58872a69,
130 0x2c2fc7df, 0xe389ccc6, 0x30738df1, 0x0824a734,
131 0xe1797a8b, 0xa4a8d57b, 0x5b5d193b, 0xc8a8309b,
132 0x73f9a978, 0x73398d32, 0x0f59573e, 0xe9df2b03,
133 0xe8a5b6c8, 0x848d0704, 0x98df93c2, 0x720a1dc3,
134 0x684f259a, 0x943ba848, 0xa6370152, 0x863b5ea3,
135 0xd17b978b, 0x6d9b58ef, 0x0a700dd4, 0xa73d36bf,
136 0x8e6a0829, 0x8695bc14, 0xe35b3447, 0x933ac568,
137 0x8894b022, 0x2f511c27, 0xddfbcc3c, 0x006662b6,
138 0x117c83fe, 0x4e12b414, 0xc2bca766, 0x3a2fec10,
139 0xf4562420, 0x55792e2a, 0x46f5d857, 0xceda25ce,
140 0xc3601d3b, 0x6c00ab46, 0xefac9c28, 0xb3c35047,
141 0x611dfee3, 0x257c3207, 0xfdd58482, 0x3b14d84f,
142 0x23becb64, 0xa075f3a3, 0x088f8ead, 0x07adf158,
143 0x7796943c, 0xfacabf3d, 0xc09730cd, 0xf7679969,
144 0xda44e9ed, 0x2c854c12, 0x35935fa3, 0x2f057d9f,
145 0x690624f8, 0x1cb0bafd, 0x7b0dbdc6, 0x810f23bb,
146 0xfa929a1a, 0x6d969a17, 0x6742979b, 0x74ac7d05,
147 0x010e65c4, 0x86a3d963, 0xf907b5a0, 0xd0042bd3,
148 0x158d7d03, 0x287a8255, 0xbba8366f, 0x096edc33,
149 0x21916a7b, 0x77b56b86, 0x951622f9, 0xa6c5e650,
150 0x8cea17d1, 0xcd8c62bc, 0xa3d63433, 0x358a68fd,
151 0x0f9b9d3c, 0xd6aa295b, 0xfe33384a, 0xc000738e,
152 0xcd67eb2f, 0xe2eb6dc2, 0x97338b02, 0x06c9f246,
153 0x419cf1ad, 0x2b83c045, 0x3723f18a, 0xcb5b3089,
154 0x160bead7, 0x5d494656, 0x35f8a74b, 0x1e4e6c9e,
155 0x000399bd, 0x67466880, 0xb4174831, 0xacf423b2,
156 0xca815ab3, 0x5a6395e7, 0x302a67c5, 0x8bdb446b,
157 0x108f8fa4, 0x10223eda, 0x92b8b48b, 0x7f38d0ee,
158 0xab2701d4, 0x0262d415, 0xaf224a30, 0xb3d88aba,
159 0xf8b2c3af, 0xdaf7ef70, 0xcc97d3b7, 0xe9614b6c,
160 0x2baebff4, 0x70f687cf, 0x386c9156, 0xce092ee5,
161 0x01e87da6, 0x6ce91e6a, 0xbb7bcc84, 0xc7922c20,
162 0x9d3b71fd, 0x060e41c6, 0xd7590f15, 0x4e03bb47,
163 0x183c198e, 0x63eeb240, 0x2ddbf49a, 0x6d5cba54,
164 0x923750af, 0xf9e14236, 0x7838162b, 0x59726c72,
165 0x81b66760, 0xbb2926c1, 0x48a0ce0d, 0xa6c0496d,
166 0xad43507b, 0x718d496a, 0x9df057af, 0x44b1bde6,
167 0x054356dc, 0xde7ced35, 0xd51a138b, 0x62088cc9,
168 0x35830311, 0xc96efca2, 0x686f86ec, 0x8e77cb68,
169 0x63e1d6b8, 0xc80f9778, 0x79c491fd, 0x1b4c67f2,
170 0x72698d7d, 0x5e368c31, 0xf7d95e2e, 0xa1d3493f,
171 0xdcd9433e, 0x896f1552, 0x4bc4ca7a, 0xa6d1baf4,
172 0xa5a96dcc, 0x0bef8b46, 0xa169fda7, 0x74df40b7,
173 0x4e208804, 0x9a756607, 0x038e87c8, 0x20211e44,
174 0x8b7ad4bf, 0xc6403f35, 0x1848e36d, 0x80bdb038,
175 0x1e62891c, 0x643d2107, 0xbf04d6f8, 0x21092c8c,
176 0xf644f389, 0x0778404e, 0x7b78adb8, 0xa2c52d53,
177 0x42157abe, 0xa2253e2e, 0x7bf3f4ae, 0x80f594f9,
178 0x953194e7, 0x77eb92ed, 0xb3816930, 0xda8d9336,
179 0xbf447469, 0xf26d9483, 0xee6faed5, 0x71371235,
180 0xde425f73, 0xb4e59f43, 0x7dbe2d4e, 0x2d37b185,
181 0x49dc9a63, 0x98c39d98, 0x1301c9a2, 0x389b1bbf,
182 0x0c18588d, 0xa421c1ba, 0x7aa3865c, 0x71e08558,
183 0x3c5cfcaa, 0x7d239ca4, 0x0297d9dd, 0xd7dc2830,
184 0x4b37802b, 0x7428ab54, 0xaeee0347, 0x4b3fbb85,
185 0x692f2f08, 0x134e578e, 0x36d9e0bf, 0xae8b5fcf,
186 0xedb93ecf, 0x2b27248e, 0x170eb1ef, 0x7dc57fd6,
187 0x1e760f16, 0xb1136601, 0x864e1b9b, 0xd7ea7319,
188 0x3ab871bd, 0xcfa4d76f, 0xe31bd782, 0x0dbeb469,
189 0xabb96061, 0x5370f85d, 0xffb07e37, 0xda30d0fb,
190 0xebc977b6, 0x0b98b40f, 0x3a4d0fe6, 0xdf4fc26b,
191 0x159cf22a, 0xc298d6e2, 0x2b78ef6a, 0x61a94ac0,
192 0xab561187, 0x14eea0f0, 0xdf0d4164, 0x19af70ee
193 };
194
195
196
197
198 private final int[] vk = {
199 0x09d0c479, 0x28c8ffe0, 0x84aa6c39, 0x9dad7287, 0x7dff9be3, 0xd4268361,
200 0xc96da1d4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
201 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
202 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
203 };
204
205
206
207
208 private final int[] lKey = new int[40];
209
210 private static int rotr(final int x, final int n) {
211 return ((x >>> n) | (x << (32 - n)));
212 }
213
214 private static int rotl(final int x, final int n) {
215 return ((x << n) | (x >>> (32 - n)));
216 }
217
218 private static void fMix(final int[] vals, final int offset) {
219
220 int myOffset = offset;
221 final int a = myOffset++ % 4;
222 final int b = myOffset++ % 4;
223 final int c = myOffset++ % 4;
224 final int d = myOffset % 4;
225
226
227 int r = rotr(vals[a], 8);
228 vals[b] ^= S_BOX[vals[a] & 255];
229 vals[b] += S_BOX[(r & 255) + 256];
230 r = rotr(vals[a], 16);
231 vals[a] = rotr(vals[a], 24);
232 vals[c] += S_BOX[r & 255];
233 vals[d] ^= S_BOX[(vals[a] & 255) + 256];
234 }
235
236 private static void bMix(final int[] vals, final int offset) {
237
238 int myOffset = offset;
239 final int a = myOffset++ % 4;
240 final int b = myOffset++ % 4;
241 final int c = myOffset++ % 4;
242 final int d = myOffset % 4;
243
244
245 int r = rotl(vals[a], 8);
246 vals[b] ^= S_BOX[(vals[a] & 255) + 256];
247 vals[c] -= S_BOX[r & 255];
248 r = rotl(vals[a], 16);
249 vals[a] = rotl(vals[a], 24);
250 vals[d] -= S_BOX[(r & 255) + 256];
251 vals[d] ^= S_BOX[vals[a] & 255];
252 }
253
254 private void fKtr(final int[] vals, final int i, final int offset, final boolean doSwitch) {
255
256 int myOffset = offset;
257 final int a = myOffset++ % 4;
258 int b = myOffset++ % 4;
259 final int c = myOffset++ % 4;
260 int d = myOffset % 4;
261
262
263 if (doSwitch) {
264 final int temp = b;
265 b = d;
266 d = temp;
267 }
268
269
270 final int m = vals[a] + lKey[i];
271 vals[a] = rotl(vals[a], 13);
272 int r = vals[a] * lKey[i + 1];
273 int l = S_BOX[m & 511];
274 r = rotl(r, 5);
275 vals[c] += rotl(m, r);
276 l ^= r;
277 r = rotl(r, 5);
278 l ^= r;
279 vals[d] ^= r;
280 vals[b] += rotl(l, r);
281 }
282
283 private void rKtr(final int[] vals, final int i, final int offset, final boolean doSwitch) {
284
285 int myOffset = offset;
286 final int a = myOffset++ % 4;
287 int b = myOffset++ % 4;
288 final int c = myOffset++ % 4;
289 int d = myOffset % 4;
290
291
292 if (doSwitch) {
293 final int temp = b;
294 b = d;
295 d = temp;
296 }
297
298
299 int r = vals[a] * lKey[i + 1];
300 vals[a] = rotr(vals[a], 13);
301 final int m = vals[a] + lKey[i];
302 int l = S_BOX[m & 511];
303 r = rotl(r, 5);
304 l ^= r;
305 vals[c] -= rotl(m, r);
306 r = rotl(r, 5);
307 l ^= r;
308 vals[d] ^= r;
309 vals[b] -= rotl(l, r);
310 }
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326 private static int genMask(final int x) {
327
328
329
330
331 int m = (~x ^ (x >>> 1)) & 0x7fffffff;
332
333
334
335
336
337
338 m &= (m >>> 1) & (m >>> 2);
339 m &= (m >>> 3) & (m >>> 6);
340
341
342 if (m == 0) {
343 return 0;
344 }
345
346
347
348
349
350
351 m <<= 1;
352 m |= (m << 1);
353 m |= (m << 2);
354 m |= (m << 4);
355
356
357
358
359 m |= (m << 1) & ~x & 0x80000000;
360 return m & 0xfffffffc;
361 }
362
363
364
365 private int[] setKey(final int[] inKey, final int keyLen) {
366 int w;
367 int m = keyLen / 32 - 1;
368 for (int i = 0, j = 0; i < 39; ++i) {
369 vk[i + 7] = rotl(vk[i] ^ vk[i + 5], 3) ^ inKey[j] ^ i;
370 j = (j == m
371 ? 0
372 : j + 1);
373 }
374
375 vk[46] = keyLen / 32;
376
377 for (int j = 0; j < 7; ++j) {
378 for (int i = 1; i < 40; ++i) {
379 vk[i + 7] = rotl(vk[i + 7] + S_BOX[vk[i + 6] & 511], 9);
380 }
381 vk[7] = rotl(vk[7] + S_BOX[vk[46] & 511], 9);
382 }
383
384 for (int i = 0, j = 0; i < 40; ++i) {
385 lKey[j] = vk[i + 7];
386 j = (j < 33
387 ? j + 7
388 : j - 33);
389 }
390
391 for (int i = 5; i < 37; i += 2) {
392 w = lKey[i] | 3;
393 m = genMask(w);
394 if (m != 0) {
395 w ^= (rotl(S_BOX[265 + (lKey[i] & 3)], lKey[i + 3] & 31) & m);
396 }
397 lKey[i] = w;
398 }
399 return lKey;
400 }
401
402 private void encrypt(final int[] inBlk, final int[] outBlk) {
403 final int[] vals = new int[4];
404
405 vals[0] = inBlk[0] + lKey[0];
406 vals[1] = inBlk[1] + lKey[1];
407 vals[2] = inBlk[2] + lKey[2];
408 vals[3] = inBlk[3] + lKey[3];
409
410 fMix(vals, 0);
411 vals[0] += vals[3];
412 fMix(vals, 1);
413 vals[1] += vals[2];
414 fMix(vals, 2);
415 fMix(vals, 3);
416
417 fMix(vals, 0);
418 vals[0] += vals[3];
419 fMix(vals, 1);
420 vals[1] += vals[2];
421 fMix(vals, 2);
422 fMix(vals, 3);
423
424 fKtr(vals, 4, 0, false);
425 fKtr(vals, 6, 1, false);
426 fKtr(vals, 8, 2, false);
427 fKtr(vals, 10, 3, false);
428 fKtr(vals, 12, 0, false);
429 fKtr(vals, 14, 1, false);
430 fKtr(vals, 16, 2, false);
431 fKtr(vals, 18, 3, false);
432 fKtr(vals, 20, 0, true);
433 fKtr(vals, 22, 1, true);
434 fKtr(vals, 24, 2, true);
435 fKtr(vals, 26, 3, true);
436 fKtr(vals, 28, 0, true);
437 fKtr(vals, 30, 1, true);
438 fKtr(vals, 32, 2, true);
439 fKtr(vals, 34, 3, true);
440
441 bMix(vals, 0);
442 bMix(vals, 1);
443 vals[2] -= vals[1];
444 bMix(vals, 2);
445 vals[3] -= vals[0];
446 bMix(vals, 3);
447
448 bMix(vals, 0);
449 bMix(vals, 1);
450 vals[2] -= vals[1];
451 bMix(vals, 2);
452 vals[3] -= vals[0];
453 bMix(vals, 3);
454
455 outBlk[0] = vals[0] - lKey[36];
456 outBlk[1] = vals[1] - lKey[37];
457 outBlk[2] = vals[2] - lKey[38];
458 outBlk[3] = vals[3] - lKey[39];
459 }
460
461 private void decrypt(final int[] inBlk, final int[] outBlk) {
462 final int[] vals = new int[4];
463
464 vals[3] = inBlk[0] + lKey[36];
465 vals[2] = inBlk[1] + lKey[37];
466 vals[1] = inBlk[2] + lKey[38];
467 vals[0] = inBlk[3] + lKey[39];
468
469 fMix(vals, 0);
470 vals[0] += vals[3];
471 fMix(vals, 1);
472 vals[1] += vals[2];
473 fMix(vals, 2);
474 fMix(vals, 3);
475
476 fMix(vals, 0);
477 vals[0] += vals[3];
478 fMix(vals, 1);
479 vals[1] += vals[2];
480 fMix(vals, 2);
481 fMix(vals, 3);
482
483 rKtr(vals, 34, 0, false);
484 rKtr(vals, 32, 1, false);
485 rKtr(vals, 30, 2, false);
486 rKtr(vals, 28, 3, false);
487 rKtr(vals, 26, 0, false);
488 rKtr(vals, 24, 1, false);
489 rKtr(vals, 22, 2, false);
490 rKtr(vals, 20, 3, false);
491 rKtr(vals, 18, 0, true);
492 rKtr(vals, 16, 1, true);
493 rKtr(vals, 14, 2, true);
494 rKtr(vals, 12, 3, true);
495 rKtr(vals, 10, 0, true);
496 rKtr(vals, 8, 1, true);
497 rKtr(vals, 6, 2, true);
498 rKtr(vals, 4, 3, true);
499
500 bMix(vals, 0);
501 bMix(vals, 1);
502 vals[2] -= vals[1];
503 bMix(vals, 2);
504 vals[3] -= vals[0];
505 bMix(vals, 3);
506 bMix(vals, 0);
507 bMix(vals, 1);
508 vals[2] -= vals[1];
509 bMix(vals, 2);
510 vals[3] -= vals[0];
511 bMix(vals, 3);
512
513 outBlk[0] = vals[3] - lKey[0];
514 outBlk[1] = vals[2] - lKey[1];
515 outBlk[2] = vals[1] - lKey[2];
516 outBlk[3] = vals[0] - lKey[3];
517 }
518
519
520
521
522
523
524 public void setKey(final byte[] pKey) {
525
526 int keyLength = pKey.length;
527 final int intLength = keyLength / Integer.BYTES;
528 keyLength *= Byte.SIZE;
529
530
531
532 final int[] myIntKey = new int[intLength];
533 for (int i = 0, pos = 0; i < intLength; i++, pos += Integer.BYTES) {
534 myIntKey[i] = ((pKey[pos + 3] & 255) << 24)
535 | ((pKey[pos + 2] & 255) << 16)
536 | ((pKey[pos + 1] & 255) << 8)
537 | (pKey[pos] & 255);
538 }
539
540
541 setKey(myIntKey, keyLength);
542 }
543
544
545
546
547
548
549
550 private void buildInput(final byte[] pInput, final int pOffset) {
551
552 for (int i = 0, pos = pOffset; i < INTLENGTH; i++, pos += Integer.BYTES) {
553 input[i] = ((pInput[pos + 3] & 255) << 24)
554 | ((pInput[pos + 2] & 255) << 16)
555 | ((pInput[pos + 1] & 255) << 8)
556 | (pInput[pos] & 255);
557 }
558 }
559
560
561
562
563
564
565
566 private void buildOutput(final byte[] pOutput, final int pOffset) {
567
568 final int intLength = 4;
569
570
571 for (int i = 0, pos = pOffset; i < intLength; i++, pos += Integer.BYTES) {
572 final int w = output[i];
573 pOutput[pos] = (byte) (w);
574 pOutput[pos + 1] = (byte) (w >> 8);
575 pOutput[pos + 2] = (byte) (w >> 16);
576 pOutput[pos + 3] = (byte) (w >> 24);
577 }
578 }
579
580 @Override
581 public String getAlgorithmName() {
582 return "MARS";
583 }
584
585 @Override
586 public int getBlockSize() {
587 return BLOCKSIZEB;
588 }
589
590 @Override
591 public void init(final boolean forEncrypt, final CipherParameters pParameters) throws IllegalArgumentException {
592
593 if (!(pParameters instanceof KeyParameter)) {
594 throw new IllegalArgumentException("Invalid parameter passed to MARS init - "
595 + pParameters.getClass().getName());
596 }
597
598
599 final byte[] keyBytes = ((KeyParameter) pParameters).getKey();
600 final int keyBitSize = keyBytes.length * Byte.SIZE;
601 if (keyBitSize != 128 && keyBitSize != 192 && keyBitSize != 256) {
602 throw new IllegalArgumentException("KeyBitSize must be 128, 192 or 256");
603 }
604
605
606 this.forEncryption = forEncrypt;
607 setKey(keyBytes);
608 }
609
610 @Override
611 public int processBlock(final byte[] in, final int inOff, final byte[] out, final int outOff) throws DataLengthException, IllegalStateException {
612 if (forEncryption == null) {
613 throw new IllegalStateException("Anubis engine not initialised");
614 }
615 if (inOff > (in.length - BLOCKSIZEB)) {
616 throw new DataLengthException("input buffer too short");
617 }
618 if (outOff > (out.length - BLOCKSIZEB)) {
619 throw new OutputLengthException("output buffer too short");
620 }
621
622 buildInput(in, inOff);
623 if (forEncryption) {
624 encrypt(input, output);
625 } else {
626 decrypt(input, output);
627 }
628 buildOutput(out, outOff);
629 return BLOCKSIZEB;
630 }
631
632 @Override
633 public void reset() {
634
635 }
636 }