mirror of
https://github.com/OpenVPN/openvpn3.git
synced 2024-09-20 04:02:15 +02:00
Added CryptoAlgs for managing crypto algorithms independently of
underlying crypto implementation. Modified proto.hpp to use the new CryptoAlgs types for cipher/digest selection. Added initial PolarSSL implementation for cipher/digest selection using CryptoAlgs types. Note: this implementation is incomplete, see fixmes.
This commit is contained in:
parent
9145145b64
commit
bd04ed3755
@ -50,9 +50,25 @@ namespace openvpn {
|
||||
encrypt_.prng = prng;
|
||||
}
|
||||
|
||||
virtual void init_encrypt_cipher(const StaticKey& key, const int mode)
|
||||
// Encrypt/Decrypt
|
||||
|
||||
/* returns true if packet ID is close to wrapping */
|
||||
virtual bool encrypt(BufferAllocated& buf, const PacketID::time_t now)
|
||||
{
|
||||
encrypt_.cipher.init(cipher, key, mode);
|
||||
encrypt_.encrypt(buf, now);
|
||||
return encrypt_.pid_send.wrap_warning();
|
||||
}
|
||||
|
||||
virtual Error::Type decrypt(BufferAllocated& buf, const PacketID::time_t now)
|
||||
{
|
||||
return decrypt_.decrypt(buf, now);
|
||||
}
|
||||
|
||||
// Initialization
|
||||
|
||||
virtual void init_encrypt_cipher(const StaticKey& key)
|
||||
{
|
||||
encrypt_.cipher.init(cipher, key, CRYPTO_API::CipherContext::ENCRYPT);
|
||||
}
|
||||
|
||||
virtual void init_encrypt_hmac(const StaticKey& key)
|
||||
@ -65,9 +81,9 @@ namespace openvpn {
|
||||
encrypt_.pid_send.init(form);
|
||||
}
|
||||
|
||||
virtual void init_decrypt_cipher(const StaticKey& key, const int mode)
|
||||
virtual void init_decrypt_cipher(const StaticKey& key)
|
||||
{
|
||||
decrypt_.cipher.init(cipher, key, mode);
|
||||
decrypt_.cipher.init(cipher, key, CRYPTO_API::CipherContext::DECRYPT);
|
||||
}
|
||||
|
||||
virtual void init_decrypt_hmac(const StaticKey& key)
|
||||
@ -83,18 +99,20 @@ namespace openvpn {
|
||||
decrypt_.pid_recv.init(mode, form, seq_backtrack, time_backtrack, name, unit, stats_arg);
|
||||
}
|
||||
|
||||
/* returns true if packet ID is close to wrapping */
|
||||
virtual bool encrypt(BufferAllocated& buf, const PacketID::time_t now)
|
||||
// Indicate whether or not cipher/digest is defined
|
||||
|
||||
virtual bool cipher_defined() const
|
||||
{
|
||||
encrypt_.encrypt(buf, now);
|
||||
return encrypt_.pid_send.wrap_warning();
|
||||
return cipher.defined();
|
||||
}
|
||||
|
||||
virtual Error::Type decrypt(BufferAllocated& buf, const PacketID::time_t now)
|
||||
virtual bool digest_defined() const
|
||||
{
|
||||
return decrypt_.decrypt(buf, now);
|
||||
return digest.defined();
|
||||
}
|
||||
|
||||
// Rekeying
|
||||
|
||||
virtual void rekey(const typename Base::RekeyType type)
|
||||
{
|
||||
}
|
||||
@ -115,12 +133,12 @@ namespace openvpn {
|
||||
public:
|
||||
typedef boost::intrusive_ptr<CryptoContextCHM> Ptr;
|
||||
|
||||
CryptoContextCHM(const typename CRYPTO_API::Cipher& cipher_arg,
|
||||
const typename CRYPTO_API::Digest& digest_arg,
|
||||
CryptoContextCHM(const CryptoAlgs::Type cipher_arg,
|
||||
const CryptoAlgs::Type digest_arg,
|
||||
const Frame::Ptr& frame_arg,
|
||||
const typename PRNG<CRYPTO_API>::Ptr& prng_arg)
|
||||
: cipher(cipher_arg),
|
||||
digest(digest_arg),
|
||||
: cipher(CryptoAlgs::legal_dc_cipher(cipher_arg)),
|
||||
digest(CryptoAlgs::legal_dc_digest(digest_arg)),
|
||||
frame(frame_arg),
|
||||
prng(prng_arg)
|
||||
{
|
||||
@ -131,6 +149,32 @@ namespace openvpn {
|
||||
return new CryptoCHM<CRYPTO_API>(cipher, digest, frame, prng);
|
||||
}
|
||||
|
||||
// Info for ProtoContext::options_string
|
||||
|
||||
virtual std::string cipher_name() const
|
||||
{
|
||||
return cipher.defined() ? cipher.name() : "[null-cipher]";
|
||||
}
|
||||
|
||||
virtual std::string digest_name() const
|
||||
{
|
||||
return digest.defined() ? digest.name() : "[null-digest]";
|
||||
}
|
||||
|
||||
virtual size_t key_size() const
|
||||
{
|
||||
return cipher.defined() ? cipher.key_length_in_bits() : 0;
|
||||
}
|
||||
|
||||
// Info for ProtoContext::link_mtu_adjust
|
||||
|
||||
virtual size_t encap_overhead() const
|
||||
{
|
||||
return (digest.defined() ? digest.size() : 0) + // HMAC
|
||||
(cipher.defined() ? cipher.iv_length() : 0) + // Cipher IV
|
||||
(cipher.defined() ? cipher.block_size() : 0); // worst-case cipher padding expansion
|
||||
}
|
||||
|
||||
private:
|
||||
typename CRYPTO_API::Cipher cipher;
|
||||
typename CRYPTO_API::Digest digest;
|
||||
|
147
openvpn/crypto/cryptoalgs.hpp
Normal file
147
openvpn/crypto/cryptoalgs.hpp
Normal file
@ -0,0 +1,147 @@
|
||||
// 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) 2013-2014 OpenVPN Technologies, 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/>.
|
||||
|
||||
// Crypto algorithms
|
||||
|
||||
#ifndef OPENVPN_CRYPTO_CRYPTOALGS_H
|
||||
#define OPENVPN_CRYPTO_CRYPTOALGS_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <openvpn/common/exception.hpp>
|
||||
#include <openvpn/common/string.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
namespace CryptoAlgs {
|
||||
|
||||
OPENVPN_EXCEPTION(crypto_alg);
|
||||
OPENVPN_SIMPLE_EXCEPTION(crypto_alg_index);
|
||||
|
||||
enum Type {
|
||||
NONE=0,
|
||||
|
||||
// CBC ciphers
|
||||
AES_128_CBC,
|
||||
AES_192_CBC,
|
||||
AES_256_CBC,
|
||||
DES_CBC,
|
||||
DES_EDE3_CBC,
|
||||
BF_CBC,
|
||||
|
||||
// AEAD ciphers
|
||||
AES_128_GCM,
|
||||
AES_192_GCM,
|
||||
AES_256_GCM,
|
||||
|
||||
// digests
|
||||
MD4,
|
||||
MD5,
|
||||
SHA1,
|
||||
SHA224,
|
||||
SHA256,
|
||||
SHA384,
|
||||
SHA512,
|
||||
|
||||
SIZE,
|
||||
};
|
||||
|
||||
enum Mode {
|
||||
MODE_UNDEF=0,
|
||||
CBC_HMAC,
|
||||
AEAD,
|
||||
};
|
||||
|
||||
enum AlgFlags {
|
||||
F_CIPHER=(1<<0), // alg is a cipher
|
||||
F_DIGEST=(1<<1), // alg is a digest
|
||||
F_ALLOW_DC=(1<<2), // alg may be used in OpenVPN data channel
|
||||
};
|
||||
|
||||
struct Alg
|
||||
{
|
||||
const char *name;
|
||||
unsigned int flags;
|
||||
Mode mode;
|
||||
};
|
||||
|
||||
const Alg algs[] = { // NOTE: MUST be indexed by CryptoAlgs::Type (CONST GLOBAL)
|
||||
{ "NONE", F_CIPHER|F_DIGEST|F_ALLOW_DC, CBC_HMAC },
|
||||
{ "AES-128-CBC", F_CIPHER|F_ALLOW_DC, CBC_HMAC },
|
||||
{ "AES-192-CBC", F_CIPHER|F_ALLOW_DC, CBC_HMAC },
|
||||
{ "AES-256-CBC", F_CIPHER|F_ALLOW_DC, CBC_HMAC },
|
||||
{ "DES-CBC", F_CIPHER|F_ALLOW_DC, CBC_HMAC },
|
||||
{ "DES-EDE3-CBC", F_CIPHER|F_ALLOW_DC, CBC_HMAC },
|
||||
{ "BF-CBC", F_CIPHER|F_ALLOW_DC, CBC_HMAC },
|
||||
{ "AES-128-GCM", F_CIPHER|F_ALLOW_DC, AEAD },
|
||||
{ "AES-192-GCM", F_CIPHER|F_ALLOW_DC, AEAD },
|
||||
{ "AES-256-GCM", F_CIPHER|F_ALLOW_DC, AEAD },
|
||||
{ "MD4", F_DIGEST, MODE_UNDEF },
|
||||
{ "MD5", F_DIGEST|F_ALLOW_DC, MODE_UNDEF },
|
||||
{ "SHA1", F_DIGEST|F_ALLOW_DC, MODE_UNDEF },
|
||||
{ "SHA224", F_DIGEST|F_ALLOW_DC, MODE_UNDEF },
|
||||
{ "SHA256", F_DIGEST|F_ALLOW_DC, MODE_UNDEF },
|
||||
{ "SHA384", F_DIGEST|F_ALLOW_DC, MODE_UNDEF },
|
||||
{ "SHA512", F_DIGEST|F_ALLOW_DC, MODE_UNDEF },
|
||||
};
|
||||
|
||||
inline const Alg& get(const Type type)
|
||||
{
|
||||
const size_t i = static_cast<size_t>(type);
|
||||
if (i >= SIZE)
|
||||
throw crypto_alg_index();
|
||||
return algs[i];
|
||||
}
|
||||
|
||||
inline Type lookup(const std::string& name)
|
||||
{
|
||||
for (size_t i = 0; i < SIZE; ++i)
|
||||
{
|
||||
const Alg& alg = algs[i];
|
||||
if (string::strcasecmp(name, alg.name) == 0)
|
||||
return static_cast<Type>(i);
|
||||
}
|
||||
OPENVPN_THROW(crypto_alg, name << ": not found");
|
||||
}
|
||||
|
||||
inline const char *name(const Type type)
|
||||
{
|
||||
return get(type).name;
|
||||
}
|
||||
|
||||
inline Type legal_dc_cipher(const Type type)
|
||||
{
|
||||
const Alg& alg = get(type);
|
||||
if ((alg.flags & (F_CIPHER|F_ALLOW_DC)) != (F_CIPHER|F_ALLOW_DC))
|
||||
OPENVPN_THROW(crypto_alg, alg.name << ": bad cipher");
|
||||
return type;
|
||||
}
|
||||
|
||||
inline Type legal_dc_digest(const Type type)
|
||||
{
|
||||
const Alg& alg = get(type);
|
||||
if ((alg.flags & (F_DIGEST|F_ALLOW_DC)) != (F_DIGEST|F_ALLOW_DC))
|
||||
OPENVPN_THROW(crypto_alg, alg.name << ": bad digest");
|
||||
return type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -31,6 +31,7 @@
|
||||
#include <openvpn/random/prng.hpp>
|
||||
#include <openvpn/crypto/static_key.hpp>
|
||||
#include <openvpn/crypto/packet_id.hpp>
|
||||
#include <openvpn/crypto/cryptoalgs.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
|
||||
@ -41,23 +42,6 @@ namespace openvpn {
|
||||
public:
|
||||
typedef boost::intrusive_ptr<CryptoDCBase> Ptr;
|
||||
|
||||
// Initialization
|
||||
|
||||
virtual void init_encrypt_cipher(const StaticKey& key, const int mode) = 0;
|
||||
|
||||
virtual void init_encrypt_hmac(const StaticKey& key) = 0;
|
||||
|
||||
virtual void init_encrypt_pid_send(const int form) = 0;
|
||||
|
||||
virtual void init_decrypt_cipher(const StaticKey& key, const int mode) = 0;
|
||||
|
||||
virtual void init_decrypt_hmac(const StaticKey& key) = 0;
|
||||
|
||||
virtual void init_decrypt_pid_recv(const int mode, const int form,
|
||||
const int seq_backtrack, const int time_backtrack,
|
||||
const char *name, const int unit,
|
||||
const SessionStats::Ptr& stats_arg) = 0;
|
||||
|
||||
// Encrypt/Decrypt
|
||||
|
||||
// returns true if packet ID is close to wrapping
|
||||
@ -65,6 +49,23 @@ namespace openvpn {
|
||||
|
||||
virtual Error::Type decrypt(BufferAllocated& buf, const PacketID::time_t now) = 0;
|
||||
|
||||
// Initialization
|
||||
|
||||
virtual void init_encrypt_cipher(const StaticKey& key) = 0;
|
||||
virtual void init_encrypt_hmac(const StaticKey& key) = 0;
|
||||
virtual void init_encrypt_pid_send(const int form) = 0;
|
||||
virtual void init_decrypt_cipher(const StaticKey& key) = 0;
|
||||
virtual void init_decrypt_hmac(const StaticKey& key) = 0;
|
||||
virtual void init_decrypt_pid_recv(const int mode, const int form,
|
||||
const int seq_backtrack, const int time_backtrack,
|
||||
const char *name, const int unit,
|
||||
const SessionStats::Ptr& stats_arg) = 0;
|
||||
|
||||
// Indicate whether or not cipher/digest is defined
|
||||
|
||||
virtual bool cipher_defined() const = 0;
|
||||
virtual bool digest_defined() const = 0;
|
||||
|
||||
// Rekeying
|
||||
|
||||
enum RekeyType {
|
||||
@ -85,6 +86,16 @@ namespace openvpn {
|
||||
typedef boost::intrusive_ptr<CryptoDCContext> Ptr;
|
||||
|
||||
virtual typename CryptoDCBase<CRYPTO_API>::Ptr new_obj(const unsigned int key_id) = 0;
|
||||
|
||||
// Info for ProtoContext::options_string
|
||||
|
||||
virtual std::string cipher_name() const = 0;
|
||||
virtual std::string digest_name() const = 0;
|
||||
virtual size_t key_size() const = 0;
|
||||
|
||||
// Info for ProtoContext::link_mtu_adjust
|
||||
|
||||
virtual size_t encap_overhead() const = 0;
|
||||
};
|
||||
|
||||
// Factory for CryptoDCContext objects
|
||||
@ -94,8 +105,8 @@ namespace openvpn {
|
||||
public:
|
||||
typedef boost::intrusive_ptr<CryptoDCFactory> Ptr;
|
||||
|
||||
virtual typename CryptoDCContext<CRYPTO_API>::Ptr new_obj(const typename CRYPTO_API::Cipher& cipher,
|
||||
const typename CRYPTO_API::Digest& digest) = 0;
|
||||
virtual typename CryptoDCContext<CRYPTO_API>::Ptr new_obj(const CryptoAlgs::Type cipher,
|
||||
const CryptoAlgs::Type digest) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -39,14 +39,14 @@ namespace openvpn {
|
||||
typedef boost::intrusive_ptr<CryptoDCSelect> Ptr;
|
||||
|
||||
CryptoDCSelect(const Frame::Ptr& frame_arg,
|
||||
const typename PRNG<CRYPTO_API>::Ptr& prng_arg)
|
||||
const typename PRNG<CRYPTO_API>::Ptr& prng_arg)
|
||||
: frame(frame_arg),
|
||||
prng(prng_arg)
|
||||
{
|
||||
}
|
||||
|
||||
virtual typename CryptoDCContext<CRYPTO_API>::Ptr new_obj(const typename CRYPTO_API::Cipher& cipher,
|
||||
const typename CRYPTO_API::Digest& digest)
|
||||
virtual typename CryptoDCContext<CRYPTO_API>::Ptr new_obj(const CryptoAlgs::Type cipher,
|
||||
const CryptoAlgs::Type digest)
|
||||
{
|
||||
// fixme -- handle AEAD modes as well
|
||||
return new CryptoContextCHM<CRYPTO_API>(cipher, digest, frame, prng);
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include <openvpn/common/types.hpp>
|
||||
#include <openvpn/common/exception.hpp>
|
||||
#include <openvpn/crypto/static_key.hpp>
|
||||
#include <openvpn/crypto/cryptoalgs.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
namespace PolarSSLCrypto {
|
||||
@ -45,23 +46,47 @@ namespace openvpn {
|
||||
friend class CipherContext;
|
||||
|
||||
public:
|
||||
OPENVPN_EXCEPTION(polarssl_cipher_not_found);
|
||||
OPENVPN_EXCEPTION(polarssl_cipher);
|
||||
OPENVPN_SIMPLE_EXCEPTION(polarssl_cipher_undefined);
|
||||
|
||||
Cipher() : cipher_(NULL) {}
|
||||
|
||||
Cipher(const std::string& name)
|
||||
Cipher()
|
||||
{
|
||||
const std::string translated_name = openvpn_to_cipher_name(name.c_str());
|
||||
cipher_ = cipher_info_from_string(translated_name.c_str());
|
||||
if (!cipher_)
|
||||
throw polarssl_cipher_not_found(translated_name);
|
||||
reset();
|
||||
}
|
||||
|
||||
Cipher(const CryptoAlgs::Type alg)
|
||||
{
|
||||
switch (type_ = alg)
|
||||
{
|
||||
case CryptoAlgs::NONE:
|
||||
reset();
|
||||
break;
|
||||
case CryptoAlgs::AES_128_CBC:
|
||||
cipher_ = cipher_info_from_type(POLARSSL_CIPHER_AES_128_CBC);
|
||||
break;
|
||||
case CryptoAlgs::AES_192_CBC:
|
||||
cipher_ = cipher_info_from_type(POLARSSL_CIPHER_AES_192_CBC);
|
||||
break;
|
||||
case CryptoAlgs::AES_256_CBC:
|
||||
cipher_ = cipher_info_from_type(POLARSSL_CIPHER_AES_256_CBC);
|
||||
break;
|
||||
case CryptoAlgs::DES_CBC:
|
||||
cipher_ = cipher_info_from_type(POLARSSL_CIPHER_DES_CBC);
|
||||
break;
|
||||
case CryptoAlgs::DES_EDE3_CBC:
|
||||
cipher_ = cipher_info_from_type(POLARSSL_CIPHER_DES_EDE3_CBC);
|
||||
break;
|
||||
case CryptoAlgs::BF_CBC:
|
||||
cipher_ = cipher_info_from_type(POLARSSL_CIPHER_BLOWFISH_CBC);
|
||||
break;
|
||||
default:
|
||||
OPENVPN_THROW(polarssl_cipher, CryptoAlgs::name(alg) << ": not usable");
|
||||
}
|
||||
}
|
||||
|
||||
std::string name() const
|
||||
{
|
||||
check_initialized();
|
||||
return cipher_name_to_openvpn(cipher_->name);
|
||||
return CryptoAlgs::name(type_);
|
||||
}
|
||||
|
||||
size_t key_length() const
|
||||
@ -91,6 +116,12 @@ namespace openvpn {
|
||||
bool defined() const { return cipher_ != NULL; }
|
||||
|
||||
private:
|
||||
void reset()
|
||||
{
|
||||
cipher_ = NULL;
|
||||
type_ = CryptoAlgs::NONE;
|
||||
}
|
||||
|
||||
const cipher_info_t *get() const
|
||||
{
|
||||
check_initialized();
|
||||
@ -105,24 +136,8 @@ namespace openvpn {
|
||||
#endif
|
||||
}
|
||||
|
||||
static std::string openvpn_to_cipher_name(const std::string& name)
|
||||
{
|
||||
const std::string n = boost::algorithm::to_upper_copy(name);
|
||||
if (boost::algorithm::starts_with(n, "BF-"))
|
||||
return "BLOWFISH-" + n.substr(3);
|
||||
else
|
||||
return n;
|
||||
}
|
||||
|
||||
static std::string cipher_name_to_openvpn(const std::string& name)
|
||||
{
|
||||
if (boost::algorithm::starts_with(name, "BLOWFISH-"))
|
||||
return "BF-" + name.substr(9);
|
||||
else
|
||||
return name;
|
||||
}
|
||||
|
||||
const cipher_info_t *cipher_;
|
||||
CryptoAlgs::Type type_;
|
||||
};
|
||||
|
||||
class CipherContext : boost::noncopyable
|
||||
|
@ -45,22 +45,58 @@ namespace openvpn {
|
||||
friend class HMACContext;
|
||||
|
||||
public:
|
||||
OPENVPN_EXCEPTION(polarssl_digest_not_found);
|
||||
OPENVPN_EXCEPTION(polarssl_digest_not_found); // fixme
|
||||
OPENVPN_EXCEPTION(polarssl_digest);
|
||||
OPENVPN_SIMPLE_EXCEPTION(polarssl_digest_undefined);
|
||||
|
||||
Digest() : digest_(NULL) {}
|
||||
Digest()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
Digest(const std::string& name)
|
||||
Digest(const std::string& name) // fixme
|
||||
{
|
||||
digest_ = md_info_from_string(name.c_str());
|
||||
if (!digest_)
|
||||
throw polarssl_digest_not_found(name);
|
||||
}
|
||||
|
||||
Digest(const CryptoAlgs::Type alg)
|
||||
{
|
||||
switch (type_ = alg)
|
||||
{
|
||||
case CryptoAlgs::NONE:
|
||||
reset();
|
||||
break;
|
||||
case CryptoAlgs::MD4:
|
||||
digest_ = md_info_from_type(POLARSSL_MD_MD4);
|
||||
break;
|
||||
case CryptoAlgs::MD5:
|
||||
digest_ = md_info_from_type(POLARSSL_MD_MD5);
|
||||
break;
|
||||
case CryptoAlgs::SHA1:
|
||||
digest_ = md_info_from_type(POLARSSL_MD_SHA1);
|
||||
break;
|
||||
case CryptoAlgs::SHA224:
|
||||
digest_ = md_info_from_type(POLARSSL_MD_SHA224);
|
||||
break;
|
||||
case CryptoAlgs::SHA256:
|
||||
digest_ = md_info_from_type(POLARSSL_MD_SHA256);
|
||||
break;
|
||||
case CryptoAlgs::SHA384:
|
||||
digest_ = md_info_from_type(POLARSSL_MD_SHA384);
|
||||
break;
|
||||
case CryptoAlgs::SHA512:
|
||||
digest_ = md_info_from_type(POLARSSL_MD_SHA512);
|
||||
break;
|
||||
default:
|
||||
OPENVPN_THROW(polarssl_digest, CryptoAlgs::name(alg) << ": not usable");
|
||||
}
|
||||
}
|
||||
|
||||
std::string name() const
|
||||
{
|
||||
check_initialized();
|
||||
return md_get_name(digest_);
|
||||
return CryptoAlgs::name(type_);
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
@ -79,6 +115,12 @@ namespace openvpn {
|
||||
private:
|
||||
Digest(const md_info_t *digest) : digest_(digest) {}
|
||||
|
||||
void reset()
|
||||
{
|
||||
digest_ = NULL;
|
||||
type_ = CryptoAlgs::NONE;
|
||||
}
|
||||
|
||||
const md_info_t *get() const
|
||||
{
|
||||
check_initialized();
|
||||
@ -94,6 +136,7 @@ namespace openvpn {
|
||||
}
|
||||
|
||||
const md_info_t *digest_;
|
||||
CryptoAlgs::Type type_;
|
||||
};
|
||||
|
||||
class DigestContext : boost::noncopyable
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include <openvpn/frame/frame.hpp>
|
||||
#include <openvpn/random/randapi.hpp>
|
||||
#include <openvpn/random/prng.hpp>
|
||||
#include <openvpn/crypto/cryptoalgs.hpp>
|
||||
#include <openvpn/crypto/cryptodc.hpp>
|
||||
#include <openvpn/crypto/cipher.hpp>
|
||||
#include <openvpn/crypto/hmac.hpp>
|
||||
@ -237,8 +238,8 @@ namespace openvpn {
|
||||
SSLFactoryAPI::Ptr ssl_factory;
|
||||
|
||||
// data channel context and factory
|
||||
typename DCContext::Ptr dc_context; // set with set_cipher_digest
|
||||
typename DCFactory::Ptr dc_factory;
|
||||
typename DCContext::Ptr dc_context; // set with set_cipher_digest
|
||||
|
||||
// master Frame object
|
||||
Frame::Ptr frame;
|
||||
@ -264,10 +265,6 @@ namespace openvpn {
|
||||
// compressor
|
||||
CompressContext comp_ctx;
|
||||
|
||||
// data channel parms
|
||||
typename CRYPTO_API::Cipher cipher; // set with set_cipher_digest
|
||||
typename CRYPTO_API::Digest digest; // set with set_cipher_digest
|
||||
|
||||
// tls_auth parms
|
||||
OpenVPNStaticKey tls_auth_key; // leave this undefined to disable tls_auth
|
||||
typename CRYPTO_API::Digest tls_auth_digest;
|
||||
@ -341,36 +338,39 @@ namespace openvpn {
|
||||
throw proto_option_error("bad dev-type");
|
||||
}
|
||||
|
||||
// cipher
|
||||
// data channel
|
||||
{
|
||||
const Option *o = opt.get_ptr("cipher");
|
||||
if (o)
|
||||
{
|
||||
const std::string& cipher_name = o->get(1, 128);
|
||||
if (cipher_name != "none")
|
||||
cipher = typename CRYPTO_API::Cipher(cipher_name);
|
||||
else
|
||||
cipher = typename CRYPTO_API::Cipher();
|
||||
}
|
||||
else
|
||||
cipher = typename CRYPTO_API::Cipher("BF-CBC");
|
||||
}
|
||||
CryptoAlgs::Type cipher = CryptoAlgs::NONE;
|
||||
CryptoAlgs::Type digest = CryptoAlgs::NONE;
|
||||
|
||||
// digest
|
||||
{
|
||||
const Option *o = opt.get_ptr("auth");
|
||||
if (o)
|
||||
{
|
||||
const std::string& auth_name = o->get(1, 128);
|
||||
if (auth_name != "none")
|
||||
digest = typename CRYPTO_API::Digest(auth_name);
|
||||
else
|
||||
digest = typename CRYPTO_API::Digest();
|
||||
}
|
||||
else
|
||||
digest = typename CRYPTO_API::Digest("SHA1");
|
||||
// cipher
|
||||
{
|
||||
const Option *o = opt.get_ptr("cipher");
|
||||
if (o)
|
||||
{
|
||||
const std::string& cipher_name = o->get(1, 128);
|
||||
if (cipher_name != "none")
|
||||
cipher = CryptoAlgs::lookup(cipher_name);
|
||||
}
|
||||
else
|
||||
cipher = CryptoAlgs::lookup("BF-CBC");
|
||||
}
|
||||
|
||||
// digest
|
||||
{
|
||||
const Option *o = opt.get_ptr("auth");
|
||||
if (o)
|
||||
{
|
||||
const std::string& auth_name = o->get(1, 128);
|
||||
if (auth_name != "none")
|
||||
digest = CryptoAlgs::lookup(auth_name);
|
||||
}
|
||||
else
|
||||
digest = CryptoAlgs::lookup("SHA1");
|
||||
}
|
||||
OPENVPN_LOG("************* CRYPTO CONFIG cipher=" << cipher << " digest=" << digest); // fixme
|
||||
set_cipher_digest(cipher, digest);
|
||||
}
|
||||
set_cipher_digest(); // fixme
|
||||
|
||||
// tls-auth
|
||||
{
|
||||
@ -378,7 +378,7 @@ namespace openvpn {
|
||||
if (o)
|
||||
{
|
||||
tls_auth_key.parse(o->get(1, 0));
|
||||
tls_auth_digest = digest;
|
||||
tls_auth_digest = typename CRYPTO_API::Digest("SHA256"); // fixme
|
||||
}
|
||||
}
|
||||
|
||||
@ -453,42 +453,45 @@ namespace openvpn {
|
||||
OPENVPN_THROW(process_server_push_error, "Problem accepting server-pushed parameter: " << e.what());
|
||||
}
|
||||
|
||||
// cipher
|
||||
std::string new_cipher;
|
||||
try {
|
||||
const Option *o = opt.get_ptr("cipher");
|
||||
if (o)
|
||||
{
|
||||
new_cipher = o->get(1, 128);
|
||||
if (new_cipher != "none")
|
||||
cipher = typename CRYPTO_API::Cipher(new_cipher);
|
||||
else
|
||||
cipher = typename CRYPTO_API::Cipher();
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
OPENVPN_THROW(process_server_push_error, "Problem accepting server-pushed cipher '" << new_cipher << "': " << e.what());
|
||||
}
|
||||
// data channel
|
||||
{
|
||||
CryptoAlgs::Type cipher = CryptoAlgs::NONE;
|
||||
CryptoAlgs::Type digest = CryptoAlgs::NONE;
|
||||
|
||||
// digest
|
||||
std::string new_digest;
|
||||
try {
|
||||
const Option *o = opt.get_ptr("auth");
|
||||
if (o)
|
||||
{
|
||||
new_digest = o->get(1, 128);
|
||||
if (new_digest != "none")
|
||||
digest = typename CRYPTO_API::Digest(new_digest);
|
||||
else
|
||||
digest = typename CRYPTO_API::Digest();
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
OPENVPN_THROW(process_server_push_error, "Problem accepting server-pushed digest '" << new_digest << "': " << e.what());
|
||||
// cipher
|
||||
std::string new_cipher;
|
||||
try {
|
||||
const Option *o = opt.get_ptr("cipher");
|
||||
if (o)
|
||||
{
|
||||
new_cipher = o->get(1, 128);
|
||||
if (new_cipher != "none")
|
||||
cipher = CryptoAlgs::lookup(new_cipher);
|
||||
}
|
||||
}
|
||||
set_cipher_digest(); // fixme
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
OPENVPN_THROW(process_server_push_error, "Problem accepting server-pushed cipher '" << new_cipher << "': " << e.what());
|
||||
}
|
||||
|
||||
// digest
|
||||
std::string new_digest;
|
||||
try {
|
||||
const Option *o = opt.get_ptr("auth");
|
||||
if (o)
|
||||
{
|
||||
new_digest = o->get(1, 128);
|
||||
if (new_digest != "none")
|
||||
digest = CryptoAlgs::lookup(new_digest);
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
OPENVPN_THROW(process_server_push_error, "Problem accepting server-pushed digest '" << new_digest << "': " << e.what());
|
||||
}
|
||||
OPENVPN_LOG("************* CRYPTO PULL cipher=" << cipher << " digest=" << digest); // fixme
|
||||
set_cipher_digest(cipher, digest);
|
||||
}
|
||||
|
||||
// compression
|
||||
std::string new_comp;
|
||||
@ -536,7 +539,7 @@ namespace openvpn {
|
||||
throw proto_option_error("transport protocol undefined");
|
||||
}
|
||||
|
||||
void set_cipher_digest() // fixme
|
||||
void set_cipher_digest(const CryptoAlgs::Type cipher, const CryptoAlgs::Type digest)
|
||||
{
|
||||
dc_context = dc_factory->new_obj(cipher, digest);
|
||||
}
|
||||
@ -581,9 +584,12 @@ namespace openvpn {
|
||||
if (key_direction >= 0)
|
||||
out << ",keydir " << key_direction;
|
||||
|
||||
out << ",cipher " << (cipher.defined() ? cipher.name() : "[null-cipher]");
|
||||
out << ",auth " << (digest.defined() ? digest.name() : "[null-digest]");
|
||||
out << ",keysize " << (cipher.defined() ? cipher.key_length_in_bits() : 0);
|
||||
if (dc_context)
|
||||
{
|
||||
out << ",cipher " << dc_context->cipher_name();
|
||||
out << ",auth " << dc_context->digest_name();
|
||||
out << ",keysize " << dc_context->key_size();
|
||||
}
|
||||
if (tls_auth_key.defined())
|
||||
out << ",tls-auth";
|
||||
out << ",key-method 2";
|
||||
@ -648,9 +654,7 @@ namespace openvpn {
|
||||
1 + // leading op byte
|
||||
comp_ctx.extra_payload_bytes() + // compression magic byte
|
||||
PacketID::size(PacketID::SHORT_FORM) + // sequence number
|
||||
(digest.defined() ? digest.size() : 0) + // HMAC
|
||||
(cipher.defined() ? cipher.iv_length() : 0) + // Cipher IV
|
||||
(cipher.defined() ? cipher.block_size() : 0); // worst-case cipher padding expansion
|
||||
(dc_context ? dc_context->encap_overhead() : 0); // data channel crypto layer overhead
|
||||
return (unsigned int)adj;
|
||||
}
|
||||
};
|
||||
@ -1572,26 +1576,24 @@ namespace openvpn {
|
||||
// OpenVPN data channel protocol
|
||||
void init_data_channel_crypto_context(const OpenVPNStaticKey& key)
|
||||
{
|
||||
// fixme -- this method is being called too early, and is preventing cipher/digest algs from being pushed by server
|
||||
const Config& c = *proto.config;
|
||||
const unsigned int key_dir = proto.is_server() ? OpenVPNStaticKey::INVERSE : OpenVPNStaticKey::NORMAL;
|
||||
|
||||
// build crypto context for data channel encryption/decryption
|
||||
OPENVPN_LOG("************* NEW_OBJ KEY_ID=" << key_id_); // fixme
|
||||
crypto = proto.config->dc_context->new_obj(key_id_);
|
||||
|
||||
// initialize CryptoContext encrypt
|
||||
if (c.cipher.defined())
|
||||
crypto->init_encrypt_cipher(key.slice(OpenVPNStaticKey::CIPHER | OpenVPNStaticKey::ENCRYPT | key_dir),
|
||||
CRYPTO_API::CipherContext::ENCRYPT);
|
||||
if (c.digest.defined())
|
||||
crypto->init_encrypt_hmac(key.slice(OpenVPNStaticKey::HMAC | OpenVPNStaticKey::ENCRYPT | key_dir));
|
||||
if (crypto->cipher_defined())
|
||||
{
|
||||
crypto->init_encrypt_cipher(key.slice(OpenVPNStaticKey::CIPHER | OpenVPNStaticKey::ENCRYPT | key_dir));
|
||||
crypto->init_decrypt_cipher(key.slice(OpenVPNStaticKey::CIPHER | OpenVPNStaticKey::DECRYPT | key_dir));
|
||||
}
|
||||
if (crypto->digest_defined())
|
||||
{
|
||||
crypto->init_encrypt_hmac(key.slice(OpenVPNStaticKey::HMAC | OpenVPNStaticKey::ENCRYPT | key_dir));
|
||||
crypto->init_decrypt_hmac(key.slice(OpenVPNStaticKey::HMAC | OpenVPNStaticKey::DECRYPT | key_dir));
|
||||
}
|
||||
crypto->init_encrypt_pid_send(PacketID::SHORT_FORM);
|
||||
|
||||
// initialize CryptoContext decrypt
|
||||
if (c.cipher.defined())
|
||||
crypto->init_decrypt_cipher(key.slice(OpenVPNStaticKey::CIPHER | OpenVPNStaticKey::DECRYPT | key_dir),
|
||||
CRYPTO_API::CipherContext::DECRYPT);
|
||||
if (c.digest.defined())
|
||||
crypto->init_decrypt_hmac(key.slice(OpenVPNStaticKey::HMAC | OpenVPNStaticKey::DECRYPT | key_dir));
|
||||
crypto->init_decrypt_pid_recv(c.pid_mode,
|
||||
PacketID::SHORT_FORM,
|
||||
c.pid_seq_backtrack, c.pid_time_backtrack,
|
||||
|
Loading…
Reference in New Issue
Block a user