public HandshakeLayer(RecordLayer recordLayer, SecurityOptions options) { connectionEnd = options.Entity; m_Disposed = false; m_Options = options; m_IsNegotiating = true; m_RNG = new RNGCryptoServiceProvider(); m_RecordLayer = recordLayer; m_State = HandshakeType.Nothing; m_IncompleteMessage = new byte[0]; m_LocalMD5Hash = new MD5CryptoServiceProvider(); m_LocalSHA1Hash = new SHA1CryptoServiceProvider(); m_RemoteMD5Hash = new MD5CryptoServiceProvider(); m_RemoteSHA1Hash = new SHA1CryptoServiceProvider(); m_CertSignHash = new MD5SHA1CryptoServiceProvider(); m_CertSignHash.Protocol = this.GetProtocol(); if (options.Entity == ConnectionEnd.Server && ((int)options.Flags & (int)SecurityFlags.MutualAuthentication) != 0) { m_MutualAuthentication = true; } else { m_MutualAuthentication = false; } }
protected SslHandshakeStatus ProcessServerKeyExchange(HandshakeMessage message) { if (m_State != HandshakeType.Certificate) { throw new SslException(AlertDescription.UnexpectedMessage, "ServerKeyExchange message must be preceded by a Certificate message."); } CipherDefinition cd = CipherSuites.GetCipherDefinition(m_EncryptionScheme); if (!cd.Exportable) { throw new SslException(AlertDescription.HandshakeFailure, "The ServerKeyExchange message should not be sent for non-exportable ciphers."); } if (m_RemoteCertificate.GetPublicKeyLength() <= 512) { throw new SslException(AlertDescription.HandshakeFailure, "The ServerKeyExchange message should not be sent because the server certificate public key is of exportable length."); } UpdateHashes(message, HashUpdate.All); // input message // extract modulus and exponent RSAParameters pars = new RSAParameters(); int size = message.fragment[0] * 256 + message.fragment[1]; pars.Modulus = new byte[size]; Buffer.BlockCopy(message.fragment, 2, pars.Modulus, 0, size); int offset = size + 2; size = message.fragment[offset] * 256 + message.fragment[offset + 1]; pars.Exponent = new byte[size]; Buffer.BlockCopy(message.fragment, offset + 2, pars.Exponent, 0, size); offset += size + 2; pars.Modulus = RemoveLeadingZeros(pars.Modulus); pars.Exponent = RemoveLeadingZeros(pars.Exponent); m_KeyCipher = new RSACryptoServiceProvider(); m_KeyCipher.ImportParameters(pars); // compute verification hashes MD5SHA1CryptoServiceProvider ms = new MD5SHA1CryptoServiceProvider(); ms.TransformBlock(m_ClientTime, 0, m_ClientTime.Length, m_ClientTime, 0); ms.TransformBlock(m_ClientRandom, 0, m_ClientRandom.Length, m_ClientRandom, 0); ms.TransformBlock(m_ServerTime, 0, m_ServerTime.Length, m_ServerTime, 0); ms.TransformBlock(m_ServerRandom, 0, m_ServerRandom.Length, m_ServerRandom, 0); ms.TransformFinalBlock(message.fragment, 0, offset); // verify the signature size = message.fragment[offset] * 256 + message.fragment[offset + 1]; byte[] signature = new byte[size]; // holds the signature returned by the server Buffer.BlockCopy(message.fragment, offset + 2, signature, 0, size); if (!ms.VerifySignature(m_RemoteCertificate, signature)) { throw new SslException(AlertDescription.HandshakeFailure, "The data was not signed by the server certificate."); } ms.Clear(); return(new SslHandshakeStatus(SslStatus.MessageIncomplete, null)); }
public HandshakeLayer(RecordLayer recordLayer, SecurityOptions options) { m_Disposed = false; m_Options = options; m_IsNegotiating = true; m_RNG = new RNGCryptoServiceProvider(); m_RecordLayer = recordLayer; m_State = HandshakeType.Nothing; m_IncompleteMessage = new byte[0]; m_LocalMD5Hash = new MD5CryptoServiceProvider(); m_LocalSHA1Hash = new SHA1CryptoServiceProvider(); m_RemoteMD5Hash = new MD5CryptoServiceProvider(); m_RemoteSHA1Hash = new SHA1CryptoServiceProvider(); m_CertSignHash = new MD5SHA1CryptoServiceProvider(); m_CertSignHash.Protocol = this.GetProtocol(); if (options.Entity == ConnectionEnd.Server && ((int)options.Flags & (int)SecurityFlags.MutualAuthentication) != 0) m_MutualAuthentication = true; else m_MutualAuthentication = false; }
protected SslHandshakeStatus ProcessServerKeyExchange(HandshakeMessage message) { if (m_State != HandshakeType.Certificate) throw new SslException(AlertDescription.UnexpectedMessage, "ServerKeyExchange message must be preceded by a Certificate message."); CipherDefinition cd = CipherSuites.GetCipherDefinition(m_EncryptionScheme); if (!cd.Exportable) throw new SslException(AlertDescription.HandshakeFailure, "The ServerKeyExchange message should not be sent for non-exportable ciphers."); if (m_RemoteCertificate.GetPublicKeyLength() <= 512) throw new SslException(AlertDescription.HandshakeFailure, "The ServerKeyExchange message should not be sent because the server certificate public key is of exportable length."); UpdateHashes(message, HashUpdate.All); // input message // extract modulus and exponent RSAParameters pars = new RSAParameters(); int size = message.fragment[0] * 256 + message.fragment[1]; pars.Modulus = new byte[size]; Buffer.BlockCopy(message.fragment, 2, pars.Modulus, 0, size); int offset = size + 2; size = message.fragment[offset] * 256 + message.fragment[offset + 1]; pars.Exponent = new byte[size]; Buffer.BlockCopy(message.fragment, offset + 2, pars.Exponent, 0, size); offset += size + 2; pars.Modulus = RemoveLeadingZeros(pars.Modulus); pars.Exponent = RemoveLeadingZeros(pars.Exponent); m_KeyCipher = new RSACryptoServiceProvider(); m_KeyCipher.ImportParameters(pars); // compute verification hashes MD5SHA1CryptoServiceProvider ms = new MD5SHA1CryptoServiceProvider(); ms.TransformBlock(m_ClientTime, 0, m_ClientTime.Length, m_ClientTime, 0); ms.TransformBlock(m_ClientRandom, 0, m_ClientRandom.Length, m_ClientRandom, 0); ms.TransformBlock(m_ServerTime, 0, m_ServerTime.Length, m_ServerTime, 0); ms.TransformBlock(m_ServerRandom, 0, m_ServerRandom.Length, m_ServerRandom, 0); ms.TransformFinalBlock(message.fragment, 0, offset); // verify the signature size = message.fragment[offset] * 256 + message.fragment[offset + 1]; byte[] signature = new byte[size]; // holds the signature returned by the server Buffer.BlockCopy(message.fragment, offset + 2, signature, 0, size); if (!ms.VerifySignature(m_RemoteCertificate, signature)) throw new SslException(AlertDescription.HandshakeFailure, "The data was not signed by the server certificate."); ms.Clear(); return new SslHandshakeStatus(SslStatus.MessageIncomplete, null); }
public HandshakeLayer(HandshakeLayer handshakeLayer) { m_Disposed = false; m_RecordLayer = handshakeLayer.m_RecordLayer; m_Options = handshakeLayer.m_Options; m_IsNegotiating = handshakeLayer.m_IsNegotiating; m_RNG = handshakeLayer.m_RNG; m_State = handshakeLayer.m_State; m_IncompleteMessage = handshakeLayer.m_IncompleteMessage; m_LocalMD5Hash = handshakeLayer.m_LocalMD5Hash; m_LocalSHA1Hash = handshakeLayer.m_LocalSHA1Hash; m_RemoteMD5Hash = handshakeLayer.m_RemoteMD5Hash; m_RemoteSHA1Hash = handshakeLayer.m_RemoteSHA1Hash; m_CertSignHash = handshakeLayer.m_CertSignHash; m_CertSignHash.Protocol = this.GetProtocol(); m_MutualAuthentication = handshakeLayer.m_MutualAuthentication; m_ClientTime = handshakeLayer.m_ClientTime; m_ClientRandom = handshakeLayer.m_ClientRandom; handshakeLayer.Dispose(false); }
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; }
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); }