diff options
Diffstat (limited to 'usr.sbin/smtpd/ca.c')
-rw-r--r-- | usr.sbin/smtpd/ca.c | 777 |
1 files changed, 777 insertions, 0 deletions
diff --git a/usr.sbin/smtpd/ca.c b/usr.sbin/smtpd/ca.c new file mode 100644 index 00000000..a27db87a --- /dev/null +++ b/usr.sbin/smtpd/ca.c @@ -0,0 +1,777 @@ +/* $OpenBSD: ca.c,v 1.36 2019/09/21 07:46:53 semarie Exp $ */ + +/* + * Copyright (c) 2014 Reyk Floeter <reyk@openbsd.org> + * Copyright (c) 2012 Gilles Chehade <gilles@poolp.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "includes.h" + +#include <sys/types.h> +#include <sys/queue.h> +#include <sys/socket.h> +#include <sys/tree.h> + +#include <grp.h> /* needed for setgroups */ +#include <err.h> +#include <imsg.h> +#include <limits.h> +#include <pwd.h> +#include <signal.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <openssl/ssl.h> +#include <openssl/pem.h> +#include <openssl/evp.h> +#include <openssl/ecdsa.h> +#include <openssl/rsa.h> +#include <openssl/engine.h> +#include <openssl/err.h> + +#include "smtpd.h" +#include "log.h" +#include "ssl.h" + +static int ca_verify_cb(int, X509_STORE_CTX *); + +static int rsae_send_imsg(int, const unsigned char *, unsigned char *, + RSA *, int, unsigned int); +static int rsae_pub_enc(int, const unsigned char *, unsigned char *, + RSA *, int); +static int rsae_pub_dec(int,const unsigned char *, unsigned char *, + RSA *, int); +static int rsae_priv_enc(int, const unsigned char *, unsigned char *, + RSA *, int); +static int rsae_priv_dec(int, const unsigned char *, unsigned char *, + RSA *, int); +static int rsae_mod_exp(BIGNUM *, const BIGNUM *, RSA *, BN_CTX *); +static int rsae_bn_mod_exp(BIGNUM *, const BIGNUM *, const BIGNUM *, + const BIGNUM *, BN_CTX *, BN_MONT_CTX *); +static int rsae_init(RSA *); +static int rsae_finish(RSA *); +static int rsae_keygen(RSA *, int, BIGNUM *, BN_GENCB *); + +#if defined(SUPPORT_ECDSA) +static ECDSA_SIG *ecdsae_do_sign(const unsigned char *, int, const BIGNUM *, + const BIGNUM *, EC_KEY *); +static int ecdsae_sign_setup(EC_KEY *, BN_CTX *, BIGNUM **, BIGNUM **); +static int ecdsae_do_verify(const unsigned char *, int, const ECDSA_SIG *, + EC_KEY *); +#endif + +static uint64_t reqid = 0; + +static void +ca_shutdown(void) +{ + log_debug("debug: ca agent exiting"); + _exit(0); +} + +int +ca(void) +{ + struct passwd *pw; + + purge_config(PURGE_LISTENERS|PURGE_TABLES|PURGE_RULES|PURGE_DISPATCHERS); + + if ((pw = getpwnam(SMTPD_USER)) == NULL) + fatalx("unknown user " SMTPD_USER); + + if (chroot(PATH_CHROOT) == -1) + fatal("ca: chroot"); + if (chdir("/") == -1) + fatal("ca: chdir(\"/\")"); + + config_process(PROC_CA); + + if (setgroups(1, &pw->pw_gid) || + setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || + setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) + fatal("ca: cannot drop privileges"); + + imsg_callback = ca_imsg; + event_init(); + + signal(SIGINT, SIG_IGN); + signal(SIGTERM, SIG_IGN); + signal(SIGPIPE, SIG_IGN); + signal(SIGHUP, SIG_IGN); + + config_peer(PROC_CONTROL); + config_peer(PROC_PARENT); + config_peer(PROC_PONY); + + /* Ignore them until we get our config */ + mproc_disable(p_pony); + +#if HAVE_PLEDGE + if (pledge("stdio", NULL) == -1) + err(1, "pledge"); +#endif + + event_dispatch(); + fatalx("exited event loop"); + + return (0); +} + +void +ca_init(void) +{ + BIO *in = NULL; + EVP_PKEY *pkey = NULL; + struct pki *pki; + const char *k; + void *iter_dict; + + log_debug("debug: init private ssl-tree"); + iter_dict = NULL; + while (dict_iter(env->sc_pki_dict, &iter_dict, &k, (void **)&pki)) { + if (pki->pki_key == NULL) + continue; + + if ((in = BIO_new_mem_buf(pki->pki_key, + pki->pki_key_len)) == NULL) + fatalx("ca_launch: key"); + + if ((pkey = PEM_read_bio_PrivateKey(in, + NULL, NULL, NULL)) == NULL) + fatalx("ca_launch: PEM"); + BIO_free(in); + + pki->pki_pkey = pkey; + + freezero(pki->pki_key, pki->pki_key_len); + pki->pki_key = NULL; + } +} + +static int +ca_verify_cb(int ok, X509_STORE_CTX *ctx) +{ + switch (X509_STORE_CTX_get_error(ctx)) { + case X509_V_OK: + break; + case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: + break; + case X509_V_ERR_CERT_NOT_YET_VALID: + case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: + break; + case X509_V_ERR_CERT_HAS_EXPIRED: + case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: + break; + case X509_V_ERR_NO_EXPLICIT_POLICY: + break; + } + return ok; +} + +int +ca_X509_verify(void *certificate, void *chain, const char *CAfile, + const char *CRLfile, const char **errstr) +{ + X509_STORE *store = NULL; + X509_STORE_CTX *xsc = NULL; + int ret = 0; + long error = 0; + + if ((store = X509_STORE_new()) == NULL) + goto end; + + if (!X509_STORE_load_locations(store, CAfile, NULL)) { + log_warn("warn: unable to load CA file %s", CAfile); + goto end; + } + X509_STORE_set_default_paths(store); + + if ((xsc = X509_STORE_CTX_new()) == NULL) + goto end; + + if (X509_STORE_CTX_init(xsc, store, certificate, chain) != 1) + goto end; + + X509_STORE_CTX_set_verify_cb(xsc, ca_verify_cb); + + ret = X509_verify_cert(xsc); + +end: + *errstr = NULL; + if (ret != 1) { + if (xsc) { + error = X509_STORE_CTX_get_error(xsc); + *errstr = X509_verify_cert_error_string(error); + } + else if (ERR_peek_last_error()) + *errstr = ERR_error_string(ERR_peek_last_error(), NULL); + } + + X509_STORE_CTX_free(xsc); + X509_STORE_free(store); + + return ret > 0 ? 1 : 0; +} + +void +ca_imsg(struct mproc *p, struct imsg *imsg) +{ + RSA *rsa = NULL; +#if defined(SUPPORT_ECDSA) + EC_KEY *ecdsa = NULL; +#endif + const void *from = NULL; + unsigned char *to = NULL; + struct msg m; + const char *pkiname; + size_t flen, tlen, padding; +#if defined(SUPPORT_ECDSA) + int buf_len; +#endif + struct pki *pki; + int ret = 0; + uint64_t id; + int v; + + if (imsg == NULL) + ca_shutdown(); + + switch (imsg->hdr.type) { + case IMSG_CONF_START: + return; + case IMSG_CONF_END: + ca_init(); + + /* Start fulfilling requests */ + mproc_enable(p_pony); + return; + + case IMSG_CTL_VERBOSE: + m_msg(&m, imsg); + m_get_int(&m, &v); + m_end(&m); + log_trace_verbose(v); + return; + + case IMSG_CTL_PROFILE: + m_msg(&m, imsg); + m_get_int(&m, &v); + m_end(&m); + profiling = v; + return; + + case IMSG_CA_RSA_PRIVENC: + case IMSG_CA_RSA_PRIVDEC: + m_msg(&m, imsg); + m_get_id(&m, &id); + m_get_string(&m, &pkiname); + m_get_data(&m, &from, &flen); + m_get_size(&m, &tlen); + m_get_size(&m, &padding); + m_end(&m); + + pki = dict_get(env->sc_pki_dict, pkiname); + if (pki == NULL || pki->pki_pkey == NULL || + (rsa = EVP_PKEY_get1_RSA(pki->pki_pkey)) == NULL) + fatalx("ca_imsg: invalid pki"); + + if ((to = calloc(1, tlen)) == NULL) + fatalx("ca_imsg: calloc"); + + switch (imsg->hdr.type) { + case IMSG_CA_RSA_PRIVENC: + ret = RSA_private_encrypt(flen, from, to, rsa, + padding); + break; + case IMSG_CA_RSA_PRIVDEC: + ret = RSA_private_decrypt(flen, from, to, rsa, + padding); + break; + } + + m_create(p, imsg->hdr.type, 0, 0, -1); + m_add_id(p, id); + m_add_int(p, ret); + if (ret > 0) + m_add_data(p, to, (size_t)ret); + m_close(p); + + free(to); + RSA_free(rsa); + return; + +#if defined(SUPPORT_ECDSA) + case IMSG_CA_ECDSA_SIGN: + m_msg(&m, imsg); + m_get_id(&m, &id); + m_get_string(&m, &pkiname); + m_get_data(&m, &from, &flen); + m_end(&m); + + pki = dict_get(env->sc_pki_dict, pkiname); + if (pki == NULL || pki->pki_pkey == NULL || + (ecdsa = EVP_PKEY_get1_EC_KEY(pki->pki_pkey)) == NULL) + fatalx("ca_imsg: invalid pki"); + + buf_len = ECDSA_size(ecdsa); + if ((to = calloc(1, buf_len)) == NULL) + fatalx("ca_imsg: calloc"); + ret = ECDSA_sign(0, from, flen, to, &buf_len, ecdsa); + m_create(p, imsg->hdr.type, 0, 0, -1); + m_add_id(p, id); + m_add_int(p, ret); + if (ret > 0) + m_add_data(p, to, (size_t)buf_len); + m_close(p); + free(to); + EC_KEY_free(ecdsa); + return; +#endif + } + errx(1, "ca_imsg: unexpected %s imsg", imsg_to_str(imsg->hdr.type)); +} + +/* + * RSA privsep engine (called from unprivileged processes) + */ + +const RSA_METHOD *rsa_default = NULL; + +static RSA_METHOD *rsae_method = NULL; + +static int +rsae_send_imsg(int flen, const unsigned char *from, unsigned char *to, + RSA *rsa, int padding, unsigned int cmd) +{ + int ret = 0; + struct imsgbuf *ibuf; + struct imsg imsg; + int n, done = 0; + const void *toptr; + char *pkiname; + size_t tlen; + struct msg m; + uint64_t id; + + if ((pkiname = RSA_get_ex_data(rsa, 0)) == NULL) + return (0); + + /* + * Send a synchronous imsg because we cannot defer the RSA + * operation in OpenSSL's engine layer. + */ + m_create(p_ca, cmd, 0, 0, -1); + reqid++; + m_add_id(p_ca, reqid); + m_add_string(p_ca, pkiname); + m_add_data(p_ca, (const void *)from, (size_t)flen); + m_add_size(p_ca, (size_t)RSA_size(rsa)); + m_add_size(p_ca, (size_t)padding); + m_flush(p_ca); + + ibuf = &p_ca->imsgbuf; + + while (!done) { + if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) + fatalx("imsg_read"); + if (n == 0) + fatalx("pipe closed"); + + while (!done) { + if ((n = imsg_get(ibuf, &imsg)) == -1) + fatalx("imsg_get error"); + if (n == 0) + break; + + log_imsg(PROC_PONY, PROC_CA, &imsg); + + switch (imsg.hdr.type) { + case IMSG_CA_RSA_PRIVENC: + case IMSG_CA_RSA_PRIVDEC: + break; + default: + /* Another imsg is queued up in the buffer */ + pony_imsg(p_ca, &imsg); + imsg_free(&imsg); + continue; + } + + m_msg(&m, &imsg); + m_get_id(&m, &id); + if (id != reqid) + fatalx("invalid response id"); + m_get_int(&m, &ret); + if (ret > 0) + m_get_data(&m, &toptr, &tlen); + m_end(&m); + + if (ret > 0) + memcpy(to, toptr, tlen); + done = 1; + + imsg_free(&imsg); + } + } + mproc_event_add(p_ca); + + return (ret); +} + +static int +rsae_pub_enc(int flen,const unsigned char *from, unsigned char *to, RSA *rsa, + int padding) +{ + log_debug("debug: %s: %s", proc_name(smtpd_process), __func__); + return (RSA_meth_get_pub_enc(rsa_default)(flen, from, to, rsa, padding)); +} + +static int +rsae_pub_dec(int flen,const unsigned char *from, unsigned char *to, RSA *rsa, + int padding) +{ + log_debug("debug: %s: %s", proc_name(smtpd_process), __func__); + return (RSA_meth_get_pub_dec(rsa_default)(flen, from, to, rsa, padding)); +} + +static int +rsae_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, + int padding) +{ + log_debug("debug: %s: %s", proc_name(smtpd_process), __func__); + if (RSA_get_ex_data(rsa, 0) != NULL) + return (rsae_send_imsg(flen, from, to, rsa, padding, + IMSG_CA_RSA_PRIVENC)); + return (RSA_meth_get_priv_enc(rsa_default)(flen, from, to, rsa, padding)); +} + +static int +rsae_priv_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, + int padding) +{ + log_debug("debug: %s: %s", proc_name(smtpd_process), __func__); + if (RSA_get_ex_data(rsa, 0) != NULL) + return (rsae_send_imsg(flen, from, to, rsa, padding, + IMSG_CA_RSA_PRIVDEC)); + + return (RSA_meth_get_priv_dec(rsa_default)(flen, from, to, rsa, padding)); +} + +static int +rsae_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) +{ + log_debug("debug: %s: %s", proc_name(smtpd_process), __func__); + return (RSA_meth_get_mod_exp(rsa_default)(r0, I, rsa, ctx)); +} + +static int +rsae_bn_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) +{ + log_debug("debug: %s: %s", proc_name(smtpd_process), __func__); + return (RSA_meth_get_bn_mod_exp(rsa_default)(r, a, p, m, ctx, m_ctx)); +} + +static int +rsae_init(RSA *rsa) +{ + log_debug("debug: %s: %s", proc_name(smtpd_process), __func__); + if (RSA_meth_get_init(rsa_default) == NULL) + return (1); + return (RSA_meth_get_init(rsa_default)(rsa)); +} + +static int +rsae_finish(RSA *rsa) +{ + log_debug("debug: %s: %s", proc_name(smtpd_process), __func__); + if (RSA_meth_get_finish(rsa_default) == NULL) + return (1); + return (RSA_meth_get_finish(rsa_default)(rsa)); +} + +static int +rsae_keygen(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb) +{ + log_debug("debug: %s: %s", proc_name(smtpd_process), __func__); + return (RSA_meth_get_keygen(rsa_default)(rsa, bits, e, cb)); +} + + +#if defined(SUPPORT_ECDSA) +/* + * ECDSA privsep engine (called from unprivileged processes) + */ + +const ECDSA_METHOD *ecdsa_default = NULL; + +static ECDSA_METHOD *ecdsae_method = NULL; + +ECDSA_METHOD * +ECDSA_METHOD_new_temporary(const char *name, int); + +ECDSA_METHOD * +ECDSA_METHOD_new_temporary(const char *name, int flags) +{ + ECDSA_METHOD *ecdsa; + + if ((ecdsa = calloc(1, sizeof (*ecdsa))) == NULL) + return NULL; + + if ((ecdsa->name = strdup(name)) == NULL) { + free(ecdsa); + return NULL; + } + + ecdsa->flags = flags; + return ecdsa; +} + +static ECDSA_SIG * +ecdsae_send_enc_imsg(const unsigned char *dgst, int dgst_len, + const BIGNUM *inv, const BIGNUM *rp, EC_KEY *eckey) +{ + int ret = 0; + struct imsgbuf *ibuf; + struct imsg imsg; + int n, done = 0; + const void *toptr; + char *pkiname; + size_t tlen; + struct msg m; + uint64_t id; + ECDSA_SIG *sig = NULL; + + if ((pkiname = ECDSA_get_ex_data(eckey, 0)) == NULL) + return (0); + + /* + * Send a synchronous imsg because we cannot defer the ECDSA + * operation in OpenSSL's engine layer. + */ + m_create(p_ca, IMSG_CA_ECDSA_SIGN, 0, 0, -1); + reqid++; + m_add_id(p_ca, reqid); + m_add_string(p_ca, pkiname); + m_add_data(p_ca, (const void *)dgst, (size_t)dgst_len); + m_flush(p_ca); + + ibuf = &p_ca->imsgbuf; + + while (!done) { + if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) + fatalx("imsg_read"); + if (n == 0) + fatalx("pipe closed"); + while (!done) { + if ((n = imsg_get(ibuf, &imsg)) == -1) + fatalx("imsg_get error"); + if (n == 0) + break; + + log_imsg(PROC_PONY, PROC_CA, &imsg); + + switch (imsg.hdr.type) { + case IMSG_CA_ECDSA_SIGN: + break; + default: + /* Another imsg is queued up in the buffer */ + pony_imsg(p_ca, &imsg); + imsg_free(&imsg); + continue; + } + + m_msg(&m, &imsg); + m_get_id(&m, &id); + if (id != reqid) + fatalx("invalid response id"); + m_get_int(&m, &ret); + if (ret > 0) + m_get_data(&m, &toptr, &tlen); + m_end(&m); + done = 1; + + if (ret > 0) + d2i_ECDSA_SIG(&sig, (const unsigned char **)&toptr, tlen); + imsg_free(&imsg); + } + } + mproc_event_add(p_ca); + + return (sig); +} + +ECDSA_SIG * +ecdsae_do_sign(const unsigned char *dgst, int dgst_len, + const BIGNUM *inv, const BIGNUM *rp, EC_KEY *eckey) +{ + log_debug("debug: %s: %s", proc_name(smtpd_process), __func__); + if (ECDSA_get_ex_data(eckey, 0) != NULL) + return (ecdsae_send_enc_imsg(dgst, dgst_len, inv, rp, eckey)); + return (ecdsa_default->ecdsa_do_sign(dgst, dgst_len, inv, rp, eckey)); +} + +int +ecdsae_sign_setup(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv, + BIGNUM **r) +{ + log_debug("debug: %s: %s", proc_name(smtpd_process), __func__); + return (ecdsa_default->ecdsa_sign_setup(eckey, ctx, kinv, r)); +} + +int +ecdsae_do_verify(const unsigned char *dgst, int dgst_len, + const ECDSA_SIG *sig, EC_KEY *eckey) +{ + log_debug("debug: %s: %s", proc_name(smtpd_process), __func__); + return (ecdsa_default->ecdsa_do_verify(dgst, dgst_len, sig, eckey)); +} +#endif + +static void +rsa_engine_init(void) +{ + ENGINE *e; + const char *errstr, *name; + + if ((rsae_method = RSA_meth_new("RSA privsep engine", 0)) == NULL) { + errstr = "RSA_meth_new"; + goto fail; + } + + RSA_meth_set_pub_enc(rsae_method, rsae_pub_enc); + RSA_meth_set_pub_dec(rsae_method, rsae_pub_dec); + RSA_meth_set_priv_enc(rsae_method, rsae_priv_enc); + RSA_meth_set_priv_dec(rsae_method, rsae_priv_dec); + RSA_meth_set_mod_exp(rsae_method, rsae_mod_exp); + RSA_meth_set_bn_mod_exp(rsae_method, rsae_bn_mod_exp); + RSA_meth_set_init(rsae_method, rsae_init); + RSA_meth_set_finish(rsae_method, rsae_finish); + RSA_meth_set_keygen(rsae_method, rsae_keygen); + + if ((e = ENGINE_get_default_RSA()) == NULL) { + if ((e = ENGINE_new()) == NULL) { + errstr = "ENGINE_new"; + goto fail; + } + if (!ENGINE_set_name(e, RSA_meth_get0_name(rsae_method))) { + errstr = "ENGINE_set_name"; + goto fail; + } + if ((rsa_default = RSA_get_default_method()) == NULL) { + errstr = "RSA_get_default_method"; + goto fail; + } + } else if ((rsa_default = ENGINE_get_RSA(e)) == NULL) { + errstr = "ENGINE_get_RSA"; + goto fail; + } + + if ((name = ENGINE_get_name(e)) == NULL) + name = "unknown RSA engine"; + + log_debug("debug: %s: using %s", __func__, name); + + if (RSA_meth_get_mod_exp(rsa_default) == NULL) + RSA_meth_set_mod_exp(rsae_method, NULL); + if (RSA_meth_get_bn_mod_exp(rsa_default) == NULL) + RSA_meth_set_bn_mod_exp(rsae_method, NULL); + if (RSA_meth_get_keygen(rsa_default) == NULL) + RSA_meth_set_keygen(rsae_method, NULL); + RSA_meth_set_flags(rsae_method, + RSA_meth_get_flags(rsa_default) | RSA_METHOD_FLAG_NO_CHECK); + RSA_meth_set0_app_data(rsae_method, + RSA_meth_get0_app_data(rsa_default)); + + if (!ENGINE_set_RSA(e, rsae_method)) { + errstr = "ENGINE_set_RSA"; + goto fail; + } + if (!ENGINE_set_default_RSA(e)) { + errstr = "ENGINE_set_default_RSA"; + goto fail; + } + + return; + + fail: + ssl_error(errstr); + fatalx("%s", errstr); +} + +#if defined(SUPPORT_ECDSA) +static void +ecdsa_engine_init(void) +{ + ENGINE *e; + const char *errstr, *name; + + if ((ecdsae_method = ECDSA_METHOD_new_temporary("ECDSA privsep engine", 0)) == NULL) { + errstr = "ECDSA_METHOD_new_temporary"; + goto fail; + } + + ecdsae_method->ecdsa_do_sign = ecdsae_do_sign; + ecdsae_method->ecdsa_sign_setup = ecdsae_sign_setup; + ecdsae_method->ecdsa_do_verify = ecdsae_do_verify; + + if ((e = ENGINE_get_default_ECDSA()) == NULL) { + if ((e = ENGINE_new()) == NULL) { + errstr = "ENGINE_new"; + goto fail; + } + if (!ENGINE_set_name(e, ecdsae_method->name)) { + errstr = "ENGINE_set_name"; + goto fail; + } + if ((ecdsa_default = ECDSA_get_default_method()) == NULL) { + errstr = "ECDSA_get_default_method"; + goto fail; + } + } else if ((ecdsa_default = ENGINE_get_ECDSA(e)) == NULL) { + errstr = "ENGINE_get_ECDSA"; + goto fail; + } + + if ((name = ENGINE_get_name(e)) == NULL) + name = "unknown ECDSA engine"; + + log_debug("debug: %s: using %s", __func__, name); + + if (!ENGINE_set_ECDSA(e, ecdsae_method)) { + errstr = "ENGINE_set_ECDSA"; + goto fail; + } + if (!ENGINE_set_default_ECDSA(e)) { + errstr = "ENGINE_set_default_ECDSA"; + goto fail; + } + + return; + + fail: + ssl_error(errstr); + fatalx("%s", errstr); +} +#endif + +void +ca_engine_init(void) +{ + rsa_engine_init(); +#if defined(SUPPORT_ECDSA) + ecdsa_engine_init(); +#endif +} |