0
0
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:
Arne Schwabe 2024-07-12 01:08:39 +02:00 committed by Jenkins-dev
parent d52d98c7ec
commit a384f16b32
8 changed files with 214 additions and 204 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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_cipher(CryptoAlgs::Type cipher)
{
cipher_ = cipher;
}
void set_factory(const CryptoDCFactory::Ptr &factory)
void set_digest(CryptoAlgs::Type digest)
{
factory_ = factory;
context_.reset();
dirty = false;
}
void set_cipher(const CryptoAlgs::Type cipher)
{
if (cipher != cipher_)
{
cipher_ = cipher;
dirty = true;
}
}
void set_digest(const CryptoAlgs::Type digest)
{
if (digest != 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;
digest_ = digest;
}
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

View File

@ -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");
}

View File

@ -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:

View File

@ -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;

View File

@ -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);

View File

@ -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 */