forked from mirrors/kore
Isolate ECDSA keys in keymgr as well.
This commit is contained in:
parent
87a826d89b
commit
f62430d1fa
175
src/domain.c
175
src/domain.c
|
@ -20,7 +20,8 @@
|
|||
#include <openssl/x509.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/evp.h>
|
||||
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/ecdsa.h>
|
||||
#include <poll.h>
|
||||
#endif
|
||||
|
||||
|
@ -46,15 +47,49 @@ static void domain_load_crl(struct kore_domain *);
|
|||
#if !defined(KORE_NO_TLS)
|
||||
static int domain_x509_verify(int, X509_STORE_CTX *);
|
||||
|
||||
static void keymgr_msg_response(struct kore_msg *, const void *);
|
||||
static void keymgr_init(void);
|
||||
static void keymgr_await_data(void);
|
||||
static void keymgr_msg_response(struct kore_msg *, const void *);
|
||||
|
||||
static int keymgr_rsa_init(RSA *);
|
||||
static int keymgr_rsa_finish(RSA *);
|
||||
static int keymgr_rsa_privenc(int, const unsigned char *,
|
||||
unsigned char *, RSA *, int);
|
||||
|
||||
static ECDSA_SIG *keymgr_ecdsa_sign(const unsigned char *, int,
|
||||
const BIGNUM *, const BIGNUM *, EC_KEY *);
|
||||
|
||||
#if !defined(OpenBSD)
|
||||
/*
|
||||
* 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;
|
||||
ECDSA_SIG *(*ecdsa_do_sign)(const unsigned char *,
|
||||
int, const BIGNUM *, const BIGNUM *, EC_KEY *);
|
||||
int (*ecdsa_sign_setup)(EC_KEY *, BN_CTX *, BIGNUM **,
|
||||
BIGNUM **);
|
||||
int (*ecdsa_do_verify)(const unsigned char *, int,
|
||||
const ECDSA_SIG *, EC_KEY *);
|
||||
int flags;
|
||||
char *app_data;
|
||||
};
|
||||
#endif
|
||||
|
||||
static ECDSA_METHOD keymgr_ecdsa = {
|
||||
"kore ECDSA keymgr method",
|
||||
keymgr_ecdsa_sign,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
NULL
|
||||
};
|
||||
|
||||
static RSA_METHOD keymgr_rsa = {
|
||||
"kore RSA keymgr engine",
|
||||
"kore RSA keymgr method",
|
||||
NULL,
|
||||
NULL,
|
||||
keymgr_rsa_privenc,
|
||||
|
@ -167,6 +202,7 @@ kore_domain_sslstart(struct kore_domain *dom)
|
|||
X509 *x509;
|
||||
EVP_PKEY *pkey;
|
||||
STACK_OF(X509_NAME) *certs;
|
||||
EC_KEY *eckey;
|
||||
X509_STORE *store;
|
||||
const SSL_METHOD *method;
|
||||
#if !defined(OPENSSL_NO_EC)
|
||||
|
@ -210,11 +246,22 @@ kore_domain_sslstart(struct kore_domain *dom)
|
|||
if ((pkey = X509_get_pubkey(x509)) == NULL)
|
||||
fatal("certificate has no public key");
|
||||
|
||||
if ((rsa = EVP_PKEY_get1_RSA(pkey)) == NULL)
|
||||
fatal("no RSA public key present");
|
||||
|
||||
RSA_set_app_data(rsa, dom);
|
||||
RSA_set_method(rsa, &keymgr_rsa);
|
||||
switch (EVP_PKEY_id(pkey)) {
|
||||
case EVP_PKEY_RSA:
|
||||
if ((rsa = EVP_PKEY_get1_RSA(pkey)) == NULL)
|
||||
fatal("no RSA public key present");
|
||||
RSA_set_app_data(rsa, dom);
|
||||
RSA_set_method(rsa, &keymgr_rsa);
|
||||
break;
|
||||
case EVP_PKEY_EC:
|
||||
if ((eckey = EVP_PKEY_get1_EC_KEY(pkey)) == NULL)
|
||||
fatal("no EC public key present");
|
||||
ECDSA_set_ex_data(eckey, 0, dom);
|
||||
ECDSA_set_method(eckey, &keymgr_ecdsa);
|
||||
break;
|
||||
default:
|
||||
fatal("unknown public key in certificate");
|
||||
}
|
||||
|
||||
if (!SSL_CTX_use_PrivateKey(dom->ssl_ctx, pkey))
|
||||
fatal("SSL_CTX_use_PrivateKey(): %s", ssl_errno_s);
|
||||
|
@ -228,12 +275,11 @@ kore_domain_sslstart(struct kore_domain *dom)
|
|||
SSL_CTX_set_tmp_dh(dom->ssl_ctx, tls_dhparam);
|
||||
SSL_CTX_set_options(dom->ssl_ctx, SSL_OP_SINGLE_DH_USE);
|
||||
|
||||
#if !defined(OPENSSL_NO_EC)
|
||||
if ((ecdh = EC_KEY_new_by_curve_name(NID_secp384r1)) != NULL) {
|
||||
SSL_CTX_set_tmp_ecdh(dom->ssl_ctx, ecdh);
|
||||
EC_KEY_free(ecdh);
|
||||
}
|
||||
#endif
|
||||
if ((ecdh = EC_KEY_new_by_curve_name(NID_secp384r1)) == NULL)
|
||||
fatal("EC_KEY_new_by_curve_name: %s", ssl_errno_s);
|
||||
|
||||
SSL_CTX_set_tmp_ecdh(dom->ssl_ctx, ecdh);
|
||||
EC_KEY_free(ecdh);
|
||||
|
||||
SSL_CTX_set_options(dom->ssl_ctx, SSL_OP_NO_COMPRESSION);
|
||||
|
||||
|
@ -407,11 +453,8 @@ keymgr_rsa_privenc(int flen, const unsigned char *from, unsigned char *to,
|
|||
size_t len;
|
||||
struct kore_keyreq *req;
|
||||
struct kore_domain *dom;
|
||||
struct pollfd pfd[1];
|
||||
u_int64_t start, cur;
|
||||
|
||||
len = sizeof(*req) + flen;
|
||||
|
||||
if (len > sizeof(keymgr_buf))
|
||||
fatal("keymgr_buf too small");
|
||||
|
||||
|
@ -431,6 +474,82 @@ keymgr_rsa_privenc(int flen, const unsigned char *from, unsigned char *to,
|
|||
memcpy(req->domain, dom->domain, req->domain_len);
|
||||
|
||||
kore_msg_send(KORE_WORKER_KEYMGR, KORE_MSG_KEYMGR_REQ, keymgr_buf, len);
|
||||
keymgr_await_data();
|
||||
|
||||
ret = -1;
|
||||
if (keymgr_response) {
|
||||
if (keymgr_buflen < INT_MAX &&
|
||||
(int)keymgr_buflen == RSA_size(rsa)) {
|
||||
ret = RSA_size(rsa);
|
||||
memcpy(to, keymgr_buf, RSA_size(rsa));
|
||||
}
|
||||
}
|
||||
|
||||
keymgr_buflen = 0;
|
||||
keymgr_response = 0;
|
||||
kore_platform_event_all(worker->msg[1]->fd, worker->msg[1]);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
keymgr_rsa_finish(RSA *rsa)
|
||||
{
|
||||
return (1);
|
||||
}
|
||||
|
||||
static ECDSA_SIG *
|
||||
keymgr_ecdsa_sign(const unsigned char *dgst, int dgst_len,
|
||||
const BIGNUM *in_kinv, const BIGNUM *in_r, EC_KEY *eckey)
|
||||
{
|
||||
size_t len;
|
||||
ECDSA_SIG *sig;
|
||||
const u_int8_t *ptr;
|
||||
struct kore_domain *dom;
|
||||
struct kore_keyreq *req;
|
||||
|
||||
if (in_kinv != NULL || in_r != NULL)
|
||||
return (NULL);
|
||||
|
||||
len = sizeof(*req) + dgst_len;
|
||||
if (len > sizeof(keymgr_buf))
|
||||
fatal("keymgr_buf too small");
|
||||
|
||||
if ((dom = ECDSA_get_ex_data(eckey, 0)) == NULL)
|
||||
fatal("EC_KEY has no domain");
|
||||
|
||||
memset(keymgr_buf, 0, sizeof(keymgr_buf));
|
||||
|
||||
req = (struct kore_keyreq *)keymgr_buf;
|
||||
req->data_len = dgst_len;
|
||||
req->domain_len = strlen(dom->domain);
|
||||
|
||||
memcpy(&req->data[0], dgst, req->data_len);
|
||||
memcpy(req->domain, dom->domain, req->domain_len);
|
||||
|
||||
kore_msg_send(KORE_WORKER_KEYMGR, KORE_MSG_KEYMGR_REQ, keymgr_buf, len);
|
||||
keymgr_await_data();
|
||||
|
||||
if (keymgr_response) {
|
||||
ptr = keymgr_buf;
|
||||
sig = d2i_ECDSA_SIG(NULL, &ptr, keymgr_buflen);
|
||||
} else {
|
||||
sig = NULL;
|
||||
}
|
||||
|
||||
keymgr_buflen = 0;
|
||||
keymgr_response = 0;
|
||||
kore_platform_event_all(worker->msg[1]->fd, worker->msg[1]);
|
||||
|
||||
return (sig);
|
||||
}
|
||||
|
||||
static void
|
||||
keymgr_await_data(void)
|
||||
{
|
||||
int ret;
|
||||
struct pollfd pfd[1];
|
||||
u_int64_t start, cur;
|
||||
|
||||
/*
|
||||
* We need to wait until the keymgr responds to us, so keep doing
|
||||
|
@ -482,22 +601,6 @@ keymgr_rsa_privenc(int flen, const unsigned char *from, unsigned char *to,
|
|||
if (keymgr_response)
|
||||
break;
|
||||
}
|
||||
|
||||
ret = -1;
|
||||
|
||||
if (keymgr_response) {
|
||||
if (keymgr_buflen < INT_MAX &&
|
||||
(int)keymgr_buflen == RSA_size(rsa)) {
|
||||
ret = RSA_size(rsa);
|
||||
memcpy(to, keymgr_buf, RSA_size(rsa));
|
||||
}
|
||||
}
|
||||
|
||||
keymgr_buflen = 0;
|
||||
keymgr_response = 0;
|
||||
kore_platform_event_all(worker->msg[1]->fd, worker->msg[1]);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -512,12 +615,6 @@ keymgr_msg_response(struct kore_msg *msg, const void *data)
|
|||
memcpy(keymgr_buf, data, keymgr_buflen);
|
||||
}
|
||||
|
||||
static int
|
||||
keymgr_rsa_finish(RSA *rsa)
|
||||
{
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
domain_x509_verify(int ok, X509_STORE_CTX *ctx)
|
||||
{
|
||||
|
|
91
src/keymgr.c
91
src/keymgr.c
|
@ -16,7 +16,7 @@
|
|||
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/evp.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -27,7 +27,7 @@
|
|||
|
||||
#if !defined(KORE_NO_TLS)
|
||||
struct key {
|
||||
RSA *rsa;
|
||||
EVP_PKEY *pkey;
|
||||
struct kore_domain *dom;
|
||||
TAILQ_ENTRY(key) list;
|
||||
};
|
||||
|
@ -39,6 +39,11 @@ static int initialized = 0;
|
|||
static void keymgr_load_privatekey(struct kore_domain *);
|
||||
static void keymgr_msg_recv(struct kore_msg *, const void *);
|
||||
|
||||
static void keymgr_rsa_encrypt(struct kore_msg *, const void *,
|
||||
struct key *);
|
||||
static void keymgr_ecdsa_sign(struct kore_msg *, const void *,
|
||||
struct key *);
|
||||
|
||||
void
|
||||
kore_keymgr_run(void)
|
||||
{
|
||||
|
@ -101,7 +106,7 @@ kore_keymgr_cleanup(void)
|
|||
next = TAILQ_NEXT(key, list);
|
||||
TAILQ_REMOVE(&keys, key, list);
|
||||
|
||||
RSA_free(key->rsa);
|
||||
EVP_PKEY_free(key->pkey);
|
||||
kore_mem_free(key);
|
||||
}
|
||||
}
|
||||
|
@ -121,8 +126,8 @@ keymgr_load_privatekey(struct kore_domain *dom)
|
|||
key = kore_malloc(sizeof(*key));
|
||||
key->dom = dom;
|
||||
|
||||
if ((key->rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL)) == NULL)
|
||||
fatal("PEM_read_RSAPrivateKey: %s", ssl_errno_s);
|
||||
if ((key->pkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL)) == NULL)
|
||||
fatal("PEM_read_PrivateKey: %s", ssl_errno_s);
|
||||
|
||||
(void)fclose(fp);
|
||||
kore_mem_free(dom->certkey);
|
||||
|
@ -134,37 +139,81 @@ keymgr_load_privatekey(struct kore_domain *dom)
|
|||
static void
|
||||
keymgr_msg_recv(struct kore_msg *msg, const void *data)
|
||||
{
|
||||
int ret;
|
||||
const struct kore_keyreq *req;
|
||||
struct key *key;
|
||||
size_t keylen;
|
||||
u_int8_t buf[1024];
|
||||
|
||||
if (msg->length < sizeof(*req))
|
||||
return;
|
||||
|
||||
key = NULL;
|
||||
req = (const struct kore_keyreq *)data;
|
||||
|
||||
if (msg->length != (sizeof(*req) + req->data_len))
|
||||
return;
|
||||
|
||||
key = NULL;
|
||||
TAILQ_FOREACH(key, &keys, list) {
|
||||
if (strncmp(key->dom->domain, req->domain, req->domain_len))
|
||||
continue;
|
||||
if (!strncmp(key->dom->domain, req->domain, req->domain_len))
|
||||
break;
|
||||
}
|
||||
|
||||
keylen = RSA_size(key->rsa);
|
||||
if (req->data_len > keylen || keylen > sizeof(buf))
|
||||
return;
|
||||
if (key == NULL)
|
||||
return;
|
||||
|
||||
ret = RSA_private_encrypt(req->data_len, req->data,
|
||||
buf, key->rsa, req->padding);
|
||||
if (ret != RSA_size(key->rsa))
|
||||
return;
|
||||
|
||||
kore_msg_send(msg->src, KORE_MSG_KEYMGR_RESP, buf, ret);
|
||||
switch (EVP_PKEY_id(key->pkey)) {
|
||||
case EVP_PKEY_RSA:
|
||||
keymgr_rsa_encrypt(msg, data, key);
|
||||
break;
|
||||
case EVP_PKEY_EC:
|
||||
keymgr_ecdsa_sign(msg, data, key);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
keymgr_rsa_encrypt(struct kore_msg *msg, const void *data, struct key *key)
|
||||
{
|
||||
int ret;
|
||||
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 (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))
|
||||
return;
|
||||
|
||||
kore_msg_send(msg->src, KORE_MSG_KEYMGR_RESP, buf, ret);
|
||||
}
|
||||
|
||||
static void
|
||||
keymgr_ecdsa_sign(struct kore_msg *msg, const void *data, struct key *key)
|
||||
{
|
||||
size_t len;
|
||||
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 (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)
|
||||
return;
|
||||
|
||||
if (siglen > sizeof(sig))
|
||||
return;
|
||||
|
||||
kore_msg_send(msg->src, KORE_MSG_KEYMGR_RESP, sig, siglen);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue