Example #1
0
        private void gCTRPartial(byte[] buf, int off, int len, byte[] output, int outOff)
        {
            byte[] tmp = GetNextCounterBlock();

            GcmUtilities.Xor(tmp, buf, off, len);
            Array.Copy(tmp, 0, output, outOff, len);

            gHASHPartial(S, forEncryption ? tmp : buf, 0, len);

            totalLength += (uint)len;
        }
Example #2
0
        private void gCTRBlock(byte[] block, byte[] output, int outOff)
        {
            byte[] tmp = GetNextCounterBlock();

            GcmUtilities.Xor(tmp, block);
            Array.Copy(tmp, 0, output, outOff, BlockSize);

            gHASHBlock(S, forEncryption ? tmp : block);

            totalLength += BlockSize;
        }
Example #3
0
 private byte[] gHASH(byte[] b)
 {
     byte[] array = new byte[16];
     for (int i = 0; i < b.Length; i += 16)
     {
         byte[] array2 = new byte[16];
         int    length = Math.Min(b.Length - i, 16);
         Array.Copy(b, i, array2, 0, length);
         GcmUtilities.Xor(array, array2);
         multiplier.MultiplyH(array);
     }
     return(array);
 }
Example #4
0
 private byte[] gHASH(byte[] b)
 {
     byte[] numArray = new byte[16];
     for (int sourceIndex = 0; sourceIndex < b.Length; sourceIndex += 16)
     {
         byte[] val    = new byte[16];
         int    length = Math.Min(b.Length - sourceIndex, 16);
         Array.Copy((Array)b, sourceIndex, (Array)val, 0, length);
         GcmUtilities.Xor(numArray, val);
         this.multiplier.MultiplyH(numArray);
     }
     return(numArray);
 }
Example #5
0
        private byte[] gHASH(byte[] b)
        {
            byte[] Y = new byte[16];

            for (int pos = 0; pos < b.Length; pos += 16)
            {
                byte[] X   = new byte[16];
                int    num = System.Math.Min(b.Length - pos, 16);
                Array.Copy(b, pos, X, 0, num);
                GcmUtilities.Xor(Y, X);
                multiplier.MultiplyH(Y);
            }

            return(Y);
        }
    public void Init(byte[] H)
    {
        if (M == null)
        {
            M = new uint[16][][];
        }
        else if (Arrays.AreEqual(this.H, H))
        {
            return;
        }
        this.H    = Arrays.Clone(H);
        M[0]      = new uint[256][];
        M[0][0]   = new uint[4];
        M[0][128] = GcmUtilities.AsUints(H);
        for (int num = 64; num >= 1; num >>= 1)
        {
            uint[] array = (uint[])M[0][num + num].Clone();
            GcmUtilities.MultiplyP(array);
            M[0][num] = array;
        }
        int num2 = 0;

        while (true)
        {
            for (int i = 2; i < 256; i += i)
            {
                for (int j = 1; j < i; j++)
                {
                    uint[] array2 = (uint[])M[num2][i].Clone();
                    GcmUtilities.Xor(array2, M[num2][j]);
                    M[num2][i + j] = array2;
                }
            }
            if (++num2 == 16)
            {
                break;
            }
            M[num2]    = new uint[256][];
            M[num2][0] = new uint[4];
            for (int num3 = 128; num3 > 0; num3 >>= 1)
            {
                uint[] array3 = (uint[])M[num2 - 1][num3].Clone();
                GcmUtilities.MultiplyP8(array3);
                M[num2][num3] = array3;
            }
        }
    }
