From 8550d54fac848459d6797cc0f5d6e95ebc776ac6 Mon Sep 17 00:00:00 2001 From: Michal Hlavinka Date: Mon, 22 Mar 2021 19:30:17 +0100 Subject: [PATCH] do not use own implementation of HMAC, use OpenSSL --- dovecot-2.3.6-opensslhmac.patch | 763 ++++++++++++++++++++++++++++++++ dovecot.spec | 10 +- 2 files changed, 769 insertions(+), 4 deletions(-) create mode 100644 dovecot-2.3.6-opensslhmac.patch diff --git a/dovecot-2.3.6-opensslhmac.patch b/dovecot-2.3.6-opensslhmac.patch new file mode 100644 index 0000000..a95202e --- /dev/null +++ b/dovecot-2.3.6-opensslhmac.patch @@ -0,0 +1,763 @@ +diff -up dovecot-2.3.13/src/auth/auth-token.c.opensslhmac dovecot-2.3.13/src/auth/auth-token.c +--- dovecot-2.3.13/src/auth/auth-token.c.opensslhmac 2020-12-22 14:26:52.000000000 +0100 ++++ dovecot-2.3.13/src/auth/auth-token.c 2021-03-22 18:44:06.946142422 +0100 +@@ -161,17 +161,17 @@ void auth_token_deinit(void) + const char *auth_token_get(const char *service, const char *session_pid, + const char *username, const char *session_id) + { +- struct hmac_context ctx; ++ struct openssl_hmac_context ctx; + unsigned char result[SHA1_RESULTLEN]; + +- hmac_init(&ctx, (const unsigned char*)username, strlen(username), ++ openssl_hmac_init(&ctx, (const unsigned char*)username, strlen(username), + &hash_method_sha1); +- hmac_update(&ctx, session_pid, strlen(session_pid)); ++ openssl_hmac_update(&ctx, session_pid, strlen(session_pid)); + if (session_id != NULL && *session_id != '\0') +- hmac_update(&ctx, session_id, strlen(session_id)); +- hmac_update(&ctx, service, strlen(service)); +- hmac_update(&ctx, auth_token_secret, sizeof(auth_token_secret)); +- hmac_final(&ctx, result); ++ openssl_hmac_update(&ctx, session_id, strlen(session_id)); ++ openssl_hmac_update(&ctx, service, strlen(service)); ++ openssl_hmac_update(&ctx, auth_token_secret, sizeof(auth_token_secret)); ++ openssl_hmac_final(&ctx, result); + + return binary_to_hex(result, sizeof(result)); + } +diff -up dovecot-2.3.13/src/auth/mech-cram-md5.c.opensslhmac dovecot-2.3.13/src/auth/mech-cram-md5.c +--- dovecot-2.3.13/src/auth/mech-cram-md5.c.opensslhmac 2020-12-22 14:26:52.000000000 +0100 ++++ dovecot-2.3.13/src/auth/mech-cram-md5.c 2021-03-22 18:44:06.946142422 +0100 +@@ -51,7 +51,7 @@ static bool verify_credentials(struct cr + { + + unsigned char digest[MD5_RESULTLEN]; +- struct hmac_context ctx; ++ struct orig_hmac_context ctx; + const char *response_hex; + + if (size != CRAM_MD5_CONTEXTLEN) { +@@ -60,10 +60,10 @@ static bool verify_credentials(struct cr + return FALSE; + } + +- hmac_init(&ctx, NULL, 0, &hash_method_md5); ++ orig_hmac_init(&ctx, NULL, 0, &hash_method_md5); + hmac_md5_set_cram_context(&ctx, credentials); +- hmac_update(&ctx, request->challenge, strlen(request->challenge)); +- hmac_final(&ctx, digest); ++ orig_hmac_update(&ctx, request->challenge, strlen(request->challenge)); ++ orig_hmac_final(&ctx, digest); + + response_hex = binary_to_hex(digest, sizeof(digest)); + +diff -up dovecot-2.3.13/src/auth/mech-scram.c.opensslhmac dovecot-2.3.13/src/auth/mech-scram.c +--- dovecot-2.3.13/src/auth/mech-scram.c.opensslhmac 2020-12-22 14:26:52.000000000 +0100 ++++ dovecot-2.3.13/src/auth/mech-scram.c 2021-03-22 18:44:06.946142422 +0100 +@@ -78,7 +78,7 @@ static const char *get_scram_server_firs + static const char *get_scram_server_final(struct scram_auth_request *request) + { + const struct hash_method *hmethod = request->hash_method; +- struct hmac_context ctx; ++ struct openssl_hmac_context ctx; + const char *auth_message; + unsigned char server_signature[hmethod->digest_size]; + string_t *str; +@@ -87,9 +87,9 @@ static const char *get_scram_server_fina + request->server_first_message, ",", + request->client_final_message_without_proof, NULL); + +- hmac_init(&ctx, request->server_key, hmethod->digest_size, hmethod); +- hmac_update(&ctx, auth_message, strlen(auth_message)); +- hmac_final(&ctx, server_signature); ++ openssl_hmac_init(&ctx, request->server_key, hmethod->digest_size, hmethod); ++ openssl_hmac_update(&ctx, auth_message, strlen(auth_message)); ++ openssl_hmac_final(&ctx, server_signature); + + str = t_str_new(MAX_BASE64_ENCODED_SIZE(sizeof(server_signature))); + str_append(str, "v="); +@@ -228,7 +228,7 @@ static bool parse_scram_client_first(str + static bool verify_credentials(struct scram_auth_request *request) + { + const struct hash_method *hmethod = request->hash_method; +- struct hmac_context ctx; ++ struct openssl_hmac_context ctx; + const char *auth_message; + unsigned char client_key[hmethod->digest_size]; + unsigned char client_signature[hmethod->digest_size]; +@@ -239,9 +239,9 @@ static bool verify_credentials(struct sc + request->server_first_message, ",", + request->client_final_message_without_proof, NULL); + +- hmac_init(&ctx, request->stored_key, hmethod->digest_size, hmethod); +- hmac_update(&ctx, auth_message, strlen(auth_message)); +- hmac_final(&ctx, client_signature); ++ openssl_hmac_init(&ctx, request->stored_key, hmethod->digest_size, hmethod); ++ openssl_hmac_update(&ctx, auth_message, strlen(auth_message)); ++ openssl_hmac_final(&ctx, client_signature); + + const unsigned char *proof_data = request->proof->data; + for (i = 0; i < sizeof(client_signature); i++) +diff -up dovecot-2.3.13/src/auth/password-scheme.c.opensslhmac dovecot-2.3.13/src/auth/password-scheme.c +--- dovecot-2.3.13/src/auth/password-scheme.c.opensslhmac 2020-12-22 14:26:52.000000000 +0100 ++++ dovecot-2.3.13/src/auth/password-scheme.c 2021-03-22 18:44:06.947142409 +0100 +@@ -639,11 +639,11 @@ static void + cram_md5_generate(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED, + const unsigned char **raw_password_r, size_t *size_r) + { +- struct hmac_context ctx; ++ struct orig_hmac_context ctx; + unsigned char *context_digest; + + context_digest = t_malloc_no0(CRAM_MD5_CONTEXTLEN); +- hmac_init(&ctx, (const unsigned char *)plaintext, ++ orig_hmac_init(&ctx, (const unsigned char *)plaintext, + strlen(plaintext), &hash_method_md5); + hmac_md5_get_cram_context(&ctx, context_digest); + +diff -up dovecot-2.3.13/src/auth/password-scheme-scram.c.opensslhmac dovecot-2.3.13/src/auth/password-scheme-scram.c +--- dovecot-2.3.13/src/auth/password-scheme-scram.c.opensslhmac 2020-12-22 14:26:52.000000000 +0100 ++++ dovecot-2.3.13/src/auth/password-scheme-scram.c 2021-03-22 18:44:06.947142409 +0100 +@@ -30,23 +30,23 @@ Hi(const struct hash_method *hmethod, co + const unsigned char *salt, size_t salt_size, unsigned int i, + unsigned char *result) + { +- struct hmac_context ctx; ++ struct openssl_hmac_context ctx; + unsigned char U[hmethod->digest_size]; + unsigned int j, k; + + /* Calculate U1 */ +- hmac_init(&ctx, str, str_size, hmethod); +- hmac_update(&ctx, salt, salt_size); +- hmac_update(&ctx, "\0\0\0\1", 4); +- hmac_final(&ctx, U); ++ openssl_hmac_init(&ctx, str, str_size, hmethod); ++ openssl_hmac_update(&ctx, salt, salt_size); ++ openssl_hmac_update(&ctx, "\0\0\0\1", 4); ++ openssl_hmac_final(&ctx, U); + + memcpy(result, U, hmethod->digest_size); + + /* Calculate U2 to Ui and Hi */ + for (j = 2; j <= i; j++) { +- hmac_init(&ctx, str, str_size, hmethod); +- hmac_update(&ctx, U, sizeof(U)); +- hmac_final(&ctx, U); ++ openssl_hmac_init(&ctx, str, str_size, hmethod); ++ openssl_hmac_update(&ctx, U, sizeof(U)); ++ openssl_hmac_final(&ctx, U); + for (k = 0; k < hmethod->digest_size; k++) + result[k] ^= U[k]; + } +@@ -102,7 +102,7 @@ int scram_verify(const struct hash_metho + const char *plaintext, const unsigned char *raw_password, + size_t size, const char **error_r) + { +- struct hmac_context ctx; ++ struct openssl_hmac_context ctx; + const char *salt_base64; + unsigned int iter_count; + const unsigned char *salt; +@@ -126,9 +126,9 @@ int scram_verify(const struct hash_metho + salt, salt_len, iter_count, salted_password); + + /* Calculate ClientKey */ +- hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod); +- hmac_update(&ctx, "Client Key", 10); +- hmac_final(&ctx, client_key); ++ openssl_hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod); ++ openssl_hmac_update(&ctx, "Client Key", 10); ++ openssl_hmac_final(&ctx, client_key); + + /* Calculate StoredKey */ + hash_method_get_digest(hmethod, client_key, sizeof(client_key), +@@ -147,7 +147,7 @@ void scram_generate(const struct hash_me + const unsigned char **raw_password_r, size_t *size_r) + { + string_t *str; +- struct hmac_context ctx; ++ struct openssl_hmac_context ctx; + unsigned char salt[16]; + unsigned char salted_password[hmethod->digest_size]; + unsigned char client_key[hmethod->digest_size]; +@@ -165,9 +165,9 @@ void scram_generate(const struct hash_me + sizeof(salt), SCRAM_DEFAULT_ITERATE_COUNT, salted_password); + + /* Calculate ClientKey */ +- hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod); +- hmac_update(&ctx, "Client Key", 10); +- hmac_final(&ctx, client_key); ++ openssl_hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod); ++ openssl_hmac_update(&ctx, "Client Key", 10); ++ openssl_hmac_final(&ctx, client_key); + + /* Calculate StoredKey */ + hash_method_get_digest(hmethod, client_key, sizeof(client_key), +@@ -176,9 +176,9 @@ void scram_generate(const struct hash_me + base64_encode(stored_key, sizeof(stored_key), str); + + /* Calculate ServerKey */ +- hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod); +- hmac_update(&ctx, "Server Key", 10); +- hmac_final(&ctx, server_key); ++ openssl_hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod); ++ openssl_hmac_update(&ctx, "Server Key", 10); ++ openssl_hmac_final(&ctx, server_key); + str_append_c(str, ','); + base64_encode(server_key, sizeof(server_key), str); + +diff -up dovecot-2.3.13/src/lib/hmac.c.opensslhmac dovecot-2.3.13/src/lib/hmac.c +--- dovecot-2.3.13/src/lib/hmac.c.opensslhmac 2020-12-22 14:26:52.000000000 +0100 ++++ dovecot-2.3.13/src/lib/hmac.c 2021-03-22 18:44:06.947142409 +0100 +@@ -7,6 +7,10 @@ + * This software is released under the MIT license. + */ + ++#include ++#include ++#include ++#include + #include "lib.h" + #include "hmac.h" + #include "safe-memset.h" +@@ -14,10 +18,65 @@ + + #include "hex-binary.h" + +-void hmac_init(struct hmac_context *_ctx, const unsigned char *key, ++#ifndef HAVE_HMAC_CTX_NEW ++# define HMAC_Init_ex(ctx, key, key_len, md, impl) \ ++ HMAC_Init_ex(&(ctx), key, key_len, md, impl) ++# define HMAC_Update(ctx, data, len) HMAC_Update(&(ctx), data, len) ++# define HMAC_Final(ctx, md, len) HMAC_Final(&(ctx), md, len) ++# define HMAC_CTX_free(ctx) HMAC_cleanup(&(ctx)) ++#else ++# define HMAC_CTX_free(ctx) \ ++ STMT_START { HMAC_CTX_free(ctx); (ctx) = NULL; } STMT_END ++#endif ++ ++ ++void openssl_hmac_init(struct openssl_hmac_context *_ctx, const unsigned char *key, + size_t key_len, const struct hash_method *meth) + { +- struct hmac_context_priv *ctx = &_ctx->u.priv; ++ struct openssl_hmac_context_priv *ctx = &_ctx->u.priv; ++ ++ const EVP_MD *md; ++ const char *ebuf = NULL; ++ const char **error_r = &ebuf; ++ ++ md = EVP_get_digestbyname(meth->name); ++ if(md == NULL) { ++ if (error_r != NULL) { ++ *error_r = t_strdup_printf("Invalid digest %s", ++ meth->name); ++ } ++ //return FALSE; ++ } ++ ++// int ec; ++ ++ i_assert(md != NULL); ++#ifdef HAVE_HMAC_CTX_NEW ++ ctx->ctx = HMAC_CTX_new(); ++/* if (ctx->ctx == NULL) ++ dcrypt_openssl_error(error_r);*/ ++#endif ++ /*ec = */HMAC_Init_ex(ctx->ctx, key, key_len, md, NULL); ++} ++ ++void orig_hmac_init(struct orig_hmac_context *_ctx, const unsigned char *key, ++ size_t key_len, const struct hash_method *meth) ++{ ++ static int no_fips = -1; ++ if (no_fips == -1) { ++ int fd = open("/proc/sys/crypto/fips_enabled", O_RDONLY); ++ if (fd != -1) ++ { ++ char buf[4]; ++ if (read(fd, buf, 4) > 0) ++ { ++ no_fips = buf[0] == '0'; ++ } ++ close(fd); ++ } ++ } ++ i_assert(no_fips); ++ struct orig_hmac_context_priv *ctx = &_ctx->u.priv; + int i; + unsigned char k_ipad[64]; + unsigned char k_opad[64]; +@@ -53,9 +112,27 @@ void hmac_init(struct hmac_context *_ctx + safe_memset(k_opad, 0, 64); + } + +-void hmac_final(struct hmac_context *_ctx, unsigned char *digest) ++void openssl_hmac_final(struct openssl_hmac_context *_ctx, unsigned char *digest) ++{ ++ int ec; ++ unsigned char buf[HMAC_MAX_MD_CBLOCK]; ++ unsigned int outl; ++// const char *ebuf = NULL; ++// const char **error_r = &ebuf; ++ ++ struct openssl_hmac_context_priv *ctx = &_ctx->u.priv; ++ ec = HMAC_Final(ctx->ctx, buf, &outl); ++ HMAC_CTX_free(ctx->ctx); ++ if (ec == 1) ++ memcpy(digest, buf, outl); ++// else ++// dcrypt_openssl_error(error_r); ++ ++} ++ ++void orig_hmac_final(struct orig_hmac_context *_ctx, unsigned char *digest) + { +- struct hmac_context_priv *ctx = &_ctx->u.priv; ++ struct orig_hmac_context_priv *ctx = &_ctx->u.priv; + + ctx->hash->result(ctx->ctx, digest); + +@@ -63,53 +140,50 @@ void hmac_final(struct hmac_context *_ct + ctx->hash->result(ctx->ctxo, digest); + } + +-buffer_t *t_hmac_data(const struct hash_method *meth, ++buffer_t *openssl_t_hmac_data(const struct hash_method *meth, + const unsigned char *key, size_t key_len, + const void *data, size_t data_len) + { +- struct hmac_context ctx; ++ struct openssl_hmac_context ctx; + i_assert(meth != NULL); + i_assert(key != NULL && key_len > 0); + i_assert(data != NULL || data_len == 0); + + buffer_t *res = t_buffer_create(meth->digest_size); +- hmac_init(&ctx, key, key_len, meth); ++ openssl_hmac_init(&ctx, key, key_len, meth); + if (data_len > 0) +- hmac_update(&ctx, data, data_len); ++ openssl_hmac_update(&ctx, data, data_len); + unsigned char *buf = buffer_get_space_unsafe(res, 0, meth->digest_size); +- hmac_final(&ctx, buf); ++ openssl_hmac_final(&ctx, buf); + return res; + } + +-buffer_t *t_hmac_buffer(const struct hash_method *meth, ++buffer_t *openssl_t_hmac_buffer(const struct hash_method *meth, + const unsigned char *key, size_t key_len, + const buffer_t *data) + { +- return t_hmac_data(meth, key, key_len, data->data, data->used); ++ return openssl_t_hmac_data(meth, key, key_len, data->data, data->used); + } + +-buffer_t *t_hmac_str(const struct hash_method *meth, ++buffer_t *openssl_t_hmac_str(const struct hash_method *meth, + const unsigned char *key, size_t key_len, + const char *data) + { +- return t_hmac_data(meth, key, key_len, data, strlen(data)); ++ return openssl_t_hmac_data(meth, key, key_len, data, strlen(data)); + } + +-void hmac_hkdf(const struct hash_method *method, ++void openssl_hmac_hkdf(const struct hash_method *method, + const unsigned char *salt, size_t salt_len, + const unsigned char *ikm, size_t ikm_len, + const unsigned char *info, size_t info_len, + buffer_t *okm_r, size_t okm_len) + { ++ const EVP_MD *md; ++ EVP_PKEY_CTX *pctx; ++ int r = 1; ++ + i_assert(method != NULL); + i_assert(okm_len < 255*method->digest_size); +- struct hmac_context key_mac; +- struct hmac_context info_mac; +- size_t remain = okm_len; +- unsigned char prk[method->digest_size]; +- unsigned char okm[method->digest_size]; +- /* N = ceil(L/HashLen) */ +- unsigned int rounds = (okm_len + method->digest_size - 1)/method->digest_size; + + /* salt and info can be NULL */ + i_assert(salt != NULL || salt_len == 0); +@@ -118,35 +192,30 @@ void hmac_hkdf(const struct hash_method + i_assert(ikm != NULL && ikm_len > 0); + i_assert(okm_r != NULL && okm_len > 0); + +- /* but they still need valid pointer, reduces +- complains from static analysers */ +- if (salt == NULL) +- salt = &uchar_nul; +- if (info == NULL) +- info = &uchar_nul; +- +- /* extract */ +- hmac_init(&key_mac, salt, salt_len, method); +- hmac_update(&key_mac, ikm, ikm_len); +- hmac_final(&key_mac, prk); +- +- /* expand */ +- for (unsigned int i = 0; remain > 0 && i < rounds; i++) { +- unsigned char round = (i+1); +- size_t amt = remain; +- if (amt > method->digest_size) +- amt = method->digest_size; +- hmac_init(&info_mac, prk, method->digest_size, method); +- if (i > 0) +- hmac_update(&info_mac, okm, method->digest_size); +- hmac_update(&info_mac, info, info_len); +- hmac_update(&info_mac, &round, 1); +- memset(okm, 0, method->digest_size); +- hmac_final(&info_mac, okm); +- buffer_append(okm_r, okm, amt); +- remain -= amt; ++ ++ md = EVP_get_digestbyname(method->name); ++ pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL); ++ unsigned char *okm_buf = buffer_get_space_unsafe(okm_r, 0, okm_len); ++ ++ if ((r=EVP_PKEY_derive_init(pctx)) <= 0) ++ goto out; ++ if ((r=EVP_PKEY_CTX_set_hkdf_md(pctx, md)) <= 0) ++ goto out; ++ if ((r=EVP_PKEY_CTX_set1_hkdf_salt(pctx, salt, salt_len)) <= 0) ++ goto out; ++ if ((r=EVP_PKEY_CTX_set1_hkdf_key(pctx, ikm, ikm_len)) <= 0) ++ goto out; ++ if ((r=EVP_PKEY_CTX_add1_hkdf_info(pctx, info, info_len)) <= 0) ++ goto out; ++ if ((r=EVP_PKEY_derive(pctx, okm_buf, &okm_len)) <= 0) ++ goto out; ++ ++ out: ++ EVP_PKEY_CTX_free(pctx); ++ if (r <= 0) { ++ unsigned long ec = ERR_get_error(); ++ unsigned char *error = t_strdup_printf("%s", ERR_error_string(ec, NULL)); ++ i_error("%s", error); + } + +- safe_memset(prk, 0, sizeof(prk)); +- safe_memset(okm, 0, sizeof(okm)); + } +diff -up dovecot-2.3.13/src/lib/hmac-cram-md5.c.opensslhmac dovecot-2.3.13/src/lib/hmac-cram-md5.c +--- dovecot-2.3.13/src/lib/hmac-cram-md5.c.opensslhmac 2020-12-22 14:26:52.000000000 +0100 ++++ dovecot-2.3.13/src/lib/hmac-cram-md5.c 2021-03-22 18:44:06.947142409 +0100 +@@ -9,10 +9,10 @@ + #include "md5.h" + #include "hmac-cram-md5.h" + +-void hmac_md5_get_cram_context(struct hmac_context *_hmac_ctx, ++void hmac_md5_get_cram_context(struct orig_hmac_context *_hmac_ctx, + unsigned char context_digest[CRAM_MD5_CONTEXTLEN]) + { +- struct hmac_context_priv *hmac_ctx = &_hmac_ctx->u.priv; ++ struct orig_hmac_context_priv *hmac_ctx = &_hmac_ctx->u.priv; + unsigned char *cdp; + + struct md5_context *ctx = (void*)hmac_ctx->ctx; +@@ -35,10 +35,10 @@ void hmac_md5_get_cram_context(struct hm + CDPUT(cdp, ctx->d); + } + +-void hmac_md5_set_cram_context(struct hmac_context *_hmac_ctx, ++void hmac_md5_set_cram_context(struct orig_hmac_context *_hmac_ctx, + const unsigned char context_digest[CRAM_MD5_CONTEXTLEN]) + { +- struct hmac_context_priv *hmac_ctx = &_hmac_ctx->u.priv; ++ struct orig_hmac_context_priv *hmac_ctx = &_hmac_ctx->u.priv; + const unsigned char *cdp; + + struct md5_context *ctx = (void*)hmac_ctx->ctx; +diff -up dovecot-2.3.13/src/lib/hmac-cram-md5.h.opensslhmac dovecot-2.3.13/src/lib/hmac-cram-md5.h +--- dovecot-2.3.13/src/lib/hmac-cram-md5.h.opensslhmac 2020-12-22 14:26:52.000000000 +0100 ++++ dovecot-2.3.13/src/lib/hmac-cram-md5.h 2021-03-22 18:44:06.947142409 +0100 +@@ -5,9 +5,9 @@ + + #define CRAM_MD5_CONTEXTLEN 32 + +-void hmac_md5_get_cram_context(struct hmac_context *ctx, ++void hmac_md5_get_cram_context(struct orig_hmac_context *ctx, + unsigned char context_digest[CRAM_MD5_CONTEXTLEN]); +-void hmac_md5_set_cram_context(struct hmac_context *ctx, ++void hmac_md5_set_cram_context(struct orig_hmac_context *ctx, + const unsigned char context_digest[CRAM_MD5_CONTEXTLEN]); + + +diff -up dovecot-2.3.13/src/lib/hmac.h.opensslhmac dovecot-2.3.13/src/lib/hmac.h +--- dovecot-2.3.13/src/lib/hmac.h.opensslhmac 2020-12-22 14:26:52.000000000 +0100 ++++ dovecot-2.3.13/src/lib/hmac.h 2021-03-22 18:44:06.947142409 +0100 +@@ -3,60 +3,97 @@ + + #include "hash-method.h" + #include "sha1.h" ++#include ++#include ++#include ++#include + + #define HMAC_MAX_CONTEXT_SIZE 256 + +-struct hmac_context_priv { ++struct openssl_hmac_context_priv { ++#ifdef HAVE_HMAC_CTX_NEW ++ HMAC_CTX *ctx; ++#else ++ HMAC_CTX ctx; ++#endif ++ const struct hash_method *hash; ++}; ++ ++struct orig_hmac_context_priv { + char ctx[HMAC_MAX_CONTEXT_SIZE]; + char ctxo[HMAC_MAX_CONTEXT_SIZE]; + const struct hash_method *hash; + }; + +-struct hmac_context { ++struct openssl_hmac_context { ++ union { ++ struct openssl_hmac_context_priv priv; ++ uint64_t padding_requirement; ++ } u; ++}; ++ ++struct orig_hmac_context { + union { +- struct hmac_context_priv priv; ++ struct orig_hmac_context_priv priv; + uint64_t padding_requirement; + } u; + }; + +-void hmac_init(struct hmac_context *ctx, const unsigned char *key, ++void openssl_hmac_init(struct openssl_hmac_context *ctx, const unsigned char *key, ++ size_t key_len, const struct hash_method *meth); ++void openssl_hmac_final(struct openssl_hmac_context *ctx, unsigned char *digest); ++ ++static inline void ++openssl_hmac_update(struct openssl_hmac_context *_ctx, const void *data, size_t size) ++{ ++ struct openssl_hmac_context_priv *ctx = &_ctx->u.priv; ++ HMAC_Update(ctx->ctx, data, size); ++/* if (ec != 1) ++ { ++ const char *ebuf = NULL; ++ const char **error_r = &ebuf; ++ dcrypt_openssl_error(error_r); ++ }*/ ++} ++ ++void orig_hmac_init(struct orig_hmac_context *ctx, const unsigned char *key, + size_t key_len, const struct hash_method *meth); +-void hmac_final(struct hmac_context *ctx, unsigned char *digest); ++void orig_hmac_final(struct orig_hmac_context *ctx, unsigned char *digest); + + + static inline void +-hmac_update(struct hmac_context *_ctx, const void *data, size_t size) ++orig_hmac_update(struct orig_hmac_context *_ctx, const void *data, size_t size) + { +- struct hmac_context_priv *ctx = &_ctx->u.priv; ++ struct orig_hmac_context_priv *ctx = &_ctx->u.priv; + + ctx->hash->loop(ctx->ctx, data, size); + } + +-buffer_t *t_hmac_data(const struct hash_method *meth, ++buffer_t *openssl_t_hmac_data(const struct hash_method *meth, + const unsigned char *key, size_t key_len, + const void *data, size_t data_len); +-buffer_t *t_hmac_buffer(const struct hash_method *meth, ++buffer_t *openssl_t_hmac_buffer(const struct hash_method *meth, + const unsigned char *key, size_t key_len, + const buffer_t *data); +-buffer_t *t_hmac_str(const struct hash_method *meth, ++buffer_t *openssl_t_hmac_str(const struct hash_method *meth, + const unsigned char *key, size_t key_len, + const char *data); + +-void hmac_hkdf(const struct hash_method *method, ++void openssl_hmac_hkdf(const struct hash_method *method, + const unsigned char *salt, size_t salt_len, + const unsigned char *ikm, size_t ikm_len, + const unsigned char *info, size_t info_len, + buffer_t *okm_r, size_t okm_len); + + static inline buffer_t * +-t_hmac_hkdf(const struct hash_method *method, ++openssl_t_hmac_hkdf(const struct hash_method *method, + const unsigned char *salt, size_t salt_len, + const unsigned char *ikm, size_t ikm_len, + const unsigned char *info, size_t info_len, + size_t okm_len) + { + buffer_t *okm_buffer = t_buffer_create(okm_len); +- hmac_hkdf(method, salt, salt_len, ikm, ikm_len, info, info_len, ++ openssl_hmac_hkdf(method, salt, salt_len, ikm, ikm_len, info, info_len, + okm_buffer, okm_len); + return okm_buffer; + } +diff -up dovecot-2.3.13/src/lib-imap-urlauth/imap-urlauth.c.opensslhmac dovecot-2.3.13/src/lib-imap-urlauth/imap-urlauth.c +--- dovecot-2.3.13/src/lib-imap-urlauth/imap-urlauth.c.opensslhmac 2020-12-22 14:26:52.000000000 +0100 ++++ dovecot-2.3.13/src/lib-imap-urlauth/imap-urlauth.c 2021-03-22 18:44:06.948142396 +0100 +@@ -85,15 +85,15 @@ imap_urlauth_internal_generate(const cha + const unsigned char mailbox_key[IMAP_URLAUTH_KEY_LEN], + size_t *token_len_r) + { +- struct hmac_context hmac; ++ struct openssl_hmac_context hmac; + unsigned char *token; + + token = t_new(unsigned char, SHA1_RESULTLEN + 1); + token[0] = IMAP_URLAUTH_MECH_INTERNAL_VERSION; + +- hmac_init(&hmac, mailbox_key, IMAP_URLAUTH_KEY_LEN, &hash_method_sha1); +- hmac_update(&hmac, rumpurl, strlen(rumpurl)); +- hmac_final(&hmac, token+1); ++ openssl_hmac_init(&hmac, mailbox_key, IMAP_URLAUTH_KEY_LEN, &hash_method_sha1); ++ openssl_hmac_update(&hmac, rumpurl, strlen(rumpurl)); ++ openssl_hmac_final(&hmac, token+1); + + *token_len_r = SHA1_RESULTLEN + 1; + return token; +diff -up dovecot-2.3.13/src/lib/Makefile.am.opensslhmac dovecot-2.3.13/src/lib/Makefile.am +--- dovecot-2.3.13/src/lib/Makefile.am.opensslhmac 2020-12-22 14:26:52.000000000 +0100 ++++ dovecot-2.3.13/src/lib/Makefile.am 2021-03-22 18:44:06.948142396 +0100 +@@ -352,6 +352,9 @@ headers = \ + wildcard-match.h \ + write-full.h + ++liblib_la_LIBADD = $(SSL_LIBS) ++liblib_la_CFLAGS = $(SSL_CFLAGS) ++ + test_programs = test-lib + noinst_PROGRAMS = $(test_programs) + +diff -up dovecot-2.3.13/src/lib-oauth2/oauth2-jwt.c.opensslhmac dovecot-2.3.13/src/lib-oauth2/oauth2-jwt.c +--- dovecot-2.3.13/src/lib-oauth2/oauth2-jwt.c.opensslhmac 2021-03-22 18:46:42.645100171 +0100 ++++ dovecot-2.3.13/src/lib-oauth2/oauth2-jwt.c 2021-03-22 18:46:42.657100014 +0100 +@@ -96,14 +96,14 @@ static int oauth2_validate_hmac(const st + const buffer_t *key; + if (oauth2_lookup_hmac_key(set, azp, alg, key_id, &key, error_r) < 0) + return -1; +- struct hmac_context ctx; +- hmac_init(&ctx, key->data, key->used, method); +- hmac_update(&ctx, blobs[0], strlen(blobs[0])); +- hmac_update(&ctx, ".", 1); +- hmac_update(&ctx, blobs[1], strlen(blobs[1])); ++ struct openssl_hmac_context ctx; ++ openssl_hmac_init(&ctx, key->data, key->used, method); ++ openssl_hmac_update(&ctx, blobs[0], strlen(blobs[0])); ++ openssl_hmac_update(&ctx, ".", 1); ++ openssl_hmac_update(&ctx, blobs[1], strlen(blobs[1])); + unsigned char digest[method->digest_size]; + +- hmac_final(&ctx, digest); ++ openssl_hmac_final(&ctx, digest); + + buffer_t *their_digest = + t_base64url_decode_str(BASE64_DECODE_FLAG_NO_PADDING, blobs[2]); +diff -up dovecot-2.3.13/src/lib-oauth2/test-oauth2-jwt.c.opensslhmac dovecot-2.3.13/src/lib-oauth2/test-oauth2-jwt.c +--- dovecot-2.3.13/src/lib-oauth2/test-oauth2-jwt.c.opensslhmac 2020-12-22 14:26:52.000000000 +0100 ++++ dovecot-2.3.13/src/lib-oauth2/test-oauth2-jwt.c 2021-03-22 18:44:06.948142396 +0100 +@@ -219,7 +219,7 @@ static void save_key_to(const char *algo + static void sign_jwt_token_hs256(buffer_t *tokenbuf, buffer_t *key) + { + i_assert(key != NULL); +- buffer_t *sig = t_hmac_buffer(&hash_method_sha256, key->data, key->used, ++ buffer_t *sig = openssl_t_hmac_buffer(&hash_method_sha256, key->data, key->used, + tokenbuf); + buffer_append(tokenbuf, ".", 1); + base64url_encode(BASE64_ENCODE_FLAG_NO_PADDING, SIZE_MAX, +diff -up dovecot-2.3.13/src/lib/pkcs5.c.opensslhmac dovecot-2.3.13/src/lib/pkcs5.c +--- dovecot-2.3.13/src/lib/pkcs5.c.opensslhmac 2020-12-22 14:26:52.000000000 +0100 ++++ dovecot-2.3.13/src/lib/pkcs5.c 2021-03-22 18:44:06.948142396 +0100 +@@ -52,7 +52,7 @@ int pkcs5_pbkdf2(const struct hash_metho + size_t l = (length + hash->digest_size - 1)/hash->digest_size; /* same as ceil(length/hash->digest_size) */ + unsigned char dk[l * hash->digest_size]; + unsigned char *block; +- struct hmac_context hctx; ++ struct openssl_hmac_context hctx; + unsigned int c,i,t; + unsigned char U_c[hash->digest_size]; + +@@ -60,17 +60,17 @@ int pkcs5_pbkdf2(const struct hash_metho + block = &(dk[t*hash->digest_size]); + /* U_1 = PRF(Password, Salt|| INT_BE32(Block_Number)) */ + c = htonl(t+1); +- hmac_init(&hctx, password, password_len, hash); +- hmac_update(&hctx, salt, salt_len); +- hmac_update(&hctx, &c, sizeof(c)); +- hmac_final(&hctx, U_c); ++ openssl_hmac_init(&hctx, password, password_len, hash); ++ openssl_hmac_update(&hctx, salt, salt_len); ++ openssl_hmac_update(&hctx, &c, sizeof(c)); ++ openssl_hmac_final(&hctx, U_c); + /* block = U_1 ^ .. ^ U_iter */ + memcpy(block, U_c, hash->digest_size); + /* U_c = PRF(Password, U_c-1) */ + for(c = 1; c < iter; c++) { +- hmac_init(&hctx, password, password_len, hash); +- hmac_update(&hctx, U_c, hash->digest_size); +- hmac_final(&hctx, U_c); ++ openssl_hmac_init(&hctx, password, password_len, hash); ++ openssl_hmac_update(&hctx, U_c, hash->digest_size); ++ openssl_hmac_final(&hctx, U_c); + for(i = 0; i < hash->digest_size; i++) + block[i] ^= U_c[i]; + } +diff -up dovecot-2.3.13/src/lib/test-hmac.c.opensslhmac dovecot-2.3.13/src/lib/test-hmac.c +--- dovecot-2.3.13/src/lib/test-hmac.c.opensslhmac 2020-12-22 14:26:52.000000000 +0100 ++++ dovecot-2.3.13/src/lib/test-hmac.c 2021-03-22 18:44:06.948142396 +0100 +@@ -112,11 +112,11 @@ static void test_hmac_rfc(void) + test_begin("hmac sha256 rfc4231 vectors"); + for(size_t i = 0; i < N_ELEMENTS(test_vectors); i++) { + const struct test_vector *vec = &(test_vectors[i]); +- struct hmac_context ctx; +- hmac_init(&ctx, vec->key, vec->key_len, hash_method_lookup(vec->prf)); +- hmac_update(&ctx, vec->data, vec->data_len); ++ struct openssl_hmac_context ctx; ++ openssl_hmac_init(&ctx, vec->key, vec->key_len, hash_method_lookup(vec->prf)); ++ openssl_hmac_update(&ctx, vec->data, vec->data_len); + unsigned char res[SHA256_RESULTLEN]; +- hmac_final(&ctx, res); ++ openssl_hmac_final(&ctx, res); + test_assert_idx(memcmp(res, vec->res, vec->res_len) == 0, i); + } + test_end(); +@@ -129,7 +129,7 @@ static void test_hmac_buffer(void) + + buffer_t *tmp; + +- tmp = t_hmac_data(hash_method_lookup(vec->prf), vec->key, vec->key_len, ++ tmp = openssl_t_hmac_data(hash_method_lookup(vec->prf), vec->key, vec->key_len, + vec->data, vec->data_len); + + test_assert(tmp->used == vec->res_len && +@@ -146,7 +146,7 @@ static void test_hkdf_rfc(void) + buffer_set_used_size(res, 0); + const struct test_vector_5869 *vec = &(test_vectors_5869[i]); + const struct hash_method *m = hash_method_lookup(vec->prf); +- hmac_hkdf(m, vec->salt, vec->salt_len, vec->ikm, vec->ikm_len, ++ openssl_hmac_hkdf(m, vec->salt, vec->salt_len, vec->ikm, vec->ikm_len, + vec->info, vec->info_len, res, vec->okm_len); + test_assert_idx(memcmp(res->data, vec->okm, vec->okm_len) == 0, i); + } +@@ -159,7 +159,7 @@ static void test_hkdf_buffer(void) + test_begin("hkdf temporary buffer"); + const struct test_vector_5869 *vec = &(test_vectors_5869[0]); + const struct hash_method *m = hash_method_lookup(vec->prf); +- buffer_t *tmp = t_hmac_hkdf(m, vec->salt, vec->salt_len, vec->ikm, ++ buffer_t *tmp = openssl_t_hmac_hkdf(m, vec->salt, vec->salt_len, vec->ikm, + vec->ikm_len, vec->info, vec->info_len, + vec->okm_len); + test_assert(tmp->used == vec->okm_len && diff --git a/dovecot.spec b/dovecot.spec index 6ee95b3..7e769e6 100644 --- a/dovecot.spec +++ b/dovecot.spec @@ -35,6 +35,11 @@ Patch10: dovecot-2.3.0.1-libxcrypt.patch Patch15: dovecot-2.3.11-bigkey.patch Patch16: dovecot-2.3.13-bigtvsec.patch +# do not use own implementation of HMAC, use OpenSSL for certification purposes +# not sent upstream as proper fix would use dovecot's lib-dcrypt but it introduces +# hard to break circular dependency between lib and lib-dcrypt +Patch17: dovecot-2.3.6-opensslhmac.patch + Source15: prestartscript BuildRequires: gcc, gcc-c++, openssl-devel, pam-devel, zlib-devel, bzip2-devel, libcap-devel @@ -121,12 +126,9 @@ This package provides the development files for dovecot. %patch6 -p1 -b .waitonline %patch8 -p1 -b .initbysystemd %patch9 -p1 -b .systemd_w_protectsystem -#%patch10 -p1 -b .libxcrypt -#patch12 -p1 -b .ftbfs1 -#patch13 -p1 -b .ftbfs2 -#patch14 -p1 -b .gssapi %patch15 -p1 -b .bigkey %patch16 -p1 -b .bigtvsec +%patch17 -p1 -b .opensslhmac #pushd dovecot-2*3-pigeonhole-%{pigeonholever} #popd