Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions cmake/findcoredeps.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ set(CORE_DIR ${CMAKE_CURRENT_LIST_DIR}/..)

set(DEP_DIR ${CORE_DIR}/../deps CACHE PATH "Dependencies")
option(USE_MBEDTLS "Use mbed TLS instead of OpenSSL")
option(USE_AWSLC "Use AWS-LC as the crypto/SSL backend instead of the default")

option(USE_WERROR "Treat compiler warnings as errors (-Werror)")
option(USE_WCONVERSION "Enable -Wconversion")
Expand Down Expand Up @@ -43,6 +44,15 @@ function(add_ssl_library target)
set(SSL_LIBRARY mbedTLS::mbedTLS)
endif ()
target_compile_definitions(${target} PRIVATE -DUSE_MBEDTLS)
elseif (${USE_AWSLC})
if (NOT OPENSSL_ROOT_DIR)
message(FATAL_ERROR "USE_AWSLC requires -DOPENSSL_ROOT_DIR=/path/to/aws-lc/install")
endif ()
find_package(OpenSSL REQUIRED)
set(SSL_LIBRARY OpenSSL::SSL OpenSSL::Crypto)
include_directories(BEFORE SYSTEM "${OPENSSL_INCLUDE_DIR}")
message(STATUS "Using AWS-LC from: ${OPENSSL_ROOT_DIR}")
target_compile_definitions(${target} PRIVATE -DUSE_OPENSSL)
else ()
pkg_search_module(OpenSSL REQUIRED IMPORTED_TARGET openssl)
SET(SSL_LIBRARY PkgConfig::OpenSSL)
Expand Down
122 changes: 122 additions & 0 deletions openvpn/openssl/aws-lc-compat.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
// 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- OpenVPN Inc.
//
// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
//

#pragma once

#include <openssl/bio.h>
#include <openssl/bn.h>
#include <openssl/cipher.h>
#include <openssl/digest.h>
#include <openssl/ec_key.h>
#include <openssl/ecdsa.h>
#include <openssl/err.h>
#include <openssl/kdf.h>
#include <openssl/pkcs7.h>
#include <openssl/rsa.h>
#include <openssl/x509.h>
#include <openssl/x509_vfy.h>


#define BIO_F_MEM_WRITE 0
#define BIO_F_MEM_READ 0
#define BIOerr(f, r) ERR_put_error(ERR_LIB_BIO, (f), (r), __FILE__, __LINE__)

#define EVP_PKEY_DSA1 (-101)
#define EVP_PKEY_DSA2 (-102)
#define EVP_PKEY_DSA3 (-103)
#define EVP_PKEY_DSA4 (-104)

/* AWS-LC's GCM reads a NULL input as "finalize", so empty AAD/data (in=NULL, inl=0)
* would prematurely compute the tag. Substitute a valid zero length buffer so it
* stays a no-op. */
static inline int
EVP_EncryptUpdate_wrapper(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl)
{
static unsigned char empty_buf[1] = {0};
if (inl == 0 && in == nullptr)
in = empty_buf;
return EVP_EncryptUpdate(ctx, out, outl, in, inl);
}
#define EVP_EncryptUpdate EVP_EncryptUpdate_wrapper

static inline int
EVP_DecryptUpdate_wrapper(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl)
{
static unsigned char empty_buf[1] = {0};
if (inl == 0 && in == nullptr)
in = empty_buf;
return EVP_DecryptUpdate(ctx, out, outl, in, inl);
}
#define EVP_DecryptUpdate EVP_DecryptUpdate_wrapper


/* AWS-LC has no RSA_set_app_data or RSA_get_app_data. Re-provide them so a
* pointer can be attached to an RSA object and read back later. */
static inline int RSA_app_data_index()
{
static int idx = RSA_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr);
return idx;
}

static inline int RSA_set_app_data(RSA *rsa, void *data)
{
return RSA_set_ex_data(rsa, RSA_app_data_index(), data);
}

static inline void *RSA_get_app_data(const RSA *rsa)
{
return RSA_get_ex_data(rsa, RSA_app_data_index());
}

/* AWS-LC defines EC_KEY_METHOD_set_sign as a macro that static_asserts
* |sign_setup| == NULL. Override it to accept and drop |sign_setup| instead. */
static inline void
EC_KEY_METHOD_set_sign_wrapper(
EC_KEY_METHOD *meth,
int (*sign)(int type, const unsigned char *dgst, int dlen,
unsigned char *sig, unsigned int *siglen,
const BIGNUM *kinv, const BIGNUM *r, EC_KEY *eckey),
int (*)(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinvp, BIGNUM **rp),
ECDSA_SIG *(*sign_sig)(const unsigned char *dgst, int dgst_len,
const BIGNUM *in_kinv, const BIGNUM *in_r,
EC_KEY *eckey))
{
EC_KEY_METHOD_set_sign_awslc(meth, sign, sign_sig);
}
#undef EC_KEY_METHOD_set_sign
#define EC_KEY_METHOD_set_sign EC_KEY_METHOD_set_sign_wrapper

