diff --git a/SOURCES/cyrus-sasl-2.1.27-cumulative-digestmd5.patch b/SOURCES/cyrus-sasl-2.1.27-cumulative-digestmd5.patch
new file mode 100644
index 0000000..d61130f
--- /dev/null
+++ b/SOURCES/cyrus-sasl-2.1.27-cumulative-digestmd5.patch
@@ -0,0 +1,544 @@
+diff -uPr cyrus-sasl-2.1.27/plugins/digestmd5.c cyrus-sasl-2.1.27.digestmd5/plugins/digestmd5.c
+--- cyrus-sasl-2.1.27/plugins/digestmd5.c	2021-09-30 17:13:06.573093526 -0400
++++ cyrus-sasl-2.1.27.digestmd5/plugins/digestmd5.c	2021-09-30 17:26:31.818378442 -0400
+@@ -80,6 +80,12 @@
+ # endif
+ #endif /* WITH_DES */
+ 
++/* legacy provider with openssl 3.0 */
++#if OPENSSL_VERSION_NUMBER >= 0x30000000L
++#  include <openssl/provider.h>
++#  include <openssl/crypto.h>
++#endif
++
+ #ifdef WIN32
+ # include <winsock2.h>
+ #else /* Unix */
+@@ -170,6 +176,12 @@
+ 
+ typedef struct cipher_context cipher_context_t;
+ 
++typedef struct crypto_context {
++    void *libctx;
++    cipher_context_t *enc_ctx;
++    cipher_context_t *dec_ctx;
++} crypto_context_t;
++
+ /* cached auth info used for fast reauth */
+ typedef struct reauth_entry {
+     char *authid;
+@@ -254,12 +266,12 @@
+     decode_context_t decode_context;
+ 
+     /* if privacy mode is used use these functions for encode and decode */
++    char *cipher_name;
+     cipher_function_t *cipher_enc;
+     cipher_function_t *cipher_dec;
+     cipher_init_t *cipher_init;
+     cipher_free_t *cipher_free;
+-    struct cipher_context *cipher_enc_context;
+-    struct cipher_context *cipher_dec_context;
++    crypto_context_t crypto;
+ } context_t;
+ 
+ struct digest_cipher {
+@@ -888,7 +900,7 @@
+ 		    char *output,
+ 		    unsigned *outputlen)
+ {
+-    des_context_t *c = (des_context_t *) text->cipher_dec_context;
++    des_context_t *c = (des_context_t *) text->crypto.dec_ctx;
+     int padding, p;
+     
+     des_ede2_cbc_encrypt((void *) input,
+@@ -925,7 +937,7 @@
+ 		    char *output,
+ 		    unsigned *outputlen)
+ {
+-    des_context_t *c = (des_context_t *) text->cipher_enc_context;
++    des_context_t *c = (des_context_t *) text->crypto.enc_ctx;
+     int len;
+     int paddinglen;
+     
+@@ -973,7 +985,7 @@
+ 	return SASL_FAIL;
+     memcpy(c->ivec, ((char *) enckey) + 8, 8);
+ 
+-    text->cipher_enc_context = (cipher_context_t *) c;
++    text->crypto.enc_ctx = (cipher_context_t *) c;
+ 
+     /* setup dec context */
+     c++;
+@@ -987,7 +999,7 @@
+     
+     memcpy(c->ivec, ((char *) deckey) + 8, 8);
+ 
+-    text->cipher_dec_context = (cipher_context_t *) c;
++    text->crypto.dec_ctx = (cipher_context_t *) c;
+     
+     return SASL_OK;
+ }
+@@ -1006,7 +1018,7 @@
+ 		   char *output,
+ 		   unsigned *outputlen)
+ {
+-    des_context_t *c = (des_context_t *) text->cipher_dec_context;
++    des_context_t *c = (des_context_t *) text->crypto.dec_ctx;
+     int p, padding = 0;
+     
+     des_cbc_encrypt((void *) input,
+@@ -1046,7 +1058,7 @@
+ 		   char *output,
+ 		   unsigned *outputlen)
+ {
+-    des_context_t *c = (des_context_t *) text->cipher_enc_context;
++    des_context_t *c = (des_context_t *) text->crypto.enc_ctx;
+     int len;
+     int paddinglen;
+   
+@@ -1093,7 +1105,7 @@
+ 
+     memcpy(c->ivec, ((char *) enckey) + 8, 8);
+     
+-    text->cipher_enc_context = (cipher_context_t *) c;
++    text->crypto.enc_ctx = (cipher_context_t *) c;
+ 
+     /* setup dec context */
+     c++;
+@@ -1102,60 +1114,139 @@
+ 
+     memcpy(c->ivec, ((char *) deckey) + 8, 8);
+     
+-    text->cipher_dec_context = (cipher_context_t *) c;
++    text->crypto.dec_ctx = (cipher_context_t *) c;
+ 
+     return SASL_OK;
+ }
+ 
+ static void free_des(context_t *text)
+ {
+-    /* free des contextss. only cipher_enc_context needs to be free'd,
+-       since cipher_dec_context was allocated at the same time. */
+-    if (text->cipher_enc_context) text->utils->free(text->cipher_enc_context);
++    /* free des contextss. only enc_ctx needs to be free'd,
++       since dec_cxt was allocated at the same time. */
++    if (text->crypto.enc_ctx) {
++        text->utils->free(text->crypto.enc_ctx);
++    }
+ }
+ 
+ #endif /* WITH_DES */
+ 
+ #ifdef WITH_RC4
+-#ifdef HAVE_OPENSSL
+ #include <openssl/evp.h>
+ 
++#if OPENSSL_VERSION_NUMBER >= 0x30000000L
++typedef struct ossl3_library_context {
++    OSSL_LIB_CTX *libctx;
++    OSSL_PROVIDER *legacy_provider;
++    OSSL_PROVIDER *default_provider;
++} ossl3_context_t;
++
++static int init_ossl3_ctx(context_t *text)
++{
++    ossl3_context_t *ctx = text->utils->malloc(sizeof(ossl3_context_t));
++    if (!ctx) return SASL_NOMEM;
++
++    ctx->libctx = OSSL_LIB_CTX_new();
++    if (!ctx->libctx) {
++        text->utils->free(ctx);
++        return SASL_FAIL;
++    }
++
++    /* Load both legacy and default provider as both may be needed */
++    /* if they fail keep going and an error will be raised when we try to
++     * fetch the cipher later */
++    ctx->legacy_provider = OSSL_PROVIDER_load(ctx->libctx, "legacy");
++    ctx->default_provider = OSSL_PROVIDER_load(ctx->libctx, "default");
++    text->crypto.libctx = (void *)ctx;
++
++    return SASL_OK;
++}
++
++static void free_ossl3_ctx(context_t *text)
++{
++    ossl3_context_t *ctx;
++
++    if (!text->crypto.libctx) return;
++
++    ctx = (ossl3_context_t *)text->crypto.libctx;
++
++    if (ctx->legacy_provider) OSSL_PROVIDER_unload(ctx->legacy_provider);
++    if (ctx->default_provider) OSSL_PROVIDER_unload(ctx->default_provider);
++    if (ctx->libctx) OSSL_LIB_CTX_free(ctx->libctx);
++
++    text->utils->free(ctx);
++    text->crypto.libctx = NULL;
++}
++#endif
++
+ static void free_rc4(context_t *text)
+ {
+-    if (text->cipher_enc_context) {
+-        EVP_CIPHER_CTX_free((EVP_CIPHER_CTX *)text->cipher_enc_context);
+-        text->cipher_enc_context = NULL;
+-    }
+-    if (text->cipher_dec_context) {
+-        EVP_CIPHER_CTX_free((EVP_CIPHER_CTX *)text->cipher_dec_context);
+-        text->cipher_dec_context = NULL;
++    if (text->crypto.enc_ctx) {
++        EVP_CIPHER_CTX_free((EVP_CIPHER_CTX *)text->crypto.enc_ctx);
++        text->crypto.enc_ctx = NULL;
++    }
++    if (text->crypto.dec_ctx) {
++        EVP_CIPHER_CTX_free((EVP_CIPHER_CTX *)text->crypto.dec_ctx);
++        text->crypto.dec_ctx = NULL;
+     }
++#if OPENSSL_VERSION_NUMBER >= 0x30000000L
++    free_ossl3_ctx(text);
++#endif
+ }
+ 
+ static int init_rc4(context_t *text,
+ 		    unsigned char enckey[16],
+ 		    unsigned char deckey[16])
+ {
++    const EVP_CIPHER *cipher;
+     EVP_CIPHER_CTX *ctx;
+     int rc;
+ 
+-    ctx = EVP_CIPHER_CTX_new();
+-    if (ctx == NULL) return SASL_NOMEM;
++#if OPENSSL_VERSION_NUMBER >= 0x30000000L
++    ossl3_context_t *ossl3_ctx;
+ 
+-    rc = EVP_EncryptInit_ex(ctx, EVP_rc4(), NULL, enckey, NULL);
+-    if (rc != 1) return SASL_FAIL;
++    rc = init_ossl3_ctx(text);
++    if (rc != SASL_OK) return rc;
++
++    ossl3_ctx = (ossl3_context_t *)text->crypto.libctx;
++    cipher = EVP_CIPHER_fetch(ossl3_ctx->libctx, "RC4", "");
++#else
++    cipher = EVP_rc4();
++#endif
+ 
+-    text->cipher_enc_context = (void *)ctx;
+ 
+     ctx = EVP_CIPHER_CTX_new();
+-    if (ctx == NULL) return SASL_NOMEM;
++    if (ctx == NULL) {
++        rc = SASL_NOMEM;
++        goto done;
++    }
+ 
+-    rc = EVP_DecryptInit_ex(ctx, EVP_rc4(), NULL, deckey, NULL);
+-    if (rc != 1) return SASL_FAIL;
++    rc = EVP_EncryptInit_ex(ctx, cipher, NULL, enckey, NULL);
++    if (rc != 1) {
++        rc = SASL_FAIL;
++        goto done;
++    }
++    text->crypto.enc_ctx = (void *)ctx;
+ 
+-    text->cipher_dec_context = (void *)ctx;
++    ctx = EVP_CIPHER_CTX_new();
++    if (ctx == NULL) {
++        rc = SASL_NOMEM;
++        goto done;
++    }
+ 
+-    return SASL_OK;
++    rc = EVP_DecryptInit_ex(ctx, cipher, NULL, deckey, NULL);
++    if (rc != 1) {
++        rc = SASL_FAIL;
++        goto done;
++    }
++    text->crypto.dec_ctx = (void *)ctx;
++
++    rc = SASL_OK;
++
++done:
++    if (rc != SASL_OK) {
++        free_rc4(text);
++    }
++    return rc;
+ }
+ 
+ static int dec_rc4(context_t *text,
+@@ -1169,14 +1260,14 @@
+     int rc;
+ 
+     /* decrypt the text part & HMAC */
+-    rc = EVP_DecryptUpdate((EVP_CIPHER_CTX *)text->cipher_dec_context,
++    rc = EVP_DecryptUpdate((EVP_CIPHER_CTX *)text->crypto.dec_ctx,
+                            (unsigned char *)output, &len,
+                            (const unsigned char *)input, inputlen);
+     if (rc != 1) return SASL_FAIL;
+ 
+     *outputlen = len;
+ 
+-    rc = EVP_DecryptFinal_ex((EVP_CIPHER_CTX *)text->cipher_dec_context,
++    rc = EVP_DecryptFinal_ex((EVP_CIPHER_CTX *)text->crypto.dec_ctx,
+                              (unsigned char *)output + len, &len);
+     if (rc != 1) return SASL_FAIL;
+ 
+@@ -1198,7 +1289,7 @@
+     int len;
+     int rc;
+     /* encrypt the text part */
+-    rc = EVP_EncryptUpdate((EVP_CIPHER_CTX *)text->cipher_enc_context,
++    rc = EVP_EncryptUpdate((EVP_CIPHER_CTX *)text->crypto.enc_ctx,
+                            (unsigned char *)output, &len,
+                            (const unsigned char *)input, inputlen);
+     if (rc != 1) return SASL_FAIL;
+@@ -1206,14 +1297,14 @@
+     *outputlen = len;
+ 
+     /* encrypt the `MAC part */
+-    rc = EVP_EncryptUpdate((EVP_CIPHER_CTX *)text->cipher_enc_context,
++    rc = EVP_EncryptUpdate((EVP_CIPHER_CTX *)text->crypto.enc_ctx,
+                            (unsigned char *)output + *outputlen, &len,
+                            digest, 10);
+     if (rc != 1) return SASL_FAIL;
+ 
+     *outputlen += len;
+ 
+-    rc = EVP_EncryptFinal_ex((EVP_CIPHER_CTX *)text->cipher_enc_context,
++    rc = EVP_EncryptFinal_ex((EVP_CIPHER_CTX *)text->crypto.enc_ctx,
+                              (unsigned char *)output + *outputlen, &len);
+     if (rc != 1) return SASL_FAIL;
+ 
+@@ -1221,188 +1312,11 @@
+ 
+     return SASL_OK;
+ }
+-#else
+-/* quick generic implementation of RC4 */
+-struct rc4_context_s {
+-    unsigned char sbox[256];
+-    int i, j;
+-};
+-
+-typedef struct rc4_context_s rc4_context_t;
+-
+-static void rc4_init(rc4_context_t *text,
+-		     const unsigned char *key,
+-		     unsigned keylen)
+-{
+-    int i, j;
+-    
+-    /* fill in linearly s0=0 s1=1... */
+-    for (i=0;i<256;i++)
+-	text->sbox[i]=i;
+-    
+-    j=0;
+-    for (i = 0; i < 256; i++) {
+-	unsigned char tmp;
+-	/* j = (j + Si + Ki) mod 256 */
+-	j = (j + text->sbox[i] + key[i % keylen]) % 256;
+-	
+-	/* swap Si and Sj */
+-	tmp = text->sbox[i];
+-	text->sbox[i] = text->sbox[j];
+-	text->sbox[j] = tmp;
+-    }
+-    
+-    /* counters initialized to 0 */
+-    text->i = 0;
+-    text->j = 0;
+-}
+-
+-static void rc4_encrypt(rc4_context_t *text,
+-			const char *input,
+-			char *output,
+-			unsigned len)
+-{
+-    int tmp;
+-    int i = text->i;
+-    int j = text->j;
+-    int t;
+-    int K;
+-    const char *input_end = input + len;
+-    
+-    while (input < input_end) {
+-	i = (i + 1) % 256;
+-	
+-	j = (j + text->sbox[i]) % 256;
+-	
+-	/* swap Si and Sj */
+-	tmp = text->sbox[i];
+-	text->sbox[i] = text->sbox[j];
+-	text->sbox[j] = tmp;
+-	
+-	t = (text->sbox[i] + text->sbox[j]) % 256;
+-	
+-	K = text->sbox[t];
+-	
+-	/* byte K is Xor'ed with plaintext */
+-	*output++ = *input++ ^ K;
+-    }
+-    
+-    text->i = i;
+-    text->j = j;
+-}
+-
+-static void rc4_decrypt(rc4_context_t *text,
+-			const char *input,
+-			char *output,
+-			unsigned len)
+-{
+-    int tmp;
+-    int i = text->i;
+-    int j = text->j;
+-    int t;
+-    int K;
+-    const char *input_end = input + len;
+-    
+-    while (input < input_end) {
+-	i = (i + 1) % 256;
+-	
+-	j = (j + text->sbox[i]) % 256;
+-	
+-	/* swap Si and Sj */
+-	tmp = text->sbox[i];
+-	text->sbox[i] = text->sbox[j];
+-	text->sbox[j] = tmp;
+-	
+-	t = (text->sbox[i] + text->sbox[j]) % 256;
+-	
+-	K = text->sbox[t];
+-	
+-	/* byte K is Xor'ed with plaintext */
+-	*output++ = *input++ ^ K;
+-    }
+-    
+-    text->i = i;
+-    text->j = j;
+-}
+-
+-static void free_rc4(context_t *text)
+-{
+-    /* free rc4 context structures */
+-
+-    if(text->cipher_enc_context) text->utils->free(text->cipher_enc_context);
+-    if(text->cipher_dec_context) text->utils->free(text->cipher_dec_context);
+-}
+-
+-static int init_rc4(context_t *text, 
+-		    unsigned char enckey[16],
+-		    unsigned char deckey[16])
+-{
+-    /* allocate rc4 context structures */
+-    text->cipher_enc_context=
+-	(cipher_context_t *) text->utils->malloc(sizeof(rc4_context_t));
+-    if (text->cipher_enc_context == NULL) return SASL_NOMEM;
+-    
+-    text->cipher_dec_context=
+-	(cipher_context_t *) text->utils->malloc(sizeof(rc4_context_t));
+-    if (text->cipher_dec_context == NULL) return SASL_NOMEM;
+-    
+-    /* initialize them */
+-    rc4_init((rc4_context_t *) text->cipher_enc_context,
+-             (const unsigned char *) enckey, 16);
+-    rc4_init((rc4_context_t *) text->cipher_dec_context,
+-             (const unsigned char *) deckey, 16);
+-    
+-    return SASL_OK;
+-}
+-
+-static int dec_rc4(context_t *text,
+-		   const char *input,
+-		   unsigned inputlen,
+-		   unsigned char digest[16] __attribute__((unused)),
+-		   char *output,
+-		   unsigned *outputlen)
+-{
+-    /* decrypt the text part & HMAC */
+-    rc4_decrypt((rc4_context_t *) text->cipher_dec_context, 
+-                input, output, inputlen);
+-
+-    /* no padding so we just subtract the HMAC to get the text length */
+-    *outputlen = inputlen - 10;
+-    
+-    return SASL_OK;
+-}
+-
+-static int enc_rc4(context_t *text,
+-		   const char *input,
+-		   unsigned inputlen,
+-		   unsigned char digest[16],
+-		   char *output,
+-		   unsigned *outputlen)
+-{
+-    /* pad is zero */
+-    *outputlen = inputlen+10;
+-    
+-    /* encrypt the text part */
+-    rc4_encrypt((rc4_context_t *) text->cipher_enc_context,
+-                input,
+-                output,
+-                inputlen);
+-    
+-    /* encrypt the HMAC part */
+-    rc4_encrypt((rc4_context_t *) text->cipher_enc_context, 
+-                (const char *) digest, 
+-		(output)+inputlen, 10);
+-    
+-    return SASL_OK;
+-}
+-#endif /* HAVE_OPENSSL */
+ #endif /* WITH_RC4 */
+ 
+ struct digest_cipher available_ciphers[] =
+ {
+ #ifdef WITH_RC4
+-    { "rc4-40", 40, 5, 0x01, &enc_rc4, &dec_rc4, &init_rc4, &free_rc4 },
+-    { "rc4-56", 56, 7, 0x02, &enc_rc4, &dec_rc4, &init_rc4, &free_rc4 },
+     { "rc4", 128, 16, 0x04, &enc_rc4, &dec_rc4, &init_rc4, &free_rc4 },
+ #endif
+ #ifdef WITH_DES
+@@ -2815,6 +2729,7 @@
+ 	}
+ 	
+ 	if (cptr->name) {
++	    text->cipher_name = cptr->name;
+ 	    text->cipher_enc = cptr->cipher_enc;
+ 	    text->cipher_dec = cptr->cipher_dec;
+ 	    text->cipher_init = cptr->cipher_init;
+@@ -2958,7 +2873,10 @@
+ 	if (text->cipher_init) {
+ 	    if (text->cipher_init(text, enckey, deckey) != SASL_OK) {
+ 		sparams->utils->seterror(sparams->utils->conn, 0,
+-					 "couldn't init cipher");
++					 "couldn't init cipher '%s'",
++                                         text->cipher_name);
++                result = SASL_FAIL;
++                goto FreeAllMem;
+ 	    }
+ 	}
+     }
+@@ -3509,6 +3427,7 @@
+ 	oparams->mech_ssf = ctext->cipher->ssf;
+ 
+ 	nbits = ctext->cipher->n;
++	text->cipher_name = ctext->cipher->name;
+ 	text->cipher_enc = ctext->cipher->cipher_enc;
+ 	text->cipher_dec = ctext->cipher->cipher_dec;
+ 	text->cipher_free = ctext->cipher->cipher_free;
+@@ -3733,7 +3652,13 @@
+ 	
+ 	/* initialize cipher if need be */
+ 	if (text->cipher_init) {
+-	    text->cipher_init(text, enckey, deckey);
++	    if (text->cipher_init(text, enckey, deckey) != SASL_OK) {
++	        params->utils->seterror(params->utils->conn, 0,
++		         "internal error: failed to init cipher '%s'",
++                         text->cipher_name);
++                result = SASL_FAIL;
++                goto FreeAllocatedMem;
++            }
+ 	}
+     }
+     
diff --git a/SOURCES/cyrus-sasl-2.1.27-cumulative-ossl3.patch b/SOURCES/cyrus-sasl-2.1.27-cumulative-ossl3.patch
new file mode 100644
index 0000000..10b57cc
--- /dev/null
+++ b/SOURCES/cyrus-sasl-2.1.27-cumulative-ossl3.patch
@@ -0,0 +1,109 @@
+diff -uPr cyrus-sasl-2.1.27/configure.ac cyrus-sasl-2.1.27.ossl3/configure.ac
+--- cyrus-sasl-2.1.27/configure.ac	2021-10-06 11:29:53.274375206 -0400
++++ cyrus-sasl-2.1.27.ossl3/configure.ac	2021-10-06 11:31:19.966726775 -0400
+@@ -1115,7 +1115,11 @@
+ 	with_rc4=yes)
+ 
+ if test "$with_rc4" != no; then
+-    AC_DEFINE(WITH_RC4,[],[Use RC4])
++    if test "$with_openssl" = no; then
++        AC_WARN([OpenSSL not found -- RC4 will be disabled])
++    else
++        AC_DEFINE(WITH_RC4,[],[Use RC4])
++    fi
+ fi
+ 
+ building_for_macosx=no
+diff -uPr cyrus-sasl-2.1.27/plugins/scram.c cyrus-sasl-2.1.27.ossl3/plugins/scram.c
+--- cyrus-sasl-2.1.27/plugins/scram.c	2018-11-08 12:29:57.000000000 -0500
++++ cyrus-sasl-2.1.27.ossl3/plugins/scram.c	2021-10-06 11:31:04.407484201 -0400
+@@ -65,7 +65,9 @@
+ 
+ #include <openssl/sha.h>
+ #include <openssl/evp.h>
++#if OPENSSL_VERSION_NUMBER < 0x30000000L
+ #include <openssl/hmac.h>
++#endif
+ 
+ /*****************************  Common Section  *****************************/
+ 
+@@ -267,6 +271,32 @@
+ }
+ #endif
+ 
++#if OPENSSL_VERSION_NUMBER >= 0x30000000L
++
++/* Decalre as void given functions never use the result */
++void *HMAC(const EVP_MD *evp_md, const void *key, int key_len,
++                     const unsigned char *data, size_t data_len,
++                     unsigned char *md, unsigned int *md_len)
++{
++    const char *digest;
++    size_t digest_size;
++    size_t out_len;
++    void *ret = NULL;
++
++    digest = EVP_MD_get0_name(evp_md);
++    if (digest == NULL) {
++        return NULL;
++    }
++    digest_size = EVP_MD_size(evp_md);
++
++    ret = EVP_Q_mac(NULL, "hmac", NULL, digest, NULL, key, key_len,
++                    data, data_len, md, digest_size, &out_len);
++    if (ret != NULL) {
++        *md_len = (unsigned int)out_len;
++    }
++    return ret;
++}
++#endif
+ 
+ /* The result variable need to point to a buffer big enough for the [SHA-1] hash */
+ static void
+diff -uPr cyrus-sasl-2.1.27/saslauthd/lak.c cyrus-sasl-2.1.27.ossl3/saslauthd/lak.c
+--- cyrus-sasl-2.1.27/saslauthd/lak.c	2022-01-09 11:30:50.000000000 -0400
++++ cyrus-sasl-2.1.27.ossl3/saslauthd/lak.c	2022-01-09 11:30:50.000000001 -0400
+@@ -1806,18 +1806,36 @@
+ 		return rc;
+ 	}
+ 
+-	EVP_DigestInit(mdctx, md);
+-	EVP_DigestUpdate(mdctx, passwd, strlen(passwd));
++	rc = EVP_DigestInit(mdctx, md);
++	if (rc != 1) {
++		rc = LAK_FAIL;
++		goto done;
++	}
++	rc = EVP_DigestUpdate(mdctx, passwd, strlen(passwd));
++	if (rc != 1) {
++		rc = LAK_FAIL;
++		goto done;
++	}
+ 	if (hrock->salted) {
+-		EVP_DigestUpdate(mdctx, &cred[EVP_MD_size(md)],
+-				 clen - EVP_MD_size(md));
++		rc = EVP_DigestUpdate(mdctx, &cred[EVP_MD_size(md)],
++				      clen - EVP_MD_size(md));
++		if (rc != 1) {
++		    rc = LAK_FAIL;
++		    goto done;
++		}
++	}
++	rc = EVP_DigestFinal(mdctx, digest, NULL);
++	if (rc != 1) {
++		rc = LAK_FAIL;
++		goto done;
+ 	}
+-	EVP_DigestFinal(mdctx, digest, NULL);
+-	EVP_MD_CTX_free(mdctx);
+ 
+ 	rc = memcmp((char *)cred, (char *)digest, EVP_MD_size(md));
++	rc = rc ? LAK_INVALID_PASSWORD : LAK_OK;
++done:
++	EVP_MD_CTX_free(mdctx);
+ 	free(cred);
+-	return rc ? LAK_INVALID_PASSWORD : LAK_OK;
++	return rc;
+ }
+ 
+ #endif /* HAVE_OPENSSL */
diff --git a/SOURCES/cyrus-sasl-2.1.27-fix-for-autoconf270.patch b/SOURCES/cyrus-sasl-2.1.27-fix-for-autoconf270.patch
new file mode 100644
index 0000000..3c6e7be
--- /dev/null
+++ b/SOURCES/cyrus-sasl-2.1.27-fix-for-autoconf270.patch
@@ -0,0 +1,74 @@
+From 3b0149cf3d235247b051b7cb7663bc3dadbb999b Mon Sep 17 00:00:00 2001
+From: Pavel Raiskup <praiskup@redhat.com>
+Date: Thu, 1 Apr 2021 17:17:52 +0200
+Subject: [PATCH] configure.ac: avoid side-effects in AC_CACHE_VAL
+
+In the COMMANDS-TO-SET-IT argument, per Autoconf docs:
+https://www.gnu.org/software/autoconf/manual/autoconf-2.63/html_node/Caching-Results.html
+---
+ configure.ac | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index a106d35e..d333496d 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -220,11 +220,14 @@ void foo() { int i=0;}
+ int main() { void *self, *ptr1, *ptr2; self=dlopen(NULL,RTLD_LAZY);
+     if(self) { ptr1=dlsym(self,"foo"); ptr2=dlsym(self,"_foo");
+     if(ptr1 && !ptr2) exit(0); } exit(1); } 
+-], [sasl_cv_dlsym_adds_uscore=yes], sasl_cv_dlsym_adds_uscore=no
+-	AC_DEFINE(DLSYM_NEEDS_UNDERSCORE, [], [Do we need a leading _ for dlsym?]),
++], [sasl_cv_dlsym_adds_uscore=yes], sasl_cv_dlsym_adds_uscore=no,
+ 	AC_MSG_WARN(cross-compiler, we'll do our best)))
+ 	LIBS="$cmu_save_LIBS"
+       AC_MSG_RESULT($sasl_cv_dlsym_adds_uscore)
++
++      if test "$sasl_cv_dlsym_adds_uscore" = no; then
++        AC_DEFINE(DLSYM_NEEDS_UNDERSCORE, [], [Do we need a leading _ for dlsym?])
++      fi
+   fi
+ fi
+ 
+From d3bcaf62f6213e7635e9c4a574f39a831e333980 Mon Sep 17 00:00:00 2001
+From: Pavel Raiskup <praiskup@redhat.com>
+Date: Thu, 1 Apr 2021 17:26:28 +0200
+Subject: [PATCH] configure.ac: properly quote macro arguments
+
+Autoconf 2.70+ is more picky about the quotation (even though with
+previous versions the arguments should have been quoted, too).  When we
+don't quote macros inside the AC_CACHE_VAL macro - some of the Autoconf
+initialization is wrongly ordered in ./configure script and we keep
+seeing bugs like:
+
+    ./configure: line 2165: ac_fn_c_try_run: command not found
+
+Original report: https://bugzilla.redhat.com/1943013
+---
+ configure.ac | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index d333496d..7281cba0 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -213,15 +213,16 @@ if test $sasl_cv_uscore = yes; then
+ 	AC_MSG_CHECKING(whether dlsym adds the underscore for us)
+ 	cmu_save_LIBS="$LIBS"
+ 	LIBS="$LIBS $SASL_DL_LIB"
+-	AC_CACHE_VAL(sasl_cv_dlsym_adds_uscore,AC_TRY_RUN( [
++	AC_CACHE_VAL([sasl_cv_dlsym_adds_uscore],
++	             [AC_TRY_RUN([
+ #include <dlfcn.h>
+ #include <stdio.h>
+ void foo() { int i=0;}
+ int main() { void *self, *ptr1, *ptr2; self=dlopen(NULL,RTLD_LAZY);
+     if(self) { ptr1=dlsym(self,"foo"); ptr2=dlsym(self,"_foo");
+     if(ptr1 && !ptr2) exit(0); } exit(1); } 
+-], [sasl_cv_dlsym_adds_uscore=yes], sasl_cv_dlsym_adds_uscore=no,
+-	AC_MSG_WARN(cross-compiler, we'll do our best)))
++], [sasl_cv_dlsym_adds_uscore=yes], [sasl_cv_dlsym_adds_uscore=no],
++	[AC_MSG_WARN(cross-compiler, we'll do our best)])])
+ 	LIBS="$cmu_save_LIBS"
+       AC_MSG_RESULT($sasl_cv_dlsym_adds_uscore)
+ 
diff --git a/SOURCES/cyrus-sasl-2.1.27-legacy-init.patch b/SOURCES/cyrus-sasl-2.1.27-legacy-init.patch
deleted file mode 100644
index 371408e..0000000
--- a/SOURCES/cyrus-sasl-2.1.27-legacy-init.patch
+++ /dev/null
@@ -1,73 +0,0 @@
-From 4edb8ce82ac530f473a8728bae01d9fc8535c9cb Mon Sep 17 00:00:00 2001
-From: Simo Sorce <simo@redhat.com>
-Date: Mon, 21 Jun 2021 14:24:18 -0400
-Subject: [PATCH] Gracefully handle failed initializations
-
-In OpenSSL 3.0 these algorithms have been moved to the legacy provider
-which is not enabled by default. This means allocation can and do fail.
-Handle failed allocations by returning an actual error instead of
-crashing later with a NULL context.
-
-Signed-off-by: Simo Sorce <simo@redhat.com>
----
- plugins/digestmd5.c | 16 ++++++++++++++--
- 1 file changed, 14 insertions(+), 2 deletions(-)
-
-diff --git a/plugins/digestmd5.c b/plugins/digestmd5.c
-index c6b54317..b2617536 100644
---- a/plugins/digestmd5.c
-+++ b/plugins/digestmd5.c
-@@ -254,6 +254,7 @@ typedef struct context {
-     decode_context_t decode_context;
- 
-     /* if privacy mode is used use these functions for encode and decode */
-+    char *cipher_name;
-     cipher_function_t *cipher_enc;
-     cipher_function_t *cipher_dec;
-     cipher_init_t *cipher_init;
-@@ -2821,6 +2822,7 @@ static int digestmd5_server_mech_step2(server_context_t *stext,
- 	}
- 	
- 	if (cptr->name) {
-+	    text->cipher_name = cptr->name;
- 	    text->cipher_enc = cptr->cipher_enc;
- 	    text->cipher_dec = cptr->cipher_dec;
- 	    text->cipher_init = cptr->cipher_init;
-@@ -2964,7 +2966,10 @@ static int digestmd5_server_mech_step2(server_context_t *stext,
- 	if (text->cipher_init) {
- 	    if (text->cipher_init(text, enckey, deckey) != SASL_OK) {
- 		sparams->utils->seterror(sparams->utils->conn, 0,
--					 "couldn't init cipher");
-+					 "couldn't init cipher '%s'",
-+                                         text->cipher_name);
-+                result = SASL_FAIL;
-+                goto FreeAllMem;
- 	    }
- 	}
-     }
-@@ -3515,6 +3520,7 @@ static int make_client_response(context_t *text,
- 	oparams->mech_ssf = ctext->cipher->ssf;
- 
- 	nbits = ctext->cipher->n;
-+	text->cipher_name = ctext->cipher->name;
- 	text->cipher_enc = ctext->cipher->cipher_enc;
- 	text->cipher_dec = ctext->cipher->cipher_dec;
- 	text->cipher_free = ctext->cipher->cipher_free;
-@@ -3739,7 +3745,13 @@ static int make_client_response(context_t *text,
- 	
- 	/* initialize cipher if need be */
- 	if (text->cipher_init) {
--	    text->cipher_init(text, enckey, deckey);
-+	    if (text->cipher_init(text, enckey, deckey) != SASL_OK) {
-+	        params->utils->seterror(params->utils->conn, 0,
-+		         "internal error: failed to init cipher '%s'",
-+                         text->cipher_name);
-+                result = SASL_FAIL;
-+                goto FreeAllocatedMem;
-+            }
- 	}
-     }
-     
--- 
-2.31.1
-
diff --git a/SPECS/cyrus-sasl.spec b/SPECS/cyrus-sasl.spec
index 0b62996..7475aa3 100644
--- a/SPECS/cyrus-sasl.spec
+++ b/SPECS/cyrus-sasl.spec
@@ -9,7 +9,7 @@
 Summary: The Cyrus SASL library
 Name: cyrus-sasl
 Version: 2.1.27
-Release: 17%{?dist}
+Release: 19%{?dist}
 License: BSD with advertising
 URL: https://www.cyrusimap.org/sasl/
 
@@ -25,7 +25,6 @@ Source10: make-no-dlcompatorsrp-tarball.sh
 # https://raw.githubusercontent.com/cyrusimap/cyrus-sasl/master/autogen.sh
 Source11: autogen.sh
 
-Requires: %{name}-lib%{?_isa} = %{version}-%{release}
 Patch11: cyrus-sasl-2.1.25-no_rpath.patch
 Patch15: cyrus-sasl-2.1.20-saslauthd.conf-path.patch
 Patch23: cyrus-sasl-2.1.23-man.patch
@@ -39,17 +38,19 @@ Patch101: cyrus-sasl-2.1.27-Add-basic-test-infrastructure.patch
 Patch102: cyrus-sasl-2.1.27-Add-Channel-Binding-support-for-GSSAPI-GSS-SPNEGO.patch
 Patch103: cyrus-sasl-2.1.27-Add-support-for-setting-max-ssf-0-to-GSS-SPNEGO.patch
 Patch104: cyrus-sasl-2.1.27-Emit-debug-log-only-in-case-of-errors.patch
+Patch105: cyrus-sasl-2.1.27-fix-for-autoconf270.patch
 #https://github.com/simo5/cyrus-sasl/commit/ebd2387f06c84c7f9aac3167ec041bb01e5c6e48
-Patch105: cyrus-sasl-2.1.27-nostrncpy.patch
-#Migration tool should be removed from RHEL10
-Patch106: cyrus-sasl-2.1.27-Migration-from-BerkeleyDB.patch
+Patch106: cyrus-sasl-2.1.27-nostrncpy.patch
 # Upstream PR: https://github.com/cyrusimap/cyrus-sasl/pull/635
 Patch107: cyrus-sasl-2.1.27-Add-basic-test-plain-auth.patch
+#Migration tool should be removed from RHEL10
+Patch108: cyrus-sasl-2.1.27-Migration-from-BerkeleyDB.patch
 Patch500: cyrus-sasl-2.1.27-coverity.patch
-Patch501: cyrus-sasl-2.1.27-legacy-init.patch
+Patch501: cyrus-sasl-2.1.27-cumulative-digestmd5.patch
+Patch502: cyrus-sasl-2.1.27-cumulative-ossl3.patch
 
 BuildRequires: autoconf, automake, libtool, gdbm-devel, groff
-BuildRequires: krb5-devel >= 1.2.2, openssl-devel, pam-devel, pkgconfig
+BuildRequires: krb5-devel >= 1.19, openssl-devel, pam-devel, pkgconfig
 BuildRequires: mariadb-connector-c-devel, libpq-devel, zlib-devel
 %if ! %{bootstrap_cyrus_sasl}
 BuildRequires: openldap-devel
@@ -60,10 +61,14 @@ BuildRequires: libdb-devel-static
 #build reqs for make check
 BuildRequires: python3 nss_wrapper socket_wrapper krb5-server
 %{?systemd_requires}
+
+Requires: %{name}-lib = %{version}-%{release}
+Requires: systemd
+
+#Requires/Provides related to the saslauthd user creation
+Requires: /sbin/nologin
 Requires(pre): /usr/sbin/useradd /usr/sbin/groupadd
 Requires(postun): /usr/sbin/userdel /usr/sbin/groupdel
-Requires: /sbin/nologin
-Requires: systemd >= 211
 Provides: user(%username)
 Provides: group(%username)
 
@@ -81,8 +86,8 @@ The %{name}-lib package contains shared libraries which are needed by
 applications which use the Cyrus SASL library.
 
 %package devel
-Requires: %{name}-lib%{?_isa} = %{version}-%{release}
-Requires: %{name}%{?_isa} = %{version}-%{release}
+Requires: %{name}-lib = %{version}-%{release}
+Requires: %{name} = %{version}-%{release}
 Requires: pkgconfig
 Summary: Files needed for developing applications with Cyrus SASL
 
@@ -175,11 +180,13 @@ the GS2 authentication scheme.
 %patch102 -p1 -b .gssapi_cbs
 %patch103 -p1 -b .maxssf0
 %patch104 -p1 -b .nolog
-%patch105 -p1 -b .nostrncpy
-%patch106 -p1 -b .frombdb
+%patch105 -p1 -b .autoconf270
+%patch106 -p1 -b .nostrncpy
 %patch107 -p1 -b .plaintests
+%patch108 -p1 -b .frombdb
 %patch500 -p1 -b .coverity
-%patch501 -p1 -b .legacy_init
+%patch501 -p1 -b .digestmd5
+%patch502 -p1 -b .ossl3
 
 %build
 # reconfigure
@@ -391,6 +398,13 @@ getent passwd %{username} >/dev/null || useradd -r -g %{username} -d %{homedir} 
 %{_sbindir}/sasl2-shared-mechlist
 
 %changelog
+* Mon Feb  9 2022 Simo Sorce <simo@redhat.com> - 2.1.27-19
+- Fix a memleak in one of the OpenSSL 3 compat patches
+  found by covscan
+
+* Mon Feb  7 2022 Simo Sorce <simo@redhat.com> - 2.1.27-18
+- Update OpenSSL 3 related compatibility patch backports
+
 * Mon Aug 09 2021 Mohan Boddu <mboddu@redhat.com> - 2.1.27-17
 - Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
   Related: rhbz#1991688