CalculateMac() публичный Метод

public CalculateMac ( Org.BouncyCastle.Crypto.Tls.ContentType type, byte message, int offset, int len ) : byte[]
type Org.BouncyCastle.Crypto.Tls.ContentType
message byte
offset int
len int
Результат byte[]
Пример #1
0
        public virtual byte[] EncodePlaintext(ContentType type, byte[] plaintext, int offset, int len)
        {
            int blocksize      = encryptCipher.GetBlockSize();
            int padding_length = blocksize - 1 - ((len + wMac.Size) % blocksize);

            //bool isTls = context.ServerVersion.FullVersion >= ProtocolVersion.TLSv10.FullVersion;
            bool isTls = true;

            if (isTls)
            {
                // Add a random number of extra blocks worth of padding
                int maxExtraPadBlocks    = (255 - padding_length) / blocksize;
                int actualExtraPadBlocks = ChooseExtraPadBlocks(context.SecureRandom, maxExtraPadBlocks);
                padding_length += actualExtraPadBlocks * blocksize;
            }

            int totalsize = len + wMac.Size + padding_length + 1;

            byte[] outbuf = new byte[totalsize];
            Array.Copy(plaintext, offset, outbuf, 0, len);
            byte[] mac = wMac.CalculateMac(type, plaintext, offset, len);
            Array.Copy(mac, 0, outbuf, len, mac.Length);
            int paddoffset = len + mac.Length;

            for (int i = 0; i <= padding_length; i++)
            {
                outbuf[i + paddoffset] = (byte)padding_length;
            }
            for (int i = 0; i < totalsize; i += blocksize)
            {
                encryptCipher.ProcessBlock(outbuf, i, outbuf, i);
            }
            return(outbuf);
        }
Пример #2
0
        internal override byte[] EncodePlaintext(
            short type,
            byte[]  plaintext,
            int offset,
            int len)
        {
            int blocksize   = encryptCipher.GetBlockSize();
            int paddingsize = blocksize
                              - ((len + writeMac.Size + 1) % blocksize);
            int totalsize = len + writeMac.Size + paddingsize + 1;

            byte[] outbuf = new byte[totalsize];
            Array.Copy(plaintext, offset, outbuf, 0, len);
            byte[] mac = writeMac.CalculateMac(type, plaintext, offset, len);
            Array.Copy(mac, 0, outbuf, len, mac.Length);
            int paddoffset = len + mac.Length;

            for (int i = 0; i <= paddingsize; i++)
            {
                outbuf[i + paddoffset] = (byte)paddingsize;
            }
            for (int i = 0; i < totalsize; i += blocksize)
            {
                encryptCipher.ProcessBlock(outbuf, i, outbuf, i);
            }
            return(outbuf);
        }
Пример #3
0
        public byte[] EncodePlaintext(short type, byte[] plaintext, int offset, int len)
        {
            int blocksize = encryptCipher.GetBlockSize();

            // Add a random number of extra blocks worth of padding
            int minPaddingSize       = blocksize - ((len + writeMac.Size + 1) % blocksize);
            int maxExtraPadBlocks    = (255 - minPaddingSize) / blocksize;
            int actualExtraPadBlocks = ChooseExtraPadBlocks(handler.Random, maxExtraPadBlocks);
            int paddingsize          = minPaddingSize + (actualExtraPadBlocks * blocksize);

            int totalsize = len + writeMac.Size + paddingsize + 1;

            byte[] outbuf = new byte[totalsize];
            Array.Copy(plaintext, offset, outbuf, 0, len);
            byte[] mac = writeMac.CalculateMac(type, plaintext, offset, len);
            Array.Copy(mac, 0, outbuf, len, mac.Length);
            int paddoffset = len + mac.Length;

            for (int i = 0; i <= paddingsize; i++)
            {
                outbuf[i + paddoffset] = (byte)paddingsize;
            }
            for (int i = 0; i < totalsize; i += blocksize)
            {
                encryptCipher.ProcessBlock(outbuf, i, outbuf, i);
            }
            return(outbuf);
        }
