diff options
-rw-r--r-- | usr.sbin/smtpd/ca.c | 188 | ||||
-rw-r--r-- | usr.sbin/smtpd/ssl.c | 5 |
2 files changed, 180 insertions, 13 deletions
diff --git a/usr.sbin/smtpd/ca.c b/usr.sbin/smtpd/ca.c index a27db87a..b36033b4 100644 --- a/usr.sbin/smtpd/ca.c +++ b/usr.sbin/smtpd/ca.c @@ -65,13 +65,11 @@ static int rsae_init(RSA *); static int rsae_finish(RSA *); static int rsae_keygen(RSA *, int, BIGNUM *, BN_GENCB *); -#if defined(SUPPORT_ECDSA) 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_do_verify(const unsigned char *, int, const ECDSA_SIG *, EC_KEY *); -#endif static uint64_t reqid = 0; @@ -230,17 +228,13 @@ void ca_imsg(struct mproc *p, struct imsg *imsg) { RSA *rsa = NULL; -#if defined(SUPPORT_ECDSA) EC_KEY *ecdsa = NULL; -#endif const void *from = NULL; unsigned char *to = NULL; struct msg m; const char *pkiname; size_t flen, tlen, padding; -#if defined(SUPPORT_ECDSA) int buf_len; -#endif struct pki *pki; int ret = 0; uint64_t id; @@ -313,7 +307,6 @@ ca_imsg(struct mproc *p, struct imsg *imsg) RSA_free(rsa); return; -#if defined(SUPPORT_ECDSA) case IMSG_CA_ECDSA_SIGN: m_msg(&m, imsg); m_get_id(&m, &id); @@ -329,6 +322,7 @@ ca_imsg(struct mproc *p, struct imsg *imsg) buf_len = ECDSA_size(ecdsa); if ((to = calloc(1, buf_len)) == NULL) fatalx("ca_imsg: calloc"); + ret = ECDSA_sign(0, from, flen, to, &buf_len, ecdsa); m_create(p, imsg->hdr.type, 0, 0, -1); m_add_id(p, id); @@ -339,7 +333,6 @@ ca_imsg(struct mproc *p, struct imsg *imsg) free(to); EC_KEY_free(ecdsa); return; -#endif } errx(1, "ca_imsg: unexpected %s imsg", imsg_to_str(imsg->hdr.type)); } @@ -510,11 +503,11 @@ rsae_keygen(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb) } -#if defined(SUPPORT_ECDSA) /* * ECDSA privsep engine (called from unprivileged processes) */ +#if defined(SUPPORT_ECDSA) const ECDSA_METHOD *ecdsa_default = NULL; static ECDSA_METHOD *ecdsae_method = NULL; @@ -538,6 +531,11 @@ ECDSA_METHOD_new_temporary(const char *name, int flags) ecdsa->flags = flags; return ecdsa; } +#else +const EC_KEY_METHOD *ecdsa_default = NULL; + +static EC_KEY_METHOD *ecdsae_method = NULL; +#endif static ECDSA_SIG * ecdsae_send_enc_imsg(const unsigned char *dgst, int dgst_len, @@ -554,8 +552,13 @@ ecdsae_send_enc_imsg(const unsigned char *dgst, int dgst_len, uint64_t id; ECDSA_SIG *sig = NULL; +#if defined(SUPPORT_ECDSA) if ((pkiname = ECDSA_get_ex_data(eckey, 0)) == NULL) return (0); +#else + if ((pkiname = EC_KEY_get_ex_data(eckey, 0)) == NULL) + return (0); +#endif /* * Send a synchronous imsg because we cannot defer the ECDSA @@ -613,6 +616,7 @@ ecdsae_send_enc_imsg(const unsigned char *dgst, int dgst_len, return (sig); } +#if defined(SUPPORT_ECDSA) ECDSA_SIG * ecdsae_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv, const BIGNUM *rp, EC_KEY *eckey) @@ -621,6 +625,7 @@ ecdsae_do_sign(const unsigned char *dgst, int dgst_len, if (ECDSA_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)); + } int @@ -638,6 +643,114 @@ ecdsae_do_verify(const unsigned char *dgst, int dgst_len, log_debug("debug: %s: %s", proc_name(smtpd_process), __func__); return (ecdsa_default->ecdsa_do_verify(dgst, dgst_len, sig, eckey)); } +#else +int +ecdsae_keygen(EC_KEY *eckey) +{ + int (*keygen)(EC_KEY *key); + EC_KEY_METHOD_get_keygen(ecdsa_default, + &keygen); + return keygen(eckey); +} + +int +ecdsae_compute_key(unsigned char **psec, size_t *pseclen, + const EC_POINT *pub_key, const EC_KEY *ecdh) +{ + int (*ckey)(unsigned char **psec, + size_t *pseclen, + const EC_POINT *pub_key, + const EC_KEY *ecdh); + EC_KEY_METHOD_get_compute_key(ecdsa_default, + &ckey); + return ckey(psec, pseclen, pub_key, ecdh); +} + +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 type, const unsigned char *dgst, + int dlen, unsigned char *sig, + unsigned int *siglen, + const BIGNUM *kinv, const BIGNUM *r, + EC_KEY *eckey); + + 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)); +} + + +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 *dgst, + int dgst_len, + const BIGNUM *in_kinv, + const BIGNUM *in_r, + EC_KEY *eckey); + + 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)); + 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) +{ + int (*psign_setup)(EC_KEY *eckey, BN_CTX *ctx_in, + BIGNUM **kinvp, BIGNUM **rp); + + log_debug("debug: %s: %s", proc_name(smtpd_process), __func__); + EC_KEY_METHOD_get_sign(ecdsa_default, + NULL, + &psign_setup, + NULL); + return (psign_setup(eckey, ctx, kinv, r)); +} + +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 type, const unsigned + char *dgst, int dgst_len, + const unsigned char *sigbuf, + int sig_len, EC_KEY *eckey); + + 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)); +} + +int +ecdsae_do_verify(const unsigned char *dgst, int dgst_len, + const ECDSA_SIG *sig, EC_KEY *eckey) +{ + int (*pverify_sig)(const unsigned char *dgst, + int dgst_len, + const ECDSA_SIG *sig, + EC_KEY *eckey); + + log_debug("debug: %s: %s", proc_name(smtpd_process), __func__); + EC_KEY_METHOD_get_verify(ecdsa_default, + NULL, + &pverify_sig); + return (pverify_sig(dgst, dgst_len, sig, eckey)); +} #endif static void @@ -765,13 +878,66 @@ ecdsa_engine_init(void) ssl_error(errstr); fatalx("%s", errstr); } +#else +static void +ecdsa_engine_init(void) +{ + ENGINE *e; + const char *errstr, *name; + + if ((ecdsae_method = EC_KEY_METHOD_new(NULL)) == NULL) { + errstr = "EC_KEY_new"; + goto fail; + } + + 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_EC()) == NULL) { + if ((e = ENGINE_new()) == NULL) { + errstr = "ENGINE_new"; + goto fail; + } + if (!ENGINE_set_name(e, "ECDSA privsep engine")) { + errstr = "ENGINE_set_name"; + goto fail; + } + if ((ecdsa_default = EC_KEY_get_default_method()) == NULL) { + errstr = "EC_KEY_get_default_method"; + goto fail; + } + } else if ((ecdsa_default = ENGINE_get_EC(e)) == NULL) { + errstr = "ENGINE_get_EC"; + goto fail; + } + + if ((name = ENGINE_get_name(e)) == NULL) + name = "unknown ECDSA engine"; + + log_debug("debug: %s: using %s", __func__, name); + + if (!ENGINE_set_EC(e, ecdsae_method)) { + errstr = "ENGINE_set_EC"; + goto fail; + } + if (!ENGINE_set_default_EC(e)) { + errstr = "ENGINE_set_default_EC"; + goto fail; + } + return; + + fail: + ssl_error(errstr); + fatalx("%s", errstr); +} #endif void ca_engine_init(void) { rsa_engine_init(); -#if defined(SUPPORT_ECDSA) ecdsa_engine_init(); -#endif } diff --git a/usr.sbin/smtpd/ssl.c b/usr.sbin/smtpd/ssl.c index a37d6fea..97f7b1df 100644 --- a/usr.sbin/smtpd/ssl.c +++ b/usr.sbin/smtpd/ssl.c @@ -400,11 +400,12 @@ ssl_load_pkey(const void *data, size_t datalen, char *buf, off_t len, #if defined(SUPPORT_ECDSA) if (eckey) ECDSA_set_ex_data(eckey, 0, exdata); +#else + if (eckey) + EC_KEY_set_ex_data(eckey, 0, exdata); #endif RSA_free(rsa); /* dereference, will be cleaned up with pkey */ -#if defined(SUPPORT_ECDSA) EC_KEY_free(eckey); /* dereference, will be cleaned up with pkey */ -#endif } *x509ptr = x509; |