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; }