1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 06:57:45 +00:00

LibTLS: Define cipher suite parameters and components in a macro

Instead of sprinkling the definition of the ciper suites all over the
TLS implementation, let's regroup it all once and for all in a single
place, and then add our new implementations there.
This commit is contained in:
DexesTTP 2021-05-17 22:34:03 +02:00 committed by Andreas Kling
parent 17a1f51579
commit 6d190b299e
2 changed files with 84 additions and 56 deletions

View file

@ -42,6 +42,31 @@ enum class SignatureAlgorithm : u8 {
ECDSA = 3, ECDSA = 3,
}; };
enum class CipherAlgorithm {
AES_128_CBC,
AES_128_GCM,
AES_128_CCM,
AES_128_CCM_8,
AES_256_CBC,
AES_256_GCM,
};
constexpr size_t cipher_key_size(CipherAlgorithm algorithm)
{
switch (algorithm) {
case CipherAlgorithm::AES_128_CBC:
case CipherAlgorithm::AES_128_GCM:
case CipherAlgorithm::AES_128_CCM:
case CipherAlgorithm::AES_128_CCM_8:
return 128;
case CipherAlgorithm::AES_256_CBC:
case CipherAlgorithm::AES_256_GCM:
return 256;
default:
return 128;
}
}
struct SignatureAndHashAlgorithm { struct SignatureAndHashAlgorithm {
HashAlgorithm hash; HashAlgorithm hash;
SignatureAlgorithm signature; SignatureAlgorithm signature;

View file

@ -163,18 +163,39 @@ enum ClientVerificationStaus {
VerificationNeeded, VerificationNeeded,
}; };
// Note for the 16 iv length instead of 8:
// 4 bytes of fixed IV, 8 random (nonce) bytes, 4 bytes for counter
// 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(false, CipherSuite::AES_128_GCM_SHA256, SignatureAlgorithm::Anonymous, CipherAlgorithm::AES_128_GCM, Crypto::Hash::SHA256, 8, true) \
C(false, CipherSuite::AES_256_GCM_SHA384, SignatureAlgorithm::Anonymous, CipherAlgorithm::AES_256_GCM, Crypto::Hash::SHA384, 8, true) \
C(false, CipherSuite::AES_128_CCM_SHA256, SignatureAlgorithm::Anonymous, CipherAlgorithm::AES_128_CCM, Crypto::Hash::SHA256, 16, false) \
C(false, CipherSuite::AES_128_CCM_8_SHA256, SignatureAlgorithm::Anonymous, CipherAlgorithm::AES_128_CCM_8, Crypto::Hash::SHA256, 16, false) \
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(false, CipherSuite::RSA_WITH_AES_256_GCM_SHA384, SignatureAlgorithm::RSA, CipherAlgorithm::AES_256_GCM, Crypto::Hash::SHA384, 8, true)
struct Options { struct Options {
static Vector<CipherSuite> default_usable_cipher_suites()
{
Vector<CipherSuite> cipher_suites;
#define C(is_supported, suite, signature, cipher, hash, iv_size, is_aead) \
if constexpr (is_supported) \
cipher_suites.empend(suite);
ENUMERATE_CIPHERS(C)
#undef C
return cipher_suites;
}
Vector<CipherSuite> usable_cipher_suites = default_usable_cipher_suites();
#define OPTION_WITH_DEFAULTS(typ, name, ...) \ #define OPTION_WITH_DEFAULTS(typ, name, ...) \
static typ default_##name() { return typ { __VA_ARGS__ }; } \ static typ default_##name() { return typ { __VA_ARGS__ }; } \
typ name = default_##name(); typ name = default_##name();
OPTION_WITH_DEFAULTS(Vector<CipherSuite>, usable_cipher_suites,
CipherSuite::RSA_WITH_AES_128_CBC_SHA256,
CipherSuite::RSA_WITH_AES_256_CBC_SHA256,
CipherSuite::RSA_WITH_AES_128_CBC_SHA,
CipherSuite::RSA_WITH_AES_256_CBC_SHA,
CipherSuite::RSA_WITH_AES_128_GCM_SHA256)
OPTION_WITH_DEFAULTS(Version, version, Version::V12) OPTION_WITH_DEFAULTS(Version, version, Version::V12)
OPTION_WITH_DEFAULTS(Vector<SignatureAndHashAlgorithm>, supported_signature_algorithms, OPTION_WITH_DEFAULTS(Vector<SignatureAndHashAlgorithm>, supported_signature_algorithms,
{ HashAlgorithm::SHA512, SignatureAlgorithm::RSA }, { HashAlgorithm::SHA512, SignatureAlgorithm::RSA },
@ -297,11 +318,15 @@ public:
bool supports_cipher(CipherSuite suite) const bool supports_cipher(CipherSuite suite) const
{ {
return suite == CipherSuite::RSA_WITH_AES_128_CBC_SHA256 switch (suite) {
|| suite == CipherSuite::RSA_WITH_AES_256_CBC_SHA256 #define C(is_supported, suite, signature, cipher, hash, iv_size, is_aead) \
|| suite == CipherSuite::RSA_WITH_AES_128_CBC_SHA case suite: \
|| suite == CipherSuite::RSA_WITH_AES_256_CBC_SHA return is_supported;
|| suite == CipherSuite::RSA_WITH_AES_128_GCM_SHA256; ENUMERATE_CIPHERS(C)
#undef C
default:
return false;
}
} }
bool supports_version(Version v) const bool supports_version(Version v) const
@ -376,72 +401,50 @@ private:
size_t key_length() const size_t key_length() const
{ {
switch (m_context.cipher) { switch (m_context.cipher) {
case CipherSuite::AES_128_CCM_8_SHA256: #define C(is_supported, suite, signature, cipher, hash, iv_size, is_aead) \
case CipherSuite::AES_128_CCM_SHA256: case suite: \
case CipherSuite::AES_128_GCM_SHA256: return cipher_key_size(cipher) / 8;
case CipherSuite::Invalid: ENUMERATE_CIPHERS(C)
case CipherSuite::RSA_WITH_AES_128_CBC_SHA256: #undef C
case CipherSuite::RSA_WITH_AES_128_CBC_SHA:
case CipherSuite::RSA_WITH_AES_128_GCM_SHA256:
default: default:
return 128 / 8; return 128 / 8;
case CipherSuite::AES_256_GCM_SHA384:
case CipherSuite::RSA_WITH_AES_256_CBC_SHA:
case CipherSuite::RSA_WITH_AES_256_CBC_SHA256:
case CipherSuite::RSA_WITH_AES_256_GCM_SHA384:
return 256 / 8;
} }
} }
size_t mac_length() const size_t mac_length() const
{ {
switch (m_context.cipher) { switch (m_context.cipher) {
case CipherSuite::RSA_WITH_AES_128_CBC_SHA: #define C(is_supported, suite, signature, cipher, hash, iv_size, is_aead) \
case CipherSuite::RSA_WITH_AES_256_CBC_SHA: case suite: \
return Crypto::Hash::SHA1::digest_size(); return hash ::digest_size();
case CipherSuite::AES_256_GCM_SHA384: ENUMERATE_CIPHERS(C)
case CipherSuite::RSA_WITH_AES_256_GCM_SHA384: #undef C
return Crypto::Hash::SHA512::digest_size();
case CipherSuite::AES_128_CCM_8_SHA256:
case CipherSuite::AES_128_CCM_SHA256:
case CipherSuite::AES_128_GCM_SHA256:
case CipherSuite::Invalid:
case CipherSuite::RSA_WITH_AES_128_CBC_SHA256:
case CipherSuite::RSA_WITH_AES_128_GCM_SHA256:
case CipherSuite::RSA_WITH_AES_256_CBC_SHA256:
default: default:
return Crypto::Hash::SHA256::digest_size(); return Crypto::Hash::SHA256::digest_size();
} }
} }
size_t iv_length() const size_t iv_length() const
{ {
switch (m_context.cipher) { switch (m_context.cipher) {
case CipherSuite::AES_128_CCM_8_SHA256: #define C(is_supported, suite, signature, cipher, hash, iv_size, is_aead) \
case CipherSuite::AES_128_CCM_SHA256: case suite: \
case CipherSuite::Invalid: return iv_size;
case CipherSuite::RSA_WITH_AES_128_CBC_SHA256: ENUMERATE_CIPHERS(C)
case CipherSuite::RSA_WITH_AES_128_CBC_SHA: #undef C
case CipherSuite::RSA_WITH_AES_256_CBC_SHA256:
case CipherSuite::RSA_WITH_AES_256_CBC_SHA:
default: default:
return 16; return 16;
case CipherSuite::AES_128_GCM_SHA256:
case CipherSuite::AES_256_GCM_SHA384:
case CipherSuite::RSA_WITH_AES_128_GCM_SHA256:
case CipherSuite::RSA_WITH_AES_256_GCM_SHA384:
return 8; // 4 bytes of fixed IV, 8 random (nonce) bytes, 4 bytes for counter
// GCM specifically asks us to transmit only the nonce, the counter is zero
// and the fixed IV is derived from the premaster key.
} }
} }
bool is_aead() const bool is_aead() const
{ {
switch (m_context.cipher) { switch (m_context.cipher) {
case CipherSuite::AES_128_GCM_SHA256: #define C(is_supported, suite, signature, cipher, hash, iv_size, is_aead) \
case CipherSuite::AES_256_GCM_SHA384: case suite: \
case CipherSuite::RSA_WITH_AES_128_GCM_SHA256: return is_aead;
case CipherSuite::RSA_WITH_AES_256_GCM_SHA384: ENUMERATE_CIPHERS(C)
return true; #undef C
default: default:
return false; return false;
} }