0
0
mirror of https://github.com/OpenVPN/openvpn3.git synced 2024-09-20 04:02:15 +02:00
openvpn3/openvpn/dco/kocrypto.hpp
Antonio Quartulli 6eb1680099
ovpn-dco: add support for configuring ChaCha20Poly1305 as data channel cipher
Extend the ovpn-dco module to allow the user to specify ChaCha20Poly1305
as data channel cipher.
Same as AES-GCM, it also belongs to the AEAD family and its nonce length
is 12 bytes.

Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
2020-11-17 15:49:36 +01:00

146 lines
4.3 KiB
C++

// OpenVPN -- An application to securely tunnel IP networks
// over a single port, with support for SSL/TLS-based
// session authentication and key exchange,
// packet encryption, packet authentication, and
// packet compression.
//
// Copyright (C) 2012-2020 OpenVPN Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License Version 3
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program in the COPYING file.
// If not, see <http://www.gnu.org/licenses/>.
// kovpn crypto wrappers
#pragma once
#include <cstring> // for std::memset, std::memcpy
#include <utility> // for std::move
#include <openvpn/common/size.hpp>
#include <openvpn/common/exception.hpp>
#include <openvpn/common/rc.hpp>
#include <openvpn/frame/frame.hpp>
#include <openvpn/crypto/cryptodc.hpp>
#include <openvpn/crypto/bs64_data_limit.hpp>
namespace openvpn {
namespace KoRekey {
OPENVPN_EXCEPTION(korekey_error);
struct Info {
Info() {}
Info(const CryptoDCContext::Ptr& dc_context_delegate_arg,
const unsigned int key_id_arg,
const Frame::Ptr& frame_arg)
: dc_context_delegate(dc_context_delegate_arg),
key_id(key_id_arg),
frame(frame_arg)
{
}
CryptoDCContext::Ptr dc_context_delegate;
CompressContext comp_ctx;
unsigned int key_id = 0;
int remote_peer_id = -1;
bool tcp_linear = false;
StaticKey encrypt_cipher;
StaticKey encrypt_hmac;
StaticKey decrypt_cipher;
StaticKey decrypt_hmac;
Frame::Ptr frame;
};
class Key
{
// noncopyable because of "opk.primary = &key" below
Key(const Key&) = delete;
Key& operator=(const Key&) = delete;
public:
static void validate(const CryptoAlgs::Type cipher,
const CryptoAlgs::Type digest)
{
const CryptoAlgs::Alg& calg = CryptoAlgs::get(cipher);
const CryptoAlgs::Alg& halg = CryptoAlgs::get(digest);
switch (cipher)
{
case CryptoAlgs::AES_128_GCM:
case CryptoAlgs::AES_192_GCM:
case CryptoAlgs::AES_256_GCM:
case CryptoAlgs::AES_128_CBC:
case CryptoAlgs::AES_192_CBC:
case CryptoAlgs::AES_256_CBC:
case CryptoAlgs::BF_CBC:
#ifdef ENABLE_OVPNDCO
case CryptoAlgs::CHACHA20_POLY1305:
case CryptoAlgs::NONE:
#endif
break;
default:
OPENVPN_THROW(korekey_error, "cipher alg " << calg.name() << " is not currently supported by kovpn");
}
if (calg.mode() == CryptoAlgs::CBC_HMAC)
{
switch (digest)
{
case CryptoAlgs::SHA1:
case CryptoAlgs::SHA256:
#ifdef ENABLE_OVPNDCO
case CryptoAlgs::NONE:
#endif
break;
default:
OPENVPN_THROW(korekey_error, "HMAC alg " << halg.name() << " is not currently supported by kovpn");
}
}
}
Key() {}
protected:
const unsigned char *verify_key(const char *title, const StaticKey& sk, const size_t size_required)
{
if (sk.size() < size_required)
OPENVPN_THROW(korekey_error, title << ": insufficient key material, provided=" << sk.size() << " required=" << size_required);
return sk.data();
}
void set_nonce_tail(const char *title, unsigned char *dest, const size_t dest_size, const StaticKey& src)
{
const int NONCE_TAIL_SIZE = CryptoAlgs::AEAD_NONCE_TAIL_SIZE;
const unsigned char *k = verify_key(title, src, NONCE_TAIL_SIZE);
if (dest_size < NONCE_TAIL_SIZE)
OPENVPN_THROW(korekey_error, title << ": cannot set");
std::memcpy(dest, k, NONCE_TAIL_SIZE);
// if dest is larger than NONCE_TAIL_SIZE, zero remaining bytes
if (dest_size > NONCE_TAIL_SIZE)
std::memset(dest + NONCE_TAIL_SIZE, 0, dest_size - NONCE_TAIL_SIZE);
}
};
}
}
#ifdef ENABLE_KOVPN
#include <openvpn/kovpn/kovpnkocrypto.hpp>
#elif ENABLE_OVPNDCO
#include <openvpn/dco/ovpndcokocrypto.hpp>
#else
#error either ENABLE_KOVPN or ENABLE_OVPNDCO must be defined
#endif