Exemple #1
0
        public virtual void Init(bool forEncryption, ICipherParameters parameters)
        {
            //IL_005e: Unknown result type (might be due to invalid IL or missing references)
            //IL_00b3: Unknown result type (might be due to invalid IL or missing references)
            //IL_00f0: Unknown result type (might be due to invalid IL or missing references)
            //IL_0154: Unknown result type (might be due to invalid IL or missing references)
            this.forEncryption = forEncryption;
            macBlock           = null;
            KeyParameter keyParameter;

            if (parameters is AeadParameters)
            {
                AeadParameters aeadParameters = (AeadParameters)parameters;
                nonce = aeadParameters.GetNonce();
                initialAssociatedText = aeadParameters.GetAssociatedText();
                int num = aeadParameters.MacSize;
                if (num < 32 || num > 128 || num % 8 != 0)
                {
                    throw new ArgumentException(string.Concat((object)"Invalid value for MAC size: ", (object)num));
                }
                macSize      = num / 8;
                keyParameter = aeadParameters.Key;
            }
            else
            {
                if (!(parameters is ParametersWithIV))
                {
                    throw new ArgumentException("invalid parameters passed to GCM");
                }
                ParametersWithIV parametersWithIV = (ParametersWithIV)parameters;
                nonce = parametersWithIV.GetIV();
                initialAssociatedText = null;
                macSize      = 16;
                keyParameter = (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 (keyParameter != null)
            {
                cipher.Init(forEncryption: true, keyParameter);
                H = new byte[16];
                cipher.ProcessBlock(H, 0, H, 0);
                multiplier.Init(H);
                exp = null;
            }
            else if (H == null)
            {
                throw new ArgumentException("Key must be specified in initial init");
            }
            J0 = new byte[16];
            if (nonce.Length == 12)
            {
                global::System.Array.Copy((global::System.Array)nonce, 0, (global::System.Array)J0, 0, nonce.Length);
                J0[15] = 1;
            }
            else
            {
                gHASH(J0, nonce, nonce.Length);
                byte[] array = new byte[16];
                Pack.UInt64_To_BE((ulong)nonce.Length * 8uL, array, 8);
                gHASHBlock(J0, array);
            }
            S           = new byte[16];
            S_at        = new byte[16];
            S_atPre     = new byte[16];
            atBlock     = new byte[16];
            atBlockPos  = 0;
            atLength    = 0uL;
            atLengthPre = 0uL;
            counter     = Arrays.Clone(J0);
            bufOff      = 0;
            totalLength = 0uL;
            if (initialAssociatedText != null)
            {
                ProcessAadBytes(initialAssociatedText, 0, initialAssociatedText.Length);
            }
        }
Exemple #2
0
        /// <remarks>
        /// MAC sizes from 32 bits to 128 bits (must be a multiple of 8) are supported. The default is 128 bits.
        /// Sizes less than 96 are not recommended, but are supported for specialized applications.
        /// </remarks>
        public virtual void Init(
            bool forEncryption,
            ICipherParameters parameters)
        {
            this.forEncryption = forEncryption;
            this.macBlock      = null;

            KeyParameter keyParam;

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

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

                int macSizeBits = param.MacSize;
                if (macSizeBits < 32 || 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();
                initialAssociatedText = 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");
            }

            // TODO Restrict macSize to 16 if nonce length not 12?

            // Cipher always used in forward mode
            // if keyParam is null we're reusing the last key.
            if (keyParam != null)
            {
                cipher.Init(true, keyParam);

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

                // if keyParam is null we're reusing the last key and the multiplier doesn't need re-init
                multiplier.Init(H);
                exp = null;
            }
            else if (this.H == null)
            {
                throw new ArgumentException("Key must be specified in initial init");
            }

            this.J0 = new byte[BlockSize];

            if (nonce.Length == 12)
            {
                Array.Copy(nonce, 0, J0, 0, nonce.Length);
                this.J0[BlockSize - 1] = 0x01;
            }
            else
            {
                gHASH(J0, nonce, nonce.Length);
                byte[] X = new byte[BlockSize];
                Pack.UInt64_To_BE((ulong)nonce.Length * 8UL, X, 8);
                gHASHBlock(J0, X);
            }

            this.S           = new byte[BlockSize];
            this.S_at        = new byte[BlockSize];
            this.S_atPre     = new byte[BlockSize];
            this.atBlock     = new byte[BlockSize];
            this.atBlockPos  = 0;
            this.atLength    = 0;
            this.atLengthPre = 0;
            this.counter     = Arrays.Clone(J0);
            this.bufOff      = 0;
            this.totalLength = 0;

            if (initialAssociatedText != null)
            {
                ProcessAadBytes(initialAssociatedText, 0, initialAssociatedText.Length);
            }
        }
Exemple #3
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);
        }
