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