Example #7
0
        public int DoFinal(byte[] output, int outOff)
        {
            int bufOff = this.bufOff;

            if (!this.forEncryption)
            {
                if (bufOff < this.macSize)
                {
                    throw new InvalidCipherTextException("data too short");
                }
                bufOff -= this.macSize;
            }
            if (bufOff > 0)
            {
                byte[] buf = new byte[16];
                Array.Copy((Array)this.bufBlock, 0, (Array)buf, 0, bufOff);
                this.gCTRBlock(buf, bufOff, output, outOff);
            }
            byte[] numArray1 = new byte[16];
            GcmBlockCipher.packLength((ulong)this.A.Length * 8UL, numArray1, 0);
            GcmBlockCipher.packLength(this.totalLength * 8UL, numArray1, 8);
            GcmUtilities.Xor(this.S, numArray1);
            this.multiplier.MultiplyH(this.S);
            byte[] numArray2 = new byte[16];
            this.cipher.ProcessBlock(this.J0, 0, numArray2, 0);
            GcmUtilities.Xor(numArray2, this.S);
            int num = bufOff;

            this.macBlock = new byte[this.macSize];
            Array.Copy((Array)numArray2, 0, (Array)this.macBlock, 0, this.macSize);
            if (this.forEncryption)
            {
                Array.Copy((Array)this.macBlock, 0, (Array)output, outOff + this.bufOff, this.macSize);
                num += this.macSize;
            }
            else
            {
                byte[] b = new byte[this.macSize];
                Array.Copy((Array)this.bufBlock, bufOff, (Array)b, 0, this.macSize);
                if (!Arrays.ConstantTimeAreEqual(this.macBlock, b))
                {
                    throw new InvalidCipherTextException("mac check in GCM failed");
                }
            }
            this.Reset(false);
            return(num);
        }
Example #8
0
        public int DoFinal(byte[] output, int outOff)
        {
            int num = bufOff;

            if (!forEncryption)
            {
                if (num < macSize)
                {
                    throw new InvalidCipherTextException("data too short");
                }
                num -= macSize;
            }
            if (num > 0)
            {
                byte[] array = new byte[16];
                Array.Copy(bufBlock, 0, array, 0, num);
                gCTRBlock(array, num, output, outOff);
            }
            byte[] array2 = new byte[16];
            packLength((ulong)((long)A.Length * 8L), array2, 0);
            packLength(totalLength * 8, array2, 8);
            GcmUtilities.Xor(S, array2);
            multiplier.MultiplyH(S);
            byte[] array3 = new byte[16];
            cipher.ProcessBlock(J0, 0, array3, 0);
            GcmUtilities.Xor(array3, S);
            int num2 = num;

            macBlock = new byte[macSize];
            Array.Copy(array3, 0, macBlock, 0, macSize);
            if (forEncryption)
            {
                Array.Copy(macBlock, 0, output, outOff + bufOff, macSize);
                num2 += macSize;
            }
            else
            {
                byte[] array4 = new byte[macSize];
                Array.Copy(bufBlock, num, array4, 0, macSize);
                if (!Arrays.ConstantTimeAreEqual(macBlock, array4))
                {
                    throw new InvalidCipherTextException("mac check in GCM failed");
                }
            }
            Reset(clearMac: false);
            return(num2);
        }
 // Token: 0x060000ED RID: 237 RVA: 0x000086C8 File Offset: 0x000068C8
 private void ProcessPartial(byte[] buf, int off, int len, byte[] output, int outOff)
 {
     byte[] array = new byte[16];
     this.GetNextCtrBlock(array);
     if (this.forEncryption)
     {
         GcmUtilities.Xor(buf, off, array, 0, len);
         this.gHASHPartial(this.S, buf, off, len);
     }
     else
     {
         this.gHASHPartial(this.S, buf, off, len);
         GcmUtilities.Xor(buf, off, array, 0, len);
     }
     Array.Copy(buf, off, output, outOff, len);
     this.totalLength += (ulong)len;
 }
Example #10
0
        private void ProcessPartial(byte[] buf, int off, int len, byte[] output, int outOff)
        {
            byte[] ctrBlock = new byte[BlockSize];
            GetNextCtrBlock(ctrBlock);

            if (forEncryption)
            {
                GcmUtilities.Xor(buf, off, ctrBlock, 0, len);
                gHASHPartial(S, buf, off, len);
            }
            else
            {
                gHASHPartial(S, buf, off, len);
                GcmUtilities.Xor(buf, off, ctrBlock, 0, len);
            }

            Array.Copy(buf, off, output, outOff, len);
            totalLength += (uint)len;
        }
Example #11
0
 // Token: 0x060000EC RID: 236 RVA: 0x00008638 File Offset: 0x00006838
 private void ProcessBlock(byte[] buf, int bufOff, byte[] output, int outOff)
 {
     Check.OutputLength(output, outOff, 16, "Output buffer too short");
     if (this.totalLength == 0UL)
     {
         this.InitCipher();
     }
     byte[] array = new byte[16];
     this.GetNextCtrBlock(array);
     if (this.forEncryption)
     {
         GcmUtilities.Xor(array, buf, bufOff);
         this.gHASHBlock(this.S, array);
         Array.Copy(array, 0, output, outOff, 16);
     }
     else
     {
         this.gHASHBlock(this.S, buf, bufOff);
         GcmUtilities.Xor(array, 0, buf, bufOff, output, outOff);
     }
     this.totalLength += 16UL;
 }
