[pgsqlclient-checkins] pgsqlclient_10/Mono.Security.Protocol.Tls/Mono.Security.Protocol.Tls TlsCiphe
Status: Inactive
Brought to you by:
carlosga_fb
Update of /cvsroot/pgsqlclient/pgsqlclient_10/Mono.Security.Protocol.Tls/Mono.Security.Protocol.Tls In directory sc8-pr-cvs1:/tmp/cvs-serv29414 Modified Files: TlsCipherSuite.cs TlsCipherSuiteCollection.cs TlsSession.cs TlsSessionContext.cs Log Message: * TLS implementation: - Fixed padding length calculation on record encryption. - Abstracted CipherSuite classes for allow work with other protocol versions. - Added new files : TlsAbstractCipherSuite.cs TlsSslCipherSuite.cs TlsCipherSuiteFactory.cs - Added new cipher suites definitions based on RFC3268 - (http://www.ietf.org/rfc/rfc3268.txt) - Added two new supported ciphersuites for TLS protocol: TLS_RSA_WITH_AES_256_CBC_SHA TLS_RSA_WITH_AES_128_CBC_SHA - Moved key generation stuff to specific cipher suite classes. Index: TlsCipherSuite.cs =================================================================== RCS file: /cvsroot/pgsqlclient/pgsqlclient_10/Mono.Security.Protocol.Tls/Mono.Security.Protocol.Tls/TlsCipherSuite.cs,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** TlsCipherSuite.cs 13 Oct 2003 19:13:30 -0000 1.2 --- TlsCipherSuite.cs 20 Oct 2003 09:58:29 -0000 1.3 *************** *** 34,155 **** namespace Mono.Security.Protocol.Tls { ! internal class TlsCipherSuite { - #region FIELDS - - private short code; - private string name; - private string algName; - private string hashName; - private bool isExportable; - private CipherMode cipherMode; - private byte keyMaterialSize; - private byte expandedKeyMaterialSize; - private byte effectiveKeyBits; - private byte ivSize; - private byte blockSize; - private TlsSessionContext sessionContext; - private SymmetricAlgorithm encryptionAlgorithm; - private ICryptoTransform encryptionCipher; - private SymmetricAlgorithm decryptionAlgorithm; - private ICryptoTransform decryptionCipher; - private KeyedHashAlgorithm clientHMAC; - private KeyedHashAlgorithm serverHMAC; - - #endregion - - #region PROPERTIES - - public short Code - { - get { return code; } - } - - public string Name - { - get { return name; } - } - - public bool IsExportable - { - get { return isExportable; } - } - - public CipherMode CipherMode - { - get { return cipherMode; } - } - - public int HashSize - { - get { return (int)(hashName == "MD5" ? 16 : 20); } - } - - public byte KeyMaterialSize - { - get { return keyMaterialSize; } - } - - public byte ExpandedKeyMaterialSize - { - get { return expandedKeyMaterialSize; } - } - - public byte EffectiveKeyBits - { - get { return EffectiveKeyBits; } - } - - public byte IvSize - { - get { return ivSize; } - } - - public byte BlockSize - { - get { return blockSize; } - } - - public string HashName - { - get { return hashName; } - } - - public TlsSessionContext SessionState - { - get { return sessionContext; } - set { sessionContext = value; } - } - - public KeyedHashAlgorithm ClientHMAC - { - get { return clientHMAC; } - } - - public KeyedHashAlgorithm ServerHMAC - { - get { return serverHMAC; } - } - - #endregion - #region CONSTRUCTORS ! public TlsCipherSuite(short code, string name, string algName, string hashName, bool exportable, bool blockMode, byte keyMaterialSize, byte expandedKeyMaterialSize, byte effectiveKeyBytes, byte ivSize, byte blockSize) { - this.code = code; - this.name = name; - this.algName = algName; - this.hashName = hashName; - this.isExportable = exportable; - if (blockMode) - { - this.cipherMode = CipherMode.CBC; - } - this.keyMaterialSize = keyMaterialSize; - this.expandedKeyMaterialSize = expandedKeyMaterialSize; - this.effectiveKeyBits = effectiveKeyBits; - this.ivSize = ivSize; - this.blockSize = blockSize; } --- 34,49 ---- namespace Mono.Security.Protocol.Tls { ! internal class TlsCipherSuite : TlsAbstractCipherSuite { #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) { } *************** *** 158,228 **** #region METHODS ! public RSACryptoServiceProvider CreateRSA(X509Certificate certificate) ! { ! RSAParameters rsaParams = new RSAParameters(); ! ! // for RSA m_publickey contains 2 ASN.1 integers ! // the modulus and the public exponent ! ASN1 pubkey = new ASN1(certificate.GetPublicKey()); ! ASN1 modulus = pubkey [0]; ! if ((modulus == null) || (modulus.Tag != 0x02)) ! { ! return null; ! } ! ASN1 exponent = pubkey [1]; ! if (exponent.Tag != 0x02) ! { ! return null; ! } ! ! rsaParams.Modulus = getUnsignedBigInteger(modulus.Value); ! rsaParams.Exponent = exponent.Value; ! ! return CreateRSA(rsaParams); ! } ! ! public RSACryptoServiceProvider CreateRSA(RSAParameters rsaParams) ! { ! // BUG: MS BCL 1.0 can't import a key which ! // isn't the same size as the one present in ! // the container. ! int keySize = (rsaParams.Modulus.Length << 3); ! RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(keySize); ! rsa.ImportParameters(rsaParams); ! ! return rsa; ! } ! ! public void InitializeCipher() ! { ! createEncryptionCipher(); ! createDecryptionCipher(); ! } ! ! public void UpdateClientCipherIV(byte[] iv) ! { ! if (cipherMode == CipherMode.CBC) ! { ! // Set the new IV ! encryptionAlgorithm.IV = iv; ! ! // Create encryption cipher with the new IV ! encryptionCipher = encryptionAlgorithm.CreateEncryptor(); ! } ! } ! ! public void UpdateServerCipherIV(byte[] iv) ! { ! if (cipherMode == CipherMode.CBC) ! { ! // Set the new IV ! decryptionAlgorithm.IV = iv; ! ! // Create encryption cipher with the new IV ! decryptionCipher = decryptionAlgorithm.CreateDecryptor(); ! } ! } ! ! public byte[] EncryptRecord(byte[] fragment, byte[] mac) { // Encryption ( fragment + mac [+ padding + padding_length] ) --- 52,56 ---- #region METHODS ! public override byte[] EncryptRecord(byte[] fragment, byte[] mac) { // Encryption ( fragment + mac [+ padding + padding_length] ) *************** *** 236,240 **** // Calculate padding_length int fragmentLength = fragment.Length + mac.Length + 1; ! int paddingLength = (((fragmentLength/blockSize)*8) + blockSize) - fragmentLength; // Write padding length byte --- 64,68 ---- // Calculate padding_length int fragmentLength = fragment.Length + mac.Length + 1; ! int paddingLength = (((fragmentLength/blockSize)*blockSize) + blockSize) - fragmentLength; // Write padding length byte *************** *** 247,251 **** } ! public void DecryptRecord(byte[] fragment, ref byte[] dcrFragment, ref byte[] dcrMAC) { int fragmentSize = 0; --- 75,79 ---- } ! public override void DecryptRecord(byte[] fragment, ref byte[] dcrFragment, ref byte[] dcrMAC) { int fragmentSize = 0; *************** *** 284,383 **** } - public int GetKeyBlockSize() - { - return keyMaterialSize*2 + HashSize*2 + ivSize*2; - } - #endregion ! #region PRIVATE_METHODS ! // This code is from Mono.Security.X509Certificate class. ! private byte[] getUnsignedBigInteger(byte[] integer) { ! if (integer[0] == 0x00) ! { ! // this first byte is added so we're sure it's an unsigned integer ! // however we can't feed it into RSAParameters or DSAParameters ! int length = integer.Length - 1; ! byte[] uinteger = new byte[length]; ! Array.Copy(integer, 1, uinteger, 0, length); ! return uinteger; ! } ! else ! { ! return integer; ! } } ! private void createEncryptionCipher() { ! // Create and configure the symmetric algorithm ! switch (this.algName) ! { ! case "RC4": ! encryptionAlgorithm = new ARC4Managed(); ! break; ! ! default: ! encryptionAlgorithm = SymmetricAlgorithm.Create(algName); ! break; ! } ! // If it's a block cipher ! if (cipherMode == CipherMode.CBC) ! { ! // Configure encrypt algorithm ! encryptionAlgorithm.Mode = this.cipherMode; ! encryptionAlgorithm.Padding = PaddingMode.PKCS7; ! encryptionAlgorithm.KeySize = this.keyMaterialSize * 8; ! encryptionAlgorithm.BlockSize = this.blockSize * 8; ! } ! // Set the key and IV for the algorithm ! encryptionAlgorithm.Key = sessionContext.ClientWriteKey; ! encryptionAlgorithm.IV = sessionContext.ClientWriteIV; ! ! // Create encryption cipher ! encryptionCipher = encryptionAlgorithm.CreateEncryptor(); ! // Create the HMAC algorithm for the client ! clientHMAC = new HMAC(hashName, sessionContext.ClientWriteMAC); ! } ! private void createDecryptionCipher() ! { ! // Create and configure the symmetric algorithm ! switch (this.algName) { ! case "RC4": ! decryptionAlgorithm = new ARC4Managed(); ! break; ! ! default: ! decryptionAlgorithm = SymmetricAlgorithm.Create(algName); ! break; } ! ! // If it's a block cipher ! if (cipherMode == CipherMode.CBC) { ! // Configure encrypt algorithm ! decryptionAlgorithm.Mode = this.cipherMode; ! decryptionAlgorithm.Padding = PaddingMode.None; ! decryptionAlgorithm.KeySize = this.keyMaterialSize * 8; ! decryptionAlgorithm.BlockSize = this.blockSize * 8; ! } ! // Set the key and IV for the algorithm ! decryptionAlgorithm.Key = sessionContext.ServerWriteKey; ! decryptionAlgorithm.IV = sessionContext.ServerWriteIV; ! // Create decryption cipher ! decryptionCipher = decryptionAlgorithm.CreateDecryptor(); ! // Create the HMAC algorithm for the server ! serverHMAC = new HMAC(hashName, sessionContext.ServerWriteMAC); } --- 112,194 ---- } #endregion ! #region KEY_GENERATION_METODS ! public override void CreateMasterSecret(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(); } ! public override void CreateKeys() { ! TlsStream seed = new TlsStream(); ! // Seed ! seed.Write(context.ServerRandom); ! seed.Write(context.ClientRandom); ! // Create keyblock ! TlsStream keyBlock = new TlsStream( ! PRF(this.Context.MasterSecret, ! "key expansion", ! seed.ToArray(), ! this.KeyBlockSize)); ! this.Context.ClientWriteMAC = keyBlock.ReadBytes(this.HashSize); ! this.Context.ServerWriteMAC = keyBlock.ReadBytes(this.HashSize); ! this.Context.ClientWriteKey = keyBlock.ReadBytes(this.KeyMaterialSize); ! this.Context.ServerWriteKey = keyBlock.ReadBytes(this.KeyMaterialSize); ! if (!this.IsExportable) { ! if (this.IvSize != 0) ! { ! this.Context.ClientWriteIV = keyBlock.ReadBytes(this.IvSize); ! this.Context.ServerWriteIV = keyBlock.ReadBytes(this.IvSize); ! } ! else ! { ! this.Context.ClientWriteIV = new byte[0]; ! this.Context.ServerWriteIV = new byte[0]; ! } } ! 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); ! ! this.Context.ClientWriteKey = finalClientWriteKey; ! this.Context.ServerWriteKey = finalServerWriteKey; ! // Generate IV block ! byte[] ivBlock = PRF(new byte[]{}, "IV block", seed.ToArray(), 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(); } Index: TlsCipherSuiteCollection.cs =================================================================== RCS file: /cvsroot/pgsqlclient/pgsqlclient_10/Mono.Security.Protocol.Tls/Mono.Security.Protocol.Tls/TlsCipherSuiteCollection.cs,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** TlsCipherSuiteCollection.cs 11 Oct 2003 10:04:20 -0000 1.1 --- TlsCipherSuiteCollection.cs 20 Oct 2003 09:58:29 -0000 1.2 *************** *** 54,110 **** #endregion - #region STATIC_METHODS - - public static TlsCipherSuiteCollection GetSupportedCipherSuiteCollection() - { - TlsCipherSuiteCollection scs = new TlsCipherSuiteCollection(); - - // Supported ciphers - scs.Add((0x00 << 0x08) | 0x0A, "TLS_RSA_WITH_3DES_EDE_CBC_SHA", "3DES", "SHA", false, true, 24, 24, 168, 8, 8); - scs.Add((0x00 << 0x08) | 0x09, "TLS_RSA_WITH_DES_CBC_SHA", "DES", "SHA", false, true, 8, 8, 56, 8, 8); - scs.Add((0x00 << 0x08) | 0x05, "TLS_RSA_WITH_RC4_128_SHA", "RC4", "SHA", false, false, 16, 16, 128, 0, 0); - scs.Add((0x00 << 0x08) | 0x04, "TLS_RSA_WITH_RC4_128_MD5", "RC4", "MD5", false, false, 16, 16, 128, 0, 0); - - // Default CipherSuite - // scs.Add(0, "TLS_NULL_WITH_NULL_NULL", "", "", true, false, 0, 0, 0, 0, 0); - - // RSA Cipher Suites - // scs.Add((0x00 << 0x08) | 0x01, "TLS_RSA_WITH_NULL_MD5", "", "MD5", true, false, 0, 0, 0, 0, 0); - // scs.Add((0x00 << 0x08) | 0x02, "TLS_RSA_WITH_NULL_SHA", "", "SHA", true, false, 0, 0, 0, 0, 0); - // scs.Add((0x00 << 0x08) | 0x03, "TLS_RSA_EXPORT_WITH_RC4_40_MD5", "RC4", "MD5", true, false, 5, 16, 40, 0, 0); - // scs.Add((0x00 << 0x08) | 0x05, "TLS_RSA_WITH_RC4_128_SHA", "RC4", "SHA", false, false, 16, 16, 128, 0, 0); - // scs.Add((0x00 << 0x08) | 0x04, "TLS_RSA_WITH_RC4_128_MD5", "RC4", "MD5", false, false, 16, 16, 128, 0, 0); - // scs.Add((0x00 << 0x08) | 0x06, "TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5", "RC2", "MD5", true, true, 5, 16, 40, 8, 8); - // scs.Add((0x00 << 0x08) | 0x07, "TLS_RSA_WITH_IDEA_CBC_SHA", "IDEA", "SHA", false, true, 16, 16, 128, 8, 8); - // scs.Add((0x00 << 0x08) | 0x08, "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA", "DES", "SHA", true, true, 5, 8, 40, 8, 8); - // scs.Add((0x00 << 0x08) | 0x09, "TLS_RSA_WITH_DES_CBC_SHA", "DES", "SHA", false, true, 8, 8, 56, 8, 8); - // scs.Add((0x00 << 0x08) | 0x0A, "TLS_RSA_WITH_3DES_EDE_CBC_SHA", "3DES", "SHA", false, true, 24, 24, 168, 8, 8); - - // Diffie-Hellman Cipher Suites - // scs.Add((0x00 << 0x08) | 0x0B, "TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA", "DES", "SHA", true, true, 5, 8, 40, 8, 8); - // scs.Add((0x00 << 0x08) | 0x0C, "TLS_DH_DSS_WITH_DES_CBC_SHA", "DES", "SHA", false, true, 8, 8, 56, 8, 8); - // scs.Add((0x00 << 0x08) | 0x0D, "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA", "3DES", "SHA", false, true, 24, 24, 168, 8, 8); - // scs.Add((0x00 << 0x08) | 0x0E, "TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA", "DES", "SHA", true, true, 5, 8, 40, 8, 8); - // scs.Add((0x00 << 0x08) | 0x0F, "TLS_DH_RSA_WITH_DES_CBC_SHA", "DES", "SHA", false, true, 8, 8, 56, 8, 8); - // scs.Add((0x00 << 0x08) | 0x10, "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA", "3DES", "SHA", false, true, 24, 24, 168, 8, 8); - // scs.Add((0x00 << 0x08) | 0x11, "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA", "DES", "SHA", true, true, 5, 8, 40, 8, 8); - // scs.Add((0x00 << 0x08) | 0x12, "TLS_DHE_DSS_WITH_DES_CBC_SHA", "DES", "SHA", false, true, 8, 8, 56, 8, 8); - // scs.Add((0x00 << 0x08) | 0x13, "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA", "3DES", "SHA", false, true, 24, 24, 168, 8, 8); - // scs.Add((0x00 << 0x08) | 0x14, "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", "DES", "SHA", true, true, 5, 8, 40, 8, 8); - // scs.Add((0x00 << 0x08) | 0x15, "TLS_DHE_RSA_WITH_DES_CBC_SHA", "SHA", "DES", false, true, 8, 8, 56, 8, 8); - // scs.Add((0x00 << 0x08) | 0x16, "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA", "3DES", "SHA", false, true, 24, 24, 168, 8, 8); - - // Anonymous Diffie-Hellman Cipher Suites - // scs.Add((0x00 << 0x08) | 0x17, "TLS_DH_anon_EXPORT_WITH_RC4_40_MD5", "RC4", "MD5", true, false, 5, 16, 40, 0, 0); - // scs.Add((0x00 << 0x08) | 0x18, "TLS_DH_anon_WITH_RC4_128_MD5", "RC4", "MD5", false, false, 16, 16, 128, 0, 0); - // scs.Add((0x00 << 0x08) | 0x19, "TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA", "DES", "SHA", false, true, 5, 8, 40, 8, 8); - // scs.Add((0x00 << 0x08) | 0x1A, "TLS_DH_anon_WITH_DES_CBC_SHA", "DES4", "SHA", false, true, 8, 8, 56, 8, 8); - // scs.Add((0x00 << 0x08) | 0x1B, "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA", "3DES", "SHA", false, true, 24, 24, 168, 8, 8); - - return scs; - } - - #endregion - #region METHODS --- 54,57 ---- *************** *** 154,158 **** } ! public TlsCipherSuite Add(short code, string name, string algName, string hashName, bool exportable, bool blockMode, byte keyMaterialSize, byte expandedKeyMaterialSize, byte effectiveKeyBytes, byte ivSize, byte blockSize) { TlsCipherSuite cipherSuite = new TlsCipherSuite(code, name, algName, hashName, exportable, blockMode, keyMaterialSize, expandedKeyMaterialSize, effectiveKeyBytes, ivSize, blockSize); --- 101,105 ---- } ! public TlsCipherSuite Add(short code, string name, string algName, string hashName, bool exportable, bool blockMode, byte keyMaterialSize, byte expandedKeyMaterialSize, short effectiveKeyBytes, byte ivSize, byte blockSize) { TlsCipherSuite cipherSuite = new TlsCipherSuite(code, name, algName, hashName, exportable, blockMode, keyMaterialSize, expandedKeyMaterialSize, effectiveKeyBytes, ivSize, blockSize); Index: TlsSession.cs =================================================================== RCS file: /cvsroot/pgsqlclient/pgsqlclient_10/Mono.Security.Protocol.Tls/Mono.Security.Protocol.Tls/TlsSession.cs,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** TlsSession.cs 13 Oct 2003 19:13:30 -0000 1.2 --- TlsSession.cs 20 Oct 2003 09:58:29 -0000 1.3 *************** *** 123,127 **** public TlsSession(TlsSessionSettings settings) { - this.supportedCiphers = TlsCipherSuiteCollection.GetSupportedCipherSuiteCollection(); this.settings = settings; this.context = new TlsSessionContext(); --- 123,126 ---- *************** *** 170,174 **** --- 169,175 ---- this.context.Protocol = settings.Protocol; this.state = TlsSessionState.OpeningSecure; + this.supportedCiphers = TlsCipherSuiteFactory.GetSupportedCiphers(context.Protocol); this.socket.DoHandshake(); + this.state = TlsSessionState.OpenSecure; } catch (TlsException ex) Index: TlsSessionContext.cs =================================================================== RCS file: /cvsroot/pgsqlclient/pgsqlclient_10/Mono.Security.Protocol.Tls/Mono.Security.Protocol.Tls/TlsSessionContext.cs,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** TlsSessionContext.cs 14 Oct 2003 10:13:58 -0000 1.4 --- TlsSessionContext.cs 20 Oct 2003 09:58:29 -0000 1.5 *************** *** 192,207 **** #endregion ! #region KEY_GENERATION_METODS ! ! public byte[] GetSecureRandomBytes(int count) ! { ! byte[] secureBytes = new byte[count]; ! ! RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); ! rng.GetNonZeroBytes(secureBytes); ! ! return secureBytes; ! } ! public int GetUnixTime() { --- 192,197 ---- #endregion ! #region METHODS ! public int GetUnixTime() { *************** *** 212,387 **** } ! public byte[] CreatePremasterSecret() ! { ! TlsStream stream = new TlsStream(); ! ! // Write protocol version ! stream.Write((short)protocol); ! ! // Generate random bytes ! stream.Write(GetSecureRandomBytes(46)); ! ! byte[] preMasterSecret = stream.ToArray(); ! ! stream.Reset(); ! ! return preMasterSecret; ! } ! ! public void CreateMasterSecret(byte[] preMasterSecret) ! { ! TlsCipherSuite cipherSuite = cipher; ! TlsStream seed = new TlsStream(); ! ! // Seed ! seed.Write(clientRandom); ! seed.Write(serverRandom); ! ! // Create master secret ! masterSecret = new byte[preMasterSecret.Length]; ! masterSecret = PRF(preMasterSecret, "master secret", seed.ToArray(), 48); ! ! seed.Reset(); ! } ! ! public void CreateKeys() ! { ! TlsStream seed = new TlsStream(); ! ! // Seed ! seed.Write(serverRandom); ! seed.Write(clientRandom); ! ! // Create keyblock ! TlsStream keyBlock = new TlsStream( ! PRF(masterSecret, ! "key expansion", ! seed.ToArray(), ! cipher.GetKeyBlockSize())); ! ! clientWriteMAC = keyBlock.ReadBytes(cipher.HashSize); ! serverWriteMAC = keyBlock.ReadBytes(cipher.HashSize); ! clientWriteKey = keyBlock.ReadBytes(cipher.KeyMaterialSize); ! serverWriteKey = keyBlock.ReadBytes(cipher.KeyMaterialSize); ! ! if (!cipher.IsExportable) ! { ! if (cipher.IvSize != 0) ! { ! clientWriteIV = keyBlock.ReadBytes(cipher.IvSize); ! serverWriteIV = keyBlock.ReadBytes(cipher.IvSize); ! } ! else ! { ! clientWriteIV = new byte[0]; ! serverWriteIV = new byte[0]; ! } ! } ! else ! { ! // Seed ! seed.Reset(); ! seed.Write(clientRandom); ! seed.Write(serverRandom); ! ! // Generate final write keys ! byte[] finalClientWriteKey = PRF(clientWriteKey, "client write key", seed.ToArray(), cipher.KeyMaterialSize); ! byte[] finalServerWriteKey = PRF(serverWriteKey, "server write key", seed.ToArray(), cipher.KeyMaterialSize); ! ! clientWriteKey = finalClientWriteKey; ! serverWriteKey = finalServerWriteKey; ! ! // Generate IV block ! byte[] ivBlock = PRF(new byte[]{}, "IV block", seed.ToArray(), cipher.IvSize*2); ! ! // Generate IV keys ! clientWriteIV = new byte[cipher.IvSize]; ! System.Array.Copy(ivBlock, 0, clientWriteIV, 0, clientWriteIV.Length); ! serverWriteIV = new byte[cipher.IvSize]; ! System.Array.Copy(ivBlock, cipher.IvSize, serverWriteIV, 0, serverWriteIV.Length); ! } ! ! // Clear no more needed data ! seed.Reset(); ! keyBlock.Reset(); ! } ! ! public byte[] PRF(byte[] secret, string label, byte[] data, int length) ! { ! MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider(); ! SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider(); ! ! int secretLen = secret.Length / 2; ! ! // Seed ! TlsStream seedStream = new TlsStream(); ! seedStream.Write(Encoding.ASCII.GetBytes(label)); ! seedStream.Write(data); ! byte[] seed = seedStream.ToArray(); ! seedStream.Reset(); ! ! // Secret 1 ! byte[] secret1 = new byte[secretLen]; ! System.Array.Copy(secret, 0, secret1, 0, secretLen); ! ! // Secret2 ! byte[] secret2 = new byte[secretLen]; ! System.Array.Copy(secret, secretLen, secret2, 0, secretLen); ! ! // Secret 1 processing ! byte[] p_md5 = Expand("MD5", secret1, seed, length); ! ! // Secret 2 processing ! byte[] p_sha = Expand("SHA1", secret2, seed, length); ! ! // Perfor XOR of both results ! byte[] masterSecret = new byte[length]; ! for (int i = 0; i < masterSecret.Length; i++) ! { ! masterSecret[i] = (byte)(p_md5[i] ^ p_sha[i]); ! } ! ! return masterSecret; ! } ! ! public byte[] Expand(string hashName, byte[] secret, byte[] seed, int length) { ! int hashLength = hashName == "MD5" ? 16 : 20; ! int iterations = (int)(length / hashLength); ! if ((length % hashLength) > 0) ! { ! iterations++; ! } ! ! HMAC hmac = new HMAC(hashName, secret); ! TlsStream resMacs = new TlsStream(); ! ! byte[][] hmacs = new byte[iterations + 1][]; ! hmacs[0] = seed; ! for (int i = 1; i <= iterations; i++) ! { ! TlsStream hcseed = new TlsStream(); ! hmac.TransformFinalBlock(hmacs[i-1], 0, hmacs[i-1].Length); ! hmacs[i] = hmac.Hash; ! hcseed.Write(hmacs[i]); ! hcseed.Write(seed); ! hmac.TransformFinalBlock(hcseed.ToArray(), 0, (int)hcseed.Length); ! resMacs.Write(hmac.Hash); ! hcseed.Reset(); ! } ! byte[] res = new byte[length]; ! System.Array.Copy(resMacs.ToArray(), 0, res, 0, res.Length); ! ! resMacs.Reset(); ! ! return res; } - #endregion - - #region METHODS - public void ClearKeyInfo() { --- 202,215 ---- } ! public byte[] GetSecureRandomBytes(int count) { ! byte[] secureBytes = new byte[count]; ! RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); ! rng.GetNonZeroBytes(secureBytes); ! return secureBytes; } public void ClearKeyInfo() { |