From d46c5ad4a55e54681db731e0b4086b9f7e6b6bed Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Wed, 7 Aug 2024 10:26:09 +0100 Subject: [PATCH] [Fix] Fix and rework various parts --- contrib/aho-corasick/acism.c | 2 - src/libcryptobox/cryptobox.c | 97 +++++++++++++++++++++++------------- src/libcryptobox/cryptobox.h | 33 ++++++++---- src/libserver/dkim.c | 16 +++--- 4 files changed, 94 insertions(+), 54 deletions(-) diff --git a/contrib/aho-corasick/acism.c b/contrib/aho-corasick/acism.c index b0cee0d66..7451a8791 100644 --- a/contrib/aho-corasick/acism.c +++ b/contrib/aho-corasick/acism.c @@ -38,8 +38,6 @@ #include "_acism.h" #include "unix-std.h" -#define BACK ((SYMBOL) 0) -#define ROOT ((STATE) 0) extern const unsigned char lc_map[256]; int acism_lookup(ac_trie_t const *psp, const char *text, size_t len, diff --git a/src/libcryptobox/cryptobox.c b/src/libcryptobox/cryptobox.c index 87e2db227..6c6aed031 100644 --- a/src/libcryptobox/cryptobox.c +++ b/src/libcryptobox/cryptobox.c @@ -410,8 +410,6 @@ void rspamd_cryptobox_keypair_sig(rspamd_sig_pk_t pk, rspamd_sig_sk_t sk, g_assert(0); #else - const EC_POINT *ec_pub; - EC_GROUP *group; gsize len; #if OPENSSL_VERSION_MAJOR >= 3 OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new(); @@ -436,6 +434,8 @@ void rspamd_cryptobox_keypair_sig(rspamd_sig_pk_t pk, rspamd_sig_sk_t sk, #else EC_KEY *ec_sec; const BIGNUM *bn_sec; + const EC_POINT *ec_pub; + EC_GROUP *group; ec_sec = EC_KEY_new_by_curve_name(CRYPTOBOX_CURVE_NID); g_assert(ec_sec != NULL); @@ -459,9 +459,9 @@ void rspamd_cryptobox_keypair_sig(rspamd_sig_pk_t pk, rspamd_sig_sk_t sk, len = BN_num_bytes(bn_sec); g_assert(len <= (int) sizeof(rspamd_sk_t)); BN_bn2bin(bn_sec, sk); + EC_GROUP_free(group); #endif - EC_GROUP_free(group); #endif } } @@ -532,7 +532,6 @@ void rspamd_cryptobox_nm(rspamd_nm_t nm, #ifndef HAVE_USABLE_OPENSSL g_assert(0); #else - int len; unsigned char s[32]; #if OPENSSL_VERSION_MAJOR >= 3 @@ -572,6 +571,7 @@ void rspamd_cryptobox_nm(rspamd_nm_t nm, OSSL_LIB_CTX_free(libctx); #else //g_error(ERR_error_string(ERR_get_error(), NULL)); + int len; EC_KEY *lk; EC_POINT *ec_pub; BIGNUM *bn_pub, *bn_sec; @@ -688,48 +688,75 @@ void rspamd_cryptobox_sign(unsigned char *sig, unsigned long long *siglen_p, } } -bool rspamd_cryptobox_verify_compat(int nid, - const unsigned char *sig, - gsize siglen, - const unsigned char *digest, - gsize dlen, - struct evp_pkey_st *pub_key, int ktype, - enum rspamd_cryptobox_mode mode) +#ifdef HAVE_OPENSSL +bool rspamd_cryptobox_verify_evp_ed25519(int nid, + const unsigned char *sig, + gsize siglen, + const unsigned char *digest, + gsize dlen, + struct evp_pkey_st *pub_key) { bool ret = false; - if (G_LIKELY(mode == RSPAMD_CRYPTOBOX_MODE_25519)) { - if (siglen == rspamd_cryptobox_signature_bytes(RSPAMD_CRYPTOBOX_MODE_25519)) { - 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, digest, dlen, pk) == 0); - } + if (siglen == rspamd_cryptobox_signature_bytes(RSPAMD_CRYPTOBOX_MODE_25519)) { + 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, digest, dlen, pk) == 0); } - else { -#ifndef HAVE_USABLE_OPENSSL - g_assert(0); -#else - 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_PKEY_verify_init(pctx) == 1); + return ret; +} - 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); +bool rspamd_cryptobox_verify_evp_ecdsa(int nid, + const unsigned char *sig, + gsize siglen, + const unsigned char *digest, + gsize dlen, + EVP_PKEY *pub_key) +{ + bool ret = false; + EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(pub_key, NULL); + g_assert(pctx != NULL); + EVP_MD_CTX *mdctx = EVP_MD_CTX_new(); + const EVP_MD *md = EVP_get_digestbynid(nid); - ret = (EVP_PKEY_verify(pctx, sig, siglen, digest, dlen) == 1); + g_assert(EVP_PKEY_verify_init(pctx) == 1); + g_assert(EVP_PKEY_CTX_set_signature_md(pctx, md) == 1); - EVP_PKEY_CTX_free(pctx); - EVP_MD_free(md); - EVP_MD_CTX_free(mdctx); -#endif - } + ret = (EVP_PKEY_verify(pctx, sig, siglen, digest, dlen) == 1); + + EVP_PKEY_CTX_free(pctx); + EVP_MD_CTX_free(mdctx); return ret; } +bool rspamd_cryptobox_verify_evp_rsa(int nid, + const unsigned char *sig, + gsize siglen, + const unsigned char *digest, + gsize dlen, + EVP_PKEY *pub_key) +{ + bool ret = false; + + EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(pub_key, NULL); + g_assert(pctx != NULL); + EVP_MD_CTX *mdctx = EVP_MD_CTX_new(); + const EVP_MD *md = EVP_get_digestbynid(nid); + + g_assert(EVP_PKEY_verify_init(pctx) == 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); + + ret = (EVP_PKEY_verify(pctx, sig, siglen, digest, dlen) == 1); + + EVP_PKEY_CTX_free(pctx); + EVP_MD_CTX_free(mdctx); + + return ret; +} +#endif bool rspamd_cryptobox_verify(const unsigned char *sig, gsize siglen, diff --git a/src/libcryptobox/cryptobox.h b/src/libcryptobox/cryptobox.h index 7b214c491..234da2054 100644 --- a/src/libcryptobox/cryptobox.h +++ b/src/libcryptobox/cryptobox.h @@ -18,7 +18,10 @@ #define CRYPTOBOX_H_ #include "config.h" -#include "openssl/evp.h" + +#ifdef HAVE_OPENSSL +#include +#endif #include @@ -224,22 +227,34 @@ bool rspamd_cryptobox_verify(const unsigned char *sig, const rspamd_pk_t pk, enum rspamd_cryptobox_mode mode); +#ifdef HAVE_OPENSSL /** * Verifies digital signature for specified raw digest with specified pubkey * @param nid signing algorithm nid * @param sig signature source * @param digest raw digest * @param pub_key public key for verification - * @param ktype type of public key (1 - RSA, 0 - ECDSA) * @return true if signature is valid, false otherwise */ -bool rspamd_cryptobox_verify_compat(int nid, - const unsigned char *sig, - gsize siglen, - const unsigned char *digest, - gsize dlen, - struct evp_pkey_st *pub_key, int ktype, - enum rspamd_cryptobox_mode mode); +bool rspamd_cryptobox_verify_evp_ed25519(int nid, + const unsigned char *sig, + gsize siglen, + const unsigned char *digest, + gsize dlen, + EVP_PKEY *pub_key); +bool rspamd_cryptobox_verify_evp_ecdsa(int nid, + const unsigned char *sig, + gsize siglen, + const unsigned char *digest, + gsize dlen, + EVP_PKEY *pub_key); +bool rspamd_cryptobox_verify_evp_rsa(int nid, + const unsigned char *sig, + gsize siglen, + const unsigned char *digest, + gsize dlen, + EVP_PKEY *pub_key); +#endif /** * Securely clear the buffer specified diff --git a/src/libserver/dkim.c b/src/libserver/dkim.c index 8fcd157a2..50a55ebaa 100644 --- a/src/libserver/dkim.c +++ b/src/libserver/dkim.c @@ -2143,7 +2143,8 @@ rspamd_dkim_canonize_body(struct rspamd_task *task, if (ctx->body_canon_type == DKIM_CANON_SIMPLE) { /* Simple canonization */ while (rspamd_dkim_simple_body_step(ctx, ctx->body_hash, - &start, end - start, &remain)); + &start, end - start, &remain)) + ; /* * If we have l= tag then we cannot add crlf... @@ -2179,7 +2180,8 @@ rspamd_dkim_canonize_body(struct rspamd_task *task, size_t orig_len = remain; while (rspamd_dkim_relaxed_body_step(ctx, ctx->body_hash, - &start, end - start, &remain)); + &start, end - start, &remain)) + ; if (ctx->len > 0 && remain > (double) orig_len * 0.1) { msg_info_task("DKIM l tag does not cover enough of the body: %d (%d actual size)", @@ -2199,7 +2201,6 @@ rspamd_dkim_canonize_body(struct rspamd_task *task, return TRUE; } - /* TODO: Implement relaxed algorithm */ return FALSE; } @@ -2873,8 +2874,8 @@ rspamd_dkim_check(rspamd_dkim_context_t *ctx, } switch (key->type) { case RSPAMD_DKIM_KEY_RSA: - if (!rspamd_cryptobox_verify_compat(nid, ctx->b, ctx->blen, raw_digest, dlen, - key->specific.key_ssl.key_evp, 1, RSPAMD_CRYPTOBOX_MODE_NIST)) { + if (!rspamd_cryptobox_verify_evp_rsa(nid, ctx->b, ctx->blen, raw_digest, dlen, + key->specific.key_ssl.key_evp)) { msg_debug_dkim("headers rsa verify failed"); ERR_clear_error(); res->rcode = DKIM_REJECT; @@ -2892,9 +2893,8 @@ rspamd_dkim_check(rspamd_dkim_context_t *ctx, } break; case RSPAMD_DKIM_KEY_ECDSA: - /* TODO: this is currently badly broken, as it tries to verify RSA instead of ECDSA */ - if (rspamd_cryptobox_verify_compat(nid, ctx->b, ctx->blen, raw_digest, dlen, - key->specific.key_ssl.key_evp, 0, RSPAMD_CRYPTOBOX_MODE_NIST) != 1) { + if (rspamd_cryptobox_verify_evp_ecdsa(nid, ctx->b, ctx->blen, raw_digest, dlen, + key->specific.key_ssl.key_evp) != 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", -- 2.39.5