TlsServerHello.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. // Transport Security Layer (TLS)
  2. // Copyright (c) 2003-2004 Carlos Guzman Alvarez
  3. // Copyright (C) 2006 Novell, Inc (http://www.novell.com)
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining
  6. // a copy of this software and associated documentation files (the
  7. // "Software"), to deal in the Software without restriction, including
  8. // without limitation the rights to use, copy, modify, merge, publish,
  9. // distribute, sublicense, and/or sell copies of the Software, and to
  10. // permit persons to whom the Software is furnished to do so, subject to
  11. // the following conditions:
  12. //
  13. // The above copyright notice and this permission notice shall be
  14. // included in all copies or substantial portions of the Software.
  15. //
  16. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  17. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  18. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  19. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  20. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  21. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  22. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23. //
  24. using System;
  25. namespace Mono.Security.Protocol.Tls.Handshake.Client
  26. {
  27. internal class TlsServerHello : HandshakeMessage
  28. {
  29. #region Fields
  30. private SecurityCompressionType compressionMethod;
  31. private byte[] random;
  32. private byte[] sessionId;
  33. private CipherSuite cipherSuite;
  34. #endregion
  35. #region Constructors
  36. public TlsServerHello(Context context, byte[] buffer)
  37. : base(context, HandshakeType.ServerHello, buffer)
  38. {
  39. }
  40. #endregion
  41. #region Methods
  42. public override void Update()
  43. {
  44. base.Update();
  45. this.Context.SessionId = this.sessionId;
  46. this.Context.ServerRandom = this.random;
  47. this.Context.Negotiating.Cipher = this.cipherSuite;
  48. this.Context.CompressionMethod = this.compressionMethod;
  49. this.Context.ProtocolNegotiated = true;
  50. DebugHelper.WriteLine("Selected Cipher Suite {0}", this.cipherSuite.Name);
  51. DebugHelper.WriteLine("Client random", this.Context.ClientRandom);
  52. DebugHelper.WriteLine("Server random", this.Context.ServerRandom);
  53. // Compute ClientRandom + ServerRandom
  54. int clen = this.Context.ClientRandom.Length;
  55. int slen = this.Context.ServerRandom.Length;
  56. int rlen = clen + slen;
  57. byte[] cs = new byte[rlen];
  58. Buffer.BlockCopy (this.Context.ClientRandom, 0, cs, 0, clen);
  59. Buffer.BlockCopy (this.Context.ServerRandom, 0, cs, clen, slen);
  60. this.Context.RandomCS = cs;
  61. // Server Random + Client Random
  62. byte[] sc = new byte[rlen];
  63. Buffer.BlockCopy (this.Context.ServerRandom, 0, sc, 0, slen);
  64. Buffer.BlockCopy (this.Context.ClientRandom, 0, sc, slen, clen);
  65. this.Context.RandomSC = sc;
  66. }
  67. #endregion
  68. #region Protected Methods
  69. protected override void ProcessAsSsl3()
  70. {
  71. this.ProcessAsTls1();
  72. }
  73. protected override void ProcessAsTls1()
  74. {
  75. // Read protocol version
  76. this.processProtocol(this.ReadInt16());
  77. // Read random - Unix time + Random bytes
  78. this.random = this.ReadBytes(32);
  79. // Read Session id
  80. int length = (int) ReadByte ();
  81. if (length > 0)
  82. {
  83. this.sessionId = this.ReadBytes(length);
  84. ClientSessionCache.Add (this.Context.ClientSettings.TargetHost, this.sessionId);
  85. this.Context.AbbreviatedHandshake = Compare (this.sessionId, this.Context.SessionId);
  86. }
  87. else
  88. {
  89. this.Context.AbbreviatedHandshake = false;
  90. }
  91. // Read cipher suite
  92. short cipherCode = this.ReadInt16();
  93. if (this.Context.SupportedCiphers.IndexOf(cipherCode) == -1)
  94. {
  95. // The server has sent an invalid ciphersuite
  96. throw new TlsException(AlertDescription.InsuficientSecurity, "Invalid cipher suite received from server");
  97. }
  98. this.cipherSuite = this.Context.SupportedCiphers[cipherCode];
  99. // Read compression methods ( always 0 )
  100. this.compressionMethod = (SecurityCompressionType)this.ReadByte();
  101. }
  102. #endregion
  103. #region Private Methods
  104. private void processProtocol(short protocol)
  105. {
  106. SecurityProtocolType serverProtocol = this.Context.DecodeProtocolCode(protocol);
  107. if ((serverProtocol & this.Context.SecurityProtocolFlags) == serverProtocol ||
  108. (this.Context.SecurityProtocolFlags & SecurityProtocolType.Default) == SecurityProtocolType.Default)
  109. {
  110. this.Context.SecurityProtocol = serverProtocol;
  111. this.Context.SupportedCiphers.Clear();
  112. this.Context.SupportedCiphers = null;
  113. this.Context.SupportedCiphers = CipherSuiteFactory.GetSupportedCiphers(serverProtocol);
  114. DebugHelper.WriteLine("Selected protocol {0}", serverProtocol);
  115. }
  116. else
  117. {
  118. throw new TlsException(
  119. AlertDescription.ProtocolVersion,
  120. "Incorrect protocol version received from server");
  121. }
  122. }
  123. #endregion
  124. }
  125. }