From dd104e839294fd8b8c6286deabefd60679f23743 Mon Sep 17 00:00:00 2001 From: Heiko Hund Date: Thu, 17 Jun 2021 20:42:39 +0200 Subject: [PATCH] make it possible to specify dc algorithms DCO only supports a limited set of ciphers, currently it is discovered quite late if a unsupported algorithm is configured (or pushed). This introduces CryptoAlgs::allow_dc_algs() with which the supported set of data channel algorithms can be specified. The DCO code makes use of this, at the time a new_controller() is created. Signed-off-by: Heiko Hund --- openvpn/client/cliopt.hpp | 12 ++++--- openvpn/crypto/cryptoalgs.hpp | 60 ++++++++++++++++++++++++----------- openvpn/dco/dcocli.hpp | 21 ++++++++++-- test/ssl/proto.cpp | 1 + 4 files changed, 68 insertions(+), 26 deletions(-) diff --git a/openvpn/client/cliopt.hpp b/openvpn/client/cliopt.hpp index 3e6fca93..ee5f57ef 100644 --- a/openvpn/client/cliopt.hpp +++ b/openvpn/client/cliopt.hpp @@ -207,6 +207,13 @@ namespace openvpn { ,extern_transport_factory(config.extern_transport_factory) #endif { + CryptoAlgs::allow_default_dc_algs(); + +#if (defined(ENABLE_KOVPN) || defined(ENABLE_OVPNDCO) || defined(ENABLE_OVPNDCOWIN)) && !defined(OPENVPN_FORCE_TUN_NULL) && !defined(OPENVPN_EXTERNAL_TUN_FACTORY) + if (config.dco) + dco = DCOTransport::new_controller(); +#endif + // parse general client options const ParseClientConfig pcc(opt); @@ -222,11 +229,6 @@ namespace openvpn { rng.reset(new SSLLib::RandomAPI(false)); prng.reset(new SSLLib::RandomAPI(true)); -#if (defined(ENABLE_KOVPN) || defined(ENABLE_OVPNDCO) || defined(ENABLE_OVPNDCOWIN)) && !defined(OPENVPN_FORCE_TUN_NULL) && !defined(OPENVPN_EXTERNAL_TUN_FACTORY) - if (config.dco) - dco = DCOTransport::new_controller(); -#endif - // frame const unsigned int tun_mtu = parse_tun_mtu(opt, 0); // get tun-mtu parameter from config const MSSCtrlParms mc(opt); diff --git a/openvpn/crypto/cryptoalgs.hpp b/openvpn/crypto/cryptoalgs.hpp index cb601afd..cb4438d9 100644 --- a/openvpn/crypto/cryptoalgs.hpp +++ b/openvpn/crypto/cryptoalgs.hpp @@ -135,6 +135,10 @@ namespace openvpn { size_t key_length() const { return size_; } // cipher key length size_t iv_length() const { return iv_length_; } // cipher only size_t block_size() const { return block_size_; } // cipher only + void allow_dc(bool allow) { + if (allow) flags_ |= F_ALLOW_DC; + else flags_ &= ~F_ALLOW_DC; + } private: const char *name_; @@ -145,25 +149,25 @@ namespace openvpn { }; static std::array algs = { - Alg {"NONE", F_CIPHER|F_DIGEST|F_ALLOW_DC|CBC_HMAC, 0, 0, 0 }, - Alg {"AES-128-CBC", F_CIPHER|F_ALLOW_DC|CBC_HMAC, 16, 16, 16 }, - Alg {"AES-192-CBC", F_CIPHER|F_ALLOW_DC|CBC_HMAC, 24, 16, 16 }, - Alg {"AES-256-CBC", F_CIPHER|F_ALLOW_DC|CBC_HMAC, 32, 16, 16 }, - Alg {"DES-CBC", F_CIPHER|F_ALLOW_DC|CBC_HMAC, 8, 8, 8 }, - Alg {"DES-EDE3-CBC", F_CIPHER|F_ALLOW_DC|CBC_HMAC, 24, 8, 8 }, - Alg {"BF-CBC", F_CIPHER|F_ALLOW_DC|CBC_HMAC, 16, 8, 8 }, - Alg {"AES-256-CTR", F_CIPHER, 32, 16, 16 }, - Alg {"AES-128-GCM", F_CIPHER|F_ALLOW_DC|AEAD|F_NO_CIPHER_DIGEST, 16, 12, 16 }, - Alg {"AES-192-GCM", F_CIPHER|F_ALLOW_DC|AEAD|F_NO_CIPHER_DIGEST, 24, 12, 16 }, - Alg {"AES-256-GCM", F_CIPHER|F_ALLOW_DC|AEAD|F_NO_CIPHER_DIGEST, 32, 12, 16 }, - Alg {"CHACHA20-POLY1305", F_CIPHER|F_ALLOW_DC|AEAD|F_NO_CIPHER_DIGEST, 32, 12, 16 }, - Alg {"MD4", F_DIGEST, 16, 0, 0 }, - Alg {"MD5", F_DIGEST|F_ALLOW_DC, 16, 0, 0 }, - Alg {"SHA1", F_DIGEST|F_ALLOW_DC, 20, 0, 0 }, - Alg {"SHA224", F_DIGEST|F_ALLOW_DC, 28, 0, 0 }, - Alg {"SHA256", F_DIGEST|F_ALLOW_DC, 32, 0, 0 }, - Alg {"SHA384", F_DIGEST|F_ALLOW_DC, 48, 0, 0 }, - Alg {"SHA512", F_DIGEST|F_ALLOW_DC, 64, 0, 0 } + Alg {"NONE", F_CIPHER|F_DIGEST|CBC_HMAC, 0, 0, 0 }, + Alg {"AES-128-CBC", F_CIPHER|CBC_HMAC, 16, 16, 16 }, + Alg {"AES-192-CBC", F_CIPHER|CBC_HMAC, 24, 16, 16 }, + Alg {"AES-256-CBC", F_CIPHER|CBC_HMAC, 32, 16, 16 }, + Alg {"DES-CBC", F_CIPHER|CBC_HMAC, 8, 8, 8 }, + Alg {"DES-EDE3-CBC", F_CIPHER|CBC_HMAC, 24, 8, 8 }, + Alg {"BF-CBC", F_CIPHER|CBC_HMAC, 16, 8, 8 }, + Alg {"AES-256-CTR", F_CIPHER, 32, 16, 16 }, + Alg {"AES-128-GCM", F_CIPHER|AEAD|F_NO_CIPHER_DIGEST, 16, 12, 16 }, + Alg {"AES-192-GCM", F_CIPHER|AEAD|F_NO_CIPHER_DIGEST, 24, 12, 16 }, + Alg {"AES-256-GCM", F_CIPHER|AEAD|F_NO_CIPHER_DIGEST, 32, 12, 16 }, + Alg {"CHACHA20-POLY1305", F_CIPHER|AEAD|F_NO_CIPHER_DIGEST, 32, 12, 16 }, + Alg {"MD4", F_DIGEST, 16, 0, 0 }, + Alg {"MD5", F_DIGEST, 16, 0, 0 }, + Alg {"SHA1", F_DIGEST, 20, 0, 0 }, + Alg {"SHA224", F_DIGEST, 28, 0, 0 }, + Alg {"SHA256", F_DIGEST, 32, 0, 0 }, + Alg {"SHA384", F_DIGEST, 48, 0, 0 }, + Alg {"SHA512", F_DIGEST, 64, 0, 0 } }; inline bool defined(const Type type) @@ -253,6 +257,24 @@ namespace openvpn { return type; } + inline void allow_dc_algs(const std::initializer_list types) + { + for (auto& alg : algs) + alg.allow_dc(false); + for (auto& type : types) + algs.at(type).allow_dc(true); + } + + inline void allow_default_dc_algs() + { + allow_dc_algs({ + NONE, AES_128_CBC, AES_192_CBC, AES_256_CBC, + DES_CBC, DES_EDE3_CBC, BF_CBC, + AES_128_GCM, AES_192_GCM, AES_256_GCM, CHACHA20_POLY1305, + MD5, SHA1, SHA224, SHA256, SHA384, SHA512 + }); + } + /** * Check if a specific algorithm depends on an additional digest or not * diff --git a/openvpn/dco/dcocli.hpp b/openvpn/dco/dcocli.hpp index 24fe8461..9713c443 100644 --- a/openvpn/dco/dcocli.hpp +++ b/openvpn/dco/dcocli.hpp @@ -240,7 +240,16 @@ ClientConfig::new_transport_client_obj(openvpn_io::io_context &io_context, #elif ENABLE_OVPNDCO #include inline DCO::Ptr new_controller() { - return OvpnDcoClient::available() ? ClientConfig::new_controller() : nullptr; + if (!OvpnDcoClient::available()) + return nullptr; + + CryptoAlgs::allow_dc_algs({ + CryptoAlgs::CHACHA20_POLY1305, + CryptoAlgs::AES_128_GCM, + CryptoAlgs::AES_192_GCM, + CryptoAlgs::AES_256_GCM + }); + return ClientConfig::new_controller(); } inline TransportClient::Ptr ClientConfig::new_transport_client_obj(openvpn_io::io_context &io_context, @@ -250,7 +259,15 @@ ClientConfig::new_transport_client_obj(openvpn_io::io_context &io_context, #elif ENABLE_OVPNDCOWIN #include inline DCO::Ptr new_controller() { - return OvpnDcoWinClient::available() ? ClientConfig::new_controller() : nullptr; + if (!OvpnDcoWinClient::available()) + return nullptr; + + CryptoAlgs::allow_dc_algs({ + CryptoAlgs::AES_128_GCM, + CryptoAlgs::AES_192_GCM, + CryptoAlgs::AES_256_GCM + }); + return ClientConfig::new_controller(); } inline TransportClient::Ptr ClientConfig::new_transport_client_obj(openvpn_io::io_context& io_context, diff --git a/test/ssl/proto.cpp b/test/ssl/proto.cpp index 5067051e..6279144d 100644 --- a/test/ssl/proto.cpp +++ b/test/ssl/proto.cpp @@ -865,6 +865,7 @@ int test(const int thread_num) MySessionStats::Ptr serv_stats(new MySessionStats); // client ProtoContext config + CryptoAlgs::allow_default_dc_algs(); typedef ProtoContext ClientProtoContext; ClientProtoContext::Config::Ptr cp(new ClientProtoContext::Config); cp->ssl_factory = cc->new_factory();