Пример #4
0
        /// <exception cref="IOException"></exception>
        public virtual byte[] DecodeCiphertext(long seqNo, byte type, byte[] ciphertext, int offset, int len)
        {
            if (readMac == null)
            {
                return(Arrays.CopyOfRange(ciphertext, offset, offset + len));
            }

            int macSize = readMac.Size;

            if (len < macSize)
            {
                throw new TlsFatalAlert(AlertDescription.decode_error);
            }

            int macInputLen = len - macSize;

            byte[] receivedMac = Arrays.CopyOfRange(ciphertext, offset + macInputLen, offset + len);
            byte[] computedMac = readMac.CalculateMac(seqNo, type, ciphertext, offset, macInputLen);

            if (!Arrays.ConstantTimeAreEqual(receivedMac, computedMac))
            {
                throw new TlsFatalAlert(AlertDescription.bad_record_mac);
            }

            return(Arrays.CopyOfRange(ciphertext, offset, offset + macInputLen));
        }
Пример #5
0
 protected virtual void CheckMac(long seqNo, byte type, byte[] recBuf, int recStart, int recEnd, byte[] calcBuf, int calcOff, int calcLen)
 {
     byte[] a = Arrays.CopyOfRange(recBuf, recStart, recEnd);
     byte[] b = readMac.CalculateMac(seqNo, type, calcBuf, calcOff, calcLen);
     if (!Arrays.ConstantTimeAreEqual(a, b))
     {
         throw new TlsFatalAlert(20);
     }
 }
Пример #6
0
        /// <exception cref="IOException"></exception>
        protected virtual void CheckMac(long seqNo, byte type, byte[] recBuf, int recStart, int recEnd, byte[] calcBuf, int calcOff, int calcLen)
        {
            byte[] receivedMac = Arrays.CopyOfRange(recBuf, recStart, recEnd);
            byte[] computedMac = readMac.CalculateMac(seqNo, type, calcBuf, calcOff, calcLen);

            if (!Arrays.ConstantTimeAreEqual(receivedMac, computedMac))
            {
                throw new TlsFatalAlert(AlertDescription.bad_record_mac);
            }
        }
Пример #7
0
        public byte[] EncodePlaintext(byte type, byte[] plaintext, int offset, int len)
        {
            byte[] mac  = writeMac.CalculateMac(type, plaintext, offset, len);
            int    size = len + mac.Length;

            byte[] outbuf = new byte[size];

            encryptCipher.ProcessBytes(plaintext, offset, len, outbuf, 0);
            encryptCipher.ProcessBytes(mac, 0, mac.Length, outbuf, len);

            return(outbuf);
        }
Пример #8
0
 public virtual byte[] EncodePlaintext(long seqNo, byte type, byte[] plaintext, int offset, int len)
 {
     if (usesNonce)
     {
         UpdateIV(encryptCipher, forEncryption: true, seqNo);
     }
     byte[] array = new byte[len + writeMac.Size];
     encryptCipher.ProcessBytes(plaintext, offset, len, array, 0);
     byte[] array2 = writeMac.CalculateMac(seqNo, type, plaintext, offset, len);
     encryptCipher.ProcessBytes(array2, 0, array2.Length, array, len);
     return(array);
 }
Пример #9
0
 public virtual byte[] EncodePlaintext(long seqNo, byte type, byte[] plaintext, int offset, int len)
 {
     if (writeMac == null)
     {
         return(Arrays.CopyOfRange(plaintext, offset, offset + len));
     }
     byte[] array  = writeMac.CalculateMac(seqNo, type, plaintext, offset, len);
     byte[] array2 = new byte[len + array.Length];
     Array.Copy(plaintext, offset, array2, 0, len);
     Array.Copy(array, 0, array2, len, array.Length);
     return(array2);
 }
Пример #10
0
        /// <exception cref="IOException"></exception>
        public virtual byte[] EncodePlaintext(long seqNo, byte type, byte[] plaintext, int offset, int len)
        {
            if (writeMac == null)
            {
                return(Arrays.CopyOfRange(plaintext, offset, offset + len));
            }

            byte[] mac        = writeMac.CalculateMac(seqNo, type, plaintext, offset, len);
            byte[] ciphertext = new byte[len + mac.Length];
            Array.Copy(plaintext, offset, ciphertext, 0, len);
            Array.Copy(mac, 0, ciphertext, len, mac.Length);
            return(ciphertext);
        }
        public virtual byte[] EncodePlaintext(long seqNo, byte type, byte[] plaintext, int offset, int len)
        {
            if (usesNonce)
            {
                UpdateIV(encryptCipher, true, seqNo);
            }

            byte[] outBuf = new byte[len + writeMac.Size];

            encryptCipher.ProcessBytes(plaintext, offset, len, outBuf, 0);

            byte[] mac = writeMac.CalculateMac(seqNo, type, plaintext, offset, len);
            encryptCipher.ProcessBytes(mac, 0, mac.Length, outBuf, len);

            return(outBuf);
        }
