mirror of
https://github.com/OpenVPN/openvpn3.git
synced 2024-09-20 04:02:15 +02:00
tls-crypt-v2: implement abstract metadata parser
The metadata that may be possibly be contained in the WKc has to be verified by means of a user implemented behaviour. Implement an abstract class that exports a verify() method to be used for this purpose. Users can extend this class and override the verify() method with their own. A basic implementation is also provided: it will just ignore the metadata (if any) and report success to the core. Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
This commit is contained in:
parent
be38bbeb84
commit
9814079944
@ -693,6 +693,7 @@ namespace openvpn {
|
||||
cp->dc_deferred = true; // defer data channel setup until after options pull
|
||||
cp->tls_auth_factory.reset(new CryptoOvpnHMACFactory<SSLLib::CryptoAPI>());
|
||||
cp->tls_crypt_factory.reset(new CryptoTLSCryptFactory<SSLLib::CryptoAPI>());
|
||||
cp->tls_crypt_metadata_factory.reset(new CryptoTLSCryptMetadataFactory());
|
||||
cp->tlsprf_factory.reset(new CryptoTLSPRFFactory<SSLLib::CryptoAPI>());
|
||||
cp->ssl_factory = cc->new_factory();
|
||||
cp->load(opt, *proto_context_options, config.default_key_direction, false);
|
||||
|
@ -155,6 +155,44 @@ namespace openvpn {
|
||||
};
|
||||
|
||||
const std::string TLSCryptV2ClientKey::tls_crypt_v2_client_key_name = "OpenVPN tls-crypt-v2 client key";
|
||||
|
||||
// the user can extend the TLSCryptMetadata and the TLSCryptMetadataFactory
|
||||
// classes to implement its own metadata verification method.
|
||||
//
|
||||
// default method is to *ignore* the metadata contained in the WKc sent by the client
|
||||
class TLSCryptMetadata : public RC<thread_unsafe_refcount>
|
||||
{
|
||||
public:
|
||||
typedef RCPtr<TLSCryptMetadata> Ptr;
|
||||
|
||||
// override this method with your own verification mechanism.
|
||||
//
|
||||
// If type is -1 it means that metadata is empty.
|
||||
//
|
||||
virtual bool verify(int type, Buffer& metadata) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// abstract class to be extended when creating other factories
|
||||
class TLSCryptMetadataFactory : public RC<thread_unsafe_refcount>
|
||||
{
|
||||
public:
|
||||
typedef RCPtr<TLSCryptMetadataFactory> Ptr;
|
||||
|
||||
virtual TLSCryptMetadata::Ptr new_obj() = 0;
|
||||
};
|
||||
|
||||
// factory implementation for the basic verification method
|
||||
class CryptoTLSCryptMetadataFactory : public TLSCryptMetadataFactory
|
||||
{
|
||||
public:
|
||||
TLSCryptMetadata::Ptr new_obj()
|
||||
{
|
||||
return new TLSCryptMetadata();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* OPENVPN_CRYPTO_TLS_CRYPT_V2_H */
|
||||
|
@ -70,6 +70,7 @@ namespace openvpn {
|
||||
PRIMARY_EXPIRE, // primary key context expired
|
||||
TLS_VERSION_MIN, // peer cannot handshake at our minimum required TLS version
|
||||
TLS_AUTH_FAIL, // tls-auth HMAC verification failed
|
||||
TLS_CRYPT_META_FAIL, // tls-crypt-v2 metadata verification failed
|
||||
CERT_VERIFY_FAIL, // peer certificate verification failure
|
||||
PEM_PASSWORD_FAIL, // incorrect or missing PEM private key decryption password
|
||||
AUTH_FAILED, // general authentication failure
|
||||
@ -145,6 +146,7 @@ namespace openvpn {
|
||||
"PRIMARY_EXPIRE",
|
||||
"TLS_VERSION_MIN",
|
||||
"TLS_AUTH_FAIL",
|
||||
"TLS_CRYPT_META_FAIL",
|
||||
"CERT_VERIFY_FAIL",
|
||||
"PEM_PASSWORD_FAIL",
|
||||
"AUTH_FAILED",
|
||||
|
@ -305,6 +305,8 @@ namespace openvpn {
|
||||
TLSCryptFactory::Ptr tls_crypt_factory;
|
||||
TLSCryptContext::Ptr tls_crypt_context;
|
||||
|
||||
TLSCryptMetadataFactory::Ptr tls_crypt_metadata_factory;
|
||||
|
||||
// reliability layer parms
|
||||
reliable::id_t reliable_window = 0;
|
||||
size_t max_ack_list = 0;
|
||||
@ -2690,11 +2692,16 @@ namespace openvpn {
|
||||
plaintext.read(client_key.raw_alloc(), OpenVPNStaticKey::KEY_SIZE);
|
||||
proto.reset_tls_crypt(*proto.config, client_key);
|
||||
|
||||
// check existence of optional metadata
|
||||
size_t metadata_size = decrypt_bytes - OpenVPNStaticKey::KEY_SIZE;
|
||||
if (metadata_size > 0)
|
||||
OPENVPN_LOG("tls-crypt-v2: received metadata (" << metadata_size << " bytes) - IGNORING");
|
||||
// metadata is ignored at the moment
|
||||
// verify metadata
|
||||
int metadata_type = -1;
|
||||
if (!plaintext.empty())
|
||||
metadata_type = plaintext.pop_front();
|
||||
|
||||
if (!proto.tls_crypt_metadata->verify(metadata_type, plaintext))
|
||||
{
|
||||
proto.stats->error(Error::TLS_CRYPT_META_FAIL);
|
||||
return false;
|
||||
}
|
||||
|
||||
// virtually remove the WKc from the packet
|
||||
recv.set_size(tls_frame_size);
|
||||
@ -3048,6 +3055,8 @@ namespace openvpn {
|
||||
//mode should not be specified when slicing
|
||||
tls_crypt_server->init(c.tls_key.slice(OpenVPNStaticKey::HMAC),
|
||||
c.tls_key.slice(OpenVPNStaticKey::CIPHER));
|
||||
|
||||
tls_crypt_metadata = c.tls_crypt_metadata_factory->new_obj();
|
||||
}
|
||||
|
||||
void reset()
|
||||
@ -3767,6 +3776,7 @@ namespace openvpn {
|
||||
TLSCryptInstance::Ptr tls_crypt_recv;
|
||||
|
||||
TLSCryptInstance::Ptr tls_crypt_server;
|
||||
TLSCryptMetadata::Ptr tls_crypt_metadata;
|
||||
|
||||
PacketIDSend ta_pid_send;
|
||||
PacketIDReceive ta_pid_recv;
|
||||
|
@ -835,6 +835,7 @@ int test(const int thread_num)
|
||||
const std::string server_key = read_text("server.key");
|
||||
const std::string dh_pem = read_text("dh.pem");
|
||||
const std::string tls_auth_key = read_text("tls-auth.key");
|
||||
const std::string tls_crypt_v2_server_key = read_text("tls-crypt-v2-server.key");
|
||||
const std::string tls_crypt_v2_client_key = read_text("tls-crypt-v2-client.key");
|
||||
|
||||
// client config
|
||||
@ -894,10 +895,12 @@ int test(const int thread_num)
|
||||
#ifdef USE_TLS_CRYPT_V2
|
||||
cp->tls_crypt_factory.reset(new CryptoTLSCryptFactory<ClientCryptoAPI>());
|
||||
cp->set_tls_crypt_algs(CryptoAlgs::lookup("SHA256"), CryptoAlgs::lookup("AES-256-CTR"));
|
||||
TLSCryptV2ClientKey tls_crypt_v2_key(cp->tls_crypt_context);
|
||||
tls_crypt_v2_key.parse(tls_crypt_v2_client_key);
|
||||
tls_crypt_v2_key.extract_key(cp->tls_key);
|
||||
tls_crypt_v2_key.extract_wkc(cp->wkc);
|
||||
{
|
||||
TLSCryptV2ClientKey tls_crypt_v2_key(cp->tls_crypt_context);
|
||||
tls_crypt_v2_key.parse(tls_crypt_v2_client_key);
|
||||
tls_crypt_v2_key.extract_key(cp->tls_key);
|
||||
tls_crypt_v2_key.extract_wkc(cp->wkc);
|
||||
}
|
||||
cp->tls_crypt_v2 = true;
|
||||
#endif
|
||||
cp->reliable_window = 4;
|
||||
@ -970,12 +973,20 @@ int test(const int thread_num)
|
||||
sp->set_tls_auth_digest(CryptoAlgs::lookup(PROTO_DIGEST));
|
||||
sp->key_direction = 1;
|
||||
#endif
|
||||
#if defined(USE_TLS_CRYPT) || defined(USE_TLS_CRYPT_V2)
|
||||
#if defined(USE_TLS_CRYPT)
|
||||
sp->tls_crypt_factory.reset(new CryptoTLSCryptFactory<ClientCryptoAPI>());
|
||||
sp->tls_key.parse(tls_auth_key);
|
||||
sp->set_tls_crypt_algs(CryptoAlgs::lookup("SHA256"), CryptoAlgs::lookup("AES-256-CTR"));
|
||||
#endif
|
||||
#ifdef USE_TLS_CRYPT_V2
|
||||
sp->tls_crypt_factory.reset(new CryptoTLSCryptFactory<ClientCryptoAPI>());
|
||||
{
|
||||
TLSCryptV2ServerKey tls_crypt_v2_key;
|
||||
tls_crypt_v2_key.parse(tls_crypt_v2_server_key);
|
||||
tls_crypt_v2_key.extract_key(sp->tls_key);
|
||||
}
|
||||
sp->set_tls_crypt_algs(CryptoAlgs::lookup("SHA256"), CryptoAlgs::lookup("AES-256-CTR"));
|
||||
sp->tls_crypt_metadata_factory.reset(new CryptoTLSCryptMetadataFactory());
|
||||
sp->tls_crypt_v2 = true;
|
||||
#endif
|
||||
sp->reliable_window = 4;
|
||||
|
@ -1,14 +1,14 @@
|
||||
-----BEGIN OpenVPN tls-crypt-v2 client key-----
|
||||
lxflRree2ic6dq7H6fR0nuNEv26m/kMm/Xt0kMPjAkLYfu5XFLTU3xELudrGMyWQ
|
||||
vVbHRBzN/14+BU+RW8rc1Ub14EX6rXwpKaQmCh28/FWKBK+4Bzcwb1bPXBMLEI1j
|
||||
aFmfgyKFYsOSGqkNtAT+PdRXTTZBwmvSfH2BwqhrwoIv+3W6KUnqLOlsjvDext6K
|
||||
/n6HXPyAgOBcCAVZUjIAzcd9HTc+oJKYFkp4zOPDCQ0RmcnCqWq/I6F9imzw8N+t
|
||||
vkv9yPaTQEINI6wzHWDNc18YsLyHbgGdeYyMZLBMSVWJzospQot6J7e5uVkEmc3N
|
||||
2dtPE0KnYeGqr0dihjgRZkKnKnwmsZ4rpu4Ue3+HITQ23v0bNdtwOAaHZkbdSM3c
|
||||
At3nKXzWT5jCoZlqZWGsy1gza3WUm4Z4pLFmfoaxaF3ImRvtEvqgHBurFbokYmGv
|
||||
VuCpuGeAJq3gQ0Z/lY89DKuj7B8htStSCzoubrh32dBwlYWkN1HrNrk+pwbVcTe7
|
||||
BX0nPnYILF+78F6y4VYI33PBiwtE8D69FGDq38zcK+LJIPJB7t1m42svJJ6u6mGN
|
||||
YRevm+zVYsbT/pA/wU+gIBoW1K5pe+euTBPSHe/PCxQ0Y+RiD7aOj8sScx+xfa8O
|
||||
RRJ0IwgoBTAkEyW7PmW4SEYUFZxEe9dAVlwmhCmoA99Vpz4I9hiS9a/TVEXCnLWy
|
||||
U/RPr7C84ehaZs7I8iY8ZQ==
|
||||
fxgWlYpYT1H8ZCW3/139Ip6WSAa2QQZUu64N/x3g7RzhYuaInPRpP9GLpeDpj/PP
|
||||
MOa0LuvbIr9Wm6V4+WUO+R8hOdfIMwtBlRleMDedFNRD5h1DCpoDdpgr5CxaPyqO
|
||||
H6eCvNP7POmqdGJyo9L6H9ndyetQp4r/8wXeYWSkcJKsIJsmyBqRzuODTENGYCqG
|
||||
FN3+XcUrEMYUyvb/c8NqDVQ6xpwc9+6N7840encSMZPYCq6o8J1QXZJ8sMoBEPa1
|
||||
gVtLCsPXp2oTs1h82NBpxO8BNPNFz1xIG+2Zy1NpU8PONnr0rtCRPNU7ejsG+p2I
|
||||
vRDt3VOf+3aD2eVFesR4NAWYTZlxg3eLG4zD/xSiGblBltbB/7qGPxgK6WOP2XD/
|
||||
V0Yh+TruX2vo4xjEXqV1umTx9K8u6nvaC8uv/72NsvPWkuAOEpY6qpDrqiya+zod
|
||||
zjrlKdLmftaTEMGURDIjooNygFOAania7UhLWOjhnzZFntLHoYmskF0C7om4CqPR
|
||||
dhf1OuyaD436yQVdt3t/8sjBGuY4hQZ3PuMKDEsHEzmq8bYwfmDf3U8IsK39NbXO
|
||||
Bh7Q3Gxxy0vTP2TRsGUbePh5ZveVtCJGe79tjtveLdEVdh+TsMB2xo/ZLFfjDPOx
|
||||
6xvj5xKQtyou5YawuniHn5nrDWbyARQDTmVl7a5w5HvK3SbuVDrJsuLiRohfKyah
|
||||
M17SAY5reFev6+piR+zT64zwTYdU20i28gEr
|
||||
-----END OpenVPN tls-crypt-v2 client key-----
|
||||
|
5
test/ssl/tls-crypt-v2-server.key
Normal file
5
test/ssl/tls-crypt-v2-server.key
Normal file
@ -0,0 +1,5 @@
|
||||
-----BEGIN OpenVPN tls-crypt-v2 server key-----
|
||||
hn6VWraZG0o64iPI7faGYkwTMajjqhXqG2kC1X19jCl+aXhWPSgmDbRCT/pSfjLZ
|
||||
a2pKXP6DGdi3nuINKuPw4655AcuMaBe4b45+zJz5xk92NnNosLaTsanXtjfBNOK5
|
||||
S/M1f4cLZViVsJTDSMcINK/RCclWVK+IFi//CThZQM8=
|
||||
-----END OpenVPN tls-crypt-v2 server key-----
|
Loading…
Reference in New Issue
Block a user