Esempio n. 1
0
        internal void WriteMessage(
            ContentType	type,
            byte[]		message,
            int			offset,
            int			len)
        {
            if (type == ContentType.handshake)
            {
                UpdateHandshakeData(message, offset, len);
            }

            Stream cOut = writeCompression.Compress(buffer);

            byte[] ciphertext;
            if (cOut == buffer)
            {
                ciphertext = writeCipher.EncodePlaintext(type, message, offset, len);
            }
            else
            {
                cOut.Write(message, offset, len);
                cOut.Flush();
                ciphertext = writeCipher.EncodePlaintext(type, buffer.GetBuffer(), 0, (int)buffer.Position);
                buffer.SetLength(0);
            }

            byte[] writeMessage = new byte[ciphertext.Length + 5];
            TlsUtilities.WriteUint8((byte)type, writeMessage, 0);
            TlsUtilities.WriteVersion(writeMessage, 1);
            TlsUtilities.WriteUint16(ciphertext.Length, writeMessage, 3);
            Array.Copy(ciphertext, 0, writeMessage, 5, ciphertext.Length);
            outStr.Write(writeMessage, 0, writeMessage.Length);
            outStr.Flush();
        }
        public byte[] EncodePlaintext(ContentType 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;
        }
Esempio n. 3
0
		/**
		* Calculate the mac for some given data.
		* <p/>
		* TlsMac will keep track of the sequence number internally.
		*
		* @param type    The message type of the message.
		* @param message A byte-buffer containing the message.
		* @param offset  The number of bytes to skip, before the message starts.
		* @param len     The length of the message.
		* @return A new byte-buffer containing the mac value.
		*/
		public virtual byte[] CalculateMac(
			ContentType	type,
			byte[]		message,
			int			offset,
			int			len)
		{
			byte[] macHeader = new byte[13];
			TlsUtilities.WriteUint64(seqNo++, macHeader, 0);
			TlsUtilities.WriteUint8((byte)type, macHeader, 8);
			TlsUtilities.WriteVersion(macHeader, 9);
			TlsUtilities.WriteUint16(len, macHeader, 11);

			mac.BlockUpdate(macHeader, 0, macHeader.Length);
			mac.BlockUpdate(message, offset, len);
			return MacUtilities.DoFinal(mac);
		}
        public byte[] DecodeCiphertext(ContentType 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;
        }
Esempio n. 5
0
        internal byte[] DecodeAndVerify(
            ContentType	type,
            Stream		inStr,
            int			len)
        {
            byte[] buf = new byte[len];
            TlsUtilities.ReadFully(buf, inStr);
            byte[] decoded = readCipher.DecodeCiphertext(type, buf, 0, buf.Length);

            Stream cOut = readCompression.Decompress(buffer);

            if (cOut == buffer)
            {
                return decoded;
            }

            cOut.Write(decoded, 0, decoded.Length);
            cOut.Flush();
            byte[] contents = buffer.ToArray();
            buffer.SetLength(0);
            return contents;
        }
		public virtual byte[] EncodePlaintext(ContentType 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(context.SecureRandom, 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;
		}
        public virtual byte[] DecodeCiphertext(ContentType 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)
			{
				throw new TlsFatalAlert(AlertDescription.decode_error);
			}

			/*
			* ciphertext must be a multiple of blocksize
			*/
			if (len % blocksize != 0)
			{
				throw new TlsFatalAlert(AlertDescription.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)
			{
				throw new TlsFatalAlert(AlertDescription.bad_record_mac);
			}

			byte[] plaintext = new byte[plaintextlength];
			Array.Copy(ciphertext, offset, plaintext, 0, plaintextlength);
			return plaintext;
		}
        internal void ProcessData(
			ContentType	protocol,
			byte[]		buf,
			int			offset,
			int			len)
        {
            /*
            * Have a look at the protocol type, and add it to the correct queue.
            */
            switch (protocol)
            {
                case ContentType.change_cipher_spec:
                    changeCipherSpecQueue.AddData(buf, offset, len);
                    ProcessChangeCipherSpec();
                    break;
                case ContentType.alert:
                    alertQueue.AddData(buf, offset, len);
                    ProcessAlert();
                    break;
                case ContentType.handshake:
                    handshakeQueue.AddData(buf, offset, len);
                    ProcessHandshake();
                    break;
                case ContentType.application_data:
                    if (!appDataReady)
                    {
                        this.FailWithError(AlertLevel.fatal, AlertDescription.unexpected_message);
                    }
                    applicationDataQueue.AddData(buf, offset, len);
                    ProcessApplicationData();
                    break;
                default:
                    /*
                    * Uh, we don't know this protocol.
                    *
                    * RFC2246 defines on page 13, that we should ignore this.
                    */
                    break;
            }
        }
 private void SafeWriteMessage(ContentType type, byte[] buf, int offset, int len)
 {
     try
     {
         rs.WriteMessage(type, buf, offset, len);
     }
     catch (TlsFatalAlert e)
     {
         if (!this.closed)
         {
             this.FailWithError(AlertLevel.fatal, e.AlertDescription);
         }
         throw e;
     }
     catch (IOException e)
     {
         if (!closed)
         {
             this.FailWithError(AlertLevel.fatal, AlertDescription.internal_error);
         }
         throw e;
     }
     catch (Exception e)
     {
         if (!closed)
         {
             this.FailWithError(AlertLevel.fatal, AlertDescription.internal_error);
         }
         throw e;
     }
 }
Esempio n. 10
0
		/**
		* Calculate the mac for some given data.
		* <p/>
		* TlsMac will keep track of the sequence number internally.
		*
		* @param type    The message type of the message.
		* @param message A byte-buffer containing the message.
		* @param offset  The number of bytes to skip, before the message starts.
		* @param len     The length of the message.
		* @return A new byte-buffer containing the mac value.
		*/
		public virtual byte[] CalculateMac(ContentType type, byte[] message, int offset, int len)
		{
            //bool isTls = context.ServerVersion.FullVersion >= ProtocolVersion.TLSv10.FullVersion;
            bool isTls = true;

            byte[] macHeader = new byte[isTls ? 13 : 11];
			TlsUtilities.WriteUint64(seqNo++, macHeader, 0);
			TlsUtilities.WriteUint8((byte)type, macHeader, 8);
            if (isTls)
            {
                TlsUtilities.WriteVersion(macHeader, 9);
            }
			TlsUtilities.WriteUint16(len, macHeader, 11);

            mac.BlockUpdate(macHeader, 0, macHeader.Length);
			mac.BlockUpdate(message, offset, len);
			return MacUtilities.DoFinal(mac);
		}
Esempio n. 11
0
        public virtual byte[] CalculateMacConstantTime(ContentType type, byte[] message, int offset, int len,
            int fullLength, byte[] dummyData)
        {
            // Actual MAC only calculated on 'len' bytes
            byte[] result = CalculateMac(type, message, offset, len);

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

            // ...but ensure a constant number of complete digest blocks are processed (per 'fullLength')
            if (isTls)
            {
                // TODO Currently all TLS digests use a block size of 64, a suffix (length field) of 8, and padding (1+)
                int db = 64, ds = 8;

                int L1 = 13 + fullLength;
                int L2 = 13 + len;

                // How many extra full blocks do we need to calculate?
                int extra = ((L1 + ds) / db) - ((L2 + ds) / db);

                while (--extra >= 0)
                {
                    mac.BlockUpdate(dummyData, 0, db);
                }

                // One more byte in case the implementation is "lazy" about processing blocks
                mac.Update(dummyData[0]);
                mac.Reset();
            }

            return result;
        }
Esempio n. 12
0
        public virtual byte[] DecodeCiphertext(ContentType type, byte[] ciphertext, int offset, int len)
		{
            int blockSize = decryptCipher.GetBlockSize();
            int macSize = rMac.Size;

            /*
             *  TODO[TLS 1.1] Explicit IV implies minLen = blockSize + max(blockSize, macSize + 1),
             *  and will need further changes to offset and plen variables below.
             */

            int minLen = System.Math.Max(blockSize, macSize + 1);
            if (len < minLen)
                throw new TlsFatalAlert(AlertDescription.decode_error);

            if (len % blockSize != 0)
                throw new TlsFatalAlert(AlertDescription.decryption_failed);

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

            int plen = len;

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

            int macInputLen = plen - totalPad - macSize;

            byte[] decryptedMac = Arrays.Copy(ciphertext, offset + macInputLen, macSize);
            byte[] calculatedMac = rMac.CalculateMacConstantTime(type, ciphertext, offset, macInputLen, plen - macSize, randomData);

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

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

            return Arrays.Copy(ciphertext, offset, macInputLen);
		}
Esempio n. 13
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;
		}
        public virtual byte[] DecodeCiphertext(ContentType type, byte[] ciphertext, int offset, int len)
		{
			return CopyData(ciphertext, offset, len);
		}
		public virtual byte[] EncodePlaintext(ContentType type, byte[] plaintext, int offset, int len)
		{
			return CopyData(plaintext, offset, len);
		}