Пример #12
0
        public byte[] DecodeCiphertext(byte type, byte[] ciphertext, int offset, int len)
        {
            byte[] deciphered = new byte[len];
            decryptCipher.ProcessBytes(ciphertext, offset, len, deciphered, 0);

            int plaintextSize = deciphered.Length - readMac.Size;

            byte[] plainText = CopyData(deciphered, 0, plaintextSize);

            byte[] receivedMac = CopyData(deciphered, plaintextSize, readMac.Size);
            byte[] computedMac = readMac.CalculateMac(type, plainText, 0, plainText.Length);

            if (!Arrays.ConstantTimeAreEqual(receivedMac, computedMac))
            {
                throw new TlsFatalAlert(AlertDescription.bad_record_mac);
            }

            return(plainText);
        }
Пример #13
0
        public virtual byte[] EncodePlaintext(long seqNo, byte type, byte[] plaintext, int offset, int len)
        {
            /*
             * draft-josefsson-salsa20-tls-04 2.1 Note that Salsa20 requires a 64-bit nonce. That
             * nonce is updated on the encryption of every TLS record, and is set to be the 64-bit TLS
             * record sequence number. In case of DTLS the 64-bit nonce is formed as the concatenation
             * of the 16-bit epoch with the 48-bit sequence number.
             */
            if (usesNonce)
            {
                UpdateIV(encryptCipher, true, seqNo);
            }

            byte[] outBuf = new byte[len + writeMac.Size];

            encryptCipher.ProcessBytes(plaintext, offset, len, outBuf, 0);

            byte[] mac = writeMac.CalculateMac(seqNo, type, plaintext, offset, len);
            encryptCipher.ProcessBytes(mac, 0, mac.Length, outBuf, len);

            return(outBuf);
        }
Пример #14
0
        public virtual byte[] DecodeCiphertext(long seqNo, byte type, byte[] ciphertext, int offset, int len)
        {
            if (readMac == null)
            {
                return(Arrays.CopyOfRange(ciphertext, offset, offset + len));
            }
            int size = readMac.Size;

            if (len < size)
            {
                throw new TlsFatalAlert(50);
            }
            int num = len - size;

            byte[] a = Arrays.CopyOfRange(ciphertext, offset + num, offset + len);
            byte[] b = readMac.CalculateMac(seqNo, type, ciphertext, offset, num);
            if (!Arrays.ConstantTimeAreEqual(a, b))
            {
                throw new TlsFatalAlert(20);
            }
            return(Arrays.CopyOfRange(ciphertext, offset, offset + num));
        }
Пример #15
0
        public virtual byte[] DecodeCiphertext(long seqNo, byte type, byte[] ciphertext, int offset, int len)
        {
            int blockSize = decryptCipher.GetBlockSize();
            int size      = mReadMac.Size;
            int num       = blockSize;

            num = ((!encryptThenMac) ? Math.Max(num, size + 1) : (num + size));
            if (useExplicitIV)
            {
                num += blockSize;
            }
            if (len < num)
            {
                throw new TlsFatalAlert(50);
            }
            int num2 = len;

            if (encryptThenMac)
            {
                num2 -= size;
            }
            if (num2 % blockSize != 0)
            {
                throw new TlsFatalAlert(21);
            }
            if (encryptThenMac)
            {
                int    num3 = offset + len;
                byte[] b    = Arrays.CopyOfRange(ciphertext, num3 - size, num3);
                byte[] a    = mReadMac.CalculateMac(seqNo, type, ciphertext, offset, len - size);
                if (!Arrays.ConstantTimeAreEqual(a, b))
                {
                    throw new TlsFatalAlert(20);
                }
            }
            if (useExplicitIV)
            {
                decryptCipher.Init(forEncryption: false, new ParametersWithIV(null, ciphertext, offset, blockSize));
                offset += blockSize;
                num2   -= blockSize;
            }
            for (int i = 0; i < num2; i += blockSize)
            {
                decryptCipher.ProcessBlock(ciphertext, offset + i, ciphertext, offset + i);
            }
            int  num4 = CheckPaddingConstantTime(ciphertext, offset, num2, blockSize, (!encryptThenMac) ? size : 0);
            bool flag = num4 == 0;
            int  num5 = num2 - num4;

            if (!encryptThenMac)
            {
                num5 -= size;
                int    num6 = num5;
                int    num7 = offset + num6;
                byte[] b2   = Arrays.CopyOfRange(ciphertext, num7, num7 + size);
                byte[] a2   = mReadMac.CalculateMacConstantTime(seqNo, type, ciphertext, offset, num6, num2 - size, randomData);
                flag |= !Arrays.ConstantTimeAreEqual(a2, b2);
            }
            if (flag)
            {
                throw new TlsFatalAlert(20);
            }
            return(Arrays.CopyOfRange(ciphertext, offset, offset + num5));
        }
