Blame SOURCES/krb5-1.17post6-FIPS-with-PRNG-and-RADIUS-and-MD4.patch

92593c
From 2a4e2418875b41c3273db5f6b4e9e1b01c1fb5ff Mon Sep 17 00:00:00 2001
92593c
From: Robbie Harwood <rharwood@redhat.com>
92593c
Date: Fri, 9 Nov 2018 15:12:21 -0500
92593c
Subject: [PATCH] krb5-1.17post6 FIPS with PRNG and RADIUS and MD4
92593c
92593c
NB: Use openssl's PRNG in FIPS mode and taint within krad.
92593c
92593c
A lot of the FIPS error conditions from OpenSSL are incredibly
92593c
mysterious (at best, things return NULL unexpectedly; at worst,
92593c
internal assertions are tripped; most of the time, you just get
92593c
ENOMEM).  In order to cope with this, we need to have some level of
92593c
awareness of what we can and can't safely call.
92593c
92593c
This will slow down some calls slightly (FIPS_mode() takes multiple
92593c
locks), but not for any ciphers we care about - which is to say that
92593c
AES is fine.  Shame about SPAKE though.
92593c
92593c
post6 restores MD4 (and therefore keygen-only RC4).
92593c
92593c
(cherry picked from commit 80b56b04d90fcacd9f78fed305c7d5528d863b38)
92593c
---
92593c
 src/lib/crypto/krb/prng.c                     | 11 ++++-
92593c
 .../crypto/openssl/enc_provider/camellia.c    |  6 +++
92593c
 src/lib/crypto/openssl/enc_provider/rc4.c     | 13 +++++-
92593c
 .../crypto/openssl/hash_provider/hash_evp.c   | 12 +++++
92593c
 src/lib/crypto/openssl/hmac.c                 |  6 ++-
92593c
 src/lib/krad/attr.c                           | 45 ++++++++++++++-----
92593c
 src/lib/krad/attrset.c                        |  5 ++-
92593c
 src/lib/krad/internal.h                       | 13 +++++-
92593c
 src/lib/krad/packet.c                         | 22 ++++-----
92593c
 src/lib/krad/remote.c                         | 10 ++++-
92593c
 src/lib/krad/t_attr.c                         |  3 +-
92593c
 src/lib/krad/t_attrset.c                      |  4 +-
92593c
 src/plugins/preauth/spake/spake_client.c      |  6 +++
92593c
 src/plugins/preauth/spake/spake_kdc.c         |  6 +++
92593c
 14 files changed, 129 insertions(+), 33 deletions(-)
92593c
92593c
diff --git a/src/lib/crypto/krb/prng.c b/src/lib/crypto/krb/prng.c
92593c
index cb9ca9b98..f0e9984ca 100644
92593c
--- a/src/lib/crypto/krb/prng.c
92593c
+++ b/src/lib/crypto/krb/prng.c
92593c
@@ -26,6 +26,8 @@
92593c
 
92593c
 #include "crypto_int.h"
92593c
 
92593c
+#include <openssl/rand.h>
92593c
+
92593c
 krb5_error_code KRB5_CALLCONV
92593c
 krb5_c_random_seed(krb5_context context, krb5_data *data)
