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