コード例 #1
0
		protected override SslHandshakeStatus ProcessMessage(HandshakeMessage message) { // throws SslExceptions
			SslHandshakeStatus ret = new SslHandshakeStatus();
			switch(message.type) {
				case HandshakeType.ServerHello:
					ret = ProcessServerHello(message);
					break;
				case HandshakeType.Certificate: // optional
					ret = ProcessCertificate(message, true);
					break;
				case HandshakeType.ServerKeyExchange: // optional
					ret = ProcessServerKeyExchange(message);
					break;
				case HandshakeType.CertificateRequest: // optional
					ret = ProcessCertificateRequest(message);
					break;
				case HandshakeType.ServerHelloDone:
					ret = ProcessServerHelloDone(message);
					break;
				case HandshakeType.Finished:
					ret = ProcessFinished(message);
					break;
				case HandshakeType.HelloRequest:
					ret = ProcessHelloRequest(message);
					break;
				default:
					throw new SslException(AlertDescription.UnexpectedMessage, "The received message was not expected from a server.");
			}
			return ret;
		}
コード例 #2
0
ファイル: HandshakeLayer.cs プロジェクト: skoant/http2-katana
        // processes Handshake & ChangeCipherSpec messages
        public SslHandshakeStatus ProcessMessages(RecordMessage message)
        {
            if (message == null)
            {
                throw new ArgumentNullException();
            }
            SslHandshakeStatus ret;

            if (message.contentType == ContentType.ChangeCipherSpec)
            {
                ret     = ProcessChangeCipherSpec(message);
                m_State = HandshakeType.ChangeCipherSpec;
            }
            else if (message.contentType == ContentType.Handshake)
            {
                ret = new SslHandshakeStatus();
                // copy the new bytes and the old bytes in one buffer
                MemoryStream ms         = new MemoryStream();
                byte[]       fullbuffer = new byte[m_IncompleteMessage.Length + message.length];
                Buffer.BlockCopy(m_IncompleteMessage, 0, fullbuffer, 0, m_IncompleteMessage.Length);
                Buffer.BlockCopy(message.fragment, 0, fullbuffer, m_IncompleteMessage.Length, message.length);
                // loop through all messages in buffer, if any
                int offset          = 0;
                HandshakeMessage hm = GetHandshakeMessage(fullbuffer, offset);

                while (hm != null)
                {
                    offset += hm.fragment.Length + 4;
                    SslHandshakeStatus status = ProcessMessage(hm);
                    if (status.Message != null)
                    {
                        ms.Write(status.Message, 0, status.Message.Length);
                    }
                    ret.Status = status.Status;
                    // go to next message
                    m_State = hm.type;
                    hm      = GetHandshakeMessage(fullbuffer, offset);
                }
                if (offset > 0)
                {
                    m_IncompleteMessage = new byte[fullbuffer.Length - offset];
                    Buffer.BlockCopy(fullbuffer, offset, m_IncompleteMessage, 0, m_IncompleteMessage.Length);
                }
                else
                {
                    m_IncompleteMessage = fullbuffer;
                }
                if (ms.Length > 0)
                {
                    ret.Message = ms.ToArray();
                }
                ms.Close();
            }
            else                 // message.contentType == ContentType.Alert
            {
                ret = ProcessAlert(message);
            }
            return(ret);
        }
コード例 #3
0
ファイル: HandshakeLayer.cs プロジェクト: skoant/http2-katana
        protected SslHandshakeStatus ProcessAlert(RecordMessage message)
        {
            if (message.length != 2 || message.fragment.Length != 2)
            {
                throw new SslException(AlertDescription.RecordOverflow, "The alert message is invalid.");
            }
            try {
                AlertLevel       level       = (AlertLevel)message.fragment[0];
                AlertDescription description = (AlertDescription)message.fragment[1];

                if (level == AlertLevel.Fatal && description == AlertDescription.NoApplicationProtocol)
                {
                    throw new ALPNCantSelectProtocolException();
                }

                if (level == AlertLevel.Fatal)
                {
                    throw new SslException(description, "The other side has sent a failure alert with code: " + description.ToString());
                }
                SslHandshakeStatus ret;
                if (description == AlertDescription.CloseNotify)
                {
                    if (m_State == HandshakeType.ShuttingDown)                       // true if we've already sent a shutdown notification
                    // close connection
                    {
                        ret = new SslHandshakeStatus(SslStatus.Close, null);
                    }
                    else
                    {
                        // send a shutdown notifications, and then close the connection
                        ret = new SslHandshakeStatus(SslStatus.Close, GetControlBytes(ControlType.Shutdown));
                    }
                }
                else
                {
                    ret = new SslHandshakeStatus(SslStatus.OK, null);
                }
                return(ret);
            } catch (SslException) {
                throw;
            } catch (Exception e) {
                throw new SslException(e, AlertDescription.InternalError, "There was an internal error.");
            }
        }
