Exemplo n.º 1
0
        protected override void ProcessHandshakeMessage(TlsStream handMsg)
        {
            HandshakeType    handshakeType = (HandshakeType)handMsg.ReadByte();
            HandshakeMessage message       = null;

            // Read message length
            int length = handMsg.ReadInt24();

            // Read message data
            byte[] data = new byte[length];
            handMsg.Read(data, 0, length);

            // Create and process the server message
            message = this.createClientHandshakeMessage(handshakeType, data);
            message.Process();

            // Update the last handshake message
            this.Context.LastHandshakeMsg = handshakeType;

            // Update session
            if (message != null)
            {
                message.Update();
                this.Context.HandshakeMessages.WriteByte((byte)handshakeType);
                this.Context.HandshakeMessages.WriteInt24(length);
                this.Context.HandshakeMessages.Write(data, 0, data.Length);
            }
        }
Exemplo n.º 2
0
        public byte[] Expand(string hashName, byte[] secret, byte[] seed, int length)
        {
            int hashLength = hashName == "MD5" ? 16 : 20;
            int iterations = (int)(length / hashLength);

            if ((length % hashLength) > 0)
            {
                iterations++;
            }

            M.HMAC    hmac    = new M.HMAC(hashName, secret);
            TlsStream resMacs = new TlsStream();

            byte[][] hmacs = new byte[iterations + 1][];
            hmacs[0] = seed;
            for (int i = 1; i <= iterations; i++)
            {
                TlsStream hcseed = new TlsStream();
                hmac.TransformFinalBlock(hmacs[i - 1], 0, hmacs[i - 1].Length);
                hmacs[i] = hmac.Hash;
                hcseed.Write(hmacs[i]);
                hcseed.Write(seed);
                hmac.TransformFinalBlock(hcseed.ToArray(), 0, (int)hcseed.Length);
                resMacs.Write(hmac.Hash);
                hcseed.Reset();
            }

            byte[] res = new byte[length];

            Buffer.BlockCopy(resMacs.ToArray(), 0, res, 0, res.Length);

            resMacs.Reset();

            return(res);
        }
Exemplo n.º 3
0
        private byte[] prf(byte[] secret, string label, byte[] random)
        {
            HashAlgorithm md5 = MD5.Create();
            HashAlgorithm sha = SHA1.Create();

            // Compute SHA hash
            TlsStream block = new TlsStream();

            block.Write(Encoding.ASCII.GetBytes(label));
            block.Write(secret);
            block.Write(random);

            byte[] shaHash = sha.ComputeHash(block.ToArray(), 0, (int)block.Length);

            block.Reset();

            // Compute MD5 hash
            block.Write(secret);
            block.Write(shaHash);

            byte[] result = md5.ComputeHash(block.ToArray(), 0, (int)block.Length);

            // Free resources
            block.Reset();

            return(result);
        }
Exemplo n.º 4
0
        public byte[] EncodeRecord(
            ContentType contentType,
            byte[]          recordData,
            int offset,
            int count)
        {
            if (this.context.SentConnectionEnd)
            {
                throw new TlsException(
                          AlertDescription.InternalError,
                          "The session is finished and it's no longer valid.");
            }

            TlsStream record = new TlsStream();

            int position = offset;

            while (position < (offset + count))
            {
                short  fragmentLength = 0;
                byte[] fragment;

                if ((count + offset - position) > Context.MAX_FRAGMENT_SIZE)
                {
                    fragmentLength = Context.MAX_FRAGMENT_SIZE;
                }
                else
                {
                    fragmentLength = (short)(count + offset - position);
                }

                // Fill the fragment data
                fragment = new byte[fragmentLength];
                Buffer.BlockCopy(recordData, position, fragment, 0, fragmentLength);

                if ((this.Context.Write != null) && (this.Context.Write.Cipher != null))
                {
                    // Encrypt fragment
                    fragment = this.encryptRecordFragment(contentType, fragment);
                }

                // Write tls message
                record.Write((byte)contentType);
                record.Write(this.context.Protocol);
                record.Write((short)fragment.Length);
                record.Write(fragment);

                DebugHelper.WriteLine("Record data", fragment);

                // Update buffer position
                position += fragmentLength;
            }

            return(record.ToArray());
        }
