0
0
mirror of https://github.com/OpenVPN/openvpn3.git synced 2024-09-20 12:12:15 +02:00

Implement external PKI emulation with OpenSSL

This uses the rather lowlevel EVP_* interfaces directly instead of
using OpenVPN's own PKI classes since this a very specific code
and reusability outside the testing scope is very limited.

Signed-off-by: Arne Schwabe <arne@openvpn.net>
This commit is contained in:
Arne Schwabe 2021-09-09 01:40:04 +02:00 committed by David Sommerseth
parent 989d2f590a
commit 73890429d2
No known key found for this signature in database
GPG Key ID: 86CF944C9671FDF2

View File

@ -79,6 +79,8 @@
#if defined(USE_MBEDTLS) #if defined(USE_MBEDTLS)
#include <openvpn/mbedtls/util/pkcs1.hpp> #include <openvpn/mbedtls/util/pkcs1.hpp>
#elif defined(USE_OPENSSL)
#include <openssl/evp.h>
#endif #endif
#if defined(OPENVPN_PLATFORM_WIN) #if defined(OPENVPN_PLATFORM_WIN)
@ -231,6 +233,8 @@ public:
std::string epki_cert; std::string epki_cert;
#if defined(USE_MBEDTLS) #if defined(USE_MBEDTLS)
MbedTLSPKI::PKContext epki_ctx; // external PKI context MbedTLSPKI::PKContext epki_ctx; // external PKI context
#elif defined(USE_OPENSSL)
openvpn::OpenSSLPKI::PKey epki_pkey;
#endif #endif
void set_clock_tick_action(const ClockTickAction action) void set_clock_tick_action(const ClockTickAction action)
@ -456,6 +460,64 @@ private:
} }
} }
else else
#elif defined(USE_OPENSSL)
if (epki_pkey.defined())
{
EVP_PKEY_CTX* pkey_ctx = nullptr;
try {
BufferAllocated signdata(256, BufferAllocated::GROW);
base64->decode(signdata, signreq.data);
EVP_PKEY* pkey = epki_pkey.obj();
if(!(pkey_ctx = EVP_PKEY_CTX_new(pkey, NULL)))
throw Exception("epki_sign failed, error creating PKEY ctx");
if ((EVP_PKEY_sign_init(pkey_ctx) < 0))
{
throw Exception("epki_sign failed, error in EVP_PKEY_sign_init: " + openssl_error());
}
if (signreq.algorithm == "RSA_PKCS1_PADDING")
{
EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PADDING);
}
else if (signreq.algorithm == "RSA_NO_PADDING")
{
EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_NO_PADDING);
}
/* determine the output length */
std::size_t outlen;
if ((EVP_PKEY_sign(pkey_ctx, nullptr, &outlen, signdata.c_data(), signdata.size())) < 0)
{
throw Exception("epki_sign failed, error signing data: " + openssl_error());
}
BufferAllocated sig(outlen, BufferAllocated::ARRAY);
if ((EVP_PKEY_sign(pkey_ctx, sig.data(), &outlen, signdata.c_data(), signdata.size())) < 0)
{
throw Exception("epki_sign failed, error signing data: " + openssl_error());
}
sig.set_size(outlen);
// encode base64 signature
signreq.sig = base64->encode(sig);
OPENVPN_LOG("SIGNATURE[" << outlen << "]: " << signreq.sig);
}
catch (const std::exception& e)
{
signreq.error = true;
signreq.errorText = std::string("external_pki_sign_request: ") + e.what();
}
EVP_PKEY_CTX_free(pkey_ctx);
}
else
#endif #endif
{ {
signreq.error = true; signreq.error = true;
@ -1162,11 +1224,15 @@ int openvpn_client(int argc, char *argv[], const std::string* profile_content)
client.epki_cert = read_text_utf8(epki_cert_fn); client.epki_cert = read_text_utf8(epki_cert_fn);
if (!epki_ca_fn.empty()) if (!epki_ca_fn.empty())
client.epki_ca = read_text_utf8(epki_ca_fn); client.epki_ca = read_text_utf8(epki_ca_fn);
#if defined(USE_MBEDTLS) #if defined(USE_MBEDTLS) || defined(USE_OPENSSL)
if (!epki_key_fn.empty()) if (!epki_key_fn.empty())
{ {
const std::string epki_key_txt = read_text_utf8(epki_key_fn); const std::string epki_key_txt = read_text_utf8(epki_key_fn);
#if defined(USE_MBEDTLS)
client.epki_ctx.parse(epki_key_txt, "EPKI", privateKeyPassword); client.epki_ctx.parse(epki_key_txt, "EPKI", privateKeyPassword);
#else
client.epki_pkey.parse_pem(epki_key_txt, "epki private key");
#endif
} }
else else
OPENVPN_THROW_EXCEPTION("--epki-key must be specified"); OPENVPN_THROW_EXCEPTION("--epki-key must be specified");