Example #12
0
        private void gCTRBlock(byte[] buf, int bufCount, byte[] output, int outOff)
        {
//			inc(counter);
            for (int i = 15; i >= 12; --i)
            {
                if (++counter[i] != 0)
                {
                    break;
                }
            }

            byte[] tmp = new byte[BlockSize];
            cipher.ProcessBlock(counter, 0, tmp, 0);

            byte[] hashBytes;
            if (forEncryption)
            {
                Array.Copy(Zeroes, bufCount, tmp, bufCount, BlockSize - bufCount);
                hashBytes = tmp;
            }
            else
            {
                hashBytes = buf;
            }

            for (int i = bufCount - 1; i >= 0; --i)
            {
                tmp[i]            ^= buf[i];
                output[outOff + i] = tmp[i];
            }

//			gHASHBlock(hashBytes);
            GcmUtilities.Xor(S, hashBytes);
            multiplier.MultiplyH(S);

            totalLength += (ulong)bufCount;
        }
Example #13
0
 private void gHASHPartial(byte[] Y, byte[] b, int off, int len)
 {
     GcmUtilities.Xor(Y, b, off, len);
     multiplier.MultiplyH(Y);
 }
Example #14
0
        public int DoFinal(byte[] output, int outOff)
        {
            if (totalLength == 0)
            {
                InitCipher();
            }
            int num = bufOff;

            if (forEncryption)
            {
                Check.OutputLength(output, outOff, num + macSize, "Output buffer too short");
            }
            else
            {
                if (num < macSize)
                {
                    throw new InvalidCipherTextException("data too short");
                }
                num -= macSize;
                Check.OutputLength(output, outOff, num, "Output buffer too short");
            }
            if (num > 0)
            {
                gCTRPartial(bufBlock, 0, num, output, outOff);
            }
            atLength += (uint)atBlockPos;
            if (atLength > atLengthPre)
            {
                if (atBlockPos > 0)
                {
                    gHASHPartial(S_at, atBlock, 0, atBlockPos);
                }
                if (atLengthPre != 0)
                {
                    GcmUtilities.Xor(S_at, S_atPre);
                }
                long   pow   = (long)(totalLength * 8 + 127 >> 7);
                byte[] array = new byte[16];
                if (exp == null)
                {
                    exp = new Tables1kGcmExponentiator();
                    exp.Init(H);
                }
                exp.ExponentiateX(pow, array);
                GcmUtilities.Multiply(S_at, array);
                GcmUtilities.Xor(S, S_at);
            }
            byte[] array2 = new byte[16];
            Pack.UInt64_To_BE(atLength * 8, array2, 0);
            Pack.UInt64_To_BE(totalLength * 8, array2, 8);
            gHASHBlock(S, array2);
            byte[] array3 = new byte[16];
            cipher.ProcessBlock(J0, 0, array3, 0);
            GcmUtilities.Xor(array3, S);
            int num2 = num;

            macBlock = new byte[macSize];
            global::System.Array.Copy((global::System.Array)array3, 0, (global::System.Array)macBlock, 0, macSize);
            if (forEncryption)
            {
                global::System.Array.Copy((global::System.Array)macBlock, 0, (global::System.Array)output, outOff + bufOff, macSize);
                num2 += macSize;
            }
            else
            {
                byte[] array4 = new byte[macSize];
                global::System.Array.Copy((global::System.Array)bufBlock, num, (global::System.Array)array4, 0, macSize);
                if (!Arrays.ConstantTimeAreEqual(macBlock, array4))
                {
                    throw new InvalidCipherTextException("mac check in GCM failed");
                }
            }
            Reset(clearMac: false);
            return(num2);
        }
Example #15
0
 private void gHASHBlock(byte[] Y, byte[] b)
 {
     GcmUtilities.Xor(Y, b);
     multiplier.MultiplyH(Y);
 }
Example #16
0
        public virtual void Init(bool forEncryption, ICipherParameters parameters)
        {
            this.forEncryption = forEncryption;
            macBlock           = null;
            if (parameters is AeadParameters)
            {
                AeadParameters aeadParameters = (AeadParameters)parameters;
                nonce = aeadParameters.GetNonce();
                A     = aeadParameters.GetAssociatedText();
                int num = aeadParameters.MacSize;
                if (num < 96 || num > 128 || num % 8 != 0)
                {
                    throw new ArgumentException("Invalid value for MAC size: " + num);
                }
                macSize  = num / 8;
                keyParam = aeadParameters.Key;
            }
            else
            {
                if (!(parameters is ParametersWithIV))
                {
                    throw new ArgumentException("invalid parameters passed to GCM");
                }
                ParametersWithIV parametersWithIV = (ParametersWithIV)parameters;
                nonce    = parametersWithIV.GetIV();
                A        = null;
                macSize  = 16;
                keyParam = (KeyParameter)parametersWithIV.Parameters;
            }
            int num2 = forEncryption ? 16 : (16 + macSize);

            bufBlock = new byte[num2];
            if (nonce == null || nonce.Length < 1)
            {
                throw new ArgumentException("IV must be at least 1 byte");
            }
            if (A == null)
            {
                A = new byte[0];
            }
            cipher.Init(forEncryption: true, keyParam);
            H = new byte[16];
            cipher.ProcessBlock(H, 0, H, 0);
            multiplier.Init(H);
            initS = gHASH(A);
            if (nonce.Length == 12)
            {
                J0 = new byte[16];
                Array.Copy(nonce, 0, J0, 0, nonce.Length);
                J0[15] = 1;
            }
            else
            {
                J0 = gHASH(nonce);
                byte[] array = new byte[16];
                packLength((ulong)((long)nonce.Length * 8L), array, 8);
                GcmUtilities.Xor(J0, array);
                multiplier.MultiplyH(J0);
            }
            S           = Arrays.Clone(initS);
            counter     = Arrays.Clone(J0);
            bufOff      = 0;
            totalLength = 0uL;
        }
Example #17
0
 // Token: 0x060000F0 RID: 240 RVA: 0x00008780 File Offset: 0x00006980
 private void gHASHBlock(byte[] Y, byte[] b, int off)
 {
     GcmUtilities.Xor(Y, b, off);
     this.multiplier.MultiplyH(Y);
 }
Example #18
0
        // Token: 0x060000E8 RID: 232 RVA: 0x0000827C File Offset: 0x0000647C
        public int DoFinal(byte[] output, int outOff)
        {
            this.CheckStatus();
            if (this.totalLength == 0UL)
            {
                this.InitCipher();
            }
            int num = this.bufOff;

            if (this.forEncryption)
            {
                Check.OutputLength(output, outOff, num + this.macSize, "Output buffer too short");
            }
            else
            {
                if (num < this.macSize)
                {
                    throw new CryptoException("data too short");
                }
                num -= this.macSize;
                Check.OutputLength(output, outOff, num, "Output buffer too short");
            }
            if (num > 0)
            {
                this.ProcessPartial(this.bufBlock, 0, num, output, outOff);
            }
            this.atLength += (ulong)this.atBlockPos;
            if (this.atLength > this.atLengthPre)
            {
                if (this.atBlockPos > 0)
                {
                    this.gHASHPartial(this.S_at, this.atBlock, 0, this.atBlockPos);
                }
                if (this.atLengthPre > 0UL)
                {
                    GcmUtilities.Xor(this.S_at, this.S_atPre);
                }
                long   pow   = (long)(this.totalLength * 8UL + 127UL >> 7);
                byte[] array = new byte[16];
                if (this.exp == null)
                {
                    this.exp = new Tables1kGcmExponentiator();
                    this.exp.Init(this.H);
                }
                this.exp.ExponentiateX(pow, array);
                GcmUtilities.Multiply(this.S_at, array);
                GcmUtilities.Xor(this.S, this.S_at);
            }
            byte[] array2 = new byte[16];
            Pack.UInt64_To_BE(this.atLength * 8UL, array2, 0);
            Pack.UInt64_To_BE(this.totalLength * 8UL, array2, 8);
            this.gHASHBlock(this.S, array2);
            byte[] array3 = new byte[16];
            this.cipher.ProcessBlock(this.J0, 0, array3, 0);
            GcmUtilities.Xor(array3, this.S);
            int num2 = num;

            this.macBlock = new byte[this.macSize];
            Array.Copy(array3, 0, this.macBlock, 0, this.macSize);
            if (this.forEncryption)
            {
                Array.Copy(this.macBlock, 0, output, outOff + this.bufOff, this.macSize);
                num2 += this.macSize;
            }
            else
            {
                byte[] array4 = new byte[this.macSize];
                Array.Copy(this.bufBlock, num, array4, 0, this.macSize);
                if (!Arrays.ConstantTimeAreEqual(this.macBlock, array4))
                {
                    throw new CryptoException("mac check in GCM failed");
                }
            }
            this.Reset(false);
            return(num2);
        }
