public static CipherSuite InitializeCipherSuite(byte[] master, byte[] clientrnd, byte[] serverrnd, CipherDefinition definition, ConnectionEnd entity)
 {
     CipherSuite ret = new CipherSuite();
     SymmetricAlgorithm bulk = (SymmetricAlgorithm)Activator.CreateInstance(definition.BulkCipherAlgorithm);
     if (definition.BulkIVSize > 0)
         bulk.Mode = CipherMode.CBC;
     bulk.Padding = PaddingMode.None;
     bulk.BlockSize = definition.BulkIVSize * 8;
     // get the keys and IVs
     byte[] client_mac, server_mac, client_key, server_key, client_iv, server_iv;
     byte[] random = new byte[64];
     Array.Copy(serverrnd, 0, random, 0, 32);
     Array.Copy(clientrnd, 0, random, 32, 32);
     PseudoRandomDeriveBytes prf = new PseudoRandomDeriveBytes(master, "key expansion", random);
     client_mac = prf.GetBytes(definition.HashSize);
     server_mac = prf.GetBytes(definition.HashSize);
     client_key = prf.GetBytes(definition.BulkKeySize);
     server_key = prf.GetBytes(definition.BulkKeySize);
     client_iv = prf.GetBytes(definition.BulkIVSize);
     server_iv = prf.GetBytes(definition.BulkIVSize);
     prf.Dispose();
     if (definition.Exportable) { // make some extra modifications if the keys are exportable
         Array.Copy(clientrnd, 0, random, 0, 32);
         Array.Copy(serverrnd, 0, random, 32, 32);
         prf = new PseudoRandomDeriveBytes(client_key, "client write key", random);
         client_key = prf.GetBytes(definition.BulkExpandedSize);
         prf.Dispose();
         prf = new PseudoRandomDeriveBytes(server_key, "server write key", random);
         server_key = prf.GetBytes(definition.BulkExpandedSize);
         prf.Dispose();
         prf = new PseudoRandomDeriveBytes(new byte[0], "IV block", random);
         client_iv = prf.GetBytes(definition.BulkIVSize);
         server_iv = prf.GetBytes(definition.BulkIVSize);
         prf.Dispose();
     }
     // generate the cipher objects
     if (entity == ConnectionEnd.Client) {
         ret.Encryptor = bulk.CreateEncryptor(client_key, client_iv);
         ret.Decryptor = bulk.CreateDecryptor(server_key, server_iv);
         ret.LocalHasher = new HMAC((HashAlgorithm)Activator.CreateInstance(definition.HashAlgorithm), client_mac);
         ret.RemoteHasher = new HMAC((HashAlgorithm)Activator.CreateInstance(definition.HashAlgorithm), server_mac);
     } else {
         ret.Encryptor = bulk.CreateEncryptor(server_key, server_iv);
         ret.Decryptor = bulk.CreateDecryptor(client_key, client_iv);
         ret.LocalHasher = new HMAC((HashAlgorithm)Activator.CreateInstance(definition.HashAlgorithm), server_mac);
         ret.RemoteHasher = new HMAC((HashAlgorithm)Activator.CreateInstance(definition.HashAlgorithm), client_mac);
     }
     // clear sensitive data
     Array.Clear(client_mac, 0, client_mac.Length);
     Array.Clear(server_mac, 0, server_mac.Length);
     Array.Clear(client_key, 0, client_key.Length);
     Array.Clear(server_key, 0, server_key.Length);
     Array.Clear(client_iv, 0, client_iv.Length);
     Array.Clear(server_iv, 0, server_iv.Length);
     Array.Clear(random, 0, random.Length);
     return ret;
 }
        protected SslHandshakeStatus ProcessServerKeyExchange(HandshakeMessage message)
        {
            if (m_State != HandshakeType.Certificate)
            {
                throw new SslException(AlertDescription.UnexpectedMessage, "ServerKeyExchange message must be preceded by a Certificate message.");
            }
            CipherDefinition cd = CipherSuites.GetCipherDefinition(m_EncryptionScheme);

            if (!cd.Exportable)
            {
                throw new SslException(AlertDescription.HandshakeFailure, "The ServerKeyExchange message should not be sent for non-exportable ciphers.");
            }
            if (m_RemoteCertificate.GetPublicKeyLength() <= 512)
            {
                throw new SslException(AlertDescription.HandshakeFailure, "The ServerKeyExchange message should not be sent because the server certificate public key is of exportable length.");
            }
            UpdateHashes(message, HashUpdate.All);             // input message
            // extract modulus and exponent
            RSAParameters pars = new RSAParameters();
            int           size = message.fragment[0] * 256 + message.fragment[1];

            pars.Modulus = new byte[size];
            Buffer.BlockCopy(message.fragment, 2, pars.Modulus, 0, size);
            int offset = size + 2;

            size          = message.fragment[offset] * 256 + message.fragment[offset + 1];
            pars.Exponent = new byte[size];
            Buffer.BlockCopy(message.fragment, offset + 2, pars.Exponent, 0, size);
            offset       += size + 2;
            pars.Modulus  = RemoveLeadingZeros(pars.Modulus);
            pars.Exponent = RemoveLeadingZeros(pars.Exponent);
            m_KeyCipher   = new RSACryptoServiceProvider();
            m_KeyCipher.ImportParameters(pars);
            // compute verification hashes
            MD5SHA1CryptoServiceProvider ms = new MD5SHA1CryptoServiceProvider();

            ms.TransformBlock(m_ClientTime, 0, m_ClientTime.Length, m_ClientTime, 0);
            ms.TransformBlock(m_ClientRandom, 0, m_ClientRandom.Length, m_ClientRandom, 0);
            ms.TransformBlock(m_ServerTime, 0, m_ServerTime.Length, m_ServerTime, 0);
            ms.TransformBlock(m_ServerRandom, 0, m_ServerRandom.Length, m_ServerRandom, 0);
            ms.TransformFinalBlock(message.fragment, 0, offset);
            // verify the signature
            size = message.fragment[offset] * 256 + message.fragment[offset + 1];
            byte[] signature = new byte[size];             // holds the signature returned by the server
            Buffer.BlockCopy(message.fragment, offset + 2, signature, 0, size);
            if (!ms.VerifySignature(m_RemoteCertificate, signature))
            {
                throw new SslException(AlertDescription.HandshakeFailure, "The data was not signed by the server certificate.");
            }
            ms.Clear();
            return(new SslHandshakeStatus(SslStatus.MessageIncomplete, null));
        }
