]> source.dussan.org Git - rspamd.git/commitdiff
[Feature] Add support for OpenSSL 3.0 for DKIM
authorLeftTry <lerest.go@gmail.com>
Sat, 27 Jul 2024 09:25:54 +0000 (14:25 +0500)
committerLeftTry <lerest.go@gmail.com>
Sat, 27 Jul 2024 09:25:54 +0000 (14:25 +0500)
src/libcryptobox/cryptobox.c
src/libcryptobox/cryptobox.h
src/libserver/dkim.c

index 27323bbaec2fe437baaf3e230277c299ba810bee..25ee9a471eda3a061579a27c8e48e98a6c9cff02 100644 (file)
@@ -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
        }
 
index 54ef48c9a3095a809c43377744bcc6557d249048..f11d31994990cd31132f5f51260e3f321ccea3f0 100644 (file)
@@ -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);
 
 /**
index 3d974c0c4e3d738c48c2b03b6bafddf3f698fd4e..3dcaef246695062dd7d7108b02a0c1ccd832b29f 100644 (file)
@@ -25,6 +25,7 @@
 #include <openssl/evp.h>
 #include <openssl/rsa.h>
 #include <openssl/engine.h>
+#include <openssl/param_build.h>
 
 /* 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) {