92593c
 {
92593c
@@ -99,9 +101,16 @@ krb5_boolean
92593c
 k5_get_os_entropy(unsigned char *buf, size_t len, int strong)
92593c
 {
92593c
     const char *device;
92593c
-#if defined(__linux__) && defined(SYS_getrandom)
92593c
     int r;
92593c
 
92593c
+    /* A wild FIPS mode appeared! */
92593c
+    if (FIPS_mode()) {
92593c
+        /* The return codes on this API are not good */
92593c
+        r = RAND_bytes(buf, len);
92593c
+        return r == 1;
92593c
+    }
92593c
+
92593c
+#if defined(__linux__) && defined(SYS_getrandom)
92593c
     while (len > 0) {
92593c
         /*
92593c
          * Pull from the /dev/urandom pool, but require it to have been seeded.
92593c
diff --git a/src/lib/crypto/openssl/enc_provider/camellia.c b/src/lib/crypto/openssl/enc_provider/camellia.c
92593c
index 2da691329..f79679a0b 100644
92593c
--- a/src/lib/crypto/openssl/enc_provider/camellia.c
92593c
+++ b/src/lib/crypto/openssl/enc_provider/camellia.c
92593c
@@ -304,6 +304,9 @@ krb5int_camellia_cbc_mac(krb5_key key, const krb5_crypto_iov *data,
92593c
     unsigned char blockY[CAMELLIA_BLOCK_SIZE], blockB[CAMELLIA_BLOCK_SIZE];
92593c
     struct iov_cursor cursor;
92593c
 
92593c
+    if (FIPS_mode())
92593c
+        return KRB5_CRYPTO_INTERNAL;
92593c
+
92593c
     if (output->length < CAMELLIA_BLOCK_SIZE)
92593c
         return KRB5_BAD_MSIZE;
92593c
 
92593c
@@ -331,6 +334,9 @@ static krb5_error_code
92593c
 krb5int_camellia_init_state (const krb5_keyblock *key, krb5_keyusage usage,
92593c
                              krb5_data *state)
92593c
 {
92593c
+    if (FIPS_mode())
92593c
+        return KRB5_CRYPTO_INTERNAL;
92593c
+
92593c
     state->length = 16;
92593c
     state->data = (void *) malloc(16);
92593c
     if (state->data == NULL)
92593c
diff --git a/src/lib/crypto/openssl/enc_provider/rc4.c b/src/lib/crypto/openssl/enc_provider/rc4.c
92593c
index a65d57b7a..6ccaca94a 100644
92593c
--- a/src/lib/crypto/openssl/enc_provider/rc4.c
92593c
+++ b/src/lib/crypto/openssl/enc_provider/rc4.c
92593c
@@ -66,6 +66,9 @@ k5_arcfour_docrypt(krb5_key key, const krb5_data *state, krb5_crypto_iov *data,
92593c
     EVP_CIPHER_CTX *ctx = NULL;
92593c
     struct arcfour_state *arcstate;
92593c
 
92593c
+    if (FIPS_mode())
92593c
+        return KRB5_CRYPTO_INTERNAL;
92593c
+
92593c
     arcstate = (state != NULL) ? (void *)state->data : NULL;
92593c
     if (arcstate != NULL) {
92593c
         ctx = arcstate->ctx;
92593c
@@ -113,7 +116,12 @@ k5_arcfour_docrypt(krb5_key key, const krb5_data *state, krb5_crypto_iov *data,
92593c
 static void
92593c
 k5_arcfour_free_state(krb5_data *state)
92593c
 {
92593c
-    struct arcfour_state *arcstate = (void *)state->data;
92593c
+    struct arcfour_state *arcstate;
92593c
+
92593c
+    if (FIPS_mode())
92593c
+        return;
92593c
+
92593c
+    arcstate = (void *) state->data;
92593c
 
92593c
     EVP_CIPHER_CTX_free(arcstate->ctx);
92593c
     free(arcstate);
92593c
@@ -125,6 +133,9 @@ k5_arcfour_init_state(const krb5_keyblock *key,
92593c
 {
92593c
     struct arcfour_state *arcstate;
92593c
 
92593c
+    if (FIPS_mode())
92593c
+        return KRB5_CRYPTO_INTERNAL;
92593c
+
92593c
     /*
92593c
      * The cipher state here is a saved pointer to a struct arcfour_state
92593c
      * object, rather than a flat byte array as in most enc providers.  The
92593c
diff --git a/src/lib/crypto/openssl/hash_provider/hash_evp.c b/src/lib/crypto/openssl/hash_provider/hash_evp.c
92593c
index 957ed8d9c..915da9dbe 100644
92593c
--- a/src/lib/crypto/openssl/hash_provider/hash_evp.c
92593c
+++ b/src/lib/crypto/openssl/hash_provider/hash_evp.c
92593c
@@ -49,6 +49,11 @@ hash_evp(const EVP_MD *type, const krb5_crypto_iov *data, size_t num_data,
92593c
     if (ctx == NULL)
92593c
         return ENOMEM;
92593c
 
92593c
+    if (type == EVP_md4()) {
92593c
+        /* See comment below in hash_md4(). */
92593c
+        EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
92593c
+    }
92593c
+
92593c
     ok = EVP_DigestInit_ex(ctx, type, NULL);
92593c
     for (i = 0; i < num_data; i++) {
92593c
         if (!SIGN_IOV(&data[i]))
92593c
@@ -64,12 +69,19 @@ hash_evp(const EVP_MD *type, const krb5_crypto_iov *data, size_t num_data,
92593c
 static krb5_error_code
92593c
 hash_md4(const krb5_crypto_iov *data, size_t num_data, krb5_data *output)
92593c
 {
92593c
+    /*
92593c
+     * MD4 is needed in FIPS mode to perform key generation for RC4 keys used
92593c
+     * by IPA.  These keys are only used along a (separately) secured channel
92593c
+     * for legacy reasons when performing trusts to Active Directory.
92593c
+     */
92593c
     return hash_evp(EVP_md4(), data, num_data, output);
92593c
 }
92593c
 
92593c
 static krb5_error_code
92593c
 hash_md5(const krb5_crypto_iov *data, size_t num_data, krb5_data *output)
92593c
 {
92593c
+    if (FIPS_mode())
92593c
+        return KRB5_CRYPTO_INTERNAL;
92593c
     return hash_evp(EVP_md5(), data, num_data, output);
92593c
 }
92593c
 
92593c
diff --git a/src/lib/crypto/openssl/hmac.c b/src/lib/crypto/openssl/hmac.c
92593c
index b2db6ec02..d94d9ac94 100644
92593c
--- a/src/lib/crypto/openssl/hmac.c
92593c
+++ b/src/lib/crypto/openssl/hmac.c
92593c
@@ -103,7 +103,11 @@ map_digest(const struct krb5_hash_provider *hash)
92593c
         return EVP_sha256();
92593c
     else if (!strncmp(hash->hash_name, "SHA-384",7))
92593c
         return EVP_sha384();
92593c
-    else if (!strncmp(hash->hash_name, "MD5", 3))
92593c
+
92593c
+    if (FIPS_mode())
92593c
+        return NULL;
92593c
+
92593c
+    if (!strncmp(hash->hash_name, "MD5", 3))
92593c
         return EVP_md5();
92593c
     else if (!strncmp(hash->hash_name, "MD4", 3))
92593c
         return EVP_md4();
92593c
diff --git a/src/lib/krad/attr.c b/src/lib/krad/attr.c
92593c
index 9c13d9d75..275327e67 100644
92593c
--- a/src/lib/krad/attr.c
92593c
+++ b/src/lib/krad/attr.c
92593c
@@ -30,6 +30,7 @@
92593c
 #include <k5-int.h>
92593c
 #include "internal.h"
92593c
 
92593c
+#include <openssl/crypto.h>
92593c
 #include <string.h>
92593c
 
92593c
 /* RFC 2865 */
92593c
@@ -38,7 +39,8 @@
92593c
 typedef krb5_error_code
92593c
 (*attribute_transform_fn)(krb5_context ctx, const char *secret,
92593c
                           const unsigned char *auth, const krb5_data *in,
92593c
-                          unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen);
92593c
+                          unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
92593c
+                          krb5_boolean *is_fips);
92593c
 
92593c
 typedef struct {
92593c
     const char *name;
92593c
@@ -51,12 +53,14 @@ typedef struct {
92593c
 static krb5_error_code
92593c
 user_password_encode(krb5_context ctx, const char *secret,
92593c
                      const unsigned char *auth, const krb5_data *in,
92593c
-                     unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen);
92593c
+                     unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
92593c
+                     krb5_boolean *is_fips);
92593c
 
92593c
 static krb5_error_code
92593c
 user_password_decode(krb5_context ctx, const char *secret,
92593c
                      const unsigned char *auth, const krb5_data *in,
92593c
-                     unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen);
92593c
+                     unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
92593c
+                     krb5_boolean *ignored);
92593c
 
92593c
 static const attribute_record attributes[UCHAR_MAX] = {
92593c
     {"User-Name", 1, MAX_ATTRSIZE, NULL, NULL},
92593c
@@ -128,7 +132,8 @@ static const attribute_record attributes[UCHAR_MAX] = {
92593c
 static krb5_error_code
92593c
 user_password_encode(krb5_context ctx, const char *secret,
92593c
                      const unsigned char *auth, const krb5_data *in,
92593c
-                     unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen)
92593c
+                     unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
92593c
+                     krb5_boolean *is_fips)
92593c
 {
92593c
     const unsigned char *indx;
92593c
     krb5_error_code retval;
92593c
@@ -154,8 +159,14 @@ user_password_encode(krb5_context ctx, const char *secret,
92593c
     for (blck = 0, indx = auth; blck * BLOCKSIZE < len; blck++) {
92593c
         memcpy(tmp.data + seclen, indx, BLOCKSIZE);
92593c
 
92593c
-        retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0, &tmp,
92593c
-                                      &sum);
92593c
+        if (FIPS_mode()) {
92593c
+            /* Skip encryption here.  Taint so that we won't pass it out of
92593c
+             * the machine by accident. */
92593c
+            *is_fips = TRUE;
92593c
+            sum.contents = calloc(1, BLOCKSIZE);
92593c
+        } else
92593c
+            retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0, &tmp,
92593c
+                                          &sum);
92593c
         if (retval != 0) {
92593c
             zap(tmp.data, tmp.length);
92593c
             zap(outbuf, len);
92593c
@@ -180,7 +191,8 @@ user_password_encode(krb5_context ctx, const char *secret,
92593c
 static krb5_error_code
92593c
 user_password_decode(krb5_context ctx, const char *secret,
92593c
                      const unsigned char *auth, const krb5_data *in,
92593c
-                     unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen)
92593c
+                     unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
92593c
+                     krb5_boolean *is_fips)
92593c
 {
92593c
     const unsigned char *indx;
92593c
     krb5_error_code retval;
92593c
@@ -204,8 +216,14 @@ user_password_decode(krb5_context ctx, const char *secret,
92593c
     for (blck = 0, indx = auth; blck * BLOCKSIZE < in->length; blck++) {
92593c
         memcpy(tmp.data + seclen, indx, BLOCKSIZE);
92593c
 
92593c
-        retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0,
92593c
-                                      &tmp, &sum);
92593c
+        if (FIPS_mode()) {
92593c
+            /* Skip encryption here.  Taint so that we won't pass it out of
92593c
+             * the machine by accident. */
92593c
+            *is_fips = TRUE;
92593c
+            sum.contents = calloc(1, BLOCKSIZE);
92593c
+        } else
92593c
+            retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0,
92593c
+                                          &tmp, &sum);
92593c
         if (retval != 0) {
92593c
             zap(tmp.data, tmp.length);
92593c
             zap(outbuf, in->length);
92593c
@@ -248,7 +266,7 @@ krb5_error_code
92593c
 kr_attr_encode(krb5_context ctx, const char *secret,
92593c
                const unsigned char *auth, krad_attr type,
92593c
                const krb5_data *in, unsigned char outbuf[MAX_ATTRSIZE],
92593c
-               size_t *outlen)
92593c
+               size_t *outlen, krb5_boolean *is_fips)
92593c
 {
92593c
     krb5_error_code retval;
92593c
 
92593c
@@ -265,7 +283,8 @@ kr_attr_encode(krb5_context ctx, const char *secret,
92593c
         return 0;
92593c
     }
92593c
 
92593c
-    return attributes[type - 1].encode(ctx, secret, auth, in, outbuf, outlen);
92593c
+    return attributes[type - 1].encode(ctx, secret, auth, in, outbuf, outlen,
92593c
+                                       is_fips);
92593c
 }
92593c
 
92593c
 krb5_error_code
92593c
@@ -274,6 +293,7 @@ kr_attr_decode(krb5_context ctx, const char *secret, const unsigned char *auth,
92593c
                unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen)
92593c
 {
92593c
     krb5_error_code retval;
92593c
+    krb5_boolean ignored;
92593c
 
92593c
     retval = kr_attr_valid(type, in);
92593c
     if (retval != 0)
92593c
@@ -288,7 +308,8 @@ kr_attr_decode(krb5_context ctx, const char *secret, const unsigned char *auth,
92593c
         return 0;
92593c
     }
92593c
 
92593c
-    return attributes[type - 1].decode(ctx, secret, auth, in, outbuf, outlen);
92593c
+    return attributes[type - 1].decode(ctx, secret, auth, in, outbuf, outlen,
92593c
+                                       &ignored);
92593c
 }
92593c
 
92593c
 krad_attr
92593c
diff --git a/src/lib/krad/attrset.c b/src/lib/krad/attrset.c
92593c
index 03c613716..d89982a13 100644
92593c
--- a/src/lib/krad/attrset.c
92593c
+++ b/src/lib/krad/attrset.c
92593c
@@ -167,7 +167,8 @@ krad_attrset_copy(const krad_attrset *set, krad_attrset **copy)
92593c
 krb5_error_code
92593c
 kr_attrset_encode(const krad_attrset *set, const char *secret,
92593c
                   const unsigned char *auth,
92593c
-                  unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen)
92593c
+                  unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen,
92593c
+                  krb5_boolean *is_fips)
92593c
 {
92593c
     unsigned char buffer[MAX_ATTRSIZE];
92593c
     krb5_error_code retval;
92593c
@@ -181,7 +182,7 @@ kr_attrset_encode(const krad_attrset *set, const char *secret,
92593c
 
92593c
     K5_TAILQ_FOREACH(a, &set->list, list) {
92593c
         retval = kr_attr_encode(set->ctx, secret, auth, a->type, &a->attr,
92593c
-                                buffer, &attrlen);
92593c
+                                buffer, &attrlen, is_fips);
92593c
         if (retval != 0)
92593c
             return retval;
92593c
 
92593c
diff --git a/src/lib/krad/internal.h b/src/lib/krad/internal.h
92593c
index 996a89372..a53ce31ce 100644
92593c
--- a/src/lib/krad/internal.h
92593c
+++ b/src/lib/krad/internal.h
92593c
@@ -49,6 +49,13 @@
92593c
 
92593c
 typedef struct krad_remote_st krad_remote;
92593c
 
92593c
+struct krad_packet_st {
92593c
+    char buffer[KRAD_PACKET_SIZE_MAX];
92593c
+    krad_attrset *attrset;
92593c
+    krb5_data pkt;
92593c
+    krb5_boolean is_fips;
92593c
+};
92593c
+
92593c
 /* Validate constraints of an attribute. */
92593c
 krb5_error_code
92593c
 kr_attr_valid(krad_attr type, const krb5_data *data);
92593c
@@ -57,7 +64,8 @@ kr_attr_valid(krad_attr type, const krb5_data *data);
92593c
 krb5_error_code
92593c
 kr_attr_encode(krb5_context ctx, const char *secret, const unsigned char *auth,
92593c
                krad_attr type, const krb5_data *in,
92593c
-               unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen);
92593c
+               unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
92593c
+               krb5_boolean *is_fips);
92593c
 
92593c
 /* Decode an attribute. */
92593c
 krb5_error_code
92593c
@@ -69,7 +77,8 @@ kr_attr_decode(krb5_context ctx, const char *secret, const unsigned char *auth,
92593c
 krb5_error_code
92593c
 kr_attrset_encode(const krad_attrset *set, const char *secret,
92593c
                   const unsigned char *auth,
92593c
-                  unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen);
92593c
+                  unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen,
92593c
+                  krb5_boolean *is_fips);
92593c
 
92593c
 /* Decode attributes from a buffer. */
92593c
 krb5_error_code
92593c
diff --git a/src/lib/krad/packet.c b/src/lib/krad/packet.c
92593c
index c597174b6..794ac84c4 100644
92593c
--- a/src/lib/krad/packet.c
92593c
+++ b/src/lib/krad/packet.c
92593c
@@ -32,6 +32,7 @@
92593c
 #include <string.h>
92593c
 
92593c
 #include <arpa/inet.h>
92593c
+#include <openssl/crypto.h>
92593c
 
92593c
 typedef unsigned char uchar;
92593c
 
92593c
@@ -53,12 +54,6 @@ typedef unsigned char uchar;
92593c
 #define pkt_auth(p) ((uchar *)offset(&(p)->pkt, OFFSET_AUTH))
92593c
 #define pkt_attr(p) ((unsigned char *)offset(&(p)->pkt, OFFSET_ATTR))
92593c
 
92593c
-struct krad_packet_st {
92593c
-    char buffer[KRAD_PACKET_SIZE_MAX];
92593c
-    krad_attrset *attrset;
92593c
-    krb5_data pkt;
92593c
-};
92593c
-
92593c
 typedef struct {
92593c
     uchar x[(UCHAR_MAX + 1) / 8];
92593c
 } idmap;
92593c
@@ -187,8 +182,13 @@ auth_generate_response(krb5_context ctx, const char *secret,
92593c
     memcpy(data.data + response->pkt.length, secret, strlen(secret));
92593c
 
92593c
     /* Hash it. */
92593c
-    retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0, &data,
92593c
-                                  &hash);
92593c
+    if (FIPS_mode()) {
92593c
+        /* This checksum does very little security-wise anyway, so don't
92593c
+         * taint. */
92593c
+        hash.contents = calloc(1, AUTH_FIELD_SIZE);
92593c
+    } else
92593c
+        retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0, &data,
92593c
+                                      &hash);
92593c
     free(data.data);
92593c
     if (retval != 0)
92593c
         return retval;
92593c
@@ -276,7 +276,7 @@ krad_packet_new_request(krb5_context ctx, const char *secret, krad_code code,
92593c
 
92593c
     /* Encode the attributes. */
92593c
     retval = kr_attrset_encode(set, secret, pkt_auth(pkt), pkt_attr(pkt),
92593c
-                               &attrset_len);
92593c
+                               &attrset_len, &pkt->is_fips);
92593c
     if (retval != 0)
92593c
         goto error;
92593c
 
92593c
@@ -314,7 +314,7 @@ krad_packet_new_response(krb5_context ctx, const char *secret, krad_code code,
92593c
 
92593c
     /* Encode the attributes. */
92593c
     retval = kr_attrset_encode(set, secret, pkt_auth(request), pkt_attr(pkt),
92593c
-                               &attrset_len);
92593c
+                               &attrset_len, &pkt->is_fips);
92593c
     if (retval != 0)
92593c
         goto error;
92593c
 
92593c
@@ -451,6 +451,8 @@ krad_packet_decode_response(krb5_context ctx, const char *secret,
92593c
 const krb5_data *
92593c
 krad_packet_encode(const krad_packet *pkt)
92593c
 {
92593c
+    if (pkt->is_fips)
92593c
+        return NULL;
92593c
     return &pkt->pkt;
92593c
 }
92593c
 
92593c
diff --git a/src/lib/krad/remote.c b/src/lib/krad/remote.c
92593c
index 437f7e91a..0f90443ce 100644
92593c
--- a/src/lib/krad/remote.c
92593c
+++ b/src/lib/krad/remote.c
92593c
@@ -263,7 +263,7 @@ on_io_write(krad_remote *rr)
92593c
     request *r;
92593c
 
92593c
     K5_TAILQ_FOREACH(r, &rr->list, list) {
92593c
-        tmp = krad_packet_encode(r->request);
92593c
+        tmp = &r->request->pkt;
92593c
 
92593c
         /* If the packet has already been sent, do nothing. */
92593c
         if (r->sent == tmp->length)
92593c
@@ -359,7 +359,7 @@ on_io_read(krad_remote *rr)
92593c
     if (req != NULL) {
92593c
         K5_TAILQ_FOREACH(r, &rr->list, list) {
92593c
             if (r->request == req &&
92593c
-                r->sent == krad_packet_encode(req)->length) {
92593c
+                r->sent == req->pkt.length) {
92593c
                 request_finish(r, 0, rsp);
92593c
                 break;
92593c
             }
92593c
@@ -455,6 +455,12 @@ kr_remote_send(krad_remote *rr, krad_code code, krad_attrset *attrs,
92593c
                                      (krad_packet_iter_cb)iterator, &r, &tmp);
92593c
     if (retval != 0)
92593c
         goto error;
92593c
+    else if (tmp->is_fips && rr->info->ai_family != AF_LOCAL &&
92593c
+        rr->info->ai_family != AF_UNIX) {
92593c
+        /* This would expose cleartext passwords, so abort. */
92593c
+        retval = ESOCKTNOSUPPORT;
92593c
+        goto error;
92593c
+    }
92593c
 
92593c
     K5_TAILQ_FOREACH(r, &rr->list, list) {
92593c
         if (r->request == tmp) {
92593c
diff --git a/src/lib/krad/t_attr.c b/src/lib/krad/t_attr.c
92593c
index eb2a780c8..4d285ad9d 100644
92593c
--- a/src/lib/krad/t_attr.c
92593c
+++ b/src/lib/krad/t_attr.c
92593c
@@ -50,6 +50,7 @@ main()
92593c
     const char *tmp;
92593c
     krb5_data in;
92593c
     size_t len;
92593c
+    krb5_boolean is_fips = FALSE;
92593c
 
92593c
     noerror(krb5_init_context(&ctx));
92593c
 
92593c
@@ -73,7 +74,7 @@ main()
92593c
     in = string2data((char *)decoded);
92593c
     retval = kr_attr_encode(ctx, secret, auth,
92593c
                             krad_attr_name2num("User-Password"),
92593c
-                            &in, outbuf, &len;;
92593c
+                            &in, outbuf, &len, &is_fips);
92593c
     insist(retval == 0);
92593c
     insist(len == sizeof(encoded));
92593c
     insist(memcmp(outbuf, encoded, len) == 0);
92593c
diff --git a/src/lib/krad/t_attrset.c b/src/lib/krad/t_attrset.c
92593c
index 7928335ca..0f9576253 100644
92593c
--- a/src/lib/krad/t_attrset.c
92593c
+++ b/src/lib/krad/t_attrset.c
92593c
@@ -49,6 +49,7 @@ main()
92593c
     krb5_context ctx;
92593c
     size_t len = 0, encode_len;
92593c
     krb5_data tmp;
92593c
+    krb5_boolean is_fips = FALSE;
92593c
 
92593c
     noerror(krb5_init_context(&ctx));
92593c
     noerror(krad_attrset_new(ctx, &set);;
92593c
@@ -62,7 +63,8 @@ main()
92593c
     noerror(krad_attrset_add(set, krad_attr_name2num("User-Password"), &tmp));
92593c
 
92593c
     /* Encode attrset. */
92593c
-    noerror(kr_attrset_encode(set, "foo", auth, buffer, &encode_len));
92593c
+    noerror(kr_attrset_encode(set, "foo", auth, buffer, &encode_len,
92593c
+                              &is_fips));
92593c
     krad_attrset_free(set);
92593c
 
92593c
     /* Manually encode User-Name. */
92593c
diff --git a/src/plugins/preauth/spake/spake_client.c b/src/plugins/preauth/spake/spake_client.c
92593c
index 00734a13b..a3ce22b70 100644
92593c
--- a/src/plugins/preauth/spake/spake_client.c
92593c
+++ b/src/plugins/preauth/spake/spake_client.c
92593c
@@ -38,6 +38,8 @@
92593c
 #include "groups.h"
92593c
 #include <krb5/clpreauth_plugin.h>
92593c
 
92593c
+#include <openssl/crypto.h>
92593c
+
92593c
 typedef struct reqstate_st {
92593c
     krb5_pa_spake *msg;         /* set in prep_questions, used in process */
92593c
     krb5_keyblock *initial_key;
92593c
@@ -375,6 +377,10 @@ clpreauth_spake_initvt(krb5_context context, int maj_ver, int min_ver,
92593c
 
92593c
     if (maj_ver != 1)
92593c
         return KRB5_PLUGIN_VER_NOTSUPP;
92593c
+
92593c
+    if (FIPS_mode())
92593c
+        return KRB5_CRYPTO_INTERNAL;
92593c
+
92593c
     vt = (krb5_clpreauth_vtable)vtable;
92593c
     vt->name = "spake";
92593c
     vt->pa_type_list = pa_types;
92593c
diff --git a/src/plugins/preauth/spake/spake_kdc.c b/src/plugins/preauth/spake/spake_kdc.c
92593c
index 59e88409e..1b3e569e9 100644
92593c
--- a/src/plugins/preauth/spake/spake_kdc.c
92593c
+++ b/src/plugins/preauth/spake/spake_kdc.c
92593c
@@ -41,6 +41,8 @@
92593c
 
92593c
 #include <krb5/kdcpreauth_plugin.h>
92593c
 
92593c
+#include <openssl/crypto.h>
92593c
+
92593c
 /*
92593c
  * The SPAKE kdcpreauth module uses a secure cookie containing the following
92593c
  * concatenated fields (all integer fields are big-endian):
92593c
@@ -578,6 +580,10 @@ kdcpreauth_spake_initvt(krb5_context context, int maj_ver, int min_ver,
92593c
 
92593c
     if (maj_ver != 1)
92593c
         return KRB5_PLUGIN_VER_NOTSUPP;
92593c
+
92593c
+    if (FIPS_mode())
92593c
+        return KRB5_CRYPTO_INTERNAL;
92593c
+
92593c
     vt = (krb5_kdcpreauth_vtable)vtable;
92593c
     vt->name = "spake";
92593c
     vt->pa_type_list = pa_types;