Пример #16
0
        public byte[] DecodeCiphertext(short type, byte[] ciphertext, int offset, int len)
        {
            // TODO TLS 1.1 (RFC 4346) introduces an explicit IV

            int  minLength    = readMac.Size + 1;
            int  blocksize    = decryptCipher.GetBlockSize();
            bool decrypterror = false;

            /*
             * ciphertext must be at least (macsize + 1) bytes long
             */
            if (len < minLength)
            {
                handler.FailWithError(TlsProtocolHandler.AL_fatal, TlsProtocolHandler.AP_decode_error);
            }

            /*
             * ciphertext must be a multiple of blocksize
             */
            if (len % blocksize != 0)
            {
                handler.FailWithError(TlsProtocolHandler.AL_fatal, TlsProtocolHandler.AP_decryption_failed);
            }

            /*
             * Decrypt all the ciphertext using the blockcipher
             */
            for (int i = 0; i < len; i += blocksize)
            {
                decryptCipher.ProcessBlock(ciphertext, i + offset, ciphertext, i + offset);
            }

            /*
             * Check if padding is correct
             */
            int lastByteOffset = offset + len - 1;

            byte paddingsizebyte = ciphertext[lastByteOffset];

            int paddingsize = paddingsizebyte;

            int maxPaddingSize = len - minLength;

            if (paddingsize > maxPaddingSize)
            {
                decrypterror = true;
                paddingsize  = 0;
            }
            else
            {
                /*
                 * Now, check all the padding-bytes (constant-time comparison).
                 */
                byte diff = 0;
                for (int i = lastByteOffset - paddingsize; i < lastByteOffset; ++i)
                {
                    diff |= (byte)(ciphertext[i] ^ paddingsizebyte);
                }
                if (diff != 0)
                {
                    /* Wrong padding */
                    decrypterror = true;
                    paddingsize  = 0;
                }
            }

            /*
             * We now don't care if padding verification has failed or not, we will calculate
             * the mac to give an attacker no kind of timing profile he can use to find out if
             * mac verification failed or padding verification failed.
             */
            int plaintextlength = len - minLength - paddingsize;

            byte[] calculatedMac = readMac.CalculateMac(type, ciphertext, offset, plaintextlength);

            /*
             * Check all bytes in the mac (constant-time comparison).
             */
            byte[] decryptedMac = new byte[calculatedMac.Length];
            Array.Copy(ciphertext, offset + plaintextlength, decryptedMac, 0, calculatedMac.Length);

            if (!Arrays.ConstantTimeAreEqual(calculatedMac, decryptedMac))
            {
                decrypterror = true;
            }

            /*
             * Now, it is safe to fail.
             */
            if (decrypterror)
            {
                handler.FailWithError(TlsProtocolHandler.AL_fatal, TlsProtocolHandler.AP_bad_record_mac);
            }

            byte[] plaintext = new byte[plaintextlength];
            Array.Copy(ciphertext, offset, plaintext, 0, plaintextlength);
            return(plaintext);
        }
