Example #1
0
        /// <exception cref="IOException"></exception>
        public virtual BufferSegment DecodeCiphertext(long seqNo, byte type, byte[] ciphertext, int offset, int len)
        {
            byte[] output;
            if (readMac == null)
            {
                output = Arrays.CopyOfRange(ciphertext, offset, offset + len);
                return(new BufferSegment(output, 0, output.Length));
            }

            int macSize = readMac.Size;

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

            int macInputLen = len - macSize;

            BufferSegment receivedMac = new BufferSegment(ciphertext, offset + macInputLen, offset + len);
            BufferSegment computedMac = readMac.CalculateMac(seqNo, type, ciphertext, offset, macInputLen);

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

            BufferPool.Release(computedMac);

            output = Arrays.CopyOfRange(ciphertext, offset, offset + macInputLen);
            return(new BufferSegment(output, 0, output.Length));
        }
        /// <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));
        }
Example #3
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);
            }
        }
Example #4
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)
        {
            BufferSegment receivedMac = new BufferSegment(recBuf, recStart, recEnd - recStart);
            BufferSegment computedMac = readMac.CalculateMac(seqNo, type, calcBuf, calcOff, calcLen);

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

            BufferPool.Release(computedMac);
        }
        /// <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);
        }
Example #6
0
        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);
        }
Example #7
0
        /// <exception cref="IOException"></exception>
        public virtual BufferSegment EncodePlaintext(long seqNo, byte type, byte[] plaintext, int offset, int len)
        {
            if (writeMac == null)
            {
                byte[] output = Arrays.CopyOfRange(plaintext, offset, offset + len);
                return(new BufferSegment(output, 0, output.Length));
            }

            BufferSegment mac = writeMac.CalculateMac(seqNo, type, plaintext, offset, len);
            int           ciphertextLength = len + mac.Count;

            byte[] ciphertext = BufferPool.Get(len + mac.Count, true);
            Array.Copy(plaintext, offset, ciphertext, 0, len);
            Array.Copy(mac.Data, 0, ciphertext, len, mac.Count);

            BufferPool.Release(mac);

            return(new BufferSegment(ciphertext, 0, ciphertextLength));
        }
Example #8
0
        public virtual BufferSegment EncodePlaintext(long seqNo, byte type, byte[] plaintext, int offset, int len)
        {
            if (usesNonce)
            {
                UpdateIV(encryptCipher, true, seqNo);
            }

            int outBufLength = len + writeMac.Size;

            byte[] outBuf = BufferPool.Get(outBufLength, true);

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

            BufferSegment mac = writeMac.CalculateMac(seqNo, type, plaintext, offset, len);

            encryptCipher.ProcessBytes(mac.Data, mac.Offset, mac.Count, outBuf, len);

            BufferPool.Release(mac);

            return(new BufferSegment(outBuf, 0, outBufLength));
        }
Example #9
0
        /// <exception cref="IOException"></exception>
        public virtual BufferSegment 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;
                BufferSegment receivedMac   = new BufferSegment(ciphertext, end - macSize, macSize);
                BufferSegment calculatedMac = mReadMac.CalculateMac(seqNo, type, ciphertext, offset, len - macSize);

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

                BufferPool.Release(calculatedMac);

                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;
                BufferSegment receivedMac   = new BufferSegment(ciphertext, macOff, macSize);
                BufferSegment calculatedMac = mReadMac.CalculateMacConstantTime(seqNo, type, ciphertext, offset, macInputLen, blocks_length - macSize, randomData);

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

                BufferPool.Release(calculatedMac);
            }

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

            //byte[] output = BufferPool.Get(dec_output_length, true); //Arrays.CopyOfRange(ciphertext, offset, offset + dec_output_length);
            //Array.Copy(ciphertext, offset, output, 0, dec_output_length);
            return(new BufferSegment(ciphertext, offset, dec_output_length));
        }
Example #10
0
        public virtual BufferSegment 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);

            /*
             * Don't use variable-length padding with truncated MACs.
             *
             * See "Tag Size Does Matter: Attacks and Proofs for the TLS Record Protocol", Paterson,
             * Ristenpart, Shrimpton.
             */
            if (encryptThenMac || !context.SecurityParameters.truncatedHMac)
            {
                // 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 = BufferPool.Get(totalSize, true);
            int    outOff = 0;

            if (useExplicitIV)
            {
                if (explicitIV == null || explicitIV.Length != blockSize)
                {
                    Array.Resize(ref explicitIV, 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)
            {
                BufferSegment mac = mWriteMac.CalculateMac(seqNo, type, plaintext, offset, len);
                Array.Copy(mac.Data, mac.Offset, outBuf, outOff, mac.Count);
                outOff += mac.Count;

                BufferPool.Release(mac);
            }

            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)
            {
                BufferSegment mac = mWriteMac.CalculateMac(seqNo, type, outBuf, 0, outOff);
                Array.Copy(mac.Data, mac.Offset, outBuf, outOff, mac.Count);
                outOff += mac.Count;
                BufferPool.Release(mac);
            }

            //        assert outBuf.length == outOff;

            return(new BufferSegment(outBuf, 0, totalSize));
        }