示例#1
0
        private void HandleSpecificPacket(KexDHInit packet)
        {
            m_Logger.LogDebug("Received KexDHInit");

            if ((m_PendingExchangeContext == null) || (m_PendingExchangeContext.KexAlgorithm == null))
            {
                throw new SSHServerException(DisconnectReason.SSH_DISCONNECT_PROTOCOL_ERROR, "Server did not receive SSH_MSG_KEX_INIT as expected.");
            }

            // 1. C generates a random number x (1 < x < q) and computes e = g ^ x mod p.  C sends e to S.
            // 2. S receives e.  It computes K = e^y mod p
            byte[] sharedSecret = m_PendingExchangeContext.KexAlgorithm.DecryptKeyExchange(packet.ClientValue);

            // 2. S generates a random number y (0 < y < q) and computes f = g ^ y mod p.
            byte[] serverKeyExchange = m_PendingExchangeContext.KexAlgorithm.CreateKeyExchange();

            byte[] hostKey = m_PendingExchangeContext.HostKeyAlgorithm.CreateKeyAndCertificatesData();

            // H = hash(V_C || V_S || I_C || I_S || K_S || e || f || K)
            byte[] exchangeHash = ComputeExchangeHash(
                m_PendingExchangeContext.KexAlgorithm,
                hostKey,
                packet.ClientValue,
                serverKeyExchange,
                sharedSecret);

            if (m_SessionId == null)
            {
                m_SessionId = exchangeHash;
            }

            // https://tools.ietf.org/html/rfc4253#section-7.2

            // Initial IV client to server: HASH(K || H || "A" || session_id)
            // (Here K is encoded as mpint and "A" as byte and session_id as raw
            // data.  "A" means the single character A, ASCII 65).
            byte[] clientCipherIV = ComputeEncryptionKey(
                m_PendingExchangeContext.KexAlgorithm,
                exchangeHash,
                m_PendingExchangeContext.CipherClientToServer.BlockSize,
                sharedSecret, 'A');

            // Initial IV server to client: HASH(K || H || "B" || session_id)
            byte[] serverCipherIV = ComputeEncryptionKey(
                m_PendingExchangeContext.KexAlgorithm,
                exchangeHash,
                m_PendingExchangeContext.CipherServerToClient.BlockSize,
                sharedSecret, 'B');

            // Encryption key client to server: HASH(K || H || "C" || session_id)
            byte[] clientCipherKey = ComputeEncryptionKey(
                m_PendingExchangeContext.KexAlgorithm,
                exchangeHash,
                m_PendingExchangeContext.CipherClientToServer.KeySize,
                sharedSecret, 'C');

            // Encryption key server to client: HASH(K || H || "D" || session_id)
            byte[] serverCipherKey = ComputeEncryptionKey(
                m_PendingExchangeContext.KexAlgorithm,
                exchangeHash,
                m_PendingExchangeContext.CipherServerToClient.KeySize,
                sharedSecret, 'D');

            // Integrity key client to server: HASH(K || H || "E" || session_id)
            byte[] clientHmacKey = ComputeEncryptionKey(
                m_PendingExchangeContext.KexAlgorithm,
                exchangeHash,
                m_PendingExchangeContext.MACAlgorithmClientToServer.KeySize,
                sharedSecret, 'E');

            // Integrity key server to client: HASH(K || H || "F" || session_id)
            byte[] serverHmacKey = ComputeEncryptionKey(
                m_PendingExchangeContext.KexAlgorithm,
                exchangeHash,
                m_PendingExchangeContext.MACAlgorithmServerToClient.KeySize,
                sharedSecret, 'F');

            // Set all keys we just generated
            m_PendingExchangeContext.CipherClientToServer.SetKey(clientCipherKey, clientCipherIV);
            m_PendingExchangeContext.CipherServerToClient.SetKey(serverCipherKey, serverCipherIV);
            m_PendingExchangeContext.MACAlgorithmClientToServer.SetKey(clientHmacKey);
            m_PendingExchangeContext.MACAlgorithmServerToClient.SetKey(serverHmacKey);

            // Send reply to client!
            KexDHReply reply = new KexDHReply()
            {
                ServerHostKey = hostKey,
                ServerValue   = serverKeyExchange,
                Signature     = m_PendingExchangeContext.HostKeyAlgorithm.CreateSignatureData(exchangeHash)
            };

            Send(reply);
            Send(new NewKeys());
        }