コード例 #4
0
        protected override SslHandshakeStatus ProcessMessage(HandshakeMessage message)           // throws SslExceptions
        {
            SslHandshakeStatus ret = new SslHandshakeStatus();

            switch (message.type)
            {
            case HandshakeType.ServerHello:
                ret = ProcessServerHello(message);
                break;

            case HandshakeType.Certificate:                     // optional
                ret = ProcessCertificate(message, true);
                break;

            case HandshakeType.ServerKeyExchange:                     // optional
                ret = ProcessServerKeyExchange(message);
                break;

            case HandshakeType.CertificateRequest:                     // optional
                ret = ProcessCertificateRequest(message);
                break;

            case HandshakeType.ServerHelloDone:
                ret = ProcessServerHelloDone(message);
                break;

            case HandshakeType.Finished:
                ret = ProcessFinished(message);
                break;

            case HandshakeType.HelloRequest:
                ret = ProcessHelloRequest(message);
                break;

            default:
                throw new SslException(AlertDescription.UnexpectedMessage, "The received message was not expected from a server.");
            }
            return(ret);
        }
コード例 #5
0
 protected SslHandshakeStatus ProcessAlert(RecordMessage message)
 {
     if (message.length != 2 || message.fragment.Length != 2)
         throw new SslException(AlertDescription.RecordOverflow, "The alert message is invalid.");
     try {
         AlertLevel level = (AlertLevel)message.fragment[0];
         AlertDescription description = (AlertDescription)message.fragment[1];
         if (level == AlertLevel.Fatal)
             throw new SslException(description, "The other side has sent a failure alert.");
         SslHandshakeStatus ret;
         if (description == AlertDescription.CloseNotify) {
             if (m_State == HandshakeType.ShuttingDown) { // true if we've already sent a shutdown notification
                 // close connection
                 ret = new SslHandshakeStatus(SslStatus.Close, null);
             } else {
                 // send a shutdown notifications, and then close the connection
                 ret = new SslHandshakeStatus(SslStatus.Close, GetControlBytes(ControlType.Shutdown));
             }
         } else {
             ret = new SslHandshakeStatus(SslStatus.OK, null);
         }
         return ret;
     } catch (SslException t) {
         throw t;
     } catch (Exception e) {
         throw new SslException(e, AlertDescription.InternalError, "There was an internal error.");
     }
 }
コード例 #6
0
 // processes Handshake & ChangeCipherSpec messages
 public SslHandshakeStatus ProcessMessages(RecordMessage message)
 {
     if (message == null)
         throw new ArgumentNullException();
     SslHandshakeStatus ret;
     if (message.contentType == ContentType.ChangeCipherSpec) {
         ret = ProcessChangeCipherSpec(message);
         m_State = HandshakeType.ChangeCipherSpec;
     } else if (message.contentType == ContentType.Handshake) {
         ret = new SslHandshakeStatus();
         // copy the new bytes and the old bytes in one buffer
         MemoryStream ms = new MemoryStream();
         byte[] fullbuffer = new byte[m_IncompleteMessage.Length + message.length];
         Array.Copy(m_IncompleteMessage, 0, fullbuffer, 0, m_IncompleteMessage.Length);
         Array.Copy(message.fragment, 0, fullbuffer, m_IncompleteMessage.Length, message.length);
         // loop through all messages in buffer, if any
         int offset = 0;
         HandshakeMessage hm = GetHandshakeMessage(fullbuffer, offset);
         while(hm != null) {
             offset += hm.fragment.Length + 4;
             SslHandshakeStatus status = ProcessMessage(hm);
             if (status.Message != null) {
                 ms.Write(status.Message, 0, status.Message.Length);
             }
             ret.Status = status.Status;
             // go to next message
             m_State = hm.type;
             hm = GetHandshakeMessage(fullbuffer, offset);
         }
         if (offset > 0) {
             m_IncompleteMessage = new byte[fullbuffer.Length - offset];
             Array.Copy(fullbuffer, offset, m_IncompleteMessage, 0, m_IncompleteMessage.Length);
         } else {
             m_IncompleteMessage = fullbuffer;
         }
         if (ms.Length > 0) {
             ret.Message = ms.ToArray();
         }
         ms.Close();
     } else { // message.contentType == ContentType.Alert
         ret = ProcessAlert(message);
     }
     return ret;
 }
