Beispiel #1
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));
        }
        /// <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);
            }
        }
Beispiel #3
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)
        {
            /*
             * 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);
        }
Beispiel #5
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));
        }
Beispiel #6
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);
        }