protected override byte[] GetClientHello()
        {
            if (m_State != HandshakeType.Nothing && m_State != HandshakeType.Finished)
            {
                throw new SslException(AlertDescription.UnexpectedMessage, "ClientHello message must be the first message or must be preceded by a Finished message.");
            }
            m_IsNegotiating = true;
            m_State         = HandshakeType.ClientHello;
            byte[]           ciphers = CipherSuites.GetCipherAlgorithmBytes(m_Options.AllowedAlgorithms);
            byte[]           compr   = CompressionAlgorithm.GetCompressionAlgorithmBytes(m_Options.AllowedAlgorithms);
            HandshakeMessage temp    = new HandshakeMessage(HandshakeType.ClientHello, new byte[38 + ciphers.Length + compr.Length]);

            m_ClientTime   = GetUnixTime();
            m_ClientRandom = new byte[28];
            m_RNG.GetBytes(m_ClientRandom);
            ProtocolVersion pv = CompatibilityLayer.GetMaxProtocol(m_Options.Protocol);

            temp.fragment[0] = pv.major;
            temp.fragment[1] = pv.minor;
            Array.Copy(m_ClientTime, 0, temp.fragment, 2, 4);
            Array.Copy(m_ClientRandom, 0, temp.fragment, 6, 28);
            temp.fragment[34] = 0;             // do not resume a session, and do not let the other side cache it
            temp.fragment[35] = (byte)(ciphers.Length / 256);
            temp.fragment[36] = (byte)(ciphers.Length % 256);
            Array.Copy(ciphers, 0, temp.fragment, 37, ciphers.Length);
            temp.fragment[37 + ciphers.Length] = (byte)compr.Length;
            Array.Copy(compr, 0, temp.fragment, 38 + ciphers.Length, compr.Length);
            byte[] ret = temp.ToBytes();
            UpdateHashes(ret, HashUpdate.All);             // client hello message
            return(m_RecordLayer.EncryptBytes(ret, 0, ret.Length, ContentType.Handshake));
        }
예제 #2
0
        protected override byte[] GetClientHello()
        {
            if (m_State != HandshakeType.Nothing && m_State != HandshakeType.Finished)
            {
                throw new SslException(AlertDescription.UnexpectedMessage, "ClientHello message must be the first message or must be preceded by a Finished message.");
            }

            m_IsNegotiating = true;
            m_State         = HandshakeType.ClientHello;
            byte[] ciphers = CipherSuites.GetCipherAlgorithmBytes(m_Options.AllowedAlgorithms);
            byte[] compr   = CompressionAlgorithm.GetCompressionAlgorithmBytes(m_Options.AllowedAlgorithms);

            MemoryStream clientHello = new MemoryStream();

            m_ClientTime   = GetUnixTime();
            m_ClientRandom = new byte[28];
            m_RNG.GetBytes(m_ClientRandom);

            ProtocolVersion pv = CompatibilityLayer.GetMaxProtocol(m_Options.Protocol);

            clientHello.WriteByte(pv.major);
            clientHello.WriteByte(pv.minor);
            clientHello.Write(m_ClientTime, 0, m_ClientTime.Length);
            clientHello.Write(m_ClientRandom, 0, m_ClientRandom.Length);
            clientHello.WriteByte(0);
            clientHello.WriteByte((byte)(ciphers.Length / 256));
            clientHello.WriteByte((byte)(ciphers.Length % 256));
            clientHello.Write(ciphers, 0, ciphers.Length);
            clientHello.WriteByte((byte)compr.Length);
            clientHello.Write(compr, 0, compr.Length);

            if (this.clientHelloExts != null)
            {
                this.clientHelloExts.WriteExtensions(clientHello, ConnectionEnd.Client);
            }

            HandshakeMessage hm = new HandshakeMessage(HandshakeType.ClientHello, clientHello.ToArray());

            byte[] ret = hm.ToBytes();
            UpdateHashes(ret, HashUpdate.All);             // client hello message
            return(m_RecordLayer.EncryptBytes(ret, 0, ret.Length, ContentType.Handshake));
        }
        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);
        }