Exemplo n.º 5
0
        public virtual void Clear()
        {
            this.compressionMethod = SecurityCompressionType.None;
            this.serverSettings    = new TlsServerSettings();
            this.clientSettings    = new TlsClientSettings();
            this.handshakeMessages = new TlsStream();
            this.sessionId         = null;
            this.handshakeState    = HandshakeState.None;

            this.ClearKeyInfo();
        }
Exemplo n.º 6
0
 public Context(SecurityProtocolType securityProtocolType)
 {
     this.SecurityProtocol  = securityProtocolType;
     this.compressionMethod = SecurityCompressionType.None;
     this.serverSettings    = new TlsServerSettings();
     this.clientSettings    = new TlsClientSettings();
     this.handshakeMessages = new TlsStream();
     this.sessionId         = null;
     this.handshakeState    = HandshakeState.None;
     this.random            = RandomNumberGenerator.Create();
 }
Exemplo n.º 7
0
        public override void ComputeMasterSecret(byte[] preMasterSecret)
        {
            TlsStream masterSecret = new TlsStream();

            masterSecret.Write(this.prf(preMasterSecret, "A", this.Context.RandomCS));
            masterSecret.Write(this.prf(preMasterSecret, "BB", this.Context.RandomCS));
            masterSecret.Write(this.prf(preMasterSecret, "CCC", this.Context.RandomCS));

            this.Context.MasterSecret = masterSecret.ToArray();

            DebugHelper.WriteLine(">>>> MasterSecret", this.Context.MasterSecret);
        }
Exemplo n.º 8
0
        public byte[] PRF(byte[] secret, string label, byte[] data, int length)
        {
            /* Secret Length calc exmplain from the RFC2246. Section 5
             *
             * S1 and S2 are the two halves of the secret and each is the same
             * length. S1 is taken from the first half of the secret, S2 from the
             * second half. Their length is created by rounding up the length of the
             * overall secret divided by two; thus, if the original secret is an odd
             * number of bytes long, the last byte of S1 will be the same as the
             * first byte of S2.
             */

            // split secret in 2
            int secretLen = secret.Length >> 1;

            // rounding up
            if ((secret.Length & 0x1) == 0x1)
            {
                secretLen++;
            }

            // Seed
            TlsStream seedStream = new TlsStream();

            seedStream.Write(Encoding.ASCII.GetBytes(label));
            seedStream.Write(data);
            byte[] seed = seedStream.ToArray();
            seedStream.Reset();

            // Secret 1
            byte[] secret1 = new byte[secretLen];
            Buffer.BlockCopy(secret, 0, secret1, 0, secretLen);

            // Secret2
            byte[] secret2 = new byte[secretLen];
            Buffer.BlockCopy(secret, (secret.Length - secretLen), secret2, 0, secretLen);

            // Secret 1 processing
            byte[] p_md5 = Expand("MD5", secret1, seed, length);

            // Secret 2 processing
            byte[] p_sha = Expand("SHA1", secret2, seed, length);

            // Perfor XOR of both results
            byte[] masterSecret = new byte[length];
            for (int i = 0; i < masterSecret.Length; i++)
            {
                masterSecret[i] = (byte)(p_md5[i] ^ p_sha[i]);
            }

            return(masterSecret);
        }
Exemplo n.º 9
0
        private void ProcessCipherSpecV2Buffer(SecurityProtocolType protocol, byte[] buffer)
        {
            TlsStream codes = new TlsStream(buffer);

            string prefix = (protocol == SecurityProtocolType.Ssl3) ? "SSL_" : "TLS_";

            while (codes.Position < codes.Length)
            {
                byte check = codes.ReadByte();

                if (check == 0)
                {
                    // SSL/TLS cipher spec
                    short code  = codes.ReadInt16();
                    int   index = this.Context.SupportedCiphers.IndexOf(code);
                    if (index != -1)
                    {
                        this.Context.Negotiating.Cipher = this.Context.SupportedCiphers[index];
                        break;
                    }
                }
                else
                {
                    byte[] tmp = new byte[2];
                    codes.Read(tmp, 0, tmp.Length);

                    int         tmpCode = ((check & 0xff) << 16) | ((tmp[0] & 0xff) << 8) | (tmp[1] & 0xff);
                    CipherSuite cipher  = this.MapV2CipherCode(prefix, tmpCode);

                    if (cipher != null)
                    {
                        this.Context.Negotiating.Cipher = cipher;
                        break;
                    }
                }
            }

            if (this.Context.Negotiating == null)
            {
                throw new TlsException(AlertDescription.InsuficientSecurity, "Insuficient Security");
            }
        }
Exemplo n.º 10
0
        protected override void ProcessHandshakeMessage(TlsStream handMsg)
        {
            HandshakeType    handshakeType = (HandshakeType)handMsg.ReadByte();
            HandshakeMessage message       = null;

            DebugHelper.WriteLine(">>>> Processing Handshake record ({0})", handshakeType);

            // Read message length
            int length = handMsg.ReadInt24();

            // Read message data
            byte[] data = null;
            if (length > 0)
            {
                data = new byte[length];
                handMsg.Read(data, 0, length);
            }

            // Create and process the server message
            message = this.createServerHandshakeMessage(handshakeType, data);
            if (message != null)
            {
                message.Process();
            }

            // Update the last handshake message
            this.Context.LastHandshakeMsg = handshakeType;

            // Update session
            if (message != null)
            {
                message.Update();
                this.Context.HandshakeMessages.WriteByte((byte)handshakeType);
                this.Context.HandshakeMessages.WriteInt24(length);
                if (length > 0)
                {
                    this.Context.HandshakeMessages.Write(data, 0, data.Length);
                }
            }
        }
Exemplo n.º 11
0
 protected abstract void ProcessHandshakeMessage(TlsStream handMsg);
Exemplo n.º 12
0
        private void InternalReceiveRecordCallback(IAsyncResult asyncResult)
        {
            ReceiveRecordAsyncResult internalResult = asyncResult.AsyncState as ReceiveRecordAsyncResult;
            Stream record = internalResult.Record;

            try
            {
                int bytesRead = internalResult.Record.EndRead(asyncResult);

                //We're at the end of the stream. Time to bail.
                if (bytesRead == 0)
                {
                    internalResult.SetComplete((byte[])null);
                    return;
                }

                // Try to read the Record Content Type
                int type = internalResult.InitialBuffer[0];

                // Set last handshake message received to None
                this.context.LastHandshakeMsg = HandshakeType.ClientHello;

                ContentType contentType = (ContentType)type;
                byte[]      buffer      = this.ReadRecordBuffer(type, record);
                if (buffer == null)
                {
                    // record incomplete (at the moment)
                    internalResult.SetComplete((byte[])null);
                    return;
                }

                // Decrypt message contents if needed
                if (contentType == ContentType.Alert && buffer.Length == 2)
                {
                }
                else if ((this.Context.Read != null) && (this.Context.Read.Cipher != null))
                {
                    buffer = this.decryptRecordFragment(contentType, buffer);
                    DebugHelper.WriteLine("Decrypted record data", buffer);
                }

                // Process record
                switch (contentType)
                {
                case ContentType.Alert:
                    this.ProcessAlert((AlertLevel)buffer [0], (AlertDescription)buffer [1]);
                    if (record.CanSeek)
                    {
                        // don't reprocess that memory block
                        record.SetLength(0);
                    }
                    buffer = null;
                    break;

                case ContentType.ChangeCipherSpec:
                    this.ProcessChangeCipherSpec();
                    break;

                case ContentType.ApplicationData:
                    break;

                case ContentType.Handshake:
                    TlsStream message = new TlsStream(buffer);
                    while (!message.EOF)
                    {
                        this.ProcessHandshakeMessage(message);
                    }
                    break;

                case (ContentType)0x80:
                    this.context.HandshakeMessages.Write(buffer);
                    break;

                default:
                    throw new TlsException(
                              AlertDescription.UnexpectedMessage,
                              "Unknown record received from server.");
                }

                internalResult.SetComplete(buffer);
            }
            catch (Exception ex)
            {
                internalResult.SetComplete(ex);
            }
        }