Example #19
0
    public void Init(byte[] H)
    {
        if (M == null)
        {
            M = new uint[32][][];
        }
        else if (Arrays.AreEqual(this.H, H))
        {
            return;
        }
        this.H  = Arrays.Clone(H);
        M[0]    = new uint[16][];
        M[1]    = new uint[16][];
        M[0][0] = new uint[4];
        M[1][0] = new uint[4];
        M[1][8] = GcmUtilities.AsUints(H);
        for (int num = 4; num >= 1; num >>= 1)
        {
            uint[] array = (uint[])M[1][num + num].Clone();
            GcmUtilities.MultiplyP(array);
            M[1][num] = array;
        }
        uint[] array2 = (uint[])M[1][1].Clone();
        GcmUtilities.MultiplyP(array2);
        M[0][8] = array2;
        for (int num2 = 4; num2 >= 1; num2 >>= 1)
        {
            uint[] array3 = (uint[])M[0][num2 + num2].Clone();
            GcmUtilities.MultiplyP(array3);
            M[0][num2] = array3;
        }
        int num3 = 0;

        while (true)
        {
            for (int i = 2; i < 16; i += i)
            {
                for (int j = 1; j < i; j++)
                {
                    uint[] array4 = (uint[])M[num3][i].Clone();
                    GcmUtilities.Xor(array4, M[num3][j]);
                    M[num3][i + j] = array4;
                }
            }
            if (++num3 == 32)
            {
                break;
            }
            if (num3 > 1)
            {
                M[num3]    = new uint[16][];
                M[num3][0] = new uint[4];
                for (int num4 = 8; num4 > 0; num4 >>= 1)
                {
                    uint[] array5 = (uint[])M[num3 - 2][num4].Clone();
                    GcmUtilities.MultiplyP8(array5);
                    M[num3][num4] = array5;
                }
            }
        }
    }
Example #20
0
 private void gHASHBlock(byte[] Y, byte[] b, int off)
 {
     GcmUtilities.Xor(Y, b, off);
     Tables8kGcmMultiplier_MultiplyH(Y);
 }
Example #21
0
 public virtual void Init(bool forEncryption, ICipherParameters parameters)
 {
     this.forEncryption = forEncryption;
     this.macBlock      = (byte[])null;
     if (parameters is AeadParameters)
     {
         AeadParameters aeadParameters = (AeadParameters)parameters;
         this.nonce = aeadParameters.GetNonce();
         this.A     = aeadParameters.GetAssociatedText();
         int macSize = aeadParameters.MacSize;
         if (macSize < 96 || macSize > 128 || macSize % 8 != 0)
         {
             throw new ArgumentException("Invalid value for MAC size: " + (object)macSize);
         }
         this.macSize  = macSize / 8;
         this.keyParam = aeadParameters.Key;
     }
     else
     {
         if (!(parameters is ParametersWithIV))
         {
             throw new ArgumentException("invalid parameters passed to GCM");
         }
         ParametersWithIV parametersWithIv = (ParametersWithIV)parameters;
         this.nonce    = parametersWithIv.GetIV();
         this.A        = (byte[])null;
         this.macSize  = 16;
         this.keyParam = (KeyParameter)parametersWithIv.Parameters;
     }
     this.bufBlock = new byte[forEncryption ? 16 : 16 + this.macSize];
     if (this.nonce == null || this.nonce.Length < 1)
     {
         throw new ArgumentException("IV must be at least 1 byte");
     }
     if (this.A == null)
     {
         this.A = new byte[0];
     }
     this.cipher.Init(true, (ICipherParameters)this.keyParam);
     this.H = new byte[16];
     this.cipher.ProcessBlock(this.H, 0, this.H, 0);
     this.multiplier.Init(this.H);
     this.initS = this.gHASH(this.A);
     if (this.nonce.Length == 12)
     {
         this.J0 = new byte[16];
         Array.Copy((Array)this.nonce, 0, (Array)this.J0, 0, this.nonce.Length);
         this.J0[15] = (byte)1;
     }
     else
     {
         this.J0 = this.gHASH(this.nonce);
         byte[] numArray = new byte[16];
         GcmBlockCipher.packLength((ulong)this.nonce.Length * 8UL, numArray, 8);
         GcmUtilities.Xor(this.J0, numArray);
         this.multiplier.MultiplyH(this.J0);
     }
     this.S           = Arrays.Clone(this.initS);
     this.counter     = Arrays.Clone(this.J0);
     this.bufOff      = 0;
     this.totalLength = 0UL;
 }
