/// <summary>3a) Receive a DHEWithCertificate, verify the certificate and DHE and /// send a Confirm that you are ready to Verify the stack and start the /// system.</summary> /// <param name="sa">A security association that we wish to perform the /// specified control operation on.</param> /// <param name="scm">The received SecurityControlMessage.</param> /// <param name="scm_reply">A prepared reply message (with headers and such.</param> /// <param name="return_path">Where to send the result.</param> /// <param name="low_level_sender">We expect the return_path to not be an edge or /// some other type of "low level" sender, so this contains the parsed out value.</param> protected void HandleControlDHEWithCertificates(SecurityAssociation sa, SecurityControlMessage scm, SecurityControlMessage scm_reply, ISender return_path, ISender low_level_sender) { ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " Received DHEWithCertificate from: " + low_level_sender); if (sa == null) { throw new Exception("No valid SA!"); } byte[] cert = new byte[scm.Certificate.Length]; scm.Certificate.CopyTo(cert, 0); X509Certificate rcert = new X509Certificate(cert); HashAlgorithm sha1 = new SHA1CryptoServiceProvider(); scm.Verify((RSACryptoServiceProvider)rcert.RSA, sha1); _ch.Verify(rcert); sa.RemoteCertificate.Value = rcert; sa.RDHE.Value = scm.DHE; scm_reply.LocalCookie = scm.RemoteCookie; scm_reply.RemoteCookie = scm.LocalCookie; scm_reply.Hash = MemBlock.Reference(sha1.ComputeHash((byte[])scm.Packet)); scm_reply.Type = SecurityControlMessage.MessageType.Confirm; lock (_private_key_lock) { scm_reply.Sign(_private_key, sha1); } ICopyable to_send = new CopyList(Security, SecureControl, scm_reply.Packet); _rrman.SendRequest(return_path, ReqrepManager.ReqrepType.Request, to_send, this, sa); ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " Successful DHEWithCertificate from: " + low_level_sender); }
/// <summary>After a restart of the Security system, one guy may think /// we still have an association and there will be no way for him to know /// that our side is broken, unless we notify him as such. We notify him /// by sending this packet. How he deals with that is up to him.</summary> protected void NoSuchSA(int spi, ISender remote_sender) { SecurityControlMessage scm_reply = new SecurityControlMessage(); scm_reply.Version = Version; scm_reply.SPI = spi; scm_reply.Type = SecurityControlMessage.MessageType.NoSuchSA; ICopyable to_send = new CopyList(Security, SecureControl, scm_reply.Packet); remote_sender.Send(to_send); }
/// <summary>2a) Receive a CookieResponse that contains a list of CAs, if you have /// a Certificate that supports one of the CAs send it along with a DHE /// and a list of your supported CAs in a DHEWithCertificateAndCAs.</summary> /// <param name="sa">A security association that we wish to perform the /// specified control operation on.</param> /// <param name="scm">The received SecurityControlMessage.</param> /// <param name="scm_reply">A prepared reply message (with headers and such.</param> /// <param name="return_path">Where to send the result.</param> /// <param name="low_level_sender">We expect the return_path to not be an edge or /// some other type of "low level" sender, so this contains the parsed out value.</param> protected void HandleControlCookieResponse(SecurityAssociation sa, SecurityControlMessage scm, SecurityControlMessage scm_reply, ISender return_path, ISender low_level_sender) { ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " Received CookieResponse from: " + low_level_sender); if (sa == null) { throw new Exception("No valid SA!"); } // This seems like unnecessary code scm_reply.Type = SecurityControlMessage.MessageType.CookieResponse; X509Certificate lcert = null; if (SecurityPolicy.GetPolicy(scm.SPI).PreExchangedKeys) { lcert = _ch.DefaultCertificate; } else { lcert = _ch.FindCertificate(scm.CAs); } sa.RemoteCookie.Value = scm.LocalCookie; sa.LocalCertificate.Value = lcert; scm_reply.Certificate = lcert.RawData; scm_reply.DHE = sa.LDHE; scm_reply.LocalCookie = scm.RemoteCookie; scm_reply.RemoteCookie = scm.LocalCookie; scm_reply.Type = SecurityControlMessage.MessageType.DHEWithCertificateAndCAs; if (SecurityPolicy.GetPolicy(scm.SPI).PreExchangedKeys) { scm_reply.CAs = new List <MemBlock>(0); } else { scm_reply.CAs = _ch.SupportedCAs; } HashAlgorithm sha1 = new SHA1CryptoServiceProvider(); lock (_private_key_lock) { scm_reply.Sign(_private_key, sha1); } sa.DHEWithCertificateAndCAsOutHash.Value = sha1.ComputeHash((byte[])scm_reply.Packet); ICopyable to_send = new CopyList(Security, SecureControl, scm_reply.Packet); _rrman.SendRequest(return_path, ReqrepManager.ReqrepType.Request, to_send, this, sa); ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " Successful CookieResponse from: " + low_level_sender); }
/// <summary>This begins the SecurityAssociation exchange protocol over the /// specified SecurityAssociation.</summary> protected void StartSA(SecurityAssociation sa) { SecurityControlMessage scm_reply = new SecurityControlMessage(); scm_reply.Version = Version; scm_reply.SPI = sa.SPI; scm_reply.Type = SecurityControlMessage.MessageType.Cookie; scm_reply.LocalCookie = CalculateCookie(sa.Sender); ICopyable to_send = new CopyList(Security, SecureControl, scm_reply.Packet); _rrman.SendRequest(sa.Sender, ReqrepManager.ReqrepType.Request, to_send, this, sa); }
/// <summary>2b) Receive a DHEWithCertificateAndCAs, verify the certificate and attempt /// to find a matching Certificate for the list of CAs, if you find one, /// finish the DHE handshake and send the certificate via a DHEWithCertificate</summary> /// <param name="sa">A security association that we wish to perform the /// specified control operation on.</param> /// <param name="scm">The received SecurityControlMessage.</param> /// <param name="scm_reply">A prepared reply message (with headers and such.</param> /// <param name="return_path">Where to send the result.</param> /// <param name="low_level_sender">We expect the return_path to not be an edge or /// some other type of "low level" sender, so this contains the parsed out value.</param> protected void HandleControlDHEWithCertificateAndCAs(SecurityAssociation sa, SecurityControlMessage scm, SecurityControlMessage scm_reply, ISender return_path, ISender low_level_sender) { ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " Received DHEWithCertificateAndCAs from: " + low_level_sender); if (sa == null) { sa = CreateSecurityAssociation(low_level_sender, scm.SPI, false); } byte[] cert = new byte[scm.Certificate.Length]; scm.Certificate.CopyTo(cert, 0); X509Certificate rcert = new X509Certificate(cert); _ch.Verify(rcert); HashAlgorithm sha1 = new SHA1CryptoServiceProvider(); scm.Verify((RSACryptoServiceProvider)rcert.RSA, sha1); X509Certificate lcert = null; if (SecurityPolicy.GetPolicy(scm.SPI).PreExchangedKeys) { lcert = _ch.DefaultCertificate; } else { lcert = _ch.FindCertificate(scm.CAs); } sa.LocalCertificate.Value = lcert; sa.RemoteCertificate.Value = rcert; sa.RDHE.Value = scm.DHE; sa.DHEWithCertificateAndCAsInHash.Value = MemBlock.Reference(sha1.ComputeHash((byte[])scm.Packet)); scm_reply.LocalCookie = scm.RemoteCookie; scm_reply.RemoteCookie = scm.LocalCookie; scm_reply.DHE = sa.LDHE; scm_reply.Certificate = MemBlock.Reference(lcert.RawData); scm_reply.Type = SecurityControlMessage.MessageType.DHEWithCertificate; lock (_private_key_lock) { scm_reply.Sign(_private_key, sha1); } sa.DHEWithCertificateHash.Value = MemBlock.Reference(sha1.ComputeHash((byte[])scm_reply.Packet)); ICopyable to_send = new CopyList(SecureControl, scm_reply.Packet); return_path.Send(to_send); ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " Successful DHEWithCertificateAndCAs from: " + low_level_sender); }
/// <summary>3b) Receive a Confirm, verify the entire stack and send a Confirm /// 4a)Receive a Confirm, verify the entire stack and all set to go</summary> /// <param name="sa">A security association that we wish to perform the /// specified control operation on.</param> /// <param name="scm">The received SecurityControlMessage.</param> /// <param name="scm_reply">A prepared reply message (with headers and such.</param> /// <param name="return_path">Where to send the result.</param> /// <param name="low_level_sender">We expect the return_path to not be an edge or /// some other type of "low level" sender, so this contains the parsed out value.</param> protected void HandleControlConfirm(SecurityAssociation sa, SecurityControlMessage scm, SecurityControlMessage scm_reply, ISender return_path, ISender low_level_sender) { ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " Received Confirm from: " + low_level_sender); if (sa == null) { throw new Exception("No valid SA!"); } HashAlgorithm sha1 = new SHA1CryptoServiceProvider(); scm.Verify((RSACryptoServiceProvider)sa.RemoteCertificate.Value.RSA, sha1); if (return_path == low_level_sender) { sa.VerifyResponse(scm.Hash); } else { sa.VerifyRequest(scm.Hash); scm_reply.LocalCookie = scm.RemoteCookie; scm_reply.RemoteCookie = scm.LocalCookie; scm_reply.Hash = sa.DHEWithCertificateAndCAsInHash.Value; scm_reply.Type = SecurityControlMessage.MessageType.Confirm; lock (_private_key_lock) { scm_reply.Sign(_private_key, sha1); } ICopyable to_send = new CopyList(SecureControl, scm_reply.Packet); return_path.Send(to_send); } if (Verify(sa)) { sa.Enable(); } else { sa.Close("Unable to verify the SA as being valid!"); } ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " Successful Confirm from: " + low_level_sender); }
/// <summary>1b) Receive a Cookie which responds with a CookieResponse</summary> /// <param name="sa">A security association that we wish to perform the /// specified control operation on.</param> /// <param name="calc_cookie">Cookie value for the association sender.</param> /// <param name="scm">The received SecurityControlMessage.</param> /// <param name="scm_reply">A prepared reply message (with headers and such.</param> /// <param name="return_path">Where to send the result.</param> /// <param name="low_level_sender">We expect the return_path to not be an edge or /// some other type of "low level" sender, so this contains the parsed out value.</param> protected void HandleControlCookie(SecurityAssociation sa, MemBlock calc_cookie, SecurityControlMessage scm, SecurityControlMessage scm_reply, ISender return_path, ISender low_level_sender) { ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " Received Cookie from: " + low_level_sender); scm_reply.Type = SecurityControlMessage.MessageType.CookieResponse; scm_reply.RemoteCookie = scm.LocalCookie; scm_reply.LocalCookie = calc_cookie; if (SecurityPolicy.GetPolicy(scm.SPI).PreExchangedKeys) { scm_reply.CAs = new List <MemBlock>(0); } else { scm_reply.CAs = _ch.SupportedCAs; } ICopyable to_send = new CopyList(SecureControl, scm_reply.Packet); return_path.Send(to_send); ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " Successful Cookie from: " + low_level_sender); }
/// <summary>This is the control state machine. There are three paths in /// the state machine, iniator, receiver, and bidirectional. The /// bidirectional case occurs when two remote ISenders that are matched /// together initiate a handshake at the same time, otherwise the initiator /// /receiver pattern is followed. The high level overview for the states /// are: /// 1a) Send a Cookie /// 1b) Receive a Cookie which responds with a CookieResponse /// 2a) Receive a CookieResponse that contains a list of CAs, if you have /// a Certificate that supports one of the CAs send it along with a DHE /// and a list of your supported CAs in a DHEWithCertificateAndCAs. /// 2b) Receive a DHEWithCertificateAndCAs, verify the certificate and attempt /// to find a matching Certificate for the list of CAs, if you find one, /// finish the DHE handshake and send the certificate via a DHEWithCertificate /// 3a) Receive a DHEWithCertificate, verify the certificate and DHE and /// send a Confirm that you are ready to Verify the stack and start the /// system. /// 3b) Receive a Confirm, verify the entire stack and send a Confirm /// 4a)Receive a Confirm, verify the entire stack and all set to go /// </summary> protected void HandleControl(MemBlock b, ISender return_path) { ISender low_level_sender = return_path; if (low_level_sender is ReqrepManager.ReplyState) { low_level_sender = ((ReqrepManager.ReplyState)low_level_sender).ReturnPath; } SecurityControlMessage scm = new SecurityControlMessage(b); MemBlock calc_cookie = CalculateCookie(low_level_sender); if (scm.Version != Version) { throw new Exception("Invalid version: " + scm.Version); } else if (!SecurityPolicy.Supports(scm.SPI)) { throw new Exception("No support for SPI: " + scm.SPI); } else if (!scm.RemoteCookie.Equals(calc_cookie)) { if (scm.Type != SecurityControlMessage.MessageType.Cookie && scm.Type != SecurityControlMessage.MessageType.NoSuchSA) { throw new Exception("Invalid cookie!"); } } SecurityControlMessage scm_reply = new SecurityControlMessage(); scm_reply.Version = Version; scm_reply.SPI = scm.SPI; SecurityAssociation sa = null; // This can be in a try statement since this is best effort anyway try { Dictionary <ISender, SecurityAssociation> sender_to_sa = _spi[scm.SPI]; sa = sender_to_sa[low_level_sender]; } catch { } if (sa != null) { sa.Reset(); if (sa.Closed) { throw new Exception("SA closed!"); } else if (sa.State == SecurityAssociation.SAState.Active) { return; } } try { switch (scm.Type) { case SecurityControlMessage.MessageType.NoSuchSA: HandleControlNoSuchSA(sa); break; case SecurityControlMessage.MessageType.Cookie: HandleControlCookie(sa, calc_cookie, scm, scm_reply, return_path, low_level_sender); break; case SecurityControlMessage.MessageType.CookieResponse: HandleControlCookieResponse(sa, scm, scm_reply, return_path, low_level_sender); break; case SecurityControlMessage.MessageType.DHEWithCertificateAndCAs: HandleControlDHEWithCertificateAndCAs(sa, scm, scm_reply, return_path, low_level_sender); break; case SecurityControlMessage.MessageType.DHEWithCertificate: HandleControlDHEWithCertificates(sa, scm, scm_reply, return_path, low_level_sender); break; case SecurityControlMessage.MessageType.Confirm: HandleControlConfirm(sa, scm, scm_reply, return_path, low_level_sender); break; default: throw new Exception("Invalid message!"); } } catch { if (sa != null && sa.Closed) { throw new Exception("SA closed."); } else { throw; } } }
/// <summary>3b) Receive a Confirm, verify the entire stack and send a Confirm /// 4a)Receive a Confirm, verify the entire stack and all set to go</summary> /// <param name="sa">A security association that we wish to perform the /// specified control operation on.</param> /// <param name="scm">The received SecurityControlMessage.</param> /// <param name="scm_reply">A prepared reply message (with headers and such.</param> /// <param name="return_path">Where to send the result.</param> /// <param name="low_level_sender">We expect the return_path to not be an edge or /// some other type of "low level" sender, so this contains the parsed out value.</param> protected void HandleControlConfirm(SecurityAssociation sa, SecurityControlMessage scm, SecurityControlMessage scm_reply, ISender return_path, ISender low_level_sender) { ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " Received Confirm from: " + low_level_sender); if(sa == null) { throw new Exception("No valid SA!"); } HashAlgorithm sha1 = new SHA1CryptoServiceProvider(); scm.Verify((RSACryptoServiceProvider) sa.RemoteCertificate.Value.RSA, sha1); if(return_path == low_level_sender) { sa.VerifyResponse(scm.Hash); } else { sa.VerifyRequest(scm.Hash); scm_reply.LocalCookie = scm.RemoteCookie; scm_reply.RemoteCookie = scm.LocalCookie; scm_reply.Hash = sa.DHEWithCertificateAndCAsInHash.Value; scm_reply.Type = SecurityControlMessage.MessageType.Confirm; lock(_private_key_lock) { scm_reply.Sign(_private_key, sha1); } ICopyable to_send = new CopyList(SecureControl, scm_reply.Packet); return_path.Send(to_send); } if(Verify(sa)) { sa.Enable(); } else { sa.Close("Unable to verify the SA as being valid!"); } ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " Successful Confirm from: " + low_level_sender); }
/// <summary>3a) Receive a DHEWithCertificate, verify the certificate and DHE and /// send a Confirm that you are ready to Verify the stack and start the /// system.</summary> /// <param name="sa">A security association that we wish to perform the /// specified control operation on.</param> /// <param name="scm">The received SecurityControlMessage.</param> /// <param name="scm_reply">A prepared reply message (with headers and such.</param> /// <param name="return_path">Where to send the result.</param> /// <param name="low_level_sender">We expect the return_path to not be an edge or /// some other type of "low level" sender, so this contains the parsed out value.</param> protected void HandleControlDHEWithCertificates(SecurityAssociation sa, SecurityControlMessage scm, SecurityControlMessage scm_reply, ISender return_path, ISender low_level_sender) { ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " Received DHEWithCertificate from: " + low_level_sender); if(sa == null) { throw new Exception("No valid SA!"); } byte[] cert = new byte[scm.Certificate.Length]; scm.Certificate.CopyTo(cert, 0); X509Certificate rcert = new X509Certificate(cert); HashAlgorithm sha1 = new SHA1CryptoServiceProvider(); scm.Verify((RSACryptoServiceProvider) rcert.RSA, sha1); _ch.Verify(rcert); sa.RemoteCertificate.Value = rcert; sa.RDHE.Value = scm.DHE; scm_reply.LocalCookie = scm.RemoteCookie; scm_reply.RemoteCookie = scm.LocalCookie; scm_reply.Hash = MemBlock.Reference(sha1.ComputeHash((byte[]) scm.Packet)); scm_reply.Type = SecurityControlMessage.MessageType.Confirm; lock(_private_key_lock) { scm_reply.Sign(_private_key, sha1); } ICopyable to_send = new CopyList(Security, SecureControl, scm_reply.Packet); _rrman.SendRequest(return_path, ReqrepManager.ReqrepType.Request, to_send, this, sa); ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " Successful DHEWithCertificate from: " + low_level_sender); }
/// <summary>2b) Receive a DHEWithCertificateAndCAs, verify the certificate and attempt /// to find a matching Certificate for the list of CAs, if you find one, /// finish the DHE handshake and send the certificate via a DHEWithCertificate</summary> /// <param name="sa">A security association that we wish to perform the /// specified control operation on.</param> /// <param name="scm">The received SecurityControlMessage.</param> /// <param name="scm_reply">A prepared reply message (with headers and such.</param> /// <param name="return_path">Where to send the result.</param> /// <param name="low_level_sender">We expect the return_path to not be an edge or /// some other type of "low level" sender, so this contains the parsed out value.</param> protected void HandleControlDHEWithCertificateAndCAs(SecurityAssociation sa, SecurityControlMessage scm, SecurityControlMessage scm_reply, ISender return_path, ISender low_level_sender) { ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " Received DHEWithCertificateAndCAs from: " + low_level_sender); if(sa == null) { sa = CreateSecurityAssociation(low_level_sender, scm.SPI, false); } byte[] cert = new byte[scm.Certificate.Length]; scm.Certificate.CopyTo(cert, 0); X509Certificate rcert = new X509Certificate(cert); _ch.Verify(rcert); HashAlgorithm sha1 = new SHA1CryptoServiceProvider(); scm.Verify((RSACryptoServiceProvider) rcert.RSA, sha1); X509Certificate lcert = null; if(SecurityPolicy.GetPolicy(scm.SPI).PreExchangedKeys) { lcert = _ch.DefaultCertificate; } else { lcert = _ch.FindCertificate(scm.CAs); } sa.LocalCertificate.Value = lcert; sa.RemoteCertificate.Value = rcert; sa.RDHE.Value = scm.DHE; sa.DHEWithCertificateAndCAsInHash.Value = MemBlock.Reference(sha1.ComputeHash((byte[]) scm.Packet)); scm_reply.LocalCookie = scm.RemoteCookie; scm_reply.RemoteCookie = scm.LocalCookie; scm_reply.DHE = sa.LDHE; scm_reply.Certificate = MemBlock.Reference(lcert.RawData); scm_reply.Type = SecurityControlMessage.MessageType.DHEWithCertificate; lock(_private_key_lock) { scm_reply.Sign(_private_key, sha1); } sa.DHEWithCertificateHash.Value = MemBlock.Reference(sha1.ComputeHash((byte[]) scm_reply.Packet)); ICopyable to_send = new CopyList(SecureControl, scm_reply.Packet); return_path.Send(to_send); ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " Successful DHEWithCertificateAndCAs from: " + low_level_sender); }
/// <summary>2a) Receive a CookieResponse that contains a list of CAs, if you have /// a Certificate that supports one of the CAs send it along with a DHE /// and a list of your supported CAs in a DHEWithCertificateAndCAs.</summary> /// <param name="sa">A security association that we wish to perform the /// specified control operation on.</param> /// <param name="scm">The received SecurityControlMessage.</param> /// <param name="scm_reply">A prepared reply message (with headers and such.</param> /// <param name="return_path">Where to send the result.</param> /// <param name="low_level_sender">We expect the return_path to not be an edge or /// some other type of "low level" sender, so this contains the parsed out value.</param> protected void HandleControlCookieResponse(SecurityAssociation sa, SecurityControlMessage scm, SecurityControlMessage scm_reply, ISender return_path, ISender low_level_sender) { ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " Received CookieResponse from: " + low_level_sender); if(sa == null) { throw new Exception("No valid SA!"); } // This seems like unnecessary code scm_reply.Type = SecurityControlMessage.MessageType.CookieResponse; X509Certificate lcert = null; if(SecurityPolicy.GetPolicy(scm.SPI).PreExchangedKeys) { lcert = _ch.DefaultCertificate; } else { lcert = _ch.FindCertificate(scm.CAs); } sa.RemoteCookie.Value = scm.LocalCookie; sa.LocalCertificate.Value = lcert; scm_reply.Certificate = lcert.RawData; scm_reply.DHE = sa.LDHE; scm_reply.LocalCookie = scm.RemoteCookie; scm_reply.RemoteCookie = scm.LocalCookie; scm_reply.Type = SecurityControlMessage.MessageType.DHEWithCertificateAndCAs; if(SecurityPolicy.GetPolicy(scm.SPI).PreExchangedKeys) { scm_reply.CAs = new List<MemBlock>(0); } else { scm_reply.CAs = _ch.SupportedCAs; } HashAlgorithm sha1 = new SHA1CryptoServiceProvider(); lock(_private_key_lock) { scm_reply.Sign(_private_key, sha1); } sa.DHEWithCertificateAndCAsOutHash.Value = sha1.ComputeHash((byte[]) scm_reply.Packet); ICopyable to_send = new CopyList(Security, SecureControl, scm_reply.Packet); _rrman.SendRequest(return_path, ReqrepManager.ReqrepType.Request, to_send, this, sa); ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " Successful CookieResponse from: " + low_level_sender); }
/// <summary>1b) Receive a Cookie which responds with a CookieResponse</summary> /// <param name="sa">A security association that we wish to perform the /// specified control operation on.</param> /// <param name="calc_cookie">Cookie value for the association sender.</param> /// <param name="scm">The received SecurityControlMessage.</param> /// <param name="scm_reply">A prepared reply message (with headers and such.</param> /// <param name="return_path">Where to send the result.</param> /// <param name="low_level_sender">We expect the return_path to not be an edge or /// some other type of "low level" sender, so this contains the parsed out value.</param> protected void HandleControlCookie(SecurityAssociation sa, MemBlock calc_cookie, SecurityControlMessage scm, SecurityControlMessage scm_reply, ISender return_path, ISender low_level_sender) { ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " Received Cookie from: " + low_level_sender); scm_reply.Type = SecurityControlMessage.MessageType.CookieResponse; scm_reply.RemoteCookie = scm.LocalCookie; scm_reply.LocalCookie = calc_cookie; if(SecurityPolicy.GetPolicy(scm.SPI).PreExchangedKeys) { scm_reply.CAs = new List<MemBlock>(0); } else { scm_reply.CAs = _ch.SupportedCAs; } ICopyable to_send = new CopyList(SecureControl, scm_reply.Packet); return_path.Send(to_send); ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " Successful Cookie from: " + low_level_sender); }
/// <summary>This is the control state machine. There are three paths in /// the state machine, iniator, receiver, and bidirectional. The /// bidirectional case occurs when two remote ISenders that are matched /// together initiate a handshake at the same time, otherwise the initiator /// /receiver pattern is followed. The high level overview for the states /// are: /// 1a) Send a Cookie /// 1b) Receive a Cookie which responds with a CookieResponse /// 2a) Receive a CookieResponse that contains a list of CAs, if you have /// a Certificate that supports one of the CAs send it along with a DHE /// and a list of your supported CAs in a DHEWithCertificateAndCAs. /// 2b) Receive a DHEWithCertificateAndCAs, verify the certificate and attempt /// to find a matching Certificate for the list of CAs, if you find one, /// finish the DHE handshake and send the certificate via a DHEWithCertificate /// 3a) Receive a DHEWithCertificate, verify the certificate and DHE and /// send a Confirm that you are ready to Verify the stack and start the /// system. /// 3b) Receive a Confirm, verify the entire stack and send a Confirm /// 4a)Receive a Confirm, verify the entire stack and all set to go /// </summary> protected void HandleControl(MemBlock b, ISender return_path) { ISender low_level_sender = return_path; if(low_level_sender is ReqrepManager.ReplyState) { low_level_sender = ((ReqrepManager.ReplyState) low_level_sender).ReturnPath; } SecurityControlMessage scm = new SecurityControlMessage(b); MemBlock calc_cookie = CalculateCookie(low_level_sender); if(scm.Version != Version) { throw new Exception("Invalid version: " + scm.Version); } else if(!SecurityPolicy.Supports(scm.SPI)) { throw new Exception("No support for SPI: " + scm.SPI); } else if(!scm.RemoteCookie.Equals(calc_cookie)) { if(scm.Type != SecurityControlMessage.MessageType.Cookie && scm.Type != SecurityControlMessage.MessageType.NoSuchSA) { throw new Exception("Invalid cookie!"); } } SecurityControlMessage scm_reply = new SecurityControlMessage(); scm_reply.Version = Version; scm_reply.SPI = scm.SPI; SecurityAssociation sa = null; // This can be in a try statement since this is best effort anyway try { Dictionary<ISender, SecurityAssociation> sender_to_sa = _spi[scm.SPI]; sa = sender_to_sa[low_level_sender]; } catch { } if(sa != null) { sa.Reset(); if(sa.Closed) { throw new Exception("SA closed!"); } else if(sa.State == SecurityAssociation.SAState.Active) { return; } } try { switch(scm.Type) { case SecurityControlMessage.MessageType.NoSuchSA: HandleControlNoSuchSA(sa); break; case SecurityControlMessage.MessageType.Cookie: HandleControlCookie(sa, calc_cookie, scm, scm_reply, return_path, low_level_sender); break; case SecurityControlMessage.MessageType.CookieResponse: HandleControlCookieResponse(sa, scm, scm_reply, return_path, low_level_sender); break; case SecurityControlMessage.MessageType.DHEWithCertificateAndCAs: HandleControlDHEWithCertificateAndCAs(sa, scm, scm_reply, return_path, low_level_sender); break; case SecurityControlMessage.MessageType.DHEWithCertificate: HandleControlDHEWithCertificates(sa, scm, scm_reply, return_path, low_level_sender); break; case SecurityControlMessage.MessageType.Confirm: HandleControlConfirm(sa, scm, scm_reply, return_path, low_level_sender); break; default: throw new Exception("Invalid message!"); } } catch { if(sa != null && sa.Closed) { throw new Exception("SA closed."); } else { throw; } } }
public void Incoming() { Random rand = new Random(); byte[] local_cookie = new byte[SecurityControlMessage.CookieLength]; byte[] remote_cookie = new byte[SecurityControlMessage.CookieLength]; byte[] dhe = new byte[144]; byte[] cas = new byte[120]; byte[] cert = new byte[100]; RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); HashAlgorithm hash = new SHA1CryptoServiceProvider(); rand.NextBytes(local_cookie); rand.NextBytes(remote_cookie); rand.NextBytes(dhe); rand.NextBytes(cas); rand.NextBytes(cert); MemBlock mlocal_cookie = MemBlock.Reference(local_cookie); MemBlock mremote_cookie = MemBlock.Reference(remote_cookie); MemBlock mdhe = MemBlock.Reference(dhe); MemBlock mcert = MemBlock.Reference(cert); MemBlock mcas = MemBlock.Reference(cas); List<MemBlock> lcas = new List<MemBlock>(); for(int i = 0; i < cas.Length; i+= SecurityControlMessage.CALength) { lcas.Add(MemBlock.Reference(mcas.Slice(i, SecurityControlMessage.CALength))); } int length = 4 + 4 + 4 + 2 * SecurityControlMessage.CookieLength + 4 + cas.Length + 4 + dhe.Length + 4 + cert.Length; byte[] b = new byte[length]; int pos = 0; NumberSerializer.WriteInt(5, b, pos); pos += 4; NumberSerializer.WriteInt(12345, b, pos); pos += 4; NumberSerializer.WriteInt((int) SecurityControlMessage.MessageType.DHEWithCertificateAndCAs, b, pos); pos += 4; local_cookie.CopyTo(b, pos); pos += SecurityControlMessage.CookieLength; remote_cookie.CopyTo(b, pos); pos += SecurityControlMessage.CookieLength; NumberSerializer.WriteInt(dhe.Length, b, pos); pos += 4; dhe.CopyTo(b, pos); pos += dhe.Length; NumberSerializer.WriteInt(cert.Length, b, pos); pos += 4; cert.CopyTo(b, pos); pos += cert.Length; NumberSerializer.WriteInt(cas.Length, b, pos); pos += 4; mcas.CopyTo(b, pos); pos += cas.Length; byte[] signature = rsa.SignData(b, hash); byte[] nb = new byte[b.Length + signature.Length]; b.CopyTo(nb, 0); signature.CopyTo(nb, b.Length); MemBlock packet = MemBlock.Reference(nb); // check SecurityControlMessage scm = new SecurityControlMessage(packet); Assert.AreEqual(5, scm.Version, "Version"); Assert.AreEqual(12345, scm.SPI, "SPI"); Assert.AreEqual(SecurityControlMessage.MessageType.DHEWithCertificateAndCAs, scm.Type, "Type"); Assert.AreEqual(mlocal_cookie, scm.LocalCookie, "LocalCookie"); Assert.AreEqual(mremote_cookie, scm.RemoteCookie, "RemoteCookie"); Assert.AreEqual(mdhe, scm.DHE, "DHE"); Assert.AreEqual(mcert, scm.Certificate, "Certificate"); int contains = 0; foreach(MemBlock ca in scm.CAs) { if(scm.CAs.Contains(ca)) { contains++; } } Assert.AreEqual(contains, lcas.Count, "Contains CAs"); Assert.IsTrue(scm.Verify(rsa, hash), "Signature"); Assert.AreEqual(packet, scm.Packet, "Packet"); // change a few things around and check again! scm.Version = 0; SecurityControlMessage scm1 = new SecurityControlMessage(scm.Packet); scm1.Sign(rsa, hash); Assert.AreEqual(scm1.Version, scm.Version, "Version 1"); Assert.AreEqual(scm1.SPI, scm.SPI, "SPI 1"); Assert.AreEqual(scm1.Type, scm.Type, "Type 1"); Assert.AreEqual(scm1.LocalCookie, scm.LocalCookie, "LocalCookie 1"); Assert.AreEqual(scm1.RemoteCookie, scm.RemoteCookie, "RemoteCookie 1"); Assert.AreEqual(mdhe, scm.DHE, "DHE 1"); Assert.AreEqual(mcert, scm.Certificate, "Certificate 1"); contains = 0; foreach(MemBlock ca in scm.CAs) { if(scm.CAs.Contains(ca)) { contains++; } } Assert.AreEqual(contains, lcas.Count, "Contains CAs 1"); Assert.IsTrue(scm1.Signature != scm.Signature, "Signature 1"); Assert.AreEqual(scm1.Packet.Slice(4, scm1.Signature.Length), scm.Packet.Slice(4, scm.Signature.Length), "Packet 1"); }
public void Incoming() { Random rand = new Random(); byte[] local_cookie = new byte[SecurityControlMessage.CookieLength]; byte[] remote_cookie = new byte[SecurityControlMessage.CookieLength]; byte[] dhe = new byte[144]; byte[] cas = new byte[120]; byte[] cert = new byte[100]; RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); HashAlgorithm hash = new SHA1CryptoServiceProvider(); rand.NextBytes(local_cookie); rand.NextBytes(remote_cookie); rand.NextBytes(dhe); rand.NextBytes(cas); rand.NextBytes(cert); MemBlock mlocal_cookie = MemBlock.Reference(local_cookie); MemBlock mremote_cookie = MemBlock.Reference(remote_cookie); MemBlock mdhe = MemBlock.Reference(dhe); MemBlock mcert = MemBlock.Reference(cert); MemBlock mcas = MemBlock.Reference(cas); List <MemBlock> lcas = new List <MemBlock>(); for (int i = 0; i < cas.Length; i += SecurityControlMessage.CALength) { lcas.Add(MemBlock.Reference(mcas.Slice(i, SecurityControlMessage.CALength))); } int length = 4 + 4 + 4 + 2 * SecurityControlMessage.CookieLength + 4 + cas.Length + 4 + dhe.Length + 4 + cert.Length; byte[] b = new byte[length]; int pos = 0; NumberSerializer.WriteInt(5, b, pos); pos += 4; NumberSerializer.WriteInt(12345, b, pos); pos += 4; NumberSerializer.WriteInt((int)SecurityControlMessage.MessageType.DHEWithCertificateAndCAs, b, pos); pos += 4; local_cookie.CopyTo(b, pos); pos += SecurityControlMessage.CookieLength; remote_cookie.CopyTo(b, pos); pos += SecurityControlMessage.CookieLength; NumberSerializer.WriteInt(dhe.Length, b, pos); pos += 4; dhe.CopyTo(b, pos); pos += dhe.Length; NumberSerializer.WriteInt(cert.Length, b, pos); pos += 4; cert.CopyTo(b, pos); pos += cert.Length; NumberSerializer.WriteInt(cas.Length, b, pos); pos += 4; mcas.CopyTo(b, pos); pos += cas.Length; byte[] signature = rsa.SignData(b, hash); byte[] nb = new byte[b.Length + signature.Length]; b.CopyTo(nb, 0); signature.CopyTo(nb, b.Length); MemBlock packet = MemBlock.Reference(nb); // check SecurityControlMessage scm = new SecurityControlMessage(packet); Assert.AreEqual(5, scm.Version, "Version"); Assert.AreEqual(12345, scm.SPI, "SPI"); Assert.AreEqual(SecurityControlMessage.MessageType.DHEWithCertificateAndCAs, scm.Type, "Type"); Assert.AreEqual(mlocal_cookie, scm.LocalCookie, "LocalCookie"); Assert.AreEqual(mremote_cookie, scm.RemoteCookie, "RemoteCookie"); Assert.AreEqual(mdhe, scm.DHE, "DHE"); Assert.AreEqual(mcert, scm.Certificate, "Certificate"); int contains = 0; foreach (MemBlock ca in scm.CAs) { if (scm.CAs.Contains(ca)) { contains++; } } Assert.AreEqual(contains, lcas.Count, "Contains CAs"); Assert.IsTrue(scm.Verify(rsa, hash), "Signature"); Assert.AreEqual(packet, scm.Packet, "Packet"); // change a few things around and check again! scm.Version = 0; SecurityControlMessage scm1 = new SecurityControlMessage(scm.Packet); scm1.Sign(rsa, hash); Assert.AreEqual(scm1.Version, scm.Version, "Version 1"); Assert.AreEqual(scm1.SPI, scm.SPI, "SPI 1"); Assert.AreEqual(scm1.Type, scm.Type, "Type 1"); Assert.AreEqual(scm1.LocalCookie, scm.LocalCookie, "LocalCookie 1"); Assert.AreEqual(scm1.RemoteCookie, scm.RemoteCookie, "RemoteCookie 1"); Assert.AreEqual(mdhe, scm.DHE, "DHE 1"); Assert.AreEqual(mcert, scm.Certificate, "Certificate 1"); contains = 0; foreach (MemBlock ca in scm.CAs) { if (scm.CAs.Contains(ca)) { contains++; } } Assert.AreEqual(contains, lcas.Count, "Contains CAs 1"); Assert.IsTrue(scm1.Signature != scm.Signature, "Signature 1"); Assert.AreEqual(scm1.Packet.Slice(4, scm1.Signature.Length), scm.Packet.Slice(4, scm.Signature.Length), "Packet 1"); }