Exemple #4
0
        /// <remarks>
        /// MAC sizes from 32 bits to 128 bits (must be a multiple of 8) are supported. The default is 128 bits.
        /// Sizes less than 96 are not recommended, but are supported for specialized applications.
        /// </remarks>
        public virtual void Init(
            bool				forEncryption,
            ICipherParameters	parameters)
        {
            this.forEncryption = forEncryption;
            this.macBlock = null;

            KeyParameter keyParam;

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

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

                int macSizeBits = param.MacSize;
                if (macSizeBits < 32 || 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();
                initialAssociatedText = 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");
            }

            // TODO Restrict macSize to 16 if nonce length not 12?

            // Cipher always used in forward mode
            // if keyParam is null we're reusing the last key.
            if (keyParam != null)
            {
                cipher.Init(true, keyParam);

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

                // if keyParam is null we're reusing the last key and the multiplier doesn't need re-init
                multiplier.Init(H);
                exp = null;
            }
            else if (this.H == null)
            {
                throw new ArgumentException("Key must be specified in initial init");
            }

            this.J0 = new byte[BlockSize];

            if (nonce.Length == 12)
            {
                Array.Copy(nonce, 0, J0, 0, nonce.Length);
                this.J0[BlockSize - 1] = 0x01;
            }
            else
            {
                gHASH(J0, nonce, nonce.Length);
                byte[] X = new byte[BlockSize];
                Pack.UInt64_To_BE((ulong)nonce.Length * 8UL, X, 8);
                gHASHBlock(J0, X);
            }

            this.S = new byte[BlockSize];
            this.S_at = new byte[BlockSize];
            this.S_atPre = new byte[BlockSize];
            this.atBlock = new byte[BlockSize];
            this.atBlockPos = 0;
            this.atLength = 0;
            this.atLengthPre = 0;
            this.counter = Arrays.Clone(J0);
            this.bufOff = 0;
            this.totalLength = 0;

            if (initialAssociatedText != null)
            {
                ProcessAadBytes(initialAssociatedText, 0, initialAssociatedText.Length);
            }
        }
Exemple #5
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);
        }
Exemple #6
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);
        }
Exemple #7
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;
        }
