On 2023/05/25 19:23:48 +0200, Omar Polo <[email protected]> wrote:
> As far as I (and grep) can see, smtpd and the part it needs in libtls
> are the only user of ECDSA_METHOD in tree.
>
> What I've understood talking with tb (and apologizes if I'm making
> mistakes) is that ECDSA_METHOD was replaced with EC_KEY_METHOD. "We"
> inherited the former, it got used in smtpd, and then added the latter
> for openssh. smtpd and libtls were never updated to these new shiny
> APIs.
>
> Diff below is 99% gilles' work on OpenSMTPD-portable. I only had to
> tweak EC_KEY_METHOD_get_compute_key() since the compute key function
> has a different signature in LibreSSL than OpenSSL, and some minor
> style nits.
friendly ping
> While I've tested it (on localhost and between vms), and I'm also
> running it on linux and freebsd with OpenSSL 3.1 and 1.1 respectively
> via OpenSMTPD-portable, additional testing on busier mx is greatly
> appreciated. I don't expect regressions however.
I'm also running with this on my backup mx. I've stopped the main mx
a few times to have all the traffic going through the backup one.
Nothing to report :)
more testing is always apreciated.
> To test:
>
> - apply the diff
> - rebuild and reinstall libtls
> - rebuild, reinstall and restart smtpd
forgot to point out one thing, apologies. You need to have a
certificate with an ec key. For acme-client it means having something
like the following:
domain m.example.com {
# note the `ecdsa' on the following line.
domain key "/etc/ssl/private/m.example.com.key" ecdsa
domain full chain certificate "..."
sign with foobar
}
note also that acme-client won't re-generate the private key, so you
may have to delete it prior requesting a new certificate since it
defaults to rsa.
> It doesn't change the libtls ABI (tls_signer_ecdsa_method is internal)
> and the parts it touches are only used by smtpd AFAIK, so no need to
> rebuild anything else.
>
>
> Thanks!
diff 2b0e5a68588bd522338c80975b42b1e5c355be29
3ea882bd0e5cf2ef7f577629af6affb53aef7775
commit - 2b0e5a68588bd522338c80975b42b1e5c355be29
commit + 3ea882bd0e5cf2ef7f577629af6affb53aef7775
blob - 989339dc033f3c231659a9a37946c453d03509da
blob + f6ba5760737d40ec5250a21c0bdcc7446073111f
--- lib/libtls/tls.c
+++ lib/libtls/tls.c
@@ -389,7 +389,7 @@ tls_keypair_setup_pkey(struct tls *ctx, struct tls_key
tls_keypair_setup_pkey(struct tls *ctx, struct tls_keypair *keypair, EVP_PKEY
*pkey)
{
RSA_METHOD *rsa_method;
- ECDSA_METHOD *ecdsa_method;
+ EC_KEY_METHOD *ecdsa_method;
RSA *rsa = NULL;
EC_KEY *eckey = NULL;
int ret = -1;
@@ -427,15 +427,15 @@ tls_keypair_setup_pkey(struct tls *ctx, struct tls_key
break;
case EVP_PKEY_EC:
if ((eckey = EVP_PKEY_get1_EC_KEY(pkey)) == NULL ||
- ECDSA_set_ex_data(eckey, 0, keypair->pubkey_hash) == 0) {
+ EC_KEY_set_ex_data(eckey, 0, keypair->pubkey_hash) == 0) {
tls_set_errorx(ctx, "EC key setup failure");
goto err;
}
if (ctx->config->sign_cb != NULL) {
ecdsa_method = tls_signer_ecdsa_method();
if (ecdsa_method == NULL ||
- ECDSA_set_ex_data(eckey, 1, ctx->config) == 0 ||
- ECDSA_set_method(eckey, ecdsa_method) == 0) {
+ EC_KEY_set_ex_data(eckey, 1, ctx->config) == 0 ||
+ EC_KEY_set_method(eckey, ecdsa_method) == 0) {
tls_set_errorx(ctx, "failed to setup EC key");
goto err;
}
blob - f4c23f64e67f2f45056467dbdffe84960cdc4e2c
blob + f53b6c800941a746425ba01ffe26daf4c236bc37
--- lib/libtls/tls_internal.h
+++ lib/libtls/tls_internal.h
@@ -298,7 +298,7 @@ ECDSA_METHOD *tls_signer_ecdsa_method(void);
int tls_password_cb(char *_buf, int _size, int _rwflag, void *_u);
RSA_METHOD *tls_signer_rsa_method(void);
-ECDSA_METHOD *tls_signer_ecdsa_method(void);
+EC_KEY_METHOD *tls_signer_ecdsa_method(void);
#define TLS_PADDING_NONE 0
#define TLS_PADDING_RSA_PKCS1 1
blob - f6005d3e07ac6423098c9d35f1f03993cd4dfd88
blob + 93777aa3253fdacbc28abc852f8e660fbd882b01
--- lib/libtls/tls_signer.c
+++ lib/libtls/tls_signer.c
@@ -419,26 +419,21 @@ ECDSA_METHOD *
return (NULL);
}
-ECDSA_METHOD *
+EC_KEY_METHOD *
tls_signer_ecdsa_method(void)
{
- static ECDSA_METHOD *ecdsa_method = NULL;
+ static EC_KEY_METHOD *ecdsa_method = NULL;
pthread_mutex_lock(&signer_method_lock);
if (ecdsa_method != NULL)
goto out;
- ecdsa_method = calloc(1, sizeof(*ecdsa_method));
+ ecdsa_method = EC_KEY_METHOD_new(NULL);
if (ecdsa_method == NULL)
goto out;
- ecdsa_method->ecdsa_do_sign = tls_ecdsa_do_sign;
- ecdsa_method->name = strdup("libtls ECDSA method");
- if (ecdsa_method->name == NULL) {
- free(ecdsa_method);
- ecdsa_method = NULL;
- }
+ EC_KEY_METHOD_set_sign(ecdsa_method, NULL, NULL, tls_ecdsa_do_sign);
out:
pthread_mutex_unlock(&signer_method_lock);
blob - c0c918601e741019515da6c83a6874fb9f552a1a
blob + f5d81174b597f8368b45719833d92772e49e78db
--- usr.sbin/smtpd/ca.c
+++ usr.sbin/smtpd/ca.c
@@ -47,10 +47,17 @@ static int rsae_keygen(RSA *, int, BIGNUM *, BN_GENCB
static int rsae_init(RSA *);
static int rsae_finish(RSA *);
static int rsae_keygen(RSA *, int, BIGNUM *, BN_GENCB *);
+static int ecdsae_keygen(EC_KEY *);
+static int ecdsae_compute_key(void *, size_t, const EC_POINT *, EC_KEY *,
+ void *(*)(const void *, size_t, void *, size_t *));
+static int ecdsae_sign(int, const unsigned char *, int, unsigned char *,
+ unsigned int *, const BIGNUM *, const BIGNUM *, EC_KEY *);
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_verify(int, const unsigned char *, int, const unsigned char
*,
+ int, EC_KEY *);
static int ecdsae_do_verify(const unsigned char *, int, const ECDSA_SIG *,
EC_KEY *);
@@ -492,30 +499,10 @@ const ECDSA_METHOD *ecdsa_default = NULL;
* ECDSA privsep engine (called from unprivileged processes)
*/
-const ECDSA_METHOD *ecdsa_default = NULL;
+const EC_KEY_METHOD *ecdsa_default = NULL;
-static ECDSA_METHOD *ecdsae_method = NULL;
+static EC_KEY_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)
@@ -531,7 +518,7 @@ ecdsae_send_enc_imsg(const unsigned char *dgst, int dg
uint64_t id;
ECDSA_SIG *sig = NULL;
- if ((hash = ECDSA_get_ex_data(eckey, 0)) == NULL)
+ if ((hash = EC_KEY_get_ex_data(eckey, 0)) == NULL)
return (0);
/*
@@ -590,30 +577,86 @@ ECDSA_SIG *
return (sig);
}
-ECDSA_SIG *
-ecdsae_do_sign(const unsigned char *dgst, int dgst_len,
- const BIGNUM *inv, const BIGNUM *rp, EC_KEY *eckey)
+static int
+ecdsae_keygen(EC_KEY *eckey)
{
+ int (*keygen)(EC_KEY *);
+
log_debug("debug: %s: %s", proc_name(smtpd_process), __func__);
- if (ECDSA_get_ex_data(eckey, 0) != NULL)
+ EC_KEY_METHOD_get_keygen(ecdsa_default, &keygen);
+ return (keygen(eckey));
+}
+
+static int
+ecdsae_compute_key(void *out, size_t outlen, const EC_POINT *pub_key,
+ EC_KEY *ecdh, void *(*kdf)(const void *, size_t, void *, size_t *))
+{
+ int (*ckey)(void *, size_t, const EC_POINT *, EC_KEY *,
+ void *(*)(const void *, size_t, void *, size_t *));
+
+ log_debug("debug: %s: %s", proc_name(smtpd_process), __func__);
+ EC_KEY_METHOD_get_compute_key(ecdsa_default, &ckey);
+ return (ckey(out, outlen, pub_key, ecdh, kdf));
+}
+
+static int
+ecdsae_sign(int type, const unsigned char *dgst, int dlen, unsigned char *sig,
+ unsigned int *siglen, const BIGNUM *kinv, const BIGNUM *r, EC_KEY *eckey)
+{
+ int (*sign)(int, const unsigned char *, int, unsigned char *,
+ unsigned int *, const BIGNUM *, const BIGNUM *, EC_KEY *);
+
+ log_debug("debug: %s: %s", proc_name(smtpd_process), __func__);
+ EC_KEY_METHOD_get_sign(ecdsa_default, &sign, NULL, NULL);
+ return (sign(type, dgst, dlen, sig, siglen, kinv, r, eckey));
+}
+
+static ECDSA_SIG *
+ecdsae_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
+ const BIGNUM *rp, EC_KEY *eckey)
+{
+ ECDSA_SIG *(*psign_sig)(const unsigned char *, int, const BIGNUM *,
+ const BIGNUM *, EC_KEY *);
+
+ log_debug("debug: %s: %s", proc_name(smtpd_process), __func__);
+ if (EC_KEY_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));
+ EC_KEY_METHOD_get_sign(ecdsa_default, NULL, NULL, &psign_sig);
+ return (psign_sig(dgst, dgst_len, inv, rp, eckey));
}
-int
-ecdsae_sign_setup(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv,
- BIGNUM **r)
+static int
+ecdsae_sign_setup(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv, BIGNUM **r)
{
+ int (*psign_setup)(EC_KEY *, BN_CTX *, BIGNUM **, BIGNUM **);
+
log_debug("debug: %s: %s", proc_name(smtpd_process), __func__);
- return (ecdsa_default->ecdsa_sign_setup(eckey, ctx, kinv, r));
+ EC_KEY_METHOD_get_sign(ecdsa_default, NULL, &psign_setup, NULL);
+ return (psign_setup(eckey, ctx, kinv, r));
}
-int
+static int
+ecdsae_verify(int type, const unsigned char *dgst, int dgst_len,
+ const unsigned char *sigbuf, int sig_len, EC_KEY *eckey)
+{
+ int (*verify)(int, const unsigned char *, int, const unsigned char *,
+ int, EC_KEY *);
+
+ log_debug("debug: %s: %s", proc_name(smtpd_process), __func__);
+ EC_KEY_METHOD_get_verify(ecdsa_default, &verify, NULL);
+ return (verify(type, dgst, dgst_len, sigbuf, sig_len, eckey));
+}
+
+static int
ecdsae_do_verify(const unsigned char *dgst, int dgst_len,
const ECDSA_SIG *sig, EC_KEY *eckey)
{
+ int (*pverify_sig)(const unsigned char *, int, const ECDSA_SIG *,
+ EC_KEY *);
+
log_debug("debug: %s: %s", proc_name(smtpd_process), __func__);
- return (ecdsa_default->ecdsa_do_verify(dgst, dgst_len, sig, eckey));
+ EC_KEY_METHOD_get_verify(ecdsa_default, NULL, &pverify_sig);
+ return (pverify_sig(dgst, dgst_len, sig, eckey));
}
@@ -694,30 +737,33 @@ 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";
+ if ((ecdsae_method = EC_KEY_METHOD_new(NULL)) == NULL) {
+ errstr = "EC_KEY_METHOD_new";
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;
+ EC_KEY_METHOD_set_keygen(ecdsae_method, ecdsae_keygen);
+ EC_KEY_METHOD_set_compute_key(ecdsae_method, ecdsae_compute_key);
+ EC_KEY_METHOD_set_sign(ecdsae_method, ecdsae_sign, ecdsae_sign_setup,
+ ecdsae_do_sign);
+ EC_KEY_METHOD_set_verify(ecdsae_method, ecdsae_verify,
+ ecdsae_do_verify);
- if ((e = ENGINE_get_default_ECDSA()) == NULL) {
+ if ((e = ENGINE_get_default_EC()) == NULL) {
if ((e = ENGINE_new()) == NULL) {
errstr = "ENGINE_new";
goto fail;
}
- if (!ENGINE_set_name(e, ecdsae_method->name)) {
+ if (!ENGINE_set_name(e, "ECDSA privsep engine")) {
errstr = "ENGINE_set_name";
goto fail;
}
- if ((ecdsa_default = ECDSA_get_default_method()) == NULL) {
- errstr = "ECDSA_get_default_method";
+ if ((ecdsa_default = EC_KEY_get_default_method()) == NULL) {
+ errstr = "EC_KEY_get_default_method";
goto fail;
}
- } else if ((ecdsa_default = ENGINE_get_ECDSA(e)) == NULL) {
- errstr = "ENGINE_get_ECDSA";
+ } else if ((ecdsa_default = ENGINE_get_EC(e)) == NULL) {
+ errstr = "ENGINE_get_EC";
goto fail;
}
@@ -726,12 +772,12 @@ ecdsa_engine_init(void)
log_debug("debug: %s: using %s", __func__, name);
- if (!ENGINE_set_ECDSA(e, ecdsae_method)) {
- errstr = "ENGINE_set_ECDSA";
+ if (!ENGINE_set_EC(e, ecdsae_method)) {
+ errstr = "ENGINE_set_EC";
goto fail;
}
- if (!ENGINE_set_default_ECDSA(e)) {
- errstr = "ENGINE_set_default_ECDSA";
+ if (!ENGINE_set_default_EC(e)) {
+ errstr = "ENGINE_set_default_EC";
goto fail;
}