Merge commit '86cc97e55fe346502462284d2e636a2b3708163e' as 'Sources/OpenVPN3'

This commit is contained in:
Sergey Abramchuk
2020-02-24 14:43:11 +03:00
655 changed files with 146468 additions and 0 deletions
@@ -0,0 +1,141 @@
// 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-2017 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/>.
// mbed TLS exception class that allows a error code
// to be represented.
#ifndef OPENVPN_MBEDTLS_UTIL_ERROR_H
#define OPENVPN_MBEDTLS_UTIL_ERROR_H
#include <string>
#include <mbedtls/ssl.h>
#include <mbedtls/pem.h>
#include <mbedtls/error.h>
#include <openvpn/common/exception.hpp>
#include <openvpn/error/error.hpp>
#include <openvpn/error/excode.hpp>
namespace openvpn {
// string exception class
class MbedTLSException : public ExceptionCode
{
public:
MbedTLSException()
{
errnum = 0;
errtxt = "mbed TLS";
}
explicit MbedTLSException(const std::string& error_text)
{
errnum = 0;
errtxt = "mbed TLS: " + error_text;
}
explicit MbedTLSException(const std::string& error_text, const Error::Type code, const bool fatal)
: ExceptionCode(code, fatal)
{
errnum = 0;
errtxt = "mbed TLS: " + error_text;
}
explicit MbedTLSException(const std::string& error_text, const int mbedtls_errnum)
{
errnum = mbedtls_errnum;
errtxt = "mbed TLS: " + error_text + " : " + mbedtls_errtext(mbedtls_errnum);
// cite forum URL for mbed TLS invalid date
// TODO: Get a better URL for such knowledge information record
if (mbedtls_errnum == MBEDTLS_ERR_X509_INVALID_DATE)
errtxt += ", please see https://forums.openvpn.net/viewtopic.php?f=36&t=21873 for more info";
// for certain mbed TLS errors, translate them to an OpenVPN error code,
// so they can be propagated up to the higher levels (such as UI level)
switch (errnum) {
case MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:
set_code(Error::CERT_VERIFY_FAIL, true);
break;
case MBEDTLS_ERR_PK_PASSWORD_REQUIRED:
case MBEDTLS_ERR_PK_PASSWORD_MISMATCH:
set_code(Error::PEM_PASSWORD_FAIL, true);
break;
case MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION:
set_code(Error::TLS_VERSION_MIN, true);
break;
}
}
virtual const char* what() const throw() { return errtxt.c_str(); }
std::string what_str() const { return errtxt; }
int get_errnum() const { return errnum; }
virtual ~MbedTLSException() throw() {}
static std::string mbedtls_errtext(int errnum)
{
char buf[256];
mbedtls_strerror(errnum, buf, sizeof(buf));
return buf;
}
static std::string mbedtls_verify_flags_errtext(const uint32_t flags)
{
// get string rendition of flags
const size_t BUF_SIZE = 1024;
std::unique_ptr<char[]> buf(new char[BUF_SIZE]);
buf[0] = '\0';
mbedtls_x509_crt_verify_info(buf.get(), BUF_SIZE, "", flags);
// postprocess string
std::string ret;
ret.reserve(std::strlen(buf.get()) + 64);
bool newline = false;
for (size_t i = 0; i < BUF_SIZE; ++i)
{
const char c = buf[i];
if (c == '\0')
break;
else if (c == '\n')
newline = true;
else
{
if (newline)
{
ret += ", ";
newline = false;
}
ret += c;
}
}
return ret;
}
private:
std::string errtxt;
int errnum;
};
}
#endif
@@ -0,0 +1,77 @@
// 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) 2017-2018 OpenVPN Technologies, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program in the COPYING file.
// If not, see <http://www.gnu.org/licenses/>.
// Wrap the mbedTLS PEM API defined in <mbedtls/pem.h> so
// that it can be used as part of the crypto layer of the OpenVPN core.
#ifndef OPENVPN_MBEDTLS_UTIL_PEM_H
#define OPENVPN_MBEDTLS_UTIL_PEM_H
#include <mbedtls/pem.h>
namespace openvpn {
class MbedTLSPEM
{
public:
static bool pem_encode(BufferAllocated& dst, const unsigned char *src,
size_t src_len, const std::string& key_name)
{
std::string header = "-----BEGIN " + key_name + "-----\n";
std::string footer = "-----END " + key_name + "-----\n";
size_t out_len = 0;
int ret = mbedtls_pem_write_buffer(header.c_str(), footer.c_str(),
src, src_len, dst.data(),
dst.max_size(), &out_len);
if (ret == 0)
dst.set_size(out_len);
else
{
char buf[128];
mbedtls_strerror(ret, buf, 128);
OPENVPN_LOG("mbedtls_pem_write_buffer error: " << buf);
}
return (ret == 0);
}
static bool pem_decode(BufferAllocated& dst, const char *src,
size_t src_len, const std::string& key_name)
{
std::string header = "-----BEGIN " + key_name + "-----";
std::string footer = "-----END " + key_name + "-----";
mbedtls_pem_context ctx = { };
size_t out_len = 0;
int ret = mbedtls_pem_read_buffer(&ctx, header.c_str(), footer.c_str(),
(unsigned char *)src, nullptr, 0,
&out_len);
if (ret == 0)
dst.init(ctx.buf, ctx.buflen, BufferAllocated::DESTRUCT_ZERO);
mbedtls_pem_free(&ctx);
return (ret == 0);
}
};
};
#endif /* OPENVPN_MBEDTLS_UTIL_PEM_H */
@@ -0,0 +1,71 @@
// 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-2017 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/>.
#ifndef OPENVPN_MBEDTLS_UTIL_PKCS1_H
#define OPENVPN_MBEDTLS_UTIL_PKCS1_H
#include <openvpn/pki/pkcs1.hpp>
namespace openvpn {
namespace PKCS1 {
namespace DigestPrefix {
class MbedTLSParse : public Parse<mbedtls_md_type_t>
{
public:
MbedTLSParse()
: Parse(MBEDTLS_MD_NONE,
MBEDTLS_MD_MD2,
MBEDTLS_MD_MD5,
MBEDTLS_MD_SHA1,
MBEDTLS_MD_SHA256,
MBEDTLS_MD_SHA384,
MBEDTLS_MD_SHA512)
{
}
static const char *to_string(const mbedtls_md_type_t t)
{
switch (t)
{
case MBEDTLS_MD_NONE:
return "MBEDTLS_MD_NONE";
case MBEDTLS_MD_MD2:
return "MBEDTLS_MD_MD2";
case MBEDTLS_MD_MD5:
return "MBEDTLS_MD_MD5";
case MBEDTLS_MD_SHA1:
return "MBEDTLS_MD_SHA1";
case MBEDTLS_MD_SHA256:
return "MBEDTLS_MD_SHA256";
case MBEDTLS_MD_SHA384:
return "MBEDTLS_MD_SHA384";
case MBEDTLS_MD_SHA512:
return "MBEDTLS_MD_SHA512";
default:
return "MBEDTLS_MD_???";
}
}
};
}
}
}
#endif
@@ -0,0 +1,135 @@
// 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-2017 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/>.
// Wrap the mbed TLS Cryptographic Random API defined in <mbedtls/ctr_drbg.h>
// so that it can be used as the primary source of cryptographic entropy by
// the OpenVPN core.
#ifndef OPENVPN_MBEDTLS_UTIL_RAND_H
#define OPENVPN_MBEDTLS_UTIL_RAND_H
#include <mbedtls/entropy.h>
#include <mbedtls/entropy_poll.h>
#include <mbedtls/ctr_drbg.h>
#include <openvpn/random/randapi.hpp>
#include <openvpn/mbedtls/util/error.hpp>
namespace openvpn {
class MbedTLSRandom : public RandomAPI
{
public:
OPENVPN_EXCEPTION(rand_error_mbedtls);
typedef RCPtr<MbedTLSRandom> Ptr;
MbedTLSRandom(const bool prng, RandomAPI::Ptr entropy_source)
: entropy(std::move(entropy_source))
{
// Init RNG context
mbedtls_ctr_drbg_init(&ctx);
// Seed RNG
const int errnum = mbedtls_ctr_drbg_seed(&ctx, entropy_poll, entropy.get(), nullptr, 0);
if (errnum < 0)
throw MbedTLSException("mbedtls_ctr_drbg_seed", errnum);
// If prng is set, configure for higher performance
// by reseeding less frequently.
if (prng)
mbedtls_ctr_drbg_set_reseed_interval(&ctx, 1000000);
}
MbedTLSRandom(const bool prng)
: MbedTLSRandom(prng, RandomAPI::Ptr()) { }
virtual ~MbedTLSRandom()
{
// Free RNG context
mbedtls_ctr_drbg_free(&ctx);
}
// Random algorithm name
virtual std::string name() const
{
const std::string n = "mbedTLS-CTR_DRBG";
if (entropy)
return n + '+' + entropy->name();
else
return n;
}
// Return true if algorithm is crypto-strength
virtual bool is_crypto() const
{
return true;
}
// Fill buffer with random bytes
virtual void rand_bytes(unsigned char *buf, size_t size)
{
const int errnum = rndbytes(buf, size);
if (errnum < 0)
throw MbedTLSException("mbedtls_ctr_drbg_random", errnum);
}
// Like rand_bytes, but don't throw exception.
// Return true on successs, false on fail.
virtual bool rand_bytes_noexcept(unsigned char *buf, size_t size)
{
return rndbytes(buf, size) >= 0;
}
private:
int rndbytes(unsigned char *buf, size_t size)
{
return mbedtls_ctr_drbg_random(&ctx, buf, size);
}
static int entropy_poll(void *arg, unsigned char *output, size_t len)
{
if (arg)
{
RandomAPI* entropy = (RandomAPI*)arg;
if (entropy->rand_bytes_noexcept(output, len))
return 0;
else
return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
}
else
{
#ifndef OPENVPN_DISABLE_MBEDTLS_PLATFORM_ENTROPY_POLL
size_t olen;
return mbedtls_platform_entropy_poll(nullptr, output, len, &olen);
#else
return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
#endif
}
}
mbedtls_ctr_drbg_context ctx;
RandomAPI::Ptr entropy;
};
}
#endif
@@ -0,0 +1,56 @@
// 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-2017 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/>.
// Call various mbed TLS self-test functions
#ifndef OPENVPN_MBEDTLS_UTIL_SELFTEST_H
#define OPENVPN_MBEDTLS_UTIL_SELFTEST_H
#include <sstream>
#include <mbedtls/bignum.h>
#include <mbedtls/config.h>
#include <mbedtls/cipher.h>
#include <mbedtls/aes.h>
#include <mbedtls/sha1.h>
#include <mbedtls/sha256.h>
#include <mbedtls/sha512.h>
namespace openvpn {
inline std::string crypto_self_test_mbedtls()
{
std::ostringstream os;
#ifdef MBEDTLS_SELF_TEST
const int verbose = 1;
os << "mbed TLS self test (tests return 0 if successful):" << std::endl;
os << " mbedlts_aes_self_test status=" << mbedtls_aes_self_test(verbose) << std::endl;
os << " mbedtls_sha1_self_test status=" << mbedtls_sha1_self_test(verbose) << std::endl;
os << " mbedtls_sha256_self_test status=" << mbedtls_sha256_self_test(verbose) << std::endl;
os << " mbedtls_sha512_self_test status=" << mbedtls_sha512_self_test(verbose) << std::endl;
os << " mbedtls_mpi_self_test status=" << mbedtls_mpi_self_test(verbose) << std::endl;
#else
os << "mbed TLS self test: not compiled" << std::endl;
#endif
return os.str();
}
}
#endif