Пример #17
0
        internal override byte[] DecodeCiphertext(
            short type,
            byte[]                          ciphertext,
            int offset,
            int len,
            TlsProtocolHandler handler)
        {
            int  blocksize    = decryptCipher.GetBlockSize();
            bool decrypterror = false;

            /*
             * Decrypt all the ciphertext using the blockcipher
             */
            for (int i = 0; i < len; i += blocksize)
            {
                decryptCipher.ProcessBlock(ciphertext, i + offset, ciphertext, i
                                           + offset);
            }

            /*
             * Check if padding is correct
             */
            int paddingsize = ciphertext[offset + len - 1];

            if (offset + len - 1 - paddingsize < 0)
            {
                /*
                 * This would lead to an negativ array index, so this padding
                 * must be incorrect!
                 */
                decrypterror = true;
                paddingsize  = 0;
            }
            else
            {
                /*
                 * Now, check all the padding-bytes.
                 */
                for (int i = 0; i <= paddingsize; i++)
                {
                    if (ciphertext[offset + len - 1 - i] != paddingsize)
                    {
                        /* Wrong padding */
                        decrypterror = true;
                    }
                }
            }

            /*
             * We now don't care if padding verification has failed or not,
             * we will calculate the mac to give an attacker no kind of timing
             * profile he can use to find out if mac verification failed or
             * padding verification failed.
             */
            int plaintextlength = len - readMac.Size - paddingsize - 1;

            byte[] calculatedMac = readMac.CalculateMac(type, ciphertext, offset,
                                                        plaintextlength);

            /*
             * Check all bytes in the mac.
             */
            for (int i = 0; i < calculatedMac.Length; i++)
            {
                if (ciphertext[offset + plaintextlength + i] != calculatedMac[i])
                {
                    decrypterror = true;
                }
            }

            /*
             * Now, it is save to fail.
             */
            if (decrypterror)
            {
                handler.FailWithError(TlsProtocolHandler.AL_fatal,
                                      TlsProtocolHandler.AP_bad_record_mac);
            }
            byte[] plaintext = new byte[plaintextlength];
            Array.Copy(ciphertext, offset, plaintext, 0, plaintextlength);
            return(plaintext);
        }
Пример #18
0
        /// <exception cref="IOException"></exception>
        public virtual byte[] DecodeCiphertext(long seqNo, byte type, byte[] ciphertext, int offset, int len)
        {
            int blockSize = decryptCipher.GetBlockSize();
            int macSize   = mReadMac.Size;

            int minLen = blockSize;

            if (encryptThenMac)
            {
                minLen += macSize;
            }
            else
            {
                minLen = System.Math.Max(minLen, macSize + 1);
            }

            if (useExplicitIV)
            {
                minLen += blockSize;
            }

            if (len < minLen)
            {
                throw new TlsFatalAlert(AlertDescription.decode_error);
            }

            int blocks_length = len;

            if (encryptThenMac)
            {
                blocks_length -= macSize;
            }

            if (blocks_length % blockSize != 0)
            {
                throw new TlsFatalAlert(AlertDescription.decryption_failed);
            }

            if (encryptThenMac)
            {
                int    end           = offset + len;
                byte[] receivedMac   = Arrays.CopyOfRange(ciphertext, end - macSize, end);
                byte[] calculatedMac = mReadMac.CalculateMac(seqNo, type, ciphertext, offset, len - macSize);

                bool badMacEtm = !Arrays.ConstantTimeAreEqual(calculatedMac, receivedMac);
                if (badMacEtm)
                {
                    /*
                     * RFC 7366 3. The MAC SHALL be evaluated before any further processing such as
                     * decryption is performed, and if the MAC verification fails, then processing SHALL
                     * terminate immediately. For TLS, a fatal bad_record_mac MUST be generated [2]. For
                     * DTLS, the record MUST be discarded, and a fatal bad_record_mac MAY be generated
                     * [4]. This immediate response to a bad MAC eliminates any timing channels that may
                     * be available through the use of manipulated packet data.
                     */
                    throw new TlsFatalAlert(AlertDescription.bad_record_mac);
                }
            }

            if (useExplicitIV)
            {
                decryptCipher.Init(false, new ParametersWithIV(null, ciphertext, offset, blockSize));

                offset        += blockSize;
                blocks_length -= blockSize;
            }

            for (int i = 0; i < blocks_length; i += blockSize)
            {
                decryptCipher.ProcessBlock(ciphertext, offset + i, ciphertext, offset + i);
            }

            // If there's anything wrong with the padding, this will return zero
            int  totalPad = CheckPaddingConstantTime(ciphertext, offset, blocks_length, blockSize, encryptThenMac ? 0 : macSize);
            bool badMac   = (totalPad == 0);

            int dec_output_length = blocks_length - totalPad;

            if (!encryptThenMac)
            {
                dec_output_length -= macSize;
                int    macInputLen   = dec_output_length;
                int    macOff        = offset + macInputLen;
                byte[] receivedMac   = Arrays.CopyOfRange(ciphertext, macOff, macOff + macSize);
                byte[] calculatedMac = mReadMac.CalculateMacConstantTime(seqNo, type, ciphertext, offset, macInputLen,
                                                                         blocks_length - macSize, randomData);

                badMac |= !Arrays.ConstantTimeAreEqual(calculatedMac, receivedMac);
            }

            if (badMac)
            {
                throw new TlsFatalAlert(AlertDescription.bad_record_mac);
            }

            return(Arrays.CopyOfRange(ciphertext, offset, offset + dec_output_length));
        }
