diff --git a/.gitignore b/.gitignore
index f9809d6..045d4b9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,2 @@
-SOURCES/krb5-1.17-pdfs.tar
-SOURCES/krb5-1.17.tar.gz
+SOURCES/krb5-1.18.2-pdfs.tar
+SOURCES/krb5-1.18.2.tar.gz
diff --git a/.krb5.metadata b/.krb5.metadata
index 5858b94..d1787a9 100644
--- a/.krb5.metadata
+++ b/.krb5.metadata
@@ -1,2 +1,2 @@
-494c62bea08e5d26e01d47c409ac745b65e509c8 SOURCES/krb5-1.17-pdfs.tar
-0c404b081db9c996c581f636ce450ee28778f338 SOURCES/krb5-1.17.tar.gz
+db930a6653503c36027a4f65d761f8838c7636ae SOURCES/krb5-1.18.2-pdfs.tar
+547c4e4afa06dd39c888a9ee89397ec3c3425c90 SOURCES/krb5-1.18.2.tar.gz
diff --git a/SOURCES/Add-finalization-safety-check-to-com_err.patch b/SOURCES/Add-finalization-safety-check-to-com_err.patch
new file mode 100644
index 0000000..f7c9d54
--- /dev/null
+++ b/SOURCES/Add-finalization-safety-check-to-com_err.patch
@@ -0,0 +1,54 @@
+From 2ea85d8228663c9592705a13edecbd4d3c70aac1 Mon Sep 17 00:00:00 2001
+From: Jiri Sasek <Jiri.Sasek@Oracle.COM>
+Date: Fri, 13 Mar 2020 19:02:58 +0100
+Subject: [PATCH] Add finalization safety check to com_err
+
+If the linker erroneously runs the libkrb5 finalizer after the
+libcom_err finalizer, the consequent remove_error_table() calls could
+crash due to accessing a destroyed mutex or an invalid et_list
+pointer.  Add an unsynchronized check on finalized in
+remove_error_table(), and set et_list to null in com_err_terminate()
+after destroying the list.
+
+[ghudson@mit.edu: minimized code hanges; rewrote comment and commit
+message]
+
+ticket: 8890 (new)
+(cherry picked from commit 9d654aa05e26bbf22f140abde3436afeff2fdf8d)
+(cherry picked from commit c7a37d3e87132864ebc44710baf1d50a69682b5c)
+---
+ src/util/et/error_message.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/src/util/et/error_message.c b/src/util/et/error_message.c
+index d7069a9df..7dc02a34e 100644
+--- a/src/util/et/error_message.c
++++ b/src/util/et/error_message.c
+@@ -26,7 +26,7 @@
+ 
+ static struct et_list *et_list;
+ static k5_mutex_t et_list_lock = K5_MUTEX_PARTIAL_INITIALIZER;
+-static int terminated = 0;      /* for debugging shlib fini sequence errors */
++static int terminated = 0;      /* for safety and finalization debugging */
+ 
+ MAKE_INIT_FUNCTION(com_err_initialize);
+ MAKE_FINI_FUNCTION(com_err_terminate);
+@@ -69,6 +69,7 @@ void com_err_terminate(void)
+         enext = e->next;
+         free(e);
+     }
++    et_list = NULL;
+     k5_mutex_unlock(&et_list_lock);
+     k5_mutex_destroy(&et_list_lock);
+     terminated = 1;
+@@ -280,6 +281,10 @@ remove_error_table(const struct error_table *et)
+ {
+     struct et_list **ep, *e;
+ 
++    /* Safety check in case libraries are finalized in the wrong order. */
++    if (terminated)
++        return ENOENT;
++
+     if (CALL_INIT_FUNCTION(com_err_initialize))
+         return 0;
+     k5_mutex_lock(&et_list_lock);
diff --git a/SOURCES/Add-function-and-enctype-flag-for-deprecations.patch b/SOURCES/Add-function-and-enctype-flag-for-deprecations.patch
deleted file mode 100644
index 2a094e7..0000000
--- a/SOURCES/Add-function-and-enctype-flag-for-deprecations.patch
+++ /dev/null
@@ -1,183 +0,0 @@
-From ba1fd0a44c74089d42af244ff2b315baf506fd2f Mon Sep 17 00:00:00 2001
-From: Robbie Harwood <rharwood@redhat.com>
-Date: Tue, 15 Jan 2019 16:16:57 -0500
-Subject: [PATCH] Add function and enctype flag for deprecations
-
-krb5int_c_deprecated_enctype() checks for the ETYPE_DEPRECATED flag on
-enctypes.  All ENCTYPE_WEAK enctypes are currently deprecated; not all
-deprecated enctypes are considered weak.  Deprecations follow RFC 6649
-and RFC 8429.
-
-(cherry picked from commit 484a6e7712f9b66e782b2520f07b0883889e116f)
----
- src/include/k5-int.h               |  1 +
- src/lib/crypto/krb/crypto_int.h    |  9 ++++++++-
- src/lib/crypto/krb/enctype_util.c  |  7 +++++++
- src/lib/crypto/krb/etypes.c        | 19 ++++++++++---------
- src/lib/crypto/libk5crypto.exports |  1 +
- src/lib/krb5_32.def                |  3 +++
- 6 files changed, 30 insertions(+), 10 deletions(-)
-
-diff --git a/src/include/k5-int.h b/src/include/k5-int.h
-index 8f9329c59..255cee822 100644
---- a/src/include/k5-int.h
-+++ b/src/include/k5-int.h
-@@ -2077,6 +2077,7 @@ krb5_get_tgs_ktypes(krb5_context, krb5_const_principal, krb5_enctype **);
- krb5_boolean krb5_is_permitted_enctype(krb5_context, krb5_enctype);
- 
- krb5_boolean KRB5_CALLCONV krb5int_c_weak_enctype(krb5_enctype);
-+krb5_boolean KRB5_CALLCONV krb5int_c_deprecated_enctype(krb5_enctype);
- krb5_error_code k5_enctype_to_ssf(krb5_enctype enctype, unsigned int *ssf_out);
- 
- krb5_error_code krb5_kdc_rep_decrypt_proc(krb5_context, const krb5_keyblock *,
-diff --git a/src/lib/crypto/krb/crypto_int.h b/src/lib/crypto/krb/crypto_int.h
-index e5099291e..6c1c77cac 100644
---- a/src/lib/crypto/krb/crypto_int.h
-+++ b/src/lib/crypto/krb/crypto_int.h
-@@ -114,7 +114,14 @@ struct krb5_keytypes {
-     unsigned int ssf;
- };
- 
--#define ETYPE_WEAK 1
-+/*
-+ * "Weak" means the enctype is believed to be vulnerable to practical attacks,
-+ * and will be disabled unless allow_weak_crypto is set to true.  "Deprecated"
-+ * means the enctype has been deprecated by the IETF, and affects display and
-+ * logging.
-+ */
-+#define ETYPE_WEAK (1 << 0)
-+#define ETYPE_DEPRECATED (1 << 1)
- 
- extern const struct krb5_keytypes krb5int_enctypes_list[];
- extern const int krb5int_enctypes_length;
-diff --git a/src/lib/crypto/krb/enctype_util.c b/src/lib/crypto/krb/enctype_util.c
-index b1b40e7ec..e394f4e19 100644
---- a/src/lib/crypto/krb/enctype_util.c
-+++ b/src/lib/crypto/krb/enctype_util.c
-@@ -51,6 +51,13 @@ krb5int_c_weak_enctype(krb5_enctype etype)
-     return (ktp != NULL && (ktp->flags & ETYPE_WEAK) != 0);
- }
- 
-+krb5_boolean KRB5_CALLCONV
-+krb5int_c_deprecated_enctype(krb5_enctype etype)
-+{
-+    const struct krb5_keytypes *ktp = find_enctype(etype);
-+    return ktp != NULL && (ktp->flags & ETYPE_DEPRECATED) != 0;
-+}
-+
- krb5_error_code KRB5_CALLCONV
- krb5_c_enctype_compare(krb5_context context, krb5_enctype e1, krb5_enctype e2,
-                        krb5_boolean *similar)
-diff --git a/src/lib/crypto/krb/etypes.c b/src/lib/crypto/krb/etypes.c
-index 53d4a5c79..8f44c37e7 100644
---- a/src/lib/crypto/krb/etypes.c
-+++ b/src/lib/crypto/krb/etypes.c
-@@ -33,6 +33,7 @@
-    that the keytypes are all near each other.  I'd rather not make
-    that assumption. */
- 
-+/* Deprecations come from RFC 6649 and RFC 8249. */
- const struct krb5_keytypes krb5int_enctypes_list[] = {
-     { ENCTYPE_DES_CBC_CRC,
-       "des-cbc-crc", { 0 }, "DES cbc mode with CRC-32",
-@@ -42,7 +43,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
-       krb5int_des_string_to_key, k5_rand2key_des,
-       krb5int_des_prf,
-       CKSUMTYPE_RSA_MD5_DES,
--      ETYPE_WEAK, 56 },
-+      ETYPE_WEAK | ETYPE_DEPRECATED, 56 },
-     { ENCTYPE_DES_CBC_MD4,
-       "des-cbc-md4", { 0 }, "DES cbc mode with RSA-MD4",
-       &krb5int_enc_des, &krb5int_hash_md4,
-@@ -51,7 +52,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
-       krb5int_des_string_to_key, k5_rand2key_des,
-       krb5int_des_prf,
-       CKSUMTYPE_RSA_MD4_DES,
--      ETYPE_WEAK, 56 },
-+      ETYPE_WEAK | ETYPE_DEPRECATED, 56 },
-     { ENCTYPE_DES_CBC_MD5,
-       "des-cbc-md5", { "des" }, "DES cbc mode with RSA-MD5",
-       &krb5int_enc_des, &krb5int_hash_md5,
-@@ -60,7 +61,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
-       krb5int_des_string_to_key, k5_rand2key_des,
-       krb5int_des_prf,
-       CKSUMTYPE_RSA_MD5_DES,
--      ETYPE_WEAK, 56 },
-+      ETYPE_WEAK | ETYPE_DEPRECATED, 56 },
-     { ENCTYPE_DES_CBC_RAW,
-       "des-cbc-raw", { 0 }, "DES cbc mode raw",
-       &krb5int_enc_des, NULL,
-@@ -69,7 +70,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
-       krb5int_des_string_to_key, k5_rand2key_des,
-       krb5int_des_prf,
-       0,
--      ETYPE_WEAK, 56 },
-+      ETYPE_WEAK | ETYPE_DEPRECATED, 56 },
-     { ENCTYPE_DES3_CBC_RAW,
-       "des3-cbc-raw", { 0 }, "Triple DES cbc mode raw",
-       &krb5int_enc_des3, NULL,
-@@ -78,7 +79,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
-       krb5int_dk_string_to_key, k5_rand2key_des3,
-       NULL, /*PRF*/
-       0,
--      ETYPE_WEAK, 112 },
-+      ETYPE_WEAK | ETYPE_DEPRECATED, 112 },
- 
-     { ENCTYPE_DES3_CBC_SHA1,
-       "des3-cbc-sha1", { "des3-hmac-sha1", "des3-cbc-sha1-kd" },
-@@ -89,7 +90,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
-       krb5int_dk_string_to_key, k5_rand2key_des3,
-       krb5int_dk_prf,
-       CKSUMTYPE_HMAC_SHA1_DES3,
--      0 /*flags*/, 112 },
-+      ETYPE_DEPRECATED, 112 },
- 
-     { ENCTYPE_DES_HMAC_SHA1,
-       "des-hmac-sha1", { 0 }, "DES with HMAC/sha1",
-@@ -99,7 +100,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
-       krb5int_dk_string_to_key, k5_rand2key_des,
-       NULL, /*PRF*/
-       0,
--      ETYPE_WEAK, 56 },
-+      ETYPE_WEAK | ETYPE_DEPRECATED, 56 },
- 
-     /* rc4-hmac uses a 128-bit key, but due to weaknesses in the RC4 cipher, we
-      * consider its strength degraded and assign it an SSF value of 64. */
-@@ -113,7 +114,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
-       krb5int_arcfour_decrypt, krb5int_arcfour_string_to_key,
-       k5_rand2key_direct, krb5int_arcfour_prf,
-       CKSUMTYPE_HMAC_MD5_ARCFOUR,
--      0 /*flags*/, 64 },
-+      ETYPE_DEPRECATED, 64 },
-     { ENCTYPE_ARCFOUR_HMAC_EXP,
-       "arcfour-hmac-exp", { "rc4-hmac-exp", "arcfour-hmac-md5-exp" },
-       "Exportable ArcFour with HMAC/md5",
-@@ -124,7 +125,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
-       krb5int_arcfour_decrypt, krb5int_arcfour_string_to_key,
-       k5_rand2key_direct, krb5int_arcfour_prf,
-       CKSUMTYPE_HMAC_MD5_ARCFOUR,
--      ETYPE_WEAK, 40
-+      ETYPE_WEAK | ETYPE_DEPRECATED, 40
-     },
- 
-     { ENCTYPE_AES128_CTS_HMAC_SHA1_96,
-diff --git a/src/lib/crypto/libk5crypto.exports b/src/lib/crypto/libk5crypto.exports
-index 82eb5f30c..90afdf5f7 100644
---- a/src/lib/crypto/libk5crypto.exports
-+++ b/src/lib/crypto/libk5crypto.exports
-@@ -109,3 +109,4 @@ k5_allow_weak_pbkdf2iter
- krb5_c_prfplus
- krb5_c_derive_prfplus
- k5_enctype_to_ssf
-+krb5int_c_deprecated_enctype
-diff --git a/src/lib/krb5_32.def b/src/lib/krb5_32.def
-index c35022931..e6a487593 100644
---- a/src/lib/krb5_32.def
-+++ b/src/lib/krb5_32.def
-@@ -487,3 +487,6 @@ EXPORTS
- 	encode_krb5_pa_spake				@444 ; PRIVATE
- 	decode_krb5_pa_spake				@445 ; PRIVATE
- 	k5_free_pa_spake				@446 ; PRIVATE
-+
-+; new in 1.18
-+	krb5int_c_deprecated_enctype			@450 ; PRIVATE
diff --git a/SOURCES/Add-soft-pkcs11-source-code.patch b/SOURCES/Add-soft-pkcs11-source-code.patch
deleted file mode 100644
index 25488b5..0000000
--- a/SOURCES/Add-soft-pkcs11-source-code.patch
+++ /dev/null
@@ -1,2072 +0,0 @@
-From c4626f17ece51265eaa5446e96104b115ecbe31c Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Thu, 20 Jun 2019 10:45:18 -0400
-Subject: [PATCH] Add soft-pkcs11 source code
-
-soft-pkcs11 is no longer available upstream and is not generally
-packaged in distributions, making it inconvenient to use for tests.
-Import the 1.8 source code, detabified and with trailing whitespace
-removed but otherwise unmodified.
-
-(cherry picked from commit a4bc3e513a58b0d1292f3506ac3b35be8c178086)
-(cherry picked from commit a186597238ae40e167ce041857b5bd1f94ee2383)
----
- src/tests/softpkcs11/main.c | 2049 +++++++++++++++++++++++++++++++++++
- 1 file changed, 2049 insertions(+)
- create mode 100644 src/tests/softpkcs11/main.c
-
-diff --git a/src/tests/softpkcs11/main.c b/src/tests/softpkcs11/main.c
-new file mode 100644
-index 000000000..2acec5169
---- /dev/null
-+++ b/src/tests/softpkcs11/main.c
-@@ -0,0 +1,2049 @@
-+/*
-+ * Copyright (c) 2004-2006, Stockholms universitet
-+ * (Stockholm University, Stockholm Sweden)
-+ * All rights reserved.
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions
-+ * are met:
-+ *
-+ * 1. Redistributions of source code must retain the above copyright
-+ *    notice, this list of conditions and the following disclaimer.
-+ *
-+ * 2. Redistributions in binary form must reproduce the above copyright
-+ *    notice, this list of conditions and the following disclaimer in the
-+ *    documentation and/or other materials provided with the distribution.
-+ *
-+ * 3. Neither the name of the university nor the names of its contributors
-+ *    may be used to endorse or promote products derived from this software
-+ *    without specific prior written permission.
-+ *
-+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-+ * POSSIBILITY OF SUCH DAMAGE.
-+ */
-+
-+#include "locl.h"
-+
-+/* RCSID("$Id: main.c,v 1.24 2006/01/11 12:42:53 lha Exp $"); */
-+
-+#define OBJECT_ID_MASK          0xfff
-+#define HANDLE_OBJECT_ID(h)     ((h) & OBJECT_ID_MASK)
-+#define OBJECT_ID(obj)          HANDLE_OBJECT_ID((obj)->object_handle)
-+
-+struct st_attr {
-+    CK_ATTRIBUTE attribute;
-+    int secret;
-+};
-+
-+struct st_object {
-+    CK_OBJECT_HANDLE object_handle;
-+    struct st_attr *attrs;
-+    int num_attributes;
-+    enum {
-+        STO_T_CERTIFICATE,
-+        STO_T_PRIVATE_KEY,
-+        STO_T_PUBLIC_KEY
-+    } type;
-+    union {
-+        X509 *cert;
-+        EVP_PKEY *public_key;
-+        struct {
-+            const char *file;
-+            EVP_PKEY *key;
-+            X509 *cert;
-+        } private_key;
-+    } u;
-+};
-+
-+static struct soft_token {
-+    CK_VOID_PTR application;
-+    CK_NOTIFY notify;
-+    struct {
-+        struct st_object **objs;
-+        int num_objs;
-+    } object;
-+    struct {
-+        int hardware_slot;
-+        int app_error_fatal;
-+        int login_done;
-+    } flags;
-+    int open_sessions;
-+    struct session_state {
-+        CK_SESSION_HANDLE session_handle;
-+
-+        struct {
-+            CK_ATTRIBUTE *attributes;
-+            CK_ULONG num_attributes;
-+            int next_object;
-+        } find;
-+
-+        int encrypt_object;
-+        CK_MECHANISM_PTR encrypt_mechanism;
-+        int decrypt_object;
-+        CK_MECHANISM_PTR decrypt_mechanism;
-+        int sign_object;
-+        CK_MECHANISM_PTR sign_mechanism;
-+        int verify_object;
-+        CK_MECHANISM_PTR verify_mechanism;
-+        int digest_object;
-+    } state[10];
-+#define MAX_NUM_SESSION (sizeof(soft_token.state)/sizeof(soft_token.state[0]))
-+    FILE *logfile;
-+} soft_token;
-+
-+static void
-+application_error(const char *fmt, ...)
-+{
-+    va_list ap;
-+    va_start(ap, fmt);
-+    vprintf(fmt, ap);
-+    va_end(ap);
-+    if (soft_token.flags.app_error_fatal)
-+        abort();
-+}
-+
-+static void
-+st_logf(const char *fmt, ...)
-+{
-+    va_list ap;
-+    if (soft_token.logfile == NULL)
-+        return;
-+    va_start(ap, fmt);
-+    vfprintf(soft_token.logfile, fmt, ap);
-+    va_end(ap);
-+    fflush(soft_token.logfile);
-+}
-+
-+static void
-+snprintf_fill(char *str, size_t size, char fillchar, const char *fmt, ...)
-+{
-+    int len;
-+    va_list ap;
-+    len = vsnprintf(str, size, fmt, ap);
-+    va_end(ap);
-+    if (len < 0 || len > size)
-+        return;
-+    while(len < size)
-+        str[len++] = fillchar;
-+}
-+
-+#ifndef TEST_APP
-+#define printf error_use_st_logf
-+#endif
-+
-+#define VERIFY_SESSION_HANDLE(s, state)                 \
-+{                                                       \
-+    CK_RV ret;                                          \
-+    ret = verify_session_handle(s, state);              \
-+    if (ret != CKR_OK) {                                \
-+        /* return CKR_OK */;                            \
-+    }                                                   \
-+}
-+
-+static CK_RV
-+verify_session_handle(CK_SESSION_HANDLE hSession,
-+                      struct session_state **state)
-+{
-+    int i;
-+
-+    for (i = 0; i < MAX_NUM_SESSION; i++){
-+        if (soft_token.state[i].session_handle == hSession)
-+            break;
-+    }
-+    if (i == MAX_NUM_SESSION) {
-+        application_error("use of invalid handle: 0x%08lx\n",
-+                          (unsigned long)hSession);
-+        return CKR_SESSION_HANDLE_INVALID;
-+    }
-+    if (state)
-+        *state = &soft_token.state[i];
-+    return CKR_OK;
-+}
-+
-+static CK_RV
-+object_handle_to_object(CK_OBJECT_HANDLE handle,
-+                        struct st_object **object)
-+{
-+    int i = HANDLE_OBJECT_ID(handle);
-+
-+    *object = NULL;
-+    if (i >= soft_token.object.num_objs)
-+        return CKR_ARGUMENTS_BAD;
-+    if (soft_token.object.objs[i] == NULL)
-+        return CKR_ARGUMENTS_BAD;
-+    if (soft_token.object.objs[i]->object_handle != handle)
-+        return CKR_ARGUMENTS_BAD;
-+    *object = soft_token.object.objs[i];
-+    return CKR_OK;
-+}
-+
-+static int
-+attributes_match(const struct st_object *obj,
-+                 const CK_ATTRIBUTE *attributes,
-+                 CK_ULONG num_attributes)
-+{
-+    CK_ULONG i;
-+    int j;
-+    st_logf("attributes_match: %ld\n", (unsigned long)OBJECT_ID(obj));
-+
-+    for (i = 0; i < num_attributes; i++) {
-+        int match = 0;
-+        for (j = 0; j < obj->num_attributes; j++) {
-+            if (attributes[i].type == obj->attrs[j].attribute.type &&
-+                attributes[i].ulValueLen == obj->attrs[j].attribute.ulValueLen &&
-+                memcmp(attributes[i].pValue, obj->attrs[j].attribute.pValue,
-+                       attributes[i].ulValueLen) == 0) {
-+                match = 1;
-+                break;
-+            }
-+        }
-+        if (match == 0) {
-+            st_logf("type %d attribute have no match\n", attributes[i].type);
-+            return 0;
-+        }
-+    }
-+    st_logf("attribute matches\n");
-+    return 1;
-+}
-+
-+static void
-+print_attributes(const CK_ATTRIBUTE *attributes,
-+                 CK_ULONG num_attributes)
-+{
-+    CK_ULONG i;
-+
-+    st_logf("find objects: attrs: %lu\n", (unsigned long)num_attributes);
-+
-+    for (i = 0; i < num_attributes; i++) {
-+        st_logf("  type: ");
-+        switch (attributes[i].type) {
-+        case CKA_TOKEN: {
-+            CK_BBOOL *ck_true;
-+            if (attributes[i].ulValueLen != sizeof(CK_BBOOL)) {
-+                application_error("token attribute wrong length\n");
-+                break;
-+            }
-+            ck_true = attributes[i].pValue;
-+            st_logf("token: %s", *ck_true ? "TRUE" : "FALSE");
-+            break;
-+        }
-+        case CKA_CLASS: {
-+            CK_OBJECT_CLASS *class;
-+            if (attributes[i].ulValueLen != sizeof(CK_ULONG)) {
-+                application_error("class attribute wrong length\n");
-+                break;
-+            }
-+            class = attributes[i].pValue;
-+            st_logf("class ");
-+            switch (*class) {
-+            case CKO_CERTIFICATE:
-+                st_logf("certificate");
-+                break;
-+            case CKO_PUBLIC_KEY:
-+                st_logf("public key");
-+                break;
-+            case CKO_PRIVATE_KEY:
-+                st_logf("private key");
-+                break;
-+            case CKO_SECRET_KEY:
-+                st_logf("secret key");
-+                break;
-+            case CKO_DOMAIN_PARAMETERS:
-+                st_logf("domain parameters");
-+                break;
-+            default:
-+                st_logf("[class %lx]", (long unsigned)*class);
-+                break;
-+            }
-+            break;
-+        }
-+        case CKA_PRIVATE:
-+            st_logf("private");
-+            break;
-+        case CKA_LABEL:
-+            st_logf("label");
-+            break;
-+        case CKA_APPLICATION:
-+            st_logf("application");
-+            break;
-+        case CKA_VALUE:
-+            st_logf("value");
-+            break;
-+        case CKA_ID:
-+            st_logf("id");
-+            break;
-+        default:
-+            st_logf("[unknown 0x%08lx]", (unsigned long)attributes[i].type);
-+            break;
-+        }
-+        st_logf("\n");
-+    }
-+}
-+
-+static struct st_object *
-+add_st_object(void)
-+{
-+    struct st_object *o, **objs;
-+    int i;
-+
-+    o = malloc(sizeof(*o));
-+    if (o == NULL)
-+        return NULL;
-+    memset(o, 0, sizeof(*o));
-+    o->attrs = NULL;
-+    o->num_attributes = 0;
-+
-+    for (i = 0; i < soft_token.object.num_objs; i++) {
-+        if (soft_token.object.objs == NULL) {
-+            soft_token.object.objs[i] = o;
-+            break;
-+        }
-+    }
-+    if (i == soft_token.object.num_objs) {
-+        objs = realloc(soft_token.object.objs,
-+                       (soft_token.object.num_objs + 1) * sizeof(soft_token.object.objs[0]));
-+        if (objs == NULL) {
-+            free(o);
-+            return NULL;
-+        }
-+        soft_token.object.objs = objs;
-+        soft_token.object.objs[soft_token.object.num_objs++] = o;
-+    }
-+    soft_token.object.objs[i]->object_handle =
-+        (random() & (~OBJECT_ID_MASK)) | i;
-+
-+    return o;
-+}
-+
-+static CK_RV
-+add_object_attribute(struct st_object *o,
-+                     int secret,
-+                     CK_ATTRIBUTE_TYPE type,
-+                     CK_VOID_PTR pValue,
-+                     CK_ULONG ulValueLen)
-+{
-+    struct st_attr *a;
-+    int i;
-+
-+    i = o->num_attributes;
-+    a = realloc(o->attrs, (i + 1) * sizeof(o->attrs[0]));
-+    if (a == NULL)
-+        return CKR_DEVICE_MEMORY;
-+    o->attrs = a;
-+    o->attrs[i].secret = secret;
-+    o->attrs[i].attribute.type = type;
-+    o->attrs[i].attribute.pValue = malloc(ulValueLen);
-+    if (o->attrs[i].attribute.pValue == NULL && ulValueLen != 0)
-+        return CKR_DEVICE_MEMORY;
-+    memcpy(o->attrs[i].attribute.pValue, pValue, ulValueLen);
-+    o->attrs[i].attribute.ulValueLen = ulValueLen;
-+    o->num_attributes++;
-+
-+    return CKR_OK;
-+}
-+
-+static CK_RV
-+add_pubkey_info(struct st_object *o, CK_KEY_TYPE key_type, EVP_PKEY *key)
-+{
-+    switch (key_type) {
-+    case CKK_RSA: {
-+        CK_BYTE *modulus = NULL;
-+        size_t modulus_len = 0;
-+        CK_ULONG modulus_bits = 0;
-+        CK_BYTE *exponent = NULL;
-+        size_t exponent_len = 0;
-+
-+        modulus_bits = BN_num_bits(key->pkey.rsa->n);
-+
-+        modulus_len = BN_num_bytes(key->pkey.rsa->n);
-+        modulus = malloc(modulus_len);
-+        BN_bn2bin(key->pkey.rsa->n, modulus);
-+
-+        exponent_len = BN_num_bytes(key->pkey.rsa->e);
-+        exponent = malloc(exponent_len);
-+        BN_bn2bin(key->pkey.rsa->e, exponent);
-+
-+        add_object_attribute(o, 0, CKA_MODULUS, modulus, modulus_len);
-+        add_object_attribute(o, 0, CKA_MODULUS_BITS,
-+                             &modulus_bits, sizeof(modulus_bits));
-+        add_object_attribute(o, 0, CKA_PUBLIC_EXPONENT,
-+                             exponent, exponent_len);
-+
-+        RSA_set_method(key->pkey.rsa, RSA_PKCS1_SSLeay());
-+
-+        free(modulus);
-+        free(exponent);
-+    }
-+    default:
-+        /* XXX */
-+        break;
-+    }
-+    return CKR_OK;
-+}
-+
-+
-+static int
-+pem_callback(char *buf, int num, int w, void *key)
-+{
-+    return -1;
-+}
-+
-+
-+static CK_RV
-+add_certificate(char *label,
-+                const char *cert_file,
-+                const char *private_key_file,
-+                char *id,
-+                int anchor)
-+{
-+    struct st_object *o = NULL;
-+    CK_BBOOL bool_true = CK_TRUE;
-+    CK_BBOOL bool_false = CK_FALSE;
-+    CK_OBJECT_CLASS c;
-+    CK_CERTIFICATE_TYPE cert_type = CKC_X_509;
-+    CK_KEY_TYPE key_type;
-+    CK_MECHANISM_TYPE mech_type;
-+    void *cert_data = NULL;
-+    size_t cert_length;
-+    void *subject_data = NULL;
-+    size_t subject_length;
-+    void *issuer_data = NULL;
-+    size_t issuer_length;
-+    void *serial_data = NULL;
-+    size_t serial_length;
-+    CK_RV ret = CKR_GENERAL_ERROR;
-+    X509 *cert;
-+    EVP_PKEY *public_key;
-+
-+    size_t id_len = strlen(id);
-+
-+    {
-+        FILE *f;
-+
-+        f = fopen(cert_file, "r");
-+        if (f == NULL) {
-+            st_logf("failed to open file %s\n", cert_file);
-+            return CKR_GENERAL_ERROR;
-+        }
-+
-+        cert = PEM_read_X509(f, NULL, NULL, NULL);
-+        fclose(f);
-+        if (cert == NULL) {
-+            st_logf("failed reading PEM cert\n");
-+            return CKR_GENERAL_ERROR;
-+        }
-+
-+        OPENSSL_ASN1_MALLOC_ENCODE(X509, cert_data, cert_length, cert, ret);
-+        if (ret)
-+            goto out;
-+
-+        OPENSSL_ASN1_MALLOC_ENCODE(X509_NAME, issuer_data, issuer_length,
-+                                   X509_get_issuer_name(cert), ret);
-+        if (ret)
-+            goto out;
-+
-+        OPENSSL_ASN1_MALLOC_ENCODE(X509_NAME, subject_data, subject_length,
-+                                   X509_get_subject_name(cert), ret);
-+        if (ret)
-+            goto out;
-+
-+        OPENSSL_ASN1_MALLOC_ENCODE(ASN1_INTEGER, serial_data, serial_length,
-+                                   X509_get_serialNumber(cert), ret);
-+        if (ret)
-+            goto out;
-+
-+    }
-+
-+    st_logf("done parsing, adding to internal structure\n");
-+
-+    o = add_st_object();
-+    if (o == NULL) {
-+        ret = CKR_DEVICE_MEMORY;
-+        goto out;
-+    }
-+    o->type = STO_T_CERTIFICATE;
-+    o->u.cert = cert;
-+    public_key = X509_get_pubkey(o->u.cert);
-+
-+    switch (EVP_PKEY_type(public_key->type)) {
-+    case EVP_PKEY_RSA:
-+        key_type = CKK_RSA;
-+        break;
-+    case EVP_PKEY_DSA:
-+        key_type = CKK_DSA;
-+        break;
-+    default:
-+        /* XXX */
-+        break;
-+    }
-+
-+    c = CKO_CERTIFICATE;
-+    add_object_attribute(o, 0, CKA_CLASS, &c, sizeof(c));
-+    add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true));
-+    add_object_attribute(o, 0, CKA_PRIVATE, &bool_false, sizeof(bool_false));
-+    add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false));
-+    add_object_attribute(o, 0, CKA_LABEL, label, strlen(label));
-+
-+    add_object_attribute(o, 0, CKA_CERTIFICATE_TYPE, &cert_type, sizeof(cert_type));
-+    add_object_attribute(o, 0, CKA_ID, id, id_len);
-+
-+    add_object_attribute(o, 0, CKA_SUBJECT, subject_data, subject_length);
-+    add_object_attribute(o, 0, CKA_ISSUER, issuer_data, issuer_length);
-+    add_object_attribute(o, 0, CKA_SERIAL_NUMBER, serial_data, serial_length);
-+    add_object_attribute(o, 0, CKA_VALUE, cert_data, cert_length);
-+    if (anchor)
-+        add_object_attribute(o, 0, CKA_TRUSTED, &bool_true, sizeof(bool_true));
-+    else
-+        add_object_attribute(o, 0, CKA_TRUSTED, &bool_false, sizeof(bool_false));
-+
-+    st_logf("add cert ok: %lx\n", (unsigned long)OBJECT_ID(o));
-+
-+    o = add_st_object();
-+    if (o == NULL) {
-+        ret = CKR_DEVICE_MEMORY;
-+        goto out;
-+    }
-+    o->type = STO_T_PUBLIC_KEY;
-+    o->u.public_key = public_key;
-+
-+    c = CKO_PUBLIC_KEY;
-+    add_object_attribute(o, 0, CKA_CLASS, &c, sizeof(c));
-+    add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true));
-+    add_object_attribute(o, 0, CKA_PRIVATE, &bool_false, sizeof(bool_false));
-+    add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false));
-+    add_object_attribute(o, 0, CKA_LABEL, label, strlen(label));
-+
-+    add_object_attribute(o, 0, CKA_KEY_TYPE, &key_type, sizeof(key_type));
-+    add_object_attribute(o, 0, CKA_ID, id, id_len);
-+    add_object_attribute(o, 0, CKA_START_DATE, "", 1); /* XXX */
-+    add_object_attribute(o, 0, CKA_END_DATE, "", 1); /* XXX */
-+    add_object_attribute(o, 0, CKA_DERIVE, &bool_false, sizeof(bool_false));
-+    add_object_attribute(o, 0, CKA_LOCAL, &bool_false, sizeof(bool_false));
-+    mech_type = CKM_RSA_X_509;
-+    add_object_attribute(o, 0, CKA_KEY_GEN_MECHANISM, &mech_type, sizeof(mech_type));
-+
-+    add_object_attribute(o, 0, CKA_SUBJECT, subject_data, subject_length);
-+    add_object_attribute(o, 0, CKA_ENCRYPT, &bool_true, sizeof(bool_true));
-+    add_object_attribute(o, 0, CKA_VERIFY, &bool_true, sizeof(bool_true));
-+    add_object_attribute(o, 0, CKA_VERIFY_RECOVER, &bool_false, sizeof(bool_false));
-+    add_object_attribute(o, 0, CKA_WRAP, &bool_true, sizeof(bool_true));
-+    add_object_attribute(o, 0, CKA_TRUSTED, &bool_true, sizeof(bool_true));
-+
-+    add_pubkey_info(o, key_type, public_key);
-+
-+    st_logf("add key ok: %lx\n", (unsigned long)OBJECT_ID(o));
-+
-+    if (private_key_file) {
-+        CK_FLAGS flags;
-+        FILE *f;
-+
-+        o = add_st_object();
-+        if (o == NULL) {
-+            ret = CKR_DEVICE_MEMORY;
-+            goto out;
-+        }
-+        o->type = STO_T_PRIVATE_KEY;
-+        o->u.private_key.file = strdup(private_key_file);
-+        o->u.private_key.key = NULL;
-+
-+        o->u.private_key.cert = cert;
-+
-+        c = CKO_PRIVATE_KEY;
-+        add_object_attribute(o, 0, CKA_CLASS, &c, sizeof(c));
-+        add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true));
-+        add_object_attribute(o, 0, CKA_PRIVATE, &bool_true, sizeof(bool_false));
-+        add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false));
-+        add_object_attribute(o, 0, CKA_LABEL, label, strlen(label));
-+
-+        add_object_attribute(o, 0, CKA_KEY_TYPE, &key_type, sizeof(key_type));
-+        add_object_attribute(o, 0, CKA_ID, id, id_len);
-+        add_object_attribute(o, 0, CKA_START_DATE, "", 1); /* XXX */
-+        add_object_attribute(o, 0, CKA_END_DATE, "", 1); /* XXX */
-+        add_object_attribute(o, 0, CKA_DERIVE, &bool_false, sizeof(bool_false));
-+        add_object_attribute(o, 0, CKA_LOCAL, &bool_false, sizeof(bool_false));
-+        mech_type = CKM_RSA_X_509;
-+        add_object_attribute(o, 0, CKA_KEY_GEN_MECHANISM, &mech_type, sizeof(mech_type));
-+
-+        add_object_attribute(o, 0, CKA_SUBJECT, subject_data, subject_length);
-+        add_object_attribute(o, 0, CKA_SENSITIVE, &bool_true, sizeof(bool_true));
-+        add_object_attribute(o, 0, CKA_SECONDARY_AUTH, &bool_false, sizeof(bool_true));
-+        flags = 0;
-+        add_object_attribute(o, 0, CKA_AUTH_PIN_FLAGS, &flags, sizeof(flags));
-+
-+        add_object_attribute(o, 0, CKA_DECRYPT, &bool_true, sizeof(bool_true));
-+        add_object_attribute(o, 0, CKA_SIGN, &bool_true, sizeof(bool_true));
-+        add_object_attribute(o, 0, CKA_SIGN_RECOVER, &bool_false, sizeof(bool_false));
-+        add_object_attribute(o, 0, CKA_UNWRAP, &bool_true, sizeof(bool_true));
-+        add_object_attribute(o, 0, CKA_EXTRACTABLE, &bool_true, sizeof(bool_true));
-+        add_object_attribute(o, 0, CKA_NEVER_EXTRACTABLE, &bool_false, sizeof(bool_false));
-+
-+        add_pubkey_info(o, key_type, public_key);
-+
-+        f = fopen(private_key_file, "r");
-+        if (f == NULL) {
-+            st_logf("failed to open private key\n");
-+            return CKR_GENERAL_ERROR;
-+        }
-+
-+        o->u.private_key.key = PEM_read_PrivateKey(f, NULL, pem_callback, NULL);
-+        fclose(f);
-+        if (o->u.private_key.key == NULL) {
-+            st_logf("failed to read private key a startup\n");
-+            /* don't bother with this failure for now,
-+               fix it at C_Login time */;
-+        } else {
-+            /* XXX verify keytype */
-+
-+            if (key_type == CKK_RSA)
-+                RSA_set_method(o->u.private_key.key->pkey.rsa,
-+                               RSA_PKCS1_SSLeay());
-+
-+            if (X509_check_private_key(cert, o->u.private_key.key) != 1) {
-+                EVP_PKEY_free(o->u.private_key.key);
-+                o->u.private_key.key = NULL;
-+                st_logf("private key doesn't verify\n");
-+            } else {
-+                st_logf("private key usable\n");
-+                soft_token.flags.login_done = 1;
-+            }
-+        }
-+    }
-+
-+    ret = CKR_OK;
-+ out:
-+    if (ret != CKR_OK) {
-+        st_logf("something went wrong when adding cert!\n");
-+
-+        /* XXX wack o */;
-+    }
-+    free(cert_data);
-+    free(serial_data);
-+    free(issuer_data);
-+    free(subject_data);
-+
-+    return ret;
-+}
-+
-+static void
-+find_object_final(struct session_state *state)
-+{
-+    if (state->find.attributes) {
-+        CK_ULONG i;
-+
-+        for (i = 0; i < state->find.num_attributes; i++) {
-+            if (state->find.attributes[i].pValue)
-+                free(state->find.attributes[i].pValue);
-+        }
-+        free(state->find.attributes);
-+        state->find.attributes = NULL;
-+        state->find.num_attributes = 0;
-+        state->find.next_object = -1;
-+    }
-+}
-+
-+static void
-+reset_crypto_state(struct session_state *state)
-+{
-+    state->encrypt_object = -1;
-+    if (state->encrypt_mechanism)
-+        free(state->encrypt_mechanism);
-+    state->encrypt_mechanism = NULL_PTR;
-+    state->decrypt_object = -1;
-+    if (state->decrypt_mechanism)
-+        free(state->decrypt_mechanism);
-+    state->decrypt_mechanism = NULL_PTR;
-+    state->sign_object = -1;
-+    if (state->sign_mechanism)
-+        free(state->sign_mechanism);
-+    state->sign_mechanism = NULL_PTR;
-+    state->verify_object = -1;
-+    if (state->verify_mechanism)
-+        free(state->verify_mechanism);
-+    state->verify_mechanism = NULL_PTR;
-+    state->digest_object = -1;
-+}
-+
-+static void
-+close_session(struct session_state *state)
-+{
-+    if (state->find.attributes) {
-+        application_error("application didn't do C_FindObjectsFinal\n");
-+        find_object_final(state);
-+    }
-+
-+    state->session_handle = CK_INVALID_HANDLE;
-+    soft_token.application = NULL_PTR;
-+    soft_token.notify = NULL_PTR;
-+    reset_crypto_state(state);
-+}
-+
-+static const char *
-+has_session(void)
-+{
-+    return soft_token.open_sessions > 0 ? "yes" : "no";
-+}
-+
-+static void
-+read_conf_file(const char *fn)
-+{
-+    char buf[1024], *cert, *key, *id, *label, *s, *p;
-+    int anchor;
-+    FILE *f;
-+
-+    f = fopen(fn, "r");
-+    if (f == NULL) {
-+        st_logf("can't open configuration file %s\n", fn);
-+        return;
-+    }
-+
-+    while(fgets(buf, sizeof(buf), f) != NULL) {
-+        buf[strcspn(buf, "\n")] = '\0';
-+
-+        anchor = 0;
-+
-+        st_logf("line: %s\n", buf);
-+
-+        p = buf;
-+        while (isspace(*p))
-+            p++;
-+        if (*p == '#')
-+            continue;
-+        while (isspace(*p))
-+            p++;
-+
-+        s = NULL;
-+        id = strtok_r(p, "\t", &s);
-+        if (id == NULL)
-+            continue;
-+        label = strtok_r(NULL, "\t", &s);
-+        if (label == NULL)
-+            continue;
-+        cert = strtok_r(NULL, "\t", &s);
-+        if (cert == NULL)
-+            continue;
-+        key = strtok_r(NULL, "\t", &s);
-+
-+        /* XXX */
-+        if (strcmp(id, "anchor") == 0) {
-+            id = "\x00\x00";
-+            anchor = 1;
-+        }
-+
-+        st_logf("adding: %s\n", label);
-+
-+        add_certificate(label, cert, key, id, anchor);
-+    }
-+}
-+
-+static CK_RV
-+func_not_supported(void)
-+{
-+    st_logf("function not supported\n");
-+    return CKR_FUNCTION_NOT_SUPPORTED;
-+}
-+
-+CK_RV
-+C_Initialize(CK_VOID_PTR a)
-+{
-+    CK_C_INITIALIZE_ARGS_PTR args = a;
-+    st_logf("Initialize\n");
-+    int i;
-+
-+    OpenSSL_add_all_algorithms();
-+    ERR_load_crypto_strings();
-+
-+    srandom(getpid() ^ time(NULL));
-+
-+    for (i = 0; i < MAX_NUM_SESSION; i++) {
-+        soft_token.state[i].session_handle = CK_INVALID_HANDLE;
-+        soft_token.state[i].find.attributes = NULL;
-+        soft_token.state[i].find.num_attributes = 0;
-+        soft_token.state[i].find.next_object = -1;
-+        reset_crypto_state(&soft_token.state[i]);
-+    }
-+
-+    soft_token.flags.hardware_slot = 1;
-+    soft_token.flags.app_error_fatal = 0;
-+    soft_token.flags.login_done = 0;
-+
-+    soft_token.object.objs = NULL;
-+    soft_token.object.num_objs = 0;
-+
-+    soft_token.logfile = NULL;
-+#if 0
-+    soft_token.logfile = stdout;
-+#endif
-+#if 0
-+    soft_token.logfile = fopen("/tmp/log-pkcs11.txt", "a");
-+#endif
-+
-+    if (a != NULL_PTR) {
-+        st_logf("\tCreateMutex:\t%p\n", args->CreateMutex);
-+        st_logf("\tDestroyMutext\t%p\n", args->DestroyMutex);
-+        st_logf("\tLockMutext\t%p\n", args->LockMutex);
-+        st_logf("\tUnlockMutext\t%p\n", args->UnlockMutex);
-+        st_logf("\tFlags\t%04x\n", (unsigned int)args->flags);
-+    }
-+
-+    {
-+        char *fn = NULL, *home = NULL;
-+
-+        if (getuid() == geteuid()) {
-+            fn = getenv("SOFTPKCS11RC");
-+            if (fn)
-+                fn = strdup(fn);
-+            home = getenv("HOME");
-+        }
-+        if (fn == NULL && home == NULL) {
-+            struct passwd *pw = getpwuid(getuid());
-+            if(pw != NULL)
-+                home = pw->pw_dir;
-+        }
-+        if (fn == NULL) {
-+            if (home)
-+                asprintf(&fn, "%s/.soft-token.rc", home);
-+            else
-+                fn = strdup("/etc/soft-token.rc");
-+        }
-+
-+        read_conf_file(fn);
-+        free(fn);
-+    }
-+
-+    return CKR_OK;
-+}
-+
-+CK_RV
-+C_Finalize(CK_VOID_PTR args)
-+{
-+    int i;
-+
-+    st_logf("Finalize\n");
-+
-+    for (i = 0; i < MAX_NUM_SESSION; i++) {
-+        if (soft_token.state[i].session_handle != CK_INVALID_HANDLE) {
-+            application_error("application finalized without "
-+                              "closing session\n");
-+            close_session(&soft_token.state[i]);
-+        }
-+    }
-+
-+    return CKR_OK;
-+}
-+
-+CK_RV
-+C_GetInfo(CK_INFO_PTR args)
-+{
-+    st_logf("GetInfo\n");
-+
-+    memset(args, 17, sizeof(*args));
-+    args->cryptokiVersion.major = 2;
-+    args->cryptokiVersion.minor = 10;
-+    snprintf_fill((char *)args->manufacturerID,
-+                  sizeof(args->manufacturerID),
-+                  ' ',
-+                  "SoftToken");
-+    snprintf_fill((char *)args->libraryDescription,
-+                  sizeof(args->libraryDescription), ' ',
-+                  "SoftToken");
-+    args->libraryVersion.major = 1;
-+    args->libraryVersion.minor = 8;
-+
-+    return CKR_OK;
-+}
-+
-+extern CK_FUNCTION_LIST funcs;
-+
-+CK_RV
-+C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList)
-+{
-+    *ppFunctionList = &funcs;
-+    return CKR_OK;
-+}
-+
-+CK_RV
-+C_GetSlotList(CK_BBOOL tokenPresent,
-+              CK_SLOT_ID_PTR pSlotList,
-+              CK_ULONG_PTR   pulCount)
-+{
-+    st_logf("GetSlotList: %s\n",
-+            tokenPresent ? "tokenPresent" : "token not Present");
-+    if (pSlotList)
-+        pSlotList[0] = 1;
-+    *pulCount = 1;
-+    return CKR_OK;
-+}
-+
-+CK_RV
-+C_GetSlotInfo(CK_SLOT_ID slotID,
-+              CK_SLOT_INFO_PTR pInfo)
-+{
-+    st_logf("GetSlotInfo: slot: %d : %s\n", (int)slotID, has_session());
-+
-+    memset(pInfo, 18, sizeof(*pInfo));
-+
-+    if (slotID != 1)
-+        return CKR_ARGUMENTS_BAD;
-+
-+    snprintf_fill((char *)pInfo->slotDescription,
-+                  sizeof(pInfo->slotDescription),
-+                  ' ',
-+                  "SoftToken (slot)");
-+    snprintf_fill((char *)pInfo->manufacturerID,
-+                  sizeof(pInfo->manufacturerID),
-+                  ' ',
-+                  "SoftToken (slot)");
-+    pInfo->flags = CKF_TOKEN_PRESENT;
-+    if (soft_token.flags.hardware_slot)
-+        pInfo->flags |= CKF_HW_SLOT;
-+    pInfo->hardwareVersion.major = 1;
-+    pInfo->hardwareVersion.minor = 0;
-+    pInfo->firmwareVersion.major = 1;
-+    pInfo->firmwareVersion.minor = 0;
-+
-+    return CKR_OK;
-+}
-+
-+CK_RV
-+C_GetTokenInfo(CK_SLOT_ID slotID,
-+               CK_TOKEN_INFO_PTR pInfo)
-+{
-+    st_logf("GetTokenInfo: %s\n", has_session());
-+
-+    memset(pInfo, 19, sizeof(*pInfo));
-+
-+    snprintf_fill((char *)pInfo->label,
-+                  sizeof(pInfo->label),
-+                  ' ',
-+                  "SoftToken (token)");
-+    snprintf_fill((char *)pInfo->manufacturerID,
-+                  sizeof(pInfo->manufacturerID),
-+                  ' ',
-+                  "SoftToken (token)");
-+    snprintf_fill((char *)pInfo->model,
-+                  sizeof(pInfo->model),
-+                  ' ',
-+                  "SoftToken (token)");
-+    snprintf_fill((char *)pInfo->serialNumber,
-+                  sizeof(pInfo->serialNumber),
-+                  ' ',
-+                  "4711");
-+    pInfo->flags =
-+        CKF_TOKEN_INITIALIZED |
-+        CKF_USER_PIN_INITIALIZED;
-+
-+    if (soft_token.flags.login_done == 0)
-+        pInfo->flags |= CKF_LOGIN_REQUIRED;
-+
-+    /* CFK_RNG |
-+       CKF_RESTORE_KEY_NOT_NEEDED |
-+    */
-+    pInfo->ulMaxSessionCount = MAX_NUM_SESSION;
-+    pInfo->ulSessionCount = soft_token.open_sessions;
-+    pInfo->ulMaxRwSessionCount = MAX_NUM_SESSION;
-+    pInfo->ulRwSessionCount = soft_token.open_sessions;
-+    pInfo->ulMaxPinLen = 1024;
-+    pInfo->ulMinPinLen = 0;
-+    pInfo->ulTotalPublicMemory = 4711;
-+    pInfo->ulFreePublicMemory = 4712;
-+    pInfo->ulTotalPrivateMemory = 4713;
-+    pInfo->ulFreePrivateMemory = 4714;
-+    pInfo->hardwareVersion.major = 2;
-+    pInfo->hardwareVersion.minor = 0;
-+    pInfo->firmwareVersion.major = 2;
-+    pInfo->firmwareVersion.minor = 0;
-+
-+    return CKR_OK;
-+}
-+
-+CK_RV
-+C_GetMechanismList(CK_SLOT_ID slotID,
-+                   CK_MECHANISM_TYPE_PTR pMechanismList,
-+                   CK_ULONG_PTR pulCount)
-+{
-+    st_logf("GetMechanismList\n");
-+
-+    *pulCount = 2;
-+    if (pMechanismList == NULL_PTR)
-+        return CKR_OK;
-+    pMechanismList[0] = CKM_RSA_X_509;
-+    pMechanismList[1] = CKM_RSA_PKCS;
-+
-+    return CKR_OK;
-+}
-+
-+CK_RV
-+C_GetMechanismInfo(CK_SLOT_ID slotID,
-+                   CK_MECHANISM_TYPE type,
-+                   CK_MECHANISM_INFO_PTR pInfo)
-+{
-+    st_logf("GetMechanismInfo: slot %d type: %d\n",
-+            (int)slotID, (int)type);
-+    return CKR_FUNCTION_NOT_SUPPORTED;
-+}
-+
-+CK_RV
-+C_InitToken(CK_SLOT_ID slotID,
-+            CK_UTF8CHAR_PTR pPin,
-+            CK_ULONG ulPinLen,
-+            CK_UTF8CHAR_PTR pLabel)
-+{
-+    st_logf("InitToken: slot %d\n", (int)slotID);
-+    return CKR_FUNCTION_NOT_SUPPORTED;
-+}
-+
-+CK_RV
-+C_OpenSession(CK_SLOT_ID slotID,
-+              CK_FLAGS flags,
-+              CK_VOID_PTR pApplication,
-+              CK_NOTIFY Notify,
-+              CK_SESSION_HANDLE_PTR phSession)
-+{
-+    int i;
-+
-+    st_logf("OpenSession: slot: %d\n", (int)slotID);
-+
-+    if (soft_token.open_sessions == MAX_NUM_SESSION)
-+        return CKR_SESSION_COUNT;
-+
-+    soft_token.application = pApplication;
-+    soft_token.notify = Notify;
-+
-+    for (i = 0; i < MAX_NUM_SESSION; i++)
-+        if (soft_token.state[i].session_handle == CK_INVALID_HANDLE)
-+            break;
-+    if (i == MAX_NUM_SESSION)
-+        abort();
-+
-+    soft_token.open_sessions++;
-+
-+    soft_token.state[i].session_handle =
-+        (CK_SESSION_HANDLE)(random() & 0xfffff);
-+    *phSession = soft_token.state[i].session_handle;
-+
-+    return CKR_OK;
-+}
-+
-+CK_RV
-+C_CloseSession(CK_SESSION_HANDLE hSession)
-+{
-+    struct session_state *state;
-+    st_logf("CloseSession\n");
-+
-+    if (verify_session_handle(hSession, &state) != CKR_OK)
-+        application_error("closed session not open");
-+    else
-+        close_session(state);
-+
-+    return CKR_OK;
-+}
-+
-+CK_RV
-+C_CloseAllSessions(CK_SLOT_ID slotID)
-+{
-+    int i;
-+
-+    st_logf("CloseAllSessions\n");
-+
-+    for (i = 0; i < MAX_NUM_SESSION; i++)
-+        if (soft_token.state[i].session_handle != CK_INVALID_HANDLE)
-+            close_session(&soft_token.state[i]);
-+
-+    return CKR_OK;
-+}
-+
-+CK_RV
-+C_GetSessionInfo(CK_SESSION_HANDLE hSession,
-+                 CK_SESSION_INFO_PTR pInfo)
-+{
-+    st_logf("GetSessionInfo\n");
-+
-+    VERIFY_SESSION_HANDLE(hSession, NULL);
-+
-+    memset(pInfo, 20, sizeof(*pInfo));
-+
-+    pInfo->slotID = 1;
-+    if (soft_token.flags.login_done)
-+        pInfo->state = CKS_RO_USER_FUNCTIONS;
-+    else
-+        pInfo->state = CKS_RO_PUBLIC_SESSION;
-+    pInfo->flags = CKF_SERIAL_SESSION;
-+    pInfo->ulDeviceError = 0;
-+
-+    return CKR_OK;
-+}
-+
-+CK_RV
-+C_Login(CK_SESSION_HANDLE hSession,
-+        CK_USER_TYPE userType,
-+        CK_UTF8CHAR_PTR pPin,
-+        CK_ULONG ulPinLen)
-+{
-+    char *pin = NULL;
-+    int i;
-+
-+    st_logf("Login\n");
-+
-+    VERIFY_SESSION_HANDLE(hSession, NULL);
-+
-+    if (pPin != NULL_PTR) {
-+        asprintf(&pin, "%.*s", (int)ulPinLen, pPin);
-+        st_logf("type: %d password: %s\n", (int)userType, pin);
-+    }
-+
-+    for (i = 0; i < soft_token.object.num_objs; i++) {
-+        struct st_object *o = soft_token.object.objs[i];
-+        FILE *f;
-+
-+        if (o->type != STO_T_PRIVATE_KEY)
-+            continue;
-+
-+        if (o->u.private_key.key)
-+            continue;
-+
-+        f = fopen(o->u.private_key.file, "r");
-+        if (f == NULL) {
-+            st_logf("can't open private file: %s\n", o->u.private_key.file);
-+            continue;
-+        }
-+
-+        o->u.private_key.key = PEM_read_PrivateKey(f, NULL, NULL, pin);
-+        fclose(f);
-+        if (o->u.private_key.key == NULL) {
-+            st_logf("failed to read key: %s error: %s\n",
-+                    o->u.private_key.file,
-+                    ERR_error_string(ERR_get_error(), NULL));
-+            /* just ignore failure */;
-+            continue;
-+        }
-+
-+        /* XXX check keytype */
-+        RSA_set_method(o->u.private_key.key->pkey.rsa, RSA_PKCS1_SSLeay());
-+
-+        if (X509_check_private_key(o->u.private_key.cert, o->u.private_key.key) != 1) {
-+            EVP_PKEY_free(o->u.private_key.key);
-+            o->u.private_key.key = NULL;
-+            st_logf("private key %s doesn't verify\n", o->u.private_key.file);
-+            continue;
-+        }
-+
-+        soft_token.flags.login_done = 1;
-+    }
-+    free(pin);
-+
-+    return soft_token.flags.login_done ? CKR_OK : CKR_PIN_INCORRECT;
-+}
-+
-+CK_RV
-+C_Logout(CK_SESSION_HANDLE hSession)
-+{
-+    st_logf("Logout\n");
-+    VERIFY_SESSION_HANDLE(hSession, NULL);
-+    return CKR_FUNCTION_NOT_SUPPORTED;
-+}
-+
-+CK_RV
-+C_GetObjectSize(CK_SESSION_HANDLE hSession,
-+                CK_OBJECT_HANDLE hObject,
-+                CK_ULONG_PTR pulSize)
-+{
-+    st_logf("GetObjectSize\n");
-+    VERIFY_SESSION_HANDLE(hSession, NULL);
-+    return CKR_FUNCTION_NOT_SUPPORTED;
-+}
-+
-+CK_RV
-+C_GetAttributeValue(CK_SESSION_HANDLE hSession,
-+                    CK_OBJECT_HANDLE hObject,
-+                    CK_ATTRIBUTE_PTR pTemplate,
-+                    CK_ULONG ulCount)
-+{
-+    struct session_state *state;
-+    struct st_object *obj;
-+    CK_ULONG i;
-+    CK_RV ret;
-+    int j;
-+
-+    st_logf("GetAttributeValue: %lx\n",
-+            (unsigned long)HANDLE_OBJECT_ID(hObject));
-+    VERIFY_SESSION_HANDLE(hSession, &state);
-+
-+    if ((ret = object_handle_to_object(hObject, &obj)) != CKR_OK) {
-+        st_logf("object not found: %lx\n",
-+                (unsigned long)HANDLE_OBJECT_ID(hObject));
-+        return ret;
-+    }
-+
-+    for (i = 0; i < ulCount; i++) {
-+        st_logf("       getting 0x%08lx\n", (unsigned long)pTemplate[i].type);
-+        for (j = 0; j < obj->num_attributes; j++) {
-+            if (obj->attrs[j].secret) {
-+                pTemplate[i].ulValueLen = (CK_ULONG)-1;
-+                break;
-+            }
-+            if (pTemplate[i].type == obj->attrs[j].attribute.type) {
-+                if (pTemplate[i].pValue != NULL_PTR && obj->attrs[j].secret == 0) {
-+                    if (pTemplate[i].ulValueLen >= obj->attrs[j].attribute.ulValueLen)
-+                        memcpy(pTemplate[i].pValue, obj->attrs[j].attribute.pValue,
-+                               obj->attrs[j].attribute.ulValueLen);
-+                }
-+                pTemplate[i].ulValueLen = obj->attrs[j].attribute.ulValueLen;
-+                break;
-+            }
-+        }
-+        if (j == obj->num_attributes) {
-+            st_logf("key type: 0x%08lx not found\n", (unsigned long)pTemplate[i].type);
-+            pTemplate[i].ulValueLen = (CK_ULONG)-1;
-+        }
-+
-+    }
-+    return CKR_OK;
-+}
-+
-+CK_RV
-+C_FindObjectsInit(CK_SESSION_HANDLE hSession,
-+                  CK_ATTRIBUTE_PTR pTemplate,
-+                  CK_ULONG ulCount)
-+{
-+    struct session_state *state;
-+
-+    st_logf("FindObjectsInit\n");
-+
-+    VERIFY_SESSION_HANDLE(hSession, &state);
-+
-+    if (state->find.next_object != -1) {
-+        application_error("application didn't do C_FindObjectsFinal\n");
-+        find_object_final(state);
-+    }
-+    if (ulCount) {
-+        CK_ULONG i;
-+        size_t len;
-+
-+        print_attributes(pTemplate, ulCount);
-+
-+        state->find.attributes =
-+            calloc(1, ulCount * sizeof(state->find.attributes[0]));
-+        if (state->find.attributes == NULL)
-+            return CKR_DEVICE_MEMORY;
-+        for (i = 0; i < ulCount; i++) {
-+            state->find.attributes[i].pValue =
-+                malloc(pTemplate[i].ulValueLen);
-+            if (state->find.attributes[i].pValue == NULL) {
-+                find_object_final(state);
-+                return CKR_DEVICE_MEMORY;
-+            }
-+            memcpy(state->find.attributes[i].pValue,
-+                   pTemplate[i].pValue, pTemplate[i].ulValueLen);
-+            state->find.attributes[i].type = pTemplate[i].type;
-+            state->find.attributes[i].ulValueLen = pTemplate[i].ulValueLen;
-+        }
-+        state->find.num_attributes = ulCount;
-+        state->find.next_object = 0;
-+    } else {
-+        st_logf("find all objects\n");
-+        state->find.attributes = NULL;
-+        state->find.num_attributes = 0;
-+        state->find.next_object = 0;
-+    }
-+
-+    return CKR_OK;
-+}
-+
-+CK_RV
-+C_FindObjects(CK_SESSION_HANDLE hSession,
-+              CK_OBJECT_HANDLE_PTR phObject,
-+              CK_ULONG ulMaxObjectCount,
-+              CK_ULONG_PTR pulObjectCount)
-+{
-+    struct session_state *state;
-+    int i;
-+
-+    st_logf("FindObjects\n");
-+
-+    VERIFY_SESSION_HANDLE(hSession, &state);
-+
-+    if (state->find.next_object == -1) {
-+        application_error("application didn't do C_FindObjectsInit\n");
-+        return CKR_ARGUMENTS_BAD;
-+    }
-+    if (ulMaxObjectCount == 0) {
-+        application_error("application asked for 0 objects\n");
-+        return CKR_ARGUMENTS_BAD;
-+    }
-+    *pulObjectCount = 0;
-+    for (i = state->find.next_object; i < soft_token.object.num_objs; i++) {
-+        st_logf("FindObjects: %d\n", i);
-+        state->find.next_object = i + 1;
-+        if (attributes_match(soft_token.object.objs[i],
-+                             state->find.attributes,
-+                             state->find.num_attributes)) {
-+            *phObject++ = soft_token.object.objs[i]->object_handle;
-+            ulMaxObjectCount--;
-+            (*pulObjectCount)++;
-+            if (ulMaxObjectCount == 0)
-+                break;
-+        }
-+    }
-+    return CKR_OK;
-+}
-+
-+CK_RV
-+C_FindObjectsFinal(CK_SESSION_HANDLE hSession)
-+{
-+    struct session_state *state;
-+
-+    st_logf("FindObjectsFinal\n");
-+    VERIFY_SESSION_HANDLE(hSession, &state);
-+    find_object_final(state);
-+    return CKR_OK;
-+}
-+
-+static CK_RV
-+commonInit(CK_ATTRIBUTE *attr_match, int attr_match_len,
-+           const CK_MECHANISM_TYPE *mechs, int mechs_len,
-+           const CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey,
-+           struct st_object **o)
-+{
-+    CK_RV ret;
-+    int i;
-+
-+    *o = NULL;
-+    if ((ret = object_handle_to_object(hKey, o)) != CKR_OK)
-+        return ret;
-+
-+    ret = attributes_match(*o, attr_match, attr_match_len);
-+    if (!ret) {
-+        application_error("called commonInit on key that doesn't "
-+                          "support required attr");
-+        return CKR_ARGUMENTS_BAD;
-+    }
-+
-+    for (i = 0; i < mechs_len; i++)
-+        if (mechs[i] == pMechanism->mechanism)
-+            break;
-+    if (i == mechs_len) {
-+        application_error("called mech (%08lx) not supported\n",
-+                          pMechanism->mechanism);
-+        return CKR_ARGUMENTS_BAD;
-+    }
-+    return CKR_OK;
-+}
-+
-+
-+static CK_RV
-+dup_mechanism(CK_MECHANISM_PTR *dup, const CK_MECHANISM_PTR pMechanism)
-+{
-+    CK_MECHANISM_PTR p;
-+
-+    p = malloc(sizeof(*p));
-+    if (p == NULL)
-+        return CKR_DEVICE_MEMORY;
-+
-+    if (*dup)
-+        free(*dup);
-+    *dup = p;
-+    memcpy(p, pMechanism, sizeof(*p));
-+
-+    return CKR_OK;
-+}
-+
-+
-+CK_RV
-+C_EncryptInit(CK_SESSION_HANDLE hSession,
-+              CK_MECHANISM_PTR pMechanism,
-+              CK_OBJECT_HANDLE hKey)
-+{
-+    struct session_state *state;
-+    CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS, CKM_RSA_X_509 };
-+    CK_BBOOL bool_true = CK_TRUE;
-+    CK_ATTRIBUTE attr[] = {
-+        { CKA_ENCRYPT, &bool_true, sizeof(bool_true) }
-+    };
-+    struct st_object *o;
-+    CK_RV ret;
-+
-+    st_logf("EncryptInit\n");
-+    VERIFY_SESSION_HANDLE(hSession, &state);
-+
-+    ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]),
-+                     mechs, sizeof(mechs)/sizeof(mechs[0]),
-+                     pMechanism, hKey, &o);
-+    if (ret)
-+        return ret;
-+
-+    ret = dup_mechanism(&state->encrypt_mechanism, pMechanism);
-+    if (ret == CKR_OK)
-+        state->encrypt_object = OBJECT_ID(o);
-+
-+    return ret;
-+}
-+
-+CK_RV
-+C_Encrypt(CK_SESSION_HANDLE hSession,
-+          CK_BYTE_PTR pData,
-+          CK_ULONG ulDataLen,
-+          CK_BYTE_PTR pEncryptedData,
-+          CK_ULONG_PTR pulEncryptedDataLen)
-+{
-+    struct session_state *state;
-+    struct st_object *o;
-+    void *buffer = NULL;
-+    CK_RV ret;
-+    RSA *rsa;
-+    int padding, len, buffer_len, padding_len;
-+
-+    st_logf("Encrypt\n");
-+
-+    VERIFY_SESSION_HANDLE(hSession, &state);
-+
-+    if (state->encrypt_object == -1)
-+        return CKR_ARGUMENTS_BAD;
-+
-+    o = soft_token.object.objs[state->encrypt_object];
-+
-+    if (o->u.public_key == NULL) {
-+        st_logf("public key NULL\n");
-+        return CKR_ARGUMENTS_BAD;
-+    }
-+
-+    rsa = o->u.public_key->pkey.rsa;
-+
-+    if (rsa == NULL)
-+        return CKR_ARGUMENTS_BAD;
-+
-+    RSA_blinding_off(rsa); /* XXX RAND is broken while running in mozilla ? */
-+
-+    buffer_len = RSA_size(rsa);
-+
-+    buffer = malloc(buffer_len);
-+    if (buffer == NULL) {
-+        ret = CKR_DEVICE_MEMORY;
-+        goto out;
-+    }
-+
-+    ret = CKR_OK;
-+    switch(state->encrypt_mechanism->mechanism) {
-+    case CKM_RSA_PKCS:
-+        padding = RSA_PKCS1_PADDING;
-+        padding_len = RSA_PKCS1_PADDING_SIZE;
-+        break;
-+    case CKM_RSA_X_509:
-+        padding = RSA_NO_PADDING;
-+        padding_len = 0;
-+        break;
-+    default:
-+        ret = CKR_FUNCTION_NOT_SUPPORTED;
-+        goto out;
-+    }
-+
-+    if (buffer_len + padding_len < ulDataLen) {
-+        ret = CKR_ARGUMENTS_BAD;
-+        goto out;
-+    }
-+
-+    if (pulEncryptedDataLen == NULL) {
-+        st_logf("pulEncryptedDataLen NULL\n");
-+        ret = CKR_ARGUMENTS_BAD;
-+        goto out;
-+    }
-+
-+    if (pData == NULL_PTR) {
-+        st_logf("data NULL\n");
-+        ret = CKR_ARGUMENTS_BAD;
-+        goto out;
-+    }
-+
-+    len = RSA_public_encrypt(ulDataLen, pData, buffer, rsa, padding);
-+    if (len <= 0) {
-+        ret = CKR_DEVICE_ERROR;
-+        goto out;
-+    }
-+    if (len > buffer_len)
-+        abort();
-+
-+    if (pEncryptedData != NULL_PTR)
-+        memcpy(pEncryptedData, buffer, len);
-+    *pulEncryptedDataLen = len;
-+
-+ out:
-+    if (buffer) {
-+        memset(buffer, 0, buffer_len);
-+        free(buffer);
-+    }
-+    return ret;
-+}
-+
-+CK_RV
-+C_EncryptUpdate(CK_SESSION_HANDLE hSession,
-+                CK_BYTE_PTR pPart,
-+                CK_ULONG ulPartLen,
-+                CK_BYTE_PTR pEncryptedPart,
-+                CK_ULONG_PTR pulEncryptedPartLen)
-+{
-+    st_logf("EncryptUpdate\n");
-+    VERIFY_SESSION_HANDLE(hSession, NULL);
-+    return CKR_FUNCTION_NOT_SUPPORTED;
-+}
-+
-+
-+CK_RV
-+C_EncryptFinal(CK_SESSION_HANDLE hSession,
-+               CK_BYTE_PTR pLastEncryptedPart,
-+               CK_ULONG_PTR pulLastEncryptedPartLen)
-+{
-+    st_logf("EncryptFinal\n");
-+    VERIFY_SESSION_HANDLE(hSession, NULL);
-+    return CKR_FUNCTION_NOT_SUPPORTED;
-+}
-+
-+
-+/* C_DecryptInit initializes a decryption operation. */
-+CK_RV
-+C_DecryptInit(CK_SESSION_HANDLE hSession,
-+              CK_MECHANISM_PTR pMechanism,
-+              CK_OBJECT_HANDLE hKey)
-+{
-+    struct session_state *state;
-+    CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS, CKM_RSA_X_509 };
-+    CK_BBOOL bool_true = CK_TRUE;
-+    CK_ATTRIBUTE attr[] = {
-+        { CKA_DECRYPT, &bool_true, sizeof(bool_true) }
-+    };
-+    struct st_object *o;
-+    CK_RV ret;
-+
-+    st_logf("DecryptInit\n");
-+    VERIFY_SESSION_HANDLE(hSession, &state);
-+
-+    ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]),
-+                     mechs, sizeof(mechs)/sizeof(mechs[0]),
-+                     pMechanism, hKey, &o);
-+    if (ret)
-+        return ret;
-+
-+    ret = dup_mechanism(&state->decrypt_mechanism, pMechanism);
-+    if (ret == CKR_OK)
-+        state->decrypt_object = OBJECT_ID(o);
-+
-+    return CKR_OK;
-+}
-+
-+
-+CK_RV
-+C_Decrypt(CK_SESSION_HANDLE hSession,
-+          CK_BYTE_PTR       pEncryptedData,
-+          CK_ULONG          ulEncryptedDataLen,
-+          CK_BYTE_PTR       pData,
-+          CK_ULONG_PTR      pulDataLen)
-+{
-+    struct session_state *state;
-+    struct st_object *o;
-+    void *buffer = NULL;
-+    CK_RV ret;
-+    RSA *rsa;
-+    int padding, len, buffer_len, padding_len;
-+
-+    st_logf("Decrypt\n");
-+
-+    VERIFY_SESSION_HANDLE(hSession, &state);
-+
-+    if (state->decrypt_object == -1)
-+        return CKR_ARGUMENTS_BAD;
-+
-+    o = soft_token.object.objs[state->decrypt_object];
-+
-+    if (o->u.private_key.key == NULL) {
-+        st_logf("private key NULL\n");
-+        return CKR_ARGUMENTS_BAD;
-+    }
-+
-+    rsa = o->u.private_key.key->pkey.rsa;
-+
-+    if (rsa == NULL)
-+        return CKR_ARGUMENTS_BAD;
-+
-+    RSA_blinding_off(rsa); /* XXX RAND is broken while running in mozilla ? */
-+
-+    buffer_len = RSA_size(rsa);
-+
-+    buffer = malloc(buffer_len);
-+    if (buffer == NULL) {
-+        ret = CKR_DEVICE_MEMORY;
-+        goto out;
-+    }
-+
-+    ret = CKR_OK;
-+    switch(state->decrypt_mechanism->mechanism) {
-+    case CKM_RSA_PKCS:
-+        padding = RSA_PKCS1_PADDING;
-+        padding_len = RSA_PKCS1_PADDING_SIZE;
-+        break;
-+    case CKM_RSA_X_509:
-+        padding = RSA_NO_PADDING;
-+        padding_len = 0;
-+        break;
-+    default:
-+        ret = CKR_FUNCTION_NOT_SUPPORTED;
-+        goto out;
-+    }
-+
-+    if (buffer_len + padding_len < ulEncryptedDataLen) {
-+        ret = CKR_ARGUMENTS_BAD;
-+        goto out;
-+    }
-+
-+    if (pulDataLen == NULL) {
-+        st_logf("pulDataLen NULL\n");
-+        ret = CKR_ARGUMENTS_BAD;
-+        goto out;
-+    }
-+
-+    if (pEncryptedData == NULL_PTR) {
-+        st_logf("data NULL\n");
-+        ret = CKR_ARGUMENTS_BAD;
-+        goto out;
-+    }
-+
-+    len = RSA_private_decrypt(ulEncryptedDataLen, pEncryptedData, buffer,
-+                              rsa, padding);
-+    if (len <= 0) {
-+        ret = CKR_DEVICE_ERROR;
-+        goto out;
-+    }
-+    if (len > buffer_len)
-+        abort();
-+
-+    if (pData != NULL_PTR)
-+        memcpy(pData, buffer, len);
-+    *pulDataLen = len;
-+
-+ out:
-+    if (buffer) {
-+        memset(buffer, 0, buffer_len);
-+        free(buffer);
-+    }
-+    return ret;
-+}
-+
-+
-+CK_RV
-+C_DecryptUpdate(CK_SESSION_HANDLE hSession,
-+                CK_BYTE_PTR pEncryptedPart,
-+                CK_ULONG ulEncryptedPartLen,
-+                CK_BYTE_PTR pPart,
-+                CK_ULONG_PTR pulPartLen)
-+
-+{
-+    st_logf("DecryptUpdate\n");
-+    VERIFY_SESSION_HANDLE(hSession, NULL);
-+    return CKR_FUNCTION_NOT_SUPPORTED;
-+}
-+
-+
-+CK_RV
-+C_DecryptFinal(CK_SESSION_HANDLE hSession,
-+               CK_BYTE_PTR pLastPart,
-+               CK_ULONG_PTR pulLastPartLen)
-+{
-+    st_logf("DecryptFinal\n");
-+    VERIFY_SESSION_HANDLE(hSession, NULL);
-+    return CKR_FUNCTION_NOT_SUPPORTED;
-+}
-+
-+CK_RV
-+C_DigestInit(CK_SESSION_HANDLE hSession,
-+             CK_MECHANISM_PTR pMechanism)
-+{
-+    st_logf("DigestInit\n");
-+    VERIFY_SESSION_HANDLE(hSession, NULL);
-+    return CKR_FUNCTION_NOT_SUPPORTED;
-+}
-+
-+CK_RV
-+C_SignInit(CK_SESSION_HANDLE hSession,
-+           CK_MECHANISM_PTR pMechanism,
-+           CK_OBJECT_HANDLE hKey)
-+{
-+    struct session_state *state;
-+    CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS, CKM_RSA_X_509 };
-+    CK_BBOOL bool_true = CK_TRUE;
-+    CK_ATTRIBUTE attr[] = {
-+        { CKA_SIGN, &bool_true, sizeof(bool_true) }
-+    };
-+    struct st_object *o;
-+    CK_RV ret;
-+
-+    st_logf("SignInit\n");
-+    VERIFY_SESSION_HANDLE(hSession, &state);
-+
-+    ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]),
-+                     mechs, sizeof(mechs)/sizeof(mechs[0]),
-+                     pMechanism, hKey, &o);
-+    if (ret)
-+        return ret;
-+
-+    ret = dup_mechanism(&state->sign_mechanism, pMechanism);
-+    if (ret == CKR_OK)
-+        state->sign_object = OBJECT_ID(o);
-+
-+    return CKR_OK;
-+}
-+
-+CK_RV
-+C_Sign(CK_SESSION_HANDLE hSession,
-+       CK_BYTE_PTR pData,
-+       CK_ULONG ulDataLen,
-+       CK_BYTE_PTR pSignature,
-+       CK_ULONG_PTR pulSignatureLen)
-+{
-+    struct session_state *state;
-+    struct st_object *o;
-+    void *buffer = NULL;
-+    CK_RV ret;
-+    RSA *rsa;
-+    int padding, len, buffer_len, padding_len;
-+
-+    st_logf("Sign\n");
-+    VERIFY_SESSION_HANDLE(hSession, &state);
-+
-+    if (state->sign_object == -1)
-+        return CKR_ARGUMENTS_BAD;
-+
-+    o = soft_token.object.objs[state->sign_object];
-+
-+    if (o->u.private_key.key == NULL) {
-+        st_logf("private key NULL\n");
-+        return CKR_ARGUMENTS_BAD;
-+    }
-+
-+    rsa = o->u.private_key.key->pkey.rsa;
-+
-+    if (rsa == NULL)
-+        return CKR_ARGUMENTS_BAD;
-+
-+    RSA_blinding_off(rsa); /* XXX RAND is broken while running in mozilla ? */
-+
-+    buffer_len = RSA_size(rsa);
-+
-+    buffer = malloc(buffer_len);
-+    if (buffer == NULL) {
-+        ret = CKR_DEVICE_MEMORY;
-+        goto out;
-+    }
-+
-+    switch(state->sign_mechanism->mechanism) {
-+    case CKM_RSA_PKCS:
-+        padding = RSA_PKCS1_PADDING;
-+        padding_len = RSA_PKCS1_PADDING_SIZE;
-+        break;
-+    case CKM_RSA_X_509:
-+        padding = RSA_NO_PADDING;
-+        padding_len = 0;
-+        break;
-+    default:
-+        ret = CKR_FUNCTION_NOT_SUPPORTED;
-+        goto out;
-+    }
-+
-+    if (buffer_len < ulDataLen + padding_len) {
-+        ret = CKR_ARGUMENTS_BAD;
-+        goto out;
-+    }
-+
-+    if (pulSignatureLen == NULL) {
-+        st_logf("signature len NULL\n");
-+        ret = CKR_ARGUMENTS_BAD;
-+        goto out;
-+    }
-+
-+    if (pData == NULL_PTR) {
-+        st_logf("data NULL\n");
-+        ret = CKR_ARGUMENTS_BAD;
-+        goto out;
-+    }
-+
-+    len = RSA_private_encrypt(ulDataLen, pData, buffer, rsa, padding);
-+    st_logf("private encrypt done\n");
-+    if (len <= 0) {
-+        ret = CKR_DEVICE_ERROR;
-+        goto out;
-+    }
-+    if (len > buffer_len)
-+        abort();
-+
-+    if (pSignature != NULL_PTR)
-+        memcpy(pSignature, buffer, len);
-+    *pulSignatureLen = len;
-+
-+    ret = CKR_OK;
-+
-+ out:
-+    if (buffer) {
-+        memset(buffer, 0, buffer_len);
-+        free(buffer);
-+    }
-+    return ret;
-+}
-+
-+CK_RV
-+C_SignUpdate(CK_SESSION_HANDLE hSession,
-+             CK_BYTE_PTR pPart,
-+             CK_ULONG ulPartLen)
-+{
-+    st_logf("SignUpdate\n");
-+    VERIFY_SESSION_HANDLE(hSession, NULL);
-+    return CKR_FUNCTION_NOT_SUPPORTED;
-+}
-+
-+
-+CK_RV
-+C_SignFinal(CK_SESSION_HANDLE hSession,
-+            CK_BYTE_PTR pSignature,
-+            CK_ULONG_PTR pulSignatureLen)
-+{
-+    st_logf("SignUpdate\n");
-+    VERIFY_SESSION_HANDLE(hSession, NULL);
-+    return CKR_FUNCTION_NOT_SUPPORTED;
-+}
-+
-+CK_RV
-+C_VerifyInit(CK_SESSION_HANDLE hSession,
-+             CK_MECHANISM_PTR pMechanism,
-+             CK_OBJECT_HANDLE hKey)
-+{
-+    struct session_state *state;
-+    CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS, CKM_RSA_X_509 };
-+    CK_BBOOL bool_true = CK_TRUE;
-+    CK_ATTRIBUTE attr[] = {
-+        { CKA_VERIFY, &bool_true, sizeof(bool_true) }
-+    };
-+    struct st_object *o;
-+    CK_RV ret;
-+
-+    st_logf("VerifyInit\n");
-+    VERIFY_SESSION_HANDLE(hSession, &state);
-+
-+    ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]),
-+                     mechs, sizeof(mechs)/sizeof(mechs[0]),
-+                     pMechanism, hKey, &o);
-+    if (ret)
-+        return ret;
-+
-+    ret = dup_mechanism(&state->verify_mechanism, pMechanism);
-+    if (ret == CKR_OK)
-+        state->verify_object = OBJECT_ID(o);
-+
-+    return ret;
-+}
-+
-+CK_RV
-+C_Verify(CK_SESSION_HANDLE hSession,
-+         CK_BYTE_PTR pData,
-+         CK_ULONG ulDataLen,
-+         CK_BYTE_PTR pSignature,
-+         CK_ULONG ulSignatureLen)
-+{
-+    struct session_state *state;
-+    struct st_object *o;
-+    void *buffer = NULL;
-+    CK_RV ret;
-+    RSA *rsa;
-+    int padding, len, buffer_len;
-+
-+    st_logf("Verify\n");
-+    VERIFY_SESSION_HANDLE(hSession, &state);
-+
-+    if (state->verify_object == -1)
-+        return CKR_ARGUMENTS_BAD;
-+
-+    o = soft_token.object.objs[state->verify_object];
-+
-+    if (o->u.public_key == NULL) {
-+        st_logf("public key NULL\n");
-+        return CKR_ARGUMENTS_BAD;
-+    }
-+
-+    rsa = o->u.public_key->pkey.rsa;
-+
-+    if (rsa == NULL)
-+        return CKR_ARGUMENTS_BAD;
-+
-+    RSA_blinding_off(rsa); /* XXX RAND is broken while running in mozilla ? */
-+
-+    buffer_len = RSA_size(rsa);
-+
-+    buffer = malloc(buffer_len);
-+    if (buffer == NULL) {
-+        ret = CKR_DEVICE_MEMORY;
-+        goto out;
-+    }
-+
-+    ret = CKR_OK;
-+    switch(state->verify_mechanism->mechanism) {
-+    case CKM_RSA_PKCS:
-+        padding = RSA_PKCS1_PADDING;
-+        break;
-+    case CKM_RSA_X_509:
-+        padding = RSA_NO_PADDING;
-+        break;
-+    default:
-+        ret = CKR_FUNCTION_NOT_SUPPORTED;
-+        goto out;
-+    }
-+
-+    if (buffer_len < ulDataLen) {
-+        ret = CKR_ARGUMENTS_BAD;
-+        goto out;
-+    }
-+
-+    if (pSignature == NULL) {
-+        st_logf("signature NULL\n");
-+        ret = CKR_ARGUMENTS_BAD;
-+        goto out;
-+    }
-+
-+    if (pData == NULL_PTR) {
-+        st_logf("data NULL\n");
-+        ret = CKR_ARGUMENTS_BAD;
-+        goto out;
-+    }
-+
-+    len = RSA_public_decrypt(ulDataLen, pData, buffer, rsa, padding);
-+    st_logf("private encrypt done\n");
-+    if (len <= 0) {
-+        ret = CKR_DEVICE_ERROR;
-+        goto out;
-+    }
-+    if (len > buffer_len)
-+        abort();
-+
-+    if (len != ulSignatureLen) {
-+        ret = CKR_GENERAL_ERROR;
-+        goto out;
-+    }
-+
-+    if (memcmp(pSignature, buffer, len) != 0) {
-+        ret = CKR_GENERAL_ERROR;
-+        goto out;
-+    }
-+
-+ out:
-+    if (buffer) {
-+        memset(buffer, 0, buffer_len);
-+        free(buffer);
-+    }
-+    return ret;
-+}
-+
-+
-+CK_RV
-+C_VerifyUpdate(CK_SESSION_HANDLE hSession,
-+               CK_BYTE_PTR pPart,
-+               CK_ULONG ulPartLen)
-+{
-+    st_logf("VerifyUpdate\n");
-+    VERIFY_SESSION_HANDLE(hSession, NULL);
-+    return CKR_FUNCTION_NOT_SUPPORTED;
-+}
-+
-+CK_RV
-+C_VerifyFinal(CK_SESSION_HANDLE hSession,
-+              CK_BYTE_PTR pSignature,
-+              CK_ULONG ulSignatureLen)
-+{
-+    st_logf("VerifyFinal\n");
-+    VERIFY_SESSION_HANDLE(hSession, NULL);
-+    return CKR_FUNCTION_NOT_SUPPORTED;
-+}
-+
-+CK_RV
-+C_GenerateRandom(CK_SESSION_HANDLE hSession,
-+                 CK_BYTE_PTR RandomData,
-+                 CK_ULONG ulRandomLen)
-+{
-+    st_logf("GenerateRandom\n");
-+    VERIFY_SESSION_HANDLE(hSession, NULL);
-+    return CKR_FUNCTION_NOT_SUPPORTED;
-+}
-+
-+
-+CK_FUNCTION_LIST funcs = {
-+    { 2, 11 },
-+    C_Initialize,
-+    C_Finalize,
-+    C_GetInfo,
-+    C_GetFunctionList,
-+    C_GetSlotList,
-+    C_GetSlotInfo,
-+    C_GetTokenInfo,
-+    C_GetMechanismList,
-+    C_GetMechanismInfo,
-+    C_InitToken,
-+    (void *)func_not_supported, /* C_InitPIN */
-+    (void *)func_not_supported, /* C_SetPIN */
-+    C_OpenSession,
-+    C_CloseSession,
-+    C_CloseAllSessions,
-+    C_GetSessionInfo,
-+    (void *)func_not_supported, /* C_GetOperationState */
-+    (void *)func_not_supported, /* C_SetOperationState */
-+    C_Login,
-+    C_Logout,
-+    (void *)func_not_supported, /* C_CreateObject */
-+    (void *)func_not_supported, /* C_CopyObject */
-+    (void *)func_not_supported, /* C_DestroyObject */
-+    (void *)func_not_supported, /* C_GetObjectSize */
-+    C_GetAttributeValue,
-+    (void *)func_not_supported, /* C_SetAttributeValue */
-+    C_FindObjectsInit,
-+    C_FindObjects,
-+    C_FindObjectsFinal,
-+    C_EncryptInit,
-+    C_Encrypt,
-+    C_EncryptUpdate,
-+    C_EncryptFinal,
-+    C_DecryptInit,
-+    C_Decrypt,
-+    C_DecryptUpdate,
-+    C_DecryptFinal,
-+    C_DigestInit,
-+    (void *)func_not_supported, /* C_Digest */
-+    (void *)func_not_supported, /* C_DigestUpdate */
-+    (void *)func_not_supported, /* C_DigestKey */
-+    (void *)func_not_supported, /* C_DigestFinal */
-+    C_SignInit,
-+    C_Sign,
-+    C_SignUpdate,
-+    C_SignFinal,
-+    (void *)func_not_supported, /* C_SignRecoverInit */
-+    (void *)func_not_supported, /* C_SignRecover */
-+    C_VerifyInit,
-+    C_Verify,
-+    C_VerifyUpdate,
-+    C_VerifyFinal,
-+    (void *)func_not_supported, /* C_VerifyRecoverInit */
-+    (void *)func_not_supported, /* C_VerifyRecover */
-+    (void *)func_not_supported, /* C_DigestEncryptUpdate */
-+    (void *)func_not_supported, /* C_DecryptDigestUpdate */
-+    (void *)func_not_supported, /* C_SignEncryptUpdate */
-+    (void *)func_not_supported, /* C_DecryptVerifyUpdate */
-+    (void *)func_not_supported, /* C_GenerateKey */
-+    (void *)func_not_supported, /* C_GenerateKeyPair */
-+    (void *)func_not_supported, /* C_WrapKey */
-+    (void *)func_not_supported, /* C_UnwrapKey */
-+    (void *)func_not_supported, /* C_DeriveKey */
-+    (void *)func_not_supported, /* C_SeedRandom */
-+    C_GenerateRandom,
-+    (void *)func_not_supported, /* C_GetFunctionStatus */
-+    (void *)func_not_supported, /* C_CancelFunction */
-+    (void *)func_not_supported  /* C_WaitForSlotEvent */
-+};
diff --git a/SOURCES/Add-tests-for-KCM-ccache-type.patch b/SOURCES/Add-tests-for-KCM-ccache-type.patch
deleted file mode 100644
index f572041..0000000
--- a/SOURCES/Add-tests-for-KCM-ccache-type.patch
+++ /dev/null
@@ -1,295 +0,0 @@
-From 7ab0bbac058d2b82aa3432759c600b22012f8afe Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Thu, 22 Nov 2018 00:27:35 -0500
-Subject: [PATCH] Add tests for KCM ccache type
-
-Using a trivial Python implementation of a KCM server, run the
-t_ccache.py tests against the KCM ccache type.
-
-(cherry picked from commit f0bcb86131e385b2603ccf0f3c7d65aa3891b220)
-(cherry picked from commit 5ecbe8d3ab4f53c0923a0442273bf18a9ff04fd5)
----
- src/tests/kcmserver.py | 246 +++++++++++++++++++++++++++++++++++++++++
- src/tests/t_ccache.py  |   9 +-
- 2 files changed, 254 insertions(+), 1 deletion(-)
- create mode 100644 src/tests/kcmserver.py
-
-diff --git a/src/tests/kcmserver.py b/src/tests/kcmserver.py
-new file mode 100644
-index 000000000..57432e5a7
---- /dev/null
-+++ b/src/tests/kcmserver.py
-@@ -0,0 +1,246 @@
-+# This is a simple KCM test server, used to exercise the KCM ccache
-+# client code.  It will generally throw an uncaught exception if the
-+# client sends anything unexpected, so is unsuitable for production.
-+# (It also imposes no namespace or access constraints, and blocks
-+# while reading requests and writing responses.)
-+
-+# This code knows nothing about how to marshal and unmarshal principal
-+# names and credentials as is required in the KCM protocol; instead,
-+# it just remembers the marshalled forms and replays them to the
-+# client when asked.  This works because marshalled creds and
-+# principal names are always the last part of marshalled request
-+# arguments, and because we don't need to implement remove_cred (which
-+# would need to know how to match a cred tag against previously stored
-+# credentials).
-+
-+# The following code is useful for debugging if anything appears to be
-+# going wrong in the server, since daemon output is generally not
-+# visible in Python test scripts.
-+#
-+# import sys, traceback
-+# def ehook(etype, value, tb):
-+#     with open('/tmp/exception', 'w') as f:
-+#         traceback.print_exception(etype, value, tb, file=f)
-+# sys.excepthook = ehook
-+
-+import select
-+import socket
-+import struct
-+import sys
-+
-+caches = {}
-+cache_uuidmap = {}
-+defname = b'default'
-+next_unique = 1
-+next_uuid = 1
-+
-+class KCMOpcodes(object):
-+    GEN_NEW = 3
-+    INITIALIZE = 4
-+    DESTROY = 5
-+    STORE = 6
-+    GET_PRINCIPAL = 8
-+    GET_CRED_UUID_LIST = 9
-+    GET_CRED_BY_UUID = 10
-+    REMOVE_CRED = 11
-+    GET_CACHE_UUID_LIST = 18
-+    GET_CACHE_BY_UUID = 19
-+    GET_DEFAULT_CACHE = 20
-+    SET_DEFAULT_CACHE = 21
-+    GET_KDC_OFFSET = 22
-+    SET_KDC_OFFSET = 23
-+
-+
-+class KRB5Errors(object):
-+    KRB5_CC_END = -1765328242
-+    KRB5_CC_NOSUPP = -1765328137
-+    KRB5_FCC_NOFILE = -1765328189
-+
-+
-+def make_uuid():
-+    global next_uuid
-+    uuid = bytes(12) + struct.pack('>L', next_uuid)
-+    next_uuid = next_uuid + 1
-+    return uuid
-+
-+
-+class Cache(object):
-+    def __init__(self, name):
-+        self.name = name
-+        self.princ = None
-+        self.uuid = make_uuid()
-+        self.cred_uuids = []
-+        self.creds = {}
-+        self.time_offset = 0
-+
-+
-+def get_cache(name):
-+    if name in caches:
-+        return caches[name]
-+    cache = Cache(name)
-+    caches[name] = cache
-+    cache_uuidmap[cache.uuid] = cache
-+    return cache
-+
-+
-+def unmarshal_name(argbytes):
-+    offset = argbytes.find(b'\0')
-+    return argbytes[0:offset], argbytes[offset+1:]
-+
-+
-+def op_gen_new(argbytes):
-+    # Does not actually check for uniqueness.
-+    global next_unique
-+    name = b'unique' + str(next_unique).encode('ascii')
-+    next_unique += 1
-+    return 0, name + b'\0'
-+
-+
-+def op_initialize(argbytes):
-+    name, princ = unmarshal_name(argbytes)
-+    cache = get_cache(name)
-+    cache.princ = princ
-+    cache.cred_uuids = []
-+    cache.creds = {}
-+    cache.time_offset = 0
-+    return 0, b''
-+
-+
-+def op_destroy(argbytes):
-+    name, rest = unmarshal_name(argbytes)
-+    cache = get_cache(name)
-+    del cache_uuidmap[cache.uuid]
-+    del caches[name]
-+    return 0, b''
-+
-+
-+def op_store(argbytes):
-+    name, cred = unmarshal_name(argbytes)
-+    cache = get_cache(name)
-+    uuid = make_uuid()
-+    cache.creds[uuid] = cred
-+    cache.cred_uuids.append(uuid)
-+    return 0, b''
-+
-+
-+def op_get_principal(argbytes):
-+    name, rest = unmarshal_name(argbytes)
-+    cache = get_cache(name)
-+    if cache.princ is None:
-+        return KRB5Errors.KRB5_FCC_NOFILE, b''
-+    return 0, cache.princ + b'\0'
-+
-+
-+def op_get_cred_uuid_list(argbytes):
-+    name, rest = unmarshal_name(argbytes)
-+    cache = get_cache(name)
-+    return 0, b''.join(cache.cred_uuids)
-+
-+
-+def op_get_cred_by_uuid(argbytes):
-+    name, uuid = unmarshal_name(argbytes)
-+    cache = get_cache(name)
-+    if uuid not in cache.creds:
-+        return KRB5Errors.KRB5_CC_END, b''
-+    return 0, cache.creds[uuid]
-+
-+
-+def op_remove_cred(argbytes):
-+    return KRB5Errors.KRB5_CC_NOSUPP, b''
-+
-+
-+def op_get_cache_uuid_list(argbytes):
-+    return 0, b''.join(cache_uuidmap.keys())
-+
-+
-+def op_get_cache_by_uuid(argbytes):
-+    uuid = argbytes
-+    if uuid not in cache_uuidmap:
-+        return KRB5Errors.KRB5_CC_END, b''
-+    return 0, cache_uuidmap[uuid].name + b'\0'
-+
-+
-+def op_get_default_cache(argbytes):
-+    return 0, defname + b'\0'
-+
-+
-+def op_set_default_cache(argbytes):
-+    global defname
-+    defname, rest = unmarshal_name(argbytes)
-+    return 0, b''
-+
-+
-+def op_get_kdc_offset(argbytes):
-+    name, rest = unmarshal_name(argbytes)
-+    cache = get_cache(name)
-+    return 0, struct.pack('>l', cache.time_offset)
-+
-+
-+def op_set_kdc_offset(argbytes):
-+    name, obytes = unmarshal_name(argbytes)
-+    cache = get_cache(name)
-+    cache.time_offset, = struct.unpack('>l', obytes)
-+    return 0, b''
-+
-+
-+ophandlers = {
-+    KCMOpcodes.GEN_NEW : op_gen_new,
-+    KCMOpcodes.INITIALIZE : op_initialize,
-+    KCMOpcodes.DESTROY : op_destroy,
-+    KCMOpcodes.STORE : op_store,
-+    KCMOpcodes.GET_PRINCIPAL : op_get_principal,
-+    KCMOpcodes.GET_CRED_UUID_LIST : op_get_cred_uuid_list,
-+    KCMOpcodes.GET_CRED_BY_UUID : op_get_cred_by_uuid,
-+    KCMOpcodes.REMOVE_CRED : op_remove_cred,
-+    KCMOpcodes.GET_CACHE_UUID_LIST : op_get_cache_uuid_list,
-+    KCMOpcodes.GET_CACHE_BY_UUID : op_get_cache_by_uuid,
-+    KCMOpcodes.GET_DEFAULT_CACHE : op_get_default_cache,
-+    KCMOpcodes.SET_DEFAULT_CACHE : op_set_default_cache,
-+    KCMOpcodes.GET_KDC_OFFSET : op_get_kdc_offset,
-+    KCMOpcodes.SET_KDC_OFFSET : op_set_kdc_offset
-+}
-+
-+# Read and respond to a request from the socket s.
-+def service_request(s):
-+    lenbytes = b''
-+    while len(lenbytes) < 4:
-+        lenbytes += s.recv(4 - len(lenbytes))
-+        if lenbytes == b'':
-+                return False
-+
-+    reqlen, = struct.unpack('>L', lenbytes)
-+    req = b''
-+    while len(req) < reqlen:
-+        req += s.recv(reqlen - len(req))
-+
-+    majver, minver, op = struct.unpack('>BBH', req[:4])
-+    argbytes = req[4:]
-+    code, payload = ophandlers[op](argbytes)
-+
-+    # The KCM response is the code (4 bytes) and the response payload.
-+    # The Heimdal IPC response is the length of the KCM response (4
-+    # bytes), a status code which is essentially always 0 (4 bytes),
-+    # and the KCM response.
-+    kcm_response = struct.pack('>l', code) + payload
-+    hipc_response = struct.pack('>LL', len(kcm_response), 0) + kcm_response
-+    s.sendall(hipc_response)
-+    return True
-+
-+
-+server = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
-+server.bind(sys.argv[1])
-+server.listen(5)
-+select_input = [server,]
-+sys.stderr.write('starting...\n')
-+sys.stderr.flush()
-+
-+while True:
-+    iready, oready, xready = select.select(select_input, [], [])
-+    for s in iready:
-+        if s == server:
-+            client, addr = server.accept()
-+            select_input.append(client)
-+        else:
-+            if not service_request(s):
-+                select_input.remove(s)
-+                s.close()
-diff --git a/src/tests/t_ccache.py b/src/tests/t_ccache.py
-index fcf1a611e..66804afa5 100755
---- a/src/tests/t_ccache.py
-+++ b/src/tests/t_ccache.py
-@@ -22,7 +22,10 @@
- 
- from k5test import *
- 
--realm = K5Realm(create_host=False)
-+kcm_socket_path = os.path.join(os.getcwd(), 'testdir', 'kcm')
-+conf = {'libdefaults': {'kcm_socket': kcm_socket_path,
-+                        'kcm_mach_service': '-'}}
-+realm = K5Realm(create_host=False, krb5_conf=conf)
- 
- keyctl = which('keyctl')
- out = realm.run([klist, '-c', 'KEYRING:process:abcd'], expected_code=1)
-@@ -122,6 +125,10 @@ def collection_test(realm, ccname):
- 
- 
- collection_test(realm, 'DIR:' + os.path.join(realm.testdir, 'cc'))
-+kcmserver_path = os.path.join(srctop, 'tests', 'kcmserver.py')
-+realm.start_server([sys.executable, kcmserver_path, kcm_socket_path],
-+                   'starting...')
-+collection_test(realm, 'KCM:')
- if test_keyring:
-     def cleanup_keyring(anchor, name):
-         out = realm.run(['keyctl', 'list', anchor])
diff --git a/SOURCES/Address-some-optimized-out-memset-calls.patch b/SOURCES/Address-some-optimized-out-memset-calls.patch
deleted file mode 100644
index 372e527..0000000
--- a/SOURCES/Address-some-optimized-out-memset-calls.patch
+++ /dev/null
@@ -1,95 +0,0 @@
-From 722247aa6201d18a7ee69c4a9a05315226fe6383 Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Sun, 30 Dec 2018 16:40:28 -0500
-Subject: [PATCH] Address some optimized-out memset() calls
-
-Ilja Van Sprundel reported a list of memset() calls which gcc
-optimizes out.  In krb_auth_su.c, use zap() to clear the password, and
-remove two memset() calls when there is no password to clear.  In
-iakerb.c, remove an unnecessary memset() before setting the only two
-fields of the IAKERB header structure.  In svr_principal.c, use
-krb5_free_key_keyblock_contents() instead of hand-freeing key data.
-In asn1_k_encode.c, remove an unnecessary memset() of the kdc_req_hack
-shell before returning.
-
-(cherry picked from commit 1057b0befec1f1c0e9d4da5521a58496e2dc0997)
-(cherry picked from commit 1dfff7202448a950c9133cdfe43d650092d930fd)
----
- src/clients/ksu/krb_auth_su.c      |  4 +---
- src/lib/gssapi/krb5/iakerb.c       |  1 -
- src/lib/kadm5/srv/svr_principal.c  | 10 ++--------
- src/lib/krb5/asn.1/asn1_k_encode.c |  1 -
- 4 files changed, 3 insertions(+), 13 deletions(-)
-
-diff --git a/src/clients/ksu/krb_auth_su.c b/src/clients/ksu/krb_auth_su.c
-index 7af48195c..e39685fff 100644
---- a/src/clients/ksu/krb_auth_su.c
-+++ b/src/clients/ksu/krb_auth_su.c
-@@ -183,21 +183,19 @@ krb5_boolean ksu_get_tgt_via_passwd(context, client, options, zero_password,
-     if (code ) {
-         com_err(prog_name, code, _("while reading password for '%s'\n"),
-                 client_name);
--        memset(password, 0, sizeof(password));
-         return (FALSE);
-     }
- 
-     if ( pwsize == 0) {
-         fprintf(stderr, _("No password given\n"));
-         *zero_password = TRUE;
--        memset(password, 0, sizeof(password));
-         return (FALSE);
-     }
- 
-     code = krb5_get_init_creds_password(context, &creds, client, password,
-                                         krb5_prompter_posix, NULL, 0, NULL,
-                                         options);
--    memset(password, 0, sizeof(password));
-+    zap(password, sizeof(password));
- 
- 
-     if (code) {
-diff --git a/src/lib/gssapi/krb5/iakerb.c b/src/lib/gssapi/krb5/iakerb.c
-index bb1072fe4..47c161ec9 100644
---- a/src/lib/gssapi/krb5/iakerb.c
-+++ b/src/lib/gssapi/krb5/iakerb.c
-@@ -262,7 +262,6 @@ iakerb_make_token(iakerb_ctx_id_t ctx,
-     /*
-      * Assemble the IAKERB-HEADER from the realm and cookie
-      */
--    memset(&iah, 0, sizeof(iah));
-     iah.target_realm = *realm;
-     iah.cookie = cookie;
- 
-diff --git a/src/lib/kadm5/srv/svr_principal.c b/src/lib/kadm5/srv/svr_principal.c
-index 21c53ece1..9ab2c5a74 100644
---- a/src/lib/kadm5/srv/svr_principal.c
-+++ b/src/lib/kadm5/srv/svr_principal.c
-@@ -2093,14 +2093,8 @@ static int decrypt_key_data(krb5_context context,
-         ret = krb5_dbe_decrypt_key_data(context, NULL, &key_data[i], &keys[i],
-                                         NULL);
-         if (ret) {
--            for (; i >= 0; i--) {
--                if (keys[i].contents) {
--                    memset (keys[i].contents, 0, keys[i].length);
--                    free( keys[i].contents );
--                }
--            }
--
--            memset(keys, 0, n_key_data*sizeof(krb5_keyblock));
-+            for (; i >= 0; i--)
-+                krb5_free_keyblock_contents(context, &keys[i]);
-             free(keys);
-             return ret;
-         }
-diff --git a/src/lib/krb5/asn.1/asn1_k_encode.c b/src/lib/krb5/asn.1/asn1_k_encode.c
-index 65c84be2f..81a34bac9 100644
---- a/src/lib/krb5/asn.1/asn1_k_encode.c
-+++ b/src/lib/krb5/asn.1/asn1_k_encode.c
-@@ -528,7 +528,6 @@ decode_kdc_req_body(const taginfo *t, const uint8_t *asn1, size_t len,
-         if (ret) {
-             free_kdc_req_body(b);
-             free(h.server_realm.data);
--            memset(&h, 0, sizeof(h));
-             return ret;
-         }
-         b->server->realm = h.server_realm;
diff --git a/SOURCES/Allow-certauth-modules-to-set-hw-authent-flag.patch b/SOURCES/Allow-certauth-modules-to-set-hw-authent-flag.patch
new file mode 100644
index 0000000..f728c1c
--- /dev/null
+++ b/SOURCES/Allow-certauth-modules-to-set-hw-authent-flag.patch
@@ -0,0 +1,242 @@
+From b4dba5a4c16b2585c38445e3067b5e3399f38a10 Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Mon, 24 Feb 2020 15:58:59 -0500
+Subject: [PATCH] Allow certauth modules to set hw-authent flag
+
+In PKINIT, if a certauth module returns KRB5_CERTAUTH_HWAUTH from its
+authorize method, set the hw-authent flag in the ticket.
+
+ticket: 8879 (new)
+(cherry picked from commit 50fb43b4a2d97ce2cd53e1ced30e8e8224fede70)
+(cherry picked from commit d23b2ed4f06fa77cd021814834dd1391ef6f452f)
+---
+ doc/plugindev/certauth.rst              |  7 +++++--
+ src/include/krb5/certauth_plugin.h      |  9 ++++++---
+ src/lib/krb5/error_tables/k5e1_err.et   |  1 +
+ src/plugins/certauth/test/Makefile.in   |  4 ++--
+ src/plugins/certauth/test/main.c        | 11 +++++++++--
+ src/plugins/preauth/pkinit/pkinit_srv.c | 24 ++++++++++++++++--------
+ src/tests/t_certauth.py                 | 13 +++++++++++++
+ 7 files changed, 52 insertions(+), 17 deletions(-)
+
+diff --git a/doc/plugindev/certauth.rst b/doc/plugindev/certauth.rst
+index 8a7f7c5eb..3b715f738 100644
+--- a/doc/plugindev/certauth.rst
++++ b/doc/plugindev/certauth.rst
+@@ -15,8 +15,11 @@ principal.  **authorize** receives the DER-encoded certificate, the
+ requested client principal, and a pointer to the client's
+ krb5_db_entry (for modules that link against libkdb5).  It returns the
+ authorization status and optionally outputs a list of authentication
+-indicator strings to be added to the ticket.  A module must use its
+-own internal or library-provided ASN.1 certificate decoder.
++indicator strings to be added to the ticket.  Beginning in release
++1.19, the authorize method can request that the hardware
++authentication bit be set in the ticket by returning
++**KRB5_CERTAUTH_HWAUTH**.  A module must use its own internal or
++library-provided ASN.1 certificate decoder.
+ 
+ A module can optionally create and destroy module data with the
+ **init** and **fini** methods.  Module data objects last for the
+diff --git a/src/include/krb5/certauth_plugin.h b/src/include/krb5/certauth_plugin.h
+index 3074790f8..3466cf345 100644
+--- a/src/include/krb5/certauth_plugin.h
++++ b/src/include/krb5/certauth_plugin.h
+@@ -85,14 +85,17 @@ typedef void
+ (*krb5_certauth_fini_fn)(krb5_context context, krb5_certauth_moddata moddata);
+ 
+ /*
+- * Mandatory:
+- * Return 0 if the DER-encoded cert is authorized for PKINIT authentication by
+- * princ; otherwise return one of the following error codes:
++ * Mandatory: return 0 or KRB5_CERTAUTH_HWAUTH if the DER-encoded cert is
++ * authorized for PKINIT authentication by princ; otherwise return one of the
++ * following error codes:
+  * - KRB5KDC_ERR_CLIENT_NAME_MISMATCH - incorrect SAN value
+  * - KRB5KDC_ERR_INCONSISTENT_KEY_PURPOSE - incorrect EKU
+  * - KRB5KDC_ERR_CERTIFICATE_MISMATCH - other extension error
+  * - KRB5_PLUGIN_NO_HANDLE - the module has no opinion about cert
+  *
++ * Returning KRB5_CERTAUTH_HWAUTH will cause the hw-authent flag to be set in
++ * the issued ticket (new in release 1.19).
++ *
+  * - opts is used by built-in modules to receive internal data, and must be
+  *   ignored by other modules.
+  * - db_entry receives the client principal database entry, and can be ignored
+diff --git a/src/lib/krb5/error_tables/k5e1_err.et b/src/lib/krb5/error_tables/k5e1_err.et
+index ade5caecf..abd9f3bfe 100644
+--- a/src/lib/krb5/error_tables/k5e1_err.et
++++ b/src/lib/krb5/error_tables/k5e1_err.et
+@@ -42,4 +42,5 @@ error_code KRB5_KCM_MALFORMED_REPLY, "Malformed reply from KCM daemon"
+ error_code KRB5_KCM_RPC_ERROR, "Mach RPC error communicating with KCM daemon"
+ error_code KRB5_KCM_REPLY_TOO_BIG, "KCM daemon reply too big"
+ error_code KRB5_KCM_NO_SERVER, "No KCM server found"
++error_code KRB5_CERTAUTH_HWAUTH, "Authorize and set hw-authent ticket flag"
+ end
+diff --git a/src/plugins/certauth/test/Makefile.in b/src/plugins/certauth/test/Makefile.in
+index d3524084c..e94c13845 100644
+--- a/src/plugins/certauth/test/Makefile.in
++++ b/src/plugins/certauth/test/Makefile.in
+@@ -5,8 +5,8 @@ LIBBASE=certauth_test
+ LIBMAJOR=0
+ LIBMINOR=0
+ RELDIR=../plugins/certauth/test
+-SHLIB_EXPDEPS=$(KRB5_BASE_DEPLIBS)
+-SHLIB_EXPLIBS=$(KRB5_BASE_LIBS)
++SHLIB_EXPDEPS=$(KDB5_DEPLIBS) $(KRB5_BASE_DEPLIBS)
++SHLIB_EXPLIBS=$(KDB5_LIBS) $(KRB5_BASE_LIBS)
+ 
+ STLIBOBJS=main.o
+ 
+diff --git a/src/plugins/certauth/test/main.c b/src/plugins/certauth/test/main.c
+index 77641230c..d4633b8cd 100644
+--- a/src/plugins/certauth/test/main.c
++++ b/src/plugins/certauth/test/main.c
+@@ -31,6 +31,7 @@
+  */
+ 
+ #include <k5-int.h>
++#include <kdb.h>
+ #include "krb5/certauth_plugin.h"
+ 
+ struct krb5_certauth_moddata_st {
+@@ -131,7 +132,8 @@ has_cn(krb5_context context, const uint8_t *cert, size_t cert_len,
+ 
+ /*
+  * Test module 2 returns OK if princ matches the CN part of the subject name,
+- * and returns indicators of the module name and princ.
++ * and returns indicators of the module name and princ.  If the "hwauth" string
++ * attribute is set on db_entry, it returns KRB5_CERTAUTH_HWAUTH.
+  */
+ static krb5_error_code
+ test2_authorize(krb5_context context, krb5_certauth_moddata moddata,
+@@ -141,7 +143,7 @@ test2_authorize(krb5_context context, krb5_certauth_moddata moddata,
+                 char ***authinds_out)
+ {
+     krb5_error_code ret;
+-    char *name = NULL, **ais = NULL;
++    char *name = NULL, *strval = NULL, **ais = NULL;
+ 
+     *authinds_out = NULL;
+ 
+@@ -167,6 +169,11 @@ test2_authorize(krb5_context context, krb5_certauth_moddata moddata,
+ 
+     ais = NULL;
+ 
++    ret = krb5_dbe_get_string(context, (krb5_db_entry *)db_entry, "hwauth",
++                              &strval);
++    ret = (strval != NULL) ? KRB5_CERTAUTH_HWAUTH : 0;
++    krb5_dbe_free_string(context, strval);
++
+ cleanup:
+     krb5_free_unparsed_name(context, name);
+     return ret;
+diff --git a/src/plugins/preauth/pkinit/pkinit_srv.c b/src/plugins/preauth/pkinit/pkinit_srv.c
+index feca11806..3ae56c064 100644
+--- a/src/plugins/preauth/pkinit/pkinit_srv.c
++++ b/src/plugins/preauth/pkinit/pkinit_srv.c
+@@ -320,12 +320,12 @@ static krb5_error_code
+ authorize_cert(krb5_context context, certauth_handle *certauth_modules,
+                pkinit_kdc_context plgctx, pkinit_kdc_req_context reqctx,
+                krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock,
+-               krb5_principal client)
++               krb5_principal client, krb5_boolean *hwauth_out)
+ {
+     krb5_error_code ret;
+     certauth_handle h;
+     struct certauth_req_opts opts;
+-    krb5_boolean accepted = FALSE;
++    krb5_boolean accepted = FALSE, hwauth = FALSE;
+     uint8_t *cert;
+     size_t i, cert_len;
+     void *db_ent = NULL;
+@@ -347,9 +347,10 @@ authorize_cert(krb5_context context, certauth_handle *certauth_modules,
+ 
+     /*
+      * Check the certificate against each certauth module.  For the certificate
+-     * to be authorized at least one module must return 0, and no module can an
+-     * error code other than KRB5_PLUGIN_NO_HANDLE (pass).  Add indicators from
+-     * modules that return 0 or pass.
++     * to be authorized at least one module must return 0 or
++     * KRB5_CERTAUTH_HWAUTH, and no module can return an error code other than
++     * KRB5_PLUGIN_NO_HANDLE (pass).  Add indicators from modules that return 0
++     * or pass.
+      */
+     ret = KRB5_PLUGIN_NO_HANDLE;
+     for (i = 0; certauth_modules != NULL && certauth_modules[i] != NULL; i++) {
+@@ -359,6 +360,8 @@ authorize_cert(krb5_context context, certauth_handle *certauth_modules,
+                               &opts, db_ent, &ais);
+         if (ret == 0)
+             accepted = TRUE;
++        else if (ret == KRB5_CERTAUTH_HWAUTH)
++            accepted = hwauth = TRUE;
+         else if (ret != KRB5_PLUGIN_NO_HANDLE)
+             goto cleanup;
+ 
+@@ -374,6 +377,7 @@ authorize_cert(krb5_context context, certauth_handle *certauth_modules,
+         }
+     }
+ 
++    *hwauth_out = hwauth;
+     ret = accepted ? 0 : KRB5KDC_ERR_CLIENT_NAME_MISMATCH;
+ 
+ cleanup:
+@@ -430,7 +434,7 @@ pkinit_server_verify_padata(krb5_context context,
+     int is_signed = 1;
+     krb5_pa_data **e_data = NULL;
+     krb5_kdcpreauth_modreq modreq = NULL;
+-    krb5_boolean valid_freshness_token = FALSE;
++    krb5_boolean valid_freshness_token = FALSE, hwauth = FALSE;
+     char **sp;
+ 
+     pkiDebug("pkinit_verify_padata: entered!\n");
+@@ -494,7 +498,7 @@ pkinit_server_verify_padata(krb5_context context,
+     }
+     if (is_signed) {
+         retval = authorize_cert(context, moddata->certauth_modules, plgctx,
+-                                reqctx, cb, rock, request->client);
++                                reqctx, cb, rock, request->client, &hwauth);
+         if (retval)
+             goto cleanup;
+ 
+@@ -613,6 +617,8 @@ pkinit_server_verify_padata(krb5_context context,
+ 
+     /* remember to set the PREAUTH flag in the reply */
+     enc_tkt_reply->flags |= TKT_FLG_PRE_AUTH;
++    if (hwauth)
++        enc_tkt_reply->flags |= TKT_FLG_HW_AUTH;
+     modreq = (krb5_kdcpreauth_modreq)reqctx;
+     reqctx = NULL;
+ 
+@@ -1044,7 +1050,9 @@ pkinit_server_get_flags(krb5_context kcontext, krb5_preauthtype patype)
+ {
+     if (patype == KRB5_PADATA_PKINIT_KX)
+         return PA_INFO;
+-    return PA_SUFFICIENT | PA_REPLACES_KEY | PA_TYPED_E_DATA;
++    /* PKINIT does not normally set the hw-authent ticket flag, but a
++     * certauth module can cause it to do so. */
++    return PA_SUFFICIENT | PA_REPLACES_KEY | PA_TYPED_E_DATA | PA_HARDWARE;
+ }
+ 
+ static krb5_preauthtype supported_server_pa_types[] = {
+diff --git a/src/tests/t_certauth.py b/src/tests/t_certauth.py
+index 9c7094525..0fe0fdb4a 100644
+--- a/src/tests/t_certauth.py
++++ b/src/tests/t_certauth.py
+@@ -43,4 +43,17 @@ out = realm.kinit("user2@KRBTEST.COM",
+                   expected_code=1,
+                   expected_msg='kinit: Certificate mismatch')
+ 
++# Test the KRB5_CERTAUTH_HWAUTH return code.
++mark('hw-authent flag tests')
++# First test +requires_hwauth without causing the hw-authent ticket
++# flag to be set.  This currently results in a preauth loop.
++realm.run([kadminl, 'modprinc', '+requires_hwauth', realm.user_princ])
++realm.kinit(realm.user_princ,
++            flags=['-X', 'X509_user_identity=%s' % file_identity],
++            expected_code=1, expected_msg='Looping detected')
++# Cause the test2 module to return KRB5_CERTAUTH_HWAUTH and try again.
++realm.run([kadminl, 'setstr', realm.user_princ, 'hwauth', 'x'])
++realm.kinit(realm.user_princ,
++            flags=['-X', 'X509_user_identity=%s' % file_identity])
++
+ success("certauth tests")
diff --git a/SOURCES/Avoid-alignment-warnings-in-openssl-rc4.c.patch b/SOURCES/Avoid-alignment-warnings-in-openssl-rc4.c.patch
deleted file mode 100644
index e684c88..0000000
--- a/SOURCES/Avoid-alignment-warnings-in-openssl-rc4.c.patch
+++ /dev/null
@@ -1,63 +0,0 @@
-From e22f3e2439903aa05321ca339be6a12067b2c4db Mon Sep 17 00:00:00 2001
-From: Robbie Harwood <rharwood@redhat.com>
-Date: Mon, 6 May 2019 15:14:49 -0400
-Subject: [PATCH] Avoid alignment warnings in openssl rc4.c
-
-Add a comment to k5_arcfour_init_state() explaining how we stretch the
-krb5_data cipher state contract.  Use void * casts when interpreting
-the data pointer to avoid alignment warnings.
-
-[ghudson@mit.edu: moved and expanded comment; rewrote commit message]
-
-(cherry picked from commit 1cd41d76c12fc1cea0a8bf0d6a40f34623c60d6d)
----
- src/lib/crypto/openssl/enc_provider/rc4.c | 15 ++++++++++++---
- 1 file changed, 12 insertions(+), 3 deletions(-)
-
-diff --git a/src/lib/crypto/openssl/enc_provider/rc4.c b/src/lib/crypto/openssl/enc_provider/rc4.c
-index 7f3c086ed..a65d57b7a 100644
---- a/src/lib/crypto/openssl/enc_provider/rc4.c
-+++ b/src/lib/crypto/openssl/enc_provider/rc4.c
-@@ -57,7 +57,7 @@ struct arcfour_state {
- 
- /* In-place IOV crypto */
- static krb5_error_code
--k5_arcfour_docrypt(krb5_key key,const krb5_data *state, krb5_crypto_iov *data,
-+k5_arcfour_docrypt(krb5_key key, const krb5_data *state, krb5_crypto_iov *data,
-                    size_t num_data)
- {
-     size_t i;
-@@ -66,7 +66,7 @@ k5_arcfour_docrypt(krb5_key key,const krb5_data *state, krb5_crypto_iov *data,
-     EVP_CIPHER_CTX *ctx = NULL;
-     struct arcfour_state *arcstate;
- 
--    arcstate = (state != NULL) ? (struct arcfour_state *) state->data : NULL;
-+    arcstate = (state != NULL) ? (void *)state->data : NULL;
-     if (arcstate != NULL) {
-         ctx = arcstate->ctx;
-         if (arcstate->loopback != arcstate)
-@@ -113,7 +113,7 @@ k5_arcfour_docrypt(krb5_key key,const krb5_data *state, krb5_crypto_iov *data,
- static void
- k5_arcfour_free_state(krb5_data *state)
- {
--    struct arcfour_state *arcstate = (struct arcfour_state *) state->data;
-+    struct arcfour_state *arcstate = (void *)state->data;
- 
-     EVP_CIPHER_CTX_free(arcstate->ctx);
-     free(arcstate);
-@@ -125,6 +125,15 @@ k5_arcfour_init_state(const krb5_keyblock *key,
- {
-     struct arcfour_state *arcstate;
- 
-+    /*
-+     * 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
-+     * object includes a loopback pointer to detect if if the caller made a
-+     * copy of the krb5_data value or otherwise assumed it was a simple byte
-+     * array.  When we cast the data pointer back, we need to go through void *
-+     * to avoid increased alignment warnings.
-+     */
-+
-     /* Create a state structure with an uninitialized context. */
-     arcstate = calloc(1, sizeof(*arcstate));
-     if (arcstate == NULL)
diff --git a/SOURCES/Correctly-import-service-GSS-host-based-name.patch b/SOURCES/Correctly-import-service-GSS-host-based-name.patch
new file mode 100644
index 0000000..5c03863
--- /dev/null
+++ b/SOURCES/Correctly-import-service-GSS-host-based-name.patch
@@ -0,0 +1,53 @@
+From abcbd3d12b0c92aa37384627edb6e1e6fad9b47a Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Mon, 30 Mar 2020 15:26:02 -0400
+Subject: [PATCH] Correctly import "service@" GSS host-based name
+
+The intended way to specify only a service in a GSS host-based name is
+to omit the "@" separator.  Some applications include the separator
+but no hostname, and this happened to yield wildcard hostname behavior
+prior to commit 996353767fe8afa7f67a3b5b465e4d70e18bad7c when
+shortname qualification was added.  To restore this behavior, check in
+parse_hostbased() that at least one character is present after the "@"
+separator before copying the hostname.  Add a test case to t_gssapi.py.
+
+ticket: 8892
+tags: pullup
+target_version: 1.18-next
+
+(cherry picked from commit a2f047af0400ba8080dc26033fae2b17534501e2)
+(cherry picked from commit dd4364d76925ce1fe21c2ab995554d6af3a2ea12)
+---
+ src/lib/gssapi/krb5/import_name.c | 4 ++--
+ src/tests/gssapi/t_gssapi.py      | 3 +++
+ 2 files changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/src/lib/gssapi/krb5/import_name.c b/src/lib/gssapi/krb5/import_name.c
+index da2ab1423..21023dd76 100644
+--- a/src/lib/gssapi/krb5/import_name.c
++++ b/src/lib/gssapi/krb5/import_name.c
+@@ -102,8 +102,8 @@ parse_hostbased(const char *str, size_t len,
+     memcpy(service, str, servicelen);
+     service[servicelen] = '\0';
+ 
+-    /* If present, copy the hostname. */
+-    if (at != NULL) {
++    /* Copy the hostname if present (at least one character after '@'). */
++    if (len - servicelen > 1) {
+         hostlen = len - servicelen - 1;
+         host = malloc(hostlen + 1);
+         if (host == NULL) {
+diff --git a/src/tests/gssapi/t_gssapi.py b/src/tests/gssapi/t_gssapi.py
+index 54d5cf549..ecf982604 100755
+--- a/src/tests/gssapi/t_gssapi.py
++++ b/src/tests/gssapi/t_gssapi.py
+@@ -47,6 +47,9 @@ realm.run(['./t_accname', 'p:service2/calvin', 'h:service2'],
+           expected_msg='service2/calvin')
+ realm.run(['./t_accname', 'p:service2/calvin', 'h:service1'], expected_code=1,
+           expected_msg=' found in keytab but does not match server principal')
++# Regression test for #8892 (trailing @ in name).
++realm.run(['./t_accname', 'p:service1/andrew', 'h:service1@'],
++          expected_msg='service1/abraham')
+ 
+ # Test with acceptor name containing service and host.  Use the
+ # client's un-canonicalized hostname as acceptor input to mirror what
diff --git a/SOURCES/Do-expiration-warnings-for-all-init_creds-APIs.patch b/SOURCES/Do-expiration-warnings-for-all-init_creds-APIs.patch
new file mode 100644
index 0000000..d4cb2c4
--- /dev/null
+++ b/SOURCES/Do-expiration-warnings-for-all-init_creds-APIs.patch
@@ -0,0 +1,426 @@
+From 640ba4fe0c5d7423431d649f8e5e6ac72341f4ab Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Fri, 28 Feb 2020 10:11:49 +0100
+Subject: [PATCH] Do expiration warnings for all init_creds APIs
+
+Move the password expiration warning code from gic_pwd.c to
+get_in_tkt.c.  Call it from init_creds_step_reply() on successful
+completion.
+
+[ghudson@mit.edu: added test case; simplified doc comment; moved call
+site to init_creds_step_reply(); rewrote commit message]
+
+ticket: 8893 (new)
+(cherry picked from commit e1efb890f7ac31b32c68ab816ef118dbfb5a8c7e)
+(cherry picked from commit c136cfe050d203c910624573a33247fde2889b09)
+---
+ src/include/krb5/krb5.hin         |   9 ++-
+ src/lib/krb5/krb/get_in_tkt.c     | 112 ++++++++++++++++++++++++++++++
+ src/lib/krb5/krb/gic_pwd.c        | 110 -----------------------------
+ src/lib/krb5/krb/t_expire_warn.c  |  47 +++++++++----
+ src/lib/krb5/krb/t_expire_warn.py |  22 ++++--
+ 5 files changed, 165 insertions(+), 135 deletions(-)
+
+diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin
+index 6355e6540..f8269fb17 100644
+--- a/src/include/krb5/krb5.hin
++++ b/src/include/krb5/krb5.hin
+@@ -7174,11 +7174,10 @@ typedef void
+  *
+  * Set a callback to receive password and account expiration times.
+  *
+- * This option only applies to krb5_get_init_creds_password().  @a cb will be
+- * invoked if and only if credentials are successfully acquired.  The callback
+- * will receive the @a context from the krb5_get_init_creds_password() call and
+- * the @a data argument supplied with this API.  The remaining arguments should
+- * be interpreted as follows:
++ * @a cb will be invoked if and only if credentials are successfully acquired.
++ * The callback will receive the @a context from the calling function and the
++ * @a data argument supplied with this API.  The remaining arguments should be
++ * interpreted as follows:
+  *
+  * If @a is_last_req is true, then the KDC reply contained last-req entries
+  * which unambiguously indicated the password expiration, account expiration,
+diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c
+index 870df62a1..cc0f70e83 100644
+--- a/src/lib/krb5/krb/get_in_tkt.c
++++ b/src/lib/krb5/krb/get_in_tkt.c
+@@ -1482,6 +1482,116 @@ accept_method_data(krb5_context context, krb5_init_creds_context ctx)
+                                      ctx->method_padata);
+ }
+ 
++/* Return the password expiry time indicated by enc_part2.  Set *is_last_req
++ * if the information came from a last_req value. */
++static void
++get_expiry_times(krb5_enc_kdc_rep_part *enc_part2, krb5_timestamp *pw_exp,
++                 krb5_timestamp *acct_exp, krb5_boolean *is_last_req)
++{
++    krb5_last_req_entry **last_req;
++    krb5_int32 lr_type;
++
++    *pw_exp = 0;
++    *acct_exp = 0;
++    *is_last_req = FALSE;
++
++    /* Look for last-req entries for password or account expiration. */
++    if (enc_part2->last_req) {
++        for (last_req = enc_part2->last_req; *last_req; last_req++) {
++            lr_type = (*last_req)->lr_type;
++            if (lr_type == KRB5_LRQ_ALL_PW_EXPTIME ||
++                lr_type == KRB5_LRQ_ONE_PW_EXPTIME) {
++                *is_last_req = TRUE;
++                *pw_exp = (*last_req)->value;
++            } else if (lr_type == KRB5_LRQ_ALL_ACCT_EXPTIME ||
++                       lr_type == KRB5_LRQ_ONE_ACCT_EXPTIME) {
++                *is_last_req = TRUE;
++                *acct_exp = (*last_req)->value;
++            }
++        }
++    }
++
++    /* If we didn't find any, use the ambiguous key_exp field. */
++    if (*is_last_req == FALSE)
++        *pw_exp = enc_part2->key_exp;
++}
++
++/*
++ * Send an appropriate warning prompter if as_reply indicates that the password
++ * is going to expire soon.  If an expire callback was provided, use that
++ * instead.
++ */
++static void
++warn_pw_expiry(krb5_context context, krb5_get_init_creds_opt *options,
++               krb5_prompter_fct prompter, void *data,
++               const char *in_tkt_service, krb5_kdc_rep *as_reply)
++{
++    krb5_error_code ret;
++    krb5_expire_callback_func expire_cb;
++    void *expire_data;
++    krb5_timestamp pw_exp, acct_exp, now;
++    krb5_boolean is_last_req;
++    krb5_deltat delta;
++    char ts[256], banner[1024];
++
++    if (as_reply == NULL || as_reply->enc_part2 == NULL)
++        return;
++
++    get_expiry_times(as_reply->enc_part2, &pw_exp, &acct_exp, &is_last_req);
++
++    k5_gic_opt_get_expire_cb(options, &expire_cb, &expire_data);
++    if (expire_cb != NULL) {
++        /* Invoke the expire callback and don't send prompter warnings. */
++        (*expire_cb)(context, expire_data, pw_exp, acct_exp, is_last_req);
++        return;
++    }
++
++    /* Don't warn if no password expiry value was sent. */
++    if (pw_exp == 0)
++        return;
++
++    /* Don't warn if the password is being changed. */
++    if (in_tkt_service && strcmp(in_tkt_service, "kadmin/changepw") == 0)
++        return;
++
++    /*
++     * If the expiry time came from a last_req field, assume the KDC wants us
++     * to warn.  Otherwise, warn only if the expiry time is less than a week
++     * from now.
++     */
++    ret = krb5_timeofday(context, &now);
++    if (ret != 0)
++        return;
++    if (!is_last_req &&
++        (ts_after(now, pw_exp) || ts_delta(pw_exp, now) > 7 * 24 * 60 * 60))
++        return;
++
++    if (!prompter)
++        return;
++
++    ret = krb5_timestamp_to_string(pw_exp, ts, sizeof(ts));
++    if (ret != 0)
++        return;
++
++    delta = ts_delta(pw_exp, now);
++    if (delta < 3600) {
++        snprintf(banner, sizeof(banner),
++                 _("Warning: Your password will expire in less than one hour "
++                   "on %s"), ts);
++    } else if (delta < 86400 * 2) {
++        snprintf(banner, sizeof(banner),
++                 _("Warning: Your password will expire in %d hour%s on %s"),
++                 delta / 3600, delta < 7200 ? "" : "s", ts);
++    } else {
++        snprintf(banner, sizeof(banner),
++                 _("Warning: Your password will expire in %d days on %s"),
++                 delta / 86400, ts);
++    }
++
++    /* PROMPTER_INVOCATION */
++    (*prompter)(context, data, 0, banner, 0, 0);
++}
++
+ static krb5_error_code
+ init_creds_step_reply(krb5_context context,
+                       krb5_init_creds_context ctx,
+@@ -1693,6 +1803,8 @@ init_creds_step_reply(krb5_context context,
+ 
+     /* success */
+     ctx->complete = TRUE;
++    warn_pw_expiry(context, ctx->opt, ctx->prompter, ctx->prompter_data,
++                   ctx->in_tkt_service, ctx->reply);
+ 
+ cleanup:
+     krb5_free_pa_data(context, kdc_padata);
+diff --git a/src/lib/krb5/krb/gic_pwd.c b/src/lib/krb5/krb/gic_pwd.c
+index 14ce23ba4..54e0a8ebe 100644
+--- a/src/lib/krb5/krb/gic_pwd.c
++++ b/src/lib/krb5/krb/gic_pwd.c
+@@ -133,113 +133,6 @@ krb5_init_creds_set_password(krb5_context context,
+     return 0;
+ }
+ 
+-/* Return the password expiry time indicated by enc_part2.  Set *is_last_req
+- * if the information came from a last_req value. */
+-static void
+-get_expiry_times(krb5_enc_kdc_rep_part *enc_part2, krb5_timestamp *pw_exp,
+-                 krb5_timestamp *acct_exp, krb5_boolean *is_last_req)
+-{
+-    krb5_last_req_entry **last_req;
+-    krb5_int32 lr_type;
+-
+-    *pw_exp = 0;
+-    *acct_exp = 0;
+-    *is_last_req = FALSE;
+-
+-    /* Look for last-req entries for password or account expiration. */
+-    if (enc_part2->last_req) {
+-        for (last_req = enc_part2->last_req; *last_req; last_req++) {
+-            lr_type = (*last_req)->lr_type;
+-            if (lr_type == KRB5_LRQ_ALL_PW_EXPTIME ||
+-                lr_type == KRB5_LRQ_ONE_PW_EXPTIME) {
+-                *is_last_req = TRUE;
+-                *pw_exp = (*last_req)->value;
+-            } else if (lr_type == KRB5_LRQ_ALL_ACCT_EXPTIME ||
+-                       lr_type == KRB5_LRQ_ONE_ACCT_EXPTIME) {
+-                *is_last_req = TRUE;
+-                *acct_exp = (*last_req)->value;
+-            }
+-        }
+-    }
+-
+-    /* If we didn't find any, use the ambiguous key_exp field. */
+-    if (*is_last_req == FALSE)
+-        *pw_exp = enc_part2->key_exp;
+-}
+-
+-/*
+- * Send an appropriate warning prompter if as_reply indicates that the password
+- * is going to expire soon.  If an expire callback was provided, use that
+- * instead.
+- */
+-static void
+-warn_pw_expiry(krb5_context context, krb5_get_init_creds_opt *options,
+-               krb5_prompter_fct prompter, void *data,
+-               const char *in_tkt_service, krb5_kdc_rep *as_reply)
+-{
+-    krb5_error_code ret;
+-    krb5_expire_callback_func expire_cb;
+-    void *expire_data;
+-    krb5_timestamp pw_exp, acct_exp, now;
+-    krb5_boolean is_last_req;
+-    krb5_deltat delta;
+-    char ts[256], banner[1024];
+-
+-    get_expiry_times(as_reply->enc_part2, &pw_exp, &acct_exp, &is_last_req);
+-
+-    k5_gic_opt_get_expire_cb(options, &expire_cb, &expire_data);
+-    if (expire_cb != NULL) {
+-        /* Invoke the expire callback and don't send prompter warnings. */
+-        (*expire_cb)(context, expire_data, pw_exp, acct_exp, is_last_req);
+-        return;
+-    }
+-
+-    /* Don't warn if no password expiry value was sent. */
+-    if (pw_exp == 0)
+-        return;
+-
+-    /* Don't warn if the password is being changed. */
+-    if (in_tkt_service && strcmp(in_tkt_service, "kadmin/changepw") == 0)
+-        return;
+-
+-    /*
+-     * If the expiry time came from a last_req field, assume the KDC wants us
+-     * to warn.  Otherwise, warn only if the expiry time is less than a week
+-     * from now.
+-     */
+-    ret = krb5_timeofday(context, &now);
+-    if (ret != 0)
+-        return;
+-    if (!is_last_req &&
+-        (ts_after(now, pw_exp) || ts_delta(pw_exp, now) > 7 * 24 * 60 * 60))
+-        return;
+-
+-    if (!prompter)
+-        return;
+-
+-    ret = krb5_timestamp_to_string(pw_exp, ts, sizeof(ts));
+-    if (ret != 0)
+-        return;
+-
+-    delta = ts_delta(pw_exp, now);
+-    if (delta < 3600) {
+-        snprintf(banner, sizeof(banner),
+-                 _("Warning: Your password will expire in less than one hour "
+-                   "on %s"), ts);
+-    } else if (delta < 86400*2) {
+-        snprintf(banner, sizeof(banner),
+-                 _("Warning: Your password will expire in %d hour%s on %s"),
+-                 delta / 3600, delta < 7200 ? "" : "s", ts);
+-    } else {
+-        snprintf(banner, sizeof(banner),
+-                 _("Warning: Your password will expire in %d days on %s"),
+-                 delta / 86400, ts);
+-    }
+-
+-    /* PROMPTER_INVOCATION */
+-    (*prompter)(context, data, 0, banner, 0, 0);
+-}
+-
+ /*
+  * Create a temporary options structure for getting a kadmin/changepw ticket,
+  * based on the appplication-specified options.  Propagate all application
+@@ -496,9 +389,6 @@ krb5_get_init_creds_password(krb5_context context,
+         goto cleanup;
+ 
+ cleanup:
+-    if (ret == 0)
+-        warn_pw_expiry(context, options, prompter, data, in_tkt_service,
+-                       as_reply);
+     free(chpw_opts);
+     zapfree(gakpw.storage.data, gakpw.storage.length);
+     memset(pw0array, 0, sizeof(pw0array));
+diff --git a/src/lib/krb5/krb/t_expire_warn.c b/src/lib/krb5/krb/t_expire_warn.c
+index 1e59acba1..dc8dc8fb3 100644
+--- a/src/lib/krb5/krb/t_expire_warn.c
++++ b/src/lib/krb5/krb/t_expire_warn.c
+@@ -28,6 +28,13 @@
+ 
+ static int exp_dummy, prompt_dummy;
+ 
++static void
++check(krb5_error_code code)
++{
++    if (code != 0)
++        abort();
++}
++
+ static krb5_error_code
+ prompter_cb(krb5_context ctx, void *data, const char *name,
+             const char *banner, int num_prompts, krb5_prompt prompts[])
+@@ -52,36 +59,48 @@ int
+ main(int argc, char **argv)
+ {
+     krb5_context ctx;
++    krb5_init_creds_context icctx;
+     krb5_get_init_creds_opt *opt;
+     char *user, *password, *service = NULL;
+-    krb5_boolean use_cb;
++    krb5_boolean use_cb, stepwise;
+     krb5_principal client;
+     krb5_creds creds;
+ 
+-    if (argc < 4) {
+-        fprintf(stderr, "Usage: %s username password {1|0} [service]\n",
++    if (argc < 5) {
++        fprintf(stderr, "Usage: %s username password {1|0} {1|0} [service]\n",
+                 argv[0]);
+         return 1;
+     }
+     user = argv[1];
+     password = argv[2];
+     use_cb = atoi(argv[3]);
+-    if (argc >= 5)
+-        service = argv[4];
++    stepwise = atoi(argv[4]);
++    if (argc >= 6)
++        service = argv[5];
+ 
+-    assert(krb5_init_context(&ctx) == 0);
+-    assert(krb5_get_init_creds_opt_alloc(ctx, &opt) == 0);
++    check(krb5_init_context(&ctx));
++    check(krb5_get_init_creds_opt_alloc(ctx, &opt));
+     if (use_cb) {
+-        assert(krb5_get_init_creds_opt_set_expire_callback(ctx, opt, expire_cb,
+-                                                           &exp_dummy) == 0);
++        check(krb5_get_init_creds_opt_set_expire_callback(ctx, opt, expire_cb,
++                                                          &exp_dummy));
++    }
++    check(krb5_parse_name(ctx, user, &client));
++    if (stepwise) {
++        check(krb5_init_creds_init(ctx, client, prompter_cb, &prompt_dummy, 0,
++                                   opt, &icctx));
++        krb5_init_creds_set_password(ctx, icctx, password);
++        if (service != NULL)
++            check(krb5_init_creds_set_service(ctx, icctx, service));
++        check(krb5_init_creds_get(ctx, icctx));
++        krb5_init_creds_free(ctx, icctx);
++    } else {
++        check(krb5_get_init_creds_password(ctx, &creds, client, password,
++                                           prompter_cb, &prompt_dummy, 0,
++                                           service, opt));
++        krb5_free_cred_contents(ctx, &creds);
+     }
+-    assert(krb5_parse_name(ctx, user, &client) == 0);
+-    assert(krb5_get_init_creds_password(ctx, &creds, client, password,
+-                                        prompter_cb, &prompt_dummy, 0, service,
+-                                        opt) == 0);
+     krb5_get_init_creds_opt_free(ctx, opt);
+     krb5_free_principal(ctx, client);
+-    krb5_free_cred_contents(ctx, &creds);
+     krb5_free_context(ctx);
+     return 0;
+ }
+diff --git a/src/lib/krb5/krb/t_expire_warn.py b/src/lib/krb5/krb/t_expire_warn.py
+index 781f2728a..e163cc7e4 100755
+--- a/src/lib/krb5/krb/t_expire_warn.py
++++ b/src/lib/krb5/krb/t_expire_warn.py
+@@ -34,23 +34,33 @@ realm.run([kadminl, 'addprinc', '-pw', 'pass', '-pwexpire', '12 hours',
+ realm.run([kadminl, 'addprinc', '-pw', 'pass', '-pwexpire', '3 days', 'days'])
+ 
+ # Check for expected prompter warnings when no expire callback is used.
+-output = realm.run(['./t_expire_warn', 'noexpire', 'pass', '0'])
++output = realm.run(['./t_expire_warn', 'noexpire', 'pass', '0', '0'])
+ if output:
+     fail('Unexpected output for noexpire')
+-realm.run(['./t_expire_warn', 'minutes', 'pass', '0'],
++realm.run(['./t_expire_warn', 'minutes', 'pass', '0', '0'],
+           expected_msg=' less than one hour on ')
+-realm.run(['./t_expire_warn', 'hours', 'pass', '0'], expected_msg=' hours on ')
+-realm.run(['./t_expire_warn', 'days', 'pass', '0'], expected_msg=' days on ')
++realm.run(['./t_expire_warn', 'hours', 'pass', '0', '0'],
++          expected_msg=' hours on ')
++realm.run(['./t_expire_warn', 'days', 'pass', '0', '0'],
++          expected_msg=' days on ')
++# Try one case with the stepwise interface.
++realm.run(['./t_expire_warn', 'days', 'pass', '0', '1'],
++          expected_msg=' days on ')
+ 
+ # Check for expected expire callback behavior.  These tests are
+ # carefully agnostic about whether the KDC supports last_req fields,
+ # and could be made more specific if last_req support is added.
+-output = realm.run(['./t_expire_warn', 'noexpire', 'pass', '1'])
++output = realm.run(['./t_expire_warn', 'noexpire', 'pass', '1', '0'])
+ if 'password_expiration = 0\n' not in output or \
+         'account_expiration = 0\n' not in output or \
+         'is_last_req = ' not in output:
+     fail('Expected callback output not seen for noexpire')
+-output = realm.run(['./t_expire_warn', 'days', 'pass', '1'])
++output = realm.run(['./t_expire_warn', 'days', 'pass', '1', '0'])
++if 'password_expiration = ' not in output or \
++        'password_expiration = 0\n' in output:
++    fail('Expected non-zero password expiration not seen for days')
++# Try one case with the stepwise interface.
++output = realm.run(['./t_expire_warn', 'days', 'pass', '1', '1'])
+ if 'password_expiration = ' not in output or \
+         'password_expiration = 0\n' in output:
+     fail('Expected non-zero password expiration not seen for days')
diff --git a/SOURCES/Eliminate-redundant-PKINIT-responder-invocation.patch b/SOURCES/Eliminate-redundant-PKINIT-responder-invocation.patch
new file mode 100644
index 0000000..7e70423
--- /dev/null
+++ b/SOURCES/Eliminate-redundant-PKINIT-responder-invocation.patch
@@ -0,0 +1,94 @@
+From fa5d09798a56960c34f28296726ed4525e6950d9 Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Mon, 23 Mar 2020 19:10:03 -0400
+Subject: [PATCH] Eliminate redundant PKINIT responder invocation
+
+In pkinit_client_prep_questions(), only act if the input padata type
+is KRB5_PADATA_PK_AS_REQ.  Otherwise we will ask questions again when
+the KDC issues a ticket.
+
+Commit 7621d2f9a87214327ca3b2594e34dc7cea84596b (ticket 8242)
+unintentionally changed the behavior of pkinit_load_fs_cert_and_key(),
+causing pkinit_client_prep_questions() to do nothing on its first
+call.  Restore the original behavior of returning 0 when prompting is
+deferred.
+
+Modify the existing "FILE identity, password on key (responder)"
+PKINIT test to check that the responder is only invoked once.
+
+ticket: 8885
+(cherry picked from commit f1286842ce7b9e507a4ce0a47f44ab361a98be63)
+(cherry picked from commit 4a05805eb39ba088c07f782fb52a6538ec3f2db6)
+---
+ src/plugins/preauth/pkinit/pkinit_clnt.c           |  5 +++++
+ src/plugins/preauth/pkinit/pkinit_crypto_openssl.c | 13 +++++++------
+ src/tests/t_pkinit.py                              | 11 +++++++----
+ 3 files changed, 19 insertions(+), 10 deletions(-)
+
+diff --git a/src/plugins/preauth/pkinit/pkinit_clnt.c b/src/plugins/preauth/pkinit/pkinit_clnt.c
+index 2f0431991..9b991ffe0 100644
+--- a/src/plugins/preauth/pkinit/pkinit_clnt.c
++++ b/src/plugins/preauth/pkinit/pkinit_clnt.c
+@@ -897,6 +897,11 @@ pkinit_client_prep_questions(krb5_context context,
+     k5_json_object jval = NULL;
+     k5_json_number jflag = NULL;
+ 
++    /* Don't ask questions for the informational padata items or when the
++     * ticket is issued. */
++    if (pa_data->pa_type != KRB5_PADATA_PK_AS_REQ)
++        return 0;
++
+     if (!reqctx->identity_initialized) {
+         pkinit_client_profile(context, plgctx, reqctx, cb, rock,
+                               &request->server->realm);
+diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+index dd718c2be..dbb054378 100644
+--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
++++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+@@ -4362,17 +4362,18 @@ pkinit_load_fs_cert_and_key(krb5_context context,
+ 
+     /* Load the certificate. */
+     retval = get_cert(certname, &x);
+-    if (retval != 0 || x == NULL) {
+-        retval = oerr(context, 0, _("Cannot read certificate file '%s'"),
++    if (retval) {
++        retval = oerr(context, retval, _("Cannot read certificate file '%s'"),
+                       certname);
+-        goto cleanup;
+     }
++    if (retval || x == NULL)
++        goto cleanup;
+     /* Load the key. */
+     retval = get_key(context, id_cryptoctx, keyname, fsname, &y, password);
+-    if (retval != 0 || y == NULL) {
+-        retval = oerr(context, 0, _("Cannot read key file '%s'"), fsname);
++    if (retval)
++        retval = oerr(context, retval, _("Cannot read key file '%s'"), fsname);
++    if (retval || y == NULL)
+         goto cleanup;
+-    }
+ 
+     id_cryptoctx->creds[cindex] = malloc(sizeof(struct _pkinit_cred_info));
+     if (id_cryptoctx->creds[cindex] == NULL) {
+diff --git a/src/tests/t_pkinit.py b/src/tests/t_pkinit.py
+index 69daf4987..ecd450e8a 100755
+--- a/src/tests/t_pkinit.py
++++ b/src/tests/t_pkinit.py
+@@ -248,10 +248,13 @@ realm.run(['./adata', realm.host_princ],
+ # supplied by the responder.
+ # Supply the response in raw form.
+ mark('FILE identity, password on key (responder)')
+-realm.run(['./responder', '-x', 'pkinit={"%s": 0}' % file_enc_identity,
+-           '-r', 'pkinit={"%s": "encrypted"}' % file_enc_identity,
+-           '-X', 'X509_user_identity=%s' % file_enc_identity,
+-           realm.user_princ])
++out = realm.run(['./responder', '-x', 'pkinit={"%s": 0}' % file_enc_identity,
++                 '-r', 'pkinit={"%s": "encrypted"}' % file_enc_identity,
++                 '-X', 'X509_user_identity=%s' % file_enc_identity,
++                 realm.user_princ])
++# Regression test for #8885 (password question asked twice).
++if out.count('OK: ') != 1:
++    fail('Wrong number of responder calls')
+ # Supply the response through the convenience API.
+ realm.run(['./responder', '-X', 'X509_user_identity=%s' % file_enc_identity,
+            '-p', '%s=%s' % (file_enc_identity, 'encrypted'), realm.user_princ])
diff --git a/SOURCES/Fix-Coverity-defects-in-soft-pkcs11-test-code.patch b/SOURCES/Fix-Coverity-defects-in-soft-pkcs11-test-code.patch
deleted file mode 100644
index 359335d..0000000
--- a/SOURCES/Fix-Coverity-defects-in-soft-pkcs11-test-code.patch
+++ /dev/null
@@ -1,207 +0,0 @@
-From 44b429df9ac4bb8ad84a090fee1bd70d83adcf23 Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Sat, 20 Jul 2019 00:51:52 -0400
-Subject: [PATCH] Fix Coverity defects in soft-pkcs11 test code
-
-Nothing in the code removes objects from soft_token.object.obs, so
-simplify add_st_object() not to search for an empty slot.  Avoid using
-random() by using a counter for session handles and just the array
-slot number for object handles.  Add a helper get_rcfilename() to
-facilitate checking the result of asprintf().  Properly initialize ap
-in sprintf_fill().  Close the file handle in read_conf_file().
-
-(cherry picked from commit b4831515b2f3b6fd7d7fd4bff4558c10c710891d)
-(cherry picked from commit 28db01445d2807d51b5045c0a04d5e49905de504)
----
- src/tests/softpkcs11/main.c | 102 +++++++++++++++++++-----------------
- 1 file changed, 53 insertions(+), 49 deletions(-)
-
-diff --git a/src/tests/softpkcs11/main.c b/src/tests/softpkcs11/main.c
-index 5255323d3..2d1448ca2 100644
---- a/src/tests/softpkcs11/main.c
-+++ b/src/tests/softpkcs11/main.c
-@@ -78,6 +78,7 @@ compat_rsa_get0_key(const RSA *rsa, const BIGNUM **n, const BIGNUM **e,
-                 (BL) = i2d_##T((S), &p);                \
-                 if ((BL) <= 0) {                        \
-                     free((B));                          \
-+                    (B) = NULL;                         \
-                     (R) = EINVAL;                       \
-                 }                                       \
-             }                                           \
-@@ -149,6 +150,7 @@ static struct soft_token {
-     } state[10];
- #define MAX_NUM_SESSION (sizeof(soft_token.state)/sizeof(soft_token.state[0]))
-     FILE *logfile;
-+    CK_SESSION_HANDLE next_session_handle;
- } soft_token;
- 
- static void
-@@ -179,6 +181,7 @@ snprintf_fill(char *str, int size, char fillchar, const char *fmt, ...)
- {
-     int len;
-     va_list ap;
-+    va_start(ap, fmt);
-     len = vsnprintf(str, size, fmt, ap);
-     va_end(ap);
-     if (len < 0 || len > size)
-@@ -344,7 +347,13 @@ static struct st_object *
- add_st_object(void)
- {
-     struct st_object *o, **objs;
--    int i;
-+
-+    objs = realloc(soft_token.object.objs,
-+                   (soft_token.object.num_objs + 1) *
-+                   sizeof(soft_token.object.objs[0]));
-+    if (objs == NULL)
-+        return NULL;
-+    soft_token.object.objs = objs;
- 
-     o = malloc(sizeof(*o));
-     if (o == NULL)
-@@ -352,26 +361,9 @@ add_st_object(void)
-     memset(o, 0, sizeof(*o));
-     o->attrs = NULL;
-     o->num_attributes = 0;
-+    o->object_handle = soft_token.object.num_objs;
- 
--    for (i = 0; i < soft_token.object.num_objs; i++) {
--        if (soft_token.object.objs == NULL) {
--            soft_token.object.objs[i] = o;
--            break;
--        }
--    }
--    if (i == soft_token.object.num_objs) {
--        objs = realloc(soft_token.object.objs,
--                       (soft_token.object.num_objs + 1) * sizeof(soft_token.object.objs[0]));
--        if (objs == NULL) {
--            free(o);
--            return NULL;
--        }
--        soft_token.object.objs = objs;
--        soft_token.object.objs[soft_token.object.num_objs++] = o;
--    }
--    soft_token.object.objs[i]->object_handle =
--        (random() & (~OBJECT_ID_MASK)) | i;
--
-+    soft_token.object.objs[soft_token.object.num_objs++] = o;
-     return o;
- }
- 
-@@ -797,6 +789,8 @@ read_conf_file(const char *fn)
- 
-         add_certificate(label, cert, key, id, anchor);
-     }
-+
-+    fclose(f);
- }
- 
- static CK_RV
-@@ -806,19 +800,47 @@ func_not_supported(void)
-     return CKR_FUNCTION_NOT_SUPPORTED;
- }
- 
-+static char *
-+get_rcfilename()
-+{
-+    struct passwd *pw;
-+    const char *home = NULL;
-+    char *fn;
-+
-+    if (getuid() == geteuid()) {
-+        fn = getenv("SOFTPKCS11RC");
-+        if (fn != NULL)
-+            return strdup(fn);
-+
-+        home = getenv("HOME");
-+    }
-+
-+    if (home == NULL) {
-+        pw = getpwuid(getuid());
-+        if (pw != NULL)
-+            home = pw->pw_dir;
-+    }
-+
-+    if (home == NULL)
-+        return strdup("/etc/soft-token.rc");
-+
-+    if (asprintf(&fn, "%s/.soft-token.rc", home) < 0)
-+        return NULL;
-+    return fn;
-+}
-+
- CK_RV
- C_Initialize(CK_VOID_PTR a)
- {
-     CK_C_INITIALIZE_ARGS_PTR args = a;
-     size_t i;
-+    char *fn;
- 
-     st_logf("Initialize\n");
- 
-     OpenSSL_add_all_algorithms();
-     ERR_load_crypto_strings();
- 
--    srandom(getpid() ^ time(NULL));
--
-     for (i = 0; i < MAX_NUM_SESSION; i++) {
-         soft_token.state[i].session_handle = CK_INVALID_HANDLE;
-         soft_token.state[i].find.attributes = NULL;
-@@ -850,31 +872,13 @@ C_Initialize(CK_VOID_PTR a)
-         st_logf("\tFlags\t%04x\n", (unsigned int)args->flags);
-     }
- 
--    {
--        char *fn = NULL, *home = NULL;
--
--        if (getuid() == geteuid()) {
--            fn = getenv("SOFTPKCS11RC");
--            if (fn)
--                fn = strdup(fn);
--            home = getenv("HOME");
--        }
--        if (fn == NULL && home == NULL) {
--            struct passwd *pw = getpwuid(getuid());
--            if(pw != NULL)
--                home = pw->pw_dir;
--        }
--        if (fn == NULL) {
--            if (home)
--                asprintf(&fn, "%s/.soft-token.rc", home);
--            else
--                fn = strdup("/etc/soft-token.rc");
--        }
--
--        read_conf_file(fn);
--        free(fn);
--    }
-+    soft_token.next_session_handle = 0;
- 
-+    fn = get_rcfilename();
-+    if (fn == NULL)
-+        return CKR_DEVICE_MEMORY;
-+    read_conf_file(fn);
-+    free(fn);
-     return CKR_OK;
- }
- 
-@@ -1082,8 +1086,7 @@ C_OpenSession(CK_SLOT_ID slotID,
- 
-     soft_token.open_sessions++;
- 
--    soft_token.state[i].session_handle =
--        (CK_SESSION_HANDLE)(random() & 0xfffff);
-+    soft_token.state[i].session_handle = soft_token.next_session_handle++;
-     *phSession = soft_token.state[i].session_handle;
- 
-     return CKR_OK;
-@@ -1152,7 +1155,8 @@ C_Login(CK_SESSION_HANDLE hSession,
-     VERIFY_SESSION_HANDLE(hSession, NULL);
- 
-     if (pPin != NULL_PTR) {
--        asprintf(&pin, "%.*s", (int)ulPinLen, pPin);
-+        if (asprintf(&pin, "%.*s", (int)ulPinLen, pPin) < 0)
-+            return CKR_DEVICE_MEMORY;
-         st_logf("type: %d password: %s\n", (int)userType, pin);
-     }
- 
diff --git a/SOURCES/Fix-KCM-client-time-offset-propagation.patch b/SOURCES/Fix-KCM-client-time-offset-propagation.patch
deleted file mode 100644
index eedc4c0..0000000
--- a/SOURCES/Fix-KCM-client-time-offset-propagation.patch
+++ /dev/null
@@ -1,33 +0,0 @@
-From 7e4576cc62a16fa77030c42dcc43c61cdfa5b4e6 Mon Sep 17 00:00:00 2001
-From: Robbie Harwood <rharwood@redhat.com>
-Date: Wed, 14 Aug 2019 13:52:27 -0400
-Subject: [PATCH] Fix KCM client time offset propagation
-
-An inverted status check in get_kdc_offset() would cause querying the
-offset time from the ccache to always fail (silently) on KCM.  Fix the
-status check so that KCM can properly handle desync.
-
-ticket: 8826 (new)
-tags: pullup
-target_version: 1.17-next
-target_verison: 1.16-next
-
-(cherry picked from commit 323abb6d1ebe5469d6c2167c29aa5d696d099b90)
-(cherry picked from commit 7e81b8077cf2cf186dadb96b064573f7c221fbf3)
----
- src/lib/krb5/ccache/cc_kcm.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/lib/krb5/ccache/cc_kcm.c b/src/lib/krb5/ccache/cc_kcm.c
-index 092ab7daf..fe93ca3dc 100644
---- a/src/lib/krb5/ccache/cc_kcm.c
-+++ b/src/lib/krb5/ccache/cc_kcm.c
-@@ -583,7 +583,7 @@ get_kdc_offset(krb5_context context, krb5_ccache cache)
-     if (cache_call(context, cache, &req, FALSE) != 0)
-         goto cleanup;
-     time_offset = k5_input_get_uint32_be(&req.reply);
--    if (!req.reply.status)
-+    if (req.reply.status)
-         goto cleanup;
-     context->os_context.time_offset = time_offset;
-     context->os_context.usec_offset = 0;
diff --git a/SOURCES/Fix-argument-order-on-strlcpy-in-enctype_name.patch b/SOURCES/Fix-argument-order-on-strlcpy-in-enctype_name.patch
deleted file mode 100644
index 99648bd..0000000
--- a/SOURCES/Fix-argument-order-on-strlcpy-in-enctype_name.patch
+++ /dev/null
@@ -1,22 +0,0 @@
-From 9a38af6aa136fdc92d5e0f1591c1647aec498f5a Mon Sep 17 00:00:00 2001
-From: Robbie Harwood <rharwood@redhat.com>
-Date: Tue, 17 Sep 2019 18:29:15 -0400
-Subject: [PATCH] Fix argument order on strlcpy() in enctype_name()
-
----
- src/kdc/kdc_util.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
-index 96c88edc1..6d1861a3b 100644
---- a/src/kdc/kdc_util.c
-+++ b/src/kdc/kdc_util.c
-@@ -1081,7 +1081,7 @@ enctype_name(krb5_enctype ktype, char *buf, size_t buflen)
-     else
-         return krb5_enctype_to_name(ktype, FALSE, buf, buflen);
- 
--    if (strlcpy(name, buf, buflen) >= buflen)
-+    if (strlcpy(buf, name, buflen) >= buflen)
-         return ENOMEM;
-     return 0;
- }
diff --git a/SOURCES/Fix-memory-leak-in-none-replay-cache-type.patch b/SOURCES/Fix-memory-leak-in-none-replay-cache-type.patch
deleted file mode 100644
index 166ef05..0000000
--- a/SOURCES/Fix-memory-leak-in-none-replay-cache-type.patch
+++ /dev/null
@@ -1,34 +0,0 @@
-From 74a3b8448949130d91417b261c3e1c316ffa8796 Mon Sep 17 00:00:00 2001
-From: Corene Casper <C.Casper@Dell.com>
-Date: Sat, 16 Feb 2019 00:49:26 -0500
-Subject: [PATCH] Fix memory leak in 'none' replay cache type
-
-Commit 0f06098e2ab419d02e89a1ca6bc9f2828f6bdb1e fixed part of a memory
-leak in the 'none' replay cache type by freeing the outer container,
-but we also need to free the mutex.
-
-[ghudson@mit.edu: wrote commit message]
-
-ticket: 8783
-tags: pullup
-target_version: 1.17-next
-target_version: 1.16-next
-
-(cherry picked from commit af2a3115cb8feb5174151b4b40223ae45aa9db17)
-(cherry picked from commit ff79351c4755d6df7c3245274708454311c25731)
----
- src/lib/krb5/rcache/rc_none.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/src/lib/krb5/rcache/rc_none.c b/src/lib/krb5/rcache/rc_none.c
-index e30aed09f..0b2274df7 100644
---- a/src/lib/krb5/rcache/rc_none.c
-+++ b/src/lib/krb5/rcache/rc_none.c
-@@ -50,6 +50,7 @@ krb5_rc_none_noargs(krb5_context ctx, krb5_rcache rc)
- static krb5_error_code KRB5_CALLCONV
- krb5_rc_none_close(krb5_context ctx, krb5_rcache rc)
- {
-+    k5_mutex_destroy(&rc->lock);
-     free (rc);
-     return 0;
- }
diff --git a/SOURCES/Fix-memory-leaks-in-soft-pkcs11-code.patch b/SOURCES/Fix-memory-leaks-in-soft-pkcs11-code.patch
deleted file mode 100644
index 01e41fc..0000000
--- a/SOURCES/Fix-memory-leaks-in-soft-pkcs11-code.patch
+++ /dev/null
@@ -1,123 +0,0 @@
-From 604f5dcbb018fca8ea27e00314ed615133b861e1 Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Mon, 5 Aug 2019 01:53:51 -0400
-Subject: [PATCH] Fix memory leaks in soft-pkcs11 code
-
-Fix leaks detected by asan in t_pkinit.py.  Add a helper to free a
-struct st_object and free objects in C_Finalize().  Duplicate the X509
-cert in add_certificate() instead of creating aliases so it can be
-properly freed.  Start the session handle counter at 1 so that
-C_Finalize() won't confuse the first session handle with
-CK_INVALID_HANDLE (defined to 0 in pkinit.h) and will properly clean
-the session object.
-
-(cherry picked from commit 15bcaf8bcb4af25ff89820ad3bf23ad5a324e863)
-(cherry picked from commit 5cc80472e7a8b0fb3002f229ffb104dccf8bd120)
----
- src/tests/softpkcs11/main.c | 44 +++++++++++++++++++++++++++++++++----
- 1 file changed, 40 insertions(+), 4 deletions(-)
-
-diff --git a/src/tests/softpkcs11/main.c b/src/tests/softpkcs11/main.c
-index 2d1448ca2..a4c3ae78e 100644
---- a/src/tests/softpkcs11/main.c
-+++ b/src/tests/softpkcs11/main.c
-@@ -109,7 +109,7 @@ struct st_object {
-         X509 *cert;
-         EVP_PKEY *public_key;
-         struct {
--            const char *file;
-+            char *file;
-             EVP_PKEY *key;
-             X509 *cert;
-         } private_key;
-@@ -343,6 +343,26 @@ print_attributes(const CK_ATTRIBUTE *attributes,
-     }
- }
- 
-+static void
-+free_st_object(struct st_object *o)
-+{
-+    int i;
-+
-+    for (i = 0; i < o->num_attributes; i++)
-+        free(o->attrs[i].attribute.pValue);
-+    free(o->attrs);
-+    if (o->type == STO_T_CERTIFICATE) {
-+        X509_free(o->u.cert);
-+    } else if (o->type == STO_T_PRIVATE_KEY) {
-+        free(o->u.private_key.file);
-+        EVP_PKEY_free(o->u.private_key.key);
-+        X509_free(o->u.private_key.cert);
-+    } else if (o->type == STO_T_PUBLIC_KEY) {
-+        EVP_PKEY_free(o->u.public_key);
-+    }
-+    free(o);
-+}
-+
- static struct st_object *
- add_st_object(void)
- {
-@@ -518,7 +538,11 @@ add_certificate(char *label,
-         goto out;
-     }
-     o->type = STO_T_CERTIFICATE;
--    o->u.cert = cert;
-+    o->u.cert = X509_dup(cert);
-+    if (o->u.cert == NULL) {
-+        ret = CKR_DEVICE_MEMORY;
-+        goto out;
-+    }
-     public_key = X509_get_pubkey(o->u.cert);
- 
-     switch (EVP_PKEY_base_id(public_key)) {
-@@ -602,7 +626,11 @@ add_certificate(char *label,
-         o->u.private_key.file = strdup(private_key_file);
-         o->u.private_key.key = NULL;
- 
--        o->u.private_key.cert = cert;
-+        o->u.private_key.cert = X509_dup(cert);
-+        if (o->u.private_key.cert == NULL) {
-+            ret = CKR_DEVICE_MEMORY;
-+            goto out;
-+        }
- 
-         c = CKO_PRIVATE_KEY;
-         add_object_attribute(o, 0, CKA_CLASS, &c, sizeof(c));
-@@ -676,6 +704,7 @@ add_certificate(char *label,
-     free(serial_data);
-     free(issuer_data);
-     free(subject_data);
-+    X509_free(cert);
- 
-     return ret;
- }
-@@ -872,7 +901,7 @@ C_Initialize(CK_VOID_PTR a)
-         st_logf("\tFlags\t%04x\n", (unsigned int)args->flags);
-     }
- 
--    soft_token.next_session_handle = 0;
-+    soft_token.next_session_handle = 1;
- 
-     fn = get_rcfilename();
-     if (fn == NULL)
-@@ -886,6 +915,7 @@ CK_RV
- C_Finalize(CK_VOID_PTR args)
- {
-     size_t i;
-+    int j;
- 
-     st_logf("Finalize\n");
- 
-@@ -897,6 +927,12 @@ C_Finalize(CK_VOID_PTR args)
-         }
-     }
- 
-+    for (j = 0; j < soft_token.object.num_objs; j++)
-+        free_st_object(soft_token.object.objs[j]);
-+    free(soft_token.object.objs);
-+    soft_token.object.objs = NULL;
-+    soft_token.object.num_objs = 0;
-+
-     return CKR_OK;
- }
- 
diff --git a/SOURCES/Fix-typo-in-in-in-the-ksu-man-page.patch b/SOURCES/Fix-typo-in-in-in-the-ksu-man-page.patch
new file mode 100644
index 0000000..0d2f2ef
--- /dev/null
+++ b/SOURCES/Fix-typo-in-in-in-the-ksu-man-page.patch
@@ -0,0 +1,38 @@
+From 117681ff995f7a271ded83ff4615e7945c72a942 Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Thu, 14 May 2020 15:01:18 -0400
+Subject: [PATCH] Fix typo ("in in") in the ksu man page
+
+(cherry picked from commit 1011841acdc1020f308ef4f569c6622f279d8c3f)
+(cherry picked from commit 8de669742ae4190542741f0dc61119a6a0dad666)
+---
+ doc/user/user_commands/ksu.rst | 2 +-
+ src/man/ksu.man                | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/doc/user/user_commands/ksu.rst b/doc/user/user_commands/ksu.rst
+index 8d6c7ef79..933738229 100644
+--- a/doc/user/user_commands/ksu.rst
++++ b/doc/user/user_commands/ksu.rst
+@@ -155,7 +155,7 @@ wrong password is typed in, ksu fails.
+ .. note::
+ 
+           During authentication, only the tickets that could be
+-          obtained without providing a password are cached in in the
++          obtained without providing a password are cached in the
+           source cache.
+ 
+ 
+diff --git a/src/man/ksu.man b/src/man/ksu.man
+index 81e34815d..8d4c6a359 100644
+--- a/src/man/ksu.man
++++ b/src/man/ksu.man
+@@ -176,7 +176,7 @@ wrong password is typed in, ksu fails.
+ .INDENT 0.0
+ .INDENT 3.5
+ During authentication, only the tickets that could be
+-obtained without providing a password are cached in in the
++obtained without providing a password are cached in the
+ source cache.
+ .UNINDENT
+ .UNINDENT
diff --git a/SOURCES/In-kpropd-debug-log-proper-ticket-enctype-names.patch b/SOURCES/In-kpropd-debug-log-proper-ticket-enctype-names.patch
deleted file mode 100644
index 8a20e3d..0000000
--- a/SOURCES/In-kpropd-debug-log-proper-ticket-enctype-names.patch
+++ /dev/null
@@ -1,28 +0,0 @@
-From 30f112f8dc1c5241da5ba301cb45a06bb5bb4c01 Mon Sep 17 00:00:00 2001
-From: Robbie Harwood <rharwood@redhat.com>
-Date: Tue, 15 Jan 2019 13:41:16 -0500
-Subject: [PATCH] In kpropd, debug-log proper ticket enctype names
-
-This change replaces the last call of krb5_enctype_to_string() in our
-sources with krb5_enctype_to_name(), ensuring that we log consistently
-to users using readily discoverable strings.
-
-(cherry picked from commit 30e12a2ecdf7e2a034a91626a03b5c9909e4c68d)
----
- src/kprop/kpropd.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/src/kprop/kpropd.c b/src/kprop/kpropd.c
-index 4cc035dc6..0c7bffa24 100644
---- a/src/kprop/kpropd.c
-+++ b/src/kprop/kpropd.c
-@@ -1279,7 +1279,8 @@ kerberos_authenticate(krb5_context context, int fd, krb5_principal *clientp,
-             exit(1);
-         }
- 
--        retval = krb5_enctype_to_string(*etype, etypebuf, sizeof(etypebuf));
-+        retval = krb5_enctype_to_name(*etype, FALSE, etypebuf,
-+                                      sizeof(etypebuf));
-         if (retval) {
-             com_err(progname, retval, _("while unparsing ticket etype"));
-             exit(1);
diff --git a/SOURCES/In-rd_req_dec-always-log-non-permitted-enctypes.patch b/SOURCES/In-rd_req_dec-always-log-non-permitted-enctypes.patch
deleted file mode 100644
index 6ca3da0..0000000
--- a/SOURCES/In-rd_req_dec-always-log-non-permitted-enctypes.patch
+++ /dev/null
@@ -1,54 +0,0 @@
-From 2b4521f3ba3dad064e3f64bfd56b88d5cb5d0955 Mon Sep 17 00:00:00 2001
-From: Robbie Harwood <rharwood@redhat.com>
-Date: Mon, 14 Jan 2019 17:14:42 -0500
-Subject: [PATCH] In rd_req_dec, always log non-permitted enctypes
-
-The buffer specified in negotiate_etype() is too small for use with
-the AES enctypes when used with krb5_enctype_to_string(), so switch to
-using krb5_enctype_to_name().
-
-(cherry picked from commit bf75ebf583a51bf00005a96d17924818d19377be)
----
- src/lib/krb5/krb/rd_req_dec.c  | 5 ++---
- src/tests/gssapi/t_enctypes.py | 5 +++--
- 2 files changed, 5 insertions(+), 5 deletions(-)
-
-diff --git a/src/lib/krb5/krb/rd_req_dec.c b/src/lib/krb5/krb/rd_req_dec.c
-index 4cd429a11..e75192fee 100644
---- a/src/lib/krb5/krb/rd_req_dec.c
-+++ b/src/lib/krb5/krb/rd_req_dec.c
-@@ -864,9 +864,8 @@ negotiate_etype(krb5_context context,
-         if (permitted == FALSE) {
-             char enctype_name[30];
- 
--            if (krb5_enctype_to_string(desired_etypes[i],
--                                       enctype_name,
--                                       sizeof(enctype_name)) == 0)
-+            if (krb5_enctype_to_name(desired_etypes[i], FALSE, enctype_name,
-+                                     sizeof(enctype_name)) == 0)
-                 k5_setmsg(context, KRB5_NOPERM_ETYPE,
-                           _("Encryption type %s not permitted"), enctype_name);
-             return KRB5_NOPERM_ETYPE;
-diff --git a/src/tests/gssapi/t_enctypes.py b/src/tests/gssapi/t_enctypes.py
-index ee43ff028..5d9f80e04 100755
---- a/src/tests/gssapi/t_enctypes.py
-+++ b/src/tests/gssapi/t_enctypes.py
-@@ -85,7 +85,8 @@ test('both aes128', 'aes128-cts', 'aes128-cts',
- # If only the acceptor constrains the permitted session enctypes to
- # aes128, subkey negotiation fails because the acceptor considers the
- # aes256 session key to be non-permitted.
--test_err('acc aes128', None, 'aes128-cts', 'Encryption type not permitted')
-+test_err('acc aes128', None, 'aes128-cts',
-+         'Encryption type aes256-cts-hmac-sha1-96 not permitted')
- 
- # If the initiator constrains the permitted session enctypes to des3,
- # no acceptor subkey will be generated because we can't upgrade to a
-@@ -128,7 +129,7 @@ test('upgrade init des3+rc4', 'des3 rc4', None,
- # is only for the sake of the kernel, since we could upgrade to an
- # aes128 subkey, but it's the current semantics.)
- test_err('upgrade acc aes128', None, 'aes128-cts',
--         'Encryption type ArcFour with HMAC/md5 not permitted')
-+         'Encryption type arcfour-hmac not permitted')
- 
- # If the acceptor permits rc4 but prefers aes128, it will negotiate an
- # upgrade to aes128.
diff --git a/SOURCES/Make-etype-names-in-KDC-logs-human-readable.patch b/SOURCES/Make-etype-names-in-KDC-logs-human-readable.patch
deleted file mode 100644
index 8b3413b..0000000
--- a/SOURCES/Make-etype-names-in-KDC-logs-human-readable.patch
+++ /dev/null
@@ -1,296 +0,0 @@
-From f815140182976e882445a38ee5a0a77f56da7c8a Mon Sep 17 00:00:00 2001
-From: Robbie Harwood <rharwood@redhat.com>
-Date: Tue, 8 Jan 2019 17:42:35 -0500
-Subject: [PATCH] Make etype names in KDC logs human-readable
-
-Introduce enctype_name() as a wrapper over krb5_enctype_to_name for
-converting between registered constants and names.  Adjust signatures
-and rewrite ktypes2str() and rep_etypes2str() to operate on dynamic
-buffers.
-
-ticket: 8772 (new)
-(cherry picked from commit a649279727490687d54becad91fde8cf7429d951)
----
- src/kdc/kdc_log.c  |  42 +++++++--------
- src/kdc/kdc_util.c | 131 +++++++++++++++++++++++----------------------
- src/kdc/kdc_util.h |   6 +--
- 3 files changed, 90 insertions(+), 89 deletions(-)
-
-diff --git a/src/kdc/kdc_log.c b/src/kdc/kdc_log.c
-index 4eec50373..b160ba21a 100644
---- a/src/kdc/kdc_log.c
-+++ b/src/kdc/kdc_log.c
-@@ -65,7 +65,7 @@ log_as_req(krb5_context context,
- {
-     const char *fromstring = 0;
-     char fromstringbuf[70];
--    char ktypestr[128];
-+    char *ktypestr = NULL;
-     const char *cname2 = cname ? cname : "<unknown client>";
-     const char *sname2 = sname ? sname : "<unknown server>";
- 
-@@ -74,26 +74,29 @@ log_as_req(krb5_context context,
-                            fromstringbuf, sizeof(fromstringbuf));
-     if (!fromstring)
-         fromstring = "<unknown>";
--    ktypes2str(ktypestr, sizeof(ktypestr),
--               request->nktypes, request->ktype);
-+
-+    ktypestr = ktypes2str(request->ktype, request->nktypes);
- 
-     if (status == NULL) {
-         /* success */
--        char rep_etypestr[128];
--        rep_etypes2str(rep_etypestr, sizeof(rep_etypestr), reply);
-+        char *rep_etypestr = rep_etypes2str(reply);
-         krb5_klog_syslog(LOG_INFO, _("AS_REQ (%s) %s: ISSUE: authtime %u, %s, "
-                                      "%s for %s"),
--                         ktypestr, fromstring, (unsigned int)authtime,
--                         rep_etypestr, cname2, sname2);
-+                         ktypestr ? ktypestr : "", fromstring,
-+                         (unsigned int)authtime,
-+                         rep_etypestr ? rep_etypestr : "", cname2, sname2);
-+        free(rep_etypestr);
-     } else {
-         /* fail */
-         krb5_klog_syslog(LOG_INFO, _("AS_REQ (%s) %s: %s: %s for %s%s%s"),
--                         ktypestr, fromstring, status,
--                         cname2, sname2, emsg ? ", " : "", emsg ? emsg : "");
-+                         ktypestr ? ktypestr : "", fromstring, status, cname2,
-+                         sname2, emsg ? ", " : "", emsg ? emsg : "");
-     }
-     krb5_db_audit_as_req(context, request,
-                          local_addr->address, remote_addr->address,
-                          client, server, authtime, errcode);
-+
-+    free(ktypestr);
- }
- 
- /*
-@@ -122,10 +125,9 @@ log_tgs_req(krb5_context ctx, const krb5_fulladdr *from,
-             unsigned int c_flags,
-             const char *status, krb5_error_code errcode, const char *emsg)
- {
--    char ktypestr[128];
-+    char *ktypestr = NULL, *rep_etypestr = NULL;
-     const char *fromstring = 0;
-     char fromstringbuf[70];
--    char rep_etypestr[128];
-     char *cname = NULL, *sname = NULL, *altcname = NULL;
-     char *logcname = NULL, *logsname = NULL, *logaltcname = NULL;
- 
-@@ -134,11 +136,6 @@ log_tgs_req(krb5_context ctx, const krb5_fulladdr *from,
-                            fromstringbuf, sizeof(fromstringbuf));
-     if (!fromstring)
-         fromstring = "<unknown>";
--    ktypes2str(ktypestr, sizeof(ktypestr), request->nktypes, request->ktype);
--    if (!errcode)
--        rep_etypes2str(rep_etypestr, sizeof(rep_etypestr), reply);
--    else
--        rep_etypestr[0] = 0;
- 
-     unparse_and_limit(ctx, cprinc, &cname);
-     logcname = (cname != NULL) ? cname : "<unknown client>";
-@@ -151,10 +148,14 @@ log_tgs_req(krb5_context ctx, const krb5_fulladdr *from,
-        name (useful), and doesn't log ktypestr (probably not
-        important).  */
-     if (errcode != KRB5KDC_ERR_SERVER_NOMATCH) {
-+        ktypestr = ktypes2str(request->ktype, request->nktypes);
-+        rep_etypestr = rep_etypes2str(reply);
-         krb5_klog_syslog(LOG_INFO, _("TGS_REQ (%s) %s: %s: authtime %u, %s%s "
-                                      "%s for %s%s%s"),
--                         ktypestr, fromstring, status, (unsigned int)authtime,
--                         rep_etypestr, !errcode ? "," : "", logcname, logsname,
-+                         ktypestr ? ktypestr : "", fromstring, status,
-+                         (unsigned int)authtime,
-+                         rep_etypestr ? rep_etypestr : "",
-+                         !errcode ? "," : "", logcname, logsname,
-                          errcode ? ", " : "", errcode ? emsg : "");
-         if (isflagset(c_flags, KRB5_KDB_FLAG_PROTOCOL_TRANSITION))
-             krb5_klog_syslog(LOG_INFO,
-@@ -171,9 +172,8 @@ log_tgs_req(krb5_context ctx, const krb5_fulladdr *from,
-                          fromstring, status, (unsigned int)authtime,
-                          logcname, logsname, logaltcname);
- 
--    /* OpenSolaris: audit_krb5kdc_tgs_req(...)  or
--       audit_krb5kdc_tgs_req_2ndtktmm(...) */
--
-+    free(rep_etypestr);
-+    free(ktypestr);
-     krb5_free_unparsed_name(ctx, cname);
-     krb5_free_unparsed_name(ctx, sname);
-     krb5_free_unparsed_name(ctx, altcname);
-diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
-index 0155c28c6..f5c581c82 100644
---- a/src/kdc/kdc_util.c
-+++ b/src/kdc/kdc_util.c
-@@ -1043,84 +1043,87 @@ void limit_string(char *name)
-     return;
- }
- 
--/*
-- * L10_2 = log10(2**x), rounded up; log10(2) ~= 0.301.
-- */
--#define L10_2(x) ((int)(((x * 301) + 999) / 1000))
--
--/*
-- * Max length of sprintf("%ld") for an int of type T; includes leading
-- * minus sign and terminating NUL.
-- */
--#define D_LEN(t) (L10_2(sizeof(t) * CHAR_BIT) + 2)
--
--void
--ktypes2str(char *s, size_t len, int nktypes, krb5_enctype *ktype)
-+/* Wrapper of krb5_enctype_to_name() to include the PKINIT types. */
-+static krb5_error_code
-+enctype_name(krb5_enctype ktype, char *buf, size_t buflen)
- {
--    int i;
--    char stmp[D_LEN(krb5_enctype) + 1];
--    char *p;
-+    char *name;
- 
--    if (nktypes < 0
--        || len < (sizeof(" etypes {...}") + D_LEN(int))) {
--        *s = '\0';
--        return;
--    }
-+    if (buflen == 0)
-+        return EINVAL;
-+    *buf = '\0'; /* ensure these are always valid C-strings */
- 
--    snprintf(s, len, "%d etypes {", nktypes);
--    for (i = 0; i < nktypes; i++) {
--        snprintf(stmp, sizeof(stmp), "%s%ld", i ? " " : "", (long)ktype[i]);
--        if (strlen(s) + strlen(stmp) + sizeof("}") > len)
--            break;
--        strlcat(s, stmp, len);
--    }
--    if (i < nktypes) {
--        /*
--         * We broke out of the loop. Try to truncate the list.
--         */
--        p = s + strlen(s);
--        while (p - s + sizeof("...}") > len) {
--            while (p > s && *p != ' ' && *p != '{')
--                *p-- = '\0';
--            if (p > s && *p == ' ') {
--                *p-- = '\0';
--                continue;
--            }
--        }
--        strlcat(s, "...", len);
--    }
--    strlcat(s, "}", len);
--    return;
-+    /* rfc4556 recommends that clients wishing to indicate support for these
-+     * pkinit algorithms include them in the etype field of the AS-REQ. */
-+    if (ktype == ENCTYPE_DSA_SHA1_CMS)
-+        name = "id-dsa-with-sha1-CmsOID";
-+    else if (ktype == ENCTYPE_MD5_RSA_CMS)
-+        name = "md5WithRSAEncryption-CmsOID";
-+    else if (ktype == ENCTYPE_SHA1_RSA_CMS)
-+        name = "sha-1WithRSAEncryption-CmsOID";
-+    else if (ktype == ENCTYPE_RC2_CBC_ENV)
-+        name = "rc2-cbc-EnvOID";
-+    else if (ktype == ENCTYPE_RSA_ENV)
-+        name = "rsaEncryption-EnvOID";
-+    else if (ktype == ENCTYPE_RSA_ES_OAEP_ENV)
-+        name = "id-RSAES-OAEP-EnvOID";
-+    else if (ktype == ENCTYPE_DES3_CBC_ENV)
-+        name = "des-ede3-cbc-EnvOID";
-+    else
-+        return krb5_enctype_to_name(ktype, FALSE, buf, buflen);
-+
-+    if (strlcpy(name, buf, buflen) >= buflen)
-+        return ENOMEM;
-+    return 0;
- }
- 
--void
--rep_etypes2str(char *s, size_t len, krb5_kdc_rep *rep)
-+char *
-+ktypes2str(krb5_enctype *ktype, int nktypes)
- {
--    char stmp[sizeof("ses=") + D_LEN(krb5_enctype)];
-+    struct k5buf buf;
-+    int i;
-+    char name[64];
- 
--    if (len < (3 * D_LEN(krb5_enctype)
--               + sizeof("etypes {rep= tkt= ses=}"))) {
--        *s = '\0';
--        return;
-+    if (nktypes < 0)
-+        return NULL;
-+
-+    k5_buf_init_dynamic(&buf);
-+    k5_buf_add_fmt(&buf, "%d etypes {", nktypes);
-+    for (i = 0; i < nktypes; i++) {
-+        enctype_name(ktype[i], name, sizeof(name));
-+        k5_buf_add_fmt(&buf, "%s%s(%ld)", i ? ", " : "", name, (long)ktype[i]);
-     }
-+    k5_buf_add(&buf, "}");
-+    return buf.data;
-+}
- 
--    snprintf(s, len, "etypes {rep=%ld", (long)rep->enc_part.enctype);
-+char *
-+rep_etypes2str(krb5_kdc_rep *rep)
-+{
-+    struct k5buf buf;
-+    char name[64];
-+    krb5_enctype etype;
-+
-+    k5_buf_init_dynamic(&buf);
-+    k5_buf_add(&buf, "etypes {rep=");
-+    enctype_name(rep->enc_part.enctype, name, sizeof(name));
-+    k5_buf_add_fmt(&buf, "%s(%ld)", name, (long)rep->enc_part.enctype);
- 
-     if (rep->ticket != NULL) {
--        snprintf(stmp, sizeof(stmp),
--                 " tkt=%ld", (long)rep->ticket->enc_part.enctype);
--        strlcat(s, stmp, len);
-+        etype = rep->ticket->enc_part.enctype;
-+        enctype_name(etype, name, sizeof(name));
-+        k5_buf_add_fmt(&buf, ", tkt=%s(%ld)", name, (long)etype);
-     }
- 
--    if (rep->ticket != NULL
--        && rep->ticket->enc_part2 != NULL
--        && rep->ticket->enc_part2->session != NULL) {
--        snprintf(stmp, sizeof(stmp), " ses=%ld",
--                 (long)rep->ticket->enc_part2->session->enctype);
--        strlcat(s, stmp, len);
-+    if (rep->ticket != NULL && rep->ticket->enc_part2 != NULL &&
-+        rep->ticket->enc_part2->session != NULL) {
-+        etype = rep->ticket->enc_part2->session->enctype;
-+        enctype_name(etype, name, sizeof(name));
-+        k5_buf_add_fmt(&buf, ", ses=%s(%ld)", name, (long)etype);
-     }
--    strlcat(s, "}", len);
--    return;
-+
-+    k5_buf_add(&buf, "}");
-+    return buf.data;
- }
- 
- static krb5_error_code
-diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h
-index 6ec645fc3..25077cbf5 100644
---- a/src/kdc/kdc_util.h
-+++ b/src/kdc/kdc_util.h
-@@ -110,11 +110,9 @@ select_session_keytype (kdc_realm_t *kdc_active_realm,
- 
- void limit_string (char *name);
- 
--void
--ktypes2str(char *s, size_t len, int nktypes, krb5_enctype *ktype);
-+char *ktypes2str(krb5_enctype *ktype, int nktypes);
- 
--void
--rep_etypes2str(char *s, size_t len, krb5_kdc_rep *rep);
-+char *rep_etypes2str(krb5_kdc_rep *rep);
- 
- /* authind.c */
- krb5_boolean
diff --git a/SOURCES/Mark-deprecated-enctypes-when-used.patch b/SOURCES/Mark-deprecated-enctypes-when-used.patch
deleted file mode 100644
index 4ded20a..0000000
--- a/SOURCES/Mark-deprecated-enctypes-when-used.patch
+++ /dev/null
@@ -1,250 +0,0 @@
-From 6306a2a8697c94f968a02d66204f7d357aa0e7f6 Mon Sep 17 00:00:00 2001
-From: Robbie Harwood <rharwood@redhat.com>
-Date: Thu, 10 Jan 2019 16:34:54 -0500
-Subject: [PATCH] Mark deprecated enctypes when used
-
-Preface ETYPE_DEPRECATED enctypes with "DEPRECATED:" in klist output,
-KDC logs, and kadmin interactions.  Also complain in krb5kdc when the
-stash file has a deprecated enctype or a deprecated enctype is
-requested with -k.
-
-ticket: 8773 (new)
-(cherry picked from commit 8d8e68283b599e680f9fe45eff8af397e827bd6c)
----
- src/clients/klist/klist.c      | 14 ++++++++++----
- src/kadmin/cli/kadmin.c        |  6 +++++-
- src/kdc/kdc_util.c             |  9 +++++++++
- src/kdc/main.c                 | 19 +++++++++++++++++++
- src/tests/gssapi/t_enctypes.py | 15 +++++++++------
- src/tests/t_keyrollover.py     |  8 +++++---
- src/tests/t_sesskeynego.py     |  4 ++--
- 7 files changed, 59 insertions(+), 16 deletions(-)
-
-diff --git a/src/clients/klist/klist.c b/src/clients/klist/klist.c
-index 70adb54e8..8c307151a 100644
---- a/src/clients/klist/klist.c
-+++ b/src/clients/klist/klist.c
-@@ -571,11 +571,17 @@ static char *
- etype_string(krb5_enctype enctype)
- {
-     static char buf[100];
--    krb5_error_code ret;
-+    char *bp = buf;
-+    size_t deplen, buflen = sizeof(buf);
- 
--    ret = krb5_enctype_to_name(enctype, FALSE, buf, sizeof(buf));
--    if (ret)
--        snprintf(buf, sizeof(buf), "etype %d", enctype);
-+    if (krb5int_c_deprecated_enctype(enctype)) {
-+        deplen = strlcpy(bp, "DEPRECATED:", buflen);
-+        buflen -= deplen;
-+        bp += deplen;
-+    }
-+
-+    if (krb5_enctype_to_name(enctype, FALSE, bp, buflen))
-+        snprintf(bp, buflen, "etype %d", enctype);
-     return buf;
- }
- 
-diff --git a/src/kadmin/cli/kadmin.c b/src/kadmin/cli/kadmin.c
-index ed581ee79..cc74921bf 100644
---- a/src/kadmin/cli/kadmin.c
-+++ b/src/kadmin/cli/kadmin.c
-@@ -1451,12 +1451,16 @@ kadmin_getprinc(int argc, char *argv[])
-         for (i = 0; i < dprinc.n_key_data; i++) {
-             krb5_key_data *key_data = &dprinc.key_data[i];
-             char enctype[BUFSIZ], salttype[BUFSIZ];
-+            char *deprecated = "";
- 
-             if (krb5_enctype_to_name(key_data->key_data_type[0], FALSE,
-                                      enctype, sizeof(enctype)))
-                 snprintf(enctype, sizeof(enctype), _("<Encryption type 0x%x>"),
-                          key_data->key_data_type[0]);
--            printf("Key: vno %d, %s", key_data->key_data_kvno, enctype);
-+            if (krb5int_c_deprecated_enctype(key_data->key_data_type[0]))
-+                deprecated = "DEPRECATED:";
-+            printf("Key: vno %d, %s%s", key_data->key_data_kvno, deprecated,
-+                   enctype);
-             if (key_data->key_data_ver > 1 &&
-                 key_data->key_data_type[1] != KRB5_KDB_SALTTYPE_NORMAL) {
-                 if (krb5_salttype_to_string(key_data->key_data_type[1],
-diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
-index f5c581c82..96c88edc1 100644
---- a/src/kdc/kdc_util.c
-+++ b/src/kdc/kdc_util.c
-@@ -1048,11 +1048,20 @@ static krb5_error_code
- enctype_name(krb5_enctype ktype, char *buf, size_t buflen)
- {
-     char *name;
-+    size_t len;
- 
-     if (buflen == 0)
-         return EINVAL;
-     *buf = '\0'; /* ensure these are always valid C-strings */
- 
-+    if (krb5int_c_deprecated_enctype(ktype)) {
-+        len = strlcpy(buf, "DEPRECATED:", buflen);
-+        if (len >= buflen)
-+            return ENOMEM;
-+        buflen -= len;
-+        buf += len;
-+    }
-+
-     /* rfc4556 recommends that clients wishing to indicate support for these
-      * pkinit algorithms include them in the etype field of the AS-REQ. */
-     if (ktype == ENCTYPE_DSA_SHA1_CMS)
-diff --git a/src/kdc/main.c b/src/kdc/main.c
-index 663fd6303..60092a0df 100644
---- a/src/kdc/main.c
-+++ b/src/kdc/main.c
-@@ -210,12 +210,23 @@ init_realm(kdc_realm_t * rdp, krb5_pointer aprof, char *realm,
-     char                *svalue = NULL;
-     const char          *hierarchy[4];
-     krb5_kvno       mkvno = IGNORE_VNO;
-+    char ename[32];
- 
-     memset(rdp, 0, sizeof(kdc_realm_t));
-     if (!realm) {
-         kret = EINVAL;
-         goto whoops;
-     }
-+
-+    if (def_enctype != ENCTYPE_UNKNOWN &&
-+        krb5int_c_deprecated_enctype(def_enctype)) {
-+        if (krb5_enctype_to_name(def_enctype, FALSE, ename, sizeof(ename)))
-+            ename[0] = '\0';
-+        fprintf(stderr,
-+                _("Requested master password enctype %s in %s is DEPRECATED!"),
-+                ename, realm);
-+    }
-+
-     hierarchy[0] = KRB5_CONF_REALMS;
-     hierarchy[1] = realm;
-     hierarchy[3] = NULL;
-@@ -370,6 +381,14 @@ init_realm(kdc_realm_t * rdp, krb5_pointer aprof, char *realm,
-         goto whoops;
-     }
- 
-+    if (krb5int_c_deprecated_enctype(rdp->realm_mkey.enctype)) {
-+        if (krb5_enctype_to_name(rdp->realm_mkey.enctype, FALSE, ename,
-+                                 sizeof(ename)))
-+            ename[0] = '\0';
-+        fprintf(stderr, _("Stash file %s uses DEPRECATED enctype %s!"),
-+                rdp->realm_stash, ename);
-+    }
-+
-     if ((kret = krb5_db_fetch_mkey_list(rdp->realm_context, rdp->realm_mprinc,
-                                         &rdp->realm_mkey))) {
-         kdc_err(rdp->realm_context, kret,
-diff --git a/src/tests/gssapi/t_enctypes.py b/src/tests/gssapi/t_enctypes.py
-index 5d9f80e04..ca3d32d21 100755
---- a/src/tests/gssapi/t_enctypes.py
-+++ b/src/tests/gssapi/t_enctypes.py
-@@ -9,8 +9,11 @@ from k5test import *
- aes256 = 'aes256-cts-hmac-sha1-96'
- aes128 = 'aes128-cts-hmac-sha1-96'
- des3 = 'des3-cbc-sha1'
-+d_des3 = 'DEPRECATED:des3-cbc-sha1'
- des3raw = 'des3-cbc-raw'
-+d_des3raw = 'DEPRECATED:des3-cbc-raw'
- rc4 = 'arcfour-hmac'
-+d_rc4 = 'DEPRECATED:arcfour-hmac'
- 
- # These tests make assumptions about the default enctype lists, so set
- # them explicitly rather than relying on the library defaults.
-@@ -92,7 +95,7 @@ test_err('acc aes128', None, 'aes128-cts',
- # no acceptor subkey will be generated because we can't upgrade to a
- # CFX enctype.
- test('init des3', 'des3', None,
--     tktenc=aes256, tktsession=des3,
-+     tktenc=aes256, tktsession=d_des3,
-      proto='rfc1964', isubkey=des3raw, asubkey=None)
- 
- # Force the ticket session key to be rc4, so we can test some subkey
-@@ -103,7 +106,7 @@ realm.run([kadminl, 'setstr', realm.host_princ, 'session_enctypes', 'rc4'])
- # [aes256 aes128 des3] and the acceptor should upgrade to an aes256
- # subkey.
- test('upgrade noargs', None, None,
--     tktenc=aes256, tktsession=rc4,
-+     tktenc=aes256, tktsession=d_rc4,
-      proto='cfx', isubkey=rc4, asubkey=aes256)
- 
- # If the initiator won't permit rc4 as a session key, it won't be able
-@@ -113,14 +116,14 @@ test_err('upgrade init aes', 'aes', None, 'no support for encryption type')
- # If the initiator permits rc4 but prefers aes128, it will send an
- # upgrade list of [aes128] and the acceptor will upgrade to aes128.
- test('upgrade init aes128+rc4', 'aes128-cts rc4', None,
--     tktenc=aes256, tktsession=rc4,
-+     tktenc=aes256, tktsession=d_rc4,
-      proto='cfx', isubkey=rc4, asubkey=aes128)
- 
- # If the initiator permits rc4 but prefers des3, it will send an
- # upgrade list of [des3], but the acceptor won't generate a subkey
- # because des3 isn't a CFX enctype.
- test('upgrade init des3+rc4', 'des3 rc4', None,
--     tktenc=aes256, tktsession=rc4,
-+     tktenc=aes256, tktsession=d_rc4,
-      proto='rfc1964', isubkey=rc4, asubkey=None)
- 
- # If the acceptor permits only aes128, subkey negotiation will fail
-@@ -134,14 +137,14 @@ test_err('upgrade acc aes128', None, 'aes128-cts',
- # If the acceptor permits rc4 but prefers aes128, it will negotiate an
- # upgrade to aes128.
- test('upgrade acc aes128 rc4', None, 'aes128-cts rc4',
--     tktenc=aes256, tktsession=rc4,
-+     tktenc=aes256, tktsession=d_rc4,
-      proto='cfx', isubkey=rc4, asubkey=aes128)
- 
- # In this test, the initiator and acceptor each prefer an AES enctype
- # to rc4, but they can't agree on which one, so no subkey is
- # generated.
- test('upgrade mismatch', 'aes128-cts rc4', 'aes256-cts rc4',
--     tktenc=aes256, tktsession=rc4,
-+     tktenc=aes256, tktsession=d_rc4,
-      proto='rfc1964', isubkey=rc4, asubkey=None)
- 
- success('gss_krb5_set_allowable_enctypes tests')
-diff --git a/src/tests/t_keyrollover.py b/src/tests/t_keyrollover.py
-index 7c8d828f0..4af6804f2 100755
---- a/src/tests/t_keyrollover.py
-+++ b/src/tests/t_keyrollover.py
-@@ -22,8 +22,9 @@ realm.run([kvno, princ1])
- realm.run([kadminl, 'purgekeys', realm.krbtgt_princ])
- # Make sure an old TGT fails after purging old TGS key.
- realm.run([kvno, princ2], expected_code=1)
--msg = 'krbtgt/%s@%s\n\tEtype (skey, tkt): des-cbc-crc, des-cbc-crc' % \
--    (realm.realm, realm.realm)
-+ddes = "DEPRECATED:des-cbc-crc"
-+msg = 'krbtgt/%s@%s\n\tEtype (skey, tkt): %s, %s' % \
-+    (realm.realm, realm.realm, ddes, ddes)
- realm.run([klist, '-e'], expected_msg=msg)
- 
- # Check that new key actually works.
-@@ -48,7 +49,8 @@ realm.run([kadminl, 'cpw', '-randkey', '-keepold', '-e', 'aes256-cts',
-            realm.krbtgt_princ])
- realm.run([kadminl, 'modprinc', '-kvno', '1', realm.krbtgt_princ])
- out = realm.run([kadminl, 'getprinc', realm.krbtgt_princ])
--if 'vno 1, aes256' not in out or 'vno 1, des3' not in out:
-+if 'vno 1, aes256-cts' not in out or \
-+   'vno 1, DEPRECATED:des3-cbc-sha1' not in out:
-     fail('keyrollover: setup for TGS enctype test failed')
- # Now present the DES3 ticket to the KDC and make sure it's rejected.
- realm.run([kvno, realm.host_princ], expected_code=1)
-diff --git a/src/tests/t_sesskeynego.py b/src/tests/t_sesskeynego.py
-index 448092387..da02f224a 100755
---- a/src/tests/t_sesskeynego.py
-+++ b/src/tests/t_sesskeynego.py
-@@ -62,11 +62,11 @@ test_kvno(realm, 'aes128-cts-hmac-sha1-96', 'aes256-cts-hmac-sha1-96')
- # 3b: Negotiate rc4-hmac session key when principal only has aes256 long-term.
- realm.run([kadminl, 'setstr', 'server', 'session_enctypes',
-            'rc4-hmac,aes128-cts,aes256-cts'])
--test_kvno(realm, 'arcfour-hmac', 'aes256-cts-hmac-sha1-96')
-+test_kvno(realm, 'DEPRECATED:arcfour-hmac', 'aes256-cts-hmac-sha1-96')
- 
- # 3c: Test des-cbc-crc default assumption.
- realm.run([kadminl, 'delstr', 'server', 'session_enctypes'])
--test_kvno(realm, 'des-cbc-crc', 'aes256-cts-hmac-sha1-96')
-+test_kvno(realm, 'DEPRECATED:des-cbc-crc', 'aes256-cts-hmac-sha1-96')
- realm.stop()
- 
- # Last go: test that we can disable the des-cbc-crc assumption
diff --git a/SOURCES/Omit-KDC-indicator-check-for-S4U2Self-requests.patch b/SOURCES/Omit-KDC-indicator-check-for-S4U2Self-requests.patch
new file mode 100644
index 0000000..c1d53b3
--- /dev/null
+++ b/SOURCES/Omit-KDC-indicator-check-for-S4U2Self-requests.patch
@@ -0,0 +1,49 @@
+From 61f3943f9fc237936ed9fd098edcd8dcc43b8da7 Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Wed, 6 May 2020 16:03:13 -0400
+Subject: [PATCH] Omit KDC indicator check for S4U2Self requests
+
+As there was no initial ticket exchange from the client for an
+S4U2Self request, the auth indicator check is inapplicable (and would
+always fail if any auth indicators are required).
+
+ticket: 8902 (new)
+(cherry picked from commit 183631fbf72351c2d5fc7d60b2d9fc4d09fe7465)
+(cherry picked from commit 442f1fa5b2e4034954a51048414cc0863b914379)
+---
+ src/kdc/do_tgs_req.c | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c
+index 241f34e2a..463a9c0dd 100644
+--- a/src/kdc/do_tgs_req.c
++++ b/src/kdc/do_tgs_req.c
+@@ -392,8 +392,8 @@ process_tgs_req(krb5_kdc_req *request, krb5_data *pkt,
+     }
+     authtime = subject_tkt->times.authtime;
+ 
+-    /* Extract auth indicators from the subject ticket, except for S4U2Self
+-     * requests (where the client didn't authenticate). */
++    /* Extract and check auth indicators from the subject ticket, except for
++     * S4U2Self requests (where the client didn't authenticate). */
+     if (s4u_x509_user == NULL) {
+         errcode = get_auth_indicators(kdc_context, subject_tkt, local_tgt,
+                                       &local_tgt_key, &auth_indicators);
+@@ -401,12 +401,12 @@ process_tgs_req(krb5_kdc_req *request, krb5_data *pkt,
+             status = "GET_AUTH_INDICATORS";
+             goto cleanup;
+         }
+-    }
+ 
+-    errcode = check_indicators(kdc_context, server, auth_indicators);
+-    if (errcode) {
+-        status = "HIGHER_AUTHENTICATION_REQUIRED";
+-        goto cleanup;
++        errcode = check_indicators(kdc_context, server, auth_indicators);
++        if (errcode) {
++            status = "HIGHER_AUTHENTICATION_REQUIRED";
++            goto cleanup;
++        }
+     }
+ 
+     if (is_referral)
diff --git a/SOURCES/Pass-gss_localname-through-SPNEGO.patch b/SOURCES/Pass-gss_localname-through-SPNEGO.patch
new file mode 100644
index 0000000..90804e0
--- /dev/null
+++ b/SOURCES/Pass-gss_localname-through-SPNEGO.patch
@@ -0,0 +1,59 @@
+From 64b1fdf0732b094e174b484fd9aac29f06e482bd Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Sun, 26 Apr 2020 19:55:54 -0400
+Subject: [PATCH] Pass gss_localname() through SPNEGO
+
+ticket: 8897 (new)
+(cherry picked from commit f7b8a6432bd289bdc528017be122305f95b8e285)
+(cherry picked from commit 646212314a580a8cdffdacda9cb3c8f806471b08)
+---
+ src/lib/gssapi/spnego/gssapiP_spnego.h | 8 ++++++++
+ src/lib/gssapi/spnego/spnego_mech.c    | 9 ++++++++-
+ 2 files changed, 16 insertions(+), 1 deletion(-)
+
+diff --git a/src/lib/gssapi/spnego/gssapiP_spnego.h b/src/lib/gssapi/spnego/gssapiP_spnego.h
+index a93763314..066ec736f 100644
+--- a/src/lib/gssapi/spnego/gssapiP_spnego.h
++++ b/src/lib/gssapi/spnego/gssapiP_spnego.h
+@@ -357,6 +357,14 @@ OM_uint32 KRB5_CALLCONV spnego_gss_wrap_size_limit
+ 	OM_uint32	*max_input_size
+ );
+ 
++OM_uint32 KRB5_CALLCONV spnego_gss_localname
++(
++	OM_uint32 *minor_status,
++	const gss_name_t pname,
++	const gss_const_OID mech_type,
++	gss_buffer_t localname
++);
++
+ OM_uint32 KRB5_CALLCONV spnego_gss_get_mic
+ (
+ 	OM_uint32 *minor_status,
+diff --git a/src/lib/gssapi/spnego/spnego_mech.c b/src/lib/gssapi/spnego/spnego_mech.c
+index ec0bae6a4..594fc5894 100644
+--- a/src/lib/gssapi/spnego/spnego_mech.c
++++ b/src/lib/gssapi/spnego/spnego_mech.c
+@@ -237,7 +237,7 @@ static struct gss_config spnego_mechanism =
+ 	spnego_gss_inquire_context,	/* gss_inquire_context */
+ 	NULL,				/* gss_internal_release_oid */
+ 	spnego_gss_wrap_size_limit,	/* gss_wrap_size_limit */
+-	NULL,				/* gssd_pname_to_uid */
++	spnego_gss_localname,
+ 	NULL,				/* gss_userok */
+ 	NULL,				/* gss_export_name */
+ 	spnego_gss_duplicate_name,	/* gss_duplicate_name */
+@@ -2371,6 +2371,13 @@ spnego_gss_wrap_size_limit(
+ 	return (ret);
+ }
+ 
++OM_uint32 KRB5_CALLCONV
++spnego_gss_localname(OM_uint32 *minor_status, const gss_name_t pname,
++		     const gss_const_OID mech_type, gss_buffer_t localname)
++{
++	return gss_localname(minor_status, pname, GSS_C_NO_OID, localname);
++}
++
+ OM_uint32 KRB5_CALLCONV
+ spnego_gss_get_mic(
+ 		OM_uint32 *minor_status,
diff --git a/SOURCES/Properly-size-ifdef-in-k5_cccol_lock.patch b/SOURCES/Properly-size-ifdef-in-k5_cccol_lock.patch
deleted file mode 100644
index b1e4563..0000000
--- a/SOURCES/Properly-size-ifdef-in-k5_cccol_lock.patch
+++ /dev/null
@@ -1,34 +0,0 @@
-From bad6d4390e6e23099cc2295d94e2553575687561 Mon Sep 17 00:00:00 2001
-From: Robbie Harwood <rharwood@redhat.com>
-Date: Thu, 14 Feb 2019 11:50:35 -0500
-Subject: [PATCH] Properly size #ifdef in k5_cccol_lock()
-
-The cleanup code only could get executed in the USE_CCAPI_V3 case, so
-move it inside that block.  Reported by Coverity.
-
-(cherry picked from commit 444a15f9cf82b9a6c1bca3f20307f82fee91c228)
-(cherry picked from commit e2a0e04fb3be9297a8c532dd35a7c1045cae88f4)
----
- src/lib/krb5/ccache/ccbase.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/lib/krb5/ccache/ccbase.c b/src/lib/krb5/ccache/ccbase.c
-index 8198f2b9b..2702bef69 100644
---- a/src/lib/krb5/ccache/ccbase.c
-+++ b/src/lib/krb5/ccache/ccbase.c
-@@ -511,7 +511,6 @@ krb5_cccol_lock(krb5_context context)
- #endif
- #ifdef USE_CCAPI_V3
-     ret = krb5_stdccv3_context_lock(context);
--#endif
-     if (ret) {
-         k5_cc_mutex_unlock(context, &krb5int_mcc_mutex);
-         k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex);
-@@ -519,6 +518,7 @@ krb5_cccol_lock(krb5_context context)
-         k5_cc_mutex_unlock(context, &cccol_lock);
-         return ret;
-     }
-+#endif
-     k5_mutex_unlock(&cc_typelist_lock);
-     return ret;
- }
diff --git a/SOURCES/Put-KDB-authdata-first.patch b/SOURCES/Put-KDB-authdata-first.patch
deleted file mode 100644
index 998fa0e..0000000
--- a/SOURCES/Put-KDB-authdata-first.patch
+++ /dev/null
@@ -1,45 +0,0 @@
-From 684821fc68fd27ddcc5f809a37819edd35365a9d Mon Sep 17 00:00:00 2001
-From: Isaac Boukris <iboukris@gmail.com>
-Date: Sat, 1 Feb 2020 16:13:30 +0100
-Subject: [PATCH] Put KDB authdata first
-
-Windows services, as well as some versions of Samba, may refuse
-tickets if the PAC is not in the first AD-IF-RELEVANT container.  In
-fetch_kdb_authdata(), change the merge order so that authdata from the
-KDB module appears first.
-
-[ghudson@mit.edu: added comment and clarified commit message]
-
-ticket: 8872 (new)
-tags: pullup
-target_version: 1.18
-target_version: 1.17-next
-
-(cherry picked from commit 331fa4bdd34263ea20667a0f51338cb84357fdaa)
-(cherry picked from commit 1678270de3fda699114122447b1f06b08fb4e53e)
----
- src/kdc/kdc_authdata.c | 9 ++++++---
- 1 file changed, 6 insertions(+), 3 deletions(-)
-
-diff --git a/src/kdc/kdc_authdata.c b/src/kdc/kdc_authdata.c
-index 1b067cb0b..616c3eadc 100644
---- a/src/kdc/kdc_authdata.c
-+++ b/src/kdc/kdc_authdata.c
-@@ -383,11 +383,14 @@ fetch_kdb_authdata(krb5_context context, unsigned int flags,
-     if (ret)
-         return (ret == KRB5_PLUGIN_OP_NOTSUPP) ? 0 : ret;
- 
--    /* Add the KDB authdata to the ticket, without copying or filtering. */
--    ret = merge_authdata(context, db_authdata,
--                         &enc_tkt_reply->authorization_data, FALSE, FALSE);
-+    /* Put the KDB authdata first in the ticket.  A successful merge places the
-+     * combined list in db_authdata and releases the old ticket authdata. */
-+    ret = merge_authdata(context, enc_tkt_reply->authorization_data,
-+                         &db_authdata, FALSE, FALSE);
-     if (ret)
-         krb5_free_authdata(context, db_authdata);
-+    else
-+        enc_tkt_reply->authorization_data = db_authdata;
-     return ret;
- }
- 
diff --git a/SOURCES/Refresh-manually-acquired-creds-from-client-keytab.patch b/SOURCES/Refresh-manually-acquired-creds-from-client-keytab.patch
new file mode 100644
index 0000000..c8c6cd8
--- /dev/null
+++ b/SOURCES/Refresh-manually-acquired-creds-from-client-keytab.patch
@@ -0,0 +1,79 @@
+From fdd97fe6c9f0a3a6ff8d2580ca9f3c46826449b7 Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Wed, 26 Feb 2020 18:27:17 -0500
+Subject: [PATCH] Refresh manually acquired creds from client keytab
+
+If a client keytab is present but credentials are acquired manually,
+the credentials would not be refreshed because no refresh_time config
+var is set in the cache.  Change kg_cred_time_to_refresh() to attempt
+a refresh from the client keytab on any credentials which will expire
+in the next 30 seconds.
+
+[ghudson@mit.edu: adjused code and added test case]
+
+ticket: 7976
+(cherry picked from commit 729896467e3c77904666019d6cbbda583ae49b95)
+(cherry picked from commit 685aada9eae420cb5156ca7b71c2c7614c0b6e2c)
+---
+ src/lib/gssapi/krb5/acquire_cred.c  | 14 +++++++++++---
+ src/tests/gssapi/t_client_keytab.py | 18 ++++++++++++++++++
+ 2 files changed, 29 insertions(+), 3 deletions(-)
+
+diff --git a/src/lib/gssapi/krb5/acquire_cred.c b/src/lib/gssapi/krb5/acquire_cred.c
+index acc1868f8..4062f4741 100644
+--- a/src/lib/gssapi/krb5/acquire_cred.c
++++ b/src/lib/gssapi/krb5/acquire_cred.c
+@@ -557,15 +557,23 @@ set_refresh_time(krb5_context context, krb5_ccache ccache,
+ krb5_boolean
+ kg_cred_time_to_refresh(krb5_context context, krb5_gss_cred_id_rec *cred)
+ {
+-    krb5_timestamp now;
++    krb5_timestamp now, soon;
+ 
+     if (krb5_timeofday(context, &now))
+         return FALSE;
++    soon = ts_incr(now, 30);
+     if (cred->refresh_time != 0 && !ts_after(cred->refresh_time, now)) {
+-        set_refresh_time(context, cred->ccache,
+-                         ts_incr(cred->refresh_time, 30));
++        set_refresh_time(context, cred->ccache, soon);
+         return TRUE;
+     }
++
++    /* If the creds will expire soon, try to refresh even if they weren't
++     * acquired with a client keytab. */
++    if (ts_after(soon, cred->expire)) {
++        set_refresh_time(context, cred->ccache, soon);
++        return TRUE;
++    }
++
+     return FALSE;
+ }
+ 
+diff --git a/src/tests/gssapi/t_client_keytab.py b/src/tests/gssapi/t_client_keytab.py
+index e474a27c7..7847b3ecd 100755
+--- a/src/tests/gssapi/t_client_keytab.py
++++ b/src/tests/gssapi/t_client_keytab.py
+@@ -124,4 +124,22 @@ realm.kinit(realm.user_princ, password('user'))
+ realm.run(['./t_ccselect', phost], env=bad_cktname,
+           expected_msg=realm.user_princ)
+ 
++mark('refresh of manually acquired creds')
++
++# Test 17: no name/ccache specified, manually acquired creds which
++# will expire soon.  Verify that creds are refreshed using the current
++# client name, with refresh_time set in the refreshed ccache.
++realm.kinit('bob', password('bob'), ['-l', '15s'])
++realm.run(['./t_ccselect', phost], expected_msg='bob')
++realm.run([klist, '-C'], expected_msg='refresh_time = ')
++
++# Test 18: no name/ccache specified, manually acquired creds with a
++# client principal not present in the client keytab.  A refresh is
++# attempted but fails, and an expired ticket error results.
++realm.kinit(realm.admin_princ, password('admin'), ['-l', '-1s'])
++msgs = ('Getting initial credentials for user/admin@KRBTEST.COM',
++        '/Matching credential not found')
++realm.run(['./t_ccselect', phost], expected_code=1,
++          expected_msg='Ticket expired', expected_trace=msgs)
++
+ success('Client keytab tests')
diff --git a/SOURCES/Use-backported-version-of-OpenSSL-3-KDF-interface.patch b/SOURCES/Use-backported-version-of-OpenSSL-3-KDF-interface.patch
deleted file mode 100644
index b8d3916..0000000
--- a/SOURCES/Use-backported-version-of-OpenSSL-3-KDF-interface.patch
+++ /dev/null
@@ -1,751 +0,0 @@
-From 5e147f7f2924edfd278940dea8b1d8ed09d6872c Mon Sep 17 00:00:00 2001
-From: Robbie Harwood <rharwood@redhat.com>
-Date: Fri, 15 Nov 2019 20:05:16 +0000
-Subject: [PATCH] Use backported version of OpenSSL-3 KDF interface
-
-(cherry picked from commit 0e20daf7ccfe50518c89735c3dae2fde08d92325)
----
- src/configure.in                              |   4 +
- src/lib/crypto/krb/derive.c                   | 356 +++++++++++++-----
- .../preauth/pkinit/pkinit_crypto_openssl.c    | 257 ++++++++-----
- 3 files changed, 428 insertions(+), 189 deletions(-)
-
-diff --git a/src/configure.in b/src/configure.in
-index 9f6b67b44..cf4b1139a 100644
---- a/src/configure.in
-+++ b/src/configure.in
-@@ -269,6 +269,10 @@ AC_SUBST(CRYPTO_IMPL)
- AC_SUBST(CRYPTO_IMPL_CFLAGS)
- AC_SUBST(CRYPTO_IMPL_LIBS)
- 
-+AC_CHECK_FUNCS(EVP_KDF_CTX_new_id EVP_KDF_ctrl EVP_KDF_derive,
-+               AC_DEFINE(OSSL_KDFS, 1, [Define if using OpenSSL KDFs]),
-+               AC_MSG_ERROR([backported OpenSSL KDFs not found]))
-+
- AC_ARG_WITH([prng-alg],
- AC_HELP_STRING([--with-prng-alg=ALG], [use specified PRNG algorithm. @<:@fortuna@:>@]),
- [PRNG_ALG=$withval
-diff --git a/src/lib/crypto/krb/derive.c b/src/lib/crypto/krb/derive.c
-index 6707a7308..915a173dd 100644
---- a/src/lib/crypto/krb/derive.c
-+++ b/src/lib/crypto/krb/derive.c
-@@ -27,6 +27,13 @@
- 
- #include "crypto_int.h"
- 
-+#ifdef OSSL_KDFS
-+#include <openssl/evp.h>
-+#include <openssl/kdf.h>
-+#else
-+#error "Refusing to build without OpenSSL KDFs!"
-+#endif
-+
- static krb5_key
- find_cached_dkey(struct derived_key *list, const krb5_data *constant)
- {
-@@ -77,55 +84,193 @@ cleanup:
-     return ENOMEM;
- }
- 
-+#ifdef OSSL_KDFS
- static krb5_error_code
--derive_random_rfc3961(const struct krb5_enc_provider *enc,
--                      krb5_key inkey, krb5_data *outrnd,
--                      const krb5_data *in_constant)
-+openssl_kbdkf_counter_hmac(const struct krb5_hash_provider *hash,
-+                           krb5_key inkey, krb5_data *outrnd,
-+                           const krb5_data *label, const krb5_data *context)
- {
--    size_t blocksize, keybytes, n;
-+    krb5_error_code ret = KRB5_CRYPTO_INTERNAL;
-+    EVP_KDF_CTX *ctx = NULL;
-+    const EVP_MD *digest;
-+
-+    if (!strcmp(hash->hash_name, "SHA1"))
-+        digest = EVP_sha1();
-+    else if (!strcmp(hash->hash_name, "SHA-256"))
-+        digest = EVP_sha256();
-+    else if (!strcmp(hash->hash_name, "SHA-384"))
-+        digest = EVP_sha384();
-+    else
-+        goto done;
-+
-+    ctx = EVP_KDF_CTX_new_id(EVP_KDF_KB);
-+    if (!ctx)
-+        goto done;
-+
-+    if (EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_MD, digest) != 1 ||
-+        EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KB_MAC_TYPE,
-+                     EVP_KDF_KB_MAC_TYPE_HMAC) != 1 ||
-+        EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KEY, inkey->keyblock.contents,
-+                     inkey->keyblock.length) != 1 ||
-+        (context->length > 0 &&
-+         EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KB_INFO, context->data,
-+                      context->length) != 1) ||
-+        (label->length > 0 &&
-+         EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SALT, label->data,
-+                      label->length) != 1) ||
-+        EVP_KDF_derive(ctx, (unsigned char *)outrnd->data,
-+                       outrnd->length) != 1)
-+        goto done;
-+
-+    ret = 0;
-+done:
-+    if (ret)
-+        zap(outrnd->data, outrnd->length);
-+    EVP_KDF_CTX_free(ctx);
-+    return ret;
-+}
-+
-+static krb5_error_code
-+openssl_kbkdf_feedback_cmac(const struct krb5_enc_provider *enc,
-+                            krb5_key inkey, krb5_data *outrnd,
-+                            const krb5_data *in_constant)
-+{
-+    krb5_error_code ret = KRB5_CRYPTO_INTERNAL;
-+    EVP_KDF_CTX *ctx = NULL;
-+    const EVP_CIPHER *cipher;
-+    static unsigned char zeroes[16];
-+
-+    memset(zeroes, 0, sizeof(zeroes));
-+
-+    if (enc->keylength == 16)
-+        cipher = EVP_camellia_128_cbc();
-+    else if (enc->keylength == 32)
-+        cipher = EVP_camellia_256_cbc();
-+    else
-+        goto done;
-+
-+    ctx = EVP_KDF_CTX_new_id(EVP_KDF_KB);
-+    if (!ctx)
-+        goto done;
-+
-+    if (EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KB_MODE,
-+                     EVP_KDF_KB_MODE_FEEDBACK) != 1 ||
-+        EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KB_MAC_TYPE,
-+                     EVP_KDF_KB_MAC_TYPE_CMAC) != 1 ||
-+        EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_CIPHER, cipher) != 1 ||
-+        EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KEY, inkey->keyblock.contents,
-+                     inkey->keyblock.length) != 1 ||
-+        EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SALT, in_constant->data,
-+                     in_constant->length) != 1 ||
-+        EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KB_SEED, zeroes,
-+                     sizeof(zeroes)) != 1 ||
-+        EVP_KDF_derive(ctx, (unsigned char *)outrnd->data,
-+                       outrnd->length) != 1)
-+        goto done;
-+
-+    ret = 0;
-+done:
-+    if (ret)
-+        zap(outrnd->data, outrnd->length);
-+    EVP_KDF_CTX_free(ctx);
-+    return ret;
-+}
-+
-+static krb5_error_code
-+openssl_krb5kdf(const struct krb5_enc_provider *enc, krb5_key inkey,
-+                krb5_data *outrnd, const krb5_data *in_constant)
-+{
-+    krb5_error_code ret = KRB5_CRYPTO_INTERNAL;
-+    EVP_KDF_CTX *ctx = NULL;
-+    const EVP_CIPHER *cipher;
-+
-+    if (inkey->keyblock.length != enc->keylength ||
-+        outrnd->length != enc->keybytes) {
-+        return KRB5_CRYPTO_INTERNAL;
-+    }
-+
-+    if (enc->encrypt == krb5int_aes_encrypt && enc->keylength == 16)
-+        cipher = EVP_aes_128_cbc();
-+    else if (enc->encrypt == krb5int_aes_encrypt && enc->keylength == 32)
-+        cipher = EVP_aes_256_cbc();
-+    else if (enc->keylength == 24)
-+        cipher = EVP_des_ede3_cbc();
-+    else
-+        goto done;
-+
-+    ctx = EVP_KDF_CTX_new_id(EVP_KDF_KRB5KDF);
-+    if (ctx == NULL)
-+        goto done;
-+
-+    if (EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_CIPHER, cipher) != 1 ||
-+        EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KEY, inkey->keyblock.contents,
-+                     inkey->keyblock.length) != 1 ||
-+        EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KRB5KDF_CONSTANT,
-+                     in_constant->data, in_constant->length) != 1 ||
-+        EVP_KDF_derive(ctx, (unsigned char *)outrnd->data,
-+                       outrnd->length) != 1)
-+        goto done;
-+
-+    ret = 0;
-+done:
-+    if (ret)
-+        zap(outrnd->data, outrnd->length);
-+    EVP_KDF_CTX_free(ctx);
-+    return ret;
-+}
-+
-+#else /* OSSL_KDFS */
-+
-+/*
-+ * NIST SP800-108 KDF in counter mode (section 5.1).
-+ * Parameters:
-+ *   - HMAC (with hash as the hash provider) is the PRF.
-+ *   - A block counter of four bytes is used.
-+ *   - Four bytes are used to encode the output length in the PRF input.
-+ *
-+ * There are no uses requiring more than a single PRF invocation.
-+ */
-+static krb5_error_code
-+builtin_sp800_108_counter_hmac(const struct krb5_hash_provider *hash,
-+                               krb5_key inkey, krb5_data *outrnd,
-+                               const krb5_data *label,
-+                               const krb5_data *context)
-+{
-+    krb5_crypto_iov iov[5];
-     krb5_error_code ret;
--    krb5_data block = empty_data();
-+    krb5_data prf;
-+    unsigned char ibuf[4], lbuf[4];
- 
--    blocksize = enc->block_size;
--    keybytes = enc->keybytes;
--
--    if (blocksize == 1)
--        return KRB5_BAD_ENCTYPE;
--    if (inkey->keyblock.length != enc->keylength || outrnd->length != keybytes)
-+    if (hash == NULL || outrnd->length > hash->hashsize)
-         return KRB5_CRYPTO_INTERNAL;
- 
-     /* Allocate encryption data buffer. */
--    ret = alloc_data(&block, blocksize);
-+    ret = alloc_data(&prf, hash->hashsize);
-     if (ret)
-         return ret;
- 
--    /* Initialize the input block. */
--    if (in_constant->length == blocksize) {
--        memcpy(block.data, in_constant->data, blocksize);
--    } else {
--        krb5int_nfold(in_constant->length * 8,
--                      (unsigned char *) in_constant->data,
--                      blocksize * 8, (unsigned char *) block.data);
--    }
-+    /* [i]2: four-byte big-endian binary string giving the block counter (1) */
-+    iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
-+    iov[0].data = make_data(ibuf, sizeof(ibuf));
-+    store_32_be(1, ibuf);
-+    /* Label */
-+    iov[1].flags = KRB5_CRYPTO_TYPE_DATA;
-+    iov[1].data = *label;
-+    /* 0x00: separator byte */
-+    iov[2].flags = KRB5_CRYPTO_TYPE_DATA;
-+    iov[2].data = make_data("", 1);
-+    /* Context */
-+    iov[3].flags = KRB5_CRYPTO_TYPE_DATA;
-+    iov[3].data = *context;
-+    /* [L]2: four-byte big-endian binary string giving the output length */
-+    iov[4].flags = KRB5_CRYPTO_TYPE_DATA;
-+    iov[4].data = make_data(lbuf, sizeof(lbuf));
-+    store_32_be(outrnd->length * 8, lbuf);
- 
--    /* Loop encrypting the blocks until enough key bytes are generated. */
--    n = 0;
--    while (n < keybytes) {
--        ret = encrypt_block(enc, inkey, &block);
--        if (ret)
--            goto cleanup;
--
--        if ((keybytes - n) <= blocksize) {
--            memcpy(outrnd->data + n, block.data, (keybytes - n));
--            break;
--        }
--
--        memcpy(outrnd->data + n, block.data, blocksize);
--        n += blocksize;
--    }
--
--cleanup:
--    zapfree(block.data, blocksize);
-+    ret = krb5int_hmac(hash, inkey, iov, 5, &prf);
-+    if (!ret)
-+        memcpy(outrnd->data, prf.data, outrnd->length);
-+    zapfree(prf.data, prf.length);
-     return ret;
- }
- 
-@@ -139,9 +284,9 @@ cleanup:
-  *   - Four bytes are used to encode the output length in the PRF input.
-  */
- static krb5_error_code
--derive_random_sp800_108_feedback_cmac(const struct krb5_enc_provider *enc,
--                                      krb5_key inkey, krb5_data *outrnd,
--                                      const krb5_data *in_constant)
-+builtin_sp800_108_feedback_cmac(const struct krb5_enc_provider *enc,
-+                                krb5_key inkey, krb5_data *outrnd,
-+                                const krb5_data *in_constant)
- {
-     size_t blocksize, keybytes, n;
-     krb5_crypto_iov iov[6];
-@@ -204,56 +349,94 @@ cleanup:
-     return ret;
- }
- 
--/*
-- * NIST SP800-108 KDF in counter mode (section 5.1).
-- * Parameters:
-- *   - HMAC (with hash as the hash provider) is the PRF.
-- *   - A block counter of four bytes is used.
-- *   - Four bytes are used to encode the output length in the PRF input.
-- *
-- * There are no uses requiring more than a single PRF invocation.
-- */
-+static krb5_error_code
-+builtin_derive_random_rfc3961(const struct krb5_enc_provider *enc,
-+                              krb5_key inkey, krb5_data *outrnd,
-+                              const krb5_data *in_constant)
-+{
-+    size_t blocksize, keybytes, n;
-+    krb5_error_code ret;
-+    krb5_data block = empty_data();
-+
-+    blocksize = enc->block_size;
-+    keybytes = enc->keybytes;
-+
-+    if (blocksize == 1)
-+        return KRB5_BAD_ENCTYPE;
-+    if (inkey->keyblock.length != enc->keylength || outrnd->length != keybytes)
-+        return KRB5_CRYPTO_INTERNAL;
-+
-+    /* Allocate encryption data buffer. */
-+    ret = alloc_data(&block, blocksize);
-+    if (ret)
-+        return ret;
-+
-+    /* Initialize the input block. */
-+    if (in_constant->length == blocksize) {
-+        memcpy(block.data, in_constant->data, blocksize);
-+    } else {
-+        krb5int_nfold(in_constant->length * 8,
-+                      (unsigned char *) in_constant->data,
-+                      blocksize * 8, (unsigned char *) block.data);
-+    }
-+
-+    /* Loop encrypting the blocks until enough key bytes are generated. */
-+    n = 0;
-+    while (n < keybytes) {
-+        ret = encrypt_block(enc, inkey, &block);
-+        if (ret)
-+            goto cleanup;
-+
-+        if ((keybytes - n) <= blocksize) {
-+            memcpy(outrnd->data + n, block.data, (keybytes - n));
-+            break;
-+        }
-+
-+        memcpy(outrnd->data + n, block.data, blocksize);
-+        n += blocksize;
-+    }
-+
-+cleanup:
-+    zapfree(block.data, blocksize);
-+    return ret;
-+}
-+#endif /* OSSL_KDFS */
-+
- krb5_error_code
- k5_sp800_108_counter_hmac(const struct krb5_hash_provider *hash,
-                           krb5_key inkey, krb5_data *outrnd,
-                           const krb5_data *label, const krb5_data *context)
- {
--    krb5_crypto_iov iov[5];
--    krb5_error_code ret;
--    krb5_data prf;
--    unsigned char ibuf[4], lbuf[4];
-+#ifdef OSSL_KDFS
-+    return openssl_kbdkf_counter_hmac(hash, inkey, outrnd, label, context);
-+#else
-+    return builtin_sp800_108_counter_hmac(hash, inkey, outrnd, label,
-+                                          context);
-+#endif
-+}
- 
--    if (hash == NULL || outrnd->length > hash->hashsize)
--        return KRB5_CRYPTO_INTERNAL;
-+static krb5_error_code
-+k5_sp800_108_feedback_cmac(const struct krb5_enc_provider *enc,
-+                           krb5_key inkey, krb5_data *outrnd,
-+                           const krb5_data *in_constant)
-+{
-+#ifdef OSSL_KDFS
-+    return openssl_kbkdf_feedback_cmac(enc, inkey, outrnd, in_constant);
-+#else
-+    return builtin_sp800_108_feedback_cmac(enc, inkey, outrnd, in_constant);
-+#endif
-+}
- 
--    /* Allocate encryption data buffer. */
--    ret = alloc_data(&prf, hash->hashsize);
--    if (ret)
--        return ret;
--
--    /* [i]2: four-byte big-endian binary string giving the block counter (1) */
--    iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
--    iov[0].data = make_data(ibuf, sizeof(ibuf));
--    store_32_be(1, ibuf);
--    /* Label */
--    iov[1].flags = KRB5_CRYPTO_TYPE_DATA;
--    iov[1].data = *label;
--    /* 0x00: separator byte */
--    iov[2].flags = KRB5_CRYPTO_TYPE_DATA;
--    iov[2].data = make_data("", 1);
--    /* Context */
--    iov[3].flags = KRB5_CRYPTO_TYPE_DATA;
--    iov[3].data = *context;
--    /* [L]2: four-byte big-endian binary string giving the output length */
--    iov[4].flags = KRB5_CRYPTO_TYPE_DATA;
--    iov[4].data = make_data(lbuf, sizeof(lbuf));
--    store_32_be(outrnd->length * 8, lbuf);
--
--    ret = krb5int_hmac(hash, inkey, iov, 5, &prf);
--    if (!ret)
--        memcpy(outrnd->data, prf.data, outrnd->length);
--    zapfree(prf.data, prf.length);
--    return ret;
-+static krb5_error_code
-+k5_derive_random_rfc3961(const struct krb5_enc_provider *enc,
-+                         krb5_key inkey, krb5_data *outrnd,
-+                         const krb5_data *in_constant)
-+{
-+#ifdef OSSL_KDFS
-+    return openssl_krb5kdf(enc, inkey, outrnd, in_constant);
-+#else
-+    return builtin_derive_random_rfc3961(enc, inkey, outrnd, in_constant);
-+#endif
- }
- 
- krb5_error_code
-@@ -266,10 +449,9 @@ krb5int_derive_random(const struct krb5_enc_provider *enc,
- 
-     switch (alg) {
-     case DERIVE_RFC3961:
--        return derive_random_rfc3961(enc, inkey, outrnd, in_constant);
-+        return k5_derive_random_rfc3961(enc, inkey, outrnd, in_constant);
-     case DERIVE_SP800_108_CMAC:
--        return derive_random_sp800_108_feedback_cmac(enc, inkey, outrnd,
--                                                     in_constant);
-+        return k5_sp800_108_feedback_cmac(enc, inkey, outrnd, in_constant);
-     case DERIVE_SP800_108_HMAC:
-         return k5_sp800_108_counter_hmac(hash, inkey, outrnd, in_constant,
-                                          &empty);
-diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
-index 5ff81d8cf..8d2c230c8 100644
---- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
-+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
-@@ -38,6 +38,13 @@
- #include <dirent.h>
- #include <arpa/inet.h>
- 
-+#ifdef OSSL_KDFS
-+#include <openssl/evp.h>
-+#include <openssl/kdf.h>
-+#else
-+#error "Refusing to build without OpenSSL KDFs!"
-+#endif
-+
- static krb5_error_code pkinit_init_pkinit_oids(pkinit_plg_crypto_context );
- static void pkinit_fini_pkinit_oids(pkinit_plg_crypto_context );
- 
-@@ -2460,11 +2467,51 @@ pkinit_alg_values(krb5_context context,
-     }
- } /* pkinit_alg_values() */
- 
-+#ifdef OSSL_KDFS
-+static krb5_error_code
-+openssl_sskdf(krb5_context context, size_t hash_bytes, krb5_data *key,
-+              krb5_data *info, char *out, size_t out_len)
-+{
-+    krb5_error_code ret = KRB5_CRYPTO_INTERNAL;
-+    EVP_KDF_CTX *ctx = NULL;
-+    const EVP_MD *digest;
- 
--/* pkinit_alg_agility_kdf() --
-- * This function generates a key using the KDF described in
-- * draft_ietf_krb_wg_pkinit_alg_agility-04.txt.  The algorithm is
-- * described as follows:
-+    /* RFC 8636 defines a SHA384 variant, but we don't use it. */
-+    if (hash_bytes == 20) {
-+        digest = EVP_sha1();
-+    } else if (hash_bytes == 32) {
-+        digest = EVP_sha256();
-+    } else if (hash_bytes == 64) {
-+        digest = EVP_sha512();
-+    } else {
-+        krb5_set_error_message(context, ret, "Bad hash type for SSKDF");
-+        goto done;
-+    }
-+
-+    ctx = EVP_KDF_CTX_new_id(EVP_KDF_SS);
-+    if (!ctx) {
-+        oerr(context, ret, _("Failed to instantiate SSKDF"));
-+        goto done;
-+    }
-+
-+    if (EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_MD, digest) != 1 ||
-+        EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KEY, key->data,
-+                     key->length) != 1 ||
-+        EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSKDF_INFO, info->data,
-+                     info->length) != 1 ||
-+        EVP_KDF_derive(ctx, (unsigned char *)out, out_len) != 1)
-+        goto done;
-+
-+    ret = 0;
-+done:
-+    EVP_KDF_CTX_free(ctx);
-+    return ret;
-+}
-+#else
-+/*
-+ * Generate a key using the KDF described in RFC 8636, also known as SSKDF
-+ * (single-step kdf).  Our caller precomputes `reps`, but otherwise the
-+ * algorithm is as follows:
-  *
-  *     1.  reps = keydatalen (K) / hash length (H)
-  *
-@@ -2478,95 +2525,16 @@ pkinit_alg_values(krb5_context context,
-  *
-  *     4.  Set key = Hash1 || Hash2 || ... so that length of key is K bytes.
-  */
--krb5_error_code
--pkinit_alg_agility_kdf(krb5_context context,
--                       krb5_data *secret,
--                       krb5_data *alg_oid,
--                       krb5_const_principal party_u_info,
--                       krb5_const_principal party_v_info,
--                       krb5_enctype enctype,
--                       krb5_data *as_req,
--                       krb5_data *pk_as_rep,
--                       krb5_keyblock *key_block)
-+static krb5_error_code
-+builtin_sskdf(krb5_context context, unsigned int reps, size_t hash_len,
-+              const EVP_MD *(*EVP_func)(void), krb5_data *secret,
-+              krb5_data *other_info, char *out, size_t out_len)
- {
-     krb5_error_code retval = 0;
- 
--    unsigned int reps = 0;
--    uint32_t counter = 1;       /* Does this type work on Windows? */
-+    uint32_t counter = 1;
-     size_t offset = 0;
--    size_t hash_len = 0;
--    size_t rand_len = 0;
--    size_t key_len = 0;
--    krb5_data random_data;
--    krb5_sp80056a_other_info other_info_fields;
--    krb5_pkinit_supp_pub_info supp_pub_info_fields;
--    krb5_data *other_info = NULL;
--    krb5_data *supp_pub_info = NULL;
--    krb5_algorithm_identifier alg_id;
-     EVP_MD_CTX *ctx = NULL;
--    const EVP_MD *(*EVP_func)(void);
--
--    /* initialize random_data here to make clean-up safe */
--    random_data.length = 0;
--    random_data.data = NULL;
--
--    /* allocate and initialize the key block */
--    key_block->magic = 0;
--    key_block->enctype = enctype;
--    if (0 != (retval = krb5_c_keylengths(context, enctype, &rand_len,
--                                         &key_len)))
--        goto cleanup;
--
--    random_data.length = rand_len;
--    key_block->length = key_len;
--
--    if (NULL == (key_block->contents = malloc(key_block->length))) {
--        retval = ENOMEM;
--        goto cleanup;
--    }
--
--    memset (key_block->contents, 0, key_block->length);
--
--    /* If this is anonymous pkinit, use the anonymous principle for party_u_info */
--    if (party_u_info && krb5_principal_compare_any_realm(context, party_u_info,
--                                                         krb5_anonymous_principal()))
--        party_u_info = (krb5_principal)krb5_anonymous_principal();
--
--    if (0 != (retval = pkinit_alg_values(context, alg_oid, &hash_len, &EVP_func)))
--        goto cleanup;
--
--    /* 1.  reps = keydatalen (K) / hash length (H) */
--    reps = key_block->length/hash_len;
--
--    /* ... and round up, if necessary */
--    if (key_block->length > (reps * hash_len))
--        reps++;
--
--    /* Allocate enough space in the random data buffer to hash directly into
--     * it, even if the last hash will make it bigger than the key length. */
--    if (NULL == (random_data.data = malloc(reps * hash_len))) {
--        retval = ENOMEM;
--        goto cleanup;
--    }
--
--    /* Encode the ASN.1 octet string for "SuppPubInfo" */
--    supp_pub_info_fields.enctype = enctype;
--    supp_pub_info_fields.as_req = *as_req;
--    supp_pub_info_fields.pk_as_rep = *pk_as_rep;
--    if (0 != ((retval = encode_krb5_pkinit_supp_pub_info(&supp_pub_info_fields,
--                                                         &supp_pub_info))))
--        goto cleanup;
--
--    /* Now encode the ASN.1 octet string for "OtherInfo" */
--    memset(&alg_id, 0, sizeof alg_id);
--    alg_id.algorithm = *alg_oid; /*alias*/
--
--    other_info_fields.algorithm_identifier = alg_id;
--    other_info_fields.party_u_info = (krb5_principal) party_u_info;
--    other_info_fields.party_v_info = (krb5_principal) party_v_info;
--    other_info_fields.supp_pub_info = *supp_pub_info;
--    if (0 != (retval = encode_krb5_sp80056a_other_info(&other_info_fields, &other_info)))
--        goto cleanup;
- 
-     /* 2.  Initialize a 32-bit, big-endian bit string counter as 1.
-      * 3.  For i = 1 to reps by 1, do the following:
-@@ -2600,8 +2568,9 @@ pkinit_alg_agility_kdf(krb5_context context,
-             goto cleanup;
-         }
- 
--        /* 4.  Set key = Hash1 || Hash2 || ... so that length of key is K bytes. */
--        if (!EVP_DigestFinal(ctx, (uint8_t *)random_data.data + offset, &s)) {
-+        /* 4.  Set key = Hash1 || Hash2 || ... so that length of key is K
-+         * bytes. */
-+        if (!EVP_DigestFinal(ctx, (unsigned char *)out + offset, &s)) {
-             krb5_set_error_message(context, KRB5_CRYPTO_INTERNAL,
-                                    "Call to OpenSSL EVP_DigestUpdate() returned an error.");
-             retval = KRB5_CRYPTO_INTERNAL;
-@@ -2613,26 +2582,110 @@ pkinit_alg_agility_kdf(krb5_context context,
-         EVP_MD_CTX_free(ctx);
-         ctx = NULL;
-     }
--
--    retval = krb5_c_random_to_key(context, enctype, &random_data,
--                                  key_block);
--
- cleanup:
-     EVP_MD_CTX_free(ctx);
-+    return retval;
-+} /* builtin_sskdf() */
-+#endif /* OSSL_KDFS */
- 
--    /* If this has been an error, free the allocated key_block, if any */
--    if (retval) {
--        krb5_free_keyblock_contents(context, key_block);
-+/* id-pkinit-kdf family, as specified by RFC 8636. */
-+krb5_error_code
-+pkinit_alg_agility_kdf(krb5_context context, krb5_data *secret,
-+                       krb5_data *alg_oid, krb5_const_principal party_u_info,
-+                       krb5_const_principal party_v_info,
-+                       krb5_enctype enctype, krb5_data *as_req,
-+                       krb5_data *pk_as_rep, krb5_keyblock *key_block)
-+{
-+    krb5_error_code retval;
-+    size_t hash_len = 0, rand_len = 0, key_len = 0;
-+    const EVP_MD *(*EVP_func)(void);
-+    krb5_sp80056a_other_info other_info_fields;
-+    krb5_pkinit_supp_pub_info supp_pub_info_fields;
-+    krb5_data *other_info = NULL, *supp_pub_info = NULL;
-+    krb5_data random_data = empty_data();
-+    krb5_algorithm_identifier alg_id;
-+    unsigned int reps;
-+
-+    /* Allocate and initialize the key block. */
-+    key_block->magic = 0;
-+    key_block->enctype = enctype;
-+
-+    /* Use separate variables to avoid alignment restriction problems. */
-+    retval = krb5_c_keylengths(context, enctype, &rand_len, &key_len);
-+    if (retval)
-+        goto cleanup;
-+    random_data.length = rand_len;
-+    key_block->length = key_len;
-+
-+    key_block->contents = k5calloc(key_block->length, 1, &retval);
-+    if (key_block->contents == NULL)
-+        goto cleanup;
-+
-+    /* If this is anonymous pkinit, use the anonymous principle for
-+     * party_u_info. */
-+    if (party_u_info &&
-+        krb5_principal_compare_any_realm(context, party_u_info,
-+                                         krb5_anonymous_principal())) {
-+        party_u_info = (krb5_principal)krb5_anonymous_principal();
-     }
- 
--    /* free other allocated resources, either way */
--    if (random_data.data)
--        free(random_data.data);
-+    retval = pkinit_alg_values(context, alg_oid, &hash_len, &EVP_func);
-+    if (retval)
-+        goto cleanup;
-+
-+    /* 1.  reps = keydatalen (K) / hash length (H) */
-+    reps = key_block->length / hash_len;
-+
-+    /* ... and round up, if necessary. */
-+    if (key_block->length > (reps * hash_len))
-+        reps++;
-+
-+    /* Allocate enough space in the random data buffer to hash directly into
-+     * it, even if the last hash will make it bigger than the key length. */
-+    random_data.data = k5alloc(reps * hash_len, &retval);
-+    if (random_data.data == NULL)
-+        goto cleanup;
-+
-+    /* Encode the ASN.1 octet string for "SuppPubInfo". */
-+    supp_pub_info_fields.enctype = enctype;
-+    supp_pub_info_fields.as_req = *as_req;
-+    supp_pub_info_fields.pk_as_rep = *pk_as_rep;
-+    retval = encode_krb5_pkinit_supp_pub_info(&supp_pub_info_fields,
-+                                              &supp_pub_info);
-+    if (retval)
-+        goto cleanup;
-+
-+    /* Now encode the ASN.1 octet string for "OtherInfo". */
-+    memset(&alg_id, 0, sizeof(alg_id));
-+    alg_id.algorithm = *alg_oid;
-+    other_info_fields.algorithm_identifier = alg_id;
-+    other_info_fields.party_u_info = (krb5_principal)party_u_info;
-+    other_info_fields.party_v_info = (krb5_principal)party_v_info;
-+    other_info_fields.supp_pub_info = *supp_pub_info;
-+    retval = encode_krb5_sp80056a_other_info(&other_info_fields, &other_info);
-+    if (retval)
-+        goto cleanup;
-+
-+#ifdef OSSL_KDFS
-+    retval = openssl_sskdf(context, hash_len, secret, other_info,
-+                           random_data.data, key_block->length);
-+#else
-+    retval = builtin_sskdf(context, reps, hash_len, EVP_func, secret,
-+                           other_info, random_data.data, key_block->length);
-+#endif
-+    if (retval)
-+        goto cleanup;
-+
-+    retval = krb5_c_random_to_key(context, enctype, &random_data, key_block);
-+cleanup:
-+    if (retval)
-+        krb5_free_keyblock_contents(context, key_block);
-+
-+    zapfree(random_data.data, random_data.length);
-     krb5_free_data(context, other_info);
-     krb5_free_data(context, supp_pub_info);
--
-     return retval;
--} /*pkinit_alg_agility_kdf() */
-+}
- 
- /* Call DH_compute_key() and ensure that we left-pad short results instead of
-  * leaving junk bytes at the end of the buffer. */
diff --git a/SOURCES/Use-imported-soft-pkcs11-for-tests.patch b/SOURCES/Use-imported-soft-pkcs11-for-tests.patch
deleted file mode 100644
index 0be2d97..0000000
--- a/SOURCES/Use-imported-soft-pkcs11-for-tests.patch
+++ /dev/null
@@ -1,472 +0,0 @@
-From 43f5837eecd5022c525efcfb3605af16958dc59a Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Thu, 20 Jun 2019 13:41:57 -0400
-Subject: [PATCH] Use imported soft-pkcs11 for tests
-
-Update the soft-pkcs11 code for OpenSSL 1.1, fix some warnings,
-integrate it into the build system, and use it for the PKINIT tests.
-
-(cherry picked from commit e5ef7b69765353ea62ad8712a229ed4e90a8fe17)
-(cherry picked from commit 47e66724b9d5cfef84965d99c83d29e4739932e3)
----
- src/configure.in                        |   1 +
- src/tests/Makefile.in                   |   2 +-
- src/tests/softpkcs11/Makefile.in        |  21 ++++
- src/tests/softpkcs11/deps               |   6 ++
- src/tests/softpkcs11/main.c             | 124 +++++++++++++++++-------
- src/tests/softpkcs11/softpkcs11.exports |  39 ++++++++
- src/tests/t_pkinit.py                   |  18 +---
- 7 files changed, 162 insertions(+), 49 deletions(-)
- create mode 100644 src/tests/softpkcs11/Makefile.in
- create mode 100644 src/tests/softpkcs11/deps
- create mode 100644 src/tests/softpkcs11/softpkcs11.exports
-
-diff --git a/src/configure.in b/src/configure.in
-index 93aec682e..9f6b67b44 100644
---- a/src/configure.in
-+++ b/src/configure.in
-@@ -1086,6 +1086,7 @@ int i = 1;
- fi
- if test "$k5_cv_openssl_version_okay" = yes && (test "$enable_pkinit" = yes || test "$enable_pkinit" = try); then
-   K5_GEN_MAKEFILE(plugins/preauth/pkinit)
-+  K5_GEN_MAKEFILE(tests/softpkcs11)
-   PKINIT=yes
-   AC_CHECK_LIB(crypto, CMS_get0_content, [AC_DEFINE([HAVE_OPENSSL_CMS], 1, [Define if OpenSSL supports cms.])])
- elif test "$k5_cv_openssl_version_okay" = no && test "$enable_pkinit" = yes; then
-diff --git a/src/tests/Makefile.in b/src/tests/Makefile.in
-index e27617ee2..ab958eb4c 100644
---- a/src/tests/Makefile.in
-+++ b/src/tests/Makefile.in
-@@ -1,7 +1,7 @@
- mydir=tests
- BUILDTOP=$(REL)..
- SUBDIRS = resolve asn.1 create hammer verify gssapi dejagnu shlib \
--	gss-threads misc threads
-+	gss-threads misc threads softpkcs11
- 
- RUN_DB_TEST = $(RUN_SETUP) KRB5_KDC_PROFILE=kdc.conf KRB5_CONFIG=krb5.conf \
- 	LC_ALL=C $(VALGRIND)
-diff --git a/src/tests/softpkcs11/Makefile.in b/src/tests/softpkcs11/Makefile.in
-new file mode 100644
-index 000000000..e89678154
---- /dev/null
-+++ b/src/tests/softpkcs11/Makefile.in
-@@ -0,0 +1,21 @@
-+mydir=tests$(S)softpkcs11
-+BUILDTOP=$(REL)..$(S)..
-+
-+LOCALINCLUDES = -I$(top_srcdir)/plugins/preauth/pkinit
-+
-+LIBBASE=softpkcs11
-+LIBMAJOR=0
-+LIBMINOR=0
-+
-+SHLIB_EXPLIBS=$(SUPPORT_LIB) -lcrypto
-+SHLIB_EXPDEPS=$(SUPPORT_DEPLIB)
-+
-+STLIBOBJS=main.o
-+
-+SRCS=$(srcdir)/main.c
-+
-+all-unix: all-libs
-+clean-unix:: clean-libs clean-libobjs
-+
-+@libnover_frag@
-+@libobj_frag@
-diff --git a/src/tests/softpkcs11/deps b/src/tests/softpkcs11/deps
-new file mode 100644
-index 000000000..1e82d9572
---- /dev/null
-+++ b/src/tests/softpkcs11/deps
-@@ -0,0 +1,6 @@
-+#
-+# Generated makefile dependencies follow.
-+#
-+main.so main.po $(OUTPRE)main.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
-+  $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \
-+  $(top_srcdir)/plugins/preauth/pkinit/pkcs11.h main.c
-diff --git a/src/tests/softpkcs11/main.c b/src/tests/softpkcs11/main.c
-index 2acec5169..5255323d3 100644
---- a/src/tests/softpkcs11/main.c
-+++ b/src/tests/softpkcs11/main.c
-@@ -1,3 +1,4 @@
-+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
- /*
-  * Copyright (c) 2004-2006, Stockholms universitet
-  * (Stockholm University, Stockholm Sweden)
-@@ -31,7 +32,57 @@
-  * POSSIBILITY OF SUCH DAMAGE.
-  */
- 
--#include "locl.h"
-+#include "k5-platform.h"
-+
-+#include <openssl/err.h>
-+#include <openssl/evp.h>
-+#include <openssl/pem.h>
-+#include <openssl/rand.h>
-+#include <openssl/x509.h>
-+
-+#include <ctype.h>
-+#include <pwd.h>
-+
-+#include <pkcs11.h>
-+
-+#if OPENSSL_VERSION_NUMBER < 0x10100000L
-+#define EVP_PKEY_get0_RSA(key) ((key)->pkey.rsa)
-+#define RSA_PKCS1_OpenSSL RSA_PKCS1_SSLeay
-+#define RSA_get0_key compat_rsa_get0_key
-+static void
-+compat_rsa_get0_key(const RSA *rsa, const BIGNUM **n, const BIGNUM **e,
-+                    const BIGNUM **d)
-+{
-+    if (n != NULL)
-+        *n = rsa->n;
-+    if (e != NULL)
-+        *e = rsa->e;
-+    if (d != NULL)
-+        *d = rsa->d;
-+}
-+#endif
-+
-+#define OPENSSL_ASN1_MALLOC_ENCODE(T, B, BL, S, R)      \
-+    {                                                   \
-+        unsigned char *p;                               \
-+        (BL) = i2d_##T((S), NULL);                      \
-+        if ((BL) <= 0) {                                \
-+            (R) = EINVAL;                               \
-+        } else {                                        \
-+            (B) = malloc((BL));                         \
-+            if ((B) == NULL) {                          \
-+                (R) = ENOMEM;                           \
-+            } else {                                    \
-+                p = (B);                                \
-+                (R) = 0;                                \
-+                (BL) = i2d_##T((S), &p);                \
-+                if ((BL) <= 0) {                        \
-+                    free((B));                          \
-+                    (R) = EINVAL;                       \
-+                }                                       \
-+            }                                           \
-+        }                                               \
-+    }
- 
- /* RCSID("$Id: main.c,v 1.24 2006/01/11 12:42:53 lha Exp $"); */
- 
-@@ -124,7 +175,7 @@ st_logf(const char *fmt, ...)
- }
- 
- static void
--snprintf_fill(char *str, size_t size, char fillchar, const char *fmt, ...)
-+snprintf_fill(char *str, int size, char fillchar, const char *fmt, ...)
- {
-     int len;
-     va_list ap;
-@@ -141,19 +192,19 @@ snprintf_fill(char *str, size_t size, char fillchar, const char *fmt, ...)
- #endif
- 
- #define VERIFY_SESSION_HANDLE(s, state)                 \
--{                                                       \
--    CK_RV ret;                                          \
--    ret = verify_session_handle(s, state);              \
--    if (ret != CKR_OK) {                                \
--        /* return CKR_OK */;                            \
--    }                                                   \
--}
-+    {                                                   \
-+        CK_RV vshret;                                   \
-+        vshret = verify_session_handle(s, state);       \
-+        if (vshret != CKR_OK) {                         \
-+            /* return CKR_OK */;                        \
-+        }                                               \
-+    }
- 
- static CK_RV
- verify_session_handle(CK_SESSION_HANDLE hSession,
-                       struct session_state **state)
- {
--    int i;
-+    size_t i;
- 
-     for (i = 0; i < MAX_NUM_SESSION; i++){
-         if (soft_token.state[i].session_handle == hSession)
-@@ -361,16 +412,20 @@ add_pubkey_info(struct st_object *o, CK_KEY_TYPE key_type, EVP_PKEY *key)
-         CK_ULONG modulus_bits = 0;
-         CK_BYTE *exponent = NULL;
-         size_t exponent_len = 0;
-+        RSA *rsa;
-+        const BIGNUM *n, *e;
- 
--        modulus_bits = BN_num_bits(key->pkey.rsa->n);
-+        rsa = EVP_PKEY_get0_RSA(key);
-+        RSA_get0_key(rsa, &n, &e, NULL);
-+        modulus_bits = BN_num_bits(n);
- 
--        modulus_len = BN_num_bytes(key->pkey.rsa->n);
-+        modulus_len = BN_num_bytes(n);
-         modulus = malloc(modulus_len);
--        BN_bn2bin(key->pkey.rsa->n, modulus);
-+        BN_bn2bin(n, modulus);
- 
--        exponent_len = BN_num_bytes(key->pkey.rsa->e);
-+        exponent_len = BN_num_bytes(e);
-         exponent = malloc(exponent_len);
--        BN_bn2bin(key->pkey.rsa->e, exponent);
-+        BN_bn2bin(e, exponent);
- 
-         add_object_attribute(o, 0, CKA_MODULUS, modulus, modulus_len);
-         add_object_attribute(o, 0, CKA_MODULUS_BITS,
-@@ -378,7 +433,7 @@ add_pubkey_info(struct st_object *o, CK_KEY_TYPE key_type, EVP_PKEY *key)
-         add_object_attribute(o, 0, CKA_PUBLIC_EXPONENT,
-                              exponent, exponent_len);
- 
--        RSA_set_method(key->pkey.rsa, RSA_PKCS1_SSLeay());
-+        RSA_set_method(rsa, RSA_PKCS1_OpenSSL());
- 
-         free(modulus);
-         free(exponent);
-@@ -474,7 +529,7 @@ add_certificate(char *label,
-     o->u.cert = cert;
-     public_key = X509_get_pubkey(o->u.cert);
- 
--    switch (EVP_PKEY_type(public_key->type)) {
-+    switch (EVP_PKEY_base_id(public_key)) {
-     case EVP_PKEY_RSA:
-         key_type = CKK_RSA;
-         break;
-@@ -604,8 +659,8 @@ add_certificate(char *label,
-             /* XXX verify keytype */
- 
-             if (key_type == CKK_RSA)
--                RSA_set_method(o->u.private_key.key->pkey.rsa,
--                               RSA_PKCS1_SSLeay());
-+                RSA_set_method(EVP_PKEY_get0_RSA(o->u.private_key.key),
-+                               RSA_PKCS1_OpenSSL());
- 
-             if (X509_check_private_key(cert, o->u.private_key.key) != 1) {
-                 EVP_PKEY_free(o->u.private_key.key);
-@@ -755,8 +810,9 @@ CK_RV
- C_Initialize(CK_VOID_PTR a)
- {
-     CK_C_INITIALIZE_ARGS_PTR args = a;
-+    size_t i;
-+
-     st_logf("Initialize\n");
--    int i;
- 
-     OpenSSL_add_all_algorithms();
-     ERR_load_crypto_strings();
-@@ -825,7 +881,7 @@ C_Initialize(CK_VOID_PTR a)
- CK_RV
- C_Finalize(CK_VOID_PTR args)
- {
--    int i;
-+    size_t i;
- 
-     st_logf("Finalize\n");
- 
-@@ -1008,7 +1064,7 @@ C_OpenSession(CK_SLOT_ID slotID,
-               CK_NOTIFY Notify,
-               CK_SESSION_HANDLE_PTR phSession)
- {
--    int i;
-+    size_t i;
- 
-     st_logf("OpenSession: slot: %d\n", (int)slotID);
- 
-@@ -1050,7 +1106,7 @@ C_CloseSession(CK_SESSION_HANDLE hSession)
- CK_RV
- C_CloseAllSessions(CK_SLOT_ID slotID)
- {
--    int i;
-+    size_t i;
- 
-     st_logf("CloseAllSessions\n");
- 
-@@ -1127,7 +1183,8 @@ C_Login(CK_SESSION_HANDLE hSession,
-         }
- 
-         /* XXX check keytype */
--        RSA_set_method(o->u.private_key.key->pkey.rsa, RSA_PKCS1_SSLeay());
-+        RSA_set_method(EVP_PKEY_get0_RSA(o->u.private_key.key),
-+                       RSA_PKCS1_OpenSSL());
- 
-         if (X509_check_private_key(o->u.private_key.cert, o->u.private_key.key) != 1) {
-             EVP_PKEY_free(o->u.private_key.key);
-@@ -1226,7 +1283,6 @@ C_FindObjectsInit(CK_SESSION_HANDLE hSession,
-     }
-     if (ulCount) {
-         CK_ULONG i;
--        size_t len;
- 
-         print_attributes(pTemplate, ulCount);
- 
-@@ -1415,7 +1471,7 @@ C_Encrypt(CK_SESSION_HANDLE hSession,
-         return CKR_ARGUMENTS_BAD;
-     }
- 
--    rsa = o->u.public_key->pkey.rsa;
-+    rsa = EVP_PKEY_get0_RSA(o->u.public_key);
- 
-     if (rsa == NULL)
-         return CKR_ARGUMENTS_BAD;
-@@ -1445,7 +1501,7 @@ C_Encrypt(CK_SESSION_HANDLE hSession,
-         goto out;
-     }
- 
--    if (buffer_len + padding_len < ulDataLen) {
-+    if ((CK_ULONG)buffer_len + padding_len < ulDataLen) {
-         ret = CKR_ARGUMENTS_BAD;
-         goto out;
-     }
-@@ -1566,7 +1622,7 @@ C_Decrypt(CK_SESSION_HANDLE hSession,
-         return CKR_ARGUMENTS_BAD;
-     }
- 
--    rsa = o->u.private_key.key->pkey.rsa;
-+    rsa = EVP_PKEY_get0_RSA(o->u.private_key.key);
- 
-     if (rsa == NULL)
-         return CKR_ARGUMENTS_BAD;
-@@ -1596,7 +1652,7 @@ C_Decrypt(CK_SESSION_HANDLE hSession,
-         goto out;
-     }
- 
--    if (buffer_len + padding_len < ulEncryptedDataLen) {
-+    if ((CK_ULONG)buffer_len + padding_len < ulEncryptedDataLen) {
-         ret = CKR_ARGUMENTS_BAD;
-         goto out;
-     }
-@@ -1725,7 +1781,7 @@ C_Sign(CK_SESSION_HANDLE hSession,
-         return CKR_ARGUMENTS_BAD;
-     }
- 
--    rsa = o->u.private_key.key->pkey.rsa;
-+    rsa = EVP_PKEY_get0_RSA(o->u.private_key.key);
- 
-     if (rsa == NULL)
-         return CKR_ARGUMENTS_BAD;
-@@ -1754,7 +1810,7 @@ C_Sign(CK_SESSION_HANDLE hSession,
-         goto out;
-     }
- 
--    if (buffer_len < ulDataLen + padding_len) {
-+    if ((CK_ULONG)buffer_len < ulDataLen + padding_len) {
-         ret = CKR_ARGUMENTS_BAD;
-         goto out;
-     }
-@@ -1872,7 +1928,7 @@ C_Verify(CK_SESSION_HANDLE hSession,
-         return CKR_ARGUMENTS_BAD;
-     }
- 
--    rsa = o->u.public_key->pkey.rsa;
-+    rsa = EVP_PKEY_get0_RSA(o->u.public_key);
- 
-     if (rsa == NULL)
-         return CKR_ARGUMENTS_BAD;
-@@ -1900,7 +1956,7 @@ C_Verify(CK_SESSION_HANDLE hSession,
-         goto out;
-     }
- 
--    if (buffer_len < ulDataLen) {
-+    if ((CK_ULONG)buffer_len < ulDataLen) {
-         ret = CKR_ARGUMENTS_BAD;
-         goto out;
-     }
-@@ -1926,7 +1982,7 @@ C_Verify(CK_SESSION_HANDLE hSession,
-     if (len > buffer_len)
-         abort();
- 
--    if (len != ulSignatureLen) {
-+    if ((CK_ULONG)len != ulSignatureLen) {
-         ret = CKR_GENERAL_ERROR;
-         goto out;
-     }
-diff --git a/src/tests/softpkcs11/softpkcs11.exports b/src/tests/softpkcs11/softpkcs11.exports
-new file mode 100644
-index 000000000..aa7284511
---- /dev/null
-+++ b/src/tests/softpkcs11/softpkcs11.exports
-@@ -0,0 +1,39 @@
-+C_CloseAllSessions
-+C_CloseSession
-+C_Decrypt
-+C_DecryptFinal
-+C_DecryptInit
-+C_DecryptUpdate
-+C_DigestInit
-+C_Encrypt
-+C_EncryptFinal
-+C_EncryptInit
-+C_EncryptUpdate
-+C_Finalize
-+C_FindObjects
-+C_FindObjectsFinal
-+C_FindObjectsInit
-+C_GenerateRandom
-+C_GetAttributeValue
-+C_GetFunctionList
-+C_GetInfo
-+C_GetMechanismInfo
-+C_GetMechanismList
-+C_GetObjectSize
-+C_GetSessionInfo
-+C_GetSlotInfo
-+C_GetSlotList
-+C_GetTokenInfo
-+C_Initialize
-+C_InitToken
-+C_Login
-+C_Logout
-+C_OpenSession
-+C_Sign
-+C_SignFinal
-+C_SignInit
-+C_SignUpdate
-+C_Verify
-+C_VerifyFinal
-+C_VerifyInit
-+C_VerifyUpdate
-diff --git a/src/tests/t_pkinit.py b/src/tests/t_pkinit.py
-index 1dadb1b96..384bf1426 100755
---- a/src/tests/t_pkinit.py
-+++ b/src/tests/t_pkinit.py
-@@ -4,14 +4,7 @@ from k5test import *
- if not os.path.exists(os.path.join(plugins, 'preauth', 'pkinit.so')):
-     skip_rest('PKINIT tests', 'PKINIT module not built')
- 
--# Check if soft-pkcs11.so is available.
--try:
--    import ctypes
--    lib = ctypes.LibraryLoader(ctypes.CDLL).LoadLibrary('soft-pkcs11.so')
--    del lib
--    have_soft_pkcs11 = True
--except:
--    have_soft_pkcs11 = False
-+soft_pkcs11 = os.path.join(buildtop, 'tests', 'softpkcs11', 'softpkcs11.so')
- 
- # Construct a krb5.conf fragment configuring pkinit.
- certs = os.path.join(srctop, 'tests', 'dejagnu', 'pkinit-certs')
-@@ -69,9 +62,9 @@ p12_upn2_identity = 'PKCS12:%s' % user_upn2_p12
- p12_upn3_identity = 'PKCS12:%s' % user_upn3_p12
- p12_generic_identity = 'PKCS12:%s' % generic_p12
- p12_enc_identity = 'PKCS12:%s' % user_enc_p12
--p11_identity = 'PKCS11:soft-pkcs11.so'
--p11_token_identity = ('PKCS11:module_name=soft-pkcs11.so:'
--                      'slotid=1:token=SoftToken (token)')
-+p11_identity = 'PKCS11:' + soft_pkcs11
-+p11_token_identity = ('PKCS11:module_name=' + soft_pkcs11 +
-+                      ':slotid=1:token=SoftToken (token)')
- 
- # Start a realm with the test kdb module for the following UPN SAN tests.
- realm = K5Realm(krb5_conf=pkinit_krb5_conf, kdc_conf=alias_kdc_conf,
-@@ -398,9 +391,6 @@ realm.klist(realm.user_princ)
- realm.kinit(realm.user_princ, flags=['-X', 'X509_user_identity=,'],
-             expected_code=1, expected_msg='Preauthentication failed while')
- 
--if not have_soft_pkcs11:
--    skip_rest('PKINIT PKCS11 tests', 'soft-pkcs11.so not found')
--
- softpkcs11rc = os.path.join(os.getcwd(), 'testdir', 'soft-pkcs11.rc')
- realm.env['SOFTPKCS11RC'] = softpkcs11rc
- 
diff --git a/SOURCES/downstream-Adjust-build-configuration.patch b/SOURCES/downstream-Adjust-build-configuration.patch
new file mode 100644
index 0000000..68a7878
--- /dev/null
+++ b/SOURCES/downstream-Adjust-build-configuration.patch
@@ -0,0 +1,73 @@
+From 4e42a6786a06b7223f27536267492a463a700c76 Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Tue, 23 Aug 2016 16:45:26 -0400
+Subject: [PATCH] [downstream] Adjust build configuration
+
+Build binaries in this package as RELRO PIEs, libraries as partial RELRO,
+and install shared libraries with the execute bit set on them.  Prune out
+the -L/usr/lib* and PIE flags where they might leak out and affect
+apps which just want to link with the libraries. FIXME: needs to check and
+not just assume that the compiler supports using these flags.
+
+Last-updated: krb5-1.15-beta1
+(cherry picked from commit 92508996ed4c69fa6f5cf855fdf10f34cfa07ec9)
+---
+ src/build-tools/krb5-config.in | 7 +++++++
+ src/config/pre.in              | 2 +-
+ src/config/shlib.conf          | 5 +++--
+ 3 files changed, 11 insertions(+), 3 deletions(-)
+
+diff --git a/src/build-tools/krb5-config.in b/src/build-tools/krb5-config.in
+index c17cb5eb5..1891dea99 100755
+--- a/src/build-tools/krb5-config.in
++++ b/src/build-tools/krb5-config.in
+@@ -226,6 +226,13 @@ if test -n "$do_libs"; then
+ 	    -e 's#\$(PTHREAD_CFLAGS)#'"$PTHREAD_CFLAGS"'#' \
+ 	    -e 's#\$(CFLAGS)##'`
+ 
++    if test `dirname $libdir` = /usr ; then
++        lib_flags=`echo $lib_flags | sed -e "s#-L$libdir##" -e "s#$RPATH_FLAG$libdir##"`
++    fi
++    lib_flags=`echo $lib_flags | sed -e "s#-fPIE##g" -e "s#-pie##g"`
++    lib_flags=`echo $lib_flags | sed -e "s#-Wl,-z,relro##g"`
++    lib_flags=`echo $lib_flags | sed -e "s#-Wl,-z,now##g"`
++
+     if test $library = 'kdb'; then
+ 	lib_flags="$lib_flags -lkdb5 $KDB5_DB_LIB"
+ 	library=krb5
+diff --git a/src/config/pre.in b/src/config/pre.in
+index 917357df9..a8540ae2a 100644
+--- a/src/config/pre.in
++++ b/src/config/pre.in
+@@ -185,7 +185,7 @@ INSTALL_PROGRAM=@INSTALL_PROGRAM@ $(INSTALL_STRIP)
+ INSTALL_SCRIPT=@INSTALL_PROGRAM@
+ INSTALL_DATA=@INSTALL_DATA@
+ INSTALL_SHLIB=@INSTALL_SHLIB@
+-INSTALL_SETUID=$(INSTALL) $(INSTALL_STRIP) -m 4755 -o root
++INSTALL_SETUID=$(INSTALL) $(INSTALL_STRIP) -m 4755
+ ## This is needed because autoconf will sometimes define @exec_prefix@ to be
+ ## ${prefix}.
+ prefix=@prefix@
+diff --git a/src/config/shlib.conf b/src/config/shlib.conf
+index 3e4af6c02..2b20c3fda 100644
+--- a/src/config/shlib.conf
++++ b/src/config/shlib.conf
+@@ -423,7 +423,7 @@ mips-*-netbsd*)
+ 	# Linux ld doesn't default to stuffing the SONAME field...
+ 	# Use objdump -x to examine the fields of the library
+ 	# UNDEF_CHECK is suppressed by --enable-asan
+-	LDCOMBINE='$(CC) -shared -fPIC -Wl,-h,$(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT) $(UNDEF_CHECK)'
++	LDCOMBINE='$(CC) -shared -fPIC -Wl,-h,$(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT) $(UNDEF_CHECK)  -Wl,-z,relro -Wl,--warn-shared-textrel'
+ 	UNDEF_CHECK='-Wl,--no-undefined'
+ 	# $(EXPORT_CHECK) runs export-check.pl when in maintainer mode.
+ 	LDCOMBINE_TAIL='-Wl,--version-script binutils.versions $(EXPORT_CHECK)'
+@@ -435,7 +435,8 @@ mips-*-netbsd*)
+ 	SHLIB_EXPFLAGS='$(SHLIB_RPATH_FLAGS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)'
+ 	PROFFLAGS=-pg
+ 	PROG_RPATH_FLAGS='$(RPATH_FLAG)$(PROG_RPATH)'
+-	CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CFLAGS) $(LDFLAGS)'
++	CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CFLAGS) -pie -Wl,-z,relro -Wl,-z,now $(LDFLAGS)'
++	INSTALL_SHLIB='${INSTALL} -m755'
+ 	CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)'
+ 	CXX_LINK_SHARED='$(CXX) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CXXFLAGS) $(LDFLAGS)'
+ 	CXX_LINK_STATIC='$(CXX) $(PROG_LIBPATH) $(CXXFLAGS) $(LDFLAGS)'
diff --git a/SOURCES/downstream-FIPS-with-PRNG-and-RADIUS-and-MD4.patch b/SOURCES/downstream-FIPS-with-PRNG-and-RADIUS-and-MD4.patch
new file mode 100644
index 0000000..913c6c3
--- /dev/null
+++ b/SOURCES/downstream-FIPS-with-PRNG-and-RADIUS-and-MD4.patch
@@ -0,0 +1,569 @@
+From a3f9d8f66a7f2e01aa7b12ef4e2a289d867bb276 Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Fri, 9 Nov 2018 15:12:21 -0500
+Subject: [PATCH] [downstream] FIPS with PRNG and RADIUS and MD4
+
+NB: Use openssl's PRNG in FIPS mode and taint within krad.
+
+A lot of the FIPS error conditions from OpenSSL are incredibly
+mysterious (at best, things return NULL unexpectedly; at worst,
+internal assertions are tripped; most of the time, you just get
+ENOMEM).  In order to cope with this, we need to have some level of
+awareness of what we can and can't safely call.
+
+This will slow down some calls slightly (FIPS_mode() takes multiple
+locks), but not for any ciphers we care about - which is to say that
+AES is fine.  Shame about SPAKE though.
+
+post6 restores MD4 (and therefore keygen-only RC4).
+
+Last-updated: krb5-1.17
+(cherry picked from commit a721df13d09b5fdad32de15e6aa973b732727aa9)
+---
+ 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                           | 45 ++++++++++++++-----
+ src/lib/krad/attrset.c                        |  5 ++-
+ src/lib/krad/internal.h                       | 13 +++++-
+ 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 +++
+ 14 files changed, 129 insertions(+), 33 deletions(-)
+
+diff --git a/src/lib/crypto/krb/prng.c b/src/lib/crypto/krb/prng.c
+index cb9ca9b98..f0e9984ca 100644
+--- a/src/lib/crypto/krb/prng.c
++++ b/src/lib/crypto/krb/prng.c
+@@ -26,6 +26,8 @@
+ 
+ #include "crypto_int.h"
+ 
++#include <openssl/rand.h>
++
+ krb5_error_code KRB5_CALLCONV
+ krb5_c_random_seed(krb5_context context, krb5_data *data)
+ {
+@@ -99,9 +101,16 @@ krb5_boolean
+ k5_get_os_entropy(unsigned char *buf, size_t len, int strong)
+ {
+     const char *device;
+-#if defined(__linux__) && defined(SYS_getrandom)
+     int r;
+ 
++    /* A wild FIPS mode appeared! */
++    if (FIPS_mode()) {
++        /* The return codes on this API are not good */
++        r = RAND_bytes(buf, len);
++        return r == 1;
++    }
++
++#if defined(__linux__) && defined(SYS_getrandom)
+     while (len > 0) {
+         /*
+          * Pull from the /dev/urandom pool, but require it to have been seeded.
+diff --git a/src/lib/crypto/openssl/enc_provider/camellia.c b/src/lib/crypto/openssl/enc_provider/camellia.c
+index 2da691329..f79679a0b 100644
+--- a/src/lib/crypto/openssl/enc_provider/camellia.c
++++ b/src/lib/crypto/openssl/enc_provider/camellia.c
+@@ -304,6 +304,9 @@ krb5int_camellia_cbc_mac(krb5_key key, const krb5_crypto_iov *data,
+     unsigned char blockY[CAMELLIA_BLOCK_SIZE], blockB[CAMELLIA_BLOCK_SIZE];
+     struct iov_cursor cursor;
+ 
++    if (FIPS_mode())
++        return KRB5_CRYPTO_INTERNAL;
++
+     if (output->length < CAMELLIA_BLOCK_SIZE)
+         return KRB5_BAD_MSIZE;
+ 
+@@ -331,6 +334,9 @@ static krb5_error_code
+ krb5int_camellia_init_state (const krb5_keyblock *key, krb5_keyusage usage,
+                              krb5_data *state)
+ {
++    if (FIPS_mode())
++        return KRB5_CRYPTO_INTERNAL;
++
+     state->length = 16;
+     state->data = (void *) malloc(16);
+     if (state->data == NULL)
+diff --git a/src/lib/crypto/openssl/enc_provider/rc4.c b/src/lib/crypto/openssl/enc_provider/rc4.c
+index a65d57b7a..6ccaca94a 100644
+--- a/src/lib/crypto/openssl/enc_provider/rc4.c
++++ b/src/lib/crypto/openssl/enc_provider/rc4.c
+@@ -66,6 +66,9 @@ k5_arcfour_docrypt(krb5_key key, const krb5_data *state, krb5_crypto_iov *data,
+     EVP_CIPHER_CTX *ctx = NULL;
+     struct arcfour_state *arcstate;
+ 
++    if (FIPS_mode())
++        return KRB5_CRYPTO_INTERNAL;
++
+     arcstate = (state != NULL) ? (void *)state->data : NULL;
+     if (arcstate != NULL) {
+         ctx = arcstate->ctx;
+@@ -113,7 +116,12 @@ k5_arcfour_docrypt(krb5_key key, const krb5_data *state, krb5_crypto_iov *data,
+ static void
+ k5_arcfour_free_state(krb5_data *state)
+ {
+-    struct arcfour_state *arcstate = (void *)state->data;
++    struct arcfour_state *arcstate;
++
++    if (FIPS_mode())
++        return;
++
++    arcstate = (void *) state->data;
+ 
+     EVP_CIPHER_CTX_free(arcstate->ctx);
+     free(arcstate);
+@@ -125,6 +133,9 @@ k5_arcfour_init_state(const krb5_keyblock *key,
+ {
+     struct arcfour_state *arcstate;
+ 
++    if (FIPS_mode())
++        return KRB5_CRYPTO_INTERNAL;
++
+     /*
+      * 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..feb5eda99 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;
+ 
++    if (type == EVP_md4()) {
++        /* See comment below in hash_md4(). */
++        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]))
+@@ -64,12 +69,19 @@ hash_evp(const EVP_MD *type, const krb5_crypto_iov *data, size_t num_data,
+ static krb5_error_code
+ hash_md4(const krb5_crypto_iov *data, size_t num_data, krb5_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);
+ }
+ 
+ static krb5_error_code
+ hash_md5(const krb5_crypto_iov *data, size_t num_data, krb5_data *output)
+ {
++    if (FIPS_mode())
++        return KRB5_CRYPTO_INTERNAL;
+     return hash_evp(EVP_md5(), data, num_data, output);
+ }
+ 
+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
++++ b/src/lib/crypto/openssl/hmac.c
+@@ -103,7 +103,11 @@ map_digest(const struct krb5_hash_provider *hash)
+         return EVP_sha256();
+     else if (!strncmp(hash->hash_name, "SHA-384",7))
+         return EVP_sha384();
+-    else if (!strncmp(hash->hash_name, "MD5", 3))
++
++    if (FIPS_mode())
++        return NULL;
++
++    if (!strncmp(hash->hash_name, "MD5", 3))
+         return EVP_md5();
+     else if (!strncmp(hash->hash_name, "MD4", 3))
+         return EVP_md4();
+diff --git a/src/lib/krad/attr.c b/src/lib/krad/attr.c
+index 9c13d9d75..275327e67 100644
+--- a/src/lib/krad/attr.c
++++ b/src/lib/krad/attr.c
+@@ -30,6 +30,7 @@
+ #include <k5-int.h>
+ #include "internal.h"
+ 
++#include <openssl/crypto.h>
+ #include <string.h>
+ 
+ /* RFC 2865 */
+@@ -38,7 +39,8 @@
+ typedef krb5_error_code
+ (*attribute_transform_fn)(krb5_context ctx, const char *secret,
+                           const unsigned char *auth, const krb5_data *in,
+-                          unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen);
++                          unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
++                          krb5_boolean *is_fips);
+ 
+ typedef struct {
+     const char *name;
+@@ -51,12 +53,14 @@ typedef struct {
+ static krb5_error_code
+ user_password_encode(krb5_context ctx, const char *secret,
+                      const unsigned char *auth, const krb5_data *in,
+-                     unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen);
++                     unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
++                     krb5_boolean *is_fips);
+ 
+ static krb5_error_code
+ user_password_decode(krb5_context ctx, const char *secret,
+                      const unsigned char *auth, const krb5_data *in,
+-                     unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen);
++                     unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
++                     krb5_boolean *ignored);
+ 
+ static const attribute_record attributes[UCHAR_MAX] = {
+     {"User-Name", 1, MAX_ATTRSIZE, NULL, NULL},
+@@ -128,7 +132,8 @@ static const attribute_record attributes[UCHAR_MAX] = {
+ static krb5_error_code
+ user_password_encode(krb5_context ctx, const char *secret,
+                      const unsigned char *auth, const krb5_data *in,
+-                     unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen)
++                     unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
++                     krb5_boolean *is_fips)
+ {
+     const unsigned char *indx;
+     krb5_error_code retval;
+@@ -154,8 +159,14 @@ user_password_encode(krb5_context ctx, const char *secret,
+     for (blck = 0, indx = auth; blck * BLOCKSIZE < len; blck++) {
+         memcpy(tmp.data + seclen, indx, BLOCKSIZE);
+ 
+-        retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0, &tmp,
+-                                      &sum);
++        if (FIPS_mode()) {
++            /* Skip encryption here.  Taint so that we won't pass it out of
++             * the machine by accident. */
++            *is_fips = TRUE;
++            sum.contents = calloc(1, BLOCKSIZE);
++        } else
++            retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0, &tmp,
++                                          &sum);
+         if (retval != 0) {
+             zap(tmp.data, tmp.length);
+             zap(outbuf, len);
+@@ -180,7 +191,8 @@ user_password_encode(krb5_context ctx, const char *secret,
+ static krb5_error_code
+ user_password_decode(krb5_context ctx, const char *secret,
+                      const unsigned char *auth, const krb5_data *in,
+-                     unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen)
++                     unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
++                     krb5_boolean *is_fips)
+ {
+     const unsigned char *indx;
+     krb5_error_code retval;
+@@ -204,8 +216,14 @@ user_password_decode(krb5_context ctx, const char *secret,
+     for (blck = 0, indx = auth; blck * BLOCKSIZE < in->length; blck++) {
+         memcpy(tmp.data + seclen, indx, BLOCKSIZE);
+ 
+-        retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0,
+-                                      &tmp, &sum);
++        if (FIPS_mode()) {
++            /* Skip encryption here.  Taint so that we won't pass it out of
++             * the machine by accident. */
++            *is_fips = TRUE;
++            sum.contents = calloc(1, BLOCKSIZE);
++        } else
++            retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0,
++                                          &tmp, &sum);
+         if (retval != 0) {
+             zap(tmp.data, tmp.length);
+             zap(outbuf, in->length);
+@@ -248,7 +266,7 @@ krb5_error_code
+ kr_attr_encode(krb5_context ctx, const char *secret,
+                const unsigned char *auth, krad_attr type,
+                const krb5_data *in, unsigned char outbuf[MAX_ATTRSIZE],
+-               size_t *outlen)
++               size_t *outlen, krb5_boolean *is_fips)
+ {
+     krb5_error_code retval;
+ 
+@@ -265,7 +283,8 @@ kr_attr_encode(krb5_context ctx, const char *secret,
+         return 0;
+     }
+ 
+-    return attributes[type - 1].encode(ctx, secret, auth, in, outbuf, outlen);
++    return attributes[type - 1].encode(ctx, secret, auth, in, outbuf, outlen,
++                                       is_fips);
+ }
+ 
+ krb5_error_code
+@@ -274,6 +293,7 @@ kr_attr_decode(krb5_context ctx, const char *secret, const unsigned char *auth,
+                unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen)
+ {
+     krb5_error_code retval;
++    krb5_boolean ignored;
+ 
+     retval = kr_attr_valid(type, in);
+     if (retval != 0)
+@@ -288,7 +308,8 @@ kr_attr_decode(krb5_context ctx, const char *secret, const unsigned char *auth,
+         return 0;
+     }
+ 
+-    return attributes[type - 1].decode(ctx, secret, auth, in, outbuf, outlen);
++    return attributes[type - 1].decode(ctx, secret, auth, in, outbuf, outlen,
++                                       &ignored);
+ }
+ 
+ krad_attr
+diff --git a/src/lib/krad/attrset.c b/src/lib/krad/attrset.c
+index 03c613716..d89982a13 100644
+--- a/src/lib/krad/attrset.c
++++ b/src/lib/krad/attrset.c
+@@ -167,7 +167,8 @@ krad_attrset_copy(const krad_attrset *set, krad_attrset **copy)
+ krb5_error_code
+ kr_attrset_encode(const krad_attrset *set, const char *secret,
+                   const unsigned char *auth,
+-                  unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen)
++                  unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen,
++                  krb5_boolean *is_fips)
+ {
+     unsigned char buffer[MAX_ATTRSIZE];
+     krb5_error_code retval;
+@@ -181,7 +182,7 @@ kr_attrset_encode(const krad_attrset *set, const char *secret,
+ 
+     K5_TAILQ_FOREACH(a, &set->list, list) {
+         retval = kr_attr_encode(set->ctx, secret, auth, a->type, &a->attr,
+-                                buffer, &attrlen);
++                                buffer, &attrlen, is_fips);
+         if (retval != 0)
+             return retval;
+ 
+diff --git a/src/lib/krad/internal.h b/src/lib/krad/internal.h
+index 996a89372..a53ce31ce 100644
+--- a/src/lib/krad/internal.h
++++ b/src/lib/krad/internal.h
+@@ -49,6 +49,13 @@
+ 
+ typedef struct krad_remote_st krad_remote;
+ 
++struct krad_packet_st {
++    char buffer[KRAD_PACKET_SIZE_MAX];
++    krad_attrset *attrset;
++    krb5_data pkt;
++    krb5_boolean is_fips;
++};
++
+ /* Validate constraints of an attribute. */
+ krb5_error_code
+ kr_attr_valid(krad_attr type, const krb5_data *data);
+@@ -57,7 +64,8 @@ kr_attr_valid(krad_attr type, const krb5_data *data);
+ krb5_error_code
+ kr_attr_encode(krb5_context ctx, const char *secret, const unsigned char *auth,
+                krad_attr type, const krb5_data *in,
+-               unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen);
++               unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
++               krb5_boolean *is_fips);
+ 
+ /* Decode an attribute. */
+ krb5_error_code
+@@ -69,7 +77,8 @@ kr_attr_decode(krb5_context ctx, const char *secret, const unsigned char *auth,
+ krb5_error_code
+ kr_attrset_encode(const krad_attrset *set, const char *secret,
+                   const unsigned char *auth,
+-                  unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen);
++                  unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen,
++                  krb5_boolean *is_fips);
+ 
+ /* Decode attributes from a buffer. */
+ krb5_error_code
+diff --git a/src/lib/krad/packet.c b/src/lib/krad/packet.c
+index c597174b6..794ac84c4 100644
+--- a/src/lib/krad/packet.c
++++ b/src/lib/krad/packet.c
+@@ -32,6 +32,7 @@
+ #include <string.h>
+ 
+ #include <arpa/inet.h>
++#include <openssl/crypto.h>
+ 
+ typedef unsigned char uchar;
+ 
+@@ -53,12 +54,6 @@ typedef unsigned char uchar;
+ #define pkt_auth(p) ((uchar *)offset(&(p)->pkt, OFFSET_AUTH))
+ #define pkt_attr(p) ((unsigned char *)offset(&(p)->pkt, OFFSET_ATTR))
+ 
+-struct krad_packet_st {
+-    char buffer[KRAD_PACKET_SIZE_MAX];
+-    krad_attrset *attrset;
+-    krb5_data pkt;
+-};
+-
+ typedef struct {
+     uchar x[(UCHAR_MAX + 1) / 8];
+ } idmap;
+@@ -187,8 +182,13 @@ auth_generate_response(krb5_context ctx, const char *secret,
+     memcpy(data.data + response->pkt.length, secret, strlen(secret));
+ 
+     /* Hash it. */
+-    retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0, &data,
+-                                  &hash);
++    if (FIPS_mode()) {
++        /* This checksum does very little security-wise anyway, so don't
++         * taint. */
++        hash.contents = calloc(1, AUTH_FIELD_SIZE);
++    } else
++        retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0, &data,
++                                      &hash);
+     free(data.data);
+     if (retval != 0)
+         return retval;
+@@ -276,7 +276,7 @@ krad_packet_new_request(krb5_context ctx, const char *secret, krad_code code,
+ 
+     /* Encode the attributes. */
+     retval = kr_attrset_encode(set, secret, pkt_auth(pkt), pkt_attr(pkt),
+-                               &attrset_len);
++                               &attrset_len, &pkt->is_fips);
+     if (retval != 0)
+         goto error;
+ 
+@@ -314,7 +314,7 @@ krad_packet_new_response(krb5_context ctx, const char *secret, krad_code code,
+ 
+     /* Encode the attributes. */
+     retval = kr_attrset_encode(set, secret, pkt_auth(request), pkt_attr(pkt),
+-                               &attrset_len);
++                               &attrset_len, &pkt->is_fips);
+     if (retval != 0)
+         goto error;
+ 
+@@ -451,6 +451,8 @@ krad_packet_decode_response(krb5_context ctx, const char *secret,
+ const krb5_data *
+ krad_packet_encode(const krad_packet *pkt)
+ {
++    if (pkt->is_fips)
++        return NULL;
+     return &pkt->pkt;
+ }
+ 
+diff --git a/src/lib/krad/remote.c b/src/lib/krad/remote.c
+index 437f7e91a..0f90443ce 100644
+--- a/src/lib/krad/remote.c
++++ b/src/lib/krad/remote.c
+@@ -263,7 +263,7 @@ on_io_write(krad_remote *rr)
+     request *r;
+ 
+     K5_TAILQ_FOREACH(r, &rr->list, list) {
+-        tmp = krad_packet_encode(r->request);
++        tmp = &r->request->pkt;
+ 
+         /* If the packet has already been sent, do nothing. */
+         if (r->sent == tmp->length)
+@@ -359,7 +359,7 @@ on_io_read(krad_remote *rr)
+     if (req != NULL) {
+         K5_TAILQ_FOREACH(r, &rr->list, list) {
+             if (r->request == req &&
+-                r->sent == krad_packet_encode(req)->length) {
++                r->sent == req->pkt.length) {
+                 request_finish(r, 0, rsp);
+                 break;
+             }
+@@ -455,6 +455,12 @@ kr_remote_send(krad_remote *rr, krad_code code, krad_attrset *attrs,
+                                      (krad_packet_iter_cb)iterator, &r, &tmp);
+     if (retval != 0)
+         goto error;
++    else if (tmp->is_fips && rr->info->ai_family != AF_LOCAL &&
++        rr->info->ai_family != AF_UNIX) {
++        /* This would expose cleartext passwords, so abort. */
++        retval = ESOCKTNOSUPPORT;
++        goto error;
++    }
+ 
+     K5_TAILQ_FOREACH(r, &rr->list, list) {
+         if (r->request == tmp) {
+diff --git a/src/lib/krad/t_attr.c b/src/lib/krad/t_attr.c
+index eb2a780c8..4d285ad9d 100644
+--- a/src/lib/krad/t_attr.c
++++ b/src/lib/krad/t_attr.c
+@@ -50,6 +50,7 @@ main()
+     const char *tmp;
+     krb5_data in;
+     size_t len;
++    krb5_boolean is_fips = FALSE;
+ 
+     noerror(krb5_init_context(&ctx));
+ 
+@@ -73,7 +74,7 @@ main()
+     in = string2data((char *)decoded);
+     retval = kr_attr_encode(ctx, secret, auth,
+                             krad_attr_name2num("User-Password"),
+-                            &in, outbuf, &len);
++                            &in, outbuf, &len, &is_fips);
+     insist(retval == 0);
+     insist(len == sizeof(encoded));
+     insist(memcmp(outbuf, encoded, len) == 0);
+diff --git a/src/lib/krad/t_attrset.c b/src/lib/krad/t_attrset.c
+index 7928335ca..0f9576253 100644
+--- a/src/lib/krad/t_attrset.c
++++ b/src/lib/krad/t_attrset.c
+@@ -49,6 +49,7 @@ main()
+     krb5_context ctx;
+     size_t len = 0, encode_len;
+     krb5_data tmp;
++    krb5_boolean is_fips = FALSE;
+ 
+     noerror(krb5_init_context(&ctx));
+     noerror(krad_attrset_new(ctx, &set));
+@@ -62,7 +63,8 @@ main()
+     noerror(krad_attrset_add(set, krad_attr_name2num("User-Password"), &tmp));
+ 
+     /* Encode attrset. */
+-    noerror(kr_attrset_encode(set, "foo", auth, buffer, &encode_len));
++    noerror(kr_attrset_encode(set, "foo", auth, buffer, &encode_len,
++                              &is_fips));
+     krad_attrset_free(set);
+ 
+     /* Manually encode User-Name. */
+diff --git a/src/plugins/preauth/spake/spake_client.c b/src/plugins/preauth/spake/spake_client.c
+index 00734a13b..a3ce22b70 100644
+--- a/src/plugins/preauth/spake/spake_client.c
++++ b/src/plugins/preauth/spake/spake_client.c
+@@ -38,6 +38,8 @@
+ #include "groups.h"
+ #include <krb5/clpreauth_plugin.h>
+ 
++#include <openssl/crypto.h>
++
+ typedef struct reqstate_st {
+     krb5_pa_spake *msg;         /* set in prep_questions, used in process */
+     krb5_keyblock *initial_key;
+@@ -375,6 +377,10 @@ clpreauth_spake_initvt(krb5_context context, int maj_ver, int min_ver,
+ 
+     if (maj_ver != 1)
+         return KRB5_PLUGIN_VER_NOTSUPP;
++
++    if (FIPS_mode())
++        return KRB5_CRYPTO_INTERNAL;
++
+     vt = (krb5_clpreauth_vtable)vtable;
+     vt->name = "spake";
+     vt->pa_type_list = pa_types;
+diff --git a/src/plugins/preauth/spake/spake_kdc.c b/src/plugins/preauth/spake/spake_kdc.c
+index 88c964ce1..c7df0392f 100644
+--- a/src/plugins/preauth/spake/spake_kdc.c
++++ b/src/plugins/preauth/spake/spake_kdc.c
+@@ -41,6 +41,8 @@
+ 
+ #include <krb5/kdcpreauth_plugin.h>
+ 
++#include <openssl/crypto.h>
++
+ /*
+  * The SPAKE kdcpreauth module uses a secure cookie containing the following
+  * concatenated fields (all integer fields are big-endian):
+@@ -571,6 +573,10 @@ kdcpreauth_spake_initvt(krb5_context context, int maj_ver, int min_ver,
+ 
+     if (maj_ver != 1)
+         return KRB5_PLUGIN_VER_NOTSUPP;
++
++    if (FIPS_mode())
++        return KRB5_CRYPTO_INTERNAL;
++
+     vt = (krb5_kdcpreauth_vtable)vtable;
+     vt->name = "spake";
+     vt->pa_type_list = pa_types;
diff --git a/SOURCES/downstream-Remove-3des-support.patch b/SOURCES/downstream-Remove-3des-support.patch
new file mode 100644
index 0000000..22251b9
--- /dev/null
+++ b/SOURCES/downstream-Remove-3des-support.patch
@@ -0,0 +1,6465 @@
+From 3c1f235c1c82b1cebfd2eba800cd2cd2610f0535 Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Tue, 26 Mar 2019 18:51:10 -0400
+Subject: [PATCH] [downstream] Remove 3des support
+
+Completely remove support for all DES3 enctypes (des3-cbc-raw,
+des3-hmac-sha1, des3-cbc-sha1-kd).  Update all tests and documentation
+to user other enctypes.  Mark the 3DES enctypes UNSUPPORTED and retain
+their constants.
+
+Last-updated: 1.18-beta2
+(cherry picked from commit e9cd83237b54e2f6010a063f523217b0a442ecbf)
+---
+ doc/admin/advanced/retiring-des.rst           |  11 +
+ doc/admin/conf_files/kdc_conf.rst             |   7 +-
+ doc/admin/enctypes.rst                        |  13 +-
+ doc/admin/troubleshoot.rst                    |   9 +-
+ doc/appdev/refs/macros/index.rst              |   1 -
+ doc/conf.py                                   |   2 +-
+ doc/mitK5features.rst                         |   2 +-
+ src/Makefile.in                               |   4 +-
+ src/configure.ac                              |   1 -
+ src/include/krb5/krb5.hin                     |  10 +-
+ src/kadmin/testing/proto/kdc.conf.proto       |   4 +-
+ src/kdc/kdc_util.c                            |   4 -
+ src/lib/crypto/Makefile.in                    |   8 +-
+ src/lib/crypto/builtin/Makefile.in            |   6 +-
+ src/lib/crypto/builtin/des/ISSUES             |  13 -
+ src/lib/crypto/builtin/des/Makefile.in        |  80 ----
+ src/lib/crypto/builtin/des/d3_aead.c          | 133 ------
+ src/lib/crypto/builtin/des/d3_kysched.c       |  51 ---
+ src/lib/crypto/builtin/des/deps               | 148 -------
+ src/lib/crypto/builtin/des/des_int.h          | 285 -------------
+ src/lib/crypto/builtin/des/des_keys.c         |  40 --
+ src/lib/crypto/builtin/des/destest.c          | 240 -----------
+ src/lib/crypto/builtin/des/doc/libdes.doc     | 208 ---------
+ src/lib/crypto/builtin/des/f_aead.c           | 173 --------
+ src/lib/crypto/builtin/des/f_cbc.c            | 256 ------------
+ src/lib/crypto/builtin/des/f_cksum.c          | 136 ------
+ src/lib/crypto/builtin/des/f_parity.c         |  56 ---
+ src/lib/crypto/builtin/des/f_sched.c          | 359 ----------------
+ src/lib/crypto/builtin/des/f_tables.c         | 370 ----------------
+ src/lib/crypto/builtin/des/f_tables.h         | 285 -------------
+ src/lib/crypto/builtin/des/key_sched.c        |  62 ---
+ src/lib/crypto/builtin/des/keytest.data       | 171 --------
+ src/lib/crypto/builtin/des/t_verify.c         | 395 ------------------
+ src/lib/crypto/builtin/des/weak_key.c         |  86 ----
+ .../crypto/builtin/enc_provider/Makefile.in   |   6 +-
+ src/lib/crypto/builtin/enc_provider/deps      |  12 -
+ src/lib/crypto/builtin/enc_provider/des3.c    | 105 -----
+ src/lib/crypto/crypto_tests/t_cf2.expected    |   1 -
+ src/lib/crypto/crypto_tests/t_cf2.in          |   5 -
+ src/lib/crypto/crypto_tests/t_cksums.c        |  10 -
+ src/lib/crypto/crypto_tests/t_decrypt.c       |  57 ---
+ src/lib/crypto/crypto_tests/t_derive.c        |  36 --
+ src/lib/crypto/crypto_tests/t_encrypt.c       |   1 -
+ src/lib/crypto/crypto_tests/t_short.c         |   1 -
+ src/lib/crypto/crypto_tests/t_str2key.c       |  52 ---
+ src/lib/crypto/krb/Makefile.in                |   3 -
+ src/lib/crypto/krb/cksumtypes.c               |   6 -
+ src/lib/crypto/krb/crypto_int.h               |  16 -
+ src/lib/crypto/krb/default_state.c            |  10 -
+ src/lib/crypto/krb/enctype_util.c             |   3 +
+ src/lib/crypto/krb/etypes.c                   |  21 -
+ src/lib/crypto/krb/prf_des.c                  |  47 ---
+ src/lib/crypto/krb/random_to_key.c            |  45 --
+ src/lib/crypto/libk5crypto.exports            |   1 -
+ src/lib/crypto/openssl/Makefile.in            |   8 +-
+ src/lib/crypto/openssl/des/Makefile.in        |  20 -
+ src/lib/crypto/openssl/des/deps               |  15 -
+ src/lib/crypto/openssl/des/des_keys.c         |  40 --
+ .../crypto/openssl/enc_provider/Makefile.in   |   3 -
+ src/lib/crypto/openssl/enc_provider/deps      |  11 -
+ src/lib/crypto/openssl/enc_provider/des3.c    | 184 --------
+ src/lib/gssapi/krb5/accept_sec_context.c      |   1 -
+ src/lib/gssapi/krb5/gssapiP_krb5.h            |   6 +-
+ src/lib/gssapi/krb5/k5seal.c                  |  35 +-
+ src/lib/gssapi/krb5/k5sealiov.c               |  27 +-
+ src/lib/gssapi/krb5/k5unseal.c                | 102 ++---
+ src/lib/gssapi/krb5/k5unsealiov.c             |  38 +-
+ src/lib/gssapi/krb5/util_crypt.c              |  11 -
+ .../api.current/chpass-principal-v2.exp       |   4 +-
+ .../api.current/get-principal-v2.exp          |   4 +-
+ .../api.current/randkey-principal-v2.exp      |   4 +-
+ src/lib/krb5/krb/init_ctx.c                   |   3 -
+ src/lib/krb5/krb/s4u_creds.c                  |   2 -
+ src/lib/krb5/krb/t_copy_context.c             |   2 +-
+ src/lib/krb5/krb/t_etypes.c                   |  48 +--
+ src/lib/krb5/os/t_trace.c                     |   4 +-
+ src/lib/krb5/os/t_trace.ref                   |   2 +-
+ src/plugins/preauth/pkinit/pkcs11.h           |   6 +-
+ src/plugins/preauth/pkinit/pkinit_clnt.c      |   8 -
+ src/plugins/preauth/pkinit/pkinit_crypto.h    |  12 -
+ .../preauth/pkinit/pkinit_crypto_openssl.c    |  38 --
+ src/plugins/preauth/pkinit/pkinit_kdf_test.c  |  31 --
+ src/plugins/preauth/spake/t_vectors.c         |  25 --
+ src/tests/dejagnu/config/default.exp          |  78 ----
+ src/tests/dejagnu/krb-standalone/kprop.exp    |   2 +-
+ src/tests/gssapi/t_enctypes.py                |  33 +-
+ src/tests/gssapi/t_invalid.c                  |  12 -
+ src/tests/gssapi/t_pcontok.c                  |  16 +-
+ src/tests/gssapi/t_prf.c                      |   7 -
+ src/tests/t_authdata.py                       |   2 +-
+ src/tests/t_etype_info.py                     |  18 +-
+ src/tests/t_keyrollover.py                    |   8 +-
+ src/tests/t_mkey.py                           |  35 --
+ src/tests/t_salt.py                           |   5 +-
+ src/util/k5test.py                            |   7 -
+ .../leash/htmlhelp/html/Encryption_Types.htm  |  13 -
+ 96 files changed, 163 insertions(+), 4834 deletions(-)
+ delete mode 100644 src/lib/crypto/builtin/des/ISSUES
+ delete mode 100644 src/lib/crypto/builtin/des/Makefile.in
+ delete mode 100644 src/lib/crypto/builtin/des/d3_aead.c
+ delete mode 100644 src/lib/crypto/builtin/des/d3_kysched.c
+ delete mode 100644 src/lib/crypto/builtin/des/deps
+ delete mode 100644 src/lib/crypto/builtin/des/des_int.h
+ delete mode 100644 src/lib/crypto/builtin/des/des_keys.c
+ delete mode 100644 src/lib/crypto/builtin/des/destest.c
+ delete mode 100644 src/lib/crypto/builtin/des/doc/libdes.doc
+ delete mode 100644 src/lib/crypto/builtin/des/f_aead.c
+ delete mode 100644 src/lib/crypto/builtin/des/f_cbc.c
+ delete mode 100644 src/lib/crypto/builtin/des/f_cksum.c
+ delete mode 100644 src/lib/crypto/builtin/des/f_parity.c
+ delete mode 100644 src/lib/crypto/builtin/des/f_sched.c
+ delete mode 100644 src/lib/crypto/builtin/des/f_tables.c
+ delete mode 100644 src/lib/crypto/builtin/des/f_tables.h
+ delete mode 100644 src/lib/crypto/builtin/des/key_sched.c
+ delete mode 100644 src/lib/crypto/builtin/des/keytest.data
+ delete mode 100644 src/lib/crypto/builtin/des/t_verify.c
+ delete mode 100644 src/lib/crypto/builtin/des/weak_key.c
+ delete mode 100644 src/lib/crypto/builtin/enc_provider/des3.c
+ delete mode 100644 src/lib/crypto/krb/prf_des.c
+ delete mode 100644 src/lib/crypto/openssl/des/Makefile.in
+ delete mode 100644 src/lib/crypto/openssl/des/deps
+ delete mode 100644 src/lib/crypto/openssl/des/des_keys.c
+ delete mode 100644 src/lib/crypto/openssl/enc_provider/des3.c
+
+diff --git a/doc/admin/advanced/retiring-des.rst b/doc/admin/advanced/retiring-des.rst
+index 4a964c15c..cb6258d77 100644
+--- a/doc/admin/advanced/retiring-des.rst
++++ b/doc/admin/advanced/retiring-des.rst
+@@ -10,6 +10,13 @@ ability have rendered DES vulnerable to brute force attacks on its 56-bit
+ keyspace.  As such, it is now considered insecure and should not be
+ used (:rfc:`6649`).
+ 
++In 1999, MIT krb5 added support for Triple-DES (3DES) encryption types.
++However, due to weakenings of DES and other security concerns, it is now also
++considered insecure and should not be used (:rfc:`8429`).  AES encryption
++types were added to MIT in 2003, meaning that the number of deployments with
++3DES as the strongest encryption type is hopefully small.  The rotation
++procedure described herein works for both DES and 3DES.
++
+ History
+ -------
+ 
+@@ -27,6 +34,10 @@ and removed DES (single-DES) support in release 1.18.  As a
+ consequence, a release prior to 1.18 is required to perform these
+ migrations.
+ 
++3DES (a flagged deprecated encryption type) was also removed downstream by
++rharwood@redhat.com starting in 1.18; likewise, a pre-1.18 release is required
++to perform these migrations.
++
+ Types of keys
+ -------------
+ 
+diff --git a/doc/admin/conf_files/kdc_conf.rst b/doc/admin/conf_files/kdc_conf.rst
+index 9759756a2..cf8a12547 100644
+--- a/doc/admin/conf_files/kdc_conf.rst
++++ b/doc/admin/conf_files/kdc_conf.rst
+@@ -843,8 +843,6 @@ Encryption types marked as "weak" are available for compatibility but
+ not recommended for use.
+ 
+ ==================================================== =========================================================
+-des3-cbc-raw                                         Triple DES cbc mode raw (weak)
+-des3-cbc-sha1 des3-hmac-sha1 des3-cbc-sha1-kd        Triple DES cbc mode with HMAC/sha1
+ aes256-cts-hmac-sha1-96 aes256-cts aes256-sha1       AES-256 CTS mode with 96-bit SHA-1 HMAC
+ aes128-cts-hmac-sha1-96 aes128-cts aes128-sha1       AES-128 CTS mode with 96-bit SHA-1 HMAC
+ aes256-cts-hmac-sha384-192 aes256-sha2               AES-256 CTS mode with 192-bit SHA-384 HMAC
+@@ -853,7 +851,6 @@ arcfour-hmac rc4-hmac arcfour-hmac-md5               RC4 with HMAC/MD5
+ arcfour-hmac-exp rc4-hmac-exp arcfour-hmac-md5-exp   Exportable RC4 with HMAC/MD5 (weak)
+ camellia256-cts-cmac camellia256-cts                 Camellia-256 CTS mode with CMAC
+ camellia128-cts-cmac camellia128-cts                 Camellia-128 CTS mode with CMAC
+-des3                                                 The triple DES family: des3-cbc-sha1
+ aes                                                  The AES family: aes256-cts-hmac-sha1-96, aes128-cts-hmac-sha1-96, aes256-cts-hmac-sha384-192, and aes128-cts-hmac-sha256-128
+ rc4                                                  The RC4 family: arcfour-hmac
+ camellia                                             The Camellia family: camellia256-cts-cmac and camellia128-cts-cmac
+@@ -865,8 +862,8 @@ from the current list by prefixing them with a minus sign ("-").
+ Types or families can be prefixed with a plus sign ("+") for symmetry;
+ it has the same meaning as just listing the type or family.  For
+ example, "``DEFAULT -rc4``" would be the default set of encryption
+-types with RC4 types removed, and "``des3 DEFAULT``" would be the
+-default set of encryption types with triple DES types moved to the
++types with RC4 types removed, and "``aes128-sha2 DEFAULT``" would be
++the default set of encryption types with aes128-sha2 moved to the
+ front.
+ 
+ While **aes128-cts** and **aes256-cts** are supported for all Kerberos
+diff --git a/doc/admin/enctypes.rst b/doc/admin/enctypes.rst
+index caf6d9267..65b55cdb9 100644
+--- a/doc/admin/enctypes.rst
++++ b/doc/admin/enctypes.rst
+@@ -129,7 +129,7 @@ enctype                    weak? krb5     Windows
+ des-cbc-crc                weak  <1.18    >=2000
+ des-cbc-md4                weak  <1.18    ?
+ des-cbc-md5                weak  <1.18    >=2000
+-des3-cbc-sha1                    >=1.1    none
++des3-cbc-sha1                    <1.18    none
+ arcfour-hmac                     >=1.3    >=2000
+ arcfour-hmac-exp           weak  >=1.3    >=2000
+ aes128-cts-hmac-sha1-96          >=1.3    >=Vista
+@@ -140,7 +140,10 @@ camellia128-cts-cmac             >=1.9    none
+ camellia256-cts-cmac             >=1.9    none
+ ========================== ===== ======== =======
+ 
+-krb5 releases 1.18 and later do not support single-DES.  krb5 releases
+-1.8 and later disable the single-DES enctypes by default.  Microsoft
+-Windows releases Windows 7 and later disable single-DES enctypes by
+-default.
++krb5 releases 1.8 and later disable the single-DES enctypes by
++default.  Microsoft Windows releases Windows 7 and later disable
++single-DES enctypes by default.
++
++krb5 releases 1.18 and later remove single-DES and 3DES
++(downstream-only patch) enctype support.  Microsoft Windows never
++supported 3DES.
+diff --git a/doc/admin/troubleshoot.rst b/doc/admin/troubleshoot.rst
+index 6a0c7f89b..263fc9c97 100644
+--- a/doc/admin/troubleshoot.rst
++++ b/doc/admin/troubleshoot.rst
+@@ -73,11 +73,10 @@ credential verification failed: KDC has no support for encryption type
+ ......................................................................
+ 
+ This most commonly happens when trying to use a principal with only
+-DES keys, in a release (MIT krb5 1.7 or later) which disables DES by
+-default.  DES encryption is considered weak due to its inadequate key
+-size.  If you cannot migrate away from its use, you can re-enable DES
+-by adding ``allow_weak_crypto = true`` to the :ref:`libdefaults`
+-section of :ref:`krb5.conf(5)`.
++DES/3DES keys, in a release (MIT krb5 1.7 or later) which disables DES
++by default.  DES encryption is considered weak due to its inadequate
++key size and has been removed upstream; 3DES is not recommended, and
++has been removed downstream by rharwood@redhat.com.
+ 
+ 
+ .. _err_cert_chain_cert_expired:
+diff --git a/doc/appdev/refs/macros/index.rst b/doc/appdev/refs/macros/index.rst
+index 68debe714..788d094bf 100644
+--- a/doc/appdev/refs/macros/index.rst
++++ b/doc/appdev/refs/macros/index.rst
+@@ -36,7 +36,6 @@ Public
+    CKSUMTYPE_HMAC_SHA1_96_AES256.rst
+    CKSUMTYPE_HMAC_SHA256_128_AES128.rst
+    CKSUMTYPE_HMAC_SHA384_192_AES256.rst
+-   CKSUMTYPE_HMAC_SHA1_DES3.rst
+    CKSUMTYPE_MD5_HMAC_ARCFOUR.rst
+    CKSUMTYPE_NIST_SHA.rst
+    CKSUMTYPE_RSA_MD4.rst
+diff --git a/doc/conf.py b/doc/conf.py
+index c32b2882a..5eeafc30f 100644
+--- a/doc/conf.py
++++ b/doc/conf.py
+@@ -272,7 +272,7 @@ else:
+     rst_epilog += '''
+ .. |krb5conf| replace:: ``/etc/krb5.conf``
+ .. |defkeysalts| replace:: ``aes256-cts-hmac-sha1-96:normal aes128-cts-hmac-sha1-96:normal``
+-.. |defetypes| replace:: ``aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96 aes256-cts-hmac-sha384-192 aes128-cts-hmac-sha256-128 des3-cbc-sha1 arcfour-hmac-md5 camellia256-cts-cmac camellia128-cts-cmac``
++.. |defetypes| replace:: ``aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96 aes256-cts-hmac-sha384-192 aes128-cts-hmac-sha256-128 arcfour-hmac-md5 camellia256-cts-cmac camellia128-cts-cmac``
+ .. |defmkey| replace:: ``aes256-cts-hmac-sha1-96``
+ .. |copy| unicode:: U+000A9
+ '''
+diff --git a/doc/mitK5features.rst b/doc/mitK5features.rst
+index 5d286b6ee..f4594ed13 100644
+--- a/doc/mitK5features.rst
++++ b/doc/mitK5features.rst
+@@ -37,7 +37,7 @@ Database backends: LDAP, DB2, LMDB
+ 
+ krb4 support: Kerberos 5 release < 1.8
+ 
+-DES support: Kerberos 5 release < 1.18 (See :ref:`retiring-des`)
++DES/3DES support: Kerberos 5 release < 1.18 (See :ref:`retiring-des`)
+ 
+ Interoperability
+ ----------------
+diff --git a/src/Makefile.in b/src/Makefile.in
+index 56c7a4e6f..70db82a30 100644
+--- a/src/Makefile.in
++++ b/src/Makefile.in
+@@ -130,7 +130,7 @@ WINMAKEFILES=Makefile \
+ 	lib\Makefile lib\crypto\Makefile lib\crypto\krb\Makefile \
+ 	lib\crypto\builtin\Makefile lib\crypto\builtin\aes\Makefile \
+ 	lib\crypto\builtin\enc_provider\Makefile \
+-	lib\crypto\builtin\des\Makefile lib\crypto\builtin\md5\Makefile \
++	lib\crypto\builtin\md5\Makefile \
+ 	lib\crypto\builtin\camellia\Makefile lib\crypto\builtin\md4\Makefile \
+ 	lib\crypto\builtin\hash_provider\Makefile \
+ 	lib\crypto\builtin\sha2\Makefile lib\crypto\builtin\sha1\Makefile \
+@@ -202,8 +202,6 @@ WINMAKEFILES=Makefile \
+ ##DOS##	$(WCONFIG) config < $@.in > $@
+ ##DOS##lib\crypto\builtin\enc_provider\Makefile: lib\crypto\builtin\enc_provider\Makefile.in $(MKFDEP)
+ ##DOS##	$(WCONFIG) config < $@.in > $@
+-##DOS##lib\crypto\builtin\des\Makefile: lib\crypto\builtin\des\Makefile.in $(MKFDEP)
+-##DOS##	$(WCONFIG) config < $@.in > $@
+ ##DOS##lib\crypto\builtin\md5\Makefile: lib\crypto\builtin\md5\Makefile.in $(MKFDEP)
+ ##DOS##	$(WCONFIG) config < $@.in > $@
+ ##DOS##lib\crypto\builtin\camellia\Makefile: lib\crypto\builtin\camellia\Makefile.in $(MKFDEP)
+diff --git a/src/configure.ac b/src/configure.ac
+index 440a22bd9..d4e4da525 100644
+--- a/src/configure.ac
++++ b/src/configure.ac
+@@ -1481,7 +1481,6 @@ V5_AC_OUTPUT_MAKEFILE(.
+ 	lib/crypto lib/crypto/krb lib/crypto/$CRYPTO_IMPL
+ 	lib/crypto/$CRYPTO_IMPL/enc_provider
+ 	lib/crypto/$CRYPTO_IMPL/hash_provider
+-	lib/crypto/$CRYPTO_IMPL/des
+ 	lib/crypto/$CRYPTO_IMPL/md4 lib/crypto/$CRYPTO_IMPL/md5
+         lib/crypto/$CRYPTO_IMPL/sha1 lib/crypto/$CRYPTO_IMPL/sha2
+ 	lib/crypto/$CRYPTO_IMPL/aes lib/crypto/$CRYPTO_IMPL/camellia
+diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin
+index e9435c693..6355e6540 100644
+--- a/src/include/krb5/krb5.hin
++++ b/src/include/krb5/krb5.hin
+@@ -426,8 +426,8 @@ typedef struct _krb5_crypto_iov {
+ #define ENCTYPE_DES_CBC_MD4     0x0002  /**< @deprecated no longer supported */
+ #define ENCTYPE_DES_CBC_MD5     0x0003  /**< @deprecated no longer supported */
+ #define ENCTYPE_DES_CBC_RAW     0x0004  /**< @deprecated no longer supported */
+-#define ENCTYPE_DES3_CBC_SHA    0x0005  /**< @deprecated DES-3 cbc with SHA1 */
+-#define ENCTYPE_DES3_CBC_RAW    0x0006  /**< @deprecated DES-3 cbc mode raw */
++#define ENCTYPE_DES3_CBC_SHA    0x0005  /**< @deprecated no longer supported */
++#define ENCTYPE_DES3_CBC_RAW    0x0006  /**< @deprecated no longer supported */
+ #define ENCTYPE_DES_HMAC_SHA1   0x0008  /**< @deprecated no longer supported */
+ /* PKINIT */
+ #define ENCTYPE_DSA_SHA1_CMS    0x0009  /**< DSA with SHA1, CMS signature */
+@@ -436,9 +436,9 @@ typedef struct _krb5_crypto_iov {
+ #define ENCTYPE_RC2_CBC_ENV     0x000c  /**< RC2 cbc mode, CMS enveloped data */
+ #define ENCTYPE_RSA_ENV         0x000d  /**< RSA encryption, CMS enveloped data */
+ #define ENCTYPE_RSA_ES_OAEP_ENV 0x000e  /**< RSA w/OEAP encryption, CMS enveloped data */
+-#define ENCTYPE_DES3_CBC_ENV    0x000f  /**< DES-3 cbc mode, CMS enveloped data */
++#define ENCTYPE_DES3_CBC_ENV    0x000f  /**< @deprecated no longer supported */
+ 
+-#define ENCTYPE_DES3_CBC_SHA1               0x0010
++#define ENCTYPE_DES3_CBC_SHA1               0x0010 /**< @deprecated removed */
+ #define ENCTYPE_AES128_CTS_HMAC_SHA1_96     0x0011 /**< RFC 3962 */
+ #define ENCTYPE_AES256_CTS_HMAC_SHA1_96     0x0012 /**< RFC 3962 */
+ #define ENCTYPE_AES128_CTS_HMAC_SHA256_128  0x0013 /**< RFC 8009 */
+@@ -458,7 +458,7 @@ typedef struct _krb5_crypto_iov {
+ #define CKSUMTYPE_RSA_MD5       0x0007
+ #define CKSUMTYPE_RSA_MD5_DES   0x0008
+ #define CKSUMTYPE_NIST_SHA      0x0009
+-#define CKSUMTYPE_HMAC_SHA1_DES3      0x000c
++#define CKSUMTYPE_HMAC_SHA1_DES3      0x000c /* @deprecated removed */
+ #define CKSUMTYPE_HMAC_SHA1_96_AES128 0x000f /**< RFC 3962. Used with
+                                                 ENCTYPE_AES128_CTS_HMAC_SHA1_96 */
+ #define CKSUMTYPE_HMAC_SHA1_96_AES256 0x0010 /**< RFC 3962. Used with
+diff --git a/src/kadmin/testing/proto/kdc.conf.proto b/src/kadmin/testing/proto/kdc.conf.proto
+index 8a4b87de1..d7f1d076b 100644
+--- a/src/kadmin/testing/proto/kdc.conf.proto
++++ b/src/kadmin/testing/proto/kdc.conf.proto
+@@ -11,6 +11,6 @@
+ 		dict_file = __K5ROOT__/ovsec_adm.dict
+ 		kadmind_port = 1751
+ 		kpasswd_port = 1752
+-		master_key_type = des3-hmac-sha1
+-		supported_enctypes = des3-hmac-sha1:normal aes256-cts:normal aes128-cts:normal aes256-sha2:normal aes128-sha2:normal
++		master_key_type = aes256-cts
++		supported_enctypes = aes256-cts:normal aes128-cts:normal aes256-sha2:normal aes128-sha2:normal
+ 	}
+diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
+index ba0ce0b71..e3352f9cc 100644
+--- a/src/kdc/kdc_util.c
++++ b/src/kdc/kdc_util.c
+@@ -1103,8 +1103,6 @@ enctype_name(krb5_enctype ktype, char *buf, size_t buflen)
+         name = "rsaEncryption-EnvOID";
+     else if (ktype == ENCTYPE_RSA_ES_OAEP_ENV)
+         name = "id-RSAES-OAEP-EnvOID";
+-    else if (ktype == ENCTYPE_DES3_CBC_ENV)
+-        name = "des-ede3-cbc-EnvOID";
+     else
+         return krb5_enctype_to_name(ktype, FALSE, buf, buflen);
+ 
+@@ -1826,8 +1824,6 @@ krb5_boolean
+ enctype_requires_etype_info_2(krb5_enctype enctype)
+ {
+     switch(enctype) {
+-    case ENCTYPE_DES3_CBC_SHA1:
+-    case ENCTYPE_DES3_CBC_RAW:
+     case ENCTYPE_ARCFOUR_HMAC:
+     case ENCTYPE_ARCFOUR_HMAC_EXP :
+         return 0;
+diff --git a/src/lib/crypto/Makefile.in b/src/lib/crypto/Makefile.in
+index c3fcfd7e8..890d54adf 100644
+--- a/src/lib/crypto/Makefile.in
++++ b/src/lib/crypto/Makefile.in
+@@ -13,7 +13,7 @@ STOBJLISTS=$(CRYPTO_IMPL)/enc_provider/OBJS.ST				\
+ 	$(CRYPTO_IMPL)/hash_provider/OBJS.ST				\
+ 	$(CRYPTO_IMPL)/md4/OBJS.ST $(CRYPTO_IMPL)/md5/OBJS.ST		\
+ 	$(CRYPTO_IMPL)/sha1/OBJS.ST $(CRYPTO_IMPL)/sha2/OBJS.ST		\
+-	$(CRYPTO_IMPL)/aes/OBJS.ST $(CRYPTO_IMPL)/des/OBJS.ST		\
++	$(CRYPTO_IMPL)/aes/OBJS.ST					\
+ 	$(CRYPTO_IMPL)/camellia/OBJS.ST krb/OBJS.ST			\
+ 	$(CRYPTO_IMPL)/OBJS.ST
+ 
+@@ -21,7 +21,7 @@ SUBDIROBJLISTS=$(CRYPTO_IMPL)/enc_provider/OBJS.ST			\
+ 	$(CRYPTO_IMPL)/hash_provider/OBJS.ST				\
+ 	$(CRYPTO_IMPL)/md4/OBJS.ST $(CRYPTO_IMPL)/md5/OBJS.ST		\
+ 	$(CRYPTO_IMPL)/sha1/OBJS.ST $(CRYPTO_IMPL)/sha2/OBJS.ST		\
+-	$(CRYPTO_IMPL)/aes/OBJS.ST $(CRYPTO_IMPL)/des/OBJS.ST		\
++	$(CRYPTO_IMPL)/aes/OBJS.ST					\
+ 	$(CRYPTO_IMPL)/camellia/OBJS.ST krb/OBJS.ST			\
+ 	$(CRYPTO_IMPL)/OBJS.ST
+ 
+@@ -34,8 +34,8 @@ SHLIB_EXPDEPLIBS= $(SUPPORT_DEPLIB)
+ SHLIB_LDFLAGS= $(LDFLAGS) @SHLIB_RPATH_DIRS@
+ 
+ ##DOS##LIBNAME=$(OUTPRE)crypto.lib
+-##DOS##OBJFILEDEP=$(OUTPRE)krb.lst $(OUTPRE)aes.lst $(OUTPRE)enc_provider.lst $(OUTPRE)des.lst $(OUTPRE)md5.lst $(OUTPRE)camellia.lst $(OUTPRE)md4.lst $(OUTPRE)hash_provider.lst $(OUTPRE)sha2.lst $(OUTPRE)sha1.lst $(OUTPRE)builtin.lst
+-##DOS##OBJFILELIST=@$(OUTPRE)krb.lst @$(OUTPRE)aes.lst @$(OUTPRE)enc_provider.lst @$(OUTPRE)des.lst @$(OUTPRE)md5.lst @$(OUTPRE)camellia.lst @$(OUTPRE)md4.lst @$(OUTPRE)hash_provider.lst @$(OUTPRE)sha2.lst @$(OUTPRE)sha1.lst @$(OUTPRE)builtin.lst
++##DOS##OBJFILEDEP=$(OUTPRE)krb.lst $(OUTPRE)aes.lst $(OUTPRE)enc_provider.lst $(OUTPRE)md5.lst $(OUTPRE)camellia.lst $(OUTPRE)md4.lst $(OUTPRE)hash_provider.lst $(OUTPRE)sha2.lst $(OUTPRE)sha1.lst $(OUTPRE)builtin.lst
++##DOS##OBJFILELIST=@$(OUTPRE)krb.lst @$(OUTPRE)aes.lst @$(OUTPRE)enc_provider.lst @$(OUTPRE)md5.lst @$(OUTPRE)camellia.lst @$(OUTPRE)md4.lst @$(OUTPRE)hash_provider.lst @$(OUTPRE)sha2.lst @$(OUTPRE)sha1.lst @$(OUTPRE)builtin.lst
+ 
+ all-unix: all-liblinks
+ install-unix: install-libs
+diff --git a/src/lib/crypto/builtin/Makefile.in b/src/lib/crypto/builtin/Makefile.in
+index baf5d974f..82adf1dec 100644
+--- a/src/lib/crypto/builtin/Makefile.in
++++ b/src/lib/crypto/builtin/Makefile.in
+@@ -1,6 +1,6 @@
+ mydir=lib$(S)crypto$(S)builtin
+ BUILDTOP=$(REL)..$(S)..$(S)..
+-SUBDIRS=camellia des aes md4 md5 sha1 sha2 enc_provider hash_provider
++SUBDIRS=camellia aes md4 md5 sha1 sha2 enc_provider hash_provider
+ LOCALINCLUDES = -I$(srcdir)/../krb -I$(srcdir)
+ 
+ ##DOS##BUILDTOP = ..\..\..
+@@ -22,7 +22,7 @@ SRCS=\
+ 	$(srcdir)/init.c	\
+ 	$(srcdir)/pbkdf2.c	
+ 
+-STOBJLISTS= des/OBJS.ST md4/OBJS.ST 	\
++STOBJLISTS= md4/OBJS.ST 		\
+ 	md5/OBJS.ST sha1/OBJS.ST sha2/OBJS.ST	\
+ 	enc_provider/OBJS.ST 		\
+ 	hash_provider/OBJS.ST 		\
+@@ -30,7 +30,7 @@ STOBJLISTS= des/OBJS.ST md4/OBJS.ST 	\
+ 	camellia/OBJS.ST 		\
+ 	OBJS.ST
+ 
+-SUBDIROBJLISTS= des/OBJS.ST md4/OBJS.ST 	\
++SUBDIROBJLISTS= md4/OBJS.ST	 	\
+ 		md5/OBJS.ST sha1/OBJS.ST sha2/OBJS.ST 	\
+ 		enc_provider/OBJS.ST 		\
+ 		hash_provider/OBJS.ST 		\
+diff --git a/src/lib/crypto/builtin/des/ISSUES b/src/lib/crypto/builtin/des/ISSUES
+deleted file mode 100644
+index 157891103..000000000
+--- a/src/lib/crypto/builtin/des/ISSUES
++++ /dev/null
+@@ -1,13 +0,0 @@
+-Issues to be addressed for src/lib/crypto/des: -*- text -*-
+-
+-
+-"const" could be used in more places
+-
+-
+-Array types are used in calling interfaces.  Under ANSI C, a value of
+-type "arraytype *" cannot be assigned to a variable of type "const
+-arraytype *", so we get compilation warnings.
+-
+-Possible fix: Rewrite internal interfaces to not use arrays this way.
+-Provide external routines compatible with old API, but not using
+-const?
+diff --git a/src/lib/crypto/builtin/des/Makefile.in b/src/lib/crypto/builtin/des/Makefile.in
+deleted file mode 100644
+index ed25dab7c..000000000
+--- a/src/lib/crypto/builtin/des/Makefile.in
++++ /dev/null
+@@ -1,80 +0,0 @@
+-mydir=lib$(S)crypto$(S)builtin$(S)des
+-BUILDTOP=$(REL)..$(S)..$(S)..$(S)..
+-LOCALINCLUDES = -I$(srcdir)/.. -I$(srcdir)/../../krb
+-
+-##DOS##BUILDTOP = ..\..\..\..
+-##DOS##PREFIXDIR = builtin\des
+-##DOS##OBJFILE = ..\..\$(OUTPRE)des.lst
+-
+-STLIBOBJS=\
+-	d3_aead.o	\
+-	d3_kysched.o	\
+-	des_keys.o	\
+-	f_aead.o 	\
+-	f_cksum.o	\
+-	f_parity.o 	\
+-	f_sched.o 	\
+-	f_tables.o	\
+-	key_sched.o	\
+-	weak_key.o
+-
+-OBJS=	$(OUTPRE)d3_aead.$(OBJEXT)	\
+-	$(OUTPRE)d3_kysched.$(OBJEXT)	\
+-	$(OUTPRE)des_keys.$(OBJEXT)	\
+-	$(OUTPRE)f_aead.$(OBJEXT) 	\
+-	$(OUTPRE)f_cksum.$(OBJEXT)	\
+-	$(OUTPRE)f_parity.$(OBJEXT) 	\
+-	$(OUTPRE)f_sched.$(OBJEXT) 	\
+-	$(OUTPRE)f_tables.$(OBJEXT)	\
+-	$(OUTPRE)key_sched.$(OBJEXT)	\
+-	$(OUTPRE)weak_key.$(OBJEXT)
+-
+-SRCS=	$(srcdir)/d3_aead.c	\
+-	$(srcdir)/d3_kysched.c	\
+-	$(srcdir)/des_keys.c	\
+-	$(srcdir)/f_aead.c	\
+-	$(srcdir)/f_cksum.c	\
+-	$(srcdir)/f_parity.c	\
+-	$(srcdir)/f_sched.c	\
+-	$(srcdir)/f_tables.c	\
+-	$(srcdir)/key_sched.c	\
+-	$(srcdir)/weak_key.c
+-
+-EXTRADEPSRCS = $(srcdir)/destest.c $(srcdir)/f_cbc.c $(srcdir)/t_verify.c
+-
+-##DOS##LIBOBJS = $(OBJS)
+-
+-TOBJS = $(OUTPRE)key_sched.$(OBJEXT) $(OUTPRE)f_sched.$(OBJEXT) \
+-	$(OUTPRE)f_cbc.$(OBJEXT) $(OUTPRE)f_tables.$(OBJEXT) \
+-	$(OUTPRE)f_cksum.$(OBJEXT)
+-
+-verify$(EXEEXT): t_verify.$(OBJEXT) $(TOBJS) f_parity.$(OBJEXT) \
+-	$(COM_ERR_DEPLIB) $(SUPPORT_DEPLIB)
+-	$(CC_LINK) -o $@ t_verify.$(OBJEXT) $(TOBJS) f_parity.$(OBJEXT) \
+-		-lcom_err $(SUPPORT_LIB)
+-
+-destest$(EXEEXT): destest.$(OBJEXT) $(TOBJS) $(SUPPORT_DEPLIB)
+-	$(CC_LINK) -o $@ destest.$(OBJEXT) $(TOBJS) $(SUPPORT_LIB)
+-
+-all-unix: all-libobjs
+-
+-check-unix: verify destest
+-	$(RUN_TEST) ./verify -z
+-	$(RUN_TEST) ./verify -m
+-	$(RUN_TEST) ./verify
+-	$(RUN_TEST) ./destest < $(srcdir)/keytest.data
+-
+-includes: depend
+-
+-depend: $(SRCS)
+-
+-check-windows:
+-
+-clean:
+-	$(RM) destest.$(OBJEXT) destest$(EXEEXT) verify$(EXEEXT) \
+-	t_verify.$(OBJEXT) $(TOBJS)
+-
+-clean-unix:: clean-libobjs
+-
+-@libobj_frag@
+-
+diff --git a/src/lib/crypto/builtin/des/d3_aead.c b/src/lib/crypto/builtin/des/d3_aead.c
+deleted file mode 100644
+index bddf75a47..000000000
+--- a/src/lib/crypto/builtin/des/d3_aead.c
++++ /dev/null
+@@ -1,133 +0,0 @@
+-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+-/*
+- * Copyright (C) 2008 by the Massachusetts Institute of Technology.
+- * Copyright 1995 by Richard P. Basch.  All Rights Reserved.
+- * Copyright 1995 by Lehman Brothers, Inc.  All Rights Reserved.
+- *
+- * Export of this software from the United States of America may
+- *   require a specific license from the United States Government.
+- *   It is the responsibility of any person or organization contemplating
+- *   export to obtain such a license before exporting.
+- *
+- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+- * distribute this software and its documentation for any purpose and
+- * without fee is hereby granted, provided that the above copyright
+- * notice appear in all copies and that both that copyright notice and
+- * this permission notice appear in supporting documentation, and that
+- * the name of Richard P. Basch, Lehman Brothers and M.I.T. not be used
+- * in advertising or publicity pertaining to distribution of the software
+- * without specific, written prior permission.  Richard P. Basch,
+- * Lehman Brothers and M.I.T. make no representations about the suitability
+- * of this software for any purpose.  It is provided "as is" without
+- * express or implied warranty.
+- */
+-
+-#include "crypto_int.h"
+-#include "des_int.h"
+-#include "f_tables.h"
+-
+-void
+-krb5int_des3_cbc_encrypt(krb5_crypto_iov *data, unsigned long num_data,
+-                         const mit_des_key_schedule ks1,
+-                         const mit_des_key_schedule ks2,
+-                         const mit_des_key_schedule ks3,
+-                         mit_des_cblock ivec)
+-{
+-    unsigned DES_INT32 left, right;
+-    const unsigned DES_INT32 *kp1, *kp2, *kp3;
+-    const unsigned char *ip;
+-    struct iov_cursor cursor;
+-    unsigned char block[MIT_DES_BLOCK_LENGTH];
+-
+-    /* Get key pointers here.  These won't need to be reinitialized. */
+-    kp1 = (const unsigned DES_INT32 *)ks1;
+-    kp2 = (const unsigned DES_INT32 *)ks2;
+-    kp3 = (const unsigned DES_INT32 *)ks3;
+-
+-    /* Initialize left and right with the contents of the initial vector. */
+-    ip = (ivec != NULL) ? ivec : mit_des_zeroblock;
+-    left = load_32_be(ip);
+-    right = load_32_be(ip + 4);
+-
+-    k5_iov_cursor_init(&cursor, data, num_data, MIT_DES_BLOCK_LENGTH, FALSE);
+-    while (k5_iov_cursor_get(&cursor, block)) {
+-        /* xor this block with the previous ciphertext. */
+-        left ^= load_32_be(block);
+-        right ^= load_32_be(block + 4);
+-
+-        /* Encrypt what we have and store it back into block. */
+-        DES_DO_ENCRYPT(left, right, kp1);
+-        DES_DO_DECRYPT(left, right, kp2);
+-        DES_DO_ENCRYPT(left, right, kp3);
+-        store_32_be(left, block);
+-        store_32_be(right, block + 4);
+-
+-        k5_iov_cursor_put(&cursor, block);
+-    }
+-
+-    if (ivec != NULL) {
+-        store_32_be(left, ivec);
+-        store_32_be(right, ivec + 4);
+-    }
+-}
+-
+-void
+-krb5int_des3_cbc_decrypt(krb5_crypto_iov *data, unsigned long num_data,
+-                         const mit_des_key_schedule ks1,
+-                         const mit_des_key_schedule ks2,
+-                         const mit_des_key_schedule ks3,
+-                         mit_des_cblock ivec)
+-{
+-    unsigned DES_INT32 left, right;
+-    const unsigned DES_INT32 *kp1, *kp2, *kp3;
+-    const unsigned char *ip;
+-    unsigned DES_INT32 ocipherl, ocipherr;
+-    unsigned DES_INT32 cipherl, cipherr;
+-    struct iov_cursor cursor;
+-    unsigned char block[MIT_DES_BLOCK_LENGTH];
+-
+-    /* Get key pointers here.  These won't need to be reinitialized. */
+-    kp1 = (const unsigned DES_INT32 *)ks1;
+-    kp2 = (const unsigned DES_INT32 *)ks2;
+-    kp3 = (const unsigned DES_INT32 *)ks3;
+-
+-    /*
+-     * Decrypting is harder than encrypting because of
+-     * the necessity of remembering a lot more things.
+-     * Should think about this a little more...
+-     */
+-
+-    /* Prime the old cipher with ivec.*/
+-    ip = (ivec != NULL) ? ivec : mit_des_zeroblock;
+-    ocipherl = load_32_be(ip);
+-    ocipherr = load_32_be(ip + 4);
+-
+-    k5_iov_cursor_init(&cursor, data, num_data, MIT_DES_BLOCK_LENGTH, FALSE);
+-    while (k5_iov_cursor_get(&cursor, block)) {
+-        /* Split this block into left and right. */
+-        cipherl = left = load_32_be(block);
+-        cipherr = right = load_32_be(block + 4);
+-
+-        /* Decrypt and xor with the old cipher to get plain text. */
+-        DES_DO_DECRYPT(left, right, kp3);
+-        DES_DO_ENCRYPT(left, right, kp2);
+-        DES_DO_DECRYPT(left, right, kp1);
+-        left ^= ocipherl;
+-        right ^= ocipherr;
+-
+-        /* Store the encrypted halves back into block. */
+-        store_32_be(left, block);
+-        store_32_be(right, block + 4);
+-
+-        /* Save current cipher block halves. */
+-        ocipherl = cipherl;
+-        ocipherr = cipherr;
+-
+-        k5_iov_cursor_put(&cursor, block);
+-    }
+-
+-    if (ivec != NULL) {
+-        store_32_be(ocipherl, ivec);
+-        store_32_be(ocipherr, ivec + 4);
+-    }
+-}
+diff --git a/src/lib/crypto/builtin/des/d3_kysched.c b/src/lib/crypto/builtin/des/d3_kysched.c
+deleted file mode 100644
+index ebd1050b1..000000000
+--- a/src/lib/crypto/builtin/des/d3_kysched.c
++++ /dev/null
+@@ -1,51 +0,0 @@
+-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+-/*
+- * Copyright 1995 by Richard P. Basch.  All Rights Reserved.
+- * Copyright 1995 by Lehman Brothers, Inc.  All Rights Reserved.
+- *
+- * Export of this software from the United States of America may
+- *   require a specific license from the United States Government.
+- *   It is the responsibility of any person or organization contemplating
+- *   export to obtain such a license before exporting.
+- *
+- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+- * distribute this software and its documentation for any purpose and
+- * without fee is hereby granted, provided that the above copyright
+- * notice appear in all copies and that both that copyright notice and
+- * this permission notice appear in supporting documentation, and that
+- * the name of Richard P. Basch, Lehman Brothers and M.I.T. not be used
+- * in advertising or publicity pertaining to distribution of the software
+- * without specific, written prior permission.  Richard P. Basch,
+- * Lehman Brothers and M.I.T. make no representations about the suitability
+- * of this software for any purpose.  It is provided "as is" without
+- * express or implied warranty.
+- */
+-
+-#include "k5-int.h"
+-#include "des_int.h"
+-
+-int
+-mit_des3_key_sched(mit_des3_cblock k, mit_des3_key_schedule schedule)
+-{
+-    mit_des_make_key_sched(k[0],schedule[0]);
+-    mit_des_make_key_sched(k[1],schedule[1]);
+-    mit_des_make_key_sched(k[2],schedule[2]);
+-
+-    if (!mit_des_check_key_parity(k[0]))        /* bad parity --> return -1 */
+-        return(-1);
+-    if (mit_des_is_weak_key(k[0]))
+-        return(-2);
+-
+-    if (!mit_des_check_key_parity(k[1]))
+-        return(-1);
+-    if (mit_des_is_weak_key(k[1]))
+-        return(-2);
+-
+-    if (!mit_des_check_key_parity(k[2]))
+-        return(-1);
+-    if (mit_des_is_weak_key(k[2]))
+-        return(-2);
+-
+-    /* if key was good, return 0 */
+-    return 0;
+-}
+diff --git a/src/lib/crypto/builtin/des/deps b/src/lib/crypto/builtin/des/deps
+deleted file mode 100644
+index df2a31dac..000000000
+--- a/src/lib/crypto/builtin/des/deps
++++ /dev/null
+@@ -1,148 +0,0 @@
+-#
+-# Generated makefile dependencies follow.
+-#
+-d3_aead.so d3_aead.po $(OUTPRE)d3_aead.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+-  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+-  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h \
+-  $(srcdir)/../aes/aes.h $(srcdir)/../crypto_mod.h $(srcdir)/../sha2/sha2.h \
+-  $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+-  $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+-  $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+-  $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+-  $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+-  $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+-  $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+-  d3_aead.c des_int.h f_tables.h
+-d3_kysched.so d3_kysched.po $(OUTPRE)d3_kysched.$(OBJEXT): \
+-  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+-  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+-  $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+-  $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+-  $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+-  $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+-  $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+-  $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+-  $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+-  d3_kysched.c des_int.h
+-des_keys.so des_keys.po $(OUTPRE)des_keys.$(OBJEXT): \
+-  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+-  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+-  $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h $(srcdir)/../aes/aes.h \
+-  $(srcdir)/../crypto_mod.h $(srcdir)/../sha2/sha2.h \
+-  $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+-  $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+-  $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+-  $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+-  $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+-  $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+-  $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+-  des_int.h des_keys.c
+-f_aead.so f_aead.po $(OUTPRE)f_aead.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+-  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+-  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h \
+-  $(srcdir)/../aes/aes.h $(srcdir)/../crypto_mod.h $(srcdir)/../sha2/sha2.h \
+-  $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+-  $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+-  $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+-  $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+-  $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+-  $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+-  $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+-  des_int.h f_aead.c f_tables.h
+-f_cksum.so f_cksum.po $(OUTPRE)f_cksum.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+-  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+-  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \
+-  $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+-  $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+-  $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+-  $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+-  $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+-  $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+-  $(top_srcdir)/include/socket-utils.h des_int.h f_cksum.c \
+-  f_tables.h
+-f_parity.so f_parity.po $(OUTPRE)f_parity.$(OBJEXT): \
+-  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+-  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+-  $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+-  $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+-  $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+-  $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+-  $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+-  $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+-  $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+-  des_int.h f_parity.c
+-f_sched.so f_sched.po $(OUTPRE)f_sched.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+-  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+-  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \
+-  $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+-  $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+-  $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+-  $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+-  $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+-  $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+-  $(top_srcdir)/include/socket-utils.h des_int.h f_sched.c
+-f_tables.so f_tables.po $(OUTPRE)f_tables.$(OBJEXT): \
+-  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+-  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+-  $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+-  $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+-  $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+-  $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+-  $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+-  $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+-  $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+-  des_int.h f_tables.c f_tables.h
+-key_sched.so key_sched.po $(OUTPRE)key_sched.$(OBJEXT): \
+-  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+-  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+-  $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+-  $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+-  $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+-  $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+-  $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+-  $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+-  $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+-  des_int.h key_sched.c
+-weak_key.so weak_key.po $(OUTPRE)weak_key.$(OBJEXT): \
+-  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+-  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+-  $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+-  $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+-  $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+-  $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+-  $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+-  $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+-  $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+-  des_int.h weak_key.c
+-destest.so destest.po $(OUTPRE)destest.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+-  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+-  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \
+-  $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+-  $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+-  $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+-  $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+-  $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+-  $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+-  $(top_srcdir)/include/socket-utils.h des_int.h destest.c
+-f_cbc.so f_cbc.po $(OUTPRE)f_cbc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+-  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+-  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \
+-  $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+-  $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+-  $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+-  $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+-  $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+-  $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+-  $(top_srcdir)/include/socket-utils.h des_int.h f_cbc.c \
+-  f_tables.h
+-t_verify.so t_verify.po $(OUTPRE)t_verify.$(OBJEXT): \
+-  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+-  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+-  $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+-  $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+-  $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+-  $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+-  $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+-  $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+-  $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+-  des_int.h t_verify.c
+diff --git a/src/lib/crypto/builtin/des/des_int.h b/src/lib/crypto/builtin/des/des_int.h
+deleted file mode 100644
+index f8dc6b296..000000000
+--- a/src/lib/crypto/builtin/des/des_int.h
++++ /dev/null
+@@ -1,285 +0,0 @@
+-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+-/* lib/crypto/builtin/des/des_int.h */
+-/*
+- * Copyright 1987, 1988, 1990, 2002 by the Massachusetts Institute of
+- * Technology.  All Rights Reserved.
+- *
+- * Export of this software from the United States of America may
+- *   require a specific license from the United States Government.
+- *   It is the responsibility of any person or organization contemplating
+- *   export to obtain such a license before exporting.
+- *
+- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+- * distribute this software and its documentation for any purpose and
+- * without fee is hereby granted, provided that the above copyright
+- * notice appear in all copies and that both that copyright notice and
+- * this permission notice appear in supporting documentation, and that
+- * the name of M.I.T. not be used in advertising or publicity pertaining
+- * to distribution of the software without specific, written prior
+- * permission.  Furthermore if you modify this software you must label
+- * your software as modified software and not distribute it in such a
+- * fashion that it might be confused with the original M.I.T. software.
+- * M.I.T. makes no representations about the suitability of
+- * this software for any purpose.  It is provided "as is" without express
+- * or implied warranty.
+- */
+-/*
+- * Copyright (C) 1998 by the FundsXpress, INC.
+- *
+- * All rights reserved.
+- *
+- * Export of this software from the United States of America may require
+- * a specific license from the United States Government.  It is the
+- * responsibility of any person or organization contemplating export to
+- * obtain such a license before exporting.
+- *
+- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+- * distribute this software and its documentation for any purpose and
+- * without fee is hereby granted, provided that the above copyright
+- * notice appear in all copies and that both that copyright notice and
+- * this permission notice appear in supporting documentation, and that
+- * the name of FundsXpress. not be used in advertising or publicity pertaining
+- * to distribution of the software without specific, written prior
+- * permission.  FundsXpress makes no representations about the suitability of
+- * this software for any purpose.  It is provided "as is" without express
+- * or implied warranty.
+- *
+- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+- */
+-
+-/* Private include file for the Data Encryption Standard library. */
+-
+-/* only do the whole thing once  */
+-#ifndef DES_INTERNAL_DEFS
+-#define DES_INTERNAL_DEFS
+-
+-#include "k5-int.h"
+-/*
+- * Begin "mit-des.h"
+- */
+-#ifndef KRB5_MIT_DES__
+-#define KRB5_MIT_DES__
+-
+-#if defined(__MACH__) && defined(__APPLE__)
+-#include <TargetConditionals.h>
+-#include <AvailabilityMacros.h>
+-#if TARGET_RT_MAC_CFM
+-#error "Use KfM 4.0 SDK headers for CFM compilation."
+-#endif
+-#if defined(DEPRECATED_IN_MAC_OS_X_VERSION_10_5) && !defined(KRB5_SUPRESS_DEPRECATED_WARNINGS)
+-#define KRB5INT_DES_DEPRECATED DEPRECATED_IN_MAC_OS_X_VERSION_10_5
+-#endif
+-#endif /* defined(__MACH__) && defined(__APPLE__) */
+-
+-/* Macro to add deprecated attribute to DES types and functions */
+-/* Currently only defined on macOS 10.5 and later.              */
+-#ifndef KRB5INT_DES_DEPRECATED
+-#define KRB5INT_DES_DEPRECATED
+-#endif
+-
+-#include <limits.h>
+-
+-#if UINT_MAX >= 0xFFFFFFFFUL
+-#define DES_INT32 int
+-#define DES_UINT32 unsigned int
+-#else
+-#define DES_INT32 long
+-#define DES_UINT32 unsigned long
+-#endif
+-
+-typedef unsigned char des_cblock[8]     /* crypto-block size */
+-KRB5INT_DES_DEPRECATED;
+-
+-/*
+- * Key schedule.
+- *
+- * This used to be
+- *
+- * typedef struct des_ks_struct {
+- *     union { DES_INT32 pad; des_cblock _;} __;
+- * } des_key_schedule[16];
+- *
+- * but it would cause trouble if DES_INT32 were ever more than 4
+- * bytes.  The reason is that all the encryption functions cast it to
+- * (DES_INT32 *), and treat it as if it were DES_INT32[32].  If
+- * 2*sizeof(DES_INT32) is ever more than sizeof(des_cblock), the
+- * caller-allocated des_key_schedule will be overflowed by the key
+- * scheduling functions.  We can't assume that every platform will
+- * have an exact 32-bit int, and nothing should be looking inside a
+- * des_key_schedule anyway.
+- */
+-typedef struct des_ks_struct {  DES_INT32 _[2]; } des_key_schedule[16]
+-KRB5INT_DES_DEPRECATED;
+-
+-typedef des_cblock mit_des_cblock;
+-typedef des_key_schedule mit_des_key_schedule;
+-
+-/* Triple-DES structures */
+-typedef mit_des_cblock          mit_des3_cblock[3];
+-typedef mit_des_key_schedule    mit_des3_key_schedule[3];
+-
+-#define MIT_DES_ENCRYPT 1
+-#define MIT_DES_DECRYPT 0
+-
+-typedef struct mit_des_ran_key_seed {
+-    krb5_encrypt_block eblock;
+-    krb5_data sequence;
+-} mit_des_random_state;
+-
+-/* the first byte of the key is already in the keyblock */
+-
+-#define MIT_DES_BLOCK_LENGTH            (8*sizeof(krb5_octet))
+-/* This used to be 8*sizeof(krb5_octet) */
+-#define MIT_DES_KEYSIZE                 8
+-
+-#define MIT_DES_CBC_CKSUM_LENGTH        (4*sizeof(krb5_octet))
+-
+-#endif /* KRB5_MIT_DES__ */
+-/*
+- * End "mit-des.h"
+- */
+-
+-/* afsstring2key.c */
+-krb5_error_code mit_afs_string_to_key(krb5_keyblock *keyblock,
+-                                      const krb5_data *data,
+-                                      const krb5_data *salt);
+-char *mit_afs_crypt(const char *pw, const char *salt, char *iobuf);
+-
+-/* f_cksum.c */
+-unsigned long mit_des_cbc_cksum(const krb5_octet *, krb5_octet *,
+-                                unsigned long, const mit_des_key_schedule,
+-                                const krb5_octet *);
+-
+-/* f_cbc.c (used by test programs) */
+-int
+-mit_des_cbc_encrypt(const mit_des_cblock *in, mit_des_cblock *out,
+-                    unsigned long length, const mit_des_key_schedule schedule,
+-                    const mit_des_cblock ivec, int enc);
+-
+-#define mit_des_zeroblock krb5int_c_mit_des_zeroblock
+-extern const mit_des_cblock mit_des_zeroblock;
+-
+-/* fin_rndkey.c */
+-krb5_error_code mit_des_finish_random_key(const krb5_encrypt_block *,
+-                                          krb5_pointer *);
+-
+-/* finish_key.c */
+-krb5_error_code mit_des_finish_key(krb5_encrypt_block *);
+-
+-/* init_rkey.c */
+-krb5_error_code mit_des_init_random_key(const krb5_encrypt_block *,
+-                                        const krb5_keyblock *,
+-                                        krb5_pointer *);
+-
+-/* key_parity.c */
+-void mit_des_fixup_key_parity(mit_des_cblock);
+-int mit_des_check_key_parity(mit_des_cblock);
+-
+-/* key_sched.c */
+-int mit_des_key_sched(mit_des_cblock, mit_des_key_schedule);
+-
+-/* process_ky.c */
+-krb5_error_code mit_des_process_key(krb5_encrypt_block *,
+-                                    const krb5_keyblock *);
+-
+-/* random_key.c */
+-krb5_error_code mit_des_random_key(const krb5_encrypt_block *,
+-                                   krb5_pointer, krb5_keyblock **);
+-
+-/* string2key.c */
+-krb5_error_code mit_des_string_to_key(const krb5_encrypt_block *,
+-                                      krb5_keyblock *, const krb5_data *,
+-                                      const krb5_data *);
+-krb5_error_code mit_des_string_to_key_int(krb5_keyblock *, const krb5_data *,
+-                                          const krb5_data *);
+-
+-/* weak_key.c */
+-int mit_des_is_weak_key(mit_des_cblock);
+-
+-/* cmb_keys.c */
+-krb5_error_code mit_des_combine_subkeys(const krb5_keyblock *,
+-                                        const krb5_keyblock *,
+-                                        krb5_keyblock **);
+-
+-/* f_pcbc.c */
+-int mit_des_pcbc_encrypt();
+-
+-/* f_sched.c */
+-int mit_des_make_key_sched(mit_des_cblock, mit_des_key_schedule);
+-
+-
+-/* misc.c */
+-extern void swap_bits(char *);
+-extern unsigned long long_swap_bits(unsigned long);
+-extern unsigned long swap_six_bits_to_ansi(unsigned long);
+-extern unsigned long swap_four_bits_to_ansi(unsigned long);
+-extern unsigned long swap_bit_pos_1(unsigned long);
+-extern unsigned long swap_bit_pos_0(unsigned long);
+-extern unsigned long swap_bit_pos_0_to_ansi(unsigned long);
+-extern unsigned long rev_swap_bit_pos_0(unsigned long);
+-extern unsigned long swap_byte_bits(unsigned long);
+-extern unsigned long swap_long_bytes_bit_number(unsigned long);
+-#ifdef FILE
+-/* XXX depends on FILE being a #define! */
+-extern void test_set(FILE *, const char *, int, const char *, int);
+-#endif
+-
+-void
+-krb5int_des3_cbc_encrypt(krb5_crypto_iov *data, unsigned long num_data,
+-                         const mit_des_key_schedule ks1,
+-                         const mit_des_key_schedule ks2,
+-                         const mit_des_key_schedule ks3,
+-                         mit_des_cblock ivec);
+-
+-void
+-krb5int_des3_cbc_decrypt(krb5_crypto_iov *data, unsigned long num_data,
+-                         const mit_des_key_schedule ks1,
+-                         const mit_des_key_schedule ks2,
+-                         const mit_des_key_schedule ks3,
+-                         mit_des_cblock ivec);
+-
+-void
+-krb5int_des_cbc_encrypt(krb5_crypto_iov *data, unsigned long num_data,
+-                        const mit_des_key_schedule schedule,
+-                        mit_des_cblock ivec);
+-
+-void
+-krb5int_des_cbc_decrypt(krb5_crypto_iov *data, unsigned long num_data,
+-                        const mit_des_key_schedule schedule,
+-                        mit_des_cblock ivec);
+-
+-void
+-krb5int_des_cbc_mac(const krb5_crypto_iov *data, unsigned long num_data,
+-                    const mit_des_key_schedule schedule, mit_des_cblock ivec,
+-                    mit_des_cblock out);
+-
+-/* d3_procky.c */
+-krb5_error_code mit_des3_process_key(krb5_encrypt_block *eblock,
+-                                     const krb5_keyblock *keyblock);
+-
+-/* d3_kysched.c */
+-int mit_des3_key_sched(mit_des3_cblock key, mit_des3_key_schedule schedule);
+-
+-/* d3_str2ky.c */
+-krb5_error_code mit_des3_string_to_key(const krb5_encrypt_block *eblock,
+-                                       krb5_keyblock *keyblock,
+-                                       const krb5_data *data,
+-                                       const krb5_data *salt);
+-
+-/* u_nfold.c */
+-krb5_error_code mit_des_n_fold(const krb5_octet *input, const size_t in_len,
+-                               krb5_octet *output, const size_t out_len);
+-
+-/* u_rn_key.c */
+-int mit_des_is_weak_keyblock(krb5_keyblock *keyblock);
+-
+-void mit_des_fixup_keyblock_parity(krb5_keyblock *keyblock);
+-
+-krb5_error_code mit_des_set_random_generator_seed(const krb5_data *seed,
+-                                                  krb5_pointer random_state);
+-
+-krb5_error_code mit_des_set_random_sequence_number(const krb5_data *sequence,
+-                                                   krb5_pointer random_state);
+-#endif  /*DES_INTERNAL_DEFS*/
+diff --git a/src/lib/crypto/builtin/des/des_keys.c b/src/lib/crypto/builtin/des/des_keys.c
+deleted file mode 100644
+index 32b119aad..000000000
+--- a/src/lib/crypto/builtin/des/des_keys.c
++++ /dev/null
+@@ -1,40 +0,0 @@
+-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+-/* lib/crypto/builtin/des/des_keys.c - Key functions used by Kerberos code */
+-/*
+- * Copyright (C) 2011 by the Massachusetts Institute of Technology.
+- * All rights reserved.
+- *
+- * Export of this software from the United States of America may
+- *   require a specific license from the United States Government.
+- *   It is the responsibility of any person or organization contemplating
+- *   export to obtain such a license before exporting.
+- *
+- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+- * distribute this software and its documentation for any purpose and
+- * without fee is hereby granted, provided that the above copyright
+- * notice appear in all copies and that both that copyright notice and
+- * this permission notice appear in supporting documentation, and that
+- * the name of M.I.T. not be used in advertising or publicity pertaining
+- * to distribution of the software without specific, written prior
+- * permission.  Furthermore if you modify this software you must label
+- * your software as modified software and not distribute it in such a
+- * fashion that it might be confused with the original M.I.T. software.
+- * M.I.T. makes no representations about the suitability of
+- * this software for any purpose.  It is provided "as is" without express
+- * or implied warranty.
+- */
+-
+-#include "crypto_int.h"
+-#include "des_int.h"
+-
+-void
+-k5_des_fixup_key_parity(unsigned char *keybits)
+-{
+-    mit_des_fixup_key_parity(keybits);
+-}
+-
+-krb5_boolean
+-k5_des_is_weak_key(unsigned char *keybits)
+-{
+-    return mit_des_is_weak_key(keybits);
+-}
+diff --git a/src/lib/crypto/builtin/des/destest.c b/src/lib/crypto/builtin/des/destest.c
+deleted file mode 100644
+index 52114304e..000000000
+--- a/src/lib/crypto/builtin/des/destest.c
++++ /dev/null
+@@ -1,240 +0,0 @@
+-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+-/* lib/crypto/builtin/des/destest.c */
+-/*
+- * Copyright 1990,1991 by the Massachusetts Institute of Technology.
+- * All Rights Reserved.
+- *
+- * Export of this software from the United States of America may
+- *   require a specific license from the United States Government.
+- *   It is the responsibility of any person or organization contemplating
+- *   export to obtain such a license before exporting.
+- *
+- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+- * distribute this software and its documentation for any purpose and
+- * without fee is hereby granted, provided that the above copyright
+- * notice appear in all copies and that both that copyright notice and
+- * this permission notice appear in supporting documentation, and that
+- * the name of M.I.T. not be used in advertising or publicity pertaining
+- * to distribution of the software without specific, written prior
+- * permission.  Furthermore if you modify this software you must label
+- * your software as modified software and not distribute it in such a
+- * fashion that it might be confused with the original M.I.T. software.
+- * M.I.T. makes no representations about the suitability of
+- * this software for any purpose.  It is provided "as is" without express
+- * or implied warranty.
+- */
+-/*
+- * Copyright (C) 1998 by the FundsXpress, INC.
+- *
+- * All rights reserved.
+- *
+- * Export of this software from the United States of America may require
+- * a specific license from the United States Government.  It is the
+- * responsibility of any person or organization contemplating export to
+- * obtain such a license before exporting.
+- *
+- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+- * distribute this software and its documentation for any purpose and
+- * without fee is hereby granted, provided that the above copyright
+- * notice appear in all copies and that both that copyright notice and
+- * this permission notice appear in supporting documentation, and that
+- * the name of FundsXpress. not be used in advertising or publicity pertaining
+- * to distribution of the software without specific, written prior
+- * permission.  FundsXpress makes no representations about the suitability of
+- * this software for any purpose.  It is provided "as is" without express
+- * or implied warranty.
+- *
+- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+- */
+-
+-/* Test a DES implementation against known inputs & outputs. */
+-
+-#include "des_int.h"
+-#include <ctype.h>
+-#include <stdio.h>
+-
+-void convert (char *, unsigned char []);
+-
+-void des_cblock_print_file (mit_des_cblock, FILE *);
+-
+-krb5_octet zeroblock[8] = {0,0,0,0,0,0,0,0};
+-
+-int
+-main(argc, argv)
+-    int argc;
+-    char *argv[];
+-{
+-    char block1[17], block2[17], block3[17];
+-    /* Force tests of unaligned accesses.  */
+-    union { unsigned char c[8*4+3]; long l; } u;
+-    unsigned char *ioblocks = u.c;
+-    unsigned char *input = ioblocks+1;
+-    unsigned char *output = ioblocks+10;
+-    unsigned char *output2 = ioblocks+19;
+-    unsigned char *key = ioblocks+27;
+-    mit_des_key_schedule sched;
+-    int num = 0;
+-    int retval;
+-
+-    int error = 0;
+-
+-    while (scanf("%16s %16s %16s", block1, block2, block3) == 3) {
+-        convert(block1, key);
+-        convert(block2, input);
+-        convert(block3, output);
+-
+-        retval = mit_des_key_sched(key, sched);
+-        if (retval) {
+-            fprintf(stderr, "des test: can't process key: %d\n", retval);
+-            fprintf(stderr, "des test: %s %s %s\n", block1, block2, block3);
+-            exit(1);
+-        }
+-        mit_des_cbc_encrypt((const mit_des_cblock *) input,
+-                            (mit_des_cblock *) output2, 8,
+-                            sched, zeroblock, 1);
+-
+-        if (memcmp((char *)output2, (char *)output, 8)) {
+-            fprintf(stderr,
+-                    "DES ENCRYPT ERROR, key %s, text %s, real cipher %s, computed cyphertext %02X%02X%02X%02X%02X%02X%02X%02X\n",
+-                    block1, block2, block3,
+-                    output2[0],output2[1],output2[2],output2[3],
+-                    output2[4],output2[5],output2[6],output2[7]);
+-            error++;
+-        }
+-
+-        /*
+-         * Now try decrypting....
+-         */
+-        mit_des_cbc_encrypt((const mit_des_cblock *) output,
+-                            (mit_des_cblock *) output2, 8,
+-                            sched, zeroblock, 0);
+-
+-        if (memcmp((char *)output2, (char *)input, 8)) {
+-            fprintf(stderr,
+-                    "DES DECRYPT ERROR, key %s, text %s, real cipher %s, computed cleartext %02X%02X%02X%02X%02X%02X%02X%02X\n",
+-                    block1, block2, block3,
+-                    output2[0],output2[1],output2[2],output2[3],
+-                    output2[4],output2[5],output2[6],output2[7]);
+-            error++;
+-        }
+-
+-        num++;
+-    }
+-
+-    if (error)
+-        printf("destest: failed to pass the test\n");
+-    else
+-        printf("destest: %d tests passed successfully\n", num);
+-
+-    exit( (error > 256 && error % 256) ? 1 : error);
+-}
+-
+-int value[128] = {
+-    -1, -1, -1, -1, -1, -1, -1, -1,
+-    -1, -1, -1, -1, -1, -1, -1, -1,
+-    -1, -1, -1, -1, -1, -1, -1, -1,
+-    -1, -1, -1, -1, -1, -1, -1, -1,
+-    -1, -1, -1, -1, -1, -1, -1, -1,
+-    -1, -1, -1, -1, -1, -1, -1, -1,
+-    0, 1, 2, 3, 4, 5, 6, 7,
+-    8, 9, -1, -1, -1, -1, -1, -1,
+-    -1, 10, 11, 12, 13, 14, 15, -1,
+-    -1, -1, -1, -1, -1, -1, -1, -1,
+-    -1, -1, -1, -1, -1, -1, -1, -1,
+-    -1, -1, -1, -1, -1, -1, -1, -1,
+-    -1, -1, -1, -1, -1, -1, -1, -1,
+-    -1, -1, -1, -1, -1, -1, -1, -1,
+-    -1, -1, -1, -1, -1, -1, -1, -1,
+-    -1, -1, -1, -1, -1, -1, -1, -1,
+-};
+-
+-void
+-convert(text, cblock)
+-    char *text;
+-    unsigned char cblock[];
+-{
+-    int i;
+-    for (i = 0; i < 8; i++) {
+-        if (!isascii((unsigned char)text[i * 2]))
+-            abort ();
+-        if (value[(int) text[i*2]] == -1 || value[(int) text[i*2+1]] == -1) {
+-            printf("Bad value byte %d in %s\n", i, text);
+-            exit(1);
+-        }
+-        cblock[i] = 16*value[(int) text[i*2]] + value[(int) text[i*2+1]];
+-    }
+-    return;
+-}
+-
+-/*
+- * Fake out the DES library, for the purposes of testing.
+- */
+-
+-int
+-mit_des_is_weak_key(key)
+-    mit_des_cblock key;
+-{
+-    return 0;                           /* fake it out for testing */
+-}
+-
+-void
+-des_cblock_print_file(x, fp)
+-    mit_des_cblock x;
+-    FILE *fp;
+-{
+-    unsigned char *y = (unsigned char *) x;
+-    int i = 0;
+-    fprintf(fp," 0x { ");
+-
+-    while (i++ < 8) {
+-        fprintf(fp,"%x",*y++);
+-        if (i < 8)
+-            fprintf(fp,", ");
+-    }
+-    fprintf(fp," }");
+-}
+-
+-
+-#define smask(step) ((1<<step)-1)
+-#define pstep(x,step) (((x)&smask(step))^(((x)>>step)&smask(step)))
+-#define parity_char(x) pstep(pstep(pstep((x),4),2),1)
+-
+-/*
+- * des_check_key_parity: returns true iff key has the correct des parity.
+- *                       See des_fix_key_parity for the definition of
+- *                       correct des parity.
+- */
+-int
+-mit_des_check_key_parity(key)
+-    mit_des_cblock key;
+-{
+-    unsigned int i;
+-
+-    for (i=0; i<sizeof(mit_des_cblock); i++) {
+-        if ((key[i] & 1) == parity_char(0xfe&key[i])) {
+-            printf("warning: bad parity key:");
+-            des_cblock_print_file(key, stdout);
+-            putchar('\n');
+-
+-            return 1;
+-        }
+-    }
+-
+-    return(1);
+-}
+-
+-void
+-mit_des_fixup_key_parity(key)
+-    mit_des_cblock key;
+-{
+-    unsigned int i;
+-    for (i=0; i<sizeof(mit_des_cblock); i++)
+-    {
+-        key[i] &= 0xfe;
+-        key[i] |= 1^parity_char(key[i]);
+-    }
+-
+-    return;
+-}
+diff --git a/src/lib/crypto/builtin/des/doc/libdes.doc b/src/lib/crypto/builtin/des/doc/libdes.doc
+deleted file mode 100644
+index 19c03c1d3..000000000
+--- a/src/lib/crypto/builtin/des/doc/libdes.doc
++++ /dev/null
+@@ -1,208 +0,0 @@
+-
+-	How to use the Kerberos encryption library.
+-
+-			Revised		10/15/85	spm
+-
+-1)	The following include file is needed:
+-	
+-	/projects/auth/include/des.h	(VAX)
+-	---------------					(PC8086)
+-
+-2)	The encryption library that should be linked to is:
+-	
+-	/projects/auth/lib/libdes.a		(VAX)
+-|	/projects/auth/ibm/lib/libdes.a	(PC8086 cross-compilation environment)
+-
+-3)	For each key that may be simultaneously active,
+-	allocate (either compile or malloc) a "Key_schedule" struct, 
+-	defined in "des.h"
+-
+-4)	Create key schedules, as needed, prior to using the encryption
+-	routines, via "des_set_key()".
+-
+-5)  Setup the input and output areas.  Make sure to note the restrictions
+-	on lengths being multiples of eight bytes.
+-
+-6)	Invoke the encryption/decryption routines, "ecb_encrypt()"
+-	 or "cbc_encrypt()"
+-
+-7)	To generate a cryptographic checksum, use "cbc_cksum()"
+-/*	----------------------------------------------------------------	*/
+-	
+-	Routine Interfaces--
+-
+-/*	-----------------------------------------------------------------	*/
+-
+-int
+-	des_set_key(k,schedule)
+-		C_Block			*k;
+-		Key_schedule	schedule;
+-
+-	Calculates a key schedule from (all) eight bytes of the input key, and
+-	puts it into the indicated "Key_schedule" struct;
+-
+-	Make sure to pass valid eight bytes, no padding or other processing
+-	it done.
+-
+-	The key schedule is then used in subsequent encryption/decryption
+-	operations.  Many key schedules may be created and cached for later
+-	use.
+-
+-	The user is responsible to clear keys and schedules no longer needed
+-	to prevent their disclosure.
+-
+-|	Checks the parity of the key provided, to make sure it is odd per
+-|	FIPS spec.  Returns 0 value for key ok, 1 for key_parity error.
+-
+-/*	----------------------------------------------------------------	*/
+-	
+-int
+-	ecb_encrypt(input,output,schedule,encrypt)
+-		C_Block			*input;		/* ptr to eight byte input value */
+-		C_Block			*output;	/* ptr to eight byte output value */
+-		int				encrypt;	/* 0 ==> decrypt, else encrypt */
+-		Key_schedule	schedule;	/* addr of key schedule */
+-
+-This is the low level routine that encrypts or decrypts a single 8-byte
+-block in electronic code book mode.  Always transforms the input
+-data into the output data.
+-
+-If encrypt is non-zero, the input (cleartext) is encrypted into the
+-output (ciphertext) using the specified key_schedule, pre-set via "des_set_key".
+-
+-If encrypt is zero, the input (now ciphertext) is decrypted into
+-the output (now cleartext).
+-
+-Input and output may be the same space.
+-
+-Does not return any meaningful value.  Void is not used for compatibility
+-with other compilers.
+-
+-/*	--------------------------------------------------------------	*/
+-
+-int	
+-	cbc_encrypt(input,output,length,schedule,ivec,encrypt)
+-
+-		C_Block			*input;		/* ptr to input data */
+-		C_Block			*output;	/* ptr to output data */
+-		int				length;		/* desired length, in bytes */
+-		Key_schedule	schedule;		/* addr of precomputed schedule */
+-		C_Block			*ivec;		/* pointer to 8 byte initialization
+-									 * vector
+-									 */
+-		int				encrypt		/* 0 ==> decrypt; else encrypt*/
+-
+-
+-	If encrypt is non-zero, the routine cipher-block-chain encrypts
+-	the INPUT (cleartext) into the OUTPUT (ciphertext) using the provided
+-	key schedule and initialization vector.  If the length is not an integral
+-	multiple of eight bytes, the last block is copied to a temp and zero 
+-	filled (highest addresses).  The output is ALWAYS an integral multiple
+-	of eight bytes.
+-
+-	If encrypt is zero, the routine cipher-block chain decrypts the INPUT
+-	(ciphertext) into the OUTPUT (cleartext) using the provided key schedule
+-	and	initialization vector.	Decryption ALWAYS operates on integral
+-	multiples of 8 bytes, so will round the length provided up to the
+-	appropriate	multiple. Consequently,	it will always produce the rounded-up
+-	number of bytes of output cleartext. The application must determine if
+-	the output cleartext was zero-padded due to cleartext lengths not integral
+-	multiples of 8.
+-
+-	No errors or meaningful value are returned.  Void is not used for
+-	compatibility with other compilers.
+-
+-
+-/* cbc checksum (MAC) only routine  ---------------------------------------- */
+-int	
+-	cbc_cksum(input,output,length,schedule,ivec)
+-
+-	C_Block		 	*input;		/* >= length bytes of inputtext	 */
+-	C_Block		 	*output;	/* >= length bytes of outputtext */
+-	int				length;		/* in bytes						*/
+-	Key_schedule	schedule;	/* precomputed key schedule	   */
+-	C_Block			*ivec;		/* 8 bytes of ivec			   */
+-
+-
+-	Produces a cryptographic checksum, 8 bytes, by cipher-block-chain
+-	encrypting the input, discarding the ciphertext output, and only retaining
+-	the last ciphertext 8-byte block.  Uses the provided key schedule and ivec.
+-	The input is effectively zero-padded to an integral multiple of
+-	eight bytes, though the original input is not modified.
+-
+-	No meaningful value is returned.  Void is not used for compatibility
+-	with other compilers.
+-
+-
+-/*	random_key ----------------------------------------*/
+-int
+-	random_key(key)
+-
+-	C_Block	*key;
+-
+-	The start for the random number generated is set from the current time
+-	in microseconds, then the random number generator is invoked
+-	to create an eight byte output key (not a schedule).  The key
+-	generated is set to odd parity per FIPS spec.
+-
+-	The caller must	supply space for the output key, pointed to 
+-	by "*key", then after getting a new key, call the des_set_key() 
+-	routine when needed.
+-
+-	No meaningfull value is returned.  Void is not used for compatibility
+-	with other compilers.
+-
+-
+-/* string_to_key --------------------------------------------*/
+-
+-int
+-	string_to_key(str,key)
+-	char		*str;
+-	C_Block	*key;
+-
+-	This routines converts an arbitrary length, null terminated string
+-	to an 8 byte DES key, with each byte parity set to odd, per FIPS spec.
+-
+-	The algorithm is as follows:
+-
+-|	Take the first 8 bytes and remove the parity (leaving 56 bits).
+-|	Do the same for the second 8 bytes, and the third, etc.  Do this for
+-|	as many sets of 8 bytes as necessary, filling in the remainder of the
+-|	last set with nulls.  Fold the second set back on the first (i.e. bit
+-|	0 over bit 55, and bit 55 over bit 0).  Fold the third over the second
+-|	(bit 0 of the third set is now over bit 0 of the first set).  Repeat
+-|	until you have done this to all sets.  Xor the folded sets.  Break the
+-|	result into 8 7 bit bytes, and generate odd parity for each byte.  You
+-|	now have 64 bits.  Note that DES takes a 64 bit key, and uses only the
+-|	non parity bits.
+-
+-
+-/* read_password -------------------------------------------*/
+-
+-read_password(k,prompt,verify)
+-	C_Block	*k;
+-	char *prompt;
+-	int	verify;
+-
+-This routine issues the supplied prompt, turns off echo, if possible, and
+-reads an input string.  If verify is non-zero, it does it again, for use
+-in applications such as changing a password. If verify is non-zero, both
+-versions are compared, and the input is requested repeatedly until they
+-match.  Then, the input string is mapped into a valid DES key, internally
+-using the string_to_key routine.  The newly created key is copied to the
+-area pointed to by parameter "k".  
+-
+-No meaningful value is returned.  If an error occurs trying to manipulate
+-the terminal echo, the routine forces the process to exit.
+-
+-/* get_line ------------------------*/
+-long get_line(p,max)
+-	char	*p;
+-	long	max;
+-
+-Reads input characters from standard input until either a newline appears or
+-else the max length is reached.  The characters read are stuffed into
+-the string pointed to, which will always be null terminated.  The newline
+-is not inserted in the string.  The max parameter includes the byte needed
+-for the null terminator, so allocate and pass one more than the maximum
+-string length desired.
+diff --git a/src/lib/crypto/builtin/des/f_aead.c b/src/lib/crypto/builtin/des/f_aead.c
+deleted file mode 100644
+index 71b8dff4d..000000000
+--- a/src/lib/crypto/builtin/des/f_aead.c
++++ /dev/null
+@@ -1,173 +0,0 @@
+-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+-/*
+- * Copyright (C) 2008 by the Massachusetts Institute of Technology.
+- * Copyright 1995 by Richard P. Basch.  All Rights Reserved.
+- * Copyright 1995 by Lehman Brothers, Inc.  All Rights Reserved.
+- *
+- * Export of this software from the United States of America may
+- *   require a specific license from the United States Government.
+- *   It is the responsibility of any person or organization contemplating
+- *   export to obtain such a license before exporting.
+- *
+- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+- * distribute this software and its documentation for any purpose and
+- * without fee is hereby granted, provided that the above copyright
+- * notice appear in all copies and that both that copyright notice and
+- * this permission notice appear in supporting documentation, and that
+- * the name of Richard P. Basch, Lehman Brothers and M.I.T. not be used
+- * in advertising or publicity pertaining to distribution of the software
+- * without specific, written prior permission.  Richard P. Basch,
+- * Lehman Brothers and M.I.T. make no representations about the suitability
+- * of this software for any purpose.  It is provided "as is" without
+- * express or implied warranty.
+- */
+-
+-#include "crypto_int.h"
+-#include "des_int.h"
+-#include "f_tables.h"
+-
+-const mit_des_cblock mit_des_zeroblock /* = all zero */;
+-
+-void
+-krb5int_des_cbc_encrypt(krb5_crypto_iov *data, unsigned long num_data,
+-                        const mit_des_key_schedule schedule,
+-                        mit_des_cblock ivec)
+-{
+-    unsigned DES_INT32 left, right;
+-    const unsigned DES_INT32 *kp;
+-    const unsigned char *ip;
+-    struct iov_cursor cursor;
+-    unsigned char block[MIT_DES_BLOCK_LENGTH];
+-
+-    /* Get key pointer here.  This won't need to be reinitialized. */
+-    kp = (const unsigned DES_INT32 *)schedule;
+-
+-    /* Initialize left and right with the contents of the initial vector. */
+-    ip = (ivec != NULL) ? ivec : mit_des_zeroblock;
+-    left = load_32_be(ip);
+-    right = load_32_be(ip + 4);
+-
+-    k5_iov_cursor_init(&cursor, data, num_data, MIT_DES_BLOCK_LENGTH, FALSE);
+-    while (k5_iov_cursor_get(&cursor, block)) {
+-        /* Decompose this block and xor it with the previous ciphertext. */
+-        left ^= load_32_be(block);
+-        right ^= load_32_be(block + 4);
+-
+-        /* Encrypt what we have and put back into block. */
+-        DES_DO_ENCRYPT(left, right, kp);
+-        store_32_be(left, block);
+-        store_32_be(right, block + 4);
+-
+-        k5_iov_cursor_put(&cursor, block);
+-    }
+-
+-    if (ivec != NULL) {
+-        store_32_be(left, ivec);
+-        store_32_be(right, ivec + 4);
+-    }
+-}
+-
+-void
+-krb5int_des_cbc_decrypt(krb5_crypto_iov *data, unsigned long num_data,
+-                        const mit_des_key_schedule schedule,
+-                        mit_des_cblock ivec)
+-{
+-    unsigned DES_INT32 left, right;
+-    const unsigned DES_INT32 *kp;
+-    const unsigned char *ip;
+-    unsigned DES_INT32 ocipherl, ocipherr;
+-    unsigned DES_INT32 cipherl, cipherr;
+-    struct iov_cursor cursor;
+-    unsigned char block[MIT_DES_BLOCK_LENGTH];
+-
+-    /* Get key pointer here.  This won't need to be reinitialized. */
+-    kp = (const unsigned DES_INT32 *)schedule;
+-
+-    /*
+-     * Decrypting is harder than encrypting because of
+-     * the necessity of remembering a lot more things.
+-     * Should think about this a little more...
+-     */
+-
+-    /* Prime the old cipher with ivec. */
+-    ip = (ivec != NULL) ? ivec : mit_des_zeroblock;
+-    ocipherl = load_32_be(ip);
+-    ocipherr = load_32_be(ip + 4);
+-
+-    k5_iov_cursor_init(&cursor, data, num_data, MIT_DES_BLOCK_LENGTH, FALSE);
+-    while (k5_iov_cursor_get(&cursor, block)) {
+-        /* Split this block into left and right. */
+-        cipherl = left = load_32_be(block);
+-        cipherr = right = load_32_be(block + 4);
+-
+-        /* Decrypt and xor with the old cipher to get plain text. */
+-        DES_DO_DECRYPT(left, right, kp);
+-        left ^= ocipherl;
+-        right ^= ocipherr;
+-
+-        /* Store the encrypted halves back into block. */
+-        store_32_be(left, block);
+-        store_32_be(right, block + 4);
+-
+-        /* Save current cipher block halves. */
+-        ocipherl = cipherl;
+-        ocipherr = cipherr;
+-
+-        k5_iov_cursor_put(&cursor, block);
+-    }
+-
+-    if (ivec != NULL) {
+-        store_32_be(ocipherl, ivec);
+-        store_32_be(ocipherr, ivec + 4);
+-    }
+-}
+-
+-void
+-krb5int_des_cbc_mac(const krb5_crypto_iov *data, unsigned long num_data,
+-                    const mit_des_key_schedule schedule, mit_des_cblock ivec,
+-                    mit_des_cblock out)
+-{
+-    unsigned DES_INT32 left, right;
+-    const unsigned DES_INT32 *kp;
+-    const unsigned char *ip;
+-    struct iov_cursor cursor;
+-    unsigned char block[MIT_DES_BLOCK_LENGTH];
+-
+-    /* Get key pointer here.  This won't need to be reinitialized. */
+-    kp = (const unsigned DES_INT32 *)schedule;
+-
+-    /* Initialize left and right with the contents of the initial vector. */
+-    ip = (ivec != NULL) ? ivec : mit_des_zeroblock;
+-    left = load_32_be(ip);
+-    right = load_32_be(ip + 4);
+-
+-    k5_iov_cursor_init(&cursor, data, num_data, MIT_DES_BLOCK_LENGTH, TRUE);
+-    while (k5_iov_cursor_get(&cursor, block)) {
+-        /* Decompose this block and xor it with the previous ciphertext. */
+-        left ^= load_32_be(block);
+-        right ^= load_32_be(block + 4);
+-
+-        /* Encrypt what we have. */
+-        DES_DO_ENCRYPT(left, right, kp);
+-    }
+-
+-    /* Output the final ciphertext block. */
+-    store_32_be(left, out);
+-    store_32_be(right, out + 4);
+-}
+-
+-#if defined(CONFIG_SMALL) && !defined(CONFIG_SMALL_NO_CRYPTO)
+-void krb5int_des_do_encrypt_2 (unsigned DES_INT32 *left,
+-                               unsigned DES_INT32 *right,
+-                               const unsigned DES_INT32 *kp)
+-{
+-    DES_DO_ENCRYPT_1 (*left, *right, kp);
+-}
+-
+-void krb5int_des_do_decrypt_2 (unsigned DES_INT32 *left,
+-                               unsigned DES_INT32 *right,
+-                               const unsigned DES_INT32 *kp)
+-{
+-    DES_DO_DECRYPT_1 (*left, *right, kp);
+-}
+-#endif
+diff --git a/src/lib/crypto/builtin/des/f_cbc.c b/src/lib/crypto/builtin/des/f_cbc.c
+deleted file mode 100644
+index 84d5382f2..000000000
+--- a/src/lib/crypto/builtin/des/f_cbc.c
++++ /dev/null
+@@ -1,256 +0,0 @@
+-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+-/* lib/crypto/builtin/des/f_cbc.c */
+-/*
+- * Copyright (C) 1990 by the Massachusetts Institute of Technology.
+- * All rights reserved.
+- *
+- * Export of this software from the United States of America may
+- *   require a specific license from the United States Government.
+- *   It is the responsibility of any person or organization contemplating
+- *   export to obtain such a license before exporting.
+- *
+- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+- * distribute this software and its documentation for any purpose and
+- * without fee is hereby granted, provided that the above copyright
+- * notice appear in all copies and that both that copyright notice and
+- * this permission notice appear in supporting documentation, and that
+- * the name of M.I.T. not be used in advertising or publicity pertaining
+- * to distribution of the software without specific, written prior
+- * permission.  Furthermore if you modify this software you must label
+- * your software as modified software and not distribute it in such a
+- * fashion that it might be confused with the original M.I.T. software.
+- * M.I.T. makes no representations about the suitability of
+- * this software for any purpose.  It is provided "as is" without express
+- * or implied warranty.
+- */
+-
+-/*
+- * CBC functions; used only by the test programs at this time.  (krb5 uses the
+- * functions in f_aead.c instead.)
+- */
+-
+-/*
+- * des_cbc_encrypt.c - an implementation of the DES cipher function in cbc mode
+- */
+-#include "des_int.h"
+-#include "f_tables.h"
+-
+-/*
+- * des_cbc_encrypt - {en,de}crypt a stream in CBC mode
+- */
+-
+-/*
+- * This routine performs DES cipher-block-chaining operation, either
+- * encrypting from cleartext to ciphertext, if encrypt != 0 or
+- * decrypting from ciphertext to cleartext, if encrypt == 0.
+- *
+- * The key schedule is passed as an arg, as well as the cleartext or
+- * ciphertext.  The cleartext and ciphertext should be in host order.
+- *
+- * NOTE-- the output is ALWAYS an multiple of 8 bytes long.  If not
+- * enough space was provided, your program will get trashed.
+- *
+- * For encryption, the cleartext string is null padded, at the end, to
+- * an integral multiple of eight bytes.
+- *
+- * For decryption, the ciphertext will be used in integral multiples
+- * of 8 bytes, but only the first "length" bytes returned into the
+- * cleartext.
+- */
+-
+-const mit_des_cblock mit_des_zeroblock /* = all zero */;
+-
+-static void
+-des_cbc_encrypt(const mit_des_cblock *in, mit_des_cblock *out,
+-                unsigned long length, const mit_des_key_schedule schedule,
+-                const mit_des_cblock ivec)
+-{
+-    unsigned DES_INT32 left, right;
+-    const unsigned DES_INT32 *kp;
+-    const unsigned char *ip;
+-    unsigned char *op;
+-
+-    /*
+-     * Get key pointer here.  This won't need to be reinitialized
+-     */
+-    kp = (const unsigned DES_INT32 *)schedule;
+-
+-    /*
+-     * Initialize left and right with the contents of the initial
+-     * vector.
+-     */
+-    ip = ivec;
+-    GET_HALF_BLOCK(left, ip);
+-    GET_HALF_BLOCK(right, ip);
+-
+-    /*
+-     * Suitably initialized, now work the length down 8 bytes
+-     * at a time.
+-     */
+-    ip = *in;
+-    op = *out;
+-    while (length > 0) {
+-        /*
+-         * Get more input, xor it in.  If the length is
+-         * greater than or equal to 8 this is straight
+-         * forward.  Otherwise we have to fart around.
+-         */
+-        if (length >= 8) {
+-            unsigned DES_INT32 temp;
+-            GET_HALF_BLOCK(temp, ip);
+-            left  ^= temp;
+-            GET_HALF_BLOCK(temp, ip);
+-            right ^= temp;
+-            length -= 8;
+-        } else {
+-            /*
+-             * Oh, shoot.  We need to pad the
+-             * end with zeroes.  Work backwards
+-             * to do this.
+-             */
+-            ip += (int) length;
+-            switch(length) {
+-            case 7:
+-                right ^= (*(--ip) & FF_UINT32) <<  8;
+-            case 6:
+-                right ^= (*(--ip) & FF_UINT32) << 16;
+-            case 5:
+-                right ^= (*(--ip) & FF_UINT32) << 24;
+-            case 4:
+-                left  ^=  *(--ip) & FF_UINT32;
+-            case 3:
+-                left  ^= (*(--ip) & FF_UINT32) <<  8;
+-            case 2:
+-                left  ^= (*(--ip) & FF_UINT32) << 16;
+-            case 1:
+-                left  ^= (*(--ip) & FF_UINT32) << 24;
+-                break;
+-            }
+-            length = 0;
+-        }
+-
+-        /*
+-         * Encrypt what we have
+-         */
+-        DES_DO_ENCRYPT(left, right, kp);
+-
+-        /*
+-         * Copy the results out
+-         */
+-        PUT_HALF_BLOCK(left, op);
+-        PUT_HALF_BLOCK(right, op);
+-    }
+-}
+-
+-static void
+-des_cbc_decrypt(const mit_des_cblock *in, mit_des_cblock *out,
+-                unsigned long length, const mit_des_key_schedule schedule,
+-                const mit_des_cblock ivec)
+-{
+-    unsigned DES_INT32 left, right;
+-    const unsigned DES_INT32 *kp;
+-    const unsigned char *ip;
+-    unsigned char *op;
+-    unsigned DES_INT32 ocipherl, ocipherr;
+-    unsigned DES_INT32 cipherl, cipherr;
+-
+-    /*
+-     * Get key pointer here.  This won't need to be reinitialized
+-     */
+-    kp = (const unsigned DES_INT32 *)schedule;
+-
+-    /*
+-     * Decrypting is harder than encrypting because of
+-     * the necessity of remembering a lot more things.
+-     * Should think about this a little more...
+-     */
+-
+-    if (length <= 0)
+-        return;
+-
+-    /*
+-     * Prime the old cipher with ivec.
+-     */
+-    ip = ivec;
+-    GET_HALF_BLOCK(ocipherl, ip);
+-    GET_HALF_BLOCK(ocipherr, ip);
+-
+-    /*
+-     * Now do this in earnest until we run out of length.
+-     */
+-    ip = *in;
+-    op = *out;
+-    for (;;) {              /* check done inside loop */
+-        /*
+-         * Read a block from the input into left and
+-         * right.  Save this cipher block for later.
+-         */
+-        GET_HALF_BLOCK(left, ip);
+-        GET_HALF_BLOCK(right, ip);
+-        cipherl = left;
+-        cipherr = right;
+-
+-        /*
+-         * Decrypt this.
+-         */
+-        DES_DO_DECRYPT(left, right, kp);
+-
+-        /*
+-         * Xor with the old cipher to get plain
+-         * text.  Output 8 or less bytes of this.
+-         */
+-        left ^= ocipherl;
+-        right ^= ocipherr;
+-        if (length > 8) {
+-            length -= 8;
+-            PUT_HALF_BLOCK(left, op);
+-            PUT_HALF_BLOCK(right, op);
+-            /*
+-             * Save current cipher block here
+-             */
+-            ocipherl = cipherl;
+-            ocipherr = cipherr;
+-        } else {
+-            /*
+-             * Trouble here.  Start at end of output,
+-             * work backwards.
+-             */
+-            op += (int) length;
+-            switch(length) {
+-            case 8:
+-                *(--op) = (unsigned char) (right & 0xff);
+-            case 7:
+-                *(--op) = (unsigned char) ((right >> 8) & 0xff);
+-            case 6:
+-                *(--op) = (unsigned char) ((right >> 16) & 0xff);
+-            case 5:
+-                *(--op) = (unsigned char) ((right >> 24) & 0xff);
+-            case 4:
+-                *(--op) = (unsigned char) (left & 0xff);
+-            case 3:
+-                *(--op) = (unsigned char) ((left >> 8) & 0xff);
+-            case 2:
+-                *(--op) = (unsigned char) ((left >> 16) & 0xff);
+-            case 1:
+-                *(--op) = (unsigned char) ((left >> 24) & 0xff);
+-                break;
+-            }
+-            break;          /* we're done */
+-        }
+-    }
+-}
+-
+-int
+-mit_des_cbc_encrypt(const mit_des_cblock *in, mit_des_cblock *out,
+-                    unsigned long length, const mit_des_key_schedule schedule,
+-                    const mit_des_cblock ivec, int enc)
+-{
+-    /*
+-     * Deal with encryption and decryption separately.
+-     */
+-    if (enc)
+-        des_cbc_encrypt(in, out, length, schedule, ivec);
+-    else
+-        des_cbc_decrypt(in, out, length, schedule, ivec);
+-    return 0;
+-}
+diff --git a/src/lib/crypto/builtin/des/f_cksum.c b/src/lib/crypto/builtin/des/f_cksum.c
+deleted file mode 100644
+index cb482b009..000000000
+--- a/src/lib/crypto/builtin/des/f_cksum.c
++++ /dev/null
+@@ -1,136 +0,0 @@
+-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+-/* lib/crypto/builtin/des/f_cksum.c */
+-/*
+- * Copyright (C) 1990 by the Massachusetts Institute of Technology.
+- * All rights reserved.
+- *
+- * Export of this software from the United States of America may
+- *   require a specific license from the United States Government.
+- *   It is the responsibility of any person or organization contemplating
+- *   export to obtain such a license before exporting.
+- *
+- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+- * distribute this software and its documentation for any purpose and
+- * without fee is hereby granted, provided that the above copyright
+- * notice appear in all copies and that both that copyright notice and
+- * this permission notice appear in supporting documentation, and that
+- * the name of M.I.T. not be used in advertising or publicity pertaining
+- * to distribution of the software without specific, written prior
+- * permission.  Furthermore if you modify this software you must label
+- * your software as modified software and not distribute it in such a
+- * fashion that it might be confused with the original M.I.T. software.
+- * M.I.T. makes no representations about the suitability of
+- * this software for any purpose.  It is provided "as is" without express
+- * or implied warranty.
+- */
+-
+-/* DES implementation donated by Dennis Ferguson */
+-
+-/*
+- * des_cbc_cksum.c - compute an 8 byte checksum using DES in CBC mode
+- */
+-#include "des_int.h"
+-#include "f_tables.h"
+-
+-/*
+- * This routine performs DES cipher-block-chaining checksum operation,
+- * a.k.a.  Message Authentication Code.  It ALWAYS encrypts from input
+- * to a single 64 bit output MAC checksum.
+- *
+- * The key schedule is passed as an arg, as well as the cleartext or
+- * ciphertext. The cleartext and ciphertext should be in host order.
+- *
+- * NOTE-- the output is ALWAYS 8 bytes long.  If not enough space was
+- * provided, your program will get trashed.
+- *
+- * The input is null padded, at the end (highest addr), to an integral
+- * multiple of eight bytes.
+- */
+-
+-unsigned long
+-mit_des_cbc_cksum(const krb5_octet *in, krb5_octet *out,
+-                  unsigned long length, const mit_des_key_schedule schedule,
+-                  const krb5_octet *ivec)
+-{
+-    unsigned DES_INT32 left, right;
+-    const unsigned DES_INT32 *kp;
+-    const unsigned char *ip;
+-    unsigned char *op;
+-    DES_INT32 len;
+-
+-    /*
+-     * Initialize left and right with the contents of the initial
+-     * vector.
+-     */
+-    ip = ivec;
+-    GET_HALF_BLOCK(left, ip);
+-    GET_HALF_BLOCK(right, ip);
+-
+-    /*
+-     * Suitably initialized, now work the length down 8 bytes
+-     * at a time.
+-     */
+-    ip = in;
+-    len = length;
+-    while (len > 0) {
+-        /*
+-         * Get more input, xor it in.  If the length is
+-         * greater than or equal to 8 this is straight
+-         * forward.  Otherwise we have to fart around.
+-         */
+-        if (len >= 8) {
+-            unsigned DES_INT32 temp;
+-            GET_HALF_BLOCK(temp, ip);
+-            left  ^= temp;
+-            GET_HALF_BLOCK(temp, ip);
+-            right ^= temp;
+-            len -= 8;
+-        } else {
+-            /*
+-             * Oh, shoot.  We need to pad the
+-             * end with zeroes.  Work backwards
+-             * to do this.
+-             */
+-            ip += (int) len;
+-            switch(len) {
+-            case 7:
+-                right ^= (*(--ip) & FF_UINT32) <<  8;
+-            case 6:
+-                right ^= (*(--ip) & FF_UINT32) << 16;
+-            case 5:
+-                right ^= (*(--ip) & FF_UINT32) << 24;
+-            case 4:
+-                left  ^=  *(--ip) & FF_UINT32;
+-            case 3:
+-                left  ^= (*(--ip) & FF_UINT32) <<  8;
+-            case 2:
+-                left  ^= (*(--ip) & FF_UINT32) << 16;
+-            case 1:
+-                left  ^= (*(--ip) & FF_UINT32) << 24;
+-                break;
+-            }
+-            len = 0;
+-        }
+-
+-        /*
+-         * Encrypt what we have
+-         */
+-        kp = (const unsigned DES_INT32 *)schedule;
+-        DES_DO_ENCRYPT(left, right, kp);
+-    }
+-
+-    /*
+-     * Done.  Left and right have the checksum.  Put it into
+-     * the output.
+-     */
+-    op = out;
+-    PUT_HALF_BLOCK(left, op);
+-    PUT_HALF_BLOCK(right, op);
+-
+-    /*
+-     * Return right.  I'll bet the MIT code returns this
+-     * inconsistantly (with the low order byte of the checksum
+-     * not always in the low order byte of the DES_INT32).  We won't.
+-     */
+-    return right & 0xFFFFFFFFUL;
+-}
+diff --git a/src/lib/crypto/builtin/des/f_parity.c b/src/lib/crypto/builtin/des/f_parity.c
+deleted file mode 100644
+index 460b5061b..000000000
+--- a/src/lib/crypto/builtin/des/f_parity.c
++++ /dev/null
+@@ -1,56 +0,0 @@
+-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+-/*
+- * These routines check and fix parity of encryption keys for the DES
+- * algorithm.
+- *
+- * They are a replacement for routines in key_parity.c, that don't require
+- * the table building that they do.
+- *
+- * Mark Eichin -- Cygnus Support
+- */
+-
+-
+-#include "des_int.h"
+-
+-/*
+- * des_fixup_key_parity: Forces odd parity per byte; parity is bits
+- *                       8,16,...64 in des order, implies 0, 8, 16, ...
+- *                       vax order.
+- */
+-#define smask(step) ((1<<step)-1)
+-#define pstep(x,step) (((x)&smask(step))^(((x)>>step)&smask(step)))
+-#define parity_char(x) pstep(pstep(pstep((x),4),2),1)
+-
+-void
+-mit_des_fixup_key_parity(mit_des_cblock key)
+-{
+-    unsigned int i;
+-    for (i=0; i<sizeof(mit_des_cblock); i++)
+-    {
+-        key[i] &= 0xfe;
+-        key[i] |= 1^parity_char(key[i]);
+-    }
+-
+-    return;
+-}
+-
+-/*
+- * des_check_key_parity: returns true iff key has the correct des parity.
+- *                       See des_fix_key_parity for the definition of
+- *                       correct des parity.
+- */
+-int
+-mit_des_check_key_parity(mit_des_cblock key)
+-{
+-    unsigned int i;
+-
+-    for (i=0; i<sizeof(mit_des_cblock); i++)
+-    {
+-        if((key[i] & 1) == parity_char(0xfe&key[i]))
+-        {
+-            return 0;
+-        }
+-    }
+-
+-    return(1);
+-}
+diff --git a/src/lib/crypto/builtin/des/f_sched.c b/src/lib/crypto/builtin/des/f_sched.c
+deleted file mode 100644
+index 666a510fb..000000000
+--- a/src/lib/crypto/builtin/des/f_sched.c
++++ /dev/null
+@@ -1,359 +0,0 @@
+-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+-/* lib/crypto/builtin/des/f_sched.c */
+-/*
+- * Copyright (C) 1990 by the Massachusetts Institute of Technology.
+- * All rights reserved.
+- *
+- * Export of this software from the United States of America may
+- *   require a specific license from the United States Government.
+- *   It is the responsibility of any person or organization contemplating
+- *   export to obtain such a license before exporting.
+- *
+- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+- * distribute this software and its documentation for any purpose and
+- * without fee is hereby granted, provided that the above copyright
+- * notice appear in all copies and that both that copyright notice and
+- * this permission notice appear in supporting documentation, and that
+- * the name of M.I.T. not be used in advertising or publicity pertaining
+- * to distribution of the software without specific, written prior
+- * permission.  Furthermore if you modify this software you must label
+- * your software as modified software and not distribute it in such a
+- * fashion that it might be confused with the original M.I.T. software.
+- * M.I.T. makes no representations about the suitability of
+- * this software for any purpose.  It is provided "as is" without express
+- * or implied warranty.
+- */
+-
+-/* DES implementation donated by Dennis Ferguson */
+-
+-/*
+- * des_make_sched.c - permute a DES key, returning the resulting key schedule
+- */
+-#include "k5-int.h"
+-#include "des_int.h"
+-
+-/*
+- * Permuted choice 1 tables.  These are used to extract bits
+- * from the left and right parts of the key to form Ci and Di.
+- * The code that uses these tables knows which bits from which
+- * part of each key are used to form Ci and Di.
+- */
+-static const unsigned DES_INT32 PC1_CL[8] = {
+-    0x00000000, 0x00000010, 0x00001000, 0x00001010,
+-    0x00100000, 0x00100010, 0x00101000, 0x00101010
+-};
+-
+-static const unsigned DES_INT32 PC1_DL[16] = {
+-    0x00000000, 0x00100000, 0x00001000, 0x00101000,
+-    0x00000010, 0x00100010, 0x00001010, 0x00101010,
+-    0x00000001, 0x00100001, 0x00001001, 0x00101001,
+-    0x00000011, 0x00100011, 0x00001011, 0x00101011
+-};
+-
+-static const unsigned DES_INT32 PC1_CR[16] = {
+-    0x00000000, 0x00000001, 0x00000100, 0x00000101,
+-    0x00010000, 0x00010001, 0x00010100, 0x00010101,
+-    0x01000000, 0x01000001, 0x01000100, 0x01000101,
+-    0x01010000, 0x01010001, 0x01010100, 0x01010101
+-};
+-
+-static const unsigned DES_INT32 PC1_DR[8] = {
+-    0x00000000, 0x01000000, 0x00010000, 0x01010000,
+-    0x00000100, 0x01000100, 0x00010100, 0x01010100
+-};
+-
+-
+-/*
+- * At the start of some iterations of the key schedule we do
+- * a circular left shift by one place, while for others we do a shift by
+- * two places.  This has bits set for the iterations where we do 2 bit
+- * shifts, starting at the low order bit.
+- */
+-#define TWO_BIT_SHIFTS  0x7efc
+-
+-/*
+- * Permuted choice 2 tables.  The first actually produces the low order
+- * 24 bits of the subkey Ki from the 28 bit value of Ci.  The second produces
+- * the high order 24 bits from Di.  The tables are indexed by six bit
+- * segments of Ci and Di respectively.  The code is handcrafted to compute
+- * the appropriate 6 bit chunks.
+- *
+- * Note that for ease of computation, the 24 bit values are produced with
+- * six bits going into each byte.  Note also that the table has been byte
+- * rearranged to produce keys which match the order we will apply them
+- * in in the des code.
+- */
+-static const unsigned DES_INT32 PC2_C[4][64] = {
+-    {
+-        0x00000000, 0x00000004, 0x00010000, 0x00010004,
+-        0x00000400, 0x00000404, 0x00010400, 0x00010404,
+-        0x00000020, 0x00000024, 0x00010020, 0x00010024,
+-        0x00000420, 0x00000424, 0x00010420, 0x00010424,
+-        0x01000000, 0x01000004, 0x01010000, 0x01010004,
+-        0x01000400, 0x01000404, 0x01010400, 0x01010404,
+-        0x01000020, 0x01000024, 0x01010020, 0x01010024,
+-        0x01000420, 0x01000424, 0x01010420, 0x01010424,
+-        0x00020000, 0x00020004, 0x00030000, 0x00030004,
+-        0x00020400, 0x00020404, 0x00030400, 0x00030404,
+-        0x00020020, 0x00020024, 0x00030020, 0x00030024,
+-        0x00020420, 0x00020424, 0x00030420, 0x00030424,
+-        0x01020000, 0x01020004, 0x01030000, 0x01030004,
+-        0x01020400, 0x01020404, 0x01030400, 0x01030404,
+-        0x01020020, 0x01020024, 0x01030020, 0x01030024,
+-        0x01020420, 0x01020424, 0x01030420, 0x01030424,
+-    },
+-    {
+-        0x00000000, 0x02000000, 0x00000800, 0x02000800,
+-        0x00080000, 0x02080000, 0x00080800, 0x02080800,
+-        0x00000001, 0x02000001, 0x00000801, 0x02000801,
+-        0x00080001, 0x02080001, 0x00080801, 0x02080801,
+-        0x00000100, 0x02000100, 0x00000900, 0x02000900,
+-        0x00080100, 0x02080100, 0x00080900, 0x02080900,
+-        0x00000101, 0x02000101, 0x00000901, 0x02000901,
+-        0x00080101, 0x02080101, 0x00080901, 0x02080901,
+-        0x10000000, 0x12000000, 0x10000800, 0x12000800,
+-        0x10080000, 0x12080000, 0x10080800, 0x12080800,
+-        0x10000001, 0x12000001, 0x10000801, 0x12000801,
+-        0x10080001, 0x12080001, 0x10080801, 0x12080801,
+-        0x10000100, 0x12000100, 0x10000900, 0x12000900,
+-        0x10080100, 0x12080100, 0x10080900, 0x12080900,
+-        0x10000101, 0x12000101, 0x10000901, 0x12000901,
+-        0x10080101, 0x12080101, 0x10080901, 0x12080901,
+-    },
+-    {
+-        0x00000000, 0x00040000, 0x00002000, 0x00042000,
+-        0x00100000, 0x00140000, 0x00102000, 0x00142000,
+-        0x20000000, 0x20040000, 0x20002000, 0x20042000,
+-        0x20100000, 0x20140000, 0x20102000, 0x20142000,
+-        0x00000008, 0x00040008, 0x00002008, 0x00042008,
+-        0x00100008, 0x00140008, 0x00102008, 0x00142008,
+-        0x20000008, 0x20040008, 0x20002008, 0x20042008,
+-        0x20100008, 0x20140008, 0x20102008, 0x20142008,
+-        0x00200000, 0x00240000, 0x00202000, 0x00242000,
+-        0x00300000, 0x00340000, 0x00302000, 0x00342000,
+-        0x20200000, 0x20240000, 0x20202000, 0x20242000,
+-        0x20300000, 0x20340000, 0x20302000, 0x20342000,
+-        0x00200008, 0x00240008, 0x00202008, 0x00242008,
+-        0x00300008, 0x00340008, 0x00302008, 0x00342008,
+-        0x20200008, 0x20240008, 0x20202008, 0x20242008,
+-        0x20300008, 0x20340008, 0x20302008, 0x20342008,
+-    },
+-    {
+-        0x00000000, 0x00000010, 0x08000000, 0x08000010,
+-        0x00000200, 0x00000210, 0x08000200, 0x08000210,
+-        0x00000002, 0x00000012, 0x08000002, 0x08000012,
+-        0x00000202, 0x00000212, 0x08000202, 0x08000212,
+-        0x04000000, 0x04000010, 0x0c000000, 0x0c000010,
+-        0x04000200, 0x04000210, 0x0c000200, 0x0c000210,
+-        0x04000002, 0x04000012, 0x0c000002, 0x0c000012,
+-        0x04000202, 0x04000212, 0x0c000202, 0x0c000212,
+-        0x00001000, 0x00001010, 0x08001000, 0x08001010,
+-        0x00001200, 0x00001210, 0x08001200, 0x08001210,
+-        0x00001002, 0x00001012, 0x08001002, 0x08001012,
+-        0x00001202, 0x00001212, 0x08001202, 0x08001212,
+-        0x04001000, 0x04001010, 0x0c001000, 0x0c001010,
+-        0x04001200, 0x04001210, 0x0c001200, 0x0c001210,
+-        0x04001002, 0x04001012, 0x0c001002, 0x0c001012,
+-        0x04001202, 0x04001212, 0x0c001202, 0x0c001212
+-    },
+-};
+-
+-static const unsigned DES_INT32 PC2_D[4][64] = {
+-    {
+-        0x00000000, 0x02000000, 0x00020000, 0x02020000,
+-        0x00000100, 0x02000100, 0x00020100, 0x02020100,
+-        0x00000008, 0x02000008, 0x00020008, 0x02020008,
+-        0x00000108, 0x02000108, 0x00020108, 0x02020108,
+-        0x00200000, 0x02200000, 0x00220000, 0x02220000,
+-        0x00200100, 0x02200100, 0x00220100, 0x02220100,
+-        0x00200008, 0x02200008, 0x00220008, 0x02220008,
+-        0x00200108, 0x02200108, 0x00220108, 0x02220108,
+-        0x00000200, 0x02000200, 0x00020200, 0x02020200,
+-        0x00000300, 0x02000300, 0x00020300, 0x02020300,
+-        0x00000208, 0x02000208, 0x00020208, 0x02020208,
+-        0x00000308, 0x02000308, 0x00020308, 0x02020308,
+-        0x00200200, 0x02200200, 0x00220200, 0x02220200,
+-        0x00200300, 0x02200300, 0x00220300, 0x02220300,
+-        0x00200208, 0x02200208, 0x00220208, 0x02220208,
+-        0x00200308, 0x02200308, 0x00220308, 0x02220308,
+-    },
+-    {
+-        0x00000000, 0x00001000, 0x00000020, 0x00001020,
+-        0x00100000, 0x00101000, 0x00100020, 0x00101020,
+-        0x08000000, 0x08001000, 0x08000020, 0x08001020,
+-        0x08100000, 0x08101000, 0x08100020, 0x08101020,
+-        0x00000004, 0x00001004, 0x00000024, 0x00001024,
+-        0x00100004, 0x00101004, 0x00100024, 0x00101024,
+-        0x08000004, 0x08001004, 0x08000024, 0x08001024,
+-        0x08100004, 0x08101004, 0x08100024, 0x08101024,
+-        0x00000400, 0x00001400, 0x00000420, 0x00001420,
+-        0x00100400, 0x00101400, 0x00100420, 0x00101420,
+-        0x08000400, 0x08001400, 0x08000420, 0x08001420,
+-        0x08100400, 0x08101400, 0x08100420, 0x08101420,
+-        0x00000404, 0x00001404, 0x00000424, 0x00001424,
+-        0x00100404, 0x00101404, 0x00100424, 0x00101424,
+-        0x08000404, 0x08001404, 0x08000424, 0x08001424,
+-        0x08100404, 0x08101404, 0x08100424, 0x08101424,
+-    },
+-    {
+-        0x00000000, 0x10000000, 0x00010000, 0x10010000,
+-        0x00000002, 0x10000002, 0x00010002, 0x10010002,
+-        0x00002000, 0x10002000, 0x00012000, 0x10012000,
+-        0x00002002, 0x10002002, 0x00012002, 0x10012002,
+-        0x00040000, 0x10040000, 0x00050000, 0x10050000,
+-        0x00040002, 0x10040002, 0x00050002, 0x10050002,
+-        0x00042000, 0x10042000, 0x00052000, 0x10052000,
+-        0x00042002, 0x10042002, 0x00052002, 0x10052002,
+-        0x20000000, 0x30000000, 0x20010000, 0x30010000,
+-        0x20000002, 0x30000002, 0x20010002, 0x30010002,
+-        0x20002000, 0x30002000, 0x20012000, 0x30012000,
+-        0x20002002, 0x30002002, 0x20012002, 0x30012002,
+-        0x20040000, 0x30040000, 0x20050000, 0x30050000,
+-        0x20040002, 0x30040002, 0x20050002, 0x30050002,
+-        0x20042000, 0x30042000, 0x20052000, 0x30052000,
+-        0x20042002, 0x30042002, 0x20052002, 0x30052002,
+-    },
+-    {
+-        0x00000000, 0x04000000, 0x00000001, 0x04000001,
+-        0x01000000, 0x05000000, 0x01000001, 0x05000001,
+-        0x00000010, 0x04000010, 0x00000011, 0x04000011,
+-        0x01000010, 0x05000010, 0x01000011, 0x05000011,
+-        0x00080000, 0x04080000, 0x00080001, 0x04080001,
+-        0x01080000, 0x05080000, 0x01080001, 0x05080001,
+-        0x00080010, 0x04080010, 0x00080011, 0x04080011,
+-        0x01080010, 0x05080010, 0x01080011, 0x05080011,
+-        0x00000800, 0x04000800, 0x00000801, 0x04000801,
+-        0x01000800, 0x05000800, 0x01000801, 0x05000801,
+-        0x00000810, 0x04000810, 0x00000811, 0x04000811,
+-        0x01000810, 0x05000810, 0x01000811, 0x05000811,
+-        0x00080800, 0x04080800, 0x00080801, 0x04080801,
+-        0x01080800, 0x05080800, 0x01080801, 0x05080801,
+-        0x00080810, 0x04080810, 0x00080811, 0x04080811,
+-        0x01080810, 0x05080810, 0x01080811, 0x05080811
+-    },
+-};
+-
+-
+-
+-/*
+- * Permute the key to give us our key schedule.
+- */
+-int
+-mit_des_make_key_sched(mit_des_cblock key, mit_des_key_schedule schedule)
+-{
+-    unsigned DES_INT32 c, d;
+-
+-    {
+-        /*
+-         * Need a pointer for the keys and a temporary DES_INT32
+-         */
+-        const unsigned char *k;
+-        unsigned DES_INT32 tmp;
+-
+-        /*
+-         * Fetch the key into something we can work with
+-         */
+-        k = key;
+-
+-        /*
+-         * The first permutted choice gives us the 28 bits for C0 and
+-         * 28 for D0.  C0 gets 12 bits from the left key and 16 from
+-         * the right, while D0 gets 16 from the left and 12 from the
+-         * right.  The code knows which bits go where.
+-         */
+-        tmp = load_32_be(k), k += 4;
+-
+-        c =  PC1_CL[(tmp >> 29) & 0x7]
+-            | (PC1_CL[(tmp >> 21) & 0x7] << 1)
+-            | (PC1_CL[(tmp >> 13) & 0x7] << 2)
+-            | (PC1_CL[(tmp >>  5) & 0x7] << 3);
+-        d =  PC1_DL[(tmp >> 25) & 0xf]
+-            | (PC1_DL[(tmp >> 17) & 0xf] << 1)
+-            | (PC1_DL[(tmp >>  9) & 0xf] << 2)
+-            | (PC1_DL[(tmp >>  1) & 0xf] << 3);
+-
+-        tmp = load_32_be(k), k += 4;
+-
+-        c |= PC1_CR[(tmp >> 28) & 0xf]
+-            | (PC1_CR[(tmp >> 20) & 0xf] << 1)
+-            | (PC1_CR[(tmp >> 12) & 0xf] << 2)
+-            | (PC1_CR[(tmp >>  4) & 0xf] << 3);
+-        d |= PC1_DR[(tmp >> 25) & 0x7]
+-            | (PC1_DR[(tmp >> 17) & 0x7] << 1)
+-            | (PC1_DR[(tmp >>  9) & 0x7] << 2)
+-            | (PC1_DR[(tmp >>  1) & 0x7] << 3);
+-    }
+-
+-    {
+-        /*
+-         * Need several temporaries in here
+-         */
+-        unsigned DES_INT32 ltmp, rtmp;
+-        unsigned DES_INT32 *k;
+-        int two_bit_shifts;
+-        int i;
+-        /*
+-         * Now iterate to compute the key schedule.  Note that we
+-         * record the entire set of subkeys in 6 bit chunks since
+-         * they are used that way.  At 6 bits/char, we need
+-         * 48/6 char's/subkey * 16 subkeys/encryption == 128 bytes.
+-         * The schedule must be this big.
+-         */
+-        k = (unsigned DES_INT32 *)schedule;
+-        two_bit_shifts = TWO_BIT_SHIFTS;
+-        for (i = 16; i > 0; i--) {
+-            /*
+-             * Do the rotation.  One bit and two bit rotations
+-             * are done separately.  Note C and D are 28 bits.
+-             */
+-            if (two_bit_shifts & 0x1) {
+-                c = ((c << 2) & 0xffffffc) | (c >> 26);
+-                d = ((d << 2) & 0xffffffc) | (d >> 26);
+-            } else {
+-                c = ((c << 1) & 0xffffffe) | (c >> 27);
+-                d = ((d << 1) & 0xffffffe) | (d >> 27);
+-            }
+-            two_bit_shifts >>= 1;
+-
+-            /*
+-             * Apply permutted choice 2 to C to get the first
+-             * 24 bits worth of keys.  Note that bits 9, 18, 22
+-             * and 25 (using DES numbering) in C are unused.  The
+-             * shift-mask stuff is done to delete these bits from
+-             * the indices, since this cuts the table size in half.
+-             *
+-             * The table is torqued, by the way.  If the standard
+-             * byte order for this (high to low order) is 1234,
+-             * the table actually gives us 4132.
+-             */
+-            ltmp = PC2_C[0][((c >> 22) & 0x3f)]
+-                | PC2_C[1][((c >> 15) & 0xf) | ((c >> 16) & 0x30)]
+-                | PC2_C[2][((c >>  4) & 0x3) | ((c >>  9) & 0x3c)]
+-                | PC2_C[3][((c      ) & 0x7) | ((c >>  4) & 0x38)];
+-            /*
+-             * Apply permutted choice 2 to D to get the other half.
+-             * Here, bits 7, 10, 15 and 26 go unused.  The sqeezing
+-             * actually turns out to be cheaper here.
+-             *
+-             * This table is similarly torqued.  If the standard
+-             * byte order is 5678, the table has the bytes permuted
+-             * to give us 7685.
+-             */
+-            rtmp = PC2_D[0][((d >> 22) & 0x3f)]
+-                | PC2_D[1][((d >> 14) & 0xf) | ((d >> 15) & 0x30)]
+-                | PC2_D[2][((d >>  7) & 0x3f)]
+-                | PC2_D[3][((d      ) & 0x3) | ((d >>  1) & 0x3c)];
+-
+-            /*
+-             * Make up two words of the key schedule, with a
+-             * byte order which is convenient for the DES
+-             * inner loop.  The high order (first) word will
+-             * hold bytes 7135 (high to low order) while the
+-             * second holds bytes 4682.
+-             */
+-            *k++ = (ltmp & 0x00ffff00) | (rtmp & 0xff0000ff);
+-            *k++ = (ltmp & 0xff0000ff) | (rtmp & 0x00ffff00);
+-        }
+-    }
+-    return (0);
+-}
+diff --git a/src/lib/crypto/builtin/des/f_tables.c b/src/lib/crypto/builtin/des/f_tables.c
+deleted file mode 100644
+index 6308cb0d5..000000000
+--- a/src/lib/crypto/builtin/des/f_tables.c
++++ /dev/null
+@@ -1,370 +0,0 @@
+-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+-/* lib/crypto/builtin/des/f_tables.c */
+-/*
+- * Copyright (C) 1990 by the Massachusetts Institute of Technology.
+- * All rights reserved.
+- *
+- * Export of this software from the United States of America may
+- *   require a specific license from the United States Government.
+- *   It is the responsibility of any person or organization contemplating
+- *   export to obtain such a license before exporting.
+- *
+- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+- * distribute this software and its documentation for any purpose and
+- * without fee is hereby granted, provided that the above copyright
+- * notice appear in all copies and that both that copyright notice and
+- * this permission notice appear in supporting documentation, and that
+- * the name of M.I.T. not be used in advertising or publicity pertaining
+- * to distribution of the software without specific, written prior
+- * permission.  Furthermore if you modify this software you must label
+- * your software as modified software and not distribute it in such a
+- * fashion that it might be confused with the original M.I.T. software.
+- * M.I.T. makes no representations about the suitability of
+- * this software for any purpose.  It is provided "as is" without express
+- * or implied warranty.
+- */
+-
+-/* DES implementation donated by Dennis Ferguson */
+-
+-/*
+- * des_tables.c - precomputed tables used for the DES cipher function
+- */
+-
+-/*
+- * Include the header file so something will complain if the
+- * declarations get out of sync
+- */
+-#include "des_int.h"
+-#include "f_tables.h"
+-
+-/*
+- * These tables may be declared const if you want.  Many compilers
+- * don't support this, though.
+- */
+-
+-/*
+- * The DES algorithm which uses these is intended to be fairly speedy
+- * at the expense of some memory.  All the standard hacks are used.
+- * The S boxes and the P permutation are precomputed into one table.
+- * The E box never actually appears explicitly since it is easy to apply
+- * this algorithmically as needed.  The initial permutation and final
+- * (inverse initial) permutation are computed from tables designed to
+- * permute one byte at a time.  This should run pretty fast on machines
+- * with 32 bit words and bit field/multiple bit shift instructions which
+- * are fast.
+- */
+-
+-/*
+- * The initial permutation array.  This is used to compute both the
+- * left and the right halves of the initial permutation using bytes
+- * from words made from the following operations:
+- *
+- * ((left & 0x55555555) << 1) | (right & 0x55555555)  for left half
+- * (left & 0xaaaaaaaa) | ((right & 0xaaaaaaaa) >> 1)  for right half
+- *
+- * The scheme is that we index into the table using each byte.  The
+- * result from the high order byte is or'd with the result from the
+- * next byte shifted left once is or'd with the result from the next
+- * byte shifted left twice if or'd with the result from the low order
+- * byte shifted left by three.  Clear?
+- */
+-
+-const unsigned DES_INT32 des_IP_table[256] = {
+-    0x00000000, 0x00000010, 0x00000001, 0x00000011,
+-    0x00001000, 0x00001010, 0x00001001, 0x00001011,
+-    0x00000100, 0x00000110, 0x00000101, 0x00000111,
+-    0x00001100, 0x00001110, 0x00001101, 0x00001111,
+-    0x00100000, 0x00100010, 0x00100001, 0x00100011,
+-    0x00101000, 0x00101010, 0x00101001, 0x00101011,
+-    0x00100100, 0x00100110, 0x00100101, 0x00100111,
+-    0x00101100, 0x00101110, 0x00101101, 0x00101111,
+-    0x00010000, 0x00010010, 0x00010001, 0x00010011,
+-    0x00011000, 0x00011010, 0x00011001, 0x00011011,
+-    0x00010100, 0x00010110, 0x00010101, 0x00010111,
+-    0x00011100, 0x00011110, 0x00011101, 0x00011111,
+-    0x00110000, 0x00110010, 0x00110001, 0x00110011,
+-    0x00111000, 0x00111010, 0x00111001, 0x00111011,
+-    0x00110100, 0x00110110, 0x00110101, 0x00110111,
+-    0x00111100, 0x00111110, 0x00111101, 0x00111111,
+-    0x10000000, 0x10000010, 0x10000001, 0x10000011,
+-    0x10001000, 0x10001010, 0x10001001, 0x10001011,
+-    0x10000100, 0x10000110, 0x10000101, 0x10000111,
+-    0x10001100, 0x10001110, 0x10001101, 0x10001111,
+-    0x10100000, 0x10100010, 0x10100001, 0x10100011,
+-    0x10101000, 0x10101010, 0x10101001, 0x10101011,
+-    0x10100100, 0x10100110, 0x10100101, 0x10100111,
+-    0x10101100, 0x10101110, 0x10101101, 0x10101111,
+-    0x10010000, 0x10010010, 0x10010001, 0x10010011,
+-    0x10011000, 0x10011010, 0x10011001, 0x10011011,
+-    0x10010100, 0x10010110, 0x10010101, 0x10010111,
+-    0x10011100, 0x10011110, 0x10011101, 0x10011111,
+-    0x10110000, 0x10110010, 0x10110001, 0x10110011,
+-    0x10111000, 0x10111010, 0x10111001, 0x10111011,
+-    0x10110100, 0x10110110, 0x10110101, 0x10110111,
+-    0x10111100, 0x10111110, 0x10111101, 0x10111111,
+-    0x01000000, 0x01000010, 0x01000001, 0x01000011,
+-    0x01001000, 0x01001010, 0x01001001, 0x01001011,
+-    0x01000100, 0x01000110, 0x01000101, 0x01000111,
+-    0x01001100, 0x01001110, 0x01001101, 0x01001111,
+-    0x01100000, 0x01100010, 0x01100001, 0x01100011,
+-    0x01101000, 0x01101010, 0x01101001, 0x01101011,
+-    0x01100100, 0x01100110, 0x01100101, 0x01100111,
+-    0x01101100, 0x01101110, 0x01101101, 0x01101111,
+-    0x01010000, 0x01010010, 0x01010001, 0x01010011,
+-    0x01011000, 0x01011010, 0x01011001, 0x01011011,
+-    0x01010100, 0x01010110, 0x01010101, 0x01010111,
+-    0x01011100, 0x01011110, 0x01011101, 0x01011111,
+-    0x01110000, 0x01110010, 0x01110001, 0x01110011,
+-    0x01111000, 0x01111010, 0x01111001, 0x01111011,
+-    0x01110100, 0x01110110, 0x01110101, 0x01110111,
+-    0x01111100, 0x01111110, 0x01111101, 0x01111111,
+-    0x11000000, 0x11000010, 0x11000001, 0x11000011,
+-    0x11001000, 0x11001010, 0x11001001, 0x11001011,
+-    0x11000100, 0x11000110, 0x11000101, 0x11000111,
+-    0x11001100, 0x11001110, 0x11001101, 0x11001111,
+-    0x11100000, 0x11100010, 0x11100001, 0x11100011,
+-    0x11101000, 0x11101010, 0x11101001, 0x11101011,
+-    0x11100100, 0x11100110, 0x11100101, 0x11100111,
+-    0x11101100, 0x11101110, 0x11101101, 0x11101111,
+-    0x11010000, 0x11010010, 0x11010001, 0x11010011,
+-    0x11011000, 0x11011010, 0x11011001, 0x11011011,
+-    0x11010100, 0x11010110, 0x11010101, 0x11010111,
+-    0x11011100, 0x11011110, 0x11011101, 0x11011111,
+-    0x11110000, 0x11110010, 0x11110001, 0x11110011,
+-    0x11111000, 0x11111010, 0x11111001, 0x11111011,
+-    0x11110100, 0x11110110, 0x11110101, 0x11110111,
+-    0x11111100, 0x11111110, 0x11111101, 0x11111111
+-};
+-
+-/*
+- * The final permutation array.  Like the IP array, used
+- * to compute both the left and right results from the bytes
+- * of words computed from:
+- *
+- * ((left & 0x0f0f0f0f) << 4) | (right & 0x0f0f0f0f)  for left result
+- * (left & 0xf0f0f0f0) | ((right & 0xf0f0f0f0) >> 4)  for right result
+- *
+- * The result from the high order byte is shifted left 6 bits and
+- * or'd with the result from the next byte shifted left 4 bits, which
+- * is or'd with the result from the next byte shifted left 2 bits,
+- * which is or'd with the result from the low byte.
+- */
+-const unsigned DES_INT32 des_FP_table[256] = {
+-    0x00000000, 0x02000000, 0x00020000, 0x02020000,
+-    0x00000200, 0x02000200, 0x00020200, 0x02020200,
+-    0x00000002, 0x02000002, 0x00020002, 0x02020002,
+-    0x00000202, 0x02000202, 0x00020202, 0x02020202,
+-    0x01000000, 0x03000000, 0x01020000, 0x03020000,
+-    0x01000200, 0x03000200, 0x01020200, 0x03020200,
+-    0x01000002, 0x03000002, 0x01020002, 0x03020002,
+-    0x01000202, 0x03000202, 0x01020202, 0x03020202,
+-    0x00010000, 0x02010000, 0x00030000, 0x02030000,
+-    0x00010200, 0x02010200, 0x00030200, 0x02030200,
+-    0x00010002, 0x02010002, 0x00030002, 0x02030002,
+-    0x00010202, 0x02010202, 0x00030202, 0x02030202,
+-    0x01010000, 0x03010000, 0x01030000, 0x03030000,
+-    0x01010200, 0x03010200, 0x01030200, 0x03030200,
+-    0x01010002, 0x03010002, 0x01030002, 0x03030002,
+-    0x01010202, 0x03010202, 0x01030202, 0x03030202,
+-    0x00000100, 0x02000100, 0x00020100, 0x02020100,
+-    0x00000300, 0x02000300, 0x00020300, 0x02020300,
+-    0x00000102, 0x02000102, 0x00020102, 0x02020102,
+-    0x00000302, 0x02000302, 0x00020302, 0x02020302,
+-    0x01000100, 0x03000100, 0x01020100, 0x03020100,
+-    0x01000300, 0x03000300, 0x01020300, 0x03020300,
+-    0x01000102, 0x03000102, 0x01020102, 0x03020102,
+-    0x01000302, 0x03000302, 0x01020302, 0x03020302,
+-    0x00010100, 0x02010100, 0x00030100, 0x02030100,
+-    0x00010300, 0x02010300, 0x00030300, 0x02030300,
+-    0x00010102, 0x02010102, 0x00030102, 0x02030102,
+-    0x00010302, 0x02010302, 0x00030302, 0x02030302,
+-    0x01010100, 0x03010100, 0x01030100, 0x03030100,
+-    0x01010300, 0x03010300, 0x01030300, 0x03030300,
+-    0x01010102, 0x03010102, 0x01030102, 0x03030102,
+-    0x01010302, 0x03010302, 0x01030302, 0x03030302,
+-    0x00000001, 0x02000001, 0x00020001, 0x02020001,
+-    0x00000201, 0x02000201, 0x00020201, 0x02020201,
+-    0x00000003, 0x02000003, 0x00020003, 0x02020003,
+-    0x00000203, 0x02000203, 0x00020203, 0x02020203,
+-    0x01000001, 0x03000001, 0x01020001, 0x03020001,
+-    0x01000201, 0x03000201, 0x01020201, 0x03020201,
+-    0x01000003, 0x03000003, 0x01020003, 0x03020003,
+-    0x01000203, 0x03000203, 0x01020203, 0x03020203,
+-    0x00010001, 0x02010001, 0x00030001, 0x02030001,
+-    0x00010201, 0x02010201, 0x00030201, 0x02030201,
+-    0x00010003, 0x02010003, 0x00030003, 0x02030003,
+-    0x00010203, 0x02010203, 0x00030203, 0x02030203,
+-    0x01010001, 0x03010001, 0x01030001, 0x03030001,
+-    0x01010201, 0x03010201, 0x01030201, 0x03030201,
+-    0x01010003, 0x03010003, 0x01030003, 0x03030003,
+-    0x01010203, 0x03010203, 0x01030203, 0x03030203,
+-    0x00000101, 0x02000101, 0x00020101, 0x02020101,
+-    0x00000301, 0x02000301, 0x00020301, 0x02020301,
+-    0x00000103, 0x02000103, 0x00020103, 0x02020103,
+-    0x00000303, 0x02000303, 0x00020303, 0x02020303,
+-    0x01000101, 0x03000101, 0x01020101, 0x03020101,
+-    0x01000301, 0x03000301, 0x01020301, 0x03020301,
+-    0x01000103, 0x03000103, 0x01020103, 0x03020103,
+-    0x01000303, 0x03000303, 0x01020303, 0x03020303,
+-    0x00010101, 0x02010101, 0x00030101, 0x02030101,
+-    0x00010301, 0x02010301, 0x00030301, 0x02030301,
+-    0x00010103, 0x02010103, 0x00030103, 0x02030103,
+-    0x00010303, 0x02010303, 0x00030303, 0x02030303,
+-    0x01010101, 0x03010101, 0x01030101, 0x03030101,
+-    0x01010301, 0x03010301, 0x01030301, 0x03030301,
+-    0x01010103, 0x03010103, 0x01030103, 0x03030103,
+-    0x01010303, 0x03010303, 0x01030303, 0x03030303
+-};
+-
+-
+-/*
+- * The SP table is actually the S boxes and the P permutation
+- * table combined.  This table is actually reordered from the
+- * spec, to match the order of key application we follow.
+- */
+-const unsigned DES_INT32 des_SP_table[8][64] = {
+-    {
+-        0x00100000, 0x02100001, 0x02000401, 0x00000000, /* 7 */
+-        0x00000400, 0x02000401, 0x00100401, 0x02100400,
+-        0x02100401, 0x00100000, 0x00000000, 0x02000001,
+-        0x00000001, 0x02000000, 0x02100001, 0x00000401,
+-        0x02000400, 0x00100401, 0x00100001, 0x02000400,
+-        0x02000001, 0x02100000, 0x02100400, 0x00100001,
+-        0x02100000, 0x00000400, 0x00000401, 0x02100401,
+-        0x00100400, 0x00000001, 0x02000000, 0x00100400,
+-        0x02000000, 0x00100400, 0x00100000, 0x02000401,
+-        0x02000401, 0x02100001, 0x02100001, 0x00000001,
+-        0x00100001, 0x02000000, 0x02000400, 0x00100000,
+-        0x02100400, 0x00000401, 0x00100401, 0x02100400,
+-        0x00000401, 0x02000001, 0x02100401, 0x02100000,
+-        0x00100400, 0x00000000, 0x00000001, 0x02100401,
+-        0x00000000, 0x00100401, 0x02100000, 0x00000400,
+-        0x02000001, 0x02000400, 0x00000400, 0x00100001,
+-    },
+-    {
+-        0x00808200, 0x00000000, 0x00008000, 0x00808202, /* 1 */
+-        0x00808002, 0x00008202, 0x00000002, 0x00008000,
+-        0x00000200, 0x00808200, 0x00808202, 0x00000200,
+-        0x00800202, 0x00808002, 0x00800000, 0x00000002,
+-        0x00000202, 0x00800200, 0x00800200, 0x00008200,
+-        0x00008200, 0x00808000, 0x00808000, 0x00800202,
+-        0x00008002, 0x00800002, 0x00800002, 0x00008002,
+-        0x00000000, 0x00000202, 0x00008202, 0x00800000,
+-        0x00008000, 0x00808202, 0x00000002, 0x00808000,
+-        0x00808200, 0x00800000, 0x00800000, 0x00000200,
+-        0x00808002, 0x00008000, 0x00008200, 0x00800002,
+-        0x00000200, 0x00000002, 0x00800202, 0x00008202,
+-        0x00808202, 0x00008002, 0x00808000, 0x00800202,
+-        0x00800002, 0x00000202, 0x00008202, 0x00808200,
+-        0x00000202, 0x00800200, 0x00800200, 0x00000000,
+-        0x00008002, 0x00008200, 0x00000000, 0x00808002,
+-    },
+-    {
+-        0x00000104, 0x04010100, 0x00000000, 0x04010004, /* 3 */
+-        0x04000100, 0x00000000, 0x00010104, 0x04000100,
+-        0x00010004, 0x04000004, 0x04000004, 0x00010000,
+-        0x04010104, 0x00010004, 0x04010000, 0x00000104,
+-        0x04000000, 0x00000004, 0x04010100, 0x00000100,
+-        0x00010100, 0x04010000, 0x04010004, 0x00010104,
+-        0x04000104, 0x00010100, 0x00010000, 0x04000104,
+-        0x00000004, 0x04010104, 0x00000100, 0x04000000,
+-        0x04010100, 0x04000000, 0x00010004, 0x00000104,
+-        0x00010000, 0x04010100, 0x04000100, 0x00000000,
+-        0x00000100, 0x00010004, 0x04010104, 0x04000100,
+-        0x04000004, 0x00000100, 0x00000000, 0x04010004,
+-        0x04000104, 0x00010000, 0x04000000, 0x04010104,
+-        0x00000004, 0x00010104, 0x00010100, 0x04000004,
+-        0x04010000, 0x04000104, 0x00000104, 0x04010000,
+-        0x00010104, 0x00000004, 0x04010004, 0x00010100,
+-    },
+-    {
+-        0x00000080, 0x01040080, 0x01040000, 0x21000080, /* 5 */
+-        0x00040000, 0x00000080, 0x20000000, 0x01040000,
+-        0x20040080, 0x00040000, 0x01000080, 0x20040080,
+-        0x21000080, 0x21040000, 0x00040080, 0x20000000,
+-        0x01000000, 0x20040000, 0x20040000, 0x00000000,
+-        0x20000080, 0x21040080, 0x21040080, 0x01000080,
+-        0x21040000, 0x20000080, 0x00000000, 0x21000000,
+-        0x01040080, 0x01000000, 0x21000000, 0x00040080,
+-        0x00040000, 0x21000080, 0x00000080, 0x01000000,
+-        0x20000000, 0x01040000, 0x21000080, 0x20040080,
+-        0x01000080, 0x20000000, 0x21040000, 0x01040080,
+-        0x20040080, 0x00000080, 0x01000000, 0x21040000,
+-        0x21040080, 0x00040080, 0x21000000, 0x21040080,
+-        0x01040000, 0x00000000, 0x20040000, 0x21000000,
+-        0x00040080, 0x01000080, 0x20000080, 0x00040000,
+-        0x00000000, 0x20040000, 0x01040080, 0x20000080,
+-    },
+-    {
+-        0x80401000, 0x80001040, 0x80001040, 0x00000040, /* 4 */
+-        0x00401040, 0x80400040, 0x80400000, 0x80001000,
+-        0x00000000, 0x00401000, 0x00401000, 0x80401040,
+-        0x80000040, 0x00000000, 0x00400040, 0x80400000,
+-        0x80000000, 0x00001000, 0x00400000, 0x80401000,
+-        0x00000040, 0x00400000, 0x80001000, 0x00001040,
+-        0x80400040, 0x80000000, 0x00001040, 0x00400040,
+-        0x00001000, 0x00401040, 0x80401040, 0x80000040,
+-        0x00400040, 0x80400000, 0x00401000, 0x80401040,
+-        0x80000040, 0x00000000, 0x00000000, 0x00401000,
+-        0x00001040, 0x00400040, 0x80400040, 0x80000000,
+-        0x80401000, 0x80001040, 0x80001040, 0x00000040,
+-        0x80401040, 0x80000040, 0x80000000, 0x00001000,
+-        0x80400000, 0x80001000, 0x00401040, 0x80400040,
+-        0x80001000, 0x00001040, 0x00400000, 0x80401000,
+-        0x00000040, 0x00400000, 0x00001000, 0x00401040,
+-    },
+-    {
+-        0x10000008, 0x10200000, 0x00002000, 0x10202008, /* 6 */
+-        0x10200000, 0x00000008, 0x10202008, 0x00200000,
+-        0x10002000, 0x00202008, 0x00200000, 0x10000008,
+-        0x00200008, 0x10002000, 0x10000000, 0x00002008,
+-        0x00000000, 0x00200008, 0x10002008, 0x00002000,
+-        0x00202000, 0x10002008, 0x00000008, 0x10200008,
+-        0x10200008, 0x00000000, 0x00202008, 0x10202000,
+-        0x00002008, 0x00202000, 0x10202000, 0x10000000,
+-        0x10002000, 0x00000008, 0x10200008, 0x00202000,
+-        0x10202008, 0x00200000, 0x00002008, 0x10000008,
+-        0x00200000, 0x10002000, 0x10000000, 0x00002008,
+-        0x10000008, 0x10202008, 0x00202000, 0x10200000,
+-        0x00202008, 0x10202000, 0x00000000, 0x10200008,
+-        0x00000008, 0x00002000, 0x10200000, 0x00202008,
+-        0x00002000, 0x00200008, 0x10002008, 0x00000000,
+-        0x10202000, 0x10000000, 0x00200008, 0x10002008,
+-    },
+-    {
+-        0x08000820, 0x00000800, 0x00020000, 0x08020820, /* 8 */
+-        0x08000000, 0x08000820, 0x00000020, 0x08000000,
+-        0x00020020, 0x08020000, 0x08020820, 0x00020800,
+-        0x08020800, 0x00020820, 0x00000800, 0x00000020,
+-        0x08020000, 0x08000020, 0x08000800, 0x00000820,
+-        0x00020800, 0x00020020, 0x08020020, 0x08020800,
+-        0x00000820, 0x00000000, 0x00000000, 0x08020020,
+-        0x08000020, 0x08000800, 0x00020820, 0x00020000,
+-        0x00020820, 0x00020000, 0x08020800, 0x00000800,
+-        0x00000020, 0x08020020, 0x00000800, 0x00020820,
+-        0x08000800, 0x00000020, 0x08000020, 0x08020000,
+-        0x08020020, 0x08000000, 0x00020000, 0x08000820,
+-        0x00000000, 0x08020820, 0x00020020, 0x08000020,
+-        0x08020000, 0x08000800, 0x08000820, 0x00000000,
+-        0x08020820, 0x00020800, 0x00020800, 0x00000820,
+-        0x00000820, 0x00020020, 0x08000000, 0x08020800,
+-    },
+-    {
+-        0x40084010, 0x40004000, 0x00004000, 0x00084010, /* 2 */
+-        0x00080000, 0x00000010, 0x40080010, 0x40004010,
+-        0x40000010, 0x40084010, 0x40084000, 0x40000000,
+-        0x40004000, 0x00080000, 0x00000010, 0x40080010,
+-        0x00084000, 0x00080010, 0x40004010, 0x00000000,
+-        0x40000000, 0x00004000, 0x00084010, 0x40080000,
+-        0x00080010, 0x40000010, 0x00000000, 0x00084000,
+-        0x00004010, 0x40084000, 0x40080000, 0x00004010,
+-        0x00000000, 0x00084010, 0x40080010, 0x00080000,
+-        0x40004010, 0x40080000, 0x40084000, 0x00004000,
+-        0x40080000, 0x40004000, 0x00000010, 0x40084010,
+-        0x00084010, 0x00000010, 0x00004000, 0x40000000,
+-        0x00004010, 0x40084000, 0x00080000, 0x40000010,
+-        0x00080010, 0x40004010, 0x40000010, 0x00080010,
+-        0x00084000, 0x00000000, 0x40004000, 0x00004010,
+-        0x40000000, 0x40080010, 0x40084010, 0x00084000
+-    },
+-};
+diff --git a/src/lib/crypto/builtin/des/f_tables.h b/src/lib/crypto/builtin/des/f_tables.h
+deleted file mode 100644
+index fc91b566c..000000000
+--- a/src/lib/crypto/builtin/des/f_tables.h
++++ /dev/null
+@@ -1,285 +0,0 @@
+-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+-/* lib/crypto/builtin/des/f_tables.h */
+-/*
+- * Copyright (C) 1990 by the Massachusetts Institute of Technology.
+- * All rights reserved.
+- *
+- * Export of this software from the United States of America may
+- *   require a specific license from the United States Government.
+- *   It is the responsibility of any person or organization contemplating
+- *   export to obtain such a license before exporting.
+- *
+- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+- * distribute this software and its documentation for any purpose and
+- * without fee is hereby granted, provided that the above copyright
+- * notice appear in all copies and that both that copyright notice and
+- * this permission notice appear in supporting documentation, and that
+- * the name of M.I.T. not be used in advertising or publicity pertaining
+- * to distribution of the software without specific, written prior
+- * permission.  Furthermore if you modify this software you must label
+- * your software as modified software and not distribute it in such a
+- * fashion that it might be confused with the original M.I.T. software.
+- * M.I.T. makes no representations about the suitability of
+- * this software for any purpose.  It is provided "as is" without express
+- * or implied warranty.
+- */
+-
+-/*
+- * DES implementation donated by Dennis Ferguson
+- */
+-
+-/*
+- * des_tables.h - declarations to import the DES tables, used internally
+- *                by some of the library routines.
+- */
+-#ifndef __DES_TABLES_H__
+-#define __DES_TABLES_H__        /* nothing */
+-
+-#include "k5-platform.h"
+-/*
+- * These may be declared const if you wish.  Be sure to change the
+- * declarations in des_tables.c as well.
+- */
+-extern const unsigned DES_INT32 des_IP_table[256];
+-extern const unsigned DES_INT32 des_FP_table[256];
+-extern const unsigned DES_INT32 des_SP_table[8][64];
+-
+-/*
+- * Use standard shortforms to reference these to save typing
+- */
+-#define IP      des_IP_table
+-#define FP      des_FP_table
+-#define SP      des_SP_table
+-
+-#ifdef DEBUG
+-#define DEB(foofraw)    printf foofraw
+-#else
+-#define DEB(foofraw)    /* nothing */
+-#endif
+-
+-/*
+- * Code to do a DES round using the tables.  Note that the E expansion
+- * is easy to compute algorithmically, especially if done out-of-order.
+- * Take a look at its form and compare it to everything involving temp
+- * below.  Since SP[0-7] don't have any bits in common set it is okay
+- * to do the successive xor's.
+- *
+- * Note too that the SP table has been reordered to match the order of
+- * the keys (if the original order of SP was 12345678, the reordered
+- * table is 71354682).  This is unnecessary, but was done since some
+- * compilers seem to like you going through the matrix from beginning
+- * to end.
+- *
+- * There is a difference in the best way to do this depending on whether
+- * one is encrypting or decrypting.  If encrypting we move forward through
+- * the keys and hence should move forward through the table.  If decrypting
+- * we go back.  Part of the need for this comes from trying to emulate
+- * existing software which generates a single key schedule and uses it
+- * both for encrypting and decrypting.  Generating separate encryption
+- * and decryption key schedules would allow one to use the same code
+- * for both.
+- *
+- * left, right and temp should be unsigned DES_INT32 values.  left and right
+- * should be the high and low order parts of the cipher block at the
+- * current stage of processing (this makes sense if you read the spec).
+- * kp should be an unsigned DES_INT32 pointer which points at the current
+- * set of subkeys in the key schedule.  It is advanced to the next set
+- * (i.e. by 8 bytes) when this is done.
+- *
+- * This occurs in the innermost loop of the DES function.  The four
+- * variables should really be in registers.
+- *
+- * When using this, the inner loop of the DES function might look like:
+- *
+- *      for (i = 0; i < 8; i++) {
+- *              DES_SP_{EN,DE}CRYPT_ROUND(left, right, temp, kp);
+- *              DES_SP_{EN,DE}CRYPT_ROUND(right, left, temp, kp);
+- *      }
+- *
+- * Note the trick above.  You are supposed to do 16 rounds, swapping
+- * left and right at the end of each round.  By doing two rounds at
+- * a time and swapping left and right in the code we can avoid the
+- * swaps altogether.
+- */
+-#define DES_SP_ENCRYPT_ROUND(left, right, temp, kp) do {        \
+-        (temp) = (((right) >> 11) | ((right) << 21)) ^ *(kp)++; \
+-        (left) ^= SP[0][((temp) >> 24) & 0x3f]                  \
+-            | SP[1][((temp) >> 16) & 0x3f]                      \
+-            | SP[2][((temp) >>  8) & 0x3f]                      \
+-            | SP[3][((temp)      ) & 0x3f];                     \
+-        (temp) = (((right) >> 23) | ((right) << 9)) ^ *(kp)++;  \
+-        (left) ^= SP[4][((temp) >> 24) & 0x3f]                  \
+-            | SP[5][((temp) >> 16) & 0x3f]                      \
+-            | SP[6][((temp) >>  8) & 0x3f]                      \
+-            | SP[7][((temp)      ) & 0x3f];                     \
+-    } while(0);
+-
+-#define DES_SP_DECRYPT_ROUND(left, right, temp, kp) do {                \
+-        (temp) = (((right) >> 23) | ((right) << 9)) ^ *(--(kp));        \
+-        (left) ^= SP[7][((temp)      ) & 0x3f]                          \
+-            | SP[6][((temp) >>  8) & 0x3f]                              \
+-            | SP[5][((temp) >> 16) & 0x3f]                              \
+-            | SP[4][((temp) >> 24) & 0x3f];                             \
+-        (temp) = (((right) >> 11) | ((right) << 21)) ^ *(--(kp));       \
+-        (left) ^= SP[3][((temp)      ) & 0x3f]                          \
+-            | SP[2][((temp) >>  8) & 0x3f]                              \
+-            | SP[1][((temp) >> 16) & 0x3f]                              \
+-            | SP[0][((temp) >> 24) & 0x3f];                             \
+-    } while (0);
+-
+-/*
+- * Macros to help deal with the initial permutation table.  Note
+- * the IP table only deals with 32 bits at a time, allowing us to
+- * collect the bits we need to deal with each half into an unsigned
+- * DES_INT32.  By carefully selecting how the bits are ordered we also
+- * take advantages of symmetries in the table so that we can use a
+- * single table to compute the permutation of all bytes.  This sounds
+- * complicated, but if you go through the process of designing the
+- * table you'll find the symmetries fall right out.
+- *
+- * The follow macros compute the set of bits used to index the
+- * table for produce the left and right permuted result.
+- *
+- * The inserted cast to unsigned DES_INT32 circumvents a bug in
+- * the Macintosh MPW 3.2 C compiler which loses the unsignedness and
+- * propagates the high-order bit in the shift.
+- */
+-#define DES_IP_LEFT_BITS(left, right)                           \
+-    ((((left) & 0x55555555) << 1) | ((right) & 0x55555555))
+-#define DES_IP_RIGHT_BITS(left, right)                          \
+-    (((left) & 0xaaaaaaaa) |                                    \
+-     ( ( (unsigned DES_INT32) ((right) & 0xaaaaaaaa) ) >> 1))
+-
+-/*
+- * The following macro does an in-place initial permutation given
+- * the current left and right parts of the block and a single
+- * temporary.  Use this more as a guide for rolling your own, though.
+- * The best way to do the IP depends on the form of the data you
+- * are dealing with.  If you use this, though, try to make left,
+- * right and temp unsigned DES_INT32s.
+- */
+-#define DES_INITIAL_PERM(left, right, temp) do {        \
+-        (temp) = DES_IP_RIGHT_BITS((left), (right));    \
+-        (right) = DES_IP_LEFT_BITS((left), (right));    \
+-        (left) = IP[((right) >> 24) & 0xff]             \
+-            | (IP[((right) >> 16) & 0xff] << 1)         \
+-            | (IP[((right) >>  8) & 0xff] << 2)         \
+-            | (IP[(right) & 0xff] << 3);                \
+-        (right) = IP[((temp) >> 24) & 0xff]             \
+-            | (IP[((temp) >> 16) & 0xff] << 1)          \
+-            | (IP[((temp) >>  8) & 0xff] << 2)          \
+-            | (IP[(temp) & 0xff] << 3);                 \
+-    } while(0);
+-
+-/*
+- * Now the final permutation stuff.  The same comments apply to
+- * this as to the initial permutation, except that we use different
+- * bits and shifts.
+- *
+- * The inserted cast to unsigned DES_INT32 circumvents a bug in
+- * the Macintosh MPW 3.2 C compiler which loses the unsignedness and
+- * propagates the high-order bit in the shift.
+- */
+-#define DES_FP_LEFT_BITS(left, right)                           \
+-    ((((left) & 0x0f0f0f0f) << 4) | ((right) & 0x0f0f0f0f))
+-#define DES_FP_RIGHT_BITS(left, right)                          \
+-    (((left) & 0xf0f0f0f0) |                                    \
+-     ( ( (unsigned DES_INT32) ((right) & 0xf0f0f0f0) ) >> 4))
+-
+-
+-/*
+- * Here is a sample final permutation.  Note that there is a trick
+- * here.  DES requires swapping the left and right parts after the
+- * last cipher round but before the final permutation.  We do this
+- * swapping internally, which is why left and right are confused
+- * at the beginning.
+- */
+-#define DES_FINAL_PERM(left, right, temp) do {          \
+-        (temp) = DES_FP_RIGHT_BITS((right), (left));    \
+-        (right) = DES_FP_LEFT_BITS((right), (left));    \
+-        (left) = (FP[((right) >> 24) & 0xff] << 6)      \
+-            | (FP[((right) >> 16) & 0xff] << 4)         \
+-            | (FP[((right) >>  8) & 0xff] << 2)         \
+-            |  FP[(right) & 0xff];                      \
+-        (right) = (FP[((temp) >> 24) & 0xff] << 6)      \
+-            | (FP[((temp) >> 16) & 0xff] << 4)          \
+-            | (FP[((temp) >>  8) & 0xff] << 2)          \
+-            |  FP[temp & 0xff];                         \
+-    } while(0);
+-
+-
+-/*
+- * Finally, as a sample of how all this might be held together, the
+- * following two macros do in-place encryptions and decryptions.  left
+- * and right are two unsigned DES_INT32 variables which at the beginning
+- * are expected to hold the clear (encrypted) block in host byte order
+- * (left the high order four bytes, right the low order).  At the end
+- * they will contain the encrypted (clear) block.  temp is an unsigned DES_INT32
+- * used as a temporary.  kp is an unsigned DES_INT32 pointer pointing at
+- * the start of the key schedule.  All these should be in registers.
+- *
+- * You can probably do better than these by rewriting for particular
+- * situations.  These aren't bad, though.
+- *
+- * The DEB macros enable debugging when this code breaks (typically
+- * when a buggy compiler breaks it), by printing the intermediate values
+- * at each stage of the encryption, so that by comparing the output to
+- * a known good machine, the location of the first error can be found.
+- */
+-#define DES_DO_ENCRYPT_1(left, right, kp)                               \
+-    do {                                                                \
+-        int i;                                                          \
+-        unsigned DES_INT32 temp1;                                       \
+-        DEB (("do_encrypt %8lX %8lX \n", left, right));                 \
+-        DES_INITIAL_PERM((left), (right), (temp1));                     \
+-        DEB (("  after IP %8lX %8lX\n", left, right));                  \
+-        for (i = 0; i < 8; i++) {                                       \
+-            DES_SP_ENCRYPT_ROUND((left), (right), (temp1), (kp));       \
+-            DEB (("  round %2d %8lX %8lX \n", i*2, left, right));       \
+-            DES_SP_ENCRYPT_ROUND((right), (left), (temp1), (kp));       \
+-            DEB (("  round %2d %8lX %8lX \n", 1+i*2, left, right));     \
+-        }                                                               \
+-        DES_FINAL_PERM((left), (right), (temp1));                       \
+-        (kp) -= (2 * 16);                                               \
+-        DEB (("  after FP %8lX %8lX \n", left, right));                 \
+-    } while (0)
+-
+-#define DES_DO_DECRYPT_1(left, right, kp)                               \
+-    do {                                                                \
+-        int i;                                                          \
+-        unsigned DES_INT32 temp2;                                       \
+-        DES_INITIAL_PERM((left), (right), (temp2));                     \
+-        (kp) += (2 * 16);                                               \
+-        for (i = 0; i < 8; i++) {                                       \
+-            DES_SP_DECRYPT_ROUND((left), (right), (temp2), (kp));       \
+-            DES_SP_DECRYPT_ROUND((right), (left), (temp2), (kp));       \
+-        }                                                               \
+-        DES_FINAL_PERM((left), (right), (temp2));                       \
+-    } while (0)
+-
+-#if defined(CONFIG_SMALL) && !defined(CONFIG_SMALL_NO_CRYPTO)
+-extern void krb5int_des_do_encrypt_2(unsigned DES_INT32 *l,
+-                                     unsigned DES_INT32 *r,
+-                                     const unsigned DES_INT32 *k);
+-extern void krb5int_des_do_decrypt_2(unsigned DES_INT32 *l,
+-                                     unsigned DES_INT32 *r,
+-                                     const unsigned DES_INT32 *k);
+-#define DES_DO_ENCRYPT(L,R,K) krb5int_des_do_encrypt_2(&(L), &(R), (K))
+-#define DES_DO_DECRYPT(L,R,K) krb5int_des_do_decrypt_2(&(L), &(R), (K))
+-#else
+-#define DES_DO_ENCRYPT DES_DO_ENCRYPT_1
+-#define DES_DO_DECRYPT DES_DO_DECRYPT_1
+-#endif
+-
+-/*
+- * These are handy dandy utility thingies for straightening out bytes.
+- * Included here because they're used a couple of places.
+- */
+-#define GET_HALF_BLOCK(lr, ip)  ((lr) = load_32_be(ip), (ip) += 4)
+-#define PUT_HALF_BLOCK(lr, op)  (store_32_be(lr, op), (op) += 4)
+-
+-/* Shorthand that we'll need in several places, for creating values that
+-   really can hold 32 bits regardless of the prevailing int size.  */
+-#define FF_UINT32       ((unsigned DES_INT32) 0xFF)
+-
+-#endif  /* __DES_TABLES_H__ */
+diff --git a/src/lib/crypto/builtin/des/key_sched.c b/src/lib/crypto/builtin/des/key_sched.c
+deleted file mode 100644
+index 87f02b6a9..000000000
+--- a/src/lib/crypto/builtin/des/key_sched.c
++++ /dev/null
+@@ -1,62 +0,0 @@
+-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+-/* lib/crypto/builtin/des/key_sched.c */
+-/*
+- * Copyright 1985, 1986, 1987, 1988, 1990 by the Massachusetts Institute
+- * of Technology.
+- * All Rights Reserved.
+- *
+- * Export of this software from the United States of America may
+- *   require a specific license from the United States Government.
+- *   It is the responsibility of any person or organization contemplating
+- *   export to obtain such a license before exporting.
+- *
+- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+- * distribute this software and its documentation for any purpose and
+- * without fee is hereby granted, provided that the above copyright
+- * notice appear in all copies and that both that copyright notice and
+- * this permission notice appear in supporting documentation, and that
+- * the name of M.I.T. not be used in advertising or publicity pertaining
+- * to distribution of the software without specific, written prior
+- * permission.  Furthermore if you modify this software you must label
+- * your software as modified software and not distribute it in such a
+- * fashion that it might be confused with the original M.I.T. software.
+- * M.I.T. makes no representations about the suitability of
+- * this software for any purpose.  It is provided "as is" without express
+- * or implied warranty.
+- */
+-
+-/*
+- * This routine computes the DES key schedule given a key.  The
+- * permutations and shifts have been done at compile time, resulting
+- * in a direct one-step mapping from the input key to the key
+- * schedule.
+- *
+- * Also checks parity and weak keys.
+- *
+- * Watch out for the subscripts -- most effectively start at 1 instead
+- * of at zero.  Maybe some bugs in that area.
+- *
+- * In case the user wants to cache the computed key schedule, it is
+- * passed as an arg.  Also implies that caller has explicit control
+- * over zeroing both the key schedule and the key.
+- *
+- * Originally written 6/85 by Steve Miller, MIT Project Athena.
+- */
+-
+-#include "k5-int.h"
+-#include "des_int.h"
+-
+-int
+-mit_des_key_sched(mit_des_cblock k, mit_des_key_schedule schedule)
+-{
+-    mit_des_make_key_sched(k,schedule);
+-
+-    if (!mit_des_check_key_parity(k))   /* bad parity --> return -1 */
+-        return(-1);
+-
+-    if (mit_des_is_weak_key(k))
+-        return(-2);
+-
+-    /* if key was good, return 0 */
+-    return 0;
+-}
+diff --git a/src/lib/crypto/builtin/des/keytest.data b/src/lib/crypto/builtin/des/keytest.data
+deleted file mode 100644
+index 7ff34eedc..000000000
+--- a/src/lib/crypto/builtin/des/keytest.data
++++ /dev/null
+@@ -1,171 +0,0 @@
+-0101010101010101 95F8A5E5DD31D900 8000000000000000
+-0101010101010101 DD7F121CA5015619 4000000000000000
+-0101010101010101 2E8653104F3834EA 2000000000000000
+-0101010101010101 4BD388FF6CD81D4F 1000000000000000
+-0101010101010101 20B9E767B2FB1456 0800000000000000
+-0101010101010101 55579380D77138EF 0400000000000000
+-0101010101010101 6CC5DEFAAF04512F 0200000000000000
+-0101010101010101 0D9F279BA5D87260 0100000000000000
+-0101010101010101 D9031B0271BD5A0A 0080000000000000
+-0101010101010101 424250B37C3DD951 0040000000000000
+-0101010101010101 B8061B7ECD9A21E5 0020000000000000
+-0101010101010101 F15D0F286B65BD28 0010000000000000
+-0101010101010101 ADD0CC8D6E5DEBA1 0008000000000000
+-0101010101010101 E6D5F82752AD63D1 0004000000000000
+-0101010101010101 ECBFE3BD3F591A5E 0002000000000000
+-0101010101010101 F356834379D165CD 0001000000000000
+-0101010101010101 2B9F982F20037FA9 0000800000000000
+-0101010101010101 889DE068A16F0BE6 0000400000000000
+-0101010101010101 E19E275D846A1298 0000200000000000
+-0101010101010101 329A8ED523D71AEC 0000100000000000
+-0101010101010101 E7FCE22557D23C97 0000080000000000
+-0101010101010101 12A9F5817FF2D65D 0000040000000000
+-0101010101010101 A484C3AD38DC9C19 0000020000000000
+-0101010101010101 FBE00A8A1EF8AD72 0000010000000000
+-0101010101010101 750D079407521363 0000008000000000
+-0101010101010101 64FEED9C724C2FAF 0000004000000000
+-0101010101010101 F02B263B328E2B60 0000002000000000
+-0101010101010101 9D64555A9A10B852 0000001000000000
+-0101010101010101 D106FF0BED5255D7 0000000800000000
+-0101010101010101 E1652C6B138C64A5 0000000400000000
+-0101010101010101 E428581186EC8F46 0000000200000000
+-0101010101010101 AEB5F5EDE22D1A36 0000000100000000
+-0101010101010101 E943D7568AEC0C5C 0000000080000000
+-0101010101010101 DF98C8276F54B04B 0000000040000000
+-0101010101010101 B160E4680F6C696F 0000000020000000
+-0101010101010101 FA0752B07D9C4AB8 0000000010000000
+-0101010101010101 CA3A2B036DBC8502 0000000008000000
+-0101010101010101 5E0905517BB59BCF 0000000004000000
+-0101010101010101 814EEB3B91D90726 0000000002000000
+-0101010101010101 4D49DB1532919C9F 0000000001000000
+-0101010101010101 25EB5FC3F8CF0621 0000000000800000
+-0101010101010101 AB6A20C0620D1C6F 0000000000400000
+-0101010101010101 79E90DBC98F92CCA 0000000000200000
+-0101010101010101 866ECEDD8072BB0E 0000000000100000
+-0101010101010101 8B54536F2F3E64A8 0000000000080000
+-0101010101010101 EA51D3975595B86B 0000000000040000
+-0101010101010101 CAFFC6AC4542DE31 0000000000020000
+-0101010101010101 8DD45A2DDF90796C 0000000000010000
+-0101010101010101 1029D55E880EC2D0 0000000000008000
+-0101010101010101 5D86CB23639DBEA9 0000000000004000
+-0101010101010101 1D1CA853AE7C0C5F 0000000000002000
+-0101010101010101 CE332329248F3228 0000000000001000
+-0101010101010101 8405D1ABE24FB942 0000000000000800
+-0101010101010101 E643D78090CA4207 0000000000000400
+-0101010101010101 48221B9937748A23 0000000000000200
+-0101010101010101 DD7C0BBD61FAFD54 0000000000000100
+-0101010101010101 2FBC291A570DB5C4 0000000000000080
+-0101010101010101 E07C30D7E4E26E12 0000000000000040
+-0101010101010101 0953E2258E8E90A1 0000000000000020
+-0101010101010101 5B711BC4CEEBF2EE 0000000000000010
+-0101010101010101 CC083F1E6D9E85F6 0000000000000008
+-0101010101010101 D2FD8867D50D2DFE 0000000000000004
+-0101010101010101 06E7EA22CE92708F 0000000000000002
+-0101010101010101 166B40B44ABA4BD6 0000000000000001
+-8001010101010101 0000000000000000 95A8D72813DAA94D
+-4001010101010101 0000000000000000 0EEC1487DD8C26D5
+-2001010101010101 0000000000000000 7AD16FFB79C45926
+-1001010101010101 0000000000000000 D3746294CA6A6CF3
+-0801010101010101 0000000000000000 809F5F873C1FD761
+-0401010101010101 0000000000000000 C02FAFFEC989D1FC
+-0201010101010101 0000000000000000 4615AA1D33E72F10
+-0180010101010101 0000000000000000 2055123350C00858
+-0140010101010101 0000000000000000 DF3B99D6577397C8
+-0120010101010101 0000000000000000 31FE17369B5288C9
+-0110010101010101 0000000000000000 DFDD3CC64DAE1642
+-0108010101010101 0000000000000000 178C83CE2B399D94
+-0104010101010101 0000000000000000 50F636324A9B7F80
+-0102010101010101 0000000000000000 A8468EE3BC18F06D
+-0101800101010101 0000000000000000 A2DC9E92FD3CDE92
+-0101400101010101 0000000000000000 CAC09F797D031287
+-0101200101010101 0000000000000000 90BA680B22AEB525
+-0101100101010101 0000000000000000 CE7A24F350E280B6
+-0101080101010101 0000000000000000 882BFF0AA01A0B87
+-0101040101010101 0000000000000000 25610288924511C2
+-0101020101010101 0000000000000000 C71516C29C75D170
+-0101018001010101 0000000000000000 5199C29A52C9F059
+-0101014001010101 0000000000000000 C22F0A294A71F29F
+-0101012001010101 0000000000000000 EE371483714C02EA
+-0101011001010101 0000000000000000 A81FBD448F9E522F
+-0101010801010101 0000000000000000 4F644C92E192DFED
+-0101010401010101 0000000000000000 1AFA9A66A6DF92AE
+-0101010201010101 0000000000000000 B3C1CC715CB879D8
+-0101010180010101 0000000000000000 19D032E64AB0BD8B
+-0101010140010101 0000000000000000 3CFAA7A7DC8720DC
+-0101010120010101 0000000000000000 B7265F7F447AC6F3
+-0101010110010101 0000000000000000 9DB73B3C0D163F54
+-0101010108010101 0000000000000000 8181B65BABF4A975
+-0101010104010101 0000000000000000 93C9B64042EAA240
+-0101010102010101 0000000000000000 5570530829705592
+-0101010101800101 0000000000000000 8638809E878787A0
+-0101010101400101 0000000000000000 41B9A79AF79AC208
+-0101010101200101 0000000000000000 7A9BE42F2009A892
+-0101010101100101 0000000000000000 29038D56BA6D2745
+-0101010101080101 0000000000000000 5495C6ABF1E5DF51
+-0101010101040101 0000000000000000 AE13DBD561488933
+-0101010101020101 0000000000000000 024D1FFA8904E389
+-0101010101018001 0000000000000000 D1399712F99BF02E
+-0101010101014001 0000000000000000 14C1D7C1CFFEC79E
+-0101010101012001 0000000000000000 1DE5279DAE3BED6F
+-0101010101011001 0000000000000000 E941A33F85501303
+-0101010101010801 0000000000000000 DA99DBBC9A03F379
+-0101010101010401 0000000000000000 B7FC92F91D8E92E9
+-0101010101010201 0000000000000000 AE8E5CAA3CA04E85
+-0101010101010180 0000000000000000 9CC62DF43B6EED74
+-0101010101010140 0000000000000000 D863DBB5C59A91A0
+-0101010101010120 0000000000000000 A1AB2190545B91D7
+-0101010101010110 0000000000000000 0875041E64C570F7
+-0101010101010108 0000000000000000 5A594528BEBEF1CC
+-0101010101010104 0000000000000000 FCDB3291DE21F0C0
+-0101010101010102 0000000000000000 869EFD7F9F265A09
+-1046913489980131 0000000000000000 88D55E54F54C97B4
+-1007103489988020 0000000000000000 0C0CC00C83EA48FD
+-10071034C8980120 0000000000000000 83BC8EF3A6570183
+-1046103489988020 0000000000000000 DF725DCAD94EA2E9
+-1086911519190101 0000000000000000 E652B53B550BE8B0
+-1086911519580101 0000000000000000 AF527120C485CBB0
+-5107B01519580101 0000000000000000 0F04CE393DB926D5
+-1007B01519190101 0000000000000000 C9F00FFC74079067
+-3107915498080101 0000000000000000 7CFD82A593252B4E
+-3107919498080101 0000000000000000 CB49A2F9E91363E3
+-10079115B9080140 0000000000000000 00B588BE70D23F56
+-3107911598080140 0000000000000000 406A9A6AB43399AE
+-1007D01589980101 0000000000000000 6CB773611DCA9ADA
+-9107911589980101 0000000000000000 67FD21C17DBB5D70
+-9107D01589190101 0000000000000000 9592CB4110430787
+-1007D01598980120 0000000000000000 A6B7FF68A318DDD3
+-1007940498190101 0000000000000000 4D102196C914CA16
+-0107910491190401 0000000000000000 2DFA9F4573594965
+-0107910491190101 0000000000000000 B46604816C0E0774
+-0107940491190401 0000000000000000 6E7E6221A4F34E87
+-19079210981A0101 0000000000000000 AA85E74643233199
+-1007911998190801 0000000000000000 2E5A19DB4D1962D6
+-10079119981A0801 0000000000000000 23A866A809D30894
+-1007921098190101 0000000000000000 D812D961F017D320
+-100791159819010B 0000000000000000 055605816E58608F
+-1004801598190101 0000000000000000 ABD88E8B1B7716F1
+-1004801598190102 0000000000000000 537AC95BE69DA1E1
+-1004801598190108 0000000000000000 AED0F6AE3C25CDD8
+-1002911598100104 0000000000000000 B3E35A5EE53E7B8D
+-1002911598190104 0000000000000000 61C79C71921A2EF8
+-1002911598100201 0000000000000000 E2F5728F0995013C
+-1002911698100101 0000000000000000 1AEAC39A61F0A464
+-7CA110454A1A6E57 01A1D6D039776742 690F5B0D9A26939B
+-0131D9619DC1376E 5CD54CA83DEF57DA 7A389D10354BD271
+-07A1133E4A0B2686 0248D43806F67172 868EBB51CAB4599A
+-3849674C2602319E 51454B582DDF440A 7178876E01F19B2A
+-04B915BA43FEB5B6 42FD443059577FA2 AF37FB421F8C4095
+-0113B970FD34F2CE 059B5E0851CF143A 86A560F10EC6D85B
+-0170F175468FB5E6 0756D8E0774761D2 0CD3DA020021DC09
+-43297FAD38E373FE 762514B829BF486A EA676B2CB7DB2B7A
+-07A7137045DA2A16 3BDD119049372802 DFD64A815CAF1A0F
+-04689104C2FD3B2F 26955F6835AF609A 5C513C9C4886C088
+-37D06BB516CB7546 164D5E404F275232 0A2AEEAE3FF4AB77
+-1F08260D1AC2465E 6B056E18759F5CCA EF1BF03E5DFA575A
+-584023641ABA6176 004BD6EF09176062 88BF0DB6D70DEE56
+-025816164629B007 480D39006EE762F2 A1F9915541020B56
+-49793EBC79B3258F 437540C8698F3CFA 6FBF1CAFCFFD0556
+-4FB05E1515AB73A7 072D43A077075292 2F22E49BAB7CA1AC
+-49E95D6D4CA229BF 02FE55778117F12A 5A6B612CC26CCE4A
+-018310DC409B26D6 1D9D5C5018F728C2 5F4C038ED12B2E41
+-1C587F1C13924FEF 305532286D6F295A 63FAC0D034D9F793
+diff --git a/src/lib/crypto/builtin/des/t_verify.c b/src/lib/crypto/builtin/des/t_verify.c
+deleted file mode 100644
+index f4332f5c0..000000000
+--- a/src/lib/crypto/builtin/des/t_verify.c
++++ /dev/null
+@@ -1,395 +0,0 @@
+-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+-/* lib/crypto/builtin/des/t_verify.c */
+-/*
+- * Copyright 1988, 1990 by the Massachusetts Institute of Technology.
+- * All Rights Reserved.
+- *
+- * Export of this software from the United States of America may
+- *   require a specific license from the United States Government.
+- *   It is the responsibility of any person or organization contemplating
+- *   export to obtain such a license before exporting.
+- *
+- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+- * distribute this software and its documentation for any purpose and
+- * without fee is hereby granted, provided that the above copyright
+- * notice appear in all copies and that both that copyright notice and
+- * this permission notice appear in supporting documentation, and that
+- * the name of M.I.T. not be used in advertising or publicity pertaining
+- * to distribution of the software without specific, written prior
+- * permission.  Furthermore if you modify this software you must label
+- * your software as modified software and not distribute it in such a
+- * fashion that it might be confused with the original M.I.T. software.
+- * M.I.T. makes no representations about the suitability of
+- * this software for any purpose.  It is provided "as is" without express
+- * or implied warranty.
+- */
+-/*
+- * Copyright (C) 1998 by the FundsXpress, INC.
+- *
+- * All rights reserved.
+- *
+- * Export of this software from the United States of America may require
+- * a specific license from the United States Government.  It is the
+- * responsibility of any person or organization contemplating export to
+- * obtain such a license before exporting.
+- *
+- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+- * distribute this software and its documentation for any purpose and
+- * without fee is hereby granted, provided that the above copyright
+- * notice appear in all copies and that both that copyright notice and
+- * this permission notice appear in supporting documentation, and that
+- * the name of FundsXpress. not be used in advertising or publicity pertaining
+- * to distribution of the software without specific, written prior
+- * permission.  FundsXpress makes no representations about the suitability of
+- * this software for any purpose.  It is provided "as is" without express
+- * or implied warranty.
+- *
+- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+- */
+-
+-/*
+- *
+- * Program to test the correctness of the DES library
+- * implementation.
+- *
+- * exit returns  0 ==> success
+- *              -1 ==> error
+- */
+-
+-#include "k5-int.h"
+-#include "des_int.h"
+-#include <stdio.h>
+-#include "com_err.h"
+-
+-static void do_encrypt(unsigned char *, unsigned char *);
+-static void do_decrypt(unsigned char *, unsigned char *);
+-
+-char *progname;
+-int nflag = 2;
+-int vflag;
+-int mflag;
+-int zflag;
+-int pid;
+-int mit_des_debug;
+-
+-unsigned char cipher_text[64];
+-unsigned char clear_text[64] = "Now is the time for all " ;
+-unsigned char clear_text2[64] = "7654321 Now is the time for ";
+-unsigned char clear_text3[64] = {2,0,0,0, 1,0,0,0};
+-unsigned char output[64];
+-unsigned char zero_text[8] = {0x0,0,0,0,0,0,0,0};
+-unsigned char msb_text[8] = {0x0,0,0,0, 0,0,0,0x40}; /* to ANSI MSB */
+-unsigned char *input;
+-
+-/* 0x0123456789abcdef */
+-unsigned char default_key[8] = {
+-    0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef
+-};
+-unsigned char key2[8] = { 0x08,0x19,0x2a,0x3b,0x4c,0x5d,0x6e,0x7f };
+-unsigned char key3[8] = { 0x80,1,1,1,1,1,1,1 };
+-mit_des_cblock s_key;
+-unsigned char default_ivec[8] = {
+-    0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef
+-};
+-unsigned char *ivec;
+-unsigned char zero_key[8] = {1,1,1,1,1,1,1,1}; /* just parity bits */
+-
+-unsigned char cipher1[8] = {
+-    0x25,0xdd,0xac,0x3e,0x96,0x17,0x64,0x67
+-};
+-unsigned char cipher2[8] = {
+-    0x3f,0xa4,0x0e,0x8a,0x98,0x4d,0x48,0x15
+-};
+-unsigned char cipher3[64] = {
+-    0xe5,0xc7,0xcd,0xde,0x87,0x2b,0xf2,0x7c,
+-    0x43,0xe9,0x34,0x00,0x8c,0x38,0x9c,0x0f,
+-    0x68,0x37,0x88,0x49,0x9a,0x7c,0x05,0xf6
+-};
+-unsigned char checksum[8] = {
+-    0x58,0xd2,0xe7,0x7e,0x86,0x06,0x27,0x33
+-};
+-
+-unsigned char zresult[8] = {
+-    0x8c, 0xa6, 0x4d, 0xe9, 0xc1, 0xb1, 0x23, 0xa7
+-};
+-
+-unsigned char mresult[8] = {
+-    0xa3, 0x80, 0xe0, 0x2a, 0x6b, 0xe5, 0x46, 0x96
+-};
+-
+-
+-/*
+- * Can also add :
+- * plaintext = 0, key = 0, cipher = 0x8ca64de9c1b123a7 (or is it a 1?)
+- */
+-
+-mit_des_key_schedule sched;
+-
+-int
+-main(argc,argv)
+-    int argc;
+-    char *argv[];
+-{
+-    /* Local Declarations */
+-    size_t  in_length;
+-    int  retval;
+-    int i, j;
+-
+-#ifdef WINDOWS
+-    /* Set screen window buffer to infinite size -- MS default is tiny.  */
+-    _wsetscreenbuf (fileno (stdout), _WINBUFINF);
+-#endif
+-    progname=argv[0];           /* salt away invoking program */
+-
+-    while (--argc > 0 && (*++argv)[0] == '-')
+-        for (i=1; argv[0][i] != '\0'; i++) {
+-            switch (argv[0][i]) {
+-
+-                /* debug flag */
+-            case 'd':
+-                mit_des_debug=3;
+-                continue;
+-
+-            case 'z':
+-                zflag = 1;
+-                continue;
+-
+-            case 'm':
+-                mflag = 1;
+-                continue;
+-
+-            default:
+-                printf("%s: illegal flag \"%c\" ",
+-                       progname,argv[0][i]);
+-                exit(1);
+-            }
+-        };
+-
+-    if (argc) {
+-        fprintf(stderr, "Usage: %s [-dmz]\n", progname);
+-        exit(1);
+-    }
+-
+-    /* do some initialisation */
+-
+-    /* use known input and key */
+-
+-    /* ECB zero text zero key */
+-    if (zflag) {
+-        input = zero_text;
+-        mit_des_key_sched(zero_key, sched);
+-        printf("plaintext = key = 0, cipher = 0x8ca64de9c1b123a7\n");
+-        do_encrypt(input,cipher_text);
+-        printf("\tcipher  = (low to high bytes)\n\t\t");
+-        for (j = 0; j<=7; j++)
+-            printf("%02x ",cipher_text[j]);
+-        printf("\n");
+-        do_decrypt(output,cipher_text);
+-        if ( memcmp((char *)cipher_text, (char *)zresult, 8) ) {
+-            printf("verify: error in zero key test\n");
+-            exit(-1);
+-        }
+-
+-        exit(0);
+-    }
+-
+-    if (mflag) {
+-        input = msb_text;
+-        mit_des_key_sched(key3, sched);
+-        printf("plaintext = 0x00 00 00 00 00 00 00 40, ");
+-        printf("key = 0x80 01 01 01 01 01 01 01\n");
+-        printf("        cipher = 0xa380e02a6be54696\n");
+-        do_encrypt(input,cipher_text);
+-        printf("\tcipher  = (low to high bytes)\n\t\t");
+-        for (j = 0; j<=7; j++) {
+-            printf("%02x ",cipher_text[j]);
+-        }
+-        printf("\n");
+-        do_decrypt(output,cipher_text);
+-        if ( memcmp((char *)cipher_text, (char *)mresult, 8) ) {
+-            printf("verify: error in msb test\n");
+-            exit(-1);
+-        }
+-        exit(0);
+-    }
+-
+-    /* ECB mode Davies and Price */
+-    {
+-        input = zero_text;
+-        mit_des_key_sched(key2, sched);
+-        printf("Examples per FIPS publication 81, keys ivs and cipher\n");
+-        printf("in hex.  These are the correct answers, see below for\n");
+-        printf("the actual answers.\n\n");
+-        printf("Examples per Davies and Price.\n\n");
+-        printf("EXAMPLE ECB\tkey = 08192a3b4c5d6e7f\n");
+-        printf("\tclear = 0\n");
+-        printf("\tcipher = 25 dd ac 3e 96 17 64 67\n");
+-        printf("ACTUAL ECB\n");
+-        printf("\tclear \"%s\"\n", input);
+-        do_encrypt(input,cipher_text);
+-        printf("\tcipher  = (low to high bytes)\n\t\t");
+-        for (j = 0; j<=7; j++)
+-            printf("%02x ",cipher_text[j]);
+-        printf("\n\n");
+-        do_decrypt(output,cipher_text);
+-        if ( memcmp((char *)cipher_text, (char *)cipher1, 8) ) {
+-            printf("verify: error in ECB encryption\n");
+-            exit(-1);
+-        }
+-        else
+-            printf("verify: ECB encryption is correct\n\n");
+-    }
+-
+-    /* ECB mode */
+-    {
+-        mit_des_key_sched(default_key, sched);
+-        input = clear_text;
+-        ivec = default_ivec;
+-        printf("EXAMPLE ECB\tkey = 0123456789abcdef\n");
+-        printf("\tclear = \"Now is the time for all \"\n");
+-        printf("\tcipher = 3f a4 0e 8a 98 4d 48 15 ...\n");
+-        printf("ACTUAL ECB\n\tclear \"%s\"",input);
+-        do_encrypt(input,cipher_text);
+-        printf("\n\tcipher      = (low to high bytes)\n\t\t");
+-        for (j = 0; j<=7; j++) {
+-            printf("%02x ",cipher_text[j]);
+-        }
+-        printf("\n\n");
+-        do_decrypt(output,cipher_text);
+-        if ( memcmp((char *)cipher_text, (char *)cipher2, 8) ) {
+-            printf("verify: error in ECB encryption\n");
+-            exit(-1);
+-        }
+-        else
+-            printf("verify: ECB encryption is correct\n\n");
+-    }
+-
+-    /* CBC mode */
+-    printf("EXAMPLE CBC\tkey = 0123456789abcdef");
+-    printf("\tiv = 1234567890abcdef\n");
+-    printf("\tclear = \"Now is the time for all \"\n");
+-    printf("\tcipher =\te5 c7 cd de 87 2b f2 7c\n");
+-    printf("\t\t\t43 e9 34 00 8c 38 9c 0f\n");
+-    printf("\t\t\t68 37 88 49 9a 7c 05 f6\n");
+-
+-    printf("ACTUAL CBC\n\tclear \"%s\"\n",input);
+-    in_length =  strlen((char *)input);
+-    if ((retval = mit_des_cbc_encrypt((const mit_des_cblock *) input,
+-                                      (mit_des_cblock *) cipher_text,
+-                                      (size_t) in_length,
+-                                      sched,
+-                                      ivec,
+-                                      MIT_DES_ENCRYPT))) {
+-        com_err("des verify", retval, "can't encrypt");
+-        exit(-1);
+-    }
+-    printf("\tciphertext = (low to high bytes)\n");
+-    for (i = 0; i <= 2; i++) {
+-        printf("\t\t");
+-        for (j = 0; j <= 7; j++) {
+-            printf("%02x ",cipher_text[i*8+j]);
+-        }
+-        printf("\n");
+-    }
+-    if ((retval = mit_des_cbc_encrypt((const mit_des_cblock *) cipher_text,
+-                                      (mit_des_cblock *) clear_text,
+-                                      (size_t) in_length,
+-                                      sched,
+-                                      ivec,
+-                                      MIT_DES_DECRYPT))) {
+-        com_err("des verify", retval, "can't decrypt");
+-        exit(-1);
+-    }
+-    printf("\tdecrypted clear_text = \"%s\"\n",clear_text);
+-
+-    if ( memcmp((char *)cipher_text, (char *)cipher3, in_length) ) {
+-        printf("verify: error in CBC encryption\n");
+-        exit(-1);
+-    }
+-    else
+-        printf("verify: CBC encryption is correct\n\n");
+-
+-    printf("EXAMPLE CBC checksum");
+-    printf("\tkey =  0123456789abcdef\tiv =  1234567890abcdef\n");
+-    printf("\tclear =\t\t\"7654321 Now is the time for \"\n");
+-    printf("\tchecksum\t58 d2 e7 7e 86 06 27 33, ");
+-    printf("or some part thereof\n");
+-    input = clear_text2;
+-    mit_des_cbc_cksum(input,cipher_text, strlen((char *)input),
+-                      sched,ivec);
+-    printf("ACTUAL CBC checksum\n");
+-    printf("\t\tencrypted cksum = (low to high bytes)\n\t\t");
+-    for (j = 0; j<=7; j++)
+-        printf("%02x ",cipher_text[j]);
+-    printf("\n\n");
+-    if ( memcmp((char *)cipher_text, (char *)checksum, 8) ) {
+-        printf("verify: error in CBC cheksum\n");
+-        exit(-1);
+-    }
+-    else
+-        printf("verify: CBC checksum is correct\n\n");
+-
+-    exit(0);
+-}
+-
+-static void
+-do_encrypt(in,out)
+-    unsigned char *in;
+-    unsigned char *out;
+-{
+-    int i, j;
+-    for (i =1; i<=nflag; i++) {
+-        mit_des_cbc_encrypt((const mit_des_cblock *)in,
+-                            (mit_des_cblock *)out,
+-                            8,
+-                            sched,
+-                            zero_text,
+-                            MIT_DES_ENCRYPT);
+-        if (mit_des_debug) {
+-            printf("\nclear %s\n",in);
+-            for (j = 0; j<=7; j++)
+-                printf("%02X ",in[j] & 0xff);
+-            printf("\tcipher ");
+-            for (j = 0; j<=7; j++)
+-                printf("%02X ",out[j] & 0xff);
+-        }
+-    }
+-}
+-
+-static void
+-do_decrypt(in,out)
+-    unsigned char *out;
+-    unsigned char *in;
+-    /* try to invert it */
+-{
+-    int i, j;
+-    for (i =1; i<=nflag; i++) {
+-        mit_des_cbc_encrypt((const mit_des_cblock *)out,
+-                            (mit_des_cblock *)in,
+-                            8,
+-                            sched,
+-                            zero_text,
+-                            MIT_DES_DECRYPT);
+-        if (mit_des_debug) {
+-            printf("clear %s\n",in);
+-            for (j = 0; j<=7; j++)
+-                printf("%02X ",in[j] & 0xff);
+-            printf("\tcipher ");
+-            for (j = 0; j<=7; j++)
+-                printf("%02X ",out[j] & 0xff);
+-        }
+-    }
+-}
+-
+-/*
+- * Fake out the DES library, for the purposes of testing.
+- */
+-
+-int
+-mit_des_is_weak_key(key)
+-    mit_des_cblock key;
+-{
+-    return 0;                           /* fake it out for testing */
+-}
+diff --git a/src/lib/crypto/builtin/des/weak_key.c b/src/lib/crypto/builtin/des/weak_key.c
+deleted file mode 100644
+index eb41b267d..000000000
+--- a/src/lib/crypto/builtin/des/weak_key.c
++++ /dev/null
+@@ -1,86 +0,0 @@
+-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+-/* lib/crypto/builtin/des/weak_key.c */
+-/*
+- * Copyright 1989,1990 by the Massachusetts Institute of Technology.
+- * All Rights Reserved.
+- *
+- * Export of this software from the United States of America may
+- *   require a specific license from the United States Government.
+- *   It is the responsibility of any person or organization contemplating
+- *   export to obtain such a license before exporting.
+- *
+- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+- * distribute this software and its documentation for any purpose and
+- * without fee is hereby granted, provided that the above copyright
+- * notice appear in all copies and that both that copyright notice and
+- * this permission notice appear in supporting documentation, and that
+- * the name of M.I.T. not be used in advertising or publicity pertaining
+- * to distribution of the software without specific, written prior
+- * permission.  Furthermore if you modify this software you must label
+- * your software as modified software and not distribute it in such a
+- * fashion that it might be confused with the original M.I.T. software.
+- * M.I.T. makes no representations about the suitability of
+- * this software for any purpose.  It is provided "as is" without express
+- * or implied warranty.
+- */
+-
+-/*
+- * Under U.S. law, this software may not be exported outside the US
+- * without license from the U.S. Commerce department.
+- *
+- * These routines form the library interface to the DES facilities.
+- *
+- * Originally written 8/85 by Steve Miller, MIT Project Athena.
+- */
+-
+-#include "k5-int.h"
+-#include "des_int.h"
+-
+-/*
+- * The following are the weak DES keys:
+- */
+-static const mit_des_cblock weak[16] = {
+-    /* weak keys */
+-    {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01},
+-    {0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe},
+-    {0x1f,0x1f,0x1f,0x1f,0x0e,0x0e,0x0e,0x0e},
+-    {0xe0,0xe0,0xe0,0xe0,0xf1,0xf1,0xf1,0xf1},
+-
+-    /* semi-weak */
+-    {0x01,0xfe,0x01,0xfe,0x01,0xfe,0x01,0xfe},
+-    {0xfe,0x01,0xfe,0x01,0xfe,0x01,0xfe,0x01},
+-
+-    {0x1f,0xe0,0x1f,0xe0,0x0e,0xf1,0x0e,0xf1},
+-    {0xe0,0x1f,0xe0,0x1f,0xf1,0x0e,0xf1,0x0e},
+-
+-    {0x01,0xe0,0x01,0xe0,0x01,0xf1,0x01,0xf1},
+-    {0xe0,0x01,0xe0,0x01,0xf1,0x01,0xf1,0x01},
+-
+-    {0x1f,0xfe,0x1f,0xfe,0x0e,0xfe,0x0e,0xfe},
+-    {0xfe,0x1f,0xfe,0x1f,0xfe,0x0e,0xfe,0x0e},
+-
+-    {0x01,0x1f,0x01,0x1f,0x01,0x0e,0x01,0x0e},
+-    {0x1f,0x01,0x1f,0x01,0x0e,0x01,0x0e,0x01},
+-
+-    {0xe0,0xfe,0xe0,0xfe,0xf1,0xfe,0xf1,0xfe},
+-    {0xfe,0xe0,0xfe,0xe0,0xfe,0xf1,0xfe,0xf1}
+-};
+-
+-/*
+- * mit_des_is_weak_key: returns true iff key is a [semi-]weak des key.
+- *
+- * Requires: key has correct odd parity.
+- */
+-int
+-mit_des_is_weak_key(mit_des_cblock key)
+-{
+-    unsigned int i;
+-    const mit_des_cblock *weak_p = weak;
+-
+-    for (i = 0; i < (sizeof(weak)/sizeof(mit_des_cblock)); i++) {
+-        if (!memcmp(weak_p++,key,sizeof(mit_des_cblock)))
+-            return 1;
+-    }
+-
+-    return 0;
+-}
+diff --git a/src/lib/crypto/builtin/enc_provider/Makefile.in b/src/lib/crypto/builtin/enc_provider/Makefile.in
+index 3459e1d0e..af6276b96 100644
+--- a/src/lib/crypto/builtin/enc_provider/Makefile.in
++++ b/src/lib/crypto/builtin/enc_provider/Makefile.in
+@@ -1,7 +1,6 @@
+ mydir=lib$(S)crypto$(S)builtin$(S)enc_provider
+ BUILDTOP=$(REL)..$(S)..$(S)..$(S)..
+-LOCALINCLUDES = -I$(srcdir)/../des 	\
+-		-I$(srcdir)/../aes 	\
++LOCALINCLUDES = -I$(srcdir)/../aes 	\
+ 		-I$(srcdir)/../camellia \
+ 		-I$(srcdir)/../../krb 	\
+ 		-I$(srcdir)/..
+@@ -11,19 +10,16 @@ LOCALINCLUDES = -I$(srcdir)/../des 	\
+ ##DOS##OBJFILE = ..\..\$(OUTPRE)enc_provider.lst
+ 
+ STLIBOBJS= \
+-	des3.o 	\
+ 	rc4.o 	\
+ 	aes.o   \
+ 	camellia.o
+ 
+ OBJS= \
+-	$(OUTPRE)des3.$(OBJEXT) 	\
+ 	$(OUTPRE)aes.$(OBJEXT) 	\
+ 	$(OUTPRE)camellia.$(OBJEXT)	\
+ 	$(OUTPRE)rc4.$(OBJEXT)
+ 
+ SRCS= \
+-	$(srcdir)/des3.c 	\
+ 	$(srcdir)/aes.c 	\
+ 	$(srcdir)/camellia.c	\
+ 	$(srcdir)/rc4.c
+diff --git a/src/lib/crypto/builtin/enc_provider/deps b/src/lib/crypto/builtin/enc_provider/deps
+index 7a3324c44..c1201cc1a 100644
+--- a/src/lib/crypto/builtin/enc_provider/deps
++++ b/src/lib/crypto/builtin/enc_provider/deps
+@@ -1,18 +1,6 @@
+ #
+ # Generated makefile dependencies follow.
+ #
+-des3.so des3.po $(OUTPRE)des3.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+-  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+-  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h \
+-  $(srcdir)/../aes/aes.h $(srcdir)/../crypto_mod.h $(srcdir)/../des/des_int.h \
+-  $(srcdir)/../sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+-  $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+-  $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+-  $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+-  $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+-  $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+-  $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+-  $(top_srcdir)/include/socket-utils.h des3.c
+ aes.so aes.po $(OUTPRE)aes.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+   $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+   $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h \
+diff --git a/src/lib/crypto/builtin/enc_provider/des3.c b/src/lib/crypto/builtin/enc_provider/des3.c
+deleted file mode 100644
+index 9b8244223..000000000
+--- a/src/lib/crypto/builtin/enc_provider/des3.c
++++ /dev/null
+@@ -1,105 +0,0 @@
+-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+-/*
+- * Copyright (C) 1998 by the FundsXpress, INC.
+- *
+- * All rights reserved.
+- *
+- * Export of this software from the United States of America may require
+- * a specific license from the United States Government.  It is the
+- * responsibility of any person or organization contemplating export to
+- * obtain such a license before exporting.
+- *
+- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+- * distribute this software and its documentation for any purpose and
+- * without fee is hereby granted, provided that the above copyright
+- * notice appear in all copies and that both that copyright notice and
+- * this permission notice appear in supporting documentation, and that
+- * the name of FundsXpress. not be used in advertising or publicity pertaining
+- * to distribution of the software without specific, written prior
+- * permission.  FundsXpress makes no representations about the suitability of
+- * this software for any purpose.  It is provided "as is" without express
+- * or implied warranty.
+- *
+- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+- */
+-
+-#include "crypto_int.h"
+-#include "des_int.h"
+-
+-static krb5_error_code
+-validate_and_schedule(krb5_key key, const krb5_data *ivec,
+-                      const krb5_crypto_iov *data, size_t num_data,
+-                      mit_des3_key_schedule *schedule)
+-{
+-    if (key->keyblock.length != 24)
+-        return(KRB5_BAD_KEYSIZE);
+-    if (iov_total_length(data, num_data, FALSE) % 8 != 0)
+-        return(KRB5_BAD_MSIZE);
+-    if (ivec && (ivec->length != 8))
+-        return(KRB5_BAD_MSIZE);
+-
+-    switch (mit_des3_key_sched(*(mit_des3_cblock *)key->keyblock.contents,
+-                               *schedule)) {
+-    case -1:
+-        return(KRB5DES_BAD_KEYPAR);
+-    case -2:
+-        return(KRB5DES_WEAK_KEY);
+-    }
+-    return 0;
+-}
+-
+-static krb5_error_code
+-k5_des3_encrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
+-                size_t num_data)
+-{
+-    mit_des3_key_schedule schedule;
+-    krb5_error_code err;
+-
+-    err = validate_and_schedule(key, ivec, data, num_data, &schedule);
+-    if (err)
+-        return err;
+-
+-    /* this has a return value, but the code always returns zero */
+-    krb5int_des3_cbc_encrypt(data, num_data,
+-                             schedule[0], schedule[1], schedule[2],
+-                             ivec != NULL ? (unsigned char *) ivec->data :
+-                             NULL);
+-
+-    zap(schedule, sizeof(schedule));
+-
+-    return(0);
+-}
+-
+-static krb5_error_code
+-k5_des3_decrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
+-                size_t num_data)
+-{
+-    mit_des3_key_schedule schedule;
+-    krb5_error_code err;
+-
+-    err = validate_and_schedule(key, ivec, data, num_data, &schedule);
+-    if (err)
+-        return err;
+-
+-    /* this has a return value, but the code always returns zero */
+-    krb5int_des3_cbc_decrypt(data, num_data,
+-                             schedule[0], schedule[1], schedule[2],
+-                             ivec != NULL ? (unsigned char *) ivec->data :
+-                             NULL);
+-
+-    zap(schedule, sizeof(schedule));
+-
+-    return 0;
+-}
+-
+-const struct krb5_enc_provider krb5int_enc_des3 = {
+-    8,
+-    21, 24,
+-    k5_des3_encrypt,
+-    k5_des3_decrypt,
+-    NULL,
+-    krb5int_des_init_state,
+-    krb5int_default_free_state
+-};
+diff --git a/src/lib/crypto/crypto_tests/t_cf2.expected b/src/lib/crypto/crypto_tests/t_cf2.expected
+index f8251a16c..bc6aa50c8 100644
+--- a/src/lib/crypto/crypto_tests/t_cf2.expected
++++ b/src/lib/crypto/crypto_tests/t_cf2.expected
+@@ -1,6 +1,5 @@
+ 97df97e4b798b29eb31ed7280287a92a
+ 4d6ca4e629785c1f01baf55e2e548566b9617ae3a96868c337cb93b5e72b1c7b
+-e58f9eb643862c13ad38e529313462a7f73e62834fe54a01
+ 24d7f6b6bae4e5c00d2082c5ebab3672
+ edd02a39d2dbde31611c16e610be062c
+ 67f6ea530aea85a37dcbb23349ea52dcc61ca8493ff557252327fd8304341584
+diff --git a/src/lib/crypto/crypto_tests/t_cf2.in b/src/lib/crypto/crypto_tests/t_cf2.in
+index 73e2f8fbc..c4d23b506 100644
+--- a/src/lib/crypto/crypto_tests/t_cf2.in
++++ b/src/lib/crypto/crypto_tests/t_cf2.in
+@@ -8,11 +8,6 @@ key1
+ key2
+ a
+ b
+-16
+-key1
+-key2
+-a
+-b
+ 23
+ key1
+ key2
+diff --git a/src/lib/crypto/crypto_tests/t_cksums.c b/src/lib/crypto/crypto_tests/t_cksums.c
+index 4da14ea43..84408fb68 100644
+--- a/src/lib/crypto/crypto_tests/t_cksums.c
++++ b/src/lib/crypto/crypto_tests/t_cksums.c
+@@ -59,16 +59,6 @@ struct test {
+           "\xDA\x39\xA3\xEE\x5E\x6B\x4B\x0D\x32\x55\xBF\xEF\x95\x60\x18\x90"
+           "\xAF\xD8\x07\x09" }
+     },
+-    {
+-        { KV5M_DATA, 9, "six seven" },
+-        CKSUMTYPE_HMAC_SHA1_DES3, ENCTYPE_DES3_CBC_SHA1, 2,
+-        { KV5M_DATA, 24,
+-          "\x7A\x25\xDF\x89\x92\x29\x6D\xCE\xDA\x0E\x13\x5B\xC4\x04\x6E\x23"
+-          "\x75\xB3\xC1\x4C\x98\xFB\xC1\x62" },
+-        { KV5M_DATA, 20,
+-          "\x0E\xEF\xC9\xC3\xE0\x49\xAA\xBC\x1B\xA5\xC4\x01\x67\x7D\x9A\xB6"
+-          "\x99\x08\x2B\xB4" }
+-    },
+     {
+         { KV5M_DATA, 37, "eight nine ten eleven twelve thirteen" },
+         CKSUMTYPE_HMAC_SHA1_96_AES128, ENCTYPE_AES128_CTS_HMAC_SHA1_96, 3,
+diff --git a/src/lib/crypto/crypto_tests/t_decrypt.c b/src/lib/crypto/crypto_tests/t_decrypt.c
+index a40a85500..716f2c337 100644
+--- a/src/lib/crypto/crypto_tests/t_decrypt.c
++++ b/src/lib/crypto/crypto_tests/t_decrypt.c
+@@ -39,62 +39,6 @@ struct test {
+     krb5_data keybits;
+     krb5_data ciphertext;
+ } test_cases[] = {
+-    {
+-        ENCTYPE_DES3_CBC_SHA1,
+-        { KV5M_DATA, 0, "", }, 0,
+-        { KV5M_DATA, 24,
+-          "\x7A\x25\xDF\x89\x92\x29\x6D\xCE\xDA\x0E\x13\x5B\xC4\x04\x6E\x23"
+-          "\x75\xB3\xC1\x4C\x98\xFB\xC1\x62" },
+-        { KV5M_DATA, 28,
+-          "\x54\x8A\xF4\xD5\x04\xF7\xD7\x23\x30\x3F\x12\x17\x5F\xE8\x38\x6B"
+-          "\x7B\x53\x35\xA9\x67\xBA\xD6\x1F\x3B\xF0\xB1\x43" }
+-    },
+-    {
+-        ENCTYPE_DES3_CBC_SHA1,
+-        { KV5M_DATA, 1, "1", }, 1,
+-        { KV5M_DATA, 24,
+-          "\xBC\x07\x83\x89\x15\x13\xD5\xCE\x57\xBC\x13\x8F\xD3\xC1\x1A\xE6"
+-          "\x40\x45\x23\x85\x32\x29\x62\xB6" },
+-        { KV5M_DATA, 36,
+-          "\x9C\x3C\x1D\xBA\x47\x47\xD8\x5A\xF2\x91\x6E\x47\x45\xF2\xDC\xE3"
+-          "\x80\x46\x79\x6E\x51\x04\xBC\xCD\xFB\x66\x9A\x91\xD4\x4B\xC3\x56"
+-          "\x66\x09\x45\xC7" }
+-    },
+-    {
+-        ENCTYPE_DES3_CBC_SHA1,
+-        { KV5M_DATA, 9, "9 bytesss", }, 2,
+-        { KV5M_DATA, 24,
+-          "\x2F\xD0\xF7\x25\xCE\x04\x10\x0D\x2F\xC8\xA1\x80\x98\x83\x1F\x85"
+-          "\x0B\x45\xD9\xEF\x85\x0B\xD9\x20" },
+-        { KV5M_DATA, 44,
+-          "\xCF\x91\x44\xEB\xC8\x69\x79\x81\x07\x5A\x8B\xAD\x8D\x74\xE5\xD7"
+-          "\xD5\x91\xEB\x7D\x97\x70\xC7\xAD\xA2\x5E\xE8\xC5\xB3\xD6\x94\x44"
+-          "\xDF\xEC\x79\xA5\xB7\xA0\x14\x82\xD9\xAF\x74\xE6" }
+-    },
+-    {
+-        ENCTYPE_DES3_CBC_SHA1,
+-        { KV5M_DATA, 13, "13 bytes byte", }, 3,
+-        { KV5M_DATA, 24,
+-          "\x0D\xD5\x20\x94\xE0\xF4\x1C\xEC\xCB\x5B\xE5\x10\xA7\x64\xB3\x51"
+-          "\x76\xE3\x98\x13\x32\xF1\xE5\x98" },
+-        { KV5M_DATA, 44,
+-          "\x83\x9A\x17\x08\x1E\xCB\xAF\xBC\xDC\x91\xB8\x8C\x69\x55\xDD\x3C"
+-          "\x45\x14\x02\x3C\xF1\x77\xB7\x7B\xF0\xD0\x17\x7A\x16\xF7\x05\xE8"
+-          "\x49\xCB\x77\x81\xD7\x6A\x31\x6B\x19\x3F\x8D\x30" }
+-    },
+-    {
+-        ENCTYPE_DES3_CBC_SHA1,
+-        { KV5M_DATA, 30, "30 bytes bytes bytes bytes byt", }, 4,
+-        { KV5M_DATA, 24,
+-          "\xF1\x16\x86\xCB\xBC\x9E\x23\xEA\x54\xFE\xCD\x2A\x3D\xCD\xFB\x20"
+-          "\xB6\xFE\x98\xBF\x26\x45\xC4\xC4" },
+-        { KV5M_DATA, 60,
+-          "\x89\x43\x3E\x83\xFD\x0E\xA3\x66\x6C\xFF\xCD\x18\xD8\xDE\xEB\xC5"
+-          "\x3B\x9A\x34\xED\xBE\xB1\x59\xD9\xF6\x67\xC6\xC2\xB9\xA9\x64\x40"
+-          "\x1D\x55\xE7\xE9\xC6\x8D\x64\x8D\x65\xC3\xAA\x84\xFF\xA3\x79\x0C"
+-          "\x14\xA8\x64\xDA\x80\x73\xA9\xA9\x5C\x4B\xA2\xBC" }
+-    },
+-
+     {
+         ENCTYPE_ARCFOUR_HMAC,
+         { KV5M_DATA, 0, "", }, 0,
+@@ -524,7 +468,6 @@ printhex(const char *head, void *data, size_t len)
+ 
+ static krb5_enctype
+ enctypes[] = {
+-    ENCTYPE_DES3_CBC_SHA1,
+     ENCTYPE_ARCFOUR_HMAC,
+     ENCTYPE_ARCFOUR_HMAC_EXP,
+     ENCTYPE_AES128_CTS_HMAC_SHA1_96,
+diff --git a/src/lib/crypto/crypto_tests/t_derive.c b/src/lib/crypto/crypto_tests/t_derive.c
+index afbf7477f..93ce30da2 100644
+--- a/src/lib/crypto/crypto_tests/t_derive.c
++++ b/src/lib/crypto/crypto_tests/t_derive.c
+@@ -38,41 +38,6 @@ struct test {
+     enum deriv_alg alg;
+     krb5_data expected_key;
+ } test_cases[] = {
+-    /* Kc, Ke, Kei for a DES3 key */
+-    {
+-        ENCTYPE_DES3_CBC_SHA1,
+-        { KV5M_DATA, 24,
+-          "\x85\x0B\xB5\x13\x58\x54\x8C\xD0\x5E\x86\x76\x8C\x31\x3E\x3B\xFE"
+-          "\xF7\x51\x19\x37\xDC\xF7\x2C\x3E" },
+-        { KV5M_DATA, 5, "\0\0\0\2\x99" },
+-        DERIVE_RFC3961,
+-        { KV5M_DATA, 24,
+-          "\xF7\x8C\x49\x6D\x16\xE6\xC2\xDA\xE0\xE0\xB6\xC2\x40\x57\xA8\x4C"
+-          "\x04\x26\xAE\xEF\x26\xFD\x6D\xCE" }
+-    },
+-    {
+-        ENCTYPE_DES3_CBC_SHA1,
+-        { KV5M_DATA, 24,
+-          "\x85\x0B\xB5\x13\x58\x54\x8C\xD0\x5E\x86\x76\x8C\x31\x3E\x3B\xFE"
+-          "\xF7\x51\x19\x37\xDC\xF7\x2C\x3E" },
+-        { KV5M_DATA, 5, "\0\0\0\2\xAA" },
+-        DERIVE_RFC3961,
+-        { KV5M_DATA, 24,
+-          "\x5B\x57\x23\xD0\xB6\x34\xCB\x68\x4C\x3E\xBA\x52\x64\xE9\xA7\x0D"
+-          "\x52\xE6\x83\x23\x1A\xD3\xC4\xCE" }
+-    },
+-    {
+-        ENCTYPE_DES3_CBC_SHA1,
+-        { KV5M_DATA, 24,
+-          "\x85\x0B\xB5\x13\x58\x54\x8C\xD0\x5E\x86\x76\x8C\x31\x3E\x3B\xFE"
+-          "\xF7\x51\x19\x37\xDC\xF7\x2C\x3E" },
+-        { KV5M_DATA, 5, "\0\0\0\2\x55" },
+-        DERIVE_RFC3961,
+-        { KV5M_DATA, 24,
+-          "\xA7\x7C\x94\x98\x0E\x9B\x73\x45\xA8\x15\x25\xC4\x23\xA7\x37\xCE"
+-          "\x67\xF4\xCD\x91\xB6\xB3\xDA\x45" }
+-    },
+-
+     /* Kc, Ke, Ki for an AES-128 key */
+     {
+         ENCTYPE_AES128_CTS_HMAC_SHA1_96,
+@@ -286,7 +251,6 @@ static const struct krb5_enc_provider *
+ get_enc_provider(krb5_enctype enctype)
+ {
+     switch (enctype) {
+-    case ENCTYPE_DES3_CBC_SHA1:              return &krb5int_enc_des3;
+     case ENCTYPE_AES128_CTS_HMAC_SHA1_96:    return &krb5int_enc_aes128;
+     case ENCTYPE_AES256_CTS_HMAC_SHA1_96:    return &krb5int_enc_aes256;
+     case ENCTYPE_CAMELLIA128_CTS_CMAC:       return &krb5int_enc_camellia128;
+diff --git a/src/lib/crypto/crypto_tests/t_encrypt.c b/src/lib/crypto/crypto_tests/t_encrypt.c
+index bd9b94691..290a72e1e 100644
+--- a/src/lib/crypto/crypto_tests/t_encrypt.c
++++ b/src/lib/crypto/crypto_tests/t_encrypt.c
+@@ -37,7 +37,6 @@
+ 
+ /* What enctypes should we test?*/
+ krb5_enctype interesting_enctypes[] = {
+-    ENCTYPE_DES3_CBC_SHA1,
+     ENCTYPE_ARCFOUR_HMAC,
+     ENCTYPE_ARCFOUR_HMAC_EXP,
+     ENCTYPE_AES256_CTS_HMAC_SHA1_96,
+diff --git a/src/lib/crypto/crypto_tests/t_short.c b/src/lib/crypto/crypto_tests/t_short.c
+index d4c2b97df..4466b7115 100644
+--- a/src/lib/crypto/crypto_tests/t_short.c
++++ b/src/lib/crypto/crypto_tests/t_short.c
+@@ -34,7 +34,6 @@
+ #include "k5-int.h"
+ 
+ krb5_enctype interesting_enctypes[] = {
+-    ENCTYPE_DES3_CBC_SHA1,
+     ENCTYPE_ARCFOUR_HMAC,
+     ENCTYPE_ARCFOUR_HMAC_EXP,
+     ENCTYPE_AES256_CTS_HMAC_SHA1_96,
+diff --git a/src/lib/crypto/crypto_tests/t_str2key.c b/src/lib/crypto/crypto_tests/t_str2key.c
+index cdb1acc6d..ef4c4a7d3 100644
+--- a/src/lib/crypto/crypto_tests/t_str2key.c
++++ b/src/lib/crypto/crypto_tests/t_str2key.c
+@@ -35,58 +35,6 @@ struct test {
+     krb5_error_code expected_err;
+     krb5_boolean allow_weak;
+ } test_cases[] = {
+-    /* Test vectors from RFC 3961 appendix A.4. */
+-    {
+-        ENCTYPE_DES3_CBC_SHA1,
+-        "password",
+-        { KV5M_DATA, 21, "ATHENA.MIT.EDUraeburn" },
+-        { KV5M_DATA, 0, NULL },
+-        { KV5M_DATA, 24, "\x85\x0B\xB5\x13\x58\x54\x8C\xD0\x5E\x86\x76\x8C"
+-          "\x31\x3E\x3B\xFE\xF7\x51\x19\x37\xDC\xF7\x2C\x3E" },
+-        0,
+-        FALSE
+-    },
+-    {
+-        ENCTYPE_DES3_CBC_SHA1,
+-        "potatoe",
+-        { KV5M_DATA, 19, "WHITEHOUSE.GOVdanny" },
+-        { KV5M_DATA, 0, NULL },
+-        { KV5M_DATA, 24, "\xDF\xCD\x23\x3D\xD0\xA4\x32\x04\xEA\x6D\xC4\x37"
+-          "\xFB\x15\xE0\x61\xB0\x29\x79\xC1\xF7\x4F\x37\x7A" },
+-        0,
+-        FALSE
+-    },
+-    {
+-        ENCTYPE_DES3_CBC_SHA1,
+-        "penny",
+-        { KV5M_DATA, 19, "EXAMPLE.COMbuckaroo" },
+-        { KV5M_DATA, 0, NULL },
+-        { KV5M_DATA, 24, "\x6D\x2F\xCD\xF2\xD6\xFB\xBC\x3D\xDC\xAD\xB5\xDA"
+-          "\x57\x10\xA2\x34\x89\xB0\xD3\xB6\x9D\x5D\x9D\x4A" },
+-        0,
+-        FALSE
+-    },
+-    {
+-        ENCTYPE_DES3_CBC_SHA1,
+-        "\xC3\x9F",
+-        { KV5M_DATA, 23, "ATHENA.MIT.EDUJuri\xC5\xA1\x69\xC4\x87" },
+-        { KV5M_DATA, 0, NULL },
+-        { KV5M_DATA, 24, "\x16\xD5\xA4\x0E\x1C\xE3\xBA\xCB\x61\xB9\xDC\xE0"
+-          "\x04\x70\x32\x4C\x83\x19\x73\xA7\xB9\x52\xFE\xB0" },
+-        0,
+-        FALSE
+-    },
+-    {
+-        ENCTYPE_DES3_CBC_SHA1,
+-        "\xF0\x9D\x84\x9E",
+-        { KV5M_DATA, 18, "EXAMPLE.COMpianist" },
+-        { KV5M_DATA, 0, NULL },
+-        { KV5M_DATA, 24, "\x85\x76\x37\x26\x58\x5D\xBC\x1C\xCE\x6E\xC4\x3E"
+-          "\x1F\x75\x1F\x07\xF1\xC4\xCB\xB0\x98\xF4\x0B\x19" },
+-        0,
+-        FALSE
+-    },
+-
+     /* Test vectors from RFC 3962 appendix B. */
+     {
+         ENCTYPE_AES128_CTS_HMAC_SHA1_96,
+diff --git a/src/lib/crypto/krb/Makefile.in b/src/lib/crypto/krb/Makefile.in
+index b74e6f7cc..2b0c4163d 100644
+--- a/src/lib/crypto/krb/Makefile.in
++++ b/src/lib/crypto/krb/Makefile.in
+@@ -50,7 +50,6 @@ STLIBOBJS=\
+ 	prf.o			\
+ 	prf_aes2.o		\
+ 	prf_cmac.o		\
+-	prf_des.o		\
+ 	prf_dk.o		\
+ 	prf_rc4.o		\
+ 	prng.o			\
+@@ -109,7 +108,6 @@ OBJS=\
+ 	$(OUTPRE)prf.$(OBJEXT)			\
+ 	$(OUTPRE)prf_aes2.$(OBJEXT)		\
+ 	$(OUTPRE)prf_cmac.$(OBJEXT)		\
+-	$(OUTPRE)prf_des.$(OBJEXT)		\
+ 	$(OUTPRE)prf_dk.$(OBJEXT)		\
+ 	$(OUTPRE)prf_rc4.$(OBJEXT)		\
+ 	$(OUTPRE)prng.$(OBJEXT)			\
+@@ -168,7 +166,6 @@ SRCS=\
+ 	$(srcdir)/prf.c			\
+ 	$(srcdir)/prf_aes2.c		\
+ 	$(srcdir)/prf_cmac.c		\
+-	$(srcdir)/prf_des.c		\
+ 	$(srcdir)/prf_dk.c		\
+ 	$(srcdir)/prf_rc4.c		\
+ 	$(srcdir)/prng.c 		\
+diff --git a/src/lib/crypto/krb/cksumtypes.c b/src/lib/crypto/krb/cksumtypes.c
+index ecc2e08c9..f5fbe8a2a 100644
+--- a/src/lib/crypto/krb/cksumtypes.c
++++ b/src/lib/crypto/krb/cksumtypes.c
+@@ -46,12 +46,6 @@ const struct krb5_cksumtypes krb5int_cksumtypes_list[] = {
+       krb5int_unkeyed_checksum, NULL,
+       20, 20, CKSUM_UNKEYED },
+ 
+-    { CKSUMTYPE_HMAC_SHA1_DES3,
+-      "hmac-sha1-des3", { "hmac-sha1-des3-kd" }, "HMAC-SHA1 DES3 key",
+-      &krb5int_enc_des3, &krb5int_hash_sha1,
+-      krb5int_dk_checksum, NULL,
+-      20, 20, 0 },
+-
+     { CKSUMTYPE_HMAC_MD5_ARCFOUR,
+       "hmac-md5-rc4", { "hmac-md5-enc", "hmac-md5-earcfour" },
+       "Microsoft HMAC MD5",
+diff --git a/src/lib/crypto/krb/crypto_int.h b/src/lib/crypto/krb/crypto_int.h
+index ba693f8a4..5cc1f8e43 100644
+--- a/src/lib/crypto/krb/crypto_int.h
++++ b/src/lib/crypto/krb/crypto_int.h
+@@ -276,10 +276,6 @@ krb5_error_code krb5int_aes2_string_to_key(const struct krb5_keytypes *enc,
+ /* Random to key */
+ krb5_error_code k5_rand2key_direct(const krb5_data *randombits,
+                                    krb5_keyblock *keyblock);
+-krb5_error_code k5_rand2key_des(const krb5_data *randombits,
+-                                krb5_keyblock *keyblock);
+-krb5_error_code k5_rand2key_des3(const krb5_data *randombits,
+-                                 krb5_keyblock *keyblock);
+ 
+ /* Pseudo-random function */
+ krb5_error_code krb5int_des_prf(const struct krb5_keytypes *ktp,
+@@ -368,11 +364,6 @@ krb5_keyusage krb5int_arcfour_translate_usage(krb5_keyusage usage);
+ /* Ensure library initialization has occurred. */
+ int krb5int_crypto_init(void);
+ 
+-/* DES default state initialization handler (used by module enc providers). */
+-krb5_error_code krb5int_des_init_state(const krb5_keyblock *key,
+-                                       krb5_keyusage keyusage,
+-                                       krb5_data *state_out);
+-
+ /* Default state cleanup handler (used by module enc providers). */
+ void krb5int_default_free_state(krb5_data *state);
+ 
+@@ -425,7 +416,6 @@ void k5_iov_cursor_put(struct iov_cursor *cursor, unsigned char *block);
+ /* Modules must implement the k5_sha256() function prototyped in k5-int.h. */
+ 
+ /* Modules must implement the following enc_providers and hash_providers: */
+-extern const struct krb5_enc_provider krb5int_enc_des3;
+ extern const struct krb5_enc_provider krb5int_enc_arcfour;
+ extern const struct krb5_enc_provider krb5int_enc_aes128;
+ extern const struct krb5_enc_provider krb5int_enc_aes256;
+@@ -442,12 +432,6 @@ extern const struct krb5_hash_provider krb5int_hash_sha384;
+ 
+ /* Modules must implement the following functions. */
+ 
+-/* Set the parity bits to the correct values in keybits. */
+-void k5_des_fixup_key_parity(unsigned char *keybits);
+-
+-/* Return true if keybits is a weak or semi-weak DES key. */
+-krb5_boolean k5_des_is_weak_key(unsigned char *keybits);
+-
+ /* Compute an HMAC using the provided hash function, key, and data, storing the
+  * result into output (caller-allocated). */
+ krb5_error_code krb5int_hmac(const struct krb5_hash_provider *hash,
+diff --git a/src/lib/crypto/krb/default_state.c b/src/lib/crypto/krb/default_state.c
+index 0757c8b02..f89dc7902 100644
+--- a/src/lib/crypto/krb/default_state.c
++++ b/src/lib/crypto/krb/default_state.c
+@@ -32,16 +32,6 @@
+ 
+ #include "crypto_int.h"
+ 
+-krb5_error_code
+-krb5int_des_init_state(const krb5_keyblock *key, krb5_keyusage usage,
+-                       krb5_data *state_out)
+-{
+-    if (alloc_data(state_out, 8))
+-        return ENOMEM;
+-
+-    return 0;
+-}
+-
+ void
+ krb5int_default_free_state(krb5_data *state)
+ {
+diff --git a/src/lib/crypto/krb/enctype_util.c b/src/lib/crypto/krb/enctype_util.c
+index 1542d4062..a0037912a 100644
+--- a/src/lib/crypto/krb/enctype_util.c
++++ b/src/lib/crypto/krb/enctype_util.c
+@@ -45,6 +45,9 @@ struct {
+     { ENCTYPE_DES_CBC_MD5, "des-cbc-md5" },
+     { ENCTYPE_DES_CBC_RAW, "des-cbc-raw" },
+     { ENCTYPE_DES_HMAC_SHA1, "des-hmac-sha1" },
++    { ENCTYPE_DES3_CBC_SHA, "des3-cbc-sha1" },
++    { ENCTYPE_DES3_CBC_RAW, "des3-cbc-raw" },
++    { ENCTYPE_DES3_CBC_SHA1, "des3-hmac-sha1" },
+     { ENCTYPE_NULL, NULL }
+ };
+ 
+diff --git a/src/lib/crypto/krb/etypes.c b/src/lib/crypto/krb/etypes.c
+index fc278783b..7635393a4 100644
+--- a/src/lib/crypto/krb/etypes.c
++++ b/src/lib/crypto/krb/etypes.c
+@@ -35,27 +35,6 @@
+ 
+ /* Deprecations come from RFC 6649 and RFC 8249. */
+ const struct krb5_keytypes krb5int_enctypes_list[] = {
+-    { ENCTYPE_DES3_CBC_RAW,
+-      "des3-cbc-raw", { 0 }, "Triple DES cbc mode raw",
+-      &krb5int_enc_des3, NULL,
+-      16,
+-      krb5int_raw_crypto_length, krb5int_raw_encrypt, krb5int_raw_decrypt,
+-      krb5int_dk_string_to_key, k5_rand2key_des3,
+-      NULL, /*PRF*/
+-      0,
+-      ETYPE_WEAK | ETYPE_DEPRECATED, 112 },
+-
+-    { ENCTYPE_DES3_CBC_SHA1,
+-      "des3-cbc-sha1", { "des3-hmac-sha1", "des3-cbc-sha1-kd" },
+-      "Triple DES cbc mode with HMAC/sha1",
+-      &krb5int_enc_des3, &krb5int_hash_sha1,
+-      16,
+-      krb5int_dk_crypto_length, krb5int_dk_encrypt, krb5int_dk_decrypt,
+-      krb5int_dk_string_to_key, k5_rand2key_des3,
+-      krb5int_dk_prf,
+-      CKSUMTYPE_HMAC_SHA1_DES3,
+-      ETYPE_DEPRECATED, 112 },
+-
+     /* rc4-hmac uses a 128-bit key, but due to weaknesses in the RC4 cipher, we
+      * consider its strength degraded and assign it an SSF value of 64. */
+     { ENCTYPE_ARCFOUR_HMAC,
+diff --git a/src/lib/crypto/krb/prf_des.c b/src/lib/crypto/krb/prf_des.c
+deleted file mode 100644
+index 7a2d719c5..000000000
+--- a/src/lib/crypto/krb/prf_des.c
++++ /dev/null
+@@ -1,47 +0,0 @@
+-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+-/* lib/crypto/krb/prf_des.c - RFC 3961 DES-based PRF */
+-/*
+- * Copyright (C) 2004, 2009  by the Massachusetts Institute of Technology.
+- * All rights reserved.
+- *
+- * Export of this software from the United States of America may
+- *   require a specific license from the United States Government.
+- *   It is the responsibility of any person or organization contemplating
+- *   export to obtain such a license before exporting.
+- *
+- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+- * distribute this software and its documentation for any purpose and
+- * without fee is hereby granted, provided that the above copyright
+- * notice appear in all copies and that both that copyright notice and
+- * this permission notice appear in supporting documentation, and that
+- * the name of M.I.T. not be used in advertising or publicity pertaining
+- * to distribution of the software without specific, written prior
+- * permission.  Furthermore if you modify this software you must label
+- * your software as modified software and not distribute it in such a
+- * fashion that it might be confused with the original M.I.T. software.
+- * M.I.T. makes no representations about the suitability of
+- * this software for any purpose.  It is provided "as is" without express
+- * or implied warranty.
+- */
+-
+-#include "crypto_int.h"
+-
+-krb5_error_code
+-krb5int_des_prf(const struct krb5_keytypes *ktp, krb5_key key,
+-                const krb5_data *in, krb5_data *out)
+-{
+-    const struct krb5_hash_provider *hash = &krb5int_hash_md5;
+-    krb5_crypto_iov iov;
+-    krb5_error_code ret;
+-
+-    /* Compute a hash of the input, storing into the output buffer. */
+-    iov.flags = KRB5_CRYPTO_TYPE_DATA;
+-    iov.data = *in;
+-    ret = hash->hash(&iov, 1, out);
+-    if (ret != 0)
+-        return ret;
+-
+-    /* Encrypt the hash in place. */
+-    iov.data = *out;
+-    return ktp->enc->encrypt(key, NULL, &iov, 1);
+-}
+diff --git a/src/lib/crypto/krb/random_to_key.c b/src/lib/crypto/krb/random_to_key.c
+index 157462526..863090beb 100644
+--- a/src/lib/crypto/krb/random_to_key.c
++++ b/src/lib/crypto/krb/random_to_key.c
+@@ -71,48 +71,3 @@ k5_rand2key_direct(const krb5_data *randombits, krb5_keyblock *keyblock)
+     memcpy(keyblock->contents, randombits->data, randombits->length);
+     return 0;
+ }
+-
+-static inline void
+-eighth_byte(unsigned char *b)
+-{
+-    b[7] = (((b[0] & 1) << 1) | ((b[1] & 1) << 2) | ((b[2] & 1) << 3) |
+-            ((b[3] & 1) << 4) | ((b[4] & 1) << 5) | ((b[5] & 1) << 6) |
+-            ((b[6] & 1) << 7));
+-}
+-
+-krb5_error_code
+-k5_rand2key_des(const krb5_data *randombits, krb5_keyblock *keyblock)
+-{
+-    if (randombits->length != 7)
+-        return(KRB5_CRYPTO_INTERNAL);
+-
+-    keyblock->magic = KV5M_KEYBLOCK;
+-
+-    /* Take the seven bytes, move them around into the top 7 bits of the
+-     * 8 key bytes, then compute the parity bits. */
+-    memcpy(keyblock->contents, randombits->data, randombits->length);
+-    eighth_byte(keyblock->contents);
+-    k5_des_fixup_key_parity(keyblock->contents);
+-
+-    return 0;
+-}
+-
+-krb5_error_code
+-k5_rand2key_des3(const krb5_data *randombits, krb5_keyblock *keyblock)
+-{
+-    int i;
+-
+-    if (randombits->length != 21)
+-        return KRB5_CRYPTO_INTERNAL;
+-
+-    keyblock->magic = KV5M_KEYBLOCK;
+-
+-    /* Take the seven bytes, move them around into the top 7 bits of the
+-     * 8 key bytes, then compute the parity bits.  Do this three times. */
+-    for (i = 0; i < 3; i++) {
+-        memcpy(&keyblock->contents[i * 8], &randombits->data[i * 7], 7);
+-        eighth_byte(&keyblock->contents[i * 8]);
+-        k5_des_fixup_key_parity(&keyblock->contents[i * 8]);
+-    }
+-    return 0;
+-}
+diff --git a/src/lib/crypto/libk5crypto.exports b/src/lib/crypto/libk5crypto.exports
+index 451d5e035..9db181381 100644
+--- a/src/lib/crypto/libk5crypto.exports
++++ b/src/lib/crypto/libk5crypto.exports
+@@ -86,7 +86,6 @@ krb5_k_verify_checksum
+ krb5_k_verify_checksum_iov
+ krb5int_aes_encrypt
+ krb5int_aes_decrypt
+-krb5int_enc_des3
+ krb5int_arcfour_gsscrypt
+ krb5int_camellia_cbc_mac
+ krb5int_cmac_checksum
+diff --git a/src/lib/crypto/openssl/Makefile.in b/src/lib/crypto/openssl/Makefile.in
+index aa434b168..234fc0e76 100644
+--- a/src/lib/crypto/openssl/Makefile.in
++++ b/src/lib/crypto/openssl/Makefile.in
+@@ -1,6 +1,6 @@
+ mydir=lib$(S)crypto$(S)openssl
+ BUILDTOP=$(REL)..$(S)..$(S)..
+-SUBDIRS=camellia des aes md4 md5  sha1 sha2 enc_provider hash_provider
++SUBDIRS=camellia aes md4 md5  sha1 sha2 enc_provider hash_provider
+ LOCALINCLUDES = -I$(srcdir)/../krb -I$(srcdir)
+ 
+ STLIBOBJS=\
+@@ -24,14 +24,14 @@ SRCS=\
+ 	$(srcdir)/sha256.c	\
+ 	$(srcdir)/stubs.c
+ 
+-STOBJLISTS= des/OBJS.ST md4/OBJS.ST 	\
++STOBJLISTS= md4/OBJS.ST 		\
+ 	md5/OBJS.ST sha1/OBJS.ST sha2/OBJS.ST 	\
+ 	enc_provider/OBJS.ST 		\
+ 	hash_provider/OBJS.ST 		\
+ 	aes/OBJS.ST 			\
+ 	OBJS.ST
+ 
+-SUBDIROBJLISTS= des/OBJS.ST md4/OBJS.ST 	\
++SUBDIROBJLISTS= md4/OBJS.ST 		\
+ 		md5/OBJS.ST sha1/OBJS.ST sha2/OBJS.ST 	\
+ 		enc_provider/OBJS.ST 		\
+ 		hash_provider/OBJS.ST 		\
+@@ -42,7 +42,7 @@ includes: depend
+ 
+ depend: $(SRCS)
+ 
+-clean-unix:: clean-libobjs
++clean-unix:: clean-libobjsn
+ 
+ @lib_frag@
+ @libobj_frag@
+diff --git a/src/lib/crypto/openssl/des/Makefile.in b/src/lib/crypto/openssl/des/Makefile.in
+deleted file mode 100644
+index 4392fb8ea..000000000
+--- a/src/lib/crypto/openssl/des/Makefile.in
++++ /dev/null
+@@ -1,20 +0,0 @@
+-mydir=lib$(S)crypto$(S)openssl$(S)des
+-BUILDTOP=$(REL)..$(S)..$(S)..$(S)..
+-LOCALINCLUDES = -I$(srcdir)/../../krb -I$(srcdir)/..
+-
+-STLIBOBJS= des_keys.o
+-
+-OBJS= $(OUTPRE)des_keys.$(OBJEXT)
+-
+-SRCS= $(srcdir)/des_keys.c
+-
+-all-unix: all-libobjs
+-
+-includes: depend
+-
+-depend: $(SRCS)
+-
+-clean-unix:: clean-libobjs
+-
+-@libobj_frag@
+-
+diff --git a/src/lib/crypto/openssl/des/deps b/src/lib/crypto/openssl/des/deps
+deleted file mode 100644
+index 21b904f89..000000000
+--- a/src/lib/crypto/openssl/des/deps
++++ /dev/null
+@@ -1,15 +0,0 @@
+-#
+-# Generated makefile dependencies follow.
+-#
+-des_keys.so des_keys.po $(OUTPRE)des_keys.$(OBJEXT): \
+-  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+-  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+-  $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h $(srcdir)/../crypto_mod.h \
+-  $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+-  $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+-  $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+-  $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+-  $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+-  $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+-  $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+-  des_keys.c
+diff --git a/src/lib/crypto/openssl/des/des_keys.c b/src/lib/crypto/openssl/des/des_keys.c
+deleted file mode 100644
+index 51d9db216..000000000
+--- a/src/lib/crypto/openssl/des/des_keys.c
++++ /dev/null
+@@ -1,40 +0,0 @@
+-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+-/* lib/crypto/openssl/des/des_keys.c - Key functions used by Kerberos code */
+-/*
+- * Copyright (C) 2011 by the Massachusetts Institute of Technology.
+- * All rights reserved.
+- *
+- * Export of this software from the United States of America may
+- *   require a specific license from the United States Government.
+- *   It is the responsibility of any person or organization contemplating
+- *   export to obtain such a license before exporting.
+- *
+- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+- * distribute this software and its documentation for any purpose and
+- * without fee is hereby granted, provided that the above copyright
+- * notice appear in all copies and that both that copyright notice and
+- * this permission notice appear in supporting documentation, and that
+- * the name of M.I.T. not be used in advertising or publicity pertaining
+- * to distribution of the software without specific, written prior
+- * permission.  Furthermore if you modify this software you must label
+- * your software as modified software and not distribute it in such a
+- * fashion that it might be confused with the original M.I.T. software.
+- * M.I.T. makes no representations about the suitability of
+- * this software for any purpose.  It is provided "as is" without express
+- * or implied warranty.
+- */
+-
+-#include "crypto_int.h"
+-#include <openssl/des.h>
+-
+-void
+-k5_des_fixup_key_parity(unsigned char *keybits)
+-{
+-    DES_set_odd_parity((DES_cblock *)keybits);
+-}
+-
+-krb5_boolean
+-k5_des_is_weak_key(unsigned char *keybits)
+-{
+-    return DES_is_weak_key((DES_cblock *)keybits);
+-}
+diff --git a/src/lib/crypto/openssl/enc_provider/Makefile.in b/src/lib/crypto/openssl/enc_provider/Makefile.in
+index a9069d22d..2b32c3ac4 100644
+--- a/src/lib/crypto/openssl/enc_provider/Makefile.in
++++ b/src/lib/crypto/openssl/enc_provider/Makefile.in
+@@ -3,19 +3,16 @@ BUILDTOP=$(REL)..$(S)..$(S)..$(S)..
+ LOCALINCLUDES = -I$(srcdir)/../../krb -I$(srcdir)/..
+ 
+ STLIBOBJS= \
+-	des3.o 	\
+ 	rc4.o 	\
+ 	aes.o   \
+ 	camellia.o
+ 
+ OBJS= \
+-	$(OUTPRE)des3.$(OBJEXT) 	\
+ 	$(OUTPRE)aes.$(OBJEXT) 	\
+ 	$(OUTPRE)camellia.$(OBJEXT) 	\
+ 	$(OUTPRE)rc4.$(OBJEXT)
+ 
+ SRCS= \
+-	$(srcdir)/des3.c 	\
+ 	$(srcdir)/aes.c 	\
+ 	$(srcdir)/camellia.c 	\
+ 	$(srcdir)/rc4.c
+diff --git a/src/lib/crypto/openssl/enc_provider/deps b/src/lib/crypto/openssl/enc_provider/deps
+index 1c28cc842..91ba48234 100644
+--- a/src/lib/crypto/openssl/enc_provider/deps
++++ b/src/lib/crypto/openssl/enc_provider/deps
+@@ -1,17 +1,6 @@
+ #
+ # Generated makefile dependencies follow.
+ #
+-des3.so des3.po $(OUTPRE)des3.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+-  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+-  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h \
+-  $(srcdir)/../crypto_mod.h $(top_srcdir)/include/k5-buf.h \
+-  $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+-  $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+-  $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+-  $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+-  $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+-  $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+-  $(top_srcdir)/include/socket-utils.h des3.c
+ aes.so aes.po $(OUTPRE)aes.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+   $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+   $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h \
+diff --git a/src/lib/crypto/openssl/enc_provider/des3.c b/src/lib/crypto/openssl/enc_provider/des3.c
+deleted file mode 100644
+index 1c439c2cd..000000000
+--- a/src/lib/crypto/openssl/enc_provider/des3.c
++++ /dev/null
+@@ -1,184 +0,0 @@
+-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+-/* lib/crypto/openssl/enc_provider/des3.c */
+-/*
+- * Copyright (C) 2009 by the Massachusetts Institute of Technology.
+- * All rights reserved.
+- *
+- * Export of this software from the United States of America may
+- *   require a specific license from the United States Government.
+- *   It is the responsibility of any person or organization contemplating
+- *   export to obtain such a license before exporting.
+- *
+- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+- * distribute this software and its documentation for any purpose and
+- * without fee is hereby granted, provided that the above copyright
+- * notice appear in all copies and that both that copyright notice and
+- * this permission notice appear in supporting documentation, and that
+- * the name of M.I.T. not be used in advertising or publicity pertaining
+- * to distribution of the software without specific, written prior
+- * permission.  Furthermore if you modify this software you must label
+- * your software as modified software and not distribute it in such a
+- * fashion that it might be confused with the original M.I.T. software.
+- * M.I.T. makes no representations about the suitability of
+- * this software for any purpose.  It is provided "as is" without express
+- * or implied warranty.
+- */
+-/*
+- * Copyright (C) 1998 by the FundsXpress, INC.
+- *
+- * All rights reserved.
+- *
+- * Export of this software from the United States of America may require
+- * a specific license from the United States Government.  It is the
+- * responsibility of any person or organization contemplating export to
+- * obtain such a license before exporting.
+- *
+- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+- * distribute this software and its documentation for any purpose and
+- * without fee is hereby granted, provided that the above copyright
+- * notice appear in all copies and that both that copyright notice and
+- * this permission notice appear in supporting documentation, and that
+- * the name of FundsXpress. not be used in advertising or publicity pertaining
+- * to distribution of the software without specific, written prior
+- * permission.  FundsXpress makes no representations about the suitability of
+- * this software for any purpose.  It is provided "as is" without express
+- * or implied warranty.
+- *
+- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+- */
+-
+-#include "crypto_int.h"
+-#include <openssl/evp.h>
+-
+-
+-#define DES3_BLOCK_SIZE 8
+-#define DES3_KEY_SIZE 24
+-#define DES3_KEY_BYTES 21
+-
+-static krb5_error_code
+-validate(krb5_key key, const krb5_data *ivec, const krb5_crypto_iov *data,
+-         size_t num_data, krb5_boolean *empty)
+-{
+-    size_t input_length = iov_total_length(data, num_data, FALSE);
+-
+-    if (key->keyblock.length != DES3_KEY_SIZE)
+-        return(KRB5_BAD_KEYSIZE);
+-    if ((input_length%DES3_BLOCK_SIZE) != 0)
+-        return(KRB5_BAD_MSIZE);
+-    if (ivec && (ivec->length != 8))
+-        return(KRB5_BAD_MSIZE);
+-
+-    *empty = (input_length == 0);
+-    return 0;
+-}
+-
+-static krb5_error_code
+-k5_des3_encrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
+-                size_t num_data)
+-{
+-    int ret, olen = DES3_BLOCK_SIZE;
+-    unsigned char iblock[DES3_BLOCK_SIZE], oblock[DES3_BLOCK_SIZE];
+-    struct iov_cursor cursor;
+-    EVP_CIPHER_CTX *ctx;
+-    krb5_boolean empty;
+-
+-    ret = validate(key, ivec, data, num_data, &empty);
+-    if (ret != 0 || empty)
+-        return ret;
+-
+-    ctx = EVP_CIPHER_CTX_new();
+-    if (ctx == NULL)
+-        return ENOMEM;
+-
+-    ret = EVP_EncryptInit_ex(ctx, EVP_des_ede3_cbc(), NULL,
+-                             key->keyblock.contents,
+-                             (ivec) ? (unsigned char*)ivec->data : NULL);
+-    if (!ret) {
+-        EVP_CIPHER_CTX_free(ctx);
+-        return KRB5_CRYPTO_INTERNAL;
+-    }
+-
+-    EVP_CIPHER_CTX_set_padding(ctx,0);
+-
+-    k5_iov_cursor_init(&cursor, data, num_data, DES3_BLOCK_SIZE, FALSE);
+-    while (k5_iov_cursor_get(&cursor, iblock)) {
+-        ret = EVP_EncryptUpdate(ctx, oblock, &olen, iblock, DES3_BLOCK_SIZE);
+-        if (!ret)
+-            break;
+-        k5_iov_cursor_put(&cursor, oblock);
+-    }
+-
+-    if (ivec != NULL)
+-        memcpy(ivec->data, oblock, DES3_BLOCK_SIZE);
+-
+-    EVP_CIPHER_CTX_free(ctx);
+-
+-    zap(iblock, sizeof(iblock));
+-    zap(oblock, sizeof(oblock));
+-
+-    if (ret != 1)
+-        return KRB5_CRYPTO_INTERNAL;
+-    return 0;
+-}
+-
+-static krb5_error_code
+-k5_des3_decrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
+-                size_t num_data)
+-{
+-    int ret, olen = DES3_BLOCK_SIZE;
+-    unsigned char iblock[DES3_BLOCK_SIZE], oblock[DES3_BLOCK_SIZE];
+-    struct iov_cursor cursor;
+-    EVP_CIPHER_CTX *ctx;
+-    krb5_boolean empty;
+-
+-    ret = validate(key, ivec, data, num_data, &empty);
+-    if (ret != 0 || empty)
+-        return ret;
+-
+-    ctx = EVP_CIPHER_CTX_new();
+-    if (ctx == NULL)
+-        return ENOMEM;
+-
+-    ret = EVP_DecryptInit_ex(ctx, EVP_des_ede3_cbc(), NULL,
+-                             key->keyblock.contents,
+-                             (ivec) ? (unsigned char*)ivec->data : NULL);
+-    if (!ret) {
+-        EVP_CIPHER_CTX_free(ctx);
+-        return KRB5_CRYPTO_INTERNAL;
+-    }
+-
+-    EVP_CIPHER_CTX_set_padding(ctx,0);
+-
+-    k5_iov_cursor_init(&cursor, data, num_data, DES3_BLOCK_SIZE, FALSE);
+-    while (k5_iov_cursor_get(&cursor, iblock)) {
+-        ret = EVP_DecryptUpdate(ctx, oblock, &olen,
+-                                (unsigned char *)iblock, DES3_BLOCK_SIZE);
+-        if (!ret)
+-            break;
+-        k5_iov_cursor_put(&cursor, oblock);
+-    }
+-
+-    if (ivec != NULL)
+-        memcpy(ivec->data, iblock, DES3_BLOCK_SIZE);
+-
+-    EVP_CIPHER_CTX_free(ctx);
+-
+-    zap(iblock, sizeof(iblock));
+-    zap(oblock, sizeof(oblock));
+-
+-    if (ret != 1)
+-        return KRB5_CRYPTO_INTERNAL;
+-    return 0;
+-}
+-
+-const struct krb5_enc_provider krb5int_enc_des3 = {
+-    DES3_BLOCK_SIZE,
+-    DES3_KEY_BYTES, DES3_KEY_SIZE,
+-    k5_des3_encrypt,
+-    k5_des3_decrypt,
+-    NULL,
+-    krb5int_des_init_state,
+-    krb5int_default_free_state
+-};
+diff --git a/src/lib/gssapi/krb5/accept_sec_context.c b/src/lib/gssapi/krb5/accept_sec_context.c
+index c821cc830..c5bddb1e8 100644
+--- a/src/lib/gssapi/krb5/accept_sec_context.c
++++ b/src/lib/gssapi/krb5/accept_sec_context.c
+@@ -1010,7 +1010,6 @@ kg_accept_krb5(minor_status, context_handle,
+             }
+ 
+             switch (negotiated_etype) {
+-            case ENCTYPE_DES3_CBC_SHA1:
+             case ENCTYPE_ARCFOUR_HMAC:
+             case ENCTYPE_ARCFOUR_HMAC_EXP:
+                 /* RFC 4121 accidentally omits RC4-HMAC-EXP as a "not-newer"
+diff --git a/src/lib/gssapi/krb5/gssapiP_krb5.h b/src/lib/gssapi/krb5/gssapiP_krb5.h
+index 2e2c775d6..f5b0fede6 100644
+--- a/src/lib/gssapi/krb5/gssapiP_krb5.h
++++ b/src/lib/gssapi/krb5/gssapiP_krb5.h
+@@ -125,14 +125,14 @@ enum sgn_alg {
+     /* SGN_ALG_DES_MAC               = 0x0002, */
+     /* SGN_ALG_3                     = 0x0003, /\* not published *\/ */
+     SGN_ALG_HMAC_MD5              = 0x0011, /* microsoft w2k;  */
+-    SGN_ALG_HMAC_SHA1_DES3_KD     = 0x0004
++    /* SGN_ALG_HMAC_SHA1_DES3_KD     = 0x0004 */
+ };
+ enum seal_alg {
+     SEAL_ALG_NONE            = 0xffff,
+     /* SEAL_ALG_DES             = 0x0000, */
+     /* SEAL_ALG_1               = 0x0001, /\* not published *\/ */
+     SEAL_ALG_MICROSOFT_RC4   = 0x0010, /* microsoft w2k;  */
+-    SEAL_ALG_DES3KD          = 0x0002
++    /* SEAL_ALG_DES3KD          = 0x0002 */
+ };
+ 
+ /* for 3DES */
+@@ -153,7 +153,7 @@ enum qop {
+     GSS_KRB5_INTEG_C_QOP_HMAC_SHA1 = 0x0004,
+     GSS_KRB5_INTEG_C_QOP_MASK      = 0x00ff,
+     /* GSS_KRB5_CONF_C_QOP_DES        = 0x0100, */
+-    GSS_KRB5_CONF_C_QOP_DES3_KD    = 0x0200,
++    /* GSS_KRB5_CONF_C_QOP_DES3_KD    = 0x0200, */
+     GSS_KRB5_CONF_C_QOP_MASK       = 0xff00
+ };
+ 
+diff --git a/src/lib/gssapi/krb5/k5seal.c b/src/lib/gssapi/krb5/k5seal.c
+index d1cdce486..7f7146a0a 100644
+--- a/src/lib/gssapi/krb5/k5seal.c
++++ b/src/lib/gssapi/krb5/k5seal.c
+@@ -136,19 +136,12 @@ make_seal_token_v1 (krb5_context context,
+ 
+     /* pad the plaintext, encrypt if needed, and stick it in the token */
+ 
+-    /* initialize the the checksum */
+-    switch (signalg) {
+-    case SGN_ALG_HMAC_SHA1_DES3_KD:
+-        md5cksum.checksum_type = CKSUMTYPE_HMAC_SHA1_DES3;
+-        break;
+-    case SGN_ALG_HMAC_MD5:
+-        md5cksum.checksum_type = CKSUMTYPE_HMAC_MD5_ARCFOUR;
+-        if (toktype != KG_TOK_SEAL_MSG)
+-            sign_usage = 15;
+-        break;
+-    default:
+-        abort ();
+-    }
++    if (signalg != SGN_ALG_HMAC_MD5)
++        abort();
++
++    md5cksum.checksum_type = CKSUMTYPE_HMAC_MD5_ARCFOUR;
++    if (toktype != KG_TOK_SEAL_MSG)
++        sign_usage = 15;
+ 
+     code = krb5_c_checksum_length(context, md5cksum.checksum_type, &sumlen);
+     if (code) {
+@@ -196,20 +189,8 @@ make_seal_token_v1 (krb5_context context,
+         gssalloc_free(t);
+         return(code);
+     }
+-    switch(signalg) {
+-    case SGN_ALG_HMAC_SHA1_DES3_KD:
+-        /*
+-         * Using key derivation, the call to krb5_c_make_checksum
+-         * already dealt with encrypting.
+-         */
+-        if (md5cksum.length != cksum_size)
+-            abort ();
+-        memcpy (ptr+14, md5cksum.contents, md5cksum.length);
+-        break;
+-    case SGN_ALG_HMAC_MD5:
+-        memcpy (ptr+14, md5cksum.contents, cksum_size);
+-        break;
+-    }
++
++    memcpy (ptr+14, md5cksum.contents, cksum_size);
+ 
+     krb5_free_checksum_contents(context, &md5cksum);
+ 
+diff --git a/src/lib/gssapi/krb5/k5sealiov.c b/src/lib/gssapi/krb5/k5sealiov.c
+index 9bb2ee109..9147bb2c7 100644
+--- a/src/lib/gssapi/krb5/k5sealiov.c
++++ b/src/lib/gssapi/krb5/k5sealiov.c
+@@ -144,18 +144,11 @@ make_seal_token_v1_iov(krb5_context context,
+     /* pad the plaintext, encrypt if needed, and stick it in the token */
+ 
+     /* initialize the checksum */
+-    switch (ctx->signalg) {
+-    case SGN_ALG_HMAC_SHA1_DES3_KD:
+-        md5cksum.checksum_type = CKSUMTYPE_HMAC_SHA1_DES3;
+-        break;
+-    case SGN_ALG_HMAC_MD5:
+-        md5cksum.checksum_type = CKSUMTYPE_HMAC_MD5_ARCFOUR;
+-        if (toktype != KG_TOK_WRAP_MSG)
+-            sign_usage = 15;
+-        break;
+-    default:
+-        abort ();
+-    }
++    if (ctx->signalg != SGN_ALG_HMAC_MD5)
++        abort();
++    md5cksum.checksum_type = CKSUMTYPE_HMAC_MD5_ARCFOUR;
++    if (toktype != KG_TOK_WRAP_MSG)
++        sign_usage = 15;
+ 
+     code = krb5_c_checksum_length(context, md5cksum.checksum_type, &k5_trailerlen);
+     if (code != 0)
+@@ -177,15 +170,7 @@ make_seal_token_v1_iov(krb5_context context,
+     if (code != 0)
+         goto cleanup;
+ 
+-    switch (ctx->signalg) {
+-    case SGN_ALG_HMAC_SHA1_DES3_KD:
+-        assert(md5cksum.length == ctx->cksum_size);
+-        memcpy(ptr + 14, md5cksum.contents, md5cksum.length);
+-        break;
+-    case SGN_ALG_HMAC_MD5:
+-        memcpy(ptr + 14, md5cksum.contents, ctx->cksum_size);
+-        break;
+-    }
++    memcpy(ptr + 14, md5cksum.contents, ctx->cksum_size);
+ 
+     /* create the seq_num */
+     code = kg_make_seq_num(context, ctx->seq, ctx->initiate ? 0 : 0xFF,
+diff --git a/src/lib/gssapi/krb5/k5unseal.c b/src/lib/gssapi/krb5/k5unseal.c
+index 9b183bc33..f0cc4a680 100644
+--- a/src/lib/gssapi/krb5/k5unseal.c
++++ b/src/lib/gssapi/krb5/k5unseal.c
+@@ -131,28 +131,21 @@ kg_unseal_v1(context, minor_status, ctx, ptr, bodysize, message_buffer,
+        but few enough that we can try them all. */
+ 
+     if ((ctx->sealalg == SEAL_ALG_NONE && signalg > 1) ||
+-        (ctx->sealalg == SEAL_ALG_DES3KD &&
+-         signalg != SGN_ALG_HMAC_SHA1_DES3_KD)||
+         (ctx->sealalg == SEAL_ALG_MICROSOFT_RC4 &&
+          signalg != SGN_ALG_HMAC_MD5)) {
+         *minor_status = 0;
+         return GSS_S_DEFECTIVE_TOKEN;
+     }
+ 
+-    switch (signalg) {
+-    case SGN_ALG_HMAC_MD5:
+-        cksum_len = 8;
+-        if (toktype != KG_TOK_SEAL_MSG)
+-            sign_usage = 15;
+-        break;
+-    case SGN_ALG_HMAC_SHA1_DES3_KD:
+-        cksum_len = 20;
+-        break;
+-    default:
++    if (signalg != SGN_ALG_HMAC_MD5) {
+         *minor_status = 0;
+         return GSS_S_DEFECTIVE_TOKEN;
+     }
+ 
++    cksum_len = 8;
++    if (toktype != KG_TOK_SEAL_MSG)
++        sign_usage = 15;
++
+     if ((size_t)bodysize < 14 + cksum_len) {
+         *minor_status = 0;
+         return GSS_S_DEFECTIVE_TOKEN;
+@@ -252,64 +245,53 @@ kg_unseal_v1(context, minor_status, ctx, ptr, bodysize, message_buffer,
+     /* compute the checksum of the message */
+ 
+     /* initialize the the cksum */
+-    switch (signalg) {
+-    case SGN_ALG_HMAC_MD5:
+-        md5cksum.checksum_type = CKSUMTYPE_HMAC_MD5_ARCFOUR;
+-        break;
+-    case SGN_ALG_HMAC_SHA1_DES3_KD:
+-        md5cksum.checksum_type = CKSUMTYPE_HMAC_SHA1_DES3;
+-        break;
+-    default:
+-        abort ();
+-    }
++    if (signalg != SGN_ALG_HMAC_MD5)
++        abort();
++    md5cksum.checksum_type = CKSUMTYPE_HMAC_MD5_ARCFOUR;
+ 
+     code = krb5_c_checksum_length(context, md5cksum.checksum_type, &sumlen);
+     if (code)
+         return(code);
+     md5cksum.length = sumlen;
+ 
+-    switch (signalg) {
+-    default:
++    if (signalg != SGN_ALG_HMAC_MD5) {
+         *minor_status = 0;
+         return(GSS_S_DEFECTIVE_TOKEN);
+-
+-    case SGN_ALG_HMAC_SHA1_DES3_KD:
+-    case SGN_ALG_HMAC_MD5:
+-        /* compute the checksum of the message */
+-
+-        /* 8 = bytes of token body to be checksummed according to spec */
+-
+-        if (! (data_ptr = xmalloc(8 + plainlen))) {
+-            if (sealalg != 0xffff)
+-                xfree(plain);
+-            if (toktype == KG_TOK_SEAL_MSG)
+-                gssalloc_free(token.value);
+-            *minor_status = ENOMEM;
+-            return(GSS_S_FAILURE);
+-        }
+-
+-        (void) memcpy(data_ptr, ptr-2, 8);
+-
+-        (void) memcpy(data_ptr+8, plain, plainlen);
+-
+-        plaind.length = 8 + plainlen;
+-        plaind.data = data_ptr;
+-        code = krb5_k_make_checksum(context, md5cksum.checksum_type,
+-                                    ctx->seq, sign_usage,
+-                                    &plaind, &md5cksum);
+-        xfree(data_ptr);
+-
+-        if (code) {
+-            if (toktype == KG_TOK_SEAL_MSG)
+-                gssalloc_free(token.value);
+-            *minor_status = code;
+-            return(GSS_S_FAILURE);
+-        }
+-
+-        code = k5_bcmp(md5cksum.contents, ptr + 14, cksum_len);
+-        break;
+     }
+ 
++    /* compute the checksum of the message */
++
++    /* 8 = bytes of token body to be checksummed according to spec */
++
++    if (! (data_ptr = xmalloc(8 + plainlen))) {
++        if (sealalg != 0xffff)
++            xfree(plain);
++        if (toktype == KG_TOK_SEAL_MSG)
++            gssalloc_free(token.value);
++        *minor_status = ENOMEM;
++        return(GSS_S_FAILURE);
++    }
++
++    (void) memcpy(data_ptr, ptr-2, 8);
++
++    (void) memcpy(data_ptr+8, plain, plainlen);
++
++    plaind.length = 8 + plainlen;
++    plaind.data = data_ptr;
++    code = krb5_k_make_checksum(context, md5cksum.checksum_type,
++                                ctx->seq, sign_usage,
++                                &plaind, &md5cksum);
++    xfree(data_ptr);
++
++    if (code) {
++        if (toktype == KG_TOK_SEAL_MSG)
++            gssalloc_free(token.value);
++        *minor_status = code;
++        return(GSS_S_FAILURE);
++    }
++
++    code = k5_bcmp(md5cksum.contents, ptr + 14, cksum_len);
++
+     krb5_free_checksum_contents(context, &md5cksum);
+     if (sealalg != 0xffff)
+         xfree(plain);
+diff --git a/src/lib/gssapi/krb5/k5unsealiov.c b/src/lib/gssapi/krb5/k5unsealiov.c
+index 85a9574f3..3ce2a90ce 100644
+--- a/src/lib/gssapi/krb5/k5unsealiov.c
++++ b/src/lib/gssapi/krb5/k5unsealiov.c
+@@ -102,28 +102,21 @@ kg_unseal_v1_iov(krb5_context context,
+     }
+ 
+     if ((ctx->sealalg == SEAL_ALG_NONE && signalg > 1) ||
+-        (ctx->sealalg == SEAL_ALG_DES3KD &&
+-         signalg != SGN_ALG_HMAC_SHA1_DES3_KD)||
+         (ctx->sealalg == SEAL_ALG_MICROSOFT_RC4 &&
+          signalg != SGN_ALG_HMAC_MD5)) {
+         *minor_status = 0;
+         return GSS_S_DEFECTIVE_TOKEN;
+     }
+ 
+-    switch (signalg) {
+-    case SGN_ALG_HMAC_MD5:
+-        cksum_len = 8;
+-        if (toktype != KG_TOK_WRAP_MSG)
+-            sign_usage = 15;
+-        break;
+-    case SGN_ALG_HMAC_SHA1_DES3_KD:
+-        cksum_len = 20;
+-        break;
+-    default:
++    if (signalg != SGN_ALG_HMAC_MD5) {
+         *minor_status = 0;
+         return GSS_S_DEFECTIVE_TOKEN;
+     }
+ 
++    cksum_len = 8;
++    if (toktype != KG_TOK_WRAP_MSG)
++        sign_usage = 15;
++
+     /* get the token parameters */
+     code = kg_get_seq_num(context, ctx->seq, ptr + 14, ptr + 6, &direction,
+                           &seqnum);
+@@ -181,16 +174,10 @@ kg_unseal_v1_iov(krb5_context context,
+ 
+     /* initialize the checksum */
+ 
+-    switch (signalg) {
+-    case SGN_ALG_HMAC_MD5:
+-        md5cksum.checksum_type = CKSUMTYPE_HMAC_MD5_ARCFOUR;
+-        break;
+-    case SGN_ALG_HMAC_SHA1_DES3_KD:
+-        md5cksum.checksum_type = CKSUMTYPE_HMAC_SHA1_DES3;
+-        break;
+-    default:
++    if (signalg != SGN_ALG_HMAC_MD5)
+         abort();
+-    }
++
++    md5cksum.checksum_type = CKSUMTYPE_HMAC_MD5_ARCFOUR;
+ 
+     code = krb5_c_checksum_length(context, md5cksum.checksum_type, &sumlen);
+     if (code != 0) {
+@@ -209,18 +196,13 @@ kg_unseal_v1_iov(krb5_context context,
+         goto cleanup;
+     }
+ 
+-    switch (signalg) {
+-    case SGN_ALG_HMAC_SHA1_DES3_KD:
+-    case SGN_ALG_HMAC_MD5:
+-        code = k5_bcmp(md5cksum.contents, ptr + 14, cksum_len);
+-        break;
+-    default:
++    if (signalg != SGN_ALG_HMAC_MD5) {
+         code = 0;
+         retval = GSS_S_DEFECTIVE_TOKEN;
+         goto cleanup;
+-        break;
+     }
+ 
++    code = k5_bcmp(md5cksum.contents, ptr + 14, cksum_len);
+     if (code != 0) {
+         code = 0;
+         retval = GSS_S_BAD_SIG;
+diff --git a/src/lib/gssapi/krb5/util_crypt.c b/src/lib/gssapi/krb5/util_crypt.c
+index 80954aff7..f7d3e92c4 100644
+--- a/src/lib/gssapi/krb5/util_crypt.c
++++ b/src/lib/gssapi/krb5/util_crypt.c
+@@ -97,17 +97,6 @@ kg_setup_keys(krb5_context context, krb5_gss_ctx_id_rec *ctx, krb5_key subkey,
+         return code;
+ 
+     switch (subkey->keyblock.enctype) {
+-    case ENCTYPE_DES3_CBC_SHA1:
+-        code = kg_copy_keys(context, ctx, subkey);
+-        if (code != 0)
+-            return code;
+-
+-        ctx->enc->keyblock.enctype = ENCTYPE_DES3_CBC_RAW;
+-        ctx->seq->keyblock.enctype = ENCTYPE_DES3_CBC_RAW;
+-        ctx->signalg = SGN_ALG_HMAC_SHA1_DES3_KD;
+-        ctx->cksum_size = 20;
+-        ctx->sealalg = SEAL_ALG_DES3KD;
+-        break;
+     case ENCTYPE_ARCFOUR_HMAC:
+     case ENCTYPE_ARCFOUR_HMAC_EXP:
+         /* RFC 4121 accidentally omits RC4-HMAC-EXP as a "not-newer" enctype,
+diff --git a/src/lib/kadm5/unit-test/api.current/chpass-principal-v2.exp b/src/lib/kadm5/unit-test/api.current/chpass-principal-v2.exp
+index 740425c69..6b45f5f72 100644
+--- a/src/lib/kadm5/unit-test/api.current/chpass-principal-v2.exp
++++ b/src/lib/kadm5/unit-test/api.current/chpass-principal-v2.exp
+@@ -53,10 +53,10 @@ proc test200 {} {
+     }
+ 
+     # XXX Perhaps I should actually check the key type returned.
+-    if {$num_keys == 5} {
++    if {$num_keys == 4} {
+ 	pass "$test"
+     } else {
+-	fail "$test: $num_keys keys, should be 5"
++	fail "$test: $num_keys keys, should be 4"
+     }
+     if { ! [cmd {kadm5_destroy $server_handle}]} {
+ 	perror "$test: unexpected failure in destroy"
+diff --git a/src/lib/kadm5/unit-test/api.current/get-principal-v2.exp b/src/lib/kadm5/unit-test/api.current/get-principal-v2.exp
+index 3ea1ba29b..d2c6d1afa 100644
+--- a/src/lib/kadm5/unit-test/api.current/get-principal-v2.exp
++++ b/src/lib/kadm5/unit-test/api.current/get-principal-v2.exp
+@@ -143,8 +143,8 @@ proc test101_102 {rpc} {
+     }
+ 
+     set failed 0
+-    if {$num_keys != 5} {
+-	fail "$test: num_keys $num_keys should be 5"
++    if {$num_keys != 4} {
++	fail "$test: num_keys $num_keys should be 4"
+ 	set failed 1
+     }
+     for {set i 0} {$i < $num_keys} {incr i} {
+diff --git a/src/lib/kadm5/unit-test/api.current/randkey-principal-v2.exp b/src/lib/kadm5/unit-test/api.current/randkey-principal-v2.exp
+index 2925c1c43..2f76c8b43 100644
+--- a/src/lib/kadm5/unit-test/api.current/randkey-principal-v2.exp
++++ b/src/lib/kadm5/unit-test/api.current/randkey-principal-v2.exp
+@@ -46,10 +46,10 @@ proc test100 {} {
+     }
+ 
+     # XXX Perhaps I should actually check the key type returned.
+-    if {$num_keys == 5} {
++    if {$num_keys == 4} {
+ 	pass "$test"
+     } else {
+-	fail "$test: $num_keys keys, should be 5"
++	fail "$test: $num_keys keys, should be 4"
+     }
+     if { ! [cmd {kadm5_destroy $server_handle}]} {
+ 	perror "$test: unexpected failure in destroy"
+diff --git a/src/lib/krb5/krb/init_ctx.c b/src/lib/krb5/krb/init_ctx.c
+index e7d67cca4..9a4741fa6 100644
+--- a/src/lib/krb5/krb/init_ctx.c
++++ b/src/lib/krb5/krb/init_ctx.c
+@@ -59,7 +59,6 @@
+ static krb5_enctype default_enctype_list[] = {
+     ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_AES128_CTS_HMAC_SHA1_96,
+     ENCTYPE_AES256_CTS_HMAC_SHA384_192, ENCTYPE_AES128_CTS_HMAC_SHA256_128,
+-    ENCTYPE_DES3_CBC_SHA1,
+     ENCTYPE_ARCFOUR_HMAC,
+     ENCTYPE_CAMELLIA128_CTS_CMAC, ENCTYPE_CAMELLIA256_CTS_CMAC,
+     0
+@@ -479,8 +478,6 @@ krb5int_parse_enctype_list(krb5_context context, const char *profkey,
+             /* Set all enctypes in the default list. */
+             for (i = 0; default_list[i]; i++)
+                 mod_list(default_list[i], sel, weak, &list);
+-        } else if (strcasecmp(token, "des3") == 0) {
+-            mod_list(ENCTYPE_DES3_CBC_SHA1, sel, weak, &list);
+         } else if (strcasecmp(token, "aes") == 0) {
+             mod_list(ENCTYPE_AES256_CTS_HMAC_SHA1_96, sel, weak, &list);
+             mod_list(ENCTYPE_AES128_CTS_HMAC_SHA1_96, sel, weak, &list);
+diff --git a/src/lib/krb5/krb/s4u_creds.c b/src/lib/krb5/krb/s4u_creds.c
+index 504eb557f..fc5c886d6 100644
+--- a/src/lib/krb5/krb/s4u_creds.c
++++ b/src/lib/krb5/krb/s4u_creds.c
+@@ -287,8 +287,6 @@ verify_s4u2self_reply(krb5_context context,
+     assert(req_s4u_user != NULL);
+ 
+     switch (subkey->enctype) {
+-    case ENCTYPE_DES3_CBC_SHA1:
+-    case ENCTYPE_DES3_CBC_RAW:
+     case ENCTYPE_ARCFOUR_HMAC:
+     case ENCTYPE_ARCFOUR_HMAC_EXP :
+         not_newer = TRUE;
+diff --git a/src/lib/krb5/krb/t_copy_context.c b/src/lib/krb5/krb/t_copy_context.c
+index 2970a8cea..fb82daf19 100644
+--- a/src/lib/krb5/krb/t_copy_context.c
++++ b/src/lib/krb5/krb/t_copy_context.c
+@@ -113,7 +113,7 @@ main(int argc, char **argv)
+ {
+     krb5_context ctx, ctx2;
+     krb5_plugin_initvt_fn *mods;
+-    const krb5_enctype etypes1[] = { ENCTYPE_DES3_CBC_SHA1, 0 };
++    const krb5_enctype etypes1[] = { ENCTYPE_AES128_CTS_HMAC_SHA256_128, 0 };
+     const krb5_enctype etypes2[] = { ENCTYPE_AES128_CTS_HMAC_SHA1_96,
+                                      ENCTYPE_AES256_CTS_HMAC_SHA1_96, 0 };
+     krb5_prompt_type ptypes[] = { KRB5_PROMPT_TYPE_PASSWORD };
+diff --git a/src/lib/krb5/krb/t_etypes.c b/src/lib/krb5/krb/t_etypes.c
+index f609e938a..248ffea90 100644
+--- a/src/lib/krb5/krb/t_etypes.c
++++ b/src/lib/krb5/krb/t_etypes.c
+@@ -50,17 +50,6 @@ static struct {
+       { ENCTYPE_AES256_CTS_HMAC_SHA1_96, 0 },
+       0, 0
+     },
+-    /* Family followed by enctype */
+-    { "aes des3-cbc-sha1-kd",
+-      { 0 },
+-      { ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_AES128_CTS_HMAC_SHA1_96,
+-        ENCTYPE_AES256_CTS_HMAC_SHA384_192, ENCTYPE_AES128_CTS_HMAC_SHA256_128,
+-        ENCTYPE_DES3_CBC_SHA1, 0 },
+-      { ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_AES128_CTS_HMAC_SHA1_96,
+-        ENCTYPE_AES256_CTS_HMAC_SHA384_192, ENCTYPE_AES128_CTS_HMAC_SHA256_128,
+-        ENCTYPE_DES3_CBC_SHA1, 0 },
+-      0, 0
+-    },
+     /* Family with enctype removed */
+     { "camellia -camellia256-cts-cmac",
+       { 0 },
+@@ -69,46 +58,15 @@ static struct {
+     },
+     /* Default set with family added and enctype removed */
+     { "DEFAULT +aes -arcfour-hmac-md5",
+-      { ENCTYPE_ARCFOUR_HMAC, ENCTYPE_DES3_CBC_SHA1, 0 },
+-      { ENCTYPE_DES3_CBC_SHA1, ENCTYPE_AES256_CTS_HMAC_SHA1_96,
++      { ENCTYPE_ARCFOUR_HMAC, 0 },
++      { ENCTYPE_AES256_CTS_HMAC_SHA1_96,
+         ENCTYPE_AES128_CTS_HMAC_SHA1_96, ENCTYPE_AES256_CTS_HMAC_SHA384_192,
+         ENCTYPE_AES128_CTS_HMAC_SHA256_128, 0 },
+-      { ENCTYPE_DES3_CBC_SHA1,
+-        ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_AES128_CTS_HMAC_SHA1_96,
++      { ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_AES128_CTS_HMAC_SHA1_96,
+         ENCTYPE_AES256_CTS_HMAC_SHA384_192, ENCTYPE_AES128_CTS_HMAC_SHA256_128,
+         0 },
+       0, 0
+     },
+-    /* Default set with families removed and enctypes added (one redundant) */
+-    { "DEFAULT -des3 rc4-hmac rc4-hmac-exp",
+-      { ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_AES128_CTS_HMAC_SHA1_96,
+-        ENCTYPE_DES3_CBC_SHA1, ENCTYPE_ARCFOUR_HMAC, 0 },
+-      { ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_AES128_CTS_HMAC_SHA1_96,
+-        ENCTYPE_ARCFOUR_HMAC, 0 },
+-      { ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_AES128_CTS_HMAC_SHA1_96,
+-        ENCTYPE_ARCFOUR_HMAC, ENCTYPE_ARCFOUR_HMAC_EXP, 0 },
+-      0, 0
+-    },
+-    /* Default set with family moved to front */
+-    { "des3 +DEFAULT",
+-      { ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_AES128_CTS_HMAC_SHA1_96,
+-        ENCTYPE_DES3_CBC_SHA1, 0 },
+-      { ENCTYPE_DES3_CBC_SHA1, ENCTYPE_AES256_CTS_HMAC_SHA1_96,
+-        ENCTYPE_AES128_CTS_HMAC_SHA1_96, 0 },
+-      { ENCTYPE_DES3_CBC_SHA1, ENCTYPE_AES256_CTS_HMAC_SHA1_96,
+-        ENCTYPE_AES128_CTS_HMAC_SHA1_96, 0 },
+-      0, 0
+-    },
+-    /* Two families with default set removed (exotic case), enctype added */
+-    { "aes +rc4 -DEFaulT des3-hmac-sha1",
+-      { ENCTYPE_AES128_CTS_HMAC_SHA1_96, ENCTYPE_DES3_CBC_SHA1,
+-        ENCTYPE_ARCFOUR_HMAC, 0 },
+-      { ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_AES256_CTS_HMAC_SHA384_192,
+-        ENCTYPE_AES128_CTS_HMAC_SHA256_128, ENCTYPE_DES3_CBC_SHA1, 0 },
+-      { ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_AES256_CTS_HMAC_SHA384_192,
+-        ENCTYPE_AES128_CTS_HMAC_SHA256_128, ENCTYPE_DES3_CBC_SHA1, 0 },
+-      0, 0
+-    },
+     /* Test krb5_set_default_in_tkt_ktypes */
+     { NULL,
+       { ENCTYPE_AES256_CTS_HMAC_SHA1_96, 0 },
+diff --git a/src/lib/krb5/os/t_trace.c b/src/lib/krb5/os/t_trace.c
+index 10ba8d0ac..24064ffcf 100644
+--- a/src/lib/krb5/os/t_trace.c
++++ b/src/lib/krb5/os/t_trace.c
+@@ -65,8 +65,8 @@ main (int argc, char *argv[])
+     krb5_principal princ = &principal_data;
+     krb5_pa_data padata, padata2, **padatap;
+     krb5_enctype enctypes[4] = {
+-        ENCTYPE_DES3_CBC_SHA, ENCTYPE_ARCFOUR_HMAC_EXP, ENCTYPE_UNKNOWN,
+-        ENCTYPE_NULL};
++        ENCTYPE_AES128_CTS_HMAC_SHA1_96, ENCTYPE_ARCFOUR_HMAC_EXP,
++        ENCTYPE_UNKNOWN, ENCTYPE_NULL};
+     krb5_ccache ccache;
+     krb5_keytab keytab;
+     krb5_creds creds;
+diff --git a/src/lib/krb5/os/t_trace.ref b/src/lib/krb5/os/t_trace.ref
+index 044a66999..98fb14f3f 100644
+--- a/src/lib/krb5/os/t_trace.ref
++++ b/src/lib/krb5/os/t_trace.ref
+@@ -41,7 +41,7 @@ int, krb5_principal type: ?
+ krb5_pa_data **, display list of padata type numbers: PA-PW-SALT (3), 0
+ krb5_pa_data **, display list of padata type numbers: (empty)
+ krb5_enctype, display shortest name of enctype: aes128-cts
+-krb5_enctype *, display list of enctypes: 5, rc4-hmac-exp, 511
++krb5_enctype *, display list of enctypes: aes128-cts, rc4-hmac-exp, 511
+ krb5_enctype *, display list of enctypes: (empty)
+ krb5_ccache, display type:name: FILE:/path/to/ccache
+ krb5_keytab, display name: FILE:/etc/krb5.keytab
+diff --git a/src/plugins/preauth/pkinit/pkcs11.h b/src/plugins/preauth/pkinit/pkcs11.h
+index e3d284631..586661bb7 100644
+--- a/src/plugins/preauth/pkinit/pkcs11.h
++++ b/src/plugins/preauth/pkinit/pkcs11.h
+@@ -339,9 +339,9 @@ typedef unsigned long ck_key_type_t;
+ #define CKK_GENERIC_SECRET	(0x10)
+ #define CKK_RC2			(0x11)
+ #define CKK_RC4			(0x12)
+-#define CKK_DES			(0x13)
+-#define CKK_DES2		(0x14)
+-#define CKK_DES3		(0x15)
++/* #define CKK_DES			(0x13) */
++/* #define CKK_DES2		(0x14) */
++/* #define CKK_DES3		(0x15) */
+ #define CKK_CAST		(0x16)
+ #define CKK_CAST3		(0x17)
+ #define CKK_CAST128		(0x18)
+diff --git a/src/plugins/preauth/pkinit/pkinit_clnt.c b/src/plugins/preauth/pkinit/pkinit_clnt.c
+index 1a642139a..2f0431991 100644
+--- a/src/plugins/preauth/pkinit/pkinit_clnt.c
++++ b/src/plugins/preauth/pkinit/pkinit_clnt.c
+@@ -212,14 +212,6 @@ pkinit_as_req_create(krb5_context context,
+     auth_pack.clientPublicValue = &info;
+     auth_pack.supportedKDFs = (krb5_data **)supported_kdf_alg_ids;
+ 
+-    /* add List of CMS algorithms */
+-    retval = create_krb5_supportedCMSTypes(context, plgctx->cryptoctx,
+-                                           reqctx->cryptoctx,
+-                                           reqctx->idctx, &cmstypes);
+-    auth_pack.supportedCMSTypes = cmstypes;
+-    if (retval)
+-        goto cleanup;
+-
+     switch(protocol) {
+     case DH_PROTOCOL:
+         TRACE_PKINIT_CLIENT_REQ_DH(context);
+diff --git a/src/plugins/preauth/pkinit/pkinit_crypto.h b/src/plugins/preauth/pkinit/pkinit_crypto.h
+index 8064a07d0..a291889b0 100644
+--- a/src/plugins/preauth/pkinit/pkinit_crypto.h
++++ b/src/plugins/preauth/pkinit/pkinit_crypto.h
+@@ -380,18 +380,6 @@ krb5_error_code server_process_dh
+ 	unsigned int *server_key_len_out);		/* OUT
+ 		    receives length of DH secret key */
+ 
+-/*
+- * this functions takes in crypto specific representation of
+- * supportedCMSTypes and creates a list of
+- * krb5_algorithm_identifier
+- */
+-krb5_error_code create_krb5_supportedCMSTypes
+-	(krb5_context context,				/* IN */
+-	pkinit_plg_crypto_context plg_cryptoctx,	/* IN */
+-	pkinit_req_crypto_context req_cryptoctx,	/* IN */
+-	pkinit_identity_crypto_context id_cryptoctx,	/* IN */
+-	krb5_algorithm_identifier ***supportedCMSTypes); /* OUT */
+-
+ /*
+  * this functions takes in crypto specific representation of
+  * trustedCertifiers and creates a list of
+diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+index 8c7fd0cca..52976895b 100644
+--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
++++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+@@ -5487,44 +5487,6 @@ cleanup:
+     return retval;
+ }
+ 
+-krb5_error_code
+-create_krb5_supportedCMSTypes(krb5_context context,
+-                              pkinit_plg_crypto_context plg_cryptoctx,
+-                              pkinit_req_crypto_context req_cryptoctx,
+-                              pkinit_identity_crypto_context id_cryptoctx,
+-                              krb5_algorithm_identifier ***oids)
+-{
+-
+-    krb5_error_code retval = ENOMEM;
+-    krb5_algorithm_identifier **loids = NULL;
+-    krb5_data des3oid = {0, 8, "\x2A\x86\x48\x86\xF7\x0D\x03\x07" };
+-
+-    *oids = NULL;
+-    loids = malloc(2 * sizeof(krb5_algorithm_identifier *));
+-    if (loids == NULL)
+-        goto cleanup;
+-    loids[1] = NULL;
+-    loids[0] = malloc(sizeof(krb5_algorithm_identifier));
+-    if (loids[0] == NULL) {
+-        free(loids);
+-        goto cleanup;
+-    }
+-    retval = pkinit_copy_krb5_data(&loids[0]->algorithm, &des3oid);
+-    if (retval) {
+-        free(loids[0]);
+-        free(loids);
+-        goto cleanup;
+-    }
+-    loids[0]->parameters.length = 0;
+-    loids[0]->parameters.data = NULL;
+-
+-    *oids = loids;
+-    retval = 0;
+-cleanup:
+-
+-    return retval;
+-}
+-
+ krb5_error_code
+ create_krb5_trustedCertifiers(krb5_context context,
+                               pkinit_plg_crypto_context plg_cryptoctx,
+diff --git a/src/plugins/preauth/pkinit/pkinit_kdf_test.c b/src/plugins/preauth/pkinit/pkinit_kdf_test.c
+index 7acbd0d28..cd998a29a 100644
+--- a/src/plugins/preauth/pkinit/pkinit_kdf_test.c
++++ b/src/plugins/preauth/pkinit/pkinit_kdf_test.c
+@@ -49,7 +49,6 @@ char eighteen_bs[9];
+ char party_u_name[] = "lha@SU.SE";
+ char party_v_name[] = "krbtgt/SU.SE@SU.SE";
+ int enctype_aes = ENCTYPE_AES256_CTS_HMAC_SHA1_96;
+-int enctype_des3 = ENCTYPE_DES3_CBC_SHA1;
+ const krb5_data lha_data = DATA_FROM_STRING("lha");
+ 
+ krb5_octet key1_hex[] =
+@@ -185,36 +184,6 @@ main(int argc, char **argv)
+         goto cleanup;
+     }
+ 
+-    /* TEST 3: SHA-512/DES3 */
+-    /* set up algorithm id */
+-    alg_id.algorithm.data = (char *)krb5_pkinit_sha512_oid;
+-    alg_id.algorithm.length = krb5_pkinit_sha512_oid_len;
+-
+-    enctype = enctype_des3;
+-
+-    /* call pkinit_alg_agility_kdf() with test vector values*/
+-    if (0 != (retval = pkinit_alg_agility_kdf(context, &secret,
+-                                              &alg_id.algorithm,
+-                                              u_principal, v_principal,
+-                                              enctype, &as_req, &pk_as_rep,
+-                                              &key_block))) {
+-        printf("ERROR in pkinit_kdf_test: kdf call failed, retval = %d",
+-               retval);
+-        goto cleanup;
+-    }
+-
+-    /* compare key to expected key value */
+-
+-    if ((key_block.length == sizeof(key3_hex)) &&
+-        (0 == memcmp(key_block.contents, key3_hex, key_block.length))) {
+-        printf("SUCCESS: TEST 3 (SHA-512/DES3), Correct key value generated.\n");
+-        retval = 0;
+-    } else {
+-        printf("FAILURE: TEST 2 (SHA-512/DES3), Incorrect key value generated!\n");
+-        retval = 1;
+-        goto cleanup;
+-    }
+-
+ cleanup:
+     /* release all allocated resources, whether good or bad return */
+     free(secret.data);
+diff --git a/src/plugins/preauth/spake/t_vectors.c b/src/plugins/preauth/spake/t_vectors.c
+index 2279202d3..96b0307d7 100644
+--- a/src/plugins/preauth/spake/t_vectors.c
++++ b/src/plugins/preauth/spake/t_vectors.c
+@@ -56,31 +56,6 @@ struct test {
+     const char *K2;
+     const char *K3;
+ } tests[] = {
+-    { ENCTYPE_DES3_CBC_SHA1, SPAKE_GROUP_EDWARDS25519,
+-      /* initial key, w, x, y, T, S, K */
+-      "850BB51358548CD05E86768C313E3BFEF7511937DCF72C3E",
+-      "686D84730CB8679AE95416C6567C6A63F2C9CEF124F7A3371AE81E11CAD42A37",
+-      "201012D07BFD48DDFA33C4AAC4FB1E229FB0D043CFE65EBFB14399091C71A723",
+-      "500B294797B8B042ACA1BEDC0F5931A4F52C537B3608B2D05CC8A2372F439F25",
+-      "18F511E750C97B592ACD30DB7D9E5FCA660389102E6BF610C1BFBED4616C8362",
+-      "5D10705E0D1E43D5DBF30240CCFBDE4A0230C70D4C79147AB0B317EDAD2F8AE7",
+-      "25BDE0D875F0FEB5755F45BA5E857889D916ECF7476F116AA31DC3E037EC4292",
+-      /* support, challenge, thash, body */
+-      "A0093007A0053003020101",
+-      "A1363034A003020101A122042018F511E750C97B592ACD30DB7D9E5FCA660389"
+-      "102E6BF610C1BFBED4616C8362A20930073005A003020101",
+-      "EAAA08807D0616026FF51C849EFBF35BA0CE3C5300E7D486DA46351B13D4605B",
+-      "3075A00703050000000000A1143012A003020101A10B30091B07726165627572"
+-      "6EA2101B0E415448454E412E4D49542E454455A3233021A003020102A11A3018"
+-      "1B066B72627467741B0E415448454E412E4D49542E454455A511180F31393730"
+-      "303130313030303030305AA703020100A8053003020110",
+-      /* K'[0], K'[1], K'[2], K'[3] */
+-      "BAF12FAE7CD958CBF1A29BFBC71F89CE49E03E295D89DAFD",
+-      "64F73DD9C41908206BCEC1F719026B574F9D13463D7A2520",
+-      "0454520B086B152C455829E6BAEFF78A61DFE9E3D04A895D",
+-      "4A92260B25E3EF94C125D5C24C3E5BCED5B37976E67F25C4",
+-    },
+-
+     { ENCTYPE_ARCFOUR_HMAC, SPAKE_GROUP_EDWARDS25519,
+       /* initial key, w, x, y, T, S, K */
+       "8846F7EAEE8FB117AD06BDD830B7586C",
+diff --git a/src/tests/dejagnu/config/default.exp b/src/tests/dejagnu/config/default.exp
+index b047ef1f7..4d8c917cd 100644
+--- a/src/tests/dejagnu/config/default.exp
++++ b/src/tests/dejagnu/config/default.exp
+@@ -15,8 +15,6 @@ set timeout 100
+ set stty_init {erase \^h kill \^u}
+ set env(TERM) dumb
+ 
+-set des3_krbtgt 0
+-
+ if { [string length $VALGRIND] } {
+     rename spawn valgrind_aux_spawn
+     proc spawn { args } {
+@@ -105,17 +103,9 @@ if { $PRIOCNTL_HACK } {
+ # particularly with regards to encryption types.
+ 
+ set passes {
+-    {
+-	des3
+-	mode=udp
+-	des3_krbtgt=1
+-	{supported_enctypes=des3-cbc-sha1:normal}
+-	{dummy=[verbose -log "DES3 TGT, DES3 enctype"]}
+-    }
+     {
+ 	aes-only
+ 	mode=udp
+-	des3_krbtgt=0
+ 	{supported_enctypes=aes256-cts-hmac-sha1-96:normal}
+ 	{permitted_enctypes(kdc)=aes256-cts-hmac-sha1-96}
+ 	{permitted_enctypes(client)=aes256-cts-hmac-sha1-96}
+@@ -130,7 +120,6 @@ set passes {
+     {
+ 	aes-sha2-only
+ 	mode=udp
+-	des3_krbtgt=0
+ 	{supported_enctypes=aes256-sha2:normal}
+ 	{permitted_enctypes(kdc)=aes256-sha2}
+ 	{permitted_enctypes(replica)=aes256-sha2}
+@@ -146,7 +135,6 @@ set passes {
+     {
+ 	camellia-only
+ 	mode=udp
+-	des3_krbtgt=0
+ 	{supported_enctypes=camellia256-cts:normal}
+ 	{permitted_enctypes(kdc)=camellia256-cts}
+ 	{permitted_enctypes(replica)=camellia256-cts}
+@@ -159,32 +147,9 @@ set passes {
+ 	{master_key_type=camellia256-cts}
+ 	{dummy=[verbose -log "Camellia-256 enctype"]}
+     }
+-    {
+-	aes-des3
+-	mode=udp
+-	des3_krbtgt=0
+-	{supported_enctypes=aes256-cts-hmac-sha1-96:normal des3-cbc-sha1:normal}
+-	{permitted_enctypes(kdc)=aes256-cts-hmac-sha1-96 des3-cbc-sha1}
+-	{permitted_enctypes(client)=aes256-cts-hmac-sha1-96 des3-cbc-sha1}
+-	{permitted_enctypes(server)=aes256-cts-hmac-sha1-96 des3-cbc-sha1}
+-	{master_key_type=aes256-cts-hmac-sha1-96}
+-	{dummy=[verbose -log "AES + DES3 + DES enctypes"]}
+-    }
+-    {
+-	aes-des3tgt
+-	mode=udp
+-	des3_krbtgt=1
+-	{supported_enctypes=aes256-cts-hmac-sha1-96:normal des3-cbc-sha1:normal}
+-	{permitted_enctypes(kdc)=aes256-cts-hmac-sha1-96 des3-cbc-sha1}
+-	{permitted_enctypes(client)=aes256-cts-hmac-sha1-96 des3-cbc-sha1}
+-	{permitted_enctypes(server)=aes256-cts-hmac-sha1-96 des3-cbc-sha1}
+-	{master_key_type=aes256-cts-hmac-sha1-96}
+-	{dummy=[verbose -log "AES enctypes, DES3 TGT"]}
+-    }
+     {
+ 	all-enctypes
+ 	mode=udp
+-	des3_krbtgt=0
+ 	{allow_weak_crypto(kdc)=false}
+ 	{allow_weak_crypto(replica)=false}
+ 	{allow_weak_crypto(client)=false}
+@@ -946,7 +911,6 @@ proc setup_kerberos_db { standalone } {
+     global REALMNAME KDB5_UTIL KADMIN_LOCAL KEY
+     global tmppwd hostname
+     global spawn_id
+-    global des3_krbtgt
+     global multipass_name last_passname_db
+ 
+     set failall 0
+@@ -1143,48 +1107,6 @@ proc setup_kerberos_db { standalone } {
+ 	}
+     }
+ 
+-    if $des3_krbtgt {
+-	# Set the TGT key to DES3.
+-	set test "kadmin.local TGT to DES3"
+-	set body {
+-	    if $failall {
+-		break
+-	    }
+-	    spawn $KADMIN_LOCAL -r $REALMNAME -e des3-cbc-sha1:normal
+-	    verbose "starting $test"
+-	    expect_after $def_exp_after
+-
+-	    expect "kadmin.local: "
+-	    send "cpw -randkey krbtgt/$REALMNAME@$REALMNAME\r"
+-	    # It echos...
+-	    expect "cpw -randkey krbtgt/$REALMNAME@$REALMNAME\r"
+-	    expect {
+-		"Key for \"krbtgt/$REALMNAME@$REALMNAME\" randomized." { }
+-	    }
+-	    expect "kadmin.local: "
+-	    send "quit\r"
+-	    expect eof
+-	    catch expect_after
+-	    if ![check_exit_status kadmin_local] {
+-		break
+-	    }
+-	}
+-	set ret [catch $body]
+-	catch "expect eof"
+-	catch expect_after
+-	if $ret {
+-	    set failall 1
+-	    if $standalone {
+-		fail $test
+-	    } else {
+-		delete_db
+-	    }
+-	} else {
+-	    if $standalone {
+-		pass $test
+-	    }
+-	}
+-    }
+     envstack_pop
+ 
+     # create the admin database lock file
+diff --git a/src/tests/dejagnu/krb-standalone/kprop.exp b/src/tests/dejagnu/krb-standalone/kprop.exp
+index f71ee8638..8c08cf42f 100644
+--- a/src/tests/dejagnu/krb-standalone/kprop.exp
++++ b/src/tests/dejagnu/krb-standalone/kprop.exp
+@@ -54,7 +54,7 @@ proc doit { } {
+     global REALMNAME KEY
+     global KADMIN_LOCAL KTUTIL KDB5_UTIL KPROPLOG KPROP kpropd_spawn_id
+     global hostname tmppwd spawn_id timeout
+-    global KRBIV supported_enctypes portbase mode ulog des3_krbtgt
++    global KRBIV supported_enctypes portbase mode ulog
+ 
+     # Delete any db, ulog files
+     delete_db
+diff --git a/src/tests/gssapi/t_enctypes.py b/src/tests/gssapi/t_enctypes.py
+index 7494d7fcd..2f95d8996 100755
+--- a/src/tests/gssapi/t_enctypes.py
++++ b/src/tests/gssapi/t_enctypes.py
+@@ -1,24 +1,17 @@
+ from k5test import *
+ 
+-# Define some convenience abbreviations for enctypes we will see in
+-# test program output.  For background, aes256 and aes128 are "CFX
+-# enctypes", meaning that they imply support for RFC 4121, while des3
+-# and rc4 are not.  DES3 keys will appear as 'des3-cbc-raw' in
+-# t_enctypes output because that's how GSSAPI does raw triple-DES
+-# encryption without the RFC3961 framing.
++# Define some convenience abbreviations for enctypes we will see in test
++# program output.  For background, aes256 and aes128 are "CFX enctypes",
++# meaning that they imply support for RFC 4121, while rc4 does not.
+ aes256 = 'aes256-cts-hmac-sha1-96'
+ aes128 = 'aes128-cts-hmac-sha1-96'
+-des3 = 'des3-cbc-sha1'
+-d_des3 = 'DEPRECATED:des3-cbc-sha1'
+-des3raw = 'des3-cbc-raw'
+-d_des3raw = 'DEPRECATED:des3-cbc-raw'
+ rc4 = 'arcfour-hmac'
+ d_rc4 = 'DEPRECATED:arcfour-hmac'
+ 
+ # These tests make assumptions about the default enctype lists, so set
+ # them explicitly rather than relying on the library defaults.
+-supp='aes256-cts:normal aes128-cts:normal des3-cbc-sha1:normal rc4-hmac:normal'
+-conf = {'libdefaults': {'permitted_enctypes': 'aes des3 rc4'},
++supp='aes256-cts:normal aes128-cts:normal rc4-hmac:normal'
++conf = {'libdefaults': {'permitted_enctypes': 'aes rc4'},
+         'realms': {'$realm': {'supported_enctypes': supp}}}
+ realm = K5Realm(krb5_conf=conf)
+ shutil.copyfile(realm.ccache, os.path.join(realm.testdir, 'save'))
+@@ -87,19 +80,12 @@ test('both aes128', 'aes128-cts', 'aes128-cts',
+ test_err('acc aes128', None, 'aes128-cts',
+          'Encryption type aes256-cts-hmac-sha1-96 not permitted')
+ 
+-# If the initiator constrains the permitted session enctypes to des3,
+-# no acceptor subkey will be generated because we can't upgrade to a
+-# CFX enctype.
+-test('init des3', 'des3', None,
+-     tktenc=aes256, tktsession=d_des3,
+-     proto='rfc1964', isubkey=des3raw, asubkey=None)
+-
+ # Force the ticket session key to be rc4, so we can test some subkey
+ # upgrade cases.  The ticket encryption key remains aes256.
+ realm.run([kadminl, 'setstr', realm.host_princ, 'session_enctypes', 'rc4'])
+ 
+ # With no arguments, the initiator should send an upgrade list of
+-# [aes256 aes128 des3] and the acceptor should upgrade to an aes256
++# [aes256 aes128] and the acceptor should upgrade to an aes256
+ # subkey.
+ test('upgrade noargs', None, None,
+      tktenc=aes256, tktsession=d_rc4,
+@@ -115,13 +101,6 @@ test('upgrade init aes128+rc4', 'aes128-cts rc4', None,
+      tktenc=aes256, tktsession=d_rc4,
+      proto='cfx', isubkey=rc4, asubkey=aes128)
+ 
+-# If the initiator permits rc4 but prefers des3, it will send an
+-# upgrade list of [des3], but the acceptor won't generate a subkey
+-# because des3 isn't a CFX enctype.
+-test('upgrade init des3+rc4', 'des3 rc4', None,
+-     tktenc=aes256, tktsession=d_rc4,
+-     proto='rfc1964', isubkey=rc4, asubkey=None)
+-
+ # If the acceptor permits only aes128, subkey negotiation will fail
+ # because the ticket session key and initiator subkey are
+ # non-permitted.  (This is unfortunate if the acceptor's restriction
+diff --git a/src/tests/gssapi/t_invalid.c b/src/tests/gssapi/t_invalid.c
+index 9876a11e6..fb8fe5511 100644
+--- a/src/tests/gssapi/t_invalid.c
++++ b/src/tests/gssapi/t_invalid.c
+@@ -84,18 +84,6 @@ struct test {
+     size_t toklen;
+     const char *token;
+ } tests[] = {
+-    {
+-        ENCTYPE_DES3_CBC_SHA1, ENCTYPE_DES3_CBC_RAW,
+-        SEAL_ALG_DES3KD, SGN_ALG_HMAC_SHA1_DES3_KD, 20,
+-        24,
+-        "\x4F\xEA\x19\x19\x5E\x0E\x10\xDF\x3D\x29\xB5\x13\x8F\x01\xC7\xA7"
+-        "\x92\x3D\x38\xF7\x26\x73\x0D\x6D",
+-        65,
+-        "\x60\x3F\x06\x09\x2A\x86\x48\x86\xF7\x12\x01\x02\x02\x02\x01\x04"
+-        "\x00\x02\x00\xFF\xFF\xEB\xF3\x9A\x89\x24\x57\xB8\x63\x95\x25\xE8"
+-        "\x6E\x8E\x79\xE6\x2E\xCA\xD3\xFF\x57\x9F\x8C\xAB\xEF\xDD\x28\x10"
+-        "\x2F\x93\x21\x2E\xF2\x52\xB6\x6F\xA8\xBB\x8A\x6D\xAA\x6F\xB7\xF4\xD4"
+-    },
+     {
+         ENCTYPE_ARCFOUR_HMAC, ENCTYPE_ARCFOUR_HMAC,
+         SEAL_ALG_MICROSOFT_RC4, SGN_ALG_HMAC_MD5, 8,
+diff --git a/src/tests/gssapi/t_pcontok.c b/src/tests/gssapi/t_pcontok.c
+index 7368f752f..bf22bd3da 100644
+--- a/src/tests/gssapi/t_pcontok.c
++++ b/src/tests/gssapi/t_pcontok.c
+@@ -43,7 +43,6 @@
+ #include "k5-int.h"
+ #include "common.h"
+ 
+-#define SGN_ALG_HMAC_SHA1_DES3_KD 0x04
+ #define SGN_ALG_HMAC_MD5          0x11
+ 
+ /*
+@@ -77,17 +76,12 @@ make_delete_token(gss_krb5_lucid_context_v1_t *lctx, gss_buffer_desc *out)
+     ret = krb5_k_create_key(context, &seqkb, &seq);
+     check_k5err(context, "krb5_k_create_key", ret);
+ 
+-    if (signalg == SGN_ALG_HMAC_SHA1_DES3_KD) {
+-        cktype = CKSUMTYPE_HMAC_SHA1_DES3;
+-        cksize = 20;
+-        ckusage = 23;
+-    } else if (signalg == SGN_ALG_HMAC_MD5) {
+-        cktype = CKSUMTYPE_HMAC_MD5_ARCFOUR;
+-        cksize = 8;
+-        ckusage = 15;
+-    } else {
++    if (signalg != SGN_ALG_HMAC_MD5)
+         abort();
+-    }
++
++    cktype = CKSUMTYPE_HMAC_MD5_ARCFOUR;
++    cksize = 8;
++    ckusage = 15;
+ 
+     tlen = 20 + mech_krb5.length + cksize;
+     token = malloc(tlen);
+diff --git a/src/tests/gssapi/t_prf.c b/src/tests/gssapi/t_prf.c
+index f71774cdc..d1857c433 100644
+--- a/src/tests/gssapi/t_prf.c
++++ b/src/tests/gssapi/t_prf.c
+@@ -41,13 +41,6 @@ static struct {
+     const char *key2;
+     const char *out2;
+ } tests[] = {
+-    { ENCTYPE_DES3_CBC_SHA1,
+-      "70378A19CD64134580C27C0115D6B34A1CF2FEECEF9886A2",
+-      "9F8D127C520BB826BFF3E0FE5EF352389C17E0C073D9"
+-      "AC4A333D644D21BA3EF24F4A886D143F85AC9F6377FB",
+-      "3452A167DF1094BA1089E0A20E9E51ABEF1525922558B69E",
+-      "6BF24FABC858F8DD9752E4FCD331BB831F238B5BE190"
+-      "4EEA42E38F7A60C588F075C5C96A67E7F8B7BD0AECF4" },
+     { ENCTYPE_ARCFOUR_HMAC,
+       "3BB3AE288C12B3B9D06B208A4151B3B6",
+       "9AEA11A3BCF3C53F1F91F5A0BA2132E2501ADF5F3C28"
+diff --git a/src/tests/t_authdata.py b/src/tests/t_authdata.py
+index c589adf2a..4fbdbec05 100644
+--- a/src/tests/t_authdata.py
++++ b/src/tests/t_authdata.py
+@@ -174,7 +174,7 @@ realm.run([kvno, 'restricted'])
+ # preferred krbtgt enctype changes.
+ mark('#8139 regression test')
+ realm.kinit(realm.user_princ, password('user'), ['-f'])
+-realm.run([kadminl, 'cpw', '-randkey', '-keepold', '-e', 'des3-cbc-sha1',
++realm.run([kadminl, 'cpw', '-randkey', '-keepold', '-e', 'aes256-sha2',
+            realm.krbtgt_princ])
+ realm.run(['./forward'])
+ realm.run([kvno, realm.host_princ])
+diff --git a/src/tests/t_etype_info.py b/src/tests/t_etype_info.py
+index 2a052fc17..ace0edc3c 100644
+--- a/src/tests/t_etype_info.py
++++ b/src/tests/t_etype_info.py
+@@ -1,6 +1,6 @@
+ from k5test import *
+ 
+-supported_enctypes = 'aes128-cts des3-cbc-sha1 rc4-hmac'
++supported_enctypes = 'aes128-cts rc4-hmac'
+ conf = {'libdefaults': {'allow_weak_crypto': 'true'},
+         'realms': {'$realm': {'supported_enctypes': supported_enctypes}}}
+ realm = K5Realm(create_host=False, get_creds=False, krb5_conf=conf)
+@@ -24,9 +24,9 @@ def test_etinfo(princ, enctypes, expected_lines):
+ # With no newer enctypes in the request, PA-ETYPE-INFO2,
+ # PA-ETYPE-INFO, and PA-PW-SALT appear in the AS-REP, each listing one
+ # key for the most preferred matching enctype.
+-test_etinfo('user', 'rc4-hmac-exp des3 rc4',
+-            ['asrep etype_info2 des3-cbc-sha1 KRBTEST.COMuser',
+-             'asrep etype_info des3-cbc-sha1 KRBTEST.COMuser',
++test_etinfo('user', 'rc4-hmac-exp rc4',
++            ['asrep etype_info2 rc4-hmac KRBTEST.COMuser',
++             'asrep etype_info rc4-hmac KRBTEST.COMuser',
+              'asrep pw_salt KRBTEST.COMuser'])
+ 
+ # With a newer enctype in the request (even if it is not the most
+@@ -37,9 +37,9 @@ test_etinfo('user', 'rc4 aes256-cts',
+ 
+ # In preauth-required errors, PA-PW-SALT does not appear, but the same
+ # etype-info2 values are expected.
+-test_etinfo('preauthuser', 'rc4-hmac-exp des3 rc4',
+-            ['error etype_info2 des3-cbc-sha1 KRBTEST.COMpreauthuser',
+-             'error etype_info des3-cbc-sha1 KRBTEST.COMpreauthuser'])
++test_etinfo('preauthuser', 'rc4-hmac-exp rc4',
++            ['error etype_info2 rc4-hmac KRBTEST.COMpreauthuser',
++             'error etype_info rc4-hmac KRBTEST.COMpreauthuser'])
+ test_etinfo('preauthuser', 'rc4 aes256-cts',
+             ['error etype_info2 rc4-hmac KRBTEST.COMpreauthuser'])
+ 
+@@ -48,8 +48,8 @@ test_etinfo('preauthuser', 'rc4 aes256-cts',
+ # (to allow for preauth mechs which don't depend on long-term keys).
+ # An AS-REP cannot be generated without preauth as there is no reply
+ # key.
+-test_etinfo('rc4user', 'des3', [])
+-test_etinfo('nokeyuser', 'des3', [])
++test_etinfo('rc4user', 'aes128-cts', [])
++test_etinfo('nokeyuser', 'aes128-cts', [])
+ 
+ # Verify that etype-info2 is included in a MORE_PREAUTH_DATA_REQUIRED
+ # error if the client does optimistic preauth.
+diff --git a/src/tests/t_keyrollover.py b/src/tests/t_keyrollover.py
+index 2c825a692..f29e0d550 100755
+--- a/src/tests/t_keyrollover.py
++++ b/src/tests/t_keyrollover.py
+@@ -37,9 +37,9 @@ realm.run([klist, '-e'], expected_msg=msg)
+ 
+ # Test that the KDC only accepts the first enctype for a kvno, for a
+ # local-realm TGS request.  To set this up, we abuse an edge-case
+-# behavior of modprinc -kvno.  First, set up a DES3 krbtgt entry at
++# behavior of modprinc -kvno.  First, set up an aes128-sha2 krbtgt entry at
+ # kvno 1 and cache a krbtgt ticket.
+-realm.run([kadminl, 'cpw', '-randkey', '-e', 'des3-cbc-sha1',
++realm.run([kadminl, 'cpw', '-randkey', '-e', 'aes128-cts-hmac-sha256-128',
+            realm.krbtgt_princ])
+ realm.run([kadminl, 'modprinc', '-kvno', '1', realm.krbtgt_princ])
+ realm.kinit(realm.user_princ, password('user'))
+@@ -50,9 +50,9 @@ realm.run([kadminl, 'cpw', '-randkey', '-keepold', '-e', 'aes256-cts',
+ realm.run([kadminl, 'modprinc', '-kvno', '1', realm.krbtgt_princ])
+ out = realm.run([kadminl, 'getprinc', realm.krbtgt_princ])
+ if 'vno 1, aes256-cts' not in out or \
+-   'vno 1, DEPRECATED:des3-cbc-sha1' not in out:
++   'vno 1, aes128-cts-hmac-sha256-128' not in out:
+     fail('keyrollover: setup for TGS enctype test failed')
+-# Now present the DES3 ticket to the KDC and make sure it's rejected.
++# Now present the aes128-sha2 ticket to the KDC and make sure it's rejected.
+ realm.run([kvno, realm.host_princ], expected_code=1)
+ 
+ realm.stop()
+diff --git a/src/tests/t_mkey.py b/src/tests/t_mkey.py
+index 99273c907..f84041ca4 100755
+--- a/src/tests/t_mkey.py
++++ b/src/tests/t_mkey.py
+@@ -7,7 +7,6 @@ import struct
+ # default enctype for master keys.
+ aes256 = 'aes256-cts-hmac-sha1-96'
+ aes128 = 'aes128-cts-hmac-sha1-96'
+-des3 = 'des3-cbc-sha1'
+ defetype = aes256
+ 
+ realm = K5Realm(create_host=False, start_kadmind=True)
+@@ -300,40 +299,6 @@ if 'Decrypt integrity check failed' in out or 'added to keytab' not in out:
+ 
+ realm.stop()
+ 
+-# Load a dump file created with krb5 1.6, before the master key
+-# rollover changes were introduced.  Write out an old-format stash
+-# file consistent with the dump's master password ("footes").  The K/M
+-# entry in this database will not have actkvno tl-data because it was
+-# created prior to master key rollover support.  Verify that:
+-# 1. We can access the database using the old-format stash file.
+-# 2. list_mkeys displays the same list as for a post-1.7 KDB.
+-mark('pre-1.7 stash file')
+-dumpfile = os.path.join(srctop, 'tests', 'dumpfiles', 'dump.16')
+-os.remove(stash_file)
+-f = open(stash_file, 'wb')
+-f.write(struct.pack('=HL24s', 16, 24,
+-                    b'\xF8\x3E\xFB\xBA\x6D\x80\xD9\x54\xE5\x5D\xF2\xE0'
+-                    b'\x94\xAD\x6D\x86\xB5\x16\x37\xEC\x7C\x8A\xBC\x86'))
+-f.close()
+-realm.run([kdb5_util, 'load', dumpfile])
+-nprincs = len(realm.run([kadminl, 'listprincs']).splitlines())
+-check_mkvno('K/M', 1)
+-check_mkey_list((1, des3, True, True))
+-
+-# Create a new master key and verify that, without actkvkno tl-data:
+-# 1. list_mkeys displays the same as for a post-1.7 KDB.
+-# 2. update_princ_encryption still targets mkvno 1.
+-# 3. libkadm5 still uses mkvno 1 for key changes.
+-# 4. use_mkey creates the same list as for a post-1.7 KDB.
+-mark('rollover from pre-1.7 KDB')
+-add_mkey([])
+-check_mkey_list((2, defetype, False, False), (1, des3, True, True))
+-update_princ_encryption(False, 1, 0, nprincs - 1)
+-realm.run([kadminl, 'addprinc', '-randkey', realm.user_princ])
+-check_mkvno(realm.user_princ, 1)
+-realm.run([kdb5_util, 'use_mkey', '2', 'now-1day'])
+-check_mkey_list((2, defetype, True, True), (1, des3, True, False))
+-
+ # Regression test for #8395.  Purge the master key and verify that a
+ # master key fetch does not segfault.
+ mark('#8395 regression test')
+diff --git a/src/tests/t_salt.py b/src/tests/t_salt.py
+index 65084bbf3..55ca89745 100755
+--- a/src/tests/t_salt.py
++++ b/src/tests/t_salt.py
+@@ -16,13 +16,12 @@ def test_salt(realm, e1, salt, e2):
+ 
+ # Enctype/salt pairs chosen with non-default salt types.
+ # The enctypes are mostly arbitrary.
+-salts = [('des3-cbc-sha1', 'norealm'),
++salts = [('aes128-cts-hmac-sha1-96', 'norealm'),
+          ('arcfour-hmac', 'onlyrealm'),
+          ('aes128-cts-hmac-sha1-96', 'special')]
+ # These enctypes are chosen to cover the different string-to-key routines.
+ # Omit ":normal" from aes256 to check that salttype defaulting works.
+-second_kstypes = ['aes256-cts-hmac-sha1-96', 'arcfour-hmac:normal',
+-                  'des3-cbc-sha1:normal']
++second_kstypes = ['aes256-cts-hmac-sha1-96', 'arcfour-hmac:normal']
+ 
+ # Test using different salt types in a principal's key list.
+ # Parameters from one key in the list must not leak over to later ones.
+diff --git a/src/util/k5test.py b/src/util/k5test.py
+index 442a4e4f7..eea92275d 100644
+--- a/src/util/k5test.py
++++ b/src/util/k5test.py
+@@ -1299,13 +1299,6 @@ _passes = [
+     # No special settings; exercises AES256.
+     ('default', None, None, None),
+ 
+-    # Exercise the DES3 enctype.
+-    ('des3', None,
+-     {'libdefaults': {'permitted_enctypes': 'des3'}},
+-     {'realms': {'$realm': {
+-                    'supported_enctypes': 'des3-cbc-sha1:normal',
+-                    'master_key_type': 'des3-cbc-sha1'}}}),
+-
+     # Exercise the arcfour enctype.
+     ('arcfour', None,
+      {'libdefaults': {'permitted_enctypes': 'rc4'}},
+diff --git a/src/windows/leash/htmlhelp/html/Encryption_Types.htm b/src/windows/leash/htmlhelp/html/Encryption_Types.htm
+index 1aebdd0b4..c38eefd2b 100644
+--- a/src/windows/leash/htmlhelp/html/Encryption_Types.htm
++++ b/src/windows/leash/htmlhelp/html/Encryption_Types.htm
+@@ -79,19 +79,6 @@ will have an entry in the Encryption type column. <br>
+ <th>Description</th>
+ </tr>
+ <tr>
+-<th id="th2"> des3- </th>
+-   <td> The triple DES family improves on
+-the original DES (Data Encryption Standard) by using 3 separate 56-bit
+-keys. Some modes of 3DES are considered weak while others are strong
+-(if slow). <ul id="helpul">
+-<li> des3-cbc-sha1</li>
+-<li> des3-cbc-raw  (<b>weak</b>) </li>
+-<li>des3-hmac-sha1 </li>
+-<li>des3-cbc-sha1-kd </li>
+-</ul>
+-</td>
+- </tr>
+-<tr>
+ <th id="th2"> aes </th>
+      <td>The AES Advanced Encryption Standard
+ family, like 3DES, is a symmetric block cipher and was designed
diff --git a/SOURCES/downstream-SELinux-integration.patch b/SOURCES/downstream-SELinux-integration.patch
new file mode 100644
index 0000000..13aa0b6
--- /dev/null
+++ b/SOURCES/downstream-SELinux-integration.patch
@@ -0,0 +1,1035 @@
+From 791fe183bf67dcab6d044b23d8daaf4a3a96be48 Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Tue, 23 Aug 2016 16:30:53 -0400
+Subject: [PATCH] [downstream] SELinux integration
+
+SELinux bases access to files on the domain of the requesting process,
+the operation being performed, and the context applied to the file.
+
+In many cases, applications needn't be SELinux aware to work properly,
+because SELinux can apply a default label to a file based on the label
+of the directory in which it's created.
+
+In the case of files such as /etc/krb5.keytab, however, this isn't
+sufficient, as /etc/krb5.keytab will almost always need to be given a
+label which differs from that of /etc/issue or /etc/resolv.conf.  The
+the kdb stash file needs a different label than the database for which
+it's holding a master key, even though both typically live in the same
+directory.
+
+To give the file the correct label, we can either force a "restorecon"
+call to fix a file's label after it's created, or create the file with
+the right label, as we attempt to do here.  We lean on THREEPARAMOPEN
+and define a similar macro named WRITABLEFOPEN with which we replace
+several uses of fopen().
+
+The file creation context that we're manipulating here is a process-wide
+attribute.  While for the most part, applications which need to label
+files when they're created have tended to be single-threaded, there's
+not much we can do to avoid interfering with an application that
+manipulates the creation context directly.  Right now we're mediating
+access using a library-local mutex, but that can only work for consumers
+that are part of this package -- an unsuspecting application will still
+stomp all over us.
+
+The selabel APIs for looking up the context should be thread-safe (per
+Red Hat #273081), so switching to using them instead of matchpathcon(),
+which we used earlier, is some improvement.
+
+Last-updated: krb5-1.18-beta1
+(cherry picked from commit 0f8851a23a7b6fa0e195e01d0475e9e55707adf2)
+---
+ src/aclocal.m4                                |  48 +++
+ src/build-tools/krb5-config.in                |   3 +-
+ src/config/pre.in                             |   3 +-
+ src/configure.ac                              |   2 +
+ src/include/k5-int.h                          |   1 +
+ src/include/k5-label.h                        |  32 ++
+ src/include/krb5/krb5.hin                     |   6 +
+ src/kadmin/dbutil/dump.c                      |  11 +-
+ src/kdc/main.c                                |   2 +-
+ src/kprop/kpropd.c                            |   9 +
+ src/lib/kadm5/logger.c                        |   4 +-
+ src/lib/kdb/kdb_log.c                         |   2 +-
+ src/lib/krb5/ccache/cc_dir.c                  |  26 +-
+ src/lib/krb5/keytab/kt_file.c                 |   4 +-
+ src/lib/krb5/os/trace.c                       |   2 +-
+ src/plugins/kdb/db2/adb_openclose.c           |   2 +-
+ src/plugins/kdb/db2/kdb_db2.c                 |   4 +-
+ src/plugins/kdb/db2/libdb2/btree/bt_open.c    |   3 +-
+ src/plugins/kdb/db2/libdb2/hash/hash.c        |   3 +-
+ src/plugins/kdb/db2/libdb2/recno/rec_open.c   |   4 +-
+ .../kdb/ldap/ldap_util/kdb5_ldap_services.c   |  11 +-
+ src/util/profile/prof_file.c                  |   3 +-
+ src/util/support/Makefile.in                  |   3 +-
+ src/util/support/selinux.c                    | 406 ++++++++++++++++++
+ 24 files changed, 573 insertions(+), 21 deletions(-)
+ create mode 100644 src/include/k5-label.h
+ create mode 100644 src/util/support/selinux.c
+
+diff --git a/src/aclocal.m4 b/src/aclocal.m4
+index 830203683..6796fec53 100644
+--- a/src/aclocal.m4
++++ b/src/aclocal.m4
+@@ -89,6 +89,7 @@ AC_SUBST_FILE(libnodeps_frag)
+ dnl
+ KRB5_AC_PRAGMA_WEAK_REF
+ WITH_LDAP
++KRB5_WITH_SELINUX
+ KRB5_LIB_PARAMS
+ KRB5_AC_INITFINI
+ KRB5_AC_ENABLE_THREADS
+@@ -1743,4 +1744,51 @@ AC_SUBST(PAM_LIBS)
+ AC_SUBST(PAM_MAN)
+ AC_SUBST(NON_PAM_MAN)
+ ])dnl
++dnl
++dnl Use libselinux to set file contexts on newly-created files.
++dnl
++AC_DEFUN(KRB5_WITH_SELINUX,[
++AC_ARG_WITH(selinux,[AC_HELP_STRING(--with-selinux,[compile with SELinux labeling support])],
++           withselinux="$withval",withselinux=auto)
++old_LIBS="$LIBS"
++if test "$withselinux" != no ; then
++       AC_MSG_RESULT([checking for libselinux...])
++       SELINUX_LIBS=
++       AC_CHECK_HEADERS(selinux/selinux.h selinux/label.h)
++       if test "x$ac_cv_header_selinux_selinux_h" != xyes ; then
++               if test "$withselinux" = auto ; then
++                       AC_MSG_RESULT([Unable to locate selinux/selinux.h.])
++                       withselinux=no
++               else
++                       AC_MSG_ERROR([Unable to locate selinux/selinux.h.])
++               fi
++       fi
+ 
++       LIBS=
++       unset ac_cv_func_setfscreatecon
++       AC_CHECK_FUNCS(setfscreatecon selabel_open)
++       if test "x$ac_cv_func_setfscreatecon" = xno ; then
++               AC_CHECK_LIB(selinux,setfscreatecon)
++               unset ac_cv_func_setfscreatecon
++               AC_CHECK_FUNCS(setfscreatecon selabel_open)
++               if test "x$ac_cv_func_setfscreatecon" = xyes ; then
++                       SELINUX_LIBS="$LIBS"
++               else
++                       if test "$withselinux" = auto ; then
++                               AC_MSG_RESULT([Unable to locate libselinux.])
++                               withselinux=no
++                       else
++                               AC_MSG_ERROR([Unable to locate libselinux.])
++                       fi
++               fi
++       fi
++       if test "$withselinux" != no ; then
++               AC_MSG_NOTICE([building with SELinux labeling support])
++               AC_DEFINE(USE_SELINUX,1,[Define if Kerberos-aware tools should set SELinux file contexts when creating files.])
++               SELINUX_LIBS="$LIBS"
++		EXTRA_SUPPORT_SYMS="$EXTRA_SUPPORT_SYMS krb5int_labeled_open krb5int_labeled_fopen krb5int_push_fscreatecon_for krb5int_pop_fscreatecon"
++       fi
++fi
++LIBS="$old_LIBS"
++AC_SUBST(SELINUX_LIBS)
++])dnl
+diff --git a/src/build-tools/krb5-config.in b/src/build-tools/krb5-config.in
+index f6184da3f..c17cb5eb5 100755
+--- a/src/build-tools/krb5-config.in
++++ b/src/build-tools/krb5-config.in
+@@ -41,6 +41,7 @@ DL_LIB='@DL_LIB@'
+ DEFCCNAME='@DEFCCNAME@'
+ DEFKTNAME='@DEFKTNAME@'
+ DEFCKTNAME='@DEFCKTNAME@'
++SELINUX_LIBS='@SELINUX_LIBS@'
+ 
+ LIBS='@LIBS@'
+ GEN_LIB=@GEN_LIB@
+@@ -255,7 +256,7 @@ if test -n "$do_libs"; then
+     fi
+ 
+     # If we ever support a flag to generate output suitable for static
+-    # linking, we would output "-lkrb5support $GEN_LIB $LIBS $DL_LIB"
++    # linking, we would output "-lkrb5support $GEN_LIB $LIBS $SELINUX_LIBS $DL_LIB"
+     # here.
+ 
+     echo $lib_flags
+diff --git a/src/config/pre.in b/src/config/pre.in
+index ce87e21ca..917357df9 100644
+--- a/src/config/pre.in
++++ b/src/config/pre.in
+@@ -177,6 +177,7 @@ LD = $(PURE) @LD@
+ KRB_INCLUDES = -I$(BUILDTOP)/include -I$(top_srcdir)/include
+ LDFLAGS = @LDFLAGS@
+ LIBS = @LIBS@
++SELINUX_LIBS=@SELINUX_LIBS@
+ 
+ INSTALL=@INSTALL@
+ INSTALL_STRIP=
+@@ -402,7 +403,7 @@ SUPPORT_LIB			= -l$(SUPPORT_LIBNAME)
+ # HESIOD_LIBS is -lhesiod...
+ HESIOD_LIBS	= @HESIOD_LIBS@
+ 
+-KRB5_BASE_LIBS	= $(KRB5_LIB) $(K5CRYPTO_LIB) $(COM_ERR_LIB) $(SUPPORT_LIB) $(GEN_LIB) $(LIBS) $(DL_LIB)
++KRB5_BASE_LIBS	= $(KRB5_LIB) $(K5CRYPTO_LIB) $(COM_ERR_LIB) $(SUPPORT_LIB) $(GEN_LIB) $(LIBS) $(SELINUX_LIBS) $(DL_LIB)
+ KDB5_LIBS	= $(KDB5_LIB) $(GSSRPC_LIBS)
+ GSS_LIBS	= $(GSS_KRB5_LIB)
+ # needs fixing if ever used on macOS!
+diff --git a/src/configure.ac b/src/configure.ac
+index d1f576124..440a22bd9 100644
+--- a/src/configure.ac
++++ b/src/configure.ac
+@@ -1392,6 +1392,8 @@ AC_PATH_PROG(GROFF, groff)
+ 
+ KRB5_WITH_PAM
+ 
++KRB5_WITH_SELINUX
++
+ # Make localedir work in autoconf 2.5x.
+ if test "${localedir+set}" != set; then
+     localedir='$(datadir)/locale'
+diff --git a/src/include/k5-int.h b/src/include/k5-int.h
+index 9616b24bf..0d9af3d95 100644
+--- a/src/include/k5-int.h
++++ b/src/include/k5-int.h
+@@ -128,6 +128,7 @@ typedef unsigned char   u_char;
+ 
+ 
+ #include "k5-platform.h"
++#include "k5-label.h"
+ 
+ #define KRB5_KDB_MAX_LIFE       (60*60*24) /* one day */
+ #define KRB5_KDB_MAX_RLIFE      (60*60*24*7) /* one week */
+diff --git a/src/include/k5-label.h b/src/include/k5-label.h
+new file mode 100644
+index 000000000..dfaaa847c
+--- /dev/null
++++ b/src/include/k5-label.h
+@@ -0,0 +1,32 @@
++#ifndef _KRB5_LABEL_H
++#define _KRB5_LABEL_H
++
++#ifdef THREEPARAMOPEN
++#undef THREEPARAMOPEN
++#endif
++#ifdef WRITABLEFOPEN
++#undef WRITABLEFOPEN
++#endif
++
++/* Wrapper functions which help us create files and directories with the right
++ * context labels. */
++#ifdef USE_SELINUX
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <fcntl.h>
++#include <stdio.h>
++#include <unistd.h>
++FILE *krb5int_labeled_fopen(const char *path, const char *mode);
++int krb5int_labeled_creat(const char *path, mode_t mode);
++int krb5int_labeled_open(const char *path, int flags, ...);
++int krb5int_labeled_mkdir(const char *path, mode_t mode);
++int krb5int_labeled_mknod(const char *path, mode_t mode, dev_t device);
++#define THREEPARAMOPEN(x,y,z) krb5int_labeled_open(x,y,z)
++#define WRITABLEFOPEN(x,y) krb5int_labeled_fopen(x,y)
++void *krb5int_push_fscreatecon_for(const char *pathname);
++void krb5int_pop_fscreatecon(void *previous);
++#else
++#define WRITABLEFOPEN(x,y) fopen(x,y)
++#define THREEPARAMOPEN(x,y,z) open(x,y,z)
++#endif
++#endif
+diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin
+index 79761f6d2..e9435c693 100644
+--- a/src/include/krb5/krb5.hin
++++ b/src/include/krb5/krb5.hin
+@@ -87,6 +87,12 @@
+ #define THREEPARAMOPEN(x,y,z) open(x,y,z)
+ #endif
+ 
++#if KRB5_PRIVATE
++#ifndef WRITABLEFOPEN
++#define WRITABLEFOPEN(x,y) fopen(x,y)
++#endif
++#endif
++
+ #define KRB5_OLD_CRYPTO
+ 
+ #include <stdlib.h>
+diff --git a/src/kadmin/dbutil/dump.c b/src/kadmin/dbutil/dump.c
+index 301e3476d..19f2cc230 100644
+--- a/src/kadmin/dbutil/dump.c
++++ b/src/kadmin/dbutil/dump.c
+@@ -148,12 +148,21 @@ create_ofile(char *ofile, char **tmpname)
+ {
+     int fd = -1;
+     FILE *f;
++#ifdef USE_SELINUX
++    void *selabel;
++#endif
+ 
+     *tmpname = NULL;
+     if (asprintf(tmpname, "%s-XXXXXX", ofile) < 0)
+         goto error;
+ 
++#ifdef USE_SELINUX
++    selabel = krb5int_push_fscreatecon_for(ofile);
++#endif
+     fd = mkstemp(*tmpname);
++#ifdef USE_SELINUX
++    krb5int_pop_fscreatecon(selabel);
++#endif
+     if (fd == -1)
+         goto error;
+ 
+@@ -197,7 +206,7 @@ prep_ok_file(krb5_context context, char *file_name, int *fd_out)
+         goto cleanup;
+     }
+ 
+-    fd = open(file_ok, O_WRONLY | O_CREAT | O_TRUNC, 0600);
++    fd = THREEPARAMOPEN(file_ok, O_WRONLY | O_CREAT | O_TRUNC, 0600);
+     if (fd == -1) {
+         com_err(progname, errno, _("while creating 'ok' file, '%s'"), file_ok);
+         goto cleanup;
+diff --git a/src/kdc/main.c b/src/kdc/main.c
+index fdcd694d7..1ede4bf2f 100644
+--- a/src/kdc/main.c
++++ b/src/kdc/main.c
+@@ -872,7 +872,7 @@ write_pid_file(const char *path)
+     FILE *file;
+     unsigned long pid;
+ 
+-    file = fopen(path, "w");
++    file = WRITABLEFOPEN(path, "w");
+     if (file == NULL)
+         return errno;
+     pid = (unsigned long) getpid();
+diff --git a/src/kprop/kpropd.c b/src/kprop/kpropd.c
+index 5622d56e1..356e3e0e6 100644
+--- a/src/kprop/kpropd.c
++++ b/src/kprop/kpropd.c
+@@ -487,6 +487,9 @@ doit(int fd)
+     krb5_enctype etype;
+     int database_fd;
+     char host[INET6_ADDRSTRLEN + 1];
++#ifdef USE_SELINUX
++    void *selabel;
++#endif
+ 
+     signal_wrapper(SIGALRM, alarm_handler);
+     alarm(params.iprop_resync_timeout);
+@@ -542,9 +545,15 @@ doit(int fd)
+         free(name);
+         exit(1);
+     }
++#ifdef USE_SELINUX
++    selabel = krb5int_push_fscreatecon_for(file);
++#endif
+     omask = umask(077);
+     lock_fd = open(temp_file_name, O_RDWR | O_CREAT, 0600);
+     (void)umask(omask);
++#ifdef USE_SELINUX
++    krb5int_pop_fscreatecon(selabel);
++#endif
+     retval = krb5_lock_file(kpropd_context, lock_fd,
+                             KRB5_LOCKMODE_EXCLUSIVE | KRB5_LOCKMODE_DONTBLOCK);
+     if (retval) {
+diff --git a/src/lib/kadm5/logger.c b/src/lib/kadm5/logger.c
+index c6885edf2..9aec3c05e 100644
+--- a/src/lib/kadm5/logger.c
++++ b/src/lib/kadm5/logger.c
+@@ -309,7 +309,7 @@ krb5_klog_init(krb5_context kcontext, char *ename, char *whoami, krb5_boolean do
+                      */
+                     append = (cp[4] == ':') ? O_APPEND : 0;
+                     if (append || cp[4] == '=') {
+-                        fd = open(&cp[5], O_CREAT | O_WRONLY | append,
++                        fd = THREEPARAMOPEN(&cp[5], O_CREAT | O_WRONLY | append,
+                                   S_IRUSR | S_IWUSR | S_IRGRP);
+                         if (fd != -1)
+                             f = fdopen(fd, append ? "a" : "w");
+@@ -776,7 +776,7 @@ krb5_klog_reopen(krb5_context kcontext)
+              * In case the old logfile did not get moved out of the
+              * way, open for append to prevent squashing the old logs.
+              */
+-            f = fopen(log_control.log_entries[lindex].lfu_fname, "a+");
++            f = WRITABLEFOPEN(log_control.log_entries[lindex].lfu_fname, "a+");
+             if (f) {
+                 set_cloexec_file(f);
+                 log_control.log_entries[lindex].lfu_filep = f;
+diff --git a/src/lib/kdb/kdb_log.c b/src/lib/kdb/kdb_log.c
+index 2659a2501..e9b95fce5 100644
+--- a/src/lib/kdb/kdb_log.c
++++ b/src/lib/kdb/kdb_log.c
+@@ -480,7 +480,7 @@ ulog_map(krb5_context context, const char *logname, uint32_t ulogentries)
+         return ENOMEM;
+ 
+     if (stat(logname, &st) == -1) {
+-        log_ctx->ulogfd = open(logname, O_RDWR | O_CREAT, 0600);
++        log_ctx->ulogfd = THREEPARAMOPEN(logname, O_RDWR | O_CREAT, 0600);
+         if (log_ctx->ulogfd == -1) {
+             retval = errno;
+             goto cleanup;
+diff --git a/src/lib/krb5/ccache/cc_dir.c b/src/lib/krb5/ccache/cc_dir.c
+index 7b100a0ec..5683a0433 100644
+--- a/src/lib/krb5/ccache/cc_dir.c
++++ b/src/lib/krb5/ccache/cc_dir.c
+@@ -183,10 +183,19 @@ write_primary_file(const char *primary_path, const char *contents)
+     char *newpath = NULL;
+     FILE *fp = NULL;
+     int fd = -1, status;
++#ifdef USE_SELINUX
++    void *selabel;
++#endif
+ 
+     if (asprintf(&newpath, "%s.XXXXXX", primary_path) < 0)
+         return ENOMEM;
++#ifdef USE_SELINUX
++    selabel = krb5int_push_fscreatecon_for(primary_path);
++#endif
+     fd = mkstemp(newpath);
++#ifdef USE_SELINUX
++    krb5int_pop_fscreatecon(selabel);
++#endif
+     if (fd < 0)
+         goto cleanup;
+ #ifdef HAVE_CHMOD
+@@ -221,10 +230,23 @@ static krb5_error_code
+ verify_dir(krb5_context context, const char *dirname)
+ {
+     struct stat st;
++    int status;
++#ifdef USE_SELINUX
++    void *selabel;
++#endif
+ 
+     if (stat(dirname, &st) < 0) {
+-        if (errno == ENOENT && mkdir(dirname, S_IRWXU) == 0)
+-            return 0;
++        if (errno == ENOENT) {
++#ifdef USE_SELINUX
++            selabel = krb5int_push_fscreatecon_for(dirname);
++#endif
++            status = mkdir(dirname, S_IRWXU);
++#ifdef USE_SELINUX
++            krb5int_pop_fscreatecon(selabel);
++#endif
++            if (status == 0)
++                return 0;
++        }
+         k5_setmsg(context, KRB5_FCC_NOFILE,
+                   _("Credential cache directory %s does not exist"),
+                   dirname);
+diff --git a/src/lib/krb5/keytab/kt_file.c b/src/lib/krb5/keytab/kt_file.c
+index 021c94398..aaf573439 100644
+--- a/src/lib/krb5/keytab/kt_file.c
++++ b/src/lib/krb5/keytab/kt_file.c
+@@ -735,14 +735,14 @@ krb5_ktfileint_open(krb5_context context, krb5_keytab id, int mode)
+ 
+     KTCHECKLOCK(id);
+     errno = 0;
+-    KTFILEP(id) = fopen(KTFILENAME(id),
++    KTFILEP(id) = WRITABLEFOPEN(KTFILENAME(id),
+                         (mode == KRB5_LOCKMODE_EXCLUSIVE) ? "rb+" : "rb");
+     if (!KTFILEP(id)) {
+         if ((mode == KRB5_LOCKMODE_EXCLUSIVE) && (errno == ENOENT)) {
+             /* try making it first time around */
+             k5_create_secure_file(context, KTFILENAME(id));
+             errno = 0;
+-            KTFILEP(id) = fopen(KTFILENAME(id), "rb+");
++            KTFILEP(id) = WRITABLEFOPEN(KTFILENAME(id), "rb+");
+             if (!KTFILEP(id))
+                 goto report_errno;
+             writevno = 1;
+diff --git a/src/lib/krb5/os/trace.c b/src/lib/krb5/os/trace.c
+index 7073459f0..e9b99f4ca 100644
+--- a/src/lib/krb5/os/trace.c
++++ b/src/lib/krb5/os/trace.c
+@@ -458,7 +458,7 @@ krb5_set_trace_filename(krb5_context context, const char *filename)
+     fd = malloc(sizeof(*fd));
+     if (fd == NULL)
+         return ENOMEM;
+-    *fd = open(filename, O_WRONLY|O_CREAT|O_APPEND, 0600);
++    *fd = THREEPARAMOPEN(filename, O_WRONLY|O_CREAT|O_APPEND, 0600);
+     if (*fd == -1) {
+         free(fd);
+         return errno;
+diff --git a/src/plugins/kdb/db2/adb_openclose.c b/src/plugins/kdb/db2/adb_openclose.c
+index 7db30a33b..2b9d01921 100644
+--- a/src/plugins/kdb/db2/adb_openclose.c
++++ b/src/plugins/kdb/db2/adb_openclose.c
+@@ -152,7 +152,7 @@ osa_adb_init_db(osa_adb_db_t *dbp, char *filename, char *lockfilename,
+          * needs be open read/write so that write locking can work with
+          * POSIX systems
+          */
+-        if ((lockp->lockinfo.lockfile = fopen(lockfilename, "r+")) == NULL) {
++        if ((lockp->lockinfo.lockfile = WRITABLEFOPEN(lockfilename, "r+")) == NULL) {
+             /*
+              * maybe someone took away write permission so we could only
+              * get shared locks?
+diff --git a/src/plugins/kdb/db2/kdb_db2.c b/src/plugins/kdb/db2/kdb_db2.c
+index 5106a5c99..e481e8121 100644
+--- a/src/plugins/kdb/db2/kdb_db2.c
++++ b/src/plugins/kdb/db2/kdb_db2.c
+@@ -694,8 +694,8 @@ ctx_create_db(krb5_context context, krb5_db2_context *dbc)
+     if (retval)
+         return retval;
+ 
+-    dbc->db_lf_file = open(dbc->db_lf_name, O_CREAT | O_RDWR | O_TRUNC,
+-                           0600);
++    dbc->db_lf_file = THREEPARAMOPEN(dbc->db_lf_name,
++                                     O_CREAT | O_RDWR | O_TRUNC, 0600);
+     if (dbc->db_lf_file < 0) {
+         retval = errno;
+         goto cleanup;
+diff --git a/src/plugins/kdb/db2/libdb2/btree/bt_open.c b/src/plugins/kdb/db2/libdb2/btree/bt_open.c
+index 2977b17f3..d5809a5a9 100644
+--- a/src/plugins/kdb/db2/libdb2/btree/bt_open.c
++++ b/src/plugins/kdb/db2/libdb2/btree/bt_open.c
+@@ -60,6 +60,7 @@ static char sccsid[] = "@(#)bt_open.c	8.11 (Berkeley) 11/2/95";
+ #include <string.h>
+ #include <unistd.h>
+ 
++#include "k5-int.h"
+ #include "db-int.h"
+ #include "btree.h"
+ 
+@@ -203,7 +204,7 @@ __bt_open(fname, flags, mode, openinfo, dflags)
+ 			goto einval;
+ 		}
+ 
+-		if ((t->bt_fd = open(fname, flags | O_BINARY, mode)) < 0)
++		if ((t->bt_fd = THREEPARAMOPEN(fname, flags | O_BINARY, mode)) < 0)
+ 			goto err;
+ 
+ 	} else {
+diff --git a/src/plugins/kdb/db2/libdb2/hash/hash.c b/src/plugins/kdb/db2/libdb2/hash/hash.c
+index 862dbb164..686a960c9 100644
+--- a/src/plugins/kdb/db2/libdb2/hash/hash.c
++++ b/src/plugins/kdb/db2/libdb2/hash/hash.c
+@@ -51,6 +51,7 @@ static char sccsid[] = "@(#)hash.c	8.12 (Berkeley) 11/7/95";
+ #include <assert.h>
+ #endif
+ 
++#include "k5-int.h"
+ #include "db-int.h"
+ #include "hash.h"
+ #include "page.h"
+@@ -129,7 +130,7 @@ __kdb2_hash_open(file, flags, mode, info, dflags)
+ 		new_table = 1;
+ 	}
+ 	if (file) {
+-		if ((hashp->fp = open(file, flags|O_BINARY, mode)) == -1)
++		if ((hashp->fp = THREEPARAMOPEN(file, flags|O_BINARY, mode)) == -1)
+ 			RETURN_ERROR(errno, error0);
+ 		(void)fcntl(hashp->fp, F_SETFD, 1);
+ 	}
+diff --git a/src/plugins/kdb/db2/libdb2/recno/rec_open.c b/src/plugins/kdb/db2/libdb2/recno/rec_open.c
+index d8b26e701..b0daa7c02 100644
+--- a/src/plugins/kdb/db2/libdb2/recno/rec_open.c
++++ b/src/plugins/kdb/db2/libdb2/recno/rec_open.c
+@@ -51,6 +51,7 @@ static char sccsid[] = "@(#)rec_open.c	8.12 (Berkeley) 11/18/94";
+ #include <stdio.h>
+ #include <unistd.h>
+ 
++#include "k5-int.h"
+ #include "db-int.h"
+ #include "recno.h"
+ 
+@@ -68,7 +69,8 @@ __rec_open(fname, flags, mode, openinfo, dflags)
+ 	int rfd = -1, sverrno;
+ 
+ 	/* Open the user's file -- if this fails, we're done. */
+-	if (fname != NULL && (rfd = open(fname, flags | O_BINARY, mode)) < 0)
++	if (fname != NULL &&
++            (rfd = THREEPARAMOPEN(fname, flags | O_BINARY, mode)) < 0)
+ 		return (NULL);
+ 
+ 	if (fname != NULL && fcntl(rfd, F_SETFD, 1) == -1) {
+diff --git a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c
+index b92cb58c7..0a95101ad 100644
+--- a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c
++++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c
+@@ -190,7 +190,7 @@ kdb5_ldap_stash_service_password(int argc, char **argv)
+ 
+     /* set password in the file */
+     old_mode = umask(0177);
+-    pfile = fopen(file_name, "a+");
++    pfile = WRITABLEFOPEN(file_name, "a+");
+     if (pfile == NULL) {
+         com_err(me, errno, _("Failed to open file %s: %s"), file_name,
+                 strerror (errno));
+@@ -231,6 +231,9 @@ kdb5_ldap_stash_service_password(int argc, char **argv)
+          * Delete the existing entry and add the new entry
+          */
+         FILE *newfile;
++#ifdef USE_SELINUX
++        void *selabel;
++#endif
+ 
+         mode_t omask;
+ 
+@@ -242,7 +245,13 @@ kdb5_ldap_stash_service_password(int argc, char **argv)
+         }
+ 
+         omask = umask(077);
++#ifdef USE_SELINUX
++        selabel = krb5int_push_fscreatecon_for(file_name);
++#endif
+         newfile = fopen(tmp_file, "w");
++#ifdef USE_SELINUX
++        krb5int_pop_fscreatecon(selabel);
++#endif
+         umask (omask);
+         if (newfile == NULL) {
+             com_err(me, errno, _("Error creating file %s"), tmp_file);
+diff --git a/src/util/profile/prof_file.c b/src/util/profile/prof_file.c
+index aa951df05..79f9500f6 100644
+--- a/src/util/profile/prof_file.c
++++ b/src/util/profile/prof_file.c
+@@ -33,6 +33,7 @@
+ #endif
+ 
+ #include "k5-platform.h"
++#include "k5-label.h"
+ 
+ struct global_shared_profile_data {
+     /* This is the head of the global list of shared trees */
+@@ -391,7 +392,7 @@ static errcode_t write_data_to_file(prf_data_t data, const char *outfile,
+ 
+     errno = 0;
+ 
+-    f = fopen(new_file, "w");
++    f = WRITABLEFOPEN(new_file, "w");
+     if (!f) {
+         retval = errno;
+         if (retval == 0)
+diff --git a/src/util/support/Makefile.in b/src/util/support/Makefile.in
+index 86d5a950a..1052d53a1 100644
+--- a/src/util/support/Makefile.in
++++ b/src/util/support/Makefile.in
+@@ -74,6 +74,7 @@ IPC_SYMS= \
+ 
+ STLIBOBJS= \
+ 	threads.o \
++	selinux.o \
+ 	init-addrinfo.o \
+ 	plugins.o \
+ 	errors.o \
+@@ -168,7 +169,7 @@ SRCS=\
+ 
+ SHLIB_EXPDEPS =
+ # Add -lm if dumping thread stats, for sqrt.
+-SHLIB_EXPLIBS= $(LIBS) $(DL_LIB)
++SHLIB_EXPLIBS= $(LIBS) $(SELINUX_LIBS) $(DL_LIB)
+ 
+ DEPLIBS=
+ 
+diff --git a/src/util/support/selinux.c b/src/util/support/selinux.c
+new file mode 100644
+index 000000000..6d41f3244
+--- /dev/null
++++ b/src/util/support/selinux.c
+@@ -0,0 +1,406 @@
++/*
++ * Copyright 2007,2008,2009,2011,2012,2013,2016 Red Hat, Inc.  All Rights Reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are met:
++ *
++ *  Redistributions of source code must retain the above copyright notice, this
++ *  list of conditions and the following disclaimer.
++ *
++ *  Redistributions in binary form must reproduce the above copyright notice,
++ *  this list of conditions and the following disclaimer in the documentation
++ *  and/or other materials provided with the distribution.
++ *
++ *  Neither the name of Red Hat, Inc. nor the names of its contributors may be
++ *  used to endorse or promote products derived from this software without
++ *  specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++ * POSSIBILITY OF SUCH DAMAGE.
++ *
++ * File-opening wrappers for creating correctly-labeled files.  So far, we can
++ * assume that this is Linux-specific, so we make many simplifying assumptions.
++ */
++
++#include "../../include/autoconf.h"
++
++#ifdef USE_SELINUX
++
++#include <k5-label.h>
++#include <k5-platform.h>
++
++#include <sys/types.h>
++#include <sys/stat.h>
++
++#include <errno.h>
++#include <fcntl.h>
++#include <limits.h>
++#include <pthread.h>
++#include <stdarg.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <unistd.h>
++
++#include <selinux/selinux.h>
++#include <selinux/context.h>
++#include <selinux/label.h>
++
++/* #define DEBUG 1 */
++static void
++debug_log(const char *fmt, ...)
++{
++#ifdef DEBUG
++    va_list ap;
++    va_start(ap, fmt);
++    if (isatty(fileno(stderr))) {
++        vfprintf(stderr, fmt, ap);
++    }
++    va_end(ap);
++#endif
++
++    return;
++}
++
++/* Mutex used to serialize use of the process-global file creation context. */
++k5_mutex_t labeled_mutex = K5_MUTEX_PARTIAL_INITIALIZER;
++
++/* Make sure we finish initializing that mutex before attempting to use it. */
++k5_once_t labeled_once = K5_ONCE_INIT;
++static void
++label_mutex_init(void)
++{
++    k5_mutex_finish_init(&labeled_mutex);
++}
++
++static struct selabel_handle *selabel_ctx;
++static time_t selabel_last_changed;
++
++MAKE_FINI_FUNCTION(cleanup_fscreatecon);
++
++static void
++cleanup_fscreatecon(void)
++{
++    if (selabel_ctx != NULL) {
++        selabel_close(selabel_ctx);
++        selabel_ctx = NULL;
++    }
++}
++
++static security_context_t
++push_fscreatecon(const char *pathname, mode_t mode)
++{
++    security_context_t previous, configuredsc, currentsc, derivedsc;
++    context_t current, derived;
++    const char *fullpath, *currentuser;
++    char *genpath;
++
++    previous = configuredsc = currentsc = derivedsc = NULL;
++    current = derived = NULL;
++    genpath = NULL;
++
++    fullpath = pathname;
++
++    if (!is_selinux_enabled()) {
++        goto fail;
++    }
++
++    if (getfscreatecon(&previous) != 0) {
++        goto fail;
++    }
++
++    /* Canonicalize pathname */
++    if (pathname[0] != '/') {
++        char *wd;
++        size_t len;
++        len = 0;
++
++        wd = getcwd(NULL, len);
++        if (wd == NULL) {
++            goto fail;
++        }
++
++        len = strlen(wd) + 1 + strlen(pathname) + 1;
++        genpath = malloc(len);
++        if (genpath == NULL) {
++            free(wd);
++            goto fail;
++        }
++
++        sprintf(genpath, "%s/%s", wd, pathname);
++        free(wd);
++        fullpath = genpath;
++    }
++
++    debug_log("Looking up context for \"%s\"(%05o).\n", fullpath, mode);
++
++    /* Check whether context file has changed under us */
++    if (selabel_ctx != NULL || selabel_last_changed == 0) {
++        const char *cpath;
++        struct stat st;
++        int i = -1;
++
++        cpath = selinux_file_context_path();
++        if (cpath == NULL || (i = stat(cpath, &st)) != 0 ||
++            st.st_mtime != selabel_last_changed) {
++            cleanup_fscreatecon();
++
++            selabel_last_changed = i ? time(NULL) : st.st_mtime;
++        }
++    }
++
++    if (selabel_ctx == NULL) {
++        selabel_ctx = selabel_open(SELABEL_CTX_FILE, NULL, 0);
++    }
++
++    if (selabel_ctx != NULL &&
++        selabel_lookup(selabel_ctx, &configuredsc, fullpath, mode) != 0) {
++        goto fail;
++    }
++
++    if (genpath != NULL) {
++        free(genpath);
++        genpath = NULL;
++    }
++
++    if (configuredsc == NULL) {
++        goto fail;
++    }
++
++    getcon(&currentsc);
++
++    /* AAAAAAAA */
++    if (currentsc != NULL) {
++        derived = context_new(configuredsc);
++
++        if (derived != NULL) {
++            current = context_new(currentsc);
++
++            if (current != NULL) {
++                currentuser = context_user_get(current);
++
++                if (currentuser != NULL) {
++                    if (context_user_set(derived,
++                                         currentuser) == 0) {
++                        derivedsc = context_str(derived);
++
++                        if (derivedsc != NULL) {
++                            freecon(configuredsc);
++                            configuredsc = strdup(derivedsc);
++                        }
++                    }
++                }
++
++                context_free(current);
++            }
++
++            context_free(derived);
++        }
++
++        freecon(currentsc);
++    }
++
++    debug_log("Setting file creation context to \"%s\".\n", configuredsc);
++    if (setfscreatecon(configuredsc) != 0) {
++        debug_log("Unable to determine current context.\n");
++        goto fail;
++    }
++
++    freecon(configuredsc);
++    return previous;
++
++fail:
++    if (previous != NULL) {
++        freecon(previous);
++    }
++    if (genpath != NULL) {
++        free(genpath);
++    }
++    if (configuredsc != NULL) {
++        freecon(configuredsc);
++    }
++
++    cleanup_fscreatecon();
++    return NULL;
++}
++
++static void
++pop_fscreatecon(security_context_t previous)
++{
++    if (!is_selinux_enabled()) {
++        return;
++    }
++
++    if (previous != NULL) {
++        debug_log("Resetting file creation context to \"%s\".\n", previous);
++    } else {
++        debug_log("Resetting file creation context to default.\n");
++    }
++
++    /* NULL resets to default */
++    setfscreatecon(previous);
++
++    if (previous != NULL) {
++        freecon(previous);
++    }
++
++    /* Need to clean this up here otherwise it leaks */
++    cleanup_fscreatecon();
++}
++
++void *
++krb5int_push_fscreatecon_for(const char *pathname)
++{
++    struct stat st;
++    void *retval;
++
++    k5_once(&labeled_once, label_mutex_init);
++    k5_mutex_lock(&labeled_mutex);
++
++    if (stat(pathname, &st) != 0) {
++        st.st_mode = S_IRUSR | S_IWUSR;
++    }
++
++    retval = push_fscreatecon(pathname, st.st_mode);
++    return retval ? retval : (void *) -1;
++}
++
++void
++krb5int_pop_fscreatecon(void *con)
++{
++    if (con != NULL) {
++        pop_fscreatecon((con == (void *) -1) ? NULL : con);
++        k5_mutex_unlock(&labeled_mutex);
++    }
++}
++
++FILE *
++krb5int_labeled_fopen(const char *path, const char *mode)
++{
++    FILE *fp;
++    int errno_save;
++    security_context_t ctx;
++
++    if ((strcmp(mode, "r") == 0) ||
++        (strcmp(mode, "rb") == 0)) {
++        return fopen(path, mode);
++    }
++
++    k5_once(&labeled_once, label_mutex_init);
++    k5_mutex_lock(&labeled_mutex);
++    ctx = push_fscreatecon(path, 0);
++
++    fp = fopen(path, mode);
++    errno_save = errno;
++
++    pop_fscreatecon(ctx);
++    k5_mutex_unlock(&labeled_mutex);
++
++    errno = errno_save;
++    return fp;
++}
++
++int
++krb5int_labeled_creat(const char *path, mode_t mode)
++{
++    int fd;
++    int errno_save;
++    security_context_t ctx;
++
++    k5_once(&labeled_once, label_mutex_init);
++    k5_mutex_lock(&labeled_mutex);
++    ctx = push_fscreatecon(path, 0);
++
++    fd = creat(path, mode);
++    errno_save = errno;
++
++    pop_fscreatecon(ctx);
++    k5_mutex_unlock(&labeled_mutex);
++
++    errno = errno_save;
++    return fd;
++}
++
++int
++krb5int_labeled_mknod(const char *path, mode_t mode, dev_t dev)
++{
++    int ret;
++    int errno_save;
++    security_context_t ctx;
++
++    k5_once(&labeled_once, label_mutex_init);
++    k5_mutex_lock(&labeled_mutex);
++    ctx = push_fscreatecon(path, mode);
++
++    ret = mknod(path, mode, dev);
++    errno_save = errno;
++
++    pop_fscreatecon(ctx);
++    k5_mutex_unlock(&labeled_mutex);
++
++    errno = errno_save;
++    return ret;
++}
++
++int
++krb5int_labeled_mkdir(const char *path, mode_t mode)
++{
++    int ret;
++    int errno_save;
++    security_context_t ctx;
++
++    k5_once(&labeled_once, label_mutex_init);
++    k5_mutex_lock(&labeled_mutex);
++    ctx = push_fscreatecon(path, S_IFDIR);
++
++    ret = mkdir(path, mode);
++    errno_save = errno;
++
++    pop_fscreatecon(ctx);
++    k5_mutex_unlock(&labeled_mutex);
++
++    errno = errno_save;
++    return ret;
++}
++
++int
++krb5int_labeled_open(const char *path, int flags, ...)
++{
++    int fd;
++    int errno_save;
++    security_context_t ctx;
++    mode_t mode;
++    va_list ap;
++
++    if ((flags & O_CREAT) == 0) {
++        return open(path, flags);
++    }
++
++    k5_once(&labeled_once, label_mutex_init);
++    k5_mutex_lock(&labeled_mutex);
++    ctx = push_fscreatecon(path, 0);
++
++    va_start(ap, flags);
++    mode = va_arg(ap, mode_t);
++    fd = open(path, flags, mode);
++    va_end(ap);
++
++    errno_save = errno;
++
++    pop_fscreatecon(ctx);
++    k5_mutex_unlock(&labeled_mutex);
++
++    errno = errno_save;
++    return fd;
++}
++
++#endif /* USE_SELINUX */
diff --git a/SOURCES/downstream-fix-debuginfo-with-y.tab.c.patch b/SOURCES/downstream-fix-debuginfo-with-y.tab.c.patch
new file mode 100644
index 0000000..fc1c8a4
--- /dev/null
+++ b/SOURCES/downstream-fix-debuginfo-with-y.tab.c.patch
@@ -0,0 +1,42 @@
+From 7f382fc40e082416e90f1e80c9fd0c91afa5baf7 Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Tue, 23 Aug 2016 16:49:25 -0400
+Subject: [PATCH] [downstream] fix debuginfo with y.tab.c
+
+We want to keep these y.tab.c files around because the debuginfo points to
+them.  It would be more elegant at the end to use symbolic links, but that
+could mess up people working in the tree on other things.
+
+Last-updated: krb5-1.9
+(cherry picked from commit f4002f246332695d8ea12ec803139fcac18fbba2)
+---
+ src/kadmin/cli/Makefile.in                 | 5 +++++
+ src/plugins/kdb/ldap/ldap_util/Makefile.in | 2 +-
+ 2 files changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/src/kadmin/cli/Makefile.in b/src/kadmin/cli/Makefile.in
+index adfea6e2b..d1327e400 100644
+--- a/src/kadmin/cli/Makefile.in
++++ b/src/kadmin/cli/Makefile.in
+@@ -37,3 +37,8 @@ clean-unix::
+ # CC_LINK is not meant for compilation and this use may break in the future.
+ datetest: getdate.c
+ 	$(CC_LINK) $(ALL_CFLAGS) -DTEST -o datetest getdate.c
++
++%.c: %.y
++	$(RM) y.tab.c $@
++	$(YACC.y) $< 
++	$(CP) y.tab.c $@
+diff --git a/src/plugins/kdb/ldap/ldap_util/Makefile.in b/src/plugins/kdb/ldap/ldap_util/Makefile.in
+index 8669c2436..a22f23c02 100644
+--- a/src/plugins/kdb/ldap/ldap_util/Makefile.in
++++ b/src/plugins/kdb/ldap/ldap_util/Makefile.in
+@@ -20,7 +20,7 @@ $(PROG): $(OBJS) $(KADMSRV_DEPLIBS) $(KRB5_BASE_DEPLIB) $(GETDATE)
+ getdate.c: $(GETDATE)
+ 	$(RM) getdate.c y.tab.c
+ 	$(YACC) $(GETDATE)
+-	$(MV) y.tab.c getdate.c
++	$(CP) y.tab.c getdate.c
+ 
+ install:
+ 	$(INSTALL_PROGRAM) $(PROG) ${DESTDIR}$(ADMIN_BINDIR)/$(PROG)
diff --git a/SOURCES/downstream-ksu-pam-integration.patch b/SOURCES/downstream-ksu-pam-integration.patch
new file mode 100644
index 0000000..d21ed37
--- /dev/null
+++ b/SOURCES/downstream-ksu-pam-integration.patch
@@ -0,0 +1,775 @@
+From 664bdd73b620f00d42e36e3888805fe0f035c8ee Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Tue, 23 Aug 2016 16:29:58 -0400
+Subject: [PATCH] [downstream] ksu pam integration
+
+Modify ksu so that it performs account and session management on behalf of
+the target user account, mimicking the action of regular su.  The default
+service name is "ksu", because on Fedora at least the configuration used
+is determined by whether or not a login shell is being opened, and so
+this may need to vary, too.  At run-time, ksu's behavior can be reset to
+the earlier, non-PAM behavior by setting "use_pam" to false in the [ksu]
+section of /etc/krb5.conf.
+
+When enabled, ksu gains a dependency on libpam.
+
+Originally RT#5939, though it's changed since then to perform the account
+and session management before dropping privileges, and to apply on top of
+changes we're proposing for how it handles cache collections.
+
+Last-updated: krb5-1.18-beta1
+(cherry picked from commit a7322a84657752c886c317a6994a9fc7a4a70ca5)
+---
+ src/aclocal.m4              |  69 +++++++
+ src/clients/ksu/Makefile.in |   8 +-
+ src/clients/ksu/main.c      |  88 +++++++-
+ src/clients/ksu/pam.c       | 389 ++++++++++++++++++++++++++++++++++++
+ src/clients/ksu/pam.h       |  57 ++++++
+ src/configure.ac            |   2 +
+ 6 files changed, 610 insertions(+), 3 deletions(-)
+ create mode 100644 src/clients/ksu/pam.c
+ create mode 100644 src/clients/ksu/pam.h
+
+diff --git a/src/aclocal.m4 b/src/aclocal.m4
+index 2394f7e33..830203683 100644
+--- a/src/aclocal.m4
++++ b/src/aclocal.m4
+@@ -1675,3 +1675,72 @@ if test "$with_ldap" = yes; then
+   OPENLDAP_PLUGIN=yes
+ fi
+ ])dnl
++dnl
++dnl
++dnl Use PAM instead of local crypt() compare for checking local passwords,
++dnl and perform PAM account, session management, and password-changing where
++dnl appropriate.
++dnl 
++AC_DEFUN(KRB5_WITH_PAM,[
++AC_ARG_WITH(pam,[AC_HELP_STRING(--with-pam,[compile with PAM support])],
++	    withpam="$withval",withpam=auto)
++AC_ARG_WITH(pam-ksu-service,[AC_HELP_STRING(--with-ksu-service,[PAM service name for ksu ["ksu"]])],
++	    withksupamservice="$withval",withksupamservice=ksu)
++old_LIBS="$LIBS"
++if test "$withpam" != no ; then
++	AC_MSG_RESULT([checking for PAM...])
++	PAM_LIBS=
++
++	AC_CHECK_HEADERS(security/pam_appl.h)
++	if test "x$ac_cv_header_security_pam_appl_h" != xyes ; then
++		if test "$withpam" = auto ; then
++			AC_MSG_RESULT([Unable to locate security/pam_appl.h.])
++			withpam=no
++		else
++			AC_MSG_ERROR([Unable to locate security/pam_appl.h.])
++		fi
++	fi
++
++	LIBS=
++	unset ac_cv_func_pam_start
++	AC_CHECK_FUNCS(putenv pam_start)
++	if test "x$ac_cv_func_pam_start" = xno ; then
++		unset ac_cv_func_pam_start
++		AC_CHECK_LIB(dl,dlopen)
++		AC_CHECK_FUNCS(pam_start)
++		if test "x$ac_cv_func_pam_start" = xno ; then
++			AC_CHECK_LIB(pam,pam_start)
++			unset ac_cv_func_pam_start
++			unset ac_cv_func_pam_getenvlist
++			AC_CHECK_FUNCS(pam_start pam_getenvlist)
++			if test "x$ac_cv_func_pam_start" = xyes ; then
++				PAM_LIBS="$LIBS"
++			else
++				if test "$withpam" = auto ; then
++					AC_MSG_RESULT([Unable to locate libpam.])
++					withpam=no
++				else
++					AC_MSG_ERROR([Unable to locate libpam.])
++				fi
++			fi
++		fi
++	fi
++	if test "$withpam" != no ; then
++		AC_MSG_NOTICE([building with PAM support])
++		AC_DEFINE(USE_PAM,1,[Define if Kerberos-aware tools should support PAM])
++		AC_DEFINE_UNQUOTED(KSU_PAM_SERVICE,"$withksupamservice",
++				   [Define to the name of the PAM service name to be used by ksu.])
++		PAM_LIBS="$LIBS"
++		NON_PAM_MAN=".\\\" "
++		PAM_MAN=
++	else
++		PAM_MAN=".\\\" "
++		NON_PAM_MAN=
++	fi
++fi
++LIBS="$old_LIBS"
++AC_SUBST(PAM_LIBS)
++AC_SUBST(PAM_MAN)
++AC_SUBST(NON_PAM_MAN)
++])dnl
++
+diff --git a/src/clients/ksu/Makefile.in b/src/clients/ksu/Makefile.in
+index 8b4edce4d..9d58f29b5 100644
+--- a/src/clients/ksu/Makefile.in
++++ b/src/clients/ksu/Makefile.in
+@@ -3,12 +3,14 @@ BUILDTOP=$(REL)..$(S)..
+ DEFINES = -DGET_TGT_VIA_PASSWD -DPRINC_LOOK_AHEAD -DCMD_PATH='"/usr/local/sbin /usr/local/bin /sbin /bin /usr/sbin /usr/bin"'
+ 
+ KSU_LIBS=@KSU_LIBS@
++PAM_LIBS=@PAM_LIBS@
+ 
+ SRCS = \
+ 	$(srcdir)/krb_auth_su.c \
+ 	$(srcdir)/ccache.c \
+ 	$(srcdir)/authorization.c \
+ 	$(srcdir)/main.c \
++	$(srcdir)/pam.c \
+ 	$(srcdir)/heuristic.c \
+ 	$(srcdir)/xmalloc.c \
+ 	$(srcdir)/setenv.c
+@@ -17,13 +19,17 @@ OBJS = \
+ 	ccache.o \
+ 	authorization.o \
+ 	main.o \
++	pam.o \
+ 	heuristic.o \
+ 	xmalloc.o @SETENVOBJ@
+ 
+ all: ksu
+ 
+ ksu: $(OBJS) $(KRB5_BASE_DEPLIBS)
+-	$(CC_LINK) -o $@ $(OBJS) $(KRB5_BASE_LIBS) $(KSU_LIBS)
++	$(CC_LINK) -o $@ $(OBJS) $(KRB5_BASE_LIBS) $(KSU_LIBS) $(PAM_LIBS)
++
++pam.o: pam.c
++	$(CC) $(ALL_CFLAGS) -c $<
+ 
+ clean:
+ 	$(RM) ksu
+diff --git a/src/clients/ksu/main.c b/src/clients/ksu/main.c
+index 57c349200..508242e0e 100644
+--- a/src/clients/ksu/main.c
++++ b/src/clients/ksu/main.c
+@@ -26,6 +26,7 @@
+  * KSU was writen by:  Ari Medvinsky, ari@isi.edu
+  */
+ 
++#include "autoconf.h"
+ #include "ksu.h"
+ #include "adm_proto.h"
+ #include <sys/types.h>
+@@ -33,6 +34,10 @@
+ #include <signal.h>
+ #include <grp.h>
+ 
++#ifdef USE_PAM
++#include "pam.h"
++#endif
++
+ /* globals */
+ char * prog_name;
+ int auth_debug =0;
+@@ -40,6 +45,7 @@ char k5login_path[MAXPATHLEN];
+ char k5users_path[MAXPATHLEN];
+ char * gb_err = NULL;
+ int quiet = 0;
++int force_fork = 0;
+ /***********/
+ 
+ #define KS_TEMPORARY_CACHE "MEMORY:_ksu"
+@@ -536,6 +542,23 @@ main (argc, argv)
+                prog_name,target_user,client_name,
+                source_user,ontty());
+ 
++#ifdef USE_PAM
++        if (appl_pam_enabled(ksu_context, "ksu")) {
++            if (appl_pam_acct_mgmt(KSU_PAM_SERVICE, 1, target_user, NULL,
++                                   NULL, source_user,
++                                   ttyname(STDERR_FILENO)) != 0) {
++                fprintf(stderr, "Access denied for %s.\n", target_user);
++                exit(1);
++            }
++            if (appl_pam_requires_chauthtok()) {
++                fprintf(stderr, "Password change required for %s.\n",
++                        target_user);
++                exit(1);
++            }
++            force_fork++;
++        }
++#endif
++
+         /* Run authorization as target.*/
+         if (krb5_seteuid(target_uid)) {
+             com_err(prog_name, errno, _("while switching to target for "
+@@ -596,6 +619,24 @@ main (argc, argv)
+ 
+             exit(1);
+         }
++#ifdef USE_PAM
++    } else {
++        /* we always do PAM account management, even for root */
++        if (appl_pam_enabled(ksu_context, "ksu")) {
++            if (appl_pam_acct_mgmt(KSU_PAM_SERVICE, 1, target_user, NULL,
++                                   NULL, source_user,
++                                   ttyname(STDERR_FILENO)) != 0) {
++                fprintf(stderr, "Access denied for %s.\n", target_user);
++                exit(1);
++            }
++            if (appl_pam_requires_chauthtok()) {
++                fprintf(stderr, "Password change required for %s.\n",
++                        target_user);
++                exit(1);
++            }
++            force_fork++;
++        }
++#endif
+     }
+ 
+     if( some_rest_copy){
+@@ -653,6 +694,30 @@ main (argc, argv)
+         exit(1);
+     }
+ 
++#ifdef USE_PAM
++    if (appl_pam_enabled(ksu_context, "ksu")) {
++        if (appl_pam_session_open() != 0) {
++            fprintf(stderr, "Error opening session for %s.\n", target_user);
++            exit(1);
++        }
++#ifdef DEBUG
++        if (auth_debug){
++            printf(" Opened PAM session.\n");
++        }
++#endif
++        if (appl_pam_cred_init()) {
++            fprintf(stderr, "Error initializing credentials for %s.\n",
++                    target_user);
++            exit(1);
++        }
++#ifdef DEBUG
++        if (auth_debug){
++            printf(" Initialized PAM credentials.\n");
++        }
++#endif
++    }
++#endif
++
+     /* set permissions */
+     if (setgid(target_pwd->pw_gid) < 0) {
+         perror("ksu: setgid");
+@@ -750,7 +815,7 @@ main (argc, argv)
+         fprintf(stderr, "program to be execed %s\n",params[0]);
+     }
+ 
+-    if( keep_target_cache ) {
++    if( keep_target_cache && !force_fork ) {
+         execv(params[0], params);
+         com_err(prog_name, errno, _("while trying to execv %s"), params[0]);
+         sweep_up(ksu_context, cc_target);
+@@ -780,16 +845,35 @@ main (argc, argv)
+             if (ret_pid == -1) {
+                 com_err(prog_name, errno, _("while calling waitpid"));
+             }
+-            sweep_up(ksu_context, cc_target);
++            if( !keep_target_cache ) {
++                sweep_up(ksu_context, cc_target);
++            }
+             exit (statusp);
+         case -1:
+             com_err(prog_name, errno, _("while trying to fork."));
+             sweep_up(ksu_context, cc_target);
+             exit (1);
+         case 0:
++#ifdef USE_PAM
++            if (appl_pam_enabled(ksu_context, "ksu")) {
++                if (appl_pam_setenv() != 0) {
++                    fprintf(stderr, "Error setting up environment for %s.\n",
++                            target_user);
++                    exit (1);
++                }
++#ifdef DEBUG
++                if (auth_debug){
++                    printf(" Set up PAM environment.\n");
++                }
++#endif
++            }
++#endif
+             execv(params[0], params);
+             com_err(prog_name, errno, _("while trying to execv %s"),
+                     params[0]);
++            if( keep_target_cache ) {
++                sweep_up(ksu_context, cc_target);
++            }
+             exit (1);
+         }
+     }
+diff --git a/src/clients/ksu/pam.c b/src/clients/ksu/pam.c
+new file mode 100644
+index 000000000..cbfe48704
+--- /dev/null
++++ b/src/clients/ksu/pam.c
+@@ -0,0 +1,389 @@
++/*
++ * src/clients/ksu/pam.c
++ *
++ * Copyright 2007,2009,2010 Red Hat, Inc.
++ *
++ * All Rights Reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are met:
++ *
++ *  Redistributions of source code must retain the above copyright notice, this
++ *  list of conditions and the following disclaimer.
++ *
++ *  Redistributions in binary form must reproduce the above copyright notice,
++ *  this list of conditions and the following disclaimer in the documentation
++ *  and/or other materials provided with the distribution.
++ *
++ *  Neither the name of Red Hat, Inc. nor the names of its contributors may be
++ *  used to endorse or promote products derived from this software without
++ *  specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++ * POSSIBILITY OF SUCH DAMAGE.
++ * 
++ * Convenience wrappers for using PAM.
++ */
++
++#include "autoconf.h"
++#ifdef USE_PAM
++#include <sys/types.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <unistd.h>
++#include "k5-int.h"
++#include "pam.h"
++
++#ifndef MAXPWSIZE
++#define MAXPWSIZE 128
++#endif
++
++static int appl_pam_started;
++static pid_t appl_pam_starter = -1;
++static int appl_pam_session_opened;
++static int appl_pam_creds_initialized;
++static int appl_pam_pwchange_required;
++static pam_handle_t *appl_pamh;
++static struct pam_conv appl_pam_conv;
++static char *appl_pam_user;
++struct appl_pam_non_interactive_args {
++	const char *user;
++	const char *password;
++};
++
++int
++appl_pam_enabled(krb5_context context, const char *section)
++{
++	int enabled = 1;
++	if ((context != NULL) && (context->profile != NULL)) {
++		if (profile_get_boolean(context->profile,
++					section,
++					USE_PAM_CONFIGURATION_KEYWORD,
++					NULL,
++					enabled, &enabled) != 0) {
++			enabled = 1;
++		}
++	}
++	return enabled;
++}
++
++void
++appl_pam_cleanup(void)
++{
++	if (getpid() != appl_pam_starter) {
++		return;
++	}
++#ifdef DEBUG
++	printf("Called to clean up PAM.\n");
++#endif
++	if (appl_pam_creds_initialized) {
++#ifdef DEBUG
++		printf("Deleting PAM credentials.\n");
++#endif
++		pam_setcred(appl_pamh, PAM_DELETE_CRED);
++		appl_pam_creds_initialized = 0;
++	}
++	if (appl_pam_session_opened) {
++#ifdef DEBUG
++		printf("Closing PAM session.\n");
++#endif
++		pam_close_session(appl_pamh, 0);
++		appl_pam_session_opened = 0;
++	}
++	appl_pam_pwchange_required = 0;
++	if (appl_pam_started) {
++#ifdef DEBUG
++		printf("Shutting down PAM.\n");
++#endif
++		pam_end(appl_pamh, 0);
++		appl_pam_started = 0;
++		appl_pam_starter = -1;
++		free(appl_pam_user);
++		appl_pam_user = NULL;
++	}
++}
++static int
++appl_pam_interactive_converse(int num_msg, const struct pam_message **msg,
++			      struct pam_response **presp, void *appdata_ptr)
++{
++	const struct pam_message *message;
++	struct pam_response *resp;
++	int i, code;
++	char *pwstring, pwbuf[MAXPWSIZE];
++	unsigned int pwsize;
++	resp = malloc(sizeof(struct pam_response) * num_msg);
++	if (resp == NULL) {
++		return PAM_BUF_ERR;
++	}
++	memset(resp, 0, sizeof(struct pam_response) * num_msg);
++	code = PAM_SUCCESS;
++	for (i = 0; i < num_msg; i++) {
++		message = &(msg[0][i]); /* XXX */
++		message = msg[i]; /* XXX */
++		pwstring = NULL;
++		switch (message->msg_style) {
++		case PAM_TEXT_INFO:
++		case PAM_ERROR_MSG:
++			printf("[%s]\n", message->msg ? message->msg : "");
++			fflush(stdout);
++			resp[i].resp = NULL;
++			resp[i].resp_retcode = PAM_SUCCESS;
++			break;
++		case PAM_PROMPT_ECHO_ON:
++		case PAM_PROMPT_ECHO_OFF:
++			if (message->msg_style == PAM_PROMPT_ECHO_ON) {
++				if (fgets(pwbuf, sizeof(pwbuf),
++					  stdin) != NULL) {
++					pwbuf[strcspn(pwbuf, "\r\n")] = '\0';
++					pwstring = pwbuf;
++				}
++			} else {
++				pwstring = getpass(message->msg ?
++						   message->msg :
++						   "");
++			}
++			if ((pwstring != NULL) && (pwstring[0] != '\0')) {
++				pwsize = strlen(pwstring);
++				resp[i].resp = malloc(pwsize + 1);
++				if (resp[i].resp == NULL) {
++					resp[i].resp_retcode = PAM_BUF_ERR;
++				} else {
++					memcpy(resp[i].resp, pwstring, pwsize);
++					resp[i].resp[pwsize] = '\0';
++					resp[i].resp_retcode = PAM_SUCCESS;
++				}
++			} else {
++				resp[i].resp_retcode = PAM_CONV_ERR;
++				code = PAM_CONV_ERR;
++			}
++			break;
++		default:
++			break;
++		}
++	}
++	*presp = resp;
++	return code;
++}
++static int
++appl_pam_non_interactive_converse(int num_msg,
++				  const struct pam_message **msg,
++				  struct pam_response **presp,
++				  void *appdata_ptr)
++{
++	const struct pam_message *message;
++	struct pam_response *resp;
++	int i, code;
++	unsigned int pwsize;
++	struct appl_pam_non_interactive_args *args;
++	const char *pwstring;
++	resp = malloc(sizeof(struct pam_response) * num_msg);
++	if (resp == NULL) {
++		return PAM_BUF_ERR;
++	}
++	args = appdata_ptr;
++	memset(resp, 0, sizeof(struct pam_response) * num_msg);
++	code = PAM_SUCCESS;
++	for (i = 0; i < num_msg; i++) {
++		message = &((*msg)[i]);
++		message = msg[i];
++		pwstring = NULL;
++		switch (message->msg_style) {
++		case PAM_TEXT_INFO:
++		case PAM_ERROR_MSG:
++			break;
++		case PAM_PROMPT_ECHO_ON:
++		case PAM_PROMPT_ECHO_OFF:
++			if (message->msg_style == PAM_PROMPT_ECHO_ON) {
++				/* assume "user" */
++				pwstring = args->user;
++			} else {
++				/* assume "password" */
++				pwstring = args->password;
++			}
++			if ((pwstring != NULL) && (pwstring[0] != '\0')) {
++				pwsize = strlen(pwstring);
++				resp[i].resp = malloc(pwsize + 1);
++				if (resp[i].resp == NULL) {
++					resp[i].resp_retcode = PAM_BUF_ERR;
++				} else {
++					memcpy(resp[i].resp, pwstring, pwsize);
++					resp[i].resp[pwsize] = '\0';
++					resp[i].resp_retcode = PAM_SUCCESS;
++				}
++			} else {
++				resp[i].resp_retcode = PAM_CONV_ERR;
++				code = PAM_CONV_ERR;
++			}
++			break;
++		default:
++			break;
++		}
++	}
++	*presp = resp;
++	return code;
++}
++static int
++appl_pam_start(const char *service, int interactive,
++	       const char *login_username,
++	       const char *non_interactive_password,
++	       const char *hostname,
++	       const char *ruser,
++	       const char *tty)
++{
++	static int exit_handler_registered;
++	static struct appl_pam_non_interactive_args args;
++	int ret = 0;
++	if (appl_pam_started &&
++	    (strcmp(login_username, appl_pam_user) != 0)) {
++		appl_pam_cleanup();
++		appl_pam_user = NULL;
++	}
++	if (!appl_pam_started) {
++#ifdef DEBUG
++		printf("Starting PAM up (service=\"%s\",user=\"%s\").\n",
++		       service, login_username);
++#endif
++		memset(&appl_pam_conv, 0, sizeof(appl_pam_conv));
++		appl_pam_conv.conv = interactive ?
++				     &appl_pam_interactive_converse :
++				     &appl_pam_non_interactive_converse;
++		memset(&args, 0, sizeof(args));
++		args.user = strdup(login_username);
++		args.password = non_interactive_password ?
++				strdup(non_interactive_password) :
++				NULL;
++		appl_pam_conv.appdata_ptr = &args;
++		ret = pam_start(service, login_username,
++				&appl_pam_conv, &appl_pamh);
++		if (ret == 0) {
++			if (hostname != NULL) {
++#ifdef DEBUG
++				printf("Setting PAM_RHOST to \"%s\".\n", hostname);
++#endif
++				pam_set_item(appl_pamh, PAM_RHOST, hostname);
++			}
++			if (ruser != NULL) {
++#ifdef DEBUG
++				printf("Setting PAM_RUSER to \"%s\".\n", ruser);
++#endif
++				pam_set_item(appl_pamh, PAM_RUSER, ruser);
++			}
++			if (tty != NULL) {
++#ifdef DEBUG
++				printf("Setting PAM_TTY to \"%s\".\n", tty);
++#endif
++				pam_set_item(appl_pamh, PAM_TTY, tty);
++			}
++			if (!exit_handler_registered &&
++			    (atexit(appl_pam_cleanup) != 0)) {
++				pam_end(appl_pamh, 0);
++				appl_pamh = NULL;
++				ret = -1;
++			} else {
++				appl_pam_started = 1;
++				appl_pam_starter = getpid();
++				appl_pam_user = strdup(login_username);
++				exit_handler_registered = 1;
++			}
++		}
++	}
++	return ret;
++}
++int
++appl_pam_acct_mgmt(const char *service, int interactive,
++		   const char *login_username,
++		   const char *non_interactive_password,
++		   const char *hostname,
++		   const char *ruser,
++		   const char *tty)
++{
++	int ret;
++	appl_pam_pwchange_required = 0;
++	ret = appl_pam_start(service, interactive, login_username,
++			     non_interactive_password, hostname, ruser, tty);
++	if (ret == 0) {
++#ifdef DEBUG
++		printf("Calling pam_acct_mgmt().\n");
++#endif
++		ret = pam_acct_mgmt(appl_pamh, 0);
++		switch (ret) {
++		case PAM_IGNORE:
++			ret = 0;
++			break;
++		case PAM_NEW_AUTHTOK_REQD:
++			appl_pam_pwchange_required = 1;
++			ret = 0;
++			break;
++		default:
++			break;
++		}
++	}
++	return ret;
++}
++int
++appl_pam_requires_chauthtok(void)
++{
++	return appl_pam_pwchange_required;
++}
++int
++appl_pam_session_open(void)
++{
++	int ret = 0;
++	if (appl_pam_started) {
++#ifdef DEBUG
++		printf("Opening PAM session.\n");
++#endif
++		ret = pam_open_session(appl_pamh, 0);
++		if (ret == 0) {
++			appl_pam_session_opened = 1;
++		}
++	}
++	return ret;
++}
++int
++appl_pam_setenv(void)
++{
++	int ret = 0;
++#ifdef HAVE_PAM_GETENVLIST
++#ifdef HAVE_PUTENV
++	int i;
++	char **list;
++	if (appl_pam_started) {
++		list = pam_getenvlist(appl_pamh);
++		for (i = 0; ((list != NULL) && (list[i] != NULL)); i++) {
++#ifdef DEBUG
++			printf("Setting \"%s\" in environment.\n", list[i]);
++#endif
++			putenv(list[i]);
++		}
++	}
++#endif
++#endif
++	return ret;
++}
++int
++appl_pam_cred_init(void)
++{
++	int ret = 0;
++	if (appl_pam_started) {
++#ifdef DEBUG
++		printf("Initializing PAM credentials.\n");
++#endif
++		ret = pam_setcred(appl_pamh, PAM_ESTABLISH_CRED);
++		if (ret == 0) {
++			appl_pam_creds_initialized = 1;
++		}
++	}
++	return ret;
++}
++#endif
+diff --git a/src/clients/ksu/pam.h b/src/clients/ksu/pam.h
+new file mode 100644
+index 000000000..0ab76569c
+--- /dev/null
++++ b/src/clients/ksu/pam.h
+@@ -0,0 +1,57 @@
++/*
++ * src/clients/ksu/pam.h
++ *
++ * Copyright 2007,2009,2010 Red Hat, Inc.
++ *
++ * All Rights Reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are met:
++ *
++ *  Redistributions of source code must retain the above copyright notice, this
++ *  list of conditions and the following disclaimer.
++ *
++ *  Redistributions in binary form must reproduce the above copyright notice,
++ *  this list of conditions and the following disclaimer in the documentation
++ *  and/or other materials provided with the distribution.
++ *
++ *  Neither the name of Red Hat, Inc. nor the names of its contributors may be
++ *  used to endorse or promote products derived from this software without
++ *  specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++ * POSSIBILITY OF SUCH DAMAGE.
++ * 
++ * Convenience wrappers for using PAM.
++ */
++
++#include <krb5.h>
++#ifdef HAVE_SECURITY_PAM_APPL_H
++#include <security/pam_appl.h>
++#endif
++
++#define USE_PAM_CONFIGURATION_KEYWORD "use_pam"
++
++#ifdef USE_PAM
++int appl_pam_enabled(krb5_context context, const char *section);
++int appl_pam_acct_mgmt(const char *service, int interactive,
++		       const char *local_username,
++		       const char *non_interactive_password,
++		       const char *hostname,
++		       const char *ruser,
++		       const char *tty);
++int appl_pam_requires_chauthtok(void);
++int appl_pam_session_open(void);
++int appl_pam_setenv(void);
++int appl_pam_cred_init(void);
++void appl_pam_cleanup(void);
++#endif
+diff --git a/src/configure.ac b/src/configure.ac
+index 234f4281c..d1f576124 100644
+--- a/src/configure.ac
++++ b/src/configure.ac
+@@ -1390,6 +1390,8 @@ AC_SUBST([VERTO_VERSION])
+ 
+ AC_PATH_PROG(GROFF, groff)
+ 
++KRB5_WITH_PAM
++
+ # Make localedir work in autoconf 2.5x.
+ if test "${localedir+set}" != set; then
+     localedir='$(datadir)/locale'
diff --git a/SOURCES/downstream-netlib-and-dns.patch b/SOURCES/downstream-netlib-and-dns.patch
new file mode 100644
index 0000000..b966083
--- /dev/null
+++ b/SOURCES/downstream-netlib-and-dns.patch
@@ -0,0 +1,25 @@
+From 0a164c9c53a6f8ce20cfe5c6ef94ae5a2c2e9e28 Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Tue, 23 Aug 2016 16:46:21 -0400
+Subject: [PATCH] [downstream] netlib and dns
+
+We want to be able to use --with-netlib and --enable-dns at the same time.
+
+Last-updated: krb5-1.3.1
+(cherry picked from commit 355dd481511af4d517ee540854f95a6fb12116a9)
+---
+ src/aclocal.m4 | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/src/aclocal.m4 b/src/aclocal.m4
+index 6796fec53..c4358988a 100644
+--- a/src/aclocal.m4
++++ b/src/aclocal.m4
+@@ -724,6 +724,7 @@ AC_HELP_STRING([--with-netlib=LIBS], use user defined resolver library),
+ 	LIBS="$LIBS $withval"
+ 	AC_MSG_RESULT("netlib will use \'$withval\'")
+   fi
++  KRB5_AC_ENABLE_DNS
+ ],dnl
+ [AC_LIBRARY_NET]
+ )])dnl
diff --git a/SOURCES/kdc.conf b/SOURCES/kdc.conf
index b2e5e9b..f21c761 100644
--- a/SOURCES/kdc.conf
+++ b/SOURCES/kdc.conf
@@ -9,5 +9,5 @@ EXAMPLE.COM = {
      acl_file = /var/kerberos/krb5kdc/kadm5.acl
      dict_file = /usr/share/dict/words
      admin_keytab = /var/kerberos/krb5kdc/kadm5.keytab
-     supported_enctypes = aes256-cts:normal aes128-cts:normal des3-hmac-sha1:normal arcfour-hmac:normal camellia256-cts:normal camellia128-cts:normal
+     supported_enctypes = aes256-cts:normal aes128-cts:normal arcfour-hmac:normal camellia256-cts:normal camellia128-cts:normal
 }
diff --git a/SOURCES/krb5-1.11-kpasswdtest.patch b/SOURCES/krb5-1.11-kpasswdtest.patch
deleted file mode 100644
index 7da7384..0000000
--- a/SOURCES/krb5-1.11-kpasswdtest.patch
+++ /dev/null
@@ -1,21 +0,0 @@
-From 174fddfa0c7d0d5c0f12d1531bc791865b630596 Mon Sep 17 00:00:00 2001
-From: Robbie Harwood <rharwood@redhat.com>
-Date: Tue, 23 Aug 2016 16:52:01 -0400
-Subject: [PATCH] krb5-1.11-kpasswdtest.patch
-
----
- src/kadmin/testing/proto/krb5.conf.proto | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/src/kadmin/testing/proto/krb5.conf.proto b/src/kadmin/testing/proto/krb5.conf.proto
-index 00c442978..9c4bc1de7 100644
---- a/src/kadmin/testing/proto/krb5.conf.proto
-+++ b/src/kadmin/testing/proto/krb5.conf.proto
-@@ -9,6 +9,7 @@
- 	__REALM__ = {
- 		kdc = __KDCHOST__:1750
- 		admin_server = __KDCHOST__:1751
-+		kpasswd_server = __KDCHOST__:1752
- 		database_module = foobar_db2_module_blah
- 	}
- 
diff --git a/SOURCES/krb5-1.11-run_user_0.patch b/SOURCES/krb5-1.11-run_user_0.patch
deleted file mode 100644
index 7a38d43..0000000
--- a/SOURCES/krb5-1.11-run_user_0.patch
+++ /dev/null
@@ -1,44 +0,0 @@
-From f19ee759c49fac6477ef77eb4a0be41118add1f5 Mon Sep 17 00:00:00 2001
-From: Robbie Harwood <rharwood@redhat.com>
-Date: Tue, 23 Aug 2016 16:49:57 -0400
-Subject: [PATCH] krb5-1.11-run_user_0.patch
-
-A hack: if we're looking at creating a ccache directory directly below
-the /run/user/0 directory, and /run/user/0 doesn't exist, try to create
-it, too.
----
- src/lib/krb5/ccache/cc_dir.c | 14 ++++++++++++++
- 1 file changed, 14 insertions(+)
-
-diff --git a/src/lib/krb5/ccache/cc_dir.c b/src/lib/krb5/ccache/cc_dir.c
-index 73f0fe62d..4850c0d07 100644
---- a/src/lib/krb5/ccache/cc_dir.c
-+++ b/src/lib/krb5/ccache/cc_dir.c
-@@ -61,6 +61,8 @@
- 
- #include <dirent.h>
- 
-+#define ROOT_SPECIAL_DCC_PARENT "/run/user/0"
-+
- extern const krb5_cc_ops krb5_dcc_ops;
- extern const krb5_cc_ops krb5_fcc_ops;
- 
-@@ -237,6 +239,18 @@ verify_dir(krb5_context context, const char *dirname)
- 
-     if (stat(dirname, &st) < 0) {
-         if (errno == ENOENT) {
-+            if (strncmp(dirname, ROOT_SPECIAL_DCC_PARENT "/",
-+                        sizeof(ROOT_SPECIAL_DCC_PARENT)) == 0 &&
-+                stat(ROOT_SPECIAL_DCC_PARENT, &st) < 0 &&
-+                errno == ENOENT) {
-+#ifdef USE_SELINUX
-+                selabel = krb5int_push_fscreatecon_for(ROOT_SPECIAL_DCC_PARENT);
-+#endif
-+                status = mkdir(ROOT_SPECIAL_DCC_PARENT, S_IRWXU);
-+#ifdef USE_SELINUX
-+                krb5int_pop_fscreatecon(selabel);
-+#endif
-+            }
- #ifdef USE_SELINUX
-             selabel = krb5int_push_fscreatecon_for(dirname);
- #endif
diff --git a/SOURCES/krb5-1.12-api.patch b/SOURCES/krb5-1.12-api.patch
deleted file mode 100644
index 4e42414..0000000
--- a/SOURCES/krb5-1.12-api.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-From 3bac1a71756c634fe6b8cb3858ee9df87b1a660d Mon Sep 17 00:00:00 2001
-From: Robbie Harwood <rharwood@redhat.com>
-Date: Tue, 23 Aug 2016 16:47:00 -0400
-Subject: [PATCH] krb5-1.12-api.patch
-
-Reference docs don't define what happens if you call krb5_realm_compare() with
-malformed krb5_principal structures.  Define a behavior which keeps it from
-crashing if applications don't check ahead of time.
----
- src/lib/krb5/krb/princ_comp.c | 7 +++++++
- 1 file changed, 7 insertions(+)
-
-diff --git a/src/lib/krb5/krb/princ_comp.c b/src/lib/krb5/krb/princ_comp.c
-index a6936107d..0ed78833b 100644
---- a/src/lib/krb5/krb/princ_comp.c
-+++ b/src/lib/krb5/krb/princ_comp.c
-@@ -36,6 +36,10 @@ realm_compare_flags(krb5_context context,
-     const krb5_data *realm1 = &princ1->realm;
-     const krb5_data *realm2 = &princ2->realm;
- 
-+    if (princ1 == NULL || princ2 == NULL)
-+        return FALSE;
-+    if (realm1 == NULL || realm2 == NULL)
-+        return FALSE;
-     if (realm1->length != realm2->length)
-         return FALSE;
-     if (realm1->length == 0)
-@@ -88,6 +92,9 @@ krb5_principal_compare_flags(krb5_context context,
-     krb5_principal upn2 = NULL;
-     krb5_boolean ret = FALSE;
- 
-+    if (princ1 == NULL || princ2 == NULL)
-+        return FALSE;
-+
-     if (flags & KRB5_PRINCIPAL_COMPARE_ENTERPRISE) {
-         /* Treat UPNs as if they were real principals */
-         if (princ1->type == KRB5_NT_ENTERPRISE_PRINCIPAL) {
diff --git a/SOURCES/krb5-1.12-ksu-path.patch b/SOURCES/krb5-1.12-ksu-path.patch
deleted file mode 100644
index 25b805a..0000000
--- a/SOURCES/krb5-1.12-ksu-path.patch
+++ /dev/null
@@ -1,22 +0,0 @@
-From ef8aa0a18c2bd2f960942380202a5fa992e2c7b3 Mon Sep 17 00:00:00 2001
-From: Robbie Harwood <rharwood@redhat.com>
-Date: Tue, 23 Aug 2016 16:32:09 -0400
-Subject: [PATCH] krb5-1.12-ksu-path.patch
-
-Set the default PATH to the one set by login.
----
- src/clients/ksu/Makefile.in | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/clients/ksu/Makefile.in b/src/clients/ksu/Makefile.in
-index 5755bb58a..9d58f29b5 100644
---- a/src/clients/ksu/Makefile.in
-+++ b/src/clients/ksu/Makefile.in
-@@ -1,6 +1,6 @@
- mydir=clients$(S)ksu
- BUILDTOP=$(REL)..$(S)..
--DEFINES = -DGET_TGT_VIA_PASSWD -DPRINC_LOOK_AHEAD -DCMD_PATH='"/bin /local/bin"'
-+DEFINES = -DGET_TGT_VIA_PASSWD -DPRINC_LOOK_AHEAD -DCMD_PATH='"/usr/local/sbin /usr/local/bin /sbin /bin /usr/sbin /usr/bin"'
- 
- KSU_LIBS=@KSU_LIBS@
- PAM_LIBS=@PAM_LIBS@
diff --git a/SOURCES/krb5-1.12-ktany.patch b/SOURCES/krb5-1.12-ktany.patch
deleted file mode 100644
index 26d36df..0000000
--- a/SOURCES/krb5-1.12-ktany.patch
+++ /dev/null
@@ -1,366 +0,0 @@
-From 2ca8d242b1cac8abdb35bf0068e5d78300e07c3c Mon Sep 17 00:00:00 2001
-From: Robbie Harwood <rharwood@redhat.com>
-Date: Tue, 23 Aug 2016 16:33:53 -0400
-Subject: [PATCH] krb5-1.12-ktany.patch
-
-Adds an "ANY" keytab type which is a list of other keytab locations to search
-when searching for a specific entry.  When iterated through, it only presents
-the contents of the first keytab.
----
- src/lib/krb5/keytab/Makefile.in |   3 +
- src/lib/krb5/keytab/kt_any.c    | 292 ++++++++++++++++++++++++++++++++
- src/lib/krb5/keytab/ktbase.c    |   7 +-
- 3 files changed, 301 insertions(+), 1 deletion(-)
- create mode 100644 src/lib/krb5/keytab/kt_any.c
-
-diff --git a/src/lib/krb5/keytab/Makefile.in b/src/lib/krb5/keytab/Makefile.in
-index 2a8fceb00..ffd179fb2 100644
---- a/src/lib/krb5/keytab/Makefile.in
-+++ b/src/lib/krb5/keytab/Makefile.in
-@@ -12,6 +12,7 @@ STLIBOBJS= \
- 	ktfr_entry.o	\
- 	ktremove.o	\
- 	ktfns.o		\
-+	kt_any.o	\
- 	kt_file.o	\
- 	kt_memory.o	\
- 	kt_srvtab.o	\
-@@ -24,6 +25,7 @@ OBJS=	\
- 	$(OUTPRE)ktfr_entry.$(OBJEXT)	\
- 	$(OUTPRE)ktremove.$(OBJEXT)	\
- 	$(OUTPRE)ktfns.$(OBJEXT)	\
-+	$(OUTPRE)kt_any.$(OBJEXT)	\
- 	$(OUTPRE)kt_file.$(OBJEXT)	\
- 	$(OUTPRE)kt_memory.$(OBJEXT)	\
- 	$(OUTPRE)kt_srvtab.$(OBJEXT)	\
-@@ -36,6 +38,7 @@ SRCS=	\
- 	$(srcdir)/ktfr_entry.c	\
- 	$(srcdir)/ktremove.c	\
- 	$(srcdir)/ktfns.c	\
-+	$(srcdir)/kt_any.c	\
- 	$(srcdir)/kt_file.c	\
- 	$(srcdir)/kt_memory.c	\
- 	$(srcdir)/kt_srvtab.c	\
-diff --git a/src/lib/krb5/keytab/kt_any.c b/src/lib/krb5/keytab/kt_any.c
-new file mode 100644
-index 000000000..1b9b7765b
---- /dev/null
-+++ b/src/lib/krb5/keytab/kt_any.c
-@@ -0,0 +1,292 @@
-+/*
-+ * lib/krb5/keytab/kt_any.c
-+ *
-+ * Copyright 1998, 1999 by the Massachusetts Institute of Technology.
-+ * All Rights Reserved.
-+ *
-+ * Export of this software from the United States of America may
-+ *   require a specific license from the United States Government.
-+ *   It is the responsibility of any person or organization contemplating
-+ *   export to obtain such a license before exporting.
-+ * 
-+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
-+ * distribute this software and its documentation for any purpose and
-+ * without fee is hereby granted, provided that the above copyright
-+ * notice appear in all copies and that both that copyright notice and
-+ * this permission notice appear in supporting documentation, and that
-+ * the name of M.I.T. not be used in advertising or publicity pertaining
-+ * to distribution of the software without specific, written prior
-+ * permission.  M.I.T. makes no representations about the suitability of
-+ * this software for any purpose.  It is provided "as is" without express
-+ * or implied warranty.
-+ * 
-+ *
-+ * krb5_kta_ops
-+ */
-+
-+#include "k5-int.h"
-+
-+typedef struct _krb5_ktany_data {
-+    char *name;
-+    krb5_keytab *choices;
-+    int nchoices;
-+} krb5_ktany_data;
-+
-+typedef struct _krb5_ktany_cursor_data {
-+    int which;
-+    krb5_kt_cursor cursor;
-+} krb5_ktany_cursor_data;
-+
-+static krb5_error_code krb5_ktany_resolve
-+	          (krb5_context,
-+		   const char *,
-+		   krb5_keytab *);
-+static krb5_error_code krb5_ktany_get_name
-+	          (krb5_context context,
-+		   krb5_keytab id,
-+		   char *name,
-+		   unsigned int len);
-+static krb5_error_code krb5_ktany_close
-+	          (krb5_context context,
-+		   krb5_keytab id);
-+static krb5_error_code krb5_ktany_get_entry
-+	          (krb5_context context,
-+		   krb5_keytab id,
-+		   krb5_const_principal principal,
-+		   krb5_kvno kvno,
-+		   krb5_enctype enctype,
-+		   krb5_keytab_entry *entry);
-+static krb5_error_code krb5_ktany_start_seq_get
-+	          (krb5_context context,
-+		   krb5_keytab id,
-+		   krb5_kt_cursor *cursorp);
-+static krb5_error_code krb5_ktany_next_entry
-+	          (krb5_context context,
-+		   krb5_keytab id,
-+		   krb5_keytab_entry *entry,
-+		   krb5_kt_cursor *cursor);
-+static krb5_error_code krb5_ktany_end_seq_get
-+	          (krb5_context context,
-+		   krb5_keytab id,
-+		   krb5_kt_cursor *cursor);
-+static void cleanup
-+	          (krb5_context context,
-+		   krb5_ktany_data *data,
-+		   int nchoices);
-+
-+struct _krb5_kt_ops krb5_kta_ops = {
-+    0,
-+    "ANY", 	/* Prefix -- this string should not appear anywhere else! */
-+    krb5_ktany_resolve,
-+    krb5_ktany_get_name,
-+    krb5_ktany_close,
-+    krb5_ktany_get_entry,
-+    krb5_ktany_start_seq_get,
-+    krb5_ktany_next_entry,
-+    krb5_ktany_end_seq_get,
-+    NULL,
-+    NULL,
-+    NULL,
-+};
-+
-+static krb5_error_code
-+krb5_ktany_resolve(context, name, id)
-+    krb5_context context;
-+    const char *name;
-+    krb5_keytab *id;
-+{
-+    const char *p, *q;
-+    char *copy;
-+    krb5_error_code kerror;
-+    krb5_ktany_data *data;
-+    int i;
-+
-+    /* Allocate space for our data and remember a copy of the name. */
-+    if ((data = (krb5_ktany_data *)malloc(sizeof(krb5_ktany_data))) == NULL)
-+	return(ENOMEM);
-+    if ((data->name = (char *)malloc(strlen(name) + 1)) == NULL) {
-+	free(data);
-+	return(ENOMEM);
-+    }
-+    strcpy(data->name, name);
-+
-+    /* Count the number of choices and allocate memory for them. */
-+    data->nchoices = 1;
-+    for (p = name; (q = strchr(p, ',')) != NULL; p = q + 1)
-+	data->nchoices++;
-+    if ((data->choices = (krb5_keytab *)
-+	 malloc(data->nchoices * sizeof(krb5_keytab))) == NULL) {
-+	free(data->name);
-+	free(data);
-+	return(ENOMEM);
-+    }
-+
-+    /* Resolve each of the choices. */
-+    i = 0;
-+    for (p = name; (q = strchr(p, ',')) != NULL; p = q + 1) {
-+	/* Make a copy of the choice name so we can terminate it. */
-+	if ((copy = (char *)malloc(q - p + 1)) == NULL) {
-+	    cleanup(context, data, i);
-+	    return(ENOMEM);
-+	}
-+	memcpy(copy, p, q - p);
-+	copy[q - p] = 0;
-+
-+	/* Try resolving the choice name. */
-+	kerror = krb5_kt_resolve(context, copy, &data->choices[i]);
-+	free(copy);
-+	if (kerror) {
-+	    cleanup(context, data, i);
-+	    return(kerror);
-+	}
-+	i++;
-+    }
-+    if ((kerror = krb5_kt_resolve(context, p, &data->choices[i]))) {
-+	cleanup(context, data, i);
-+	return(kerror);
-+    }
-+
-+    /* Allocate and fill in an ID for the caller. */
-+    if ((*id = (krb5_keytab)malloc(sizeof(**id))) == NULL) {
-+	cleanup(context, data, i);
-+	return(ENOMEM);
-+    }
-+    (*id)->ops = &krb5_kta_ops;
-+    (*id)->data = (krb5_pointer)data;
-+    (*id)->magic = KV5M_KEYTAB;
-+
-+    return(0);
-+}
-+
-+static krb5_error_code
-+krb5_ktany_get_name(context, id, name, len)
-+    krb5_context context;
-+    krb5_keytab id;
-+    char *name;
-+    unsigned int len;
-+{
-+    krb5_ktany_data *data = (krb5_ktany_data *)id->data;
-+
-+    if (len < strlen(data->name) + 1)
-+	return(KRB5_KT_NAME_TOOLONG);
-+    strcpy(name, data->name);
-+    return(0);
-+}
-+
-+static krb5_error_code
-+krb5_ktany_close(context, id)
-+    krb5_context context;
-+    krb5_keytab id;
-+{
-+    krb5_ktany_data *data = (krb5_ktany_data *)id->data;
-+
-+    cleanup(context, data, data->nchoices);
-+    id->ops = 0;
-+    free(id);
-+    return(0);
-+}
-+
-+static krb5_error_code
-+krb5_ktany_get_entry(context, id, principal, kvno, enctype, entry)
-+    krb5_context context;
-+    krb5_keytab id;
-+    krb5_const_principal principal;
-+    krb5_kvno kvno;
-+    krb5_enctype enctype;
-+    krb5_keytab_entry *entry;
-+{
-+    krb5_ktany_data *data = (krb5_ktany_data *)id->data;
-+    krb5_error_code kerror = KRB5_KT_NOTFOUND;
-+    int i;
-+
-+    for (i = 0; i < data->nchoices; i++) {
-+	if ((kerror = krb5_kt_get_entry(context, data->choices[i], principal,
-+					kvno, enctype, entry)) != ENOENT)
-+	    return kerror;
-+    }
-+    return kerror;
-+}
-+
-+static krb5_error_code
-+krb5_ktany_start_seq_get(context, id, cursorp)
-+    krb5_context context;
-+    krb5_keytab id;
-+    krb5_kt_cursor *cursorp;
-+{
-+    krb5_ktany_data *data = (krb5_ktany_data *)id->data;
-+    krb5_ktany_cursor_data *cdata;
-+    krb5_error_code kerror = ENOENT;
-+    int i;
-+
-+    if ((cdata = (krb5_ktany_cursor_data *)
-+	 malloc(sizeof(krb5_ktany_cursor_data))) == NULL)
-+	return(ENOMEM);
-+
-+    /* Find a choice which can handle the serialization request. */
-+    for (i = 0; i < data->nchoices; i++) {
-+	if ((kerror = krb5_kt_start_seq_get(context, data->choices[i],
-+					    &cdata->cursor)) == 0)
-+	    break;
-+	else if (kerror != ENOENT) {
-+	    free(cdata);
-+	    return(kerror);
-+	}
-+    }
-+
-+    if (i == data->nchoices) {
-+	/* Everyone returned ENOENT, so no go. */
-+	free(cdata);
-+	return(kerror);
-+    }
-+
-+    cdata->which = i;
-+    *cursorp = (krb5_kt_cursor)cdata;
-+    return(0);
-+}
-+
-+static krb5_error_code
-+krb5_ktany_next_entry(context, id, entry, cursor)
-+    krb5_context context;
-+    krb5_keytab id;
-+    krb5_keytab_entry *entry;
-+    krb5_kt_cursor *cursor;
-+{
-+    krb5_ktany_data *data = (krb5_ktany_data *)id->data;
-+    krb5_ktany_cursor_data *cdata = (krb5_ktany_cursor_data *)*cursor;
-+    krb5_keytab choice_id;
-+
-+    choice_id = data->choices[cdata->which];
-+    return(krb5_kt_next_entry(context, choice_id, entry, &cdata->cursor));
-+}
-+
-+static krb5_error_code
-+krb5_ktany_end_seq_get(context, id, cursor)
-+    krb5_context context;
-+    krb5_keytab id;
-+    krb5_kt_cursor *cursor;
-+{
-+    krb5_ktany_data *data = (krb5_ktany_data *)id->data;
-+    krb5_ktany_cursor_data *cdata = (krb5_ktany_cursor_data *)*cursor;
-+    krb5_keytab choice_id;
-+    krb5_error_code kerror;
-+
-+    choice_id = data->choices[cdata->which];
-+    kerror = krb5_kt_end_seq_get(context, choice_id, &cdata->cursor);
-+    free(cdata);
-+    return(kerror);
-+}
-+
-+static void
-+cleanup(context, data, nchoices)
-+    krb5_context context;
-+    krb5_ktany_data *data;
-+    int nchoices;
-+{
-+    int i;
-+
-+    free(data->name);
-+    for (i = 0; i < nchoices; i++)
-+	krb5_kt_close(context, data->choices[i]);
-+    free(data->choices);
-+    free(data);
-+}
-diff --git a/src/lib/krb5/keytab/ktbase.c b/src/lib/krb5/keytab/ktbase.c
-index 0d39b2940..6534d7c52 100644
---- a/src/lib/krb5/keytab/ktbase.c
-+++ b/src/lib/krb5/keytab/ktbase.c
-@@ -57,14 +57,19 @@ extern const krb5_kt_ops krb5_ktf_ops;
- extern const krb5_kt_ops krb5_ktf_writable_ops;
- extern const krb5_kt_ops krb5_kts_ops;
- extern const krb5_kt_ops krb5_mkt_ops;
-+extern const krb5_kt_ops krb5_kta_ops;
- 
- struct krb5_kt_typelist {
-     const krb5_kt_ops *ops;
-     const struct krb5_kt_typelist *next;
- };
-+static struct krb5_kt_typelist krb5_kt_typelist_any = {
-+    &krb5_kta_ops,
-+    NULL
-+};
- const static struct krb5_kt_typelist krb5_kt_typelist_srvtab = {
-     &krb5_kts_ops,
--    NULL
-+    &krb5_kt_typelist_any
- };
- const static struct krb5_kt_typelist krb5_kt_typelist_memory = {
-     &krb5_mkt_ops,
diff --git a/SOURCES/krb5-1.12.1-pam.patch b/SOURCES/krb5-1.12.1-pam.patch
deleted file mode 100644
index c5b5e78..0000000
--- a/SOURCES/krb5-1.12.1-pam.patch
+++ /dev/null
@@ -1,770 +0,0 @@
-From 02a10f4b9a8decc8d10f3e045282a0ae7ed1c00d Mon Sep 17 00:00:00 2001
-From: Robbie Harwood <rharwood@redhat.com>
-Date: Tue, 23 Aug 2016 16:29:58 -0400
-Subject: [PATCH] krb5-1.12.1-pam.patch
-
-Modify ksu so that it performs account and session management on behalf of
-the target user account, mimicking the action of regular su.  The default
-service name is "ksu", because on Fedora at least the configuration used
-is determined by whether or not a login shell is being opened, and so
-this may need to vary, too.  At run-time, ksu's behavior can be reset to
-the earlier, non-PAM behavior by setting "use_pam" to false in the [ksu]
-section of /etc/krb5.conf.
-
-When enabled, ksu gains a dependency on libpam.
-
-Originally RT#5939, though it's changed since then to perform the account
-and session management before dropping privileges, and to apply on top of
-changes we're proposing for how it handles cache collections.
----
- src/aclocal.m4              |  67 +++++++
- src/clients/ksu/Makefile.in |   8 +-
- src/clients/ksu/main.c      |  88 +++++++-
- src/clients/ksu/pam.c       | 389 ++++++++++++++++++++++++++++++++++++
- src/clients/ksu/pam.h       |  57 ++++++
- src/configure.in            |   2 +
- 6 files changed, 608 insertions(+), 3 deletions(-)
- create mode 100644 src/clients/ksu/pam.c
- create mode 100644 src/clients/ksu/pam.h
-
-diff --git a/src/aclocal.m4 b/src/aclocal.m4
-index 3752d9bd5..340546d80 100644
---- a/src/aclocal.m4
-+++ b/src/aclocal.m4
-@@ -1697,3 +1697,70 @@ AC_DEFUN(KRB5_AC_PERSISTENT_KEYRING,[
-       ]))
- ])dnl
- dnl
-+dnl
-+dnl Use PAM instead of local crypt() compare for checking local passwords,
-+dnl and perform PAM account, session management, and password-changing where
-+dnl appropriate.
-+dnl 
-+AC_DEFUN(KRB5_WITH_PAM,[
-+AC_ARG_WITH(pam,[AC_HELP_STRING(--with-pam,[compile with PAM support])],
-+	    withpam="$withval",withpam=auto)
-+AC_ARG_WITH(pam-ksu-service,[AC_HELP_STRING(--with-ksu-service,[PAM service name for ksu ["ksu"]])],
-+	    withksupamservice="$withval",withksupamservice=ksu)
-+old_LIBS="$LIBS"
-+if test "$withpam" != no ; then
-+	AC_MSG_RESULT([checking for PAM...])
-+	PAM_LIBS=
-+
-+	AC_CHECK_HEADERS(security/pam_appl.h)
-+	if test "x$ac_cv_header_security_pam_appl_h" != xyes ; then
-+		if test "$withpam" = auto ; then
-+			AC_MSG_RESULT([Unable to locate security/pam_appl.h.])
-+			withpam=no
-+		else
-+			AC_MSG_ERROR([Unable to locate security/pam_appl.h.])
-+		fi
-+	fi
-+
-+	LIBS=
-+	unset ac_cv_func_pam_start
-+	AC_CHECK_FUNCS(putenv pam_start)
-+	if test "x$ac_cv_func_pam_start" = xno ; then
-+		unset ac_cv_func_pam_start
-+		AC_CHECK_LIB(dl,dlopen)
-+		AC_CHECK_FUNCS(pam_start)
-+		if test "x$ac_cv_func_pam_start" = xno ; then
-+			AC_CHECK_LIB(pam,pam_start)
-+			unset ac_cv_func_pam_start
-+			unset ac_cv_func_pam_getenvlist
-+			AC_CHECK_FUNCS(pam_start pam_getenvlist)
-+			if test "x$ac_cv_func_pam_start" = xyes ; then
-+				PAM_LIBS="$LIBS"
-+			else
-+				if test "$withpam" = auto ; then
-+					AC_MSG_RESULT([Unable to locate libpam.])
-+					withpam=no
-+				else
-+					AC_MSG_ERROR([Unable to locate libpam.])
-+				fi
-+			fi
-+		fi
-+	fi
-+	if test "$withpam" != no ; then
-+		AC_MSG_NOTICE([building with PAM support])
-+		AC_DEFINE(USE_PAM,1,[Define if Kerberos-aware tools should support PAM])
-+		AC_DEFINE_UNQUOTED(KSU_PAM_SERVICE,"$withksupamservice",
-+				   [Define to the name of the PAM service name to be used by ksu.])
-+		PAM_LIBS="$LIBS"
-+		NON_PAM_MAN=".\\\" "
-+		PAM_MAN=
-+	else
-+		PAM_MAN=".\\\" "
-+		NON_PAM_MAN=
-+	fi
-+fi
-+LIBS="$old_LIBS"
-+AC_SUBST(PAM_LIBS)
-+AC_SUBST(PAM_MAN)
-+AC_SUBST(NON_PAM_MAN)
-+])dnl
-diff --git a/src/clients/ksu/Makefile.in b/src/clients/ksu/Makefile.in
-index b2fcbf240..5755bb58a 100644
---- a/src/clients/ksu/Makefile.in
-+++ b/src/clients/ksu/Makefile.in
-@@ -3,12 +3,14 @@ BUILDTOP=$(REL)..$(S)..
- DEFINES = -DGET_TGT_VIA_PASSWD -DPRINC_LOOK_AHEAD -DCMD_PATH='"/bin /local/bin"'
- 
- KSU_LIBS=@KSU_LIBS@
-+PAM_LIBS=@PAM_LIBS@
- 
- SRCS = \
- 	$(srcdir)/krb_auth_su.c \
- 	$(srcdir)/ccache.c \
- 	$(srcdir)/authorization.c \
- 	$(srcdir)/main.c \
-+	$(srcdir)/pam.c \
- 	$(srcdir)/heuristic.c \
- 	$(srcdir)/xmalloc.c \
- 	$(srcdir)/setenv.c
-@@ -17,13 +19,17 @@ OBJS = \
- 	ccache.o \
- 	authorization.o \
- 	main.o \
-+	pam.o \
- 	heuristic.o \
- 	xmalloc.o @SETENVOBJ@
- 
- all: ksu
- 
- ksu: $(OBJS) $(KRB5_BASE_DEPLIBS)
--	$(CC_LINK) -o $@ $(OBJS) $(KRB5_BASE_LIBS) $(KSU_LIBS)
-+	$(CC_LINK) -o $@ $(OBJS) $(KRB5_BASE_LIBS) $(KSU_LIBS) $(PAM_LIBS)
-+
-+pam.o: pam.c
-+	$(CC) $(ALL_CFLAGS) -c $<
- 
- clean:
- 	$(RM) ksu
-diff --git a/src/clients/ksu/main.c b/src/clients/ksu/main.c
-index d9596d948..ec06788bc 100644
---- a/src/clients/ksu/main.c
-+++ b/src/clients/ksu/main.c
-@@ -26,6 +26,7 @@
-  * KSU was writen by:  Ari Medvinsky, ari@isi.edu
-  */
- 
-+#include "autoconf.h"
- #include "ksu.h"
- #include "adm_proto.h"
- #include <sys/types.h>
-@@ -33,6 +34,10 @@
- #include <signal.h>
- #include <grp.h>
- 
-+#ifdef USE_PAM
-+#include "pam.h"
-+#endif
-+
- /* globals */
- char * prog_name;
- int auth_debug =0;
-@@ -40,6 +45,7 @@ char k5login_path[MAXPATHLEN];
- char k5users_path[MAXPATHLEN];
- char * gb_err = NULL;
- int quiet = 0;
-+int force_fork = 0;
- /***********/
- 
- #define KS_TEMPORARY_CACHE "MEMORY:_ksu"
-@@ -528,6 +534,23 @@ main (argc, argv)
-                prog_name,target_user,client_name,
-                source_user,ontty());
- 
-+#ifdef USE_PAM
-+        if (appl_pam_enabled(ksu_context, "ksu")) {
-+            if (appl_pam_acct_mgmt(KSU_PAM_SERVICE, 1, target_user, NULL,
-+                                   NULL, source_user,
-+                                   ttyname(STDERR_FILENO)) != 0) {
-+                fprintf(stderr, "Access denied for %s.\n", target_user);
-+                exit(1);
-+            }
-+            if (appl_pam_requires_chauthtok()) {
-+                fprintf(stderr, "Password change required for %s.\n",
-+                        target_user);
-+                exit(1);
-+            }
-+            force_fork++;
-+        }
-+#endif
-+
-         /* Run authorization as target.*/
-         if (krb5_seteuid(target_uid)) {
-             com_err(prog_name, errno, _("while switching to target for "
-@@ -588,6 +611,24 @@ main (argc, argv)
- 
-             exit(1);
-         }
-+#ifdef USE_PAM
-+    } else {
-+        /* we always do PAM account management, even for root */
-+        if (appl_pam_enabled(ksu_context, "ksu")) {
-+            if (appl_pam_acct_mgmt(KSU_PAM_SERVICE, 1, target_user, NULL,
-+                                   NULL, source_user,
-+                                   ttyname(STDERR_FILENO)) != 0) {
-+                fprintf(stderr, "Access denied for %s.\n", target_user);
-+                exit(1);
-+            }
-+            if (appl_pam_requires_chauthtok()) {
-+                fprintf(stderr, "Password change required for %s.\n",
-+                        target_user);
-+                exit(1);
-+            }
-+            force_fork++;
-+        }
-+#endif
-     }
- 
-     if( some_rest_copy){
-@@ -645,6 +686,30 @@ main (argc, argv)
-         exit(1);
-     }
- 
-+#ifdef USE_PAM
-+    if (appl_pam_enabled(ksu_context, "ksu")) {
-+        if (appl_pam_session_open() != 0) {
-+            fprintf(stderr, "Error opening session for %s.\n", target_user);
-+            exit(1);
-+        }
-+#ifdef DEBUG
-+        if (auth_debug){
-+            printf(" Opened PAM session.\n");
-+        }
-+#endif
-+        if (appl_pam_cred_init()) {
-+            fprintf(stderr, "Error initializing credentials for %s.\n",
-+                    target_user);
-+            exit(1);
-+        }
-+#ifdef DEBUG
-+        if (auth_debug){
-+            printf(" Initialized PAM credentials.\n");
-+        }
-+#endif
-+    }
-+#endif
-+
-     /* set permissions */
-     if (setgid(target_pwd->pw_gid) < 0) {
-         perror("ksu: setgid");
-@@ -742,7 +807,7 @@ main (argc, argv)
-         fprintf(stderr, "program to be execed %s\n",params[0]);
-     }
- 
--    if( keep_target_cache ) {
-+    if( keep_target_cache && !force_fork ) {
-         execv(params[0], params);
-         com_err(prog_name, errno, _("while trying to execv %s"), params[0]);
-         sweep_up(ksu_context, cc_target);
-@@ -772,16 +837,35 @@ main (argc, argv)
-             if (ret_pid == -1) {
-                 com_err(prog_name, errno, _("while calling waitpid"));
-             }
--            sweep_up(ksu_context, cc_target);
-+            if( !keep_target_cache ) {
-+                sweep_up(ksu_context, cc_target);
-+            }
-             exit (statusp);
-         case -1:
-             com_err(prog_name, errno, _("while trying to fork."));
-             sweep_up(ksu_context, cc_target);
-             exit (1);
-         case 0:
-+#ifdef USE_PAM
-+            if (appl_pam_enabled(ksu_context, "ksu")) {
-+                if (appl_pam_setenv() != 0) {
-+                    fprintf(stderr, "Error setting up environment for %s.\n",
-+                            target_user);
-+                    exit (1);
-+                }
-+#ifdef DEBUG
-+                if (auth_debug){
-+                    printf(" Set up PAM environment.\n");
-+                }
-+#endif
-+            }
-+#endif
-             execv(params[0], params);
-             com_err(prog_name, errno, _("while trying to execv %s"),
-                     params[0]);
-+            if( keep_target_cache ) {
-+                sweep_up(ksu_context, cc_target);
-+            }
-             exit (1);
-         }
-     }
-diff --git a/src/clients/ksu/pam.c b/src/clients/ksu/pam.c
-new file mode 100644
-index 000000000..cbfe48704
---- /dev/null
-+++ b/src/clients/ksu/pam.c
-@@ -0,0 +1,389 @@
-+/*
-+ * src/clients/ksu/pam.c
-+ *
-+ * Copyright 2007,2009,2010 Red Hat, Inc.
-+ *
-+ * All Rights Reserved.
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions are met:
-+ *
-+ *  Redistributions of source code must retain the above copyright notice, this
-+ *  list of conditions and the following disclaimer.
-+ *
-+ *  Redistributions in binary form must reproduce the above copyright notice,
-+ *  this list of conditions and the following disclaimer in the documentation
-+ *  and/or other materials provided with the distribution.
-+ *
-+ *  Neither the name of Red Hat, Inc. nor the names of its contributors may be
-+ *  used to endorse or promote products derived from this software without
-+ *  specific prior written permission.
-+ *
-+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-+ * POSSIBILITY OF SUCH DAMAGE.
-+ * 
-+ * Convenience wrappers for using PAM.
-+ */
-+
-+#include "autoconf.h"
-+#ifdef USE_PAM
-+#include <sys/types.h>
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <string.h>
-+#include <unistd.h>
-+#include "k5-int.h"
-+#include "pam.h"
-+
-+#ifndef MAXPWSIZE
-+#define MAXPWSIZE 128
-+#endif
-+
-+static int appl_pam_started;
-+static pid_t appl_pam_starter = -1;
-+static int appl_pam_session_opened;
-+static int appl_pam_creds_initialized;
-+static int appl_pam_pwchange_required;
-+static pam_handle_t *appl_pamh;
-+static struct pam_conv appl_pam_conv;
-+static char *appl_pam_user;
-+struct appl_pam_non_interactive_args {
-+	const char *user;
-+	const char *password;
-+};
-+
-+int
-+appl_pam_enabled(krb5_context context, const char *section)
-+{
-+	int enabled = 1;
-+	if ((context != NULL) && (context->profile != NULL)) {
-+		if (profile_get_boolean(context->profile,
-+					section,
-+					USE_PAM_CONFIGURATION_KEYWORD,
-+					NULL,
-+					enabled, &enabled) != 0) {
-+			enabled = 1;
-+		}
-+	}
-+	return enabled;
-+}
-+
-+void
-+appl_pam_cleanup(void)
-+{
-+	if (getpid() != appl_pam_starter) {
-+		return;
-+	}
-+#ifdef DEBUG
-+	printf("Called to clean up PAM.\n");
-+#endif
-+	if (appl_pam_creds_initialized) {
-+#ifdef DEBUG
-+		printf("Deleting PAM credentials.\n");
-+#endif
-+		pam_setcred(appl_pamh, PAM_DELETE_CRED);
-+		appl_pam_creds_initialized = 0;
-+	}
-+	if (appl_pam_session_opened) {
-+#ifdef DEBUG
-+		printf("Closing PAM session.\n");
-+#endif
-+		pam_close_session(appl_pamh, 0);
-+		appl_pam_session_opened = 0;
-+	}
-+	appl_pam_pwchange_required = 0;
-+	if (appl_pam_started) {
-+#ifdef DEBUG
-+		printf("Shutting down PAM.\n");
-+#endif
-+		pam_end(appl_pamh, 0);
-+		appl_pam_started = 0;
-+		appl_pam_starter = -1;
-+		free(appl_pam_user);
-+		appl_pam_user = NULL;
-+	}
-+}
-+static int
-+appl_pam_interactive_converse(int num_msg, const struct pam_message **msg,
-+			      struct pam_response **presp, void *appdata_ptr)
-+{
-+	const struct pam_message *message;
-+	struct pam_response *resp;
-+	int i, code;
-+	char *pwstring, pwbuf[MAXPWSIZE];
-+	unsigned int pwsize;
-+	resp = malloc(sizeof(struct pam_response) * num_msg);
-+	if (resp == NULL) {
-+		return PAM_BUF_ERR;
-+	}
-+	memset(resp, 0, sizeof(struct pam_response) * num_msg);
-+	code = PAM_SUCCESS;
-+	for (i = 0; i < num_msg; i++) {
-+		message = &(msg[0][i]); /* XXX */
-+		message = msg[i]; /* XXX */
-+		pwstring = NULL;
-+		switch (message->msg_style) {
-+		case PAM_TEXT_INFO:
-+		case PAM_ERROR_MSG:
-+			printf("[%s]\n", message->msg ? message->msg : "");
-+			fflush(stdout);
-+			resp[i].resp = NULL;
-+			resp[i].resp_retcode = PAM_SUCCESS;
-+			break;
-+		case PAM_PROMPT_ECHO_ON:
-+		case PAM_PROMPT_ECHO_OFF:
-+			if (message->msg_style == PAM_PROMPT_ECHO_ON) {
-+				if (fgets(pwbuf, sizeof(pwbuf),
-+					  stdin) != NULL) {
-+					pwbuf[strcspn(pwbuf, "\r\n")] = '\0';
-+					pwstring = pwbuf;
-+				}
-+			} else {
-+				pwstring = getpass(message->msg ?
-+						   message->msg :
-+						   "");
-+			}
-+			if ((pwstring != NULL) && (pwstring[0] != '\0')) {
-+				pwsize = strlen(pwstring);
-+				resp[i].resp = malloc(pwsize + 1);
-+				if (resp[i].resp == NULL) {
-+					resp[i].resp_retcode = PAM_BUF_ERR;
-+				} else {
-+					memcpy(resp[i].resp, pwstring, pwsize);
-+					resp[i].resp[pwsize] = '\0';
-+					resp[i].resp_retcode = PAM_SUCCESS;
-+				}
-+			} else {
-+				resp[i].resp_retcode = PAM_CONV_ERR;
-+				code = PAM_CONV_ERR;
-+			}
-+			break;
-+		default:
-+			break;
-+		}
-+	}
-+	*presp = resp;
-+	return code;
-+}
-+static int
-+appl_pam_non_interactive_converse(int num_msg,
-+				  const struct pam_message **msg,
-+				  struct pam_response **presp,
-+				  void *appdata_ptr)
-+{
-+	const struct pam_message *message;
-+	struct pam_response *resp;
-+	int i, code;
-+	unsigned int pwsize;
-+	struct appl_pam_non_interactive_args *args;
-+	const char *pwstring;
-+	resp = malloc(sizeof(struct pam_response) * num_msg);
-+	if (resp == NULL) {
-+		return PAM_BUF_ERR;
-+	}
-+	args = appdata_ptr;
-+	memset(resp, 0, sizeof(struct pam_response) * num_msg);
-+	code = PAM_SUCCESS;
-+	for (i = 0; i < num_msg; i++) {
-+		message = &((*msg)[i]);
-+		message = msg[i];
-+		pwstring = NULL;
-+		switch (message->msg_style) {
-+		case PAM_TEXT_INFO:
-+		case PAM_ERROR_MSG:
-+			break;
-+		case PAM_PROMPT_ECHO_ON:
-+		case PAM_PROMPT_ECHO_OFF:
-+			if (message->msg_style == PAM_PROMPT_ECHO_ON) {
-+				/* assume "user" */
-+				pwstring = args->user;
-+			} else {
-+				/* assume "password" */
-+				pwstring = args->password;
-+			}
-+			if ((pwstring != NULL) && (pwstring[0] != '\0')) {
-+				pwsize = strlen(pwstring);
-+				resp[i].resp = malloc(pwsize + 1);
-+				if (resp[i].resp == NULL) {
-+					resp[i].resp_retcode = PAM_BUF_ERR;
-+				} else {
-+					memcpy(resp[i].resp, pwstring, pwsize);
-+					resp[i].resp[pwsize] = '\0';
-+					resp[i].resp_retcode = PAM_SUCCESS;
-+				}
-+			} else {
-+				resp[i].resp_retcode = PAM_CONV_ERR;
-+				code = PAM_CONV_ERR;
-+			}
-+			break;
-+		default:
-+			break;
-+		}
-+	}
-+	*presp = resp;
-+	return code;
-+}
-+static int
-+appl_pam_start(const char *service, int interactive,
-+	       const char *login_username,
-+	       const char *non_interactive_password,
-+	       const char *hostname,
-+	       const char *ruser,
-+	       const char *tty)
-+{
-+	static int exit_handler_registered;
-+	static struct appl_pam_non_interactive_args args;
-+	int ret = 0;
-+	if (appl_pam_started &&
-+	    (strcmp(login_username, appl_pam_user) != 0)) {
-+		appl_pam_cleanup();
-+		appl_pam_user = NULL;
-+	}
-+	if (!appl_pam_started) {
-+#ifdef DEBUG
-+		printf("Starting PAM up (service=\"%s\",user=\"%s\").\n",
-+		       service, login_username);
-+#endif
-+		memset(&appl_pam_conv, 0, sizeof(appl_pam_conv));
-+		appl_pam_conv.conv = interactive ?
-+				     &appl_pam_interactive_converse :
-+				     &appl_pam_non_interactive_converse;
-+		memset(&args, 0, sizeof(args));
-+		args.user = strdup(login_username);
-+		args.password = non_interactive_password ?
-+				strdup(non_interactive_password) :
-+				NULL;
-+		appl_pam_conv.appdata_ptr = &args;
-+		ret = pam_start(service, login_username,
-+				&appl_pam_conv, &appl_pamh);
-+		if (ret == 0) {
-+			if (hostname != NULL) {
-+#ifdef DEBUG
-+				printf("Setting PAM_RHOST to \"%s\".\n", hostname);
-+#endif
-+				pam_set_item(appl_pamh, PAM_RHOST, hostname);
-+			}
-+			if (ruser != NULL) {
-+#ifdef DEBUG
-+				printf("Setting PAM_RUSER to \"%s\".\n", ruser);
-+#endif
-+				pam_set_item(appl_pamh, PAM_RUSER, ruser);
-+			}
-+			if (tty != NULL) {
-+#ifdef DEBUG
-+				printf("Setting PAM_TTY to \"%s\".\n", tty);
-+#endif
-+				pam_set_item(appl_pamh, PAM_TTY, tty);
-+			}
-+			if (!exit_handler_registered &&
-+			    (atexit(appl_pam_cleanup) != 0)) {
-+				pam_end(appl_pamh, 0);
-+				appl_pamh = NULL;
-+				ret = -1;
-+			} else {
-+				appl_pam_started = 1;
-+				appl_pam_starter = getpid();
-+				appl_pam_user = strdup(login_username);
-+				exit_handler_registered = 1;
-+			}
-+		}
-+	}
-+	return ret;
-+}
-+int
-+appl_pam_acct_mgmt(const char *service, int interactive,
-+		   const char *login_username,
-+		   const char *non_interactive_password,
-+		   const char *hostname,
-+		   const char *ruser,
-+		   const char *tty)
-+{
-+	int ret;
-+	appl_pam_pwchange_required = 0;
-+	ret = appl_pam_start(service, interactive, login_username,
-+			     non_interactive_password, hostname, ruser, tty);
-+	if (ret == 0) {
-+#ifdef DEBUG
-+		printf("Calling pam_acct_mgmt().\n");
-+#endif
-+		ret = pam_acct_mgmt(appl_pamh, 0);
-+		switch (ret) {
-+		case PAM_IGNORE:
-+			ret = 0;
-+			break;
-+		case PAM_NEW_AUTHTOK_REQD:
-+			appl_pam_pwchange_required = 1;
-+			ret = 0;
-+			break;
-+		default:
-+			break;
-+		}
-+	}
-+	return ret;
-+}
-+int
-+appl_pam_requires_chauthtok(void)
-+{
-+	return appl_pam_pwchange_required;
-+}
-+int
-+appl_pam_session_open(void)
-+{
-+	int ret = 0;
-+	if (appl_pam_started) {
-+#ifdef DEBUG
-+		printf("Opening PAM session.\n");
-+#endif
-+		ret = pam_open_session(appl_pamh, 0);
-+		if (ret == 0) {
-+			appl_pam_session_opened = 1;
-+		}
-+	}
-+	return ret;
-+}
-+int
-+appl_pam_setenv(void)
-+{
-+	int ret = 0;
-+#ifdef HAVE_PAM_GETENVLIST
-+#ifdef HAVE_PUTENV
-+	int i;
-+	char **list;
-+	if (appl_pam_started) {
-+		list = pam_getenvlist(appl_pamh);
-+		for (i = 0; ((list != NULL) && (list[i] != NULL)); i++) {
-+#ifdef DEBUG
-+			printf("Setting \"%s\" in environment.\n", list[i]);
-+#endif
-+			putenv(list[i]);
-+		}
-+	}
-+#endif
-+#endif
-+	return ret;
-+}
-+int
-+appl_pam_cred_init(void)
-+{
-+	int ret = 0;
-+	if (appl_pam_started) {
-+#ifdef DEBUG
-+		printf("Initializing PAM credentials.\n");
-+#endif
-+		ret = pam_setcred(appl_pamh, PAM_ESTABLISH_CRED);
-+		if (ret == 0) {
-+			appl_pam_creds_initialized = 1;
-+		}
-+	}
-+	return ret;
-+}
-+#endif
-diff --git a/src/clients/ksu/pam.h b/src/clients/ksu/pam.h
-new file mode 100644
-index 000000000..0ab76569c
---- /dev/null
-+++ b/src/clients/ksu/pam.h
-@@ -0,0 +1,57 @@
-+/*
-+ * src/clients/ksu/pam.h
-+ *
-+ * Copyright 2007,2009,2010 Red Hat, Inc.
-+ *
-+ * All Rights Reserved.
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions are met:
-+ *
-+ *  Redistributions of source code must retain the above copyright notice, this
-+ *  list of conditions and the following disclaimer.
-+ *
-+ *  Redistributions in binary form must reproduce the above copyright notice,
-+ *  this list of conditions and the following disclaimer in the documentation
-+ *  and/or other materials provided with the distribution.
-+ *
-+ *  Neither the name of Red Hat, Inc. nor the names of its contributors may be
-+ *  used to endorse or promote products derived from this software without
-+ *  specific prior written permission.
-+ *
-+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-+ * POSSIBILITY OF SUCH DAMAGE.
-+ * 
-+ * Convenience wrappers for using PAM.
-+ */
-+
-+#include <krb5.h>
-+#ifdef HAVE_SECURITY_PAM_APPL_H
-+#include <security/pam_appl.h>
-+#endif
-+
-+#define USE_PAM_CONFIGURATION_KEYWORD "use_pam"
-+
-+#ifdef USE_PAM
-+int appl_pam_enabled(krb5_context context, const char *section);
-+int appl_pam_acct_mgmt(const char *service, int interactive,
-+		       const char *local_username,
-+		       const char *non_interactive_password,
-+		       const char *hostname,
-+		       const char *ruser,
-+		       const char *tty);
-+int appl_pam_requires_chauthtok(void);
-+int appl_pam_session_open(void);
-+int appl_pam_setenv(void);
-+int appl_pam_cred_init(void);
-+void appl_pam_cleanup(void);
-+#endif
-diff --git a/src/configure.in b/src/configure.in
-index 61ef738dc..e9a12ac16 100644
---- a/src/configure.in
-+++ b/src/configure.in
-@@ -1352,6 +1352,8 @@ AC_SUBST([VERTO_VERSION])
- 
- AC_PATH_PROG(GROFF, groff)
- 
-+KRB5_WITH_PAM
-+
- # Make localedir work in autoconf 2.5x.
- if test "${localedir+set}" != set; then
-     localedir='$(datadir)/locale'
diff --git a/SOURCES/krb5-1.13-dirsrv-accountlock.patch b/SOURCES/krb5-1.13-dirsrv-accountlock.patch
deleted file mode 100644
index db48910..0000000
--- a/SOURCES/krb5-1.13-dirsrv-accountlock.patch
+++ /dev/null
@@ -1,75 +0,0 @@
-From 1dc051d5964aba0b8cd3d01f063ffc28253456de Mon Sep 17 00:00:00 2001
-From: Robbie Harwood <rharwood@redhat.com>
-Date: Tue, 23 Aug 2016 16:47:44 -0400
-Subject: [PATCH] krb5-1.13-dirsrv-accountlock.patch
-
-Treat 'nsAccountLock: true' the same as 'loginDisabled: true'.  Updated from
-original version filed as RT#5891.
----
- src/aclocal.m4                                  |  9 +++++++++
- src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c    | 17 +++++++++++++++++
- .../kdb/ldap/libkdb_ldap/ldap_principal.c       |  3 +++
- 3 files changed, 29 insertions(+)
-
-diff --git a/src/aclocal.m4 b/src/aclocal.m4
-index db18226ed..518b1a547 100644
---- a/src/aclocal.m4
-+++ b/src/aclocal.m4
-@@ -1678,6 +1678,15 @@ if test "$with_ldap" = yes; then
-   AC_MSG_NOTICE(enabling OpenLDAP database backend module support)
-   OPENLDAP_PLUGIN=yes
- fi
-+AC_ARG_WITH([dirsrv-account-locking],
-+[  --with-dirsrv-account-locking       compile 389/Red Hat/Fedora/Netscape Directory Server database backend module],
-+[case "$withval" in
-+    yes | no) ;;
-+    *)  AC_MSG_ERROR(Invalid option value --with-dirsrv-account-locking="$withval") ;;
-+esac], with_dirsrv_account_locking=no)
-+if test $with_dirsrv_account_locking = yes; then
-+    AC_DEFINE(HAVE_DIRSRV_ACCOUNT_LOCKING,1,[Define if LDAP KDB interface should heed 389 DS's nsAccountLock attribute.])
-+fi
- ])dnl
- dnl
- dnl If libkeyutils exists (on Linux) include it and use keyring ccache
-diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c
-index 5b9d1e9fa..4e7270065 100644
---- a/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c
-+++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c
-@@ -1652,6 +1652,23 @@ populate_krb5_db_entry(krb5_context context, krb5_ldap_context *ldap_context,
-     ret = krb5_dbe_update_tl_data(context, entry, &userinfo_tl_data);
-     if (ret)
-         goto cleanup;
-+#ifdef HAVE_DIRSRV_ACCOUNT_LOCKING
-+    {
-+        krb5_timestamp              expiretime=0;
-+        char                        *is_login_disabled=NULL;
-+
-+        /* LOGIN DISABLED */
-+        ret = krb5_ldap_get_string(ld, ent, "nsAccountLock", &is_login_disabled,
-+                                   &attr_present);
-+        if (ret)
-+            goto cleanup;
-+        if (attr_present == TRUE) {
-+            if (strcasecmp(is_login_disabled, "TRUE")== 0)
-+                entry->attributes |= KRB5_KDB_DISALLOW_ALL_TIX;
-+            free (is_login_disabled);
-+        }
-+    }
-+#endif
- 
-     ret = krb5_read_tkt_policy(context, ldap_context, entry, tktpolname);
-     if (ret)
-diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c
-index d722dbfa6..5e8e9a897 100644
---- a/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c
-+++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c
-@@ -54,6 +54,9 @@ char     *principal_attributes[] = { "krbprincipalname",
-                                      "krbLastFailedAuth",
-                                      "krbLoginFailedCount",
-                                      "krbLastSuccessfulAuth",
-+#ifdef HAVE_DIRSRV_ACCOUNT_LOCKING
-+                                     "nsAccountLock",
-+#endif
-                                      "krbLastPwdChange",
-                                      "krbLastAdminUnlock",
-                                      "krbPrincipalAuthInd",
diff --git a/SOURCES/krb5-1.15-beta1-buildconf.patch b/SOURCES/krb5-1.15-beta1-buildconf.patch
deleted file mode 100644
index 6d1e151..0000000
--- a/SOURCES/krb5-1.15-beta1-buildconf.patch
+++ /dev/null
@@ -1,70 +0,0 @@
-From 90bf9e3c4a80e7e46e6e00b9d541c6144968cad4 Mon Sep 17 00:00:00 2001
-From: Robbie Harwood <rharwood@redhat.com>
-Date: Tue, 23 Aug 2016 16:45:26 -0400
-Subject: [PATCH] krb5-1.15-beta1-buildconf.patch
-
-Build binaries in this package as RELRO PIEs, libraries as partial RELRO,
-and install shared libraries with the execute bit set on them.  Prune out
-the -L/usr/lib* and PIE flags where they might leak out and affect
-apps which just want to link with the libraries. FIXME: needs to check and
-not just assume that the compiler supports using these flags.
----
- src/build-tools/krb5-config.in | 7 +++++++
- src/config/pre.in              | 2 +-
- src/config/shlib.conf          | 5 +++--
- 3 files changed, 11 insertions(+), 3 deletions(-)
-
-diff --git a/src/build-tools/krb5-config.in b/src/build-tools/krb5-config.in
-index c17cb5eb5..1891dea99 100755
---- a/src/build-tools/krb5-config.in
-+++ b/src/build-tools/krb5-config.in
-@@ -226,6 +226,13 @@ if test -n "$do_libs"; then
- 	    -e 's#\$(PTHREAD_CFLAGS)#'"$PTHREAD_CFLAGS"'#' \
- 	    -e 's#\$(CFLAGS)##'`
- 
-+    if test `dirname $libdir` = /usr ; then
-+        lib_flags=`echo $lib_flags | sed -e "s#-L$libdir##" -e "s#$RPATH_FLAG$libdir##"`
-+    fi
-+    lib_flags=`echo $lib_flags | sed -e "s#-fPIE##g" -e "s#-pie##g"`
-+    lib_flags=`echo $lib_flags | sed -e "s#-Wl,-z,relro##g"`
-+    lib_flags=`echo $lib_flags | sed -e "s#-Wl,-z,now##g"`
-+
-     if test $library = 'kdb'; then
- 	lib_flags="$lib_flags -lkdb5 $KDB5_DB_LIB"
- 	library=krb5
-diff --git a/src/config/pre.in b/src/config/pre.in
-index 917357df9..a8540ae2a 100644
---- a/src/config/pre.in
-+++ b/src/config/pre.in
-@@ -185,7 +185,7 @@ INSTALL_PROGRAM=@INSTALL_PROGRAM@ $(INSTALL_STRIP)
- INSTALL_SCRIPT=@INSTALL_PROGRAM@
- INSTALL_DATA=@INSTALL_DATA@
- INSTALL_SHLIB=@INSTALL_SHLIB@
--INSTALL_SETUID=$(INSTALL) $(INSTALL_STRIP) -m 4755 -o root
-+INSTALL_SETUID=$(INSTALL) $(INSTALL_STRIP) -m 4755
- ## This is needed because autoconf will sometimes define @exec_prefix@ to be
- ## ${prefix}.
- prefix=@prefix@
-diff --git a/src/config/shlib.conf b/src/config/shlib.conf
-index 3e4af6c02..2b20c3fda 100644
---- a/src/config/shlib.conf
-+++ b/src/config/shlib.conf
-@@ -423,7 +423,7 @@ mips-*-netbsd*)
- 	# Linux ld doesn't default to stuffing the SONAME field...
- 	# Use objdump -x to examine the fields of the library
- 	# UNDEF_CHECK is suppressed by --enable-asan
--	LDCOMBINE='$(CC) -shared -fPIC -Wl,-h,$(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT) $(UNDEF_CHECK)'
-+	LDCOMBINE='$(CC) -shared -fPIC -Wl,-h,$(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT) $(UNDEF_CHECK)  -Wl,-z,relro -Wl,--warn-shared-textrel'
- 	UNDEF_CHECK='-Wl,--no-undefined'
- 	# $(EXPORT_CHECK) runs export-check.pl when in maintainer mode.
- 	LDCOMBINE_TAIL='-Wl,--version-script binutils.versions $(EXPORT_CHECK)'
-@@ -435,7 +435,8 @@ mips-*-netbsd*)
- 	SHLIB_EXPFLAGS='$(SHLIB_RPATH_FLAGS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)'
- 	PROFFLAGS=-pg
- 	PROG_RPATH_FLAGS='$(RPATH_FLAG)$(PROG_RPATH)'
--	CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CFLAGS) $(LDFLAGS)'
-+	CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CFLAGS) -pie -Wl,-z,relro -Wl,-z,now $(LDFLAGS)'
-+	INSTALL_SHLIB='${INSTALL} -m755'
- 	CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)'
- 	CXX_LINK_SHARED='$(CXX) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CXXFLAGS) $(LDFLAGS)'
- 	CXX_LINK_STATIC='$(CXX) $(PROG_LIBPATH) $(CXXFLAGS) $(LDFLAGS)'
diff --git a/SOURCES/krb5-1.17-beta1-selinux-label.patch b/SOURCES/krb5-1.17-beta1-selinux-label.patch
deleted file mode 100644
index 3f874f5..0000000
--- a/SOURCES/krb5-1.17-beta1-selinux-label.patch
+++ /dev/null
@@ -1,1065 +0,0 @@
-From 46946e305e4536a56866ff21ac1f6e8ed7c3b814 Mon Sep 17 00:00:00 2001
-From: Robbie Harwood <rharwood@redhat.com>
-Date: Tue, 23 Aug 2016 16:30:53 -0400
-Subject: [PATCH] krb5-1.17-beta1-selinux-label.patch
-
-SELinux bases access to files on the domain of the requesting process,
-the operation being performed, and the context applied to the file.
-
-In many cases, applications needn't be SELinux aware to work properly,
-because SELinux can apply a default label to a file based on the label
-of the directory in which it's created.
-
-In the case of files such as /etc/krb5.keytab, however, this isn't
-sufficient, as /etc/krb5.keytab will almost always need to be given a
-label which differs from that of /etc/issue or /etc/resolv.conf.  The
-the kdb stash file needs a different label than the database for which
-it's holding a master key, even though both typically live in the same
-directory.
-
-To give the file the correct label, we can either force a "restorecon"
-call to fix a file's label after it's created, or create the file with
-the right label, as we attempt to do here.  We lean on THREEPARAMOPEN
-and define a similar macro named WRITABLEFOPEN with which we replace
-several uses of fopen().
-
-The file creation context that we're manipulating here is a process-wide
-attribute.  While for the most part, applications which need to label
-files when they're created have tended to be single-threaded, there's
-not much we can do to avoid interfering with an application that
-manipulates the creation context directly.  Right now we're mediating
-access using a library-local mutex, but that can only work for consumers
-that are part of this package -- an unsuspecting application will still
-stomp all over us.
-
-The selabel APIs for looking up the context should be thread-safe (per
-Red Hat #273081), so switching to using them instead of matchpathcon(),
-which we used earlier, is some improvement.
----
- src/aclocal.m4                                |  49 +++
- src/build-tools/krb5-config.in                |   3 +-
- src/config/pre.in                             |   3 +-
- src/configure.in                              |   2 +
- src/include/k5-int.h                          |   1 +
- src/include/k5-label.h                        |  32 ++
- src/include/krb5/krb5.hin                     |   6 +
- src/kadmin/dbutil/dump.c                      |  11 +-
- src/kdc/main.c                                |   2 +-
- src/kprop/kpropd.c                            |   9 +
- src/lib/kadm5/logger.c                        |   4 +-
- src/lib/kdb/kdb_log.c                         |   2 +-
- src/lib/krb5/ccache/cc_dir.c                  |  26 +-
- src/lib/krb5/keytab/kt_file.c                 |   4 +-
- src/lib/krb5/os/trace.c                       |   2 +-
- src/lib/krb5/rcache/rc_dfl.c                  |  13 +
- src/plugins/kdb/db2/adb_openclose.c           |   2 +-
- src/plugins/kdb/db2/kdb_db2.c                 |   4 +-
- src/plugins/kdb/db2/libdb2/btree/bt_open.c    |   3 +-
- src/plugins/kdb/db2/libdb2/hash/hash.c        |   3 +-
- src/plugins/kdb/db2/libdb2/recno/rec_open.c   |   4 +-
- .../kdb/ldap/ldap_util/kdb5_ldap_services.c   |  11 +-
- src/util/profile/prof_file.c                  |   3 +-
- src/util/support/Makefile.in                  |   3 +-
- src/util/support/selinux.c                    | 406 ++++++++++++++++++
- 25 files changed, 587 insertions(+), 21 deletions(-)
- create mode 100644 src/include/k5-label.h
- create mode 100644 src/util/support/selinux.c
-
-diff --git a/src/aclocal.m4 b/src/aclocal.m4
-index 340546d80..a7afec09e 100644
---- a/src/aclocal.m4
-+++ b/src/aclocal.m4
-@@ -89,6 +89,7 @@ AC_SUBST_FILE(libnodeps_frag)
- dnl
- KRB5_AC_PRAGMA_WEAK_REF
- WITH_LDAP
-+KRB5_WITH_SELINUX
- KRB5_LIB_PARAMS
- KRB5_AC_INITFINI
- KRB5_AC_ENABLE_THREADS
-@@ -1764,3 +1765,51 @@ AC_SUBST(PAM_LIBS)
- AC_SUBST(PAM_MAN)
- AC_SUBST(NON_PAM_MAN)
- ])dnl
-+dnl
-+dnl Use libselinux to set file contexts on newly-created files.
-+dnl
-+AC_DEFUN(KRB5_WITH_SELINUX,[
-+AC_ARG_WITH(selinux,[AC_HELP_STRING(--with-selinux,[compile with SELinux labeling support])],
-+           withselinux="$withval",withselinux=auto)
-+old_LIBS="$LIBS"
-+if test "$withselinux" != no ; then
-+       AC_MSG_RESULT([checking for libselinux...])
-+       SELINUX_LIBS=
-+       AC_CHECK_HEADERS(selinux/selinux.h selinux/label.h)
-+       if test "x$ac_cv_header_selinux_selinux_h" != xyes ; then
-+               if test "$withselinux" = auto ; then
-+                       AC_MSG_RESULT([Unable to locate selinux/selinux.h.])
-+                       withselinux=no
-+               else
-+                       AC_MSG_ERROR([Unable to locate selinux/selinux.h.])
-+               fi
-+       fi
-+
-+       LIBS=
-+       unset ac_cv_func_setfscreatecon
-+       AC_CHECK_FUNCS(setfscreatecon selabel_open)
-+       if test "x$ac_cv_func_setfscreatecon" = xno ; then
-+               AC_CHECK_LIB(selinux,setfscreatecon)
-+               unset ac_cv_func_setfscreatecon
-+               AC_CHECK_FUNCS(setfscreatecon selabel_open)
-+               if test "x$ac_cv_func_setfscreatecon" = xyes ; then
-+                       SELINUX_LIBS="$LIBS"
-+               else
-+                       if test "$withselinux" = auto ; then
-+                               AC_MSG_RESULT([Unable to locate libselinux.])
-+                               withselinux=no
-+                       else
-+                               AC_MSG_ERROR([Unable to locate libselinux.])
-+                       fi
-+               fi
-+       fi
-+       if test "$withselinux" != no ; then
-+               AC_MSG_NOTICE([building with SELinux labeling support])
-+               AC_DEFINE(USE_SELINUX,1,[Define if Kerberos-aware tools should set SELinux file contexts when creating files.])
-+               SELINUX_LIBS="$LIBS"
-+		EXTRA_SUPPORT_SYMS="$EXTRA_SUPPORT_SYMS krb5int_labeled_open krb5int_labeled_fopen krb5int_push_fscreatecon_for krb5int_pop_fscreatecon"
-+       fi
-+fi
-+LIBS="$old_LIBS"
-+AC_SUBST(SELINUX_LIBS)
-+])dnl
-diff --git a/src/build-tools/krb5-config.in b/src/build-tools/krb5-config.in
-index f6184da3f..c17cb5eb5 100755
---- a/src/build-tools/krb5-config.in
-+++ b/src/build-tools/krb5-config.in
-@@ -41,6 +41,7 @@ DL_LIB='@DL_LIB@'
- DEFCCNAME='@DEFCCNAME@'
- DEFKTNAME='@DEFKTNAME@'
- DEFCKTNAME='@DEFCKTNAME@'
-+SELINUX_LIBS='@SELINUX_LIBS@'
- 
- LIBS='@LIBS@'
- GEN_LIB=@GEN_LIB@
-@@ -255,7 +256,7 @@ if test -n "$do_libs"; then
-     fi
- 
-     # If we ever support a flag to generate output suitable for static
--    # linking, we would output "-lkrb5support $GEN_LIB $LIBS $DL_LIB"
-+    # linking, we would output "-lkrb5support $GEN_LIB $LIBS $SELINUX_LIBS $DL_LIB"
-     # here.
- 
-     echo $lib_flags
-diff --git a/src/config/pre.in b/src/config/pre.in
-index ce87e21ca..917357df9 100644
---- a/src/config/pre.in
-+++ b/src/config/pre.in
-@@ -177,6 +177,7 @@ LD = $(PURE) @LD@
- KRB_INCLUDES = -I$(BUILDTOP)/include -I$(top_srcdir)/include
- LDFLAGS = @LDFLAGS@
- LIBS = @LIBS@
-+SELINUX_LIBS=@SELINUX_LIBS@
- 
- INSTALL=@INSTALL@
- INSTALL_STRIP=
-@@ -402,7 +403,7 @@ SUPPORT_LIB			= -l$(SUPPORT_LIBNAME)
- # HESIOD_LIBS is -lhesiod...
- HESIOD_LIBS	= @HESIOD_LIBS@
- 
--KRB5_BASE_LIBS	= $(KRB5_LIB) $(K5CRYPTO_LIB) $(COM_ERR_LIB) $(SUPPORT_LIB) $(GEN_LIB) $(LIBS) $(DL_LIB)
-+KRB5_BASE_LIBS	= $(KRB5_LIB) $(K5CRYPTO_LIB) $(COM_ERR_LIB) $(SUPPORT_LIB) $(GEN_LIB) $(LIBS) $(SELINUX_LIBS) $(DL_LIB)
- KDB5_LIBS	= $(KDB5_LIB) $(GSSRPC_LIBS)
- GSS_LIBS	= $(GSS_KRB5_LIB)
- # needs fixing if ever used on macOS!
-diff --git a/src/configure.in b/src/configure.in
-index e9a12ac16..93aec682e 100644
---- a/src/configure.in
-+++ b/src/configure.in
-@@ -1354,6 +1354,8 @@ AC_PATH_PROG(GROFF, groff)
- 
- KRB5_WITH_PAM
- 
-+KRB5_WITH_SELINUX
-+
- # Make localedir work in autoconf 2.5x.
- if test "${localedir+set}" != set; then
-     localedir='$(datadir)/locale'
-diff --git a/src/include/k5-int.h b/src/include/k5-int.h
-index 652242207..8f9329c59 100644
---- a/src/include/k5-int.h
-+++ b/src/include/k5-int.h
-@@ -128,6 +128,7 @@ typedef unsigned char   u_char;
- 
- 
- #include "k5-platform.h"
-+#include "k5-label.h"
- 
- #define KRB5_KDB_MAX_LIFE       (60*60*24) /* one day */
- #define KRB5_KDB_MAX_RLIFE      (60*60*24*7) /* one week */
-diff --git a/src/include/k5-label.h b/src/include/k5-label.h
-new file mode 100644
-index 000000000..dfaaa847c
---- /dev/null
-+++ b/src/include/k5-label.h
-@@ -0,0 +1,32 @@
-+#ifndef _KRB5_LABEL_H
-+#define _KRB5_LABEL_H
-+
-+#ifdef THREEPARAMOPEN
-+#undef THREEPARAMOPEN
-+#endif
-+#ifdef WRITABLEFOPEN
-+#undef WRITABLEFOPEN
-+#endif
-+
-+/* Wrapper functions which help us create files and directories with the right
-+ * context labels. */
-+#ifdef USE_SELINUX
-+#include <sys/types.h>
-+#include <sys/stat.h>
-+#include <fcntl.h>
-+#include <stdio.h>
-+#include <unistd.h>
-+FILE *krb5int_labeled_fopen(const char *path, const char *mode);
-+int krb5int_labeled_creat(const char *path, mode_t mode);
-+int krb5int_labeled_open(const char *path, int flags, ...);
-+int krb5int_labeled_mkdir(const char *path, mode_t mode);
-+int krb5int_labeled_mknod(const char *path, mode_t mode, dev_t device);
-+#define THREEPARAMOPEN(x,y,z) krb5int_labeled_open(x,y,z)
-+#define WRITABLEFOPEN(x,y) krb5int_labeled_fopen(x,y)
-+void *krb5int_push_fscreatecon_for(const char *pathname);
-+void krb5int_pop_fscreatecon(void *previous);
-+#else
-+#define WRITABLEFOPEN(x,y) fopen(x,y)
-+#define THREEPARAMOPEN(x,y,z) open(x,y,z)
-+#endif
-+#endif
-diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin
-index c40a6cca8..3ff86d7ff 100644
---- a/src/include/krb5/krb5.hin
-+++ b/src/include/krb5/krb5.hin
-@@ -87,6 +87,12 @@
- #define THREEPARAMOPEN(x,y,z) open(x,y,z)
- #endif
- 
-+#if KRB5_PRIVATE
-+#ifndef WRITABLEFOPEN
-+#define WRITABLEFOPEN(x,y) fopen(x,y)
-+#endif
-+#endif
-+
- #define KRB5_OLD_CRYPTO
- 
- #include <stdlib.h>
-diff --git a/src/kadmin/dbutil/dump.c b/src/kadmin/dbutil/dump.c
-index c9574c6e1..8301a33d0 100644
---- a/src/kadmin/dbutil/dump.c
-+++ b/src/kadmin/dbutil/dump.c
-@@ -148,12 +148,21 @@ create_ofile(char *ofile, char **tmpname)
- {
-     int fd = -1;
-     FILE *f;
-+#ifdef USE_SELINUX
-+    void *selabel;
-+#endif
- 
-     *tmpname = NULL;
-     if (asprintf(tmpname, "%s-XXXXXX", ofile) < 0)
-         goto error;
- 
-+#ifdef USE_SELINUX
-+    selabel = krb5int_push_fscreatecon_for(ofile);
-+#endif
-     fd = mkstemp(*tmpname);
-+#ifdef USE_SELINUX
-+    krb5int_pop_fscreatecon(selabel);
-+#endif
-     if (fd == -1)
-         goto error;
- 
-@@ -197,7 +206,7 @@ prep_ok_file(krb5_context context, char *file_name, int *fd_out)
-         goto cleanup;
-     }
- 
--    fd = open(file_ok, O_WRONLY | O_CREAT | O_TRUNC, 0600);
-+    fd = THREEPARAMOPEN(file_ok, O_WRONLY | O_CREAT | O_TRUNC, 0600);
-     if (fd == -1) {
-         com_err(progname, errno, _("while creating 'ok' file, '%s'"), file_ok);
-         goto cleanup;
-diff --git a/src/kdc/main.c b/src/kdc/main.c
-index 408c723f5..663fd6303 100644
---- a/src/kdc/main.c
-+++ b/src/kdc/main.c
-@@ -858,7 +858,7 @@ write_pid_file(const char *path)
-     FILE *file;
-     unsigned long pid;
- 
--    file = fopen(path, "w");
-+    file = WRITABLEFOPEN(path, "w");
-     if (file == NULL)
-         return errno;
-     pid = (unsigned long) getpid();
-diff --git a/src/kprop/kpropd.c b/src/kprop/kpropd.c
-index 68323dd0f..4cc035dc6 100644
---- a/src/kprop/kpropd.c
-+++ b/src/kprop/kpropd.c
-@@ -488,6 +488,9 @@ doit(int fd)
-     krb5_enctype etype;
-     int database_fd;
-     char host[INET6_ADDRSTRLEN + 1];
-+#ifdef USE_SELINUX
-+    void *selabel;
-+#endif
- 
-     signal_wrapper(SIGALRM, alarm_handler);
-     alarm(params.iprop_resync_timeout);
-@@ -543,9 +546,15 @@ doit(int fd)
-         free(name);
-         exit(1);
-     }
-+#ifdef USE_SELINUX
-+    selabel = krb5int_push_fscreatecon_for(file);
-+#endif
-     omask = umask(077);
-     lock_fd = open(temp_file_name, O_RDWR | O_CREAT, 0600);
-     (void)umask(omask);
-+#ifdef USE_SELINUX
-+    krb5int_pop_fscreatecon(selabel);
-+#endif
-     retval = krb5_lock_file(kpropd_context, lock_fd,
-                             KRB5_LOCKMODE_EXCLUSIVE | KRB5_LOCKMODE_DONTBLOCK);
-     if (retval) {
-diff --git a/src/lib/kadm5/logger.c b/src/lib/kadm5/logger.c
-index c6885edf2..9aec3c05e 100644
---- a/src/lib/kadm5/logger.c
-+++ b/src/lib/kadm5/logger.c
-@@ -309,7 +309,7 @@ krb5_klog_init(krb5_context kcontext, char *ename, char *whoami, krb5_boolean do
-                      */
-                     append = (cp[4] == ':') ? O_APPEND : 0;
-                     if (append || cp[4] == '=') {
--                        fd = open(&cp[5], O_CREAT | O_WRONLY | append,
-+                        fd = THREEPARAMOPEN(&cp[5], O_CREAT | O_WRONLY | append,
-                                   S_IRUSR | S_IWUSR | S_IRGRP);
-                         if (fd != -1)
-                             f = fdopen(fd, append ? "a" : "w");
-@@ -776,7 +776,7 @@ krb5_klog_reopen(krb5_context kcontext)
-              * In case the old logfile did not get moved out of the
-              * way, open for append to prevent squashing the old logs.
-              */
--            f = fopen(log_control.log_entries[lindex].lfu_fname, "a+");
-+            f = WRITABLEFOPEN(log_control.log_entries[lindex].lfu_fname, "a+");
-             if (f) {
-                 set_cloexec_file(f);
-                 log_control.log_entries[lindex].lfu_filep = f;
-diff --git a/src/lib/kdb/kdb_log.c b/src/lib/kdb/kdb_log.c
-index 2659a2501..e9b95fce5 100644
---- a/src/lib/kdb/kdb_log.c
-+++ b/src/lib/kdb/kdb_log.c
-@@ -480,7 +480,7 @@ ulog_map(krb5_context context, const char *logname, uint32_t ulogentries)
-         return ENOMEM;
- 
-     if (stat(logname, &st) == -1) {
--        log_ctx->ulogfd = open(logname, O_RDWR | O_CREAT, 0600);
-+        log_ctx->ulogfd = THREEPARAMOPEN(logname, O_RDWR | O_CREAT, 0600);
-         if (log_ctx->ulogfd == -1) {
-             retval = errno;
-             goto cleanup;
-diff --git a/src/lib/krb5/ccache/cc_dir.c b/src/lib/krb5/ccache/cc_dir.c
-index bba64e516..73f0fe62d 100644
---- a/src/lib/krb5/ccache/cc_dir.c
-+++ b/src/lib/krb5/ccache/cc_dir.c
-@@ -183,10 +183,19 @@ write_primary_file(const char *primary_path, const char *contents)
-     char *newpath = NULL;
-     FILE *fp = NULL;
-     int fd = -1, status;
-+#ifdef USE_SELINUX
-+    void *selabel;
-+#endif
- 
-     if (asprintf(&newpath, "%s.XXXXXX", primary_path) < 0)
-         return ENOMEM;
-+#ifdef USE_SELINUX
-+    selabel = krb5int_push_fscreatecon_for(primary_path);
-+#endif
-     fd = mkstemp(newpath);
-+#ifdef USE_SELINUX
-+    krb5int_pop_fscreatecon(selabel);
-+#endif
-     if (fd < 0)
-         goto cleanup;
- #ifdef HAVE_CHMOD
-@@ -221,10 +230,23 @@ static krb5_error_code
- verify_dir(krb5_context context, const char *dirname)
- {
-     struct stat st;
-+    int status;
-+#ifdef USE_SELINUX
-+    void *selabel;
-+#endif
- 
-     if (stat(dirname, &st) < 0) {
--        if (errno == ENOENT && mkdir(dirname, S_IRWXU) == 0)
--            return 0;
-+        if (errno == ENOENT) {
-+#ifdef USE_SELINUX
-+            selabel = krb5int_push_fscreatecon_for(dirname);
-+#endif
-+            status = mkdir(dirname, S_IRWXU);
-+#ifdef USE_SELINUX
-+            krb5int_pop_fscreatecon(selabel);
-+#endif
-+            if (status == 0)
-+                return 0;
-+        }
-         k5_setmsg(context, KRB5_FCC_NOFILE,
-                   _("Credential cache directory %s does not exist"),
-                   dirname);
-diff --git a/src/lib/krb5/keytab/kt_file.c b/src/lib/krb5/keytab/kt_file.c
-index 89cb68680..21c80d419 100644
---- a/src/lib/krb5/keytab/kt_file.c
-+++ b/src/lib/krb5/keytab/kt_file.c
-@@ -1024,14 +1024,14 @@ krb5_ktfileint_open(krb5_context context, krb5_keytab id, int mode)
- 
-     KTCHECKLOCK(id);
-     errno = 0;
--    KTFILEP(id) = fopen(KTFILENAME(id),
-+    KTFILEP(id) = WRITABLEFOPEN(KTFILENAME(id),
-                         (mode == KRB5_LOCKMODE_EXCLUSIVE) ? "rb+" : "rb");
-     if (!KTFILEP(id)) {
-         if ((mode == KRB5_LOCKMODE_EXCLUSIVE) && (errno == ENOENT)) {
-             /* try making it first time around */
-             k5_create_secure_file(context, KTFILENAME(id));
-             errno = 0;
--            KTFILEP(id) = fopen(KTFILENAME(id), "rb+");
-+            KTFILEP(id) = WRITABLEFOPEN(KTFILENAME(id), "rb+");
-             if (!KTFILEP(id))
-                 goto report_errno;
-             writevno = 1;
-diff --git a/src/lib/krb5/os/trace.c b/src/lib/krb5/os/trace.c
-index 4fff8f38c..40a9e7b10 100644
---- a/src/lib/krb5/os/trace.c
-+++ b/src/lib/krb5/os/trace.c
-@@ -458,7 +458,7 @@ krb5_set_trace_filename(krb5_context context, const char *filename)
-     fd = malloc(sizeof(*fd));
-     if (fd == NULL)
-         return ENOMEM;
--    *fd = open(filename, O_WRONLY|O_CREAT|O_APPEND, 0600);
-+    *fd = THREEPARAMOPEN(filename, O_WRONLY|O_CREAT|O_APPEND, 0600);
-     if (*fd == -1) {
-         free(fd);
-         return errno;
-diff --git a/src/lib/krb5/rcache/rc_dfl.c b/src/lib/krb5/rcache/rc_dfl.c
-index 1e0cb22c9..f5e93b1ab 100644
---- a/src/lib/krb5/rcache/rc_dfl.c
-+++ b/src/lib/krb5/rcache/rc_dfl.c
-@@ -793,6 +793,9 @@ krb5_rc_dfl_expunge_locked(krb5_context context, krb5_rcache id)
-     krb5_error_code retval = 0;
-     krb5_rcache tmp;
-     krb5_deltat lifespan = t->lifespan;  /* save original lifespan */
-+#ifdef USE_SELINUX
-+    void *selabel;
-+#endif
- 
-     if (! t->recovering) {
-         name = t->name;
-@@ -814,7 +817,17 @@ krb5_rc_dfl_expunge_locked(krb5_context context, krb5_rcache id)
-     retval = krb5_rc_resolve(context, tmp, 0);
-     if (retval)
-         goto cleanup;
-+#ifdef USE_SELINUX
-+    if (t->d.fn != NULL)
-+        selabel = krb5int_push_fscreatecon_for(t->d.fn);
-+    else
-+        selabel = NULL;
-+#endif
-     retval = krb5_rc_initialize(context, tmp, lifespan);
-+#ifdef USE_SELINUX
-+    if (selabel != NULL)
-+        krb5int_pop_fscreatecon(selabel);
-+#endif
-     if (retval)
-         goto cleanup;
-     for (q = t->a; q; q = q->na) {
-diff --git a/src/plugins/kdb/db2/adb_openclose.c b/src/plugins/kdb/db2/adb_openclose.c
-index 7db30a33b..2b9d01921 100644
---- a/src/plugins/kdb/db2/adb_openclose.c
-+++ b/src/plugins/kdb/db2/adb_openclose.c
-@@ -152,7 +152,7 @@ osa_adb_init_db(osa_adb_db_t *dbp, char *filename, char *lockfilename,
-          * needs be open read/write so that write locking can work with
-          * POSIX systems
-          */
--        if ((lockp->lockinfo.lockfile = fopen(lockfilename, "r+")) == NULL) {
-+        if ((lockp->lockinfo.lockfile = WRITABLEFOPEN(lockfilename, "r+")) == NULL) {
-             /*
-              * maybe someone took away write permission so we could only
-              * get shared locks?
-diff --git a/src/plugins/kdb/db2/kdb_db2.c b/src/plugins/kdb/db2/kdb_db2.c
-index 5106a5c99..e481e8121 100644
---- a/src/plugins/kdb/db2/kdb_db2.c
-+++ b/src/plugins/kdb/db2/kdb_db2.c
-@@ -694,8 +694,8 @@ ctx_create_db(krb5_context context, krb5_db2_context *dbc)
-     if (retval)
-         return retval;
- 
--    dbc->db_lf_file = open(dbc->db_lf_name, O_CREAT | O_RDWR | O_TRUNC,
--                           0600);
-+    dbc->db_lf_file = THREEPARAMOPEN(dbc->db_lf_name,
-+                                     O_CREAT | O_RDWR | O_TRUNC, 0600);
-     if (dbc->db_lf_file < 0) {
-         retval = errno;
-         goto cleanup;
-diff --git a/src/plugins/kdb/db2/libdb2/btree/bt_open.c b/src/plugins/kdb/db2/libdb2/btree/bt_open.c
-index 2977b17f3..d5809a5a9 100644
---- a/src/plugins/kdb/db2/libdb2/btree/bt_open.c
-+++ b/src/plugins/kdb/db2/libdb2/btree/bt_open.c
-@@ -60,6 +60,7 @@ static char sccsid[] = "@(#)bt_open.c	8.11 (Berkeley) 11/2/95";
- #include <string.h>
- #include <unistd.h>
- 
-+#include "k5-int.h"
- #include "db-int.h"
- #include "btree.h"
- 
-@@ -203,7 +204,7 @@ __bt_open(fname, flags, mode, openinfo, dflags)
- 			goto einval;
- 		}
- 
--		if ((t->bt_fd = open(fname, flags | O_BINARY, mode)) < 0)
-+		if ((t->bt_fd = THREEPARAMOPEN(fname, flags | O_BINARY, mode)) < 0)
- 			goto err;
- 
- 	} else {
-diff --git a/src/plugins/kdb/db2/libdb2/hash/hash.c b/src/plugins/kdb/db2/libdb2/hash/hash.c
-index 862dbb164..686a960c9 100644
---- a/src/plugins/kdb/db2/libdb2/hash/hash.c
-+++ b/src/plugins/kdb/db2/libdb2/hash/hash.c
-@@ -51,6 +51,7 @@ static char sccsid[] = "@(#)hash.c	8.12 (Berkeley) 11/7/95";
- #include <assert.h>
- #endif
- 
-+#include "k5-int.h"
- #include "db-int.h"
- #include "hash.h"
- #include "page.h"
-@@ -129,7 +130,7 @@ __kdb2_hash_open(file, flags, mode, info, dflags)
- 		new_table = 1;
- 	}
- 	if (file) {
--		if ((hashp->fp = open(file, flags|O_BINARY, mode)) == -1)
-+		if ((hashp->fp = THREEPARAMOPEN(file, flags|O_BINARY, mode)) == -1)
- 			RETURN_ERROR(errno, error0);
- 		(void)fcntl(hashp->fp, F_SETFD, 1);
- 	}
-diff --git a/src/plugins/kdb/db2/libdb2/recno/rec_open.c b/src/plugins/kdb/db2/libdb2/recno/rec_open.c
-index d8b26e701..b0daa7c02 100644
---- a/src/plugins/kdb/db2/libdb2/recno/rec_open.c
-+++ b/src/plugins/kdb/db2/libdb2/recno/rec_open.c
-@@ -51,6 +51,7 @@ static char sccsid[] = "@(#)rec_open.c	8.12 (Berkeley) 11/18/94";
- #include <stdio.h>
- #include <unistd.h>
- 
-+#include "k5-int.h"
- #include "db-int.h"
- #include "recno.h"
- 
-@@ -68,7 +69,8 @@ __rec_open(fname, flags, mode, openinfo, dflags)
- 	int rfd = -1, sverrno;
- 
- 	/* Open the user's file -- if this fails, we're done. */
--	if (fname != NULL && (rfd = open(fname, flags | O_BINARY, mode)) < 0)
-+	if (fname != NULL &&
-+            (rfd = THREEPARAMOPEN(fname, flags | O_BINARY, mode)) < 0)
- 		return (NULL);
- 
- 	if (fname != NULL && fcntl(rfd, F_SETFD, 1) == -1) {
-diff --git a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c
-index 1ed72afe9..ce038fc3d 100644
---- a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c
-+++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c
-@@ -194,7 +194,7 @@ kdb5_ldap_stash_service_password(int argc, char **argv)
- 
-     /* set password in the file */
-     old_mode = umask(0177);
--    pfile = fopen(file_name, "a+");
-+    pfile = WRITABLEFOPEN(file_name, "a+");
-     if (pfile == NULL) {
-         com_err(me, errno, _("Failed to open file %s: %s"), file_name,
-                 strerror (errno));
-@@ -235,6 +235,9 @@ kdb5_ldap_stash_service_password(int argc, char **argv)
-          * Delete the existing entry and add the new entry
-          */
-         FILE *newfile;
-+#ifdef USE_SELINUX
-+        void *selabel;
-+#endif
- 
-         mode_t omask;
- 
-@@ -246,7 +249,13 @@ kdb5_ldap_stash_service_password(int argc, char **argv)
-         }
- 
-         omask = umask(077);
-+#ifdef USE_SELINUX
-+        selabel = krb5int_push_fscreatecon_for(file_name);
-+#endif
-         newfile = fopen(tmp_file, "w");
-+#ifdef USE_SELINUX
-+        krb5int_pop_fscreatecon(selabel);
-+#endif
-         umask (omask);
-         if (newfile == NULL) {
-             com_err(me, errno, _("Error creating file %s"), tmp_file);
-diff --git a/src/util/profile/prof_file.c b/src/util/profile/prof_file.c
-index 24e41fb80..0dcb6b543 100644
---- a/src/util/profile/prof_file.c
-+++ b/src/util/profile/prof_file.c
-@@ -33,6 +33,7 @@
- #endif
- 
- #include "k5-platform.h"
-+#include "k5-label.h"
- 
- struct global_shared_profile_data {
-     /* This is the head of the global list of shared trees */
-@@ -391,7 +392,7 @@ static errcode_t write_data_to_file(prf_data_t data, const char *outfile,
- 
-     errno = 0;
- 
--    f = fopen(new_file, "w");
-+    f = WRITABLEFOPEN(new_file, "w");
-     if (!f) {
-         retval = errno;
-         if (retval == 0)
-diff --git a/src/util/support/Makefile.in b/src/util/support/Makefile.in
-index db7b030b8..321672bcb 100644
---- a/src/util/support/Makefile.in
-+++ b/src/util/support/Makefile.in
-@@ -69,6 +69,7 @@ IPC_SYMS= \
- 
- STLIBOBJS= \
- 	threads.o \
-+	selinux.o \
- 	init-addrinfo.o \
- 	plugins.o \
- 	errors.o \
-@@ -160,7 +161,7 @@ SRCS=\
- 
- SHLIB_EXPDEPS =
- # Add -lm if dumping thread stats, for sqrt.
--SHLIB_EXPLIBS= $(LIBS) $(DL_LIB)
-+SHLIB_EXPLIBS= $(LIBS) $(SELINUX_LIBS) $(DL_LIB)
- 
- DEPLIBS=
- 
-diff --git a/src/util/support/selinux.c b/src/util/support/selinux.c
-new file mode 100644
-index 000000000..6d41f3244
---- /dev/null
-+++ b/src/util/support/selinux.c
-@@ -0,0 +1,406 @@
-+/*
-+ * Copyright 2007,2008,2009,2011,2012,2013,2016 Red Hat, Inc.  All Rights Reserved.
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions are met:
-+ *
-+ *  Redistributions of source code must retain the above copyright notice, this
-+ *  list of conditions and the following disclaimer.
-+ *
-+ *  Redistributions in binary form must reproduce the above copyright notice,
-+ *  this list of conditions and the following disclaimer in the documentation
-+ *  and/or other materials provided with the distribution.
-+ *
-+ *  Neither the name of Red Hat, Inc. nor the names of its contributors may be
-+ *  used to endorse or promote products derived from this software without
-+ *  specific prior written permission.
-+ *
-+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-+ * POSSIBILITY OF SUCH DAMAGE.
-+ *
-+ * File-opening wrappers for creating correctly-labeled files.  So far, we can
-+ * assume that this is Linux-specific, so we make many simplifying assumptions.
-+ */
-+
-+#include "../../include/autoconf.h"
-+
-+#ifdef USE_SELINUX
-+
-+#include <k5-label.h>
-+#include <k5-platform.h>
-+
-+#include <sys/types.h>
-+#include <sys/stat.h>
-+
-+#include <errno.h>
-+#include <fcntl.h>
-+#include <limits.h>
-+#include <pthread.h>
-+#include <stdarg.h>
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <string.h>
-+#include <unistd.h>
-+
-+#include <selinux/selinux.h>
-+#include <selinux/context.h>
-+#include <selinux/label.h>
-+
-+/* #define DEBUG 1 */
-+static void
-+debug_log(const char *fmt, ...)
-+{
-+#ifdef DEBUG
-+    va_list ap;
-+    va_start(ap, fmt);
-+    if (isatty(fileno(stderr))) {
-+        vfprintf(stderr, fmt, ap);
-+    }
-+    va_end(ap);
-+#endif
-+
-+    return;
-+}
-+
-+/* Mutex used to serialize use of the process-global file creation context. */
-+k5_mutex_t labeled_mutex = K5_MUTEX_PARTIAL_INITIALIZER;
-+
-+/* Make sure we finish initializing that mutex before attempting to use it. */
-+k5_once_t labeled_once = K5_ONCE_INIT;
-+static void
-+label_mutex_init(void)
-+{
-+    k5_mutex_finish_init(&labeled_mutex);
-+}
-+
-+static struct selabel_handle *selabel_ctx;
-+static time_t selabel_last_changed;
-+
-+MAKE_FINI_FUNCTION(cleanup_fscreatecon);
-+
-+static void
-+cleanup_fscreatecon(void)
-+{
-+    if (selabel_ctx != NULL) {
-+        selabel_close(selabel_ctx);
-+        selabel_ctx = NULL;
-+    }
-+}
-+
-+static security_context_t
-+push_fscreatecon(const char *pathname, mode_t mode)
-+{
-+    security_context_t previous, configuredsc, currentsc, derivedsc;
-+    context_t current, derived;
-+    const char *fullpath, *currentuser;
-+    char *genpath;
-+
-+    previous = configuredsc = currentsc = derivedsc = NULL;
-+    current = derived = NULL;
-+    genpath = NULL;
-+
-+    fullpath = pathname;
-+
-+    if (!is_selinux_enabled()) {
-+        goto fail;
-+    }
-+
-+    if (getfscreatecon(&previous) != 0) {
-+        goto fail;
-+    }
-+
-+    /* Canonicalize pathname */
-+    if (pathname[0] != '/') {
-+        char *wd;
-+        size_t len;
-+        len = 0;
-+
-+        wd = getcwd(NULL, len);
-+        if (wd == NULL) {
-+            goto fail;
-+        }
-+
-+        len = strlen(wd) + 1 + strlen(pathname) + 1;
-+        genpath = malloc(len);
-+        if (genpath == NULL) {
-+            free(wd);
-+            goto fail;
-+        }
-+
-+        sprintf(genpath, "%s/%s", wd, pathname);
-+        free(wd);
-+        fullpath = genpath;
-+    }
-+
-+    debug_log("Looking up context for \"%s\"(%05o).\n", fullpath, mode);
-+
-+    /* Check whether context file has changed under us */
-+    if (selabel_ctx != NULL || selabel_last_changed == 0) {
-+        const char *cpath;
-+        struct stat st;
-+        int i = -1;
-+
-+        cpath = selinux_file_context_path();
-+        if (cpath == NULL || (i = stat(cpath, &st)) != 0 ||
-+            st.st_mtime != selabel_last_changed) {
-+            cleanup_fscreatecon();
-+
-+            selabel_last_changed = i ? time(NULL) : st.st_mtime;
-+        }
-+    }
-+
-+    if (selabel_ctx == NULL) {
-+        selabel_ctx = selabel_open(SELABEL_CTX_FILE, NULL, 0);
-+    }
-+
-+    if (selabel_ctx != NULL &&
-+        selabel_lookup(selabel_ctx, &configuredsc, fullpath, mode) != 0) {
-+        goto fail;
-+    }
-+
-+    if (genpath != NULL) {
-+        free(genpath);
-+        genpath = NULL;
-+    }
-+
-+    if (configuredsc == NULL) {
-+        goto fail;
-+    }
-+
-+    getcon(&currentsc);
-+
-+    /* AAAAAAAA */
-+    if (currentsc != NULL) {
-+        derived = context_new(configuredsc);
-+
-+        if (derived != NULL) {
-+            current = context_new(currentsc);
-+
-+            if (current != NULL) {
-+                currentuser = context_user_get(current);
-+
-+                if (currentuser != NULL) {
-+                    if (context_user_set(derived,
-+                                         currentuser) == 0) {
-+                        derivedsc = context_str(derived);
-+
-+                        if (derivedsc != NULL) {
-+                            freecon(configuredsc);
-+                            configuredsc = strdup(derivedsc);
-+                        }
-+                    }
-+                }
-+
-+                context_free(current);
-+            }
-+
-+            context_free(derived);
-+        }
-+
-+        freecon(currentsc);
-+    }
-+
-+    debug_log("Setting file creation context to \"%s\".\n", configuredsc);
-+    if (setfscreatecon(configuredsc) != 0) {
-+        debug_log("Unable to determine current context.\n");
-+        goto fail;
-+    }
-+
-+    freecon(configuredsc);
-+    return previous;
-+
-+fail:
-+    if (previous != NULL) {
-+        freecon(previous);
-+    }
-+    if (genpath != NULL) {
-+        free(genpath);
-+    }
-+    if (configuredsc != NULL) {
-+        freecon(configuredsc);
-+    }
-+
-+    cleanup_fscreatecon();
-+    return NULL;
-+}
-+
-+static void
-+pop_fscreatecon(security_context_t previous)
-+{
-+    if (!is_selinux_enabled()) {
-+        return;
-+    }
-+
-+    if (previous != NULL) {
-+        debug_log("Resetting file creation context to \"%s\".\n", previous);
-+    } else {
-+        debug_log("Resetting file creation context to default.\n");
-+    }
-+
-+    /* NULL resets to default */
-+    setfscreatecon(previous);
-+
-+    if (previous != NULL) {
-+        freecon(previous);
-+    }
-+
-+    /* Need to clean this up here otherwise it leaks */
-+    cleanup_fscreatecon();
-+}
-+
-+void *
-+krb5int_push_fscreatecon_for(const char *pathname)
-+{
-+    struct stat st;
-+    void *retval;
-+
-+    k5_once(&labeled_once, label_mutex_init);
-+    k5_mutex_lock(&labeled_mutex);
-+
-+    if (stat(pathname, &st) != 0) {
-+        st.st_mode = S_IRUSR | S_IWUSR;
-+    }
-+
-+    retval = push_fscreatecon(pathname, st.st_mode);
-+    return retval ? retval : (void *) -1;
-+}
-+
-+void
-+krb5int_pop_fscreatecon(void *con)
-+{
-+    if (con != NULL) {
-+        pop_fscreatecon((con == (void *) -1) ? NULL : con);
-+        k5_mutex_unlock(&labeled_mutex);
-+    }
-+}
-+
-+FILE *
-+krb5int_labeled_fopen(const char *path, const char *mode)
-+{
-+    FILE *fp;
-+    int errno_save;
-+    security_context_t ctx;
-+
-+    if ((strcmp(mode, "r") == 0) ||
-+        (strcmp(mode, "rb") == 0)) {
-+        return fopen(path, mode);
-+    }
-+
-+    k5_once(&labeled_once, label_mutex_init);
-+    k5_mutex_lock(&labeled_mutex);
-+    ctx = push_fscreatecon(path, 0);
-+
-+    fp = fopen(path, mode);
-+    errno_save = errno;
-+
-+    pop_fscreatecon(ctx);
-+    k5_mutex_unlock(&labeled_mutex);
-+
-+    errno = errno_save;
-+    return fp;
-+}
-+
-+int
-+krb5int_labeled_creat(const char *path, mode_t mode)
-+{
-+    int fd;
-+    int errno_save;
-+    security_context_t ctx;
-+
-+    k5_once(&labeled_once, label_mutex_init);
-+    k5_mutex_lock(&labeled_mutex);
-+    ctx = push_fscreatecon(path, 0);
-+
-+    fd = creat(path, mode);
-+    errno_save = errno;
-+
-+    pop_fscreatecon(ctx);
-+    k5_mutex_unlock(&labeled_mutex);
-+
-+    errno = errno_save;
-+    return fd;
-+}
-+
-+int
-+krb5int_labeled_mknod(const char *path, mode_t mode, dev_t dev)
-+{
-+    int ret;
-+    int errno_save;
-+    security_context_t ctx;
-+
-+    k5_once(&labeled_once, label_mutex_init);
-+    k5_mutex_lock(&labeled_mutex);
-+    ctx = push_fscreatecon(path, mode);
-+
-+    ret = mknod(path, mode, dev);
-+    errno_save = errno;
-+
-+    pop_fscreatecon(ctx);
-+    k5_mutex_unlock(&labeled_mutex);
-+
-+    errno = errno_save;
-+    return ret;
-+}
-+
-+int
-+krb5int_labeled_mkdir(const char *path, mode_t mode)
-+{
-+    int ret;
-+    int errno_save;
-+    security_context_t ctx;
-+
-+    k5_once(&labeled_once, label_mutex_init);
-+    k5_mutex_lock(&labeled_mutex);
-+    ctx = push_fscreatecon(path, S_IFDIR);
-+
-+    ret = mkdir(path, mode);
-+    errno_save = errno;
-+
-+    pop_fscreatecon(ctx);
-+    k5_mutex_unlock(&labeled_mutex);
-+
-+    errno = errno_save;
-+    return ret;
-+}
-+
-+int
-+krb5int_labeled_open(const char *path, int flags, ...)
-+{
-+    int fd;
-+    int errno_save;
-+    security_context_t ctx;
-+    mode_t mode;
-+    va_list ap;
-+
-+    if ((flags & O_CREAT) == 0) {
-+        return open(path, flags);
-+    }
-+
-+    k5_once(&labeled_once, label_mutex_init);
-+    k5_mutex_lock(&labeled_mutex);
-+    ctx = push_fscreatecon(path, 0);
-+
-+    va_start(ap, flags);
-+    mode = va_arg(ap, mode_t);
-+    fd = open(path, flags, mode);
-+    va_end(ap);
-+
-+    errno_save = errno;
-+
-+    pop_fscreatecon(ctx);
-+    k5_mutex_unlock(&labeled_mutex);
-+
-+    errno = errno_save;
-+    return fd;
-+}
-+
-+#endif /* USE_SELINUX */
diff --git a/SOURCES/krb5-1.17.tar.gz.asc b/SOURCES/krb5-1.17.tar.gz.asc
deleted file mode 100644
index 90f7148..0000000
--- a/SOURCES/krb5-1.17.tar.gz.asc
+++ /dev/null
@@ -1,17 +0,0 @@
------BEGIN PGP SIGNATURE-----
-Version: GnuPG v1
-
-iQIcBAABAgAGBQJcNMxOAAoJEAy6CFdfg3LfjAwP/2/oQe+4Bs/XwZTwNfakTbBl
-YHSY8MNAHIKsLh6Bn+SJBQQXSE0fEsm0hYH+JWz85+mzlZk7TbNZUI+zeikhLxi6
-+d8MMQBpk2mQN0dkIeWjTdfkcThGCDSL7l0fh3MuEfN5C7QPAPD1JL1ZeqXPH5AV
-PSQRC9s2wiOTwwuHM2i27rZ7gdhL/xfJ3ZPUFJH4klRgszwp9j10I/nh4/XyS/wB
-82umjfusFPa9VNSPzm1jm94oRmALkR3CHGvmku2XD3YOv/f5yO8C1cHWNNLxg+5h
-EqVv05ddb6iLku4fRhkEjfN3VgCtEvXuMkuAXppkDJJ7wWxMBWgCIr1DS/x7LfbL
-CI0ZTejn8HCUBNmRWsKkUuebgHJ7ccch8p/Fp0cV4eT1FL35N2oV51u7+/zK6R8y
-1dygUF2VWFOqwm8cyczdFue7dFQVDGCw7R2eK5lXY3NpZVmJblQ/gNLMcbOxGBis
-H2dOzSn+CnxlD/2LqOZnhQ1WnGBhOMxoINwX/MQsIvkwAFaM1EsdhPIP/6mSVA/g
-p04+YQ2u2ag7Pq3zHsMIonC18w4ZqDPcvXvOXqCHtlQBDAMtb927XvjoTNj5W8Ei
-jywxqdWuuqalmrKGPEsKVOJZN6xg7UTgaKzcvQTvW7D3gLbrTT2iM++VKB3vh9V9
-SkULnR3c7fKMzFeLb/Q2
-=4hZX
------END PGP SIGNATURE-----
diff --git a/SOURCES/krb5-1.17post2-DES-3DES-fixups.patch b/SOURCES/krb5-1.17post2-DES-3DES-fixups.patch
deleted file mode 100644
index 0fcb76c..0000000
--- a/SOURCES/krb5-1.17post2-DES-3DES-fixups.patch
+++ /dev/null
@@ -1,103 +0,0 @@
-From fe66536c1b7aec67233739df97cbe0301ee6475e Mon Sep 17 00:00:00 2001
-From: Robbie Harwood <rharwood@redhat.com>
-Date: Tue, 19 Nov 2019 15:03:19 -0500
-Subject: [PATCH] krb5-1.17post2 DES/3DES fixups
-
-Kept separate from the other patch because rawhide doesn't have DES.
-
-post2 adds krb5kdf workarounds.
----
- src/lib/crypto/krb/derive.c                | 6 +++++-
- src/lib/crypto/openssl/enc_provider/des.c  | 9 +++++++++
- src/lib/crypto/openssl/enc_provider/des3.c | 6 ++++++
- 3 files changed, 20 insertions(+), 1 deletion(-)
-
-diff --git a/src/lib/crypto/krb/derive.c b/src/lib/crypto/krb/derive.c
-index 915a173dd..ebdab69bc 100644
---- a/src/lib/crypto/krb/derive.c
-+++ b/src/lib/crypto/krb/derive.c
-@@ -348,6 +348,7 @@ cleanup:
-     zapfree(prf.data, blocksize);
-     return ret;
- }
-+#endif /* OSSL_KDFS */
- 
- static krb5_error_code
- builtin_derive_random_rfc3961(const struct krb5_enc_provider *enc,
-@@ -400,7 +401,6 @@ cleanup:
-     zapfree(block.data, blocksize);
-     return ret;
- }
--#endif /* OSSL_KDFS */
- 
- krb5_error_code
- k5_sp800_108_counter_hmac(const struct krb5_hash_provider *hash,
-@@ -432,6 +432,10 @@ k5_derive_random_rfc3961(const struct krb5_enc_provider *enc,
-                          krb5_key inkey, krb5_data *outrnd,
-                          const krb5_data *in_constant)
- {
-+    /* DES (single and triple).  They'll be gone very soon. */
-+    if (enc->keylength == 8 || enc->keylength == 24)
-+        return builtin_derive_random_rfc3961(enc, inkey, outrnd, in_constant);
-+
- #ifdef OSSL_KDFS
-     return openssl_krb5kdf(enc, inkey, outrnd, in_constant);
- #else
-diff --git a/src/lib/crypto/openssl/enc_provider/des.c b/src/lib/crypto/openssl/enc_provider/des.c
-index a662db512..7d17d287e 100644
---- a/src/lib/crypto/openssl/enc_provider/des.c
-+++ b/src/lib/crypto/openssl/enc_provider/des.c
-@@ -85,6 +85,9 @@ k5_des_encrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
-     EVP_CIPHER_CTX *ctx;
-     krb5_boolean empty;
- 
-+    if (FIPS_mode())
-+        return KRB5_CRYPTO_INTERNAL;
-+
-     ret = validate(key, ivec, data, num_data, &empty);
-     if (ret != 0 || empty)
-         return ret;
-@@ -133,6 +136,9 @@ k5_des_decrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
-     EVP_CIPHER_CTX *ctx;
-     krb5_boolean empty;
- 
-+    if (FIPS_mode())
-+        return KRB5_CRYPTO_INTERNAL;
-+
-     ret = validate(key, ivec, data, num_data, &empty);
-     if (ret != 0 || empty)
-         return ret;
-@@ -182,6 +188,9 @@ k5_des_cbc_mac(krb5_key key, const krb5_crypto_iov *data, size_t num_data,
-     DES_key_schedule sched;
-     krb5_boolean empty;
- 
-+    if (FIPS_mode())
-+        return KRB5_CRYPTO_INTERNAL;
-+
-     ret = validate(key, ivec, data, num_data, &empty);
-     if (ret != 0)
-         return ret;
-diff --git a/src/lib/crypto/openssl/enc_provider/des3.c b/src/lib/crypto/openssl/enc_provider/des3.c
-index 1c439c2cd..8be555a8d 100644
---- a/src/lib/crypto/openssl/enc_provider/des3.c
-+++ b/src/lib/crypto/openssl/enc_provider/des3.c
-@@ -84,6 +84,9 @@ k5_des3_encrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
-     EVP_CIPHER_CTX *ctx;
-     krb5_boolean empty;
- 
-+    if (FIPS_mode())
-+        return KRB5_CRYPTO_INTERNAL;
-+
-     ret = validate(key, ivec, data, num_data, &empty);
-     if (ret != 0 || empty)
-         return ret;
-@@ -133,6 +136,9 @@ k5_des3_decrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
-     EVP_CIPHER_CTX *ctx;
-     krb5_boolean empty;
- 
-+    if (FIPS_mode())
-+        return KRB5_CRYPTO_INTERNAL;
-+
-     ret = validate(key, ivec, data, num_data, &empty);
-     if (ret != 0 || empty)
-         return ret;
diff --git a/SOURCES/krb5-1.17post6-FIPS-with-PRNG-and-RADIUS-and-MD4.patch b/SOURCES/krb5-1.17post6-FIPS-with-PRNG-and-RADIUS-and-MD4.patch
deleted file mode 100644
index 308137f..0000000
--- a/SOURCES/krb5-1.17post6-FIPS-with-PRNG-and-RADIUS-and-MD4.patch
+++ /dev/null
@@ -1,568 +0,0 @@
-From 2a4e2418875b41c3273db5f6b4e9e1b01c1fb5ff Mon Sep 17 00:00:00 2001
-From: Robbie Harwood <rharwood@redhat.com>
-Date: Fri, 9 Nov 2018 15:12:21 -0500
-Subject: [PATCH] krb5-1.17post6 FIPS with PRNG and RADIUS and MD4
-
-NB: Use openssl's PRNG in FIPS mode and taint within krad.
-
-A lot of the FIPS error conditions from OpenSSL are incredibly
-mysterious (at best, things return NULL unexpectedly; at worst,
-internal assertions are tripped; most of the time, you just get
-ENOMEM).  In order to cope with this, we need to have some level of
-awareness of what we can and can't safely call.
-
-This will slow down some calls slightly (FIPS_mode() takes multiple
-locks), but not for any ciphers we care about - which is to say that
-AES is fine.  Shame about SPAKE though.
-
-post6 restores MD4 (and therefore keygen-only RC4).
-
-(cherry picked from commit 80b56b04d90fcacd9f78fed305c7d5528d863b38)
----
- 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                           | 45 ++++++++++++++-----
- src/lib/krad/attrset.c                        |  5 ++-
- src/lib/krad/internal.h                       | 13 +++++-
- 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 +++
- 14 files changed, 129 insertions(+), 33 deletions(-)
-
-diff --git a/src/lib/crypto/krb/prng.c b/src/lib/crypto/krb/prng.c
-index cb9ca9b98..f0e9984ca 100644
---- a/src/lib/crypto/krb/prng.c
-+++ b/src/lib/crypto/krb/prng.c
-@@ -26,6 +26,8 @@
- 
- #include "crypto_int.h"
- 
-+#include <openssl/rand.h>
-+
- krb5_error_code KRB5_CALLCONV
- krb5_c_random_seed(krb5_context context, krb5_data *data)
- {
-@@ -99,9 +101,16 @@ krb5_boolean
- k5_get_os_entropy(unsigned char *buf, size_t len, int strong)
- {
-     const char *device;
--#if defined(__linux__) && defined(SYS_getrandom)
-     int r;
- 
-+    /* A wild FIPS mode appeared! */
-+    if (FIPS_mode()) {
-+        /* The return codes on this API are not good */
-+        r = RAND_bytes(buf, len);
-+        return r == 1;
-+    }
-+
-+#if defined(__linux__) && defined(SYS_getrandom)
-     while (len > 0) {
-         /*
-          * Pull from the /dev/urandom pool, but require it to have been seeded.
-diff --git a/src/lib/crypto/openssl/enc_provider/camellia.c b/src/lib/crypto/openssl/enc_provider/camellia.c
-index 2da691329..f79679a0b 100644
---- a/src/lib/crypto/openssl/enc_provider/camellia.c
-+++ b/src/lib/crypto/openssl/enc_provider/camellia.c
-@@ -304,6 +304,9 @@ krb5int_camellia_cbc_mac(krb5_key key, const krb5_crypto_iov *data,
-     unsigned char blockY[CAMELLIA_BLOCK_SIZE], blockB[CAMELLIA_BLOCK_SIZE];
-     struct iov_cursor cursor;
- 
-+    if (FIPS_mode())
-+        return KRB5_CRYPTO_INTERNAL;
-+
-     if (output->length < CAMELLIA_BLOCK_SIZE)
-         return KRB5_BAD_MSIZE;
- 
-@@ -331,6 +334,9 @@ static krb5_error_code
- krb5int_camellia_init_state (const krb5_keyblock *key, krb5_keyusage usage,
-                              krb5_data *state)
- {
-+    if (FIPS_mode())
-+        return KRB5_CRYPTO_INTERNAL;
-+
-     state->length = 16;
-     state->data = (void *) malloc(16);
-     if (state->data == NULL)
-diff --git a/src/lib/crypto/openssl/enc_provider/rc4.c b/src/lib/crypto/openssl/enc_provider/rc4.c
-index a65d57b7a..6ccaca94a 100644
---- a/src/lib/crypto/openssl/enc_provider/rc4.c
-+++ b/src/lib/crypto/openssl/enc_provider/rc4.c
-@@ -66,6 +66,9 @@ k5_arcfour_docrypt(krb5_key key, const krb5_data *state, krb5_crypto_iov *data,
-     EVP_CIPHER_CTX *ctx = NULL;
-     struct arcfour_state *arcstate;
- 
-+    if (FIPS_mode())
-+        return KRB5_CRYPTO_INTERNAL;
-+
-     arcstate = (state != NULL) ? (void *)state->data : NULL;
-     if (arcstate != NULL) {
-         ctx = arcstate->ctx;
-@@ -113,7 +116,12 @@ k5_arcfour_docrypt(krb5_key key, const krb5_data *state, krb5_crypto_iov *data,
- static void
- k5_arcfour_free_state(krb5_data *state)
- {
--    struct arcfour_state *arcstate = (void *)state->data;
-+    struct arcfour_state *arcstate;
-+
-+    if (FIPS_mode())
-+        return;
-+
-+    arcstate = (void *) state->data;
- 
-     EVP_CIPHER_CTX_free(arcstate->ctx);
-     free(arcstate);
-@@ -125,6 +133,9 @@ k5_arcfour_init_state(const krb5_keyblock *key,
- {
-     struct arcfour_state *arcstate;
- 
-+    if (FIPS_mode())
-+        return KRB5_CRYPTO_INTERNAL;
-+
-     /*
-      * 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 957ed8d9c..915da9dbe 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;
- 
-+    if (type == EVP_md4()) {
-+        /* See comment below in hash_md4(). */
-+        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]))
-@@ -64,12 +69,19 @@ hash_evp(const EVP_MD *type, const krb5_crypto_iov *data, size_t num_data,
- static krb5_error_code
- hash_md4(const krb5_crypto_iov *data, size_t num_data, krb5_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);
- }
- 
- static krb5_error_code
- hash_md5(const krb5_crypto_iov *data, size_t num_data, krb5_data *output)
- {
-+    if (FIPS_mode())
-+        return KRB5_CRYPTO_INTERNAL;
-     return hash_evp(EVP_md5(), data, num_data, output);
- }
- 
-diff --git a/src/lib/crypto/openssl/hmac.c b/src/lib/crypto/openssl/hmac.c
-index b2db6ec02..d94d9ac94 100644
---- a/src/lib/crypto/openssl/hmac.c
-+++ b/src/lib/crypto/openssl/hmac.c
-@@ -103,7 +103,11 @@ map_digest(const struct krb5_hash_provider *hash)
-         return EVP_sha256();
-     else if (!strncmp(hash->hash_name, "SHA-384",7))
-         return EVP_sha384();
--    else if (!strncmp(hash->hash_name, "MD5", 3))
-+
-+    if (FIPS_mode())
-+        return NULL;
-+
-+    if (!strncmp(hash->hash_name, "MD5", 3))
-         return EVP_md5();
-     else if (!strncmp(hash->hash_name, "MD4", 3))
-         return EVP_md4();
-diff --git a/src/lib/krad/attr.c b/src/lib/krad/attr.c
-index 9c13d9d75..275327e67 100644
---- a/src/lib/krad/attr.c
-+++ b/src/lib/krad/attr.c
-@@ -30,6 +30,7 @@
- #include <k5-int.h>
- #include "internal.h"
- 
-+#include <openssl/crypto.h>
- #include <string.h>
- 
- /* RFC 2865 */
-@@ -38,7 +39,8 @@
- typedef krb5_error_code
- (*attribute_transform_fn)(krb5_context ctx, const char *secret,
-                           const unsigned char *auth, const krb5_data *in,
--                          unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen);
-+                          unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
-+                          krb5_boolean *is_fips);
- 
- typedef struct {
-     const char *name;
-@@ -51,12 +53,14 @@ typedef struct {
- static krb5_error_code
- user_password_encode(krb5_context ctx, const char *secret,
-                      const unsigned char *auth, const krb5_data *in,
--                     unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen);
-+                     unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
-+                     krb5_boolean *is_fips);
- 
- static krb5_error_code
- user_password_decode(krb5_context ctx, const char *secret,
-                      const unsigned char *auth, const krb5_data *in,
--                     unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen);
-+                     unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
-+                     krb5_boolean *ignored);
- 
- static const attribute_record attributes[UCHAR_MAX] = {
-     {"User-Name", 1, MAX_ATTRSIZE, NULL, NULL},
-@@ -128,7 +132,8 @@ static const attribute_record attributes[UCHAR_MAX] = {
- static krb5_error_code
- user_password_encode(krb5_context ctx, const char *secret,
-                      const unsigned char *auth, const krb5_data *in,
--                     unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen)
-+                     unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
-+                     krb5_boolean *is_fips)
- {
-     const unsigned char *indx;
-     krb5_error_code retval;
-@@ -154,8 +159,14 @@ user_password_encode(krb5_context ctx, const char *secret,
-     for (blck = 0, indx = auth; blck * BLOCKSIZE < len; blck++) {
-         memcpy(tmp.data + seclen, indx, BLOCKSIZE);
- 
--        retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0, &tmp,
--                                      &sum);
-+        if (FIPS_mode()) {
-+            /* Skip encryption here.  Taint so that we won't pass it out of
-+             * the machine by accident. */
-+            *is_fips = TRUE;
-+            sum.contents = calloc(1, BLOCKSIZE);
-+        } else
-+            retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0, &tmp,
-+                                          &sum);
-         if (retval != 0) {
-             zap(tmp.data, tmp.length);
-             zap(outbuf, len);
-@@ -180,7 +191,8 @@ user_password_encode(krb5_context ctx, const char *secret,
- static krb5_error_code
- user_password_decode(krb5_context ctx, const char *secret,
-                      const unsigned char *auth, const krb5_data *in,
--                     unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen)
-+                     unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
-+                     krb5_boolean *is_fips)
- {
-     const unsigned char *indx;
-     krb5_error_code retval;
-@@ -204,8 +216,14 @@ user_password_decode(krb5_context ctx, const char *secret,
-     for (blck = 0, indx = auth; blck * BLOCKSIZE < in->length; blck++) {
-         memcpy(tmp.data + seclen, indx, BLOCKSIZE);
- 
--        retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0,
--                                      &tmp, &sum);
-+        if (FIPS_mode()) {
-+            /* Skip encryption here.  Taint so that we won't pass it out of
-+             * the machine by accident. */
-+            *is_fips = TRUE;
-+            sum.contents = calloc(1, BLOCKSIZE);
-+        } else
-+            retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0,
-+                                          &tmp, &sum);
-         if (retval != 0) {
-             zap(tmp.data, tmp.length);
-             zap(outbuf, in->length);
-@@ -248,7 +266,7 @@ krb5_error_code
- kr_attr_encode(krb5_context ctx, const char *secret,
-                const unsigned char *auth, krad_attr type,
-                const krb5_data *in, unsigned char outbuf[MAX_ATTRSIZE],
--               size_t *outlen)
-+               size_t *outlen, krb5_boolean *is_fips)
- {
-     krb5_error_code retval;
- 
-@@ -265,7 +283,8 @@ kr_attr_encode(krb5_context ctx, const char *secret,
-         return 0;
-     }
- 
--    return attributes[type - 1].encode(ctx, secret, auth, in, outbuf, outlen);
-+    return attributes[type - 1].encode(ctx, secret, auth, in, outbuf, outlen,
-+                                       is_fips);
- }
- 
- krb5_error_code
-@@ -274,6 +293,7 @@ kr_attr_decode(krb5_context ctx, const char *secret, const unsigned char *auth,
-                unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen)
- {
-     krb5_error_code retval;
-+    krb5_boolean ignored;
- 
-     retval = kr_attr_valid(type, in);
-     if (retval != 0)
-@@ -288,7 +308,8 @@ kr_attr_decode(krb5_context ctx, const char *secret, const unsigned char *auth,
-         return 0;
-     }
- 
--    return attributes[type - 1].decode(ctx, secret, auth, in, outbuf, outlen);
-+    return attributes[type - 1].decode(ctx, secret, auth, in, outbuf, outlen,
-+                                       &ignored);
- }
- 
- krad_attr
-diff --git a/src/lib/krad/attrset.c b/src/lib/krad/attrset.c
-index 03c613716..d89982a13 100644
---- a/src/lib/krad/attrset.c
-+++ b/src/lib/krad/attrset.c
-@@ -167,7 +167,8 @@ krad_attrset_copy(const krad_attrset *set, krad_attrset **copy)
- krb5_error_code
- kr_attrset_encode(const krad_attrset *set, const char *secret,
-                   const unsigned char *auth,
--                  unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen)
-+                  unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen,
-+                  krb5_boolean *is_fips)
- {
-     unsigned char buffer[MAX_ATTRSIZE];
-     krb5_error_code retval;
-@@ -181,7 +182,7 @@ kr_attrset_encode(const krad_attrset *set, const char *secret,
- 
-     K5_TAILQ_FOREACH(a, &set->list, list) {
-         retval = kr_attr_encode(set->ctx, secret, auth, a->type, &a->attr,
--                                buffer, &attrlen);
-+                                buffer, &attrlen, is_fips);
-         if (retval != 0)
-             return retval;
- 
-diff --git a/src/lib/krad/internal.h b/src/lib/krad/internal.h
-index 996a89372..a53ce31ce 100644
---- a/src/lib/krad/internal.h
-+++ b/src/lib/krad/internal.h
-@@ -49,6 +49,13 @@
- 
- typedef struct krad_remote_st krad_remote;
- 
-+struct krad_packet_st {
-+    char buffer[KRAD_PACKET_SIZE_MAX];
-+    krad_attrset *attrset;
-+    krb5_data pkt;
-+    krb5_boolean is_fips;
-+};
-+
- /* Validate constraints of an attribute. */
- krb5_error_code
- kr_attr_valid(krad_attr type, const krb5_data *data);
-@@ -57,7 +64,8 @@ kr_attr_valid(krad_attr type, const krb5_data *data);
- krb5_error_code
- kr_attr_encode(krb5_context ctx, const char *secret, const unsigned char *auth,
-                krad_attr type, const krb5_data *in,
--               unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen);
-+               unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
-+               krb5_boolean *is_fips);
- 
- /* Decode an attribute. */
- krb5_error_code
-@@ -69,7 +77,8 @@ kr_attr_decode(krb5_context ctx, const char *secret, const unsigned char *auth,
- krb5_error_code
- kr_attrset_encode(const krad_attrset *set, const char *secret,
-                   const unsigned char *auth,
--                  unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen);
-+                  unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen,
-+                  krb5_boolean *is_fips);
- 
- /* Decode attributes from a buffer. */
- krb5_error_code
-diff --git a/src/lib/krad/packet.c b/src/lib/krad/packet.c
-index c597174b6..794ac84c4 100644
---- a/src/lib/krad/packet.c
-+++ b/src/lib/krad/packet.c
-@@ -32,6 +32,7 @@
- #include <string.h>
- 
- #include <arpa/inet.h>
-+#include <openssl/crypto.h>
- 
- typedef unsigned char uchar;
- 
-@@ -53,12 +54,6 @@ typedef unsigned char uchar;
- #define pkt_auth(p) ((uchar *)offset(&(p)->pkt, OFFSET_AUTH))
- #define pkt_attr(p) ((unsigned char *)offset(&(p)->pkt, OFFSET_ATTR))
- 
--struct krad_packet_st {
--    char buffer[KRAD_PACKET_SIZE_MAX];
--    krad_attrset *attrset;
--    krb5_data pkt;
--};
--
- typedef struct {
-     uchar x[(UCHAR_MAX + 1) / 8];
- } idmap;
-@@ -187,8 +182,13 @@ auth_generate_response(krb5_context ctx, const char *secret,
-     memcpy(data.data + response->pkt.length, secret, strlen(secret));
- 
-     /* Hash it. */
--    retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0, &data,
--                                  &hash);
-+    if (FIPS_mode()) {
-+        /* This checksum does very little security-wise anyway, so don't
-+         * taint. */
-+        hash.contents = calloc(1, AUTH_FIELD_SIZE);
-+    } else
-+        retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0, &data,
-+                                      &hash);
-     free(data.data);
-     if (retval != 0)
-         return retval;
-@@ -276,7 +276,7 @@ krad_packet_new_request(krb5_context ctx, const char *secret, krad_code code,
- 
-     /* Encode the attributes. */
-     retval = kr_attrset_encode(set, secret, pkt_auth(pkt), pkt_attr(pkt),
--                               &attrset_len);
-+                               &attrset_len, &pkt->is_fips);
-     if (retval != 0)
-         goto error;
- 
-@@ -314,7 +314,7 @@ krad_packet_new_response(krb5_context ctx, const char *secret, krad_code code,
- 
-     /* Encode the attributes. */
-     retval = kr_attrset_encode(set, secret, pkt_auth(request), pkt_attr(pkt),
--                               &attrset_len);
-+                               &attrset_len, &pkt->is_fips);
-     if (retval != 0)
-         goto error;
- 
-@@ -451,6 +451,8 @@ krad_packet_decode_response(krb5_context ctx, const char *secret,
- const krb5_data *
- krad_packet_encode(const krad_packet *pkt)
- {
-+    if (pkt->is_fips)
-+        return NULL;
-     return &pkt->pkt;
- }
- 
-diff --git a/src/lib/krad/remote.c b/src/lib/krad/remote.c
-index 437f7e91a..0f90443ce 100644
---- a/src/lib/krad/remote.c
-+++ b/src/lib/krad/remote.c
-@@ -263,7 +263,7 @@ on_io_write(krad_remote *rr)
-     request *r;
- 
-     K5_TAILQ_FOREACH(r, &rr->list, list) {
--        tmp = krad_packet_encode(r->request);
-+        tmp = &r->request->pkt;
- 
-         /* If the packet has already been sent, do nothing. */
-         if (r->sent == tmp->length)
-@@ -359,7 +359,7 @@ on_io_read(krad_remote *rr)
-     if (req != NULL) {
-         K5_TAILQ_FOREACH(r, &rr->list, list) {
-             if (r->request == req &&
--                r->sent == krad_packet_encode(req)->length) {
-+                r->sent == req->pkt.length) {
-                 request_finish(r, 0, rsp);
-                 break;
-             }
-@@ -455,6 +455,12 @@ kr_remote_send(krad_remote *rr, krad_code code, krad_attrset *attrs,
-                                      (krad_packet_iter_cb)iterator, &r, &tmp);
-     if (retval != 0)
-         goto error;
-+    else if (tmp->is_fips && rr->info->ai_family != AF_LOCAL &&
-+        rr->info->ai_family != AF_UNIX) {
-+        /* This would expose cleartext passwords, so abort. */
-+        retval = ESOCKTNOSUPPORT;
-+        goto error;
-+    }
- 
-     K5_TAILQ_FOREACH(r, &rr->list, list) {
-         if (r->request == tmp) {
-diff --git a/src/lib/krad/t_attr.c b/src/lib/krad/t_attr.c
-index eb2a780c8..4d285ad9d 100644
---- a/src/lib/krad/t_attr.c
-+++ b/src/lib/krad/t_attr.c
-@@ -50,6 +50,7 @@ main()
-     const char *tmp;
-     krb5_data in;
-     size_t len;
-+    krb5_boolean is_fips = FALSE;
- 
-     noerror(krb5_init_context(&ctx));
- 
-@@ -73,7 +74,7 @@ main()
-     in = string2data((char *)decoded);
-     retval = kr_attr_encode(ctx, secret, auth,
-                             krad_attr_name2num("User-Password"),
--                            &in, outbuf, &len);
-+                            &in, outbuf, &len, &is_fips);
-     insist(retval == 0);
-     insist(len == sizeof(encoded));
-     insist(memcmp(outbuf, encoded, len) == 0);
-diff --git a/src/lib/krad/t_attrset.c b/src/lib/krad/t_attrset.c
-index 7928335ca..0f9576253 100644
---- a/src/lib/krad/t_attrset.c
-+++ b/src/lib/krad/t_attrset.c
-@@ -49,6 +49,7 @@ main()
-     krb5_context ctx;
-     size_t len = 0, encode_len;
-     krb5_data tmp;
-+    krb5_boolean is_fips = FALSE;
- 
-     noerror(krb5_init_context(&ctx));
-     noerror(krad_attrset_new(ctx, &set));
-@@ -62,7 +63,8 @@ main()
-     noerror(krad_attrset_add(set, krad_attr_name2num("User-Password"), &tmp));
- 
-     /* Encode attrset. */
--    noerror(kr_attrset_encode(set, "foo", auth, buffer, &encode_len));
-+    noerror(kr_attrset_encode(set, "foo", auth, buffer, &encode_len,
-+                              &is_fips));
-     krad_attrset_free(set);
- 
-     /* Manually encode User-Name. */
-diff --git a/src/plugins/preauth/spake/spake_client.c b/src/plugins/preauth/spake/spake_client.c
-index 00734a13b..a3ce22b70 100644
---- a/src/plugins/preauth/spake/spake_client.c
-+++ b/src/plugins/preauth/spake/spake_client.c
-@@ -38,6 +38,8 @@
- #include "groups.h"
- #include <krb5/clpreauth_plugin.h>
- 
-+#include <openssl/crypto.h>
-+
- typedef struct reqstate_st {
-     krb5_pa_spake *msg;         /* set in prep_questions, used in process */
-     krb5_keyblock *initial_key;
-@@ -375,6 +377,10 @@ clpreauth_spake_initvt(krb5_context context, int maj_ver, int min_ver,
- 
-     if (maj_ver != 1)
-         return KRB5_PLUGIN_VER_NOTSUPP;
-+
-+    if (FIPS_mode())
-+        return KRB5_CRYPTO_INTERNAL;
-+
-     vt = (krb5_clpreauth_vtable)vtable;
-     vt->name = "spake";
-     vt->pa_type_list = pa_types;
-diff --git a/src/plugins/preauth/spake/spake_kdc.c b/src/plugins/preauth/spake/spake_kdc.c
-index 59e88409e..1b3e569e9 100644
---- a/src/plugins/preauth/spake/spake_kdc.c
-+++ b/src/plugins/preauth/spake/spake_kdc.c
-@@ -41,6 +41,8 @@
- 
- #include <krb5/kdcpreauth_plugin.h>
- 
-+#include <openssl/crypto.h>
-+
- /*
-  * The SPAKE kdcpreauth module uses a secure cookie containing the following
-  * concatenated fields (all integer fields are big-endian):
-@@ -578,6 +580,10 @@ kdcpreauth_spake_initvt(krb5_context context, int maj_ver, int min_ver,
- 
-     if (maj_ver != 1)
-         return KRB5_PLUGIN_VER_NOTSUPP;
-+
-+    if (FIPS_mode())
-+        return KRB5_CRYPTO_INTERNAL;
-+
-     vt = (krb5_kdcpreauth_vtable)vtable;
-     vt->name = "spake";
-     vt->pa_type_list = pa_types;
diff --git a/SOURCES/krb5-1.18.2.tar.gz.asc b/SOURCES/krb5-1.18.2.tar.gz.asc
new file mode 100644
index 0000000..aea279d
--- /dev/null
+++ b/SOURCES/krb5-1.18.2.tar.gz.asc
@@ -0,0 +1,16 @@
+-----BEGIN PGP SIGNATURE-----
+
+iQIzBAABCgAdFiEExEk8tzn0qJ+YUsvCDLoIV1+Dct8FAl7H9FAACgkQDLoIV1+D
+ct+rjxAAqLlDjeExNw1sJyyjaAKzo7vGzK0tFVouMglmmGcyluVwsqu9B2uHw3UC
+TIm4bn1rgGtUB5oKWmbeD+hiuoAghLDa6gSrmDDkJfFR+o/K/vE7BGZewrrp7QJ5
+jJnEhjuY9O+ZFM/ZNEwHa4/RNG1ga5uJUrfdlNkTUMFje5d1TXvx/ozuSk4bAUTF
+nqHuJsyRAuhKcqTOZ9nr5a54me97CbWj7Be6sA7LQVaFDPyWcJCQsBHjFyextTOF
+3ewsF7330B3oO8yE9/f+nxFq/x9ot6CctMXZqLzhbvdzcO2GwmwbvXy73ibhvjVU
+w9n/zQ1xDjRO0z1wfM54Vq1upQW78+YXA33fEX6od0WBzdiR/o7hfU3arg/WraUy
+pVcD9V7jvYhGPpqYwEdRhs4qROhAh/yvebZ+MVe/1Pd8kA4tTXtR+VmVkp21X3cq
++19eTz7actQemfdsUvfcL8guub0Mea/l+1l3cEHl20FOEeZ8RjpPMisYS9IrJ52O
+3lro26vYFSWS4+U9j4gwdjuQwLS3xHuPZFwS7aykKGsIQ1r8l5Yb0xorDXXKKLjm
+z4DNPaZbxxfcGhDWKTlDudrXEIAGTOD4FC1SJBV3hbqUsv4EH+EJnf92rmVMJ5z/
+AmeUKsL02Abl3BjhwaLWmhIwoXIUhcI/5xNsoI6ePCAT2HLyJlE=
+=fGT7
+-----END PGP SIGNATURE-----
diff --git a/SOURCES/krb5-1.3.1-dns.patch b/SOURCES/krb5-1.3.1-dns.patch
deleted file mode 100644
index 819bf9f..0000000
--- a/SOURCES/krb5-1.3.1-dns.patch
+++ /dev/null
@@ -1,22 +0,0 @@
-From 19f0dc268c127fb51c4bb8c106104eee67119cca Mon Sep 17 00:00:00 2001
-From: Robbie Harwood <rharwood@redhat.com>
-Date: Tue, 23 Aug 2016 16:46:21 -0400
-Subject: [PATCH] krb5-1.3.1-dns.patch
-
-We want to be able to use --with-netlib and --enable-dns at the same time.
----
- src/aclocal.m4 | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/src/aclocal.m4 b/src/aclocal.m4
-index a7afec09e..db18226ed 100644
---- a/src/aclocal.m4
-+++ b/src/aclocal.m4
-@@ -726,6 +726,7 @@ AC_HELP_STRING([--with-netlib=LIBS], use user defined resolver library),
- 	LIBS="$LIBS $withval"
- 	AC_MSG_RESULT("netlib will use \'$withval\'")
-   fi
-+  KRB5_AC_ENABLE_DNS
- ],dnl
- [AC_LIBRARY_NET]
- )])dnl
diff --git a/SOURCES/krb5-1.9-debuginfo.patch b/SOURCES/krb5-1.9-debuginfo.patch
deleted file mode 100644
index 21971ff..0000000
--- a/SOURCES/krb5-1.9-debuginfo.patch
+++ /dev/null
@@ -1,39 +0,0 @@
-From 56954a72afe83cce5168bc139139d7f74c3685d6 Mon Sep 17 00:00:00 2001
-From: Robbie Harwood <rharwood@redhat.com>
-Date: Tue, 23 Aug 2016 16:49:25 -0400
-Subject: [PATCH] krb5-1.9-debuginfo.patch
-
-We want to keep these y.tab.c files around because the debuginfo points to
-them.  It would be more elegant at the end to use symbolic links, but that
-could mess up people working in the tree on other things.
----
- src/kadmin/cli/Makefile.in                 | 5 +++++
- src/plugins/kdb/ldap/ldap_util/Makefile.in | 2 +-
- 2 files changed, 6 insertions(+), 1 deletion(-)
-
-diff --git a/src/kadmin/cli/Makefile.in b/src/kadmin/cli/Makefile.in
-index adfea6e2b..d1327e400 100644
---- a/src/kadmin/cli/Makefile.in
-+++ b/src/kadmin/cli/Makefile.in
-@@ -37,3 +37,8 @@ clean-unix::
- # CC_LINK is not meant for compilation and this use may break in the future.
- datetest: getdate.c
- 	$(CC_LINK) $(ALL_CFLAGS) -DTEST -o datetest getdate.c
-+
-+%.c: %.y
-+	$(RM) y.tab.c $@
-+	$(YACC.y) $< 
-+	$(CP) y.tab.c $@
-diff --git a/src/plugins/kdb/ldap/ldap_util/Makefile.in b/src/plugins/kdb/ldap/ldap_util/Makefile.in
-index 8669c2436..a22f23c02 100644
---- a/src/plugins/kdb/ldap/ldap_util/Makefile.in
-+++ b/src/plugins/kdb/ldap/ldap_util/Makefile.in
-@@ -20,7 +20,7 @@ $(PROG): $(OBJS) $(KADMSRV_DEPLIBS) $(KRB5_BASE_DEPLIB) $(GETDATE)
- getdate.c: $(GETDATE)
- 	$(RM) getdate.c y.tab.c
- 	$(YACC) $(GETDATE)
--	$(MV) y.tab.c getdate.c
-+	$(CP) y.tab.c getdate.c
- 
- install:
- 	$(INSTALL_PROGRAM) $(PROG) ${DESTDIR}$(ADMIN_BINDIR)/$(PROG)
diff --git a/SOURCES/rhel-Use-backported-version-of-OpenSSL-3-KDF-interfa.patch b/SOURCES/rhel-Use-backported-version-of-OpenSSL-3-KDF-interfa.patch
new file mode 100644
index 0000000..cbbfd2d
--- /dev/null
+++ b/SOURCES/rhel-Use-backported-version-of-OpenSSL-3-KDF-interfa.patch
@@ -0,0 +1,751 @@
+From 396ce77f48f758efa090aadd00cd7208e7e97491 Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Fri, 15 Nov 2019 20:05:16 +0000
+Subject: [PATCH] [rhel] Use backported version of OpenSSL-3 KDF interface
+
+(cherry picked from commit 0e20daf7ccfe50518c89735c3dae2fde08d92325)
+---
+ src/configure.ac                              |   4 +
+ src/lib/crypto/krb/derive.c                   | 356 +++++++++++++-----
+ .../preauth/pkinit/pkinit_crypto_openssl.c    | 257 ++++++++-----
+ 3 files changed, 428 insertions(+), 189 deletions(-)
+
+diff --git a/src/configure.ac b/src/configure.ac
+index d4e4da525..29be532cb 100644
+--- a/src/configure.ac
++++ b/src/configure.ac
+@@ -282,6 +282,10 @@ AC_SUBST(CRYPTO_IMPL)
+ AC_SUBST(CRYPTO_IMPL_CFLAGS)
+ AC_SUBST(CRYPTO_IMPL_LIBS)
+ 
++AC_CHECK_FUNCS(EVP_KDF_CTX_new_id EVP_KDF_ctrl EVP_KDF_derive,
++               AC_DEFINE(OSSL_KDFS, 1, [Define if using OpenSSL KDFs]),
++               AC_MSG_ERROR([backported OpenSSL KDFs not found]))
++
+ AC_ARG_WITH([prng-alg],
+ AC_HELP_STRING([--with-prng-alg=ALG], [use specified PRNG algorithm. @<:@fortuna@:>@]),
+ [PRNG_ALG=$withval
+diff --git a/src/lib/crypto/krb/derive.c b/src/lib/crypto/krb/derive.c
+index 6707a7308..915a173dd 100644
+--- a/src/lib/crypto/krb/derive.c
++++ b/src/lib/crypto/krb/derive.c
+@@ -27,6 +27,13 @@
+ 
+ #include "crypto_int.h"
+ 
++#ifdef OSSL_KDFS
++#include <openssl/evp.h>
++#include <openssl/kdf.h>
++#else
++#error "Refusing to build without OpenSSL KDFs!"
++#endif
++
+ static krb5_key
+ find_cached_dkey(struct derived_key *list, const krb5_data *constant)
+ {
+@@ -77,55 +84,193 @@ cleanup:
+     return ENOMEM;
+ }
+ 
++#ifdef OSSL_KDFS
+ static krb5_error_code
+-derive_random_rfc3961(const struct krb5_enc_provider *enc,
+-                      krb5_key inkey, krb5_data *outrnd,
+-                      const krb5_data *in_constant)
++openssl_kbdkf_counter_hmac(const struct krb5_hash_provider *hash,
++                           krb5_key inkey, krb5_data *outrnd,
++                           const krb5_data *label, const krb5_data *context)
+ {
+-    size_t blocksize, keybytes, n;
++    krb5_error_code ret = KRB5_CRYPTO_INTERNAL;
++    EVP_KDF_CTX *ctx = NULL;
++    const EVP_MD *digest;
++
++    if (!strcmp(hash->hash_name, "SHA1"))
++        digest = EVP_sha1();
++    else if (!strcmp(hash->hash_name, "SHA-256"))
++        digest = EVP_sha256();
++    else if (!strcmp(hash->hash_name, "SHA-384"))
++        digest = EVP_sha384();
++    else
++        goto done;
++
++    ctx = EVP_KDF_CTX_new_id(EVP_KDF_KB);
++    if (!ctx)
++        goto done;
++
++    if (EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_MD, digest) != 1 ||
++        EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KB_MAC_TYPE,
++                     EVP_KDF_KB_MAC_TYPE_HMAC) != 1 ||
++        EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KEY, inkey->keyblock.contents,
++                     inkey->keyblock.length) != 1 ||
++        (context->length > 0 &&
++         EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KB_INFO, context->data,
++                      context->length) != 1) ||
++        (label->length > 0 &&
++         EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SALT, label->data,
++                      label->length) != 1) ||
++        EVP_KDF_derive(ctx, (unsigned char *)outrnd->data,
++                       outrnd->length) != 1)
++        goto done;
++
++    ret = 0;
++done:
++    if (ret)
++        zap(outrnd->data, outrnd->length);
++    EVP_KDF_CTX_free(ctx);
++    return ret;
++}
++
++static krb5_error_code
++openssl_kbkdf_feedback_cmac(const struct krb5_enc_provider *enc,
++                            krb5_key inkey, krb5_data *outrnd,
++                            const krb5_data *in_constant)
++{
++    krb5_error_code ret = KRB5_CRYPTO_INTERNAL;
++    EVP_KDF_CTX *ctx = NULL;
++    const EVP_CIPHER *cipher;
++    static unsigned char zeroes[16];
++
++    memset(zeroes, 0, sizeof(zeroes));
++
++    if (enc->keylength == 16)
++        cipher = EVP_camellia_128_cbc();
++    else if (enc->keylength == 32)
++        cipher = EVP_camellia_256_cbc();
++    else
++        goto done;
++
++    ctx = EVP_KDF_CTX_new_id(EVP_KDF_KB);
++    if (!ctx)
++        goto done;
++
++    if (EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KB_MODE,
++                     EVP_KDF_KB_MODE_FEEDBACK) != 1 ||
++        EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KB_MAC_TYPE,
++                     EVP_KDF_KB_MAC_TYPE_CMAC) != 1 ||
++        EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_CIPHER, cipher) != 1 ||
++        EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KEY, inkey->keyblock.contents,
++                     inkey->keyblock.length) != 1 ||
++        EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SALT, in_constant->data,
++                     in_constant->length) != 1 ||
++        EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KB_SEED, zeroes,
++                     sizeof(zeroes)) != 1 ||
++        EVP_KDF_derive(ctx, (unsigned char *)outrnd->data,
++                       outrnd->length) != 1)
++        goto done;
++
++    ret = 0;
++done:
++    if (ret)
++        zap(outrnd->data, outrnd->length);
++    EVP_KDF_CTX_free(ctx);
++    return ret;
++}
++
++static krb5_error_code
++openssl_krb5kdf(const struct krb5_enc_provider *enc, krb5_key inkey,
++                krb5_data *outrnd, const krb5_data *in_constant)
++{
++    krb5_error_code ret = KRB5_CRYPTO_INTERNAL;
++    EVP_KDF_CTX *ctx = NULL;
++    const EVP_CIPHER *cipher;
++
++    if (inkey->keyblock.length != enc->keylength ||
++        outrnd->length != enc->keybytes) {
++        return KRB5_CRYPTO_INTERNAL;
++    }
++
++    if (enc->encrypt == krb5int_aes_encrypt && enc->keylength == 16)
++        cipher = EVP_aes_128_cbc();
++    else if (enc->encrypt == krb5int_aes_encrypt && enc->keylength == 32)
++        cipher = EVP_aes_256_cbc();
++    else if (enc->keylength == 24)
++        cipher = EVP_des_ede3_cbc();
++    else
++        goto done;
++
++    ctx = EVP_KDF_CTX_new_id(EVP_KDF_KRB5KDF);
++    if (ctx == NULL)
++        goto done;
++
++    if (EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_CIPHER, cipher) != 1 ||
++        EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KEY, inkey->keyblock.contents,
++                     inkey->keyblock.length) != 1 ||
++        EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KRB5KDF_CONSTANT,
++                     in_constant->data, in_constant->length) != 1 ||
++        EVP_KDF_derive(ctx, (unsigned char *)outrnd->data,
++                       outrnd->length) != 1)
++        goto done;
++
++    ret = 0;
++done:
++    if (ret)
++        zap(outrnd->data, outrnd->length);
++    EVP_KDF_CTX_free(ctx);
++    return ret;
++}
++
++#else /* OSSL_KDFS */
++
++/*
++ * NIST SP800-108 KDF in counter mode (section 5.1).
++ * Parameters:
++ *   - HMAC (with hash as the hash provider) is the PRF.
++ *   - A block counter of four bytes is used.
++ *   - Four bytes are used to encode the output length in the PRF input.
++ *
++ * There are no uses requiring more than a single PRF invocation.
++ */
++static krb5_error_code
++builtin_sp800_108_counter_hmac(const struct krb5_hash_provider *hash,
++                               krb5_key inkey, krb5_data *outrnd,
++                               const krb5_data *label,
++                               const krb5_data *context)
++{
++    krb5_crypto_iov iov[5];
+     krb5_error_code ret;
+-    krb5_data block = empty_data();
++    krb5_data prf;
++    unsigned char ibuf[4], lbuf[4];
+ 
+-    blocksize = enc->block_size;
+-    keybytes = enc->keybytes;
+-
+-    if (blocksize == 1)
+-        return KRB5_BAD_ENCTYPE;
+-    if (inkey->keyblock.length != enc->keylength || outrnd->length != keybytes)
++    if (hash == NULL || outrnd->length > hash->hashsize)
+         return KRB5_CRYPTO_INTERNAL;
+ 
+     /* Allocate encryption data buffer. */
+-    ret = alloc_data(&block, blocksize);
++    ret = alloc_data(&prf, hash->hashsize);
+     if (ret)
+         return ret;
+ 
+-    /* Initialize the input block. */
+-    if (in_constant->length == blocksize) {
+-        memcpy(block.data, in_constant->data, blocksize);
+-    } else {
+-        krb5int_nfold(in_constant->length * 8,
+-                      (unsigned char *) in_constant->data,
+-                      blocksize * 8, (unsigned char *) block.data);
+-    }
++    /* [i]2: four-byte big-endian binary string giving the block counter (1) */
++    iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
++    iov[0].data = make_data(ibuf, sizeof(ibuf));
++    store_32_be(1, ibuf);
++    /* Label */
++    iov[1].flags = KRB5_CRYPTO_TYPE_DATA;
++    iov[1].data = *label;
++    /* 0x00: separator byte */
++    iov[2].flags = KRB5_CRYPTO_TYPE_DATA;
++    iov[2].data = make_data("", 1);
++    /* Context */
++    iov[3].flags = KRB5_CRYPTO_TYPE_DATA;
++    iov[3].data = *context;
++    /* [L]2: four-byte big-endian binary string giving the output length */
++    iov[4].flags = KRB5_CRYPTO_TYPE_DATA;
++    iov[4].data = make_data(lbuf, sizeof(lbuf));
++    store_32_be(outrnd->length * 8, lbuf);
+ 
+-    /* Loop encrypting the blocks until enough key bytes are generated. */
+-    n = 0;
+-    while (n < keybytes) {
+-        ret = encrypt_block(enc, inkey, &block);
+-        if (ret)
+-            goto cleanup;
+-
+-        if ((keybytes - n) <= blocksize) {
+-            memcpy(outrnd->data + n, block.data, (keybytes - n));
+-            break;
+-        }
+-
+-        memcpy(outrnd->data + n, block.data, blocksize);
+-        n += blocksize;
+-    }
+-
+-cleanup:
+-    zapfree(block.data, blocksize);
++    ret = krb5int_hmac(hash, inkey, iov, 5, &prf);
++    if (!ret)
++        memcpy(outrnd->data, prf.data, outrnd->length);
++    zapfree(prf.data, prf.length);
+     return ret;
+ }
+ 
+@@ -139,9 +284,9 @@ cleanup:
+  *   - Four bytes are used to encode the output length in the PRF input.
+  */
+ static krb5_error_code
+-derive_random_sp800_108_feedback_cmac(const struct krb5_enc_provider *enc,
+-                                      krb5_key inkey, krb5_data *outrnd,
+-                                      const krb5_data *in_constant)
++builtin_sp800_108_feedback_cmac(const struct krb5_enc_provider *enc,
++                                krb5_key inkey, krb5_data *outrnd,
++                                const krb5_data *in_constant)
+ {
+     size_t blocksize, keybytes, n;
+     krb5_crypto_iov iov[6];
+@@ -204,56 +349,94 @@ cleanup:
+     return ret;
+ }
+ 
+-/*
+- * NIST SP800-108 KDF in counter mode (section 5.1).
+- * Parameters:
+- *   - HMAC (with hash as the hash provider) is the PRF.
+- *   - A block counter of four bytes is used.
+- *   - Four bytes are used to encode the output length in the PRF input.
+- *
+- * There are no uses requiring more than a single PRF invocation.
+- */
++static krb5_error_code
++builtin_derive_random_rfc3961(const struct krb5_enc_provider *enc,
++                              krb5_key inkey, krb5_data *outrnd,
++                              const krb5_data *in_constant)
++{
++    size_t blocksize, keybytes, n;
++    krb5_error_code ret;
++    krb5_data block = empty_data();
++
++    blocksize = enc->block_size;
++    keybytes = enc->keybytes;
++
++    if (blocksize == 1)
++        return KRB5_BAD_ENCTYPE;
++    if (inkey->keyblock.length != enc->keylength || outrnd->length != keybytes)
++        return KRB5_CRYPTO_INTERNAL;
++
++    /* Allocate encryption data buffer. */
++    ret = alloc_data(&block, blocksize);
++    if (ret)
++        return ret;
++
++    /* Initialize the input block. */
++    if (in_constant->length == blocksize) {
++        memcpy(block.data, in_constant->data, blocksize);
++    } else {
++        krb5int_nfold(in_constant->length * 8,
++                      (unsigned char *) in_constant->data,
++                      blocksize * 8, (unsigned char *) block.data);
++    }
++
++    /* Loop encrypting the blocks until enough key bytes are generated. */
++    n = 0;
++    while (n < keybytes) {
++        ret = encrypt_block(enc, inkey, &block);
++        if (ret)
++            goto cleanup;
++
++        if ((keybytes - n) <= blocksize) {
++            memcpy(outrnd->data + n, block.data, (keybytes - n));
++            break;
++        }
++
++        memcpy(outrnd->data + n, block.data, blocksize);
++        n += blocksize;
++    }
++
++cleanup:
++    zapfree(block.data, blocksize);
++    return ret;
++}
++#endif /* OSSL_KDFS */
++
+ krb5_error_code
+ k5_sp800_108_counter_hmac(const struct krb5_hash_provider *hash,
+                           krb5_key inkey, krb5_data *outrnd,
+                           const krb5_data *label, const krb5_data *context)
+ {
+-    krb5_crypto_iov iov[5];
+-    krb5_error_code ret;
+-    krb5_data prf;
+-    unsigned char ibuf[4], lbuf[4];
++#ifdef OSSL_KDFS
++    return openssl_kbdkf_counter_hmac(hash, inkey, outrnd, label, context);
++#else
++    return builtin_sp800_108_counter_hmac(hash, inkey, outrnd, label,
++                                          context);
++#endif
++}
+ 
+-    if (hash == NULL || outrnd->length > hash->hashsize)
+-        return KRB5_CRYPTO_INTERNAL;
++static krb5_error_code
++k5_sp800_108_feedback_cmac(const struct krb5_enc_provider *enc,
++                           krb5_key inkey, krb5_data *outrnd,
++                           const krb5_data *in_constant)
++{
++#ifdef OSSL_KDFS
++    return openssl_kbkdf_feedback_cmac(enc, inkey, outrnd, in_constant);
++#else
++    return builtin_sp800_108_feedback_cmac(enc, inkey, outrnd, in_constant);
++#endif
++}
+ 
+-    /* Allocate encryption data buffer. */
+-    ret = alloc_data(&prf, hash->hashsize);
+-    if (ret)
+-        return ret;
+-
+-    /* [i]2: four-byte big-endian binary string giving the block counter (1) */
+-    iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
+-    iov[0].data = make_data(ibuf, sizeof(ibuf));
+-    store_32_be(1, ibuf);
+-    /* Label */
+-    iov[1].flags = KRB5_CRYPTO_TYPE_DATA;
+-    iov[1].data = *label;
+-    /* 0x00: separator byte */
+-    iov[2].flags = KRB5_CRYPTO_TYPE_DATA;
+-    iov[2].data = make_data("", 1);
+-    /* Context */
+-    iov[3].flags = KRB5_CRYPTO_TYPE_DATA;
+-    iov[3].data = *context;
+-    /* [L]2: four-byte big-endian binary string giving the output length */
+-    iov[4].flags = KRB5_CRYPTO_TYPE_DATA;
+-    iov[4].data = make_data(lbuf, sizeof(lbuf));
+-    store_32_be(outrnd->length * 8, lbuf);
+-
+-    ret = krb5int_hmac(hash, inkey, iov, 5, &prf);
+-    if (!ret)
+-        memcpy(outrnd->data, prf.data, outrnd->length);
+-    zapfree(prf.data, prf.length);
+-    return ret;
++static krb5_error_code
++k5_derive_random_rfc3961(const struct krb5_enc_provider *enc,
++                         krb5_key inkey, krb5_data *outrnd,
++                         const krb5_data *in_constant)
++{
++#ifdef OSSL_KDFS
++    return openssl_krb5kdf(enc, inkey, outrnd, in_constant);
++#else
++    return builtin_derive_random_rfc3961(enc, inkey, outrnd, in_constant);
++#endif
+ }
+ 
+ krb5_error_code
+@@ -266,10 +449,9 @@ krb5int_derive_random(const struct krb5_enc_provider *enc,
+ 
+     switch (alg) {
+     case DERIVE_RFC3961:
+-        return derive_random_rfc3961(enc, inkey, outrnd, in_constant);
++        return k5_derive_random_rfc3961(enc, inkey, outrnd, in_constant);
+     case DERIVE_SP800_108_CMAC:
+-        return derive_random_sp800_108_feedback_cmac(enc, inkey, outrnd,
+-                                                     in_constant);
++        return k5_sp800_108_feedback_cmac(enc, inkey, outrnd, in_constant);
+     case DERIVE_SP800_108_HMAC:
+         return k5_sp800_108_counter_hmac(hash, inkey, outrnd, in_constant,
+                                          &empty);
+diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+index 52976895b..dd718c2be 100644
+--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
++++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+@@ -38,6 +38,13 @@
+ #include <dirent.h>
+ #include <arpa/inet.h>
+ 
++#ifdef OSSL_KDFS
++#include <openssl/evp.h>
++#include <openssl/kdf.h>
++#else
++#error "Refusing to build without OpenSSL KDFs!"
++#endif
++
+ static krb5_error_code pkinit_init_pkinit_oids(pkinit_plg_crypto_context );
+ static void pkinit_fini_pkinit_oids(pkinit_plg_crypto_context );
+ 
+@@ -2331,11 +2338,51 @@ pkinit_alg_values(krb5_context context,
+     }
+ } /* pkinit_alg_values() */
+ 
++#ifdef OSSL_KDFS
++static krb5_error_code
++openssl_sskdf(krb5_context context, size_t hash_bytes, krb5_data *key,
++              krb5_data *info, char *out, size_t out_len)
++{
++    krb5_error_code ret = KRB5_CRYPTO_INTERNAL;
++    EVP_KDF_CTX *ctx = NULL;
++    const EVP_MD *digest;
+ 
+-/* pkinit_alg_agility_kdf() --
+- * This function generates a key using the KDF described in
+- * draft_ietf_krb_wg_pkinit_alg_agility-04.txt.  The algorithm is
+- * described as follows:
++    /* RFC 8636 defines a SHA384 variant, but we don't use it. */
++    if (hash_bytes == 20) {
++        digest = EVP_sha1();
++    } else if (hash_bytes == 32) {
++        digest = EVP_sha256();
++    } else if (hash_bytes == 64) {
++        digest = EVP_sha512();
++    } else {
++        krb5_set_error_message(context, ret, "Bad hash type for SSKDF");
++        goto done;
++    }
++
++    ctx = EVP_KDF_CTX_new_id(EVP_KDF_SS);
++    if (!ctx) {
++        oerr(context, ret, _("Failed to instantiate SSKDF"));
++        goto done;
++    }
++
++    if (EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_MD, digest) != 1 ||
++        EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KEY, key->data,
++                     key->length) != 1 ||
++        EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSKDF_INFO, info->data,
++                     info->length) != 1 ||
++        EVP_KDF_derive(ctx, (unsigned char *)out, out_len) != 1)
++        goto done;
++
++    ret = 0;
++done:
++    EVP_KDF_CTX_free(ctx);
++    return ret;
++}
++#else
++/*
++ * Generate a key using the KDF described in RFC 8636, also known as SSKDF
++ * (single-step kdf).  Our caller precomputes `reps`, but otherwise the
++ * algorithm is as follows:
+  *
+  *     1.  reps = keydatalen (K) / hash length (H)
+  *
+@@ -2349,95 +2396,16 @@ pkinit_alg_values(krb5_context context,
+  *
+  *     4.  Set key = Hash1 || Hash2 || ... so that length of key is K bytes.
+  */
+-krb5_error_code
+-pkinit_alg_agility_kdf(krb5_context context,
+-                       krb5_data *secret,
+-                       krb5_data *alg_oid,
+-                       krb5_const_principal party_u_info,
+-                       krb5_const_principal party_v_info,
+-                       krb5_enctype enctype,
+-                       krb5_data *as_req,
+-                       krb5_data *pk_as_rep,
+-                       krb5_keyblock *key_block)
++static krb5_error_code
++builtin_sskdf(krb5_context context, unsigned int reps, size_t hash_len,
++              const EVP_MD *(*EVP_func)(void), krb5_data *secret,
++              krb5_data *other_info, char *out, size_t out_len)
+ {
+     krb5_error_code retval = 0;
+ 
+-    unsigned int reps = 0;
+-    uint32_t counter = 1;       /* Does this type work on Windows? */
++    uint32_t counter = 1;
+     size_t offset = 0;
+-    size_t hash_len = 0;
+-    size_t rand_len = 0;
+-    size_t key_len = 0;
+-    krb5_data random_data;
+-    krb5_sp80056a_other_info other_info_fields;
+-    krb5_pkinit_supp_pub_info supp_pub_info_fields;
+-    krb5_data *other_info = NULL;
+-    krb5_data *supp_pub_info = NULL;
+-    krb5_algorithm_identifier alg_id;
+     EVP_MD_CTX *ctx = NULL;
+-    const EVP_MD *(*EVP_func)(void);
+-
+-    /* initialize random_data here to make clean-up safe */
+-    random_data.length = 0;
+-    random_data.data = NULL;
+-
+-    /* allocate and initialize the key block */
+-    key_block->magic = 0;
+-    key_block->enctype = enctype;
+-    if (0 != (retval = krb5_c_keylengths(context, enctype, &rand_len,
+-                                         &key_len)))
+-        goto cleanup;
+-
+-    random_data.length = rand_len;
+-    key_block->length = key_len;
+-
+-    if (NULL == (key_block->contents = malloc(key_block->length))) {
+-        retval = ENOMEM;
+-        goto cleanup;
+-    }
+-
+-    memset (key_block->contents, 0, key_block->length);
+-
+-    /* If this is anonymous pkinit, use the anonymous principle for party_u_info */
+-    if (party_u_info && krb5_principal_compare_any_realm(context, party_u_info,
+-                                                         krb5_anonymous_principal()))
+-        party_u_info = (krb5_principal)krb5_anonymous_principal();
+-
+-    if (0 != (retval = pkinit_alg_values(context, alg_oid, &hash_len, &EVP_func)))
+-        goto cleanup;
+-
+-    /* 1.  reps = keydatalen (K) / hash length (H) */
+-    reps = key_block->length/hash_len;
+-
+-    /* ... and round up, if necessary */
+-    if (key_block->length > (reps * hash_len))
+-        reps++;
+-
+-    /* Allocate enough space in the random data buffer to hash directly into
+-     * it, even if the last hash will make it bigger than the key length. */
+-    if (NULL == (random_data.data = malloc(reps * hash_len))) {
+-        retval = ENOMEM;
+-        goto cleanup;
+-    }
+-
+-    /* Encode the ASN.1 octet string for "SuppPubInfo" */
+-    supp_pub_info_fields.enctype = enctype;
+-    supp_pub_info_fields.as_req = *as_req;
+-    supp_pub_info_fields.pk_as_rep = *pk_as_rep;
+-    if (0 != ((retval = encode_krb5_pkinit_supp_pub_info(&supp_pub_info_fields,
+-                                                         &supp_pub_info))))
+-        goto cleanup;
+-
+-    /* Now encode the ASN.1 octet string for "OtherInfo" */
+-    memset(&alg_id, 0, sizeof alg_id);
+-    alg_id.algorithm = *alg_oid; /*alias*/
+-
+-    other_info_fields.algorithm_identifier = alg_id;
+-    other_info_fields.party_u_info = (krb5_principal) party_u_info;
+-    other_info_fields.party_v_info = (krb5_principal) party_v_info;
+-    other_info_fields.supp_pub_info = *supp_pub_info;
+-    if (0 != (retval = encode_krb5_sp80056a_other_info(&other_info_fields, &other_info)))
+-        goto cleanup;
+ 
+     /* 2.  Initialize a 32-bit, big-endian bit string counter as 1.
+      * 3.  For i = 1 to reps by 1, do the following:
+@@ -2471,8 +2439,9 @@ pkinit_alg_agility_kdf(krb5_context context,
+             goto cleanup;
+         }
+ 
+-        /* 4.  Set key = Hash1 || Hash2 || ... so that length of key is K bytes. */
+-        if (!EVP_DigestFinal(ctx, (uint8_t *)random_data.data + offset, &s)) {
++        /* 4.  Set key = Hash1 || Hash2 || ... so that length of key is K
++         * bytes. */
++        if (!EVP_DigestFinal(ctx, (unsigned char *)out + offset, &s)) {
+             krb5_set_error_message(context, KRB5_CRYPTO_INTERNAL,
+                                    "Call to OpenSSL EVP_DigestUpdate() returned an error.");
+             retval = KRB5_CRYPTO_INTERNAL;
+@@ -2484,26 +2453,110 @@ pkinit_alg_agility_kdf(krb5_context context,
+         EVP_MD_CTX_free(ctx);
+         ctx = NULL;
+     }
+-
+-    retval = krb5_c_random_to_key(context, enctype, &random_data,
+-                                  key_block);
+-
+ cleanup:
+     EVP_MD_CTX_free(ctx);
++    return retval;
++} /* builtin_sskdf() */
++#endif /* OSSL_KDFS */
+ 
+-    /* If this has been an error, free the allocated key_block, if any */
+-    if (retval) {
+-        krb5_free_keyblock_contents(context, key_block);
++/* id-pkinit-kdf family, as specified by RFC 8636. */
++krb5_error_code
++pkinit_alg_agility_kdf(krb5_context context, krb5_data *secret,
++                       krb5_data *alg_oid, krb5_const_principal party_u_info,
++                       krb5_const_principal party_v_info,
++                       krb5_enctype enctype, krb5_data *as_req,
++                       krb5_data *pk_as_rep, krb5_keyblock *key_block)
++{
++    krb5_error_code retval;
++    size_t hash_len = 0, rand_len = 0, key_len = 0;
++    const EVP_MD *(*EVP_func)(void);
++    krb5_sp80056a_other_info other_info_fields;
++    krb5_pkinit_supp_pub_info supp_pub_info_fields;
++    krb5_data *other_info = NULL, *supp_pub_info = NULL;
++    krb5_data random_data = empty_data();
++    krb5_algorithm_identifier alg_id;
++    unsigned int reps;
++
++    /* Allocate and initialize the key block. */
++    key_block->magic = 0;
++    key_block->enctype = enctype;
++
++    /* Use separate variables to avoid alignment restriction problems. */
++    retval = krb5_c_keylengths(context, enctype, &rand_len, &key_len);
++    if (retval)
++        goto cleanup;
++    random_data.length = rand_len;
++    key_block->length = key_len;
++
++    key_block->contents = k5calloc(key_block->length, 1, &retval);
++    if (key_block->contents == NULL)
++        goto cleanup;
++
++    /* If this is anonymous pkinit, use the anonymous principle for
++     * party_u_info. */
++    if (party_u_info &&
++        krb5_principal_compare_any_realm(context, party_u_info,
++                                         krb5_anonymous_principal())) {
++        party_u_info = (krb5_principal)krb5_anonymous_principal();
+     }
+ 
+-    /* free other allocated resources, either way */
+-    if (random_data.data)
+-        free(random_data.data);
++    retval = pkinit_alg_values(context, alg_oid, &hash_len, &EVP_func);
++    if (retval)
++        goto cleanup;
++
++    /* 1.  reps = keydatalen (K) / hash length (H) */
++    reps = key_block->length / hash_len;
++
++    /* ... and round up, if necessary. */
++    if (key_block->length > (reps * hash_len))
++        reps++;
++
++    /* Allocate enough space in the random data buffer to hash directly into
++     * it, even if the last hash will make it bigger than the key length. */
++    random_data.data = k5alloc(reps * hash_len, &retval);
++    if (random_data.data == NULL)
++        goto cleanup;
++
++    /* Encode the ASN.1 octet string for "SuppPubInfo". */
++    supp_pub_info_fields.enctype = enctype;
++    supp_pub_info_fields.as_req = *as_req;
++    supp_pub_info_fields.pk_as_rep = *pk_as_rep;
++    retval = encode_krb5_pkinit_supp_pub_info(&supp_pub_info_fields,
++                                              &supp_pub_info);
++    if (retval)
++        goto cleanup;
++
++    /* Now encode the ASN.1 octet string for "OtherInfo". */
++    memset(&alg_id, 0, sizeof(alg_id));
++    alg_id.algorithm = *alg_oid;
++    other_info_fields.algorithm_identifier = alg_id;
++    other_info_fields.party_u_info = (krb5_principal)party_u_info;
++    other_info_fields.party_v_info = (krb5_principal)party_v_info;
++    other_info_fields.supp_pub_info = *supp_pub_info;
++    retval = encode_krb5_sp80056a_other_info(&other_info_fields, &other_info);
++    if (retval)
++        goto cleanup;
++
++#ifdef OSSL_KDFS
++    retval = openssl_sskdf(context, hash_len, secret, other_info,
++                           random_data.data, key_block->length);
++#else
++    retval = builtin_sskdf(context, reps, hash_len, EVP_func, secret,
++                           other_info, random_data.data, key_block->length);
++#endif
++    if (retval)
++        goto cleanup;
++
++    retval = krb5_c_random_to_key(context, enctype, &random_data, key_block);
++cleanup:
++    if (retval)
++        krb5_free_keyblock_contents(context, key_block);
++
++    zapfree(random_data.data, random_data.length);
+     krb5_free_data(context, other_info);
+     krb5_free_data(context, supp_pub_info);
+-
+     return retval;
+-} /*pkinit_alg_agility_kdf() */
++}
+ 
+ /* Call DH_compute_key() and ensure that we left-pad short results instead of
+  * leaving junk bytes at the end of the buffer. */
diff --git a/SPECS/krb5.spec b/SPECS/krb5.spec
index b285a4b..f87f2de 100644
--- a/SPECS/krb5.spec
+++ b/SPECS/krb5.spec
@@ -12,13 +12,13 @@
 %global prerelease %{nil}
 
 # Should be in form 5.0, 6.1, etc.
-%global kdbversion 7.0
+%global kdbversion 8.0
 
 Summary: The Kerberos network authentication system
 Name: krb5
-Version: 1.17
+Version: 1.18.2
 # for prerelease, should be e.g., 0.% {prerelease}.1% { ?dist } (without spaces)
-Release: 18%{?dist}
+Release: 2%{?dist}
 
 # lookaside-cached sources; two downloads and a build artifact
 Source0: https://web.mit.edu/kerberos/dist/krb5/1.17/krb5-%{version}%{prerelease}.tar.gz
@@ -46,37 +46,23 @@ Source33: krb5kdc.logrotate
 Source34: kadmind.logrotate
 Source39: krb5-krb5kdc.conf
 
-Patch26: krb5-1.12.1-pam.patch
-Patch27: krb5-1.17-beta1-selinux-label.patch
-Patch28: krb5-1.12-ksu-path.patch
-Patch29: krb5-1.12-ktany.patch
-Patch30: krb5-1.15-beta1-buildconf.patch
-Patch31: krb5-1.3.1-dns.patch
-Patch32: krb5-1.12-api.patch
-Patch33: krb5-1.13-dirsrv-accountlock.patch
-Patch34: krb5-1.9-debuginfo.patch
-Patch35: krb5-1.11-run_user_0.patch
-Patch36: krb5-1.11-kpasswdtest.patch
-Patch88: Add-tests-for-KCM-ccache-type.patch
-Patch89: Properly-size-ifdef-in-k5_cccol_lock.patch
-Patch90: Fix-memory-leak-in-none-replay-cache-type.patch
-Patch91: Address-some-optimized-out-memset-calls.patch
-Patch95: In-rd_req_dec-always-log-non-permitted-enctypes.patch
-Patch96: In-kpropd-debug-log-proper-ticket-enctype-names.patch
-Patch97: Make-etype-names-in-KDC-logs-human-readable.patch
-Patch98: Mark-deprecated-enctypes-when-used.patch
-Patch99: Add-function-and-enctype-flag-for-deprecations.patch
-Patch100: Fix-argument-order-on-strlcpy-in-enctype_name.patch
-Patch101: Fix-KCM-client-time-offset-propagation.patch
-Patch102: Add-soft-pkcs11-source-code.patch
-Patch103: Use-imported-soft-pkcs11-for-tests.patch
-Patch104: Fix-Coverity-defects-in-soft-pkcs11-test-code.patch
-Patch105: Fix-memory-leaks-in-soft-pkcs11-code.patch
-Patch106: Avoid-alignment-warnings-in-openssl-rc4.c.patch
-Patch107: Use-backported-version-of-OpenSSL-3-KDF-interface.patch
-Patch108: krb5-1.17post6-FIPS-with-PRNG-and-RADIUS-and-MD4.patch
-Patch109: krb5-1.17post2-DES-3DES-fixups.patch
-Patch110: Put-KDB-authdata-first.patch
+Patch1: downstream-ksu-pam-integration.patch
+Patch2: downstream-SELinux-integration.patch
+Patch3: downstream-Adjust-build-configuration.patch
+Patch4: downstream-netlib-and-dns.patch
+Patch5: downstream-fix-debuginfo-with-y.tab.c.patch
+Patch6: downstream-Remove-3des-support.patch
+Patch7: rhel-Use-backported-version-of-OpenSSL-3-KDF-interfa.patch
+Patch108: downstream-FIPS-with-PRNG-and-RADIUS-and-MD4.patch
+Patch110: Allow-certauth-modules-to-set-hw-authent-flag.patch
+Patch112: Refresh-manually-acquired-creds-from-client-keytab.patch
+Patch114: Add-finalization-safety-check-to-com_err.patch
+Patch115: Eliminate-redundant-PKINIT-responder-invocation.patch
+Patch116: Correctly-import-service-GSS-host-based-name.patch
+Patch117: Do-expiration-warnings-for-all-init_creds-APIs.patch
+Patch118: Pass-gss_localname-through-SPNEGO.patch
+Patch119: Omit-KDC-indicator-check-for-S4U2Self-requests.patch
+Patch120: Fix-typo-in-in-in-the-ksu-man-page.patch
 
 License: MIT
 URL: http://web.mit.edu/kerberos/www/
@@ -262,9 +248,6 @@ interface is not considered stable.
 %autosetup -S git -n %{name}-%{version}%{prerelease} -a 3
 ln NOTICE LICENSE
 
-# Take the execute bit off of documentation.
-chmod -x doc/ccapi/*.html
-
 # Generate an FDS-compatible LDIF file.
 inldif=src/plugins/kdb/ldap/libkdb_ldap/kerberos.ldif
 cat > '60kerberos.ldif' << EOF
@@ -690,6 +673,33 @@ exit 0
 %{_libdir}/libkadm5srv_mit.so.*
 
 %changelog
+* Wed May 27 2020 Robbie Harwood <rharwood@redhat.com> - 1.18.2-2
+- Drop DES3 from sample kdc.conf
+- Resolves: #1802334
+
+* Fri May 22 2020 Robbie Harwood <rharwood@redhat.com> - 1.18.2-1
+- New upstream release (1.18.2)
+- Resolves: #1802334
+
+* Fri May 08 2020 Robbie Harwood <rharwood@redhat.com> - 1.18.1-3
+- Omit KDC indicator check for S4U2Self requests
+- Resolves: #1802334
+
+* Tue Apr 28 2020 Robbie Harwood <rharwood@redhat.com> - 1.18.1-2
+- Pass gss_localname() through SPNEGO
+- Resolves: #1802334
+
+* Tue Apr 14 2020 Robbie Harwood <rharwood@redhat.com> - 1.18.1-1
+- New upstream version (1.18.1)
+- Resolves: #1802334
+
+* Tue Apr 07 2020 Robbie Harwood <rharwood@redhat.com> - 1.18-1
+- New upstream version (1.18)
+- Resolves: #1802334
+- Resolves: #1820311
+- Resolves: #1791062
+- Resolves: #1784655
+
 * Wed Feb 19 2020 Robbie Harwood <rharwood@redhat.com> - 1.17-18
 - Put KDB authdata first
 - Resolves: #1800575