On 2023/05/25 19:23:48 +0200, Omar Polo <o...@omarpolo.com> 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;
        }
 

Reply via email to