0
0
mirror of https://github.com/OpenVPN/openvpn3.git synced 2024-09-20 04:02:15 +02:00

implement support for dynamic tls-crypt

Signed-off-by: Heiko Hund <heiko@openvpn.net>
This commit is contained in:
Heiko Hund 2023-01-25 10:26:40 +01:00 committed by Frank Lichtenheld
parent be3834a740
commit 2ea80037e3
2 changed files with 72 additions and 11 deletions

View File

@ -231,7 +231,8 @@ class ProtoContext
IV_PROTO_NCP_P2P = (1 << 5), // not implemented
IV_PROTO_DNS_OPTION = (1 << 6),
IV_PROTO_CC_EXIT_NOTIFY = (1 << 7),
IV_PROTO_AUTH_FAIL_TEMP = (1 << 8)
IV_PROTO_AUTH_FAIL_TEMP = (1 << 8),
IV_PROTO_DYN_TLS_CRYPT = (1 << 9),
};
enum tlv_types : uint16_t
@ -331,9 +332,16 @@ class ProtoContext
CompressContext comp_ctx;
// tls_auth/crypt parms
OpenVPNStaticKey tls_key; // leave this undefined to disable tls_auth/crypt
bool tls_crypt_v2 = false; // needed to distinguish between tls-crypt and tls-crypt-v2 server mode
BufferAllocated wkc; // leave this undefined to disable tls-crypt-v2 on client
enum TLSCrypt
{
None = 0,
V1 = (1 << 0),
V2 = (1 << 1),
Dynamic = (1 << 2)
};
OpenVPNStaticKey tls_key; // leave this undefined to disable tls_auth/crypt
unsigned tls_crypt_ = TLSCrypt::None; // needed to distinguish between tls-crypt and tls-crypt-v2 server mode
BufferAllocated wkc; // leave this undefined to disable tls-crypt-v2 on client
OvpnHMACFactory::Ptr tls_auth_factory;
OvpnHMACContext::Ptr tls_auth_context;
@ -474,6 +482,7 @@ class ProtoContext
if (tls_crypt_context)
throw proto_option_error("tls-crypt and tls-crypt-v2 are mutually exclusive");
tls_crypt_ = TLSCrypt::V1;
tls_key.parse(o->get(1, 0));
set_tls_crypt_algs();
@ -510,7 +519,7 @@ class ProtoContext
tls_crypt_v2_key.parse(keyfile);
tls_crypt_v2_key.extract_key(tls_key);
}
tls_crypt_v2 = true;
tls_crypt_ = TLSCrypt::V2;
}
}
}
@ -672,6 +681,11 @@ class ProtoContext
{
cc_exit_notify = true;
}
else if (flag == "dyn-tls-crypt")
{
set_tls_crypt_algs();
tls_crypt_ |= TLSCrypt::Dynamic;
}
else if (flag == "tls-ekm")
{
// Overrides "key-derivation" method set above
@ -787,7 +801,7 @@ class ProtoContext
{
os << " control channel: tls-auth enabled" << std::endl;
}
else if (tls_crypt_v2_enabled())
if (tls_crypt_v2_enabled())
{
os << " control channel: tls-crypt v2 enabled" << std::endl;
}
@ -795,6 +809,10 @@ class ProtoContext
{
os << " control channel: tls-crypt enabled" << std::endl;
}
else if (dynamic_tls_crypt_enabled())
{
os << " control channel: dynamic tls-crypt enabled" << std::endl;
}
return os.str();
}
@ -849,12 +867,17 @@ class ProtoContext
bool tls_crypt_enabled() const
{
return tls_key.defined() && tls_crypt_context;
return tls_key.defined() && (tls_crypt_ & TLSCrypt::V1);
}
bool tls_crypt_v2_enabled() const
{
return tls_crypt_enabled() && tls_crypt_v2;
return tls_key.defined() && (tls_crypt_ & TLSCrypt::V2);
}
bool dynamic_tls_crypt_enabled() const
{
return (tls_crypt_ & TLSCrypt::Dynamic);
}
// generate a string summarizing options that will be
@ -925,6 +948,9 @@ class ProtoContext
| IV_PROTO_CC_EXIT_NOTIFY
| IV_PROTO_AUTH_FAIL_TEMP;
if (CryptoAlgs::lookup("SHA256") != CryptoAlgs::NONE && CryptoAlgs::lookup("AES-256-CTR") != CryptoAlgs::NONE)
iv_proto |= IV_PROTO_DYN_TLS_CRYPT;
if (SSLLib::SSLAPI::support_key_material_export())
{
iv_proto |= IV_PROTO_TLS_KEY_EXPORT;
@ -3463,8 +3489,11 @@ class ProtoContext
n_key_ids(0),
now_(config_arg->now)
{
const Config &c = *config;
reset_tls_wrap_mode(*config);
}
void reset_tls_wrap_mode(const Config &c)
{
// tls-auth setup
if (c.tls_crypt_v2_enabled())
{
@ -3524,6 +3553,25 @@ class ProtoContext
key.slice(OpenVPNStaticKey::CIPHER | OpenVPNStaticKey::DECRYPT | key_dir));
}
void set_dynamic_tls_crypt(const Config &c, const KeyContext::Ptr &key_ctx)
{
OpenVPNStaticKey dyn_key;
key_ctx->export_key_material(dyn_key, "EXPORTER-OpenVPN-dynamic-tls-crypt");
if (c.tls_auth_enabled() || c.tls_crypt_enabled() || c.tls_crypt_v2_enabled())
dyn_key.XOR(c.tls_key);
tls_wrap_mode = TLS_CRYPT;
// get HMAC size from Digest object
hmac_size = c.tls_crypt_context->digest_size();
ta_pid_send.init(PacketID::LONG_FORM);
ta_pid_recv.init(c.pid_mode, PacketID::LONG_FORM, "SSL-CC", 0, stats);
reset_tls_crypt(c, dyn_key);
}
void reset_tls_crypt_server(const Config &c)
{
// tls-crypt session key is derived later from WKc received from the client
@ -3559,6 +3607,7 @@ class ProtoContext
const PacketID::id_t EARLY_NEG_START = 0x0f000000;
// tls-auth initialization
reset_tls_wrap_mode(c);
switch (tls_wrap_mode)
{
case TLS_CRYPT:
@ -3666,6 +3715,11 @@ class ProtoContext
// trigger a protocol renegotiation
void renegotiate()
{
// set up dynamic tls-crypt keys when the first rekeying happens
// primary key_id 0 indicates that it is the first rekey
if (conf().dynamic_tls_crypt_enabled() && primary && primary->key_id() == 0)
set_dynamic_tls_crypt(conf(), primary);
// initialize secondary key context
new_secondary_key(true);
secondary->start();
@ -4091,6 +4145,11 @@ class ProtoContext
// we're getting a request from peer to renegotiate.
bool renegotiate_request(Packet &pkt)
{
// set up dynamic tls-crypt keys when the first rekeying happens
// primary key_id 0 indicates that it is the first rekey
if (conf().dynamic_tls_crypt_enabled() && primary && primary->key_id() == 0)
set_dynamic_tls_crypt(conf(), primary);
if (KeyContext::validate(pkt.buffer(), *this, now_))
{
new_secondary_key(false);

View File

@ -947,6 +947,7 @@ int test(const int thread_num)
cp->tls_crypt_factory.reset(new CryptoTLSCryptFactory<ClientCryptoAPI>());
cp->tls_key.parse(tls_auth_key);
cp->set_tls_crypt_algs();
cp->tls_crypt_ = ClientProtoContext::Config::TLSCrypt::V1;
#endif
#ifdef USE_TLS_CRYPT_V2
cp->tls_crypt_factory.reset(new CryptoTLSCryptFactory<ClientCryptoAPI>());
@ -957,7 +958,7 @@ int test(const int thread_num)
tls_crypt_v2_key.extract_key(cp->tls_key);
tls_crypt_v2_key.extract_wkc(cp->wkc);
}
cp->tls_crypt_v2 = true;
cp->tls_crypt_ = ClientProtoContext::Config::TLSCrypt::V2;
#endif
cp->pid_mode = PacketIDReceive::UDP_MODE;
#if defined(HANDSHAKE_WINDOW)
@ -1035,6 +1036,7 @@ int test(const int thread_num)
sp->tls_crypt_factory.reset(new CryptoTLSCryptFactory<ClientCryptoAPI>());
sp->tls_key.parse(tls_auth_key);
sp->set_tls_crypt_algs();
cp->tls_crypt_ = ClientProtoContext::Config::TLSCrypt::V1;
#endif
#ifdef USE_TLS_CRYPT_V2
sp->tls_crypt_factory.reset(new CryptoTLSCryptFactory<ClientCryptoAPI>());
@ -1045,7 +1047,7 @@ int test(const int thread_num)
}
sp->set_tls_crypt_algs();
sp->tls_crypt_metadata_factory.reset(new CryptoTLSCryptMetadataFactory());
sp->tls_crypt_v2 = true;
sp->tls_crypt_ = ClientProtoContext::Config::TLSCrypt::V2;
#endif
sp->pid_mode = PacketIDReceive::UDP_MODE;
#if defined(HANDSHAKE_WINDOW)