CamelliaEngine
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Utilities;
using System;
namespace Org.BouncyCastle.Crypto.Engines
{
public class CamelliaEngine : IBlockCipher
{
private bool initialised;
private bool _keyIs128;
private const int BLOCK_SIZE = 16;
private uint[] subkey = new uint[96];
private uint[] kw = new uint[8];
private uint[] ke = new uint[12];
private static readonly uint[] SIGMA = new uint[12] {
2694735487,
1003262091,
3061508184,
1286239154,
3337565999,
3914302142,
1426019237,
4057165596,
283453434,
3731369245,
2958461122,
3018244605
};
private static readonly uint[] SBOX1_1110 = new uint[256] {
1886416896,
2189591040,
741092352,
3974949888,
3014898432,
656877312,
3233857536,
3857048832,
3840205824,
2240120064,
1465341696,
892679424,
3941263872,
202116096,
2930683392,
1094795520,
589505280,
4025478912,
1802201856,
2475922176,
1162167552,
421075200,
2779096320,
555819264,
3991792896,
235802112,
1330597632,
1313754624,
488447232,
1701143808,
2459079168,
3183328512,
2256963072,
3099113472,
2947526400,
2408550144,
2088532992,
3958106880,
522133248,
3469659648,
1044266496,
808464384,
3705461760,
1600085760,
1583242752,
3318072576,
185273088,
437918208,
2795939328,
3789676800,
960051456,
3402287616,
3587560704,
1195853568,
1566399744,
1027423488,
3654932736,
16843008,
1515870720,
3604403712,
1364283648,
1448498688,
1819044864,
1296911616,
2341178112,
218959104,
2593823232,
1717986816,
4227595008,
3435973632,
2964369408,
757935360,
1953788928,
303174144,
724249344,
538976256,
4042321920,
2981212416,
2223277056,
2576980224,
3755990784,
1280068608,
3419130624,
3267543552,
875836416,
2122219008,
1987474944,
84215040,
1835887872,
3082270464,
2846468352,
825307392,
3520188672,
387389184,
67372032,
3621246720,
336860160,
1482184704,
976894464,
1633771776,
3739147776,
454761216,
286331136,
471604224,
842150400,
252645120,
2627509248,
370546176,
1397969664,
404232192,
4076007936,
572662272,
4278124032,
1145324544,
3486502656,
2998055424,
3284386560,
3048584448,
2054846976,
2442236160,
606348288,
134744064,
3907577856,
2829625344,
1616928768,
4244438016,
1768515840,
1347440640,
2863311360,
3503345664,
2694881280,
2105376000,
2711724288,
2307492096,
1650614784,
2543294208,
1414812672,
1532713728,
505290240,
2509608192,
3772833792,
4294967040,
1684300800,
3537031680,
269488128,
3301229568,
0,
1212696576,
2745410304,
4160222976,
1970631936,
3688618752,
2324335104,
50529024,
3873891840,
3671775744,
151587072,
1061109504,
3722304768,
2492765184,
2273806080,
1549556736,
2206434048,
33686016,
3452816640,
1246382592,
2425393152,
858993408,
1936945920,
1734829824,
4143379968,
4092850944,
2644352256,
2139062016,
3217014528,
3806519808,
1381126656,
2610666240,
3638089728,
640034304,
3368601600,
926365440,
3334915584,
993737472,
2172748032,
2526451200,
1869573888,
1263225600,
320017152,
3200171520,
1667457792,
774778368,
3924420864,
2038003968,
2812782336,
2358021120,
2678038272,
1852730880,
3166485504,
2391707136,
690563328,
4126536960,
4193908992,
3065427456,
791621376,
4261281024,
3031741440,
1499027712,
2021160960,
2560137216,
101058048,
1785358848,
3890734848,
1179010560,
1903259904,
3132799488,
3570717696,
623191296,
2880154368,
1111638528,
2290649088,
2728567296,
2374864128,
4210752000,
1920102912,
117901056,
3115956480,
1431655680,
4177065984,
4008635904,
2896997376,
168430080,
909522432,
1229539584,
707406336,
1751672832,
1010580480,
943208448,
4059164928,
2762253312,
1077952512,
673720320,
3553874688,
2071689984,
3149642496,
3385444608,
1128481536,
3250700544,
353703168,
3823362816,
2913840384,
4109693952,
2004317952,
3351758592,
2155905024,
2661195264
};
private static readonly uint[] SBOX4_4404 = new uint[256] {
1886388336,
741081132,
3014852787,
3233808576,
3840147684,
1465319511,
3941204202,
2930639022,
589496355,
1802174571,
1162149957,
2779054245,
3991732461,
1330577487,
488439837,
2459041938,
2256928902,
2947481775,
2088501372,
522125343,
1044250686,
3705405660,
1583218782,
185270283,
2795896998,
960036921,
3587506389,
1566376029,
3654877401,
1515847770,
1364262993,
1819017324,
2341142667,
2593783962,
4227531003,
2964324528,
1953759348,
724238379,
4042260720,
2223243396,
3755933919,
3419078859,
875823156,
1987444854,
1835860077,
2846425257,
3520135377,
67371012,
336855060,
976879674,
3739091166,
286326801,
842137650,
2627469468,
1397948499,
4075946226,
4278059262,
3486449871,
3284336835,
2054815866,
606339108,
3907518696,
1616904288,
1768489065,
2863268010,
2694840480,
2711683233,
1650589794,
1414791252,
505282590,
3772776672,
1684275300,
269484048,
0,
2745368739,
1970602101,
2324299914,
3873833190,
151584777,
3722248413,
2273771655,
2206400643,
3452764365,
2425356432,
1936916595,
4143317238,
2644312221,
3216965823,
1381105746,
3638034648,
3368550600,
3334865094,
2172715137,
1869545583,
320012307,
1667432547,
3924361449,
2812739751,
2677997727,
3166437564,
690552873,
4193845497,
791609391,
3031695540,
2021130360,
101056518,
3890675943,
1903231089,
3570663636,
2880110763,
2290614408,
2374828173,
1920073842,
3115909305,
4177002744,
2896953516,
909508662,
707395626,
1010565180,
4059103473,
1077936192,
3553820883,
3149594811,
1128464451,
353697813,
2913796269,
2004287607,
2155872384,
2189557890,
3974889708,
656867367,
3856990437,
2240086149,
892665909,
202113036,
1094778945,
4025417967,
2475884691,
421068825,
555810849,
235798542,
1313734734,
1701118053,
3183280317,
3099066552,
2408513679,
3958046955,
3469607118,
808452144,
1600061535,
3318022341,
437911578,
3789619425,
3402236106,
1195835463,
1027407933,
16842753,
3604349142,
1448476758,
1296891981,
218955789,
1717960806,
3435921612,
757923885,
303169554,
538968096,
2981167281,
2576941209,
1280049228,
3267494082,
2122186878,
84213765,
3082223799,
825294897,
387383319,
3621191895,
1482162264,
1633747041,
454754331,
471597084,
252641295,
370540566,
404226072,
572653602,
1145307204,
2998010034,
3048538293,
2442199185,
134742024,
2829582504,
4244373756,
1347420240,
3503292624,
2105344125,
2307457161,
2543255703,
1532690523,
2509570197,
4294902015,
3536978130,
3301179588,
1212678216,
4160159991,
3688562907,
50528259,
3671720154,
1061093439,
2492727444,
1549533276,
33685506,
1246363722,
858980403,
1734803559,
4092788979,
2139029631,
3806462178,
2610626715,
640024614,
926351415,
993722427,
2526412950,
1263206475,
3200123070,
774766638,
2037973113,
2357985420,
1852702830,
2391670926,
4126474485,
3065381046,
4261216509,
1499005017,
2560098456,
1785331818,
1178992710,
3132752058,
623181861,
1111621698,
2728525986,
4210688250,
117899271,
1431634005,
4008575214,
168427530,
1229520969,
1751646312,
943194168,
2762211492,
673710120,
2071658619,
3385393353,
3250651329,
3823304931,
4109631732,
3351707847,
2661154974
};
private static readonly uint[] SBOX2_0222 = new uint[256] {
14737632,
328965,
5789784,
14277081,
6776679,
5131854,
8487297,
13355979,
13224393,
723723,
11447982,
6974058,
14013909,
1579032,
6118749,
8553090,
4605510,
14671839,
14079702,
2565927,
9079434,
3289650,
4934475,
4342338,
14408667,
1842204,
10395294,
10263708,
3815994,
13290186,
2434341,
8092539,
855309,
7434609,
6250335,
2039583,
16316664,
14145495,
4079166,
10329501,
8158332,
6316128,
12171705,
12500670,
12369084,
9145227,
1447446,
3421236,
5066061,
12829635,
7500402,
9803157,
11250603,
9342606,
12237498,
8026746,
11776947,
131586,
11842740,
11382189,
10658466,
11316396,
14211288,
10132122,
1513239,
1710618,
3487029,
13421772,
16250871,
10066329,
6381921,
5921370,
15263976,
2368548,
5658198,
4210752,
14803425,
6513507,
592137,
3355443,
12566463,
10000536,
9934743,
8750469,
6842472,
16579836,
15527148,
657930,
14342874,
7303023,
5460819,
6447714,
10724259,
3026478,
526344,
11513775,
2631720,
11579568,
7631988,
12763842,
12434877,
3552822,
2236962,
3684408,
6579300,
1973790,
3750201,
2894892,
10921638,
3158064,
15066597,
4473924,
16645629,
8947848,
10461087,
6645093,
8882055,
7039851,
16053492,
2302755,
4737096,
1052688,
13750737,
5329233,
12632256,
16382457,
13816530,
10526880,
5592405,
10592673,
4276545,
16448250,
4408131,
1250067,
12895428,
3092271,
11053224,
11974326,
3947580,
2829099,
12698049,
16777215,
13158600,
10855845,
2105376,
9013641,
0,
9474192,
4671303,
15724527,
15395562,
12040119,
1381653,
394758,
13487565,
11908533,
1184274,
8289918,
12303291,
2697513,
986895,
12105912,
460551,
263172,
10197915,
9737364,
2171169,
6710886,
15132390,
13553358,
15592941,
15198183,
3881787,
16711422,
8355711,
12961221,
10790052,
3618615,
11645361,
5000268,
9539985,
7237230,
9276813,
7763574,
197379,
2960685,
14606046,
9868950,
2500134,
8224125,
13027014,
6052956,
13882323,
15921906,
5197647,
1644825,
4144959,
14474460,
7960953,
1907997,
5395026,
15461355,
15987699,
7171437,
6184542,
16514043,
6908265,
11711154,
15790320,
3223857,
789516,
13948116,
13619151,
9211020,
14869218,
7697781,
11119017,
4868682,
5723991,
8684676,
1118481,
4539717,
1776411,
16119285,
15000804,
921102,
7566195,
11184810,
15856113,
14540253,
5855577,
1315860,
7105644,
9605778,
5526612,
13684944,
7895160,
7368816,
14935011,
4802889,
8421504,
5263440,
10987431,
16185078,
7829367,
9671571,
8816262,
8618883,
2763306,
13092807,
5987163,
15329769,
15658734,
9408399,
65793,
4013373
};
private static readonly uint[] SBOX3_3033 = new uint[256] {
939538488,
1090535745,
369104406,
1979741814,
3640711641,
2466288531,
1610637408,
4060148466,
1912631922,
3254829762,
2868947883,
2583730842,
1962964341,
100664838,
1459640151,
2684395680,
2432733585,
4144035831,
3036722613,
3372272073,
2717950626,
2348846220,
3523269330,
2415956112,
4127258358,
117442311,
2801837991,
654321447,
2382401166,
2986390194,
1224755529,
3724599006,
1124090691,
1543527516,
3607156695,
3338717127,
1040203326,
4110480885,
2399178639,
1728079719,
520101663,
402659352,
1845522030,
2936057775,
788541231,
3791708898,
2231403909,
218107149,
1392530259,
4026593520,
2617285788,
1694524773,
3925928682,
2734728099,
2919280302,
2650840734,
3959483628,
2147516544,
754986285,
1795189611,
2818615464,
721431339,
905983542,
2785060518,
3305162181,
2248181382,
1291865421,
855651123,
4244700669,
1711302246,
1476417624,
2516620950,
973093434,
150997257,
2499843477,
268439568,
2013296760,
3623934168,
1107313218,
3422604492,
4009816047,
637543974,
3842041317,
1627414881,
436214298,
1056980799,
989870907,
2181071490,
3053500086,
3674266587,
3556824276,
2550175896,
3892373736,
2332068747,
33554946,
3942706155,
167774730,
738208812,
486546717,
2952835248,
1862299503,
2365623693,
2281736328,
234884622,
419436825,
2264958855,
1308642894,
184552203,
2835392937,
201329676,
2030074233,
285217041,
2130739071,
570434082,
3875596263,
1493195097,
3774931425,
3657489114,
1023425853,
3355494600,
301994514,
67109892,
1946186868,
1409307732,
805318704,
2113961598,
3019945140,
671098920,
1426085205,
1744857192,
1342197840,
3187719870,
3489714384,
3288384708,
822096177,
3405827019,
704653866,
2902502829,
251662095,
3389049546,
1879076976,
4278255615,
838873650,
1761634665,
134219784,
1644192354,
0,
603989028,
3506491857,
4211145723,
3120609978,
3976261101,
1157645637,
2164294017,
1929409395,
1828744557,
2214626436,
2667618207,
3993038574,
1241533002,
3271607235,
771763758,
3238052289,
16777473,
3858818790,
620766501,
1207978056,
2566953369,
3103832505,
3003167667,
2063629179,
4177590777,
3456159438,
3204497343,
3741376479,
1895854449,
687876393,
3439381965,
1811967084,
318771987,
1677747300,
2600508315,
1660969827,
2634063261,
3221274816,
1258310475,
3070277559,
2768283045,
2298513801,
1593859935,
2969612721,
385881879,
4093703412,
3154164924,
3540046803,
1174423110,
3472936911,
922761015,
1577082462,
1191200583,
2483066004,
4194368250,
4227923196,
1526750043,
2533398423,
4261478142,
1509972570,
2885725356,
1006648380,
1275087948,
50332419,
889206069,
4076925939,
587211555,
3087055032,
1560304989,
1778412138,
2449511058,
3573601749,
553656609,
1140868164,
1358975313,
3321939654,
2097184125,
956315961,
2197848963,
3691044060,
2852170410,
2080406652,
1996519287,
1442862678,
83887365,
452991771,
2751505572,
352326933,
872428596,
503324190,
469769244,
4160813304,
1375752786,
536879136,
335549460,
3909151209,
3170942397,
3707821533,
3825263844,
2701173153,
3758153952,
2315291274,
4043370993,
3590379222,
2046851706,
3137387451,
3808486371,
1073758272,
1325420367
};
public virtual string AlgorithmName => "Camellia";
private static uint rightRotate(uint x, int s)
{
return (x >> s) + (x << 32 - s);
}
private static uint leftRotate(uint x, int s)
{
return (x << s) + (x >> 32 - s);
}
private static void roldq(int rot, uint[] ki, int ioff, uint[] ko, int ooff)
{
ko[ooff] = ((ki[ioff] << rot) | (ki[1 + ioff] >> 32 - rot));
ko[1 + ooff] = ((ki[1 + ioff] << rot) | (ki[2 + ioff] >> 32 - rot));
ko[2 + ooff] = ((ki[2 + ioff] << rot) | (ki[3 + ioff] >> 32 - rot));
ko[3 + ooff] = ((ki[3 + ioff] << rot) | (ki[ioff] >> 32 - rot));
ki[ioff] = ko[ooff];
ki[1 + ioff] = ko[1 + ooff];
ki[2 + ioff] = ko[2 + ooff];
ki[3 + ioff] = ko[3 + ooff];
}
private static void decroldq(int rot, uint[] ki, int ioff, uint[] ko, int ooff)
{
ko[2 + ooff] = ((ki[ioff] << rot) | (ki[1 + ioff] >> 32 - rot));
ko[3 + ooff] = ((ki[1 + ioff] << rot) | (ki[2 + ioff] >> 32 - rot));
ko[ooff] = ((ki[2 + ioff] << rot) | (ki[3 + ioff] >> 32 - rot));
ko[1 + ooff] = ((ki[3 + ioff] << rot) | (ki[ioff] >> 32 - rot));
ki[ioff] = ko[2 + ooff];
ki[1 + ioff] = ko[3 + ooff];
ki[2 + ioff] = ko[ooff];
ki[3 + ioff] = ko[1 + ooff];
}
private static void roldqo32(int rot, uint[] ki, int ioff, uint[] ko, int ooff)
{
ko[ooff] = ((ki[1 + ioff] << rot - 32) | (ki[2 + ioff] >> 64 - rot));
ko[1 + ooff] = ((ki[2 + ioff] << rot - 32) | (ki[3 + ioff] >> 64 - rot));
ko[2 + ooff] = ((ki[3 + ioff] << rot - 32) | (ki[ioff] >> 64 - rot));
ko[3 + ooff] = ((ki[ioff] << rot - 32) | (ki[1 + ioff] >> 64 - rot));
ki[ioff] = ko[ooff];
ki[1 + ioff] = ko[1 + ooff];
ki[2 + ioff] = ko[2 + ooff];
ki[3 + ioff] = ko[3 + ooff];
}
private static void decroldqo32(int rot, uint[] ki, int ioff, uint[] ko, int ooff)
{
ko[2 + ooff] = ((ki[1 + ioff] << rot - 32) | (ki[2 + ioff] >> 64 - rot));
ko[3 + ooff] = ((ki[2 + ioff] << rot - 32) | (ki[3 + ioff] >> 64 - rot));
ko[ooff] = ((ki[3 + ioff] << rot - 32) | (ki[ioff] >> 64 - rot));
ko[1 + ooff] = ((ki[ioff] << rot - 32) | (ki[1 + ioff] >> 64 - rot));
ki[ioff] = ko[2 + ooff];
ki[1 + ioff] = ko[3 + ooff];
ki[2 + ioff] = ko[ooff];
ki[3 + ioff] = ko[1 + ooff];
}
private static void camelliaF2(uint[] s, uint[] skey, int keyoff)
{
uint num = s[0] ^ skey[keyoff];
uint num2 = SBOX4_4404[(byte)num];
num2 ^= SBOX3_3033[(byte)(num >> 8)];
num2 ^= SBOX2_0222[(byte)(num >> 16)];
num2 ^= SBOX1_1110[(byte)(num >> 24)];
uint num3 = s[1] ^ skey[1 + keyoff];
uint num4 = SBOX1_1110[(byte)num3];
num4 ^= SBOX4_4404[(byte)(num3 >> 8)];
num4 ^= SBOX3_3033[(byte)(num3 >> 16)];
num4 ^= SBOX2_0222[(byte)(num3 >> 24)];
s[2] ^= (num2 ^ num4);
s[3] ^= (num2 ^ num4 ^ rightRotate(num2, 8));
num = (s[2] ^ skey[2 + keyoff]);
num2 = SBOX4_4404[(byte)num];
num2 ^= SBOX3_3033[(byte)(num >> 8)];
num2 ^= SBOX2_0222[(byte)(num >> 16)];
num2 ^= SBOX1_1110[(byte)(num >> 24)];
num3 = (s[3] ^ skey[3 + keyoff]);
num4 = SBOX1_1110[(byte)num3];
num4 ^= SBOX4_4404[(byte)(num3 >> 8)];
num4 ^= SBOX3_3033[(byte)(num3 >> 16)];
num4 ^= SBOX2_0222[(byte)(num3 >> 24)];
s[0] ^= (num2 ^ num4);
s[1] ^= (num2 ^ num4 ^ rightRotate(num2, 8));
}
private static void camelliaFLs(uint[] s, uint[] fkey, int keyoff)
{
s[1] ^= leftRotate(s[0] & fkey[keyoff], 1);
s[0] ^= (fkey[1 + keyoff] | s[1]);
s[2] ^= (fkey[3 + keyoff] | s[3]);
s[3] ^= leftRotate(fkey[2 + keyoff] & s[2], 1);
}
private void setKey(bool forEncryption, byte[] key)
{
uint[] array = new uint[8];
uint[] array2 = new uint[4];
uint[] array3 = new uint[4];
uint[] array4 = new uint[4];
switch (key.LongLength) {
case 16:
_keyIs128 = true;
Pack.BE_To_UInt32(key, 0, array, 0, 4);
array[4] = (array[5] = (array[6] = (array[7] = 0)));
break;
case 24:
Pack.BE_To_UInt32(key, 0, array, 0, 6);
array[6] = ~array[4];
array[7] = ~array[5];
_keyIs128 = false;
break;
case 32:
Pack.BE_To_UInt32(key, 0, array, 0, 8);
_keyIs128 = false;
break;
default:
throw new ArgumentException("key sizes are only 16/24/32 bytes.");
}
for (int i = 0; i < 4; i++) {
array2[i] = (array[i] ^ array[i + 4]);
}
camelliaF2(array2, SIGMA, 0);
for (int j = 0; j < 4; j++) {
array2[j] ^= array[j];
}
camelliaF2(array2, SIGMA, 4);
if (_keyIs128) {
if (forEncryption) {
kw[0] = array[0];
kw[1] = array[1];
kw[2] = array[2];
kw[3] = array[3];
roldq(15, array, 0, subkey, 4);
roldq(30, array, 0, subkey, 12);
roldq(15, array, 0, array4, 0);
subkey[18] = array4[2];
subkey[19] = array4[3];
roldq(17, array, 0, ke, 4);
roldq(17, array, 0, subkey, 24);
roldq(17, array, 0, subkey, 32);
subkey[0] = array2[0];
subkey[1] = array2[1];
subkey[2] = array2[2];
subkey[3] = array2[3];
roldq(15, array2, 0, subkey, 8);
roldq(15, array2, 0, ke, 0);
roldq(15, array2, 0, array4, 0);
subkey[16] = array4[0];
subkey[17] = array4[1];
roldq(15, array2, 0, subkey, 20);
roldqo32(34, array2, 0, subkey, 28);
roldq(17, array2, 0, kw, 4);
} else {
kw[4] = array[0];
kw[5] = array[1];
kw[6] = array[2];
kw[7] = array[3];
decroldq(15, array, 0, subkey, 28);
decroldq(30, array, 0, subkey, 20);
decroldq(15, array, 0, array4, 0);
subkey[16] = array4[0];
subkey[17] = array4[1];
decroldq(17, array, 0, ke, 0);
decroldq(17, array, 0, subkey, 8);
decroldq(17, array, 0, subkey, 0);
subkey[34] = array2[0];
subkey[35] = array2[1];
subkey[32] = array2[2];
subkey[33] = array2[3];
decroldq(15, array2, 0, subkey, 24);
decroldq(15, array2, 0, ke, 4);
decroldq(15, array2, 0, array4, 0);
subkey[18] = array4[2];
subkey[19] = array4[3];
decroldq(15, array2, 0, subkey, 12);
decroldqo32(34, array2, 0, subkey, 4);
roldq(17, array2, 0, kw, 0);
}
} else {
for (int k = 0; k < 4; k++) {
array3[k] = (array2[k] ^ array[k + 4]);
}
camelliaF2(array3, SIGMA, 8);
if (forEncryption) {
kw[0] = array[0];
kw[1] = array[1];
kw[2] = array[2];
kw[3] = array[3];
roldqo32(45, array, 0, subkey, 16);
roldq(15, array, 0, ke, 4);
roldq(17, array, 0, subkey, 32);
roldqo32(34, array, 0, subkey, 44);
roldq(15, array, 4, subkey, 4);
roldq(15, array, 4, ke, 0);
roldq(30, array, 4, subkey, 24);
roldqo32(34, array, 4, subkey, 36);
roldq(15, array2, 0, subkey, 8);
roldq(30, array2, 0, subkey, 20);
ke[8] = array2[1];
ke[9] = array2[2];
ke[10] = array2[3];
ke[11] = array2[0];
roldqo32(49, array2, 0, subkey, 40);
subkey[0] = array3[0];
subkey[1] = array3[1];
subkey[2] = array3[2];
subkey[3] = array3[3];
roldq(30, array3, 0, subkey, 12);
roldq(30, array3, 0, subkey, 28);
roldqo32(51, array3, 0, kw, 4);
} else {
kw[4] = array[0];
kw[5] = array[1];
kw[6] = array[2];
kw[7] = array[3];
decroldqo32(45, array, 0, subkey, 28);
decroldq(15, array, 0, ke, 4);
decroldq(17, array, 0, subkey, 12);
decroldqo32(34, array, 0, subkey, 0);
decroldq(15, array, 4, subkey, 40);
decroldq(15, array, 4, ke, 8);
decroldq(30, array, 4, subkey, 20);
decroldqo32(34, array, 4, subkey, 8);
decroldq(15, array2, 0, subkey, 36);
decroldq(30, array2, 0, subkey, 24);
ke[2] = array2[1];
ke[3] = array2[2];
ke[0] = array2[3];
ke[1] = array2[0];
decroldqo32(49, array2, 0, subkey, 4);
subkey[46] = array3[0];
subkey[47] = array3[1];
subkey[44] = array3[2];
subkey[45] = array3[3];
decroldq(30, array3, 0, subkey, 32);
decroldq(30, array3, 0, subkey, 16);
roldqo32(51, array3, 0, kw, 0);
}
}
}
private int ProcessBlock128(ReadOnlySpan<byte> input, Span<byte> output)
{
uint[] array = new uint[4];
Pack.BE_To_UInt32(input, array);
array[0] ^= kw[0];
array[1] ^= kw[1];
array[2] ^= kw[2];
array[3] ^= kw[3];
camelliaF2(array, subkey, 0);
camelliaF2(array, subkey, 4);
camelliaF2(array, subkey, 8);
camelliaFLs(array, ke, 0);
camelliaF2(array, subkey, 12);
camelliaF2(array, subkey, 16);
camelliaF2(array, subkey, 20);
camelliaFLs(array, ke, 4);
camelliaF2(array, subkey, 24);
camelliaF2(array, subkey, 28);
camelliaF2(array, subkey, 32);
Pack.UInt32_To_BE(array[2] ^ kw[4], output);
Pack.UInt32_To_BE(array[3] ^ kw[5], output.Slice(4, output.Length - 4));
Pack.UInt32_To_BE(array[0] ^ kw[6], output.Slice(8, output.Length - 8));
Pack.UInt32_To_BE(array[1] ^ kw[7], output.Slice(12, output.Length - 12));
return 16;
}
private int ProcessBlock192or256(ReadOnlySpan<byte> input, Span<byte> output)
{
uint[] array = new uint[4];
Pack.BE_To_UInt32(input, array);
array[0] ^= kw[0];
array[1] ^= kw[1];
array[2] ^= kw[2];
array[3] ^= kw[3];
camelliaF2(array, subkey, 0);
camelliaF2(array, subkey, 4);
camelliaF2(array, subkey, 8);
camelliaFLs(array, ke, 0);
camelliaF2(array, subkey, 12);
camelliaF2(array, subkey, 16);
camelliaF2(array, subkey, 20);
camelliaFLs(array, ke, 4);
camelliaF2(array, subkey, 24);
camelliaF2(array, subkey, 28);
camelliaF2(array, subkey, 32);
camelliaFLs(array, ke, 8);
camelliaF2(array, subkey, 36);
camelliaF2(array, subkey, 40);
camelliaF2(array, subkey, 44);
Pack.UInt32_To_BE(array[2] ^ kw[4], output);
Pack.UInt32_To_BE(array[3] ^ kw[5], output.Slice(4, output.Length - 4));
Pack.UInt32_To_BE(array[0] ^ kw[6], output.Slice(8, output.Length - 8));
Pack.UInt32_To_BE(array[1] ^ kw[7], output.Slice(12, output.Length - 12));
return 16;
}
public virtual void Init(bool forEncryption, ICipherParameters parameters)
{
if (!(parameters is KeyParameter))
throw new ArgumentException("only simple KeyParameter expected.");
setKey(forEncryption, ((KeyParameter)parameters).GetKey());
initialised = true;
}
public virtual int GetBlockSize()
{
return 16;
}
public virtual int ProcessBlock(byte[] input, int inOff, byte[] output, int outOff)
{
if (!initialised)
throw new InvalidOperationException("Camellia engine not initialised");
Check.DataLength(input, inOff, 16, "input buffer too short");
Check.OutputLength(output, outOff, 16, "output buffer too short");
if (_keyIs128)
return ProcessBlock128(input.AsSpan(inOff), output.AsSpan(outOff));
return ProcessBlock192or256(input.AsSpan(inOff), output.AsSpan(outOff));
}
public virtual int ProcessBlock(ReadOnlySpan<byte> input, Span<byte> output)
{
if (!initialised)
throw new InvalidOperationException("Camellia engine not initialised");
Check.DataLength(input, 16, "input buffer too short");
Check.OutputLength(output, 16, "output buffer too short");
if (_keyIs128)
return ProcessBlock128(input, output);
return ProcessBlock192or256(input, output);
}
}
}