mirror of
https://github.com/OpenVPN/openvpn3.git
synced 2024-09-19 19:52:15 +02:00
Refactor data channel setting to CryptoDCSettingsData class
Instead of passing around a number of individual argument, use a data holder class to describe all the settings. This will also allow adding more data channel parameters in the future (tag location, 64 bit IV) easier. This has a slight cost of something passing more parameters than needed. Signed-off-by: Arne Schwabe <arne@openvpn.net>
This commit is contained in:
parent
d52d98c7ec
commit
a384f16b32
@ -157,10 +157,10 @@ class Crypto : public CryptoDCInstance
|
||||
typedef CryptoDCInstance Base;
|
||||
|
||||
Crypto(SSLLib::Ctx libctx_arg,
|
||||
const CryptoAlgs::Type cipher_arg,
|
||||
CryptoDCSettingsData dc_settings_data,
|
||||
const Frame::Ptr &frame_arg,
|
||||
const SessionStats::Ptr &stats_arg)
|
||||
: cipher(cipher_arg),
|
||||
: dc_settings(dc_settings_data),
|
||||
frame(frame_arg),
|
||||
stats(stats_arg),
|
||||
libctx(libctx_arg)
|
||||
@ -270,12 +270,12 @@ class Crypto : public CryptoDCInstance
|
||||
void init_cipher(StaticKey &&encrypt_key, StaticKey &&decrypt_key) override
|
||||
{
|
||||
e.impl.init(libctx,
|
||||
cipher,
|
||||
dc_settings.cipher(),
|
||||
encrypt_key.data(),
|
||||
clamp_to_default<unsigned int>(encrypt_key.size(), 0),
|
||||
CRYPTO_API::CipherContextAEAD::ENCRYPT);
|
||||
d.impl.init(libctx,
|
||||
cipher,
|
||||
dc_settings.cipher(),
|
||||
decrypt_key.data(),
|
||||
clamp_to_default<unsigned int>(decrypt_key.size(), 0),
|
||||
CRYPTO_API::CipherContextAEAD::DECRYPT);
|
||||
@ -288,15 +288,13 @@ class Crypto : public CryptoDCInstance
|
||||
d.nonce.set_tail(decrypt_key);
|
||||
}
|
||||
|
||||
void init_pid(const int send_form,
|
||||
const int recv_mode,
|
||||
const int recv_form,
|
||||
void init_pid(const int recv_mode,
|
||||
const char *recv_name,
|
||||
const int recv_unit,
|
||||
const SessionStats::Ptr &recv_stats_arg) override
|
||||
{
|
||||
e.pid_send.init(send_form);
|
||||
d.pid_recv.init(recv_mode, recv_form, recv_name, recv_unit, recv_stats_arg);
|
||||
e.pid_send.init(PacketID::SHORT_FORM);
|
||||
d.pid_recv.init(recv_mode, PacketID::SHORT_FORM, recv_name, recv_unit, recv_stats_arg);
|
||||
}
|
||||
|
||||
// Indicate whether or not cipher/digest is defined
|
||||
@ -307,7 +305,7 @@ class Crypto : public CryptoDCInstance
|
||||
|
||||
// AEAD mode doesn't use HMAC, but we still indicate HMAC_DEFINED
|
||||
// because we want to use the HMAC keying material for the AEAD nonce tail.
|
||||
if (CryptoAlgs::defined(cipher))
|
||||
if (CryptoAlgs::defined(dc_settings.cipher()))
|
||||
ret |= (CIPHER_DEFINED | HMAC_DEFINED);
|
||||
return ret;
|
||||
}
|
||||
@ -324,7 +322,7 @@ class Crypto : public CryptoDCInstance
|
||||
}
|
||||
|
||||
private:
|
||||
CryptoAlgs::Type cipher;
|
||||
CryptoDCSettingsData dc_settings;
|
||||
Frame::Ptr frame;
|
||||
SessionStats::Ptr stats;
|
||||
SSLLib::Ctx libctx;
|
||||
@ -339,31 +337,29 @@ class CryptoContext : public CryptoDCContext
|
||||
typedef RCPtr<CryptoContext> Ptr;
|
||||
|
||||
CryptoContext(SSLLib::Ctx libctx_arg,
|
||||
const CryptoAlgs::Type cipher_arg,
|
||||
const CryptoAlgs::KeyDerivation key_method,
|
||||
CryptoDCSettingsData dc_settings_data,
|
||||
const Frame::Ptr &frame_arg,
|
||||
const SessionStats::Ptr &stats_arg)
|
||||
: CryptoDCContext(key_method),
|
||||
cipher(CryptoAlgs::legal_dc_cipher(cipher_arg)),
|
||||
: CryptoDCContext(dc_settings_data.key_derivation()),
|
||||
dc_settings(std::move(dc_settings_data)),
|
||||
frame(frame_arg),
|
||||
stats(stats_arg),
|
||||
libctx(libctx_arg)
|
||||
{
|
||||
/* Check if the cipher is legal for AEAD and otherwise throw */
|
||||
legal_dc_cipher(dc_settings.cipher());
|
||||
dc_settings.set_digest(CryptoAlgs::NONE);
|
||||
}
|
||||
|
||||
CryptoDCInstance::Ptr new_obj(const unsigned int key_id) override
|
||||
{
|
||||
return new Crypto<CRYPTO_API>(libctx, cipher, frame, stats);
|
||||
return new Crypto<CRYPTO_API>(libctx, dc_settings, frame, stats);
|
||||
}
|
||||
|
||||
// cipher/HMAC/key info
|
||||
Info crypto_info() override
|
||||
CryptoDCSettingsData crypto_info() override
|
||||
{
|
||||
Info ret;
|
||||
ret.cipher_alg = cipher;
|
||||
ret.hmac_alg = CryptoAlgs::NONE;
|
||||
ret.key_derivation = key_derivation;
|
||||
return ret;
|
||||
return dc_settings;
|
||||
}
|
||||
|
||||
// Info for ProtoContext::link_mtu_adjust
|
||||
@ -374,7 +370,7 @@ class CryptoContext : public CryptoDCContext
|
||||
}
|
||||
|
||||
private:
|
||||
CryptoAlgs::Type cipher;
|
||||
CryptoDCSettingsData dc_settings;
|
||||
Frame::Ptr frame;
|
||||
SessionStats::Ptr stats;
|
||||
SSLLib::Ctx libctx;
|
||||
|
@ -40,13 +40,11 @@ class CryptoCHM : public CryptoDCInstance
|
||||
|
||||
CryptoCHM(
|
||||
SSLLib::Ctx libctx_arg,
|
||||
const CryptoAlgs::Type cipher_arg,
|
||||
const CryptoAlgs::Type digest_arg,
|
||||
CryptoDCSettingsData dc_settings_data,
|
||||
const Frame::Ptr &frame_arg,
|
||||
const SessionStats::Ptr &stats_arg,
|
||||
const StrongRandomAPI::Ptr &rng_arg)
|
||||
: cipher(cipher_arg),
|
||||
digest(digest_arg),
|
||||
: dc_settings(dc_settings_data),
|
||||
frame(frame_arg),
|
||||
stats(stats_arg),
|
||||
rng(rng_arg),
|
||||
@ -76,26 +74,27 @@ class CryptoCHM : public CryptoDCInstance
|
||||
void init_cipher(StaticKey &&encrypt_key,
|
||||
StaticKey &&decrypt_key) override
|
||||
{
|
||||
encrypt_.cipher.init(libctx, cipher, encrypt_key, CRYPTO_API::CipherContext::ENCRYPT);
|
||||
decrypt_.cipher.init(libctx, cipher, decrypt_key, CRYPTO_API::CipherContext::DECRYPT);
|
||||
encrypt_.cipher.init(libctx, dc_settings.cipher(), encrypt_key, CRYPTO_API::CipherContext::ENCRYPT);
|
||||
decrypt_.cipher.init(libctx, dc_settings.cipher(), decrypt_key, CRYPTO_API::CipherContext::DECRYPT);
|
||||
}
|
||||
|
||||
void init_hmac(StaticKey &&encrypt_key,
|
||||
StaticKey &&decrypt_key) override
|
||||
{
|
||||
encrypt_.hmac.init(digest, encrypt_key);
|
||||
decrypt_.hmac.init(digest, decrypt_key);
|
||||
encrypt_.hmac.init(dc_settings.digest(), encrypt_key);
|
||||
decrypt_.hmac.init(dc_settings.digest(), decrypt_key);
|
||||
}
|
||||
|
||||
void init_pid(const int send_form,
|
||||
const int recv_mode,
|
||||
const int recv_form,
|
||||
void init_pid(const int recv_mode,
|
||||
const char *recv_name,
|
||||
const int recv_unit,
|
||||
const SessionStats::Ptr &recv_stats_arg) override
|
||||
{
|
||||
encrypt_.pid_send.init(send_form);
|
||||
decrypt_.pid_recv.init(recv_mode, recv_form, recv_name, recv_unit, recv_stats_arg);
|
||||
/* CBC encryption always uses short packet ID */
|
||||
auto pid_form = PacketID::SHORT_FORM;
|
||||
|
||||
encrypt_.pid_send.init(pid_form);
|
||||
decrypt_.pid_recv.init(recv_mode, pid_form, recv_name, recv_unit, recv_stats_arg);
|
||||
}
|
||||
|
||||
bool consider_compression(const CompressContext &comp_ctx) override
|
||||
@ -108,9 +107,9 @@ class CryptoCHM : public CryptoDCInstance
|
||||
unsigned int defined() const override
|
||||
{
|
||||
unsigned int ret = CRYPTO_DEFINED;
|
||||
if (CryptoAlgs::defined(cipher))
|
||||
if (CryptoAlgs::defined(dc_settings.cipher()))
|
||||
ret |= CIPHER_DEFINED;
|
||||
if (CryptoAlgs::defined(digest))
|
||||
if (CryptoAlgs::defined(dc_settings.digest()))
|
||||
ret |= HMAC_DEFINED;
|
||||
return ret;
|
||||
}
|
||||
@ -122,8 +121,7 @@ class CryptoCHM : public CryptoDCInstance
|
||||
}
|
||||
|
||||
private:
|
||||
CryptoAlgs::Type cipher;
|
||||
CryptoAlgs::Type digest;
|
||||
CryptoDCSettingsData dc_settings;
|
||||
Frame::Ptr frame;
|
||||
SessionStats::Ptr stats;
|
||||
StrongRandomAPI::Ptr rng;
|
||||
@ -141,15 +139,12 @@ class CryptoContextCHM : public CryptoDCContext
|
||||
|
||||
CryptoContextCHM(
|
||||
SSLLib::Ctx libctx_arg,
|
||||
const CryptoAlgs::Type cipher_arg,
|
||||
const CryptoAlgs::Type digest_arg,
|
||||
const CryptoAlgs::KeyDerivation key_method,
|
||||
CryptoDCSettingsData dc_settings_arg,
|
||||
const Frame::Ptr &frame_arg,
|
||||
const SessionStats::Ptr &stats_arg,
|
||||
const StrongRandomAPI::Ptr &rng_arg)
|
||||
: CryptoDCContext(key_method),
|
||||
cipher(CryptoAlgs::dc_cbc_cipher(cipher_arg)),
|
||||
digest(CryptoAlgs::dc_cbc_hash(digest_arg)),
|
||||
: CryptoDCContext(dc_settings_arg.key_derivation()),
|
||||
dc_settings(std::move(dc_settings_arg)),
|
||||
frame(frame_arg),
|
||||
stats(stats_arg),
|
||||
rng(rng_arg),
|
||||
@ -163,35 +158,29 @@ class CryptoContextCHM : public CryptoDCContext
|
||||
* can be called and calculated for the OCC strings even if we do not allow the cipher
|
||||
* to be actually used */
|
||||
return new CryptoCHM<CRYPTO_API>(libctx,
|
||||
CryptoAlgs::legal_dc_cipher(cipher),
|
||||
CryptoAlgs::legal_dc_digest(digest),
|
||||
dc_settings,
|
||||
frame,
|
||||
stats,
|
||||
rng);
|
||||
}
|
||||
|
||||
// cipher/HMAC/key info
|
||||
Info crypto_info() override
|
||||
CryptoDCSettingsData crypto_info() override
|
||||
{
|
||||
Info ret;
|
||||
ret.cipher_alg = cipher;
|
||||
ret.hmac_alg = digest;
|
||||
ret.key_derivation = key_derivation;
|
||||
return ret;
|
||||
return dc_settings;
|
||||
}
|
||||
|
||||
// Info for ProtoContext::link_mtu_adjust
|
||||
|
||||
size_t encap_overhead() const override
|
||||
{
|
||||
return CryptoAlgs::size(digest) + // HMAC
|
||||
CryptoAlgs::iv_length(cipher) + // Cipher IV
|
||||
CryptoAlgs::block_size(cipher); // worst-case PKCS#7 padding expansion
|
||||
return CryptoAlgs::size(dc_settings.digest()) + // HMAC
|
||||
CryptoAlgs::iv_length(dc_settings.cipher()) + // Cipher IV
|
||||
CryptoAlgs::block_size(dc_settings.cipher()); // worst-case PKCS#7 padding expansion
|
||||
}
|
||||
|
||||
private:
|
||||
CryptoAlgs::Type cipher;
|
||||
CryptoAlgs::Type digest;
|
||||
CryptoDCSettingsData dc_settings;
|
||||
Frame::Ptr frame;
|
||||
SessionStats::Ptr stats;
|
||||
StrongRandomAPI::Ptr rng;
|
||||
|
@ -61,6 +61,7 @@ class CryptoDCInstance : public RC<thread_unsafe_refcount>
|
||||
HMAC_DEFINED = (1 << 1), // may call init_hmac method
|
||||
CRYPTO_DEFINED = (1 << 2), // may call encrypt or decrypt methods
|
||||
EXPLICIT_EXIT_NOTIFY_DEFINED = (1 << 3), // may call explicit_exit_notify method
|
||||
LONG_IV_DEFINED = (1 << 4)
|
||||
};
|
||||
virtual unsigned int defined() const = 0;
|
||||
|
||||
@ -72,9 +73,7 @@ class CryptoDCInstance : public RC<thread_unsafe_refcount>
|
||||
StaticKey &&decrypt_key)
|
||||
= 0;
|
||||
|
||||
virtual void init_pid(const int send_form,
|
||||
const int recv_mode,
|
||||
const int recv_form,
|
||||
virtual void init_pid(const int recv_mode,
|
||||
const char *recv_name,
|
||||
const int recv_unit,
|
||||
const SessionStats::Ptr &recv_stats_arg)
|
||||
@ -105,102 +104,22 @@ class CryptoDCInstance : public RC<thread_unsafe_refcount>
|
||||
virtual void rekey(const RekeyType type) = 0;
|
||||
};
|
||||
|
||||
// Factory for CryptoDCInstance objects
|
||||
class CryptoDCContext : public RC<thread_unsafe_refcount>
|
||||
{
|
||||
public:
|
||||
explicit CryptoDCContext(const CryptoAlgs::KeyDerivation method)
|
||||
: key_derivation(method)
|
||||
{
|
||||
}
|
||||
|
||||
typedef RCPtr<CryptoDCContext> Ptr;
|
||||
|
||||
virtual CryptoDCInstance::Ptr new_obj(const unsigned int key_id) = 0;
|
||||
|
||||
// cipher/HMAC/key info
|
||||
struct Info
|
||||
{
|
||||
Info()
|
||||
{
|
||||
}
|
||||
CryptoAlgs::Type cipher_alg = CryptoAlgs::NONE;
|
||||
CryptoAlgs::Type hmac_alg = CryptoAlgs::NONE;
|
||||
CryptoAlgs::KeyDerivation key_derivation = CryptoAlgs::KeyDerivation::OPENVPN_PRF;
|
||||
};
|
||||
virtual Info crypto_info() = 0;
|
||||
|
||||
// Info for ProtoContext::link_mtu_adjust
|
||||
virtual size_t encap_overhead() const = 0;
|
||||
|
||||
protected:
|
||||
CryptoAlgs::KeyDerivation key_derivation = CryptoAlgs::KeyDerivation::OPENVPN_PRF;
|
||||
};
|
||||
|
||||
// Factory for CryptoDCContext objects
|
||||
class CryptoDCFactory : public RC<thread_unsafe_refcount>
|
||||
{
|
||||
public:
|
||||
typedef RCPtr<CryptoDCFactory> Ptr;
|
||||
|
||||
virtual CryptoDCContext::Ptr new_obj(const CryptoAlgs::Type cipher,
|
||||
const CryptoAlgs::Type digest,
|
||||
const CryptoAlgs::KeyDerivation method)
|
||||
= 0;
|
||||
};
|
||||
|
||||
// Manage cipher/digest settings, DC factory, and DC context.
|
||||
class CryptoDCSettings
|
||||
/** class that holds settings for a data channel encryption */
|
||||
class CryptoDCSettingsData
|
||||
{
|
||||
public:
|
||||
OPENVPN_SIMPLE_EXCEPTION(no_data_channel_factory);
|
||||
|
||||
CryptoDCSettings()
|
||||
{
|
||||
}
|
||||
CryptoDCSettingsData() = default;
|
||||
|
||||
void set_factory(const CryptoDCFactory::Ptr &factory)
|
||||
{
|
||||
factory_ = factory;
|
||||
context_.reset();
|
||||
dirty = false;
|
||||
}
|
||||
|
||||
void set_cipher(const CryptoAlgs::Type cipher)
|
||||
{
|
||||
if (cipher != cipher_)
|
||||
void set_cipher(CryptoAlgs::Type cipher)
|
||||
{
|
||||
cipher_ = cipher;
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void set_digest(const CryptoAlgs::Type digest)
|
||||
{
|
||||
if (digest != digest_)
|
||||
void set_digest(CryptoAlgs::Type digest)
|
||||
{
|
||||
digest_ = digest;
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
CryptoDCContext &context()
|
||||
{
|
||||
if (!context_ || dirty)
|
||||
{
|
||||
if (!factory_)
|
||||
throw no_data_channel_factory();
|
||||
context_ = factory_->new_obj(cipher_, digest_, key_derivation_);
|
||||
dirty = false;
|
||||
}
|
||||
return *context_;
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
factory_.reset();
|
||||
context_.reset();
|
||||
dirty = false;
|
||||
}
|
||||
|
||||
CryptoAlgs::Type cipher() const
|
||||
@ -220,12 +139,6 @@ class CryptoDCSettings
|
||||
return (CryptoAlgs::use_cipher_digest(cipher_) ? digest_ : CryptoAlgs::NONE);
|
||||
}
|
||||
|
||||
|
||||
CryptoDCFactory::Ptr factory() const
|
||||
{
|
||||
return factory_;
|
||||
}
|
||||
|
||||
void set_key_derivation(CryptoAlgs::KeyDerivation method)
|
||||
{
|
||||
key_derivation_ = method;
|
||||
@ -236,14 +149,106 @@ class CryptoDCSettings
|
||||
return key_derivation_;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
CryptoAlgs::Type cipher_ = CryptoAlgs::NONE;
|
||||
CryptoAlgs::Type digest_ = CryptoAlgs::NONE;
|
||||
CryptoAlgs::KeyDerivation key_derivation_ = CryptoAlgs::KeyDerivation::OPENVPN_PRF;
|
||||
};
|
||||
|
||||
// Factory for CryptoDCInstance objects
|
||||
class CryptoDCContext : public RC<thread_unsafe_refcount>
|
||||
{
|
||||
public:
|
||||
explicit CryptoDCContext(const CryptoAlgs::KeyDerivation method)
|
||||
: key_derivation(method)
|
||||
{
|
||||
}
|
||||
|
||||
typedef RCPtr<CryptoDCContext> Ptr;
|
||||
|
||||
virtual CryptoDCInstance::Ptr new_obj(const unsigned int key_id) = 0;
|
||||
|
||||
virtual CryptoDCSettingsData crypto_info() = 0;
|
||||
|
||||
// Info for ProtoContext::link_mtu_adjust
|
||||
virtual size_t encap_overhead() const = 0;
|
||||
|
||||
protected:
|
||||
CryptoAlgs::KeyDerivation key_derivation = CryptoAlgs::KeyDerivation::OPENVPN_PRF;
|
||||
};
|
||||
|
||||
// Factory for CryptoDCContext objects
|
||||
class CryptoDCFactory : public RC<thread_unsafe_refcount>
|
||||
{
|
||||
public:
|
||||
typedef RCPtr<CryptoDCFactory> Ptr;
|
||||
|
||||
virtual CryptoDCContext::Ptr new_obj(const CryptoDCSettingsData) = 0;
|
||||
};
|
||||
|
||||
|
||||
// Manage cipher/digest settings, DC factory, and DC context.
|
||||
class CryptoDCSettings : public CryptoDCSettingsData
|
||||
{
|
||||
public:
|
||||
OPENVPN_SIMPLE_EXCEPTION(no_data_channel_factory);
|
||||
|
||||
CryptoDCSettings() = default;
|
||||
|
||||
void set_factory(const CryptoDCFactory::Ptr &factory)
|
||||
{
|
||||
factory_ = factory;
|
||||
context_.reset();
|
||||
dirty = false;
|
||||
}
|
||||
|
||||
void set_cipher(const CryptoAlgs::Type new_cipher)
|
||||
{
|
||||
if (new_cipher != cipher())
|
||||
{
|
||||
CryptoDCSettingsData::set_cipher(new_cipher);
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void set_digest(const CryptoAlgs::Type new_digest)
|
||||
{
|
||||
if (new_digest != digest())
|
||||
{
|
||||
CryptoDCSettingsData::set_digest(new_digest);
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
CryptoDCContext &context()
|
||||
{
|
||||
if (!context_ || dirty)
|
||||
{
|
||||
if (!factory_)
|
||||
throw no_data_channel_factory();
|
||||
context_ = factory_->new_obj(*this);
|
||||
dirty = false;
|
||||
}
|
||||
return *context_;
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
factory_.reset();
|
||||
context_.reset();
|
||||
dirty = false;
|
||||
}
|
||||
|
||||
[[nodiscard]] CryptoDCFactory::Ptr factory() const
|
||||
{
|
||||
return factory_;
|
||||
}
|
||||
|
||||
private:
|
||||
bool dirty = false;
|
||||
CryptoDCFactory::Ptr factory_;
|
||||
CryptoDCContext::Ptr context_;
|
||||
bool dirty = false;
|
||||
};
|
||||
} // namespace openvpn
|
||||
|
||||
|
@ -34,6 +34,9 @@ namespace openvpn {
|
||||
|
||||
OPENVPN_EXCEPTION(crypto_dc_select);
|
||||
|
||||
/**
|
||||
* Implements the data channel encryption and decryption in userspace
|
||||
*/
|
||||
template <typename CRYPTO_API>
|
||||
class CryptoDCSelect : public CryptoDCFactory
|
||||
{
|
||||
@ -51,15 +54,13 @@ class CryptoDCSelect : public CryptoDCFactory
|
||||
{
|
||||
}
|
||||
|
||||
CryptoDCContext::Ptr new_obj(const CryptoAlgs::Type cipher,
|
||||
const CryptoAlgs::Type digest,
|
||||
const CryptoAlgs::KeyDerivation method) override
|
||||
CryptoDCContext::Ptr new_obj(CryptoDCSettingsData dc_settings) override
|
||||
{
|
||||
const CryptoAlgs::Alg &alg = CryptoAlgs::get(cipher);
|
||||
const CryptoAlgs::Alg &alg = CryptoAlgs::get(dc_settings.cipher());
|
||||
if (alg.flags() & CryptoAlgs::CBC_HMAC)
|
||||
return new CryptoContextCHM<CRYPTO_API>(libctx, cipher, digest, method, frame, stats, rng);
|
||||
return new CryptoContextCHM<CRYPTO_API>(libctx, std::move(dc_settings), frame, stats, rng);
|
||||
else if (alg.flags() & CryptoAlgs::AEAD)
|
||||
return new AEAD::CryptoContext<CRYPTO_API>(libctx, cipher, method, frame, stats);
|
||||
return new AEAD::CryptoContext<CRYPTO_API>(libctx, std::move(dc_settings), frame, stats);
|
||||
else
|
||||
OPENVPN_THROW(crypto_dc_select, alg.name() << ": only CBC/HMAC and AEAD cipher modes supported");
|
||||
}
|
||||
|
@ -75,9 +75,7 @@ class Instance : public CryptoDCInstance
|
||||
info.decrypt_hmac = std::move(decrypt_key);
|
||||
}
|
||||
|
||||
void init_pid(const int send_form,
|
||||
const int recv_mode,
|
||||
const int recv_form,
|
||||
void init_pid(const int recv_mode,
|
||||
const char *recv_name,
|
||||
const int recv_unit,
|
||||
const SessionStats::Ptr &recv_stats_arg) override
|
||||
@ -122,6 +120,7 @@ class Instance : public CryptoDCInstance
|
||||
throw korekey_error("decrypt");
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
Receiver::Ptr rcv;
|
||||
Info info;
|
||||
@ -130,18 +129,16 @@ class Instance : public CryptoDCInstance
|
||||
class Context : public CryptoDCContext
|
||||
{
|
||||
public:
|
||||
Context(const CryptoAlgs::Type cipher,
|
||||
const CryptoAlgs::Type digest,
|
||||
const CryptoAlgs::KeyDerivation key_method,
|
||||
Context(CryptoDCSettingsData dc_settings_data,
|
||||
CryptoDCFactory &dc_factory_delegate,
|
||||
const Receiver::Ptr &rcv_arg,
|
||||
const Frame::Ptr &frame_arg)
|
||||
: CryptoDCContext(key_method),
|
||||
: CryptoDCContext(dc_settings_data.key_derivation()),
|
||||
rcv(rcv_arg),
|
||||
dc_context_delegate(dc_factory_delegate.new_obj(cipher, digest, key_method)),
|
||||
dc_context_delegate(dc_factory_delegate.new_obj(dc_settings_data)),
|
||||
frame(frame_arg)
|
||||
{
|
||||
Key::validate(cipher, digest);
|
||||
Key::validate(dc_settings_data.cipher(), dc_settings_data.digest());
|
||||
}
|
||||
|
||||
CryptoDCInstance::Ptr new_obj(const unsigned int key_id) override
|
||||
@ -150,8 +147,7 @@ class Context : public CryptoDCContext
|
||||
}
|
||||
|
||||
// Info for ProtoContext::options_string
|
||||
|
||||
Info crypto_info() override
|
||||
CryptoDCSettingsData crypto_info() override
|
||||
{
|
||||
return dc_context_delegate->crypto_info();
|
||||
}
|
||||
@ -181,11 +177,9 @@ class Factory : public CryptoDCFactory
|
||||
{
|
||||
}
|
||||
|
||||
CryptoDCContext::Ptr new_obj(const CryptoAlgs::Type cipher,
|
||||
const CryptoAlgs::Type digest,
|
||||
const CryptoAlgs::KeyDerivation key_method) override
|
||||
CryptoDCContext::Ptr new_obj(const CryptoDCSettingsData dc_settings_data) override
|
||||
{
|
||||
return new Context(cipher, digest, key_method, *dc_factory_delegate, rcv, frame);
|
||||
return new Context(dc_settings_data, *dc_factory_delegate, rcv, frame);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -39,9 +39,9 @@ class OvpnDcoKey : public Key
|
||||
|
||||
kc.remote_peer_id = rkinfo.remote_peer_id;
|
||||
|
||||
const CryptoDCContext::Info ci = rkinfo.dc_context_delegate->crypto_info();
|
||||
const CryptoAlgs::Alg &calg = CryptoAlgs::get(ci.cipher_alg);
|
||||
switch (ci.cipher_alg)
|
||||
const CryptoDCSettingsData ci = rkinfo.dc_context_delegate->crypto_info();
|
||||
const CryptoAlgs::Alg &calg = CryptoAlgs::get(ci.cipher());
|
||||
switch (ci.cipher())
|
||||
{
|
||||
case CryptoAlgs::NONE:
|
||||
kc.cipher_alg = OVPN_CIPHER_ALG_NONE;
|
||||
|
@ -896,15 +896,20 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO,
|
||||
}
|
||||
}
|
||||
|
||||
std::string show_options() const
|
||||
void get_data_channel_options(std::ostringstream &os) const
|
||||
{
|
||||
os << " data channel:";
|
||||
os << " cipher " << CryptoAlgs::name(dc.cipher());
|
||||
if (CryptoAlgs::mode(dc.cipher()) != CryptoAlgs::Mode::AEAD)
|
||||
os << ", digest " << CryptoAlgs::name(dc.digest());
|
||||
|
||||
os << ", peer-id " << remote_peer_id;
|
||||
|
||||
os << std::endl;
|
||||
}
|
||||
|
||||
void show_cc_enc_option(std::ostringstream &os) const
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << "PROTOCOL OPTIONS:" << std::endl;
|
||||
os << " cipher: " << CryptoAlgs::name(dc.cipher()) << std::endl;
|
||||
os << " digest: " << CryptoAlgs::name(dc.digest()) << std::endl;
|
||||
os << " key-derivation: " << CryptoAlgs::name(dc.key_derivation()) << std::endl;
|
||||
os << " compress: " << comp_ctx.str() << std::endl;
|
||||
os << " peer ID: " << remote_peer_id << std::endl;
|
||||
if (tls_auth_enabled())
|
||||
{
|
||||
os << " control channel: tls-auth enabled" << std::endl;
|
||||
@ -921,10 +926,24 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO,
|
||||
{
|
||||
os << " control channel: dynamic tls-crypt enabled" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
std::string show_options() const
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << "PROTOCOL OPTIONS:" << std::endl;
|
||||
os << " key-derivation: " << CryptoAlgs::name(dc.key_derivation()) << std::endl;
|
||||
if (comp_ctx.type() != CompressContext::NONE)
|
||||
os << " compress: " << comp_ctx.str() << std::endl;
|
||||
|
||||
show_cc_enc_option(os);
|
||||
get_data_channel_options(os);
|
||||
|
||||
if (!app_control_config.supported_protocols.empty())
|
||||
{
|
||||
os << " app custom control channel: " << app_control_config.str() << std::endl;
|
||||
}
|
||||
|
||||
return os.str();
|
||||
}
|
||||
|
||||
@ -1129,6 +1148,8 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO,
|
||||
out << "IV_BS64DL=1\n"; // indicate support for data limits when using 64-bit block-size ciphers, version 1 (CVE-2016-6329)
|
||||
if (relay_mode)
|
||||
out << "IV_RELAY=1\n";
|
||||
|
||||
|
||||
const std::string ret = out.str();
|
||||
OVPN_LOG_INFO("Sending Peer Info:" << std::endl
|
||||
<< ret);
|
||||
@ -2278,9 +2299,7 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO,
|
||||
crypto->init_hmac(key.slice(OpenVPNStaticKey::HMAC | OpenVPNStaticKey::ENCRYPT | key_dir),
|
||||
key.slice(OpenVPNStaticKey::HMAC | OpenVPNStaticKey::DECRYPT | key_dir));
|
||||
|
||||
crypto->init_pid(PacketID::SHORT_FORM,
|
||||
c.pid_mode,
|
||||
PacketID::SHORT_FORM,
|
||||
crypto->init_pid(c.pid_mode,
|
||||
"DATA",
|
||||
int(key_id_),
|
||||
proto.stats);
|
||||
|
@ -102,7 +102,10 @@ TEST(crypto, dcaead)
|
||||
auto frameptr = openvpn::Frame::Ptr{new openvpn::Frame{frame_ctx()}};
|
||||
auto statsptr = openvpn::SessionStats::Ptr{new openvpn::SessionStats{}};
|
||||
|
||||
openvpn::AEAD::Crypto<openvpn::SSLLib::CryptoAPI> cryptodc{nullptr, openvpn::CryptoAlgs::AES_256_GCM, frameptr, statsptr};
|
||||
openvpn::CryptoDCSettingsData dc;
|
||||
dc.set_cipher(openvpn::CryptoAlgs::AES_256_GCM);
|
||||
|
||||
openvpn::AEAD::Crypto<openvpn::SSLLib::CryptoAPI> cryptodc{nullptr, dc, frameptr, statsptr};
|
||||
|
||||
const char *plaintext = "The quick little fox jumps over the bureaucratic hurdles";
|
||||
|
||||
@ -119,16 +122,19 @@ TEST(crypto, dcaead)
|
||||
bigkey[i] = static_cast<uint8_t>(key[i % sizeof(key)] ^ i);
|
||||
}
|
||||
|
||||
openvpn::StaticKey const static_bigkey{bigkey, openvpn::OpenVPNStaticKey::KEY_SIZE};
|
||||
openvpn::StaticKey static_en_key{key, sizeof(key)};
|
||||
openvpn::StaticKey static_de_key = static_en_key;
|
||||
openvpn::OpenVPNStaticKey static_key;
|
||||
std::memcpy(static_key.raw_alloc(), bigkey, sizeof(bigkey));
|
||||
|
||||
/* StaticKey implements all implicit copy and move operations as it
|
||||
explicitly defines none of them nor does it explicitly define a dtor */
|
||||
cryptodc.init_cipher(std::move(static_en_key), std::move(static_de_key));
|
||||
cryptodc.init_pid(openvpn::PacketID::SHORT_FORM,
|
||||
0,
|
||||
openvpn::PacketID::SHORT_FORM,
|
||||
auto key_dir = openvpn::OpenVPNStaticKey::NORMAL;
|
||||
|
||||
/* We here make encrypt and decrypt keys the same by design to have the loopback decryption capability */
|
||||
cryptodc.init_hmac(static_key.slice(openvpn::OpenVPNStaticKey::HMAC | openvpn::OpenVPNStaticKey::ENCRYPT | key_dir),
|
||||
static_key.slice(openvpn::OpenVPNStaticKey::HMAC | openvpn::OpenVPNStaticKey::ENCRYPT | key_dir));
|
||||
|
||||
cryptodc.init_cipher(static_key.slice(openvpn::OpenVPNStaticKey::CIPHER | openvpn::OpenVPNStaticKey::ENCRYPT | key_dir),
|
||||
static_key.slice(openvpn::OpenVPNStaticKey::CIPHER | openvpn::OpenVPNStaticKey::ENCRYPT | key_dir));
|
||||
|
||||
cryptodc.init_pid(0,
|
||||
"DATA",
|
||||
0,
|
||||
statsptr);
|
||||
@ -152,7 +158,7 @@ TEST(crypto, dcaead)
|
||||
/* 16 for tag, 4 for IV */
|
||||
EXPECT_EQ(work.size(), std::strlen(plaintext) + 4 + 16);
|
||||
|
||||
const uint8_t expected_tag[16]{0xe0, 0xa7, 0x19, '*', 0x89, ']', 0x1d, 0x90, 0xc9, 0xd6, '\n', 0xee, '8', 'z', 0x01, 0xbd};
|
||||
const uint8_t expected_tag[16]{0x1f, 0xdd, 0x90, 0x8f, 0x0e, 0x9d, 0xc2, 0x5e, 0x79, 0xd8, 0x32, 0x02, 0x0d, 0x58, 0xe7, 0x3f};
|
||||
// Packet id/IV should 1
|
||||
uint8_t packetid1[]{0, 0, 0, 1};
|
||||
EXPECT_TRUE(std::memcmp(work.data(), packetid1, 4) == 0);
|
||||
@ -161,7 +167,7 @@ TEST(crypto, dcaead)
|
||||
EXPECT_TRUE(std::memcmp(work.data() + 4, expected_tag, 16) == 0);
|
||||
|
||||
// Check a few random bytes of the encrypted output
|
||||
const uint8_t bytesat30[6]{0x52, 0x2e, 0xbf, 0xdf, 0x24, 0x1c};
|
||||
const uint8_t bytesat30[6]{0xa8, 0x2e, 0x6b, 0x2e, 0x6b, 0x17};
|
||||
EXPECT_TRUE(std::memcmp(work.data() + 30, bytesat30, 6) == 0);
|
||||
|
||||
/* Check now if decrypting also works */
|
||||
|
Loading…
Reference in New Issue
Block a user