コード例 #7
0
		protected SslHandshakeStatus GetClientHelloResult() {
			MemoryStream retMessage = new MemoryStream();
			SslHandshakeStatus ret = new SslHandshakeStatus();
			HandshakeMessage temp;
			byte[] bytes;
			// ServerHello message
			temp = new HandshakeMessage(HandshakeType.ServerHello, new byte[38]);
			m_ServerTime = GetUnixTime();
			m_ServerRandom = new byte[28];
			m_RNG.GetBytes(m_ServerRandom);
			temp.fragment[0] = GetVersion().major;
			temp.fragment[1] = GetVersion().minor;
			Array.Copy(m_ServerTime, 0, temp.fragment, 2, 4);
			Array.Copy(m_ServerRandom, 0, temp.fragment, 6, 28);
			temp.fragment[34] = 0; // do not resume a session, and do not let the other side cache it
			Array.Copy(CipherSuites.GetCipherAlgorithmBytes(m_EncryptionScheme), 0, temp.fragment, 35, 2);
			temp.fragment[37] = CompressionAlgorithm.GetAlgorithmByte(m_CompressionMethod);
			bytes = temp.ToBytes();
			retMessage.Write(bytes, 0, bytes.Length);
			// Certificate message
			byte[] certs = GetCertificateList(m_Options.Certificate);
			temp.type = HandshakeType.Certificate;
			temp.fragment = certs;
			bytes = temp.ToBytes();
			retMessage.Write(bytes, 0, bytes.Length);
			// ServerKeyExchange message [optional] => only with RSA_EXPORT and public key > 512 bits
			if (m_Options.Certificate.GetPublicKeyLength() > 512 && CipherSuites.GetCipherDefinition(m_EncryptionScheme).Exportable) {
				MemoryStream kes = new MemoryStream();
				MD5SHA1CryptoServiceProvider mscsp = new MD5SHA1CryptoServiceProvider();
				// hash the client and server random values
				mscsp.TransformBlock(m_ClientTime, 0, 4, m_ClientTime, 0);
				mscsp.TransformBlock(m_ClientRandom, 0, 28, m_ClientRandom, 0);
				mscsp.TransformBlock(m_ServerTime, 0, 4, m_ServerTime, 0);
				mscsp.TransformBlock(m_ServerRandom, 0, 28, m_ServerRandom, 0);
				// create a new 512 bit RSA key
				m_KeyCipher = new RSACryptoServiceProvider(512);
				RSAParameters p = m_KeyCipher.ExportParameters(false);
				// write the key parameters to the output stream
				bytes = new byte[]{(byte)(p.Modulus.Length / 256), (byte)(p.Modulus.Length % 256)};
				kes.Write(bytes, 0, 2);
				kes.Write(p.Modulus, 0, p.Modulus.Length);
				mscsp.TransformBlock(bytes, 0, 2, bytes, 0);
				mscsp.TransformBlock(p.Modulus, 0, p.Modulus.Length, p.Modulus, 0);
				bytes = new byte[]{(byte)(p.Exponent.Length / 256), (byte)(p.Exponent.Length % 256)};
				kes.Write(bytes, 0, 2);
				kes.Write(p.Exponent, 0, p.Exponent.Length);
				mscsp.TransformBlock(bytes, 0, 2, bytes, 0);
				mscsp.TransformFinalBlock(p.Exponent, 0, p.Exponent.Length);
				// create signature
				bytes = mscsp.CreateSignature(m_Options.Certificate);
				kes.Write(new byte[]{(byte)(bytes.Length / 256), (byte)(bytes.Length % 256)}, 0, 2);
				kes.Write(bytes, 0, bytes.Length);
				// write to output
				temp.type = HandshakeType.ServerKeyExchange;
				temp.fragment = kes.ToArray();
				bytes = temp.ToBytes();
				retMessage.Write(bytes, 0, bytes.Length);
				kes.Close();
			} else {
				m_KeyCipher = (RSACryptoServiceProvider)m_Options.Certificate.PrivateKey;
			}
			// CertificateRequest message [optional]
			if (m_MutualAuthentication) {
				bytes = GetDistinguishedNames();
				if (bytes.Length != 0) { // make sure at least one certificate is returned
					temp.type = HandshakeType.CertificateRequest;
					temp.fragment = new byte[bytes.Length + 4];
					temp.fragment[0] = 1; // one certificate type supported
					temp.fragment[1] = 1; // cert type RSA
					temp.fragment[2] = (byte)(bytes.Length / 256);
					temp.fragment[3] = (byte)(bytes.Length % 256);
					Array.Copy(bytes, 0, temp.fragment, 4, bytes.Length);
					bytes = temp.ToBytes();
					retMessage.Write(bytes, 0, bytes.Length);
				}
			}
			// ServerHelloDone message
			temp.type = HandshakeType.ServerHelloDone;
			temp.fragment = new byte[0];
			bytes = temp.ToBytes();
			retMessage.Write(bytes, 0, bytes.Length);
			// final adjustments
			ret.Status = SslStatus.ContinueNeeded;
			ret.Message = retMessage.ToArray();
			retMessage.Close();
			UpdateHashes(ret.Message, HashUpdate.All); // output message
			ret.Message = m_RecordLayer.EncryptBytes(ret.Message, 0, ret.Message.Length, ContentType.Handshake);
			return ret;
		}
