mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 05:47:35 +00:00
LibTLS: Use a more precise KeyExchangeAlgorithm enum
The old enumeration didn't allow discriminating the key exchange algorithms used, but only allowed the handshake with the server. With this new enumeration, we can know which key exchange algorithm we are actually supposed to use :^)
This commit is contained in:
parent
dd35aa7725
commit
cb4a0dec8a
4 changed files with 116 additions and 47 deletions
|
@ -105,6 +105,49 @@ struct SignatureAndHashAlgorithm {
|
||||||
SignatureAlgorithm signature;
|
SignatureAlgorithm signature;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class KeyExchangeAlgorithm {
|
||||||
|
Invalid,
|
||||||
|
// Defined in RFC 5246 section 7.4.2 / RFC 4279 section 4
|
||||||
|
RSA_PSK,
|
||||||
|
// Defined in RFC 5246 section 7.4.3
|
||||||
|
DHE_DSS,
|
||||||
|
DHE_RSA,
|
||||||
|
DH_anon,
|
||||||
|
RSA,
|
||||||
|
DH_DSS,
|
||||||
|
DH_RSA,
|
||||||
|
// Defined in RFC 4492 section 2
|
||||||
|
ECDHE_RSA,
|
||||||
|
ECDH_ECDSA,
|
||||||
|
ECDH_RSA,
|
||||||
|
ECDHE_ECDSA,
|
||||||
|
ECDH_anon,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Defined in RFC 5246 section 7.4.1.4.1
|
||||||
|
constexpr SignatureAlgorithm signature_for_key_exchange_algorithm(KeyExchangeAlgorithm algorithm)
|
||||||
|
{
|
||||||
|
switch (algorithm) {
|
||||||
|
case KeyExchangeAlgorithm::RSA:
|
||||||
|
case KeyExchangeAlgorithm::DHE_RSA:
|
||||||
|
case KeyExchangeAlgorithm::DH_RSA:
|
||||||
|
case KeyExchangeAlgorithm::RSA_PSK:
|
||||||
|
case KeyExchangeAlgorithm::ECDH_RSA:
|
||||||
|
case KeyExchangeAlgorithm::ECDHE_RSA:
|
||||||
|
return SignatureAlgorithm::RSA;
|
||||||
|
case KeyExchangeAlgorithm::DHE_DSS:
|
||||||
|
case KeyExchangeAlgorithm::DH_DSS:
|
||||||
|
return SignatureAlgorithm::DSA;
|
||||||
|
case KeyExchangeAlgorithm::ECDH_ECDSA:
|
||||||
|
case KeyExchangeAlgorithm::ECDHE_ECDSA:
|
||||||
|
return SignatureAlgorithm::ECDSA;
|
||||||
|
case KeyExchangeAlgorithm::DH_anon:
|
||||||
|
case KeyExchangeAlgorithm::ECDH_anon:
|
||||||
|
default:
|
||||||
|
return SignatureAlgorithm::Anonymous;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
enum class CipherAlgorithm {
|
enum class CipherAlgorithm {
|
||||||
Invalid,
|
Invalid,
|
||||||
AES_128_CBC,
|
AES_128_CBC,
|
||||||
|
|
|
@ -283,24 +283,37 @@ ByteBuffer TLSv12::build_client_key_exchange()
|
||||||
PacketBuilder builder { MessageType::Handshake, m_context.options.version };
|
PacketBuilder builder { MessageType::Handshake, m_context.options.version };
|
||||||
builder.append((u8)HandshakeType::ClientKeyExchange);
|
builder.append((u8)HandshakeType::ClientKeyExchange);
|
||||||
|
|
||||||
switch (get_signature_algorithm(m_context.cipher)) {
|
switch (get_key_exchange_algorithm(m_context.cipher)) {
|
||||||
case SignatureAlgorithm::Anonymous:
|
case KeyExchangeAlgorithm::RSA:
|
||||||
dbgln("Client key exchange for Anonymous signature is not implemented");
|
|
||||||
TODO();
|
|
||||||
break;
|
|
||||||
case SignatureAlgorithm::RSA:
|
|
||||||
build_rsa_pre_master_secret(builder);
|
build_rsa_pre_master_secret(builder);
|
||||||
break;
|
break;
|
||||||
case SignatureAlgorithm::DSA:
|
case KeyExchangeAlgorithm::DHE_DSS:
|
||||||
dbgln("Client key exchange for DSA signature is not implemented");
|
dbgln("Client key exchange for DHE_DSS is not implemented");
|
||||||
TODO();
|
TODO();
|
||||||
break;
|
break;
|
||||||
case SignatureAlgorithm::ECDSA:
|
case KeyExchangeAlgorithm::DH_DSS:
|
||||||
dbgln("Client key exchange for ECDSA signature is not implemented");
|
case KeyExchangeAlgorithm::DH_RSA:
|
||||||
|
dbgln("Client key exchange for DH algorithms is not implemented");
|
||||||
|
TODO();
|
||||||
|
break;
|
||||||
|
case KeyExchangeAlgorithm::DHE_RSA:
|
||||||
|
dbgln("Client key exchange for DHE_RSA is not implemented");
|
||||||
|
TODO();
|
||||||
|
break;
|
||||||
|
case KeyExchangeAlgorithm::DH_anon:
|
||||||
|
dbgln("Client key exchange for DH_anon is not implemented");
|
||||||
|
TODO();
|
||||||
|
break;
|
||||||
|
case KeyExchangeAlgorithm::ECDHE_RSA:
|
||||||
|
case KeyExchangeAlgorithm::ECDH_ECDSA:
|
||||||
|
case KeyExchangeAlgorithm::ECDH_RSA:
|
||||||
|
case KeyExchangeAlgorithm::ECDHE_ECDSA:
|
||||||
|
case KeyExchangeAlgorithm::ECDH_anon:
|
||||||
|
dbgln("Client key exchange for ECDHE algorithms is not implemented");
|
||||||
TODO();
|
TODO();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dbgln("Unknonwn client key exchange signature algorithm");
|
dbgln("Unknonwn client key exchange algorithm");
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -201,23 +201,36 @@ ByteBuffer TLSv12::build_server_key_exchange()
|
||||||
|
|
||||||
ssize_t TLSv12::handle_server_key_exchange(ReadonlyBytes)
|
ssize_t TLSv12::handle_server_key_exchange(ReadonlyBytes)
|
||||||
{
|
{
|
||||||
switch (get_signature_algorithm(m_context.cipher)) {
|
switch (get_key_exchange_algorithm(m_context.cipher)) {
|
||||||
case SignatureAlgorithm::Anonymous:
|
case KeyExchangeAlgorithm::RSA:
|
||||||
dbgln("Client key exchange for Anonymous signature is not implemented");
|
case KeyExchangeAlgorithm::DH_DSS:
|
||||||
TODO();
|
case KeyExchangeAlgorithm::DH_RSA:
|
||||||
break;
|
|
||||||
case SignatureAlgorithm::RSA:
|
|
||||||
case SignatureAlgorithm::DSA:
|
|
||||||
// RFC 5246 section 7.4.3. Server Key Exchange Message
|
// RFC 5246 section 7.4.3. Server Key Exchange Message
|
||||||
// It is not legal to send the server key exchange message for RSA, DH_DSS, DH_RSA
|
// It is not legal to send the server key exchange message for RSA, DH_DSS, DH_RSA
|
||||||
dbgln("Server key exchange received for RSA or DSA is not legal");
|
dbgln("Server key exchange received for RSA, DH_DSS or DH_RSA is not legal");
|
||||||
return (i8)Error::UnexpectedMessage;
|
return (i8)Error::UnexpectedMessage;
|
||||||
case SignatureAlgorithm::ECDSA:
|
case KeyExchangeAlgorithm::DHE_DSS:
|
||||||
dbgln("Client key exchange for ECDSA signature is not implemented");
|
dbgln("Server key exchange for DHE_DSS is not implemented");
|
||||||
|
TODO();
|
||||||
|
break;
|
||||||
|
case KeyExchangeAlgorithm::DHE_RSA:
|
||||||
|
dbgln("Server key exchange for DHE_RSA is not implemented");
|
||||||
|
TODO();
|
||||||
|
break;
|
||||||
|
case KeyExchangeAlgorithm::DH_anon:
|
||||||
|
dbgln("Server key exchange for DH_anon is not implemented");
|
||||||
|
TODO();
|
||||||
|
break;
|
||||||
|
case KeyExchangeAlgorithm::ECDHE_RSA:
|
||||||
|
case KeyExchangeAlgorithm::ECDH_ECDSA:
|
||||||
|
case KeyExchangeAlgorithm::ECDH_RSA:
|
||||||
|
case KeyExchangeAlgorithm::ECDHE_ECDSA:
|
||||||
|
case KeyExchangeAlgorithm::ECDH_anon:
|
||||||
|
dbgln("Server key exchange for ECDHE algorithms is not implemented");
|
||||||
TODO();
|
TODO();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dbgln("Unknonwn client key exchange signature algorithm");
|
dbgln("Unknonwn server key exchange algorithm");
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -168,31 +168,31 @@ enum ClientVerificationStaus {
|
||||||
// GCM specifically asks us to transmit only the nonce, the counter is zero
|
// GCM specifically asks us to transmit only the nonce, the counter is zero
|
||||||
// and the fixed IV is derived from the premaster key.
|
// and the fixed IV is derived from the premaster key.
|
||||||
#define ENUMERATE_CIPHERS(C) \
|
#define ENUMERATE_CIPHERS(C) \
|
||||||
C(true, CipherSuite::RSA_WITH_AES_128_CBC_SHA, SignatureAlgorithm::RSA, CipherAlgorithm::AES_128_CBC, Crypto::Hash::SHA1, 16, false) \
|
C(true, CipherSuite::RSA_WITH_AES_128_CBC_SHA, KeyExchangeAlgorithm::RSA, CipherAlgorithm::AES_128_CBC, Crypto::Hash::SHA1, 16, false) \
|
||||||
C(true, CipherSuite::RSA_WITH_AES_256_CBC_SHA, SignatureAlgorithm::RSA, CipherAlgorithm::AES_256_CBC, Crypto::Hash::SHA1, 16, false) \
|
C(true, CipherSuite::RSA_WITH_AES_256_CBC_SHA, KeyExchangeAlgorithm::RSA, CipherAlgorithm::AES_256_CBC, Crypto::Hash::SHA1, 16, false) \
|
||||||
C(true, CipherSuite::RSA_WITH_AES_128_CBC_SHA256, SignatureAlgorithm::RSA, CipherAlgorithm::AES_128_CBC, Crypto::Hash::SHA256, 16, false) \
|
C(true, CipherSuite::RSA_WITH_AES_128_CBC_SHA256, KeyExchangeAlgorithm::RSA, CipherAlgorithm::AES_128_CBC, Crypto::Hash::SHA256, 16, false) \
|
||||||
C(true, CipherSuite::RSA_WITH_AES_256_CBC_SHA256, SignatureAlgorithm::RSA, CipherAlgorithm::AES_256_CBC, Crypto::Hash::SHA256, 16, false) \
|
C(true, CipherSuite::RSA_WITH_AES_256_CBC_SHA256, KeyExchangeAlgorithm::RSA, CipherAlgorithm::AES_256_CBC, Crypto::Hash::SHA256, 16, false) \
|
||||||
C(true, CipherSuite::RSA_WITH_AES_128_GCM_SHA256, SignatureAlgorithm::RSA, CipherAlgorithm::AES_128_GCM, Crypto::Hash::SHA256, 8, true) \
|
C(true, CipherSuite::RSA_WITH_AES_128_GCM_SHA256, KeyExchangeAlgorithm::RSA, CipherAlgorithm::AES_128_GCM, Crypto::Hash::SHA256, 8, true) \
|
||||||
C(true, CipherSuite::RSA_WITH_AES_256_GCM_SHA384, SignatureAlgorithm::RSA, CipherAlgorithm::AES_256_GCM, Crypto::Hash::SHA384, 8, true)
|
C(true, CipherSuite::RSA_WITH_AES_256_GCM_SHA384, KeyExchangeAlgorithm::RSA, CipherAlgorithm::AES_256_GCM, Crypto::Hash::SHA384, 8, true)
|
||||||
|
|
||||||
constexpr SignatureAlgorithm get_signature_algorithm(CipherSuite suite)
|
constexpr KeyExchangeAlgorithm get_key_exchange_algorithm(CipherSuite suite)
|
||||||
{
|
{
|
||||||
switch (suite) {
|
switch (suite) {
|
||||||
#define C(is_supported, suite, signature, cipher, hash, iv_size, is_aead) \
|
#define C(is_supported, suite, key_exchange, cipher, hash, iv_size, is_aead) \
|
||||||
case suite: \
|
case suite: \
|
||||||
return signature;
|
return key_exchange;
|
||||||
ENUMERATE_CIPHERS(C)
|
ENUMERATE_CIPHERS(C)
|
||||||
#undef C
|
#undef C
|
||||||
default:
|
default:
|
||||||
return SignatureAlgorithm::Anonymous;
|
return KeyExchangeAlgorithm::Invalid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr CipherAlgorithm get_cipher_algorithm(CipherSuite suite)
|
constexpr CipherAlgorithm get_cipher_algorithm(CipherSuite suite)
|
||||||
{
|
{
|
||||||
switch (suite) {
|
switch (suite) {
|
||||||
#define C(is_supported, suite, signature, cipher, hash, iv_size, is_aead) \
|
#define C(is_supported, suite, key_exchange, cipher, hash, iv_size, is_aead) \
|
||||||
case suite: \
|
case suite: \
|
||||||
return cipher;
|
return cipher;
|
||||||
ENUMERATE_CIPHERS(C)
|
ENUMERATE_CIPHERS(C)
|
||||||
#undef C
|
#undef C
|
||||||
|
@ -205,8 +205,8 @@ struct Options {
|
||||||
static Vector<CipherSuite> default_usable_cipher_suites()
|
static Vector<CipherSuite> default_usable_cipher_suites()
|
||||||
{
|
{
|
||||||
Vector<CipherSuite> cipher_suites;
|
Vector<CipherSuite> cipher_suites;
|
||||||
#define C(is_supported, suite, signature, cipher, hash, iv_size, is_aead) \
|
#define C(is_supported, suite, key_exchange, cipher, hash, iv_size, is_aead) \
|
||||||
if constexpr (is_supported) \
|
if constexpr (is_supported) \
|
||||||
cipher_suites.empend(suite);
|
cipher_suites.empend(suite);
|
||||||
ENUMERATE_CIPHERS(C)
|
ENUMERATE_CIPHERS(C)
|
||||||
#undef C
|
#undef C
|
||||||
|
@ -342,8 +342,8 @@ public:
|
||||||
bool supports_cipher(CipherSuite suite) const
|
bool supports_cipher(CipherSuite suite) const
|
||||||
{
|
{
|
||||||
switch (suite) {
|
switch (suite) {
|
||||||
#define C(is_supported, suite, signature, cipher, hash, iv_size, is_aead) \
|
#define C(is_supported, suite, key_exchange, cipher, hash, iv_size, is_aead) \
|
||||||
case suite: \
|
case suite: \
|
||||||
return is_supported;
|
return is_supported;
|
||||||
ENUMERATE_CIPHERS(C)
|
ENUMERATE_CIPHERS(C)
|
||||||
#undef C
|
#undef C
|
||||||
|
@ -424,8 +424,8 @@ private:
|
||||||
size_t key_length() const
|
size_t key_length() const
|
||||||
{
|
{
|
||||||
switch (m_context.cipher) {
|
switch (m_context.cipher) {
|
||||||
#define C(is_supported, suite, signature, cipher, hash, iv_size, is_aead) \
|
#define C(is_supported, suite, key_exchange, cipher, hash, iv_size, is_aead) \
|
||||||
case suite: \
|
case suite: \
|
||||||
return cipher_key_size(cipher) / 8;
|
return cipher_key_size(cipher) / 8;
|
||||||
ENUMERATE_CIPHERS(C)
|
ENUMERATE_CIPHERS(C)
|
||||||
#undef C
|
#undef C
|
||||||
|
@ -437,8 +437,8 @@ private:
|
||||||
size_t mac_length() const
|
size_t mac_length() const
|
||||||
{
|
{
|
||||||
switch (m_context.cipher) {
|
switch (m_context.cipher) {
|
||||||
#define C(is_supported, suite, signature, cipher, hash, iv_size, is_aead) \
|
#define C(is_supported, suite, key_exchange, cipher, hash, iv_size, is_aead) \
|
||||||
case suite: \
|
case suite: \
|
||||||
return hash ::digest_size();
|
return hash ::digest_size();
|
||||||
ENUMERATE_CIPHERS(C)
|
ENUMERATE_CIPHERS(C)
|
||||||
#undef C
|
#undef C
|
||||||
|
@ -450,8 +450,8 @@ private:
|
||||||
size_t iv_length() const
|
size_t iv_length() const
|
||||||
{
|
{
|
||||||
switch (m_context.cipher) {
|
switch (m_context.cipher) {
|
||||||
#define C(is_supported, suite, signature, cipher, hash, iv_size, is_aead) \
|
#define C(is_supported, suite, key_exchange, cipher, hash, iv_size, is_aead) \
|
||||||
case suite: \
|
case suite: \
|
||||||
return iv_size;
|
return iv_size;
|
||||||
ENUMERATE_CIPHERS(C)
|
ENUMERATE_CIPHERS(C)
|
||||||
#undef C
|
#undef C
|
||||||
|
@ -463,8 +463,8 @@ private:
|
||||||
bool is_aead() const
|
bool is_aead() const
|
||||||
{
|
{
|
||||||
switch (m_context.cipher) {
|
switch (m_context.cipher) {
|
||||||
#define C(is_supported, suite, signature, cipher, hash, iv_size, is_aead) \
|
#define C(is_supported, suite, key_exchange, cipher, hash, iv_size, is_aead) \
|
||||||
case suite: \
|
case suite: \
|
||||||
return is_aead;
|
return is_aead;
|
||||||
ENUMERATE_CIPHERS(C)
|
ENUMERATE_CIPHERS(C)
|
||||||
#undef C
|
#undef C
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue