// --------------------------------------------------------------------------
inline
void
client_key_exchange::process_dh (
 CryptoPP::SecByteBlock& premaster
)
// --------------------------------------------------------------------------
{
  CryptoPP::SimpleKeyAgreementDomain*& alg = m_handshake.m_key_algo;
  size_t pos;

  // Add leading zeros to match domain's public key length.
  if (m_pub.size() < alg->PublicKeyLength())
  {
    CryptoPP::SecByteBlock padding;

    padding.CleanNew(alg->PublicKeyLength() - m_pub.size());
    m_pub = padding + m_pub;
  }
  
  // Agree on the premaster secret.
  premaster.New(alg->AgreedValueLength());

  if (!alg->Agree(premaster, m_handshake.m_key_value, m_pub, true))
  {
    LOG_ERR("net.tls.client_key_exchange",
     "Error agreeing on pre-master secret. (DH)"
    );
    
    throw alert(
     alert_level::fatal,
     alert_description::illegal_parameter
    );
  }

  // Strip any leading zero bytes from the agreed value.
  pos = 0;

  while (premaster[pos] == 0 && pos < premaster.size())
  {
    ++pos;
  }

  premaster.Assign(&premaster[pos], (premaster.size() - pos));
}
// --------------------------------------------------------------------------
inline
void
client_key_exchange::process_ecdh (
 CryptoPP::SecByteBlock& premaster
)
// --------------------------------------------------------------------------
{
  CryptoPP::SimpleKeyAgreementDomain*& alg = m_handshake.m_key_algo;

  // Agree on the premaster secret.
  premaster.New(alg->AgreedValueLength());

  if (!alg->Agree(premaster, m_handshake.m_key_value, m_pub, true))
  {
    LOG_ERR("net.tls.client_key_exchange",
     "Error agreeing on pre-master secret. (ECDH)"
    );
    
    throw alert(
     alert_level::fatal,
     alert_description::illegal_parameter
    );
  }
}