Example #22
0
        public int DoFinal(byte[] output, int outOff)
        {
            if (totalLength == 0)
            {
                InitCipher();
            }

            int extra = bufOff;

            if (forEncryption)
            {
                Check.OutputLength(output, outOff, extra + macSize, "Output buffer too short");
            }
            else
            {
                if (extra < macSize)
                {
                    throw new InvalidCipherTextException("data too short");
                }

                extra -= macSize;

                Check.OutputLength(output, outOff, extra, "Output buffer too short");
            }

            if (extra > 0)
            {
                gCTRPartial(bufBlock, 0, extra, output, outOff);
            }

            atLength += (uint)atBlockPos;

            if (atLength > atLengthPre)
            {
                /*
                 *  Some AAD was sent after the cipher started. We determine the difference b/w the hash value
                 *  we actually used when the cipher started (S_atPre) and the final hash value calculated (S_at).
                 *  Then we carry this difference forward by multiplying by H^c, where c is the number of (full or
                 *  partial) cipher-text blocks produced, and adjust the current hash.
                 */

                // Finish hash for partial AAD block
                if (atBlockPos > 0)
                {
                    gHASHPartial(S_at, atBlock, 0, atBlockPos);
                }

                // Find the difference between the AAD hashes
                if (atLengthPre > 0)
                {
                    GcmUtilities.Xor(S_at, S_atPre);
                }

                // Number of cipher-text blocks produced
                long c = (long)(((totalLength * 8) + 127) >> 7);

                // Calculate the adjustment factor
                byte[] H_c = new byte[16];
                if (exp == null)
                {
                    exp = new Tables1kGcmExponentiator();
                    exp.Init(H);
                }
                exp.ExponentiateX(c, H_c);

                // Carry the difference forward
                GcmUtilities.Multiply(S_at, H_c);

                // Adjust the current hash
                GcmUtilities.Xor(S, S_at);
            }

            // Final gHASH
            byte[] X = new byte[BlockSize];
            Pack.UInt64_To_BE(atLength * 8UL, X, 0);
            Pack.UInt64_To_BE(totalLength * 8UL, X, 8);

            gHASHBlock(S, X);

            // T = MSBt(GCTRk(J0,S))
            byte[] tag = new byte[BlockSize];
            cipher.ProcessBlock(J0, 0, tag, 0);
            GcmUtilities.Xor(tag, S);

            int resultLen = extra;

            // We place into macBlock our calculated value for T
            this.macBlock = new byte[macSize];
            Array.Copy(tag, 0, macBlock, 0, macSize);

            if (forEncryption)
            {
                // Append T to the message
                Array.Copy(macBlock, 0, output, outOff + bufOff, macSize);
                resultLen += macSize;
            }
            else
            {
                // Retrieve the T value from the message and compare to calculated one
                byte[] msgMac = new byte[macSize];
                Array.Copy(bufBlock, extra, msgMac, 0, macSize);
                if (!Arrays.ConstantTimeAreEqual(this.macBlock, msgMac))
                {
                    throw new InvalidCipherTextException("mac check in GCM failed");
                }
            }

            Reset(false);

            return(resultLen);
        }