Пример #19
0
        public virtual byte[] EncodePlaintext(long seqNo, byte type, byte[] plaintext, int offset, int len)
        {
            int blockSize = encryptCipher.GetBlockSize();
            int macSize   = mWriteMac.Size;

            ProtocolVersion version = context.ServerVersion;

            int enc_input_length = len;

            if (!encryptThenMac)
            {
                enc_input_length += macSize;
            }

            int padding_length = blockSize - 1 - (enc_input_length % blockSize);

            // TODO[DTLS] Consider supporting in DTLS (without exceeding send limit though)
            if (!version.IsDtls && !version.IsSsl)
            {
                // Add a random number of extra blocks worth of padding
                int maxExtraPadBlocks    = (255 - padding_length) / blockSize;
                int actualExtraPadBlocks = ChooseExtraPadBlocks(context.SecureRandom, maxExtraPadBlocks);
                padding_length += actualExtraPadBlocks * blockSize;
            }

            int totalSize = len + macSize + padding_length + 1;

            if (useExplicitIV)
            {
                totalSize += blockSize;
            }

            byte[] outBuf = new byte[totalSize];
            int    outOff = 0;

            if (useExplicitIV)
            {
                byte[] explicitIV = new byte[blockSize];
                context.NonceRandomGenerator.NextBytes(explicitIV);

                encryptCipher.Init(true, new ParametersWithIV(null, explicitIV));

                Array.Copy(explicitIV, 0, outBuf, outOff, blockSize);
                outOff += blockSize;
            }

            int blocks_start = outOff;

            Array.Copy(plaintext, offset, outBuf, outOff, len);
            outOff += len;

            if (!encryptThenMac)
            {
                byte[] mac = mWriteMac.CalculateMac(seqNo, type, plaintext, offset, len);
                Array.Copy(mac, 0, outBuf, outOff, mac.Length);
                outOff += mac.Length;
            }

            for (int i = 0; i <= padding_length; i++)
            {
                outBuf[outOff++] = (byte)padding_length;
            }

            for (int i = blocks_start; i < outOff; i += blockSize)
            {
                encryptCipher.ProcessBlock(outBuf, i, outBuf, i);
            }

            if (encryptThenMac)
            {
                byte[] mac = mWriteMac.CalculateMac(seqNo, type, outBuf, 0, outOff);
                Array.Copy(mac, 0, outBuf, outOff, mac.Length);
                outOff += mac.Length;
            }

            //        assert outBuf.length == outOff;

            return(outBuf);
        }
