diff --git a/Userland/Libraries/LibTLS/CipherSuite.h b/Userland/Libraries/LibTLS/CipherSuite.h index 76b8f7e3b4..1d5bf8bd48 100644 --- a/Userland/Libraries/LibTLS/CipherSuite.h +++ b/Userland/Libraries/LibTLS/CipherSuite.h @@ -105,6 +105,49 @@ struct SignatureAndHashAlgorithm { 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 { Invalid, AES_128_CBC, diff --git a/Userland/Libraries/LibTLS/HandshakeClient.cpp b/Userland/Libraries/LibTLS/HandshakeClient.cpp index e314878bbf..949121c891 100644 --- a/Userland/Libraries/LibTLS/HandshakeClient.cpp +++ b/Userland/Libraries/LibTLS/HandshakeClient.cpp @@ -283,24 +283,37 @@ ByteBuffer TLSv12::build_client_key_exchange() PacketBuilder builder { MessageType::Handshake, m_context.options.version }; builder.append((u8)HandshakeType::ClientKeyExchange); - switch (get_signature_algorithm(m_context.cipher)) { - case SignatureAlgorithm::Anonymous: - dbgln("Client key exchange for Anonymous signature is not implemented"); - TODO(); - break; - case SignatureAlgorithm::RSA: + switch (get_key_exchange_algorithm(m_context.cipher)) { + case KeyExchangeAlgorithm::RSA: build_rsa_pre_master_secret(builder); break; - case SignatureAlgorithm::DSA: - dbgln("Client key exchange for DSA signature is not implemented"); + case KeyExchangeAlgorithm::DHE_DSS: + dbgln("Client key exchange for DHE_DSS is not implemented"); TODO(); break; - case SignatureAlgorithm::ECDSA: - dbgln("Client key exchange for ECDSA signature is not implemented"); + case KeyExchangeAlgorithm::DH_DSS: + 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(); break; default: - dbgln("Unknonwn client key exchange signature algorithm"); + dbgln("Unknonwn client key exchange algorithm"); VERIFY_NOT_REACHED(); break; } diff --git a/Userland/Libraries/LibTLS/HandshakeServer.cpp b/Userland/Libraries/LibTLS/HandshakeServer.cpp index a834626743..66b615fdee 100644 --- a/Userland/Libraries/LibTLS/HandshakeServer.cpp +++ b/Userland/Libraries/LibTLS/HandshakeServer.cpp @@ -201,23 +201,36 @@ ByteBuffer TLSv12::build_server_key_exchange() ssize_t TLSv12::handle_server_key_exchange(ReadonlyBytes) { - switch (get_signature_algorithm(m_context.cipher)) { - case SignatureAlgorithm::Anonymous: - dbgln("Client key exchange for Anonymous signature is not implemented"); - TODO(); - break; - case SignatureAlgorithm::RSA: - case SignatureAlgorithm::DSA: + switch (get_key_exchange_algorithm(m_context.cipher)) { + case KeyExchangeAlgorithm::RSA: + case KeyExchangeAlgorithm::DH_DSS: + case KeyExchangeAlgorithm::DH_RSA: // 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 - 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; - case SignatureAlgorithm::ECDSA: - dbgln("Client key exchange for ECDSA signature is not implemented"); + case KeyExchangeAlgorithm::DHE_DSS: + 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(); break; default: - dbgln("Unknonwn client key exchange signature algorithm"); + dbgln("Unknonwn server key exchange algorithm"); VERIFY_NOT_REACHED(); break; } diff --git a/Userland/Libraries/LibTLS/TLSv12.h b/Userland/Libraries/LibTLS/TLSv12.h index d0c5645630..23f899ca54 100644 --- a/Userland/Libraries/LibTLS/TLSv12.h +++ b/Userland/Libraries/LibTLS/TLSv12.h @@ -168,31 +168,31 @@ enum ClientVerificationStaus { // GCM specifically asks us to transmit only the nonce, the counter is zero // and the fixed IV is derived from the premaster key. #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_256_CBC_SHA, SignatureAlgorithm::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_256_CBC_SHA256, SignatureAlgorithm::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_256_GCM_SHA384, SignatureAlgorithm::RSA, CipherAlgorithm::AES_256_GCM, Crypto::Hash::SHA384, 8, true) + 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, KeyExchangeAlgorithm::RSA, CipherAlgorithm::AES_256_CBC, Crypto::Hash::SHA1, 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, KeyExchangeAlgorithm::RSA, CipherAlgorithm::AES_256_CBC, Crypto::Hash::SHA256, 16, false) \ + 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, 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) { -#define C(is_supported, suite, signature, cipher, hash, iv_size, is_aead) \ - case suite: \ - return signature; +#define C(is_supported, suite, key_exchange, cipher, hash, iv_size, is_aead) \ + case suite: \ + return key_exchange; ENUMERATE_CIPHERS(C) #undef C default: - return SignatureAlgorithm::Anonymous; + return KeyExchangeAlgorithm::Invalid; } } constexpr CipherAlgorithm get_cipher_algorithm(CipherSuite suite) { switch (suite) { -#define C(is_supported, suite, signature, cipher, hash, iv_size, is_aead) \ - case suite: \ +#define C(is_supported, suite, key_exchange, cipher, hash, iv_size, is_aead) \ + case suite: \ return cipher; ENUMERATE_CIPHERS(C) #undef C @@ -205,8 +205,8 @@ struct Options { static Vector default_usable_cipher_suites() { Vector cipher_suites; -#define C(is_supported, suite, signature, cipher, hash, iv_size, is_aead) \ - if constexpr (is_supported) \ +#define C(is_supported, suite, key_exchange, cipher, hash, iv_size, is_aead) \ + if constexpr (is_supported) \ cipher_suites.empend(suite); ENUMERATE_CIPHERS(C) #undef C @@ -342,8 +342,8 @@ public: bool supports_cipher(CipherSuite suite) const { switch (suite) { -#define C(is_supported, suite, signature, cipher, hash, iv_size, is_aead) \ - case suite: \ +#define C(is_supported, suite, key_exchange, cipher, hash, iv_size, is_aead) \ + case suite: \ return is_supported; ENUMERATE_CIPHERS(C) #undef C @@ -424,8 +424,8 @@ private: size_t key_length() const { switch (m_context.cipher) { -#define C(is_supported, suite, signature, cipher, hash, iv_size, is_aead) \ - case suite: \ +#define C(is_supported, suite, key_exchange, cipher, hash, iv_size, is_aead) \ + case suite: \ return cipher_key_size(cipher) / 8; ENUMERATE_CIPHERS(C) #undef C @@ -437,8 +437,8 @@ private: size_t mac_length() const { switch (m_context.cipher) { -#define C(is_supported, suite, signature, cipher, hash, iv_size, is_aead) \ - case suite: \ +#define C(is_supported, suite, key_exchange, cipher, hash, iv_size, is_aead) \ + case suite: \ return hash ::digest_size(); ENUMERATE_CIPHERS(C) #undef C @@ -450,8 +450,8 @@ private: size_t iv_length() const { switch (m_context.cipher) { -#define C(is_supported, suite, signature, cipher, hash, iv_size, is_aead) \ - case suite: \ +#define C(is_supported, suite, key_exchange, cipher, hash, iv_size, is_aead) \ + case suite: \ return iv_size; ENUMERATE_CIPHERS(C) #undef C @@ -463,8 +463,8 @@ private: bool is_aead() const { switch (m_context.cipher) { -#define C(is_supported, suite, signature, cipher, hash, iv_size, is_aead) \ - case suite: \ +#define C(is_supported, suite, key_exchange, cipher, hash, iv_size, is_aead) \ + case suite: \ return is_aead; ENUMERATE_CIPHERS(C) #undef C