Exemplo n.º 13
0
        public override void ComputeKeys()
        {
            // Compute KeyBlock
            TlsStream tmp = new TlsStream();

            char labelChar = 'A';
            int  count     = 1;

            while (tmp.Length < this.KeyBlockSize)
            {
                string label = String.Empty;

                for (int i = 0; i < count; i++)
                {
                    label += labelChar.ToString();
                }

                byte[] block = this.prf(this.Context.MasterSecret, label.ToString(), this.Context.RandomSC);

                int size = (tmp.Length + block.Length) > this.KeyBlockSize ? (this.KeyBlockSize - (int)tmp.Length) : block.Length;

                tmp.Write(block, 0, size);

                labelChar++;
                count++;
            }

            // Create keyblock
            TlsStream keyBlock = new TlsStream(tmp.ToArray());

            this.Context.Negotiating.ClientWriteMAC = keyBlock.ReadBytes(this.HashSize);
            this.Context.Negotiating.ServerWriteMAC = keyBlock.ReadBytes(this.HashSize);
            this.Context.ClientWriteKey             = keyBlock.ReadBytes(this.KeyMaterialSize);
            this.Context.ServerWriteKey             = keyBlock.ReadBytes(this.KeyMaterialSize);

            if (!this.IsExportable)
            {
                if (this.IvSize != 0)
                {
                    this.Context.ClientWriteIV = keyBlock.ReadBytes(this.IvSize);
                    this.Context.ServerWriteIV = keyBlock.ReadBytes(this.IvSize);
                }
                else
                {
                    this.Context.ClientWriteIV = CipherSuite.EmptyArray;
                    this.Context.ServerWriteIV = CipherSuite.EmptyArray;
                }
            }
            else
            {
                HashAlgorithm md5 = MD5.Create();

                int    keySize = (md5.HashSize >> 3);              //in bytes not bits
                byte[] temp    = new byte [keySize];

                // Generate final write keys
                md5.TransformBlock(this.Context.ClientWriteKey, 0, this.Context.ClientWriteKey.Length, temp, 0);
                md5.TransformFinalBlock(this.Context.RandomCS, 0, this.Context.RandomCS.Length);
                byte[] finalClientWriteKey = new byte[this.ExpandedKeyMaterialSize];
                Buffer.BlockCopy(md5.Hash, 0, finalClientWriteKey, 0, this.ExpandedKeyMaterialSize);

                md5.Initialize();
                md5.TransformBlock(this.Context.ServerWriteKey, 0, this.Context.ServerWriteKey.Length, temp, 0);
                md5.TransformFinalBlock(this.Context.RandomSC, 0, this.Context.RandomSC.Length);
                byte[] finalServerWriteKey = new byte[this.ExpandedKeyMaterialSize];
                Buffer.BlockCopy(md5.Hash, 0, finalServerWriteKey, 0, this.ExpandedKeyMaterialSize);

                this.Context.ClientWriteKey = finalClientWriteKey;
                this.Context.ServerWriteKey = finalServerWriteKey;

                // Generate IV keys
                if (this.IvSize > 0)
                {
                    md5.Initialize();
                    temp = md5.ComputeHash(this.Context.RandomCS, 0, this.Context.RandomCS.Length);
                    this.Context.ClientWriteIV = new byte[this.IvSize];
                    Buffer.BlockCopy(temp, 0, this.Context.ClientWriteIV, 0, this.IvSize);

                    md5.Initialize();
                    temp = md5.ComputeHash(this.Context.RandomSC, 0, this.Context.RandomSC.Length);
                    this.Context.ServerWriteIV = new byte[this.IvSize];
                    Buffer.BlockCopy(temp, 0, this.Context.ServerWriteIV, 0, this.IvSize);
                }
                else
                {
                    this.Context.ClientWriteIV = CipherSuite.EmptyArray;
                    this.Context.ServerWriteIV = CipherSuite.EmptyArray;
                }
            }

            DebugHelper.WriteLine(">>>> KeyBlock", keyBlock.ToArray());
            DebugHelper.WriteLine(">>>> ClientWriteKey", this.Context.ClientWriteKey);
            DebugHelper.WriteLine(">>>> ClientWriteIV", this.Context.ClientWriteIV);
            DebugHelper.WriteLine(">>>> ClientWriteMAC", this.Context.Negotiating.ClientWriteMAC);
            DebugHelper.WriteLine(">>>> ServerWriteKey", this.Context.ServerWriteKey);
            DebugHelper.WriteLine(">>>> ServerWriteIV", this.Context.ServerWriteIV);
            DebugHelper.WriteLine(">>>> ServerWriteMAC", this.Context.Negotiating.ServerWriteMAC);

            ClientSessionCache.SetContextInCache(this.Context);
            // Clear no more needed data
            keyBlock.Reset();
            tmp.Reset();
        }