/* AWS-LC's PKCS7_verify rejects a NULL store even under PKCS7_NOVERIFY, where it
* goes unused. Pass an empty store when none is given. */
static inline int
PKCS7_verify_wrapper(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, BIO *indata, BIO *out, int flags)
{
static X509_STORE *empty_store = X509_STORE_new();
return PKCS7_verify(p7, certs, store ? store : empty_store, indata, out, flags);
}
#define PKCS7_verify PKCS7_verify_wrapper

static inline bool
CRYPTO_tls1_prf_wrapper(unsigned char *out,
size_t out_len,
const unsigned char *secret,
size_t secret_len,
const unsigned char *label,
size_t label_len)
{
return CRYPTO_tls1_prf(EVP_md5_sha1(),
out, out_len,
secret, secret_len,
reinterpret_cast<const char *>(label), label_len,
nullptr, 0,
nullptr, 0)
== 1;
}
1 change: 1 addition & 0 deletions openvpn/openssl/bio/bio_memq_dgram.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <openssl/err.h>
#include <openssl/bio.h>

#include <openvpn/openssl/compat.hpp>
#include <openvpn/common/size.hpp>
#include <openvpn/common/exception.hpp>
#include <openvpn/frame/frame.hpp>
Expand Down
4 changes: 4 additions & 0 deletions openvpn/openssl/compat.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@
#include <openssl/evp.h>
#include <openssl/ec.h>
#include <openssl/objects.h>
#include <openssl/rsa.h>

#ifdef OPENSSL_IS_AWSLC
#include <openvpn/openssl/aws-lc-compat.hpp>
#endif

/* Note that this is not a perfect emulation of the new function but
* is good enough for our case of printing certificate details during
Expand Down
1 change: 1 addition & 0 deletions openvpn/openssl/crypto/cipheraead.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <openvpn/crypto/cryptoalgs.hpp>
#include <openvpn/crypto/aead_usage_limit.hpp>
#include <openvpn/openssl/util/error.hpp>
#include <openvpn/openssl/compat.hpp>

namespace openvpn::OpenSSLCrypto {
class CipherContextAEAD
Expand Down
5 changes: 5 additions & 0 deletions openvpn/openssl/crypto/tls1prf.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <openssl/kdf.h>

#include <openvpn/common/numeric_util.hpp>
#include <openvpn/openssl/compat.hpp>

namespace openvpn::OpenSSLCrypto {

Expand Down Expand Up @@ -78,6 +79,9 @@ class TLS1PRF
unsigned char *out1,
const size_t olen)
{
#ifdef OPENSSL_IS_AWSLC
return CRYPTO_tls1_prf_wrapper(out1, olen, sec, slen, label, label_len);
#else
/* TODO use EVP_PKEY_CTX_new_from_name and library context for OpenSSL 3.0 but
* this needs passing the library context down here.*/
using EVP_PKEY_CTX_ptr = std::unique_ptr<EVP_PKEY_CTX, decltype(&::EVP_PKEY_CTX_free)>;
Expand Down Expand Up @@ -108,6 +112,7 @@ class TLS1PRF
return false;

return true;
#endif
}
#endif
};
Expand Down
6 changes: 3 additions & 3 deletions openvpn/openssl/pki/extpki.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ class ExternalPKIRsaImpl : public ExternalPKIImpl
RSA_meth_set_priv_dec(rsa_meth, rsa_priv_dec);
RSA_meth_set_init(rsa_meth, nullptr);
RSA_meth_set_finish(rsa_meth, rsa_finish);
RSA_meth_set0_app_data(rsa_meth, this);


/* get the public key */
Expand Down Expand Up @@ -75,6 +74,7 @@ class ExternalPKIRsaImpl : public ExternalPKIImpl
/* only set e and n as d (private key) is outside our control */
RSA_set0_key(rsa, BN_dup(RSA_get0_n(pub_rsa)), BN_dup(RSA_get0_e(pub_rsa)), nullptr);
RSA_set_flags(rsa, RSA_FLAG_EXT_PKEY);
RSA_set_app_data(rsa, this);

