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.

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.

To test:

 - apply the diff
 - rebuild and reinstall libtls
 - rebuild, reinstall and restart smtpd

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 a6995f7d4e4b475f514b46014b476ba2fb99e6ca 
15eb8637ab039139400e655284e2e2d8ca898a03
commit - a6995f7d4e4b475f514b46014b476ba2fb99e6ca
commit + 15eb8637ab039139400e655284e2e2d8ca898a03
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