From 3201fb4d838f41895125761e7c8a7b2140f1c7f1 Mon Sep 17 00:00:00 2001 From: waterjuice Date: Mon, 11 Dec 2017 11:22:29 +1100 Subject: [PATCH] Version 2.1.0 * Changed implementation of AES to one which is almost 5 times as fast. The new implementation comes from LibTomCrypt. The newer implementation produces a larger binary size as a trade-off. * AES-CTR module now supports OpenMP and when compiled with OpenMP will run in parallel giving a much greater speed. * Changed interface for Initialisation functions for both AES and AES-CTR to be match RC4 (The context is first parameter not last) --- Exe/Linux/AesBlock | Bin 21680 -> 34320 bytes Exe/Linux/AesCtrOutput | Bin 22008 -> 39016 bytes Exe/MacOS/AesBlock | Bin 17556 -> 34052 bytes Exe/MacOS/AesCtrOutput | Bin 17868 -> 38492 bytes Exe/Windows/AesBlock.exe | Bin 11776 -> 30208 bytes Exe/Windows/AesCtrOutput.exe | Bin 13824 -> 32256 bytes ReadMe.md | 17 +- lib/CryptLib_Aes.c | 1335 ++++++++++++------- lib/CryptLib_Aes.h | 56 +- lib/CryptLib_AesCtr.c | 86 +- lib/CryptLib_AesCtr.h | 10 +- lib/CryptLib_Md5.c | 20 +- lib/CryptLib_Md5.h | 12 +- lib/CryptLib_Rc4.c | 22 +- lib/CryptLib_Rc4.h | 22 +- lib/CryptLib_Sha1.c | 12 +- lib/CryptLib_Sha1.h | 12 +- lib/CryptLib_Sha256.c | 22 +- lib/CryptLib_Sha256.h | 18 +- lib/CryptLib_Sha512.c | 12 +- lib/CryptLib_Sha512.h | 18 +- projects/AesBlock/AesBlock.c | 6 +- projects/AesCtrOutput/AesCtrOutput.c | 4 +- projects/CryptLibTest/CryptLibTest_Aes.c | 6 +- projects/CryptLibTest/CryptLibTest_AesCtr.c | 78 +- 25 files changed, 1144 insertions(+), 624 deletions(-) diff --git a/Exe/Linux/AesBlock b/Exe/Linux/AesBlock index de58c8ab91e897b2edb8ba69140a3325d28d3390..2e7029a229d0a45c3b6dd92c493d3d898582102e 100644 GIT binary patch literal 34320 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 L>62|`_Wl1aE88NK literal 21680 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%0AMEo_znQ91pt2ofKmW(7y#@80P_LB zivVC20C*Ard;|cN1Ax~6z`Fq82mm+$04@T6vjAW{04M|izW{*m0l@13;C%p400341 zfNTKZ0RT?}fENJ3Q~;0#0MY=!XaF!60Q3O>-2p%s0MHr$+zkM32LLSrKqvsX5dioD zfSLf{M*y$~0DKDoHUof@0N@+|_#FTg1As*U;8_5W4*+riz?T5vV*v0D09XtFx&eTm z0AK(B7zzMJ0)U4Azyts=830%TKve*669A|S0PX|;w*r6;03ZqgJP!b#0RXuGU^)Q! z1^_Gr080SC8vtMj0N4!xRsw(x0N@M&C6>;nLQ0e~_9a2f!70{}h&0IvgpcL2Z>0ALmX zm`YLfMWpQ4*+lq0Q?OAJ_Z0Q0KnS-;0*vU69D7^fENM4Qvjd_0H_84LIJ={ z0N@?~5CZ@r06;SUFaiLi1Axf@APWEt1ON{JfCKS0stlgfB^ttFaYQU z06GJJ>Hr`R09*$EZUz8%1Ar(1&;$V70RTP%0AB%s_W;0~0AL0H$OQn40Kn4#;Aa4^ z69B9R09ygTQ2)fV}`<2LSjM0IUZ9 zhXKGr0B{@tTmS&00l-55;86fD9su+M01pCycmQAr09F9t4*==`fG_~i5dgFW0Ji{u z<^UiV0Qdob>j6Lm0MH%)v;hFO0)UnPAPE4Z0Dx%#AQJ%e1^~kVKz9Jp4FLQK0JZ~w zwE$of04N3k2LQkc08kD9J_P`u1Aq?zz-s^?8vx`3fad|g0sx@*pYT6~@V_D9e;vaA z_Jsd!3I8Jq|L-9DA5Zu{jqpE}@P7p1zk~3g#T|6{(nmN{{`XyZo>Z`2>;g+{%;`s|AX-V zDB*uO;s0^M|Mv+0-yr;7M)?0Z;r}y)|1S~#&msJuPWa!E@V^b=e-pz0W`zF%g#Wb& z{~Hnh*CzbGkMKW^@P82D|NVsjnS}q368@(X{wEUtzfbu88sYy(g#RlD|K}6_zd-o! zA^e|3`2QQ>|M!Idg@pg#5&j<_{69?i|2N_PS;GGwg#TR#|N9XBI|=`@2>%};{7)hL zA5HjwH{pK_;r}g!|1Amss}TOzB>caT@c#zF|A~bElL`MHBK%Jx{O?KlA4~Y(m+*fm z;eS=a{~*Hu`h@>=3IFdQ{Es61zm@R6IpP1ag#QZ(|DPcI&msK(fbf4Y;s3{k|6dXQ zA0+%QCj37~_(AM{QsKp{}aOh=Lr875dO~~{Ldr&-%j|y zm+*fJ;s0vF{}RIgKMDU&6aJqk{C}SCe;(ogOv3+M!v9wZ|CbQ{e?$1cl<@x$;s1WZ z|1*UDWrY7b2>*X2{NGCWzmo9(VZwhG;r}SY|1pIBoeBRF2>%}>{O?WpUxV;JknsO{ z!v8SB|5k+moe2LU3ID?h|Bn#35KYr_A#2>+WB{@+gcKb7!5gYbVi;eQ(8 zzn$>EJK_Ie!vBGU|Lq9>I}rZgN%-HG@ZU=K???E59pV2?g#XexG@P8BG|F?wye-ZxwPWXS4@c$pe|F;PL-y!_}lJNgC!v95t z|4$MAy9xjEmA5LtSAMCyMftRHXXRkZos}agM^S%6*j6D4$Zkth`itqjGrVeagk81t?Efo}-*wIi>Um<>|_0 zl&dKRmp&maKslsxX6XgWx1=K|CsZD+yj%ID@_6OW%43zYNoP>rtQ<-Cl5%h5y~??j zw@SlMKBt^idAo8yEkq#nFL%M_VROOt?;gwq|*HzA|d{a5L@>A&z z%JY?zOLvflqnuUwxilE*2+C`fe@cr{E-U><`h;>{X&BO2l)p+Jl8zy5NP3TQaOn=x zIF!drACcxH9YC6r@^|S;%4emuNY9Zzqr6?YxHJ!GOVS;bcPr0V&MQ4c`MdNO<;v2a zl#feikbWe+L%Nr8f9Xon7Nl)S=aP;iO-h=H@^DkXk^UnsMLLDFF6j@_i=>lDt5QBM z{Y83*G!p3v(m|BJOaG7tAZ<#zl5`DeUCQC5ZAgDm-Y@M!+LbgK=}gj8q#H?NlP)IR zPMVH%4(UG9AEcp4TabPvT~7Lvv?=Lr(($ANDQ{JNul!PZi}GpZ&dR}*J1a+0j;!2F zIh%4tBQ9h-7S$V1QM&#Z%Ic`PN+OsdAIUQy3@^f`Vl|L&7R<5o5SvjI|TfP6vua%=Jmz3tB98Ni*bOh-#%4e15 zN~4fQqx@5vi1ZZYhNSl>2bb<3jYE07^bu)J(gCC?DSwxqq<-F2El)p=lQLZcvO8K~S2I)uAJEVIl_m{3DZ9&?WbS~*Q(xjxBC=WOF z8|gpNQlwKz>yrK;y+}Hlv?}HE(qE)^NF$M+ARR>cyYvrf0Me$UD@oUo)}Ykn&dL z_sTDowXdW%IB1mDsNZr zr`%onx$;ZpyvoOwgG(on7NFcp`I&M~<$TKXrH4pQkRG6%R{67XVCCA%pOqsjx7GWv z{8~Axa!F|}%Hfm~N=J|`qkL9*t~3g1G|E4viAYaTKCV1fx`wnFX*$Ynl_x9bmA)gb zM>>u2dFct#MU=lw!;uamO+&ha@>J!V%Hfq;D%Vxct9(;Aw(?Wy4a)PClaqGTmWHF8 zRr$Fz80iSgYn6XWi%~8s{YUzQa$ji}(pZ$gN*|JrA#F%{k8*J74$?T3$4eiP<|G|J znv(K&=}F3GrL{=Ukv^lmUAee44{1x%9h7$~&sWYXJw*At^cdyJ(x8-&OJ|UNB)vnr zmvVpUO41gjZAs^njw4M=6dWSR;=?T(7 zl)p>=kOm-aO1hGC4QXA<;iYXze^A~p?Lyj>G#cql(p01yNn?{PCf!b&j&u&`KGGkg zp-Eeiek5H^`jWIM>21>SqyzEDjl`$olki9I6Zlv>9oI;ZC|tiWj>hlAFXBJq@8J{i zjrilZp5I6DbNKyuH(VV>-p6<1ui_dQ@^{tSLQuHP!}#n0mEPuCiM z13!SP)8hpECp;RjhwFFGb@*+#eliZjpT(=-&*RnbI(Rm|4?m1I!9T{caE+yQ8%+-VFZ(Z;2~r?}u;4Wg0ILj;lk=NB9HyL-;2A8@vPF9Z$dq z8npSwSJ=9z?tZofTsNZYp4Z1>)K+W+iXcdyNx#|&-Vy3eUM z-q_yyz=6MmjvwFm%!CQ=W&ZTjh`f%A(Ozka4~--$gsc3hUYYuBS&Kl!BZ zBh8xqcF!MwJUF3c%j*{8 z`{V7mUp?8U&#;THy_UT)Hnz$WbLQOp{?kw2^3_W(jd!$fe?0K?>5+TC`f5^PLBWSv zzx>j9wSs9#?GPsquWE5_~EF+E|+maw|P!MC@$?z+`2j~w~tcc-(>s|yz7 zZnoPaJKS)?GlSNw8F1pQw=O(BZQ8@#?!J5dlBA?B{v0-})txuqcyNAZ=E}vxhu^qx z`t+B#_v-c9W551tA9d@k{ioe=N5}W(&aLUr&7HlmYu9znjvX8O{qp5aJJqfG)|5Sa zzS{TTgV*0wv*!B~ckkZav8X6%V5?THo_F0<_vRWkp57fFA6%nqRYz(>#Pa<^hb|hn zYSq_i-+$lbuO&;?yg6b-hqs@4D*E;L^S^JmfB%WRDN}xE_2-{?UDmHpyT4t#UzUv< z=Qle)|D&WIet2<5&z|u`@4WNVr>Ut+&J7%Rvf8Or-!(pTXyb>;$)}!t_~C9PAAArR z78I2J!xvwa=1!j6J-u<`p&5~p?IRjC9CZB6H#66L`sso`Yu9eNt+@D=slWYJ{G!Ws z&n=A_J^R~z_a*-N_1Cp#=H*#uJn=-)-0|b5cE0DH32Q$4Z1cOLM$P@n;iy_AAmFUu znKKRRgoLbmEiv&SXPY)3{5@z;%C^rxzu~EwGoKq=Sa?^Hn{I0I`O7c=-2V694_{YS zcIPJx7v36EyY`MRQ&Qd;|MSn)JWoCu^VYn1Eec+Eq0_B5-(2tMS+h2Tmz2zk-@5hP z@&N;SPj1@ujfeN{4VW`~_WfnAyiz^el8vTHIXQYJFtW(xq=-=-+?bt}nlAe%JNaj|2cy0l*{x@CX1n0RYAVfOG)x zEdYoD0Db^qGyu3009*tBKLUXF0Kh~5un_<}4gfX)fJXtqIRJ1!0O$q)N&&$80AMEo zcohJA2moFL0Ivgp3;?ha04xIl{{Vnz0Kn}4pe+En7XX|E0Gk0oYXI;D05|{ujst)R z0N^J85Dft80f0aNunqv+1^`wAfG_~?EC8qi0Ga`pN0O0`O0s#0306YKy9s&TH0Khi@paTHt4geAWz+eFI9RSz{0R931?*f4H0H6y1 z=m7v?0Kg0Y5C;JM1_1s5;4uKu8vt|y0E+;?+W?>s0C)`m!~%dh0N`l=@Dc!M4**UB zfUf{R0RZ>~0NerqLIFTI05}N%b^w4a03a9uTn7M-001WdSO5U*0N@4yum%9U1puZ2 zfV%-e5&#$m0B!^TnE+ro0GJK{dI5l60l=*Q;0^#V7Xah}fUW@G7ywuf0O|sOJpkZA z08kSE>;?cu0H75BxC;Q(008j-peg`}002V)z$yUnJpfn&07d|SrvSiw0I(kbOaTCY z0)X`ZpdA1h2LSQ`zz+bRCjfW{0HgwdfdJqX05}8yk^#WO0N?`v5Cj0e005H#Kw|(9 z2>==bfHwiarvP9r04N3kzX1Rj0B8gN?gIc{1AsgL@B{!D4*>1~0G|PXQ2@XJ00IEO z82}Ih01^Q}8vrl}0DKMrW&(gh0B{okco_iv4gkskz(N2}8vvvLfS&=tlK@~I0C)ia z+zbF_0e}(!uoVCd002z^z+M0_8vwil06YMo764cQ01g6x&H!Kx0I&go=Kw$p0AK|G zO94QC0PrOMxE=tE1OQV3z$5_h2mm+%0LB7KyLuh z2>>ht0B-|;J^1=1_15`07(E~7y!5t0AvDy;Q(Md0O$n( zegy!x0)RUJz+3>33jn$TfMWn)IRK~&0QLZY2LV7$0I(YX6aj!%0N^eFPy+zO1AwXk zAOZjk1puo6!1n-P2>=)Y0G^8vtq05Amr{0RWo1Auk_U>pF*2LL|+fSv&09RQFD z00shpQvl!)07wP^4+DS?06-7`_yPb-1^|r#KqLTY2msy$0G|SYwE&v%A0B|z^m<0ez0KirNFaQ8F1ps>iz-$2U z3IOl`fLZ`x1pqh*06GJJF#x~@0G|T4SN}zj-AAQ#Li<=u|Kd5*yGp>SW8TQQ*0L28haA!g4wY(*dD9|+l2MU z9>L~et*|$-RoHFV-PkcK0h^E2#5!Z=u+>;kEC`FlUcp9TO|hS`2<&5QBK83GDi)88 z!}750SYs>$E5puUN!Uzm47L!v9@~k%jt#{&W5cjytN?o&OU1@x4y-r!4|Wv$9Qy@( z5UYoE#Rg$-VfolgSPnK9`w4pw6GLWWUt!;4HL$bTerzyS1zV1Ng2iD~v29p$>}G5Z zwh_A*vts^OA@(8mH5P#RVb@_#U}Lenu&1!vm<{WNjmCb(4q*$h6WDjyR;(2J6g!Az zV$WhrFc)?!_9yl})&`q_?Zf`Y+F`|5Lo5s1i=|=Ru;W;LYyx%@)(ra=^I+-NGHe7E zg1w7{Vc%d4unX8g>>lhsY%R6}n}TWd@ADX0#_pBaMQk#*1sj5$!Wv<}VQ*tGST0r# zTZctsA7OQ{Q0#uJ36_l=!JOD|tPl1W_6~L<_8Hb4tA(||4qy*si?C;~4cLp=U)W-- z2`SZ@=EnMA&tZw!4cMJnAT|yA0-J>G!fwZY$5ODm*hp*u zb_*7aJ&LK{y88F4f4TZCt3SQ^&Z`f$`p&D5wED=aZ?^hutFO5F8LMxz`V*@^x%w@u zkG=YktB<$(<*RS8`j4wWzWR!ree2b~T793@r&;}})n8uy($#NVefZVyTYa%L7J%-* zkE)-u`rNBexyB!;pT7DstFN~D;A?z>#sa7hx%$j&yny;!YaD_4gsUIC`rWI4x%%;| z@4Wi4tIxK^8K~d9`bew4wEEtw-@E$UtKYiDFsMJb`lPGhzWRQv@4ouytADxrysJOH z`rvDvfW`u-Z?*botIxUme5;?o#zSa4fyM)T+N=M(`iQGd&rz?i!<@F&gTBt}ziBPoe(!>Zh)84H}!FF&*mLu72|B z^RDq78tb8P8tTul@dO$dq5k_C!=Z5y8q=V02kNJ;KIiJgufFB#>#jcU>Tj+-_UfOm z@doPWuRi%2cc3vG>a(u?`5J?vaRlnuuKwqA|E;aQ>>B@}@d@htt}zT6W1;@*8Xux@ z3>q7v@gC}fuW<(&08XuuCCmIK!F(vB1ukj@6&#ti+8qY!Z-|y6KUw!d4=0Rgi zH10tC?$ys!^54hEe@`O+ok#w&A^&}X z{O3gei$ngq4f(Gh^51^szZa1IvXK9NNB+AT`7Z(aFBSQ38uH(1>)FA^#0V{%ei=*B1HjSLDA>k^de*{(BwyZzA&FGUUHU zk^lN4|NVyi_aO4$b;y5jBLAshhXwhs5cw|_`R@u{jF)XD=!*U&u7-HMV2Al&OB0TKsx>c`Vc3 zZ%~iv(znXXCo?T#`Zm+hcgoAln2!Iryu5t?4HmFo(=TYBX(-ceOv9P#Zv)R|8WqTT ztgd%r@q4(h#cy(`UxVOkL3918g{oW~wYG7rclfr^5|$qj7ZN@@&=%5kW)*u#l)Gv| zNN@jdYJ@~lVhagp3%2YW5@f5XTE=g5>X@~d{pE74)K0$InH|8^Gu4i}O1F@?wfqOv zFdDE`Za}{gZpMo^j@Naqs6R*bpA6_65}qH}Ii%@q9mmY7wvhJjYW9%1egQoKYJ{}6 z8Arr6myXDxBQmZR#}WHVdHEEUP1A3Qtto$-@&hXT_c-mBj!SYP zSIf&^Rehi7TF<7ul=8mZdkg347ZB%P!*_+6Q?!KjQ9Lv1n5O;C_U{rBHdEKf9q0@R zvl-V@>o8r9Uwzv*VOrsOa9@1aqsyi1(Jy3MkpJl`UJmaK(s?)MxI*77FCVBbVD>BA z=dQZX0Xcr&Grx2}yKq5OKb87XAM%HbefQ_e&q=_9fRLsfl{x5u(|HuCFT~!T=HHxnHO>g&2+xn(meba%y=_ucH zqHj9WH+|MOebYBB@J-kHrkC%xTbC|(g*P2AA}h_672YP2e}>(nZI-bVJuSLzWK`?O zHqE@{;jN;g+eWpG>Tr1z|FImv)7;)a_6p_xmi|{P53sndSRQ!kd92u208gj+99Ax` zdg*zsTwcv`rTZMf({DZ>mA9{MF`u)_a`}yx>?@Ynx9HyrUv2@$7|Y6~ z!b+g!czNYgFGu}Er^}9C{PgGgFRl?=sfswN@}kSiBYowUb6vWaALBmF<1~4$VO@S# zxSkLD+A+T;STt-VpMDIXzWlztLHU)=>r={goa24pGlteo*~+VIzr(lv@ZebH7(gFj zOpJlPS8D$>tNnQ1idx5dHw^Sn&Y9&+E0^oS8{0=!E)V2_80F0?msdB-6DpTm&GO!r z%j=ot_R8fA%yLKN@>_i6i+#u0)Z(?<&F#lj-u@1=ynp5LNV9xsc$`QXasZO!te z%H?;Neqn-cc!xxm-(R1$Op80*g(J0q3Rkpp9 zhgU8#mh}5kIDc~Ba?YGL+6l3g-X3dgXT}-&FRl7b>vC&kl(T)kSYwr;{WI6%D%;yB z4`sh5AI$dd^R*LI$J>ta8wV=~T&0}}zU^1m^=@zchQao0jN|{$?~BK;($2G2DgXE? zxL7{%CoX?YkJ|A(q~aVvP#M zZzs(4q`bEOjh5W(;YPXn@qo%Jd~fvwYApW@?Dq@LX`?jPPTMa+O*=o4&gZaCMPC2k|)~} zU5S=18B@l)5>iGuz1y(XJ2N;vBhtxnIY*^MMpfF1P5O_`jM7JpKBD!}%F;i%wUb#s zS;Z&o_-tj#7@3}C=^sa797S<#6351NmhCLtS+=vB)S7eX+Sk@2&KcL!&gJu7OLM-` z86{bq_WOI+seVZ(kmQ}c24VYX~uQro+M?aJI5rZC2@V7@x7>*l#=Gm%1lnG zu$g(espz`_6>p}V2$oYa(?@pb;LOY%nV2@}-?MG!yUgDIqvKoXm+b0i{0E!(w4~(8 zR34F;={q@H3<}0)q@=k<>3aU#R7_-RU;TftjCoU>-6uNx`riL8sfn4H#>>y+V?N$` zu1r8wda8`4VtisoVrpu#E|e}LSucO8Cv(a;SK8Wk~79zBGb}c$&t3s z@hx15qkT)G)3PE*WTm7gwMa>_L~3bFV&)i2WYUy0+Vf6b8QwJ$lQS|?cw3Fld<#z2 zWhAF2s)BEBe5%V5XQ|M(M`m9GN`EN2M`IG-57!t9tR|tzphT zG?LBOP2#weksL$1OU+ZFcO#NJVu=Kl4#;t627SEs&nfqVpA8Tx| z&{tp{e-)$jUmeZ2X#BA#X<}ym<^Hk8s^z|drMfs+Ra~=XoJquM*g!t{O1xCx)ZxbX z4%F1$yjy$QFy}RW5SQj)vA(JIZ1WwcdAw#b zmoL9`S$#8pEAnml^vz~X@6_C{S^C;#^-cZA)x^6+b#p`C^z!q6$5;Q-{c93yY?#sjK5R_kT%mnnodZ`Tj0nKFBtDcFp>x zt`_90U#iA2^Z7RGo6o^Q)>YiUslSyyW>mZC{>^s&x~#q>d$_k^cBP4TflsrZIW42C z;{MJ2FFV^?#XL^$(!cf1<%`UyE%W@%{9L4S3?YOx6BWfg7_2=h67jAYyep)|-)PAe5M z1)nfR7%ilOl7^p;D8abQ8WN=P1}+~@ z8qi&8pe7Uq7bB1y)iv)Hh62{Igb8bTJsLPPcB)p_89051!CXv=iXh~gT zGbnd1X=&z^kWf)wSymqM7EdfL=}+I>pBkWfi*G{ht?bXn?u6M{KehmppUrrTT+^6I zJ$wbHjc9DlrHIiuUchjh@F>UIM-snP_z`fr&fQweAoYa|mNIUIzFL+b8kJ{Wt|WSY z*GFbi5}o4IygW&Cv+q$}X%anoeDWpHll!NdL^sC_(laxOj)wJLwn%uXR;U5!DP3>FB@WX_Y+546<{2<}fZ+qlp}RWPVLD0;zuN_{3WY4c2vPl#WOA~sUv)Xqm3PrW)ZhY5*mN<|W)Yy+0svnle9gWXH zEXDi@HTFw;9e5TOi(@)SToAj4O5K|(V5`lbBXYJ{;f|Hs@A=mpYX9+Os$P8C z=ZS>W-S>NB#p6hu^3t(NefJ%zeo&1bIx(}Ra!0ody3`##&)!I2$J%tX`V9!2UM!AL z1YzSn2;@2Hgrxv#^qf=G-@kj*Myd&g?~nzXDI;+J%trkdY^A6jsP87qpQEli&J^@q zv_XNYpHO?^x2l%y>h6n?Vg1^&O>N>BVZm0T{FPr_ezQvu+K0@6V7wVlSg<{9F-VqE ztfb8@Oz>*-R-rxZ$U4aND?3R7iQWZ$_d;f%J`}Hh=_~@aQa>}hQh!y|Kb4N5SGtnI zQ*jqc-BR~<#houK))jYN{ISnq&a+2y*T!z^U3nq%?rY`fc8j8atWMt2)+Bc24Apl< z555yUEU&zfcF%tOMD(IXtG4Gw@>Knu`0WthMBX~Gb1jdz74AH^QK69k7IHfggnB&s zqD9tf(gbDzx7e0^--hsQQrEf(fTNBebi`u)M$OwXnoXZeU!C6z5$CS^ubCBK(l}F zdZnS0_ANpN$LC;x?3)cdKIK9pu{O!y=qvj3R7Z3fyE^4zs-xJkhT7b@-l!0xX%ADO zs=nT6-N$Or;i=ksYKMw2?Kxbct*6!)$arl%waGx-+Inh>fsEGHQ;QgKJO^?GKJ9sG zl^T1VG;8arrF}0BCC9?fMlT$wuRISuY$L4>76{o|RaRsM5wg9(Y!Gs^s_e)uM9A?5b3n+|s&XO|h>+_I=7QkVs&XTv ziQx1G$ryQBm9srt>{8N1Z$Q+_LolUI2Z%@OG@^u%BCXSi5<*;Brx7KD6l$GDln|1qby7^IIw20N zlcFX5Z+ z-d$j3S&@~`vTT$EAD5X~He?NDS$4{Tr*AN`?8qu$S!tAovU1FG7QB8E zzGT%%M;7g7qUSRx3%;k&VObf-8o{z0l!XZRqnYJE7FjWRK9jN>V#fwED-&5{)9Cpu z%E~l4FH@L>EV6L)d^TleMVc8o8)UL|^n4DHvm^5uIR|92dh~oQk#izGM$QG9>>oYv zByw(K93wkHCQn4q=MmZ2p3lf4$TUz8O_VJ!%i~@V*X+Q2uXHxKbE+-RP?v%X=AY=c zLUUG;Ll{+8qD2GowJtTj)*11&B_+NNmul;b_}YTe#G|b<;){?XZJiNcgt)YIMtl)c zsI4>Ni;z5Roe^JzIJ9+aG#XU7zDXh$SvzGNZTS>aW}gousiODw-2j+6|LA+>VEQ?w z>aSJmpGjwFntkJRBBA%G`aV^EyITK{THQAh(id~d;@HEYDSX`e2E5SUF)fiX_$8wYK?Hz7f9}~QWpsMdcawI2>;&3#F z*K&9rhhqrFcVLTWRtaXV#%fYO9=BlT!gN;vn-9zfY<_z$J`6)s-$dkaJd7IkeGzzk z+NosrwW@wWjbTl%pOm`Q9S@ygO+;zY56`LN&adjBsO#yoVauS#g6fWR%oW0pfSuO7 zYAoPTC+}*@Rby2?b@EH%>P}Eki7i%fNWh_pU4a6z>w#fnS8%x4HFv}&5?$*%yWQ6Q zRiD_E5W9AYU3>guS2tL{v(oFsB=Uj*zC{4tXDx&J3Arb3^?S8i>=69=ONv+Ud6!wR zAoQwM?@SwpTf3t9a(vpdTupUqGsWn|@$KKoOxcyC1s!5nl|>6?0$8t>1C z+!1}5%-;XFJp-^OZ3JP@9A?iT?74;PSq6Ldh^yaBvZvTpmM8y#*yTSy^YqhCYk@+L zhG>Cn0P?lKNPwYQU=%=s7QhTvHVk$Rj@AO#B0Zekajh1(4(So_%5_>`jM#Pen6--D zD}VA{&tYrKKFflY!It(?atS#Izq4?{N^$~dJE7uXN_$t6BgC#v+)KYPywsz3GZn9l z#ljX$Ez2>7d=swefom!Y6ipuH)0PkSY2O?nM=zALYvdiP7JzrkELs5GDFX)Yl-aZZ zyi;b^0`N{*niha}%F?v}yi=B;1>l`BhZcZ$$}+V8yi=B?1>l{sY%Kuql;vm?b!E9) z0NyEcY5{nsOwrhW+nFzU_Y*`J)l}*J|o@+RQQ0i&G<0W&NZaeK#YrPL7_px9>9j*4Sn+|4*K`^@;p^PFVDr^jMmSXsWA9=&c%3`q3ZK+%pl`854~~A-RPFGs!rY^ zuHJ}E4%}Voz%663_)(8IBqO>UE2xKF!dZ#fb+gztPed5Z%f;;;i`W%Hm{%aiThc(7 zfq^RG?n91M)_Xx{vE%ljQ_=U}gTyl~`ng zpjgiM^^38lV<_%*zjV+qeI`qBzjQ*;6!#HD%Rs&S(q6xG-YS`1S2@6Y*H~pwJcWlNGTXm>D(pTVC?(yZx3uBq4YAWhl}XMcRit z9@XYq6@8Zyv*#<8EwO?)S$Y$Uiu5UZuY6n|&qwc7-eomHNl=WA!hwxjDp+a2YDJV>j6$qAI zSelwCy$D`rh~u)f#V@_4ztH@VMBy*O0Udr%8mXLhNG6=W*XVOi?+TXs`p z6zR|UUPb>@k+w=(6@9N1C)aBshpcabBvt$qx%)6w_9`e`vGkG(6pzOH^?kDbH@~z+ z?mm)%DnML`jm}r#6-B=QyHZh#1*UpKiMjKcYd(Ue!{i8rv`uHBrd5V28*Qq=7ZfJD+r=YoT=b9xU_Srwvku7Rmq#!y974 zAUO~kinqq%h|&m&;bDsso13XsWCpzRhd7YVBG(1H^$f`-9|gSC49Ovbmw9U#k_$ry zyenAR8Qq>oMhbWp;5ZRH#0)d#HoLgG3rlOUD+5D#2I|iTwhC&?YGcr1Q>dcdpjFs0 zv}1T@1dUP^ShsKtsR|7LPZ=^5X=2y2JedhqCYff5jht>3yB_DsbdcEs7)r8`Ht9~J zO*J-N6e@~Fx4^FVSkR_S*f$pzu~IyXU2Hkc<|OT&bTksI^PE}*n#afQ86rlbPT7tT zfeyNao&$FDLYOlXwpF3=hB9v?(?Qx}ORdpvo8p}>Ij8{g31rJ+1#4(|uj&}zVQSAj zdu%3J&XQ@dnIyxpbmFBI5klPJ@Kj))HDw%-`8sFIG=vs#G>fEYk<6vC2c&W!CC}%4 zxrUf*%3;;WN)hEd*q$2lvcrRx%b6Z>jhyAFfX(G>PX#I{=Xl7Ua;}GbB|AM8=>Q@s z36SR@@5)0wG?UBuo(im1<)NMmtXAa$4|!c4=Bda981AV+x$+24h1hrK6Iyi+tT(XQ zP-Am_Sax7(LF6a7{>bb>iXj9`r_*P;_CY1>iXh; zbA2%x>x+l4t}p&auPx+P~z6coWi-57d2pH>&fU&*^80!l<4a53^PQ$Ri zpwlp{FX%K3>kB#!!}@|w!?3=f(=eDeDV*9$2ZL;)fafna&Eks;_Xzv3$bn ziB@*By{Z-+9w%0IMk;8Dsm2P8=s{~N=P_E$Vd<3N@C5J%!AqRaJ|L1dNF*I1w5E#{ zJjNGkB#EV+Dd`xH%p4?%MzT`)f^LMvGnW>0Sk6(BFXuQ$i#gIOQlnxI;936)cW;c| zsu6n*+M{ucUgLfXuMeCSJLsI6Juk)b*N>J=hfUjI^ZTKB4jkgA)pgh=)3O?enZ!k_ z`xgiSH?5j~O=)cSv;}k&-Ook`+dp73+LAPEQ}$^K?8*5#ep;S$ow;DxuPwk*`TpE~ zCLB~8P_*_ODC#0cZ2?x;?U{2MXxo)u|;yBYSRU!v)cWZU;m37 z-DWBC&UZPGMy=%7*Q{9S7lLPj)gSwsE#R#oWRA@ryN%3M?cN6+d8EVck5#*2V6->j zZE`pWMRk^>VSD8OgFoFLQ`{M4-W3A&5%*`vu@!EIcYdjZ5}9NoZ^S^bm21Z{JYXmR zrlKS|z^2|62IeG_dutpH7*57JM|cjm zA`i!UaTHExbEWt-Sa4fv#m#5K&bvG|{#NYC=_mzTc*`zq$)(ry!?dN{$M)*(eA)7< zewgj=-G^l9FN*#i&L!M9hrlV6egqjvGC`d8;J73wpU!&rTXvPlswbdx?2&fqyXmk3 z2L?FhvHUqUdcPv=M+I)T;bb9}Gl~w8aMB@Lb}9NvAW*+2HZ{{P?Xvu}JeD&lHZ>vr zRXx5vg$vK&Y2Mu8%o!O;hu zoGAL+s0nxh=A&}Ne9EuyWhY7cc5DTaw;g8y6-G{RL2G{YWG6`|N(LJkzgDOXJ+Kb{}>7`!HlPY2XgRF-)6y4&iuo+(uo$4Fes^ zfU_Us{j&`ZkngkbQ2_e!9KH<`!lOoQSn0enYUg}+T-Ihgp=marlTU-TZ*eWNF+ng9 zkny-4+29dntz4{(mHYbhW@oFh+3fjJj;im4UDe9TTU)PZ1Hma-Y_Z`mTXoQBwk!^@ znU6LjW-hm*)eb{^dgfQTOr!K$xw37$By%^5K9O>dQv}ipdqB_g|_zoz?7o{`G1- zt6HDs=*v1k_&gs^ko5%3f7P+EL8l8Z!^I{L#CtJkEA`i^$Gy+q3GMmZ7Juh8JRn_j zEaH;(o9E}%`r&H*tO5;*g16{xKYG#cFugFERFkCr{Hd+>a_6kTU=8s=i(M@UsAR_5^lSNxLiDI zf=lw2j(16uz2jXituF6PlUxfMBd&W|8zYf$v#YMn)evTCAwXJO6I_!@uFTS32KbO( z7;bg7EOsrVVkv@0x zKh*H}@K>Ll|Ca^fu1A}esxv=7_QJk9h6U#Rd+dphwR@it9{JPXvOYO9e|_b|b04&Q|Cf>LKm65AYYv{jIX=4m zo#u*@Bfoj=xEJ-7=NCGkF5EQgv$?lS+rDSH>tFVFUtIR`Kc61+_opUm89SukEmXJ0z<$EnfTKd2k=Pxc4?aL?;s zdbhD)(VQ>j+`nkWJ@rj zd$(}R_1SN}{*6Cxnp{=^D`G+svyd?Ho@E1*UPah87`yY-!EE`)q`rn@09{+n}%(VaP{MOQ2e!p0?opsjT zH1CCndanKPyXPJs()i}LzxTuI9`1W(PSHD${Hvb3`Gc|s`3DokXKVgA+%n2Gk+%`EP5zS zaeAWZ)y|pLO<7J4D6-Q94sez^9WwpLgrVmVz^70i*)B$C4fiqTL$`AuKy9M>@0l92K`Zcm2-pDIz7wj0!d~S3$TijJ~#OgKK&`z zMW7zPsh~UH<44K%Xw7%1-QTvUPFKuc<}7-I+Wk@1CD+~%BVd)k)eEX83i3{aM2 z05#j%dD#p4IBt85hdz65_0kQkz6nZu2MTq5eK=Y#d)B|_Dn@H5t){NQ7 zPj*6mxSe1WZYSHS4Af|bv#7!8n&~W@#XO;)Mx^JL(4+Px5;df!lI)F;Ox81CZ`BgO^=y{0kCY*RVV06Z|_BU8C3?>lzM6a#+aoX-!C%nSbVD zqJ{9stv&(*9t*Rp+va1CrdYZ*T73irdSREYrwkyl#Rk%a9LGNn4Z1MZ8JDk?L37UA z%gHp~(uD`r>>9yg-0ov3litg5v)*QT=KpS*I8Ja_dscFO9O^RMwC4$qH}HI3-2Zi8 z{vUg4L1(#N)6;z{YdD8r;&2j&0S@PKxR}GcIZV}CQC|KPSJ9k>?ah&P*GA1TnknWkR0 z{?Tk8hx)NyI7$D3G3cUk(jr`1e;OaHu>aDOahAqOqCcBLFXr^raam#d2kL2#C$ky- zQhVOZ^_b&4Peq~J$R^)=IKQXB$H?YheGlk)(4X30-sJonatwZUrUA+KIDP35 zgU-$rKwr%0mySQD866BM7yYMFehQ6H_Z8^$y&1CSfqWm6GS46?ufX5H`8`<%|7s>B z2+KjI_NLnNA<$i%CmB4(^dwV^^e-44^%>z~1a_8z)N`N@v0fuIq>Mj3L`TWyIBYl6 z2)$g-OqZdDon;{JAg8ar(V&}W2gf*_{!O1Qc6I>xIioYupd0!>v8`~n`)=*?gXi-y3bC^ERQr{A~v#DiaT~nw&($d-%s%u{+ zENWS@v?&}3*B9S>Q|V2YX9_KDY;FwIwYJtR4~3f}t;>bQt#wPnq5AeEOO`_<2@8QU zGKe+#Q4Q)jD_mEvhLqU2!Gqjn3Ne?@2nw@im(92xr37Zl)BPcT zP(cHY)|%--W!4KJ@zuo<-t=4do|+eP+J&}r-V?ro(yByvEEX%u>)V@xr852+XiY1eyXPNtsWqQKHOt`?&lH({$^$i5^ZY%+?+ys)i}*PnlVXyE%s1FGobLxwK~8gDuxRCRY~7Vl-{O?7Q;tcxK8%n+s6FuP%D zWDKao!$?6WZd<-2QnwHg-%4Vz!A#+!OX1d~LUD6TBwQ?)RZfW1-N~^#o7;;Qwm0H4 zS&j8VF<}jLZ4E+k{qkn$Ghn3E$hkY*+Sb_8JO~LPuQl9MM*=*xv?(GKGxHWBS$t;; z&`5Y0?lc5|sfER7akznZ`i6QaF)>5b=>3L-nf}Hiu%Vc`C5?+vhn5Jb2Ze&Y7_JbC zF%B)k*kTTy|3{G4xtLP=*E8n+jpk>%%<}*PGkDE3!7t)RdvMO)zt1zjx8_1#@@3AG zCQU*jS>D_aMz}(^$;e@u*+o_94V-%A5P&UM_F8(=0!={T*Dsj4L$v z$#E{fm(xj}bfwCF8#J;B)sHT7Ki$m>9BGjI?_6y^t|OH!Z|=JfaQO}WoJJy#<0kwb z@MQUw=|0A>l2^#AFBj{tzllGAM6$fOK3dD=A020M8qh4)r2Z^L-rVoIJqCw)er58f zw*MDg-t?cj9`$i~ACE&*-eo2@{0$)0-;_7MZ@6-z!SE#KGeK(kn~{+$Z=N$0l^7DA zrIep)&z)d%;%Bm%`!w@Ah^hRk_-l|AljO~Fi$eaL$W;DR{9VXW{mt^t^9|QODE|Ru z$sn@@llF=|GA3Kkf=34 z|J{@`;W^|amv8Q)YJG-?Sx-}eDQDsrkszAceslf4)Ms#{@^f<-nIs1S(RjG_(@l9E zM*VbC-h}i&$!6L8Oh^<>H!%7%O!Ae2va-$CPv(2dXJ8w71Fi#l6MklUXe^_P`sd}! QudQU+0=>_Xe5IEEUle-@5&!@I diff --git a/Exe/MacOS/AesBlock b/Exe/MacOS/AesBlock index 9cc9273e0140783355d8d9762697cd949363e7a7..49462db194c3ea48116e29f722f3208b60c7c528 100644 GIT binary patch literal 34052 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 E0OS=2tpET3 literal 17556 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 PN85a~%}3k1S1|oAnA_+c literal 17868 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 Xpvd5ynKgYb=e%$7^l7M7gya4bHH@EL diff --git a/Exe/Windows/AesBlock.exe b/Exe/Windows/AesBlock.exe index be08d3c1144dfca6ce961a9399784d52a436339c..a41b104eb740ff0e133d436924a0b5afec85547b 100644 GIT binary patch literal 30208 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 literal 13824 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 diff --git a/ReadMe.md b/ReadMe.md index 06a4f97..4f4baff 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -7,7 +7,8 @@ and a a single .h file. AES-CTR does depend on the AES module, so in this case all four files are needed. The functions are designed to be portable and have been tested on both -a Little-Endian and a Big-Endian architecture +a Little-Endian and a Big-Endian architecture. OpenMP is supported where +parallelisation can occur. The library and the demo programs can be built using CMake to generate a build setup for any system, including Visual Studio on Windows and @@ -15,6 +16,19 @@ Make or Ninja for Linux. Refer to cmake.org to get CMake. *Placed into Public Domain by WaterJuice 2013 - 2017* +Version 2.1.0 - December 2017 +----------------------------- + +Changes: + +* Changed implementation of AES to one which is almost 5 times as fast. +The new implementation comes from LibTomCrypt. The newer implementation +produces a larger binary size as a trade-off. +* AES-CTR module now supports OpenMP and when compiled with OpenMP will +run in parallel giving a much greater speed. +* Changed interface for Initialisation functions for both AES and AES-CTR +to be match RC4 (The context is first parameter not last) + Version 2.0.0 - December 2017 ----------------------------- @@ -42,7 +56,6 @@ depending on what cryptographic functions are wanted. * AES-CTR - (CryptLib_AesCtr.h, and CryptLib_AesCtr.c, CryptLib_Aes.h, and CryptLib_Aes.c) - Version 1.0.0 - June 2013 ------------------------- diff --git a/lib/CryptLib_Aes.c b/lib/CryptLib_Aes.c index dd91706..12b9929 100644 --- a/lib/CryptLib_Aes.c +++ b/lib/CryptLib_Aes.c @@ -1,18 +1,22 @@ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // CryptLib_Aes // -// Implementation of AES block cipher. Originally written by Kokke (https://github.com/kokke). Modified by WaterJuice -// retaining Public Domain license. +// Implementation of AES block cipher. This implementation was modified from LibTomCrypt written by Tom St Denis +// (https://github.com/libtom). Modified by WaterJuice retaining Public Domain license. +// Derived from Public Domain source by original authors: +// Vincent Rijmen +// Antoon Bosselaers +// Paulo Barreto // // AES is a block cipher that operates on 128 bit blocks. Encryption an Decryption routines use an AesContext which // must be initialised with the key. An AesContext can be initialised with a 128, 192, or 256 bit key. Use the // AesInitialise[n] functions to initialise the context with the key. Once an AES context is initialised its contents // are not changed by the encrypting and decrypting functions. A context only needs to be initialised once for any // given key and the context may be used by the encrypt/decrypt functions in simultaneous threads. -// All operations are performed byte wise and this implementation works in both little and endian processors. +// All operations are performed BYTE wise and this implementation works in both little and endian processors. // There are no alignment requirements with the keys and data blocks. // -// This is free and unencumbered software released into the public domain - November 2017 waterjuice.org +// This is free and unencumbered software released into the public domain - December 2017 waterjuice.org //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -23,458 +27,808 @@ #include #include -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// DEFINES -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -// Array holding the intermediate results during decryption. -typedef struct -{ - uint8_t state[4][4]; -} AesState; - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // CONSTANTS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// AES lookup values -static const uint8_t SBOX[256] = +static const uint32_t TE0[256] = { - 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, - 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, - 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, - 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, - 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, - 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, - 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, - 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, - 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, - 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, - 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, - 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, - 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, - 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, - 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, - 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 + 0xc66363a5UL, 0xf87c7c84UL, 0xee777799UL, 0xf67b7b8dUL, 0xfff2f20dUL, 0xd66b6bbdUL, 0xde6f6fb1UL, 0x91c5c554UL, + 0x60303050UL, 0x02010103UL, 0xce6767a9UL, 0x562b2b7dUL, 0xe7fefe19UL, 0xb5d7d762UL, 0x4dababe6UL, 0xec76769aUL, + 0x8fcaca45UL, 0x1f82829dUL, 0x89c9c940UL, 0xfa7d7d87UL, 0xeffafa15UL, 0xb25959ebUL, 0x8e4747c9UL, 0xfbf0f00bUL, + 0x41adadecUL, 0xb3d4d467UL, 0x5fa2a2fdUL, 0x45afafeaUL, 0x239c9cbfUL, 0x53a4a4f7UL, 0xe4727296UL, 0x9bc0c05bUL, + 0x75b7b7c2UL, 0xe1fdfd1cUL, 0x3d9393aeUL, 0x4c26266aUL, 0x6c36365aUL, 0x7e3f3f41UL, 0xf5f7f702UL, 0x83cccc4fUL, + 0x6834345cUL, 0x51a5a5f4UL, 0xd1e5e534UL, 0xf9f1f108UL, 0xe2717193UL, 0xabd8d873UL, 0x62313153UL, 0x2a15153fUL, + 0x0804040cUL, 0x95c7c752UL, 0x46232365UL, 0x9dc3c35eUL, 0x30181828UL, 0x379696a1UL, 0x0a05050fUL, 0x2f9a9ab5UL, + 0x0e070709UL, 0x24121236UL, 0x1b80809bUL, 0xdfe2e23dUL, 0xcdebeb26UL, 0x4e272769UL, 0x7fb2b2cdUL, 0xea75759fUL, + 0x1209091bUL, 0x1d83839eUL, 0x582c2c74UL, 0x341a1a2eUL, 0x361b1b2dUL, 0xdc6e6eb2UL, 0xb45a5aeeUL, 0x5ba0a0fbUL, + 0xa45252f6UL, 0x763b3b4dUL, 0xb7d6d661UL, 0x7db3b3ceUL, 0x5229297bUL, 0xdde3e33eUL, 0x5e2f2f71UL, 0x13848497UL, + 0xa65353f5UL, 0xb9d1d168UL, 0x00000000UL, 0xc1eded2cUL, 0x40202060UL, 0xe3fcfc1fUL, 0x79b1b1c8UL, 0xb65b5bedUL, + 0xd46a6abeUL, 0x8dcbcb46UL, 0x67bebed9UL, 0x7239394bUL, 0x944a4adeUL, 0x984c4cd4UL, 0xb05858e8UL, 0x85cfcf4aUL, + 0xbbd0d06bUL, 0xc5efef2aUL, 0x4faaaae5UL, 0xedfbfb16UL, 0x864343c5UL, 0x9a4d4dd7UL, 0x66333355UL, 0x11858594UL, + 0x8a4545cfUL, 0xe9f9f910UL, 0x04020206UL, 0xfe7f7f81UL, 0xa05050f0UL, 0x783c3c44UL, 0x259f9fbaUL, 0x4ba8a8e3UL, + 0xa25151f3UL, 0x5da3a3feUL, 0x804040c0UL, 0x058f8f8aUL, 0x3f9292adUL, 0x219d9dbcUL, 0x70383848UL, 0xf1f5f504UL, + 0x63bcbcdfUL, 0x77b6b6c1UL, 0xafdada75UL, 0x42212163UL, 0x20101030UL, 0xe5ffff1aUL, 0xfdf3f30eUL, 0xbfd2d26dUL, + 0x81cdcd4cUL, 0x180c0c14UL, 0x26131335UL, 0xc3ecec2fUL, 0xbe5f5fe1UL, 0x359797a2UL, 0x884444ccUL, 0x2e171739UL, + 0x93c4c457UL, 0x55a7a7f2UL, 0xfc7e7e82UL, 0x7a3d3d47UL, 0xc86464acUL, 0xba5d5de7UL, 0x3219192bUL, 0xe6737395UL, + 0xc06060a0UL, 0x19818198UL, 0x9e4f4fd1UL, 0xa3dcdc7fUL, 0x44222266UL, 0x542a2a7eUL, 0x3b9090abUL, 0x0b888883UL, + 0x8c4646caUL, 0xc7eeee29UL, 0x6bb8b8d3UL, 0x2814143cUL, 0xa7dede79UL, 0xbc5e5ee2UL, 0x160b0b1dUL, 0xaddbdb76UL, + 0xdbe0e03bUL, 0x64323256UL, 0x743a3a4eUL, 0x140a0a1eUL, 0x924949dbUL, 0x0c06060aUL, 0x4824246cUL, 0xb85c5ce4UL, + 0x9fc2c25dUL, 0xbdd3d36eUL, 0x43acacefUL, 0xc46262a6UL, 0x399191a8UL, 0x319595a4UL, 0xd3e4e437UL, 0xf279798bUL, + 0xd5e7e732UL, 0x8bc8c843UL, 0x6e373759UL, 0xda6d6db7UL, 0x018d8d8cUL, 0xb1d5d564UL, 0x9c4e4ed2UL, 0x49a9a9e0UL, + 0xd86c6cb4UL, 0xac5656faUL, 0xf3f4f407UL, 0xcfeaea25UL, 0xca6565afUL, 0xf47a7a8eUL, 0x47aeaee9UL, 0x10080818UL, + 0x6fbabad5UL, 0xf0787888UL, 0x4a25256fUL, 0x5c2e2e72UL, 0x381c1c24UL, 0x57a6a6f1UL, 0x73b4b4c7UL, 0x97c6c651UL, + 0xcbe8e823UL, 0xa1dddd7cUL, 0xe874749cUL, 0x3e1f1f21UL, 0x964b4bddUL, 0x61bdbddcUL, 0x0d8b8b86UL, 0x0f8a8a85UL, + 0xe0707090UL, 0x7c3e3e42UL, 0x71b5b5c4UL, 0xcc6666aaUL, 0x904848d8UL, 0x06030305UL, 0xf7f6f601UL, 0x1c0e0e12UL, + 0xc26161a3UL, 0x6a35355fUL, 0xae5757f9UL, 0x69b9b9d0UL, 0x17868691UL, 0x99c1c158UL, 0x3a1d1d27UL, 0x279e9eb9UL, + 0xd9e1e138UL, 0xebf8f813UL, 0x2b9898b3UL, 0x22111133UL, 0xd26969bbUL, 0xa9d9d970UL, 0x078e8e89UL, 0x339494a7UL, + 0x2d9b9bb6UL, 0x3c1e1e22UL, 0x15878792UL, 0xc9e9e920UL, 0x87cece49UL, 0xaa5555ffUL, 0x50282878UL, 0xa5dfdf7aUL, + 0x038c8c8fUL, 0x59a1a1f8UL, 0x09898980UL, 0x1a0d0d17UL, 0x65bfbfdaUL, 0xd7e6e631UL, 0x844242c6UL, 0xd06868b8UL, + 0x824141c3UL, 0x299999b0UL, 0x5a2d2d77UL, 0x1e0f0f11UL, 0x7bb0b0cbUL, 0xa85454fcUL, 0x6dbbbbd6UL, 0x2c16163aUL, }; -static const uint8_t RSBOX[256] = +static const uint32_t TD0[256] = { - 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, - 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, - 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, - 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, - 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, - 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, - 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, - 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, - 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, - 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, - 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, - 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, - 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, - 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, - 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, - 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d }; + 0x51f4a750UL, 0x7e416553UL, 0x1a17a4c3UL, 0x3a275e96UL, 0x3bab6bcbUL, 0x1f9d45f1UL, 0xacfa58abUL, 0x4be30393UL, + 0x2030fa55UL, 0xad766df6UL, 0x88cc7691UL, 0xf5024c25UL, 0x4fe5d7fcUL, 0xc52acbd7UL, 0x26354480UL, 0xb562a38fUL, + 0xdeb15a49UL, 0x25ba1b67UL, 0x45ea0e98UL, 0x5dfec0e1UL, 0xc32f7502UL, 0x814cf012UL, 0x8d4697a3UL, 0x6bd3f9c6UL, + 0x038f5fe7UL, 0x15929c95UL, 0xbf6d7aebUL, 0x955259daUL, 0xd4be832dUL, 0x587421d3UL, 0x49e06929UL, 0x8ec9c844UL, + 0x75c2896aUL, 0xf48e7978UL, 0x99583e6bUL, 0x27b971ddUL, 0xbee14fb6UL, 0xf088ad17UL, 0xc920ac66UL, 0x7dce3ab4UL, + 0x63df4a18UL, 0xe51a3182UL, 0x97513360UL, 0x62537f45UL, 0xb16477e0UL, 0xbb6bae84UL, 0xfe81a01cUL, 0xf9082b94UL, + 0x70486858UL, 0x8f45fd19UL, 0x94de6c87UL, 0x527bf8b7UL, 0xab73d323UL, 0x724b02e2UL, 0xe31f8f57UL, 0x6655ab2aUL, + 0xb2eb2807UL, 0x2fb5c203UL, 0x86c57b9aUL, 0xd33708a5UL, 0x302887f2UL, 0x23bfa5b2UL, 0x02036abaUL, 0xed16825cUL, + 0x8acf1c2bUL, 0xa779b492UL, 0xf307f2f0UL, 0x4e69e2a1UL, 0x65daf4cdUL, 0x0605bed5UL, 0xd134621fUL, 0xc4a6fe8aUL, + 0x342e539dUL, 0xa2f355a0UL, 0x058ae132UL, 0xa4f6eb75UL, 0x0b83ec39UL, 0x4060efaaUL, 0x5e719f06UL, 0xbd6e1051UL, + 0x3e218af9UL, 0x96dd063dUL, 0xdd3e05aeUL, 0x4de6bd46UL, 0x91548db5UL, 0x71c45d05UL, 0x0406d46fUL, 0x605015ffUL, + 0x1998fb24UL, 0xd6bde997UL, 0x894043ccUL, 0x67d99e77UL, 0xb0e842bdUL, 0x07898b88UL, 0xe7195b38UL, 0x79c8eedbUL, + 0xa17c0a47UL, 0x7c420fe9UL, 0xf8841ec9UL, 0x00000000UL, 0x09808683UL, 0x322bed48UL, 0x1e1170acUL, 0x6c5a724eUL, + 0xfd0efffbUL, 0x0f853856UL, 0x3daed51eUL, 0x362d3927UL, 0x0a0fd964UL, 0x685ca621UL, 0x9b5b54d1UL, 0x24362e3aUL, + 0x0c0a67b1UL, 0x9357e70fUL, 0xb4ee96d2UL, 0x1b9b919eUL, 0x80c0c54fUL, 0x61dc20a2UL, 0x5a774b69UL, 0x1c121a16UL, + 0xe293ba0aUL, 0xc0a02ae5UL, 0x3c22e043UL, 0x121b171dUL, 0x0e090d0bUL, 0xf28bc7adUL, 0x2db6a8b9UL, 0x141ea9c8UL, + 0x57f11985UL, 0xaf75074cUL, 0xee99ddbbUL, 0xa37f60fdUL, 0xf701269fUL, 0x5c72f5bcUL, 0x44663bc5UL, 0x5bfb7e34UL, + 0x8b432976UL, 0xcb23c6dcUL, 0xb6edfc68UL, 0xb8e4f163UL, 0xd731dccaUL, 0x42638510UL, 0x13972240UL, 0x84c61120UL, + 0x854a247dUL, 0xd2bb3df8UL, 0xaef93211UL, 0xc729a16dUL, 0x1d9e2f4bUL, 0xdcb230f3UL, 0x0d8652ecUL, 0x77c1e3d0UL, + 0x2bb3166cUL, 0xa970b999UL, 0x119448faUL, 0x47e96422UL, 0xa8fc8cc4UL, 0xa0f03f1aUL, 0x567d2cd8UL, 0x223390efUL, + 0x87494ec7UL, 0xd938d1c1UL, 0x8ccaa2feUL, 0x98d40b36UL, 0xa6f581cfUL, 0xa57ade28UL, 0xdab78e26UL, 0x3fadbfa4UL, + 0x2c3a9de4UL, 0x5078920dUL, 0x6a5fcc9bUL, 0x547e4662UL, 0xf68d13c2UL, 0x90d8b8e8UL, 0x2e39f75eUL, 0x82c3aff5UL, + 0x9f5d80beUL, 0x69d0937cUL, 0x6fd52da9UL, 0xcf2512b3UL, 0xc8ac993bUL, 0x10187da7UL, 0xe89c636eUL, 0xdb3bbb7bUL, + 0xcd267809UL, 0x6e5918f4UL, 0xec9ab701UL, 0x834f9aa8UL, 0xe6956e65UL, 0xaaffe67eUL, 0x21bccf08UL, 0xef15e8e6UL, + 0xbae79bd9UL, 0x4a6f36ceUL, 0xea9f09d4UL, 0x29b07cd6UL, 0x31a4b2afUL, 0x2a3f2331UL, 0xc6a59430UL, 0x35a266c0UL, + 0x744ebc37UL, 0xfc82caa6UL, 0xe090d0b0UL, 0x33a7d815UL, 0xf104984aUL, 0x41ecdaf7UL, 0x7fcd500eUL, 0x1791f62fUL, + 0x764dd68dUL, 0x43efb04dUL, 0xccaa4d54UL, 0xe49604dfUL, 0x9ed1b5e3UL, 0x4c6a881bUL, 0xc12c1fb8UL, 0x4665517fUL, + 0x9d5eea04UL, 0x018c355dUL, 0xfa877473UL, 0xfb0b412eUL, 0xb3671d5aUL, 0x92dbd252UL, 0xe9105633UL, 0x6dd64713UL, + 0x9ad7618cUL, 0x37a10c7aUL, 0x59f8148eUL, 0xeb133c89UL, 0xcea927eeUL, 0xb761c935UL, 0xe11ce5edUL, 0x7a47b13cUL, + 0x9cd2df59UL, 0x55f2733fUL, 0x1814ce79UL, 0x73c737bfUL, 0x53f7cdeaUL, 0x5ffdaa5bUL, 0xdf3d6f14UL, 0x7844db86UL, + 0xcaaff381UL, 0xb968c43eUL, 0x3824342cUL, 0xc2a3405fUL, 0x161dc372UL, 0xbce2250cUL, 0x283c498bUL, 0xff0d9541UL, + 0x39a80171UL, 0x080cb3deUL, 0xd8b4e49cUL, 0x6456c190UL, 0x7bcb8461UL, 0xd532b670UL, 0x486c5c74UL, 0xd0b85742UL, +}; -// The round constant word array, RCON[i], contains the values given by -// x to the power (i-1) being powers of x (x is denoted as {02}) in the field GF(2^8) -static const uint8_t RCON[11] = { 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 }; - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// INTERNAL FUNCTIONS -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// KeyExpansion -// -// This function produces Nb(Nr+1) round keys. The round keys are used in each round to decrypt the states. -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -static -void - KeyExpansion - ( - uint8_t const* Key, // [in] - AesContext* Context // [in out] - ) +static const uint32_t Td4[256] = { - uint32_t i; - uint8_t k; - uint8_t temp [4]; // Used for the column/row operations + 0x52525252UL, 0x09090909UL, 0x6a6a6a6aUL, 0xd5d5d5d5UL, 0x30303030UL, 0x36363636UL, 0xa5a5a5a5UL, 0x38383838UL, + 0xbfbfbfbfUL, 0x40404040UL, 0xa3a3a3a3UL, 0x9e9e9e9eUL, 0x81818181UL, 0xf3f3f3f3UL, 0xd7d7d7d7UL, 0xfbfbfbfbUL, + 0x7c7c7c7cUL, 0xe3e3e3e3UL, 0x39393939UL, 0x82828282UL, 0x9b9b9b9bUL, 0x2f2f2f2fUL, 0xffffffffUL, 0x87878787UL, + 0x34343434UL, 0x8e8e8e8eUL, 0x43434343UL, 0x44444444UL, 0xc4c4c4c4UL, 0xdedededeUL, 0xe9e9e9e9UL, 0xcbcbcbcbUL, + 0x54545454UL, 0x7b7b7b7bUL, 0x94949494UL, 0x32323232UL, 0xa6a6a6a6UL, 0xc2c2c2c2UL, 0x23232323UL, 0x3d3d3d3dUL, + 0xeeeeeeeeUL, 0x4c4c4c4cUL, 0x95959595UL, 0x0b0b0b0bUL, 0x42424242UL, 0xfafafafaUL, 0xc3c3c3c3UL, 0x4e4e4e4eUL, + 0x08080808UL, 0x2e2e2e2eUL, 0xa1a1a1a1UL, 0x66666666UL, 0x28282828UL, 0xd9d9d9d9UL, 0x24242424UL, 0xb2b2b2b2UL, + 0x76767676UL, 0x5b5b5b5bUL, 0xa2a2a2a2UL, 0x49494949UL, 0x6d6d6d6dUL, 0x8b8b8b8bUL, 0xd1d1d1d1UL, 0x25252525UL, + 0x72727272UL, 0xf8f8f8f8UL, 0xf6f6f6f6UL, 0x64646464UL, 0x86868686UL, 0x68686868UL, 0x98989898UL, 0x16161616UL, + 0xd4d4d4d4UL, 0xa4a4a4a4UL, 0x5c5c5c5cUL, 0xccccccccUL, 0x5d5d5d5dUL, 0x65656565UL, 0xb6b6b6b6UL, 0x92929292UL, + 0x6c6c6c6cUL, 0x70707070UL, 0x48484848UL, 0x50505050UL, 0xfdfdfdfdUL, 0xededededUL, 0xb9b9b9b9UL, 0xdadadadaUL, + 0x5e5e5e5eUL, 0x15151515UL, 0x46464646UL, 0x57575757UL, 0xa7a7a7a7UL, 0x8d8d8d8dUL, 0x9d9d9d9dUL, 0x84848484UL, + 0x90909090UL, 0xd8d8d8d8UL, 0xababababUL, 0x00000000UL, 0x8c8c8c8cUL, 0xbcbcbcbcUL, 0xd3d3d3d3UL, 0x0a0a0a0aUL, + 0xf7f7f7f7UL, 0xe4e4e4e4UL, 0x58585858UL, 0x05050505UL, 0xb8b8b8b8UL, 0xb3b3b3b3UL, 0x45454545UL, 0x06060606UL, + 0xd0d0d0d0UL, 0x2c2c2c2cUL, 0x1e1e1e1eUL, 0x8f8f8f8fUL, 0xcacacacaUL, 0x3f3f3f3fUL, 0x0f0f0f0fUL, 0x02020202UL, + 0xc1c1c1c1UL, 0xafafafafUL, 0xbdbdbdbdUL, 0x03030303UL, 0x01010101UL, 0x13131313UL, 0x8a8a8a8aUL, 0x6b6b6b6bUL, + 0x3a3a3a3aUL, 0x91919191UL, 0x11111111UL, 0x41414141UL, 0x4f4f4f4fUL, 0x67676767UL, 0xdcdcdcdcUL, 0xeaeaeaeaUL, + 0x97979797UL, 0xf2f2f2f2UL, 0xcfcfcfcfUL, 0xcecececeUL, 0xf0f0f0f0UL, 0xb4b4b4b4UL, 0xe6e6e6e6UL, 0x73737373UL, + 0x96969696UL, 0xacacacacUL, 0x74747474UL, 0x22222222UL, 0xe7e7e7e7UL, 0xadadadadUL, 0x35353535UL, 0x85858585UL, + 0xe2e2e2e2UL, 0xf9f9f9f9UL, 0x37373737UL, 0xe8e8e8e8UL, 0x1c1c1c1cUL, 0x75757575UL, 0xdfdfdfdfUL, 0x6e6e6e6eUL, + 0x47474747UL, 0xf1f1f1f1UL, 0x1a1a1a1aUL, 0x71717171UL, 0x1d1d1d1dUL, 0x29292929UL, 0xc5c5c5c5UL, 0x89898989UL, + 0x6f6f6f6fUL, 0xb7b7b7b7UL, 0x62626262UL, 0x0e0e0e0eUL, 0xaaaaaaaaUL, 0x18181818UL, 0xbebebebeUL, 0x1b1b1b1bUL, + 0xfcfcfcfcUL, 0x56565656UL, 0x3e3e3e3eUL, 0x4b4b4b4bUL, 0xc6c6c6c6UL, 0xd2d2d2d2UL, 0x79797979UL, 0x20202020UL, + 0x9a9a9a9aUL, 0xdbdbdbdbUL, 0xc0c0c0c0UL, 0xfefefefeUL, 0x78787878UL, 0xcdcdcdcdUL, 0x5a5a5a5aUL, 0xf4f4f4f4UL, + 0x1f1f1f1fUL, 0xddddddddUL, 0xa8a8a8a8UL, 0x33333333UL, 0x88888888UL, 0x07070707UL, 0xc7c7c7c7UL, 0x31313131UL, + 0xb1b1b1b1UL, 0x12121212UL, 0x10101010UL, 0x59595959UL, 0x27272727UL, 0x80808080UL, 0xececececUL, 0x5f5f5f5fUL, + 0x60606060UL, 0x51515151UL, 0x7f7f7f7fUL, 0xa9a9a9a9UL, 0x19191919UL, 0xb5b5b5b5UL, 0x4a4a4a4aUL, 0x0d0d0d0dUL, + 0x2d2d2d2dUL, 0xe5e5e5e5UL, 0x7a7a7a7aUL, 0x9f9f9f9fUL, 0x93939393UL, 0xc9c9c9c9UL, 0x9c9c9c9cUL, 0xefefefefUL, + 0xa0a0a0a0UL, 0xe0e0e0e0UL, 0x3b3b3b3bUL, 0x4d4d4d4dUL, 0xaeaeaeaeUL, 0x2a2a2a2aUL, 0xf5f5f5f5UL, 0xb0b0b0b0UL, + 0xc8c8c8c8UL, 0xebebebebUL, 0xbbbbbbbbUL, 0x3c3c3c3cUL, 0x83838383UL, 0x53535353UL, 0x99999999UL, 0x61616161UL, + 0x17171717UL, 0x2b2b2b2bUL, 0x04040404UL, 0x7e7e7e7eUL, 0xbabababaUL, 0x77777777UL, 0xd6d6d6d6UL, 0x26262626UL, + 0xe1e1e1e1UL, 0x69696969UL, 0x14141414UL, 0x63636363UL, 0x55555555UL, 0x21212121UL, 0x0c0c0c0cUL, 0x7d7d7d7dUL, +}; - // The first round key is the key itself. - for( i=0; iKeySizeInWords; i++ ) - { - Context->RoundKey[(i * 4) + 0] = Key[(i * 4) + 0]; - Context->RoundKey[(i * 4) + 1] = Key[(i * 4) + 1]; - Context->RoundKey[(i * 4) + 2] = Key[(i * 4) + 2]; - Context->RoundKey[(i * 4) + 3] = Key[(i * 4) + 3]; - } +static const uint32_t TE1[256] = +{ + 0xa5c66363UL, 0x84f87c7cUL, 0x99ee7777UL, 0x8df67b7bUL, 0x0dfff2f2UL, 0xbdd66b6bUL, 0xb1de6f6fUL, 0x5491c5c5UL, + 0x50603030UL, 0x03020101UL, 0xa9ce6767UL, 0x7d562b2bUL, 0x19e7fefeUL, 0x62b5d7d7UL, 0xe64dababUL, 0x9aec7676UL, + 0x458fcacaUL, 0x9d1f8282UL, 0x4089c9c9UL, 0x87fa7d7dUL, 0x15effafaUL, 0xebb25959UL, 0xc98e4747UL, 0x0bfbf0f0UL, + 0xec41adadUL, 0x67b3d4d4UL, 0xfd5fa2a2UL, 0xea45afafUL, 0xbf239c9cUL, 0xf753a4a4UL, 0x96e47272UL, 0x5b9bc0c0UL, + 0xc275b7b7UL, 0x1ce1fdfdUL, 0xae3d9393UL, 0x6a4c2626UL, 0x5a6c3636UL, 0x417e3f3fUL, 0x02f5f7f7UL, 0x4f83ccccUL, + 0x5c683434UL, 0xf451a5a5UL, 0x34d1e5e5UL, 0x08f9f1f1UL, 0x93e27171UL, 0x73abd8d8UL, 0x53623131UL, 0x3f2a1515UL, + 0x0c080404UL, 0x5295c7c7UL, 0x65462323UL, 0x5e9dc3c3UL, 0x28301818UL, 0xa1379696UL, 0x0f0a0505UL, 0xb52f9a9aUL, + 0x090e0707UL, 0x36241212UL, 0x9b1b8080UL, 0x3ddfe2e2UL, 0x26cdebebUL, 0x694e2727UL, 0xcd7fb2b2UL, 0x9fea7575UL, + 0x1b120909UL, 0x9e1d8383UL, 0x74582c2cUL, 0x2e341a1aUL, 0x2d361b1bUL, 0xb2dc6e6eUL, 0xeeb45a5aUL, 0xfb5ba0a0UL, + 0xf6a45252UL, 0x4d763b3bUL, 0x61b7d6d6UL, 0xce7db3b3UL, 0x7b522929UL, 0x3edde3e3UL, 0x715e2f2fUL, 0x97138484UL, + 0xf5a65353UL, 0x68b9d1d1UL, 0x00000000UL, 0x2cc1ededUL, 0x60402020UL, 0x1fe3fcfcUL, 0xc879b1b1UL, 0xedb65b5bUL, + 0xbed46a6aUL, 0x468dcbcbUL, 0xd967bebeUL, 0x4b723939UL, 0xde944a4aUL, 0xd4984c4cUL, 0xe8b05858UL, 0x4a85cfcfUL, + 0x6bbbd0d0UL, 0x2ac5efefUL, 0xe54faaaaUL, 0x16edfbfbUL, 0xc5864343UL, 0xd79a4d4dUL, 0x55663333UL, 0x94118585UL, + 0xcf8a4545UL, 0x10e9f9f9UL, 0x06040202UL, 0x81fe7f7fUL, 0xf0a05050UL, 0x44783c3cUL, 0xba259f9fUL, 0xe34ba8a8UL, + 0xf3a25151UL, 0xfe5da3a3UL, 0xc0804040UL, 0x8a058f8fUL, 0xad3f9292UL, 0xbc219d9dUL, 0x48703838UL, 0x04f1f5f5UL, + 0xdf63bcbcUL, 0xc177b6b6UL, 0x75afdadaUL, 0x63422121UL, 0x30201010UL, 0x1ae5ffffUL, 0x0efdf3f3UL, 0x6dbfd2d2UL, + 0x4c81cdcdUL, 0x14180c0cUL, 0x35261313UL, 0x2fc3ececUL, 0xe1be5f5fUL, 0xa2359797UL, 0xcc884444UL, 0x392e1717UL, + 0x5793c4c4UL, 0xf255a7a7UL, 0x82fc7e7eUL, 0x477a3d3dUL, 0xacc86464UL, 0xe7ba5d5dUL, 0x2b321919UL, 0x95e67373UL, + 0xa0c06060UL, 0x98198181UL, 0xd19e4f4fUL, 0x7fa3dcdcUL, 0x66442222UL, 0x7e542a2aUL, 0xab3b9090UL, 0x830b8888UL, + 0xca8c4646UL, 0x29c7eeeeUL, 0xd36bb8b8UL, 0x3c281414UL, 0x79a7dedeUL, 0xe2bc5e5eUL, 0x1d160b0bUL, 0x76addbdbUL, + 0x3bdbe0e0UL, 0x56643232UL, 0x4e743a3aUL, 0x1e140a0aUL, 0xdb924949UL, 0x0a0c0606UL, 0x6c482424UL, 0xe4b85c5cUL, + 0x5d9fc2c2UL, 0x6ebdd3d3UL, 0xef43acacUL, 0xa6c46262UL, 0xa8399191UL, 0xa4319595UL, 0x37d3e4e4UL, 0x8bf27979UL, + 0x32d5e7e7UL, 0x438bc8c8UL, 0x596e3737UL, 0xb7da6d6dUL, 0x8c018d8dUL, 0x64b1d5d5UL, 0xd29c4e4eUL, 0xe049a9a9UL, + 0xb4d86c6cUL, 0xfaac5656UL, 0x07f3f4f4UL, 0x25cfeaeaUL, 0xafca6565UL, 0x8ef47a7aUL, 0xe947aeaeUL, 0x18100808UL, + 0xd56fbabaUL, 0x88f07878UL, 0x6f4a2525UL, 0x725c2e2eUL, 0x24381c1cUL, 0xf157a6a6UL, 0xc773b4b4UL, 0x5197c6c6UL, + 0x23cbe8e8UL, 0x7ca1ddddUL, 0x9ce87474UL, 0x213e1f1fUL, 0xdd964b4bUL, 0xdc61bdbdUL, 0x860d8b8bUL, 0x850f8a8aUL, + 0x90e07070UL, 0x427c3e3eUL, 0xc471b5b5UL, 0xaacc6666UL, 0xd8904848UL, 0x05060303UL, 0x01f7f6f6UL, 0x121c0e0eUL, + 0xa3c26161UL, 0x5f6a3535UL, 0xf9ae5757UL, 0xd069b9b9UL, 0x91178686UL, 0x5899c1c1UL, 0x273a1d1dUL, 0xb9279e9eUL, + 0x38d9e1e1UL, 0x13ebf8f8UL, 0xb32b9898UL, 0x33221111UL, 0xbbd26969UL, 0x70a9d9d9UL, 0x89078e8eUL, 0xa7339494UL, + 0xb62d9b9bUL, 0x223c1e1eUL, 0x92158787UL, 0x20c9e9e9UL, 0x4987ceceUL, 0xffaa5555UL, 0x78502828UL, 0x7aa5dfdfUL, + 0x8f038c8cUL, 0xf859a1a1UL, 0x80098989UL, 0x171a0d0dUL, 0xda65bfbfUL, 0x31d7e6e6UL, 0xc6844242UL, 0xb8d06868UL, + 0xc3824141UL, 0xb0299999UL, 0x775a2d2dUL, 0x111e0f0fUL, 0xcb7bb0b0UL, 0xfca85454UL, 0xd66dbbbbUL, 0x3a2c1616UL, +}; - // All other round keys are found from the previous round keys. - for( i=Context->KeySizeInWords; i<4*(Context->NumberOfRounds+1); i++ ) - { - #ifdef _MSC_VER - // Visual Studio code analysis complains about the following code that the index into Context->RoundKey - // may be -4. This is because it is concerned that 'i' may be zero. However we know that 'i' will not - // be zero as it starts at Context->KeySizeInWords which is never going to be zero when this function - // is called (It will have one of 3 values assigned to it by the initialise functions). So we need to - // just suppress the warning here to stop Visual Studio complaining. - #pragma warning( suppress : 6385 ) - #endif - temp[0] = Context->RoundKey[(i-1) * 4 + 0]; - temp[1] = Context->RoundKey[(i-1) * 4 + 1]; - temp[2] = Context->RoundKey[(i-1) * 4 + 2]; - temp[3] = Context->RoundKey[(i-1) * 4 + 3]; +static const uint32_t TE2[256] = +{ + 0x63a5c663UL, 0x7c84f87cUL, 0x7799ee77UL, 0x7b8df67bUL, 0xf20dfff2UL, 0x6bbdd66bUL, 0x6fb1de6fUL, 0xc55491c5UL, + 0x30506030UL, 0x01030201UL, 0x67a9ce67UL, 0x2b7d562bUL, 0xfe19e7feUL, 0xd762b5d7UL, 0xabe64dabUL, 0x769aec76UL, + 0xca458fcaUL, 0x829d1f82UL, 0xc94089c9UL, 0x7d87fa7dUL, 0xfa15effaUL, 0x59ebb259UL, 0x47c98e47UL, 0xf00bfbf0UL, + 0xadec41adUL, 0xd467b3d4UL, 0xa2fd5fa2UL, 0xafea45afUL, 0x9cbf239cUL, 0xa4f753a4UL, 0x7296e472UL, 0xc05b9bc0UL, + 0xb7c275b7UL, 0xfd1ce1fdUL, 0x93ae3d93UL, 0x266a4c26UL, 0x365a6c36UL, 0x3f417e3fUL, 0xf702f5f7UL, 0xcc4f83ccUL, + 0x345c6834UL, 0xa5f451a5UL, 0xe534d1e5UL, 0xf108f9f1UL, 0x7193e271UL, 0xd873abd8UL, 0x31536231UL, 0x153f2a15UL, + 0x040c0804UL, 0xc75295c7UL, 0x23654623UL, 0xc35e9dc3UL, 0x18283018UL, 0x96a13796UL, 0x050f0a05UL, 0x9ab52f9aUL, + 0x07090e07UL, 0x12362412UL, 0x809b1b80UL, 0xe23ddfe2UL, 0xeb26cdebUL, 0x27694e27UL, 0xb2cd7fb2UL, 0x759fea75UL, + 0x091b1209UL, 0x839e1d83UL, 0x2c74582cUL, 0x1a2e341aUL, 0x1b2d361bUL, 0x6eb2dc6eUL, 0x5aeeb45aUL, 0xa0fb5ba0UL, + 0x52f6a452UL, 0x3b4d763bUL, 0xd661b7d6UL, 0xb3ce7db3UL, 0x297b5229UL, 0xe33edde3UL, 0x2f715e2fUL, 0x84971384UL, + 0x53f5a653UL, 0xd168b9d1UL, 0x00000000UL, 0xed2cc1edUL, 0x20604020UL, 0xfc1fe3fcUL, 0xb1c879b1UL, 0x5bedb65bUL, + 0x6abed46aUL, 0xcb468dcbUL, 0xbed967beUL, 0x394b7239UL, 0x4ade944aUL, 0x4cd4984cUL, 0x58e8b058UL, 0xcf4a85cfUL, + 0xd06bbbd0UL, 0xef2ac5efUL, 0xaae54faaUL, 0xfb16edfbUL, 0x43c58643UL, 0x4dd79a4dUL, 0x33556633UL, 0x85941185UL, + 0x45cf8a45UL, 0xf910e9f9UL, 0x02060402UL, 0x7f81fe7fUL, 0x50f0a050UL, 0x3c44783cUL, 0x9fba259fUL, 0xa8e34ba8UL, + 0x51f3a251UL, 0xa3fe5da3UL, 0x40c08040UL, 0x8f8a058fUL, 0x92ad3f92UL, 0x9dbc219dUL, 0x38487038UL, 0xf504f1f5UL, + 0xbcdf63bcUL, 0xb6c177b6UL, 0xda75afdaUL, 0x21634221UL, 0x10302010UL, 0xff1ae5ffUL, 0xf30efdf3UL, 0xd26dbfd2UL, + 0xcd4c81cdUL, 0x0c14180cUL, 0x13352613UL, 0xec2fc3ecUL, 0x5fe1be5fUL, 0x97a23597UL, 0x44cc8844UL, 0x17392e17UL, + 0xc45793c4UL, 0xa7f255a7UL, 0x7e82fc7eUL, 0x3d477a3dUL, 0x64acc864UL, 0x5de7ba5dUL, 0x192b3219UL, 0x7395e673UL, + 0x60a0c060UL, 0x81981981UL, 0x4fd19e4fUL, 0xdc7fa3dcUL, 0x22664422UL, 0x2a7e542aUL, 0x90ab3b90UL, 0x88830b88UL, + 0x46ca8c46UL, 0xee29c7eeUL, 0xb8d36bb8UL, 0x143c2814UL, 0xde79a7deUL, 0x5ee2bc5eUL, 0x0b1d160bUL, 0xdb76addbUL, + 0xe03bdbe0UL, 0x32566432UL, 0x3a4e743aUL, 0x0a1e140aUL, 0x49db9249UL, 0x060a0c06UL, 0x246c4824UL, 0x5ce4b85cUL, + 0xc25d9fc2UL, 0xd36ebdd3UL, 0xacef43acUL, 0x62a6c462UL, 0x91a83991UL, 0x95a43195UL, 0xe437d3e4UL, 0x798bf279UL, + 0xe732d5e7UL, 0xc8438bc8UL, 0x37596e37UL, 0x6db7da6dUL, 0x8d8c018dUL, 0xd564b1d5UL, 0x4ed29c4eUL, 0xa9e049a9UL, + 0x6cb4d86cUL, 0x56faac56UL, 0xf407f3f4UL, 0xea25cfeaUL, 0x65afca65UL, 0x7a8ef47aUL, 0xaee947aeUL, 0x08181008UL, + 0xbad56fbaUL, 0x7888f078UL, 0x256f4a25UL, 0x2e725c2eUL, 0x1c24381cUL, 0xa6f157a6UL, 0xb4c773b4UL, 0xc65197c6UL, + 0xe823cbe8UL, 0xdd7ca1ddUL, 0x749ce874UL, 0x1f213e1fUL, 0x4bdd964bUL, 0xbddc61bdUL, 0x8b860d8bUL, 0x8a850f8aUL, + 0x7090e070UL, 0x3e427c3eUL, 0xb5c471b5UL, 0x66aacc66UL, 0x48d89048UL, 0x03050603UL, 0xf601f7f6UL, 0x0e121c0eUL, + 0x61a3c261UL, 0x355f6a35UL, 0x57f9ae57UL, 0xb9d069b9UL, 0x86911786UL, 0xc15899c1UL, 0x1d273a1dUL, 0x9eb9279eUL, + 0xe138d9e1UL, 0xf813ebf8UL, 0x98b32b98UL, 0x11332211UL, 0x69bbd269UL, 0xd970a9d9UL, 0x8e89078eUL, 0x94a73394UL, + 0x9bb62d9bUL, 0x1e223c1eUL, 0x87921587UL, 0xe920c9e9UL, 0xce4987ceUL, 0x55ffaa55UL, 0x28785028UL, 0xdf7aa5dfUL, + 0x8c8f038cUL, 0xa1f859a1UL, 0x89800989UL, 0x0d171a0dUL, 0xbfda65bfUL, 0xe631d7e6UL, 0x42c68442UL, 0x68b8d068UL, + 0x41c38241UL, 0x99b02999UL, 0x2d775a2dUL, 0x0f111e0fUL, 0xb0cb7bb0UL, 0x54fca854UL, 0xbbd66dbbUL, 0x163a2c16UL, +}; - if( 0 == i % Context->KeySizeInWords ) - { - // This function shifts the 4 bytes in a word to the left once. - // [a0,a1,a2,a3] becomes [a1,a2,a3,a0] - k = temp[0]; - temp[0] = temp[1]; - temp[1] = temp[2]; - temp[2] = temp[3]; - temp[3] = k; +static const uint32_t TE3[256] = +{ + 0x6363a5c6UL, 0x7c7c84f8UL, 0x777799eeUL, 0x7b7b8df6UL, 0xf2f20dffUL, 0x6b6bbdd6UL, 0x6f6fb1deUL, 0xc5c55491UL, + 0x30305060UL, 0x01010302UL, 0x6767a9ceUL, 0x2b2b7d56UL, 0xfefe19e7UL, 0xd7d762b5UL, 0xababe64dUL, 0x76769aecUL, + 0xcaca458fUL, 0x82829d1fUL, 0xc9c94089UL, 0x7d7d87faUL, 0xfafa15efUL, 0x5959ebb2UL, 0x4747c98eUL, 0xf0f00bfbUL, + 0xadadec41UL, 0xd4d467b3UL, 0xa2a2fd5fUL, 0xafafea45UL, 0x9c9cbf23UL, 0xa4a4f753UL, 0x727296e4UL, 0xc0c05b9bUL, + 0xb7b7c275UL, 0xfdfd1ce1UL, 0x9393ae3dUL, 0x26266a4cUL, 0x36365a6cUL, 0x3f3f417eUL, 0xf7f702f5UL, 0xcccc4f83UL, + 0x34345c68UL, 0xa5a5f451UL, 0xe5e534d1UL, 0xf1f108f9UL, 0x717193e2UL, 0xd8d873abUL, 0x31315362UL, 0x15153f2aUL, + 0x04040c08UL, 0xc7c75295UL, 0x23236546UL, 0xc3c35e9dUL, 0x18182830UL, 0x9696a137UL, 0x05050f0aUL, 0x9a9ab52fUL, + 0x0707090eUL, 0x12123624UL, 0x80809b1bUL, 0xe2e23ddfUL, 0xebeb26cdUL, 0x2727694eUL, 0xb2b2cd7fUL, 0x75759feaUL, + 0x09091b12UL, 0x83839e1dUL, 0x2c2c7458UL, 0x1a1a2e34UL, 0x1b1b2d36UL, 0x6e6eb2dcUL, 0x5a5aeeb4UL, 0xa0a0fb5bUL, + 0x5252f6a4UL, 0x3b3b4d76UL, 0xd6d661b7UL, 0xb3b3ce7dUL, 0x29297b52UL, 0xe3e33eddUL, 0x2f2f715eUL, 0x84849713UL, + 0x5353f5a6UL, 0xd1d168b9UL, 0x00000000UL, 0xeded2cc1UL, 0x20206040UL, 0xfcfc1fe3UL, 0xb1b1c879UL, 0x5b5bedb6UL, + 0x6a6abed4UL, 0xcbcb468dUL, 0xbebed967UL, 0x39394b72UL, 0x4a4ade94UL, 0x4c4cd498UL, 0x5858e8b0UL, 0xcfcf4a85UL, + 0xd0d06bbbUL, 0xefef2ac5UL, 0xaaaae54fUL, 0xfbfb16edUL, 0x4343c586UL, 0x4d4dd79aUL, 0x33335566UL, 0x85859411UL, + 0x4545cf8aUL, 0xf9f910e9UL, 0x02020604UL, 0x7f7f81feUL, 0x5050f0a0UL, 0x3c3c4478UL, 0x9f9fba25UL, 0xa8a8e34bUL, + 0x5151f3a2UL, 0xa3a3fe5dUL, 0x4040c080UL, 0x8f8f8a05UL, 0x9292ad3fUL, 0x9d9dbc21UL, 0x38384870UL, 0xf5f504f1UL, + 0xbcbcdf63UL, 0xb6b6c177UL, 0xdada75afUL, 0x21216342UL, 0x10103020UL, 0xffff1ae5UL, 0xf3f30efdUL, 0xd2d26dbfUL, + 0xcdcd4c81UL, 0x0c0c1418UL, 0x13133526UL, 0xecec2fc3UL, 0x5f5fe1beUL, 0x9797a235UL, 0x4444cc88UL, 0x1717392eUL, + 0xc4c45793UL, 0xa7a7f255UL, 0x7e7e82fcUL, 0x3d3d477aUL, 0x6464acc8UL, 0x5d5de7baUL, 0x19192b32UL, 0x737395e6UL, + 0x6060a0c0UL, 0x81819819UL, 0x4f4fd19eUL, 0xdcdc7fa3UL, 0x22226644UL, 0x2a2a7e54UL, 0x9090ab3bUL, 0x8888830bUL, + 0x4646ca8cUL, 0xeeee29c7UL, 0xb8b8d36bUL, 0x14143c28UL, 0xdede79a7UL, 0x5e5ee2bcUL, 0x0b0b1d16UL, 0xdbdb76adUL, + 0xe0e03bdbUL, 0x32325664UL, 0x3a3a4e74UL, 0x0a0a1e14UL, 0x4949db92UL, 0x06060a0cUL, 0x24246c48UL, 0x5c5ce4b8UL, + 0xc2c25d9fUL, 0xd3d36ebdUL, 0xacacef43UL, 0x6262a6c4UL, 0x9191a839UL, 0x9595a431UL, 0xe4e437d3UL, 0x79798bf2UL, + 0xe7e732d5UL, 0xc8c8438bUL, 0x3737596eUL, 0x6d6db7daUL, 0x8d8d8c01UL, 0xd5d564b1UL, 0x4e4ed29cUL, 0xa9a9e049UL, + 0x6c6cb4d8UL, 0x5656faacUL, 0xf4f407f3UL, 0xeaea25cfUL, 0x6565afcaUL, 0x7a7a8ef4UL, 0xaeaee947UL, 0x08081810UL, + 0xbabad56fUL, 0x787888f0UL, 0x25256f4aUL, 0x2e2e725cUL, 0x1c1c2438UL, 0xa6a6f157UL, 0xb4b4c773UL, 0xc6c65197UL, + 0xe8e823cbUL, 0xdddd7ca1UL, 0x74749ce8UL, 0x1f1f213eUL, 0x4b4bdd96UL, 0xbdbddc61UL, 0x8b8b860dUL, 0x8a8a850fUL, + 0x707090e0UL, 0x3e3e427cUL, 0xb5b5c471UL, 0x6666aaccUL, 0x4848d890UL, 0x03030506UL, 0xf6f601f7UL, 0x0e0e121cUL, + 0x6161a3c2UL, 0x35355f6aUL, 0x5757f9aeUL, 0xb9b9d069UL, 0x86869117UL, 0xc1c15899UL, 0x1d1d273aUL, 0x9e9eb927UL, + 0xe1e138d9UL, 0xf8f813ebUL, 0x9898b32bUL, 0x11113322UL, 0x6969bbd2UL, 0xd9d970a9UL, 0x8e8e8907UL, 0x9494a733UL, + 0x9b9bb62dUL, 0x1e1e223cUL, 0x87879215UL, 0xe9e920c9UL, 0xcece4987UL, 0x5555ffaaUL, 0x28287850UL, 0xdfdf7aa5UL, + 0x8c8c8f03UL, 0xa1a1f859UL, 0x89898009UL, 0x0d0d171aUL, 0xbfbfda65UL, 0xe6e631d7UL, 0x4242c684UL, 0x6868b8d0UL, + 0x4141c382UL, 0x9999b029UL, 0x2d2d775aUL, 0x0f0f111eUL, 0xb0b0cb7bUL, 0x5454fca8UL, 0xbbbbd66dUL, 0x16163a2cUL, +}; - // SubWord is a function that takes a four-byte input word and - // applies the S-box to each of the four bytes to produce an output word. - temp[0] = SBOX[temp[0]]; - temp[1] = SBOX[temp[1]]; - temp[2] = SBOX[temp[2]]; - temp[3] = SBOX[temp[3]]; +static const uint32_t Te4_0[] = +{ + 0x00000063UL, 0x0000007cUL, 0x00000077UL, 0x0000007bUL, 0x000000f2UL, 0x0000006bUL, 0x0000006fUL, 0x000000c5UL, + 0x00000030UL, 0x00000001UL, 0x00000067UL, 0x0000002bUL, 0x000000feUL, 0x000000d7UL, 0x000000abUL, 0x00000076UL, + 0x000000caUL, 0x00000082UL, 0x000000c9UL, 0x0000007dUL, 0x000000faUL, 0x00000059UL, 0x00000047UL, 0x000000f0UL, + 0x000000adUL, 0x000000d4UL, 0x000000a2UL, 0x000000afUL, 0x0000009cUL, 0x000000a4UL, 0x00000072UL, 0x000000c0UL, + 0x000000b7UL, 0x000000fdUL, 0x00000093UL, 0x00000026UL, 0x00000036UL, 0x0000003fUL, 0x000000f7UL, 0x000000ccUL, + 0x00000034UL, 0x000000a5UL, 0x000000e5UL, 0x000000f1UL, 0x00000071UL, 0x000000d8UL, 0x00000031UL, 0x00000015UL, + 0x00000004UL, 0x000000c7UL, 0x00000023UL, 0x000000c3UL, 0x00000018UL, 0x00000096UL, 0x00000005UL, 0x0000009aUL, + 0x00000007UL, 0x00000012UL, 0x00000080UL, 0x000000e2UL, 0x000000ebUL, 0x00000027UL, 0x000000b2UL, 0x00000075UL, + 0x00000009UL, 0x00000083UL, 0x0000002cUL, 0x0000001aUL, 0x0000001bUL, 0x0000006eUL, 0x0000005aUL, 0x000000a0UL, + 0x00000052UL, 0x0000003bUL, 0x000000d6UL, 0x000000b3UL, 0x00000029UL, 0x000000e3UL, 0x0000002fUL, 0x00000084UL, + 0x00000053UL, 0x000000d1UL, 0x00000000UL, 0x000000edUL, 0x00000020UL, 0x000000fcUL, 0x000000b1UL, 0x0000005bUL, + 0x0000006aUL, 0x000000cbUL, 0x000000beUL, 0x00000039UL, 0x0000004aUL, 0x0000004cUL, 0x00000058UL, 0x000000cfUL, + 0x000000d0UL, 0x000000efUL, 0x000000aaUL, 0x000000fbUL, 0x00000043UL, 0x0000004dUL, 0x00000033UL, 0x00000085UL, + 0x00000045UL, 0x000000f9UL, 0x00000002UL, 0x0000007fUL, 0x00000050UL, 0x0000003cUL, 0x0000009fUL, 0x000000a8UL, + 0x00000051UL, 0x000000a3UL, 0x00000040UL, 0x0000008fUL, 0x00000092UL, 0x0000009dUL, 0x00000038UL, 0x000000f5UL, + 0x000000bcUL, 0x000000b6UL, 0x000000daUL, 0x00000021UL, 0x00000010UL, 0x000000ffUL, 0x000000f3UL, 0x000000d2UL, + 0x000000cdUL, 0x0000000cUL, 0x00000013UL, 0x000000ecUL, 0x0000005fUL, 0x00000097UL, 0x00000044UL, 0x00000017UL, + 0x000000c4UL, 0x000000a7UL, 0x0000007eUL, 0x0000003dUL, 0x00000064UL, 0x0000005dUL, 0x00000019UL, 0x00000073UL, + 0x00000060UL, 0x00000081UL, 0x0000004fUL, 0x000000dcUL, 0x00000022UL, 0x0000002aUL, 0x00000090UL, 0x00000088UL, + 0x00000046UL, 0x000000eeUL, 0x000000b8UL, 0x00000014UL, 0x000000deUL, 0x0000005eUL, 0x0000000bUL, 0x000000dbUL, + 0x000000e0UL, 0x00000032UL, 0x0000003aUL, 0x0000000aUL, 0x00000049UL, 0x00000006UL, 0x00000024UL, 0x0000005cUL, + 0x000000c2UL, 0x000000d3UL, 0x000000acUL, 0x00000062UL, 0x00000091UL, 0x00000095UL, 0x000000e4UL, 0x00000079UL, + 0x000000e7UL, 0x000000c8UL, 0x00000037UL, 0x0000006dUL, 0x0000008dUL, 0x000000d5UL, 0x0000004eUL, 0x000000a9UL, + 0x0000006cUL, 0x00000056UL, 0x000000f4UL, 0x000000eaUL, 0x00000065UL, 0x0000007aUL, 0x000000aeUL, 0x00000008UL, + 0x000000baUL, 0x00000078UL, 0x00000025UL, 0x0000002eUL, 0x0000001cUL, 0x000000a6UL, 0x000000b4UL, 0x000000c6UL, + 0x000000e8UL, 0x000000ddUL, 0x00000074UL, 0x0000001fUL, 0x0000004bUL, 0x000000bdUL, 0x0000008bUL, 0x0000008aUL, + 0x00000070UL, 0x0000003eUL, 0x000000b5UL, 0x00000066UL, 0x00000048UL, 0x00000003UL, 0x000000f6UL, 0x0000000eUL, + 0x00000061UL, 0x00000035UL, 0x00000057UL, 0x000000b9UL, 0x00000086UL, 0x000000c1UL, 0x0000001dUL, 0x0000009eUL, + 0x000000e1UL, 0x000000f8UL, 0x00000098UL, 0x00000011UL, 0x00000069UL, 0x000000d9UL, 0x0000008eUL, 0x00000094UL, + 0x0000009bUL, 0x0000001eUL, 0x00000087UL, 0x000000e9UL, 0x000000ceUL, 0x00000055UL, 0x00000028UL, 0x000000dfUL, + 0x0000008cUL, 0x000000a1UL, 0x00000089UL, 0x0000000dUL, 0x000000bfUL, 0x000000e6UL, 0x00000042UL, 0x00000068UL, + 0x00000041UL, 0x00000099UL, 0x0000002dUL, 0x0000000fUL, 0x000000b0UL, 0x00000054UL, 0x000000bbUL, 0x00000016UL +}; - temp[0] = temp[0] ^ RCON[i/Context->KeySizeInWords]; - } +static const uint32_t Te4_1[] = +{ + 0x00006300UL, 0x00007c00UL, 0x00007700UL, 0x00007b00UL, 0x0000f200UL, 0x00006b00UL, 0x00006f00UL, 0x0000c500UL, + 0x00003000UL, 0x00000100UL, 0x00006700UL, 0x00002b00UL, 0x0000fe00UL, 0x0000d700UL, 0x0000ab00UL, 0x00007600UL, + 0x0000ca00UL, 0x00008200UL, 0x0000c900UL, 0x00007d00UL, 0x0000fa00UL, 0x00005900UL, 0x00004700UL, 0x0000f000UL, + 0x0000ad00UL, 0x0000d400UL, 0x0000a200UL, 0x0000af00UL, 0x00009c00UL, 0x0000a400UL, 0x00007200UL, 0x0000c000UL, + 0x0000b700UL, 0x0000fd00UL, 0x00009300UL, 0x00002600UL, 0x00003600UL, 0x00003f00UL, 0x0000f700UL, 0x0000cc00UL, + 0x00003400UL, 0x0000a500UL, 0x0000e500UL, 0x0000f100UL, 0x00007100UL, 0x0000d800UL, 0x00003100UL, 0x00001500UL, + 0x00000400UL, 0x0000c700UL, 0x00002300UL, 0x0000c300UL, 0x00001800UL, 0x00009600UL, 0x00000500UL, 0x00009a00UL, + 0x00000700UL, 0x00001200UL, 0x00008000UL, 0x0000e200UL, 0x0000eb00UL, 0x00002700UL, 0x0000b200UL, 0x00007500UL, + 0x00000900UL, 0x00008300UL, 0x00002c00UL, 0x00001a00UL, 0x00001b00UL, 0x00006e00UL, 0x00005a00UL, 0x0000a000UL, + 0x00005200UL, 0x00003b00UL, 0x0000d600UL, 0x0000b300UL, 0x00002900UL, 0x0000e300UL, 0x00002f00UL, 0x00008400UL, + 0x00005300UL, 0x0000d100UL, 0x00000000UL, 0x0000ed00UL, 0x00002000UL, 0x0000fc00UL, 0x0000b100UL, 0x00005b00UL, + 0x00006a00UL, 0x0000cb00UL, 0x0000be00UL, 0x00003900UL, 0x00004a00UL, 0x00004c00UL, 0x00005800UL, 0x0000cf00UL, + 0x0000d000UL, 0x0000ef00UL, 0x0000aa00UL, 0x0000fb00UL, 0x00004300UL, 0x00004d00UL, 0x00003300UL, 0x00008500UL, + 0x00004500UL, 0x0000f900UL, 0x00000200UL, 0x00007f00UL, 0x00005000UL, 0x00003c00UL, 0x00009f00UL, 0x0000a800UL, + 0x00005100UL, 0x0000a300UL, 0x00004000UL, 0x00008f00UL, 0x00009200UL, 0x00009d00UL, 0x00003800UL, 0x0000f500UL, + 0x0000bc00UL, 0x0000b600UL, 0x0000da00UL, 0x00002100UL, 0x00001000UL, 0x0000ff00UL, 0x0000f300UL, 0x0000d200UL, + 0x0000cd00UL, 0x00000c00UL, 0x00001300UL, 0x0000ec00UL, 0x00005f00UL, 0x00009700UL, 0x00004400UL, 0x00001700UL, + 0x0000c400UL, 0x0000a700UL, 0x00007e00UL, 0x00003d00UL, 0x00006400UL, 0x00005d00UL, 0x00001900UL, 0x00007300UL, + 0x00006000UL, 0x00008100UL, 0x00004f00UL, 0x0000dc00UL, 0x00002200UL, 0x00002a00UL, 0x00009000UL, 0x00008800UL, + 0x00004600UL, 0x0000ee00UL, 0x0000b800UL, 0x00001400UL, 0x0000de00UL, 0x00005e00UL, 0x00000b00UL, 0x0000db00UL, + 0x0000e000UL, 0x00003200UL, 0x00003a00UL, 0x00000a00UL, 0x00004900UL, 0x00000600UL, 0x00002400UL, 0x00005c00UL, + 0x0000c200UL, 0x0000d300UL, 0x0000ac00UL, 0x00006200UL, 0x00009100UL, 0x00009500UL, 0x0000e400UL, 0x00007900UL, + 0x0000e700UL, 0x0000c800UL, 0x00003700UL, 0x00006d00UL, 0x00008d00UL, 0x0000d500UL, 0x00004e00UL, 0x0000a900UL, + 0x00006c00UL, 0x00005600UL, 0x0000f400UL, 0x0000ea00UL, 0x00006500UL, 0x00007a00UL, 0x0000ae00UL, 0x00000800UL, + 0x0000ba00UL, 0x00007800UL, 0x00002500UL, 0x00002e00UL, 0x00001c00UL, 0x0000a600UL, 0x0000b400UL, 0x0000c600UL, + 0x0000e800UL, 0x0000dd00UL, 0x00007400UL, 0x00001f00UL, 0x00004b00UL, 0x0000bd00UL, 0x00008b00UL, 0x00008a00UL, + 0x00007000UL, 0x00003e00UL, 0x0000b500UL, 0x00006600UL, 0x00004800UL, 0x00000300UL, 0x0000f600UL, 0x00000e00UL, + 0x00006100UL, 0x00003500UL, 0x00005700UL, 0x0000b900UL, 0x00008600UL, 0x0000c100UL, 0x00001d00UL, 0x00009e00UL, + 0x0000e100UL, 0x0000f800UL, 0x00009800UL, 0x00001100UL, 0x00006900UL, 0x0000d900UL, 0x00008e00UL, 0x00009400UL, + 0x00009b00UL, 0x00001e00UL, 0x00008700UL, 0x0000e900UL, 0x0000ce00UL, 0x00005500UL, 0x00002800UL, 0x0000df00UL, + 0x00008c00UL, 0x0000a100UL, 0x00008900UL, 0x00000d00UL, 0x0000bf00UL, 0x0000e600UL, 0x00004200UL, 0x00006800UL, + 0x00004100UL, 0x00009900UL, 0x00002d00UL, 0x00000f00UL, 0x0000b000UL, 0x00005400UL, 0x0000bb00UL, 0x00001600UL +}; - if( AES_KEY_SIZE_256/4 == Context->KeySizeInWords ) - { - // Only performed with 256 bit sized keys - if( 4 == i % Context->KeySizeInWords ) - { - // Function Subword() - temp[0] = SBOX[temp[0]]; - temp[1] = SBOX[temp[1]]; - temp[2] = SBOX[temp[2]]; - temp[3] = SBOX[temp[3]]; - } - } +static const uint32_t Te4_2[] = +{ + 0x00630000UL, 0x007c0000UL, 0x00770000UL, 0x007b0000UL, 0x00f20000UL, 0x006b0000UL, 0x006f0000UL, 0x00c50000UL, + 0x00300000UL, 0x00010000UL, 0x00670000UL, 0x002b0000UL, 0x00fe0000UL, 0x00d70000UL, 0x00ab0000UL, 0x00760000UL, + 0x00ca0000UL, 0x00820000UL, 0x00c90000UL, 0x007d0000UL, 0x00fa0000UL, 0x00590000UL, 0x00470000UL, 0x00f00000UL, + 0x00ad0000UL, 0x00d40000UL, 0x00a20000UL, 0x00af0000UL, 0x009c0000UL, 0x00a40000UL, 0x00720000UL, 0x00c00000UL, + 0x00b70000UL, 0x00fd0000UL, 0x00930000UL, 0x00260000UL, 0x00360000UL, 0x003f0000UL, 0x00f70000UL, 0x00cc0000UL, + 0x00340000UL, 0x00a50000UL, 0x00e50000UL, 0x00f10000UL, 0x00710000UL, 0x00d80000UL, 0x00310000UL, 0x00150000UL, + 0x00040000UL, 0x00c70000UL, 0x00230000UL, 0x00c30000UL, 0x00180000UL, 0x00960000UL, 0x00050000UL, 0x009a0000UL, + 0x00070000UL, 0x00120000UL, 0x00800000UL, 0x00e20000UL, 0x00eb0000UL, 0x00270000UL, 0x00b20000UL, 0x00750000UL, + 0x00090000UL, 0x00830000UL, 0x002c0000UL, 0x001a0000UL, 0x001b0000UL, 0x006e0000UL, 0x005a0000UL, 0x00a00000UL, + 0x00520000UL, 0x003b0000UL, 0x00d60000UL, 0x00b30000UL, 0x00290000UL, 0x00e30000UL, 0x002f0000UL, 0x00840000UL, + 0x00530000UL, 0x00d10000UL, 0x00000000UL, 0x00ed0000UL, 0x00200000UL, 0x00fc0000UL, 0x00b10000UL, 0x005b0000UL, + 0x006a0000UL, 0x00cb0000UL, 0x00be0000UL, 0x00390000UL, 0x004a0000UL, 0x004c0000UL, 0x00580000UL, 0x00cf0000UL, + 0x00d00000UL, 0x00ef0000UL, 0x00aa0000UL, 0x00fb0000UL, 0x00430000UL, 0x004d0000UL, 0x00330000UL, 0x00850000UL, + 0x00450000UL, 0x00f90000UL, 0x00020000UL, 0x007f0000UL, 0x00500000UL, 0x003c0000UL, 0x009f0000UL, 0x00a80000UL, + 0x00510000UL, 0x00a30000UL, 0x00400000UL, 0x008f0000UL, 0x00920000UL, 0x009d0000UL, 0x00380000UL, 0x00f50000UL, + 0x00bc0000UL, 0x00b60000UL, 0x00da0000UL, 0x00210000UL, 0x00100000UL, 0x00ff0000UL, 0x00f30000UL, 0x00d20000UL, + 0x00cd0000UL, 0x000c0000UL, 0x00130000UL, 0x00ec0000UL, 0x005f0000UL, 0x00970000UL, 0x00440000UL, 0x00170000UL, + 0x00c40000UL, 0x00a70000UL, 0x007e0000UL, 0x003d0000UL, 0x00640000UL, 0x005d0000UL, 0x00190000UL, 0x00730000UL, + 0x00600000UL, 0x00810000UL, 0x004f0000UL, 0x00dc0000UL, 0x00220000UL, 0x002a0000UL, 0x00900000UL, 0x00880000UL, + 0x00460000UL, 0x00ee0000UL, 0x00b80000UL, 0x00140000UL, 0x00de0000UL, 0x005e0000UL, 0x000b0000UL, 0x00db0000UL, + 0x00e00000UL, 0x00320000UL, 0x003a0000UL, 0x000a0000UL, 0x00490000UL, 0x00060000UL, 0x00240000UL, 0x005c0000UL, + 0x00c20000UL, 0x00d30000UL, 0x00ac0000UL, 0x00620000UL, 0x00910000UL, 0x00950000UL, 0x00e40000UL, 0x00790000UL, + 0x00e70000UL, 0x00c80000UL, 0x00370000UL, 0x006d0000UL, 0x008d0000UL, 0x00d50000UL, 0x004e0000UL, 0x00a90000UL, + 0x006c0000UL, 0x00560000UL, 0x00f40000UL, 0x00ea0000UL, 0x00650000UL, 0x007a0000UL, 0x00ae0000UL, 0x00080000UL, + 0x00ba0000UL, 0x00780000UL, 0x00250000UL, 0x002e0000UL, 0x001c0000UL, 0x00a60000UL, 0x00b40000UL, 0x00c60000UL, + 0x00e80000UL, 0x00dd0000UL, 0x00740000UL, 0x001f0000UL, 0x004b0000UL, 0x00bd0000UL, 0x008b0000UL, 0x008a0000UL, + 0x00700000UL, 0x003e0000UL, 0x00b50000UL, 0x00660000UL, 0x00480000UL, 0x00030000UL, 0x00f60000UL, 0x000e0000UL, + 0x00610000UL, 0x00350000UL, 0x00570000UL, 0x00b90000UL, 0x00860000UL, 0x00c10000UL, 0x001d0000UL, 0x009e0000UL, + 0x00e10000UL, 0x00f80000UL, 0x00980000UL, 0x00110000UL, 0x00690000UL, 0x00d90000UL, 0x008e0000UL, 0x00940000UL, + 0x009b0000UL, 0x001e0000UL, 0x00870000UL, 0x00e90000UL, 0x00ce0000UL, 0x00550000UL, 0x00280000UL, 0x00df0000UL, + 0x008c0000UL, 0x00a10000UL, 0x00890000UL, 0x000d0000UL, 0x00bf0000UL, 0x00e60000UL, 0x00420000UL, 0x00680000UL, + 0x00410000UL, 0x00990000UL, 0x002d0000UL, 0x000f0000UL, 0x00b00000UL, 0x00540000UL, 0x00bb0000UL, 0x00160000UL +}; - Context->RoundKey[i*4 + 0] = Context->RoundKey[(i-Context->KeySizeInWords)*4 + 0] ^ temp[0]; - Context->RoundKey[i*4 + 1] = Context->RoundKey[(i-Context->KeySizeInWords)*4 + 1] ^ temp[1]; - Context->RoundKey[i*4 + 2] = Context->RoundKey[(i-Context->KeySizeInWords)*4 + 2] ^ temp[2]; - Context->RoundKey[i*4 + 3] = Context->RoundKey[(i-Context->KeySizeInWords)*4 + 3] ^ temp[3]; - } +static const uint32_t Te4_3[] = +{ + 0x63000000UL, 0x7c000000UL, 0x77000000UL, 0x7b000000UL, 0xf2000000UL, 0x6b000000UL, 0x6f000000UL, 0xc5000000UL, + 0x30000000UL, 0x01000000UL, 0x67000000UL, 0x2b000000UL, 0xfe000000UL, 0xd7000000UL, 0xab000000UL, 0x76000000UL, + 0xca000000UL, 0x82000000UL, 0xc9000000UL, 0x7d000000UL, 0xfa000000UL, 0x59000000UL, 0x47000000UL, 0xf0000000UL, + 0xad000000UL, 0xd4000000UL, 0xa2000000UL, 0xaf000000UL, 0x9c000000UL, 0xa4000000UL, 0x72000000UL, 0xc0000000UL, + 0xb7000000UL, 0xfd000000UL, 0x93000000UL, 0x26000000UL, 0x36000000UL, 0x3f000000UL, 0xf7000000UL, 0xcc000000UL, + 0x34000000UL, 0xa5000000UL, 0xe5000000UL, 0xf1000000UL, 0x71000000UL, 0xd8000000UL, 0x31000000UL, 0x15000000UL, + 0x04000000UL, 0xc7000000UL, 0x23000000UL, 0xc3000000UL, 0x18000000UL, 0x96000000UL, 0x05000000UL, 0x9a000000UL, + 0x07000000UL, 0x12000000UL, 0x80000000UL, 0xe2000000UL, 0xeb000000UL, 0x27000000UL, 0xb2000000UL, 0x75000000UL, + 0x09000000UL, 0x83000000UL, 0x2c000000UL, 0x1a000000UL, 0x1b000000UL, 0x6e000000UL, 0x5a000000UL, 0xa0000000UL, + 0x52000000UL, 0x3b000000UL, 0xd6000000UL, 0xb3000000UL, 0x29000000UL, 0xe3000000UL, 0x2f000000UL, 0x84000000UL, + 0x53000000UL, 0xd1000000UL, 0x00000000UL, 0xed000000UL, 0x20000000UL, 0xfc000000UL, 0xb1000000UL, 0x5b000000UL, + 0x6a000000UL, 0xcb000000UL, 0xbe000000UL, 0x39000000UL, 0x4a000000UL, 0x4c000000UL, 0x58000000UL, 0xcf000000UL, + 0xd0000000UL, 0xef000000UL, 0xaa000000UL, 0xfb000000UL, 0x43000000UL, 0x4d000000UL, 0x33000000UL, 0x85000000UL, + 0x45000000UL, 0xf9000000UL, 0x02000000UL, 0x7f000000UL, 0x50000000UL, 0x3c000000UL, 0x9f000000UL, 0xa8000000UL, + 0x51000000UL, 0xa3000000UL, 0x40000000UL, 0x8f000000UL, 0x92000000UL, 0x9d000000UL, 0x38000000UL, 0xf5000000UL, + 0xbc000000UL, 0xb6000000UL, 0xda000000UL, 0x21000000UL, 0x10000000UL, 0xff000000UL, 0xf3000000UL, 0xd2000000UL, + 0xcd000000UL, 0x0c000000UL, 0x13000000UL, 0xec000000UL, 0x5f000000UL, 0x97000000UL, 0x44000000UL, 0x17000000UL, + 0xc4000000UL, 0xa7000000UL, 0x7e000000UL, 0x3d000000UL, 0x64000000UL, 0x5d000000UL, 0x19000000UL, 0x73000000UL, + 0x60000000UL, 0x81000000UL, 0x4f000000UL, 0xdc000000UL, 0x22000000UL, 0x2a000000UL, 0x90000000UL, 0x88000000UL, + 0x46000000UL, 0xee000000UL, 0xb8000000UL, 0x14000000UL, 0xde000000UL, 0x5e000000UL, 0x0b000000UL, 0xdb000000UL, + 0xe0000000UL, 0x32000000UL, 0x3a000000UL, 0x0a000000UL, 0x49000000UL, 0x06000000UL, 0x24000000UL, 0x5c000000UL, + 0xc2000000UL, 0xd3000000UL, 0xac000000UL, 0x62000000UL, 0x91000000UL, 0x95000000UL, 0xe4000000UL, 0x79000000UL, + 0xe7000000UL, 0xc8000000UL, 0x37000000UL, 0x6d000000UL, 0x8d000000UL, 0xd5000000UL, 0x4e000000UL, 0xa9000000UL, + 0x6c000000UL, 0x56000000UL, 0xf4000000UL, 0xea000000UL, 0x65000000UL, 0x7a000000UL, 0xae000000UL, 0x08000000UL, + 0xba000000UL, 0x78000000UL, 0x25000000UL, 0x2e000000UL, 0x1c000000UL, 0xa6000000UL, 0xb4000000UL, 0xc6000000UL, + 0xe8000000UL, 0xdd000000UL, 0x74000000UL, 0x1f000000UL, 0x4b000000UL, 0xbd000000UL, 0x8b000000UL, 0x8a000000UL, + 0x70000000UL, 0x3e000000UL, 0xb5000000UL, 0x66000000UL, 0x48000000UL, 0x03000000UL, 0xf6000000UL, 0x0e000000UL, + 0x61000000UL, 0x35000000UL, 0x57000000UL, 0xb9000000UL, 0x86000000UL, 0xc1000000UL, 0x1d000000UL, 0x9e000000UL, + 0xe1000000UL, 0xf8000000UL, 0x98000000UL, 0x11000000UL, 0x69000000UL, 0xd9000000UL, 0x8e000000UL, 0x94000000UL, + 0x9b000000UL, 0x1e000000UL, 0x87000000UL, 0xe9000000UL, 0xce000000UL, 0x55000000UL, 0x28000000UL, 0xdf000000UL, + 0x8c000000UL, 0xa1000000UL, 0x89000000UL, 0x0d000000UL, 0xbf000000UL, 0xe6000000UL, 0x42000000UL, 0x68000000UL, + 0x41000000UL, 0x99000000UL, 0x2d000000UL, 0x0f000000UL, 0xb0000000UL, 0x54000000UL, 0xbb000000UL, 0x16000000UL +}; + +static const uint32_t TD1[256] = +{ + 0x5051f4a7UL, 0x537e4165UL, 0xc31a17a4UL, 0x963a275eUL, 0xcb3bab6bUL, 0xf11f9d45UL, 0xabacfa58UL, 0x934be303UL, + 0x552030faUL, 0xf6ad766dUL, 0x9188cc76UL, 0x25f5024cUL, 0xfc4fe5d7UL, 0xd7c52acbUL, 0x80263544UL, 0x8fb562a3UL, + 0x49deb15aUL, 0x6725ba1bUL, 0x9845ea0eUL, 0xe15dfec0UL, 0x02c32f75UL, 0x12814cf0UL, 0xa38d4697UL, 0xc66bd3f9UL, + 0xe7038f5fUL, 0x9515929cUL, 0xebbf6d7aUL, 0xda955259UL, 0x2dd4be83UL, 0xd3587421UL, 0x2949e069UL, 0x448ec9c8UL, + 0x6a75c289UL, 0x78f48e79UL, 0x6b99583eUL, 0xdd27b971UL, 0xb6bee14fUL, 0x17f088adUL, 0x66c920acUL, 0xb47dce3aUL, + 0x1863df4aUL, 0x82e51a31UL, 0x60975133UL, 0x4562537fUL, 0xe0b16477UL, 0x84bb6baeUL, 0x1cfe81a0UL, 0x94f9082bUL, + 0x58704868UL, 0x198f45fdUL, 0x8794de6cUL, 0xb7527bf8UL, 0x23ab73d3UL, 0xe2724b02UL, 0x57e31f8fUL, 0x2a6655abUL, + 0x07b2eb28UL, 0x032fb5c2UL, 0x9a86c57bUL, 0xa5d33708UL, 0xf2302887UL, 0xb223bfa5UL, 0xba02036aUL, 0x5ced1682UL, + 0x2b8acf1cUL, 0x92a779b4UL, 0xf0f307f2UL, 0xa14e69e2UL, 0xcd65daf4UL, 0xd50605beUL, 0x1fd13462UL, 0x8ac4a6feUL, + 0x9d342e53UL, 0xa0a2f355UL, 0x32058ae1UL, 0x75a4f6ebUL, 0x390b83ecUL, 0xaa4060efUL, 0x065e719fUL, 0x51bd6e10UL, + 0xf93e218aUL, 0x3d96dd06UL, 0xaedd3e05UL, 0x464de6bdUL, 0xb591548dUL, 0x0571c45dUL, 0x6f0406d4UL, 0xff605015UL, + 0x241998fbUL, 0x97d6bde9UL, 0xcc894043UL, 0x7767d99eUL, 0xbdb0e842UL, 0x8807898bUL, 0x38e7195bUL, 0xdb79c8eeUL, + 0x47a17c0aUL, 0xe97c420fUL, 0xc9f8841eUL, 0x00000000UL, 0x83098086UL, 0x48322bedUL, 0xac1e1170UL, 0x4e6c5a72UL, + 0xfbfd0effUL, 0x560f8538UL, 0x1e3daed5UL, 0x27362d39UL, 0x640a0fd9UL, 0x21685ca6UL, 0xd19b5b54UL, 0x3a24362eUL, + 0xb10c0a67UL, 0x0f9357e7UL, 0xd2b4ee96UL, 0x9e1b9b91UL, 0x4f80c0c5UL, 0xa261dc20UL, 0x695a774bUL, 0x161c121aUL, + 0x0ae293baUL, 0xe5c0a02aUL, 0x433c22e0UL, 0x1d121b17UL, 0x0b0e090dUL, 0xadf28bc7UL, 0xb92db6a8UL, 0xc8141ea9UL, + 0x8557f119UL, 0x4caf7507UL, 0xbbee99ddUL, 0xfda37f60UL, 0x9ff70126UL, 0xbc5c72f5UL, 0xc544663bUL, 0x345bfb7eUL, + 0x768b4329UL, 0xdccb23c6UL, 0x68b6edfcUL, 0x63b8e4f1UL, 0xcad731dcUL, 0x10426385UL, 0x40139722UL, 0x2084c611UL, + 0x7d854a24UL, 0xf8d2bb3dUL, 0x11aef932UL, 0x6dc729a1UL, 0x4b1d9e2fUL, 0xf3dcb230UL, 0xec0d8652UL, 0xd077c1e3UL, + 0x6c2bb316UL, 0x99a970b9UL, 0xfa119448UL, 0x2247e964UL, 0xc4a8fc8cUL, 0x1aa0f03fUL, 0xd8567d2cUL, 0xef223390UL, + 0xc787494eUL, 0xc1d938d1UL, 0xfe8ccaa2UL, 0x3698d40bUL, 0xcfa6f581UL, 0x28a57adeUL, 0x26dab78eUL, 0xa43fadbfUL, + 0xe42c3a9dUL, 0x0d507892UL, 0x9b6a5fccUL, 0x62547e46UL, 0xc2f68d13UL, 0xe890d8b8UL, 0x5e2e39f7UL, 0xf582c3afUL, + 0xbe9f5d80UL, 0x7c69d093UL, 0xa96fd52dUL, 0xb3cf2512UL, 0x3bc8ac99UL, 0xa710187dUL, 0x6ee89c63UL, 0x7bdb3bbbUL, + 0x09cd2678UL, 0xf46e5918UL, 0x01ec9ab7UL, 0xa8834f9aUL, 0x65e6956eUL, 0x7eaaffe6UL, 0x0821bccfUL, 0xe6ef15e8UL, + 0xd9bae79bUL, 0xce4a6f36UL, 0xd4ea9f09UL, 0xd629b07cUL, 0xaf31a4b2UL, 0x312a3f23UL, 0x30c6a594UL, 0xc035a266UL, + 0x37744ebcUL, 0xa6fc82caUL, 0xb0e090d0UL, 0x1533a7d8UL, 0x4af10498UL, 0xf741ecdaUL, 0x0e7fcd50UL, 0x2f1791f6UL, + 0x8d764dd6UL, 0x4d43efb0UL, 0x54ccaa4dUL, 0xdfe49604UL, 0xe39ed1b5UL, 0x1b4c6a88UL, 0xb8c12c1fUL, 0x7f466551UL, + 0x049d5eeaUL, 0x5d018c35UL, 0x73fa8774UL, 0x2efb0b41UL, 0x5ab3671dUL, 0x5292dbd2UL, 0x33e91056UL, 0x136dd647UL, + 0x8c9ad761UL, 0x7a37a10cUL, 0x8e59f814UL, 0x89eb133cUL, 0xeecea927UL, 0x35b761c9UL, 0xede11ce5UL, 0x3c7a47b1UL, + 0x599cd2dfUL, 0x3f55f273UL, 0x791814ceUL, 0xbf73c737UL, 0xea53f7cdUL, 0x5b5ffdaaUL, 0x14df3d6fUL, 0x867844dbUL, + 0x81caaff3UL, 0x3eb968c4UL, 0x2c382434UL, 0x5fc2a340UL, 0x72161dc3UL, 0x0cbce225UL, 0x8b283c49UL, 0x41ff0d95UL, + 0x7139a801UL, 0xde080cb3UL, 0x9cd8b4e4UL, 0x906456c1UL, 0x617bcb84UL, 0x70d532b6UL, 0x74486c5cUL, 0x42d0b857UL, +}; + +static const uint32_t TD2[256] = +{ + 0xa75051f4UL, 0x65537e41UL, 0xa4c31a17UL, 0x5e963a27UL, 0x6bcb3babUL, 0x45f11f9dUL, 0x58abacfaUL, 0x03934be3UL, + 0xfa552030UL, 0x6df6ad76UL, 0x769188ccUL, 0x4c25f502UL, 0xd7fc4fe5UL, 0xcbd7c52aUL, 0x44802635UL, 0xa38fb562UL, + 0x5a49deb1UL, 0x1b6725baUL, 0x0e9845eaUL, 0xc0e15dfeUL, 0x7502c32fUL, 0xf012814cUL, 0x97a38d46UL, 0xf9c66bd3UL, + 0x5fe7038fUL, 0x9c951592UL, 0x7aebbf6dUL, 0x59da9552UL, 0x832dd4beUL, 0x21d35874UL, 0x692949e0UL, 0xc8448ec9UL, + 0x896a75c2UL, 0x7978f48eUL, 0x3e6b9958UL, 0x71dd27b9UL, 0x4fb6bee1UL, 0xad17f088UL, 0xac66c920UL, 0x3ab47dceUL, + 0x4a1863dfUL, 0x3182e51aUL, 0x33609751UL, 0x7f456253UL, 0x77e0b164UL, 0xae84bb6bUL, 0xa01cfe81UL, 0x2b94f908UL, + 0x68587048UL, 0xfd198f45UL, 0x6c8794deUL, 0xf8b7527bUL, 0xd323ab73UL, 0x02e2724bUL, 0x8f57e31fUL, 0xab2a6655UL, + 0x2807b2ebUL, 0xc2032fb5UL, 0x7b9a86c5UL, 0x08a5d337UL, 0x87f23028UL, 0xa5b223bfUL, 0x6aba0203UL, 0x825ced16UL, + 0x1c2b8acfUL, 0xb492a779UL, 0xf2f0f307UL, 0xe2a14e69UL, 0xf4cd65daUL, 0xbed50605UL, 0x621fd134UL, 0xfe8ac4a6UL, + 0x539d342eUL, 0x55a0a2f3UL, 0xe132058aUL, 0xeb75a4f6UL, 0xec390b83UL, 0xefaa4060UL, 0x9f065e71UL, 0x1051bd6eUL, + 0x8af93e21UL, 0x063d96ddUL, 0x05aedd3eUL, 0xbd464de6UL, 0x8db59154UL, 0x5d0571c4UL, 0xd46f0406UL, 0x15ff6050UL, + 0xfb241998UL, 0xe997d6bdUL, 0x43cc8940UL, 0x9e7767d9UL, 0x42bdb0e8UL, 0x8b880789UL, 0x5b38e719UL, 0xeedb79c8UL, + 0x0a47a17cUL, 0x0fe97c42UL, 0x1ec9f884UL, 0x00000000UL, 0x86830980UL, 0xed48322bUL, 0x70ac1e11UL, 0x724e6c5aUL, + 0xfffbfd0eUL, 0x38560f85UL, 0xd51e3daeUL, 0x3927362dUL, 0xd9640a0fUL, 0xa621685cUL, 0x54d19b5bUL, 0x2e3a2436UL, + 0x67b10c0aUL, 0xe70f9357UL, 0x96d2b4eeUL, 0x919e1b9bUL, 0xc54f80c0UL, 0x20a261dcUL, 0x4b695a77UL, 0x1a161c12UL, + 0xba0ae293UL, 0x2ae5c0a0UL, 0xe0433c22UL, 0x171d121bUL, 0x0d0b0e09UL, 0xc7adf28bUL, 0xa8b92db6UL, 0xa9c8141eUL, + 0x198557f1UL, 0x074caf75UL, 0xddbbee99UL, 0x60fda37fUL, 0x269ff701UL, 0xf5bc5c72UL, 0x3bc54466UL, 0x7e345bfbUL, + 0x29768b43UL, 0xc6dccb23UL, 0xfc68b6edUL, 0xf163b8e4UL, 0xdccad731UL, 0x85104263UL, 0x22401397UL, 0x112084c6UL, + 0x247d854aUL, 0x3df8d2bbUL, 0x3211aef9UL, 0xa16dc729UL, 0x2f4b1d9eUL, 0x30f3dcb2UL, 0x52ec0d86UL, 0xe3d077c1UL, + 0x166c2bb3UL, 0xb999a970UL, 0x48fa1194UL, 0x642247e9UL, 0x8cc4a8fcUL, 0x3f1aa0f0UL, 0x2cd8567dUL, 0x90ef2233UL, + 0x4ec78749UL, 0xd1c1d938UL, 0xa2fe8ccaUL, 0x0b3698d4UL, 0x81cfa6f5UL, 0xde28a57aUL, 0x8e26dab7UL, 0xbfa43fadUL, + 0x9de42c3aUL, 0x920d5078UL, 0xcc9b6a5fUL, 0x4662547eUL, 0x13c2f68dUL, 0xb8e890d8UL, 0xf75e2e39UL, 0xaff582c3UL, + 0x80be9f5dUL, 0x937c69d0UL, 0x2da96fd5UL, 0x12b3cf25UL, 0x993bc8acUL, 0x7da71018UL, 0x636ee89cUL, 0xbb7bdb3bUL, + 0x7809cd26UL, 0x18f46e59UL, 0xb701ec9aUL, 0x9aa8834fUL, 0x6e65e695UL, 0xe67eaaffUL, 0xcf0821bcUL, 0xe8e6ef15UL, + 0x9bd9bae7UL, 0x36ce4a6fUL, 0x09d4ea9fUL, 0x7cd629b0UL, 0xb2af31a4UL, 0x23312a3fUL, 0x9430c6a5UL, 0x66c035a2UL, + 0xbc37744eUL, 0xcaa6fc82UL, 0xd0b0e090UL, 0xd81533a7UL, 0x984af104UL, 0xdaf741ecUL, 0x500e7fcdUL, 0xf62f1791UL, + 0xd68d764dUL, 0xb04d43efUL, 0x4d54ccaaUL, 0x04dfe496UL, 0xb5e39ed1UL, 0x881b4c6aUL, 0x1fb8c12cUL, 0x517f4665UL, + 0xea049d5eUL, 0x355d018cUL, 0x7473fa87UL, 0x412efb0bUL, 0x1d5ab367UL, 0xd25292dbUL, 0x5633e910UL, 0x47136dd6UL, + 0x618c9ad7UL, 0x0c7a37a1UL, 0x148e59f8UL, 0x3c89eb13UL, 0x27eecea9UL, 0xc935b761UL, 0xe5ede11cUL, 0xb13c7a47UL, + 0xdf599cd2UL, 0x733f55f2UL, 0xce791814UL, 0x37bf73c7UL, 0xcdea53f7UL, 0xaa5b5ffdUL, 0x6f14df3dUL, 0xdb867844UL, + 0xf381caafUL, 0xc43eb968UL, 0x342c3824UL, 0x405fc2a3UL, 0xc372161dUL, 0x250cbce2UL, 0x498b283cUL, 0x9541ff0dUL, + 0x017139a8UL, 0xb3de080cUL, 0xe49cd8b4UL, 0xc1906456UL, 0x84617bcbUL, 0xb670d532UL, 0x5c74486cUL, 0x5742d0b8UL, +}; + +static const uint32_t TD3[256] = +{ + 0xf4a75051UL, 0x4165537eUL, 0x17a4c31aUL, 0x275e963aUL, 0xab6bcb3bUL, 0x9d45f11fUL, 0xfa58abacUL, 0xe303934bUL, + 0x30fa5520UL, 0x766df6adUL, 0xcc769188UL, 0x024c25f5UL, 0xe5d7fc4fUL, 0x2acbd7c5UL, 0x35448026UL, 0x62a38fb5UL, + 0xb15a49deUL, 0xba1b6725UL, 0xea0e9845UL, 0xfec0e15dUL, 0x2f7502c3UL, 0x4cf01281UL, 0x4697a38dUL, 0xd3f9c66bUL, + 0x8f5fe703UL, 0x929c9515UL, 0x6d7aebbfUL, 0x5259da95UL, 0xbe832dd4UL, 0x7421d358UL, 0xe0692949UL, 0xc9c8448eUL, + 0xc2896a75UL, 0x8e7978f4UL, 0x583e6b99UL, 0xb971dd27UL, 0xe14fb6beUL, 0x88ad17f0UL, 0x20ac66c9UL, 0xce3ab47dUL, + 0xdf4a1863UL, 0x1a3182e5UL, 0x51336097UL, 0x537f4562UL, 0x6477e0b1UL, 0x6bae84bbUL, 0x81a01cfeUL, 0x082b94f9UL, + 0x48685870UL, 0x45fd198fUL, 0xde6c8794UL, 0x7bf8b752UL, 0x73d323abUL, 0x4b02e272UL, 0x1f8f57e3UL, 0x55ab2a66UL, + 0xeb2807b2UL, 0xb5c2032fUL, 0xc57b9a86UL, 0x3708a5d3UL, 0x2887f230UL, 0xbfa5b223UL, 0x036aba02UL, 0x16825cedUL, + 0xcf1c2b8aUL, 0x79b492a7UL, 0x07f2f0f3UL, 0x69e2a14eUL, 0xdaf4cd65UL, 0x05bed506UL, 0x34621fd1UL, 0xa6fe8ac4UL, + 0x2e539d34UL, 0xf355a0a2UL, 0x8ae13205UL, 0xf6eb75a4UL, 0x83ec390bUL, 0x60efaa40UL, 0x719f065eUL, 0x6e1051bdUL, + 0x218af93eUL, 0xdd063d96UL, 0x3e05aeddUL, 0xe6bd464dUL, 0x548db591UL, 0xc45d0571UL, 0x06d46f04UL, 0x5015ff60UL, + 0x98fb2419UL, 0xbde997d6UL, 0x4043cc89UL, 0xd99e7767UL, 0xe842bdb0UL, 0x898b8807UL, 0x195b38e7UL, 0xc8eedb79UL, + 0x7c0a47a1UL, 0x420fe97cUL, 0x841ec9f8UL, 0x00000000UL, 0x80868309UL, 0x2bed4832UL, 0x1170ac1eUL, 0x5a724e6cUL, + 0x0efffbfdUL, 0x8538560fUL, 0xaed51e3dUL, 0x2d392736UL, 0x0fd9640aUL, 0x5ca62168UL, 0x5b54d19bUL, 0x362e3a24UL, + 0x0a67b10cUL, 0x57e70f93UL, 0xee96d2b4UL, 0x9b919e1bUL, 0xc0c54f80UL, 0xdc20a261UL, 0x774b695aUL, 0x121a161cUL, + 0x93ba0ae2UL, 0xa02ae5c0UL, 0x22e0433cUL, 0x1b171d12UL, 0x090d0b0eUL, 0x8bc7adf2UL, 0xb6a8b92dUL, 0x1ea9c814UL, + 0xf1198557UL, 0x75074cafUL, 0x99ddbbeeUL, 0x7f60fda3UL, 0x01269ff7UL, 0x72f5bc5cUL, 0x663bc544UL, 0xfb7e345bUL, + 0x4329768bUL, 0x23c6dccbUL, 0xedfc68b6UL, 0xe4f163b8UL, 0x31dccad7UL, 0x63851042UL, 0x97224013UL, 0xc6112084UL, + 0x4a247d85UL, 0xbb3df8d2UL, 0xf93211aeUL, 0x29a16dc7UL, 0x9e2f4b1dUL, 0xb230f3dcUL, 0x8652ec0dUL, 0xc1e3d077UL, + 0xb3166c2bUL, 0x70b999a9UL, 0x9448fa11UL, 0xe9642247UL, 0xfc8cc4a8UL, 0xf03f1aa0UL, 0x7d2cd856UL, 0x3390ef22UL, + 0x494ec787UL, 0x38d1c1d9UL, 0xcaa2fe8cUL, 0xd40b3698UL, 0xf581cfa6UL, 0x7ade28a5UL, 0xb78e26daUL, 0xadbfa43fUL, + 0x3a9de42cUL, 0x78920d50UL, 0x5fcc9b6aUL, 0x7e466254UL, 0x8d13c2f6UL, 0xd8b8e890UL, 0x39f75e2eUL, 0xc3aff582UL, + 0x5d80be9fUL, 0xd0937c69UL, 0xd52da96fUL, 0x2512b3cfUL, 0xac993bc8UL, 0x187da710UL, 0x9c636ee8UL, 0x3bbb7bdbUL, + 0x267809cdUL, 0x5918f46eUL, 0x9ab701ecUL, 0x4f9aa883UL, 0x956e65e6UL, 0xffe67eaaUL, 0xbccf0821UL, 0x15e8e6efUL, + 0xe79bd9baUL, 0x6f36ce4aUL, 0x9f09d4eaUL, 0xb07cd629UL, 0xa4b2af31UL, 0x3f23312aUL, 0xa59430c6UL, 0xa266c035UL, + 0x4ebc3774UL, 0x82caa6fcUL, 0x90d0b0e0UL, 0xa7d81533UL, 0x04984af1UL, 0xecdaf741UL, 0xcd500e7fUL, 0x91f62f17UL, + 0x4dd68d76UL, 0xefb04d43UL, 0xaa4d54ccUL, 0x9604dfe4UL, 0xd1b5e39eUL, 0x6a881b4cUL, 0x2c1fb8c1UL, 0x65517f46UL, + 0x5eea049dUL, 0x8c355d01UL, 0x877473faUL, 0x0b412efbUL, 0x671d5ab3UL, 0xdbd25292UL, 0x105633e9UL, 0xd647136dUL, + 0xd7618c9aUL, 0xa10c7a37UL, 0xf8148e59UL, 0x133c89ebUL, 0xa927eeceUL, 0x61c935b7UL, 0x1ce5ede1UL, 0x47b13c7aUL, + 0xd2df599cUL, 0xf2733f55UL, 0x14ce7918UL, 0xc737bf73UL, 0xf7cdea53UL, 0xfdaa5b5fUL, 0x3d6f14dfUL, 0x44db8678UL, + 0xaff381caUL, 0x68c43eb9UL, 0x24342c38UL, 0xa3405fc2UL, 0x1dc37216UL, 0xe2250cbcUL, 0x3c498b28UL, 0x0d9541ffUL, + 0xa8017139UL, 0x0cb3de08UL, 0xb4e49cd8UL, 0x56c19064UL, 0xcb84617bUL, 0x32b670d5UL, 0x6c5c7448UL, 0xb85742d0UL, +}; + +static const uint32_t Tks0[] = +{ + 0x00000000UL, 0x0e090d0bUL, 0x1c121a16UL, 0x121b171dUL, 0x3824342cUL, 0x362d3927UL, 0x24362e3aUL, 0x2a3f2331UL, + 0x70486858UL, 0x7e416553UL, 0x6c5a724eUL, 0x62537f45UL, 0x486c5c74UL, 0x4665517fUL, 0x547e4662UL, 0x5a774b69UL, + 0xe090d0b0UL, 0xee99ddbbUL, 0xfc82caa6UL, 0xf28bc7adUL, 0xd8b4e49cUL, 0xd6bde997UL, 0xc4a6fe8aUL, 0xcaaff381UL, + 0x90d8b8e8UL, 0x9ed1b5e3UL, 0x8ccaa2feUL, 0x82c3aff5UL, 0xa8fc8cc4UL, 0xa6f581cfUL, 0xb4ee96d2UL, 0xbae79bd9UL, + 0xdb3bbb7bUL, 0xd532b670UL, 0xc729a16dUL, 0xc920ac66UL, 0xe31f8f57UL, 0xed16825cUL, 0xff0d9541UL, 0xf104984aUL, + 0xab73d323UL, 0xa57ade28UL, 0xb761c935UL, 0xb968c43eUL, 0x9357e70fUL, 0x9d5eea04UL, 0x8f45fd19UL, 0x814cf012UL, + 0x3bab6bcbUL, 0x35a266c0UL, 0x27b971ddUL, 0x29b07cd6UL, 0x038f5fe7UL, 0x0d8652ecUL, 0x1f9d45f1UL, 0x119448faUL, + 0x4be30393UL, 0x45ea0e98UL, 0x57f11985UL, 0x59f8148eUL, 0x73c737bfUL, 0x7dce3ab4UL, 0x6fd52da9UL, 0x61dc20a2UL, + 0xad766df6UL, 0xa37f60fdUL, 0xb16477e0UL, 0xbf6d7aebUL, 0x955259daUL, 0x9b5b54d1UL, 0x894043ccUL, 0x87494ec7UL, + 0xdd3e05aeUL, 0xd33708a5UL, 0xc12c1fb8UL, 0xcf2512b3UL, 0xe51a3182UL, 0xeb133c89UL, 0xf9082b94UL, 0xf701269fUL, + 0x4de6bd46UL, 0x43efb04dUL, 0x51f4a750UL, 0x5ffdaa5bUL, 0x75c2896aUL, 0x7bcb8461UL, 0x69d0937cUL, 0x67d99e77UL, + 0x3daed51eUL, 0x33a7d815UL, 0x21bccf08UL, 0x2fb5c203UL, 0x058ae132UL, 0x0b83ec39UL, 0x1998fb24UL, 0x1791f62fUL, + 0x764dd68dUL, 0x7844db86UL, 0x6a5fcc9bUL, 0x6456c190UL, 0x4e69e2a1UL, 0x4060efaaUL, 0x527bf8b7UL, 0x5c72f5bcUL, + 0x0605bed5UL, 0x080cb3deUL, 0x1a17a4c3UL, 0x141ea9c8UL, 0x3e218af9UL, 0x302887f2UL, 0x223390efUL, 0x2c3a9de4UL, + 0x96dd063dUL, 0x98d40b36UL, 0x8acf1c2bUL, 0x84c61120UL, 0xaef93211UL, 0xa0f03f1aUL, 0xb2eb2807UL, 0xbce2250cUL, + 0xe6956e65UL, 0xe89c636eUL, 0xfa877473UL, 0xf48e7978UL, 0xdeb15a49UL, 0xd0b85742UL, 0xc2a3405fUL, 0xccaa4d54UL, + 0x41ecdaf7UL, 0x4fe5d7fcUL, 0x5dfec0e1UL, 0x53f7cdeaUL, 0x79c8eedbUL, 0x77c1e3d0UL, 0x65daf4cdUL, 0x6bd3f9c6UL, + 0x31a4b2afUL, 0x3fadbfa4UL, 0x2db6a8b9UL, 0x23bfa5b2UL, 0x09808683UL, 0x07898b88UL, 0x15929c95UL, 0x1b9b919eUL, + 0xa17c0a47UL, 0xaf75074cUL, 0xbd6e1051UL, 0xb3671d5aUL, 0x99583e6bUL, 0x97513360UL, 0x854a247dUL, 0x8b432976UL, + 0xd134621fUL, 0xdf3d6f14UL, 0xcd267809UL, 0xc32f7502UL, 0xe9105633UL, 0xe7195b38UL, 0xf5024c25UL, 0xfb0b412eUL, + 0x9ad7618cUL, 0x94de6c87UL, 0x86c57b9aUL, 0x88cc7691UL, 0xa2f355a0UL, 0xacfa58abUL, 0xbee14fb6UL, 0xb0e842bdUL, + 0xea9f09d4UL, 0xe49604dfUL, 0xf68d13c2UL, 0xf8841ec9UL, 0xd2bb3df8UL, 0xdcb230f3UL, 0xcea927eeUL, 0xc0a02ae5UL, + 0x7a47b13cUL, 0x744ebc37UL, 0x6655ab2aUL, 0x685ca621UL, 0x42638510UL, 0x4c6a881bUL, 0x5e719f06UL, 0x5078920dUL, + 0x0a0fd964UL, 0x0406d46fUL, 0x161dc372UL, 0x1814ce79UL, 0x322bed48UL, 0x3c22e043UL, 0x2e39f75eUL, 0x2030fa55UL, + 0xec9ab701UL, 0xe293ba0aUL, 0xf088ad17UL, 0xfe81a01cUL, 0xd4be832dUL, 0xdab78e26UL, 0xc8ac993bUL, 0xc6a59430UL, + 0x9cd2df59UL, 0x92dbd252UL, 0x80c0c54fUL, 0x8ec9c844UL, 0xa4f6eb75UL, 0xaaffe67eUL, 0xb8e4f163UL, 0xb6edfc68UL, + 0x0c0a67b1UL, 0x02036abaUL, 0x10187da7UL, 0x1e1170acUL, 0x342e539dUL, 0x3a275e96UL, 0x283c498bUL, 0x26354480UL, + 0x7c420fe9UL, 0x724b02e2UL, 0x605015ffUL, 0x6e5918f4UL, 0x44663bc5UL, 0x4a6f36ceUL, 0x587421d3UL, 0x567d2cd8UL, + 0x37a10c7aUL, 0x39a80171UL, 0x2bb3166cUL, 0x25ba1b67UL, 0x0f853856UL, 0x018c355dUL, 0x13972240UL, 0x1d9e2f4bUL, + 0x47e96422UL, 0x49e06929UL, 0x5bfb7e34UL, 0x55f2733fUL, 0x7fcd500eUL, 0x71c45d05UL, 0x63df4a18UL, 0x6dd64713UL, + 0xd731dccaUL, 0xd938d1c1UL, 0xcb23c6dcUL, 0xc52acbd7UL, 0xef15e8e6UL, 0xe11ce5edUL, 0xf307f2f0UL, 0xfd0efffbUL, + 0xa779b492UL, 0xa970b999UL, 0xbb6bae84UL, 0xb562a38fUL, 0x9f5d80beUL, 0x91548db5UL, 0x834f9aa8UL, 0x8d4697a3UL +}; + +static const uint32_t Tks1[] = +{ + 0x00000000UL, 0x0b0e090dUL, 0x161c121aUL, 0x1d121b17UL, 0x2c382434UL, 0x27362d39UL, 0x3a24362eUL, 0x312a3f23UL, + 0x58704868UL, 0x537e4165UL, 0x4e6c5a72UL, 0x4562537fUL, 0x74486c5cUL, 0x7f466551UL, 0x62547e46UL, 0x695a774bUL, + 0xb0e090d0UL, 0xbbee99ddUL, 0xa6fc82caUL, 0xadf28bc7UL, 0x9cd8b4e4UL, 0x97d6bde9UL, 0x8ac4a6feUL, 0x81caaff3UL, + 0xe890d8b8UL, 0xe39ed1b5UL, 0xfe8ccaa2UL, 0xf582c3afUL, 0xc4a8fc8cUL, 0xcfa6f581UL, 0xd2b4ee96UL, 0xd9bae79bUL, + 0x7bdb3bbbUL, 0x70d532b6UL, 0x6dc729a1UL, 0x66c920acUL, 0x57e31f8fUL, 0x5ced1682UL, 0x41ff0d95UL, 0x4af10498UL, + 0x23ab73d3UL, 0x28a57adeUL, 0x35b761c9UL, 0x3eb968c4UL, 0x0f9357e7UL, 0x049d5eeaUL, 0x198f45fdUL, 0x12814cf0UL, + 0xcb3bab6bUL, 0xc035a266UL, 0xdd27b971UL, 0xd629b07cUL, 0xe7038f5fUL, 0xec0d8652UL, 0xf11f9d45UL, 0xfa119448UL, + 0x934be303UL, 0x9845ea0eUL, 0x8557f119UL, 0x8e59f814UL, 0xbf73c737UL, 0xb47dce3aUL, 0xa96fd52dUL, 0xa261dc20UL, + 0xf6ad766dUL, 0xfda37f60UL, 0xe0b16477UL, 0xebbf6d7aUL, 0xda955259UL, 0xd19b5b54UL, 0xcc894043UL, 0xc787494eUL, + 0xaedd3e05UL, 0xa5d33708UL, 0xb8c12c1fUL, 0xb3cf2512UL, 0x82e51a31UL, 0x89eb133cUL, 0x94f9082bUL, 0x9ff70126UL, + 0x464de6bdUL, 0x4d43efb0UL, 0x5051f4a7UL, 0x5b5ffdaaUL, 0x6a75c289UL, 0x617bcb84UL, 0x7c69d093UL, 0x7767d99eUL, + 0x1e3daed5UL, 0x1533a7d8UL, 0x0821bccfUL, 0x032fb5c2UL, 0x32058ae1UL, 0x390b83ecUL, 0x241998fbUL, 0x2f1791f6UL, + 0x8d764dd6UL, 0x867844dbUL, 0x9b6a5fccUL, 0x906456c1UL, 0xa14e69e2UL, 0xaa4060efUL, 0xb7527bf8UL, 0xbc5c72f5UL, + 0xd50605beUL, 0xde080cb3UL, 0xc31a17a4UL, 0xc8141ea9UL, 0xf93e218aUL, 0xf2302887UL, 0xef223390UL, 0xe42c3a9dUL, + 0x3d96dd06UL, 0x3698d40bUL, 0x2b8acf1cUL, 0x2084c611UL, 0x11aef932UL, 0x1aa0f03fUL, 0x07b2eb28UL, 0x0cbce225UL, + 0x65e6956eUL, 0x6ee89c63UL, 0x73fa8774UL, 0x78f48e79UL, 0x49deb15aUL, 0x42d0b857UL, 0x5fc2a340UL, 0x54ccaa4dUL, + 0xf741ecdaUL, 0xfc4fe5d7UL, 0xe15dfec0UL, 0xea53f7cdUL, 0xdb79c8eeUL, 0xd077c1e3UL, 0xcd65daf4UL, 0xc66bd3f9UL, + 0xaf31a4b2UL, 0xa43fadbfUL, 0xb92db6a8UL, 0xb223bfa5UL, 0x83098086UL, 0x8807898bUL, 0x9515929cUL, 0x9e1b9b91UL, + 0x47a17c0aUL, 0x4caf7507UL, 0x51bd6e10UL, 0x5ab3671dUL, 0x6b99583eUL, 0x60975133UL, 0x7d854a24UL, 0x768b4329UL, + 0x1fd13462UL, 0x14df3d6fUL, 0x09cd2678UL, 0x02c32f75UL, 0x33e91056UL, 0x38e7195bUL, 0x25f5024cUL, 0x2efb0b41UL, + 0x8c9ad761UL, 0x8794de6cUL, 0x9a86c57bUL, 0x9188cc76UL, 0xa0a2f355UL, 0xabacfa58UL, 0xb6bee14fUL, 0xbdb0e842UL, + 0xd4ea9f09UL, 0xdfe49604UL, 0xc2f68d13UL, 0xc9f8841eUL, 0xf8d2bb3dUL, 0xf3dcb230UL, 0xeecea927UL, 0xe5c0a02aUL, + 0x3c7a47b1UL, 0x37744ebcUL, 0x2a6655abUL, 0x21685ca6UL, 0x10426385UL, 0x1b4c6a88UL, 0x065e719fUL, 0x0d507892UL, + 0x640a0fd9UL, 0x6f0406d4UL, 0x72161dc3UL, 0x791814ceUL, 0x48322bedUL, 0x433c22e0UL, 0x5e2e39f7UL, 0x552030faUL, + 0x01ec9ab7UL, 0x0ae293baUL, 0x17f088adUL, 0x1cfe81a0UL, 0x2dd4be83UL, 0x26dab78eUL, 0x3bc8ac99UL, 0x30c6a594UL, + 0x599cd2dfUL, 0x5292dbd2UL, 0x4f80c0c5UL, 0x448ec9c8UL, 0x75a4f6ebUL, 0x7eaaffe6UL, 0x63b8e4f1UL, 0x68b6edfcUL, + 0xb10c0a67UL, 0xba02036aUL, 0xa710187dUL, 0xac1e1170UL, 0x9d342e53UL, 0x963a275eUL, 0x8b283c49UL, 0x80263544UL, + 0xe97c420fUL, 0xe2724b02UL, 0xff605015UL, 0xf46e5918UL, 0xc544663bUL, 0xce4a6f36UL, 0xd3587421UL, 0xd8567d2cUL, + 0x7a37a10cUL, 0x7139a801UL, 0x6c2bb316UL, 0x6725ba1bUL, 0x560f8538UL, 0x5d018c35UL, 0x40139722UL, 0x4b1d9e2fUL, + 0x2247e964UL, 0x2949e069UL, 0x345bfb7eUL, 0x3f55f273UL, 0x0e7fcd50UL, 0x0571c45dUL, 0x1863df4aUL, 0x136dd647UL, + 0xcad731dcUL, 0xc1d938d1UL, 0xdccb23c6UL, 0xd7c52acbUL, 0xe6ef15e8UL, 0xede11ce5UL, 0xf0f307f2UL, 0xfbfd0effUL, + 0x92a779b4UL, 0x99a970b9UL, 0x84bb6baeUL, 0x8fb562a3UL, 0xbe9f5d80UL, 0xb591548dUL, 0xa8834f9aUL, 0xa38d4697UL +}; + +static const uint32_t Tks2[] = +{ + 0x00000000UL, 0x0d0b0e09UL, 0x1a161c12UL, 0x171d121bUL, 0x342c3824UL, 0x3927362dUL, 0x2e3a2436UL, 0x23312a3fUL, + 0x68587048UL, 0x65537e41UL, 0x724e6c5aUL, 0x7f456253UL, 0x5c74486cUL, 0x517f4665UL, 0x4662547eUL, 0x4b695a77UL, + 0xd0b0e090UL, 0xddbbee99UL, 0xcaa6fc82UL, 0xc7adf28bUL, 0xe49cd8b4UL, 0xe997d6bdUL, 0xfe8ac4a6UL, 0xf381caafUL, + 0xb8e890d8UL, 0xb5e39ed1UL, 0xa2fe8ccaUL, 0xaff582c3UL, 0x8cc4a8fcUL, 0x81cfa6f5UL, 0x96d2b4eeUL, 0x9bd9bae7UL, + 0xbb7bdb3bUL, 0xb670d532UL, 0xa16dc729UL, 0xac66c920UL, 0x8f57e31fUL, 0x825ced16UL, 0x9541ff0dUL, 0x984af104UL, + 0xd323ab73UL, 0xde28a57aUL, 0xc935b761UL, 0xc43eb968UL, 0xe70f9357UL, 0xea049d5eUL, 0xfd198f45UL, 0xf012814cUL, + 0x6bcb3babUL, 0x66c035a2UL, 0x71dd27b9UL, 0x7cd629b0UL, 0x5fe7038fUL, 0x52ec0d86UL, 0x45f11f9dUL, 0x48fa1194UL, + 0x03934be3UL, 0x0e9845eaUL, 0x198557f1UL, 0x148e59f8UL, 0x37bf73c7UL, 0x3ab47dceUL, 0x2da96fd5UL, 0x20a261dcUL, + 0x6df6ad76UL, 0x60fda37fUL, 0x77e0b164UL, 0x7aebbf6dUL, 0x59da9552UL, 0x54d19b5bUL, 0x43cc8940UL, 0x4ec78749UL, + 0x05aedd3eUL, 0x08a5d337UL, 0x1fb8c12cUL, 0x12b3cf25UL, 0x3182e51aUL, 0x3c89eb13UL, 0x2b94f908UL, 0x269ff701UL, + 0xbd464de6UL, 0xb04d43efUL, 0xa75051f4UL, 0xaa5b5ffdUL, 0x896a75c2UL, 0x84617bcbUL, 0x937c69d0UL, 0x9e7767d9UL, + 0xd51e3daeUL, 0xd81533a7UL, 0xcf0821bcUL, 0xc2032fb5UL, 0xe132058aUL, 0xec390b83UL, 0xfb241998UL, 0xf62f1791UL, + 0xd68d764dUL, 0xdb867844UL, 0xcc9b6a5fUL, 0xc1906456UL, 0xe2a14e69UL, 0xefaa4060UL, 0xf8b7527bUL, 0xf5bc5c72UL, + 0xbed50605UL, 0xb3de080cUL, 0xa4c31a17UL, 0xa9c8141eUL, 0x8af93e21UL, 0x87f23028UL, 0x90ef2233UL, 0x9de42c3aUL, + 0x063d96ddUL, 0x0b3698d4UL, 0x1c2b8acfUL, 0x112084c6UL, 0x3211aef9UL, 0x3f1aa0f0UL, 0x2807b2ebUL, 0x250cbce2UL, + 0x6e65e695UL, 0x636ee89cUL, 0x7473fa87UL, 0x7978f48eUL, 0x5a49deb1UL, 0x5742d0b8UL, 0x405fc2a3UL, 0x4d54ccaaUL, + 0xdaf741ecUL, 0xd7fc4fe5UL, 0xc0e15dfeUL, 0xcdea53f7UL, 0xeedb79c8UL, 0xe3d077c1UL, 0xf4cd65daUL, 0xf9c66bd3UL, + 0xb2af31a4UL, 0xbfa43fadUL, 0xa8b92db6UL, 0xa5b223bfUL, 0x86830980UL, 0x8b880789UL, 0x9c951592UL, 0x919e1b9bUL, + 0x0a47a17cUL, 0x074caf75UL, 0x1051bd6eUL, 0x1d5ab367UL, 0x3e6b9958UL, 0x33609751UL, 0x247d854aUL, 0x29768b43UL, + 0x621fd134UL, 0x6f14df3dUL, 0x7809cd26UL, 0x7502c32fUL, 0x5633e910UL, 0x5b38e719UL, 0x4c25f502UL, 0x412efb0bUL, + 0x618c9ad7UL, 0x6c8794deUL, 0x7b9a86c5UL, 0x769188ccUL, 0x55a0a2f3UL, 0x58abacfaUL, 0x4fb6bee1UL, 0x42bdb0e8UL, + 0x09d4ea9fUL, 0x04dfe496UL, 0x13c2f68dUL, 0x1ec9f884UL, 0x3df8d2bbUL, 0x30f3dcb2UL, 0x27eecea9UL, 0x2ae5c0a0UL, + 0xb13c7a47UL, 0xbc37744eUL, 0xab2a6655UL, 0xa621685cUL, 0x85104263UL, 0x881b4c6aUL, 0x9f065e71UL, 0x920d5078UL, + 0xd9640a0fUL, 0xd46f0406UL, 0xc372161dUL, 0xce791814UL, 0xed48322bUL, 0xe0433c22UL, 0xf75e2e39UL, 0xfa552030UL, + 0xb701ec9aUL, 0xba0ae293UL, 0xad17f088UL, 0xa01cfe81UL, 0x832dd4beUL, 0x8e26dab7UL, 0x993bc8acUL, 0x9430c6a5UL, + 0xdf599cd2UL, 0xd25292dbUL, 0xc54f80c0UL, 0xc8448ec9UL, 0xeb75a4f6UL, 0xe67eaaffUL, 0xf163b8e4UL, 0xfc68b6edUL, + 0x67b10c0aUL, 0x6aba0203UL, 0x7da71018UL, 0x70ac1e11UL, 0x539d342eUL, 0x5e963a27UL, 0x498b283cUL, 0x44802635UL, + 0x0fe97c42UL, 0x02e2724bUL, 0x15ff6050UL, 0x18f46e59UL, 0x3bc54466UL, 0x36ce4a6fUL, 0x21d35874UL, 0x2cd8567dUL, + 0x0c7a37a1UL, 0x017139a8UL, 0x166c2bb3UL, 0x1b6725baUL, 0x38560f85UL, 0x355d018cUL, 0x22401397UL, 0x2f4b1d9eUL, + 0x642247e9UL, 0x692949e0UL, 0x7e345bfbUL, 0x733f55f2UL, 0x500e7fcdUL, 0x5d0571c4UL, 0x4a1863dfUL, 0x47136dd6UL, + 0xdccad731UL, 0xd1c1d938UL, 0xc6dccb23UL, 0xcbd7c52aUL, 0xe8e6ef15UL, 0xe5ede11cUL, 0xf2f0f307UL, 0xfffbfd0eUL, + 0xb492a779UL, 0xb999a970UL, 0xae84bb6bUL, 0xa38fb562UL, 0x80be9f5dUL, 0x8db59154UL, 0x9aa8834fUL, 0x97a38d46UL +}; + +static const uint32_t Tks3[] = +{ + 0x00000000UL, 0x090d0b0eUL, 0x121a161cUL, 0x1b171d12UL, 0x24342c38UL, 0x2d392736UL, 0x362e3a24UL, 0x3f23312aUL, + 0x48685870UL, 0x4165537eUL, 0x5a724e6cUL, 0x537f4562UL, 0x6c5c7448UL, 0x65517f46UL, 0x7e466254UL, 0x774b695aUL, + 0x90d0b0e0UL, 0x99ddbbeeUL, 0x82caa6fcUL, 0x8bc7adf2UL, 0xb4e49cd8UL, 0xbde997d6UL, 0xa6fe8ac4UL, 0xaff381caUL, + 0xd8b8e890UL, 0xd1b5e39eUL, 0xcaa2fe8cUL, 0xc3aff582UL, 0xfc8cc4a8UL, 0xf581cfa6UL, 0xee96d2b4UL, 0xe79bd9baUL, + 0x3bbb7bdbUL, 0x32b670d5UL, 0x29a16dc7UL, 0x20ac66c9UL, 0x1f8f57e3UL, 0x16825cedUL, 0x0d9541ffUL, 0x04984af1UL, + 0x73d323abUL, 0x7ade28a5UL, 0x61c935b7UL, 0x68c43eb9UL, 0x57e70f93UL, 0x5eea049dUL, 0x45fd198fUL, 0x4cf01281UL, + 0xab6bcb3bUL, 0xa266c035UL, 0xb971dd27UL, 0xb07cd629UL, 0x8f5fe703UL, 0x8652ec0dUL, 0x9d45f11fUL, 0x9448fa11UL, + 0xe303934bUL, 0xea0e9845UL, 0xf1198557UL, 0xf8148e59UL, 0xc737bf73UL, 0xce3ab47dUL, 0xd52da96fUL, 0xdc20a261UL, + 0x766df6adUL, 0x7f60fda3UL, 0x6477e0b1UL, 0x6d7aebbfUL, 0x5259da95UL, 0x5b54d19bUL, 0x4043cc89UL, 0x494ec787UL, + 0x3e05aeddUL, 0x3708a5d3UL, 0x2c1fb8c1UL, 0x2512b3cfUL, 0x1a3182e5UL, 0x133c89ebUL, 0x082b94f9UL, 0x01269ff7UL, + 0xe6bd464dUL, 0xefb04d43UL, 0xf4a75051UL, 0xfdaa5b5fUL, 0xc2896a75UL, 0xcb84617bUL, 0xd0937c69UL, 0xd99e7767UL, + 0xaed51e3dUL, 0xa7d81533UL, 0xbccf0821UL, 0xb5c2032fUL, 0x8ae13205UL, 0x83ec390bUL, 0x98fb2419UL, 0x91f62f17UL, + 0x4dd68d76UL, 0x44db8678UL, 0x5fcc9b6aUL, 0x56c19064UL, 0x69e2a14eUL, 0x60efaa40UL, 0x7bf8b752UL, 0x72f5bc5cUL, + 0x05bed506UL, 0x0cb3de08UL, 0x17a4c31aUL, 0x1ea9c814UL, 0x218af93eUL, 0x2887f230UL, 0x3390ef22UL, 0x3a9de42cUL, + 0xdd063d96UL, 0xd40b3698UL, 0xcf1c2b8aUL, 0xc6112084UL, 0xf93211aeUL, 0xf03f1aa0UL, 0xeb2807b2UL, 0xe2250cbcUL, + 0x956e65e6UL, 0x9c636ee8UL, 0x877473faUL, 0x8e7978f4UL, 0xb15a49deUL, 0xb85742d0UL, 0xa3405fc2UL, 0xaa4d54ccUL, + 0xecdaf741UL, 0xe5d7fc4fUL, 0xfec0e15dUL, 0xf7cdea53UL, 0xc8eedb79UL, 0xc1e3d077UL, 0xdaf4cd65UL, 0xd3f9c66bUL, + 0xa4b2af31UL, 0xadbfa43fUL, 0xb6a8b92dUL, 0xbfa5b223UL, 0x80868309UL, 0x898b8807UL, 0x929c9515UL, 0x9b919e1bUL, + 0x7c0a47a1UL, 0x75074cafUL, 0x6e1051bdUL, 0x671d5ab3UL, 0x583e6b99UL, 0x51336097UL, 0x4a247d85UL, 0x4329768bUL, + 0x34621fd1UL, 0x3d6f14dfUL, 0x267809cdUL, 0x2f7502c3UL, 0x105633e9UL, 0x195b38e7UL, 0x024c25f5UL, 0x0b412efbUL, + 0xd7618c9aUL, 0xde6c8794UL, 0xc57b9a86UL, 0xcc769188UL, 0xf355a0a2UL, 0xfa58abacUL, 0xe14fb6beUL, 0xe842bdb0UL, + 0x9f09d4eaUL, 0x9604dfe4UL, 0x8d13c2f6UL, 0x841ec9f8UL, 0xbb3df8d2UL, 0xb230f3dcUL, 0xa927eeceUL, 0xa02ae5c0UL, + 0x47b13c7aUL, 0x4ebc3774UL, 0x55ab2a66UL, 0x5ca62168UL, 0x63851042UL, 0x6a881b4cUL, 0x719f065eUL, 0x78920d50UL, + 0x0fd9640aUL, 0x06d46f04UL, 0x1dc37216UL, 0x14ce7918UL, 0x2bed4832UL, 0x22e0433cUL, 0x39f75e2eUL, 0x30fa5520UL, + 0x9ab701ecUL, 0x93ba0ae2UL, 0x88ad17f0UL, 0x81a01cfeUL, 0xbe832dd4UL, 0xb78e26daUL, 0xac993bc8UL, 0xa59430c6UL, + 0xd2df599cUL, 0xdbd25292UL, 0xc0c54f80UL, 0xc9c8448eUL, 0xf6eb75a4UL, 0xffe67eaaUL, 0xe4f163b8UL, 0xedfc68b6UL, + 0x0a67b10cUL, 0x036aba02UL, 0x187da710UL, 0x1170ac1eUL, 0x2e539d34UL, 0x275e963aUL, 0x3c498b28UL, 0x35448026UL, + 0x420fe97cUL, 0x4b02e272UL, 0x5015ff60UL, 0x5918f46eUL, 0x663bc544UL, 0x6f36ce4aUL, 0x7421d358UL, 0x7d2cd856UL, + 0xa10c7a37UL, 0xa8017139UL, 0xb3166c2bUL, 0xba1b6725UL, 0x8538560fUL, 0x8c355d01UL, 0x97224013UL, 0x9e2f4b1dUL, + 0xe9642247UL, 0xe0692949UL, 0xfb7e345bUL, 0xf2733f55UL, 0xcd500e7fUL, 0xc45d0571UL, 0xdf4a1863UL, 0xd647136dUL, + 0x31dccad7UL, 0x38d1c1d9UL, 0x23c6dccbUL, 0x2acbd7c5UL, 0x15e8e6efUL, 0x1ce5ede1UL, 0x07f2f0f3UL, 0x0efffbfdUL, + 0x79b492a7UL, 0x70b999a9UL, 0x6bae84bbUL, 0x62a38fb5UL, 0x5d80be9fUL, 0x548db591UL, 0x4f9aa883UL, 0x4697a38dUL +}; + +static const uint32_t rcon[] = +{ + 0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL, + 0x10000000UL, 0x20000000UL, 0x40000000UL, 0x80000000UL, + 0x1B000000UL, 0x36000000UL, // for 128-bit blocks, Rijndael never uses more than 10 rcon values +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// MACROS +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#define Te0(x) TE0[x] +#define Te1(x) TE1[x] +#define Te2(x) TE2[x] +#define Te3(x) TE3[x] + +#define Td0(x) TD0[x] +#define Td1(x) TD1[x] +#define Td2(x) TD2[x] +#define Td3(x) TD3[x] + +#define BYTE(x, n) (((x) >> (8 * (n))) & 255) + +#define STORE32H(x, y) \ +{ \ + (y)[0] = (unsigned char)(((x)>>24)&255); \ + (y)[1] = (unsigned char)(((x)>>16)&255); \ + (y)[2] = (unsigned char)(((x)>>8)&255); \ + (y)[3] = (unsigned char)((x)&255); \ } -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// AddRoundKey -// -// This function adds the round key to state. The round key is added to the state by an XOR function. -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -static -void - AddRoundKey - ( - uint32_t Round, // [in] - AesContext const* Context, // [in] - AesState* State // [in out] - ) -{ - uint32_t i; - uint32_t j; - - for( i=0; i<4; i++ ) - { - for( j=0; j<4; j++ ) - { - State->state[i][j] ^= Context->RoundKey[(Round*4*4) + (i*4) + j]; - } - } +#define LOAD32H(x, y) \ +{ \ + x = ((uint32_t)((y)[0] & 255)<<24) \ + | ((uint32_t)((y)[1] & 255)<<16) \ + | ((uint32_t)((y)[2] & 255)<<8) \ + | ((uint32_t)((y)[3] & 255)); \ } -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// SubBytes -// -// The SubBytes Function Substitutes the values in the state matrix with values in an S-box. -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -static -void - SubBytes - ( - AesState* State // [in out] - ) -{ - uint32_t i; - uint32_t j; - - for( i=0; i<4; i++ ) - { - for( j=0; j<4; j++ ) - { - State->state[j][i] = SBOX[ State->state[j][i] ]; - } - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// ShiftRows -// -// The ShiftRows() function shifts the rows in the state to the left. Each row is shifted with different offset. -// Offset = Row number. So the first row is not shifted. -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -static -void - ShiftRows - ( - AesState* State // [in out] - ) -{ - uint8_t temp; - - // Rotate first row 1 columns to left - temp = State->state[0][1]; - State->state[0][1] = State->state[1][1]; - State->state[1][1] = State->state[2][1]; - State->state[2][1] = State->state[3][1]; - State->state[3][1] = temp; - - // Rotate second row 2 columns to left - temp = State->state[0][2]; - State->state[0][2] = State->state[2][2]; - State->state[2][2] = temp; - - temp = State->state[1][2]; - State->state[1][2] = State->state[3][2]; - State->state[3][2] = temp; - - // Rotate third row 3 columns to left - temp = State->state[0][3]; - State->state[0][3] = State->state[3][3]; - State->state[3][3] = State->state[2][3]; - State->state[2][3] = State->state[1][3]; - State->state[1][3] = temp; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// xtime -// -// Performs a calculation -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -static -uint8_t - xtime - ( - uint8_t x // [in] - ) -{ - return (x<<1) ^ ( ((x>>7) & 1) * 0x1b ); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// MixColumns -// -// MixColumns function mixes the columns of the state matrix -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -static -void - MixColumns - ( - AesState* State // [in out] - ) -{ - uint32_t i; - uint8_t Tmp; - uint8_t Tm; - uint8_t t; - - for( i=0; i<4; i++ ) - { - t = State->state[i][0]; - Tmp = State->state[i][0] ^ State->state[i][1] ^ State->state[i][2] ^ State->state[i][3] ; - Tm = State->state[i][0] ^ State->state[i][1] ; Tm = xtime(Tm); State->state[i][0] ^= Tm ^ Tmp ; - Tm = State->state[i][1] ^ State->state[i][2] ; Tm = xtime(Tm); State->state[i][1] ^= Tm ^ Tmp ; - Tm = State->state[i][2] ^ State->state[i][3] ; Tm = xtime(Tm); State->state[i][2] ^= Tm ^ Tmp ; - Tm = State->state[i][3] ^ t ; Tm = xtime(Tm); State->state[i][3] ^= Tm ^ Tmp ; - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Multiply -// -// Multiply is used to multiply numbers in the field GF(2^8). This is defined as a macro. -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#define Multiply(x, y) \ - ( ((y & 1) * x) ^ \ - ((y>>1 & 1) * xtime(x)) ^ \ - ((y>>2 & 1) * xtime(xtime(x))) ^ \ - ((y>>3 & 1) * xtime(xtime(xtime(x)))) ^ \ - ((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))) \ - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// InvMixColumns -// -// InvMixColumns function mixes the columns of the state matrix. -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -static -void - InvMixColumns - ( - AesState* State // [in out] - ) -{ - uint32_t i; - uint8_t a; - uint8_t b; - uint8_t c; - uint8_t d; - - for( i=0; i<4; i++ ) - { - a = State->state[i][0]; - b = State->state[i][1]; - c = State->state[i][2]; - d = State->state[i][3]; - - State->state[i][0] = Multiply(a, 0x0e) ^ Multiply(b, 0x0b) ^ Multiply(c, 0x0d) ^ Multiply(d, 0x09); - State->state[i][1] = Multiply(a, 0x09) ^ Multiply(b, 0x0e) ^ Multiply(c, 0x0b) ^ Multiply(d, 0x0d); - State->state[i][2] = Multiply(a, 0x0d) ^ Multiply(b, 0x09) ^ Multiply(c, 0x0e) ^ Multiply(d, 0x0b); - State->state[i][3] = Multiply(a, 0x0b) ^ Multiply(b, 0x0d) ^ Multiply(c, 0x09) ^ Multiply(d, 0x0e); - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// InvSubBytes -// -// The InvSubBytes Function Substitutes the values in the state matrix with values in an S-box. -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -static -void - InvSubBytes - ( - AesState* State // [in out] - ) -{ - uint32_t i; - uint32_t j; - - for( i=0; i<4; i++ ) - { - for( j=0; j<4; j++ ) - { - State->state[j][i] = RSBOX[ State->state[j][i] ]; - } - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// InvShiftRows -// -// Inverse of ShiftRows -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -static -void - InvShiftRows - ( - AesState* State // [in out] - ) -{ - uint8_t temp; - - // Rotate first row 1 columns to right - temp = State->state[3][1]; - State->state[3][1] = State->state[2][1]; - State->state[2][1] = State->state[1][1]; - State->state[1][1] = State->state[0][1]; - State->state[0][1] = temp; - - // Rotate second row 2 columns to right - temp = State->state[0][2]; - State->state[0][2] = State->state[2][2]; - State->state[2][2] = temp; - - temp = State->state[1][2]; - State->state[1][2] = State->state[3][2]; - State->state[3][2] = temp; - - // Rotate third row 3 columns to right - temp = State->state[0][3]; - State->state[0][3] = State->state[1][3]; - State->state[1][3] = State->state[2][3]; - State->state[2][3] = State->state[3][3]; - State->state[3][3] = temp; -} +#define ROL(x, y) ( (((uint32_t)(x)<<(uint32_t)((y)&31)) | (((uint32_t)(x)&0xFFFFFFFFUL)>>(uint32_t)((32-((y)&31))&31))) & 0xFFFFFFFFUL) +#define ROR(x, y) ( ((((uint32_t)(x)&0xFFFFFFFFUL)>>(uint32_t)((y)&31)) | ((uint32_t)(x)<<(uint32_t)((32-((y)&31))&31))) & 0xFFFFFFFFUL) +#define ROLc(x, y) ( (((uint32_t)(x)<<(uint32_t)((y)&31)) | (((uint32_t)(x)&0xFFFFFFFFUL)>>(uint32_t)((32-((y)&31))&31))) & 0xFFFFFFFFUL) +#define RORc(x, y) ( ((((uint32_t)(x)&0xFFFFFFFFUL)>>(uint32_t)((y)&31)) | ((uint32_t)(x)<<(uint32_t)((32-((y)&31))&31))) & 0xFFFFFFFFUL) //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // EXPORTED FUNCTIONS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// AesInitialise128 +// AesInitialise // -// Initialises an AesContext with a 128 bit key. +// Initialises an AesContext with an AES Key. KeySize must be 16, 24, or 32 (for 128, 192, or 256 bit key size) +// Returns 0 if successful, or -1 if invalid KeySize provided //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void - AesInitialise128 +int + AesInitialise ( - uint8_t const Key [AES_KEY_SIZE_128], // [in] - AesContext* Context // [out] + AesContext* Context, // [out] + void const* Key, // [in] + uint32_t KeySize // [in] ) { - memset( Context, 0, sizeof(*Context) ); + uint8_t const* key = Key; + uint_fast32_t i; + uint32_t temp; + uint32_t* rk; + uint32_t* rrk; - Context->KeySizeInWords = AES_KEY_SIZE_128 / sizeof(uint32_t); - Context->NumberOfRounds = 10; + #define SETUP_MIX( Value ) \ + ( (Te4_3[BYTE(Value, 2)]) ^ (Te4_2[BYTE(Value, 1)]) ^ (Te4_1[BYTE(Value, 0)]) ^ (Te4_0[BYTE(Value, 3)]) ) - KeyExpansion( Key, Context ); -} + Context->Nr = 10 + ((KeySize/8)-2)*2; -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// AesInitialise192 -// -// Initialises an AesContext with a 192 bit key. -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void - AesInitialise192 - ( - uint8_t const Key [AES_KEY_SIZE_192], // [in] - AesContext* Context // [out] - ) -{ - memset( Context, 0, sizeof(*Context) ); + // Setup the forward key + i = 0; + rk = Context->eK; - Context->KeySizeInWords = AES_KEY_SIZE_192 / sizeof(uint32_t); - Context->NumberOfRounds = 12; + LOAD32H( rk[0], key ); + LOAD32H( rk[1], key + 4 ); + LOAD32H( rk[2], key + 8 ); + LOAD32H( rk[3], key + 12 ); - KeyExpansion( Key, Context ); -} + if( AES_KEY_SIZE_128 == KeySize ) + { + for( ;; ) + { + temp = rk[3]; + rk[4] = rk[0] ^ SETUP_MIX( temp ) ^ rcon[i]; + rk[5] = rk[1] ^ rk[4]; + rk[6] = rk[2] ^ rk[5]; + rk[7] = rk[3] ^ rk[6]; + i += 1; + if( 10 == i ) + { + break; + } + rk += 4; + } + } + else if( AES_KEY_SIZE_192 == KeySize ) + { + LOAD32H( rk[4], key + 16 ); + LOAD32H( rk[5], key + 20 ); + for( ;; ) + { + temp = rk[5]; + rk[6] = rk[0] ^ SETUP_MIX( temp ) ^ rcon[i]; + rk[7] = rk[1] ^ rk[6]; + rk[8] = rk[2] ^ rk[7]; + rk[9] = rk[3] ^ rk[8]; + i += 1; + if( 8 == i ) + { + break; + } + rk[10] = rk[4] ^ rk[9]; + rk[11] = rk[5] ^ rk[10]; + rk += 6; + } + } + else if( AES_KEY_SIZE_256 == KeySize ) + { + LOAD32H( rk[4], key + 16 ); + LOAD32H( rk[5], key + 20 ); + LOAD32H( rk[6], key + 24 ); + LOAD32H( rk[7], key + 28 ); + for( ;; ) + { + temp = rk[7]; + rk[8] = rk[0] ^ SETUP_MIX( temp ) ^ rcon[i]; + rk[9] = rk[1] ^ rk[8]; + rk[10] = rk[2] ^ rk[9]; + rk[11] = rk[3] ^ rk[10]; + i += 1; + if( 7 == i ) + { + break; + } + temp = rk[11]; + rk[12] = rk[4] ^ SETUP_MIX( RORc( temp, 8 ) ); + rk[13] = rk[5] ^ rk[12]; + rk[14] = rk[6] ^ rk[13]; + rk[15] = rk[7] ^ rk[14]; + rk += 8; + } + } -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// AesInitialise256 -// -// Initialises an AesContext with a 256 bit key. -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void - AesInitialise256 - ( - uint8_t const Key [AES_KEY_SIZE_256], // [in] - AesContext* Context // [out] - ) -{ - memset( Context, 0, sizeof(*Context) ); + // Setup the inverse key now + rk = Context->dK; + rrk = Context->eK + (28 + KeySize) - 4; - Context->KeySizeInWords = AES_KEY_SIZE_256 / sizeof(uint32_t); - Context->NumberOfRounds = 14; + // Apply the inverse MixColumn transform to all round keys but the first and the last + // Copy first + *rk++ = *rrk++; + *rk++ = *rrk++; + *rk++ = *rrk++; + *rk = *rrk; + rk -= 3; rrk -= 3; - KeyExpansion( Key, Context ); + for( i=1; iNr; i++ ) + { + rrk -= 4; + rk += 4; + temp = rrk[0]; rk[0] = Tks0[BYTE(temp, 3)] ^ Tks1[BYTE(temp, 2)] ^ Tks2[BYTE(temp, 1)] ^ Tks3[BYTE(temp, 0)]; + temp = rrk[1]; rk[1] = Tks0[BYTE(temp, 3)] ^ Tks1[BYTE(temp, 2)] ^ Tks2[BYTE(temp, 1)] ^ Tks3[BYTE(temp, 0)]; + temp = rrk[2]; rk[2] = Tks0[BYTE(temp, 3)] ^ Tks1[BYTE(temp, 2)] ^ Tks2[BYTE(temp, 1)] ^ Tks3[BYTE(temp, 0)]; + temp = rrk[3]; rk[3] = Tks0[BYTE(temp, 3)] ^ Tks1[BYTE(temp, 2)] ^ Tks2[BYTE(temp, 1)] ^ Tks3[BYTE(temp, 0)]; + } + + // Copy last + rrk -= 4; + rk += 4; + *rk++ = *rrk++; + *rk++ = *rrk++; + *rk++ = *rrk++; + *rk = *rrk; + + #undef SETUP_MIX + return 0; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // AesEncrypt // // Performs an AES encryption of one block (128 bits) with the AesContext initialised with one of the functions -// AesInitialise[n]. Input and Output can point to same memory location, however it is more efficient to use -// AesEncryptInPlace in this situation. +// AesInitialise[n]. Input and Output can point to same memory location. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void AesEncrypt @@ -484,8 +838,62 @@ void uint8_t Output [AES_BLOCK_SIZE] // [out] ) { - memcpy( Output, Input, AES_BLOCK_SIZE ); - AesEncryptInPlace( Context, Output ); + uint32_t s0; + uint32_t s1; + uint32_t s2; + uint32_t s3; + uint32_t t0; + uint32_t t1; + uint32_t t2; + uint32_t t3; + uint32_t const* rk; + uint_fast32_t r; + + rk = Context->eK; + + // Map BYTE array block to cipher state and add initial round key: + LOAD32H( s0, Input ); + LOAD32H( s1, Input + 4); + LOAD32H( s2, Input + 8); + LOAD32H( s3, Input + 12); + + s0 ^= rk[0]; + s1 ^= rk[1]; + s2 ^= rk[2]; + s3 ^= rk[3]; + + // Nr - 1 full rounds: + r = Context->Nr >> 1; + for( ;; ) + { + t0 = Te0( BYTE( s0, 3 ) ) ^ Te1( BYTE( s1, 2 ) ) ^ Te2( BYTE( s2, 1 ) ) ^ Te3( BYTE( s3, 0 ) ) ^ rk[4]; + t1 = Te0( BYTE( s1, 3 ) ) ^ Te1( BYTE( s2, 2 ) ) ^ Te2( BYTE( s3, 1 ) ) ^ Te3( BYTE( s0, 0 ) ) ^ rk[5]; + t2 = Te0( BYTE( s2, 3 ) ) ^ Te1( BYTE( s3, 2 ) ) ^ Te2( BYTE( s0, 1 ) ) ^ Te3( BYTE( s1, 0 ) ) ^ rk[6]; + t3 = Te0( BYTE( s3, 3 ) ) ^ Te1( BYTE( s0, 2 ) ) ^ Te2( BYTE( s1, 1 ) ) ^ Te3( BYTE( s2, 0 ) ) ^ rk[7]; + + rk += 8; + r -= 1; + if ( 0 == r ) + { + break; + } + + s0 = Te0( BYTE( t0, 3 ) ) ^ Te1( BYTE( t1, 2 ) ) ^ Te2( BYTE( t2, 1 ) ) ^ Te3( BYTE( t3, 0 ) ) ^ rk[0]; + s1 = Te0( BYTE( t1, 3 ) ) ^ Te1( BYTE( t2, 2 ) ) ^ Te2( BYTE( t3, 1 ) ) ^ Te3( BYTE( t0, 0 ) ) ^ rk[1]; + s2 = Te0( BYTE( t2, 3 ) ) ^ Te1( BYTE( t3, 2 ) ) ^ Te2( BYTE( t0, 1 ) ) ^ Te3( BYTE( t1, 0 ) ) ^ rk[2]; + s3 = Te0( BYTE( t3, 3 ) ) ^ Te1( BYTE( t0, 2 ) ) ^ Te2( BYTE( t1, 1 ) ) ^ Te3( BYTE( t2, 0 ) ) ^ rk[3]; + } + + // Apply last round and map cipher state to BYTE array block: + s0 = (Te4_3[BYTE( t0, 3 )]) ^ (Te4_2[BYTE( t1, 2 )]) ^ (Te4_1[BYTE( t2, 1 )]) ^ (Te4_0[BYTE( t3, 0 )]) ^ rk[0]; + s1 = (Te4_3[BYTE( t1, 3 )]) ^ (Te4_2[BYTE( t2, 2 )]) ^ (Te4_1[BYTE( t3, 1 )]) ^ (Te4_0[BYTE( t0, 0 )]) ^ rk[1]; + s2 = (Te4_3[BYTE( t2, 3 )]) ^ (Te4_2[BYTE( t3, 2 )]) ^ (Te4_1[BYTE( t0, 1 )]) ^ (Te4_0[BYTE( t1, 0 )]) ^ rk[2]; + s3 = (Te4_3[BYTE( t3, 3 )]) ^ (Te4_2[BYTE( t0, 2 )]) ^ (Te4_1[BYTE( t1, 1 )]) ^ (Te4_0[BYTE( t2, 0 )]) ^ rk[3]; + + STORE32H( s0, Output ); + STORE32H( s1, Output + 4 ); + STORE32H( s2, Output + 8 ); + STORE32H( s3, Output + 12); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -503,8 +911,66 @@ void uint8_t Output [AES_BLOCK_SIZE] // [out] ) { - memcpy( Output, Input, AES_BLOCK_SIZE); - AesDecryptInPlace(Context, Output ); + uint32_t s0; + uint32_t s1; + uint32_t s2; + uint32_t s3; + uint32_t t0; + uint32_t t1; + uint32_t t2; + uint32_t t3; + uint32_t const* rk; + uint_fast32_t r; + + rk = Context->dK; + + // Map BYTE array block to cipher state and add initial round key: + LOAD32H( s0, Input ); + LOAD32H( s1, Input + 4 ); + LOAD32H( s2, Input + 8 ); + LOAD32H( s3, Input + 12 ); + + s0 ^= rk[0]; + s1 ^= rk[1]; + s2 ^= rk[2]; + s3 ^= rk[3]; + + // Nr - 1 full rounds + r = Context->Nr >> 1; + for( ;; ) + { + t0 = Td0( BYTE( s0, 3 ) ) ^ Td1( BYTE( s3, 2 ) ) ^ Td2( BYTE( s2, 1 ) ) ^ Td3( BYTE( s1, 0 ) ) ^ rk[4]; + t1 = Td0( BYTE( s1, 3 ) ) ^ Td1( BYTE( s0, 2 ) ) ^ Td2( BYTE( s3, 1 ) ) ^ Td3( BYTE( s2, 0 ) ) ^ rk[5]; + t2 = Td0( BYTE( s2, 3 ) ) ^ Td1( BYTE( s1, 2 ) ) ^ Td2( BYTE( s0, 1 ) ) ^ Td3( BYTE( s3, 0 ) ) ^ rk[6]; + t3 = Td0( BYTE( s3, 3 ) ) ^ Td1( BYTE( s2, 2 ) ) ^ Td2( BYTE( s1, 1 ) ) ^ Td3( BYTE( s0, 0 ) ) ^ rk[7]; + + rk += 8; + r -= 1; + if( 0 == r ) + { + break; + } + + s0 = Td0( BYTE( t0, 3 ) ) ^ Td1( BYTE( t3, 2 ) ) ^ Td2( BYTE( t2, 1 ) ) ^ Td3( BYTE( t1, 0 )) ^ rk[0]; + s1 = Td0( BYTE( t1, 3 ) ) ^ Td1( BYTE( t0, 2 ) ) ^ Td2( BYTE( t3, 1 ) ) ^ Td3( BYTE( t2, 0 )) ^ rk[1]; + s2 = Td0( BYTE( t2, 3 ) ) ^ Td1( BYTE( t1, 2 ) ) ^ Td2( BYTE( t0, 1 ) ) ^ Td3( BYTE( t3, 0 )) ^ rk[2]; + s3 = Td0( BYTE( t3, 3 ) ) ^ Td1( BYTE( t2, 2 ) ) ^ Td2( BYTE( t1, 1 ) ) ^ Td3( BYTE( t0, 0 )) ^ rk[3]; + } + + // Apply last round and map cipher state to BYTE array block: + s0 = ( Td4[BYTE( t0, 3 )] & 0xff000000) ^ (Td4[BYTE( t3, 2 )] & 0x00ff0000) + ^ ( Td4[BYTE( t2, 1 )] & 0x0000ff00) ^ (Td4[BYTE( t1, 0 )] & 0x000000ff) ^ rk[0]; + s1 = ( Td4[BYTE( t1, 3 )] & 0xff000000) ^ (Td4[BYTE( t0, 2 )] & 0x00ff0000) + ^ ( Td4[BYTE( t3, 1 )] & 0x0000ff00) ^ (Td4[BYTE( t2, 0 )] & 0x000000ff) ^ rk[1]; + s2 = ( Td4[BYTE( t2, 3 )] & 0xff000000) ^ (Td4[BYTE( t1, 2 )] & 0x00ff0000) + ^ ( Td4[BYTE( t0, 1 )] & 0x0000ff00) ^ (Td4[BYTE( t3, 0 )] & 0x000000ff) ^ rk[2]; + s3 = ( Td4[BYTE( t3, 3 )] & 0xff000000) ^ (Td4[BYTE( t2, 2 )] & 0x00ff0000) + ^ ( Td4[BYTE( t1, 1 )] & 0x0000ff00) ^ (Td4[BYTE( t0, 0 )] & 0x000000ff) ^ rk[3]; + + STORE32H( s0, Output ); + STORE32H( s1, Output + 4 ); + STORE32H( s2, Output + 8 ); + STORE32H( s3, Output + 12 ); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -520,27 +986,7 @@ void uint8_t Block [AES_BLOCK_SIZE] // [in out] ) { - uint32_t round = 0; - - // Add the First round key to the state before starting the rounds. - AddRoundKey( 0, Context, (AesState*)Block ); - - // There will be Nr rounds. - // The first Nr-1 rounds are identical. - // These Nr-1 rounds are executed in the loop below. - for( round=1; roundNumberOfRounds; round++ ) - { - SubBytes( (AesState*)Block ); - ShiftRows( (AesState*)Block ); - MixColumns( (AesState*)Block ); - AddRoundKey( round, Context, (AesState*)Block ); - } - - // The last round is given below. - // The MixColumns function is not here in the last round. - SubBytes( (AesState*)Block); - ShiftRows( (AesState*)Block); - AddRoundKey( Context->NumberOfRounds, Context, (AesState*)Block ); + AesEncrypt( Context, Block, Block ); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -556,22 +1002,5 @@ void uint8_t Block [AES_BLOCK_SIZE] // [in out] ) { - uint32_t round = 0; - - // Add the First round key to the state before starting the rounds. - AddRoundKey( Context->NumberOfRounds, Context, (AesState*)Block ); - - // The first NumberOfRounds-1 rounds are identical. - for( round=(Context->NumberOfRounds-1); round>0; round-- ) - { - InvShiftRows( (AesState*)Block ); - InvSubBytes( (AesState*)Block ); - AddRoundKey( round, Context, (AesState*)Block ); - InvMixColumns( (AesState*)Block ); - } - - // The MixColumns function is not here in the last round. - InvShiftRows( (AesState*)Block ); - InvSubBytes( (AesState*)Block ); - AddRoundKey( 0, Context, (AesState*)Block ); + AesDecrypt( Context, Block, Block ); } diff --git a/lib/CryptLib_Aes.h b/lib/CryptLib_Aes.h index ae8461c..3239530 100644 --- a/lib/CryptLib_Aes.h +++ b/lib/CryptLib_Aes.h @@ -1,18 +1,22 @@ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // CryptLib_Aes // -// Implementation of AES block cipher. Originally written by Kokke (https://github.com/kokke). Modified by WaterJuice -// retaining Public Domain license. +// Implementation of AES block cipher. This implementation was modified from LibTomCrypt written by Tom St Denis +// (https://github.com/libtom). Modified by WaterJuice retaining Public Domain license. +// Derived from Public Domain source by original authors: +// Vincent Rijmen +// Antoon Bosselaers +// Paulo Barreto // // AES is a block cipher that operates on 128 bit blocks. Encryption an Decryption routines use an AesContext which // must be initialised with the key. An AesContext can be initialised with a 128, 192, or 256 bit key. Use the // AesInitialise[n] functions to initialise the context with the key. Once an AES context is initialised its contents // are not changed by the encrypting and decrypting functions. A context only needs to be initialised once for any // given key and the context may be used by the encrypt/decrypt functions in simultaneous threads. -// All operations are performed byte wise and this implementation works in both little and endian processors. +// All operations are performed BYTE wise and this implementation works in both little and endian processors. // There are no alignment requirements with the keys and data blocks. // -// This is free and unencumbered software released into the public domain - November 2017 waterjuice.org +// This is free and unencumbered software released into the public domain - December 2017 waterjuice.org //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #pragma once @@ -36,9 +40,9 @@ // Do not modify the contents of this structure directly. typedef struct { - uint32_t KeySizeInWords; - uint32_t NumberOfRounds; - uint8_t RoundKey[240]; + uint32_t eK[60]; + uint32_t dK[60]; + uint_fast32_t Nr; } AesContext; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -46,39 +50,17 @@ typedef struct //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// AesInitialise128 +// AesInitialise // -// Initialises an AesContext with a 128 bit key. +// Initialises an AesContext with an AES Key. KeySize must be 16, 24, or 32 (for 128, 192, or 256 bit key size) +// Returns 0 if successful, or -1 if invalid KeySize provided //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void - AesInitialise128 +int + AesInitialise ( - uint8_t const Key [AES_KEY_SIZE_128], // [in] - AesContext* Context // [out] - ); - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// AesInitialise192 -// -// Initialises an AesContext with a 192 bit key. -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void - AesInitialise192 - ( - uint8_t const Key [AES_KEY_SIZE_192], // [in] - AesContext* Context // [out] - ); - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// AesInitialise256 -// -// Initialises an AesContext with a 256 bit key. -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void - AesInitialise256 - ( - uint8_t const Key [AES_KEY_SIZE_256], // [in] - AesContext* Context // [out] + AesContext* Context, // [out] + void const* Key, // [in] + uint32_t KeySize // [in] ); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/lib/CryptLib_AesCtr.c b/lib/CryptLib_AesCtr.c index 1f1f8e8..8e5e08d 100644 --- a/lib/CryptLib_AesCtr.c +++ b/lib/CryptLib_AesCtr.c @@ -96,9 +96,9 @@ void void AesCtrInitialise ( + AesCtrContext* Context, // [out] AesContext const* InitialisedAesContext, // [in] - uint8_t const IV [AES_CTR_IV_SIZE], // [in] - AesCtrContext* Context // [out] + uint8_t const IV [AES_CTR_IV_SIZE] // [in] ) { // Setup context values @@ -121,27 +121,22 @@ void int AesCtrInitialiseWithKey ( + AesCtrContext* Context, // [out] uint8_t const* Key, // [in] uint32_t KeySize, // [in] - uint8_t const IV [AES_CTR_IV_SIZE], // [in] - AesCtrContext* Context // [out] + uint8_t const IV [AES_CTR_IV_SIZE] // [in] ) { AesContext aes; // Initialise AES Context - switch( KeySize ) + if( 0 != AesInitialise( &aes, Key, KeySize ) ) { - case AES_KEY_SIZE_128: AesInitialise128( Key, &aes ); break; - case AES_KEY_SIZE_192: AesInitialise192( Key, &aes ); break; - case AES_KEY_SIZE_256: AesInitialise256( Key, &aes ); break; - default: - // Invalid key size return -1; } // Now set-up AesCtrContext - AesCtrInitialise( &aes, IV, Context ); + AesCtrInitialise( Context, &aes, IV ); return 0; } @@ -177,7 +172,7 @@ void // advance the stream index by that number of bytes. // Use once over data to encrypt it. Use it a second time over the same data from the same stream position and the // data will be decrypted. -// InBuffer and OutBuffer can point to the same location for inplace encrypting/decrypting +// InBuffer and OutBuffer can point to the same location for in-place encrypting/decrypting //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void AesCtrXor @@ -188,47 +183,68 @@ void uint32_t Size // [in] ) { - uint32_t amountLeft = Size; - uint32_t outputOffset = 0; - uint32_t chunkSize; - uint32_t amountAvailableInBlock; + uint32_t firstChunkSize; + uint32_t amountAvailableInBlock; + int numIterations; + int i; + uint64_t loopStartingCipherBlockIndex; + uint32_t loopStartingOutputOffset; + uint8_t preCipherBlock [AES_KEY_SIZE_128]; + uint8_t encCipherBlock [AES_KEY_SIZE_128]; + uint64_t cipherBlockIndex = 0; // First determine how much is available in the current block. amountAvailableInBlock = AES_BLOCK_SIZE - (Context->StreamIndex % AES_BLOCK_SIZE); // Determine how much of the current block we will take, either all that is available, or less // if the amount requested is smaller. - chunkSize = MIN( amountAvailableInBlock, amountLeft ); + firstChunkSize = MIN( amountAvailableInBlock, Size ); // XOR the bytes from the cipher block - XorBuffers( InBuffer, Context->CurrentCipherBlock + (AES_BLOCK_SIZE - amountAvailableInBlock), OutBuffer, chunkSize ); + XorBuffers( InBuffer, Context->CurrentCipherBlock + (AES_BLOCK_SIZE - amountAvailableInBlock), OutBuffer, firstChunkSize ); - amountLeft -= chunkSize; - outputOffset += chunkSize; + // Determine how many iterations will be needed for generating cipher blocks. + // We always have to finish with a non-depleted cipher block. + // Also calculate the cipher block index and the output offset for when we start the loop. + // This function may be built with OpenMP and the loop will run in parallel. So we set-up variables that will + // be common at the start of the loop. + numIterations = ( (Size - firstChunkSize) + AES_BLOCK_SIZE ) / AES_BLOCK_SIZE; + loopStartingCipherBlockIndex = Context->CurrentCipherBlockIndex + 1; + loopStartingOutputOffset = firstChunkSize; + + // Copy the IV into the first half of the preCipherBlock. When built for OpenMP preCipherBlock will be copied into + // a local version within the loop. + memcpy( preCipherBlock, Context->IV, AES_CTR_IV_SIZE ); // Now start generating new cipher blocks as required. - while( amountLeft > 0 ) + #ifdef _OPENMP + #pragma omp parallel for firstprivate( preCipherBlock, cipherBlockIndex ) lastprivate( encCipherBlock, cipherBlockIndex ) + #endif + for( i=0; iCurrentCipherBlockIndex += 1; - CreateCurrentCipherBlock( Context ); + cipherBlockIndex = loopStartingCipherBlockIndex + i; - // Determine how much of the current block we need and XOR it out onto the buffer - chunkSize = MIN( amountLeft, AES_BLOCK_SIZE ); - XorBuffers( (uint8_t*)InBuffer + outputOffset, Context->CurrentCipherBlock, (uint8_t*)OutBuffer + outputOffset, chunkSize ); + // Now place in the counter in Big Endian form in second half of preCipherBlock + STORE64H( cipherBlockIndex, preCipherBlock + AES_CTR_IV_SIZE ); - amountLeft -= chunkSize; - outputOffset += chunkSize; + // Perform AES encryption on the preCipherBlock and put result in encCipherBlock + AesEncrypt( &Context->Aes, preCipherBlock, encCipherBlock ); + + // XOR block out onto the buffer. + XorBuffers( (uint8_t*)InBuffer + outputOffset, encCipherBlock, (uint8_t*)OutBuffer + outputOffset, chunkSize ); } - // All data read out now, so update index in the context. + // Update context Context->StreamIndex += Size; - - // If we ended up completely reading the last cipher block we need to generate a new one for next time. - if( AES_BLOCK_SIZE == chunkSize ) + if( numIterations > 0 ) { - Context->CurrentCipherBlockIndex += 1; - CreateCurrentCipherBlock( Context ); + Context->CurrentCipherBlockIndex = cipherBlockIndex; + memcpy( Context->CurrentCipherBlock, encCipherBlock, AES_BLOCK_SIZE ); } } @@ -273,7 +289,7 @@ int int error; AesCtrContext context; - error = AesCtrInitialiseWithKey( Key, KeySize, IV, &context ); + error = AesCtrInitialiseWithKey( &context, Key, KeySize, IV ); if( 0 == error ) { AesCtrXor( &context, InBuffer, OutBuffer, BufferSize ); diff --git a/lib/CryptLib_AesCtr.h b/lib/CryptLib_AesCtr.h index 9b53db4..efb3601 100644 --- a/lib/CryptLib_AesCtr.h +++ b/lib/CryptLib_AesCtr.h @@ -54,9 +54,9 @@ typedef struct void AesCtrInitialise ( + AesCtrContext* Context, // [out] AesContext const* InitialisedAesContext, // [in] - uint8_t const IV [AES_CTR_IV_SIZE], // [in] - AesCtrContext* Context // [out] + uint8_t const IV [AES_CTR_IV_SIZE] // [in] ); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -69,10 +69,10 @@ void int AesCtrInitialiseWithKey ( + AesCtrContext* Context, // [out] uint8_t const* Key, // [in] uint32_t KeySize, // [in] - uint8_t const IV [AES_CTR_IV_SIZE], // [in] - AesCtrContext* Context // [out] + uint8_t const IV [AES_CTR_IV_SIZE] // [in] ); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -95,7 +95,7 @@ void // advance the stream index by that number of bytes. // Use once over data to encrypt it. Use it a second time over the same data from the same stream position and the // data will be decrypted. -// InBuffer and OutBuffer can point to the same location for inplace encrypting/decrypting +// InBuffer and OutBuffer can point to the same location for in-place encrypting/decrypting //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void AesCtrXor diff --git a/lib/CryptLib_Md5.c b/lib/CryptLib_Md5.c index 86fa98f..8b299bf 100644 --- a/lib/CryptLib_Md5.c +++ b/lib/CryptLib_Md5.c @@ -66,10 +66,10 @@ void* #define GET(n) (ctx->block[(n)]) #define SET(n) (ctx->block[(n)] = \ - ((uint32_t)ptr[(n)*4 + 0] << 0 ) \ - | ((uint32_t)ptr[(n)*4 + 1] << 8 ) \ - | ((uint32_t)ptr[(n)*4 + 2] << 16) \ - | ((uint32_t)ptr[(n)*4 + 3] << 24) ) + ((uint32_t)ptr[(n)*4 + 0] << 0 ) \ + | ((uint32_t)ptr[(n)*4 + 1] << 8 ) \ + | ((uint32_t)ptr[(n)*4 + 2] << 16) \ + | ((uint32_t)ptr[(n)*4 + 3] << 24) ) ptr = (uint8_t*)data; @@ -188,7 +188,7 @@ void* void Md5Initialise ( - Md5Context* Context + Md5Context* Context // [out] ) { Context->a = 0x67452301; @@ -209,9 +209,9 @@ void void Md5Update ( - Md5Context* Context, - void const* Buffer, - uint32_t BufferSize + Md5Context* Context, // [in out] + void const* Buffer, // [in] + uint32_t BufferSize // [in] ) { uint32_t saved_lo; @@ -261,8 +261,8 @@ void void Md5Finalise ( - Md5Context* Context, - MD5_HASH* Digest + Md5Context* Context, // [in out] + MD5_HASH* Digest // [in] ) { uint32_t used; diff --git a/lib/CryptLib_Md5.h b/lib/CryptLib_Md5.h index f14686a..f7ca92d 100644 --- a/lib/CryptLib_Md5.h +++ b/lib/CryptLib_Md5.h @@ -52,7 +52,7 @@ typedef struct void Md5Initialise ( - Md5Context* Context + Md5Context* Context // [out] ); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -64,9 +64,9 @@ void void Md5Update ( - Md5Context* Context, - void const* Buffer, - uint32_t BufferSize + Md5Context* Context, // [in out] + void const* Buffer, // [in] + uint32_t BufferSize // [in] ); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -78,6 +78,6 @@ void void Md5Finalise ( - Md5Context* Context, - MD5_HASH* Digest + Md5Context* Context, // [in out] + MD5_HASH* Digest // [in] ); diff --git a/lib/CryptLib_Rc4.c b/lib/CryptLib_Rc4.c index 3cc41e3..6352f78 100644 --- a/lib/CryptLib_Rc4.c +++ b/lib/CryptLib_Rc4.c @@ -36,10 +36,10 @@ void Rc4Initialise ( - Rc4Context* Context, - void const* Key, - uint32_t KeySize, - uint32_t DropN + Rc4Context* Context, // [out] + void const* Key, // [in] + uint32_t KeySize, // [in] + uint32_t DropN // [in] ) { uint32_t i; @@ -82,9 +82,9 @@ void void Rc4Output ( - Rc4Context* Context, - void* Buffer, - uint32_t Size + Rc4Context* Context, // [in out] + void* Buffer, // [out] + uint32_t Size // [in] ) { uint32_t n; @@ -108,10 +108,10 @@ void void Rc4Xor ( - Rc4Context* Context, - void const* InBuffer, - void* OutBuffer, - uint32_t Size + Rc4Context* Context, // [in out] + void const* InBuffer, // [in] + void* OutBuffer, // [out] + uint32_t Size // [in] ) { uint32_t n; diff --git a/lib/CryptLib_Rc4.h b/lib/CryptLib_Rc4.h index 81ffd32..fed71de 100644 --- a/lib/CryptLib_Rc4.h +++ b/lib/CryptLib_Rc4.h @@ -38,10 +38,10 @@ typedef struct void Rc4Initialise ( - Rc4Context* Context, - void const* Key, - uint32_t KeySize, - uint32_t DropN + Rc4Context* Context, // [out] + void const* Key, // [in] + uint32_t KeySize, // [in] + uint32_t DropN // [in] ); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -52,9 +52,9 @@ void void Rc4Output ( - Rc4Context* Context, - void* Buffer, - uint32_t Size + Rc4Context* Context, // [in out] + void* Buffer, // [out] + uint32_t Size // [in] ); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -66,8 +66,8 @@ void void Rc4Xor ( - Rc4Context* Context, - void const* InBuffer, - void* OutBuffer, - uint32_t Size + Rc4Context* Context, // [in out] + void const* InBuffer, // [in] + void* OutBuffer, // [out] + uint32_t Size // [in] ); diff --git a/lib/CryptLib_Sha1.c b/lib/CryptLib_Sha1.c index 5c599ee..3542604 100644 --- a/lib/CryptLib_Sha1.c +++ b/lib/CryptLib_Sha1.c @@ -158,7 +158,7 @@ void void Sha1Initialise ( - Sha1Context* Context + Sha1Context* Context // [out] ) { // SHA1 initialisation constants @@ -180,9 +180,9 @@ void void Sha1Update ( - Sha1Context* Context, - void const* Buffer, - uint32_t BufferSize + Sha1Context* Context, // [in out] + void const* Buffer, // [in] + uint32_t BufferSize // [in] ) { uint32_t i; @@ -223,8 +223,8 @@ void void Sha1Finalise ( - Sha1Context* Context, - SHA1_HASH* Digest + Sha1Context* Context, // [in out] + SHA1_HASH* Digest // [in] ) { uint32_t i; diff --git a/lib/CryptLib_Sha1.h b/lib/CryptLib_Sha1.h index 7e00089..8e15442 100644 --- a/lib/CryptLib_Sha1.h +++ b/lib/CryptLib_Sha1.h @@ -50,7 +50,7 @@ typedef struct void Sha1Initialise ( - Sha1Context* Context + Sha1Context* Context // [out] ); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -62,9 +62,9 @@ void void Sha1Update ( - Sha1Context* Context, - void const* Buffer, - uint32_t BufferSize + Sha1Context* Context, // [in out] + void const* Buffer, // [in] + uint32_t BufferSize // [in] ); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -76,6 +76,6 @@ void void Sha1Finalise ( - Sha1Context* Context, - SHA1_HASH* Digest + Sha1Context* Context, // [in out] + SHA1_HASH* Digest // [in] ); diff --git a/lib/CryptLib_Sha256.c b/lib/CryptLib_Sha256.c index 59071d8..5e2f679 100644 --- a/lib/CryptLib_Sha256.c +++ b/lib/CryptLib_Sha256.c @@ -151,9 +151,10 @@ void // // Initialises a SHA256 Context. Use this to initialise/reset a context. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void Sha256Initialise +void + Sha256Initialise ( - Sha256Context* Context + Sha256Context* Context // [out] ) { Context->curlen = 0; @@ -174,15 +175,16 @@ void Sha256Initialise // Adds data to the SHA256 context. This will process the data and update the internal state of the context. Keep on // calling this function until all the data has been added. Then call Sha256Finalise to calculate the hash. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void Sha256Update +void + Sha256Update ( - Sha256Context* Context, - void const* Buffer, - uint32_t BufferSize + Sha256Context* Context, // [in out] + void const* Buffer, // [in] + uint32_t BufferSize // [in] ) { - uint32_t n - ; + uint32_t n; + if( Context->curlen > sizeof(Context->buf) ) { return; @@ -223,8 +225,8 @@ void Sha256Update void Sha256Finalise ( - Sha256Context* Context, - SHA256_HASH* Digest + Sha256Context* Context, // [in out] + SHA256_HASH* Digest // [out] ) { int i; diff --git a/lib/CryptLib_Sha256.h b/lib/CryptLib_Sha256.h index cf7d839..7e6aadd 100644 --- a/lib/CryptLib_Sha256.h +++ b/lib/CryptLib_Sha256.h @@ -41,9 +41,10 @@ typedef struct // // Initialises a SHA256 Context. Use this to initialise/reset a context. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void Sha256Initialise +void + Sha256Initialise ( - Sha256Context* Context + Sha256Context* Context // [out] ); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -52,11 +53,12 @@ void Sha256Initialise // Adds data to the SHA256 context. This will process the data and update the internal state of the context. Keep on // calling this function until all the data has been added. Then call Sha256Finalise to calculate the hash. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void Sha256Update +void + Sha256Update ( - Sha256Context* Context, - void const* Buffer, - uint32_t BufferSize + Sha256Context* Context, // [in out] + void const* Buffer, // [in] + uint32_t BufferSize // [in] ); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -68,6 +70,6 @@ void Sha256Update void Sha256Finalise ( - Sha256Context* Context, - SHA256_HASH* Digest + Sha256Context* Context, // [in out] + SHA256_HASH* Digest // [out] ); diff --git a/lib/CryptLib_Sha512.c b/lib/CryptLib_Sha512.c index e6d8c7e..43fb3b2 100644 --- a/lib/CryptLib_Sha512.c +++ b/lib/CryptLib_Sha512.c @@ -154,7 +154,7 @@ void void Sha512Initialise ( - Sha512Context* Context + Sha512Context* Context // [out] ) { Context->curlen = 0; @@ -178,9 +178,9 @@ void void Sha512Update ( - Sha512Context* Context, - void const* Buffer, - uint32_t BufferSize + Sha512Context* Context, // [in out] + void const* Buffer, // [in] + uint32_t BufferSize // [in] ) { uint32_t n; @@ -225,8 +225,8 @@ void void Sha512Finalise ( - Sha512Context* Context, - SHA512_HASH* Digest + Sha512Context* Context, // [in out] + SHA512_HASH* Digest // [out] ) { int i; diff --git a/lib/CryptLib_Sha512.h b/lib/CryptLib_Sha512.h index 5cade5e..2d63eef 100644 --- a/lib/CryptLib_Sha512.h +++ b/lib/CryptLib_Sha512.h @@ -41,9 +41,10 @@ typedef struct // // Initialises a SHA512 Context. Use this to initialise/reset a context. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void Sha512Initialise +void + Sha512Initialise ( - Sha512Context* Context + Sha512Context* Context // [out] ); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -52,11 +53,12 @@ void Sha512Initialise // Adds data to the SHA512 context. This will process the data and update the internal state of the context. Keep on // calling this function until all the data has been added. Then call Sha512Finalise to calculate the hash. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void Sha512Update +void + Sha512Update ( - Sha512Context* Context, - void const* Buffer, - uint32_t BufferSize + Sha512Context* Context, // [in out] + void const* Buffer, // [in] + uint32_t BufferSize // [in] ); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -68,6 +70,6 @@ void Sha512Update void Sha512Finalise ( - Sha512Context* Context, - SHA512_HASH* Digest + Sha512Context* Context, // [in out] + SHA512_HASH* Digest // [out] ); diff --git a/projects/AesBlock/AesBlock.c b/projects/AesBlock/AesBlock.c index d8a13ea..9648287 100644 --- a/projects/AesBlock/AesBlock.c +++ b/projects/AesBlock/AesBlock.c @@ -146,9 +146,9 @@ int switch( keySize ) { - case 128/8: AesInitialise128( key, &aesContext ); break; - case 192/8: AesInitialise192( key, &aesContext ); break; - case 256/8: AesInitialise256( key, &aesContext ); break; + case 128/8: AesInitialise( &aesContext, key, AES_KEY_SIZE_128 ); break; + case 192/8: AesInitialise( &aesContext, key, AES_KEY_SIZE_192 ); break; + case 256/8: AesInitialise( &aesContext, key, AES_KEY_SIZE_256 ); break; default: printf( "Invalid key size, must be 128, 192, or 256 bits (was %u bits)\n", keySize*8 ); exit( 1 ); diff --git a/projects/AesCtrOutput/AesCtrOutput.c b/projects/AesCtrOutput/AesCtrOutput.c index aef921c..98ea4f6 100644 --- a/projects/AesCtrOutput/AesCtrOutput.c +++ b/projects/AesCtrOutput/AesCtrOutput.c @@ -101,7 +101,7 @@ int uint8_t buffer [BUFFER_SIZE]; uint32_t amountLeft; uint32_t chunk; - AesCtrContext aesCtr = {{0}}; + AesCtrContext aesCtr; uint8_t key [AES_KEY_SIZE_256]; uint32_t keySize = sizeof(key); uint8_t IV [AES_CTR_IV_SIZE]; @@ -134,7 +134,7 @@ int numBytes = atoi( ArgV[3] ); - AesCtrInitialiseWithKey( key, keySize, IV, &aesCtr ); + AesCtrInitialiseWithKey( &aesCtr, key, keySize, IV ); amountLeft = numBytes; while( amountLeft > 0 ) diff --git a/projects/CryptLibTest/CryptLibTest_Aes.c b/projects/CryptLibTest/CryptLibTest_Aes.c index 6e435ed..813404c 100644 --- a/projects/CryptLibTest/CryptLibTest_Aes.c +++ b/projects/CryptLibTest/CryptLibTest_Aes.c @@ -117,15 +117,15 @@ bool for( i=0; i #include #include "CryptLib_AesCtr.h" +#include "CryptLib_Sha1.h" //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // MACROS @@ -163,6 +164,76 @@ bool return true; } +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// TestLargeVector +// +// Tests AES CTR against a known large vector (of 1 million bytes). We check it against a known SHA-1 hash of +// the output. +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +static +bool + TestLargeVector + ( + void + ) +{ + +//dd if=/dev/zero iflag=count_bytes count=1000000 status=none | openssl enc -aes-128-ctr -K 00001111222233334444555566667777 -iv 88889999aaaabbbb | openssl sha1 +//(stdin)= 6227c0192b110133fadd6d229790bbdf13c068ab + + uint8_t const* key = (uint8_t const*)"\x00\x00\x11\x11\x22\x22\x33\x33\x44\x44\x55\x55\x66\x66\x77\x77"; + uint8_t const* iv = (uint8_t const*)"\x88\x88\x99\x99\xaa\xaa\xbb\xbb"; + uint8_t const* sha1Hash = (uint8_t const*)"\xe1\x63\x5f\xa4\xf5\x7c\x98\x54\xf6\x18\xec\x0c\x8f\x18\x7f\x04\x34\xa2\xe1\x72"; + uint32_t const numBytesToGenerate = 1000000; + + uint8_t* buffer = malloc( numBytesToGenerate ); + uint32_t amountLeft = numBytesToGenerate; + uint32_t chunkSize; + Sha1Context sha1Context; + AesCtrContext aesCtrContext; + SHA1_HASH calcSha1; + + // Encrypt in one go first. + memset( buffer, 0, numBytesToGenerate ); + AesCtrXorWithKey( key, AES_KEY_SIZE_128, iv, buffer, buffer, numBytesToGenerate ); + + Sha1Initialise( &sha1Context ); + Sha1Update( &sha1Context, buffer, numBytesToGenerate ); + Sha1Finalise( &sha1Context, &calcSha1 ); + + if( 0 != memcmp( &calcSha1, sha1Hash, SHA1_HASH_SIZE ) ) + { + printf( "Large test vector failed\n" ); + return false; + } + + memset( buffer, 0, numBytesToGenerate ); + + // Now encrypt in smaller pieces (10000 bytes at a time) + Sha1Initialise( &sha1Context ); + AesCtrInitialiseWithKey( &aesCtrContext, key, AES_KEY_SIZE_128, iv ); + + while( amountLeft > 0 ) + { + memset( buffer, 0, numBytesToGenerate ); + chunkSize = MIN( amountLeft, 10000 ); + AesCtrOutput( &aesCtrContext, buffer, chunkSize ); + Sha1Update( &sha1Context, buffer, chunkSize ); + amountLeft -= chunkSize; + } + + Sha1Finalise( &sha1Context, &calcSha1 ); + + if( 0 != memcmp( &calcSha1, sha1Hash, SHA1_HASH_SIZE ) ) + { + printf( "Large test vector failed\n" ); + return false; + } + + return true; +} + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // TestStreamConsistency // @@ -199,7 +270,7 @@ bool } // Now recreate the stream in small bits. Starting at 1 byte at a time and increasing chunk size - AesCtrInitialiseWithKey( key, sizeof(key), iv, &context ); + AesCtrInitialiseWithKey( &context, key, sizeof(key), iv ); for( chunkSize=1; chunkSize<64; chunkSize++ ) { uint32_t amountLeft = STREAMSIZE; @@ -262,7 +333,7 @@ bool 0xf8, 0x8f, 0x45, 0xd1, 0xf6, 0x68, 0x28, 0x54, 0x6f, 0xef, 0xce, 0xf9, 0x23, 0x1b, 0xb0, 0x08 }; - AesCtrInitialiseWithKey( key, sizeof(key), iv, &context ); + AesCtrInitialiseWithKey( &context, key, sizeof(key), iv ); AesCtrSetStreamIndex( &context, positionIndex ); AesCtrOutput( &context, output, sizeof(output) ); @@ -296,6 +367,9 @@ bool success = TestVectors( ); if( !success ) { totalSuccess = false; } + success = TestLargeVector( ); + if( !success ) { totalSuccess = false; } + success = TestStreamConsistency( ); if( !success ) { totalSuccess = false; }