commit 95daf3a62bef0b9c84101eecbb464fd474566f45
parent b73343aea4de14c17f852300c29e474c88b256f5
Author: Joris Vink <joris@coders.se>
Date: Mon, 22 May 2017 14:31:38 +0200
Add support for openssl 1.1.0 release line.
Eventually I will phase out 1.0.2 down the line to get rid of the
nightmare that is the 2 different APIs.
This commit adds full support for building kore with 1.1.0e while
retaining the privsep keymanager support.
based on excellent work done by @hiwk.
Diffstat:
src/domain.c | | | 108 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ |
src/keymgr.c | | | 25 | ++++++++++++++++++------- |
2 files changed, 119 insertions(+), 14 deletions(-)
diff --git a/src/domain.c b/src/domain.c
@@ -14,6 +14,11 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+/*
+ * XXX - Lots of OPENSSL ifdefs here for 1.0.2 and 1.1.0 release lines.
+ * The idea is to only support 1.1.0 down the line and remove the 1.0.2 goo.
+ */
+
#include <sys/param.h>
#if !defined(KORE_NO_TLS)
@@ -63,12 +68,14 @@ static int keymgr_rsa_privenc(int, const unsigned char *,
static ECDSA_SIG *keymgr_ecdsa_sign(const unsigned char *, int,
const BIGNUM *, const BIGNUM *, EC_KEY *);
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+static RSA_METHOD *keymgr_rsa_meth = NULL;
+static EC_KEY_METHOD *keymgr_ec_meth = NULL;
+#else
#if !defined(LIBRESSL_VERSION_TEXT)
/*
* Run own ecdsa_method data structure as OpenSSL has this in ecs_locl.h
* and does not export this on systems.
- *
- * XXX - OpenSSL is merging ECDSA functionality into EC in 1.1.0.
*/
struct ecdsa_method {
const char *name;
@@ -109,12 +116,32 @@ static RSA_METHOD keymgr_rsa = {
NULL
};
-#endif
+#endif /* OPENSSL_VERSION_NUMBER */
+#endif /* KORE_NO_TLS */
void
kore_domain_init(void)
{
TAILQ_INIT(&domains);
+
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ if (keymgr_rsa_meth == NULL) {
+ if ((keymgr_rsa_meth = RSA_meth_new("kore RSA keymgr method",
+ RSA_METHOD_FLAG_NO_CHECK)) == NULL)
+ fatal("failed to allocate RSA method");
+ }
+
+ RSA_meth_set_init(keymgr_rsa_meth, keymgr_rsa_init);
+ RSA_meth_set_finish(keymgr_rsa_meth, keymgr_rsa_finish);
+ RSA_meth_set_priv_enc(keymgr_rsa_meth, keymgr_rsa_privenc);
+
+ if (keymgr_ec_meth == NULL) {
+ if ((keymgr_ec_meth = EC_KEY_METHOD_new(NULL)) == NULL)
+ fatal("failed to allocate EC KEY method");
+ }
+
+ EC_KEY_METHOD_set_sign(keymgr_ec_meth, NULL, NULL, keymgr_ecdsa_sign);
+#endif
}
void
@@ -126,6 +153,18 @@ kore_domain_cleanup(void)
TAILQ_REMOVE(&domains, dom, list);
kore_domain_free(dom);
}
+
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ if (keymgr_rsa_meth != NULL) {
+ RSA_meth_free(keymgr_rsa_meth);
+ keymgr_rsa_meth = NULL;
+ }
+
+ if (keymgr_ec_meth != NULL) {
+ EC_KEY_METHOD_free(keymgr_ec_meth);
+ keymgr_ec_meth = NULL;
+ }
+#endif
}
int
@@ -215,6 +254,10 @@ kore_domain_tlsinit(struct kore_domain *dom)
kore_debug("kore_domain_sslstart(%s)", dom->domain);
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ if ((method = TLS_method()) == NULL)
+ fatal("TLS_method(): %s", ssl_errno_s);
+#else
switch (tls_version) {
case KORE_TLS_VERSION_1_2:
method = TLSv1_2_server_method();
@@ -229,16 +272,40 @@ kore_domain_tlsinit(struct kore_domain *dom)
fatal("unknown tls_version: %d", tls_version);
return;
}
+#endif
+
+ if ((dom->ssl_ctx = SSL_CTX_new(method)) == NULL)
+ fatal("SSL_ctx_new(): %s", ssl_errno_s);
+
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ if (!SSL_CTX_set_min_proto_version(dom->ssl_ctx, TLS1_VERSION))
+ fatal("SSL_CTX_set_min_proto_version: %s", ssl_errno_s);
+ if (!SSL_CTX_set_max_proto_version(dom->ssl_ctx, TLS1_2_VERSION))
+ fatal("SSL_CTX_set_max_proto_version: %s", ssl_errno_s);
- dom->ssl_ctx = SSL_CTX_new(method);
- if (dom->ssl_ctx == NULL)
- fatal("kore_domain_sslstart(): SSL_ctx_new(): %s", ssl_errno_s);
+ switch (tls_version) {
+ case KORE_TLS_VERSION_1_2:
+ if (!SSL_CTX_set_min_proto_version(dom->ssl_ctx,
+ TLS1_2_VERSION))
+ fatal("SSL_CTX_set_min_proto_version: %s", ssl_errno_s);
+ break;
+ case KORE_TLS_VERSION_1_0:
+ if (!SSL_CTX_set_max_proto_version(dom->ssl_ctx, TLS1_VERSION))
+ fatal("SSL_CTX_set_min_proto_version: %s", ssl_errno_s);
+ break;
+ case KORE_TLS_VERSION_BOTH:
+ break;
+ default:
+ fatal("unknown tls_version: %d", tls_version);
+ return;
+ }
+#endif
if (!SSL_CTX_use_certificate_chain_file(dom->ssl_ctx, dom->certfile)) {
fatal("SSL_CTX_use_certificate_chain_file(%s): %s",
dom->certfile, ssl_errno_s);
}
- if ((in = BIO_new(BIO_s_file_internal())) == NULL)
+ if ((in = BIO_new(BIO_s_file())) == NULL)
fatal("BIO_new: %s", ssl_errno_s);
if (BIO_read_filename(in, dom->certfile) <= 0)
fatal("BIO_read_filename: %s", ssl_errno_s);
@@ -255,13 +322,22 @@ kore_domain_tlsinit(struct kore_domain *dom)
if ((rsa = EVP_PKEY_get1_RSA(pkey)) == NULL)
fatal("no RSA public key present");
RSA_set_app_data(rsa, dom);
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ RSA_set_method(rsa, keymgr_rsa_meth);
+#else
RSA_set_method(rsa, &keymgr_rsa);
+#endif
break;
case EVP_PKEY_EC:
if ((eckey = EVP_PKEY_get1_EC_KEY(pkey)) == NULL)
fatal("no EC public key present");
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ EC_KEY_set_ex_data(eckey, 0, dom);
+ EC_KEY_set_method(eckey, keymgr_ec_meth);
+#else
ECDSA_set_ex_data(eckey, 0, dom);
ECDSA_set_method(eckey, &keymgr_ecdsa);
+#endif
break;
default:
fatal("unknown public key in certificate");
@@ -319,8 +395,10 @@ kore_domain_tlsinit(struct kore_domain *dom)
* from its OpenSSL in base so we don't need to care about it.
*/
#if !defined(LIBRESSL_VERSION_TEXT)
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
dom->ssl_ctx->freelist_max_len = 0;
#endif
+#endif
SSL_CTX_set_mode(dom->ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
if (tls_version == KORE_TLS_VERSION_BOTH) {
@@ -436,16 +514,27 @@ keymgr_init(void)
if ((meth = RSA_get_default_method()) == NULL)
fatal("failed to obtain RSA method");
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ RSA_meth_set_pub_enc(keymgr_rsa_meth, RSA_meth_get_pub_enc(meth));
+ RSA_meth_set_pub_dec(keymgr_rsa_meth, RSA_meth_get_pub_dec(meth));
+ RSA_meth_set_bn_mod_exp(keymgr_rsa_meth, RSA_meth_get_bn_mod_exp(meth));
+#else
keymgr_rsa.rsa_pub_enc = meth->rsa_pub_enc;
keymgr_rsa.rsa_pub_dec = meth->rsa_pub_dec;
keymgr_rsa.bn_mod_exp = meth->bn_mod_exp;
+#endif
}
static int
keymgr_rsa_init(RSA *rsa)
{
if (rsa != NULL) {
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ RSA_set_flags(rsa, RSA_flags(rsa) |
+ RSA_FLAG_EXT_PKEY | RSA_METHOD_FLAG_NO_CHECK);
+#else
rsa->flags |= RSA_FLAG_EXT_PKEY | RSA_METHOD_FLAG_NO_CHECK;
+#endif
return (1);
}
@@ -522,8 +611,13 @@ keymgr_ecdsa_sign(const unsigned char *dgst, int dgst_len,
if (len > sizeof(keymgr_buf))
fatal("keymgr_buf too small");
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ if ((dom = EC_KEY_get_ex_data(eckey, 0)) == NULL)
+ fatal("EC_KEY has no domain");
+#else
if ((dom = ECDSA_get_ex_data(eckey, 0)) == NULL)
fatal("EC_KEY has no domain");
+#endif
memset(keymgr_buf, 0, sizeof(keymgr_buf));
diff --git a/src/keymgr.c b/src/keymgr.c
@@ -318,19 +318,25 @@ static void
keymgr_rsa_encrypt(struct kore_msg *msg, const void *data, struct key *key)
{
int ret;
+ RSA *rsa;
const struct kore_keyreq *req;
size_t keylen;
u_int8_t buf[1024];
req = (const struct kore_keyreq *)data;
- keylen = RSA_size(key->pkey->pkey.rsa);
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ rsa = EVP_PKEY_get0_RSA(key->pkey);
+#else
+ rsa = key->pkey->pkey.rsa;
+#endif
+ keylen = RSA_size(rsa);
if (req->data_len > keylen || keylen > sizeof(buf))
return;
ret = RSA_private_encrypt(req->data_len, req->data,
- buf, key->pkey->pkey.rsa, req->padding);
- if (ret != RSA_size(key->pkey->pkey.rsa))
+ buf, rsa, req->padding);
+ if (ret != RSA_size(rsa))
return;
kore_msg_send(msg->src, KORE_MSG_KEYMGR_RESP, buf, ret);
@@ -340,18 +346,23 @@ static void
keymgr_ecdsa_sign(struct kore_msg *msg, const void *data, struct key *key)
{
size_t len;
+ EC_KEY *ec;
const struct kore_keyreq *req;
unsigned int siglen;
u_int8_t sig[1024];
req = (const struct kore_keyreq *)data;
-
- len = ECDSA_size(key->pkey->pkey.ec);
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ ec = EVP_PKEY_get0_EC_KEY(key->pkey);
+#else
+ ec = key->pkey->pkey.ec;
+#endif
+ len = ECDSA_size(ec);
if (req->data_len > len || len > sizeof(sig))
return;
- if (ECDSA_sign(key->pkey->save_type, req->data, req->data_len,
- sig, &siglen, key->pkey->pkey.ec) == 0)
+ if (ECDSA_sign(EVP_PKEY_NONE, req->data, req->data_len,
+ sig, &siglen, ec) == 0)
return;
if (siglen > sizeof(sig))