1 // Transport Security Layer (TLS)
2 // Copyright (c) 2003-2004 Carlos Guzman Alvarez
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:
13 // The above copyright notice and this permission notice shall be
14 // included in all copies or substantial portions of the Software.
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.
28 using System.Security.Cryptography;
29 using System.Security.Cryptography.X509Certificates;
32 using Mono.Security.Cryptography;
34 namespace Mono.Security.Protocol.Tls
36 internal class TlsCipherSuite : CipherSuite
40 public TlsCipherSuite(
41 short code, string name, CipherAlgorithmType cipherAlgorithmType,
42 HashAlgorithmType hashAlgorithmType, ExchangeAlgorithmType exchangeAlgorithmType,
43 bool exportable, bool blockMode, byte keyMaterialSize,
44 byte expandedKeyMaterialSize, short effectiveKeyBytes,
45 byte ivSize, byte blockSize)
46 :base(code, name, cipherAlgorithmType, hashAlgorithmType,
47 exchangeAlgorithmType, exportable, blockMode, keyMaterialSize,
48 expandedKeyMaterialSize, effectiveKeyBytes, ivSize, blockSize)
54 #region MAC Generation Methods
56 public override byte[] ComputeServerRecordMAC(ContentType contentType, byte[] fragment)
58 TlsStream data = new TlsStream();
61 if (this.Context is ClientContext)
63 data.Write(this.Context.ReadSequenceNumber);
67 data.Write(this.Context.WriteSequenceNumber);
70 data.Write((byte)contentType);
71 data.Write(this.Context.Protocol);
72 data.Write((short)fragment.Length);
75 result = this.ServerHMAC.ComputeHash(data.ToArray());
82 public override byte[] ComputeClientRecordMAC(ContentType contentType, byte[] fragment)
84 TlsStream data = new TlsStream();
87 if (this.Context is ClientContext)
89 data.Write(this.Context.WriteSequenceNumber);
93 data.Write(this.Context.ReadSequenceNumber);
96 data.Write((byte)contentType);
97 data.Write(this.Context.Protocol);
98 data.Write((short)fragment.Length);
101 result = this.ClientHMAC.ComputeHash(data.ToArray());
110 #region Key Generation Methods
112 public override void ComputeMasterSecret(byte[] preMasterSecret)
114 // Create master secret
115 this.Context.MasterSecret = new byte[preMasterSecret.Length];
116 this.Context.MasterSecret = this.PRF(
117 preMasterSecret, "master secret", this.Context.RandomCS, 48);
119 DebugHelper.WriteLine(">>>> MasterSecret", this.Context.MasterSecret);
122 public override void ComputeKeys()
125 TlsStream keyBlock = new TlsStream(
127 this.Context.MasterSecret,
129 this.Context.RandomSC,
132 this.Context.ClientWriteMAC = keyBlock.ReadBytes(this.HashSize);
133 this.Context.ServerWriteMAC = keyBlock.ReadBytes(this.HashSize);
134 this.Context.ClientWriteKey = keyBlock.ReadBytes(this.KeyMaterialSize);
135 this.Context.ServerWriteKey = keyBlock.ReadBytes(this.KeyMaterialSize);
137 if (!this.IsExportable)
139 if (this.IvSize != 0)
141 this.Context.ClientWriteIV = keyBlock.ReadBytes(this.IvSize);
142 this.Context.ServerWriteIV = keyBlock.ReadBytes(this.IvSize);
146 this.Context.ClientWriteIV = CipherSuite.EmptyArray;
147 this.Context.ServerWriteIV = CipherSuite.EmptyArray;
152 // Generate final write keys
153 byte[] finalClientWriteKey = PRF(this.Context.ClientWriteKey, "client write key", this.Context.RandomCS, this.ExpandedKeyMaterialSize);
154 byte[] finalServerWriteKey = PRF(this.Context.ServerWriteKey, "server write key", this.Context.RandomCS, this.ExpandedKeyMaterialSize);
156 this.Context.ClientWriteKey = finalClientWriteKey;
157 this.Context.ServerWriteKey = finalServerWriteKey;
162 byte[] ivBlock = PRF(CipherSuite.EmptyArray, "IV block", this.Context.RandomCS, this.IvSize*2);
165 this.Context.ClientWriteIV = new byte[this.IvSize];
166 Buffer.BlockCopy(ivBlock, 0, this.Context.ClientWriteIV, 0, this.Context.ClientWriteIV.Length);
168 this.Context.ServerWriteIV = new byte[this.IvSize];
169 Buffer.BlockCopy(ivBlock, this.IvSize, this.Context.ServerWriteIV, 0, this.Context.ServerWriteIV.Length);
173 this.Context.ClientWriteIV = CipherSuite.EmptyArray;
174 this.Context.ServerWriteIV = CipherSuite.EmptyArray;
178 DebugHelper.WriteLine(">>>> KeyBlock", keyBlock.ToArray());
179 DebugHelper.WriteLine(">>>> ClientWriteKey", this.Context.ClientWriteKey);
180 DebugHelper.WriteLine(">>>> ClientWriteIV", this.Context.ClientWriteIV);
181 DebugHelper.WriteLine(">>>> ClientWriteMAC", this.Context.ClientWriteMAC);
182 DebugHelper.WriteLine(">>>> ServerWriteKey", this.Context.ServerWriteKey);
183 DebugHelper.WriteLine(">>>> ServerWriteIV", this.Context.ServerWriteIV);
184 DebugHelper.WriteLine(">>>> ServerWriteMAC", this.Context.ServerWriteMAC);
186 // Clear no more needed data