Esempio n. 3
0
 public static CipherSuite InitializeCipherSuite(byte[] master, byte[] clientrnd, byte[] serverrnd, CipherDefinition definition, ConnectionEnd entity)
 {
     CipherSuite ret = new CipherSuite();
     SymmetricAlgorithm bulk = (SymmetricAlgorithm)Activator.CreateInstance(definition.BulkCipherAlgorithm);
     if (definition.BulkIVSize > 0)
         bulk.Mode = CipherMode.CBC;
     bulk.Padding = PaddingMode.None;
     bulk.BlockSize = definition.BulkIVSize * 8;
     // get the keys and IVs
     byte[] client_mac, server_mac, client_key, server_key, client_iv, server_iv;
     Ssl3DeriveBytes prf = new Ssl3DeriveBytes(master, clientrnd, serverrnd, false);
     client_mac = prf.GetBytes(definition.HashSize);
     server_mac = prf.GetBytes(definition.HashSize);
     client_key = prf.GetBytes(definition.BulkKeySize);
     server_key = prf.GetBytes(definition.BulkKeySize);
     client_iv = prf.GetBytes(definition.BulkIVSize);
     server_iv = prf.GetBytes(definition.BulkIVSize);
     prf.Dispose();
     if (definition.Exportable) { // make some extra modifications if the keys are exportable
         MD5 md5 = new MD5CryptoServiceProvider();
         md5.TransformBlock(client_key, 0, client_key.Length, client_key, 0);
         md5.TransformBlock(clientrnd, 0, clientrnd.Length, clientrnd, 0);
         md5.TransformFinalBlock(serverrnd, 0, serverrnd.Length);
         client_key = new byte[definition.BulkExpandedSize];
         Buffer.BlockCopy(md5.Hash, 0, client_key, 0, client_key.Length);
         md5.Initialize();
         md5.TransformBlock(server_key, 0, server_key.Length, server_key, 0);
         md5.TransformBlock(serverrnd, 0, serverrnd.Length, serverrnd, 0);
         md5.TransformFinalBlock(clientrnd, 0, clientrnd.Length);
         server_key = new byte[definition.BulkExpandedSize];
         Buffer.BlockCopy(md5.Hash, 0, server_key, 0, server_key.Length);
         md5.Initialize();
         md5.TransformBlock(clientrnd, 0, clientrnd.Length, clientrnd, 0);
         md5.TransformFinalBlock(serverrnd, 0, serverrnd.Length);
         client_iv = new byte[definition.BulkIVSize];
         Buffer.BlockCopy(md5.Hash, 0, client_iv, 0, client_iv.Length);
         md5.Initialize();
         md5.TransformBlock(serverrnd, 0, serverrnd.Length, serverrnd, 0);
         md5.TransformFinalBlock(clientrnd, 0, clientrnd.Length);
         server_iv = new byte[definition.BulkIVSize];
         Buffer.BlockCopy(md5.Hash, 0, server_iv, 0, server_iv.Length);
         md5.Clear();
     }
     // generate the cipher objects
     if (entity == ConnectionEnd.Client) {
         ret.Encryptor = bulk.CreateEncryptor(client_key, client_iv);
         ret.Decryptor = bulk.CreateDecryptor(server_key, server_iv);
         ret.LocalHasher = new Ssl3RecordMAC(definition.HashAlgorithmType, client_mac);
         ret.RemoteHasher = new Ssl3RecordMAC(definition.HashAlgorithmType, server_mac);
     } else {
         ret.Encryptor = bulk.CreateEncryptor(server_key, server_iv);
         ret.Decryptor = bulk.CreateDecryptor(client_key, client_iv);
         ret.LocalHasher = new Ssl3RecordMAC(definition.HashAlgorithmType, server_mac);
         ret.RemoteHasher = new Ssl3RecordMAC(definition.HashAlgorithmType, client_mac);
     }
     // clear sensitive data
     Array.Clear(client_mac, 0, client_mac.Length);
     Array.Clear(server_mac, 0, server_mac.Length);
     Array.Clear(client_key, 0, client_key.Length);
     Array.Clear(server_key, 0, server_key.Length);
     Array.Clear(client_iv, 0, client_iv.Length);
     Array.Clear(server_iv, 0, server_iv.Length);
     return ret;
 }
        protected SslHandshakeStatus ProcessCertificateRequest(HandshakeMessage message)
        {
            if (m_State == HandshakeType.ServerKeyExchange)
            {
                CipherDefinition cd = CipherSuites.GetCipherDefinition(m_EncryptionScheme);
                if (this.m_RemoteCertificate.GetPublicKeyLength() <= 512 || !cd.Exportable)
                {
                    throw new SslException(AlertDescription.HandshakeFailure, "Invalid message.");
                }
            }
            else if (m_State != HandshakeType.Certificate)
            {
                throw new SslException(AlertDescription.UnexpectedMessage, "CertificateRequest message must be preceded by a Certificate or ServerKeyExchange message.");
            }
            UpdateHashes(message, HashUpdate.All);             // input message
            // get supported certificate types
            bool supportsRsaCerts = false;

            byte[] certTypes = new byte[message.fragment[0]];             // currently we're not doing anything with the supported certificate types
            Buffer.BlockCopy(message.fragment, 1, certTypes, 0, certTypes.Length);
            for (int i = 0; i < certTypes.Length; i++)
            {
                if (certTypes[i] == 1)                   // rsa_sign
                {
                    supportsRsaCerts = true;
                    break;
                }
            }
            // get list of distinguished names
            if (m_Options.RequestHandler != null && supportsRsaCerts)               // make sure the client passed a delegate
            {
                Queue q = new Queue();
                DistinguishedNameList r = new DistinguishedNameList();
                int    size, offset = message.fragment[0] + 3;
                byte[] buffer;
                while (offset < message.fragment.Length)
                {
                    size   = message.fragment[offset] * 256 + message.fragment[offset + 1];
                    buffer = new byte[size];
                    Buffer.BlockCopy(message.fragment, offset + 2, buffer, 0, size);
                    q.Enqueue(buffer);
                    offset += size + 2;
                }
                // decode RDN structures
                while (q.Count > 0)
                {
                    r.Add(ProcessName((byte[])q.Dequeue()));
                }
                RequestEventArgs e = new RequestEventArgs();
                try {
                    m_Options.RequestHandler(Parent, r, e);
                    if (e.Certificate != null)
                    {
                        m_Options.Certificate = e.Certificate;
                    }
                } catch (Exception de) {
                    throw new SslException(de, AlertDescription.InternalError, "The code in the CertRequestEventHandler delegate threw an error.");
                }
            }
            if (!supportsRsaCerts)
            {
                m_Options.Certificate = null;                 // do not send client certificate
            }
            m_MutualAuthentication = true;
            return(new SslHandshakeStatus(SslStatus.MessageIncomplete, null));
        }