Example #23
0
        public virtual void Init(
            bool forEncryption,
            ICipherParameters parameters)
        {
            this.forEncryption = forEncryption;
            this.macBlock      = null;

            if (parameters is AeadParameters)
            {
                AeadParameters param = (AeadParameters)parameters;

                nonce = param.GetNonce();
                A     = param.GetAssociatedText();

                int macSizeBits = param.MacSize;
                if (macSizeBits < 96 || macSizeBits > 128 || macSizeBits % 8 != 0)
                {
                    throw new ArgumentException("Invalid value for MAC size: " + macSizeBits);
                }

                macSize  = macSizeBits / 8;
                keyParam = param.Key;
            }
            else if (parameters is ParametersWithIV)
            {
                ParametersWithIV param = (ParametersWithIV)parameters;

                nonce    = param.GetIV();
                A        = null;
                macSize  = 16;
                keyParam = (KeyParameter)param.Parameters;
            }
            else
            {
                throw new ArgumentException("invalid parameters passed to GCM");
            }

            int bufLength = forEncryption ? BlockSize : (BlockSize + macSize);

            this.bufBlock = new byte[bufLength];

            if (nonce == null || nonce.Length < 1)
            {
                throw new ArgumentException("IV must be at least 1 byte");
            }

            if (A == null)
            {
                // Avoid lots of null checks
                A = new byte[0];
            }

            // Cipher always used in forward mode
            cipher.Init(true, keyParam);

            // TODO This should be configurable by Init parameters
            // (but must be 16 if nonce length not 12) (BlockSize?)
//			this.tagLength = 16;

            this.H = new byte[BlockSize];
            cipher.ProcessBlock(H, 0, H, 0);
            multiplier.Init(H);

            this.initS = gHASH(A);

            if (nonce.Length == 12)
            {
                this.J0 = new byte[16];
                Array.Copy(nonce, 0, J0, 0, nonce.Length);
                this.J0[15] = 0x01;
            }
            else
            {
                this.J0 = gHASH(nonce);
                byte[] X = new byte[16];
                packLength((ulong)nonce.Length * 8UL, X, 8);
                GcmUtilities.Xor(this.J0, X);
                multiplier.MultiplyH(this.J0);
            }

            this.S           = Arrays.Clone(initS);
            this.counter     = Arrays.Clone(J0);
            this.bufOff      = 0;
            this.totalLength = 0;
        }
Example #24
0
        public void Tables8kGcmMultiplier_Init(byte[] H)
        {
            if (Tables8kGcmMultiplier_M == null)
            {
                Tables8kGcmMultiplier_M = new uint[32][][];
            }
            else if (Arrays.AreEqual(this.Tables8kGcmMultiplier_H, H))
            {
                return;
            }

            this.Tables8kGcmMultiplier_H = Arrays.Clone(H);

            Tables8kGcmMultiplier_M[0]    = new uint[16][];
            Tables8kGcmMultiplier_M[1]    = new uint[16][];
            Tables8kGcmMultiplier_M[0][0] = new uint[4];
            Tables8kGcmMultiplier_M[1][0] = new uint[4];
            Tables8kGcmMultiplier_M[1][8] = GcmUtilities.AsUints(H);

            for (int j = 4; j >= 1; j >>= 1)
            {
                uint[] tmp = (uint[])Tables8kGcmMultiplier_M[1][j + j].Clone();
                GcmUtilities.MultiplyP(tmp);
                Tables8kGcmMultiplier_M[1][j] = tmp;
            }

            {
                uint[] tmp = (uint[])Tables8kGcmMultiplier_M[1][1].Clone();
                GcmUtilities.MultiplyP(tmp);
                Tables8kGcmMultiplier_M[0][8] = tmp;
            }

            for (int j = 4; j >= 1; j >>= 1)
            {
                uint[] tmp = (uint[])Tables8kGcmMultiplier_M[0][j + j].Clone();
                GcmUtilities.MultiplyP(tmp);
                Tables8kGcmMultiplier_M[0][j] = tmp;
            }

            for (int i = 0; ;)
            {
                for (int j = 2; j < 16; j += j)
                {
                    for (int k = 1; k < j; ++k)
                    {
                        uint[] tmp = (uint[])Tables8kGcmMultiplier_M[i][j].Clone();
                        GcmUtilities.Xor(tmp, Tables8kGcmMultiplier_M[i][k]);
                        Tables8kGcmMultiplier_M[i][j + k] = tmp;
                    }
                }

                if (++i == 32)
                {
                    return;
                }

                if (i > 1)
                {
                    Tables8kGcmMultiplier_M[i]    = new uint[16][];
                    Tables8kGcmMultiplier_M[i][0] = new uint[4];
                    for (int j = 8; j > 0; j >>= 1)
                    {
                        uint[] tmp = (uint[])Tables8kGcmMultiplier_M[i - 2][j].Clone();
                        GcmUtilities.MultiplyP8(tmp);
                        Tables8kGcmMultiplier_M[i][j] = tmp;
                    }
                }
            }
        }
