diff --git a/SOURCES/Use-OpenSSL-s-KBKDF-and-KRB5KDF-for-deriving-long-te.patch b/SOURCES/Use-OpenSSL-s-KBKDF-and-KRB5KDF-for-deriving-long-te.patch
index 927b506..12b4967 100644
--- a/SOURCES/Use-OpenSSL-s-KBKDF-and-KRB5KDF-for-deriving-long-te.patch
+++ b/SOURCES/Use-OpenSSL-s-KBKDF-and-KRB5KDF-for-deriving-long-te.patch
@@ -7,6 +7,9 @@ If supported, use OpenSSL-provided KBKDF (aes-sha2 and camellia) and
 KRB5KDF (3des and aes-sha1).  We already use OpenSSL's PBKDF2 where
 appropriate.  OpenSSL added support for these KDFs in 3.0.
 
+OpenSSL's restrictions to use KRB5KDF in FIPS mode are bypassed in case
+AES SHA-1 HMAC encryption types are allowed by the crypto policy.
+
 (cherry picked from commit ef8d11f6fb1232201c9efd2ae2ed567023fb85d2)
 [rharwood@redhat.com: 3des removal]
 ---
@@ -201,7 +204,7 @@ index 6707a7308..8e474b38e 100644
 +        goto done;
 +    }
 +