Exemplo n.º 14
0
        public override void ComputeKeys()
        {
            // Create keyblock
            TlsStream keyBlock = new TlsStream(
                this.PRF(
                    this.Context.MasterSecret,
                    "key expansion",
                    this.Context.RandomSC,
                    this.KeyBlockSize));

            this.Context.Negotiating.ClientWriteMAC = keyBlock.ReadBytes(this.HashSize);
            this.Context.Negotiating.ServerWriteMAC = keyBlock.ReadBytes(this.HashSize);
            this.Context.ClientWriteKey             = keyBlock.ReadBytes(this.KeyMaterialSize);
            this.Context.ServerWriteKey             = keyBlock.ReadBytes(this.KeyMaterialSize);

            if (!this.IsExportable)
            {
                if (this.IvSize != 0)
                {
                    this.Context.ClientWriteIV = keyBlock.ReadBytes(this.IvSize);
                    this.Context.ServerWriteIV = keyBlock.ReadBytes(this.IvSize);
                }
                else
                {
                    this.Context.ClientWriteIV = CipherSuite.EmptyArray;
                    this.Context.ServerWriteIV = CipherSuite.EmptyArray;
                }
            }
            else
            {
                // Generate final write keys
                byte[] finalClientWriteKey = PRF(this.Context.ClientWriteKey, "client write key", this.Context.RandomCS, this.ExpandedKeyMaterialSize);
                byte[] finalServerWriteKey = PRF(this.Context.ServerWriteKey, "server write key", this.Context.RandomCS, this.ExpandedKeyMaterialSize);

                this.Context.ClientWriteKey = finalClientWriteKey;
                this.Context.ServerWriteKey = finalServerWriteKey;

                if (this.IvSize > 0)
                {
                    // Generate IV block
                    byte[] ivBlock = PRF(CipherSuite.EmptyArray, "IV block", this.Context.RandomCS, this.IvSize * 2);

                    // Generate IV keys
                    this.Context.ClientWriteIV = new byte[this.IvSize];
                    Buffer.BlockCopy(ivBlock, 0, this.Context.ClientWriteIV, 0, this.Context.ClientWriteIV.Length);

                    this.Context.ServerWriteIV = new byte[this.IvSize];
                    Buffer.BlockCopy(ivBlock, this.IvSize, this.Context.ServerWriteIV, 0, this.Context.ServerWriteIV.Length);
                }
                else
                {
                    this.Context.ClientWriteIV = CipherSuite.EmptyArray;
                    this.Context.ServerWriteIV = CipherSuite.EmptyArray;
                }
            }

            DebugHelper.WriteLine(">>>> KeyBlock", keyBlock.ToArray());
            DebugHelper.WriteLine(">>>> ClientWriteKey", this.Context.ClientWriteKey);
            DebugHelper.WriteLine(">>>> ClientWriteIV", this.Context.ClientWriteIV);
            DebugHelper.WriteLine(">>>> ClientWriteMAC", this.Context.Negotiating.ClientWriteMAC);
            DebugHelper.WriteLine(">>>> ServerWriteKey", this.Context.ServerWriteKey);
            DebugHelper.WriteLine(">>>> ServerWriteIV", this.Context.ServerWriteIV);
            DebugHelper.WriteLine(">>>> ServerWriteMAC", this.Context.Negotiating.ServerWriteMAC);

            ClientSessionCache.SetContextInCache(this.Context);
            // Clear no more needed data
            keyBlock.Reset();
        }