0
0
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:
Antonio Quartulli 2017-06-30 23:07:10 +08:00
parent be38bbeb84
commit 9814079944
No known key found for this signature in database
GPG Key ID: F4556C5945830E6D
7 changed files with 89 additions and 22 deletions

View File

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

View File

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

View File

@ -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",

View File

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

View File

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

View File

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

View 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-----