mirror of
https://github.com/deneraraujo/OpenVPNAdapter.git
synced 2026-04-06 00:00:03 +08:00
Merge commit '86cc97e55fe346502462284d2e636a2b3708163e' as 'Sources/OpenVPN3'
This commit is contained in:
61
Sources/OpenVPN3/openvpn/openssl/util/engine.hpp
Normal file
61
Sources/OpenVPN3/openvpn/openssl/util/engine.hpp
Normal file
@@ -0,0 +1,61 @@
|
||||
// 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/>.
|
||||
|
||||
// Method to set up a particular OpenSSL engine type
|
||||
|
||||
#ifndef OPENVPN_OPENSSL_UTIL_ENGINE_H
|
||||
#define OPENVPN_OPENSSL_UTIL_ENGINE_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#ifndef OPENSSL_NO_ENGINE
|
||||
#include <openssl/engine.h>
|
||||
#endif
|
||||
|
||||
#include <openvpn/common/exception.hpp>
|
||||
#include <openvpn/openssl/util/error.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
|
||||
OPENVPN_EXCEPTION(openssl_engine_error);
|
||||
|
||||
inline void openssl_setup_engine (const std::string& engine)
|
||||
{
|
||||
#ifndef OPENSSL_NO_ENGINE
|
||||
ENGINE_load_builtin_engines ();
|
||||
|
||||
if (engine == "auto")
|
||||
{
|
||||
ENGINE_register_all_complete ();
|
||||
return;
|
||||
}
|
||||
|
||||
ENGINE *e = ENGINE_by_id (engine.c_str());
|
||||
if (!e)
|
||||
throw openssl_engine_error();
|
||||
if (!ENGINE_set_default (e, ENGINE_METHOD_ALL))
|
||||
throw openssl_engine_error();
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace openvpn
|
||||
|
||||
#endif // OPENVPN_OPENSSL_UTIL_ENGINE_H
|
||||
200
Sources/OpenVPN3/openvpn/openssl/util/error.hpp
Normal file
200
Sources/OpenVPN3/openvpn/openssl/util/error.hpp
Normal file
@@ -0,0 +1,200 @@
|
||||
// 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/>.
|
||||
|
||||
// OpenSSL exception class that allows a full OpenSSL error stack
|
||||
// to be represented.
|
||||
|
||||
#ifndef OPENVPN_OPENSSL_UTIL_ERROR_H
|
||||
#define OPENVPN_OPENSSL_UTIL_ERROR_H
|
||||
|
||||
#include <string>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
#include <openvpn/common/exception.hpp>
|
||||
#include <openvpn/error/error.hpp>
|
||||
#include <openvpn/error/excode.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
|
||||
// string exception class
|
||||
class OpenSSLException : public ExceptionCode
|
||||
{
|
||||
public:
|
||||
OPENVPN_EXCEPTION(ssl_exception_index);
|
||||
|
||||
enum {
|
||||
MAX_ERRORS = 8
|
||||
};
|
||||
|
||||
OpenSSLException()
|
||||
{
|
||||
ssl_err = -1;
|
||||
init_error("OpenSSL");
|
||||
}
|
||||
|
||||
explicit OpenSSLException(const std::string& error_text)
|
||||
{
|
||||
ssl_err = -1;
|
||||
init_error(error_text.c_str());
|
||||
}
|
||||
|
||||
explicit OpenSSLException(const int ssl_error)
|
||||
{
|
||||
init_ssl_error(ssl_error, "OpenSSL");
|
||||
}
|
||||
|
||||
explicit OpenSSLException(const std::string& error_text, const int ssl_error)
|
||||
{
|
||||
init_ssl_error(ssl_error, error_text.c_str());
|
||||
}
|
||||
|
||||
virtual const char* what() const throw() { return errtxt.c_str(); }
|
||||
std::string what_str() const { return errtxt; }
|
||||
|
||||
size_t len() const { return n_err; }
|
||||
unsigned long operator[](const size_t i) const
|
||||
{
|
||||
if (i < n_err)
|
||||
return errstack[i];
|
||||
else
|
||||
throw ssl_exception_index();
|
||||
}
|
||||
|
||||
int ssl_error() const { return ssl_err; }
|
||||
|
||||
virtual ~OpenSSLException() throw() {}
|
||||
|
||||
static const char *ssl_error_text(const int ssl_error, bool *unknown = nullptr)
|
||||
{
|
||||
switch (ssl_error)
|
||||
{
|
||||
case SSL_ERROR_NONE:
|
||||
return "SSL_ERROR_NONE";
|
||||
case SSL_ERROR_ZERO_RETURN:
|
||||
return "SSL_ERROR_ZERO_RETURN";
|
||||
case SSL_ERROR_WANT_READ:
|
||||
return "SSL_ERROR_WANT_READ";
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
return "SSL_ERROR_WANT_WRITE";
|
||||
case SSL_ERROR_WANT_CONNECT:
|
||||
return "SSL_ERROR_WANT_CONNECT";
|
||||
case SSL_ERROR_WANT_ACCEPT:
|
||||
return "SSL_ERROR_WANT_ACCEPT";
|
||||
case SSL_ERROR_WANT_X509_LOOKUP:
|
||||
return "SSL_ERROR_WANT_X509_LOOKUP";
|
||||
case SSL_ERROR_SYSCALL:
|
||||
return "SSL_ERROR_SYSCALL";
|
||||
case SSL_ERROR_SSL:
|
||||
return "SSL_ERROR_SSL";
|
||||
default:
|
||||
if (unknown)
|
||||
*unknown = true;
|
||||
return "(unknown SSL error)";
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void init_error(const char *error_text)
|
||||
{
|
||||
const char *prefix = ": ";
|
||||
std::ostringstream tmp;
|
||||
char buf[256];
|
||||
|
||||
tmp << error_text;
|
||||
|
||||
n_err = 0;
|
||||
while (unsigned long err = ERR_get_error())
|
||||
{
|
||||
if (n_err < MAX_ERRORS)
|
||||
errstack[n_err++] = err;
|
||||
ERR_error_string_n(err, buf, sizeof(buf));
|
||||
tmp << prefix << buf;
|
||||
prefix = " / ";
|
||||
|
||||
// for certain OpenSSL errors, translate them to an OpenVPN error code,
|
||||
// so they can be propagated up to the higher levels (such as UI level)
|
||||
switch (ERR_GET_REASON(err))
|
||||
{
|
||||
case SSL_R_CERTIFICATE_VERIFY_FAILED:
|
||||
set_code(Error::CERT_VERIFY_FAIL, true);
|
||||
break;
|
||||
case PEM_R_BAD_PASSWORD_READ:
|
||||
case PEM_R_BAD_DECRYPT:
|
||||
set_code(Error::PEM_PASSWORD_FAIL, true);
|
||||
break;
|
||||
case SSL_R_UNSUPPORTED_PROTOCOL:
|
||||
set_code(Error::TLS_VERSION_MIN, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
errtxt = tmp.str();
|
||||
}
|
||||
|
||||
void init_ssl_error(const int ssl_error, const char *error_text)
|
||||
{
|
||||
bool unknown = false;
|
||||
ssl_err = ssl_error;
|
||||
const char *text = ssl_error_text(ssl_error, &unknown);
|
||||
if (unknown || ssl_error == SSL_ERROR_SYSCALL || ssl_error == SSL_ERROR_SSL)
|
||||
{
|
||||
init_error(error_text);
|
||||
errtxt += " (";
|
||||
errtxt += text;
|
||||
errtxt += ")";
|
||||
}
|
||||
else
|
||||
{
|
||||
errtxt = error_text;
|
||||
errtxt += ": ";
|
||||
errtxt += text;
|
||||
}
|
||||
}
|
||||
|
||||
size_t n_err;
|
||||
unsigned long errstack[MAX_ERRORS];
|
||||
std::string errtxt;
|
||||
int ssl_err;
|
||||
};
|
||||
|
||||
// return an OpenSSL error string
|
||||
|
||||
inline std::string openssl_error()
|
||||
{
|
||||
OpenSSLException err;
|
||||
return err.what_str();
|
||||
}
|
||||
|
||||
inline std::string openssl_error(const int ssl_error)
|
||||
{
|
||||
OpenSSLException err(ssl_error);
|
||||
return err.what_str();
|
||||
}
|
||||
|
||||
inline void openssl_clear_error_stack()
|
||||
{
|
||||
while (ERR_get_error())
|
||||
;
|
||||
}
|
||||
|
||||
} // namespace openvpn
|
||||
|
||||
#endif // OPENVPN_OPENSSL_UTIL_ERROR_H
|
||||
39
Sources/OpenVPN3/openvpn/openssl/util/init.hpp
Normal file
39
Sources/OpenVPN3/openvpn/openssl/util/init.hpp
Normal file
@@ -0,0 +1,39 @@
|
||||
// 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/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <openssl/opensslv.h>
|
||||
|
||||
// OpenSSL 1.1.0 does not require an explicit init, in fact the
|
||||
// asio init for 1.1.0 is a noop, see also OPENSSL_init_ssl man page
|
||||
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
|
||||
#define OPENSSL_NEEDS_INIT
|
||||
|
||||
// Instantiate this object to ensure openssl is initialised.
|
||||
#ifdef USE_ASIO
|
||||
#include <asio/ssl/detail/openssl_init.hpp>
|
||||
typedef asio::ssl::detail::openssl_init<> openssl_init;
|
||||
#else
|
||||
#error no OpenSSL init code (USE_ASIO needed for OpenSSL < 1.1)
|
||||
#endif
|
||||
#endif
|
||||
103
Sources/OpenVPN3/openvpn/openssl/util/pem.hpp
Normal file
103
Sources/OpenVPN3/openvpn/openssl/util/pem.hpp
Normal file
@@ -0,0 +1,103 @@
|
||||
// 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 OpenSSL PEM API defined in <openssl/pem.h> so
|
||||
// that it can be used as part of the crypto layer of the OpenVPN core.
|
||||
|
||||
#ifndef OPENVPN_OPENSSL_UTIL_PEM_H
|
||||
#define OPENVPN_OPENSSL_UTIL_PEM_H
|
||||
|
||||
#include <openvpn/openssl/util/error.hpp>
|
||||
|
||||
#include <openssl/pem.h>
|
||||
|
||||
namespace openvpn {
|
||||
class OpenSSLPEM
|
||||
{
|
||||
public:
|
||||
static bool pem_encode(BufferAllocated& dst, const unsigned char *src,
|
||||
size_t src_len, const std::string& key_name)
|
||||
{
|
||||
bool ret = false;
|
||||
BIO *bio = BIO_new(BIO_s_mem());
|
||||
if (!bio)
|
||||
return false;
|
||||
|
||||
if (!PEM_write_bio(bio, key_name.c_str(), "", src, src_len))
|
||||
goto out;
|
||||
|
||||
BUF_MEM *bptr;
|
||||
BIO_get_mem_ptr(bio, &bptr);
|
||||
dst.write((unsigned char *)bptr->data, bptr->length);
|
||||
|
||||
ret = true;
|
||||
|
||||
out:
|
||||
if (!BIO_free(bio))
|
||||
ret = false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool pem_decode(BufferAllocated& dst, const char *src,
|
||||
size_t src_len, const std::string& key_name)
|
||||
{
|
||||
bool ret = false;
|
||||
BIO *bio;
|
||||
|
||||
if (!(bio = BIO_new_mem_buf(src, src_len)))
|
||||
throw OpenSSLException("Cannot open memory BIO for PEM decode");
|
||||
|
||||
char *name_read = NULL;
|
||||
char *header_read = NULL;
|
||||
uint8_t *data_read = NULL;
|
||||
long data_read_len = 0;
|
||||
if (!PEM_read_bio(bio, &name_read, &header_read, &data_read,
|
||||
&data_read_len))
|
||||
{
|
||||
OPENVPN_LOG("PEM decode failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (key_name.compare(std::string(name_read)))
|
||||
{
|
||||
OPENVPN_LOG("unexpected PEM name (got '" << name_read <<
|
||||
"', expected '" << key_name << "')");
|
||||
goto out;
|
||||
}
|
||||
|
||||
dst.write(data_read, data_read_len);
|
||||
|
||||
ret = true;
|
||||
out:
|
||||
OPENSSL_free(name_read);
|
||||
OPENSSL_free(header_read);
|
||||
OPENSSL_free(data_read);
|
||||
|
||||
if (!BIO_free(bio))
|
||||
ret = false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
#endif /* OPENVPN_OPENSSL_UTIL_PEM_H */
|
||||
78
Sources/OpenVPN3/openvpn/openssl/util/rand.hpp
Normal file
78
Sources/OpenVPN3/openvpn/openssl/util/rand.hpp
Normal file
@@ -0,0 +1,78 @@
|
||||
// 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 OpenSSL Cryptographic Random API defined in <openssl/rand.h>
|
||||
// so that it can be used as the primary source of cryptographic entropy by
|
||||
// the OpenVPN core.
|
||||
|
||||
#ifndef OPENVPN_OPENSSL_UTIL_RAND_H
|
||||
#define OPENVPN_OPENSSL_UTIL_RAND_H
|
||||
|
||||
#include <openssl/rand.h>
|
||||
|
||||
#include <openvpn/random/randapi.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
class OpenSSLRandom : public RandomAPI
|
||||
{
|
||||
public:
|
||||
OPENVPN_EXCEPTION(rand_error_openssl);
|
||||
|
||||
typedef RCPtr<OpenSSLRandom> Ptr;
|
||||
|
||||
OpenSSLRandom(const bool prng)
|
||||
{
|
||||
}
|
||||
|
||||
virtual std::string name() const
|
||||
{
|
||||
return "OpenSSLRandom";
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
if (!rndbytes(buf, size))
|
||||
throw rand_error_openssl("rand_bytes");
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
private:
|
||||
bool rndbytes(unsigned char *buf, size_t size)
|
||||
{
|
||||
return RAND_bytes(buf, size) == 1;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
40
Sources/OpenVPN3/openvpn/openssl/util/reseed.hpp
Normal file
40
Sources/OpenVPN3/openvpn/openssl/util/reseed.hpp
Normal file
@@ -0,0 +1,40 @@
|
||||
// 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/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
// seed OpenSSL's random number generator with /dev/urandom
|
||||
|
||||
#include <openssl/rand.h>
|
||||
|
||||
#include <openvpn/random/devurand.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
inline void openssl_reseed_rng()
|
||||
{
|
||||
unsigned char entropy[64];
|
||||
|
||||
RandomAPI::Ptr rng(new DevURand);
|
||||
rng->rand_bytes(entropy, sizeof(entropy));
|
||||
|
||||
RAND_seed(entropy, sizeof(entropy));
|
||||
}
|
||||
}
|
||||
121
Sources/OpenVPN3/openvpn/openssl/util/tokenencrypt.hpp
Normal file
121
Sources/OpenVPN3/openvpn/openssl/util/tokenencrypt.hpp
Normal file
@@ -0,0 +1,121 @@
|
||||
// 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_CRYPTO_TOKENENCRYPT_H
|
||||
#define OPENVPN_CRYPTO_TOKENENCRYPT_H
|
||||
|
||||
#include <string>
|
||||
#include <atomic>
|
||||
#include <cstdint> // for std::uint8_t
|
||||
|
||||
#include <openssl/evp.h>
|
||||
|
||||
#include <openvpn/common/size.hpp>
|
||||
#include <openvpn/common/exception.hpp>
|
||||
#include <openvpn/common/base64.hpp>
|
||||
#include <openvpn/buffer/buffer.hpp>
|
||||
#include <openvpn/random/randapi.hpp>
|
||||
#include <openvpn/openssl/util/error.hpp>
|
||||
|
||||
#include <openvpn/openssl/compat.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
class TokenEncrypt
|
||||
{
|
||||
public:
|
||||
class Key
|
||||
{
|
||||
public:
|
||||
static constexpr size_t SIZE = 16;
|
||||
|
||||
Key(RandomAPI& rng)
|
||||
{
|
||||
rng.assert_crypto();
|
||||
rng.rand_bytes(data, sizeof(data));
|
||||
}
|
||||
|
||||
private:
|
||||
friend class TokenEncrypt;
|
||||
std::uint8_t data[SIZE];
|
||||
};
|
||||
|
||||
// mode parameter for constructor
|
||||
enum {
|
||||
ENCRYPT = 1,
|
||||
DECRYPT = 0
|
||||
};
|
||||
|
||||
TokenEncrypt(const Key& key, const int mode)
|
||||
{
|
||||
ctx = EVP_CIPHER_CTX_new ();
|
||||
EVP_CIPHER_CTX_reset (ctx);
|
||||
if (!EVP_CipherInit_ex(ctx, EVP_aes_128_ecb(), nullptr, key.data, nullptr, mode))
|
||||
{
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
throw OpenSSLException("TokenEncrypt: EVP_CipherInit_ex[1] failed");
|
||||
}
|
||||
EVP_CIPHER_CTX_set_padding(ctx, 0);
|
||||
}
|
||||
|
||||
~TokenEncrypt()
|
||||
{
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
}
|
||||
|
||||
// Do the encrypt/decrypt
|
||||
void operator()(std::uint8_t* dest, const std::uint8_t* src, const size_t size)
|
||||
{
|
||||
// NOTE: since this algorithm uses the ECB block cipher mode,
|
||||
// it should only be used to encrypt/decrypt a message which
|
||||
// is exactly equal to the AES block size (16 bytes).
|
||||
if (size != EVP_CIPHER_CTX_block_size(ctx))
|
||||
throw Exception("TokenEncrypt: encrypt/decrypt data must be equal to AES block size");
|
||||
int outlen=0;
|
||||
if (!EVP_CipherInit_ex(ctx, nullptr, nullptr, nullptr, nullptr, -1))
|
||||
throw OpenSSLException("TokenEncrypt: EVP_CipherInit_ex[2] failed");
|
||||
if (!EVP_CipherUpdate(ctx, dest, &outlen, src, size))
|
||||
throw OpenSSLException("TokenEncrypt: EVP_CipherUpdate failed");
|
||||
// NOTE: we skip EVP_CipherFinal_ex because we are running in ECB mode without padding
|
||||
if (outlen != size)
|
||||
throw Exception("TokenEncrypt: unexpected output length=" + std::to_string(outlen) + " expected=" + std::to_string(size));
|
||||
}
|
||||
|
||||
private:
|
||||
TokenEncrypt(const TokenEncrypt&) = delete;
|
||||
TokenEncrypt& operator=(const TokenEncrypt&) = delete;
|
||||
|
||||
EVP_CIPHER_CTX* ctx;
|
||||
};
|
||||
|
||||
struct TokenEncryptDecrypt
|
||||
{
|
||||
TokenEncryptDecrypt(const TokenEncrypt::Key& key)
|
||||
: encrypt(key, TokenEncrypt::ENCRYPT),
|
||||
decrypt(key, TokenEncrypt::DECRYPT)
|
||||
{
|
||||
}
|
||||
|
||||
TokenEncrypt encrypt;
|
||||
TokenEncrypt decrypt;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user