コード例 #8
0
        protected SslHandshakeStatus GetClientHelloResult()
        {
            MemoryStream       retMessage = new MemoryStream();
            SslHandshakeStatus ret        = new SslHandshakeStatus();
            HandshakeMessage   temp;

            byte[] bytes;
            // ServerHello message
            temp           = new HandshakeMessage(HandshakeType.ServerHello, new byte[38]);
            m_ServerTime   = GetUnixTime();
            m_ServerRandom = new byte[28];
            m_RNG.GetBytes(m_ServerRandom);
            temp.fragment[0] = GetVersion().major;
            temp.fragment[1] = GetVersion().minor;
            Array.Copy(m_ServerTime, 0, temp.fragment, 2, 4);
            Array.Copy(m_ServerRandom, 0, temp.fragment, 6, 28);
            temp.fragment[34] = 0;             // do not resume a session, and do not let the other side cache it
            Array.Copy(CipherSuites.GetCipherAlgorithmBytes(m_EncryptionScheme), 0, temp.fragment, 35, 2);
            temp.fragment[37] = CompressionAlgorithm.GetAlgorithmByte(m_CompressionMethod);
            bytes             = temp.ToBytes();
            retMessage.Write(bytes, 0, bytes.Length);
            // Certificate message
            byte[] certs = GetCertificateList(m_Options.Certificate);
            temp.type     = HandshakeType.Certificate;
            temp.fragment = certs;
            bytes         = temp.ToBytes();
            retMessage.Write(bytes, 0, bytes.Length);
            // ServerKeyExchange message [optional] => only with RSA_EXPORT and public key > 512 bits
            if (m_Options.Certificate.GetPublicKeyLength() > 512 && CipherSuites.GetCipherDefinition(m_EncryptionScheme).Exportable)
            {
                MemoryStream kes = new MemoryStream();
                MD5SHA1CryptoServiceProvider mscsp = new MD5SHA1CryptoServiceProvider();
                // hash the client and server random values
                mscsp.TransformBlock(m_ClientTime, 0, 4, m_ClientTime, 0);
                mscsp.TransformBlock(m_ClientRandom, 0, 28, m_ClientRandom, 0);
                mscsp.TransformBlock(m_ServerTime, 0, 4, m_ServerTime, 0);
                mscsp.TransformBlock(m_ServerRandom, 0, 28, m_ServerRandom, 0);
                // create a new 512 bit RSA key
                m_KeyCipher = new RSACryptoServiceProvider(512);
                RSAParameters p = m_KeyCipher.ExportParameters(false);
                // write the key parameters to the output stream
                bytes = new byte[] { (byte)(p.Modulus.Length / 256), (byte)(p.Modulus.Length % 256) };
                kes.Write(bytes, 0, 2);
                kes.Write(p.Modulus, 0, p.Modulus.Length);
                mscsp.TransformBlock(bytes, 0, 2, bytes, 0);
                mscsp.TransformBlock(p.Modulus, 0, p.Modulus.Length, p.Modulus, 0);
                bytes = new byte[] { (byte)(p.Exponent.Length / 256), (byte)(p.Exponent.Length % 256) };
                kes.Write(bytes, 0, 2);
                kes.Write(p.Exponent, 0, p.Exponent.Length);
                mscsp.TransformBlock(bytes, 0, 2, bytes, 0);
                mscsp.TransformFinalBlock(p.Exponent, 0, p.Exponent.Length);
                // create signature
                bytes = mscsp.CreateSignature(m_Options.Certificate);
                kes.Write(new byte[] { (byte)(bytes.Length / 256), (byte)(bytes.Length % 256) }, 0, 2);
                kes.Write(bytes, 0, bytes.Length);
                // write to output
                temp.type     = HandshakeType.ServerKeyExchange;
                temp.fragment = kes.ToArray();
                bytes         = temp.ToBytes();
                retMessage.Write(bytes, 0, bytes.Length);
                kes.Close();
            }
            else
            {
                m_KeyCipher = (RSACryptoServiceProvider)m_Options.Certificate.PrivateKey;
            }
            // CertificateRequest message [optional]
            if (m_MutualAuthentication)
            {
                bytes = GetDistinguishedNames();
                if (bytes.Length != 0)                   // make sure at least one certificate is returned
                {
                    temp.type        = HandshakeType.CertificateRequest;
                    temp.fragment    = new byte[bytes.Length + 4];
                    temp.fragment[0] = 1;                     // one certificate type supported
                    temp.fragment[1] = 1;                     // cert type RSA
                    temp.fragment[2] = (byte)(bytes.Length / 256);
                    temp.fragment[3] = (byte)(bytes.Length % 256);
                    Array.Copy(bytes, 0, temp.fragment, 4, bytes.Length);
                    bytes = temp.ToBytes();
                    retMessage.Write(bytes, 0, bytes.Length);
                }
            }
            // ServerHelloDone message
            temp.type     = HandshakeType.ServerHelloDone;
            temp.fragment = new byte[0];
            bytes         = temp.ToBytes();
            retMessage.Write(bytes, 0, bytes.Length);
            // final adjustments
            ret.Status  = SslStatus.ContinueNeeded;
            ret.Message = retMessage.ToArray();
            retMessage.Close();
            UpdateHashes(ret.Message, HashUpdate.All);             // output message
            ret.Message = m_RecordLayer.EncryptBytes(ret.Message, 0, ret.Message.Length, ContentType.Handshake);
            return(ret);
        }
コード例 #9
0
        public SslRecordStatus ProcessSsl2Hello(byte[] hello)
        {
            SslHandshakeStatus hs = m_HandshakeLayer.ProcessSsl2Hello(hello);

            return(new SslRecordStatus(hs.Status, hs.Message, null));
        }
コード例 #10
0
        public SslRecordStatus ProcessBytes(byte[] buffer, int offset, int size)
        {
            if (buffer == null)
            {
                throw new ArgumentNullException();
            }
            if (offset < 0 || offset + size > buffer.Length || size <= 0)
            {
                throw new ArgumentException();
            }
            SslRecordStatus ret = new SslRecordStatus();

            ret.Status = SslStatus.MessageIncomplete;
            MemoryStream decrypted = new MemoryStream();
            MemoryStream protocol  = new MemoryStream();

            // copy the new bytes and the old bytes in one buffer
            byte[] fullbuffer = new byte[m_IncompleteMessage.Length + size];
            Array.Copy(m_IncompleteMessage, 0, fullbuffer, 0, m_IncompleteMessage.Length);
            Array.Copy(buffer, offset, fullbuffer, m_IncompleteMessage.Length, size);
            // extract all record messages, if any, and process them
            int recordSize = 0;
            int recordLength;

            while (IsRecordMessageComplete(fullbuffer, recordSize))
            {
                RecordMessage message = new RecordMessage(fullbuffer, recordSize);
                recordLength = message.length + 5;
                UnwrapMessage(message);                 // decrypt and verify message
                // process message
                if (message.contentType == ContentType.ApplicationData)
                {
                    if (!m_HandshakeLayer.IsNegotiating())
                    {
                        decrypted.Write(message.fragment, 0, message.fragment.Length);
                    }
                    else
                    {
                        throw new SslException(AlertDescription.UnexpectedMessage, "The handshake procedure was not completed successfully before application data was received.");
                    }
                    ret.Status = SslStatus.OK;
                }
                else                     // handshake message or change cipher spec message
                {
                    SslHandshakeStatus status = m_HandshakeLayer.ProcessMessages(message);
                    if (status.Message != null)
                    {
                        protocol.Write(status.Message, 0, status.Message.Length);
                    }
                    ret.Status = status.Status;
                }
                recordSize += recordLength;
            }
            // copy remaining data [incomplete record]
            if (recordSize > 0)
            {
                m_IncompleteMessage = new byte[fullbuffer.Length - recordSize];
                Array.Copy(fullbuffer, recordSize, m_IncompleteMessage, 0, m_IncompleteMessage.Length);
            }
            else
            {
                m_IncompleteMessage = fullbuffer;
            }
            if (decrypted.Length > 0)
            {
                ret.Decrypted = decrypted.ToArray();
            }
            decrypted.Close();
            if (protocol.Length > 0)
            {
                ret.Buffer = protocol.ToArray();
            }
            protocol.Close();
            return(ret);
        }