#34 Do not block KRB5KDF and MD4/5 in FIPS mode
Merged a year ago by jrische. Opened a year ago by jrische.
rpms/ jrische/krb5 next  into  rawhide

@@ -0,0 +1,165 @@ 

+ From d8f67df42efd68142aa904040f9e8cc0f9138c10 Mon Sep 17 00:00:00 2001

+ From: Julien Rische <jrische@redhat.com>

+ Date: Thu, 19 Jan 2023 19:22:27 +0100

+ Subject: [PATCH] [downstream] Allow KRB5KDF, MD5, and MD4 in FIPS mode

+ 

+ OpenSSL's restrictions to use KRB5KDF, MD5, and MD4 in FIPS mode are

+ bypassed in case AES SHA-1 HMAC or RC4 encryption types are allowed by

+ the crypto policy.

+ ---

+  .../crypto/openssl/hash_provider/hash_evp.c   | 97 +++++++++++++++++--

+  src/lib/crypto/openssl/kdf.c                  |  2 +-

+  2 files changed, 89 insertions(+), 10 deletions(-)

+ 

+ diff --git a/src/lib/crypto/openssl/hash_provider/hash_evp.c b/src/lib/crypto/openssl/hash_provider/hash_evp.c

+ index 11659908bb..eb2e693e9f 100644

+ --- a/src/lib/crypto/openssl/hash_provider/hash_evp.c

+ +++ b/src/lib/crypto/openssl/hash_provider/hash_evp.c

+ @@ -44,6 +44,49 @@

+  #define EVP_MD_CTX_free EVP_MD_CTX_destroy

+  #endif

+  

+ +#include <openssl/provider.h>

+ +#include <openssl/fips.h>

+ +#include <threads.h>

+ +

+ +typedef struct ossl_lib_md_context {

+ +    OSSL_LIB_CTX *libctx;

+ +    OSSL_PROVIDER *default_provider;

+ +    OSSL_PROVIDER *legacy_provider;

+ +} 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. */

+ +    ctx->default_provider = OSSL_PROVIDER_load(ctx->libctx, "default");

+ +    ctx->legacy_provider = OSSL_PROVIDER_load(ctx->libctx, "legacy");

+ +

+ +    if (!(ctx->default_provider && ctx->legacy_provider))

+ +        return KRB5_CRYPTO_INTERNAL;

+ +

+ +    return 0;

+ +}

+ +

+ +static void

+ +deinit_ossl_ctx(ossl_md_context_t *ctx)

+ +{

+ +    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);

+ +}

+ +

+ +

+  static krb5_error_code

+  hash_evp(const EVP_MD *type, const krb5_crypto_iov *data, size_t num_data,

+           krb5_data *output)

+ @@ -60,11 +103,6 @@ hash_evp(const EVP_MD *type, const krb5_crypto_iov *data, size_t num_data,

+      if (ctx == NULL)

+          return ENOMEM;

+  

+ -    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);

+ -    }

+ -

+      ok = EVP_DigestInit_ex(ctx, type, NULL);

+      for (i = 0; i < num_data; i++) {

+          if (!SIGN_IOV(&data[i]))

+ @@ -77,6 +115,43 @@ 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;

+ +    EVP_MD *md = NULL;

+ +

+ +    if (!ossl_md_ctx) {

+ +        ossl_md_ctx = malloc(sizeof(ossl_md_context_t));

+ +        if (!ossl_md_ctx) {

+ +            err = ENOMEM;

+ +            goto end;

+ +        }

+ +

+ +        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;

+ +        }

+ +    }

+ +

+ +    md = EVP_MD_fetch(ossl_md_ctx->libctx, algo, NULL);

+ +    if (!md) {

+ +        err = KRB5_CRYPTO_INTERNAL;

+ +        goto end;

+ +    }

+ +

+ +    err = hash_evp(md, data, num_data, output);

+ +

+ +end:

+ +    if (md)

+ +        EVP_MD_free(md);

+ +

+ +    return err;

+ +}

+  #endif

+  

+  #ifdef K5_OPENSSL_MD4

+ @@ -88,7 +163,8 @@ hash_md4(const krb5_crypto_iov *data, size_t num_data, krb5_data *output)

+       * 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);

+  }

+  

+  const struct krb5_hash_provider krb5int_hash_md4 = {

+ @@ -100,9 +176,12 @@ const struct krb5_hash_provider krb5int_hash_md4 = {

+  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);

+ +    /*

+ +     * 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);

+  }

+  

+  const struct krb5_hash_provider krb5int_hash_md5 = {

+ diff --git a/src/lib/crypto/openssl/kdf.c b/src/lib/crypto/openssl/kdf.c

+ index 5a43c3d9eb..8528ddc4a9 100644

+ --- a/src/lib/crypto/openssl/kdf.c

+ +++ b/src/lib/crypto/openssl/kdf.c

+ @@ -198,7 +198,7 @@ k5_derive_random_rfc3961(const struct krb5_enc_provider *enc, krb5_key key,

+          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;

+ -- 

+ 2.39.1

+ 

file modified
+6 -1
@@ -10,7 +10,7 @@ 

  #

  # baserelease is what we have standardized across Fedora and what

  # rpmdev-bumpspec knows how to handle.

- %global baserelease 7

+ %global baserelease 8

  

  # This should be e.g. beta1 or %%nil

  %global pre_release %nil
@@ -74,6 +74,7 @@ 

  Patch13: 0013-downstream-Make-tests-compatible-with-sssd_krb5_loca.patch

  Patch14: 0014-downstream-Include-missing-OpenSSL-FIPS-header.patch

  Patch15: 0015-downstream-Do-not-set-root-as-ksu-file-owner.patch

+ Patch16: 0016-downstream-Allow-KRB5KDF-MD5-and-MD4-in-FIPS-mode.patch

  

  License: MIT

  URL: https://web.mit.edu/kerberos/www/
@@ -710,6 +711,10 @@ 

  %{_datarootdir}/%{name}-tests/

  

  %changelog

+ * Mon Jan 30 2023 Julien Rische <jrische@redhat.com> - 1.20.1-8

+ - 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

+ 

  * Thu Jan 19 2023 Fedora Release Engineering <releng@fedoraproject.org> - 1.20.1-7

  - Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild

  

Bypass OpenSSL's restrictions to use KRB5KDF in FIPS mode in case at least one of AES SHA-1 HMAC encryption types are used.

Use OpenSSL 3.0 library context to access MD4 and MD5 lazily from legacy provider if RADIUS is being used or RC4 encryption type is enabled, without affecting global context.

Such exceptions should not be allowed by the default FIPS crypto policy.

Metadata Update from @jrische:
- Request assigned

a year ago

rebased onto ec957f5

a year ago

Pull-Request has been merged by jrische

a year ago