/* Transport Security Layer (TLS)
- * Copyright (c) 2003 Carlos Guzmán Álvarez
+ * Copyright (c) 2003-2004 Carlos Guzman Alvarez
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
namespace Mono.Security.Protocol.Tls
{
- internal class TlsCipherSuite : TlsAbstractCipherSuite
+ internal class TlsCipherSuite : CipherSuite
{
- #region CONSTRUCTORS
+ #region Constructors
- public TlsCipherSuite(short code, string name, string algName,
- string hashName, bool exportable, bool blockMode,
- byte keyMaterialSize, byte expandedKeyMaterialSize,
- short effectiveKeyBytes, byte ivSize, byte blockSize)
- : base (code, name, algName, hashName, exportable, blockMode,
- keyMaterialSize, expandedKeyMaterialSize, effectiveKeyBytes,
- ivSize, blockSize)
+ public TlsCipherSuite(
+ short code, string name, CipherAlgorithmType cipherAlgorithmType,
+ HashAlgorithmType hashAlgorithmType, ExchangeAlgorithmType exchangeAlgorithmType,
+ bool exportable, bool blockMode, byte keyMaterialSize,
+ byte expandedKeyMaterialSize, short effectiveKeyBytes,
+ byte ivSize, byte blockSize) :
+ base(code, name, cipherAlgorithmType, hashAlgorithmType,
+ exchangeAlgorithmType, exportable, blockMode, keyMaterialSize,
+ expandedKeyMaterialSize, effectiveKeyBytes, ivSize, blockSize)
{
}
#endregion
- #region METHODS
+ #region MAC Generation Methods
- public override byte[] EncryptRecord(byte[] fragment, byte[] mac)
+ public override byte[] ComputeServerRecordMAC(TlsContentType contentType, byte[] fragment)
{
- // Encryption ( fragment + mac [+ padding + padding_length] )
- MemoryStream ms = new MemoryStream();
- CryptoStream cs = new CryptoStream(ms, encryptionCipher, CryptoStreamMode.Write);
+ TlsStream data = new TlsStream();
+ byte[] result = null;
- cs.Write(fragment, 0, fragment.Length);
- cs.Write(mac, 0, mac.Length);
- if (cipherMode == CipherMode.CBC)
- {
- // Calculate padding_length
- int fragmentLength = fragment.Length + mac.Length + 1;
- int paddingLength = (((fragmentLength/blockSize)*blockSize) + blockSize) - fragmentLength;
+ data.Write(this.Context.ReadSequenceNumber);
+ data.Write((byte)contentType);
+ data.Write((short)this.Context.Protocol);
+ data.Write((short)fragment.Length);
+ data.Write(fragment);
- // Write padding length byte
- cs.WriteByte((byte)paddingLength);
- }
- //cs.FlushFinalBlock();
- cs.Close();
+ result = this.ServerHMAC.ComputeHash(data.ToArray());
+
+ data.Reset();
- return ms.ToArray();
+ return result;
}
- public override void DecryptRecord(byte[] fragment, ref byte[] dcrFragment, ref byte[] dcrMAC)
+ public override byte[] ComputeClientRecordMAC(TlsContentType contentType, byte[] fragment)
{
- int fragmentSize = 0;
- int paddingLength = 0;
+ TlsStream data = new TlsStream();
+ byte[] result = null;
- // Decrypt message fragment ( fragment + mac [+ padding + padding_length] )
- byte[] buffer = new byte[fragment.Length];
- decryptionCipher.TransformBlock(fragment, 0, fragment.Length, buffer, 0);
+ data.Write(this.Context.WriteSequenceNumber);
+ data.Write((byte)contentType);
+ data.Write((short)this.Context.Protocol);
+ data.Write((short)fragment.Length);
+ data.Write(fragment);
- // Calculate fragment size
- if (cipherMode == CipherMode.CBC)
- {
- // Calculate padding_length
- paddingLength = buffer[buffer.Length - 1];
- for (int i = (buffer.Length - 1); i > (buffer.Length - (paddingLength + 1)); i--)
- {
- if (buffer[i] != paddingLength)
- {
- paddingLength = 0;
- break;
- }
- }
-
- fragmentSize = (buffer.Length - (paddingLength + 1)) - HashSize;
- }
- else
- {
- fragmentSize = buffer.Length - HashSize;
- }
+ result = this.ClientHMAC.ComputeHash(data.ToArray());
- dcrFragment = new byte[fragmentSize];
- dcrMAC = new byte[HashSize];
+ data.Reset();
- Buffer.BlockCopy(buffer, 0, dcrFragment, 0, dcrFragment.Length);
- Buffer.BlockCopy(buffer, dcrFragment.Length, dcrMAC, 0, dcrMAC.Length);
+ return result;
}
#endregion
- #region KEY_GENERATION_METODS
+ #region Key Generation Methods
- public override void CreateMasterSecret(byte[] preMasterSecret)
+ public override void ComputeMasterSecret(byte[] preMasterSecret)
{
- TlsStream seed = new TlsStream();
-
- // Seed
- seed.Write(context.ClientRandom);
- seed.Write(context.ServerRandom);
-
// Create master secret
- context.MasterSecret = new byte[preMasterSecret.Length];
- context.MasterSecret = PRF(preMasterSecret, "master secret", seed.ToArray(), 48);
-
- seed.Reset();
+ this.Context.MasterSecret = new byte[preMasterSecret.Length];
+ this.Context.MasterSecret = this.PRF(
+ preMasterSecret, "master secret", this.Context.RandomCS, 48);
}
- public override void CreateKeys()
+ public override void ComputeKeys()
{
- TlsStream seed = new TlsStream();
-
- // Seed
- seed.Write(context.ServerRandom);
- seed.Write(context.ClientRandom);
-
// Create keyblock
TlsStream keyBlock = new TlsStream(
- PRF(this.Context.MasterSecret,
+ this.PRF(
+ this.Context.MasterSecret,
"key expansion",
- seed.ToArray(),
+ this.Context.RandomSC,
this.KeyBlockSize));
this.Context.ClientWriteMAC = keyBlock.ReadBytes(this.HashSize);
}
else
{
- // Seed
- seed.Reset();
- seed.Write(this.Context.ClientRandom);
- seed.Write(this.Context.ServerRandom);
-
// Generate final write keys
- byte[] finalClientWriteKey = PRF(this.Context.ClientWriteKey, "client write key", seed.ToArray(), this.KeyMaterialSize);
- byte[] finalServerWriteKey = PRF(this.Context.ServerWriteKey, "server write key", seed.ToArray(), this.KeyMaterialSize);
+ byte[] finalClientWriteKey = PRF(this.Context.ClientWriteKey, "client write key", this.Context.RandomCS, this.KeyMaterialSize);
+ byte[] finalServerWriteKey = PRF(this.Context.ServerWriteKey, "server write key", this.Context.RandomCS, this.KeyMaterialSize);
this.Context.ClientWriteKey = finalClientWriteKey;
this.Context.ServerWriteKey = finalServerWriteKey;
// Generate IV block
- byte[] ivBlock = PRF(new byte[]{}, "IV block", seed.ToArray(), this.IvSize*2);
+ byte[] ivBlock = PRF(new byte[]{}, "IV block", this.Context.RandomCS, this.IvSize*2);
// Generate IV keys
this.Context.ClientWriteIV = new byte[this.IvSize];
System.Array.Copy(ivBlock, 0, this.Context.ClientWriteIV, 0, this.Context.ClientWriteIV.Length);
+
this.Context.ServerWriteIV = new byte[this.IvSize];
System.Array.Copy(ivBlock, this.IvSize, this.Context.ServerWriteIV, 0, this.Context.ServerWriteIV.Length);
}
// Clear no more needed data
- seed.Reset();
keyBlock.Reset();
}