Example #25
0
        public int DoFinal(byte[] output, int outOff)
        {
            if (this.totalLength == 0L)
            {
                this.InitCipher();
            }
            int bufOff = this.bufOff;

            if (this.forEncryption)
            {
                Check.OutputLength(output, outOff, bufOff + this.macSize, "Output buffer too short");
            }
            else
            {
                if (bufOff < this.macSize)
                {
                    throw new InvalidCipherTextException("data too short");
                }
                bufOff -= this.macSize;
                Check.OutputLength(output, outOff, bufOff, "Output buffer too short");
            }
            if (bufOff > 0)
            {
                this.gCTRPartial(this.bufBlock, 0, bufOff, output, outOff);
            }
            this.atLength += (ulong)this.atBlockPos;
            if (this.atLength > this.atLengthPre)
            {
                if (this.atBlockPos > 0)
                {
                    this.gHASHPartial(this.S_at, this.atBlock, 0, this.atBlockPos);
                }
                if (this.atLengthPre > 0L)
                {
                    GcmUtilities.Xor(this.S_at, this.S_atPre);
                }
                long   pow    = (long)(((this.totalLength * 8L) + 0x7fL) >> 7);
                byte[] buffer = new byte[0x10];
                if (this.exp == null)
                {
                    this.exp = new Tables1kGcmExponentiator();
                    this.exp.Init(this.H);
                }
                this.exp.ExponentiateX(pow, buffer);
                GcmUtilities.Multiply(this.S_at, buffer);
                GcmUtilities.Xor(this.S, this.S_at);
            }
            byte[] bs = new byte[0x10];
            Pack.UInt64_To_BE((ulong)(this.atLength * ((ulong)8L)), bs, 0);
            Pack.UInt64_To_BE((ulong)(this.totalLength * ((ulong)8L)), bs, 8);
            this.gHASHBlock(this.S, bs);
            byte[] outBuf = new byte[0x10];
            this.cipher.ProcessBlock(this.J0, 0, outBuf, 0);
            GcmUtilities.Xor(outBuf, this.S);
            int num3 = bufOff;

            this.macBlock = new byte[this.macSize];
            Array.Copy(outBuf, 0, this.macBlock, 0, this.macSize);
            if (this.forEncryption)
            {
                Array.Copy(this.macBlock, 0, output, outOff + this.bufOff, this.macSize);
                num3 += this.macSize;
            }
            else
            {
                byte[] destinationArray = new byte[this.macSize];
                Array.Copy(this.bufBlock, bufOff, destinationArray, 0, this.macSize);
                if (!Arrays.ConstantTimeAreEqual(this.macBlock, destinationArray))
                {
                    throw new InvalidCipherTextException("mac check in GCM failed");
                }
            }
            this.Reset(false);
            return(num3);
        }
Example #26
0
        public int DoFinal(byte[] output, int outOff)
        {
            int extra = bufOff;

            if (!forEncryption)
            {
                if (extra < macSize)
                {
                    throw new InvalidCipherTextException("data too short");
                }

                extra -= macSize;
            }

            if (extra > 0)
            {
                byte[] tmp = new byte[BlockSize];
                Array.Copy(bufBlock, 0, tmp, 0, extra);
                gCTRBlock(tmp, extra, output, outOff);
            }

            // Final gHASH
            byte[] X = new byte[16];
            packLength((ulong)A.Length * 8UL, X, 0);
            packLength(totalLength * 8UL, X, 8);

            GcmUtilities.Xor(S, X);
            multiplier.MultiplyH(S);

            // TODO Fix this if tagLength becomes configurable
            // T = MSBt(GCTRk(J0,S))
            byte[] tag = new byte[BlockSize];
            cipher.ProcessBlock(J0, 0, tag, 0);
            GcmUtilities.Xor(tag, S);

            int resultLen = extra;

            // We place into macBlock our calculated value for T
            this.macBlock = new byte[macSize];
            Array.Copy(tag, 0, macBlock, 0, macSize);

            if (forEncryption)
            {
                // Append T to the message
                Array.Copy(macBlock, 0, output, outOff + bufOff, macSize);
                resultLen += macSize;
            }
            else
            {
                // Retrieve the T value from the message and compare to calculated one
                byte[] msgMac = new byte[macSize];
                Array.Copy(bufBlock, extra, msgMac, 0, macSize);
                if (!Arrays.ConstantTimeAreEqual(this.macBlock, msgMac))
                {
                    throw new InvalidCipherTextException("mac check in GCM failed");
                }
            }

            Reset(false);

            return(resultLen);
        }