Package org.bouncycastle.crypto.engines

Source Code of org.bouncycastle.crypto.engines.RijndaelEngine

package org.bouncycastle.crypto.engines;

import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.OutputLengthException;
import org.bouncycastle.crypto.params.KeyParameter;

/**
* an implementation of Rijndael, based on the documentation and reference implementation
* by Paulo Barreto, Vincent Rijmen, for v2.0 August '99.
* <p>
* Note: this implementation is based on information prior to final NIST publication.
*/
public class RijndaelEngine
    implements BlockCipher
{
    private static final int MAXROUNDS = 14;

    private static final int MAXKC = (256/4);

    private static final byte[] logtable = {
        (byte)0,    (byte)0,    (byte)25,   (byte)1,    (byte)50,   (byte)2,    (byte)26,   (byte)198,
        (byte)75,   (byte)199(byte)27,   (byte)104(byte)51,   (byte)238(byte)223(byte)3,
        (byte)100(byte)4,    (byte)224(byte)14,   (byte)52,   (byte)141(byte)129(byte)239,
        (byte)76,   (byte)113(byte)8,    (byte)200(byte)248(byte)105(byte)28,   (byte)193,
        (byte)125(byte)194(byte)29,   (byte)181(byte)249(byte)185(byte)39,   (byte)106,
        (byte)77,   (byte)228(byte)166(byte)114(byte)154(byte)201(byte)9,    (byte)120,
        (byte)101(byte)47,   (byte)138(byte)5,    (byte)33,   (byte)15,   (byte)225(byte)36,
        (byte)18,   (byte)240(byte)130(byte)69,   (byte)53,   (byte)147(byte)218(byte)142,
        (byte)150(byte)143(byte)219(byte)189(byte)54,   (byte)208(byte)206(byte)148,
        (byte)19,   (byte)92,   (byte)210(byte)241(byte)64,   (byte)70,   (byte)131(byte)56,
        (byte)102(byte)221(byte)253(byte)48,   (byte)191(byte)6,    (byte)139(byte)98,
        (byte)179(byte)37,   (byte)226(byte)152(byte)34,   (byte)136(byte)145(byte)16,
        (byte)126(byte)110(byte)72,   (byte)195(byte)163(byte)182(byte)30,   (byte)66,
        (byte)58,   (byte)107(byte)40,   (byte)84,   (byte)250(byte)133(byte)61,   (byte)186,
        (byte)43,   (byte)121(byte)10,   (byte)21,   (byte)155(byte)159(byte)94,   (byte)202,
        (byte)78,   (byte)212(byte)172(byte)229(byte)243(byte)115(byte)167(byte)87,
        (byte)175(byte)88,   (byte)168(byte)80,   (byte)244(byte)234(byte)214(byte)116,
        (byte)79,   (byte)174(byte)233(byte)213(byte)231(byte)230(byte)173(byte)232,
        (byte)44,   (byte)215(byte)117(byte)122(byte)235(byte)22,   (byte)11,   (byte)245,
        (byte)89,   (byte)203(byte)95,   (byte)176(byte)156(byte)169(byte)81,   (byte)160,
        (byte)127(byte)12,   (byte)246(byte)111(byte)23,   (byte)196(byte)73,   (byte)236,
        (byte)216(byte)67,   (byte)31,   (byte)45,   (byte)164(byte)118(byte)123(byte)183,
        (byte)204(byte)187(byte)62,   (byte)90,   (byte)251(byte)96,   (byte)177(byte)134,
        (byte)59,   (byte)82,   (byte)161(byte)108(byte)170(byte)85,   (byte)41,   (byte)157,
        (byte)151(byte)178(byte)135(byte)144(byte)97,   (byte)190(byte)220(byte)252,
        (byte)188(byte)149(byte)207(byte)205(byte)55,   (byte)63,   (byte)91,   (byte)209,
        (byte)83,   (byte)57,   (byte)132(byte)60,   (byte)65,   (byte)162(byte)109(byte)71,
        (byte)20,   (byte)42,   (byte)158(byte)93,   (byte)86,   (byte)242(byte)211(byte)171,
        (byte)68,   (byte)17,   (byte)146(byte)217(byte)35,   (byte)32,   (byte)46,   (byte)137,
        (byte)180(byte)124(byte)184(byte)38,   (byte)119(byte)153(byte)227(byte)165,
        (byte)103(byte)74,   (byte)237(byte)222(byte)197(byte)49,   (byte)254(byte)24,
        (byte)13,   (byte)99,   (byte)140(byte)128(byte)192(byte)247(byte)112(byte)7
    };

    private static final byte[] aLogtable = {
          (byte)0,   (byte)3,   (byte)5(byte)15(byte)17(byte)51(byte)85, (byte)255(byte)26(byte)46, (byte)114, (byte)150, (byte)161, (byte)248(byte)19(byte)53,
         (byte)95, (byte)225(byte)56(byte)72, (byte)216, (byte)115, (byte)149, (byte)164, (byte)247,   (byte)2,   (byte)6(byte)10(byte)30(byte)34, (byte)102, (byte)170,
        (byte)229(byte)52(byte)92, (byte)228(byte)55(byte)89, (byte)235(byte)38, (byte)106, (byte)190, (byte)217, (byte)112, (byte)144, (byte)171, (byte)230(byte)49,
         (byte)83, (byte)245,   (byte)4(byte)12(byte)20(byte)60(byte)68, (byte)204(byte)79, (byte)209, (byte)104, (byte)184, (byte)211, (byte)110, (byte)178, (byte)205,
         (byte)76, (byte)212, (byte)103, (byte)169, (byte)224(byte)59(byte)77, (byte)215(byte)98, (byte)166, (byte)241,   (byte)8(byte)24(byte)40, (byte)120, (byte)136,
        (byte)131, (byte)158, (byte)185, (byte)208, (byte)107, (byte)189, (byte)220, (byte)127, (byte)129, (byte)152, (byte)179, (byte)206(byte)73, (byte)219, (byte)118, (byte)154,
        (byte)181, (byte)196(byte)87, (byte)249(byte)16(byte)48(byte)80, (byte)240(byte)11(byte)29(byte)39, (byte)105, (byte)187, (byte)214(byte)97, (byte)163,
        (byte)254(byte)25(byte)43, (byte)125, (byte)135, (byte)146, (byte)173, (byte)236(byte)47, (byte)113, (byte)147, (byte)174, (byte)233(byte)32(byte)96, (byte)160,
        (byte)251(byte)22(byte)58(byte)78, (byte)210, (byte)109, (byte)183, (byte)194(byte)93, (byte)231(byte)50(byte)86, (byte)250(byte)21(byte)63(byte)65,
        (byte)195(byte)94, (byte)226(byte)61(byte)71, (byte)201(byte)64, (byte)192(byte)91, (byte)237(byte)44, (byte)116, (byte)156, (byte)191, (byte)218, (byte)117,
        (byte)159, (byte)186, (byte)213, (byte)100, (byte)172, (byte)239(byte)42, (byte)126, (byte)130, (byte)157, (byte)188, (byte)223, (byte)122, (byte)142, (byte)137, (byte)128,
        (byte)155, (byte)182, (byte)193(byte)88, (byte)232(byte)35, (byte)101, (byte)175, (byte)234(byte)37, (byte)111, (byte)177, (byte)200(byte)67, (byte)197(byte)84,
        (byte)252(byte)31(byte)33(byte)99, (byte)165, (byte)244,   (byte)7,   (byte)9(byte)27(byte)45, (byte)119, (byte)153, (byte)176, (byte)203(byte)70, (byte)202,
         (byte)69, (byte)207(byte)74, (byte)222, (byte)121, (byte)139, (byte)134, (byte)145, (byte)168, (byte)227(byte)62(byte)66, (byte)198(byte)81, (byte)243(byte)14,
         (byte)18(byte)54(byte)90, (byte)238(byte)41, (byte)123, (byte)141, (byte)140, (byte)143, (byte)138, (byte)133, (byte)148, (byte)167, (byte)242(byte)13(byte)23,
         (byte)57(byte)75, (byte)221, (byte)124, (byte)132, (byte)151, (byte)162, (byte)253(byte)28(byte)36, (byte)108, (byte)180, (byte)199(byte)82, (byte)246,   (byte)1,
          (byte)3,   (byte)5(byte)15(byte)17(byte)51(byte)85, (byte)255(byte)26(byte)46, (byte)114, (byte)150, (byte)161, (byte)248(byte)19(byte)53,
         (byte)95, (byte)225(byte)56(byte)72, (byte)216, (byte)115, (byte)149, (byte)164, (byte)247,   (byte)2,   (byte)6(byte)10(byte)30(byte)34, (byte)102, (byte)170,
        (byte)229(byte)52(byte)92, (byte)228(byte)55(byte)89, (byte)235(byte)38, (byte)106, (byte)190, (byte)217, (byte)112, (byte)144, (byte)171, (byte)230(byte)49,
         (byte)83, (byte)245,   (byte)4(byte)12(byte)20(byte)60(byte)68, (byte)204(byte)79, (byte)209, (byte)104, (byte)184, (byte)211, (byte)110, (byte)178, (byte)205,
         (byte)76, (byte)212, (byte)103, (byte)169, (byte)224(byte)59(byte)77, (byte)215(byte)98, (byte)166, (byte)241,   (byte)8(byte)24(byte)40, (byte)120, (byte)136,
        (byte)131, (byte)158, (byte)185, (byte)208, (byte)107, (byte)189, (byte)220, (byte)127, (byte)129, (byte)152, (byte)179, (byte)206(byte)73, (byte)219, (byte)118, (byte)154,
        (byte)181, (byte)196(byte)87, (byte)249(byte)16(byte)48(byte)80, (byte)240(byte)11(byte)29(byte)39, (byte)105, (byte)187, (byte)214(byte)97, (byte)163,
        (byte)254(byte)25(byte)43, (byte)125, (byte)135, (byte)146, (byte)173, (byte)236(byte)47, (byte)113, (byte)147, (byte)174, (byte)233(byte)32(byte)96, (byte)160,
        (byte)251(byte)22(byte)58(byte)78, (byte)210, (byte)109, (byte)183, (byte)194(byte)93, (byte)231(byte)50(byte)86, (byte)250(byte)21(byte)63(byte)65,
        (byte)195(byte)94, (byte)226(byte)61(byte)71, (byte)201(byte)64, (byte)192(byte)91, (byte)237(byte)44, (byte)116, (byte)156, (byte)191, (byte)218, (byte)117,
        (byte)159, (byte)186, (byte)213, (byte)100, (byte)172, (byte)239(byte)42, (byte)126, (byte)130, (byte)157, (byte)188, (byte)223, (byte)122, (byte)142, (byte)137, (byte)128,
        (byte)155, (byte)182, (byte)193(byte)88, (byte)232(byte)35, (byte)101, (byte)175, (byte)234(byte)37, (byte)111, (byte)177, (byte)200(byte)67, (byte)197(byte)84,
        (byte)252(byte)31(byte)33(byte)99, (byte)165, (byte)244,   (byte)7,   (byte)9(byte)27(byte)45, (byte)119, (byte)153, (byte)176, (byte)203(byte)70, (byte)202,
         (byte)69, (byte)207(byte)74, (byte)222, (byte)121, (byte)139, (byte)134, (byte)145, (byte)168, (byte)227(byte)62(byte)66, (byte)198(byte)81, (byte)243(byte)14,
         (byte)18(byte)54(byte)90, (byte)238(byte)41, (byte)123, (byte)141, (byte)140, (byte)143, (byte)138, (byte)133, (byte)148, (byte)167, (byte)242(byte)13(byte)23,
         (byte)57(byte)75, (byte)221, (byte)124, (byte)132, (byte)151, (byte)162, (byte)253(byte)28(byte)36, (byte)108, (byte)180, (byte)199(byte)82, (byte)246,   (byte)1,
        };

    private static final byte[] S = {
         (byte)99, (byte)124, (byte)119, (byte)123, (byte)242, (byte)107, (byte)111, (byte)197(byte)48,   (byte)1, (byte)103(byte)43, (byte)254, (byte)215, (byte)171, (byte)118,
        (byte)202, (byte)130, (byte)201, (byte)125, (byte)250(byte)89(byte)71, (byte)240, (byte)173, (byte)212, (byte)162, (byte)175, (byte)156, (byte)164, (byte)114, (byte)192,
        (byte)183, (byte)253, (byte)147(byte)38(byte)54(byte)63, (byte)247, (byte)204(byte)52, (byte)165, (byte)229, (byte)241, (byte)113, (byte)216(byte)49(byte)21,
          (byte)4, (byte)199(byte)35, (byte)195(byte)24, (byte)150,   (byte)5, (byte)154,   (byte)7(byte)18, (byte)128, (byte)226, (byte)235(byte)39, (byte)178, (byte)117,
          (byte)9, (byte)131(byte)44(byte)26(byte)27, (byte)110(byte)90, (byte)160(byte)82(byte)59, (byte)214, (byte)179(byte)41, (byte)227(byte)47, (byte)132,
         (byte)83, (byte)209,   (byte)0, (byte)237(byte)32, (byte)252, (byte)177(byte)91, (byte)106, (byte)203, (byte)190(byte)57(byte)74(byte)76(byte)88, (byte)207,
        (byte)208, (byte)239, (byte)170, (byte)251(byte)67(byte)77(byte)51, (byte)133(byte)69, (byte)249,   (byte)2, (byte)127(byte)80(byte)60, (byte)159, (byte)168,
         (byte)81, (byte)163(byte)64, (byte)143, (byte)146, (byte)157(byte)56, (byte)245, (byte)188, (byte)182, (byte)218(byte)33(byte)16, (byte)255, (byte)243, (byte)210,
        (byte)205(byte)12(byte)19, (byte)236(byte)95, (byte)151(byte)68(byte)23, (byte)196, (byte)167, (byte)126(byte)61, (byte)100(byte)93(byte)25, (byte)115,
         (byte)96, (byte)129(byte)79, (byte)220(byte)34(byte)42, (byte)144, (byte)136(byte)70, (byte)238, (byte)184(byte)20, (byte)222(byte)94(byte)11, (byte)219,
        (byte)224(byte)50(byte)58(byte)10(byte)73,   (byte)6(byte)36(byte)92, (byte)194, (byte)211, (byte)172(byte)98, (byte)145, (byte)149, (byte)228, (byte)121,
        (byte)231, (byte)200(byte)55, (byte)109, (byte)141, (byte)213(byte)78, (byte)169, (byte)108(byte)86, (byte)244, (byte)234, (byte)101, (byte)122, (byte)174,   (byte)8,
        (byte)186, (byte)120(byte)37(byte)46(byte)28, (byte)166, (byte)180, (byte)198, (byte)232, (byte)221, (byte)116(byte)31(byte)75, (byte)189, (byte)139, (byte)138,
        (byte)112(byte)62, (byte)181, (byte)102(byte)72,   (byte)3, (byte)246(byte)14(byte)97(byte)53(byte)87, (byte)185, (byte)134, (byte)193(byte)29, (byte)158,
        (byte)225, (byte)248, (byte)152(byte)17, (byte)105, (byte)217, (byte)142, (byte)148, (byte)155(byte)30, (byte)135, (byte)233, (byte)206(byte)85(byte)40, (byte)223,
        (byte)140, (byte)161, (byte)137(byte)13, (byte)191, (byte)230(byte)66, (byte)104(byte)65, (byte)153(byte)45(byte)15, (byte)176(byte)84, (byte)187(byte)22,
    };

    private static final byte[] Si = {
         (byte)82,   (byte)9, (byte)106, (byte)213(byte)48(byte)54, (byte)165(byte)56, (byte)191(byte)64, (byte)163, (byte)158, (byte)129, (byte)243, (byte)215, (byte)251,
        (byte)124, (byte)227(byte)57, (byte)130, (byte)155(byte)47, (byte)255, (byte)135(byte)52, (byte)142(byte)67(byte)68, (byte)196, (byte)222, (byte)233, (byte)203,
         (byte)84, (byte)123, (byte)148(byte)50, (byte)166, (byte)194(byte)35(byte)61, (byte)238(byte)76, (byte)149(byte)11(byte)66, (byte)250, (byte)195(byte)78,
          (byte)8(byte)46, (byte)161, (byte)102(byte)40, (byte)217(byte)36, (byte)178, (byte)118(byte)91, (byte)162(byte)73, (byte)109, (byte)139, (byte)209(byte)37,
        (byte)114, (byte)248, (byte)246, (byte)100, (byte)134, (byte)104, (byte)152(byte)22, (byte)212, (byte)164(byte)92, (byte)204(byte)93, (byte)101, (byte)182, (byte)146,
        (byte)108, (byte)112(byte)72(byte)80, (byte)253, (byte)237, (byte)185, (byte)218(byte)94(byte)21(byte)70(byte)87, (byte)167, (byte)141, (byte)157, (byte)132,
        (byte)144, (byte)216, (byte)171,   (byte)0, (byte)140, (byte)188, (byte)211(byte)10, (byte)247, (byte)228(byte)88,   (byte)5, (byte)184, (byte)179(byte)69,   (byte)6,
        (byte)208(byte)44(byte)30, (byte)143, (byte)202(byte)63(byte)15,   (byte)2, (byte)193, (byte)175, (byte)189,   (byte)3,   (byte)1(byte)19, (byte)138, (byte)107,
         (byte)58, (byte)145(byte)17(byte)65(byte)79, (byte)103, (byte)220, (byte)234, (byte)151, (byte)242, (byte)207, (byte)206, (byte)240, (byte)180, (byte)230, (byte)115,
        (byte)150, (byte)172, (byte)116(byte)34, (byte)231, (byte)173(byte)53, (byte)133, (byte)226, (byte)249(byte)55, (byte)232(byte)28, (byte)117, (byte)223, (byte)110,
         (byte)71, (byte)241(byte)26, (byte)113(byte)29(byte)41, (byte)197, (byte)137, (byte)111, (byte)183(byte)98(byte)14, (byte)170(byte)24, (byte)190(byte)27,
        (byte)252(byte)86(byte)62(byte)75, (byte)198, (byte)210, (byte)121(byte)32, (byte)154, (byte)219, (byte)192, (byte)254, (byte)120, (byte)205(byte)90, (byte)244,
         (byte)31, (byte)221, (byte)168(byte)51, (byte)136,   (byte)7, (byte)199(byte)49, (byte)177(byte)18(byte)16(byte)89(byte)39, (byte)128, (byte)236(byte)95,
         (byte)96(byte)81, (byte)127, (byte)169(byte)25, (byte)181(byte)74(byte)13(byte)45, (byte)229, (byte)122, (byte)159, (byte)147, (byte)201, (byte)156, (byte)239,
        (byte)160, (byte)224(byte)59(byte)77, (byte)174(byte)42, (byte)245, (byte)176, (byte)200, (byte)235, (byte)187(byte)60, (byte)131(byte)83, (byte)153(byte)97,
         (byte)23(byte)43,   (byte)4, (byte)126, (byte)186, (byte)119, (byte)214(byte)38, (byte)225, (byte)105(byte)20(byte)99(byte)85(byte)33(byte)12, (byte)125,
        };

    private static final int[] rcon = {
          0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 };

    static byte[][] shifts0 =
    {
       { 0, 8, 16, 24 },
       { 0, 8, 16, 24 },
       { 0, 8, 16, 24 },
       { 0, 8, 16, 32 },
       { 0, 8, 24, 32 }
    };

    static byte[][] shifts1 =
    {
       { 0, 24, 16, 8 },
       { 0, 32, 24, 16 },
       { 0, 40, 32, 24 },
       { 0, 48, 40, 24 },
       { 0, 56, 40, 32 }
    };

    /**
     * multiply two elements of GF(2^m)
     * needed for MixColumn and InvMixColumn
     */
    private byte mul0x2(
        int b)
    {
        if (b != 0)
        {
            return aLogtable[25 + (logtable[b] & 0xff)];
        }
        else
        {
            return 0;
        }
    }

    private byte mul0x3(
        int b)
    {
        if (b != 0)
        {
            return aLogtable[1 + (logtable[b] & 0xff)];
        }
        else
        {
            return 0;
        }
    }

    private byte mul0x9(
        int b)
    {
        if (b >= 0)
        {
            return aLogtable[199 + b];
        }
        else
        {
            return 0;
        }
    }

    private byte mul0xb(
        int b)
    {
        if (b >= 0)
        {
            return aLogtable[104 + b];
        }
        else
        {
            return 0;
        }
    }

    private byte mul0xd(
        int b)
    {
        if (b >= 0)
        {
            return aLogtable[238 + b];
        }
        else
        {
            return 0;
        }
    }

    private byte mul0xe(
        int b)
    {
        if (b >= 0)
        {
            return aLogtable[223 + b];
        }
        else
        {
            return 0;
        }
    }

    /**
     * xor corresponding text input and round key input bytes
     */
    private void KeyAddition(
        long[] rk)
    {
        A0 ^= rk[0];
        A1 ^= rk[1];
        A2 ^= rk[2];
        A3 ^= rk[3];
    }

    private long shift(
        long    r,
        int     shift)
    {
        return (((r >>> shift) | (r << (BC - shift)))) & BC_MASK;
    }

    /**
     * Row 0 remains unchanged
     * The other three rows are shifted a variable amount
     */
    private void ShiftRow(
        byte[]      shiftsSC)
    {
        A1 = shift(A1, shiftsSC[1]);
        A2 = shift(A2, shiftsSC[2]);
        A3 = shift(A3, shiftsSC[3]);
    }

    private long applyS(
        long    r,
        byte[]  box)
    {
        long    res = 0;

        for (int j = 0; j < BC; j += 8)
        {
            res |= (long)(box[(int)((r >> j) & 0xff)] & 0xff) << j;
        }

        return res;
    }

    /**
     * Replace every byte of the input by the byte at that place
     * in the nonlinear S-box
     */
    private void Substitution(
        byte[]      box)
    {
        A0 = applyS(A0, box);
        A1 = applyS(A1, box);
        A2 = applyS(A2, box);
        A3 = applyS(A3, box);
    }

    /**
     * Mix the bytes of every column in a linear way
     */
    private void MixColumn()
    {
        long r0, r1, r2, r3;

        r0 = r1 = r2 = r3 = 0;

        for (int j = 0; j < BC; j += 8)
        {
            int a0 = (int)((A0 >> j) & 0xff);
            int a1 = (int)((A1 >> j) & 0xff);
            int a2 = (int)((A2 >> j) & 0xff);
            int a3 = (int)((A3 >> j) & 0xff);

            r0 |= (long)((mul0x2(a0) ^ mul0x3(a1) ^ a2 ^ a3) & 0xff) << j;

            r1 |= (long)((mul0x2(a1) ^ mul0x3(a2) ^ a3 ^ a0) & 0xff) << j;

            r2 |= (long)((mul0x2(a2) ^ mul0x3(a3) ^ a0 ^ a1) & 0xff) << j;

            r3 |= (long)((mul0x2(a3) ^ mul0x3(a0) ^ a1 ^ a2) & 0xff) << j;
        }

        A0 = r0;
        A1 = r1;
        A2 = r2;
        A3 = r3;
    }

    /**
     * Mix the bytes of every column in a linear way
     * This is the opposite operation of Mixcolumn
     */
    private void InvMixColumn()
    {
        long r0, r1, r2, r3;

        r0 = r1 = r2 = r3 = 0;
        for (int j = 0; j < BC; j += 8)
        {
            int a0 = (int)((A0 >> j) & 0xff);
            int a1 = (int)((A1 >> j) & 0xff);
            int a2 = (int)((A2 >> j) & 0xff);
            int a3 = (int)((A3 >> j) & 0xff);

            //
            // pre-lookup the log table
            //
            a0 = (a0 != 0) ? (logtable[a0 & 0xff] & 0xff) : -1;
            a1 = (a1 != 0) ? (logtable[a1 & 0xff] & 0xff) : -1;
            a2 = (a2 != 0) ? (logtable[a2 & 0xff] & 0xff) : -1;
            a3 = (a3 != 0) ? (logtable[a3 & 0xff] & 0xff) : -1;

            r0 |= (long)((mul0xe(a0) ^ mul0xb(a1) ^ mul0xd(a2) ^ mul0x9(a3)) & 0xff) << j;

            r1 |= (long)((mul0xe(a1) ^ mul0xb(a2) ^ mul0xd(a3) ^ mul0x9(a0)) & 0xff) << j;

            r2 |= (long)((mul0xe(a2) ^ mul0xb(a3) ^ mul0xd(a0) ^ mul0x9(a1)) & 0xff) << j;

            r3 |= (long)((mul0xe(a3) ^ mul0xb(a0) ^ mul0xd(a1) ^ mul0x9(a2)) & 0xff) << j;
        }

        A0 = r0;
        A1 = r1;
        A2 = r2;
        A3 = r3;
    }

    /**
     * Calculate the necessary round keys
     * The number of calculations depends on keyBits and blockBits
     */
    private long[][] generateWorkingKey(
        byte[]      key)
    {
        int         KC;
        int         t, rconpointer = 0;
        int         keyBits = key.length * 8;
        byte[][]    tk = new byte[4][MAXKC];
        long[][]    W = new long[MAXROUNDS+1][4];

        switch (keyBits)
        {
        case 128:
            KC = 4;
            break;
        case 160:
            KC = 5;
            break;
        case 192:
            KC = 6;
            break;
        case 224:
            KC = 7;
            break;
        case 256:
            KC = 8;
            break;
        default :
            throw new IllegalArgumentException("Key length not 128/160/192/224/256 bits.");
        }

        if (keyBits >= blockBits)
        {
            ROUNDS = KC + 6;
        }
        else
        {
            ROUNDS = (BC / 8) + 6;
        }

        //
        // copy the key into the processing area
        //
        int index = 0;

        for (int i = 0; i < key.length; i++)
        {
            tk[i % 4][i / 4] = key[index++];
        }

        t = 0;

        //
        // copy values into round key array
        //
        for (int j = 0; (j < KC) && (t < (ROUNDS+1)*(BC / 8)); j++, t++)
        {
            for (int i = 0; i < 4; i++)
            {
                W[t / (BC / 8)][i] |= (long)(tk[i][j] & 0xff) << ((t * 8) % BC);
            }
        }

        //
        // while not enough round key material calculated
        // calculate new values
        //
        while (t < (ROUNDS+1)*(BC/8))
        {
            for (int i = 0; i < 4; i++)
            {
                tk[i][0] ^= S[tk[(i+1)%4][KC-1] & 0xff];
            }
            tk[0][0] ^= rcon[rconpointer++];

            if (KC <= 6)
            {
                for (int j = 1; j < KC; j++)
                {
                    for (int i = 0; i < 4; i++)
                    {
                        tk[i][j] ^= tk[i][j-1];
                    }
                }
            }
            else
            {
                for (int j = 1; j < 4; j++)
                {
                    for (int i = 0; i < 4; i++)
                    {
                        tk[i][j] ^= tk[i][j-1];
                    }
                }
                for (int i = 0; i < 4; i++)
                {
                    tk[i][4] ^= S[tk[i][3] & 0xff];
                }
                for (int j = 5; j < KC; j++)
                {
                    for (int i = 0; i < 4; i++)
                    {
                        tk[i][j] ^= tk[i][j-1];
                    }
                }
            }

            //
            // copy values into round key array
            //
            for (int j = 0; (j < KC) && (t < (ROUNDS+1)*(BC/8)); j++, t++)
            {
                for (int i = 0; i < 4; i++)
                {
                    W[t / (BC/8)][i] |= (long)(tk[i][j] & 0xff) << ((t * 8) % (BC));
                }
            }
        }

        return W;
    }

    private int         BC;
    private long        BC_MASK;
    private int         ROUNDS;
    private int         blockBits;
    private long[][]    workingKey;
    private long        A0, A1, A2, A3;
    private boolean     forEncryption;
    private byte[]      shifts0SC;
    private byte[]      shifts1SC;

    /**
     * default constructor - 128 bit block size.
     */
    public RijndaelEngine()
    {
        this(128);
    }

    /**
     * basic constructor - set the cipher up for a given blocksize
     *
     * @param blockBits the blocksize in bits, must be 128, 192, or 256.
     */
    public RijndaelEngine(
        int blockBits)
    {
        switch (blockBits)
        {
        case 128:
            BC = 32;
            BC_MASK = 0xffffffffL;
            shifts0SC = shifts0[0];
            shifts1SC = shifts1[0];
            break;
        case 160:
            BC = 40;
            BC_MASK = 0xffffffffffL;
            shifts0SC = shifts0[1];
            shifts1SC = shifts1[1];
            break;
        case 192:
            BC = 48;
            BC_MASK = 0xffffffffffffL;
            shifts0SC = shifts0[2];
            shifts1SC = shifts1[2];
            break;
        case 224:
            BC = 56;
            BC_MASK = 0xffffffffffffffL;
            shifts0SC = shifts0[3];
            shifts1SC = shifts1[3];
            break;
        case 256:
            BC = 64;
            BC_MASK = 0xffffffffffffffffL;
            shifts0SC = shifts0[4];
            shifts1SC = shifts1[4];
            break;
        default:
            throw new IllegalArgumentException("unknown blocksize to Rijndael");
        }

        this.blockBits = blockBits;
    }

    /**
     * initialise a Rijndael cipher.
     *
     * @param forEncryption whether or not we are for encryption.
     * @param params the parameters required to set up the cipher.
     * @exception IllegalArgumentException if the params argument is
     * inappropriate.
     */
    public void init(
        boolean           forEncryption,
        CipherParameters  params)
    {
        if (params instanceof KeyParameter)
        {
            workingKey = generateWorkingKey(((KeyParameter)params).getKey());
            this.forEncryption = forEncryption;
            return;
        }

        throw new IllegalArgumentException("invalid parameter passed to Rijndael init - " + params.getClass().getName());
    }

    public String getAlgorithmName()
    {
        return "Rijndael";
    }

    public int getBlockSize()
    {
        return BC / 2;
    }

    public int processBlock(
        byte[] in,
        int inOff,
        byte[] out,
        int outOff)
    {
        if (workingKey == null)
        {
            throw new IllegalStateException("Rijndael engine not initialised");
        }

        if ((inOff + (BC / 2)) > in.length)
        {
            throw new DataLengthException("input buffer too short");
        }

        if ((outOff + (BC / 2)) > out.length)
        {
            throw new OutputLengthException("output buffer too short");
        }

        if (forEncryption)
        {
            unpackBlock(in, inOff);
            encryptBlock(workingKey);
            packBlock(out, outOff);
        }
        else
        {
            unpackBlock(in, inOff);
            decryptBlock(workingKey);
            packBlock(out, outOff);
        }

        return BC / 2;
    }

    public void reset()
    {
    }

    private void unpackBlock(
        byte[]      bytes,
        int         off)
    {
        int     index = off;

        A0 = (bytes[index++] & 0xff);
        A1 = (bytes[index++] & 0xff);
        A2 = (bytes[index++] & 0xff);
        A3 = (bytes[index++] & 0xff);

        for (int j = 8; j != BC; j += 8)
        {
            A0 |= (long)(bytes[index++] & 0xff) << j;
            A1 |= (long)(bytes[index++] & 0xff) << j;
            A2 |= (long)(bytes[index++] & 0xff) << j;
            A3 |= (long)(bytes[index++] & 0xff) << j;
        }
    }

    private void packBlock(
        byte[]      bytes,
        int         off)
    {
        int     index = off;

        for (int j = 0; j != BC; j += 8)
        {
            bytes[index++] = (byte)(A0 >> j);
            bytes[index++] = (byte)(A1 >> j);
            bytes[index++] = (byte)(A2 >> j);
            bytes[index++] = (byte)(A3 >> j);
        }
    }

    private void encryptBlock(
        long[][] rk)
    {
        int r;

        //
        // begin with a key addition
        //
        KeyAddition(rk[0]);

        //
        // ROUNDS-1 ordinary rounds
        //
        for (r = 1; r < ROUNDS; r++)
        {
            Substitution(S);
            ShiftRow(shifts0SC);
            MixColumn();
            KeyAddition(rk[r]);
        }

        //
        // Last round is special: there is no MixColumn
        //
        Substitution(S);
        ShiftRow(shifts0SC);
        KeyAddition(rk[ROUNDS]);
    }

    private void decryptBlock(
        long[][] rk)
    {
        int r;

        // To decrypt: apply the inverse operations of the encrypt routine,
        //             in opposite order
        //
        // (KeyAddition is an involution: it 's equal to its inverse)
        // (the inverse of Substitution with table S is Substitution with the inverse table of S)
        // (the inverse of Shiftrow is Shiftrow over a suitable distance)
        //

        // First the special round:
        //   without InvMixColumn
        //   with extra KeyAddition
        //
        KeyAddition(rk[ROUNDS]);
        Substitution(Si);
        ShiftRow(shifts1SC);

        //
        // ROUNDS-1 ordinary rounds
        //
        for (r = ROUNDS-1; r > 0; r--)
        {
            KeyAddition(rk[r]);
            InvMixColumn();
            Substitution(Si);
            ShiftRow(shifts1SC);
        }

        //
        // End with the extra key addition
        //
        KeyAddition(rk[0]);
    }
}
TOP

Related Classes of org.bouncycastle.crypto.engines.RijndaelEngine

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.