diff options
-rw-r--r-- | src/libcryptobox/cryptobox.h | 514 | ||||
-rw-r--r-- | src/libserver/dkim.c | 199 |
2 files changed, 397 insertions, 316 deletions
diff --git a/src/libcryptobox/cryptobox.h b/src/libcryptobox/cryptobox.h index 8382c8f68..54ef48c9a 100644 --- a/src/libcryptobox/cryptobox.h +++ b/src/libcryptobox/cryptobox.h @@ -1,22 +1,23 @@ /* - * Copyright 2024 Vsevolod Stakhov - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +* Copyright 2024 Vsevolod Stakhov +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ #ifndef CRYPTOBOX_H_ #define CRYPTOBOX_H_ #include "config.h" +#include "openssl/evp.h" #include <sodium.h> @@ -25,13 +26,13 @@ extern "C" { #endif struct rspamd_cryptobox_segment { - unsigned char *data; - gsize len; + unsigned char *data; + gsize len; }; #if defined(__GNUC__) && \ - ((defined(__clang__) && (__clang_major__ >= 4 || (__clang_major__ >= 3 && __clang_minor__ >= 8))) || \ - ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8) || (__GNUC__ > 4))) + ((defined(__clang__) && (__clang_major__ >= 4 || (__clang_major__ >= 3 && __clang_minor__ >= 8))) || \ + ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8) || (__GNUC__ > 4))) #define RSPAMD_HAS_TARGET_ATTR 1 #endif @@ -68,366 +69,379 @@ typedef unsigned char rspamd_sig_pk_t[rspamd_cryptobox_MAX_SIGPKBYTES]; typedef unsigned char rspamd_sig_sk_t[rspamd_cryptobox_MAX_SIGSKBYTES]; enum rspamd_cryptobox_mode { - RSPAMD_CRYPTOBOX_MODE_25519 = 0, - RSPAMD_CRYPTOBOX_MODE_NIST + RSPAMD_CRYPTOBOX_MODE_25519 = 0, + RSPAMD_CRYPTOBOX_MODE_NIST }; struct rspamd_cryptobox_library_ctx { - char *cpu_extensions; - const char *chacha20_impl; - const char *base64_impl; - unsigned long cpu_config; + char *cpu_extensions; + const char *chacha20_impl; + const char *base64_impl; + unsigned long cpu_config; }; /** - * Init cryptobox library - */ +* Init cryptobox library +*/ struct rspamd_cryptobox_library_ctx *rspamd_cryptobox_init(void); void rspamd_cryptobox_deinit(struct rspamd_cryptobox_library_ctx *); /** - * Generate new keypair - * @param pk public key buffer - * @param sk secret key buffer - */ +* Generate new keypair +* @param pk public key buffer +* @param sk secret key buffer +*/ void rspamd_cryptobox_keypair(rspamd_pk_t pk, rspamd_sk_t sk, - enum rspamd_cryptobox_mode mode); + enum rspamd_cryptobox_mode mode); /** - * Generate new keypair for signing - * @param pk public key buffer - * @param sk secret key buffer - */ +* Generate new keypair for signing +* @param pk public key buffer +* @param sk secret key buffer +*/ void rspamd_cryptobox_keypair_sig(rspamd_sig_pk_t pk, rspamd_sig_sk_t sk, - enum rspamd_cryptobox_mode mode); + enum rspamd_cryptobox_mode mode); /** - * Encrypt data inplace adding signature to sig afterwards - * @param data input buffer - * @param pk remote pubkey - * @param sk local secret key - * @param sig output signature - */ +* Encrypt data inplace adding signature to sig afterwards +* @param data input buffer +* @param pk remote pubkey +* @param sk local secret key +* @param sig output signature +*/ void rspamd_cryptobox_encrypt_inplace(unsigned char *data, gsize len, + const rspamd_nonce_t nonce, + const rspamd_pk_t pk, const rspamd_sk_t sk, rspamd_mac_t sig, + enum rspamd_cryptobox_mode mode); + +/** +* Encrypt segments of data inplace adding signature to sig afterwards +* @param segments segments of data +* @param cnt count of segments +* @param pk remote pubkey +* @param sk local secret key +* @param sig output signature +*/ +void rspamd_cryptobox_encryptv_inplace(struct rspamd_cryptobox_segment *segments, + gsize cnt, const rspamd_nonce_t nonce, const rspamd_pk_t pk, const rspamd_sk_t sk, rspamd_mac_t sig, enum rspamd_cryptobox_mode mode); -/** - * Encrypt segments of data inplace adding signature to sig afterwards - * @param segments segments of data - * @param cnt count of segments - * @param pk remote pubkey - * @param sk local secret key - * @param sig output signature - */ -void rspamd_cryptobox_encryptv_inplace(struct rspamd_cryptobox_segment *segments, - gsize cnt, - const rspamd_nonce_t nonce, - const rspamd_pk_t pk, const rspamd_sk_t sk, rspamd_mac_t sig, - enum rspamd_cryptobox_mode mode); - /** - * Decrypt and verify data chunk inplace - * @param data data to decrypt - * @param len length of data - * @param pk remote pubkey - * @param sk local privkey - * @param sig signature input - * @return TRUE if input has been verified successfully - */ +* Decrypt and verify data chunk inplace +* @param data data to decrypt +* @param len length of data +* @param pk remote pubkey +* @param sk local privkey +* @param sig signature input +* @return TRUE if input has been verified successfully +*/ gboolean rspamd_cryptobox_decrypt_inplace(unsigned char *data, gsize len, - const rspamd_nonce_t nonce, - const rspamd_pk_t pk, const rspamd_sk_t sk, const rspamd_mac_t sig, - enum rspamd_cryptobox_mode mode); - -/** - * Encrypt segments of data inplace adding signature to sig afterwards - * @param segments segments of data - * @param cnt count of segments - * @param pk remote pubkey - * @param sk local secret key - * @param sig output signature - */ -void rspamd_cryptobox_encrypt_nm_inplace(unsigned char *data, gsize len, const rspamd_nonce_t nonce, - const rspamd_nm_t nm, rspamd_mac_t sig, + const rspamd_pk_t pk, const rspamd_sk_t sk, const rspamd_mac_t sig, enum rspamd_cryptobox_mode mode); /** - * Encrypt segments of data inplace adding signature to sig afterwards - * @param segments segments of data - * @param cnt count of segments - * @param pk remote pubkey - * @param sk local secret key - * @param sig output signature - */ +* Encrypt segments of data inplace adding signature to sig afterwards +* @param segments segments of data +* @param cnt count of segments +* @param pk remote pubkey +* @param sk local secret key +* @param sig output signature +*/ +void rspamd_cryptobox_encrypt_nm_inplace(unsigned char *data, gsize len, + const rspamd_nonce_t nonce, + const rspamd_nm_t nm, rspamd_mac_t sig, + enum rspamd_cryptobox_mode mode); + +/** +* Encrypt segments of data inplace adding signature to sig afterwards +* @param segments segments of data +* @param cnt count of segments +* @param pk remote pubkey +* @param sk local secret key +* @param sig output signature +*/ void rspamd_cryptobox_encryptv_nm_inplace(struct rspamd_cryptobox_segment *segments, - gsize cnt, - const rspamd_nonce_t nonce, - const rspamd_nm_t nm, rspamd_mac_t sig, - enum rspamd_cryptobox_mode mode); + gsize cnt, + const rspamd_nonce_t nonce, + const rspamd_nm_t nm, rspamd_mac_t sig, + enum rspamd_cryptobox_mode mode); /** - * Decrypt and verify data chunk inplace - * @param data data to decrypt - * @param len length of data - * @param pk remote pubkey - * @param sk local privkey - * @param sig signature input - * @return TRUE if input has been verified successfully - */ +* Decrypt and verify data chunk inplace +* @param data data to decrypt +* @param len length of data +* @param pk remote pubkey +* @param sk local privkey +* @param sig signature input +* @return TRUE if input has been verified successfully +*/ gboolean rspamd_cryptobox_decrypt_nm_inplace(unsigned char *data, gsize len, - const rspamd_nonce_t nonce, - const rspamd_nm_t nm, const rspamd_mac_t sig, - enum rspamd_cryptobox_mode mode); + const rspamd_nonce_t nonce, + const rspamd_nm_t nm, const rspamd_mac_t sig, + enum rspamd_cryptobox_mode mode); /** - * Generate shared secret from local sk and remote pk - * @param nm shared secret - * @param pk remote pubkey - * @param sk local privkey - */ +* Generate shared secret from local sk and remote pk +* @param nm shared secret +* @param pk remote pubkey +* @param sk local privkey +*/ void rspamd_cryptobox_nm(rspamd_nm_t nm, const rspamd_pk_t pk, - const rspamd_sk_t sk, enum rspamd_cryptobox_mode mode); + const rspamd_sk_t sk, enum rspamd_cryptobox_mode mode); /** - * Create digital signature for the specified message and place result in `sig` - * @param sig signature target - * @param siglen_p pointer to signature length (might be NULL) - * @param m input message - * @param mlen input length - * @param sk secret key - */ +* Create digital signature for the specified message and place result in `sig` +* @param sig signature target +* @param siglen_p pointer to signature length (might be NULL) +* @param m input message +* @param mlen input length +* @param sk secret key +*/ void rspamd_cryptobox_sign(unsigned char *sig, unsigned long long *siglen_p, - const unsigned char *m, gsize mlen, - const rspamd_sk_t sk, - enum rspamd_cryptobox_mode mode); - -/** - * Verifies digital signature for the specified message using the specified - * pubkey - * @param sig signature source - * @param m input message - * @param mlen message length - * @param pk public key for verification - * @return true if signature is valid, false otherwise - */ + const unsigned char *m, gsize mlen, + const rspamd_sk_t sk, + enum rspamd_cryptobox_mode mode); + +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, + enum rspamd_cryptobox_mode mode); + +/** +* Verifies digital signature for the specified message using the specified +* pubkey +* @param sig signature source +* @param m input message +* @param mlen message length +* @param pk public key for verification +* @return true if signature is valid, false otherwise +*/ bool rspamd_cryptobox_verify(const unsigned char *sig, - gsize siglen, - const unsigned char *m, - gsize mlen, - const rspamd_pk_t pk, - enum rspamd_cryptobox_mode mode); - -/** - * Securely clear the buffer specified - * @param buf buffer to zero - * @param buflen length of buffer - */ + gsize siglen, + const unsigned char *m, + gsize mlen, + const rspamd_pk_t pk, + enum rspamd_cryptobox_mode mode); + +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, + enum rspamd_cryptobox_mode mode); + +/** +* Securely clear the buffer specified +* @param buf buffer to zero +* @param buflen length of buffer +*/ #define rspamd_explicit_memzero sodium_memzero /** - * Constant time memcmp - * @param b1_ - * @param b2_ - * @param len - * @return - */ +* Constant time memcmp +* @param b1_ +* @param b2_ +* @param len +* @return +*/ #define rspamd_cryptobox_memcmp sodium_memcmp /** - * Calculates siphash-2-4 for a message - * @param out (8 bytes output) - * @param in - * @param inlen - * @param k key (must be 16 bytes) - */ +* Calculates siphash-2-4 for a message +* @param out (8 bytes output) +* @param in +* @param inlen +* @param k key (must be 16 bytes) +*/ void rspamd_cryptobox_siphash(unsigned char *out, const unsigned char *in, - unsigned long long inlen, - const rspamd_sipkey_t k); + unsigned long long inlen, + const rspamd_sipkey_t k); enum rspamd_cryptobox_pbkdf_type { - RSPAMD_CRYPTOBOX_PBKDF2 = 0, - RSPAMD_CRYPTOBOX_CATENA + RSPAMD_CRYPTOBOX_PBKDF2 = 0, + RSPAMD_CRYPTOBOX_CATENA }; /** - * Derive key from password using the specified algorithm - * @param pass input password - * @param pass_len length of the password - * @param salt input salt - * @param salt_len length of salt - * @param key output key - * @param key_len size of the key - * @param complexity empiric number of complexity (rounds for pbkdf2 and garlic for catena) - * @return TRUE in case of success and FALSE if failed - */ +* Derive key from password using the specified algorithm +* @param pass input password +* @param pass_len length of the password +* @param salt input salt +* @param salt_len length of salt +* @param key output key +* @param key_len size of the key +* @param complexity empiric number of complexity (rounds for pbkdf2 and garlic for catena) +* @return TRUE in case of success and FALSE if failed +*/ gboolean rspamd_cryptobox_pbkdf(const char *pass, gsize pass_len, - const uint8_t *salt, gsize salt_len, - uint8_t *key, gsize key_len, - unsigned int complexity, - enum rspamd_cryptobox_pbkdf_type type); + const uint8_t *salt, gsize salt_len, + uint8_t *key, gsize key_len, + unsigned int complexity, + enum rspamd_cryptobox_pbkdf_type type); /** - * Real size of rspamd cryptobox public key - */ +* Real size of rspamd cryptobox public key +*/ unsigned int rspamd_cryptobox_pk_bytes(enum rspamd_cryptobox_mode mode); /** - * Real size of rspamd cryptobox signing public key - */ +* Real size of rspamd cryptobox signing public key +*/ unsigned int rspamd_cryptobox_pk_sig_bytes(enum rspamd_cryptobox_mode mode); /** - * Real size of crypto nonce - */ +* Real size of crypto nonce +*/ unsigned int rspamd_cryptobox_nonce_bytes(enum rspamd_cryptobox_mode mode); /** - * Real size of rspamd cryptobox secret key - */ +* Real size of rspamd cryptobox secret key +*/ unsigned int rspamd_cryptobox_sk_bytes(enum rspamd_cryptobox_mode mode); /** - * Real size of rspamd cryptobox signing secret key - */ +* Real size of rspamd cryptobox signing secret key +*/ unsigned int rspamd_cryptobox_sk_sig_bytes(enum rspamd_cryptobox_mode mode); /** - * Real size of rspamd cryptobox shared key - */ +* Real size of rspamd cryptobox shared key +*/ unsigned int rspamd_cryptobox_nm_bytes(enum rspamd_cryptobox_mode mode); /** - * Real size of rspamd cryptobox MAC signature - */ +* Real size of rspamd cryptobox MAC signature +*/ unsigned int rspamd_cryptobox_mac_bytes(enum rspamd_cryptobox_mode mode); /** - * Real size of rspamd cryptobox digital signature - */ +* Real size of rspamd cryptobox digital signature +*/ unsigned int rspamd_cryptobox_signature_bytes(enum rspamd_cryptobox_mode mode); /* Hash IUF interface */ typedef crypto_generichash_blake2b_state rspamd_cryptobox_hash_state_t; /** - * Init cryptobox hash state using key if needed, `st` must point to the buffer - * with at least rspamd_cryptobox_HASHSTATEBYTES bytes length. If keylen == 0, then - * non-keyed hash is generated - */ +* Init cryptobox hash state using key if needed, `st` must point to the buffer +* with at least rspamd_cryptobox_HASHSTATEBYTES bytes length. If keylen == 0, then +* non-keyed hash is generated +*/ void rspamd_cryptobox_hash_init(rspamd_cryptobox_hash_state_t *st, - const unsigned char *key, gsize keylen); + const unsigned char *key, gsize keylen); /** - * Update hash with data portion - */ +* Update hash with data portion +*/ void rspamd_cryptobox_hash_update(rspamd_cryptobox_hash_state_t *st, - const unsigned char *data, gsize len); + const unsigned char *data, gsize len); /** - * Output hash to the buffer of rspamd_cryptobox_HASHBYTES length - */ +* Output hash to the buffer of rspamd_cryptobox_HASHBYTES length +*/ void rspamd_cryptobox_hash_final(rspamd_cryptobox_hash_state_t *st, unsigned char *out); /** - * One in all function - */ +* One in all function +*/ void rspamd_cryptobox_hash(unsigned char *out, - const unsigned char *data, - gsize len, - const unsigned char *key, - gsize keylen); + const unsigned char *data, + gsize len, + const unsigned char *key, + gsize keylen); enum rspamd_cryptobox_fast_hash_type { - RSPAMD_CRYPTOBOX_XXHASH64 = 0, - RSPAMD_CRYPTOBOX_XXHASH32, - RSPAMD_CRYPTOBOX_XXHASH3, - RSPAMD_CRYPTOBOX_MUMHASH, - RSPAMD_CRYPTOBOX_T1HA, - RSPAMD_CRYPTOBOX_HASHFAST, - RSPAMD_CRYPTOBOX_HASHFAST_INDEPENDENT + RSPAMD_CRYPTOBOX_XXHASH64 = 0, + RSPAMD_CRYPTOBOX_XXHASH32, + RSPAMD_CRYPTOBOX_XXHASH3, + RSPAMD_CRYPTOBOX_MUMHASH, + RSPAMD_CRYPTOBOX_T1HA, + RSPAMD_CRYPTOBOX_HASHFAST, + RSPAMD_CRYPTOBOX_HASHFAST_INDEPENDENT }; /* Non crypto hash IUF interface */ typedef struct CRYPTO_ALIGN(64) rspamd_cryptobox_fast_hash_state_s { - unsigned char opaque[576]; /* Required for xxhash3 */ - enum rspamd_cryptobox_fast_hash_type type; + unsigned char opaque[576]; /* Required for xxhash3 */ + enum rspamd_cryptobox_fast_hash_type type; } rspamd_cryptobox_fast_hash_state_t; /** - * Creates a new cryptobox state properly aligned - * @return - */ +* Creates a new cryptobox state properly aligned +* @return +*/ rspamd_cryptobox_fast_hash_state_t *rspamd_cryptobox_fast_hash_new(void); void rspamd_cryptobox_fast_hash_free(rspamd_cryptobox_fast_hash_state_t *st); /** - * Init cryptobox hash state using key if needed, `st` must point to the buffer - * with at least rspamd_cryptobox_HASHSTATEBYTES bytes length. If keylen == 0, then - * non-keyed hash is generated - */ +* Init cryptobox hash state using key if needed, `st` must point to the buffer +* with at least rspamd_cryptobox_HASHSTATEBYTES bytes length. If keylen == 0, then +* non-keyed hash is generated +*/ void rspamd_cryptobox_fast_hash_init(rspamd_cryptobox_fast_hash_state_t *st, - uint64_t seed); + uint64_t seed); /** - * Init cryptobox hash state using key if needed, `st` must point to the buffer - * with at least rspamd_cryptobox_HASHSTATEBYTES bytes length. If keylen == 0, then - * non-keyed hash is generated - */ +* Init cryptobox hash state using key if needed, `st` must point to the buffer +* with at least rspamd_cryptobox_HASHSTATEBYTES bytes length. If keylen == 0, then +* non-keyed hash is generated +*/ void rspamd_cryptobox_fast_hash_init_specific(rspamd_cryptobox_fast_hash_state_t *st, - enum rspamd_cryptobox_fast_hash_type type, - uint64_t seed); + enum rspamd_cryptobox_fast_hash_type type, + uint64_t seed); /** - * Update hash with data portion - */ +* Update hash with data portion +*/ void rspamd_cryptobox_fast_hash_update(rspamd_cryptobox_fast_hash_state_t *st, - const void *data, gsize len); + const void *data, gsize len); /** - * Output hash to the buffer of rspamd_cryptobox_HASHBYTES length - */ +* Output hash to the buffer of rspamd_cryptobox_HASHBYTES length +*/ uint64_t rspamd_cryptobox_fast_hash_final(rspamd_cryptobox_fast_hash_state_t *st); /** - * One in all function - */ +* One in all function +*/ uint64_t rspamd_cryptobox_fast_hash(const void *data, - gsize len, uint64_t seed); + gsize len, uint64_t seed); /** - * Platform independent version - */ +* Platform independent version +*/ uint64_t rspamd_cryptobox_fast_hash_specific( - enum rspamd_cryptobox_fast_hash_type type, - const void *data, - gsize len, uint64_t seed); - -/** - * Decode base64 using platform optimized code - * @param in - * @param inlen - * @param out - * @param outlen - * @return - */ + enum rspamd_cryptobox_fast_hash_type type, + const void *data, + gsize len, uint64_t seed); + +/** +* Decode base64 using platform optimized code +* @param in +* @param inlen +* @param out +* @param outlen +* @return +*/ gboolean rspamd_cryptobox_base64_decode(const char *in, gsize inlen, - unsigned char *out, gsize *outlen); + unsigned char *out, gsize *outlen); /** - * Returns TRUE if data looks like a valid base64 string - * @param in - * @param inlen - * @return - */ +* Returns TRUE if data looks like a valid base64 string +* @param in +* @param inlen +* @return +*/ gboolean rspamd_cryptobox_base64_is_valid(const char *in, gsize inlen); #ifdef __cplusplus diff --git a/src/libserver/dkim.c b/src/libserver/dkim.c index 742e4db8b..3d974c0c4 100644 --- a/src/libserver/dkim.c +++ b/src/libserver/dkim.c @@ -1,18 +1,18 @@ /* - * Copyright 2024 Vsevolod Stakhov - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +* Copyright 2024 Vsevolod Stakhov +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ #include "config.h" #include "rspamd.h" #include "message.h" @@ -67,25 +67,25 @@ enum rspamd_dkim_param_type { #define RSPAMD_DKIM_MAX_ARC_IDX 10 #define msg_err_dkim(...) rspamd_default_log_function(G_LOG_LEVEL_CRITICAL, \ + "dkim", ctx->pool->tag.uid, \ + RSPAMD_LOG_FUNC, \ + __VA_ARGS__) +#define msg_warn_dkim(...) rspamd_default_log_function(G_LOG_LEVEL_WARNING, \ "dkim", ctx->pool->tag.uid, \ RSPAMD_LOG_FUNC, \ __VA_ARGS__) -#define msg_warn_dkim(...) rspamd_default_log_function(G_LOG_LEVEL_WARNING, \ - "dkim", ctx->pool->tag.uid, \ - RSPAMD_LOG_FUNC, \ - __VA_ARGS__) #define msg_info_dkim(...) rspamd_default_log_function(G_LOG_LEVEL_INFO, \ - "dkim", ctx->pool->tag.uid, \ - RSPAMD_LOG_FUNC, \ - __VA_ARGS__) + "dkim", ctx->pool->tag.uid, \ + RSPAMD_LOG_FUNC, \ + __VA_ARGS__) #define msg_debug_dkim(...) rspamd_conditional_debug_fast(NULL, NULL, \ - rspamd_dkim_log_id, "dkim", ctx->pool->tag.uid, \ - RSPAMD_LOG_FUNC, \ - __VA_ARGS__) + rspamd_dkim_log_id, "dkim", ctx->pool->tag.uid, \ + RSPAMD_LOG_FUNC, \ + __VA_ARGS__) #define msg_debug_dkim_taskless(...) rspamd_conditional_debug_fast(NULL, NULL, \ - rspamd_dkim_log_id, "dkim", "", \ - RSPAMD_LOG_FUNC, \ - __VA_ARGS__) + rspamd_dkim_log_id, "dkim", "", \ + RSPAMD_LOG_FUNC, \ + __VA_ARGS__) INIT_LOG_MODULE(dkim) @@ -790,12 +790,12 @@ rspamd_dkim_add_arc_seal_headers(rspamd_mempool_t *pool, } /** - * Create new dkim context from signature - * @param sig message's signature - * @param pool pool to allocate memory from - * @param err pointer to error object - * @return new context or NULL - */ +* Create new dkim context from signature +* @param sig message's signature +* @param pool pool to allocate memory from +* @param err pointer to error object +* @return new context or NULL +*/ rspamd_dkim_context_t * rspamd_create_dkim_context(const char *sig, rspamd_mempool_t *pool, @@ -1097,9 +1097,9 @@ rspamd_create_dkim_context(const char *sig, if (state == DKIM_STATE_ERROR) { /* - * We need to return from here as state machine won't - * do any more steps after p == end - */ + * We need to return from here as state machine won't + * do any more steps after p == end + */ if (err) { msg_info_dkim("dkim parse failed: %e", *err); } @@ -1430,8 +1430,8 @@ rspamd_dkim_make_key(const char *keydata, return NULL; } - if (type == RSPAMD_DKIM_KEY_RSA) { +#if OPENSSL_VERSION_MAJOR < 3 key->key.key_rsa = EVP_PKEY_get1_RSA(key->key_evp); if (key->key.key_rsa == NULL) { @@ -1443,8 +1443,10 @@ rspamd_dkim_make_key(const char *keydata, return NULL; } +#endif } else { +#if OPENSSL_VERSION_MAJOR < 3 key->key.key_ecdsa = EVP_PKEY_get1_EC_KEY(key->key_evp); if (key->key.key_ecdsa == NULL) { @@ -1456,7 +1458,9 @@ rspamd_dkim_make_key(const char *keydata, return NULL; } +#endif } + } return key; @@ -1473,15 +1477,16 @@ rspamd_dkim_key_id(rspamd_dkim_key_t *key) } /** - * Free DKIM key - * @param key - */ +* Free DKIM key +* @param key +*/ void rspamd_dkim_key_free(rspamd_dkim_key_t *key) { if (key->key_evp) { EVP_PKEY_free(key->key_evp); } +#if OPENSSL_VERSION_MAJOR < 3 if (key->type == RSPAMD_DKIM_KEY_RSA) { if (key->key.key_rsa) { RSA_free(key->key.key_rsa); @@ -1492,6 +1497,7 @@ void rspamd_dkim_key_free(rspamd_dkim_key_t *key) EC_KEY_free(key->key.key_ecdsa); } } +#endif /* Nothing in case of eddsa key */ if (key->key_bio) { BIO_free(key->key_bio); @@ -1507,11 +1513,13 @@ void rspamd_dkim_sign_key_free(rspamd_dkim_sign_key_t *key) if (key->key_evp) { EVP_PKEY_free(key->key_evp); } +#if OPENSSL_VERSION_MAJOR < 3 if (key->type == RSPAMD_DKIM_KEY_RSA) { if (key->key.key_rsa) { RSA_free(key->key.key_rsa); } } +#endif if (key->key_bio) { BIO_free(key->key_bio); } @@ -1570,9 +1578,9 @@ rspamd_dkim_parse_key(const char *txt, gsize *keylen, GError **err) break; case read_tag_before_eqsign: /* Input: spaces before eqsign - * Output: either read a next tag (previous had no value), or read value - * p is moved forward - */ + * Output: either read a next tag (previous had no value), or read value + * p is moved forward + */ if (*p == '=') { state = read_eqsign; } @@ -1759,12 +1767,12 @@ rspamd_dkim_dns_cb(struct rdns_reply *reply, gpointer arg) } /** - * Make DNS request for specified context and obtain and parse key - * @param ctx dkim context from signature - * @param resolver dns resolver object - * @param s async session to make request - * @return - */ +* Make DNS request for specified context and obtain and parse key +* @param ctx dkim context from signature +* @param resolver dns resolver object +* @param s async session to make request +* @return +*/ gboolean rspamd_get_dkim_key(rspamd_dkim_context_t *ctx, struct rspamd_task *task, @@ -2187,8 +2195,8 @@ rspamd_dkim_canonize_body(struct rspamd_task *task, ; /* - * If we have l= tag then we cannot add crlf... - */ + * If we have l= tag then we cannot add crlf... + */ if (need_crlf) { /* l is evil... */ if (ctx->len == 0) { @@ -2461,9 +2469,9 @@ rspamd_dkim_canonize_header(struct rspamd_dkim_common_ctx *ctx, bool use_idx = false, is_sign = ctx->is_sign; /* - * TODO: - * Temporary hack to prevent linked list being misused until refactored - */ + * TODO: + * Temporary hack to prevent linked list being misused until refactored + */ const unsigned int max_list_iters = 1000; if (count < 0) { @@ -2509,17 +2517,17 @@ rspamd_dkim_canonize_header(struct rspamd_dkim_common_ctx *ctx, if (hdr_cnt <= count) { /* - * If DKIM has less headers requested than there are in a - * message, then it's fine, it allows adding extra headers - */ + * If DKIM has less headers requested than there are in a + * message, then it's fine, it allows adding extra headers + */ return TRUE; } } else { /* - * This branch is used for ARC headers, and it orders them based on - * i=<number> string and not their real order in the list of headers - */ + * This branch is used for ARC headers, and it orders them based on + * i=<number> string and not their real order in the list of headers + */ char idx_buf[16]; int id_len, i; @@ -2692,12 +2700,12 @@ rspamd_dkim_type_to_string(enum rspamd_dkim_type t) } /** - * Check task for dkim context using dkim key - * @param ctx dkim verify context - * @param key dkim key (from cache or from dns request) - * @param task task to check - * @return - */ +* Check task for dkim context using dkim key +* @param ctx dkim verify context +* @param key dkim key (from cache or from dns request) +* @param task task to check +* @return +*/ struct rspamd_dkim_check_result * rspamd_dkim_check(rspamd_dkim_context_t *ctx, rspamd_dkim_key_t *key, @@ -2916,6 +2924,7 @@ rspamd_dkim_check(rspamd_dkim_context_t *ctx, switch (key->type) { case RSPAMD_DKIM_KEY_RSA: +#if OPENSSL_VERSION_MAJOR < 3 if (RSA_verify(nid, raw_digest, dlen, ctx->b, ctx->blen, key->key.key_rsa) != 1) { msg_debug_dkim("headers rsa verify failed"); @@ -2933,8 +2942,28 @@ rspamd_dkim_check(rspamd_dkim_context_t *ctx, 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) { + msg_debug_dkim("headers rsa verify failed"); + ERR_clear_error(); + res->rcode = DKIM_REJECT; + res->fail_reason = "headers rsa verify failed"; + + 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); + } +#endif break; case RSPAMD_DKIM_KEY_ECDSA: +#if OPENSSL_VERSION_MAJOR < 3 if (ECDSA_verify(nid, raw_digest, dlen, ctx->b, ctx->blen, key->key.key_ecdsa) != 1) { msg_info_dkim( @@ -2951,7 +2980,26 @@ rspamd_dkim_check(rspamd_dkim_context_t *ctx, res->rcode = DKIM_REJECT; res->fail_reason = "headers ecdsa verify failed"; } +#else + if (rspamd_cryptobox_verify_compat(nid, ctx->b, ctx->blen, raw_digest, dlen, + key->key_evp, 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", + 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); + msg_debug_dkim("headers ecdsa verify failed"); + ERR_clear_error(); + res->rcode = DKIM_REJECT; + res->fail_reason = "headers ecdsa verify failed"; + } +#endif break; + case RSPAMD_DKIM_KEY_EDDSA: if (!rspamd_cryptobox_verify(ctx->b, ctx->blen, raw_digest, dlen, key->key.key_eddsa, RSPAMD_CRYPTOBOX_MODE_25519)) { @@ -3200,6 +3248,7 @@ rspamd_dkim_sign_key_load(const char *key, gsize len, goto end; } } +#if OPENSSL_VERSION_MAJOR < 3 nkey->key.key_rsa = EVP_PKEY_get1_RSA(nkey->key_evp); if (nkey->key.key_rsa == NULL) { g_set_error(err, @@ -3212,6 +3261,7 @@ rspamd_dkim_sign_key_load(const char *key, gsize len, goto end; } nkey->type = RSPAMD_DKIM_KEY_RSA; +#endif } REF_INIT_RETAIN(nkey, rspamd_dkim_sign_key_free); @@ -3536,7 +3586,9 @@ rspamd_dkim_sign(struct rspamd_task *task, const char *selector, dlen = EVP_MD_CTX_size(ctx->common.headers_hash); EVP_DigestFinal_ex(ctx->common.headers_hash, raw_digest, NULL); + if (ctx->key->type == RSPAMD_DKIM_KEY_RSA) { +#if OPENSSL_VERSION_MAJOR < 3 sig_len = RSA_size(ctx->key->key.key_rsa); sig_buf = g_alloca(sig_len); @@ -3548,6 +3600,13 @@ rspamd_dkim_sign(struct rspamd_task *task, const char *selector, return NULL; } +#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"); +#endif } else if (ctx->key->type == RSPAMD_DKIM_KEY_EDDSA) { sig_len = rspamd_cryptobox_signature_bytes(RSPAMD_CRYPTOBOX_MODE_25519); @@ -3601,11 +3660,19 @@ rspamd_dkim_match_keys(rspamd_dkim_key_t *pk, return FALSE; } } +#if OPENSSL_VERSION_MAJOR >= 3 + else if (EVP_PKEY_eq(pk->key_evp, sk->key_evp) != 1) { + g_set_error(err, dkim_error_quark(), DKIM_SIGERROR_KEYHASHMISMATCH, + "pubkey does not match private key"); + return FALSE; + } +#else else if (EVP_PKEY_cmp(pk->key_evp, sk->key_evp) != 1) { g_set_error(err, dkim_error_quark(), DKIM_SIGERROR_KEYHASHMISMATCH, "pubkey does not match private key"); return FALSE; } +#endif return TRUE; } |