示例#2
0
        private void HandleSpecificPacket(KexDHInit packet)
        {
            logger.LogDebug("Processing KexDHInit packet.");

            if ((pendingExchangeContext == null) || (pendingExchangeContext.KexAlgorithm == null))
            {
                throw new SwishServerException(DisconnectReason.SSH_DISCONNECT_PROTOCOL_ERROR, "Server did not receive SSH_MSG_KEX_INIT as expected.");
            }

            // Set the host key
            // TODO - better handling of missing config
            var hostKeyAlgoName = pendingExchangeContext.HostKeyAlgorithm.Name;

            if (!settings.HostKeyPaths.ContainsKey(hostKeyAlgoName))
            {
                throw new Exception(string.Format("HostKey path for algo '{0}' not found in configuration.", hostKeyAlgoName));
            }

            pendingExchangeContext.HostKeyAlgorithm.ImportKeyFromFile(settings.HostKeyPaths[hostKeyAlgoName]);

            // 1. C generates a random number x (1 &lt x &lt q) and computes e = g ^ x mod p.  C sends e to S.
            // 2. S receives e.  It computes K = e^y mod p
            byte[] sharedSecret = pendingExchangeContext.KexAlgorithm.DecryptKeyExchange(packet.ClientValue);

            // 2. S generates a random number y (0 < y < q) and computes f = g ^ y mod p.
            byte[] serverKeyExchange = pendingExchangeContext.KexAlgorithm.CreateKeyExchange();

            byte[] hostKey = pendingExchangeContext.HostKeyAlgorithm.CreateKeyAndCertificatesData();

            // H = hash(V_C || V_S || I_C || I_S || K_S || e || f || K)
            byte[] exchangeHash = ComputeExchangeHash(
                pendingExchangeContext.KexAlgorithm,
                hostKey,
                packet.ClientValue,
                serverKeyExchange,
                sharedSecret);

            if (sessionId == null)
            {
                sessionId = exchangeHash;
            }

            // https://tools.ietf.org/html/rfc4253#section-7.2

            // Initial IV client to server: HASH(K || H || "A" || session_id)
            // (Here K is encoded as mpint and "A" as byte and session_id as raw
            // data.  "A" means the single character A, ASCII 65).
            byte[] clientCipherIV = ComputeEncryptionKey(
                pendingExchangeContext.KexAlgorithm,
                exchangeHash,
                pendingExchangeContext.CipherClientToServer.BlockSize,
                sharedSecret, 'A');

            // Initial IV server to client: HASH(K || H || "B" || session_id)
            byte[] serverCipherIV = ComputeEncryptionKey(
                pendingExchangeContext.KexAlgorithm,
                exchangeHash,
                pendingExchangeContext.CipherServerToClient.BlockSize,
                sharedSecret, 'B');

            // Encryption key client to server: HASH(K || H || "C" || session_id)
            byte[] clientCipherKey = ComputeEncryptionKey(
                pendingExchangeContext.KexAlgorithm,
                exchangeHash,
                pendingExchangeContext.CipherClientToServer.KeySize,
                sharedSecret, 'C');

            // Encryption key server to client: HASH(K || H || "D" || session_id)
            byte[] serverCipherKey = ComputeEncryptionKey(
                pendingExchangeContext.KexAlgorithm,
                exchangeHash,
                pendingExchangeContext.CipherServerToClient.KeySize,
                sharedSecret, 'D');

            // Integrity key client to server: HASH(K || H || "E" || session_id)
            byte[] clientHmacKey = ComputeEncryptionKey(
                pendingExchangeContext.KexAlgorithm,
                exchangeHash,
                pendingExchangeContext.MACAlgorithmClientToServer.KeySize,
                sharedSecret, 'E');

            // Integrity key server to client: HASH(K || H || "F" || session_id)
            byte[] serverHmacKey = ComputeEncryptionKey(
                pendingExchangeContext.KexAlgorithm,
                exchangeHash,
                pendingExchangeContext.MACAlgorithmServerToClient.KeySize,
                sharedSecret, 'F');

            // Set all keys we just generated
            pendingExchangeContext.CipherClientToServer.SetKey(clientCipherKey, clientCipherIV);
            pendingExchangeContext.CipherServerToClient.SetKey(serverCipherKey, serverCipherIV);
            pendingExchangeContext.MACAlgorithmClientToServer.SetKey(clientHmacKey);
            pendingExchangeContext.MACAlgorithmServerToClient.SetKey(serverHmacKey);

            // Send reply to client!
            var reply = new KexDHReply
            {
                ServerHostKey = hostKey,
                ServerValue   = serverKeyExchange,
                Signature     = pendingExchangeContext.HostKeyAlgorithm.CreateSignatureData(exchangeHash)
            };

            Send(reply);
            Send(new NewKeys());
        }