mirror of
https://github.com/OpenVPN/openvpn3.git
synced 2024-09-20 12:12:15 +02:00
be3f20dc58
The need of having to call the assert_crypto() member function to ensure that a cryptographically strong RNG is used where needed, was reported as potentially insecure, since calling it manually can easily be missed. In the commit the two new classes StrongRandomAPI and WeakRandomAPI are introduced. They are to be used instead of just RandomAPI, unless it doesn't matter what strength the RNG is. All the places the assert_crypto() was called were converted to using StrongRandomAPI instead. Also the RNGs for which assert_crypto() was not throwing are now inheriting from StrongRandomAPI. Variable names, which have the StrongRandomAPI type, but were called prng, are changed to rng instead to follow the source code convention. Signed-off-by: Heiko Hund <heiko@openvpn.net>
212 lines
5.3 KiB
C++
212 lines
5.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-2022 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/>.
|
|
|
|
// Classes for handling OpenVPN static keys (and tls-auth keys)
|
|
|
|
#ifndef OPENVPN_CRYPTO_STATIC_KEY_H
|
|
#define OPENVPN_CRYPTO_STATIC_KEY_H
|
|
|
|
#include <string>
|
|
#include <sstream>
|
|
|
|
#include <openvpn/common/exception.hpp>
|
|
#include <openvpn/common/hexstr.hpp>
|
|
#include <openvpn/common/file.hpp>
|
|
#include <openvpn/common/splitlines.hpp>
|
|
#include <openvpn/common/base64.hpp>
|
|
#include <openvpn/buffer/buffer.hpp>
|
|
#include <openvpn/random/randapi.hpp>
|
|
|
|
namespace openvpn {
|
|
|
|
class StaticKey
|
|
{
|
|
friend class OpenVPNStaticKey;
|
|
typedef BufferAllocated key_t;
|
|
|
|
public:
|
|
StaticKey()
|
|
{
|
|
}
|
|
StaticKey(const unsigned char *key_data, const size_t key_size)
|
|
: key_data_(key_data, key_size, key_t::DESTRUCT_ZERO)
|
|
{
|
|
}
|
|
|
|
size_t size() const
|
|
{
|
|
return key_data_.size();
|
|
}
|
|
const unsigned char *data() const
|
|
{
|
|
return key_data_.c_data();
|
|
}
|
|
void erase()
|
|
{
|
|
key_data_.clear();
|
|
}
|
|
|
|
std::string render_hex() const
|
|
{
|
|
return openvpn::render_hex_generic(key_data_);
|
|
}
|
|
|
|
void parse_from_base64(const std::string &b64, const size_t capacity)
|
|
{
|
|
key_data_.reset(capacity, key_t::DESTRUCT_ZERO);
|
|
base64->decode(key_data_, b64);
|
|
}
|
|
|
|
std::string render_to_base64() const
|
|
{
|
|
return base64->encode(key_data_);
|
|
}
|
|
|
|
void init_from_rng(StrongRandomAPI &rng, const size_t key_size)
|
|
{
|
|
key_data_.init(key_size, key_t::DESTRUCT_ZERO);
|
|
rng.rand_bytes(key_data_.data(), key_size);
|
|
key_data_.set_size(key_size);
|
|
}
|
|
|
|
private:
|
|
key_t key_data_;
|
|
};
|
|
|
|
class OpenVPNStaticKey
|
|
{
|
|
typedef StaticKey::key_t key_t;
|
|
|
|
public:
|
|
enum
|
|
{
|
|
KEY_SIZE = 256 // bytes
|
|
};
|
|
|
|
// key specifier
|
|
enum
|
|
{
|
|
// key for cipher and hmac
|
|
CIPHER = 0,
|
|
HMAC = (1 << 0),
|
|
|
|
// do we want to encrypt or decrypt with this key
|
|
ENCRYPT = 0,
|
|
DECRYPT = (1 << 1),
|
|
|
|
// key direction
|
|
NORMAL = 0,
|
|
INVERSE = (1 << 2)
|
|
};
|
|
|
|
OPENVPN_SIMPLE_EXCEPTION(static_key_parse_error);
|
|
OPENVPN_SIMPLE_EXCEPTION(static_key_bad_size);
|
|
|
|
bool defined() const
|
|
{
|
|
return key_data_.defined();
|
|
}
|
|
|
|
void XOR(const OpenVPNStaticKey &other)
|
|
{
|
|
assert(defined() && other.defined());
|
|
|
|
for (std::size_t i = 0; i < key_data_.size(); ++i)
|
|
key_data_[i] ^= other.key_data_[i];
|
|
}
|
|
|
|
StaticKey slice(unsigned int key_specifier) const
|
|
{
|
|
if (key_data_.size() != KEY_SIZE)
|
|
throw static_key_bad_size();
|
|
static const unsigned char key_table[] = {0, 1, 2, 3, 2, 3, 0, 1};
|
|
const unsigned int idx = key_table[key_specifier & 7] * 64;
|
|
return StaticKey(key_data_.c_data() + idx, KEY_SIZE / 4);
|
|
}
|
|
|
|
void parse_from_file(const std::string &filename)
|
|
{
|
|
const std::string str = read_text(filename);
|
|
parse(str);
|
|
}
|
|
|
|
void parse(const std::string &key_text)
|
|
{
|
|
SplitLines in(key_text, 0);
|
|
key_t data(KEY_SIZE, key_t::DESTRUCT_ZERO);
|
|
bool in_body = false;
|
|
while (in(true))
|
|
{
|
|
const std::string &line = in.line_ref();
|
|
if (line == static_key_head())
|
|
in_body = true;
|
|
else if (line == static_key_foot())
|
|
in_body = false;
|
|
else if (in_body)
|
|
parse_hex(data, line);
|
|
}
|
|
if (in_body || data.size() != KEY_SIZE)
|
|
throw static_key_parse_error();
|
|
key_data_ = data;
|
|
}
|
|
|
|
std::string render() const
|
|
{
|
|
if (key_data_.size() != KEY_SIZE)
|
|
throw static_key_bad_size();
|
|
std::ostringstream out;
|
|
out << static_key_head() << "\n";
|
|
for (size_t i = 0; i < KEY_SIZE; i += 16)
|
|
out << render_hex(key_data_.c_data() + i, 16) << "\n";
|
|
out << static_key_foot() << "\n";
|
|
return out.str();
|
|
}
|
|
|
|
unsigned char *raw_alloc()
|
|
{
|
|
key_data_.init(KEY_SIZE, key_t::DESTRUCT_ZERO | key_t::ARRAY);
|
|
return key_data_.data();
|
|
}
|
|
|
|
void erase()
|
|
{
|
|
key_data_.clear();
|
|
}
|
|
|
|
private:
|
|
static const char *static_key_head()
|
|
{
|
|
return "-----BEGIN OpenVPN Static key V1-----";
|
|
}
|
|
|
|
static const char *static_key_foot()
|
|
{
|
|
return "-----END OpenVPN Static key V1-----";
|
|
}
|
|
|
|
key_t key_data_;
|
|
};
|
|
|
|
|
|
} // namespace openvpn
|
|
|
|
#endif // OPENVPN_CRYPTO_STATIC_KEY_H
|