Exemple #8
0
        public virtual void Init(bool forEncryption, ICipherParameters parameters)
        {
            KeyParameter key;

            this.forEncryption = forEncryption;
            this.macBlock      = null;
            if (parameters is AeadParameters)
            {
                AeadParameters parameters2 = (AeadParameters)parameters;
                this.nonce = parameters2.GetNonce();
                this.initialAssociatedText = parameters2.GetAssociatedText();
                int macSize = parameters2.MacSize;
                if (((macSize < 0x20) || (macSize > 0x80)) || ((macSize % 8) != 0))
                {
                    throw new ArgumentException("Invalid value for MAC size: " + macSize);
                }
                this.macSize = macSize / 8;
                key          = parameters2.Key;
            }
            else
            {
                if (!(parameters is ParametersWithIV))
                {
                    throw new ArgumentException("invalid parameters passed to GCM");
                }
                ParametersWithIV hiv = (ParametersWithIV)parameters;
                this.nonce = hiv.GetIV();
                this.initialAssociatedText = null;
                this.macSize = 0x10;
                key          = (KeyParameter)hiv.Parameters;
            }
            int num2 = !forEncryption ? (0x10 + this.macSize) : 0x10;

            this.bufBlock = new byte[num2];
            if ((this.nonce == null) || (this.nonce.Length < 1))
            {
                throw new ArgumentException("IV must be at least 1 byte");
            }
            if (key != null)
            {
                this.cipher.Init(true, key);
                this.H = new byte[0x10];
                this.cipher.ProcessBlock(this.H, 0, this.H, 0);
                this.multiplier.Init(this.H);
                this.exp = null;
            }
            else if (this.H == null)
            {
                throw new ArgumentException("Key must be specified in initial init");
            }
            this.J0 = new byte[0x10];
            if (this.nonce.Length == 12)
            {
                Array.Copy(this.nonce, 0, this.J0, 0, this.nonce.Length);
                this.J0[15] = 1;
            }
            else
            {
                this.gHASH(this.J0, this.nonce, this.nonce.Length);
                byte[] bs = new byte[0x10];
                Pack.UInt64_To_BE((ulong)(this.nonce.Length * 8L), bs, 8);
                this.gHASHBlock(this.J0, bs);
            }
            this.S               = new byte[0x10];
            this.S_at            = new byte[0x10];
            this.S_atPre         = new byte[0x10];
            this.atBlock         = new byte[0x10];
            this.atBlockPos      = 0;
            this.atLength        = 0L;
            this.atLengthPre     = 0L;
            this.counter         = Arrays.Clone(this.J0);
            this.blocksRemaining = 0xfffffffe;
            this.bufOff          = 0;
            this.totalLength     = 0L;
            if (this.initialAssociatedText != null)
            {
                this.ProcessAadBytes(this.initialAssociatedText, 0, this.initialAssociatedText.Length);
            }
        }
        /// <remarks>
        /// MAC sizes from 32 bits to 128 bits (must be a multiple of 8) are supported. The default is 128 bits.
        /// Sizes less than 96 are not recommended, but are supported for specialized applications.
        /// </remarks>
        public /*virtual*/ void Init(
            bool forEncryption,
            ICipherParameters parameters)
        {
            this.forEncryption = forEncryption;
            //this.macBlock = null;
            if (this.macBlock != null)
            {
                Array.Clear(this.macBlock, 0, this.macBlock.Length);
            }
            this.initialised = true;

            KeyParameter keyParam;

            byte[] newNonce = null;

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

                newNonce = param.GetNonce();
                initialAssociatedText = param.GetAssociatedText();

                int macSizeBits = param.MacSize;
                if (macSizeBits < 32 || 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;

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

            this.bufLength = forEncryption ? BlockSize : (BlockSize + macSize);
            if (this.bufBlock == null || this.bufLength < this.bufBlock.Length)
            {
                BufferPool.Resize(ref this.bufBlock, this.bufLength, true, true);
            }

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

            if (forEncryption)
            {
                if (nonce != null && Arrays.AreEqual(nonce, newNonce))
                {
                    if (keyParam == null)
                    {
                        throw new ArgumentException("cannot reuse nonce for GCM encryption");
                    }
                    if (lastKey != null && Arrays.AreEqual(lastKey, keyParam.GetKey()))
                    {
                        throw new ArgumentException("cannot reuse nonce for GCM encryption");
                    }
                }
            }

            nonce = newNonce;
            if (keyParam != null)
            {
                lastKey = keyParam.GetKey();
            }

            // TODO Restrict macSize to 16 if nonce length not 12?

            // Cipher always used in forward mode
            // if keyParam is null we're reusing the last key.
            if (keyParam != null)
            {
                cipher.Init(true, keyParam);

                if (this.H == null)
                {
                    this.H = new byte[BlockSize];
                }
                else
                {
                    Array.Clear(this.H, 0, BlockSize);
                }
                cipher.ProcessBlock(H, 0, H, 0);

                // if keyParam is null we're reusing the last key and the multiplier doesn't need re-init
                Tables8kGcmMultiplier_Init(H);
                exp = null;
            }
            else if (this.H == null)
            {
                throw new ArgumentException("Key must be specified in initial init");
            }

            if (this.J0 == null)
            {
                this.J0 = new byte[BlockSize];
            }
            else
            {
                Array.Clear(this.J0, 0, BlockSize);
            }

            if (nonce.Length == 12)
            {
                Array.Copy(nonce, 0, J0, 0, nonce.Length);
                this.J0[BlockSize - 1] = 0x01;
            }
            else
            {
                gHASH(J0, nonce, nonce.Length);
                byte[] X = BufferPool.Get(BlockSize, false);
                Pack.UInt64_To_BE((ulong)nonce.Length * 8UL, X, 8);
                gHASHBlock(J0, X);
                BufferPool.Release(X);
            }

            //BufferPool.Resize(ref this.S, BlockSize, false, true);
            //BufferPool.Resize(ref this.S_at, BlockSize, false, true);
            //BufferPool.Resize(ref this.S_atPre, BlockSize, false, true);
            //BufferPool.Resize(ref this.atBlock, BlockSize, false, true);
            if (this.S == null)
            {
                this.S = new byte[BlockSize];
            }
            else
            {
                Array.Clear(this.S, 0, this.S.Length);
            }

            if (this.S_at == null)
            {
                this.S_at = new byte[BlockSize];
            }
            else
            {
                Array.Clear(this.S_at, 0, this.S_at.Length);
            }

            if (this.S_atPre == null)
            {
                this.S_atPre = new byte[BlockSize];
            }
            else
            {
                Array.Clear(this.S_atPre, 0, this.S_atPre.Length);
            }

            if (this.atBlock == null)
            {
                this.atBlock = new byte[BlockSize];
            }
            else
            {
                Array.Clear(this.atBlock, 0, this.atBlock.Length);
            }

            this.atBlockPos  = 0;
            this.atLength    = 0;
            this.atLengthPre = 0;

            //this.counter = Arrays.Clone(J0);
            //BufferPool.Resize(ref this.counter, BlockSize, false, true);
            if (this.counter == null)
            {
                this.counter = new byte[BlockSize];
            }
            else
            {
                Array.Clear(this.counter, 0, this.counter.Length);
            }

            Array.Copy(this.J0, 0, this.counter, 0, BlockSize);

            this.blocksRemaining = uint.MaxValue - 1; // page 8, len(P) <= 2^39 - 256, 1 block used by tag
            this.bufOff          = 0;
            this.totalLength     = 0;

            if (initialAssociatedText != null)
            {
                ProcessAadBytes(initialAssociatedText, 0, initialAssociatedText.Length);
            }
        }
Exemple #10
0
        public virtual void Init(bool forEncryption, ICipherParameters parameters)
        {
            this.forEncryption = forEncryption;
            macBlock           = null;
            KeyParameter keyParameter;

            if (parameters is AeadParameters)
            {
                AeadParameters aeadParameters = (AeadParameters)parameters;
                nonce = aeadParameters.GetNonce();
                initialAssociatedText = aeadParameters.GetAssociatedText();
                int num = aeadParameters.MacSize;
                if (num < 32 || num > 128 || num % 8 != 0)
                {
                    throw new ArgumentException("Invalid value for MAC size: " + num);
                }
                macSize      = num / 8;
                keyParameter = aeadParameters.Key;
            }
            else
            {
                if (!(parameters is ParametersWithIV))
                {
                    throw new ArgumentException("invalid parameters passed to GCM");
                }
                ParametersWithIV parametersWithIV = (ParametersWithIV)parameters;
                nonce = parametersWithIV.GetIV();
                initialAssociatedText = null;
                macSize      = 16;
                keyParameter = (KeyParameter)parametersWithIV.Parameters;
            }
            int num2 = (!forEncryption) ? (16 + macSize) : 16;

            bufBlock = new byte[num2];
            if (nonce == null || nonce.Length < 1)
            {
                throw new ArgumentException("IV must be at least 1 byte");
            }
            if (keyParameter != null)
            {
                cipher.Init(forEncryption: true, keyParameter);
                H = new byte[16];
                cipher.ProcessBlock(H, 0, H, 0);
                multiplier.Init(H);
                exp = null;
            }
            else if (H == null)
            {
                throw new ArgumentException("Key must be specified in initial init");
            }
            J0 = new byte[16];
            if (nonce.Length == 12)
            {
                Array.Copy(nonce, 0, J0, 0, nonce.Length);
                J0[15] = 1;
            }
            else
            {
                gHASH(J0, nonce, nonce.Length);
                byte[] array = new byte[16];
                Pack.UInt64_To_BE((ulong)((long)nonce.Length * 8L), array, 8);
                gHASHBlock(J0, array);
            }
            S           = new byte[16];
            S_at        = new byte[16];
            S_atPre     = new byte[16];
            atBlock     = new byte[16];
            atBlockPos  = 0;
            atLength    = 0uL;
            atLengthPre = 0uL;
            counter     = Arrays.Clone(J0);
            bufOff      = 0;
            totalLength = 0uL;
            if (initialAssociatedText != null)
            {
                ProcessAadBytes(initialAssociatedText, 0, initialAssociatedText.Length);
            }
        }
 public virtual void Init(bool forEncryption, ICipherParameters parameters)
 {
     this.forEncryption = forEncryption;
     macBlock           = null;
     initialised        = true;
     byte[] array = null;
     if (parameters is AeadParameters)
     {
         AeadParameters aeadParameters = (AeadParameters)parameters;
         array = aeadParameters.GetNonce();
         initialAssociatedText = aeadParameters.GetAssociatedText();
         int num = aeadParameters.MacSize;
         if (num < 32 || num > 128 || num % 8 != 0)
         {
             throw new ArgumentException("Invalid value for MAC size: " + num);
         }
         macSize = num / 8;
         KeyParameter key  = aeadParameters.Key;
         int          num2 = forEncryption ? 16 : (16 + macSize);
         bufBlock = new byte[num2];
         if (array == null || array.Length < 1)
         {
             throw new ArgumentException("IV must be at least 1 byte");
         }
         if (forEncryption && nonce != null && Arrays.AreEqual(nonce, array))
         {
             if (key == null)
             {
                 throw new ArgumentException("cannot reuse nonce for GCM encryption");
             }
             if (lastKey != null && Arrays.AreEqual(lastKey, key.GetKey()))
             {
                 throw new ArgumentException("cannot reuse nonce for GCM encryption");
             }
         }
         nonce = array;
         if (key != null)
         {
             lastKey = key.GetKey();
         }
         if (key != null)
         {
             cipher.Init(forEncryption: true, key);
             H = new byte[16];
             cipher.ProcessBlock(H, 0, H, 0);
             multiplier.Init(H);
             exp = null;
         }
         else if (H == null)
         {
             throw new ArgumentException("Key must be specified in initial init");
         }
         J0 = new byte[16];
         if (nonce.Length == 12)
         {
             Array.Copy(nonce, 0, J0, 0, nonce.Length);
             J0[15] = 1;
         }
         else
         {
             gHASH(J0, nonce, nonce.Length);
             byte[] array2 = new byte[16];
             Pack.UInt64_To_BE((ulong)((long)nonce.Length * 8L), array2, 8);
             gHASHBlock(J0, array2);
         }
         S               = new byte[16];
         S_at            = new byte[16];
         S_atPre         = new byte[16];
         atBlock         = new byte[16];
         atBlockPos      = 0;
         atLength        = 0uL;
         atLengthPre     = 0uL;
         counter         = Arrays.Clone(J0);
         blocksRemaining = 4294967294u;
         bufOff          = 0;
         totalLength     = 0uL;
         if (initialAssociatedText != null)
         {
             ProcessAadBytes(initialAssociatedText, 0, initialAssociatedText.Length);
         }
         return;
     }
     throw new ArgumentException("invalid parameters passed to GCM");
 }
Exemple #12
0
        public int DoFinal(byte[] output, int outOff)
        {
            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 InvalidCipherTextException("data too short");
                }
                num -= this.macSize;
                Check.OutputLength(output, outOff, num, "Output buffer too short");
            }
            if (num > 0)
            {
                this.gCTRPartial(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 InvalidCipherTextException("mac check in GCM failed");
                }
            }
            this.Reset(false);
            return(num2);
        }