if (!RSA_set_method(rsa, rsa_meth))
{
Expand Down Expand Up @@ -122,7 +122,7 @@ class ExternalPKIRsaImpl : public ExternalPKIImpl
static int
rsa_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
{
ExternalPKIRsaImpl *self = (ExternalPKIRsaImpl *)(RSA_meth_get0_app_data(RSA_get_method(rsa)));
ExternalPKIRsaImpl *self = (ExternalPKIRsaImpl *)RSA_get_app_data(rsa);

try
{
Expand Down Expand Up @@ -173,7 +173,7 @@ class ExternalPKIRsaImpl : public ExternalPKIImpl

static void not_implemented(RSA *rsa)
{
ExternalPKIRsaImpl *self = (ExternalPKIRsaImpl *)(RSA_meth_get0_app_data(RSA_get_method(rsa)));
ExternalPKIRsaImpl *self = (ExternalPKIRsaImpl *)RSA_get_app_data(rsa);
++self->n_errors;
}

Expand Down
1 change: 1 addition & 0 deletions openvpn/openssl/sign/pkcs7verify.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <openvpn/common/cleanup.hpp>
#include <openvpn/common/numeric_cast.hpp>
#include <openvpn/openssl/pki/x509.hpp>
#include <openvpn/openssl/compat.hpp>
#include <openvpn/openssl/util/error.hpp>

namespace openvpn::OpenSSLSign {
Expand Down
7 changes: 4 additions & 3 deletions openvpn/openssl/ssl/sslctx.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
#include <openvpn/ssl/sslapi.hpp>
#include <openvpn/ssl/sni_handler.hpp>
#include <openvpn/ssl/iana_ciphers.hpp>
#include <openvpn/openssl/compat.hpp>
#include <openvpn/openssl/util/error.hpp>
#if ENABLE_EXTERNAL_PKI
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
Expand Down Expand Up @@ -1100,7 +1101,7 @@ class OpenSSLContext : public SSLFactoryAPI
const SSL_CIPHER *ciph = SSL_get_current_cipher(ssl);
if (ciph)
{
char *desc = SSL_CIPHER_description(ciph, nullptr, 0);
char *desc = const_cast<char *>(SSL_CIPHER_description(ciph, nullptr, 0));
if (!desc)
{
os << ", cipher: Error getting TLS cipher description from SSL_CIPHER_description";
Expand Down Expand Up @@ -1480,12 +1481,12 @@ class OpenSSLContext : public SSLFactoryAPI
auto certType = EVP_PKEY_id(X509_get0_pubkey(config->cert.obj()));
if (certType == EVP_PKEY_RSA)
{
epki = std::make_shared<ExternalPKIImpl>(ExternalPKIRsaImpl(ctx.get(), config->cert.obj(), config->external_pki, config->external_pki_alias));
epki = std::make_shared<ExternalPKIRsaImpl>(ctx.get(), config->cert.obj(), config->external_pki, config->external_pki_alias);
}
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(OPENSSL_NO_EC)
else if (certType == EVP_PKEY_EC)
{
epki = std::make_shared<ExternalPKIImpl>(ExternalPKIECImpl(ctx.get(), config->cert.obj(), config->external_pki, config->external_pki_alias));
epki = std::make_shared<ExternalPKIECImpl>(ctx.get(), config->cert.obj(), config->external_pki, config->external_pki_alias);
}
#endif
else
Expand Down
9 changes: 9 additions & 0 deletions openvpn/openssl/util/error.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <openvpn/common/exception.hpp>
#include <openvpn/error/error.hpp>
#include <openvpn/error/excode.hpp>
#include <openvpn/openssl/compat.hpp>

namespace openvpn {

Expand Down Expand Up @@ -147,21 +148,27 @@ class OpenSSLException : public ExceptionCode
case SSL_R_UNSUPPORTED_PROTOCOL:
set_code(Error::TLS_VERSION_MIN, true);
break;
#ifdef SSL_R_CA_MD_TOO_WEAK
case SSL_R_CA_MD_TOO_WEAK:
set_code(Error::SSL_CA_MD_TOO_WEAK, true);
break;
#endif
#ifdef SSL_R_CA_KEY_TOO_SMALL
case SSL_R_CA_KEY_TOO_SMALL:
set_code(Error::SSL_CA_KEY_TOO_SMALL, true);
break;
#endif
#ifdef SSL_R_LEGACY_SIGALG_DISALLOWED_OR_UNSUPPORTED
/* This error code has been added in OpenSSL 3.0.8 */
case SSL_R_LEGACY_SIGALG_DISALLOWED_OR_UNSUPPORTED:
set_code(Error::TLS_SIGALG_DISALLOWED_OR_UNSUPPORTED, true);
break;
#endif
#ifdef SSL_R_DH_KEY_TOO_SMALL
case SSL_R_DH_KEY_TOO_SMALL:
set_code(Error::SSL_DH_KEY_TOO_SMALL, true);
break;
#endif
case SSL_R_TLSV1_ALERT_PROTOCOL_VERSION:
set_code(Error::TLS_ALERT_PROTOCOL_VERSION, true);
break;
Expand All @@ -171,9 +178,11 @@ class OpenSSLException : public ExceptionCode
case SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE:
set_code(Error::TLS_ALERT_HANDSHAKE_FAILURE, true);
break;
#ifdef SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED
case SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED:
set_code(Error::TLS_ALERT_CERTIFICATE_REQUIRED, true);
break;
#endif
case SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED:
set_code(Error::TLS_ALERT_CERTIFICATE_EXPIRED, true);
break;
Expand Down