From d31243ddf014c95543d5d05e1fc85d2cd07dc381 Mon Sep 17 00:00:00 2001 From: LeftTry Date: Sat, 27 Jul 2024 14:25:54 +0500 Subject: [PATCH] [Feature] Add support for OpenSSL 3.0 for DKIM --- src/libcryptobox/cryptobox.c | 76 ++++++++---------------------------- src/libcryptobox/cryptobox.h | 4 +- src/libserver/dkim.c | 70 ++++++++++++++++++++++++++++----- 3 files changed, 79 insertions(+), 71 deletions(-) diff --git a/src/libcryptobox/cryptobox.c b/src/libcryptobox/cryptobox.c index 27323bbae..25ee9a471 100644 --- a/src/libcryptobox/cryptobox.c +++ b/src/libcryptobox/cryptobox.c @@ -708,7 +708,7 @@ void rspamd_cryptobox_sign(unsigned char *sig, unsigned long long *siglen_p, void rspamd_cryptobox_sign_compat(int nid, unsigned char *sig, unsigned long long *siglen_p, const unsigned char *m, gsize mlen, - struct evp_pkey_st *sec_key, + struct evp_pkey_st *sec_key, int ktype, enum rspamd_cryptobox_mode mode) { if (G_LIKELY(mode == RSPAMD_CRYPTOBOX_MODE_25519)) { @@ -750,7 +750,8 @@ void rspamd_cryptobox_sign_compat(int nid, unsigned char *sig, unsigned long lon #if OPENSSL_VERSION_MAJOR >= 3 EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(sec_key, NULL); - EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PADDING); + if(ktype == 1) + EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PADDING); g_assert(EVP_DigestSignInit(sha_ctx, NULL, type, NULL, sec_key) == 1); @@ -789,9 +790,9 @@ void rspamd_cryptobox_sign_compat(int nid, unsigned char *sig, unsigned long lon bool rspamd_cryptobox_verify_compat(int nid, const unsigned char *sig, gsize siglen, - const unsigned char *m, - gsize mlen, - struct evp_pkey_st *pub_key, + const unsigned char *digest, + gsize dlen, + struct evp_pkey_st *pub_key, int ktype, enum rspamd_cryptobox_mode mode) { bool ret = false; @@ -801,71 +802,28 @@ bool rspamd_cryptobox_verify_compat(int nid, rspamd_pk_t pk; size_t len_pk = sizeof(rspamd_pk_t); EVP_PKEY_get_raw_public_key(pub_key, pk, &len_pk); - ret = (crypto_sign_verify_detached(sig, m, mlen, pk) == 0); + ret = (crypto_sign_verify_detached(sig, digest, dlen, pk) == 0); } } else { #ifndef HAVE_USABLE_OPENSSL g_assert(0); #else - EVP_MD_CTX *sha_ctx; - unsigned char h[64]; - - /* Prehash */ - sha_ctx = EVP_MD_CTX_create(); - EVP_MD *type = NULL; - switch(nid) - { - case NID_sha1: - type = EVP_sha1(); - break; - case NID_sha256: - type = EVP_sha256(); - break; - case NID_sha512: - type = EVP_sha512(); - break; - default: - type = NULL; - } - g_assert(EVP_DigestInit(sha_ctx, type) == 1); - EVP_DigestUpdate(sha_ctx, m, mlen); - EVP_DigestFinal(sha_ctx, h, NULL); - - -#if OPENSSL_VERSION_MAJOR >= 3 EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(pub_key, NULL); + g_assert(pctx != NULL); + EVP_MD_CTX *mdctx = EVP_MD_CTX_new(); + EVP_MD *md = EVP_get_digestbynid(nid); - g_assert(EVP_DigestVerifyInit(sha_ctx, NULL, type, NULL, pub_key) == 1); - - ret = (EVP_DigestVerify(sha_ctx, sig, siglen, m, mlen) == 1); - - EVP_PKEY_free(pub_key); - EVP_PKEY_CTX_free(pctx); -#else - EC_KEY *lk; - EC_POINT *ec_pub; - BIGNUM *bn_pub; - - /* Key setup */ - lk = EC_KEY_new_by_curve_name(CRYPTOBOX_CURVE_NID); - g_assert(lk != NULL); - bn_pub = BN_bin2bn(pk, rspamd_cryptobox_pk_bytes(mode), NULL); - g_assert(bn_pub != NULL); - ec_pub = ec_point_bn2point_compat(EC_KEY_get0_group(lk), bn_pub, NULL, NULL); - g_assert(ec_pub != NULL); - g_assert(EC_KEY_set_public_key(lk, ec_pub) == 1); - - /* ECDSA */ - ret = ECDSA_verify(0, h, sizeof(h), sig, siglen, lk) == 1; + g_assert(EVP_PKEY_verify_init(pctx) == 1); - EC_KEY_free(lk); + if(ktype == 1) g_assert(EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PADDING) == 1); + g_assert(EVP_PKEY_CTX_set_signature_md(pctx, md) == 1); - BN_free(bn_pub); - EC_POINT_free(ec_pub); -#endif + ret = (EVP_PKEY_verify(pctx, sig, siglen, digest, dlen) == 1); - EVP_MD_CTX_destroy(sha_ctx); + EVP_PKEY_CTX_free(pctx); + EVP_MD_free(md); + EVP_MD_CTX_free(mdctx); #endif } diff --git a/src/libcryptobox/cryptobox.h b/src/libcryptobox/cryptobox.h index 54ef48c9a..f11d31994 100644 --- a/src/libcryptobox/cryptobox.h +++ b/src/libcryptobox/cryptobox.h @@ -209,7 +209,7 @@ void rspamd_cryptobox_sign(unsigned char *sig, unsigned long long *siglen_p, void rspamd_cryptobox_sign_compat(int nid, unsigned char *sig, unsigned long long *siglen_p, const unsigned char *m, gsize mlen, - struct evp_pkey_st *sec_key, + struct evp_pkey_st *sec_key, int ktype, enum rspamd_cryptobox_mode mode); /** @@ -233,7 +233,7 @@ bool rspamd_cryptobox_verify_compat(int nid, gsize siglen, const unsigned char *m, gsize mlen, - struct evp_pkey_st *pub_key, + struct evp_pkey_st *pub_key, int ktype, enum rspamd_cryptobox_mode mode); /** diff --git a/src/libserver/dkim.c b/src/libserver/dkim.c index 3d974c0c4..3dcaef246 100644 --- a/src/libserver/dkim.c +++ b/src/libserver/dkim.c @@ -25,6 +25,7 @@ #include #include #include +#include /* special DNS tokens */ #define DKIM_DNSKEYNAME "_domainkey" @@ -155,8 +156,8 @@ struct rspamd_dkim_key_s { gsize decoded_len; char key_id[RSPAMD_DKIM_KEY_ID_LEN]; union { - RSA *key_rsa; - EC_KEY *key_ecdsa; + //RSA *key_rsa; + //EC_KEY *key_ecdsa; unsigned char *key_eddsa; } key; BIO *key_bio; @@ -1492,6 +1493,8 @@ void rspamd_dkim_key_free(rspamd_dkim_key_t *key) RSA_free(key->key.key_rsa); } } +#endif +#if OPENSSL_VERSION_MAJOR < 3 else if (key->type == RSPAMD_DKIM_KEY_ECDSA) { if (key->key.key_ecdsa) { EC_KEY_free(key->key.key_ecdsa); @@ -2921,7 +2924,6 @@ rspamd_dkim_check(rspamd_dkim_context_t *ctx, /* Not reached */ nid = NID_sha1; } - switch (key->type) { case RSPAMD_DKIM_KEY_RSA: #if OPENSSL_VERSION_MAJOR < 3 @@ -2942,9 +2944,18 @@ rspamd_dkim_check(rspamd_dkim_context_t *ctx, RSPAMD_DKIM_KEY_ID_LEN, rspamd_dkim_key_id(key), ctx->dkim_header); } + msg_info_dkim( + "%s: headers RSA verification failure; " + "body length %d->%d; headers length %d; d=%s; s=%s; key_md5=%*xs; orig header: %s", + rspamd_dkim_type_to_string(ctx->common.type), + (int) (body_end - body_start), ctx->common.body_canonicalised, + ctx->common.headers_canonicalised, + ctx->domain, ctx->selector, + RSPAMD_DKIM_KEY_ID_LEN, rspamd_dkim_key_id(key), + ctx->dkim_header); #else - if (rspamd_cryptobox_verify_compat(nid, ctx->b, ctx->blen, raw_digest, dlen, - key->key_evp, RSPAMD_CRYPTOBOX_MODE_NIST) != 1) { + if (!rspamd_cryptobox_verify_compat(nid, ctx->b, ctx->blen, raw_digest, dlen, + key->key_evp, 1, RSPAMD_CRYPTOBOX_MODE_NIST)){ msg_debug_dkim("headers rsa verify failed"); ERR_clear_error(); res->rcode = DKIM_REJECT; @@ -2982,7 +2993,7 @@ rspamd_dkim_check(rspamd_dkim_context_t *ctx, } #else if (rspamd_cryptobox_verify_compat(nid, ctx->b, ctx->blen, raw_digest, dlen, - key->key_evp, RSPAMD_CRYPTOBOX_MODE_NIST) != 1) { + key->key_evp, 0, RSPAMD_CRYPTOBOX_MODE_NIST) != 1) { msg_info_dkim( "%s: headers ECDSA verification failure; " "body length %d->%d; headers length %d; d=%s; s=%s; key_md5=%*xs; orig header: %s", @@ -3318,7 +3329,7 @@ rspamd_create_dkim_sign_context(struct rspamd_task *task, return NULL; } - +#if OPENSSL_VERSION_MAJOR < 3 if (!priv_key || (!priv_key->key.key_rsa && !priv_key->key.key_eddsa)) { g_set_error(err, DKIM_ERROR, @@ -3327,6 +3338,17 @@ rspamd_create_dkim_sign_context(struct rspamd_task *task, return NULL; } +#else + + if (!priv_key) { + g_set_error(err, + DKIM_ERROR, + DKIM_SIGERROR_KEYFAIL, + "bad key to sign"); + + return NULL; + } +#endif nctx = rspamd_mempool_alloc0(task->task_pool, sizeof(*nctx)); nctx->common.pool = task->task_pool; @@ -3603,9 +3625,37 @@ rspamd_dkim_sign(struct rspamd_task *task, const char *selector, #else sig_len = EVP_PKEY_get_size(ctx->key->key_evp); sig_buf = g_alloca(sig_len); - rspamd_cryptobox_sign_compat(NID_sha256, sig_buf, NULL, raw_digest, dlen, - ctx->key->key_evp, RSPAMD_CRYPTOBOX_MODE_NIST); - msg_debug("signed RSA"); + + EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(ctx->key->key_evp, NULL); + if (EVP_PKEY_sign_init(pctx) <= 0) { + g_string_free(hdr, TRUE); + msg_err_task("rsa sign error: %s", + ERR_error_string(ERR_get_error(), NULL)); + + return NULL; + } + if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PADDING) <= 0) { + g_string_free(hdr, TRUE); + msg_err_task("rsa sign error: %s", + ERR_error_string(ERR_get_error(), NULL)); + + return NULL; + } + if (EVP_PKEY_CTX_set_signature_md(pctx, EVP_sha256()) <= 0) { + g_string_free(hdr, TRUE); + msg_err_task("rsa sign error: %s", + ERR_error_string(ERR_get_error(), NULL)); + + return NULL; + } + size_t sig_len_size_t = sig_len; + if (EVP_PKEY_sign(pctx, sig_buf, &sig_len_size_t, raw_digest, dlen) <= 0) { + g_string_free(hdr, TRUE); + msg_err_task("rsa sign error: %s", + ERR_error_string(ERR_get_error(), NULL)); + + return NULL; + } #endif } else if (ctx->key->type == RSPAMD_DKIM_KEY_EDDSA) { -- 2.39.5