-+    kdf = EVP_KDF_fetch(NULL, "KRB5KDF", NULL);
++    kdf = EVP_KDF_fetch(NULL, "KRB5KDF", "-fips");
 +    if (kdf == NULL) {
 +        ret = KRB5_CRYPTO_INTERNAL;
 +        goto done;
diff --git a/SOURCES/Use-SHA256-instead-of-SHA1-for-PKINIT-CMS-digest.patch b/SOURCES/Use-SHA256-instead-of-SHA1-for-PKINIT-CMS-digest.patch
new file mode 100644
index 0000000..170d58d
--- /dev/null
+++ b/SOURCES/Use-SHA256-instead-of-SHA1-for-PKINIT-CMS-digest.patch
@@ -0,0 +1,113 @@
+From f0740c131b69f3346f07e7b7b03ebf27c50c0ccd Mon Sep 17 00:00:00 2001
+From: Julien Rische <jrische@redhat.com>
+Date: Fri, 11 Mar 2022 11:33:56 +0100
+Subject: [PATCH] Use SHA-256 instead of SHA-1 for PKINIT CMS digest
+
+Various organizations including NIST have been strongly recommending to
+stop using SHA-1 for digital signatures for some years already. CMS
+digest is used to generate such signatures, hence it should be upgraded
+to use SHA-256.
+---
+ .../preauth/pkinit/pkinit_crypto_openssl.c    | 27 ++++++++++---------
+ 1 file changed, 14 insertions(+), 13 deletions(-)
+
+diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+index 42e5c581d..2a6ef4aaa 100644
+--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
++++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+@@ -1240,7 +1240,7 @@ cms_signeddata_create(krb5_context context,
+         /* will not fill-out EVP_PKEY because it's on the smartcard */
+ 
+         /* Set digest algs */
+-        p7si->digest_alg->algorithm = OBJ_nid2obj(NID_sha1);
++        p7si->digest_alg->algorithm = OBJ_nid2obj(NID_sha256);
+ 
+         if (p7si->digest_alg->parameter != NULL)
+             ASN1_TYPE_free(p7si->digest_alg->parameter);
+@@ -1251,17 +1251,17 @@ cms_signeddata_create(krb5_context context,
+         /* Set sig algs */
+         if (p7si->digest_enc_alg->parameter != NULL)
+             ASN1_TYPE_free(p7si->digest_enc_alg->parameter);
+-        p7si->digest_enc_alg->algorithm = OBJ_nid2obj(NID_sha1WithRSAEncryption);
++        p7si->digest_enc_alg->algorithm = OBJ_nid2obj(NID_sha256WithRSAEncryption);
+         if (!(p7si->digest_enc_alg->parameter = ASN1_TYPE_new()))
+             goto cleanup;
+         p7si->digest_enc_alg->parameter->type = V_ASN1_NULL;
+ 
+         /* add signed attributes */
+-        /* compute sha1 digest over the EncapsulatedContentInfo */
++        /* compute sha256 digest over the EncapsulatedContentInfo */
+         ctx = EVP_MD_CTX_new();
+         if (ctx == NULL)
+             goto cleanup;
+-        EVP_DigestInit_ex(ctx, EVP_sha1(), NULL);
++        EVP_DigestInit_ex(ctx, EVP_sha256(), NULL);
+         EVP_DigestUpdate(ctx, data, data_len);
+         md_tmp = EVP_MD_CTX_md(ctx);
+         EVP_DigestFinal_ex(ctx, md_data, &md_len);
+@@ -1289,9 +1289,10 @@ cms_signeddata_create(krb5_context context,
+             goto cleanup2;
+ 
+ #ifndef WITHOUT_PKCS11
+-        /* Some tokens can only do RSAEncryption without sha1 hash */
+-        /* to compute sha1WithRSAEncryption, encode the algorithm ID for the hash
+-         * function and the hash value into an ASN.1 value of type DigestInfo
++        /* Some tokens can only do RSAEncryption without sha256 hash */
++        /* to compute sha256WithRSAEncryption, encode the algorithm ID for the
++         * hash function and the hash value into an ASN.1 value of type
++         * DigestInfo
+          * DigestInfo::=SEQUENCE {
+          *  digestAlgorithm  AlgorithmIdentifier,
+          *  digest OCTET STRING }
+@@ -1310,7 +1311,7 @@ cms_signeddata_create(krb5_context context,
+             alg = X509_ALGOR_new();
+             if (alg == NULL)
+                 goto cleanup2;
+-            X509_ALGOR_set0(alg, OBJ_nid2obj(NID_sha1), V_ASN1_NULL, NULL);
++            X509_ALGOR_set0(alg, OBJ_nid2obj(NID_sha256), V_ASN1_NULL, NULL);
+             alg_len = i2d_X509_ALGOR(alg, NULL);
+ 
+             digest = ASN1_OCTET_STRING_new();
+@@ -1339,7 +1340,7 @@ cms_signeddata_create(krb5_context context,
+ #endif
+         {
+             pkiDebug("mech = %s\n",
+-                     id_cryptoctx->pkcs11_method == 1 ? "CKM_SHA1_RSA_PKCS" : "FS");
++                     id_cryptoctx->pkcs11_method == 1 ? "CKM_SHA256_RSA_PKCS" : "FS");
+             retval = pkinit_sign_data(context, id_cryptoctx, abuf, alen,
+                                       &sig, &sig_len);
+         }
+@@ -4189,7 +4190,7 @@ create_signature(unsigned char **sig, unsigned int *sig_len,
+     ctx = EVP_MD_CTX_new();
+     if (ctx == NULL)
+         return ENOMEM;
+-    EVP_SignInit(ctx, EVP_sha1());
++    EVP_SignInit(ctx, EVP_sha256());
+     EVP_SignUpdate(ctx, data, data_len);
+     *sig_len = EVP_PKEY_size(pkey);
+     if ((*sig = malloc(*sig_len)) == NULL)
+@@ -4663,10 +4664,10 @@ pkinit_get_certs_pkcs11(krb5_context context,
+ 
+ #ifndef PKINIT_USE_MECH_LIST
+     /*
+-     * We'd like to use CKM_SHA1_RSA_PKCS for signing if it's available, but
++     * We'd like to use CKM_SHA256_RSA_PKCS for signing if it's available, but
+      * many cards seems to be confused about whether they are capable of
+      * this or not. The safe thing seems to be to ignore the mechanism list,
+-     * always use CKM_RSA_PKCS and calculate the sha1 digest ourselves.
++     * always use CKM_RSA_PKCS and calculate the sha256 digest ourselves.
+      */
+ 
+     id_cryptoctx->mech = CKM_RSA_PKCS;
+@@ -4694,7 +4695,7 @@ pkinit_get_certs_pkcs11(krb5_context context,
+         if (mechp[i] == CKM_RSA_PKCS) {
+             /* This seems backwards... */
+             id_cryptoctx->mech =
+-                (info.flags & CKF_SIGN) ? CKM_SHA1_RSA_PKCS : CKM_RSA_PKCS;
++                (info.flags & CKF_SIGN) ? CKM_SHA256_RSA_PKCS : CKM_RSA_PKCS;
+         }
+     }
+     free(mechp);
+-- 
+2.35.1
+
diff --git a/SOURCES/downstream-FIPS-with-PRNG-and-RADIUS-and-MD4.patch b/SOURCES/downstream-FIPS-with-PRNG-and-RADIUS-and-MD4.patch
index 3de59f1..a1f5629 100644
--- a/SOURCES/downstream-FIPS-with-PRNG-and-RADIUS-and-MD4.patch
+++ b/SOURCES/downstream-FIPS-with-PRNG-and-RADIUS-and-MD4.patch
@@ -1,6 +1,6 @@
-From d2b050a5acfacd8d400560ae097f6d5f392d7398 Mon Sep 17 00:00:00 2001
-From: Robbie Harwood <rharwood@redhat.com>
-Date: Fri, 9 Nov 2018 15:12:21 -0500
+From a7318c3cd6e1f58adb80493c05b59e6c180cd584 Mon Sep 17 00:00:00 2001
+From: Julien Rische <jrische@redhat.com>
+Date: Wed, 23 Feb 2022 17:34:33 +0100
 Subject: [PATCH] [downstream] FIPS with PRNG and RADIUS and MD4
 
 NB: Use openssl's PRNG in FIPS mode and taint within krad.
@@ -19,24 +19,33 @@ post6 restores MD4 (and therefore keygen-only RC4).
 
 post7 restores MD5 and adds radius_md5_fips_override.
 
-Last-updated: krb5-1.17
+post8 restores MD4/MD5 for OpenSSL 3.0
+
+Use OpenSSL 3.0 library context to access MD4 and MD5 lazily from
+legacy provider if RC4 encryption type is enabled, without affecting
+global context.
+
+Remove EVP_MD_CTX_FLAG_NON_FIPS_ALLOW flag since does not have any
+effect anymore.
+
+Last-updated: krb5-1.19
 ---
- doc/admin/conf_files/krb5_conf.rst            |  6 +++
- src/lib/crypto/krb/prng.c                     | 11 ++++-
- .../crypto/openssl/enc_provider/camellia.c    |  6 +++
- src/lib/crypto/openssl/enc_provider/rc4.c     | 13 +++++-
- .../crypto/openssl/hash_provider/hash_evp.c   | 12 +++++
- src/lib/crypto/openssl/hmac.c                 |  6 ++-
- src/lib/krad/attr.c                           | 46 ++++++++++++++-----
+ doc/admin/conf_files/krb5_conf.rst            |  6 ++
+ src/lib/crypto/krb/prng.c                     | 11 ++-
+ .../crypto/openssl/enc_provider/camellia.c    |  6 ++
+ src/lib/crypto/openssl/enc_provider/rc4.c     | 13 +++-
+ .../crypto/openssl/hash_provider/hash_evp.c   | 85 ++++++++++++++++++-
+ src/lib/crypto/openssl/hmac.c                 |  6 +-
+ src/lib/krad/attr.c                           | 46 ++++++++---
  src/lib/krad/attrset.c                        |  5 +-
- src/lib/krad/internal.h                       | 28 ++++++++++-
- src/lib/krad/packet.c                         | 22 +++++----
- src/lib/krad/remote.c                         | 10 +++-
+ src/lib/krad/internal.h                       | 28 ++++++-
+ src/lib/krad/packet.c                         | 22 +++---
+ src/lib/krad/remote.c                         | 10 ++-
  src/lib/krad/t_attr.c                         |  3 +-
  src/lib/krad/t_attrset.c                      |  4 +-
- src/plugins/preauth/spake/spake_client.c      |  6 +++
- src/plugins/preauth/spake/spake_kdc.c         |  6 +++
- 15 files changed, 151 insertions(+), 33 deletions(-)
+ src/plugins/preauth/spake/spake_client.c      |  6 ++
+ src/plugins/preauth/spake/spake_kdc.c         |  6 ++
+ 15 files changed, 218 insertions(+), 35 deletions(-)
 
 diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst
 index 675175955..adba8238d 100644
@@ -149,41 +158,116 @@ index bc87c6f42..9bf407899 100644
       * The cipher state here is a saved pointer to a struct arcfour_state
       * object, rather than a flat byte array as in most enc providers.  The
 diff --git a/src/lib/crypto/openssl/hash_provider/hash_evp.c b/src/lib/crypto/openssl/hash_provider/hash_evp.c
-index 1e0fb8fc3..2eb5139c0 100644
+index 1e0fb8fc3..4b8e1a6b2 100644
 --- a/src/lib/crypto/openssl/hash_provider/hash_evp.c
 +++ b/src/lib/crypto/openssl/hash_provider/hash_evp.c
-@@ -49,6 +49,11 @@ hash_evp(const EVP_MD *type, const krb5_crypto_iov *data, size_t num_data,
-     if (ctx == NULL)
-         return ENOMEM;
+@@ -32,6 +32,50 @@
  
-+    if (type == EVP_md4() || type == EVP_md5()) {
-+        /* See comments below in hash_md4() and hash_md5(). */
-+        EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
+ #include "crypto_int.h"
+ #include <openssl/evp.h>
++#include <openssl/provider.h>
++#include <threads.h>
++
++typedef struct ossl_lib_md_context {
++    OSSL_LIB_CTX *libctx;
++    OSSL_PROVIDER *legacy_provider;
++    EVP_MD *md;
++} ossl_md_context_t;
++
++static thread_local ossl_md_context_t *ossl_md_ctx = NULL;
++
++static krb5_error_code
++init_ossl_md_ctx(ossl_md_context_t *ctx, const char *algo)
++{
++    ctx->libctx = OSSL_LIB_CTX_new();
++    if (!ctx->libctx)
++        return KRB5_CRYPTO_INTERNAL;
++
++    /*
++     * 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->md = EVP_MD_fetch(ctx->libctx, algo, NULL);
++    if (!ctx->md)
++        return KRB5_CRYPTO_INTERNAL;
++
++    return 0;
++}
++
++static void
++deinit_ossl_ctx(ossl_md_context_t *ctx)
++{
++    if (ctx->md)
++        EVP_MD_free(ctx->md);
++
++    if (ctx->legacy_provider)
++        OSSL_PROVIDER_unload(ctx->legacy_provider);
++
++    if (ctx->libctx)
++        OSSL_LIB_CTX_free(ctx->libctx);
++}
+ 
+ static krb5_error_code
+ hash_evp(const EVP_MD *type, const krb5_crypto_iov *data, size_t num_data,
+@@ -61,16 +104,53 @@ hash_evp(const EVP_MD *type, const krb5_crypto_iov *data, size_t num_data,
+     return ok ? 0 : KRB5_CRYPTO_INTERNAL;
+ }
+ 
++static krb5_error_code
++hash_legacy_evp(const char *algo, const krb5_crypto_iov *data, size_t num_data,
++                krb5_data *output)
++{
++    krb5_error_code err;
++
++    if (!ossl_md_ctx) {
++        ossl_md_ctx = malloc(sizeof(ossl_md_context_t));
++        if (!ossl_md_ctx)
++            return ENOMEM;
++
++        err = init_ossl_md_ctx(ossl_md_ctx, algo);
++        if (err) {
++            deinit_ossl_ctx(ossl_md_ctx);
++            free(ossl_md_ctx);
++            ossl_md_ctx = NULL;
++            goto end;
++        }
 +    }
 +
-     ok = EVP_DigestInit_ex(ctx, type, NULL);
-     for (i = 0; i < num_data; i++) {
-         if (!SIGN_IOV(&data[i]))
-@@ -64,12 +69,19 @@ hash_evp(const EVP_MD *type, const krb5_crypto_iov *data, size_t num_data,
++    err = hash_evp(ossl_md_ctx->md, data, num_data, output);
++
++end:
++    return err;
++}
++
  static krb5_error_code
  hash_md4(const krb5_crypto_iov *data, size_t num_data, krb5_data *output)
  {
+-    return hash_evp(EVP_md4(), data, num_data, output);
 +    /*
 +     * MD4 is needed in FIPS mode to perform key generation for RC4 keys used
 +     * by IPA.  These keys are only used along a (separately) secured channel
 +     * for legacy reasons when performing trusts to Active Directory.
 +     */
-     return hash_evp(EVP_md4(), data, num_data, output);
++    return FIPS_mode() ? hash_legacy_evp("MD4", data, num_data, output)
++                       : hash_evp(EVP_md4(), data, num_data, output);
  }
  
  static krb5_error_code
  hash_md5(const krb5_crypto_iov *data, size_t num_data, krb5_data *output)
  {
-+    /* MD5 is needed in FIPS mode for communication with RADIUS servers.  This
-+     * is gated in libkrad by libdefaults->radius_md5_fips_override. */
-     return hash_evp(EVP_md5(), data, num_data, output);
+-    return hash_evp(EVP_md5(), data, num_data, output);
++    /*
++     * MD5 is needed in FIPS mode for communication with RADIUS servers.  This
++     * is gated in libkrad by libdefaults->radius_md5_fips_override.
++     */
++    return FIPS_mode() ? hash_legacy_evp("MD5", data, num_data, output)
++                       : hash_evp(EVP_md5(), data, num_data, output);
  }
  
+ static krb5_error_code
 diff --git a/src/lib/crypto/openssl/hmac.c b/src/lib/crypto/openssl/hmac.c
 index 7dc59dcc0..769a50c00 100644
 --- a/src/lib/crypto/openssl/hmac.c
diff --git a/SPECS/krb5.spec b/SPECS/krb5.spec
index 277654d..7464cab 100644
--- a/SPECS/krb5.spec
+++ b/SPECS/krb5.spec
@@ -42,7 +42,7 @@
 Summary: The Kerberos network authentication system
 Name: krb5
 Version: 1.19.1
-Release: %{?zdpd}13%{?dist}
+Release: %{?zdpd}15%{?dist}
 
 # rharwood has trust path to signing key and verifies on check-in
 Source0: https://web.mit.edu/kerberos/dist/krb5/%{version}/krb5-%{version}%{?dashpre}.tar.gz
@@ -90,6 +90,7 @@ Patch25: Allow-kinit-with-keytab-to-defer-canonicalization.patch
 Patch26: Fix-kadmin-k-with-fallback-or-referral-realm.patch
 Patch27: Fix-KDC-null-deref-on-bad-encrypted-challenge.patch
 Patch28: Fix-KDC-null-deref-on-TGS-inner-body-null-server.patch
+Patch29: Use-SHA256-instead-of-SHA1-for-PKINIT-CMS-digest.patch
 
 License: MIT
 URL: https://web.mit.edu/kerberos/www/
@@ -646,6 +647,13 @@ exit 0
 %{_libdir}/libkadm5srv_mit.so.*
 
 %changelog
+* Mon Mar 14 2022 Julien Rische <jrische@redhat.com> - 1.19.1-15
+- Use SHA-256 instead of SHA-1 for PKINIT CMS digest
+
+* Thu Feb 24 2022 Julien Rische <jrische@redhat.com> - 1.19.1-14
+- Bypass FIPS restrictions to use KRB5KDF in case AES SHA-1 HMAC is enabled
+- Lazily load MD4/5 from OpenSSL if using RADIUS or RC4 enctype in FIPS mode
+
 * Fri Dec 17 2021 Antonio Torres <antorres@redhat.com> - 1.19.1-13
 - Remove -specs= from krb5-config output
 - Resolves #1997021