14#include <openssl/rsa.h>
15#include <openssl/evp.h>
17#include <openssl/ec.h>
18#include <openssl/ecdsa.h>
35 const RSA *pub_rsa =
nullptr;
36 RSA_METHOD *rsa_meth =
nullptr;
37 const char *errtext =
"";
40 rsa_meth = RSA_meth_new(
"OpenSSLContext::ExternalPKIRsaImpl private key RSA Method",
41 RSA_METHOD_FLAG_NO_CHECK);
47 RSA_meth_set_init(rsa_meth,
nullptr);
49 RSA_meth_set0_app_data(rsa_meth,
this);
53 if (X509_get0_pubkey(cert) ==
nullptr)
55 errtext =
"pkey is NULL";
59 if (EVP_PKEY_id(X509_get0_pubkey(cert)) != EVP_PKEY_RSA)
61 errtext =
"pkey is not RSA";
64 pub_rsa = EVP_PKEY_get0_RSA(X509_get0_pubkey(cert));
70 SSLerr(SSL_F_SSL_USE_PRIVATEKEY, ERR_R_MALLOC_FAILURE);
76 RSA_set0_key(rsa, BN_dup(RSA_get0_n(pub_rsa)), BN_dup(RSA_get0_e(pub_rsa)),
nullptr);
77 RSA_set_flags(rsa, RSA_FLAG_EXT_PKEY);
79 if (!RSA_set_method(rsa, rsa_meth))
81 errtext =
"RSA_set_method";
90 if (!SSL_CTX_use_RSAPrivateKey(ssl_ctx, rsa))
92 errtext =
"SSL_CTX_use_RSAPrivateKey";
101 RSA_meth_free(rsa_meth);
117 RSA_meth_free(
const_cast<RSA_METHOD *
>(RSA_get_method(rsa)));
123 rsa_priv_enc(
int flen,
const unsigned char *from,
unsigned char *to, RSA *rsa,
int padding)
129 if (padding != RSA_PKCS1_PADDING && padding != RSA_NO_PADDING)
131 RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE);
134 std::string padding_algo;
135 if (padding == RSA_PKCS1_PADDING)
137 padding_algo =
"RSA_PKCS1_PADDING";
139 else if (padding == RSA_NO_PADDING)
141 padding_algo =
"RSA_NO_PADDING";
155 const int len = RSA_size(rsa);
156 Buffer sig(to, len,
false);
160 if (sig.
size() !=
static_cast<size_t>(len))
166 catch (
const std::exception &e)
168 OPENVPN_LOG(
"OpenSSLContext::ExternalPKIRsaImpl::rsa_priv_enc exception: " << e.what());
182 rsa_pub_enc(
int flen,
const unsigned char *from,
unsigned char *to, RSA *rsa,
int padding)
190 rsa_pub_dec(
int flen,
const unsigned char *from,
unsigned char *to, RSA *rsa,
int padding)
198 rsa_priv_dec(
int flen,
const unsigned char *from,
unsigned char *to, RSA *rsa,
int padding)
210#if !defined(OPENSSL_NO_EC)
220 throw ssl_external_pki(
"ExternalPKIECImpl::ec_self_data_index is uninitialized");
224 EVP_PKEY *privkey =
nullptr;
225 EC_KEY *ec =
nullptr;
226 EC_KEY_METHOD *ec_method = EC_KEY_METHOD_new(EC_KEY_OpenSSL());
229 EC_KEY_METHOD_set_init(ec_method, NULL,
ec_finish, NULL, NULL, NULL, NULL);
233 EVP_PKEY *pubkey = X509_get0_pubkey(cert);
235 if (pubkey ==
nullptr)
237 errtext =
"public key is NULL";
241 if (EVP_PKEY_id(pubkey) != EVP_PKEY_EC)
243 errtext =
"public key is not EC";
247 ec = EVP_PKEY_get1_EC_KEY(pubkey);
251 errtext =
"cannot get public EC key";
256 if (!EC_KEY_set_method(ec, ec_method))
258 errtext =
"Could not set EC method";
259 EC_KEY_METHOD_free(ec_method);
265 errtext =
"Could not set EC Key ex data";
266 EC_KEY_METHOD_free(ec_method);
270 privkey = EVP_PKEY_new();
271 if (!EVP_PKEY_assign_EC_KEY(privkey, ec))
273 errtext =
"assigning EC key methods failed";
277 if (!SSL_CTX_use_PrivateKey(ssl_ctx, privkey))
279 errtext =
"assigning EC private key to SSL context failed";
283 EVP_PKEY_free(privkey);
290 EVP_PKEY_free(privkey);
303 ec_self_data_index = EC_KEY_get_ex_new_index(0, (
char *)
"ExternalPKIECImpl",
nullptr,
nullptr,
nullptr);
309 EC_KEY_METHOD_free(
const_cast<EC_KEY_METHOD *
>(EC_KEY_get_method(ec)));
314 const unsigned char *dgst,
317 unsigned int *siglen,
326 *siglen = ECDSA_size(eckey);
327 self->
do_sign(dgst, dlen, sig, *siglen);
331 catch (
const std::exception &e)
333 OPENVPN_LOG(
"OpenSSLContext::ExternalPKIECImpl::ecdsa_sign exception: " << e.what());
345 ecdsa_sign_sig(
const unsigned char *dgst,
int dgstlen,
const BIGNUM *kinvp,
const BIGNUM *rp, EC_KEY *eckey)
349 unsigned len = ECDSA_size(eckey);
351 auto sig =
new unsigned char[len];
353 ECDSA_SIG *ecsig =
nullptr;
356 unsigned int siglen = len;
357 self->
do_sign(dgst, dgstlen, sig, siglen);
359 ecsig = d2i_ECDSA_SIG(NULL, (
const unsigned char **)&sig, siglen);
361 catch (
const std::exception &e)
363 OPENVPN_LOG(
"OpenSSLContext::ExternalPKIECImpl::ecdsa_sign_sig exception: " << e.what());
379 void do_sign(
const unsigned char *dgst,
int dlen,
unsigned char *sig,
unsigned int &siglen)
392 Buffer sigout(sig, siglen,
false);
395 siglen = sigout.
size();
std::string encode(const V &data) const
size_t decode(void *data, size_t len, const std::string &str) const
size_t size() const
Returns the size of the buffer in T objects.
virtual bool sign(const std::string &alias, const std::string &data, std::string &sig, const std::string &algorithm, const std::string &hashalg, const std::string &saltlen)=0
static int ec_self_data_index
ExternalPKIBase * external_pki
static ECDSA_SIG * ecdsa_sign_sig(const unsigned char *dgst, int dgstlen, const BIGNUM *kinvp, const BIGNUM *rp, EC_KEY *eckey)
static void ec_finish(EC_KEY *ec)
static void init_static()
static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp)
void do_sign(const unsigned char *dgst, int dlen, unsigned char *sig, unsigned int &siglen)
ExternalPKIECImpl(SSL_CTX *ssl_ctx, ::X509 *cert, ExternalPKIBase *external_pki_arg, const std::string &alias)
static int ecdsa_sign(int type, const unsigned char *dgst, int dlen, unsigned char *sig, unsigned int *siglen, const BIGNUM *kinv, const BIGNUM *r, EC_KEY *eckey)
~ExternalPKIECImpl() override=default
~ExternalPKIRsaImpl() override=default
static int rsa_priv_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
unsigned int get_n_errors() const
static int rsa_pub_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
static void not_implemented(RSA *rsa)
static int rsa_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
static int rsa_finish(RSA *rsa)
ExternalPKIRsaImpl(SSL_CTX *ssl_ctx, ::X509 *cert, ExternalPKIBase *external_pki_arg, const std::string &alias)
static int rsa_pub_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
ExternalPKIBase * external_pki
#define OPENVPN_THROW(exc, stuff)
#define OPENVPN_LOG(args)
Support deferred server-side state creation when client connects.
SSLFactoryAPI::ssl_external_pki ssl_external_pki