Пример #20
0
        /// <exception cref="IOException"></exception>
        public virtual byte[] DecodeCiphertext(long seqNo, byte type, byte[] ciphertext, int offset, int len)
        {
            int blockSize = decryptCipher.GetBlockSize();
            int macSize   = mReadMac.Size;

            int minLen = blockSize;

            if (encryptThenMac)
            {
                minLen += macSize;
            }
            else
            {
                minLen = System.Math.Max(minLen, macSize + 1);
            }

            if (useExplicitIV)
            {
                minLen += blockSize;
            }

            if (len < minLen)
            {
                throw new TlsFatalAlert(AlertDescription.decode_error);
            }

            int blocks_length = len;

            if (encryptThenMac)
            {
                blocks_length -= macSize;
            }

            if (blocks_length % blockSize != 0)
            {
                throw new TlsFatalAlert(AlertDescription.decryption_failed);
            }

            if (encryptThenMac)
            {
                int    end           = offset + len;
                byte[] receivedMac   = Arrays.CopyOfRange(ciphertext, end - macSize, end);
                byte[] calculatedMac = mReadMac.CalculateMac(seqNo, type, ciphertext, offset, len - macSize);

                bool badMac = !Arrays.ConstantTimeAreEqual(calculatedMac, receivedMac);

                if (badMac)
                {
                    throw new TlsFatalAlert(AlertDescription.bad_record_mac);
                }
            }

            if (useExplicitIV)
            {
                decryptCipher.Init(false, new ParametersWithIV(null, ciphertext, offset, blockSize));

                offset        += blockSize;
                blocks_length -= blockSize;
            }

            for (int i = 0; i < blocks_length; i += blockSize)
            {
                decryptCipher.ProcessBlock(ciphertext, offset + i, ciphertext, offset + i);
            }

            // If there's anything wrong with the padding, this will return zero
            int totalPad = CheckPaddingConstantTime(ciphertext, offset, blocks_length, blockSize, encryptThenMac ? 0 : macSize);

            int dec_output_length = blocks_length - totalPad;

            if (!encryptThenMac)
            {
                dec_output_length -= macSize;
                int    macInputLen   = dec_output_length;
                int    macOff        = offset + macInputLen;
                byte[] receivedMac   = Arrays.CopyOfRange(ciphertext, macOff, macOff + macSize);
                byte[] calculatedMac = mReadMac.CalculateMacConstantTime(seqNo, type, ciphertext, offset, macInputLen,
                                                                         blocks_length - macSize, randomData);

                bool badMac = !Arrays.ConstantTimeAreEqual(calculatedMac, receivedMac);

                if (badMac || totalPad == 0)
                {
                    throw new TlsFatalAlert(AlertDescription.bad_record_mac);
                }
            }

            return(Arrays.CopyOfRange(ciphertext, offset, offset + dec_output_length));
        }
Пример #21
0
        public virtual byte[] EncodePlaintext(long seqNo, byte type, byte[] plaintext, int offset, int len)
        {
            int             blockSize     = encryptCipher.GetBlockSize();
            int             size          = mWriteMac.Size;
            ProtocolVersion serverVersion = context.ServerVersion;
            int             num           = len;

            if (!encryptThenMac)
            {
                num += size;
            }
            int num2 = blockSize - 1 - num % blockSize;

            if (!serverVersion.IsDtls && !serverVersion.IsSsl)
            {
                int max  = (255 - num2) / blockSize;
                int num3 = ChooseExtraPadBlocks(context.SecureRandom, max);
                num2 += num3 * blockSize;
            }
            int num4 = len + size + num2 + 1;

            if (useExplicitIV)
            {
                num4 += blockSize;
            }
            byte[] array = new byte[num4];
            int    num5  = 0;

            if (useExplicitIV)
            {
                byte[] array2 = new byte[blockSize];
                context.NonceRandomGenerator.NextBytes(array2);
                encryptCipher.Init(forEncryption: true, new ParametersWithIV(null, array2));
                global::System.Array.Copy((global::System.Array)array2, 0, (global::System.Array)array, num5, blockSize);
                num5 += blockSize;
            }
            int num6 = num5;

            global::System.Array.Copy((global::System.Array)plaintext, offset, (global::System.Array)array, num5, len);
            num5 += len;
            if (!encryptThenMac)
            {
                byte[] array3 = mWriteMac.CalculateMac(seqNo, type, plaintext, offset, len);
                global::System.Array.Copy((global::System.Array)array3, 0, (global::System.Array)array, num5, array3.Length);
                num5 += array3.Length;
            }
            for (int i = 0; i <= num2; i++)
            {
                array[num5++] = (byte)num2;
            }
            for (int j = num6; j < num5; j += blockSize)
            {
                encryptCipher.ProcessBlock(array, j, array, j);
            }
            if (encryptThenMac)
            {
                byte[] array4 = mWriteMac.CalculateMac(seqNo, type, array, 0, num5);
                global::System.Array.Copy((global::System.Array)array4, 0, (global::System.Array)array, num5, array4.Length);
                num5 += array4.Length;
            }
            return(array);
        }